react-smart-routes
Version:
A zero-config file-based routing system for React using the src/pages directory, inspired by Next.js.
77 lines (63 loc) • 2.08 kB
JavaScript
import fs from "fs";
import path from "path";
import { fileURLToPath } from "url";
import chalk from "chalk";
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const PAGES_DIR = path.join(process.cwd(), "src/pages");
const OUTPUT_FILE = path.join(process.cwd(), "src/routes.generated.jsx");
// Recursively walk through pages folder
function walk(dir) {
let results = [];
const list = fs.readdirSync(dir);
list.forEach((file) => {
const full = path.join(dir, file);
const stat = fs.statSync(full);
if (stat && stat.isDirectory()) {
results = results.concat(walk(full));
} else if (file.endsWith(".jsx")) {
results.push(full);
}
});
return results;
}
// Convert file path to route path
function getRoutePath(relPath) {
return (
"/" +
relPath
.replace(/\.jsx$/, "")
.replace(/\[([^\]]+)\]/g, ":$1")
.replace(/\/index$/, "")
.toLowerCase()
);
}
// Create component name
function toComponentName(_, index) {
return `Page${index}`;
}
// Main
function generateRoutes() {
if (!fs.existsSync(PAGES_DIR)) {
console.error(chalk.red(`❌ Pages folder not found at: ${PAGES_DIR}`));
process.exit(1);
}
const files = walk(PAGES_DIR);
const imports = [];
const routes = [];
files.forEach((file, index) => {
const relPath = path.relative(PAGES_DIR, file).replace(/\\/g, "/");
const importPath = `./pages/${relPath}`;
const routePath = getRoutePath(relPath);
const component = toComponentName(file, index);
imports.push(`import ${component} from "${importPath}";`);
routes.push(`{ path: "${routePath}", element: <${component} /> }`);
});
const content = `import React from "react";\n${imports.join(
"\n"
)}\n\nexport const routes = [\n ${routes.join(",\n ")}\n];\n`;
fs.writeFileSync(OUTPUT_FILE, content);
console.log(chalk.green("✅ routes.generated.jsx created successfully!"));
}
generateRoutes();