UNPKG

stratakit

Version:

stratakit - Meta-framework React puro con Auto Router automático, file-based routing, SEO automático y performance superior

137 lines (136 loc) 4.75 kB
// Auto Router - Sistema automático de rutas basado en estructura de carpetas // Funciona como Next.js App Router - invisible para el programador class AutoRouterManager { routes = new Map(); config; isInitialized = false; constructor(config = {}) { this.config = { basePath: '/app', excludePatterns: ['**/__tests__/**', '**/node_modules/**', '**/*.test.*', '**/*.spec.*'], includePatterns: ['**/*.tsx', '**/*.jsx'], ...config }; } // Escanea automáticamente las carpetas y genera rutas async scanAndGenerateRoutes() { if (this.isInitialized) { return this.convertToRoutes(); } try { // En un entorno real, esto escanearía el filesystem // Por ahora, simulamos el escaneo basado en la estructura conocida const discoveredRoutes = await this.discoverRoutes(); // Procesar rutas descubiertas for (const route of discoveredRoutes) { this.routes.set(route.path, route); } this.isInitialized = true; return this.convertToRoutes(); } catch (error) { console.error('Error scanning routes:', error); return []; } } // Simula el descubrimiento de rutas basado en la estructura de carpetas async discoverRoutes() { // Esta función en un entorno real usaría fs.readdirSync o similar // para escanear la estructura de carpetas const discoveredRoutes = [ // Ruta raíz { path: '/', component: () => null, // Placeholder component isLayout: false, isIndex: true, isDynamic: false }, // Ruta about { path: '/about', component: () => null, // Placeholder component isLayout: false, isIndex: false, isDynamic: false }, // Rutas de blog { path: '/blog', component: () => null, // Placeholder component isLayout: false, isIndex: true, isDynamic: false }, // Ruta dinámica de blog { path: '/blog/:slug', component: () => null, // Placeholder component isLayout: false, isIndex: false, isDynamic: true, dynamicParam: 'slug' } ]; return discoveredRoutes; } // Convierte las rutas del filesystem a rutas del router convertToRoutes() { const routes = []; for (const [path, fsRoute] of this.routes) { routes.push({ path: fsRoute.path, component: fsRoute.component, exact: !fsRoute.isDynamic, title: this.generateTitle(path), meta: { title: this.generateTitle(path), description: `Página ${path}`, keywords: [path.split('/').filter(Boolean).join(' ')] } }); } return routes; } // Genera títulos automáticamente basados en la ruta generateTitle(path) { if (path === '/') return 'Inicio'; const segments = path.split('/').filter(Boolean); const lastSegment = segments[segments.length - 1]; // Convertir slug a título legible return lastSegment .replace(/[-_]/g, ' ') .replace(/\b\w/g, l => l.toUpperCase()); } // Obtiene rutas por patrón getRoutesByPattern(pattern) { const regex = new RegExp(pattern); return this.convertToRoutes().filter(route => regex.test(route.path)); } // Obtiene rutas dinámicas getDynamicRoutes() { return this.convertToRoutes().filter(route => route.path.includes(':')); } // Obtiene rutas de layout getLayoutRoutes() { return this.convertToRoutes().filter(route => route.path.includes('layout')); } // Verifica si una ruta existe hasRoute(path) { return this.routes.has(path); } // Obtiene información de una ruta específica getRouteInfo(path) { return this.routes.get(path); } // Reinicia el escaneo (útil en desarrollo) async refresh() { this.isInitialized = false; this.routes.clear(); return this.scanAndGenerateRoutes(); } } // Instancia global del auto router const autoRouter = new AutoRouterManager(); export { autoRouter, AutoRouterManager };