workflow 5.0.0-beta.35 → 5.0.0-beta.37

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 (72) hide show
  1. package/dist/nest-builder.d.ts +2 -0
  2. package/dist/nest-builder.d.ts.map +1 -0
  3. package/dist/nest-builder.js +2 -0
  4. package/dist/nest-vercel-builder.d.ts +2 -0
  5. package/dist/nest-vercel-builder.d.ts.map +1 -0
  6. package/dist/nest-vercel-builder.js +2 -0
  7. package/dist/runtime.d.ts +1 -1
  8. package/dist/runtime.d.ts.map +1 -1
  9. package/dist/runtime.js +1 -1
  10. package/docs/ai/index.mdx +1 -1
  11. package/docs/api-reference/workflow/create-hook.mdx +43 -2
  12. package/docs/api-reference/workflow/define-hook.mdx +26 -24
  13. package/docs/api-reference/workflow/fatal-error.mdx +29 -7
  14. package/docs/api-reference/workflow/fetch.mdx +3 -4
  15. package/docs/api-reference/workflow/set-attributes.mdx +0 -4
  16. package/docs/api-reference/workflow/sleep.mdx +1 -1
  17. package/docs/api-reference/workflow-api/get-hook-by-token.mdx +2 -0
  18. package/docs/api-reference/workflow-api/resume-hook.mdx +2 -0
  19. package/docs/api-reference/workflow-api/resume-webhook.mdx +6 -4
  20. package/docs/api-reference/workflow-api/start.mdx +1 -1
  21. package/docs/api-reference/workflow-globals.mdx +4 -1
  22. package/docs/api-reference/workflow-nest/nest-local-builder.mdx +1 -1
  23. package/docs/api-reference/workflow-runtime/health-check.mdx +4 -4
  24. package/docs/api-reference/workflow-runtime/world/queue.mdx +4 -4
  25. package/docs/comparisons/index.mdx +66 -0
  26. package/docs/comparisons/meta.json +11 -0
  27. package/docs/comparisons/workflow-sdk-vs-aws-agentcore.mdx +55 -0
  28. package/docs/comparisons/workflow-sdk-vs-aws-step-functions.mdx +111 -0
  29. package/docs/comparisons/workflow-sdk-vs-cloudflare-workflows.mdx +71 -0
  30. package/docs/comparisons/workflow-sdk-vs-inngest.mdx +102 -0
  31. package/docs/comparisons/workflow-sdk-vs-temporal.mdx +123 -0
  32. package/docs/comparisons/workflow-sdk-vs-trigger-dev.mdx +103 -0
  33. package/docs/configuration/build-and-diagnostics.mdx +19 -0
  34. package/docs/configuration/runtime-tuning.mdx +30 -6
  35. package/docs/configuration/worlds.mdx +22 -8
  36. package/docs/cookbook/advanced/publishing-libraries.mdx +17 -13
  37. package/docs/cookbook/common-patterns/idempotency.mdx +1 -1
  38. package/docs/{deploying/index.mdx → deploying.mdx} +6 -8
  39. package/docs/foundations/hooks.mdx +1 -1
  40. package/docs/foundations/idempotency.mdx +16 -9
  41. package/docs/getting-started/astro.mdx +2 -2
  42. package/docs/getting-started/express.mdx +2 -2
  43. package/docs/getting-started/fastify.mdx +2 -2
  44. package/docs/getting-started/hono.mdx +2 -2
  45. package/docs/getting-started/index.mdx +3 -3
  46. package/docs/getting-started/meta.json +2 -1
  47. package/docs/getting-started/nestjs.mdx +64 -3
  48. package/docs/getting-started/next.mdx +3 -3
  49. package/docs/getting-started/nitro.mdx +2 -2
  50. package/docs/getting-started/nuxt.mdx +2 -2
  51. package/docs/getting-started/sveltekit.mdx +2 -2
  52. package/docs/getting-started/tanstack-start.mdx +1 -1
  53. package/docs/getting-started/vite.mdx +2 -2
  54. package/docs/how-it-works/cancellation.mdx +2 -2
  55. package/docs/how-it-works/code-transform.mdx +19 -15
  56. package/docs/how-it-works/encryption.mdx +3 -3
  57. package/docs/how-it-works/event-sourcing.mdx +6 -6
  58. package/docs/how-it-works/framework-integrations.mdx +96 -342
  59. package/docs/meta.json +1 -1
  60. package/package.json +14 -12
  61. package/docs/deploying/building-a-world.mdx +0 -251
  62. package/docs/deploying/meta.json +0 -4
  63. package/docs/deploying/world/local-world.mdx +0 -105
  64. package/docs/deploying/world/meta.json +0 -4
  65. package/docs/deploying/world/postgres-world.mdx +0 -288
  66. package/docs/deploying/world/vercel-world.mdx +0 -270
  67. package/docs/migration-guides/index.mdx +0 -34
  68. package/docs/migration-guides/meta.json +0 -9
  69. package/docs/migration-guides/migrating-from-aws-step-functions.mdx +0 -362
  70. package/docs/migration-guides/migrating-from-inngest.mdx +0 -308
  71. package/docs/migration-guides/migrating-from-temporal.mdx +0 -317
  72. package/docs/migration-guides/migrating-from-trigger-dev.mdx +0 -332
