Ein Image mit Webseite, Backend, SQLite und Docker-Client; startet Match-Container über /var/run/docker.sock auf demselben Host. Tests laufen beim Bauen mit. Auf amp-cluster gebaut (301 MB) und geprüft. Dazu: Testbefehl für Node 22 angepasst, beim Beenden werden ausstehende Live-Updates verworfen und laufende Server-Aktionen abgewartet, damit nach dem Schließen der Datenbank nichts mehr darauf zugreift. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
64 lines
2.3 KiB
JavaScript
64 lines
2.3 KiB
JavaScript
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();
|
|
// Laufende Server-Aktionen (Start, Konfiguration) kurz abwarten, bevor die Datenbank schließt
|
|
await manager.idle(5000);
|
|
io.disposeRealtime();
|
|
io.close();
|
|
await new Promise((resolve) => server.close(() => resolve()));
|
|
db.close();
|
|
},
|
|
};
|
|
}
|