import Fastify, { FastifyRequest, FastifyReply } 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<{ req: FastifyRequest; reply: FastifyReply; db: typeof db; redis: typeof redis }>({ schema, context: buildContext, graphqlEndpoint: "/graphql", healthCheckEndpoint: "/health", logging: { debug: (...args) => args.forEach((arg) => fastify.log.debug(arg)), info: (...args) => args.forEach((arg) => fastify.log.info(arg)), warn: (...args) => args.forEach((arg) => fastify.log.warn(arg)), error: (...args) => args.forEach((arg) => fastify.log.error(arg)), }, }); fastify.route({ url: "/graphql", method: ["GET", "POST", "OPTIONS"], handler: (req, reply) => yoga.handleNodeRequestAndResponse(req, reply, { req, reply, db, redis }), }); 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); });