98 lines
3.1 KiB
TypeScript
98 lines
3.1 KiB
TypeScript
import { Injectable, OnModuleDestroy, OnModuleInit } from '@nestjs/common';
|
|
import { ConfigService } from '@nestjs/config';
|
|
import { drizzle } from 'drizzle-orm/node-postgres';
|
|
import { Pool } from 'pg';
|
|
import * as schema from './schema';
|
|
import { runMigrations } from './migrations/migrate';
|
|
|
|
@Injectable()
|
|
export class DatabaseService implements OnModuleInit, OnModuleDestroy {
|
|
private readonly pool: Pool;
|
|
private readonly db: ReturnType<typeof drizzle>;
|
|
|
|
constructor(private configService: ConfigService) {
|
|
// Create the PostgreSQL pool
|
|
const connectionString = this.getDatabaseConnectionString();
|
|
this.pool = new Pool({
|
|
connectionString,
|
|
});
|
|
|
|
// Create the Drizzle ORM instance
|
|
this.db = drizzle(this.pool, { schema });
|
|
}
|
|
|
|
async onModuleInit() {
|
|
// Log database connection
|
|
console.log('Connecting to database...');
|
|
|
|
// Test the connection
|
|
try {
|
|
const client = await this.pool.connect();
|
|
try {
|
|
await client.query('SELECT NOW()');
|
|
console.log('Database connection established successfully');
|
|
} finally {
|
|
client.release();
|
|
}
|
|
} catch (error) {
|
|
console.error('Failed to connect to database:', error.message);
|
|
throw error;
|
|
}
|
|
|
|
// Run migrations in all environments
|
|
const result = await runMigrations({ migrationsFolder: './src/database/migrations/sql' });
|
|
|
|
// In production, we want to fail if migrations fail
|
|
if (!result.success && this.configService.get('NODE_ENV') === 'production') {
|
|
throw result.error;
|
|
}
|
|
}
|
|
|
|
async onModuleDestroy() {
|
|
// Close the database connection
|
|
await this.pool.end();
|
|
console.log('Database connection closed');
|
|
}
|
|
|
|
// Get the database connection string from environment variables
|
|
private getDatabaseConnectionString(): string {
|
|
// First try to get the full DATABASE_URL
|
|
const databaseUrl = this.configService.get<string>('DATABASE_URL');
|
|
if (databaseUrl) {
|
|
return databaseUrl;
|
|
}
|
|
|
|
// If DATABASE_URL is not provided, construct it from individual variables
|
|
const password = this.configService.get<string>('POSTGRES_PASSWORD');
|
|
const username = this.configService.get<string>('POSTGRES_USER');
|
|
const host = this.configService.get<string>('POSTGRES_HOST');
|
|
const port = this.configService.get<string>('POSTGRES_PORT');
|
|
const database = this.configService.get<string>('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) {
|
|
throw new Error(
|
|
`Database configuration is missing. Missing variables: ${missingVars.join(', ')}. Please check your .env file.`,
|
|
);
|
|
}
|
|
|
|
return `postgres://${username}:${password}@${host}:${port}/${database}`;
|
|
}
|
|
|
|
// Get the Drizzle ORM instance
|
|
getDb() {
|
|
return this.db;
|
|
}
|
|
|
|
// Get the PostgreSQL pool
|
|
getPool() {
|
|
return this.pool;
|
|
}
|
|
}
|