import Fastify from 'fastify'; import cors from '@fastify/cors'; import helmet from '@fastify/helmet'; import rateLimit from '@fastify/rate-limit'; import fastifySwagger from '@fastify/swagger'; import fastifySwaggerUi from '@fastify/swagger-ui'; import fastifyWebsocket from '@fastify/websocket'; import fastifyCookie from '@fastify/cookie'; import fastifyJwt from '@fastify/jwt'; import { PrismaClient } from '@yetanother/db'; import { API_PREFIX } from '@yetanother/utils'; import { authPlugin } from './plugins/auth.js'; import { authRoutes } from './routes/auth.js'; import { nodeRoutes } from './routes/nodes.js'; import { workspaceRoutes } from './routes/workspaces.js'; import { searchRoutes } from './routes/search.js'; import { aiRoutes } from './routes/ai.js'; const envPort = process.env.PORT ? parseInt(process.env.PORT, 10) : 4000; const envHost = process.env.HOST ?? '0.0.0.0'; const jwtSecret = process.env.JWT_SECRET ?? 'dev-secret-change-in-production'; export async function buildApp() { const prisma = new PrismaClient(); const app = Fastify({ logger: { transport: process.env.NODE_ENV !== 'production' ? { target: 'pino-pretty', options: { colorize: true } } : undefined, }, }); await app.register(cors, { origin: true, credentials: true }); await app.register(helmet, { contentSecurityPolicy: false }); await app.register(rateLimit, { max: 100, timeWindow: '1 minute' }); await app.register(fastifyCookie); await app.register(fastifyJwt, { secret: jwtSecret }); await app.register(fastifyWebsocket); await app.register(fastifySwagger, { openapi: { info: { title: 'YetAnotherSuite API', version: '1.0.0' }, }, }); await app.register(fastifySwaggerUi, { routePrefix: '/docs' }); app.decorate('prisma', prisma); await app.register(authPlugin); await app.register(authRoutes, { prefix: `${API_PREFIX}/auth` }); await app.register(nodeRoutes, { prefix: API_PREFIX }); await app.register(workspaceRoutes, { prefix: API_PREFIX }); await app.register(searchRoutes, { prefix: API_PREFIX }); await app.register(aiRoutes, { prefix: API_PREFIX }); app.get('/health', async () => ({ status: 'ok', timestamp: new Date().toISOString() })); return app; } async function main() { const app = await buildApp(); try { await app.listen({ port: envPort, host: envHost }); app.log.info(`Server running at http://${envHost}:${envPort}`); } catch (err) { app.log.error(err); throw err; } } main();