- Introduced a new contract for script returns, requiring an object with `output`, `context`, and `skipRemaining` fields. - Refactored existing scripts to align with the new return structure, ensuring compatibility with the updated context management. - Added utility functions for normalizing context and step results, improving the handling of script execution context. - Updated various scripts (e.g., fetch-binary, fetch-html, fetch-http) to return structured output and context, enhancing data flow and usability. - Improved error handling for script returns, ensuring clearer feedback when invalid structures are returned. This update significantly enhances the flexibility and clarity of script interactions within workflows.
86 lines
2.9 KiB
React
86 lines
2.9 KiB
React
import { scriptTags, scriptReadsCtx } from "../lib/script.js";
|
|
import { TagBadge } from "./TagBadge.jsx";
|
|
|
|
function FieldTable({ title, fields }) {
|
|
const entries = Object.entries(fields ?? {});
|
|
if (entries.length === 0) return null;
|
|
|
|
return (
|
|
<div>
|
|
<h3 className="mb-1 text-xs font-semibold uppercase tracking-wide opacity-60">{title}</h3>
|
|
<div className="overflow-x-auto">
|
|
<table className="table table-xs">
|
|
<thead>
|
|
<tr>
|
|
<th>Field</th>
|
|
<th>Type</th>
|
|
<th>Notes</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{entries.map(([name, spec]) => {
|
|
const field = spec && typeof spec === "object" ? spec : { description: String(spec) };
|
|
const notes = [
|
|
field.required ? "required" : null,
|
|
field.default !== undefined ? `default ${JSON.stringify(field.default)}` : null,
|
|
Array.isArray(field.enum)
|
|
? `enum ${field.enum.map((x) => (x && typeof x === "object" ? x.value : x)).join(", ")}`
|
|
: Array.isArray(field.options)
|
|
? `enum ${field.options.map((x) => (x && typeof x === "object" ? x.value : x)).join(", ")}`
|
|
: null,
|
|
field.description,
|
|
]
|
|
.filter(Boolean)
|
|
.join(" · ");
|
|
return (
|
|
<tr key={name}>
|
|
<td className="font-mono">{name}</td>
|
|
<td className="opacity-70">{field.type ?? ""}</td>
|
|
<td className="opacity-80">{notes}</td>
|
|
</tr>
|
|
);
|
|
})}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
export function ScriptMetaPanel({ meta, metaError, className = "" }) {
|
|
if (metaError) {
|
|
return <p className={`text-error text-sm ${className}`}>Meta: {metaError}</p>;
|
|
}
|
|
if (!meta) {
|
|
return (
|
|
<p className={`text-sm opacity-50 ${className}`}>
|
|
No script.meta on the default export
|
|
</p>
|
|
);
|
|
}
|
|
|
|
const tags = scriptTags(meta);
|
|
|
|
return (
|
|
<div className={`space-y-3 ${className}`}>
|
|
{meta.description ? <p className="text-sm">{meta.description}</p> : null}
|
|
{(tags.length || scriptReadsCtx(meta)) ? (
|
|
<div className="flex flex-wrap gap-1">
|
|
{tags.map((tag) => (
|
|
<TagBadge key={tag} tag={tag} />
|
|
))}
|
|
{scriptReadsCtx(meta) ? (
|
|
<span className="badge badge-outline badge-sm font-mono">reads: ctx</span>
|
|
) : null}
|
|
</div>
|
|
) : null}
|
|
<div className="grid gap-3 md:grid-cols-2 xl:grid-cols-4">
|
|
<FieldTable title="Config" fields={meta.config} />
|
|
<FieldTable title="Input (data)" fields={meta.input} />
|
|
<FieldTable title="Output" fields={meta.output} />
|
|
<FieldTable title="Context" fields={meta.context} />
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|