import { Module } from "@nestjs/common"; import { RouterModule } from "@nestjs/core"; import { ConfigModule, ConfigService } from "@nestjs/config"; import { ThrottlerModule } from "@nestjs/throttler"; import { AuthModule } from "./auth/auth.module"; import { UsersModule } from "./users/users.module"; import { MappingsModule } from "./mappings/mappings.module"; import { CatalogModule } from "./catalog/catalog.module"; import { OrdersModule } from "./orders/orders.module"; import { InvoicesModule } from "./invoices/invoices.module"; import { SubscriptionsModule } from "./subscriptions/subscriptions.module"; import { CasesModule } from "./cases/cases.module"; import { WebhooksModule } from "./webhooks/webhooks.module"; import { VendorsModule } from "./vendors/vendors.module"; import { JobsModule } from "./jobs/jobs.module"; import { HealthModule } from "./health/health.module"; import { EmailModule } from "./common/email/email.module"; import { PrismaModule } from "./common/prisma/prisma.module"; import { AuditModule } from "./common/audit/audit.module"; import { RedisModule } from "./common/redis/redis.module"; import { LoggingModule } from "./common/logging/logging.module"; import { CacheModule } from "./common/cache/cache.module"; import * as path from "path"; import { validateEnv } from "./common/config/env.validation"; // Support multiple .env files across environments and run contexts const repoRoot = path.resolve(__dirname, "../../../.."); const nodeEnv = process.env.NODE_ENV || "development"; const envFilePath = [ // Prefer repo root env files path.resolve(repoRoot, `.env.${nodeEnv}.local`), path.resolve(repoRoot, `.env.${nodeEnv}`), path.resolve(repoRoot, ".env.local"), path.resolve(repoRoot, ".env"), // Fallback to local working directory `.env.${nodeEnv}.local`, `.env.${nodeEnv}`, ".env.local", ".env", ]; @Module({ imports: [ // Configuration ConfigModule.forRoot({ isGlobal: true, envFilePath, validate: validateEnv, }), // Logging LoggingModule, // Rate limiting with environment-based configuration ThrottlerModule.forRootAsync({ imports: [ConfigModule], inject: [ConfigService], useFactory: (configService: ConfigService) => [ { ttl: configService.get("RATE_LIMIT_TTL", 60000), limit: configService.get("RATE_LIMIT_LIMIT", 100), }, // Stricter rate limiting for auth endpoints { ttl: configService.get("AUTH_RATE_LIMIT_TTL", 900000), limit: configService.get("AUTH_RATE_LIMIT_LIMIT", 3), name: "auth", }, ], }), // Core modules PrismaModule, RedisModule, CacheModule, AuditModule, VendorsModule, JobsModule, HealthModule, EmailModule, // Feature modules AuthModule, UsersModule, MappingsModule, CatalogModule, OrdersModule, InvoicesModule, SubscriptionsModule, CasesModule, WebhooksModule, // Route grouping: apply "/api" prefix to all feature modules except health RouterModule.register([ { path: "api", module: AuthModule }, { path: "api", module: UsersModule }, { path: "api", module: MappingsModule }, { path: "api", module: CatalogModule }, { path: "api", module: OrdersModule }, { path: "api", module: InvoicesModule }, { path: "api", module: SubscriptionsModule }, { path: "api", module: CasesModule }, { path: "api", module: WebhooksModule }, ]), ], }) export class AppModule {}