diff --git a/.env.example b/.env.example index 6e20640..9b464f3 100644 --- a/.env.example +++ b/.env.example @@ -14,6 +14,7 @@ DB_NAME=omnichannel FRONTEND_URL=http://localhost:3000 JWT_SECRET=change-this-long-random-secret JWT_EXPIRES_IN=8h +LOG_LEVEL=info # Auth providers: ldap,microsoft or only one of them AUTH_PROVIDERS=ldap,microsoft diff --git a/src/infra/config/env.ts b/src/infra/config/env.ts new file mode 100644 index 0000000..4ade43a --- /dev/null +++ b/src/infra/config/env.ts @@ -0,0 +1,49 @@ +export interface DatabaseConfig { + host: string; + port: number; + user: string; + password: string; + database: string; +} + +const REQUIRED_ENV = ['DB_HOST', 'DB_PORT', 'DB_USER', 'DB_PASSWORD', 'DB_NAME', 'JWT_SECRET']; + +export function validateAppEnv() { + const missing = REQUIRED_ENV.filter((name) => !String(process.env[name] || '').trim()); + + if (missing.length) { + throw new Error(`Variaveis de ambiente obrigatorias ausentes: ${missing.join(', ')}`); + } + + getNumberEnv('DB_PORT'); +} + +export function getDatabaseConfig(): DatabaseConfig { + return { + host: getRequiredEnv('DB_HOST'), + port: getNumberEnv('DB_PORT'), + user: getRequiredEnv('DB_USER'), + password: getRequiredEnv('DB_PASSWORD'), + database: getRequiredEnv('DB_NAME'), + }; +} + +function getRequiredEnv(name: string) { + const value = String(process.env[name] || '').trim(); + + if (!value) { + throw new Error(`Variavel de ambiente obrigatoria ausente: ${name}`); + } + + return value; +} + +function getNumberEnv(name: string) { + const value = Number(getRequiredEnv(name)); + + if (!Number.isFinite(value)) { + throw new Error(`Variavel de ambiente invalida: ${name} deve ser numerica`); + } + + return value; +} diff --git a/src/infra/database/database.service.ts b/src/infra/database/database.service.ts index b00bb40..cb1bbe4 100644 --- a/src/infra/database/database.service.ts +++ b/src/infra/database/database.service.ts @@ -1,15 +1,10 @@ import { Injectable, OnModuleDestroy } from '@nestjs/common'; import { Pool, PoolClient, QueryResultRow } from 'pg'; +import { getDatabaseConfig } from '../config/env'; @Injectable() export class DatabaseService implements OnModuleDestroy { - private readonly pool = new Pool({ - host: process.env.DB_HOST || 'localhost', - port: Number(process.env.DB_PORT || 5432), - user: process.env.DB_USER || process.env.POSTGRES_USER, - password: process.env.DB_PASSWORD || process.env.POSTGRES_PASSWORD, - database: process.env.DB_NAME || process.env.POSTGRES_DB, - }); + private readonly pool = new Pool(getDatabaseConfig()); query(text: string, params?: unknown[]) { return this.pool.query(text, params); diff --git a/src/infra/shared/logger.ts b/src/infra/shared/logger.ts deleted file mode 100644 index ec86896..0000000 --- a/src/infra/shared/logger.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { Logger } from '@nestjs/common'; - -export const appLogger = new Logger('Application'); diff --git a/src/main.ts b/src/main.ts index 8e323f2..5581a8e 100644 --- a/src/main.ts +++ b/src/main.ts @@ -4,10 +4,12 @@ import { NestFactory } from '@nestjs/core'; import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger'; import { json, urlencoded } from 'express'; import { AppModule } from './app.module'; +import { validateAppEnv } from './infra/config/env'; import { loadEnv } from './infra/config/load-env'; async function bootstrap() { loadEnv(); + validateAppEnv(); const app = await NestFactory.create(AppModule, { bodyParser: false }); const frontendUrl = process.env.FRONTEND_URL || 'http://localhost:3000';