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
JavaScript
// 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 };