Files
Game_Calendar_BE/src/database/prisma.service.ts
Harun CAN 8674911033
All checks were successful
CI / build (push) Successful in 2m23s
main
2026-01-30 02:52:42 +03:00

135 lines
3.4 KiB
TypeScript

import {
Injectable,
OnModuleInit,
OnModuleDestroy,
Logger,
} from '@nestjs/common';
import { PrismaClient } from '@prisma/client';
// Models that support soft delete
const SOFT_DELETE_MODELS = ['user', 'role', 'tenant'];
// Type for Prisma model delegate with common operations
interface PrismaDelegate {
delete: (args: { where: Record<string, unknown> }) => Promise<unknown>;
findMany: (args?: Record<string, unknown>) => Promise<unknown[]>;
update: (args: {
where: Record<string, unknown>;
data: Record<string, unknown>;
}) => Promise<unknown>;
}
@Injectable()
export class PrismaService
extends PrismaClient
implements OnModuleInit, OnModuleDestroy
{
private readonly logger = new Logger(PrismaService.name);
constructor() {
super({
log: [
{ emit: 'event', level: 'query' },
{ emit: 'event', level: 'error' },
{ emit: 'event', level: 'warn' },
],
});
}
async onModuleInit() {
this.logger.log(
`Connecting to database... URL: ${process.env.DATABASE_URL?.split('@')[1]}`,
); // Mask password
try {
await this.$connect();
this.logger.log('✅ Database connected successfully');
} catch (error) {
this.logger.error(
`❌ Database connection failed: ${error.message}`,
error.stack,
);
throw error;
}
}
async onModuleDestroy() {
await this.$disconnect();
this.logger.log('🔌 Database disconnected');
}
/**
* Check if model has soft delete (deletedAt field)
*/
hasSoftDelete(model: string | undefined): boolean {
return model ? SOFT_DELETE_MODELS.includes(model.toLowerCase()) : false;
}
/**
* Hard delete - actually remove from database
*/
hardDelete<T>(model: string, where: Record<string, unknown>): Promise<T> {
const delegate = this.getModelDelegate(model);
return delegate.delete({ where }) as Promise<T>;
}
/**
* Find including soft deleted records
*/
findWithDeleted<T>(
model: string,
args?: Record<string, unknown>,
): Promise<T[]> {
const delegate = this.getModelDelegate(model);
return delegate.findMany(args) as Promise<T[]>;
}
/**
* Restore a soft deleted record
*/
restore<T>(model: string, where: Record<string, unknown>): Promise<T> {
const delegate = this.getModelDelegate(model);
return delegate.update({
where,
data: { deletedAt: null },
}) as Promise<T>;
}
/**
* Soft delete - set deletedAt to current date
*/
softDelete<T>(model: string, where: Record<string, unknown>): Promise<T> {
const delegate = this.getModelDelegate(model);
return delegate.update({
where,
data: { deletedAt: new Date() },
}) as Promise<T>;
}
/**
* Find many excluding soft deleted records
*/
findManyActive<T>(
model: string,
args?: Record<string, unknown>,
): Promise<T[]> {
const delegate = this.getModelDelegate(model);
const whereWithDeleted = {
...args,
where: {
...(args?.where as Record<string, unknown> | undefined),
deletedAt: null,
},
};
return delegate.findMany(whereWithDeleted) as Promise<T[]>;
}
/**
* Get Prisma model delegate by name
*/
private getModelDelegate(model: string): PrismaDelegate {
const modelKey = model.charAt(0).toLowerCase() + model.slice(1);
return (this as any)[modelKey] as PrismaDelegate;
}
}