@ricsam/formula-engine 0.0.21 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. package/dist/cjs/core/commands/command-executor.cjs +3 -5
  2. package/dist/cjs/core/commands/command-executor.cjs.map +3 -3
  3. package/dist/cjs/core/commands/structure-commands.cjs.map +1 -1
  4. package/dist/cjs/core/commands/table-commands.cjs.map +1 -1
  5. package/dist/cjs/core/engine.cjs +56 -42
  6. package/dist/cjs/core/engine.cjs.map +3 -3
  7. package/dist/cjs/core/managers/{api-schema-manager.cjs → schema-manager.cjs} +67 -7
  8. package/dist/cjs/core/managers/schema-manager.cjs.map +10 -0
  9. package/dist/cjs/core/{api → schema}/cell-orm.cjs +9 -23
  10. package/dist/cjs/core/schema/cell-orm.cjs.map +10 -0
  11. package/dist/cjs/core/schema/grid-orm.cjs +115 -0
  12. package/dist/cjs/core/schema/grid-orm.cjs.map +10 -0
  13. package/dist/cjs/core/{api/api-builder.cjs → schema/schema-builder.cjs} +21 -14
  14. package/dist/cjs/core/schema/schema-builder.cjs.map +10 -0
  15. package/dist/cjs/core/{api/api-helpers.cjs → schema/schema-helpers.cjs} +12 -13
  16. package/dist/cjs/core/schema/schema-helpers.cjs.map +10 -0
  17. package/dist/cjs/core/{api/api.cjs → schema/schema.cjs} +31 -13
  18. package/dist/cjs/core/schema/schema.cjs.map +10 -0
  19. package/dist/cjs/core/{api → schema}/table-orm.cjs +27 -19
  20. package/dist/cjs/core/schema/table-orm.cjs.map +10 -0
  21. package/dist/cjs/lib.cjs +7 -8
  22. package/dist/cjs/lib.cjs.map +3 -3
  23. package/dist/cjs/package.json +1 -1
  24. package/dist/mjs/core/commands/command-executor.mjs +3 -5
  25. package/dist/mjs/core/commands/command-executor.mjs.map +3 -3
  26. package/dist/mjs/core/commands/structure-commands.mjs.map +1 -1
  27. package/dist/mjs/core/commands/table-commands.mjs.map +1 -1
  28. package/dist/mjs/core/engine.mjs +57 -43
  29. package/dist/mjs/core/engine.mjs.map +3 -3
  30. package/dist/mjs/core/managers/{api-schema-manager.mjs → schema-manager.mjs} +64 -4
  31. package/dist/mjs/core/managers/schema-manager.mjs.map +10 -0
  32. package/dist/mjs/core/schema/cell-orm.mjs +35 -0
  33. package/dist/mjs/core/schema/cell-orm.mjs.map +10 -0
  34. package/dist/mjs/core/schema/grid-orm.mjs +84 -0
  35. package/dist/mjs/core/schema/grid-orm.mjs.map +10 -0
  36. package/dist/mjs/core/schema/schema-builder.mjs +34 -0
  37. package/dist/mjs/core/schema/schema-builder.mjs.map +10 -0
  38. package/dist/mjs/core/{api/api-helpers.mjs → schema/schema-helpers.mjs} +9 -10
  39. package/dist/mjs/core/schema/schema-helpers.mjs.map +10 -0
  40. package/dist/mjs/core/schema/schema.mjs +51 -0
  41. package/dist/mjs/core/schema/schema.mjs.map +10 -0
  42. package/dist/mjs/core/{api → schema}/table-orm.mjs +13 -5
  43. package/dist/mjs/core/schema/table-orm.mjs.map +10 -0
  44. package/dist/mjs/lib.mjs +6 -7
  45. package/dist/mjs/lib.mjs.map +2 -2
  46. package/dist/mjs/package.json +1 -1
  47. package/dist/types/core/commands/command-executor.d.ts +1 -3
  48. package/dist/types/core/commands/structure-commands.d.ts +2 -2
  49. package/dist/types/core/commands/table-commands.d.ts +2 -2
  50. package/dist/types/core/engine.d.ts +34 -7
  51. package/dist/types/core/managers/{api-schema-manager.d.ts → schema-manager.d.ts} +26 -5
  52. package/dist/types/core/{api → schema}/cell-orm.d.ts +8 -4
  53. package/dist/types/core/schema/grid-orm.d.ts +63 -0
  54. package/dist/types/core/schema/schema-builder.d.ts +16 -0
  55. package/dist/types/core/{api/api-helpers.d.ts → schema/schema-helpers.d.ts} +16 -4
  56. package/dist/types/core/schema/schema.d.ts +167 -0
  57. package/dist/types/core/{api → schema}/table-orm.d.ts +1 -1
  58. package/dist/types/lib.d.ts +6 -6
  59. package/package.json +1 -1
  60. package/dist/cjs/core/api/api-builder.cjs.map +0 -10
  61. package/dist/cjs/core/api/api-helpers.cjs.map +0 -10
  62. package/dist/cjs/core/api/api.cjs.map +0 -10
  63. package/dist/cjs/core/api/cell-orm.cjs.map +0 -10
  64. package/dist/cjs/core/api/table-orm.cjs.map +0 -10
  65. package/dist/cjs/core/managers/api-schema-manager.cjs.map +0 -10
  66. package/dist/mjs/core/api/api-builder.mjs +0 -27
  67. package/dist/mjs/core/api/api-builder.mjs.map +0 -10
  68. package/dist/mjs/core/api/api-helpers.mjs.map +0 -10
  69. package/dist/mjs/core/api/api.mjs +0 -33
  70. package/dist/mjs/core/api/api.mjs.map +0 -10
  71. package/dist/mjs/core/api/cell-orm.mjs +0 -49
  72. package/dist/mjs/core/api/cell-orm.mjs.map +0 -10
  73. package/dist/mjs/core/api/table-orm.mjs.map +0 -10
  74. package/dist/mjs/core/managers/api-schema-manager.mjs.map +0 -10
  75. package/dist/types/core/api/api-builder.d.ts +0 -16
  76. package/dist/types/core/api/api.d.ts +0 -91
  77. /package/dist/types/core/{api/api.type-test.d.ts → schema/schema.type-test.d.ts} +0 -0
