import 'dotenv/config'; import cors from 'cors'; import express, { type NextFunction, type Request, type Response } from 'express'; import { buildApiPath, getConfig } from './config'; import { TursoClient } from './lib/db'; import { createHealthRouter } from './routes/health'; import { createTodosRouter } from './routes/todos'; const config = getConfig(); const app = express(); const db = new TursoClient(config); app.disable('x-powered-by'); app.use(cors({ origin: config.corsOrigin === '*' ? true : config.corsOrigin })); app.use(express.json({ limit: '1mb' })); const apiRoot = config.apiPrefix || '/'; app.use(apiRoot, createHealthRouter(config)); app.use(apiRoot, createTodosRouter(config, db)); // 10-second health check logger setInterval(() => { console.log('[Health Check] Sandbox is healthy at ' + new Date().toISOString()); }, 10000); app.post('/_cron/tick', (req, res) => { const authHeader = req.headers.authorization; if (!authHeader || authHeader !== 'Bearer ' + process.env.CRON_TOKEN) { return res.status(401).json({ success: false, error: 'Unauthorized' }); } console.log('[Tick] Cloud Run cron tick triggered.'); res.status(200).json({ success: true }); }); app.use((_req, res) => { res.status(404).json({ success: false, error: 'Not found' }); }); app.use((error: Error, _req: Request, res: Response, _next: NextFunction) => { const status = /required|invalid|missing/i.test(error.message) ? 400 : 500; res.status(status).json({ success: false, error: error.message || 'Unhandled error', }); }); app.listen(config.port, '0.0.0.0', () => { const healthPath = buildApiPath(config, '/health'); console.log(`Backend todo template listening on port ${config.port}`); console.log(`Health check available at ${healthPath}`); });