Building a REST API with NestJS and Prisma. A Complete Guide

nestjsnodejsprisma
Elvis Duru

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:

  1. Introduction: We discussed the purpose of the article and the technologies we will be using.
  2. Setting up a NestJS project: We set up a new Nest.js project and discussed the structure of the project.
  3. 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.
  4. 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.
  5. 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

Get the latest articles, in your inbox

Every couple of weeks, I share the best content from my blog. It's short, sweet, and practical. I'd love you to join. You may opt out at any time.