import express from 'express'; import path from 'node:path'; import { fileURLToPath } from 'node:url'; import { offlineManifest } from './src/services/offline-manifest.js'; import { setAppImageCopyright } from './src/services/copyright.js'; import { config, ensureRuntimeDirectories } from './src/config.js'; import { openDatabase } from './src/database.js'; import { createApiRouter } from './src/routes/api.js'; import { notFoundHandler, errorHandler } from './src/middleware/errors.js'; const __dirname = path.dirname(fileURLToPath(import.meta.url)); ensureRuntimeDirectories(); const db = openDatabase(); const app = express(); const publicDirectory = path.join(__dirname, 'public'); app.disable('x-powered-by'); app.use(express.json({ limit: config.maxJsonBodyBytes, type: ['application/json', 'application/*+json', 'text/json'] })); app.use(express.urlencoded({ extended: true, limit: '2mb' })); app.get('/api/offline-manifest', (req, res) => { res.setHeader('Cache-Control', 'no-store'); res.json(offlineManifest(publicDirectory)); }); app.use('/api', createApiRouter(db)); app.use(express.static(publicDirectory, { extensions: ['html'], etag: true, lastModified: true, maxAge: 0, setHeaders(res, filePath) { setAppImageCopyright(res, filePath); const extension = path.extname(filePath).toLowerCase(); const authoredAsset = ['.html', '.css', '.js'].includes(extension); res.setHeader( 'Cache-Control', authoredAsset ? 'no-cache, no-store, must-revalidate' : 'public, max-age=0, must-revalidate' ); if (authoredAsset) { res.setHeader('Pragma', 'no-cache'); res.setHeader('Expires', '0'); } } })); app.use(notFoundHandler); app.use(errorHandler); const server = app.listen(config.port, config.host, () => { console.log(`Wegwichtel läuft auf http://${config.host}:${config.port}`); }); function shutdown(signal) { console.log(`${signal}: Server wird beendet.`); server.close(() => { db.close(); process.exit(0); }); } process.on('SIGINT', () => shutdown('SIGINT')); process.on('SIGTERM', () => shutdown('SIGTERM'));