Skip to content

Commit b40389e

Browse files
docs: update astro guide with recommended approach (#7171)
1 parent b28b225 commit b40389e

File tree

2 files changed

+65
-117
lines changed

2 files changed

+65
-117
lines changed

cSpell.json

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,8 @@
113113
"nonrepeatable",
114114
"Superkey",
115115
"superkey",
116-
"Dataguide"
116+
"Dataguide",
117+
"psql"
117118
],
118119
"ignoreWords": [
119120
"Aiven",
@@ -156,7 +157,8 @@
156157
"Nixpacks",
157158
"Buildpacks",
158159
"Sevalla's",
159-
"Dataguide"
160+
"Dataguide",
161+
"justinellingwood"
160162
],
161163
"patterns": [
162164
{
@@ -210,4 +212,4 @@
210212
"HTML Tags"
211213
],
212214
"ignorePaths": []
213-
}
215+
}

content/800-guides/220-astro.mdx

Lines changed: 60 additions & 114 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ npm install @prisma/client
5858
Once installed, initialize Prisma in your project:
5959

6060
```terminal
61-
npx prisma init --db --output ../src/generated/prisma
61+
npx prisma init --db --output ../prisma/generated
6262
```
6363
:::info
6464
You'll need to answer a few questions while setting up your Prisma Postgres database. Select the region closest to your location and a memorable name for your database like "My Astro Project"
@@ -74,9 +74,9 @@ In the `prisma/schema.prisma` file, add the following models and change the gene
7474

7575
```prisma file=prisma/schema.prisma
7676
generator client {
77-
//edit-next-line
78-
provider = "prisma-client"
79-
output = "../src/generated/prisma"
77+
provider = "prisma-client"
78+
engineType = "client"
79+
output = "../prisma/generated"
8080
}
8181
8282
datasource db {
@@ -119,7 +119,7 @@ Let's add some seed data to populate the database with sample users and posts.
119119
Create a new file called `seed.ts` in the `prisma/` directory:
120120

121121
```typescript file=prisma/seed.ts
122-
import { PrismaClient, Prisma } from "../src/generated/prisma/client.js";
122+
import { PrismaClient, Prisma } from "../prisma/generated/client.js";
123123

124124
const prisma = new PrismaClient();
125125

@@ -157,19 +157,34 @@ const userData: Prisma.UserCreateInput[] = [
157157
];
158158

159159
export async function main() {
160+
console.log("Starting to seed...");
161+
160162
for (const u of userData) {
161-
await prisma.user.create({ data: u });
163+
await prisma.user.upsert({
164+
where: { email: u.email },
165+
update: {},
166+
create: u,
167+
});
162168
}
169+
170+
console.log("Seeding finished.");
163171
}
164172

165-
main();
173+
main()
174+
.catch((e) => {
175+
console.error(e);
176+
process.exit(1);
177+
})
178+
.finally(async () => {
179+
await prisma.$disconnect();
180+
});
166181
```
167182

168183
Now, tell Prisma how to run this script by updating your `package.json`:
169184

170185
```json file=package.json
171186
{
172-
"name": "extinct-eclipse-minimal",
187+
"name": "astro-prisma",
173188
"type": "module",
174189
"version": "0.0.1",
175190
"scripts": {
@@ -184,13 +199,13 @@ Now, tell Prisma how to run this script by updating your `package.json`:
184199
},
185200
//add-end
186201
"dependencies": {
187-
"@prisma/client": "^6.7.0",
188-
"@prisma/extension-accelerate": "^1.3.0",
189-
"astro": "^5.7.10"
202+
"@prisma/client": "^6.17.1",
203+
"@prisma/extension-accelerate": "^2.0.2",
204+
"astro": "^5.14.4"
190205
},
191206
"devDependencies": {
192-
"prisma": "^6.7.0",
193-
"tsx": "^4.19.4"
207+
"prisma": "^6.17.1",
208+
"tsx": "^4.20.6"
194209
}
195210
}
196211
```
@@ -209,7 +224,21 @@ npx prisma studio
209224

210225
## 3. Integrate Prisma into Astro
211226

212-
### 3.1. Create a Prisma Client
227+
### 3.1. Create TypeScript environment definitions
228+
229+
First, create an `env.d.ts` file in your `src` directory to provide TypeScript definitions for environment variables:
230+
231+
```typescript file=src/env.d.ts
232+
interface ImportMetaEnv {
233+
readonly DATABASE_URL: string;
234+
}
235+
236+
interface ImportMeta {
237+
readonly env: ImportMetaEnv;
238+
}
239+
```
240+
241+
### 3.2. Create a Prisma Client
213242

214243
Inside of `/src`, create a `lib` directory and a `prisma.ts` file inside it. This file will be used to create and export your Prisma Client instance.
215244

@@ -218,13 +247,12 @@ mkdir src/lib
218247
touch src/lib/prisma.ts
219248
```
220249

