Skip to content

Commit e1d5eca

Browse files
committed
feat: add astro support (#347)
1 parent 298e85e commit e1d5eca

39 files changed

+2674
-139
lines changed

.changeset/config.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
"@workflow/example-nitro-v2",
1919
"@workflow/example-nuxt",
2020
"@workflow/example-vite",
21-
"@workflow/example-sveltekit"
21+
"@workflow/example-sveltekit",
22+
"@workflow/example-astro"
2223
]
2324
}

.changeset/grumpy-ties-sort.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
"@workflow/builders": patch
3+
"workflow": patch
4+
"@workflow/astro": patch
5+
---
6+
7+
Add @workflow/astro package

.changeset/pre.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
"@workflow/example-nuxt": "0.0.0",
3232
"@workflow/example-vite": "0.0.0",
3333
"@workflow/example-sveltekit": "0.0.0",
34+
"@workflow/example-astro": "0.0.0",
3435
"@workflow/builders": "4.0.1-beta.3",
3536
"@workflow/sveltekit": "4.0.0-beta.1",
3637
"@workflow/nuxt": "4.0.1-beta.6",

.github/workflows/tests.yml

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,8 @@ jobs:
7575
project-id: "prj_p0GIEsfl53L7IwVbosPvi9rPSOYW"
7676
- name: "express"
7777
project-id: "prj_cCZjpBy92VRbKHHbarDMhOHtkuIr"
78+
- name: "astro"
79+
project-id: "prj_YDAXj3K8LM0hgejuIMhioz2yLgTI"
7880
env:
7981
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
8082
TURBO_TEAM: ${{ vars.TURBO_TEAM }}
@@ -191,7 +193,7 @@ jobs:
191193
run: cd workbench/${{ matrix.app.name }} && pnpm dev & echo "starting tests in 10 seconds" && sleep 10 && pnpm vitest run packages/core/e2e/dev.test.ts && sleep 10 && pnpm run test:e2e
192194
env:
193195
APP_NAME: ${{ matrix.app.name }}
194-
DEPLOYMENT_URL: "http://localhost:${{ matrix.app.name == 'sveltekit' && '5173' || '3000' }}"
196+
DEPLOYMENT_URL: "http://localhost:${{ matrix.app.name == 'sveltekit' && '5173' || (matrix.app.name == 'astro' && '4321' || '3000') }}"
195197
DEV_TEST_CONFIG: ${{ toJSON(matrix.app) }}
196198

197199
e2e-local-prod:
@@ -243,7 +245,7 @@ jobs:
243245
run: cd workbench/${{ matrix.app.name }} && pnpm start & echo "starting tests in 10 seconds" && sleep 10 && pnpm run test:e2e
244246
env:
245247
APP_NAME: ${{ matrix.app.name }}
246-
DEPLOYMENT_URL: "http://localhost:${{ matrix.app.name == 'sveltekit' && '4173' || '3000' }}"
248+
DEPLOYMENT_URL: "http://localhost:${{ matrix.app.name == 'sveltekit' && '4173' || (matrix.app.name == 'astro' && '4321' || '3000') }}"
247249

248250
e2e-local-postgres:
249251
name: E2E Local Postgres Tests (${{ matrix.app.name }} - ${{ matrix.app.canary && 'canary' || 'stable' }})
@@ -314,7 +316,7 @@ jobs:
314316
run: cd workbench/${{ matrix.app.name }} && pnpm start & echo "starting tests in 10 seconds" && sleep 10 && pnpm run test:e2e
315317
env:
316318
APP_NAME: ${{ matrix.app.name }}
317-
DEPLOYMENT_URL: "http://localhost:${{ matrix.app.name == 'sveltekit' && '4173' || '3000' }}"
319+
DEPLOYMENT_URL: "http://localhost:${{ matrix.app.name == 'sveltekit' && '4173' || (matrix.app.name == 'astro' && '4321' || '3000') }}"
318320

319321
e2e-windows:
320322
name: E2E Windows Tests

docs/app/(home)/components/frameworks.tsx

