workflow 5.0.0-beta.4 → 5.0.0-beta.40
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/README.md +63 -20
- package/dist/api-workflow.d.ts +1 -1
- package/dist/api-workflow.d.ts.map +1 -1
- package/dist/api-workflow.js +1 -1
- package/dist/api.d.ts +5 -1
- package/dist/api.d.ts.map +1 -1
- package/dist/api.js +12 -2
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -1
- package/dist/internal/builtins.d.ts +17 -0
- package/dist/internal/builtins.d.ts.map +1 -1
- package/dist/internal/builtins.js +65 -1
- package/dist/internal/errors.d.ts +1 -1
- package/dist/internal/errors.d.ts.map +1 -1
- package/dist/internal/errors.js +2 -2
- package/dist/nest-builder.d.ts +2 -0
- package/dist/nest-builder.d.ts.map +1 -0
- package/dist/nest-builder.js +2 -0
- package/dist/nest-vercel-builder.d.ts +2 -0
- package/dist/nest-vercel-builder.d.ts.map +1 -0
- package/dist/nest-vercel-builder.js +2 -0
- package/dist/observability.d.ts +1 -1
- package/dist/observability.js +2 -2
- package/dist/runtime.d.ts +2 -1
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +5 -2
- package/docs/ai/chat-session-modeling.mdx +7 -3
- package/docs/ai/defining-tools.mdx +2 -2
- package/docs/ai/index.mdx +30 -25
- package/docs/ai/message-queueing.mdx +10 -10
- package/docs/ai/resumable-streams.mdx +9 -1
- package/docs/api-reference/index.mdx +24 -0
- package/docs/api-reference/meta.json +8 -0
- package/docs/api-reference/vitest/index.mdx +28 -7
- package/docs/api-reference/workflow/create-hook.mdx +79 -0
- package/docs/api-reference/workflow/create-webhook.mdx +1 -0
- package/docs/api-reference/workflow/define-hook.mdx +26 -24
- package/docs/api-reference/workflow/fatal-error.mdx +29 -7
- package/docs/api-reference/workflow/fetch.mdx +8 -4
- package/docs/api-reference/workflow/index.mdx +3 -0
- package/docs/api-reference/workflow/set-attributes.mdx +61 -0
- package/docs/api-reference/workflow/sleep.mdx +1 -1
- package/docs/api-reference/workflow-ai/durable-agent.mdx +7 -45
- package/docs/api-reference/workflow-ai/index.mdx +2 -2
- package/docs/api-reference/workflow-ai/workflow-chat-transport.mdx +44 -1
- package/docs/api-reference/workflow-api/get-hook-by-token.mdx +9 -0
- package/docs/api-reference/workflow-api/get-run.mdx +25 -0
- package/docs/api-reference/workflow-api/index.mdx +6 -8
- package/docs/api-reference/workflow-api/resume-hook.mdx +60 -1
- package/docs/api-reference/workflow-api/resume-webhook.mdx +6 -4
- package/docs/api-reference/workflow-api/start.mdx +39 -6
- package/docs/api-reference/workflow-astro/index.mdx +18 -0
- package/docs/api-reference/workflow-astro/meta.json +4 -0
- package/docs/api-reference/workflow-astro/workflow.mdx +45 -0
- package/docs/api-reference/workflow-errors/hook-conflict-error.mdx +60 -0
- package/docs/api-reference/workflow-errors/index.mdx +88 -0
- package/docs/api-reference/workflow-errors/meta.json +6 -0
- package/docs/api-reference/workflow-errors/precondition-failed-error.mdx +68 -0
- package/docs/api-reference/workflow-errors/run-not-supported-error.mdx +58 -0
- package/docs/api-reference/workflow-errors/workflow-error.mdx +52 -0
- package/docs/api-reference/workflow-errors/workflow-run-failed-error.mdx +16 -6
- package/docs/api-reference/workflow-errors/workflow-run-not-completed-error.mdx +58 -0
- package/docs/api-reference/workflow-errors/workflow-runtime-error.mdx +58 -0
- package/docs/api-reference/workflow-globals.mdx +4 -1
- package/docs/api-reference/workflow-nest/configure-workflow-controller.mdx +33 -0
- package/docs/api-reference/workflow-nest/index.mdx +31 -0
- package/docs/api-reference/workflow-nest/meta.json +9 -0
- package/docs/api-reference/workflow-nest/nest-local-builder.mdx +64 -0
- package/docs/api-reference/workflow-nest/workflow-controller.mdx +40 -0
- package/docs/api-reference/workflow-nest/workflow-module.mdx +74 -0
- package/docs/api-reference/workflow-next/with-workflow.mdx +56 -2
- package/docs/api-reference/workflow-nitro/index.mdx +60 -0
- package/docs/api-reference/workflow-nuxt/index.mdx +48 -0
- package/docs/api-reference/workflow-observability/hydrate-data.mdx +35 -0
- package/docs/api-reference/workflow-observability/hydrate-resource-io.mdx +62 -0
- package/docs/api-reference/workflow-observability/index.mdx +64 -0
- package/docs/api-reference/workflow-observability/meta.json +11 -0
- package/docs/api-reference/workflow-observability/observability-revivers.mdx +50 -0
- package/docs/api-reference/workflow-observability/parse-class-name.mdx +41 -0
- package/docs/api-reference/workflow-observability/parse-step-name.mdx +40 -0
- package/docs/api-reference/workflow-observability/parse-workflow-name.mdx +55 -0
- package/docs/api-reference/workflow-runtime/create-world.mdx +39 -0
- package/docs/api-reference/workflow-runtime/get-world-handlers.mdx +44 -0
- package/docs/api-reference/{workflow-api → workflow-runtime}/get-world.mdx +7 -10
- package/docs/api-reference/workflow-runtime/health-check.mdx +50 -0
- package/docs/api-reference/workflow-runtime/index.mdx +43 -0
- package/docs/api-reference/workflow-runtime/meta.json +12 -0
- package/docs/api-reference/workflow-runtime/set-world.mdx +49 -0
- package/docs/api-reference/workflow-runtime/workflow-entrypoint.mdx +42 -0
- package/docs/api-reference/workflow-runtime/world/analytics.mdx +138 -0
- package/docs/api-reference/{workflow-api → workflow-runtime}/world/index.mdx +10 -10
- package/docs/api-reference/workflow-runtime/world/meta.json +4 -0
- package/docs/api-reference/{workflow-api → workflow-runtime}/world/queue.mdx +8 -6
- package/docs/api-reference/{workflow-api → workflow-runtime}/world/storage.mdx +18 -5
- package/docs/api-reference/{workflow-api → workflow-runtime}/world/streams.mdx +2 -2
- package/docs/api-reference/workflow-serde/index.mdx +0 -1
- package/docs/api-reference/workflow-serde/workflow-deserialize.mdx +1 -2
- package/docs/api-reference/workflow-serde/workflow-serialize.mdx +2 -2
- package/docs/api-reference/workflow-sveltekit/index.mdx +18 -0
- package/docs/api-reference/workflow-sveltekit/meta.json +4 -0
- package/docs/api-reference/workflow-sveltekit/workflow-plugin.mdx +42 -0
- package/docs/api-reference/workflow-vite/index.mdx +18 -0
- package/docs/api-reference/workflow-vite/meta.json +4 -0
- package/docs/api-reference/workflow-vite/workflow.mdx +48 -0
- package/docs/changelog/attributes-mvp.mdx +380 -0
- package/docs/changelog/eager-processing.mdx +269 -0
- package/docs/changelog/index.mdx +3 -1
- package/docs/changelog/lazy-event-creation.md +127 -0
- package/docs/changelog/meta.json +9 -1
- package/docs/changelog/resilient-resume.mdx +22 -0
- package/docs/changelog/resilient-start.mdx +31 -283
- package/docs/changelog/step-message-ownership.mdx +360 -0
- package/docs/changelog/turbo-mode.md +87 -0
- package/docs/comparisons/index.mdx +66 -0
- package/docs/comparisons/meta.json +11 -0
- package/docs/comparisons/workflow-sdk-vs-aws-agentcore.mdx +55 -0
- package/docs/comparisons/workflow-sdk-vs-aws-step-functions.mdx +111 -0
- package/docs/comparisons/workflow-sdk-vs-cloudflare-workflows.mdx +71 -0
- package/docs/comparisons/workflow-sdk-vs-inngest.mdx +102 -0
- package/docs/comparisons/workflow-sdk-vs-temporal.mdx +123 -0
- package/docs/comparisons/workflow-sdk-vs-trigger-dev.mdx +103 -0
- package/docs/configuration/build-and-diagnostics.mdx +70 -0
- package/docs/configuration/cli-and-web-ui.mdx +182 -0
- package/docs/configuration/framework-options.mdx +165 -0
- package/docs/configuration/index.mdx +32 -0
- package/docs/configuration/meta.json +12 -0
- package/docs/configuration/runtime-tuning.mdx +276 -0
- package/docs/configuration/worlds.mdx +275 -0
- package/docs/cookbook/advanced/child-workflows.mdx +203 -256
- package/docs/cookbook/advanced/meta.json +1 -1
- package/docs/cookbook/advanced/publishing-libraries.mdx +33 -24
- package/docs/cookbook/advanced/serializable-steps.mdx +12 -4
- package/docs/cookbook/advanced/upgrading-workflows.mdx +199 -0
- package/docs/cookbook/agent-patterns/agent-cancellation.mdx +34 -75
- package/docs/cookbook/agent-patterns/durable-agent.mdx +14 -142
- package/docs/cookbook/agent-patterns/human-in-the-loop.mdx +11 -3
- package/docs/cookbook/common-patterns/batching.mdx +4 -0
- package/docs/cookbook/common-patterns/idempotency.mdx +40 -52
- package/docs/cookbook/common-patterns/rate-limiting.mdx +5 -1
- package/docs/cookbook/common-patterns/saga.mdx +6 -2
- package/docs/cookbook/common-patterns/scheduling.mdx +12 -0
- package/docs/cookbook/common-patterns/sequential-and-parallel.mdx +4 -0
- package/docs/cookbook/common-patterns/timeouts.mdx +6 -1
- package/docs/cookbook/common-patterns/webhooks.mdx +4 -0
- package/docs/cookbook/common-patterns/workflow-composition.mdx +19 -16
- package/docs/cookbook/index.mdx +3 -3
- package/docs/cookbook/integrations/ai-sdk.mdx +64 -28
- package/docs/cookbook/integrations/chat-sdk.mdx +17 -0
- package/docs/cookbook/integrations/sandbox.mdx +17 -0
- package/docs/{deploying/index.mdx → deploying.mdx} +7 -7
- package/docs/errors/abort-signal-timeout-in-workflow.mdx +84 -0
- package/docs/errors/corrupted-event-log.mdx +5 -5
- package/docs/errors/deployment-mismatch.mdx +71 -0
- package/docs/errors/fetch-in-workflow.mdx +4 -0
- package/docs/errors/hook-conflict.mdx +60 -4
- package/docs/errors/index.mdx +1 -35
- package/docs/errors/node-js-module-in-workflow.mdx +4 -0
- package/docs/errors/replay-divergence.mdx +27 -0
- package/docs/errors/runtime-decryption-failed.mdx +77 -0
- package/docs/errors/serialization-failed.mdx +4 -0
- package/docs/errors/start-invalid-workflow-function.mdx +4 -0
- package/docs/errors/step-executed-multiple-times.mdx +23 -0
- package/docs/errors/step-not-registered.mdx +1 -1
- package/docs/errors/timeout-in-workflow.mdx +4 -0
- package/docs/errors/webhook-response-not-sent.mdx +4 -0
- package/docs/foundations/cancellation.mdx +459 -0
- package/docs/foundations/errors-and-retries.mdx +7 -3
- package/docs/foundations/hooks.mdx +29 -0
- package/docs/foundations/idempotency.mdx +243 -11
- package/docs/foundations/index.mdx +1 -23
- package/docs/foundations/meta.json +3 -1
- package/docs/foundations/serialization.mdx +77 -41
- package/docs/foundations/starting-workflows.mdx +79 -2
- package/docs/foundations/streaming.mdx +14 -23
- package/docs/foundations/versioning.mdx +263 -0
- package/docs/getting-started/astro.mdx +12 -2
- package/docs/getting-started/express.mdx +6 -2
- package/docs/getting-started/fastify.mdx +6 -2
- package/docs/getting-started/hono.mdx +6 -2
- package/docs/getting-started/index.mdx +16 -10
- package/docs/getting-started/meta.json +4 -1
- package/docs/getting-started/nestjs.mdx +77 -3
- package/docs/getting-started/next.mdx +12 -6
- package/docs/getting-started/nitro.mdx +28 -2
- package/docs/getting-started/nuxt.mdx +6 -2
- package/docs/getting-started/python.mdx +24 -18
- package/docs/getting-started/react-router/index.mdx +33 -0
- package/docs/getting-started/react-router/meta.json +5 -0
- package/docs/getting-started/react-router/v7.mdx +237 -0
- package/docs/getting-started/react-router/v8.mdx +232 -0
- package/docs/getting-started/sveltekit.mdx +12 -2
- package/docs/getting-started/tanstack-start.mdx +245 -0
- package/docs/getting-started/vite.mdx +6 -2
- package/docs/how-it-works/cancellation.mdx +287 -0
- package/docs/how-it-works/code-transform.mdx +21 -17
- package/docs/how-it-works/encryption.mdx +5 -5
- package/docs/how-it-works/event-sourcing.mdx +6 -6
- package/docs/how-it-works/framework-integrations.mdx +96 -337
- package/docs/how-it-works/meta.json +2 -1
- package/docs/internal/index.mdx +21 -0
- package/docs/internal/meta.json +10 -0
- package/docs/internal/nitro-native-build.mdx +38 -0
- package/docs/internal/nitro-web-ui.mdx +24 -0
- package/docs/internal/serializable-abort-controller.mdx +148 -0
- package/docs/meta.json +2 -2
- package/docs/observability/attributes.mdx +112 -0
- package/docs/observability/index.mdx +20 -1
- package/docs/observability/meta.json +1 -1
- package/docs/observability/tracing.mdx +124 -0
- package/docs/testing/index.mdx +2 -2
- package/package.json +17 -13
- package/docs/api-reference/workflow-api/world/meta.json +0 -4
- package/docs/api-reference/workflow-api/world/observability.mdx +0 -164
- package/docs/cookbook/advanced/distributed-abort-controller.mdx +0 -318
- package/docs/deploying/building-a-world.mdx +0 -251
- package/docs/deploying/meta.json +0 -4
- package/docs/deploying/world/local-world.mdx +0 -84
- package/docs/deploying/world/meta.json +0 -4
- package/docs/deploying/world/postgres-world.mdx +0 -222
- package/docs/deploying/world/vercel-world.mdx +0 -179
- package/docs/migration-guides/index.mdx +0 -34
- package/docs/migration-guides/meta.json +0 -9
- package/docs/migration-guides/migrating-from-aws-step-functions.mdx +0 -363
- package/docs/migration-guides/migrating-from-inngest.mdx +0 -314
- package/docs/migration-guides/migrating-from-temporal.mdx +0 -318
- package/docs/migration-guides/migrating-from-trigger-dev.mdx +0 -337
|
@@ -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.
|
|
@@ -9,6 +9,10 @@ related:
|
|
|
9
9
|
- /docs/foundations/workflows-and-steps
|
|
10
10
|
---
|
|
11
11
|
|
|
12
|
+
<CopyPrompt
|
|
13
|
+
text="In this SvelteKit app, run `npm i workflow`. In `vite.config.ts`, import `workflowPlugin` from `workflow/sveltekit` and add it to `plugins` with `sveltekit()`. Add the TypeScript plugin `{ "name": "workflow" }` to `tsconfig.json` if TypeScript is used. Create `workflows/user-signup.ts` exporting `handleUserSignup(email)` with `"use workflow"`, `sleep` from `workflow`, and `"use step"` helpers that create a user and send emails. Add `src/routes/api/signup/+server.ts` with a POST `RequestHandler` that reads `{ email }`, calls `start(handleUserSignup, [email])` from `workflow/api`, and returns `json({ message: "User signup workflow started" })`. Run `npm run dev`, call `curl -X POST --json '{"email":"hello@example.com"}' http://localhost:5173/api/signup`, then inspect with `npx workflow web` or `npx workflow inspect runs`."
|
|
14
|
+
/>
|
|
15
|
+
|
|
12
16
|
<Steps>
|
|
13
17
|
|
|
14
18
|
<Step>
|
|
@@ -46,6 +50,12 @@ export default defineConfig({
|
|
|
46
50
|
});
|
|
47
51
|
```
|
|
48
52
|
|
|
53
|
+
`workflowPlugin()` accepts an options object:
|
|
54
|
+
|
|
55
|
+
| Option | Type | Default | Description |
|
|
56
|
+
| --- | --- | --- | --- |
|
|
57
|
+
| `sourcemap` | `boolean \| 'inline' \| 'linked' \| 'external' \| 'both'` | `'inline'` (dev) / `false` (prod) | Controls source maps on generated workflow bundles. Accepts the same values as esbuild's `sourcemap` option. Defaults to `'inline'` in development and `false` in production (smaller function bundles — helps stay under the Vercel 250MB function size limit). Set it explicitly, or use the `WORKFLOW_SOURCEMAP` environment variable, to override in either environment. |
|
|
58
|
+
|
|
49
59
|
<Accordion type="single" collapsible>
|
|
50
60
|
<AccordionItem value="typescript-intellisense" className="[&_h3]:my-0">
|
|
51
61
|
<AccordionTrigger className="text-sm">
|
|
@@ -147,7 +157,7 @@ async function sendOnboardingEmail(user: { id: string; email: string}) {
|
|
|
147
157
|
|
|
148
158
|
Taking a look at this code:
|
|
149
159
|
|
|
150
|
-
* Business logic lives inside **steps**. When a
|
|
160
|
+
* Business logic lives inside **steps**. When a workflow invokes a step, the workflow suspends while the step runs with full Node.js access. The combined handler may execute it inline; queued retries and continuations return through the same flow route.
|
|
151
161
|
* If a step throws an error, like in `sendWelcomeEmail`, the step will automatically be retried until it succeeds (or hits the step's max retry count).
|
|
152
162
|
* Steps can throw a `FatalError` if an error is intentional and should not be retried.
|
|
153
163
|
|
|
@@ -235,7 +245,7 @@ Check the [Deploying](/docs/deploying) section to learn how your workflows can b
|
|
|
235
245
|
If you see this error:
|
|
236
246
|
|
|
237
247
|
```
|
|
238
|
-
'start' received an invalid workflow function. Ensure the Workflow
|
|
248
|
+
'start' received an invalid workflow function. Ensure the Workflow SDK is configured correctly and the function includes a 'use workflow' directive.
|
|
239
249
|
```
|
|
240
250
|
|
|
241
251
|
Check both of these first:
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: TanStack Start
|
|
3
|
+
description: Set up your first durable workflow in a TanStack Start application.
|
|
4
|
+
type: guide
|
|
5
|
+
summary: Set up Workflow SDK in a TanStack Start app.
|
|
6
|
+
prerequisites:
|
|
7
|
+
- /docs/getting-started
|
|
8
|
+
related:
|
|
9
|
+
- /docs/foundations/workflows-and-steps
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
<CopyPrompt
|
|
13
|
+
text="In this TanStack Start app, run `npm i workflow`. In `vite.config.ts`, import `workflow` from `workflow/vite` and add `workflow()` first in the existing `plugins` array before `tanstackStart()`, `nitro()`, or other plugins. Add `{ "name": "workflow" }` to `compilerOptions.plugins` in `tsconfig.json` if TypeScript is used. Create `src/workflows/user-signup.ts` with `handleUserSignup(email)`, `"use workflow"`, `sleep`, and `"use step"` helpers. Add `src/routes/api/signup.ts` using `createFileRoute("/api/signup")`, a POST server handler, `start` from `workflow/api`, and `json` from `@tanstack/react-start`. Run `npm run dev`, call `curl -X POST --json '{"email":"hello@example.com"}' http://localhost:3000/api/signup`, and inspect with `npx workflow web` or `npx workflow inspect runs`."
|
|
14
|
+
/>
|
|
15
|
+
|
|
16
|
+
This guide will walk through setting up your first workflow in a TanStack Start app. Along the way, you'll learn more about the concepts that are fundamental to using the Workflow SDK in your own projects.
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
<Steps>
|
|
21
|
+
|
|
22
|
+
<Step>
|
|
23
|
+
## Create Your TanStack Start Project
|
|
24
|
+
|
|
25
|
+
Start by creating a new TanStack Start project:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
npx @tanstack/cli create my-workflow-app
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Enter the newly made directory:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
cd my-workflow-app
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### Install `workflow`
|
|
38
|
+
|
|
39
|
+
```package-install
|
|
40
|
+
npm i workflow
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### Configure TanStack Start
|
|
44
|
+
|
|
45
|
+
TanStack Start runs on Vite, so the Workflow SDK is wired in via the same `workflow/vite` plugin. Add `workflow()` to the existing `plugins` array in your Vite config — list it first so the `"use workflow"` and `"use step"` transforms run before any other plugin processes the file.
|
|
46
|
+
|
|
47
|
+
```typescript title="vite.config.ts" lineNumbers
|
|
48
|
+
import { defineConfig } from "vite";
|
|
49
|
+
import { workflow } from "workflow/vite";
|
|
50
|
+
// ...
|
|
51
|
+
|
|
52
|
+
export default defineConfig({
|
|
53
|
+
plugins: [
|
|
54
|
+
workflow(), // [!code highlight]
|
|
55
|
+
// ...the existing tanstackStart(), nitro(), and any other plugins
|
|
56
|
+
],
|
|
57
|
+
});
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
<Accordion type="single" collapsible>
|
|
61
|
+
<AccordionItem value="typescript-intellisense" className="[&_h3]:my-0">
|
|
62
|
+
<AccordionTrigger className="text-sm">
|
|
63
|
+
### Setup IntelliSense for TypeScript (Optional)
|
|
64
|
+
</AccordionTrigger>
|
|
65
|
+
<AccordionContent className="[&_p]:my-2">
|
|
66
|
+
|
|
67
|
+
To enable helpful hints in your IDE, setup the workflow plugin in `tsconfig.json`:
|
|
68
|
+
|
|
69
|
+
```json title="tsconfig.json" lineNumbers
|
|
70
|
+
{
|
|
71
|
+
"compilerOptions": {
|
|
72
|
+
// ... rest of your TypeScript config
|
|
73
|
+
"plugins": [
|
|
74
|
+
{
|
|
75
|
+
"name": "workflow" // [!code highlight]
|
|
76
|
+
}
|
|
77
|
+
]
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
</AccordionContent>
|
|
83
|
+
</AccordionItem>
|
|
84
|
+
</Accordion>
|
|
85
|
+
|
|
86
|
+
</Step>
|
|
87
|
+
|
|
88
|
+
<Step>
|
|
89
|
+
|
|
90
|
+
## Create Your First Workflow
|
|
91
|
+
|
|
92
|
+
Create a new file for our first workflow:
|
|
93
|
+
|
|
94
|
+
```typescript title="src/workflows/user-signup.ts" lineNumbers
|
|
95
|
+
import { sleep } from "workflow";
|
|
96
|
+
|
|
97
|
+
export async function handleUserSignup(email: string) {
|
|
98
|
+
"use workflow"; // [!code highlight]
|
|
99
|
+
|
|
100
|
+
const user = await createUser(email);
|
|
101
|
+
await sendWelcomeEmail(user);
|
|
102
|
+
|
|
103
|
+
await sleep("5s"); // Pause for 5s - doesn't consume any resources
|
|
104
|
+
await sendOnboardingEmail(user);
|
|
105
|
+
|
|
106
|
+
return { userId: user.id, status: "onboarded" };
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
We'll fill in those functions next, but let's take a look at this code:
|
|
111
|
+
|
|
112
|
+
* We define a **workflow** function with the directive `"use workflow"`. Think of the workflow function as the _orchestrator_ of individual **steps**.
|
|
113
|
+
* The Workflow SDK's `sleep` function allows us to suspend execution of the workflow without using up any resources. A sleep can be a few seconds, hours, days, or even months long.
|
|
114
|
+
|
|
115
|
+
## Create Your Workflow Steps
|
|
116
|
+
|
|
117
|
+
Let's now define those missing functions.
|
|
118
|
+
|
|
119
|
+
```typescript title="src/workflows/user-signup.ts" lineNumbers
|
|
120
|
+
import { FatalError } from "workflow"
|
|
121
|
+
|
|
122
|
+
// Our workflow function defined earlier
|
|
123
|
+
|
|
124
|
+
async function createUser(email: string) {
|
|
125
|
+
"use step"; // [!code highlight]
|
|
126
|
+
|
|
127
|
+
console.log(`Creating user with email: ${email}`);
|
|
128
|
+
|
|
129
|
+
// Full Node.js access - database calls, APIs, etc.
|
|
130
|
+
return { id: crypto.randomUUID(), email };
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
async function sendWelcomeEmail(user: { id: string; email: string; }) {
|
|
134
|
+
"use step"; // [!code highlight]
|
|
135
|
+
|
|
136
|
+
console.log(`Sending welcome email to user: ${user.id}`);
|
|
137
|
+
|
|
138
|
+
if (Math.random() < 0.3) {
|
|
139
|
+
// By default, steps will be retried for unhandled errors
|
|
140
|
+
throw new Error("Retryable!");
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
async function sendOnboardingEmail(user: { id: string; email: string}) {
|
|
145
|
+
"use step"; // [!code highlight]
|
|
146
|
+
|
|
147
|
+
if (!user.email.includes("@")) {
|
|
148
|
+
// To skip retrying, throw a FatalError instead
|
|
149
|
+
throw new FatalError("Invalid Email");
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
console.log(`Sending onboarding email to user: ${user.id}`);
|
|
153
|
+
}
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
Taking a look at this code:
|
|
157
|
+
|
|
158
|
+
* Business logic lives inside **steps**. When a workflow invokes a step, the workflow suspends while the step runs with full Node.js access. The combined handler may execute it inline; queued retries and continuations return through the same flow route.
|
|
159
|
+
* If a step throws an error, like in `sendWelcomeEmail`, the step will automatically be retried until it succeeds (or hits the step's max retry count).
|
|
160
|
+
* Steps can throw a `FatalError` if an error is intentional and should not be retried.
|
|
161
|
+
|
|
162
|
+
<Callout>
|
|
163
|
+
We'll dive deeper into workflows, steps, and other ways to suspend or handle events in [Foundations](/docs/foundations).
|
|
164
|
+
</Callout>
|
|
165
|
+
|
|
166
|
+
</Step>
|
|
167
|
+
|
|
168
|
+
<Step>
|
|
169
|
+
|
|
170
|
+
## Create Your Route Handler
|
|
171
|
+
|
|
172
|
+
To invoke your new workflow, add a server handler at `src/routes/api/signup.ts`:
|
|
173
|
+
|
|
174
|
+
```typescript title="src/routes/api/signup.ts"
|
|
175
|
+
import { createFileRoute } from "@tanstack/react-router";
|
|
176
|
+
import { json } from "@tanstack/react-start";
|
|
177
|
+
import { start } from "workflow/api";
|
|
178
|
+
import { handleUserSignup } from "../../workflows/user-signup";
|
|
179
|
+
|
|
180
|
+
export const Route = createFileRoute("/api/signup")({
|
|
181
|
+
server: {
|
|
182
|
+
handlers: {
|
|
183
|
+
POST: async ({ request }) => {
|
|
184
|
+
const { email } = await request.json();
|
|
185
|
+
// Executes asynchronously and doesn't block your app
|
|
186
|
+
await start(handleUserSignup, [email]);
|
|
187
|
+
return json({ message: "User signup workflow started" });
|
|
188
|
+
},
|
|
189
|
+
},
|
|
190
|
+
},
|
|
191
|
+
});
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
This route handler creates a `POST` request endpoint at `/api/signup` that will trigger your workflow.
|
|
195
|
+
|
|
196
|
+
<Callout>
|
|
197
|
+
Workflows can be triggered from API routes or any server-side code.
|
|
198
|
+
</Callout>
|
|
199
|
+
|
|
200
|
+
</Step>
|
|
201
|
+
|
|
202
|
+
</Steps>
|
|
203
|
+
|
|
204
|
+
## Run in development
|
|
205
|
+
|
|
206
|
+
To start your development server, run the following command in your terminal in the TanStack Start root directory:
|
|
207
|
+
|
|
208
|
+
```bash
|
|
209
|
+
npm run dev
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
Once your development server is running, you can trigger your workflow by running this command in the terminal:
|
|
213
|
+
|
|
214
|
+
```bash
|
|
215
|
+
curl -X POST --json '{"email":"hello@example.com"}' http://localhost:3000/api/signup
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
Check the dev server logs to see your workflow execute as well as the steps that are being processed.
|
|
219
|
+
|
|
220
|
+
Additionally, you can use the [Workflow SDK CLI or Web UI](/docs/observability) to inspect your workflow runs and steps in detail.
|
|
221
|
+
|
|
222
|
+
```bash
|
|
223
|
+
# Open the observability Web UI on http://localhost:3456
|
|
224
|
+
npx workflow web
|
|
225
|
+
# or if you prefer a terminal interface, use the CLI inspect command
|
|
226
|
+
npx workflow inspect runs
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+

|
|
230
|
+
|
|
231
|
+
---
|
|
232
|
+
|
|
233
|
+
## Deploying to production
|
|
234
|
+
|
|
235
|
+
Workflow SDK apps currently work best when deployed to [Vercel](https://vercel.com/home) and needs no special configuration.
|
|
236
|
+
|
|
237
|
+
<FluidComputeCallout />
|
|
238
|
+
|
|
239
|
+
Check the [Deploying](/docs/deploying) section to learn how your workflows can be deployed elsewhere.
|
|
240
|
+
|
|
241
|
+
## Next Steps
|
|
242
|
+
|
|
243
|
+
* Learn more about the [Foundations](/docs/foundations).
|
|
244
|
+
* Check [Errors](/docs/errors) if you encounter issues.
|
|
245
|
+
* Explore the [API Reference](/docs/api-reference).
|
|
@@ -9,6 +9,10 @@ related:
|
|
|
9
9
|
- /docs/foundations/workflows-and-steps
|
|
10
10
|
---
|
|
11
11
|
|
|
12
|
+
<CopyPrompt
|
|
13
|
+
text="In this Vite app, run `npm i workflow nitro`. In `vite.config.ts`, import `nitro` from `nitro/vite`, `workflow` from `workflow/vite`, and configure `plugins: [nitro(), workflow()]` plus `nitro: { serverDir: "./" }`. Add the TypeScript plugin `{ "name": "workflow" }` to `tsconfig.json` if TypeScript is used. Create `workflows/user-signup.ts` with `"use workflow"`, `sleep`, and `"use step"` helpers. Add `api/signup.post.ts` using `defineEventHandler` from `nitro/h3` and `start` from `workflow/api`. Run `npm run dev`, call `curl -X POST --json '{"email":"hello@example.com"}' http://localhost:3000/api/signup`, and inspect with `npx workflow web` or `npx workflow inspect runs`."
|
|
14
|
+
/>
|
|
15
|
+
|
|
12
16
|
This guide will walk through setting up your first workflow in a Vite app. Along the way, you'll learn more about the concepts that are fundamental to using the Workflow SDK in your own projects.
|
|
13
17
|
|
|
14
18
|
---
|
|
@@ -156,7 +160,7 @@ async function sendOnboardingEmail(user: { id: string; email: string}) {
|
|
|
156
160
|
|
|
157
161
|
Taking a look at this code:
|
|
158
162
|
|
|
159
|
-
* Business logic lives inside **steps**. When a
|
|
163
|
+
* Business logic lives inside **steps**. When a workflow invokes a step, the workflow suspends while the step runs with full Node.js access. The combined handler may execute it inline; queued retries and continuations return through the same flow route.
|
|
160
164
|
* If a step throws an error, like in `sendWelcomeEmail`, the step will automatically be retried until it succeeds (or hits the step's max retry count).
|
|
161
165
|
* Steps can throw a `FatalError` if an error is intentional and should not be retried.
|
|
162
166
|
|
|
@@ -241,7 +245,7 @@ Check the [Deploying](/docs/deploying) section to learn how your workflows can b
|
|
|
241
245
|
If you see this error:
|
|
242
246
|
|
|
243
247
|
```
|
|
244
|
-
'start' received an invalid workflow function. Ensure the Workflow
|
|
248
|
+
'start' received an invalid workflow function. Ensure the Workflow SDK is configured correctly and the function includes a 'use workflow' directive.
|
|
245
249
|
```
|
|
246
250
|
|
|
247
251
|
Check both of these first:
|