@danielsimonjr/mathts-workbook 0.1.8 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +247 -117
- package/dist/chunk-3KTM2DZC.js +720 -0
- package/dist/chunk-TMVFG3I3.js +581 -0
- package/dist/cli.d.ts +39 -0
- package/dist/cli.js +1758 -79
- package/dist/index.d.ts +304 -9
- package/dist/index.js +35 -1
- package/dist/run-worker.d.ts +2 -0
- package/dist/run-worker.js +39 -0
- package/package.json +64 -62
- package/dist/chunk-L7UWFWMV.js +0 -269
package/dist/chunk-L7UWFWMV.js
DELETED
|
@@ -1,269 +0,0 @@
|
|
|
1
|
-
// src/parser.ts
|
|
2
|
-
function parseWorkbook(content) {
|
|
3
|
-
try {
|
|
4
|
-
const errors = [];
|
|
5
|
-
const warnings = [];
|
|
6
|
-
if (!content.trim()) {
|
|
7
|
-
return {
|
|
8
|
-
success: false,
|
|
9
|
-
errors: ["Empty workbook content"]
|
|
10
|
-
};
|
|
11
|
-
}
|
|
12
|
-
const workbook = {
|
|
13
|
-
version: "1.0",
|
|
14
|
-
metadata: {
|
|
15
|
-
title: "Untitled Workbook"
|
|
16
|
-
},
|
|
17
|
-
runtime: {
|
|
18
|
-
engine: "mathts",
|
|
19
|
-
execution: "reactive"
|
|
20
|
-
},
|
|
21
|
-
cells: []
|
|
22
|
-
};
|
|
23
|
-
if (warnings.length > 0 || errors.length > 0) {
|
|
24
|
-
return {
|
|
25
|
-
success: errors.length === 0,
|
|
26
|
-
workbook: errors.length === 0 ? workbook : void 0,
|
|
27
|
-
errors: errors.length > 0 ? errors : void 0,
|
|
28
|
-
warnings: warnings.length > 0 ? warnings : void 0
|
|
29
|
-
};
|
|
30
|
-
}
|
|
31
|
-
return {
|
|
32
|
-
success: true,
|
|
33
|
-
workbook
|
|
34
|
-
};
|
|
35
|
-
} catch (error) {
|
|
36
|
-
return {
|
|
37
|
-
success: false,
|
|
38
|
-
errors: [`Parse error: ${error instanceof Error ? error.message : String(error)}`]
|
|
39
|
-
};
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
function serializeWorkbook(_workbook) {
|
|
43
|
-
throw new Error("serializeWorkbook not yet implemented");
|
|
44
|
-
}
|
|
45
|
-
function stripOutputs(workbook) {
|
|
46
|
-
return {
|
|
47
|
-
...workbook,
|
|
48
|
-
cells: workbook.cells.map((cell) => ({
|
|
49
|
-
...cell,
|
|
50
|
-
output: void 0,
|
|
51
|
-
error: void 0
|
|
52
|
-
}))
|
|
53
|
-
};
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
// src/graph.ts
|
|
57
|
-
function buildDependencyGraph(cells) {
|
|
58
|
-
const nodes = /* @__PURE__ */ new Map();
|
|
59
|
-
for (const cell of cells) {
|
|
60
|
-
nodes.set(cell.id, {
|
|
61
|
-
id: cell.id,
|
|
62
|
-
dependencies: cell.dependsOn ?? [],
|
|
63
|
-
dependents: []
|
|
64
|
-
});
|
|
65
|
-
}
|
|
66
|
-
for (const cell of cells) {
|
|
67
|
-
for (const depId of cell.dependsOn ?? []) {
|
|
68
|
-
const depNode = nodes.get(depId);
|
|
69
|
-
if (depNode) {
|
|
70
|
-
depNode.dependents.push(cell.id);
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
const executionOrder = topologicalSort(nodes);
|
|
75
|
-
return { nodes, executionOrder };
|
|
76
|
-
}
|
|
77
|
-
function topologicalSort(nodes) {
|
|
78
|
-
const visited = /* @__PURE__ */ new Set();
|
|
79
|
-
const result = [];
|
|
80
|
-
function visit(id) {
|
|
81
|
-
if (visited.has(id)) return;
|
|
82
|
-
visited.add(id);
|
|
83
|
-
const node = nodes.get(id);
|
|
84
|
-
if (node) {
|
|
85
|
-
for (const depId of node.dependencies) {
|
|
86
|
-
visit(depId);
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
result.push(id);
|
|
90
|
-
}
|
|
91
|
-
for (const id of nodes.keys()) {
|
|
92
|
-
visit(id);
|
|
93
|
-
}
|
|
94
|
-
return result;
|
|
95
|
-
}
|
|
96
|
-
function getDependents(graph, cellId) {
|
|
97
|
-
const result = [];
|
|
98
|
-
const visited = /* @__PURE__ */ new Set();
|
|
99
|
-
function collect(id) {
|
|
100
|
-
const node = graph.nodes.get(id);
|
|
101
|
-
if (!node) return;
|
|
102
|
-
for (const depId of node.dependents) {
|
|
103
|
-
if (!visited.has(depId)) {
|
|
104
|
-
visited.add(depId);
|
|
105
|
-
result.push(depId);
|
|
106
|
-
collect(depId);
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
collect(cellId);
|
|
111
|
-
return result;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
// src/executor.ts
|
|
115
|
-
import { evaluate } from "@danielsimonjr/mathts-functions";
|
|
116
|
-
import { parse as parseYaml } from "yaml";
|
|
117
|
-
var WorkbookExecutor = class {
|
|
118
|
-
workbook;
|
|
119
|
-
graph;
|
|
120
|
-
outputs = /* @__PURE__ */ new Map();
|
|
121
|
-
handlers = [];
|
|
122
|
-
constructor(workbook) {
|
|
123
|
-
this.workbook = workbook;
|
|
124
|
-
this.graph = buildDependencyGraph(workbook.cells);
|
|
125
|
-
}
|
|
126
|
-
/**
|
|
127
|
-
* Subscribe to execution events
|
|
128
|
-
*/
|
|
129
|
-
on(handler) {
|
|
130
|
-
this.handlers.push(handler);
|
|
131
|
-
return () => {
|
|
132
|
-
const index = this.handlers.indexOf(handler);
|
|
133
|
-
if (index >= 0) {
|
|
134
|
-
this.handlers.splice(index, 1);
|
|
135
|
-
}
|
|
136
|
-
};
|
|
137
|
-
}
|
|
138
|
-
/**
|
|
139
|
-
* Emit an event to all handlers
|
|
140
|
-
*/
|
|
141
|
-
emit(event) {
|
|
142
|
-
for (const handler of this.handlers) {
|
|
143
|
-
handler(event);
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
/**
|
|
147
|
-
* Run all cells in order
|
|
148
|
-
*/
|
|
149
|
-
async runAll() {
|
|
150
|
-
for (const cellId of this.graph.executionOrder) {
|
|
151
|
-
await this.runCell(cellId);
|
|
152
|
-
}
|
|
153
|
-
this.emit({
|
|
154
|
-
type: "workbook:complete",
|
|
155
|
-
timestamp: Date.now()
|
|
156
|
-
});
|
|
157
|
-
}
|
|
158
|
-
/**
|
|
159
|
-
* Run a specific cell
|
|
160
|
-
*/
|
|
161
|
-
async runCell(cellId) {
|
|
162
|
-
const cell = this.workbook.cells.find((c) => c.id === cellId);
|
|
163
|
-
if (!cell) {
|
|
164
|
-
throw new Error(`Cell not found: ${cellId}`);
|
|
165
|
-
}
|
|
166
|
-
this.emit({
|
|
167
|
-
type: "cell:start",
|
|
168
|
-
cellId,
|
|
169
|
-
timestamp: Date.now()
|
|
170
|
-
});
|
|
171
|
-
try {
|
|
172
|
-
const output = await this.executeCell(cell);
|
|
173
|
-
this.outputs.set(cellId, output);
|
|
174
|
-
this.emit({
|
|
175
|
-
type: "cell:success",
|
|
176
|
-
cellId,
|
|
177
|
-
output,
|
|
178
|
-
timestamp: Date.now()
|
|
179
|
-
});
|
|
180
|
-
if (this.workbook.runtime.execution === "reactive") {
|
|
181
|
-
const dependents = getDependents(this.graph, cellId);
|
|
182
|
-
for (const depId of dependents) {
|
|
183
|
-
this.emit({
|
|
184
|
-
type: "cell:stale",
|
|
185
|
-
cellId: depId,
|
|
186
|
-
timestamp: Date.now()
|
|
187
|
-
});
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
return output;
|
|
191
|
-
} catch (error) {
|
|
192
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
193
|
-
this.emit({
|
|
194
|
-
type: "cell:error",
|
|
195
|
-
cellId,
|
|
196
|
-
error: errorMessage,
|
|
197
|
-
timestamp: Date.now()
|
|
198
|
-
});
|
|
199
|
-
throw error;
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
/**
|
|
203
|
-
* Execute a single cell
|
|
204
|
-
*/
|
|
205
|
-
async executeCell(cell) {
|
|
206
|
-
switch (cell.type) {
|
|
207
|
-
case "code":
|
|
208
|
-
return this.executeCode(cell);
|
|
209
|
-
case "markdown":
|
|
210
|
-
return cell.content;
|
|
211
|
-
// Markdown is pass-through
|
|
212
|
-
case "data":
|
|
213
|
-
return this.executeData(cell);
|
|
214
|
-
default:
|
|
215
|
-
throw new Error(`Unsupported cell type: ${cell.type}`);
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
/**
|
|
219
|
-
* Execute a code cell by evaluating its content as a MathTS expression.
|
|
220
|
-
*
|
|
221
|
-
* Dependency outputs are injected as named variables in the evaluation
|
|
222
|
-
* scope, so a cell can reference the result of an earlier cell by its id.
|
|
223
|
-
* Evaluation goes through the MathTS expression engine — property and
|
|
224
|
-
* method access route through the expression sandbox, so this does not
|
|
225
|
-
* have the arbitrary-code-execution exposure of the `Function` constructor.
|
|
226
|
-
*/
|
|
227
|
-
async executeCode(cell) {
|
|
228
|
-
const scope = {};
|
|
229
|
-
if (cell.dependsOn) {
|
|
230
|
-
for (const depId of cell.dependsOn) {
|
|
231
|
-
const output = this.outputs.get(depId);
|
|
232
|
-
if (output !== void 0) {
|
|
233
|
-
scope[depId] = output;
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
return evaluate(cell.content, scope);
|
|
238
|
-
}
|
|
239
|
-
/**
|
|
240
|
-
* Execute a data cell — parse its content as YAML (a superset of JSON).
|
|
241
|
-
*/
|
|
242
|
-
async executeData(cell) {
|
|
243
|
-
return parseYaml(cell.content);
|
|
244
|
-
}
|
|
245
|
-
/**
|
|
246
|
-
* Get output from a previous cell
|
|
247
|
-
*/
|
|
248
|
-
getOutput(cellId) {
|
|
249
|
-
return this.outputs.get(cellId);
|
|
250
|
-
}
|
|
251
|
-
};
|
|
252
|
-
function createExecutor(workbook) {
|
|
253
|
-
return new WorkbookExecutor(workbook);
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
// src/index.ts
|
|
257
|
-
var VERSION = "0.1.0";
|
|
258
|
-
|
|
259
|
-
export {
|
|
260
|
-
parseWorkbook,
|
|
261
|
-
serializeWorkbook,
|
|
262
|
-
stripOutputs,
|
|
263
|
-
buildDependencyGraph,
|
|
264
|
-
topologicalSort,
|
|
265
|
-
getDependents,
|
|
266
|
-
WorkbookExecutor,
|
|
267
|
-
createExecutor,
|
|
268
|
-
VERSION
|
|
269
|
-
};
|