Lines changed: 130 additions & 105 deletions
Large diffs are not rendered by default.
Lines changed: 233 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,233 @@
1+
---
2+
title: Astro
3+
---
4+
5+
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 development kit in your own projects.
6+
7+
---
8+
9+
<Steps>
10+
11+
<Step>
12+
## Create Your Astro Project
13+
14+
Start by creating a new Astro project. This command will create a new directory named `my-workflow-app` and setup a minimal Astro project inside it.
15+
16+
```bash
17+
npm create astro@latest my-workflow-app -- --template minimal --install --yes
18+
```
19+
20+
Enter the newly made directory:
21+
22+
```bash
23+
cd my-workflow-app
24+
```
25+
26+
### Install `workflow`
27+
28+
```package-install
29+
npm i workflow
30+
```
31+
32+
### Configure Astro
33+
34+
Add `workflow()` to your Astro config. This enables usage of the `"use workflow"` and `"use step"` directives.
35+
36+
```typescript title="astro.config.mjs" lineNumbers
37+
// @ts-check
38+
import { defineConfig } from "astro/config";
39+
import { workflow } from "workflow/astro";
40+
41+
// https://astro.build/config
42+
export default defineConfig({
43+
integrations: [workflow()],
44+
});
45+
```
46+
47+
<Accordion type="single" collapsible>
48+
<AccordionItem value="typescript-intellisense" className="[&_h3]:my-0">
49+
<AccordionTrigger className="text-sm">
50+
### Setup IntelliSense for TypeScript (Optional)
51+
</AccordionTrigger>
52+
<AccordionContent className="[&_p]:my-2">
53+
54+
To enable helpful hints in your IDE, setup the workflow plugin in `tsconfig.json`:
55+
56+
```json title="tsconfig.json" lineNumbers
57+
{
58+
"compilerOptions": {
59+
// ... rest of your TypeScript config
60+
"plugins": [
61+
{
62+
"name": "workflow" // [!code highlight]
63+
}
64+
]
65+
}
66+
}
67+
```
68+
69+
</AccordionContent>
70+
</AccordionItem>
71+
</Accordion>
72+
73+
</Step>
74+
75+
<Step>
76+
77+
## Create Your First Workflow
78+
79+
Create a new file for our first workflow:
80+
81+
```typescript title="src/workflows/user-signup.ts" lineNumbers
82+
import { sleep } from "workflow";
83+
84+
export async function handleUserSignup(email: string) {
85+
"use workflow"; // [!code highlight]
86+
87+
const user = await createUser(email);
88+
await sendWelcomeEmail(user);
89+
90+
await sleep("5s"); // Pause for 5s - doesn't consume any resources
91+
await sendOnboardingEmail(user);
92+
93+
return { userId: user.id, status: "onboarded" };
94+
}
95+
96+
```
97+
98+
We'll fill in those functions next, but let's take a look at this code:
99+
100+
* We define a **workflow** function with the directive `"use workflow"`. Think of the workflow function as the _orchestrator_ of individual **steps**.
101+
* The Workflow DevKit'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.
102+
103+
## Create Your Workflow Steps
104+
105+
Let's now define those missing functions.
106+
107+
```typescript title="src/workflows/user-signup.ts" lineNumbers
108+
import { FatalError } from "workflow"
109+
110+
// Our workflow function defined earlier
111+
112+
async function createUser(email: string) {
113+
"use step"; // [!code highlight]
114+
115+
console.log(`Creating user with email: ${email}`);
116+
117+
// Full Node.js access - database calls, APIs, etc.
118+
return { id: crypto.randomUUID(), email };
119+
}
120+
121+
async function sendWelcomeEmail(user: { id: string; email: string; }) {
122+
"use step"; // [!code highlight]
123+
124+
console.log(`Sending welcome email to user: ${user.id}`);
125+
126+
if (Math.random() < 0.3) {
127+
// By default, steps will be retried for unhandled errors
128+
throw new Error("Retryable!");
129+
}
130+
}
131+
132+
async function sendOnboardingEmail(user: { id: string; email: string}) {
133+
"use step"; // [!code highlight]
134+
135+
if (!user.email.includes("@")) {
136+
// To skip retrying, throw a FatalError instead
137+
throw new FatalError("Invalid Email");
138+
}
139+
140+
console.log(`Sending onboarding email to user: ${user.id}`);
141+
}
142+
```
143+
144+
Taking a look at this code:
145+
146+
* Business logic lives inside **steps**. When a step is invoked inside a **workflow**, it gets enqueued to run on a separate request while the workflow is suspended, just like `sleep`.
147+
* 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).
148+
* Steps can throw a `FatalError` if an error is intentional and should not be retried.
149+
150+
<Callout>
151+
We'll dive deeper into workflows, steps, and other ways to suspend or handle events in [Foundations](/docs/foundations).
152+
</Callout>
153+
154+
</Step>
155+
156+
<Step>
157+
158+
## Create Your Route Handler
159+
160+
To invoke your new workflow, we'll have to add your workflow to a `POST` API route handler, `src/pages/api/signup.ts` with the following code:
161+
162+
```typescript title="src/pages/api/signup.ts"
163+
import type { APIRoute } from "astro";
164+
import { start } from "workflow/api";
165+
import { handleUserSignup } from "../../workflows/user-signup";
166+
167+
export const POST: APIRoute = async ({ request }: { request: Request }) => {
168+
const { email } = await request.json();
169+
170+
// Executes asynchronously and doesn't block your app
171+
await start(handleUserSignup, [email]);
172+
return Response.json({
173+
message: "User signup workflow started",
174+
});
175+
};
176+
177+
export const prerender = false; // Don't prerender this page since it's an API route
178+
```
179+
180+
This route handler creates a `POST` request endpoint at `/api/signup` that will trigger your workflow.
181+
182+
<Callout>
183+
Workflows can be triggered from API routes or any server-side code.
184+
</Callout>
185+
186+
</Step>
187+
188+
</Steps>
189+
190+
## Run in Development
191+
192+
To start your development server, run the following command in your terminal in the Vite root directory:
193+
194+
```bash
195+
npm run dev
196+
```
197+
198+
Once your development server is running, you can trigger your workflow by running this command in the terminal:
199+
200+
```bash
201+
curl -X POST --json '{"email":"[email protected]"}' http://localhost:5173/api/signup
202+
```
203+
204+
Check the Astro development server logs to see your workflow execute as well as the steps that are being processed.
205+
206+
Additionally, you can use the [Workflow DevKit CLI or Web UI](/docs/observability) to inspect your workflow runs and steps in detail.
207+
208+
```bash
209+
npx workflow inspect runs
210+
# or add '--web' for an interactive Web based UI
211+
```
212+
213+
<img src="/o11y-ui.png" alt="Workflow DevKit Web UI" />
214+
215+
---
216+
217+
## Deploying to Production
218+
219+
Workflow DevKit apps currently work best when deployed to [Vercel](https://vercel.com/home) and needs no special configuration.
220+
221+
To deploy your Astro project to Vercel, ensure that the [Astro Vercel adapter](https://docs.astro.build/en/guides/integrations-guide/vercel) is configured:
222+
223+
```bash
224+
npx astro add vercel
225+
```
226+
227+
Additionally, check the [Deploying](/docs/deploying) section to learn how your workflows can be deployed elsewhere.
228+
229+
## Next Steps
230+
231+
* Learn more about the [Foundations](/docs/foundations).
232+
* Check [Errors](/docs/errors) if you encounter issues.
233+
* Explore the [API Reference](/docs/api-reference).

docs/content/docs/getting-started/index.mdx

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,56 +3,59 @@ title: Getting Started
33
description: Start by choosing your framework. Each guide will walk you through the steps to install the dependencies and start running your first workflow.
44
---
55

6-
import { Next, Nitro, SvelteKit, Nuxt, Hono, Bun, AstroDark, AstroLight, TanStack, Vite, Express } from '@/app/(home)/components/frameworks';
6+
import { Next, Nitro, SvelteKit, Nuxt, Hono, Bun, AstroDark, AstroLight, TanStack, Vite, Express, Nest } from '@/app/(home)/components/frameworks';
77

88
<Cards>
99
<Card href="/docs/getting-started/next">
10-
<div className="flex flex-col items-center justify-center text-center gap-2">
11-
<Next className="size-16" />
12-
<span className="font-medium">Next.js</span>
13-
</div>
10+
<div className="flex flex-col items-center justify-center gap-2"> <Next className="size-16" /> <span className="font-medium">Next.js</span> </div>
1411
</Card>
1512
<Card href="/docs/getting-started/vite">
16-
<div className="flex flex-col items-center justify-center text-center gap-2">
13+
<div className="flex flex-col items-center justify-center gap-2">
1714
<Vite className="size-16" />
1815
<span className="font-medium">Vite</span>
1916
</div>
2017
</Card>
18+
<Card href="/docs/getting-started/astro">
19+
<div className="flex flex-col items-center justify-center gap-2">
20+
<AstroLight className="size-16 dark:hidden" />
21+
<AstroDark className="size-16 hidden dark:block" />
22+
<span className="font-medium">Astro</span>
23+
</div>
24+
</Card>
2125
<Card href="/docs/getting-started/express" >
22-
<div className="flex flex-col items-center justify-center text-center gap-2">
26+
<div className="flex flex-col items-center justify-center gap-2">
2327
<Express className="size-16 dark:invert" />
2428
<span className="font-medium">Express</span>
2529
</div>
2630
</Card>
2731
<Card href="/docs/getting-started/hono">
28-
<div className="flex flex-col items-center justify-center text-center gap-2">
32+
<div className="flex flex-col items-center justify-center gap-2">
2933
<Hono className="size-16" />
3034
<span className="font-medium">Hono</span>
3135
</div>
3236
</Card>
3337
<Card href="/docs/getting-started/nitro" >
34-
<div className="flex flex-col items-center justify-center text-center gap-2">
38+
<div className="flex flex-col items-center justify-center gap-2">
3539
<Nitro className="size-16" />
3640
<span className="font-medium">Nitro</span>
3741
</div>
3842
</Card>
3943
<Card href="/docs/getting-started/nuxt" >
40-
<div className="flex flex-col items-center justify-center text-center gap-2">
44+
<div className="flex flex-col items-center justify-center gap-2">
4145
<Nuxt className="size-16" />
4246
<span className="font-medium">Nuxt</span>
4347
</div>
4448
</Card>
4549
<Card href="/docs/getting-started/sveltekit" >
46-
<div className="flex flex-col items-center justify-center text-center gap-2">
50+
<div className="flex flex-col items-center justify-center gap-2">
4751
<SvelteKit className="size-16" />
4852
<span className="font-medium">SvelteKit</span>
4953
</div>
5054
</Card>
5155
<Card className="opacity-50">
5256
<div className="flex flex-col items-center justify-center gap-2">
53-
<AstroLight className="size-16 dark:hidden grayscale" />
54-
<AstroDark className="size-16 hidden dark:block grayscale" />
55-
<span className="font-medium">Astro</span>
57+
<Nest className="size-16 dark:invert grayscale" />
58+
<span className="font-medium">NestJS</span>
5659
<Badge variant="secondary">Coming soon</Badge>
5760
</div>
5861
</Card>

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@
1919
"packageManager": "[email protected]+sha512.cf9998222162dd85864d0a8102e7892e7ba4ceadebbf5a31f9c2fce48dfce317a9c53b9f6464d1ef9042cba2e02ae02a9f7c143a2b438cd93c91840f0192b9dd",
2020
"pnpm": {
2121
"overrides": {
22-
"rfc6902": "5.1.2"
22+
"rfc6902": "5.1.2",
23+
"path-to-regexp": "6.3.0"
2324
},
2425
"onlyBuiltDependencies": [
2526
"bun"

0 commit comments

Comments
 (0)