Backend: Match-Lobbys, Map-Veto, Echtzeit und CS2-Serveradapter
Express + Socket.IO + SQLite. Veto-Engine mit konfigurierbaren Map-Pools und validierten Abläufen, rollenbasierte Berechtigungen, Server-Lebenszyklus mit Demo-, Docker- und Static-Pool-Adapter (RCON), automatisches Herunterfahren.
This commit is contained in:
commit
f08297dd0d
27 files changed
+6355
No files matched your search
@@ -0,0 +1,60 @@
|
||||
import fs from 'node:fs';
|
||||
import http from 'node:http';
|
||||
import path from 'node:path';
|
||||
import express from 'express';
|
||||
import { REPO_ROOT } from './config.js';
|
||||
import { openDatabase } from './db.js';
|
||||
import { createApiRouter } from './http.js';
|
||||
import { loadMapPools } from './mapPools.js';
|
||||
import { MatchService } from './matchService.js';
|
||||
import { attachRealtime } from './realtime.js';
|
||||
import { createServerAdapter } from './servers/adapter.js';
|
||||
import { ServerManager } from './servers/serverManager.js';
|
||||
|
||||
/** Baut die komplette Anwendung zusammen (auch für Tests nutzbar). */
|
||||
export function createApp(config, { adapter: adapterOverride, logger = console } = {}) {
|
||||
const db = openDatabase(config.databaseFile);
|
||||
const pools = loadMapPools(config.mapPoolFile);
|
||||
const service = new MatchService({ db, pools, config });
|
||||
|
||||
let manager;
|
||||
const adapter = adapterOverride ?? createServerAdapter(config, { getUsedPorts: () => manager.usedPorts() });
|
||||
manager = new ServerManager({ db, service, adapter, config, logger });
|
||||
manager.init();
|
||||
|
||||
const app = express();
|
||||
if (config.trustProxy) app.set('trust proxy', 1);
|
||||
app.disable('x-powered-by');
|
||||
app.use((req, res, next) => {
|
||||
res.set('X-Content-Type-Options', 'nosniff');
|
||||
res.set('Referrer-Policy', 'no-referrer');
|
||||
next();
|
||||
});
|
||||
app.use('/api', createApiRouter({ service, manager, config, pools, adapter }));
|
||||
|
||||
// Gebautes Frontend ausliefern (npm run build), SPA-Fallback auf index.html.
|
||||
const dist = path.join(REPO_ROOT, 'client', 'dist');
|
||||
if (fs.existsSync(dist)) {
|
||||
app.use(express.static(dist, { index: false, maxAge: '1h' }));
|
||||
app.get('*', (req, res) => res.sendFile(path.join(dist, 'index.html')));
|
||||
}
|
||||
|
||||
const server = http.createServer(app);
|
||||
const io = attachRealtime(server, { service, config });
|
||||
|
||||
return {
|
||||
app, server, io, db, service, manager, adapter,
|
||||
async start() {
|
||||
await manager.resume();
|
||||
manager.startLoops();
|
||||
await new Promise((resolve) => server.listen(config.port, resolve));
|
||||
return server.address().port;
|
||||
},
|
||||
async close() {
|
||||
manager.stopLoops();
|
||||
io.close();
|
||||
await new Promise((resolve) => server.close(() => resolve()));
|
||||
db.close();
|
||||
},
|
||||
};
|
||||
}
|
||||
Reference in new issue
Block a user