221-
222250
Set up the Prisma client like this:
223251

224252
<TabbedContent code>
225253
<TabItem value="Prisma Postgres (recommended)">
226-
```tsx file=src/lib/prisma.ts
227-
import { PrismaClient } from "../generated/prisma/client.js";
254+
```typescript file=src/lib/prisma.ts
255+
import { PrismaClient } from "../../prisma/generated/client";
228256
import { withAccelerate } from "@prisma/extension-accelerate";
229257

230258
const prisma = new PrismaClient({
@@ -236,12 +264,12 @@ export default prisma;
236264
</TabItem>
237265

238266
<TabItem value="Other databases">
239-
```tsx file=src/lib/prisma.ts
240-
import { PrismaClient } from "../generated/prisma/client.js";
267+
```typescript file=src/lib/prisma.ts
268+
import { PrismaClient } from "../../prisma/generated/client";
241269

242270
const prisma = new PrismaClient({
243271
datasourceUrl: import.meta.env.DATABASE_URL,
244-
})
272+
});
245273

246274
export default prisma;
247275
```
@@ -254,7 +282,7 @@ We recommend using a connection pooler (like [Prisma Accelerate](https://www.pri
254282
If you choose not to use one, **avoid** instantiating `PrismaClient` globally in long-lived environments. Instead, create and dispose of the client per request to prevent exhausting your database connections.
255283
:::
256284

257-
### 3.2. Create an API route
285+
### 3.3. Create an API route
258286

259287
An API route is the best way to fetch data from your database in an Astro app.
260288

@@ -267,7 +295,7 @@ touch src/pages/api/users.ts
267295

268296
Now, create a GET route that fetches the `Users` data from your database, making sure to include each user's `Posts` by adding them to the `include` field:
269297

270-
```ts file=src/pages/api/users.ts
298+
```typescript file=src/pages/api/users.ts
271299
import type { APIRoute } from "astro";
272300
import prisma from "../../lib/prisma";
273301

@@ -282,73 +310,23 @@ export const GET: APIRoute = async () => {
282310
};
283311
```
284312

285-
Next, you'll call this route from the `index.astro` file and display it.
313+
### 3.4. Fetch the data from the API route (Recommended Method)
286314

287-
### 3.3. Fetch the data from the API route
315+
Instead of using `fetch()` with HTTP requests, Astro recommends importing endpoint functions directly. This approach is more efficient and avoids URL parsing issues.
288316

289-
Start by create a new type that combines the `User` and `Post` models called `UserWithPosts`:
317+
Start by creating a new type that combines the `User` and `Post` models called `UserWithPosts`:
290318

