@kimesh/router-generator 0.0.1 → 0.1.0-nightly.20260119171158
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +1 -2
- package/dist/index.mjs +1 -2
- package/package.json +1 -1
- package/dist/index.d.mts.map +0 -1
- package/dist/index.mjs.map +0 -1
package/dist/index.d.mts
CHANGED
|
@@ -501,5 +501,4 @@ declare function generateLayoutStructure(chain: LayoutChain): {
|
|
|
501
501
|
children?: any[];
|
|
502
502
|
} | null;
|
|
503
503
|
//#endregion
|
|
504
|
-
export { type ExtendedParsedRoute, type GeneratedOutput, type KimeshRouterConfig, type KimeshRouterPluginOptions, type LayerRouteConfig, type LayerRouteNode, type LayerRouteSource, type LayerRoutesResult, type LayoutChain, LayoutResolver, type ParsedFileName, type ParsedRoute, type ResolvedLayout, type ResolvedRouterConfig, type RouteNode, type RouteNodeType, type RouteParam, RouteScanner, RouteTreeBuilder, type TreeNode, buildGlobPattern, buildRoutePath, buildRouteTree, collectLayerRoutes, createCatchAllParam, createDynamicParam, createEmptyParsedRoute, createScanner, createTreeBuilder, extractDynamicParam, generateLayoutStructure, generateRouteTypes, generateRoutes, isDotNotationRoute, isRootDir, kimeshRouterGenerator, parseRouteFile, processDirectoryPath, processPathSegment, unescapeBrackets };
|
|
505
|
-
//# sourceMappingURL=index.d.mts.map
|
|
504
|
+
export { type ExtendedParsedRoute, type GeneratedOutput, type KimeshRouterConfig, type KimeshRouterPluginOptions, type LayerRouteConfig, type LayerRouteNode, type LayerRouteSource, type LayerRoutesResult, type LayoutChain, LayoutResolver, type ParsedFileName, type ParsedRoute, type ResolvedLayout, type ResolvedRouterConfig, type RouteNode, type RouteNodeType, type RouteParam, RouteScanner, RouteTreeBuilder, type TreeNode, buildGlobPattern, buildRoutePath, buildRouteTree, collectLayerRoutes, createCatchAllParam, createDynamicParam, createEmptyParsedRoute, createScanner, createTreeBuilder, extractDynamicParam, generateLayoutStructure, generateRouteTypes, generateRoutes, isDotNotationRoute, isRootDir, kimeshRouterGenerator, parseRouteFile, processDirectoryPath, processPathSegment, unescapeBrackets };
|
package/dist/index.mjs
CHANGED
|
@@ -2025,5 +2025,4 @@ function generateLayoutStructure(chain) {
|
|
|
2025
2025
|
}
|
|
2026
2026
|
|
|
2027
2027
|
//#endregion
|
|
2028
|
-
export { LayoutResolver, RouteScanner, RouteTreeBuilder, buildGlobPattern, buildRoutePath, buildRouteTree, collectLayerRoutes, createCatchAllParam, createDynamicParam, createEmptyParsedRoute, createScanner, createTreeBuilder, extractDynamicParam, generateLayoutStructure, generateRouteTypes, generateRoutes, isDotNotationRoute, isRootDir, kimeshRouterGenerator, parseRouteFile, processDirectoryPath, processPathSegment, unescapeBrackets };
|
|
2029
|
-
//# sourceMappingURL=index.mjs.map
|
|
2028
|
+
export { LayoutResolver, RouteScanner, RouteTreeBuilder, buildGlobPattern, buildRoutePath, buildRouteTree, collectLayerRoutes, createCatchAllParam, createDynamicParam, createEmptyParsedRoute, createScanner, createTreeBuilder, extractDynamicParam, generateLayoutStructure, generateRouteTypes, generateRoutes, isDotNotationRoute, isRootDir, kimeshRouterGenerator, parseRouteFile, processDirectoryPath, processPathSegment, unescapeBrackets };
|
package/package.json
CHANGED
package/dist/index.d.mts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/types.ts","../src/plugin.ts","../src/scanner.ts","../src/parser.ts","../src/tree-builder.ts","../src/codegen/routes.ts","../src/codegen/types.ts","../src/route-utils.ts","../src/layer-collector.ts","../src/layout-resolver.ts"],"mappings":"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"}
|
package/dist/index.mjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":["logger","parseSFC","path","logger","buildGlobPatternUtil"],"sources":["../src/parser.ts","../src/scaffolder.ts","../src/route-utils.ts","../src/scanner.ts","../src/tree-builder.ts","../src/codegen/routes.ts","../src/codegen/types.ts","../src/extract-route.ts","../src/layer-collector.ts","../src/plugin.ts","../src/layout-resolver.ts"],"sourcesContent":["/**\n * @kimesh/router-generator - OXC-Powered Route Parser\n *\n * Parse Vue SFC files to extract route definition information using OXC.\n * This replaces the previous regex-based approach for more accurate parsing.\n */\n\nimport { parse as parseSFC } from '@vue/compiler-sfc'\nimport { parseSync, type Program } from 'oxc-parser'\nimport { consola } from 'consola'\nimport type { ParsedRoute } from './types'\n\nconst logger = consola.withTag('kimesh:router:parser')\n\n/**\n * Extended parsed route with OXC-extracted metadata\n */\nexport interface ExtendedParsedRoute extends ParsedRoute {\n /** defineLoader options if present */\n loaderOptions?: {\n isAsync: boolean\n hasBeforeLoad: boolean\n dependencies: string[]\n cacheStrategy?: string\n }\n\n /** defineMiddleware names */\n middleware?: string[]\n\n /** definePageMeta options */\n pageMeta?: {\n name?: string\n path?: string\n alias?: string | string[]\n redirect?: string\n layout?: string | false\n transition?: boolean | string\n keepAlive?: boolean\n meta?: Record<string, unknown>\n }\n}\n\n/**\n * Parse a Vue SFC file to extract route definition information using OXC\n */\nexport function parseRouteFile(code: string, filePath: string): ExtendedParsedRoute {\n try {\n const { descriptor, errors } = parseSFC(code, {\n filename: filePath,\n })\n\n if (errors.length > 0) {\n logger.debug(`SFC parse errors in ${filePath}:`, errors)\n return createEmptyParsedRoute(filePath)\n }\n\n const isLayout = filePath.includes('_layout') || filePath.includes('layout.vue')\n\n // Get script content (prefer non-setup for route definitions)\n const scriptContent = descriptor.script?.content || ''\n const scriptSetupContent = descriptor.scriptSetup?.content || ''\n\n // Parse with OXC for accurate extraction\n const result = parseWithOxc(scriptContent, scriptSetupContent, filePath)\n\n return {\n hasRouteDefinition: result.hasRouteDefinition ?? false,\n routePath: result.routePath ?? null,\n hasLoader: result.hasLoader ?? false,\n hasMeta: result.hasMeta ?? false,\n hasValidateSearch: result.hasValidateSearch ?? false,\n isLayout,\n routeScriptContent: result.hasRouteDefinition ? scriptContent : null,\n loaderOptions: result.loaderOptions,\n middleware: result.middleware,\n pageMeta: result.pageMeta,\n }\n } catch (error) {\n logger.debug(`Failed to parse ${filePath}:`, error)\n return createEmptyParsedRoute(filePath)\n }\n}\n\n/**\n * Parse script content with OXC\n */\nfunction parseWithOxc(\n scriptContent: string,\n scriptSetupContent: string,\n filePath: string\n): Partial<ExtendedParsedRoute> {\n const result: Partial<ExtendedParsedRoute> = {\n hasRouteDefinition: false,\n routePath: null,\n hasLoader: false,\n hasMeta: false,\n hasValidateSearch: false,\n }\n\n // Parse regular script for route definitions\n if (scriptContent) {\n try {\n const parsed = parseSync(filePath + '.ts', scriptContent, {\n sourceType: 'module',\n })\n\n if (parsed.errors.length === 0) {\n extractFromAST(parsed.program, result)\n }\n } catch (e) {\n logger.debug(`OXC parse error for script in ${filePath}:`, e)\n }\n }\n\n // Parse script setup for additional macros\n if (scriptSetupContent) {\n try {\n const parsed = parseSync(filePath + '.setup.ts', scriptSetupContent, {\n sourceType: 'module',\n })\n\n if (parsed.errors.length === 0) {\n extractFromSetupAST(parsed.program, result)\n }\n } catch (e) {\n // Setup script errors are less critical\n }\n }\n\n return result\n}\n\n/**\n * Extract route metadata from regular script AST\n */\nfunction extractFromAST(program: Program, result: Partial<ExtendedParsedRoute>): void {\n for (const node of program.body) {\n // Look for: export const Route = createFileRoute('/path')({ ... })\n if (node.type === 'ExportNamedDeclaration' && node.declaration) {\n const decl = node.declaration as any\n\n if (decl.type === 'VariableDeclaration') {\n for (const declarator of decl.declarations) {\n if (declarator.id?.name === 'Route' && declarator.init) {\n // Support both:\n // - createFileRoute('/path')({ ... }) (preferred)\n // - createFileRoute('/path') (path override only; no route definition extraction)\n const init = declarator.init as any\n\n // createFileRoute('/path')({ ... }) -> CallExpression(CallExpression(createFileRoute), [ObjectExpression])\n if (init.type === 'CallExpression' && init.callee?.type === 'CallExpression') {\n const inner = init.callee\n if (isCallTo(inner, 'createFileRoute')) {\n // Extract route path from inner call\n const arg = inner.arguments?.[0]\n if (arg?.type === 'Literal' && typeof arg.value === 'string') {\n result.routePath = arg.value\n }\n\n // Only mark as having a route definition when the outer call has an inline object\n const routeOptions = init.arguments?.[0]\n if (routeOptions?.type === 'ObjectExpression') {\n result.hasRouteDefinition = true\n for (const prop of routeOptions.properties || []) {\n if (prop.type !== 'Property' || prop.key?.type !== 'Identifier') continue\n switch (prop.key.name) {\n case 'loader':\n result.hasLoader = true\n break\n case 'meta':\n result.hasMeta = true\n break\n case 'validateSearch':\n result.hasValidateSearch = true\n break\n }\n }\n }\n }\n }\n\n // createFileRoute('/path') -> CallExpression(createFileRoute, ['/path'])\n if (init.type === 'CallExpression' && isCallTo(init, 'createFileRoute')) {\n const arg = init.arguments?.[0]\n if (arg?.type === 'Literal' && typeof arg.value === 'string') {\n result.routePath = arg.value\n }\n }\n }\n\n // Check for loader export\n if (declarator.id?.name === 'loader') {\n result.hasLoader = true\n if (isCallTo(declarator.init, 'defineLoader')) {\n result.loaderOptions = extractLoaderOptions(declarator.init)\n }\n }\n\n // Check for middleware export\n if (declarator.id?.name === 'middleware') {\n if (isCallTo(declarator.init, 'defineMiddleware')) {\n result.middleware = extractMiddlewareNames(declarator.init)\n }\n }\n }\n }\n }\n\n // Look for definePageMeta() or defineRoute() calls\n if (node.type === 'ExpressionStatement') {\n const expr = node.expression as any\n\n if (expr.type === 'CallExpression') {\n if (isCallTo(expr, 'definePageMeta')) {\n result.hasMeta = true\n result.pageMeta = extractPageMetaOptions(expr)\n }\n\n if (isCallTo(expr, 'defineRoute')) {\n result.hasRouteDefinition = true\n extractDefineRouteOptions(expr, result)\n }\n }\n }\n }\n}\n\n/**\n * Extract from setup script AST\n */\nfunction extractFromSetupAST(program: Program, result: Partial<ExtendedParsedRoute>): void {\n for (const node of program.body) {\n if (node.type === 'ExpressionStatement') {\n const expr = node.expression as any\n\n if (expr.type === 'CallExpression') {\n // definePageMeta is commonly used in script setup\n if (isCallTo(expr, 'definePageMeta')) {\n result.hasMeta = true\n result.pageMeta = extractPageMetaOptions(expr)\n }\n }\n }\n }\n}\n\n/**\n * Check if a CallExpression calls a specific function\n */\nfunction isCallTo(node: any, name: string): boolean {\n if (!node || node.type !== 'CallExpression') return false\n if (node.callee?.type === 'Identifier') {\n return node.callee.name === name\n }\n return false\n}\n\n/**\n * Extract loader options from defineLoader call\n */\nfunction extractLoaderOptions(call: any): ExtendedParsedRoute['loaderOptions'] {\n const options: NonNullable<ExtendedParsedRoute['loaderOptions']> = {\n isAsync: false,\n hasBeforeLoad: false,\n dependencies: [],\n }\n\n const arg = call.arguments?.[0]\n if (!arg) return options\n\n // defineLoader(async (ctx) => { ... })\n if (isFunctionExpression(arg)) {\n options.isAsync = arg.async === true\n return options\n }\n\n // defineLoader({ loader: ..., beforeLoad: ... })\n if (arg.type === 'ObjectExpression') {\n extractLoaderObjectOptions(arg, options)\n }\n\n return options\n}\n\nconst FUNCTION_EXPRESSION_TYPES = new Set(['ArrowFunctionExpression', 'FunctionExpression'])\n\nfunction isFunctionExpression(node: any): boolean {\n return FUNCTION_EXPRESSION_TYPES.has(node.type)\n}\n\nfunction extractLoaderObjectOptions(\n arg: any,\n options: NonNullable<ExtendedParsedRoute['loaderOptions']>\n): void {\n for (const prop of arg.properties || []) {\n if (prop.type !== 'Property' || prop.key?.type !== 'Identifier') continue\n\n switch (prop.key.name) {\n case 'loader':\n if (isFunctionExpression(prop.value)) {\n options.isAsync = prop.value.async === true\n }\n break\n\n case 'beforeLoad':\n options.hasBeforeLoad = true\n break\n\n case 'dependencies':\n if (prop.value?.type === 'ArrayExpression') {\n options.dependencies = extractStringArrayElements(prop.value.elements)\n }\n break\n\n case 'cache':\n if (prop.value?.type === 'Literal' && typeof prop.value.value === 'string') {\n options.cacheStrategy = prop.value.value\n }\n break\n }\n }\n}\n\nfunction extractStringArrayElements(elements: any[]): string[] {\n return elements\n .filter((e: any) => e?.type === 'Literal' && typeof e.value === 'string')\n .map((e: any) => e.value)\n}\n\n/**\n * Extract middleware names from defineMiddleware call\n */\nfunction extractMiddlewareNames(call: any): string[] {\n const names: string[] = []\n const arg = call.arguments?.[0]\n\n if (!arg) return names\n\n // defineMiddleware(['auth', 'admin'])\n if (arg.type === 'ArrayExpression') {\n for (const elem of arg.elements || []) {\n if (elem?.type === 'Literal' && typeof elem.value === 'string') {\n names.push(elem.value)\n }\n }\n }\n\n // defineMiddleware('auth')\n if (arg.type === 'Literal' && typeof arg.value === 'string') {\n names.push(arg.value)\n }\n\n return names\n}\n\n/**\n * Extract page meta options from definePageMeta call\n */\nfunction extractPageMetaOptions(call: any): ExtendedParsedRoute['pageMeta'] {\n const options: NonNullable<ExtendedParsedRoute['pageMeta']> = {}\n const arg = call.arguments?.[0]\n\n if (!arg || arg.type !== 'ObjectExpression') return options\n\n for (const prop of arg.properties || []) {\n if (prop.type !== 'Property' || prop.key?.type !== 'Identifier') continue\n\n const key = prop.key.name\n const { value, serializable } = extractSerializableValue(prop.value)\n\n if (!serializable) continue\n\n assignPageMetaOption(options, key, value)\n }\n\n return options\n}\n\nfunction assignPageMetaOption(\n options: NonNullable<ExtendedParsedRoute['pageMeta']>,\n key: string,\n value: unknown\n): void {\n switch (key) {\n case 'name':\n case 'path':\n case 'redirect':\n if (typeof value === 'string') {\n (options as Record<string, unknown>)[key] = value\n }\n break\n\n case 'layout':\n if (typeof value === 'string' || value === false) {\n options.layout = value\n }\n break\n\n case 'alias':\n if (typeof value === 'string' || Array.isArray(value)) {\n options.alias = value as string | string[]\n }\n break\n\n case 'transition':\n case 'keepAlive':\n if (typeof value === 'boolean' || typeof value === 'string') {\n (options as Record<string, unknown>)[key] = value\n }\n break\n\n case 'meta':\n if (typeof value === 'object' && value !== null) {\n options.meta = value as Record<string, unknown>\n }\n break\n }\n}\n\n/**\n * Extract options from defineRoute call\n */\nfunction extractDefineRouteOptions(call: any, result: Partial<ExtendedParsedRoute>): void {\n const arg = call.arguments?.[0]\n if (!arg || arg.type !== 'ObjectExpression') return\n\n for (const prop of arg.properties || []) {\n if (prop.type !== 'Property' || prop.key?.type !== 'Identifier') continue\n\n switch (prop.key.name) {\n case 'path':\n if (prop.value?.type === 'Literal' && typeof prop.value.value === 'string') {\n result.routePath = prop.value.value\n }\n break\n case 'loader':\n result.hasLoader = true\n break\n case 'meta':\n result.hasMeta = true\n break\n case 'validateSearch':\n result.hasValidateSearch = true\n break\n }\n }\n}\n\ninterface SerializableResult {\n value: unknown\n serializable: boolean\n}\n\nconst NOT_SERIALIZABLE: SerializableResult = { value: undefined, serializable: false }\n\n/**\n * Extract JSON-serializable value from AST node\n */\nfunction extractSerializableValue(node: any): SerializableResult {\n if (!node) return NOT_SERIALIZABLE\n\n switch (node.type) {\n case 'Literal':\n case 'BooleanLiteral':\n return { value: node.value, serializable: true }\n\n case 'ArrayExpression':\n return extractArrayValue(node)\n\n case 'ObjectExpression':\n return extractObjectValue(node)\n\n case 'UnaryExpression':\n return extractUnaryValue(node)\n\n case 'Identifier':\n return extractIdentifierValue(node)\n\n default:\n return NOT_SERIALIZABLE\n }\n}\n\nfunction extractArrayValue(node: any): SerializableResult {\n const values: unknown[] = []\n for (const element of node.elements || []) {\n if (!element) continue\n const result = extractSerializableValue(element)\n if (!result.serializable) return NOT_SERIALIZABLE\n values.push(result.value)\n }\n return { value: values, serializable: true }\n}\n\nfunction extractObjectValue(node: any): SerializableResult {\n const obj: Record<string, unknown> = {}\n for (const prop of node.properties || []) {\n if (prop.type !== 'Property') continue\n const key = getPropertyKey(prop)\n if (!key) continue\n const result = extractSerializableValue(prop.value)\n if (!result.serializable) return NOT_SERIALIZABLE\n obj[key] = result.value\n }\n return { value: obj, serializable: true }\n}\n\nfunction getPropertyKey(prop: any): string | null {\n if (prop.key?.type === 'Identifier') {\n return prop.key.name\n }\n if (prop.key?.type === 'Literal') {\n return String(prop.key.value)\n }\n return null\n}\n\nfunction extractUnaryValue(node: any): SerializableResult {\n if (node.operator === '-' && node.argument?.type === 'Literal') {\n return { value: -node.argument.value, serializable: true }\n }\n return NOT_SERIALIZABLE\n}\n\nfunction extractIdentifierValue(node: any): SerializableResult {\n // Note: 'true' and 'false' are typically parsed as BooleanLiteral, not Identifier\n // but we handle them here for defensive parsing\n if (node.name === 'undefined') {\n return { value: undefined, serializable: true }\n }\n\n return NOT_SERIALIZABLE\n}\n\n/**\n * Create an empty parsed route\n */\nexport function createEmptyParsedRoute(filePath: string): ExtendedParsedRoute {\n const isLayout = filePath.includes('_layout') || filePath.includes('layout.vue')\n\n return {\n hasRouteDefinition: false,\n routePath: null,\n hasLoader: false,\n hasMeta: false,\n hasValidateSearch: false,\n isLayout,\n routeScriptContent: null,\n }\n}\n","/**\n * Auto-scaffolding for empty route files\n * Generates Vue SFC boilerplate when a new/empty route file is detected\n */\n\nexport interface ScaffoldOptions {\n /** The route path (e.g., '/posts/:postId') */\n routePath: string\n /** Whether this is a layout file */\n isLayout: boolean\n /** Whether this route has dynamic params */\n isDynamic: boolean\n /** The name of the first param if dynamic */\n paramName?: string\n}\n\n/**\n * Check if file content needs scaffolding (empty or invalid SFC)\n */\nexport function needsScaffolding(content: string): boolean {\n const trimmed = content.trim()\n\n // Empty file\n if (!trimmed) return true\n\n // File without template or script (invalid SFC)\n if (!trimmed.includes('<template') && !trimmed.includes('<script')) return true\n\n return false\n}\n\n/**\n * Generate Vue SFC boilerplate for a route file\n */\nexport function generateRouteScaffold(options: ScaffoldOptions): string {\n const { routePath, isLayout } = options\n\n // Layout files get simpler boilerplate with just slot\n if (isLayout) {\n return `<script setup lang=\"ts\">\n</script>\n\n<template>\n <div>\n <slot />\n </div>\n</template>\n`\n }\n\n // Regular route with createFileRoute\n // Note: import is handled by auto-import plugin\n const displayPath = routePath === '/' ? 'Home' : routePath\n\n return `<script lang=\"ts\">\nexport const Route = createFileRoute('${routePath}')({})\n</script>\n\n<script setup lang=\"ts\">\n</script>\n\n<template>\n <div>\n <h1>Hello \"${displayPath}\"!</h1>\n </div>\n</template>\n`\n}\n","/**\n * @kimesh/router-generator - Shared Route Utilities\n *\n * Common utilities for parsing file-based routes, used by both scanner and layer-collector.\n */\n\nimport type { RouteNodeType, RouteParam } from './types'\n\nexport interface ParsedFileName {\n type: RouteNodeType\n routePath: string\n params: RouteParam[]\n rawSegment: string\n isPathlessLayout?: boolean\n}\n\n/**\n * Check if directory path is root (empty or \".\")\n */\nexport function isRootDir(dirPath: string): boolean {\n return dirPath === '.' || dirPath === ''\n}\n\n/**\n * Extract dynamic param name from segment (e.g., \"$id\" -> \"id\")\n */\nexport function extractDynamicParam(segment: string): string | null {\n const match = segment.match(/^\\$(.+)$/)\n return match ? match[1] : null\n}\n\n/**\n * Check if filename uses dot notation for flat routes\n */\nexport function isDotNotationRoute(fileName: string): boolean {\n return fileName.includes('.') && !fileName.startsWith('.') && !fileName.includes('[')\n}\n\n/**\n * Unescape bracket notation in filenames\n * e.g., script[.]js -> script.js, api[.]v1 -> api.v1\n */\nexport function unescapeBrackets(segment: string): string {\n return segment.replace(/\\[(.)\\]/g, '$1')\n}\n\n/**\n * Process a single path segment for dynamic params and special conventions\n *\n * Conventions:\n * - (auth) -> pathless group folder, returns empty string\n * - _auth -> pathless layout folder, returns empty string\n * - posts_ -> layout escape, strips trailing underscore\n * - $id -> dynamic param :id\n * - -folder -> excluded from routing (dash prefix)\n * - [x] -> escape special characters\n */\nexport function processPathSegment(segment: string): string {\n // Exclude folders with dash prefix from routing\n if (segment.startsWith('-')) {\n return ''\n }\n\n // Handle group folders (pathless): (auth) -> nothing\n if (segment.startsWith('(') && segment.endsWith(')')) {\n return ''\n }\n\n // Handle pathless layout folders: _pathless -> nothing\n if (segment.startsWith('_') && !segment.includes('$')) {\n return ''\n }\n\n // Handle layout escape: posts_ -> posts (strip trailing underscore)\n if (segment.endsWith('_') && segment.length > 1) {\n return segment.slice(0, -1)\n }\n\n // Handle dynamic: $id\n const dynamicParam = extractDynamicParam(segment)\n if (dynamicParam) {\n return `:${dynamicParam}`\n }\n\n // Apply bracket escaping for special characters\n return unescapeBrackets(segment)\n}\n\n/**\n * Process directory path into route segments\n */\nexport function processDirectoryPath(dirPath: string): string {\n return dirPath\n .split('/')\n .filter((part) => Boolean(part) && part !== '.')\n .map(processPathSegment)\n .filter(Boolean)\n .join('/')\n}\n\n/**\n * Build route path from directory and segment\n */\nexport function buildRoutePath(dirPath: string, segment: string): string {\n if (isRootDir(dirPath)) {\n return segment ? `/${segment}` : '/'\n }\n\n const processedDir = processDirectoryPath(dirPath)\n const basePath = processedDir ? `/${processedDir}` : ''\n\n if (!segment) {\n return basePath || '/'\n }\n\n return `${basePath}/${segment}`\n}\n\n/**\n * Create a standard RouteParam for a dynamic parameter\n */\nexport function createDynamicParam(name: string): RouteParam {\n return { name, optional: false, isSplat: false, repeatable: false }\n}\n\n/**\n * Create a catch-all RouteParam\n */\nexport function createCatchAllParam(): RouteParam {\n return { name: 'pathMatch', optional: false, isSplat: true, repeatable: true }\n}\n\n/**\n * Build a glob pattern for route file scanning\n */\nexport function buildGlobPattern(extensions: string[]): string {\n const exts = extensions.map((e) => (e.startsWith('.') ? e : `.${e}`))\n\n if (exts.length === 1) {\n return `**/*${exts[0]}`\n }\n\n const extPatterns = exts.map((e) => e.slice(1)).join(',')\n return `**/*.{${extPatterns}}`\n}\n","import fg from 'fast-glob'\nimport * as path from 'pathe'\nimport * as fs from 'node:fs'\nimport type { RouteNode, RouteNodeType, ResolvedRouterConfig, RouteParam } from './types'\nimport { parseRouteFile } from './parser'\nimport { needsScaffolding, generateRouteScaffold } from './scaffolder'\nimport {\n isRootDir,\n extractDynamicParam,\n isDotNotationRoute,\n buildRoutePath,\n createDynamicParam,\n createCatchAllParam,\n buildGlobPattern,\n} from './route-utils'\n\n/**\n * Route file scanner\n * Scans the routes directory and builds route nodes\n */\nexport class RouteScanner {\n private config: ResolvedRouterConfig\n private routeNodes: Map<string, RouteNode> = new Map()\n\n constructor(config: ResolvedRouterConfig) {\n this.config = config\n }\n\n /**\n * Scan routes directory and return route nodes\n */\n async scan(): Promise<RouteNode[]> {\n const pattern = this.buildGlobPattern()\n\n const files = await fg(pattern, {\n cwd: this.config.routesDirPath,\n onlyFiles: true,\n ignore: ['**/node_modules/**'],\n })\n\n // Get all directories to detect layout route patterns (posts.vue + posts/)\n const directories = await fg('**/', {\n cwd: this.config.routesDirPath,\n onlyDirectories: true,\n ignore: ['**/node_modules/**'],\n })\n const dirSet = new Set(directories.map(d => d.replace(/\\/$/, '')))\n\n this.routeNodes.clear()\n\n for (const file of files.sort()) {\n const node = await this.processFile(file, dirSet)\n if (node) {\n this.routeNodes.set(file, node)\n }\n }\n\n return Array.from(this.routeNodes.values())\n }\n\n /**\n * Process a single route file\n */\n private async processFile(filePath: string, dirSet: Set<string>): Promise<RouteNode | null> {\n const fullPath = path.join(this.config.routesDirPath, filePath)\n const fileName = path.basename(filePath, path.extname(filePath))\n const dirPath = path.dirname(filePath)\n\n // Check for layout route pattern: posts.vue + posts/ directory\n const potentialDirPath = isRootDir(dirPath) ? fileName : `${dirPath}/${fileName}`\n const hasMatchingDirectory = dirSet.has(potentialDirPath)\n\n // Determine route type and path FIRST (before reading content)\n const { type, routePath, params, rawSegment } = this.parseFileName(\n fileName,\n dirPath,\n hasMatchingDirectory\n )\n\n // Read file content\n let content = fs.readFileSync(fullPath, 'utf-8')\n\n // Check if file needs scaffolding (empty or invalid SFC)\n if (needsScaffolding(content)) {\n const isLayout = type === 'layout'\n const isDynamic = type === 'dynamic'\n const paramName = params[0]?.name\n\n content = generateRouteScaffold({\n routePath,\n isLayout,\n isDynamic,\n paramName,\n })\n\n // Write scaffolded content back to file\n fs.writeFileSync(fullPath, content, 'utf-8')\n console.log(`[kimesh:router] Scaffolded route: ${filePath}`)\n }\n\n // Parse the (possibly scaffolded) content\n const parsed = parseRouteFile(content, fullPath)\n\n // Generate variable name\n const variableName = this.generateVariableName(filePath)\n\n // Generate route name\n const routeName = this.generateRouteName(routePath)\n\n // Check if lazy loaded based on config\n const isLazy = this.shouldBeLazy(filePath)\n\n const node: RouteNode = {\n filePath,\n fullPath,\n routePath,\n variableName,\n type,\n routeName,\n isLazy,\n params,\n parsed,\n children: [],\n rawSegment,\n }\n\n return node\n }\n\n /**\n * Parse filename to determine route type and path\n *\n * Kimesh file-based routing conventions:\n * - __root.vue → root layout (wraps everything)\n * - index.vue → index route\n * - about.vue → regular page (/about)\n * - $id.vue → dynamic param (/users/:id)\n * - $.vue → catch-all (splat route)\n * - _auth.vue → pathless layout (underscore prefix, no URL segment)\n * - posts.vue + posts/ → layout route (file + matching directory)\n * - posts.index.vue → flat route notation (dot separator)\n */\n private parseFileName(\n fileName: string,\n dirPath: string,\n hasMatchingDirectory: boolean = false\n ): {\n type: RouteNodeType\n routePath: string\n params: RouteParam[]\n rawSegment: string\n } {\n const rawSegment = fileName\n\n // Handle root route file: __root.vue\n if (fileName === '__root') {\n return { type: 'layout', routePath: '/', params: [], rawSegment }\n }\n\n // Handle pathless layout pattern: _name.vue (underscore prefix = pathless layout)\n if (fileName.startsWith('_')) {\n return {\n type: 'layout',\n routePath: buildRoutePath(dirPath, ''),\n params: [],\n rawSegment,\n }\n }\n\n // Handle index route\n if (fileName === 'index') {\n return {\n type: 'index',\n routePath: buildRoutePath(dirPath, ''),\n params: [],\n rawSegment,\n }\n }\n\n // Handle flat routes with dot notation: posts.index.vue, posts.$postId.vue\n if (isDotNotationRoute(fileName)) {\n return this.parseDotNotationRoute(fileName, dirPath, rawSegment)\n }\n\n // Handle catch-all: $.vue (splat route)\n if (fileName === '$') {\n return {\n type: 'catch-all',\n routePath: buildRoutePath(dirPath, ':pathMatch(.*)*'),\n params: [createCatchAllParam()],\n rawSegment,\n }\n }\n\n // Handle dynamic params: $id.vue only (TanStack style)\n const dynamicParam = extractDynamicParam(fileName)\n if (dynamicParam) {\n return {\n type: 'dynamic',\n routePath: buildRoutePath(dirPath, `:${dynamicParam}`),\n params: [createDynamicParam(dynamicParam)],\n rawSegment,\n }\n }\n\n // If this file has matching directory (e.g., posts.vue + posts/), it's a layout route\n if (hasMatchingDirectory) {\n return {\n type: 'layout',\n routePath: buildRoutePath(dirPath, fileName),\n params: [],\n rawSegment,\n }\n }\n\n // Regular page\n return {\n type: 'page',\n routePath: buildRoutePath(dirPath, fileName),\n params: [],\n rawSegment,\n }\n }\n\n private parseDotNotationRoute(\n fileName: string,\n dirPath: string,\n rawSegment: string\n ): { type: RouteNodeType; routePath: string; params: RouteParam[]; rawSegment: string } {\n const segments = fileName.split('.')\n const lastSegment = segments[segments.length - 1]\n const parentSegments = segments.slice(0, -1)\n\n // Build the virtual directory path from dot-separated parts\n const virtualDir = isRootDir(dirPath)\n ? parentSegments.join('/')\n : `${dirPath}/${parentSegments.join('/')}`\n\n // Parse the last segment for type determination\n if (lastSegment === 'index') {\n return {\n type: 'index',\n routePath: buildRoutePath(virtualDir, ''),\n params: [],\n rawSegment,\n }\n }\n\n // Check for dynamic param in last segment\n const dynamicParam = extractDynamicParam(lastSegment)\n if (dynamicParam) {\n return {\n type: 'dynamic',\n routePath: buildRoutePath(virtualDir, `:${dynamicParam}`),\n params: [createDynamicParam(dynamicParam)],\n rawSegment,\n }\n }\n\n // Regular page with dot notation\n return {\n type: 'page',\n routePath: buildRoutePath(virtualDir, lastSegment),\n params: [],\n rawSegment,\n }\n }\n\n /**\n * Generate a valid JavaScript variable name from file path\n */\n private generateVariableName(filePath: string): string {\n const withoutExt = filePath.replace(/\\.[^/.]+$/, '')\n\n return withoutExt\n .replace(/[\\/\\\\]/g, '_')\n .replace(/[\\[\\]$().+-]/g, '_')\n .replace(/^_+|_+$/g, '')\n .replace(/_+/g, '_')\n .replace(/^(\\d)/, '_$1')\n }\n\n /**\n * Generate route name from route path\n */\n private generateRouteName(routePath: string): string {\n if (routePath === '/') {\n return 'index'\n }\n\n return routePath\n .slice(1)\n .replace(/\\//g, '-')\n .replace(/:/g, '')\n .replace(/\\(.*?\\)\\*/g, 'catchAll')\n .replace(/\\?/g, '')\n }\n\n /**\n * Check if route should be lazy loaded based on config\n */\n private shouldBeLazy(filePath: string): boolean {\n const { importMode } = this.config\n\n if (typeof importMode === 'function') {\n return importMode(filePath) === 'async'\n }\n\n return importMode === 'async'\n }\n\n /**\n * Get all scanned route nodes\n */\n getNodes(): RouteNode[] {\n return Array.from(this.routeNodes.values())\n }\n\n /**\n * Build glob pattern for file scanning based on configured extensions\n */\n private buildGlobPattern(): string {\n return buildGlobPattern(this.config.extensions)\n }\n}\n\n/**\n * Create a route scanner instance\n */\nexport function createScanner(config: ResolvedRouterConfig): RouteScanner {\n return new RouteScanner(config)\n}\n","import * as path from 'pathe'\nimport type { RouteNode, TreeNode, ResolvedRouterConfig } from './types'\nimport { isRootDir } from './route-utils'\n\n/**\n * Build a route tree from flat route nodes\n */\nexport class RouteTreeBuilder {\n private config: ResolvedRouterConfig\n private root: TreeNode\n private layoutNodes: Map<string, RouteNode> = new Map()\n private pathlessLayoutMap: Map<string, string> = new Map()\n\n constructor(config: ResolvedRouterConfig) {\n this.config = config\n this.root = this.createTreeNode('', '/')\n }\n\n /**\n * Build route tree from scanned nodes\n */\n build(nodes: RouteNode[]): RouteNode[] {\n const { layouts, pages } = this.separateLayoutsAndPages(nodes)\n\n // Register layouts\n for (const layout of layouts) {\n this.registerLayout(layout)\n }\n\n // Group pages by pathless layout\n const { pathlessPages, regularPages } = this.groupPagesByPathlessLayout(pages)\n\n // Build tree from regular pages\n for (const page of regularPages) {\n this.insertNode(page)\n }\n\n // Flatten tree with layouts\n const routes = this.flattenTree()\n\n // Add pathless layouts with their children\n this.addPathlessLayoutRoutes(routes, pathlessPages)\n\n return routes\n }\n\n private separateLayoutsAndPages(nodes: RouteNode[]): {\n layouts: RouteNode[]\n pages: RouteNode[]\n } {\n const layouts: RouteNode[] = []\n const pages: RouteNode[] = []\n\n for (const node of nodes) {\n if (node.type === 'layout') {\n layouts.push(node)\n } else {\n pages.push(node)\n }\n }\n\n return { layouts, pages }\n }\n\n private registerLayout(node: RouteNode): void {\n const fileName = path.basename(node.filePath, path.extname(node.filePath))\n const dir = path.dirname(node.filePath)\n\n if (fileName === '__root') {\n this.layoutNodes.set('', node)\n return\n }\n\n const layoutDir = isRootDir(dir) ? fileName : `${dir}/${fileName}`\n\n if (fileName.startsWith('_') && !fileName.startsWith('__')) {\n // Pathless layout (_auth.vue)\n this.layoutNodes.set(layoutDir, node)\n const folderPath = isRootDir(dir) ? `${fileName}/` : `${dir}/${fileName}/`\n this.pathlessLayoutMap.set(folderPath, layoutDir)\n } else {\n // Layout route (posts.vue + posts/)\n this.layoutNodes.set(layoutDir, node)\n }\n }\n\n private groupPagesByPathlessLayout(pages: RouteNode[]): {\n pathlessPages: Map<string, RouteNode[]>\n regularPages: RouteNode[]\n } {\n const pathlessPages = new Map<string, RouteNode[]>()\n const regularPages: RouteNode[] = []\n\n for (const page of pages) {\n const matchedPathless = this.findMatchingPathlessLayout(page)\n\n if (matchedPathless) {\n if (!pathlessPages.has(matchedPathless)) {\n pathlessPages.set(matchedPathless, [])\n }\n pathlessPages.get(matchedPathless)!.push(page)\n } else {\n regularPages.push(page)\n }\n }\n\n return { pathlessPages, regularPages }\n }\n\n private findMatchingPathlessLayout(page: RouteNode): string | null {\n for (const [folderPath, layoutKey] of this.pathlessLayoutMap) {\n if (page.filePath.startsWith(folderPath)) {\n return layoutKey\n }\n }\n return null\n }\n\n private addPathlessLayoutRoutes(\n routes: RouteNode[],\n pathlessPages: Map<string, RouteNode[]>\n ): void {\n if (pathlessPages.size === 0) return\n\n const rootLayout = routes.find((r) => r.type === 'layout' && r.routePath === '/')\n\n for (const [layoutKey, layoutPages] of pathlessPages) {\n const layout = this.layoutNodes.get(layoutKey)\n if (!layout) continue\n\n // Set children directly on layout\n layout.children = layoutPages.map((page) => {\n page.parent = layout\n return page\n })\n\n if (rootLayout) {\n // Nest pathless layout under root layout\n layout.parent = rootLayout\n rootLayout.children = rootLayout.children || []\n rootLayout.children.push(layout)\n } else {\n // No root layout, add to top level\n routes.push(layout)\n }\n }\n }\n\n /**\n * Insert a node into the tree\n */\n private insertNode(node: RouteNode): void {\n const segments = this.getPathSegments(node.routePath)\n let current = this.root\n\n for (let i = 0; i < segments.length; i++) {\n const segment = segments[i]\n const isLast = i === segments.length - 1\n\n if (!current.children.has(segment)) {\n const routePath = '/' + segments.slice(0, i + 1).join('/')\n current.children.set(segment, this.createTreeNode(segment, routePath, current))\n }\n\n current = current.children.get(segment)!\n\n if (isLast) {\n current.node = node\n node.parent = current.parent?.node\n }\n }\n\n // Handle index routes (routePath === '/')\n if (segments.length === 0 && node.type === 'index') {\n this.root.node = node\n }\n }\n\n /**\n * Get path segments from route path\n */\n private getPathSegments(routePath: string): string[] {\n return routePath\n .split('/')\n .filter(Boolean)\n }\n\n /**\n * Create a tree node\n */\n private createTreeNode(\n segment: string,\n routePath: string,\n parent?: TreeNode\n ): TreeNode {\n return {\n segment,\n routePath,\n children: new Map(),\n parent,\n }\n }\n\n /**\n * Flatten tree to route array\n */\n private flattenTree(): RouteNode[] {\n const routes: RouteNode[] = []\n\n // Check for root layout\n const rootLayout = this.layoutNodes.get('')\n\n if (rootLayout) {\n // Root layout wraps all routes\n const children = this.flattenChildren(this.root)\n\n // Add root index to children if exists\n if (this.root.node) {\n this.root.node.parent = rootLayout\n children.unshift(this.root.node)\n }\n\n // Set parent for all children\n for (const child of children) {\n child.parent = rootLayout\n }\n\n rootLayout.children = children\n routes.push(rootLayout)\n } else {\n // No root layout, flatten directly\n const children = this.flattenChildren(this.root)\n\n // Add root index if exists\n if (this.root.node) {\n children.unshift(this.root.node)\n }\n\n routes.push(...children)\n }\n\n return routes\n }\n\n /**\n * Flatten children of a tree node\n */\n private flattenChildren(treeNode: TreeNode, currentDir: string = ''): RouteNode[] {\n const children: RouteNode[] = []\n\n const sortedEntries = Array.from(treeNode.children.entries()).sort(([a], [b]) =>\n this.compareSegments(a, b)\n )\n\n for (const [segment, child] of sortedEntries) {\n const childDir = currentDir ? `${currentDir}/${segment}` : segment\n const flattenedChildren = this.flattenChildNode(child, childDir)\n children.push(...flattenedChildren)\n }\n\n return children\n }\n\n private flattenChildNode(child: TreeNode, childDir: string): RouteNode[] {\n const layout = this.layoutNodes.get(childDir)\n\n if (layout) {\n return [this.createLayoutWithChildren(layout, child, childDir)]\n }\n\n if (child.node) {\n return this.flattenNodeWithChildren(child, childDir)\n }\n\n // Virtual node (no file), just process children\n return this.flattenChildren(child, childDir)\n }\n\n private createLayoutWithChildren(\n layout: RouteNode,\n child: TreeNode,\n childDir: string\n ): RouteNode {\n layout.children = this.flattenChildren(child, childDir)\n\n // Add index page to layout children if exists\n if (child.node && child.node.type !== 'layout') {\n child.node.parent = layout\n layout.children.unshift(child.node)\n }\n\n // Set parent for all children\n for (const layoutChild of layout.children) {\n layoutChild.parent = layout\n }\n\n return layout\n }\n\n private flattenNodeWithChildren(child: TreeNode, childDir: string): RouteNode[] {\n const node = child.node!\n\n if (node.type === 'layout') {\n // This is a layout file (e.g., _layout.vue in directory)\n node.children = this.flattenChildren(child, childDir)\n return [node]\n }\n\n // Page node - add it as a leaf plus any nested children\n const nestedChildren = this.flattenChildren(child, childDir)\n return [node, ...nestedChildren]\n }\n\n /**\n * Compare segments for sorting\n * Order: static > dynamic > catch-all\n */\n private compareSegments(a: string, b: string): number {\n const aScore = this.getSegmentScore(a)\n const bScore = this.getSegmentScore(b)\n\n if (aScore !== bScore) {\n return aScore - bScore\n }\n\n return a.localeCompare(b)\n }\n\n /**\n * Get sorting score for a segment\n */\n private getSegmentScore(segment: string): number {\n // Catch-all: lowest priority\n if (segment.includes('(.*)*') || segment.includes('pathMatch')) {\n return 100\n }\n\n // Dynamic: medium priority\n if (segment.startsWith(':')) {\n return 50\n }\n\n // Static: highest priority\n return 0\n }\n}\n\n/**\n * Create a route tree builder\n */\nexport function createTreeBuilder(config: ResolvedRouterConfig): RouteTreeBuilder {\n return new RouteTreeBuilder(config)\n}\n\n/**\n * Build route tree from nodes\n */\nexport function buildRouteTree(\n nodes: RouteNode[],\n config: ResolvedRouterConfig\n): RouteNode[] {\n const builder = new RouteTreeBuilder(config)\n return builder.build(nodes)\n}\n","import * as path from 'pathe'\nimport type { RouteNode, ResolvedRouterConfig } from '../types'\n\n/**\n * Generate routes.gen.ts content\n */\nexport function generateRoutes(\n routes: RouteNode[],\n config: ResolvedRouterConfig\n): string {\n const imports: string[] = []\n const importMap = new Map<string, string>()\n const routeDefImportMap = new Map<string, string>()\n\n // Collect all component imports\n collectImports(routes, config, imports, importMap)\n\n // Collect route definition imports (for routes with loaders/meta)\n collectRouteDefinitionImports(routes, config, imports, routeDefImportMap)\n\n // Generate route records\n const routeRecords = generateRouteRecords(routes, config, importMap, routeDefImportMap)\n\n return `// Auto-generated by @kimesh/router-generator\n// Do not edit this file manually\n\n${imports.join('\\n')}\n\nexport const routes = ${routeRecords}\n`\n}\n\n/**\n * Collect imports from route nodes\n */\nfunction collectImports(\n routes: RouteNode[],\n config: ResolvedRouterConfig,\n imports: string[],\n importMap: Map<string, string>\n): void {\n for (const route of routes) {\n if (!route.isLazy) {\n // Eager import\n const importPath = getImportPath(route, config)\n const importName = route.variableName\n imports.push(`import ${importName} from '${importPath}'`)\n importMap.set(route.filePath, importName)\n }\n\n // Recursively collect children\n if (route.children.length > 0) {\n collectImports(route.children, config, imports, importMap)\n }\n }\n}\n\n/**\n * Collect route definition imports for routes with loaders/meta\n * Uses ?route query to extract route definitions at build time (Vite 8/rolldown compatible)\n */\nfunction collectRouteDefinitionImports(\n routes: RouteNode[],\n config: ResolvedRouterConfig,\n imports: string[],\n routeDefImportMap: Map<string, string>\n): void {\n for (const route of routes) {\n if (route.parsed.hasRouteDefinition) {\n const importPath = getImportPath(route, config)\n const defName = `${route.variableName}_def`\n // Use ?route query to extract route definition at build time\n imports.push(`import ${defName} from '${importPath}?route'`)\n routeDefImportMap.set(route.filePath, defName)\n }\n\n // Recursively collect children\n if (route.children.length > 0) {\n collectRouteDefinitionImports(route.children, config, imports, routeDefImportMap)\n }\n }\n}\n\n/**\n * Get import path relative to generated file\n */\nfunction getImportPath(route: RouteNode, config: ResolvedRouterConfig): string {\n const fromPath = config.generatedDirPath\n const toPath = route.fullPath\n\n let relativePath = path.relative(fromPath, toPath)\n\n // Ensure it starts with ./\n if (!relativePath.startsWith('.')) {\n relativePath = './' + relativePath\n }\n\n return relativePath\n}\n\ninterface RouteRecordContext {\n config: ResolvedRouterConfig\n importMap: Map<string, string>\n routeDefImportMap: Map<string, string>\n}\n\n/**\n * Generate route records array\n */\nfunction generateRouteRecords(\n routes: RouteNode[],\n config: ResolvedRouterConfig,\n importMap: Map<string, string>,\n routeDefImportMap: Map<string, string>,\n indent: number = 0\n): string {\n const ctx: RouteRecordContext = { config, importMap, routeDefImportMap }\n const pad = ' '.repeat(indent)\n const innerPad = ' '.repeat(indent + 1)\n\n const records = routes.map((route) =>\n generateSingleRouteRecord(route, ctx, innerPad, indent)\n )\n\n return `[\\n${records.join(',\\n')}\\n${pad}]`\n}\n\nfunction generateSingleRouteRecord(\n route: RouteNode,\n ctx: RouteRecordContext,\n innerPad: string,\n indent: number\n): string {\n const lines: string[] = [`${innerPad}{`]\n\n // Path\n const routePath = route.parent ? getRelativePath(route) : route.routePath\n lines.push(`${innerPad} path: '${routePath}',`)\n\n // Name (only for leaf routes or index)\n if (shouldIncludeName(route)) {\n lines.push(`${innerPad} name: '${route.routeName}',`)\n }\n\n // Component\n lines.push(generateComponentLine(route, ctx, innerPad))\n\n // Meta with route definition (for loaders) and layer info\n const routeDefName = ctx.routeDefImportMap.get(route.filePath)\n const metaProps: string[] = []\n if (routeDefName) {\n metaProps.push(`__kimesh: ${routeDefName}`)\n }\n if (route.layer) {\n metaProps.push(`__kimeshLayer: '${route.layer}'`)\n }\n if (metaProps.length > 0) {\n lines.push(`${innerPad} meta: { ${metaProps.join(', ')} },`)\n }\n\n // Children\n if (route.children.length > 0) {\n const childRecords = generateRouteRecords(\n route.children,\n ctx.config,\n ctx.importMap,\n ctx.routeDefImportMap,\n indent + 2\n )\n lines.push(`${innerPad} children: ${childRecords},`)\n }\n\n lines.push(`${innerPad}}`)\n return lines.join('\\n')\n}\n\nfunction shouldIncludeName(route: RouteNode): boolean {\n return route.type !== 'layout' || route.children.length === 0\n}\n\nfunction generateComponentLine(\n route: RouteNode,\n ctx: RouteRecordContext,\n innerPad: string\n): string {\n if (route.isLazy) {\n const importPath = getImportPath(route, ctx.config)\n return `${innerPad} component: () => import('${importPath}'),`\n }\n\n const importName = ctx.importMap.get(route.filePath) || route.variableName\n return `${innerPad} component: ${importName},`\n}\n\n/**\n * Get path relative to parent route\n */\nfunction getRelativePath(route: RouteNode): string {\n if (!route.parent) {\n return route.routePath\n }\n\n const parentPath = route.parent.routePath\n const routePath = route.routePath\n\n // For root level layout, children need relative paths\n if (parentPath === '/') {\n return routePath === '/' ? '' : stripLeadingSlash(routePath)\n }\n\n // For nested layouts - remove parent path prefix\n let relativePath = routePath\n if (relativePath.startsWith(parentPath)) {\n relativePath = relativePath.slice(parentPath.length)\n }\n\n relativePath = stripLeadingSlash(relativePath)\n\n // Empty path for index routes\n return !relativePath && route.type === 'index' ? '' : relativePath\n}\n\nfunction stripLeadingSlash(path: string): string {\n return path.startsWith('/') ? path.slice(1) : path\n}\n","import type { RouteNode, RouteParam } from '../types'\n\n/**\n * Route info for type generation\n */\ninterface RouteInfo {\n name: string\n path: string\n params: RouteParam[]\n children: string[]\n}\n\n/**\n * Generate typed-routes.d.ts content with comprehensive type safety\n */\nexport function generateRouteTypes(routes: RouteNode[]): string {\n const routeInfos = collectAllRoutes(routes)\n\n const routeMapEntries = routeInfos\n .map((r) => generateRouteRecordInfo(r))\n .join('\\n')\n\n const routePathsUnion =\n routeInfos.length > 0 ? routeInfos.map((r) => `'${r.path}'`).join(' | ') : 'never'\n\n return `/* eslint-disable */\n/* prettier-ignore */\n// @ts-nocheck\n// Auto-generated by @kimesh/router-generator\n// Do not edit this file manually\n\nimport type {\n RouteRecordInfo,\n ParamValue,\n ParamValueOneOrMore,\n ParamValueZeroOrMore,\n ParamValueZeroOrOne,\n} from 'vue-router'\n\n// Augment @kimesh/router-runtime for typed composables\ndeclare module '@kimesh/router-runtime' {\n export interface RouteNamedMap {\n${routeMapEntries}\n }\n}\n\n// Augment vue-router for typed router.push(), useRoute(), etc.\ndeclare module 'vue-router' {\n export interface TypesConfig {\n RouteNamedMap: import('@kimesh/router-runtime').RouteNamedMap\n }\n}\n\n/** Union of all route names/paths */\nexport type RouteNames = ${routePathsUnion}\n\n/** Union of all route paths */\nexport type RoutePaths = ${routePathsUnion}\n`\n}\n\n/**\n * Collect all routes recursively into flat array\n */\nfunction collectAllRoutes(routes: RouteNode[]): RouteInfo[] {\n const infos: RouteInfo[] = []\n collectRoutesRecursively(routes, '', infos)\n return infos\n}\n\nfunction collectRoutesRecursively(\n nodes: RouteNode[],\n parentPath: string,\n infos: RouteInfo[]\n): void {\n for (const route of nodes) {\n const fullPath = computeFullPath(route.routePath, parentPath)\n\n // Skip layouts from the route map (they don't have their own path)\n if (route.type === 'layout') {\n if (route.children.length > 0) {\n const childParentPath = fullPath === '/' ? '' : fullPath\n collectRoutesRecursively(route.children, childParentPath, infos)\n }\n continue\n }\n\n infos.push({\n name: fullPath,\n path: fullPath,\n params: collectParamsFromPath(fullPath),\n children: collectChildPaths(route.children, fullPath),\n })\n\n if (route.children.length > 0) {\n collectRoutesRecursively(route.children, fullPath, infos)\n }\n }\n}\n\nfunction computeFullPath(routePath: string, parentPath: string): string {\n if (routePath === '' || routePath === '/') {\n return parentPath || '/'\n }\n\n if (routePath.startsWith('/')) {\n return routePath\n }\n\n return parentPath === '/' ? `/${routePath}` : `${parentPath}/${routePath}`\n}\n\nfunction collectChildPaths(children: RouteNode[], parentFullPath: string): string[] {\n return children\n .filter((c) => c.type !== 'layout')\n .map((c) => computeFullPath(c.routePath, parentFullPath))\n}\n\n/**\n * Extract params from a route path\n * e.g., '/users/:userId/posts/:postId' -> [{ name: 'userId', ... }, { name: 'postId', ... }]\n */\nfunction collectParamsFromPath(routePath: string): RouteParam[] {\n const params: RouteParam[] = []\n const regex = /:([a-zA-Z_][a-zA-Z0-9_]*)(\\?)?(\\+)?(\\*)?/g\n let match\n\n while ((match = regex.exec(routePath)) !== null) {\n const name = match[1]\n const hasQuestion = match[2] === '?'\n const hasPlus = match[3] === '+'\n const hasStar = match[4] === '*'\n\n params.push({\n name,\n optional: hasQuestion || hasStar,\n isSplat: hasStar,\n repeatable: hasPlus || hasStar,\n })\n }\n\n return params\n}\n\n/**\n * Generate RouteRecordInfo entry for a route\n */\nfunction generateRouteRecordInfo(route: RouteInfo): string {\n const rawParams = generateParamsType(route.params, true)\n const params = generateParamsType(route.params, false)\n const children =\n route.children.length > 0 ? route.children.map((c) => `'${c}'`).join(' | ') : 'never'\n\n return ` '${route.name}': RouteRecordInfo<\n '${route.name}',\n '${route.path}',\n ${rawParams},\n ${params},\n ${children}\n >,`\n}\n\n/**\n * Generate params type object\n */\nfunction generateParamsType(params: RouteParam[], isRaw: boolean): string {\n if (params.length === 0) {\n return 'Record<never, never>'\n }\n\n const entries = params.map((p) => formatParamEntry(p, isRaw)).join('; ')\n return `{ ${entries} }`\n}\n\nfunction formatParamEntry(param: RouteParam, isRaw: boolean): string {\n const optional = param.optional ? '?' : ''\n const type = getParamValueType(param, isRaw)\n return `${param.name}${optional}: ${type}`\n}\n\nfunction getParamValueType(param: RouteParam, isRaw: boolean): string {\n if (param.repeatable) {\n return param.optional\n ? `ParamValueZeroOrMore<${isRaw}>`\n : `ParamValueOneOrMore<${isRaw}>`\n }\n\n if (param.optional) {\n return `ParamValueZeroOrOne<${isRaw}>`\n }\n\n return `ParamValue<${isRaw}>`\n}\n","import * as fs from 'node:fs'\nimport * as path from 'pathe'\n\nconst ROUTE_QUERY_RE = /[?&]route\\b/\nconst CREATE_FILE_ROUTE_START_RE = /export\\s+const\\s+Route\\s*=\\s*createFileRoute\\s*\\(\\s*['\"`][^'\"`]*['\"`]\\s*\\)\\s*\\(/\nconst EMPTY_EXPORT = 'export default {}'\n\n/**\n * Check if the id has a ?route query parameter\n */\nexport function isRouteQuery(id: string): boolean {\n return ROUTE_QUERY_RE.test(id)\n}\n\n/**\n * Get the base path without the ?route query\n */\nexport function getBasePath(id: string): string {\n return id.split('?')[0]\n}\n\n/**\n * Extract route definition from a Vue SFC file\n * Returns the route config object as a module with default export\n */\nexport function extractRouteDefinition(filePath: string): string {\n const code = fs.readFileSync(filePath, 'utf-8')\n\n // Find the start of createFileRoute call\n const match = CREATE_FILE_ROUTE_START_RE.exec(code)\n if (!match) {\n return EMPTY_EXPORT\n }\n\n // Find the position right after `createFileRoute('/path')(`\n const startPos = match.index + match[0].length\n\n // Extract the object using balanced bracket matching\n const routeObject = extractBalancedObject(code, startPos)\n if (!routeObject) {\n return EMPTY_EXPORT\n }\n\n // Extract imports that might be needed (with absolute paths)\n const fileDir = path.dirname(filePath)\n const imports = extractUsedImports(code, routeObject, fileDir)\n\n return `${imports}\\nexport default ${routeObject}`\n}\n\ninterface ParserState {\n inString: string | null\n inTemplateString: boolean\n inLineComment: boolean\n inBlockComment: boolean\n depth: number\n}\n\n/**\n * Extract a balanced object starting from a position in the code\n * Handles nested braces, strings, template literals, and comments\n */\nfunction extractBalancedObject(code: string, startPos: number): string | null {\n let i = skipWhitespace(code, startPos)\n\n if (code[i] !== '{') {\n return null\n }\n\n const objectStart = i\n const state: ParserState = {\n inString: null,\n inTemplateString: false,\n inLineComment: false,\n inBlockComment: false,\n depth: 0,\n }\n\n for (; i < code.length; i++) {\n const result = processCharacter(code, i, state)\n\n if (result.skip) {\n i = result.newIndex ?? i\n continue\n }\n\n if (result.foundEnd) {\n return code.slice(objectStart, i + 1)\n }\n }\n\n return null\n}\n\nfunction skipWhitespace(code: string, pos: number): number {\n while (pos < code.length && /\\s/.test(code[pos])) {\n pos++\n }\n return pos\n}\n\ninterface ProcessResult {\n skip: boolean\n newIndex?: number\n foundEnd?: boolean\n}\n\nfunction processCharacter(code: string, i: number, state: ParserState): ProcessResult {\n const char = code[i]\n const nextChar = code[i + 1]\n const prevChar = code[i - 1]\n\n // Handle line comments\n if (state.inLineComment) {\n if (char === '\\n') {\n state.inLineComment = false\n }\n return { skip: true }\n }\n\n // Handle block comments\n if (state.inBlockComment) {\n if (char === '*' && nextChar === '/') {\n state.inBlockComment = false\n return { skip: true, newIndex: i + 1 }\n }\n return { skip: true }\n }\n\n // Handle template strings\n if (state.inTemplateString) {\n if (char === '`') {\n state.inTemplateString = false\n }\n return { skip: true }\n }\n\n // Handle regular strings\n if (state.inString) {\n if (char === state.inString && prevChar !== '\\\\') {\n state.inString = null\n }\n return { skip: true }\n }\n\n // Check for start of line comment\n if (char === '/' && nextChar === '/') {\n state.inLineComment = true\n return { skip: true }\n }\n\n // Check for start of block comment\n if (char === '/' && nextChar === '*') {\n state.inBlockComment = true\n return { skip: true, newIndex: i + 1 }\n }\n\n // Check for template string\n if (char === '`') {\n state.inTemplateString = true\n return { skip: true }\n }\n\n // Check for regular string\n if (char === '\"' || char === \"'\") {\n state.inString = char\n return { skip: true }\n }\n\n // Track braces\n if (char === '{') {\n state.depth++\n return { skip: false }\n }\n\n if (char === '}') {\n state.depth--\n if (state.depth === 0) {\n return { skip: false, foundEnd: true }\n }\n }\n\n return { skip: false }\n}\n\nconst IMPORT_REGEX = /import\\s+(?:\\{([^}]+)\\}|(\\w+))\\s+from\\s+['\"]([^'\"]+)['\"]/g\nconst SKIP_IMPORT_SOURCES = new Set(['vue', '@kimesh/router-runtime'])\n\n/**\n * Extract imports that are used in the route object\n * Converts relative imports to absolute paths for virtual module compatibility\n */\nfunction extractUsedImports(code: string, routeObject: string, fileDir: string): string {\n const namedImports = new Map<string, Set<string>>()\n const defaultImports = new Map<string, string>()\n\n let match\n while ((match = IMPORT_REGEX.exec(code)) !== null) {\n processImportMatch(match, routeObject, fileDir, namedImports, defaultImports)\n }\n\n return buildImportStatements(namedImports, defaultImports)\n}\n\nfunction processImportMatch(\n match: RegExpExecArray,\n routeObject: string,\n fileDir: string,\n namedImports: Map<string, Set<string>>,\n defaultImports: Map<string, string>\n): void {\n const namedImportStr = match[1]\n const defaultImport = match[2]\n let source = match[3]\n\n if (shouldSkipImport(source)) {\n return\n }\n\n source = resolveImportSource(source, fileDir)\n\n if (namedImportStr) {\n addUsedNamedImports(namedImportStr, source, routeObject, namedImports)\n } else if (defaultImport && routeObject.includes(defaultImport)) {\n defaultImports.set(source, defaultImport)\n }\n}\n\nfunction shouldSkipImport(source: string): boolean {\n for (const skip of SKIP_IMPORT_SOURCES) {\n if (source.includes(skip)) {\n return true\n }\n }\n return false\n}\n\nfunction resolveImportSource(source: string, fileDir: string): string {\n if (source.startsWith('.')) {\n return path.resolve(fileDir, source)\n }\n return source\n}\n\nfunction addUsedNamedImports(\n namedImportStr: string,\n source: string,\n routeObject: string,\n namedImports: Map<string, Set<string>>\n): void {\n const importNames = namedImportStr.split(',').map((s) => s.trim().split(' as ')[0].trim())\n\n const usedImports = importNames.filter((name) => {\n const identifierRegex = new RegExp(`\\\\b${name}\\\\b`)\n return identifierRegex.test(routeObject)\n })\n\n if (usedImports.length === 0) {\n return\n }\n\n if (!namedImports.has(source)) {\n namedImports.set(source, new Set())\n }\n\n for (const imp of usedImports) {\n namedImports.get(source)!.add(imp)\n }\n}\n\nfunction buildImportStatements(\n namedImports: Map<string, Set<string>>,\n defaultImports: Map<string, string>\n): string {\n const statements: string[] = []\n\n for (const [source, specifiers] of namedImports) {\n statements.push(`import { ${Array.from(specifiers).join(', ')} } from '${source}'`)\n }\n\n for (const [source, name] of defaultImports) {\n statements.push(`import ${name} from '${source}'`)\n }\n\n return statements.join('\\n')\n}\n","/**\n * @kimesh/router-generator - Layer Route Collector\n *\n * Collects routes from multiple layers with priority-based resolution.\n */\n\nimport fg from 'fast-glob'\nimport * as fs from 'node:fs'\nimport * as path from 'pathe'\nimport { consola } from 'consola'\nimport type { RouteNode, ResolvedRouterConfig } from './types'\nimport { parseRouteFile } from './parser'\nimport { needsScaffolding, generateRouteScaffold } from './scaffolder'\nimport {\n isRootDir,\n extractDynamicParam,\n isDotNotationRoute,\n unescapeBrackets,\n buildRoutePath,\n createDynamicParam,\n createCatchAllParam,\n buildGlobPattern as buildGlobPatternUtil,\n} from './route-utils'\n\nconst logger = consola.withTag('kimesh:router:layer-collector')\n\n/**\n * Layer route source configuration\n */\nexport interface LayerRouteSource {\n /** Layer name */\n layer: string\n\n /** Layer priority (0 = app/highest) */\n priority: number\n\n /** Absolute path to routes directory */\n routesDir: string\n\n /** Base path prefix for all routes in this layer */\n basePath?: string\n}\n\n/**\n * Collected layer routes result\n */\nexport interface LayerRoutesResult {\n /** All route nodes from all layers */\n routes: RouteNode[]\n\n /** Routes grouped by layer */\n byLayer: Map<string, RouteNode[]>\n\n /** Timing information */\n timing: {\n totalMs: number\n perLayer: Map<string, number>\n }\n}\n\n/**\n * Extended route node with layer information\n */\nexport interface LayerRouteNode extends RouteNode {\n /** Source layer name */\n layer: string\n\n /** Layer priority */\n layerPriority: number\n\n /** Base path from layer config */\n layerBasePath?: string\n\n /** Final route path (with basePath applied) */\n finalRoutePath: string\n}\n\n/**\n * Collect routes from all configured layers and build proper route trees\n */\nexport async function collectLayerRoutes(\n sources: LayerRouteSource[],\n config: ResolvedRouterConfig\n): Promise<LayerRoutesResult> {\n const startTime = performance.now()\n const allRoutes: RouteNode[] = []\n const byLayer = new Map<string, RouteNode[]>()\n const perLayerTiming = new Map<string, number>()\n\n // Sort sources by priority (app first)\n const sortedSources = [...sources].sort((a, b) => a.priority - b.priority)\n\n // Collect and build trees from each layer in parallel\n const scanPromises = sortedSources.map(async (source) => {\n const layerStartTime = performance.now()\n const flatRoutes = await scanLayerRoutes(source, config)\n // Build tree for this layer's routes\n const routeTree = buildLayerRouteTree(flatRoutes, source)\n const layerTime = performance.now() - layerStartTime\n\n return { source, routes: routeTree, time: layerTime }\n })\n\n const results = await Promise.all(scanPromises)\n\n for (const { source, routes, time } of results) {\n allRoutes.push(...routes)\n byLayer.set(source.layer, routes)\n perLayerTiming.set(source.layer, time)\n\n logger.debug(\n `Layer '${source.layer}': ${routes.length} route tree(s) in ${time.toFixed(1)}ms`\n )\n }\n\n const totalTime = performance.now() - startTime\n logger.info(`Collected ${allRoutes.length} routes from ${sources.length} layers in ${totalTime.toFixed(1)}ms`)\n\n return {\n routes: allRoutes,\n byLayer,\n timing: {\n totalMs: totalTime,\n perLayer: perLayerTiming,\n },\n }\n}\n\n/**\n * Build a proper route tree for a layer's routes\n * Layouts become parents with children, pages become leaves\n *\n * Routes are organized by their file path which directly maps to URL path.\n * Example: routes/blog/_layout.vue → /blog layout\n * routes/blog/index.vue → /blog (index under /blog layout)\n * routes/blog/$postId.vue → /blog/:postId (child under /blog layout)\n */\nfunction buildLayerRouteTree(\n flatRoutes: LayerRouteNode[],\n source: LayerRouteSource\n): RouteNode[] {\n if (flatRoutes.length === 0) return []\n\n // Separate layouts and pages\n const layoutMap = new Map<string, LayerRouteNode>()\n const pages: LayerRouteNode[] = []\n\n for (const route of flatRoutes) {\n if (route.type === 'layout') {\n // Key by the route path\n const layoutPath = route.finalRoutePath\n layoutMap.set(layoutPath, route)\n } else {\n pages.push(route)\n }\n }\n\n // If no layouts, return pages as flat routes\n if (layoutMap.size === 0) {\n return pages.map(page => ({\n ...page,\n routePath: page.finalRoutePath,\n }))\n }\n\n // Find the root layout - the one with the shortest path (most top-level)\n let rootLayout: LayerRouteNode | null = null\n let rootLayoutPath = ''\n\n for (const [layoutPath, layout] of layoutMap) {\n if (!rootLayout || layoutPath.length < rootLayoutPath.length) {\n rootLayout = layout\n rootLayoutPath = layoutPath\n }\n }\n\n if (!rootLayout) {\n return pages.map(page => ({\n ...page,\n routePath: page.finalRoutePath,\n }))\n }\n\n // Build children for the root layout\n const children: RouteNode[] = []\n const normalizedBase = rootLayoutPath\n\n for (const page of pages) {\n const pagePath = page.finalRoutePath\n\n if (pagePath === normalizedBase || pagePath === normalizedBase + '/') {\n // This is the index page for the layout\n const indexRoute: RouteNode = {\n ...page,\n routePath: '', // Relative path under layout\n parent: rootLayout,\n }\n children.unshift(indexRoute) // Index first\n } else if (pagePath.startsWith(normalizedBase + '/') || (normalizedBase === '/' && pagePath.startsWith('/'))) {\n // Child route - make path relative\n const relativePath = normalizedBase === '/'\n ? pagePath.slice(1)\n : pagePath.slice(normalizedBase.length + 1)\n const childRoute: RouteNode = {\n ...page,\n routePath: relativePath,\n parent: rootLayout,\n }\n children.push(childRoute)\n }\n }\n\n // Set up the layout with children\n const layoutRoute: RouteNode = {\n ...rootLayout,\n routePath: rootLayout.finalRoutePath,\n children,\n }\n\n return [layoutRoute]\n}\n\n/**\n * Scan routes from a single layer\n */\nasync function scanLayerRoutes(\n source: LayerRouteSource,\n config: ResolvedRouterConfig\n): Promise<LayerRouteNode[]> {\n const { layer, priority, routesDir, basePath } = source\n\n if (!fs.existsSync(routesDir)) {\n logger.debug(`Routes directory not found for layer '${layer}': ${routesDir}`)\n return []\n }\n\n const pattern = buildGlobPatternUtil(config.extensions)\n\n const files = await fg(pattern, {\n cwd: routesDir,\n onlyFiles: true,\n ignore: ['**/node_modules/**'],\n })\n\n // Get all directories to detect layout route patterns (posts.vue + posts/)\n const directories = await fg('**/', {\n cwd: routesDir,\n onlyDirectories: true,\n ignore: ['**/node_modules/**'],\n })\n const dirSet = new Set(directories.map(d => d.replace(/\\/$/, '')))\n\n const routes: LayerRouteNode[] = []\n\n for (const file of files.sort()) {\n const node = await processLayerFile(file, routesDir, source, config, dirSet)\n if (node) {\n routes.push(node)\n }\n }\n\n return routes\n}\n\n/**\n * Process a single route file from a layer\n * \n * Supports layout route pattern: posts.vue + posts/ directory\n * When a file like posts.vue has a matching posts/ directory, it becomes a layout\n */\nasync function processLayerFile(\n filePath: string,\n routesDir: string,\n source: LayerRouteSource,\n config: ResolvedRouterConfig,\n dirSet: Set<string>\n): Promise<LayerRouteNode | null> {\n const fullPath = path.join(routesDir, filePath)\n const fileName = path.basename(filePath, path.extname(filePath))\n const dirPath = path.dirname(filePath)\n\n // Exclude files with dash prefix from routing (colocated logic)\n if (fileName.startsWith('-')) {\n return null\n }\n\n // Check for layout route pattern: posts.vue + posts/ directory\n // If this file has a matching directory, treat it as a layout\n const potentialDirPath = isRootDir(dirPath) ? fileName : `${dirPath}/${fileName}`\n const hasMatchingDirectory = dirSet.has(potentialDirPath)\n \n // Determine route type and path\n let { type, routePath, params, rawSegment, isPathlessLayout } = parseFileName(fileName, dirPath)\n\n // If file has matching directory (e.g., posts.vue + posts/), it's a layout route\n if (hasMatchingDirectory && type === 'page') {\n type = 'layout'\n // Route path for layout should be the directory path\n routePath = buildRoutePath(dirPath, fileName)\n logger.debug(`Layout route detected: ${fileName} -> ${routePath}`)\n }\n\n // Read file content\n let content: string\n try {\n content = fs.readFileSync(fullPath, 'utf-8')\n } catch {\n logger.warn(`Could not read file: ${fullPath}`)\n return null\n }\n\n // Check if file needs scaffolding\n if (needsScaffolding(content)) {\n const isLayout = type === 'layout'\n const isDynamic = type === 'dynamic'\n const paramName = params[0]?.name\n\n content = generateRouteScaffold({\n routePath,\n isLayout,\n isDynamic,\n paramName,\n })\n\n // Write scaffolded content back\n fs.writeFileSync(fullPath, content, 'utf-8')\n logger.debug(`Scaffolded route: ${source.layer}:${filePath}`)\n }\n\n // Parse the content\n const parsed = parseRouteFile(content, fullPath)\n\n // Generate variable name (unique across layers)\n const variableName = generateVariableName(filePath, source.layer)\n\n // Apply basePath to route path\n const finalRoutePath = applyBasePath(routePath, source.basePath)\n\n // Generate route name\n const routeName = generateRouteName(finalRoutePath, source.layer)\n\n // Check if lazy loaded\n const isLazy = fileName.endsWith('.lazy') || shouldBeLazy(filePath, config)\n\n const node: LayerRouteNode = {\n filePath,\n fullPath,\n routePath,\n variableName,\n type,\n routeName,\n isLazy,\n params,\n parsed,\n children: [],\n rawSegment,\n layer: source.layer,\n layerPriority: source.priority,\n layerBasePath: source.basePath,\n finalRoutePath,\n }\n\n return node\n}\n\n/**\n * Parse filename to determine route type and path\n *\n * File-based routing conventions:\n * - __root.vue → root layout (wraps all routes)\n * - index.vue → index route\n * - route.vue → alternative index route\n * - about.vue → regular page\n * - $id.vue → dynamic param\n * - $.vue → catch-all (splat route)\n * - (group)/ → pathless group folder (route group)\n * - _pathless.vue + _pathless/ → pathless layout (underscore prefix)\n * - posts.vue + posts/ → layout route\n * - posts.index.vue → flat route notation (dot separator)\n * - posts_/ → layout escape (underscore suffix)\n * - -utils.vue → excluded from routing (dash prefix)\n * - [x] → escape special characters (e.g., script[.]js.vue → /script.js)\n */\nfunction parseFileName(\n fileName: string,\n dirPath: string\n): {\n type: RouteNode['type']\n routePath: string\n params: RouteNode['params']\n rawSegment: string\n isPathlessLayout?: boolean\n} {\n let rawSegment = fileName\n\n // Remove .lazy suffix\n if (fileName.endsWith('.lazy')) {\n fileName = fileName.slice(0, -5)\n rawSegment = fileName\n }\n\n // Exclude files with dash prefix from routing (colocated logic)\n if (fileName.startsWith('-')) {\n return { type: 'page', routePath: '', params: [], rawSegment }\n }\n\n // Handle root route file: __root.vue\n if (fileName === '__root') {\n return { type: 'layout', routePath: '/', params: [], rawSegment }\n }\n\n // Handle pathless layout pattern: _name.vue (single underscore prefix = pathless layout)\n if (fileName.startsWith('_') && !fileName.startsWith('__')) {\n return {\n type: 'layout',\n routePath: buildRoutePath(dirPath, ''),\n params: [],\n rawSegment,\n isPathlessLayout: true,\n }\n }\n\n // Handle index files\n if (fileName === 'index' || fileName === 'route') {\n return {\n type: 'index',\n routePath: buildRoutePath(dirPath, ''),\n params: [],\n rawSegment,\n }\n }\n\n // Handle flat routes with dot notation: posts.index.vue, posts.$postId.vue\n if (isDotNotationRoute(fileName)) {\n return parseDotNotationRoute(fileName, dirPath, rawSegment)\n }\n\n // Handle catch-all: $.vue (splat route)\n if (fileName === '$') {\n return {\n type: 'catch-all',\n routePath: buildRoutePath(dirPath, ':pathMatch(.*)*'),\n params: [createCatchAllParam()],\n rawSegment,\n }\n }\n\n // Handle dynamic params: $id.vue only (TanStack style)\n const dynamicParam = extractDynamicParam(fileName)\n if (dynamicParam) {\n return {\n type: 'dynamic',\n routePath: buildRoutePath(dirPath, `:${dynamicParam}`),\n params: [createDynamicParam(dynamicParam)],\n rawSegment,\n }\n }\n\n // Regular page - apply bracket escaping for special characters\n const escapedFileName = unescapeBrackets(fileName)\n return {\n type: 'page',\n routePath: buildRoutePath(dirPath, escapedFileName),\n params: [],\n rawSegment,\n }\n}\n\nfunction parseDotNotationRoute(\n fileName: string,\n dirPath: string,\n rawSegment: string\n): {\n type: RouteNode['type']\n routePath: string\n params: RouteNode['params']\n rawSegment: string\n} {\n const segments = fileName.split('.')\n const lastSegment = segments[segments.length - 1]\n const parentSegments = segments.slice(0, -1)\n\n // Build the virtual directory path from dot-separated parts\n const virtualDir = isRootDir(dirPath)\n ? parentSegments.join('/')\n : `${dirPath}/${parentSegments.join('/')}`\n\n // Parse the last segment for type determination\n if (lastSegment === 'index') {\n return {\n type: 'index',\n routePath: buildRoutePath(virtualDir, ''),\n params: [],\n rawSegment,\n }\n }\n\n // Check for dynamic param in last segment\n const dynamicParam = extractDynamicParam(lastSegment)\n if (dynamicParam) {\n return {\n type: 'dynamic',\n routePath: buildRoutePath(virtualDir, `:${dynamicParam}`),\n params: [createDynamicParam(dynamicParam)],\n rawSegment,\n }\n }\n\n // Regular page with dot notation - apply bracket escaping\n const escapedSegment = unescapeBrackets(lastSegment)\n return {\n type: 'page',\n routePath: buildRoutePath(virtualDir, escapedSegment),\n params: [],\n rawSegment,\n }\n}\n\n/**\n * Apply basePath prefix to route path\n */\nfunction applyBasePath(routePath: string, basePath?: string): string {\n if (!basePath) return routePath\n\n // Normalize basePath\n const normalizedBase = basePath.startsWith('/') ? basePath : `/${basePath}`\n const base = normalizedBase.endsWith('/') ? normalizedBase.slice(0, -1) : normalizedBase\n\n if (routePath === '/') {\n return base || '/'\n }\n\n return `${base}${routePath}`\n}\n\n/**\n * Generate a unique variable name for a route\n */\nfunction generateVariableName(filePath: string, layer: string): string {\n const withoutExt = filePath.replace(/\\.[^/.]+$/, '')\n const layerPrefix = layer === 'app' ? '' : `${sanitizeForVariable(layer)}_`\n\n return (\n layerPrefix +\n withoutExt\n .replace(/[\\/\\\\]/g, '_')\n .replace(/[\\[\\]$().+-]/g, '_')\n .replace(/^_+|_+$/g, '')\n .replace(/_+/g, '_')\n .replace(/^(\\d)/, '_$1')\n )\n}\n\n/**\n * Sanitize string for use in variable name\n */\nfunction sanitizeForVariable(str: string): string {\n return str\n .replace(/^@/, '')\n .replace(/[\\/\\\\@-]/g, '_')\n .replace(/^_+|_+$/g, '')\n .replace(/_+/g, '_')\n}\n\n/**\n * Generate route name from route path\n */\nfunction generateRouteName(routePath: string, layer: string): string {\n const layerPrefix = layer === 'app' ? '' : `${layer.replace(/[@\\/]/g, '-')}-`\n\n if (routePath === '/') {\n return `${layerPrefix}index`\n }\n\n const name = routePath\n .slice(1)\n .replace(/\\//g, '-')\n .replace(/:/g, '')\n .replace(/\\(.*?\\)\\*/g, 'catchAll')\n .replace(/\\?/g, '')\n\n return `${layerPrefix}${name}`\n}\n\n/**\n * Check if route should be lazy loaded\n */\nfunction shouldBeLazy(filePath: string, config: ResolvedRouterConfig): boolean {\n const { importMode } = config\n\n if (typeof importMode === 'function') {\n return importMode(filePath) === 'async'\n }\n\n return importMode === 'async'\n}\n","import * as path from 'pathe'\nimport * as fs from 'node:fs'\nimport { watch } from 'chokidar'\nimport type { Plugin, ViteDevServer } from 'vite'\nimport type { KimeshRouterConfig, ResolvedRouterConfig, RouteNode } from './types'\nimport { RouteScanner } from './scanner'\nimport { buildRouteTree } from './tree-builder'\nimport { generateRoutes } from './codegen/routes'\nimport { generateRouteTypes } from './codegen/types'\nimport { isRouteQuery, getBasePath, extractRouteDefinition } from './extract-route'\nimport { collectLayerRoutes, type LayerRouteSource } from './layer-collector'\n\nconst VIRTUAL_ROUTES_ID = '\\0virtual:kimesh-routes'\nconst VIRTUAL_ROUTE_PREFIX = '\\0kimesh-route:'\n\n/**\n * Layer route configuration\n */\nexport interface LayerRouteConfig {\n /** Layer name */\n layerName: string\n /** Routes directory path */\n routesDir: string\n /** Layer root path (for generating .kimesh directory) */\n layerPath?: string\n /** Base path prefix for routes */\n basePath?: string\n /** Layer priority (lower = higher priority) */\n priority: number\n}\n\nexport interface KimeshRouterPluginOptions extends Partial<KimeshRouterConfig> {\n /** Enable debug logging */\n debug?: boolean\n /** Layer routes configuration (static) */\n layerRoutes?: LayerRouteConfig[]\n /** Layer routes configuration (lazy getter for async resolution) */\n getLayerRoutes?: () => LayerRouteConfig[]\n}\n\nconst DEFAULT_CONFIG: KimeshRouterConfig = {\n srcDir: 'src',\n routesDir: 'routes',\n generatedDir: '.kimesh',\n extensions: ['.vue'],\n importMode: 'async',\n}\n\n/**\n * Kimesh Router Generator Vite Plugin\n */\nexport function kimeshRouterGenerator(\n options: KimeshRouterPluginOptions = {}\n): Plugin {\n const debug = options.debug ?? false\n\n let config: ResolvedRouterConfig\n let server: ViteDevServer | null = null\n let scanner: RouteScanner\n let routes: RouteNode[] = []\n\n const log = (...args: unknown[]) => {\n if (debug) {\n console.log('[kimesh:router]', ...args)\n }\n }\n\n /**\n * Resolve layer routes - supports both static config and lazy getter\n */\n const resolveLayerRoutes = (): LayerRouteConfig[] => {\n if (options.getLayerRoutes) {\n return options.getLayerRoutes()\n }\n return options.layerRoutes ?? []\n }\n\n return {\n name: 'kimesh:router-generator',\n enforce: 'pre',\n\n configResolved(viteConfig) {\n const root = viteConfig.root\n\n const mergedConfig = {\n ...DEFAULT_CONFIG,\n ...options,\n }\n\n config = {\n ...mergedConfig,\n root,\n routesDirPath: path.resolve(root, mergedConfig.srcDir, mergedConfig.routesDir),\n generatedDirPath: path.resolve(root, mergedConfig.generatedDir),\n }\n\n scanner = new RouteScanner(config)\n\n log('Config resolved:', {\n routesDirPath: config.routesDirPath,\n generatedDirPath: config.generatedDirPath,\n layerCount: resolveLayerRoutes().length,\n })\n },\n\n async buildStart() {\n await generateRoutesOnce()\n },\n\n configureServer(_server) {\n server = _server\n\n // Watch app routes directory\n const watchPaths = [config.routesDirPath]\n\n // Also watch layer routes directories\n const layerRoutes = resolveLayerRoutes()\n for (const layer of layerRoutes) {\n if (fs.existsSync(layer.routesDir)) {\n watchPaths.push(layer.routesDir)\n }\n }\n\n const watcher = watch(watchPaths, {\n ignoreInitial: true,\n ignored: ['**/.kimesh/**', '**/node_modules/**'],\n })\n\n watcher.on('add', handleFileChange)\n watcher.on('unlink', handleFileChange)\n\n log('Watching routes at:', watchPaths)\n },\n\n resolveId(id, importer) {\n // Virtual module for generated routes\n if (id === 'virtual:kimesh-routes' || id === '~kimesh/routes') {\n return VIRTUAL_ROUTES_ID\n }\n\n // Handle ?route query for extracting route definitions\n // Use \\0 prefix to create a virtual module that other plugins won't process\n if (isRouteQuery(id)) {\n const basePath = getBasePath(id)\n const resolvedPath = importer\n ? path.resolve(path.dirname(importer.replace(/\\0/, '')), basePath)\n : basePath\n return VIRTUAL_ROUTE_PREFIX + resolvedPath\n }\n\n return null\n },\n\n load(id) {\n if (id === VIRTUAL_ROUTES_ID) {\n return generateRoutes(routes, config)\n }\n\n // Handle virtual route modules - extract route definition from Vue SFC\n if (id.startsWith(VIRTUAL_ROUTE_PREFIX)) {\n const filePath = id.slice(VIRTUAL_ROUTE_PREFIX.length)\n log('Extracting route definition from:', filePath)\n return extractRouteDefinition(filePath)\n }\n\n return null\n },\n }\n\n async function generateRoutesOnce(): Promise<void> {\n try {\n // Ensure routes directory exists\n if (!fs.existsSync(config.routesDirPath)) {\n log('Routes directory does not exist:', config.routesDirPath)\n routes = []\n }\n\n log('Scanning routes in:', config.routesDirPath)\n\n // Scan app routes\n const scannedNodes = fs.existsSync(config.routesDirPath)\n ? await scanner.scan()\n : []\n log('Scanned app nodes:', scannedNodes.length, scannedNodes.map(n => n.filePath))\n\n // Build app routes\n let appRoutes = buildRouteTree(scannedNodes, config)\n log('Built app routes:', appRoutes.length, appRoutes.map(r => r.routePath))\n\n // Collect and merge layer routes if configured\n const layerRoutes = resolveLayerRoutes()\n if (layerRoutes.length > 0) {\n const layerSources: LayerRouteSource[] = layerRoutes.map(l => ({\n layer: l.layerName,\n routesDir: l.routesDir,\n basePath: l.basePath,\n priority: l.priority,\n }))\n\n const layerResult = await collectLayerRoutes(layerSources, config)\n\n log('Collected layer routes:', layerResult.routes.length)\n\n // Merge layer routes into app routes\n routes = mergeRoutes(appRoutes, layerResult.routes, config)\n } else {\n routes = appRoutes\n }\n\n log('Final merged routes:', routes.length, routes.map(r => r.routePath))\n\n // Generate files\n await writeGeneratedFiles()\n\n console.log(`[kimesh:router] Generated ${routes.length} route(s)`)\n } catch (error) {\n console.error('[kimesh:router] Error generating routes:', error)\n }\n }\n\n async function writeGeneratedFiles(): Promise<void> {\n // Ensure generated directory exists (for routes.gen.ts)\n if (!fs.existsSync(config.generatedDirPath)) {\n fs.mkdirSync(config.generatedDirPath, { recursive: true })\n }\n\n // Write routes.gen.ts to .kimesh/\n const routesCode = generateRoutes(routes, config)\n const routesPath = path.join(config.generatedDirPath, 'routes.gen.ts')\n fs.writeFileSync(routesPath, routesCode, 'utf-8')\n\n // Write typed-routes.d.ts to .kimesh/\n const typesCode = generateRouteTypes(routes)\n const typesPath = path.join(config.generatedDirPath, 'typed-routes.d.ts')\n fs.writeFileSync(typesPath, typesCode, 'utf-8')\n\n // Also write typed-routes.d.ts to each layer's .kimesh/ directory\n // This enables type suggestions when editing layer code\n const layerRoutes = resolveLayerRoutes()\n for (const layer of layerRoutes) {\n // Use layerPath if provided, otherwise fallback to parent of routesDir\n // Resolve symlinks to get the real path for proper .kimesh generation\n let layerRoot = layer.layerPath || path.dirname(layer.routesDir)\n try {\n layerRoot = fs.realpathSync(layerRoot)\n } catch {\n // Ignore if path doesn't exist\n }\n const layerKimeshDir = path.join(layerRoot, '.kimesh')\n \n if (!fs.existsSync(layerKimeshDir)) {\n fs.mkdirSync(layerKimeshDir, { recursive: true })\n }\n \n const layerTypesPath = path.join(layerKimeshDir, 'typed-routes.d.ts')\n fs.writeFileSync(layerTypesPath, typesCode, 'utf-8')\n log('Generated layer types:', { layer: layer.layerName, path: layerTypesPath })\n }\n\n log('Generated files:', { routesPath, typesPath })\n }\n\n async function handleFileChange(filePath: string): Promise<void> {\n log('File changed:', filePath)\n\n await generateRoutesOnce()\n\n // Trigger HMR\n if (server) {\n const routesModule = server.moduleGraph.getModuleById(VIRTUAL_ROUTES_ID)\n if (routesModule) {\n server.moduleGraph.invalidateModule(routesModule)\n }\n\n server.ws.send({\n type: 'full-reload',\n path: '*',\n })\n }\n }\n}\n\n/**\n * Merge app routes with layer routes\n * App routes (priority 0) take precedence over layer routes\n * Layer routes are nested under the host's root layout if one exists\n * If app has a layout route for a path, layer routes become its children\n */\nfunction mergeRoutes(\n appRoutes: RouteNode[],\n layerRoutes: RouteNode[],\n _config: ResolvedRouterConfig\n): RouteNode[] {\n const rootLayout = findRootLayout(appRoutes)\n\n if (rootLayout && rootLayout.children) {\n return mergeWithRootLayout(appRoutes, layerRoutes, rootLayout)\n }\n\n return mergeWithoutRootLayout(appRoutes, layerRoutes)\n}\n\nfunction findRootLayout(routes: RouteNode[]): RouteNode | null {\n return routes.find((r) => r.routePath === '/' && r.type === 'layout') || null\n}\n\nfunction mergeWithRootLayout(\n appRoutes: RouteNode[],\n layerRoutes: RouteNode[],\n rootLayout: RouteNode\n): RouteNode[] {\n const layoutRoutesByPath = buildLayoutRoutesMap(rootLayout.children!)\n\n for (const layerRoute of layerRoutes) {\n const relativePath = normalizeRoutePath(layerRoute.routePath)\n const hostLayoutRoute = layoutRoutesByPath.get(relativePath)\n\n if (hostLayoutRoute) {\n nestLayerUnderHost(layerRoute, hostLayoutRoute)\n } else {\n addLayerAsSibling(layerRoute, relativePath, rootLayout, layoutRoutesByPath)\n }\n }\n\n sortRouteChildren(rootLayout.children!)\n return appRoutes\n}\n\nfunction buildLayoutRoutesMap(children: RouteNode[]): Map<string, RouteNode> {\n const map = new Map<string, RouteNode>()\n\n for (const child of children) {\n if (child.routePath && !child.routePath.includes(':')) {\n const normalizedPath = normalizeRoutePath(child.routePath)\n map.set(normalizedPath, child)\n }\n }\n\n return map\n}\n\nfunction normalizeRoutePath(routePath: string): string {\n return routePath.startsWith('/') ? routePath.slice(1) : routePath\n}\n\nfunction nestLayerUnderHost(layerRoute: RouteNode, hostLayoutRoute: RouteNode): void {\n hostLayoutRoute.children = hostLayoutRoute.children || []\n hostLayoutRoute.type = 'layout'\n\n const layerWrapper: RouteNode = {\n ...layerRoute,\n routePath: '',\n parent: hostLayoutRoute,\n }\n hostLayoutRoute.children.push(layerWrapper)\n}\n\nfunction addLayerAsSibling(\n layerRoute: RouteNode,\n relativePath: string,\n rootLayout: RouteNode,\n layoutRoutesByPath: Map<string, RouteNode>\n): void {\n const nestedRoute: RouteNode = {\n ...layerRoute,\n routePath: relativePath,\n parent: rootLayout,\n }\n rootLayout.children!.push(nestedRoute)\n layoutRoutesByPath.set(relativePath, nestedRoute)\n}\n\nfunction sortRouteChildren(children: RouteNode[]): void {\n children.sort((a, b) => {\n if (a.routePath === '') return -1\n if (b.routePath === '') return 1\n return a.routePath.localeCompare(b.routePath)\n })\n}\n\nfunction mergeWithoutRootLayout(\n appRoutes: RouteNode[],\n layerRoutes: RouteNode[]\n): RouteNode[] {\n const merged: RouteNode[] = [...appRoutes]\n const usedPaths = new Set(appRoutes.map((r) => r.routePath))\n\n for (const layerRoute of layerRoutes) {\n if (!usedPaths.has(layerRoute.routePath)) {\n merged.push(layerRoute)\n usedPaths.add(layerRoute.routePath)\n }\n }\n\n merged.sort((a, b) => a.routePath.localeCompare(b.routePath))\n return merged\n}\n","/**\n * @kimesh/router-generator - Layout Resolver\n *\n * Resolves layout hierarchy using nested wrapping strategy.\n * Host layouts wrap layer layouts (outer → inner).\n */\n\nimport * as path from 'pathe'\nimport { consola } from 'consola'\nimport type { LayerRouteNode } from './layer-collector'\nimport type { ExtendedParsedRoute } from './parser'\n\nconst logger = consola.withTag('kimesh:router:layout')\n\n/**\n * Resolved layout information\n */\nexport interface ResolvedLayout {\n /** Absolute file path */\n filePath: string\n\n /** Layout name (undefined for default) */\n name?: string\n\n /** Route path this layout applies to */\n routePath: string\n\n /** Layer this layout comes from */\n layer: string\n\n /** Layer priority */\n priority: number\n\n /** Source type: 'host' or 'layer' */\n source: 'host' | 'layer'\n\n /** Mount path for layer layouts */\n mountPath?: string\n}\n\n/**\n * Layout chain for a page\n */\nexport interface LayoutChain {\n /** Ordered list of layouts from outermost to innermost */\n layouts: ResolvedLayout[]\n\n /** Final page component */\n page: LayerRouteNode\n}\n\n/**\n * Layout resolver for nested wrapping\n *\n * Key principle: Host layouts WRAP layer layouts (outer → inner)\n * - Host root layout is always outermost\n * - Host path-specific layouts come next\n * - Layer layouts are innermost (closest to page content)\n */\nexport class LayoutResolver {\n private hostLayouts = new Map<string, ResolvedLayout>()\n private layerLayouts = new Map<string, Map<string, ResolvedLayout>>()\n private layerMounts = new Map<string, string>()\n\n /**\n * Build layout chains for all routes\n */\n resolveLayoutChains(\n routes: LayerRouteNode[],\n layerMounts: Map<string, string>\n ): Map<string, LayoutChain> {\n this.layerMounts = layerMounts\n\n // Step 1: Categorize layouts by source\n this.categorizeLayouts(routes)\n\n // Step 2: Build layout chain for each page\n const chains = new Map<string, LayoutChain>()\n const pageRoutes = routes.filter((r) => r.type !== 'layout')\n\n for (const page of pageRoutes) {\n const chain = this.buildLayoutChain(page)\n chains.set(page.finalRoutePath, chain)\n }\n\n logger.debug(`Resolved layout chains for ${chains.size} pages`)\n\n return chains\n }\n\n /**\n * Categorize layouts into host and layer layouts\n */\n private categorizeLayouts(routes: LayerRouteNode[]): void {\n this.hostLayouts.clear()\n this.layerLayouts.clear()\n\n const layoutRoutes = routes.filter((r) => r.type === 'layout')\n\n for (const route of layoutRoutes) {\n const layoutName = this.extractLayoutName(route.filePath)\n\n const layout: ResolvedLayout = {\n filePath: route.fullPath,\n name: layoutName,\n routePath: route.routePath,\n layer: route.layer,\n priority: route.layerPriority,\n source: route.layer === 'app' ? 'host' : 'layer',\n mountPath: route.layerBasePath,\n }\n\n if (route.layer === 'app') {\n // Host layout\n const key = this.makeLayoutKey(route.routePath, layoutName)\n this.hostLayouts.set(key, layout)\n logger.debug(`Host layout: ${key} -> ${route.fullPath}`)\n } else {\n // Layer layout\n if (!this.layerLayouts.has(route.layer)) {\n this.layerLayouts.set(route.layer, new Map())\n }\n\n const key = this.makeLayoutKey(route.routePath, layoutName)\n this.layerLayouts.get(route.layer)!.set(key, layout)\n logger.debug(`Layer layout: ${route.layer}:${key} -> ${route.fullPath}`)\n }\n }\n }\n\n /**\n * Build the complete layout chain for a page\n *\n * Order: Host root → Host path-specific → Layer root → Layer path-specific → Page\n */\n private buildLayoutChain(page: LayerRouteNode): LayoutChain {\n const layouts: ResolvedLayout[] = []\n const pageMeta = (page.parsed as ExtendedParsedRoute).pageMeta\n\n // Check if page explicitly disables layouts\n if (pageMeta?.layout === false) {\n return { layouts: [], page }\n }\n\n // Requested named layout (if any)\n const requestedLayout = pageMeta?.layout\n\n // Step 1: Collect HOST layouts (outer wrappers)\n const hostChain = this.collectHostLayouts(page.finalRoutePath, requestedLayout)\n layouts.push(...hostChain)\n\n // Step 2: Collect LAYER layouts (inner wrappers) if page is from a layer\n if (page.layer !== 'app') {\n const layerChain = this.collectLayerLayouts(\n page.layer,\n page.routePath,\n page.layerBasePath,\n requestedLayout\n )\n layouts.push(...layerChain)\n }\n\n return { layouts, page }\n }\n\n /**\n * Collect host layouts from root to most specific path\n */\n private collectHostLayouts(\n routePath: string,\n requestedLayout?: string\n ): ResolvedLayout[] {\n const layouts: ResolvedLayout[] = []\n const segments = routePath.split('/').filter(Boolean)\n\n // Start with root layout\n const rootLayout =\n this.hostLayouts.get(this.makeLayoutKey('/', requestedLayout)) ||\n this.hostLayouts.get('/')\n\n if (rootLayout) {\n layouts.push(rootLayout)\n }\n\n // Walk down the path, collecting layouts\n let currentPath = ''\n for (const segment of segments) {\n // Skip dynamic segments in path matching\n if (segment.startsWith(':')) continue\n\n currentPath += '/' + segment\n\n const layout =\n this.hostLayouts.get(this.makeLayoutKey(currentPath, requestedLayout)) ||\n this.hostLayouts.get(currentPath)\n\n if (layout && !layouts.includes(layout)) {\n layouts.push(layout)\n }\n }\n\n return layouts\n }\n\n /**\n * Collect layer layouts from layer root to most specific path\n */\n private collectLayerLayouts(\n layerName: string,\n routePath: string,\n mountPath?: string,\n requestedLayout?: string\n ): ResolvedLayout[] {\n const layouts: ResolvedLayout[] = []\n const layerLayoutMap = this.layerLayouts.get(layerName)\n\n if (!layerLayoutMap) return layouts\n\n const segments = routePath.split('/').filter(Boolean)\n\n // Start with layer's root layout\n const rootLayout =\n layerLayoutMap.get(this.makeLayoutKey('/', requestedLayout)) ||\n layerLayoutMap.get('/')\n\n if (rootLayout) {\n layouts.push(rootLayout)\n }\n\n // Walk down the path within the layer\n let currentPath = ''\n for (const segment of segments) {\n // Skip dynamic segments\n if (segment.startsWith(':')) continue\n\n currentPath += '/' + segment\n\n const layout =\n layerLayoutMap.get(this.makeLayoutKey(currentPath, requestedLayout)) ||\n layerLayoutMap.get(currentPath)\n\n if (layout && !layouts.includes(layout)) {\n layouts.push(layout)\n }\n }\n\n return layouts\n }\n\n /**\n * Extract layout name from file path\n * _layout.admin.vue → 'admin'\n * _layout.vue → undefined\n */\n private extractLayoutName(filePath: string): string | undefined {\n const basename = path.basename(filePath, path.extname(filePath))\n\n if (basename.startsWith('_layout.') && basename !== '_layout') {\n return basename.replace('_layout.', '')\n }\n\n return undefined\n }\n\n /**\n * Make a unique key for layout lookup\n */\n private makeLayoutKey(routePath: string, layoutName?: string): string {\n if (layoutName) {\n return `${routePath}:${layoutName}`\n }\n return routePath\n }\n}\n\n/**\n * Generate nested layout component structure for Vue Router\n *\n * This generates the component tree where layouts wrap their children\n */\nexport function generateLayoutStructure(\n chain: LayoutChain\n): { component: string; children?: any[] } | null {\n if (chain.layouts.length === 0) {\n // No layouts, just the page\n return {\n component: chain.page.fullPath,\n }\n }\n\n // Build nested structure from outermost to innermost\n let current: any = {\n component: chain.page.fullPath,\n }\n\n // Wrap in reverse order (innermost layout first)\n for (let i = chain.layouts.length - 1; i >= 0; i--) {\n const layout = chain.layouts[i]\n current = {\n component: layout.filePath,\n children: [current],\n }\n }\n\n return current\n}\n"],"mappings":"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"}
|