yaml-flow 7.1.0 → 8.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/browser/asset-integrity.json +8 -4
- package/browser/board-livecards-client.js +1 -1
- package/browser/board-livecards-localstorage.js +5 -5
- package/browser/live-cards.js +19 -3309
- package/cli/board-live-cards-lib-tjYsPt5U.d.ts +321 -0
- package/{dist/cli → cli}/browser-api/board-live-cards-browser-adapter.d.ts +3 -5
- package/{dist/cli → cli}/browser-api/card-store-browser-api.d.ts +1 -2
- package/{dist/cli → cli}/browser-api/card-store-browser-api.js +1 -1
- package/cli/execution-interface-C_A6WCiK.d.ts +284 -0
- package/{dist/cli → cli}/node/artifacts-store-cli.js +2 -2
- package/cli/node/batch-runner-cli.js +3 -0
- package/cli/node/board-live-cards-cli.js +15 -0
- package/{dist/cli → cli}/node/execution-adapter.d.ts +3 -3
- package/cli/node/execution-adapter.js +3 -0
- package/{dist/cli → cli}/node/fs-board-adapter.d.ts +24 -11
- package/cli/node/fs-board-adapter.js +14 -0
- package/cli/node/step-machine-cli.d.ts +7 -0
- package/cli/node/step-machine-cli.js +5 -0
- package/{dist/board-live-cards-public-5n1-syA3.d.cts → cli/types-CziUxkiv.d.ts} +68 -5
- package/examples/board/.demo-setup/run-1778643703151-3360-dopnpv/board-default/gandalf-runtime/.config/card-store-ref.json +1 -0
- package/examples/board/.demo-setup/run-1778643703151-3360-dopnpv/board-default/gandalf-runtime/.config/chat-handler.json +1 -0
- package/examples/board/.demo-setup/run-1778643703151-3360-dopnpv/board-default/gandalf-runtime/.config/outputs-store-ref.json +1 -0
- package/examples/board/.demo-setup/run-1778643703151-3360-dopnpv/board-default/gandalf-runtime/.config/task-executor.json +1 -0
- package/examples/board/.demo-setup/run-1778643703151-3360-dopnpv/board-default/gandalf-runtime/.state-snapshot/board/graph.json +29 -0
- package/examples/board/.demo-setup/run-1778643703151-3360-dopnpv/board-default/gandalf-runtime/.state-snapshot/board/lastJournalProcessedId.json +1 -0
- package/examples/board/.demo-setup/run-1778643703151-3360-dopnpv/board-default/gandalf-runtime-out/.outputs/status.json +25 -0
- package/examples/board/.demo-setup/run-1778643703151-3360-dopnpv/board-default/runtime-out/.outputs/cards/card-market-prices/computed_values.json +67 -0
- package/examples/board/.demo-setup/run-1778643703151-3360-dopnpv/board-default/runtime-out/.outputs/cards/card-portfolio/computed_values.json +1 -0
- package/examples/board/.demo-setup/run-1778643703151-3360-dopnpv/board-default/runtime-out/.outputs/cards/card-portfolio-value/computed_values.json +52 -0
- package/examples/board/.demo-setup/run-1778643703151-3360-dopnpv/board-default/runtime-out/.outputs/data-objects/holdings.json +22 -0
- package/examples/board/.demo-setup/run-1778643703151-3360-dopnpv/board-default/runtime-out/.outputs/data-objects/positions.json +46 -0
- package/examples/board/.demo-setup/run-1778643703151-3360-dopnpv/board-default/runtime-out/.outputs/data-objects/quotes.json +35 -0
- package/examples/board/.demo-setup/run-1778643703151-3360-dopnpv/board-default/runtime-out/.outputs/status.json +113 -0
- package/examples/{example-board → board}/demo-server-config.json +0 -1
- package/examples/{example-board → board}/demo-server.js +23 -48
- package/examples/{example-board → board}/demo-shell-with-server.html +3 -3
- package/examples/{example-board → board}/demo-task-executor.js +71 -24
- package/examples/board/gandalf-cards/card-source-kinds.json +36 -0
- package/examples/board/gandalf-cards/cards/_index.json +7 -0
- package/examples/board/gandalf-cards/cards/card-source-kinds.json +64 -0
- package/examples/board/source-def-flows/copilot.flow.json +33 -0
- package/examples/board/source-def-flows/mock.flow.json +35 -0
- package/examples/board/source-def-flows/url-list.flow.json +33 -0
- package/examples/board/source-def-flows/url.flow.json +33 -0
- package/examples/board/source-def-flows/workiq.flow.json +34 -0
- package/examples/board/source-def-handlers/copilot-source-handler.js +141 -0
- package/examples/board/source-def-handlers/http-source-handler.js +145 -0
- package/examples/board/source_def_flows.json +249 -0
- package/examples/board/test/demo-http-test.js +317 -0
- package/examples/{example-board → board-local}/demo-shell-localstorage.html +4 -4
- package/examples/{browser/boards/portfolio-tracker → portfolio-tracker/handlers}/portfolio-tracker-fetch-prices.js +1 -1
- package/examples/{browser/boards/portfolio-tracker/portfolio-tracker-public.js → portfolio-tracker/portfolio-tracker.js} +11 -14
- package/examples/{browser/boards/portfolio-tracker → portfolio-tracker/test}/portfolio-t4.js +32 -50
- package/lib/artifacts-store-lib-public-BABrgFkV.d.ts +119 -0
- package/lib/artifacts-store-lib-public-DGa8BpJT.d.cts +119 -0
- package/lib/artifacts-store-public.cjs +2 -0
- package/lib/artifacts-store-public.d.cts +5 -0
- package/lib/artifacts-store-public.d.ts +5 -0
- package/lib/artifacts-store-public.js +2 -0
- package/lib/board-live-cards-node.cjs +14 -0
- package/{dist/cli/node/execution-adapter.d.cts → lib/board-live-cards-node.d.cts} +45 -85
- package/lib/board-live-cards-node.d.ts +134 -0
- package/lib/board-live-cards-node.js +14 -0
- package/lib/board-live-cards-public-BnmRAbQV.d.cts +383 -0
- package/{dist/board-live-cards-public-CK_J8uv0.d.ts → lib/board-live-cards-public-CsmYrvpd.d.ts} +142 -76
- package/lib/board-live-cards-public.cjs +3 -0
- package/lib/board-live-cards-public.d.cts +4 -0
- package/lib/board-live-cards-public.d.ts +4 -0
- package/lib/board-live-cards-public.js +3 -0
- package/lib/board-live-cards-server-runtime.cjs +9 -0
- package/lib/board-live-cards-server-runtime.d.cts +6 -0
- package/lib/board-live-cards-server-runtime.d.ts +6 -0
- package/lib/board-live-cards-server-runtime.js +9 -0
- package/lib/board-livegraph-runtime/index.cjs +3 -0
- package/{dist → lib}/board-livegraph-runtime/index.d.cts +1 -2
- package/{dist → lib}/board-livegraph-runtime/index.d.ts +1 -2
- package/lib/board-livegraph-runtime/index.js +3 -0
- package/{dist/storage-refs.cjs → lib/board-worker-adapter.cjs} +2 -2
- package/{dist/storage-refs.d.cts → lib/board-worker-adapter.d.cts} +4 -3
- package/{dist/storage-refs.d.ts → lib/board-worker-adapter.d.ts} +4 -3
- package/{dist/storage-refs.js → lib/board-worker-adapter.js} +2 -2
- package/{dist → lib}/card-compute/index.cjs +1 -1
- package/{dist → lib}/card-compute/index.js +1 -1
- package/lib/card-store-public.cjs +2 -0
- package/lib/card-store-public.d.cts +61 -0
- package/lib/card-store-public.d.ts +61 -0
- package/lib/card-store-public.js +2 -0
- package/lib/card-validation.cjs +10 -0
- package/lib/card-validation.d.cts +35 -0
- package/lib/card-validation.d.ts +35 -0
- package/lib/card-validation.js +10 -0
- package/{dist/constants-oCEbNpul.d.ts → lib/constants-BPVLb3Es.d.ts} +1 -1
- package/{dist/constants-BzZUyYlp.d.cts → lib/constants-DXxsRN9y.d.cts} +1 -1
- package/{dist → lib}/continuous-event-graph/index.cjs +2 -2
- package/{dist → lib}/continuous-event-graph/index.d.cts +3 -5
- package/{dist → lib}/continuous-event-graph/index.d.ts +3 -5
- package/{dist → lib}/continuous-event-graph/index.js +2 -2
- package/{dist → lib}/event-graph/index.d.cts +2 -2
- package/{dist → lib}/event-graph/index.d.ts +2 -2
- package/{dist → lib}/execution-refs.d.cts +29 -10
- package/{dist → lib}/execution-refs.d.ts +29 -10
- package/lib/index.cjs +25 -0
- package/{dist → lib}/index.d.cts +7 -8
- package/{dist → lib}/index.d.ts +7 -8
- package/lib/index.js +25 -0
- package/{dist/live-cards-bridge-BXbVTsna.d.cts → lib/live-cards-bridge-DC_ZU0eS.d.ts} +134 -3
- package/{dist/live-cards-bridge-Ds28XR15.d.ts → lib/live-cards-bridge-b25aAVvE.d.cts} +134 -3
- package/lib/loader-CuuLjxVA.d.cts +42 -0
- package/lib/loader-Zborm2pq.d.ts +42 -0
- package/lib/server-runtime/index.cjs +9 -0
- package/{dist → lib}/server-runtime/index.d.cts +4 -4
- package/{dist → lib}/server-runtime/index.d.ts +4 -4
- package/lib/server-runtime/index.js +9 -0
- package/lib/step-machine/index.d.cts +64 -0
- package/lib/step-machine/index.d.ts +64 -0
- package/lib/step-machine-public/index.cjs +5 -0
- package/{dist → lib}/step-machine-public/index.d.cts +14 -1
- package/{dist → lib}/step-machine-public/index.d.ts +14 -1
- package/lib/step-machine-public/index.js +5 -0
- package/lib/storage-interface-BhAON-gW.d.cts +84 -0
- package/lib/storage-interface-BhAON-gW.d.ts +84 -0
- package/lib/stores/index.cjs +3 -0
- package/lib/stores/index.d.cts +4 -0
- package/lib/stores/index.d.ts +4 -0
- package/lib/stores/index.js +3 -0
- package/lib/stores/kv.cjs +3 -0
- package/lib/stores/kv.d.cts +32 -0
- package/lib/stores/kv.d.ts +32 -0
- package/lib/stores/kv.js +3 -0
- package/{dist → lib}/stores/memory.d.cts +1 -1
- package/{dist → lib}/stores/memory.d.ts +1 -1
- package/{dist/types-HGDTWIun.d.ts → lib/types-CBxkYuLY.d.ts} +2 -1
- package/{dist/types-ycun84cq.d.cts → lib/types-DQ1bKuB1.d.cts} +11 -0
- package/{dist/types-ycun84cq.d.ts → lib/types-DQ1bKuB1.d.ts} +11 -0
- package/{dist/types-CU3DjTKL.d.cts → lib/types-DkFvgxwq.d.cts} +2 -1
- package/package.json +79 -119
- package/board-live-cards-cli.js +0 -37
- package/browser/board-livecards-client.js.map +0 -1
- package/browser/board-livecards-localstorage.js.map +0 -1
- package/browser/board-livegraph-engine.js +0 -3
- package/browser/board-livegraph-engine.js.map +0 -1
- package/browser/card-compute.js +0 -266
- package/browser/compute-jsonata.js.map +0 -1
- package/card-store.js +0 -37
- package/dist/batch/index.cjs.map +0 -1
- package/dist/batch/index.js.map +0 -1
- package/dist/board-live-cards-lib-Bg6EvCo5.d.cts +0 -136
- package/dist/board-live-cards-lib-jM2uYG1v.d.ts +0 -136
- package/dist/board-livegraph-runtime/index.cjs +0 -3
- package/dist/board-livegraph-runtime/index.cjs.map +0 -1
- package/dist/board-livegraph-runtime/index.js +0 -3
- package/dist/board-livegraph-runtime/index.js.map +0 -1
- package/dist/card-compute/index.cjs.map +0 -1
- package/dist/card-compute/index.js.map +0 -1
- package/dist/cli/browser-api/board-live-cards-browser-adapter.cjs +0 -3
- package/dist/cli/browser-api/board-live-cards-browser-adapter.cjs.map +0 -1
- package/dist/cli/browser-api/board-live-cards-browser-adapter.d.cts +0 -37
- package/dist/cli/browser-api/board-live-cards-browser-adapter.js.map +0 -1
- package/dist/cli/browser-api/card-store-browser-api.cjs +0 -2
- package/dist/cli/browser-api/card-store-browser-api.cjs.map +0 -1
- package/dist/cli/browser-api/card-store-browser-api.d.cts +0 -26
- package/dist/cli/browser-api/card-store-browser-api.js.map +0 -1
- package/dist/cli/node/artifacts-store-cli.cjs +0 -11
- package/dist/cli/node/artifacts-store-cli.cjs.map +0 -1
- package/dist/cli/node/artifacts-store-cli.d.cts +0 -8
- package/dist/cli/node/artifacts-store-cli.js.map +0 -1
- package/dist/cli/node/board-live-cards-cli.cjs +0 -15
- package/dist/cli/node/board-live-cards-cli.cjs.map +0 -1
- package/dist/cli/node/board-live-cards-cli.d.cts +0 -20
- package/dist/cli/node/board-live-cards-cli.js +0 -15
- package/dist/cli/node/board-live-cards-cli.js.map +0 -1
- package/dist/cli/node/card-store-cli.cjs +0 -8
- package/dist/cli/node/card-store-cli.cjs.map +0 -1
- package/dist/cli/node/card-store-cli.d.cts +0 -15
- package/dist/cli/node/card-store-cli.js.map +0 -1
- package/dist/cli/node/execution-adapter.cjs +0 -3
- package/dist/cli/node/execution-adapter.cjs.map +0 -1
- package/dist/cli/node/execution-adapter.js +0 -3
- package/dist/cli/node/execution-adapter.js.map +0 -1
- package/dist/cli/node/fs-board-adapter.cjs +0 -14
- package/dist/cli/node/fs-board-adapter.cjs.map +0 -1
- package/dist/cli/node/fs-board-adapter.d.cts +0 -204
- package/dist/cli/node/fs-board-adapter.js +0 -14
- package/dist/cli/node/fs-board-adapter.js.map +0 -1
- package/dist/cli/node/source-cli-task-executor.cjs +0 -11
- package/dist/cli/node/source-cli-task-executor.cjs.map +0 -1
- package/dist/cli/node/source-cli-task-executor.js.map +0 -1
- package/dist/config/index.cjs.map +0 -1
- package/dist/config/index.js.map +0 -1
- package/dist/continuous-event-graph/index.cjs.map +0 -1
- package/dist/continuous-event-graph/index.js.map +0 -1
- package/dist/event-graph/index.cjs.map +0 -1
- package/dist/event-graph/index.js.map +0 -1
- package/dist/execution-refs.cjs.map +0 -1
- package/dist/execution-refs.js.map +0 -1
- package/dist/index.cjs +0 -30
- package/dist/index.cjs.map +0 -1
- package/dist/index.js +0 -30
- package/dist/index.js.map +0 -1
- package/dist/inference/index.cjs +0 -7
- package/dist/inference/index.cjs.map +0 -1
- package/dist/inference/index.d.cts +0 -229
- package/dist/inference/index.d.ts +0 -229
- package/dist/inference/index.js +0 -7
- package/dist/inference/index.js.map +0 -1
- package/dist/server-runtime/index.cjs +0 -9
- package/dist/server-runtime/index.cjs.map +0 -1
- package/dist/server-runtime/index.js +0 -9
- package/dist/server-runtime/index.js.map +0 -1
- package/dist/step-machine/index.cjs.map +0 -1
- package/dist/step-machine/index.d.cts +0 -102
- package/dist/step-machine/index.d.ts +0 -102
- package/dist/step-machine/index.js.map +0 -1
- package/dist/step-machine-public/index.cjs +0 -3
- package/dist/step-machine-public/index.cjs.map +0 -1
- package/dist/step-machine-public/index.js +0 -3
- package/dist/step-machine-public/index.js.map +0 -1
- package/dist/storage-refs.cjs.map +0 -1
- package/dist/storage-refs.js.map +0 -1
- package/dist/stores/file.cjs +0 -2
- package/dist/stores/file.cjs.map +0 -1
- package/dist/stores/file.d.cts +0 -36
- package/dist/stores/file.d.ts +0 -36
- package/dist/stores/file.js +0 -2
- package/dist/stores/file.js.map +0 -1
- package/dist/stores/index.cjs +0 -2
- package/dist/stores/index.cjs.map +0 -1
- package/dist/stores/index.d.cts +0 -4
- package/dist/stores/index.d.ts +0 -4
- package/dist/stores/index.js +0 -2
- package/dist/stores/index.js.map +0 -1
- package/dist/stores/localStorage.cjs +0 -2
- package/dist/stores/localStorage.cjs.map +0 -1
- package/dist/stores/localStorage.d.cts +0 -34
- package/dist/stores/localStorage.d.ts +0 -34
- package/dist/stores/localStorage.js +0 -2
- package/dist/stores/localStorage.js.map +0 -1
- package/dist/stores/memory.cjs.map +0 -1
- package/dist/stores/memory.js.map +0 -1
- package/dist/types-CHSdoAAA.d.cts +0 -135
- package/dist/types-CoW0gQl3.d.ts +0 -135
- package/examples/browser/boards/portfolio-tracker/portfolio-tracker-fetch-prices.py +0 -201
- package/examples/browser/boards/portfolio-tracker/portfolio-tracker-http-test.js +0 -370
- package/examples/browser/boards/portfolio-tracker/portfolio-tracker-http-test.py +0 -398
- package/examples/browser/boards/portfolio-tracker/portfolio-tracker-inference-adapter.js +0 -196
- package/examples/browser/boards/portfolio-tracker/portfolio-tracker-server.js +0 -300
- package/examples/browser/boards/portfolio-tracker/portfolio-tracker-server.py +0 -617
- package/examples/browser/boards/portfolio-tracker/portfolio-tracker.py +0 -366
- package/examples/browser/livecards-browser/index.html +0 -41
- package/examples/browser/step-machine-browser/index.html +0 -367
- package/examples/cli/step-machine-cli/portfolio-tracker/--base-ref/.runtime-out +0 -1
- package/examples/cli/step-machine-cli/portfolio-tracker/--base-ref/board-graph.json +0 -32
- package/examples/cli/step-machine-cli/portfolio-tracker/cards/holdings-table.json +0 -22
- package/examples/cli/step-machine-cli/portfolio-tracker/cards/portfolio-form.json +0 -43
- package/examples/cli/step-machine-cli/portfolio-tracker/cards/portfolio-value.json +0 -15
- package/examples/cli/step-machine-cli/portfolio-tracker/cards/price-fetch.json +0 -15
- package/examples/cli/step-machine-cli/portfolio-tracker/fetch-prices.js +0 -48
- package/examples/cli/step-machine-cli/portfolio-tracker/handlers/_board-cli.js +0 -125
- package/examples/cli/step-machine-cli/portfolio-tracker/handlers/add-cards-cli.js +0 -32
- package/examples/cli/step-machine-cli/portfolio-tracker/handlers/init-board-cli.js +0 -26
- package/examples/cli/step-machine-cli/portfolio-tracker/handlers/poll-status-cli.js +0 -49
- package/examples/cli/step-machine-cli/portfolio-tracker/handlers/reset-board-dir-cli.js +0 -25
- package/examples/cli/step-machine-cli/portfolio-tracker/handlers/retrigger-cli.js +0 -23
- package/examples/cli/step-machine-cli/portfolio-tracker/handlers/status-cli.js +0 -21
- package/examples/cli/step-machine-cli/portfolio-tracker/handlers/update-holdings-cli.js +0 -38
- package/examples/cli/step-machine-cli/portfolio-tracker/handlers/wait-completed-cli.js +0 -48
- package/examples/cli/step-machine-cli/portfolio-tracker/handlers/write-prices-cli.js +0 -31
- package/examples/cli/step-machine-cli/portfolio-tracker/handlers-py/_board_pycli.py +0 -107
- package/examples/cli/step-machine-cli/portfolio-tracker/handlers-py/add-cards.py +0 -51
- package/examples/cli/step-machine-cli/portfolio-tracker/handlers-py/init-board.py +0 -45
- package/examples/cli/step-machine-cli/portfolio-tracker/handlers-py/poll-status.py +0 -71
- package/examples/cli/step-machine-cli/portfolio-tracker/handlers-py/reset-board-dir.py +0 -36
- package/examples/cli/step-machine-cli/portfolio-tracker/inline-python-demo.flow.yaml +0 -26
- package/examples/cli/step-machine-cli/portfolio-tracker/inline-python-handlers.py +0 -39
- package/examples/cli/step-machine-cli/portfolio-tracker/portfolio-tracker-pycli.flow.yaml +0 -80
- package/examples/cli/step-machine-cli/portfolio-tracker/portfolio-tracker.flow.yaml +0 -76
- package/examples/cli/step-machine-cli/portfolio-tracker/portfolio-tracker.input.json +0 -44
- package/examples/cli/step-machine-cli/portfolio-tracker/run-inline-python-demo-pycli.py +0 -43
- package/examples/cli/step-machine-cli/portfolio-tracker/run-portfolio-tracker-pycli.py +0 -77
- package/examples/cli/step-machine-cli/portfolio-tracker/run-portfolio-tracker.bat +0 -28
- package/examples/cli/step-machine-demo/jsonata-init-board-cli.js +0 -31
- package/examples/cli/step-machine-demo/jsonata-init-board.flow.yaml +0 -54
- package/examples/cli/step-machine-demo/one-step-cli-only.flow.yaml +0 -21
- package/examples/cli/step-machine-demo/step-cli-echo-y.js +0 -15
- package/examples/cli/step-machine-demo/step2-double-cli.js +0 -33
- package/examples/cli/step-machine-demo/two-step-math.flow.yaml +0 -93
- package/examples/cli/step-machine-demo/two-step-mixed.flow.yaml +0 -43
- package/examples/example-board/agent-instructions-cardlayout.md +0 -56
- package/examples/example-board/agent-instructions.md +0 -834
- package/examples/example-board/demo-shell.html +0 -63
- package/examples/index.html +0 -785
- package/examples/npm-libs/batch/batch-step-machine.ts +0 -121
- package/examples/npm-libs/continuous-event-graph/live-cards-board.ts +0 -215
- package/examples/npm-libs/continuous-event-graph/live-portfolio-dashboard.ts +0 -555
- package/examples/npm-libs/continuous-event-graph/portfolio-tracker.ts +0 -287
- package/examples/npm-libs/continuous-event-graph/reactive-monitoring.ts +0 -265
- package/examples/npm-libs/continuous-event-graph/reactive-pipeline.ts +0 -168
- package/examples/npm-libs/continuous-event-graph/soc-incident-board.ts +0 -287
- package/examples/npm-libs/continuous-event-graph/stock-dashboard.ts +0 -229
- package/examples/npm-libs/event-graph/ci-cd-pipeline.ts +0 -243
- package/examples/npm-libs/event-graph/executor-diamond.ts +0 -165
- package/examples/npm-libs/event-graph/executor-pipeline.ts +0 -161
- package/examples/npm-libs/event-graph/research-pipeline.ts +0 -137
- package/examples/npm-libs/flows/ai-conversation.yaml +0 -116
- package/examples/npm-libs/flows/order-processing.yaml +0 -143
- package/examples/npm-libs/flows/simple-greeting.yaml +0 -54
- package/examples/npm-libs/graph-of-graphs/multi-stage-etl.ts +0 -307
- package/examples/npm-libs/graph-of-graphs/url-processing-pipeline.ts +0 -254
- package/examples/npm-libs/inference/azure-deployment.ts +0 -149
- package/examples/npm-libs/inference/copilot-cli.ts +0 -138
- package/examples/npm-libs/inference/data-pipeline.ts +0 -145
- package/examples/npm-libs/inference/pluggable-adapters.ts +0 -254
- package/examples/npm-libs/node/ai-conversation.ts +0 -195
- package/examples/npm-libs/node/simple-greeting.ts +0 -101
- package/examples/step-machine-cli/portfolio-tracker/cards/holdings-table.json +0 -22
- package/examples/step-machine-cli/portfolio-tracker/cards/portfolio-form.json +0 -43
- package/examples/step-machine-cli/portfolio-tracker/cards/portfolio-value.json +0 -15
- package/examples/step-machine-cli/portfolio-tracker/cards/price-fetch.json +0 -15
- package/examples/step-machine-cli/portfolio-tracker/fetch-prices.js +0 -48
- package/examples/step-machine-cli/portfolio-tracker/handlers/_board-cli.js +0 -57
- package/examples/step-machine-cli/portfolio-tracker/handlers/add-cards-cli.js +0 -27
- package/examples/step-machine-cli/portfolio-tracker/handlers/init-board-cli.js +0 -25
- package/examples/step-machine-cli/portfolio-tracker/handlers/reset-board-dir-cli.js +0 -29
- package/examples/step-machine-cli/portfolio-tracker/handlers/retrigger-cli.js +0 -27
- package/examples/step-machine-cli/portfolio-tracker/handlers/status-cli.js +0 -25
- package/examples/step-machine-cli/portfolio-tracker/handlers/update-holdings-cli.js +0 -37
- package/examples/step-machine-cli/portfolio-tracker/handlers/wait-completed-cli.js +0 -53
- package/examples/step-machine-cli/portfolio-tracker/handlers/write-prices-cli.js +0 -35
- package/examples/step-machine-cli/portfolio-tracker/portfolio-tracker-task-executor.cjs +0 -96
- package/examples/step-machine-cli/portfolio-tracker/portfolio-tracker.flow.yaml +0 -227
- package/examples/step-machine-cli/portfolio-tracker/portfolio-tracker.input.json +0 -38
- package/examples/step-machine-cli/portfolio-tracker/run-portfolio-tracker.bat +0 -28
- package/step-machine-cli.js +0 -407
- /package/{dist/cli → cli}/browser-api/board-live-cards-browser-adapter.js +0 -0
- /package/{dist/board-livegraph-runtime → cli/browser-api}/jsonata-sync.cjs +0 -0
- /package/{dist/cli → cli}/node/artifacts-store-cli.d.ts +0 -0
- /package/{dist/cli/node/source-cli-task-executor.d.cts → cli/node/batch-runner-cli.d.ts} +0 -0
- /package/{dist/cli → cli}/node/board-live-cards-cli.d.ts +0 -0
- /package/{dist/cli → cli}/node/card-store-cli.d.ts +0 -0
- /package/{dist/cli → cli}/node/card-store-cli.js +0 -0
- /package/{dist/card-compute → cli/node}/jsonata-sync.cjs +0 -0
- /package/{dist/cli → cli}/node/source-cli-task-executor.d.ts +0 -0
- /package/{dist/cli → cli}/node/source-cli-task-executor.js +0 -0
- /package/examples/{example-board → board}/cards/card-concentration.json +0 -0
- /package/examples/{example-board → board}/cards/card-my-identity.json +0 -0
- /package/examples/{example-board → board}/cards/card-portfolio-action.json +0 -0
- /package/examples/{example-board → board}/cards/card-portfolio-intelligence.json +0 -0
- /package/examples/{example-board → board}/cards/card-portfolio-risks.json +0 -0
- /package/examples/{example-board → board}/cards/card-rebalance-impact.json +0 -0
- /package/examples/{example-board → board}/cards/card-rebalance-sim.json +0 -0
- /package/examples/{example-board → board}/cards/cardT-market-prices.json +0 -0
- /package/examples/{example-board → board}/cards/cardT-portfolio-value.json +0 -0
- /package/examples/{example-board → board}/cards/cardT-portfolio.json +0 -0
- /package/examples/{example-board → board}/demo-chat-handler.js +0 -0
- /package/examples/{example-board → board}/scripts/copilot_wrapper.bat +0 -0
- /package/examples/{example-board → board}/scripts/copilot_wrapper_helper.ps1 +0 -0
- /package/examples/{example-board → board}/scripts/workiq_wrapper.mjs +0 -0
- /package/examples/{browser/boards/portfolio-tracker → board/test}/portfolio-tracker-sse-worker.js +0 -0
- /package/{dist → lib}/batch/index.cjs +0 -0
- /package/{dist → lib}/batch/index.d.cts +0 -0
- /package/{dist → lib}/batch/index.d.ts +0 -0
- /package/{dist → lib}/batch/index.js +0 -0
- /package/{dist/cli/browser-api → lib/board-livegraph-runtime}/jsonata-sync.cjs +0 -0
- /package/{dist → lib}/card-compute/index.d.cts +0 -0
- /package/{dist → lib}/card-compute/index.d.ts +0 -0
- /package/{dist/cli/node → lib/card-compute}/jsonata-sync.cjs +0 -0
- /package/{dist → lib}/config/index.cjs +0 -0
- /package/{dist → lib}/config/index.d.cts +0 -0
- /package/{dist → lib}/config/index.d.ts +0 -0
- /package/{dist → lib}/config/index.js +0 -0
- /package/{dist → lib}/continuous-event-graph/jsonata-sync.cjs +0 -0
- /package/{dist → lib}/event-graph/index.cjs +0 -0
- /package/{dist → lib}/event-graph/index.js +0 -0
- /package/{dist → lib}/execution-refs.cjs +0 -0
- /package/{dist → lib}/execution-refs.js +0 -0
- /package/{dist → lib}/jsonata-sync.cjs +0 -0
- /package/{dist → lib}/server-runtime/jsonata-sync.cjs +0 -0
- /package/{dist → lib}/step-machine/index.cjs +0 -0
- /package/{dist → lib}/step-machine/index.js +0 -0
- /package/{dist → lib}/step-machine-public/jsonata-sync.cjs +0 -0
- /package/{dist → lib}/stores/memory.cjs +0 -0
- /package/{dist → lib}/stores/memory.js +0 -0
- /package/{dist → lib}/types-BBhqYGhE.d.cts +0 -0
- /package/{dist → lib}/types-BBhqYGhE.d.ts +0 -0
- /package/{dist → lib}/validate-BAVzUJWa.d.ts +0 -0
- /package/{dist → lib}/validate-Dbu7ygys.d.cts +0 -0
|
@@ -1,370 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* portfolio-tracker-http-test.js
|
|
4
|
-
*
|
|
5
|
-
* E2E test for the portfolio-tracker board via HTTP + SSE.
|
|
6
|
-
*
|
|
7
|
-
* Two parallel tracks:
|
|
8
|
-
*
|
|
9
|
-
* Worker thread (portfolio-tracker-sse-worker.js) — SSE consumer
|
|
10
|
-
* Opens the board's /sse endpoint, parses every frame, and forwards it
|
|
11
|
-
* to the main thread via parentPort.postMessage({ type: 'frame', payload }).
|
|
12
|
-
*
|
|
13
|
-
* Main thread (this file) — Test driver
|
|
14
|
-
* Accumulates state from worker messages into NotificationState (NS).
|
|
15
|
-
* Drives sequential test steps (T1–T5) via HTTP PATCH/GET.
|
|
16
|
-
* All "wait for X" helpers poll NS with setInterval — no callbacks needed.
|
|
17
|
-
*
|
|
18
|
-
* Usage:
|
|
19
|
-
* node portfolio-tracker-http-test.js [--port 7800] [--server node|py]
|
|
20
|
-
*/
|
|
21
|
-
|
|
22
|
-
import { Worker } from 'node:worker_threads';
|
|
23
|
-
import { spawn, spawnSync } from 'node:child_process';
|
|
24
|
-
import { fileURLToPath } from 'node:url';
|
|
25
|
-
import path from 'node:path';
|
|
26
|
-
import http from 'node:http';
|
|
27
|
-
|
|
28
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
29
|
-
const __dirname = path.dirname(__filename);
|
|
30
|
-
|
|
31
|
-
const cliArgs = process.argv.slice(2);
|
|
32
|
-
const portArg = cliArgs.indexOf('--port');
|
|
33
|
-
const serverArg = cliArgs.indexOf('--server');
|
|
34
|
-
const SERVER_TYPE = serverArg !== -1 ? cliArgs[serverArg + 1] : 'node'; // 'node' | 'py'
|
|
35
|
-
const PORT = portArg !== -1 ? parseInt(cliArgs[portArg + 1], 10) : (SERVER_TYPE === 'py' ? 7801 : 7800);
|
|
36
|
-
const BASE = `http://127.0.0.1:${PORT}/api/board`;
|
|
37
|
-
const SERVER_SCRIPT = path.join(__dirname, 'portfolio-tracker-server.js');
|
|
38
|
-
const PY_SERVER_SCRIPT = path.join(__dirname, 'portfolio-tracker-server.py');
|
|
39
|
-
const SSE_WORKER_SCRIPT = path.join(__dirname, 'portfolio-tracker-sse-worker.js');
|
|
40
|
-
|
|
41
|
-
/** Find a working Python interpreter. Returns null if none found. */
|
|
42
|
-
function findPython() {
|
|
43
|
-
const candidates = ['python3', 'python'];
|
|
44
|
-
for (const cmd of candidates) {
|
|
45
|
-
try {
|
|
46
|
-
const r = spawnSync(cmd, ['--version'], { stdio: 'pipe', timeout: 3000 });
|
|
47
|
-
if (r.status === 0 && r.stdout?.toString().startsWith('Python ')) return cmd;
|
|
48
|
-
} catch { /* next */ }
|
|
49
|
-
}
|
|
50
|
-
return null;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
// =============================================================================
|
|
54
|
-
// NOTIFICATION STATE — accumulated by the main thread from worker SSE frames
|
|
55
|
-
// =============================================================================
|
|
56
|
-
const NS = {
|
|
57
|
-
initialPayload: null, // first full snapshot frame
|
|
58
|
-
statusSummary: null, // latest { card_count, completed, failed, ... }
|
|
59
|
-
statusGeneration: 0, // bumped on every status notification received
|
|
60
|
-
dataObjects: {}, // token → payload (e.g. 'prices' → { AAPL: 142.5, ... })
|
|
61
|
-
computedValues: {}, // cardId → values (e.g. 'holdings-table' → { table: { rows: [...] } })
|
|
62
|
-
cardRefreshedCount: 0, // total card_refreshed notifications seen
|
|
63
|
-
cardRefreshedByCardId: {},// cardId → count
|
|
64
|
-
};
|
|
65
|
-
|
|
66
|
-
// Apply a parsed SSE frame into NS (called from worker message handler)
|
|
67
|
-
function applyFrame(payload) {
|
|
68
|
-
// Initial full snapshot — has cardDefinitions
|
|
69
|
-
if (payload.cardDefinitions) {
|
|
70
|
-
NS.initialPayload = payload;
|
|
71
|
-
if (payload.statusSnapshot?.summary) {
|
|
72
|
-
NS.statusSummary = payload.statusSnapshot.summary;
|
|
73
|
-
NS.statusGeneration++;
|
|
74
|
-
}
|
|
75
|
-
if (payload.dataObjectsByToken) {
|
|
76
|
-
Object.assign(NS.dataObjects, payload.dataObjectsByToken);
|
|
77
|
-
}
|
|
78
|
-
if (payload.cardRuntimeById) {
|
|
79
|
-
for (const [cardId, runtime] of Object.entries(payload.cardRuntimeById)) {
|
|
80
|
-
if (runtime?.computed_values && Object.keys(runtime.computed_values).length > 0) {
|
|
81
|
-
NS.computedValues[cardId] = runtime.computed_values;
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
return;
|
|
86
|
-
}
|
|
87
|
-
// Subsequent frames — notification-batch
|
|
88
|
-
if (payload.kind === 'notification-batch' && Array.isArray(payload.notifications)) {
|
|
89
|
-
for (const n of payload.notifications) {
|
|
90
|
-
if (n.kind === 'status' && n.status?.summary) {
|
|
91
|
-
NS.statusSummary = n.status.summary;
|
|
92
|
-
NS.statusGeneration++;
|
|
93
|
-
} else if (n.kind === 'data_object' && n.key) {
|
|
94
|
-
NS.dataObjects[n.key] = n.payload;
|
|
95
|
-
} else if (n.kind === 'computed_values' && n.cardId) {
|
|
96
|
-
NS.computedValues[n.cardId] = n.values;
|
|
97
|
-
} else if (n.kind === 'card_refreshed') {
|
|
98
|
-
NS.cardRefreshedCount++;
|
|
99
|
-
if (typeof n.cardId === 'string' && n.cardId) {
|
|
100
|
-
NS.cardRefreshedByCardId[n.cardId] = (NS.cardRefreshedByCardId[n.cardId] || 0) + 1;
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
// ── Polling helpers (poll NS, never block the event loop) ───────────────────
|
|
108
|
-
|
|
109
|
-
function assert(condition, message) {
|
|
110
|
-
if (!condition) {
|
|
111
|
-
console.error(`\n[ASSERT FAILED] ${message}`);
|
|
112
|
-
process.exit(1);
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
function waitUntil(predicate, timeoutMs, label) {
|
|
117
|
-
return new Promise((resolve, reject) => {
|
|
118
|
-
const deadline = Date.now() + timeoutMs;
|
|
119
|
-
const interval = setInterval(() => {
|
|
120
|
-
let result;
|
|
121
|
-
try { result = predicate(); } catch { /* retry */ }
|
|
122
|
-
if (result !== undefined && result !== null && result !== false) {
|
|
123
|
-
clearInterval(interval);
|
|
124
|
-
resolve(result);
|
|
125
|
-
return;
|
|
126
|
-
}
|
|
127
|
-
if (Date.now() > deadline) {
|
|
128
|
-
clearInterval(interval);
|
|
129
|
-
reject(new Error(`Timeout (${timeoutMs}ms) waiting for: ${label}\n NS.statusSummary=${JSON.stringify(NS.statusSummary)}\n dataObjects=${JSON.stringify(Object.keys(NS.dataObjects))}`));
|
|
130
|
-
}
|
|
131
|
-
}, 150);
|
|
132
|
-
});
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
// Waits for first full payload frame from SSE worker
|
|
136
|
-
const waitForInitialPayload = (ms = 15_000) =>
|
|
137
|
-
waitUntil(() => NS.initialPayload || false, ms, 'initial SSE payload');
|
|
138
|
-
|
|
139
|
-
// Waits for all cards to reach completed status
|
|
140
|
-
const waitForAllCompleted = (ms = 60_000, label = 'all completed') =>
|
|
141
|
-
waitUntil(() => {
|
|
142
|
-
const s = NS.statusSummary;
|
|
143
|
-
return (s && s.card_count > 0 && s.completed === s.card_count) ? s : false;
|
|
144
|
-
}, ms, label);
|
|
145
|
-
|
|
146
|
-
// Waits until prices data object has exactly the expected set of symbols
|
|
147
|
-
function waitForPriceSymbols(expectedSymbols, ms = 30_000, label = 'price symbols') {
|
|
148
|
-
const expected = [...expectedSymbols].sort().join(',');
|
|
149
|
-
return waitUntil(() => {
|
|
150
|
-
const prices = NS.dataObjects['prices'];
|
|
151
|
-
if (!prices || typeof prices !== 'object') return false;
|
|
152
|
-
const actual = Object.keys(prices).sort().join(',');
|
|
153
|
-
return actual === expected ? prices : false;
|
|
154
|
-
}, ms, `${label}: expected [${expected}]`);
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
// ── HTTP helpers ─────────────────────────────────────────────────────────────
|
|
158
|
-
|
|
159
|
-
function httpGet(url) {
|
|
160
|
-
return new Promise((resolve, reject) => {
|
|
161
|
-
http.get(url, (res) => {
|
|
162
|
-
let body = '';
|
|
163
|
-
res.on('data', c => { body += c; });
|
|
164
|
-
res.on('end', () => {
|
|
165
|
-
try { resolve({ status: res.statusCode, data: JSON.parse(body) }); }
|
|
166
|
-
catch { resolve({ status: res.statusCode, data: body }); }
|
|
167
|
-
});
|
|
168
|
-
}).on('error', reject);
|
|
169
|
-
});
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
function httpPatch(url, payload) {
|
|
173
|
-
return new Promise((resolve, reject) => {
|
|
174
|
-
const body = JSON.stringify(payload);
|
|
175
|
-
const req = http.request(url, {
|
|
176
|
-
method: 'PATCH',
|
|
177
|
-
headers: { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(body) },
|
|
178
|
-
}, (res) => {
|
|
179
|
-
let data = '';
|
|
180
|
-
res.on('data', c => { data += c; });
|
|
181
|
-
res.on('end', () => {
|
|
182
|
-
try { resolve({ status: res.statusCode, data: JSON.parse(data) }); }
|
|
183
|
-
catch { resolve({ status: res.statusCode, data }); }
|
|
184
|
-
});
|
|
185
|
-
});
|
|
186
|
-
req.on('error', reject);
|
|
187
|
-
req.write(body);
|
|
188
|
-
req.end();
|
|
189
|
-
});
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
function makeHoldingsPatch(holdingsMap) {
|
|
193
|
-
return {
|
|
194
|
-
card_data: {
|
|
195
|
-
holdings: Object.entries(holdingsMap).map(([symbol, qty]) => ({ symbol, qty })),
|
|
196
|
-
},
|
|
197
|
-
};
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
// ── Server process ────────────────────────────────────────────────────────────
|
|
201
|
-
|
|
202
|
-
function startServer(port) {
|
|
203
|
-
const isPy = SERVER_TYPE === 'py';
|
|
204
|
-
let cmd, cmdArgs;
|
|
205
|
-
if (isPy) {
|
|
206
|
-
const python = findPython();
|
|
207
|
-
if (!python) throw new Error('Python interpreter not found on PATH');
|
|
208
|
-
cmd = python;
|
|
209
|
-
cmdArgs = [PY_SERVER_SCRIPT, '--port', String(port), '--reset'];
|
|
210
|
-
} else {
|
|
211
|
-
cmd = process.execPath;
|
|
212
|
-
cmdArgs = [SERVER_SCRIPT, '--port', String(port), '--reset'];
|
|
213
|
-
}
|
|
214
|
-
return new Promise((resolve, reject) => {
|
|
215
|
-
const proc = spawn(cmd, cmdArgs, {
|
|
216
|
-
stdio: ['ignore', 'pipe', 'pipe'],
|
|
217
|
-
windowsHide: true,
|
|
218
|
-
});
|
|
219
|
-
let ready = false;
|
|
220
|
-
proc.stdout.on('data', (chunk) => {
|
|
221
|
-
const text = chunk.toString('utf-8');
|
|
222
|
-
process.stdout.write(`[server] ${text}`);
|
|
223
|
-
if (!ready && text.includes('listening on')) { ready = true; resolve(proc); }
|
|
224
|
-
});
|
|
225
|
-
proc.stderr.on('data', (chunk) => process.stderr.write(`[server:err] ${chunk}`));
|
|
226
|
-
proc.on('error', reject);
|
|
227
|
-
proc.on('exit', (code) => { if (!ready) reject(new Error(`Server exited early: code ${code}`)); });
|
|
228
|
-
setTimeout(() => { if (!ready) reject(new Error('Server startup timeout (15s)')); }, 15_000);
|
|
229
|
-
});
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
// ── Main ──────────────────────────────────────────────────────────────────────
|
|
233
|
-
|
|
234
|
-
console.log('\n=== portfolio-tracker HTTP E2E test ===');
|
|
235
|
-
console.log(`target: ${BASE} [server: ${SERVER_TYPE}]`);
|
|
236
|
-
console.log(`architecture: main-thread (test driver) + worker-thread (SSE consumer)\n`);
|
|
237
|
-
|
|
238
|
-
const serverProc = await startServer(PORT);
|
|
239
|
-
await new Promise(r => setTimeout(r, 300)); // brief settle
|
|
240
|
-
|
|
241
|
-
let sseWorker = null;
|
|
242
|
-
try {
|
|
243
|
-
// ── Step 1: init-board ──────────────────────────────────────────────────────
|
|
244
|
-
console.log('\n=== Step 1: init-board ===');
|
|
245
|
-
const initRes = await httpGet(`${BASE}/init-board`);
|
|
246
|
-
assert(initRes.status === 200, `init-board returned ${initRes.status}`);
|
|
247
|
-
console.log('[step1] ok');
|
|
248
|
-
|
|
249
|
-
// ── Step 2: Start SSE consumer worker ───────────────────────────────────────
|
|
250
|
-
// The worker opens /sse and forwards every parsed frame here via postMessage.
|
|
251
|
-
// Main thread accumulates frames into NS via applyFrame().
|
|
252
|
-
console.log('\n=== Step 2: Start SSE consumer worker ===');
|
|
253
|
-
sseWorker = new Worker(SSE_WORKER_SCRIPT, {
|
|
254
|
-
workerData: { sseUrl: `${BASE}/sse` },
|
|
255
|
-
});
|
|
256
|
-
sseWorker.on('message', (msg) => {
|
|
257
|
-
if (msg.type === 'frame') {
|
|
258
|
-
applyFrame(msg.payload);
|
|
259
|
-
} else if (msg.type === 'error') {
|
|
260
|
-
console.error(`[sse-worker] error: ${msg.message}`);
|
|
261
|
-
} else if (msg.type === 'closed') {
|
|
262
|
-
console.log('[sse-worker] SSE stream closed by server');
|
|
263
|
-
}
|
|
264
|
-
});
|
|
265
|
-
sseWorker.on('error', (err) => console.error(`[sse-worker] uncaught: ${err.message}`));
|
|
266
|
-
|
|
267
|
-
const initialPayload = await waitForInitialPayload();
|
|
268
|
-
console.log(`[step2] SSE worker online — initial payload (${initialPayload.cardDefinitions?.length ?? 0} cards)`);
|
|
269
|
-
console.log(` statusGen=${NS.statusGeneration}, dataObjects=${JSON.stringify(Object.keys(NS.dataObjects))}`);
|
|
270
|
-
|
|
271
|
-
// ── T1: Wait for initial drain ──────────────────────────────────────────────
|
|
272
|
-
console.log('\n=== T1: Wait for initial completion ===');
|
|
273
|
-
const t1Summary = await waitForAllCompleted(60_000, 'T1 initial drain');
|
|
274
|
-
console.log(`[T1] board completed — ${JSON.stringify(t1Summary)}`);
|
|
275
|
-
|
|
276
|
-
const t1Prices = await waitForPriceSymbols(['AAPL', 'MSFT'], 30_000, 'T1 prices');
|
|
277
|
-
assert(Object.values(t1Prices).every(v => typeof v === 'number'), 'T1: all prices must be numbers');
|
|
278
|
-
const t1Table = NS.computedValues['holdings-table']?.table;
|
|
279
|
-
assert(Array.isArray(t1Table?.rows) && t1Table.rows.length === 2, `T1: expected 2 rows, got ${t1Table?.rows?.length}`);
|
|
280
|
-
const t1Total = NS.computedValues['portfolio-value']?.totalValue;
|
|
281
|
-
assert(typeof t1Total === 'number' && t1Total > 0, `T1: totalValue must be positive, got ${t1Total}`);
|
|
282
|
-
console.log(`[T1] passed: prices=[AAPL,MSFT], rows=2, totalValue=${t1Total.toFixed(2)}`);
|
|
283
|
-
|
|
284
|
-
// ── T2a: Add GOOG to holdings ────────────────────────────────────────────────
|
|
285
|
-
console.log('\n=== T2a: Update holdings — add GOOG ===');
|
|
286
|
-
const t2CardRefreshedBefore = NS.cardRefreshedCount;
|
|
287
|
-
const t2Patch = await httpPatch(
|
|
288
|
-
`${BASE}/cards/portfolio-form`,
|
|
289
|
-
makeHoldingsPatch({ AAPL: 50, MSFT: 30, GOOG: 100 }),
|
|
290
|
-
);
|
|
291
|
-
assert(t2Patch.status === 200, `PATCH portfolio-form returned ${t2Patch.status}`);
|
|
292
|
-
console.log('[T2a] PATCH ok — worker will receive SSE notifications independently');
|
|
293
|
-
|
|
294
|
-
// ── T2b: Wait for 3-ticker completion ───────────────────────────────────────
|
|
295
|
-
console.log('\n=== T2b: Wait for 3-ticker completion ===');
|
|
296
|
-
const t2Summary = await waitForAllCompleted(60_000, 'T2b 3-ticker drain');
|
|
297
|
-
console.log(`[T2b] completed — ${JSON.stringify(t2Summary)}`);
|
|
298
|
-
|
|
299
|
-
const t2Prices = await waitForPriceSymbols(['AAPL', 'GOOG', 'MSFT'], 30_000, 'T2b prices');
|
|
300
|
-
const t2CardRefreshedAfter = NS.cardRefreshedCount;
|
|
301
|
-
assert(
|
|
302
|
-
t2CardRefreshedAfter > t2CardRefreshedBefore,
|
|
303
|
-
`T2b: expected at least one card_refreshed notification after PATCH (before=${t2CardRefreshedBefore}, after=${t2CardRefreshedAfter})`,
|
|
304
|
-
);
|
|
305
|
-
const t2Table = NS.computedValues['holdings-table']?.table;
|
|
306
|
-
assert(Array.isArray(t2Table?.rows) && t2Table.rows.length === 3, `T2b: expected 3 rows, got ${t2Table?.rows?.length}`);
|
|
307
|
-
const t2Total = NS.computedValues['portfolio-value']?.totalValue;
|
|
308
|
-
assert(typeof t2Total === 'number' && t2Total > 0, 'T2b: totalValue must be positive');
|
|
309
|
-
console.log(`[T2b] passed: prices=[AAPL,GOOG,MSFT], rows=3, totalValue=${t2Total.toFixed(2)}`);
|
|
310
|
-
|
|
311
|
-
// ── T3: Rapid 3× holdings updates (queue stress) ─────────────────────────────
|
|
312
|
-
// The worker independently streams all SSE notifications while the driver
|
|
313
|
-
// fires rapid PATCHes. NS accumulates state continuously in both cases.
|
|
314
|
-
console.log('\n=== T3: Rapid 3× holdings updates ===');
|
|
315
|
-
const rapidUpdates = [
|
|
316
|
-
{ AAPL: 45, MSFT: 30, GOOG: 110, TSLA: 60 },
|
|
317
|
-
{ AAPL: 45, MSFT: 30, GOOG: 110, AMZN: 100 }, // intermediate — not expected to be final
|
|
318
|
-
{ AAPL: 40, MSFT: 35, GOOG: 120, TSLA: 70 }, // V5 — expected final state
|
|
319
|
-
];
|
|
320
|
-
for (const holdings of rapidUpdates) {
|
|
321
|
-
await httpPatch(`${BASE}/cards/portfolio-form`, makeHoldingsPatch(holdings));
|
|
322
|
-
}
|
|
323
|
-
console.log('[T3] rapid PATCHes sent — worker accumulates SSE state in parallel');
|
|
324
|
-
|
|
325
|
-
await waitForAllCompleted(60_000, 'T3 rapid-update drain');
|
|
326
|
-
const t3Prices = await waitForPriceSymbols(['AAPL', 'GOOG', 'MSFT', 'TSLA'], 30_000, 'T3 final prices');
|
|
327
|
-
const t3Table = NS.computedValues['holdings-table']?.table;
|
|
328
|
-
assert(Array.isArray(t3Table?.rows) && t3Table.rows.length === 4, `T3: expected 4 rows, got ${t3Table?.rows?.length}`);
|
|
329
|
-
assert(!Object.keys(t3Prices).includes('AMZN'), `T3: AMZN must not be present (got ${JSON.stringify(Object.keys(t3Prices))})`);
|
|
330
|
-
console.log(`[T3] passed: prices=${JSON.stringify(Object.keys(t3Prices).sort())}, rows=4, AMZN absent`);
|
|
331
|
-
|
|
332
|
-
// ── T4: Cross-verify portfolio-value totalValue ───────────────────────────────
|
|
333
|
-
console.log('\n=== T4: Cross-verify totalValue ===');
|
|
334
|
-
const t4Total = NS.computedValues['portfolio-value']?.totalValue;
|
|
335
|
-
assert(typeof t4Total === 'number' && t4Total > 0, `T4: totalValue must be positive, got ${t4Total}`);
|
|
336
|
-
const sumRows = t3Table.rows.reduce((acc, r) => acc + (r.value || 0), 0);
|
|
337
|
-
assert(Math.abs(sumRows - t4Total) < 0.01, `T4: mismatch: sumRows=${sumRows}, totalValue=${t4Total}`);
|
|
338
|
-
console.log(`[T4] passed: totalValue=${t4Total.toFixed(2)}, sumRows=${sumRows.toFixed(2)}`);
|
|
339
|
-
|
|
340
|
-
// ── T5: board-status HTTP cross-check ────────────────────────────────────────
|
|
341
|
-
// Compare the HTTP board-status endpoint response against what the worker
|
|
342
|
-
// accumulated via SSE — the two sources must agree.
|
|
343
|
-
console.log('\n=== T5: board-status HTTP cross-check ===');
|
|
344
|
-
const t5Res = await httpGet(`${BASE}/board-status`);
|
|
345
|
-
assert(t5Res.status === 200, `board-status returned ${t5Res.status}`);
|
|
346
|
-
const t5Summary = t5Res.data?.statusSnapshot?.summary;
|
|
347
|
-
assert(t5Summary, 'T5: statusSnapshot.summary missing from board-status');
|
|
348
|
-
assert(t5Summary.completed === t5Summary.card_count,
|
|
349
|
-
`T5: completed=${t5Summary.completed} !== card_count=${t5Summary.card_count}`);
|
|
350
|
-
assert(t5Summary.failed === 0, `T5: failed=${t5Summary.failed} (expected 0)`);
|
|
351
|
-
|
|
352
|
-
// Cross-check: dataObjects from HTTP response matches what worker accumulated
|
|
353
|
-
const httpDataObjKeys = Object.keys(t5Res.data.dataObjectsByToken || {}).sort().join(',');
|
|
354
|
-
const workerDataObjKeys = Object.keys(NS.dataObjects).sort().join(',');
|
|
355
|
-
assert(httpDataObjKeys === workerDataObjKeys,
|
|
356
|
-
`T5: HTTP dataObjects keys [${httpDataObjKeys}] differ from worker-accumulated [${workerDataObjKeys}]`);
|
|
357
|
-
|
|
358
|
-
console.log(`[T5] summary: ${JSON.stringify(t5Summary)}`);
|
|
359
|
-
console.log(`[T5] HTTP vs worker dataObjects agree: [${workerDataObjKeys}]`);
|
|
360
|
-
console.log(`[T5] statusGen at end: ${NS.statusGeneration}`);
|
|
361
|
-
console.log('[T5] all assertions passed');
|
|
362
|
-
|
|
363
|
-
console.log('\n=== All tests passed ✓ ===\n');
|
|
364
|
-
|
|
365
|
-
} finally {
|
|
366
|
-
sseWorker?.terminate();
|
|
367
|
-
serverProc.kill();
|
|
368
|
-
await new Promise(r => serverProc.on('exit', r));
|
|
369
|
-
console.log(`[portfolio-tracker-http-test] server stopped (${SERVER_TYPE})`);
|
|
370
|
-
}
|