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.

Tokens
7.6K
Snippets
41
Records
47
Agent score
62%

What's inside nestjs-prisma

  1. Integrate PrismaClient into NestJS using 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.
  2. Handle Prisma Client errors with PrismaClientExceptionFilter

    The PrismaClientExceptionFilter catches unhandled PrismaClientKnownRequestError and 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
  3. Use PrismaService for database access

    Inject PrismaService into controllers, resolvers, services, or guards to interact with the database. PrismaService exposes all methods and arguments of the generated PrismaClient.
    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 },
        });
      }
    }
  4. Implement CustomPrismaClientFactory for extended clients

    To use useClass for registration, create a service that implements CustomPrismaClientFactory and 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;
      }
    }
  5. Generate a custom PrismaService and PrismaModule

    Use the --addPrismaService flag during the installation of nestjs-prisma to generate a local PrismaService and PrismaModule. This allows for further customizations of the Prisma integration within the project. After generating these local files, it is recommended to remove nestjs-prisma from your dependencies to avoid duplicate import suggestions for the service and module.
    nest add nestjs-prisma -- --addPrismaService
  6. Automatically install nestjs-prisma using Nest CLI

    Use the nest add command to automatically set up the nestjs-prisma library, Prisma, and Docker (optionally) within your project.
    nest add nestjs-prisma
  7. Inject and use the extended Prisma Client in services

    Inject CustomPrismaService using the name provided during registration (e.g., 'PrismaService'). Pass the ExtendedPrismaClient type to CustomPrismaService to 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);
      }
    }
  8. Configure PrismaModule asynchronously using a class

    Use PrismaModule.forRootAsync() with the useClass property to delegate configuration to a dedicated service. The service must implement the PrismaOptionsFactory interface and provide a createPrismaOptions() method returning PrismaServiceOptions.
    // 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 {}
  9. Manually install nestjs-prisma and Prisma

    If you prefer a manual installation, first add the nestjs-prisma library 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 init
  10. Automate Prisma and Docker setup using nest-add

    The nestjs-prisma schematic 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 PrismaService and PrismaModule.
    • Optionally creates a Dockerfile and docker-compose.yml.
    • Updates tsconfig.build.json to exclude the prisma directory from the build.
    nest add nestjs-prisma
  11. Bind PrismaClientExceptionFilter globally using APP_FILTER

    You can bind the PrismaClientExceptionFilter globally within a module using the APP_FILTER token. This can be done via a factory function that injects HttpAdapterHost or by using the providePrismaClientExceptionFilter() 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 {}
  12. Implement event-based logging for Prisma in NestJS

    To enable event-based logging in Prisma, you must first configure the log level in the PrismaModule options and then subscribe to the events using the $on() method via the PrismaService during 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();