import express, { Express } from 'express'; import path from 'path'; import { CONFIG } from './config/app.config'; import { requestLogger } from './middleware/logger.middleware'; import { errorHandler } from './middleware/error.middleware'; import { globalRateLimiter } from './middleware/rateLimit.middleware'; import { createApiRouter } from './routes/api.routes'; // Repositories import { FileTaskRepository } from './repositories/fileStorage/fileTaskRepository'; import { FileWorkerRepository } from './repositories/fileStorage/fileWorkerRepository'; // Services import { OffsetIndexService } from './services/implementations/offsetIndex.service'; import { DatasetService } from './services/implementations/dataset.service'; import { WorkerService } from './services/implementations/worker.service'; import { SchedulerService } from './services/implementations/scheduler.service'; import { TaskQueueService } from './services/implementations/taskQueue.service'; import { LeaseService } from './services/implementations/lease.service'; import { ProgressService } from './services/implementations/progress.service'; import { ResultService } from './services/implementations/result.service'; import { StatisticsService } from './services/implementations/statistics.service'; // Controllers import { HealthController } from './controllers/health.controller'; import { AdminController } from './controllers/admin.controller'; export interface AppContext { app: Express; taskRepo: FileTaskRepository; workerRepo: FileWorkerRepository; offsetIndexService: OffsetIndexService; datasetService: DatasetService; workerService: WorkerService; schedulerService: SchedulerService; taskQueueService: TaskQueueService; leaseService: LeaseService; progressService: ProgressService; resultService: ResultService; statisticsService: StatisticsService; healthController: HealthController; adminController: AdminController; } export function createApp(): AppContext { const app = express(); // Trust first proxy (required for reverse proxies like HuggingFace / Docker / Nginx to properly expose client IP to rate-limiter) app.set('trust proxy', 1); // Middleware app.use(globalRateLimiter); app.use(express.json()); app.use(express.urlencoded({ extended: true })); app.use(requestLogger); // Views & Static Setup app.set('view engine', 'ejs'); app.set('views', path.resolve(process.cwd(), 'views')); app.use(express.static(path.resolve(process.cwd(), 'public'))); // Dependency Injection Instantiation const taskRepo = new FileTaskRepository(); const workerRepo = new FileWorkerRepository(); const offsetIndexService = new OffsetIndexService(); const datasetService = new DatasetService(offsetIndexService); const workerService = new WorkerService(workerRepo); const schedulerService = new SchedulerService(); const taskQueueService = new TaskQueueService( taskRepo, offsetIndexService, workerService, schedulerService ); const leaseService = new LeaseService(taskRepo, workerService); const progressService = new ProgressService(taskQueueService, workerService); const resultService = new ResultService(taskQueueService, workerService); const statisticsService = new StatisticsService(taskQueueService, workerService, datasetService); const healthController = new HealthController(datasetService); const adminController = new AdminController(statisticsService, workerService, taskQueueService, datasetService); // Mount API Router const apiRouter = createApiRouter(healthController, adminController); app.use(apiRouter); // Dashboard Page Route (EJS View) app.get('/', async (req, res, next) => { try { const stats = await statisticsService.getSystemStatistics(); const workers = await workerService.getAllWorkers(); const recentTasks = await taskQueueService.getTasks({ limit: 50 }); const initialDatasetRows = await datasetService.readRowContentSnippet(0, 5); res.render('index', { stats, workers, recentTasks, initialDatasetRows, config: CONFIG }); } catch (err) { next(err); } }); // Global Error Handler app.use(errorHandler); return { app, taskRepo, workerRepo, offsetIndexService, datasetService, workerService, schedulerService, taskQueueService, leaseService, progressService, resultService, statisticsService, healthController, adminController, }; }