From 00df493623516fa87ca3eb6a7f3008ea039e57ef Mon Sep 17 00:00:00 2001 From: Morgan <33722304+ThyMinimalDev@users.noreply.github.com> Date: Tue, 14 Nov 2023 22:22:35 +0200 Subject: [PATCH] revert: "fix: create prisma client singleton with immediately invoked function" (#12366) --- apps/api/lib/helpers/customPrisma.ts | 49 ++++++--------- packages/prisma/index.ts | 94 ++++++++++++++++------------ 2 files changed, 73 insertions(+), 70 deletions(-) diff --git a/apps/api/lib/helpers/customPrisma.ts b/apps/api/lib/helpers/customPrisma.ts index db3ffe0c2f..926c7979cf 100644 --- a/apps/api/lib/helpers/customPrisma.ts +++ b/apps/api/lib/helpers/customPrisma.ts @@ -1,7 +1,7 @@ import type { NextMiddleware } from "next-api-middleware"; import { CONSOLE_URL } from "@calcom/lib/constants"; -import prisma, { customPrisma } from "@calcom/prisma"; +import { customPrisma } from "@calcom/prisma"; const LOCAL_CONSOLE_URL = process.env.NEXT_PUBLIC_CONSOLE_URL || CONSOLE_URL; @@ -12,41 +12,32 @@ export const customPrismaClient: NextMiddleware = async (req, res, next) => { } = req; // If no custom api Id is provided, attach to request the regular cal.com prisma client. if (!key) { - req.prisma = prisma; + req.prisma = customPrisma(); await next(); return; } - try { - // If we have a key, we check if the deployment matching the key, has a databaseUrl value set. - const databaseUrl = await fetch(`${LOCAL_CONSOLE_URL}/api/deployments/database?key=${key}`) - .then((res) => res.json()) - .then((res) => res.databaseUrl); + // If we have a key, we check if the deployment matching the key, has a databaseUrl value set. + const databaseUrl = await fetch(`${LOCAL_CONSOLE_URL}/api/deployments/database?key=${key}`) + .then((res) => res.json()) + .then((res) => res.databaseUrl); - if (!databaseUrl) { - res.status(400).json({ error: "no databaseUrl set up at your instance yet" }); - return; - } - req.prisma = customPrisma({ datasources: { db: { url: databaseUrl } } }); - /* @note: + if (!databaseUrl) { + res.status(400).json({ error: "no databaseUrl set up at your instance yet" }); + return; + } + req.prisma = customPrisma({ datasources: { db: { url: databaseUrl } } }); + /* @note: In order to skip verifyApiKey for customPrisma requests, we pass isAdmin true, and userId 0, if we detect them later, we skip verifyApiKey logic and pass onto next middleware instead. */ - req.isAdmin = true; - req.isCustomPrisma = true; - // We don't need the key from here and on. Prevents unrecognized key errors. - delete req.query.key; - await next(); - await req.prisma.$disconnect(); - // @ts-expect-error testing - delete req.prisma; - } catch (err) { - if (req.prisma) { - await req.prisma.$disconnect(); - // @ts-expect-error testing - delete req.prisma; - } - throw err; - } + req.isAdmin = true; + req.isCustomPrisma = true; + // We don't need the key from here and on. Prevents unrecognized key errors. + delete req.query.key; + await next(); + await req.prisma.$disconnect(); + // @ts-expect-error testing + delete req.prisma; }; diff --git a/packages/prisma/index.ts b/packages/prisma/index.ts index eec5d2c34f..b045ff8fb6 100644 --- a/packages/prisma/index.ts +++ b/packages/prisma/index.ts @@ -6,54 +6,66 @@ import { bookingReferenceMiddleware } from "./middleware"; const prismaOptions: Prisma.PrismaClientOptions = {}; +const globalForPrisma = global as unknown as { + prismaWithoutClientExtensions: PrismaClientWithoutExtension; + prismaWithClientExtensions: PrismaClientWithExtensions; +}; + if (!!process.env.NEXT_PUBLIC_DEBUG) prismaOptions.log = ["query", "error", "warn"]; +// Prevents flooding with idle connections +const prismaWithoutClientExtensions = + globalForPrisma.prismaWithoutClientExtensions || new PrismaClientWithoutExtension(prismaOptions); + export const customPrisma = (options?: Prisma.PrismaClientOptions) => new PrismaClientWithoutExtension({ ...prismaOptions, ...options }).$extends(withAccelerate()); -export const prisma = (function () { - // Prevents flooding with idle connections - const prismaWithoutClientExtensions = new PrismaClientWithoutExtension(prismaOptions); - // If any changed on middleware server restart is required - // TODO: Migrate it to $extends - bookingReferenceMiddleware(prismaWithoutClientExtensions); +// If any changed on middleware server restart is required +// TODO: Migrate it to $extends +bookingReferenceMiddleware(prismaWithoutClientExtensions); - // FIXME: Due to some reason, there are types failing in certain places due to the $extends. Fix it and then enable it - // Specifically we get errors like `Type 'string | Date | null | undefined' is not assignable to type 'Exact'` - const prismaWithClientExtensions = prismaWithoutClientExtensions - // - .$extends(withAccelerate()); - // .$extends({ - // query: { - // $allModels: { - // async $allOperations({ model, operation, args, query }) { - // const start = performance.now(); - // /* your custom logic here */ - // const res = await query(args); - // const end = performance.now(); - // logger.debug("Query Perf: ", `${model}.${operation} took ${(end - start).toFixed(2)}ms\n`); - // return res; - // }, - // }, - // }, - // }); - // .$extends({ - // name: "teamUpdateWithMetadata", - // query: { - // team: { - // async update({ model, operation, args, query }) { - // if (args.data.metadata) { - // // Prepare args.data with merged metadata - // } - // return query(args); - // }, - // }, - // }, - // }) - return prismaWithClientExtensions; -})(); +// FIXME: Due to some reason, there are types failing in certain places due to the $extends. Fix it and then enable it +// Specifically we get errors like `Type 'string | Date | null | undefined' is not assignable to type 'Exact'` +const prismaWithClientExtensions = prismaWithoutClientExtensions + // + .$extends(withAccelerate()); +// .$extends({ +// query: { +// $allModels: { +// async $allOperations({ model, operation, args, query }) { +// const start = performance.now(); +// /* your custom logic here */ +// const res = await query(args); +// const end = performance.now(); +// logger.debug("Query Perf: ", `${model}.${operation} took ${(end - start).toFixed(2)}ms\n`); +// return res; +// }, +// }, +// }, +// }); +// .$extends({ +// name: "teamUpdateWithMetadata", +// query: { +// team: { +// async update({ model, operation, args, query }) { +// if (args.data.metadata) { +// // Prepare args.data with merged metadata +// } +// return query(args); +// }, +// }, +// }, +// }) -export type PrismaClient = typeof prisma; +export const prisma = globalForPrisma.prismaWithClientExtensions || prismaWithClientExtensions; + +if (process.env.NODE_ENV !== "production") { + globalForPrisma.prismaWithoutClientExtensions = prismaWithoutClientExtensions; + globalForPrisma.prismaWithClientExtensions = prisma; +} + +type PrismaClientWithExtensions = typeof prismaWithClientExtensions; +export type PrismaClient = PrismaClientWithExtensions; export default prisma; export * from "./selects";