Skip to content

Commit b6ce76f

Browse files
mhartingtongithub-actions[bot]coderabbitai[bot]ankur-archaidankmcalister
authored
DA-5233 Hono Guide Created (#7156)
* DA-5233 Hono Guide Created * Optimised images with calibre/image-actions * Optimised images with calibre/image-actions * Apply suggestions from code review Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * Apply suggestions from code review Co-authored-by: Ankur Datta <[email protected]> Co-authored-by: Aidan McAlister <[email protected]> * Update content/800-guides/390-hono.mdx Co-authored-by: Aidan McAlister <[email protected]> * apply updates * apply updates * apply feedback --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> Co-authored-by: Ankur Datta <[email protected]> Co-authored-by: Aidan McAlister <[email protected]>
1 parent 74f9181 commit b6ce76f

File tree

3 files changed

+393
-0
lines changed

3 files changed

+393
-0
lines changed

content/800-guides/390-hono.mdx

Lines changed: 392 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,392 @@
1+
---
2+
title: 'How to use Prisma with Hono'
3+
metaTitle: 'How to use Prisma ORM and Prisma Postgres with Hono'
4+
description: 'Learn how to use Prisma ORM in a Hono app'
5+
sidebar_label: 'Hono'
6+
image: '/img/guides/prisma-hono-cover.png'
7+
completion_time: '15 min'
8+
community_section: true
9+
---
10+
11+
## Introduction
12+
13+
Prisma ORM offers type-safe database access, and [Hono](https://hono.dev/) is built for fast, lightweight web apps. Together with [Prisma Postgres](https://www.prisma.io/postgres), you get a fast, lightweight backend, that can be deployed through Node.js, Cloudflare, or many other runtimes.
14+
15+
In this guide, you'll learn to integrate Prisma ORM with a Prisma Postgres database in a Hono backend application. You can find a complete example of this guide on [GitHub](https://github.com/prisma/prisma-examples/tree/latest/orm/hono).
16+
17+
## Prerequisites
18+
- [Node.js 20+](https://nodejs.org)
19+
20+
## 1. Set up your project
21+
22+
Create a new Hono project:
23+
24+
```terminal
25+
npm create hono@latest
26+
```
27+
28+
:::info
29+
- *Target directory?* `my-app`
30+
- *Which template do you want to use?* `nodejs`
31+
- *Install dependencies? (recommended)* `Yes`
32+
- *Which package manager do you want to use?* `npm`
33+
:::
34+
35+
## 2. Install and configure Prisma
36+
37+
### 2.1. Install dependencies
38+
39+
To get started with Prisma, you'll need to install a few dependencies:
40+
41+
<TabbedContent code>
42+
<TabItem value="Prisma Postgres (recommended)">
43+
```terminal
44+
npm install prisma --save-dev
45+
npm install @prisma/extension-accelerate @prisma/client dotenv
46+
```
47+
</TabItem>
48+
<TabItem value="Other databases">
49+
```terminal
50+
npm install prisma --save-dev
51+
npm install @prisma/client dotenv
52+
```
53+
</TabItem>
54+
</TabbedContent>
55+
56+
Once installed, initialize Prisma in your project:
57+
58+
```terminal
59+
npx prisma init --db --output ../src/generated/prisma
60+
````
61+
62+
:::info
63+
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 Hono Project"
64+
:::
65+
This will create:
66+
67+
- A `prisma/` directory with a `schema.prisma` file
68+
- A `.env` file with a `DATABASE_URL` already set
69+
70+
### 2.2. Define your Prisma Schema
71+
72+
In the `prisma/schema.prisma` file, add the following models and change the generator to use the `prisma-client` provider:
73+
74+
```prisma file=prisma/schema.prisma
75+
generator client {
76+
//edit-next-line
77+
provider = "prisma-client"
78+
engineType = "client"
79+
output = "../src/generated/prisma"
80+
}
81+
82+
datasource db {
83+
provider = "postgresql"
84+
url = env("DATABASE_URL")
85+
}
86+
87+
//add-start
88+
model User {
89+
id Int @id @default(autoincrement())
90+
email String @unique
91+
name String?
92+
posts Post[]
93+
}
94+
95+
model Post {
96+
id Int @id @default(autoincrement())
97+
title String
98+
content String?
99+
published Boolean @default(false)
100+
authorId Int
101+
author User @relation(fields: [authorId], references: [id])
102+
}
103+
//add-end
104+
```
105+
106+
This creates two models: `User` and `Post`, with a one-to-many relationship between them.
107+
108+
### 2.3. Configure the Prisma Client generator
109+
110+
Now, run the following command to create the database tables and generate the Prisma Client:
111+
112+
```terminal
113+
npx prisma migrate dev --name init
114+
```
115+
### 2.4. Seed the database
116+
117+
Let's add some seed data to populate the database with sample users and posts.
118+
119+
Create a new file called `seed.ts` in the `prisma/` directory:
120+
121+
```typescript file=prisma/seed.ts
122+
import { PrismaClient, Prisma } from "../src/generated/prisma/client.js";
123+
124+
const prisma = new PrismaClient();
125+
126+
const userData: Prisma.UserCreateInput[] = [
127+
{
128+
name: "Alice",
129+
130+
posts: {
131+
create: [
132+
{
133+
title: "Join the Prisma Discord",
134+
content: "https://pris.ly/discord",
135+
published: true,
136+
},
137+
{
138+
title: "Prisma on YouTube",
139+
content: "https://pris.ly/youtube",
140+
},
141+
],
142+
},
143+
},
144+
{
145+
name: "Bob",
146+
147+
posts: {
148+
create: [
149+
{
150+
title: "Follow Prisma on Twitter",
151+
content: "https://www.twitter.com/prisma",
152+
published: true,
153+
},
154+
],
155+
},
156+
},
157+
];
158+
159+
export async function main() {
160+
for (const u of userData) {
161+
await prisma.user.create({ data: u });
162+
}
163+
}
164+
165+
main()
166+
.catch((e) => {
167+
console.error(e);
168+
process.exit(1);
169+
})
170+
.finally(async () => {
171+
await prisma.$disconnect();
172+
});
173+
```
174+
175+
Now, tell Prisma how to run this script by updating your `package.json`:
176+
177+
```json file=package.json
178+
{
179+
"name": "my-app",
180+
"type": "module",
181+
"scripts": {
182+
"dev": "tsx watch src/index.ts",
183+
"build": "tsc",
184+
"start": "node dist/index.js"
185+
},
186+
//add-start
187+
"prisma": {
188+
"seed": "tsx prisma/seed.ts"
189+
},
190+
//add-end
191+
"dependencies": {
192+
"@hono/node-server": "^1.19.5",
193+
"@prisma/client": "^6.16.3",
194+
"@prisma/extension-accelerate": "^2.0.2",
195+
"dotenv": "^17.2.3",
196+
"hono": "^4.9.9"
197+
},
198+
"devDependencies": {
199+
"@types/node": "^20.11.17",
200+
"prisma": "^6.16.3",
201+
"tsx": "^4.20.6",
202+
"typescript": "^5.8.3"
203+
}
204+
}
205+
```
206+
207+
Run the seed script:
208+
209+
```terminal
210+
npx prisma db seed
211+
```
212+
213+
And open Prisma Studio to inspect your data:
214+
215+
```terminal
216+
npx prisma studio
217+
```
218+
219+
## 3. Integrate Prisma into Hono
220+
221+
### 3.1. Create a Prisma middleware
222+
223+
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. Set up the Prisma client like this:
224+
225+
<TabbedContent code>
226+
<TabItem value="Prisma Postgres (recommended)">
227+
228+
```tsx file=src/lib/prisma.ts
229+
import type { Context, Next } from 'hono';
230+
import { PrismaClient } from '../generated/prisma/client.js';
231+
import { withAccelerate } from '@prisma/extension-accelerate';
232+
233+
function withPrisma(c: Context, next: Next) {
234+
if (!c.get('prisma')) {
235+
const databaseUrl = process.env.DATABASE_URL;
236+
237+
if (!databaseUrl) {
238+
throw new Error('DATABASE_URL is not set');
239+
}
240+
const prisma = new PrismaClient({ datasourceUrl: databaseUrl })
241+
.$extends(withAccelerate());
242+
243+
c.set('prisma', prisma);
244+
}
245+
return next();
246+
}
247+
export default withPrisma;
248+
```
249+
250+
</TabItem>
251+
252+
<TabItem value="Other databases">
253+
254+
```tsx file=src/lib/prisma.ts
255+
import type { Context, Next } from 'hono';
256+
import { PrismaClient } from '../generated/prisma/client.js';
257+
258+
const databaseUrl = process.env.DATABASE_URL;
259+
if (!databaseUrl) {
260+
throw new Error('DATABASE_URL is not set');
261+
}
262+
const prisma = new PrismaClient({ datasourceUrl: databaseUrl });
263+
264+
function withPrisma(c: Context, next: Next) {
265+
if (!c.get('prisma')) {
266+
c.set('prisma', prisma);
267+
}
268+
return next();
269+
}
270+
271+
export default withPrisma;
272+
```
273+
</TabItem>
274+
</TabbedContent>
275+
276+
:::warning
277+
We recommend using a connection pooler (like [Prisma Accelerate](https://www.prisma.io/accelerate)) to manage database connections efficiently.
278+
279+
If you choose not to use one, in long-lived environments (for example, a Node.js server) instantiate a single `PrismaClient` and reuse it across requests to avoid exhausting database connections. In serverless environments or when using a pooler (for example, Accelerate), creating a client per request is acceptable.
280+
:::
281+
282+
### 3.2 Environment Variables & Types
283+
284+
By default, Hono does not load any environment variables from a `.env`. `dotenv` handles this and will be read that file and expose them via `process.env`.
285+
286+
Edit the `src/index.ts` to import `dotenv` and call the `config` method on it.
287+
288+
```ts file=src/index.ts
289+
import { Hono } from 'hono';
290+
import { serve } from '@hono/node-server';
291+
292+
// Read .env and set variables to process.env
293+
import * as dotenv from 'dotenv';
294+
dotenv.config();
295+
```
296+
297+
Next, Hono needs additional types to to know that the `withPrisma` middleware will set a `prisma`
298+
key on the Hono Context
299+
300+
```ts file=src/index.ts
301+
import { Hono } from "hono";
302+
import { serve } from "@hono/node-server";
303+
// add-next-line
304+
import type { PrismaClient } from "./generated/prisma/client.js";
305+
306+
import * as dotenv from "dotenv";
307+
dotenv.config();
308+
309+
// add-start
310+
type ContextWithPrisma = {
311+
Variables: {
312+
prisma: PrismaClient;
313+
};
314+
};
315+
// add-end
316+
317+
// edit-next-line
318+
const app = new Hono<ContextWithPrisma>();
319+
320+
app.get("/", (c) => {
321+
return c.text("Hello Hono!");
322+
});
323+
324+
serve(
325+
{
326+
fetch: app.fetch,
327+
port: 3000,
328+
},
329+
(info) => {
330+
console.log(`Server is running on http://localhost:${info.port}`);
331+
}
332+
);
333+
```
334+
335+
If using Cloudflare Workers, the environment variables will automatically be set to Hono's contenxt,
336+
so `dotenv` can be skipped.
337+
338+
339+
### 3.3. Create A GET Route
340+
341+
Fetch data from the database using Hono's `app.get` function. This will perform any database queries
342+
and return the data as JSON.
343+
344+
Create a new route inside of `src/index.ts`:
345+
346+
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:
347+
348+
```ts file=src/index.ts
349+
import withPrisma from './lib/prisma.js';
350+
351+
app.get('/users', withPrisma, async (c) => {
352+
const prisma = c.get('prisma');
353+
const users = await prisma.user.findMany({
354+
include: { posts: true },
355+
});
356+
return c.json({ users });
357+
});
358+
```
359+
360+
361+
### 3.4. Display The Data
362+
363+
Start the Hono app by call the `dev` script in the `package.json`
364+
365+
```terminal
366+
npm run dev
367+
```
368+
369+
There should be a "Server is running on http://localhost:3000" log printed out. From here, the data
370+
can be viewed by visting `http://localhost:3000/users` or by running `curl` from the command line
371+
372+
```terminal
373+
curl http://localhost:3000/users | jq
374+
```
375+
376+
You're done! You've created a Hono app with Prisma that's connected to a Prisma Postgres database.
377+
For next steps there are some resources below for you to explore as well as next steps for expanding
378+
your project.
379+
380+
## Next Steps
381+
382+
Now that you have a working Hono app connected to a Prisma Postgres database, you can:
383+
384+
- Extend your Prisma schema with more models and relationships
385+
- Add create/update/delete routes and forms
386+
- Explore authentication and validation
387+
- Enable query caching with [Prisma Postgres](/postgres/database/caching) for better performance
388+
389+
### More Info
390+
391+
- [Prisma Documentation](/orm/overview/introduction)
392+
- [Hono Documentation](https://hono.dev/docs/)

0 commit comments

Comments
 (0)