This commit is contained in:
2026-04-16 17:21:48 +03:00
parent c8fa4c442d
commit c8e7e4e927
116 changed files with 3720 additions and 4197 deletions
+54 -54
View File
@@ -1,19 +1,19 @@
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 { ScheduleModule } from '@nestjs/schedule';
import { redisStore } from 'cache-manager-redis-yet';
import { LoggerModule } from 'nestjs-pino';
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 { ScheduleModule } from "@nestjs/schedule";
import { redisStore } from "cache-manager-redis-yet";
import { LoggerModule } from "nestjs-pino";
import {
I18nModule,
AcceptLanguageResolver,
HeaderResolver,
QueryResolver,
} from 'nestjs-i18n';
import { ServeStaticModule } from '@nestjs/serve-static';
import * as path from 'path';
} from "nestjs-i18n";
import { ServeStaticModule } from "@nestjs/serve-static";
import * as path from "path";
// Config
import {
@@ -24,52 +24,52 @@ import {
i18nConfig,
featuresConfig,
throttleConfig,
} from './config/configuration';
import { geminiConfig } from './modules/gemini/gemini.config';
import { validateEnv } from './config/env.validation';
} 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';
import { GlobalExceptionFilter } from "./common/filters/global-exception.filter";
import { ResponseInterceptor } from "./common/interceptors/response.interceptor";
// Database
import { DatabaseModule } from './database/database.module';
import { DatabaseModule } from "./database/database.module";
// Core 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';
import { SocialPosterModule } from './modules/social-poster/social-poster.module';
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";
import { SocialPosterModule } from "./modules/social-poster/social-poster.module";
// Sports Domain Modules
import { MatchesModule } from './modules/matches/matches.module';
import { PredictionsModule } from './modules/predictions/predictions.module';
import { LeaguesModule } from './modules/leagues/leagues.module';
import { AnalysisModule } from './modules/analysis/analysis.module';
import { CouponsModule } from './modules/coupons/coupons.module';
import { SporTotoModule } from './modules/spor-toto/spor-toto.module';
import { MatchesModule } from "./modules/matches/matches.module";
import { PredictionsModule } from "./modules/predictions/predictions.module";
import { LeaguesModule } from "./modules/leagues/leagues.module";
import { AnalysisModule } from "./modules/analysis/analysis.module";
import { CouponsModule } from "./modules/coupons/coupons.module";
import { SporTotoModule } from "./modules/spor-toto/spor-toto.module";
// Services and Tasks
import { ServicesModule } from './services/services.module';
import { TasksModule } from './tasks/tasks.module';
import { ServicesModule } from "./services/services.module";
import { TasksModule } from "./tasks/tasks.module";
// Feeder Module (Historical Data Scraping)
import { FeederModule } from './modules/feeder/feeder.module';
import { FeederModule } from "./modules/feeder/feeder.module";
// Guards
import {
JwtAuthGuard,
RolesGuard,
PermissionsGuard,
} from './modules/auth/guards';
} from "./modules/auth/guards";
// Queue
import { QueueModule } from './common/queues/queue.module';
import { QueueModule } from "./common/queues/queue.module";
const redisEnabled = process.env.REDIS_ENABLED === 'true';
const historicalFeederMode = process.env.FEEDER_MODE === 'historical';
const redisEnabled = process.env.REDIS_ENABLED === "true";
const historicalFeederMode = process.env.FEEDER_MODE === "historical";
@Module({
imports: [
@@ -94,8 +94,8 @@ const historicalFeederMode = process.env.FEEDER_MODE === 'historical';
// Static Assets (Images, Uploads)
ServeStaticModule.forRoot({
rootPath: path.join(__dirname, '..', 'public'),
serveRoot: '/', // This means public/uploads/x.png -> /uploads/x.png
rootPath: path.join(__dirname, "..", "public"),
serveRoot: "/", // This means public/uploads/x.png -> /uploads/x.png
}),
// Logger (Structured Logging with Pino)
@@ -105,10 +105,10 @@ const historicalFeederMode = process.env.FEEDER_MODE === 'historical';
useFactory: (configService: ConfigService) => {
return {
pinoHttp: {
level: configService.get('app.isDevelopment') ? 'debug' : 'info',
transport: configService.get('app.isDevelopment')
level: configService.get("app.isDevelopment") ? "debug" : "info",
transport: configService.get("app.isDevelopment")
? {
target: 'pino-pretty',
target: "pino-pretty",
options: {
singleLine: true,
},
@@ -122,15 +122,15 @@ const historicalFeederMode = process.env.FEEDER_MODE === 'historical';
// i18n
I18nModule.forRootAsync({
useFactory: (configService: ConfigService) => ({
fallbackLanguage: configService.get('i18n.fallbackLanguage', 'en'),
fallbackLanguage: configService.get("i18n.fallbackLanguage", "en"),
loaderOptions: {
path: path.join(__dirname, '../i18n/'),
watch: configService.get('app.isDevelopment', true),
path: path.join(__dirname, "../i18n/"),
watch: configService.get("app.isDevelopment", true),
},
}),
resolvers: [
new HeaderResolver(['x-lang']),
new QueryResolver(['lang']),
new HeaderResolver(["x-lang"]),
new QueryResolver(["lang"]),
AcceptLanguageResolver,
],
inject: [ConfigService],
@@ -141,8 +141,8 @@ const historicalFeederMode = process.env.FEEDER_MODE === 'historical';
inject: [ConfigService],
useFactory: (configService: ConfigService) => [
{
ttl: configService.get('throttle.ttl', 60000),
limit: configService.get('throttle.limit', 100),
ttl: configService.get("throttle.ttl", 60000),
limit: configService.get("throttle.limit", 100),
},
],
}),
@@ -153,29 +153,29 @@ const historicalFeederMode = process.env.FEEDER_MODE === 'historical';
imports: [ConfigModule],
useFactory: async (configService: ConfigService) => {
// FORCE DISABLE REDIS if user doesn't want it
const useRedis = configService.get('redis.enabled', false);
const useRedis = configService.get("redis.enabled", false);
if (useRedis) {
try {
const store = await redisStore({
socket: {
host: configService.get('redis.host', 'localhost'),
port: configService.get('redis.port', 6379),
host: configService.get("redis.host", "localhost"),
port: configService.get("redis.port", 6379),
},
ttl: 60 * 1000, // 1 minute default
});
console.log('✅ Redis cache connected');
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');
console.warn("⚠️ Redis connection failed, using in-memory cache");
}
}
// Fallback to in-memory cache
console.log('📦 Using in-memory cache');
console.log("📦 Using in-memory cache");
return {
ttl: 60 * 1000,
};