generated from fahricansecer/boilerplate-be
243 lines
6.6 KiB
TypeScript
243 lines
6.6 KiB
TypeScript
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 { BullModule } from '@nestjs/bullmq';
|
||
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';
|
||
|
||
// Video SaaS Modules
|
||
import { ProjectsModule } from './modules/projects/projects.module';
|
||
import { VideoQueueModule } from './modules/video-queue/video-queue.module';
|
||
import { VideoAiModule } from './modules/video-ai/video-ai.module';
|
||
import { StorageModule } from './modules/storage/storage.module';
|
||
import { BillingModule } from './modules/billing/billing.module';
|
||
import { XTwitterModule } from './modules/x-twitter/x-twitter.module';
|
||
import { EventsModule } from './modules/events/events.module';
|
||
import { RenderCallbackModule } from './modules/render-callback/render-callback.module';
|
||
import { DashboardModule } from './modules/dashboard/dashboard.module';
|
||
import { NotificationsModule } from './modules/notifications/notifications.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,
|
||
],
|
||
}),
|
||
|
||
// BullMQ — Redis tabanlı job kuyruğu (Video üretim pipeline)
|
||
BullModule.forRootAsync({
|
||
imports: [ConfigModule],
|
||
useFactory: (configService: ConfigService) => ({
|
||
connection: {
|
||
host: configService.get<string>('redis.host', 'localhost'),
|
||
port: configService.get<number>('redis.port', 6379),
|
||
password: configService.get<string>('redis.password') || undefined,
|
||
},
|
||
}),
|
||
inject: [ConfigService],
|
||
}),
|
||
|
||
// 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,
|
||
|
||
// Video SaaS Modules
|
||
ProjectsModule,
|
||
VideoQueueModule,
|
||
VideoAiModule,
|
||
StorageModule,
|
||
BillingModule,
|
||
XTwitterModule,
|
||
|
||
// Real-time & Callback Modules
|
||
EventsModule,
|
||
RenderCallbackModule,
|
||
DashboardModule,
|
||
NotificationsModule,
|
||
],
|
||
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 {}
|