workflow 5.0.0-beta.34 → 5.0.0-beta.36

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.
Files changed (71) hide show
  1. package/dist/internal/errors.d.ts +1 -1
  2. package/dist/internal/errors.d.ts.map +1 -1
  3. package/dist/internal/errors.js +2 -2
  4. package/dist/nest-builder.d.ts +2 -0
  5. package/dist/nest-builder.d.ts.map +1 -0
  6. package/dist/nest-builder.js +2 -0
  7. package/dist/nest-vercel-builder.d.ts +2 -0
  8. package/dist/nest-vercel-builder.d.ts.map +1 -0
  9. package/dist/nest-vercel-builder.js +2 -0
  10. package/docs/api-reference/workflow/create-hook.mdx +43 -2
  11. package/docs/api-reference/workflow/define-hook.mdx +26 -24
  12. package/docs/api-reference/workflow/fatal-error.mdx +29 -7
  13. package/docs/api-reference/workflow/fetch.mdx +3 -4
  14. package/docs/api-reference/workflow/sleep.mdx +1 -1
  15. package/docs/api-reference/workflow-api/get-hook-by-token.mdx +2 -0
  16. package/docs/api-reference/workflow-api/resume-hook.mdx +2 -0
  17. package/docs/api-reference/workflow-api/resume-webhook.mdx +6 -4
  18. package/docs/api-reference/workflow-api/start.mdx +1 -1
  19. package/docs/api-reference/workflow-errors/index.mdx +3 -0
  20. package/docs/api-reference/workflow-errors/meta.json +1 -0
  21. package/docs/api-reference/workflow-errors/precondition-failed-error.mdx +62 -0
  22. package/docs/api-reference/workflow-nest/nest-local-builder.mdx +1 -1
  23. package/docs/comparisons/index.mdx +66 -0
  24. package/docs/comparisons/meta.json +11 -0
  25. package/docs/comparisons/workflow-sdk-vs-aws-agentcore.mdx +55 -0
  26. package/docs/comparisons/workflow-sdk-vs-aws-step-functions.mdx +111 -0
  27. package/docs/comparisons/workflow-sdk-vs-cloudflare-workflows.mdx +71 -0
  28. package/docs/comparisons/workflow-sdk-vs-inngest.mdx +102 -0
  29. package/docs/comparisons/workflow-sdk-vs-temporal.mdx +123 -0
  30. package/docs/comparisons/workflow-sdk-vs-trigger-dev.mdx +103 -0
  31. package/docs/configuration/runtime-tuning.mdx +26 -0
  32. package/docs/configuration/worlds.mdx +6 -7
  33. package/docs/cookbook/common-patterns/idempotency.mdx +1 -1
  34. package/docs/{deploying/index.mdx → deploying.mdx} +6 -8
  35. package/docs/foundations/hooks.mdx +1 -1
  36. package/docs/foundations/idempotency.mdx +16 -9
  37. package/docs/getting-started/astro.mdx +1 -1
  38. package/docs/getting-started/express.mdx +1 -1
  39. package/docs/getting-started/fastify.mdx +1 -1
  40. package/docs/getting-started/hono.mdx +1 -1
  41. package/docs/getting-started/index.mdx +10 -3
  42. package/docs/getting-started/meta.json +3 -1
  43. package/docs/getting-started/nestjs.mdx +63 -2
  44. package/docs/getting-started/next.mdx +2 -2
  45. package/docs/getting-started/nitro.mdx +1 -1
  46. package/docs/getting-started/nuxt.mdx +1 -1
  47. package/docs/getting-started/python.mdx +19 -17
  48. package/docs/getting-started/react-router/index.mdx +33 -0
  49. package/docs/getting-started/react-router/meta.json +5 -0
  50. package/docs/getting-started/react-router/v7.mdx +237 -0
  51. package/docs/getting-started/react-router/v8.mdx +232 -0
  52. package/docs/getting-started/sveltekit.mdx +1 -1
  53. package/docs/getting-started/vite.mdx +1 -1
  54. package/docs/how-it-works/encryption.mdx +3 -3
  55. package/docs/how-it-works/event-sourcing.mdx +6 -6
  56. package/docs/how-it-works/framework-integrations.mdx +3 -3
  57. package/docs/meta.json +1 -1
  58. package/docs/observability/attributes.mdx +9 -0
  59. package/package.json +13 -11
  60. package/docs/deploying/building-a-world.mdx +0 -251
  61. package/docs/deploying/meta.json +0 -4
  62. package/docs/deploying/world/local-world.mdx +0 -101
  63. package/docs/deploying/world/meta.json +0 -4
  64. package/docs/deploying/world/postgres-world.mdx +0 -288
  65. package/docs/deploying/world/vercel-world.mdx +0 -275
  66. package/docs/migration-guides/index.mdx +0 -34
  67. package/docs/migration-guides/meta.json +0 -9
  68. package/docs/migration-guides/migrating-from-aws-step-functions.mdx +0 -362
  69. package/docs/migration-guides/migrating-from-inngest.mdx +0 -308
  70. package/docs/migration-guides/migrating-from-temporal.mdx +0 -317
  71. package/docs/migration-guides/migrating-from-trigger-dev.mdx +0 -332
