diff --git a/src/app/api/dev/routes/route.ts b/src/app/api/dev/routes/route.ts index 98f2be72..a63a8a3a 100644 --- a/src/app/api/dev/routes/route.ts +++ b/src/app/api/dev/routes/route.ts @@ -1,4 +1,4 @@ -import { glob } from 'glob' +import { readdir } from 'fs/promises' import { NextResponse } from 'next/server' import path from 'path' import { requireDevToolsAccess } from '@/lib/dev-access' @@ -6,6 +6,31 @@ import { requireDevToolsAccess } from '@/lib/dev-access' export const dynamic = 'force-dynamic' // Ensure this route is dynamic +const PAGE_EXTENSIONS = new Set(['.tsx', '.js', '.jsx']) + +async function findPageFiles(rootDir: string, currentDir = rootDir): Promise { + const entries = await readdir(currentDir, { withFileTypes: true }) + const files = await Promise.all(entries.map(async entry => { + if (entry.name.startsWith('.') || entry.name.startsWith('_')) return [] + + const fullPath = path.join(currentDir, entry.name) + const relativePath = path.relative(rootDir, fullPath) + + if (entry.isDirectory()) { + if (entry.name === 'api') return [] + return findPageFiles(rootDir, fullPath) + } + + if (!entry.isFile()) return [] + + const parsed = path.parse(entry.name) + const isPageFile = parsed.name === 'page' && PAGE_EXTENSIONS.has(parsed.ext) + return isPageFile ? [relativePath] : [] + })) + + return files.flat() +} + // Helper to format route label function formatRouteLabel(routePath: string) { if (routePath === '/') return 'Home' @@ -28,17 +53,7 @@ export async function GET() { const cwd = process.cwd() const appDir = path.join(cwd, 'src/app') - // On Windows, glob returns forward slashes, but we should be careful with path joins - // We use fast-glob indirectly via glob, which supports forward slashes on Windows - const files = await glob('**/page.{tsx,js,jsx}', { - cwd: appDir, - ignore: [ - '**/api/**', // skip API routes - '**/_*/**', // skip private folders - '**/.*/**', // skip dotfiles/folders - ], - nodir: true - }) + const files = await findPageFiles(appDir) const routes = files.map(file => { // file is relative to appDir, e.g. "(marketing)/about/page.tsx" @@ -47,7 +62,7 @@ export async function GET() { const dirPath = path.dirname(file) // Split by separator (handle both / and \ just in case, though glob usually returns /) - const segments = dirPath.split(/[/\\]/) + const segments = dirPath.split(path.sep) const cleanSegments = segments.filter(segment => { // Remove route groups like (marketing)