import Fastify, { FastifyRequest, FastifyReply } from "fastify"; import cors from "@fastify/cors"; import swagger from "@fastify/swagger"; import swaggerUi from "@fastify/swagger-ui"; import config from "./config/env"; import { leetcodePlugin } from "./modules/leetcode"; import { codeforcesPlugin } from "./modules/codeforces"; import { codechefPlugin } from "./modules/codechef"; import { atcoderPlugin } from "./modules/atcoder"; import { gfgPlugin } from "./modules/gfg"; import { ratingsPlugin } from "./modules/ratings"; import { mcpPlugin } from "./modules/mcp"; export async function buildApp() { const fastify = Fastify({ logger: true, }); fastify.setErrorHandler((error: any, request, reply) => { fastify.log.error(error); const statusCode = error.statusCode || 500; reply.status(statusCode).send({ success: false, error: error.name || 'InternalServerError', message: error.message || 'An unexpected error occurred', }); }); await fastify.register(cors, { exposedHeaders: ['WWW-Authenticate', 'Mcp-Session-Id', 'Last-Event-Id', 'Mcp-Protocol-Version'], origin: '*', }); await fastify.register(swagger, { openapi: { info: { title: "Vortex", description: "A high-performance modular API to fetch competitive programming contest ratings and user statistics from platforms like LeetCode, Codeforces, CodeChef, and more. Built with Fastify and TypeScript.", version: "1.0.0", contact: { name: "GitHub", url: "https://github.com/Anujjoshi3105/vortex", }, license: { name: "ISC", url: "https://opensource.org/licenses/ISC", }, }, servers: [ { url: `http://localhost:${config.port}`, description: 'Development server', }, ], tags: [ { name: 'Default', description: 'General server health and infrastructure endpoints' }, { name: 'MCP', description: 'Model Context Protocol endpoints for AI agent integration' }, { name: 'Ratings', description: 'Cross-platform rating aggregation and comparison' }, { name: 'LeetCode - User', description: 'Fetch user profiles, badges, solved statistics, and submission history' }, { name: 'LeetCode - Contests', description: 'Access contest rankings, history, and upcoming competition data' }, { name: 'LeetCode - Problems', description: 'Retrieve daily challenges, problem details, and official solutions' }, { name: 'LeetCode - Discussion', description: 'Explore trending topics and community comments' }, { name: 'Codeforces - User', description: 'Fetch user profiles, ratings, contest history, and blogs' }, { name: 'Codeforces - Contests', description: 'Access contest standings, hacks, and rating changes' }, { name: 'Codeforces - Problems', description: 'Retrieve problemset and recent platform submissions' }, { name: 'Codeforces - Blog', description: 'Explore blog entries and community comments' }, { name: 'CodeChef', description: 'CodeChef platform integration' }, { name: 'AtCoder', description: 'AtCoder platform integration' }, { name: 'GFG', description: 'GeeksforGeeks platform integration for user profiles, submissions, posts, and contest leaderboards' }, ], }, }); await fastify.register(swaggerUi, { routePrefix: "/docs", uiConfig: { docExpansion: 'list', deepLinking: true, filter: true, }, staticCSP: true, transformStaticCSP: (header) => header, }); fastify.get("/health", { schema: { tags: ['Default'] } }, async (request: FastifyRequest, reply: FastifyReply) => { return { status: "ok" }; }); await fastify.register(mcpPlugin); await fastify.register(ratingsPlugin, { prefix: "/api/v1/ratings" }); await fastify.register(leetcodePlugin, { prefix: "/api/v1/leetcode" }); await fastify.register(codeforcesPlugin, { prefix: "/api/v1/codeforces" }); await fastify.register(codechefPlugin, { prefix: "/api/v1/codechef" }); await fastify.register(atcoderPlugin, { prefix: "/api/v1/atcoder" }); await fastify.register(gfgPlugin, { prefix: "/api/v1/gfg" }); return fastify; }