@ricsam/formula-engine 0.1.0 → 0.2.1

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.
@@ -2,9 +2,9 @@
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/core/managers/schema-manager.ts"],
4
4
  "sourcesContent": [
5
- "/**\n * SchemaManager - Manages schema definitions and validation\n *\n * Tracks registered schemas and provides validation for cell writes,\n * spill operations, and copy/paste operations.\n */\n\nimport type {\n CellAddress,\n FiniteSpreadsheetRange,\n SerializedCellValue,\n SpreadsheetRange,\n TableDefinition,\n} from \"../types.cjs\";\nimport { cellAddressToKey, isCellInRange } from \"../utils.cjs\";\nimport type { TableManager } from \"./table-manager.cjs\";\n\nexport type ParseFunction<TCellMetadata = unknown> = (\n value: SerializedCellValue,\n metadata: TCellMetadata\n) => unknown;\n\nexport type WriteFunction<TCellMetadata = unknown> = (value: unknown) => {\n value: SerializedCellValue;\n metadata?: TCellMetadata;\n};\n\nexport type TableSchemaHeaders<TCellMetadata = unknown> = Record<\n string,\n {\n parse: ParseFunction<TCellMetadata>;\n write: WriteFunction<TCellMetadata>;\n index: number;\n }\n>;\n\nexport interface RegisteredTableSchema {\n type: \"table\";\n namespace: string;\n workbookName: string;\n tableName: string;\n headers: TableSchemaHeaders;\n}\n\nexport interface RegisteredCellSchema {\n type: \"cell\";\n namespace: string;\n cellAddress: CellAddress;\n parse: ParseFunction;\n}\n\nexport interface RegisteredGridSchema {\n type: \"grid\";\n namespace: string;\n workbookName: string;\n sheetName: string;\n range: FiniteSpreadsheetRange;\n parse: ParseFunction;\n}\n\nexport type RegisteredSchema = RegisteredTableSchema | RegisteredCellSchema | RegisteredGridSchema;\n\nexport interface ValidationResult {\n valid: boolean;\n error?: string;\n originalError?: Error;\n}\n\nexport class SchemaValidationError extends Error {\n constructor(\n message: string,\n public cellAddress?: CellAddress,\n public originalError?: Error\n ) {\n super(message);\n this.name = \"SchemaValidationError\";\n }\n}\n\nexport class SchemaManager {\n private schemas: Map<string, RegisteredSchema> = new Map();\n\n constructor(private tableManager: TableManager) {}\n\n /**\n * Register a table schema\n */\n registerTableSchema(\n namespace: string,\n workbookName: string,\n tableName: string,\n headers: TableSchemaHeaders\n ): void {\n this.schemas.set(namespace, {\n type: \"table\",\n namespace,\n workbookName,\n tableName,\n headers,\n });\n }\n\n /**\n * Register a cell schema\n */\n registerCellSchema(\n namespace: string,\n cellAddress: CellAddress,\n parse: ParseFunction\n ): void {\n this.schemas.set(namespace, {\n type: \"cell\",\n namespace,\n cellAddress,\n parse,\n });\n }\n\n /**\n * Register a grid schema\n */\n registerGridSchema(\n namespace: string,\n workbookName: string,\n sheetName: string,\n range: FiniteSpreadsheetRange,\n parse: ParseFunction\n ): void {\n this.schemas.set(namespace, {\n type: \"grid\",\n namespace,\n workbookName,\n sheetName,\n range,\n parse,\n });\n }\n\n /**\n * Get a schema by namespace\n */\n getSchema(namespace: string): RegisteredSchema | undefined {\n return this.schemas.get(namespace);\n }\n\n /**\n * Remove a schema\n */\n removeSchema(namespace: string): boolean {\n return this.schemas.delete(namespace);\n }\n\n /**\n * Check if any schemas are registered\n */\n hasSchemas(): boolean {\n return this.schemas.size > 0;\n }\n\n /**\n * Check if a cell is protected by a schema\n * Returns the schema info if protected, null otherwise\n */\n isCellProtected(\n cell: CellAddress\n ): { schema: RegisteredSchema; columnName?: string } | null {\n for (const schema of this.schemas.values()) {\n if (schema.type === \"cell\") {\n if (\n schema.cellAddress.workbookName === cell.workbookName &&\n schema.cellAddress.sheetName === cell.sheetName &&\n schema.cellAddress.colIndex === cell.colIndex &&\n schema.cellAddress.rowIndex === cell.rowIndex\n ) {\n return { schema };\n }\n } else if (schema.type === \"table\") {\n const table = this.tableManager.getTable({\n workbookName: schema.workbookName,\n name: schema.tableName,\n });\n\n if (!table) continue;\n\n // Check if cell is in table's data range (excluding header row)\n if (\n cell.workbookName === table.workbookName &&\n cell.sheetName === table.sheetName\n ) {\n const isInDataRange = this.isCellInTableDataRange(cell, table);\n if (isInDataRange) {\n // Find which column this cell is in\n const colOffset = cell.colIndex - table.start.colIndex;\n const columnName = this.getColumnNameByIndex(\n schema.headers,\n colOffset\n );\n return { schema, columnName };\n }\n }\n } else if (schema.type === \"grid\") {\n // Check if cell is within the grid range\n if (\n cell.workbookName === schema.workbookName &&\n cell.sheetName === schema.sheetName &&\n cell.colIndex >= schema.range.start.col &&\n cell.colIndex <= schema.range.end.col &&\n cell.rowIndex >= schema.range.start.row &&\n cell.rowIndex <= schema.range.end.row\n ) {\n return { schema };\n }\n }\n }\n\n return null;\n }\n\n /**\n * Check if a cell is within a table's data range (excluding header row)\n */\n private isCellInTableDataRange(\n cell: CellAddress,\n table: TableDefinition\n ): boolean {\n const { start, endRow, headers } = table;\n\n // Data starts one row below header\n const dataStartRow = start.rowIndex + 1;\n\n // Check row bounds (data rows only, not header)\n const isInRowRange =\n endRow.type === \"infinity\"\n ? cell.rowIndex >= dataStartRow\n : cell.rowIndex >= dataStartRow && cell.rowIndex <= endRow.value;\n\n // Check column bounds\n const endColIndex = start.colIndex + headers.size - 1;\n const isInColRange =\n cell.colIndex >= start.colIndex && cell.colIndex <= endColIndex;\n\n return isInRowRange && isInColRange;\n }\n\n /**\n * Get column name by index from headers\n */\n private getColumnNameByIndex(\n headers: TableSchemaHeaders,\n index: number\n ): string | undefined {\n for (const [name, header] of Object.entries(headers)) {\n if (header.index === index) {\n return name;\n }\n }\n return undefined;\n }\n\n /**\n * Validate a cell write against schemas\n */\n validateCellWrite(\n cell: CellAddress,\n value: SerializedCellValue,\n metadata?: unknown\n ): ValidationResult {\n // Allow clearing cells (undefined or empty string)\n if (value === undefined || value === \"\") {\n return { valid: true };\n }\n\n const protection = this.isCellProtected(cell);\n\n if (!protection) {\n return { valid: true };\n }\n\n const { schema, columnName } = protection;\n\n try {\n if (schema.type === \"cell\") {\n schema.parse(value, metadata);\n } else if (schema.type === \"table\" && columnName) {\n const header = schema.headers[columnName];\n if (header) {\n header.parse(value, metadata);\n }\n } else if (schema.type === \"grid\") {\n schema.parse(value, metadata);\n }\n return { valid: true };\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err));\n return {\n valid: false,\n error: `Schema validation failed for ${schema.namespace}${\n columnName ? `.${columnName}` : \"\"\n }: ${error.message}`,\n originalError: error,\n };\n }\n }\n\n /**\n * Validate a spill area against schemas\n * Returns validation result - if invalid, spill should produce #SPILL! error\n */\n validateSpillArea(\n origin: CellAddress,\n spillArea: SpreadsheetRange,\n getSpillValue: (row: number, col: number) => SerializedCellValue,\n getMetadata?: (cell: CellAddress) => unknown\n ): ValidationResult {\n // Get the bounds of the spill area\n const startRow = spillArea.start.row;\n const startCol = spillArea.start.col;\n const endRow =\n spillArea.end.row.type === \"number\"\n ? spillArea.end.row.value\n : startRow + 100; // Limit for infinite ranges\n const endCol =\n spillArea.end.col.type === \"number\"\n ? spillArea.end.col.value\n : startCol + 100; // Limit for infinite ranges\n\n for (let row = startRow; row <= endRow; row++) {\n for (let col = startCol; col <= endCol; col++) {\n const cell: CellAddress = {\n workbookName: origin.workbookName,\n sheetName: origin.sheetName,\n rowIndex: row,\n colIndex: col,\n };\n\n const protection = this.isCellProtected(cell);\n if (protection) {\n const value = getSpillValue(row - startRow, col - startCol);\n const metadata = getMetadata ? getMetadata(cell) : undefined;\n const validation = this.validateCellWrite(cell, value, metadata);\n\n if (!validation.valid) {\n return {\n valid: false,\n error: `Spill blocked by schema at ${cellAddressToKey(cell)}: ${\n validation.error\n }`,\n originalError: validation.originalError,\n };\n }\n }\n }\n }\n\n return { valid: true };\n }\n\n /**\n * Update schemas when a table is renamed\n */\n updateForTableRename(\n workbookName: string,\n oldTableName: string,\n newTableName: string\n ): void {\n for (const schema of this.schemas.values()) {\n if (\n schema.type === \"table\" &&\n schema.workbookName === workbookName &&\n schema.tableName === oldTableName\n ) {\n schema.tableName = newTableName;\n }\n }\n }\n\n /**\n * Update schemas when a sheet is renamed\n */\n updateForSheetRename(\n workbookName: string,\n oldSheetName: string,\n newSheetName: string\n ): void {\n for (const schema of this.schemas.values()) {\n if (schema.type === \"cell\") {\n if (\n schema.cellAddress.workbookName === workbookName &&\n schema.cellAddress.sheetName === oldSheetName\n ) {\n schema.cellAddress.sheetName = newSheetName;\n }\n } else if (schema.type === \"grid\") {\n if (\n schema.workbookName === workbookName &&\n schema.sheetName === oldSheetName\n ) {\n schema.sheetName = newSheetName;\n }\n }\n // Table schemas don't store sheetName directly - they get it from TableManager\n }\n }\n\n /**\n * Update schemas when a workbook is renamed\n */\n updateForWorkbookRename(\n oldWorkbookName: string,\n newWorkbookName: string\n ): void {\n for (const schema of this.schemas.values()) {\n if (schema.type === \"cell\") {\n if (schema.cellAddress.workbookName === oldWorkbookName) {\n schema.cellAddress.workbookName = newWorkbookName;\n }\n } else if (schema.type === \"table\") {\n if (schema.workbookName === oldWorkbookName) {\n schema.workbookName = newWorkbookName;\n }\n } else if (schema.type === \"grid\") {\n if (schema.workbookName === oldWorkbookName) {\n schema.workbookName = newWorkbookName;\n }\n }\n }\n }\n\n /**\n * Get all schemas (for debugging/testing)\n */\n getAllSchemas(): Map<string, RegisteredSchema> {\n return new Map(this.schemas);\n }\n\n /**\n * Validate all schema constraints using evaluated cell values.\n *\n * This is the key method for schema validation with rollback:\n * - It validates EVALUATED values, not raw content\n * - A cell with \"=123+123\" validates as number (246), not string\n * - Called after re-evaluation to check all schema-constrained cells\n *\n * @param getCellValue - Function to get the evaluated value of a cell\n * @param getCellMetadata - Optional function to get cell metadata\n * @returns Validation result with all errors found\n */\n validateAllSchemaConstraints(\n getCellValue: (cell: CellAddress) => SerializedCellValue,\n getCellMetadata?: (cell: CellAddress) => unknown,\n getTableDataCells?: (table: TableDefinition) => CellAddress[]\n ): {\n valid: boolean;\n errors: Array<{\n message: string;\n cellAddress?: CellAddress;\n schemaNamespace?: string;\n columnName?: string;\n originalError?: Error;\n }>;\n } {\n const errors: Array<{\n message: string;\n cellAddress?: CellAddress;\n schemaNamespace?: string;\n columnName?: string;\n originalError?: Error;\n }> = [];\n\n for (const [namespace, schema] of this.schemas) {\n if (schema.type === \"cell\") {\n // Validate single cell using evaluated value\n let value: SerializedCellValue;\n try {\n value = getCellValue(schema.cellAddress);\n } catch {\n // Sheet/cell doesn't exist yet, skip validation\n continue;\n }\n\n const metadata = getCellMetadata\n ? getCellMetadata(schema.cellAddress)\n : undefined;\n\n // Skip empty cells\n if (value === undefined || value === \"\") {\n continue;\n }\n\n try {\n schema.parse(value, metadata);\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err));\n errors.push({\n message: `Schema validation failed for ${namespace}: ${error.message}`,\n cellAddress: schema.cellAddress,\n schemaNamespace: namespace,\n originalError: error,\n });\n }\n } else if (schema.type === \"table\") {\n // Get the table definition\n const table = this.tableManager.getTable({\n workbookName: schema.workbookName,\n name: schema.tableName,\n });\n\n if (!table) continue;\n\n const { start, headers } = table;\n\n // Get cells to validate - use callback if provided (handles infinite ranges efficiently)\n // Otherwise fall back to simple iteration for finite tables\n let cellsToValidate: CellAddress[];\n if (getTableDataCells) {\n cellsToValidate = getTableDataCells(table);\n } else {\n // Fallback for finite tables when no callback provided\n const { endRow } = table;\n if (endRow.type === \"infinity\") {\n // Skip validation for infinite tables without a cell iterator\n continue;\n }\n cellsToValidate = [];\n const dataStartRow = start.rowIndex + 1;\n const endColIndex = start.colIndex + headers.size - 1;\n for (let row = dataStartRow; row <= endRow.value; row++) {\n for (let col = start.colIndex; col <= endColIndex; col++) {\n cellsToValidate.push({\n workbookName: table.workbookName,\n sheetName: table.sheetName,\n rowIndex: row,\n colIndex: col,\n });\n }\n }\n }\n\n for (const cell of cellsToValidate) {\n // Skip header row\n if (cell.rowIndex <= start.rowIndex) continue;\n\n let value: SerializedCellValue;\n try {\n value = getCellValue(cell);\n } catch {\n // Sheet/cell doesn't exist yet, skip validation\n continue;\n }\n\n // Skip empty cells\n if (value === undefined || value === \"\") {\n continue;\n }\n\n // Find the column name\n const colOffset = cell.colIndex - start.colIndex;\n const columnName = this.getColumnNameByIndex(\n schema.headers,\n colOffset\n );\n\n if (columnName && schema.headers[columnName]) {\n const header = schema.headers[columnName];\n const metadata = getCellMetadata\n ? getCellMetadata(cell)\n : undefined;\n\n try {\n header.parse(value, metadata);\n } catch (err) {\n const error =\n err instanceof Error ? err : new Error(String(err));\n errors.push({\n message: `Schema validation failed for ${namespace}.${columnName}: ${error.message}`,\n cellAddress: cell,\n schemaNamespace: namespace,\n columnName,\n originalError: error,\n });\n }\n }\n }\n } else if (schema.type === \"grid\") {\n // Validate all cells in the grid range\n const { range } = schema;\n\n for (let row = range.start.row; row <= range.end.row; row++) {\n for (let col = range.start.col; col <= range.end.col; col++) {\n const cell: CellAddress = {\n workbookName: schema.workbookName,\n sheetName: schema.sheetName,\n rowIndex: row,\n colIndex: col,\n };\n\n let value: SerializedCellValue;\n try {\n value = getCellValue(cell);\n } catch {\n // Sheet/cell doesn't exist yet, skip validation\n continue;\n }\n\n // Skip empty cells\n if (value === undefined || value === \"\") {\n continue;\n }\n\n const metadata = getCellMetadata ? getCellMetadata(cell) : undefined;\n\n try {\n schema.parse(value, metadata);\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err));\n errors.push({\n message: `Schema validation failed for ${namespace}: ${error.message}`,\n cellAddress: cell,\n schemaNamespace: namespace,\n originalError: error,\n });\n }\n }\n }\n }\n }\n\n return {\n valid: errors.length === 0,\n errors,\n };\n }\n}\n"
5
+ "/**\n * SchemaManager - Manages schema definitions and validation\n *\n * Tracks registered schemas and provides validation for cell writes,\n * spill operations, and copy/paste operations.\n */\n\nimport type {\n CellAddress,\n FiniteSpreadsheetRange,\n SerializedCellValue,\n SpreadsheetRange,\n TableDefinition,\n} from \"../types.cjs\";\nimport { cellAddressToKey, isCellInRange } from \"../utils.cjs\";\nimport type { TableManager } from \"./table-manager.cjs\";\n\nexport type ParseFunction<TCellMetadata = unknown> = (\n value: SerializedCellValue,\n metadata: TCellMetadata\n) => unknown;\n\nexport type WriteFunction<TCellMetadata = unknown> = (value: any) => {\n value: SerializedCellValue;\n metadata?: TCellMetadata;\n};\n\nexport type TableSchemaHeaders<TCellMetadata = unknown> = Record<\n string,\n {\n parse: ParseFunction<TCellMetadata>;\n write: WriteFunction<TCellMetadata>;\n index: number;\n }\n>;\n\nexport interface RegisteredTableSchema {\n type: \"table\";\n namespace: string;\n workbookName: string;\n tableName: string;\n headers: TableSchemaHeaders;\n}\n\nexport interface RegisteredCellSchema {\n type: \"cell\";\n namespace: string;\n cellAddress: CellAddress;\n parse: ParseFunction;\n}\n\nexport interface RegisteredGridSchema {\n type: \"grid\";\n namespace: string;\n workbookName: string;\n sheetName: string;\n range: FiniteSpreadsheetRange;\n parse: ParseFunction;\n}\n\nexport type RegisteredSchema =\n | RegisteredTableSchema\n | RegisteredCellSchema\n | RegisteredGridSchema;\n\nexport interface ValidationResult {\n valid: boolean;\n error?: string;\n originalError?: Error;\n}\n\nexport class SchemaValidationError extends Error {\n constructor(\n message: string,\n public cellAddress?: CellAddress,\n public originalError?: Error\n ) {\n super(message);\n this.name = \"SchemaValidationError\";\n }\n}\n\nexport class SchemaManager {\n private schemas: Map<string, RegisteredSchema> = new Map();\n\n constructor(private tableManager: TableManager) {}\n\n /**\n * Register a table schema\n */\n registerTableSchema(\n namespace: string,\n workbookName: string,\n tableName: string,\n headers: TableSchemaHeaders\n ): void {\n this.schemas.set(namespace, {\n type: \"table\",\n namespace,\n workbookName,\n tableName,\n headers,\n });\n }\n\n /**\n * Register a cell schema\n */\n registerCellSchema(\n namespace: string,\n cellAddress: CellAddress,\n parse: ParseFunction\n ): void {\n this.schemas.set(namespace, {\n type: \"cell\",\n namespace,\n cellAddress,\n parse,\n });\n }\n\n /**\n * Register a grid schema\n */\n registerGridSchema(\n namespace: string,\n workbookName: string,\n sheetName: string,\n range: FiniteSpreadsheetRange,\n parse: ParseFunction\n ): void {\n this.schemas.set(namespace, {\n type: \"grid\",\n namespace,\n workbookName,\n sheetName,\n range,\n parse,\n });\n }\n\n /**\n * Get a schema by namespace\n */\n getSchema(namespace: string): RegisteredSchema | undefined {\n return this.schemas.get(namespace);\n }\n\n /**\n * Remove a schema\n */\n removeSchema(namespace: string): boolean {\n return this.schemas.delete(namespace);\n }\n\n /**\n * Check if any schemas are registered\n */\n hasSchemas(): boolean {\n return this.schemas.size > 0;\n }\n\n /**\n * Check if a cell is protected by a schema\n * Returns the schema info if protected, null otherwise\n */\n isCellProtected(\n cell: CellAddress\n ): { schema: RegisteredSchema; columnName?: string } | null {\n for (const schema of this.schemas.values()) {\n if (schema.type === \"cell\") {\n if (\n schema.cellAddress.workbookName === cell.workbookName &&\n schema.cellAddress.sheetName === cell.sheetName &&\n schema.cellAddress.colIndex === cell.colIndex &&\n schema.cellAddress.rowIndex === cell.rowIndex\n ) {\n return { schema };\n }\n } else if (schema.type === \"table\") {\n const table = this.tableManager.getTable({\n workbookName: schema.workbookName,\n name: schema.tableName,\n });\n\n if (!table) continue;\n\n // Check if cell is in table's data range (excluding header row)\n if (\n cell.workbookName === table.workbookName &&\n cell.sheetName === table.sheetName\n ) {\n const isInDataRange = this.isCellInTableDataRange(cell, table);\n if (isInDataRange) {\n // Find which column this cell is in\n const colOffset = cell.colIndex - table.start.colIndex;\n const columnName = this.getColumnNameByIndex(\n schema.headers,\n colOffset\n );\n return { schema, columnName };\n }\n }\n } else if (schema.type === \"grid\") {\n // Check if cell is within the grid range\n if (\n cell.workbookName === schema.workbookName &&\n cell.sheetName === schema.sheetName &&\n cell.colIndex >= schema.range.start.col &&\n cell.colIndex <= schema.range.end.col &&\n cell.rowIndex >= schema.range.start.row &&\n cell.rowIndex <= schema.range.end.row\n ) {\n return { schema };\n }\n }\n }\n\n return null;\n }\n\n /**\n * Check if a cell is within a table's data range (excluding header row)\n */\n private isCellInTableDataRange(\n cell: CellAddress,\n table: TableDefinition\n ): boolean {\n const { start, endRow, headers } = table;\n\n // Data starts one row below header\n const dataStartRow = start.rowIndex + 1;\n\n // Check row bounds (data rows only, not header)\n const isInRowRange =\n endRow.type === \"infinity\"\n ? cell.rowIndex >= dataStartRow\n : cell.rowIndex >= dataStartRow && cell.rowIndex <= endRow.value;\n\n // Check column bounds\n const endColIndex = start.colIndex + headers.size - 1;\n const isInColRange =\n cell.colIndex >= start.colIndex && cell.colIndex <= endColIndex;\n\n return isInRowRange && isInColRange;\n }\n\n /**\n * Get column name by index from headers\n */\n private getColumnNameByIndex(\n headers: TableSchemaHeaders,\n index: number\n ): string | undefined {\n for (const [name, header] of Object.entries(headers)) {\n if (header.index === index) {\n return name;\n }\n }\n return undefined;\n }\n\n /**\n * Validate a cell write against schemas\n */\n validateCellWrite(\n cell: CellAddress,\n value: SerializedCellValue,\n metadata?: unknown\n ): ValidationResult {\n // Allow clearing cells (undefined or empty string)\n if (value === undefined || value === \"\") {\n return { valid: true };\n }\n\n const protection = this.isCellProtected(cell);\n\n if (!protection) {\n return { valid: true };\n }\n\n const { schema, columnName } = protection;\n\n try {\n if (schema.type === \"cell\") {\n schema.parse(value, metadata);\n } else if (schema.type === \"table\" && columnName) {\n const header = schema.headers[columnName];\n if (header) {\n header.parse(value, metadata);\n }\n } else if (schema.type === \"grid\") {\n schema.parse(value, metadata);\n }\n return { valid: true };\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err));\n return {\n valid: false,\n error: `Schema validation failed for ${schema.namespace}${\n columnName ? `.${columnName}` : \"\"\n }: ${error.message}`,\n originalError: error,\n };\n }\n }\n\n /**\n * Validate a spill area against schemas\n * Returns validation result - if invalid, spill should produce #SPILL! error\n */\n validateSpillArea(\n origin: CellAddress,\n spillArea: SpreadsheetRange,\n getSpillValue: (row: number, col: number) => SerializedCellValue,\n getMetadata?: (cell: CellAddress) => unknown\n ): ValidationResult {\n // Get the bounds of the spill area\n const startRow = spillArea.start.row;\n const startCol = spillArea.start.col;\n const endRow =\n spillArea.end.row.type === \"number\"\n ? spillArea.end.row.value\n : startRow + 100; // Limit for infinite ranges\n const endCol =\n spillArea.end.col.type === \"number\"\n ? spillArea.end.col.value\n : startCol + 100; // Limit for infinite ranges\n\n for (let row = startRow; row <= endRow; row++) {\n for (let col = startCol; col <= endCol; col++) {\n const cell: CellAddress = {\n workbookName: origin.workbookName,\n sheetName: origin.sheetName,\n rowIndex: row,\n colIndex: col,\n };\n\n const protection = this.isCellProtected(cell);\n if (protection) {\n const value = getSpillValue(row - startRow, col - startCol);\n const metadata = getMetadata ? getMetadata(cell) : undefined;\n const validation = this.validateCellWrite(cell, value, metadata);\n\n if (!validation.valid) {\n return {\n valid: false,\n error: `Spill blocked by schema at ${cellAddressToKey(cell)}: ${\n validation.error\n }`,\n originalError: validation.originalError,\n };\n }\n }\n }\n }\n\n return { valid: true };\n }\n\n /**\n * Update schemas when a table is renamed\n */\n updateForTableRename(\n workbookName: string,\n oldTableName: string,\n newTableName: string\n ): void {\n for (const schema of this.schemas.values()) {\n if (\n schema.type === \"table\" &&\n schema.workbookName === workbookName &&\n schema.tableName === oldTableName\n ) {\n schema.tableName = newTableName;\n }\n }\n }\n\n /**\n * Update schemas when a sheet is renamed\n */\n updateForSheetRename(\n workbookName: string,\n oldSheetName: string,\n newSheetName: string\n ): void {\n for (const schema of this.schemas.values()) {\n if (schema.type === \"cell\") {\n if (\n schema.cellAddress.workbookName === workbookName &&\n schema.cellAddress.sheetName === oldSheetName\n ) {\n schema.cellAddress.sheetName = newSheetName;\n }\n } else if (schema.type === \"grid\") {\n if (\n schema.workbookName === workbookName &&\n schema.sheetName === oldSheetName\n ) {\n schema.sheetName = newSheetName;\n }\n }\n // Table schemas don't store sheetName directly - they get it from TableManager\n }\n }\n\n /**\n * Update schemas when a workbook is renamed\n */\n updateForWorkbookRename(\n oldWorkbookName: string,\n newWorkbookName: string\n ): void {\n for (const schema of this.schemas.values()) {\n if (schema.type === \"cell\") {\n if (schema.cellAddress.workbookName === oldWorkbookName) {\n schema.cellAddress.workbookName = newWorkbookName;\n }\n } else if (schema.type === \"table\") {\n if (schema.workbookName === oldWorkbookName) {\n schema.workbookName = newWorkbookName;\n }\n } else if (schema.type === \"grid\") {\n if (schema.workbookName === oldWorkbookName) {\n schema.workbookName = newWorkbookName;\n }\n }\n }\n }\n\n /**\n * Get all schemas (for debugging/testing)\n */\n getAllSchemas(): Map<string, RegisteredSchema> {\n return new Map(this.schemas);\n }\n\n /**\n * Validate all schema constraints using evaluated cell values.\n *\n * This is the key method for schema validation with rollback:\n * - It validates EVALUATED values, not raw content\n * - A cell with \"=123+123\" validates as number (246), not string\n * - Called after re-evaluation to check all schema-constrained cells\n *\n * @param getCellValue - Function to get the evaluated value of a cell\n * @param getCellMetadata - Optional function to get cell metadata\n * @returns Validation result with all errors found\n */\n validateAllSchemaConstraints(\n getCellValue: (cell: CellAddress) => SerializedCellValue,\n getCellMetadata?: (cell: CellAddress) => unknown,\n getTableDataCells?: (table: TableDefinition) => CellAddress[]\n ): {\n valid: boolean;\n errors: Array<{\n message: string;\n cellAddress?: CellAddress;\n schemaNamespace?: string;\n columnName?: string;\n originalError?: Error;\n }>;\n } {\n const errors: Array<{\n message: string;\n cellAddress?: CellAddress;\n schemaNamespace?: string;\n columnName?: string;\n originalError?: Error;\n }> = [];\n\n for (const [namespace, schema] of this.schemas) {\n if (schema.type === \"cell\") {\n // Validate single cell using evaluated value\n let value: SerializedCellValue;\n try {\n value = getCellValue(schema.cellAddress);\n } catch {\n // Sheet/cell doesn't exist yet, skip validation\n continue;\n }\n\n const metadata = getCellMetadata\n ? getCellMetadata(schema.cellAddress)\n : undefined;\n\n // Skip empty cells\n if (value === undefined || value === \"\") {\n continue;\n }\n\n try {\n schema.parse(value, metadata);\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err));\n errors.push({\n message: `Schema validation failed for ${namespace}: ${error.message}`,\n cellAddress: schema.cellAddress,\n schemaNamespace: namespace,\n originalError: error,\n });\n }\n } else if (schema.type === \"table\") {\n // Get the table definition\n const table = this.tableManager.getTable({\n workbookName: schema.workbookName,\n name: schema.tableName,\n });\n\n if (!table) continue;\n\n const { start, headers } = table;\n\n // Get cells to validate - use callback if provided (handles infinite ranges efficiently)\n // Otherwise fall back to simple iteration for finite tables\n let cellsToValidate: CellAddress[];\n if (getTableDataCells) {\n cellsToValidate = getTableDataCells(table);\n } else {\n // Fallback for finite tables when no callback provided\n const { endRow } = table;\n if (endRow.type === \"infinity\") {\n // Skip validation for infinite tables without a cell iterator\n continue;\n }\n cellsToValidate = [];\n const dataStartRow = start.rowIndex + 1;\n const endColIndex = start.colIndex + headers.size - 1;\n for (let row = dataStartRow; row <= endRow.value; row++) {\n for (let col = start.colIndex; col <= endColIndex; col++) {\n cellsToValidate.push({\n workbookName: table.workbookName,\n sheetName: table.sheetName,\n rowIndex: row,\n colIndex: col,\n });\n }\n }\n }\n\n for (const cell of cellsToValidate) {\n // Skip header row\n if (cell.rowIndex <= start.rowIndex) continue;\n\n let value: SerializedCellValue;\n try {\n value = getCellValue(cell);\n } catch {\n // Sheet/cell doesn't exist yet, skip validation\n continue;\n }\n\n // Skip empty cells\n if (value === undefined || value === \"\") {\n continue;\n }\n\n // Find the column name\n const colOffset = cell.colIndex - start.colIndex;\n const columnName = this.getColumnNameByIndex(\n schema.headers,\n colOffset\n );\n\n if (columnName && schema.headers[columnName]) {\n const header = schema.headers[columnName];\n const metadata = getCellMetadata\n ? getCellMetadata(cell)\n : undefined;\n\n try {\n header.parse(value, metadata);\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err));\n errors.push({\n message: `Schema validation failed for ${namespace}.${columnName}: ${error.message}`,\n cellAddress: cell,\n schemaNamespace: namespace,\n columnName,\n originalError: error,\n });\n }\n }\n }\n } else if (schema.type === \"grid\") {\n // Validate all cells in the grid range\n const { range } = schema;\n\n for (let row = range.start.row; row <= range.end.row; row++) {\n for (let col = range.start.col; col <= range.end.col; col++) {\n const cell: CellAddress = {\n workbookName: schema.workbookName,\n sheetName: schema.sheetName,\n rowIndex: row,\n colIndex: col,\n };\n\n let value: SerializedCellValue;\n try {\n value = getCellValue(cell);\n } catch {\n // Sheet/cell doesn't exist yet, skip validation\n continue;\n }\n\n // Skip empty cells\n if (value === undefined || value === \"\") {\n continue;\n }\n\n const metadata = getCellMetadata\n ? getCellMetadata(cell)\n : undefined;\n\n try {\n schema.parse(value, metadata);\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err));\n errors.push({\n message: `Schema validation failed for ${namespace}: ${error.message}`,\n cellAddress: cell,\n schemaNamespace: namespace,\n originalError: error,\n });\n }\n }\n }\n }\n }\n\n return {\n valid: errors.length === 0,\n errors,\n };\n }\n}\n"
6
6
  ],
