@danielsimonjr/mathts-workbook 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +121 -0
- package/dist/chunk-64JBL36K.js +273 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +107 -0
- package/dist/index.d.ts +187 -0
- package/dist/index.js +22 -0
- package/package.json +61 -0
package/README.md
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
# @danielsimonjr/mathts-workbook
|
|
2
|
+
|
|
3
|
+
Scientific workbook runtime for MathTS with reactive YAML-based notebooks (`.mtsw` format).
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @danielsimonjr/mathts-workbook
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
### CLI
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
# Run a workbook
|
|
17
|
+
mtsw run example.mtsw
|
|
18
|
+
|
|
19
|
+
# Run specific cell
|
|
20
|
+
mtsw run example.mtsw -c compute
|
|
21
|
+
|
|
22
|
+
# Watch for changes
|
|
23
|
+
mtsw watch example.mtsw
|
|
24
|
+
|
|
25
|
+
# Validate structure
|
|
26
|
+
mtsw validate example.mtsw
|
|
27
|
+
|
|
28
|
+
# Show dependency graph
|
|
29
|
+
mtsw graph example.mtsw
|
|
30
|
+
|
|
31
|
+
# Create from template
|
|
32
|
+
mtsw new my-workbook -t tensor-physics
|
|
33
|
+
|
|
34
|
+
# Export
|
|
35
|
+
mtsw export example.mtsw -f html
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### Programmatic API
|
|
39
|
+
|
|
40
|
+
```typescript
|
|
41
|
+
import { parseWorkbook, createExecutor } from '@danielsimonjr/mathts-workbook';
|
|
42
|
+
|
|
43
|
+
const content = `
|
|
44
|
+
version: "1.0"
|
|
45
|
+
metadata:
|
|
46
|
+
title: "My Workbook"
|
|
47
|
+
runtime:
|
|
48
|
+
engine: mathts
|
|
49
|
+
execution: reactive
|
|
50
|
+
cells:
|
|
51
|
+
- code: |
|
|
52
|
+
const x = 42;
|
|
53
|
+
export { x };
|
|
54
|
+
id: compute
|
|
55
|
+
`;
|
|
56
|
+
|
|
57
|
+
const result = parseWorkbook(content);
|
|
58
|
+
if (result.success && result.workbook) {
|
|
59
|
+
const executor = createExecutor(result.workbook);
|
|
60
|
+
|
|
61
|
+
executor.on((event) => {
|
|
62
|
+
console.log(event.type, event.cellId);
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
await executor.runAll();
|
|
66
|
+
}
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Workbook Format (.mtsw)
|
|
70
|
+
|
|
71
|
+
```yaml
|
|
72
|
+
version: "1.0"
|
|
73
|
+
metadata:
|
|
74
|
+
title: "Matrix Analysis"
|
|
75
|
+
author: "Your Name"
|
|
76
|
+
|
|
77
|
+
runtime:
|
|
78
|
+
engine: mathts
|
|
79
|
+
execution: reactive # reactive | sequential | manual
|
|
80
|
+
|
|
81
|
+
cells:
|
|
82
|
+
- markdown: |
|
|
83
|
+
# Introduction
|
|
84
|
+
id: intro
|
|
85
|
+
|
|
86
|
+
- code: |
|
|
87
|
+
import { Matrix } from '@danielsimonjr/mathts-matrix';
|
|
88
|
+
const A = Matrix.random(3, 3);
|
|
89
|
+
export { A };
|
|
90
|
+
id: create-matrix
|
|
91
|
+
|
|
92
|
+
- code: |
|
|
93
|
+
import { A } from '#create-matrix';
|
|
94
|
+
const det = A.determinant();
|
|
95
|
+
console.log('Determinant:', det);
|
|
96
|
+
id: compute
|
|
97
|
+
depends_on: [create-matrix]
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## Cell Types
|
|
101
|
+
|
|
102
|
+
| Type | Description |
|
|
103
|
+
|------|-------------|
|
|
104
|
+
| `markdown` | Documentation with LaTeX math |
|
|
105
|
+
| `code` | TypeScript/JavaScript execution |
|
|
106
|
+
| `tensor` | Einstein notation for tensor math |
|
|
107
|
+
| `equation` | LaTeX equations with labels |
|
|
108
|
+
| `visualization` | Three.js/D3/Plotly rendering |
|
|
109
|
+
| `data` | YAML/JSON/CSV data |
|
|
110
|
+
| `test` | Assertions with timeout |
|
|
111
|
+
| `export` | Publication output |
|
|
112
|
+
|
|
113
|
+
## Execution Modes
|
|
114
|
+
|
|
115
|
+
- **reactive** - Auto-rerun when dependencies change
|
|
116
|
+
- **sequential** - Top-to-bottom execution
|
|
117
|
+
- **manual** - Explicit trigger only
|
|
118
|
+
|
|
119
|
+
## License
|
|
120
|
+
|
|
121
|
+
MIT
|
|
@@ -0,0 +1,273 @@
|
|
|
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
|
+
var WorkbookExecutor = class {
|
|
116
|
+
workbook;
|
|
117
|
+
graph;
|
|
118
|
+
outputs = /* @__PURE__ */ new Map();
|
|
119
|
+
handlers = [];
|
|
120
|
+
constructor(workbook) {
|
|
121
|
+
this.workbook = workbook;
|
|
122
|
+
this.graph = buildDependencyGraph(workbook.cells);
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Subscribe to execution events
|
|
126
|
+
*/
|
|
127
|
+
on(handler) {
|
|
128
|
+
this.handlers.push(handler);
|
|
129
|
+
return () => {
|
|
130
|
+
const index = this.handlers.indexOf(handler);
|
|
131
|
+
if (index >= 0) {
|
|
132
|
+
this.handlers.splice(index, 1);
|
|
133
|
+
}
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Emit an event to all handlers
|
|
138
|
+
*/
|
|
139
|
+
emit(event) {
|
|
140
|
+
for (const handler of this.handlers) {
|
|
141
|
+
handler(event);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Run all cells in order
|
|
146
|
+
*/
|
|
147
|
+
async runAll() {
|
|
148
|
+
for (const cellId of this.graph.executionOrder) {
|
|
149
|
+
await this.runCell(cellId);
|
|
150
|
+
}
|
|
151
|
+
this.emit({
|
|
152
|
+
type: "workbook:complete",
|
|
153
|
+
timestamp: Date.now()
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Run a specific cell
|
|
158
|
+
*/
|
|
159
|
+
async runCell(cellId) {
|
|
160
|
+
const cell = this.workbook.cells.find((c) => c.id === cellId);
|
|
161
|
+
if (!cell) {
|
|
162
|
+
throw new Error(`Cell not found: ${cellId}`);
|
|
163
|
+
}
|
|
164
|
+
this.emit({
|
|
165
|
+
type: "cell:start",
|
|
166
|
+
cellId,
|
|
167
|
+
timestamp: Date.now()
|
|
168
|
+
});
|
|
169
|
+
try {
|
|
170
|
+
const output = await this.executeCell(cell);
|
|
171
|
+
this.outputs.set(cellId, output);
|
|
172
|
+
this.emit({
|
|
173
|
+
type: "cell:success",
|
|
174
|
+
cellId,
|
|
175
|
+
output,
|
|
176
|
+
timestamp: Date.now()
|
|
177
|
+
});
|
|
178
|
+
if (this.workbook.runtime.execution === "reactive") {
|
|
179
|
+
const dependents = getDependents(this.graph, cellId);
|
|
180
|
+
for (const depId of dependents) {
|
|
181
|
+
this.emit({
|
|
182
|
+
type: "cell:stale",
|
|
183
|
+
cellId: depId,
|
|
184
|
+
timestamp: Date.now()
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
return output;
|
|
189
|
+
} catch (error) {
|
|
190
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
191
|
+
this.emit({
|
|
192
|
+
type: "cell:error",
|
|
193
|
+
cellId,
|
|
194
|
+
error: errorMessage,
|
|
195
|
+
timestamp: Date.now()
|
|
196
|
+
});
|
|
197
|
+
throw error;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Execute a single cell
|
|
202
|
+
*/
|
|
203
|
+
async executeCell(cell) {
|
|
204
|
+
switch (cell.type) {
|
|
205
|
+
case "code":
|
|
206
|
+
return this.executeCode(cell);
|
|
207
|
+
case "markdown":
|
|
208
|
+
return cell.content;
|
|
209
|
+
// Markdown is pass-through
|
|
210
|
+
case "data":
|
|
211
|
+
return this.executeData(cell);
|
|
212
|
+
default:
|
|
213
|
+
throw new Error(`Unsupported cell type: ${cell.type}`);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Execute a code cell by evaluating its content with scope from dependency outputs.
|
|
218
|
+
*
|
|
219
|
+
* Uses the Function constructor to evaluate expressions. Cell dependencies
|
|
220
|
+
* are injected as named variables in the evaluation scope, allowing cells
|
|
221
|
+
* to reference outputs of earlier cells by their id.
|
|
222
|
+
*/
|
|
223
|
+
async executeCode(cell) {
|
|
224
|
+
const scope = {};
|
|
225
|
+
if (cell.dependsOn) {
|
|
226
|
+
for (const depId of cell.dependsOn) {
|
|
227
|
+
const output = this.outputs.get(depId);
|
|
228
|
+
if (output !== void 0) {
|
|
229
|
+
scope[depId] = output;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
const scopeKeys = Object.keys(scope);
|
|
234
|
+
const scopeValues = scopeKeys.map((k) => scope[k]);
|
|
235
|
+
try {
|
|
236
|
+
const fn = new Function(...scopeKeys, `return (${cell.content});`);
|
|
237
|
+
return fn(...scopeValues);
|
|
238
|
+
} catch {
|
|
239
|
+
const fn = new Function(...scopeKeys, cell.content);
|
|
240
|
+
return fn(...scopeValues);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* Execute a data cell
|
|
245
|
+
*/
|
|
246
|
+
async executeData(cell) {
|
|
247
|
+
return cell.content;
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Get output from a previous cell
|
|
251
|
+
*/
|
|
252
|
+
getOutput(cellId) {
|
|
253
|
+
return this.outputs.get(cellId);
|
|
254
|
+
}
|
|
255
|
+
};
|
|
256
|
+
function createExecutor(workbook) {
|
|
257
|
+
return new WorkbookExecutor(workbook);
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
// src/index.ts
|
|
261
|
+
var VERSION = "0.1.0";
|
|
262
|
+
|
|
263
|
+
export {
|
|
264
|
+
parseWorkbook,
|
|
265
|
+
serializeWorkbook,
|
|
266
|
+
stripOutputs,
|
|
267
|
+
buildDependencyGraph,
|
|
268
|
+
topologicalSort,
|
|
269
|
+
getDependents,
|
|
270
|
+
WorkbookExecutor,
|
|
271
|
+
createExecutor,
|
|
272
|
+
VERSION
|
|
273
|
+
};
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
createExecutor,
|
|
4
|
+
parseWorkbook
|
|
5
|
+
} from "./chunk-64JBL36K.js";
|
|
6
|
+
|
|
7
|
+
// src/cli.ts
|
|
8
|
+
var HELP = `
|
|
9
|
+
mtsw - MathTS Workbook CLI
|
|
10
|
+
|
|
11
|
+
Usage:
|
|
12
|
+
mtsw run <file> Execute a workbook
|
|
13
|
+
mtsw run <file> -c <cell> Run specific cell
|
|
14
|
+
mtsw run <file> -v Verbose output
|
|
15
|
+
mtsw watch <file> Watch and re-run on changes
|
|
16
|
+
mtsw validate <file> Validate workbook structure
|
|
17
|
+
mtsw graph <file> Show dependency graph
|
|
18
|
+
mtsw graph <file> -f mermaid Export as Mermaid diagram
|
|
19
|
+
mtsw strip <file> Strip outputs (for git)
|
|
20
|
+
mtsw new <name> Create new workbook
|
|
21
|
+
mtsw new <name> -t <template> Use template (basic|tensor-physics|data-science)
|
|
22
|
+
mtsw export <file> -f <fmt> Export to format (html|pdf|ipynb|latex)
|
|
23
|
+
|
|
24
|
+
Options:
|
|
25
|
+
-h, --help Show this help
|
|
26
|
+
-v, --verbose Verbose output
|
|
27
|
+
-V, --version Show version
|
|
28
|
+
`;
|
|
29
|
+
async function main() {
|
|
30
|
+
const args = process.argv.slice(2);
|
|
31
|
+
if (args.length === 0 || args.includes("-h") || args.includes("--help")) {
|
|
32
|
+
console.log(HELP);
|
|
33
|
+
process.exit(0);
|
|
34
|
+
}
|
|
35
|
+
if (args.includes("-V") || args.includes("--version")) {
|
|
36
|
+
console.log("mtsw version 0.1.0");
|
|
37
|
+
process.exit(0);
|
|
38
|
+
}
|
|
39
|
+
const command = args[0];
|
|
40
|
+
switch (command) {
|
|
41
|
+
case "run":
|
|
42
|
+
await runCommand(args.slice(1));
|
|
43
|
+
break;
|
|
44
|
+
case "validate":
|
|
45
|
+
await validateCommand(args.slice(1));
|
|
46
|
+
break;
|
|
47
|
+
case "graph":
|
|
48
|
+
await graphCommand(args.slice(1));
|
|
49
|
+
break;
|
|
50
|
+
case "new":
|
|
51
|
+
await newCommand(args.slice(1));
|
|
52
|
+
break;
|
|
53
|
+
default:
|
|
54
|
+
console.error(`Unknown command: ${command}`);
|
|
55
|
+
console.log(HELP);
|
|
56
|
+
process.exit(1);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
async function runCommand(args) {
|
|
60
|
+
const file = args[0];
|
|
61
|
+
if (!file) {
|
|
62
|
+
console.error("Usage: mtsw run <file>");
|
|
63
|
+
process.exit(1);
|
|
64
|
+
}
|
|
65
|
+
console.log(`Running workbook: ${file}`);
|
|
66
|
+
const content = "";
|
|
67
|
+
const result = parseWorkbook(content);
|
|
68
|
+
if (!result.success) {
|
|
69
|
+
console.error("Parse errors:", result.errors);
|
|
70
|
+
process.exit(1);
|
|
71
|
+
}
|
|
72
|
+
if (result.workbook) {
|
|
73
|
+
const executor = createExecutor(result.workbook);
|
|
74
|
+
executor.on((event) => {
|
|
75
|
+
console.log(`[${event.type}] ${event.cellId ?? ""}`);
|
|
76
|
+
});
|
|
77
|
+
await executor.runAll();
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
async function validateCommand(args) {
|
|
81
|
+
const file = args[0];
|
|
82
|
+
if (!file) {
|
|
83
|
+
console.error("Usage: mtsw validate <file>");
|
|
84
|
+
process.exit(1);
|
|
85
|
+
}
|
|
86
|
+
console.log(`Validating: ${file}`);
|
|
87
|
+
}
|
|
88
|
+
async function graphCommand(args) {
|
|
89
|
+
const file = args[0];
|
|
90
|
+
if (!file) {
|
|
91
|
+
console.error("Usage: mtsw graph <file>");
|
|
92
|
+
process.exit(1);
|
|
93
|
+
}
|
|
94
|
+
console.log(`Dependency graph for: ${file}`);
|
|
95
|
+
}
|
|
96
|
+
async function newCommand(args) {
|
|
97
|
+
const name = args[0];
|
|
98
|
+
if (!name) {
|
|
99
|
+
console.error("Usage: mtsw new <name>");
|
|
100
|
+
process.exit(1);
|
|
101
|
+
}
|
|
102
|
+
console.log(`Creating new workbook: ${name}.mtsw`);
|
|
103
|
+
}
|
|
104
|
+
main().catch((error) => {
|
|
105
|
+
console.error("Error:", error);
|
|
106
|
+
process.exit(1);
|
|
107
|
+
});
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Workbook type definitions
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Supported cell types
|
|
6
|
+
*/
|
|
7
|
+
type CellType = 'markdown' | 'code' | 'tensor' | 'equation' | 'visualization' | 'data' | 'test' | 'export';
|
|
8
|
+
/**
|
|
9
|
+
* Execution modes
|
|
10
|
+
*/
|
|
11
|
+
type ExecutionMode = 'reactive' | 'sequential' | 'manual';
|
|
12
|
+
/**
|
|
13
|
+
* Workbook metadata
|
|
14
|
+
*/
|
|
15
|
+
interface WorkbookMetadata {
|
|
16
|
+
title?: string;
|
|
17
|
+
author?: string;
|
|
18
|
+
description?: string;
|
|
19
|
+
tags?: string[];
|
|
20
|
+
created?: string;
|
|
21
|
+
modified?: string;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Runtime configuration
|
|
25
|
+
*/
|
|
26
|
+
interface RuntimeConfig {
|
|
27
|
+
engine: 'mathts' | 'custom';
|
|
28
|
+
execution: ExecutionMode;
|
|
29
|
+
timeout?: number;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Individual cell in a workbook
|
|
33
|
+
*/
|
|
34
|
+
interface Cell {
|
|
35
|
+
id: string;
|
|
36
|
+
type: CellType;
|
|
37
|
+
content: string;
|
|
38
|
+
dependsOn?: string[];
|
|
39
|
+
output?: unknown;
|
|
40
|
+
error?: string;
|
|
41
|
+
metadata?: Record<string, unknown>;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Complete workbook structure
|
|
45
|
+
*/
|
|
46
|
+
interface Workbook {
|
|
47
|
+
version: string;
|
|
48
|
+
metadata: WorkbookMetadata;
|
|
49
|
+
runtime: RuntimeConfig;
|
|
50
|
+
cells: Cell[];
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Parse result with validation
|
|
54
|
+
*/
|
|
55
|
+
interface ParseResult {
|
|
56
|
+
success: boolean;
|
|
57
|
+
workbook?: Workbook;
|
|
58
|
+
errors?: string[];
|
|
59
|
+
warnings?: string[];
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Workbook execution events
|
|
63
|
+
*/
|
|
64
|
+
interface WorkbookEvent {
|
|
65
|
+
type: 'cell:start' | 'cell:success' | 'cell:error' | 'cell:stale' | 'workbook:complete';
|
|
66
|
+
cellId?: string;
|
|
67
|
+
output?: unknown;
|
|
68
|
+
error?: string;
|
|
69
|
+
timestamp: number;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Dependency graph node
|
|
73
|
+
*/
|
|
74
|
+
interface DependencyNode {
|
|
75
|
+
id: string;
|
|
76
|
+
dependencies: string[];
|
|
77
|
+
dependents: string[];
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Dependency graph
|
|
81
|
+
*/
|
|
82
|
+
interface DependencyGraph {
|
|
83
|
+
nodes: Map<string, DependencyNode>;
|
|
84
|
+
executionOrder: string[];
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Workbook YAML parser
|
|
89
|
+
*/
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Parse a workbook from YAML content
|
|
93
|
+
*/
|
|
94
|
+
declare function parseWorkbook(content: string): ParseResult;
|
|
95
|
+
/**
|
|
96
|
+
* Serialize a workbook to YAML
|
|
97
|
+
*/
|
|
98
|
+
declare function serializeWorkbook(_workbook: Workbook): string;
|
|
99
|
+
/**
|
|
100
|
+
* Strip outputs from workbook (for git)
|
|
101
|
+
*/
|
|
102
|
+
declare function stripOutputs(workbook: Workbook): Workbook;
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Dependency graph management
|
|
106
|
+
*/
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Build dependency graph from cells
|
|
110
|
+
*/
|
|
111
|
+
declare function buildDependencyGraph(cells: Cell[]): DependencyGraph;
|
|
112
|
+
/**
|
|
113
|
+
* Topological sort for execution order
|
|
114
|
+
*/
|
|
115
|
+
declare function topologicalSort(nodes: Map<string, DependencyNode>): string[];
|
|
116
|
+
/**
|
|
117
|
+
* Get all cells that depend on a given cell
|
|
118
|
+
*/
|
|
119
|
+
declare function getDependents(graph: DependencyGraph, cellId: string): string[];
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Workbook executor
|
|
123
|
+
*/
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Event handler type
|
|
127
|
+
*/
|
|
128
|
+
type EventHandler = (event: WorkbookEvent) => void;
|
|
129
|
+
/**
|
|
130
|
+
* Workbook executor with reactive execution support
|
|
131
|
+
*/
|
|
132
|
+
declare class WorkbookExecutor {
|
|
133
|
+
private workbook;
|
|
134
|
+
private graph;
|
|
135
|
+
private outputs;
|
|
136
|
+
private handlers;
|
|
137
|
+
constructor(workbook: Workbook);
|
|
138
|
+
/**
|
|
139
|
+
* Subscribe to execution events
|
|
140
|
+
*/
|
|
141
|
+
on(handler: EventHandler): () => void;
|
|
142
|
+
/**
|
|
143
|
+
* Emit an event to all handlers
|
|
144
|
+
*/
|
|
145
|
+
private emit;
|
|
146
|
+
/**
|
|
147
|
+
* Run all cells in order
|
|
148
|
+
*/
|
|
149
|
+
runAll(): Promise<void>;
|
|
150
|
+
/**
|
|
151
|
+
* Run a specific cell
|
|
152
|
+
*/
|
|
153
|
+
runCell(cellId: string): Promise<unknown>;
|
|
154
|
+
/**
|
|
155
|
+
* Execute a single cell
|
|
156
|
+
*/
|
|
157
|
+
private executeCell;
|
|
158
|
+
/**
|
|
159
|
+
* Execute a code cell by evaluating its content with scope from dependency outputs.
|
|
160
|
+
*
|
|
161
|
+
* Uses the Function constructor to evaluate expressions. Cell dependencies
|
|
162
|
+
* are injected as named variables in the evaluation scope, allowing cells
|
|
163
|
+
* to reference outputs of earlier cells by their id.
|
|
164
|
+
*/
|
|
165
|
+
private executeCode;
|
|
166
|
+
/**
|
|
167
|
+
* Execute a data cell
|
|
168
|
+
*/
|
|
169
|
+
private executeData;
|
|
170
|
+
/**
|
|
171
|
+
* Get output from a previous cell
|
|
172
|
+
*/
|
|
173
|
+
getOutput(cellId: string): unknown;
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Create an executor for a workbook
|
|
177
|
+
*/
|
|
178
|
+
declare function createExecutor(workbook: Workbook): WorkbookExecutor;
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* @danielsimonjr/mathts-workbook - Scientific workbook runtime
|
|
182
|
+
* @packageDocumentation
|
|
183
|
+
*/
|
|
184
|
+
|
|
185
|
+
declare const VERSION = "0.1.0";
|
|
186
|
+
|
|
187
|
+
export { type Cell, type CellType, type ExecutionMode, type ParseResult, type RuntimeConfig, VERSION, type Workbook, type WorkbookEvent, WorkbookExecutor, type WorkbookMetadata, buildDependencyGraph, createExecutor, getDependents, parseWorkbook, serializeWorkbook, stripOutputs, topologicalSort };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import {
|
|
2
|
+
VERSION,
|
|
3
|
+
WorkbookExecutor,
|
|
4
|
+
buildDependencyGraph,
|
|
5
|
+
createExecutor,
|
|
6
|
+
getDependents,
|
|
7
|
+
parseWorkbook,
|
|
8
|
+
serializeWorkbook,
|
|
9
|
+
stripOutputs,
|
|
10
|
+
topologicalSort
|
|
11
|
+
} from "./chunk-64JBL36K.js";
|
|
12
|
+
export {
|
|
13
|
+
VERSION,
|
|
14
|
+
WorkbookExecutor,
|
|
15
|
+
buildDependencyGraph,
|
|
16
|
+
createExecutor,
|
|
17
|
+
getDependents,
|
|
18
|
+
parseWorkbook,
|
|
19
|
+
serializeWorkbook,
|
|
20
|
+
stripOutputs,
|
|
21
|
+
topologicalSort
|
|
22
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@danielsimonjr/mathts-workbook",
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"description": "Scientific workbook runtime for MathTS (.mtsw format)",
|
|
5
|
+
"author": "Daniel Simon Jr.",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"main": "./dist/index.js",
|
|
9
|
+
"module": "./dist/index.js",
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"bin": {
|
|
12
|
+
"mtsw": "./dist/cli.js"
|
|
13
|
+
},
|
|
14
|
+
"exports": {
|
|
15
|
+
".": {
|
|
16
|
+
"import": "./dist/index.js",
|
|
17
|
+
"types": "./dist/index.d.ts"
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"files": [
|
|
21
|
+
"dist",
|
|
22
|
+
"README.md"
|
|
23
|
+
],
|
|
24
|
+
"scripts": {
|
|
25
|
+
"build": "tsup src/index.ts src/cli.ts --format esm --dts --clean",
|
|
26
|
+
"dev": "tsup src/index.ts src/cli.ts --format esm --dts --watch",
|
|
27
|
+
"test": "vitest run",
|
|
28
|
+
"test:watch": "vitest",
|
|
29
|
+
"test:coverage": "vitest run --coverage",
|
|
30
|
+
"typecheck": "tsc --noEmit",
|
|
31
|
+
"lint": "eslint src --ext .ts",
|
|
32
|
+
"lint:fix": "eslint src --ext .ts --fix",
|
|
33
|
+
"clean": "rm -rf dist",
|
|
34
|
+
"build:prod": "tsup src/index.ts src/cli.ts --format esm --dts --clean --minify --treeshake"
|
|
35
|
+
},
|
|
36
|
+
"dependencies": {
|
|
37
|
+
"@danielsimonjr/mathts-core": "*",
|
|
38
|
+
"yaml": "^2.3.0"
|
|
39
|
+
},
|
|
40
|
+
"devDependencies": {
|
|
41
|
+
"@types/node": "^25.5.2",
|
|
42
|
+
"tsup": "^8.0.0",
|
|
43
|
+
"typescript": "^5.3.0",
|
|
44
|
+
"vitest": "^2.0.0"
|
|
45
|
+
},
|
|
46
|
+
"publishConfig": {
|
|
47
|
+
"access": "public"
|
|
48
|
+
},
|
|
49
|
+
"repository": {
|
|
50
|
+
"type": "git",
|
|
51
|
+
"url": "https://github.com/danielsimonjr/mathts",
|
|
52
|
+
"directory": "packages/workbook"
|
|
53
|
+
},
|
|
54
|
+
"keywords": [
|
|
55
|
+
"notebook",
|
|
56
|
+
"workbook",
|
|
57
|
+
"scientific-computing",
|
|
58
|
+
"reactive",
|
|
59
|
+
"yaml"
|
|
60
|
+
]
|
|
61
|
+
}
|