| Server IP : 159.203.156.69 / Your IP : 216.73.217.172 Web Server : nginx/1.24.0 System : Linux main-ubuntu 6.8.0-71-generic #71-Ubuntu SMP PREEMPT_DYNAMIC Tue Jul 22 16:52:38 UTC 2025 x86_64 User : root ( 0) PHP Version : 8.3.6 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : OFF | Sudo : ON | Pkexec : OFF Directory : /var/www/tanviranik.com/node_modules/vinext/dist/routing/ |
Upload File : |
{"version":3,"file":"app-route-graph.js","names":[],"sources":["../../src/routing/app-route-graph.ts"],"sourcesContent":["/**\n * App Router route graph construction.\n *\n * Scans app/ directories and materializes route metadata before the request-time\n * matcher consumes it. Keep request matching and cache ownership in app-router.ts.\n */\nimport path from \"node:path\";\nimport fs from \"node:fs\";\nimport { createHash } from \"node:crypto\";\nimport { compareRoutes, decodeRouteSegment } from \"./utils.js\";\nimport { scanWithExtensions, type ValidFileMatcher } from \"./file-matcher.js\";\nimport { validateRoutePatterns } from \"./route-validation.js\";\n\nexport type InterceptingRoute = {\n /** The interception convention: \".\" | \"..\" | \"../..\" | \"...\" */\n convention: string;\n /** The URL pattern this intercepts (e.g. \"/photos/:id\") */\n targetPattern: string;\n /** Absolute path to the intercepting page component */\n pagePath: string;\n /** Absolute layout paths inside the intercepting route tree, outermost to innermost */\n layoutPaths: string[];\n /** Parameter names for dynamic segments */\n params: string[];\n};\n\nexport type ParallelSlot = {\n /** Graph-owned semantic slot identity. Required on AppRouteGraphParallelSlot. */\n id?: string;\n /** Stable slot identity (name + owning directory), used for route serialization keys. */\n key: string;\n /** Slot name (e.g. \"team\" from @team) */\n name: string;\n /** Absolute path to the @slot directory that owns this slot. Internal routing metadata. */\n ownerDir: string;\n /** Stable tree path for the directory whose layout owns this slot. */\n ownerTreePath: string;\n /** Whether the slot owner directory declares its own page component. */\n hasPage: boolean;\n /** Absolute path to the slot's page component */\n pagePath: string | null;\n /** Absolute path to the slot's default.tsx fallback */\n defaultPath: string | null;\n /** Absolute path to the slot's layout component (wraps slot content) */\n layoutPath: string | null;\n /** Absolute path to the slot's loading component */\n loadingPath: string | null;\n /** Absolute path to the slot's error component */\n errorPath: string | null;\n /** Intercepting routes within this slot */\n interceptingRoutes: InterceptingRoute[];\n /**\n * The layout index (0-based, in route.layouts[]) that this slot belongs to.\n * Slots are passed as props to the layout at their directory level, not\n * necessarily the innermost layout. -1 means \"innermost\" (legacy default).\n */\n layoutIndex: number;\n /**\n * Filesystem segments from the slot's root directory to its active page.\n * Used at render time to compute segments for useSelectedLayoutSegment(slotName).\n * For a page at the slot root (@team/page.tsx), this is [].\n * For a sub-page (@team/members/page.tsx), this is [\"members\"].\n * null when the slot has no active page (showing default.tsx fallback).\n */\n routeSegments: string[] | null;\n /**\n * Full URL pattern parts for the slot's active page (owner prefix +\n * slot-relative pattern). Set when an inherited slot mirrors a sub-page\n * whose param names may differ from the route's. The runtime matches the\n * request URL against these parts to extract slot-specific params.\n */\n slotPatternParts?: string[];\n /**\n * Param names captured by `slotPatternParts`, in order of appearance.\n * Used at runtime to decide whether to extract slot-specific params or\n * reuse the route's matched params.\n */\n slotParamNames?: string[];\n};\n\nexport type AppRoute = {\n /** Graph-owned semantic identities. Required on AppRouteGraphRoute. */\n ids?: AppRouteSemanticIds;\n /** URL pattern, e.g. \"/\" or \"/about\" or \"/blog/:slug\" */\n pattern: string;\n /** Absolute file path to the page component */\n pagePath: string | null;\n /** Absolute file path to the route handler (route.ts) */\n routePath: string | null;\n /** Ordered list of layout files from root to leaf */\n layouts: string[];\n /** Ordered list of all discovered template files from root to leaf (not necessarily aligned 1:1 with layouts) */\n templates: string[];\n /** Parallel route slots (from @slot directories at the route's directory level) */\n parallelSlots: ParallelSlot[];\n /** Loading component path */\n loadingPath: string | null;\n /** Error component path (leaf directory only) */\n errorPath: string | null;\n /**\n * Per-layout error boundary paths, aligned with the layouts array.\n * Each entry is the error.tsx at the same directory level as the\n * corresponding layout (or null if that level has no error.tsx).\n */\n layoutErrorPaths: (string | null)[];\n /** Per-segment error boundary paths, aligned with errorTreePositions. */\n errorPaths?: string[];\n /** Tree position (directory depth from app/ root) for each error boundary. */\n errorTreePositions?: number[];\n /** Not-found component path (nearest, walking up from page dir) */\n notFoundPath: string | null;\n /**\n * Not-found component paths per layout level (aligned with layouts array).\n * Each entry is the not-found.tsx at that layout's directory, or null.\n * Used to create per-layout NotFoundBoundary so that notFound() thrown from\n * a layout is caught by the parent layout's boundary (matching Next.js behavior).\n */\n notFoundPaths: (string | null)[];\n /**\n * Forbidden component paths per layout level (aligned with layouts array).\n * Each entry is the forbidden.tsx at that layout's directory, or null.\n * Used to create per-layout ForbiddenBoundary.\n */\n forbiddenPaths: (string | null)[];\n /** Forbidden component path (403) at the route's directory level */\n forbiddenPath: string | null;\n /** Unauthorized component path (401) at the route's directory level */\n unauthorizedPath: string | null;\n /** Unauthorized component paths per layout level (aligned with layouts array). */\n unauthorizedPaths: (string | null)[];\n /**\n * Filesystem segments from app/ root to the route's directory.\n * Includes route groups and dynamic segments (as template strings like \"[id]\").\n * Used at render time to compute the child segments for useSelectedLayoutSegments().\n */\n routeSegments: string[];\n /** Tree position (directory depth from app/ root) for each template. */\n templateTreePositions?: number[];\n /**\n * Tree position (directory depth from app/ root) for each layout.\n * Used to slice routeSegments and determine which segments are below each layout.\n * For example, root layout = 0, a layout at app/blog/ = 1, app/blog/(group)/ = 2.\n * Unlike the old layoutSegmentDepths, this counts ALL directory levels including\n * route groups and parallel slots.\n */\n layoutTreePositions: number[];\n /** Whether this is a dynamic route */\n isDynamic: boolean;\n /** Parameter names for dynamic segments */\n params: string[];\n /** Dynamic parameter names captured by the route's root layout. */\n rootParamNames?: string[];\n /** Pre-split pattern segments (computed once at scan time, reused per request) */\n patternParts: string[];\n};\n\nexport type AppRouteSemanticIds = {\n route: string;\n page: string | null;\n routeHandler: string | null;\n rootBoundary: RootBoundaryId | null;\n layouts: readonly string[];\n templates: readonly string[];\n /**\n * Bridge map for the current route metadata shape: keyed by `slot.key`\n * (`name@relative/path` infrastructure id), value is the graph-owned semantic slot id.\n */\n slots: Readonly<Record<string, string>>;\n};\n\nexport type AppRouteGraphParallelSlot = ParallelSlot & {\n id: string;\n};\n\nexport type AppRouteGraphRoute = Omit<AppRoute, \"ids\" | \"parallelSlots\" | \"rootParamNames\"> & {\n ids: AppRouteSemanticIds;\n parallelSlots: AppRouteGraphParallelSlot[];\n rootParamNames: string[];\n};\n\ntype Flavor<T, Brand extends string> = T & { readonly __flavor?: Brand };\n\nexport type GraphVersion = Flavor<string, \"GraphVersion\">;\nexport type RootBoundaryId = Flavor<string, \"RootBoundaryId\">;\n\nexport type RouteManifestRoute = {\n id: string;\n pattern: string;\n patternParts: readonly string[];\n isDynamic: boolean;\n paramNames: readonly string[];\n rootParamNames: readonly string[];\n rootBoundaryId: RootBoundaryId | null;\n pageId: string | null;\n routeHandlerId: string | null;\n layoutIds: readonly string[];\n templateIds: readonly string[];\n slotIds: readonly string[];\n};\n\nexport type RouteManifestPage = {\n id: string;\n routeId: string;\n pattern: string;\n};\n\nexport type RouteManifestRouteHandler = {\n id: string;\n routeId: string;\n pattern: string;\n};\n\nexport type RouteManifestLayout = {\n id: string;\n treePath: string;\n rootBoundaryId: RootBoundaryId | null;\n};\n\nexport type RouteManifestTemplate = {\n id: string;\n treePath: string;\n rootBoundaryId: RootBoundaryId | null;\n ownerLayoutId: string | null;\n reset: {\n kind: \"remountSubtree\";\n treePath: string;\n };\n};\n\nexport type RouteManifestSlot = {\n id: string;\n key: string;\n name: string;\n ownerTreePath: string;\n ownerLayoutId: string | null;\n rootBoundaryId: RootBoundaryId | null;\n defaultId: string | null;\n hasDefault: boolean;\n hasPage: boolean;\n};\n\nexport type RouteManifestDefault = {\n id: string;\n slotId: string;\n ownerTreePath: string;\n ownerLayoutId: string | null;\n rootBoundaryId: RootBoundaryId | null;\n};\n\nexport type RouteManifestSlotBindingState = \"active\" | \"default\" | \"unmatched\";\n\nexport type RouteManifestSlotBinding = {\n id: string;\n routeId: string;\n slotId: string;\n ownerLayoutId: string | null;\n state: RouteManifestSlotBindingState;\n defaultId: string | null;\n routeSegments: readonly string[] | null;\n slotPatternParts?: readonly string[];\n slotParamNames?: readonly string[];\n};\n\nexport type RouteManifestBoundaryOutcome = \"error\" | \"forbidden\" | \"notFound\" | \"unauthorized\";\n\nexport type RouteManifestBoundary = {\n id: string;\n outcome: RouteManifestBoundaryOutcome;\n treePath: string;\n ownerLayoutId: string | null;\n rootBoundaryId: RootBoundaryId | null;\n};\n\nexport type RouteManifestRootBoundary = {\n id: RootBoundaryId;\n layoutId: string;\n treePath: string;\n};\n\nexport type StaticSegmentGraph = {\n routes: ReadonlyMap<string, RouteManifestRoute>;\n pages: ReadonlyMap<string, RouteManifestPage>;\n routeHandlers: ReadonlyMap<string, RouteManifestRouteHandler>;\n layouts: ReadonlyMap<string, RouteManifestLayout>;\n templates: ReadonlyMap<string, RouteManifestTemplate>;\n slots: ReadonlyMap<string, RouteManifestSlot>;\n defaults: ReadonlyMap<string, RouteManifestDefault>;\n slotBindings: ReadonlyMap<string, RouteManifestSlotBinding>;\n boundaries: ReadonlyMap<string, RouteManifestBoundary>;\n rootBoundaries: ReadonlyMap<RootBoundaryId, RouteManifestRootBoundary>;\n};\n\nexport type RouteManifest = {\n graphVersion: GraphVersion;\n segmentGraph: StaticSegmentGraph;\n};\n\nfunction createAppRouteGraphRouteId(pattern: string): string {\n return `route:${pattern}`;\n}\n\nfunction createAppRouteGraphPageId(pattern: string): string {\n return `page:${pattern}`;\n}\n\nfunction createAppRouteGraphRouteHandlerId(pattern: string): string {\n return `route-handler:${pattern}`;\n}\n\nfunction createAppRouteGraphLayoutId(treePath: string): string {\n return `layout:${treePath}`;\n}\n\nfunction createAppRouteGraphTemplateId(treePath: string): string {\n return `template:${treePath}`;\n}\n\nfunction createAppRouteGraphSlotId(slotName: string, ownerTreePath: string): string {\n return `slot:${slotName}:${ownerTreePath}`;\n}\n\nfunction createAppRouteGraphDefaultId(slotId: string): string {\n return `default:${slotId}`;\n}\n\nfunction createAppRouteGraphRootBoundaryId(treePath: string): RootBoundaryId {\n return `root-boundary:${treePath}`;\n}\n\nfunction compareStableStrings(left: string, right: string): number {\n if (left < right) return -1;\n if (left > right) return 1;\n return 0;\n}\n\nfunction sortedMapValues<T>(map: ReadonlyMap<string, T>): T[] {\n return Array.from(map.entries())\n .sort(([left], [right]) => compareStableStrings(left, right))\n .map(([, value]) => value);\n}\n\nfunction createRouteManifest(routes: readonly AppRouteGraphRoute[]): RouteManifest {\n const segmentGraph = createStaticSegmentGraph(routes);\n\n return {\n graphVersion: createRouteManifestGraphVersion(segmentGraph),\n segmentGraph,\n };\n}\n\nfunction createStaticSegmentGraph(routes: readonly AppRouteGraphRoute[]): StaticSegmentGraph {\n const routeEntries = new Map<string, RouteManifestRoute>();\n const pages = new Map<string, RouteManifestPage>();\n const routeHandlers = new Map<string, RouteManifestRouteHandler>();\n const layouts = new Map<string, RouteManifestLayout>();\n const templates = new Map<string, RouteManifestTemplate>();\n const slots = new Map<string, RouteManifestSlot>();\n const defaults = new Map<string, RouteManifestDefault>();\n const slotBindings = new Map<string, RouteManifestSlotBinding>();\n const boundaries = new Map<string, RouteManifestBoundary>();\n const rootBoundaries = new Map<RootBoundaryId, RouteManifestRootBoundary>();\n\n for (const route of routes) {\n routeEntries.set(route.ids.route, {\n id: route.ids.route,\n pattern: route.pattern,\n patternParts: [...route.patternParts],\n isDynamic: route.isDynamic,\n paramNames: [...route.params],\n rootParamNames: [...route.rootParamNames],\n rootBoundaryId: route.ids.rootBoundary,\n pageId: route.ids.page,\n routeHandlerId: route.ids.routeHandler,\n layoutIds: [...route.ids.layouts],\n templateIds: [...route.ids.templates],\n slotIds: route.parallelSlots.map((slot) => slot.id).sort(compareStableStrings),\n });\n\n if (route.ids.page) {\n pages.set(route.ids.page, {\n id: route.ids.page,\n routeId: route.ids.route,\n pattern: route.pattern,\n });\n }\n\n if (route.ids.routeHandler) {\n routeHandlers.set(route.ids.routeHandler, {\n id: route.ids.routeHandler,\n routeId: route.ids.route,\n pattern: route.pattern,\n });\n }\n\n for (const [index, layoutId] of route.ids.layouts.entries()) {\n const treePosition = route.layoutTreePositions[index];\n assertRouteManifestTreePosition(\"layout\", route, layoutId, treePosition);\n\n const treePath = createAppRouteGraphTreePath(route.routeSegments, treePosition);\n const existingLayout = layouts.get(layoutId);\n if (existingLayout) {\n assertRouteManifestRootBoundary(\"layout\", route, layoutId, existingLayout.rootBoundaryId);\n }\n const layout = {\n id: layoutId,\n treePath,\n rootBoundaryId: route.ids.rootBoundary,\n };\n layouts.set(layoutId, layout);\n addRouteManifestBoundaryFacts({\n boundaries,\n route,\n layoutId,\n treePath,\n layoutIndex: index,\n });\n\n if (index === 0 && route.ids.rootBoundary) {\n rootBoundaries.set(route.ids.rootBoundary, {\n id: route.ids.rootBoundary,\n layoutId,\n treePath,\n });\n }\n }\n\n addRouteManifestSegmentErrorBoundaryFacts({ boundaries, route });\n\n for (const [index, templateId] of route.ids.templates.entries()) {\n const treePosition = route.templateTreePositions?.[index];\n assertRouteManifestTreePosition(\"template\", route, templateId, treePosition);\n const treePath = createAppRouteGraphTreePath(route.routeSegments, treePosition);\n\n const existingTemplate = templates.get(templateId);\n if (existingTemplate) {\n assertRouteManifestRootBoundary(\n \"template\",\n route,\n templateId,\n existingTemplate.rootBoundaryId,\n );\n }\n templates.set(templateId, {\n id: templateId,\n treePath,\n rootBoundaryId: route.ids.rootBoundary,\n ownerLayoutId: findRouteManifestOwnerLayoutId(route, treePosition),\n reset: {\n kind: \"remountSubtree\",\n treePath,\n },\n });\n }\n\n for (const slot of route.parallelSlots) {\n const ownerLayoutId = findSlotOwnerLayoutId(route, slot);\n const defaultId = slot.defaultPath ? createAppRouteGraphDefaultId(slot.id) : null;\n slots.set(slot.id, {\n id: slot.id,\n key: slot.key,\n name: slot.name,\n ownerTreePath: slot.ownerTreePath,\n ownerLayoutId,\n rootBoundaryId: ownerLayoutId ? route.ids.rootBoundary : null,\n defaultId,\n hasDefault: slot.defaultPath !== null,\n hasPage: slot.hasPage,\n });\n if (defaultId) {\n defaults.set(defaultId, {\n id: defaultId,\n slotId: slot.id,\n ownerTreePath: slot.ownerTreePath,\n ownerLayoutId,\n rootBoundaryId: ownerLayoutId ? route.ids.rootBoundary : null,\n });\n }\n const binding = createRouteManifestSlotBinding(route, slot, ownerLayoutId, defaultId);\n slotBindings.set(binding.id, binding);\n }\n }\n\n return {\n routes: routeEntries,\n pages,\n routeHandlers,\n layouts,\n templates,\n slots,\n defaults,\n slotBindings,\n boundaries,\n rootBoundaries,\n };\n}\n\nfunction findRouteManifestOwnerLayoutId(\n route: AppRouteGraphRoute,\n treePosition: number,\n): string | null {\n const layoutIndex = route.layoutTreePositions.indexOf(treePosition);\n return route.ids.layouts[layoutIndex] ?? null;\n}\n\nfunction findSlotOwnerLayoutId(\n route: AppRouteGraphRoute,\n slot: AppRouteGraphParallelSlot,\n): string | null {\n if (slot.layoutIndex < 0) return null;\n return route.ids.layouts[slot.layoutIndex] ?? null;\n}\n\nfunction createRouteManifestSlotBinding(\n route: AppRouteGraphRoute,\n slot: AppRouteGraphParallelSlot,\n ownerLayoutId: string | null,\n defaultId: string | null,\n): RouteManifestSlotBinding {\n const state = getRouteManifestSlotBindingState(slot);\n const binding: RouteManifestSlotBinding = {\n id: `${route.ids.route}::${slot.id}`,\n routeId: route.ids.route,\n slotId: slot.id,\n ownerLayoutId,\n state,\n defaultId: state === \"default\" ? defaultId : null,\n routeSegments: slot.routeSegments ? [...slot.routeSegments] : null,\n };\n\n if (slot.slotPatternParts) {\n binding.slotPatternParts = [...slot.slotPatternParts];\n }\n if (slot.slotParamNames) {\n binding.slotParamNames = [...slot.slotParamNames];\n }\n\n return binding;\n}\n\nfunction getRouteManifestSlotBindingState(\n slot: AppRouteGraphParallelSlot,\n): RouteManifestSlotBindingState {\n if (slot.pagePath) return \"active\";\n if (slot.defaultPath) return \"default\";\n return \"unmatched\";\n}\n\nfunction addRouteManifestBoundaryFacts(input: {\n boundaries: Map<string, RouteManifestBoundary>;\n route: AppRouteGraphRoute;\n layoutId: string;\n treePath: string;\n layoutIndex: number;\n}): void {\n addRouteManifestBoundaryFact(input, \"error\", input.route.layoutErrorPaths[input.layoutIndex]);\n addRouteManifestBoundaryFact(input, \"notFound\", input.route.notFoundPaths[input.layoutIndex]);\n addRouteManifestBoundaryFact(input, \"forbidden\", input.route.forbiddenPaths[input.layoutIndex]);\n addRouteManifestBoundaryFact(\n input,\n \"unauthorized\",\n input.route.unauthorizedPaths[input.layoutIndex],\n );\n}\n\nfunction addRouteManifestSegmentErrorBoundaryFacts(input: {\n boundaries: Map<string, RouteManifestBoundary>;\n route: AppRouteGraphRoute;\n}): void {\n for (const [index, boundaryPath] of (input.route.errorPaths ?? []).entries()) {\n const treePosition = input.route.errorTreePositions?.[index];\n assertRouteManifestBoundaryTreePosition(input.route, boundaryPath, treePosition);\n const ownerLayoutId = findRouteManifestOwnerLayoutId(input.route, treePosition);\n if (ownerLayoutId !== null) continue;\n\n const treePath = createAppRouteGraphTreePath(input.route.routeSegments, treePosition);\n addRouteManifestBoundaryFact(\n {\n boundaries: input.boundaries,\n route: input.route,\n layoutId: ownerLayoutId,\n treePath,\n },\n \"error\",\n boundaryPath,\n );\n }\n}\n\nfunction addRouteManifestBoundaryFact(\n input: {\n boundaries: Map<string, RouteManifestBoundary>;\n route: AppRouteGraphRoute;\n layoutId: string | null;\n treePath: string;\n },\n outcome: RouteManifestBoundaryOutcome,\n boundaryPath: string | null | undefined,\n): void {\n if (!boundaryPath) return;\n\n const id = `boundary:${outcome}:${input.treePath}`;\n input.boundaries.set(id, {\n id,\n outcome,\n treePath: input.treePath,\n ownerLayoutId: input.layoutId,\n rootBoundaryId: input.route.ids.rootBoundary,\n });\n}\n\nfunction assertRouteManifestTreePosition(\n kind: \"layout\" | \"template\",\n route: AppRouteGraphRoute,\n id: string,\n treePosition: number | undefined,\n): asserts treePosition is number {\n if (treePosition !== undefined) return;\n\n throw new Error(\n `[vinext] App route graph invariant violated: missing ${kind} tree position for ${id} on ${route.pattern}`,\n );\n}\n\nfunction assertRouteManifestBoundaryTreePosition(\n route: AppRouteGraphRoute,\n boundaryPath: string,\n treePosition: number | undefined,\n): asserts treePosition is number {\n if (treePosition !== undefined) return;\n\n throw new Error(\n `[vinext] App route graph invariant violated: missing boundary tree position for ${boundaryPath} on ${route.pattern}`,\n );\n}\n\nfunction assertRouteManifestRootBoundary(\n kind: \"layout\" | \"template\",\n route: AppRouteGraphRoute,\n id: string,\n existingRootBoundaryId: RootBoundaryId | null,\n): void {\n if (existingRootBoundaryId === route.ids.rootBoundary) return;\n\n throw new Error(\n `[vinext] App route graph invariant violated: ${kind} ${id} is shared across root boundaries (${existingRootBoundaryId ?? \"none\"} and ${route.ids.rootBoundary ?? \"none\"}) on ${route.pattern}`,\n );\n}\n\nfunction createRouteManifestGraphVersion(segmentGraph: StaticSegmentGraph): GraphVersion {\n // The manifest hash is canonical only if top-level map keys are sorted and\n // inner route arrays keep their own semantic order: layoutIds/templateIds in\n // tree-position order, and slotIds in compareStableStrings order.\n const stableShape = {\n routes: sortedMapValues(segmentGraph.routes),\n pages: sortedMapValues(segmentGraph.pages),\n routeHandlers: sortedMapValues(segmentGraph.routeHandlers),\n layouts: sortedMapValues(segmentGraph.layouts),\n templates: sortedMapValues(segmentGraph.templates),\n slots: sortedMapValues(segmentGraph.slots),\n defaults: sortedMapValues(segmentGraph.defaults),\n slotBindings: sortedMapValues(segmentGraph.slotBindings),\n boundaries: sortedMapValues(segmentGraph.boundaries),\n rootBoundaries: sortedMapValues(segmentGraph.rootBoundaries),\n };\n return `graph:${createHash(\"sha256\").update(JSON.stringify(stableShape)).digest(\"hex\")}`;\n}\n\nexport async function buildAppRouteGraph(\n appDir: string,\n matcher: ValidFileMatcher,\n): Promise<{ routes: AppRouteGraphRoute[]; routeManifest: RouteManifest }> {\n // Find all page.tsx and route.ts files, excluding @slot directories\n // (slot pages are not standalone routes — they're rendered as props of their parent layout)\n // and _private folders (Next.js convention for colocated non-route files).\n const routes: AppRouteGraphRoute[] = [];\n\n const excludeDir = (name: string) => name.startsWith(\"@\") || name.startsWith(\"_\");\n\n // Process page files in a single pass\n // Use function form of exclude for Node < 22.14 compatibility (string arrays require >= 22.14)\n for await (const file of scanWithExtensions(\"**/page\", appDir, matcher.extensions, excludeDir)) {\n const route = fileToAppRoute(file, appDir, \"page\", matcher);\n if (route) routes.push(route);\n }\n\n // Process route handler files (API routes) in a single pass\n for await (const file of scanWithExtensions(\"**/route\", appDir, matcher.extensions, excludeDir)) {\n const route = fileToAppRoute(file, appDir, \"route\", matcher);\n if (route) routes.push(route);\n }\n\n // Layouts with parallel slot pages are valid route entries even when the\n // segment has no children page. Next.js uses this for modal/feed patterns\n // like app/user/[id]/layout + @feed/page + @modal/default.\n const routePatterns = new Set(routes.map((route) => route.pattern));\n for await (const file of scanWithExtensions(\n \"**/layout\",\n appDir,\n matcher.extensions,\n excludeDir,\n )) {\n const dir = path.dirname(file);\n const routeDir = dir === \".\" ? appDir : path.join(appDir, dir);\n if (!hasParallelSlotDirectory(routeDir)) continue;\n if (discoverParallelSlots(routeDir, appDir, matcher).length === 0) continue;\n\n const route = directoryToAppRoute(dir, appDir, matcher, null, null);\n if (!route || routePatterns.has(route.pattern)) continue;\n\n routes.push(route);\n routePatterns.add(route.pattern);\n }\n\n // Discover sub-routes created by nested pages within parallel slots.\n // In Next.js, pages nested inside @slot directories create additional URL routes.\n // For example, @audience/demographics/page.tsx at app/parallel-routes/ creates\n // a route at /parallel-routes/demographics.\n const slotSubRoutes = discoverSlotSubRoutes(routes, matcher);\n routes.push(...slotSubRoutes);\n\n validatePageRouteConflicts(routes, appDir);\n validateRoutePatterns(routes.map((route) => route.pattern));\n const interceptTargetPatterns = [\n ...new Set(\n routes.flatMap((route) =>\n route.parallelSlots.flatMap((slot) =>\n slot.interceptingRoutes.map((intercept) => intercept.targetPattern),\n ),\n ),\n ),\n ];\n validateRoutePatterns(interceptTargetPatterns);\n\n // Sort: static routes first, then dynamic, then catch-all\n routes.sort(compareRoutes);\n\n return { routes, routeManifest: createRouteManifest(routes) };\n}\n\nfunction hasParallelSlotDirectory(dir: string): boolean {\n try {\n return fs\n .readdirSync(dir, { withFileTypes: true })\n .some((entry) => entry.isDirectory() && entry.name.startsWith(\"@\"));\n } catch {\n return false;\n }\n}\n\nfunction validatePageRouteConflicts(routes: readonly AppRoute[], appDir: string): void {\n const byPattern = new Map<string, { pagePath: string | null; routePath: string | null }>();\n\n // validateRoutePatterns() would also reject page/route pairs because they\n // share a URL pattern. Keep this pass first so the error names both files.\n for (const route of routes) {\n const entry = byPattern.get(route.pattern);\n if (!entry) {\n byPattern.set(route.pattern, {\n pagePath: route.pagePath,\n routePath: route.routePath,\n });\n continue;\n }\n\n if (!entry.pagePath && route.pagePath) {\n entry.pagePath = route.pagePath;\n }\n if (!entry.routePath && route.routePath) {\n entry.routePath = route.routePath;\n }\n }\n\n for (const [pattern, entry] of byPattern) {\n if (!entry.pagePath || !entry.routePath) continue;\n\n throw new Error(\n `Conflicting route and page at ${pattern}: route at ${formatAppFilePath(\n entry.routePath,\n appDir,\n )} and page at ${formatAppFilePath(entry.pagePath, appDir)}`,\n );\n }\n}\n\nfunction formatAppFilePath(filePath: string, appDir: string): string {\n const relativePath = path.relative(appDir, filePath).replace(/\\\\/g, \"/\");\n const parsedPath = path.parse(relativePath);\n const withoutExtension = path.join(parsedPath.dir, parsedPath.name).replace(/\\\\/g, \"/\");\n return withoutExtension.startsWith(\"/\") ? withoutExtension : `/${withoutExtension}`;\n}\n\n/**\n * Discover sub-routes created by nested pages within parallel slots.\n *\n * In Next.js, pages nested inside @slot directories create additional URL routes.\n * For example, given:\n * app/parallel-routes/@audience/demographics/page.tsx\n * This creates a route at /parallel-routes/demographics where:\n * - children slot → parent's default.tsx\n * - @audience slot → @audience/demographics/page.tsx (matched)\n * - other slots → their default.tsx (fallback)\n */\nfunction discoverSlotSubRoutes(\n routes: AppRouteGraphRoute[],\n matcher: ValidFileMatcher,\n): AppRouteGraphRoute[] {\n const syntheticRoutes: AppRouteGraphRoute[] = [];\n\n // O(1) lookup for existing routes by pattern — avoids O(n) routes.find() per sub-path per parent.\n // Updated as new synthetic routes are pushed so that later parents can see earlier synthetic entries.\n const routesByPattern = new Map<string, AppRoute>(routes.map((r) => [r.pattern, r]));\n\n const applySlotSubPages = (\n route: AppRoute,\n slotPages: Map<string, string>,\n rawSegments: string[],\n ): void => {\n route.parallelSlots = route.parallelSlots.map((slot) => {\n const subPage = slotPages.get(slot.key);\n if (subPage !== undefined) {\n return { ...slot, pagePath: subPage, routeSegments: rawSegments };\n }\n return slot;\n });\n };\n\n for (const parentRoute of routes) {\n if (parentRoute.parallelSlots.length === 0) continue;\n\n // Only page-bearing routes or layout-only UI routes (not route handlers)\n // can own nested parallel-slot sub-routes.\n const isLayoutOnlyUiRoute =\n !parentRoute.pagePath && !parentRoute.routePath && parentRoute.layouts.length > 0;\n if (!parentRoute.pagePath && !isLayoutOnlyUiRoute) continue;\n\n // For page-bearing routes, the route directory is the page's directory.\n // For layout-only routes (no page.tsx), proxy the route directory through\n // the innermost layout — it lives at the same filesystem level as the route.\n const parentPageDir = parentRoute.pagePath\n ? path.dirname(parentRoute.pagePath)\n : path.dirname(parentRoute.layouts[parentRoute.layouts.length - 1]);\n\n // Collect sub-paths from all slots.\n // Map: normalized visible sub-path -> slot pages, raw filesystem segments (for routeSegments),\n // and the pre-computed convertedSubRoute (to avoid a redundant re-conversion in the merge loop).\n const subPathMap = new Map<\n string,\n {\n // Raw filesystem segments (with route groups, @slots, etc.) used for routeSegments so\n // that useSelectedLayoutSegments() sees the correct segment list at runtime.\n rawSegments: string[];\n // Pre-computed URL parts, params, isDynamic from convertSegmentsToRouteParts.\n converted: { urlSegments: string[]; params: string[]; isDynamic: boolean };\n slotPages: Map<string, string>;\n }\n >();\n\n for (const slot of parentRoute.parallelSlots) {\n // Only scan sub-pages from slots owned by this route directory.\n // Inherited slots with the same name live in different owner dirs.\n if (path.dirname(slot.ownerDir) !== parentPageDir) {\n continue;\n }\n const slotDir = slot.ownerDir;\n if (!fs.existsSync(slotDir)) continue;\n\n const subPages = findSlotSubPages(slotDir, matcher);\n for (const { relativePath, pagePath } of subPages) {\n const subSegments = relativePath.split(path.sep);\n const convertedSubRoute = convertSegmentsToRouteParts(subSegments);\n if (!convertedSubRoute) continue;\n\n const { urlSegments } = convertedSubRoute;\n const normalizedSubPath = urlSegments.join(\"/\");\n let subPathEntry = subPathMap.get(normalizedSubPath);\n\n if (!subPathEntry) {\n subPathEntry = {\n rawSegments: subSegments,\n converted: convertedSubRoute,\n slotPages: new Map(),\n };\n subPathMap.set(normalizedSubPath, subPathEntry);\n }\n\n const existingSlotPage = subPathEntry.slotPages.get(slot.key);\n if (existingSlotPage) {\n const pattern = joinRoutePattern(parentRoute.pattern, normalizedSubPath);\n throw new Error(\n `You cannot have two routes that resolve to the same path (\"${pattern}\").`,\n );\n }\n\n subPathEntry.slotPages.set(slot.key, pagePath);\n }\n }\n\n if (subPathMap.size === 0) continue;\n\n // Find the default.tsx for the children slot at the parent directory.\n // When the parent route has a children page, a default.tsx is required so\n // the synthetic sub-route has a fallback for the children slot. Layout-only\n // parent routes (no page.tsx) do not need a default — the children slot was\n // never occupied at the parent level, so the sub-route simply renders null.\n const childrenDefault = findFile(parentPageDir, \"default\", matcher);\n if (parentRoute.pagePath && !childrenDefault) continue;\n\n for (const { rawSegments, converted: convertedSubRoute, slotPages } of subPathMap.values()) {\n const {\n urlSegments: urlParts,\n params: subParams,\n isDynamic: subIsDynamic,\n } = convertedSubRoute;\n\n const subUrlPath = urlParts.join(\"/\");\n const pattern = joinRoutePattern(parentRoute.pattern, subUrlPath);\n\n const existingRoute = routesByPattern.get(pattern);\n if (existingRoute) {\n if (existingRoute.routePath && !existingRoute.pagePath) {\n throw new Error(\n `You cannot have two routes that resolve to the same path (\"${pattern}\").`,\n );\n }\n applySlotSubPages(existingRoute, slotPages, rawSegments);\n continue;\n }\n\n // Skip synthetic routes that would structurally conflict with an existing\n // route (same shape, different param names). The slot content is handled\n // by findMirroredSlotPage for the existing route instead.\n // Scan routesByPattern (not just the original routes array) so synthetic\n // routes created earlier in this loop are also visible.\n const syntheticParts = [...parentRoute.patternParts, ...urlParts];\n const hasStructuralConflict = Array.from(routesByPattern.values()).some((r) =>\n patternsStructurallyEquivalent(r.patternParts, syntheticParts),\n );\n if (hasStructuralConflict) continue;\n\n // Build parallel slots for this sub-route: matching slots get the sub-page,\n // non-matching slots get null pagePath (rendering falls back to defaultPath)\n const subSlots: AppRouteGraphParallelSlot[] = parentRoute.parallelSlots.map((slot) => {\n const subPage = slotPages.get(slot.key);\n return {\n ...slot,\n pagePath: subPage || null,\n routeSegments: subPage ? rawSegments : null,\n };\n });\n\n const newRoute: AppRouteGraphRoute = {\n ids: createAppRouteSemanticIds({\n pattern,\n pagePath: childrenDefault,\n routePath: null,\n routeSegments: [...parentRoute.routeSegments, ...rawSegments],\n layoutTreePositions: parentRoute.layoutTreePositions,\n templateTreePositions: parentRoute.templateTreePositions,\n slots: subSlots,\n }),\n pattern,\n pagePath: childrenDefault, // children slot uses parent's default.tsx as page\n routePath: null,\n layouts: parentRoute.layouts,\n templates: parentRoute.templates,\n parallelSlots: subSlots,\n loadingPath: parentRoute.loadingPath,\n errorPath: parentRoute.errorPath,\n layoutErrorPaths: parentRoute.layoutErrorPaths,\n notFoundPath: parentRoute.notFoundPath,\n notFoundPaths: parentRoute.notFoundPaths,\n forbiddenPaths: parentRoute.forbiddenPaths,\n forbiddenPath: parentRoute.forbiddenPath,\n unauthorizedPath: parentRoute.unauthorizedPath,\n unauthorizedPaths: parentRoute.unauthorizedPaths,\n routeSegments: [...parentRoute.routeSegments, ...rawSegments],\n templateTreePositions: parentRoute.templateTreePositions,\n layoutTreePositions: parentRoute.layoutTreePositions,\n isDynamic: parentRoute.isDynamic || subIsDynamic,\n params: [...parentRoute.params, ...subParams],\n rootParamNames: parentRoute.rootParamNames,\n patternParts: [...parentRoute.patternParts, ...urlParts],\n };\n syntheticRoutes.push(newRoute);\n routesByPattern.set(pattern, newRoute);\n }\n }\n\n return syntheticRoutes;\n}\n\n/**\n * Find all page files in subdirectories of a parallel slot directory.\n * Returns relative paths (from the slot dir) and absolute page paths.\n * Skips the root page.tsx (already handled as the slot's main page)\n * and intercepting route directories.\n */\ntype SlotSubPageEntry = { relativePath: string; pagePath: string };\n\n// Per-build memo: a slot directory's sub-pages depend only on the directory\n// contents and the matcher's accepted extensions. Inherited slots get scanned\n// once per descendant route, so without memoization a route N segments deep\n// pays O(N) full subtree walks for every shared ancestor slot.\n//\n// Keyed by matcher (one matcher per build) so the cache is naturally scoped\n// to a single build run and gets collected when the build finishes — no\n// cross-build pollution in long-lived dev servers.\nconst findSlotSubPagesCache = new WeakMap<ValidFileMatcher, Map<string, SlotSubPageEntry[]>>();\n\nfunction findSlotSubPages(slotDir: string, matcher: ValidFileMatcher): SlotSubPageEntry[] {\n let perMatcher = findSlotSubPagesCache.get(matcher);\n if (!perMatcher) {\n perMatcher = new Map();\n findSlotSubPagesCache.set(matcher, perMatcher);\n }\n const cached = perMatcher.get(slotDir);\n if (cached) return cached;\n\n const results: SlotSubPageEntry[] = [];\n\n function scan(dir: string): void {\n if (!fs.existsSync(dir)) return;\n const entries = fs.readdirSync(dir, { withFileTypes: true });\n for (const entry of entries) {\n if (!entry.isDirectory()) continue;\n // Skip intercepting route directories\n if (matchInterceptConvention(entry.name)) continue;\n // Skip private folders (prefixed with _)\n if (entry.name.startsWith(\"_\")) continue;\n\n const subDir = path.join(dir, entry.name);\n const page = findFile(subDir, \"page\", matcher);\n if (page) {\n const relativePath = path.relative(slotDir, subDir);\n results.push({ relativePath, pagePath: page });\n }\n // Continue scanning deeper for nested sub-pages\n scan(subDir);\n }\n }\n\n scan(slotDir);\n perMatcher.set(slotDir, results);\n return results;\n}\n\n/**\n * Convert a file path relative to app/ into an AppRoute.\n */\nfunction fileToAppRoute(\n file: string,\n appDir: string,\n type: \"page\" | \"route\",\n matcher: ValidFileMatcher,\n): AppRouteGraphRoute | null {\n // Remove the filename (page.tsx or route.ts)\n const dir = path.dirname(file);\n return directoryToAppRoute(\n dir,\n appDir,\n matcher,\n type === \"page\" ? path.join(appDir, file) : null,\n type === \"route\" ? path.join(appDir, file) : null,\n );\n}\n\nfunction directoryToAppRoute(\n dir: string,\n appDir: string,\n matcher: ValidFileMatcher,\n pagePath: string | null,\n routePath: string | null,\n): AppRouteGraphRoute | null {\n const segments = dir === \".\" ? [] : dir.split(path.sep);\n\n const params: string[] = [];\n let isDynamic = false;\n\n const convertedRoute = convertSegmentsToRouteParts(segments);\n if (!convertedRoute) return null;\n\n const { urlSegments, params: routeParams, isDynamic: routeIsDynamic } = convertedRoute;\n params.push(...routeParams);\n isDynamic = routeIsDynamic;\n\n const pattern = \"/\" + urlSegments.join(\"/\");\n\n // Discover layouts and templates from root to leaf\n const layouts = discoverLayouts(segments, appDir, matcher);\n const templates = discoverTemplates(segments, appDir, matcher);\n const templateTreePositions = computeLayoutTreePositions(appDir, templates);\n\n // Compute the tree position (directory depth) for each layout.\n const layoutTreePositions = computeLayoutTreePositions(appDir, layouts);\n\n // Discover per-segment error boundaries. Next.js loader trees carry an\n // error convention for a segment even when that segment has no layout.\n // In Next.js, each segment independently wraps its children with an ErrorBoundary.\n // This array enables interleaving error boundaries with layouts in the rendering.\n const layoutErrorPaths = discoverLayoutAlignedErrors(segments, appDir, matcher);\n const errorEntries = discoverSegmentErrors(segments, appDir, matcher);\n const errorPaths = errorEntries.map((entry) => entry.path);\n const errorTreePositions = errorEntries.map((entry) => entry.treePosition);\n\n // Discover loading, error in the route's directory\n const routeDir = dir === \".\" ? appDir : path.join(appDir, dir);\n const loadingPath = findFile(routeDir, \"loading\", matcher);\n const errorPath = findFile(routeDir, \"error\", matcher);\n\n // Discover not-found/forbidden/unauthorized: walk from route directory up to root (nearest wins).\n const notFoundPath = discoverBoundaryFile(segments, appDir, \"not-found\", matcher);\n const forbiddenPath = discoverBoundaryFile(segments, appDir, \"forbidden\", matcher);\n const unauthorizedPath = discoverBoundaryFile(segments, appDir, \"unauthorized\", matcher);\n\n // Discover per-layout not-found files (one per layout directory).\n // These are used for per-layout NotFoundBoundary to match Next.js behavior where\n // notFound() thrown from a layout is caught by the parent layout's boundary.\n const notFoundPaths = discoverBoundaryFilePerLayout(layouts, \"not-found\", matcher);\n const forbiddenPaths = discoverBoundaryFilePerLayout(layouts, \"forbidden\", matcher);\n const unauthorizedPaths = discoverBoundaryFilePerLayout(layouts, \"unauthorized\", matcher);\n\n // Discover parallel slots (@team, @analytics, etc.).\n // Slots at the route's own directory use page.tsx; slots at ancestor directories\n // (inherited from parent layouts) use default.tsx as fallback.\n const parallelSlots = discoverInheritedParallelSlots(segments, appDir, routeDir, matcher);\n\n return {\n ids: createAppRouteSemanticIds({\n pattern: pattern === \"/\" ? \"/\" : pattern,\n pagePath,\n routePath,\n routeSegments: segments,\n layoutTreePositions,\n templateTreePositions,\n slots: parallelSlots,\n }),\n pattern: pattern === \"/\" ? \"/\" : pattern,\n pagePath,\n routePath,\n layouts,\n templates,\n parallelSlots,\n loadingPath,\n errorPath,\n layoutErrorPaths,\n errorPaths,\n errorTreePositions,\n notFoundPath,\n notFoundPaths,\n forbiddenPaths,\n forbiddenPath,\n unauthorizedPath,\n unauthorizedPaths,\n routeSegments: segments,\n templateTreePositions,\n layoutTreePositions,\n isDynamic,\n params,\n rootParamNames: computeRootParamNames(segments, layoutTreePositions),\n patternParts: urlSegments,\n };\n}\n\nfunction dynamicParamNameFromSegment(segment: string): string | null {\n if (segment.startsWith(\"[[...\") && segment.endsWith(\"]]\")) return segment.slice(5, -2);\n if (segment.startsWith(\"[...\") && segment.endsWith(\"]\")) return segment.slice(4, -1);\n if (segment.startsWith(\"[\") && segment.endsWith(\"]\")) return segment.slice(1, -1);\n return null;\n}\n\nexport function computeRootParamNames(\n routeSegments: readonly string[],\n layoutTreePositions: readonly number[],\n): string[] {\n const rootLayoutPosition = layoutTreePositions[0];\n if (rootLayoutPosition == null || rootLayoutPosition <= 0) return [];\n\n const names: string[] = [];\n for (const segment of routeSegments.slice(0, rootLayoutPosition)) {\n const name = dynamicParamNameFromSegment(segment);\n if (name && !names.includes(name)) names.push(name);\n }\n return names;\n}\n\nfunction resolveRootBoundaryId(\n routeSegments: readonly string[],\n layoutTreePositions: readonly number[],\n): RootBoundaryId | null {\n const rootLayoutPosition = layoutTreePositions[0];\n if (rootLayoutPosition === undefined) return null;\n\n // Position 0 is the app root layout and still owns a real root boundary.\n // Only a missing layout position means the route is layoutless.\n return createAppRouteGraphRootBoundaryId(\n createAppRouteGraphTreePath(routeSegments, rootLayoutPosition),\n );\n}\n\nfunction createAppRouteSemanticIds(input: {\n pattern: string;\n pagePath: string | null;\n routePath: string | null;\n routeSegments: readonly string[];\n layoutTreePositions: readonly number[];\n templateTreePositions?: readonly number[];\n slots: readonly AppRouteGraphParallelSlot[];\n}): AppRouteSemanticIds {\n const slots: Record<string, string> = {};\n for (const slot of input.slots) {\n slots[slot.key] = slot.id;\n }\n\n return {\n route: createAppRouteGraphRouteId(input.pattern),\n page: input.pagePath ? createAppRouteGraphPageId(input.pattern) : null,\n routeHandler: input.routePath ? createAppRouteGraphRouteHandlerId(input.pattern) : null,\n rootBoundary: resolveRootBoundaryId(input.routeSegments, input.layoutTreePositions),\n layouts: input.layoutTreePositions.map((treePosition) =>\n createAppRouteGraphLayoutId(createAppRouteGraphTreePath(input.routeSegments, treePosition)),\n ),\n templates: (input.templateTreePositions ?? []).map((treePosition) =>\n createAppRouteGraphTemplateId(createAppRouteGraphTreePath(input.routeSegments, treePosition)),\n ),\n slots,\n };\n}\n\nfunction createAppRouteGraphTreePath(\n routeSegments: readonly string[],\n treePosition: number,\n): string {\n const treePathSegments = routeSegments.slice(0, treePosition);\n if (treePathSegments.length === 0) {\n return \"/\";\n }\n return `/${treePathSegments.join(\"/\")}`;\n}\n\n/**\n * Compute the tree position (directory depth from app root) for each layout.\n * Root layout = 0, a layout at app/blog/ = 1, app/blog/(group)/ = 2.\n * Counts ALL directory levels including route groups and parallel slots.\n */\nfunction computeLayoutTreePositions(appDir: string, layouts: string[]): number[] {\n return layouts.map((layoutPath) => {\n const layoutDir = path.dirname(layoutPath);\n if (layoutDir === appDir) return 0;\n const relative = path.relative(appDir, layoutDir);\n return relative.split(path.sep).length;\n });\n}\n\n/**\n * Discover all layout files from root to the given directory.\n * Each level of the directory tree may have a layout.tsx.\n */\nfunction discoverLayouts(segments: string[], appDir: string, matcher: ValidFileMatcher): string[] {\n const layouts: string[] = [];\n\n // Check root layout\n const rootLayout = findFile(appDir, \"layout\", matcher);\n if (rootLayout) layouts.push(rootLayout);\n\n // Check each directory level\n let currentDir = appDir;\n for (const segment of segments) {\n currentDir = path.join(currentDir, segment);\n const layout = findFile(currentDir, \"layout\", matcher);\n if (layout) layouts.push(layout);\n }\n\n return layouts;\n}\n\n/**\n * Discover all template files from root to the given directory.\n * Each level of the directory tree may have a template.tsx.\n * Templates are like layouts but re-mount on navigation.\n */\nfunction discoverTemplates(\n segments: string[],\n appDir: string,\n matcher: ValidFileMatcher,\n): string[] {\n const templates: string[] = [];\n\n // Check root template\n const rootTemplate = findFile(appDir, \"template\", matcher);\n if (rootTemplate) templates.push(rootTemplate);\n\n // Check each directory level\n let currentDir = appDir;\n for (const segment of segments) {\n currentDir = path.join(currentDir, segment);\n const template = findFile(currentDir, \"template\", matcher);\n if (template) templates.push(template);\n }\n\n return templates;\n}\n\n/**\n * Discover error.tsx files by segment tree position.\n *\n * Next.js stores conventions on every loader-tree segment; a route-group\n * directory with error.tsx but no sibling layout.tsx must still wrap its\n * descendants. Keeping positions explicit avoids conflating segment boundaries\n * with layout component ownership.\n */\nfunction discoverSegmentErrors(\n segments: string[],\n appDir: string,\n matcher: ValidFileMatcher,\n): { path: string; treePosition: number }[] {\n const errors: { path: string; treePosition: number }[] = [];\n\n const rootError = findFile(appDir, \"error\", matcher);\n if (rootError) {\n errors.push({ path: rootError, treePosition: 0 });\n }\n\n // Check each directory level\n let currentDir = appDir;\n for (let index = 0; index < segments.length; index++) {\n const segment = segments[index];\n currentDir = path.join(currentDir, segment);\n const error = findFile(currentDir, \"error\", matcher);\n if (error) {\n errors.push({ path: error, treePosition: index + 1 });\n }\n }\n\n return errors;\n}\n\n/**\n * Discover error.tsx files aligned with the layouts array.\n *\n * Route manifests still model layout-owned boundary facts by layout index.\n * Keep this layout-aligned compatibility shape separate from segment-owned\n * error boundaries so route-group errors without layouts do not get attributed\n * to unrelated layouts.\n */\nfunction discoverLayoutAlignedErrors(\n segments: string[],\n appDir: string,\n matcher: ValidFileMatcher,\n): (string | null)[] {\n const errors: (string | null)[] = [];\n\n const rootLayout = findFile(appDir, \"layout\", matcher);\n if (rootLayout) {\n errors.push(findFile(appDir, \"error\", matcher));\n }\n\n let currentDir = appDir;\n for (const segment of segments) {\n currentDir = path.join(currentDir, segment);\n const layout = findFile(currentDir, \"layout\", matcher);\n if (layout) {\n errors.push(findFile(currentDir, \"error\", matcher));\n }\n }\n\n return errors;\n}\n\n/**\n * Discover the nearest boundary file (not-found, forbidden, unauthorized)\n * by walking from the route's directory up to the app root.\n * Returns the first (closest) file found, or null.\n */\nfunction discoverBoundaryFile(\n segments: string[],\n appDir: string,\n fileName: string,\n matcher: ValidFileMatcher,\n): string | null {\n // Build all directory paths from leaf to root\n const dirs: string[] = [];\n let dir = appDir;\n dirs.push(dir);\n for (const segment of segments) {\n dir = path.join(dir, segment);\n dirs.push(dir);\n }\n\n // Walk from leaf (last) to root (first)\n for (let i = dirs.length - 1; i >= 0; i--) {\n const f = findFile(dirs[i], fileName, matcher);\n if (f) return f;\n }\n return null;\n}\n\n/**\n * Discover boundary files (not-found, forbidden, unauthorized) at each layout directory.\n * Returns an array aligned with the layouts array, where each entry is the boundary\n * file at that layout's directory, or null if none exists there.\n *\n * This is used for per-layout error boundaries. In Next.js, each layout level\n * has its own boundary that wraps the layout's children. When notFound() is thrown\n * from a layout, it propagates up to the parent layout's boundary.\n */\nfunction discoverBoundaryFilePerLayout(\n layouts: string[],\n fileName: string,\n matcher: ValidFileMatcher,\n): (string | null)[] {\n return layouts.map((layoutPath) => {\n const layoutDir = path.dirname(layoutPath);\n return findFile(layoutDir, fileName, matcher);\n });\n}\n\n/**\n * Discover parallel slots inherited from ancestor directories.\n *\n * In Next.js, parallel slots belong to the layout that defines them. When a\n * child route is rendered, its parent layout's slots must still be present.\n * If the child doesn't have matching content in a slot, the slot's default.tsx\n * is rendered instead.\n *\n * Walk from appDir through each segment to the route's directory. At each level\n * that has @slot dirs, collect them. Slots at the route's own directory level\n * use page.tsx; slots at ancestor levels use default.tsx only.\n */\nfunction discoverInheritedParallelSlots(\n segments: string[],\n appDir: string,\n routeDir: string,\n matcher: ValidFileMatcher,\n): AppRouteGraphParallelSlot[] {\n const slotMap = new Map<string, AppRouteGraphParallelSlot>();\n\n // Walk from appDir through each segment, tracking layout indices.\n // layoutIndex tracks which position in the route's layouts[] array corresponds\n // to a given directory. Only directories with a layout.tsx file increment.\n // segmentIndex aligns each entry with `segments`: dirsToCheck[i] is reached\n // after consuming segments[0..i-1], so segments.slice(i) are the segments\n // below this directory (used to mirror inherited slot sub-pages).\n let currentDir = appDir;\n const dirsToCheck: { dir: string; layoutIdx: number; segmentIndex: number }[] = [];\n let layoutIdx = findFile(appDir, \"layout\", matcher) ? 0 : -1;\n dirsToCheck.push({ dir: appDir, layoutIdx, segmentIndex: 0 });\n\n for (let i = 0; i < segments.length; i++) {\n currentDir = path.join(currentDir, segments[i]);\n if (findFile(currentDir, \"layout\", matcher)) {\n layoutIdx++;\n }\n dirsToCheck.push({ dir: currentDir, layoutIdx, segmentIndex: i + 1 });\n }\n\n const routeHasLayout = layoutIdx >= 0;\n\n for (const { dir, layoutIdx: lvlLayoutIdx, segmentIndex } of dirsToCheck) {\n // Once a route has a root layout below app/, slots discovered before that\n // layout are above the root and cannot be owned by any layout in this route.\n // Layout-less routes keep their legacy slot metadata here; validation is separate.\n if (lvlLayoutIdx < 0 && routeHasLayout) continue;\n\n const isOwnDir = dir === routeDir;\n const slotLayoutIdx = Math.max(lvlLayoutIdx, 0);\n const slotsAtLevel = discoverParallelSlots(dir, appDir, matcher);\n const segmentsBelow = segments.slice(segmentIndex);\n\n for (const slot of slotsAtLevel) {\n if (isOwnDir) {\n // At the route's own directory: use page.tsx (normal behavior)\n slot.layoutIndex = slotLayoutIdx;\n slotMap.set(slot.key, slot);\n } else {\n // At an ancestor directory: the slot's own page.tsx belongs to the\n // parent route. Look for a mirrored sub-page at @slot/<segments-below>\n // (e.g. @breadcrumbs/about/page.tsx for /about), falling back to\n // default.tsx when no mirror exists. The mirror search also accepts\n // pattern-compatible matches (e.g. slot's [name] for route's [id]) so\n // the runtime can extract slot-specific params via slotPatternParts.\n const mirror = findMirroredSlotPage(slot.ownerDir, segmentsBelow, matcher);\n let slotPatternParts: string[] | undefined;\n let slotParamNames: string[] | undefined;\n if (mirror) {\n const ownerSegments = segments.slice(0, segmentIndex);\n const ownerUrl = convertSegmentsToRouteParts([...ownerSegments]);\n slotPatternParts = [...(ownerUrl?.urlSegments ?? []), ...mirror.slotUrlSegments];\n slotParamNames = [...(ownerUrl?.params ?? []), ...mirror.slotParamNames];\n }\n const inheritedSlot: AppRouteGraphParallelSlot = {\n ...slot,\n pagePath: mirror?.pagePath ?? null,\n layoutIndex: slotLayoutIdx,\n routeSegments: mirror?.segments ?? null,\n slotPatternParts,\n slotParamNames,\n // defaultPath, loadingPath, errorPath, interceptingRoutes remain\n };\n slotMap.set(slot.key, inheritedSlot);\n }\n }\n }\n\n return Array.from(slotMap.values());\n}\n\n/**\n * Look for a page file inside a parallel slot directory that mirrors the\n * route's path below the slot's owner. The match falls through two tiers:\n * 1. Literal filesystem path — fast path when route and slot share shape.\n * 2. Scored pattern compatibility — enumerate sub-pages, accept those\n * whose URL pattern can match the route's URL space (slot dynamic\n * markers may have different names than the route's, and slot\n * catch-alls may subsume the route), and pick the most-specific via\n * `scoreSlotPattern`. Exact URL-parts equality (e.g. through route\n * groups appearing on only one side, like `(marketing)/about` ↔\n * `@breadcrumbs/about`) naturally wins because all literal segments\n * score highest.\n *\n * Returns the slot sub-page's absolute path, its raw filesystem segments\n * (for `routeSegments`), and its URL parts / param names (for\n * `slotPatternParts` / `slotParamNames`). Returns null when no mirror matches.\n */\nfunction findMirroredSlotPage(\n slotDir: string,\n segmentsBelow: readonly string[],\n matcher: ValidFileMatcher,\n): {\n pagePath: string;\n segments: string[];\n slotUrlSegments: string[];\n slotParamNames: string[];\n} | null {\n if (segmentsBelow.length === 0) return null;\n\n // Convert once: both tiers need the URL form of the route's segments below\n // this directory.\n const routeUrl = convertSegmentsToRouteParts([...segmentsBelow]);\n\n // Tier 1: literal filesystem match.\n const literalDir = path.join(slotDir, ...segmentsBelow);\n const literalPage = findFile(literalDir, \"page\", matcher);\n if (literalPage) {\n return {\n pagePath: literalPage,\n segments: [...segmentsBelow],\n slotUrlSegments: routeUrl?.urlSegments ?? [],\n slotParamNames: routeUrl?.params ?? [],\n };\n }\n\n if (!routeUrl || routeUrl.urlSegments.length === 0) return null;\n\n // Tier 2: enumerate slot sub-pages and pick the most-specific compatible\n // pattern. Exact URL-parts matches naturally win the score.\n type Candidate = {\n pagePath: string;\n segments: string[];\n slotUrlSegments: string[];\n slotParamNames: string[];\n score: number;\n };\n let best: Candidate | null = null;\n for (const { relativePath, pagePath } of findSlotSubPages(slotDir, matcher)) {\n const slotSegments = relativePath.split(path.sep);\n const slotUrl = convertSegmentsToRouteParts(slotSegments);\n if (!slotUrl) continue;\n if (!patternsCompatible(slotUrl.urlSegments, routeUrl.urlSegments)) continue;\n const score = scoreSlotPattern(slotUrl.urlSegments);\n if (!best || score > best.score) {\n best = {\n pagePath,\n segments: slotSegments,\n slotUrlSegments: slotUrl.urlSegments,\n slotParamNames: slotUrl.params,\n score,\n };\n }\n }\n\n return best;\n}\n\n/**\n * Whether a slot pattern can match the same URL space as the route's URL\n * parts (where the route's parts are themselves a pattern, since a route\n * file like `[id]/page.tsx` produces `:id`).\n *\n * - `:name+` (catch-all) consumes one-or-more remaining segments.\n * - `:name*` (optional catch-all) consumes zero-or-more.\n * - `:name` (single dynamic) consumes exactly one segment, matching any\n * route segment (literal or dynamic).\n * - Literal slot segments must equal the route's segment exactly; a literal\n * slot segment paired with a dynamic route segment is rejected because we\n * can't know statically whether the runtime value will equal the literal.\n * This also means a literal slot sub-page never matches a catch-all route\n * (e.g. slot `about/page.tsx` is not bound to a route `[...slug]`) — the\n * catch-all might or might not resolve to \"about\" at request time.\n */\nfunction patternsCompatible(slotParts: readonly string[], routeParts: readonly string[]): boolean {\n let i = 0;\n let j = 0;\n while (i < slotParts.length) {\n const sp = slotParts[i];\n if (sp.endsWith(\"+\")) return j < routeParts.length;\n if (sp.endsWith(\"*\")) return true;\n if (j >= routeParts.length) return false;\n const rp = routeParts[j];\n if (sp.startsWith(\":\")) {\n i++;\n j++;\n continue;\n }\n if (rp.startsWith(\":\")) return false;\n if (sp !== rp) return false;\n i++;\n j++;\n }\n return j === routeParts.length;\n}\n\n/**\n * Score a slot pattern by specificity so the most-specific match wins:\n * literal > single dynamic > catch-all > optional catch-all.\n *\n * Required catch-all (`:name+`, ≥1 segment) is more constrained than the\n * optional variant (`:name*`, ≥0 segments), so it scores higher.\n */\nfunction scoreSlotPattern(urlSegments: readonly string[]): number {\n let score = 0;\n for (const seg of urlSegments) {\n if (seg.endsWith(\"*\")) score += 1;\n else if (seg.endsWith(\"+\")) score += 2;\n else if (seg.startsWith(\":\")) score += 3;\n else score += 4;\n }\n return score;\n}\n\n/**\n * Map a pattern segment to the tree-node type used by Next.js' route\n * validator. Two segments are structurally equivalent iff they share the\n * same tree-node type.\n */\nfunction segmentTreeNodeType(seg: string): string {\n if (!seg.startsWith(\":\")) return `literal:${seg}`;\n if (seg.endsWith(\"*\")) return \"optionalCatchAll\";\n if (seg.endsWith(\"+\")) return \"catchAll\";\n return \"dynamic\";\n}\n\nfunction patternsStructurallyEquivalent(a: readonly string[], b: readonly string[]): boolean {\n if (a.length !== b.length) return false;\n for (let i = 0; i < a.length; i++) {\n if (segmentTreeNodeType(a[i]) !== segmentTreeNodeType(b[i])) return false;\n }\n return true;\n}\n\n/**\n * Discover parallel route slots (@team, @analytics, etc.) in a directory.\n * Returns a ParallelSlot for each @-prefixed subdirectory that has a page or default component.\n */\nfunction discoverParallelSlots(\n dir: string,\n appDir: string,\n matcher: ValidFileMatcher,\n): AppRouteGraphParallelSlot[] {\n if (!fs.existsSync(dir)) return [];\n\n const entries = fs.readdirSync(dir, { withFileTypes: true });\n const slots: AppRouteGraphParallelSlot[] = [];\n\n for (const entry of entries) {\n if (!entry.isDirectory() || !entry.name.startsWith(\"@\")) continue;\n\n const slotName = entry.name.slice(1); // \"@team\" -> \"team\"\n const slotDir = path.join(dir, entry.name);\n\n const pagePath = findFile(slotDir, \"page\", matcher);\n const defaultPath = findFile(slotDir, \"default\", matcher);\n const interceptingRoutes = discoverInterceptingRoutes(slotDir, dir, appDir, matcher);\n\n // Only include slots that have at least a page, default, or intercepting route\n if (!pagePath && !defaultPath && interceptingRoutes.length === 0) continue;\n\n const ownerSegments = path\n .relative(appDir, dir)\n .split(path.sep)\n .filter((segment) => segment.length > 0);\n const ownerTreePath = createAppRouteGraphTreePath(ownerSegments, ownerSegments.length);\n\n slots.push({\n id: createAppRouteGraphSlotId(slotName, ownerTreePath),\n key: `${slotName}@${path.relative(appDir, slotDir).replace(/\\\\/g, \"/\")}`,\n name: slotName,\n ownerDir: slotDir,\n ownerTreePath,\n hasPage: pagePath !== null,\n pagePath,\n defaultPath,\n layoutPath: findFile(slotDir, \"layout\", matcher),\n loadingPath: findFile(slotDir, \"loading\", matcher),\n errorPath: findFile(slotDir, \"error\", matcher),\n interceptingRoutes,\n layoutIndex: -1, // Will be set by discoverInheritedParallelSlots\n routeSegments: pagePath ? [] : null,\n });\n }\n\n return slots;\n}\n\n/**\n * The interception convention prefix patterns.\n * (.) — same level, (..) — one level up, (..)(..)\" — two levels up, (...) — root\n */\nconst INTERCEPT_PATTERNS = [\n { prefix: \"(...)\", convention: \"...\" },\n { prefix: \"(..)(..)\", convention: \"../..\" },\n { prefix: \"(..)\", convention: \"..\" },\n { prefix: \"(.)\", convention: \".\" },\n] as const;\n\n/**\n * Discover intercepting routes inside a parallel slot directory.\n *\n * Intercepting routes use conventions like (.)photo, (..)feed, (...), etc.\n * They intercept navigation to another route and render within the slot instead.\n *\n * @param slotDir - The parallel slot directory (e.g. app/feed/@modal)\n * @param routeDir - The directory of the route that owns this slot (e.g. app/feed)\n * @param appDir - The root app directory\n */\nfunction discoverInterceptingRoutes(\n slotDir: string,\n routeDir: string,\n appDir: string,\n matcher: ValidFileMatcher,\n): InterceptingRoute[] {\n if (!fs.existsSync(slotDir)) return [];\n\n const results: InterceptingRoute[] = [];\n\n // Recursively scan for page files inside intercepting directories\n scanForInterceptingPages(slotDir, routeDir, appDir, results, matcher);\n\n return results;\n}\n\n/**\n * Recursively scan a directory tree for page.tsx files that are inside\n * intercepting route directories.\n */\nfunction scanForInterceptingPages(\n currentDir: string,\n routeDir: string,\n appDir: string,\n results: InterceptingRoute[],\n matcher: ValidFileMatcher,\n): void {\n if (!fs.existsSync(currentDir)) return;\n\n const entries = fs.readdirSync(currentDir, { withFileTypes: true });\n\n for (const entry of entries) {\n if (!entry.isDirectory()) continue;\n // Skip private folders (prefixed with _)\n if (entry.name.startsWith(\"_\")) continue;\n\n // Check if this directory name starts with an interception convention\n const interceptMatch = matchInterceptConvention(entry.name);\n\n if (interceptMatch) {\n // This directory is the start of an intercepting route\n // e.g. \"(.)photos\" means intercept same-level \"photos\" route\n const restOfName = entry.name.slice(interceptMatch.prefix.length);\n const interceptDir = path.join(currentDir, entry.name);\n\n // Find page files within this intercepting directory tree\n collectInterceptingPages(\n interceptDir,\n interceptDir,\n interceptMatch.convention,\n restOfName,\n routeDir,\n appDir,\n results,\n matcher,\n );\n } else {\n // Regular subdirectory — keep scanning for intercepting dirs\n scanForInterceptingPages(\n path.join(currentDir, entry.name),\n routeDir,\n appDir,\n results,\n matcher,\n );\n }\n }\n}\n\n/**\n * Match a directory name against interception convention prefixes.\n */\nfunction matchInterceptConvention(name: string): { prefix: string; convention: string } | null {\n for (const pattern of INTERCEPT_PATTERNS) {\n if (name.startsWith(pattern.prefix)) {\n return pattern;\n }\n }\n return null;\n}\n\n/**\n * Collect page.tsx files inside an intercepting route directory tree\n * and compute their target URL patterns.\n */\nfunction collectInterceptingPages(\n currentDir: string,\n interceptRoot: string,\n convention: string,\n interceptSegment: string,\n routeDir: string,\n appDir: string,\n results: InterceptingRoute[],\n matcher: ValidFileMatcher,\n parentLayoutPaths: readonly string[] = [],\n): void {\n const currentLayoutPath = findFile(currentDir, \"layout\", matcher);\n const layoutPaths = currentLayoutPath\n ? [...parentLayoutPaths, currentLayoutPath]\n : parentLayoutPaths;\n\n // Check for page.tsx in current directory\n const page = findFile(currentDir, \"page\", matcher);\n if (page) {\n const targetPattern = computeInterceptTarget(\n convention,\n interceptSegment,\n currentDir,\n interceptRoot,\n routeDir,\n appDir,\n );\n if (targetPattern) {\n results.push({\n convention,\n layoutPaths: [...layoutPaths],\n targetPattern: targetPattern.pattern,\n pagePath: page,\n params: targetPattern.params,\n });\n }\n }\n\n // Recurse into subdirectories for nested intercepting routes\n if (!fs.existsSync(currentDir)) return;\n const entries = fs.readdirSync(currentDir, { withFileTypes: true });\n for (const entry of entries) {\n if (!entry.isDirectory()) continue;\n // Skip private folders (prefixed with _)\n if (entry.name.startsWith(\"_\")) continue;\n collectInterceptingPages(\n path.join(currentDir, entry.name),\n interceptRoot,\n convention,\n interceptSegment,\n routeDir,\n appDir,\n results,\n matcher,\n layoutPaths,\n );\n }\n}\n\n/**\n * Check whether a path segment is invisible in the URL (route groups, parallel slots, \".\").\n *\n * Used by computeInterceptTarget, convertSegmentsToRouteParts, and\n * hasRemainingVisibleSegments — keep this the single source of truth.\n */\nfunction isInvisibleSegment(segment: string): boolean {\n if (segment === \".\") return true;\n if (segment.startsWith(\"(\") && segment.endsWith(\")\")) return true;\n if (segment.startsWith(\"@\")) return true;\n return false;\n}\n\n/**\n * Compute the target URL pattern for an intercepting route.\n *\n * Interception conventions (..), (..)(..)\" climb by *visible route segments*\n * (not filesystem directories). Route groups like (marketing) and parallel\n * slots like @modal are invisible and must be skipped when counting levels.\n *\n * - (.) same level: resolve relative to routeDir\n * - (..) one level up: climb 1 visible segment\n * - (..)(..) two levels up: climb 2 visible segments\n * - (...) root: resolve from appDir\n */\nfunction computeInterceptTarget(\n convention: string,\n interceptSegment: string,\n currentDir: string,\n interceptRoot: string,\n routeDir: string,\n appDir: string,\n): { pattern: string; params: string[] } | null {\n // Determine the base segments for target resolution.\n // We work on route segments (not filesystem paths) so that route groups\n // and parallel slots are properly skipped when climbing.\n const routeSegments = path.relative(appDir, routeDir).split(path.sep).filter(Boolean);\n\n let baseParts: string[];\n switch (convention) {\n case \".\":\n baseParts = routeSegments;\n break;\n case \"..\":\n case \"../..\": {\n const levelsToClimb = convention === \"..\" ? 1 : 2;\n let climbed = 0;\n let cutIndex = routeSegments.length;\n while (cutIndex > 0 && climbed < levelsToClimb) {\n cutIndex--;\n if (!isInvisibleSegment(routeSegments[cutIndex])) {\n climbed++;\n }\n }\n if (climbed < levelsToClimb) {\n const interceptionRoute = formatInterceptionRoutePath(\n routeSegments,\n convention,\n interceptSegment,\n path.relative(interceptRoot, currentDir).split(path.sep).filter(Boolean),\n );\n if (convention === \"..\") {\n throw new Error(\n `Invalid interception route: ${interceptionRoute}. Cannot use (..) marker at the root level, use (.) instead.`,\n );\n }\n throw new Error(\n `Invalid interception route: ${interceptionRoute}. Cannot use (..)(..) marker at the root level or one level up.`,\n );\n }\n baseParts = routeSegments.slice(0, cutIndex);\n break;\n }\n case \"...\":\n baseParts = [];\n break;\n default:\n return null;\n }\n\n // Add the intercept segment and any nested path segments\n const nestedParts = path.relative(interceptRoot, currentDir).split(path.sep).filter(Boolean);\n const allSegments = [...baseParts, interceptSegment, ...nestedParts];\n\n const convertedTarget = convertSegmentsToRouteParts(allSegments);\n if (!convertedTarget) return null;\n\n const { urlSegments, params } = convertedTarget;\n\n const pattern = \"/\" + urlSegments.join(\"/\");\n return { pattern: pattern === \"/\" ? \"/\" : pattern, params };\n}\n\nfunction formatInterceptionRoutePath(\n routeSegments: string[],\n convention: string,\n interceptSegment: string,\n nestedParts: string[],\n): string {\n const marker = markerForInterceptionConvention(convention);\n const convertedRoute = convertSegmentsToRouteParts(routeSegments);\n const prefix = convertedRoute\n ? convertedRoute.urlSegments\n : routeSegments.filter((segment) => !isInvisibleSegment(segment));\n const routePath = [...prefix, `${marker}${interceptSegment}`, ...nestedParts]\n .filter(Boolean)\n .join(\"/\");\n return routePath ? `/${routePath}` : \"/\";\n}\n\nfunction markerForInterceptionConvention(convention: string): string {\n switch (convention) {\n case \".\":\n return \"(.)\";\n case \"..\":\n return \"(..)\";\n case \"../..\":\n return \"(..)(..)\";\n case \"...\":\n return \"(...)\";\n default:\n return \"\";\n }\n}\n\n/**\n * Find a file by name (without extension) in a directory.\n * Checks configured pageExtensions.\n */\nfunction findFile(dir: string, name: string, matcher: ValidFileMatcher): string | null {\n for (const ext of matcher.dottedExtensions) {\n const filePath = path.join(dir, name + ext);\n if (fs.existsSync(filePath)) return filePath;\n }\n return null;\n}\n\n/**\n * Convert filesystem path segments to URL route parts, skipping invisible segments\n * (route groups, @slots, \".\") and converting dynamic segment syntax to Express-style\n * patterns (e.g. \"[id]\" → \":id\", \"[...slug]\" → \":slug+\").\n */\nfunction convertSegmentsToRouteParts(\n segments: string[],\n): { urlSegments: string[]; params: string[]; isDynamic: boolean } | null {\n const urlSegments: string[] = [];\n const params: string[] = [];\n let isDynamic = false;\n\n for (let i = 0; i < segments.length; i++) {\n const segment = segments[i];\n\n if (isInvisibleSegment(segment)) continue;\n\n // Catch-all segments are only valid in terminal URL position.\n // Matches Next.js PARAMETER_PATTERN: any non-] chars inside brackets.\n // https://github.com/vercel/next.js/blob/canary/packages/next/src/shared/lib/router/utils/get-dynamic-param.ts\n const catchAllMatch = segment.match(/^\\[\\.\\.\\.([^\\]]+)\\]$/);\n if (catchAllMatch) {\n if (hasRemainingVisibleSegments(segments, i + 1)) return null;\n // Guard: names ending in + or * would collide with internal pattern\n // modifiers (:name+ catch-all, :name* optional-catch-all).\n if (catchAllMatch[1].endsWith(\"+\") || catchAllMatch[1].endsWith(\"*\")) return null;\n isDynamic = true;\n params.push(catchAllMatch[1]);\n urlSegments.push(`:${catchAllMatch[1]}+`);\n continue;\n }\n\n const optionalCatchAllMatch = segment.match(/^\\[\\[\\.\\.\\.([^\\]]+)\\]\\]$/);\n if (optionalCatchAllMatch) {\n if (hasRemainingVisibleSegments(segments, i + 1)) return null;\n if (optionalCatchAllMatch[1].endsWith(\"+\") || optionalCatchAllMatch[1].endsWith(\"*\"))\n return null;\n isDynamic = true;\n params.push(optionalCatchAllMatch[1]);\n urlSegments.push(`:${optionalCatchAllMatch[1]}*`);\n continue;\n }\n\n const dynamicMatch = segment.match(/^\\[([^\\]]+)\\]$/);\n if (dynamicMatch) {\n if (dynamicMatch[1].endsWith(\"+\") || dynamicMatch[1].endsWith(\"*\")) return null;\n isDynamic = true;\n params.push(dynamicMatch[1]);\n urlSegments.push(`:${dynamicMatch[1]}`);\n continue;\n }\n\n urlSegments.push(decodeRouteSegment(segment));\n }\n\n return { urlSegments, params, isDynamic };\n}\n\nfunction hasRemainingVisibleSegments(segments: string[], startIndex: number): boolean {\n for (let i = startIndex; i < segments.length; i++) {\n if (!isInvisibleSegment(segments[i])) return true;\n }\n return false;\n}\n\nfunction joinRoutePattern(basePattern: string, subPath: string): string {\n if (!subPath) return basePattern;\n return basePattern === \"/\" ? `/${subPath}` : `${basePattern}/${subPath}`;\n}\n"],"mappings":"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"}