@origints/xlsx 0.1.1 → 0.2.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.
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","sources":["../src/xlsx-result.ts","../src/util.ts","../src/xlsx-cell.ts","../src/xlsx-range.ts","../src/xlsx-cursor.ts","../src/xlsx-sheet.ts","../src/xlsx-workbook.ts","../src/xlsx-query.ts","../src/parse.ts","../src/convert.ts","../src/index.ts"],"sourcesContent":["/**\n * Result types for XLSX operations.\n *\n * @module xlsx/xlsx-result\n */\n\n/**\n * Excel source location for lineage tracking.\n * Compatible with @origints/core ExcelLocation.\n */\nexport interface ExcelLocation {\n readonly kind: 'excel'\n readonly file: string\n readonly sheet: string\n readonly range: string\n}\n\n/**\n * Path through an XLSX structure, tracking how we arrived at a value.\n */\nexport interface XlsxPath {\n /** Source file name (if known) */\n readonly file?: string\n /** Sheet name */\n readonly sheet?: string\n /** Cell address (e.g., \"A1\") */\n readonly cell?: string\n /** Range address (e.g., \"A1:C10\") */\n readonly range?: string\n}\n\n/**\n * Failure kinds specific to XLSX operations.\n */\nexport type XlsxFailureKind =\n | 'parse' // XLSX parsing error\n | 'type' // Wrong type at location\n | 'missing' // Sheet, row, column, or cell not found\n | 'range' // Invalid range specification\n | 'format' // Invalid format (e.g., date format)\n | 'bounds' // Out of bounds access\n | 'merged' // Merged cell access issue\n | 'formula' // Formula evaluation error\n\n/**\n * A failure during XLSX traversal or extraction.\n */\nexport interface XlsxFailure {\n readonly kind: XlsxFailureKind\n readonly message: string\n readonly path: XlsxPath\n readonly sourceLocation?: ExcelLocation\n}\n\n/**\n * Result of an XLSX extraction - either a successful value or a failure.\n */\nexport type XlsxResult<T> =\n | { readonly ok: true; readonly value: T; readonly path: XlsxPath }\n | { readonly ok: false; readonly failure: XlsxFailure }\n\n/**\n * Creates a success result.\n */\nexport function ok<T>(value: T, path: XlsxPath): XlsxResult<T> {\n return { ok: true, value, path }\n}\n\n/**\n * Creates a failure result.\n */\nexport function fail(\n kind: XlsxFailureKind,\n message: string,\n path: XlsxPath,\n sourceLocation?: ExcelLocation\n): XlsxResult<never> {\n return {\n ok: false,\n failure: { kind, message, path, sourceLocation },\n }\n}\n\n/**\n * Formats a path for display.\n */\nexport function formatXlsxPath(path: XlsxPath): string {\n const parts: string[] = []\n if (path.file) parts.push(path.file)\n if (path.sheet) parts.push(`[${path.sheet}]`)\n if (path.range) parts.push(`!${path.range}`)\n else if (path.cell) parts.push(`!${path.cell}`)\n return parts.join('') || 'workbook'\n}\n\n/**\n * Creates an ExcelLocation from a path.\n */\nexport function toExcelLocation(\n path: XlsxPath\n): ExcelLocation | undefined {\n if (!path.sheet) return undefined\n return {\n kind: 'excel',\n file: path.file ?? '',\n sheet: path.sheet,\n range: path.range ?? path.cell ?? '',\n }\n}\n\n/**\n * Cell value types in XLSX.\n */\nexport type CellValue = string | number | boolean | Date | null\n\n/**\n * Extended cell value including formula and error types.\n */\nexport type ExtendedCellValue =\n | CellValue\n | { readonly formula: string; readonly result?: CellValue }\n | { readonly error: string }\n\n/**\n * Type guard for formula values.\n */\nexport function isFormula(\n value: ExtendedCellValue\n): value is { formula: string; result?: CellValue } {\n return (\n typeof value === 'object' &&\n value !== null &&\n !(value instanceof Date) &&\n 'formula' in value\n )\n}\n\n/**\n * Type guard for error values.\n */\nexport function isError(\n value: ExtendedCellValue\n): value is { error: string } {\n return (\n typeof value === 'object' &&\n value !== null &&\n !(value instanceof Date) &&\n 'error' in value\n )\n}\n","/**\n * Utility functions for XLSX package.\n *\n * @module xlsx/util\n */\n\n/**\n * Convert a ReadableStream<Uint8Array> to a Buffer.\n */\nexport async function streamToBuffer(\n stream: ReadableStream<Uint8Array>\n): Promise<Buffer> {\n const reader = stream.getReader()\n const chunks: Uint8Array[] = []\n\n try {\n while (true) {\n const { done, value } = await reader.read()\n if (done) break\n chunks.push(value)\n }\n return Buffer.concat(chunks)\n } finally {\n reader.releaseLock()\n }\n}\n\n/**\n * Convert column letter(s) to 1-based column number.\n * e.g., \"A\" -> 1, \"B\" -> 2, \"Z\" -> 26, \"AA\" -> 27\n */\nexport function columnLetterToNumber(col: string): number {\n let result = 0\n for (let i = 0; i < col.length; i++) {\n result = result * 26 + (col.charCodeAt(i) - 64)\n }\n return result\n}\n\n/**\n * Convert 1-based column number to column letter(s).\n * e.g., 1 -> \"A\", 2 -> \"B\", 26 -> \"Z\", 27 -> \"AA\"\n */\nexport function columnNumberToLetter(num: number): string {\n let result = ''\n while (num > 0) {\n const remainder = (num - 1) % 26\n result = String.fromCharCode(65 + remainder) + result\n num = Math.floor((num - 1) / 26)\n }\n return result\n}\n\n/**\n * Parse a cell address into row and column numbers.\n * e.g., \"A1\" -> { row: 1, col: 1 }, \"B10\" -> { row: 10, col: 2 }\n */\nexport function parseAddress(address: string): {\n row: number\n col: number\n colLetter: string\n} {\n const match = address.match(/^([A-Z]+)(\\d+)$/i)\n if (!match) {\n throw new Error(`Invalid cell address: ${address}`)\n }\n const colLetter = match[1].toUpperCase()\n return {\n row: parseInt(match[2], 10),\n col: columnLetterToNumber(colLetter),\n colLetter,\n }\n}\n\n/**\n * Format row and column numbers into a cell address.\n * e.g., { row: 1, col: 1 } -> \"A1\"\n */\nexport function formatAddress(row: number, col: number): string {\n return `${columnNumberToLetter(col)}${row}`\n}\n\n/**\n * Parse a range address into start and end coordinates.\n * e.g., \"A1:C10\" -> { start: { row: 1, col: 1 }, end: { row: 10, col: 3 } }\n */\nexport function parseRange(range: string): {\n start: { row: number; col: number }\n end: { row: number; col: number }\n} {\n const parts = range.split(':')\n if (parts.length === 1) {\n // Single cell address\n const addr = parseAddress(parts[0])\n return {\n start: { row: addr.row, col: addr.col },\n end: { row: addr.row, col: addr.col },\n }\n }\n if (parts.length !== 2) {\n throw new Error(`Invalid range: ${range}`)\n }\n const start = parseAddress(parts[0])\n const end = parseAddress(parts[1])\n return {\n start: { row: start.row, col: start.col },\n end: { row: end.row, col: end.col },\n }\n}\n\n/**\n * Format start and end coordinates into a range address.\n */\nexport function formatRange(\n startRow: number,\n startCol: number,\n endRow: number,\n endCol: number\n): string {\n const start = formatAddress(startRow, startCol)\n const end = formatAddress(endRow, endCol)\n return start === end ? start : `${start}:${end}`\n}\n\n/**\n * Check if a cell address is within a range.\n */\nexport function isInRange(\n row: number,\n col: number,\n range: { start: { row: number; col: number }; end: { row: number; col: number } }\n): boolean {\n return (\n row >= range.start.row &&\n row <= range.end.row &&\n col >= range.start.col &&\n col <= range.end.col\n )\n}\n\n/**\n * Type helper for ExcelJS cell values.\n */\nexport function normalizeValue(value: unknown): unknown {\n if (value === undefined || value === null) return null\n if (typeof value === 'object' && 'error' in (value as object)) {\n return { error: (value as { error: string }).error }\n }\n if (typeof value === 'object' && 'formula' in (value as object)) {\n const formulaValue = value as { formula: string; result?: unknown }\n return {\n formula: formulaValue.formula,\n result: normalizeValue(formulaValue.result),\n }\n }\n return value\n}\n","/**\n * XlsxCell - wrapper around ExcelJS cell with path tracking and typed extraction.\n *\n * @module xlsx/xlsx-cell\n */\n\nimport type { Cell as ExcelJSCell, CellValue as ExcelJSValue } from 'exceljs'\nimport {\n XlsxResult,\n XlsxPath,\n CellValue,\n ExtendedCellValue,\n ok,\n fail,\n isFormula,\n isError,\n} from './xlsx-result'\nimport { formatAddress } from './util'\n\n/**\n * Cell style information.\n */\nexport interface CellStyle {\n readonly font?: {\n readonly name?: string\n readonly size?: number\n readonly bold?: boolean\n readonly italic?: boolean\n readonly underline?: boolean\n readonly strikethrough?: boolean\n readonly color?: string\n }\n readonly fill?: {\n readonly type?: string\n readonly color?: string\n }\n readonly border?: {\n readonly top?: boolean\n readonly bottom?: boolean\n readonly left?: boolean\n readonly right?: boolean\n }\n readonly alignment?: {\n readonly horizontal?: string\n readonly vertical?: string\n readonly wrapText?: boolean\n }\n readonly numFmt?: string\n}\n\n/**\n * A segment of rich text with its formatting.\n */\nexport interface RichTextSegment {\n readonly text: string\n readonly bold?: boolean\n readonly italic?: boolean\n readonly underline?: boolean\n readonly strikethrough?: boolean\n readonly color?: string\n readonly size?: number\n readonly font?: string\n}\n\n/**\n * Rich text content with all formatting preserved.\n */\nexport interface RichTextContent {\n readonly segments: readonly RichTextSegment[]\n readonly hyperlink?: string\n}\n\n/**\n * A wrapper around ExcelJS Cell with full metadata preservation.\n *\n * XlsxCell enables typed extraction of cell values while maintaining\n * provenance information. Each cell knows its exact location in the\n * workbook, allowing full traceability.\n */\nexport class XlsxCell {\n private constructor(\n private readonly cell: ExcelJSCell,\n private readonly _path: XlsxPath,\n private readonly _sheetName: string\n ) {}\n\n /**\n * Creates an XlsxCell from an ExcelJS cell.\n * @internal\n */\n static fromExcelJS(\n cell: ExcelJSCell,\n sheetName: string,\n file?: string\n ): XlsxCell {\n const path: XlsxPath = {\n file,\n sheet: sheetName,\n cell: cell.address,\n }\n return new XlsxCell(cell, path, sheetName)\n }\n\n // ---------------------------------------------------------------------------\n // IDENTITY & LOCATION\n // ---------------------------------------------------------------------------\n\n /**\n * Returns the cell address (e.g., \"A1\").\n */\n get address(): string {\n return this.cell.address\n }\n\n /**\n * Returns the 1-based row number.\n */\n get row(): number {\n return typeof this.cell.row === 'number' ? this.cell.row : parseInt(String(this.cell.row), 10)\n }\n\n /**\n * Returns the 1-based column number.\n */\n get col(): number {\n return typeof this.cell.col === 'number' ? this.cell.col : parseInt(String(this.cell.col), 10)\n }\n\n /**\n * Returns the column letter(s) (e.g., \"A\", \"AA\").\n */\n get colLetter(): string {\n return this.address.replace(/\\d+$/, '')\n }\n\n /**\n * Returns the current path for lineage tracking.\n */\n get path(): XlsxPath {\n return this._path\n }\n\n /**\n * Returns the sheet name this cell belongs to.\n */\n get sheetName(): string {\n return this._sheetName\n }\n\n // ---------------------------------------------------------------------------\n // VALUE EXTRACTION\n // ---------------------------------------------------------------------------\n\n /**\n * Returns the raw cell value.\n */\n value(): XlsxResult<CellValue> {\n const val = this.getRawValue()\n if (isFormula(val)) {\n return ok(val.result ?? null, this._path)\n }\n if (isError(val)) {\n return fail('formula', `Cell contains error: ${val.error}`, this._path)\n }\n // At this point val is CellValue (not formula or error)\n return ok(val as CellValue, this._path)\n }\n\n /**\n * Returns the extended cell value (including formula info).\n */\n extendedValue(): XlsxResult<ExtendedCellValue> {\n return ok(this.getRawValue(), this._path)\n }\n\n /**\n * Extract value as a string.\n */\n string(): XlsxResult<string> {\n const val = this.getResolvedValue()\n if (val === null || val === undefined) {\n return fail('type', 'Expected string, got null', this._path)\n }\n if (typeof val === 'string') {\n return ok(val, this._path)\n }\n // Convert to string\n if (typeof val === 'number' || typeof val === 'boolean') {\n return ok(String(val), this._path)\n }\n if (val instanceof Date) {\n return ok(val.toISOString(), this._path)\n }\n return fail('type', `Expected string, got ${typeof val}`, this._path)\n }\n\n /**\n * Extract value as a number.\n */\n number(): XlsxResult<number> {\n const val = this.getResolvedValue()\n if (typeof val === 'number') {\n return ok(val, this._path)\n }\n if (typeof val === 'string') {\n const num = parseFloat(val)\n if (!isNaN(num)) {\n return ok(num, this._path)\n }\n }\n return fail('type', `Expected number, got ${typeOf(val)}`, this._path)\n }\n\n /**\n * Extract value as a boolean.\n */\n boolean(): XlsxResult<boolean> {\n const val = this.getResolvedValue()\n if (typeof val === 'boolean') {\n return ok(val, this._path)\n }\n return fail('type', `Expected boolean, got ${typeOf(val)}`, this._path)\n }\n\n /**\n * Extract value as a Date.\n */\n date(): XlsxResult<Date> {\n const val = this.getResolvedValue()\n if (val instanceof Date) {\n return ok(val, this._path)\n }\n if (typeof val === 'number') {\n // Excel stores dates as numbers (days since 1900-01-01)\n const date = this.excelDateToJS(val)\n return ok(date, this._path)\n }\n if (typeof val === 'string') {\n const date = new Date(val)\n if (!isNaN(date.getTime())) {\n return ok(date, this._path)\n }\n }\n return fail('type', `Expected date, got ${typeOf(val)}`, this._path)\n }\n\n /**\n * Get the formula if this cell contains one.\n */\n formula(): XlsxResult<string> {\n const val = this.getRawValue()\n if (isFormula(val)) {\n return ok(val.formula, this._path)\n }\n return fail('type', 'Cell does not contain a formula', this._path)\n }\n\n // ---------------------------------------------------------------------------\n // RICH TEXT & MARKDOWN\n // ---------------------------------------------------------------------------\n\n /**\n * Get the cell content as rich text with formatting preserved.\n * Returns segments with their individual formatting properties.\n */\n richText(): XlsxResult<RichTextContent> {\n const rawVal = this.cell.value as ExcelJSValue\n const hyperlink = this.cell.hyperlink\n\n // Handle rich text cells\n if (rawVal && typeof rawVal === 'object' && 'richText' in rawVal) {\n const rt = rawVal as {\n richText: Array<{\n text: string\n font?: {\n bold?: boolean\n italic?: boolean\n underline?: boolean | string\n strike?: boolean\n color?: { argb?: string; theme?: number }\n size?: number\n name?: string\n }\n }>\n }\n\n const segments: RichTextSegment[] = rt.richText.map(segment => ({\n text: segment.text,\n bold: segment.font?.bold,\n italic: segment.font?.italic,\n underline: segment.font?.underline === true || segment.font?.underline === 'single',\n strikethrough: segment.font?.strike,\n color: segment.font?.color?.argb,\n size: segment.font?.size,\n font: segment.font?.name,\n }))\n\n return ok({ segments, hyperlink }, this._path)\n }\n\n // Handle hyperlink with text\n if (rawVal && typeof rawVal === 'object' && 'text' in rawVal && 'hyperlink' in rawVal) {\n const linkVal = rawVal as { text: string; hyperlink: string }\n const style = this.style()\n const segment: RichTextSegment = {\n text: linkVal.text,\n bold: style.font?.bold,\n italic: style.font?.italic,\n underline: style.font?.underline,\n strikethrough: style.font?.strikethrough,\n color: style.font?.color,\n size: style.font?.size,\n font: style.font?.name,\n }\n return ok(\n {\n segments: [segment],\n hyperlink: linkVal.hyperlink,\n },\n this._path\n )\n }\n\n // Plain value - wrap in single segment with cell-level formatting\n const plainValue = this.getResolvedValue()\n const text = plainValue !== null ? String(plainValue) : ''\n const style = this.style()\n\n const segment: RichTextSegment = {\n text,\n bold: style.font?.bold,\n italic: style.font?.italic,\n underline: style.font?.underline,\n strikethrough: style.font?.strikethrough,\n color: style.font?.color,\n size: style.font?.size,\n font: style.font?.name,\n }\n\n return ok({ segments: [segment], hyperlink }, this._path)\n }\n\n /**\n * Get the cell content as Markdown.\n *\n * Converts cell content including:\n * - Bold text -> **text**\n * - Italic text -> *text*\n * - Strikethrough -> ~~text~~\n * - Hyperlinks -> [text](url)\n * - Rich text segments with mixed formatting\n */\n markdown(): XlsxResult<string> {\n const rtResult = this.richText()\n if (!rtResult.ok) {\n return rtResult as XlsxResult<string>\n }\n\n const { segments, hyperlink } = rtResult.value\n let result = ''\n\n for (const segment of segments) {\n let text = segment.text\n\n // Apply formatting in order: strikethrough, then bold, then italic\n if (segment.strikethrough) {\n text = `~~${text}~~`\n }\n if (segment.bold) {\n text = `**${text}**`\n }\n if (segment.italic) {\n text = `*${text}*`\n }\n\n result += text\n }\n\n // Wrap in hyperlink if present\n if (hyperlink) {\n result = `[${result}](${hyperlink})`\n }\n\n return ok(result, this._path)\n }\n\n /**\n * Check if the cell contains rich text (multiple formatted segments).\n */\n isRichText(): boolean {\n const rawVal = this.cell.value as ExcelJSValue\n return rawVal !== null && typeof rawVal === 'object' && 'richText' in rawVal\n }\n\n // ---------------------------------------------------------------------------\n // TYPE CHECKING\n // ---------------------------------------------------------------------------\n\n /**\n * Check if the cell is empty.\n */\n isEmpty(): boolean {\n const val = this.cell.value\n return val === null || val === undefined || val === ''\n }\n\n /**\n * Check if the cell contains a formula.\n */\n isFormula(): boolean {\n return isFormula(this.getRawValue())\n }\n\n /**\n * Check if the cell is part of a merged range.\n */\n isMerged(): boolean {\n return this.cell.isMerged\n }\n\n /**\n * Check if this is the master cell of a merged range.\n */\n isMergedMaster(): boolean {\n if (!this.cell.isMerged) return false\n const master = this.cell.master\n return master.address === this.cell.address\n }\n\n /**\n * Check if the cell contains a string.\n */\n isString(): boolean {\n return typeof this.getResolvedValue() === 'string'\n }\n\n /**\n * Check if the cell contains a number.\n */\n isNumber(): boolean {\n return typeof this.getResolvedValue() === 'number'\n }\n\n /**\n * Check if the cell contains a boolean.\n */\n isBoolean(): boolean {\n return typeof this.getResolvedValue() === 'boolean'\n }\n\n /**\n * Check if the cell contains a date.\n */\n isDate(): boolean {\n const val = this.getResolvedValue()\n return val instanceof Date\n }\n\n /**\n * Check if the cell contains an error.\n */\n isError(): boolean {\n return isError(this.getRawValue())\n }\n\n // ---------------------------------------------------------------------------\n // METADATA\n // ---------------------------------------------------------------------------\n\n /**\n * Get the cell's style information.\n */\n style(): CellStyle {\n const font = this.cell.font\n const fill = this.cell.fill\n const border = this.cell.border\n const alignment = this.cell.alignment\n\n return {\n font: font\n ? {\n name: font.name,\n size: font.size,\n bold: font.bold,\n italic: font.italic,\n underline: font.underline === true || font.underline === 'single',\n strikethrough: font.strike,\n color:\n font.color?.argb ??\n (font.color?.theme !== undefined\n ? `theme:${font.color.theme}`\n : undefined),\n }\n : undefined,\n fill:\n fill && fill.type === 'pattern'\n ? {\n type: (fill as { pattern?: string }).pattern,\n color: (fill as { fgColor?: { argb?: string } }).fgColor?.argb,\n }\n : undefined,\n border: border\n ? {\n top: !!border.top,\n bottom: !!border.bottom,\n left: !!border.left,\n right: !!border.right,\n }\n : undefined,\n alignment: alignment\n ? {\n horizontal: alignment.horizontal,\n vertical: alignment.vertical,\n wrapText: alignment.wrapText,\n }\n : undefined,\n numFmt: this.cell.numFmt,\n }\n }\n\n /**\n * Get the hyperlink URL if the cell contains one.\n */\n hyperlink(): XlsxResult<string> {\n const link = this.cell.hyperlink\n if (!link) {\n return fail('missing', 'Cell does not contain a hyperlink', this._path)\n }\n return ok(link, this._path)\n }\n\n /**\n * Get the comment/note if the cell has one.\n */\n comment(): XlsxResult<string> {\n const note = this.cell.note\n if (!note) {\n return fail('missing', 'Cell does not contain a comment', this._path)\n }\n if (typeof note === 'string') {\n return ok(note, this._path)\n }\n // RichText note\n if (note.texts) {\n return ok(\n note.texts.map((t: { text: string }) => t.text).join(''),\n this._path\n )\n }\n return fail('format', 'Unable to extract comment text', this._path)\n }\n\n // ---------------------------------------------------------------------------\n // NAVIGATION FROM CELL\n // ---------------------------------------------------------------------------\n\n /**\n * Get a cell offset from this one.\n * @internal Used by navigation methods\n */\n getOffsetCell(\n rowDelta: number,\n colDelta: number,\n getCell: (row: number, col: number) => XlsxCell | undefined\n ): XlsxResult<XlsxCell> {\n const newRow = this.row + rowDelta\n const newCol = this.col + colDelta\n if (newRow < 1 || newCol < 1) {\n return fail(\n 'bounds',\n `Cell offset (${rowDelta}, ${colDelta}) from ${this.address} is out of bounds`,\n this._path\n )\n }\n const cell = getCell(newRow, newCol)\n if (!cell) {\n return fail(\n 'missing',\n `Cell at ${formatAddress(newRow, newCol)} not found`,\n this._path\n )\n }\n return ok(cell, cell.path)\n }\n\n // ---------------------------------------------------------------------------\n // INTERNAL HELPERS\n // ---------------------------------------------------------------------------\n\n /**\n * Get the raw value, handling ExcelJS value types.\n */\n private getRawValue(): ExtendedCellValue {\n const val = this.cell.value as ExcelJSValue\n if (val === null || val === undefined) {\n return null\n }\n\n // Handle different ExcelJS value types\n if (typeof val === 'object') {\n // Error value\n if ('error' in val) {\n return { error: String((val as { error: unknown }).error) }\n }\n // Formula value\n if ('formula' in val) {\n const formulaVal = val as {\n formula: string\n result?: ExcelJSValue\n }\n return {\n formula: formulaVal.formula,\n result: this.normalizeResult(formulaVal.result),\n }\n }\n // Shared formula\n if ('sharedFormula' in val) {\n const sharedVal = val as {\n sharedFormula: string\n result?: ExcelJSValue\n }\n return {\n formula: sharedVal.sharedFormula,\n result: this.normalizeResult(sharedVal.result),\n }\n }\n // Rich text\n if ('richText' in val) {\n const richText = val as {\n richText: Array<{ text: string }>\n }\n return richText.richText.map(r => r.text).join('')\n }\n // Date\n if (val instanceof Date) {\n return val\n }\n }\n\n // Primitive values\n if (\n typeof val === 'string' ||\n typeof val === 'number' ||\n typeof val === 'boolean'\n ) {\n return val\n }\n\n return null\n }\n\n /**\n * Get the resolved value (formula result or plain value).\n */\n private getResolvedValue(): CellValue {\n const val = this.getRawValue()\n if (isFormula(val)) {\n return val.result ?? null\n }\n if (isError(val)) {\n return null\n }\n // At this point val is CellValue (not formula or error)\n return val as CellValue\n }\n\n /**\n * Normalize a formula result value.\n */\n private normalizeResult(result: unknown): CellValue {\n if (result === null || result === undefined) return null\n if (\n typeof result === 'string' ||\n typeof result === 'number' ||\n typeof result === 'boolean'\n ) {\n return result\n }\n if (result instanceof Date) {\n return result\n }\n return null\n }\n\n /**\n * Convert Excel date number to JavaScript Date.\n * Excel dates are days since 1900-01-01 (with a leap year bug).\n */\n private excelDateToJS(excelDate: number): Date {\n // Excel incorrectly treats 1900 as a leap year\n // Dates before March 1, 1900 need adjustment\n const offset = excelDate > 60 ? -1 : 0\n const days = excelDate + offset - 1\n\n // Excel epoch is 1900-01-01\n const excelEpoch = new Date(1900, 0, 1)\n const jsDate = new Date(excelEpoch.getTime() + days * 24 * 60 * 60 * 1000)\n\n return jsDate\n }\n}\n\n/**\n * Returns a human-readable type name.\n */\nfunction typeOf(value: unknown): string {\n if (value === null) return 'null'\n if (value === undefined) return 'undefined'\n if (value instanceof Date) return 'date'\n if (Array.isArray(value)) return 'array'\n return typeof value\n}\n","/**\n * XlsxRange - represents a range of cells with iteration and query capabilities.\n *\n * @module xlsx/xlsx-range\n */\n\nimport type { Worksheet } from 'exceljs'\nimport { XlsxCell } from './xlsx-cell'\nimport {\n XlsxResult,\n XlsxPath,\n CellValue,\n ok,\n fail,\n} from './xlsx-result'\nimport { formatRange, parseRange } from './util'\nimport type { CellPredicate } from './xlsx-query'\n\n/**\n * A range of cells in an XLSX sheet.\n *\n * XlsxRange enables iteration over cells, rows, and columns within\n * a defined rectangular region. It supports predicate-based queries\n * and conversion to various formats.\n */\nexport class XlsxRange {\n private constructor(\n private readonly worksheet: Worksheet,\n private readonly _startRow: number,\n private readonly _startCol: number,\n private readonly _endRow: number,\n private readonly _endCol: number,\n private readonly _path: XlsxPath,\n private readonly _sheetName: string,\n private readonly _file?: string\n ) {}\n\n /**\n * Creates an XlsxRange from coordinates.\n * @internal\n */\n static fromCoords(\n worksheet: Worksheet,\n startRow: number,\n startCol: number,\n endRow: number,\n endCol: number,\n sheetName: string,\n file?: string\n ): XlsxRange {\n const rangeAddr = formatRange(startRow, startCol, endRow, endCol)\n const path: XlsxPath = {\n file,\n sheet: sheetName,\n range: rangeAddr,\n }\n return new XlsxRange(\n worksheet,\n startRow,\n startCol,\n endRow,\n endCol,\n path,\n sheetName,\n file\n )\n }\n\n /**\n * Creates an XlsxRange from an address string.\n * @internal\n */\n static fromAddress(\n worksheet: Worksheet,\n address: string,\n sheetName: string,\n file?: string\n ): XlsxResult<XlsxRange> {\n try {\n const { start, end } = parseRange(address)\n return ok(\n XlsxRange.fromCoords(\n worksheet,\n start.row,\n start.col,\n end.row,\n end.col,\n sheetName,\n file\n ),\n { file, sheet: sheetName, range: address }\n )\n } catch {\n return fail(\n 'range',\n `Invalid range address: ${address}`,\n { file, sheet: sheetName }\n )\n }\n }\n\n // ---------------------------------------------------------------------------\n // IDENTITY\n // ---------------------------------------------------------------------------\n\n /**\n * Returns the range address (e.g., \"A1:C10\").\n */\n get address(): string {\n return formatRange(\n this._startRow,\n this._startCol,\n this._endRow,\n this._endCol\n )\n }\n\n /**\n * Returns the start row (1-based).\n */\n get startRow(): number {\n return this._startRow\n }\n\n /**\n * Returns the start column (1-based).\n */\n get startCol(): number {\n return this._startCol\n }\n\n /**\n * Returns the end row (1-based).\n */\n get endRow(): number {\n return this._endRow\n }\n\n /**\n * Returns the end column (1-based).\n */\n get endCol(): number {\n return this._endCol\n }\n\n /**\n * Returns the current path for lineage tracking.\n */\n get path(): XlsxPath {\n return this._path\n }\n\n /**\n * Returns the number of rows in the range.\n */\n get rowCount(): number {\n return this._endRow - this._startRow + 1\n }\n\n /**\n * Returns the number of columns in the range.\n */\n get colCount(): number {\n return this._endCol - this._startCol + 1\n }\n\n /**\n * Returns the total number of cells in the range.\n */\n get cellCount(): number {\n return this.rowCount * this.colCount\n }\n\n // ---------------------------------------------------------------------------\n // CELL ACCESS\n // ---------------------------------------------------------------------------\n\n /**\n * Get a cell at specific row and column within this range.\n * Coordinates are relative to the range start (0-indexed).\n */\n cellAt(rowOffset: number, colOffset: number): XlsxResult<XlsxCell> {\n const row = this._startRow + rowOffset\n const col = this._startCol + colOffset\n if (\n row < this._startRow ||\n row > this._endRow ||\n col < this._startCol ||\n col > this._endCol\n ) {\n return fail(\n 'bounds',\n `Offset (${rowOffset}, ${colOffset}) is outside range ${this.address}`,\n this._path\n )\n }\n const cell = this.worksheet.getCell(row, col)\n return ok(XlsxCell.fromExcelJS(cell, this._sheetName, this._file), {\n ...this._path,\n cell: cell.address,\n range: undefined,\n })\n }\n\n /**\n * Get a cell by its address within this range.\n */\n cell(address: string): XlsxResult<XlsxCell> {\n try {\n const { start } = parseRange(address)\n if (\n start.row < this._startRow ||\n start.row > this._endRow ||\n start.col < this._startCol ||\n start.col > this._endCol\n ) {\n return fail(\n 'bounds',\n `Cell ${address} is outside range ${this.address}`,\n this._path\n )\n }\n const cell = this.worksheet.getCell(address)\n return ok(XlsxCell.fromExcelJS(cell, this._sheetName, this._file), {\n ...this._path,\n cell: address,\n range: undefined,\n })\n } catch {\n return fail('range', `Invalid cell address: ${address}`, this._path)\n }\n }\n\n // ---------------------------------------------------------------------------\n // ITERATION\n // ---------------------------------------------------------------------------\n\n /**\n * Iterate over all cells in the range (row by row).\n */\n *cells(): Iterable<XlsxCell> {\n for (let row = this._startRow; row <= this._endRow; row++) {\n for (let col = this._startCol; col <= this._endCol; col++) {\n const cell = this.worksheet.getCell(row, col)\n yield XlsxCell.fromExcelJS(cell, this._sheetName, this._file)\n }\n }\n }\n\n /**\n * Iterate over rows, returning arrays of cells.\n */\n *rows(): Iterable<XlsxCell[]> {\n for (let row = this._startRow; row <= this._endRow; row++) {\n const rowCells: XlsxCell[] = []\n for (let col = this._startCol; col <= this._endCol; col++) {\n const cell = this.worksheet.getCell(row, col)\n rowCells.push(XlsxCell.fromExcelJS(cell, this._sheetName, this._file))\n }\n yield rowCells\n }\n }\n\n /**\n * Iterate over columns, returning arrays of cells.\n */\n *cols(): Iterable<XlsxCell[]> {\n for (let col = this._startCol; col <= this._endCol; col++) {\n const colCells: XlsxCell[] = []\n for (let row = this._startRow; row <= this._endRow; row++) {\n const cell = this.worksheet.getCell(row, col)\n colCells.push(XlsxCell.fromExcelJS(cell, this._sheetName, this._file))\n }\n yield colCells\n }\n }\n\n /**\n * Get all values in the range as a 2D array.\n */\n values(): CellValue[][] {\n const result: CellValue[][] = []\n for (const rowCells of this.rows()) {\n const rowValues: CellValue[] = []\n for (const cell of rowCells) {\n const val = cell.value()\n rowValues.push(val.ok ? val.value : null)\n }\n result.push(rowValues)\n }\n return result\n }\n\n /**\n * Get all cells as a flat array.\n */\n cellsArray(): XlsxCell[] {\n return [...this.cells()]\n }\n\n // ---------------------------------------------------------------------------\n // SUBRANGE\n // ---------------------------------------------------------------------------\n\n /**\n * Get a subrange within this range.\n */\n subRange(address: string): XlsxResult<XlsxRange> {\n try {\n const { start, end } = parseRange(address)\n if (\n start.row < this._startRow ||\n end.row > this._endRow ||\n start.col < this._startCol ||\n end.col > this._endCol\n ) {\n return fail(\n 'bounds',\n `Subrange ${address} extends outside range ${this.address}`,\n this._path\n )\n }\n return ok(\n XlsxRange.fromCoords(\n this.worksheet,\n start.row,\n start.col,\n end.row,\n end.col,\n this._sheetName,\n this._file\n ),\n { ...this._path, range: address }\n )\n } catch {\n return fail('range', `Invalid range address: ${address}`, this._path)\n }\n }\n\n /**\n * Get the first row as a range.\n */\n firstRow(): XlsxRange {\n return XlsxRange.fromCoords(\n this.worksheet,\n this._startRow,\n this._startCol,\n this._startRow,\n this._endCol,\n this._sheetName,\n this._file\n )\n }\n\n /**\n * Get the last row as a range.\n */\n lastRow(): XlsxRange {\n return XlsxRange.fromCoords(\n this.worksheet,\n this._endRow,\n this._startCol,\n this._endRow,\n this._endCol,\n this._sheetName,\n this._file\n )\n }\n\n /**\n * Get the first column as a range.\n */\n firstCol(): XlsxRange {\n return XlsxRange.fromCoords(\n this.worksheet,\n this._startRow,\n this._startCol,\n this._endRow,\n this._startCol,\n this._sheetName,\n this._file\n )\n }\n\n /**\n * Get the last column as a range.\n */\n lastCol(): XlsxRange {\n return XlsxRange.fromCoords(\n this.worksheet,\n this._startRow,\n this._endCol,\n this._endRow,\n this._endCol,\n this._sheetName,\n this._file\n )\n }\n\n /**\n * Get a specific row as a range (0-indexed offset from start).\n */\n rowAt(offset: number): XlsxResult<XlsxRange> {\n const row = this._startRow + offset\n if (row < this._startRow || row > this._endRow) {\n return fail(\n 'bounds',\n `Row offset ${offset} is outside range ${this.address}`,\n this._path\n )\n }\n return ok(\n XlsxRange.fromCoords(\n this.worksheet,\n row,\n this._startCol,\n row,\n this._endCol,\n this._sheetName,\n this._file\n ),\n this._path\n )\n }\n\n /**\n * Get a specific column as a range (0-indexed offset from start).\n */\n colAt(offset: number): XlsxResult<XlsxRange> {\n const col = this._startCol + offset\n if (col < this._startCol || col > this._endCol) {\n return fail(\n 'bounds',\n `Column offset ${offset} is outside range ${this.address}`,\n this._path\n )\n }\n return ok(\n XlsxRange.fromCoords(\n this.worksheet,\n this._startRow,\n col,\n this._endRow,\n col,\n this._sheetName,\n this._file\n ),\n this._path\n )\n }\n\n // ---------------------------------------------------------------------------\n // QUERY\n // ---------------------------------------------------------------------------\n\n /**\n * Find the first cell matching the predicate.\n */\n find(predicate: CellPredicate): XlsxResult<XlsxCell> {\n for (const cell of this.cells()) {\n if (predicate(cell)) {\n return ok(cell, cell.path)\n }\n }\n return fail(\n 'missing',\n `No cell matching predicate found in range ${this.address}`,\n this._path\n )\n }\n\n /**\n * Find all cells matching the predicate.\n */\n findAll(predicate: CellPredicate): XlsxCell[] {\n const results: XlsxCell[] = []\n for (const cell of this.cells()) {\n if (predicate(cell)) {\n results.push(cell)\n }\n }\n return results\n }\n\n /**\n * Find the first cell with the specified value.\n */\n findValue(value: CellValue): XlsxResult<XlsxCell> {\n for (const cell of this.cells()) {\n const cellVal = cell.value()\n if (cellVal.ok && cellVal.value === value) {\n return ok(cell, cell.path)\n }\n }\n return fail(\n 'missing',\n `Value \"${value}\" not found in range ${this.address}`,\n this._path\n )\n }\n\n /**\n * Check if any cell matches the predicate.\n */\n some(predicate: CellPredicate): boolean {\n for (const cell of this.cells()) {\n if (predicate(cell)) {\n return true\n }\n }\n return false\n }\n\n /**\n * Check if all cells match the predicate.\n */\n every(predicate: CellPredicate): boolean {\n for (const cell of this.cells()) {\n if (!predicate(cell)) {\n return false\n }\n }\n return true\n }\n\n /**\n * Count cells matching the predicate.\n */\n count(predicate: CellPredicate): number {\n let count = 0\n for (const cell of this.cells()) {\n if (predicate(cell)) {\n count++\n }\n }\n return count\n }\n\n // ---------------------------------------------------------------------------\n // CONVERSION\n // ---------------------------------------------------------------------------\n\n /**\n * Convert range to a 2D array of values.\n */\n toArray(): CellValue[][] {\n return this.values()\n }\n\n /**\n * Convert range to array of objects using a header row.\n * @param headerRowOffset - Row offset for headers (default: 0, first row)\n * @param dataStartOffset - Row offset where data starts (default: 1, second row)\n */\n toObjects(\n headerRowOffset: number = 0,\n dataStartOffset: number = 1\n ): Record<string, CellValue>[] {\n const allRows = [...this.rows()]\n if (allRows.length === 0) return []\n\n // Get headers from the specified row\n const headerRow = allRows[headerRowOffset]\n if (!headerRow) return []\n\n const headers: string[] = headerRow.map(cell => {\n const val = cell.value()\n return val.ok && val.value !== null ? String(val.value) : ''\n })\n\n // Convert data rows to objects\n const result: Record<string, CellValue>[] = []\n for (let i = dataStartOffset; i < allRows.length; i++) {\n const row = allRows[i]\n const obj: Record<string, CellValue> = {}\n for (let j = 0; j < headers.length; j++) {\n const header = headers[j]\n if (header) {\n const cell = row[j]\n const val = cell?.value()\n obj[header] = val?.ok ? val.value : null\n }\n }\n result.push(obj)\n }\n return result\n }\n\n /**\n * Convert range to JSON-compatible structure.\n */\n toJson(): {\n address: string\n rows: Array<Array<CellValue>>\n } {\n return {\n address: this.address,\n rows: this.values(),\n }\n }\n}\n","/**\n * XlsxCursor - immutable cursor for navigating through cells.\n *\n * @module xlsx/xlsx-cursor\n */\n\nimport type { XlsxSheet } from './xlsx-sheet'\nimport { XlsxCell } from './xlsx-cell'\nimport {\n XlsxResult,\n XlsxPath,\n ok,\n fail,\n} from './xlsx-result'\nimport {\n parseAddress,\n formatAddress,\n columnLetterToNumber,\n columnNumberToLetter,\n} from './util'\nimport type { CellPredicate } from './xlsx-query'\n\n/**\n * Direction for cursor movement.\n */\nexport type CursorDirection = 'right' | 'left' | 'down' | 'up'\n\n/**\n * Result of a grab operation.\n */\nexport interface GrabResult {\n readonly cells: XlsxCell[]\n readonly cursor: XlsxCursor\n}\n\n/**\n * Result of a single grab operation.\n */\nexport interface GrabOneResult {\n readonly cell: XlsxCell\n readonly cursor: XlsxCursor\n}\n\n/**\n * An immutable cursor for navigating through cells in a sheet.\n *\n * XlsxCursor provides a fluent API for moving through cells,\n * skipping cells based on predicates, and grabbing sequences\n * of cells. Each operation returns a new cursor, maintaining\n * immutability.\n */\nexport class XlsxCursor {\n private constructor(\n private readonly sheet: XlsxSheet,\n private readonly _row: number,\n private readonly _col: number,\n private readonly _direction: CursorDirection = 'right'\n ) {}\n\n /**\n * Create a cursor from an address string.\n * @internal\n */\n static create(sheet: XlsxSheet, address: string): XlsxCursor {\n const { row, col } = parseAddress(address)\n return new XlsxCursor(sheet, row, col)\n }\n\n /**\n * Create a cursor from row and column coordinates.\n * @internal\n */\n static createAt(sheet: XlsxSheet, row: number, col: number): XlsxCursor {\n return new XlsxCursor(sheet, Math.max(1, row), Math.max(1, col))\n }\n\n // ---------------------------------------------------------------------------\n // POSITION\n // ---------------------------------------------------------------------------\n\n /**\n * Get the current row (1-based).\n */\n get row(): number {\n return this._row\n }\n\n /**\n * Get the current column (1-based).\n */\n get col(): number {\n return this._col\n }\n\n /**\n * Get the current address.\n */\n get address(): string {\n return formatAddress(this._row, this._col)\n }\n\n /**\n * Get the current column letter.\n */\n get colLetter(): string {\n return columnNumberToLetter(this._col)\n }\n\n /**\n * Get the current direction.\n */\n get direction(): CursorDirection {\n return this._direction\n }\n\n /**\n * Get the path for lineage tracking.\n */\n get path(): XlsxPath {\n return {\n ...this.sheet.path,\n cell: this.address,\n }\n }\n\n // ---------------------------------------------------------------------------\n // MOVEMENT\n // ---------------------------------------------------------------------------\n\n /**\n * Move by a delta (returns new cursor).\n */\n move(rowDelta: number, colDelta: number): XlsxCursor {\n return new XlsxCursor(\n this.sheet,\n Math.max(1, this._row + rowDelta),\n Math.max(1, this._col + colDelta),\n this._direction\n )\n }\n\n /**\n * Move to a specific address.\n */\n moveTo(address: string): XlsxCursor {\n const { row, col } = parseAddress(address)\n return new XlsxCursor(this.sheet, row, col, this._direction)\n }\n\n /**\n * Move to a specific row.\n */\n moveToRow(row: number): XlsxCursor {\n return new XlsxCursor(this.sheet, Math.max(1, row), this._col, this._direction)\n }\n\n /**\n * Move to a specific column.\n */\n moveToCol(col: number | string): XlsxCursor {\n const colNum =\n typeof col === 'string' ? columnLetterToNumber(col.toUpperCase()) : col\n return new XlsxCursor(this.sheet, this._row, Math.max(1, colNum), this._direction)\n }\n\n /**\n * Move left by count cells.\n */\n left(count: number = 1): XlsxCursor {\n return new XlsxCursor(\n this.sheet,\n this._row,\n Math.max(1, this._col - count),\n 'left'\n )\n }\n\n /**\n * Move right by count cells.\n */\n right(count: number = 1): XlsxCursor {\n return new XlsxCursor(this.sheet, this._row, this._col + count, 'right')\n }\n\n /**\n * Move up by count cells.\n */\n up(count: number = 1): XlsxCursor {\n return new XlsxCursor(\n this.sheet,\n Math.max(1, this._row - count),\n this._col,\n 'up'\n )\n }\n\n /**\n * Move down by count cells.\n */\n down(count: number = 1): XlsxCursor {\n return new XlsxCursor(this.sheet, this._row + count, this._col, 'down')\n }\n\n /**\n * Set the current direction.\n */\n setDirection(direction: CursorDirection): XlsxCursor {\n return new XlsxCursor(this.sheet, this._row, this._col, direction)\n }\n\n /**\n * Move forward in the current direction.\n */\n forward(count: number = 1): XlsxCursor {\n switch (this._direction) {\n case 'right':\n return this.right(count)\n case 'left':\n return this.left(count)\n case 'down':\n return this.down(count)\n case 'up':\n return this.up(count)\n }\n }\n\n /**\n * Move to the start of the current row.\n */\n startOfRow(): XlsxCursor {\n return new XlsxCursor(this.sheet, this._row, 1, this._direction)\n }\n\n /**\n * Move to the start of the current column.\n */\n startOfCol(): XlsxCursor {\n return new XlsxCursor(this.sheet, 1, this._col, this._direction)\n }\n\n // ---------------------------------------------------------------------------\n // SKIP OPERATIONS\n // ---------------------------------------------------------------------------\n\n /**\n * Skip empty cells in the current direction.\n */\n skipEmpty(): XlsxCursor {\n return this.skipWhile(cell => cell.isEmpty())\n }\n\n /**\n * Skip cells while the predicate is true.\n */\n skipWhile(predicate: CellPredicate): XlsxCursor {\n // eslint-disable-next-line @typescript-eslint/no-this-alias\n let cursor: XlsxCursor = this\n const dims = this.sheet.dimensions()\n const maxIterations = Math.max(dims.rowCount, dims.colCount) * 2\n\n for (let i = 0; i < maxIterations; i++) {\n const cellResult = cursor.cell()\n if (!cellResult.ok) break\n if (!predicate(cellResult.value)) break\n cursor = cursor.forward()\n }\n return cursor\n }\n\n /**\n * Skip cells until the predicate is true.\n */\n skipUntil(predicate: CellPredicate): XlsxCursor {\n return this.skipWhile(cell => !predicate(cell))\n }\n\n /**\n * Skip cells until a specific value is found.\n */\n skipToValue(value: unknown): XlsxCursor {\n return this.skipUntil(cell => {\n const val = cell.value()\n return val.ok && val.value === value\n })\n }\n\n /**\n * Skip a specific number of cells.\n */\n skip(count: number): XlsxCursor {\n return this.forward(count)\n }\n\n // ---------------------------------------------------------------------------\n // GRAB OPERATIONS\n // ---------------------------------------------------------------------------\n\n /**\n * Grab the current cell and move forward.\n */\n grab(): XlsxResult<GrabOneResult> {\n const cellResult = this.cell()\n if (!cellResult.ok) return cellResult\n return ok(\n {\n cell: cellResult.value,\n cursor: this.forward(),\n },\n this.path\n )\n }\n\n /**\n * Grab n cells in the current direction.\n */\n grabN(count: number): XlsxResult<GrabResult> {\n const cells: XlsxCell[] = []\n // eslint-disable-next-line @typescript-eslint/no-this-alias\n let cursor: XlsxCursor = this\n\n for (let i = 0; i < count; i++) {\n const cellResult = cursor.cell()\n if (!cellResult.ok) {\n // Return what we have so far\n break\n }\n cells.push(cellResult.value)\n cursor = cursor.forward()\n }\n\n if (cells.length === 0) {\n return fail('bounds', 'No cells to grab', this.path)\n }\n\n return ok({ cells, cursor }, this.path)\n }\n\n /**\n * Grab cells while the predicate is true.\n */\n grabWhile(predicate: CellPredicate): XlsxResult<GrabResult> {\n const cells: XlsxCell[] = []\n // eslint-disable-next-line @typescript-eslint/no-this-alias\n let cursor: XlsxCursor = this\n const dims = this.sheet.dimensions()\n const maxIterations = Math.max(dims.rowCount, dims.colCount) * 2\n\n for (let i = 0; i < maxIterations; i++) {\n const cellResult = cursor.cell()\n if (!cellResult.ok) break\n if (!predicate(cellResult.value)) break\n cells.push(cellResult.value)\n cursor = cursor.forward()\n }\n\n return ok({ cells, cursor }, this.path)\n }\n\n /**\n * Grab cells until the predicate is true (not including the matching cell).\n */\n grabUntil(predicate: CellPredicate): XlsxResult<GrabResult> {\n return this.grabWhile(cell => !predicate(cell))\n }\n\n /**\n * Grab the rest of the current row.\n */\n grabRow(): XlsxResult<GrabResult> {\n const cells: XlsxCell[] = []\n const dims = this.sheet.dimensions()\n let cursor = this.setDirection('right')\n\n for (let col = this._col; col <= dims.endCol; col++) {\n const cellResult = cursor.cell()\n if (!cellResult.ok) break\n cells.push(cellResult.value)\n cursor = cursor.forward()\n }\n\n return ok({ cells, cursor }, this.path)\n }\n\n /**\n * Grab the rest of the current column.\n */\n grabCol(): XlsxResult<GrabResult> {\n const cells: XlsxCell[] = []\n const dims = this.sheet.dimensions()\n let cursor = this.setDirection('down')\n\n for (let row = this._row; row <= dims.endRow; row++) {\n const cellResult = cursor.cell()\n if (!cellResult.ok) break\n cells.push(cellResult.value)\n cursor = cursor.forward()\n }\n\n return ok({ cells, cursor }, this.path)\n }\n\n /**\n * Grab non-empty cells in the current direction.\n */\n grabNonEmpty(): XlsxResult<GrabResult> {\n return this.grabWhile(cell => !cell.isEmpty())\n }\n\n // ---------------------------------------------------------------------------\n // PEEK OPERATIONS\n // ---------------------------------------------------------------------------\n\n /**\n * Peek at the current cell without moving.\n */\n peek(): XlsxResult<XlsxCell> {\n return this.cell()\n }\n\n /**\n * Peek at cells ahead without moving.\n */\n peekAhead(count: number): XlsxResult<XlsxCell[]> {\n const cells: XlsxCell[] = []\n // eslint-disable-next-line @typescript-eslint/no-this-alias\n let cursor: XlsxCursor = this\n\n for (let i = 0; i < count; i++) {\n const cellResult = cursor.cell()\n if (!cellResult.ok) break\n cells.push(cellResult.value)\n cursor = cursor.forward()\n }\n\n return ok(cells, this.path)\n }\n\n /**\n * Peek at a cell at an offset without moving.\n */\n peekAt(rowDelta: number, colDelta: number): XlsxResult<XlsxCell> {\n return this.move(rowDelta, colDelta).cell()\n }\n\n // ---------------------------------------------------------------------------\n // CURRENT CELL\n // ---------------------------------------------------------------------------\n\n /**\n * Get the cell at the current position.\n */\n cell(): XlsxResult<XlsxCell> {\n return this.sheet.cellAt(this._row, this._col)\n }\n\n /**\n * Get the value of the current cell.\n */\n value(): XlsxResult<unknown> {\n const cellResult = this.cell()\n if (!cellResult.ok) return cellResult\n return cellResult.value.value()\n }\n\n // ---------------------------------------------------------------------------\n // UTILITIES\n // ---------------------------------------------------------------------------\n\n /**\n * Check if the cursor is at a valid position with data.\n */\n isValid(): boolean {\n const cellResult = this.cell()\n return cellResult.ok\n }\n\n /**\n * Check if the current cell is empty.\n */\n isEmpty(): boolean {\n const cellResult = this.cell()\n return cellResult.ok && cellResult.value.isEmpty()\n }\n\n /**\n * Check if the current cell is non-empty.\n */\n isNotEmpty(): boolean {\n const cellResult = this.cell()\n return cellResult.ok && !cellResult.value.isEmpty()\n }\n\n /**\n * Create a new cursor at the same position.\n */\n clone(): XlsxCursor {\n return new XlsxCursor(this.sheet, this._row, this._col, this._direction)\n }\n}\n","/**\n * XlsxSheet - wrapper around ExcelJS worksheet with navigation and query capabilities.\n *\n * @module xlsx/xlsx-sheet\n */\n\nimport type { Worksheet } from 'exceljs'\nimport { XlsxCell } from './xlsx-cell'\nimport { XlsxRange } from './xlsx-range'\nimport { XlsxCursor } from './xlsx-cursor'\nimport {\n XlsxResult,\n XlsxPath,\n CellValue,\n ok,\n fail,\n} from './xlsx-result'\nimport {\n parseAddress,\n parseRange,\n columnLetterToNumber,\n} from './util'\nimport type { CellPredicate } from './xlsx-query'\n\n/**\n * Dimensions of a sheet's used range.\n */\nexport interface SheetDimensions {\n readonly startRow: number\n readonly endRow: number\n readonly startCol: number\n readonly endCol: number\n readonly rowCount: number\n readonly colCount: number\n}\n\n/**\n * A wrapper around ExcelJS Worksheet with navigation and query capabilities.\n *\n * XlsxSheet provides a rich API for navigating cells, ranges, and rows\n * within a worksheet. It supports predicate-based queries and cursor-based\n * navigation for complex data extraction scenarios.\n */\nexport class XlsxSheet {\n private constructor(\n private readonly worksheet: Worksheet,\n private readonly _path: XlsxPath,\n private readonly _file?: string\n ) {}\n\n /**\n * Creates an XlsxSheet from an ExcelJS worksheet.\n * @internal\n */\n static fromExcelJS(worksheet: Worksheet, file?: string): XlsxSheet {\n const path: XlsxPath = {\n file,\n sheet: worksheet.name,\n }\n return new XlsxSheet(worksheet, path, file)\n }\n\n // ---------------------------------------------------------------------------\n // IDENTITY\n // ---------------------------------------------------------------------------\n\n /**\n * Returns the sheet name.\n */\n get name(): string {\n return this.worksheet.name\n }\n\n /**\n * Returns the sheet index (1-based).\n */\n get index(): number {\n return this.worksheet.id\n }\n\n /**\n * Returns the current path for lineage tracking.\n */\n get path(): XlsxPath {\n return this._path\n }\n\n // ---------------------------------------------------------------------------\n // CELL ACCESS\n // ---------------------------------------------------------------------------\n\n /**\n * Get a cell by its address (e.g., \"A1\", \"B2\").\n */\n cell(address: string): XlsxResult<XlsxCell> {\n try {\n parseAddress(address) // Validate address\n const cell = this.worksheet.getCell(address)\n return ok(XlsxCell.fromExcelJS(cell, this.name, this._file), {\n ...this._path,\n cell: address,\n })\n } catch {\n return fail('range', `Invalid cell address: ${address}`, this._path)\n }\n }\n\n /**\n * Get a cell by row and column numbers (1-based).\n */\n cellAt(row: number, col: number): XlsxResult<XlsxCell> {\n if (row < 1 || col < 1) {\n return fail(\n 'bounds',\n `Invalid cell coordinates: row=${row}, col=${col}`,\n this._path\n )\n }\n const cell = this.worksheet.getCell(row, col)\n return ok(XlsxCell.fromExcelJS(cell, this.name, this._file), {\n ...this._path,\n cell: cell.address,\n })\n }\n\n /**\n * Get the value of a cell directly.\n */\n getValue(address: string): XlsxResult<CellValue> {\n const cellResult = this.cell(address)\n if (!cellResult.ok) return cellResult\n return cellResult.value.value()\n }\n\n // ---------------------------------------------------------------------------\n // RANGE OPERATIONS\n // ---------------------------------------------------------------------------\n\n /**\n * Get a range by its address (e.g., \"A1:C10\").\n */\n range(address: string): XlsxResult<XlsxRange> {\n return XlsxRange.fromAddress(this.worksheet, address, this.name, this._file)\n }\n\n /**\n * Get a range from start to end addresses.\n */\n rangeFrom(start: string, end: string): XlsxResult<XlsxRange> {\n return this.range(`${start}:${end}`)\n }\n\n /**\n * Get a range by coordinates (1-based).\n */\n rangeAt(\n startRow: number,\n startCol: number,\n endRow: number,\n endCol: number\n ): XlsxResult<XlsxRange> {\n if (startRow < 1 || startCol < 1 || endRow < 1 || endCol < 1) {\n return fail('bounds', 'Invalid range coordinates', this._path)\n }\n return ok(\n XlsxRange.fromCoords(\n this.worksheet,\n startRow,\n startCol,\n endRow,\n endCol,\n this.name,\n this._file\n ),\n this._path\n )\n }\n\n /**\n * Get the used range of the sheet (cells with data).\n */\n usedRange(): XlsxResult<XlsxRange> {\n const dims = this.dimensions()\n if (dims.rowCount === 0 || dims.colCount === 0) {\n return fail('missing', 'Sheet has no used cells', this._path)\n }\n return ok(\n XlsxRange.fromCoords(\n this.worksheet,\n dims.startRow,\n dims.startCol,\n dims.endRow,\n dims.endCol,\n this.name,\n this._file\n ),\n this._path\n )\n }\n\n // ---------------------------------------------------------------------------\n // ROW / COLUMN ACCESS\n // ---------------------------------------------------------------------------\n\n /**\n * Get a row as a range.\n */\n row(rowNum: number): XlsxResult<XlsxRange> {\n const dims = this.dimensions()\n if (rowNum < 1) {\n return fail('bounds', `Invalid row number: ${rowNum}`, this._path)\n }\n const endCol = Math.max(dims.endCol, 1)\n return ok(\n XlsxRange.fromCoords(\n this.worksheet,\n rowNum,\n 1,\n rowNum,\n endCol,\n this.name,\n this._file\n ),\n this._path\n )\n }\n\n /**\n * Get a column as a range.\n */\n col(colId: string | number): XlsxResult<XlsxRange> {\n const colNum =\n typeof colId === 'string' ? columnLetterToNumber(colId.toUpperCase()) : colId\n if (colNum < 1) {\n return fail('bounds', `Invalid column: ${colId}`, this._path)\n }\n const dims = this.dimensions()\n const endRow = Math.max(dims.endRow, 1)\n return ok(\n XlsxRange.fromCoords(\n this.worksheet,\n 1,\n colNum,\n endRow,\n colNum,\n this.name,\n this._file\n ),\n this._path\n )\n }\n\n /**\n * Iterate over all rows with data.\n */\n *rows(): Iterable<XlsxRange> {\n const dims = this.dimensions()\n for (let r = dims.startRow; r <= dims.endRow; r++) {\n yield XlsxRange.fromCoords(\n this.worksheet,\n r,\n dims.startCol,\n r,\n dims.endCol,\n this.name,\n this._file\n )\n }\n }\n\n /**\n * Iterate over all columns with data.\n */\n *cols(): Iterable<XlsxRange> {\n const dims = this.dimensions()\n for (let c = dims.startCol; c <= dims.endCol; c++) {\n yield XlsxRange.fromCoords(\n this.worksheet,\n dims.startRow,\n c,\n dims.endRow,\n c,\n this.name,\n this._file\n )\n }\n }\n\n // ---------------------------------------------------------------------------\n // CURSOR CREATION\n // ---------------------------------------------------------------------------\n\n /**\n * Create a cursor starting at the specified address.\n */\n cursor(startAddress?: string): XlsxCursor {\n const address = startAddress ?? 'A1'\n return XlsxCursor.create(this, address)\n }\n\n /**\n * Create a cursor starting at the specified coordinates (1-based).\n */\n cursorAt(row: number, col: number): XlsxCursor {\n return XlsxCursor.createAt(this, row, col)\n }\n\n // ---------------------------------------------------------------------------\n // QUERY METHODS\n // ---------------------------------------------------------------------------\n\n /**\n * Find the first cell matching the predicate.\n */\n find(predicate: CellPredicate): XlsxResult<XlsxCell> {\n const rangeResult = this.usedRange()\n if (!rangeResult.ok) return rangeResult as XlsxResult<XlsxCell>\n return rangeResult.value.find(predicate)\n }\n\n /**\n * Find all cells matching the predicate.\n */\n findAll(predicate: CellPredicate): XlsxCell[] {\n const rangeResult = this.usedRange()\n if (!rangeResult.ok) return []\n return rangeResult.value.findAll(predicate)\n }\n\n /**\n * Find the first cell with the specified value.\n */\n findValue(value: CellValue): XlsxResult<XlsxCell> {\n const rangeResult = this.usedRange()\n if (!rangeResult.ok) return rangeResult as XlsxResult<XlsxCell>\n return rangeResult.value.findValue(value)\n }\n\n /**\n * Find cells within a specific range matching the predicate.\n */\n findInRange(\n rangeAddress: string,\n predicate: CellPredicate\n ): XlsxResult<XlsxCell> {\n const rangeResult = this.range(rangeAddress)\n if (!rangeResult.ok) return rangeResult as XlsxResult<XlsxCell>\n return rangeResult.value.find(predicate)\n }\n\n /**\n * Find all cells within a specific range matching the predicate.\n */\n findAllInRange(rangeAddress: string, predicate: CellPredicate): XlsxCell[] {\n const rangeResult = this.range(rangeAddress)\n if (!rangeResult.ok) return []\n return rangeResult.value.findAll(predicate)\n }\n\n // ---------------------------------------------------------------------------\n // DIMENSIONS\n // ---------------------------------------------------------------------------\n\n /**\n * Get the dimensions of the used area.\n */\n dimensions(): SheetDimensions {\n // ExcelJS tracks dimensions in the worksheet\n const rowCount = this.worksheet.rowCount\n const columnCount = this.worksheet.columnCount\n\n // Find actual used range by checking rows\n let startRow = 1\n let endRow = rowCount\n let startCol = 1\n let endCol = columnCount\n\n // Try to get actual dimensions from worksheet\n if (this.worksheet.dimensions) {\n const dims = this.worksheet.dimensions\n // dims is a string like \"A1:C10\" or an object\n if (typeof dims === 'string') {\n try {\n const parsed = parseRange(dims)\n startRow = parsed.start.row\n startCol = parsed.start.col\n endRow = parsed.end.row\n endCol = parsed.end.col\n } catch {\n // Fall back to calculated dimensions\n }\n }\n }\n\n return {\n startRow,\n endRow,\n startCol,\n endCol,\n rowCount: endRow - startRow + 1,\n colCount: endCol - startCol + 1,\n }\n }\n\n /**\n * Get the number of rows with data.\n */\n rowCount(): number {\n return this.dimensions().rowCount\n }\n\n /**\n * Get the number of columns with data.\n */\n colCount(): number {\n return this.dimensions().colCount\n }\n\n // ---------------------------------------------------------------------------\n // MERGED CELLS\n // ---------------------------------------------------------------------------\n\n /**\n * Get all merged cell ranges.\n */\n mergedRanges(): string[] {\n // ExcelJS stores merged cells in the _merges property or via hasMerges\n const merges = (this.worksheet as unknown as { _merges?: Record<string, unknown> })._merges\n if (!merges) return []\n return Object.keys(merges)\n }\n\n /**\n * Check if a cell is part of a merged range.\n */\n isMerged(address: string): boolean {\n const cellResult = this.cell(address)\n if (!cellResult.ok) return false\n return cellResult.value.isMerged()\n }\n\n // ---------------------------------------------------------------------------\n // INTERNAL HELPERS\n // ---------------------------------------------------------------------------\n\n /**\n * Get the underlying ExcelJS worksheet.\n * @internal\n */\n getWorksheet(): Worksheet {\n return this.worksheet\n }\n\n /**\n * Get a cell by coordinates for internal use.\n * @internal\n */\n getCellInternal(row: number, col: number): XlsxCell | undefined {\n if (row < 1 || col < 1) return undefined\n const cell = this.worksheet.getCell(row, col)\n return XlsxCell.fromExcelJS(cell, this.name, this._file)\n }\n}\n","/**\n * XlsxWorkbook - wrapper around ExcelJS workbook with navigation and query capabilities.\n *\n * @module xlsx/xlsx-workbook\n */\n\nimport type { Workbook } from 'exceljs'\nimport { XlsxSheet } from './xlsx-sheet'\nimport {\n XlsxResult,\n XlsxPath,\n ok,\n fail,\n} from './xlsx-result'\n\n/**\n * Predicate function for matching sheets.\n */\nexport type SheetPredicate = (sheet: XlsxSheet) => boolean\n\n/**\n * Workbook properties.\n */\nexport interface WorkbookProperties {\n readonly title?: string\n readonly subject?: string\n readonly creator?: string\n readonly lastModifiedBy?: string\n readonly created?: Date\n readonly modified?: Date\n}\n\n/**\n * A wrapper around ExcelJS Workbook with navigation and query capabilities.\n *\n * XlsxWorkbook provides access to sheets, workbook properties, and\n * supports predicate-based queries for finding sheets.\n */\nexport class XlsxWorkbook {\n private readonly sheetsCache: Map<string, XlsxSheet> = new Map()\n\n private constructor(\n private readonly workbook: Workbook,\n private readonly _path: XlsxPath\n ) {}\n\n /**\n * Creates an XlsxWorkbook from an ExcelJS workbook.\n * @internal\n */\n static fromExcelJS(workbook: Workbook, file?: string): XlsxWorkbook {\n const path: XlsxPath = { file }\n return new XlsxWorkbook(workbook, path)\n }\n\n // ---------------------------------------------------------------------------\n // IDENTITY\n // ---------------------------------------------------------------------------\n\n /**\n * Returns the path for lineage tracking.\n */\n get path(): XlsxPath {\n return this._path\n }\n\n /**\n * Returns the file name if known.\n */\n get file(): string | undefined {\n return this._path.file\n }\n\n // ---------------------------------------------------------------------------\n // SHEET ACCESS\n // ---------------------------------------------------------------------------\n\n /**\n * Get a sheet by name.\n */\n sheet(name: string): XlsxResult<XlsxSheet> {\n // Check cache first\n const cached = this.sheetsCache.get(name)\n if (cached) {\n return ok(cached, { ...this._path, sheet: name })\n }\n\n const worksheet = this.workbook.getWorksheet(name)\n if (!worksheet) {\n return fail(\n 'missing',\n `Sheet \"${name}\" not found`,\n this._path\n )\n }\n\n const sheet = XlsxSheet.fromExcelJS(worksheet, this._path.file)\n this.sheetsCache.set(name, sheet)\n return ok(sheet, sheet.path)\n }\n\n /**\n * Get a sheet by index (1-based, as per Excel convention).\n */\n sheetAt(index: number): XlsxResult<XlsxSheet> {\n if (index < 1) {\n return fail(\n 'bounds',\n `Sheet index must be >= 1, got ${index}`,\n this._path\n )\n }\n\n const worksheet = this.workbook.getWorksheet(index)\n if (!worksheet) {\n return fail(\n 'missing',\n `Sheet at index ${index} not found`,\n this._path\n )\n }\n\n // Check cache by name\n const cached = this.sheetsCache.get(worksheet.name)\n if (cached) {\n return ok(cached, cached.path)\n }\n\n const sheet = XlsxSheet.fromExcelJS(worksheet, this._path.file)\n this.sheetsCache.set(worksheet.name, sheet)\n return ok(sheet, sheet.path)\n }\n\n /**\n * Get all sheets.\n */\n sheets(): XlsxSheet[] {\n const sheets: XlsxSheet[] = []\n this.workbook.eachSheet((worksheet) => {\n const cached = this.sheetsCache.get(worksheet.name)\n if (cached) {\n sheets.push(cached)\n } else {\n const sheet = XlsxSheet.fromExcelJS(worksheet, this._path.file)\n this.sheetsCache.set(worksheet.name, sheet)\n sheets.push(sheet)\n }\n })\n return sheets\n }\n\n /**\n * Get all sheet names.\n */\n sheetNames(): string[] {\n const names: string[] = []\n this.workbook.eachSheet((worksheet) => {\n names.push(worksheet.name)\n })\n return names\n }\n\n /**\n * Get the number of sheets.\n */\n sheetCount(): number {\n return this.workbook.worksheets.length\n }\n\n /**\n * Get the first sheet.\n */\n firstSheet(): XlsxResult<XlsxSheet> {\n return this.sheetAt(1)\n }\n\n /**\n * Get the last sheet.\n */\n lastSheet(): XlsxResult<XlsxSheet> {\n const count = this.sheetCount()\n if (count === 0) {\n return fail('missing', 'Workbook has no sheets', this._path)\n }\n return this.sheetAt(count)\n }\n\n // ---------------------------------------------------------------------------\n // PREDICATES\n // ---------------------------------------------------------------------------\n\n /**\n * Check if a sheet with the given name exists.\n */\n hasSheet(name: string): boolean {\n return this.workbook.getWorksheet(name) !== undefined\n }\n\n /**\n * Find the first sheet matching the predicate.\n */\n findSheet(predicate: SheetPredicate): XlsxResult<XlsxSheet> {\n for (const sheet of this.sheets()) {\n if (predicate(sheet)) {\n return ok(sheet, sheet.path)\n }\n }\n return fail(\n 'missing',\n 'No sheet matching predicate found',\n this._path\n )\n }\n\n /**\n * Find all sheets matching the predicate.\n */\n filterSheets(predicate: SheetPredicate): XlsxSheet[] {\n return this.sheets().filter(predicate)\n }\n\n /**\n * Find a sheet by name pattern (regex).\n */\n findSheetByPattern(pattern: RegExp): XlsxResult<XlsxSheet> {\n return this.findSheet(sheet => pattern.test(sheet.name))\n }\n\n /**\n * Find all sheets by name pattern (regex).\n */\n filterSheetsByPattern(pattern: RegExp): XlsxSheet[] {\n return this.filterSheets(sheet => pattern.test(sheet.name))\n }\n\n // ---------------------------------------------------------------------------\n // WORKBOOK PROPERTIES\n // ---------------------------------------------------------------------------\n\n /**\n * Get workbook properties.\n */\n properties(): WorkbookProperties {\n return {\n title: this.workbook.title,\n subject: this.workbook.subject,\n creator: this.workbook.creator,\n lastModifiedBy: this.workbook.lastModifiedBy,\n created: this.workbook.created,\n modified: this.workbook.modified,\n }\n }\n\n /**\n * Get the workbook creator.\n */\n creator(): string | undefined {\n return this.workbook.creator\n }\n\n /**\n * Get the workbook creation date.\n */\n created(): Date | undefined {\n return this.workbook.created\n }\n\n /**\n * Get the workbook modification date.\n */\n modified(): Date | undefined {\n return this.workbook.modified\n }\n\n // ---------------------------------------------------------------------------\n // DEFINED NAMES\n // ---------------------------------------------------------------------------\n\n /**\n * Get all defined names in the workbook.\n */\n definedNames(): string[] {\n const names: string[] = []\n // ExcelJS stores defined names differently\n // This is a simplified implementation\n return names\n }\n\n // ---------------------------------------------------------------------------\n // ITERATION\n // ---------------------------------------------------------------------------\n\n /**\n * Iterate over all sheets.\n */\n *[Symbol.iterator](): Iterator<XlsxSheet> {\n for (const sheet of this.sheets()) {\n yield sheet\n }\n }\n\n /**\n * Execute a function for each sheet.\n */\n forEach(fn: (sheet: XlsxSheet, index: number) => void): void {\n this.sheets().forEach(fn)\n }\n\n /**\n * Map over all sheets.\n */\n map<T>(fn: (sheet: XlsxSheet, index: number) => T): T[] {\n return this.sheets().map(fn)\n }\n\n // ---------------------------------------------------------------------------\n // INTERNAL\n // ---------------------------------------------------------------------------\n\n /**\n * Get the underlying ExcelJS workbook.\n * @internal\n */\n getWorkbook(): Workbook {\n return this.workbook\n }\n}\n","/**\n * Query predicates for XLSX cell matching.\n *\n * @module xlsx/xlsx-query\n */\n\nimport type { XlsxCell } from './xlsx-cell'\nimport type { CellValue } from './xlsx-result'\n\n/**\n * A predicate function for matching cells.\n */\nexport type CellPredicate = (cell: XlsxCell) => boolean\n\n/**\n * Built-in predicates for common cell matching scenarios.\n */\nexport const predicates = {\n // ---------------------------------------------------------------------------\n // VALUE PREDICATES\n // ---------------------------------------------------------------------------\n\n /**\n * Match cells with the exact value.\n */\n equals: (value: CellValue): CellPredicate => {\n return (cell: XlsxCell) => {\n const val = cell.value()\n if (!val.ok) return false\n if (value === null) return val.value === null\n if (val.value === null) return false\n // Handle date comparison\n if (value instanceof Date && val.value instanceof Date) {\n return value.getTime() === val.value.getTime()\n }\n return val.value === value\n }\n },\n\n /**\n * Match cells containing the specified text (case-insensitive by default).\n */\n contains: (text: string, caseSensitive: boolean = false): CellPredicate => {\n return (cell: XlsxCell) => {\n const val = cell.string()\n if (!val.ok) return false\n if (caseSensitive) {\n return val.value.includes(text)\n }\n return val.value.toLowerCase().includes(text.toLowerCase())\n }\n },\n\n /**\n * Match cells whose value matches the regex pattern.\n */\n matches: (pattern: RegExp): CellPredicate => {\n return (cell: XlsxCell) => {\n const val = cell.string()\n if (!val.ok) return false\n return pattern.test(val.value)\n }\n },\n\n /**\n * Match cells whose string value starts with the prefix.\n */\n startsWith: (prefix: string, caseSensitive: boolean = false): CellPredicate => {\n return (cell: XlsxCell) => {\n const val = cell.string()\n if (!val.ok) return false\n if (caseSensitive) {\n return val.value.startsWith(prefix)\n }\n return val.value.toLowerCase().startsWith(prefix.toLowerCase())\n }\n },\n\n /**\n * Match cells whose string value ends with the suffix.\n */\n endsWith: (suffix: string, caseSensitive: boolean = false): CellPredicate => {\n return (cell: XlsxCell) => {\n const val = cell.string()\n if (!val.ok) return false\n if (caseSensitive) {\n return val.value.endsWith(suffix)\n }\n return val.value.toLowerCase().endsWith(suffix.toLowerCase())\n }\n },\n\n // ---------------------------------------------------------------------------\n // TYPE PREDICATES\n // ---------------------------------------------------------------------------\n\n /**\n * Match cells containing a string value.\n */\n isString: (): CellPredicate => {\n return (cell: XlsxCell) => cell.isString()\n },\n\n /**\n * Match cells containing a numeric value.\n */\n isNumber: (): CellPredicate => {\n return (cell: XlsxCell) => cell.isNumber()\n },\n\n /**\n * Match cells containing a boolean value.\n */\n isBoolean: (): CellPredicate => {\n return (cell: XlsxCell) => cell.isBoolean()\n },\n\n /**\n * Match cells containing a date value.\n */\n isDate: (): CellPredicate => {\n return (cell: XlsxCell) => cell.isDate()\n },\n\n /**\n * Match empty cells.\n */\n isEmpty: (): CellPredicate => {\n return (cell: XlsxCell) => cell.isEmpty()\n },\n\n /**\n * Match non-empty cells.\n */\n isNotEmpty: (): CellPredicate => {\n return (cell: XlsxCell) => !cell.isEmpty()\n },\n\n /**\n * Match cells containing a formula.\n */\n isFormula: (): CellPredicate => {\n return (cell: XlsxCell) => cell.isFormula()\n },\n\n /**\n * Match cells containing an error.\n */\n isError: (): CellPredicate => {\n return (cell: XlsxCell) => cell.isError()\n },\n\n /**\n * Match merged cells.\n */\n isMerged: (): CellPredicate => {\n return (cell: XlsxCell) => cell.isMerged()\n },\n\n // ---------------------------------------------------------------------------\n // NUMERIC PREDICATES\n // ---------------------------------------------------------------------------\n\n /**\n * Match cells with numeric value greater than n.\n */\n greaterThan: (n: number): CellPredicate => {\n return (cell: XlsxCell) => {\n const val = cell.number()\n return val.ok && val.value > n\n }\n },\n\n /**\n * Match cells with numeric value greater than or equal to n.\n */\n greaterThanOrEqual: (n: number): CellPredicate => {\n return (cell: XlsxCell) => {\n const val = cell.number()\n return val.ok && val.value >= n\n }\n },\n\n /**\n * Match cells with numeric value less than n.\n */\n lessThan: (n: number): CellPredicate => {\n return (cell: XlsxCell) => {\n const val = cell.number()\n return val.ok && val.value < n\n }\n },\n\n /**\n * Match cells with numeric value less than or equal to n.\n */\n lessThanOrEqual: (n: number): CellPredicate => {\n return (cell: XlsxCell) => {\n const val = cell.number()\n return val.ok && val.value <= n\n }\n },\n\n /**\n * Match cells with numeric value between min and max (inclusive).\n */\n between: (min: number, max: number): CellPredicate => {\n return (cell: XlsxCell) => {\n const val = cell.number()\n return val.ok && val.value >= min && val.value <= max\n }\n },\n\n // ---------------------------------------------------------------------------\n // DATE PREDICATES\n // ---------------------------------------------------------------------------\n\n /**\n * Match cells with date before the specified date.\n */\n dateBefore: (date: Date): CellPredicate => {\n return (cell: XlsxCell) => {\n const val = cell.date()\n return val.ok && val.value.getTime() < date.getTime()\n }\n },\n\n /**\n * Match cells with date after the specified date.\n */\n dateAfter: (date: Date): CellPredicate => {\n return (cell: XlsxCell) => {\n const val = cell.date()\n return val.ok && val.value.getTime() > date.getTime()\n }\n },\n\n /**\n * Match cells with date between start and end (inclusive).\n */\n dateBetween: (start: Date, end: Date): CellPredicate => {\n return (cell: XlsxCell) => {\n const val = cell.date()\n if (!val.ok) return false\n const time = val.value.getTime()\n return time >= start.getTime() && time <= end.getTime()\n }\n },\n\n // ---------------------------------------------------------------------------\n // LOCATION PREDICATES\n // ---------------------------------------------------------------------------\n\n /**\n * Match cells in the specified row.\n */\n inRow: (rowNum: number): CellPredicate => {\n return (cell: XlsxCell) => cell.row === rowNum\n },\n\n /**\n * Match cells in the specified column.\n */\n inCol: (colNum: number): CellPredicate => {\n return (cell: XlsxCell) => cell.col === colNum\n },\n\n /**\n * Match cells in the specified column (by letter).\n */\n inColLetter: (colLetter: string): CellPredicate => {\n return (cell: XlsxCell) =>\n cell.colLetter.toUpperCase() === colLetter.toUpperCase()\n },\n\n // ---------------------------------------------------------------------------\n // COMPOSITION\n // ---------------------------------------------------------------------------\n\n /**\n * Match cells that satisfy all predicates.\n */\n and: (...preds: CellPredicate[]): CellPredicate => {\n return (cell: XlsxCell) => preds.every(pred => pred(cell))\n },\n\n /**\n * Match cells that satisfy at least one predicate.\n */\n or: (...preds: CellPredicate[]): CellPredicate => {\n return (cell: XlsxCell) => preds.some(pred => pred(cell))\n },\n\n /**\n * Match cells that do not satisfy the predicate.\n */\n not: (pred: CellPredicate): CellPredicate => {\n return (cell: XlsxCell) => !pred(cell)\n },\n\n // ---------------------------------------------------------------------------\n // STYLE PREDICATES\n // ---------------------------------------------------------------------------\n\n /**\n * Match cells with bold font.\n */\n isBold: (): CellPredicate => {\n return (cell: XlsxCell) => {\n const style = cell.style()\n return style.font?.bold === true\n }\n },\n\n /**\n * Match cells with italic font.\n */\n isItalic: (): CellPredicate => {\n return (cell: XlsxCell) => {\n const style = cell.style()\n return style.font?.italic === true\n }\n },\n\n /**\n * Match cells with a hyperlink.\n */\n hasHyperlink: (): CellPredicate => {\n return (cell: XlsxCell) => {\n const link = cell.hyperlink()\n return link.ok\n }\n },\n\n /**\n * Match cells with a comment.\n */\n hasComment: (): CellPredicate => {\n return (cell: XlsxCell) => {\n const comment = cell.comment()\n return comment.ok\n }\n },\n\n // ---------------------------------------------------------------------------\n // UTILITY\n // ---------------------------------------------------------------------------\n\n /**\n * Always match.\n */\n always: (): CellPredicate => {\n return () => true\n },\n\n /**\n * Never match.\n */\n never: (): CellPredicate => {\n return () => false\n },\n\n /**\n * Create a custom predicate from a function.\n */\n custom: (fn: (cell: XlsxCell) => boolean): CellPredicate => {\n return fn\n },\n}\n\n/**\n * Type for the predicates object.\n */\nexport type Predicates = typeof predicates\n","/**\n * XLSX parsing transform for Origins.\n *\n * @module xlsx/parse\n */\n\nimport ExcelJS from 'exceljs'\nimport { XlsxWorkbook } from './xlsx-workbook'\nimport { streamToBuffer } from './util'\n\n/**\n * Transform AST specification.\n * Compatible with @origints/core TransformAst.\n */\nexport interface TransformAst {\n readonly kind: 'transform'\n readonly namespace: string\n readonly name: string\n readonly args?: unknown\n}\n\n/**\n * Transform implementation.\n * Compatible with @origints/core TransformImpl.\n */\nexport interface TransformImpl<In = unknown, Out = unknown> {\n readonly namespace: string\n readonly name: string\n execute(input: In, args?: unknown): Out | Promise<Out>\n}\n\n/**\n * Options for parsing XLSX.\n */\nexport interface XlsxParseOptions {\n /**\n * Which sheets to parse.\n * - 'all': Parse all sheets (default)\n * - string[]: Only parse sheets with these names\n * - number[]: Only parse sheets at these indices (1-based)\n */\n sheets?: 'all' | string[] | number[]\n\n /**\n * Whether to use formula results instead of formulas.\n * Default: true (use calculated results)\n */\n formulaResults?: boolean\n\n /**\n * Whether to include hidden sheets.\n * Default: true\n */\n includeHidden?: boolean\n\n /**\n * Date format for parsing dates.\n * This affects how date values are interpreted.\n */\n dateFormat?: string\n\n /**\n * File name to associate with the parsed workbook.\n * Used for lineage tracking.\n */\n fileName?: string\n}\n\n/**\n * Creates a TransformAst for parsing XLSX.\n *\n * @example\n * ```ts\n * const plan = new Planner()\n * .in(loadFile('data.xlsx'))\n * .mapIn(parseXlsx())\n * .emit((out, $) => out\n * .add('revenue', $.sheet('Sales').cell('B2').number())\n * )\n * .compile()\n * ```\n */\nexport function parseXlsx(options?: XlsxParseOptions): TransformAst {\n return {\n kind: 'transform',\n namespace: '@origints/xlsx',\n name: 'parseXlsx',\n args: options,\n }\n}\n\n/**\n * Sync transform implementation for parseXlsx.\n * Note: XLSX parsing requires async due to file reading.\n */\nexport const parseXlsxImpl: TransformImpl = {\n namespace: '@origints/xlsx',\n name: 'parseXlsx',\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n execute(input: unknown, args?: unknown): never {\n throw new Error(\n 'parseXlsx requires async execution. Use parseXlsxAsyncImpl instead.'\n )\n },\n}\n\n/**\n * Convert a buffer-like input to ArrayBuffer.\n */\nfunction toArrayBuffer(input: Buffer | Uint8Array): ArrayBuffer {\n // Create a new ArrayBuffer and copy data to avoid SharedArrayBuffer issues\n const copy = new Uint8Array(input)\n return copy.buffer\n}\n\n/**\n * Async transform implementation for parseXlsx (handles streams and buffers).\n */\nexport const parseXlsxAsyncImpl: TransformImpl = {\n namespace: '@origints/xlsx',\n name: 'parseXlsx',\n\n async execute(input: unknown, args?: unknown): Promise<XlsxWorkbook> {\n const options = (args as XlsxParseOptions) ?? {}\n\n let data: ArrayBuffer\n\n if (input instanceof ReadableStream) {\n const buffer = await streamToBuffer(input)\n data = toArrayBuffer(buffer)\n } else if (Buffer.isBuffer(input)) {\n data = toArrayBuffer(input)\n } else if (input instanceof ArrayBuffer) {\n data = input\n } else if (input instanceof Uint8Array) {\n data = toArrayBuffer(input)\n } else {\n throw new Error(\n `parseXlsx expects stream or buffer input, got ${typeof input}`\n )\n }\n\n const workbook = new ExcelJS.Workbook()\n await workbook.xlsx.load(data)\n\n return XlsxWorkbook.fromExcelJS(workbook, options.fileName)\n },\n}\n\n/**\n * Parse XLSX from a buffer directly.\n */\nexport async function parseXlsxBuffer(\n buffer: Buffer | ArrayBuffer | Uint8Array,\n options?: XlsxParseOptions\n): Promise<XlsxWorkbook> {\n const workbook = new ExcelJS.Workbook()\n let data: ArrayBuffer\n if (buffer instanceof ArrayBuffer) {\n data = buffer\n } else {\n data = toArrayBuffer(buffer)\n }\n await workbook.xlsx.load(data)\n return XlsxWorkbook.fromExcelJS(workbook, options?.fileName)\n}\n\n/**\n * Parse XLSX from a file path directly.\n * Useful for testing and standalone usage.\n */\nexport async function parseXlsxFile(\n filePath: string,\n options?: XlsxParseOptions\n): Promise<XlsxWorkbook> {\n const workbook = new ExcelJS.Workbook()\n await workbook.xlsx.readFile(filePath)\n return XlsxWorkbook.fromExcelJS(workbook, options?.fileName ?? filePath)\n}\n","/**\n * Conversion utilities for XLSX data.\n *\n * @module xlsx/convert\n */\n\nimport type { XlsxWorkbook } from './xlsx-workbook'\nimport type { XlsxSheet } from './xlsx-sheet'\nimport type { XlsxRange } from './xlsx-range'\nimport type { XlsxCell } from './xlsx-cell'\nimport type { CellValue } from './xlsx-result'\n\n/**\n * JSON-compatible value types.\n */\nexport type JsonValue =\n | string\n | number\n | boolean\n | null\n | JsonValue[]\n | { [key: string]: JsonValue }\n\n/**\n * Options for converting to JSON.\n */\nexport interface ToJsonOptions {\n /**\n * Include sheet names as keys.\n * Default: true\n */\n includeSheetNames?: boolean\n\n /**\n * Include cell addresses in output.\n * Default: false\n */\n includeCellAddresses?: boolean\n\n /**\n * Convert dates to ISO strings.\n * Default: true\n */\n dateAsIsoString?: boolean\n\n /**\n * Include empty cells.\n * Default: false\n */\n includeEmpty?: boolean\n\n /**\n * Use first row as headers for object conversion.\n * Default: false\n */\n firstRowAsHeaders?: boolean\n}\n\n/**\n * Convert a cell value to a JSON-compatible value.\n */\nexport function cellValueToJson(\n value: CellValue,\n options?: ToJsonOptions\n): JsonValue {\n if (value === null || value === undefined) {\n return null\n }\n if (value instanceof Date) {\n if (options?.dateAsIsoString !== false) {\n return value.toISOString()\n }\n return value.getTime()\n }\n if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {\n return value\n }\n return null\n}\n\n/**\n * Convert a cell to a JSON representation.\n */\nexport function cellToJson(\n cell: XlsxCell,\n options?: ToJsonOptions\n): JsonValue {\n const val = cell.value()\n const value = val.ok ? cellValueToJson(val.value, options) : null\n\n if (options?.includeCellAddresses) {\n return {\n address: cell.address,\n value,\n }\n }\n return value\n}\n\n/**\n * Convert a range to a JSON representation.\n */\nexport function rangeToJson(\n range: XlsxRange,\n options?: ToJsonOptions\n): JsonValue {\n if (options?.firstRowAsHeaders) {\n return rangeToObjects(range, options)\n }\n return rangeToArray(range, options)\n}\n\n/**\n * Convert a range to a 2D array.\n */\nexport function rangeToArray(\n range: XlsxRange,\n options?: ToJsonOptions\n): JsonValue[][] {\n const result: JsonValue[][] = []\n for (const rowCells of range.rows()) {\n const row: JsonValue[] = []\n for (const cell of rowCells) {\n const value = cellToJson(cell, options)\n if (value !== null || options?.includeEmpty) {\n row.push(value)\n } else if (row.length > 0 || options?.includeEmpty) {\n // Keep nulls for consistent column count\n row.push(null)\n }\n }\n if (row.length > 0 || options?.includeEmpty) {\n result.push(row)\n }\n }\n return result\n}\n\n/**\n * Convert a range to an array of objects using the first row as headers.\n */\nexport function rangeToObjects(\n range: XlsxRange,\n options?: ToJsonOptions\n): JsonValue {\n const rows = [...range.rows()]\n if (rows.length === 0) return []\n\n // Get headers from first row\n const headerRow = rows[0]\n const headers: string[] = headerRow.map(cell => {\n const val = cell.value()\n if (val.ok && val.value !== null) {\n return String(val.value)\n }\n return `col_${cell.col}`\n })\n\n // Convert data rows to objects\n const result: JsonValue[] = []\n for (let i = 1; i < rows.length; i++) {\n const row = rows[i]\n const obj: { [key: string]: JsonValue } = {}\n let hasData = false\n\n for (let j = 0; j < headers.length; j++) {\n const header = headers[j]\n const cell = row[j]\n if (cell) {\n const value = cellToJson(cell, options)\n if (value !== null) {\n hasData = true\n }\n obj[header] = value\n } else {\n obj[header] = null\n }\n }\n\n if (hasData || options?.includeEmpty) {\n result.push(obj)\n }\n }\n\n return result\n}\n\n/**\n * Convert a sheet to a JSON representation.\n */\nexport function sheetToJson(\n sheet: XlsxSheet,\n options?: ToJsonOptions\n): JsonValue {\n const rangeResult = sheet.usedRange()\n if (!rangeResult.ok) {\n return options?.firstRowAsHeaders ? [] : [[]]\n }\n return rangeToJson(rangeResult.value, options)\n}\n\n/**\n * Convert a workbook to a JSON representation.\n */\nexport function workbookToJson(\n workbook: XlsxWorkbook,\n options?: ToJsonOptions\n): JsonValue {\n const sheets = workbook.sheets()\n\n if (options?.includeSheetNames !== false) {\n const result: { [key: string]: JsonValue } = {}\n for (const sheet of sheets) {\n result[sheet.name] = sheetToJson(sheet, options)\n }\n return result\n }\n\n // Just return array of sheet data\n return sheets.map(sheet => sheetToJson(sheet, options))\n}\n\n/**\n * Convert a range to CSV format.\n */\nexport function rangeToCsv(\n range: XlsxRange,\n options?: {\n delimiter?: string\n lineEnding?: string\n quoteStrings?: boolean\n }\n): string {\n const delimiter = options?.delimiter ?? ','\n const lineEnding = options?.lineEnding ?? '\\n'\n const quoteStrings = options?.quoteStrings ?? true\n\n const lines: string[] = []\n\n for (const rowCells of range.rows()) {\n const values: string[] = []\n for (const cell of rowCells) {\n const val = cell.value()\n let str: string\n\n if (!val.ok || val.value === null) {\n str = ''\n } else if (val.value instanceof Date) {\n str = val.value.toISOString()\n } else {\n str = String(val.value)\n }\n\n // Quote if contains delimiter, newline, or quotes\n if (quoteStrings && (\n str.includes(delimiter) ||\n str.includes('\\n') ||\n str.includes('\\r') ||\n str.includes('\"')\n )) {\n str = '\"' + str.replace(/\"/g, '\"\"') + '\"'\n }\n\n values.push(str)\n }\n lines.push(values.join(delimiter))\n }\n\n return lines.join(lineEnding)\n}\n\n/**\n * Convert a sheet to CSV format.\n */\nexport function sheetToCsv(\n sheet: XlsxSheet,\n options?: {\n delimiter?: string\n lineEnding?: string\n quoteStrings?: boolean\n }\n): string {\n const rangeResult = sheet.usedRange()\n if (!rangeResult.ok) {\n return ''\n }\n return rangeToCsv(rangeResult.value, options)\n}\n","/**\n * @origints/xlsx - XLSX parsing for Origins with full traceability.\n *\n * This package provides a rich API for parsing and navigating XLSX files\n * with complete traceability to sheets, ranges, and cells.\n *\n * @packageDocumentation\n */\n\n// Re-export result types\nexport type {\n ExcelLocation,\n XlsxPath,\n XlsxFailure,\n XlsxFailureKind,\n XlsxResult,\n CellValue,\n ExtendedCellValue,\n} from './xlsx-result'\nexport {\n ok,\n fail,\n formatXlsxPath,\n toExcelLocation,\n isFormula,\n isError,\n} from './xlsx-result'\n\n// Re-export cell\nexport type { CellStyle, RichTextSegment, RichTextContent } from './xlsx-cell'\nexport { XlsxCell } from './xlsx-cell'\n\n// Re-export range\nexport { XlsxRange } from './xlsx-range'\n\n// Re-export sheet\nexport type { SheetDimensions } from './xlsx-sheet'\nexport { XlsxSheet } from './xlsx-sheet'\n\n// Re-export workbook\nexport type { SheetPredicate, WorkbookProperties } from './xlsx-workbook'\nexport { XlsxWorkbook } from './xlsx-workbook'\n\n// Re-export cursor\nexport type {\n CursorDirection,\n GrabResult,\n GrabOneResult,\n} from './xlsx-cursor'\nexport { XlsxCursor } from './xlsx-cursor'\n\n// Re-export query predicates\nexport type { CellPredicate, Predicates } from './xlsx-query'\nexport { predicates } from './xlsx-query'\n\n// Re-export parse functions and implementations\nexport type { XlsxParseOptions, TransformAst, TransformImpl } from './parse'\nexport {\n parseXlsx,\n parseXlsxImpl,\n parseXlsxAsyncImpl,\n parseXlsxBuffer,\n parseXlsxFile,\n} from './parse'\n\n// Re-export conversion utilities\nexport type { JsonValue, ToJsonOptions } from './convert'\nexport {\n cellValueToJson,\n cellToJson,\n rangeToJson,\n rangeToArray,\n rangeToObjects,\n sheetToJson,\n workbookToJson,\n rangeToCsv,\n sheetToCsv,\n} from './convert'\n\n// Re-export utilities\nexport {\n streamToBuffer,\n columnLetterToNumber,\n columnNumberToLetter,\n parseAddress,\n formatAddress,\n parseRange,\n formatRange,\n isInRange,\n} from './util'\n\n// ---------------------------------------------------------------------------\n// Auto-registration of transforms\n// ---------------------------------------------------------------------------\n\nimport { parseXlsxAsyncImpl } from './parse'\n\n/**\n * Register the XLSX transforms with a registry.\n * Call this to enable parseXlsx() in your plans.\n *\n * @example\n * ```ts\n * import { globalRegistry } from '@origints/core'\n * import { registerXlsxTransforms } from '@origints/xlsx'\n *\n * registerXlsxTransforms(globalRegistry)\n * ```\n */\nexport function registerXlsxTransforms(registry: {\n register(impl: {\n namespace: string\n name: string\n execute: (...args: unknown[]) => unknown\n }): void\n}): void {\n registry.register(parseXlsxAsyncImpl)\n}\n"],"names":["ok","value","path","fail","kind","message","sourceLocation","formatXlsxPath","parts","toExcelLocation","isFormula","isError","streamToBuffer","stream","reader","chunks","done","columnLetterToNumber","col","result","i","columnNumberToLetter","num","remainder","parseAddress","address","match","colLetter","formatAddress","row","parseRange","range","addr","start","end","formatRange","startRow","startCol","endRow","endCol","isInRange","XlsxCell","cell","_path","_sheetName","sheetName","file","val","typeOf","date","rawVal","hyperlink","segments","segment","linkVal","style","plainValue","text","rtResult","font","fill","border","alignment","link","note","t","rowDelta","colDelta","getCell","newRow","newCol","formulaVal","sharedVal","excelDate","offset","days","excelEpoch","XlsxRange","worksheet","_startRow","_startCol","_endRow","_endCol","_file","rangeAddr","rowOffset","colOffset","rowCells","colCells","rowValues","predicate","results","cellVal","count","headerRowOffset","dataStartOffset","allRows","headerRow","headers","obj","j","header","XlsxCursor","sheet","_row","_col","_direction","colNum","direction","cursor","dims","maxIterations","cellResult","cells","XlsxSheet","rowNum","colId","r","c","startAddress","rangeResult","rangeAddress","rowCount","columnCount","parsed","merges","XlsxWorkbook","workbook","name","cached","index","sheets","names","pattern","fn","predicates","caseSensitive","prefix","suffix","n","min","max","time","preds","pred","parseXlsx","options","parseXlsxImpl","input","args","toArrayBuffer","parseXlsxAsyncImpl","data","buffer","ExcelJS","parseXlsxBuffer","parseXlsxFile","filePath","cellValueToJson","cellToJson","rangeToJson","rangeToObjects","rangeToArray","rows","hasData","sheetToJson","workbookToJson","rangeToCsv","delimiter","lineEnding","quoteStrings","lines","values","str","sheetToCsv","registerXlsxTransforms","registry"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","sources":["../src/xlsx-result.ts","../src/util.ts","../src/xlsx-cell.ts","../src/xlsx-range.ts","../src/xlsx-cursor.ts","../src/xlsx-sheet.ts","../src/xlsx-workbook.ts","../src/xlsx-query.ts","../src/xlsx-spec-builder.ts","../src/parse.ts","../src/xlsx-predicate-compiler.ts","../src/xlsx-predicate-spec.ts","../src/xlsx-spec-executor.ts","../src/convert.ts","../src/index.ts"],"sourcesContent":["/**\n * Result types for XLSX operations.\n *\n * @module xlsx/xlsx-result\n */\n\n/**\n * Excel source location for lineage tracking.\n * Compatible with @origints/core ExcelLocation.\n */\nexport interface ExcelLocation {\n readonly kind: 'excel'\n readonly file: string\n readonly sheet: string\n readonly range: string\n}\n\n/**\n * Path through an XLSX structure, tracking how we arrived at a value.\n */\nexport interface XlsxPath {\n /** Source file name (if known) */\n readonly file?: string\n /** Sheet name */\n readonly sheet?: string\n /** Cell address (e.g., \"A1\") */\n readonly cell?: string\n /** Range address (e.g., \"A1:C10\") */\n readonly range?: string\n}\n\n/**\n * Failure kinds specific to XLSX operations.\n */\nexport type XlsxFailureKind =\n | 'parse' // XLSX parsing error\n | 'type' // Wrong type at location\n | 'missing' // Sheet, row, column, or cell not found\n | 'range' // Invalid range specification\n | 'format' // Invalid format (e.g., date format)\n | 'bounds' // Out of bounds access\n | 'merged' // Merged cell access issue\n | 'formula' // Formula evaluation error\n\n/**\n * A failure during XLSX traversal or extraction.\n */\nexport interface XlsxFailure {\n readonly kind: XlsxFailureKind\n readonly message: string\n readonly path: XlsxPath\n readonly sourceLocation?: ExcelLocation\n}\n\n/**\n * Result of an XLSX extraction - either a successful value or a failure.\n */\nexport type XlsxResult<T> =\n | { readonly ok: true; readonly value: T; readonly path: XlsxPath }\n | { readonly ok: false; readonly failure: XlsxFailure }\n\n/**\n * Creates a success result.\n */\nexport function ok<T>(value: T, path: XlsxPath): XlsxResult<T> {\n return { ok: true, value, path }\n}\n\n/**\n * Creates a failure result.\n */\nexport function fail(\n kind: XlsxFailureKind,\n message: string,\n path: XlsxPath,\n sourceLocation?: ExcelLocation\n): XlsxResult<never> {\n return {\n ok: false,\n failure: { kind, message, path, sourceLocation },\n }\n}\n\n/**\n * Formats a path for display.\n */\nexport function formatXlsxPath(path: XlsxPath): string {\n const parts: string[] = []\n if (path.file) parts.push(path.file)\n if (path.sheet) parts.push(`[${path.sheet}]`)\n if (path.range) parts.push(`!${path.range}`)\n else if (path.cell) parts.push(`!${path.cell}`)\n return parts.join('') || 'workbook'\n}\n\n/**\n * Creates an ExcelLocation from a path.\n */\nexport function toExcelLocation(path: XlsxPath): ExcelLocation | undefined {\n if (!path.sheet) return undefined\n return {\n kind: 'excel',\n file: path.file ?? '',\n sheet: path.sheet,\n range: path.range ?? path.cell ?? '',\n }\n}\n\n/**\n * Cell value types in XLSX.\n */\nexport type CellValue = string | number | boolean | Date | null\n\n/**\n * Extended cell value including formula and error types.\n */\nexport type ExtendedCellValue =\n | CellValue\n | { readonly formula: string; readonly result?: CellValue }\n | { readonly error: string }\n\n/**\n * Type guard for formula values.\n */\nexport function isFormula(\n value: ExtendedCellValue\n): value is { formula: string; result?: CellValue } {\n return (\n typeof value === 'object' &&\n value !== null &&\n !(value instanceof Date) &&\n 'formula' in value\n )\n}\n\n/**\n * Type guard for error values.\n */\nexport function isError(value: ExtendedCellValue): value is { error: string } {\n return (\n typeof value === 'object' &&\n value !== null &&\n !(value instanceof Date) &&\n 'error' in value\n )\n}\n","/**\n * Utility functions for XLSX package.\n *\n * @module xlsx/util\n */\n\n/**\n * Convert a ReadableStream<Uint8Array> to a Buffer.\n */\nexport async function streamToBuffer(\n stream: ReadableStream<Uint8Array>\n): Promise<Buffer> {\n const reader = stream.getReader()\n const chunks: Uint8Array[] = []\n\n try {\n while (true) {\n const { done, value } = await reader.read()\n if (done) break\n chunks.push(value)\n }\n return Buffer.concat(chunks)\n } finally {\n reader.releaseLock()\n }\n}\n\n/**\n * Convert column letter(s) to 1-based column number.\n * e.g., \"A\" -> 1, \"B\" -> 2, \"Z\" -> 26, \"AA\" -> 27\n */\nexport function columnLetterToNumber(col: string): number {\n let result = 0\n for (let i = 0; i < col.length; i++) {\n result = result * 26 + (col.charCodeAt(i) - 64)\n }\n return result\n}\n\n/**\n * Convert 1-based column number to column letter(s).\n * e.g., 1 -> \"A\", 2 -> \"B\", 26 -> \"Z\", 27 -> \"AA\"\n */\nexport function columnNumberToLetter(num: number): string {\n let result = ''\n while (num > 0) {\n const remainder = (num - 1) % 26\n result = String.fromCharCode(65 + remainder) + result\n num = Math.floor((num - 1) / 26)\n }\n return result\n}\n\n/**\n * Parse a cell address into row and column numbers.\n * e.g., \"A1\" -> { row: 1, col: 1 }, \"B10\" -> { row: 10, col: 2 }\n */\nexport function parseAddress(address: string): {\n row: number\n col: number\n colLetter: string\n} {\n const match = address.match(/^([A-Z]+)(\\d+)$/i)\n if (!match) {\n throw new Error(`Invalid cell address: ${address}`)\n }\n const colLetter = match[1].toUpperCase()\n return {\n row: parseInt(match[2], 10),\n col: columnLetterToNumber(colLetter),\n colLetter,\n }\n}\n\n/**\n * Format row and column numbers into a cell address.\n * e.g., { row: 1, col: 1 } -> \"A1\"\n */\nexport function formatAddress(row: number, col: number): string {\n return `${columnNumberToLetter(col)}${row}`\n}\n\n/**\n * Parse a range address into start and end coordinates.\n * e.g., \"A1:C10\" -> { start: { row: 1, col: 1 }, end: { row: 10, col: 3 } }\n */\nexport function parseRange(range: string): {\n start: { row: number; col: number }\n end: { row: number; col: number }\n} {\n const parts = range.split(':')\n if (parts.length === 1) {\n // Single cell address\n const addr = parseAddress(parts[0])\n return {\n start: { row: addr.row, col: addr.col },\n end: { row: addr.row, col: addr.col },\n }\n }\n if (parts.length !== 2) {\n throw new Error(`Invalid range: ${range}`)\n }\n const start = parseAddress(parts[0])\n const end = parseAddress(parts[1])\n return {\n start: { row: start.row, col: start.col },\n end: { row: end.row, col: end.col },\n }\n}\n\n/**\n * Format start and end coordinates into a range address.\n */\nexport function formatRange(\n startRow: number,\n startCol: number,\n endRow: number,\n endCol: number\n): string {\n const start = formatAddress(startRow, startCol)\n const end = formatAddress(endRow, endCol)\n return start === end ? start : `${start}:${end}`\n}\n\n/**\n * Check if a cell address is within a range.\n */\nexport function isInRange(\n row: number,\n col: number,\n range: {\n start: { row: number; col: number }\n end: { row: number; col: number }\n }\n): boolean {\n return (\n row >= range.start.row &&\n row <= range.end.row &&\n col >= range.start.col &&\n col <= range.end.col\n )\n}\n\n/**\n * Type helper for ExcelJS cell values.\n */\nexport function normalizeValue(value: unknown): unknown {\n if (value === undefined || value === null) return null\n if (typeof value === 'object' && 'error' in (value as object)) {\n return { error: (value as { error: string }).error }\n }\n if (typeof value === 'object' && 'formula' in (value as object)) {\n const formulaValue = value as { formula: string; result?: unknown }\n return {\n formula: formulaValue.formula,\n result: normalizeValue(formulaValue.result),\n }\n }\n return value\n}\n","/**\n * XlsxCell - wrapper around ExcelJS cell with path tracking and typed extraction.\n *\n * @module xlsx/xlsx-cell\n */\n\nimport { TYPE_LABEL } from '@origints/core'\nimport type { Cell as ExcelJSCell, CellValue as ExcelJSValue } from 'exceljs'\nimport {\n XlsxResult,\n XlsxPath,\n CellValue,\n ExtendedCellValue,\n ok,\n fail,\n isFormula,\n isError,\n} from './xlsx-result'\nimport { formatAddress } from './util'\n\n/**\n * Cell style information.\n */\nexport interface CellStyle {\n readonly font?: {\n readonly name?: string\n readonly size?: number\n readonly bold?: boolean\n readonly italic?: boolean\n readonly underline?: boolean\n readonly strikethrough?: boolean\n readonly color?: string\n }\n readonly fill?: {\n readonly type?: string\n readonly color?: string\n }\n readonly border?: {\n readonly top?: boolean\n readonly bottom?: boolean\n readonly left?: boolean\n readonly right?: boolean\n }\n readonly alignment?: {\n readonly horizontal?: string\n readonly vertical?: string\n readonly wrapText?: boolean\n }\n readonly numFmt?: string\n}\n\n/**\n * A segment of rich text with its formatting.\n */\nexport interface RichTextSegment {\n readonly text: string\n readonly bold?: boolean\n readonly italic?: boolean\n readonly underline?: boolean\n readonly strikethrough?: boolean\n readonly color?: string\n readonly size?: number\n readonly font?: string\n}\n\n/**\n * Rich text content with all formatting preserved.\n */\nexport interface RichTextContent {\n readonly segments: readonly RichTextSegment[]\n readonly hyperlink?: string\n}\n\n/**\n * A wrapper around ExcelJS Cell with full metadata preservation.\n *\n * XlsxCell enables typed extraction of cell values while maintaining\n * provenance information. Each cell knows its exact location in the\n * workbook, allowing full traceability.\n */\nexport class XlsxCell {\n get [TYPE_LABEL]() {\n return `XlsxCell(${this.address})`\n }\n\n private constructor(\n private readonly cell: ExcelJSCell,\n private readonly _path: XlsxPath,\n private readonly _sheetName: string\n ) {}\n\n /**\n * Creates an XlsxCell from an ExcelJS cell.\n * @internal\n */\n static fromExcelJS(\n cell: ExcelJSCell,\n sheetName: string,\n file?: string\n ): XlsxCell {\n const path: XlsxPath = {\n file,\n sheet: sheetName,\n cell: cell.address,\n }\n return new XlsxCell(cell, path, sheetName)\n }\n\n // ---------------------------------------------------------------------------\n // IDENTITY & LOCATION\n // ---------------------------------------------------------------------------\n\n /**\n * Returns the cell address (e.g., \"A1\").\n */\n get address(): string {\n return this.cell.address\n }\n\n /**\n * Returns the 1-based row number.\n */\n get row(): number {\n return typeof this.cell.row === 'number'\n ? this.cell.row\n : parseInt(String(this.cell.row), 10)\n }\n\n /**\n * Returns the 1-based column number.\n */\n get col(): number {\n return typeof this.cell.col === 'number'\n ? this.cell.col\n : parseInt(String(this.cell.col), 10)\n }\n\n /**\n * Returns the column letter(s) (e.g., \"A\", \"AA\").\n */\n get colLetter(): string {\n return this.address.replace(/\\d+$/, '')\n }\n\n /**\n * Returns the current path for lineage tracking.\n */\n get path(): XlsxPath {\n return this._path\n }\n\n /**\n * Returns the sheet name this cell belongs to.\n */\n get sheetName(): string {\n return this._sheetName\n }\n\n // ---------------------------------------------------------------------------\n // VALUE EXTRACTION\n // ---------------------------------------------------------------------------\n\n /**\n * Returns the raw cell value.\n */\n value(): XlsxResult<CellValue> {\n const val = this.getRawValue()\n if (isFormula(val)) {\n return ok(val.result ?? null, this._path)\n }\n if (isError(val)) {\n return fail('formula', `Cell contains error: ${val.error}`, this._path)\n }\n // At this point val is CellValue (not formula or error)\n return ok(val as CellValue, this._path)\n }\n\n /**\n * Returns the extended cell value (including formula info).\n */\n extendedValue(): XlsxResult<ExtendedCellValue> {\n return ok(this.getRawValue(), this._path)\n }\n\n /**\n * Extract value as a string.\n */\n string(): XlsxResult<string> {\n const val = this.getResolvedValue()\n if (val === null || val === undefined) {\n return fail('type', 'Expected string, got null', this._path)\n }\n if (typeof val === 'string') {\n return ok(val, this._path)\n }\n // Convert to string\n if (typeof val === 'number' || typeof val === 'boolean') {\n return ok(String(val), this._path)\n }\n if (val instanceof Date) {\n return ok(val.toISOString(), this._path)\n }\n return fail('type', `Expected string, got ${typeof val}`, this._path)\n }\n\n /**\n * Extract value as a number.\n */\n number(): XlsxResult<number> {\n const val = this.getResolvedValue()\n if (typeof val === 'number') {\n return ok(val, this._path)\n }\n if (typeof val === 'string') {\n const num = parseFloat(val)\n if (!isNaN(num)) {\n return ok(num, this._path)\n }\n }\n return fail('type', `Expected number, got ${typeOf(val)}`, this._path)\n }\n\n /**\n * Extract value as a boolean.\n */\n boolean(): XlsxResult<boolean> {\n const val = this.getResolvedValue()\n if (typeof val === 'boolean') {\n return ok(val, this._path)\n }\n return fail('type', `Expected boolean, got ${typeOf(val)}`, this._path)\n }\n\n /**\n * Extract value as a Date.\n */\n date(): XlsxResult<Date> {\n const val = this.getResolvedValue()\n if (val instanceof Date) {\n return ok(val, this._path)\n }\n if (typeof val === 'number') {\n // Excel stores dates as numbers (days since 1900-01-01)\n const date = this.excelDateToJS(val)\n return ok(date, this._path)\n }\n if (typeof val === 'string') {\n const date = new Date(val)\n if (!isNaN(date.getTime())) {\n return ok(date, this._path)\n }\n }\n return fail('type', `Expected date, got ${typeOf(val)}`, this._path)\n }\n\n /**\n * Get the formula if this cell contains one.\n */\n formula(): XlsxResult<string> {\n const val = this.getRawValue()\n if (isFormula(val)) {\n return ok(val.formula, this._path)\n }\n return fail('type', 'Cell does not contain a formula', this._path)\n }\n\n // ---------------------------------------------------------------------------\n // RICH TEXT & MARKDOWN\n // ---------------------------------------------------------------------------\n\n /**\n * Get the cell content as rich text with formatting preserved.\n * Returns segments with their individual formatting properties.\n */\n richText(): XlsxResult<RichTextContent> {\n const rawVal = this.cell.value as ExcelJSValue\n const hyperlink = this.cell.hyperlink\n\n // Handle rich text cells\n if (rawVal && typeof rawVal === 'object' && 'richText' in rawVal) {\n const rt = rawVal as {\n richText: Array<{\n text: string\n font?: {\n bold?: boolean\n italic?: boolean\n underline?: boolean | string\n strike?: boolean\n color?: { argb?: string; theme?: number }\n size?: number\n name?: string\n }\n }>\n }\n\n const segments: RichTextSegment[] = rt.richText.map(segment => ({\n text: segment.text,\n bold: segment.font?.bold,\n italic: segment.font?.italic,\n underline:\n segment.font?.underline === true ||\n segment.font?.underline === 'single',\n strikethrough: segment.font?.strike,\n color: segment.font?.color?.argb,\n size: segment.font?.size,\n font: segment.font?.name,\n }))\n\n return ok({ segments, hyperlink }, this._path)\n }\n\n // Handle hyperlink with text\n if (\n rawVal &&\n typeof rawVal === 'object' &&\n 'text' in rawVal &&\n 'hyperlink' in rawVal\n ) {\n const linkVal = rawVal as { text: string; hyperlink: string }\n const style = this.style()\n const segment: RichTextSegment = {\n text: linkVal.text,\n bold: style.font?.bold,\n italic: style.font?.italic,\n underline: style.font?.underline,\n strikethrough: style.font?.strikethrough,\n color: style.font?.color,\n size: style.font?.size,\n font: style.font?.name,\n }\n return ok(\n {\n segments: [segment],\n hyperlink: linkVal.hyperlink,\n },\n this._path\n )\n }\n\n // Plain value - wrap in single segment with cell-level formatting\n const plainValue = this.getResolvedValue()\n const text = plainValue !== null ? String(plainValue) : ''\n const style = this.style()\n\n const segment: RichTextSegment = {\n text,\n bold: style.font?.bold,\n italic: style.font?.italic,\n underline: style.font?.underline,\n strikethrough: style.font?.strikethrough,\n color: style.font?.color,\n size: style.font?.size,\n font: style.font?.name,\n }\n\n return ok({ segments: [segment], hyperlink }, this._path)\n }\n\n /**\n * Get the cell content as Markdown.\n *\n * Converts cell content including:\n * - Bold text -> **text**\n * - Italic text -> *text*\n * - Strikethrough -> ~~text~~\n * - Hyperlinks -> [text](url)\n * - Rich text segments with mixed formatting\n */\n markdown(): XlsxResult<string> {\n const rtResult = this.richText()\n if (!rtResult.ok) {\n return rtResult as XlsxResult<string>\n }\n\n const { segments, hyperlink } = rtResult.value\n let result = ''\n\n for (const segment of segments) {\n let text = segment.text\n\n // Apply formatting in order: strikethrough, then bold, then italic\n if (segment.strikethrough) {\n text = `~~${text}~~`\n }\n if (segment.bold) {\n text = `**${text}**`\n }\n if (segment.italic) {\n text = `*${text}*`\n }\n\n result += text\n }\n\n // Wrap in hyperlink if present\n if (hyperlink) {\n result = `[${result}](${hyperlink})`\n }\n\n return ok(result, this._path)\n }\n\n /**\n * Check if the cell contains rich text (multiple formatted segments).\n */\n isRichText(): boolean {\n const rawVal = this.cell.value as ExcelJSValue\n return rawVal !== null && typeof rawVal === 'object' && 'richText' in rawVal\n }\n\n // ---------------------------------------------------------------------------\n // TYPE CHECKING\n // ---------------------------------------------------------------------------\n\n /**\n * Check if the cell is empty.\n */\n isEmpty(): boolean {\n const val = this.cell.value\n return val === null || val === undefined || val === ''\n }\n\n /**\n * Check if the cell contains a formula.\n */\n isFormula(): boolean {\n return isFormula(this.getRawValue())\n }\n\n /**\n * Check if the cell is part of a merged range.\n */\n isMerged(): boolean {\n return this.cell.isMerged\n }\n\n /**\n * Check if this is the master cell of a merged range.\n */\n isMergedMaster(): boolean {\n if (!this.cell.isMerged) return false\n const master = this.cell.master\n return master.address === this.cell.address\n }\n\n /**\n * Check if the cell contains a string.\n */\n isString(): boolean {\n return typeof this.getResolvedValue() === 'string'\n }\n\n /**\n * Check if the cell contains a number.\n */\n isNumber(): boolean {\n return typeof this.getResolvedValue() === 'number'\n }\n\n /**\n * Check if the cell contains a boolean.\n */\n isBoolean(): boolean {\n return typeof this.getResolvedValue() === 'boolean'\n }\n\n /**\n * Check if the cell contains a date.\n */\n isDate(): boolean {\n const val = this.getResolvedValue()\n return val instanceof Date\n }\n\n /**\n * Check if the cell contains an error.\n */\n isError(): boolean {\n return isError(this.getRawValue())\n }\n\n // ---------------------------------------------------------------------------\n // METADATA\n // ---------------------------------------------------------------------------\n\n /**\n * Get the cell's style information.\n */\n style(): CellStyle {\n const font = this.cell.font\n const fill = this.cell.fill\n const border = this.cell.border\n const alignment = this.cell.alignment\n\n return {\n font: font\n ? {\n name: font.name,\n size: font.size,\n bold: font.bold,\n italic: font.italic,\n underline: font.underline === true || font.underline === 'single',\n strikethrough: font.strike,\n color:\n font.color?.argb ??\n (font.color?.theme !== undefined\n ? `theme:${font.color.theme}`\n : undefined),\n }\n : undefined,\n fill:\n fill && fill.type === 'pattern'\n ? {\n type: (fill as { pattern?: string }).pattern,\n color: (fill as { fgColor?: { argb?: string } }).fgColor?.argb,\n }\n : undefined,\n border: border\n ? {\n top: !!border.top,\n bottom: !!border.bottom,\n left: !!border.left,\n right: !!border.right,\n }\n : undefined,\n alignment: alignment\n ? {\n horizontal: alignment.horizontal,\n vertical: alignment.vertical,\n wrapText: alignment.wrapText,\n }\n : undefined,\n numFmt: this.cell.numFmt,\n }\n }\n\n /**\n * Get the hyperlink URL if the cell contains one.\n */\n hyperlink(): XlsxResult<string> {\n const link = this.cell.hyperlink\n if (!link) {\n return fail('missing', 'Cell does not contain a hyperlink', this._path)\n }\n return ok(link, this._path)\n }\n\n /**\n * Get the comment/note if the cell has one.\n */\n comment(): XlsxResult<string> {\n const note = this.cell.note\n if (!note) {\n return fail('missing', 'Cell does not contain a comment', this._path)\n }\n if (typeof note === 'string') {\n return ok(note, this._path)\n }\n // RichText note\n if (note.texts) {\n return ok(\n note.texts.map((t: { text: string }) => t.text).join(''),\n this._path\n )\n }\n return fail('format', 'Unable to extract comment text', this._path)\n }\n\n // ---------------------------------------------------------------------------\n // NAVIGATION FROM CELL\n // ---------------------------------------------------------------------------\n\n /**\n * Get a cell offset from this one.\n * @internal Used by navigation methods\n */\n getOffsetCell(\n rowDelta: number,\n colDelta: number,\n getCell: (row: number, col: number) => XlsxCell | undefined\n ): XlsxResult<XlsxCell> {\n const newRow = this.row + rowDelta\n const newCol = this.col + colDelta\n if (newRow < 1 || newCol < 1) {\n return fail(\n 'bounds',\n `Cell offset (${rowDelta}, ${colDelta}) from ${this.address} is out of bounds`,\n this._path\n )\n }\n const cell = getCell(newRow, newCol)\n if (!cell) {\n return fail(\n 'missing',\n `Cell at ${formatAddress(newRow, newCol)} not found`,\n this._path\n )\n }\n return ok(cell, cell.path)\n }\n\n // ---------------------------------------------------------------------------\n // INTERNAL HELPERS\n // ---------------------------------------------------------------------------\n\n /**\n * Get the raw value, handling ExcelJS value types.\n */\n private getRawValue(): ExtendedCellValue {\n const val = this.cell.value as ExcelJSValue\n if (val === null || val === undefined) {\n return null\n }\n\n // Handle different ExcelJS value types\n if (typeof val === 'object') {\n // Error value\n if ('error' in val) {\n return { error: String((val as { error: unknown }).error) }\n }\n // Formula value\n if ('formula' in val) {\n const formulaVal = val as {\n formula: string\n result?: ExcelJSValue\n }\n return {\n formula: formulaVal.formula,\n result: this.normalizeResult(formulaVal.result),\n }\n }\n // Shared formula\n if ('sharedFormula' in val) {\n const sharedVal = val as {\n sharedFormula: string\n result?: ExcelJSValue\n }\n return {\n formula: sharedVal.sharedFormula,\n result: this.normalizeResult(sharedVal.result),\n }\n }\n // Rich text\n if ('richText' in val) {\n const richText = val as {\n richText: Array<{ text: string }>\n }\n return richText.richText.map(r => r.text).join('')\n }\n // Date\n if (val instanceof Date) {\n return val\n }\n }\n\n // Primitive values\n if (\n typeof val === 'string' ||\n typeof val === 'number' ||\n typeof val === 'boolean'\n ) {\n return val\n }\n\n return null\n }\n\n /**\n * Get the resolved value (formula result or plain value).\n */\n private getResolvedValue(): CellValue {\n const val = this.getRawValue()\n if (isFormula(val)) {\n return val.result ?? null\n }\n if (isError(val)) {\n return null\n }\n // At this point val is CellValue (not formula or error)\n return val as CellValue\n }\n\n /**\n * Normalize a formula result value.\n */\n private normalizeResult(result: unknown): CellValue {\n if (result === null || result === undefined) return null\n if (\n typeof result === 'string' ||\n typeof result === 'number' ||\n typeof result === 'boolean'\n ) {\n return result\n }\n if (result instanceof Date) {\n return result\n }\n return null\n }\n\n /**\n * Convert Excel date number to JavaScript Date.\n * Excel dates are days since 1900-01-01 (with a leap year bug).\n */\n private excelDateToJS(excelDate: number): Date {\n // Excel incorrectly treats 1900 as a leap year\n // Dates before March 1, 1900 need adjustment\n const offset = excelDate > 60 ? -1 : 0\n const days = excelDate + offset - 1\n\n // Excel epoch is 1900-01-01\n const excelEpoch = new Date(1900, 0, 1)\n const jsDate = new Date(excelEpoch.getTime() + days * 24 * 60 * 60 * 1000)\n\n return jsDate\n }\n}\n\n/**\n * Returns a human-readable type name.\n */\nfunction typeOf(value: unknown): string {\n if (value === null) return 'null'\n if (value === undefined) return 'undefined'\n if (value instanceof Date) return 'date'\n if (Array.isArray(value)) return 'array'\n return typeof value\n}\n","/**\n * XlsxRange - represents a range of cells with iteration and query capabilities.\n *\n * @module xlsx/xlsx-range\n */\n\nimport { TYPE_LABEL } from '@origints/core'\nimport type { Worksheet } from 'exceljs'\nimport { XlsxCell } from './xlsx-cell'\nimport { XlsxResult, XlsxPath, CellValue, ok, fail } from './xlsx-result'\nimport { formatRange, parseRange } from './util'\nimport type { CellPredicate } from './xlsx-query'\n\n/**\n * A range of cells in an XLSX sheet.\n *\n * XlsxRange enables iteration over cells, rows, and columns within\n * a defined rectangular region. It supports predicate-based queries\n * and conversion to various formats.\n */\nexport class XlsxRange {\n get [TYPE_LABEL]() {\n return `XlsxRange(${this.address})`\n }\n\n private constructor(\n private readonly worksheet: Worksheet,\n private readonly _startRow: number,\n private readonly _startCol: number,\n private readonly _endRow: number,\n private readonly _endCol: number,\n private readonly _path: XlsxPath,\n private readonly _sheetName: string,\n private readonly _file?: string\n ) {}\n\n /**\n * Creates an XlsxRange from coordinates.\n * @internal\n */\n static fromCoords(\n worksheet: Worksheet,\n startRow: number,\n startCol: number,\n endRow: number,\n endCol: number,\n sheetName: string,\n file?: string\n ): XlsxRange {\n const rangeAddr = formatRange(startRow, startCol, endRow, endCol)\n const path: XlsxPath = {\n file,\n sheet: sheetName,\n range: rangeAddr,\n }\n return new XlsxRange(\n worksheet,\n startRow,\n startCol,\n endRow,\n endCol,\n path,\n sheetName,\n file\n )\n }\n\n /**\n * Creates an XlsxRange from an address string.\n * @internal\n */\n static fromAddress(\n worksheet: Worksheet,\n address: string,\n sheetName: string,\n file?: string\n ): XlsxResult<XlsxRange> {\n try {\n const { start, end } = parseRange(address)\n return ok(\n XlsxRange.fromCoords(\n worksheet,\n start.row,\n start.col,\n end.row,\n end.col,\n sheetName,\n file\n ),\n { file, sheet: sheetName, range: address }\n )\n } catch {\n return fail('range', `Invalid range address: ${address}`, {\n file,\n sheet: sheetName,\n })\n }\n }\n\n // ---------------------------------------------------------------------------\n // IDENTITY\n // ---------------------------------------------------------------------------\n\n /**\n * Returns the range address (e.g., \"A1:C10\").\n */\n get address(): string {\n return formatRange(\n this._startRow,\n this._startCol,\n this._endRow,\n this._endCol\n )\n }\n\n /**\n * Returns the start row (1-based).\n */\n get startRow(): number {\n return this._startRow\n }\n\n /**\n * Returns the start column (1-based).\n */\n get startCol(): number {\n return this._startCol\n }\n\n /**\n * Returns the end row (1-based).\n */\n get endRow(): number {\n return this._endRow\n }\n\n /**\n * Returns the end column (1-based).\n */\n get endCol(): number {\n return this._endCol\n }\n\n /**\n * Returns the current path for lineage tracking.\n */\n get path(): XlsxPath {\n return this._path\n }\n\n /**\n * Returns the number of rows in the range.\n */\n get rowCount(): number {\n return this._endRow - this._startRow + 1\n }\n\n /**\n * Returns the number of columns in the range.\n */\n get colCount(): number {\n return this._endCol - this._startCol + 1\n }\n\n /**\n * Returns the total number of cells in the range.\n */\n get cellCount(): number {\n return this.rowCount * this.colCount\n }\n\n // ---------------------------------------------------------------------------\n // CELL ACCESS\n // ---------------------------------------------------------------------------\n\n /**\n * Get a cell at specific row and column within this range.\n * Coordinates are relative to the range start (0-indexed).\n */\n cellAt(rowOffset: number, colOffset: number): XlsxResult<XlsxCell> {\n const row = this._startRow + rowOffset\n const col = this._startCol + colOffset\n if (\n row < this._startRow ||\n row > this._endRow ||\n col < this._startCol ||\n col > this._endCol\n ) {\n return fail(\n 'bounds',\n `Offset (${rowOffset}, ${colOffset}) is outside range ${this.address}`,\n this._path\n )\n }\n const cell = this.worksheet.getCell(row, col)\n return ok(XlsxCell.fromExcelJS(cell, this._sheetName, this._file), {\n ...this._path,\n cell: cell.address,\n range: undefined,\n })\n }\n\n /**\n * Get a cell by its address within this range.\n */\n cell(address: string): XlsxResult<XlsxCell> {\n try {\n const { start } = parseRange(address)\n if (\n start.row < this._startRow ||\n start.row > this._endRow ||\n start.col < this._startCol ||\n start.col > this._endCol\n ) {\n return fail(\n 'bounds',\n `Cell ${address} is outside range ${this.address}`,\n this._path\n )\n }\n const cell = this.worksheet.getCell(address)\n return ok(XlsxCell.fromExcelJS(cell, this._sheetName, this._file), {\n ...this._path,\n cell: address,\n range: undefined,\n })\n } catch {\n return fail('range', `Invalid cell address: ${address}`, this._path)\n }\n }\n\n // ---------------------------------------------------------------------------\n // ITERATION\n // ---------------------------------------------------------------------------\n\n /**\n * Iterate over all cells in the range (row by row).\n */\n *cells(): Iterable<XlsxCell> {\n for (let row = this._startRow; row <= this._endRow; row++) {\n for (let col = this._startCol; col <= this._endCol; col++) {\n const cell = this.worksheet.getCell(row, col)\n yield XlsxCell.fromExcelJS(cell, this._sheetName, this._file)\n }\n }\n }\n\n /**\n * Iterate over rows, returning arrays of cells.\n */\n *rows(): Iterable<XlsxCell[]> {\n for (let row = this._startRow; row <= this._endRow; row++) {\n const rowCells: XlsxCell[] = []\n for (let col = this._startCol; col <= this._endCol; col++) {\n const cell = this.worksheet.getCell(row, col)\n rowCells.push(XlsxCell.fromExcelJS(cell, this._sheetName, this._file))\n }\n yield rowCells\n }\n }\n\n /**\n * Iterate over columns, returning arrays of cells.\n */\n *cols(): Iterable<XlsxCell[]> {\n for (let col = this._startCol; col <= this._endCol; col++) {\n const colCells: XlsxCell[] = []\n for (let row = this._startRow; row <= this._endRow; row++) {\n const cell = this.worksheet.getCell(row, col)\n colCells.push(XlsxCell.fromExcelJS(cell, this._sheetName, this._file))\n }\n yield colCells\n }\n }\n\n /**\n * Get all values in the range as a 2D array.\n */\n values(): CellValue[][] {\n const result: CellValue[][] = []\n for (const rowCells of this.rows()) {\n const rowValues: CellValue[] = []\n for (const cell of rowCells) {\n const val = cell.value()\n rowValues.push(val.ok ? val.value : null)\n }\n result.push(rowValues)\n }\n return result\n }\n\n /**\n * Get all cells as a flat array.\n */\n cellsArray(): XlsxCell[] {\n return [...this.cells()]\n }\n\n // ---------------------------------------------------------------------------\n // SUBRANGE\n // ---------------------------------------------------------------------------\n\n /**\n * Get a subrange within this range.\n */\n subRange(address: string): XlsxResult<XlsxRange> {\n try {\n const { start, end } = parseRange(address)\n if (\n start.row < this._startRow ||\n end.row > this._endRow ||\n start.col < this._startCol ||\n end.col > this._endCol\n ) {\n return fail(\n 'bounds',\n `Subrange ${address} extends outside range ${this.address}`,\n this._path\n )\n }\n return ok(\n XlsxRange.fromCoords(\n this.worksheet,\n start.row,\n start.col,\n end.row,\n end.col,\n this._sheetName,\n this._file\n ),\n { ...this._path, range: address }\n )\n } catch {\n return fail('range', `Invalid range address: ${address}`, this._path)\n }\n }\n\n /**\n * Get the first row as a range.\n */\n firstRow(): XlsxRange {\n return XlsxRange.fromCoords(\n this.worksheet,\n this._startRow,\n this._startCol,\n this._startRow,\n this._endCol,\n this._sheetName,\n this._file\n )\n }\n\n /**\n * Get the last row as a range.\n */\n lastRow(): XlsxRange {\n return XlsxRange.fromCoords(\n this.worksheet,\n this._endRow,\n this._startCol,\n this._endRow,\n this._endCol,\n this._sheetName,\n this._file\n )\n }\n\n /**\n * Get the first column as a range.\n */\n firstCol(): XlsxRange {\n return XlsxRange.fromCoords(\n this.worksheet,\n this._startRow,\n this._startCol,\n this._endRow,\n this._startCol,\n this._sheetName,\n this._file\n )\n }\n\n /**\n * Get the last column as a range.\n */\n lastCol(): XlsxRange {\n return XlsxRange.fromCoords(\n this.worksheet,\n this._startRow,\n this._endCol,\n this._endRow,\n this._endCol,\n this._sheetName,\n this._file\n )\n }\n\n /**\n * Get a specific row as a range (0-indexed offset from start).\n */\n rowAt(offset: number): XlsxResult<XlsxRange> {\n const row = this._startRow + offset\n if (row < this._startRow || row > this._endRow) {\n return fail(\n 'bounds',\n `Row offset ${offset} is outside range ${this.address}`,\n this._path\n )\n }\n return ok(\n XlsxRange.fromCoords(\n this.worksheet,\n row,\n this._startCol,\n row,\n this._endCol,\n this._sheetName,\n this._file\n ),\n this._path\n )\n }\n\n /**\n * Get a specific column as a range (0-indexed offset from start).\n */\n colAt(offset: number): XlsxResult<XlsxRange> {\n const col = this._startCol + offset\n if (col < this._startCol || col > this._endCol) {\n return fail(\n 'bounds',\n `Column offset ${offset} is outside range ${this.address}`,\n this._path\n )\n }\n return ok(\n XlsxRange.fromCoords(\n this.worksheet,\n this._startRow,\n col,\n this._endRow,\n col,\n this._sheetName,\n this._file\n ),\n this._path\n )\n }\n\n // ---------------------------------------------------------------------------\n // QUERY\n // ---------------------------------------------------------------------------\n\n /**\n * Find the first cell matching the predicate.\n */\n find(predicate: CellPredicate): XlsxResult<XlsxCell> {\n for (const cell of this.cells()) {\n if (predicate(cell)) {\n return ok(cell, cell.path)\n }\n }\n return fail(\n 'missing',\n `No cell matching predicate found in range ${this.address}`,\n this._path\n )\n }\n\n /**\n * Find all cells matching the predicate.\n */\n findAll(predicate: CellPredicate): XlsxCell[] {\n const results: XlsxCell[] = []\n for (const cell of this.cells()) {\n if (predicate(cell)) {\n results.push(cell)\n }\n }\n return results\n }\n\n /**\n * Find the first cell with the specified value.\n */\n findValue(value: CellValue): XlsxResult<XlsxCell> {\n for (const cell of this.cells()) {\n const cellVal = cell.value()\n if (cellVal.ok && cellVal.value === value) {\n return ok(cell, cell.path)\n }\n }\n return fail(\n 'missing',\n `Value \"${value}\" not found in range ${this.address}`,\n this._path\n )\n }\n\n /**\n * Check if any cell matches the predicate.\n */\n some(predicate: CellPredicate): boolean {\n for (const cell of this.cells()) {\n if (predicate(cell)) {\n return true\n }\n }\n return false\n }\n\n /**\n * Check if all cells match the predicate.\n */\n every(predicate: CellPredicate): boolean {\n for (const cell of this.cells()) {\n if (!predicate(cell)) {\n return false\n }\n }\n return true\n }\n\n /**\n * Count cells matching the predicate.\n */\n count(predicate: CellPredicate): number {\n let count = 0\n for (const cell of this.cells()) {\n if (predicate(cell)) {\n count++\n }\n }\n return count\n }\n\n // ---------------------------------------------------------------------------\n // CONVERSION\n // ---------------------------------------------------------------------------\n\n /**\n * Convert range to a 2D array of values.\n */\n toArray(): CellValue[][] {\n return this.values()\n }\n\n /**\n * Convert range to array of objects using a header row.\n * @param headerRowOffset - Row offset for headers (default: 0, first row)\n * @param dataStartOffset - Row offset where data starts (default: 1, second row)\n */\n toObjects(\n headerRowOffset: number = 0,\n dataStartOffset: number = 1\n ): Record<string, CellValue>[] {\n const allRows = [...this.rows()]\n if (allRows.length === 0) return []\n\n // Get headers from the specified row\n const headerRow = allRows[headerRowOffset]\n if (!headerRow) return []\n\n const headers: string[] = headerRow.map(cell => {\n const val = cell.value()\n return val.ok && val.value !== null ? String(val.value) : ''\n })\n\n // Convert data rows to objects\n const result: Record<string, CellValue>[] = []\n for (let i = dataStartOffset; i < allRows.length; i++) {\n const row = allRows[i]\n const obj: Record<string, CellValue> = {}\n for (let j = 0; j < headers.length; j++) {\n const header = headers[j]\n if (header) {\n const cell = row[j]\n const val = cell?.value()\n obj[header] = val?.ok ? val.value : null\n }\n }\n result.push(obj)\n }\n return result\n }\n\n /**\n * Convert range to JSON-compatible structure.\n */\n toJson(): {\n address: string\n rows: Array<Array<CellValue>>\n } {\n return {\n address: this.address,\n rows: this.values(),\n }\n }\n}\n","/**\n * XlsxCursor - immutable cursor for navigating through cells.\n *\n * @module xlsx/xlsx-cursor\n */\n\nimport { TYPE_LABEL } from '@origints/core'\nimport type { XlsxSheet } from './xlsx-sheet'\nimport { XlsxCell } from './xlsx-cell'\nimport { XlsxResult, XlsxPath, ok, fail } from './xlsx-result'\nimport {\n parseAddress,\n formatAddress,\n columnLetterToNumber,\n columnNumberToLetter,\n} from './util'\nimport type { CellPredicate } from './xlsx-query'\n\n/**\n * Direction for cursor movement.\n */\nexport type CursorDirection = 'right' | 'left' | 'down' | 'up'\n\n/**\n * Result of a grab operation.\n */\nexport interface GrabResult {\n readonly cells: XlsxCell[]\n readonly cursor: XlsxCursor\n}\n\n/**\n * Result of a single grab operation.\n */\nexport interface GrabOneResult {\n readonly cell: XlsxCell\n readonly cursor: XlsxCursor\n}\n\n/**\n * An immutable cursor for navigating through cells in a sheet.\n *\n * XlsxCursor provides a fluent API for moving through cells,\n * skipping cells based on predicates, and grabbing sequences\n * of cells. Each operation returns a new cursor, maintaining\n * immutability.\n */\nexport class XlsxCursor {\n get [TYPE_LABEL]() {\n return `XlsxCursor(${this.address} ${this._direction})`\n }\n\n private constructor(\n private readonly sheet: XlsxSheet,\n private readonly _row: number,\n private readonly _col: number,\n private readonly _direction: CursorDirection = 'right'\n ) {}\n\n /**\n * Create a cursor from an address string.\n * @internal\n */\n static create(sheet: XlsxSheet, address: string): XlsxCursor {\n const { row, col } = parseAddress(address)\n return new XlsxCursor(sheet, row, col)\n }\n\n /**\n * Create a cursor from row and column coordinates.\n * @internal\n */\n static createAt(sheet: XlsxSheet, row: number, col: number): XlsxCursor {\n return new XlsxCursor(sheet, Math.max(1, row), Math.max(1, col))\n }\n\n // ---------------------------------------------------------------------------\n // POSITION\n // ---------------------------------------------------------------------------\n\n /**\n * Get the current row (1-based).\n */\n get row(): number {\n return this._row\n }\n\n /**\n * Get the current column (1-based).\n */\n get col(): number {\n return this._col\n }\n\n /**\n * Get the current address.\n */\n get address(): string {\n return formatAddress(this._row, this._col)\n }\n\n /**\n * Get the current column letter.\n */\n get colLetter(): string {\n return columnNumberToLetter(this._col)\n }\n\n /**\n * Get the current direction.\n */\n get direction(): CursorDirection {\n return this._direction\n }\n\n /**\n * Get the path for lineage tracking.\n */\n get path(): XlsxPath {\n return {\n ...this.sheet.path,\n cell: this.address,\n }\n }\n\n // ---------------------------------------------------------------------------\n // MOVEMENT\n // ---------------------------------------------------------------------------\n\n /**\n * Move by a delta (returns new cursor).\n */\n move(rowDelta: number, colDelta: number): XlsxCursor {\n return new XlsxCursor(\n this.sheet,\n Math.max(1, this._row + rowDelta),\n Math.max(1, this._col + colDelta),\n this._direction\n )\n }\n\n /**\n * Move to a specific address.\n */\n moveTo(address: string): XlsxCursor {\n const { row, col } = parseAddress(address)\n return new XlsxCursor(this.sheet, row, col, this._direction)\n }\n\n /**\n * Move to a specific row.\n */\n moveToRow(row: number): XlsxCursor {\n return new XlsxCursor(\n this.sheet,\n Math.max(1, row),\n this._col,\n this._direction\n )\n }\n\n /**\n * Move to a specific column.\n */\n moveToCol(col: number | string): XlsxCursor {\n const colNum =\n typeof col === 'string' ? columnLetterToNumber(col.toUpperCase()) : col\n return new XlsxCursor(\n this.sheet,\n this._row,\n Math.max(1, colNum),\n this._direction\n )\n }\n\n /**\n * Move left by count cells.\n */\n left(count: number = 1): XlsxCursor {\n return new XlsxCursor(\n this.sheet,\n this._row,\n Math.max(1, this._col - count),\n 'left'\n )\n }\n\n /**\n * Move right by count cells.\n */\n right(count: number = 1): XlsxCursor {\n return new XlsxCursor(this.sheet, this._row, this._col + count, 'right')\n }\n\n /**\n * Move up by count cells.\n */\n up(count: number = 1): XlsxCursor {\n return new XlsxCursor(\n this.sheet,\n Math.max(1, this._row - count),\n this._col,\n 'up'\n )\n }\n\n /**\n * Move down by count cells.\n */\n down(count: number = 1): XlsxCursor {\n return new XlsxCursor(this.sheet, this._row + count, this._col, 'down')\n }\n\n /**\n * Set the current direction.\n */\n setDirection(direction: CursorDirection): XlsxCursor {\n return new XlsxCursor(this.sheet, this._row, this._col, direction)\n }\n\n /**\n * Move forward in the current direction.\n */\n forward(count: number = 1): XlsxCursor {\n switch (this._direction) {\n case 'right':\n return this.right(count)\n case 'left':\n return this.left(count)\n case 'down':\n return this.down(count)\n case 'up':\n return this.up(count)\n }\n }\n\n /**\n * Move to the start of the current row.\n */\n startOfRow(): XlsxCursor {\n return new XlsxCursor(this.sheet, this._row, 1, this._direction)\n }\n\n /**\n * Move to the start of the current column.\n */\n startOfCol(): XlsxCursor {\n return new XlsxCursor(this.sheet, 1, this._col, this._direction)\n }\n\n // ---------------------------------------------------------------------------\n // SKIP OPERATIONS\n // ---------------------------------------------------------------------------\n\n /**\n * Skip empty cells in the current direction.\n */\n skipEmpty(): XlsxCursor {\n return this.skipWhile(cell => cell.isEmpty())\n }\n\n /**\n * Skip cells while the predicate is true.\n */\n skipWhile(predicate: CellPredicate): XlsxCursor {\n // eslint-disable-next-line @typescript-eslint/no-this-alias\n let cursor: XlsxCursor = this\n const dims = this.sheet.dimensions()\n const maxIterations = Math.max(dims.rowCount, dims.colCount) * 2\n\n for (let i = 0; i < maxIterations; i++) {\n const cellResult = cursor.cell()\n if (!cellResult.ok) break\n if (!predicate(cellResult.value)) break\n cursor = cursor.forward()\n }\n return cursor\n }\n\n /**\n * Skip cells until the predicate is true.\n */\n skipUntil(predicate: CellPredicate): XlsxCursor {\n return this.skipWhile(cell => !predicate(cell))\n }\n\n /**\n * Skip cells until a specific value is found.\n */\n skipToValue(value: unknown): XlsxCursor {\n return this.skipUntil(cell => {\n const val = cell.value()\n return val.ok && val.value === value\n })\n }\n\n /**\n * Skip a specific number of cells.\n */\n skip(count: number): XlsxCursor {\n return this.forward(count)\n }\n\n // ---------------------------------------------------------------------------\n // GRAB OPERATIONS\n // ---------------------------------------------------------------------------\n\n /**\n * Grab the current cell and move forward.\n */\n grab(): XlsxResult<GrabOneResult> {\n const cellResult = this.cell()\n if (!cellResult.ok) return cellResult\n return ok(\n {\n cell: cellResult.value,\n cursor: this.forward(),\n },\n this.path\n )\n }\n\n /**\n * Grab n cells in the current direction.\n */\n grabN(count: number): XlsxResult<GrabResult> {\n const cells: XlsxCell[] = []\n // eslint-disable-next-line @typescript-eslint/no-this-alias\n let cursor: XlsxCursor = this\n\n for (let i = 0; i < count; i++) {\n const cellResult = cursor.cell()\n if (!cellResult.ok) {\n // Return what we have so far\n break\n }\n cells.push(cellResult.value)\n cursor = cursor.forward()\n }\n\n if (cells.length === 0) {\n return fail('bounds', 'No cells to grab', this.path)\n }\n\n return ok({ cells, cursor }, this.path)\n }\n\n /**\n * Grab cells while the predicate is true.\n */\n grabWhile(predicate: CellPredicate): XlsxResult<GrabResult> {\n const cells: XlsxCell[] = []\n // eslint-disable-next-line @typescript-eslint/no-this-alias\n let cursor: XlsxCursor = this\n const dims = this.sheet.dimensions()\n const maxIterations = Math.max(dims.rowCount, dims.colCount) * 2\n\n for (let i = 0; i < maxIterations; i++) {\n const cellResult = cursor.cell()\n if (!cellResult.ok) break\n if (!predicate(cellResult.value)) break\n cells.push(cellResult.value)\n cursor = cursor.forward()\n }\n\n return ok({ cells, cursor }, this.path)\n }\n\n /**\n * Grab cells until the predicate is true (not including the matching cell).\n */\n grabUntil(predicate: CellPredicate): XlsxResult<GrabResult> {\n return this.grabWhile(cell => !predicate(cell))\n }\n\n /**\n * Grab the rest of the current row.\n */\n grabRow(): XlsxResult<GrabResult> {\n const cells: XlsxCell[] = []\n const dims = this.sheet.dimensions()\n let cursor = this.setDirection('right')\n\n for (let col = this._col; col <= dims.endCol; col++) {\n const cellResult = cursor.cell()\n if (!cellResult.ok) break\n cells.push(cellResult.value)\n cursor = cursor.forward()\n }\n\n return ok({ cells, cursor }, this.path)\n }\n\n /**\n * Grab the rest of the current column.\n */\n grabCol(): XlsxResult<GrabResult> {\n const cells: XlsxCell[] = []\n const dims = this.sheet.dimensions()\n let cursor = this.setDirection('down')\n\n for (let row = this._row; row <= dims.endRow; row++) {\n const cellResult = cursor.cell()\n if (!cellResult.ok) break\n cells.push(cellResult.value)\n cursor = cursor.forward()\n }\n\n return ok({ cells, cursor }, this.path)\n }\n\n /**\n * Grab non-empty cells in the current direction.\n */\n grabNonEmpty(): XlsxResult<GrabResult> {\n return this.grabWhile(cell => !cell.isEmpty())\n }\n\n // ---------------------------------------------------------------------------\n // PEEK OPERATIONS\n // ---------------------------------------------------------------------------\n\n /**\n * Peek at the current cell without moving.\n */\n peek(): XlsxResult<XlsxCell> {\n return this.cell()\n }\n\n /**\n * Peek at cells ahead without moving.\n */\n peekAhead(count: number): XlsxResult<XlsxCell[]> {\n const cells: XlsxCell[] = []\n // eslint-disable-next-line @typescript-eslint/no-this-alias\n let cursor: XlsxCursor = this\n\n for (let i = 0; i < count; i++) {\n const cellResult = cursor.cell()\n if (!cellResult.ok) break\n cells.push(cellResult.value)\n cursor = cursor.forward()\n }\n\n return ok(cells, this.path)\n }\n\n /**\n * Peek at a cell at an offset without moving.\n */\n peekAt(rowDelta: number, colDelta: number): XlsxResult<XlsxCell> {\n return this.move(rowDelta, colDelta).cell()\n }\n\n // ---------------------------------------------------------------------------\n // CURRENT CELL\n // ---------------------------------------------------------------------------\n\n /**\n * Get the cell at the current position.\n */\n cell(): XlsxResult<XlsxCell> {\n return this.sheet.cellAt(this._row, this._col)\n }\n\n /**\n * Get the value of the current cell.\n */\n value(): XlsxResult<unknown> {\n const cellResult = this.cell()\n if (!cellResult.ok) return cellResult\n return cellResult.value.value()\n }\n\n // ---------------------------------------------------------------------------\n // UTILITIES\n // ---------------------------------------------------------------------------\n\n /**\n * Check if the cursor is at a valid position with data.\n */\n isValid(): boolean {\n const cellResult = this.cell()\n return cellResult.ok\n }\n\n /**\n * Check if the current cell is empty.\n */\n isEmpty(): boolean {\n const cellResult = this.cell()\n return cellResult.ok && cellResult.value.isEmpty()\n }\n\n /**\n * Check if the current cell is non-empty.\n */\n isNotEmpty(): boolean {\n const cellResult = this.cell()\n return cellResult.ok && !cellResult.value.isEmpty()\n }\n\n /**\n * Create a new cursor at the same position.\n */\n clone(): XlsxCursor {\n return new XlsxCursor(this.sheet, this._row, this._col, this._direction)\n }\n}\n","/**\n * XlsxSheet - wrapper around ExcelJS worksheet with navigation and query capabilities.\n *\n * @module xlsx/xlsx-sheet\n */\n\nimport { TYPE_LABEL } from '@origints/core'\nimport type { Worksheet } from 'exceljs'\nimport { XlsxCell } from './xlsx-cell'\nimport { XlsxRange } from './xlsx-range'\nimport { XlsxCursor } from './xlsx-cursor'\nimport { XlsxResult, XlsxPath, CellValue, ok, fail } from './xlsx-result'\nimport { parseAddress, parseRange, columnLetterToNumber } from './util'\nimport type { CellPredicate } from './xlsx-query'\n\n/**\n * Dimensions of a sheet's used range.\n */\nexport interface SheetDimensions {\n readonly startRow: number\n readonly endRow: number\n readonly startCol: number\n readonly endCol: number\n readonly rowCount: number\n readonly colCount: number\n}\n\n/**\n * A wrapper around ExcelJS Worksheet with navigation and query capabilities.\n *\n * XlsxSheet provides a rich API for navigating cells, ranges, and rows\n * within a worksheet. It supports predicate-based queries and cursor-based\n * navigation for complex data extraction scenarios.\n */\nexport class XlsxSheet {\n get [TYPE_LABEL]() {\n return `XlsxSheet(${this.name})`\n }\n\n private constructor(\n private readonly worksheet: Worksheet,\n private readonly _path: XlsxPath,\n private readonly _file?: string\n ) {}\n\n /**\n * Creates an XlsxSheet from an ExcelJS worksheet.\n * @internal\n */\n static fromExcelJS(worksheet: Worksheet, file?: string): XlsxSheet {\n const path: XlsxPath = {\n file,\n sheet: worksheet.name,\n }\n return new XlsxSheet(worksheet, path, file)\n }\n\n // ---------------------------------------------------------------------------\n // IDENTITY\n // ---------------------------------------------------------------------------\n\n /**\n * Returns the sheet name.\n */\n get name(): string {\n return this.worksheet.name\n }\n\n /**\n * Returns the sheet index (1-based).\n */\n get index(): number {\n return this.worksheet.id\n }\n\n /**\n * Returns the current path for lineage tracking.\n */\n get path(): XlsxPath {\n return this._path\n }\n\n // ---------------------------------------------------------------------------\n // CELL ACCESS\n // ---------------------------------------------------------------------------\n\n /**\n * Get a cell by its address (e.g., \"A1\", \"B2\").\n */\n cell(address: string): XlsxResult<XlsxCell> {\n try {\n parseAddress(address) // Validate address\n const cell = this.worksheet.getCell(address)\n return ok(XlsxCell.fromExcelJS(cell, this.name, this._file), {\n ...this._path,\n cell: address,\n })\n } catch {\n return fail('range', `Invalid cell address: ${address}`, this._path)\n }\n }\n\n /**\n * Get a cell by row and column numbers (1-based).\n */\n cellAt(row: number, col: number): XlsxResult<XlsxCell> {\n if (row < 1 || col < 1) {\n return fail(\n 'bounds',\n `Invalid cell coordinates: row=${row}, col=${col}`,\n this._path\n )\n }\n const cell = this.worksheet.getCell(row, col)\n return ok(XlsxCell.fromExcelJS(cell, this.name, this._file), {\n ...this._path,\n cell: cell.address,\n })\n }\n\n /**\n * Get the value of a cell directly.\n */\n getValue(address: string): XlsxResult<CellValue> {\n const cellResult = this.cell(address)\n if (!cellResult.ok) return cellResult\n return cellResult.value.value()\n }\n\n // ---------------------------------------------------------------------------\n // RANGE OPERATIONS\n // ---------------------------------------------------------------------------\n\n /**\n * Get a range by its address (e.g., \"A1:C10\").\n */\n range(address: string): XlsxResult<XlsxRange> {\n return XlsxRange.fromAddress(this.worksheet, address, this.name, this._file)\n }\n\n /**\n * Get a range from start to end addresses.\n */\n rangeFrom(start: string, end: string): XlsxResult<XlsxRange> {\n return this.range(`${start}:${end}`)\n }\n\n /**\n * Get a range by coordinates (1-based).\n */\n rangeAt(\n startRow: number,\n startCol: number,\n endRow: number,\n endCol: number\n ): XlsxResult<XlsxRange> {\n if (startRow < 1 || startCol < 1 || endRow < 1 || endCol < 1) {\n return fail('bounds', 'Invalid range coordinates', this._path)\n }\n return ok(\n XlsxRange.fromCoords(\n this.worksheet,\n startRow,\n startCol,\n endRow,\n endCol,\n this.name,\n this._file\n ),\n this._path\n )\n }\n\n /**\n * Get the used range of the sheet (cells with data).\n */\n usedRange(): XlsxResult<XlsxRange> {\n const dims = this.dimensions()\n if (dims.rowCount === 0 || dims.colCount === 0) {\n return fail('missing', 'Sheet has no used cells', this._path)\n }\n return ok(\n XlsxRange.fromCoords(\n this.worksheet,\n dims.startRow,\n dims.startCol,\n dims.endRow,\n dims.endCol,\n this.name,\n this._file\n ),\n this._path\n )\n }\n\n // ---------------------------------------------------------------------------\n // ROW / COLUMN ACCESS\n // ---------------------------------------------------------------------------\n\n /**\n * Get a row as a range.\n */\n row(rowNum: number): XlsxResult<XlsxRange> {\n const dims = this.dimensions()\n if (rowNum < 1) {\n return fail('bounds', `Invalid row number: ${rowNum}`, this._path)\n }\n const endCol = Math.max(dims.endCol, 1)\n return ok(\n XlsxRange.fromCoords(\n this.worksheet,\n rowNum,\n 1,\n rowNum,\n endCol,\n this.name,\n this._file\n ),\n this._path\n )\n }\n\n /**\n * Get a column as a range.\n */\n col(colId: string | number): XlsxResult<XlsxRange> {\n const colNum =\n typeof colId === 'string'\n ? columnLetterToNumber(colId.toUpperCase())\n : colId\n if (colNum < 1) {\n return fail('bounds', `Invalid column: ${colId}`, this._path)\n }\n const dims = this.dimensions()\n const endRow = Math.max(dims.endRow, 1)\n return ok(\n XlsxRange.fromCoords(\n this.worksheet,\n 1,\n colNum,\n endRow,\n colNum,\n this.name,\n this._file\n ),\n this._path\n )\n }\n\n /**\n * Iterate over all rows with data.\n */\n *rows(): Iterable<XlsxRange> {\n const dims = this.dimensions()\n for (let r = dims.startRow; r <= dims.endRow; r++) {\n yield XlsxRange.fromCoords(\n this.worksheet,\n r,\n dims.startCol,\n r,\n dims.endCol,\n this.name,\n this._file\n )\n }\n }\n\n /**\n * Iterate over all columns with data.\n */\n *cols(): Iterable<XlsxRange> {\n const dims = this.dimensions()\n for (let c = dims.startCol; c <= dims.endCol; c++) {\n yield XlsxRange.fromCoords(\n this.worksheet,\n dims.startRow,\n c,\n dims.endRow,\n c,\n this.name,\n this._file\n )\n }\n }\n\n // ---------------------------------------------------------------------------\n // CURSOR CREATION\n // ---------------------------------------------------------------------------\n\n /**\n * Create a cursor starting at the specified address.\n */\n cursor(startAddress?: string): XlsxCursor {\n const address = startAddress ?? 'A1'\n return XlsxCursor.create(this, address)\n }\n\n /**\n * Create a cursor starting at the specified coordinates (1-based).\n */\n cursorAt(row: number, col: number): XlsxCursor {\n return XlsxCursor.createAt(this, row, col)\n }\n\n // ---------------------------------------------------------------------------\n // QUERY METHODS\n // ---------------------------------------------------------------------------\n\n /**\n * Find the first cell matching the predicate.\n */\n find(predicate: CellPredicate): XlsxResult<XlsxCell> {\n const rangeResult = this.usedRange()\n if (!rangeResult.ok) return rangeResult as XlsxResult<XlsxCell>\n return rangeResult.value.find(predicate)\n }\n\n /**\n * Find all cells matching the predicate.\n */\n findAll(predicate: CellPredicate): XlsxCell[] {\n const rangeResult = this.usedRange()\n if (!rangeResult.ok) return []\n return rangeResult.value.findAll(predicate)\n }\n\n /**\n * Find the first cell with the specified value.\n */\n findValue(value: CellValue): XlsxResult<XlsxCell> {\n const rangeResult = this.usedRange()\n if (!rangeResult.ok) return rangeResult as XlsxResult<XlsxCell>\n return rangeResult.value.findValue(value)\n }\n\n /**\n * Find cells within a specific range matching the predicate.\n */\n findInRange(\n rangeAddress: string,\n predicate: CellPredicate\n ): XlsxResult<XlsxCell> {\n const rangeResult = this.range(rangeAddress)\n if (!rangeResult.ok) return rangeResult as XlsxResult<XlsxCell>\n return rangeResult.value.find(predicate)\n }\n\n /**\n * Find all cells within a specific range matching the predicate.\n */\n findAllInRange(rangeAddress: string, predicate: CellPredicate): XlsxCell[] {\n const rangeResult = this.range(rangeAddress)\n if (!rangeResult.ok) return []\n return rangeResult.value.findAll(predicate)\n }\n\n // ---------------------------------------------------------------------------\n // DIMENSIONS\n // ---------------------------------------------------------------------------\n\n /**\n * Get the dimensions of the used area.\n */\n dimensions(): SheetDimensions {\n // ExcelJS tracks dimensions in the worksheet\n const rowCount = this.worksheet.rowCount\n const columnCount = this.worksheet.columnCount\n\n // Find actual used range by checking rows\n let startRow = 1\n let endRow = rowCount\n let startCol = 1\n let endCol = columnCount\n\n // Try to get actual dimensions from worksheet\n if (this.worksheet.dimensions) {\n const dims = this.worksheet.dimensions\n // dims is a string like \"A1:C10\" or an object\n if (typeof dims === 'string') {\n try {\n const parsed = parseRange(dims)\n startRow = parsed.start.row\n startCol = parsed.start.col\n endRow = parsed.end.row\n endCol = parsed.end.col\n } catch {\n // Fall back to calculated dimensions\n }\n }\n }\n\n return {\n startRow,\n endRow,\n startCol,\n endCol,\n rowCount: endRow - startRow + 1,\n colCount: endCol - startCol + 1,\n }\n }\n\n /**\n * Get the number of rows with data.\n */\n rowCount(): number {\n return this.dimensions().rowCount\n }\n\n /**\n * Get the number of columns with data.\n */\n colCount(): number {\n return this.dimensions().colCount\n }\n\n // ---------------------------------------------------------------------------\n // MERGED CELLS\n // ---------------------------------------------------------------------------\n\n /**\n * Get all merged cell ranges.\n */\n mergedRanges(): string[] {\n // ExcelJS stores merged cells in the _merges property or via hasMerges\n const merges = (\n this.worksheet as unknown as { _merges?: Record<string, unknown> }\n )._merges\n if (!merges) return []\n return Object.keys(merges)\n }\n\n /**\n * Check if a cell is part of a merged range.\n */\n isMerged(address: string): boolean {\n const cellResult = this.cell(address)\n if (!cellResult.ok) return false\n return cellResult.value.isMerged()\n }\n\n // ---------------------------------------------------------------------------\n // INTERNAL HELPERS\n // ---------------------------------------------------------------------------\n\n /**\n * Get the underlying ExcelJS worksheet.\n * @internal\n */\n getWorksheet(): Worksheet {\n return this.worksheet\n }\n\n /**\n * Get a cell by coordinates for internal use.\n * @internal\n */\n getCellInternal(row: number, col: number): XlsxCell | undefined {\n if (row < 1 || col < 1) return undefined\n const cell = this.worksheet.getCell(row, col)\n return XlsxCell.fromExcelJS(cell, this.name, this._file)\n }\n}\n","/**\n * XlsxWorkbook - wrapper around ExcelJS workbook with navigation and query capabilities.\n *\n * @module xlsx/xlsx-workbook\n */\n\nimport { TYPE_LABEL } from '@origints/core'\nimport type { Workbook } from 'exceljs'\nimport { XlsxSheet } from './xlsx-sheet'\nimport { XlsxResult, XlsxPath, ok, fail } from './xlsx-result'\n\n/**\n * Predicate function for matching sheets.\n */\nexport type SheetPredicate = (sheet: XlsxSheet) => boolean\n\n/**\n * Workbook properties.\n */\nexport interface WorkbookProperties {\n readonly title?: string\n readonly subject?: string\n readonly creator?: string\n readonly lastModifiedBy?: string\n readonly created?: Date\n readonly modified?: Date\n}\n\n/**\n * A wrapper around ExcelJS Workbook with navigation and query capabilities.\n *\n * XlsxWorkbook provides access to sheets, workbook properties, and\n * supports predicate-based queries for finding sheets.\n */\nexport class XlsxWorkbook {\n get [TYPE_LABEL]() {\n return `XlsxWorkbook(${this.sheetCount()} sheets)`\n }\n\n private readonly sheetsCache: Map<string, XlsxSheet> = new Map()\n\n private constructor(\n private readonly workbook: Workbook,\n private readonly _path: XlsxPath\n ) {}\n\n /**\n * Creates an XlsxWorkbook from an ExcelJS workbook.\n * @internal\n */\n static fromExcelJS(workbook: Workbook, file?: string): XlsxWorkbook {\n const path: XlsxPath = { file }\n return new XlsxWorkbook(workbook, path)\n }\n\n // ---------------------------------------------------------------------------\n // IDENTITY\n // ---------------------------------------------------------------------------\n\n /**\n * Returns the path for lineage tracking.\n */\n get path(): XlsxPath {\n return this._path\n }\n\n /**\n * Returns the file name if known.\n */\n get file(): string | undefined {\n return this._path.file\n }\n\n // ---------------------------------------------------------------------------\n // SHEET ACCESS\n // ---------------------------------------------------------------------------\n\n /**\n * Get a sheet by name.\n */\n sheet(name: string): XlsxResult<XlsxSheet> {\n // Check cache first\n const cached = this.sheetsCache.get(name)\n if (cached) {\n return ok(cached, { ...this._path, sheet: name })\n }\n\n const worksheet = this.workbook.getWorksheet(name)\n if (!worksheet) {\n return fail('missing', `Sheet \"${name}\" not found`, this._path)\n }\n\n const sheet = XlsxSheet.fromExcelJS(worksheet, this._path.file)\n this.sheetsCache.set(name, sheet)\n return ok(sheet, sheet.path)\n }\n\n /**\n * Get a sheet by index (1-based, as per Excel convention).\n */\n sheetAt(index: number): XlsxResult<XlsxSheet> {\n if (index < 1) {\n return fail(\n 'bounds',\n `Sheet index must be >= 1, got ${index}`,\n this._path\n )\n }\n\n const worksheet = this.workbook.getWorksheet(index)\n if (!worksheet) {\n return fail('missing', `Sheet at index ${index} not found`, this._path)\n }\n\n // Check cache by name\n const cached = this.sheetsCache.get(worksheet.name)\n if (cached) {\n return ok(cached, cached.path)\n }\n\n const sheet = XlsxSheet.fromExcelJS(worksheet, this._path.file)\n this.sheetsCache.set(worksheet.name, sheet)\n return ok(sheet, sheet.path)\n }\n\n /**\n * Get all sheets.\n */\n sheets(): XlsxSheet[] {\n const sheets: XlsxSheet[] = []\n this.workbook.eachSheet(worksheet => {\n const cached = this.sheetsCache.get(worksheet.name)\n if (cached) {\n sheets.push(cached)\n } else {\n const sheet = XlsxSheet.fromExcelJS(worksheet, this._path.file)\n this.sheetsCache.set(worksheet.name, sheet)\n sheets.push(sheet)\n }\n })\n return sheets\n }\n\n /**\n * Get all sheet names.\n */\n sheetNames(): string[] {\n const names: string[] = []\n this.workbook.eachSheet(worksheet => {\n names.push(worksheet.name)\n })\n return names\n }\n\n /**\n * Get the number of sheets.\n */\n sheetCount(): number {\n return this.workbook.worksheets.length\n }\n\n /**\n * Get the first sheet.\n */\n firstSheet(): XlsxResult<XlsxSheet> {\n return this.sheetAt(1)\n }\n\n /**\n * Get the last sheet.\n */\n lastSheet(): XlsxResult<XlsxSheet> {\n const count = this.sheetCount()\n if (count === 0) {\n return fail('missing', 'Workbook has no sheets', this._path)\n }\n return this.sheetAt(count)\n }\n\n // ---------------------------------------------------------------------------\n // PREDICATES\n // ---------------------------------------------------------------------------\n\n /**\n * Check if a sheet with the given name exists.\n */\n hasSheet(name: string): boolean {\n return this.workbook.getWorksheet(name) !== undefined\n }\n\n /**\n * Find the first sheet matching the predicate.\n */\n findSheet(predicate: SheetPredicate): XlsxResult<XlsxSheet> {\n for (const sheet of this.sheets()) {\n if (predicate(sheet)) {\n return ok(sheet, sheet.path)\n }\n }\n return fail('missing', 'No sheet matching predicate found', this._path)\n }\n\n /**\n * Find all sheets matching the predicate.\n */\n filterSheets(predicate: SheetPredicate): XlsxSheet[] {\n return this.sheets().filter(predicate)\n }\n\n /**\n * Find a sheet by name pattern (regex).\n */\n findSheetByPattern(pattern: RegExp): XlsxResult<XlsxSheet> {\n return this.findSheet(sheet => pattern.test(sheet.name))\n }\n\n /**\n * Find all sheets by name pattern (regex).\n */\n filterSheetsByPattern(pattern: RegExp): XlsxSheet[] {\n return this.filterSheets(sheet => pattern.test(sheet.name))\n }\n\n // ---------------------------------------------------------------------------\n // WORKBOOK PROPERTIES\n // ---------------------------------------------------------------------------\n\n /**\n * Get workbook properties.\n */\n properties(): WorkbookProperties {\n return {\n title: this.workbook.title,\n subject: this.workbook.subject,\n creator: this.workbook.creator,\n lastModifiedBy: this.workbook.lastModifiedBy,\n created: this.workbook.created,\n modified: this.workbook.modified,\n }\n }\n\n /**\n * Get the workbook creator.\n */\n creator(): string | undefined {\n return this.workbook.creator\n }\n\n /**\n * Get the workbook creation date.\n */\n created(): Date | undefined {\n return this.workbook.created\n }\n\n /**\n * Get the workbook modification date.\n */\n modified(): Date | undefined {\n return this.workbook.modified\n }\n\n // ---------------------------------------------------------------------------\n // DEFINED NAMES\n // ---------------------------------------------------------------------------\n\n /**\n * Get all defined names in the workbook.\n */\n definedNames(): string[] {\n const names: string[] = []\n // ExcelJS stores defined names differently\n // This is a simplified implementation\n return names\n }\n\n // ---------------------------------------------------------------------------\n // ITERATION\n // ---------------------------------------------------------------------------\n\n /**\n * Iterate over all sheets.\n */\n *[Symbol.iterator](): Iterator<XlsxSheet> {\n for (const sheet of this.sheets()) {\n yield sheet\n }\n }\n\n /**\n * Execute a function for each sheet.\n */\n forEach(fn: (sheet: XlsxSheet, index: number) => void): void {\n this.sheets().forEach(fn)\n }\n\n /**\n * Map over all sheets.\n */\n map<T>(fn: (sheet: XlsxSheet, index: number) => T): T[] {\n return this.sheets().map(fn)\n }\n\n // ---------------------------------------------------------------------------\n // INTERNAL\n // ---------------------------------------------------------------------------\n\n /**\n * Get the underlying ExcelJS workbook.\n * @internal\n */\n getWorkbook(): Workbook {\n return this.workbook\n }\n}\n","/**\n * Query predicates for XLSX cell matching.\n *\n * @module xlsx/xlsx-query\n */\n\nimport type { XlsxCell } from './xlsx-cell'\nimport type { CellValue } from './xlsx-result'\n\n/**\n * A predicate function for matching cells.\n */\nexport type CellPredicate = (cell: XlsxCell) => boolean\n\n/**\n * Built-in predicates for common cell matching scenarios.\n */\nexport const predicates = {\n // ---------------------------------------------------------------------------\n // VALUE PREDICATES\n // ---------------------------------------------------------------------------\n\n /**\n * Match cells with the exact value.\n */\n equals: (value: CellValue): CellPredicate => {\n return (cell: XlsxCell) => {\n const val = cell.value()\n if (!val.ok) return false\n if (value === null) return val.value === null\n if (val.value === null) return false\n // Handle date comparison\n if (value instanceof Date && val.value instanceof Date) {\n return value.getTime() === val.value.getTime()\n }\n return val.value === value\n }\n },\n\n /**\n * Match cells containing the specified text (case-insensitive by default).\n */\n contains: (text: string, caseSensitive: boolean = false): CellPredicate => {\n return (cell: XlsxCell) => {\n const val = cell.string()\n if (!val.ok) return false\n if (caseSensitive) {\n return val.value.includes(text)\n }\n return val.value.toLowerCase().includes(text.toLowerCase())\n }\n },\n\n /**\n * Match cells whose value matches the regex pattern.\n */\n matches: (pattern: RegExp): CellPredicate => {\n return (cell: XlsxCell) => {\n const val = cell.string()\n if (!val.ok) return false\n return pattern.test(val.value)\n }\n },\n\n /**\n * Match cells whose string value starts with the prefix.\n */\n startsWith: (\n prefix: string,\n caseSensitive: boolean = false\n ): CellPredicate => {\n return (cell: XlsxCell) => {\n const val = cell.string()\n if (!val.ok) return false\n if (caseSensitive) {\n return val.value.startsWith(prefix)\n }\n return val.value.toLowerCase().startsWith(prefix.toLowerCase())\n }\n },\n\n /**\n * Match cells whose string value ends with the suffix.\n */\n endsWith: (suffix: string, caseSensitive: boolean = false): CellPredicate => {\n return (cell: XlsxCell) => {\n const val = cell.string()\n if (!val.ok) return false\n if (caseSensitive) {\n return val.value.endsWith(suffix)\n }\n return val.value.toLowerCase().endsWith(suffix.toLowerCase())\n }\n },\n\n // ---------------------------------------------------------------------------\n // TYPE PREDICATES\n // ---------------------------------------------------------------------------\n\n /**\n * Match cells containing a string value.\n */\n isString: (): CellPredicate => {\n return (cell: XlsxCell) => cell.isString()\n },\n\n /**\n * Match cells containing a numeric value.\n */\n isNumber: (): CellPredicate => {\n return (cell: XlsxCell) => cell.isNumber()\n },\n\n /**\n * Match cells containing a boolean value.\n */\n isBoolean: (): CellPredicate => {\n return (cell: XlsxCell) => cell.isBoolean()\n },\n\n /**\n * Match cells containing a date value.\n */\n isDate: (): CellPredicate => {\n return (cell: XlsxCell) => cell.isDate()\n },\n\n /**\n * Match empty cells.\n */\n isEmpty: (): CellPredicate => {\n return (cell: XlsxCell) => cell.isEmpty()\n },\n\n /**\n * Match non-empty cells.\n */\n isNotEmpty: (): CellPredicate => {\n return (cell: XlsxCell) => !cell.isEmpty()\n },\n\n /**\n * Match cells containing a formula.\n */\n isFormula: (): CellPredicate => {\n return (cell: XlsxCell) => cell.isFormula()\n },\n\n /**\n * Match cells containing an error.\n */\n isError: (): CellPredicate => {\n return (cell: XlsxCell) => cell.isError()\n },\n\n /**\n * Match merged cells.\n */\n isMerged: (): CellPredicate => {\n return (cell: XlsxCell) => cell.isMerged()\n },\n\n // ---------------------------------------------------------------------------\n // NUMERIC PREDICATES\n // ---------------------------------------------------------------------------\n\n /**\n * Match cells with numeric value greater than n.\n */\n greaterThan: (n: number): CellPredicate => {\n return (cell: XlsxCell) => {\n const val = cell.number()\n return val.ok && val.value > n\n }\n },\n\n /**\n * Match cells with numeric value greater than or equal to n.\n */\n greaterThanOrEqual: (n: number): CellPredicate => {\n return (cell: XlsxCell) => {\n const val = cell.number()\n return val.ok && val.value >= n\n }\n },\n\n /**\n * Match cells with numeric value less than n.\n */\n lessThan: (n: number): CellPredicate => {\n return (cell: XlsxCell) => {\n const val = cell.number()\n return val.ok && val.value < n\n }\n },\n\n /**\n * Match cells with numeric value less than or equal to n.\n */\n lessThanOrEqual: (n: number): CellPredicate => {\n return (cell: XlsxCell) => {\n const val = cell.number()\n return val.ok && val.value <= n\n }\n },\n\n /**\n * Match cells with numeric value between min and max (inclusive).\n */\n between: (min: number, max: number): CellPredicate => {\n return (cell: XlsxCell) => {\n const val = cell.number()\n return val.ok && val.value >= min && val.value <= max\n }\n },\n\n // ---------------------------------------------------------------------------\n // DATE PREDICATES\n // ---------------------------------------------------------------------------\n\n /**\n * Match cells with date before the specified date.\n */\n dateBefore: (date: Date): CellPredicate => {\n return (cell: XlsxCell) => {\n const val = cell.date()\n return val.ok && val.value.getTime() < date.getTime()\n }\n },\n\n /**\n * Match cells with date after the specified date.\n */\n dateAfter: (date: Date): CellPredicate => {\n return (cell: XlsxCell) => {\n const val = cell.date()\n return val.ok && val.value.getTime() > date.getTime()\n }\n },\n\n /**\n * Match cells with date between start and end (inclusive).\n */\n dateBetween: (start: Date, end: Date): CellPredicate => {\n return (cell: XlsxCell) => {\n const val = cell.date()\n if (!val.ok) return false\n const time = val.value.getTime()\n return time >= start.getTime() && time <= end.getTime()\n }\n },\n\n // ---------------------------------------------------------------------------\n // LOCATION PREDICATES\n // ---------------------------------------------------------------------------\n\n /**\n * Match cells in the specified row.\n */\n inRow: (rowNum: number): CellPredicate => {\n return (cell: XlsxCell) => cell.row === rowNum\n },\n\n /**\n * Match cells in the specified column.\n */\n inCol: (colNum: number): CellPredicate => {\n return (cell: XlsxCell) => cell.col === colNum\n },\n\n /**\n * Match cells in the specified column (by letter).\n */\n inColLetter: (colLetter: string): CellPredicate => {\n return (cell: XlsxCell) =>\n cell.colLetter.toUpperCase() === colLetter.toUpperCase()\n },\n\n // ---------------------------------------------------------------------------\n // COMPOSITION\n // ---------------------------------------------------------------------------\n\n /**\n * Match cells that satisfy all predicates.\n */\n and: (...preds: CellPredicate[]): CellPredicate => {\n return (cell: XlsxCell) => preds.every(pred => pred(cell))\n },\n\n /**\n * Match cells that satisfy at least one predicate.\n */\n or: (...preds: CellPredicate[]): CellPredicate => {\n return (cell: XlsxCell) => preds.some(pred => pred(cell))\n },\n\n /**\n * Match cells that do not satisfy the predicate.\n */\n not: (pred: CellPredicate): CellPredicate => {\n return (cell: XlsxCell) => !pred(cell)\n },\n\n // ---------------------------------------------------------------------------\n // STYLE PREDICATES\n // ---------------------------------------------------------------------------\n\n /**\n * Match cells with bold font.\n */\n isBold: (): CellPredicate => {\n return (cell: XlsxCell) => {\n const style = cell.style()\n return style.font?.bold === true\n }\n },\n\n /**\n * Match cells with italic font.\n */\n isItalic: (): CellPredicate => {\n return (cell: XlsxCell) => {\n const style = cell.style()\n return style.font?.italic === true\n }\n },\n\n /**\n * Match cells with a hyperlink.\n */\n hasHyperlink: (): CellPredicate => {\n return (cell: XlsxCell) => {\n const link = cell.hyperlink()\n return link.ok\n }\n },\n\n /**\n * Match cells with a comment.\n */\n hasComment: (): CellPredicate => {\n return (cell: XlsxCell) => {\n const comment = cell.comment()\n return comment.ok\n }\n },\n\n // ---------------------------------------------------------------------------\n // UTILITY\n // ---------------------------------------------------------------------------\n\n /**\n * Always match.\n */\n always: (): CellPredicate => {\n return () => true\n },\n\n /**\n * Never match.\n */\n never: (): CellPredicate => {\n return () => false\n },\n\n /**\n * Create a custom predicate from a function.\n */\n custom: (fn: (cell: XlsxCell) => boolean): CellPredicate => {\n return fn\n },\n}\n\n/**\n * Type for the predicates object.\n */\nexport type Predicates = typeof predicates\n","/**\n * XLSX spec builders — build-time recorders that produce XlsxSpec objects.\n *\n * These mirror the runtime navigator API (XlsxWorkbook, XlsxSheet, XlsxCell)\n * but instead of navigating live data, they record navigation steps as\n * JSON-serializable specs.\n *\n * @module xlsx/xlsx-spec-builder\n */\n\nimport type { ArraySpec, ExtractSpec, Spec } from '@origints/core'\nimport type {\n XlsxStep,\n XlsxExtract,\n Direction,\n EachCellExtract,\n EachSliceExtract,\n} from './xlsx-spec'\nimport type { CellPred, SheetPred, RowPred } from './xlsx-predicate-spec'\n\n// -----------------------------------------------------------------------------\n// Internal helper\n// -----------------------------------------------------------------------------\n\nfunction buildSpec<E extends XlsxExtract>(\n steps: readonly XlsxStep[],\n extract: E\n): ExtractSpec<XlsxStep, E> {\n return { kind: 'extract', format: 'xlsx', steps, extract }\n}\n\n// -----------------------------------------------------------------------------\n// Cell-level spec builder\n// -----------------------------------------------------------------------------\n\n/**\n * Spec builder at the cell level — terminal extraction and navigation methods.\n */\nexport class XlsxCellSB {\n /** @internal */\n constructor(private readonly steps: readonly XlsxStep[]) {}\n\n /** @internal Expose steps for colWhere/rowWhere headerRef */\n get _steps(): readonly XlsxStep[] {\n return this.steps\n }\n\n // ---------------------------------------------------------------------------\n // Terminal extraction\n // ---------------------------------------------------------------------------\n\n /** Extract cell value as string */\n string(): ExtractSpec<XlsxStep, 'string'> {\n return buildSpec(this.steps, 'string')\n }\n\n /** Extract cell value as number */\n number(): ExtractSpec<XlsxStep, 'number'> {\n return buildSpec(this.steps, 'number')\n }\n\n /** Extract cell value as boolean */\n boolean(): ExtractSpec<XlsxStep, 'boolean'> {\n return buildSpec(this.steps, 'boolean')\n }\n\n /** Extract cell value as Date */\n date(): ExtractSpec<XlsxStep, 'date'> {\n return buildSpec(this.steps, 'date')\n }\n\n /** Extract raw cell value */\n value(): ExtractSpec<XlsxStep, 'value'> {\n return buildSpec(this.steps, 'value')\n }\n\n /** Extract cell formula */\n formula(): ExtractSpec<XlsxStep, 'formula'> {\n return buildSpec(this.steps, 'formula')\n }\n\n // ---------------------------------------------------------------------------\n // Relative movement (cell → cell)\n // ---------------------------------------------------------------------------\n\n /** Move right by count cells (default 1) */\n right(count: number = 1): XlsxCellSB {\n return new XlsxCellSB([...this.steps, { kind: 'right', count }])\n }\n\n /** Move left by count cells (default 1) */\n left(count: number = 1): XlsxCellSB {\n return new XlsxCellSB([...this.steps, { kind: 'left', count }])\n }\n\n /** Move up by count cells (default 1) */\n up(count: number = 1): XlsxCellSB {\n return new XlsxCellSB([...this.steps, { kind: 'up', count }])\n }\n\n /** Move down by count cells (default 1) */\n down(count: number = 1): XlsxCellSB {\n return new XlsxCellSB([...this.steps, { kind: 'down', count }])\n }\n\n /** Move by row and column deltas */\n offset(rowDelta: number, colDelta: number): XlsxCellSB {\n return new XlsxCellSB([\n ...this.steps,\n { kind: 'offset', rowDelta, colDelta },\n ])\n }\n\n /** Scan in direction until predicate matches */\n scanTo(direction: Direction, predicate: CellPred): XlsxCellSB {\n return new XlsxCellSB([\n ...this.steps,\n { kind: 'scanTo', direction, predicate: predicate._spec },\n ])\n }\n\n /** Skip cells in direction while predicate matches, land on first non-matching */\n skipWhile(direction: Direction, predicate: CellPred): XlsxCellSB {\n return new XlsxCellSB([\n ...this.steps,\n { kind: 'skipWhile', direction, predicate: predicate._spec },\n ])\n }\n\n // ---------------------------------------------------------------------------\n // Collection (cell → array via collect)\n // ---------------------------------------------------------------------------\n\n /**\n * Iterate over cells from this position in a direction while the predicate matches.\n * Returns an ArraySpec whose items are produced by the itemMapper.\n */\n eachCell<T extends Spec>(\n direction: Direction,\n while_: CellPred,\n itemMapper: (cell: XlsxCellSB) => T\n ): ArraySpec<T> {\n const itemSpec = itemMapper(new XlsxCellSB([]))\n const collectExtract: EachCellExtract = {\n kind: 'eachCell',\n direction,\n while: while_._spec,\n }\n return {\n kind: 'array',\n source: buildSpec(this.steps, collectExtract),\n items: itemSpec,\n }\n }\n\n /**\n * Iterate over slices (rows or columns) from this cell position.\n * Each slice is passed as an XlsxSliceSB to the mapper, providing\n * header-relative column/row access via colWhere/rowWhere.\n */\n eachSlice<T extends Spec>(\n direction: Direction,\n while_: RowPred,\n itemMapper: (slice: XlsxSliceSB) => T\n ): ArraySpec<T> {\n const itemSpec = itemMapper(new XlsxSliceSB([]))\n const collectExtract: EachSliceExtract = {\n kind: 'eachSlice',\n direction,\n while: while_._spec,\n }\n return {\n kind: 'array',\n source: buildSpec(this.steps, collectExtract),\n items: itemSpec,\n }\n }\n}\n\n// -----------------------------------------------------------------------------\n// Slice item spec builder — used inside eachSlice() mapper\n// -----------------------------------------------------------------------------\n\n/**\n * Spec builder for items within a slice (row or column section).\n * Provides header-relative column/row access.\n */\nexport class XlsxSliceSB {\n /** @internal */\n constructor(private readonly steps: readonly XlsxStep[]) {}\n\n /** Access a column by matching its header cell against a predicate (header-relative) */\n colWhere(headerRef: XlsxCellSB, predicate: CellPred): XlsxCellSB {\n const headerSpec = buildSpec(headerRef._steps, 'value')\n return new XlsxCellSB([\n ...this.steps,\n { kind: 'colWhere', headerRef: headerSpec, predicate: predicate._spec },\n ])\n }\n\n /** Access a row by matching its header cell against a predicate (header-relative, for rotated tables) */\n rowWhere(headerRef: XlsxCellSB, predicate: CellPred): XlsxCellSB {\n const headerSpec = buildSpec(headerRef._steps, 'value')\n return new XlsxCellSB([\n ...this.steps,\n { kind: 'rowWhere', headerRef: headerSpec, predicate: predicate._spec },\n ])\n }\n\n /** Access a column by 0-based offset from the anchor */\n col(offset: number): XlsxCellSB {\n return new XlsxCellSB([\n ...this.steps,\n { kind: 'offset', rowDelta: 0, colDelta: offset },\n ])\n }\n\n /** Access a row by 0-based offset from the anchor (for rotated tables) */\n row(offset: number): XlsxCellSB {\n return new XlsxCellSB([\n ...this.steps,\n { kind: 'offset', rowDelta: offset, colDelta: 0 },\n ])\n }\n}\n\n// -----------------------------------------------------------------------------\n// Row item spec builder — used inside rows() mapper\n// -----------------------------------------------------------------------------\n\n/**\n * Spec builder for items within a row (receives an XlsxRange representing one row).\n * Provides column access to navigate within the row.\n */\nexport class XlsxRowItemSB {\n /** @internal */\n constructor(private readonly steps: readonly XlsxStep[]) {}\n\n /** Access a column by 1-based index within the row */\n col(index: number): XlsxCellSB {\n return new XlsxCellSB([...this.steps, { kind: 'col', index }])\n }\n\n /** Navigate to a cell by address within the row */\n cell(ref: string): XlsxCellSB {\n return new XlsxCellSB([...this.steps, { kind: 'cell', ref }])\n }\n}\n\n// -----------------------------------------------------------------------------\n// Range-level spec builder\n// -----------------------------------------------------------------------------\n\n/**\n * Spec builder at the range level — cell navigation, rows, and cells collection.\n */\nexport class XlsxRangeSB {\n /** @internal */\n constructor(private readonly steps: readonly XlsxStep[]) {}\n\n /** Navigate to a cell by address within the range */\n cell(ref: string): XlsxCellSB {\n return new XlsxCellSB([...this.steps, { kind: 'cell', ref }])\n }\n\n /** Navigate to a cell by coordinates within the range */\n cellAt(row: number, col: number): XlsxCellSB {\n return new XlsxCellSB([...this.steps, { kind: 'cellAt', row, col }])\n }\n\n /**\n * Iterate over rows in the range.\n * Each row is provided as an XlsxRowItemSB to the mapper.\n * Returns an ArraySpec.\n */\n rows<T extends Spec>(itemMapper: (row: XlsxRowItemSB) => T): ArraySpec<T> {\n const itemSpec = itemMapper(new XlsxRowItemSB([]))\n return {\n kind: 'array',\n source: buildSpec(this.steps, 'rows'),\n items: itemSpec,\n }\n }\n\n /**\n * Iterate over all cells in the range as a flat list.\n * Each cell is provided as an XlsxCellSB to the mapper.\n * Returns an ArraySpec.\n */\n cells<T extends Spec>(itemMapper: (cell: XlsxCellSB) => T): ArraySpec<T> {\n const itemSpec = itemMapper(new XlsxCellSB([]))\n return {\n kind: 'array',\n source: buildSpec(this.steps, 'cells'),\n items: itemSpec,\n }\n }\n}\n\n// -----------------------------------------------------------------------------\n// Row/Col spec builders\n// -----------------------------------------------------------------------------\n\n/**\n * Spec builder at the row level.\n */\nexport class XlsxRowSB {\n /** @internal */\n constructor(private readonly steps: readonly XlsxStep[]) {}\n\n /** Navigate to a cell by address within this row */\n cell(ref: string): XlsxCellSB {\n return new XlsxCellSB([...this.steps, { kind: 'cell', ref }])\n }\n\n /** Navigate to a cell by column within this row */\n cellAt(row: number, col: number): XlsxCellSB {\n return new XlsxCellSB([...this.steps, { kind: 'cellAt', row, col }])\n }\n}\n\n/**\n * Spec builder at the column level.\n */\nexport class XlsxColSB {\n /** @internal */\n constructor(private readonly steps: readonly XlsxStep[]) {}\n\n /** Navigate to a cell by address within this column */\n cell(ref: string): XlsxCellSB {\n return new XlsxCellSB([...this.steps, { kind: 'cell', ref }])\n }\n\n /** Navigate to a cell by coordinates within this column */\n cellAt(row: number, col: number): XlsxCellSB {\n return new XlsxCellSB([...this.steps, { kind: 'cellAt', row, col }])\n }\n}\n\n// -----------------------------------------------------------------------------\n// Sheet-level spec builder\n// -----------------------------------------------------------------------------\n\n/**\n * Spec builder at the sheet level — cell, range, row, column, and search navigation.\n */\nexport class XlsxSheetSB {\n /** @internal */\n constructor(private readonly steps: readonly XlsxStep[]) {}\n\n // ---------------------------------------------------------------------------\n // Direct cell navigation\n // ---------------------------------------------------------------------------\n\n /** Navigate to a cell by address (e.g., \"A1\", \"B2\") */\n cell(ref: string): XlsxCellSB {\n return new XlsxCellSB([...this.steps, { kind: 'cell', ref }])\n }\n\n /** Navigate to a cell by 1-based row and column coordinates */\n cellAt(row: number, col: number): XlsxCellSB {\n return new XlsxCellSB([...this.steps, { kind: 'cellAt', row, col }])\n }\n\n // ---------------------------------------------------------------------------\n // Cell search (sheet → cell)\n // ---------------------------------------------------------------------------\n\n /** Find the first cell matching the predicate */\n find(predicate: CellPred): XlsxCellSB {\n return new XlsxCellSB([\n ...this.steps,\n { kind: 'find', predicate: predicate._spec },\n ])\n }\n\n /** Find the first cell matching the predicate in the specified row */\n findInRow(rowIndex: number, predicate: CellPred): XlsxCellSB {\n return new XlsxCellSB([\n ...this.steps,\n { kind: 'findInRow', rowIndex, predicate: predicate._spec },\n ])\n }\n\n /** Find the first cell matching the predicate in the specified column */\n findInCol(colIndex: number, predicate: CellPred): XlsxCellSB {\n return new XlsxCellSB([\n ...this.steps,\n { kind: 'findInCol', colIndex, predicate: predicate._spec },\n ])\n }\n\n /** Find the first cell matching the predicate in the specified range */\n findInRange(rangeRef: string, predicate: CellPred): XlsxCellSB {\n return new XlsxCellSB([\n ...this.steps,\n { kind: 'findInRange', rangeRef, predicate: predicate._spec },\n ])\n }\n\n // ---------------------------------------------------------------------------\n // Range/row/col navigation\n // ---------------------------------------------------------------------------\n\n /** Navigate to a range by address (e.g., \"A1:C10\") */\n range(ref: string): XlsxRangeSB\n /** Navigate to a range by two corner addresses */\n range(from: string, to: string): XlsxRangeSB\n /** Navigate to a range defined by two dynamically resolved cells */\n range(from: XlsxCellSB, to: XlsxCellSB): XlsxRangeSB\n range(fromOrRef: string | XlsxCellSB, to?: string | XlsxCellSB): XlsxRangeSB {\n if (to === undefined) {\n return new XlsxRangeSB([\n ...this.steps,\n { kind: 'range', ref: fromOrRef as string },\n ])\n }\n if (typeof fromOrRef === 'string' && typeof to === 'string') {\n return new XlsxRangeSB([\n ...this.steps,\n { kind: 'range', ref: `${fromOrRef}:${to}` },\n ])\n }\n const fromSpec = buildSpec((fromOrRef as XlsxCellSB)._steps, 'value')\n const toSpec = buildSpec((to as XlsxCellSB)._steps, 'value')\n return new XlsxRangeSB([\n ...this.steps,\n { kind: 'rangeFromCells', from: fromSpec, to: toSpec },\n ])\n }\n\n /** Navigate to a row by 1-based index */\n row(index: number): XlsxRowSB {\n return new XlsxRowSB([...this.steps, { kind: 'row', index }])\n }\n\n /** Navigate to a column by 1-based index */\n col(index: number): XlsxColSB {\n return new XlsxColSB([...this.steps, { kind: 'col', index }])\n }\n}\n\n// -----------------------------------------------------------------------------\n// Workbook-level spec builder (entry point)\n// -----------------------------------------------------------------------------\n\n/**\n * Spec builder for XLSX workbook — the entry point for xlsx navigation specs.\n *\n * Used as `$` in `emit()` after `.mapIn(parseXlsx())`.\n */\nexport class XlsxSpecBuilder {\n private constructor(private readonly steps: readonly XlsxStep[]) {}\n\n /** Create a root spec builder */\n static root(): XlsxSpecBuilder {\n return new XlsxSpecBuilder([])\n }\n\n /** Navigate to a sheet by name */\n sheet(name: string): XlsxSheetSB {\n return new XlsxSheetSB([...this.steps, { kind: 'sheet', name }])\n }\n\n /** Navigate to a sheet by 1-based index */\n sheetAt(index: number): XlsxSheetSB {\n return new XlsxSheetSB([...this.steps, { kind: 'sheetAt', index }])\n }\n\n /** Navigate to the first sheet */\n firstSheet(): XlsxSheetSB {\n return new XlsxSheetSB([...this.steps, { kind: 'firstSheet' }])\n }\n\n /** Find a sheet matching the predicate */\n findSheet(predicate: SheetPred): XlsxSheetSB {\n return new XlsxSheetSB([\n ...this.steps,\n { kind: 'findSheet', predicate: predicate._spec },\n ])\n }\n}\n","/**\n * XLSX parsing transform for Origins.\n *\n * @module xlsx/parse\n */\n\nimport ExcelJS from 'exceljs'\nimport { XlsxWorkbook } from './xlsx-workbook'\nimport { XlsxSpecBuilder } from './xlsx-spec-builder'\nimport { streamToBuffer } from './util'\n\n/**\n * Transform AST specification.\n * Compatible with @origints/core TransformAst.\n */\nexport interface TransformAst {\n readonly kind: 'transform'\n readonly namespace: string\n readonly name: string\n readonly args?: unknown\n}\n\n/**\n * Typed transform AST with spec builder type parameter.\n * Compatible with @origints/core TypedTransformAst.\n */\nexport interface TypedTransformAst<SB = unknown> extends TransformAst {\n readonly __specBuilder?: SB\n readonly specBuilderFactory: () => SB\n}\n\n/**\n * Transform implementation.\n * Compatible with @origints/core TransformImpl.\n */\nexport interface TransformImpl<In = unknown, Out = unknown> {\n readonly namespace: string\n readonly name: string\n execute(input: In, args?: unknown): Out | Promise<Out>\n}\n\n/**\n * Options for parsing XLSX.\n */\nexport interface XlsxParseOptions {\n /**\n * Which sheets to parse.\n * - 'all': Parse all sheets (default)\n * - string[]: Only parse sheets with these names\n * - number[]: Only parse sheets at these indices (1-based)\n */\n sheets?: 'all' | string[] | number[]\n\n /**\n * Whether to use formula results instead of formulas.\n * Default: true (use calculated results)\n */\n formulaResults?: boolean\n\n /**\n * Whether to include hidden sheets.\n * Default: true\n */\n includeHidden?: boolean\n\n /**\n * Date format for parsing dates.\n * This affects how date values are interpreted.\n */\n dateFormat?: string\n\n /**\n * File name to associate with the parsed workbook.\n * Used for lineage tracking.\n */\n fileName?: string\n}\n\n/**\n * Creates a TransformAst for parsing XLSX.\n *\n * @example\n * ```ts\n * const plan = new Planner()\n * .in(loadFile('data.xlsx'))\n * .mapIn(parseXlsx())\n * .emit((out, $) => out\n * .add('revenue', $.get('Sales').get('B2').number())\n * )\n * .compile()\n * ```\n */\nexport function parseXlsx(\n options?: XlsxParseOptions\n): TypedTransformAst<XlsxSpecBuilder> {\n return {\n kind: 'transform',\n namespace: '@origints/xlsx',\n name: 'parseXlsx',\n args: options,\n specBuilderFactory: () => XlsxSpecBuilder.root(),\n }\n}\n\n/**\n * Sync transform implementation for parseXlsx.\n * Note: XLSX parsing requires async due to file reading.\n */\nexport const parseXlsxImpl: TransformImpl = {\n namespace: '@origints/xlsx',\n name: 'parseXlsx',\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n execute(input: unknown, args?: unknown): never {\n throw new Error(\n 'parseXlsx requires async execution. Use parseXlsxAsyncImpl instead.'\n )\n },\n}\n\n/**\n * Convert a buffer-like input to ArrayBuffer.\n */\nfunction toArrayBuffer(input: Buffer | Uint8Array): ArrayBuffer {\n // Create a new ArrayBuffer and copy data to avoid SharedArrayBuffer issues\n const copy = new Uint8Array(input)\n return copy.buffer\n}\n\n/**\n * Async transform implementation for parseXlsx (handles streams and buffers).\n */\nexport const parseXlsxAsyncImpl: TransformImpl = {\n namespace: '@origints/xlsx',\n name: 'parseXlsx',\n\n async execute(input: unknown, args?: unknown): Promise<XlsxWorkbook> {\n const options = (args as XlsxParseOptions) ?? {}\n\n let data: ArrayBuffer\n\n if (input instanceof ReadableStream) {\n const buffer = await streamToBuffer(input)\n data = toArrayBuffer(buffer)\n } else if (Buffer.isBuffer(input)) {\n data = toArrayBuffer(input)\n } else if (input instanceof ArrayBuffer) {\n data = input\n } else if (input instanceof Uint8Array) {\n data = toArrayBuffer(input)\n } else {\n throw new Error(\n `parseXlsx expects stream or buffer input, got ${typeof input}`\n )\n }\n\n const workbook = new ExcelJS.Workbook()\n await workbook.xlsx.load(data)\n\n return XlsxWorkbook.fromExcelJS(workbook, options.fileName)\n },\n}\n\n/**\n * Parse XLSX from a buffer directly.\n */\nexport async function parseXlsxBuffer(\n buffer: Buffer | ArrayBuffer | Uint8Array,\n options?: XlsxParseOptions\n): Promise<XlsxWorkbook> {\n const workbook = new ExcelJS.Workbook()\n let data: ArrayBuffer\n if (buffer instanceof ArrayBuffer) {\n data = buffer\n } else {\n data = toArrayBuffer(buffer)\n }\n await workbook.xlsx.load(data)\n return XlsxWorkbook.fromExcelJS(workbook, options?.fileName)\n}\n\n/**\n * Parse XLSX from a file path directly.\n * Useful for testing and standalone usage.\n */\nexport async function parseXlsxFile(\n filePath: string,\n options?: XlsxParseOptions\n): Promise<XlsxWorkbook> {\n const workbook = new ExcelJS.Workbook()\n await workbook.xlsx.readFile(filePath)\n return XlsxWorkbook.fromExcelJS(workbook, options?.fileName ?? filePath)\n}\n","/**\n * Compiles predicate spec ASTs into runtime closures.\n *\n * @module xlsx/xlsx-predicate-compiler\n */\n\nimport type { XlsxCell } from './xlsx-cell'\nimport type { XlsxSheet } from './xlsx-sheet'\nimport type { CellPredicate } from './xlsx-query'\nimport type { SheetPredicate } from './xlsx-workbook'\nimport type {\n CellPredicateSpec,\n SheetPredicateSpec,\n RowPredicateSpec,\n} from './xlsx-predicate-spec'\n\n/**\n * Compile a CellPredicateSpec AST into a runtime CellPredicate closure.\n */\nexport function compileCellPredicate(spec: CellPredicateSpec): CellPredicate {\n switch (spec.kind) {\n // Value predicates\n case 'equals':\n return (cell: XlsxCell) => {\n const val = cell.value()\n if (!val.ok) return false\n if (spec.value === null) return val.value === null\n if (val.value === null) return false\n if (spec.value instanceof Date && val.value instanceof Date) {\n return spec.value.getTime() === val.value.getTime()\n }\n return val.value === spec.value\n }\n\n case 'contains':\n return (cell: XlsxCell) => {\n const val = cell.string()\n if (!val.ok) return false\n if (spec.caseSensitive) {\n return val.value.includes(spec.text)\n }\n return val.value.toLowerCase().includes(spec.text.toLowerCase())\n }\n\n case 'matches':\n return (cell: XlsxCell) => {\n const val = cell.string()\n if (!val.ok) return false\n const re = new RegExp(spec.pattern, spec.flags)\n return re.test(val.value)\n }\n\n case 'startsWith':\n return (cell: XlsxCell) => {\n const val = cell.string()\n if (!val.ok) return false\n if (spec.caseSensitive) {\n return val.value.startsWith(spec.prefix)\n }\n return val.value.toLowerCase().startsWith(spec.prefix.toLowerCase())\n }\n\n case 'endsWith':\n return (cell: XlsxCell) => {\n const val = cell.string()\n if (!val.ok) return false\n if (spec.caseSensitive) {\n return val.value.endsWith(spec.suffix)\n }\n return val.value.toLowerCase().endsWith(spec.suffix.toLowerCase())\n }\n\n // Type predicates\n case 'isString':\n return (cell: XlsxCell) => cell.isString()\n case 'isNumber':\n return (cell: XlsxCell) => cell.isNumber()\n case 'isBoolean':\n return (cell: XlsxCell) => cell.isBoolean()\n case 'isDate':\n return (cell: XlsxCell) => cell.isDate()\n case 'isEmpty':\n return (cell: XlsxCell) => cell.isEmpty()\n case 'isNotEmpty':\n return (cell: XlsxCell) => !cell.isEmpty()\n case 'isFormula':\n return (cell: XlsxCell) => cell.isFormula()\n case 'isError':\n return (cell: XlsxCell) => cell.isError()\n case 'isMerged':\n return (cell: XlsxCell) => cell.isMerged()\n\n // Numeric predicates\n case 'gt':\n return (cell: XlsxCell) => {\n const val = cell.number()\n return val.ok && val.value > spec.value\n }\n case 'gte':\n return (cell: XlsxCell) => {\n const val = cell.number()\n return val.ok && val.value >= spec.value\n }\n case 'lt':\n return (cell: XlsxCell) => {\n const val = cell.number()\n return val.ok && val.value < spec.value\n }\n case 'lte':\n return (cell: XlsxCell) => {\n const val = cell.number()\n return val.ok && val.value <= spec.value\n }\n case 'between':\n return (cell: XlsxCell) => {\n const val = cell.number()\n return val.ok && val.value >= spec.min && val.value <= spec.max\n }\n\n // Style predicates\n case 'isBold':\n return (cell: XlsxCell) => {\n const style = cell.style()\n return style.font?.bold === true\n }\n case 'isItalic':\n return (cell: XlsxCell) => {\n const style = cell.style()\n return style.font?.italic === true\n }\n case 'hasHyperlink':\n return (cell: XlsxCell) => {\n const link = cell.hyperlink()\n return link.ok\n }\n case 'hasComment':\n return (cell: XlsxCell) => {\n const comment = cell.comment()\n return comment.ok\n }\n\n // Composition\n case 'and': {\n const left = compileCellPredicate(spec.left)\n const right = compileCellPredicate(spec.right)\n return (cell: XlsxCell) => left(cell) && right(cell)\n }\n case 'or': {\n const left = compileCellPredicate(spec.left)\n const right = compileCellPredicate(spec.right)\n return (cell: XlsxCell) => left(cell) || right(cell)\n }\n case 'not': {\n const operand = compileCellPredicate(spec.operand)\n return (cell: XlsxCell) => !operand(cell)\n }\n }\n}\n\n/**\n * Compile a SheetPredicateSpec AST into a runtime SheetPredicate closure.\n */\nexport function compileSheetPredicate(\n spec: SheetPredicateSpec\n): SheetPredicate {\n switch (spec.kind) {\n case 'nameEquals':\n return (sheet: XlsxSheet) => sheet.name === spec.name\n case 'nameContains':\n return (sheet: XlsxSheet) => sheet.name.includes(spec.text)\n case 'nameStartsWith':\n return (sheet: XlsxSheet) => sheet.name.startsWith(spec.prefix)\n case 'nameEndsWith':\n return (sheet: XlsxSheet) => sheet.name.endsWith(spec.suffix)\n case 'nameMatches': {\n const re = new RegExp(spec.pattern, spec.flags)\n return (sheet: XlsxSheet) => re.test(sheet.name)\n }\n case 'and': {\n const left = compileSheetPredicate(spec.left)\n const right = compileSheetPredicate(spec.right)\n return (sheet: XlsxSheet) => left(sheet) && right(sheet)\n }\n case 'or': {\n const left = compileSheetPredicate(spec.left)\n const right = compileSheetPredicate(spec.right)\n return (sheet: XlsxSheet) => left(sheet) || right(sheet)\n }\n case 'not': {\n const operand = compileSheetPredicate(spec.operand)\n return (sheet: XlsxSheet) => !operand(sheet)\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Row predicate compiler\n// ---------------------------------------------------------------------------\n\nexport type RowPredicate = (\n sheet: XlsxSheet,\n row: number,\n anchorCol: number\n) => boolean\n\n/**\n * Compile a RowPredicateSpec AST into a runtime RowPredicate closure.\n */\nexport function compileRowPredicate(spec: RowPredicateSpec): RowPredicate {\n switch (spec.kind) {\n case 'rowCol': {\n const cellPred = compileCellPredicate(spec.predicate)\n return (sheet: XlsxSheet, row: number, anchorCol: number) => {\n const col = anchorCol + spec.offset\n if (col < 1) return false\n const cellResult = sheet.cellAt(row, col)\n if (!cellResult.ok) return false\n return cellPred(cellResult.value)\n }\n }\n case 'and': {\n const left = compileRowPredicate(spec.left)\n const right = compileRowPredicate(spec.right)\n return (sheet: XlsxSheet, row: number, anchorCol: number) =>\n left(sheet, row, anchorCol) && right(sheet, row, anchorCol)\n }\n case 'or': {\n const left = compileRowPredicate(spec.left)\n const right = compileRowPredicate(spec.right)\n return (sheet: XlsxSheet, row: number, anchorCol: number) =>\n left(sheet, row, anchorCol) || right(sheet, row, anchorCol)\n }\n case 'not': {\n const operand = compileRowPredicate(spec.operand)\n return (sheet: XlsxSheet, row: number, anchorCol: number) =>\n !operand(sheet, row, anchorCol)\n }\n }\n}\n","/**\n * Predicate AST types and builder factories for XLSX cell and sheet matching.\n *\n * These types are JSON-serializable specs that describe predicates over cells\n * and sheets. They are compiled to runtime closures by xlsx-predicate-compiler.\n *\n * @module xlsx/xlsx-predicate-spec\n */\n\nimport type { CellValue } from './xlsx-result'\n\n// ---------------------------------------------------------------------------\n// CellPredicateSpec — discriminated union\n// ---------------------------------------------------------------------------\n\nexport type CellPredicateSpec =\n // Value predicates\n | { readonly kind: 'equals'; readonly value: CellValue }\n | {\n readonly kind: 'contains'\n readonly text: string\n readonly caseSensitive: boolean\n }\n | {\n readonly kind: 'matches'\n readonly pattern: string\n readonly flags: string\n }\n | {\n readonly kind: 'startsWith'\n readonly prefix: string\n readonly caseSensitive: boolean\n }\n | {\n readonly kind: 'endsWith'\n readonly suffix: string\n readonly caseSensitive: boolean\n }\n // Type predicates\n | { readonly kind: 'isString' }\n | { readonly kind: 'isNumber' }\n | { readonly kind: 'isBoolean' }\n | { readonly kind: 'isDate' }\n | { readonly kind: 'isEmpty' }\n | { readonly kind: 'isNotEmpty' }\n | { readonly kind: 'isFormula' }\n | { readonly kind: 'isError' }\n | { readonly kind: 'isMerged' }\n // Numeric predicates\n | { readonly kind: 'gt'; readonly value: number }\n | { readonly kind: 'gte'; readonly value: number }\n | { readonly kind: 'lt'; readonly value: number }\n | { readonly kind: 'lte'; readonly value: number }\n | { readonly kind: 'between'; readonly min: number; readonly max: number }\n // Style predicates\n | { readonly kind: 'isBold' }\n | { readonly kind: 'isItalic' }\n | { readonly kind: 'hasHyperlink' }\n | { readonly kind: 'hasComment' }\n // Composition\n | {\n readonly kind: 'and'\n readonly left: CellPredicateSpec\n readonly right: CellPredicateSpec\n }\n | {\n readonly kind: 'or'\n readonly left: CellPredicateSpec\n readonly right: CellPredicateSpec\n }\n | { readonly kind: 'not'; readonly operand: CellPredicateSpec }\n\n// ---------------------------------------------------------------------------\n// SheetPredicateSpec — discriminated union\n// ---------------------------------------------------------------------------\n\nexport type SheetPredicateSpec =\n | { readonly kind: 'nameEquals'; readonly name: string }\n | { readonly kind: 'nameContains'; readonly text: string }\n | { readonly kind: 'nameStartsWith'; readonly prefix: string }\n | { readonly kind: 'nameEndsWith'; readonly suffix: string }\n | {\n readonly kind: 'nameMatches'\n readonly pattern: string\n readonly flags: string\n }\n // Composition\n | {\n readonly kind: 'and'\n readonly left: SheetPredicateSpec\n readonly right: SheetPredicateSpec\n }\n | {\n readonly kind: 'or'\n readonly left: SheetPredicateSpec\n readonly right: SheetPredicateSpec\n }\n | { readonly kind: 'not'; readonly operand: SheetPredicateSpec }\n\n// ---------------------------------------------------------------------------\n// CellPred wrapper\n// ---------------------------------------------------------------------------\n\nexport interface CellPred {\n readonly _spec: CellPredicateSpec\n and(other: CellPred): CellPred\n or(other: CellPred): CellPred\n not(): CellPred\n describe(): string\n}\n\nfunction wrapCell(spec: CellPredicateSpec): CellPred {\n return {\n _spec: spec,\n and(other: CellPred): CellPred {\n return wrapCell({ kind: 'and', left: spec, right: other._spec })\n },\n or(other: CellPred): CellPred {\n return wrapCell({ kind: 'or', left: spec, right: other._spec })\n },\n not(): CellPred {\n return wrapCell({ kind: 'not', operand: spec })\n },\n describe(): string {\n return describeCellPredicate(spec)\n },\n }\n}\n\n// ---------------------------------------------------------------------------\n// SheetPred wrapper\n// ---------------------------------------------------------------------------\n\nexport interface SheetPred {\n readonly _spec: SheetPredicateSpec\n and(other: SheetPred): SheetPred\n or(other: SheetPred): SheetPred\n not(): SheetPred\n describe(): string\n}\n\nfunction wrapSheet(spec: SheetPredicateSpec): SheetPred {\n return {\n _spec: spec,\n and(other: SheetPred): SheetPred {\n return wrapSheet({ kind: 'and', left: spec, right: other._spec })\n },\n or(other: SheetPred): SheetPred {\n return wrapSheet({ kind: 'or', left: spec, right: other._spec })\n },\n not(): SheetPred {\n return wrapSheet({ kind: 'not', operand: spec })\n },\n describe(): string {\n return describeSheetPredicate(spec)\n },\n }\n}\n\n// ---------------------------------------------------------------------------\n// cell factory namespace\n// ---------------------------------------------------------------------------\n\nfunction formatCellValue(value: CellValue): string {\n if (value === null) return 'null'\n if (value instanceof Date) return `Date(${value.toISOString()})`\n if (typeof value === 'string') return `'${value}'`\n return String(value)\n}\n\nexport const cell = Object.freeze({\n // Value predicates\n equals: (value: CellValue): CellPred => wrapCell({ kind: 'equals', value }),\n contains: (text: string, caseSensitive: boolean = false): CellPred =>\n wrapCell({ kind: 'contains', text, caseSensitive }),\n matches: (pattern: RegExp): CellPred =>\n wrapCell({\n kind: 'matches',\n pattern: pattern.source,\n flags: pattern.flags,\n }),\n startsWith: (prefix: string, caseSensitive: boolean = false): CellPred =>\n wrapCell({ kind: 'startsWith', prefix, caseSensitive }),\n endsWith: (suffix: string, caseSensitive: boolean = false): CellPred =>\n wrapCell({ kind: 'endsWith', suffix, caseSensitive }),\n\n // Type predicates\n isString: (): CellPred => wrapCell({ kind: 'isString' }),\n isNumber: (): CellPred => wrapCell({ kind: 'isNumber' }),\n isBoolean: (): CellPred => wrapCell({ kind: 'isBoolean' }),\n isDate: (): CellPred => wrapCell({ kind: 'isDate' }),\n isEmpty: (): CellPred => wrapCell({ kind: 'isEmpty' }),\n isNotEmpty: (): CellPred => wrapCell({ kind: 'isNotEmpty' }),\n isFormula: (): CellPred => wrapCell({ kind: 'isFormula' }),\n isError: (): CellPred => wrapCell({ kind: 'isError' }),\n isMerged: (): CellPred => wrapCell({ kind: 'isMerged' }),\n\n // Numeric predicates\n gt: (value: number): CellPred => wrapCell({ kind: 'gt', value }),\n gte: (value: number): CellPred => wrapCell({ kind: 'gte', value }),\n lt: (value: number): CellPred => wrapCell({ kind: 'lt', value }),\n lte: (value: number): CellPred => wrapCell({ kind: 'lte', value }),\n between: (min: number, max: number): CellPred =>\n wrapCell({ kind: 'between', min, max }),\n\n // Style predicates\n isBold: (): CellPred => wrapCell({ kind: 'isBold' }),\n isItalic: (): CellPred => wrapCell({ kind: 'isItalic' }),\n hasHyperlink: (): CellPred => wrapCell({ kind: 'hasHyperlink' }),\n hasComment: (): CellPred => wrapCell({ kind: 'hasComment' }),\n})\n\n// ---------------------------------------------------------------------------\n// sheet factory namespace\n// ---------------------------------------------------------------------------\n\nexport const sheet = Object.freeze({\n nameEquals: (name: string): SheetPred =>\n wrapSheet({ kind: 'nameEquals', name }),\n nameContains: (text: string): SheetPred =>\n wrapSheet({ kind: 'nameContains', text }),\n nameStartsWith: (prefix: string): SheetPred =>\n wrapSheet({ kind: 'nameStartsWith', prefix }),\n nameEndsWith: (suffix: string): SheetPred =>\n wrapSheet({ kind: 'nameEndsWith', suffix }),\n nameMatches: (pattern: RegExp): SheetPred =>\n wrapSheet({\n kind: 'nameMatches',\n pattern: pattern.source,\n flags: pattern.flags,\n }),\n})\n\n// ---------------------------------------------------------------------------\n// describe functions\n// ---------------------------------------------------------------------------\n\nexport function describeCellPredicate(spec: CellPredicateSpec): string {\n switch (spec.kind) {\n case 'equals':\n return `equals(${formatCellValue(spec.value)})`\n case 'contains':\n return `contains('${spec.text}')`\n case 'matches':\n return `matches(/${spec.pattern}/${spec.flags})`\n case 'startsWith':\n return `startsWith('${spec.prefix}')`\n case 'endsWith':\n return `endsWith('${spec.suffix}')`\n case 'isString':\n return 'isString()'\n case 'isNumber':\n return 'isNumber()'\n case 'isBoolean':\n return 'isBoolean()'\n case 'isDate':\n return 'isDate()'\n case 'isEmpty':\n return 'isEmpty()'\n case 'isNotEmpty':\n return 'isNotEmpty()'\n case 'isFormula':\n return 'isFormula()'\n case 'isError':\n return 'isError()'\n case 'isMerged':\n return 'isMerged()'\n case 'gt':\n return `gt(${spec.value})`\n case 'gte':\n return `gte(${spec.value})`\n case 'lt':\n return `lt(${spec.value})`\n case 'lte':\n return `lte(${spec.value})`\n case 'between':\n return `between(${spec.min}, ${spec.max})`\n case 'isBold':\n return 'isBold()'\n case 'isItalic':\n return 'isItalic()'\n case 'hasHyperlink':\n return 'hasHyperlink()'\n case 'hasComment':\n return 'hasComment()'\n case 'and':\n return `${describeCellPredicate(spec.left)} AND ${describeCellPredicate(spec.right)}`\n case 'or':\n return `${describeCellPredicate(spec.left)} OR ${describeCellPredicate(spec.right)}`\n case 'not':\n return `NOT(${describeCellPredicate(spec.operand)})`\n }\n}\n\n// ---------------------------------------------------------------------------\n// RowPredicateSpec — discriminated union\n// ---------------------------------------------------------------------------\n\nexport type RowPredicateSpec =\n | {\n readonly kind: 'rowCol'\n readonly offset: number\n readonly predicate: CellPredicateSpec\n }\n | {\n readonly kind: 'and'\n readonly left: RowPredicateSpec\n readonly right: RowPredicateSpec\n }\n | {\n readonly kind: 'or'\n readonly left: RowPredicateSpec\n readonly right: RowPredicateSpec\n }\n | { readonly kind: 'not'; readonly operand: RowPredicateSpec }\n\n// ---------------------------------------------------------------------------\n// RowPred wrapper\n// ---------------------------------------------------------------------------\n\nexport interface RowPred {\n readonly _spec: RowPredicateSpec\n and(other: RowPred): RowPred\n or(other: RowPred): RowPred\n not(): RowPred\n describe(): string\n}\n\nfunction wrapRow(spec: RowPredicateSpec): RowPred {\n return {\n _spec: spec,\n and(other: RowPred): RowPred {\n return wrapRow({ kind: 'and', left: spec, right: other._spec })\n },\n or(other: RowPred): RowPred {\n return wrapRow({ kind: 'or', left: spec, right: other._spec })\n },\n not(): RowPred {\n return wrapRow({ kind: 'not', operand: spec })\n },\n describe(): string {\n return describeRowPredicate(spec)\n },\n }\n}\n\nexport function rowCol(offset: number, predicate: CellPred): RowPred {\n return wrapRow({ kind: 'rowCol', offset, predicate: predicate._spec })\n}\n\nexport function describeRowPredicate(spec: RowPredicateSpec): string {\n switch (spec.kind) {\n case 'rowCol':\n return `rowCol(${spec.offset}, ${describeCellPredicate(spec.predicate)})`\n case 'and':\n return `${describeRowPredicate(spec.left)} AND ${describeRowPredicate(spec.right)}`\n case 'or':\n return `${describeRowPredicate(spec.left)} OR ${describeRowPredicate(spec.right)}`\n case 'not':\n return `NOT(${describeRowPredicate(spec.operand)})`\n }\n}\n\n// ---------------------------------------------------------------------------\n// describe functions\n// ---------------------------------------------------------------------------\n\nexport function describeSheetPredicate(spec: SheetPredicateSpec): string {\n switch (spec.kind) {\n case 'nameEquals':\n return `nameEquals('${spec.name}')`\n case 'nameContains':\n return `nameContains('${spec.text}')`\n case 'nameStartsWith':\n return `nameStartsWith('${spec.prefix}')`\n case 'nameEndsWith':\n return `nameEndsWith('${spec.suffix}')`\n case 'nameMatches':\n return `nameMatches(/${spec.pattern}/${spec.flags})`\n case 'and':\n return `${describeSheetPredicate(spec.left)} AND ${describeSheetPredicate(spec.right)}`\n case 'or':\n return `${describeSheetPredicate(spec.left)} OR ${describeSheetPredicate(spec.right)}`\n case 'not':\n return `NOT(${describeSheetPredicate(spec.operand)})`\n }\n}\n","/**\n * Runtime executor for XlsxSpec — walks spec steps against an XlsxWorkbook.\n *\n * Uses a state-machine approach: each step transitions the navigation state\n * through workbook → sheet → range → cell levels.\n *\n * The executor is polymorphic — it accepts XlsxWorkbook, XlsxRange, or XlsxCell\n * as input, starting at the appropriate navigation level.\n *\n * @module xlsx/xlsx-spec-executor\n */\n\nimport { TYPE_LABEL } from '@origints/core'\nimport type { ExtractionResult } from '@origints/core'\nimport type {\n XlsxSpec,\n XlsxStep,\n XlsxExtract,\n Direction,\n EachCellExtract,\n} from './xlsx-spec'\nimport type { XlsxWorkbook } from './xlsx-workbook'\nimport type { XlsxSheet } from './xlsx-sheet'\nimport { XlsxRange } from './xlsx-range'\nimport { XlsxCell } from './xlsx-cell'\nimport type { XlsxResult } from './xlsx-result'\nimport type { CellPredicateSpec, RowPredicateSpec } from './xlsx-predicate-spec'\nimport {\n compileCellPredicate,\n compileSheetPredicate,\n compileRowPredicate,\n} from './xlsx-predicate-compiler'\nimport {\n describeCellPredicate,\n describeSheetPredicate,\n} from './xlsx-predicate-spec'\n\n// ---------------------------------------------------------------------------\n// Header lookup caches — WeakMap keyed by XlsxSheet, inner Map keyed by serialized step\n// ---------------------------------------------------------------------------\n\nconst colWhereCache = new WeakMap<XlsxSheet, Map<string, number>>()\nconst rowWhereCache = new WeakMap<XlsxSheet, Map<string, number>>()\n\n// ---------------------------------------------------------------------------\n// Navigation state\n// ---------------------------------------------------------------------------\n\ntype NavState =\n | { level: 'workbook'; workbook: XlsxWorkbook }\n | { level: 'sheet'; workbook: XlsxWorkbook; sheet: XlsxSheet }\n | {\n level: 'range'\n workbook: XlsxWorkbook\n sheet: XlsxSheet\n range: XlsxRange\n }\n | { level: 'cell'; workbook: XlsxWorkbook; sheet: XlsxSheet; cell: XlsxCell }\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction success<T>(value: T): ExtractionResult<T> {\n return { ok: true, value, path: [] }\n}\n\nfunction failure(message: string): ExtractionResult<never> {\n return { ok: false, kind: 'format', message, path: [] }\n}\n\nfunction failureWithPath(\n message: string,\n path: readonly string[]\n): ExtractionResult<never> {\n return { ok: false, kind: 'format', message, path: [...path] }\n}\n\nfunction unwrap<T>(\n result: XlsxResult<T>,\n stepDesc: string\n): T | ExtractionResult<never> {\n if (result.ok) return result.value\n return failure(\n `XLSX navigation failed at ${stepDesc}: ${result.failure.message}`\n )\n}\n\n// ---------------------------------------------------------------------------\n// NavigateSuccess — returned by navigate() with breadcrumbs\n// ---------------------------------------------------------------------------\n\ninterface NavigateSuccess {\n readonly state: NavState\n readonly breadcrumbs: readonly string[]\n}\n\n// ---------------------------------------------------------------------------\n// describeStep — human-readable description of a navigation step\n// ---------------------------------------------------------------------------\n\nfunction describeStep(step: XlsxStep): string {\n switch (step.kind) {\n case 'sheet':\n return `sheet(\"${step.name}\")`\n case 'sheetAt':\n return `sheetAt(${step.index})`\n case 'firstSheet':\n return 'firstSheet()'\n case 'findSheet':\n return `findSheet(${describeSheetPredicate(step.predicate)})`\n case 'cell':\n return `cell(\"${step.ref}\")`\n case 'cellAt':\n return `cellAt(${step.row}, ${step.col})`\n case 'find':\n return `find(${describeCellPredicate(step.predicate)})`\n case 'findInRow':\n return `findInRow(${step.rowIndex}, ${describeCellPredicate(step.predicate)})`\n case 'findInCol':\n return `findInCol(${step.colIndex}, ${describeCellPredicate(step.predicate)})`\n case 'findInRange':\n return `findInRange(\"${step.rangeRef}\", ${describeCellPredicate(step.predicate)})`\n case 'right':\n return `right(${step.count})`\n case 'left':\n return `left(${step.count})`\n case 'up':\n return `up(${step.count})`\n case 'down':\n return `down(${step.count})`\n case 'offset':\n return `offset(${step.rowDelta}, ${step.colDelta})`\n case 'scanTo':\n return `scanTo(${step.direction}, ${describeCellPredicate(step.predicate)})`\n case 'skipWhile':\n return `skipWhile(${step.direction}, ${describeCellPredicate(step.predicate)})`\n case 'colWhere':\n return `colWhere(${describeCellPredicate(step.predicate)})`\n case 'rowWhere':\n return `rowWhere(${describeCellPredicate(step.predicate)})`\n case 'range':\n return `range(\"${step.ref}\")`\n case 'rangeFromCells':\n return 'rangeFromCells()'\n case 'row':\n return `row(${step.index})`\n case 'col':\n return `col(${step.index})`\n }\n}\n\nfunction isFailure(value: unknown): value is ExtractionResult<never> {\n return (\n typeof value === 'object' &&\n value !== null &&\n 'ok' in value &&\n !(value as { ok: boolean }).ok\n )\n}\n\n// ---------------------------------------------------------------------------\n// Slice context (for eachSlice items)\n// ---------------------------------------------------------------------------\n\n/**\n * Context wrapper for slice items.\n * Carries workbook+sheet references so colWhere/rowWhere can resolve headers.\n */\nexport class XlsxSliceContext {\n get [TYPE_LABEL]() {\n return 'XlsxSliceContext'\n }\n constructor(\n readonly workbook: XlsxWorkbook,\n readonly sheet: XlsxSheet,\n readonly anchorCell: XlsxCell\n ) {}\n}\n\n// ---------------------------------------------------------------------------\n// Input type detection\n// ---------------------------------------------------------------------------\n\nfunction detectInputLevel(\n data: unknown\n): 'workbook' | 'range' | 'cell' | 'sliceContext' | null {\n if (data == null || typeof data !== 'object') return null\n const label = (data as Record<symbol, unknown>)[TYPE_LABEL]\n if (typeof label === 'string') {\n if (label === 'XlsxSliceContext') return 'sliceContext'\n if (label.startsWith('XlsxWorkbook')) return 'workbook'\n if (label.startsWith('XlsxRange')) return 'range'\n if (label.startsWith('XlsxCell')) return 'cell'\n }\n // Fallback: check instanceof\n if (data instanceof XlsxRange) return 'range'\n if (data instanceof XlsxCell) return 'cell'\n return 'workbook'\n}\n\n// ---------------------------------------------------------------------------\n// Direction helpers for scan/skip\n// ---------------------------------------------------------------------------\n\nfunction directionDelta(direction: Direction): {\n rowDelta: number\n colDelta: number\n} {\n switch (direction) {\n case 'right':\n return { rowDelta: 0, colDelta: 1 }\n case 'left':\n return { rowDelta: 0, colDelta: -1 }\n case 'down':\n return { rowDelta: 1, colDelta: 0 }\n case 'up':\n return { rowDelta: -1, colDelta: 0 }\n }\n}\n\nfunction scanCells(\n sheet: XlsxSheet,\n startRow: number,\n startCol: number,\n direction: Direction,\n predicateSpec: CellPredicateSpec,\n mode: 'scanTo' | 'skipWhile'\n): XlsxCell | ExtractionResult<never> {\n const predicate = compileCellPredicate(predicateSpec)\n const { rowDelta, colDelta } = directionDelta(direction)\n const dims = sheet.dimensions()\n const maxIterations = Math.max(dims.rowCount, dims.colCount) * 2\n\n // Start from the NEXT cell in the direction (advance once)\n let row = startRow + rowDelta\n let col = startCol + colDelta\n\n for (let i = 0; i < maxIterations; i++) {\n if (row < 1 || col < 1) break\n if (row > dims.endRow + 1 || col > dims.endCol + 1) break\n\n const cellResult = sheet.cellAt(row, col)\n if (!cellResult.ok) break\n\n const cell = cellResult.value\n if (mode === 'scanTo') {\n // Land on first matching cell\n if (predicate(cell)) return cell\n } else {\n // skipWhile: land on first non-matching cell\n if (!predicate(cell)) return cell\n }\n\n row += rowDelta\n col += colDelta\n }\n\n const desc = describeCellPredicate(predicateSpec)\n if (mode === 'scanTo') {\n return failure(`scanTo(${direction}): no cell matching ${desc} found`)\n }\n return failure(\n `skipWhile(${direction}): predicate ${desc} never stopped matching`\n )\n}\n\n// ---------------------------------------------------------------------------\n// Gather cells from a starting cell in a direction\n// ---------------------------------------------------------------------------\n\nfunction gatherCells(\n sheet: XlsxSheet,\n startRow: number,\n startCol: number,\n direction: Direction,\n predicateSpec: CellPredicateSpec\n): XlsxCell[] {\n const predicate = compileCellPredicate(predicateSpec)\n const { rowDelta, colDelta } = directionDelta(direction)\n const dims = sheet.dimensions()\n const maxIterations = Math.max(dims.rowCount, dims.colCount) * 2\n const result: XlsxCell[] = []\n\n let row = startRow\n let col = startCol\n\n for (let i = 0; i < maxIterations; i++) {\n if (row < 1 || col < 1) break\n if (row > dims.endRow + 1 || col > dims.endCol + 1) break\n\n const cellResult = sheet.cellAt(row, col)\n if (!cellResult.ok) break\n\n const cell = cellResult.value\n if (!predicate(cell)) break\n\n result.push(cell)\n row += rowDelta\n col += colDelta\n }\n\n return result\n}\n\n// ---------------------------------------------------------------------------\n// Gather slices from a starting cell in a direction\n// ---------------------------------------------------------------------------\n\nfunction gatherSlices(\n workbook: XlsxWorkbook,\n sheet: XlsxSheet,\n startRow: number,\n startCol: number,\n direction: Direction,\n predicateSpec: RowPredicateSpec\n): XlsxSliceContext[] {\n const predicate = compileRowPredicate(predicateSpec)\n const { rowDelta, colDelta } = directionDelta(direction)\n const dims = sheet.dimensions()\n const maxIterations = Math.max(dims.rowCount, dims.colCount) * 2\n const result: XlsxSliceContext[] = []\n\n let row = startRow\n let col = startCol\n\n for (let i = 0; i < maxIterations; i++) {\n if (row < 1 || col < 1) break\n if (row > dims.endRow + 1 || col > dims.endCol + 1) break\n\n if (!predicate(sheet, row, col)) break\n\n const cellResult = sheet.cellAt(row, col)\n if (!cellResult.ok) break\n result.push(new XlsxSliceContext(workbook, sheet, cellResult.value))\n\n row += rowDelta\n col += colDelta\n }\n\n return result\n}\n\n// ---------------------------------------------------------------------------\n// Navigate through steps\n// ---------------------------------------------------------------------------\n\nfunction navigate(\n initialState: NavState,\n steps: readonly XlsxStep[]\n): NavigateSuccess | ExtractionResult<never> {\n let state = initialState\n const breadcrumbs: string[] = []\n\n /** Append a breadcrumb, annotating with cell address if state is at cell level */\n function pushBreadcrumb(desc: string, s: NavState): void {\n if (s.level === 'cell') {\n breadcrumbs.push(`${desc}@${s.cell.address}`)\n } else {\n breadcrumbs.push(desc)\n }\n }\n\n /** Return a failure with the breadcrumbs collected so far (plus a failing step description) */\n function failNav(\n message: string,\n failingStep?: XlsxStep\n ): ExtractionResult<never> {\n const path = [...breadcrumbs]\n if (failingStep) path.push(describeStep(failingStep))\n return failureWithPath(message, path)\n }\n\n /** Extract failure message from an ExtractionResult that isFailure() confirmed is a failure */\n function failMsg(result: ExtractionResult<never>): string {\n return (result as { message: string }).message\n }\n\n for (const step of steps) {\n const desc = describeStep(step)\n switch (step.kind) {\n // ----- Workbook → Sheet -----\n case 'sheet': {\n const result = unwrap(state.workbook.sheet(step.name), desc)\n if (isFailure(result)) return failNav(failMsg(result), step)\n state = {\n level: 'sheet',\n workbook: state.workbook,\n sheet: result as XlsxSheet,\n }\n pushBreadcrumb(desc, state)\n break\n }\n case 'sheetAt': {\n const result = unwrap(state.workbook.sheetAt(step.index), desc)\n if (isFailure(result)) return failNav(failMsg(result), step)\n state = {\n level: 'sheet',\n workbook: state.workbook,\n sheet: result as XlsxSheet,\n }\n pushBreadcrumb(desc, state)\n break\n }\n case 'firstSheet': {\n const result = unwrap(state.workbook.firstSheet(), desc)\n if (isFailure(result)) return failNav(failMsg(result), step)\n state = {\n level: 'sheet',\n workbook: state.workbook,\n sheet: result as XlsxSheet,\n }\n pushBreadcrumb(desc, state)\n break\n }\n case 'findSheet': {\n const pred = compileSheetPredicate(step.predicate)\n const result = unwrap(state.workbook.findSheet(pred), desc)\n if (isFailure(result)) return failNav(failMsg(result), step)\n state = {\n level: 'sheet',\n workbook: state.workbook,\n sheet: result as XlsxSheet,\n }\n pushBreadcrumb(desc, state)\n break\n }\n\n // ----- Sheet → Cell (direct) -----\n case 'cell': {\n if (state.level === 'workbook')\n return failNav('cell() called without a sheet navigation step', step)\n if (state.level === 'range') {\n const r = unwrap(state.range.cell(step.ref), desc)\n if (isFailure(r)) return failNav(failMsg(r), step)\n state = {\n level: 'cell',\n workbook: state.workbook,\n sheet: state.sheet,\n cell: r as XlsxCell,\n }\n pushBreadcrumb(desc, state)\n break\n }\n const currentSheet: XlsxSheet = state.sheet\n const result = unwrap(currentSheet.cell(step.ref), desc)\n if (isFailure(result)) return failNav(failMsg(result), step)\n state = {\n level: 'cell',\n workbook: state.workbook,\n sheet: currentSheet,\n cell: result as XlsxCell,\n }\n pushBreadcrumb(desc, state)\n break\n }\n case 'cellAt': {\n if (state.level === 'workbook')\n return failNav(\n 'cellAt() called without a sheet navigation step',\n step\n )\n if (state.level === 'range') {\n const r = unwrap(state.range.cellAt(step.row, step.col), desc)\n if (isFailure(r)) return failNav(failMsg(r), step)\n state = {\n level: 'cell',\n workbook: state.workbook,\n sheet: state.sheet,\n cell: r as XlsxCell,\n }\n pushBreadcrumb(desc, state)\n break\n }\n const currentSheet: XlsxSheet = state.sheet\n const result = unwrap(currentSheet.cellAt(step.row, step.col), desc)\n if (isFailure(result)) return failNav(failMsg(result), step)\n state = {\n level: 'cell',\n workbook: state.workbook,\n sheet: currentSheet,\n cell: result as XlsxCell,\n }\n pushBreadcrumb(desc, state)\n break\n }\n\n // ----- Sheet → Cell (search) -----\n case 'find': {\n if (state.level !== 'sheet')\n return failNav('find() requires sheet-level navigation state', step)\n const s: XlsxSheet = state.sheet\n const pred = compileCellPredicate(step.predicate)\n const r: XlsxCell | ExtractionResult<never> = unwrap(s.find(pred), desc)\n if (isFailure(r))\n return failNav(failMsg(r as ExtractionResult<never>), step)\n state = { level: 'cell', workbook: state.workbook, sheet: s, cell: r }\n pushBreadcrumb(desc, state)\n break\n }\n case 'findInRow': {\n if (state.level !== 'sheet')\n return failNav(\n 'findInRow() requires sheet-level navigation state',\n step\n )\n const s: XlsxSheet = state.sheet\n const pred = compileCellPredicate(step.predicate)\n const dims = s.dimensions()\n const endCol = Math.max(dims.endCol, 1)\n let found: XlsxCell | null = null\n for (let col = 1; col <= endCol; col++) {\n const cr: XlsxResult<XlsxCell> = s.cellAt(step.rowIndex, col)\n if (cr.ok && pred(cr.value)) {\n found = cr.value\n break\n }\n }\n if (!found) {\n return failNav(\n `findInRow(${step.rowIndex}): no cell matching ${describeCellPredicate(step.predicate)} found`,\n step\n )\n }\n state = {\n level: 'cell',\n workbook: state.workbook,\n sheet: s,\n cell: found,\n }\n pushBreadcrumb(desc, state)\n break\n }\n case 'findInCol': {\n if (state.level !== 'sheet')\n return failNav(\n 'findInCol() requires sheet-level navigation state',\n step\n )\n const s: XlsxSheet = state.sheet\n const pred = compileCellPredicate(step.predicate)\n const dims = s.dimensions()\n const endRow = Math.max(dims.endRow, 1)\n let found: XlsxCell | null = null\n for (let row = 1; row <= endRow; row++) {\n const cr: XlsxResult<XlsxCell> = s.cellAt(row, step.colIndex)\n if (cr.ok && pred(cr.value)) {\n found = cr.value\n break\n }\n }\n if (!found) {\n return failNav(\n `findInCol(${step.colIndex}): no cell matching ${describeCellPredicate(step.predicate)} found`,\n step\n )\n }\n state = {\n level: 'cell',\n workbook: state.workbook,\n sheet: s,\n cell: found,\n }\n pushBreadcrumb(desc, state)\n break\n }\n case 'findInRange': {\n if (state.level !== 'sheet')\n return failNav(\n 'findInRange() requires sheet-level navigation state',\n step\n )\n const s: XlsxSheet = state.sheet\n const pred = compileCellPredicate(step.predicate)\n const r: XlsxCell | ExtractionResult<never> = unwrap(\n s.findInRange(step.rangeRef, pred),\n desc\n )\n if (isFailure(r))\n return failNav(failMsg(r as ExtractionResult<never>), step)\n state = { level: 'cell', workbook: state.workbook, sheet: s, cell: r }\n pushBreadcrumb(desc, state)\n break\n }\n\n // ----- Cell → Cell (relative movement) -----\n case 'right': {\n if (state.level !== 'cell')\n return failNav('right() requires cell-level navigation state', step)\n const s: XlsxSheet = state.sheet\n const r: XlsxCell | ExtractionResult<never> = unwrap(\n s.cellAt(state.cell.row, state.cell.col + step.count),\n desc\n )\n if (isFailure(r))\n return failNav(failMsg(r as ExtractionResult<never>), step)\n state = { level: 'cell', workbook: state.workbook, sheet: s, cell: r }\n pushBreadcrumb(desc, state)\n break\n }\n case 'left': {\n if (state.level !== 'cell')\n return failNav('left() requires cell-level navigation state', step)\n const s: XlsxSheet = state.sheet\n const newCol: number = state.cell.col - step.count\n if (newCol < 1)\n return failNav(\n `left(${step.count}) from column ${state.cell.col} goes out of bounds`,\n step\n )\n const r: XlsxCell | ExtractionResult<never> = unwrap(\n s.cellAt(state.cell.row, newCol),\n desc\n )\n if (isFailure(r))\n return failNav(failMsg(r as ExtractionResult<never>), step)\n state = { level: 'cell', workbook: state.workbook, sheet: s, cell: r }\n pushBreadcrumb(desc, state)\n break\n }\n case 'up': {\n if (state.level !== 'cell')\n return failNav('up() requires cell-level navigation state', step)\n const s: XlsxSheet = state.sheet\n const newRow: number = state.cell.row - step.count\n if (newRow < 1)\n return failNav(\n `up(${step.count}) from row ${state.cell.row} goes out of bounds`,\n step\n )\n const r: XlsxCell | ExtractionResult<never> = unwrap(\n s.cellAt(newRow, state.cell.col),\n desc\n )\n if (isFailure(r))\n return failNav(failMsg(r as ExtractionResult<never>), step)\n state = { level: 'cell', workbook: state.workbook, sheet: s, cell: r }\n pushBreadcrumb(desc, state)\n break\n }\n case 'down': {\n if (state.level !== 'cell')\n return failNav('down() requires cell-level navigation state', step)\n const s: XlsxSheet = state.sheet\n const r: XlsxCell | ExtractionResult<never> = unwrap(\n s.cellAt(state.cell.row + step.count, state.cell.col),\n desc\n )\n if (isFailure(r))\n return failNav(failMsg(r as ExtractionResult<never>), step)\n state = { level: 'cell', workbook: state.workbook, sheet: s, cell: r }\n pushBreadcrumb(desc, state)\n break\n }\n case 'offset': {\n if (state.level !== 'cell')\n return failNav('offset() requires cell-level navigation state', step)\n const s: XlsxSheet = state.sheet\n const newRow: number = state.cell.row + step.rowDelta\n const newCol: number = state.cell.col + step.colDelta\n if (newRow < 1 || newCol < 1) {\n return failNav(\n `offset(${step.rowDelta}, ${step.colDelta}) from ${state.cell.address} goes out of bounds`,\n step\n )\n }\n const r: XlsxCell | ExtractionResult<never> = unwrap(\n s.cellAt(newRow, newCol),\n desc\n )\n if (isFailure(r))\n return failNav(failMsg(r as ExtractionResult<never>), step)\n state = { level: 'cell', workbook: state.workbook, sheet: s, cell: r }\n pushBreadcrumb(desc, state)\n break\n }\n\n // ----- Cell → Cell (scan) -----\n case 'scanTo': {\n if (state.level !== 'cell')\n return failNav('scanTo() requires cell-level navigation state', step)\n const s: XlsxSheet = state.sheet\n const cellOrFailure = scanCells(\n s,\n state.cell.row,\n state.cell.col,\n step.direction,\n step.predicate,\n 'scanTo'\n )\n if (isFailure(cellOrFailure))\n return failNav(\n failMsg(cellOrFailure as ExtractionResult<never>),\n step\n )\n state = {\n level: 'cell',\n workbook: state.workbook,\n sheet: s,\n cell: cellOrFailure as XlsxCell,\n }\n pushBreadcrumb(desc, state)\n break\n }\n case 'skipWhile': {\n if (state.level !== 'cell')\n return failNav(\n 'skipWhile() requires cell-level navigation state',\n step\n )\n const s: XlsxSheet = state.sheet\n const cellOrFailure = scanCells(\n s,\n state.cell.row,\n state.cell.col,\n step.direction,\n step.predicate,\n 'skipWhile'\n )\n if (isFailure(cellOrFailure))\n return failNav(\n failMsg(cellOrFailure as ExtractionResult<never>),\n step\n )\n state = {\n level: 'cell',\n workbook: state.workbook,\n sheet: s,\n cell: cellOrFailure as XlsxCell,\n }\n pushBreadcrumb(desc, state)\n break\n }\n\n // ----- Sheet → Range -----\n case 'range': {\n if (state.level !== 'sheet')\n return failNav('range() requires sheet-level navigation state', step)\n const s: XlsxSheet = state.sheet\n const r = unwrap(s.range(step.ref), desc)\n if (isFailure(r)) return failNav(failMsg(r), step)\n state = {\n level: 'range',\n workbook: state.workbook,\n sheet: s,\n range: r as XlsxRange,\n }\n pushBreadcrumb(desc, state)\n break\n }\n case 'rangeFromCells': {\n if (state.level !== 'sheet')\n return failNav(\n 'rangeFromCells requires sheet-level navigation state',\n step\n )\n const s: XlsxSheet = state.sheet\n const fromNav = navigate(\n { level: 'workbook', workbook: state.workbook },\n (step.from as XlsxSpec).steps\n )\n if (isFailure(fromNav))\n return failNav(failMsg(fromNav as ExtractionResult<never>), step)\n const fromSuccess = fromNav as NavigateSuccess\n if (fromSuccess.state.level !== 'cell')\n return failNav(\n 'rangeFromCells: \"from\" did not resolve to a cell',\n step\n )\n const fromCell = (\n fromSuccess.state as { level: 'cell'; cell: XlsxCell }\n ).cell\n const toNav = navigate(\n { level: 'workbook', workbook: state.workbook },\n (step.to as XlsxSpec).steps\n )\n if (isFailure(toNav))\n return failNav(failMsg(toNav as ExtractionResult<never>), step)\n const toSuccess = toNav as NavigateSuccess\n if (toSuccess.state.level !== 'cell')\n return failNav('rangeFromCells: \"to\" did not resolve to a cell', step)\n const toCell = (toSuccess.state as { level: 'cell'; cell: XlsxCell })\n .cell\n const r = unwrap(\n s.rangeAt(fromCell.row, fromCell.col, toCell.row, toCell.col),\n desc\n )\n if (isFailure(r)) return failNav(failMsg(r), step)\n state = {\n level: 'range',\n workbook: state.workbook,\n sheet: s,\n range: r as XlsxRange,\n }\n pushBreadcrumb(desc, state)\n break\n }\n case 'row': {\n if (state.level !== 'sheet')\n return failNav('row() requires sheet-level navigation state', step)\n const s: XlsxSheet = state.sheet\n const r = unwrap(s.row(step.index), desc)\n if (isFailure(r)) return failNav(failMsg(r), step)\n state = {\n level: 'range',\n workbook: state.workbook,\n sheet: s,\n range: r as XlsxRange,\n }\n pushBreadcrumb(desc, state)\n break\n }\n case 'col': {\n if (state.level === 'range') {\n const r = unwrap(state.range.cellAt(0, step.index - 1), desc)\n if (isFailure(r)) return failNav(failMsg(r), step)\n state = {\n level: 'cell',\n workbook: state.workbook,\n sheet: state.sheet,\n cell: r as XlsxCell,\n }\n pushBreadcrumb(desc, state)\n break\n }\n if (state.level !== 'sheet')\n return failNav(\n 'col() requires sheet-level or range-level navigation state',\n step\n )\n const s: XlsxSheet = state.sheet\n const r = unwrap(s.col(step.index), desc)\n if (isFailure(r)) return failNav(failMsg(r), step)\n state = {\n level: 'range',\n workbook: state.workbook,\n sheet: s,\n range: r as XlsxRange,\n }\n pushBreadcrumb(desc, state)\n break\n }\n\n // ----- Header-relative navigation -----\n case 'colWhere': {\n if (state.level !== 'cell')\n return failNav(\n 'colWhere() requires cell-level navigation state',\n step\n )\n const s = state.sheet\n // Check cache first\n const cacheKey = JSON.stringify(step)\n let sheetCache = colWhereCache.get(s)\n let foundCol: number | null = sheetCache?.get(cacheKey) ?? null\n if (foundCol === null) {\n // 1. Navigate headerRef to reach the header anchor cell\n const headerSpec = step.headerRef as XlsxSpec\n const headerNav = navigate(\n { level: 'workbook', workbook: state.workbook },\n headerSpec.steps\n )\n if (isFailure(headerNav))\n return failNav(failMsg(headerNav as ExtractionResult<never>), step)\n const headerSuccess = headerNav as NavigateSuccess\n if (headerSuccess.state.level !== 'cell') {\n return failNav(\n 'colWhere: headerRef did not resolve to a cell',\n step\n )\n }\n const headerCell = (\n headerSuccess.state as { level: 'cell'; cell: XlsxCell }\n ).cell\n // 2. Scan the header row for the column matching the predicate\n const headerRow = headerCell.row\n const dims = s.dimensions()\n const colPred = compileCellPredicate(step.predicate)\n for (let c = 1; c <= dims.endCol; c++) {\n const cr = s.cellAt(headerRow, c)\n if (!cr.ok) continue\n if (colPred(cr.value)) {\n foundCol = c\n break\n }\n }\n if (foundCol === null) {\n const predDesc = describeCellPredicate(step.predicate)\n return failNav(\n `colWhere: no column matching ${predDesc} found in header row ${headerRow}`,\n step\n )\n }\n // Populate cache\n if (!sheetCache) {\n sheetCache = new Map()\n colWhereCache.set(s, sheetCache)\n }\n sheetCache.set(cacheKey, foundCol)\n }\n // 3. Navigate to (current row, found col)\n const targetResult = unwrap(s.cellAt(state.cell.row, foundCol), desc)\n if (isFailure(targetResult)) return failNav(failMsg(targetResult), step)\n state = {\n level: 'cell',\n workbook: state.workbook,\n sheet: s,\n cell: targetResult as XlsxCell,\n }\n pushBreadcrumb(desc, state)\n break\n }\n\n case 'rowWhere': {\n if (state.level !== 'cell')\n return failNav(\n 'rowWhere() requires cell-level navigation state',\n step\n )\n const s = state.sheet\n // Check cache first\n const cacheKey = JSON.stringify(step)\n let sheetCache = rowWhereCache.get(s)\n let foundRow: number | null = sheetCache?.get(cacheKey) ?? null\n if (foundRow === null) {\n // 1. Navigate headerRef to reach the header anchor cell\n const headerSpec = step.headerRef as XlsxSpec\n const headerNav = navigate(\n { level: 'workbook', workbook: state.workbook },\n headerSpec.steps\n )\n if (isFailure(headerNav))\n return failNav(failMsg(headerNav as ExtractionResult<never>), step)\n const headerSuccess = headerNav as NavigateSuccess\n if (headerSuccess.state.level !== 'cell') {\n return failNav(\n 'rowWhere: headerRef did not resolve to a cell',\n step\n )\n }\n const headerCell = (\n headerSuccess.state as { level: 'cell'; cell: XlsxCell }\n ).cell\n // 2. Scan the header column for the row matching the predicate\n const headerCol = headerCell.col\n const dims = s.dimensions()\n const rowPred = compileCellPredicate(step.predicate)\n for (let r = 1; r <= dims.endRow; r++) {\n const cr = s.cellAt(r, headerCol)\n if (!cr.ok) continue\n if (rowPred(cr.value)) {\n foundRow = r\n break\n }\n }\n if (foundRow === null) {\n const predDesc = describeCellPredicate(step.predicate)\n return failNav(\n `rowWhere: no row matching ${predDesc} found in header column ${headerCol}`,\n step\n )\n }\n // Populate cache\n if (!sheetCache) {\n sheetCache = new Map()\n rowWhereCache.set(s, sheetCache)\n }\n sheetCache.set(cacheKey, foundRow)\n }\n // 3. Navigate to (found row, current col)\n const targetResult = unwrap(s.cellAt(foundRow, state.cell.col), desc)\n if (isFailure(targetResult)) return failNav(failMsg(targetResult), step)\n state = {\n level: 'cell',\n workbook: state.workbook,\n sheet: s,\n cell: targetResult as XlsxCell,\n }\n pushBreadcrumb(desc, state)\n break\n }\n }\n }\n\n return { state, breadcrumbs }\n}\n\n// ---------------------------------------------------------------------------\n// Extract from cell\n// ---------------------------------------------------------------------------\n\nfunction extractFromCell(\n cell: XlsxCell,\n extract: XlsxExtract\n): ExtractionResult<unknown> {\n if (typeof extract !== 'string') {\n return failure(\n `Unexpected extract type on cell: ${JSON.stringify(extract)}`\n )\n }\n switch (extract) {\n case 'string': {\n const result = cell.string()\n if (result.ok) return success(result.value)\n return failure(`Failed to extract string: ${result.failure.message}`)\n }\n case 'number': {\n const result = cell.number()\n if (result.ok) return success(result.value)\n return failure(`Failed to extract number: ${result.failure.message}`)\n }\n case 'boolean': {\n const result = cell.boolean()\n if (result.ok) return success(result.value)\n return failure(`Failed to extract boolean: ${result.failure.message}`)\n }\n case 'date': {\n const result = cell.date()\n if (result.ok) return success(result.value)\n return failure(`Failed to extract date: ${result.failure.message}`)\n }\n case 'value': {\n const result = cell.value()\n if (result.ok) return success(result.value)\n return failure(`Failed to extract value: ${result.failure.message}`)\n }\n case 'formula': {\n const result = cell.formula()\n if (result.ok) return success(result.value)\n return failure(`Failed to extract formula: ${result.failure.message}`)\n }\n default:\n return failure(`Unknown cell extract type: ${extract}`)\n }\n}\n\n// ---------------------------------------------------------------------------\n// Extract from range (collection types)\n// ---------------------------------------------------------------------------\n\nfunction extractFromRange(\n range: XlsxRange,\n extract: XlsxExtract\n): ExtractionResult<unknown> {\n if (extract === 'rows') {\n // Produce an array of XlsxRange (one per row)\n const rows: XlsxRange[] = []\n for (let i = 0; i < range.rowCount; i++) {\n const rowResult = range.rowAt(i)\n if (!rowResult.ok) {\n return failure(\n `Failed to get row at offset ${i}: ${rowResult.failure.message}`\n )\n }\n rows.push(rowResult.value)\n }\n return success(rows)\n }\n\n if (extract === 'cells') {\n // Produce a flat array of XlsxCell\n return success(range.cellsArray())\n }\n\n return failure(\n `Extract type \"${typeof extract === 'string' ? extract : JSON.stringify(extract)}\" is not valid at range level`\n )\n}\n\n// ---------------------------------------------------------------------------\n// Extract from cell (eachCell)\n// ---------------------------------------------------------------------------\n\nfunction extractEachCell(\n sheet: XlsxSheet,\n cell: XlsxCell,\n extract: EachCellExtract\n): ExtractionResult<unknown> {\n const cells = gatherCells(\n sheet,\n cell.row,\n cell.col,\n extract.direction,\n extract.while\n )\n return success(cells)\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Execute an XlsxSpec against data.\n *\n * The executor is polymorphic — it detects the input type:\n * - XlsxWorkbook → starts at workbook level\n * - XlsxRange → starts at range level (used for row items)\n * - XlsxCell → starts at cell level (used for cell items)\n */\nexport function executeXlsxSpec(\n spec: XlsxSpec,\n data: unknown\n): ExtractionResult<unknown> {\n if (spec.kind !== 'extract' || spec.format !== 'xlsx') {\n return failure(\n `Expected extract spec with format \"xlsx\", got kind=\"${spec.kind}\" format=\"${spec.format}\"`\n )\n }\n\n // Determine initial navigation state based on input type\n const inputLevel = detectInputLevel(data)\n\n let initialState: NavState\n switch (inputLevel) {\n case 'range': {\n // For range input, we need a dummy workbook/sheet reference\n // The range itself carries the context needed\n const range = data as XlsxRange\n initialState = {\n level: 'range',\n workbook: null as unknown as XlsxWorkbook,\n sheet: null as unknown as XlsxSheet,\n range,\n }\n break\n }\n case 'cell': {\n const cell = data as XlsxCell\n initialState = {\n level: 'cell',\n workbook: null as unknown as XlsxWorkbook,\n sheet: null as unknown as XlsxSheet,\n cell,\n }\n break\n }\n case 'sliceContext': {\n const ctx = data as XlsxSliceContext\n initialState = {\n level: 'cell',\n workbook: ctx.workbook,\n sheet: ctx.sheet,\n cell: ctx.anchorCell,\n }\n break\n }\n default: {\n const workbook = data as XlsxWorkbook\n initialState = { level: 'workbook', workbook }\n break\n }\n }\n\n const navResult = navigate(initialState, spec.steps)\n if (isFailure(navResult)) {\n return navResult\n }\n\n const { state, breadcrumbs } = navResult as NavigateSuccess\n const extract = spec.extract\n\n /** Wrap a success result with the navigation breadcrumbs as path */\n function withPath<T>(result: ExtractionResult<T>): ExtractionResult<T> {\n if (result.ok) {\n return { ...result, path: [...breadcrumbs] }\n }\n // For failures, merge breadcrumbs into path\n return { ...result, path: [...breadcrumbs, ...result.path] }\n }\n\n // Handle collection extract types\n if (typeof extract === 'object' && extract.kind === 'eachCell') {\n if (state.level !== 'cell') {\n return failureWithPath(\n 'eachCell extract requires cell-level navigation state',\n breadcrumbs\n )\n }\n return withPath(extractEachCell(state.sheet, state.cell, extract))\n }\n\n if (typeof extract === 'object' && extract.kind === 'eachSlice') {\n if (state.level !== 'cell') {\n return failureWithPath(\n 'eachSlice extract requires cell-level navigation state',\n breadcrumbs\n )\n }\n const slices = gatherSlices(\n state.workbook,\n state.sheet,\n state.cell.row,\n state.cell.col,\n extract.direction,\n extract.while\n )\n return { ok: true, value: slices, path: [...breadcrumbs] }\n }\n\n if (extract === 'rows' || extract === 'cells') {\n if (state.level !== 'range') {\n return failureWithPath(\n `\"${extract}\" extract requires range-level navigation state`,\n breadcrumbs\n )\n }\n return withPath(extractFromRange(state.range, extract))\n }\n\n // Standard cell-level extraction\n if (state.level !== 'cell') {\n return failureWithPath(\n 'XLSX spec navigation did not reach a cell',\n breadcrumbs\n )\n }\n\n return withPath(extractFromCell(state.cell, extract))\n}\n","/**\n * Conversion utilities for XLSX data.\n *\n * @module xlsx/convert\n */\n\nimport type { XlsxWorkbook } from './xlsx-workbook'\nimport type { XlsxSheet } from './xlsx-sheet'\nimport type { XlsxRange } from './xlsx-range'\nimport type { XlsxCell } from './xlsx-cell'\nimport type { CellValue } from './xlsx-result'\n\n/**\n * JSON-compatible value types.\n */\nexport type JsonValue =\n | string\n | number\n | boolean\n | null\n | JsonValue[]\n | { [key: string]: JsonValue }\n\n/**\n * Options for converting to JSON.\n */\nexport interface ToJsonOptions {\n /**\n * Include sheet names as keys.\n * Default: true\n */\n includeSheetNames?: boolean\n\n /**\n * Include cell addresses in output.\n * Default: false\n */\n includeCellAddresses?: boolean\n\n /**\n * Convert dates to ISO strings.\n * Default: true\n */\n dateAsIsoString?: boolean\n\n /**\n * Include empty cells.\n * Default: false\n */\n includeEmpty?: boolean\n\n /**\n * Use first row as headers for object conversion.\n * Default: false\n */\n firstRowAsHeaders?: boolean\n}\n\n/**\n * Convert a cell value to a JSON-compatible value.\n */\nexport function cellValueToJson(\n value: CellValue,\n options?: ToJsonOptions\n): JsonValue {\n if (value === null || value === undefined) {\n return null\n }\n if (value instanceof Date) {\n if (options?.dateAsIsoString !== false) {\n return value.toISOString()\n }\n return value.getTime()\n }\n if (\n typeof value === 'string' ||\n typeof value === 'number' ||\n typeof value === 'boolean'\n ) {\n return value\n }\n return null\n}\n\n/**\n * Convert a cell to a JSON representation.\n */\nexport function cellToJson(cell: XlsxCell, options?: ToJsonOptions): JsonValue {\n const val = cell.value()\n const value = val.ok ? cellValueToJson(val.value, options) : null\n\n if (options?.includeCellAddresses) {\n return {\n address: cell.address,\n value,\n }\n }\n return value\n}\n\n/**\n * Convert a range to a JSON representation.\n */\nexport function rangeToJson(\n range: XlsxRange,\n options?: ToJsonOptions\n): JsonValue {\n if (options?.firstRowAsHeaders) {\n return rangeToObjects(range, options)\n }\n return rangeToArray(range, options)\n}\n\n/**\n * Convert a range to a 2D array.\n */\nexport function rangeToArray(\n range: XlsxRange,\n options?: ToJsonOptions\n): JsonValue[][] {\n const result: JsonValue[][] = []\n for (const rowCells of range.rows()) {\n const row: JsonValue[] = []\n for (const cell of rowCells) {\n const value = cellToJson(cell, options)\n if (value !== null || options?.includeEmpty) {\n row.push(value)\n } else if (row.length > 0 || options?.includeEmpty) {\n // Keep nulls for consistent column count\n row.push(null)\n }\n }\n if (row.length > 0 || options?.includeEmpty) {\n result.push(row)\n }\n }\n return result\n}\n\n/**\n * Convert a range to an array of objects using the first row as headers.\n */\nexport function rangeToObjects(\n range: XlsxRange,\n options?: ToJsonOptions\n): JsonValue {\n const rows = [...range.rows()]\n if (rows.length === 0) return []\n\n // Get headers from first row\n const headerRow = rows[0]\n const headers: string[] = headerRow.map(cell => {\n const val = cell.value()\n if (val.ok && val.value !== null) {\n return String(val.value)\n }\n return `col_${cell.col}`\n })\n\n // Convert data rows to objects\n const result: JsonValue[] = []\n for (let i = 1; i < rows.length; i++) {\n const row = rows[i]\n const obj: { [key: string]: JsonValue } = {}\n let hasData = false\n\n for (let j = 0; j < headers.length; j++) {\n const header = headers[j]\n const cell = row[j]\n if (cell) {\n const value = cellToJson(cell, options)\n if (value !== null) {\n hasData = true\n }\n obj[header] = value\n } else {\n obj[header] = null\n }\n }\n\n if (hasData || options?.includeEmpty) {\n result.push(obj)\n }\n }\n\n return result\n}\n\n/**\n * Convert a sheet to a JSON representation.\n */\nexport function sheetToJson(\n sheet: XlsxSheet,\n options?: ToJsonOptions\n): JsonValue {\n const rangeResult = sheet.usedRange()\n if (!rangeResult.ok) {\n return options?.firstRowAsHeaders ? [] : [[]]\n }\n return rangeToJson(rangeResult.value, options)\n}\n\n/**\n * Convert a workbook to a JSON representation.\n */\nexport function workbookToJson(\n workbook: XlsxWorkbook,\n options?: ToJsonOptions\n): JsonValue {\n const sheets = workbook.sheets()\n\n if (options?.includeSheetNames !== false) {\n const result: { [key: string]: JsonValue } = {}\n for (const sheet of sheets) {\n result[sheet.name] = sheetToJson(sheet, options)\n }\n return result\n }\n\n // Just return array of sheet data\n return sheets.map(sheet => sheetToJson(sheet, options))\n}\n\n/**\n * Convert a range to CSV format.\n */\nexport function rangeToCsv(\n range: XlsxRange,\n options?: {\n delimiter?: string\n lineEnding?: string\n quoteStrings?: boolean\n }\n): string {\n const delimiter = options?.delimiter ?? ','\n const lineEnding = options?.lineEnding ?? '\\n'\n const quoteStrings = options?.quoteStrings ?? true\n\n const lines: string[] = []\n\n for (const rowCells of range.rows()) {\n const values: string[] = []\n for (const cell of rowCells) {\n const val = cell.value()\n let str: string\n\n if (!val.ok || val.value === null) {\n str = ''\n } else if (val.value instanceof Date) {\n str = val.value.toISOString()\n } else {\n str = String(val.value)\n }\n\n // Quote if contains delimiter, newline, or quotes\n if (\n quoteStrings &&\n (str.includes(delimiter) ||\n str.includes('\\n') ||\n str.includes('\\r') ||\n str.includes('\"'))\n ) {\n str = '\"' + str.replace(/\"/g, '\"\"') + '\"'\n }\n\n values.push(str)\n }\n lines.push(values.join(delimiter))\n }\n\n return lines.join(lineEnding)\n}\n\n/**\n * Convert a sheet to CSV format.\n */\nexport function sheetToCsv(\n sheet: XlsxSheet,\n options?: {\n delimiter?: string\n lineEnding?: string\n quoteStrings?: boolean\n }\n): string {\n const rangeResult = sheet.usedRange()\n if (!rangeResult.ok) {\n return ''\n }\n return rangeToCsv(rangeResult.value, options)\n}\n","/**\n * @origints/xlsx - XLSX parsing for Origins with full traceability.\n *\n * This package provides a rich API for parsing and navigating XLSX files\n * with complete traceability to sheets, ranges, and cells.\n *\n * @packageDocumentation\n */\n\n// Re-export result types\nexport type {\n ExcelLocation,\n XlsxPath,\n XlsxFailure,\n XlsxFailureKind,\n XlsxResult,\n CellValue,\n ExtendedCellValue,\n} from './xlsx-result'\nexport {\n ok,\n fail,\n formatXlsxPath,\n toExcelLocation,\n isFormula,\n isError,\n} from './xlsx-result'\n\n// Re-export cell\nexport type { CellStyle, RichTextSegment, RichTextContent } from './xlsx-cell'\nexport { XlsxCell } from './xlsx-cell'\n\n// Re-export range\nexport { XlsxRange } from './xlsx-range'\n\n// Re-export sheet\nexport type { SheetDimensions } from './xlsx-sheet'\nexport { XlsxSheet } from './xlsx-sheet'\n\n// Re-export workbook\nexport type { SheetPredicate, WorkbookProperties } from './xlsx-workbook'\nexport { XlsxWorkbook } from './xlsx-workbook'\n\n// Re-export cursor\nexport type { CursorDirection, GrabResult, GrabOneResult } from './xlsx-cursor'\nexport { XlsxCursor } from './xlsx-cursor'\n\n// Re-export query predicates\nexport type { CellPredicate, Predicates } from './xlsx-query'\nexport { predicates } from './xlsx-query'\n\n// Re-export parse functions and implementations\nexport type {\n XlsxParseOptions,\n TransformAst,\n TransformImpl,\n TypedTransformAst,\n} from './parse'\nexport {\n parseXlsx,\n parseXlsxImpl,\n parseXlsxAsyncImpl,\n parseXlsxBuffer,\n parseXlsxFile,\n} from './parse'\n\n// Re-export spec types and builders\nexport type {\n XlsxSpec,\n XlsxStep,\n XlsxExtract,\n Direction,\n EachCellExtract,\n EachSliceExtract,\n} from './xlsx-spec'\nexport {\n XlsxSpecBuilder,\n XlsxSheetSB,\n XlsxCellSB,\n XlsxRangeSB,\n XlsxRowSB,\n XlsxColSB,\n XlsxRowItemSB,\n XlsxSliceSB,\n} from './xlsx-spec-builder'\nexport { executeXlsxSpec, XlsxSliceContext } from './xlsx-spec-executor'\n\n// Re-export predicate spec types and builders\nexport type {\n CellPredicateSpec,\n SheetPredicateSpec,\n RowPredicateSpec,\n CellPred,\n SheetPred,\n RowPred,\n} from './xlsx-predicate-spec'\nexport {\n cell,\n sheet,\n rowCol,\n describeCellPredicate,\n describeSheetPredicate,\n describeRowPredicate,\n} from './xlsx-predicate-spec'\n\n// Re-export predicate compiler (advanced use)\nexport {\n compileCellPredicate,\n compileSheetPredicate,\n compileRowPredicate,\n} from './xlsx-predicate-compiler'\nexport type { RowPredicate } from './xlsx-predicate-compiler'\n\n// Re-export conversion utilities\nexport type { JsonValue, ToJsonOptions } from './convert'\nexport {\n cellValueToJson,\n cellToJson,\n rangeToJson,\n rangeToArray,\n rangeToObjects,\n sheetToJson,\n workbookToJson,\n rangeToCsv,\n sheetToCsv,\n} from './convert'\n\n// Re-export utilities\nexport {\n streamToBuffer,\n columnLetterToNumber,\n columnNumberToLetter,\n parseAddress,\n formatAddress,\n parseRange,\n formatRange,\n isInRange,\n} from './util'\n\n// ---------------------------------------------------------------------------\n// Auto-registration of transforms\n// ---------------------------------------------------------------------------\n\nimport { globalRegistry, registerSpecExecutor } from '@origints/core'\nimport { parseXlsxAsyncImpl } from './parse'\nimport { executeXlsxSpec } from './xlsx-spec-executor'\nimport type { XlsxSpec } from './xlsx-spec'\n\n/**\n * Register the XLSX transforms with a registry.\n * Call this to enable parseXlsx() in your plans.\n *\n * @example\n * ```ts\n * import { globalRegistry } from '@origints/core'\n * import { registerXlsxTransforms } from '@origints/xlsx'\n *\n * registerXlsxTransforms(globalRegistry)\n * ```\n */\nexport function registerXlsxTransforms(registry: {\n register(impl: {\n namespace: string\n name: string\n execute: (...args: unknown[]) => unknown\n }): void\n}): void {\n registry.register(parseXlsxAsyncImpl)\n}\n\n// Auto-register transforms and spec executor\nregisterXlsxTransforms(globalRegistry)\nregisterSpecExecutor('xlsx', (spec, data) =>\n executeXlsxSpec(spec as unknown as XlsxSpec, data)\n)\n"],"names":["ok","value","path","fail","kind","message","sourceLocation","formatXlsxPath","parts","toExcelLocation","isFormula","isError","streamToBuffer","stream","reader","chunks","done","columnLetterToNumber","col","result","i","columnNumberToLetter","num","remainder","parseAddress","address","match","colLetter","formatAddress","row","parseRange","range","addr","start","end","formatRange","startRow","startCol","endRow","endCol","isInRange","XlsxCell","cell","_path","_sheetName","TYPE_LABEL","sheetName","file","val","typeOf","date","rawVal","hyperlink","segments","segment","linkVal","style","plainValue","text","rtResult","font","fill","border","alignment","link","note","rowDelta","colDelta","getCell","newRow","newCol","formulaVal","sharedVal","r","excelDate","offset","days","excelEpoch","XlsxRange","worksheet","_startRow","_startCol","_endRow","_endCol","_file","rangeAddr","rowOffset","colOffset","rowCells","colCells","rowValues","predicate","results","cellVal","count","headerRowOffset","dataStartOffset","allRows","headerRow","headers","obj","j","header","XlsxCursor","sheet","_row","_col","_direction","colNum","direction","cursor","dims","maxIterations","cellResult","cells","XlsxSheet","rowNum","colId","c","startAddress","rangeResult","rangeAddress","rowCount","columnCount","parsed","merges","XlsxWorkbook","workbook","name","cached","index","sheets","names","pattern","fn","predicates","caseSensitive","prefix","suffix","n","min","max","time","preds","pred","buildSpec","steps","extract","XlsxCellSB","while_","itemMapper","itemSpec","collectExtract","XlsxSliceSB","headerRef","headerSpec","XlsxRowItemSB","ref","XlsxRangeSB","XlsxRowSB","XlsxColSB","XlsxSheetSB","rowIndex","colIndex","rangeRef","fromOrRef","to","fromSpec","toSpec","XlsxSpecBuilder","parseXlsx","options","parseXlsxImpl","input","args","toArrayBuffer","parseXlsxAsyncImpl","data","buffer","ExcelJS","parseXlsxBuffer","parseXlsxFile","filePath","compileCellPredicate","spec","left","right","operand","compileSheetPredicate","re","compileRowPredicate","cellPred","anchorCol","wrapCell","other","describeCellPredicate","wrapSheet","describeSheetPredicate","formatCellValue","wrapRow","describeRowPredicate","rowCol","colWhereCache","rowWhereCache","success","failure","failureWithPath","unwrap","stepDesc","describeStep","step","isFailure","XlsxSliceContext","anchorCell","detectInputLevel","label","directionDelta","scanCells","predicateSpec","mode","desc","gatherCells","gatherSlices","navigate","initialState","state","breadcrumbs","pushBreadcrumb","s","failNav","failingStep","failMsg","currentSheet","found","cr","cellOrFailure","fromNav","fromSuccess","fromCell","toNav","toSuccess","toCell","cacheKey","sheetCache","foundCol","headerNav","headerSuccess","colPred","predDesc","targetResult","foundRow","headerCol","rowPred","extractFromCell","extractFromRange","rows","rowResult","extractEachCell","executeXlsxSpec","inputLevel","ctx","navResult","withPath","cellValueToJson","cellToJson","rangeToJson","rangeToObjects","rangeToArray","hasData","sheetToJson","workbookToJson","rangeToCsv","delimiter","lineEnding","quoteStrings","lines","values","str","sheetToCsv","registerXlsxTransforms","registry","globalRegistry","registerSpecExecutor"],"mappings":"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"}