Quick Start

Run a workflow locally with SQLite persistence in three files.

1. Define a workflow and router

shared.ts
import { workflow, createWorkflowRouter } from "yieldstar";
import { SqliteEventLoop, createSqliteDb } from "@yieldstar/bun-sqlite-runtime";

export const greet = workflow<{ name: string }, string>(
  async function* (step, event) {
    const greeting = yield* step.run(() => `Hello, ${event.params.name}`);
    yield* step.delay(1000);
    return yield* step.run(() => `${greeting}!`);
  }
);

export const router = createWorkflowRouter({ greet });
export type Router = typeof router;

export const db = createSqliteDb({ path: "./.db/local.sqlite" });
export const eventLoop = new SqliteEventLoop(db);

2. Create the worker process

worker.ts
import pino from "pino";
import { WorkflowRunner } from "@yieldstar/core";
import { createWorkflowWorker } from "@yieldstar/bun-worker-invoker";
import {
  SqliteHeapClient,
  SqliteSchedulerClient,
  SqliteTaskQueueClient,
  SqliteTimersClient,
} from "@yieldstar/bun-sqlite-runtime";
import { router, db } from "./shared";

const logger = pino();

const runner = new WorkflowRunner({
  router,
  heapClient: new SqliteHeapClient(db),
  schedulerClient: new SqliteSchedulerClient({
    taskQueueClient: new SqliteTaskQueueClient(db),
    timersClient: new SqliteTimersClient(db),
  }),
  logger,
});

createWorkflowWorker(runner, logger).listen();

3. Trigger and await the result

app.ts
import pino from "pino";
import { createWorkflowInvoker } from "@yieldstar/bun-worker-invoker";
import { createLocalSdk } from "yieldstar";
import { eventLoop } from "./shared";
import type { Router } from "./shared";

const logger = pino();
const workerPath = new URL("./worker.ts", import.meta.url).href;
const invoker = createWorkflowInvoker({ workerPath, logger });

eventLoop.start({ onNewEvent: invoker.execute, logger });

const sdk = createLocalSdk<Router>(invoker);
const result = await sdk.triggerAndWait({
  workflowId: "greet",
  params: { name: "World" },
});

console.log(result); // "Hello, World!"
eventLoop.stop();

4. Run it

bun app.ts

The workflow executes two steps with a 1-second delay between them. The first step computes a greeting, the delay pauses execution (persisting state to SQLite), and the second step appends punctuation. On resume, completed steps replay from the heap without re-executing.