@@ -0,0 +1,63 @@
1
+ /**
2
+ * GridOrm - Object-Relational Mapping for grid/range data
3
+ *
4
+ * Provides read/write operations for a 2D range of cells with type-safe access.
5
+ * Supports both column-major and row-major array access patterns.
6
+ */
7
+ import type { FiniteSpreadsheetRange, SerializedCellValue } from "../types";
8
+ import type { FormulaEngine } from "../engine";
9
+ export type GridParseFunction<TCellMetadata, TValue> = (value: unknown, metadata: TCellMetadata) => TValue;
10
+ export type GridWriteFunction<TCellMetadata, TValue> = (value: TValue) => {
11
+ value: SerializedCellValue;
12
+ metadata?: TCellMetadata;
13
+ };
14
+ export declare class GridOrm<TValue, TCellMetadata = unknown> {
15
+ private engine;
16
+ private workbookName;
17
+ private sheetName;
18
+ private range;
19
+ private parser;
20
+ private writer;
21
+ private namespace;
22
+ private numCols;
23
+ private numRows;
24
+ constructor(engine: FormulaEngine<any, any>, workbookName: string, sheetName: string, range: FiniteSpreadsheetRange, parser: GridParseFunction<TCellMetadata, TValue>, writer: GridWriteFunction<TCellMetadata, TValue>, namespace: string);
25
+ /**
26
+ * Get the cell address for a given column and row index within the grid
27
+ */
28
+ private getCellAddress;
29
+ /**
30
+ * Read a single cell and parse it
31
+ */
32
+ private readCell;
33
+ /**
34
+ * Write a single cell using the write function
35
+ */
36
+ private writeCell;
37
+ /**
38
+ * Get all cells as a column-major 2D array (readonly)
39
+ * columns[colIndex][rowIndex]
40
+ */
41
+ get columns(): readonly (readonly TValue[])[];
42
+ /**
43
+ * Get all cells as a row-major 2D array (readonly)
44
+ * rows[rowIndex][colIndex]
45
+ */
46
+ get rows(): readonly (readonly TValue[])[];
47
+ /**
48
+ * Set a single value at the specified position
49
+ * Position is relative to the grid (0-indexed)
50
+ */
51
+ setValue(value: TValue, position: {
52
+ col: number;
53
+ row: number;
54
+ }): void;
55
+ /**
56
+ * Get a single value at the specified position
57
+ * Position is relative to the grid (0-indexed)
58
+ */
59
+ getValue(position: {
60
+ col: number;
61
+ row: number;
62
+ }): TValue;
63
+ }
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Schema Builder - Constructs the working schema from declarations
3
+ *
4
+ * This module is responsible for creating the actual working schema
5
+ * from the schema declarations when attached to a FormulaEngine.
6
+ */
7
+ import type { FormulaEngine } from "../engine";
8
+ import type { SchemaDeclaration, Schema } from "./schema";
9
+ import type { SchemaManager } from "../managers/schema-manager";
10
+ /**
11
+ * Build the working schema surface from declarations
12
+ *
13
+ * This creates TableOrm, CellOrm, and GridOrm instances for each declared schema
14
+ * and returns them directly.
15
+ */
16
+ export declare function buildSchemaFromDeclaration(engine: FormulaEngine<any, any>, declaration: SchemaDeclaration, schemaManager: SchemaManager): Schema;
@@ -1,11 +1,16 @@
1
1
  /**
2
- * API Helper utilities for row/object conversion and filtering
2
+ * Schema Helper utilities for row/object conversion and filtering
3
3
  */
4
4
  import type { CellAddress, SerializedCellValue, TableDefinition } from "../types";
5
5
  import type { FormulaEngine } from "../engine";
6
- export type ParseFunction<TCellMetadata = unknown> = (value: unknown, metadata: TCellMetadata) => unknown;
6
+ export type ParseFunction<TCellMetadata = unknown> = (value: SerializedCellValue, metadata: TCellMetadata) => unknown;
7
+ export type WriteFunction<TCellMetadata = unknown> = (value: unknown) => {
8
+ value: SerializedCellValue;
9
+ metadata?: TCellMetadata;
10
+ };
7
11
  export type TableSchemaHeaders<TCellMetadata = unknown> = Record<string, {
8
12
  parse: ParseFunction<TCellMetadata>;
13
+ write: WriteFunction<TCellMetadata>;
9
14
  index: number;
10
15
  }>;
11
16
  /**
@@ -13,9 +18,16 @@ export type TableSchemaHeaders<TCellMetadata = unknown> = Record<string, {
13
18
  */
14
19
  export declare function rowToObject<TItem extends Record<string, unknown>>(engine: FormulaEngine<any, any>, table: TableDefinition, rowIndex: number, headers: TableSchemaHeaders, getCellMetadata?: (cell: CellAddress) => unknown): TItem;
15
20
  /**
16
- * Convert a typed object to cell values based on headers
21
+ * Result from objectToRowValues including both values and optional metadata
17
22
  */
18
- export declare function objectToRowValues<TItem extends Record<string, unknown>>(obj: TItem, headers: TableSchemaHeaders): Map<number, SerializedCellValue>;
23
+ export type RowValuesResult<TCellMetadata = unknown> = {
24
+ values: Map<number, SerializedCellValue>;
25
+ metadata: Map<number, TCellMetadata>;
26
+ };
27
+ /**
28
+ * Convert a typed object to cell values based on headers using write functions
29
+ */
30
+ export declare function objectToRowValues<TItem extends Record<string, unknown>, TCellMetadata = unknown>(obj: TItem, headers: TableSchemaHeaders<TCellMetadata>): RowValuesResult<TCellMetadata>;
19
31
  /**
20
32
  * Check if an object matches a filter predicate
21
33
  */