@@ -176,12 +176,12 @@ The step's `ops` array is awaited via `waitUntil(Promise.all(ops))` after the st
176
176
 
177
177
  ### Abort Errors Are Wrapped in FatalError
178
178
 
179
- When a step throws due to an abort — whether from `fetch` throwing `AbortError`, `signal.throwIfAborted()`, or any other abort-induced error — the step handler wraps the error in `FatalError` before recording it in the event log. This ensures:
179
+ When a step throws due to an abort — whether from `fetch` throwing `AbortError`, `signal.throwIfAborted()`, or any other abort-induced error — the step executor wraps the error in `FatalError` before recording it in the event log. This ensures:
180
180
 
181
181
  - **No retries**: An abort is intentional cancellation, not a transient failure. Retrying would just abort again.
182
182
  - **Immediate propagation**: The error bubbles up to the workflow as a `FatalError`, which the workflow can catch with `FatalError.is(err)`.
183
183
 
184
- The wrapping happens at the step handler level (`runtime/step-handler.ts`), during error hydration. When the step's thrown error is an `AbortError` (checked via `err.name === 'AbortError'`), it is treated as fatal regardless of the step's `maxRetries` configuration.
184
+ The wrapping happens in `runtime/step-executor.ts` during error hydration. When the step's thrown error is an `AbortError` (checked via `err.name === 'AbortError'`), it is treated as fatal regardless of the step's `maxRetries` configuration.
185
185
 
186
186
  ### abort() in the Workflow
187
187
 
@@ -53,18 +53,20 @@ flowchart LR
53
53
  A["Source Code<br/>with directives"] --> B["Step Mode"]
54
54
  A --> C["Workflow Mode"]
55
55
  A --> D["Client Mode"]
56
- B --> E["step.js<br/>(Step Execution)"]
57
- C --> F["flow.js<br/>(Workflow Execution)"]
56
+ B --> E["Step registration bundle"]
57
+ C --> F["Workflow bundle"]
58
+ E --> H["Combined flow handler"]
59
+ F --> H
58
60
  D --> G["Your App Code<br/>(Enables `start`)"]
