import { Hono } from 'hono'; import { serveStatic } from 'hono/bun'; import fs from 'fs'; // @ts-ignore Bun project may not have dotenv types configured import { config } from 'dotenv'; config(); const app = new Hono(); // Minimal log helpers const logLine = (path: string, line: string) => { try { fs.appendFileSync(path, `${new Date().toISOString()} ${line}\n`); } catch (err) { console.error('Failed to write log:', err); } }; // Version endpoint sourced from package.json app.get('/version', (c) => { try { const pkgRaw = fs.readFileSync('./package.json', 'utf-8'); const pkg = JSON.parse(pkgRaw); return c.json({ version: pkg.version || '0.0.0' }); } catch (err) { logLine('logs/error.log', `version endpoint error: ${(err as Error)?.message || String(err)}`); return c.json({ version: '0.0.0' }, 200); } }); // Serve static files from the frontend directory app.use('/*', serveStatic({ root: './frontend' })); // Error handler app.onError((err, c) => { logLine('logs/error.log', `Unhandled error: ${err?.message || err}`); return c.text('Internal Server Error', 500); }); // Mutation logging endpoint app.post('/log-change', async (c) => { try { const body = await c.req.json(); const { action = 'unknown', user = 'unknown', target = '', detail = '' } = body || {}; const payload = JSON.stringify({ action, user, target, detail }); logLine('logs/changes.log', payload); return c.json({ status: 'ok' }); } catch (err) { logLine('logs/error.log', `log-change error: ${(err as Error)?.message || String(err)}`); return c.text('Bad Request', 400); } }); const PORT = Number(process.env.PORT || 3000); logLine('logs/server.log', `Starting frontend server on port ${PORT}`); // Graceful shutdown logging const shutdown = (signal: string) => { logLine('logs/server.log', `Shutting down due to ${signal}`); process.exit(0); }; process.on('SIGINT', () => shutdown('SIGINT')); process.on('SIGTERM', () => shutdown('SIGTERM')); export default { port: PORT, fetch: app.fetch, };