import Fastify from "fastify"; import fastifyCookie from "@fastify/cookie"; import fastifyCors from "@fastify/cors"; import fastifyMultipart from "@fastify/multipart"; import fastifyStatic from "@fastify/static"; import { createYoga } from "graphql-yoga"; import path from "path"; import { schema } from "./graphql/index"; import { buildContext } from "./graphql/context"; import { db } from "./db/connection"; import { redis } from "./lib/auth"; const PORT = parseInt(process.env.PORT || "4000"); const UPLOAD_DIR = process.env.UPLOAD_DIR || "/data/uploads"; const CORS_ORIGIN = process.env.CORS_ORIGIN || "http://localhost:3000"; async function main() { const fastify = Fastify({ logger: { level: process.env.LOG_LEVEL || "info", }, }); await fastify.register(fastifyCookie, { secret: process.env.COOKIE_SECRET || "change-me-in-production", }); await fastify.register(fastifyCors, { origin: CORS_ORIGIN, credentials: true, methods: ["GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"], }); await fastify.register(fastifyMultipart, { limits: { fileSize: 5 * 1024 * 1024 * 1024, // 5 GB }, }); await fastify.register(fastifyStatic, { root: path.resolve(UPLOAD_DIR), prefix: "/assets/", decorateReply: false, }); const yoga = createYoga({ schema, context: buildContext, graphqlEndpoint: "/graphql", healthCheckEndpoint: "/health", logging: { debug: (msg: string) => fastify.log.debug(msg), info: (msg: string) => fastify.log.info(msg), warn: (msg: string) => fastify.log.warn(msg), error: (msg: string) => fastify.log.error(msg), }, }); fastify.route({ url: "/graphql", method: ["GET", "POST", "OPTIONS"], handler: async (request, reply) => { const response = await yoga.handleNodeRequestAndResponse( request.raw, reply.raw, { reply, db, redis }, ); reply.status(response.status); for (const [key, value] of response.headers.entries()) { reply.header(key, value); } return reply.send(response.body); }, }); fastify.get("/health", async (_request, reply) => { return reply.send({ status: "ok", timestamp: new Date().toISOString() }); }); try { await fastify.listen({ port: PORT, host: "0.0.0.0" }); fastify.log.info(`Backend running at http://0.0.0.0:${PORT}`); fastify.log.info(`GraphQL at http://0.0.0.0:${PORT}/graphql`); } catch (err) { fastify.log.error(err); process.exit(1); } } main().catch((err) => { console.error("Fatal error:", err); process.exit(1); });