workflow 5.0.0-beta.2 → 5.0.0-beta.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api-workflow.d.ts +1 -1
- package/dist/api-workflow.d.ts.map +1 -1
- package/dist/api-workflow.js +2 -2
- package/docs/cookbook/{common-patterns → advanced}/child-workflows.mdx +1 -1
- package/docs/cookbook/advanced/distributed-abort-controller.mdx +318 -0
- package/docs/cookbook/advanced/meta.json +2 -3
- package/docs/cookbook/advanced/publishing-libraries.mdx +83 -26
- package/docs/cookbook/advanced/serializable-steps.mdx +15 -3
- package/docs/cookbook/agent-patterns/agent-cancellation.mdx +205 -0
- package/docs/cookbook/agent-patterns/durable-agent.mdx +50 -91
- package/docs/cookbook/agent-patterns/human-in-the-loop.mdx +148 -171
- package/docs/cookbook/agent-patterns/meta.json +1 -7
- package/docs/cookbook/common-patterns/batching.mdx +44 -118
- package/docs/cookbook/common-patterns/meta.json +4 -4
- package/docs/cookbook/common-patterns/saga.mdx +126 -31
- package/docs/cookbook/common-patterns/scheduling.mdx +70 -194
- package/docs/cookbook/common-patterns/sequential-and-parallel.mdx +155 -0
- package/docs/cookbook/common-patterns/timeouts.mdx +99 -0
- package/docs/cookbook/common-patterns/workflow-composition.mdx +118 -0
- package/docs/cookbook/index.mdx +13 -16
- package/docs/cookbook/integrations/ai-sdk.mdx +296 -140
- package/docs/cookbook/integrations/chat-sdk.mdx +251 -151
- package/docs/cookbook/integrations/sandbox.mdx +469 -81
- package/docs/cookbook/meta.json +1 -1
- package/docs/foundations/index.mdx +0 -3
- package/docs/foundations/meta.json +0 -1
- package/docs/foundations/serialization.mdx +1 -1
- package/docs/foundations/starting-workflows.mdx +1 -1
- package/docs/migration-guides/migrating-from-aws-step-functions.mdx +60 -8
- package/docs/migration-guides/migrating-from-inngest.mdx +38 -6
- package/docs/migration-guides/migrating-from-temporal.mdx +38 -4
- package/docs/migration-guides/migrating-from-trigger-dev.mdx +52 -11
- package/package.json +11 -11
- package/docs/cookbook/advanced/custom-serialization.mdx +0 -168
- package/docs/cookbook/advanced/durable-objects.mdx +0 -148
- package/docs/cookbook/advanced/isomorphic-packages.mdx +0 -145
- package/docs/cookbook/agent-patterns/stop-workflow.mdx +0 -216
- package/docs/cookbook/agent-patterns/tool-orchestration.mdx +0 -255
- package/docs/cookbook/agent-patterns/tool-streaming.mdx +0 -181
- package/docs/cookbook/common-patterns/content-router.mdx +0 -207
- package/docs/cookbook/common-patterns/fan-out.mdx +0 -208
- package/docs/foundations/common-patterns.mdx +0 -265
|
@@ -30,7 +30,12 @@ npx skills add https://github.com/vercel/workflow --skill migrating-to-workflow-
|
|
|
30
30
|
- Streaming is built in. Write durable progress from steps with `getWritable()` and named streams. No DynamoDB or SNS glue to surface status to clients.
|
|
31
31
|
- Infrastructure lives in one deployment. No separate state machine, per-task Lambda, IAM role wiring, or callback SQS queues.
|
|
32
32
|
- Error handling is TypeScript-native: step-level retries, `RetryableError`, and `FatalError` replace per-state Retry/Catch blocks.
|
|
33
|
-
-
|
|
33
|
+
- The `npx workflow` CLI and `npx workflow web` observability UI ship out of the box.
|
|
34
|
+
- AI/agent helpers — `@workflow/ai` for AI-SDK integration and the Claude migration skill — are available as separate installs.
|
|
35
|
+
|
|
36
|
+
## Before you migrate
|
|
37
|
+
|
|
38
|
+
This guide assumes **Standard** workflows. Express workflows have different semantics (at-least-once, 5-minute max duration, no execution history) and may need a different target — consider keeping them on Step Functions, moving them to a queue consumer, or ensuring your steps are idempotent before replaying the pattern here.
|
|
34
39
|
|
|
35
40
|
## What changes when you leave Step Functions?
|
|
36
41
|
|
|
@@ -49,8 +54,9 @@ The migration replaces declarative configuration with idiomatic TypeScript and c
|
|
|
49
54
|
| Choice state | `if` / `else` / `switch` | Native TypeScript control flow. |
|
|
50
55
|
| Wait state | `sleep()` | Import `sleep` from `workflow`. |
|
|
51
56
|
| Parallel state | `Promise.all()` | Standard concurrency primitives. |
|
|
52
|
-
| Map state |
|
|
57
|
+
| Map state | Inline sequential → `for` loop; bounded parallel (`MaxConcurrency: N`) → batched `Promise.all` or a concurrency limiter like `p-limit`; Distributed Map / large fan-out → step-wrapped `start()` per item, then step-wrapped `getRun()` to collect. | Match the concurrency mode of the original Map. |
|
|
53
58
|
| Retry / Catch | Step retries, `RetryableError`, `FatalError` | Retry logic moves to step boundaries. |
|
|
59
|
+
| `Catch` to a compensation state | `try`/`catch` in the workflow function, calling compensation steps in reverse order (push/pop a rollback stack) | See [`/docs/foundations/errors-and-retries`](/docs/foundations/errors-and-retries) for the SAGA pattern. |
|
|
54
60
|
| `.waitForTaskToken` | `createHook()` or `createWebhook()` | Hooks for typed signals; webhooks for HTTP. |
|
|
55
61
|
| Child state machine (`StartExecution`) | `"use step"` around `start()` / `getRun()` | Return the `Run` object, await its result from another step. |
|
|
56
62
|
| Execution event history | Workflow event log | Same durable replay model. |
|
|
@@ -73,6 +79,10 @@ Start with a single Task state. In ASL, even "call one Lambda" requires a state
|
|
|
73
79
|
}
|
|
74
80
|
```
|
|
75
81
|
|
|
82
|
+
<Callout type="info">
|
|
83
|
+
Examples use JSONPath mode. If your state machine sets `QueryLanguage: 'JSONata'`, the shape of `Arguments`/`Output` fields differs but the TypeScript translation is identical.
|
|
84
|
+
</Callout>
|
|
85
|
+
|
|
76
86
|
```typescript title="workflow/workflows/order.ts (Workflow SDK)"
|
|
77
87
|
export async function processOrder(orderId: string) {
|
|
78
88
|
'use workflow'; // [!code highlight]
|
|
@@ -101,7 +111,7 @@ export async function processOrder(orderId: string) {
|
|
|
101
111
|
}
|
|
102
112
|
```
|
|
103
113
|
|
|
104
|
-
`await` replaces `"Next"`. Each new step is a new function with `"use step"`; no additional deployment.
|
|
114
|
+
`await` replaces `"Next"`. Each new step is a new function with `"use step"`; no additional deployment. The second version also reshapes the return value; the workflow return type can be anything serializable.
|
|
105
115
|
|
|
106
116
|
### Starting from an API route
|
|
107
117
|
|
|
@@ -118,6 +128,20 @@ export async function POST(request: Request) {
|
|
|
118
128
|
}
|
|
119
129
|
```
|
|
120
130
|
|
|
131
|
+
### Waiting for a fixed duration
|
|
132
|
+
|
|
133
|
+
A `Wait` state becomes `sleep()`:
|
|
134
|
+
|
|
135
|
+
```json title="stateMachine.asl.json (Step Functions)"
|
|
136
|
+
{ "Type": "Wait", "Seconds": 60, "Next": "Next" }
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
{/* @skip-typecheck: one-line snippet fragment */}
|
|
140
|
+
|
|
141
|
+
```typescript title="workflow/workflows/order.ts (Workflow SDK)"
|
|
142
|
+
await sleep('1m');
|
|
143
|
+
```
|
|
144
|
+
|
|
121
145
|
## Wait for an external signal
|
|
122
146
|
|
|
123
147
|
The minimal ASL for a callback is a Task with `.waitForTaskToken`:
|
|
@@ -198,7 +222,7 @@ import { start } from 'workflow/api';
|
|
|
198
222
|
|
|
199
223
|
async function spawnChild(item: string) {
|
|
200
224
|
'use step'; // [!code highlight]
|
|
201
|
-
return start(childWorkflow, [item]);
|
|
225
|
+
return await start(childWorkflow, [item]);
|
|
202
226
|
}
|
|
203
227
|
|
|
204
228
|
export async function parentWorkflow(item: string) {
|
|
@@ -232,9 +256,13 @@ Moving off Step Functions removes these surfaces from the application:
|
|
|
232
256
|
- Per-task Lambda functions, their IAM roles, and CloudFormation/CDK wiring.
|
|
233
257
|
- Task-token delivery infrastructure (SQS queues, callback Lambdas).
|
|
234
258
|
- Separate progress channels (DynamoDB, SNS) for client-visible updates.
|
|
235
|
-
- CloudWatch and X-Ray
|
|
259
|
+
- Remove CloudWatch and X-Ray wiring that was specific to orchestrator state transitions. Keep (or re-wire) any application-level CloudWatch alarms, log retention policies, or X-Ray propagation that the rest of your AWS footprint still depends on. Workflow SDK exports OTEL traces, so existing OTEL-compatible backends can continue to ingest them.
|
|
260
|
+
|
|
261
|
+
Workflow and step functions live in the same deployment as the application. State transitions are ordinary control flow (`await`, `if`, `Promise.all`, `for`). Progress streaming, retries, and observability are built in.
|
|
236
262
|
|
|
237
|
-
|
|
263
|
+
### What you take on
|
|
264
|
+
|
|
265
|
+
Steps that previously invoked AWS services via optimized integrations (EventBridge, DynamoDB, Bedrock, ECS.RunTask.sync, etc.) become ordinary SDK calls inside `'use step'` functions. Credentials and retries move into the step, and `.sync`-style waits for long-running jobs become explicit polling loops or hook-based callbacks.
|
|
238
266
|
|
|
239
267
|
## Step-by-step first migration
|
|
240
268
|
|
|
@@ -276,6 +304,18 @@ async function loadOrder(id: string) {
|
|
|
276
304
|
|
|
277
305
|
Swap the task-token callback Lambda for `createHook()`. Callers `resumeHook(token, payload)` instead of `SendTaskSuccess`.
|
|
278
306
|
|
|
307
|
+
Move Retry/Catch off per-state configuration and onto step boundaries. Set `maxRetries` as a function property; throw `RetryableError` or `FatalError` to control retry behavior:
|
|
308
|
+
|
|
309
|
+
```typescript
|
|
310
|
+
async function chargePayment(orderId: string) {
|
|
311
|
+
"use step";
|
|
312
|
+
// ...
|
|
313
|
+
}
|
|
314
|
+
chargePayment.maxRetries = 5;
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
See [`/docs/foundations/errors-and-retries`](/docs/foundations/errors-and-retries) for the full retry and SAGA compensation patterns.
|
|
318
|
+
|
|
279
319
|
### Step 5: Start runs from an API route
|
|
280
320
|
|
|
281
321
|
Delete the `StartExecution` call and IAM wiring. Launch runs directly from a route handler:
|
|
@@ -293,7 +333,16 @@ export async function POST(req: Request) {
|
|
|
293
333
|
|
|
294
334
|
### Step 6: Retire the Step Functions infrastructure
|
|
295
335
|
|
|
296
|
-
Delete the ASL JSON, per-task Lambda deployments, IAM roles, and callback queues. Remove CloudWatch and X-Ray wiring
|
|
336
|
+
Delete the ASL JSON, per-task Lambda deployments, IAM roles, and callback queues. Remove CloudWatch and X-Ray wiring that was specific to orchestrator state transitions — keep alarms, log retention, and traces for resources you still depend on. Verify the run in `npx workflow web` before shipping.
|
|
337
|
+
|
|
338
|
+
## Features without a 1:1 equivalent
|
|
339
|
+
|
|
340
|
+
- **Express workflows.** At-least-once semantics and 5-minute duration make them a poor fit for the SDK's durable replay model. Consider keeping them on Step Functions or migrating to a queue consumer.
|
|
341
|
+
- **Distributed Map state.** Up to 10,000 concurrent child executions with S3 item sources has no 1:1 analog; fan out with step-wrapped `start()` per item, then `Promise.all` with `p-limit` to bound concurrency.
|
|
342
|
+
- **Optimized AWS service integrations (`arn:aws:states:::dynamodb:*`, `eventbridge:*`, `bedrock:*`, `ecs:runTask.sync`, etc.).** These become regular SDK calls inside `'use step'` functions — credentials, retries, and polling move into the step.
|
|
343
|
+
- **Per-state IAM roles.** ASL lets each state run under its own IAM role. In the SDK, all steps share the deployment's credentials; scope secrets and roles at deployment time.
|
|
344
|
+
- **CloudWatch alarms / X-Ray cross-service traces / CloudWatch Logs retention.** The SDK event log + observability UI replaces orchestrator state transitions, not AWS-wide observability. Keep alarms and traces for other resources.
|
|
345
|
+
- **`JSONata` `QueryLanguage` mode.** Valid at the source; the TS translation is identical regardless of mode.
|
|
297
346
|
|
|
298
347
|
## Quick-start checklist
|
|
299
348
|
|
|
@@ -302,10 +351,13 @@ Delete the ASL JSON, per-task Lambda deployments, IAM roles, and callback queues
|
|
|
302
351
|
- Replace Choice states with `if`/`else`/`switch`.
|
|
303
352
|
- Replace Wait states with `sleep()` from `workflow`.
|
|
304
353
|
- Replace Parallel states with `Promise.all()`.
|
|
305
|
-
- Replace Map states
|
|
354
|
+
- Replace Map states based on their concurrency mode: inline sequential → `for` loop; bounded parallel (`MaxConcurrency: N`) → batched `Promise.all` or a concurrency limiter like `p-limit`; Distributed Map / large fan-out → step-wrapped `start()` per item, then step-wrapped `getRun()` to collect.
|
|
306
355
|
- Replace `StartExecution` child machines with `"use step"` wrappers around `start()` and `getRun()`.
|
|
307
356
|
- Replace `.waitForTaskToken` with `createHook()` (internal callers) or `createWebhook()` (HTTP callers).
|
|
308
357
|
- Move Retry/Catch to step boundaries using `maxRetries`, `RetryableError`, and `FatalError`.
|
|
309
358
|
- Use `getStepMetadata().stepId` as the idempotency key for external side effects.
|
|
310
359
|
- Stream progress from steps with `getWritable()` instead of polling DynamoDB or SNS.
|
|
311
360
|
- Deploy and verify runs end-to-end with built-in observability.
|
|
361
|
+
|
|
362
|
+
---
|
|
363
|
+
*Verified against `workflow@5.0.0-beta.1` and the AWS Step Functions Amazon States Language spec on 2026-04-16.*
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: Migrating from Inngest
|
|
3
|
-
description: Move an Inngest TypeScript app to the Workflow SDK by replacing createFunction, step.run(), step.sleep(), step.waitForEvent(), and step.invoke() with Workflows, Steps, Hooks, and start()/getRun().
|
|
3
|
+
description: Move an Inngest TypeScript SDK v3 or v4 app to the Workflow SDK by replacing createFunction, step.run(), step.sleep(), step.waitForEvent(), and step.invoke() with Workflows, Steps, Hooks, and start()/getRun().
|
|
4
4
|
type: guide
|
|
5
5
|
summary: Translate an Inngest app into the Workflow SDK with side-by-side code examples.
|
|
6
6
|
prerequisites:
|
|
@@ -29,6 +29,8 @@ npx skills add https://github.com/vercel/workflow --skill migrating-to-workflow-
|
|
|
29
29
|
- TypeScript-first DX. Steps are named async functions marked with `"use step"`. No inline closures tied to a framework-specific lifecycle.
|
|
30
30
|
- Agent-first tooling: the `npx workflow` CLI, `@workflow/ai` integration for durable AI agents, and a Claude skill for generating workflows.
|
|
31
31
|
|
|
32
|
+
Inngest code samples in this guide use the v4 two-argument `createFunction({ id, triggers }, handler)` shape. If the app is still on Inngest v3, treat the three-argument form `createFunction({ id }, { event: '...' }, handler)` as equivalent — the `triggers` option in v4 replaces the second argument in v3.
|
|
33
|
+
|
|
32
34
|
## What changes when you leave Inngest
|
|
33
35
|
|
|
34
36
|
Inngest defines functions with `inngest.createFunction()`, registers them through a `serve()` handler, and breaks work into steps with `step.run()`, `step.sleep()`, and `step.waitForEvent()`. The platform routes events, schedules steps, and applies retries.
|
|
@@ -37,13 +39,17 @@ The Workflow SDK replaces that with `"use workflow"` functions that orchestrate
|
|
|
37
39
|
|
|
38
40
|
Migration collapses the SDK abstraction into plain async functions. Business logic stays the same.
|
|
39
41
|
|
|
42
|
+
<Callout type="info">
|
|
43
|
+
Inngest's event-bus model is loosely coupled — publishers don't know consumers. `start()` requires the caller to import the workflow function directly, giving stronger type safety but tighter coupling. For event-bus-like fan-out, wrap `start()` in a shared publisher module.
|
|
44
|
+
</Callout>
|
|
45
|
+
|
|
40
46
|
## Concept mapping
|
|
41
47
|
|
|
42
48
|
| Inngest | Workflow SDK | Migration note |
|
|
43
49
|
| --- | --- | --- |
|
|
44
50
|
| `inngest.createFunction()` | `"use workflow"` function started with `start()` | No wrapper needed. |
|
|
45
51
|
| `step.run()` | `"use step"` function | Standalone async function with Node.js access. |
|
|
46
|
-
| `step.sleep()` / `step.sleepUntil()` | `sleep()` |
|
|
52
|
+
| `step.sleep()` / `step.sleepUntil()` | `sleep()` | `sleep('5m')` for a duration; `sleep(date)` for sleep-until. |
|
|
47
53
|
| `step.waitForEvent()` | `createHook()` or `createWebhook()` | Hooks for typed signals, webhooks for HTTP. |
|
|
48
54
|
| `step.invoke()` | `"use step"` wrappers around `start()` / `getRun()` | Spawn a child run, pass `runId` forward. |
|
|
49
55
|
| `inngest.send()` / event triggers | `start()` from your app boundary | Start workflows directly. |
|
|
@@ -60,7 +66,7 @@ Start with the shell of a function. Inngest wraps it in `createFunction`; Workfl
|
|
|
60
66
|
export const processOrder = inngest.createFunction(
|
|
61
67
|
{
|
|
62
68
|
id: 'process-order',
|
|
63
|
-
triggers:
|
|
69
|
+
triggers: { event: 'order/created' },
|
|
64
70
|
},
|
|
65
71
|
async ({ event, step }) => {
|
|
66
72
|
return { orderId: event.data.orderId, status: 'completed' };
|
|
@@ -165,6 +171,8 @@ Event matching disappears. A hook's token encodes the routing (for example, `ref
|
|
|
165
171
|
|
|
166
172
|
`step.invoke()` splits into two steps: spawn and collect. `start()` and `getRun()` are runtime APIs, so wrap them in `"use step"` functions. Return the `Run` object from the spawn step so observability can deep-link into the child run.
|
|
167
173
|
|
|
174
|
+
You can return either the full `Run` object (enables deep-linking) or just `run.runId` (simpler).
|
|
175
|
+
|
|
168
176
|
{/* @skip-typecheck: snippet without imports */}
|
|
169
177
|
```typescript title="workflow/workflows/parent.ts"
|
|
170
178
|
async function spawnChild(item: string) {
|
|
@@ -206,7 +214,7 @@ Pick one Inngest function and migrate it end-to-end before touching the rest. Th
|
|
|
206
214
|
|
|
207
215
|
### Step 1: Install the Workflow SDK
|
|
208
216
|
|
|
209
|
-
|
|
217
|
+
Install the SDK. Framework integrations (`workflow/next`, `workflow/nitro`, `workflow/nuxt`, etc.) are subpath exports of the same `workflow` package — no additional install needed.
|
|
210
218
|
|
|
211
219
|
```bash
|
|
212
220
|
pnpm add workflow
|
|
@@ -219,7 +227,7 @@ Replace the factory call with a plain async export. Move the handler body up. Th
|
|
|
219
227
|
```ts title="workflows/order.ts"
|
|
220
228
|
// Before (Inngest)
|
|
221
229
|
// export const processOrder = inngest.createFunction(
|
|
222
|
-
// { id: "process-order", triggers:
|
|
230
|
+
// { id: "process-order", triggers: { event: "order/created" } },
|
|
223
231
|
// async ({ event, step }) => { ... }
|
|
224
232
|
// );
|
|
225
233
|
|
|
@@ -237,10 +245,23 @@ Each inline callback becomes a named function with `"use step"` on the first lin
|
|
|
237
245
|
```ts
|
|
238
246
|
async function loadOrder(id: string) {
|
|
239
247
|
"use step"; // [!code highlight]
|
|
240
|
-
return fetch(
|
|
248
|
+
return fetch(`https://example.com/api/orders/${id}`).then((r) => r.json());
|
|
249
|
+
}
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
Configure per-step retry counts by assigning `maxRetries` as a function property:
|
|
253
|
+
|
|
254
|
+
```ts
|
|
255
|
+
async function callApi(endpoint: string) {
|
|
256
|
+
"use step";
|
|
257
|
+
const response = await fetch(endpoint);
|
|
258
|
+
return response.json();
|
|
241
259
|
}
|
|
260
|
+
callApi.maxRetries = 5;
|
|
242
261
|
```
|
|
243
262
|
|
|
263
|
+
See [Errors and retries](/docs/foundations/errors-and-retries) for full retry docs.
|
|
264
|
+
|
|
244
265
|
### Step 4: Replace `waitForEvent`, `sleep`, and `invoke`
|
|
245
266
|
|
|
246
267
|
- `step.waitForEvent(...)` → `createHook({ token })` + `await hook`. Resume it from an API route with `resumeHook(token, payload)`.
|
|
@@ -266,6 +287,13 @@ export async function POST(req: Request) {
|
|
|
266
287
|
|
|
267
288
|
Remove the `inngest` client, the `serve()` route, event schemas, and the Inngest Dev Server from the app. Verify the run in `npx workflow web` before shipping.
|
|
268
289
|
|
|
290
|
+
## Features without a 1:1 equivalent
|
|
291
|
+
|
|
292
|
+
- **Cron / scheduled functions (`triggers: { cron: '...' }`).** The SDK has no built-in scheduler. Trigger runs from Vercel Cron or a system cron calling `start()` from an API route.
|
|
293
|
+
- **Concurrency, throttling, rate limiting, debounce, singleton, priority, and `batchEvents`.** These function-level settings have no direct analog. Enforce limits inside steps (semaphores, external rate-limiter service) or debounce at the publisher before calling `start()`.
|
|
294
|
+
- **`EventSchemas` / typed events.** The event-bus indirection goes away; publishers import the workflow function directly, giving the same type safety through a different mechanism.
|
|
295
|
+
- **Event-bus fan-out by name match.** `inngest.send()` that triggered multiple functions by event name must be replaced by explicit `start()` calls for each target workflow.
|
|
296
|
+
|
|
269
297
|
## Quick-start checklist
|
|
270
298
|
|
|
271
299
|
- Replace `inngest.createFunction()` with a `"use workflow"` function; launch it with `start()`.
|
|
@@ -280,3 +308,7 @@ Remove the `inngest` client, the `serve()` route, event schemas, and the Inngest
|
|
|
280
308
|
- Use `getStepMetadata().stepId` as the idempotency key for external side effects.
|
|
281
309
|
- Replace `step.realtime.publish()` with `getWritable()`.
|
|
282
310
|
- Deploy and verify end-to-end with the built-in observability UI.
|
|
311
|
+
|
|
312
|
+
---
|
|
313
|
+
|
|
314
|
+
*Verified against `workflow@5.0.0-beta.1` and Inngest TypeScript SDK v4 on 2026-04-16.*
|
|
@@ -27,7 +27,7 @@ npx skills add https://github.com/vercel/workflow --skill migrating-to-workflow-
|
|
|
27
27
|
- Streaming is built in. Durable progress writes go to named streams via `getWritable({ namespace })`, and clients read them directly. No separate WebSocket, SSE, or progress-polling layer to operate.
|
|
28
28
|
- Infrastructure and orchestration live in a single deployment. There is no separate Worker fleet or Temporal Server to run. The runtime, step logic, and orchestration share the app's observability and log aggregation.
|
|
29
29
|
- TypeScript-first developer experience. Workflows and steps live in the same file with plain `await` control flow, `try/catch`, and `Promise.all`.
|
|
30
|
-
- Agent-first tooling. A first-class CLI (`npx workflow`), `@workflow/ai` integration for durable AI agents, and a bundled Claude skill for AI-assisted authoring.
|
|
30
|
+
- Agent-first tooling. A first-class CLI (`npx workflow`), [`@workflow/ai` integration for durable AI agents](/docs/ai), and a bundled Claude skill for AI-assisted authoring.
|
|
31
31
|
- Per-step retry controls. `RetryableError`, `FatalError`, and `maxRetries` live at the step boundary instead of an Activity-level retry policy configured elsewhere.
|
|
32
32
|
|
|
33
33
|
## What changes when you leave Temporal
|
|
@@ -36,6 +36,8 @@ Temporal requires operating a control plane (Temporal Server or Cloud), a Worker
|
|
|
36
36
|
|
|
37
37
|
The Workflow SDK runs on managed infrastructure. Write `"use workflow"` functions that orchestrate `"use step"` functions in the same file, in plain TypeScript. There are no Workers, Task Queues, or separate Activity modules. Durable replay, automatic retries, and event history are handled by the runtime.
|
|
38
38
|
|
|
39
|
+
Workflow functions must still be deterministic — no `Date.now()`, `Math.random()`, direct network I/O, or wall-clock branches inside `"use workflow"`. Move any such logic into a step, as you do today with Activities.
|
|
40
|
+
|
|
39
41
|
Migration removes infrastructure and collapses indirection. Business logic stays as regular async TypeScript.
|
|
40
42
|
|
|
41
43
|
## Concept mapping
|
|
@@ -47,10 +49,10 @@ Migration removes infrastructure and collapses indirection. Business logic stays
|
|
|
47
49
|
| Worker + Task Queue | Managed execution | No worker fleet or polling loop to operate. |
|
|
48
50
|
| Signal | `createHook()` or `createWebhook()` | Use hooks for typed resume signals; webhooks for HTTP callbacks. |
|
|
49
51
|
| Query | `getWritable({ namespace: 'status' })` stream | Durably stream status updates from the workflow. Clients read from the stream instead of polling a database. |
|
|
50
|
-
| Update | `createHook()` + `resumeHook()` |
|
|
52
|
+
| Update | `createHook()` + `resumeHook()` (one-way) | Temporal Updates return a value to the caller; hooks do not. If the Update returns data, either write the result to a named stream via `getWritable()` and have the caller read from it, or keep an HTTP read route that fetches the workflow's current state. |
|
|
51
53
|
| Child Workflow | `"use step"` wrappers around `start()` / `getRun()` | Spawn from a step and return the `Run` object so observability can deep-link into child runs. |
|
|
52
54
|
| Activity retry policy | Step retries, `RetryableError`, `FatalError`, `maxRetries` | Retries live at the step boundary. |
|
|
53
|
-
| Event History | Workflow event log / run timeline | Same durable replay
|
|
55
|
+
| Event History | Workflow event log / run timeline | Same durable replay; built-in observability UI replaces Temporal Web. Search attributes and visibility APIs have no direct equivalent — filter by run status and timestamps instead. |
|
|
54
56
|
|
|
55
57
|
## Translate your first workflow
|
|
56
58
|
|
|
@@ -60,6 +62,9 @@ Start with the directive change. The Temporal definition proxies activities thro
|
|
|
60
62
|
|
|
61
63
|
{/* @skip-typecheck: Temporal SDK types not available */}
|
|
62
64
|
```typescript title="workflows/order.ts (Temporal)"
|
|
65
|
+
import * as wf from '@temporalio/workflow';
|
|
66
|
+
import type * as activities from './activities';
|
|
67
|
+
|
|
63
68
|
const { chargePayment } = wf.proxyActivities<typeof activities>({
|
|
64
69
|
startToCloseTimeout: '5 minutes',
|
|
65
70
|
});
|
|
@@ -143,6 +148,8 @@ export async function refundWorkflow(refundId: string) {
|
|
|
143
148
|
|
|
144
149
|
The workflow suspends durably at `await approval` until resumed. No polling, no handler registration.
|
|
145
150
|
|
|
151
|
+
Requires TypeScript 5.2+ for the `using` keyword. On older TypeScript, assign the hook to a `const` and call `resumeHook()` from the consuming code path.
|
|
152
|
+
|
|
146
153
|
### Resuming from an API route
|
|
147
154
|
|
|
148
155
|
Any HTTP caller can resume by token:
|
|
@@ -201,6 +208,22 @@ Call both steps from the parent in sequence: `const result = await collectResult
|
|
|
201
208
|
|
|
202
209
|
<Callout type="warn">
|
|
203
210
|
Activity retry policy moves to the step boundary. Use `maxRetries`, `RetryableError`, and `FatalError` on each step instead of a single workflow-wide retry block.
|
|
211
|
+
|
|
212
|
+
Temporal's per-activity timeouts (`startToCloseTimeout`, `scheduleToCloseTimeout`, `heartbeatTimeout`) have no direct Workflow SDK equivalent. Enforce per-step deadlines inside the step using `AbortSignal.timeout(ms)` (e.g. on `fetch`), or wrap the call from the workflow in `Promise.race(step(), sleep('5m'))` to bail out after a bounded duration.
|
|
213
|
+
|
|
214
|
+
Temporal's retry policy knobs (`initialInterval`, `backoffCoefficient`, `maximumInterval`, `nonRetryableErrorTypes`) don't port 1:1 — only `maxRetries` is configurable at the step boundary. Classify retryability with `RetryableError` (retryable) and `FatalError` (terminal) instead of listing error types, and control the delay between attempts with `new RetryableError(msg, { retryAfter: '5s' })`.
|
|
215
|
+
|
|
216
|
+
Set `maxRetries` as a property assignment on the step function:
|
|
217
|
+
|
|
218
|
+
```typescript
|
|
219
|
+
async function chargePayment(orderId: string) {
|
|
220
|
+
"use step";
|
|
221
|
+
// ...
|
|
222
|
+
}
|
|
223
|
+
chargePayment.maxRetries = 5;
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
See [/docs/foundations/errors-and-retries](/docs/foundations/errors-and-retries) for full retry docs.
|
|
204
227
|
</Callout>
|
|
205
228
|
|
|
206
229
|
## What you stop operating
|
|
@@ -250,7 +273,7 @@ export async function processOrder(orderId: string) {
|
|
|
250
273
|
|
|
251
274
|
### Step 4: Replace Signals with hooks
|
|
252
275
|
|
|
253
|
-
Swap `defineSignal` + `setHandler` for `createHook()`. Callers `resumeHook(token, payload)` instead of `client.workflow.
|
|
276
|
+
Swap `defineSignal` + `setHandler` for `createHook()`. Callers `resumeHook(token, payload)` instead of `handle.signal(signalDef, payload)` on a `WorkflowHandle` obtained from `client.workflow.getHandle(workflowId)`.
|
|
254
277
|
|
|
255
278
|
### Step 5: Start runs from an API route or server action
|
|
256
279
|
|
|
@@ -271,6 +294,14 @@ export async function POST(req: Request) {
|
|
|
271
294
|
|
|
272
295
|
Remove the Worker process, `@temporalio/*` dependencies, and the Temporal Server or Cloud connection. Verify the run in the built-in observability UI (`npx workflow web`) before shipping.
|
|
273
296
|
|
|
297
|
+
## Features without a 1:1 equivalent
|
|
298
|
+
|
|
299
|
+
- **Search attributes / visibility queries.** Temporal's search attribute system has no direct analog. Filter runs by status and timestamps via `getRun()` / observability UI.
|
|
300
|
+
- **Event history archival.** Temporal archives histories to S3/GCS for long-term retention. Workflow SDK event logs are durable, but retention depends on the integration you are using. For example, see [Vercel Workflow Storage Retention](https://vercel.com/docs/workflows/pricing#storage-retention) for Vercel.
|
|
301
|
+
- **Per-activity timeouts (`startToCloseTimeout`, `scheduleToCloseTimeout`, `heartbeatTimeout`).** Implement deadlines inside the step with `AbortSignal.timeout(ms)`, or wrap the call in `Promise.race(step(), sleep(...))` from the workflow.
|
|
302
|
+
- **Rich retry policy (`initialInterval`, `backoffCoefficient`, `maximumInterval`, `nonRetryableErrorTypes`).** Only `maxRetries` is configurable. Classify retryability with `RetryableError`/`FatalError`; control delay between attempts via `new RetryableError(msg, { retryAfter: '5s' })`.
|
|
303
|
+
- **Workers + task queues.** Managed deployments replace workers; self-hosted deployments still need a `World` implementation (see [/docs/deploying/world](/docs/deploying/world)).
|
|
304
|
+
|
|
274
305
|
## Quick-start checklist
|
|
275
306
|
|
|
276
307
|
- Move orchestration into a `"use workflow"` function.
|
|
@@ -282,3 +313,6 @@ Remove the Worker process, `@temporalio/*` dependencies, and the Temporal Server
|
|
|
282
313
|
- Use `getStepMetadata().stepId` as the idempotency key for external side effects.
|
|
283
314
|
- Stream status and progress from steps with `getWritable({ namespace: 'status' })`, and have clients read from the stream instead of polling.
|
|
284
315
|
- Deploy the app and verify runs end-to-end in the built-in observability UI.
|
|
316
|
+
|
|
317
|
+
---
|
|
318
|
+
*Verified against `workflow@5.0.0-beta.1` and `@temporalio/workflow@1.16` on 2026-04-16.*
|
|
@@ -32,7 +32,7 @@ npx skills add https://github.com/vercel/workflow --skill migrating-to-workflow-
|
|
|
32
32
|
|
|
33
33
|
## What changes when you leave trigger.dev?
|
|
34
34
|
|
|
35
|
-
trigger.dev v3 defines durable work with `task()` or `schemaTask()` from `@trigger.dev/sdk
|
|
35
|
+
trigger.dev v3 defines durable work with `task()` or `schemaTask()` from `@trigger.dev/sdk` (trigger.dev v3), deploys tasks to the trigger.dev cloud or a self-hosted instance, and triggers runs via `tasks.trigger()`. A separate worker fleet picks up runs, applies retry policies, and routes `wait.for`, `wait.forToken`, and `metadata.stream` calls through the platform.
|
|
36
36
|
|
|
37
37
|
The Workflow SDK replaces that with `"use workflow"` functions that orchestrate `"use step"` functions in plain TypeScript. There is no task registry, separate deploy target, or SDK client. Durable replay, retries, and event history ship with the runtime.
|
|
38
38
|
|
|
@@ -46,21 +46,25 @@ Migration collapses the task abstraction into plain async functions. Business lo
|
|
|
46
46
|
| `schemaTask({ schema, run })` | Typed function + `"use workflow"` | Validate inputs at the call site. |
|
|
47
47
|
| Inline `run` body | `"use step"` function | Side effects move into named steps. |
|
|
48
48
|
| `logger` / `metadata.set` | `console` + `getWritable({ namespace: 'status' })` | Logs flow through the run timeline. Status writes go on a named stream. |
|
|
49
|
-
| `wait.for({ seconds })` / `wait.until({ date })` | `sleep()` | Import from `workflow`. |
|
|
49
|
+
| `wait.for({ seconds \| minutes \| hours \| days })` / `wait.until({ date })` | `sleep()` | Import from `workflow`. |
|
|
50
50
|
| `wait.forToken({ timeout })` | `createHook()` + `Promise.race` with `sleep()` | Hooks carry a typed token. |
|
|
51
51
|
| `tasks.trigger()` / `triggerAndWait()` | `start()` and `getRun(runId).returnValue` | Wrap both in `"use step"` functions. |
|
|
52
52
|
| `batch.triggerAndWait()` | `Promise.all(runIds.map(collectResult))` | Fan out via standard concurrency. |
|
|
53
53
|
| `AbortTaskRunError` | `FatalError` | Stops retries immediately. |
|
|
54
|
-
| `retry.onThrow` / `retry.fetch` | `RetryableError`, `FatalError`, `maxRetries` | Retry lives on the step.
|
|
55
|
-
| `metadata.stream()` / Realtime | `getWritable()` / `getWritable({ namespace })` |
|
|
54
|
+
| `retry.onThrow` / `retry.fetch` | `RetryableError`, `FatalError`, `maxRetries` | Retry count lives on the step via `myStep.maxRetries = N` (default 3). Control delay between attempts by throwing `new RetryableError(msg, { retryAfter: '5s' })` — there is no built-in exponential helper; compute the delay yourself based on `getStepMetadata().attempt` if you need one. |
|
|
55
|
+
| `metadata.stream()` / Realtime | `getWritable()` / `getWritable({ namespace })` | For granular business status (progress updates, current-stage messages), prefer writing to `getWritable({ namespace: 'status' })` from a step and reading from the end of the named stream on the client. Use `getRun(runId).status` for terminal/lifecycle state only. |
|
|
56
56
|
| Self-hosted worker + dashboard | Managed execution + built-in UI | No worker fleet to operate. |
|
|
57
57
|
|
|
58
58
|
## Translate your first workflow
|
|
59
59
|
|
|
60
|
+
<Callout type="warn">
|
|
61
|
+
trigger.dev's `task.run` body has full Node.js access. The SDK's `'use workflow'` body runs in a sandboxed VM — side effects (I/O, `Date.now()`, `Math.random()`, DB, fetch) must live inside `'use step'` functions. Orchestration stays in the workflow body.
|
|
62
|
+
</Callout>
|
|
63
|
+
|
|
60
64
|
Start with the shell. trigger.dev wraps the handler in `task()`; the Workflow SDK marks the function with a directive.
|
|
61
65
|
|
|
62
66
|
```typescript title="trigger/order.ts (trigger.dev)"
|
|
63
|
-
import { task } from '@trigger.dev/sdk
|
|
67
|
+
import { task } from '@trigger.dev/sdk';
|
|
64
68
|
|
|
65
69
|
export const processOrder = task({
|
|
66
70
|
id: 'process-order',
|
|
@@ -116,7 +120,7 @@ No id lookup, no API key, no separate worker. `start()` returns a handle immedia
|
|
|
116
120
|
|
|
117
121
|
{/* @skip-typecheck: trigger.dev SDK types not available */}
|
|
118
122
|
```typescript title="workflow/workflows/refund.ts (trigger.dev, abbreviated)"
|
|
119
|
-
// import { wait } from '@trigger.dev/sdk
|
|
123
|
+
// import { wait } from '@trigger.dev/sdk';
|
|
120
124
|
const token = await wait.createToken({ timeout: '7d' });
|
|
121
125
|
const approval = await wait.forToken<{ approved: boolean }>(token.id).unwrap();
|
|
122
126
|
// External system resumes with: await wait.completeToken(token.id, { approved: true });
|
|
@@ -130,10 +134,17 @@ using approval = createHook<{ approved: boolean }>({ // [!code highlight]
|
|
|
130
134
|
const payload = await approval;
|
|
131
135
|
```
|
|
132
136
|
|
|
133
|
-
**What changed:** the platform-issued opaque token becomes an app-owned string. The caller that resumes the run supplies that same string, so there is no token lookup.
|
|
137
|
+
**What changed:** the platform-issued opaque token becomes an app-owned string. The caller that resumes the run supplies that same string, so there is no token lookup. (trigger.dev also exposes `token.url` for external callers; the SDK analog is `createWebhook().url`).
|
|
134
138
|
|
|
135
139
|
### Resume from an API route
|
|
136
140
|
|
|
141
|
+
There are two shapes of resume, and `wait.forToken` can map to either:
|
|
142
|
+
|
|
143
|
+
- **Server-side resume (known token):** `createHook<T>({ token: 'business-token' })` + `resumeHook(token, payload)` from an API route. Use this when your app knows the token shape and controls the resume call.
|
|
144
|
+
- **Third-party callback URL (generated token):** `createWebhook({ respondWith: 'default' })` + pass `webhook.url` to the external system. The external system hits the URL to resume.
|
|
145
|
+
|
|
146
|
+
See [`/docs/foundations/hooks`](/docs/foundations/hooks) for both surfaces.
|
|
147
|
+
|
|
137
148
|
trigger.dev completes a token with `wait.completeToken(tokenId, { approved })`. The SDK equivalent is `resumeHook`:
|
|
138
149
|
|
|
139
150
|
```typescript title="app/api/refunds/[refundId]/approve/route.ts"
|
|
@@ -164,13 +175,15 @@ return { refundId, status: 'approved' };
|
|
|
164
175
|
```
|
|
165
176
|
|
|
166
177
|
<Callout type="info">
|
|
167
|
-
A hook is an inbound write channel. The caller that knows the token resumes the run with a typed payload.
|
|
178
|
+
A hook is an inbound write channel. The caller that knows the token resumes the run with a typed payload. For granular business status (progress updates, current-stage messages), prefer writing to `getWritable({ namespace: 'status' })` from a step and reading from the end of the named stream on the client. Use `getRun(runId).status` for terminal/lifecycle state only.
|
|
168
179
|
</Callout>
|
|
169
180
|
|
|
170
181
|
## Spawn a child workflow
|
|
171
182
|
|
|
172
183
|
`triggerAndWait()` splits into two steps: spawn and collect. `start()` and `getRun()` are runtime APIs, so wrap them in `"use step"` functions. Return the full `Run` object from `spawnChild` so observability tooling can deep-link to the child run.
|
|
173
184
|
|
|
185
|
+
You can return either the full `Run` object (enables deep-linking) or just `run.runId` (simpler). The runtime serializes `Run` to its `runId` in the event log either way.
|
|
186
|
+
|
|
174
187
|
```typescript title="workflow/workflows/parent.ts"
|
|
175
188
|
import { start } from 'workflow/api';
|
|
176
189
|
|
|
@@ -200,12 +213,14 @@ export async function parentWorkflow(item: string) {
|
|
|
200
213
|
|
|
201
214
|
To fan out, call `spawnChild` inside a loop, then `Promise.all` the `collectResult` calls. That replaces `batch.triggerAndWait()`.
|
|
202
215
|
|
|
216
|
+
`Promise.all` rejects on first failure; use `Promise.allSettled` if you need batch-mode error tolerance similar to trigger.dev's `{ ok, output, error }` per-run result.
|
|
217
|
+
|
|
203
218
|
## What you stop operating
|
|
204
219
|
|
|
205
220
|
Dropping the trigger.dev SDK removes several moving parts:
|
|
206
221
|
|
|
207
222
|
- **No task registry or `id` strings.** Workflow files carry directive annotations and export plain functions.
|
|
208
|
-
- **No `@trigger.dev/sdk
|
|
223
|
+
- **No `@trigger.dev/sdk` client or API key.** `start()` launches runs directly from API routes or server actions.
|
|
209
224
|
- **No worker fleet or self-hosted instance.** The runtime schedules execution inside the app's deploy target.
|
|
210
225
|
- **No separate Realtime channel.** `getWritable()` streams updates from steps over the run's durable stream.
|
|
211
226
|
- **No dashboard account.** The built-in observability UI (`npx workflow web`) reads the same event log the runtime writes.
|
|
@@ -218,7 +233,7 @@ Pick one trigger.dev task and migrate it end-to-end before touching the rest. Th
|
|
|
218
233
|
|
|
219
234
|
### Step 1: Install the Workflow SDK
|
|
220
235
|
|
|
221
|
-
Add the runtime.
|
|
236
|
+
Add the runtime. Framework integrations (Next.js, Nitro, Nuxt, SvelteKit, Astro, Nest) are subpath exports of the same `workflow` package, e.g. `workflow/next` — no additional install needed.
|
|
222
237
|
|
|
223
238
|
```bash
|
|
224
239
|
pnpm add workflow
|
|
@@ -255,7 +270,7 @@ async function loadOrder(id: string) {
|
|
|
255
270
|
|
|
256
271
|
### Step 4: Replace `wait.*` with hooks and `sleep`
|
|
257
272
|
|
|
258
|
-
- `wait.for({ seconds })` / `wait.until({ date })` → `sleep('5m')` or `sleep(date)` from `workflow`.
|
|
273
|
+
- `wait.for({ seconds | minutes | hours | days })` / `wait.until({ date })` → `sleep('5m')` or `sleep(date)` from `workflow`.
|
|
259
274
|
- `wait.forToken(token)` → `createHook({ token })` + `await`. Complete it with `resumeHook(token, payload)` from an API route.
|
|
260
275
|
- `wait.forToken({ timeout })` → `Promise.race([hook, sleep(timeout)])`.
|
|
261
276
|
- `triggerAndWait(payload)` → wrap `start(child, [payload])` in a `"use step"` function and return the `Run` object, then read the result with a second step that calls `getRun(runId).returnValue`.
|
|
@@ -279,6 +294,29 @@ export async function POST(req: Request) {
|
|
|
279
294
|
|
|
280
295
|
Remove the `@trigger.dev/sdk` dependency, the `trigger.config.ts` file, the `trigger/` directory, and any self-hosted worker deployment. Delete dashboard API keys from the environment. Verify the run in `npx workflow web` before shipping.
|
|
281
296
|
|
|
297
|
+
## Retries on steps
|
|
298
|
+
|
|
299
|
+
Retry count lives on the step function itself. Set it as a property on the step:
|
|
300
|
+
|
|
301
|
+
```typescript
|
|
302
|
+
async function chargePayment(orderId: string) {
|
|
303
|
+
"use step";
|
|
304
|
+
// ...
|
|
305
|
+
}
|
|
306
|
+
chargePayment.maxRetries = 5;
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
Throw `new RetryableError(msg, { retryAfter: '5s' })` to control delay between attempts, or `FatalError` to stop retries immediately. See [`/docs/foundations/errors-and-retries`](/docs/foundations/errors-and-retries).
|
|
310
|
+
|
|
311
|
+
## Features without a 1:1 equivalent
|
|
312
|
+
|
|
313
|
+
- **`schedules.task()` / cron triggers.** The SDK has no built-in scheduler. Trigger runs from Vercel Cron or a system cron calling `start()`.
|
|
314
|
+
- **Concurrency keys / queue concurrency limits.** No direct analog. Enforce limits inside steps (semaphores, external coordinator) or debounce at the publisher.
|
|
315
|
+
- **`machine` presets / custom images.** Machine specs are per-task in trigger.dev; in the SDK, function resources are per-deployment (configure via your hosting platform).
|
|
316
|
+
- **Realtime / `subscribeToRun`.** Use `getRun(runId).getReadable()` plus named `getWritable()` streams for live progress.
|
|
317
|
+
- **`onFailure` lifecycle hook.** No equivalent. Handle cleanup in the workflow body with a try/catch + compensation-stack pattern.
|
|
318
|
+
- **Trigger.dev dashboard.** Workflow SDK ships `npx workflow web` for local inspection and the Vercel Observability tab for deployed runs.
|
|
319
|
+
|
|
282
320
|
## Quick-start checklist
|
|
283
321
|
|
|
284
322
|
- Replace `task({ id, run })` with a `"use workflow"` function; launch it with `start()`.
|
|
@@ -294,3 +332,6 @@ Remove the `@trigger.dev/sdk` dependency, the `trigger.config.ts` file, the `tri
|
|
|
294
332
|
- Replace `metadata.stream()` and Realtime with `getWritable()`.
|
|
295
333
|
- Remove the `@trigger.dev/sdk` dependency, `trigger.config.ts`, and any self-hosted worker.
|
|
296
334
|
- Deploy and verify runs end-to-end with the built-in observability UI.
|
|
335
|
+
|
|
336
|
+
---
|
|
337
|
+
*Verified against `workflow@5.0.0-beta.1` and `@trigger.dev/sdk` v3 on 2026-04-16.*
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "workflow",
|
|
3
|
-
"version": "5.0.0-beta.
|
|
3
|
+
"version": "5.0.0-beta.4",
|
|
4
4
|
"description": "Workflow SDK - Build durable, resilient, and observable workflows",
|
|
5
5
|
"main": "dist/typescript-plugin.cjs",
|
|
6
6
|
"type": "module",
|
|
@@ -56,18 +56,18 @@
|
|
|
56
56
|
},
|
|
57
57
|
"dependencies": {
|
|
58
58
|
"ms": "2.1.3",
|
|
59
|
-
"@workflow/astro": "5.0.0-beta.
|
|
60
|
-
"@workflow/
|
|
59
|
+
"@workflow/astro": "5.0.0-beta.4",
|
|
60
|
+
"@workflow/cli": "5.0.0-beta.4",
|
|
61
|
+
"@workflow/core": "5.0.0-beta.4",
|
|
61
62
|
"@workflow/errors": "5.0.0-beta.1",
|
|
62
|
-
"@workflow/
|
|
63
|
-
"@workflow/typescript-plugin": "5.0.0-beta.2",
|
|
64
|
-
"@workflow/next": "5.0.0-beta.2",
|
|
63
|
+
"@workflow/typescript-plugin": "5.0.0-beta.3",
|
|
65
64
|
"@workflow/utils": "5.0.0-beta.1",
|
|
66
|
-
"@workflow/
|
|
67
|
-
"@workflow/nest": "5.0.0-beta.
|
|
68
|
-
"@workflow/
|
|
69
|
-
"@workflow/sveltekit": "5.0.0-beta.
|
|
70
|
-
"@workflow/rollup": "5.0.0-beta.
|
|
65
|
+
"@workflow/next": "5.0.0-beta.4",
|
|
66
|
+
"@workflow/nest": "5.0.0-beta.4",
|
|
67
|
+
"@workflow/nuxt": "5.0.0-beta.4",
|
|
68
|
+
"@workflow/sveltekit": "5.0.0-beta.4",
|
|
69
|
+
"@workflow/rollup": "5.0.0-beta.4",
|
|
70
|
+
"@workflow/nitro": "5.0.0-beta.4"
|
|
71
71
|
},
|
|
72
72
|
"devDependencies": {
|
|
73
73
|
"@types/ms": "2.1.0",
|