nestjs-prisma
website·Indexed 32 days ago
https://nestjs-prisma.dev/Easy Prisma support for NestJS applications. Provides tools for automatic installation via the nest add command, PrismaService and PrismaModule configuration, exception filters for PrismaClientKnownRequestError, and support for Rust-free Prisma Client (v6.16.0+). Includes documentation on Prisma Client Extensions, query logging, and custom service generation.
What's inside nestjs-prisma
- nestjs-prisma provides a way to make the PrismaClient available within the NestJS dependency injection (DI) system, allowing for easier database access across services and controllers.
Handle Prisma Client errors with PrismaClientExceptionFilter
The
PrismaClientExceptionFiltercatches unhandledPrismaClientKnownRequestErrorand maps them to appropriate HTTP status codes. It is compatible with REST (Express/Fastify) and GraphQL. By default, it maps the following error codes:- P2000 (Value too long): 400 Bad Request
- P2002 (Unique constraint failed): 409 Conflict
- P2025 (Record not found): 404 Not Found
Use PrismaService for database access
InjectPrismaServiceinto controllers, resolvers, services, or guards to interact with the database.PrismaServiceexposes all methods and arguments of the generatedPrismaClient.import { Injectable } from '@nestjs/common'; import { PrismaService } from 'nestjs-prisma'; @Injectable() export class AppService { constructor(private prisma: PrismaService) {} users() { return this.prisma.user.findMany(); } user(userId: string) { return this.prisma.user.findUnique({ where: { id: userId }, }); } }Implement CustomPrismaClientFactory for extended clients
To useuseClassfor registration, create a service that implementsCustomPrismaClientFactoryand provide the specific type of your extended Prisma client.import { Injectable } from '@nestjs/common'; import { CustomPrismaClientFactory } from 'nestjs-prisma'; import { type ExtendedPrismaClient, extendedPrismaClient } from './prisma.extension'; @Injectable() export class ExtendedPrismaConfigService implements CustomPrismaClientFactory<ExtendedPrismaClient> { createPrismaClient(): ExtendedPrismaClient { return extendedPrismaClient; } }Generate a custom PrismaService and PrismaModule
Use the--addPrismaServiceflag during the installation ofnestjs-prismato generate a localPrismaServiceandPrismaModule. This allows for further customizations of the Prisma integration within the project. After generating these local files, it is recommended to removenestjs-prismafrom your dependencies to avoid duplicate import suggestions for the service and module.nest add nestjs-prisma -- --addPrismaServiceAutomatically install nestjs-prisma using Nest CLI
Use thenest addcommand to automatically set up thenestjs-prismalibrary, Prisma, and Docker (optionally) within your project.nest add nestjs-prismaInject and use the extended Prisma Client in services
InjectCustomPrismaServiceusing the name provided during registration (e.g., 'PrismaService'). Pass theExtendedPrismaClienttype toCustomPrismaServiceto enable type-safety for your custom extension methods.import { Inject, Injectable } from '@nestjs/common'; import { CustomPrismaService } from 'nestjs-prisma'; import { type ExtendedPrismaClient } from './prisma.extension'; @Injectable() export class AppService { constructor( @Inject('PrismaService') private prismaService: CustomPrismaService<ExtendedPrismaClient>, ) {} async getUser(email: string) { // Access custom extension method return this.prismaService.client.user.findByEmail(email); } }Configure PrismaModule asynchronously using a class
UsePrismaModule.forRootAsync()with theuseClassproperty to delegate configuration to a dedicated service. The service must implement thePrismaOptionsFactoryinterface and provide acreatePrismaOptions()method returningPrismaServiceOptions.// 1. Define the config service import { Injectable } from '@nestjs/common'; import { PrismaOptionsFactory, PrismaServiceOptions } from 'nestjs-prisma'; @Injectable() export class PrismaConfigService implements PrismaOptionsFactory { createPrismaOptions(): PrismaServiceOptions | Promise<PrismaServiceOptions> { return { prismaOptions: { log: ['info', 'query'], }, explicitConnect: true, }; } } // 2. Register in the module import { Module } from '@nestjs/common'; import { PrismaModule } from 'nestjs-prisma'; @Module({ imports: [ PrismaModule.forRootAsync({ isGlobal: true, useClass: PrismaConfigService, }), ], }) export class AppModule {}Manually install nestjs-prisma and Prisma
If you prefer a manual installation, first add thenestjs-prismalibrary to your NestJS application. Then, install the Prisma CLI as a development dependency and the Prisma Client as a production dependency, followed by initializing Prisma.# Install the library npm install nestjs-prisma # or yarn add nestjs-prisma # Setup Prisma npm i -D prisma npm install @prisma/client npx prisma initAutomate Prisma and Docker setup using nest-add
The
nestjs-prismaschematic automates the initial configuration of Prisma and Docker in a NestJS project. When executed, it performs the following actions:- Initializes Prisma with a specified datasource provider (e.g.,
npx prisma init). - Adds Prisma npm scripts and a seed script to
package.json. - Optionally generates a custom
PrismaServiceandPrismaModule. - Optionally creates a
Dockerfileanddocker-compose.yml. - Updates
tsconfig.build.jsonto exclude theprismadirectory from the build.
nest add nestjs-prisma- Initializes Prisma with a specified datasource provider (e.g.,
Bind PrismaClientExceptionFilter globally using APP_FILTER
You can bind thePrismaClientExceptionFilterglobally within a module using theAPP_FILTERtoken. This can be done via a factory function that injectsHttpAdapterHostor by using theprovidePrismaClientExceptionFilter()helper (available since v0.21.0-dev.0).// Option 1: Using APP_FILTER token import { Module } from '@nestjs/common'; import { APP_FILTER, HttpAdapterHost } from '@nestjs/core'; import { PrismaClientExceptionFilter } from 'nestjs-prisma'; @Module({ providers: [ { provide: APP_FILTER, useFactory: ({ httpAdapter }: HttpAdapterHost) => { return new PrismaClientExceptionFilter(httpAdapter); }, inject: [HttpAdapterHost], }, ], }) export class AppModule {} // Option 2: Using providePrismaClientExceptionFilter helper import { Module } from '@nestjs/common'; import { providePrismaClientExceptionFilter } from 'nestjs-prisma'; @Module({ providers: [providePrismaClientExceptionFilter()], }) export class AppModule {}Implement event-based logging for Prisma in NestJS
To enable event-based logging in Prisma, you must first configure the log level in thePrismaModuleoptions and then subscribe to the events using the$on()method via thePrismaServiceduring application bootstrap.// 1. Configure the log level in AppModule import { Module } from '@nestjs/common'; import { PrismaModule } from 'nestjs-prisma'; @Module({ imports: [ PrismaModule.forRoot({ prismaServiceOptions: { prismaOptions: { log: [ { emit: 'event', level: 'query', }, ], }, }, }), ], }) export class AppModule {} // 2. Subscribe to events in main.ts import { NestFactory } from '@nestjs/core'; import { AppModule } from './app.module'; import { PrismaService } from 'nestjs-prisma'; async function bootstrap() { const app = await NestFactory.create(AppModule); const prismaService: PrismaService = app.get(PrismaService); prismaService.$on('query', (event) => { console.log(event); }); await app.listen(process.env.PORT || 3000); } bootstrap();