291319
```tsx file=src/pages/index.astro
292320
---
293321
//add-start
294-
import type { User, Post } from "../generated/prisma/client.js";
295-
type UserWithPosts = User & { posts: Post[] };
296-
//add-end
297-
---
322+
import type { User, Post } from "../../prisma/generated/client";
323+
import { GET } from "./api/users.ts";
298324

299-
<html lang="en">
300-
<head>
301-
<meta charset="utf-8" />
302-
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
303-
<meta name="viewport" content="width=device-width" />
304-
<meta name="generator" content={Astro.generator} />
305-
<title>Astro</title>
306-
</head>
307-
<body>
308-
<h1>Astro</h1>
309-
</body>
310-
</html>
311-
```
312-
313-
Fetch the data from the API route and set it's type to the `UserWithPosts` type you just created:
314-
315-
```tsx file=src/pages/index.astro
316-
---
317-
import type { User, Post } from "../generated/prisma/client.js";
318325
type UserWithPosts = User & { posts: Post[] };
319-
//add-start
320-
const response = await fetch("http://localhost:4321/api/users");
321-
const users: UserWithPosts[] = await response.json();
322-
//add-end
323-
---
324-
325-
<html lang="en">
326-
<head>
327-
<meta charset="utf-8" />
328-
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
329-
<meta name="viewport" content="width=device-width" />
330-
<meta name="generator" content={Astro.generator} />
331-
<title>Astro</title>
332-
</head>
333-
<body>
334-
<h1>Astro</h1>
335-
</body>
336-
</html>
337-
```
338-
339326

340-
### 3.4. Display the data
341-
342-
With the variables from the frontmatter now available throughout your file, you can display the list of users.
343-
344-
Just below the `<h1>` tag, map through the `users` array, add the `UserWithPosts` type to the users, and display the names of the users:
345-
346-
```tsx file=src/pages/index.astro
347-
---
348-
import type { User, Post } from "../generated/prisma/client.js";
349-
type UserWithPosts = User & { posts: Post[] };
350-
const response = await fetch("http://localhost:4321/api/users");
327+
const response = await GET(Astro);
351328
const users: UserWithPosts[] = await response.json();
329+
//add-end
352330
---
353331

354332
<html lang="en">
@@ -357,56 +335,24 @@ const users: UserWithPosts[] = await response.json();
357335
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
358336
<meta name="viewport" content="width=device-width" />
359337
<meta name="generator" content={Astro.generator} />
360-
<title>Astro</title>
338+
<title>Astro + Prisma</title>
361339
</head>
362340
<body>
363-
//edit-next-line
364341
<h1>Astro + Prisma</h1>
365342
//add-start
366-
{users.map((user: UserWithPosts) => (
367-
<li>
368-
<h2>{user.name}</h2>
369-
</li>
370-
))}
371-
//add-end
372-
</body>
373-
</html>
374-
```
375-
376-
Finally, display the `Posts` below the respective `User` and set the `Post` type:
377-
378-
```tsx file=src/pages/index.astro
379-
---
380-
import type { User, Post } from "../generated/prisma/client.js";
381-
type UserWithPosts = User & { posts: Post[] };
382-
const response = await fetch("http://localhost:4321/api/users");
383-
const users: UserWithPosts[] = await response.json();
384-
---
385-
386-
<html lang="en">
387-
<head>
388-
<meta charset="utf-8" />
389-
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
390-
<meta name="viewport" content="width=device-width" />
391-
<meta name="generator" content={Astro.generator} />
392-
<title>Astro</title>
393-
</head>
394-
<body>
395-
<h1>Astro + Prisma</h1>
396343
<ul>
397344
{users.map((user: UserWithPosts) => (
398345
<li>
399-
<h2>{user.name}</h2>
400-
//add-start
346+
<h2>{user.name}</h2>
401347
<ul>
402348
{user.posts.map((post: Post) => (
403349
<li>{post.title}</li>
404350
))}
405351
</ul>
406-
//add-end
407352
</li>
408353
))}
409354
</ul>
355+
//add-end
410356
</body>
411357
</html>
412358
```

0 commit comments

Comments
 (0)