@@ -0,0 +1,167 @@
1
+ import type { CellAddress, FiniteSpreadsheetRange, SerializedCellValue } from "../types";
2
+ /**
3
+ * Define a schema for the FormulaEngine.
4
+ *
5
+ * The returned object contains:
6
+ * - `declaration`: The schema definitions for tables and cells
7
+ * - `schema`: A type-only placeholder (undefined at runtime) for TypeScript inference
8
+ *
9
+ * The actual working schema is only available through `engine.schema` after
10
+ * attaching the definition to a FormulaEngine instance.
11
+ *
12
+ * @example
13
+ * ```typescript
14
+ * const mySchema = defineSchema<CellMetadata>()
15
+ * .addTableSchema("users", { workbookName: "wb1", tableName: "users" }, headers)
16
+ * .addCellSchema("config", cellAddress, parse);
17
+ *
18
+ * const engine = new FormulaEngine(mySchema);
19
+ * engine.schema.users.findWhere({ id: 1 }); // Works!
20
+ * engine.schema.config.read(); // Works!
21
+ * mySchema.schema.users.findWhere({ id: 1 }); // Error: schema is undefined at runtime
22
+ * ```
23
+ */
24
+ export declare function defineSchema<TCellMetadata = unknown, TCurrentSchema extends Record<string, object> = Record<string, object>, TCurrentDeclaration extends Record<string, TableSchemaDefinition | CellSchemaDefinition | GridSchemaDefinition> = Record<string, TableSchemaDefinition | CellSchemaDefinition | GridSchemaDefinition>>(): CreateSchema<TCellMetadata, TCurrentSchema, TCurrentDeclaration>;
25
+ export interface TableSchemaDefinition {
26
+ type: "table";
27
+ headers: Headers<unknown>;
28
+ tableName: string;
29
+ workbookName: string;
30
+ }
31
+ export interface CellSchemaDefinition {
32
+ type: "cell";
33
+ cellAddress: CellAddress;
34
+ parse: (value: unknown, metadata: unknown) => unknown;
35
+ write: (value: unknown) => {
36
+ value: SerializedCellValue;
37
+ metadata?: unknown;
38
+ };
39
+ }
40
+ export interface GridSchemaDefinition {
41
+ type: "grid";
42
+ workbookName: string;
43
+ sheetName: string;
44
+ range: FiniteSpreadsheetRange;
45
+ parse: (value: unknown, metadata: unknown) => unknown;
46
+ write: (value: unknown) => {
47
+ value: SerializedCellValue;
48
+ metadata?: unknown;
49
+ };
50
+ }
51
+ type Headers<TCellMetadata> = Record<string, {
52
+ parse: (value: SerializedCellValue, metadata: TCellMetadata) => unknown;
53
+ write: (value: any) => {
54
+ value: SerializedCellValue;
55
+ metadata?: TCellMetadata;
56
+ };
57
+ index: number;
58
+ }>;
59
+ /**
60
+ * Type representing the TableOrm methods exposed on the schema
61
+ */
62
+ export type TableOrmSchema<TItem extends Record<string, unknown>> = {
63
+ findWhere(filter: Partial<TItem>): TItem | undefined;
64
+ findAllWhere(filter: Partial<TItem>): TItem[];
65
+ append(item: TItem): TItem;
66
+ updateWhere(filter: Partial<TItem>, update: Partial<TItem>): number;
67
+ removeWhere(filter: Partial<TItem>): number;
68
+ count(): number;
69
+ };
70
+ /**
71
+ * Type representing the CellOrm methods exposed on the schema
72
+ */
73
+ export type CellOrmSchema<TValue> = {
74
+ read(): TValue;
75
+ write(value: TValue): void;
76
+ getAddress(): CellAddress;
77
+ };
78
+ /**
79
+ * Type representing the GridOrm methods exposed on the schema
80
+ */
81
+ export type GridOrmSchema<TValue> = {
82
+ columns: readonly TValue[][];
83
+ rows: readonly TValue[][];
84
+ setValue(value: TValue, position: {
85
+ col: number;
86
+ row: number;
87
+ }): void;
88
+ getValue(position: {
89
+ col: number;
90
+ row: number;
91
+ }): TValue;
92
+ };
93
+ export type SchemaDeclaration = Record<string, TableSchemaDefinition | CellSchemaDefinition | GridSchemaDefinition>;
94
+ export type Schema = Record<string, object>;
95
+ /**
96
+ * Write function type for converting parsed values back to serializable form
97
+ */
98
+ type WriteFunction<TValue, TCellMetadata> = (value: TValue) => {
99
+ value: SerializedCellValue;
100
+ metadata?: TCellMetadata;
101
+ };
102
+ /**
103
+ * Helper type to create the return type for addCellSchema/addGridSchema
104
+ */
105
+ type AddCellSchemaResult<TCellMetadata, TCurrentSchema extends Schema, TCurrentDeclaration extends SchemaDeclaration, T extends string, TValue> = CreateSchema<TCellMetadata, TCurrentSchema & {
106
+ [K in T]: CellOrmSchema<TValue>;
107
+ }, TCurrentDeclaration & {
108
+ [K in T]: {
109
+ type: "cell";
110
+ cellAddress: CellAddress;
111
+ parse: (value: unknown, metadata: unknown) => unknown;
112
+ };
113
+ }>;
114
+ type AddGridSchemaResult<TCellMetadata, TCurrentSchema extends Schema, TCurrentDeclaration extends SchemaDeclaration, T extends string, TValue> = CreateSchema<TCellMetadata, TCurrentSchema & {
115
+ [K in T]: GridOrmSchema<TValue>;
116
+ }, TCurrentDeclaration & {
117
+ [K in T]: {
118
+ type: "grid";
119
+ workbookName: string;
120
+ sheetName: string;
121
+ range: FiniteSpreadsheetRange;
122
+ parse: (value: unknown, metadata: unknown) => unknown;
123
+ };
124
+ }>;
125
+ export type CreateSchema<TCellMetadata, TCurrentSchema extends Schema, TCurrentDeclaration extends SchemaDeclaration> = {
126
+ addTableSchema<T extends string, THeaders extends Headers<TCellMetadata>>(namespace: T, address: {
127
+ workbookName: string;
128
+ tableName: string;
129
+ }, headers: THeaders): CreateSchema<TCellMetadata, TCurrentSchema & {
130
+ [K in T]: TableOrmSchema<{
131
+ [H in keyof THeaders]: ReturnType<THeaders[H]["parse"]>;
132
+ }>;
133
+ }, TCurrentDeclaration & {
134
+ [K in T]: {
135
+ type: "table";
136
+ tableName: string;
137
+ workbookName: string;
138
+ headers: THeaders;
139
+ };
140
+ }>;
141
+ addCellSchema<T extends string, TValue>(namespace: T, cellAddress: CellAddress, parse: (value: unknown, metadata: TCellMetadata) => TValue, write: WriteFunction<TValue, TCellMetadata>): AddCellSchemaResult<TCellMetadata, TCurrentSchema, TCurrentDeclaration, T, TValue>;
142
+ addCellSchema<T extends string, TValue extends SerializedCellValue>(namespace: T, cellAddress: CellAddress, parse: (value: unknown, metadata: TCellMetadata) => TValue, write?: WriteFunction<TValue, TCellMetadata>): AddCellSchemaResult<TCellMetadata, TCurrentSchema, TCurrentDeclaration, T, TValue>;
143
+ addGridSchema<T extends string, TValue>(namespace: T, address: {
144
+ workbookName: string;
145
+ sheetName: string;
146
+ }, range: FiniteSpreadsheetRange, parse: (value: unknown, metadata: TCellMetadata) => TValue, write: WriteFunction<TValue, TCellMetadata>): AddGridSchemaResult<TCellMetadata, TCurrentSchema, TCurrentDeclaration, T, TValue>;
147
+ addGridSchema<T extends string, TValue extends SerializedCellValue>(namespace: T, address: {
148
+ workbookName: string;
149
+ sheetName: string;
150
+ }, range: FiniteSpreadsheetRange, parse: (value: unknown, metadata: TCellMetadata) => TValue, write?: WriteFunction<TValue, TCellMetadata>): AddGridSchemaResult<TCellMetadata, TCurrentSchema, TCurrentDeclaration, T, TValue>;
151
+ schema: TCurrentSchema;
152
+ declaration: TCurrentDeclaration;
153
+ };
154
+ export declare const createHeader: <TValue, TMetadata>(index: number, parse: (value: SerializedCellValue, metadata: TMetadata) => TValue, write?: (value: TValue) => {
155
+ value: SerializedCellValue;
156
+ metadata?: TMetadata;
157
+ }) => {
158
+ parse: (value: SerializedCellValue, metadata: TMetadata) => TValue;
159
+ write: ((value: TValue) => {
160
+ value: SerializedCellValue;
161
+ metadata?: TMetadata;
162
+ }) | ((value: TValue) => {
163
+ value: TValue;
164
+ });
165
+ index: number;
166
+ };
167
+ export {};
@@ -5,7 +5,7 @@
5
5
  * Used as the `this` context for custom table API methods.
6
6
  */
7
7
  import type { FormulaEngine } from "../engine";
