rr-next-routes
Version:
generate nextjs-style routes in your react-router-v7 application
1 lines • 23.4 kB
Source Map (JSON)
{"version":3,"sources":["../../src/react-router/index.ts","../../src/common/next-routes-common.ts","../../src/common/utils.ts"],"sourcesContent":["import {\n appRouterStyle,\n generateNextRoutes,\n pageRouterStyle,\n type Options\n} from \"../common/next-routes-common\";\nimport {type RouteConfigEntry, getAppDirectory, route, layout, index} from \"@react-router/dev/routes\";\n\n/**\n * @deprecated The method should not be used anymore. please use {@link nextRoutes} instead.\n */\nexport function generateRouteConfig(options: Options = appRouterStyle): RouteConfigEntry[] {\n return nextRoutes(options);\n}\n\n/**\n * Generates route configuration from a Next.js-style pages directory for React Router\n */\nexport function nextRoutes(options: Options = appRouterStyle): RouteConfigEntry[] {\n return generateNextRoutes(\n options,\n getAppDirectory,\n index,\n route,\n layout\n );\n}\n\nexport {\n appRouterStyle,\n pageRouterStyle,\n type Options,\n type RouteConfigEntry\n};","import {readdirSync, statSync} from 'node:fs';\nimport {join, parse, relative, resolve} from 'node:path';\nimport {\n deepSortByPath,\n isHoistedFolder,\n parseParameter,\n printRoutesAsTable,\n printRoutesAsTree,\n transformRoutePath\n} from \"./utils\";\nimport {RouteConfigEntry} from \"./types\";\n\ntype PrintOption = \"no\" | \"info\" | \"table\" | \"tree\";\n\nexport const appRouterStyle: Options = {\n folderName: \"\",\n print: \"info\",\n layoutFileName: \"layout\",\n routeFileNames: [\"page\", \"route\"], // in nextjs this is the difference between a page (with components) and an api route (without components). in react-router an api route (resource route) just does not export a default component. \n extensions: [\".tsx\", \".ts\", \".jsx\", \".js\"],\n routeFileNameOnly: true, // all files with names different from routeFileNames get no routes\n enableHoistedFolders: false,\n};\n\nexport const pageRouterStyle: Options = {\n folderName: \"pages\",\n print: \"info\",\n layoutFileName: \"_layout\", //layouts do no exist like that in nextjs pages router so we use a special file.\n routeFileNames: [\"index\"],\n extensions: [\".tsx\", \".ts\", \".jsx\", \".js\"],\n routeFileNameOnly: false, // all files without a leading underscore get routes as long as the extension matches\n enableHoistedFolders: false,\n};\n\nexport type Options = {\n folderName?: string;\n layoutFileName?: string;\n routeFileNames?: string[];\n routeFileNameOnly?: boolean;\n extensions?: string[];\n print?: PrintOption;\n enableHoistedFolders?: boolean;\n};\n\nconst defaultOptions: Options = appRouterStyle;\n\n/**\n * Creates a route configuration for a file or directory\n * @param name - Name of the file or directory\n * @param parentPath - Current path in the route hierarchy\n * @param relativePath - Relative path to the file from pages directory\n * @param folderName - Name of the current folder (needed for dynamic routes)\n * @param routeFileNames - name of the index routes\n * @param indexCreator - Function to create an index entry\n * @param routeCreator - Function to create a route entry\n * @returns Route configuration entry\n */\nexport function createRouteConfig(\n name: string,\n parentPath: string,\n relativePath: string,\n folderName: string,\n routeFileNames: string[],\n indexCreator: (path: string) => RouteConfigEntry,\n routeCreator: (path: string, file: string) => RouteConfigEntry\n): RouteConfigEntry {\n // Handle index routes in dynamic folders\n if (routeFileNames.includes(name) && folderName.startsWith('[') && folderName.endsWith(']')) {\n const {routeName} = parseParameter(folderName);\n const routePath = parentPath === '' ? routeName : `${parentPath.replace(folderName, '')}${routeName}`;\n return routeCreator(transformRoutePath(routePath), relativePath);\n }\n\n // Handle regular index routes\n if (routeFileNames.includes(name)) {\n // This is an index route - should use the index function\n if (parentPath === \"\") {\n // Root index route - should be an index route\n return indexCreator(relativePath); // Use the index function instead of route\n } else {\n // Nested index route\n return routeCreator(transformRoutePath(parentPath), relativePath);\n }\n }\n\n // Handle dynamic and regular routes\n const {routeName} = parseParameter(name);\n const routePath = parentPath === '' ? `/${routeName}` : `${parentPath}/${routeName}`;\n return routeCreator(transformRoutePath(routePath), relativePath);\n}\n\n/**\n * Generates route configuration from a Next.js-style pages directory\n * @param options - Configuration options for route generation\n * @param getAppDir - Function to get the app directory\n * @param indexCreator - Function to create an index entry\n * @param routeCreator - Function to create a route entry\n * @param layoutCreator - Function to create a layout entry\n * @returns Array of route configurations\n */\nexport function generateNextRoutes(\n options: Options = defaultOptions,\n getAppDir: () => string,\n indexCreator: (path: string) => RouteConfigEntry,\n routeCreator: (path: string, file: string) => RouteConfigEntry,\n layoutCreator: (file: string, children: RouteConfigEntry[]) => RouteConfigEntry\n): RouteConfigEntry[] {\n const {\n folderName: baseFolder = defaultOptions.folderName!,\n print: printOption = defaultOptions.print!,\n extensions = defaultOptions.extensions!,\n layoutFileName = defaultOptions.layoutFileName!,\n routeFileNames = defaultOptions.routeFileNames!,\n routeFileNameOnly = defaultOptions.routeFileNameOnly!,\n enableHoistedFolders = defaultOptions.enableHoistedFolders!,\n } = options;\n\n let appDirectory = getAppDir();\n\n const pagesDir = resolve(appDirectory, baseFolder);\n\n /**\n * Scans a directory and returns its contents\n * @param dirPath - Path to the directory to scan\n */\n function scanDir(dirPath: string) {\n return {\n folderName: parse(dirPath).base,\n files: readdirSync(dirPath).sort((a, b) => {\n const {ext: aExt, name: aName} = parse(a);\n return ((routeFileNames.includes(aName) && extensions.includes(aExt)) ? -1 : 1)\n })\n };\n }\n\n /**\n * Recursively scans directory and generates route configurations\n * @param dir - Current directory path\n * @param parentPath - Current path in route hierarchy\n */\n function scanDirectory(dir: string, parentPath: string = ''): RouteConfigEntry[] {\n const routes: RouteConfigEntry[] = [];\n const {files, folderName} = scanDir(dir);\n const layoutFile = files.find(item => {\n const {ext, name} = parse(item);\n return (name === layoutFileName && extensions.includes(ext));\n });\n const currentLevelRoutes: RouteConfigEntry[] = [];\n\n // Process each file in the directory\n files.forEach(item => {\n // Early return for excluded items\n if (item.startsWith('_')) return;\n\n const fullPath = join(dir, item);\n const stats = statSync(fullPath);\n const {name, ext, base} = parse(item);\n const relativePath = join(baseFolder, relative(pagesDir, fullPath));\n\n // Don't create accessible routes for layout files.\n if (layoutFileName && name === layoutFileName) return;\n\n if (stats.isDirectory()) {\n // Handle nested directories\n const nestedRoutes = scanDirectory(fullPath, `${parentPath}/${base}`);\n (layoutFile && !(enableHoistedFolders && isHoistedFolder(name)) ? currentLevelRoutes : routes).push(...nestedRoutes);\n } else if (extensions.includes(ext)) {\n // Early return if strict file names are enabled and the current item is not in the list.\n if (routeFileNameOnly && !routeFileNames.includes(name)) return;\n const routeConfig = createRouteConfig(name, parentPath, relativePath, folderName, routeFileNames, indexCreator, routeCreator);\n (layoutFile ? currentLevelRoutes : routes).push(routeConfig);\n }\n });\n if (layoutFile) {\n const layoutPath = join(baseFolder, relative(pagesDir, join(dir, layoutFile)));\n routes.push(layoutCreator(layoutPath, currentLevelRoutes));\n } else {\n routes.push(...currentLevelRoutes);\n }\n\n return routes;\n }\n\n const results = scanDirectory(pagesDir);\n\n // Handle printing options\n switch (printOption) {\n case \"tree\":\n printRoutesAsTree(results);\n break;\n case \"table\":\n printRoutesAsTable(results);\n break;\n case \"info\":\n console.log(\"✅ Generated Routes\");\n break;\n case \"no\":\n break;\n }\n\n return deepSortByPath(results);\n}\n","// This file contains utility functions for route generation\nimport {RouteConfigEntry} from \"./types\";\n\nexport function transformRoutePath(path: string): string {\n let transformedPath = path\n .replace(/\\[\\[\\s*([^\\]]+)\\s*]]/g, ':$1?') // Handle optional parameters [[param]]\n .replace(/\\[\\.\\.\\.\\s*([^\\]]+)\\s*]/g, '*') // Handle catch-all parameters [...param]\n .replace(/\\[([^\\]]+)]/g, ':$1') // Handle regular parameters [param]\n .replace(/\\/\\([^)]*\\)\\//g, '/') // Handle regular parameters [param]\n .replace(/\\{([^}]+)\\}/g, '$1') // Strip curly braces {param}\n .replace(/\\/\\([^)]*\\)/g, ''); // Remove parentheses and contents only if surrounded by slashes\n \n if(transformedPath === \"\") {\n transformedPath = \"/\" + transformedPath;\n }\n \n return transformedPath;\n}\n\nexport function isHoistedFolder(name: string): boolean {\n return /^{[^{}]+}$/.test(name);\n}\n\nfunction parseDynamicRoute(name: string): { paramName?: string; routeName: string } {\n const paramMatch = name.match(/\\[(.+?)]/);\n if (!paramMatch) return {routeName: name};\n\n const paramName = paramMatch[1];\n return {\n paramName,\n routeName: `:${paramName}`\n };\n}\n\nfunction parseCatchAllParam(name: string): { paramName?: string; routeName: string } {\n const paramMatch = name.match(/\\[\\.\\.\\.(.+?)]/);\n if (!paramMatch) return {routeName: name};\n\n const paramName = paramMatch[1];\n return {\n paramName,\n routeName: \"*\" // Placeholder to indicate \"catch-all\" route for now\n };\n}\n\nfunction parseOptionalDynamicRoute(name: string): { paramName?: string; routeName: string } {\n const paramMatch = name.match(/\\[\\[(.+?)]]/);\n if (!paramMatch) return {routeName: name};\n\n const paramName = paramMatch[1];\n return {\n paramName,\n routeName: `:${paramName}?`\n };\n}\n\nexport function parseParameter(name: string): { paramName?: string; routeName: string } {\n if (name.startsWith('[[') && name.endsWith(']]')) {\n // Optional parameter format: [[param]]\n return parseOptionalDynamicRoute(name);\n } else if (name.startsWith('[...') && name.endsWith(']')) {\n // Catch-all parameter format: [...param]\n return parseCatchAllParam(name);\n } else if (name.startsWith('[') && name.endsWith(']')) {\n // Regular parameter format: [param]\n return parseDynamicRoute(name);\n } else {\n // Not a dynamic parameter\n return {routeName: name};\n }\n}\n\nexport function deepSortByPath(value: any): any {\n if (Array.isArray(value)) {\n // Recursively sort arrays based on 'path'\n return value\n .map(deepSortByPath) // Sort children first\n .sort((a: any, b: any) => compareByPath(a, b));\n }\n\n if (typeof value === 'object' && value !== null) {\n if ('path' in value) {\n // If the object has a 'path' property, sort its children if any\n return {\n ...value,\n children: value.children ? deepSortByPath(value.children) : undefined,\n };\n }\n\n // Sort object keys for non-'path' objects\n return Object.keys(value)\n .sort()\n .reduce((acc, key) => {\n acc[key] = deepSortByPath(value[key]);\n return acc;\n }, {} as Record<string, any>);\n }\n\n return value; // Primitive values\n}\n\nfunction compareByPath(a: any, b: any): number {\n const pathA = a.path || '';\n const pathB = b.path || '';\n\n // Check if either file path contains a hoisted folder\n const aHoisted = a.file?.includes('/{');\n const bHoisted = b.file?.includes('/{');\n\n // If one is hoisted and the other isn't, hoisted should come first\n if (aHoisted && !bHoisted) return -1;\n if (!aHoisted && bHoisted) return 1;\n\n // If both are hoisted or both are not, sort by path\n return pathA.localeCompare(pathB);\n}\n\nexport function printRoutesAsTable(routes: RouteConfigEntry[]): void {\n function extractRoutesForTable(routes: RouteConfigEntry[], parentLayout: string | null = null): {\n routePath: string;\n routeFile: string;\n parentLayout?: string\n }[] {\n const result: { routePath: string; routeFile: string; parentLayout?: string }[] = [];\n\n // Sort routes alphabetically based on `path`. Use `file` for sorting if `path` is undefined.\n const sortedRoutes = routes.sort((a, b) => {\n const pathA = a.path ?? ''; // Default to empty string if `path` is undefined\n const pathB = b.path ?? '';\n return pathA.localeCompare(pathB);\n });\n\n // Separate routes into paths and layouts\n const pathsFirst = sortedRoutes.filter(route => route.path); // Routes with a `path`\n const layoutsLast = sortedRoutes.filter(route => !route.path && route.children); // Layouts only\n\n // Add all routes with `path` first\n pathsFirst.forEach(route => {\n result.push({\n routePath: route.path!,\n routeFile: route.file,\n parentLayout: parentLayout ?? undefined\n });\n });\n\n // Add all layouts and recurse into their children\n layoutsLast.forEach(layout => {\n result.push({\n routePath: \"(layout)\",\n routeFile: layout.file,\n parentLayout: parentLayout ?? undefined\n });\n\n if (layout.children) {\n const layoutChildren = extractRoutesForTable(layout.children, layout.file); // Recurse with layout's file as parent\n result.push(...layoutChildren);\n }\n });\n\n return result;\n }\n\n console.groupCollapsed(\"✅ Generated Routes Table (open to see generated routes)\");\n console.table(extractRoutesForTable(routes));\n console.groupEnd();\n}\n\nexport function printRoutesAsTree(routes: RouteConfigEntry[], indent = 0): void {\n function printRouteTree(routes: RouteConfigEntry[], indent = 0): void {\n const indentation = ' '.repeat(indent); // Indentation for the tree\n\n // Sort routes alphabetically:\n const sortedRoutes = routes.sort((a, b) => {\n const pathA = a.path ?? ''; // Use empty string if `path` is undefined\n const pathB = b.path ?? '';\n return pathA.localeCompare(pathB); // Compare paths alphabetically\n });\n\n // Separate routes from layouts\n const pathsFirst = sortedRoutes.filter(route => route.path); // Routes with \"path\"\n const layoutsLast = sortedRoutes.filter(route => !route.path && route.children); // Layouts only\n\n // Print the routes\n pathsFirst.forEach(route => {\n const routePath = `\"${route.path}\"`;\n console.log(`${indentation}├── ${routePath} (${route.file})`);\n });\n\n // Print the layouts and recursively handle children\n layoutsLast.forEach(route => {\n console.log(`${indentation}├── (layout) (${route.file})`);\n if (route.children) {\n printRouteTree(route.children, indent + 1); // Recursive call for children\n }\n });\n }\n\n console.groupCollapsed(\"✅ Generated Route Tree (open to see generated routes)\");\n printRouteTree(routes, indent);\n console.groupEnd();\n}"],"mappings":"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","names":["routes","route","layout","indent","routeName","routePath"]}