import Fastify from "fastify"; import cors from "@fastify/cors"; import fastifyStatic from "@fastify/static"; import path from "node:path"; import { fileURLToPath } from "node:url"; import { systemsRoutes } from "./routes/systems.js"; import { structuresRoutes } from "./routes/structures.js"; import { quizRoutes } from "./routes/quiz.js"; import { analyticsRoutes } from "./routes/analytics.js"; import { adminRoutes } from "./routes/admin.js"; import { feedbackRoutes } from "./routes/feedback.js"; const __dirname = path.dirname(fileURLToPath(import.meta.url)); const MODELS_DIR = process.env.MODELS_DIR ?? path.resolve(__dirname, "../models"); // trustProxy: essencial pra "req.ip" refletir o visitante real (via // X-Forwarded-For) em vez do IP do nginx interno — ver nginx/nginx.conf, // que já repassa X-Forwarded-For a partir do reverse proxy externo. const app = Fastify({ logger: true, trustProxy: true }); await app.register(cors, { origin: true }); // Cache-Control é decidido no nginx interno (ver nginx/nginx.conf, // location /models/), não aqui — "immutable"/maxAge nesse nível conflitava // com o "no-cache" que o nginx adiciona por cima (dois headers // Cache-Control na mesma resposta, comportamento indefinido entre // navegadores), e ia contra o motivo do "no-cache": os .glb têm nome fixo // mas o CONTEÚDO muda toda vez que o pipeline roda de novo. await app.register(fastifyStatic, { root: MODELS_DIR, prefix: "/models/", decorateReply: false, etag: true, }); app.get("/api/health", async () => ({ status: "ok" })); await app.register(systemsRoutes); await app.register(structuresRoutes); await app.register(quizRoutes); await app.register(analyticsRoutes); await app.register(adminRoutes); await app.register(feedbackRoutes); const port = Number(process.env.PORT ?? 3333); app .listen({ port, host: "0.0.0.0" }) .catch((err) => { app.log.error(err); process.exit(1); });