From 72f3bb772364a6766d0c96df003345d3f2f11e99 Mon Sep 17 00:00:00 2001 From: Mathis HERRIOT <197931332+0x485254@users.noreply.github.com> Date: Mon, 5 Jan 2026 12:07:12 +0100 Subject: [PATCH] feat: implement database module and service with PostgreSQL integration and migrations support --- backend/src/database/database.module.ts | 10 +++ backend/src/database/database.service.ts | 86 ++++++++++++++++++++++++ 2 files changed, 96 insertions(+) create mode 100644 backend/src/database/database.module.ts create mode 100644 backend/src/database/database.service.ts diff --git a/backend/src/database/database.module.ts b/backend/src/database/database.module.ts new file mode 100644 index 0000000..a42c89f --- /dev/null +++ b/backend/src/database/database.module.ts @@ -0,0 +1,10 @@ +import { Module } from "@nestjs/common"; +import { ConfigModule } from "@nestjs/config"; +import { DatabaseService } from "./database.service"; + +@Module({ + imports: [ConfigModule], + providers: [DatabaseService], + exports: [DatabaseService], +}) +export class DatabaseModule {} diff --git a/backend/src/database/database.service.ts b/backend/src/database/database.service.ts new file mode 100644 index 0000000..e42c837 --- /dev/null +++ b/backend/src/database/database.service.ts @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2025 Yidhra Studio. - All Rights Reserved + * Updated : 25/04/2025 10:52 + * + * Unauthorized copying or redistribution of this file in source and binary forms via any medium + * is strictly prohibited. + */ + +import {Injectable, Logger, OnModuleDestroy, OnModuleInit} from "@nestjs/common"; +import { ConfigService } from "@nestjs/config"; +import { drizzle } from "drizzle-orm/node-postgres"; +import { migrate } from "drizzle-orm/node-postgres/migrator"; +import * as schema from "./schemas"; +import {Pool} from "pg"; + +@Injectable() +export class DatabaseService implements OnModuleInit, OnModuleDestroy { + private readonly logger = new Logger(DatabaseService.name); + private readonly pool!: Pool + public readonly db: ReturnType; + + constructor( + private configService: ConfigService + ) { + // Create the PostgreSQL client + const connectionString = this.getDatabaseConnectionString(); + this.pool = new Pool({ connectionString }); + // Recreate drizzle with initialized pool + this.db = drizzle(this.pool, { schema }); + + } + + async onModuleInit() { + try { + // Run migrations if in production mode + if (this.configService.get("NODE_ENV") === "production") { + this.logger.log("Running database migrations..."); + await migrate(this.db, { migrationsFolder: ".migrations" }); + this.logger.log("Database migrations completed successfully"); + } else { + this.logger.debug("Skipping migrations in non-production environment"); + } + this.logger.log("Database connection established successfully"); + } catch (error) { + this.logger.error("Failed to initialize database connection", error); + throw error; + } + } + + async onModuleDestroy() { + try { + // Close the database connection + await this.pool.end(); + this.logger.log("Database connection closed successfully"); + } catch (error) { + this.logger.error("Error closing database connection", error); + } + } + + // Get the database connection string from environment variables + private getDatabaseConnectionString(): string { + this.logger.debug('Getting database connection string from environment variables'); + + const password = this.configService.get("POSTGRES_PASSWORD"); + const username = this.configService.get("POSTGRES_USER"); + const host = this.configService.get("POSTGRES_HOST"); + const port = this.configService.get("POSTGRES_PORT"); + const database = this.configService.get("POSTGRES_DB"); + + const missingVars: string[] = []; + if (!password) missingVars.push("POSTGRES_PASSWORD"); + if (!username) missingVars.push("POSTGRES_USER"); + if (!host) missingVars.push("POSTGRES_HOST"); + if (!port) missingVars.push("POSTGRES_PORT"); + if (!database) missingVars.push("POSTGRES_DB"); + + if (missingVars.length > 0) { + const errorMessage = `Database configuration is missing. Missing variables: ${missingVars.join(", ")}. Please check your .env file.`; + this.logger.error(errorMessage); + throw new Error(errorMessage); + } + + this.logger.debug(`Database connection configured for ${username}@${host}:${port}/${database}`); + return `postgres://${username}:${password}@${host}:${port}/${database}`; + } +}