import Fastify from 'fastify'; import cors from '@fastify/cors'; import cookie from '@fastify/cookie'; import dbPlugin from './plugins/db.js'; import authPlugin from './plugins/auth.js'; import authRoutes from './routes/auth/index.js'; import organizationRoutes from './routes/organizations/index.js'; import nodeRoutes from './routes/nodes/index.js'; import serverRoutes from './routes/servers/index.js'; import adminRoutes from './routes/admin/index.js'; import { AppError } from './lib/errors.js'; const app = Fastify({ logger: { transport: process.env.NODE_ENV !== 'production' ? { target: 'pino-pretty' } : undefined, }, }); // Plugins await app.register(cors, { origin: process.env.CORS_ORIGIN || 'http://localhost:5173', credentials: true, }); await app.register(cookie); await app.register(dbPlugin); await app.register(authPlugin); // Error handler app.setErrorHandler((error: Error & { validation?: unknown; statusCode?: number; code?: string }, _request, reply) => { if (error instanceof AppError) { return reply.code(error.statusCode).send({ error: error.name, message: error.message, code: error.code, }); } // Fastify validation errors if (error.validation) { return reply.code(400).send({ error: 'Validation Error', message: error.message, }); } app.log.error(error); return reply.code(500).send({ error: 'Internal Server Error', message: 'An unexpected error occurred', }); }); // Routes app.get('/api/health', async () => { return { status: 'ok', timestamp: new Date().toISOString() }; }); await app.register(authRoutes, { prefix: '/api/auth' }); await app.register(organizationRoutes, { prefix: '/api/organizations' }); await app.register(adminRoutes, { prefix: '/api/admin' }); // Nested org routes: nodes and servers are scoped to an org await app.register( async (orgScope) => { await orgScope.register(nodeRoutes, { prefix: '/nodes' }); await orgScope.register(serverRoutes, { prefix: '/servers' }); }, { prefix: '/api/organizations/:orgId' }, ); // Start const PORT = Number(process.env.PORT) || 3000; const HOST = process.env.HOST || '0.0.0.0'; try { await app.listen({ port: PORT, host: HOST }); app.log.info(`API server running on http://${HOST}:${PORT}`); } catch (err) { app.log.error(err); process.exit(1); }