import { Elysia } from 'elysia'; import { cors } from '@elysiajs/cors'; import { auth } from './lib/auth'; import { authRoutes } from './routes/auth'; import { adminRoutes } from './routes/admin'; import { projectRoutes } from './routes/projects'; import { taskRoutes } from './routes/tasks'; import { labelRoutes } from './routes/labels'; import { commentRoutes } from './routes/comments'; import { hammerRoutes } from './routes/hammer'; const app = new Elysia() // CORS .use(cors({ origin: process.env.ALLOWED_ORIGINS?.split(',') || [ 'http://localhost:5173', 'https://todo.donovankelly.xyz', ], credentials: true, exposeHeaders: ['set-auth-token'], })) // Health check .get('/health', () => ({ status: 'ok', timestamp: new Date().toISOString(), version: '0.1.0', })) // BetterAuth routes (login, register, session, etc.) .all('/api/auth/*', async ({ request }) => { return auth.handler(request); }) // Public auth routes (invite acceptance) .use(authRoutes) // Hammer API (uses separate API key auth) .group('/api', app => app.use(hammerRoutes)) // Authenticated API routes (auth middleware is in each route plugin) .group('/api', app => app .use(adminRoutes) .use(projectRoutes) .use(taskRoutes) .use(labelRoutes) .use(commentRoutes) ) // Error handler .onError(({ code, error, set, path }) => { const message = error instanceof Error ? error.message : String(error); const stack = error instanceof Error ? error.stack : undefined; console.error(`[${new Date().toISOString()}] ERROR on ${path}:`, { code, message, stack: process.env.NODE_ENV !== 'production' ? stack : undefined, }); if (code === 'VALIDATION') { set.status = 400; return { error: 'Validation error', details: message }; } if (message === 'Unauthorized') { set.status = 401; return { error: 'Unauthorized' }; } if (message === 'Admin access required') { set.status = 403; return { error: 'Forbidden: Admin access required' }; } if (message.includes('not found')) { set.status = 404; return { error: message }; } set.status = 500; return { error: 'Internal server error' }; }) .listen(process.env.PORT || 3001); console.log(`🚀 Todo API running at ${app.server?.hostname}:${app.server?.port}`); export type App = typeof app;