- 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.
JerapahFlow
Workflow runner with a sandboxed script engine, SQLite run history, and an admin UI.
Packages
@jerapah-flow/server(packages/server) — Fastify runner, HTTP/cron triggers, admin REST API@jerapah-flow/web(packages/web) — React admin UI (Vite, DaisyUI, React Query)
Setup
pnpm install
pnpm dev
- API: http://localhost:9000
- UI (dev): http://localhost:5173
The first account created becomes admin. Later accounts are created from Users.
Script contract
Each script is async function main(ctx) and must return:
{ output, context?, skipRemaining? }
| Field | Meaning |
|---|---|
ctx.data |
This step’s input (trigger payload, previous output, or DAG needs) |
ctx.context |
Run clipboard (plain object, default {}) |
ctx.config |
This step’s YAML config |
output |
Becomes the next step’s data |
context |
Next snapshot of the bag. Omitted → keep incoming |
skipRemaining |
Stop later steps. Sibling of output/context, not inside output |
Returning the full ctx is an error. Mutating ctx.data or ctx.context does not persist unless returned.
YAML SET evaluates JSONata against the full ctx; the result is output (the next step’s data). jsonata.js does the same.
DAG needs assemble this step’s data from upstream outputs. Independent steps in the same wave share a context snapshot; sibling writes to the same context key fail the run.
Optional script.meta.reads = "ctx" documents expression hosts. meta.input / meta.output / meta.context describe data, the return pipe, and clipboard keys.
Scripts
| Command | Description |
|---|---|
pnpm dev |
Server + Vite together |
pnpm dev:server |
API/runner only |
pnpm dev:web |
UI only (proxies /api to :9000) |
pnpm build |
Production UI build |
pnpm start |
Serve API and built UI from :9000 |
pnpm migrate |
Apply SQLite migrations |
Environment
| Variable | Default | Notes |
|---|---|---|
JERAPAH_FLOW_JWT_SECRET |
scrunner-dev-secret (dev only) |
Required in production. SCRUNNER_JWT_SECRET is still accepted. |
JERAPAH_FLOW_SECRETS_KEY |
scrunner-dev-secrets-key (dev only) |
Master key for named secrets. Required in production. Changing it makes existing secrets unreadable. 64 hex chars are used as a raw AES-256 key; any other string is derived with scrypt. SCRUNNER_SECRETS_KEY is still accepted. |
JERAPAH_FLOW_DB_PATH |
packages/server/data/jerapah-flow.db (or existing scrunner.db) |
SQLite file. SCRUNNER_DB_PATH is still accepted. |
JERAPAH_FLOW_LOG_LEVEL |
debug |
Pino level |
JERAPAH_FLOW_RETENTION_DAYS |
30 |
Run history prune |
JERAPAH_FLOW_CORS_ORIGIN |
http://localhost:5173 |
Vite origin in dev |
PORT |
9000 |
HTTP port |
NODE_ENV |
— | Set production for secure cookies |
Production
pnpm install
pnpm build
JERAPAH_FLOW_JWT_SECRET=... JERAPAH_FLOW_SECRETS_KEY=... NODE_ENV=production pnpm start
The server serves packages/web/dist when that folder exists.
