yaml-flow 6.0.0 → 7.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/board-live-cards-cli.js +4 -4
- package/browser/asset-integrity.json +3 -3
- package/browser/board-livecards-client.js +2 -0
- package/browser/board-livecards-client.js.map +1 -0
- package/browser/board-livecards-localstorage.js +10 -0
- package/browser/board-livecards-localstorage.js.map +1 -0
- package/browser/board-livegraph-engine.js +2 -2
- package/browser/board-livegraph-engine.js.map +1 -1
- package/browser/card-compute.js +28 -28
- package/browser/compute-jsonata.js +5 -0
- package/browser/compute-jsonata.js.map +1 -0
- package/browser/live-cards.js +261 -150
- package/card-store.js +4 -4
- package/dist/{board-live-cards-public-CltXYgaY.d.cts → board-live-cards-public-CW5074xr.d.cts} +9 -5
- package/dist/{board-live-cards-public-f-E-FAyp.d.ts → board-live-cards-public-hnZo0mAf.d.ts} +9 -5
- package/dist/board-livegraph-runtime/index.cjs +2 -2
- package/dist/board-livegraph-runtime/index.cjs.map +1 -1
- package/dist/board-livegraph-runtime/index.d.cts +11 -9
- package/dist/board-livegraph-runtime/index.d.ts +11 -9
- package/dist/board-livegraph-runtime/index.js +2 -2
- package/dist/board-livegraph-runtime/index.js.map +1 -1
- package/dist/board-livegraph-runtime/jsonata-sync.cjs +37 -1
- package/dist/card-compute/index.cjs +4 -4
- package/dist/card-compute/index.cjs.map +1 -1
- package/dist/card-compute/index.d.cts +5 -1
- package/dist/card-compute/index.d.ts +5 -1
- package/dist/card-compute/index.js +4 -4
- package/dist/card-compute/index.js.map +1 -1
- package/dist/card-compute/jsonata-sync.cjs +37 -1
- package/dist/cli/browser-api/board-live-cards-browser-adapter.cjs +2 -1
- package/dist/cli/browser-api/board-live-cards-browser-adapter.cjs.map +1 -1
- package/dist/cli/browser-api/board-live-cards-browser-adapter.d.cts +27 -14
- package/dist/cli/browser-api/board-live-cards-browser-adapter.d.ts +27 -14
- package/dist/cli/browser-api/board-live-cards-browser-adapter.js +2 -1
- package/dist/cli/browser-api/board-live-cards-browser-adapter.js.map +1 -1
- package/dist/cli/browser-api/card-store-browser-api.cjs +1 -1
- package/dist/cli/browser-api/card-store-browser-api.cjs.map +1 -1
- package/dist/cli/browser-api/card-store-browser-api.js +1 -1
- package/dist/cli/browser-api/card-store-browser-api.js.map +1 -1
- package/dist/cli/browser-api/jsonata-sync.cjs +37 -1
- package/dist/cli/node/artifacts-store-cli.cjs +8 -8
- package/dist/cli/node/artifacts-store-cli.cjs.map +1 -1
- package/dist/cli/node/artifacts-store-cli.js +8 -8
- package/dist/cli/node/artifacts-store-cli.js.map +1 -1
- package/dist/cli/node/board-live-cards-cli.cjs +7 -7
- package/dist/cli/node/board-live-cards-cli.cjs.map +1 -1
- package/dist/cli/node/board-live-cards-cli.js +7 -7
- package/dist/cli/node/board-live-cards-cli.js.map +1 -1
- package/dist/cli/node/card-store-cli.cjs +5 -5
- package/dist/cli/node/card-store-cli.cjs.map +1 -1
- package/dist/cli/node/card-store-cli.js +5 -5
- package/dist/cli/node/card-store-cli.js.map +1 -1
- package/dist/cli/node/execution-adapter.cjs +3 -0
- package/dist/cli/node/execution-adapter.cjs.map +1 -0
- package/dist/cli/node/execution-adapter.d.cts +174 -0
- package/dist/cli/node/execution-adapter.d.ts +174 -0
- package/dist/cli/node/execution-adapter.js +3 -0
- package/dist/cli/node/execution-adapter.js.map +1 -0
- package/dist/cli/node/fs-board-adapter.cjs +7 -7
- package/dist/cli/node/fs-board-adapter.cjs.map +1 -1
- package/dist/cli/node/fs-board-adapter.d.cts +2 -2
- package/dist/cli/node/fs-board-adapter.d.ts +2 -2
- package/dist/cli/node/fs-board-adapter.js +7 -7
- package/dist/cli/node/fs-board-adapter.js.map +1 -1
- package/dist/cli/node/jsonata-sync.cjs +37 -1
- package/dist/cli/node/source-cli-task-executor.cjs +4 -4
- package/dist/cli/node/source-cli-task-executor.cjs.map +1 -1
- package/dist/cli/node/source-cli-task-executor.js +4 -4
- package/dist/cli/node/source-cli-task-executor.js.map +1 -1
- package/dist/continuous-event-graph/index.cjs +2 -2
- package/dist/continuous-event-graph/index.cjs.map +1 -1
- package/dist/continuous-event-graph/index.js +2 -2
- package/dist/continuous-event-graph/index.js.map +1 -1
- package/dist/continuous-event-graph/jsonata-sync.cjs +37 -1
- package/dist/execution-refs.cjs +2 -1
- package/dist/execution-refs.cjs.map +1 -1
- package/dist/execution-refs.d.cts +49 -11
- package/dist/execution-refs.d.ts +49 -11
- package/dist/execution-refs.js +2 -1
- package/dist/execution-refs.js.map +1 -1
- package/dist/index.cjs +10 -10
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +10 -10
- package/dist/index.js.map +1 -1
- package/dist/jsonata-sync.cjs +37 -1
- package/dist/server-runtime/index.cjs +9 -0
- package/dist/server-runtime/index.cjs.map +1 -0
- package/dist/server-runtime/index.d.cts +31 -0
- package/dist/server-runtime/index.d.ts +31 -0
- package/dist/server-runtime/index.js +9 -0
- package/dist/server-runtime/index.js.map +1 -0
- package/dist/server-runtime/jsonata-sync.cjs +7623 -0
- package/dist/step-machine-public/index.cjs +2 -0
- package/dist/step-machine-public/index.cjs.map +1 -0
- package/dist/step-machine-public/index.d.cts +159 -0
- package/dist/step-machine-public/index.d.ts +159 -0
- package/dist/step-machine-public/index.js +2 -0
- package/dist/step-machine-public/index.js.map +1 -0
- package/dist/step-machine-public/jsonata-sync.cjs +7623 -0
- package/dist/storage-refs.cjs +2 -2
- package/dist/storage-refs.cjs.map +1 -1
- package/dist/storage-refs.d.cts +7 -6
- package/dist/storage-refs.d.ts +7 -6
- package/dist/storage-refs.js +2 -2
- package/dist/storage-refs.js.map +1 -1
- package/dist/types-B1ZRa4aI.d.ts +147 -0
- package/dist/types-BxEFcVK9.d.cts +147 -0
- package/examples/browser/boards/portfolio-tracker/portfolio-t4.js +9 -10
- package/examples/browser/boards/portfolio-tracker/portfolio-tracker-http-test.js +357 -0
- package/examples/browser/boards/portfolio-tracker/portfolio-tracker-public.js +9 -10
- package/examples/browser/boards/portfolio-tracker/portfolio-tracker-server.js +300 -0
- package/examples/browser/boards/portfolio-tracker/portfolio-tracker-server.py +617 -0
- package/examples/browser/boards/portfolio-tracker/portfolio-tracker-sse-worker.js +48 -0
- package/examples/browser/boards/portfolio-tracker/portfolio-tracker.py +11 -10
- package/examples/cli/step-machine-cli/portfolio-tracker/handlers/_board-cli.js +19 -4
- package/examples/cli/step-machine-cli/portfolio-tracker/handlers/add-cards-cli.js +4 -8
- package/examples/cli/step-machine-cli/portfolio-tracker/handlers/init-board-cli.js +6 -10
- package/examples/cli/step-machine-cli/portfolio-tracker/handlers/poll-status-cli.js +8 -16
- package/examples/cli/step-machine-cli/portfolio-tracker/handlers/reset-board-dir-cli.js +2 -6
- package/examples/cli/step-machine-cli/portfolio-tracker/handlers/retrigger-cli.js +4 -8
- package/examples/cli/step-machine-cli/portfolio-tracker/handlers/status-cli.js +3 -7
- package/examples/cli/step-machine-cli/portfolio-tracker/handlers/update-holdings-cli.js +4 -8
- package/examples/cli/step-machine-cli/portfolio-tracker/handlers/wait-completed-cli.js +7 -16
- package/examples/cli/step-machine-cli/portfolio-tracker/handlers/write-prices-cli.js +2 -6
- package/examples/cli/step-machine-cli/portfolio-tracker/handlers-py/_board_pycli.py +13 -3
- package/examples/cli/step-machine-cli/portfolio-tracker/handlers-py/add-cards.py +2 -1
- package/examples/cli/step-machine-cli/portfolio-tracker/handlers-py/init-board.py +2 -1
- package/examples/cli/step-machine-cli/portfolio-tracker/handlers-py/poll-status.py +2 -1
- package/examples/cli/step-machine-cli/portfolio-tracker/portfolio-tracker.flow.yaml +20 -24
- package/examples/cli/step-machine-cli/portfolio-tracker/run-inline-python-demo-pycli.py +0 -3
- package/examples/cli/step-machine-demo/jsonata-init-board-cli.js +8 -13
- package/examples/cli/step-machine-demo/jsonata-init-board.flow.yaml +33 -9
- package/examples/cli/step-machine-demo/one-step-cli-only.flow.yaml +3 -1
- package/examples/cli/step-machine-demo/step2-double-cli.js +6 -12
- package/examples/cli/step-machine-demo/two-step-math.flow.yaml +66 -4
- package/examples/cli/step-machine-demo/two-step-mixed.flow.yaml +13 -5
- package/examples/example-board/cards/_index.json +47 -0
- package/examples/example-board/cards/card-market-prices.json +33 -9
- package/examples/example-board/cards/card-my-identity.json +30 -6
- package/examples/example-board/cards/card-portfolio-action.json +24 -6
- package/examples/example-board/cards/card-portfolio-intelligence.json +97 -0
- package/examples/example-board/cards/card-portfolio-risks.json +24 -6
- package/examples/example-board/cards/card-portfolio-value.json +38 -10
- package/examples/example-board/cards/card-portfolio.json +57 -13
- package/examples/example-board/cards/card-rebalance-impact.json +22 -6
- package/examples/example-board/cards/card-rebalance-sim.json +66 -15
- package/examples/example-board/demo-server.js +360 -69
- package/examples/example-board/demo-shell-localstorage.html +774 -0
- package/examples/example-board/demo-shell-with-server.html +18 -36
- package/examples/example-board/demo-shell.html +5 -4
- package/examples/example-board/demo-task-executor.js +217 -265
- package/package.json +15 -13
- package/step-machine-cli.js +43 -310
- package/board-livecards-server-runtime.js +0 -1513
- package/browser/board-livecards-runtime-client.js +0 -263
- package/dist/pycli/quickjs-board-runtime.global.js +0 -9
- package/dist/pycli/quickjs-board-runtime.global.js.map +0 -1
- package/dist/pycli/quickjs-step-machine-runtime.global.js +0 -5
- package/dist/pycli/quickjs-step-machine-runtime.global.js.map +0 -1
- package/examples/cli/step-machine-demo/two-step-math-handlers.js +0 -32
- package/examples/cli/step-machine-demo/two-step-mixed-handlers.js +0 -24
- package/examples/example-board/demo-shell-browser.html +0 -675
package/step-machine-cli.js
CHANGED
|
@@ -2,11 +2,31 @@
|
|
|
2
2
|
|
|
3
3
|
import * as fs from 'node:fs';
|
|
4
4
|
import * as path from 'node:path';
|
|
5
|
-
import {
|
|
5
|
+
import { fileURLToPath } from 'node:url';
|
|
6
6
|
import { spawnSync } from 'node:child_process';
|
|
7
|
-
|
|
7
|
+
|
|
8
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
9
|
+
const srcCli = path.join(__dirname, 'src', 'cli', 'node', 'step-machine-cli.ts');
|
|
10
|
+
const tsxCli = path.join(__dirname, 'node_modules', 'tsx', 'dist', 'cli.mjs');
|
|
11
|
+
|
|
12
|
+
if (fs.existsSync(srcCli)) {
|
|
13
|
+
const result = spawnSync(process.execPath, [tsxCli, srcCli, ...process.argv.slice(2)], {
|
|
14
|
+
stdio: 'inherit',
|
|
15
|
+
shell: false,
|
|
16
|
+
windowsHide: true,
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
if (result.error) {
|
|
20
|
+
console.error(`[step-machine-cli] Failed to launch dev fallback: ${result.error.message}`);
|
|
21
|
+
process.exit(1);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
process.exit(result.status ?? 0);
|
|
25
|
+
}
|
|
8
26
|
|
|
9
27
|
const { loadStepFlow, createStepMachine, MemoryStore, FileStore } = await import('./dist/index.js');
|
|
28
|
+
const { buildStepHandlersForFlow } = await import('./dist/step-machine-public/index.js');
|
|
29
|
+
const { invokeRefSync } = await import('./dist/cli/node/execution-adapter.js');
|
|
10
30
|
const PAUSE_FILE_NAME = '.pause';
|
|
11
31
|
|
|
12
32
|
async function main() {
|
|
@@ -20,7 +40,6 @@ async function main() {
|
|
|
20
40
|
|
|
21
41
|
const {
|
|
22
42
|
flowArg,
|
|
23
|
-
handlersArg,
|
|
24
43
|
dataArg,
|
|
25
44
|
storeArg,
|
|
26
45
|
storeDirArg,
|
|
@@ -29,8 +48,8 @@ async function main() {
|
|
|
29
48
|
statusRequested,
|
|
30
49
|
} = parsed;
|
|
31
50
|
|
|
32
|
-
if ((pauseRequested || statusRequested) && (
|
|
33
|
-
throw new Error('[step-machine-cli] --pause and --status are store-level operations. Do not provide flow,
|
|
51
|
+
if ((pauseRequested || statusRequested) && (dataArg || resumeRequested || flowArg)) {
|
|
52
|
+
throw new Error('[step-machine-cli] --pause and --status are store-level operations. Do not provide flow, data, or --resume.');
|
|
34
53
|
}
|
|
35
54
|
|
|
36
55
|
if (resumeRequested && dataArg) {
|
|
@@ -55,13 +74,11 @@ async function main() {
|
|
|
55
74
|
|
|
56
75
|
const flowPath = resolveInputPath(flowArg);
|
|
57
76
|
const flowDir = path.dirname(flowPath);
|
|
58
|
-
const handlersPath = handlersArg ? resolveInputPath(handlersArg) : undefined;
|
|
59
77
|
const initialData = parseInitialData(dataArg);
|
|
60
78
|
const { store } = storeContext;
|
|
61
79
|
|
|
62
80
|
const flow = await loadStepFlow(flowPath);
|
|
63
|
-
const
|
|
64
|
-
const handlers = buildStepHandlers(flow, inlineHandlers, flowDir, flow.handler_vars);
|
|
81
|
+
const handlers = buildStepHandlers(flow, flowDir);
|
|
65
82
|
|
|
66
83
|
// Resume/start should ignore stale pause markers from previous runs.
|
|
67
84
|
clearPauseRequest(storeContext);
|
|
@@ -127,7 +144,7 @@ async function main() {
|
|
|
127
144
|
}
|
|
128
145
|
|
|
129
146
|
function parseCliArgs(args) {
|
|
130
|
-
const valueFlags = new Set(['--
|
|
147
|
+
const valueFlags = new Set(['--initial-data', '--store', '--store-dir']);
|
|
131
148
|
const values = {};
|
|
132
149
|
const positionals = [];
|
|
133
150
|
let help = false;
|
|
@@ -181,7 +198,6 @@ function parseCliArgs(args) {
|
|
|
181
198
|
return {
|
|
182
199
|
help,
|
|
183
200
|
flowArg: positionals[0],
|
|
184
|
-
handlersArg: values['--handlers'],
|
|
185
201
|
dataArg: values['--initial-data'],
|
|
186
202
|
storeArg: String(values['--store'] ?? 'memory').toLowerCase(),
|
|
187
203
|
storeDirArg: values['--store-dir'],
|
|
@@ -348,319 +364,36 @@ function parseInitialData(dataArg) {
|
|
|
348
364
|
}
|
|
349
365
|
}
|
|
350
366
|
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
if (!candidate || typeof candidate !== 'object') {
|
|
356
|
-
throw new Error('[step-machine-cli] Handlers module must export an object map of stepName -> function.');
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
for (const [stepName, handler] of Object.entries(candidate)) {
|
|
360
|
-
if (typeof handler !== 'function') {
|
|
361
|
-
throw new Error(`[step-machine-cli] Handler for step "${stepName}" is not a function.`);
|
|
362
|
-
}
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
return candidate;
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
function buildStepHandlers(flow, inlineHandlers, flowDir, handlerVars) {
|
|
369
|
-
const handlers = {};
|
|
370
|
-
|
|
371
|
-
for (const [stepName, stepConfig] of Object.entries(flow.steps ?? {})) {
|
|
372
|
-
handlers[stepName] = resolveStepHandler(stepName, stepConfig, inlineHandlers, flowDir, handlerVars);
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
return handlers;
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
function resolveStepHandler(stepName, stepConfig, inlineHandlers, flowDir, handlerVars) {
|
|
379
|
-
const produces = Array.isArray(stepConfig?.produces_data) ? stepConfig.produces_data : undefined;
|
|
380
|
-
const spec = stepConfig?.handler;
|
|
381
|
-
|
|
382
|
-
if (isCliSpec(spec)) {
|
|
383
|
-
const base = createCliStepHandler(spec, flowDir, stepName, handlerVars);
|
|
384
|
-
return wrapWithOutputFiltering(base, produces);
|
|
385
|
-
}
|
|
386
|
-
|
|
387
|
-
if (isInlineSpec(spec)) {
|
|
388
|
-
const inlineName = spec.inline;
|
|
389
|
-
const handler = inlineHandlers[inlineName];
|
|
390
|
-
if (typeof handler !== 'function') {
|
|
391
|
-
throw new Error(`[step-machine-cli] Inline handler "${inlineName}" for step "${stepName}" was not found in --handlers module.`);
|
|
392
|
-
}
|
|
393
|
-
return wrapWithOutputFiltering(handler, produces);
|
|
394
|
-
}
|
|
395
|
-
|
|
396
|
-
// Default behavior is explicit and predictable: no configured handler means passthrough.
|
|
397
|
-
return wrapWithOutputFiltering(createPassthroughHandler(), produces);
|
|
398
|
-
}
|
|
399
|
-
|
|
400
|
-
function isCliSpec(spec) {
|
|
401
|
-
return !!spec && typeof spec === 'object' && typeof spec.cli === 'string' && spec.cli.trim().length > 0;
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
function isInlineSpec(spec) {
|
|
405
|
-
return !!spec && typeof spec === 'object' && typeof spec.inline === 'string' && spec.inline.trim().length > 0;
|
|
406
|
-
}
|
|
407
|
-
|
|
408
|
-
function createCliStepHandler(spec, flowDir, stepName, handlerVars) {
|
|
409
|
-
return async (input) => {
|
|
410
|
-
const stepInput = input && typeof input === 'object' && !Array.isArray(input)
|
|
411
|
-
? input
|
|
412
|
-
: {};
|
|
413
|
-
|
|
414
|
-
const resolvedHandlerVars = await evaluateTransforms(
|
|
415
|
-
handlerVars,
|
|
416
|
-
stepInput,
|
|
417
|
-
stepName,
|
|
418
|
-
'handler_vars',
|
|
419
|
-
);
|
|
420
|
-
|
|
421
|
-
const inputTransforms = await evaluateTransforms(
|
|
422
|
-
spec['input-transforms'],
|
|
423
|
-
{ ...stepInput, ...resolvedHandlerVars },
|
|
424
|
-
stepName,
|
|
425
|
-
'input-transforms',
|
|
426
|
-
);
|
|
427
|
-
|
|
428
|
-
const effectiveInput = { ...stepInput, ...resolvedHandlerVars, ...inputTransforms };
|
|
429
|
-
const command = applyCommandTemplate(spec.cli, effectiveInput, stepName);
|
|
430
|
-
|
|
431
|
-
const payload = JSON.stringify(effectiveInput);
|
|
432
|
-
const result = spawnSync(command, {
|
|
433
|
-
cwd: flowDir,
|
|
434
|
-
shell: true,
|
|
435
|
-
input: payload,
|
|
436
|
-
encoding: 'utf-8',
|
|
437
|
-
windowsHide: true,
|
|
438
|
-
});
|
|
439
|
-
|
|
440
|
-
if (result.error) {
|
|
441
|
-
return {
|
|
442
|
-
result: 'failure',
|
|
443
|
-
data: { error: `[step-machine-cli] step "${stepName}" failed to start: ${result.error.message}` },
|
|
444
|
-
};
|
|
445
|
-
}
|
|
446
|
-
|
|
447
|
-
const stdout = result.stdout ?? '';
|
|
448
|
-
const stderr = (result.stderr ?? '').trim();
|
|
449
|
-
const resultMode = String(spec['result-mode'] ?? 'json').toLowerCase();
|
|
450
|
-
|
|
451
|
-
if (result.status !== 0) {
|
|
452
|
-
return {
|
|
453
|
-
result: 'failure',
|
|
454
|
-
data: {
|
|
455
|
-
error: `[step-machine-cli] step "${stepName}" exited with status ${result.status}${stderr ? `: ${stderr}` : ''}`,
|
|
456
|
-
},
|
|
457
|
-
};
|
|
458
|
-
}
|
|
459
|
-
|
|
460
|
-
if (resultMode === 'exit-code') {
|
|
461
|
-
const outputTransforms = await evaluateTransforms(
|
|
462
|
-
spec['output-transforms'],
|
|
463
|
-
{
|
|
464
|
-
...effectiveInput,
|
|
465
|
-
result: 'success',
|
|
466
|
-
stdout,
|
|
467
|
-
stderr,
|
|
468
|
-
},
|
|
469
|
-
stepName,
|
|
470
|
-
'output-transforms',
|
|
471
|
-
);
|
|
472
|
-
|
|
473
|
-
return {
|
|
474
|
-
result: 'success',
|
|
475
|
-
data: outputTransforms,
|
|
476
|
-
};
|
|
477
|
-
}
|
|
478
|
-
|
|
479
|
-
try {
|
|
480
|
-
const parsed = parseJsonOutput(stdout);
|
|
481
|
-
const normalized = normalizeHandlerResult(parsed, stepName);
|
|
482
|
-
const outputTransforms = await evaluateTransforms(
|
|
483
|
-
spec['output-transforms'],
|
|
484
|
-
{
|
|
485
|
-
...effectiveInput,
|
|
486
|
-
result: normalized.result,
|
|
487
|
-
data: normalized.data,
|
|
488
|
-
},
|
|
489
|
-
stepName,
|
|
490
|
-
'output-transforms',
|
|
491
|
-
);
|
|
492
|
-
|
|
493
|
-
if (Object.keys(outputTransforms).length === 0) {
|
|
494
|
-
return normalized;
|
|
495
|
-
}
|
|
496
|
-
|
|
497
|
-
return {
|
|
498
|
-
result: normalized.result,
|
|
499
|
-
data: outputTransforms,
|
|
500
|
-
};
|
|
501
|
-
} catch (error) {
|
|
502
|
-
const msg = error instanceof Error ? error.message : String(error);
|
|
503
|
-
return {
|
|
504
|
-
result: 'failure',
|
|
505
|
-
data: {
|
|
506
|
-
error: `[step-machine-cli] step "${stepName}" returned invalid JSON on stdout: ${msg}`,
|
|
507
|
-
},
|
|
508
|
-
};
|
|
509
|
-
}
|
|
510
|
-
};
|
|
511
|
-
}
|
|
512
|
-
|
|
513
|
-
async function evaluateTransforms(transformSpec, source, stepName, label) {
|
|
514
|
-
if (transformSpec === undefined || transformSpec === null) {
|
|
515
|
-
return {};
|
|
516
|
-
}
|
|
517
|
-
|
|
518
|
-
if (!transformSpec || typeof transformSpec !== 'object' || Array.isArray(transformSpec)) {
|
|
519
|
-
throw new Error(`[step-machine-cli] Step "${stepName}" ${label} must be an object map of key -> JSONata expression.`);
|
|
520
|
-
}
|
|
521
|
-
|
|
522
|
-
const result = {};
|
|
523
|
-
for (const [key, expression] of Object.entries(transformSpec)) {
|
|
524
|
-
if (typeof expression !== 'string') {
|
|
525
|
-
// Non-string values are treated as literals for convenience.
|
|
526
|
-
result[key] = expression;
|
|
527
|
-
continue;
|
|
528
|
-
}
|
|
529
|
-
|
|
530
|
-
if (expression.trim().length === 0) {
|
|
531
|
-
throw new Error(`[step-machine-cli] Step "${stepName}" ${label}.${key} must be a non-empty string expression.`);
|
|
532
|
-
}
|
|
533
|
-
|
|
534
|
-
// handler_vars defaults to literal strings for ergonomics; use "=..." for JSONata expressions.
|
|
535
|
-
if (label === 'handler_vars' && !expression.startsWith('=')) {
|
|
536
|
-
result[key] = expression;
|
|
537
|
-
continue;
|
|
538
|
-
}
|
|
539
|
-
|
|
540
|
-
const jsonataExpression = label === 'handler_vars' && expression.startsWith('=')
|
|
541
|
-
? expression.slice(1)
|
|
542
|
-
: expression;
|
|
543
|
-
|
|
544
|
-
// Convenience: direct key aliasing supports non-identifier keys like BOARD-DIR-NAME.
|
|
545
|
-
if (Object.prototype.hasOwnProperty.call(source, jsonataExpression)) {
|
|
546
|
-
result[key] = source[jsonataExpression];
|
|
547
|
-
continue;
|
|
548
|
-
}
|
|
549
|
-
|
|
550
|
-
try {
|
|
551
|
-
const compiled = jsonata(jsonataExpression);
|
|
552
|
-
result[key] = await compiled.evaluate(source);
|
|
553
|
-
} catch (error) {
|
|
554
|
-
const msg = error instanceof Error ? error.message : String(error);
|
|
555
|
-
throw new Error(`[step-machine-cli] Step "${stepName}" ${label}.${key} failed: ${msg}`);
|
|
556
|
-
}
|
|
557
|
-
}
|
|
558
|
-
|
|
559
|
-
return result;
|
|
560
|
-
}
|
|
561
|
-
|
|
562
|
-
function applyCommandTemplate(command, source, stepName) {
|
|
563
|
-
if (typeof command !== 'string' || command.trim().length === 0) {
|
|
564
|
-
throw new Error(`[step-machine-cli] Step "${stepName}" handler.cli must be a non-empty command string.`);
|
|
565
|
-
}
|
|
566
|
-
|
|
567
|
-
return command.replace(/%%([A-Za-z0-9_-]+)%%/g, (full, key) => {
|
|
568
|
-
if (!Object.prototype.hasOwnProperty.call(source, key)) {
|
|
569
|
-
throw new Error(`[step-machine-cli] Step "${stepName}" command placeholder ${full} has no matching input or input-transform value.`);
|
|
570
|
-
}
|
|
571
|
-
|
|
572
|
-
const value = source[key];
|
|
573
|
-
if (value === undefined || value === null) {
|
|
574
|
-
throw new Error(`[step-machine-cli] Step "${stepName}" command placeholder ${full} resolved to empty value.`);
|
|
575
|
-
}
|
|
576
|
-
|
|
577
|
-
return String(value);
|
|
578
|
-
});
|
|
579
|
-
}
|
|
580
|
-
|
|
581
|
-
function createPassthroughHandler() {
|
|
582
|
-
return async (input) => {
|
|
583
|
-
const data = input && typeof input === 'object' && !Array.isArray(input)
|
|
584
|
-
? input
|
|
585
|
-
: {};
|
|
586
|
-
|
|
587
|
-
return {
|
|
588
|
-
result: 'success',
|
|
589
|
-
data,
|
|
590
|
-
};
|
|
591
|
-
};
|
|
592
|
-
}
|
|
593
|
-
|
|
594
|
-
function parseJsonOutput(stdout) {
|
|
595
|
-
const trimmed = stdout.trim();
|
|
596
|
-
if (!trimmed) {
|
|
597
|
-
throw new Error('empty stdout');
|
|
598
|
-
}
|
|
367
|
+
function normalizeExecutionRef(ref) {
|
|
368
|
+
if (!ref || typeof ref !== 'object') return ref;
|
|
369
|
+
if (typeof ref.whatToRun !== 'string' || !ref.whatToRun.startsWith('b64:')) return ref;
|
|
599
370
|
|
|
600
371
|
try {
|
|
601
|
-
|
|
372
|
+
const payload = ref.whatToRun.slice(4);
|
|
373
|
+
const padded = payload + '='.repeat((4 - (payload.length % 4)) % 4);
|
|
374
|
+
const json = Buffer.from(padded.replace(/-/g, '+').replace(/_/g, '/'), 'base64').toString('utf8');
|
|
375
|
+
const decoded = JSON.parse(json);
|
|
376
|
+
if (!decoded || typeof decoded !== 'object' || typeof decoded.value !== 'string') {
|
|
377
|
+
return ref;
|
|
378
|
+
}
|
|
379
|
+
return { ...ref, whatToRun: decoded.value };
|
|
602
380
|
} catch {
|
|
603
|
-
|
|
604
|
-
const last = lines[lines.length - 1];
|
|
605
|
-
return JSON.parse(last);
|
|
381
|
+
return ref;
|
|
606
382
|
}
|
|
607
383
|
}
|
|
608
384
|
|
|
609
|
-
function
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
const normalized = normalizeHandlerResult(raw, context?.stepName ?? 'unknown');
|
|
613
|
-
const filteredData = filterProducedData(normalized.data, produces);
|
|
614
|
-
return {
|
|
615
|
-
result: normalized.result,
|
|
616
|
-
data: filteredData,
|
|
617
|
-
};
|
|
618
|
-
};
|
|
619
|
-
}
|
|
620
|
-
|
|
621
|
-
function normalizeHandlerResult(raw, stepName) {
|
|
622
|
-
if (!raw || typeof raw !== 'object') {
|
|
623
|
-
throw new Error(`[step-machine-cli] Step "${stepName}" returned a non-object result.`);
|
|
624
|
-
}
|
|
625
|
-
|
|
626
|
-
const result = raw.result ?? raw.status;
|
|
627
|
-
if (typeof result !== 'string' || result.trim().length === 0) {
|
|
628
|
-
throw new Error(`[step-machine-cli] Step "${stepName}" result must include a non-empty "result" (or "status") string.`);
|
|
629
|
-
}
|
|
630
|
-
|
|
631
|
-
const data = raw.data && typeof raw.data === 'object' && !Array.isArray(raw.data)
|
|
632
|
-
? raw.data
|
|
633
|
-
: {};
|
|
634
|
-
|
|
635
|
-
const error = typeof raw.error === 'string' ? raw.error : undefined;
|
|
636
|
-
if (error && !('error' in data)) {
|
|
637
|
-
data.error = error;
|
|
638
|
-
}
|
|
639
|
-
|
|
640
|
-
return { result, data };
|
|
641
|
-
}
|
|
642
|
-
|
|
643
|
-
function filterProducedData(data, produces) {
|
|
644
|
-
if (!produces || produces.length === 0) {
|
|
645
|
-
return data;
|
|
646
|
-
}
|
|
647
|
-
|
|
648
|
-
const filtered = {};
|
|
649
|
-
for (const key of produces) {
|
|
650
|
-
if (Object.prototype.hasOwnProperty.call(data, key)) {
|
|
651
|
-
filtered[key] = data[key];
|
|
652
|
-
}
|
|
653
|
-
}
|
|
654
|
-
return filtered;
|
|
385
|
+
function buildStepHandlers(flow, flowDir) {
|
|
386
|
+
const invoke = (ref, args) => invokeRefSync(normalizeExecutionRef(ref), args, { cliDir: flowDir, cwd: flowDir });
|
|
387
|
+
return buildStepHandlersForFlow(flow, { invoke });
|
|
655
388
|
}
|
|
656
389
|
|
|
657
390
|
function printUsage() {
|
|
658
|
-
console.error('Usage: step-machine-cli <step-flow.yaml> [--
|
|
391
|
+
console.error('Usage: step-machine-cli <step-flow.yaml> [--initial-data <json>] [--store <memory|file>] [--store-dir <directory>] [--resume]');
|
|
659
392
|
console.error(' step-machine-cli --store file --store-dir <directory> --pause');
|
|
660
393
|
console.error(' step-machine-cli --store file --store-dir <directory> --status');
|
|
661
394
|
console.error('');
|
|
662
395
|
console.error('Example:');
|
|
663
|
-
console.error(' step-machine-cli examples/step-machine-demo/two-step-
|
|
396
|
+
console.error(' step-machine-cli examples/cli/step-machine-demo/two-step-math.flow.yaml --initial-data "{\"a\":3,\"b\":4}"');
|
|
664
397
|
console.error(' step-machine-cli ./flow.yaml --store file --store-dir ./.runs');
|
|
665
398
|
console.error(' step-machine-cli ./flow.yaml --store file --store-dir ./.runs --resume');
|
|
666
399
|
console.error(' step-machine-cli --store file --store-dir ./.runs --pause');
|