@ricsam/formula-engine 0.2.8 → 0.2.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -3
- package/dist/cjs/core/engine.cjs +515 -166
- package/dist/cjs/core/engine.cjs.map +3 -3
- package/dist/cjs/core/managers/dependency-manager.cjs.map +2 -2
- package/dist/cjs/core/managers/evaluation-manager.cjs.map +1 -1
- package/dist/cjs/core/mutation-invalidation.cjs +241 -0
- package/dist/cjs/core/mutation-invalidation.cjs.map +10 -0
- package/dist/cjs/lib.cjs +2 -13
- package/dist/cjs/lib.cjs.map +3 -3
- package/dist/cjs/package.json +1 -1
- package/dist/mjs/core/engine.mjs +529 -207
- package/dist/mjs/core/engine.mjs.map +3 -3
- package/dist/mjs/core/managers/dependency-manager.mjs.map +2 -2
- package/dist/mjs/core/managers/evaluation-manager.mjs.map +1 -1
- package/dist/mjs/core/mutation-invalidation.mjs +201 -0
- package/dist/mjs/core/mutation-invalidation.mjs.map +10 -0
- package/dist/mjs/lib.mjs +2 -13
- package/dist/mjs/lib.mjs.map +3 -3
- package/dist/mjs/package.json +1 -1
- package/dist/types/core/engine.d.ts +17 -135
- package/dist/types/core/managers/dependency-manager.d.ts +1 -1
- package/dist/types/core/managers/evaluation-manager.d.ts +1 -1
- package/dist/types/core/mutation-invalidation.d.ts +46 -0
- package/dist/types/lib.d.ts +0 -8
- package/package.json +1 -1
- package/dist/cjs/core/commands/command-executor.cjs +0 -149
- package/dist/cjs/core/commands/command-executor.cjs.map +0 -10
- package/dist/cjs/core/commands/content-commands.cjs +0 -857
- package/dist/cjs/core/commands/content-commands.cjs.map +0 -10
- package/dist/cjs/core/commands/metadata-commands.cjs +0 -160
- package/dist/cjs/core/commands/metadata-commands.cjs.map +0 -10
- package/dist/cjs/core/commands/named-expression-commands.cjs +0 -363
- package/dist/cjs/core/commands/named-expression-commands.cjs.map +0 -10
- package/dist/cjs/core/commands/structure-commands.cjs +0 -696
- package/dist/cjs/core/commands/structure-commands.cjs.map +0 -10
- package/dist/cjs/core/commands/style-commands.cjs +0 -229
- package/dist/cjs/core/commands/style-commands.cjs.map +0 -10
- package/dist/cjs/core/commands/table-commands.cjs +0 -495
- package/dist/cjs/core/commands/table-commands.cjs.map +0 -10
- package/dist/cjs/core/commands/types.cjs +0 -99
- package/dist/cjs/core/commands/types.cjs.map +0 -10
- package/dist/cjs/core/managers/schema-manager.cjs +0 -374
- package/dist/cjs/core/managers/schema-manager.cjs.map +0 -10
- package/dist/cjs/core/schema/cell-orm.cjs +0 -76
- package/dist/cjs/core/schema/cell-orm.cjs.map +0 -10
- package/dist/cjs/core/schema/grid-orm.cjs +0 -125
- package/dist/cjs/core/schema/grid-orm.cjs.map +0 -10
- package/dist/cjs/core/schema/schema-builder.cjs +0 -74
- package/dist/cjs/core/schema/schema-builder.cjs.map +0 -10
- package/dist/cjs/core/schema/schema-helpers.cjs +0 -200
- package/dist/cjs/core/schema/schema-helpers.cjs.map +0 -10
- package/dist/cjs/core/schema/schema.cjs +0 -91
- package/dist/cjs/core/schema/schema.cjs.map +0 -10
- package/dist/cjs/core/schema/table-orm.cjs +0 -189
- package/dist/cjs/core/schema/table-orm.cjs.map +0 -10
- package/dist/mjs/core/commands/command-executor.mjs +0 -109
- package/dist/mjs/core/commands/command-executor.mjs.map +0 -10
- package/dist/mjs/core/commands/content-commands.mjs +0 -821
- package/dist/mjs/core/commands/content-commands.mjs.map +0 -10
- package/dist/mjs/core/commands/metadata-commands.mjs +0 -120
- package/dist/mjs/core/commands/metadata-commands.mjs.map +0 -10
- package/dist/mjs/core/commands/named-expression-commands.mjs +0 -323
- package/dist/mjs/core/commands/named-expression-commands.mjs.map +0 -10
- package/dist/mjs/core/commands/structure-commands.mjs +0 -661
- package/dist/mjs/core/commands/structure-commands.mjs.map +0 -10
- package/dist/mjs/core/commands/style-commands.mjs +0 -189
- package/dist/mjs/core/commands/style-commands.mjs.map +0 -10
- package/dist/mjs/core/commands/table-commands.mjs +0 -459
- package/dist/mjs/core/commands/table-commands.mjs.map +0 -10
- package/dist/mjs/core/commands/types.mjs +0 -59
- package/dist/mjs/core/commands/types.mjs.map +0 -10
- package/dist/mjs/core/managers/schema-manager.mjs +0 -334
- package/dist/mjs/core/managers/schema-manager.mjs.map +0 -10
- package/dist/mjs/core/schema/cell-orm.mjs +0 -35
- package/dist/mjs/core/schema/cell-orm.mjs.map +0 -10
- package/dist/mjs/core/schema/grid-orm.mjs +0 -84
- package/dist/mjs/core/schema/grid-orm.mjs.map +0 -10
- package/dist/mjs/core/schema/schema-builder.mjs +0 -34
- package/dist/mjs/core/schema/schema-builder.mjs.map +0 -10
- package/dist/mjs/core/schema/schema-helpers.mjs +0 -160
- package/dist/mjs/core/schema/schema-helpers.mjs.map +0 -10
- package/dist/mjs/core/schema/schema.mjs +0 -51
- package/dist/mjs/core/schema/schema.mjs.map +0 -10
- package/dist/mjs/core/schema/table-orm.mjs +0 -156
- package/dist/mjs/core/schema/table-orm.mjs.map +0 -10
- package/dist/types/core/commands/command-executor.d.ts +0 -81
- package/dist/types/core/commands/content-commands.d.ts +0 -172
- package/dist/types/core/commands/metadata-commands.d.ts +0 -55
- package/dist/types/core/commands/named-expression-commands.d.ts +0 -130
- package/dist/types/core/commands/structure-commands.d.ts +0 -155
- package/dist/types/core/commands/style-commands.d.ts +0 -76
- package/dist/types/core/commands/table-commands.d.ts +0 -119
- package/dist/types/core/commands/types.d.ts +0 -143
- package/dist/types/core/managers/schema-manager.d.ts +0 -142
- package/dist/types/core/schema/cell-orm.d.ts +0 -33
- package/dist/types/core/schema/grid-orm.d.ts +0 -63
- package/dist/types/core/schema/schema-builder.d.ts +0 -16
- package/dist/types/core/schema/schema-helpers.d.ts +0 -49
- package/dist/types/core/schema/schema.d.ts +0 -167
- package/dist/types/core/schema/schema.type-test.d.ts +0 -1
- package/dist/types/core/schema/table-orm.d.ts +0 -46
|
@@ -1,160 +0,0 @@
|
|
|
1
|
-
// src/core/schema/schema-helpers.ts
|
|
2
|
-
function rowToObject(engine, table, rowIndex, headers, getCellMetadata) {
|
|
3
|
-
const result = {};
|
|
4
|
-
for (const [columnName, header] of Object.entries(headers)) {
|
|
5
|
-
const cellAddress = {
|
|
6
|
-
workbookName: table.workbookName,
|
|
7
|
-
sheetName: table.sheetName,
|
|
8
|
-
colIndex: table.start.colIndex + header.index,
|
|
9
|
-
rowIndex
|
|
10
|
-
};
|
|
11
|
-
const value = engine.getCellValue(cellAddress);
|
|
12
|
-
const metadata = getCellMetadata ? getCellMetadata(cellAddress) : undefined;
|
|
13
|
-
result[columnName] = header.parse(value, metadata);
|
|
14
|
-
}
|
|
15
|
-
return result;
|
|
16
|
-
}
|
|
17
|
-
function objectToRowValues(obj, headers) {
|
|
18
|
-
const values = new Map;
|
|
19
|
-
const metadata = new Map;
|
|
20
|
-
for (const [columnName, header] of Object.entries(headers)) {
|
|
21
|
-
if (columnName in obj) {
|
|
22
|
-
const columnValue = obj[columnName];
|
|
23
|
-
const { value, metadata: cellMetadata } = header.write(columnValue);
|
|
24
|
-
values.set(header.index, value);
|
|
25
|
-
if (cellMetadata !== undefined) {
|
|
26
|
-
metadata.set(header.index, cellMetadata);
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
return { values, metadata };
|
|
31
|
-
}
|
|
32
|
-
function matchesFilter(item, filter) {
|
|
33
|
-
for (const [key, value] of Object.entries(filter)) {
|
|
34
|
-
if (item[key] !== value) {
|
|
35
|
-
return false;
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
return true;
|
|
39
|
-
}
|
|
40
|
-
function getTableRowCount(engine, table) {
|
|
41
|
-
if (table.endRow.type === "infinity") {
|
|
42
|
-
let count = 0;
|
|
43
|
-
let emptyRowStreak = 0;
|
|
44
|
-
const maxEmptyRows = 10;
|
|
45
|
-
for (let row = table.start.rowIndex + 1;emptyRowStreak < maxEmptyRows; row++) {
|
|
46
|
-
let hasContent = false;
|
|
47
|
-
for (let col = 0;col < table.headers.size; col++) {
|
|
48
|
-
const cellAddress = {
|
|
49
|
-
workbookName: table.workbookName,
|
|
50
|
-
sheetName: table.sheetName,
|
|
51
|
-
colIndex: table.start.colIndex + col,
|
|
52
|
-
rowIndex: row
|
|
53
|
-
};
|
|
54
|
-
const value = engine.getCellValue(cellAddress);
|
|
55
|
-
if (value !== "" && value !== undefined) {
|
|
56
|
-
hasContent = true;
|
|
57
|
-
break;
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
if (hasContent) {
|
|
61
|
-
count++;
|
|
62
|
-
emptyRowStreak = 0;
|
|
63
|
-
} else {
|
|
64
|
-
emptyRowStreak++;
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
return count;
|
|
68
|
-
} else {
|
|
69
|
-
return table.endRow.value - table.start.rowIndex;
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
function getNextEmptyRow(engine, table) {
|
|
73
|
-
const dataStartRow = table.start.rowIndex + 1;
|
|
74
|
-
if (table.endRow.type === "infinity") {
|
|
75
|
-
let emptyRowStreak = 0;
|
|
76
|
-
const maxEmptyRows = 10;
|
|
77
|
-
for (let row = dataStartRow;; row++) {
|
|
78
|
-
let hasContent = false;
|
|
79
|
-
for (let col = 0;col < table.headers.size; col++) {
|
|
80
|
-
const cellAddress = {
|
|
81
|
-
workbookName: table.workbookName,
|
|
82
|
-
sheetName: table.sheetName,
|
|
83
|
-
colIndex: table.start.colIndex + col,
|
|
84
|
-
rowIndex: row
|
|
85
|
-
};
|
|
86
|
-
const value = engine.getCellValue(cellAddress);
|
|
87
|
-
if (value !== "" && value !== undefined) {
|
|
88
|
-
hasContent = true;
|
|
89
|
-
break;
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
if (!hasContent) {
|
|
93
|
-
return row;
|
|
94
|
-
}
|
|
95
|
-
emptyRowStreak = hasContent ? 0 : emptyRowStreak + 1;
|
|
96
|
-
if (emptyRowStreak >= maxEmptyRows) {
|
|
97
|
-
return row - maxEmptyRows + 1;
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
} else {
|
|
101
|
-
return table.endRow.value + 1;
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
function* iterateTableRows(engine, table) {
|
|
105
|
-
const dataStartRow = table.start.rowIndex + 1;
|
|
106
|
-
if (table.endRow.type === "infinity") {
|
|
107
|
-
let emptyRowStreak = 0;
|
|
108
|
-
const maxEmptyRows = 10;
|
|
109
|
-
for (let row = dataStartRow;emptyRowStreak < maxEmptyRows; row++) {
|
|
110
|
-
let hasContent = false;
|
|
111
|
-
for (let col = 0;col < table.headers.size; col++) {
|
|
112
|
-
const cellAddress = {
|
|
113
|
-
workbookName: table.workbookName,
|
|
114
|
-
sheetName: table.sheetName,
|
|
115
|
-
colIndex: table.start.colIndex + col,
|
|
116
|
-
rowIndex: row
|
|
117
|
-
};
|
|
118
|
-
const value = engine.getCellValue(cellAddress);
|
|
119
|
-
if (value !== "" && value !== undefined) {
|
|
120
|
-
hasContent = true;
|
|
121
|
-
break;
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
if (hasContent) {
|
|
125
|
-
emptyRowStreak = 0;
|
|
126
|
-
yield { rowIndex: row, isEmpty: false };
|
|
127
|
-
} else {
|
|
128
|
-
emptyRowStreak++;
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
} else {
|
|
132
|
-
for (let row = dataStartRow;row <= table.endRow.value; row++) {
|
|
133
|
-
let hasContent = false;
|
|
134
|
-
for (let col = 0;col < table.headers.size; col++) {
|
|
135
|
-
const cellAddress = {
|
|
136
|
-
workbookName: table.workbookName,
|
|
137
|
-
sheetName: table.sheetName,
|
|
138
|
-
colIndex: table.start.colIndex + col,
|
|
139
|
-
rowIndex: row
|
|
140
|
-
};
|
|
141
|
-
const value = engine.getCellValue(cellAddress);
|
|
142
|
-
if (value !== "" && value !== undefined) {
|
|
143
|
-
hasContent = true;
|
|
144
|
-
break;
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
yield { rowIndex: row, isEmpty: !hasContent };
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
export {
|
|
152
|
-
rowToObject,
|
|
153
|
-
objectToRowValues,
|
|
154
|
-
matchesFilter,
|
|
155
|
-
iterateTableRows,
|
|
156
|
-
getTableRowCount,
|
|
157
|
-
getNextEmptyRow
|
|
158
|
-
};
|
|
159
|
-
|
|
160
|
-
//# debugId=16C0BE2ADACEA9EB64756E2164756E21
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../../../src/core/schema/schema-helpers.ts"],
|
|
4
|
-
"sourcesContent": [
|
|
5
|
-
"/**\n * Schema 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: 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\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 * Result from objectToRowValues including both values and optional metadata\n */\nexport type RowValuesResult<TCellMetadata = unknown> = {\n values: Map<number, SerializedCellValue>;\n metadata: Map<number, TCellMetadata>;\n};\n\n/**\n * Convert a typed object to cell values based on headers using write functions\n */\nexport function objectToRowValues<TItem extends Record<string, unknown>, TCellMetadata = unknown>(\n obj: TItem,\n headers: TableSchemaHeaders<TCellMetadata>\n): RowValuesResult<TCellMetadata> {\n const values = new Map<number, SerializedCellValue>();\n const metadata = new Map<number, TCellMetadata>();\n\n for (const [columnName, header] of Object.entries(headers)) {\n if (columnName in obj) {\n const columnValue = obj[columnName];\n const { value, metadata: cellMetadata } = header.write(columnValue);\n values.set(header.index, value);\n if (cellMetadata !== undefined) {\n metadata.set(header.index, cellMetadata);\n }\n }\n }\n\n return { values, metadata };\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": "16C0BE2ADACEA9EB64756E2164756E21",
|
|
9
|
-
"names": []
|
|
10
|
-
}
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
// src/core/schema/schema.ts
|
|
2
|
-
function defineSchema() {
|
|
3
|
-
const declaration = {};
|
|
4
|
-
const builder = {
|
|
5
|
-
addTableSchema(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
|
-
addCellSchema(namespace, cellAddress, parse, write) {
|
|
15
|
-
declaration[namespace] = {
|
|
16
|
-
type: "cell",
|
|
17
|
-
cellAddress,
|
|
18
|
-
parse,
|
|
19
|
-
write: write ?? ((value) => ({ value }))
|
|
20
|
-
};
|
|
21
|
-
return builder;
|
|
22
|
-
},
|
|
23
|
-
addGridSchema(namespace, address, range, parse, write) {
|
|
24
|
-
declaration[namespace] = {
|
|
25
|
-
type: "grid",
|
|
26
|
-
workbookName: address.workbookName,
|
|
27
|
-
sheetName: address.sheetName,
|
|
28
|
-
range,
|
|
29
|
-
parse,
|
|
30
|
-
write: write ?? ((value) => ({ value }))
|
|
31
|
-
};
|
|
32
|
-
return builder;
|
|
33
|
-
},
|
|
34
|
-
schema: undefined,
|
|
35
|
-
declaration
|
|
36
|
-
};
|
|
37
|
-
return builder;
|
|
38
|
-
}
|
|
39
|
-
var defineHeader = (index, parse, write) => {
|
|
40
|
-
return {
|
|
41
|
-
parse,
|
|
42
|
-
write: write ?? ((value) => ({ value })),
|
|
43
|
-
index
|
|
44
|
-
};
|
|
45
|
-
};
|
|
46
|
-
export {
|
|
47
|
-
defineSchema,
|
|
48
|
-
defineHeader
|
|
49
|
-
};
|
|
50
|
-
|
|
51
|
-
//# debugId=5C9087F143083A7464756E2164756E21
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../../../src/core/schema/schema.ts"],
|
|
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 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
|
-
],
|
|
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": "5C9087F143083A7464756E2164756E21",
|
|
9
|
-
"names": []
|
|
10
|
-
}
|
|
@@ -1,156 +0,0 @@
|
|
|
1
|
-
// src/core/schema/table-orm.ts
|
|
2
|
-
import {
|
|
3
|
-
rowToObject,
|
|
4
|
-
objectToRowValues,
|
|
5
|
-
matchesFilter,
|
|
6
|
-
getTableRowCount,
|
|
7
|
-
getNextEmptyRow,
|
|
8
|
-
iterateTableRows
|
|
9
|
-
} from "./schema-helpers.mjs";
|
|
10
|
-
|
|
11
|
-
class TableOrm {
|
|
12
|
-
engine;
|
|
13
|
-
workbookName;
|
|
14
|
-
tableName;
|
|
15
|
-
headers;
|
|
16
|
-
namespace;
|
|
17
|
-
constructor(engine, workbookName, tableName, headers, namespace) {
|
|
18
|
-
this.engine = engine;
|
|
19
|
-
this.workbookName = workbookName;
|
|
20
|
-
this.tableName = tableName;
|
|
21
|
-
this.headers = headers;
|
|
22
|
-
this.namespace = namespace;
|
|
23
|
-
}
|
|
24
|
-
getTable() {
|
|
25
|
-
const table = this.engine._tableManager.getTable({
|
|
26
|
-
workbookName: this.workbookName,
|
|
27
|
-
name: this.tableName
|
|
28
|
-
});
|
|
29
|
-
if (!table) {
|
|
30
|
-
throw new Error(`Table "${this.tableName}" not found in workbook "${this.workbookName}"`);
|
|
31
|
-
}
|
|
32
|
-
return table;
|
|
33
|
-
}
|
|
34
|
-
findWhere(filter) {
|
|
35
|
-
const table = this.getTable();
|
|
36
|
-
for (const { rowIndex, isEmpty } of iterateTableRows(this.engine, table)) {
|
|
37
|
-
if (isEmpty)
|
|
38
|
-
continue;
|
|
39
|
-
try {
|
|
40
|
-
const item = rowToObject(this.engine, table, rowIndex, this.headers, (cell) => this.engine.getCellMetadata(cell));
|
|
41
|
-
if (matchesFilter(item, filter)) {
|
|
42
|
-
return item;
|
|
43
|
-
}
|
|
44
|
-
} catch {
|
|
45
|
-
continue;
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
return;
|
|
49
|
-
}
|
|
50
|
-
findAllWhere(filter) {
|
|
51
|
-
const table = this.getTable();
|
|
52
|
-
const results = [];
|
|
53
|
-
for (const { rowIndex, isEmpty } of iterateTableRows(this.engine, table)) {
|
|
54
|
-
if (isEmpty)
|
|
55
|
-
continue;
|
|
56
|
-
try {
|
|
57
|
-
const item = rowToObject(this.engine, table, rowIndex, this.headers, (cell) => this.engine.getCellMetadata(cell));
|
|
58
|
-
if (matchesFilter(item, filter)) {
|
|
59
|
-
results.push(item);
|
|
60
|
-
}
|
|
61
|
-
} catch {
|
|
62
|
-
continue;
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
return results;
|
|
66
|
-
}
|
|
67
|
-
append(item) {
|
|
68
|
-
const table = this.getTable();
|
|
69
|
-
const nextRow = getNextEmptyRow(this.engine, table);
|
|
70
|
-
const { values, metadata } = objectToRowValues(item, this.headers);
|
|
71
|
-
for (const [colOffset, value] of values) {
|
|
72
|
-
const cellAddress = {
|
|
73
|
-
workbookName: table.workbookName,
|
|
74
|
-
sheetName: table.sheetName,
|
|
75
|
-
colIndex: table.start.colIndex + colOffset,
|
|
76
|
-
rowIndex: nextRow
|
|
77
|
-
};
|
|
78
|
-
this.engine.setCellContent(cellAddress, value);
|
|
79
|
-
const cellMetadata = metadata.get(colOffset);
|
|
80
|
-
if (cellMetadata !== undefined) {
|
|
81
|
-
this.engine.setCellMetadata(cellAddress, cellMetadata);
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
return item;
|
|
85
|
-
}
|
|
86
|
-
updateWhere(filter, update) {
|
|
87
|
-
const table = this.getTable();
|
|
88
|
-
let updatedCount = 0;
|
|
89
|
-
for (const { rowIndex, isEmpty } of iterateTableRows(this.engine, table)) {
|
|
90
|
-
if (isEmpty)
|
|
91
|
-
continue;
|
|
92
|
-
try {
|
|
93
|
-
const item = rowToObject(this.engine, table, rowIndex, this.headers, (cell) => this.engine.getCellMetadata(cell));
|
|
94
|
-
if (matchesFilter(item, filter)) {
|
|
95
|
-
const { values, metadata } = objectToRowValues(update, this.headers);
|
|
96
|
-
for (const [colOffset, value] of values) {
|
|
97
|
-
const cellAddress = {
|
|
98
|
-
workbookName: table.workbookName,
|
|
99
|
-
sheetName: table.sheetName,
|
|
100
|
-
colIndex: table.start.colIndex + colOffset,
|
|
101
|
-
rowIndex
|
|
102
|
-
};
|
|
103
|
-
this.engine.setCellContent(cellAddress, value);
|
|
104
|
-
const cellMetadata = metadata.get(colOffset);
|
|
105
|
-
if (cellMetadata !== undefined) {
|
|
106
|
-
this.engine.setCellMetadata(cellAddress, cellMetadata);
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
updatedCount++;
|
|
110
|
-
}
|
|
111
|
-
} catch {
|
|
112
|
-
continue;
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
return updatedCount;
|
|
116
|
-
}
|
|
117
|
-
removeWhere(filter) {
|
|
118
|
-
const table = this.getTable();
|
|
119
|
-
let removedCount = 0;
|
|
120
|
-
const rowsToRemove = [];
|
|
121
|
-
for (const { rowIndex, isEmpty } of iterateTableRows(this.engine, table)) {
|
|
122
|
-
if (isEmpty)
|
|
123
|
-
continue;
|
|
124
|
-
try {
|
|
125
|
-
const item = rowToObject(this.engine, table, rowIndex, this.headers, (cell) => this.engine.getCellMetadata(cell));
|
|
126
|
-
if (matchesFilter(item, filter)) {
|
|
127
|
-
rowsToRemove.push(rowIndex);
|
|
128
|
-
}
|
|
129
|
-
} catch {
|
|
130
|
-
continue;
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
for (const rowIndex of rowsToRemove.reverse()) {
|
|
134
|
-
for (const header of Object.values(this.headers)) {
|
|
135
|
-
const cellAddress = {
|
|
136
|
-
workbookName: table.workbookName,
|
|
137
|
-
sheetName: table.sheetName,
|
|
138
|
-
colIndex: table.start.colIndex + header.index,
|
|
139
|
-
rowIndex
|
|
140
|
-
};
|
|
141
|
-
this.engine.setCellContent(cellAddress, undefined);
|
|
142
|
-
}
|
|
143
|
-
removedCount++;
|
|
144
|
-
}
|
|
145
|
-
return removedCount;
|
|
146
|
-
}
|
|
147
|
-
count() {
|
|
148
|
-
const table = this.getTable();
|
|
149
|
-
return getTableRowCount(this.engine, table);
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
export {
|
|
153
|
-
TableOrm
|
|
154
|
-
};
|
|
155
|
-
|
|
156
|
-
//# debugId=8F0B80F520964A2164756E2164756E21
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../../../src/core/schema/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.mjs\";\nimport type { FormulaEngine } from \"../engine.mjs\";\nimport {\n rowToObject,\n objectToRowValues,\n matchesFilter,\n getTableRowCount,\n getNextEmptyRow,\n iterateTableRows,\n type TableSchemaHeaders,\n} from \"./schema-helpers.mjs\";\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, metadata } = objectToRowValues(item, this.headers);\n\n // Write each cell value and metadata\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 const cellMetadata = metadata.get(colOffset);\n if (cellMetadata !== undefined) {\n this.engine.setCellMetadata(cellAddress, cellMetadata);\n }\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, metadata } = 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 const cellMetadata = metadata.get(colOffset);\n if (cellMetadata !== undefined) {\n this.engine.setCellMetadata(cellAddress, cellMetadata);\n }\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": ";AASA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAUO,MAAM,SAAgD;AAAA,EAEjD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EALV,WAAW,CACD,QACA,cACA,WACA,SACA,WACR;AAAA,IALQ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA;AAAA,EAMF,QAAQ,GAAoB;AAAA,IAClC,MAAM,QAAQ,KAAK,OAAO,cAAc,SAAS;AAAA,MAC/C,cAAc,KAAK;AAAA,MACnB,MAAM,KAAK;AAAA,IACb,CAAC;AAAA,IAED,IAAI,CAAC,OAAO;AAAA,MACV,MAAM,IAAI,MACR,UAAU,KAAK,qCAAqC,KAAK,eAC3D;AAAA,IACF;AAAA,IAEA,OAAO;AAAA;AAAA,EAMT,SAAS,CAAC,QAA2C;AAAA,IACnD,MAAM,QAAQ,KAAK,SAAS;AAAA,IAE5B,aAAa,UAAU,aAAa,iBAAiB,KAAK,QAAQ,KAAK,GAAG;AAAA,MACxE,IAAI;AAAA,QAAS;AAAA,MAEb,IAAI;AAAA,QACF,MAAM,OAAO,YACX,KAAK,QACL,OACA,UACA,KAAK,SACL,CAAC,SAAS,KAAK,OAAO,gBAAgB,IAAI,CAC5C;AAAA,QAEA,IAAI,cAAc,MAAM,MAAM,GAAG;AAAA,UAC/B,OAAO;AAAA,QACT;AAAA,QACA,MAAM;AAAA,QAEN;AAAA;AAAA,IAEJ;AAAA,IAEA;AAAA;AAAA,EAMF,YAAY,CAAC,QAAiC;AAAA,IAC5C,MAAM,QAAQ,KAAK,SAAS;AAAA,IAC5B,MAAM,UAAmB,CAAC;AAAA,IAE1B,aAAa,UAAU,aAAa,iBAAiB,KAAK,QAAQ,KAAK,GAAG;AAAA,MACxE,IAAI;AAAA,QAAS;AAAA,MAEb,IAAI;AAAA,QACF,MAAM,OAAO,YACX,KAAK,QACL,OACA,UACA,KAAK,SACL,CAAC,SAAS,KAAK,OAAO,gBAAgB,IAAI,CAC5C;AAAA,QAEA,IAAI,cAAc,MAAM,MAAM,GAAG;AAAA,UAC/B,QAAQ,KAAK,IAAI;AAAA,QACnB;AAAA,QACA,MAAM;AAAA,QAEN;AAAA;AAAA,IAEJ;AAAA,IAEA,OAAO;AAAA;AAAA,EAMT,MAAM,CAAC,MAAoB;AAAA,IACzB,MAAM,QAAQ,KAAK,SAAS;AAAA,IAC5B,MAAM,UAAU,gBAAgB,KAAK,QAAQ,KAAK;AAAA,IAClD,QAAQ,QAAQ,aAAa,kBAAkB,MAAM,KAAK,OAAO;AAAA,IAGjE,YAAY,WAAW,UAAU,QAAQ;AAAA,MACvC,MAAM,cAA2B;AAAA,QAC/B,cAAc,MAAM;AAAA,QACpB,WAAW,MAAM;AAAA,QACjB,UAAU,MAAM,MAAM,WAAW;AAAA,QACjC,UAAU;AAAA,MACZ;AAAA,MAEA,KAAK,OAAO,eAAe,aAAa,KAAK;AAAA,MAC7C,MAAM,eAAe,SAAS,IAAI,SAAS;AAAA,MAC3C,IAAI,iBAAiB,WAAW;AAAA,QAC9B,KAAK,OAAO,gBAAgB,aAAa,YAAY;AAAA,MACvD;AAAA,IACF;AAAA,IAEA,OAAO;AAAA;AAAA,EAOT,WAAW,CAAC,QAAwB,QAAgC;AAAA,IAClE,MAAM,QAAQ,KAAK,SAAS;AAAA,IAC5B,IAAI,eAAe;AAAA,IAEnB,aAAa,UAAU,aAAa,iBAAiB,KAAK,QAAQ,KAAK,GAAG;AAAA,MACxE,IAAI;AAAA,QAAS;AAAA,MAEb,IAAI;AAAA,QACF,MAAM,OAAO,YACX,KAAK,QACL,OACA,UACA,KAAK,SACL,CAAC,SAAS,KAAK,OAAO,gBAAgB,IAAI,CAC5C;AAAA,QAEA,IAAI,cAAc,MAAM,MAAM,GAAG;AAAA,UAE/B,QAAQ,QAAQ,aAAa,kBAAkB,QAAiB,KAAK,OAAO;AAAA,UAE5E,YAAY,WAAW,UAAU,QAAQ;AAAA,YACvC,MAAM,cAA2B;AAAA,cAC/B,cAAc,MAAM;AAAA,cACpB,WAAW,MAAM;AAAA,cACjB,UAAU,MAAM,MAAM,WAAW;AAAA,cACjC;AAAA,YACF;AAAA,YAEA,KAAK,OAAO,eAAe,aAAa,KAAK;AAAA,YAC7C,MAAM,eAAe,SAAS,IAAI,SAAS;AAAA,YAC3C,IAAI,iBAAiB,WAAW;AAAA,cAC9B,KAAK,OAAO,gBAAgB,aAAa,YAAY;AAAA,YACvD;AAAA,UACF;AAAA,UAEA;AAAA,QACF;AAAA,QACA,MAAM;AAAA,QAEN;AAAA;AAAA,IAEJ;AAAA,IAEA,OAAO;AAAA;AAAA,EAOT,WAAW,CAAC,QAAgC;AAAA,IAC1C,MAAM,QAAQ,KAAK,SAAS;AAAA,IAC5B,IAAI,eAAe;AAAA,IAGnB,MAAM,eAAyB,CAAC;AAAA,IAEhC,aAAa,UAAU,aAAa,iBAAiB,KAAK,QAAQ,KAAK,GAAG;AAAA,MACxE,IAAI;AAAA,QAAS;AAAA,MAEb,IAAI;AAAA,QACF,MAAM,OAAO,YACX,KAAK,QACL,OACA,UACA,KAAK,SACL,CAAC,SAAS,KAAK,OAAO,gBAAgB,IAAI,CAC5C;AAAA,QAEA,IAAI,cAAc,MAAM,MAAM,GAAG;AAAA,UAC/B,aAAa,KAAK,QAAQ;AAAA,QAC5B;AAAA,QACA,MAAM;AAAA,QAEN;AAAA;AAAA,IAEJ;AAAA,IAGA,WAAW,YAAY,aAAa,QAAQ,GAAG;AAAA,MAE7C,WAAW,UAAU,OAAO,OAAO,KAAK,OAAO,GAAG;AAAA,QAChD,MAAM,cAA2B;AAAA,UAC/B,cAAc,MAAM;AAAA,UACpB,WAAW,MAAM;AAAA,UACjB,UAAU,MAAM,MAAM,WAAW,OAAO;AAAA,UACxC;AAAA,QACF;AAAA,QAEA,KAAK,OAAO,eAAe,aAAa,SAAS;AAAA,MACnD;AAAA,MAEA;AAAA,IACF;AAAA,IAEA,OAAO;AAAA;AAAA,EAMT,KAAK,GAAW;AAAA,IACd,MAAM,QAAQ,KAAK,SAAS;AAAA,IAC5B,OAAO,iBAAiB,KAAK,QAAQ,KAAK;AAAA;AAE9C;",
|
|
8
|
-
"debugId": "8F0B80F520964A2164756E2164756E21",
|
|
9
|
-
"names": []
|
|
10
|
-
}
|
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* CommandExecutor - Executes commands with undo/redo support and schema validation
|
|
3
|
-
*
|
|
4
|
-
* Handles:
|
|
5
|
-
* - Command execution with optional re-evaluation
|
|
6
|
-
* - Schema validation after re-evaluation
|
|
7
|
-
* - Automatic rollback on validation failure
|
|
8
|
-
* - Undo/redo stacks
|
|
9
|
-
* - Action serialization for persistence
|
|
10
|
-
*/
|
|
11
|
-
import type { EvaluationManager } from "../managers/evaluation-manager";
|
|
12
|
-
import type { EventManager } from "../managers/event-manager";
|
|
13
|
-
import type { EngineCommand, EngineAction, ExecuteOptions, SchemaValidationResult, SchemaValidationErrorInfo } from "./types";
|
|
14
|
-
/**
|
|
15
|
-
* Error thrown when schema integrity validation fails.
|
|
16
|
-
* Contains all validation errors that occurred.
|
|
17
|
-
*/
|
|
18
|
-
export declare class SchemaIntegrityError extends Error {
|
|
19
|
-
errors: SchemaValidationErrorInfo[];
|
|
20
|
-
constructor(errors: SchemaValidationErrorInfo[]);
|
|
21
|
-
}
|
|
22
|
-
/**
|
|
23
|
-
* CommandExecutor manages command execution with validation and undo/redo support.
|
|
24
|
-
*/
|
|
25
|
-
export declare class CommandExecutor {
|
|
26
|
-
private evaluationManager;
|
|
27
|
-
private eventManager;
|
|
28
|
-
private validateAllSchemas;
|
|
29
|
-
private undoStack;
|
|
30
|
-
private redoStack;
|
|
31
|
-
private actionLog;
|
|
32
|
-
constructor(evaluationManager: EvaluationManager, eventManager: EventManager, validateAllSchemas: () => SchemaValidationResult);
|
|
33
|
-
/**
|
|
34
|
-
* Execute a command with optional schema validation.
|
|
35
|
-
*
|
|
36
|
-
* @param command - The command to execute
|
|
37
|
-
* @param options - Execution options
|
|
38
|
-
* @throws SchemaIntegrityError if validation fails
|
|
39
|
-
*/
|
|
40
|
-
execute(command: EngineCommand, options?: ExecuteOptions): void;
|
|
41
|
-
/**
|
|
42
|
-
* Undo the last command.
|
|
43
|
-
*
|
|
44
|
-
* @returns true if undo was performed, false if nothing to undo
|
|
45
|
-
*/
|
|
46
|
-
undo(): boolean;
|
|
47
|
-
/**
|
|
48
|
-
* Redo the last undone command.
|
|
49
|
-
*
|
|
50
|
-
* @returns true if redo was performed, false if nothing to redo
|
|
51
|
-
*/
|
|
52
|
-
redo(): boolean;
|
|
53
|
-
/**
|
|
54
|
-
* Check if undo is available.
|
|
55
|
-
*/
|
|
56
|
-
canUndo(): boolean;
|
|
57
|
-
/**
|
|
58
|
-
* Check if redo is available.
|
|
59
|
-
*/
|
|
60
|
-
canRedo(): boolean;
|
|
61
|
-
/**
|
|
62
|
-
* Get the action log for persistence/collaboration.
|
|
63
|
-
*/
|
|
64
|
-
getActionLog(): EngineAction[];
|
|
65
|
-
/**
|
|
66
|
-
* Clear the action log.
|
|
67
|
-
*/
|
|
68
|
-
clearActionLog(): void;
|
|
69
|
-
/**
|
|
70
|
-
* Clear undo/redo stacks.
|
|
71
|
-
*/
|
|
72
|
-
clearHistory(): void;
|
|
73
|
-
/**
|
|
74
|
-
* Get the number of commands in the undo stack.
|
|
75
|
-
*/
|
|
76
|
-
getUndoStackSize(): number;
|
|
77
|
-
/**
|
|
78
|
-
* Get the number of commands in the redo stack.
|
|
79
|
-
*/
|
|
80
|
-
getRedoStackSize(): number;
|
|
81
|
-
}
|