@rkmodules/rules 0.0.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.
Files changed (52) hide show
  1. package/dist/app/editor/calcTestFunction.d.ts +2 -0
  2. package/dist/app/editor/page.d.ts +2 -0
  3. package/dist/app/finance/entriesTestFunction.d.ts +2 -0
  4. package/dist/app/finance/page.d.ts +2 -0
  5. package/dist/app/finance/testEntries.d.ts +40 -0
  6. package/dist/app/layout.d.ts +9 -0
  7. package/dist/app/page.d.ts +2 -0
  8. package/dist/app/supalipu/page.d.ts +13 -0
  9. package/dist/index.css +81 -0
  10. package/dist/index.d.ts +6 -0
  11. package/dist/index.js +1635 -0
  12. package/dist/index.js.map +1 -0
  13. package/dist/lib/DataTree/index.d.ts +100 -0
  14. package/dist/lib/DataTree/monad.d.ts +35 -0
  15. package/dist/lib/DataTree/types.d.ts +2 -0
  16. package/dist/lib/DataTree/util.d.ts +31 -0
  17. package/dist/lib/Engine/Rule.d.ts +2 -0
  18. package/dist/lib/Engine/index.d.ts +54 -0
  19. package/dist/lib/Engine/types.d.ts +55 -0
  20. package/dist/lib/Engine/util.d.ts +7 -0
  21. package/dist/lib/Flow/Components/Control.d.ts +9 -0
  22. package/dist/lib/Flow/Components/GenericNode.d.ts +15 -0
  23. package/dist/lib/Flow/Components/Input.d.ts +8 -0
  24. package/dist/lib/Flow/Components/NodeContainer.d.ts +10 -0
  25. package/dist/lib/Flow/Components/Output.d.ts +6 -0
  26. package/dist/lib/Flow/Components/Param.d.ts +8 -0
  27. package/dist/lib/Flow/Context.d.ts +6 -0
  28. package/dist/lib/Flow/Nodes/Calc.d.ts +11 -0
  29. package/dist/lib/Flow/Nodes/Default.d.ts +4 -0
  30. package/dist/lib/Flow/Nodes/Log.d.ts +4 -0
  31. package/dist/lib/Flow/Nodes/index.d.ts +5 -0
  32. package/dist/lib/Flow/index.d.ts +21 -0
  33. package/dist/lib/Flow/types.d.ts +8 -0
  34. package/dist/lib/Primitives/List/filterList.d.ts +2 -0
  35. package/dist/lib/Primitives/List/graftTree.d.ts +2 -0
  36. package/dist/lib/Primitives/List/index.d.ts +3 -0
  37. package/dist/lib/Primitives/List/listItem.d.ts +2 -0
  38. package/dist/lib/Primitives/List/listLength.d.ts +2 -0
  39. package/dist/lib/Primitives/List/trimTree.d.ts +2 -0
  40. package/dist/lib/Primitives/Math/calc.d.ts +12 -0
  41. package/dist/lib/Primitives/Math/greaterThan.d.ts +2 -0
  42. package/dist/lib/Primitives/Math/index.d.ts +3 -0
  43. package/dist/lib/Primitives/Math/lessThan.d.ts +2 -0
  44. package/dist/lib/Primitives/Util/getValue.d.ts +5 -0
  45. package/dist/lib/Primitives/Util/index.d.ts +3 -0
  46. package/dist/lib/Primitives/Util/log.d.ts +2 -0
  47. package/dist/lib/Primitives/Util/value.d.ts +5 -0
  48. package/dist/lib/Primitives/index.d.ts +2 -0
  49. package/dist/lib/hooks/useFunction.d.ts +18 -0
  50. package/dist/lib/hooks/useVariable.d.ts +6 -0
  51. package/package.json +56 -0
  52. package/readme.md +66 -0
