import 'dotenv/config'; import express from 'express'; import cors from 'cors'; import cookieParser from 'cookie-parser'; import authRoutes from './routes/auth.routes.js'; import scenarioRoutes from './routes/scenario.routes.js'; import resultRoutes from './routes/result.routes.js'; import uploadRoutes from './routes/upload.routes.js'; import mediaRoutes from './routes/media.routes.js'; import { errorHandler } from './middleware/errorHandler.js'; const app = express(); // CORS настройка const allowedOrigins = (process.env.FRONTEND_URL || 'http://localhost:3000') .split(',').map(o => o.trim()); const corsOptions = { origin: (origin, callback) => { // Разрешаем запросы без origin (от nginx proxy) if (!origin) return callback(null, true); const isReplit = origin && (origin.endsWith('.replit.dev') || origin.endsWith('.repl.co')); if (allowedOrigins.includes(origin) || isReplit) callback(null, true); else callback(new Error('Not allowed by CORS')); }, credentials: true, allowedHeaders: ['Content-Type', 'Authorization', 'x-csrf-token'], methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'], }; app.use(cors(corsOptions)); // Статические файлы app.use(express.static('public')); // Увеличенные лимиты для больших файлов app.use(express.json({ limit: '500mb' })); app.use(express.urlencoded({ extended: true, limit: '500mb' })); app.use(cookieParser()); // health app.get('/api/health', (req, res) => { res.json({ ok: true }); }); // routes app.use('/api/auth', authRoutes); app.use('/api/scenario', scenarioRoutes); app.use('/api/result', resultRoutes); app.use('/api/upload', uploadRoutes); app.use('/api/media', mediaRoutes); // errors app.use(errorHandler); export default app; const PORT = Number(process.env.PORT || 3001); const HOST = process.env.HOST || '127.0.0.1'; app.set('trust proxy', 1); app.listen(PORT, HOST, () => { console.log(`BFF started on http://${HOST}:${PORT}`); });