import { Injectable, OnModuleInit, OnModuleDestroy } from '@nestjs/common'; import { PrismaClient, Prisma } from '@prisma/client'; // 定义事务客户端类型 export type TransactionClient = Omit< PrismaClient, '$connect' | '$disconnect' | '$on' | '$transaction' | '$use' | '$extends' >; @Injectable() export class PrismaService extends PrismaClient implements OnModuleInit, OnModuleDestroy { constructor() { super({ log: process.env.NODE_ENV === 'development' ? ['query', 'info', 'warn', 'error'] : ['error'], }); } async onModuleInit() { await this.$connect(); } async onModuleDestroy() { await this.$disconnect(); } /** * 执行数据库事务 * @param fn 事务回调函数 * @param options 事务选项 */ async executeTransaction( fn: (tx: TransactionClient) => Promise, options?: { maxWait?: number; timeout?: number; isolationLevel?: Prisma.TransactionIsolationLevel; }, ): Promise { return this.$transaction(fn, { maxWait: options?.maxWait ?? 5000, timeout: options?.timeout ?? 10000, isolationLevel: options?.isolationLevel ?? Prisma.TransactionIsolationLevel.ReadCommitted, }); } async cleanDatabase() { if (process.env.NODE_ENV !== 'test') { throw new Error('cleanDatabase can only be used in test environment'); } const tablenames = await this.$queryRaw< Array<{ tablename: string }> >`SELECT tablename FROM pg_tables WHERE schemaname='public'`; for (const { tablename } of tablenames) { if (tablename !== '_prisma_migrations') { await this.$executeRawUnsafe( `TRUNCATE TABLE "public"."${tablename}" CASCADE;`, ); } } } }