59
61
  ```
60
62
 
61
63
  ### Comparison Table
62
64
 
63
- | Mode | Used In | Purpose | Output API Route | Required? |
64
- |----------|------------|--------------------------------|------------------------------------|-----------|
65
- | Step | Build time | Bundles step handlers | `.well-known/workflow/v1/step` | Yes |
66
- | Workflow | Build time | Bundles workflow orchestrators | `.well-known/workflow/v1/flow` | Yes |
67
- | Client | Build/Runtime | Provides workflow IDs and types to `start` | Your application code | Optional* |
65
+ | Mode | Used In | Purpose | Runtime role | Required? |
66
+ |----------|------------|--------------------------------|--------------|-----------|
67
+ | Step | Build time | Registers executable step functions | Imported by the combined flow handler | Yes |
68
+ | Workflow | Build time | Bundles workflow orchestrators | Executed by `.well-known/workflow/v1/flow` | Yes |
69
+ | Client | Build/Runtime | Provides workflow IDs and types to `start` | Your application code | Optional* |
68
70
 
69
71
  \* Client mode is **recommended** for better developer experience—it provides automatic ID generation and type safety. Without it, you must manually construct workflow IDs or use the build manifest.
70
72
 
@@ -73,7 +75,7 @@ flowchart LR
73
75
  <Tabs items={["Step Mode", "Workflow Mode", "Client Mode"]}>
74
76
  <Tab value="Step Mode">
75
77
 
76
- **Step Mode** creates the step execution bundle served at `/.well-known/workflow/v1/step`.
78
+ **Step Mode** creates a registration bundle that the combined flow handler imports. It is not an HTTP route.
77
79
 
78
80
  **Input:**
79
81
 
@@ -211,7 +213,7 @@ The IDs are generated exactly like in workflow mode to ensure they can be direct
211
213
 
212
214
  ## Generated Files
213
215
 
214
- When you build your application, the Workflow SDK generates three handler files in `.well-known/workflow/v1/`:
216
+ When you build your application, the Workflow SDK generates a combined flow handler, an internal step registration bundle, and a webhook handler. Exact filenames vary by framework.
215
217
 
216
218
  ### `flow.js`
217
219
 
@@ -245,15 +247,17 @@ Most invalid patterns cause **build-time errors**, catching issues before deploy
245
247
  **Why a VM?** Workflow functions must be deterministic to support replay. The VM sandbox prevents accidental use of non-deterministic APIs or side effects. All side effects should be performed in [step functions](/docs/foundations/workflows-and-steps#step-functions) instead.
246
248
  </Callout>
247
249
 
248
- ### `step.js`
250
+ ### `__step_registrations.js`
249
251
 
250
- Contains all step functions transformed in **step mode**. This file is imported by your framework to handle step execution requests at `POST /.well-known/workflow/v1/step`.
252
+ Contains all step functions transformed in **step mode**. The combined flow handler imports this module for its registration side effects.
251
253
 
252
254
  **What it does:**
253
255
 
254
- - Exports a `POST` handler that accepts Web standard `Request` objects
255
- - Executes individual steps with full runtime access
256
- - Returns step results to the orchestration layer
256
+ - Adds step functions to the runtime step registry
257
+ - Keeps step bodies in the full host runtime
258
+ - Makes registered steps available when a flow queue message includes `stepId` and `stepName`
259
+
260
+ This module must not be exposed as an HTTP endpoint.
257
261
 
258
262
  ### `webhook.js`
259
263
 
@@ -336,7 +340,7 @@ These transformations are framework-agnostic—they output standard JavaScript t
336
340
 
337
341
  If you need to debug transformation issues, you can inspect the generated files:
338
342
 
339
- 1. **Look in `.well-known/workflow/v1/`**: Check the generated `flow.js`, `step.js`,`webhook.js`, and other emitted debug files.
343
+ 1. **Inspect the generated output**: Check the combined flow handler, step registration bundle, webhook handler, and emitted debug files.
340
344
  2. **Check build logs**: Most frameworks log transformation activity during builds
341
345
  3. **Verify directives**: Ensure `"use workflow"` and `"use step"` are the first statements in functions
342
346
  4. **Check file locations**: Transformations only apply to files in configured source directories
@@ -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