7
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAcgD,IAAhD;AAAA;AAsDO,MAAM,8BAA8B,MAAM;AAAA,EAGtC;AAAA,EACA;AAAA,EAHT,WAAW,CACT,SACO,aACA,eACP;AAAA,IACA,MAAM,OAAO;AAAA,IAHN;AAAA,IACA;AAAA,IAGP,KAAK,OAAO;AAAA;AAEhB;AAAA;AAEO,MAAM,cAAc;AAAA,EAGL;AAAA,EAFZ,UAAyC,IAAI;AAAA,EAErD,WAAW,CAAS,cAA4B;AAAA,IAA5B;AAAA;AAAA,EAKpB,mBAAmB,CACjB,WACA,cACA,WACA,SACM;AAAA,IACN,KAAK,QAAQ,IAAI,WAAW;AAAA,MAC1B,MAAM;AAAA,MACN;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAAA;AAAA,EAMH,kBAAkB,CAChB,WACA,aACA,OACM;AAAA,IACN,KAAK,QAAQ,IAAI,WAAW;AAAA,MAC1B,MAAM;AAAA,MACN;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAAA;AAAA,EAMH,kBAAkB,CAChB,WACA,cACA,WACA,OACA,OACM;AAAA,IACN,KAAK,QAAQ,IAAI,WAAW;AAAA,MAC1B,MAAM;AAAA,MACN;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAAA;AAAA,EAMH,SAAS,CAAC,WAAiD;AAAA,IACzD,OAAO,KAAK,QAAQ,IAAI,SAAS;AAAA;AAAA,EAMnC,YAAY,CAAC,WAA4B;AAAA,IACvC,OAAO,KAAK,QAAQ,OAAO,SAAS;AAAA;AAAA,EAMtC,UAAU,GAAY;AAAA,IACpB,OAAO,KAAK,QAAQ,OAAO;AAAA;AAAA,EAO7B,eAAe,CACb,MAC0D;AAAA,IAC1D,WAAW,UAAU,KAAK,QAAQ,OAAO,GAAG;AAAA,MAC1C,IAAI,OAAO,SAAS,QAAQ;AAAA,QAC1B,IACE,OAAO,YAAY,iBAAiB,KAAK,gBACzC,OAAO,YAAY,cAAc,KAAK,aACtC,OAAO,YAAY,aAAa,KAAK,YACrC,OAAO,YAAY,aAAa,KAAK,UACrC;AAAA,UACA,OAAO,EAAE,OAAO;AAAA,QAClB;AAAA,MACF,EAAO,SAAI,OAAO,SAAS,SAAS;AAAA,QAClC,MAAM,QAAQ,KAAK,aAAa,SAAS;AAAA,UACvC,cAAc,OAAO;AAAA,UACrB,MAAM,OAAO;AAAA,QACf,CAAC;AAAA,QAED,IAAI,CAAC;AAAA,UAAO;AAAA,QAGZ,IACE,KAAK,iBAAiB,MAAM,gBAC5B,KAAK,cAAc,MAAM,WACzB;AAAA,UACA,MAAM,gBAAgB,KAAK,uBAAuB,MAAM,KAAK;AAAA,UAC7D,IAAI,eAAe;AAAA,YAEjB,MAAM,YAAY,KAAK,WAAW,MAAM,MAAM;AAAA,YAC9C,MAAM,aAAa,KAAK,qBACtB,OAAO,SACP,SACF;AAAA,YACA,OAAO,EAAE,QAAQ,WAAW;AAAA,UAC9B;AAAA,QACF;AAAA,MACF,EAAO,SAAI,OAAO,SAAS,QAAQ;AAAA,QAEjC,IACE,KAAK,iBAAiB,OAAO,gBAC7B,KAAK,cAAc,OAAO,aAC1B,KAAK,YAAY,OAAO,MAAM,MAAM,OACpC,KAAK,YAAY,OAAO,MAAM,IAAI,OAClC,KAAK,YAAY,OAAO,MAAM,MAAM,OACpC,KAAK,YAAY,OAAO,MAAM,IAAI,KAClC;AAAA,UACA,OAAO,EAAE,OAAO;AAAA,QAClB;AAAA,MACF;AAAA,IACF;AAAA,IAEA,OAAO;AAAA;AAAA,EAMD,sBAAsB,CAC5B,MACA,OACS;AAAA,IACT,QAAQ,OAAO,QAAQ,YAAY;AAAA,IAGnC,MAAM,eAAe,MAAM,WAAW;AAAA,IAGtC,MAAM,eACJ,OAAO,SAAS,aACZ,KAAK,YAAY,eACjB,KAAK,YAAY,gBAAgB,KAAK,YAAY,OAAO;AAAA,IAG/D,MAAM,cAAc,MAAM,WAAW,QAAQ,OAAO;AAAA,IACpD,MAAM,eACJ,KAAK,YAAY,MAAM,YAAY,KAAK,YAAY;AAAA,IAEtD,OAAO,gBAAgB;AAAA;AAAA,EAMjB,oBAAoB,CAC1B,SACA,OACoB;AAAA,IACpB,YAAY,MAAM,WAAW,OAAO,QAAQ,OAAO,GAAG;AAAA,MACpD,IAAI,OAAO,UAAU,OAAO;AAAA,QAC1B,OAAO;AAAA,MACT;AAAA,IACF;AAAA,IACA;AAAA;AAAA,EAMF,iBAAiB,CACf,MACA,OACA,UACkB;AAAA,IAElB,IAAI,UAAU,aAAa,UAAU,IAAI;AAAA,MACvC,OAAO,EAAE,OAAO,KAAK;AAAA,IACvB;AAAA,IAEA,MAAM,aAAa,KAAK,gBAAgB,IAAI;AAAA,IAE5C,IAAI,CAAC,YAAY;AAAA,MACf,OAAO,EAAE,OAAO,KAAK;AAAA,IACvB;AAAA,IAEA,QAAQ,QAAQ,eAAe;AAAA,IAE/B,IAAI;AAAA,MACF,IAAI,OAAO,SAAS,QAAQ;AAAA,QAC1B,OAAO,MAAM,OAAO,QAAQ;AAAA,MAC9B,EAAO,SAAI,OAAO,SAAS,WAAW,YAAY;AAAA,QAChD,MAAM,SAAS,OAAO,QAAQ;AAAA,QAC9B,IAAI,QAAQ;AAAA,UACV,OAAO,MAAM,OAAO,QAAQ;AAAA,QAC9B;AAAA,MACF,EAAO,SAAI,OAAO,SAAS,QAAQ;AAAA,QACjC,OAAO,MAAM,OAAO,QAAQ;AAAA,MAC9B;AAAA,MACA,OAAO,EAAE,OAAO,KAAK;AAAA,MACrB,OAAO,KAAK;AAAA,MACZ,MAAM,QAAQ,eAAe,QAAQ,MAAM,IAAI,MAAM,OAAO,GAAG,CAAC;AAAA,MAChE,OAAO;AAAA,QACL,OAAO;AAAA,QACP,OAAO,gCAAgC,OAAO,YAC5C,aAAa,IAAI,eAAe,OAC7B,MAAM;AAAA,QACX,eAAe;AAAA,MACjB;AAAA;AAAA;AAAA,EAQJ,iBAAiB,CACf,QACA,WACA,eACA,aACkB;AAAA,IAElB,MAAM,WAAW,UAAU,MAAM;AAAA,IACjC,MAAM,WAAW,UAAU,MAAM;AAAA,IACjC,MAAM,SACJ,UAAU,IAAI,IAAI,SAAS,WACvB,UAAU,IAAI,IAAI,QAClB,WAAW;AAAA,IACjB,MAAM,SACJ,UAAU,IAAI,IAAI,SAAS,WACvB,UAAU,IAAI,IAAI,QAClB,WAAW;AAAA,IAEjB,SAAS,MAAM,SAAU,OAAO,QAAQ,OAAO;AAAA,MAC7C,SAAS,MAAM,SAAU,OAAO,QAAQ,OAAO;AAAA,QAC7C,MAAM,OAAoB;AAAA,UACxB,cAAc,OAAO;AAAA,UACrB,WAAW,OAAO;AAAA,UAClB,UAAU;AAAA,UACV,UAAU;AAAA,QACZ;AAAA,QAEA,MAAM,aAAa,KAAK,gBAAgB,IAAI;AAAA,QAC5C,IAAI,YAAY;AAAA,UACd,MAAM,QAAQ,cAAc,MAAM,UAAU,MAAM,QAAQ;AAAA,UAC1D,MAAM,WAAW,cAAc,YAAY,IAAI,IAAI;AAAA,UACnD,MAAM,aAAa,KAAK,kBAAkB,MAAM,OAAO,QAAQ;AAAA,UAE/D,IAAI,CAAC,WAAW,OAAO;AAAA,YACrB,OAAO;AAAA,cACL,OAAO;AAAA,cACP,OAAO,8BAA8B,8BAAiB,IAAI,MACxD,WAAW;AAAA,cAEb,eAAe,WAAW;AAAA,YAC5B;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,IAEA,OAAO,EAAE,OAAO,KAAK;AAAA;AAAA,EAMvB,oBAAoB,CAClB,cACA,cACA,cACM;AAAA,IACN,WAAW,UAAU,KAAK,QAAQ,OAAO,GAAG;AAAA,MAC1C,IACE,OAAO,SAAS,WAChB,OAAO,iBAAiB,gBACxB,OAAO,cAAc,cACrB;AAAA,QACA,OAAO,YAAY;AAAA,MACrB;AAAA,IACF;AAAA;AAAA,EAMF,oBAAoB,CAClB,cACA,cACA,cACM;AAAA,IACN,WAAW,UAAU,KAAK,QAAQ,OAAO,GAAG;AAAA,MAC1C,IAAI,OAAO,SAAS,QAAQ;AAAA,QAC1B,IACE,OAAO,YAAY,iBAAiB,gBACpC,OAAO,YAAY,cAAc,cACjC;AAAA,UACA,OAAO,YAAY,YAAY;AAAA,QACjC;AAAA,MACF,EAAO,SAAI,OAAO,SAAS,QAAQ;AAAA,QACjC,IACE,OAAO,iBAAiB,gBACxB,OAAO,cAAc,cACrB;AAAA,UACA,OAAO,YAAY;AAAA,QACrB;AAAA,MACF;AAAA,IAEF;AAAA;AAAA,EAMF,uBAAuB,CACrB,iBACA,iBACM;AAAA,IACN,WAAW,UAAU,KAAK,QAAQ,OAAO,GAAG;AAAA,MAC1C,IAAI,OAAO,SAAS,QAAQ;AAAA,QAC1B,IAAI,OAAO,YAAY,iBAAiB,iBAAiB;AAAA,UACvD,OAAO,YAAY,eAAe;AAAA,QACpC;AAAA,MACF,EAAO,SAAI,OAAO,SAAS,SAAS;AAAA,QAClC,IAAI,OAAO,iBAAiB,iBAAiB;AAAA,UAC3C,OAAO,eAAe;AAAA,QACxB;AAAA,MACF,EAAO,SAAI,OAAO,SAAS,QAAQ;AAAA,QACjC,IAAI,OAAO,iBAAiB,iBAAiB;AAAA,UAC3C,OAAO,eAAe;AAAA,QACxB;AAAA,MACF;AAAA,IACF;AAAA;AAAA,EAMF,aAAa,GAAkC;AAAA,IAC7C,OAAO,IAAI,IAAI,KAAK,OAAO;AAAA;AAAA,EAe7B,4BAA4B,CAC1B,cACA,iBACA,mBAUA;AAAA,IACA,MAAM,SAMD,CAAC;AAAA,IAEN,YAAY,WAAW,WAAW,KAAK,SAAS;AAAA,MAC9C,IAAI,OAAO,SAAS,QAAQ;AAAA,QAE1B,IAAI;AAAA,QACJ,IAAI;AAAA,UACF,QAAQ,aAAa,OAAO,WAAW;AAAA,UACvC,MAAM;AAAA,UAEN;AAAA;AAAA,QAGF,MAAM,WAAW,kBACb,gBAAgB,OAAO,WAAW,IAClC;AAAA,QAGJ,IAAI,UAAU,aAAa,UAAU,IAAI;AAAA,UACvC;AAAA,QACF;AAAA,QAEA,IAAI;AAAA,UACF,OAAO,MAAM,OAAO,QAAQ;AAAA,UAC5B,OAAO,KAAK;AAAA,UACZ,MAAM,QAAQ,eAAe,QAAQ,MAAM,IAAI,MAAM,OAAO,GAAG,CAAC;AAAA,UAChE,OAAO,KAAK;AAAA,YACV,SAAS,gCAAgC,cAAc,MAAM;AAAA,YAC7D,aAAa,OAAO;AAAA,YACpB,iBAAiB;AAAA,YACjB,eAAe;AAAA,UACjB,CAAC;AAAA;AAAA,MAEL,EAAO,SAAI,OAAO,SAAS,SAAS;AAAA,QAElC,MAAM,QAAQ,KAAK,aAAa,SAAS;AAAA,UACvC,cAAc,OAAO;AAAA,UACrB,MAAM,OAAO;AAAA,QACf,CAAC;AAAA,QAED,IAAI,CAAC;AAAA,UAAO;AAAA,QAEZ,QAAQ,OAAO,YAAY;AAAA,QAI3B,IAAI;AAAA,QACJ,IAAI,mBAAmB;AAAA,UACrB,kBAAkB,kBAAkB,KAAK;AAAA,QAC3C,EAAO;AAAA,UAEL,QAAQ,WAAW;AAAA,UACnB,IAAI,OAAO,SAAS,YAAY;AAAA,YAE9B;AAAA,UACF;AAAA,UACA,kBAAkB,CAAC;AAAA,UACnB,MAAM,eAAe,MAAM,WAAW;AAAA,UACtC,MAAM,cAAc,MAAM,WAAW,QAAQ,OAAO;AAAA,UACpD,SAAS,MAAM,aAAc,OAAO,OAAO,OAAO,OAAO;AAAA,YACvD,SAAS,MAAM,MAAM,SAAU,OAAO,aAAa,OAAO;AAAA,cACxD,gBAAgB,KAAK;AAAA,gBACnB,cAAc,MAAM;AAAA,gBACpB,WAAW,MAAM;AAAA,gBACjB,UAAU;AAAA,gBACV,UAAU;AAAA,cACZ,CAAC;AAAA,YACH;AAAA,UACF;AAAA;AAAA,QAGF,WAAW,QAAQ,iBAAiB;AAAA,UAElC,IAAI,KAAK,YAAY,MAAM;AAAA,YAAU;AAAA,UAErC,IAAI;AAAA,UACJ,IAAI;AAAA,YACF,QAAQ,aAAa,IAAI;AAAA,YACzB,MAAM;AAAA,YAEN;AAAA;AAAA,UAIF,IAAI,UAAU,aAAa,UAAU,IAAI;AAAA,YACvC;AAAA,UACF;AAAA,UAGA,MAAM,YAAY,KAAK,WAAW,MAAM;AAAA,UACxC,MAAM,aAAa,KAAK,qBACtB,OAAO,SACP,SACF;AAAA,UAEA,IAAI,cAAc,OAAO,QAAQ,aAAa;AAAA,YAC5C,MAAM,SAAS,OAAO,QAAQ;AAAA,YAC9B,MAAM,WAAW,kBACb,gBAAgB,IAAI,IACpB;AAAA,YAEJ,IAAI;AAAA,cACF,OAAO,MAAM,OAAO,QAAQ;AAAA,cAC5B,OAAO,KAAK;AAAA,cACZ,MAAM,QACJ,eAAe,QAAQ,MAAM,IAAI,MAAM,OAAO,GAAG,CAAC;AAAA,cACpD,OAAO,KAAK;AAAA,gBACV,SAAS,gCAAgC,aAAa,eAAe,MAAM;AAAA,gBAC3E,aAAa;AAAA,gBACb,iBAAiB;AAAA,gBACjB;AAAA,gBACA,eAAe;AAAA,cACjB,CAAC;AAAA;AAAA,UAEL;AAAA,QACF;AAAA,MACF,EAAO,SAAI,OAAO,SAAS,QAAQ;AAAA,QAEjC,QAAQ,UAAU;AAAA,QAElB,SAAS,MAAM,MAAM,MAAM,IAAK,OAAO,MAAM,IAAI,KAAK,OAAO;AAAA,UAC3D,SAAS,MAAM,MAAM,MAAM,IAAK,OAAO,MAAM,IAAI,KAAK,OAAO;AAAA,YAC3D,MAAM,OAAoB;AAAA,cACxB,cAAc,OAAO;AAAA,cACrB,WAAW,OAAO;AAAA,cAClB,UAAU;AAAA,cACV,UAAU;AAAA,YACZ;AAAA,YAEA,IAAI;AAAA,YACJ,IAAI;AAAA,cACF,QAAQ,aAAa,IAAI;AAAA,cACzB,MAAM;AAAA,cAEN;AAAA;AAAA,YAIF,IAAI,UAAU,aAAa,UAAU,IAAI;AAAA,cACvC;AAAA,YACF;AAAA,YAEA,MAAM,WAAW,kBAAkB,gBAAgB,IAAI,IAAI;AAAA,YAE3D,IAAI;AAAA,cACF,OAAO,MAAM,OAAO,QAAQ;AAAA,cAC5B,OAAO,KAAK;AAAA,cACZ,MAAM,QAAQ,eAAe,QAAQ,MAAM,IAAI,MAAM,OAAO,GAAG,CAAC;AAAA,cAChE,OAAO,KAAK;AAAA,gBACV,SAAS,gCAAgC,cAAc,MAAM;AAAA,gBAC7D,aAAa;AAAA,gBACb,iBAAiB;AAAA,gBACjB,eAAe;AAAA,cACjB,CAAC;AAAA;AAAA,UAEL;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,IAEA,OAAO;AAAA,MACL,OAAO,OAAO,WAAW;AAAA,MACzB;AAAA,IACF;AAAA;AAEJ;",
7
+ "mappings": "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",
8
8
  "debugId": "0143AD2525CF4D0D64756E2164756E21",
