@autochitect/engine 1.1.0 → 1.1.2
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 +10 -12
- package/engine.wasm +0 -0
- package/index.mjs +18 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -5,7 +5,7 @@ A 245KB WebAssembly cost estimation engine. Define cost models in a purpose-buil
|
|
|
5
5
|
## Install
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
|
-
|
|
8
|
+
npm install @autochitect/engine
|
|
9
9
|
```
|
|
10
10
|
|
|
11
11
|
## Quick start
|
|
@@ -35,7 +35,7 @@ console.log(result.results);
|
|
|
35
35
|
|
|
36
36
|
**`result.results`** — computed values for every variable.
|
|
37
37
|
|
|
38
|
-
**`result.graph`** — the full dependency DAG showing how each value was derived. Nodes have `kind` (input,
|
|
38
|
+
**`result.graph`** — the full dependency DAG showing how each value was derived. Nodes have `kind` (input, formula, map, scan) and edges show data flow. Build audit trails, trace calculations back to source inputs, or render interactive cost breakdowns.
|
|
39
39
|
|
|
40
40
|
**`result.errors`** / **`result.warnings`** — with line and column numbers.
|
|
41
41
|
|
|
@@ -48,16 +48,16 @@ The language is deliberately small. It's designed for cost estimation and financ
|
|
|
48
48
|
revenue: Input("annual_revenue")
|
|
49
49
|
headcount: Input
|
|
50
50
|
|
|
51
|
-
# Constants —
|
|
52
|
-
tax_rate
|
|
53
|
-
avg_salary
|
|
51
|
+
# Constants — use formula assignment
|
|
52
|
+
tax_rate = 0.21
|
|
53
|
+
avg_salary = 85000
|
|
54
54
|
|
|
55
|
-
# Params — tunable scenario knobs
|
|
55
|
+
# Params — tunable scenario knobs (passed via inputs)
|
|
56
56
|
growth: Param
|
|
57
57
|
|
|
58
58
|
# Formulas — define cost relationships
|
|
59
59
|
labor_cost = headcount * avg_salary
|
|
60
|
-
gross_profit = revenue * (1 -
|
|
60
|
+
gross_profit = revenue * (1 - tax_rate)
|
|
61
61
|
net_income = gross_profit * (1 - tax_rate)
|
|
62
62
|
|
|
63
63
|
# Array operations — project over time
|
|
@@ -68,7 +68,7 @@ monthly = MAP(periods, LAMBDA(p, revenue / 12 * POWER(1 + growth, p)))
|
|
|
68
68
|
cumulative = SCAN(monthly, 0, LAMBDA(acc, m, acc + m))
|
|
69
69
|
```
|
|
70
70
|
|
|
71
|
-
**Inputs** bind to external data (your JSON). **Constants** are
|
|
71
|
+
**Inputs** bind to external data (your JSON). **Constants** are defined with formula assignment (`name = value`). **Params** are tunable scenario knobs passed via the inputs object.
|
|
72
72
|
|
|
73
73
|
**MAP** transforms arrays element-wise. **SCAN** accumulates (like reduce, but returns intermediate results). **LAMBDA** defines inline functions with named parameters.
|
|
74
74
|
|
|
@@ -78,8 +78,6 @@ The engine compiles this into a directed acyclic graph, topologically sorts it,
|
|
|
78
78
|
|
|
79
79
|
```javascript
|
|
80
80
|
import { createEngine } from '@autochitect/engine';
|
|
81
|
-
import { fileURLToPath } from 'url';
|
|
82
|
-
import { dirname, join } from 'path';
|
|
83
81
|
import { createRequire } from 'module';
|
|
84
82
|
|
|
85
83
|
const require = createRequire(import.meta.url);
|
|
@@ -88,8 +86,8 @@ const engine = await createEngine(wasmPath);
|
|
|
88
86
|
|
|
89
87
|
const result = engine.estimate(`
|
|
90
88
|
headcount: Input
|
|
91
|
-
avg_salary
|
|
92
|
-
benefits_rate
|
|
89
|
+
avg_salary = 85000
|
|
90
|
+
benefits_rate = 0.3
|
|
93
91
|
|
|
94
92
|
labor_cost = headcount * avg_salary
|
|
95
93
|
benefits = labor_cost * benefits_rate
|
package/engine.wasm
CHANGED
|
Binary file
|
package/index.mjs
CHANGED
|
@@ -88,16 +88,31 @@ export async function createEngine(wasmSource) {
|
|
|
88
88
|
} else if (wasmSource instanceof Response || (typeof wasmSource === 'object' && typeof wasmSource.then === 'function')) {
|
|
89
89
|
const response = await wasmSource;
|
|
90
90
|
bytes = await response.arrayBuffer();
|
|
91
|
+
} else if (wasmSource instanceof URL) {
|
|
92
|
+
if (wasmSource.protocol === 'file:') {
|
|
93
|
+
const fs = await import('fs');
|
|
94
|
+
bytes = fs.readFileSync(wasmSource);
|
|
95
|
+
} else {
|
|
96
|
+
bytes = await (await fetch(wasmSource)).arrayBuffer();
|
|
97
|
+
}
|
|
91
98
|
} else if (typeof wasmSource === 'string') {
|
|
92
|
-
|
|
99
|
+
const isFilePath = wasmSource.startsWith('/') || wasmSource.startsWith('./') || wasmSource.startsWith('../') || wasmSource.startsWith('file://') || /^[a-zA-Z]:\\/.test(wasmSource);
|
|
100
|
+
if (isFilePath && typeof globalThis.process !== 'undefined') {
|
|
101
|
+
const fs = await import('fs');
|
|
102
|
+
if (wasmSource.startsWith('file://')) {
|
|
103
|
+
const { fileURLToPath } = await import('url');
|
|
104
|
+
bytes = fs.readFileSync(fileURLToPath(wasmSource));
|
|
105
|
+
} else {
|
|
106
|
+
bytes = fs.readFileSync(wasmSource);
|
|
107
|
+
}
|
|
108
|
+
} else if (typeof fetch !== 'undefined') {
|
|
93
109
|
bytes = await (await fetch(wasmSource)).arrayBuffer();
|
|
94
110
|
} else {
|
|
95
111
|
const fs = await import('fs');
|
|
96
|
-
const path = await import('path');
|
|
97
112
|
bytes = fs.readFileSync(wasmSource);
|
|
98
113
|
}
|
|
99
114
|
} else {
|
|
100
|
-
throw new Error('wasmSource must be a URL string, Response, or ArrayBuffer');
|
|
115
|
+
throw new Error('wasmSource must be a URL, URL string, file path, Response, or ArrayBuffer');
|
|
101
116
|
}
|
|
102
117
|
|
|
103
118
|
const { instance } = await WebAssembly.instantiate(bytes, imports);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@autochitect/engine",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.2",
|
|
4
4
|
"description": "A 245KB WebAssembly financial modeling engine. Define cost models in a purpose-built DSL, get instant estimates with full dependency tracing. No server required.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|