@@ -0,0 +1,237 @@
1
+ ---
2
+ title: React Router v7
3
+ description: Add durable workflows to a React Router v7 framework-mode app using Nitro v3.
4
+ type: guide
5
+ summary: Enable the Vite Environment API and configure React Router v7, Nitro v3, and Workflow SDK.
6
+ prerequisites:
7
+ - /docs/getting-started/react-router
8
+ related:
9
+ - /docs/getting-started/nitro
10
+ - /docs/foundations/workflows-and-steps
11
+ ---
12
+
13
+ This guide starts with an existing React Router v7 framework-mode app. It is verified with v7.18.1; if your config does not recognize `v8_viteEnvironmentApi`, update to the latest v7 release.
14
+
15
+ <Steps>
16
+
17
+ <Step>
18
+
19
+ ## Install Nitro and Workflow SDK
20
+
21
+ <Tabs items={["npm", "pnpm", "bun", "yarn"]} defaultValue="pnpm">
22
+
23
+ <Tab value="npm">
24
+
25
+ ```bash
26
+ npm install nitro workflow
27
+ ```
28
+
29
+ </Tab>
30
+
31
+ <Tab value="pnpm">
32
+
33
+ ```bash
34
+ pnpm add nitro workflow
35
+ ```
36
+
37
+ </Tab>
38
+
39
+ <Tab value="bun">
40
+
41
+ ```bash
42
+ bun add nitro workflow
43
+ ```
44
+
45
+ </Tab>
46
+
47
+ <Tab value="yarn">
48
+
49
+ ```bash
50
+ yarn add nitro workflow
51
+ ```
52
+
53
+ </Tab>
54
+
55
+ </Tabs>
56
+
57
+ This integration requires Nitro v3.
58
+
59
+ </Step>
60
+
61
+ <Step>
62
+
63
+ ## Enable the Vite Environment API
64
+
65
+ React Router v7 keeps the Vite Environment API behind a future flag. Enable the required flag and set an explicit build directory:
66
+
67
+ ```typescript title="react-router.config.ts" lineNumbers
68
+ import type { Config } from "@react-router/dev/config";
69
+
70
+ export default {
71
+ ssr: true,
72
+ buildDirectory: "build", // [!code highlight]
73
+ future: {
74
+ v8_viteEnvironmentApi: true, // [!code highlight]
75
+ },
76
+ } satisfies Config;
77
+ ```
78
+
79
+ </Step>
80
+
81
+ <Step>
82
+
83
+ ## Create the React Router server handler
84
+
85
+ Create `server/ssr.ts`:
86
+
87
+ ```typescript title="server/ssr.ts" lineNumbers
88
+ import { createRequestHandler } from "react-router";
89
+
90
+ export default {
91
+ fetch: createRequestHandler(
92
+ () => import("virtual:react-router/server-build"),
93
+ import.meta.env.MODE,
94
+ ),
95
+ };
96
+ ```
97
+
98
+ This adapts React Router's generated server build to the Fetch API handler Nitro expects.
99
+
100
+ </Step>
101
+
102
+ <Step>
103
+
104
+ ## Configure Vite
105
+
106
+ Update `vite.config.ts`:
107
+
108
+ ```typescript title="vite.config.ts" lineNumbers
109
+ import { reactRouter } from "@react-router/dev/vite";
110
+ import { nitro } from "nitro/vite";
111
+ import { defineConfig } from "vite";
112
+ import { workflow } from "workflow/vite";
113
+ import reactRouterConfig from "./react-router.config";
114
+
115
+ export default defineConfig({
116
+ plugins: [
117
+ reactRouter(),
118
+ nitro({
119
+ serverDir: "./server",
120
+ output: {
121
+ dir: reactRouterConfig.buildDirectory,
122
+ serverDir: `${reactRouterConfig.buildDirectory}/server`,
123
+ publicDir: `${reactRouterConfig.buildDirectory}/client`,
124
+ },
125
+ }),
126
+ workflow({ dirs: ["workflows"] }),
127
+ ],
128
+ environments: {
129
+ ssr: {
130
+ build: {
131
+ rollupOptions: {
132
+ input: "./server/ssr.ts",
133
+ },
134
+ },
135
+ },
136
+ },
137
+ });
138
+ ```
139
+
140
+ Keep `dirs: ["workflows"]` so subsequent builds do not scan generated files under `build`. Place `reactRouter()` before `nitro()` in the plugin array.
141
+
142
+ </Step>
143
+
144
+ <Step>
145
+
146
+ ## Create a workflow
147
+
148
+ Create `workflows/greeting.ts`:
149
+
150
+ ```typescript title="workflows/greeting.ts" lineNumbers
151
+ export async function greetingWorkflow(name: string) {
152
+ "use workflow";
153
+
154
+ return greet(name);
155
+ }
156
+
157
+ async function greet(name: string) {
158
+ "use step";
159
+
160
+ return `Hello, ${name}!`;
161
+ }
162
+ ```
163
+
164
+ </Step>
165
+
166
+ <Step>
167
+
168
+ ## Start the workflow from a Nitro route
169
+
170
+ Create `server/routes/api/greeting.post.ts`:
171
+
172
+ ```typescript title="server/routes/api/greeting.post.ts" lineNumbers
173
+ import { defineHandler } from "nitro";
174
+ import { start } from "workflow/api";
175
+ import { greetingWorkflow } from "../../../workflows/greeting";
176
+
177
+ export default defineHandler(async (event) => {
178
+ const { name } = (await event.req.json()) as { name: string };
179
+ const run = await start(greetingWorkflow, [name]);
180
+
181
+ return { runId: run.runId };
182
+ });
183
+ ```
184
+
185
+ React Router continues to handle your application routes. Nitro handles this server route at `POST /api/greeting`, as well as Workflow SDK's internal routes.
186
+
187
+ </Step>
188
+
189
+ <Step>
190
+
191
+ ## Run the app
192
+
193
+ Start the development server:
194
+
195
+ ```bash
196
+ pnpm vite dev
197
+ ```
198
+
199
+ Then start a workflow:
200
+
201
+ ```bash
202
+ curl -X POST \
203
+ -H "content-type: application/json" \
204
+ -d '{"name":"Workflow"}' \
205
+ http://localhost:3000/api/greeting
206
+ ```
207
+
208
+ Build and start the production server:
209
+
210
+ ```bash
211
+ pnpm vite build
212
+ node ./build/server/index.mjs
213
+ ```
214
+
215
+ You can inspect local runs with `pnpm workflow web`.
216
+
217
+ </Step>
218
+
219
+ </Steps>
220
+
221
+ ## Troubleshooting
222
+
223
+ ### Vite reports an invalid SSR input or `path.replace is not a function`
224
+
225
+ Set `future.v8_viteEnvironmentApi` to `true` in `react-router.config.ts`.
226
+
227
+ ### React Router pages return 404
228
+
229
+ Check that the `ssr` environment input points to `./server/ssr.ts`.
230
+
231
+ ### A second build tries to compile files under `build/server`
232
+
233
+ Use `workflow({ dirs: ["workflows"] })`, remove the existing `build` directory once, and rebuild.
234
+
235
+ ### `vite build` finishes output but does not exit
236
+
237
+ Use `workflow@5.0.0-beta.33` or later with Nitro v3.
@@ -0,0 +1,232 @@
1
+ ---
2
+ title: React Router v8
3
+ description: Add durable workflows to a React Router v8 framework-mode app using Nitro v3.
4
+ type: guide
5
+ summary: Configure React Router v8, Nitro v3, and Workflow SDK in one Vite build.
6
+ prerequisites:
7
+ - /docs/getting-started/react-router
8
+ related:
9
+ - /docs/getting-started/nitro
10
+ - /docs/foundations/workflows-and-steps
11
+ ---
12
+
13
+ This guide starts with an existing React Router v8 framework-mode app.
14
+
15
+ <Steps>
16
+
17
+ <Step>
18
+
19
+ ## Install Nitro and Workflow SDK
20
+
21
+ <Tabs items={["npm", "pnpm", "bun", "yarn"]} defaultValue="pnpm">
22
+
23
+ <Tab value="npm">
24
+
25
+ ```bash
26
+ npm install nitro workflow
27
+ ```
28
+
29
+ </Tab>
30
+
31
+ <Tab value="pnpm">
32
+
33
+ ```bash
34
+ pnpm add nitro workflow
35
+ ```
36
+
37
+ </Tab>
38
+
39
+ <Tab value="bun">
40
+
41
+ ```bash
42
+ bun add nitro workflow
43
+ ```
44
+
45
+ </Tab>
46
+
47
+ <Tab value="yarn">
48
+
49
+ ```bash
50
+ yarn add nitro workflow
51
+ ```
52
+
53
+ </Tab>
54
+
55
+ </Tabs>
56
+
57
+ This integration requires Nitro v3.
58
+
59
+ </Step>
60
+
61
+ <Step>
62
+
63
+ ## Use a shared build directory
64
+
65
+ Set an explicit build directory in your React Router config:
66
+
67
+ ```typescript title="react-router.config.ts" lineNumbers
68
+ import type { Config } from "@react-router/dev/config";
69
+
70
+ export default {
71
+ ssr: true,
72
+ buildDirectory: "build", // [!code highlight]
73
+ } satisfies Config;
74
+ ```
75
+
76
+ React Router will place browser assets in `build/client`. Nitro will place the runnable server in `build/server`.
77
+
78
+ </Step>
79
+
80
+ <Step>
81
+
82
+ ## Create the React Router server handler
83
+
84
+ Create `server/ssr.ts`:
85
+
86
+ ```typescript title="server/ssr.ts" lineNumbers
87
+ import { createRequestHandler } from "react-router";
88
+
89
+ export default {
90
+ fetch: createRequestHandler(
91
+ () => import("virtual:react-router/server-build"),
92
+ import.meta.env.MODE,
93
+ ),
94
+ };
95
+ ```
96
+
97
+ This adapts React Router's generated server build to the Fetch API handler Nitro expects.
98
+
99
+ </Step>
100
+
101
+ <Step>
102
+
103
+ ## Configure Vite
104
+
105
+ Update `vite.config.ts`:
106
+
107
+ ```typescript title="vite.config.ts" lineNumbers
108
+ import { reactRouter } from "@react-router/dev/vite";
109
+ import { nitro } from "nitro/vite";
110
+ import { defineConfig } from "vite";
111
+ import { workflow } from "workflow/vite";
112
+ import reactRouterConfig from "./react-router.config";
113
+
114
+ export default defineConfig({
115
+ plugins: [
116
+ reactRouter(),
117
+ nitro({
118
+ serverDir: "./server",
119
+ output: {
120
+ dir: reactRouterConfig.buildDirectory,
121
+ serverDir: `${reactRouterConfig.buildDirectory}/server`,
122
+ publicDir: `${reactRouterConfig.buildDirectory}/client`,
123
+ },
124
+ }),
125
+ workflow({ dirs: ["workflows"] }),
126
+ ],
127
+ environments: {
128
+ ssr: {
129
+ build: {
130
+ rollupOptions: {
131
+ input: "./server/ssr.ts",
132
+ },
133
+ },
134
+ },
135
+ },
136
+ });
137
+ ```
138
+
139
+ Keep `dirs: ["workflows"]` so subsequent builds do not scan generated files under `build`. Place `reactRouter()` before `nitro()` in the plugin array.
140
+
141
+ </Step>
142
+
143
+ <Step>
144
+
145
+ ## Create a workflow
146
+
147
+ Create `workflows/greeting.ts`:
148
+
149
+ ```typescript title="workflows/greeting.ts" lineNumbers
150
+ export async function greetingWorkflow(name: string) {
151
+ "use workflow";
152
+
153
+ return greet(name);
154
+ }
155
+
156
+ async function greet(name: string) {
157
+ "use step";
158
+
159
+ return `Hello, ${name}!`;
160
+ }
161
+ ```
162
+
163
+ </Step>
164
+
165
+ <Step>
166
+
167
+ ## Start the workflow from a Nitro route
168
+
169
+ Create `server/routes/api/greeting.post.ts`:
170
+
171
+ ```typescript title="server/routes/api/greeting.post.ts" lineNumbers
172
+ import { defineHandler } from "nitro";
173
+ import { start } from "workflow/api";
174
+ import { greetingWorkflow } from "../../../workflows/greeting";
175
+
176
+ export default defineHandler(async (event) => {
177
+ const { name } = (await event.req.json()) as { name: string };
178
+ const run = await start(greetingWorkflow, [name]);
179
+
180
+ return { runId: run.runId };
181
+ });
182
+ ```
183
+
184
+ React Router continues to handle your application routes. Nitro handles this server route at `POST /api/greeting`, as well as Workflow SDK's internal routes.
185
+
186
+ </Step>
187
+
188
+ <Step>
189
+
190
+ ## Run the app
191
+
192
+ Start the development server:
193
+
194
+ ```bash
195
+ pnpm vite dev
196
+ ```
197
+
198
+ Then start a workflow:
199
+
200
+ ```bash
201
+ curl -X POST \
202
+ -H "content-type: application/json" \
203
+ -d '{"name":"Workflow"}' \
204
+ http://localhost:3000/api/greeting
205
+ ```
206
+
207
+ Build and start the production server:
208
+
209
+ ```bash
210
+ pnpm vite build
211
+ node ./build/server/index.mjs
212
+ ```
213
+
214
+ You can inspect local runs with `pnpm workflow web`.
215
+
216
+ </Step>
217
+
218
+ </Steps>
219
+
220
+ ## Troubleshooting
221
+
222
+ ### React Router pages return 404
223
+
224
+ Check that the `ssr` environment input points to `./server/ssr.ts`.
225
+
226
+ ### A second build tries to compile files under `build/server`
227
+
228
+ Use `workflow({ dirs: ["workflows"] })`, remove the existing `build` directory once, and rebuild.
229
+
230
+ ### `vite build` finishes output but does not exit
231
+
232
+ Use `workflow@5.0.0-beta.33` or later with Nitro v3.
@@ -245,7 +245,7 @@ Check the [Deploying](/docs/deploying) section to learn how your workflows can b
245
245
  If you see this error:
