const path = require('path') const fs = require('fs') const dotenv = require('dotenv') const express = require('express') const cors = require('cors') const session = require('express-session') const FileStoreFactory = require('session-file-store') dotenv.config({ path: path.join(__dirname, '..', '.env.production') }) const { ensureData } = require('./src/db') const authRoutes = require('./src/routes/auth') const topicsRoutes = require('./src/routes/topics') const tierListsRoutes = require('./src/routes/tierlists') const usersRoutes = require('./src/routes/users') const adminRoutes = require('./src/routes/admin') const shareRoutes = require('./src/routes/share') const app = express() const PORT = process.env.PORT ? Number(process.env.PORT) : 5179 const SESSION_SECRET = process.env.SESSION_SECRET || 'dev-secret-change-me' const SESSION_COOKIE_SECURE = process.env.SESSION_COOKIE_SECURE === 'true' const SESSION_COOKIE_SAME_SITE = process.env.SESSION_COOKIE_SAME_SITE || 'lax' const TRUST_PROXY = process.env.TRUST_PROXY ? Number(process.env.TRUST_PROXY) : 1 const allowedOrigins = (process.env.CORS_ORIGINS || '') .split(',') .map((origin) => origin.trim()) .filter(Boolean) const FileStore = FileStoreFactory(session) ;['uploads/avatars', 'uploads/topics', 'uploads/custom', 'uploads/tierlists', '.sessions'].forEach((relativePath) => { fs.mkdirSync(path.join(__dirname, relativePath), { recursive: true }) }) app.set('trust proxy', TRUST_PROXY) app.use( cors({ origin: (origin, cb) => { if (!origin) return cb(null, true) if (allowedOrigins.includes(origin)) return cb(null, true) if (/^http:\/\/localhost:517\d$/.test(origin)) return cb(null, true) // 5170~5179 if (/^https?:\/\/127\.0\.0\.1:517\d$/.test(origin)) return cb(null, true) if (origin === 'http://localhost:5173') return cb(null, true) cb(new Error('not_allowed_by_cors')) }, credentials: true, }) ) app.use(express.json({ limit: '10mb' })) app.use(express.urlencoded({ extended: true })) app.use( session({ store: new FileStore({ path: path.join(__dirname, '.sessions'), ttl: 60 * 60 * 24 * 30, retries: 0, }), secret: SESSION_SECRET, proxy: TRUST_PROXY > 0, resave: false, saveUninitialized: false, cookie: { httpOnly: true, sameSite: SESSION_COOKIE_SAME_SITE, secure: SESSION_COOKIE_SECURE, maxAge: 1000 * 60 * 60 * 24 * 30, }, }) ) app.use('/uploads', express.static(path.join(__dirname, 'uploads'))) app.get('/health', (req, res) => res.json({ ok: true })) app.use(async (req, res, next) => { try { await ensureData() next() } catch (e) { console.error('[backend] db init failed', e) res.status(500).json({ error: 'db_init_failed' }) } }) app.use('/api/auth', authRoutes) app.use('/api/topics', topicsRoutes) app.use('/api/tierlists', tierListsRoutes) app.use('/api/users', usersRoutes) app.use('/api/admin', adminRoutes) app.use('/share', shareRoutes) app.listen(PORT, () => { console.log(`[backend] listening on http://localhost:${PORT}`) })