File size: 4,670 Bytes
3d23b0f |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 |
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;
}
|