yaml-flow 3.1.0 → 4.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/card-compute.js +132 -431
- package/browser/live-cards.js +41 -27
- package/browser/live-cards.schema.json +59 -77
- package/dist/card-compute/index.cjs +135 -415
- package/dist/card-compute/index.cjs.map +1 -1
- package/dist/card-compute/index.d.cts +52 -49
- package/dist/card-compute/index.d.ts +52 -49
- package/dist/card-compute/index.js +134 -415
- package/dist/card-compute/index.js.map +1 -1
- package/dist/cli/board-live-cards-cli.cjs +2379 -0
- package/dist/cli/board-live-cards-cli.cjs.map +1 -0
- package/dist/cli/board-live-cards-cli.d.cts +213 -0
- package/dist/cli/board-live-cards-cli.d.ts +213 -0
- package/dist/cli/board-live-cards-cli.js +2332 -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 +201 -448
- package/dist/continuous-event-graph/index.cjs.map +1 -1
- package/dist/continuous-event-graph/index.d.cts +16 -340
- package/dist/continuous-event-graph/index.d.ts +16 -340
- package/dist/continuous-event-graph/index.js +198 -448
- 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 +278 -533
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +8 -7
- package/dist/index.d.ts +8 -7
- package/dist/index.js +278 -533
- 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-BJDjWb5Q.d.cts +343 -0
- package/dist/journal-B_2JnBMF.d.ts +343 -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.bat +7 -0
- package/examples/browser/boards/portfolio-tracker/portfolio-tracker.js +189 -0
- package/examples/browser/livecards-browser/index.html +688 -0
- package/examples/browser/step-machine-browser/index.html +367 -0
- 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/index.html +792 -0
- package/examples/ingest.js +733 -0
- package/examples/npm-libs/batch/batch-step-machine.ts +121 -0
- package/examples/npm-libs/continuous-event-graph/live-cards-board.ts +215 -0
- package/examples/npm-libs/continuous-event-graph/live-portfolio-dashboard.ts +555 -0
- package/examples/npm-libs/continuous-event-graph/portfolio-tracker.ts +287 -0
- package/examples/npm-libs/continuous-event-graph/reactive-monitoring.ts +265 -0
- package/examples/npm-libs/continuous-event-graph/reactive-pipeline.ts +168 -0
- package/examples/npm-libs/continuous-event-graph/soc-incident-board.ts +287 -0
- package/examples/npm-libs/continuous-event-graph/stock-dashboard.ts +229 -0
- package/examples/npm-libs/event-graph/ci-cd-pipeline.ts +243 -0
- package/examples/npm-libs/event-graph/executor-diamond.ts +165 -0
- package/examples/npm-libs/event-graph/executor-pipeline.ts +161 -0
- package/examples/npm-libs/event-graph/research-pipeline.ts +137 -0
- package/examples/npm-libs/flows/ai-conversation.yaml +116 -0
- package/examples/npm-libs/flows/order-processing.yaml +143 -0
- package/examples/npm-libs/flows/simple-greeting.yaml +54 -0
- package/examples/npm-libs/graph-of-graphs/multi-stage-etl.ts +307 -0
- package/examples/npm-libs/graph-of-graphs/url-processing-pipeline.ts +254 -0
- package/examples/npm-libs/inference/azure-deployment.ts +149 -0
- package/examples/npm-libs/inference/copilot-cli.ts +138 -0
- package/examples/npm-libs/inference/data-pipeline.ts +145 -0
- package/examples/npm-libs/inference/pluggable-adapters.ts +254 -0
- package/examples/npm-libs/node/ai-conversation.ts +195 -0
- package/examples/npm-libs/node/simple-greeting.ts +101 -0
- 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.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 +14 -2
- package/schema/board-status.schema.json +118 -0
- package/schema/flow.schema.json +5 -0
- package/schema/live-cards.schema.json +59 -77
- package/step-machine-cli.js +674 -0
|
@@ -2,10 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
|
+
var jsonata = require('jsonata');
|
|
5
6
|
var addFormats = require('ajv-formats');
|
|
6
7
|
|
|
7
8
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
8
9
|
|
|
10
|
+
var jsonata__default = /*#__PURE__*/_interopDefault(jsonata);
|
|
9
11
|
var addFormats__default = /*#__PURE__*/_interopDefault(addFormats);
|
|
10
12
|
|
|
11
13
|
var __create = Object.create;
|
|
@@ -6427,9 +6429,9 @@ var live_cards_schema_default = {
|
|
|
6427
6429
|
description: "Schema for Card and ExternalSource nodes in the LiveCards Board/Canvas engine",
|
|
6428
6430
|
definitions: {
|
|
6429
6431
|
bind_ref: {
|
|
6430
|
-
description: "A state path reference, e.g. 'state.raw_quotes' or '
|
|
6432
|
+
description: "A state path reference, e.g. 'state.raw_quotes' or 'requires.upstream'",
|
|
6431
6433
|
type: "string",
|
|
6432
|
-
pattern: "^state\\."
|
|
6434
|
+
pattern: "^(state|requires|computed_values)\\."
|
|
6433
6435
|
},
|
|
6434
6436
|
bind_or_literal: {
|
|
6435
6437
|
description: "A literal value or a bind reference object",
|
|
@@ -6522,38 +6524,43 @@ var live_cards_schema_default = {
|
|
|
6522
6524
|
tags: { type: "array", items: { type: "string" } }
|
|
6523
6525
|
}
|
|
6524
6526
|
},
|
|
6525
|
-
|
|
6527
|
+
requires: {
|
|
6528
|
+
type: "array",
|
|
6529
|
+
items: { type: "string" },
|
|
6530
|
+
description: "IDs of upstream nodes this node depends on"
|
|
6531
|
+
},
|
|
6532
|
+
provides: {
|
|
6533
|
+
type: "array",
|
|
6534
|
+
items: {
|
|
6535
|
+
type: "object",
|
|
6536
|
+
required: ["bindTo", "src"],
|
|
6537
|
+
properties: {
|
|
6538
|
+
bindTo: { type: "string", description: "Token name published downstream" },
|
|
6539
|
+
src: { type: "string", description: "Path to read value from (state.*, requires.*, computed_values.*)" }
|
|
6540
|
+
}
|
|
6541
|
+
},
|
|
6542
|
+
description: "Explicit bindings exposing computed/state values downstream as named tokens"
|
|
6543
|
+
},
|
|
6544
|
+
compute_step: {
|
|
6545
|
+
description: "A single ordered compute step: reads state.*/requires.*/computed_values.*, writes to computed_values[bindTo]",
|
|
6526
6546
|
type: "object",
|
|
6547
|
+
required: ["bindTo", "expr"],
|
|
6527
6548
|
properties: {
|
|
6528
|
-
|
|
6529
|
-
|
|
6530
|
-
items: { type: "string" },
|
|
6531
|
-
description: "IDs of upstream nodes this node depends on"
|
|
6532
|
-
},
|
|
6533
|
-
provides: {
|
|
6534
|
-
type: "object",
|
|
6535
|
-
description: "Subset of state exposed downstream. Keys are published names, values are bind refs.",
|
|
6536
|
-
additionalProperties: { $ref: "#/definitions/bind_or_literal" }
|
|
6537
|
-
}
|
|
6549
|
+
bindTo: { type: "string", description: "Key in computed_values to write result" },
|
|
6550
|
+
expr: { type: "string", description: "JSONata expression evaluated against { state, requires, sources, computed_values }" }
|
|
6538
6551
|
}
|
|
6539
6552
|
},
|
|
6540
6553
|
source_def: {
|
|
6554
|
+
description: "One source entry. The engine only cares about 'bindTo' (compute namespace key) and 'outputFile' (delivery signal). Every other property is yours \u2014 add whatever your task-executor needs: kind, url, headers, mailbox, channel, model, query, etc. The full object is passed verbatim as the --in JSON to the executor.",
|
|
6541
6555
|
type: "object",
|
|
6542
|
-
required: ["
|
|
6556
|
+
required: ["bindTo"],
|
|
6557
|
+
additionalProperties: true,
|
|
6543
6558
|
properties: {
|
|
6544
|
-
|
|
6545
|
-
|
|
6546
|
-
|
|
6547
|
-
|
|
6548
|
-
|
|
6549
|
-
body_template: { type: "object", description: "Request body with {{var}} placeholders or bind refs" },
|
|
6550
|
-
template_vars: {
|
|
6551
|
-
type: "object",
|
|
6552
|
-
additionalProperties: { $ref: "#/definitions/bind_or_literal" },
|
|
6553
|
-
description: "Variables for url/body templates \u2014 static values or bind refs"
|
|
6554
|
-
},
|
|
6555
|
-
poll_interval: { type: "integer", minimum: 0, description: "Auto-refresh in seconds (0 = manual)" },
|
|
6556
|
-
transform: { type: "string", description: "Dot-path to extract from response, e.g. 'data.items'" }
|
|
6559
|
+
bindTo: { type: "string", description: "Key under sources.* available in compute expressions" },
|
|
6560
|
+
outputFile: { type: "string", description: "Board-relative path the executor writes its JSON result to. Presence of this file signals delivery." },
|
|
6561
|
+
optionalForCompletionGating: { type: "boolean", default: false, description: "When true this source does not gate card completion. Default false when absent, so sources are completion-gating by default." },
|
|
6562
|
+
timeout: { type: "integer", minimum: 0, default: 12e4, description: "Executor/script timeout in ms. Default: 120 000 (2 min)." },
|
|
6563
|
+
script: { type: "string", description: "Legacy direct-run: shell command executed when no .task-executor is registered. stdout is captured as the result." }
|
|
6557
6564
|
}
|
|
6558
6565
|
},
|
|
6559
6566
|
render_element: {
|
|
@@ -6671,64 +6678,37 @@ var live_cards_schema_default = {
|
|
|
6671
6678
|
}
|
|
6672
6679
|
}
|
|
6673
6680
|
},
|
|
6674
|
-
|
|
6675
|
-
|
|
6676
|
-
|
|
6677
|
-
|
|
6681
|
+
title: "LiveCard",
|
|
6682
|
+
description: "A unified card node. Behavior depends on which sections are present (sources, compute, view, etc.)",
|
|
6683
|
+
type: "object",
|
|
6684
|
+
required: ["id"],
|
|
6685
|
+
additionalProperties: false,
|
|
6686
|
+
properties: {
|
|
6687
|
+
id: { type: "string" },
|
|
6688
|
+
requires: { $ref: "#/definitions/requires" },
|
|
6689
|
+
provides: { $ref: "#/definitions/provides" },
|
|
6690
|
+
meta: { $ref: "#/definitions/meta" },
|
|
6691
|
+
view: { $ref: "#/definitions/view" },
|
|
6692
|
+
state: {
|
|
6678
6693
|
type: "object",
|
|
6679
|
-
|
|
6680
|
-
additionalProperties: false,
|
|
6694
|
+
additionalProperties: true,
|
|
6681
6695
|
properties: {
|
|
6682
|
-
|
|
6683
|
-
|
|
6684
|
-
|
|
6685
|
-
data: { $ref: "#/definitions/data" },
|
|
6686
|
-
view: { $ref: "#/definitions/view" },
|
|
6687
|
-
state: {
|
|
6688
|
-
type: "object",
|
|
6689
|
-
additionalProperties: true,
|
|
6690
|
-
properties: {
|
|
6691
|
-
status: { enum: ["fresh", "stale", "loading", "error"] },
|
|
6692
|
-
lastRun: { type: "string", format: "date-time" },
|
|
6693
|
-
error: { type: "string" }
|
|
6694
|
-
}
|
|
6695
|
-
},
|
|
6696
|
-
compute: {
|
|
6697
|
-
type: "object",
|
|
6698
|
-
description: "Derived state: key = state path to write, value = compute_expr",
|
|
6699
|
-
additionalProperties: { $ref: "#/definitions/compute_expr" }
|
|
6700
|
-
}
|
|
6696
|
+
status: { enum: ["fresh", "stale", "loading", "error"] },
|
|
6697
|
+
lastRun: { type: "string", format: "date-time" },
|
|
6698
|
+
error: { type: "string" }
|
|
6701
6699
|
}
|
|
6702
6700
|
},
|
|
6703
|
-
{
|
|
6704
|
-
|
|
6705
|
-
description: "
|
|
6706
|
-
|
|
6707
|
-
|
|
6708
|
-
|
|
6709
|
-
|
|
6710
|
-
|
|
6711
|
-
|
|
6712
|
-
meta: { $ref: "#/definitions/meta" },
|
|
6713
|
-
data: { $ref: "#/definitions/data" },
|
|
6714
|
-
source: { $ref: "#/definitions/source_def" },
|
|
6715
|
-
state: {
|
|
6716
|
-
type: "object",
|
|
6717
|
-
additionalProperties: true,
|
|
6718
|
-
properties: {
|
|
6719
|
-
status: { enum: ["fresh", "stale", "loading", "error"] },
|
|
6720
|
-
lastRun: { type: "string", format: "date-time" },
|
|
6721
|
-
error: { type: "string" }
|
|
6722
|
-
}
|
|
6723
|
-
},
|
|
6724
|
-
compute: {
|
|
6725
|
-
type: "object",
|
|
6726
|
-
description: "Derived state: key = state path to write, value = compute_expr",
|
|
6727
|
-
additionalProperties: { $ref: "#/definitions/compute_expr" }
|
|
6728
|
-
}
|
|
6729
|
-
}
|
|
6701
|
+
sources: {
|
|
6702
|
+
type: "array",
|
|
6703
|
+
description: "Source entries. Each entry is passed verbatim to the board's .task-executor (registered via init --task-executor) as the --in JSON file. The executor fetches/generates the data and writes JSON to --out. If no executor is registered, the built-in executor runs the entry's 'cli' command directly. Sources gate completion by default. Set optionalForCompletionGating: true for enrichment-only sources that should not block task-completed.",
|
|
6704
|
+
items: { $ref: "#/definitions/source_def" }
|
|
6705
|
+
},
|
|
6706
|
+
compute: {
|
|
6707
|
+
type: "array",
|
|
6708
|
+
description: "Ordered array of compute steps. Each reads state.*/requires.*/sources.*/computed_values.* and writes to ephemeral computed_values[bindTo].",
|
|
6709
|
+
items: { $ref: "#/definitions/compute_step" }
|
|
6730
6710
|
}
|
|
6731
|
-
|
|
6711
|
+
}
|
|
6732
6712
|
};
|
|
6733
6713
|
|
|
6734
6714
|
// src/card-compute/schema-validator.ts
|
|
@@ -6772,288 +6752,43 @@ function deepSet(obj, path, value) {
|
|
|
6772
6752
|
}
|
|
6773
6753
|
cur[parts[parts.length - 1]] = value;
|
|
6774
6754
|
}
|
|
6775
|
-
|
|
6776
|
-
|
|
6777
|
-
const a = Array.isArray(input) ? input : [];
|
|
6778
|
-
return opts.field ? a.reduce((s, r) => s + (Number(r[opts.field]) || 0), 0) : a.reduce((s, v) => s + (Number(v) || 0), 0);
|
|
6779
|
-
};
|
|
6780
|
-
_fns.avg = (input, _e, opts) => {
|
|
6781
|
-
const s = _fns.sum(input, _e, opts);
|
|
6782
|
-
const n = Array.isArray(input) ? input.length : 1;
|
|
6783
|
-
return n ? s / n : 0;
|
|
6784
|
-
};
|
|
6785
|
-
_fns.min = (input, _e, opts) => {
|
|
6786
|
-
const a = Array.isArray(input) ? input : [];
|
|
6787
|
-
const vals = opts.field ? a.map((r) => Number(r[opts.field])) : a.map(Number);
|
|
6788
|
-
return vals.length ? Math.min(...vals) : 0;
|
|
6789
|
-
};
|
|
6790
|
-
_fns.max = (input, _e, opts) => {
|
|
6791
|
-
const a = Array.isArray(input) ? input : [];
|
|
6792
|
-
const vals = opts.field ? a.map((r) => Number(r[opts.field])) : a.map(Number);
|
|
6793
|
-
return vals.length ? Math.max(...vals) : 0;
|
|
6794
|
-
};
|
|
6795
|
-
_fns.count = (input) => Array.isArray(input) ? input.length : input != null ? 1 : 0;
|
|
6796
|
-
_fns.first = (input) => Array.isArray(input) ? input[0] : input;
|
|
6797
|
-
_fns.last = (input) => Array.isArray(input) ? input[input.length - 1] : input;
|
|
6798
|
-
_fns.add = (input) => {
|
|
6799
|
-
const a = Array.isArray(input) ? input : [];
|
|
6800
|
-
return a.reduce((s, v) => s + Number(v), 0);
|
|
6801
|
-
};
|
|
6802
|
-
_fns.sub = (input) => {
|
|
6803
|
-
const a = Array.isArray(input) ? input : [];
|
|
6804
|
-
return a.length >= 2 ? Number(a[0]) - Number(a[1]) : 0;
|
|
6805
|
-
};
|
|
6806
|
-
_fns.mul = (input) => {
|
|
6807
|
-
const a = Array.isArray(input) ? input : [];
|
|
6808
|
-
return a.reduce((s, v) => s * Number(v), 1);
|
|
6809
|
-
};
|
|
6810
|
-
_fns.div = (input) => {
|
|
6811
|
-
const a = Array.isArray(input) ? input : [];
|
|
6812
|
-
return a.length >= 2 && Number(a[1]) !== 0 ? Number(a[0]) / Number(a[1]) : 0;
|
|
6813
|
-
};
|
|
6814
|
-
_fns.round = (input, _e, opts) => {
|
|
6815
|
-
const decimals = opts.decimals != null ? opts.decimals : 0;
|
|
6816
|
-
const factor = Math.pow(10, decimals);
|
|
6817
|
-
return Math.round(Number(input) * factor) / factor;
|
|
6818
|
-
};
|
|
6819
|
-
_fns.abs = (input) => Math.abs(Number(input));
|
|
6820
|
-
_fns.mod = (input) => {
|
|
6821
|
-
const a = Array.isArray(input) ? input : [];
|
|
6822
|
-
return a.length >= 2 ? Number(a[0]) % Number(a[1]) : 0;
|
|
6823
|
-
};
|
|
6824
|
-
_fns.gt = (input) => {
|
|
6825
|
-
const a = Array.isArray(input) ? input : [];
|
|
6826
|
-
return a.length >= 2 && Number(a[0]) > Number(a[1]);
|
|
6827
|
-
};
|
|
6828
|
-
_fns.gte = (input) => {
|
|
6829
|
-
const a = Array.isArray(input) ? input : [];
|
|
6830
|
-
return a.length >= 2 && Number(a[0]) >= Number(a[1]);
|
|
6831
|
-
};
|
|
6832
|
-
_fns.lt = (input) => {
|
|
6833
|
-
const a = Array.isArray(input) ? input : [];
|
|
6834
|
-
return a.length >= 2 && Number(a[0]) < Number(a[1]);
|
|
6835
|
-
};
|
|
6836
|
-
_fns.lte = (input) => {
|
|
6837
|
-
const a = Array.isArray(input) ? input : [];
|
|
6838
|
-
return a.length >= 2 && Number(a[0]) <= Number(a[1]);
|
|
6839
|
-
};
|
|
6840
|
-
_fns.eq = (input) => {
|
|
6841
|
-
const a = Array.isArray(input) ? input : [];
|
|
6842
|
-
return a.length >= 2 && a[0] === a[1];
|
|
6843
|
-
};
|
|
6844
|
-
_fns.neq = (input) => {
|
|
6845
|
-
const a = Array.isArray(input) ? input : [];
|
|
6846
|
-
return a.length >= 2 && a[0] !== a[1];
|
|
6847
|
-
};
|
|
6848
|
-
_fns.and = (input) => {
|
|
6849
|
-
const a = Array.isArray(input) ? input : [];
|
|
6850
|
-
return a.every(Boolean);
|
|
6851
|
-
};
|
|
6852
|
-
_fns.or = (input) => {
|
|
6853
|
-
const a = Array.isArray(input) ? input : [];
|
|
6854
|
-
return a.some(Boolean);
|
|
6855
|
-
};
|
|
6856
|
-
_fns.not = (input) => !input;
|
|
6857
|
-
_fns.concat = (input) => {
|
|
6858
|
-
const a = Array.isArray(input) ? input : [];
|
|
6859
|
-
return a.map((v) => v != null ? String(v) : "").join("");
|
|
6860
|
-
};
|
|
6861
|
-
_fns.upper = (input) => String(input || "").toUpperCase();
|
|
6862
|
-
_fns.lower = (input) => String(input || "").toLowerCase();
|
|
6863
|
-
_fns.template = (input, _e, opts) => {
|
|
6864
|
-
let t = String(opts.format || "");
|
|
6865
|
-
if (input && typeof input === "object" && !Array.isArray(input)) {
|
|
6866
|
-
for (const k of Object.keys(input)) {
|
|
6867
|
-
const v = input[k];
|
|
6868
|
-
t = t.split("{{" + k + "}}").join(v != null ? String(v) : "");
|
|
6869
|
-
}
|
|
6870
|
-
}
|
|
6871
|
-
return t;
|
|
6872
|
-
};
|
|
6873
|
-
_fns.join = (input, _e, opts) => {
|
|
6874
|
-
const a = Array.isArray(input) ? input : [];
|
|
6875
|
-
const sep = opts.separator != null ? String(opts.separator) : ", ";
|
|
6876
|
-
return a.map((v) => v != null ? String(v) : "").join(sep);
|
|
6877
|
-
};
|
|
6878
|
-
_fns.split = (input, _e, opts) => {
|
|
6879
|
-
const sep = opts.separator != null ? String(opts.separator) : ",";
|
|
6880
|
-
return String(input || "").split(sep).map((s) => s.trim());
|
|
6881
|
-
};
|
|
6882
|
-
_fns.trim = (input) => String(input || "").trim();
|
|
6883
|
-
_fns.pluck = (input, _e, opts) => Array.isArray(input) ? input.map((r) => r[opts.field]) : [];
|
|
6884
|
-
_fns.filter = (input, _e, opts) => {
|
|
6885
|
-
if (!Array.isArray(input)) return [];
|
|
6886
|
-
if (opts.field) return input.filter((r) => !!r[opts.field]);
|
|
6887
|
-
return input.filter(Boolean);
|
|
6888
|
-
};
|
|
6889
|
-
_fns.map = (input) => Array.isArray(input) ? input.slice() : [];
|
|
6890
|
-
_fns.sort = (input, _e, opts) => {
|
|
6891
|
-
const a = Array.isArray(input) ? input.slice() : [];
|
|
6892
|
-
const f = opts.field;
|
|
6893
|
-
const dir = opts.direction === "desc" ? -1 : 1;
|
|
6894
|
-
if (f) return a.sort((x, y) => x[f] > y[f] ? dir : x[f] < y[f] ? -dir : 0);
|
|
6895
|
-
return a.sort((x, y) => x > y ? dir : x < y ? -dir : 0);
|
|
6896
|
-
};
|
|
6897
|
-
_fns.slice = (input, _e, opts) => Array.isArray(input) ? input.slice(opts.start || 0, opts.end) : input;
|
|
6898
|
-
_fns.flat = (input, _e, opts) => {
|
|
6899
|
-
const depth = opts.depth != null ? opts.depth : 1;
|
|
6900
|
-
return Array.isArray(input) ? input.flat(depth) : [input];
|
|
6901
|
-
};
|
|
6902
|
-
_fns.unique = (input) => {
|
|
6903
|
-
if (!Array.isArray(input)) return [input];
|
|
6904
|
-
const seen = /* @__PURE__ */ new Set();
|
|
6905
|
-
return input.filter((v) => {
|
|
6906
|
-
const key = typeof v === "object" ? JSON.stringify(v) : v;
|
|
6907
|
-
if (seen.has(key)) return false;
|
|
6908
|
-
seen.add(key);
|
|
6909
|
-
return true;
|
|
6910
|
-
});
|
|
6911
|
-
};
|
|
6912
|
-
_fns.group = (input, _e, opts) => {
|
|
6913
|
-
const a = Array.isArray(input) ? input : [];
|
|
6914
|
-
const g = {};
|
|
6915
|
-
a.forEach((r) => {
|
|
6916
|
-
const k = String(r[opts.field] || "");
|
|
6917
|
-
if (!g[k]) g[k] = [];
|
|
6918
|
-
g[k].push(r);
|
|
6919
|
-
});
|
|
6920
|
-
return g;
|
|
6921
|
-
};
|
|
6922
|
-
_fns.flatten_keys = (input) => {
|
|
6923
|
-
if (!input || typeof input !== "object" || Array.isArray(input)) return [];
|
|
6924
|
-
const result = [];
|
|
6925
|
-
for (const k of Object.keys(input)) {
|
|
6926
|
-
const vals = Array.isArray(input[k]) ? input[k] : [input[k]];
|
|
6927
|
-
vals.forEach((v) => result.push({ key: k, value: v }));
|
|
6928
|
-
}
|
|
6929
|
-
return result;
|
|
6930
|
-
};
|
|
6931
|
-
_fns.entries = (input) => {
|
|
6932
|
-
if (!input || typeof input !== "object" || Array.isArray(input)) return [];
|
|
6933
|
-
return Object.keys(input).map((k) => ({ key: k, value: input[k] }));
|
|
6934
|
-
};
|
|
6935
|
-
_fns.from_entries = (input) => {
|
|
6936
|
-
if (!Array.isArray(input)) return {};
|
|
6937
|
-
const obj = {};
|
|
6938
|
-
input.forEach((item) => {
|
|
6939
|
-
if (item.key != null) obj[item.key] = item.value;
|
|
6940
|
-
});
|
|
6941
|
-
return obj;
|
|
6942
|
-
};
|
|
6943
|
-
_fns.length = (input) => {
|
|
6944
|
-
if (Array.isArray(input)) return input.length;
|
|
6945
|
-
if (typeof input === "string") return input.length;
|
|
6946
|
-
if (input && typeof input === "object") return Object.keys(input).length;
|
|
6947
|
-
return 0;
|
|
6948
|
-
};
|
|
6949
|
-
_fns.get = (input, _e, opts) => deepGet(input, opts.field || opts.path || "");
|
|
6950
|
-
_fns.default = (input, _e, opts) => input != null ? input : opts.value;
|
|
6951
|
-
_fns.coalesce = (input) => {
|
|
6952
|
-
const a = Array.isArray(input) ? input : [];
|
|
6953
|
-
for (let i = 0; i < a.length; i++) {
|
|
6954
|
-
if (a[i] != null) return a[i];
|
|
6955
|
-
}
|
|
6956
|
-
return null;
|
|
6957
|
-
};
|
|
6958
|
-
_fns.now = () => (/* @__PURE__ */ new Date()).toISOString();
|
|
6959
|
-
_fns.diff_days = (input) => {
|
|
6960
|
-
const a = Array.isArray(input) ? input : [];
|
|
6961
|
-
return a.length >= 2 ? Math.floor((new Date(a[0]).getTime() - new Date(a[1]).getTime()) / 864e5) : 0;
|
|
6962
|
-
};
|
|
6963
|
-
_fns.format_date = (input, _e, opts) => {
|
|
6964
|
-
try {
|
|
6965
|
-
const d = new Date(input);
|
|
6966
|
-
if (opts.format === "iso") return d.toISOString();
|
|
6967
|
-
if (opts.format === "date") return d.toLocaleDateString();
|
|
6968
|
-
if (opts.format === "time") return d.toLocaleTimeString();
|
|
6969
|
-
return d.toLocaleDateString();
|
|
6970
|
-
} catch {
|
|
6971
|
-
return String(input);
|
|
6972
|
-
}
|
|
6973
|
-
};
|
|
6974
|
-
_fns.parse_date = (input) => {
|
|
6975
|
-
try {
|
|
6976
|
-
return new Date(input).toISOString();
|
|
6977
|
-
} catch {
|
|
6978
|
-
return null;
|
|
6979
|
-
}
|
|
6980
|
-
};
|
|
6981
|
-
_fns.to_number = (input) => Number(input) || 0;
|
|
6982
|
-
_fns.to_string = (input) => input != null ? String(input) : "";
|
|
6983
|
-
_fns.to_bool = (input) => !!input;
|
|
6984
|
-
_fns.type_of = (input) => Array.isArray(input) ? "array" : typeof input;
|
|
6985
|
-
_fns.is_null = (input) => input == null;
|
|
6986
|
-
_fns.is_empty = (input) => {
|
|
6987
|
-
if (input == null) return true;
|
|
6988
|
-
if (Array.isArray(input)) return input.length === 0;
|
|
6989
|
-
if (typeof input === "string") return input.length === 0;
|
|
6990
|
-
if (typeof input === "object") return Object.keys(input).length === 0;
|
|
6991
|
-
return false;
|
|
6992
|
-
};
|
|
6993
|
-
var _customFns = {};
|
|
6994
|
-
function evalExpr(expr, node) {
|
|
6995
|
-
if (expr == null) return expr;
|
|
6996
|
-
if (typeof expr !== "object" || Array.isArray(expr)) return expr;
|
|
6997
|
-
const e = expr;
|
|
6998
|
-
if (!e.fn) return expr;
|
|
6999
|
-
let input = e.input;
|
|
7000
|
-
if (typeof input === "string" && input.startsWith("state.")) {
|
|
7001
|
-
input = deepGet(node, input);
|
|
7002
|
-
} else if (Array.isArray(input)) {
|
|
7003
|
-
input = input.map((v) => {
|
|
7004
|
-
if (typeof v === "string" && v.startsWith("state.")) return deepGet(node, v);
|
|
7005
|
-
if (v && typeof v === "object" && v.fn) return evalExpr(v, node);
|
|
7006
|
-
return v;
|
|
7007
|
-
});
|
|
7008
|
-
} else if (input && typeof input === "object" && input.fn) {
|
|
7009
|
-
input = evalExpr(input, node);
|
|
7010
|
-
}
|
|
7011
|
-
if (e.fn === "if") {
|
|
7012
|
-
const cond = evalExpr(e.cond, node);
|
|
7013
|
-
if (cond) {
|
|
7014
|
-
return e.then && typeof e.then === "object" && e.then.fn ? evalExpr(e.then, node) : e.then;
|
|
7015
|
-
} else {
|
|
7016
|
-
return e.else && typeof e.else === "object" && e.else.fn ? evalExpr(e.else, node) : e.else;
|
|
7017
|
-
}
|
|
7018
|
-
}
|
|
7019
|
-
if (e.fn === "filter" && Array.isArray(input) && e.where) {
|
|
7020
|
-
return input.filter((item) => {
|
|
7021
|
-
const tmp = { state: { ...node.state, $: item } };
|
|
7022
|
-
return evalExpr(e.where, tmp);
|
|
7023
|
-
});
|
|
7024
|
-
}
|
|
7025
|
-
if (e.fn === "map" && Array.isArray(input) && e.apply) {
|
|
7026
|
-
return input.map((item) => {
|
|
7027
|
-
const tmp = { state: { ...node.state, $: item } };
|
|
7028
|
-
return evalExpr(e.apply, tmp);
|
|
7029
|
-
});
|
|
7030
|
-
}
|
|
7031
|
-
const fn = _customFns[e.fn] || _fns[e.fn];
|
|
7032
|
-
if (!fn) {
|
|
7033
|
-
console.warn('CardCompute: unknown function "' + e.fn + '"');
|
|
7034
|
-
return void 0;
|
|
7035
|
-
}
|
|
7036
|
-
return fn(input, evalExpr, e);
|
|
7037
|
-
}
|
|
7038
|
-
function run(node) {
|
|
7039
|
-
if (!node || !node.compute) return node;
|
|
6755
|
+
async function run(node, options) {
|
|
6756
|
+
if (!node?.compute?.length) return node;
|
|
7040
6757
|
if (!node.state) node.state = {};
|
|
7041
|
-
|
|
6758
|
+
node.computed_values = {};
|
|
6759
|
+
node._sourcesData = options?.sourcesData ?? {};
|
|
6760
|
+
const ctx = {
|
|
6761
|
+
state: node.state,
|
|
6762
|
+
requires: node.requires ?? {},
|
|
6763
|
+
sources: node._sourcesData,
|
|
6764
|
+
computed_values: node.computed_values
|
|
6765
|
+
};
|
|
6766
|
+
for (const step of node.compute) {
|
|
7042
6767
|
try {
|
|
7043
|
-
const val =
|
|
7044
|
-
deepSet(node.
|
|
6768
|
+
const val = await jsonata__default.default(step.expr).evaluate(ctx);
|
|
6769
|
+
deepSet(node.computed_values, step.bindTo, val);
|
|
6770
|
+
ctx.computed_values = node.computed_values;
|
|
7045
6771
|
} catch (err) {
|
|
7046
|
-
console.error(`CardCompute.run error on "${node.id
|
|
6772
|
+
console.error(`CardCompute.run error on "${node.id ?? "?"}.${step.bindTo}":`, err);
|
|
7047
6773
|
}
|
|
7048
6774
|
}
|
|
7049
6775
|
return node;
|
|
7050
6776
|
}
|
|
6777
|
+
async function evalExpr(expr, node) {
|
|
6778
|
+
const ctx = {
|
|
6779
|
+
state: node.state ?? {},
|
|
6780
|
+
requires: node.requires ?? {},
|
|
6781
|
+
sources: node._sourcesData ?? {},
|
|
6782
|
+
computed_values: node.computed_values ?? {}
|
|
6783
|
+
};
|
|
6784
|
+
return jsonata__default.default(expr).evaluate(ctx);
|
|
6785
|
+
}
|
|
7051
6786
|
function resolve(node, path) {
|
|
6787
|
+
if (path.startsWith("sources.")) {
|
|
6788
|
+
return deepGet(node._sourcesData ?? {}, path.slice("sources.".length));
|
|
6789
|
+
}
|
|
7052
6790
|
return deepGet(node, path);
|
|
7053
6791
|
}
|
|
7054
|
-
function registerFunction(name, fn) {
|
|
7055
|
-
_customFns[name] = fn;
|
|
7056
|
-
}
|
|
7057
6792
|
var VALID_ELEMENT_KINDS = /* @__PURE__ */ new Set([
|
|
7058
6793
|
"metric",
|
|
7059
6794
|
"table",
|
|
@@ -7070,26 +6805,17 @@ var VALID_ELEMENT_KINDS = /* @__PURE__ */ new Set([
|
|
|
7070
6805
|
"markdown",
|
|
7071
6806
|
"custom"
|
|
7072
6807
|
]);
|
|
7073
|
-
var VALID_SOURCE_KINDS = /* @__PURE__ */ new Set(["api", "websocket", "static", "llm"]);
|
|
7074
6808
|
var VALID_STATUSES = /* @__PURE__ */ new Set(["fresh", "stale", "loading", "error"]);
|
|
7075
|
-
var
|
|
7076
|
-
var SOURCE_ALLOWED_KEYS = /* @__PURE__ */ new Set(["id", "type", "meta", "data", "source", "state", "compute"]);
|
|
6809
|
+
var ALLOWED_KEYS = /* @__PURE__ */ new Set(["id", "meta", "requires", "provides", "view", "state", "compute", "sources"]);
|
|
7077
6810
|
function validateNode(node) {
|
|
7078
6811
|
const errors = [];
|
|
7079
6812
|
if (!node || typeof node !== "object" || Array.isArray(node)) {
|
|
7080
6813
|
return { ok: false, errors: ["Node must be a non-null object"] };
|
|
7081
6814
|
}
|
|
7082
6815
|
const n = node;
|
|
7083
|
-
if (typeof n.id !== "string" || !n.id)
|
|
7084
|
-
errors.push("id: required, must be a non-empty string");
|
|
7085
|
-
}
|
|
7086
|
-
if (n.type !== "card" && n.type !== "source") {
|
|
7087
|
-
errors.push('type: must be "card" or "source"');
|
|
7088
|
-
return { ok: false, errors };
|
|
7089
|
-
}
|
|
7090
|
-
const allowed = n.type === "card" ? CARD_ALLOWED_KEYS : SOURCE_ALLOWED_KEYS;
|
|
6816
|
+
if (typeof n.id !== "string" || !n.id) errors.push("id: required, must be a non-empty string");
|
|
7091
6817
|
for (const key of Object.keys(n)) {
|
|
7092
|
-
if (!
|
|
6818
|
+
if (!ALLOWED_KEYS.has(key)) errors.push(`Unknown top-level key: "${key}"`);
|
|
7093
6819
|
}
|
|
7094
6820
|
if (n.state == null || typeof n.state !== "object" || Array.isArray(n.state)) {
|
|
7095
6821
|
errors.push("state: required, must be an object");
|
|
@@ -7108,37 +6834,58 @@ function validateNode(node) {
|
|
|
7108
6834
|
if (meta.tags != null && !Array.isArray(meta.tags)) errors.push("meta.tags: must be an array");
|
|
7109
6835
|
}
|
|
7110
6836
|
}
|
|
7111
|
-
if (n.
|
|
7112
|
-
|
|
7113
|
-
|
|
6837
|
+
if (n.requires != null && !Array.isArray(n.requires)) errors.push("requires: must be an array of strings");
|
|
6838
|
+
if (n.provides != null) {
|
|
6839
|
+
if (!Array.isArray(n.provides)) {
|
|
6840
|
+
errors.push("provides: must be an array of { bindTo, src } bindings");
|
|
7114
6841
|
} else {
|
|
7115
|
-
|
|
7116
|
-
|
|
7117
|
-
|
|
6842
|
+
n.provides.forEach((p, i) => {
|
|
6843
|
+
if (!p || typeof p !== "object" || Array.isArray(p)) {
|
|
6844
|
+
errors.push(`provides[${i}]: must be an object with bindTo and src`);
|
|
6845
|
+
} else {
|
|
6846
|
+
const b = p;
|
|
6847
|
+
if (typeof b.bindTo !== "string" || !b.bindTo) errors.push(`provides[${i}]: missing required "bindTo" string`);
|
|
6848
|
+
if (typeof b.src !== "string" || !b.src) errors.push(`provides[${i}]: missing required "src" string`);
|
|
6849
|
+
}
|
|
6850
|
+
});
|
|
7118
6851
|
}
|
|
7119
6852
|
}
|
|
7120
6853
|
if (n.compute != null) {
|
|
7121
|
-
if (
|
|
7122
|
-
errors.push("compute: must be an
|
|
6854
|
+
if (!Array.isArray(n.compute)) {
|
|
6855
|
+
errors.push("compute: must be an array of compute steps");
|
|
6856
|
+
} else {
|
|
6857
|
+
n.compute.forEach((step, i) => {
|
|
6858
|
+
if (!step || typeof step !== "object" || Array.isArray(step)) {
|
|
6859
|
+
errors.push(`compute[${i}]: must be a compute step object`);
|
|
6860
|
+
} else {
|
|
6861
|
+
const s = step;
|
|
6862
|
+
if (typeof s.bindTo !== "string" || !s.bindTo) errors.push(`compute[${i}]: missing required "bindTo" property`);
|
|
6863
|
+
if (typeof s.expr !== "string" || !s.expr) errors.push(`compute[${i}]: missing required "expr" string (JSONata expression)`);
|
|
6864
|
+
}
|
|
6865
|
+
});
|
|
6866
|
+
}
|
|
6867
|
+
}
|
|
6868
|
+
if (n.sources != null) {
|
|
6869
|
+
if (!Array.isArray(n.sources)) {
|
|
6870
|
+
errors.push("sources: must be an array");
|
|
7123
6871
|
} else {
|
|
7124
|
-
|
|
7125
|
-
if (!
|
|
7126
|
-
errors.push(`
|
|
7127
|
-
} else if (!expr.fn) {
|
|
7128
|
-
errors.push(`compute.${key}: missing required "fn" property`);
|
|
6872
|
+
n.sources.forEach((src, i) => {
|
|
6873
|
+
if (!src || typeof src !== "object" || Array.isArray(src)) {
|
|
6874
|
+
errors.push(`sources[${i}]: must be an object`);
|
|
7129
6875
|
} else {
|
|
7130
|
-
const
|
|
7131
|
-
if (!
|
|
7132
|
-
|
|
6876
|
+
const s = src;
|
|
6877
|
+
if (typeof s.bindTo !== "string" || !s.bindTo) errors.push(`sources[${i}]: missing required "bindTo" property`);
|
|
6878
|
+
if (s.outputFile != null && typeof s.outputFile !== "string") errors.push(`sources[${i}]: outputFile must be a string`);
|
|
6879
|
+
if (s.optionalForCompletionGating != null && typeof s.optionalForCompletionGating !== "boolean") {
|
|
6880
|
+
errors.push(`sources[${i}]: optionalForCompletionGating must be a boolean`);
|
|
7133
6881
|
}
|
|
7134
6882
|
}
|
|
7135
|
-
}
|
|
6883
|
+
});
|
|
7136
6884
|
}
|
|
7137
6885
|
}
|
|
7138
|
-
if (n.
|
|
7139
|
-
if (n.
|
|
7140
|
-
|
|
7141
|
-
errors.push("view: required for card nodes, must be an object");
|
|
6886
|
+
if (n.view != null) {
|
|
6887
|
+
if (typeof n.view !== "object" || Array.isArray(n.view)) {
|
|
6888
|
+
errors.push("view: must be an object");
|
|
7142
6889
|
} else {
|
|
7143
6890
|
const view = n.view;
|
|
7144
6891
|
if (!Array.isArray(view.elements) || view.elements.length === 0) {
|
|
@@ -7159,28 +6906,8 @@ function validateNode(node) {
|
|
|
7159
6906
|
}
|
|
7160
6907
|
});
|
|
7161
6908
|
}
|
|
7162
|
-
if (view.layout != null && (typeof view.layout !== "object" || Array.isArray(view.layout)))
|
|
7163
|
-
|
|
7164
|
-
}
|
|
7165
|
-
if (view.features != null && (typeof view.features !== "object" || Array.isArray(view.features))) {
|
|
7166
|
-
errors.push("view.features: must be an object");
|
|
7167
|
-
}
|
|
7168
|
-
}
|
|
7169
|
-
}
|
|
7170
|
-
if (n.type === "source") {
|
|
7171
|
-
if (n.view != null) errors.push('Source nodes must not have "view" \u2014 use type "card" instead');
|
|
7172
|
-
if (n.source == null || typeof n.source !== "object" || Array.isArray(n.source)) {
|
|
7173
|
-
errors.push("source: required for source nodes, must be an object");
|
|
7174
|
-
} else {
|
|
7175
|
-
const src = n.source;
|
|
7176
|
-
if (!src.kind || !VALID_SOURCE_KINDS.has(src.kind)) {
|
|
7177
|
-
errors.push(`source.kind: required, must be one of: ${[...VALID_SOURCE_KINDS].join(", ")}`);
|
|
7178
|
-
}
|
|
7179
|
-
if (typeof src.bindTo !== "string" || !src.bindTo) {
|
|
7180
|
-
errors.push("source.bindTo: required, must be a state path string");
|
|
7181
|
-
} else if (!src.bindTo.startsWith("state.")) {
|
|
7182
|
-
errors.push('source.bindTo: must start with "state."');
|
|
7183
|
-
}
|
|
6909
|
+
if (view.layout != null && (typeof view.layout !== "object" || Array.isArray(view.layout))) errors.push("view.layout: must be an object");
|
|
6910
|
+
if (view.features != null && (typeof view.features !== "object" || Array.isArray(view.features))) errors.push("view.features: must be an object");
|
|
7184
6911
|
}
|
|
7185
6912
|
}
|
|
7186
6913
|
return { ok: errors.length === 0, errors };
|
|
@@ -7189,14 +6916,7 @@ var CardCompute = {
|
|
|
7189
6916
|
run,
|
|
7190
6917
|
eval: evalExpr,
|
|
7191
6918
|
resolve,
|
|
7192
|
-
validate: validateNode
|
|
7193
|
-
registerFunction,
|
|
7194
|
-
get functions() {
|
|
7195
|
-
const all = {};
|
|
7196
|
-
for (const k of Object.keys(_fns)) all[k] = _fns[k];
|
|
7197
|
-
for (const k of Object.keys(_customFns)) all[k] = _customFns[k];
|
|
7198
|
-
return all;
|
|
7199
|
-
}
|
|
6919
|
+
validate: validateNode
|
|
7200
6920
|
};
|
|
7201
6921
|
var card_compute_default = CardCompute;
|
|
7202
6922
|
|