Building a REST API with NestJS and Prisma. A Complete Guide
Elvis Duru / January 22, 2023
12 min read • --- views
Introduction
Building a REST API is a crucial task for any developer who wants to create a web application. In this guide, we will be building a simple REST API for a blog using NestJS and Prisma. NestJS is a popular framework for building server-side applications with Node.js, and Prisma is an ORM (Object-Relational Mapping) tool that makes it easy to work with databases.
We will be building a REST API that allows users to perform CRUD (Create, Read, Update, Delete) operations on blog posts. Our API will have endpoints for creating new blog posts, reading existing blog posts, updating existing blog posts, and deleting blog posts.
In this guide, we will go over the process of setting up a NestJS project, connecting it to a SQLite database using Prisma, creating the REST API, and testing the API using Postman. By the end of this guide, you will have a solid understanding of how to build a REST API using NestJS and Prisma, and you will be able to use this knowledge to build your own web applications.
Before we get started, it's important to note that this guide assumes you have some prior knowledge of Node.js, JavaScript and basic knowledge of SQL. If you're new to these technologies, it's recommended that you take some time to familiarize yourself with them before proceeding. Additionally, this guide uses the TypeScript programming language, which is a typed version of JavaScript. If you're not familiar with TypeScript, don't worry - the concepts and code examples in this guide should still be easy to follow.
Now that we have a general understanding of what we'll be building, let's move on to setting up our NestJS project.
Setting up a NestJS project
The first step in building our REST API is to set up a new NestJS project. NestJS is a framework for building server-side applications with Node.js, and it provides a powerful set of tools for building scalable and maintainable applications. To get started with NestJS, we first need to install the NestJS CLI.
To install the NestJS CLI, open up your terminal and run the following command:
npm install -g @nestjs/cli
This will install the NestJS CLI globally on your system, allowing you to use the nest
command to create new projects and generate code.
Once the CLI is installed, we can create a new NestJS project by running the following command:
nest new project-name
This will create a new directory with the specified name, and it will contain all the necessary files and dependencies for a new NestJS project.
Once the project is created, the project structure should look like this:
project-name
|-- src
| |-- app.controller.ts
| |-- app.module.ts
| |-- app.service.ts
| |-- main.ts
|-- test
|-- .gitignore
|-- nest-cli.json
|-- package.json
|-- README.md
|-- tsconfig.build.json
|-- tsconfig.json
In this structure, you can see that NestJS has created a default src
directory which contains the main files of our application: app.controller.ts
, app.module.ts
, app.service.ts
, and main.ts
.
In this guide, we will be focusing on creating new files and directories within the src
folder to build our REST API.
Now that we have set up our NestJS project, we can proceed to the next step which is setting up Prisma and connecting it to the database.
Setting up Prisma
Now that we have set up our NestJS project, we can proceed to connecting it to a database using Prisma. Prisma is an ORM (Object-Relational Mapping) tool that makes it easy to work with databases. It provides a simple and powerful API for interacting with databases, and it also generates a set of CRUD (Create, Read, Update, Delete) operations for our entities automatically.
The first step in setting up Prisma is to install the Prisma CLI. To install the Prisma CLI, open up your terminal and run the following command:
npm install prisma --save-dev
Once the CLI is installed, we can now use it to initialize a new Prisma project by running the following command:
npx prisma init
This command will create a new directory named prisma
in your project, and it will contain all the necessary files for connecting to the database.
Next, we need to define our data model in the schema.prisma
file. It should look like this:
datasource db {
provider = "sqlite"
url = "file:./dev.db"
}
Then we can define our data model in the schema.prisma
file. It should look now like this:
datasource db {
provider = "sqlite"
url = "file:./dev.db"
}
model Post {
id Int @id @default(autoincrement())
title String
body String
}
Once we have setup the database connection and defined our data model, we can run a migration to create our database tables with Prisma Migrate by running the following command:
npx prisma migrate dev --name init
Note that this command also creates our SQLite database file dev.db
, in the path we specified in the datasource
block of our schema.
Next, we have to install and generate the Prisma Client. We can do both by running the following command:
npm install @prisma/client
This command will install and generate the Prisma Client in the node_modules/@prisma/client
directory, which we can use to interact with the database. Note that after making changes to the schema, you may have to run the npx prisma generate
command to regenerate the Prisma client.
Setting up the Prisma Service
Now that we have set up Prisma, we need to create a new service that will take care of instantiating the PrismaClient
and connecting to the database. To create the PrismaService
, run the following command:
nest g service Prisma
This command will generate a new file, prisma.service.ts
, in the src/prisma
directory.
In the prisma.service.ts
file, we will import PrismaClient
from the @prisma/client
package and OnModuleInit
from @nestjs/common
. We will extend the PrismaClient
and implement OnModuleInit
.
import { INestApplication, Injectable, OnModuleInit } from '@nestjs/common';
import { PrismaClient } from '@prisma/client';
@Injectable()
export class PrismaService extends PrismaClient implements OnModuleInit {
async onModuleInit() {
await this.$connect();
}
}
In this service, we have extended the PrismaClient
and implemented the OnModuleInit
lifecycle hook. The onModuleInit
method is called by Nest.js after the module is fully initialized, where we are calling the connect
method of the PrismaClient
. We have also created a new method enableShutdownHooks
which will handle the disconnection and destruction of the service when the application is closed. By using this PrismaService
, we can now easily connect to the database and use the PrismaClient
throughout our application.
Creating the REST API
With Prisma set up and connected to the database, we can now proceed to creating the REST API for our blog application. We will use Nest.js to create controllers that handle the different routes and handle HTTP requests.
To create a new controller, we can use the Nest.js CLI by running the following command:
nest g controller Post
This command will generate a new file, post.controller.ts
, in the src/post
directory.
In the post.controller.ts
file, we will import the Controller
decorator and the Get
, Post
, Put
and Delete
decorators from the @nestjs/common
package, as well as the PrismaService
.
We will use the @Controller
decorator to define the base route for our controller, and the @Get
, @Post
, @Put
and @Delete
decorators to define the routes for the different HTTP methods. We will also use the PrismaService
to interact with the database.
Here is an example of a basic Post
controller:
import { Controller, Get, Post, Put, Delete, Body } from '@nestjs/common';
import { PrismaService } from './prisma.service';
import { Post, Prisma } from '@prisma/client';
@Controller('post')
export class PostController {
constructor(private readonly prisma: Prisma) {}
@Get()
async findAll(): Promise<Post[]> {
return await this.prisma.post.findMany();
}
@Post()
async create(@Body() data: Prisma.PostCreateInput): Promise<Post> {
return await this.prisma.post.create({ data });
}
@Put(':id')
async update(@Param('id', ParseInt) id: number, @Body() data: Prisma.PostUpdateInput): Promise<Post> {
return await this.prisma.post.update({
where: { id },
data,
});
}
@Delete(':id')
async delete(@Param('id', ParseInt) id: number): Promise<Post> {
return await this.prisma.post.delete({
where: { id },
});
}
}
As you can see, we have defined routes for the basic CRUD operations using the @Get
, @Post
, @Put
, and @Delete
decorators, and we have also used Prisma
to interact with the database. We also imported the auto-generated Prisma types for the operations like Post[]
, Prisma.PostCreateInput
, Prisma.PostUpdateInput
and Post
and used them in the respective methods. Finally, we used the built-in ParseIntPipe
which is responsible for parsing a string into an integer value.
With this controller in place, we can now test our API using a tool like Postman in the next section. Additionally, by using the auto-generated types, we have the benefit of improved type safety and better code readability.
One important thing to note is that we are using the Prisma
client directly, instead of the PrismaService
that we created in the previous section. This is because the Prisma
client is injected into the PrismaService
and we can access it through the prisma
property of the PrismaService
. But in this example, we are injecting the Prisma
client directly in the constructor of the PostController
.
It's up to your preference how you want to use the Prisma client in your controllers, whether it be through the PrismaService
or directly. The important thing is that it is properly instantiated and connected to the database.
Another thing to note is that you could as well move all the business logic of the post resource into its own PostService
class. For simplicity, we just did it directly in the controller. In a larger project though, the former would be better.
In this section, we have gone through the process of creating the REST API for our blog application using Nest.js and Prisma. We have defined routes for the basic CRUD operations and used the auto-generated types provided by the Prisma client to improve type safety and code readability. With this API in place, we can now proceed to testing it using a tool like Postman.
Testing the REST API using Postman
Now that we have set up our REST API using Nest.js and Prisma, we can test it using a tool like Postman. Postman is a popular API development and testing tool that allows us to send HTTP requests to our API and view the responses.
To test our API using Postman, we first need to make sure our Nest.js server is running. You can start the Nest.js server by running the following command in the terminal:
npm run start:dev
Once the server is running, we can open Postman or any REST client and send HTTP requests to the different routes of our API.
For example, to test the GET
route for retrieving all posts, we can send a GET
request to http://localhost:3000/post
and we should receive a JSON response containing an array of all the posts in the database.
To test the POST
route for creating a new post, we can send a POST
request to http://localhost:3000/post
with a JSON body containing the data for the new post. We should receive a JSON response containing the newly created post.
We can also test the PUT
and DELETE
routes by sending PUT
and DELETE
requests respectively to http://localhost:3000/post/:id
with the appropriate JSON body and URL parameters.
It's important to note that before testing the routes, we need to have some data in the database. We can use the Prisma client or the playground to insert some data.
By testing our API using Postman, we can ensure that our routes are working as expected and that our API is properly handling requests and responding with the correct data.
In this section, we have gone through the process of testing our REST API using Postman. We have seen how to send different types of HTTP requests to our API and view the responses, and how to test that our routes are working as expected.
Conclusion
In this article, we have gone through the process of building a REST API for a blog application using Nest.js and Prisma. We have covered the following steps:
- Introduction: We discussed the purpose of the article and the technologies we will be using.
- Setting up a NestJS project: We set up a new Nest.js project and discussed the structure of the project.
- Setting up Prisma: We set up Prisma and connected it to a SQLite database. We also created a PrismaService that can be used throughout the application to interact with the database.
- Creating the REST API: We created controllers using Nest.js that handle the different routes of the API and interact with the database using Prisma.
- Testing the REST API using Postman: We tested the different routes of the API using Postman to ensure they were working as expected.
By following this guide, you should now have a good understanding of how to build a REST API using Nest.js and Prisma. You should also have a solid foundation to build upon and create more complex and feature-rich APIs.
It's worth noting that the example provided here is a simple one and there are many more things that can be done with Nest.js and Prisma. For example, you can use Nest.js pipes to validate inputs, use guards to handle authentication and authorization, and use interceptors to handle cross-cutting concerns like logging and error handling. Additionally, Prisma provides many advanced features like subscriptions, batching, and pagination that can be implemented to improve the performance and scalability of the API.
In conclusion, Nest.js and Prisma are powerful tools that can be used together to create robust and scalable APIs. With Nest.js providing the structure and routing capabilities and Prisma providing the database connectivity and ORM capabilities, developers can focus on building the business logic and features of their application.
Further reading
Building a REST API with NestJS, MongoDB, and Mongoose: A Complete Guide NestJS JWT Authentication with Refresh Tokens Complete Guide