The goal of this lesson is to use your freshly gained knowledge about Prisma Client and use it to implement some routes of a REST API using Express.
You can continue working in the same prisma-workshop
project that you set up in lesson 1. However, the starter for this lesson is located in the rest-api
branch of the repo that you cloned.
Before you switch to that branch, you need to commit the current state of your project. For simplicity, you can use the stash
command to do this:
git stash
After you ran this command, you can switch to the rest-api
branch and delete the current migrations
directory and dev.db
file:
git checkout rest-api
rm -rf prisma/migrations
rm prisma/dev.db
Next, wipe your npm dependencies and re-install them to account for the new dependencies in package.json
:
rm -rf node_modules
npm install
The data model you will use here is very similar to the one that you created before, only the Post
model got extended with a few additional fields:
model User {
id Int @id @default(autoincrement())
email String @unique
name String?
posts Post[]
}
model Post {
id Int @id @default(autoincrement())
**createdAt DateTime @default(now())
updatedAt DateTime @updatedAt**
title String
content String?
published Boolean @default(false)
**viewCount Int @default(0)**
author User? @relation(fields: [authorId], references: [id])
authorId Int?
}
Since you are starting over with your Prisma setup, you have to recreate the database and its tables. Run the following command to do this:
npx prisma migrate dev --name init
Finally, you can seed the database with some sample data that's specified in the prisma/seed.ts
file. You can execute this seed script with this command:
npx prisma db seed --preview-feature
That's it, you're ready for your tasks now!
You can find the tasks for this lesson inside the src/index.ts
file marked with TODO
. Your goal is to insert the right Prisma Client queries for each REST API route.
Note that this is in not a lesson in API design and you should think more carefully about designing your API operations in a real-world application.
If you're using VS Code, you can install the REST Client extension and test your implementation using the provided HTTP calls in test.http
.
-
View a quick demo of the VS Code REST Client extension
Fetches all users.
-
Solution
app.get("/users", async (req, res) => { const result = await prisma.user.findMany() res.json(result) });
Creates a new user.
-
Solution
app.post(`/signup`, async (req, res) => { const { name, email } = req.body; const result = await prisma.user.create({ data: { name, email } }) res.json(result) });
Creates a new post.
-
Solution
app.post(`/post`, async (req, res) => { const { title, content, authorEmail } = req.body; const result = await prisma.post.create({ data: { title, content, author: { connect: { email: authorEmail } } } }) res.json(result) });
Increments the views of a post by 1.
-
Solution
app.put("/post/:id/views", async (req, res) => { const { id } = req.params; const result = await prisma.post.update({ where: { id: Number(id), }, data: { viewCount: { increment: 1, }, }, }); res.json(result); });
Publishes a post.
-
Solution
app.put("/publish/:id", async (req, res) => { const { id } = req.params; const result = await prisma.post.update({ where: { id: Number(id) }, data: { published: true, }, }); res.json(result); });
Fetches the unpublished posts of a specific user.
-
Solution
app.get("/user/:id/drafts", async (req, res) => { const { id } = req.params; const result = await prisma.user.findUnique({ where: { id: Number(id) }, }).posts({ where: { published: false } }) res.json(result) });
Fetches a post by its ID.
-
Solution
app.get(`/post/:id`, async (req, res) => { const { id } = req.params; const result = await prisma.post.findUnique({ where: { id: Number(id) }, }); res.json(result); });
Fetches all published posts and optionally paginates and/or filters them by checking whether the search string appears in either title or content.
-
Solution
app.get("/feed", async (req, res) => { const { searchString, skip, take } = req.query; const or = searchString ? { OR: [ { title: { contains: searchString as string } }, { content: { contains: searchString as string } }, ], } : {} const result = await prisma.post.findMany({ where: { published: true, ...or }, skip: Number(skip) || undefined, take: Number(take) || undefined, }); res.json(result); });