prisma/prisma

Types broken on void clients (no models)

NBMSacha opened this issue · 3 comments

Bug description

Due to the change introduced yesterday by #24160, void clients can now be created (yay!!). However, they aren't complete typescript-wise. The prismaClient.$extends API will throw typescript errors when used.

How to reproduce

Expected behavior

No response

Prisma information

// Add your schema.prisma
// Add your code using Prisma Client

Environment & setup

  • OS:
  • Database:
  • Node.js version:

Prisma Version


Hi @NBMSacha, can you please expand on this issue? Can you please paste the prismaClient.$extends API usage in which you see errors, and paste the error message as well?

I would also be beneficial if you please gave us more info for reproducing this, such as your Prisma schema. Thanks!

Sure!

Schema:

generator client {
    provider = "prisma-client-js"
    output   = "./generated/void"
}

datasource db {
    provider = "postgresql"
    url      = env("MAIN_DATABASE_URL")
}

Usecase:

return prismaClient.$extends({
      query: {
        $allModels: {
          // @ts-expect-error too powerful to type
          async update({model, args, query}) {
            return await prismaClient.$transaction(async prisma => {
              // @ts-expect-error too powerful to type
              const previousData = await prisma[model].findUnique({
                where: args.where,
              });

              if (!previousData) {
                throw new Error(
                  'Record to update not found, did you want to upsert?',
                );
              }

              const result = await query(args);

              const queryUnsafe = `INSERT INTO octoflow_${this.streamName}.logs (data, operation, table) VALUES (?, ?, ?, ?, ?)`;
              await prisma.$queryRawUnsafe(
                queryUnsafe,
                previousData,
                1,
                model,
                this.blockNumber,
                this.blockchain,
              );

              return result;
            });
          },

          // @ts-expect-error too powerful to type
          async create({model, args, query}) {
            return await prismaClient.$transaction(async prisma => {
              const result = await this.create(args);

              const queryUnsafe = `INSERT INTO octoflow_${this.streamName}.logs (data, operation, table) VALUES (?, ?, ?, ?, ?)`;
              await prisma.$queryRawUnsafe(
                queryUnsafe,
                result,
                0,
                model,
                this.blockNumber,
                this.blockchain,
              );

              return result;
            });
          },

          // @ts-expect-error too powerful to type
          async delete({model, args, query}) {
            return await prismaClient.$transaction(async prisma => {
              // @ts-expect-error too powerful to type
              const previousData = await prisma[model].findUnique({
                where: args.where,
              });

              const result = await query(args);

              if (previousData !== undefined) {
                const queryUnsafe = `INSERT INTO octoflow_${this.streamName}.logs (data, operation, table) VALUES (?, ?, ?, ?, ?)`;
                await prisma.$queryRawUnsafe(
                  queryUnsafe,
                  previousData,
                  2,
                  model,
                  this.blockNumber,
                  this.blockchain,
                );
              }

              return !!result;
            });
          },

          // @ts-expect-error too powerful to type
          async upsert({model, args, query}) {
            return await prismaClient.$transaction(async prisma => {
              // @ts-expect-error too powerful to type
              const previousData = await prisma[model].findUnique({
                where: args.where,
              });

              if (previousData) {
                const result = await this.update(args);
                const queryUnsafe = `INSERT INTO octoflow_${this.streamName}.logs (data, operation, table) VALUES (?, ?, ?, ?, ?)`;
                await prisma.$queryRawUnsafe(
                  queryUnsafe,
                  previousData,
                  1,
                  model,
                  this.blockNumber,
                  this.blockchain,
                );
                return result;
              } else {
                const result = await this.create(args);
                const queryUnsafe = `INSERT INTO octoflow_${this.streamName}.logs (data, operation, table) VALUES (?, ?, ?, ?, ?)`;
                await prisma.$queryRawUnsafe(
                  queryUnsafe,
                  result,
                  0,
                  model,
                  this.blockNumber,
                  this.blockchain,
                );
                return result;
              }
            });
          },

          // @ts-expect-error too powerful to type
          async updateMany({model, args, query}) {
            return await prismaClient.$transaction(async prisma => {
              // @ts-expect-error too powerful to type
              const previousData = await prisma[model].findMany({
                where: args.where,
              });

              const result = await query(args);

              if (previousData.length > 0) {
                const queryUnsafe = `INSERT INTO octoflow_${this.streamName}.logs (data, operation, table) VALUES (?, ?, ?, ?, ?)`;
                await prisma.$queryRawUnsafe(
                  queryUnsafe,
                  previousData,
                  1,
                  model,
                  this.blockNumber,
                  this.blockchain,
                );
              }

              return result;
            });
          },

          // @ts-expect-error too powerful to type
          async createMany({model, args, query}) {
            return await prismaClient.$transaction(async prisma => {
              const result = await query(args);

              const queryUnsafe = `INSERT INTO octoflow_${this.streamName}.logs (data, operation, table) VALUES (?, ?, ?, ?, ?)`;
              await prisma.$queryRawUnsafe(
                queryUnsafe,
                result,
                0,
                model,
                this.blockNumber,
                this.blockchain,
              );

              return result;
            });
          },

          // @ts-expect-error too powerful to type
          async deleteMany({model, args, query}) {
            return await prismaClient.$transaction(async prisma => {
              // @ts-expect-error too powerful to type
              const previousData = await prisma[model].findMany({
                where: args.where,
              });

              const result = await query(args);

              if (previousData.length > 0) {
                const queryUnsafe = `INSERT INTO octoflow_${this.streamName}.logs (data, operation, table) VALUES (?, ?, ?, ?, ?)`;
                await prisma.$queryRawUnsafe(
                  queryUnsafe,
                  previousData,
                  2,
                  model,
                  this.blockNumber,
                  this.blockchain,
                );
              }

              return result;
            });
          },
        },
      },
    });

Without the "ts-expect-error" flag, we're getting an issue claiming that "update" and all the other methods shouldn't be there!

I have the same problem, typescript doesn't work anymore!