9
9
  "names": []
10
10
  }
@@ -30,7 +30,7 @@ var __export = (target, all) => {
30
30
  var exports_schema = {};
31
31
  __export(exports_schema, {
32
32
  defineSchema: () => defineSchema,
33
- createHeader: () => createHeader
33
+ defineHeader: () => defineHeader
34
34
  });
35
35
  module.exports = __toCommonJS(exports_schema);
36
36
  function defineSchema() {
@@ -70,7 +70,7 @@ function defineSchema() {
70
70
  };
71
71
  return builder;
72
72
  }
73
- var createHeader = (index, parse, write) => {
73
+ var defineHeader = (index, parse, write) => {
74
74
  return {
75
75
  parse,
76
76
  write: write ?? ((value) => ({ value })),
@@ -78,4 +78,4 @@ var createHeader = (index, parse, write) => {
78
78
  };
79
79
  };
80
80
 
81
- //# debugId=FD12878AE32EA1DA64756E2164756E21
81
+ //# debugId=EE77C44315A3788C64756E2164756E21
@@ -2,9 +2,9 @@
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/core/schema/schema.ts"],
4
4
  "sourcesContent": [
5
- "import type {\n CellAddress,\n FiniteSpreadsheetRange,\n SerializedCellValue,\n} from \"../types.cjs\";\n\n/**\n * Define a schema for the FormulaEngine.\n *\n * The returned object contains:\n * - `declaration`: The schema definitions for tables and cells\n * - `schema`: A type-only placeholder (undefined at runtime) for TypeScript inference\n *\n * The actual working schema is only available through `engine.schema` after\n * attaching the definition to a FormulaEngine instance.\n *\n * @example\n * ```typescript\n * const mySchema = defineSchema<CellMetadata>()\n * .addTableSchema(\"users\", { workbookName: \"wb1\", tableName: \"users\" }, headers)\n * .addCellSchema(\"config\", cellAddress, parse);\n *\n * const engine = new FormulaEngine(mySchema);\n * engine.schema.users.findWhere({ id: 1 }); // Works!\n * engine.schema.config.read(); // Works!\n * mySchema.schema.users.findWhere({ id: 1 }); // Error: schema is undefined at runtime\n * ```\n */\nexport function defineSchema<\n TCellMetadata = unknown,\n TCurrentSchema extends Record<string, object> = Record<string, object>,\n TCurrentDeclaration extends Record<\n string,\n TableSchemaDefinition | CellSchemaDefinition | GridSchemaDefinition\n > = Record<\n string,\n TableSchemaDefinition | CellSchemaDefinition | GridSchemaDefinition\n >\n>(): CreateSchema<TCellMetadata, TCurrentSchema, TCurrentDeclaration> {\n const declaration: Record<\n string,\n TableSchemaDefinition | CellSchemaDefinition | GridSchemaDefinition\n > = {};\n\n const builder: CreateSchema<\n TCellMetadata,\n TCurrentSchema,\n TCurrentDeclaration\n > = {\n addTableSchema(namespace, address, headers) {\n declaration[namespace] = {\n type: \"table\",\n tableName: address.tableName,\n workbookName: address.workbookName,\n headers: headers as any,\n };\n return builder as any;\n },\n\n addCellSchema(\n namespace: string,\n cellAddress: CellAddress,\n parse: any,\n write?: any\n ) {\n declaration[namespace] = {\n type: \"cell\",\n cellAddress,\n parse,\n write: write ?? ((value: unknown) => ({ value: value as SerializedCellValue })),\n };\n return builder as any;\n },\n\n addGridSchema(\n namespace: string,\n address: { workbookName: string; sheetName: string },\n range: FiniteSpreadsheetRange,\n parse: any,\n write?: any\n ) {\n declaration[namespace] = {\n type: \"grid\",\n workbookName: address.workbookName,\n sheetName: address.sheetName,\n range,\n parse,\n write: write ?? ((value: unknown) => ({ value: value as SerializedCellValue })),\n };\n return builder as any;\n },\n\n // schema is undefined at runtime - it only exists for TypeScript type inference\n // The actual working schema is built by the FormulaEngine constructor\n schema: undefined as any as TCurrentSchema,\n\n declaration: declaration as TCurrentDeclaration,\n };\n\n return builder;\n}\n\nexport interface TableSchemaDefinition {\n type: \"table\";\n headers: Headers<unknown>;\n tableName: string;\n workbookName: string;\n}\n\nexport interface CellSchemaDefinition {\n type: \"cell\";\n cellAddress: CellAddress;\n parse: (value: unknown, metadata: unknown) => unknown;\n write: (value: unknown) => {\n value: SerializedCellValue;\n metadata?: unknown;\n };\n}\n\nexport interface GridSchemaDefinition {\n type: \"grid\";\n workbookName: string;\n sheetName: string;\n range: FiniteSpreadsheetRange;\n parse: (value: unknown, metadata: unknown) => unknown;\n write: (value: unknown) => {\n value: SerializedCellValue;\n metadata?: unknown;\n };\n}\n\ntype Headers<TCellMetadata> = Record<\n string,\n {\n parse: (value: SerializedCellValue, metadata: TCellMetadata) => unknown;\n write: (value: any) => {\n value: SerializedCellValue;\n metadata?: TCellMetadata;\n };\n index: number;\n }\n>;\n\n/**\n * Type representing the TableOrm methods exposed on the schema\n */\nexport type TableOrmSchema<TItem extends Record<string, unknown>> = {\n findWhere(filter: Partial<TItem>): TItem | undefined;\n findAllWhere(filter: Partial<TItem>): TItem[];\n append(item: TItem): TItem;\n updateWhere(filter: Partial<TItem>, update: Partial<TItem>): number;\n removeWhere(filter: Partial<TItem>): number;\n count(): number;\n};\n\n/**\n * Type representing the CellOrm methods exposed on the schema\n */\nexport type CellOrmSchema<TValue> = {\n read(): TValue;\n write(value: TValue): void;\n getAddress(): CellAddress;\n};\n\n/**\n * Type representing the GridOrm methods exposed on the schema\n */\nexport type GridOrmSchema<TValue> = {\n columns: readonly TValue[][];\n rows: readonly TValue[][];\n setValue(value: TValue, position: { col: number; row: number }): void;\n getValue(position: { col: number; row: number }): TValue;\n};\n\nexport type SchemaDeclaration = Record<\n string,\n TableSchemaDefinition | CellSchemaDefinition | GridSchemaDefinition\n>;\nexport type Schema = Record<string, object>;\n\n/**\n * Write function type for converting parsed values back to serializable form\n */\ntype WriteFunction<TValue, TCellMetadata> = (value: TValue) => {\n value: SerializedCellValue;\n metadata?: TCellMetadata;\n};\n\n/**\n * Helper type to create the return type for addCellSchema/addGridSchema\n */\ntype AddCellSchemaResult<\n TCellMetadata,\n TCurrentSchema extends Schema,\n TCurrentDeclaration extends SchemaDeclaration,\n T extends string,\n TValue\n> = CreateSchema<\n TCellMetadata,\n TCurrentSchema & {\n [K in T]: CellOrmSchema<TValue>;\n },\n TCurrentDeclaration & {\n [K in T]: {\n type: \"cell\";\n cellAddress: CellAddress;\n parse: (value: unknown, metadata: unknown) => unknown;\n };\n }\n>;\n\ntype AddGridSchemaResult<\n TCellMetadata,\n TCurrentSchema extends Schema,\n TCurrentDeclaration extends SchemaDeclaration,\n T extends string,\n TValue\n> = CreateSchema<\n TCellMetadata,\n TCurrentSchema & {\n [K in T]: GridOrmSchema<TValue>;\n },\n TCurrentDeclaration & {\n [K in T]: {\n type: \"grid\";\n workbookName: string;\n sheetName: string;\n range: FiniteSpreadsheetRange;\n parse: (value: unknown, metadata: unknown) => unknown;\n };\n }\n>;\n\nexport type CreateSchema<\n TCellMetadata,\n TCurrentSchema extends Schema,\n TCurrentDeclaration extends SchemaDeclaration\n> = {\n addTableSchema<T extends string, THeaders extends Headers<TCellMetadata>>(\n namespace: T,\n address: { workbookName: string; tableName: string },\n headers: THeaders\n ): CreateSchema<\n TCellMetadata,\n TCurrentSchema & {\n [K in T]: TableOrmSchema<{\n [H in keyof THeaders]: ReturnType<THeaders[H][\"parse\"]>;\n }>;\n },\n TCurrentDeclaration & {\n [K in T]: {\n type: \"table\";\n tableName: string;\n workbookName: string;\n headers: THeaders;\n };\n }\n >;\n\n // Overload 1: TValue is any type - write is required\n addCellSchema<T extends string, TValue>(\n namespace: T,\n cellAddress: CellAddress,\n parse: (value: unknown, metadata: TCellMetadata) => TValue,\n write: WriteFunction<TValue, TCellMetadata>\n ): AddCellSchemaResult<TCellMetadata, TCurrentSchema, TCurrentDeclaration, T, TValue>;\n\n // Overload 2: TValue extends SerializedCellValue - write is optional\n addCellSchema<T extends string, TValue extends SerializedCellValue>(\n namespace: T,\n cellAddress: CellAddress,\n parse: (value: unknown, metadata: TCellMetadata) => TValue,\n write?: WriteFunction<TValue, TCellMetadata>\n ): AddCellSchemaResult<TCellMetadata, TCurrentSchema, TCurrentDeclaration, T, TValue>;\n\n // Overload 1: TValue is any type - write is required\n addGridSchema<T extends string, TValue>(\n namespace: T,\n address: { workbookName: string; sheetName: string },\n range: FiniteSpreadsheetRange,\n parse: (value: unknown, metadata: TCellMetadata) => TValue,\n write: WriteFunction<TValue, TCellMetadata>\n ): AddGridSchemaResult<TCellMetadata, TCurrentSchema, TCurrentDeclaration, T, TValue>;\n\n // Overload 2: TValue extends SerializedCellValue - write is optional\n addGridSchema<T extends string, TValue extends SerializedCellValue>(\n namespace: T,\n address: { workbookName: string; sheetName: string },\n range: FiniteSpreadsheetRange,\n parse: (value: unknown, metadata: TCellMetadata) => TValue,\n write?: WriteFunction<TValue, TCellMetadata>\n ): AddGridSchemaResult<TCellMetadata, TCurrentSchema, TCurrentDeclaration, T, TValue>;\n\n schema: TCurrentSchema;\n declaration: TCurrentDeclaration;\n};\n\nexport const createHeader = <TValue, TMetadata>(\n index: number,\n parse: (value: SerializedCellValue, metadata: TMetadata) => TValue,\n write?: (value: TValue) => {\n value: SerializedCellValue;\n metadata?: TMetadata;\n }\n) => {\n return {\n parse,\n write: write ?? ((value) => ({ value })),\n index,\n };\n};\n"
5
+ "import type {\n CellAddress,\n FiniteSpreadsheetRange,\n SerializedCellValue,\n} from \"../types.cjs\";\n\n/**\n * Define a schema for the FormulaEngine.\n *\n * The returned object contains:\n * - `declaration`: The schema definitions for tables and cells\n * - `schema`: A type-only placeholder (undefined at runtime) for TypeScript inference\n *\n * The actual working schema is only available through `engine.schema` after\n * attaching the definition to a FormulaEngine instance.\n *\n * @example\n * ```typescript\n * const mySchema = defineSchema<CellMetadata>()\n * .addTableSchema(\"users\", { workbookName: \"wb1\", tableName: \"users\" }, headers)\n * .addCellSchema(\"config\", cellAddress, parse);\n *\n * const engine = new FormulaEngine(mySchema);\n * engine.schema.users.findWhere({ id: 1 }); // Works!\n * engine.schema.config.read(); // Works!\n * mySchema.schema.users.findWhere({ id: 1 }); // Error: schema is undefined at runtime\n * ```\n */\nexport function defineSchema<\n TCellMetadata = unknown,\n TCurrentSchema extends Record<string, object> = Record<string, object>,\n TCurrentDeclaration extends Record<\n string,\n TableSchemaDefinition | CellSchemaDefinition | GridSchemaDefinition\n > = Record<\n string,\n TableSchemaDefinition | CellSchemaDefinition | GridSchemaDefinition\n >\n>(): CreateSchema<TCellMetadata, TCurrentSchema, TCurrentDeclaration> {\n const declaration: Record<\n string,\n TableSchemaDefinition | CellSchemaDefinition | GridSchemaDefinition\n > = {};\n\n const builder: CreateSchema<\n TCellMetadata,\n TCurrentSchema,\n TCurrentDeclaration\n > = {\n addTableSchema(namespace, address, headers) {\n declaration[namespace] = {\n type: \"table\",\n tableName: address.tableName,\n workbookName: address.workbookName,\n headers: headers as any,\n };\n return builder as any;\n },\n\n addCellSchema(\n namespace: string,\n cellAddress: CellAddress,\n parse: any,\n write?: any\n ) {\n declaration[namespace] = {\n type: \"cell\",\n cellAddress,\n parse,\n write: write ?? ((value: unknown) => ({ value: value as SerializedCellValue })),\n };\n return builder as any;\n },\n\n addGridSchema(\n namespace: string,\n address: { workbookName: string; sheetName: string },\n range: FiniteSpreadsheetRange,\n parse: any,\n write?: any\n ) {\n declaration[namespace] = {\n type: \"grid\",\n workbookName: address.workbookName,\n sheetName: address.sheetName,\n range,\n parse,\n write: write ?? ((value: unknown) => ({ value: value as SerializedCellValue })),\n };\n return builder as any;\n },\n\n // schema is undefined at runtime - it only exists for TypeScript type inference\n // The actual working schema is built by the FormulaEngine constructor\n schema: undefined as any as TCurrentSchema,\n\n declaration: declaration as TCurrentDeclaration,\n };\n\n return builder;\n}\n\nexport interface TableSchemaDefinition {\n type: \"table\";\n headers: Headers<unknown>;\n tableName: string;\n workbookName: string;\n}\n\nexport interface CellSchemaDefinition {\n type: \"cell\";\n cellAddress: CellAddress;\n parse: (value: unknown, metadata: unknown) => unknown;\n write: (value: unknown) => {\n value: SerializedCellValue;\n metadata?: unknown;\n };\n}\n\nexport interface GridSchemaDefinition {\n type: \"grid\";\n workbookName: string;\n sheetName: string;\n range: FiniteSpreadsheetRange;\n parse: (value: unknown, metadata: unknown) => unknown;\n write: (value: unknown) => {\n value: SerializedCellValue;\n metadata?: unknown;\n };\n}\n\ntype Headers<TCellMetadata> = Record<\n string,\n {\n parse: (value: SerializedCellValue, metadata: TCellMetadata) => unknown;\n write: (value: any) => {\n value: SerializedCellValue;\n metadata?: TCellMetadata;\n };\n index: number;\n }\n>;\n\n/**\n * Type representing the TableOrm methods exposed on the schema\n */\nexport type TableOrmSchema<TItem extends Record<string, unknown>> = {\n findWhere(filter: Partial<TItem>): TItem | undefined;\n findAllWhere(filter: Partial<TItem>): TItem[];\n append(item: TItem): TItem;\n updateWhere(filter: Partial<TItem>, update: Partial<TItem>): number;\n removeWhere(filter: Partial<TItem>): number;\n count(): number;\n};\n\n/**\n * Type representing the CellOrm methods exposed on the schema\n */\nexport type CellOrmSchema<TValue> = {\n read(): TValue;\n write(value: TValue): void;\n getAddress(): CellAddress;\n};\n\n/**\n * Type representing the GridOrm methods exposed on the schema\n */\nexport type GridOrmSchema<TValue> = {\n columns: readonly TValue[][];\n rows: readonly TValue[][];\n setValue(value: TValue, position: { col: number; row: number }): void;\n getValue(position: { col: number; row: number }): TValue;\n};\n\nexport type SchemaDeclaration = Record<\n string,\n TableSchemaDefinition | CellSchemaDefinition | GridSchemaDefinition\n>;\nexport type Schema = Record<string, object>;\n\n/**\n * Write function type for converting parsed values back to serializable form\n */\ntype WriteFunction<TValue, TCellMetadata> = (value: TValue) => {\n value: SerializedCellValue;\n metadata?: TCellMetadata;\n};\n\n/**\n * Helper type to create the return type for addCellSchema/addGridSchema\n */\ntype AddCellSchemaResult<\n TCellMetadata,\n TCurrentSchema extends Schema,\n TCurrentDeclaration extends SchemaDeclaration,\n T extends string,\n TValue\n> = CreateSchema<\n TCellMetadata,\n TCurrentSchema & {\n [K in T]: CellOrmSchema<TValue>;\n },\n TCurrentDeclaration & {\n [K in T]: {\n type: \"cell\";\n cellAddress: CellAddress;\n parse: (value: unknown, metadata: unknown) => unknown;\n };\n }\n>;\n\ntype AddGridSchemaResult<\n TCellMetadata,\n TCurrentSchema extends Schema,\n TCurrentDeclaration extends SchemaDeclaration,\n T extends string,\n TValue\n> = CreateSchema<\n TCellMetadata,\n TCurrentSchema & {\n [K in T]: GridOrmSchema<TValue>;\n },\n TCurrentDeclaration & {\n [K in T]: {\n type: \"grid\";\n workbookName: string;\n sheetName: string;\n range: FiniteSpreadsheetRange;\n parse: (value: unknown, metadata: unknown) => unknown;\n };\n }\n>;\n\nexport type CreateSchema<\n TCellMetadata,\n TCurrentSchema extends Schema,\n TCurrentDeclaration extends SchemaDeclaration\n> = {\n addTableSchema<T extends string, THeaders extends Headers<TCellMetadata>>(\n namespace: T,\n address: { workbookName: string; tableName: string },\n headers: THeaders\n ): CreateSchema<\n TCellMetadata,\n TCurrentSchema & {\n [K in T]: TableOrmSchema<{\n [H in keyof THeaders]: ReturnType<THeaders[H][\"parse\"]>;\n }>;\n },\n TCurrentDeclaration & {\n [K in T]: {\n type: \"table\";\n tableName: string;\n workbookName: string;\n headers: THeaders;\n };\n }\n >;\n\n // Overload 1: TValue is any type - write is required\n addCellSchema<T extends string, TValue>(\n namespace: T,\n cellAddress: CellAddress,\n parse: (value: unknown, metadata: TCellMetadata) => TValue,\n write: WriteFunction<TValue, TCellMetadata>\n ): AddCellSchemaResult<TCellMetadata, TCurrentSchema, TCurrentDeclaration, T, TValue>;\n\n // Overload 2: TValue extends SerializedCellValue - write is optional\n addCellSchema<T extends string, TValue extends SerializedCellValue>(\n namespace: T,\n cellAddress: CellAddress,\n parse: (value: unknown, metadata: TCellMetadata) => TValue,\n write?: WriteFunction<TValue, TCellMetadata>\n ): AddCellSchemaResult<TCellMetadata, TCurrentSchema, TCurrentDeclaration, T, TValue>;\n\n // Overload 1: TValue is any type - write is required\n addGridSchema<T extends string, TValue>(\n namespace: T,\n address: { workbookName: string; sheetName: string },\n range: FiniteSpreadsheetRange,\n parse: (value: unknown, metadata: TCellMetadata) => TValue,\n write: WriteFunction<TValue, TCellMetadata>\n ): AddGridSchemaResult<TCellMetadata, TCurrentSchema, TCurrentDeclaration, T, TValue>;\n\n // Overload 2: TValue extends SerializedCellValue - write is optional\n addGridSchema<T extends string, TValue extends SerializedCellValue>(\n namespace: T,\n address: { workbookName: string; sheetName: string },\n range: FiniteSpreadsheetRange,\n parse: (value: unknown, metadata: TCellMetadata) => TValue,\n write?: WriteFunction<TValue, TCellMetadata>\n ): AddGridSchemaResult<TCellMetadata, TCurrentSchema, TCurrentDeclaration, T, TValue>;\n\n schema: TCurrentSchema;\n declaration: TCurrentDeclaration;\n};\n\nexport const defineHeader = <TValue, TMetadata>(\n index: number,\n parse: (value: SerializedCellValue, metadata: TMetadata) => TValue,\n write?: (value: TValue) => {\n value: SerializedCellValue;\n metadata?: TMetadata;\n }\n) => {\n return {\n parse,\n write: write ?? ((value) => ({ value })),\n index,\n };\n};\n"
6
6
  ],
7
7
  "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4BO,SAAS,YAUf,GAAqE;AAAA,EACpE,MAAM,cAGF,CAAC;AAAA,EAEL,MAAM,UAIF;AAAA,IACF,cAAc,CAAC,WAAW,SAAS,SAAS;AAAA,MAC1C,YAAY,aAAa;AAAA,QACvB,MAAM;AAAA,QACN,WAAW,QAAQ;AAAA,QACnB,cAAc,QAAQ;AAAA,QACtB;AAAA,MACF;AAAA,MACA,OAAO;AAAA;AAAA,IAGT,aAAa,CACX,WACA,aACA,OACA,OACA;AAAA,MACA,YAAY,aAAa;AAAA,QACvB,MAAM;AAAA,QACN;AAAA,QACA;AAAA,QACA,OAAO,UAAU,CAAC,WAAoB,EAAE,MAAoC;AAAA,MAC9E;AAAA,MACA,OAAO;AAAA;AAAA,IAGT,aAAa,CACX,WACA,SACA,OACA,OACA,OACA;AAAA,MACA,YAAY,aAAa;AAAA,QACvB,MAAM;AAAA,QACN,cAAc,QAAQ;AAAA,QACtB,WAAW,QAAQ;AAAA,QACnB;AAAA,QACA;AAAA,QACA,OAAO,UAAU,CAAC,WAAoB,EAAE,MAAoC;AAAA,MAC9E;AAAA,MACA,OAAO;AAAA;AAAA,IAKT,QAAQ;AAAA,IAER;AAAA,EACF;AAAA,EAEA,OAAO;AAAA;AAsMF,IAAM,eAAe,CAC1B,OACA,OACA,UAIG;AAAA,EACH,OAAO;AAAA,IACL;AAAA,IACA,OAAO,UAAU,CAAC,WAAW,EAAE,MAAM;AAAA,IACrC;AAAA,EACF;AAAA;",
8
- "debugId": "FD12878AE32EA1DA64756E2164756E21",
8
+ "debugId": "EE77C44315A3788C64756E2164756E21",
9
9
  "names": []
10
10
  }
package/dist/cjs/lib.cjs CHANGED
@@ -47,6 +47,7 @@ var __export = (target, all) => {
47
47
  var exports_lib = {};
48
48
  __export(exports_lib, {
49
49
  defineSchema: () => import_schema.defineSchema,
50
+ defineHeader: () => import_schema.defineHeader,
50
51
  TableOrm: () => import_table_orm.TableOrm,
51
52
  SchemaValidationError: () => import_schema_manager.SchemaValidationError,
52
53
  SchemaIntegrityError: () => import_command_executor.SchemaIntegrityError,
@@ -64,4 +65,4 @@ var import_cell_orm = require("./core/schema/cell-orm.cjs");
64
65
  var import_schema_manager = require("./core/managers/schema-manager.cjs");
65
66
  var import_command_executor = require("./core/commands/command-executor.cjs");
66
67
 
67
- //# debugId=0F275ACDD498695964756E2164756E21
68
+ //# debugId=7606169475E9CE8764756E2164756E21
@@ -2,9 +2,9 @@
2
2
  "version": 3,
3
3
  "sources": ["../../src/lib.ts"],
4
4
  "sourcesContent": [
5
- "export { FormulaEngine } from \"./core/engine.cjs\";\nexport * from \"./core/types.cjs\";\nexport * from \"./core/utils.cjs\";\nexport * from \"./core/utils/color-utils.cjs\";\n\n// Schema exports\nexport { defineSchema } from \"./core/schema/schema.cjs\";\nexport type { CreateSchema, SchemaDeclaration, Schema, TableSchemaDefinition, CellSchemaDefinition, TableOrmSchema, CellOrmSchema } from \"./core/schema/schema.cjs\";\nexport { TableOrm } from \"./core/schema/table-orm.cjs\";\nexport { CellOrm } from \"./core/schema/cell-orm.cjs\";\nexport { SchemaValidationError } from \"./core/managers/schema-manager.cjs\";\nexport type { ValidationResult } from \"./core/managers/schema-manager.cjs\";\n\n// Command Pattern exports\nexport { SchemaIntegrityError } from \"./core/commands/command-executor.cjs\";\nexport type { EngineAction, EngineCommand } from \"./core/commands/types.cjs\";\n"
5
+ "export { FormulaEngine } from \"./core/engine.cjs\";\nexport * from \"./core/types.cjs\";\nexport * from \"./core/utils.cjs\";\nexport * from \"./core/utils/color-utils.cjs\";\n\n// Schema exports\nexport { defineSchema, defineHeader } from \"./core/schema/schema.cjs\";\nexport type { CreateSchema, SchemaDeclaration, Schema, TableSchemaDefinition, CellSchemaDefinition, TableOrmSchema, CellOrmSchema } from \"./core/schema/schema.cjs\";\nexport { TableOrm } from \"./core/schema/table-orm.cjs\";\nexport { CellOrm } from \"./core/schema/cell-orm.cjs\";\nexport { SchemaValidationError } from \"./core/managers/schema-manager.cjs\";\nexport type { ValidationResult } from \"./core/managers/schema-manager.cjs\";\n\n// Command Pattern exports\nexport { SchemaIntegrityError } from \"./core/commands/command-executor.cjs\";\nexport type { EngineAction, EngineCommand } from \"./core/commands/types.cjs\";\n"
6
6
  ],
7
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAA8B,IAA9B;AACA;AACA;AACA;AAG6B,IAA7B;AAEyB,IAAzB;AACwB,IAAxB;AACsC,IAAtC;AAIqC,IAArC;",
8
- "debugId": "0F275ACDD498695964756E2164756E21",
7
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAA8B,IAA9B;AACA;AACA;AACA;AAG2C,IAA3C;AAEyB,IAAzB;AACwB,IAAxB;AACsC,IAAtC;AAIqC,IAArC;",
8
+ "debugId": "7606169475E9CE8764756E2164756E21",
9
9
  "names": []
10
10
  }
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "@ricsam/formula-engine",
3
- "version": "0.1.0",
3
+ "version": "0.2.1",
4
4
  "type": "commonjs"
5
5
  }
@@ -2,9 +2,9 @@
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/core/managers/schema-manager.ts"],
4
4
  "sourcesContent": [
5
- "/**\n * SchemaManager - Manages schema definitions and validation\n *\n * Tracks registered schemas and provides validation for cell writes,\n * spill operations, and copy/paste operations.\n */\n\nimport type {\n CellAddress,\n FiniteSpreadsheetRange,\n SerializedCellValue,\n SpreadsheetRange,\n TableDefinition,\n} from \"../types.mjs\";\nimport { cellAddressToKey, isCellInRange } from \"../utils.mjs\";\nimport type { TableManager } from \"./table-manager.mjs\";\n\nexport type ParseFunction<TCellMetadata = unknown> = (\n value: SerializedCellValue,\n metadata: TCellMetadata\n) => unknown;\n\nexport type WriteFunction<TCellMetadata = unknown> = (value: unknown) => {\n value: SerializedCellValue;\n metadata?: TCellMetadata;\n};\n\nexport type TableSchemaHeaders<TCellMetadata = unknown> = Record<\n string,\n {\n parse: ParseFunction<TCellMetadata>;\n write: WriteFunction<TCellMetadata>;\n index: number;\n }\n>;\n\nexport interface RegisteredTableSchema {\n type: \"table\";\n namespace: string;\n workbookName: string;\n tableName: string;\n headers: TableSchemaHeaders;\n}\n\nexport interface RegisteredCellSchema {\n type: \"cell\";\n namespace: string;\n cellAddress: CellAddress;\n parse: ParseFunction;\n}\n\nexport interface RegisteredGridSchema {\n type: \"grid\";\n namespace: string;\n workbookName: string;\n sheetName: string;\n range: FiniteSpreadsheetRange;\n parse: ParseFunction;\n}\n\nexport type RegisteredSchema = RegisteredTableSchema | RegisteredCellSchema | RegisteredGridSchema;\n\nexport interface ValidationResult {\n valid: boolean;\n error?: string;\n originalError?: Error;\n}\n\nexport class SchemaValidationError extends Error {\n constructor(\n message: string,\n public cellAddress?: CellAddress,\n public originalError?: Error\n ) {\n super(message);\n this.name = \"SchemaValidationError\";\n }\n}\n\nexport class SchemaManager {\n private schemas: Map<string, RegisteredSchema> = new Map();\n\n constructor(private tableManager: TableManager) {}\n\n /**\n * Register a table schema\n */\n registerTableSchema(\n namespace: string,\n workbookName: string,\n tableName: string,\n headers: TableSchemaHeaders\n ): void {\n this.schemas.set(namespace, {\n type: \"table\",\n namespace,\n workbookName,\n tableName,\n headers,\n });\n }\n\n /**\n * Register a cell schema\n */\n registerCellSchema(\n namespace: string,\n cellAddress: CellAddress,\n parse: ParseFunction\n ): void {\n this.schemas.set(namespace, {\n type: \"cell\",\n namespace,\n cellAddress,\n parse,\n });\n }\n\n /**\n * Register a grid schema\n */\n registerGridSchema(\n namespace: string,\n workbookName: string,\n sheetName: string,\n range: FiniteSpreadsheetRange,\n parse: ParseFunction\n ): void {\n this.schemas.set(namespace, {\n type: \"grid\",\n namespace,\n workbookName,\n sheetName,\n range,\n parse,\n });\n }\n\n /**\n * Get a schema by namespace\n */\n getSchema(namespace: string): RegisteredSchema | undefined {\n return this.schemas.get(namespace);\n }\n\n /**\n * Remove a schema\n */\n removeSchema(namespace: string): boolean {\n return this.schemas.delete(namespace);\n }\n\n /**\n * Check if any schemas are registered\n */\n hasSchemas(): boolean {\n return this.schemas.size > 0;\n }\n\n /**\n * Check if a cell is protected by a schema\n * Returns the schema info if protected, null otherwise\n */\n isCellProtected(\n cell: CellAddress\n ): { schema: RegisteredSchema; columnName?: string } | null {\n for (const schema of this.schemas.values()) {\n if (schema.type === \"cell\") {\n if (\n schema.cellAddress.workbookName === cell.workbookName &&\n schema.cellAddress.sheetName === cell.sheetName &&\n schema.cellAddress.colIndex === cell.colIndex &&\n schema.cellAddress.rowIndex === cell.rowIndex\n ) {\n return { schema };\n }\n } else if (schema.type === \"table\") {\n const table = this.tableManager.getTable({\n workbookName: schema.workbookName,\n name: schema.tableName,\n });\n\n if (!table) continue;\n\n // Check if cell is in table's data range (excluding header row)\n if (\n cell.workbookName === table.workbookName &&\n cell.sheetName === table.sheetName\n ) {\n const isInDataRange = this.isCellInTableDataRange(cell, table);\n if (isInDataRange) {\n // Find which column this cell is in\n const colOffset = cell.colIndex - table.start.colIndex;\n const columnName = this.getColumnNameByIndex(\n schema.headers,\n colOffset\n );\n return { schema, columnName };\n }\n }\n } else if (schema.type === \"grid\") {\n // Check if cell is within the grid range\n if (\n cell.workbookName === schema.workbookName &&\n cell.sheetName === schema.sheetName &&\n cell.colIndex >= schema.range.start.col &&\n cell.colIndex <= schema.range.end.col &&\n cell.rowIndex >= schema.range.start.row &&\n cell.rowIndex <= schema.range.end.row\n ) {\n return { schema };\n }\n }\n }\n\n return null;\n }\n\n /**\n * Check if a cell is within a table's data range (excluding header row)\n */\n private isCellInTableDataRange(\n cell: CellAddress,\n table: TableDefinition\n ): boolean {\n const { start, endRow, headers } = table;\n\n // Data starts one row below header\n const dataStartRow = start.rowIndex + 1;\n\n // Check row bounds (data rows only, not header)\n const isInRowRange =\n endRow.type === \"infinity\"\n ? cell.rowIndex >= dataStartRow\n : cell.rowIndex >= dataStartRow && cell.rowIndex <= endRow.value;\n\n // Check column bounds\n const endColIndex = start.colIndex + headers.size - 1;\n const isInColRange =\n cell.colIndex >= start.colIndex && cell.colIndex <= endColIndex;\n\n return isInRowRange && isInColRange;\n }\n\n /**\n * Get column name by index from headers\n */\n private getColumnNameByIndex(\n headers: TableSchemaHeaders,\n index: number\n ): string | undefined {\n for (const [name, header] of Object.entries(headers)) {\n if (header.index === index) {\n return name;\n }\n }\n return undefined;\n }\n\n /**\n * Validate a cell write against schemas\n */\n validateCellWrite(\n cell: CellAddress,\n value: SerializedCellValue,\n metadata?: unknown\n ): ValidationResult {\n // Allow clearing cells (undefined or empty string)\n if (value === undefined || value === \"\") {\n return { valid: true };\n }\n\n const protection = this.isCellProtected(cell);\n\n if (!protection) {\n return { valid: true };\n }\n\n const { schema, columnName } = protection;\n\n try {\n if (schema.type === \"cell\") {\n schema.parse(value, metadata);\n } else if (schema.type === \"table\" && columnName) {\n const header = schema.headers[columnName];\n if (header) {\n header.parse(value, metadata);\n }\n } else if (schema.type === \"grid\") {\n schema.parse(value, metadata);\n }\n return { valid: true };\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err));\n return {\n valid: false,\n error: `Schema validation failed for ${schema.namespace}${\n columnName ? `.${columnName}` : \"\"\n }: ${error.message}`,\n originalError: error,\n };\n }\n }\n\n /**\n * Validate a spill area against schemas\n * Returns validation result - if invalid, spill should produce #SPILL! error\n */\n validateSpillArea(\n origin: CellAddress,\n spillArea: SpreadsheetRange,\n getSpillValue: (row: number, col: number) => SerializedCellValue,\n getMetadata?: (cell: CellAddress) => unknown\n ): ValidationResult {\n // Get the bounds of the spill area\n const startRow = spillArea.start.row;\n const startCol = spillArea.start.col;\n const endRow =\n spillArea.end.row.type === \"number\"\n ? spillArea.end.row.value\n : startRow + 100; // Limit for infinite ranges\n const endCol =\n spillArea.end.col.type === \"number\"\n ? spillArea.end.col.value\n : startCol + 100; // Limit for infinite ranges\n\n for (let row = startRow; row <= endRow; row++) {\n for (let col = startCol; col <= endCol; col++) {\n const cell: CellAddress = {\n workbookName: origin.workbookName,\n sheetName: origin.sheetName,\n rowIndex: row,\n colIndex: col,\n };\n\n const protection = this.isCellProtected(cell);\n if (protection) {\n const value = getSpillValue(row - startRow, col - startCol);\n const metadata = getMetadata ? getMetadata(cell) : undefined;\n const validation = this.validateCellWrite(cell, value, metadata);\n\n if (!validation.valid) {\n return {\n valid: false,\n error: `Spill blocked by schema at ${cellAddressToKey(cell)}: ${\n validation.error\n }`,\n originalError: validation.originalError,\n };\n }\n }\n }\n }\n\n return { valid: true };\n }\n\n /**\n * Update schemas when a table is renamed\n */\n updateForTableRename(\n workbookName: string,\n oldTableName: string,\n newTableName: string\n ): void {\n for (const schema of this.schemas.values()) {\n if (\n schema.type === \"table\" &&\n schema.workbookName === workbookName &&\n schema.tableName === oldTableName\n ) {\n schema.tableName = newTableName;\n }\n }\n }\n\n /**\n * Update schemas when a sheet is renamed\n */\n updateForSheetRename(\n workbookName: string,\n oldSheetName: string,\n newSheetName: string\n ): void {\n for (const schema of this.schemas.values()) {\n if (schema.type === \"cell\") {\n if (\n schema.cellAddress.workbookName === workbookName &&\n schema.cellAddress.sheetName === oldSheetName\n ) {\n schema.cellAddress.sheetName = newSheetName;\n }\n } else if (schema.type === \"grid\") {\n if (\n schema.workbookName === workbookName &&\n schema.sheetName === oldSheetName\n ) {\n schema.sheetName = newSheetName;\n }\n }\n // Table schemas don't store sheetName directly - they get it from TableManager\n }\n }\n\n /**\n * Update schemas when a workbook is renamed\n */\n updateForWorkbookRename(\n oldWorkbookName: string,\n newWorkbookName: string\n ): void {\n for (const schema of this.schemas.values()) {\n if (schema.type === \"cell\") {\n if (schema.cellAddress.workbookName === oldWorkbookName) {\n schema.cellAddress.workbookName = newWorkbookName;\n }\n } else if (schema.type === \"table\") {\n if (schema.workbookName === oldWorkbookName) {\n schema.workbookName = newWorkbookName;\n }\n } else if (schema.type === \"grid\") {\n if (schema.workbookName === oldWorkbookName) {\n schema.workbookName = newWorkbookName;\n }\n }\n }\n }\n\n /**\n * Get all schemas (for debugging/testing)\n */\n getAllSchemas(): Map<string, RegisteredSchema> {\n return new Map(this.schemas);\n }\n\n /**\n * Validate all schema constraints using evaluated cell values.\n *\n * This is the key method for schema validation with rollback:\n * - It validates EVALUATED values, not raw content\n * - A cell with \"=123+123\" validates as number (246), not string\n * - Called after re-evaluation to check all schema-constrained cells\n *\n * @param getCellValue - Function to get the evaluated value of a cell\n * @param getCellMetadata - Optional function to get cell metadata\n * @returns Validation result with all errors found\n */\n validateAllSchemaConstraints(\n getCellValue: (cell: CellAddress) => SerializedCellValue,\n getCellMetadata?: (cell: CellAddress) => unknown,\n getTableDataCells?: (table: TableDefinition) => CellAddress[]\n ): {\n valid: boolean;\n errors: Array<{\n message: string;\n cellAddress?: CellAddress;\n schemaNamespace?: string;\n columnName?: string;\n originalError?: Error;\n }>;\n } {\n const errors: Array<{\n message: string;\n cellAddress?: CellAddress;\n schemaNamespace?: string;\n columnName?: string;\n originalError?: Error;\n }> = [];\n\n for (const [namespace, schema] of this.schemas) {\n if (schema.type === \"cell\") {\n // Validate single cell using evaluated value\n let value: SerializedCellValue;\n try {\n value = getCellValue(schema.cellAddress);\n } catch {\n // Sheet/cell doesn't exist yet, skip validation\n continue;\n }\n\n const metadata = getCellMetadata\n ? getCellMetadata(schema.cellAddress)\n : undefined;\n\n // Skip empty cells\n if (value === undefined || value === \"\") {\n continue;\n }\n\n try {\n schema.parse(value, metadata);\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err));\n errors.push({\n message: `Schema validation failed for ${namespace}: ${error.message}`,\n cellAddress: schema.cellAddress,\n schemaNamespace: namespace,\n originalError: error,\n });\n }\n } else if (schema.type === \"table\") {\n // Get the table definition\n const table = this.tableManager.getTable({\n workbookName: schema.workbookName,\n name: schema.tableName,\n });\n\n if (!table) continue;\n\n const { start, headers } = table;\n\n // Get cells to validate - use callback if provided (handles infinite ranges efficiently)\n // Otherwise fall back to simple iteration for finite tables\n let cellsToValidate: CellAddress[];\n if (getTableDataCells) {\n cellsToValidate = getTableDataCells(table);\n } else {\n // Fallback for finite tables when no callback provided\n const { endRow } = table;\n if (endRow.type === \"infinity\") {\n // Skip validation for infinite tables without a cell iterator\n continue;\n }\n cellsToValidate = [];\n const dataStartRow = start.rowIndex + 1;\n const endColIndex = start.colIndex + headers.size - 1;\n for (let row = dataStartRow; row <= endRow.value; row++) {\n for (let col = start.colIndex; col <= endColIndex; col++) {\n cellsToValidate.push({\n workbookName: table.workbookName,\n sheetName: table.sheetName,\n rowIndex: row,\n colIndex: col,\n });\n }\n }\n }\n\n for (const cell of cellsToValidate) {\n // Skip header row\n if (cell.rowIndex <= start.rowIndex) continue;\n\n let value: SerializedCellValue;\n try {\n value = getCellValue(cell);\n } catch {\n // Sheet/cell doesn't exist yet, skip validation\n continue;\n }\n\n // Skip empty cells\n if (value === undefined || value === \"\") {\n continue;\n }\n\n // Find the column name\n const colOffset = cell.colIndex - start.colIndex;\n const columnName = this.getColumnNameByIndex(\n schema.headers,\n colOffset\n );\n\n if (columnName && schema.headers[columnName]) {\n const header = schema.headers[columnName];\n const metadata = getCellMetadata\n ? getCellMetadata(cell)\n : undefined;\n\n try {\n header.parse(value, metadata);\n } catch (err) {\n const error =\n err instanceof Error ? err : new Error(String(err));\n errors.push({\n message: `Schema validation failed for ${namespace}.${columnName}: ${error.message}`,\n cellAddress: cell,\n schemaNamespace: namespace,\n columnName,\n originalError: error,\n });\n }\n }\n }\n } else if (schema.type === \"grid\") {\n // Validate all cells in the grid range\n const { range } = schema;\n\n for (let row = range.start.row; row <= range.end.row; row++) {\n for (let col = range.start.col; col <= range.end.col; col++) {\n const cell: CellAddress = {\n workbookName: schema.workbookName,\n sheetName: schema.sheetName,\n rowIndex: row,\n colIndex: col,\n };\n\n let value: SerializedCellValue;\n try {\n value = getCellValue(cell);\n } catch {\n // Sheet/cell doesn't exist yet, skip validation\n continue;\n }\n\n // Skip empty cells\n if (value === undefined || value === \"\") {\n continue;\n }\n\n const metadata = getCellMetadata ? getCellMetadata(cell) : undefined;\n\n try {\n schema.parse(value, metadata);\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err));\n errors.push({\n message: `Schema validation failed for ${namespace}: ${error.message}`,\n cellAddress: cell,\n schemaNamespace: namespace,\n originalError: error,\n });\n }\n }\n }\n }\n }\n\n return {\n valid: errors.length === 0,\n errors,\n };\n }\n}\n"
5
+ "/**\n * SchemaManager - Manages schema definitions and validation\n *\n * Tracks registered schemas and provides validation for cell writes,\n * spill operations, and copy/paste operations.\n */\n\nimport type {\n CellAddress,\n FiniteSpreadsheetRange,\n SerializedCellValue,\n SpreadsheetRange,\n TableDefinition,\n} from \"../types.mjs\";\nimport { cellAddressToKey, isCellInRange } from \"../utils.mjs\";\nimport type { TableManager } from \"./table-manager.mjs\";\n\nexport type ParseFunction<TCellMetadata = unknown> = (\n value: SerializedCellValue,\n metadata: TCellMetadata\n) => unknown;\n\nexport type WriteFunction<TCellMetadata = unknown> = (value: any) => {\n value: SerializedCellValue;\n metadata?: TCellMetadata;\n};\n\nexport type TableSchemaHeaders<TCellMetadata = unknown> = Record<\n string,\n {\n parse: ParseFunction<TCellMetadata>;\n write: WriteFunction<TCellMetadata>;\n index: number;\n }\n>;\n\nexport interface RegisteredTableSchema {\n type: \"table\";\n namespace: string;\n workbookName: string;\n tableName: string;\n headers: TableSchemaHeaders;\n}\n\nexport interface RegisteredCellSchema {\n type: \"cell\";\n namespace: string;\n cellAddress: CellAddress;\n parse: ParseFunction;\n}\n\nexport interface RegisteredGridSchema {\n type: \"grid\";\n namespace: string;\n workbookName: string;\n sheetName: string;\n range: FiniteSpreadsheetRange;\n parse: ParseFunction;\n}\n\nexport type RegisteredSchema =\n | RegisteredTableSchema\n | RegisteredCellSchema\n | RegisteredGridSchema;\n\nexport interface ValidationResult {\n valid: boolean;\n error?: string;\n originalError?: Error;\n}\n\nexport class SchemaValidationError extends Error {\n constructor(\n message: string,\n public cellAddress?: CellAddress,\n public originalError?: Error\n ) {\n super(message);\n this.name = \"SchemaValidationError\";\n }\n}\n\nexport class SchemaManager {\n private schemas: Map<string, RegisteredSchema> = new Map();\n\n constructor(private tableManager: TableManager) {}\n\n /**\n * Register a table schema\n */\n registerTableSchema(\n namespace: string,\n workbookName: string,\n tableName: string,\n headers: TableSchemaHeaders\n ): void {\n this.schemas.set(namespace, {\n type: \"table\",\n namespace,\n workbookName,\n tableName,\n headers,\n });\n }\n\n /**\n * Register a cell schema\n */\n registerCellSchema(\n namespace: string,\n cellAddress: CellAddress,\n parse: ParseFunction\n ): void {\n this.schemas.set(namespace, {\n type: \"cell\",\n namespace,\n cellAddress,\n parse,\n });\n }\n\n /**\n * Register a grid schema\n */\n registerGridSchema(\n namespace: string,\n workbookName: string,\n sheetName: string,\n range: FiniteSpreadsheetRange,\n parse: ParseFunction\n ): void {\n this.schemas.set(namespace, {\n type: \"grid\",\n namespace,\n workbookName,\n sheetName,\n range,\n parse,\n });\n }\n\n /**\n * Get a schema by namespace\n */\n getSchema(namespace: string): RegisteredSchema | undefined {\n return this.schemas.get(namespace);\n }\n\n /**\n * Remove a schema\n */\n removeSchema(namespace: string): boolean {\n return this.schemas.delete(namespace);\n }\n\n /**\n * Check if any schemas are registered\n */\n hasSchemas(): boolean {\n return this.schemas.size > 0;\n }\n\n /**\n * Check if a cell is protected by a schema\n * Returns the schema info if protected, null otherwise\n */\n isCellProtected(\n cell: CellAddress\n ): { schema: RegisteredSchema; columnName?: string } | null {\n for (const schema of this.schemas.values()) {\n if (schema.type === \"cell\") {\n if (\n schema.cellAddress.workbookName === cell.workbookName &&\n schema.cellAddress.sheetName === cell.sheetName &&\n schema.cellAddress.colIndex === cell.colIndex &&\n schema.cellAddress.rowIndex === cell.rowIndex\n ) {\n return { schema };\n }\n } else if (schema.type === \"table\") {\n const table = this.tableManager.getTable({\n workbookName: schema.workbookName,\n name: schema.tableName,\n });\n\n if (!table) continue;\n\n // Check if cell is in table's data range (excluding header row)\n if (\n cell.workbookName === table.workbookName &&\n cell.sheetName === table.sheetName\n ) {\n const isInDataRange = this.isCellInTableDataRange(cell, table);\n if (isInDataRange) {\n // Find which column this cell is in\n const colOffset = cell.colIndex - table.start.colIndex;\n const columnName = this.getColumnNameByIndex(\n schema.headers,\n colOffset\n );\n return { schema, columnName };\n }\n }\n } else if (schema.type === \"grid\") {\n // Check if cell is within the grid range\n if (\n cell.workbookName === schema.workbookName &&\n cell.sheetName === schema.sheetName &&\n cell.colIndex >= schema.range.start.col &&\n cell.colIndex <= schema.range.end.col &&\n cell.rowIndex >= schema.range.start.row &&\n cell.rowIndex <= schema.range.end.row\n ) {\n return { schema };\n }\n }\n }\n\n return null;\n }\n\n /**\n * Check if a cell is within a table's data range (excluding header row)\n */\n private isCellInTableDataRange(\n cell: CellAddress,\n table: TableDefinition\n ): boolean {\n const { start, endRow, headers } = table;\n\n // Data starts one row below header\n const dataStartRow = start.rowIndex + 1;\n\n // Check row bounds (data rows only, not header)\n const isInRowRange =\n endRow.type === \"infinity\"\n ? cell.rowIndex >= dataStartRow\n : cell.rowIndex >= dataStartRow && cell.rowIndex <= endRow.value;\n\n // Check column bounds\n const endColIndex = start.colIndex + headers.size - 1;\n const isInColRange =\n cell.colIndex >= start.colIndex && cell.colIndex <= endColIndex;\n\n return isInRowRange && isInColRange;\n }\n\n /**\n * Get column name by index from headers\n */\n private getColumnNameByIndex(\n headers: TableSchemaHeaders,\n index: number\n ): string | undefined {\n for (const [name, header] of Object.entries(headers)) {\n if (header.index === index) {\n return name;\n }\n }\n return undefined;\n }\n\n /**\n * Validate a cell write against schemas\n */\n validateCellWrite(\n cell: CellAddress,\n value: SerializedCellValue,\n metadata?: unknown\n ): ValidationResult {\n // Allow clearing cells (undefined or empty string)\n if (value === undefined || value === \"\") {\n return { valid: true };\n }\n\n const protection = this.isCellProtected(cell);\n\n if (!protection) {\n return { valid: true };\n }\n\n const { schema, columnName } = protection;\n\n try {\n if (schema.type === \"cell\") {\n schema.parse(value, metadata);\n } else if (schema.type === \"table\" && columnName) {\n const header = schema.headers[columnName];\n if (header) {\n header.parse(value, metadata);\n }\n } else if (schema.type === \"grid\") {\n schema.parse(value, metadata);\n }\n return { valid: true };\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err));\n return {\n valid: false,\n error: `Schema validation failed for ${schema.namespace}${\n columnName ? `.${columnName}` : \"\"\n }: ${error.message}`,\n originalError: error,\n };\n }\n }\n\n /**\n * Validate a spill area against schemas\n * Returns validation result - if invalid, spill should produce #SPILL! error\n */\n validateSpillArea(\n origin: CellAddress,\n spillArea: SpreadsheetRange,\n getSpillValue: (row: number, col: number) => SerializedCellValue,\n getMetadata?: (cell: CellAddress) => unknown\n ): ValidationResult {\n // Get the bounds of the spill area\n const startRow = spillArea.start.row;\n const startCol = spillArea.start.col;\n const endRow =\n spillArea.end.row.type === \"number\"\n ? spillArea.end.row.value\n : startRow + 100; // Limit for infinite ranges\n const endCol =\n spillArea.end.col.type === \"number\"\n ? spillArea.end.col.value\n : startCol + 100; // Limit for infinite ranges\n\n for (let row = startRow; row <= endRow; row++) {\n for (let col = startCol; col <= endCol; col++) {\n const cell: CellAddress = {\n workbookName: origin.workbookName,\n sheetName: origin.sheetName,\n rowIndex: row,\n colIndex: col,\n };\n\n const protection = this.isCellProtected(cell);\n if (protection) {\n const value = getSpillValue(row - startRow, col - startCol);\n const metadata = getMetadata ? getMetadata(cell) : undefined;\n const validation = this.validateCellWrite(cell, value, metadata);\n\n if (!validation.valid) {\n return {\n valid: false,\n error: `Spill blocked by schema at ${cellAddressToKey(cell)}: ${\n validation.error\n }`,\n originalError: validation.originalError,\n };\n }\n }\n }\n }\n\n return { valid: true };\n }\n\n /**\n * Update schemas when a table is renamed\n */\n updateForTableRename(\n workbookName: string,\n oldTableName: string,\n newTableName: string\n ): void {\n for (const schema of this.schemas.values()) {\n if (\n schema.type === \"table\" &&\n schema.workbookName === workbookName &&\n schema.tableName === oldTableName\n ) {\n schema.tableName = newTableName;\n }\n }\n }\n\n /**\n * Update schemas when a sheet is renamed\n */\n updateForSheetRename(\n workbookName: string,\n oldSheetName: string,\n newSheetName: string\n ): void {\n for (const schema of this.schemas.values()) {\n if (schema.type === \"cell\") {\n if (\n schema.cellAddress.workbookName === workbookName &&\n schema.cellAddress.sheetName === oldSheetName\n ) {\n schema.cellAddress.sheetName = newSheetName;\n }\n } else if (schema.type === \"grid\") {\n if (\n schema.workbookName === workbookName &&\n schema.sheetName === oldSheetName\n ) {\n schema.sheetName = newSheetName;\n }\n }\n // Table schemas don't store sheetName directly - they get it from TableManager\n }\n }\n\n /**\n * Update schemas when a workbook is renamed\n */\n updateForWorkbookRename(\n oldWorkbookName: string,\n newWorkbookName: string\n ): void {\n for (const schema of this.schemas.values()) {\n if (schema.type === \"cell\") {\n if (schema.cellAddress.workbookName === oldWorkbookName) {\n schema.cellAddress.workbookName = newWorkbookName;\n }\n } else if (schema.type === \"table\") {\n if (schema.workbookName === oldWorkbookName) {\n schema.workbookName = newWorkbookName;\n }\n } else if (schema.type === \"grid\") {\n if (schema.workbookName === oldWorkbookName) {\n schema.workbookName = newWorkbookName;\n }\n }\n }\n }\n\n /**\n * Get all schemas (for debugging/testing)\n */\n getAllSchemas(): Map<string, RegisteredSchema> {\n return new Map(this.schemas);\n }\n\n /**\n * Validate all schema constraints using evaluated cell values.\n *\n * This is the key method for schema validation with rollback:\n * - It validates EVALUATED values, not raw content\n * - A cell with \"=123+123\" validates as number (246), not string\n * - Called after re-evaluation to check all schema-constrained cells\n *\n * @param getCellValue - Function to get the evaluated value of a cell\n * @param getCellMetadata - Optional function to get cell metadata\n * @returns Validation result with all errors found\n */\n validateAllSchemaConstraints(\n getCellValue: (cell: CellAddress) => SerializedCellValue,\n getCellMetadata?: (cell: CellAddress) => unknown,\n getTableDataCells?: (table: TableDefinition) => CellAddress[]\n ): {\n valid: boolean;\n errors: Array<{\n message: string;\n cellAddress?: CellAddress;\n schemaNamespace?: string;\n columnName?: string;\n originalError?: Error;\n }>;\n } {\n const errors: Array<{\n message: string;\n cellAddress?: CellAddress;\n schemaNamespace?: string;\n columnName?: string;\n originalError?: Error;\n }> = [];\n\n for (const [namespace, schema] of this.schemas) {\n if (schema.type === \"cell\") {\n // Validate single cell using evaluated value\n let value: SerializedCellValue;\n try {\n value = getCellValue(schema.cellAddress);\n } catch {\n // Sheet/cell doesn't exist yet, skip validation\n continue;\n }\n\n const metadata = getCellMetadata\n ? getCellMetadata(schema.cellAddress)\n : undefined;\n\n // Skip empty cells\n if (value === undefined || value === \"\") {\n continue;\n }\n\n try {\n schema.parse(value, metadata);\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err));\n errors.push({\n message: `Schema validation failed for ${namespace}: ${error.message}`,\n cellAddress: schema.cellAddress,\n schemaNamespace: namespace,\n originalError: error,\n });\n }\n } else if (schema.type === \"table\") {\n // Get the table definition\n const table = this.tableManager.getTable({\n workbookName: schema.workbookName,\n name: schema.tableName,\n });\n\n if (!table) continue;\n\n const { start, headers } = table;\n\n // Get cells to validate - use callback if provided (handles infinite ranges efficiently)\n // Otherwise fall back to simple iteration for finite tables\n let cellsToValidate: CellAddress[];\n if (getTableDataCells) {\n cellsToValidate = getTableDataCells(table);\n } else {\n // Fallback for finite tables when no callback provided\n const { endRow } = table;\n if (endRow.type === \"infinity\") {\n // Skip validation for infinite tables without a cell iterator\n continue;\n }\n cellsToValidate = [];\n const dataStartRow = start.rowIndex + 1;\n const endColIndex = start.colIndex + headers.size - 1;\n for (let row = dataStartRow; row <= endRow.value; row++) {\n for (let col = start.colIndex; col <= endColIndex; col++) {\n cellsToValidate.push({\n workbookName: table.workbookName,\n sheetName: table.sheetName,\n rowIndex: row,\n colIndex: col,\n });\n }\n }\n }\n\n for (const cell of cellsToValidate) {\n // Skip header row\n if (cell.rowIndex <= start.rowIndex) continue;\n\n let value: SerializedCellValue;\n try {\n value = getCellValue(cell);\n } catch {\n // Sheet/cell doesn't exist yet, skip validation\n continue;\n }\n\n // Skip empty cells\n if (value === undefined || value === \"\") {\n continue;\n }\n\n // Find the column name\n const colOffset = cell.colIndex - start.colIndex;\n const columnName = this.getColumnNameByIndex(\n schema.headers,\n colOffset\n );\n\n if (columnName && schema.headers[columnName]) {\n const header = schema.headers[columnName];\n const metadata = getCellMetadata\n ? getCellMetadata(cell)\n : undefined;\n\n try {\n header.parse(value, metadata);\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err));\n errors.push({\n message: `Schema validation failed for ${namespace}.${columnName}: ${error.message}`,\n cellAddress: cell,\n schemaNamespace: namespace,\n columnName,\n originalError: error,\n });\n }\n }\n }\n } else if (schema.type === \"grid\") {\n // Validate all cells in the grid range\n const { range } = schema;\n\n for (let row = range.start.row; row <= range.end.row; row++) {\n for (let col = range.start.col; col <= range.end.col; col++) {\n const cell: CellAddress = {\n workbookName: schema.workbookName,\n sheetName: schema.sheetName,\n rowIndex: row,\n colIndex: col,\n };\n\n let value: SerializedCellValue;\n try {\n value = getCellValue(cell);\n } catch {\n // Sheet/cell doesn't exist yet, skip validation\n continue;\n }\n\n // Skip empty cells\n if (value === undefined || value === \"\") {\n continue;\n }\n\n const metadata = getCellMetadata\n ? getCellMetadata(cell)\n : undefined;\n\n try {\n schema.parse(value, metadata);\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err));\n errors.push({\n message: `Schema validation failed for ${namespace}: ${error.message}`,\n cellAddress: cell,\n schemaNamespace: namespace,\n originalError: error,\n });\n }\n }\n }\n }\n }\n\n return {\n valid: errors.length === 0,\n errors,\n };\n }\n}\n"
6
6
  ],
7
- "mappings": "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",
7
+ "mappings": "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",
8
8
  "debugId": "C6B324CE0B5006EE64756E2164756E21",
9
9
  "names": []
10
10
  }
@@ -36,7 +36,7 @@ function defineSchema() {
36
36
  };
37
37
  return builder;
38
38
  }
39
- var createHeader = (index, parse, write) => {
39
+ var defineHeader = (index, parse, write) => {
40
40
  return {
41
41
  parse,
42
42
  write: write ?? ((value) => ({ value })),
@@ -45,7 +45,7 @@ var createHeader = (index, parse, write) => {
45
45
  };
46
46
  export {
47
47
  defineSchema,
48
- createHeader
48
+ defineHeader
49
49
  };
50
50
 
51
- //# debugId=50A63DDDAA5631D564756E2164756E21
51
+ //# debugId=5C9087F143083A7464756E2164756E21
@@ -2,9 +2,9 @@
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/core/schema/schema.ts"],
4
4
  "sourcesContent": [
5
- "import type {\n CellAddress,\n FiniteSpreadsheetRange,\n SerializedCellValue,\n} from \"../types.mjs\";\n\n/**\n * Define a schema for the FormulaEngine.\n *\n * The returned object contains:\n * - `declaration`: The schema definitions for tables and cells\n * - `schema`: A type-only placeholder (undefined at runtime) for TypeScript inference\n *\n * The actual working schema is only available through `engine.schema` after\n * attaching the definition to a FormulaEngine instance.\n *\n * @example\n * ```typescript\n * const mySchema = defineSchema<CellMetadata>()\n * .addTableSchema(\"users\", { workbookName: \"wb1\", tableName: \"users\" }, headers)\n * .addCellSchema(\"config\", cellAddress, parse);\n *\n * const engine = new FormulaEngine(mySchema);\n * engine.schema.users.findWhere({ id: 1 }); // Works!\n * engine.schema.config.read(); // Works!\n * mySchema.schema.users.findWhere({ id: 1 }); // Error: schema is undefined at runtime\n * ```\n */\nexport function defineSchema<\n TCellMetadata = unknown,\n TCurrentSchema extends Record<string, object> = Record<string, object>,\n TCurrentDeclaration extends Record<\n string,\n TableSchemaDefinition | CellSchemaDefinition | GridSchemaDefinition\n > = Record<\n string,\n TableSchemaDefinition | CellSchemaDefinition | GridSchemaDefinition\n >\n>(): CreateSchema<TCellMetadata, TCurrentSchema, TCurrentDeclaration> {\n const declaration: Record<\n string,\n TableSchemaDefinition | CellSchemaDefinition | GridSchemaDefinition\n > = {};\n\n const builder: CreateSchema<\n TCellMetadata,\n TCurrentSchema,\n TCurrentDeclaration\n > = {\n addTableSchema(namespace, address, headers) {\n declaration[namespace] = {\n type: \"table\",\n tableName: address.tableName,\n workbookName: address.workbookName,\n headers: headers as any,\n };\n return builder as any;\n },\n\n addCellSchema(\n namespace: string,\n cellAddress: CellAddress,\n parse: any,\n write?: any\n ) {\n declaration[namespace] = {\n type: \"cell\",\n cellAddress,\n parse,\n write: write ?? ((value: unknown) => ({ value: value as SerializedCellValue })),\n };\n return builder as any;\n },\n\n addGridSchema(\n namespace: string,\n address: { workbookName: string; sheetName: string },\n range: FiniteSpreadsheetRange,\n parse: any,\n write?: any\n ) {\n declaration[namespace] = {\n type: \"grid\",\n workbookName: address.workbookName,\n sheetName: address.sheetName,\n range,\n parse,\n write: write ?? ((value: unknown) => ({ value: value as SerializedCellValue })),\n };\n return builder as any;\n },\n\n // schema is undefined at runtime - it only exists for TypeScript type inference\n // The actual working schema is built by the FormulaEngine constructor\n schema: undefined as any as TCurrentSchema,\n\n declaration: declaration as TCurrentDeclaration,\n };\n\n return builder;\n}\n\nexport interface TableSchemaDefinition {\n type: \"table\";\n headers: Headers<unknown>;\n tableName: string;\n workbookName: string;\n}\n\nexport interface CellSchemaDefinition {\n type: \"cell\";\n cellAddress: CellAddress;\n parse: (value: unknown, metadata: unknown) => unknown;\n write: (value: unknown) => {\n value: SerializedCellValue;\n metadata?: unknown;\n };\n}\n\nexport interface GridSchemaDefinition {\n type: \"grid\";\n workbookName: string;\n sheetName: string;\n range: FiniteSpreadsheetRange;\n parse: (value: unknown, metadata: unknown) => unknown;\n write: (value: unknown) => {\n value: SerializedCellValue;\n metadata?: unknown;\n };\n}\n\ntype Headers<TCellMetadata> = Record<\n string,\n {\n parse: (value: SerializedCellValue, metadata: TCellMetadata) => unknown;\n write: (value: any) => {\n value: SerializedCellValue;\n metadata?: TCellMetadata;\n };\n index: number;\n }\n>;\n\n/**\n * Type representing the TableOrm methods exposed on the schema\n */\nexport type TableOrmSchema<TItem extends Record<string, unknown>> = {\n findWhere(filter: Partial<TItem>): TItem | undefined;\n findAllWhere(filter: Partial<TItem>): TItem[];\n append(item: TItem): TItem;\n updateWhere(filter: Partial<TItem>, update: Partial<TItem>): number;\n removeWhere(filter: Partial<TItem>): number;\n count(): number;\n};\n\n/**\n * Type representing the CellOrm methods exposed on the schema\n */\nexport type CellOrmSchema<TValue> = {\n read(): TValue;\n write(value: TValue): void;\n getAddress(): CellAddress;\n};\n\n/**\n * Type representing the GridOrm methods exposed on the schema\n */\nexport type GridOrmSchema<TValue> = {\n columns: readonly TValue[][];\n rows: readonly TValue[][];\n setValue(value: TValue, position: { col: number; row: number }): void;\n getValue(position: { col: number; row: number }): TValue;\n};\n\nexport type SchemaDeclaration = Record<\n string,\n TableSchemaDefinition | CellSchemaDefinition | GridSchemaDefinition\n>;\nexport type Schema = Record<string, object>;\n\n/**\n * Write function type for converting parsed values back to serializable form\n */\ntype WriteFunction<TValue, TCellMetadata> = (value: TValue) => {\n value: SerializedCellValue;\n metadata?: TCellMetadata;\n};\n\n/**\n * Helper type to create the return type for addCellSchema/addGridSchema\n */\ntype AddCellSchemaResult<\n TCellMetadata,\n TCurrentSchema extends Schema,\n TCurrentDeclaration extends SchemaDeclaration,\n T extends string,\n TValue\n> = CreateSchema<\n TCellMetadata,\n TCurrentSchema & {\n [K in T]: CellOrmSchema<TValue>;\n },\n TCurrentDeclaration & {\n [K in T]: {\n type: \"cell\";\n cellAddress: CellAddress;\n parse: (value: unknown, metadata: unknown) => unknown;\n };\n }\n>;\n\ntype AddGridSchemaResult<\n TCellMetadata,\n TCurrentSchema extends Schema,\n TCurrentDeclaration extends SchemaDeclaration,\n T extends string,\n TValue\n> = CreateSchema<\n TCellMetadata,\n TCurrentSchema & {\n [K in T]: GridOrmSchema<TValue>;\n },\n TCurrentDeclaration & {\n [K in T]: {\n type: \"grid\";\n workbookName: string;\n sheetName: string;\n range: FiniteSpreadsheetRange;\n parse: (value: unknown, metadata: unknown) => unknown;\n };\n }\n>;\n\nexport type CreateSchema<\n TCellMetadata,\n TCurrentSchema extends Schema,\n TCurrentDeclaration extends SchemaDeclaration\n> = {\n addTableSchema<T extends string, THeaders extends Headers<TCellMetadata>>(\n namespace: T,\n address: { workbookName: string; tableName: string },\n headers: THeaders\n ): CreateSchema<\n TCellMetadata,\n TCurrentSchema & {\n [K in T]: TableOrmSchema<{\n [H in keyof THeaders]: ReturnType<THeaders[H][\"parse\"]>;\n }>;\n },\n TCurrentDeclaration & {\n [K in T]: {\n type: \"table\";\n tableName: string;\n workbookName: string;\n headers: THeaders;\n };\n }\n >;\n\n // Overload 1: TValue is any type - write is required\n addCellSchema<T extends string, TValue>(\n namespace: T,\n cellAddress: CellAddress,\n parse: (value: unknown, metadata: TCellMetadata) => TValue,\n write: WriteFunction<TValue, TCellMetadata>\n ): AddCellSchemaResult<TCellMetadata, TCurrentSchema, TCurrentDeclaration, T, TValue>;\n\n // Overload 2: TValue extends SerializedCellValue - write is optional\n addCellSchema<T extends string, TValue extends SerializedCellValue>(\n namespace: T,\n cellAddress: CellAddress,\n parse: (value: unknown, metadata: TCellMetadata) => TValue,\n write?: WriteFunction<TValue, TCellMetadata>\n ): AddCellSchemaResult<TCellMetadata, TCurrentSchema, TCurrentDeclaration, T, TValue>;\n\n // Overload 1: TValue is any type - write is required\n addGridSchema<T extends string, TValue>(\n namespace: T,\n address: { workbookName: string; sheetName: string },\n range: FiniteSpreadsheetRange,\n parse: (value: unknown, metadata: TCellMetadata) => TValue,\n write: WriteFunction<TValue, TCellMetadata>\n ): AddGridSchemaResult<TCellMetadata, TCurrentSchema, TCurrentDeclaration, T, TValue>;\n\n // Overload 2: TValue extends SerializedCellValue - write is optional\n addGridSchema<T extends string, TValue extends SerializedCellValue>(\n namespace: T,\n address: { workbookName: string; sheetName: string },\n range: FiniteSpreadsheetRange,\n parse: (value: unknown, metadata: TCellMetadata) => TValue,\n write?: WriteFunction<TValue, TCellMetadata>\n ): AddGridSchemaResult<TCellMetadata, TCurrentSchema, TCurrentDeclaration, T, TValue>;\n\n schema: TCurrentSchema;\n declaration: TCurrentDeclaration;\n};\n\nexport const createHeader = <TValue, TMetadata>(\n index: number,\n parse: (value: SerializedCellValue, metadata: TMetadata) => TValue,\n write?: (value: TValue) => {\n value: SerializedCellValue;\n metadata?: TMetadata;\n }\n) => {\n return {\n parse,\n write: write ?? ((value) => ({ value })),\n index,\n };\n};\n"
5
+ "import type {\n CellAddress,\n FiniteSpreadsheetRange,\n SerializedCellValue,\n} from \"../types.mjs\";\n\n/**\n * Define a schema for the FormulaEngine.\n *\n * The returned object contains:\n * - `declaration`: The schema definitions for tables and cells\n * - `schema`: A type-only placeholder (undefined at runtime) for TypeScript inference\n *\n * The actual working schema is only available through `engine.schema` after\n * attaching the definition to a FormulaEngine instance.\n *\n * @example\n * ```typescript\n * const mySchema = defineSchema<CellMetadata>()\n * .addTableSchema(\"users\", { workbookName: \"wb1\", tableName: \"users\" }, headers)\n * .addCellSchema(\"config\", cellAddress, parse);\n *\n * const engine = new FormulaEngine(mySchema);\n * engine.schema.users.findWhere({ id: 1 }); // Works!\n * engine.schema.config.read(); // Works!\n * mySchema.schema.users.findWhere({ id: 1 }); // Error: schema is undefined at runtime\n * ```\n */\nexport function defineSchema<\n TCellMetadata = unknown,\n TCurrentSchema extends Record<string, object> = Record<string, object>,\n TCurrentDeclaration extends Record<\n string,\n TableSchemaDefinition | CellSchemaDefinition | GridSchemaDefinition\n > = Record<\n string,\n TableSchemaDefinition | CellSchemaDefinition | GridSchemaDefinition\n >\n>(): CreateSchema<TCellMetadata, TCurrentSchema, TCurrentDeclaration> {\n const declaration: Record<\n string,\n TableSchemaDefinition | CellSchemaDefinition | GridSchemaDefinition\n > = {};\n\n const builder: CreateSchema<\n TCellMetadata,\n TCurrentSchema,\n TCurrentDeclaration\n > = {\n addTableSchema(namespace, address, headers) {\n declaration[namespace] = {\n type: \"table\",\n tableName: address.tableName,\n workbookName: address.workbookName,\n headers: headers as any,\n };\n return builder as any;\n },\n\n addCellSchema(\n namespace: string,\n cellAddress: CellAddress,\n parse: any,\n write?: any\n ) {\n declaration[namespace] = {\n type: \"cell\",\n cellAddress,\n parse,\n write: write ?? ((value: unknown) => ({ value: value as SerializedCellValue })),\n };\n return builder as any;\n },\n\n addGridSchema(\n namespace: string,\n address: { workbookName: string; sheetName: string },\n range: FiniteSpreadsheetRange,\n parse: any,\n write?: any\n ) {\n declaration[namespace] = {\n type: \"grid\",\n workbookName: address.workbookName,\n sheetName: address.sheetName,\n range,\n parse,\n write: write ?? ((value: unknown) => ({ value: value as SerializedCellValue })),\n };\n return builder as any;\n },\n\n // schema is undefined at runtime - it only exists for TypeScript type inference\n // The actual working schema is built by the FormulaEngine constructor\n schema: undefined as any as TCurrentSchema,\n\n declaration: declaration as TCurrentDeclaration,\n };\n\n return builder;\n}\n\nexport interface TableSchemaDefinition {\n type: \"table\";\n headers: Headers<unknown>;\n tableName: string;\n workbookName: string;\n}\n\nexport interface CellSchemaDefinition {\n type: \"cell\";\n cellAddress: CellAddress;\n parse: (value: unknown, metadata: unknown) => unknown;\n write: (value: unknown) => {\n value: SerializedCellValue;\n metadata?: unknown;\n };\n}\n\nexport interface GridSchemaDefinition {\n type: \"grid\";\n workbookName: string;\n sheetName: string;\n range: FiniteSpreadsheetRange;\n parse: (value: unknown, metadata: unknown) => unknown;\n write: (value: unknown) => {\n value: SerializedCellValue;\n metadata?: unknown;\n };\n}\n\ntype Headers<TCellMetadata> = Record<\n string,\n {\n parse: (value: SerializedCellValue, metadata: TCellMetadata) => unknown;\n write: (value: any) => {\n value: SerializedCellValue;\n metadata?: TCellMetadata;\n };\n index: number;\n }\n>;\n\n/**\n * Type representing the TableOrm methods exposed on the schema\n */\nexport type TableOrmSchema<TItem extends Record<string, unknown>> = {\n findWhere(filter: Partial<TItem>): TItem | undefined;\n findAllWhere(filter: Partial<TItem>): TItem[];\n append(item: TItem): TItem;\n updateWhere(filter: Partial<TItem>, update: Partial<TItem>): number;\n removeWhere(filter: Partial<TItem>): number;\n count(): number;\n};\n\n/**\n * Type representing the CellOrm methods exposed on the schema\n */\nexport type CellOrmSchema<TValue> = {\n read(): TValue;\n write(value: TValue): void;\n getAddress(): CellAddress;\n};\n\n/**\n * Type representing the GridOrm methods exposed on the schema\n */\nexport type GridOrmSchema<TValue> = {\n columns: readonly TValue[][];\n rows: readonly TValue[][];\n setValue(value: TValue, position: { col: number; row: number }): void;\n getValue(position: { col: number; row: number }): TValue;\n};\n\nexport type SchemaDeclaration = Record<\n string,\n TableSchemaDefinition | CellSchemaDefinition | GridSchemaDefinition\n>;\nexport type Schema = Record<string, object>;\n\n/**\n * Write function type for converting parsed values back to serializable form\n */\ntype WriteFunction<TValue, TCellMetadata> = (value: TValue) => {\n value: SerializedCellValue;\n metadata?: TCellMetadata;\n};\n\n/**\n * Helper type to create the return type for addCellSchema/addGridSchema\n */\ntype AddCellSchemaResult<\n TCellMetadata,\n TCurrentSchema extends Schema,\n TCurrentDeclaration extends SchemaDeclaration,\n T extends string,\n TValue\n> = CreateSchema<\n TCellMetadata,\n TCurrentSchema & {\n [K in T]: CellOrmSchema<TValue>;\n },\n TCurrentDeclaration & {\n [K in T]: {\n type: \"cell\";\n cellAddress: CellAddress;\n parse: (value: unknown, metadata: unknown) => unknown;\n };\n }\n>;\n\ntype AddGridSchemaResult<\n TCellMetadata,\n TCurrentSchema extends Schema,\n TCurrentDeclaration extends SchemaDeclaration,\n T extends string,\n TValue\n> = CreateSchema<\n TCellMetadata,\n TCurrentSchema & {\n [K in T]: GridOrmSchema<TValue>;\n },\n TCurrentDeclaration & {\n [K in T]: {\n type: \"grid\";\n workbookName: string;\n sheetName: string;\n range: FiniteSpreadsheetRange;\n parse: (value: unknown, metadata: unknown) => unknown;\n };\n }\n>;\n\nexport type CreateSchema<\n TCellMetadata,\n TCurrentSchema extends Schema,\n TCurrentDeclaration extends SchemaDeclaration\n> = {\n addTableSchema<T extends string, THeaders extends Headers<TCellMetadata>>(\n namespace: T,\n address: { workbookName: string; tableName: string },\n headers: THeaders\n ): CreateSchema<\n TCellMetadata,\n TCurrentSchema & {\n [K in T]: TableOrmSchema<{\n [H in keyof THeaders]: ReturnType<THeaders[H][\"parse\"]>;\n }>;\n },\n TCurrentDeclaration & {\n [K in T]: {\n type: \"table\";\n tableName: string;\n workbookName: string;\n headers: THeaders;\n };\n }\n >;\n\n // Overload 1: TValue is any type - write is required\n addCellSchema<T extends string, TValue>(\n namespace: T,\n cellAddress: CellAddress,\n parse: (value: unknown, metadata: TCellMetadata) => TValue,\n write: WriteFunction<TValue, TCellMetadata>\n ): AddCellSchemaResult<TCellMetadata, TCurrentSchema, TCurrentDeclaration, T, TValue>;\n\n // Overload 2: TValue extends SerializedCellValue - write is optional\n addCellSchema<T extends string, TValue extends SerializedCellValue>(\n namespace: T,\n cellAddress: CellAddress,\n parse: (value: unknown, metadata: TCellMetadata) => TValue,\n write?: WriteFunction<TValue, TCellMetadata>\n ): AddCellSchemaResult<TCellMetadata, TCurrentSchema, TCurrentDeclaration, T, TValue>;\n\n // Overload 1: TValue is any type - write is required\n addGridSchema<T extends string, TValue>(\n namespace: T,\n address: { workbookName: string; sheetName: string },\n range: FiniteSpreadsheetRange,\n parse: (value: unknown, metadata: TCellMetadata) => TValue,\n write: WriteFunction<TValue, TCellMetadata>\n ): AddGridSchemaResult<TCellMetadata, TCurrentSchema, TCurrentDeclaration, T, TValue>;\n\n // Overload 2: TValue extends SerializedCellValue - write is optional\n addGridSchema<T extends string, TValue extends SerializedCellValue>(\n namespace: T,\n address: { workbookName: string; sheetName: string },\n range: FiniteSpreadsheetRange,\n parse: (value: unknown, metadata: TCellMetadata) => TValue,\n write?: WriteFunction<TValue, TCellMetadata>\n ): AddGridSchemaResult<TCellMetadata, TCurrentSchema, TCurrentDeclaration, T, TValue>;\n\n schema: TCurrentSchema;\n declaration: TCurrentDeclaration;\n};\n\nexport const defineHeader = <TValue, TMetadata>(\n index: number,\n parse: (value: SerializedCellValue, metadata: TMetadata) => TValue,\n write?: (value: TValue) => {\n value: SerializedCellValue;\n metadata?: TMetadata;\n }\n) => {\n return {\n parse,\n write: write ?? ((value) => ({ value })),\n index,\n };\n};\n"
6
6
  ],
7
7
  "mappings": ";AA4BO,SAAS,YAUf,GAAqE;AAAA,EACpE,MAAM,cAGF,CAAC;AAAA,EAEL,MAAM,UAIF;AAAA,IACF,cAAc,CAAC,WAAW,SAAS,SAAS;AAAA,MAC1C,YAAY,aAAa;AAAA,QACvB,MAAM;AAAA,QACN,WAAW,QAAQ;AAAA,QACnB,cAAc,QAAQ;AAAA,QACtB;AAAA,MACF;AAAA,MACA,OAAO;AAAA;AAAA,IAGT,aAAa,CACX,WACA,aACA,OACA,OACA;AAAA,MACA,YAAY,aAAa;AAAA,QACvB,MAAM;AAAA,QACN;AAAA,QACA;AAAA,QACA,OAAO,UAAU,CAAC,WAAoB,EAAE,MAAoC;AAAA,MAC9E;AAAA,MACA,OAAO;AAAA;AAAA,IAGT,aAAa,CACX,WACA,SACA,OACA,OACA,OACA;AAAA,MACA,YAAY,aAAa;AAAA,QACvB,MAAM;AAAA,QACN,cAAc,QAAQ;AAAA,QACtB,WAAW,QAAQ;AAAA,QACnB;AAAA,QACA;AAAA,QACA,OAAO,UAAU,CAAC,WAAoB,EAAE,MAAoC;AAAA,MAC9E;AAAA,MACA,OAAO;AAAA;AAAA,IAKT,QAAQ;AAAA,IAER;AAAA,EACF;AAAA,EAEA,OAAO;AAAA;AAsMF,IAAM,eAAe,CAC1B,OACA,OACA,UAIG;AAAA,EACH,OAAO;AAAA,IACL;AAAA,IACA,OAAO,UAAU,CAAC,WAAW,EAAE,MAAM;AAAA,IACrC;AAAA,EACF;AAAA;",
8
- "debugId": "50A63DDDAA5631D564756E2164756E21",
8
+ "debugId": "5C9087F143083A7464756E2164756E21",
9
9
  "names": []
10
10
  }
package/dist/mjs/lib.mjs CHANGED
@@ -4,13 +4,14 @@ import { FormulaEngine } from "./core/engine.mjs";
4
4
  export * from "./core/types.mjs";
5
5
  export * from "./core/utils.mjs";
6
6
  export * from "./core/utils/color-utils.mjs";
7
- import { defineSchema } from "./core/schema/schema.mjs";
7
+ import { defineSchema, defineHeader } from "./core/schema/schema.mjs";
8
8
  import { TableOrm } from "./core/schema/table-orm.mjs";
9
9
  import { CellOrm } from "./core/schema/cell-orm.mjs";
10
10
  import { SchemaValidationError } from "./core/managers/schema-manager.mjs";
11
11
  import { SchemaIntegrityError } from "./core/commands/command-executor.mjs";
12
12
  export {
13
13
  defineSchema,
14
+ defineHeader,
14
15
  TableOrm,
15
16
  SchemaValidationError,
16
17
  SchemaIntegrityError,
@@ -18,4 +19,4 @@ export {
18
19
  CellOrm
19
20
  };
20
21
 
21
- //# debugId=14E82C883ABC721064756E2164756E21
22
+ //# debugId=D42F2BBEF074B4FE64756E2164756E21
@@ -2,9 +2,9 @@
2
2
  "version": 3,
3
3
  "sources": ["../../src/lib.ts"],
4
4
  "sourcesContent": [
5
- "export { FormulaEngine } from \"./core/engine.mjs\";\nexport * from \"./core/types.mjs\";\nexport * from \"./core/utils.mjs\";\nexport * from \"./core/utils/color-utils.mjs\";\n\n// Schema exports\nexport { defineSchema } from \"./core/schema/schema.mjs\";\nexport type { CreateSchema, SchemaDeclaration, Schema, TableSchemaDefinition, CellSchemaDefinition, TableOrmSchema, CellOrmSchema } from \"./core/schema/schema.mjs\";\nexport { TableOrm } from \"./core/schema/table-orm.mjs\";\nexport { CellOrm } from \"./core/schema/cell-orm.mjs\";\nexport { SchemaValidationError } from \"./core/managers/schema-manager.mjs\";\nexport type { ValidationResult } from \"./core/managers/schema-manager.mjs\";\n\n// Command Pattern exports\nexport { SchemaIntegrityError } from \"./core/commands/command-executor.mjs\";\nexport type { EngineAction, EngineCommand } from \"./core/commands/types.mjs\";\n"
5
+ "export { FormulaEngine } from \"./core/engine.mjs\";\nexport * from \"./core/types.mjs\";\nexport * from \"./core/utils.mjs\";\nexport * from \"./core/utils/color-utils.mjs\";\n\n// Schema exports\nexport { defineSchema, defineHeader } from \"./core/schema/schema.mjs\";\nexport type { CreateSchema, SchemaDeclaration, Schema, TableSchemaDefinition, CellSchemaDefinition, TableOrmSchema, CellOrmSchema } from \"./core/schema/schema.mjs\";\nexport { TableOrm } from \"./core/schema/table-orm.mjs\";\nexport { CellOrm } from \"./core/schema/cell-orm.mjs\";\nexport { SchemaValidationError } from \"./core/managers/schema-manager.mjs\";\nexport type { ValidationResult } from \"./core/managers/schema-manager.mjs\";\n\n// Command Pattern exports\nexport { SchemaIntegrityError } from \"./core/commands/command-executor.mjs\";\nexport type { EngineAction, EngineCommand } from \"./core/commands/types.mjs\";\n"
6
6
  ],
7
7
  "mappings": ";AAAA;AAAA;AACA;AACA;AACA;AAGA;AAEA;AACA;AACA;AAIA;",
8
- "debugId": "14E82C883ABC721064756E2164756E21",
8
+ "debugId": "D42F2BBEF074B4FE64756E2164756E21",
9
9
  "names": []
10
10
  }
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "@ricsam/formula-engine",
3
- "version": "0.1.0",
3
+ "version": "0.2.1",
4
4
  "type": "module"
5
5
  }
@@ -7,7 +7,7 @@
7
7
  import type { CellAddress, FiniteSpreadsheetRange, SerializedCellValue, SpreadsheetRange, TableDefinition } from "../types";
8
8
  import type { TableManager } from "./table-manager";
9
9
  export type ParseFunction<TCellMetadata = unknown> = (value: SerializedCellValue, metadata: TCellMetadata) => unknown;
10
- export type WriteFunction<TCellMetadata = unknown> = (value: unknown) => {
10
+ export type WriteFunction<TCellMetadata = unknown> = (value: any) => {
11
11
  value: SerializedCellValue;
12
12
  metadata?: TCellMetadata;
13
13
  };
@@ -151,7 +151,7 @@ export type CreateSchema<TCellMetadata, TCurrentSchema extends Schema, TCurrentD
151
151
  schema: TCurrentSchema;
152
152
  declaration: TCurrentDeclaration;
153
153
  };
154
- export declare const createHeader: <TValue, TMetadata>(index: number, parse: (value: SerializedCellValue, metadata: TMetadata) => TValue, write?: (value: TValue) => {
154
+ export declare const defineHeader: <TValue, TMetadata>(index: number, parse: (value: SerializedCellValue, metadata: TMetadata) => TValue, write?: (value: TValue) => {
155
155
  value: SerializedCellValue;
156
156
  metadata?: TMetadata;
157
157
  }) => {
@@ -2,7 +2,7 @@ export { FormulaEngine } from "./core/engine";
2
2
  export * from "./core/types";
3
3
  export * from "./core/utils";
4
4
  export * from "./core/utils/color-utils";
5
- export { defineSchema } from "./core/schema/schema";
5
+ export { defineSchema, defineHeader } from "./core/schema/schema";
6
6
  export type { CreateSchema, SchemaDeclaration, Schema, TableSchemaDefinition, CellSchemaDefinition, TableOrmSchema, CellOrmSchema } from "./core/schema/schema";
7
7
  export { TableOrm } from "./core/schema/table-orm";
8
8
  export { CellOrm } from "./core/schema/cell-orm";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ricsam/formula-engine",
3
- "version": "0.1.0",
3
+ "version": "0.2.1",
4
4
  "module": "./dist/mjs/lib.mjs",
5
5
  "scripts": {
6
6
  "test": "bun test",