Skip to content

Instantly share code, notes, and snippets.

@revskill10
Created July 14, 2023 16:22
Show Gist options
  • Save revskill10/10f0bb6e7a95f99ec5d2f5fea16f7f69 to your computer and use it in GitHub Desktop.
Save revskill10/10f0bb6e7a95f99ec5d2f5fea16f7f69 to your computer and use it in GitHub Desktop.
NextJS routes generation
import fs from 'fs';
import path from 'path';
function getCompName(filePath) {
const fileName = filePath.split('.')[0]
const componentName = fileName.replace(/\[|\]/g, '')
.split('/')
.filter(part => part !== 'routes')
.map(part => part.charAt(0).toUpperCase() + part.slice(1))
.join('');
const finalComponentName = componentName.charAt(0).toUpperCase() + componentName.slice(1);
return finalComponentName
}
export function generateRouteCode(folderPath, parentPath = './routes', collector = []) {
const files = fs.readdirSync(folderPath, { withFileTypes: true });
for (const file of files) {
if (file.isDirectory()) {
const folderName = file.name;
const currentPath = path.join(parentPath, folderName);
const layoutPath = path.join(folderPath, folderName, 'layout.js');
const pagePath = path.join(folderPath, folderName, 'page.js');
const layoutImport = `const ${getCompName(`${currentPath}/layout.js`)} = React.lazy(() => import("${currentPath}/layout.js"));`;
const pageImport = `const ${getCompName(`${currentPath}/page.js`)} = React.lazy(() => import("${currentPath}/page.js"));`;
collector.push(layoutImport);
collector.push(pageImport);
if (fs.existsSync(layoutPath) && fs.existsSync(pagePath)) {
const layoutRoute = `const ${getCompName(`${currentPath}/layout.js`)} = React.lazy(() => import("${currentPath}/layout.js"));`;
const pageRoute = `const ${getCompName(`${currentPath}/page.js`)} = React.lazy(() => import("${currentPath}/page.js"));`;
collector.push(layoutRoute);
collector.push(pageRoute);
}
generateRouteCode(path.join(folderPath, folderName), currentPath, collector);
}
}
}
import * as fs from 'fs';
import * as path from 'path';
import {generateRouteCode} from './genpath.mjs'
function walkFolderTree(currentPath) {
const folderName = path.basename(currentPath);
const files = fs.readdirSync(currentPath);
const layoutFile = files.find((file) => file === 'layout.tsx') || null;
const pageFile = files.find((file) => file === 'page.tsx') || null;
const subFolders = [];
files
.filter((file) => fs.statSync(path.join(currentPath, file)).isDirectory())
.forEach((subFolder) =>
subFolders.push(walkFolderTree(path.join(currentPath, subFolder)))
);
return { folderName, layoutFile, pageFile, subFolders };
}
function generateRoutes(folderEntry, basePath = '') {
const routes = [];
const { folderName, layoutFile, pageFile, subFolders } = folderEntry;
if (layoutFile && pageFile) {
const layoutImportPath = path.join(basePath, folderName, 'layout.js');
const pageImportPath = path.join(basePath, folderName, 'page.js');
const layoutComponentName = generateComponentName(`${folderName}Layout`);
const pageComponentName = generateComponentName(`${folderName}Page`);
const routePattern = `/${basePath}/${folderName}`;
const route = {
pattern: routePattern.replace('/routes',''),
Component: `
<${layoutComponentName}>
<${pageComponentName} />
</${layoutComponentName}>`,
layoutComponentName,
pageComponentName,
};
routes.push(route);
subFolders.forEach((subFolder) => {
const subFolderPath = path.join(basePath, folderName);
const subRoutes = generateRoutes(subFolder, subFolderPath);
subRoutes.forEach((subRoute) => {
subRoute.Component =
`<${route.layoutComponentName}>
${subRoute.Component}
</${route.layoutComponentName}>`
});
routes.push(...subRoutes);
});
}
return routes;
}
function generateComponentName(name) {
const sanitizedName = name.replace(/\[|\]/g, '');
const words = sanitizedName.split('-');
const capitalizedWords = words.map((word) => word.charAt(0).toUpperCase() + word.slice(1));
return capitalizedWords.join('');
}
function generateRoutesFile(routes, filePath) {
const collector = []
generateRouteCode('./routes', './routes', collector)
const imports = collector.join('\n');
const routeComponents = routes
.map(
(route) =>
`{ pattern: "${route.pattern}", Component: (props) => ${route.Component.replace('\n \n', '')} }`
)
.join(',\n');
const content = `import React from 'react';
${imports}
const routes = [
${routeComponents}
];
export default routes;
`;
fs.writeFileSync(filePath, content);
}
// Usage
const rootFolderPath = 'routes';
const folderTree = walkFolderTree(rootFolderPath);
const routes = generateRoutes(folderTree);
const routesFilePath = 'routes.tsx';
generateRoutesFile(routes, routesFilePath);
console.log(`Routes generated and saved to ${routesFilePath}`);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment