06112602ec
Version the NestJS TDLib gateway with Docker deployment, migrations, automated tests and platform integration documentation while excluding all account sessions, credentials, runtime databases and backups.
166 lines
5.6 KiB
TypeScript
166 lines
5.6 KiB
TypeScript
// Preload .env before any module imports
|
|
import * as dotenv from 'dotenv';
|
|
dotenv.config({ path: ['.env', '.env.local'] });
|
|
|
|
import { Module } from '@nestjs/common';
|
|
import { ConfigModule, ConfigService } from '@nestjs/config';
|
|
import { TypeOrmModule } from '@nestjs/typeorm';
|
|
import { ThrottlerGuard, ThrottlerModule } from '@nestjs/throttler';
|
|
import { APP_GUARD, APP_INTERCEPTOR } from '@nestjs/core';
|
|
|
|
import { appConfig } from './config/app.config';
|
|
import { databaseConfig } from './config/database.config';
|
|
import { redisConfig } from './config/redis.config';
|
|
import { rateLimitConfig } from './config/rate-limit.config';
|
|
|
|
import { JwtAuthGuard } from './common/guards/jwt-auth.guard';
|
|
|
|
import { TenantsModule } from './modules/tenants/tenants.module';
|
|
import { AuthModule } from './modules/auth/auth.module';
|
|
import { TgAccountsModule } from './modules/tg-accounts/tg-accounts.module';
|
|
import { TgAuthModule } from './modules/tg-auth/tg-auth.module';
|
|
import { TgProxiesModule } from './modules/tg-proxies/tg-proxies.module';
|
|
import { TdlibModule } from './modules/tdlib/tdlib.module';
|
|
import { TgChatsModule } from './modules/tg-chats/tg-chats.module';
|
|
import { TgDialogsModule } from './modules/tg-dialogs/tg-dialogs.module';
|
|
import { TgContactsModule } from './modules/tg-contacts/tg-contacts.module';
|
|
import { TgMessagesModule } from './modules/tg-messages/tg-messages.module';
|
|
import { TgGroupsModule } from './modules/tg-groups/tg-groups.module';
|
|
import { TgChannelsModule } from './modules/tg-channels/tg-channels.module';
|
|
import { TgFilesModule } from './modules/tg-files/tg-files.module';
|
|
import { TgWebhooksModule } from './modules/tg-webhooks/tg-webhooks.module';
|
|
import { TgRateLimitModule } from './modules/tg-rate-limit/tg-rate-limit.module';
|
|
import { TgAuditModule } from './modules/tg-audit/tg-audit.module';
|
|
import { AdminModule } from './modules/admin/admin.module';
|
|
import { TgUpdatesModule } from './modules/tg-updates/tg-updates.module';
|
|
import { AuditLogInterceptor } from './common/interceptors/audit-log.interceptor';
|
|
|
|
// Conditionally import BullMQ
|
|
const redisEnabled = process.env.REDIS_ENABLED !== 'false';
|
|
const bullImports: any[] = [];
|
|
const bullProviders: any[] = [];
|
|
|
|
if (redisEnabled) {
|
|
const { BullModule } = require('@nestjs/bull');
|
|
bullImports.push(
|
|
BullModule.forRootAsync({
|
|
imports: [ConfigModule],
|
|
inject: [ConfigService],
|
|
useFactory: (config: ConfigService) => ({
|
|
redis: {
|
|
host: config.get('redis.host'),
|
|
port: config.get('redis.port'),
|
|
password: config.get('redis.password'),
|
|
db: config.get('redis.db'),
|
|
},
|
|
}),
|
|
}),
|
|
);
|
|
} else {
|
|
// Provide mock Bull queue tokens so injectors don't crash
|
|
const { getQueueToken } = require('@nestjs/bull');
|
|
const queueNames = ['send-message', 'file-download', 'webhook-delivery'];
|
|
for (const name of queueNames) {
|
|
bullProviders.push({
|
|
provide: getQueueToken(name),
|
|
useValue: { add: () => Promise.reject(new Error('Redis/BullMQ not available')), process: () => {} },
|
|
});
|
|
bullProviders.push({
|
|
provide: 'BullQueue_' + name,
|
|
useValue: { add: () => Promise.reject(new Error('Redis/BullMQ not available')), process: () => {} },
|
|
});
|
|
}
|
|
}
|
|
|
|
const imports: any[] = [
|
|
ConfigModule.forRoot({
|
|
isGlobal: true,
|
|
load: [appConfig, databaseConfig, redisConfig, rateLimitConfig],
|
|
envFilePath: ['.env'],
|
|
}),
|
|
TypeOrmModule.forRootAsync({
|
|
imports: [ConfigModule],
|
|
inject: [ConfigService],
|
|
useFactory: (config: ConfigService) => {
|
|
const dbType = config.get('database.type') || 'postgres';
|
|
if (dbType === 'sqlite') {
|
|
const sqlitePath = config.get('database.sqlitePath') || 'data/gateway.sqlite';
|
|
const inMemory = sqlitePath === ':memory:';
|
|
return {
|
|
type: 'sqljs',
|
|
...(inMemory ? {} : { location: sqlitePath }),
|
|
autoSave: !inMemory,
|
|
entities: [__dirname + '/database/entities/**/*.entity.{ts,js}'],
|
|
synchronize: true,
|
|
};
|
|
}
|
|
return {
|
|
type: 'postgres',
|
|
host: config.get('database.host'),
|
|
port: config.get('database.port'),
|
|
username: config.get('database.username'),
|
|
password: config.get('database.password'),
|
|
database: config.get('database.database'),
|
|
entities: [__dirname + '/database/entities/**/*.entity.{ts,js}'],
|
|
synchronize:
|
|
config.get('database.synchronize') ||
|
|
config.get('app.nodeEnv') === 'development',
|
|
migrationsRun: config.get('database.migrationsRun') || false,
|
|
migrations: [__dirname + '/database/migrations/*.{ts,js}'],
|
|
logging: config.get('app.nodeEnv') === 'development',
|
|
};
|
|
},
|
|
}),
|
|
...bullImports,
|
|
ThrottlerModule.forRootAsync({
|
|
imports: [ConfigModule],
|
|
inject: [ConfigService],
|
|
useFactory: (config: ConfigService) => ({
|
|
throttlers: [
|
|
{
|
|
ttl: config.get('rateLimit.defaultTtl') || 60000,
|
|
limit: config.get('rateLimit.defaultLimit') || 30,
|
|
},
|
|
],
|
|
}),
|
|
}),
|
|
TenantsModule,
|
|
AuthModule,
|
|
TgAccountsModule,
|
|
TgAuthModule,
|
|
TgProxiesModule,
|
|
TdlibModule,
|
|
TgChatsModule,
|
|
TgDialogsModule,
|
|
TgContactsModule,
|
|
TgMessagesModule,
|
|
TgGroupsModule,
|
|
TgChannelsModule,
|
|
TgFilesModule,
|
|
TgWebhooksModule,
|
|
TgRateLimitModule,
|
|
TgAuditModule,
|
|
AdminModule,
|
|
TgUpdatesModule,
|
|
];
|
|
|
|
@Module({
|
|
imports,
|
|
providers: [
|
|
{
|
|
provide: APP_GUARD,
|
|
useClass: JwtAuthGuard,
|
|
},
|
|
{
|
|
provide: APP_GUARD,
|
|
useClass: ThrottlerGuard,
|
|
},
|
|
{
|
|
provide: APP_INTERCEPTOR,
|
|
useClass: AuditLogInterceptor,
|
|
},
|
|
...bullProviders,
|
|
],
|
|
})
|
|
export class AppModule {}
|