feat(server): enhance workflow step execution and JSONata integration
- Refactored step execution logic to introduce runCompiledStep for improved clarity and functionality. - Added support for "set" steps, allowing context manipulation using JSONata expressions. - Implemented evaluateJsonata and isJsonataTruthy functions for evaluating conditions and expressions. - Updated workflow parsing to handle new step types and validation rules. - Enhanced logging and error handling for skipped steps and invalid configurations. - Modified UI components to reflect new step types and statuses, including "skipped".
This commit is contained in:
@@ -13,7 +13,9 @@ export function StatusBadge({ status }) {
|
||||
? "badge-error"
|
||||
: status === "running"
|
||||
? "badge-warning"
|
||||
: "badge-ghost";
|
||||
: status === "skipped"
|
||||
? "badge-info"
|
||||
: "badge-ghost";
|
||||
return <span className={`badge badge-sm ${cls}`}>{status ?? "—"}</span>;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,12 +1,26 @@
|
||||
function parseStep(step) {
|
||||
if (typeof step === "string") {
|
||||
return { script: step, id: null, needs: null };
|
||||
return { kind: "script", script: step, id: null, needs: null, when: null, as: null };
|
||||
}
|
||||
if (step?.set) {
|
||||
const as = typeof step.set?.as === "string" && step.set.as ? step.set.as : "set";
|
||||
return {
|
||||
kind: "set",
|
||||
script: null,
|
||||
as,
|
||||
id: typeof step.id === "string" && step.id ? step.id : null,
|
||||
needs: null,
|
||||
when: typeof step.when === "string" && step.when ? step.when : null,
|
||||
};
|
||||
}
|
||||
if (step?.script) {
|
||||
return {
|
||||
kind: "script",
|
||||
script: step.script,
|
||||
as: null,
|
||||
id: typeof step.id === "string" && step.id ? step.id : null,
|
||||
needs: step.needs ?? null,
|
||||
when: typeof step.when === "string" && step.when ? step.when : null,
|
||||
};
|
||||
}
|
||||
return null;
|
||||
@@ -38,6 +52,15 @@ function triggerLabel(t) {
|
||||
return `${method} ${path}`.trim();
|
||||
}
|
||||
|
||||
function stepLabel(s) {
|
||||
if (s.kind === "set") {
|
||||
const base = s.id ? `${s.id}: set ${s.as}` : `set ${s.as}`;
|
||||
return s.when ? `${base} when: ${s.when}` : base;
|
||||
}
|
||||
const base = s.id ? `${s.id}: ${s.script}` : s.script;
|
||||
return s.when ? `${base} when: ${s.when}` : base;
|
||||
}
|
||||
|
||||
export function workflowToFlowchart(parsed) {
|
||||
/** @type {Record<string, string>} */
|
||||
const scriptIds = {};
|
||||
@@ -72,9 +95,13 @@ export function workflowToFlowchart(parsed) {
|
||||
}
|
||||
|
||||
for (const s of parsedSteps) {
|
||||
scriptIds[s.mermaidId] = s.script;
|
||||
const label = s.id ? `${s.id}: ${s.script}` : s.script;
|
||||
lines.push(` ${s.mermaidId}["${mermaidLabel(label)}"]`);
|
||||
const label = mermaidLabel(stepLabel(s));
|
||||
if (s.kind === "set") {
|
||||
lines.push(` ${s.mermaidId}(["${label}"])`);
|
||||
} else {
|
||||
scriptIds[s.mermaidId] = s.script;
|
||||
lines.push(` ${s.mermaidId}["${label}"]`);
|
||||
}
|
||||
}
|
||||
|
||||
if (dagMode) {
|
||||
|
||||
@@ -4,6 +4,17 @@ import { useRun } from "../api/hooks.js";
|
||||
import { LogViewer } from "../components/LogViewer.jsx";
|
||||
import { formatTime, StatusBadge } from "../lib/format.jsx";
|
||||
|
||||
function stepLabel(s) {
|
||||
if (s.script === "set") {
|
||||
return s.config?.as ? `set:${s.config.as}` : "set";
|
||||
}
|
||||
return s.script;
|
||||
}
|
||||
|
||||
function isEditableScript(s) {
|
||||
return Boolean(s.script) && s.script !== "set";
|
||||
}
|
||||
|
||||
export function EventDetailPage() {
|
||||
const { id } = useParams();
|
||||
const { data: run, isLoading, error } = useRun(id);
|
||||
@@ -67,9 +78,13 @@ export function EventDetailPage() {
|
||||
<tr key={s.id}>
|
||||
<td>{s.step_index}</td>
|
||||
<td className="font-mono">
|
||||
<Link className="link" to={`/scripts/${encodeURIComponent(s.script)}/edit`}>
|
||||
{s.script}
|
||||
</Link>
|
||||
{isEditableScript(s) ? (
|
||||
<Link className="link" to={`/scripts/${encodeURIComponent(s.script)}/edit`}>
|
||||
{stepLabel(s)}
|
||||
</Link>
|
||||
) : (
|
||||
stepLabel(s)
|
||||
)}
|
||||
</td>
|
||||
<td>
|
||||
<StatusBadge status={s.status} />
|
||||
|
||||
@@ -38,6 +38,7 @@ export function EventsPage() {
|
||||
<option value="running">running</option>
|
||||
<option value="success">success</option>
|
||||
<option value="failed">failed</option>
|
||||
<option value="skipped">skipped</option>
|
||||
</select>
|
||||
</div>
|
||||
{isLoading ? (
|
||||
|
||||
Reference in New Issue
Block a user