import express from 'express'; import cors from 'cors'; import path from 'path'; import fs from 'fs'; import { fileURLToPath } from 'url'; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); const app = express(); const PORT = process.env.PORT || 80; const DATA_DIR = process.env.DATA_DIR || path.resolve(__dirname, '../data_store'); const STATE_FILE = path.join(DATA_DIR, 'wortkraft_state.json'); if (!fs.existsSync(DATA_DIR)) { fs.mkdirSync(DATA_DIR, { recursive: true }); } function readState() { try { if (fs.existsSync(STATE_FILE)) { const raw = fs.readFileSync(STATE_FILE, 'utf8'); return JSON.parse(raw); } } catch (err) { console.error('[WORTKRAFT] Error reading state file:', err); } return null; } function writeState(stateObj) { try { fs.writeFileSync(STATE_FILE, JSON.stringify(stateObj, null, 2), 'utf8'); return true; } catch (err) { console.error('[WORTKRAFT] Error writing state file:', err); return false; } } app.use(cors()); app.use(express.json({ limit: '10mb' })); // Healthcheck endpoint for Docker & Homepage app.get('/api/health', (_req, res) => { res.json({ status: 'ok', app: 'wortkraft', timestamp: new Date().toISOString(), uptimeSeconds: Math.floor(process.uptime()) }); }); // Get persisted learning state (SRS deck, streak, custom words & stories) app.get('/api/state', (_req, res) => { const state = readState(); res.json({ exists: Boolean(state), state }); }); // Save learning state app.post('/api/state', (req, res) => { const payload = req.body; if (!payload || typeof payload !== 'object') { return res.status(400).json({ error: 'Invalid state payload' }); } payload.updatedAt = new Date().toISOString(); const ok = writeState(payload); res.json({ success: ok, updatedAt: payload.updatedAt }); }); // Serve static frontend files from project root const PUBLIC_DIR = path.resolve(__dirname, '..'); app.use('/data', express.static(path.join(PUBLIC_DIR, 'data'))); app.get('/styles.css', (_req, res) => res.sendFile(path.join(PUBLIC_DIR, 'styles.css'))); app.get('/app.js', (_req, res) => res.sendFile(path.join(PUBLIC_DIR, 'app.js'))); app.get('/', (_req, res) => res.sendFile(path.join(PUBLIC_DIR, 'index.html'))); app.use((req, res, next) => { if (req.method === 'GET' && !req.path.startsWith('/api')) { return res.sendFile(path.join(PUBLIC_DIR, 'index.html')); } next(); }); app.listen(PORT, '0.0.0.0', () => { console.log(`[WORTKRAFT] Server listening on port ${PORT}`); console.log(`[WORTKRAFT] Persistent data directory: ${DATA_DIR}`); });