How to use Prisma in NestJS

The ultimate tutorial to get started with Prisma and NestJs.

Vladimir Agaev

Posted August 18, 2022

7 min read

Learn NestJs the right way

Skyrocket your NestJs skills to the top

with Vladimir Agaev
Full Stack Developer
  • checkNestJs Architecture
  • checkSessions
  • checkCaching
  • checkPagination
  • checkScaling with Redis
  • checkUnit Testing
  • checkRBAC & CronJobs

With the advent of modern web development, even SQL and traditional ORMs are not protected from disruption. Prisma is a next-generation ORM that has been taking backend by storm.

What is Prisma

Prisma is a next-generation ORM for NodeJs that works flawlessly with Typescript. It is somewhere in between a traditional ORM and a query builder. The main selling point is that Prisma can automatically generate types when the database model changes. This is a game changer! No need to maintain classes that map to data or write complex SQL.

Prisma and NestJs are probably my favourite backend technologies in the NodeJs ecosystem, and I am excited to show you how to use them together!

Installation & Setup

Once your NestJs project is set up, you must install the Prisma CLI and the Prisma client.

npm i -D prisma
npm i @prisma/client

Once the installation is complete, you need to initialize the Prisma initial configuration.

npx prisma init

This should create a Prisma folder and a .env file.

If you open the .env file, you will see a Postgres connection string.

DATABASE_URL=postgresql://johndoe:randompassword@localhost:5432/mydb?schema=public

In this tutorial, we will use SQLite. So rename the connection string to cats.sqlite.

.env
DATABASE_URL="file:./cats.sqlite"

Create Prisma Cat Model

If you open the Prisma folder, you will find a schema file. This schema stores all your database models. Database models represent your database's tables with their values.

In this tutorial, we are going to create a Cat table with fields:

  • id
  • name
  • breed
  • createdAt
  • updatedAt

Open your prisma.schema file and fill it with the model below

prisma.schema
generator client {
  provider = "prisma-client-js"
}
datasource db {
  provider = "postgresql" // the database we use
  url      = env("DATABASE_URL") // database connectiong string
}
model Cat {
  id        Int      @id @default(autoincrement())
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt
  name      String
  breed     String
  @@map("cat")
}

Create Prisma Migrations

To create the table "Cat", we must create migrations and apply them to the database. When you develop, this can be easily done with

npx prisma migrate dev --name add_cat_table

If you omit the "name" argument, Prisma will prompt you to enter one. Every migration is timestamped and suffixed with the name you give it.

.
├── migrations
│   ├── 20220801004112_init
│   │   └── migration.sql
│   └── migration_lock.toml
└── schema.prisma

When you create migrations, Prisma also runs the generate command that generates typescript types.

NB: This command can also be individually executed with

npx prisma generate

This way, you can use the model types in your project. You can find the generated types in node_modules/.prisma/index.d.ts

node_modules/.prisma/index.d.ts
export type Cat = {
  id: number
  createdAt: Date
  updatedAt: Date
  name: string
  breed: string
}

Create Prisma Service

The easiest way to use Prisma in our NestJs application is to include it in a service/provider that can be injected as a dependency injection.

.
├── app.module.ts
├── main.ts
└── prisma
    ├── prisma.module.ts
    └── prisma.service.ts
prisma.service.ts
import { Module } from '@nestjs/common';
import { PrismaService } from './prisma.service';

@Global()
@Module({
  providers: [PrismaService],
  exports: [PrismaService],
})
export class PrismaModule {}

NB: We make the PrismaModule global. This way, the PrismaService can be easily used in all our application

Create Cat Service

We will create two functions to demonstrate that our connection to Prisma works.

  • addCat: will create a can in the database
  • getCat: will get and return a cat by its id
cat.service.ts
import { Injectable } from '@nestjs/common';
import { PrismaService } from '../prisma/prisma.service';

@Injectable()
export class CatService {
  constructor(private prisma: PrismaService) {}

  async addCat(name: string, breed: string) {
    const cat = await this.prisma.cat.create({
      data: {
        name,
        breed,
      },
    });
    return cat;
  }
  async getCat(catId: number) {
    const cat = await this.prisma.cat.findUnique({
      where: {
        id: catId,
      },
    });
    return cat;
  }
}

Configure NestJs Repl

Starting from NestJs v9, we can use the REPL to programmatically call a function in our app without writing custom scripts or tests.

To use the REPL, you first need to create the REPL bootstrap file.

.
├── app.module.ts
├── cat
│   ├── cat.module.ts
│   └── cat.service.ts
├── main.ts
├── prisma
│   ├── prisma.module.ts
│   └── prisma.service.ts
└── repl.ts
repl.ts
import { repl } from '@nestjs/core';
import { AppModule } from './app.module';

async function bootstrap() {
  await repl(AppModule);
}

bootstrap();

To run start our app with repl you can run the following script

npm run start:dev -- --entryFile repl

The terminal should start with no errors

[14:13:32] Starting compilation in watch mode...

[14:13:33] Found 0 errors. Watching for file changes.

[Nest] 13365  - 18/08/2022, 14:13:33     LOG [NestFactory] Starting Nest application...
[Nest] 13365  - 18/08/2022, 14:13:33     LOG [InstanceLoader] AppModule dependencies initialized
[Nest] 13365  - 18/08/2022, 14:13:33     LOG [InstanceLoader] PrismaModule dependencies initialized
[Nest] 13365  - 18/08/2022, 14:13:33     LOG [InstanceLoader] CatModule dependencies initialized
[Nest] 13365  - 18/08/2022, 14:13:33     LOG REPL initialized
>

Test with NestJs REPL

Create a cat record

While you are in REPL you can use the debug() function to get an understand of the available functions you have at your disposal. The syntax is similar to jQuery

Now call debug() function to see what classes you can call

> debug()
AppModule:
PrismaModule:
 - providers:
  ◻ PrismaService
CatModule:
 - providers:
  ◻ CatService
>

You also have access to the global level await. No need to wrap the call in an async function.

> await $(CatService).getCat(1)
null
>

Let's create a cat record by calling the addCat() function

> await $(CatService).addCat("Salem", "American Shorthair")
{
  id: 1,
  createdAt: 2022-08-18T13:25:07.092Z,
  updatedAt: 2022-08-18T13:25:07.093Z,
  name: 'Salem',
  breed: 'American Shorthair'
}
>

Awesome! The record has been created in the database.

Get the cat record

Now let's get this record from the SQLite database by calling getCat() function.

> await $(CatService).getCat(1)
{
  id: 1,
  createdAt: 2022-08-18T13:25:07.092Z,
  updatedAt: 2022-08-18T13:25:07.093Z,
  name: 'Salem',
  breed: 'American Shorthair'
}

Awesome!

Summary

In this tutorial we have seen how to:

  • Use Prisma with NestJs and SQLite
  • Create Prisma models
  • Run Prisma migrations
  • Integrate Prisma with NestJs as a provider
  • Use the NestJs REPL to test our application

Learn NestJs the right way

Skyrocket your NestJs skills to the top

with Vladimir Agaev
Full Stack Developer
  • checkNestJs Architecture
  • checkSessions
  • checkCaching
  • checkPagination
  • checkScaling with Redis
  • checkUnit Testing
  • checkRBAC & CronJobs