generated from fahricansecer/boilerplate-be
Initial commit
This commit is contained in:
202
src/app.module.ts
Normal file
202
src/app.module.ts
Normal file
@@ -0,0 +1,202 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { ConfigModule, ConfigService } from '@nestjs/config';
|
||||
import { APP_FILTER, APP_GUARD, APP_INTERCEPTOR } from '@nestjs/core';
|
||||
import { ThrottlerModule, ThrottlerGuard } from '@nestjs/throttler';
|
||||
import { CacheModule } from '@nestjs/cache-manager';
|
||||
import { redisStore } from 'cache-manager-redis-yet';
|
||||
import { LoggerModule } from 'nestjs-pino';
|
||||
import {
|
||||
I18nModule,
|
||||
AcceptLanguageResolver,
|
||||
HeaderResolver,
|
||||
QueryResolver,
|
||||
} from 'nestjs-i18n';
|
||||
import * as path from 'path';
|
||||
|
||||
// Config
|
||||
import {
|
||||
appConfig,
|
||||
databaseConfig,
|
||||
jwtConfig,
|
||||
redisConfig,
|
||||
i18nConfig,
|
||||
featuresConfig,
|
||||
throttleConfig,
|
||||
} from './config/configuration';
|
||||
import { geminiConfig } from './modules/gemini/gemini.config';
|
||||
import { validateEnv } from './config/env.validation';
|
||||
|
||||
// Common
|
||||
import { GlobalExceptionFilter } from './common/filters/global-exception.filter';
|
||||
import { ResponseInterceptor } from './common/interceptors/response.interceptor';
|
||||
|
||||
// Database
|
||||
import { DatabaseModule } from './database/database.module';
|
||||
|
||||
// Modules
|
||||
import { AuthModule } from './modules/auth/auth.module';
|
||||
import { UsersModule } from './modules/users/users.module';
|
||||
import { AdminModule } from './modules/admin/admin.module';
|
||||
import { HealthModule } from './modules/health/health.module';
|
||||
import { GeminiModule } from './modules/gemini/gemini.module';
|
||||
|
||||
// Guards
|
||||
import {
|
||||
JwtAuthGuard,
|
||||
RolesGuard,
|
||||
PermissionsGuard,
|
||||
} from './modules/auth/guards';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
// Configuration
|
||||
ConfigModule.forRoot({
|
||||
isGlobal: true,
|
||||
validate: validateEnv,
|
||||
load: [
|
||||
appConfig,
|
||||
databaseConfig,
|
||||
jwtConfig,
|
||||
redisConfig,
|
||||
i18nConfig,
|
||||
featuresConfig,
|
||||
throttleConfig,
|
||||
geminiConfig,
|
||||
],
|
||||
}),
|
||||
|
||||
// Logger (Structured Logging with Pino)
|
||||
LoggerModule.forRootAsync({
|
||||
imports: [ConfigModule],
|
||||
inject: [ConfigService],
|
||||
useFactory: async (configService: ConfigService) => {
|
||||
return {
|
||||
pinoHttp: {
|
||||
level: configService.get('app.isDevelopment') ? 'debug' : 'info',
|
||||
transport: configService.get('app.isDevelopment')
|
||||
? {
|
||||
target: 'pino-pretty',
|
||||
options: {
|
||||
singleLine: true,
|
||||
},
|
||||
}
|
||||
: undefined,
|
||||
},
|
||||
};
|
||||
},
|
||||
}),
|
||||
|
||||
// i18n
|
||||
I18nModule.forRootAsync({
|
||||
useFactory: (configService: ConfigService) => ({
|
||||
fallbackLanguage: configService.get('i18n.fallbackLanguage', 'en'),
|
||||
loaderOptions: {
|
||||
path: path.join(__dirname, '/i18n/'),
|
||||
watch: configService.get('app.isDevelopment', true),
|
||||
},
|
||||
}),
|
||||
resolvers: [
|
||||
new HeaderResolver(['x-lang', 'accept-language']),
|
||||
new QueryResolver(['lang']),
|
||||
AcceptLanguageResolver,
|
||||
],
|
||||
inject: [ConfigService],
|
||||
}),
|
||||
|
||||
// Throttling
|
||||
ThrottlerModule.forRootAsync({
|
||||
inject: [ConfigService],
|
||||
useFactory: (configService: ConfigService) => [
|
||||
{
|
||||
ttl: configService.get('throttle.ttl', 60000),
|
||||
limit: configService.get('throttle.limit', 100),
|
||||
},
|
||||
],
|
||||
}),
|
||||
|
||||
// Caching (Redis with in-memory fallback)
|
||||
CacheModule.registerAsync({
|
||||
isGlobal: true,
|
||||
imports: [ConfigModule],
|
||||
useFactory: async (configService: ConfigService) => {
|
||||
const useRedis = configService.get('REDIS_ENABLED', 'false') === 'true';
|
||||
|
||||
if (useRedis) {
|
||||
try {
|
||||
const store = await redisStore({
|
||||
socket: {
|
||||
host: configService.get('redis.host', 'localhost'),
|
||||
port: configService.get('redis.port', 6379),
|
||||
},
|
||||
ttl: 60 * 1000, // 1 minute default
|
||||
});
|
||||
console.log('✅ Redis cache connected');
|
||||
return {
|
||||
store: store as unknown as any,
|
||||
ttl: 60 * 1000,
|
||||
};
|
||||
} catch {
|
||||
console.warn('⚠️ Redis connection failed, using in-memory cache');
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback to in-memory cache
|
||||
console.log('📦 Using in-memory cache');
|
||||
return {
|
||||
ttl: 60 * 1000,
|
||||
};
|
||||
},
|
||||
inject: [ConfigService],
|
||||
}),
|
||||
|
||||
// Database
|
||||
DatabaseModule,
|
||||
|
||||
// Core Modules
|
||||
AuthModule,
|
||||
UsersModule,
|
||||
AdminModule,
|
||||
|
||||
// Optional Modules (controlled by env variables)
|
||||
GeminiModule,
|
||||
HealthModule,
|
||||
],
|
||||
providers: [
|
||||
// Global Exception Filter
|
||||
{
|
||||
provide: APP_FILTER,
|
||||
useClass: GlobalExceptionFilter,
|
||||
},
|
||||
|
||||
// Global Response Interceptor
|
||||
{
|
||||
provide: APP_INTERCEPTOR,
|
||||
useClass: ResponseInterceptor,
|
||||
},
|
||||
|
||||
// Global Rate Limiting
|
||||
{
|
||||
provide: APP_GUARD,
|
||||
useClass: ThrottlerGuard,
|
||||
},
|
||||
|
||||
// Global JWT Auth Guard
|
||||
{
|
||||
provide: APP_GUARD,
|
||||
useClass: JwtAuthGuard,
|
||||
},
|
||||
|
||||
// Global Roles Guard
|
||||
{
|
||||
provide: APP_GUARD,
|
||||
useClass: RolesGuard,
|
||||
},
|
||||
|
||||
// Global Permissions Guard
|
||||
{
|
||||
provide: APP_GUARD,
|
||||
useClass: PermissionsGuard,
|
||||
},
|
||||
],
|
||||
})
|
||||
export class AppModule {}
|
||||
Reference in New Issue
Block a user