246
246
 
247
247
  ```
248
- 'start' received an invalid workflow function. Ensure the Workflow Development Kit is configured correctly and the function includes a 'use workflow' directive.
248
+ 'start' received an invalid workflow function. Ensure the Workflow SDK is configured correctly and the function includes a 'use workflow' directive.
249
249
  ```
250
250
 
251
251
  Check both of these first:
@@ -245,7 +245,7 @@ Check the [Deploying](/docs/deploying) section to learn how your workflows can b
245
245
  If you see this error:
246
246
 
247
247
  ```
248
- 'start' received an invalid workflow function. Ensure the Workflow Development Kit is configured correctly and the function includes a 'use workflow' directive.
248
+ 'start' received an invalid workflow function. Ensure the Workflow SDK is configured correctly and the function includes a 'use workflow' directive.
249
249
  ```
250
250
 
251
251
  Check both of these first:
@@ -7,7 +7,7 @@ prerequisites:
7
7
  - /docs/how-it-works/event-sourcing
8
8
  related:
9
9
  - /docs/observability
10
- - /docs/deploying/world/vercel-world
10
+ - /worlds/vercel
11
11
  ---
12
12
 
13
13
  <Callout>
@@ -38,7 +38,7 @@ Metadata such as workflow names, step names, entity IDs, timestamps, and lifecyc
38
38
 
