yaml-flow 3.1.1 → 5.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +81 -20
- package/board-live-cards-cli.js +37 -0
- package/browser/board-livegraph-runtime.js +1453 -0
- package/browser/board-livegraph-runtime.js.map +1 -0
- package/browser/card-compute.js +153 -433
- package/browser/live-cards.js +868 -115
- package/browser/live-cards.schema.json +90 -83
- package/dist/board-livegraph-runtime/index.cjs +1448 -0
- package/dist/board-livegraph-runtime/index.cjs.map +1 -0
- package/dist/board-livegraph-runtime/index.d.cts +101 -0
- package/dist/board-livegraph-runtime/index.d.ts +101 -0
- package/dist/board-livegraph-runtime/index.js +1441 -0
- package/dist/board-livegraph-runtime/index.js.map +1 -0
- package/dist/card-compute/index.cjs +266 -431
- package/dist/card-compute/index.cjs.map +1 -1
- package/dist/card-compute/index.d.cts +77 -49
- package/dist/card-compute/index.d.ts +77 -49
- package/dist/card-compute/index.js +263 -432
- package/dist/card-compute/index.js.map +1 -1
- package/dist/cli/board-live-cards-cli.cjs +2750 -0
- package/dist/cli/board-live-cards-cli.cjs.map +1 -0
- package/dist/cli/board-live-cards-cli.d.cts +205 -0
- package/dist/cli/board-live-cards-cli.d.ts +205 -0
- package/dist/cli/board-live-cards-cli.js +2702 -0
- package/dist/cli/board-live-cards-cli.js.map +1 -0
- package/dist/{constants-B2zqu10b.d.ts → constants-DuzE5n03.d.ts} +2 -2
- package/dist/{constants-DJZU1pwJ.d.cts → constants-ozjf1Ejw.d.cts} +2 -2
- package/dist/continuous-event-graph/index.cjs +258 -464
- package/dist/continuous-event-graph/index.cjs.map +1 -1
- package/dist/continuous-event-graph/index.d.cts +18 -358
- package/dist/continuous-event-graph/index.d.ts +18 -358
- package/dist/continuous-event-graph/index.js +255 -464
- package/dist/continuous-event-graph/index.js.map +1 -1
- package/dist/event-graph/index.cjs +4 -4
- package/dist/event-graph/index.cjs.map +1 -1
- package/dist/event-graph/index.d.cts +5 -5
- package/dist/event-graph/index.d.ts +5 -5
- package/dist/event-graph/index.js +4 -4
- package/dist/event-graph/index.js.map +1 -1
- package/dist/index.cjs +1684 -555
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +26 -7
- package/dist/index.d.ts +26 -7
- package/dist/index.js +1678 -555
- package/dist/index.js.map +1 -1
- package/dist/inference/index.cjs +138 -19
- package/dist/inference/index.cjs.map +1 -1
- package/dist/inference/index.d.cts +2 -2
- package/dist/inference/index.d.ts +2 -2
- package/dist/inference/index.js +138 -19
- package/dist/inference/index.js.map +1 -1
- package/dist/journal-DRfJiheM.d.cts +28 -0
- package/dist/journal-NLYuqege.d.ts +28 -0
- package/dist/live-cards-bridge-Or7fdEJV.d.ts +316 -0
- package/dist/live-cards-bridge-vGJ6tMzN.d.cts +316 -0
- package/dist/schedule-CMcZe5Ny.d.ts +21 -0
- package/dist/schedule-CiucyCan.d.cts +21 -0
- package/dist/step-machine/index.cjs +18 -1
- package/dist/step-machine/index.cjs.map +1 -1
- package/dist/step-machine/index.d.cts +2 -2
- package/dist/step-machine/index.d.ts +2 -2
- package/dist/step-machine/index.js +18 -1
- package/dist/step-machine/index.js.map +1 -1
- package/dist/stores/file.d.cts +1 -1
- package/dist/stores/file.d.ts +1 -1
- package/dist/stores/index.d.cts +1 -1
- package/dist/stores/index.d.ts +1 -1
- package/dist/stores/localStorage.d.cts +1 -1
- package/dist/stores/localStorage.d.ts +1 -1
- package/dist/stores/memory.d.cts +1 -1
- package/dist/stores/memory.d.ts +1 -1
- package/dist/{types-BwvgvlOO.d.cts → types-BzLD8bjb.d.cts} +1 -1
- package/dist/{types-ClRA8hzC.d.ts → types-C2eJ7DAV.d.ts} +1 -1
- package/dist/{types-DEj7OakX.d.cts → types-CMFSIjpc.d.cts} +39 -4
- package/dist/{types-DEj7OakX.d.ts → types-CMFSIjpc.d.ts} +39 -4
- package/dist/{types-FZ_eyErS.d.cts → types-ycun84cq.d.cts} +1 -0
- package/dist/{types-FZ_eyErS.d.ts → types-ycun84cq.d.ts} +1 -0
- package/dist/{validate-DEZ2Ymdb.d.ts → validate-DJQTQ6bP.d.ts} +1 -1
- package/dist/{validate-DqKTZg_o.d.cts → validate-ke92Cleg.d.cts} +1 -1
- package/examples/browser/boards/portfolio-tracker/cards/holdings-table.json +22 -0
- package/examples/browser/boards/portfolio-tracker/cards/portfolio-form.json +16 -0
- package/examples/browser/boards/portfolio-tracker/cards/portfolio-value.json +15 -0
- package/examples/browser/boards/portfolio-tracker/cards/price-fetch.json +15 -0
- package/examples/browser/boards/portfolio-tracker/fetch-prices.js +43 -0
- package/examples/browser/boards/portfolio-tracker/portfolio-tracker-task-executor.cjs +96 -0
- package/examples/browser/boards/portfolio-tracker/portfolio-tracker.bat +7 -0
- package/examples/browser/boards/portfolio-tracker/portfolio-tracker.js +217 -0
- package/examples/browser/livecards-browser/index.html +41 -0
- package/examples/browser/{index.html → step-machine-browser/index.html} +53 -53
- package/examples/cli/step-machine-cli/portfolio-tracker/cards/holdings-table.json +22 -0
- package/examples/cli/step-machine-cli/portfolio-tracker/cards/portfolio-form.json +43 -0
- package/examples/cli/step-machine-cli/portfolio-tracker/cards/portfolio-value.json +15 -0
- package/examples/cli/step-machine-cli/portfolio-tracker/cards/price-fetch.json +15 -0
- package/examples/cli/step-machine-cli/portfolio-tracker/fetch-prices.js +48 -0
- package/examples/cli/step-machine-cli/portfolio-tracker/handlers/_board-cli.js +58 -0
- package/examples/cli/step-machine-cli/portfolio-tracker/handlers/add-cards-cli.js +27 -0
- package/examples/cli/step-machine-cli/portfolio-tracker/handlers/init-board-cli.js +25 -0
- package/examples/cli/step-machine-cli/portfolio-tracker/handlers/reset-board-dir-cli.js +29 -0
- package/examples/cli/step-machine-cli/portfolio-tracker/handlers/retrigger-cli.js +27 -0
- package/examples/cli/step-machine-cli/portfolio-tracker/handlers/status-cli.js +25 -0
- package/examples/cli/step-machine-cli/portfolio-tracker/handlers/update-holdings-cli.js +37 -0
- package/examples/cli/step-machine-cli/portfolio-tracker/handlers/wait-completed-cli.js +53 -0
- package/examples/cli/step-machine-cli/portfolio-tracker/handlers/write-prices-cli.js +35 -0
- package/examples/cli/step-machine-cli/portfolio-tracker/portfolio-tracker.flow.yaml +227 -0
- package/examples/cli/step-machine-cli/portfolio-tracker/portfolio-tracker.input.json +38 -0
- package/examples/cli/step-machine-cli/portfolio-tracker/run-portfolio-tracker.bat +29 -0
- package/examples/cli/step-machine-demo/jsonata-init-board-cli.js +36 -0
- package/examples/cli/step-machine-demo/jsonata-init-board.flow.yaml +30 -0
- package/examples/cli/step-machine-demo/one-step-cli-only.flow.yaml +19 -0
- package/examples/cli/step-machine-demo/step-cli-echo-y.js +15 -0
- package/examples/cli/step-machine-demo/step2-double-cli.js +39 -0
- package/examples/cli/step-machine-demo/two-step-math-handlers.js +32 -0
- package/examples/cli/step-machine-demo/two-step-math.flow.yaml +31 -0
- package/examples/cli/step-machine-demo/two-step-mixed-handlers.js +24 -0
- package/examples/cli/step-machine-demo/two-step-mixed.flow.yaml +35 -0
- package/examples/example-board/board.yaml +23 -0
- package/examples/example-board/bootstrap_payload.json +1 -0
- package/examples/example-board/cards/card-chain-region-alert.json +39 -0
- package/examples/example-board/cards/card-chain-region-totals.json +26 -0
- package/examples/example-board/cards/card-chain-top-region.json +24 -0
- package/examples/example-board/cards/card-ex-actions.json +32 -0
- package/examples/example-board/cards/card-ex-chart.json +30 -0
- package/examples/example-board/cards/card-ex-filter.json +36 -0
- package/examples/example-board/cards/card-ex-filtered-by-preference.json +59 -0
- package/examples/example-board/cards/card-ex-form.json +91 -0
- package/examples/example-board/cards/card-ex-list.json +22 -0
- package/examples/example-board/cards/card-ex-markdown.json +17 -0
- package/examples/example-board/cards/card-ex-metric.json +19 -0
- package/examples/example-board/cards/card-ex-narrative.json +36 -0
- package/examples/example-board/cards/card-ex-source-http.json +28 -0
- package/examples/example-board/cards/card-ex-source.json +21 -0
- package/examples/example-board/cards/card-ex-status.json +35 -0
- package/examples/example-board/cards/card-ex-table.json +30 -0
- package/examples/example-board/cards/card-ex-todo.json +29 -0
- package/examples/example-board/demo-chat-handler.js +69 -0
- package/examples/example-board/demo-server.js +87 -0
- package/examples/example-board/demo-shell-browser.html +806 -0
- package/examples/example-board/demo-shell-with-server.html +280 -0
- package/examples/example-board/demo-shell.html +62 -0
- package/examples/example-board/demo-task-executor.js +255 -0
- package/examples/example-board/mock.db +15 -0
- package/examples/example-board/reusable-board-runtime-client.js +265 -0
- package/examples/example-board/reusable-runtime-artifacts-adapter.js +233 -0
- package/examples/example-board/reusable-server-runtime.js +1284 -0
- package/examples/index.html +799 -0
- package/examples/{batch → npm-libs/batch}/batch-step-machine.ts +1 -1
- package/examples/{continuous-event-graph → npm-libs/continuous-event-graph}/live-cards-board.ts +18 -18
- package/examples/{continuous-event-graph → npm-libs/continuous-event-graph}/live-portfolio-dashboard.ts +24 -24
- package/examples/{continuous-event-graph → npm-libs/continuous-event-graph}/portfolio-tracker.ts +1 -1
- package/examples/{continuous-event-graph → npm-libs/continuous-event-graph}/reactive-monitoring.ts +1 -1
- package/examples/{continuous-event-graph → npm-libs/continuous-event-graph}/reactive-pipeline.ts +1 -1
- package/examples/{continuous-event-graph → npm-libs/continuous-event-graph}/soc-incident-board.ts +1 -1
- package/examples/{continuous-event-graph → npm-libs/continuous-event-graph}/stock-dashboard.ts +1 -1
- package/examples/{event-graph → npm-libs/event-graph}/ci-cd-pipeline.ts +1 -1
- package/examples/{event-graph → npm-libs/event-graph}/executor-diamond.ts +1 -1
- package/examples/{event-graph → npm-libs/event-graph}/executor-pipeline.ts +1 -1
- package/examples/{event-graph → npm-libs/event-graph}/research-pipeline.ts +1 -1
- package/examples/{graph-of-graphs → npm-libs/graph-of-graphs}/multi-stage-etl.ts +1 -1
- package/examples/{graph-of-graphs → npm-libs/graph-of-graphs}/url-processing-pipeline.ts +1 -1
- package/examples/{inference → npm-libs/inference}/azure-deployment.ts +1 -1
- package/examples/{inference → npm-libs/inference}/copilot-cli.ts +1 -1
- package/examples/{inference → npm-libs/inference}/data-pipeline.ts +1 -1
- package/examples/{inference → npm-libs/inference}/pluggable-adapters.ts +1 -1
- package/examples/{node → npm-libs/node}/ai-conversation.ts +1 -1
- package/examples/{node → npm-libs/node}/simple-greeting.ts +2 -2
- package/examples/step-machine-cli/portfolio-tracker/cards/holdings-table.json +22 -0
- package/examples/step-machine-cli/portfolio-tracker/cards/portfolio-form.json +43 -0
- package/examples/step-machine-cli/portfolio-tracker/cards/portfolio-value.json +15 -0
- package/examples/step-machine-cli/portfolio-tracker/cards/price-fetch.json +15 -0
- package/examples/step-machine-cli/portfolio-tracker/fetch-prices.js +48 -0
- package/examples/step-machine-cli/portfolio-tracker/handlers/_board-cli.js +58 -0
- package/examples/step-machine-cli/portfolio-tracker/handlers/add-cards-cli.js +27 -0
- package/examples/step-machine-cli/portfolio-tracker/handlers/init-board-cli.js +25 -0
- package/examples/step-machine-cli/portfolio-tracker/handlers/reset-board-dir-cli.js +29 -0
- package/examples/step-machine-cli/portfolio-tracker/handlers/retrigger-cli.js +27 -0
- package/examples/step-machine-cli/portfolio-tracker/handlers/status-cli.js +25 -0
- package/examples/step-machine-cli/portfolio-tracker/handlers/update-holdings-cli.js +37 -0
- package/examples/step-machine-cli/portfolio-tracker/handlers/wait-completed-cli.js +53 -0
- package/examples/step-machine-cli/portfolio-tracker/handlers/write-prices-cli.js +35 -0
- package/examples/step-machine-cli/portfolio-tracker/portfolio-tracker-task-executor.cjs +96 -0
- package/examples/step-machine-cli/portfolio-tracker/portfolio-tracker.flow.yaml +227 -0
- package/examples/step-machine-cli/portfolio-tracker/portfolio-tracker.input.json +38 -0
- package/examples/step-machine-cli/portfolio-tracker/run-portfolio-tracker.bat +29 -0
- package/package.json +27 -2
- package/schema/board-status.schema.json +118 -0
- package/schema/card-runtime.schema.json +25 -0
- package/schema/flow.schema.json +5 -0
- package/schema/live-cards.schema.json +90 -83
- package/step-machine-cli.js +674 -0
- package/browser/ingest-board.js +0 -296
- package/examples/ingest.js +0 -733
- /package/examples/{flows → npm-libs/flows}/ai-conversation.yaml +0 -0
- /package/examples/{flows → npm-libs/flows}/order-processing.yaml +0 -0
- /package/examples/{flows → npm-libs/flows}/simple-greeting.yaml +0 -0
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var fs = require('fs');
|
|
4
|
-
var crypto = require('crypto');
|
|
5
3
|
var child_process = require('child_process');
|
|
4
|
+
var jsonata2 = require('jsonata');
|
|
6
5
|
require('ajv-formats');
|
|
7
6
|
|
|
7
|
+
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
8
|
+
|
|
9
|
+
var jsonata2__default = /*#__PURE__*/_interopDefault(jsonata2);
|
|
10
|
+
|
|
8
11
|
// src/event-graph/constants.ts
|
|
9
12
|
var TASK_STATUS = {
|
|
10
13
|
NOT_STARTED: "not-started",
|
|
@@ -247,43 +250,51 @@ function applyEvent(live, event) {
|
|
|
247
250
|
if ("executionId" in event && event.executionId && event.executionId !== state.executionId) {
|
|
248
251
|
return live;
|
|
249
252
|
}
|
|
250
|
-
let newState;
|
|
251
253
|
switch (event.type) {
|
|
254
|
+
// --- Execution state transitions ---
|
|
252
255
|
case "task-started":
|
|
253
|
-
|
|
254
|
-
break;
|
|
256
|
+
return { config, state: applyTaskStart(state, event.taskName) };
|
|
255
257
|
case "task-completed":
|
|
256
|
-
|
|
257
|
-
break;
|
|
258
|
+
return { config, state: applyTaskCompletion(state, config, event.taskName, event.result, event.dataHash, event.data) };
|
|
258
259
|
case "task-failed":
|
|
259
|
-
|
|
260
|
-
break;
|
|
260
|
+
return { config, state: applyTaskFailure(state, config, event.taskName, event.error) };
|
|
261
261
|
case "task-progress":
|
|
262
|
-
|
|
263
|
-
break;
|
|
262
|
+
return { config, state: applyTaskProgress(state, event.taskName, event.message, event.progress) };
|
|
264
263
|
case "task-restart":
|
|
265
|
-
|
|
266
|
-
break;
|
|
264
|
+
return { config, state: applyTaskRestart(state, event.taskName) };
|
|
267
265
|
case "inject-tokens":
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
266
|
+
return {
|
|
267
|
+
config,
|
|
268
|
+
state: {
|
|
269
|
+
...state,
|
|
270
|
+
availableOutputs: [.../* @__PURE__ */ new Set([...state.availableOutputs, ...event.tokens])],
|
|
271
|
+
lastUpdated: (/* @__PURE__ */ new Date()).toISOString()
|
|
272
|
+
}
|
|
272
273
|
};
|
|
273
|
-
break;
|
|
274
274
|
case "agent-action":
|
|
275
|
-
|
|
276
|
-
|
|
275
|
+
return { config, state: applyAgentAction(state, event.action) };
|
|
276
|
+
// --- Structural mutations ---
|
|
277
|
+
case "task-upsert":
|
|
278
|
+
return addNode(live, event.taskName, event.taskConfig);
|
|
279
|
+
case "task-removal":
|
|
280
|
+
return removeNode(live, event.taskName);
|
|
281
|
+
case "node-requires-add":
|
|
282
|
+
return addRequires(live, event.nodeName, event.tokens);
|
|
283
|
+
case "node-requires-remove":
|
|
284
|
+
return removeRequires(live, event.nodeName, event.tokens);
|
|
285
|
+
case "node-provides-add":
|
|
286
|
+
return addProvides(live, event.nodeName, event.tokens);
|
|
287
|
+
case "node-provides-remove":
|
|
288
|
+
return removeProvides(live, event.nodeName, event.tokens);
|
|
277
289
|
default:
|
|
278
290
|
return live;
|
|
279
291
|
}
|
|
280
|
-
return { config, state: newState };
|
|
281
292
|
}
|
|
282
293
|
function applyEvents(live, events) {
|
|
283
294
|
return events.reduce((current, event) => applyEvent(current, event), live);
|
|
284
295
|
}
|
|
285
296
|
function addNode(live, name, taskConfig) {
|
|
286
|
-
|
|
297
|
+
const exists = !!live.config.tasks[name];
|
|
287
298
|
return {
|
|
288
299
|
config: {
|
|
289
300
|
...live.config,
|
|
@@ -291,7 +302,10 @@ function addNode(live, name, taskConfig) {
|
|
|
291
302
|
},
|
|
292
303
|
state: {
|
|
293
304
|
...live.state,
|
|
294
|
-
tasks: {
|
|
305
|
+
tasks: {
|
|
306
|
+
...live.state.tasks,
|
|
307
|
+
[name]: exists ? live.state.tasks[name] : createDefaultGraphEngineStore2()
|
|
308
|
+
},
|
|
295
309
|
lastUpdated: (/* @__PURE__ */ new Date()).toISOString()
|
|
296
310
|
}
|
|
297
311
|
};
|
|
@@ -998,6 +1012,8 @@ function getDownstream(live, nodeName) {
|
|
|
998
1012
|
}));
|
|
999
1013
|
return { nodeName, nodes, tokens: [...tokenSet] };
|
|
1000
1014
|
}
|
|
1015
|
+
|
|
1016
|
+
// src/continuous-event-graph/journal.ts
|
|
1001
1017
|
var MemoryJournal = class {
|
|
1002
1018
|
buffer = [];
|
|
1003
1019
|
append(event) {
|
|
@@ -1012,39 +1028,11 @@ var MemoryJournal = class {
|
|
|
1012
1028
|
return this.buffer.length;
|
|
1013
1029
|
}
|
|
1014
1030
|
};
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
this.path = path;
|
|
1018
|
-
if (!fs.existsSync(path)) {
|
|
1019
|
-
fs.writeFileSync(path, "", "utf-8");
|
|
1020
|
-
}
|
|
1021
|
-
}
|
|
1022
|
-
path;
|
|
1023
|
-
pending = 0;
|
|
1024
|
-
append(event) {
|
|
1025
|
-
fs.appendFileSync(this.path, JSON.stringify(event) + "\n", "utf-8");
|
|
1026
|
-
this.pending++;
|
|
1027
|
-
}
|
|
1028
|
-
drain() {
|
|
1029
|
-
const content = fs.readFileSync(this.path, "utf-8").trim();
|
|
1030
|
-
fs.writeFileSync(this.path, "", "utf-8");
|
|
1031
|
-
this.pending = 0;
|
|
1032
|
-
if (!content) return [];
|
|
1033
|
-
return content.split("\n").map((line) => JSON.parse(line));
|
|
1034
|
-
}
|
|
1035
|
-
get size() {
|
|
1036
|
-
try {
|
|
1037
|
-
const content = fs.readFileSync(this.path, "utf-8").trim();
|
|
1038
|
-
if (!content) return 0;
|
|
1039
|
-
return content.split("\n").length;
|
|
1040
|
-
} catch {
|
|
1041
|
-
return this.pending;
|
|
1042
|
-
}
|
|
1043
|
-
}
|
|
1044
|
-
};
|
|
1031
|
+
|
|
1032
|
+
// src/continuous-event-graph/reactive.ts
|
|
1045
1033
|
function computeDataHash(data) {
|
|
1046
1034
|
const json = stableStringify(data);
|
|
1047
|
-
return
|
|
1035
|
+
return fnv1a64Hex(json);
|
|
1048
1036
|
}
|
|
1049
1037
|
function stableStringify(value) {
|
|
1050
1038
|
if (value === null || value === void 0 || typeof value !== "object") {
|
|
@@ -1057,28 +1045,65 @@ function stableStringify(value) {
|
|
|
1057
1045
|
const keys = Object.keys(obj).sort();
|
|
1058
1046
|
return "{" + keys.map((k) => JSON.stringify(k) + ":" + stableStringify(obj[k])).join(",") + "}";
|
|
1059
1047
|
}
|
|
1048
|
+
function fnv1a64Hex(input) {
|
|
1049
|
+
let hash = 0xcbf29ce484222325n;
|
|
1050
|
+
const prime = 0x100000001b3n;
|
|
1051
|
+
const mod = 0xffffffffffffffffn;
|
|
1052
|
+
for (let i = 0; i < input.length; i++) {
|
|
1053
|
+
hash ^= BigInt(input.charCodeAt(i));
|
|
1054
|
+
hash = hash * prime & mod;
|
|
1055
|
+
}
|
|
1056
|
+
return hash.toString(16).padStart(16, "0");
|
|
1057
|
+
}
|
|
1058
|
+
function base64UrlEncode(input) {
|
|
1059
|
+
if (typeof Buffer !== "undefined") {
|
|
1060
|
+
return Buffer.from(input, "utf8").toString("base64url");
|
|
1061
|
+
}
|
|
1062
|
+
if (typeof btoa === "function") {
|
|
1063
|
+
const bytes = new TextEncoder().encode(input);
|
|
1064
|
+
let binary = "";
|
|
1065
|
+
for (const b of bytes) binary += String.fromCharCode(b);
|
|
1066
|
+
return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, "");
|
|
1067
|
+
}
|
|
1068
|
+
throw new Error("No base64 encoder available in this runtime");
|
|
1069
|
+
}
|
|
1070
|
+
function base64UrlDecode(input) {
|
|
1071
|
+
if (typeof Buffer !== "undefined") {
|
|
1072
|
+
return Buffer.from(input, "base64url").toString("utf8");
|
|
1073
|
+
}
|
|
1074
|
+
if (typeof atob === "function") {
|
|
1075
|
+
const base64 = input.replace(/-/g, "+").replace(/_/g, "/");
|
|
1076
|
+
const padded = base64 + "=".repeat((4 - base64.length % 4) % 4);
|
|
1077
|
+
const binary = atob(padded);
|
|
1078
|
+
const bytes = new Uint8Array(binary.length);
|
|
1079
|
+
for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);
|
|
1080
|
+
return new TextDecoder().decode(bytes);
|
|
1081
|
+
}
|
|
1082
|
+
throw new Error("No base64 decoder available in this runtime");
|
|
1083
|
+
}
|
|
1060
1084
|
function encodeCallbackToken(taskName) {
|
|
1061
1085
|
const payload = JSON.stringify({ t: taskName, n: Date.now().toString(36) + Math.random().toString(36).slice(2, 6) });
|
|
1062
|
-
return
|
|
1086
|
+
return base64UrlEncode(payload);
|
|
1063
1087
|
}
|
|
1064
1088
|
function decodeCallbackToken(token) {
|
|
1065
1089
|
try {
|
|
1066
|
-
const payload = JSON.parse(
|
|
1090
|
+
const payload = JSON.parse(base64UrlDecode(token));
|
|
1067
1091
|
if (typeof payload?.t === "string") return { taskName: payload.t };
|
|
1068
1092
|
return null;
|
|
1069
1093
|
} catch {
|
|
1070
1094
|
return null;
|
|
1071
1095
|
}
|
|
1072
1096
|
}
|
|
1073
|
-
function createReactiveGraph(
|
|
1097
|
+
function createReactiveGraph(configOrLive, options, executionId) {
|
|
1074
1098
|
const {
|
|
1075
1099
|
handlers: initialHandlers,
|
|
1076
|
-
journal = new MemoryJournal(),
|
|
1077
1100
|
onDrain
|
|
1078
1101
|
} = options;
|
|
1079
|
-
|
|
1102
|
+
const inputQueue = new MemoryJournal();
|
|
1103
|
+
let live = "state" in configOrLive && "config" in configOrLive ? configOrLive : createLiveGraph(configOrLive, executionId);
|
|
1080
1104
|
let disposed = false;
|
|
1081
1105
|
const handlers = new Map(Object.entries(initialHandlers));
|
|
1106
|
+
const internalJournal = new MemoryJournal();
|
|
1082
1107
|
let draining = false;
|
|
1083
1108
|
let drainQueued = false;
|
|
1084
1109
|
function drain() {
|
|
@@ -1098,7 +1123,9 @@ function createReactiveGraph(config, options, executionId) {
|
|
|
1098
1123
|
}
|
|
1099
1124
|
}
|
|
1100
1125
|
function drainOnce() {
|
|
1101
|
-
const
|
|
1126
|
+
const internalEvents = internalJournal.drain();
|
|
1127
|
+
const inputEvents = inputQueue.drain();
|
|
1128
|
+
const events = [...internalEvents, ...inputEvents];
|
|
1102
1129
|
if (events.length > 0) {
|
|
1103
1130
|
live = applyEvents(live, events);
|
|
1104
1131
|
}
|
|
@@ -1109,6 +1136,26 @@ function createReactiveGraph(config, options, executionId) {
|
|
|
1109
1136
|
for (const taskName of result.eligible) {
|
|
1110
1137
|
dispatchTask(taskName);
|
|
1111
1138
|
}
|
|
1139
|
+
for (const event of events) {
|
|
1140
|
+
if (event.type === "task-progress") {
|
|
1141
|
+
const { taskName, update } = event;
|
|
1142
|
+
const taskConfig = live.config.tasks[taskName];
|
|
1143
|
+
if (!taskConfig) continue;
|
|
1144
|
+
const taskState = live.state.tasks[taskName];
|
|
1145
|
+
if (!taskState || taskState.status !== "running") continue;
|
|
1146
|
+
const callbackToken = encodeCallbackToken(taskName);
|
|
1147
|
+
runPipeline(taskName, callbackToken, update).catch((error) => {
|
|
1148
|
+
if (disposed) return;
|
|
1149
|
+
internalJournal.append({
|
|
1150
|
+
type: "task-failed",
|
|
1151
|
+
taskName,
|
|
1152
|
+
error: error.message ?? String(error),
|
|
1153
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
1154
|
+
});
|
|
1155
|
+
drain();
|
|
1156
|
+
});
|
|
1157
|
+
}
|
|
1158
|
+
}
|
|
1112
1159
|
}
|
|
1113
1160
|
function resolveUpstreamState(taskName) {
|
|
1114
1161
|
const taskConfig = live.config.tasks[taskName];
|
|
@@ -1130,7 +1177,7 @@ function createReactiveGraph(config, options, executionId) {
|
|
|
1130
1177
|
}
|
|
1131
1178
|
return state;
|
|
1132
1179
|
}
|
|
1133
|
-
async function runPipeline(taskName, callbackToken) {
|
|
1180
|
+
async function runPipeline(taskName, callbackToken, update) {
|
|
1134
1181
|
const taskConfig = live.config.tasks[taskName];
|
|
1135
1182
|
const handlerNames = taskConfig.taskHandlers ?? [];
|
|
1136
1183
|
const upstreamState = resolveUpstreamState(taskName);
|
|
@@ -1144,7 +1191,8 @@ function createReactiveGraph(config, options, executionId) {
|
|
|
1144
1191
|
state: upstreamState,
|
|
1145
1192
|
taskState: live.state.tasks[taskName],
|
|
1146
1193
|
config: taskConfig,
|
|
1147
|
-
callbackToken
|
|
1194
|
+
callbackToken,
|
|
1195
|
+
update
|
|
1148
1196
|
};
|
|
1149
1197
|
const status = await handler(input);
|
|
1150
1198
|
if (status === "task-initiate-failure") {
|
|
@@ -1158,15 +1206,16 @@ function createReactiveGraph(config, options, executionId) {
|
|
|
1158
1206
|
if (!handlerNames || handlerNames.length === 0) {
|
|
1159
1207
|
return;
|
|
1160
1208
|
}
|
|
1161
|
-
|
|
1209
|
+
internalJournal.append({
|
|
1162
1210
|
type: "task-started",
|
|
1163
1211
|
taskName,
|
|
1164
1212
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
1165
1213
|
});
|
|
1214
|
+
drain();
|
|
1166
1215
|
const callbackToken = encodeCallbackToken(taskName);
|
|
1167
1216
|
runPipeline(taskName, callbackToken).catch((error) => {
|
|
1168
1217
|
if (disposed) return;
|
|
1169
|
-
|
|
1218
|
+
internalJournal.append({
|
|
1170
1219
|
type: "task-failed",
|
|
1171
1220
|
taskName,
|
|
1172
1221
|
error: error.message ?? String(error),
|
|
@@ -1181,16 +1230,16 @@ function createReactiveGraph(config, options, executionId) {
|
|
|
1181
1230
|
if (event.type === "task-completed" && event.data && !event.dataHash) {
|
|
1182
1231
|
event = { ...event, dataHash: computeDataHash(event.data) };
|
|
1183
1232
|
}
|
|
1184
|
-
|
|
1233
|
+
inputQueue.append(event);
|
|
1185
1234
|
drain();
|
|
1186
1235
|
},
|
|
1187
1236
|
pushAll(events) {
|
|
1188
1237
|
if (disposed) return;
|
|
1189
1238
|
for (const event of events) {
|
|
1190
1239
|
if (event.type === "task-completed" && event.data && !event.dataHash) {
|
|
1191
|
-
|
|
1240
|
+
inputQueue.append({ ...event, dataHash: computeDataHash(event.data) });
|
|
1192
1241
|
} else {
|
|
1193
|
-
|
|
1242
|
+
inputQueue.append(event);
|
|
1194
1243
|
}
|
|
1195
1244
|
}
|
|
1196
1245
|
drain();
|
|
@@ -1202,7 +1251,7 @@ function createReactiveGraph(config, options, executionId) {
|
|
|
1202
1251
|
const { taskName } = decoded;
|
|
1203
1252
|
if (!live.config.tasks[taskName]) return;
|
|
1204
1253
|
if (errors && errors.length > 0) {
|
|
1205
|
-
|
|
1254
|
+
inputQueue.append({
|
|
1206
1255
|
type: "task-failed",
|
|
1207
1256
|
taskName,
|
|
1208
1257
|
error: errors.join("; "),
|
|
@@ -1210,7 +1259,7 @@ function createReactiveGraph(config, options, executionId) {
|
|
|
1210
1259
|
});
|
|
1211
1260
|
} else {
|
|
1212
1261
|
const dataHash = data && Object.keys(data).length > 0 ? computeDataHash(data) : void 0;
|
|
1213
|
-
|
|
1262
|
+
inputQueue.append({
|
|
1214
1263
|
type: "task-completed",
|
|
1215
1264
|
taskName,
|
|
1216
1265
|
data,
|
|
@@ -1222,31 +1271,33 @@ function createReactiveGraph(config, options, executionId) {
|
|
|
1222
1271
|
},
|
|
1223
1272
|
addNode(name, taskConfig) {
|
|
1224
1273
|
if (disposed) return;
|
|
1225
|
-
|
|
1274
|
+
inputQueue.append({ type: "task-upsert", taskName: name, taskConfig, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
|
|
1226
1275
|
drain();
|
|
1227
1276
|
},
|
|
1228
1277
|
removeNode(name) {
|
|
1229
1278
|
if (disposed) return;
|
|
1230
|
-
|
|
1279
|
+
inputQueue.append({ type: "task-removal", taskName: name, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
|
|
1280
|
+
drain();
|
|
1231
1281
|
},
|
|
1232
1282
|
addRequires(nodeName, tokens) {
|
|
1233
1283
|
if (disposed) return;
|
|
1234
|
-
|
|
1284
|
+
inputQueue.append({ type: "node-requires-add", nodeName, tokens, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
|
|
1235
1285
|
drain();
|
|
1236
1286
|
},
|
|
1237
1287
|
removeRequires(nodeName, tokens) {
|
|
1238
1288
|
if (disposed) return;
|
|
1239
|
-
|
|
1289
|
+
inputQueue.append({ type: "node-requires-remove", nodeName, tokens, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
|
|
1240
1290
|
drain();
|
|
1241
1291
|
},
|
|
1242
1292
|
addProvides(nodeName, tokens) {
|
|
1243
1293
|
if (disposed) return;
|
|
1244
|
-
|
|
1294
|
+
inputQueue.append({ type: "node-provides-add", nodeName, tokens, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
|
|
1245
1295
|
drain();
|
|
1246
1296
|
},
|
|
1247
1297
|
removeProvides(nodeName, tokens) {
|
|
1248
1298
|
if (disposed) return;
|
|
1249
|
-
|
|
1299
|
+
inputQueue.append({ type: "node-provides-remove", nodeName, tokens, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
|
|
1300
|
+
drain();
|
|
1250
1301
|
},
|
|
1251
1302
|
registerHandler(name, fn) {
|
|
1252
1303
|
handlers.set(name, fn);
|
|
@@ -1257,7 +1308,7 @@ function createReactiveGraph(config, options, executionId) {
|
|
|
1257
1308
|
retrigger(taskName) {
|
|
1258
1309
|
if (disposed) return;
|
|
1259
1310
|
if (!live.config.tasks[taskName]) return;
|
|
1260
|
-
|
|
1311
|
+
inputQueue.append({
|
|
1261
1312
|
type: "task-restart",
|
|
1262
1313
|
taskName,
|
|
1263
1314
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
@@ -1268,7 +1319,7 @@ function createReactiveGraph(config, options, executionId) {
|
|
|
1268
1319
|
if (disposed) return;
|
|
1269
1320
|
for (const name of taskNames) {
|
|
1270
1321
|
if (!live.config.tasks[name]) continue;
|
|
1271
|
-
|
|
1322
|
+
inputQueue.append({
|
|
1272
1323
|
type: "task-restart",
|
|
1273
1324
|
taskName: name,
|
|
1274
1325
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
@@ -1276,6 +1327,9 @@ function createReactiveGraph(config, options, executionId) {
|
|
|
1276
1327
|
}
|
|
1277
1328
|
drain();
|
|
1278
1329
|
},
|
|
1330
|
+
snapshot() {
|
|
1331
|
+
return snapshot(live);
|
|
1332
|
+
},
|
|
1279
1333
|
getState() {
|
|
1280
1334
|
return live;
|
|
1281
1335
|
},
|
|
@@ -1659,288 +1713,43 @@ function deepSet(obj, path, value) {
|
|
|
1659
1713
|
}
|
|
1660
1714
|
cur[parts[parts.length - 1]] = value;
|
|
1661
1715
|
}
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
};
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
const
|
|
1674
|
-
const vals = opts.field ? a.map((r) => Number(r[opts.field])) : a.map(Number);
|
|
1675
|
-
return vals.length ? Math.min(...vals) : 0;
|
|
1676
|
-
};
|
|
1677
|
-
_fns.max = (input, _e, opts) => {
|
|
1678
|
-
const a = Array.isArray(input) ? input : [];
|
|
1679
|
-
const vals = opts.field ? a.map((r) => Number(r[opts.field])) : a.map(Number);
|
|
1680
|
-
return vals.length ? Math.max(...vals) : 0;
|
|
1681
|
-
};
|
|
1682
|
-
_fns.count = (input) => Array.isArray(input) ? input.length : input != null ? 1 : 0;
|
|
1683
|
-
_fns.first = (input) => Array.isArray(input) ? input[0] : input;
|
|
1684
|
-
_fns.last = (input) => Array.isArray(input) ? input[input.length - 1] : input;
|
|
1685
|
-
_fns.add = (input) => {
|
|
1686
|
-
const a = Array.isArray(input) ? input : [];
|
|
1687
|
-
return a.reduce((s, v) => s + Number(v), 0);
|
|
1688
|
-
};
|
|
1689
|
-
_fns.sub = (input) => {
|
|
1690
|
-
const a = Array.isArray(input) ? input : [];
|
|
1691
|
-
return a.length >= 2 ? Number(a[0]) - Number(a[1]) : 0;
|
|
1692
|
-
};
|
|
1693
|
-
_fns.mul = (input) => {
|
|
1694
|
-
const a = Array.isArray(input) ? input : [];
|
|
1695
|
-
return a.reduce((s, v) => s * Number(v), 1);
|
|
1696
|
-
};
|
|
1697
|
-
_fns.div = (input) => {
|
|
1698
|
-
const a = Array.isArray(input) ? input : [];
|
|
1699
|
-
return a.length >= 2 && Number(a[1]) !== 0 ? Number(a[0]) / Number(a[1]) : 0;
|
|
1700
|
-
};
|
|
1701
|
-
_fns.round = (input, _e, opts) => {
|
|
1702
|
-
const decimals = opts.decimals != null ? opts.decimals : 0;
|
|
1703
|
-
const factor = Math.pow(10, decimals);
|
|
1704
|
-
return Math.round(Number(input) * factor) / factor;
|
|
1705
|
-
};
|
|
1706
|
-
_fns.abs = (input) => Math.abs(Number(input));
|
|
1707
|
-
_fns.mod = (input) => {
|
|
1708
|
-
const a = Array.isArray(input) ? input : [];
|
|
1709
|
-
return a.length >= 2 ? Number(a[0]) % Number(a[1]) : 0;
|
|
1710
|
-
};
|
|
1711
|
-
_fns.gt = (input) => {
|
|
1712
|
-
const a = Array.isArray(input) ? input : [];
|
|
1713
|
-
return a.length >= 2 && Number(a[0]) > Number(a[1]);
|
|
1714
|
-
};
|
|
1715
|
-
_fns.gte = (input) => {
|
|
1716
|
-
const a = Array.isArray(input) ? input : [];
|
|
1717
|
-
return a.length >= 2 && Number(a[0]) >= Number(a[1]);
|
|
1718
|
-
};
|
|
1719
|
-
_fns.lt = (input) => {
|
|
1720
|
-
const a = Array.isArray(input) ? input : [];
|
|
1721
|
-
return a.length >= 2 && Number(a[0]) < Number(a[1]);
|
|
1722
|
-
};
|
|
1723
|
-
_fns.lte = (input) => {
|
|
1724
|
-
const a = Array.isArray(input) ? input : [];
|
|
1725
|
-
return a.length >= 2 && Number(a[0]) <= Number(a[1]);
|
|
1726
|
-
};
|
|
1727
|
-
_fns.eq = (input) => {
|
|
1728
|
-
const a = Array.isArray(input) ? input : [];
|
|
1729
|
-
return a.length >= 2 && a[0] === a[1];
|
|
1730
|
-
};
|
|
1731
|
-
_fns.neq = (input) => {
|
|
1732
|
-
const a = Array.isArray(input) ? input : [];
|
|
1733
|
-
return a.length >= 2 && a[0] !== a[1];
|
|
1734
|
-
};
|
|
1735
|
-
_fns.and = (input) => {
|
|
1736
|
-
const a = Array.isArray(input) ? input : [];
|
|
1737
|
-
return a.every(Boolean);
|
|
1738
|
-
};
|
|
1739
|
-
_fns.or = (input) => {
|
|
1740
|
-
const a = Array.isArray(input) ? input : [];
|
|
1741
|
-
return a.some(Boolean);
|
|
1742
|
-
};
|
|
1743
|
-
_fns.not = (input) => !input;
|
|
1744
|
-
_fns.concat = (input) => {
|
|
1745
|
-
const a = Array.isArray(input) ? input : [];
|
|
1746
|
-
return a.map((v) => v != null ? String(v) : "").join("");
|
|
1747
|
-
};
|
|
1748
|
-
_fns.upper = (input) => String(input || "").toUpperCase();
|
|
1749
|
-
_fns.lower = (input) => String(input || "").toLowerCase();
|
|
1750
|
-
_fns.template = (input, _e, opts) => {
|
|
1751
|
-
let t = String(opts.format || "");
|
|
1752
|
-
if (input && typeof input === "object" && !Array.isArray(input)) {
|
|
1753
|
-
for (const k of Object.keys(input)) {
|
|
1754
|
-
const v = input[k];
|
|
1755
|
-
t = t.split("{{" + k + "}}").join(v != null ? String(v) : "");
|
|
1756
|
-
}
|
|
1757
|
-
}
|
|
1758
|
-
return t;
|
|
1759
|
-
};
|
|
1760
|
-
_fns.join = (input, _e, opts) => {
|
|
1761
|
-
const a = Array.isArray(input) ? input : [];
|
|
1762
|
-
const sep = opts.separator != null ? String(opts.separator) : ", ";
|
|
1763
|
-
return a.map((v) => v != null ? String(v) : "").join(sep);
|
|
1764
|
-
};
|
|
1765
|
-
_fns.split = (input, _e, opts) => {
|
|
1766
|
-
const sep = opts.separator != null ? String(opts.separator) : ",";
|
|
1767
|
-
return String(input || "").split(sep).map((s) => s.trim());
|
|
1768
|
-
};
|
|
1769
|
-
_fns.trim = (input) => String(input || "").trim();
|
|
1770
|
-
_fns.pluck = (input, _e, opts) => Array.isArray(input) ? input.map((r) => r[opts.field]) : [];
|
|
1771
|
-
_fns.filter = (input, _e, opts) => {
|
|
1772
|
-
if (!Array.isArray(input)) return [];
|
|
1773
|
-
if (opts.field) return input.filter((r) => !!r[opts.field]);
|
|
1774
|
-
return input.filter(Boolean);
|
|
1775
|
-
};
|
|
1776
|
-
_fns.map = (input) => Array.isArray(input) ? input.slice() : [];
|
|
1777
|
-
_fns.sort = (input, _e, opts) => {
|
|
1778
|
-
const a = Array.isArray(input) ? input.slice() : [];
|
|
1779
|
-
const f = opts.field;
|
|
1780
|
-
const dir = opts.direction === "desc" ? -1 : 1;
|
|
1781
|
-
if (f) return a.sort((x, y) => x[f] > y[f] ? dir : x[f] < y[f] ? -dir : 0);
|
|
1782
|
-
return a.sort((x, y) => x > y ? dir : x < y ? -dir : 0);
|
|
1783
|
-
};
|
|
1784
|
-
_fns.slice = (input, _e, opts) => Array.isArray(input) ? input.slice(opts.start || 0, opts.end) : input;
|
|
1785
|
-
_fns.flat = (input, _e, opts) => {
|
|
1786
|
-
const depth = opts.depth != null ? opts.depth : 1;
|
|
1787
|
-
return Array.isArray(input) ? input.flat(depth) : [input];
|
|
1788
|
-
};
|
|
1789
|
-
_fns.unique = (input) => {
|
|
1790
|
-
if (!Array.isArray(input)) return [input];
|
|
1791
|
-
const seen = /* @__PURE__ */ new Set();
|
|
1792
|
-
return input.filter((v) => {
|
|
1793
|
-
const key = typeof v === "object" ? JSON.stringify(v) : v;
|
|
1794
|
-
if (seen.has(key)) return false;
|
|
1795
|
-
seen.add(key);
|
|
1796
|
-
return true;
|
|
1797
|
-
});
|
|
1798
|
-
};
|
|
1799
|
-
_fns.group = (input, _e, opts) => {
|
|
1800
|
-
const a = Array.isArray(input) ? input : [];
|
|
1801
|
-
const g = {};
|
|
1802
|
-
a.forEach((r) => {
|
|
1803
|
-
const k = String(r[opts.field] || "");
|
|
1804
|
-
if (!g[k]) g[k] = [];
|
|
1805
|
-
g[k].push(r);
|
|
1806
|
-
});
|
|
1807
|
-
return g;
|
|
1808
|
-
};
|
|
1809
|
-
_fns.flatten_keys = (input) => {
|
|
1810
|
-
if (!input || typeof input !== "object" || Array.isArray(input)) return [];
|
|
1811
|
-
const result = [];
|
|
1812
|
-
for (const k of Object.keys(input)) {
|
|
1813
|
-
const vals = Array.isArray(input[k]) ? input[k] : [input[k]];
|
|
1814
|
-
vals.forEach((v) => result.push({ key: k, value: v }));
|
|
1815
|
-
}
|
|
1816
|
-
return result;
|
|
1817
|
-
};
|
|
1818
|
-
_fns.entries = (input) => {
|
|
1819
|
-
if (!input || typeof input !== "object" || Array.isArray(input)) return [];
|
|
1820
|
-
return Object.keys(input).map((k) => ({ key: k, value: input[k] }));
|
|
1821
|
-
};
|
|
1822
|
-
_fns.from_entries = (input) => {
|
|
1823
|
-
if (!Array.isArray(input)) return {};
|
|
1824
|
-
const obj = {};
|
|
1825
|
-
input.forEach((item) => {
|
|
1826
|
-
if (item.key != null) obj[item.key] = item.value;
|
|
1827
|
-
});
|
|
1828
|
-
return obj;
|
|
1829
|
-
};
|
|
1830
|
-
_fns.length = (input) => {
|
|
1831
|
-
if (Array.isArray(input)) return input.length;
|
|
1832
|
-
if (typeof input === "string") return input.length;
|
|
1833
|
-
if (input && typeof input === "object") return Object.keys(input).length;
|
|
1834
|
-
return 0;
|
|
1835
|
-
};
|
|
1836
|
-
_fns.get = (input, _e, opts) => deepGet(input, opts.field || opts.path || "");
|
|
1837
|
-
_fns.default = (input, _e, opts) => input != null ? input : opts.value;
|
|
1838
|
-
_fns.coalesce = (input) => {
|
|
1839
|
-
const a = Array.isArray(input) ? input : [];
|
|
1840
|
-
for (let i = 0; i < a.length; i++) {
|
|
1841
|
-
if (a[i] != null) return a[i];
|
|
1842
|
-
}
|
|
1843
|
-
return null;
|
|
1844
|
-
};
|
|
1845
|
-
_fns.now = () => (/* @__PURE__ */ new Date()).toISOString();
|
|
1846
|
-
_fns.diff_days = (input) => {
|
|
1847
|
-
const a = Array.isArray(input) ? input : [];
|
|
1848
|
-
return a.length >= 2 ? Math.floor((new Date(a[0]).getTime() - new Date(a[1]).getTime()) / 864e5) : 0;
|
|
1849
|
-
};
|
|
1850
|
-
_fns.format_date = (input, _e, opts) => {
|
|
1851
|
-
try {
|
|
1852
|
-
const d = new Date(input);
|
|
1853
|
-
if (opts.format === "iso") return d.toISOString();
|
|
1854
|
-
if (opts.format === "date") return d.toLocaleDateString();
|
|
1855
|
-
if (opts.format === "time") return d.toLocaleTimeString();
|
|
1856
|
-
return d.toLocaleDateString();
|
|
1857
|
-
} catch {
|
|
1858
|
-
return String(input);
|
|
1859
|
-
}
|
|
1860
|
-
};
|
|
1861
|
-
_fns.parse_date = (input) => {
|
|
1862
|
-
try {
|
|
1863
|
-
return new Date(input).toISOString();
|
|
1864
|
-
} catch {
|
|
1865
|
-
return null;
|
|
1866
|
-
}
|
|
1867
|
-
};
|
|
1868
|
-
_fns.to_number = (input) => Number(input) || 0;
|
|
1869
|
-
_fns.to_string = (input) => input != null ? String(input) : "";
|
|
1870
|
-
_fns.to_bool = (input) => !!input;
|
|
1871
|
-
_fns.type_of = (input) => Array.isArray(input) ? "array" : typeof input;
|
|
1872
|
-
_fns.is_null = (input) => input == null;
|
|
1873
|
-
_fns.is_empty = (input) => {
|
|
1874
|
-
if (input == null) return true;
|
|
1875
|
-
if (Array.isArray(input)) return input.length === 0;
|
|
1876
|
-
if (typeof input === "string") return input.length === 0;
|
|
1877
|
-
if (typeof input === "object") return Object.keys(input).length === 0;
|
|
1878
|
-
return false;
|
|
1879
|
-
};
|
|
1880
|
-
var _customFns = {};
|
|
1881
|
-
function evalExpr(expr, node) {
|
|
1882
|
-
if (expr == null) return expr;
|
|
1883
|
-
if (typeof expr !== "object" || Array.isArray(expr)) return expr;
|
|
1884
|
-
const e = expr;
|
|
1885
|
-
if (!e.fn) return expr;
|
|
1886
|
-
let input = e.input;
|
|
1887
|
-
if (typeof input === "string" && input.startsWith("state.")) {
|
|
1888
|
-
input = deepGet(node, input);
|
|
1889
|
-
} else if (Array.isArray(input)) {
|
|
1890
|
-
input = input.map((v) => {
|
|
1891
|
-
if (typeof v === "string" && v.startsWith("state.")) return deepGet(node, v);
|
|
1892
|
-
if (v && typeof v === "object" && v.fn) return evalExpr(v, node);
|
|
1893
|
-
return v;
|
|
1894
|
-
});
|
|
1895
|
-
} else if (input && typeof input === "object" && input.fn) {
|
|
1896
|
-
input = evalExpr(input, node);
|
|
1897
|
-
}
|
|
1898
|
-
if (e.fn === "if") {
|
|
1899
|
-
const cond = evalExpr(e.cond, node);
|
|
1900
|
-
if (cond) {
|
|
1901
|
-
return e.then && typeof e.then === "object" && e.then.fn ? evalExpr(e.then, node) : e.then;
|
|
1902
|
-
} else {
|
|
1903
|
-
return e.else && typeof e.else === "object" && e.else.fn ? evalExpr(e.else, node) : e.else;
|
|
1904
|
-
}
|
|
1905
|
-
}
|
|
1906
|
-
if (e.fn === "filter" && Array.isArray(input) && e.where) {
|
|
1907
|
-
return input.filter((item) => {
|
|
1908
|
-
const tmp = { state: { ...node.state, $: item } };
|
|
1909
|
-
return evalExpr(e.where, tmp);
|
|
1910
|
-
});
|
|
1911
|
-
}
|
|
1912
|
-
if (e.fn === "map" && Array.isArray(input) && e.apply) {
|
|
1913
|
-
return input.map((item) => {
|
|
1914
|
-
const tmp = { state: { ...node.state, $: item } };
|
|
1915
|
-
return evalExpr(e.apply, tmp);
|
|
1916
|
-
});
|
|
1917
|
-
}
|
|
1918
|
-
const fn = _customFns[e.fn] || _fns[e.fn];
|
|
1919
|
-
if (!fn) {
|
|
1920
|
-
console.warn('CardCompute: unknown function "' + e.fn + '"');
|
|
1921
|
-
return void 0;
|
|
1922
|
-
}
|
|
1923
|
-
return fn(input, evalExpr, e);
|
|
1924
|
-
}
|
|
1925
|
-
function run(node) {
|
|
1926
|
-
if (!node || !node.compute) return node;
|
|
1927
|
-
if (!node.state) node.state = {};
|
|
1928
|
-
for (const key of Object.keys(node.compute)) {
|
|
1716
|
+
async function run(node, options) {
|
|
1717
|
+
if (!node?.compute?.length) return node;
|
|
1718
|
+
if (!node.card_data) node.card_data = {};
|
|
1719
|
+
node.computed_values = {};
|
|
1720
|
+
node._sourcesData = options?.sourcesData ?? {};
|
|
1721
|
+
const ctx = {
|
|
1722
|
+
card_data: node.card_data,
|
|
1723
|
+
requires: node.requires ?? {},
|
|
1724
|
+
fetched_sources: node._sourcesData,
|
|
1725
|
+
computed_values: node.computed_values
|
|
1726
|
+
};
|
|
1727
|
+
for (const step of node.compute) {
|
|
1929
1728
|
try {
|
|
1930
|
-
const val =
|
|
1931
|
-
deepSet(node.
|
|
1729
|
+
const val = await jsonata2__default.default(step.expr).evaluate(ctx);
|
|
1730
|
+
deepSet(node.computed_values, step.bindTo, val);
|
|
1731
|
+
ctx.computed_values = node.computed_values;
|
|
1932
1732
|
} catch (err) {
|
|
1933
|
-
console.error(`CardCompute.run error on "${node.id
|
|
1733
|
+
console.error(`CardCompute.run error on "${node.id ?? "?"}.${step.bindTo}":`, err);
|
|
1934
1734
|
}
|
|
1935
1735
|
}
|
|
1936
1736
|
return node;
|
|
1937
1737
|
}
|
|
1738
|
+
async function evalExpr(expr, node) {
|
|
1739
|
+
const ctx = {
|
|
1740
|
+
card_data: node.card_data ?? {},
|
|
1741
|
+
requires: node.requires ?? {},
|
|
1742
|
+
fetched_sources: node._sourcesData ?? {},
|
|
1743
|
+
computed_values: node.computed_values ?? {}
|
|
1744
|
+
};
|
|
1745
|
+
return jsonata2__default.default(expr).evaluate(ctx);
|
|
1746
|
+
}
|
|
1938
1747
|
function resolve(node, path) {
|
|
1748
|
+
if (path.startsWith("fetched_sources.")) {
|
|
1749
|
+
return deepGet(node._sourcesData ?? {}, path.slice("fetched_sources.".length));
|
|
1750
|
+
}
|
|
1939
1751
|
return deepGet(node, path);
|
|
1940
1752
|
}
|
|
1941
|
-
function registerFunction(name, fn) {
|
|
1942
|
-
_customFns[name] = fn;
|
|
1943
|
-
}
|
|
1944
1753
|
var VALID_ELEMENT_KINDS = /* @__PURE__ */ new Set([
|
|
1945
1754
|
"metric",
|
|
1946
1755
|
"table",
|
|
@@ -1957,34 +1766,19 @@ var VALID_ELEMENT_KINDS = /* @__PURE__ */ new Set([
|
|
|
1957
1766
|
"markdown",
|
|
1958
1767
|
"custom"
|
|
1959
1768
|
]);
|
|
1960
|
-
var
|
|
1961
|
-
var VALID_STATUSES = /* @__PURE__ */ new Set(["fresh", "stale", "loading", "error"]);
|
|
1962
|
-
var CARD_ALLOWED_KEYS = /* @__PURE__ */ new Set(["id", "type", "meta", "data", "view", "state", "compute"]);
|
|
1963
|
-
var SOURCE_ALLOWED_KEYS = /* @__PURE__ */ new Set(["id", "type", "meta", "data", "source", "state", "compute"]);
|
|
1769
|
+
var ALLOWED_KEYS = /* @__PURE__ */ new Set(["id", "meta", "requires", "provides", "view", "card_data", "compute", "sources"]);
|
|
1964
1770
|
function validateNode(node) {
|
|
1965
1771
|
const errors = [];
|
|
1966
1772
|
if (!node || typeof node !== "object" || Array.isArray(node)) {
|
|
1967
1773
|
return { ok: false, errors: ["Node must be a non-null object"] };
|
|
1968
1774
|
}
|
|
1969
1775
|
const n = node;
|
|
1970
|
-
if (typeof n.id !== "string" || !n.id)
|
|
1971
|
-
errors.push("id: required, must be a non-empty string");
|
|
1972
|
-
}
|
|
1973
|
-
if (n.type !== "card" && n.type !== "source") {
|
|
1974
|
-
errors.push('type: must be "card" or "source"');
|
|
1975
|
-
return { ok: false, errors };
|
|
1976
|
-
}
|
|
1977
|
-
const allowed = n.type === "card" ? CARD_ALLOWED_KEYS : SOURCE_ALLOWED_KEYS;
|
|
1776
|
+
if (typeof n.id !== "string" || !n.id) errors.push("id: required, must be a non-empty string");
|
|
1978
1777
|
for (const key of Object.keys(n)) {
|
|
1979
|
-
if (!
|
|
1778
|
+
if (!ALLOWED_KEYS.has(key)) errors.push(`Unknown top-level key: "${key}"`);
|
|
1980
1779
|
}
|
|
1981
|
-
if (n.
|
|
1982
|
-
errors.push("
|
|
1983
|
-
} else {
|
|
1984
|
-
const state = n.state;
|
|
1985
|
-
if (state.status != null && !VALID_STATUSES.has(state.status)) {
|
|
1986
|
-
errors.push(`state.status: must be one of: ${[...VALID_STATUSES].join(", ")}`);
|
|
1987
|
-
}
|
|
1780
|
+
if (n.card_data == null || typeof n.card_data !== "object" || Array.isArray(n.card_data)) {
|
|
1781
|
+
errors.push("card_data: required, must be an object");
|
|
1988
1782
|
}
|
|
1989
1783
|
if (n.meta != null) {
|
|
1990
1784
|
if (typeof n.meta !== "object" || Array.isArray(n.meta)) {
|
|
@@ -1995,37 +1789,58 @@ function validateNode(node) {
|
|
|
1995
1789
|
if (meta.tags != null && !Array.isArray(meta.tags)) errors.push("meta.tags: must be an array");
|
|
1996
1790
|
}
|
|
1997
1791
|
}
|
|
1998
|
-
if (n.
|
|
1999
|
-
|
|
2000
|
-
|
|
1792
|
+
if (n.requires != null && !Array.isArray(n.requires)) errors.push("requires: must be an array of strings");
|
|
1793
|
+
if (n.provides != null) {
|
|
1794
|
+
if (!Array.isArray(n.provides)) {
|
|
1795
|
+
errors.push("provides: must be an array of { bindTo, src } bindings");
|
|
2001
1796
|
} else {
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
1797
|
+
n.provides.forEach((p, i) => {
|
|
1798
|
+
if (!p || typeof p !== "object" || Array.isArray(p)) {
|
|
1799
|
+
errors.push(`provides[${i}]: must be an object with bindTo and src`);
|
|
1800
|
+
} else {
|
|
1801
|
+
const b = p;
|
|
1802
|
+
if (typeof b.bindTo !== "string" || !b.bindTo) errors.push(`provides[${i}]: missing required "bindTo" string`);
|
|
1803
|
+
if (typeof b.src !== "string" || !b.src) errors.push(`provides[${i}]: missing required "src" string`);
|
|
1804
|
+
}
|
|
1805
|
+
});
|
|
2005
1806
|
}
|
|
2006
1807
|
}
|
|
2007
1808
|
if (n.compute != null) {
|
|
2008
|
-
if (
|
|
2009
|
-
errors.push("compute: must be an
|
|
1809
|
+
if (!Array.isArray(n.compute)) {
|
|
1810
|
+
errors.push("compute: must be an array of compute steps");
|
|
1811
|
+
} else {
|
|
1812
|
+
n.compute.forEach((step, i) => {
|
|
1813
|
+
if (!step || typeof step !== "object" || Array.isArray(step)) {
|
|
1814
|
+
errors.push(`compute[${i}]: must be a compute step object`);
|
|
1815
|
+
} else {
|
|
1816
|
+
const s = step;
|
|
1817
|
+
if (typeof s.bindTo !== "string" || !s.bindTo) errors.push(`compute[${i}]: missing required "bindTo" property`);
|
|
1818
|
+
if (typeof s.expr !== "string" || !s.expr) errors.push(`compute[${i}]: missing required "expr" string (JSONata expression)`);
|
|
1819
|
+
}
|
|
1820
|
+
});
|
|
1821
|
+
}
|
|
1822
|
+
}
|
|
1823
|
+
if (n.sources != null) {
|
|
1824
|
+
if (!Array.isArray(n.sources)) {
|
|
1825
|
+
errors.push("sources: must be an array");
|
|
2010
1826
|
} else {
|
|
2011
|
-
|
|
2012
|
-
if (!
|
|
2013
|
-
errors.push(`
|
|
2014
|
-
} else if (!expr.fn) {
|
|
2015
|
-
errors.push(`compute.${key}: missing required "fn" property`);
|
|
1827
|
+
n.sources.forEach((src, i) => {
|
|
1828
|
+
if (!src || typeof src !== "object" || Array.isArray(src)) {
|
|
1829
|
+
errors.push(`sources[${i}]: must be an object`);
|
|
2016
1830
|
} else {
|
|
2017
|
-
const
|
|
2018
|
-
if (!
|
|
2019
|
-
|
|
1831
|
+
const s = src;
|
|
1832
|
+
if (typeof s.bindTo !== "string" || !s.bindTo) errors.push(`sources[${i}]: missing required "bindTo" property`);
|
|
1833
|
+
if (s.outputFile != null && typeof s.outputFile !== "string") errors.push(`sources[${i}]: outputFile must be a string`);
|
|
1834
|
+
if (s.optionalForCompletionGating != null && typeof s.optionalForCompletionGating !== "boolean") {
|
|
1835
|
+
errors.push(`sources[${i}]: optionalForCompletionGating must be a boolean`);
|
|
2020
1836
|
}
|
|
2021
1837
|
}
|
|
2022
|
-
}
|
|
1838
|
+
});
|
|
2023
1839
|
}
|
|
2024
1840
|
}
|
|
2025
|
-
if (n.
|
|
2026
|
-
if (n.
|
|
2027
|
-
|
|
2028
|
-
errors.push("view: required for card nodes, must be an object");
|
|
1841
|
+
if (n.view != null) {
|
|
1842
|
+
if (typeof n.view !== "object" || Array.isArray(n.view)) {
|
|
1843
|
+
errors.push("view: must be an object");
|
|
2029
1844
|
} else {
|
|
2030
1845
|
const view = n.view;
|
|
2031
1846
|
if (!Array.isArray(view.elements) || view.elements.length === 0) {
|
|
@@ -2046,44 +1861,27 @@ function validateNode(node) {
|
|
|
2046
1861
|
}
|
|
2047
1862
|
});
|
|
2048
1863
|
}
|
|
2049
|
-
if (view.layout != null && (typeof view.layout !== "object" || Array.isArray(view.layout)))
|
|
2050
|
-
|
|
2051
|
-
}
|
|
2052
|
-
if (view.features != null && (typeof view.features !== "object" || Array.isArray(view.features))) {
|
|
2053
|
-
errors.push("view.features: must be an object");
|
|
2054
|
-
}
|
|
2055
|
-
}
|
|
2056
|
-
}
|
|
2057
|
-
if (n.type === "source") {
|
|
2058
|
-
if (n.view != null) errors.push('Source nodes must not have "view" \u2014 use type "card" instead');
|
|
2059
|
-
if (n.source == null || typeof n.source !== "object" || Array.isArray(n.source)) {
|
|
2060
|
-
errors.push("source: required for source nodes, must be an object");
|
|
2061
|
-
} else {
|
|
2062
|
-
const src = n.source;
|
|
2063
|
-
if (!src.kind || !VALID_SOURCE_KINDS.has(src.kind)) {
|
|
2064
|
-
errors.push(`source.kind: required, must be one of: ${[...VALID_SOURCE_KINDS].join(", ")}`);
|
|
2065
|
-
}
|
|
2066
|
-
if (typeof src.bindTo !== "string" || !src.bindTo) {
|
|
2067
|
-
errors.push("source.bindTo: required, must be a state path string");
|
|
2068
|
-
} else if (!src.bindTo.startsWith("state.")) {
|
|
2069
|
-
errors.push('source.bindTo: must start with "state."');
|
|
2070
|
-
}
|
|
1864
|
+
if (view.layout != null && (typeof view.layout !== "object" || Array.isArray(view.layout))) errors.push("view.layout: must be an object");
|
|
1865
|
+
if (view.features != null && (typeof view.features !== "object" || Array.isArray(view.features))) errors.push("view.features: must be an object");
|
|
2071
1866
|
}
|
|
2072
1867
|
}
|
|
2073
1868
|
return { ok: errors.length === 0, errors };
|
|
2074
1869
|
}
|
|
1870
|
+
function enrichSources(sources, context) {
|
|
1871
|
+
if (!sources || sources.length === 0) return [];
|
|
1872
|
+
return sources.map((src) => ({
|
|
1873
|
+
...src,
|
|
1874
|
+
_requires: context.requires ?? {},
|
|
1875
|
+
_sourcesData: context.sourcesData ?? {},
|
|
1876
|
+
_computed_values: context.computed_values ?? {}
|
|
1877
|
+
}));
|
|
1878
|
+
}
|
|
2075
1879
|
var CardCompute = {
|
|
2076
1880
|
run,
|
|
2077
1881
|
eval: evalExpr,
|
|
2078
1882
|
resolve,
|
|
2079
1883
|
validate: validateNode,
|
|
2080
|
-
|
|
2081
|
-
get functions() {
|
|
2082
|
-
const all = {};
|
|
2083
|
-
for (const k of Object.keys(_fns)) all[k] = _fns[k];
|
|
2084
|
-
for (const k of Object.keys(_customFns)) all[k] = _customFns[k];
|
|
2085
|
-
return all;
|
|
2086
|
-
}
|
|
1884
|
+
enrichSources
|
|
2087
1885
|
};
|
|
2088
1886
|
|
|
2089
1887
|
// src/continuous-event-graph/live-cards-bridge.ts
|
|
@@ -2116,19 +1914,26 @@ function liveCardsToReactiveGraph(input, options = {}) {
|
|
|
2116
1914
|
}
|
|
2117
1915
|
const sharedState = options.sharedState ?? /* @__PURE__ */ new Map();
|
|
2118
1916
|
const tasks = {};
|
|
1917
|
+
const allTokens = /* @__PURE__ */ new Set();
|
|
1918
|
+
const tokenToCardId = /* @__PURE__ */ new Map();
|
|
1919
|
+
for (const card of cards) {
|
|
1920
|
+
for (const binding of card.provides ?? [{ bindTo: card.id, src: "card_data" }]) {
|
|
1921
|
+
allTokens.add(binding.bindTo);
|
|
1922
|
+
tokenToCardId.set(binding.bindTo, card.id);
|
|
1923
|
+
}
|
|
1924
|
+
}
|
|
2119
1925
|
for (const card of cards) {
|
|
2120
|
-
const requires = card.
|
|
1926
|
+
const requires = card.requires ?? [];
|
|
2121
1927
|
for (const req of requires) {
|
|
2122
|
-
if (!
|
|
2123
|
-
throw new Error(`Card "${card.id}" requires "${req}" but no card
|
|
1928
|
+
if (!allTokens.has(req)) {
|
|
1929
|
+
throw new Error(`Card "${card.id}" requires "${req}" but no card provides that token`);
|
|
2124
1930
|
}
|
|
2125
1931
|
}
|
|
2126
1932
|
tasks[card.id] = {
|
|
2127
1933
|
requires: requires.length > 0 ? requires : void 0,
|
|
2128
|
-
provides: [card.id],
|
|
1934
|
+
provides: (card.provides ?? [{ bindTo: card.id, src: "card_data" }]).map((p) => p.bindTo),
|
|
2129
1935
|
taskHandlers: [card.id],
|
|
2130
|
-
|
|
2131
|
-
description: card.meta?.title ?? `${card.type}: ${card.id}`
|
|
1936
|
+
description: card.meta?.title ?? card.id
|
|
2132
1937
|
};
|
|
2133
1938
|
}
|
|
2134
1939
|
const config = {
|
|
@@ -2147,10 +1952,10 @@ function liveCardsToReactiveGraph(input, options = {}) {
|
|
|
2147
1952
|
graphRef.resolveCallback(token, data, errors);
|
|
2148
1953
|
};
|
|
2149
1954
|
for (const card of cards) {
|
|
2150
|
-
if (card.
|
|
1955
|
+
if (card.sources && card.sources.length > 0) {
|
|
2151
1956
|
handlers[card.id] = buildSourceHandler(card, sourceHandlers, defaultSourceHandler, sharedState, getResolve);
|
|
2152
1957
|
} else {
|
|
2153
|
-
handlers[card.id] = buildCardHandler(card, cardHandlers, sharedState, cardMap, getResolve);
|
|
1958
|
+
handlers[card.id] = buildCardHandler(card, cardHandlers, sharedState, cardMap, tokenToCardId, getResolve);
|
|
2154
1959
|
}
|
|
2155
1960
|
}
|
|
2156
1961
|
const graph = createReactiveGraph(
|
|
@@ -2178,13 +1983,13 @@ function buildSourceHandler(card, sourceHandlers, defaultSourceHandler, sharedSt
|
|
|
2178
1983
|
};
|
|
2179
1984
|
}
|
|
2180
1985
|
return async (input) => {
|
|
2181
|
-
const
|
|
2182
|
-
sharedState.set(card.id,
|
|
2183
|
-
getResolve()(input.callbackToken,
|
|
1986
|
+
const data = { ...card.card_data };
|
|
1987
|
+
sharedState.set(card.id, data);
|
|
1988
|
+
getResolve()(input.callbackToken, data);
|
|
2184
1989
|
return "task-initiated";
|
|
2185
1990
|
};
|
|
2186
1991
|
}
|
|
2187
|
-
function buildCardHandler(card, cardHandlers, sharedState,
|
|
1992
|
+
function buildCardHandler(card, cardHandlers, sharedState, _cardMap, tokenToCardId, getResolve) {
|
|
2188
1993
|
if (cardHandlers[card.id]) {
|
|
2189
1994
|
const userHandler = cardHandlers[card.id];
|
|
2190
1995
|
return async (input) => {
|
|
@@ -2192,49 +1997,38 @@ function buildCardHandler(card, cardHandlers, sharedState, cardMap, getResolve)
|
|
|
2192
1997
|
};
|
|
2193
1998
|
}
|
|
2194
1999
|
return async (input) => {
|
|
2000
|
+
const requiresData = {};
|
|
2001
|
+
const requires = card.requires ?? [];
|
|
2002
|
+
for (const token of requires) {
|
|
2003
|
+
const producerId = tokenToCardId.get(token) ?? token;
|
|
2004
|
+
const upstreamState = sharedState.get(producerId);
|
|
2005
|
+
if (upstreamState) {
|
|
2006
|
+
requiresData[token] = upstreamState[token] ?? upstreamState;
|
|
2007
|
+
}
|
|
2008
|
+
}
|
|
2195
2009
|
const computeNode = {
|
|
2196
2010
|
id: card.id,
|
|
2197
|
-
|
|
2011
|
+
card_data: { ...card.card_data },
|
|
2012
|
+
requires: requiresData,
|
|
2198
2013
|
compute: card.compute
|
|
2199
2014
|
};
|
|
2200
|
-
|
|
2201
|
-
|
|
2202
|
-
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
const upstreamCard = cardMap.get(upstreamId);
|
|
2207
|
-
if (upstreamCard?.data?.provides && upstreamState) {
|
|
2208
|
-
for (const [key, bindRef] of Object.entries(upstreamCard.data.provides)) {
|
|
2209
|
-
if (typeof bindRef === "string" && bindRef.startsWith("state.")) {
|
|
2210
|
-
const path = bindRef.slice(6);
|
|
2211
|
-
const value = deepGet2(upstreamState, path);
|
|
2212
|
-
if (value !== void 0) {
|
|
2213
|
-
computeNode.state[key] = value;
|
|
2214
|
-
}
|
|
2215
|
-
}
|
|
2216
|
-
}
|
|
2015
|
+
await CardCompute.run(computeNode);
|
|
2016
|
+
let resultData;
|
|
2017
|
+
if (card.provides && card.provides.length > 0) {
|
|
2018
|
+
resultData = {};
|
|
2019
|
+
for (const { bindTo, src } of card.provides) {
|
|
2020
|
+
resultData[bindTo] = CardCompute.resolve(computeNode, src);
|
|
2217
2021
|
}
|
|
2022
|
+
} else {
|
|
2023
|
+
resultData = { ...computeNode.card_data, ...computeNode.computed_values };
|
|
2218
2024
|
}
|
|
2219
|
-
|
|
2220
|
-
const resultState = { ...computeNode.state };
|
|
2025
|
+
const resultState = { ...computeNode.card_data, ...computeNode.computed_values };
|
|
2221
2026
|
sharedState.set(card.id, resultState);
|
|
2222
|
-
getResolve()(input.callbackToken,
|
|
2027
|
+
getResolve()(input.callbackToken, resultData);
|
|
2223
2028
|
return "task-initiated";
|
|
2224
2029
|
};
|
|
2225
2030
|
}
|
|
2226
|
-
function deepGet2(obj, path) {
|
|
2227
|
-
if (!path || !obj) return void 0;
|
|
2228
|
-
const parts = path.split(".");
|
|
2229
|
-
let cur = obj;
|
|
2230
|
-
for (const part of parts) {
|
|
2231
|
-
if (cur == null) return void 0;
|
|
2232
|
-
cur = cur[part];
|
|
2233
|
-
}
|
|
2234
|
-
return cur;
|
|
2235
|
-
}
|
|
2236
2031
|
|
|
2237
|
-
exports.FileJournal = FileJournal;
|
|
2238
2032
|
exports.MemoryJournal = MemoryJournal;
|
|
2239
2033
|
exports.addNode = addNode;
|
|
2240
2034
|
exports.addProvides = addProvides;
|