workflow 5.0.0-beta.4 → 5.0.0-beta.41
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 +24 -7
- 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 +281 -0
- package/docs/configuration/worlds.mdx +283 -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 +11 -8
- 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 +17 -9
- 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
|
@@ -345,29 +345,19 @@ export async function batchProcessingWorkflow(items: string[]) {
|
|
|
345
345
|
}
|
|
346
346
|
```
|
|
347
347
|
|
|
348
|
-
### Streaming AI Responses with `
|
|
348
|
+
### Streaming AI Responses with `WorkflowAgent`
|
|
349
349
|
|
|
350
|
-
Stream AI-generated content using [`
|
|
350
|
+
Stream AI-generated content using AI SDK's [`WorkflowAgent`](https://ai-sdk.dev/v7/docs/agents/workflow-agent#workflowagent) from `@ai-sdk/workflow`. The agent writes `ModelCallStreamPart` chunks to the workflow stream, and route handlers convert them to UI message chunks with `createModelCallToUIChunkTransform()` before returning the response:
|
|
351
351
|
|
|
352
352
|
```typescript title="workflows/ai-assistant.ts" lineNumbers
|
|
353
|
-
import {
|
|
353
|
+
import { WorkflowAgent, type ModelCallStreamPart } from "@ai-sdk/workflow";
|
|
354
|
+
import { tool } from "ai";
|
|
354
355
|
import { getWritable } from "workflow";
|
|
355
356
|
import { z } from "zod";
|
|
356
|
-
import type { UIMessageChunk } from "ai";
|
|
357
357
|
|
|
358
358
|
async function searchFlights({ query }: { query: string }) {
|
|
359
359
|
"use step";
|
|
360
360
|
|
|
361
|
-
// Tools can emit progress updates to the stream
|
|
362
|
-
const writable = getWritable<UIMessageChunk>(); // [!code highlight]
|
|
363
|
-
const writer = writable.getWriter(); // [!code highlight]
|
|
364
|
-
await writer.write({ // [!code highlight]
|
|
365
|
-
type: "data-progress", // [!code highlight]
|
|
366
|
-
data: { message: `Searching flights for ${query}...` }, // [!code highlight]
|
|
367
|
-
transient: true, // [!code highlight]
|
|
368
|
-
}); // [!code highlight]
|
|
369
|
-
writer.releaseLock(); // [!code highlight]
|
|
370
|
-
|
|
371
361
|
// ... search logic ...
|
|
372
362
|
return { flights: [/* results */] };
|
|
373
363
|
}
|
|
@@ -375,27 +365,28 @@ async function searchFlights({ query }: { query: string }) {
|
|
|
375
365
|
export async function aiAssistantWorkflow(userMessage: string) {
|
|
376
366
|
"use workflow";
|
|
377
367
|
|
|
378
|
-
const agent = new
|
|
368
|
+
const agent = new WorkflowAgent({
|
|
379
369
|
model: "anthropic/claude-haiku-4.5",
|
|
380
|
-
|
|
370
|
+
instructions: "You are a helpful flight assistant.",
|
|
381
371
|
tools: {
|
|
382
|
-
searchFlights: {
|
|
372
|
+
searchFlights: tool({
|
|
383
373
|
description: "Search for flights",
|
|
384
374
|
inputSchema: z.object({ query: z.string() }),
|
|
385
375
|
execute: searchFlights,
|
|
386
|
-
},
|
|
376
|
+
}),
|
|
387
377
|
},
|
|
388
378
|
});
|
|
389
379
|
|
|
390
380
|
// LLM response will be streamed to the run's writable
|
|
391
381
|
await agent.stream({
|
|
392
382
|
messages: [{ role: "user", content: userMessage }],
|
|
393
|
-
writable: getWritable<
|
|
383
|
+
writable: getWritable<ModelCallStreamPart>(), // [!code highlight]
|
|
394
384
|
});
|
|
395
385
|
}
|
|
396
386
|
```
|
|
397
387
|
|
|
398
388
|
```typescript title="app/api/ai-assistant/route.ts" lineNumbers
|
|
389
|
+
import { createModelCallToUIChunkTransform } from "@ai-sdk/workflow";
|
|
399
390
|
import { createUIMessageStreamResponse } from "ai";
|
|
400
391
|
import { start } from "workflow/api";
|
|
401
392
|
import { aiAssistantWorkflow } from "./workflows/ai";
|
|
@@ -406,13 +397,13 @@ export async function POST(request: Request) {
|
|
|
406
397
|
const run = await start(aiAssistantWorkflow, [message]);
|
|
407
398
|
|
|
408
399
|
return createUIMessageStreamResponse({
|
|
409
|
-
stream: run.readable,
|
|
400
|
+
stream: run.readable.pipeThrough(createModelCallToUIChunkTransform()), // [!code highlight]
|
|
410
401
|
});
|
|
411
402
|
}
|
|
412
403
|
```
|
|
413
404
|
|
|
414
405
|
<Callout type="info">
|
|
415
|
-
For
|
|
406
|
+
For the full agent API and migration notes, see the [`WorkflowAgent` documentation](https://ai-sdk.dev/v7/docs/agents/workflow-agent#workflowagent).
|
|
416
407
|
</Callout>
|
|
417
408
|
|
|
418
409
|
### Streaming Between Steps
|
|
@@ -593,8 +584,8 @@ Stream errors don't trigger automatic retries for the producer step. Design your
|
|
|
593
584
|
- [`sleep()` API Reference](/docs/api-reference/workflow/sleep) - Pause workflow execution for a duration
|
|
594
585
|
- [`start()` API Reference](/docs/api-reference/workflow-api/start) - Start workflows and access the `Run` object
|
|
595
586
|
- [`getRun()` API Reference](/docs/api-reference/workflow-api/get-run) - Retrieve runs and their streams later
|
|
596
|
-
- [world.streams](/docs/api-reference/workflow-
|
|
597
|
-
- [
|
|
587
|
+
- [world.streams](/docs/api-reference/workflow-runtime/world/streams) - Low-level stream read/write/close via World SDK
|
|
588
|
+
- [WorkflowAgent](https://ai-sdk.dev/v7/docs/agents/workflow-agent#workflowagent) - AI agents with durable, resumable streaming support
|
|
598
589
|
- [Errors and Retries](/docs/foundations/errors-and-retries) - Understanding error handling and retry behavior
|
|
599
590
|
- [Serialization](/docs/foundations/serialization) - Understanding what data types can be passed in workflows
|
|
600
591
|
- [Workflows and Steps](/docs/foundations/workflows-and-steps) - Core concepts of workflow execution
|
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Versioning
|
|
3
|
+
description: Understand how workflow runs are pinned to deployments, how to recover runs after a fix, and how to opt in to newer code explicitly.
|
|
4
|
+
type: guide
|
|
5
|
+
summary: Keep in-flight runs stable by default, then choose explicit upgrade boundaries when you need them.
|
|
6
|
+
prerequisites:
|
|
7
|
+
- /docs/foundations/starting-workflows
|
|
8
|
+
related:
|
|
9
|
+
- /docs/api-reference/workflow-api/start
|
|
10
|
+
- /docs/foundations/cancellation
|
|
11
|
+
- /cookbook/common-patterns/workflow-composition
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
Workflow runs are pinned to the deployment that starts them. When a run begins, Workflow SDK records the deployment for that run and continues executing the run on that same copy of your code.
|
|
15
|
+
|
|
16
|
+
That default is intentional. Durable workflows can pause for minutes, days, or months. If the code underneath a paused run changed every time you deployed, an in-flight run could resume into a different function body, different step names, or different input types than the ones it started with. That can make type safety fragile and can break long-running work in hard-to-debug ways.
|
|
17
|
+
|
|
18
|
+
With Workflow SDK, you can keep shipping. New runs use new deployments, while existing runs keep the version they already understand.
|
|
19
|
+
|
|
20
|
+
## Default behavior
|
|
21
|
+
|
|
22
|
+
Start a workflow normally:
|
|
23
|
+
|
|
24
|
+
```typescript title="app/api/orders/route.ts" lineNumbers
|
|
25
|
+
import { start } from "workflow/api";
|
|
26
|
+
import { fulfillOrder } from "@/workflows/fulfill-order";
|
|
27
|
+
|
|
28
|
+
export async function POST(request: Request) {
|
|
29
|
+
const { orderId } = await request.json();
|
|
30
|
+
|
|
31
|
+
const run = await start(fulfillOrder, [orderId]); // [!code highlight]
|
|
32
|
+
|
|
33
|
+
return Response.json({ runId: run.runId });
|
|
34
|
+
}
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
The run is tied to the deployment that handled this request. If you deploy a new version while the workflow is [sleeping](/docs/api-reference/workflow/sleep), [waiting on a hook](/docs/foundations/hooks), [retrying a step](/docs/foundations/errors-and-retries), or processing later queue messages, that existing run still resumes on the original deployment.
|
|
38
|
+
|
|
39
|
+
```typescript title="workflows/fulfill-order.ts" lineNumbers
|
|
40
|
+
import { sleep } from "workflow";
|
|
41
|
+
|
|
42
|
+
export async function fulfillOrder(orderId: string) {
|
|
43
|
+
"use workflow";
|
|
44
|
+
|
|
45
|
+
await reserveInventory(orderId);
|
|
46
|
+
await sleep("2d");
|
|
47
|
+
await chargeCustomer(orderId);
|
|
48
|
+
await shipOrder(orderId);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
async function reserveInventory(orderId: string) {
|
|
52
|
+
"use step";
|
|
53
|
+
// ...
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
async function chargeCustomer(orderId: string) {
|
|
57
|
+
"use step";
|
|
58
|
+
// ...
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
async function shipOrder(orderId: string) {
|
|
62
|
+
"use step";
|
|
63
|
+
// ...
|
|
64
|
+
}
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
If you deploy a change to `chargeCustomer()` while a run is in the two-day sleep, the existing run does not suddenly resume into the new implementation. It continues on the deployment it started on. The next order starts on the latest deployment and uses the new code from the beginning.
|
|
68
|
+
|
|
69
|
+
## Fixing in-flight runs
|
|
70
|
+
|
|
71
|
+
Sometimes you deploy because the old code had a bug. The safest fix is usually explicit:
|
|
72
|
+
|
|
73
|
+
1. Deploy the fixed code.
|
|
74
|
+
2. Find the affected runs in [observability](/docs/observability) or with the CLI.
|
|
75
|
+
3. Cancel the old runs if they are still running.
|
|
76
|
+
4. Rerun them on the latest deployment with the same inputs.
|
|
77
|
+
|
|
78
|
+
This keeps the version boundary visible. The old run ends as cancelled or failed, and the replacement run starts fresh on the fixed deployment. This is a good fit for one-off, ad-hoc upgrades where you explicitly opt in to moving affected runs onto a new version.
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
# Inspect affected runs and copy the exact workflowName value.
|
|
82
|
+
npx workflow inspect runs \
|
|
83
|
+
--backend vercel \
|
|
84
|
+
--status running
|
|
85
|
+
|
|
86
|
+
# Cancel one run.
|
|
87
|
+
npx workflow cancel <run-id> \
|
|
88
|
+
--backend vercel
|
|
89
|
+
|
|
90
|
+
# Or bulk-cancel matching running runs.
|
|
91
|
+
npx workflow cancel \
|
|
92
|
+
--status running \
|
|
93
|
+
--workflowName "workflow//./workflows/fulfill-order//fulfillOrder" \
|
|
94
|
+
--backend vercel
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
The `--workflowName` filter expects the generated workflow ID, not only the exported function's short name. Use the `workflowName` value from `workflow inspect runs`, and use [`parseWorkflowName()`](/docs/api-reference/workflow-observability/parse-workflow-name) when you need display-friendly names.
|
|
98
|
+
|
|
99
|
+
In the [observability UI](/docs/observability), use **Rerun on latest** to enqueue the workflow again with the same inputs against the latest deployment.
|
|
100
|
+
|
|
101
|
+
If you are writing your own recovery route, call `start()` with the same arguments and `deploymentId: "latest"`:
|
|
102
|
+
|
|
103
|
+
```typescript title="app/api/orders/rerun/route.ts" lineNumbers
|
|
104
|
+
import { start } from "workflow/api";
|
|
105
|
+
import { fulfillOrder } from "@/workflows/fulfill-order";
|
|
106
|
+
|
|
107
|
+
export async function POST(request: Request) {
|
|
108
|
+
const { orderId } = await request.json();
|
|
109
|
+
|
|
110
|
+
const run = await start(fulfillOrder, [orderId], {
|
|
111
|
+
deploymentId: "latest", // [!code highlight]
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
return Response.json({ runId: run.runId });
|
|
115
|
+
}
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
<Callout type="warn">
|
|
119
|
+
`deploymentId: "latest"` is currently a Vercel-specific feature. Other Worlds may implement this option differently to match their own deployment runtimes, and the World spec may rename it from `deploymentId` to `version` in a future SDK version. On Vercel, `"latest"` resolves to the most recent deployment matching your current environment. Because the caller and target deployment can be different, keep the [workflow function name and file path](/docs/errors/workflow-not-registered), arguments, and return value backward-compatible across the deployments you plan to bridge.
|
|
120
|
+
</Callout>
|
|
121
|
+
|
|
122
|
+
## Self upgrading workflows
|
|
123
|
+
|
|
124
|
+
Some workflows are expected to run for a very long time. Scheduled loops, recurring jobs, agents, and chat sessions often should not stay on one deployment forever.
|
|
125
|
+
|
|
126
|
+
Model those as a sequence of runs. Each run does a bounded piece of work, then starts the next run on the latest deployment and exits. This is similar to `continueAsNew` in other durable execution systems, but in Workflow SDK it is just [explicit recursion through `start()`](/cookbook/common-patterns/workflow-composition).
|
|
127
|
+
|
|
128
|
+
```typescript title="workflows/daily-digest.ts" lineNumbers
|
|
129
|
+
import { sleep } from "workflow";
|
|
130
|
+
import { start } from "workflow/api";
|
|
131
|
+
|
|
132
|
+
type DigestState = {
|
|
133
|
+
userId: string;
|
|
134
|
+
lastSentAt?: string;
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
export async function dailyDigest(state: DigestState) {
|
|
138
|
+
"use workflow";
|
|
139
|
+
|
|
140
|
+
const sentAt = await sendDigest(state.userId);
|
|
141
|
+
await sleep("1d");
|
|
142
|
+
|
|
143
|
+
const run = await start(
|
|
144
|
+
dailyDigest,
|
|
145
|
+
[{ ...state, lastSentAt: sentAt }],
|
|
146
|
+
{
|
|
147
|
+
deploymentId: "latest", // [!code highlight]
|
|
148
|
+
}
|
|
149
|
+
);
|
|
150
|
+
|
|
151
|
+
return { continuedAs: run.runId };
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
async function sendDigest(userId: string) {
|
|
155
|
+
"use step";
|
|
156
|
+
// ...
|
|
157
|
+
return new Date().toISOString();
|
|
158
|
+
}
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
This pattern gives every run a clear lifecycle:
|
|
162
|
+
|
|
163
|
+
- The current run stays on its original deployment.
|
|
164
|
+
- The next run starts on the latest deployment.
|
|
165
|
+
- The [serialized `state`](/docs/foundations/serialization) is the migration boundary between versions.
|
|
166
|
+
- Observability can link parent and child runs when a workflow starts another run.
|
|
167
|
+
|
|
168
|
+
## Carrying context forward
|
|
169
|
+
|
|
170
|
+
Anything that is [serializable by Workflow SDK](/docs/foundations/serialization) can be passed from one run to the next as an argument. That includes plain state objects, `ReadableStream`, `WritableStream`, `AbortSignal`, and other supported serialized values.
|
|
171
|
+
|
|
172
|
+
For example, a long export can register its [output stream](/docs/foundations/streaming) once, write progress from each run, and pass the same stream plus updated state into the next run:
|
|
173
|
+
|
|
174
|
+
```typescript title="workflows/export-report.ts" lineNumbers
|
|
175
|
+
import { getWritable } from "workflow";
|
|
176
|
+
import { start } from "workflow/api";
|
|
177
|
+
|
|
178
|
+
type ExportState = {
|
|
179
|
+
exportId: string;
|
|
180
|
+
page: number;
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
export async function exportReport(
|
|
184
|
+
state: ExportState,
|
|
185
|
+
progress?: WritableStream<string>
|
|
186
|
+
) {
|
|
187
|
+
"use workflow";
|
|
188
|
+
|
|
189
|
+
// Register the stream once. Continuation runs receive this same stream
|
|
190
|
+
// as an argument and keep writing to it.
|
|
191
|
+
const stream =
|
|
192
|
+
progress !== undefined ? progress : getWritable<string>();
|
|
193
|
+
|
|
194
|
+
const hasMore = await exportPage(state, stream);
|
|
195
|
+
|
|
196
|
+
if (!hasMore) {
|
|
197
|
+
await writeProgress(stream, { type: "done", totalPages: state.page });
|
|
198
|
+
return { totalPages: state.page };
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
const run = await start(exportReport, [
|
|
202
|
+
{ ...state, page: state.page + 1 },
|
|
203
|
+
stream,
|
|
204
|
+
], {
|
|
205
|
+
deploymentId: "latest", // [!code highlight]
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
return { continuedAs: run.runId };
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
async function exportPage(
|
|
212
|
+
state: ExportState,
|
|
213
|
+
stream: WritableStream<string>
|
|
214
|
+
) {
|
|
215
|
+
"use step";
|
|
216
|
+
|
|
217
|
+
// Do work for this version boundary.
|
|
218
|
+
const hasMore = state.page < 10;
|
|
219
|
+
const writer = stream.getWriter();
|
|
220
|
+
|
|
221
|
+
try {
|
|
222
|
+
await writer.write(
|
|
223
|
+
JSON.stringify({ type: "page", page: state.page }) + "\n"
|
|
224
|
+
);
|
|
225
|
+
return hasMore;
|
|
226
|
+
} finally {
|
|
227
|
+
writer.releaseLock();
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
async function writeProgress(
|
|
232
|
+
stream: WritableStream<string>,
|
|
233
|
+
event: { type: "done"; totalPages: number }
|
|
234
|
+
) {
|
|
235
|
+
"use step";
|
|
236
|
+
|
|
237
|
+
const writer = stream.getWriter();
|
|
238
|
+
try {
|
|
239
|
+
await writer.write(JSON.stringify(event) + "\n");
|
|
240
|
+
} finally {
|
|
241
|
+
writer.releaseLock();
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
```typescript title="app/api/export/route.ts" lineNumbers
|
|
247
|
+
import { start } from "workflow/api";
|
|
248
|
+
import { exportReport } from "@/workflows/export-report";
|
|
249
|
+
|
|
250
|
+
export async function POST(request: Request) {
|
|
251
|
+
const { exportId } = await request.json();
|
|
252
|
+
|
|
253
|
+
const run = await start(exportReport, [{ exportId, page: 1 }]);
|
|
254
|
+
|
|
255
|
+
// Linked continuation runs keep writing to the stream registered by
|
|
256
|
+
// the parent run, because that stream is passed forward as an argument.
|
|
257
|
+
return new Response(run.readable, {
|
|
258
|
+
headers: { "Content-Type": "application/jsonl" },
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
Each run still has one clear version boundary: the current run stays on its original deployment, the next run starts on the latest deployment, and only the explicit state and stream handle are carried forward.
|
|
@@ -9,6 +9,10 @@ related:
|
|
|
9
9
|
- /docs/foundations/workflows-and-steps
|
|
10
10
|
---
|
|
11
11
|
|
|
12
|
+
<CopyPrompt
|
|
13
|
+
text="In this Astro app, run `npm i workflow`. In `astro.config.mjs`, import `workflow` from `workflow/astro` and add `integrations: [workflow()]`. Add the TypeScript plugin `{ "name": "workflow" }` to `tsconfig.json` if TypeScript is used. Create `src/workflows/user-signup.ts` exporting `handleUserSignup(email)` with `"use workflow"`, `sleep` from `workflow`, and `"use step"` helpers. Add `src/pages/api/signup.ts` exporting `POST: APIRoute` that reads `{ email }`, calls `start(handleUserSignup, [email])` from `workflow/api`, returns `Response.json`, and sets `prerender = false`. Run `npm run dev`, call `curl -X POST --json '{"email":"hello@example.com"}' http://localhost:4321/api/signup`, and inspect with `npx workflow inspect runs`."
|
|
14
|
+
/>
|
|
15
|
+
|
|
12
16
|
This guide will walk through setting up your first workflow in an Astro 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
|
---
|
|
@@ -51,6 +55,12 @@ export default defineConfig({
|
|
|
51
55
|
});
|
|
52
56
|
```
|
|
53
57
|
|
|
58
|
+
`workflow()` accepts an options object:
|
|
59
|
+
|
|
60
|
+
| Option | Type | Default | Description |
|
|
61
|
+
| --- | --- | --- | --- |
|
|
62
|
+
| `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. |
|
|
63
|
+
|
|
54
64
|
<Accordion type="single" collapsible>
|
|
55
65
|
<AccordionItem value="typescript-intellisense" className="[&_h3]:my-0">
|
|
56
66
|
<AccordionTrigger className="text-sm">
|
|
@@ -150,7 +160,7 @@ async function sendOnboardingEmail(user: { id: string; email: string}) {
|
|
|
150
160
|
|
|
151
161
|
Taking a look at this code:
|
|
152
162
|
|
|
153
|
-
* 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.
|
|
154
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).
|
|
155
165
|
* Steps can throw a `FatalError` if an error is intentional and should not be retried.
|
|
156
166
|
|
|
@@ -242,7 +252,7 @@ Additionally, check the [Deploying](/docs/deploying) section to learn how your w
|
|
|
242
252
|
If you see this error:
|
|
243
253
|
|
|
244
254
|
```
|
|
245
|
-
'start' received an invalid workflow function. Ensure the Workflow
|
|
255
|
+
'start' received an invalid workflow function. Ensure the Workflow SDK is configured correctly and the function includes a 'use workflow' directive.
|
|
246
256
|
```
|
|
247
257
|
|
|
248
258
|
Check both of these first:
|
|
@@ -9,6 +9,10 @@ related:
|
|
|
9
9
|
- /docs/foundations/workflows-and-steps
|
|
10
10
|
---
|
|
11
11
|
|
|
12
|
+
<CopyPrompt
|
|
13
|
+
text="In this Express app, run `npm i workflow express nitro rollup` and, if using TypeScript, `npm i -D @types/express`. Create `nitro.config.ts` with `modules: ["workflow/nitro"]`, `vercel: { entryFormat: "node" }`, and `routes: { "/**": { handler: "./src/index.ts", format: "node" } }`. Add package scripts `dev: "nitro dev"` and `build: "nitro build"`. Create `workflows/user-signup.ts` with `"use workflow"`, `sleep`, and `"use step"` helpers. Add `src/index.ts` with Express JSON middleware, POST `/api/signup`, and `start(handleUserSignup, [email])` 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 an Express 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
|
---
|
|
@@ -181,7 +185,7 @@ async function sendOnboardingEmail(user: { id: string; email: string }) {
|
|
|
181
185
|
|
|
182
186
|
Taking a look at this code:
|
|
183
187
|
|
|
184
|
-
- Business logic lives inside **steps**. When a
|
|
188
|
+
- 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.
|
|
185
189
|
- 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).
|
|
186
190
|
- Steps can throw a `FatalError` if an error is intentional and should not be retried.
|
|
187
191
|
|
|
@@ -269,7 +273,7 @@ Check the [Deploying](/docs/deploying) section to learn how your workflows can b
|
|
|
269
273
|
If you see this error:
|
|
270
274
|
|
|
271
275
|
```
|
|
272
|
-
'start' received an invalid workflow function. Ensure the Workflow
|
|
276
|
+
'start' received an invalid workflow function. Ensure the Workflow SDK is configured correctly and the function includes a 'use workflow' directive.
|
|
273
277
|
```
|
|
274
278
|
|
|
275
279
|
Check both of these first:
|
|
@@ -9,6 +9,10 @@ related:
|
|
|
9
9
|
- /docs/foundations/workflows-and-steps
|
|
10
10
|
---
|
|
11
11
|
|
|
12
|
+
<CopyPrompt
|
|
13
|
+
text="In this Fastify app, run `npm i workflow fastify nitro rollup` and, if using TypeScript, `npm i -D @types/node typescript`. Create `nitro.config.ts` with `modules: ["workflow/nitro"]`, `vercel: { entryFormat: "node" }`, and `routes: { "/**": { handler: "./src/index.ts", format: "node" } }`. Add package scripts `dev: "nitro dev"` and `build: "nitro build"`. Create `workflows/user-signup.ts` with `"use workflow"`, `sleep`, and `"use step"` helpers. Add `src/index.ts` with a Fastify app, POST `/api/signup`, `start(handleUserSignup, [email])`, `await app.ready()`, and an exported request handler. Run `npm run dev`, call `curl -X POST --json '{"email":"hello@example.com"}' http://localhost:3000/api/signup`, and inspect with `npx workflow inspect runs --web`."
|
|
14
|
+
/>
|
|
15
|
+
|
|
12
16
|
This guide will walk through setting up your first workflow in a Fastify 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
|
---
|
|
@@ -170,7 +174,7 @@ async function sendOnboardingEmail(user: { id: string; email: string }) {
|
|
|
170
174
|
```
|
|
171
175
|
Taking a look at this code:
|
|
172
176
|
|
|
173
|
-
- Business logic lives inside **steps**. When a
|
|
177
|
+
- 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.
|
|
174
178
|
- 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).
|
|
175
179
|
- Steps can throw a `FatalError` if an error is intentional and should not be retried.
|
|
176
180
|
|
|
@@ -256,7 +260,7 @@ Check the [Deploying](/docs/deploying) section to learn how your workflows can b
|
|
|
256
260
|
If you see this error:
|
|
257
261
|
|
|
258
262
|
```
|
|
259
|
-
'start' received an invalid workflow function. Ensure the Workflow
|
|
263
|
+
'start' received an invalid workflow function. Ensure the Workflow SDK is configured correctly and the function includes a 'use workflow' directive.
|
|
260
264
|
```
|
|
261
265
|
|
|
262
266
|
Check both of these first:
|
|
@@ -9,6 +9,10 @@ related:
|
|
|
9
9
|
- /docs/foundations/workflows-and-steps
|
|
10
10
|
---
|
|
11
11
|
|
|
12
|
+
<CopyPrompt
|
|
13
|
+
text="In this Hono app, run `npm i workflow nitro rollup`. Create `nitro.config.ts` with `modules: ["workflow/nitro"]` and `routes: { "/**": "./src/index.ts" }`. Add package scripts `dev: "nitro dev"` and `build: "nitro build"`. Add the TypeScript plugin `{ "name": "workflow" }` to `tsconfig.json` if TypeScript is used. Create `workflows/user-signup.ts` with `handleUserSignup(email)`, `"use workflow"`, `sleep` from `workflow`, and `"use step"` helpers. Add `src/index.ts` with a Hono app, POST `/api/signup`, `start(handleUserSignup, [email])` from `workflow/api`, and JSON response. 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
|
<Steps>
|
|
13
17
|
|
|
14
18
|
<Step>
|
|
@@ -166,7 +170,7 @@ async function sendOnboardingEmail(user: { id: string; email: string }) {
|
|
|
166
170
|
|
|
167
171
|
Taking a look at this code:
|
|
168
172
|
|
|
169
|
-
- Business logic lives inside **steps**. When a
|
|
173
|
+
- 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.
|
|
170
174
|
- 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).
|
|
171
175
|
- Steps can throw a `FatalError` if an error is intentional and should not be retried.
|
|
172
176
|
|
|
@@ -251,7 +255,7 @@ Check the [Deploying](/docs/deploying) section to learn how your workflows can b
|
|
|
251
255
|
If you see this error:
|
|
252
256
|
|
|
253
257
|
```
|
|
254
|
-
'start' received an invalid workflow function. Ensure the Workflow
|
|
258
|
+
'start' received an invalid workflow function. Ensure the Workflow SDK is configured correctly and the function includes a 'use workflow' directive.
|
|
255
259
|
```
|
|
256
260
|
|
|
257
261
|
Check both of these first:
|
|
@@ -9,6 +9,7 @@ related:
|
|
|
9
9
|
---
|
|
10
10
|
|
|
11
11
|
import { Next, Nitro, SvelteKit, Nuxt, Hono, Bun, AstroDark, AstroLight, TanStack, Vite, Express, Nest, Fastify, Python } from "@/app/[lang]/(home)/components/frameworks";
|
|
12
|
+
import { SiReactrouter } from "@icons-pack/react-simple-icons";
|
|
12
13
|
|
|
13
14
|
<Cards>
|
|
14
15
|
<Card href="/docs/getting-started/next">
|
|
@@ -20,6 +21,12 @@ import { Next, Nitro, SvelteKit, Nuxt, Hono, Bun, AstroDark, AstroLight, TanStac
|
|
|
20
21
|
<span className="font-medium">Vite</span>
|
|
21
22
|
</div>
|
|
22
23
|
</Card>
|
|
24
|
+
<Card href="/docs/getting-started/react-router">
|
|
25
|
+
<div className="flex flex-col items-center justify-center gap-2">
|
|
26
|
+
<SiReactrouter className="size-16" />
|
|
27
|
+
<span className="font-medium">React Router</span>
|
|
28
|
+
</div>
|
|
29
|
+
</Card>
|
|
23
30
|
<Card href="/docs/getting-started/astro">
|
|
24
31
|
<div className="flex flex-col items-center justify-center gap-2">
|
|
25
32
|
<AstroLight className="size-16 dark:hidden" />
|
|
@@ -63,6 +70,12 @@ import { Next, Nitro, SvelteKit, Nuxt, Hono, Bun, AstroDark, AstroLight, TanStac
|
|
|
63
70
|
<span className="font-medium">SvelteKit</span>
|
|
64
71
|
</div>
|
|
65
72
|
</Card>
|
|
73
|
+
<Card href="/docs/getting-started/tanstack-start" >
|
|
74
|
+
<div className="flex flex-col items-center justify-center gap-2">
|
|
75
|
+
<TanStack className="size-16 dark:invert" />
|
|
76
|
+
<span className="font-medium">TanStack Start</span>
|
|
77
|
+
</div>
|
|
78
|
+
</Card>
|
|
66
79
|
<Card href="/docs/getting-started/python">
|
|
67
80
|
<div className="flex flex-col items-center justify-center gap-2">
|
|
68
81
|
<Python className="size-16" />
|
|
@@ -70,18 +83,11 @@ import { Next, Nitro, SvelteKit, Nuxt, Hono, Bun, AstroDark, AstroLight, TanStac
|
|
|
70
83
|
<Badge variant="secondary">Beta</Badge>
|
|
71
84
|
</div>
|
|
72
85
|
</Card>
|
|
73
|
-
<Card
|
|
86
|
+
<Card href="/docs/getting-started/nestjs">
|
|
74
87
|
<div className="flex flex-col items-center justify-center gap-2">
|
|
75
|
-
<Nest className="size-16 dark:invert
|
|
88
|
+
<Nest className="size-16 dark:invert" />
|
|
76
89
|
<span className="font-medium">NestJS</span>
|
|
77
|
-
<Badge variant="secondary">
|
|
78
|
-
</div>
|
|
79
|
-
</Card>
|
|
80
|
-
<Card className="opacity-50">
|
|
81
|
-
<div className="flex flex-col items-center justify-center gap-2">
|
|
82
|
-
<TanStack className="size-16 dark:invert grayscale" />
|
|
83
|
-
<span className="font-medium">TanStack Start</span>
|
|
84
|
-
<Badge variant="secondary">Coming soon</Badge>
|
|
90
|
+
<Badge variant="secondary">Experimental</Badge>
|
|
85
91
|
</div>
|
|
86
92
|
</Card>
|
|
87
93
|
</Cards>
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
"title": "Getting Started",
|
|
3
3
|
"pages": [
|
|
4
4
|
"next",
|
|
5
|
+
"react-router",
|
|
5
6
|
"astro",
|
|
6
7
|
"express",
|
|
7
8
|
"fastify",
|
|
@@ -9,8 +10,10 @@
|
|
|
9
10
|
"nitro",
|
|
10
11
|
"nuxt",
|
|
11
12
|
"sveltekit",
|
|
13
|
+
"tanstack-start",
|
|
12
14
|
"vite",
|
|
13
|
-
"python"
|
|
15
|
+
"python",
|
|
16
|
+
"nestjs"
|
|
14
17
|
],
|
|
15
18
|
"defaultOpen": true
|
|
16
19
|
}
|