39
39
  Each workflow run is encrypted with its own unique key, provided by the `World` implementation via `getEncryptionKeyForRun()`. How the key is generated and stored is up to the `World`.
40
40
 
41
- For example, the [Vercel World](/docs/deploying/world/vercel-world) provides unique keys per run and execution environment, ensuring that a given run can only decrypt data from that run itself.
41
+ For example, the [Vercel World](/worlds/vercel) provides unique keys per run and execution environment, ensuring that a given run can only decrypt data from that run itself.
42
42
 
43
43
  ### Encryption Algorithm
44
44
 
@@ -127,4 +127,4 @@ async function lookupRunKey(
127
127
  }
128
128
  ```
129
129
 
130
- The [Vercel World](/docs/deploying/world/vercel-world) implementation uses HKDF derivation from a deployment-scoped key, but any consistent key management scheme will work.
130
+ The [Vercel World](/worlds/vercel) implementation uses HKDF derivation from a deployment-scoped key, but any consistent key management scheme will work.
@@ -121,15 +121,15 @@ flowchart TD
121
121
 
122
122
  **Hook states:**
123
123
 
124
- - `active`: Ready to receive payloads (hook exists in storage)
125
- - `disposed`: No longer accepting payloads (hook is deleted from storage)
124
+ - `active`: Ready to receive payloads
125
+ - `disposed`: No longer accepting payloads
126
126
  - `conflicted`: Hook creation failed because the token is already in use by another workflow
127
127
 
128
- Unlike other entities, hooks don't have a `status` field—the states above are conceptual. An "active" hook is one that exists in storage, while "disposed" means the hook has been deleted. When a `hook_disposed` event is created, the hook record is removed rather than updated.
128
+ Unlike other entities, hooks don't have a `status` field—the states above are conceptual. When a `hook_disposed` event is created, the hook record is removed rather than updated.
129
129
 
130
- While a hook is active, its token is reserved and cannot be used by other workflows. If a workflow attempts to create a hook with a token that is already in use by another active hook, a `hook_conflict` event is recorded instead of `hook_created`. Current worlds include the token and the run ID that currently owns it, though older persisted events or world implementations may only include the token. This causes `hook.getConflict()` to resolve with the conflicting run and the hook's payload promise to reject with a `HookConflictError`, which you can detect with `HookConflictError.is(error)`. See the [hook-conflict error](/docs/errors/hook-conflict) documentation for more details.
130
+ While a hook is active, its token is reserved and cannot be used by other workflows. If a workflow attempts to create a hook with a token reserved by another run either by an active hook or by `experimental_minRetention` after its run ended — a `hook_conflict` event is recorded instead of `hook_created`. Current worlds include the token and the run ID that owns it, though older persisted events or world implementations may only include the token. This causes `hook.getConflict()` to resolve with the conflicting run and the hook's payload promise to reject with a `HookConflictError`, which you can detect with `HookConflictError.is(error)`. See the [hook-conflict error](/docs/errors/hook-conflict) documentation for more details.
131
131
 
132
- When a hook is disposed (either explicitly or when its workflow completes), the token is released and can be claimed by future workflows. Hooks are automatically disposed when a workflow reaches a terminal state (`completed`, `failed`, or `cancelled`). The `hook_disposed` event is only needed for explicit disposal before workflow completion.
132
+ When a workflow ends, its Hooks can no longer be resumed. They are normally removed and their tokens become available again. With `experimental_minRetention`, a Hook remains readable and its token remains unavailable until retention ends. A `hook_disposed` event removes the Hook and makes its token available immediately.
133
133
 
134
134
  See [Hooks & Webhooks](/docs/foundations/hooks) for more on how hooks and webhooks work.
135
135
 
@@ -188,7 +188,7 @@ Events are categorized by the entity type they affect. Each event contains metad
188
188
  | Event | Description |
189
189
  |-------|-------------|
190
190
  | `hook_created` | Creates a new hook in `active` state. Contains the hook token and optional metadata. |
191
- | `hook_conflict` | Records that hook creation failed because the token is already in use by another active hook. Contains the token and, for current worlds, the active hook owner's run ID. The hook is not created: `hook.getConflict()` resolves with the conflicting run, and awaiting the hook payload rejects with a `HookConflictError`. |
191
+ | `hook_conflict` | Records that hook creation failed because another run owns the token. Contains the token and, for current worlds, the owner's run ID. The hook is not created: `hook.getConflict()` resolves with the conflicting run, and awaiting the hook payload rejects with a `HookConflictError`. |
192
192
  | `hook_received` | Records that a payload was delivered to the hook. The hook remains `active` and can receive more payloads. |
193
193
  | `hook_disposed` | Deletes the hook from storage (conceptually transitioning to `disposed` state). The token is released for reuse by future workflows. |
194
194
 
@@ -6,7 +6,7 @@ summary: Build a custom framework integration using the Workflow SDK compiler an
6
6
  prerequisites:
7
7
  - /docs/foundations/workflows-and-steps
8
8
  related:
9
- - /docs/deploying/building-a-world
9
+ - /worlds/building-a-world
10
10
  ---
11
11
 
12
12
  <Callout>
@@ -414,7 +414,7 @@ const flowTriggers = [getWorkflowQueueTrigger()];
414
414
  const stepTriggers = [STEP_QUEUE_TRIGGER];
415
415
  ```
