import Fastify from 'fastify'; import cors from '@fastify/cors'; import cookie from '@fastify/cookie'; import websocket from '@fastify/websocket'; import { seedAdmin } from '@bmm/auth'; import { config } from './config.js'; import { authRoutes } from './routes/auth.js'; import { serverRoutes } from './routes/servers.js'; import { oauthRoutes } from './routes/oauth.js'; import { settingsRoutes } from './routes/settings.js'; import { adminRoutes } from './routes/admin.js'; const app = Fastify({ logger: { level: config.NODE_ENV === 'production' ? 'info' : 'debug', }, }); await app.register(cors, { origin: [config.NEXT_PUBLIC_APP_URL], credentials: true, }); await app.register(cookie); await app.register(websocket, { options: { maxPayload: 1024 * 1024 } }); app.get('/health', async () => ({ ok: true, ts: Date.now() })); await app.register(authRoutes); await app.register(serverRoutes); await app.register(oauthRoutes); await app.register(settingsRoutes); await app.register(adminRoutes); // Bootstrap admin user from env (idempotent) if (config.ADMIN_EMAIL && config.ADMIN_PASSWORD) { try { const result = await seedAdmin({ email: config.ADMIN_EMAIL, password: config.ADMIN_PASSWORD, name: config.ADMIN_NAME, }); app.log.info( { email: config.ADMIN_EMAIL, created: result.created }, `[admin-seed] ${result.created ? 'created' : 'updated'} admin user`, ); } catch (err) { app.log.error({ err }, '[admin-seed] failed to seed admin user'); } } app.setErrorHandler((err, _req, reply) => { app.log.error(err); if (!reply.sent) { reply.code(err.statusCode ?? 500).send({ error: err.message ?? 'internal_error' }); } }); try { await app.listen({ port: config.PORT, host: '0.0.0.0' }); app.log.info(`api listening on http://localhost:${config.PORT}`); } catch (err) { app.log.error(err); process.exit(1); }