question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Extending `PrismaClient` in custom service in a Nest.js application yields wrong typings for `PrismaClient.$on`

See original GitHub issue

Bug description

The code example showing how to integrate Prisma with Nest.js on the Prisma homepage does not behave correctly when attempting to access Prisma.$on('query', fn) within the service. Since the $on method infers its own typing from the constructor using it to listen to query events works only as long as a client is created inline:

const client = new PrismaClient({
  log: [
    { emit: 'event', level: 'query' },
    { emit: 'event', level: 'info' },
    { emit: 'event', level: 'warn' },
    { emit: 'event', level: 'error' }
  ],
});
client.$on('query', event => {}); // typings only work for as long as there is at least one `event` in the log options above.

Unfortunately when extending the client within a Nest.js application there is no way at all to nudge the typings into the right direction since they are not inferable.

@Injectable()
export class PrismaService extends PrismaClient {
  public constructor() {
    super({
      log: [
        { emit: 'event', level: 'query' },
        { emit: 'event', level: 'info' },
        { emit: 'event', level: 'warn' },
        { emit: 'event', level: 'error' }
      ],
    });
    // TS2345: Argument of type '"query"' is not assignable to parameter of type '"beforeExit"'
    this.$on('query', (e) => {});
  }
}

This can only be silenced using @ts-ignore and manually supplementing the type Prisma.QueryEvent for event but is prone to breaking changes and it looks suspicious. I’d like to understand how to work around this issue, since using the client within the application directly it not an option due to a lack of support for dependency injection and not being idiomatic in terms of working with the Repository pattern. Wrapping the client is also not an option breaking design patterns and paradigms.

How to reproduce

see above

Expected behavior

No response

Prisma information

not relevant

Environment & setup

not relevant

Prisma Version

not relevant

Issue Analytics

  • State:closed
  • Created a year ago
  • Comments:5 (1 by maintainers)

github_iconTop GitHub Comments

2reactions
ChristianIviceviccommented, Sep 6, 2022

I was able to reduce a bit of the redundancy, especially using typeof options as the argument for the generic as follows:

const options = {
  log: [
    { emit: 'event', level: 'query' } as const,
    { emit: 'event', level: 'info' } as const,
    { emit: 'event', level: 'warn' } as const,
    { emit: 'event', level: 'error' } as const
  ],
  errorFormat: process.env.NODE_ENV === 'production' ? ('minimal' as const) : ('pretty' as const)
};

@Injectable()
export class PrismaService extends PrismaClient<typeof options> {
  private readonly _logger = new Logger(PrismaService.name);

  public constructor() {
    super(options);

    this.$on('query', (e: Prisma.QueryEvent) => {
      this._logger.log(e.query);
    });
    this.$on('info', (e: Prisma.LogEvent) => {
      this._logger.log(e.message);
    });
    this.$on('warn', (e: Prisma.LogEvent) => {
      this._logger.warn(e.message);
    });
    this.$on('error', (e: Prisma.LogEvent) => {
      this._logger.error(e.message);
    });
  }

  public enableShutdownHooks(app: INestApplication) {
    this.$on('beforeExit', async () => {
      await app.close();
    });
  }
}
0reactions
millspcommented, Sep 15, 2022

I think this is a TypeScript limitation, take a look at this issue tracking this. I am therefore closing this issue, but do let me know if you need anything. @ChristianIvicevic’s solution looks like a good workaround in the meantime.

Read more comments on GitHub >

github_iconTop Results From Across the Web

[Feat]: CRUD Wrapper Service (Help, Idea, Problems ... - GitHub
I am using NestJS and need to develop a RESTful application. ... In this context, i suggest to extend the current prisma-client-js to...
Read more >
Operating against partial structures of your model types - Prisma
As a solution, you can customize the generated model type using Prisma Client's helper types. The User type only contains the model's scalar...
Read more >
Prisma | NestJS - A progressive Node.js framework
Nest is a framework for building efficient, scalable Node.js server-side applications. It uses progressive JavaScript, is built with TypeScript and combines ...
Read more >
How to use NestJS with Prisma - LogRocket Blog
This tutorial will explain Prisma's effectiveness with NestJS and demonstrate how to use Nest and Prisma together to build a REST API.
Read more >
I cloned TeamSeas.org using GraphQL, Prisma, NestJS ...
In this fullstack javascript tutorial we are going to try and clone the TeamSeas website using GraphQL, Prisma, NestJS, ReactJS, Chakra UI, ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found