/** * @fileoverview Route registration module for Aurora API. * Aggregates all route handlers and provides a unified request handler. */ import type { RouteContext, RouteModule } from "./types"; import { authRoutes, isAuthenticated, getSession } from "./auth.routes"; import { healthRoutes } from "./health.routes"; import { statsRoutes } from "./stats.routes"; import { actionsRoutes } from "./actions.routes"; import { questsRoutes } from "./quests.routes"; import { settingsRoutes } from "./settings.routes"; import { guildSettingsRoutes } from "./guild-settings.routes"; import { itemsRoutes } from "./items.routes"; import { usersRoutes } from "./users.routes"; import { classesRoutes } from "./classes.routes"; import { moderationRoutes } from "./moderation.routes"; import { transactionsRoutes } from "./transactions.routes"; import { lootdropsRoutes } from "./lootdrops.routes"; import { assetsRoutes } from "./assets.routes"; import { errorResponse } from "./utils"; /** Routes that do NOT require authentication */ const publicRoutes: RouteModule[] = [ authRoutes, healthRoutes, ]; /** Routes that require an authenticated admin session */ const protectedRoutes: RouteModule[] = [ statsRoutes, actionsRoutes, questsRoutes, settingsRoutes, guildSettingsRoutes, itemsRoutes, usersRoutes, classesRoutes, moderationRoutes, transactionsRoutes, lootdropsRoutes, assetsRoutes, ]; /** * Main request handler that routes requests to appropriate handlers. * * @param req - The incoming HTTP request * @param url - Parsed URL object * @returns Response from matching route handler, or null if no match * * @example * const response = await handleRequest(req, url); * if (response) return response; * return new Response("Not Found", { status: 404 }); */ export async function handleRequest(req: Request, url: URL): Promise { const ctx: RouteContext = { req, url, method: req.method, pathname: url.pathname, }; // Try public routes first (auth, health) for (const module of publicRoutes) { const response = await module.handler(ctx); if (response !== null) return response; } // For API routes, enforce authentication if (ctx.pathname.startsWith("/api/")) { const session = getSession(req); if (!session) { return errorResponse("Unauthorized", 401); } // Admin-only routes: everything except stats and own user data const playerAllowedPrefixes = ["/api/stats", "/api/health"]; const isPlayerAllowed = playerAllowedPrefixes.some(p => ctx.pathname.startsWith(p)); // Players can access their own user data const isOwnUserRoute = ctx.pathname.match(/^\/api\/users\/\d+/) && session.role === "player"; if (session.role === "player" && !isPlayerAllowed && !isOwnUserRoute) { return errorResponse("Admin access required", 403); } } // Try protected routes for (const module of protectedRoutes) { const response = await module.handler(ctx); if (response !== null) return response; } return null; } /** * Get list of all registered route module names. * Useful for debugging and documentation. */ export function getRegisteredRoutes(): string[] { return [...publicRoutes, ...protectedRoutes].map(m => m.name); }