416
416
 
417
- If your integration constructs the flow trigger object itself instead of calling `getWorkflowQueueTrigger()`, it must add `maxConcurrency: 1` to that trigger when sequential replays are enabled at build time (`WORKFLOW_SEQUENTIAL_REPLAYS=1`, or `WORKFLOW_SAFE_MODE=1` when the specific variable is unset — the exported `isSequentialReplaysEnabled()` helper implements this check). The runtime half of the feature (per-run queue topics) activates from the environment variable alone — without the trigger half, those per-run topics are not serialized and the setting only adds queue-topic cardinality.
417
+ If your integration constructs the flow trigger object itself instead of calling `getWorkflowQueueTrigger()`, it must add `maxConcurrency: 1` to that trigger when sequential replays are enabled at build time (`WORKFLOW_SEQUENTIAL_REPLAYS=1` — the exported `isSequentialReplaysEnabled()` helper implements this check). The runtime half of the feature (per-run queue topics) activates from the environment variable alone — without the trigger half, those per-run topics are not serialized and the setting only adds queue-topic cardinality.
418
418
 
419
419
 
420
420
  ### Custom implementations
@@ -425,7 +425,7 @@ For self-hosted or non-Vercel deployments, you are responsible for securing the
425
425
  - **Network-level security** — Deploy handlers behind a VPC, private network, or firewall rules so only your queue infrastructure can reach them
