yaml-flow 3.1.1 → 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/{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/index.html +792 -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 +1 -1
- package/examples/{continuous-event-graph → npm-libs/continuous-event-graph}/live-portfolio-dashboard.ts +1 -1
- 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.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 +12 -1
- 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
- /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,3 +1,4 @@
|
|
|
1
|
+
import jsonata from 'jsonata';
|
|
1
2
|
import addFormats from 'ajv-formats';
|
|
2
3
|
|
|
3
4
|
var __create = Object.create;
|
|
@@ -6419,9 +6420,9 @@ var live_cards_schema_default = {
|
|
|
6419
6420
|
description: "Schema for Card and ExternalSource nodes in the LiveCards Board/Canvas engine",
|
|
6420
6421
|
definitions: {
|
|
6421
6422
|
bind_ref: {
|
|
6422
|
-
description: "A state path reference, e.g. 'state.raw_quotes' or '
|
|
6423
|
+
description: "A state path reference, e.g. 'state.raw_quotes' or 'requires.upstream'",
|
|
6423
6424
|
type: "string",
|
|
6424
|
-
pattern: "^state\\."
|
|
6425
|
+
pattern: "^(state|requires|computed_values)\\."
|
|
6425
6426
|
},
|
|
6426
6427
|
bind_or_literal: {
|
|
6427
6428
|
description: "A literal value or a bind reference object",
|
|
@@ -6514,38 +6515,43 @@ var live_cards_schema_default = {
|
|
|
6514
6515
|
tags: { type: "array", items: { type: "string" } }
|
|
6515
6516
|
}
|
|
6516
6517
|
},
|
|
6517
|
-
|
|
6518
|
+
requires: {
|
|
6519
|
+
type: "array",
|
|
6520
|
+
items: { type: "string" },
|
|
6521
|
+
description: "IDs of upstream nodes this node depends on"
|
|
6522
|
+
},
|
|
6523
|
+
provides: {
|
|
6524
|
+
type: "array",
|
|
6525
|
+
items: {
|
|
6526
|
+
type: "object",
|
|
6527
|
+
required: ["bindTo", "src"],
|
|
6528
|
+
properties: {
|
|
6529
|
+
bindTo: { type: "string", description: "Token name published downstream" },
|
|
6530
|
+
src: { type: "string", description: "Path to read value from (state.*, requires.*, computed_values.*)" }
|
|
6531
|
+
}
|
|
6532
|
+
},
|
|
6533
|
+
description: "Explicit bindings exposing computed/state values downstream as named tokens"
|
|
6534
|
+
},
|
|
6535
|
+
compute_step: {
|
|
6536
|
+
description: "A single ordered compute step: reads state.*/requires.*/computed_values.*, writes to computed_values[bindTo]",
|
|
6518
6537
|
type: "object",
|
|
6538
|
+
required: ["bindTo", "expr"],
|
|
6519
6539
|
properties: {
|
|
6520
|
-
|
|
6521
|
-
|
|
6522
|
-
items: { type: "string" },
|
|
6523
|
-
description: "IDs of upstream nodes this node depends on"
|
|
6524
|
-
},
|
|
6525
|
-
provides: {
|
|
6526
|
-
type: "object",
|
|
6527
|
-
description: "Subset of state exposed downstream. Keys are published names, values are bind refs.",
|
|
6528
|
-
additionalProperties: { $ref: "#/definitions/bind_or_literal" }
|
|
6529
|
-
}
|
|
6540
|
+
bindTo: { type: "string", description: "Key in computed_values to write result" },
|
|
6541
|
+
expr: { type: "string", description: "JSONata expression evaluated against { state, requires, sources, computed_values }" }
|
|
6530
6542
|
}
|
|
6531
6543
|
},
|
|
6532
6544
|
source_def: {
|
|
6545
|
+
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.",
|
|
6533
6546
|
type: "object",
|
|
6534
|
-
required: ["
|
|
6547
|
+
required: ["bindTo"],
|
|
6548
|
+
additionalProperties: true,
|
|
6535
6549
|
properties: {
|
|
6536
|
-
|
|
6537
|
-
|
|
6538
|
-
|
|
6539
|
-
|
|
6540
|
-
|
|
6541
|
-
body_template: { type: "object", description: "Request body with {{var}} placeholders or bind refs" },
|
|
6542
|
-
template_vars: {
|
|
6543
|
-
type: "object",
|
|
6544
|
-
additionalProperties: { $ref: "#/definitions/bind_or_literal" },
|
|
6545
|
-
description: "Variables for url/body templates \u2014 static values or bind refs"
|
|
6546
|
-
},
|
|
6547
|
-
poll_interval: { type: "integer", minimum: 0, description: "Auto-refresh in seconds (0 = manual)" },
|
|
6548
|
-
transform: { type: "string", description: "Dot-path to extract from response, e.g. 'data.items'" }
|
|
6550
|
+
bindTo: { type: "string", description: "Key under sources.* available in compute expressions" },
|
|
6551
|
+
outputFile: { type: "string", description: "Board-relative path the executor writes its JSON result to. Presence of this file signals delivery." },
|
|
6552
|
+
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." },
|
|
6553
|
+
timeout: { type: "integer", minimum: 0, default: 12e4, description: "Executor/script timeout in ms. Default: 120 000 (2 min)." },
|
|
6554
|
+
script: { type: "string", description: "Legacy direct-run: shell command executed when no .task-executor is registered. stdout is captured as the result." }
|
|
6549
6555
|
}
|
|
6550
6556
|
},
|
|
6551
6557
|
render_element: {
|
|
@@ -6663,64 +6669,37 @@ var live_cards_schema_default = {
|
|
|
6663
6669
|
}
|
|
6664
6670
|
}
|
|
6665
6671
|
},
|
|
6666
|
-
|
|
6667
|
-
|
|
6668
|
-
|
|
6669
|
-
|
|
6672
|
+
title: "LiveCard",
|
|
6673
|
+
description: "A unified card node. Behavior depends on which sections are present (sources, compute, view, etc.)",
|
|
6674
|
+
type: "object",
|
|
6675
|
+
required: ["id"],
|
|
6676
|
+
additionalProperties: false,
|
|
6677
|
+
properties: {
|
|
6678
|
+
id: { type: "string" },
|
|
6679
|
+
requires: { $ref: "#/definitions/requires" },
|
|
6680
|
+
provides: { $ref: "#/definitions/provides" },
|
|
6681
|
+
meta: { $ref: "#/definitions/meta" },
|
|
6682
|
+
view: { $ref: "#/definitions/view" },
|
|
6683
|
+
state: {
|
|
6670
6684
|
type: "object",
|
|
6671
|
-
|
|
6672
|
-
additionalProperties: false,
|
|
6685
|
+
additionalProperties: true,
|
|
6673
6686
|
properties: {
|
|
6674
|
-
|
|
6675
|
-
|
|
6676
|
-
|
|
6677
|
-
data: { $ref: "#/definitions/data" },
|
|
6678
|
-
view: { $ref: "#/definitions/view" },
|
|
6679
|
-
state: {
|
|
6680
|
-
type: "object",
|
|
6681
|
-
additionalProperties: true,
|
|
6682
|
-
properties: {
|
|
6683
|
-
status: { enum: ["fresh", "stale", "loading", "error"] },
|
|
6684
|
-
lastRun: { type: "string", format: "date-time" },
|
|
6685
|
-
error: { type: "string" }
|
|
6686
|
-
}
|
|
6687
|
-
},
|
|
6688
|
-
compute: {
|
|
6689
|
-
type: "object",
|
|
6690
|
-
description: "Derived state: key = state path to write, value = compute_expr",
|
|
6691
|
-
additionalProperties: { $ref: "#/definitions/compute_expr" }
|
|
6692
|
-
}
|
|
6687
|
+
status: { enum: ["fresh", "stale", "loading", "error"] },
|
|
6688
|
+
lastRun: { type: "string", format: "date-time" },
|
|
6689
|
+
error: { type: "string" }
|
|
6693
6690
|
}
|
|
6694
6691
|
},
|
|
6695
|
-
{
|
|
6696
|
-
|
|
6697
|
-
description: "
|
|
6698
|
-
|
|
6699
|
-
|
|
6700
|
-
|
|
6701
|
-
|
|
6702
|
-
|
|
6703
|
-
|
|
6704
|
-
meta: { $ref: "#/definitions/meta" },
|
|
6705
|
-
data: { $ref: "#/definitions/data" },
|
|
6706
|
-
source: { $ref: "#/definitions/source_def" },
|
|
6707
|
-
state: {
|
|
6708
|
-
type: "object",
|
|
6709
|
-
additionalProperties: true,
|
|
6710
|
-
properties: {
|
|
6711
|
-
status: { enum: ["fresh", "stale", "loading", "error"] },
|
|
6712
|
-
lastRun: { type: "string", format: "date-time" },
|
|
6713
|
-
error: { type: "string" }
|
|
6714
|
-
}
|
|
6715
|
-
},
|
|
6716
|
-
compute: {
|
|
6717
|
-
type: "object",
|
|
6718
|
-
description: "Derived state: key = state path to write, value = compute_expr",
|
|
6719
|
-
additionalProperties: { $ref: "#/definitions/compute_expr" }
|
|
6720
|
-
}
|
|
6721
|
-
}
|
|
6692
|
+
sources: {
|
|
6693
|
+
type: "array",
|
|
6694
|
+
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.",
|
|
6695
|
+
items: { $ref: "#/definitions/source_def" }
|
|
6696
|
+
},
|
|
6697
|
+
compute: {
|
|
6698
|
+
type: "array",
|
|
6699
|
+
description: "Ordered array of compute steps. Each reads state.*/requires.*/sources.*/computed_values.* and writes to ephemeral computed_values[bindTo].",
|
|
6700
|
+
items: { $ref: "#/definitions/compute_step" }
|
|
6722
6701
|
}
|
|
6723
|
-
|
|
6702
|
+
}
|
|
6724
6703
|
};
|
|
6725
6704
|
|
|
6726
6705
|
// src/card-compute/schema-validator.ts
|
|
@@ -6764,288 +6743,43 @@ function deepSet(obj, path, value) {
|
|
|
6764
6743
|
}
|
|
6765
6744
|
cur[parts[parts.length - 1]] = value;
|
|
6766
6745
|
}
|
|
6767
|
-
|
|
6768
|
-
|
|
6769
|
-
const a = Array.isArray(input) ? input : [];
|
|
6770
|
-
return opts.field ? a.reduce((s, r) => s + (Number(r[opts.field]) || 0), 0) : a.reduce((s, v) => s + (Number(v) || 0), 0);
|
|
6771
|
-
};
|
|
6772
|
-
_fns.avg = (input, _e, opts) => {
|
|
6773
|
-
const s = _fns.sum(input, _e, opts);
|
|
6774
|
-
const n = Array.isArray(input) ? input.length : 1;
|
|
6775
|
-
return n ? s / n : 0;
|
|
6776
|
-
};
|
|
6777
|
-
_fns.min = (input, _e, opts) => {
|
|
6778
|
-
const a = Array.isArray(input) ? input : [];
|
|
6779
|
-
const vals = opts.field ? a.map((r) => Number(r[opts.field])) : a.map(Number);
|
|
6780
|
-
return vals.length ? Math.min(...vals) : 0;
|
|
6781
|
-
};
|
|
6782
|
-
_fns.max = (input, _e, opts) => {
|
|
6783
|
-
const a = Array.isArray(input) ? input : [];
|
|
6784
|
-
const vals = opts.field ? a.map((r) => Number(r[opts.field])) : a.map(Number);
|
|
6785
|
-
return vals.length ? Math.max(...vals) : 0;
|
|
6786
|
-
};
|
|
6787
|
-
_fns.count = (input) => Array.isArray(input) ? input.length : input != null ? 1 : 0;
|
|
6788
|
-
_fns.first = (input) => Array.isArray(input) ? input[0] : input;
|
|
6789
|
-
_fns.last = (input) => Array.isArray(input) ? input[input.length - 1] : input;
|
|
6790
|
-
_fns.add = (input) => {
|
|
6791
|
-
const a = Array.isArray(input) ? input : [];
|
|
6792
|
-
return a.reduce((s, v) => s + Number(v), 0);
|
|
6793
|
-
};
|
|
6794
|
-
_fns.sub = (input) => {
|
|
6795
|
-
const a = Array.isArray(input) ? input : [];
|
|
6796
|
-
return a.length >= 2 ? Number(a[0]) - Number(a[1]) : 0;
|
|
6797
|
-
};
|
|
6798
|
-
_fns.mul = (input) => {
|
|
6799
|
-
const a = Array.isArray(input) ? input : [];
|
|
6800
|
-
return a.reduce((s, v) => s * Number(v), 1);
|
|
6801
|
-
};
|
|
6802
|
-
_fns.div = (input) => {
|
|
6803
|
-
const a = Array.isArray(input) ? input : [];
|
|
6804
|
-
return a.length >= 2 && Number(a[1]) !== 0 ? Number(a[0]) / Number(a[1]) : 0;
|
|
6805
|
-
};
|
|
6806
|
-
_fns.round = (input, _e, opts) => {
|
|
6807
|
-
const decimals = opts.decimals != null ? opts.decimals : 0;
|
|
6808
|
-
const factor = Math.pow(10, decimals);
|
|
6809
|
-
return Math.round(Number(input) * factor) / factor;
|
|
6810
|
-
};
|
|
6811
|
-
_fns.abs = (input) => Math.abs(Number(input));
|
|
6812
|
-
_fns.mod = (input) => {
|
|
6813
|
-
const a = Array.isArray(input) ? input : [];
|
|
6814
|
-
return a.length >= 2 ? Number(a[0]) % Number(a[1]) : 0;
|
|
6815
|
-
};
|
|
6816
|
-
_fns.gt = (input) => {
|
|
6817
|
-
const a = Array.isArray(input) ? input : [];
|
|
6818
|
-
return a.length >= 2 && Number(a[0]) > Number(a[1]);
|
|
6819
|
-
};
|
|
6820
|
-
_fns.gte = (input) => {
|
|
6821
|
-
const a = Array.isArray(input) ? input : [];
|
|
6822
|
-
return a.length >= 2 && Number(a[0]) >= Number(a[1]);
|
|
6823
|
-
};
|
|
6824
|
-
_fns.lt = (input) => {
|
|
6825
|
-
const a = Array.isArray(input) ? input : [];
|
|
6826
|
-
return a.length >= 2 && Number(a[0]) < Number(a[1]);
|
|
6827
|
-
};
|
|
6828
|
-
_fns.lte = (input) => {
|
|
6829
|
-
const a = Array.isArray(input) ? input : [];
|
|
6830
|
-
return a.length >= 2 && Number(a[0]) <= Number(a[1]);
|
|
6831
|
-
};
|
|
6832
|
-
_fns.eq = (input) => {
|
|
6833
|
-
const a = Array.isArray(input) ? input : [];
|
|
6834
|
-
return a.length >= 2 && a[0] === a[1];
|
|
6835
|
-
};
|
|
6836
|
-
_fns.neq = (input) => {
|
|
6837
|
-
const a = Array.isArray(input) ? input : [];
|
|
6838
|
-
return a.length >= 2 && a[0] !== a[1];
|
|
6839
|
-
};
|
|
6840
|
-
_fns.and = (input) => {
|
|
6841
|
-
const a = Array.isArray(input) ? input : [];
|
|
6842
|
-
return a.every(Boolean);
|
|
6843
|
-
};
|
|
6844
|
-
_fns.or = (input) => {
|
|
6845
|
-
const a = Array.isArray(input) ? input : [];
|
|
6846
|
-
return a.some(Boolean);
|
|
6847
|
-
};
|
|
6848
|
-
_fns.not = (input) => !input;
|
|
6849
|
-
_fns.concat = (input) => {
|
|
6850
|
-
const a = Array.isArray(input) ? input : [];
|
|
6851
|
-
return a.map((v) => v != null ? String(v) : "").join("");
|
|
6852
|
-
};
|
|
6853
|
-
_fns.upper = (input) => String(input || "").toUpperCase();
|
|
6854
|
-
_fns.lower = (input) => String(input || "").toLowerCase();
|
|
6855
|
-
_fns.template = (input, _e, opts) => {
|
|
6856
|
-
let t = String(opts.format || "");
|
|
6857
|
-
if (input && typeof input === "object" && !Array.isArray(input)) {
|
|
6858
|
-
for (const k of Object.keys(input)) {
|
|
6859
|
-
const v = input[k];
|
|
6860
|
-
t = t.split("{{" + k + "}}").join(v != null ? String(v) : "");
|
|
6861
|
-
}
|
|
6862
|
-
}
|
|
6863
|
-
return t;
|
|
6864
|
-
};
|
|
6865
|
-
_fns.join = (input, _e, opts) => {
|
|
6866
|
-
const a = Array.isArray(input) ? input : [];
|
|
6867
|
-
const sep = opts.separator != null ? String(opts.separator) : ", ";
|
|
6868
|
-
return a.map((v) => v != null ? String(v) : "").join(sep);
|
|
6869
|
-
};
|
|
6870
|
-
_fns.split = (input, _e, opts) => {
|
|
6871
|
-
const sep = opts.separator != null ? String(opts.separator) : ",";
|
|
6872
|
-
return String(input || "").split(sep).map((s) => s.trim());
|
|
6873
|
-
};
|
|
6874
|
-
_fns.trim = (input) => String(input || "").trim();
|
|
6875
|
-
_fns.pluck = (input, _e, opts) => Array.isArray(input) ? input.map((r) => r[opts.field]) : [];
|
|
6876
|
-
_fns.filter = (input, _e, opts) => {
|
|
6877
|
-
if (!Array.isArray(input)) return [];
|
|
6878
|
-
if (opts.field) return input.filter((r) => !!r[opts.field]);
|
|
6879
|
-
return input.filter(Boolean);
|
|
6880
|
-
};
|
|
6881
|
-
_fns.map = (input) => Array.isArray(input) ? input.slice() : [];
|
|
6882
|
-
_fns.sort = (input, _e, opts) => {
|
|
6883
|
-
const a = Array.isArray(input) ? input.slice() : [];
|
|
6884
|
-
const f = opts.field;
|
|
6885
|
-
const dir = opts.direction === "desc" ? -1 : 1;
|
|
6886
|
-
if (f) return a.sort((x, y) => x[f] > y[f] ? dir : x[f] < y[f] ? -dir : 0);
|
|
6887
|
-
return a.sort((x, y) => x > y ? dir : x < y ? -dir : 0);
|
|
6888
|
-
};
|
|
6889
|
-
_fns.slice = (input, _e, opts) => Array.isArray(input) ? input.slice(opts.start || 0, opts.end) : input;
|
|
6890
|
-
_fns.flat = (input, _e, opts) => {
|
|
6891
|
-
const depth = opts.depth != null ? opts.depth : 1;
|
|
6892
|
-
return Array.isArray(input) ? input.flat(depth) : [input];
|
|
6893
|
-
};
|
|
6894
|
-
_fns.unique = (input) => {
|
|
6895
|
-
if (!Array.isArray(input)) return [input];
|
|
6896
|
-
const seen = /* @__PURE__ */ new Set();
|
|
6897
|
-
return input.filter((v) => {
|
|
6898
|
-
const key = typeof v === "object" ? JSON.stringify(v) : v;
|
|
6899
|
-
if (seen.has(key)) return false;
|
|
6900
|
-
seen.add(key);
|
|
6901
|
-
return true;
|
|
6902
|
-
});
|
|
6903
|
-
};
|
|
6904
|
-
_fns.group = (input, _e, opts) => {
|
|
6905
|
-
const a = Array.isArray(input) ? input : [];
|
|
6906
|
-
const g = {};
|
|
6907
|
-
a.forEach((r) => {
|
|
6908
|
-
const k = String(r[opts.field] || "");
|
|
6909
|
-
if (!g[k]) g[k] = [];
|
|
6910
|
-
g[k].push(r);
|
|
6911
|
-
});
|
|
6912
|
-
return g;
|
|
6913
|
-
};
|
|
6914
|
-
_fns.flatten_keys = (input) => {
|
|
6915
|
-
if (!input || typeof input !== "object" || Array.isArray(input)) return [];
|
|
6916
|
-
const result = [];
|
|
6917
|
-
for (const k of Object.keys(input)) {
|
|
6918
|
-
const vals = Array.isArray(input[k]) ? input[k] : [input[k]];
|
|
6919
|
-
vals.forEach((v) => result.push({ key: k, value: v }));
|
|
6920
|
-
}
|
|
6921
|
-
return result;
|
|
6922
|
-
};
|
|
6923
|
-
_fns.entries = (input) => {
|
|
6924
|
-
if (!input || typeof input !== "object" || Array.isArray(input)) return [];
|
|
6925
|
-
return Object.keys(input).map((k) => ({ key: k, value: input[k] }));
|
|
6926
|
-
};
|
|
6927
|
-
_fns.from_entries = (input) => {
|
|
6928
|
-
if (!Array.isArray(input)) return {};
|
|
6929
|
-
const obj = {};
|
|
6930
|
-
input.forEach((item) => {
|
|
6931
|
-
if (item.key != null) obj[item.key] = item.value;
|
|
6932
|
-
});
|
|
6933
|
-
return obj;
|
|
6934
|
-
};
|
|
6935
|
-
_fns.length = (input) => {
|
|
6936
|
-
if (Array.isArray(input)) return input.length;
|
|
6937
|
-
if (typeof input === "string") return input.length;
|
|
6938
|
-
if (input && typeof input === "object") return Object.keys(input).length;
|
|
6939
|
-
return 0;
|
|
6940
|
-
};
|
|
6941
|
-
_fns.get = (input, _e, opts) => deepGet(input, opts.field || opts.path || "");
|
|
6942
|
-
_fns.default = (input, _e, opts) => input != null ? input : opts.value;
|
|
6943
|
-
_fns.coalesce = (input) => {
|
|
6944
|
-
const a = Array.isArray(input) ? input : [];
|
|
6945
|
-
for (let i = 0; i < a.length; i++) {
|
|
6946
|
-
if (a[i] != null) return a[i];
|
|
6947
|
-
}
|
|
6948
|
-
return null;
|
|
6949
|
-
};
|
|
6950
|
-
_fns.now = () => (/* @__PURE__ */ new Date()).toISOString();
|
|
6951
|
-
_fns.diff_days = (input) => {
|
|
6952
|
-
const a = Array.isArray(input) ? input : [];
|
|
6953
|
-
return a.length >= 2 ? Math.floor((new Date(a[0]).getTime() - new Date(a[1]).getTime()) / 864e5) : 0;
|
|
6954
|
-
};
|
|
6955
|
-
_fns.format_date = (input, _e, opts) => {
|
|
6956
|
-
try {
|
|
6957
|
-
const d = new Date(input);
|
|
6958
|
-
if (opts.format === "iso") return d.toISOString();
|
|
6959
|
-
if (opts.format === "date") return d.toLocaleDateString();
|
|
6960
|
-
if (opts.format === "time") return d.toLocaleTimeString();
|
|
6961
|
-
return d.toLocaleDateString();
|
|
6962
|
-
} catch {
|
|
6963
|
-
return String(input);
|
|
6964
|
-
}
|
|
6965
|
-
};
|
|
6966
|
-
_fns.parse_date = (input) => {
|
|
6967
|
-
try {
|
|
6968
|
-
return new Date(input).toISOString();
|
|
6969
|
-
} catch {
|
|
6970
|
-
return null;
|
|
6971
|
-
}
|
|
6972
|
-
};
|
|
6973
|
-
_fns.to_number = (input) => Number(input) || 0;
|
|
6974
|
-
_fns.to_string = (input) => input != null ? String(input) : "";
|
|
6975
|
-
_fns.to_bool = (input) => !!input;
|
|
6976
|
-
_fns.type_of = (input) => Array.isArray(input) ? "array" : typeof input;
|
|
6977
|
-
_fns.is_null = (input) => input == null;
|
|
6978
|
-
_fns.is_empty = (input) => {
|
|
6979
|
-
if (input == null) return true;
|
|
6980
|
-
if (Array.isArray(input)) return input.length === 0;
|
|
6981
|
-
if (typeof input === "string") return input.length === 0;
|
|
6982
|
-
if (typeof input === "object") return Object.keys(input).length === 0;
|
|
6983
|
-
return false;
|
|
6984
|
-
};
|
|
6985
|
-
var _customFns = {};
|
|
6986
|
-
function evalExpr(expr, node) {
|
|
6987
|
-
if (expr == null) return expr;
|
|
6988
|
-
if (typeof expr !== "object" || Array.isArray(expr)) return expr;
|
|
6989
|
-
const e = expr;
|
|
6990
|
-
if (!e.fn) return expr;
|
|
6991
|
-
let input = e.input;
|
|
6992
|
-
if (typeof input === "string" && input.startsWith("state.")) {
|
|
6993
|
-
input = deepGet(node, input);
|
|
6994
|
-
} else if (Array.isArray(input)) {
|
|
6995
|
-
input = input.map((v) => {
|
|
6996
|
-
if (typeof v === "string" && v.startsWith("state.")) return deepGet(node, v);
|
|
6997
|
-
if (v && typeof v === "object" && v.fn) return evalExpr(v, node);
|
|
6998
|
-
return v;
|
|
6999
|
-
});
|
|
7000
|
-
} else if (input && typeof input === "object" && input.fn) {
|
|
7001
|
-
input = evalExpr(input, node);
|
|
7002
|
-
}
|
|
7003
|
-
if (e.fn === "if") {
|
|
7004
|
-
const cond = evalExpr(e.cond, node);
|
|
7005
|
-
if (cond) {
|
|
7006
|
-
return e.then && typeof e.then === "object" && e.then.fn ? evalExpr(e.then, node) : e.then;
|
|
7007
|
-
} else {
|
|
7008
|
-
return e.else && typeof e.else === "object" && e.else.fn ? evalExpr(e.else, node) : e.else;
|
|
7009
|
-
}
|
|
7010
|
-
}
|
|
7011
|
-
if (e.fn === "filter" && Array.isArray(input) && e.where) {
|
|
7012
|
-
return input.filter((item) => {
|
|
7013
|
-
const tmp = { state: { ...node.state, $: item } };
|
|
7014
|
-
return evalExpr(e.where, tmp);
|
|
7015
|
-
});
|
|
7016
|
-
}
|
|
7017
|
-
if (e.fn === "map" && Array.isArray(input) && e.apply) {
|
|
7018
|
-
return input.map((item) => {
|
|
7019
|
-
const tmp = { state: { ...node.state, $: item } };
|
|
7020
|
-
return evalExpr(e.apply, tmp);
|
|
7021
|
-
});
|
|
7022
|
-
}
|
|
7023
|
-
const fn = _customFns[e.fn] || _fns[e.fn];
|
|
7024
|
-
if (!fn) {
|
|
7025
|
-
console.warn('CardCompute: unknown function "' + e.fn + '"');
|
|
7026
|
-
return void 0;
|
|
7027
|
-
}
|
|
7028
|
-
return fn(input, evalExpr, e);
|
|
7029
|
-
}
|
|
7030
|
-
function run(node) {
|
|
7031
|
-
if (!node || !node.compute) return node;
|
|
6746
|
+
async function run(node, options) {
|
|
6747
|
+
if (!node?.compute?.length) return node;
|
|
7032
6748
|
if (!node.state) node.state = {};
|
|
7033
|
-
|
|
6749
|
+
node.computed_values = {};
|
|
6750
|
+
node._sourcesData = options?.sourcesData ?? {};
|
|
6751
|
+
const ctx = {
|
|
6752
|
+
state: node.state,
|
|
6753
|
+
requires: node.requires ?? {},
|
|
6754
|
+
sources: node._sourcesData,
|
|
6755
|
+
computed_values: node.computed_values
|
|
6756
|
+
};
|
|
6757
|
+
for (const step of node.compute) {
|
|
7034
6758
|
try {
|
|
7035
|
-
const val =
|
|
7036
|
-
deepSet(node.
|
|
6759
|
+
const val = await jsonata(step.expr).evaluate(ctx);
|
|
6760
|
+
deepSet(node.computed_values, step.bindTo, val);
|
|
6761
|
+
ctx.computed_values = node.computed_values;
|
|
7037
6762
|
} catch (err) {
|
|
7038
|
-
console.error(`CardCompute.run error on "${node.id
|
|
6763
|
+
console.error(`CardCompute.run error on "${node.id ?? "?"}.${step.bindTo}":`, err);
|
|
7039
6764
|
}
|
|
7040
6765
|
}
|
|
7041
6766
|
return node;
|
|
7042
6767
|
}
|
|
6768
|
+
async function evalExpr(expr, node) {
|
|
6769
|
+
const ctx = {
|
|
6770
|
+
state: node.state ?? {},
|
|
6771
|
+
requires: node.requires ?? {},
|
|
6772
|
+
sources: node._sourcesData ?? {},
|
|
6773
|
+
computed_values: node.computed_values ?? {}
|
|
6774
|
+
};
|
|
6775
|
+
return jsonata(expr).evaluate(ctx);
|
|
6776
|
+
}
|
|
7043
6777
|
function resolve(node, path) {
|
|
6778
|
+
if (path.startsWith("sources.")) {
|
|
6779
|
+
return deepGet(node._sourcesData ?? {}, path.slice("sources.".length));
|
|
6780
|
+
}
|
|
7044
6781
|
return deepGet(node, path);
|
|
7045
6782
|
}
|
|
7046
|
-
function registerFunction(name, fn) {
|
|
7047
|
-
_customFns[name] = fn;
|
|
7048
|
-
}
|
|
7049
6783
|
var VALID_ELEMENT_KINDS = /* @__PURE__ */ new Set([
|
|
7050
6784
|
"metric",
|
|
7051
6785
|
"table",
|
|
@@ -7062,26 +6796,17 @@ var VALID_ELEMENT_KINDS = /* @__PURE__ */ new Set([
|
|
|
7062
6796
|
"markdown",
|
|
7063
6797
|
"custom"
|
|
7064
6798
|
]);
|
|
7065
|
-
var VALID_SOURCE_KINDS = /* @__PURE__ */ new Set(["api", "websocket", "static", "llm"]);
|
|
7066
6799
|
var VALID_STATUSES = /* @__PURE__ */ new Set(["fresh", "stale", "loading", "error"]);
|
|
7067
|
-
var
|
|
7068
|
-
var SOURCE_ALLOWED_KEYS = /* @__PURE__ */ new Set(["id", "type", "meta", "data", "source", "state", "compute"]);
|
|
6800
|
+
var ALLOWED_KEYS = /* @__PURE__ */ new Set(["id", "meta", "requires", "provides", "view", "state", "compute", "sources"]);
|
|
7069
6801
|
function validateNode(node) {
|
|
7070
6802
|
const errors = [];
|
|
7071
6803
|
if (!node || typeof node !== "object" || Array.isArray(node)) {
|
|
7072
6804
|
return { ok: false, errors: ["Node must be a non-null object"] };
|
|
7073
6805
|
}
|
|
7074
6806
|
const n = node;
|
|
7075
|
-
if (typeof n.id !== "string" || !n.id)
|
|
7076
|
-
errors.push("id: required, must be a non-empty string");
|
|
7077
|
-
}
|
|
7078
|
-
if (n.type !== "card" && n.type !== "source") {
|
|
7079
|
-
errors.push('type: must be "card" or "source"');
|
|
7080
|
-
return { ok: false, errors };
|
|
7081
|
-
}
|
|
7082
|
-
const allowed = n.type === "card" ? CARD_ALLOWED_KEYS : SOURCE_ALLOWED_KEYS;
|
|
6807
|
+
if (typeof n.id !== "string" || !n.id) errors.push("id: required, must be a non-empty string");
|
|
7083
6808
|
for (const key of Object.keys(n)) {
|
|
7084
|
-
if (!
|
|
6809
|
+
if (!ALLOWED_KEYS.has(key)) errors.push(`Unknown top-level key: "${key}"`);
|
|
7085
6810
|
}
|
|
7086
6811
|
if (n.state == null || typeof n.state !== "object" || Array.isArray(n.state)) {
|
|
7087
6812
|
errors.push("state: required, must be an object");
|
|
@@ -7100,37 +6825,58 @@ function validateNode(node) {
|
|
|
7100
6825
|
if (meta.tags != null && !Array.isArray(meta.tags)) errors.push("meta.tags: must be an array");
|
|
7101
6826
|
}
|
|
7102
6827
|
}
|
|
7103
|
-
if (n.
|
|
7104
|
-
|
|
7105
|
-
|
|
6828
|
+
if (n.requires != null && !Array.isArray(n.requires)) errors.push("requires: must be an array of strings");
|
|
6829
|
+
if (n.provides != null) {
|
|
6830
|
+
if (!Array.isArray(n.provides)) {
|
|
6831
|
+
errors.push("provides: must be an array of { bindTo, src } bindings");
|
|
7106
6832
|
} else {
|
|
7107
|
-
|
|
7108
|
-
|
|
7109
|
-
|
|
6833
|
+
n.provides.forEach((p, i) => {
|
|
6834
|
+
if (!p || typeof p !== "object" || Array.isArray(p)) {
|
|
6835
|
+
errors.push(`provides[${i}]: must be an object with bindTo and src`);
|
|
6836
|
+
} else {
|
|
6837
|
+
const b = p;
|
|
6838
|
+
if (typeof b.bindTo !== "string" || !b.bindTo) errors.push(`provides[${i}]: missing required "bindTo" string`);
|
|
6839
|
+
if (typeof b.src !== "string" || !b.src) errors.push(`provides[${i}]: missing required "src" string`);
|
|
6840
|
+
}
|
|
6841
|
+
});
|
|
7110
6842
|
}
|
|
7111
6843
|
}
|
|
7112
6844
|
if (n.compute != null) {
|
|
7113
|
-
if (
|
|
7114
|
-
errors.push("compute: must be an
|
|
6845
|
+
if (!Array.isArray(n.compute)) {
|
|
6846
|
+
errors.push("compute: must be an array of compute steps");
|
|
6847
|
+
} else {
|
|
6848
|
+
n.compute.forEach((step, i) => {
|
|
6849
|
+
if (!step || typeof step !== "object" || Array.isArray(step)) {
|
|
6850
|
+
errors.push(`compute[${i}]: must be a compute step object`);
|
|
6851
|
+
} else {
|
|
6852
|
+
const s = step;
|
|
6853
|
+
if (typeof s.bindTo !== "string" || !s.bindTo) errors.push(`compute[${i}]: missing required "bindTo" property`);
|
|
6854
|
+
if (typeof s.expr !== "string" || !s.expr) errors.push(`compute[${i}]: missing required "expr" string (JSONata expression)`);
|
|
6855
|
+
}
|
|
6856
|
+
});
|
|
6857
|
+
}
|
|
6858
|
+
}
|
|
6859
|
+
if (n.sources != null) {
|
|
6860
|
+
if (!Array.isArray(n.sources)) {
|
|
6861
|
+
errors.push("sources: must be an array");
|
|
7115
6862
|
} else {
|
|
7116
|
-
|
|
7117
|
-
if (!
|
|
7118
|
-
errors.push(`
|
|
7119
|
-
} else if (!expr.fn) {
|
|
7120
|
-
errors.push(`compute.${key}: missing required "fn" property`);
|
|
6863
|
+
n.sources.forEach((src, i) => {
|
|
6864
|
+
if (!src || typeof src !== "object" || Array.isArray(src)) {
|
|
6865
|
+
errors.push(`sources[${i}]: must be an object`);
|
|
7121
6866
|
} else {
|
|
7122
|
-
const
|
|
7123
|
-
if (!
|
|
7124
|
-
|
|
6867
|
+
const s = src;
|
|
6868
|
+
if (typeof s.bindTo !== "string" || !s.bindTo) errors.push(`sources[${i}]: missing required "bindTo" property`);
|
|
6869
|
+
if (s.outputFile != null && typeof s.outputFile !== "string") errors.push(`sources[${i}]: outputFile must be a string`);
|
|
6870
|
+
if (s.optionalForCompletionGating != null && typeof s.optionalForCompletionGating !== "boolean") {
|
|
6871
|
+
errors.push(`sources[${i}]: optionalForCompletionGating must be a boolean`);
|
|
7125
6872
|
}
|
|
7126
6873
|
}
|
|
7127
|
-
}
|
|
6874
|
+
});
|
|
7128
6875
|
}
|
|
7129
6876
|
}
|
|
7130
|
-
if (n.
|
|
7131
|
-
if (n.
|
|
7132
|
-
|
|
7133
|
-
errors.push("view: required for card nodes, must be an object");
|
|
6877
|
+
if (n.view != null) {
|
|
6878
|
+
if (typeof n.view !== "object" || Array.isArray(n.view)) {
|
|
6879
|
+
errors.push("view: must be an object");
|
|
7134
6880
|
} else {
|
|
7135
6881
|
const view = n.view;
|
|
7136
6882
|
if (!Array.isArray(view.elements) || view.elements.length === 0) {
|
|
@@ -7151,28 +6897,8 @@ function validateNode(node) {
|
|
|
7151
6897
|
}
|
|
7152
6898
|
});
|
|
7153
6899
|
}
|
|
7154
|
-
if (view.layout != null && (typeof view.layout !== "object" || Array.isArray(view.layout)))
|
|
7155
|
-
|
|
7156
|
-
}
|
|
7157
|
-
if (view.features != null && (typeof view.features !== "object" || Array.isArray(view.features))) {
|
|
7158
|
-
errors.push("view.features: must be an object");
|
|
7159
|
-
}
|
|
7160
|
-
}
|
|
7161
|
-
}
|
|
7162
|
-
if (n.type === "source") {
|
|
7163
|
-
if (n.view != null) errors.push('Source nodes must not have "view" \u2014 use type "card" instead');
|
|
7164
|
-
if (n.source == null || typeof n.source !== "object" || Array.isArray(n.source)) {
|
|
7165
|
-
errors.push("source: required for source nodes, must be an object");
|
|
7166
|
-
} else {
|
|
7167
|
-
const src = n.source;
|
|
7168
|
-
if (!src.kind || !VALID_SOURCE_KINDS.has(src.kind)) {
|
|
7169
|
-
errors.push(`source.kind: required, must be one of: ${[...VALID_SOURCE_KINDS].join(", ")}`);
|
|
7170
|
-
}
|
|
7171
|
-
if (typeof src.bindTo !== "string" || !src.bindTo) {
|
|
7172
|
-
errors.push("source.bindTo: required, must be a state path string");
|
|
7173
|
-
} else if (!src.bindTo.startsWith("state.")) {
|
|
7174
|
-
errors.push('source.bindTo: must start with "state."');
|
|
7175
|
-
}
|
|
6900
|
+
if (view.layout != null && (typeof view.layout !== "object" || Array.isArray(view.layout))) errors.push("view.layout: must be an object");
|
|
6901
|
+
if (view.features != null && (typeof view.features !== "object" || Array.isArray(view.features))) errors.push("view.features: must be an object");
|
|
7176
6902
|
}
|
|
7177
6903
|
}
|
|
7178
6904
|
return { ok: errors.length === 0, errors };
|
|
@@ -7181,14 +6907,7 @@ var CardCompute = {
|
|
|
7181
6907
|
run,
|
|
7182
6908
|
eval: evalExpr,
|
|
7183
6909
|
resolve,
|
|
7184
|
-
validate: validateNode
|
|
7185
|
-
registerFunction,
|
|
7186
|
-
get functions() {
|
|
7187
|
-
const all = {};
|
|
7188
|
-
for (const k of Object.keys(_fns)) all[k] = _fns[k];
|
|
7189
|
-
for (const k of Object.keys(_customFns)) all[k] = _customFns[k];
|
|
7190
|
-
return all;
|
|
7191
|
-
}
|
|
6910
|
+
validate: validateNode
|
|
7192
6911
|
};
|
|
7193
6912
|
var card_compute_default = CardCompute;
|
|
7194
6913
|
|