notiz-dev / nestjs-prisma

Easy Prisma support for your NestJS application
https://nestjs-prisma.dev
MIT License
570 stars 49 forks source link

Possibility to use extensions and this.prisma. #88

Closed famouzkk closed 7 months ago

famouzkk commented 8 months ago

Is it possible to use extensions and still access the Prisma client using this.prisma. instead of this.prisma.client.?

shreyassood commented 7 months ago

+1 would be great to have extensions support

marcjulian commented 7 months ago

@shreyassood Prisma extensions are already supported: https://nestjs-prisma.dev/docs/prisma-client-extensions/

@famouzkk I haven't found a way to make this possible.

The default PrismaService is extended by the PrismaClient

PrismaService

// simplified
import { Inject, Injectable, OnModuleInit, Optional } from '@nestjs/common';
import { Prisma, PrismaClient } from '@prisma/client';
import { PrismaServiceOptions } from './interfaces';
import { PRISMA_SERVICE_OPTIONS } from './prisma.constants';

@Injectable()
export class PrismaService extends PrismaClient {
  constructor(
    @Optional()
    @Inject(PRISMA_SERVICE_OPTIONS)
    private readonly prismaServiceOptions: PrismaServiceOptions = {},
  ) {
    super(prismaServiceOptions.prismaOptions);
  }
}

That allows to access this.prisma.MODEL_NAME directly

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

  users() {
    return this.prisma.user.findMany();
  }
}

However, with Prisma extensions it is not possible to extend the service with the applied extension. Open issue about this: https://github.com/prisma/prisma/issues/18628

My solution is to provide the Prisma Client with the extension via the CustomPrismaModule and exposing it as client property.

CustomPrismaService

@Injectable()
export class CustomPrismaService<Client extends PrismaClientLike> {
  constructor(
    @Inject(CUSTOM_PRISMA_CLIENT)
    public client: Client,
  ) {}
}

This approach requires to access the client this.prisma.client.MODEL_NAME

@Injectable()
export class AppService {
  constructor(
    // ✅ use `ExtendedPrismaClient` from extension for correct type-safety
    @Inject('PrismaService')
    private prisma: CustomPrismaService<ExtendedPrismaClient>,
  ) {}

  users() {
    return this.prisma.client.user.findMany();
  }
}

If you have a solution, I am always open for ideas or a PR.