426
426
  - **Rate limiting** — Add request validation and rate limiting to prevent abuse
427
427
 
428
- Learn more about [building custom Worlds](/docs/deploying/building-a-world).
428
+ Learn more about [building custom Worlds](/worlds/building-a-world).
429
429
 
430
430
  ## Testing Your Integration
431
431
 
package/docs/meta.json CHANGED
@@ -9,7 +9,7 @@
9
9
  "testing",
10
10
  "deploying",
11
11
  "errors",
12
- "migration-guides",
12
+ "comparisons",
13
13
  "configuration",
14
14
  "api-reference"
15
15
  ]
@@ -57,6 +57,15 @@ export async function cleanupAttributes() {
57
57
 
58
58
  Attribute keys must be 1-256 characters, values must be strings up to 256 bytes, and each run can have up to 64 attributes. Keys that start with `$` are reserved for framework and library code.
59
59
 
60
+ ## Reserved keys
61
+
62
+ When `start()` is called from inside a running workflow or step, the new run is automatically tagged with two reserved attributes:
63
+
64
+ - `$parentRunId`: the run that started it.
65
+ - `$rootRunId`: the root of the chain. It is inherited, so every run in a daisy chain or fan-out shares one root id.
66
+
67
+ Top-level runs (started outside any workflow or step) are not tagged.
68
+
60
69
  ## Viewing attributes
61
70
 
62
71
  The run details panel in the observability UI shows the run's current attributes as key-value rows. Reserved `$`-prefixed keys are marked with a badge and sorted after user keys:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "workflow",
3
- "version": "5.0.0-beta.34",
3
+ "version": "5.0.0-beta.36",
4
4
  "description": "Workflow SDK - Build durable, resilient, and observable workflows",
5
5
  "main": "dist/typescript-plugin.cjs",
6
6
  "type": "module",
@@ -49,6 +49,8 @@
49
49
  "./astro": "./dist/astro.js",
50
50
  "./vite": "./dist/vite.js",
51
51
  "./nest": "./dist/nest.js",
52
+ "./nest/builder": "./dist/nest-builder.js",
53
+ "./nest/vercel-builder": "./dist/nest-vercel-builder.js",
52
54
  "./runtime": "./dist/runtime.js",
53
55
  "./observability": {
54
56
  "types": "./dist/observability.d.ts",
@@ -57,18 +59,18 @@
57
59
  },
58
60
  "dependencies": {
59
61
  "ms": "2.1.3",
60
- "@workflow/astro": "5.0.0-beta.34",
61
- "@workflow/cli": "5.0.0-beta.34",
62
- "@workflow/core": "5.0.0-beta.34",
63
- "@workflow/errors": "5.0.0-beta.10",
62
+ "@workflow/astro": "5.0.0-beta.36",
63
+ "@workflow/cli": "5.0.0-beta.36",
64
+ "@workflow/core": "5.0.0-beta.36",
64
65
  "@workflow/typescript-plugin": "5.0.0-beta.5",
66
+ "@workflow/errors": "5.0.0-beta.12",
65
67
  "@workflow/utils": "5.0.0-beta.6",
66
- "@workflow/next": "5.0.0-beta.34",
67
- "@workflow/nest": "5.0.0-beta.34",
68
- "@workflow/nitro": "5.0.0-beta.34",
69
- "@workflow/nuxt": "5.0.0-beta.34",
70
- "@workflow/sveltekit": "5.0.0-beta.34",
71
- "@workflow/rollup": "5.0.0-beta.34"
68
+ "@workflow/next": "5.0.0-beta.36",
69
+ "@workflow/nest": "5.0.0-beta.36",
70
+ "@workflow/nitro": "5.0.0-beta.36",
71
+ "@workflow/nuxt": "5.0.0-beta.36",
72
+ "@workflow/sveltekit": "5.0.0-beta.36",
73
+ "@workflow/rollup": "5.0.0-beta.36"
72
74
  },
73
75
  "devDependencies": {
74
76
  "@types/ms": "2.1.0",