/** * TASKMATE - Health Check Routes * ============================== * Server-Status und Health-Check Endpoints */ const express = require('express'); const router = express.Router(); const fs = require('fs'); const path = require('path'); const { getDb } = require('../database'); const backup = require('../utils/backup'); /** * GET /api/health * Einfacher Health-Check */ router.get('/', (req, res) => { try { // Datenbank-Check const db = getDb(); db.prepare('SELECT 1').get(); res.json({ status: 'healthy', timestamp: new Date().toISOString() }); } catch (error) { res.status(503).json({ status: 'unhealthy', error: error.message, timestamp: new Date().toISOString() }); } }); /** * GET /api/health/detailed * Detaillierter Health-Check (mit Auth) */ router.get('/detailed', (req, res) => { try { const db = getDb(); // Datenbank-Statistiken const userCount = db.prepare('SELECT COUNT(*) as count FROM users').get().count; const projectCount = db.prepare('SELECT COUNT(*) as count FROM projects WHERE archived = 0').get().count; const taskCount = db.prepare('SELECT COUNT(*) as count FROM tasks WHERE archived = 0').get().count; // Disk-Space für Uploads const uploadsDir = process.env.UPLOAD_DIR || path.join(__dirname, '..', 'uploads'); let uploadsSize = 0; let uploadCount = 0; if (fs.existsSync(uploadsDir)) { const getDirectorySize = (dir) => { let size = 0; let count = 0; const files = fs.readdirSync(dir); for (const file of files) { const filePath = path.join(dir, file); const stats = fs.statSync(filePath); if (stats.isDirectory()) { const subResult = getDirectorySize(filePath); size += subResult.size; count += subResult.count; } else { size += stats.size; count++; } } return { size, count }; }; const result = getDirectorySize(uploadsDir); uploadsSize = result.size; uploadCount = result.count; } // Letzte Backups const backups = backup.listBackups().slice(0, 5); // Memory Usage const memUsage = process.memoryUsage(); res.json({ status: 'healthy', timestamp: new Date().toISOString(), uptime: Math.floor(process.uptime()), database: { users: userCount, projects: projectCount, tasks: taskCount }, storage: { uploadCount, uploadsSizeMB: Math.round(uploadsSize / 1024 / 1024 * 100) / 100 }, backups: backups.map(b => ({ name: b.name, sizeMB: Math.round(b.size / 1024 / 1024 * 100) / 100, created: b.created })), memory: { heapUsedMB: Math.round(memUsage.heapUsed / 1024 / 1024 * 100) / 100, heapTotalMB: Math.round(memUsage.heapTotal / 1024 / 1024 * 100) / 100, rssMB: Math.round(memUsage.rss / 1024 / 1024 * 100) / 100 }, environment: process.env.NODE_ENV || 'development' }); } catch (error) { res.status(503).json({ status: 'unhealthy', error: error.message, timestamp: new Date().toISOString() }); } }); /** * POST /api/health/backup * Manuelles Backup auslösen */ router.post('/backup', (req, res) => { try { const backupPath = backup.createBackup(); if (backupPath) { res.json({ message: 'Backup erfolgreich erstellt', path: path.basename(backupPath) }); } else { res.status(500).json({ error: 'Backup fehlgeschlagen' }); } } catch (error) { res.status(500).json({ error: error.message }); } }); /** * GET /api/health/backups * Liste aller Backups */ router.get('/backups', (req, res) => { try { const backups = backup.listBackups(); res.json(backups.map(b => ({ name: b.name, sizeMB: Math.round(b.size / 1024 / 1024 * 100) / 100, created: b.created }))); } catch (error) { res.status(500).json({ error: error.message }); } }); module.exports = router;