import { routes, routeMatchers } from '../routing/RouteConfig'; /** * RouteCatalog exposes route IDs and patterns for matching * * Route IDs follow the pattern: 'category.routeName' * Examples: * - 'auth.login' → '/auth/login' * - 'protected.dashboard' → '/dashboard' * - 'league.detail' → '/leagues/[id]' (pattern) */ export class RouteCatalog { /** * List all public route IDs * Public routes are accessible without authentication */ listPublicRoutes(): string[] { return [ 'public.home', 'public.leagues', 'public.drivers', 'public.teams', 'public.leaderboards', 'public.races', 'public.sponsorSignup', 'auth.login', 'auth.signup', 'auth.forgotPassword', 'auth.resetPassword', 'auth.iRacingStart', 'auth.iRacingCallback', 'error.notFound', 'error.serverError', // Parameterized public routes 'league.detail', 'league.rulebook', 'league.schedule', 'league.standings', 'driver.detail', 'team.detail', 'race.detail', 'race.results', 'race.all', ]; } /** * List all protected route IDs * Protected routes require authentication */ listProtectedRoutes(): string[] { return [ 'protected.dashboard', 'protected.onboarding', 'protected.profile', 'protected.profileSettings', 'protected.profileLeagues', 'protected.profileLiveries', 'protected.profileLiveryUpload', 'protected.profileSponsorshipRequests', 'sponsor.root', 'sponsor.dashboard', 'sponsor.billing', 'sponsor.campaigns', 'sponsor.leagues', 'sponsor.settings', 'admin.root', 'admin.users', 'league.create', 'race.root', 'team.root', 'team.leaderboard', ]; } /** * List all admin route IDs * Admin routes require admin-level permissions */ listAdminRoutes(): string[] { return [ 'admin.root', 'admin.users', 'league.rosterAdmin', 'league.scheduleAdmin', 'league.stewarding', 'league.settings', 'league.sponsorships', 'league.wallet', 'race.stewarding', ]; } /** * List all sponsor route IDs * Sponsor routes require sponsor role */ listSponsorRoutes(): string[] { return [ 'sponsor.root', 'sponsor.dashboard', 'sponsor.billing', 'sponsor.campaigns', 'sponsor.leagues', 'sponsor.settings', ]; } /** * Get the path pattern for a route ID * @param routeId - Route ID in format 'category.routeName' * @returns Path pattern (e.g., '/auth/login' or '/leagues/[id]') * @throws Error if route ID is unknown */ getPattern(routeId: string): string { const parts = routeId.split('.'); let route: any = routes; for (const part of parts) { route = route[part]; if (!route) { throw new Error(`Unknown route ID: ${routeId}`); } } // Handle parameterized routes if (typeof route === 'function') { // Return pattern with placeholder const paramPattern = route('placeholder'); return paramPattern.replace('/placeholder', '/[id]'); } return route as string; } /** * Check if a path is an auth page * @param logicalPath - Path to check * @returns True if path is an auth page */ isAuthPage(logicalPath: string): boolean { return routeMatchers.isInGroup(logicalPath, 'auth'); } /** * Get all route patterns with their IDs * @returns Array of route patterns with IDs */ getAllPatterns(): Array<{ routeId: string; pattern: string }> { const patterns: Array<{ routeId: string; pattern: string }> = []; // Helper to traverse routes and build patterns const traverse = (obj: any, prefix: string) => { for (const [key, value] of Object.entries(obj)) { const routeId = prefix ? `${prefix}.${key}` : key; if (typeof value === 'function') { // Parameterized route const pattern = value('placeholder').replace('/placeholder', '/[id]'); patterns.push({ routeId, pattern }); } else if (typeof value === 'object' && value !== null) { // Nested category traverse(value, routeId); } else if (typeof value === 'string') { // Simple route patterns.push({ routeId, pattern: value }); } } }; traverse(routes, ''); return patterns; } /** * Get route ID by path * @param path - Path to find * @returns Route ID or null if not found * * Note: This method prioritizes exact matches over parameterized matches. * For example, '/leagues/create' will match 'league.create' before 'league.detail'. */ getRouteIdByPath(path: string): string | null { const allPatterns = this.getAllPatterns(); // First, try exact matches for (const { routeId, pattern } of allPatterns) { if (pattern === path) { return routeId; } } // Then, try parameterized matches for (const { routeId, pattern } of allPatterns) { if (pattern.includes('[')) { const paramPattern = pattern.replace(/\[([^\]]+)\]/g, '([^/]+)'); const regex = new RegExp(`^${paramPattern}$`); if (regex.test(path)) { return routeId; } } } return null; } /** * Check if a path requires specific role-based access * @param logicalPath - Path to check * @returns Array of required roles or null */ getRequiredRoles(logicalPath: string): string[] | null { // Check admin routes if (routeMatchers.isInGroup(logicalPath, 'admin')) { return ['system-owner', 'super-admin', 'league-admin']; } // Check sponsor routes if (routeMatchers.isInGroup(logicalPath, 'sponsor')) { return ['sponsor']; } // Check league admin routes (specific patterns) if (logicalPath.match(/\/leagues\/[^/]+\/(roster\/admin|schedule\/admin|stewarding|settings|sponsorships|wallet)/)) { return ['system-owner', 'super-admin', 'league-admin']; } // Check race stewarding routes if (logicalPath.match(/\/races\/[^/]+\/stewarding/)) { return ['system-owner', 'super-admin', 'league-steward']; } // Public or auth-only routes (no specific role) return null; } /** * Get the home path for a specific role * @param role - The role name * @returns The logical path for that role's home page */ getRoleHome(role: string): string { const roleHomeMap: Record = { 'driver': '/dashboard', 'sponsor': '/sponsor/dashboard', 'league-admin': '/admin', 'league-steward': '/admin', 'league-owner': '/admin', 'system-owner': '/admin', 'super-admin': '/admin', }; return roleHomeMap[role] || '/dashboard'; } /** * Get the route ID for a specific role's home page * @param role - The role name * @returns The route ID for that role's home page */ getRoleHomeRouteId(role: string): string { const roleHomeRouteMap: Record = { 'driver': 'protected.dashboard', 'sponsor': 'sponsor.dashboard', 'league-admin': 'admin', 'league-steward': 'admin', 'league-owner': 'admin', 'system-owner': 'admin', 'super-admin': 'admin', }; return roleHomeRouteMap[role] || 'protected.dashboard'; } }