Created
July 14, 2023 16:22
-
-
Save revskill10/10f0bb6e7a95f99ec5d2f5fea16f7f69 to your computer and use it in GitHub Desktop.
NextJS routes generation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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