package/dist/index.js ADDED
@@ -0,0 +1,1635 @@
1
+ 'use strict';
2
+
3
+ var mathjs = require('mathjs');
4
+ var react = require('@xyflow/react');
5
+ var zustand = require('zustand');
6
+ var middleware = require('zustand/middleware');
7
+ var useInner = require('@rkmodules/use-inner');
8
+ var React = require('react');
9
+ var katex = require('katex');
10
+ var classNames = require('classnames');
11
+ require('katex/dist/katex.min.css');
12
+ require('@xyflow/react/dist/style.css');
13
+
14
+ /******************************************************************************
15
+ Copyright (c) Microsoft Corporation.
16
+
17
+ Permission to use, copy, modify, and/or distribute this software for any
18
+ purpose with or without fee is hereby granted.
19
+
20
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
21
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
22
+ AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
23
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
24
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
25
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
26
+ PERFORMANCE OF THIS SOFTWARE.
27
+ ***************************************************************************** */
28
+ /* global Reflect, Promise, SuppressedError, Symbol, Iterator */
29
+
30
+
31
+ var __assign = function() {
32
+ __assign = Object.assign || function __assign(t) {
33
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
34
+ s = arguments[i];
35
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
36
+ }
37
+ return t;
38
+ };
39
+ return __assign.apply(this, arguments);
40
+ };
41
+
42
+ function __rest(s, e) {
43
+ var t = {};
44
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
45
+ t[p] = s[p];
46
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
47
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
48
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
49
+ t[p[i]] = s[p[i]];
50
+ }
51
+ return t;
52
+ }
53
+
54
+ function __awaiter(thisArg, _arguments, P, generator) {
55
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
56
+ return new (P || (P = Promise))(function (resolve, reject) {
57
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
58
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
59
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
60
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
61
+ });
62
+ }
63
+
64
+ function __generator(thisArg, body) {
65
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
66
+ return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
67
+ function verb(n) { return function (v) { return step([n, v]); }; }
68
+ function step(op) {
69
+ if (f) throw new TypeError("Generator is already executing.");
70
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
71
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
72
+ if (y = 0, t) op = [op[0] & 2, t.value];
73
+ switch (op[0]) {
74
+ case 0: case 1: t = op; break;
75
+ case 4: _.label++; return { value: op[1], done: false };
76
+ case 5: _.label++; y = op[1]; op = [0]; continue;
77
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
78
+ default:
79
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
80
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
81
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
82
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
83
+ if (t[2]) _.ops.pop();
84
+ _.trys.pop(); continue;
85
+ }
86
+ op = body.call(thisArg, _);
87
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
88
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
89
+ }
90
+ }
91
+
92
+ function __values(o) {
93
+ var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
94
+ if (m) return m.call(o);
95
+ if (o && typeof o.length === "number") return {
96
+ next: function () {
97
+ if (o && i >= o.length) o = void 0;
98
+ return { value: o && o[i++], done: !o };
99
+ }
100
+ };
101
+ throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
102
+ }
103
+
104
+ function __read(o, n) {
105
+ var m = typeof Symbol === "function" && o[Symbol.iterator];
106
+ if (!m) return o;
107
+ var i = m.call(o), r, ar = [], e;
108
+ try {
109
+ while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
110
+ }
111
+ catch (error) { e = { error: error }; }
112
+ finally {
113
+ try {
114
+ if (r && !r.done && (m = i["return"])) m.call(i);
115
+ }
116
+ finally { if (e) throw e.error; }
117
+ }
118
+ return ar;
119
+ }
120
+
121
+ function __spreadArray(to, from, pack) {
122
+ if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
123
+ if (ar || !(i in from)) {
124
+ if (!ar) ar = Array.prototype.slice.call(from, 0, i);
125
+ ar[i] = from[i];
126
+ }
127
+ }
128
+ return to.concat(ar || Array.prototype.slice.call(from));
129
+ }
130
+
131
+ typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
132
+ var e = new Error(message);
133
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
134
+ };
135
+
136
+ /**
137
+ * Creates a new branch for each item in the existing tree branches
138
+ * @param tree
139
+ * @returns
140
+ */
141
+ function graftTree$1(tree) {
142
+ return Object.fromEntries(Object.entries(tree).reduce(function (entries, _a) {
143
+ var _b = __read(_a, 2), path = _b[0], values = _b[1];
144
+ entries.push.apply(entries, __spreadArray([], __read(values.map(function (value, index) {
145
+ return [path + ";" + index, [value]];
146
+ })), false));
147
+ return entries;
148
+ }, []));
149
+ }
150
+ /**
151
+ * Reduce the complexity of a tree by merging the outermost branches.
152
+ * @param tree
153
+ */
154
+ function trimTree$1(tree, depth) {
155
+ var _a;
156
+ if (depth === void 0) { depth = 1; }
157
+ if (depth <= 0)
158
+ return tree;
159
+ var result = {};
160
+ for (var path in tree) {
161
+ var parts = path.split(";");
162
+ // leave at least a path length of 1
163
+ var end = depth >= parts.length ? 1 : -depth;
164
+ var newPath = parts.slice(0, end).join(";");
165
+ if (!result[newPath]) {
166
+ result[newPath] = [];
167
+ }
168
+ // flatten onto new branch
169
+ (_a = result[newPath]).push.apply(_a, __spreadArray([], __read(tree[path]), false));
170
+ }
171
+ return result;
172
+ }
173
+ /**
174
+ * checks if the given structure is a data tree
175
+ */
176
+ function isTree(value) {
177
+ return (typeof value === "object" &&
178
+ value !== null &&
179
+ !Array.isArray(value) &&
180
+ Object.keys(value).length > 0 &&
181
+ Object.values(value).every(function (v) { return Array.isArray(v); }));
182
+ }
183
+ /**
184
+ * turns a value or array of values into a tree
185
+ */
186
+ function broadCast(value) {
187
+ if (Array.isArray(value)) {
188
+ return { "0": value };
189
+ }
190
+ if (isTree(value)) {
191
+ return value;
192
+ }
193
+ return { "0": [value] };
194
+ }
195
+ function getBranch(tree, path) {
196
+ return tree[path];
197
+ }
198
+ /**
199
+ * maps a tree, the tree branches are flatmapped, so if an array is returned for each item in the list, a flat list is returned
200
+ * @param tree
201
+ * @param fn
202
+ * @returns
203
+ */
204
+ function mapTree(tree, fn) {
205
+ var result = {};
206
+ var _loop_2 = function (path) {
207
+ var mapResult = tree[path].flatMap(function (v, i) { return fn(v, path, i); });
208
+ if (mapResult.length) {
209
+ result[path] = mapResult;
210
+ }
211
+ };
212
+ for (var path in tree) {
213
+ _loop_2(path);
214
+ }
215
+ return result;
216
+ }
217
+ function mapTreeBranch(tree, fn) {
218
+ var result = {};
219
+ for (var path in tree) {
220
+ var newBranch = fn(tree[path], path);
221
+ if (newBranch) {
222
+ result[path] = newBranch;
223
+ }
224
+ }
225
+ return result;
226
+ }
227
+ /**
228
+ * n-ary operation on a tree, branch by branch
229
+ * - branches are matched by index,
230
+ * - last branches are repeated when the branch count differs
231
+ * - branch names from the longest or first tree are used
232
+ * - if a corresponding index does not exist in the branch, its item argument is undefined
233
+ * - the callback function is called with (items, paths)
234
+ * @param trees
235
+ * @param fn
236
+ * @returns
237
+ */
238
+ function nAryOnTreeBranch(trees, fn) {
239
+ var result = {};
240
+ var allKeys = trees.map(function (tree) { return Object.keys(tree); });
241
+ var maxBranches = Math.max.apply(Math, __spreadArray([], __read(allKeys.map(function (keys) { return keys.length; })), false));
242
+ var _loop_3 = function (i) {
243
+ var paths = allKeys.map(function (keys) { return keys[Math.min(i, keys.length - 1)]; });
244
+ var branches = trees.map(function (tree) { return tree[paths[trees.indexOf(tree)]] || []; });
245
+ // get all the paths of which the trees are the longest, use the first
246
+ var maxPaths = paths.filter(function (_, i) { return allKeys[i].length === maxBranches; });
247
+ var path = maxPaths[0];
248
+ var newBranch = fn(branches, paths);
249
+ if (newBranch === null || newBranch === void 0 ? void 0 : newBranch.length) {
250
+ result[path] = newBranch;
251
+ }
252
+ };
253
+ for (var i = 0; i < maxBranches; i++) {
254
+ _loop_3(i);
255
+ }
256
+ return result;
257
+ }
258
+ /**
259
+ * n-ary operation on a tree, branch by branch
260
+ * - branches are matched by index,
261
+ * - last branches are repeated when the branch count differs
262
+ * - branch names from the longest or first tree are used
263
+ * - if a corresponding index does not exist in the branch, its item argument is undefined
264
+ * - the callback function is called with (items, paths, index)
265
+ * @param trees
266
+ * @param fn
267
+ * @returns
268
+ */
269
+ function nAryOnTree(trees, fn) {
270
+ return nAryOnTreeBranch(trees, function (branches, paths) {
271
+ var maxLength = Math.max.apply(Math, __spreadArray([], __read(branches.map(function (b) { return b.length; })), false));
272
+ if (maxLength === 0)
273
+ return; // Skip empty branches
274
+ return Array.from({ length: maxLength }, function (_, i) {
275
+ var items = branches.map(function (b) { return b[i]; });
276
+ return fn(items, paths, i);
277
+ });
278
+ });
279
+ }
280
+ /**
281
+ * binary operation on a tree, branch by branch
282
+ * - branches are matched by index,
283
+ * - last branches are repeated when the branch count differs
284
+ * - branch names from the longest or first tree are used
285
+ * - if a corresponding index does not exist in the branch, its item argument is undefined
286
+ * - the callback function is called with (itemA, itemB, pathA, pathB)
287
+ * @param treeA
288
+ * @param treeB
289
+ * @param fn
290
+ * @returns
291
+ */
292
+ function binaryOnTreeBranch(treeA, treeB, fn) {
293
+ return nAryOnTreeBranch([treeA, treeB], function (_a, _b) {
294
+ var _c = __read(_a, 2), branchA = _c[0], branchB = _c[1];
295
+ var _d = __read(_b, 2), pathA = _d[0], pathB = _d[1];
296
+ return fn(branchA, branchB, pathA, pathB);
297
+ });
298
+ }
299
+ /**
300
+ * binary operation on a tree, branch by branch
301
+ * - branches are matched by index,
302
+ * - last branches are repeated when the branch count differs
303
+ * - branch names from the longest or first tree are used
304
+ * - if a corresponding index does not exist in the branch, its item argument is undefined
305
+ * - the callback function is called with (itemA, itemB, pathA, pathB, index)
306
+ * @param treeA
307
+ * @param treeB
308
+ * @param fn
309
+ * @returns
310
+ */
311
+ function binaryOnTree(treeA, treeB, fn) {
312
+ return nAryOnTree([treeA, treeB], function (_a, _b, index) {
313
+ var _c = __read(_a, 2), itemA = _c[0], itemB = _c[1];
314
+ var _d = __read(_b, 2), pathA = _d[0], pathB = _d[1];
315
+ return fn(itemA, itemB, pathA, pathB, index);
316
+ });
317
+ }
318
+ function sameShape(a, b) {
319
+ var sa = Object.keys(a).sort().join("|");
320
+ var sb = Object.keys(b).sort().join("|");
321
+ return sa === sb;
322
+ }
323
+ /**
324
+ * flattens the whole tree into an array
325
+ */
326
+ function toArray(a) {
327
+ return Object.values(a).flat();
328
+ }
329
+
330
+ // utilities
331
+ /**
332
+ * merges two trees by concatenating the branches with the same path
333
+ * @param a
334
+ * @param b
335
+ * @returns
336
+ */
337
+ function mergeTrees(a, b) {
338
+ var e_1, _a;
339
+ var _b;
340
+ var out = __assign({}, a);
341
+ try {
342
+ for (var _c = __values(Object.entries(b)), _d = _c.next(); !_d.done; _d = _c.next()) {
343
+ var _e = __read(_d.value, 2), k = _e[0], arr = _e[1];
344
+ out[k] = ((_b = out[k]) !== null && _b !== void 0 ? _b : []).concat(arr);
345
+ }
346
+ }
347
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
348
+ finally {
349
+ try {
350
+ if (_d && !_d.done && (_a = _c.return)) _a.call(_c);
351
+ }
352
+ finally { if (e_1) throw e_1.error; }
353
+ }
354
+ return out;
355
+ }
356
+
357
+ function isReference(value) {
358
+ return (typeof value === "string" &&
359
+ value.startsWith("<") &&
360
+ value.endsWith(">"));
361
+ }
362
+ function parseReference(ref) {
363
+ return ref.slice(1, -1);
364
+ }
365
+ function uid() {
366
+ return Math.random().toString(36).substring(2, 15);
367
+ }
368
+ function getValue$1(obj, path) {
369
+ if (!(obj && path)) {
370
+ return;
371
+ }
372
+ var parts = path.split(".");
373
+ var value = obj[parts.shift() || ""];
374
+ while (parts.length && value) {
375
+ value = value[parts.shift() || ""];
376
+ }
377
+ return value;
378
+ }
379
+ function interpolateValue(value, scope) {
380
+ if (Array.isArray(value)) {
381
+ if (value.length && value.every(isTree)) {
382
+ // combine the trees into one
383
+ var tree = value.reduce(function (acc, t) { return mergeTrees(acc, t); });
384
+ return mapTree(tree, function (v) { return interpolateValue(v, scope); });
385
+ }
386
+ return broadCast(value);
387
+ }
388
+ if (isTree(value)) {
389
+ return mapTree(value, function (v) { return interpolateValue(v, scope); });
390
+ }
391
+ if (typeof value === "object" && value !== null) {
392
+ if (Object.keys(value).length === 0) {
393
+ return {};
394
+ }
395
+ // interpolate to a record of trees:
396
+ var interpolated = interpolate(value, scope);
397
+ // then, for each value, combine the branches with the same index
398
+ var keys_1 = Object.keys(interpolated);
399
+ return nAryOnTree(Object.values(interpolated), function (items) {
400
+ return Object.fromEntries(items.map(function (item, keyIndex) {
401
+ return [keys_1[keyIndex], item];
402
+ }));
403
+ });
404
+ }
405
+ if (!isReference(value)) {
406
+ return value;
407
+ }
408
+ var parts = parseReference(value).split(".");
409
+ var mappedValue = getValue$1(scope, parts.slice(0, 2).join("."));
410
+ if (parts.length > 2) {
411
+ // deep interpolate
412
+ mappedValue = mapTree(mappedValue, function (v) {
413
+ return getValue$1(v, parts.slice(2).join("."));
414
+ });
415
+ }
416
+ return mappedValue;
417
+ }
418
+ function interpolate(inputs, scope) {
419
+ return Object.fromEntries(Object.entries(inputs).map(function (_a) {
420
+ var _b = __read(_a, 2), key = _b[0], value = _b[1];
421
+ var mappedValue = interpolateValue(value, scope);
422
+ return [key, broadCast(mappedValue)];
423
+ }));
424
+ }
425
+
426
+ /**
427
+ * TODO: need rank polymorhism on the tree item sizes
428
+ */
429
+ var getValue = {
430
+ name: "getValue",
431
+ label: "Get Value",
432
+ inputs: {
433
+ tree: "any",
434
+ path: "string",
435
+ },
436
+ outputs: {
437
+ tree: "any",
438
+ },
439
+ // TODO: may want to do something with other values of path
440
+ impl: function (inputs, params) { return __awaiter(void 0, void 0, void 0, function () {
441
+ var paths, tree;
442
+ return __generator(this, function (_a) {
443
+ paths = toArray(inputs.path || {});
444
+ tree = mapTree(inputs.tree, function (value) {
445
+ // get the property from the object
446
+ return getValue$1(value, paths[0]);
447
+ });
448
+ return [2 /*return*/, { tree: tree }];
449
+ });
450
+ }); },
451
+ };
452
+
453
+ var log = {
454
+ name: "log",
455
+ label: "Log",
456
+ description: "Logs the input data to the console",
457
+ nodeType: "Log",
458
+ inputs: {
459
+ data: "any",
460
+ },
461
+ outputs: {
462
+ data: "any", // Return the data for potential further use
463
+ },
464
+ impl: function (input) { return __awaiter(void 0, void 0, void 0, function () {
465
+ return __generator(this, function (_a) {
466
+ console.table(input.data);
467
+ return [2 /*return*/, {
468
+ data: input.data, // Return the data for potential further use
469
+ }];
470
+ });
471
+ }); },
472
+ };
473
+
474
+ /**
475
+ * value primitive function
476
+ */
477
+ var value = {
478
+ name: "value",
479
+ label: "Value",
480
+ inputs: {},
481
+ params: {
482
+ value: "string",
483
+ type: {
484
+ type: "string",
485
+ options: ["number", "boolean", "string"],
486
+ },
487
+ },
488
+ outputs: {
489
+ value: "any",
490
+ },
491
+ impl: function (inputs, params) { return __awaiter(void 0, void 0, void 0, function () {
492
+ var value;
493
+ return __generator(this, function (_a) {
494
+ value = params.value;
495
+ switch (params.type) {
496
+ case "number":
497
+ return [2 /*return*/, { value: Number(value) }];
498
+ case "boolean":
499
+ return [2 /*return*/, { value: Boolean(value) }];
500
+ case "string":
501
+ return [2 /*return*/, { value: String(value) }];
502
+ default:
503
+ // return as is
504
+ return [2 /*return*/, { value: value }];
505
+ }
506
+ });
507
+ }); },
508
+ };
509
+
510
+ var _a$2;
511
+ var primitives$3 = (_a$2 = {},
512
+ _a$2[getValue.name] = getValue,
513
+ _a$2[log.name] = log,
514
+ _a$2[value.name] = value,
515
+ _a$2);
516
+
517
+ var math$1 = mathjs.create(mathjs.all, {});
518
+ function evaluate(expression, scope) {
519
+ // console.log("evaluating", expression, "in", scope);
520
+ var result;
521
+ try {
522
+ result = math$1.evaluate(expression, scope);
523
+ if (typeof result.toNumber === "function") {
524
+ result = result.toNumber();
525
+ }
526
+ }
527
+ catch (e) {
528
+ console.log("Calc:", e);
529
+ console.log("Calc:", { expression: expression, scope: scope });
530
+ // todo: communicate errors
531
+ }
532
+ // console.log("result", result);
533
+ return result;
534
+ }
535
+ /**
536
+ * TODO: need rank polymorhism on the tree item sizes
537
+ */
538
+ var calc = {
539
+ name: "calc",
540
+ label: "Calc",
541
+ nodeType: "Calc",
542
+ inputs: {},
543
+ params: {
544
+ expression: "string",
545
+ },
546
+ outputs: {
547
+ result: "number",
548
+ },
549
+ impl: function (inputs, params) { return __awaiter(void 0, void 0, void 0, function () {
550
+ var expression, inputEntries, result;
551
+ return __generator(this, function (_a) {
552
+ expression = params.expression;
553
+ if (!expression)
554
+ return [2 /*return*/, {}];
555
+ inputEntries = Object.entries(inputs);
556
+ if (!inputEntries.every(function (_a, i, a) {
557
+ var _b = __read(_a, 2); _b[0]; var v = _b[1];
558
+ return sameShape(v, a[0][1]);
559
+ })) {
560
+ throw new Error("All inputs must have the same shape");
561
+ }
562
+ // if no inputs, just return the result of the expression
563
+ if (inputEntries.length === 0) {
564
+ return [2 /*return*/, { result: broadCast(evaluate(expression, {})) }];
565
+ }
566
+ result = mapTree(inputEntries[0][1], function (_, p, i) {
567
+ // create a scope for each input
568
+ var vars = {};
569
+ inputEntries.forEach(function (_a) {
570
+ var _b = __read(_a, 2), key = _b[0], value = _b[1];
571
+ vars[key] = value[p][i];
572
+ });
573
+ return evaluate(expression, vars);
574
+ });
575
+ // await new Promise((resolve) => setTimeout(resolve, 5000)); // yield to event loop
576
+ return [2 /*return*/, { result: result }];
577
+ });
578
+ }); },
579
+ };
580
+ var BUILT_INS = new Set([
581
+ // constants
582
+ "pi",
583
+ "e",
584
+ "tau",
585
+ "phi",
586
+ "Infinity",
587
+ "NaN",
588
+ "i",
589
+ "true",
590
+ "false",
591
+ "null",
592
+ // common built-in functions (skip as variables when used as callees)
593
+ "sin",
594
+ "cos",
595
+ "tan",
596
+ "asin",
597
+ "acos",
598
+ "atan",
599
+ "atan2",
600
+ "sinh",
601
+ "cosh",
602
+ "tanh",
603
+ "log",
604
+ "log10",
605
+ "ln",
606
+ "exp",
607
+ "sqrt",
608
+ "abs",
609
+ "min",
610
+ "max",
611
+ "round",
612
+ "floor",
613
+ "ceil",
614
+ "sum",
615
+ "mean",
616
+ "median",
617
+ "mode",
618
+ "std",
619
+ "var",
620
+ "pow",
621
+ "mod",
622
+ "gcd",
623
+ "lcm",
624
+ "derivative",
625
+ "integral",
626
+ "simplify",
627
+ "im",
628
+ "re",
629
+ ]);
630
+ /**
631
+ * Return a sorted list of unbound symbol names in a MathJS expression.
632
+ * @param expr The expression string, e.g. "x + y"
633
+ * @param scope Names already defined/known (e.g. from your evaluation scope)
634
+ * @param extraBound Extra names to treat as bound (e.g. UI reserved words)
635
+ */
636
+ function getUnboundSymbols(expr, scope, extraBound) {
637
+ if (scope === void 0) { scope = {}; }
638
+ if (extraBound === void 0) { extraBound = []; }
639
+ var ast;
640
+ try {
641
+ ast = math$1.parse(expr);
642
+ }
643
+ catch (_a) {
644
+ return [];
645
+ }
646
+ var bound = new Set(__spreadArray(__spreadArray([], __read(Object.keys(scope)), false), __read(extraBound), false));
647
+ var free = new Set();
648
+ var isFunctionCallee = function (node, parent) {
649
+ return (parent === null || parent === void 0 ? void 0 : parent.type) === "FunctionNode" && parent.fn === node;
650
+ };
651
+ ast.traverse(function (node, _path, parent) {
652
+ if (node.type !== "SymbolNode")
653
+ return;
654
+ var name = node.name;
655
+ // Skip if symbol is the function name in a call, e.g. sin in sin(x)
656
+ if (isFunctionCallee(node, parent))
657
+ return;
658
+ // Skip mathjs built-ins and anything caller said is already bound
659
+ if (BUILT_INS.has(name) || bound.has(name))
660
+ return;
661
+ free.add(name);
662
+ });
663
+ // If you want to also exclude left-hand sides of assignments within the expr:
664
+ // (Uncommon in "fill in variables" UIs, but easy to guard against.)
665
+ ast.traverse(function (node) {
666
+ if (node.type === "AssignmentNode") {
667
+ var target = node.object;
668
+ if ((target === null || target === void 0 ? void 0 : target.type) === "SymbolNode") {
669
+ free.delete(target.name);
670
+ }
671
+ }
672
+ });
673
+ return Array.from(free).sort();
674
+ }
675
+
676
+ var greaterThan = {
677
+ name: "greaterThan",
678
+ label: "Greater Than",
679
+ description: "Compare on greater than or greater than or equal to",
680
+ inputs: {
681
+ a: "number",
682
+ b: "number",
683
+ },
684
+ outputs: {
685
+ gt: "boolean",
686
+ gte: "boolean",
687
+ },
688
+ impl: function (inputs) { return __awaiter(void 0, void 0, void 0, function () {
689
+ return __generator(this, function (_a) {
690
+ return [2 /*return*/, {
691
+ gt: binaryOnTree(inputs.a, inputs.b, function (itemA, itemB) {
692
+ return itemA > itemB;
693
+ }),
694
+ gte: binaryOnTree(inputs.a, inputs.b, function (itemA, itemB) {
695
+ return itemA >= itemB;
696
+ }),
697
+ }];
698
+ });
699
+ }); },
700
+ };
701
+
702
+ var lessThan = {
703
+ name: "lessThan",
704
+ label: "Less Than",
705
+ description: "Compare on less than or less than or equal to",
706
+ inputs: {
707
+ a: "number",
708
+ b: "number",
709
+ },
710
+ outputs: {
711
+ lt: "boolean",
712
+ lte: "boolean",
713
+ },
714
+ impl: function (inputs) { return __awaiter(void 0, void 0, void 0, function () {
715
+ return __generator(this, function (_a) {
716
+ return [2 /*return*/, {
717
+ lt: binaryOnTree(inputs.a, inputs.b, function (itemA, itemB) {
718
+ return itemA < itemB;
719
+ }),
720
+ lte: binaryOnTree(inputs.a, inputs.b, function (itemA, itemB) {
721
+ return itemA <= itemB;
722
+ }),
723
+ }];
724
+ });
725
+ }); },
726
+ };
727
+
728
+ var _a$1;
729
+ var primitives$2 = (_a$1 = {},
730
+ _a$1[calc.name] = calc,
731
+ _a$1[lessThan.name] = lessThan,
732
+ _a$1[greaterThan.name] = greaterThan,
733
+ _a$1);
734
+
735
+ var filterList = {
736
+ name: "filterList",
737
+ label: "Filter List",
738
+ description: "filters the list by a boolean value",
739
+ inputs: {
740
+ list: "any",
741
+ keep: "boolean",
742
+ },
743
+ outputs: {
744
+ list: "any",
745
+ },
746
+ impl: function (inputs) { return __awaiter(void 0, void 0, void 0, function () {
747
+ return __generator(this, function (_a) {
748
+ return [2 /*return*/, {
749
+ list: binaryOnTreeBranch(inputs.list, inputs.keep, function (branchA, branchB) {
750
+ return branchA.filter(function (item, index) {
751
+ return (branchB[Math.min(index, branchB.length - 1)] ===
752
+ true);
753
+ });
754
+ }),
755
+ }];
756
+ });
757
+ }); },
758
+ };
759
+
760
+ var graftTree = {
761
+ name: "graftTree",
762
+ label: "Graft Tree",
763
+ description: "Creates a new branch for each item in the existing tree branches",
764
+ inputs: {
765
+ tree: "any",
766
+ },
767
+ outputs: {
768
+ tree: "any", // Return the grafted nodes
769
+ },
770
+ impl: function (inputs) { return __awaiter(void 0, void 0, void 0, function () {
771
+ return __generator(this, function (_a) {
772
+ return [2 /*return*/, {
773
+ tree: graftTree$1(inputs.tree),
774
+ }];
775
+ });
776
+ }); },
777
+ };
778
+
779
+ var listItem = {
780
+ name: "listItem",
781
+ label: "List Item",
782
+ description: "Retrieve the items from the list at the specified indices",
783
+ inputs: {
784
+ list: "any",
785
+ index: "number",
786
+ },
787
+ outputs: {
788
+ item: "any",
789
+ },
790
+ impl: function (inputs) { return __awaiter(void 0, void 0, void 0, function () {
791
+ return __generator(this, function (_a) {
792
+ return [2 /*return*/, {
793
+ item: mapTreeBranch(inputs.list, function (branch, path) {
794
+ var indices = getBranch(inputs.index, path);
795
+ if (indices) {
796
+ return indices.map(function (i) { return branch[i]; });
797
+ }
798
+ }),
799
+ }];
800
+ });
801
+ }); },
802
+ };
803
+
804
+ var listLength = {
805
+ name: "listLength",
806
+ label: "List Length",
807
+ description: "Get the length of a list",
808
+ inputs: {
809
+ list: "any",
810
+ },
811
+ outputs: {
812
+ length: "number",
813
+ },
814
+ impl: function (inputs) { return __awaiter(void 0, void 0, void 0, function () {
815
+ return __generator(this, function (_a) {
816
+ return [2 /*return*/, {
817
+ length: mapTreeBranch(inputs.list, function (branch) {
818
+ return [branch.length];
819
+ }),
820
+ }];
821
+ });
822
+ }); },
823
+ };
824
+
825
+ var trimTree = {
826
+ name: "trimTree",
827
+ label: "Trim Tree",
828
+ description: "Reduce the complexity of a tree by merging the outermost branches.",
829
+ inputs: {
830
+ tree: "any",
831
+ },
832
+ params: {
833
+ depth: "number", // Optional depth to trim the tree
834
+ },
835
+ outputs: {
836
+ tree: "any", // Return the trimed nodes
837
+ },
838
+ impl: function (inputs, params) { return __awaiter(void 0, void 0, void 0, function () {
839
+ var depth;
840
+ var _a;
841
+ return __generator(this, function (_b) {
842
+ depth = (_a = params.depth) !== null && _a !== void 0 ? _a : 1;
843
+ return [2 /*return*/, {
844
+ tree: trimTree$1(inputs.tree, depth),
845
+ }];
846
+ });
847
+ }); },
848
+ };
849
+
850
+ var _a;
851
+ var primitives$1 = (_a = {},
852
+ _a[graftTree.name] = graftTree,
853
+ _a[trimTree.name] = trimTree,
854
+ _a[listItem.name] = listItem,
855
+ _a[listLength.name] = listLength,
856
+ _a[filterList.name] = filterList,
857
+ _a);
858
+
859
+ var primitives = __assign(__assign(__assign({}, primitives$3), primitives$2), primitives$1);
860
+
861
+ function isPrimitive(node) {
862
+ return node.impl !== undefined;
863
+ }
864
+
865
+ function normalizeVarDef(varDef) {
866
+ if (typeof varDef === "string") {
867
+ return {
868
+ type: varDef,
869
+ };
870
+ }
871
+ return varDef;
872
+ }
873
+ function getReferences(inputs) {
874
+ var references = [];
875
+ Object.entries(inputs).forEach(function (_a) {
876
+ var _b = __read(_a, 2), name = _b[0], value = _b[1];
877
+ var values = Array.isArray(value) ? value : [value];
878
+ values.forEach(function (value) {
879
+ if (!isReference(value)) {
880
+ return;
881
+ }
882
+ var path = parseReference(value);
883
+ var parts = path.split(".");
884
+ references.push({
885
+ name: name,
886
+ path: path,
887
+ parts: parts,
888
+ refNode: parts[0],
889
+ refField: parts.slice(1).join("."),
890
+ });
891
+ });
892
+ });
893
+ return references;
894
+ }
895
+ function applyNodeDelete(fn, nodeIds) {
896
+ var newFn = __assign(__assign({}, fn), { body: __assign({}, fn.body) });
897
+ nodeIds.forEach(function (id) {
898
+ delete newFn.body[id];
899
+ });
900
+ // remove any references to the deleted nodes
901
+ Object.entries(newFn.body).forEach(function (_a) {
902
+ var _b = __read(_a, 2), id = _b[0], node = _b[1];
903
+ Object.entries(node.inputs || {}).forEach(function (_a) {
904
+ var _b;
905
+ var _c = __read(_a, 2), name = _c[0], value = _c[1];
906
+ if (isReference(value)) {
907
+ var path = parseReference(value);
908
+ var parts = path.split(".");
909
+ if (nodeIds.includes(parts[0])) {
910
+ (_b = newFn.body[id].inputs) === null || _b === void 0 ? true : delete _b[name];
911
+ }
912
+ }
913
+ });
914
+ });
915
+ return newFn;
916
+ }
917
+ function applyEdgeDelete(fn, fromNode, toNode, fromField, toField) {
918
+ var newFn = __assign(__assign({}, fn), { body: __assign({}, fn.body) });
919
+ var from = newFn.body[fromNode];
920
+ var to = newFn.body[toNode];
921
+ if (!from || !to) {
922
+ console.warn("Invalid nodes for edge deletion");
923
+ return newFn;
924
+ }
925
+ if (to.inputs && to.inputs[toField] === "<".concat(fromNode, ".").concat(fromField, ">")) {
926
+ delete to.inputs[toField];
927
+ }
928
+ else {
929
+ console.warn("No matching edge found to delete");
930
+ }
931
+ return newFn;
932
+ }
933
+ function applyNodeAdd(fn, nodeName) {
934
+ var newFn = __assign(__assign({}, fn), { body: __assign({}, fn.body) });
935
+ var id = uid();
936
+ while (newFn.body[id]) {
937
+ id = uid();
938
+ }
939
+ newFn.body[id] = {
940
+ name: nodeName,
941
+ inputs: {},
942
+ params: {},
943
+ };
944
+ return topSort(newFn);
945
+ }
946
+ function applyNodeConnect(fn, fromNode, toNode, fromField, toField) {
947
+ var newFn = __assign(__assign({}, fn), { body: __assign({}, fn.body) });
948
+ var from = newFn.body[fromNode];
949
+ var to = newFn.body[toNode];
950
+ if (!from || !to) {
951
+ console.warn("Invalid nodes for connection");
952
+ return newFn;
953
+ }
954
+ if (!to.inputs) {
955
+ to.inputs = {};
956
+ }
957
+ // add the reference
958
+ to.inputs[toField] = "<".concat(fromNode, ".").concat(fromField, ">");
959
+ return topSort(newFn);
960
+ }
961
+ function topSort(fn) {
962
+ var ordered = [];
963
+ var visiting = new Set();
964
+ var done = new Set();
965
+ var visit = function (id) {
966
+ // if already done, return
967
+ if (done.has(id))
968
+ return;
969
+ // if being visited, we have a loop
970
+ if (visiting.has(id)) {
971
+ throw new Error("Circular dependency detected: ".concat(id));
972
+ }
973
+ // mark as visiting
974
+ visiting.add(id);
975
+ var fnCall = fn.body[id];
976
+ if (!fnCall) {
977
+ console.warn("Function ".concat(id, " not found in body"), fn);
978
+ }
979
+ // check the inputs and visit them
980
+ Object.values(fnCall.inputs || {}).forEach(function (input) {
981
+ if (isReference(input)) {
982
+ var _a = __read(parseReference(input).split("."), 1), id_1 = _a[0];
983
+ // visit inputs
984
+ if (id_1 !== "inputs") {
985
+ visit(id_1);
986
+ }
987
+ }
988
+ });
989
+ // push to end of the list
990
+ ordered.push(id);
991
+ // finish visting
992
+ visiting.delete(id);
993
+ // mark as done
994
+ done.add(id);
995
+ };
996
+ Object.keys(fn.body).forEach(visit);
997
+ console.log("sorted", ordered);
998
+ var orderedBody = Object.fromEntries(ordered.map(function (id) { return [id, fn.body[id]]; }));
999
+ return __assign(__assign({}, fn), { body: orderedBody });
1000
+ }
1001
+ var Engine = /** @class */ (function () {
1002
+ function Engine(morePrimitives) {
1003
+ if (morePrimitives === void 0) { morePrimitives = {}; }
1004
+ this.listeners = {};
1005
+ this.cache = {};
1006
+ this.cacheMiss = Symbol("cacheMiss");
1007
+ this.fnIndex = __assign(__assign({}, primitives), morePrimitives);
1008
+ }
1009
+ Engine.prototype.checkCache = function (fnName, inputs) {
1010
+ if (!this.cache[fnName]) {
1011
+ return this.cacheMiss;
1012
+ }
1013
+ // TODO: need to check the interpolated inputs, as the references can be the same
1014
+ // however, the interpolation does create new objects
1015
+ return {};
1016
+ };
1017
+ Engine.prototype.runGraph = function (node, inputs, params) {
1018
+ return __awaiter(this, void 0, void 0, function () {
1019
+ var _a, body, executionId, context, startTime, _b, _c, _d, _i, name_1, fnCall, fn, inputs_1, params_1, result_1, cacheResult, startTime_1, endTime_1, result, endTime;
1020
+ return __generator(this, function (_e) {
1021
+ switch (_e.label) {
1022
+ case 0:
1023
+ _a = node.body, body = _a === void 0 ? {} : _a;
1024
+ executionId = uid();
1025
+ context = {
1026
+ scope: { inputs: inputs },
1027
+ timings: {},
1028
+ activations: {},
1029
+ };
1030
+ startTime = performance.now();
1031
+ _b = body;
1032
+ _c = [];
1033
+ for (_d in _b)
1034
+ _c.push(_d);
1035
+ _i = 0;
1036
+ _e.label = 1;
1037
+ case 1:
1038
+ if (!(_i < _c.length)) return [3 /*break*/, 5];
1039
+ _d = _c[_i];
1040
+ if (!(_d in _b)) return [3 /*break*/, 4];
1041
+ name_1 = _d;
1042
+ fnCall = body[name_1];
1043
+ fn = this.fnIndex[fnCall.name];
1044
+ if (!fn) {
1045
+ throw new Error("function ".concat(fnCall.name, " not found in index"));
1046
+ }
1047
+ inputs_1 = interpolate(fnCall.inputs || {}, context.scope);
1048
+ params_1 = fnCall.params || {};
1049
+ result_1 = {};
1050
+ cacheResult = this.checkCache(name_1, inputs_1);
1051
+ if (!(cacheResult !== this.cacheMiss)) return [3 /*break*/, 2];
1052
+ // use as result
1053
+ result_1 = cacheResult;
1054
+ // store the result in the scope
1055
+ context.scope[name_1] = result_1;
1056
+ return [3 /*break*/, 4];
1057
+ case 2:
1058
+ // cache miss, call the function implementation
1059
+ context.activations[name_1] = true;
1060
+ startTime_1 = performance.now();
1061
+ this.fireEvent("functionCall", {
1062
+ name: name_1,
1063
+ inputs: inputs_1,
1064
+ params: params_1,
1065
+ executionId: executionId,
1066
+ context: context,
1067
+ startTime: startTime_1,
1068
+ });
1069
+ return [4 /*yield*/, fn.impl(inputs_1, params_1)];
1070
+ case 3:
1071
+ result_1 = _e.sent();
1072
+ endTime_1 = performance.now();
1073
+ context.activations[name_1] = false;
1074
+ context.timings[name_1] = endTime_1 - startTime_1;
1075
+ // store the result in the scope
1076
+ context.scope[name_1] = result_1;
1077
+ this.fireEvent("functionResult", {
1078
+ name: name_1,
1079
+ inputs: inputs_1,
1080
+ params: params_1,
1081
+ executionId: executionId,
1082
+ context: context,
1083
+ startTime: startTime_1,
1084
+ endTime: endTime_1,
1085
+ duration: endTime_1 - startTime_1,
1086
+ });
1087
+ _e.label = 4;
1088
+ case 4:
1089
+ _i++;
1090
+ return [3 /*break*/, 1];
1091
+ case 5:
1092
+ result = interpolate(node.outputs || {}, context.scope);
1093
+ endTime = performance.now();
1094
+ // fire event
1095
+ this.fireEvent("result", {
1096
+ name: node.name,
1097
+ inputs: inputs,
1098
+ params: params,
1099
+ executionId: executionId,
1100
+ context: context,
1101
+ startTime: startTime,
1102
+ endTime: endTime,
1103
+ duration: endTime - startTime,
1104
+ });
1105
+ return [2 /*return*/, result];
1106
+ }
1107
+ });
1108
+ });
1109
+ };
1110
+ /**
1111
+ * creates an function that can be evaluated by calling its implementation
1112
+ * @param node
1113
+ * @returns
1114
+ */
1115
+ Engine.prototype.build = function (node, id) {
1116
+ var _this = this;
1117
+ if (isPrimitive(node)) {
1118
+ // already a primitive
1119
+ return node;
1120
+ }
1121
+ var _a = node.body, body = _a === void 0 ? {} : _a, props = __rest(node, ["body"]);
1122
+ var primitive = __assign(__assign({}, props), { outputs: {}, mount: function (trigger) {
1123
+ // mount all the nodes
1124
+ var unsubs = [];
1125
+ Object.values(body).forEach(function (n) {
1126
+ var _a;
1127
+ var fn = _this.fnIndex[n.name];
1128
+ if (!fn) {
1129
+ console.warn("function ".concat(n.name, " not found in index"));
1130
+ return;
1131
+ }
1132
+ var unsub = (_a = fn.mount) === null || _a === void 0 ? void 0 : _a.call(fn, trigger);
1133
+ if (unsub) {
1134
+ unsubs.push(unsub);
1135
+ }
1136
+ });
1137
+ return function () {
1138
+ var e_1, _a;
1139
+ console.log("Unmounting function: ".concat(node.name));
1140
+ try {
1141
+ // unmount all the nodes
1142
+ for (var unsubs_1 = __values(unsubs), unsubs_1_1 = unsubs_1.next(); !unsubs_1_1.done; unsubs_1_1 = unsubs_1.next()) {
1143
+ var unsub = unsubs_1_1.value;
1144
+ unsub();
1145
+ }
1146
+ }
1147
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
1148
+ finally {
1149
+ try {
1150
+ if (unsubs_1_1 && !unsubs_1_1.done && (_a = unsubs_1.return)) _a.call(unsubs_1);
1151
+ }
1152
+ finally { if (e_1) throw e_1.error; }
1153
+ }
1154
+ };
1155
+ }, impl: function (inputs, params) { return __awaiter(_this, void 0, void 0, function () {
1156
+ return __generator(this, function (_a) {
1157
+ console.log("Running function: ".concat(node.name), node, inputs, params);
1158
+ return [2 /*return*/, this.runGraph(node, inputs, params)];
1159
+ });
1160
+ }); } });
1161
+ this.fnIndex[primitive.name] = primitive;
1162
+ return primitive;
1163
+ };
1164
+ Engine.prototype.mount = function (node) {
1165
+ var _this = this;
1166
+ var _a;
1167
+ return (_a = node.mount) === null || _a === void 0 ? void 0 : _a.call(node, function () {
1168
+ console.log("Triggering node: ".concat(node.name));
1169
+ _this.run(node);
1170
+ });
1171
+ };
1172
+ Engine.prototype.subscribe = function (eventName, listener) {
1173
+ var _this = this;
1174
+ if (!this.listeners[eventName]) {
1175
+ this.listeners[eventName] = new Set();
1176
+ }
1177
+ if (!this.listeners[eventName].has(listener)) {
1178
+ this.listeners[eventName].add(listener);
1179
+ }
1180
+ return function () {
1181
+ _this.listeners[eventName].delete(listener);
1182
+ };
1183
+ };
1184
+ Engine.prototype.fireEvent = function (eventName, event) {
1185
+ var e_2, _a;
1186
+ try {
1187
+ for (var _b = __values(this.listeners[eventName] || []), _c = _b.next(); !_c.done; _c = _b.next()) {
1188
+ var listener = _c.value;
1189
+ listener(event);
1190
+ }
1191
+ }
1192
+ catch (e_2_1) { e_2 = { error: e_2_1 }; }
1193
+ finally {
1194
+ try {
1195
+ if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
1196
+ }
1197
+ finally { if (e_2) throw e_2.error; }
1198
+ }
1199
+ };
1200
+ Engine.prototype.run = function (node_1) {
1201
+ return __awaiter(this, arguments, void 0, function (node, inputs) {
1202
+ var builtFn, mappedInputs, result;
1203
+ var _a;
1204
+ if (inputs === void 0) { inputs = {}; }
1205
+ return __generator(this, function (_b) {
1206
+ switch (_b.label) {
1207
+ case 0:
1208
+ if (!isPrimitive(node)) {
1209
+ builtFn = this.getFunction(node.name);
1210
+ if (!builtFn) {
1211
+ // not yet build
1212
+ builtFn = this.build(node);
1213
+ }
1214
+ return [2 /*return*/, this.run(builtFn, inputs)];
1215
+ }
1216
+ console.log("Engine running with inputs", inputs, interpolate(inputs, {}));
1217
+ mappedInputs = interpolate(inputs, {});
1218
+ return [4 /*yield*/, ((_a = node.impl) === null || _a === void 0 ? void 0 : _a.call(node, mappedInputs, {}))];
1219
+ case 1:
1220
+ result = _b.sent();
1221
+ return [2 /*return*/, result];
1222
+ }
1223
+ });
1224
+ });
1225
+ };
1226
+ Engine.prototype.getFunction = function (name) {
1227
+ return this.fnIndex[name];
1228
+ };
1229
+ return Engine;
1230
+ }());
1231
+
1232
+ var variableStore = zustand.create(function (set, get, api) {
1233
+ return middleware.persist(function (pset, pget) { return ({
1234
+ data: {},
1235
+ getVar: function (scope, name, persist) {
1236
+ if (persist) {
1237
+ return pget().data["".concat(scope, "|").concat(name)];
1238
+ }
1239
+ else {
1240
+ return get().data["".concat(scope, "|").concat(name)];
1241
+ }
1242
+ },
1243
+ setVar: function (scope, name, value, persist) {
1244
+ var _a, _b;
1245
+ if (persist) {
1246
+ var data = __assign(__assign({}, pget().data), (_a = {}, _a["".concat(scope, "|").concat(name)] = value, _a));
1247
+ pset({ data: data });
1248
+ }
1249
+ else {
1250
+ var data = __assign(__assign({}, get().data), (_b = {}, _b["".concat(scope, "|").concat(name)] = value, _b));
1251
+ set({ data: data });
1252
+ }
1253
+ },
1254
+ }); }, {
1255
+ name: "variable-storage", // unique name
1256
+ // getStorage: () => sessionStorage, // (optional) by default the 'localStorage' is used
1257
+ })(set, get, api);
1258
+ });
1259
+ /**
1260
+ * scope restricts the variable scope, for example to a view id
1261
+ * @param scope
1262
+ * @param name
1263
+ */
1264
+ var useVariable = function (scope, name, initial, persist) {
1265
+ if (persist === void 0) { persist = true; }
1266
+ var value = variableStore(function (_a) {
1267
+ var getVar = _a.getVar;
1268
+ return getVar(scope, name, persist);
1269
+ });
1270
+ if (typeof value === "undefined")
1271
+ value = initial;
1272
+ var setVar = variableStore(function (_a) {
1273
+ var setVar = _a.setVar;
1274
+ return setVar;
1275
+ });
1276
+ var setValue = function (value) { return setVar(scope, name, value, persist); };
1277
+ return [value, setValue];
1278
+ };
1279
+
1280
+ var dummyEngine = new Engine();
1281
+ var EngineContext = React.createContext(dummyEngine);
1282
+ var useEngine = function () {
1283
+ return React.useContext(EngineContext);
1284
+ };
1285
+ var ChangeContext = React.createContext(function () { });
1286
+ var useChange = function () {
1287
+ return React.useContext(ChangeContext);
1288
+ };
1289
+
1290
+ var styles = {"DefaultNode":"DefaultNode_R2P6c","selected":"selected_VmB-F","active":"active_zjUzx","Log":"Log_dsq5e","Label":"Label_wBwWA","Output":"Output_e4yF-","type-string":"type-string_XVlwo","type-number":"type-number_0cg49","type-boolean":"type-boolean_t4ba5","type-any":"type-any_FPwjQ","Table":"Table_aZyRT"};
1291
+
1292
+ function NodeContainer(_a) {
1293
+ var _b;
1294
+ var id = _a.id, label = _a.label, className = _a.className, selected = _a.selected, children = _a.children;
1295
+ var engine = useEngine();
1296
+ var _c = __read(React.useState(false), 2), active = _c[0], setActive = _c[1];
1297
+ React.useEffect(function () {
1298
+ if (!id)
1299
+ return;
1300
+ var removeOnCall = engine.subscribe("functionCall", function (event) {
1301
+ if (event.name === id) {
1302
+ setActive(true);
1303
+ }
1304
+ });
1305
+ var removeOnResult = engine.subscribe("functionResult", function (event) {
1306
+ if (event.name === id) {
1307
+ setTimeout(function () { return setActive(false); }, Math.max(0, 1000 - (event.duration || 0)));
1308
+ }
1309
+ });
1310
+ return function () {
1311
+ removeOnCall();
1312
+ removeOnResult();
1313
+ };
1314
+ }, [id]);
1315
+ return (React.createElement("div", { className: classNames(className, styles.DefaultNode, (_b = {},
1316
+ _b[styles.selected] = selected,
1317
+ _b[styles.active] = active,
1318
+ _b)) },
1319
+ React.createElement("div", { className: styles.Label }, label),
1320
+ children));
1321
+ }
1322
+
1323
+ function Control(_a) {
1324
+ var value = _a.value, type = _a.type, options = _a.options, onChange = _a.onChange;
1325
+ if (options) {
1326
+ return (React.createElement("select", { value: value || "", onChange: function (e) { return onChange === null || onChange === void 0 ? void 0 : onChange(e.target.value); } }, options.map(function (option) { return (React.createElement("option", { key: option, value: option }, option)); })));
1327
+ }
1328
+ switch (type) {
1329
+ case "any":
1330
+ case "string":
1331
+ return (React.createElement("input", { type: "text", value: value || "", onChange: function (e) { return onChange === null || onChange === void 0 ? void 0 : onChange(e.target.value); } }));
1332
+ case "number":
1333
+ return (React.createElement("input", { type: "number", value: value || "", onChange: function (e) { return onChange === null || onChange === void 0 ? void 0 : onChange(Number(e.target.value)); } }));
1334
+ case "boolean":
1335
+ return (React.createElement("input", { type: "checkbox", checked: Boolean(value), onChange: function (e) { return onChange === null || onChange === void 0 ? void 0 : onChange(e.target.checked); } }));
1336
+ default:
1337
+ return (React.createElement("span", null,
1338
+ String(value),
1339
+ " (",
1340
+ type,
1341
+ ")"));
1342
+ }
1343
+ }
1344
+
1345
+ var Input = function (_a) {
1346
+ var _b;
1347
+ var name = _a.name, varDef = _a.varDef, id = _a.id, data = _a.data, onChange = _a.onChange;
1348
+ var normalized = normalizeVarDef(varDef);
1349
+ var value = (_b = data.inputs) === null || _b === void 0 ? void 0 : _b[name];
1350
+ var isRef = isReference(value);
1351
+ var handleInputChange = function (param) { return function (value) {
1352
+ var _a;
1353
+ // Update the function instance with the new input value
1354
+ var body = __assign({}, data.caller.body);
1355
+ var call = __assign({}, (body[id] || {}));
1356
+ call.inputs = __assign(__assign({}, call.inputs), (_a = {}, _a[param] = value, _a));
1357
+ body[id] = call;
1358
+ var updatedFn = __assign(__assign({}, data.caller), { body: body });
1359
+ onChange(updatedFn);
1360
+ }; };
1361
+ return (React.createElement("tr", { key: name, className: classNames(styles.Input, styles["type-".concat(normalized.type)]) },
1362
+ React.createElement("td", null,
1363
+ name,
1364
+ React.createElement(react.Handle, { type: "target", position: react.Position.Left, id: "".concat(id, "-").concat(name) })),
1365
+ React.createElement("td", null, !isRef && (React.createElement(Control, { type: normalized.type, value: value, onChange: handleInputChange(name) })))));
1366
+ };
1367
+
1368
+ var Param = function (_a) {
1369
+ var _b;
1370
+ var id = _a.id, name = _a.name, varDef = _a.varDef, data = _a.data, onChange = _a.onChange;
1371
+ var normalized = normalizeVarDef(varDef);
1372
+ var value = (_b = data.params) === null || _b === void 0 ? void 0 : _b[name];
1373
+ var isRef = isReference(value);
1374
+ var handleParamChange = function (param) { return function (value) {
1375
+ var _a;
1376
+ // Update the function instance with the new param value
1377
+ var body = __assign({}, data.caller.body);
1378
+ var call = __assign({}, (body[id] || {}));
1379
+ call.params = __assign(__assign({}, call.params), (_a = {}, _a[param] = value, _a));
1380
+ body[id] = call;
1381
+ var updatedFn = __assign(__assign({}, data.caller), { body: body });
1382
+ onChange(updatedFn);
1383
+ }; };
1384
+ return (React.createElement("tr", { key: name, className: classNames(styles.Input, styles["type-".concat(normalized.type)]) },
1385
+ React.createElement("td", null, name),
1386
+ React.createElement("td", null, !isRef && (React.createElement(Control, { type: normalized.type, options: normalized.options, value: value, onChange: handleParamChange(name) })))));
1387
+ };
1388
+
1389
+ var Output = function (_a) {
1390
+ var name = _a.name, varDef = _a.varDef, id = _a.id;
1391
+ var normalized = normalizeVarDef(varDef);
1392
+ return (React.createElement("tr", { key: name, className: classNames(styles.Output, styles["type-".concat(normalized.type)]) },
1393
+ React.createElement("td", { colSpan: 2 },
1394
+ name,
1395
+ React.createElement(react.Handle, { type: "source", position: react.Position.Right, id: "".concat(id, "-").concat(name) }))));
1396
+ };
1397
+
1398
+ function GenericNode(_a) {
1399
+ var id = _a.id, data = _a.data, selected = _a.selected, inputs = _a.inputs, outputs = _a.outputs, params = _a.params, children = _a.children, onChange = _a.onChange;
1400
+ return (React.createElement(NodeContainer, { label: data.name, selected: selected, id: id },
1401
+ children,
1402
+ React.createElement("table", null,
1403
+ React.createElement("tbody", null,
1404
+ Object.entries(outputs || {}).map(function (_a) {
1405
+ var _b = __read(_a, 2), name = _b[0], varDef = _b[1];
1406
+ return (React.createElement(Output, { key: name, name: name, varDef: varDef, id: id }));
1407
+ }),
1408
+ Object.entries(inputs || {}).map(function (_a) {
1409
+ var _b = __read(_a, 2), name = _b[0], varDef = _b[1];
1410
+ return (React.createElement(Input, { key: name, name: name, varDef: varDef, id: id, data: data, onChange: onChange }));
1411
+ }),
1412
+ Object.entries(params || {}).map(function (_a) {
1413
+ var _b = __read(_a, 2), name = _b[0], varDef = _b[1];
1414
+ return (React.createElement(Param, { key: name, name: name, varDef: varDef, id: id, data: data, onChange: onChange }));
1415
+ })))));
1416
+ }
1417
+
1418
+ var math = mathjs.create(mathjs.all, {});
1419
+ function MathView(_a) {
1420
+ var expr = _a.expr, _b = _a.displayMode, displayMode = _b === void 0 ? false : _b;
1421
+ var latex = "";
1422
+ try {
1423
+ latex = math.parse(expr).toTex({ parenthesis: "auto" });
1424
+ }
1425
+ catch (e) {
1426
+ latex = String(expr); // fallback on parse error
1427
+ }
1428
+ var html = katex.renderToString(latex, {
1429
+ throwOnError: false,
1430
+ displayMode: displayMode,
1431
+ });
1432
+ return React.createElement("span", { dangerouslySetInnerHTML: { __html: html } });
1433
+ }
1434
+ var Calc = React.memo(function (_a) {
1435
+ var _b;
1436
+ var id = _a.id, data = _a.data, selected = _a.selected;
1437
+ var engine = useEngine();
1438
+ var onChange = useChange();
1439
+ var calledFn = engine.getFunction(data.name);
1440
+ if (!calledFn) {
1441
+ return (React.createElement(NodeContainer, { label: "Function not found", selected: selected }));
1442
+ }
1443
+ var expression = (((_b = data.params) === null || _b === void 0 ? void 0 : _b.expression) || "").toString();
1444
+ // add free variables to inputs
1445
+ var inputs = __assign({}, (calledFn.inputs || {}));
1446
+ var symbols = getUnboundSymbols(expression);
1447
+ symbols.forEach(function (symbol) {
1448
+ if (!inputs[symbol]) {
1449
+ inputs[symbol] = {
1450
+ type: "number",
1451
+ };
1452
+ }
1453
+ });
1454
+ return (React.createElement(GenericNode, { id: id, data: data, selected: selected, inputs: inputs, outputs: calledFn.outputs, params: calledFn.params, onChange: onChange },
1455
+ React.createElement(MathView, { expr: expression, displayMode: true })));
1456
+ });
1457
+ Calc.displayName = "CalcNode";
1458
+
1459
+ var Default = React.memo(function (_a) {
1460
+ var id = _a.id, data = _a.data, selected = _a.selected;
1461
+ var engine = useEngine();
1462
+ var onChange = useChange();
1463
+ var calledFn = engine.getFunction(data.name);
1464
+ if (!calledFn) {
1465
+ return (React.createElement(NodeContainer, { label: "Function not found", selected: selected }));
1466
+ }
1467
+ return (React.createElement(GenericNode, { id: id, data: data, selected: selected, inputs: calledFn.inputs, outputs: calledFn.outputs, params: calledFn.params, onChange: onChange }));
1468
+ });
1469
+ Default.displayName = "DefaultNode";
1470
+
1471
+ var Log = React.memo(function (_a) {
1472
+ var id = _a.id, data = _a.data, selected = _a.selected;
1473
+ var engine = useEngine();
1474
+ var calledFn = engine.getFunction(data.name);
1475
+ var _b = __read(React.useState(null), 2), value = _b[0], setValue = _b[1];
1476
+ React.useEffect(function () {
1477
+ return engine.subscribe("functionResult", function (event) {
1478
+ var _a;
1479
+ if (event.name === id) {
1480
+ setValue(((_a = event.context.scope[id]) === null || _a === void 0 ? void 0 : _a.data) || null);
1481
+ }
1482
+ });
1483
+ }, []);
1484
+ if (!calledFn) {
1485
+ return (React.createElement(NodeContainer, { label: "Function not found", selected: selected }));
1486
+ }
1487
+ return (React.createElement(NodeContainer, { id: id, label: data.name, selected: selected, className: styles.Log },
1488
+ React.createElement("div", { className: styles.Table },
1489
+ React.createElement("table", null, Object.entries(value || {}).map(function (_a) {
1490
+ var _b = __read(_a, 2), key = _b[0], val = _b[1];
1491
+ return (React.createElement(React.Fragment, { key: key },
1492
+ React.createElement("tbody", null,
1493
+ React.createElement("tr", null,
1494
+ React.createElement("th", { colSpan: 2 }, "{".concat(key, "}"))),
1495
+ val.map(function (item, index) { return (React.createElement("tr", { key: "".concat(key, "-").concat(index) },
1496
+ React.createElement("td", null, index),
1497
+ React.createElement("td", { title: JSON.stringify(item, null, 2) }, item === null || item === void 0 ? void 0 : item.toString()))); }))));
1498
+ }))),
1499
+ React.createElement(react.Handle, { type: "target", position: react.Position.Left, id: "".concat(id, "-data") }),
1500
+ React.createElement(react.Handle, { type: "source", position: react.Position.Right, id: "".concat(id, "-data") })));
1501
+ });
1502
+ Log.displayName = "LogNode";
1503
+
1504
+ var nodeTypes = {
1505
+ Default: Default,
1506
+ Calc: Calc,
1507
+ Log: Log,
1508
+ };
1509
+
1510
+ function createGraph(fn, engine, positions) {
1511
+ var nodes = [];
1512
+ var edges = [];
1513
+ Object.entries(fn.body || {}).forEach(function (_a, index) {
1514
+ var _b = __read(_a, 2), id = _b[0], fncall = _b[1];
1515
+ var reffedFn = engine.getFunction(fncall.name);
1516
+ // create a node for each function call
1517
+ nodes.push({
1518
+ id: id,
1519
+ data: {
1520
+ name: fncall.name,
1521
+ caller: fn,
1522
+ inputs: fncall.inputs,
1523
+ params: fncall.params,
1524
+ },
1525
+ position: (positions === null || positions === void 0 ? void 0 : positions[id]) || { x: 250 * index, y: 0 },
1526
+ dragHandle: ".".concat(styles.Label),
1527
+ type: (reffedFn === null || reffedFn === void 0 ? void 0 : reffedFn.nodeType) || "Default",
1528
+ });
1529
+ var refs = getReferences(fncall.inputs || {});
1530
+ refs.forEach(function (ref) {
1531
+ // create an edge for each reference
1532
+ edges.push({
1533
+ id: "".concat(ref.path, "-").concat(id, ".").concat(ref.name),
1534
+ source: ref.refNode,
1535
+ target: id,
1536
+ sourceHandle: "".concat(ref.refNode, "-").concat(ref.refField),
1537
+ targetHandle: "".concat(id, "-").concat(ref.name),
1538
+ });
1539
+ });
1540
+ });
1541
+ return { nodes: nodes, edges: edges };
1542
+ }
1543
+ function FlowInner(_a) {
1544
+ var fn = _a.function, engine = _a.engine, onChange = _a.onChange;
1545
+ var _b = __read(useVariable("rules", "".concat(fn.name, ".positions"), {}), 2), positions = _b[0], setPositions = _b[1];
1546
+ var _c = React.useMemo(function () {
1547
+ return createGraph(fn, engine, positions);
1548
+ }, [fn, engine]), initialNodes = _c.nodes, initialEdges = _c.edges;
1549
+ var _d = __read(useInner(initialNodes), 2), nodes = _d[0], setNodes = _d[1];
1550
+ var _e = __read(useInner(initialEdges), 2), edges = _e[0], setEdges = _e[1];
1551
+ // useLayoutNodes();
1552
+ var updatePosition = function (event, node) {
1553
+ var _a;
1554
+ setPositions(__assign(__assign({}, positions), (_a = {}, _a[node.id] = node.position, _a)));
1555
+ };
1556
+ var onNodesChange = React.useCallback(function (changes) {
1557
+ return setNodes(function (nodesSnapshot) {
1558
+ return react.applyNodeChanges(changes, nodesSnapshot);
1559
+ });
1560
+ }, [setNodes]);
1561
+ var onEdgesChange = React.useCallback(function (changes) {
1562
+ return setEdges(function (edgesSnapshot) {
1563
+ return react.applyEdgeChanges(changes, edgesSnapshot);
1564
+ });
1565
+ }, [setEdges]);
1566
+ var onConnect = React.useCallback(function (params) {
1567
+ var _a, _b;
1568
+ var sourceField = (_a = params.sourceHandle) === null || _a === void 0 ? void 0 : _a.split("-")[1];
1569
+ var targetField = (_b = params.targetHandle) === null || _b === void 0 ? void 0 : _b.split("-")[1];
1570
+ if (!sourceField || !targetField) {
1571
+ console.warn("Invalid connection handles", params);
1572
+ return;
1573
+ }
1574
+ onChange === null || onChange === void 0 ? void 0 : onChange(applyNodeConnect(fn, params.source, params.target, sourceField, targetField));
1575
+ setEdges(function (edgesSnapshot) { return react.addEdge(params, edgesSnapshot); });
1576
+ }, [setEdges, fn, onChange]);
1577
+ var onNodesDelete = React.useCallback(function (nodesToDelete) {
1578
+ onChange === null || onChange === void 0 ? void 0 : onChange(applyNodeDelete(fn, nodesToDelete.map(function (n) { return n.id; })));
1579
+ setNodes(function (nodesSnapshot) {
1580
+ return nodesSnapshot.filter(function (node) { return !nodesToDelete.some(function (n) { return n.id === node.id; }); });
1581
+ });
1582
+ setEdges(function (edgesSnapshot) {
1583
+ return edgesSnapshot.filter(function (edge) {
1584
+ return !nodesToDelete.some(function (n) { return n.id === edge.source || n.id === edge.target; });
1585
+ });
1586
+ });
1587
+ }, [setNodes, setEdges, onChange, fn]);
1588
+ var onEdgesDelete = React.useCallback(function (edgesToDelete) {
1589
+ var newFn = fn;
1590
+ edgesToDelete.forEach(function (edge) {
1591
+ var _a, _b;
1592
+ var sourceField = (_a = edge.sourceHandle) === null || _a === void 0 ? void 0 : _a.split("-")[1];
1593
+ var targetField = (_b = edge.targetHandle) === null || _b === void 0 ? void 0 : _b.split("-")[1];
1594
+ if (!sourceField || !targetField) {
1595
+ console.warn("Invalid connection handles", edge);
1596
+ return;
1597
+ }
1598
+ newFn = applyEdgeDelete(newFn, edge.source, edge.target, sourceField, targetField);
1599
+ });
1600
+ onChange === null || onChange === void 0 ? void 0 : onChange(newFn);
1601
+ setEdges(function (edgesSnapshot) {
1602
+ return edgesSnapshot.filter(function (edge) { return !edgesToDelete.some(function (e) { return e.id === edge.id; }); });
1603
+ });
1604
+ }, [setEdges, onChange, fn]);
1605
+ return (React.createElement(react.ReactFlow, { nodes: nodes, edges: edges, nodeTypes: nodeTypes, onNodesChange: onNodesChange, onEdgesChange: onEdgesChange, onNodesDelete: onNodesDelete, onEdgesDelete: onEdgesDelete, onNodeDragStop: updatePosition, onConnect: onConnect, fitView: true,
1606
+ // panOnDrag={false}
1607
+ selectionOnDrag: true, minZoom: 0.1, deleteKeyCode: "Delete" },
1608
+ React.createElement(react.Background, { color: "#ccc", variant: react.BackgroundVariant.Dots }),
1609
+ React.createElement(react.Controls, null)));
1610
+ }
1611
+ function Flow(_a) {
1612
+ var fn = _a.function, engine = _a.engine, _b = _a.onChange, onChange = _b === void 0 ? function () { } : _b;
1613
+ return (React.createElement(EngineContext.Provider, { value: engine },
1614
+ React.createElement(ChangeContext.Provider, { value: onChange },
1615
+ React.createElement(react.ReactFlowProvider, null,
1616
+ React.createElement(FlowInner, { function: fn, engine: engine, onChange: onChange })))));
1617
+ }
1618
+
1619
+ exports.Engine = Engine;
1620
+ exports.Flow = Flow;
1621
+ exports.applyEdgeDelete = applyEdgeDelete;
1622
+ exports.applyNodeAdd = applyNodeAdd;
1623
+ exports.applyNodeConnect = applyNodeConnect;
1624
+ exports.applyNodeDelete = applyNodeDelete;
1625
+ exports.createGraph = createGraph;
1626
+ exports.getReferences = getReferences;
1627
+ exports.getValue = getValue$1;
1628
+ exports.interpolate = interpolate;
1629
+ exports.isReference = isReference;
1630
+ exports.normalizeVarDef = normalizeVarDef;
1631
+ exports.parseReference = parseReference;
1632
+ exports.primitives = primitives;
1633
+ exports.topSort = topSort;
1634
+ exports.uid = uid;
1635
+ //# sourceMappingURL=index.js.map