8
- import { type TableSchemaHeaders } from "./api-helpers";
8
+ import { type TableSchemaHeaders } from "./schema-helpers";
9
9
  export declare class TableOrm<TItem extends Record<string, unknown>> {
10
10
  private engine;
11
11
  private workbookName;
@@ -2,11 +2,11 @@ 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 { defineApi, createApi } from "./core/api/api";
6
- export type { CreateApi, Declaration, Api, TableApi, CellApi } from "./core/api/api";
7
- export { TableOrm } from "./core/api/table-orm";
8
- export { CellOrm } from "./core/api/cell-orm";
9
- export { SchemaValidationError } from "./core/managers/api-schema-manager";
10
- export type { ValidationResult } from "./core/managers/api-schema-manager";
5
+ export { defineSchema } from "./core/schema/schema";
6
+ export type { CreateSchema, SchemaDeclaration, Schema, TableSchemaDefinition, CellSchemaDefinition, TableOrmSchema, CellOrmSchema } from "./core/schema/schema";
7
+ export { TableOrm } from "./core/schema/table-orm";
8
+ export { CellOrm } from "./core/schema/cell-orm";
9
+ export { SchemaValidationError } from "./core/managers/schema-manager";
10
+ export type { ValidationResult } from "./core/managers/schema-manager";
11
11
  export { SchemaIntegrityError } from "./core/commands/command-executor";
12
12
  export type { EngineAction, EngineCommand } from "./core/commands/types";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ricsam/formula-engine",
3
- "version": "0.0.21",
3
+ "version": "0.1.0",
4
4
  "module": "./dist/mjs/lib.mjs",
5
5
  "scripts": {
6
6
  "test": "bun test",
@@ -1,10 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../../src/core/api/api-builder.ts"],
4
- "sourcesContent": [
5
- "/**\n * API Builder - Constructs the working API from declarations\n *\n * This module is responsible for creating the actual working API\n * from the schema declarations when attached to a FormulaEngine.\n */\n\nimport type { FormulaEngine } from \"../engine.cjs\";\nimport type { Declaration, TableApi, CellApi, Api } from \"./api.cjs\";\nimport { TableOrm } from \"./table-orm.cjs\";\nimport { CellOrm } from \"./cell-orm.cjs\";\nimport type { ApiSchemaManager } from \"../managers/api-schema-manager.cjs\";\n\n/**\n * Build the working API surface from declarations\n *\n * This creates TableOrm and CellOrm instances for each declared schema\n * and returns them directly.\n */\nexport function buildApiFromDeclaration(\n engine: FormulaEngine<any, any>,\n declaration: Declaration,\n schemaManager: ApiSchemaManager\n): Api {\n const api: Api = {};\n\n for (const [namespace, def] of Object.entries(declaration)) {\n if (def.type === \"table\") {\n api[namespace] = buildTableApi(engine, namespace, def, schemaManager);\n } else if (def.type === \"cell\") {\n api[namespace] = buildCellApi(engine, namespace, def, schemaManager);\n }\n }\n\n return api;\n}\n\n/**\n * Build API for a table schema - returns TableOrm instance directly\n */\nfunction buildTableApi(\n engine: FormulaEngine<any, any>,\n namespace: string,\n def: TableApi,\n schemaManager: ApiSchemaManager\n): TableOrm<any> {\n // Register the schema with the schema manager\n schemaManager.registerTableSchema(\n namespace,\n def.workbookName,\n def.tableName,\n def.headers\n );\n\n // Create and return the ORM instance directly\n return new TableOrm(\n engine,\n def.workbookName,\n def.tableName,\n def.headers,\n namespace\n );\n}\n\n/**\n * Build API for a cell schema - returns CellOrm instance directly\n */\nfunction buildCellApi(\n engine: FormulaEngine<any, any>,\n namespace: string,\n def: CellApi,\n schemaManager: ApiSchemaManager\n): CellOrm<any> {\n // Register the schema with the schema manager\n schemaManager.registerCellSchema(namespace, def.cellAddress, def.parse);\n\n // Create and return the ORM instance directly\n return new CellOrm(engine, def.cellAddress, def.parse, namespace);\n}\n"
6
- ],
7
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AASyB,IAAzB;AACwB,IAAxB;AASO,SAAS,uBAAuB,CACrC,QACA,aACA,eACK;AAAA,EACL,MAAM,MAAW,CAAC;AAAA,EAElB,YAAY,WAAW,QAAQ,OAAO,QAAQ,WAAW,GAAG;AAAA,IAC1D,IAAI,IAAI,SAAS,SAAS;AAAA,MACxB,IAAI,aAAa,cAAc,QAAQ,WAAW,KAAK,aAAa;AAAA,IACtE,EAAO,SAAI,IAAI,SAAS,QAAQ;AAAA,MAC9B,IAAI,aAAa,aAAa,QAAQ,WAAW,KAAK,aAAa;AAAA,IACrE;AAAA,EACF;AAAA,EAEA,OAAO;AAAA;AAMT,SAAS,aAAa,CACpB,QACA,WACA,KACA,eACe;AAAA,EAEf,cAAc,oBACZ,WACA,IAAI,cACJ,IAAI,WACJ,IAAI,OACN;AAAA,EAGA,OAAO,IAAI,0BACT,QACA,IAAI,cACJ,IAAI,WACJ,IAAI,SACJ,SACF;AAAA;AAMF,SAAS,YAAY,CACnB,QACA,WACA,KACA,eACc;AAAA,EAEd,cAAc,mBAAmB,WAAW,IAAI,aAAa,IAAI,KAAK;AAAA,EAGtE,OAAO,IAAI,wBAAQ,QAAQ,IAAI,aAAa,IAAI,OAAO,SAAS;AAAA;",
8
- "debugId": "EDDFC14633608D2364756E2164756E21",
9
- "names": []
10
- }
@@ -1,10 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../../src/core/api/api-helpers.ts"],
4
- "sourcesContent": [
5
- "/**\n * API Helper utilities for row/object conversion and filtering\n */\n\nimport type { CellAddress, SerializedCellValue, TableDefinition } from \"../types.cjs\";\nimport type { FormulaEngine } from \"../engine.cjs\";\n\nexport type ParseFunction<TCellMetadata = unknown> = (\n value: unknown,\n metadata: TCellMetadata\n) => unknown;\n\nexport type TableSchemaHeaders<TCellMetadata = unknown> = Record<\n string,\n {\n parse: ParseFunction<TCellMetadata>;\n index: number;\n }\n>;\n\n/**\n * Convert a spreadsheet row to a typed object using header parsers\n */\nexport function rowToObject<TItem extends Record<string, unknown>>(\n engine: FormulaEngine<any, any>,\n table: TableDefinition,\n rowIndex: number,\n headers: TableSchemaHeaders,\n getCellMetadata?: (cell: CellAddress) => unknown\n): TItem {\n const result: Record<string, unknown> = {};\n\n for (const [columnName, header] of Object.entries(headers)) {\n const cellAddress: CellAddress = {\n workbookName: table.workbookName,\n sheetName: table.sheetName,\n colIndex: table.start.colIndex + header.index,\n rowIndex,\n };\n\n const value = engine.getCellValue(cellAddress);\n const metadata = getCellMetadata ? getCellMetadata(cellAddress) : undefined;\n\n // Parse the value using the column's parse function\n result[columnName] = header.parse(value, metadata);\n }\n\n return result as TItem;\n}\n\n/**\n * Convert a typed object to cell values based on headers\n */\nexport function objectToRowValues<TItem extends Record<string, unknown>>(\n obj: TItem,\n headers: TableSchemaHeaders\n): Map<number, SerializedCellValue> {\n const values = new Map<number, SerializedCellValue>();\n\n for (const [columnName, header] of Object.entries(headers)) {\n if (columnName in obj) {\n const value = obj[columnName];\n // Convert to serializable value\n if (\n typeof value === \"string\" ||\n typeof value === \"number\" ||\n typeof value === \"boolean\"\n ) {\n values.set(header.index, value);\n } else if (value === null || value === undefined) {\n values.set(header.index, undefined);\n } else {\n // For complex types, convert to string\n values.set(header.index, String(value));\n }\n }\n }\n\n return values;\n}\n\n/**\n * Check if an object matches a filter predicate\n */\nexport function matchesFilter<TItem extends Record<string, unknown>>(\n item: TItem,\n filter: Partial<TItem>\n): boolean {\n for (const [key, value] of Object.entries(filter)) {\n if (item[key] !== value) {\n return false;\n }\n }\n return true;\n}\n\n/**\n * Get the number of data rows in a table (excluding header)\n */\nexport function getTableRowCount(\n engine: FormulaEngine<any, any>,\n table: TableDefinition\n): number {\n if (table.endRow.type === \"infinity\") {\n // For infinite tables, count non-empty rows\n // Start from data row (after header)\n let count = 0;\n let emptyRowStreak = 0;\n const maxEmptyRows = 10; // Stop after 10 consecutive empty rows\n\n for (let row = table.start.rowIndex + 1; emptyRowStreak < maxEmptyRows; row++) {\n let hasContent = false;\n\n for (let col = 0; col < table.headers.size; col++) {\n const cellAddress: CellAddress = {\n workbookName: table.workbookName,\n sheetName: table.sheetName,\n colIndex: table.start.colIndex + col,\n rowIndex: row,\n };\n\n const value = engine.getCellValue(cellAddress);\n if (value !== \"\" && value !== undefined) {\n hasContent = true;\n break;\n }\n }\n\n if (hasContent) {\n count++;\n emptyRowStreak = 0;\n } else {\n emptyRowStreak++;\n }\n }\n\n return count;\n } else {\n // For finite tables, calculate from endRow\n return table.endRow.value - table.start.rowIndex;\n }\n}\n\n/**\n * Get the next empty row index for appending data\n */\nexport function getNextEmptyRow(\n engine: FormulaEngine<any, any>,\n table: TableDefinition\n): number {\n const dataStartRow = table.start.rowIndex + 1;\n\n if (table.endRow.type === \"infinity\") {\n // Find first empty row\n let emptyRowStreak = 0;\n const maxEmptyRows = 10;\n\n for (let row = dataStartRow; ; row++) {\n let hasContent = false;\n\n for (let col = 0; col < table.headers.size; col++) {\n const cellAddress: CellAddress = {\n workbookName: table.workbookName,\n sheetName: table.sheetName,\n colIndex: table.start.colIndex + col,\n rowIndex: row,\n };\n\n const value = engine.getCellValue(cellAddress);\n if (value !== \"\" && value !== undefined) {\n hasContent = true;\n break;\n }\n }\n\n if (!hasContent) {\n return row;\n }\n\n emptyRowStreak = hasContent ? 0 : emptyRowStreak + 1;\n if (emptyRowStreak >= maxEmptyRows) {\n return row - maxEmptyRows + 1;\n }\n }\n } else {\n // For finite tables, return the row after the last data row\n return table.endRow.value + 1;\n }\n}\n\n/**\n * Iterate over all data rows in a table\n */\nexport function* iterateTableRows(\n engine: FormulaEngine<any, any>,\n table: TableDefinition\n): Generator<{ rowIndex: number; isEmpty: boolean }> {\n const dataStartRow = table.start.rowIndex + 1;\n\n if (table.endRow.type === \"infinity\") {\n let emptyRowStreak = 0;\n const maxEmptyRows = 10;\n\n for (let row = dataStartRow; emptyRowStreak < maxEmptyRows; row++) {\n let hasContent = false;\n\n for (let col = 0; col < table.headers.size; col++) {\n const cellAddress: CellAddress = {\n workbookName: table.workbookName,\n sheetName: table.sheetName,\n colIndex: table.start.colIndex + col,\n rowIndex: row,\n };\n\n const value = engine.getCellValue(cellAddress);\n if (value !== \"\" && value !== undefined) {\n hasContent = true;\n break;\n }\n }\n\n if (hasContent) {\n emptyRowStreak = 0;\n yield { rowIndex: row, isEmpty: false };\n } else {\n emptyRowStreak++;\n // Don't yield empty rows at the end\n }\n }\n } else {\n for (let row = dataStartRow; row <= table.endRow.value; row++) {\n let hasContent = false;\n\n for (let col = 0; col < table.headers.size; col++) {\n const cellAddress: CellAddress = {\n workbookName: table.workbookName,\n sheetName: table.sheetName,\n colIndex: table.start.colIndex + col,\n rowIndex: row,\n };\n\n const value = engine.getCellValue(cellAddress);\n if (value !== \"\" && value !== undefined) {\n hasContent = true;\n break;\n }\n }\n\n yield { rowIndex: row, isEmpty: !hasContent };\n }\n }\n}\n\n"
6
- ],
7
- "mappings": "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",
8
- "debugId": "3AEF0EFABA7782E064756E2164756E21",
9
- "names": []
10
- }
@@ -1,10 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../../src/core/api/api.ts"],
4
- "sourcesContent": [
5
- "import type { CellAddress } from \"../types.cjs\";\n\n/**\n * Define an API schema for the FormulaEngine.\n *\n * The returned object contains:\n * - `declaration`: The schema definitions for tables and cells\n * - `api`: A type-only placeholder (undefined at runtime) for TypeScript inference\n *\n * The actual working API is only available through `engine.api` after\n * attaching the definition to a FormulaEngine instance.\n *\n * @example\n * ```typescript\n * const myApi = defineApi<CellMetadata>()\n * .addTableApi(\"users\", { workbookName: \"wb1\", tableName: \"users\" }, headers)\n * .addCellApi(\"config\", cellAddress, parse);\n *\n * const engine = new FormulaEngine(myApi);\n * engine.api.users.findWhere({ id: 1 }); // Works!\n * engine.api.config.read(); // Works!\n * myApi.api.users.findWhere({ id: 1 }); // Error: api is undefined at runtime\n * ```\n */\nexport function defineApi<\n TCellMetadata = unknown,\n TCurrentApi extends Record<string, object> = Record<string, object>,\n TCurrentDeclaration extends Record<string, TableApi | CellApi> = Record<\n string,\n TableApi | CellApi\n >\n>(): CreateApi<TCellMetadata, TCurrentApi, TCurrentDeclaration> {\n const declaration: Record<string, TableApi | CellApi> = {};\n\n const builder: CreateApi<TCellMetadata, TCurrentApi, TCurrentDeclaration> = {\n addTableApi(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 addCellApi(namespace, cellAddress, parse) {\n declaration[namespace] = {\n type: \"cell\",\n cellAddress,\n parse: parse as any,\n };\n return builder as any;\n },\n\n // api is undefined at runtime - it only exists for TypeScript type inference\n // The actual working API is built by the FormulaEngine constructor\n api: undefined as any as TCurrentApi,\n\n declaration: declaration as TCurrentDeclaration,\n };\n\n return builder;\n}\n\n// Keep createApi as an alias for backwards compatibility\nexport const createApi = defineApi;\n\ntype ParseFunction<TCellMetadata> = (\n value: unknown,\n metadata: TCellMetadata\n) => unknown;\n\nexport interface TableApi {\n type: \"table\";\n headers: Headers<unknown>;\n tableName: string;\n workbookName: string;\n}\n\nexport interface CellApi {\n type: \"cell\";\n cellAddress: CellAddress;\n parse: (value: unknown, metadata: unknown) => unknown;\n}\n\ntype Headers<TCellMetadata> = Record<\n string,\n {\n parse: ParseFunction<TCellMetadata>;\n index: number;\n }\n>;\n\n/**\n * Type representing the TableOrm methods exposed on the API\n */\nexport type TableOrmApi<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 API\n */\nexport type CellOrmApi<TValue> = {\n read(): TValue;\n write(value: TValue): void;\n getAddress(): CellAddress;\n};\n\nexport type Declaration = Record<string, TableApi | CellApi>;\nexport type Api = Record<string, object>;\n\nexport type CreateApi<\n TCellMetadata,\n TCurrentApi extends Api,\n TCurrentDeclaration extends Declaration\n> = {\n addTableApi<T extends string, THeaders extends Headers<TCellMetadata>>(\n namespace: T,\n address: { workbookName: string; tableName: string },\n headers: THeaders\n ): CreateApi<\n TCellMetadata,\n TCurrentApi & {\n [K in T]: TableOrmApi<{\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 addCellApi<T extends string, TValue>(\n namespace: T,\n cellAddress: CellAddress,\n parse: (value: unknown, metadata: TCellMetadata) => TValue\n ): CreateApi<\n TCellMetadata,\n TCurrentApi & {\n [K in T]: CellOrmApi<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 api: TCurrentApi;\n declaration: TCurrentDeclaration;\n};\n"
6
- ],
7
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwBO,SAAS,SAOf,GAA+D;AAAA,EAC9D,MAAM,cAAkD,CAAC;AAAA,EAEzD,MAAM,UAAsE;AAAA,IAC1E,WAAW,CAAC,WAAW,SAAS,SAAS;AAAA,MACvC,YAAY,aAAa;AAAA,QACvB,MAAM;AAAA,QACN,WAAW,QAAQ;AAAA,QACnB,cAAc,QAAQ;AAAA,QACtB;AAAA,MACF;AAAA,MACA,OAAO;AAAA;AAAA,IAGT,UAAU,CAAC,WAAW,aAAa,OAAO;AAAA,MACxC,YAAY,aAAa;AAAA,QACvB,MAAM;AAAA,QACN;AAAA,QACA;AAAA,MACF;AAAA,MACA,OAAO;AAAA;AAAA,IAKT,KAAK;AAAA,IAEL;AAAA,EACF;AAAA,EAEA,OAAO;AAAA;AAIF,IAAM,YAAY;",
8
- "debugId": "071184DEA6DB276964756E2164756E21",
9
- "names": []
10
- }
@@ -1,10 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../../src/core/api/cell-orm.ts"],
4
- "sourcesContent": [
5
- "/**\n * CellOrm - Object-Relational Mapping for single cell data\n *\n * Provides read/write operations for a single cell with type-safe access.\n * Used as the `this` context for custom cell API methods.\n */\n\nimport type { CellAddress, SerializedCellValue } from \"../types.cjs\";\nimport type { FormulaEngine } from \"../engine.cjs\";\n\nexport type CellParseFunction<TCellMetadata, TValue> = (\n value: unknown,\n metadata: TCellMetadata\n) => TValue;\n\nexport class CellOrm<TValue, TCellMetadata = unknown> {\n constructor(\n private engine: FormulaEngine<any, any>,\n private cellAddress: CellAddress,\n private parser: CellParseFunction<TCellMetadata, TValue>,\n private namespace: string\n ) {}\n\n /**\n * Read the cell value and parse it using the schema's parse function\n */\n read(): TValue {\n const value = this.engine.getCellValue(this.cellAddress);\n const metadata = this.engine.getCellMetadata(this.cellAddress) as TCellMetadata;\n return this.parser(value, metadata);\n }\n\n /**\n * Write a value to the cell\n * The value should be the parsed type - it will be converted to a serializable value\n */\n write(value: TValue): void {\n // Convert TValue to SerializedCellValue\n let serializedValue: SerializedCellValue;\n\n if (\n typeof value === \"string\" ||\n typeof value === \"number\" ||\n typeof value === \"boolean\"\n ) {\n serializedValue = value;\n } else if (value === null || value === undefined) {\n serializedValue = undefined;\n } else if (typeof value === \"object\") {\n // For objects, we need to extract the actual cell value\n // This assumes the parsed type might be an object with a 'value' property\n const obj = value as Record<string, unknown>;\n if (\"value\" in obj) {\n const innerValue = obj.value;\n if (\n typeof innerValue === \"string\" ||\n typeof innerValue === \"number\" ||\n typeof innerValue === \"boolean\"\n ) {\n serializedValue = innerValue;\n } else {\n serializedValue = String(innerValue);\n }\n } else {\n // Fallback: convert to string\n serializedValue = JSON.stringify(value);\n }\n } else {\n serializedValue = String(value);\n }\n\n this.engine.setCellContent(this.cellAddress, serializedValue);\n }\n\n /**\n * Get the cell address\n */\n getAddress(): CellAddress {\n return { ...this.cellAddress };\n }\n}\n"
6
- ],
7
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAeO,MAAM,QAAyC;AAAA,EAE1C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAJV,WAAW,CACD,QACA,aACA,QACA,WACR;AAAA,IAJQ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA;AAAA,EAMV,IAAI,GAAW;AAAA,IACb,MAAM,QAAQ,KAAK,OAAO,aAAa,KAAK,WAAW;AAAA,IACvD,MAAM,WAAW,KAAK,OAAO,gBAAgB,KAAK,WAAW;AAAA,IAC7D,OAAO,KAAK,OAAO,OAAO,QAAQ;AAAA;AAAA,EAOpC,KAAK,CAAC,OAAqB;AAAA,IAEzB,IAAI;AAAA,IAEJ,IACE,OAAO,UAAU,YACjB,OAAO,UAAU,YACjB,OAAO,UAAU,WACjB;AAAA,MACA,kBAAkB;AAAA,IACpB,EAAO,SAAI,UAAU,QAAQ,UAAU,WAAW;AAAA,MAChD,kBAAkB;AAAA,IACpB,EAAO,SAAI,OAAO,UAAU,UAAU;AAAA,MAGpC,MAAM,MAAM;AAAA,MACZ,IAAI,WAAW,KAAK;AAAA,QAClB,MAAM,aAAa,IAAI;AAAA,QACvB,IACE,OAAO,eAAe,YACtB,OAAO,eAAe,YACtB,OAAO,eAAe,WACtB;AAAA,UACA,kBAAkB;AAAA,QACpB,EAAO;AAAA,UACL,kBAAkB,OAAO,UAAU;AAAA;AAAA,MAEvC,EAAO;AAAA,QAEL,kBAAkB,KAAK,UAAU,KAAK;AAAA;AAAA,IAE1C,EAAO;AAAA,MACL,kBAAkB,OAAO,KAAK;AAAA;AAAA,IAGhC,KAAK,OAAO,eAAe,KAAK,aAAa,eAAe;AAAA;AAAA,EAM9D,UAAU,GAAgB;AAAA,IACxB,OAAO,KAAK,KAAK,YAAY;AAAA;AAEjC;",
8
- "debugId": "65719C8FCB16AB7864756E2164756E21",
9
- "names": []
10
- }
@@ -1,10 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../../src/core/api/table-orm.ts"],
4
- "sourcesContent": [
5
- "/**\n * TableOrm - Object-Relational Mapping for table data\n *\n * Provides CRUD operations for table data with type-safe access.\n * Used as the `this` context for custom table API methods.\n */\n\nimport type { CellAddress, SerializedCellValue, TableDefinition } from \"../types.cjs\";\nimport type { FormulaEngine } from \"../engine.cjs\";\nimport {\n rowToObject,\n objectToRowValues,\n matchesFilter,\n getTableRowCount,\n getNextEmptyRow,\n iterateTableRows,\n type TableSchemaHeaders,\n} from \"./api-helpers.cjs\";\n\nexport class TableOrm<TItem extends Record<string, unknown>> {\n constructor(\n private engine: FormulaEngine<any, any>,\n private workbookName: string,\n private tableName: string,\n private headers: TableSchemaHeaders,\n private namespace: string\n ) {}\n\n /**\n * Get the table definition from the engine\n */\n private getTable(): TableDefinition {\n const table = this.engine._tableManager.getTable({\n workbookName: this.workbookName,\n name: this.tableName,\n });\n\n if (!table) {\n throw new Error(\n `Table \"${this.tableName}\" not found in workbook \"${this.workbookName}\"`\n );\n }\n\n return table;\n }\n\n /**\n * Find the first row matching the filter\n */\n findWhere(filter: Partial<TItem>): TItem | undefined {\n const table = this.getTable();\n\n for (const { rowIndex, isEmpty } of iterateTableRows(this.engine, table)) {\n if (isEmpty) continue;\n\n try {\n const item = rowToObject<TItem>(\n this.engine,\n table,\n rowIndex,\n this.headers,\n (cell) => this.engine.getCellMetadata(cell)\n );\n\n if (matchesFilter(item, filter)) {\n return item;\n }\n } catch {\n // Skip rows that fail parsing\n continue;\n }\n }\n\n return undefined;\n }\n\n /**\n * Find all rows matching the filter\n */\n findAllWhere(filter: Partial<TItem>): TItem[] {\n const table = this.getTable();\n const results: TItem[] = [];\n\n for (const { rowIndex, isEmpty } of iterateTableRows(this.engine, table)) {\n if (isEmpty) continue;\n\n try {\n const item = rowToObject<TItem>(\n this.engine,\n table,\n rowIndex,\n this.headers,\n (cell) => this.engine.getCellMetadata(cell)\n );\n\n if (matchesFilter(item, filter)) {\n results.push(item);\n }\n } catch {\n // Skip rows that fail parsing\n continue;\n }\n }\n\n return results;\n }\n\n /**\n * Append a new row to the table\n */\n append(item: TItem): TItem {\n const table = this.getTable();\n const nextRow = getNextEmptyRow(this.engine, table);\n const values = objectToRowValues(item, this.headers);\n\n // Write each cell value\n for (const [colOffset, value] of values) {\n const cellAddress: CellAddress = {\n workbookName: table.workbookName,\n sheetName: table.sheetName,\n colIndex: table.start.colIndex + colOffset,\n rowIndex: nextRow,\n };\n\n this.engine.setCellContent(cellAddress, value);\n }\n\n return item;\n }\n\n /**\n * Update all rows matching the filter\n * Returns the number of rows updated\n */\n updateWhere(filter: Partial<TItem>, update: Partial<TItem>): number {\n const table = this.getTable();\n let updatedCount = 0;\n\n for (const { rowIndex, isEmpty } of iterateTableRows(this.engine, table)) {\n if (isEmpty) continue;\n\n try {\n const item = rowToObject<TItem>(\n this.engine,\n table,\n rowIndex,\n this.headers,\n (cell) => this.engine.getCellMetadata(cell)\n );\n\n if (matchesFilter(item, filter)) {\n // Apply updates\n const values = objectToRowValues(update as TItem, this.headers);\n\n for (const [colOffset, value] of values) {\n const cellAddress: CellAddress = {\n workbookName: table.workbookName,\n sheetName: table.sheetName,\n colIndex: table.start.colIndex + colOffset,\n rowIndex,\n };\n\n this.engine.setCellContent(cellAddress, value);\n }\n\n updatedCount++;\n }\n } catch {\n // Skip rows that fail parsing\n continue;\n }\n }\n\n return updatedCount;\n }\n\n /**\n * Remove all rows matching the filter\n * Returns the number of rows removed\n */\n removeWhere(filter: Partial<TItem>): number {\n const table = this.getTable();\n let removedCount = 0;\n\n // Collect rows to remove (in reverse order to avoid index shifting issues)\n const rowsToRemove: number[] = [];\n\n for (const { rowIndex, isEmpty } of iterateTableRows(this.engine, table)) {\n if (isEmpty) continue;\n\n try {\n const item = rowToObject<TItem>(\n this.engine,\n table,\n rowIndex,\n this.headers,\n (cell) => this.engine.getCellMetadata(cell)\n );\n\n if (matchesFilter(item, filter)) {\n rowsToRemove.push(rowIndex);\n }\n } catch {\n // Skip rows that fail parsing\n continue;\n }\n }\n\n // Remove rows in reverse order\n for (const rowIndex of rowsToRemove.reverse()) {\n // Clear all cells in the row\n for (const header of Object.values(this.headers)) {\n const cellAddress: CellAddress = {\n workbookName: table.workbookName,\n sheetName: table.sheetName,\n colIndex: table.start.colIndex + header.index,\n rowIndex,\n };\n\n this.engine.setCellContent(cellAddress, undefined);\n }\n\n removedCount++;\n }\n\n return removedCount;\n }\n\n /**\n * Get the count of data rows in the table\n */\n count(): number {\n const table = this.getTable();\n return getTableRowCount(this.engine, table);\n }\n}\n"
6
- ],
7
- "mappings": "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",
8
- "debugId": "EAD2C30DE3B432C664756E2164756E21",
9
- "names": []
10
- }
@@ -1,10 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../../src/core/managers/api-schema-manager.ts"],
4
- "sourcesContent": [
5
- "/**\n * ApiSchemaManager - Manages API 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 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: unknown,\n metadata: TCellMetadata\n) => unknown;\n\nexport type TableSchemaHeaders<TCellMetadata = unknown> = Record<\n string,\n {\n parse: ParseFunction<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 type RegisteredSchema = RegisteredTableSchema | RegisteredCellSchema;\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 ApiSchemaManager {\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 * 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 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 }\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 }\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 }\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 }\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 }\n }\n\n return {\n valid: errors.length === 0,\n errors,\n };\n }\n}\n"
6
- ],
7
- "mappings": "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",
8
- "debugId": "0A401D0913B21D2A64756E2164756E21",
9
- "names": []
10
- }
@@ -1,27 +0,0 @@
1
- // src/core/api/api-builder.ts
2
- import { TableOrm } from "./table-orm.mjs";
3
- import { CellOrm } from "./cell-orm.mjs";
4
- function buildApiFromDeclaration(engine, declaration, schemaManager) {
5
- const api = {};
6
- for (const [namespace, def] of Object.entries(declaration)) {
7
- if (def.type === "table") {
8
- api[namespace] = buildTableApi(engine, namespace, def, schemaManager);
9
- } else if (def.type === "cell") {
10
- api[namespace] = buildCellApi(engine, namespace, def, schemaManager);
11
- }
12
- }
13
- return api;
14
- }
15
- function buildTableApi(engine, namespace, def, schemaManager) {
16
- schemaManager.registerTableSchema(namespace, def.workbookName, def.tableName, def.headers);
17
- return new TableOrm(engine, def.workbookName, def.tableName, def.headers, namespace);
18
- }
19
- function buildCellApi(engine, namespace, def, schemaManager) {
20
- schemaManager.registerCellSchema(namespace, def.cellAddress, def.parse);
21
- return new CellOrm(engine, def.cellAddress, def.parse, namespace);
22
- }
23
- export {
24
- buildApiFromDeclaration
25
- };
26
-
27
- //# debugId=3B353A0CD99B342764756E2164756E21
@@ -1,10 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../../src/core/api/api-builder.ts"],
4
- "sourcesContent": [
5
- "/**\n * API Builder - Constructs the working API from declarations\n *\n * This module is responsible for creating the actual working API\n * from the schema declarations when attached to a FormulaEngine.\n */\n\nimport type { FormulaEngine } from \"../engine.mjs\";\nimport type { Declaration, TableApi, CellApi, Api } from \"./api.mjs\";\nimport { TableOrm } from \"./table-orm.mjs\";\nimport { CellOrm } from \"./cell-orm.mjs\";\nimport type { ApiSchemaManager } from \"../managers/api-schema-manager.mjs\";\n\n/**\n * Build the working API surface from declarations\n *\n * This creates TableOrm and CellOrm instances for each declared schema\n * and returns them directly.\n */\nexport function buildApiFromDeclaration(\n engine: FormulaEngine<any, any>,\n declaration: Declaration,\n schemaManager: ApiSchemaManager\n): Api {\n const api: Api = {};\n\n for (const [namespace, def] of Object.entries(declaration)) {\n if (def.type === \"table\") {\n api[namespace] = buildTableApi(engine, namespace, def, schemaManager);\n } else if (def.type === \"cell\") {\n api[namespace] = buildCellApi(engine, namespace, def, schemaManager);\n }\n }\n\n return api;\n}\n\n/**\n * Build API for a table schema - returns TableOrm instance directly\n */\nfunction buildTableApi(\n engine: FormulaEngine<any, any>,\n namespace: string,\n def: TableApi,\n schemaManager: ApiSchemaManager\n): TableOrm<any> {\n // Register the schema with the schema manager\n schemaManager.registerTableSchema(\n namespace,\n def.workbookName,\n def.tableName,\n def.headers\n );\n\n // Create and return the ORM instance directly\n return new TableOrm(\n engine,\n def.workbookName,\n def.tableName,\n def.headers,\n namespace\n );\n}\n\n/**\n * Build API for a cell schema - returns CellOrm instance directly\n */\nfunction buildCellApi(\n engine: FormulaEngine<any, any>,\n namespace: string,\n def: CellApi,\n schemaManager: ApiSchemaManager\n): CellOrm<any> {\n // Register the schema with the schema manager\n schemaManager.registerCellSchema(namespace, def.cellAddress, def.parse);\n\n // Create and return the ORM instance directly\n return new CellOrm(engine, def.cellAddress, def.parse, namespace);\n}\n"
6
- ],
7
- "mappings": ";AASA;AACA;AASO,SAAS,uBAAuB,CACrC,QACA,aACA,eACK;AAAA,EACL,MAAM,MAAW,CAAC;AAAA,EAElB,YAAY,WAAW,QAAQ,OAAO,QAAQ,WAAW,GAAG;AAAA,IAC1D,IAAI,IAAI,SAAS,SAAS;AAAA,MACxB,IAAI,aAAa,cAAc,QAAQ,WAAW,KAAK,aAAa;AAAA,IACtE,EAAO,SAAI,IAAI,SAAS,QAAQ;AAAA,MAC9B,IAAI,aAAa,aAAa,QAAQ,WAAW,KAAK,aAAa;AAAA,IACrE;AAAA,EACF;AAAA,EAEA,OAAO;AAAA;AAMT,SAAS,aAAa,CACpB,QACA,WACA,KACA,eACe;AAAA,EAEf,cAAc,oBACZ,WACA,IAAI,cACJ,IAAI,WACJ,IAAI,OACN;AAAA,EAGA,OAAO,IAAI,SACT,QACA,IAAI,cACJ,IAAI,WACJ,IAAI,SACJ,SACF;AAAA;AAMF,SAAS,YAAY,CACnB,QACA,WACA,KACA,eACc;AAAA,EAEd,cAAc,mBAAmB,WAAW,IAAI,aAAa,IAAI,KAAK;AAAA,EAGtE,OAAO,IAAI,QAAQ,QAAQ,IAAI,aAAa,IAAI,OAAO,SAAS;AAAA;",
8
- "debugId": "3B353A0CD99B342764756E2164756E21",
9
- "names": []
10
- }
@@ -1,10 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../../src/core/api/api-helpers.ts"],
4
- "sourcesContent": [
5
- "/**\n * API Helper utilities for row/object conversion and filtering\n */\n\nimport type { CellAddress, SerializedCellValue, TableDefinition } from \"../types.mjs\";\nimport type { FormulaEngine } from \"../engine.mjs\";\n\nexport type ParseFunction<TCellMetadata = unknown> = (\n value: unknown,\n metadata: TCellMetadata\n) => unknown;\n\nexport type TableSchemaHeaders<TCellMetadata = unknown> = Record<\n string,\n {\n parse: ParseFunction<TCellMetadata>;\n index: number;\n }\n>;\n\n/**\n * Convert a spreadsheet row to a typed object using header parsers\n */\nexport function rowToObject<TItem extends Record<string, unknown>>(\n engine: FormulaEngine<any, any>,\n table: TableDefinition,\n rowIndex: number,\n headers: TableSchemaHeaders,\n getCellMetadata?: (cell: CellAddress) => unknown\n): TItem {\n const result: Record<string, unknown> = {};\n\n for (const [columnName, header] of Object.entries(headers)) {\n const cellAddress: CellAddress = {\n workbookName: table.workbookName,\n sheetName: table.sheetName,\n colIndex: table.start.colIndex + header.index,\n rowIndex,\n };\n\n const value = engine.getCellValue(cellAddress);\n const metadata = getCellMetadata ? getCellMetadata(cellAddress) : undefined;\n\n // Parse the value using the column's parse function\n result[columnName] = header.parse(value, metadata);\n }\n\n return result as TItem;\n}\n\n/**\n * Convert a typed object to cell values based on headers\n */\nexport function objectToRowValues<TItem extends Record<string, unknown>>(\n obj: TItem,\n headers: TableSchemaHeaders\n): Map<number, SerializedCellValue> {\n const values = new Map<number, SerializedCellValue>();\n\n for (const [columnName, header] of Object.entries(headers)) {\n if (columnName in obj) {\n const value = obj[columnName];\n // Convert to serializable value\n if (\n typeof value === \"string\" ||\n typeof value === \"number\" ||\n typeof value === \"boolean\"\n ) {\n values.set(header.index, value);\n } else if (value === null || value === undefined) {\n values.set(header.index, undefined);\n } else {\n // For complex types, convert to string\n values.set(header.index, String(value));\n }\n }\n }\n\n return values;\n}\n\n/**\n * Check if an object matches a filter predicate\n */\nexport function matchesFilter<TItem extends Record<string, unknown>>(\n item: TItem,\n filter: Partial<TItem>\n): boolean {\n for (const [key, value] of Object.entries(filter)) {\n if (item[key] !== value) {\n return false;\n }\n }\n return true;\n}\n\n/**\n * Get the number of data rows in a table (excluding header)\n */\nexport function getTableRowCount(\n engine: FormulaEngine<any, any>,\n table: TableDefinition\n): number {\n if (table.endRow.type === \"infinity\") {\n // For infinite tables, count non-empty rows\n // Start from data row (after header)\n let count = 0;\n let emptyRowStreak = 0;\n const maxEmptyRows = 10; // Stop after 10 consecutive empty rows\n\n for (let row = table.start.rowIndex + 1; emptyRowStreak < maxEmptyRows; row++) {\n let hasContent = false;\n\n for (let col = 0; col < table.headers.size; col++) {\n const cellAddress: CellAddress = {\n workbookName: table.workbookName,\n sheetName: table.sheetName,\n colIndex: table.start.colIndex + col,\n rowIndex: row,\n };\n\n const value = engine.getCellValue(cellAddress);\n if (value !== \"\" && value !== undefined) {\n hasContent = true;\n break;\n }\n }\n\n if (hasContent) {\n count++;\n emptyRowStreak = 0;\n } else {\n emptyRowStreak++;\n }\n }\n\n return count;\n } else {\n // For finite tables, calculate from endRow\n return table.endRow.value - table.start.rowIndex;\n }\n}\n\n/**\n * Get the next empty row index for appending data\n */\nexport function getNextEmptyRow(\n engine: FormulaEngine<any, any>,\n table: TableDefinition\n): number {\n const dataStartRow = table.start.rowIndex + 1;\n\n if (table.endRow.type === \"infinity\") {\n // Find first empty row\n let emptyRowStreak = 0;\n const maxEmptyRows = 10;\n\n for (let row = dataStartRow; ; row++) {\n let hasContent = false;\n\n for (let col = 0; col < table.headers.size; col++) {\n const cellAddress: CellAddress = {\n workbookName: table.workbookName,\n sheetName: table.sheetName,\n colIndex: table.start.colIndex + col,\n rowIndex: row,\n };\n\n const value = engine.getCellValue(cellAddress);\n if (value !== \"\" && value !== undefined) {\n hasContent = true;\n break;\n }\n }\n\n if (!hasContent) {\n return row;\n }\n\n emptyRowStreak = hasContent ? 0 : emptyRowStreak + 1;\n if (emptyRowStreak >= maxEmptyRows) {\n return row - maxEmptyRows + 1;\n }\n }\n } else {\n // For finite tables, return the row after the last data row\n return table.endRow.value + 1;\n }\n}\n\n/**\n * Iterate over all data rows in a table\n */\nexport function* iterateTableRows(\n engine: FormulaEngine<any, any>,\n table: TableDefinition\n): Generator<{ rowIndex: number; isEmpty: boolean }> {\n const dataStartRow = table.start.rowIndex + 1;\n\n if (table.endRow.type === \"infinity\") {\n let emptyRowStreak = 0;\n const maxEmptyRows = 10;\n\n for (let row = dataStartRow; emptyRowStreak < maxEmptyRows; row++) {\n let hasContent = false;\n\n for (let col = 0; col < table.headers.size; col++) {\n const cellAddress: CellAddress = {\n workbookName: table.workbookName,\n sheetName: table.sheetName,\n colIndex: table.start.colIndex + col,\n rowIndex: row,\n };\n\n const value = engine.getCellValue(cellAddress);\n if (value !== \"\" && value !== undefined) {\n hasContent = true;\n break;\n }\n }\n\n if (hasContent) {\n emptyRowStreak = 0;\n yield { rowIndex: row, isEmpty: false };\n } else {\n emptyRowStreak++;\n // Don't yield empty rows at the end\n }\n }\n } else {\n for (let row = dataStartRow; row <= table.endRow.value; row++) {\n let hasContent = false;\n\n for (let col = 0; col < table.headers.size; col++) {\n const cellAddress: CellAddress = {\n workbookName: table.workbookName,\n sheetName: table.sheetName,\n colIndex: table.start.colIndex + col,\n rowIndex: row,\n };\n\n const value = engine.getCellValue(cellAddress);\n if (value !== \"\" && value !== undefined) {\n hasContent = true;\n break;\n }\n }\n\n yield { rowIndex: row, isEmpty: !hasContent };\n }\n }\n}\n\n"
6
- ],
7
- "mappings": "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",
8
- "debugId": "0AEE3F3D29B7684464756E2164756E21",
9
- "names": []
10
- }
@@ -1,33 +0,0 @@
1
- // src/core/api/api.ts
2
- function defineApi() {
3
- const declaration = {};
4
- const builder = {
5
- addTableApi(namespace, address, headers) {
6
- declaration[namespace] = {
7
- type: "table",
8
- tableName: address.tableName,
9
- workbookName: address.workbookName,
10
- headers
11
- };
12
- return builder;
13
- },
14
- addCellApi(namespace, cellAddress, parse) {
15
- declaration[namespace] = {
16
- type: "cell",
17
- cellAddress,
18
- parse
19
- };
20
- return builder;
21
- },
22
- api: undefined,
23
- declaration
24
- };
25
- return builder;
26
- }
27
- var createApi = defineApi;
28
- export {
29
- defineApi,
30
- createApi
31
- };
32
-
33
- //# debugId=6D6EFC9F69FE55CC64756E2164756E21