|
| 1 | +--- |
| 2 | +title: World helpers |
| 3 | +--- |
| 4 | + |
| 5 | +# Accessing the World singleton |
| 6 | + |
| 7 | +> “Is there any public API to access the active default World? I'd like to be able to list active runs in my app, like I can via the CLI. I could store them myself, but if there is an API for this that works across testing and deployment, that'd be even better!” |
| 8 | +
|
| 9 | +Yes. Import `getWorld` or any of the helper functions below directly from `workflow/api`. They proxy to the same singleton that powers the CLI, whether you're running locally with the embedded world, in tests (via `setWorld`), or on Vercel. |
| 10 | + |
| 11 | +```typescript |
| 12 | +import { |
| 13 | + getWorld, |
| 14 | + listRuns, |
| 15 | + listSteps, |
| 16 | + cancelRun, |
| 17 | + queue, |
| 18 | +} from 'workflow/api'; |
| 19 | + |
| 20 | +const runs = await listRuns({ status: 'running', pagination: { limit: 10 } }); |
| 21 | +await cancelRun(runs.data[0].runId); |
| 22 | + |
| 23 | +// You still have full access to the underlying World instance when needed. |
| 24 | +const world = getWorld(); |
| 25 | +await world.start?.(); |
| 26 | +``` |
| 27 | + |
| 28 | +## Example: List and cancel runs in a Next.js route |
| 29 | + |
| 30 | +```typescript filename="app/api/workflows/route.ts" |
| 31 | +import { listRuns, cancelRun } from 'workflow/api'; |
| 32 | + |
| 33 | +export async function GET() { |
| 34 | + const runs = await listRuns({ status: 'running', pagination: { limit: 20 } }); |
| 35 | + return Response.json({ runs: runs.data }); |
| 36 | +} |
| 37 | + |
| 38 | +export async function POST(request: Request) { |
| 39 | + const { runId } = await request.json(); |
| 40 | + await cancelRun(runId); |
| 41 | + return Response.json({ ok: true }); |
| 42 | +} |
| 43 | +``` |
| 44 | + |
| 45 | +This works the same way in development and production—just make sure the usual `WORKFLOW_*` environment variables are present so the correct world implementation can be chosen. |
| 46 | + |
| 47 | +## Helper catalog |
| 48 | + |
| 49 | +### Run helpers |
| 50 | + |
| 51 | +| Function | Description | |
| 52 | +| --- | --- | |
| 53 | +| `createRun(data)` | Calls `world.runs.create` directly. Useful for advanced tooling/tests. | |
| 54 | +| `getWorkflowRun(id, params?)` | Fetches a workflow run record without wrapping it in the `Run` class. | |
| 55 | +| `updateRun(id, data)` | Partially updates a run record. | |
| 56 | +| `listRuns(params?)` | Lists runs with optional filters/pagination. | |
| 57 | +| `cancelRun(id, params?)` | Cancels a run. | |
| 58 | +| `pauseRun(id, params?)` / `resumeRun(id, params?)` | Pause/resume administrative helpers. | |
| 59 | + |
| 60 | +### Step helpers |
| 61 | + |
| 62 | +| Function | Description | |
| 63 | +| --- | --- | |
| 64 | +| `createStep(runId, data)` | Inserts a step record. | |
| 65 | +| `getStep(runId, stepId, params?)` | Retrieves a single step. | |
| 66 | +| `updateStep(runId, stepId, data)` | Updates status/attempt metadata. | |
| 67 | +| `listSteps(params)` | Lists steps for a run (with pagination + `resolveData`). | |
| 68 | + |
| 69 | +### Events & hooks |
| 70 | + |
| 71 | +| Function | Description | |
| 72 | +| --- | --- | |
| 73 | +| `createEvent(runId, data, params?)` | Writes workflow/step events. | |
| 74 | +| `listEvents(params)` | Lists events for a run. | |
| 75 | +| `listEventsByCorrelationId(params)` | Lists events for a correlation ID across runs. | |
| 76 | +| `createHook(runId, data, params?)` | Creates a hook. | |
| 77 | +| `getHook(id, params?)` | Fetches hook metadata. | |
| 78 | +| `listHooks(params)` | Lists hooks. | |
| 79 | +| `disposeHook(id, params?)` | Disposes a hook. | |
| 80 | +| `getHookByToken(token, params?)` | Continues to be exported for convenience. | |
| 81 | + |
| 82 | +### Queue, streams, and lifecycle helpers |
| 83 | + |
| 84 | +| Function | Description | |
| 85 | +| --- | --- | |
| 86 | +| `getDeploymentId()` | Returns the deployment ID that queue operations will use. | |
| 87 | +| `queue(name, payload, opts?)` | Enqueue workflow/step invocations manually. | |
| 88 | +| `createQueueHandler(prefix, handler)` | Builds queue HTTP handlers (the same API the runtime uses). | |
| 89 | +| `writeToStream(name, chunk)` / `closeStream(name)` / `readFromStream(name, startIndex?)` | Direct streaming helpers. | |
| 90 | +| `startWorld()` | Invokes `world.start?.()` if provided by your world implementation. | |
| 91 | + |
| 92 | +## Testing tips |
| 93 | + |
| 94 | +Use `setWorld` to stub custom worlds in tests so that the helpers continue to work without hitting real infrastructure: |
| 95 | + |
| 96 | +```typescript |
| 97 | +import { setWorld } from 'workflow/runtime'; |
| 98 | +import { listRuns } from 'workflow/api'; |
| 99 | + |
| 100 | +beforeEach(() => { |
| 101 | + setWorld({ |
| 102 | + // Provide a minimal mock World |
| 103 | + runs: { |
| 104 | + list: async () => ({ data: [], cursor: null, hasMore: false }), |
| 105 | + create: async () => { throw new Error('not implemented'); }, |
| 106 | + get: async () => { throw new Error('not implemented'); }, |
| 107 | + update: async () => { throw new Error('not implemented'); }, |
| 108 | + cancel: async () => { throw new Error('not implemented'); }, |
| 109 | + pause: async () => { throw new Error('not implemented'); }, |
| 110 | + resume: async () => { throw new Error('not implemented'); }, |
| 111 | + }, |
| 112 | + steps: { /* ... */ }, |
| 113 | + events: { /* ... */ }, |
| 114 | + hooks: { /* ... */ }, |
| 115 | + getDeploymentId: async () => 'test', |
| 116 | + queue: async () => ({ messageId: 'msg_test' }), |
| 117 | + createQueueHandler: () => async () => new Response(), |
| 118 | + writeToStream: async () => {}, |
| 119 | + closeStream: async () => {}, |
| 120 | + readFromStream: async () => new ReadableStream(), |
| 121 | + } as any); |
| 122 | +}); |
| 123 | + |
| 124 | +afterEach(() => setWorld(undefined)); |
| 125 | + |
| 126 | +it('lists runs without contacting real services', async () => { |
| 127 | + const runs = await listRuns(); |
| 128 | + expect(runs.data).toHaveLength(0); |
| 129 | +}); |
| 130 | +``` |
| 131 | + |
| 132 | +This mirrors how the new automated tests stub the world singleton. |
0 commit comments