import { Injectable, Logger, OnModuleDestroy, OnModuleInit } from "@nestjs/common"; import { PrismaClient } from "@prisma/client"; /** * Prisma service that manages database connection lifecycle * Extends PrismaClient to provide connection management and health checks */ @Injectable() export class PrismaService extends PrismaClient implements OnModuleInit, OnModuleDestroy { private readonly logger = new Logger(PrismaService.name); constructor() { super({ log: process.env.NODE_ENV === "development" ? ["query", "info", "warn", "error"] : ["error"], }); } /** * Connect to database when NestJS module initializes */ async onModuleInit() { try { await this.$connect(); this.logger.log("Database connection established"); } catch (error) { this.logger.error("Failed to connect to database", error); throw error; } } /** * Disconnect from database when NestJS module is destroyed */ async onModuleDestroy() { await this.$disconnect(); this.logger.log("Database connection closed"); } /** * Health check for database connectivity * @returns true if database is accessible, false otherwise */ async isHealthy(): Promise { try { await this.$queryRaw`SELECT 1`; return true; } catch (error) { this.logger.error("Database health check failed", error); return false; } } /** * Get database connection info for debugging * @returns Connection status and basic info */ async getConnectionInfo(): Promise<{ connected: boolean; database?: string; version?: string; }> { try { const result = await this.$queryRaw<{ current_database: string; version: string }[]>` SELECT current_database(), version() `; if (result.length > 0 && result[0]) { const dbVersion = result[0].version.split(" ")[0]; return { connected: true, database: result[0].current_database, ...(dbVersion && { version: dbVersion }), }; } return { connected: false }; } catch (error) { this.logger.error("Failed to get connection info", error); return { connected: false }; } } }