path-rush 1.4.1 → 1.6.0
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/{chunk-VBEFTPIV.mjs → chunk-VZP7N76J.mjs} +105 -52
- package/dist/chunk-VZP7N76J.mjs.map +1 -0
- package/dist/core.js +66 -13
- package/dist/core.js.map +1 -1
- package/dist/core.mjs +1 -1
- package/dist/plugin.d.cts +30 -0
- package/dist/plugin.d.ts +30 -0
- package/dist/plugin.js +66 -13
- package/dist/plugin.js.map +1 -1
- package/dist/plugin.mjs +1 -1
- package/dist/react.d.cts +168 -4
- package/dist/react.d.ts +168 -4
- package/dist/react.js +228 -28
- package/dist/react.js.map +1 -1
- package/dist/react.mjs +225 -29
- package/dist/react.mjs.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-VBEFTPIV.mjs.map +0 -1
package/dist/core.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/core.ts","../src/plugin.ts","../src/core/build-generator.ts","../src/core/metadata.ts","../src/core/route-generator.ts","../src/core/scanner.ts","../src/core/utils.ts","../src/core/type-generator.ts","../src/core/hmr-handlers.ts","../src/core/manifest-loader.ts","../src/core/virtual-module.ts"],"sourcesContent":["export type { Options } from './core/types/types'\r\nexport { pathRushRouting } from './plugin'\r\n\r\n","import fs from 'node:fs'\r\nimport path from 'node:path'\r\nimport type { Plugin, UserConfig } from 'vite'\r\nimport { generateSEOFiles, generateTypes } from './core/build-generator'\r\nimport { createHMRHandlers } from './core/hmr-handlers'\r\nimport { loadGeneratedManifest } from './core/manifest-loader'\r\nimport type { Options } from './core/types/types'\r\nimport { generateVirtualModuleCode } from './core/virtual-module'\r\n\r\nexport type { Options } from './core/types/types'\r\n\r\nexport function pathRushRouting(rawOpts: Options = {}): Plugin {\r\n\tconst opts: Required<Options> = {\r\n\t\tpagesDir: rawOpts.pagesDir ?? 'src/pages',\r\n\t\tpageFileName: rawOpts.pageFileName ?? 'page',\r\n\t\tlayoutFileName: rawOpts.layoutFileName ?? 'layout',\r\n\t\textensions: rawOpts.extensions ?? ['tsx'],\r\n\t\tbaseUrl: rawOpts.baseUrl ?? 'http://localhost:5173',\r\n\t\tbasePath: rawOpts.basePath ?? '/',\r\n\t\tdisallowPaths: rawOpts.disallowPaths ?? [],\r\n\t\tgenerateTypes: rawOpts.generateTypes ?? true,\r\n\t\tenableSEO: rawOpts.enableSEO ?? true,\r\n\t}\r\n\r\n\tconst VIRTUAL_ID = 'virtual:routes'\r\n\tconst RESOLVED_VIRTUAL_ID = '\\0' + VIRTUAL_ID\r\n\tlet root = process.cwd()\r\n\tlet resolvedPagesDir = path.resolve(root, opts.pagesDir)\r\n\r\n\tconst plugin: Plugin = {\r\n\t\tname: 'vite-plugin-file-router-mwv',\r\n\t\tenforce: 'pre',\r\n\r\n\t\t// Автоматическая настройка Vite конфигурации\r\n\t\tconfig(userConfig: UserConfig): UserConfig {\r\n\t\t\tconst existingAlias = userConfig.resolve?.alias\r\n\t\t\tconst existingExclude = userConfig.optimizeDeps?.exclude\r\n\r\n\t\t\t// Безопасно мерджим с существующей конфигурацией\r\n\t\t\treturn {\r\n\t\t\t\toptimizeDeps: {\r\n\t\t\t\t\texclude: [\r\n\t\t\t\t\t\t...(Array.isArray(existingExclude) ? existingExclude : []),\r\n\t\t\t\t\t\t'virtual:routes',\r\n\t\t\t\t\t],\r\n\t\t\t\t},\r\n\t\t\t\tresolve: {\r\n\t\t\t\t\talias: {\r\n\t\t\t\t\t\t...(typeof existingAlias === 'object' ? existingAlias : {}),\r\n\t\t\t\t\t\t'virtual:routes': 'virtual:routes',\r\n\t\t\t\t\t},\r\n\t\t\t\t},\r\n\t\t\t}\r\n\t\t},\r\n\r\n\t\tresolveId(id: string) {\r\n\t\t\tif (id === VIRTUAL_ID) return RESOLVED_VIRTUAL_ID\r\n\t\t\treturn null\r\n\t\t},\r\n\r\n\t\tasync load(id: string) {\r\n\t\t\tif (id === RESOLVED_VIRTUAL_ID) {\r\n\t\t\t\t// В production режиме проверяем существование директории pages\r\n\t\t\t\tif (!fs.existsSync(resolvedPagesDir)) {\r\n\t\t\t\t\t// В production пытаемся загрузить сгенерированный манифест\r\n\t\t\t\t\treturn await loadGeneratedManifest(root)\r\n\t\t\t\t}\r\n\r\n\t\t\t\treturn await generateVirtualModuleCode(resolvedPagesDir, opts)\r\n\t\t\t}\r\n\t\t\treturn null\r\n\t\t},\r\n\r\n\t\tasync buildStart() {\r\n\t\t\troot = process.cwd()\r\n\t\t\tresolvedPagesDir = path.resolve(root, opts.pagesDir)\r\n\r\n\t\t\tif (!fs.existsSync(resolvedPagesDir)) {\r\n\t\t\t\tconsole.warn(\r\n\t\t\t\t\t`[vite-plugin-file-router] pagesDir \"${resolvedPagesDir}\" not found.`\r\n\t\t\t\t)\r\n\t\t\t}\r\n\t\t},\r\n\r\n\t\tasync generateBundle() {\r\n\t\t\t// Проверяем существование директории pages\r\n\t\t\tif (!fs.existsSync(resolvedPagesDir)) {\r\n\t\t\t\tconsole.warn(\r\n\t\t\t\t\t`[vite-plugin-file-router] pagesDir \"${resolvedPagesDir}\" not found in production build. Skipping route generation.`\r\n\t\t\t\t)\r\n\t\t\t\treturn\r\n\t\t\t}\r\n\r\n\t\t\t// Генерируем TypeScript типы\r\n\t\t\tif (opts.generateTypes) {\r\n\t\t\t\ttry {\r\n\t\t\t\t\tawait generateTypes(resolvedPagesDir, opts)\r\n\t\t\t\t} catch (error) {\r\n\t\t\t\t\tconsole.warn(\r\n\t\t\t\t\t\t`[vite-plugin-file-router] Failed to generate types: ${error}`\r\n\t\t\t\t\t)\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\t// Генерируем SEO файлы\r\n\t\t\tif (opts.enableSEO) {\r\n\t\t\t\ttry {\r\n\t\t\t\t\tawait generateSEOFiles(resolvedPagesDir, opts)\r\n\t\t\t\t} catch (error) {\r\n\t\t\t\t\tconsole.warn(\r\n\t\t\t\t\t\t`[vite-plugin-file-router] Failed to generate SEO files: ${error}`\r\n\t\t\t\t\t)\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t},\r\n\t}\r\n\r\n\t// Добавляем HMR только если в development режиме\r\n\tif (process.env.NODE_ENV !== 'production') {\r\n\t\tconst { configureServer, handleHotUpdate } = createHMRHandlers(\r\n\t\t\tresolvedPagesDir,\r\n\t\t\tRESOLVED_VIRTUAL_ID,\r\n\t\t\troot\r\n\t\t)\r\n\t\tplugin.configureServer = configureServer\r\n\t\tplugin.handleHotUpdate = handleHotUpdate\r\n\t}\r\n\r\n\treturn plugin\r\n}\r\n","import fs from 'node:fs'\r\nimport path from 'node:path'\r\nimport { extractMetadata, generateRobots, generateSitemap } from './metadata'\r\nimport { createRouteEntry } from './route-generator'\r\nimport { scanPages } from './scanner'\r\nimport { generateMetadataTypes, generateRouteTypes } from './type-generator'\r\nimport type { Options } from './types/types'\r\n\r\nexport async function generateTypes(\r\n\tresolvedPagesDir: string,\r\n\topts: Required<Options>\r\n) {\r\n\tconst pages = await scanPages(resolvedPagesDir, opts)\r\n\tconst routes = pages.map(fp => createRouteEntry(fp, resolvedPagesDir, opts))\r\n\r\n\tconst routeTypes = generateRouteTypes(routes)\r\n\tconst metadataTypes = generateMetadataTypes()\r\n\r\n\t// Создаем директорию для типов\r\n\tconst typesDir = path.join(process.cwd(), 'dist', 'types')\r\n\tif (!fs.existsSync(typesDir)) {\r\n\t\tfs.mkdirSync(typesDir, { recursive: true })\r\n\t}\r\n\r\n\tfs.writeFileSync(path.join(typesDir, 'routes.d.ts'), routeTypes)\r\n\tfs.writeFileSync(path.join(typesDir, 'metadata.d.ts'), metadataTypes)\r\n}\r\n\r\nexport async function generateSEOFiles(\r\n\tresolvedPagesDir: string,\r\n\topts: Required<Options>\r\n) {\r\n\tconst pages = await scanPages(resolvedPagesDir, opts)\r\n\tconst routesWithMetadata = pages\r\n\t\t.map(fp => {\r\n\t\t\tconst entry = createRouteEntry(fp, resolvedPagesDir, opts)\r\n\t\t\tconst metadata = extractMetadata(fp)\r\n\t\t\treturn {\r\n\t\t\t\tpath: entry.path,\r\n\t\t\t\tmetadata: metadata || undefined,\r\n\t\t\t}\r\n\t\t})\r\n\t\t.filter(\r\n\t\t\troute =>\r\n\t\t\t\t!opts.disallowPaths.some(disallow => route.path.startsWith(disallow))\r\n\t\t)\r\n\r\n\t// Генерируем sitemap.xml и robots.txt\r\n\tconst sitemap = generateSitemap(routesWithMetadata, opts.baseUrl)\r\n\tconst robots = generateRobots(opts.baseUrl, opts.disallowPaths)\r\n\r\n\tconst distDir = path.join(process.cwd(), 'dist')\r\n\tif (!fs.existsSync(distDir)) {\r\n\t\tfs.mkdirSync(distDir, { recursive: true })\r\n\t}\r\n\r\n\tfs.writeFileSync(path.join(distDir, 'sitemap.xml'), sitemap)\r\n\tfs.writeFileSync(path.join(distDir, 'robots.txt'), robots)\r\n}\r\n","import fs from 'node:fs'\r\nimport type { PageMetadata } from './types/types'\r\n\r\nexport function extractMetadata(filePath: string): PageMetadata | null {\r\n\ttry {\r\n\t\tconst content = fs.readFileSync(filePath, 'utf-8')\r\n\r\n\t\t// Парсинг JSDoc комментариев\r\n\t\tconst jsdocMetadata = extractJSDocMetadata(content)\r\n\t\tif (jsdocMetadata) {\r\n\t\t\treturn jsdocMetadata\r\n\t\t}\r\n\r\n\t\t// Парсинг экспорта metadata\r\n\t\tconst exportMetadata = extractExportMetadata(content)\r\n\t\tif (exportMetadata) {\r\n\t\t\treturn exportMetadata\r\n\t\t}\r\n\r\n\t\treturn null\r\n\t} catch (error) {\r\n\t\tconsole.warn(\r\n\t\t\t`[vite-plugin-file-router] Failed to extract metadata from ${filePath}:`,\r\n\t\t\terror\r\n\t\t)\r\n\t\treturn null\r\n\t}\r\n}\r\n\r\nfunction extractJSDocMetadata(content: string): PageMetadata | null {\r\n\tconst jsdocMatch = content.match(/\\/\\*\\*([\\s\\S]*?)\\*\\//)\r\n\tif (!jsdocMatch) return null\r\n\r\n\tconst jsdoc = jsdocMatch[1]\r\n\tconst metadata: PageMetadata = {}\r\n\r\n\t// Парсинг JSDoc тегов\r\n\tconst titleMatch = jsdoc.match(/@title\\s+(.+)/)\r\n\tif (titleMatch) metadata.title = titleMatch[1].trim()\r\n\r\n\tconst descMatch = jsdoc.match(/@description\\s+(.+)/)\r\n\tif (descMatch) metadata.description = descMatch[1].trim()\r\n\r\n\tconst keywordsMatch = jsdoc.match(/@keywords\\s+(.+)/)\r\n\tif (keywordsMatch) {\r\n\t\tmetadata.keywords = keywordsMatch[1].split(',').map(k => k.trim())\r\n\t}\r\n\r\n\tconst authorMatch = jsdoc.match(/@author\\s+(.+)/)\r\n\tif (authorMatch) metadata.author = authorMatch[1].trim()\r\n\r\n\tconst changefreqMatch = jsdoc.match(\r\n\t\t/@changefreq\\s+(always|hourly|daily|weekly|monthly|yearly|never)/\r\n\t)\r\n\tif (changefreqMatch) {\r\n\t\tmetadata.changefreq = changefreqMatch[1] as PageMetadata['changefreq']\r\n\t}\r\n\r\n\tconst priorityMatch = jsdoc.match(/@priority\\s+([0-9.]+)/)\r\n\tif (priorityMatch) {\r\n\t\tmetadata.priority = parseFloat(priorityMatch[1])\r\n\t}\r\n\r\n\treturn Object.keys(metadata).length > 0 ? metadata : null\r\n}\r\n\r\nfunction extractExportMetadata(content: string): PageMetadata | null {\r\n\t// Ищем экспорт const metadata = { ... }\r\n\tconst metadataMatch = content.match(\r\n\t\t/export\\s+const\\s+metadata\\s*=\\s*({[\\s\\S]*?});?/\r\n\t)\r\n\tif (!metadataMatch) return null\r\n\r\n\ttry {\r\n\t\t// Безопасное выполнение кода для извлечения объекта\r\n\t\tconst metadataCode = metadataMatch[1]\r\n\t\t// Заменяем возможные импорты и функции на безопасные значения\r\n\t\tconst safeCode = metadataCode\r\n\t\t\t.replace(/import\\s+.*?from\\s+['\"][^'\"]*['\"];?/g, '')\r\n\t\t\t.replace(/require\\s*\\([^)]*\\)/g, '\"\"')\r\n\t\t\t.replace(/process\\.env\\.[A-Z_]+/g, '\"\"')\r\n\r\n\t\t// Создаем функцию для безопасного выполнения\r\n\t\tconst func = new Function(`return ${safeCode}`)\r\n\t\treturn func()\r\n\t} catch (error) {\r\n\t\tconsole.warn(\r\n\t\t\t`[vite-plugin-file-router] Failed to parse metadata export:`,\r\n\t\t\terror\r\n\t\t)\r\n\t\treturn null\r\n\t}\r\n}\r\n\r\nexport function generateSitemap(\r\n\troutes: Array<{ path: string; metadata?: PageMetadata }>,\r\n\tbaseUrl: string\r\n): string {\r\n\tconst urls = routes\r\n\t\t.map(route => {\r\n\t\t\tconst lastmod = new Date().toISOString()\r\n\t\t\tconst changefreq = route.metadata?.changefreq || 'monthly'\r\n\t\t\tconst priority = route.metadata?.priority || 0.8\r\n\r\n\t\t\treturn ` <url>\r\n <loc>${baseUrl}${route.path}</loc>\r\n <lastmod>${lastmod}</lastmod>\r\n <changefreq>${changefreq}</changefreq>\r\n <priority>${priority}</priority>\r\n </url>`\r\n\t\t})\r\n\t\t.join('\\n')\r\n\r\n\treturn `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n<urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">\r\n${urls}\r\n</urlset>`\r\n}\r\n\r\nexport function generateRobots(\r\n\tbaseUrl: string,\r\n\tdisallowPaths: string[] = []\r\n): string {\r\n\tconst disallowRules = disallowPaths\r\n\t\t.map(path => `Disallow: ${path}`)\r\n\t\t.join('\\n')\r\n\r\n\treturn `User-agent: *\r\nAllow: /\r\n${disallowRules ? `\\n${disallowRules}` : ''}\r\n\r\nSitemap: ${baseUrl}/sitemap.xml`\r\n}\r\n","import path from 'node:path'\r\nimport { collectLayouts } from './scanner'\r\nimport type { Options, RouteEntry } from './types/types'\r\nimport { detectExportType, slash } from './utils'\r\n\r\nexport function segmentToRoute(seg: string): string {\r\n\tif (/^\\[\\.{3}.+\\]$/.test(seg)) {\r\n\t\tconst name = seg.slice(4, -1)\r\n\t\treturn `:${name}(.*)`\r\n\t}\r\n\tif (/^\\[.+\\]$/.test(seg)) {\r\n\t\tconst name = seg.slice(1, -1)\r\n\t\treturn `:${name}`\r\n\t}\r\n\treturn seg\r\n}\r\n\r\nexport function filePathToRoute(\r\n\tfilePath: string,\r\n\tresolvedPagesDir: string\r\n): string {\r\n\tconst rel = slash(path.relative(resolvedPagesDir, filePath))\r\n\tconst dir = path.dirname(rel)\r\n\tconst parts = dir === '.' ? [] : dir.split('/').filter(Boolean)\r\n\t// 1. Выбрасываем группы маршрутов (auth), (shop) …\r\n\t// 2. Добавляем фильтр папок, начинающихся с _\r\n\tconst filteredParts = parts.filter(\r\n\t\tpart =>\r\n\t\t\t(!part.startsWith('(') || !part.endsWith(')')) && !part.startsWith('_')\r\n\t)\r\n\tconst segments = filteredParts.map(segmentToRoute)\r\n\tconst route = '/' + segments.join('/')\r\n\treturn route === '/' ? '/' : route.replace(/\\/+/g, '/')\r\n}\r\n\r\nexport function createRouteEntry(\r\n\tfilePath: string,\r\n\tresolvedPagesDir: string,\r\n\topts: Required<Options>\r\n): RouteEntry {\r\n\tconst route = filePathToRoute(filePath, resolvedPagesDir)\r\n\tconst id = slash(path.relative(resolvedPagesDir, filePath))\r\n\t\t.replace(/\\//g, '_')\r\n\t\t.replace(/\\.[^.]+$/, '')\r\n\tconst exportType = detectExportType(filePath)\r\n\tconst loader = `() => import(${JSON.stringify(slash(filePath))})`\r\n\tconst layouts = collectLayouts(filePath, resolvedPagesDir, opts).map(\r\n\t\tlp => `() => import(${JSON.stringify(slash(lp))})`\r\n\t)\r\n\r\n\treturn {\r\n\t\tid,\r\n\t\tpath: route,\r\n\t\tfilePath: slash(filePath),\r\n\t\tloader,\r\n\t\texportType,\r\n\t\tlayouts,\r\n\t}\r\n}\r\n","import fg from 'fast-glob'\r\nimport fs from 'node:fs'\r\nimport path from 'node:path'\r\nimport type { Options } from './types/types'\r\nimport { slash } from './utils'\r\n\r\nexport async function scanPages(\r\n\tresolvedPagesDir: string,\r\n\topts: Required<Options>\r\n): Promise<string[]> {\r\n\t// pattern like /abs/path/**/page.tsx\r\n\tconst exts = opts.extensions.join('|')\r\n\tconst pattern = `${slash(resolvedPagesDir)}/**/${\r\n\t\topts.pageFileName\r\n\t}.+(${exts})`\r\n\tconst files = await fg(pattern, { dot: true })\r\n\t// return absolute normalized paths\r\n\treturn files.map((f: string) => path.resolve(f))\r\n}\r\n\r\nexport function collectLayouts(\r\n\tfilePath: string,\r\n\tresolvedPagesDir: string,\r\n\topts: Required<Options>\r\n): string[] {\r\n\tconst rel = slash(path.relative(resolvedPagesDir, filePath))\r\n\tconst dir = path.dirname(rel)\r\n\tconst parts = dir === '.' ? [] : dir.split('/').filter(Boolean)\r\n\r\n\tconst layouts: string[] = []\r\n\t// for each level from 0..parts.length include layout if exists\r\n\t// НЕ фильтруем группы маршрутов при поиске layout файлов\r\n\tfor (let i = 0; i <= parts.length; i++) {\r\n\t\tconst p = parts.slice(0, i).join('/')\r\n\t\tfor (const ext of opts.extensions) {\r\n\t\t\tconst candidate = path.resolve(\r\n\t\t\t\tresolvedPagesDir,\r\n\t\t\t\tp || '',\r\n\t\t\t\t`${opts.layoutFileName}.${ext}`\r\n\t\t\t)\r\n\t\t\tif (fs.existsSync(candidate)) {\r\n\t\t\t\tlayouts.push(candidate)\r\n\t\t\t\tbreak\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\treturn layouts\r\n}\r\n","import fs from 'node:fs'\r\nimport type { ExportType } from './types/types'\r\n\r\nexport const slash = (p: string) => p.replace(/\\\\/g, '/')\r\n\r\nexport function detectExportType(filePath: string): ExportType {\r\n\ttry {\r\n\t\tconst content = fs.readFileSync(filePath, 'utf-8')\r\n\r\n\t\t// Проверяем наличие default экспорта\r\n\t\tconst hasDefaultExport = /export\\s+default\\s+/.test(content)\r\n\r\n\t\t// Проверяем наличие любого именованного экспорта (функция, константа или класс)\r\n\t\tconst hasNamedExport = /export\\s+(const|function|class)\\s+\\w+\\s*[=(]/.test(\r\n\t\t\tcontent\r\n\t\t)\r\n\r\n\t\tif (hasDefaultExport) {\r\n\t\t\treturn 'default'\r\n\t\t} else if (hasNamedExport) {\r\n\t\t\treturn 'named'\r\n\t\t}\r\n\r\n\t\t// По умолчанию предполагаем default экспорт для обратной совместимости\r\n\t\treturn 'default'\r\n\t} catch (error) {\r\n\t\t// В случае ошибки чтения файла, предполагаем default экспорт\r\n\t\tconsole.warn(\r\n\t\t\t`[vite-plugin-file-router] Failed to read file ${filePath}:`,\r\n\t\t\terror\r\n\t\t)\r\n\t\treturn 'default'\r\n\t}\r\n}\r\n","import type { RouteEntry } from './types/types'\r\n\r\nexport function generateRouteTypes(routes: RouteEntry[]): string {\r\n\tconst routePaths = routes.map(route => `'${route.path}'`).join(' | ')\r\n\r\n\t// Извлекаем параметры из динамических маршрутов\r\n\tconst routeParams: Record<string, Record<string, string>> = {}\r\n\troutes.forEach(route => {\r\n\t\tconst params: Record<string, string> = {}\r\n\r\n\t\t// Парсим [id] параметры\r\n\t\tconst idMatches = route.path.match(/\\[([^\\]]+)\\]/g)\r\n\t\tif (idMatches) {\r\n\t\t\tidMatches.forEach(match => {\r\n\t\t\t\tconst paramName = match.slice(1, -1)\r\n\t\t\t\tif (paramName.startsWith('...')) {\r\n\t\t\t\t\t// Catch-all параметр\r\n\t\t\t\t\tparams[paramName.slice(3)] = 'string[]'\r\n\t\t\t\t} else {\r\n\t\t\t\t\tparams[paramName] = 'string'\r\n\t\t\t\t}\r\n\t\t\t})\r\n\t\t}\r\n\r\n\t\tif (Object.keys(params).length > 0) {\r\n\t\t\trouteParams[route.path] = params\r\n\t\t}\r\n\t})\r\n\r\n\tconst routeParamsType =\r\n\t\tObject.keys(routeParams).length > 0\r\n\t\t\t? `export type RouteParams = {\r\n${Object.entries(routeParams)\r\n\t.map(([path, params]) => {\r\n\t\tconst paramEntries = Object.entries(params)\r\n\t\t\t.map(([key, type]) => `${key}: ${type}`)\r\n\t\t\t.join(', ')\r\n\t\treturn ` '${path}': { ${paramEntries} }`\r\n\t})\r\n\t.join('\\n')}\r\n}`\r\n\t\t\t: 'export type RouteParams = Record<string, never>'\r\n\r\n\treturn `// Автогенерированные типы маршрутов\r\nexport type RoutePath = ${routePaths || 'never'}\r\n\r\n${routeParamsType}\r\n\r\nexport type PageProps<T extends RoutePath = RoutePath> = {\r\n params: RouteParams[T]\r\n searchParams?: Record<string, string>\r\n}\r\n\r\nexport interface LayoutProps {\r\n children: React.ReactNode\r\n}\r\n\r\nexport interface RouteInfo {\r\n id: string\r\n path: string\r\n filePath: string\r\n exportType: 'default' | 'named'\r\n layouts: string[]\r\n}\r\n\r\n// Утилиты для навигации\r\nexport function navigate<T extends RoutePath>(\r\n path: T, \r\n params?: RouteParams[T]\r\n): void {\r\n // Реализация навигации\r\n window.location.href = path\r\n}\r\n\r\nexport function useParams<T extends RoutePath>(): RouteParams[T] {\r\n // Реализация хука для получения параметров\r\n return {} as RouteParams[T]\r\n}\r\n`\r\n}\r\n\r\nexport function generateMetadataTypes(): string {\r\n\treturn `// Типы для метаданных страниц\r\nexport interface PageMetadata {\r\n title?: string\r\n description?: string\r\n keywords?: string[]\r\n author?: string\r\n changefreq?: 'always' | 'hourly' | 'daily' | 'weekly' | 'monthly' | 'yearly' | 'never'\r\n priority?: number\r\n}\r\n\r\nexport interface SEOConfig {\r\n baseUrl: string\r\n defaultTitle?: string\r\n defaultDescription?: string\r\n disallowPaths?: string[]\r\n}\r\n`\r\n}\r\n","import fs from 'node:fs'\r\n\r\nexport function createHMRHandlers(\r\n\tresolvedPagesDir: string,\r\n\tresolvedVirtualId: string,\r\n\troot: string\r\n) {\r\n\tconst configureServer = (srv: any) => {\r\n\t\tconst invalidateVirtual = async () => {\r\n\t\t\tconst mod = srv.moduleGraph?.getModuleById?.(resolvedVirtualId)\r\n\t\t\tif (mod) {\r\n\t\t\t\tsrv.moduleGraph?.invalidateModule?.(mod)\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tconst watchPath = fs.existsSync(resolvedPagesDir) ? resolvedPagesDir : root\r\n\t\tsrv.watcher?.add?.(watchPath)\r\n\r\n\t\tsrv.watcher?.on?.('add', (p: string) => {\r\n\t\t\tif (p.startsWith(resolvedPagesDir)) invalidateVirtual()\r\n\t\t})\r\n\t\tsrv.watcher?.on?.('unlink', (p: string) => {\r\n\t\t\tif (p.startsWith(resolvedPagesDir)) invalidateVirtual()\r\n\t\t})\r\n\t}\r\n\r\n\tconst handleHotUpdate = (ctx: any) => {\r\n\t\tconst f = ctx.file\r\n\t\tif (!f?.startsWith(resolvedPagesDir)) return\r\n\r\n\t\tconst mod = ctx.server.moduleGraph?.getModuleById?.(resolvedVirtualId)\r\n\t\tif (mod) {\r\n\t\t\tctx.server.moduleGraph?.invalidateModule?.(mod)\r\n\t\t\treturn [mod]\r\n\t\t}\r\n\t}\r\n\r\n\treturn { configureServer, handleHotUpdate }\r\n}\r\n","import fs from 'node:fs'\r\nimport path from 'node:path'\r\n\r\nexport async function loadGeneratedManifest(root: string): Promise<string> {\r\n\tconst manifestPath = path.join(root, 'dist', 'routes-manifest.js')\r\n\tif (fs.existsSync(manifestPath)) {\r\n\t\ttry {\r\n\t\t\tconst manifestContent = fs.readFileSync(manifestPath, 'utf-8')\r\n\t\t\tconst manifestRegex = /export const manifest = \\[.*?\\];/s\r\n\t\t\tconst manifestMatch = manifestRegex.exec(manifestContent)\r\n\t\t\tconst basePathRegex = /export const basePath = ['\"](.*?)['\"];/\r\n\t\t\tconst basePathMatch = basePathRegex.exec(manifestContent)\r\n\t\t\tconst basePath = basePathMatch ? basePathMatch[1] : '/'\r\n\t\t\t\r\n\t\t\tif (manifestMatch) {\r\n\t\t\t\treturn `// virtual routes (production mode - using generated manifest)\r\n${manifestMatch[0]}\r\nexport const basePath = ${JSON.stringify(basePath)};\r\nexport default manifest;\r\n`\r\n\t\t\t}\r\n\t\t} catch (error) {\r\n\t\t\tconsole.warn(\r\n\t\t\t\t'[vite-plugin-file-router] Failed to load generated manifest:',\r\n\t\t\t\terror\r\n\t\t\t)\r\n\t\t}\r\n\t}\r\n\r\n\t// Fallback - пустой манифест\r\n\treturn `// virtual routes (production mode - empty manifest)\r\nexport const manifest = [];\r\nexport const basePath = '/';\r\nexport default manifest;\r\n`\r\n}\r\n","import { createRouteEntry } from './route-generator'\r\nimport { scanPages } from './scanner'\r\nimport type { Options } from './types/types'\r\n\r\nexport async function generateVirtualModuleCode(\r\n\tresolvedPagesDir: string,\r\n\topts: Required<Options>\r\n): Promise<string> {\r\n\tconst pages = await scanPages(resolvedPagesDir, opts)\r\n\tconst entries = pages.map(fp => {\r\n\t\tconst entry = createRouteEntry(fp, resolvedPagesDir, opts)\r\n\t\treturn `{\r\n id: ${JSON.stringify(entry.id)},\r\n path: ${JSON.stringify(entry.path)},\r\n filePath: ${JSON.stringify(entry.filePath)},\r\n loader: ${entry.loader},\r\n exportType: ${JSON.stringify(entry.exportType)},\r\n layouts: [${entry.layouts.join(',')}]\r\n }`\r\n\t})\r\n\r\n\treturn `// Auto-generated routes manifest\r\nconst manifest = [${entries.join(',\\n')}];\r\n\r\nexport const basePath = ${JSON.stringify(opts.basePath ?? '/')};\r\n\r\nexport { manifest };\r\nexport default manifest;\r\n`\r\n}\r\n"],"mappings":"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","names":["import_node_fs","import_node_path","import_node_fs","import_node_path","fs","path","import_node_path","import_node_fs","import_node_fs","fs","fg","path","fs","path","path","path","fs","import_node_fs","fs","import_node_fs","import_node_path","path","fs","path","fs"]}
|
|
1
|
+
{"version":3,"sources":["../src/core.ts","../src/plugin.ts","../src/core/build-generator.ts","../src/core/metadata.ts","../src/core/route-generator.ts","../src/core/scanner.ts","../src/core/utils.ts","../src/core/type-generator.ts","../src/core/hmr-handlers.ts","../src/core/manifest-loader.ts","../src/core/virtual-module.ts"],"sourcesContent":["export type { Options } from './core/types/types'\r\nexport { pathRushRouting } from './plugin'\r\n\r\n","import fs from 'node:fs'\r\nimport path from 'node:path'\r\nimport type { Plugin, UserConfig } from 'vite'\r\nimport { generateSEOFiles, generateTypes } from './core/build-generator'\r\nimport { createHMRHandlers } from './core/hmr-handlers'\r\nimport { loadGeneratedManifest } from './core/manifest-loader'\r\nimport type { Options } from './core/types/types'\r\nimport { generateVirtualModuleCode } from './core/virtual-module'\r\n\r\nexport type { Options } from './core/types/types'\r\n\r\nexport function pathRushRouting(rawOpts: Options = {}): Plugin {\r\n\tconst opts: Required<Options> = {\r\n\t\tpagesDir: rawOpts.pagesDir ?? 'src/pages',\r\n\t\tpageFileName: rawOpts.pageFileName ?? 'page',\r\n\t\tlayoutFileName: rawOpts.layoutFileName ?? 'layout',\r\n\t\tloadingFileName: rawOpts.loadingFileName ?? 'loading',\r\n\t\tnotFoundFileName: rawOpts.notFoundFileName ?? 'not-found',\r\n\t\terrorFileName: rawOpts.errorFileName ?? 'error',\r\n\t\textensions: rawOpts.extensions ?? ['tsx'],\r\n\t\tbaseUrl: rawOpts.baseUrl ?? 'http://localhost:5173',\r\n\t\tbasePath: rawOpts.basePath ?? '/',\r\n\t\tdisallowPaths: rawOpts.disallowPaths ?? [],\r\n\t\tgenerateTypes: rawOpts.generateTypes ?? true,\r\n\t\tenableSEO: rawOpts.enableSEO ?? true,\r\n\t}\r\n\r\n\tconst VIRTUAL_ID = 'virtual:routes'\r\n\tconst RESOLVED_VIRTUAL_ID = '\\0' + VIRTUAL_ID\r\n\tlet root = process.cwd()\r\n\tlet resolvedPagesDir = path.resolve(root, opts.pagesDir)\r\n\r\n\tconst plugin: Plugin = {\r\n\t\tname: 'vite-plugin-file-router-mwv',\r\n\t\tenforce: 'pre',\r\n\r\n\t\t// Автоматическая настройка Vite конфигурации\r\n\t\tconfig(userConfig: UserConfig): UserConfig {\r\n\t\t\tconst existingAlias = userConfig.resolve?.alias\r\n\t\t\tconst existingExclude = userConfig.optimizeDeps?.exclude\r\n\r\n\t\t\t// Безопасно мерджим с существующей конфигурацией\r\n\t\t\treturn {\r\n\t\t\t\toptimizeDeps: {\r\n\t\t\t\t\texclude: [\r\n\t\t\t\t\t\t...(Array.isArray(existingExclude) ? existingExclude : []),\r\n\t\t\t\t\t\t'virtual:routes',\r\n\t\t\t\t\t],\r\n\t\t\t\t},\r\n\t\t\t\tresolve: {\r\n\t\t\t\t\talias: {\r\n\t\t\t\t\t\t...(typeof existingAlias === 'object' ? existingAlias : {}),\r\n\t\t\t\t\t\t'virtual:routes': 'virtual:routes',\r\n\t\t\t\t\t},\r\n\t\t\t\t},\r\n\t\t\t}\r\n\t\t},\r\n\r\n\t\tresolveId(id: string) {\r\n\t\t\tif (id === VIRTUAL_ID) return RESOLVED_VIRTUAL_ID\r\n\t\t\treturn null\r\n\t\t},\r\n\r\n\t\tasync load(id: string) {\r\n\t\t\tif (id === RESOLVED_VIRTUAL_ID) {\r\n\t\t\t\t// В production режиме проверяем существование директории pages\r\n\t\t\t\tif (!fs.existsSync(resolvedPagesDir)) {\r\n\t\t\t\t\t// В production пытаемся загрузить сгенерированный манифест\r\n\t\t\t\t\treturn await loadGeneratedManifest(root)\r\n\t\t\t\t}\r\n\r\n\t\t\t\treturn await generateVirtualModuleCode(resolvedPagesDir, opts)\r\n\t\t\t}\r\n\t\t\treturn null\r\n\t\t},\r\n\r\n\t\tasync buildStart() {\r\n\t\t\troot = process.cwd()\r\n\t\t\tresolvedPagesDir = path.resolve(root, opts.pagesDir)\r\n\r\n\t\t\tif (!fs.existsSync(resolvedPagesDir)) {\r\n\t\t\t\tconsole.warn(\r\n\t\t\t\t\t`[vite-plugin-file-router] pagesDir \"${resolvedPagesDir}\" not found.`\r\n\t\t\t\t)\r\n\t\t\t}\r\n\t\t},\r\n\r\n\t\tasync generateBundle() {\r\n\t\t\t// Проверяем существование директории pages\r\n\t\t\tif (!fs.existsSync(resolvedPagesDir)) {\r\n\t\t\t\tconsole.warn(\r\n\t\t\t\t\t`[vite-plugin-file-router] pagesDir \"${resolvedPagesDir}\" not found in production build. Skipping route generation.`\r\n\t\t\t\t)\r\n\t\t\t\treturn\r\n\t\t\t}\r\n\r\n\t\t\t// Генерируем TypeScript типы\r\n\t\t\tif (opts.generateTypes) {\r\n\t\t\t\ttry {\r\n\t\t\t\t\tawait generateTypes(resolvedPagesDir, opts)\r\n\t\t\t\t} catch (error) {\r\n\t\t\t\t\tconsole.warn(\r\n\t\t\t\t\t\t`[vite-plugin-file-router] Failed to generate types: ${error}`\r\n\t\t\t\t\t)\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\t// Генерируем SEO файлы\r\n\t\t\tif (opts.enableSEO) {\r\n\t\t\t\ttry {\r\n\t\t\t\t\tawait generateSEOFiles(resolvedPagesDir, opts)\r\n\t\t\t\t} catch (error) {\r\n\t\t\t\t\tconsole.warn(\r\n\t\t\t\t\t\t`[vite-plugin-file-router] Failed to generate SEO files: ${error}`\r\n\t\t\t\t\t)\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t},\r\n\t}\r\n\r\n\t// Добавляем HMR только если в development режиме\r\n\tif (process.env.NODE_ENV !== 'production') {\r\n\t\tconst { configureServer, handleHotUpdate } = createHMRHandlers(\r\n\t\t\tresolvedPagesDir,\r\n\t\t\tRESOLVED_VIRTUAL_ID,\r\n\t\t\troot\r\n\t\t)\r\n\t\tplugin.configureServer = configureServer\r\n\t\tplugin.handleHotUpdate = handleHotUpdate\r\n\t}\r\n\r\n\treturn plugin\r\n}\r\n","import fs from 'node:fs'\r\nimport path from 'node:path'\r\nimport { extractMetadata, generateRobots, generateSitemap } from './metadata'\r\nimport { createRouteEntry } from './route-generator'\r\nimport { scanPages } from './scanner'\r\nimport { generateMetadataTypes, generateRouteTypes } from './type-generator'\r\nimport type { Options } from './types/types'\r\n\r\nexport async function generateTypes(\r\n\tresolvedPagesDir: string,\r\n\topts: Required<Options>\r\n) {\r\n\tconst pages = await scanPages(resolvedPagesDir, opts)\r\n\tconst routes = pages.map(fp => createRouteEntry(fp, resolvedPagesDir, opts))\r\n\r\n\tconst routeTypes = generateRouteTypes(routes)\r\n\tconst metadataTypes = generateMetadataTypes()\r\n\r\n\t// Создаем директорию для типов\r\n\tconst typesDir = path.join(process.cwd(), 'dist', 'types')\r\n\tif (!fs.existsSync(typesDir)) {\r\n\t\tfs.mkdirSync(typesDir, { recursive: true })\r\n\t}\r\n\r\n\tfs.writeFileSync(path.join(typesDir, 'routes.d.ts'), routeTypes)\r\n\tfs.writeFileSync(path.join(typesDir, 'metadata.d.ts'), metadataTypes)\r\n}\r\n\r\nexport async function generateSEOFiles(\r\n\tresolvedPagesDir: string,\r\n\topts: Required<Options>\r\n) {\r\n\tconst pages = await scanPages(resolvedPagesDir, opts)\r\n\tconst routesWithMetadata = pages\r\n\t\t.map(fp => {\r\n\t\t\tconst entry = createRouteEntry(fp, resolvedPagesDir, opts)\r\n\t\t\tconst metadata = extractMetadata(fp)\r\n\t\t\treturn {\r\n\t\t\t\tpath: entry.path,\r\n\t\t\t\tmetadata: metadata || undefined,\r\n\t\t\t}\r\n\t\t})\r\n\t\t.filter(\r\n\t\t\troute =>\r\n\t\t\t\t!opts.disallowPaths.some(disallow => route.path.startsWith(disallow))\r\n\t\t)\r\n\r\n\t// Генерируем sitemap.xml и robots.txt\r\n\tconst sitemap = generateSitemap(routesWithMetadata, opts.baseUrl)\r\n\tconst robots = generateRobots(opts.baseUrl, opts.disallowPaths)\r\n\r\n\tconst distDir = path.join(process.cwd(), 'dist')\r\n\tif (!fs.existsSync(distDir)) {\r\n\t\tfs.mkdirSync(distDir, { recursive: true })\r\n\t}\r\n\r\n\tfs.writeFileSync(path.join(distDir, 'sitemap.xml'), sitemap)\r\n\tfs.writeFileSync(path.join(distDir, 'robots.txt'), robots)\r\n}\r\n","import fs from 'node:fs'\r\nimport type { PageMetadata } from './types/types'\r\n\r\nexport function extractMetadata(filePath: string): PageMetadata | null {\r\n\ttry {\r\n\t\tconst content = fs.readFileSync(filePath, 'utf-8')\r\n\r\n\t\t// Парсинг JSDoc комментариев\r\n\t\tconst jsdocMetadata = extractJSDocMetadata(content)\r\n\t\tif (jsdocMetadata) {\r\n\t\t\treturn jsdocMetadata\r\n\t\t}\r\n\r\n\t\t// Парсинг экспорта metadata\r\n\t\tconst exportMetadata = extractExportMetadata(content)\r\n\t\tif (exportMetadata) {\r\n\t\t\treturn exportMetadata\r\n\t\t}\r\n\r\n\t\treturn null\r\n\t} catch (error) {\r\n\t\tconsole.warn(\r\n\t\t\t`[vite-plugin-file-router] Failed to extract metadata from ${filePath}:`,\r\n\t\t\terror\r\n\t\t)\r\n\t\treturn null\r\n\t}\r\n}\r\n\r\nfunction extractJSDocMetadata(content: string): PageMetadata | null {\r\n\tconst jsdocMatch = content.match(/\\/\\*\\*([\\s\\S]*?)\\*\\//)\r\n\tif (!jsdocMatch) return null\r\n\r\n\tconst jsdoc = jsdocMatch[1]\r\n\tconst metadata: PageMetadata = {}\r\n\r\n\t// Парсинг JSDoc тегов\r\n\tconst titleMatch = jsdoc.match(/@title\\s+(.+)/)\r\n\tif (titleMatch) metadata.title = titleMatch[1].trim()\r\n\r\n\tconst descMatch = jsdoc.match(/@description\\s+(.+)/)\r\n\tif (descMatch) metadata.description = descMatch[1].trim()\r\n\r\n\tconst keywordsMatch = jsdoc.match(/@keywords\\s+(.+)/)\r\n\tif (keywordsMatch) {\r\n\t\tmetadata.keywords = keywordsMatch[1].split(',').map(k => k.trim())\r\n\t}\r\n\r\n\tconst authorMatch = jsdoc.match(/@author\\s+(.+)/)\r\n\tif (authorMatch) metadata.author = authorMatch[1].trim()\r\n\r\n\tconst changefreqMatch = jsdoc.match(\r\n\t\t/@changefreq\\s+(always|hourly|daily|weekly|monthly|yearly|never)/\r\n\t)\r\n\tif (changefreqMatch) {\r\n\t\tmetadata.changefreq = changefreqMatch[1] as PageMetadata['changefreq']\r\n\t}\r\n\r\n\tconst priorityMatch = jsdoc.match(/@priority\\s+([0-9.]+)/)\r\n\tif (priorityMatch) {\r\n\t\tmetadata.priority = parseFloat(priorityMatch[1])\r\n\t}\r\n\r\n\treturn Object.keys(metadata).length > 0 ? metadata : null\r\n}\r\n\r\nfunction extractExportMetadata(content: string): PageMetadata | null {\r\n\t// Ищем экспорт const metadata = { ... }\r\n\tconst metadataMatch = content.match(\r\n\t\t/export\\s+const\\s+metadata\\s*=\\s*({[\\s\\S]*?});?/\r\n\t)\r\n\tif (!metadataMatch) return null\r\n\r\n\ttry {\r\n\t\t// Безопасное выполнение кода для извлечения объекта\r\n\t\tconst metadataCode = metadataMatch[1]\r\n\t\t// Заменяем возможные импорты и функции на безопасные значения\r\n\t\tconst safeCode = metadataCode\r\n\t\t\t.replace(/import\\s+.*?from\\s+['\"][^'\"]*['\"];?/g, '')\r\n\t\t\t.replace(/require\\s*\\([^)]*\\)/g, '\"\"')\r\n\t\t\t.replace(/process\\.env\\.[A-Z_]+/g, '\"\"')\r\n\r\n\t\t// Создаем функцию для безопасного выполнения\r\n\t\tconst func = new Function(`return ${safeCode}`)\r\n\t\treturn func()\r\n\t} catch (error) {\r\n\t\tconsole.warn(\r\n\t\t\t`[vite-plugin-file-router] Failed to parse metadata export:`,\r\n\t\t\terror\r\n\t\t)\r\n\t\treturn null\r\n\t}\r\n}\r\n\r\nexport function generateSitemap(\r\n\troutes: Array<{ path: string; metadata?: PageMetadata }>,\r\n\tbaseUrl: string\r\n): string {\r\n\tconst urls = routes\r\n\t\t.map(route => {\r\n\t\t\tconst lastmod = new Date().toISOString()\r\n\t\t\tconst changefreq = route.metadata?.changefreq || 'monthly'\r\n\t\t\tconst priority = route.metadata?.priority || 0.8\r\n\r\n\t\t\treturn ` <url>\r\n <loc>${baseUrl}${route.path}</loc>\r\n <lastmod>${lastmod}</lastmod>\r\n <changefreq>${changefreq}</changefreq>\r\n <priority>${priority}</priority>\r\n </url>`\r\n\t\t})\r\n\t\t.join('\\n')\r\n\r\n\treturn `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n<urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">\r\n${urls}\r\n</urlset>`\r\n}\r\n\r\nexport function generateRobots(\r\n\tbaseUrl: string,\r\n\tdisallowPaths: string[] = []\r\n): string {\r\n\tconst disallowRules = disallowPaths\r\n\t\t.map(path => `Disallow: ${path}`)\r\n\t\t.join('\\n')\r\n\r\n\treturn `User-agent: *\r\nAllow: /\r\n${disallowRules ? `\\n${disallowRules}` : ''}\r\n\r\nSitemap: ${baseUrl}/sitemap.xml`\r\n}\r\n","import path from 'node:path'\r\nimport { collectLayouts, findSpecialFile } from './scanner'\r\nimport type { Options, RouteEntry } from './types/types'\r\nimport { detectExportType, slash } from './utils'\r\n\r\nexport function segmentToRoute(seg: string): string {\r\n\tif (/^\\[\\.{3}.+\\]$/.test(seg)) {\r\n\t\tconst name = seg.slice(4, -1)\r\n\t\treturn `:${name}(.*)`\r\n\t}\r\n\tif (/^\\[.+\\]$/.test(seg)) {\r\n\t\tconst name = seg.slice(1, -1)\r\n\t\treturn `:${name}`\r\n\t}\r\n\treturn seg\r\n}\r\n\r\nexport function filePathToRoute(\r\n\tfilePath: string,\r\n\tresolvedPagesDir: string\r\n): string {\r\n\tconst rel = slash(path.relative(resolvedPagesDir, filePath))\r\n\tconst dir = path.dirname(rel)\r\n\tconst parts = dir === '.' ? [] : dir.split('/').filter(Boolean)\r\n\t// 1. Выбрасываем группы маршрутов (auth), (shop) …\r\n\t// 2. Добавляем фильтр папок, начинающихся с _\r\n\tconst filteredParts = parts.filter(\r\n\t\tpart =>\r\n\t\t\t(!part.startsWith('(') || !part.endsWith(')')) && !part.startsWith('_')\r\n\t)\r\n\tconst segments = filteredParts.map(segmentToRoute)\r\n\tconst route = '/' + segments.join('/')\r\n\treturn route === '/' ? '/' : route.replace(/\\/+/g, '/')\r\n}\r\n\r\nexport function createRouteEntry(\r\n\tfilePath: string,\r\n\tresolvedPagesDir: string,\r\n\topts: Required<Options>\r\n): RouteEntry {\r\n\tconst route = filePathToRoute(filePath, resolvedPagesDir)\r\n\tconst id = slash(path.relative(resolvedPagesDir, filePath))\r\n\t\t.replace(/\\//g, '_')\r\n\t\t.replace(/\\.[^.]+$/, '')\r\n\tconst exportType = detectExportType(filePath)\r\n\tconst loader = `() => import(${JSON.stringify(slash(filePath))})`\r\n\tconst layouts = collectLayouts(filePath, resolvedPagesDir, opts).map(\r\n\t\tlp => `() => import(${JSON.stringify(slash(lp))})`\r\n\t)\r\n\r\n\t// Ищем специальные файлы\r\n\tconst loading = findSpecialFile(filePath, resolvedPagesDir, opts, 'loading')\r\n\tconst notFound = findSpecialFile(filePath, resolvedPagesDir, opts, 'not-found')\r\n\tconst error = findSpecialFile(filePath, resolvedPagesDir, opts, 'error')\r\n\r\n\treturn {\r\n\t\tid,\r\n\t\tpath: route,\r\n\t\tfilePath: slash(filePath),\r\n\t\tloader,\r\n\t\texportType,\r\n\t\tlayouts,\r\n\t\tloading: loading ? `() => import(${JSON.stringify(slash(loading))})` : undefined,\r\n\t\tnotFound: notFound ? `() => import(${JSON.stringify(slash(notFound))})` : undefined,\r\n\t\terror: error ? `() => import(${JSON.stringify(slash(error))})` : undefined,\r\n\t}\r\n}\r\n","import fg from 'fast-glob'\r\nimport fs from 'node:fs'\r\nimport path from 'node:path'\r\nimport type { Options } from './types/types'\r\nimport { slash } from './utils'\r\n\r\nexport async function scanPages(\r\n\tresolvedPagesDir: string,\r\n\topts: Required<Options>\r\n): Promise<string[]> {\r\n\t// pattern like /abs/path/**/page.tsx\r\n\tconst exts = opts.extensions.join('|')\r\n\tconst pattern = `${slash(resolvedPagesDir)}/**/${\r\n\t\topts.pageFileName\r\n\t}.+(${exts})`\r\n\tconst files = await fg(pattern, { dot: true })\r\n\t// return absolute normalized paths\r\n\treturn files.map((f: string) => path.resolve(f))\r\n}\r\n\r\nexport function collectLayouts(\r\n\tfilePath: string,\r\n\tresolvedPagesDir: string,\r\n\topts: Required<Options>\r\n): string[] {\r\n\tconst rel = slash(path.relative(resolvedPagesDir, filePath))\r\n\tconst dir = path.dirname(rel)\r\n\tconst parts = dir === '.' ? [] : dir.split('/').filter(Boolean)\r\n\r\n\tconst layouts: string[] = []\r\n\t// for each level from 0..parts.length include layout if exists\r\n\t// НЕ фильтруем группы маршрутов при поиске layout файлов\r\n\tfor (let i = 0; i <= parts.length; i++) {\r\n\t\tconst p = parts.slice(0, i).join('/')\r\n\t\tfor (const ext of opts.extensions) {\r\n\t\t\tconst candidate = path.resolve(\r\n\t\t\t\tresolvedPagesDir,\r\n\t\t\t\tp || '',\r\n\t\t\t\t`${opts.layoutFileName}.${ext}`\r\n\t\t\t)\r\n\t\t\tif (fs.existsSync(candidate)) {\r\n\t\t\t\tlayouts.push(candidate)\r\n\t\t\t\tbreak\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\treturn layouts\r\n}\r\n\r\n/**\r\n * Находит файл loading, not-found или error в директории страницы\r\n */\r\nexport function findSpecialFile(\r\n\tfilePath: string,\r\n\tresolvedPagesDir: string,\r\n\topts: Required<Options>,\r\n\tfileName: 'loading' | 'not-found' | 'error'\r\n): string | undefined {\r\n\tconst rel = slash(path.relative(resolvedPagesDir, filePath))\r\n\tconst dir = path.dirname(rel)\r\n\t\r\n\t// Ищем файл в той же директории, что и страница\r\n\tfor (const ext of opts.extensions) {\r\n\t\tconst candidate = path.resolve(\r\n\t\t\tresolvedPagesDir,\r\n\t\t\tdir === '.' ? '' : dir,\r\n\t\t\t`${opts[`${fileName}FileName` as keyof typeof opts]}.${ext}`\r\n\t\t)\r\n\t\tif (fs.existsSync(candidate)) {\r\n\t\t\treturn candidate\r\n\t\t}\r\n\t}\r\n\t\r\n\t// Если не найден, ищем в родительских директориях (как layouts)\r\n\tconst parts = dir === '.' ? [] : dir.split('/').filter(Boolean)\r\n\tfor (let i = parts.length; i >= 0; i--) {\r\n\t\tconst p = parts.slice(0, i).join('/')\r\n\t\tfor (const ext of opts.extensions) {\r\n\t\t\tconst candidate = path.resolve(\r\n\t\t\t\tresolvedPagesDir,\r\n\t\t\t\tp || '',\r\n\t\t\t\t`${opts[`${fileName}FileName` as keyof typeof opts]}.${ext}`\r\n\t\t\t)\r\n\t\t\tif (fs.existsSync(candidate)) {\r\n\t\t\t\treturn candidate\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t\r\n\treturn undefined\r\n}","import fs from 'node:fs'\r\nimport type { ExportType } from './types/types'\r\n\r\nexport const slash = (p: string) => p.replace(/\\\\/g, '/')\r\n\r\nexport function detectExportType(filePath: string): ExportType {\r\n\ttry {\r\n\t\tconst content = fs.readFileSync(filePath, 'utf-8')\r\n\r\n\t\t// Проверяем наличие default экспорта\r\n\t\tconst hasDefaultExport = /export\\s+default\\s+/.test(content)\r\n\r\n\t\t// Проверяем наличие любого именованного экспорта (функция, константа или класс)\r\n\t\tconst hasNamedExport = /export\\s+(const|function|class)\\s+\\w+\\s*[=(]/.test(\r\n\t\t\tcontent\r\n\t\t)\r\n\r\n\t\tif (hasDefaultExport) {\r\n\t\t\treturn 'default'\r\n\t\t} else if (hasNamedExport) {\r\n\t\t\treturn 'named'\r\n\t\t}\r\n\r\n\t\t// По умолчанию предполагаем default экспорт для обратной совместимости\r\n\t\treturn 'default'\r\n\t} catch (error) {\r\n\t\t// В случае ошибки чтения файла, предполагаем default экспорт\r\n\t\tconsole.warn(\r\n\t\t\t`[vite-plugin-file-router] Failed to read file ${filePath}:`,\r\n\t\t\terror\r\n\t\t)\r\n\t\treturn 'default'\r\n\t}\r\n}\r\n","import type { RouteEntry } from './types/types'\r\n\r\nexport function generateRouteTypes(routes: RouteEntry[]): string {\r\n\tconst routePaths = routes.map(route => `'${route.path}'`).join(' | ')\r\n\r\n\t// Извлекаем параметры из динамических маршрутов\r\n\tconst routeParams: Record<string, Record<string, string>> = {}\r\n\troutes.forEach(route => {\r\n\t\tconst params: Record<string, string> = {}\r\n\r\n\t\t// Парсим [id] параметры\r\n\t\tconst idMatches = route.path.match(/\\[([^\\]]+)\\]/g)\r\n\t\tif (idMatches) {\r\n\t\t\tidMatches.forEach(match => {\r\n\t\t\t\tconst paramName = match.slice(1, -1)\r\n\t\t\t\tif (paramName.startsWith('...')) {\r\n\t\t\t\t\t// Catch-all параметр\r\n\t\t\t\t\tparams[paramName.slice(3)] = 'string[]'\r\n\t\t\t\t} else {\r\n\t\t\t\t\tparams[paramName] = 'string'\r\n\t\t\t\t}\r\n\t\t\t})\r\n\t\t}\r\n\r\n\t\tif (Object.keys(params).length > 0) {\r\n\t\t\trouteParams[route.path] = params\r\n\t\t}\r\n\t})\r\n\r\n\tconst routeParamsType =\r\n\t\tObject.keys(routeParams).length > 0\r\n\t\t\t? `export type RouteParams = {\r\n${Object.entries(routeParams)\r\n\t.map(([path, params]) => {\r\n\t\tconst paramEntries = Object.entries(params)\r\n\t\t\t.map(([key, type]) => `${key}: ${type}`)\r\n\t\t\t.join(', ')\r\n\t\treturn ` '${path}': { ${paramEntries} }`\r\n\t})\r\n\t.join('\\n')}\r\n}`\r\n\t\t\t: 'export type RouteParams = Record<string, never>'\r\n\r\n\treturn `// Автогенерированные типы маршрутов\r\nexport type RoutePath = ${routePaths || 'never'}\r\n\r\n${routeParamsType}\r\n\r\nexport type PageProps<T extends RoutePath = RoutePath> = {\r\n params: RouteParams[T]\r\n searchParams?: Record<string, string>\r\n}\r\n\r\nexport interface LayoutProps {\r\n children: React.ReactNode\r\n}\r\n\r\nexport interface RouteInfo {\r\n id: string\r\n path: string\r\n filePath: string\r\n exportType: 'default' | 'named'\r\n layouts: string[]\r\n}\r\n\r\n// Утилиты для навигации\r\nexport function navigate<T extends RoutePath>(\r\n path: T, \r\n params?: RouteParams[T]\r\n): void {\r\n // Реализация навигации\r\n window.location.href = path\r\n}\r\n\r\nexport function useParams<T extends RoutePath>(): RouteParams[T] {\r\n // Реализация хука для получения параметров\r\n return {} as RouteParams[T]\r\n}\r\n`\r\n}\r\n\r\nexport function generateMetadataTypes(): string {\r\n\treturn `// Типы для метаданных страниц\r\nexport interface PageMetadata {\r\n title?: string\r\n description?: string\r\n keywords?: string[]\r\n author?: string\r\n changefreq?: 'always' | 'hourly' | 'daily' | 'weekly' | 'monthly' | 'yearly' | 'never'\r\n priority?: number\r\n}\r\n\r\nexport interface SEOConfig {\r\n baseUrl: string\r\n defaultTitle?: string\r\n defaultDescription?: string\r\n disallowPaths?: string[]\r\n}\r\n`\r\n}\r\n","import fs from 'node:fs'\r\n\r\nexport function createHMRHandlers(\r\n\tresolvedPagesDir: string,\r\n\tresolvedVirtualId: string,\r\n\troot: string\r\n) {\r\n\tconst configureServer = (srv: any) => {\r\n\t\tconst invalidateVirtual = async () => {\r\n\t\t\tconst mod = srv.moduleGraph?.getModuleById?.(resolvedVirtualId)\r\n\t\t\tif (mod) {\r\n\t\t\t\tsrv.moduleGraph?.invalidateModule?.(mod)\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tconst watchPath = fs.existsSync(resolvedPagesDir) ? resolvedPagesDir : root\r\n\t\tsrv.watcher?.add?.(watchPath)\r\n\r\n\t\tsrv.watcher?.on?.('add', (p: string) => {\r\n\t\t\tif (p.startsWith(resolvedPagesDir)) invalidateVirtual()\r\n\t\t})\r\n\t\tsrv.watcher?.on?.('unlink', (p: string) => {\r\n\t\t\tif (p.startsWith(resolvedPagesDir)) invalidateVirtual()\r\n\t\t})\r\n\t}\r\n\r\n\tconst handleHotUpdate = (ctx: any) => {\r\n\t\tconst f = ctx.file\r\n\t\tif (!f?.startsWith(resolvedPagesDir)) return\r\n\r\n\t\tconst mod = ctx.server.moduleGraph?.getModuleById?.(resolvedVirtualId)\r\n\t\tif (mod) {\r\n\t\t\tctx.server.moduleGraph?.invalidateModule?.(mod)\r\n\t\t\treturn [mod]\r\n\t\t}\r\n\t}\r\n\r\n\treturn { configureServer, handleHotUpdate }\r\n}\r\n","import fs from 'node:fs'\r\nimport path from 'node:path'\r\n\r\nexport async function loadGeneratedManifest(root: string): Promise<string> {\r\n\tconst manifestPath = path.join(root, 'dist', 'routes-manifest.js')\r\n\tif (fs.existsSync(manifestPath)) {\r\n\t\ttry {\r\n\t\t\tconst manifestContent = fs.readFileSync(manifestPath, 'utf-8')\r\n\t\t\tconst manifestRegex = /export const manifest = \\[.*?\\];/s\r\n\t\t\tconst manifestMatch = manifestRegex.exec(manifestContent)\r\n\t\t\tconst basePathRegex = /export const basePath = ['\"](.*?)['\"];/\r\n\t\t\tconst basePathMatch = basePathRegex.exec(manifestContent)\r\n\t\t\tconst basePath = basePathMatch ? basePathMatch[1] : '/'\r\n\t\t\t\r\n\t\t\tif (manifestMatch) {\r\n\t\t\t\treturn `// virtual routes (production mode - using generated manifest)\r\n${manifestMatch[0]}\r\nexport const basePath = ${JSON.stringify(basePath)};\r\nexport default manifest;\r\n`\r\n\t\t\t}\r\n\t\t} catch (error) {\r\n\t\t\tconsole.warn(\r\n\t\t\t\t'[vite-plugin-file-router] Failed to load generated manifest:',\r\n\t\t\t\terror\r\n\t\t\t)\r\n\t\t}\r\n\t}\r\n\r\n\t// Fallback - пустой манифест\r\n\treturn `// virtual routes (production mode - empty manifest)\r\nexport const manifest = [];\r\nexport const basePath = '/';\r\nexport default manifest;\r\n`\r\n}\r\n","import { createRouteEntry } from './route-generator'\r\nimport { scanPages } from './scanner'\r\nimport type { Options } from './types/types'\r\n\r\nexport async function generateVirtualModuleCode(\r\n\tresolvedPagesDir: string,\r\n\topts: Required<Options>\r\n): Promise<string> {\r\n\tconst pages = await scanPages(resolvedPagesDir, opts)\r\n\tconst entries = pages.map(fp => {\r\n\t\tconst entry = createRouteEntry(fp, resolvedPagesDir, opts)\r\n\t\treturn `{\r\n id: ${JSON.stringify(entry.id)},\r\n path: ${JSON.stringify(entry.path)},\r\n filePath: ${JSON.stringify(entry.filePath)},\r\n loader: ${entry.loader},\r\n exportType: ${JSON.stringify(entry.exportType)},\r\n layouts: [${entry.layouts.join(',')}],\r\n ${entry.loading ? `loading: ${entry.loading},` : ''}\r\n ${entry.notFound ? `notFound: ${entry.notFound},` : ''}\r\n ${entry.error ? `error: ${entry.error},` : ''}\r\n }`\r\n\t})\r\n\r\n\t// Ищем глобальный not-found в корне pages\r\n\tlet globalNotFound: string | undefined\r\n\tfor (const ext of opts.extensions) {\r\n\t\tconst notFoundPath = path.resolve(\r\n\t\t\tresolvedPagesDir,\r\n\t\t\t`${opts.notFoundFileName}.${ext}`\r\n\t\t)\r\n\t\tif (fs.existsSync(notFoundPath)) {\r\n\t\t\tglobalNotFound = `() => import(${JSON.stringify(slash(notFoundPath))})`\r\n\t\t\tbreak\r\n\t\t}\r\n\t}\r\n\r\n\treturn `// Auto-generated routes manifest\r\nconst manifest = [${entries.join(',\\n')}];\r\n\r\nexport const basePath = ${JSON.stringify(opts.basePath ?? '/')};\r\n${globalNotFound ? `export const globalNotFound = ${globalNotFound};` : 'export const globalNotFound = undefined;'}\r\n\r\nexport { manifest };\r\nexport default manifest;\r\n`\r\n}\r\n"],"mappings":"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","names":["import_node_fs","import_node_path","import_node_fs","import_node_path","fs","path","import_node_path","import_node_fs","import_node_fs","slash","fs","slash","fg","path","fs","slash","path","path","path","fs","import_node_fs","fs","import_node_fs","import_node_path","path","fs","path","fs"]}
|
package/dist/core.mjs
CHANGED
package/dist/plugin.d.cts
CHANGED
|
@@ -34,6 +34,36 @@ type Options = {
|
|
|
34
34
|
* @default 'layout'
|
|
35
35
|
*/
|
|
36
36
|
layoutFileName?: string;
|
|
37
|
+
/**
|
|
38
|
+
* ⏳ Имя файла loading
|
|
39
|
+
*
|
|
40
|
+
* ▸ Файлы с этим именем используются как Suspense fallback
|
|
41
|
+
*
|
|
42
|
+
* ▸ Показываются во время загрузки страницы
|
|
43
|
+
*
|
|
44
|
+
* @default 'loading'
|
|
45
|
+
*/
|
|
46
|
+
loadingFileName?: string;
|
|
47
|
+
/**
|
|
48
|
+
* ❌ Имя файла not-found
|
|
49
|
+
*
|
|
50
|
+
* ▸ Файлы с этим именем используются для 404 страниц
|
|
51
|
+
*
|
|
52
|
+
* ▸ Показываются когда маршрут не найден
|
|
53
|
+
*
|
|
54
|
+
* @default 'not-found'
|
|
55
|
+
*/
|
|
56
|
+
notFoundFileName?: string;
|
|
57
|
+
/**
|
|
58
|
+
* ⚠️ Имя файла error
|
|
59
|
+
*
|
|
60
|
+
* ▸ Файлы с этим именем используются как ErrorBoundary
|
|
61
|
+
*
|
|
62
|
+
* ▸ Показываются при ошибке рендеринга
|
|
63
|
+
*
|
|
64
|
+
* @default 'error'
|
|
65
|
+
*/
|
|
66
|
+
errorFileName?: string;
|
|
37
67
|
/**
|
|
38
68
|
* 🎯 Расширения файлов
|
|
39
69
|
*
|
package/dist/plugin.d.ts
CHANGED
|
@@ -34,6 +34,36 @@ type Options = {
|
|
|
34
34
|
* @default 'layout'
|
|
35
35
|
*/
|
|
36
36
|
layoutFileName?: string;
|
|
37
|
+
/**
|
|
38
|
+
* ⏳ Имя файла loading
|
|
39
|
+
*
|
|
40
|
+
* ▸ Файлы с этим именем используются как Suspense fallback
|
|
41
|
+
*
|
|
42
|
+
* ▸ Показываются во время загрузки страницы
|
|
43
|
+
*
|
|
44
|
+
* @default 'loading'
|
|
45
|
+
*/
|
|
46
|
+
loadingFileName?: string;
|
|
47
|
+
/**
|
|
48
|
+
* ❌ Имя файла not-found
|
|
49
|
+
*
|
|
50
|
+
* ▸ Файлы с этим именем используются для 404 страниц
|
|
51
|
+
*
|
|
52
|
+
* ▸ Показываются когда маршрут не найден
|
|
53
|
+
*
|
|
54
|
+
* @default 'not-found'
|
|
55
|
+
*/
|
|
56
|
+
notFoundFileName?: string;
|
|
57
|
+
/**
|
|
58
|
+
* ⚠️ Имя файла error
|
|
59
|
+
*
|
|
60
|
+
* ▸ Файлы с этим именем используются как ErrorBoundary
|
|
61
|
+
*
|
|
62
|
+
* ▸ Показываются при ошибке рендеринга
|
|
63
|
+
*
|
|
64
|
+
* @default 'error'
|
|
65
|
+
*/
|
|
66
|
+
errorFileName?: string;
|
|
37
67
|
/**
|
|
38
68
|
* 🎯 Расширения файлов
|
|
39
69
|
*
|
package/dist/plugin.js
CHANGED
|
@@ -125,7 +125,7 @@ ${urls}
|
|
|
125
125
|
</urlset>`;
|
|
126
126
|
}
|
|
127
127
|
function generateRobots(baseUrl, disallowPaths = []) {
|
|
128
|
-
const disallowRules = disallowPaths.map((
|
|
128
|
+
const disallowRules = disallowPaths.map((path7) => `Disallow: ${path7}`).join("\n");
|
|
129
129
|
return `User-agent: *
|
|
130
130
|
Allow: /
|
|
131
131
|
${disallowRules ? `
|
|
@@ -144,7 +144,7 @@ var import_node_path = __toESM(require("path"), 1);
|
|
|
144
144
|
|
|
145
145
|
// src/core/utils.ts
|
|
146
146
|
var import_node_fs2 = __toESM(require("fs"), 1);
|
|
147
|
-
var
|
|
147
|
+
var slash2 = (p) => p.replace(/\\/g, "/");
|
|
148
148
|
function detectExportType(filePath) {
|
|
149
149
|
try {
|
|
150
150
|
const content = import_node_fs2.default.readFileSync(filePath, "utf-8");
|
|
@@ -170,12 +170,12 @@ function detectExportType(filePath) {
|
|
|
170
170
|
// src/core/scanner.ts
|
|
171
171
|
async function scanPages(resolvedPagesDir, opts) {
|
|
172
172
|
const exts = opts.extensions.join("|");
|
|
173
|
-
const pattern = `${
|
|
173
|
+
const pattern = `${slash2(resolvedPagesDir)}/**/${opts.pageFileName}.+(${exts})`;
|
|
174
174
|
const files = await (0, import_fast_glob.default)(pattern, { dot: true });
|
|
175
175
|
return files.map((f) => import_node_path.default.resolve(f));
|
|
176
176
|
}
|
|
177
177
|
function collectLayouts(filePath, resolvedPagesDir, opts) {
|
|
178
|
-
const rel =
|
|
178
|
+
const rel = slash2(import_node_path.default.relative(resolvedPagesDir, filePath));
|
|
179
179
|
const dir = import_node_path.default.dirname(rel);
|
|
180
180
|
const parts = dir === "." ? [] : dir.split("/").filter(Boolean);
|
|
181
181
|
const layouts = [];
|
|
@@ -195,6 +195,35 @@ function collectLayouts(filePath, resolvedPagesDir, opts) {
|
|
|
195
195
|
}
|
|
196
196
|
return layouts;
|
|
197
197
|
}
|
|
198
|
+
function findSpecialFile(filePath, resolvedPagesDir, opts, fileName) {
|
|
199
|
+
const rel = slash2(import_node_path.default.relative(resolvedPagesDir, filePath));
|
|
200
|
+
const dir = import_node_path.default.dirname(rel);
|
|
201
|
+
for (const ext of opts.extensions) {
|
|
202
|
+
const candidate = import_node_path.default.resolve(
|
|
203
|
+
resolvedPagesDir,
|
|
204
|
+
dir === "." ? "" : dir,
|
|
205
|
+
`${opts[`${fileName}FileName`]}.${ext}`
|
|
206
|
+
);
|
|
207
|
+
if (import_node_fs3.default.existsSync(candidate)) {
|
|
208
|
+
return candidate;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
const parts = dir === "." ? [] : dir.split("/").filter(Boolean);
|
|
212
|
+
for (let i = parts.length; i >= 0; i--) {
|
|
213
|
+
const p = parts.slice(0, i).join("/");
|
|
214
|
+
for (const ext of opts.extensions) {
|
|
215
|
+
const candidate = import_node_path.default.resolve(
|
|
216
|
+
resolvedPagesDir,
|
|
217
|
+
p || "",
|
|
218
|
+
`${opts[`${fileName}FileName`]}.${ext}`
|
|
219
|
+
);
|
|
220
|
+
if (import_node_fs3.default.existsSync(candidate)) {
|
|
221
|
+
return candidate;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
return void 0;
|
|
226
|
+
}
|
|
198
227
|
|
|
199
228
|
// src/core/route-generator.ts
|
|
200
229
|
function segmentToRoute(seg) {
|
|
@@ -209,7 +238,7 @@ function segmentToRoute(seg) {
|
|
|
209
238
|
return seg;
|
|
210
239
|
}
|
|
211
240
|
function filePathToRoute(filePath, resolvedPagesDir) {
|
|
212
|
-
const rel =
|
|
241
|
+
const rel = slash2(import_node_path2.default.relative(resolvedPagesDir, filePath));
|
|
213
242
|
const dir = import_node_path2.default.dirname(rel);
|
|
214
243
|
const parts = dir === "." ? [] : dir.split("/").filter(Boolean);
|
|
215
244
|
const filteredParts = parts.filter(
|
|
@@ -221,19 +250,25 @@ function filePathToRoute(filePath, resolvedPagesDir) {
|
|
|
221
250
|
}
|
|
222
251
|
function createRouteEntry(filePath, resolvedPagesDir, opts) {
|
|
223
252
|
const route = filePathToRoute(filePath, resolvedPagesDir);
|
|
224
|
-
const id =
|
|
253
|
+
const id = slash2(import_node_path2.default.relative(resolvedPagesDir, filePath)).replace(/\//g, "_").replace(/\.[^.]+$/, "");
|
|
225
254
|
const exportType = detectExportType(filePath);
|
|
226
|
-
const loader = `() => import(${JSON.stringify(
|
|
255
|
+
const loader = `() => import(${JSON.stringify(slash2(filePath))})`;
|
|
227
256
|
const layouts = collectLayouts(filePath, resolvedPagesDir, opts).map(
|
|
228
|
-
(lp) => `() => import(${JSON.stringify(
|
|
257
|
+
(lp) => `() => import(${JSON.stringify(slash2(lp))})`
|
|
229
258
|
);
|
|
259
|
+
const loading = findSpecialFile(filePath, resolvedPagesDir, opts, "loading");
|
|
260
|
+
const notFound = findSpecialFile(filePath, resolvedPagesDir, opts, "not-found");
|
|
261
|
+
const error = findSpecialFile(filePath, resolvedPagesDir, opts, "error");
|
|
230
262
|
return {
|
|
231
263
|
id,
|
|
232
264
|
path: route,
|
|
233
|
-
filePath:
|
|
265
|
+
filePath: slash2(filePath),
|
|
234
266
|
loader,
|
|
235
267
|
exportType,
|
|
236
|
-
layouts
|
|
268
|
+
layouts,
|
|
269
|
+
loading: loading ? `() => import(${JSON.stringify(slash2(loading))})` : void 0,
|
|
270
|
+
notFound: notFound ? `() => import(${JSON.stringify(slash2(notFound))})` : void 0,
|
|
271
|
+
error: error ? `() => import(${JSON.stringify(slash2(error))})` : void 0
|
|
237
272
|
};
|
|
238
273
|
}
|
|
239
274
|
|
|
@@ -259,9 +294,9 @@ function generateRouteTypes(routes) {
|
|
|
259
294
|
}
|
|
260
295
|
});
|
|
261
296
|
const routeParamsType = Object.keys(routeParams).length > 0 ? `export type RouteParams = {
|
|
262
|
-
${Object.entries(routeParams).map(([
|
|
297
|
+
${Object.entries(routeParams).map(([path7, params]) => {
|
|
263
298
|
const paramEntries = Object.entries(params).map(([key, type]) => `${key}: ${type}`).join(", ");
|
|
264
|
-
return ` '${
|
|
299
|
+
return ` '${path7}': { ${paramEntries} }`;
|
|
265
300
|
}).join("\n")}
|
|
266
301
|
}` : "export type RouteParams = Record<string, never>";
|
|
267
302
|
return `// \u0410\u0432\u0442\u043E\u0433\u0435\u043D\u0435\u0440\u0438\u0440\u043E\u0432\u0430\u043D\u043D\u044B\u0435 \u0442\u0438\u043F\u044B \u043C\u0430\u0440\u0448\u0440\u0443\u0442\u043E\u0432
|
|
@@ -432,13 +467,28 @@ async function generateVirtualModuleCode(resolvedPagesDir, opts) {
|
|
|
432
467
|
filePath: ${JSON.stringify(entry.filePath)},
|
|
433
468
|
loader: ${entry.loader},
|
|
434
469
|
exportType: ${JSON.stringify(entry.exportType)},
|
|
435
|
-
layouts: [${entry.layouts.join(",")}]
|
|
470
|
+
layouts: [${entry.layouts.join(",")}],
|
|
471
|
+
${entry.loading ? `loading: ${entry.loading},` : ""}
|
|
472
|
+
${entry.notFound ? `notFound: ${entry.notFound},` : ""}
|
|
473
|
+
${entry.error ? `error: ${entry.error},` : ""}
|
|
436
474
|
}`;
|
|
437
475
|
});
|
|
476
|
+
let globalNotFound;
|
|
477
|
+
for (const ext of opts.extensions) {
|
|
478
|
+
const notFoundPath = path.resolve(
|
|
479
|
+
resolvedPagesDir,
|
|
480
|
+
`${opts.notFoundFileName}.${ext}`
|
|
481
|
+
);
|
|
482
|
+
if (fs.existsSync(notFoundPath)) {
|
|
483
|
+
globalNotFound = `() => import(${JSON.stringify(slash(notFoundPath))})`;
|
|
484
|
+
break;
|
|
485
|
+
}
|
|
486
|
+
}
|
|
438
487
|
return `// Auto-generated routes manifest
|
|
439
488
|
const manifest = [${entries.join(",\n")}];
|
|
440
489
|
|
|
441
490
|
export const basePath = ${JSON.stringify(opts.basePath ?? "/")};
|
|
491
|
+
${globalNotFound ? `export const globalNotFound = ${globalNotFound};` : "export const globalNotFound = undefined;"}
|
|
442
492
|
|
|
443
493
|
export { manifest };
|
|
444
494
|
export default manifest;
|
|
@@ -451,6 +501,9 @@ function pathRushRouting(rawOpts = {}) {
|
|
|
451
501
|
pagesDir: rawOpts.pagesDir ?? "src/pages",
|
|
452
502
|
pageFileName: rawOpts.pageFileName ?? "page",
|
|
453
503
|
layoutFileName: rawOpts.layoutFileName ?? "layout",
|
|
504
|
+
loadingFileName: rawOpts.loadingFileName ?? "loading",
|
|
505
|
+
notFoundFileName: rawOpts.notFoundFileName ?? "not-found",
|
|
506
|
+
errorFileName: rawOpts.errorFileName ?? "error",
|
|
454
507
|
extensions: rawOpts.extensions ?? ["tsx"],
|
|
455
508
|
baseUrl: rawOpts.baseUrl ?? "http://localhost:5173",
|
|
456
509
|
basePath: rawOpts.basePath ?? "/",
|
package/dist/plugin.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/plugin.ts","../src/core/build-generator.ts","../src/core/metadata.ts","../src/core/route-generator.ts","../src/core/scanner.ts","../src/core/utils.ts","../src/core/type-generator.ts","../src/core/hmr-handlers.ts","../src/core/manifest-loader.ts","../src/core/virtual-module.ts"],"sourcesContent":["import fs from 'node:fs'\r\nimport path from 'node:path'\r\nimport type { Plugin, UserConfig } from 'vite'\r\nimport { generateSEOFiles, generateTypes } from './core/build-generator'\r\nimport { createHMRHandlers } from './core/hmr-handlers'\r\nimport { loadGeneratedManifest } from './core/manifest-loader'\r\nimport type { Options } from './core/types/types'\r\nimport { generateVirtualModuleCode } from './core/virtual-module'\r\n\r\nexport type { Options } from './core/types/types'\r\n\r\nexport function pathRushRouting(rawOpts: Options = {}): Plugin {\r\n\tconst opts: Required<Options> = {\r\n\t\tpagesDir: rawOpts.pagesDir ?? 'src/pages',\r\n\t\tpageFileName: rawOpts.pageFileName ?? 'page',\r\n\t\tlayoutFileName: rawOpts.layoutFileName ?? 'layout',\r\n\t\textensions: rawOpts.extensions ?? ['tsx'],\r\n\t\tbaseUrl: rawOpts.baseUrl ?? 'http://localhost:5173',\r\n\t\tbasePath: rawOpts.basePath ?? '/',\r\n\t\tdisallowPaths: rawOpts.disallowPaths ?? [],\r\n\t\tgenerateTypes: rawOpts.generateTypes ?? true,\r\n\t\tenableSEO: rawOpts.enableSEO ?? true,\r\n\t}\r\n\r\n\tconst VIRTUAL_ID = 'virtual:routes'\r\n\tconst RESOLVED_VIRTUAL_ID = '\\0' + VIRTUAL_ID\r\n\tlet root = process.cwd()\r\n\tlet resolvedPagesDir = path.resolve(root, opts.pagesDir)\r\n\r\n\tconst plugin: Plugin = {\r\n\t\tname: 'vite-plugin-file-router-mwv',\r\n\t\tenforce: 'pre',\r\n\r\n\t\t// Автоматическая настройка Vite конфигурации\r\n\t\tconfig(userConfig: UserConfig): UserConfig {\r\n\t\t\tconst existingAlias = userConfig.resolve?.alias\r\n\t\t\tconst existingExclude = userConfig.optimizeDeps?.exclude\r\n\r\n\t\t\t// Безопасно мерджим с существующей конфигурацией\r\n\t\t\treturn {\r\n\t\t\t\toptimizeDeps: {\r\n\t\t\t\t\texclude: [\r\n\t\t\t\t\t\t...(Array.isArray(existingExclude) ? existingExclude : []),\r\n\t\t\t\t\t\t'virtual:routes',\r\n\t\t\t\t\t],\r\n\t\t\t\t},\r\n\t\t\t\tresolve: {\r\n\t\t\t\t\talias: {\r\n\t\t\t\t\t\t...(typeof existingAlias === 'object' ? existingAlias : {}),\r\n\t\t\t\t\t\t'virtual:routes': 'virtual:routes',\r\n\t\t\t\t\t},\r\n\t\t\t\t},\r\n\t\t\t}\r\n\t\t},\r\n\r\n\t\tresolveId(id: string) {\r\n\t\t\tif (id === VIRTUAL_ID) return RESOLVED_VIRTUAL_ID\r\n\t\t\treturn null\r\n\t\t},\r\n\r\n\t\tasync load(id: string) {\r\n\t\t\tif (id === RESOLVED_VIRTUAL_ID) {\r\n\t\t\t\t// В production режиме проверяем существование директории pages\r\n\t\t\t\tif (!fs.existsSync(resolvedPagesDir)) {\r\n\t\t\t\t\t// В production пытаемся загрузить сгенерированный манифест\r\n\t\t\t\t\treturn await loadGeneratedManifest(root)\r\n\t\t\t\t}\r\n\r\n\t\t\t\treturn await generateVirtualModuleCode(resolvedPagesDir, opts)\r\n\t\t\t}\r\n\t\t\treturn null\r\n\t\t},\r\n\r\n\t\tasync buildStart() {\r\n\t\t\troot = process.cwd()\r\n\t\t\tresolvedPagesDir = path.resolve(root, opts.pagesDir)\r\n\r\n\t\t\tif (!fs.existsSync(resolvedPagesDir)) {\r\n\t\t\t\tconsole.warn(\r\n\t\t\t\t\t`[vite-plugin-file-router] pagesDir \"${resolvedPagesDir}\" not found.`\r\n\t\t\t\t)\r\n\t\t\t}\r\n\t\t},\r\n\r\n\t\tasync generateBundle() {\r\n\t\t\t// Проверяем существование директории pages\r\n\t\t\tif (!fs.existsSync(resolvedPagesDir)) {\r\n\t\t\t\tconsole.warn(\r\n\t\t\t\t\t`[vite-plugin-file-router] pagesDir \"${resolvedPagesDir}\" not found in production build. Skipping route generation.`\r\n\t\t\t\t)\r\n\t\t\t\treturn\r\n\t\t\t}\r\n\r\n\t\t\t// Генерируем TypeScript типы\r\n\t\t\tif (opts.generateTypes) {\r\n\t\t\t\ttry {\r\n\t\t\t\t\tawait generateTypes(resolvedPagesDir, opts)\r\n\t\t\t\t} catch (error) {\r\n\t\t\t\t\tconsole.warn(\r\n\t\t\t\t\t\t`[vite-plugin-file-router] Failed to generate types: ${error}`\r\n\t\t\t\t\t)\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\t// Генерируем SEO файлы\r\n\t\t\tif (opts.enableSEO) {\r\n\t\t\t\ttry {\r\n\t\t\t\t\tawait generateSEOFiles(resolvedPagesDir, opts)\r\n\t\t\t\t} catch (error) {\r\n\t\t\t\t\tconsole.warn(\r\n\t\t\t\t\t\t`[vite-plugin-file-router] Failed to generate SEO files: ${error}`\r\n\t\t\t\t\t)\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t},\r\n\t}\r\n\r\n\t// Добавляем HMR только если в development режиме\r\n\tif (process.env.NODE_ENV !== 'production') {\r\n\t\tconst { configureServer, handleHotUpdate } = createHMRHandlers(\r\n\t\t\tresolvedPagesDir,\r\n\t\t\tRESOLVED_VIRTUAL_ID,\r\n\t\t\troot\r\n\t\t)\r\n\t\tplugin.configureServer = configureServer\r\n\t\tplugin.handleHotUpdate = handleHotUpdate\r\n\t}\r\n\r\n\treturn plugin\r\n}\r\n","import fs from 'node:fs'\r\nimport path from 'node:path'\r\nimport { extractMetadata, generateRobots, generateSitemap } from './metadata'\r\nimport { createRouteEntry } from './route-generator'\r\nimport { scanPages } from './scanner'\r\nimport { generateMetadataTypes, generateRouteTypes } from './type-generator'\r\nimport type { Options } from './types/types'\r\n\r\nexport async function generateTypes(\r\n\tresolvedPagesDir: string,\r\n\topts: Required<Options>\r\n) {\r\n\tconst pages = await scanPages(resolvedPagesDir, opts)\r\n\tconst routes = pages.map(fp => createRouteEntry(fp, resolvedPagesDir, opts))\r\n\r\n\tconst routeTypes = generateRouteTypes(routes)\r\n\tconst metadataTypes = generateMetadataTypes()\r\n\r\n\t// Создаем директорию для типов\r\n\tconst typesDir = path.join(process.cwd(), 'dist', 'types')\r\n\tif (!fs.existsSync(typesDir)) {\r\n\t\tfs.mkdirSync(typesDir, { recursive: true })\r\n\t}\r\n\r\n\tfs.writeFileSync(path.join(typesDir, 'routes.d.ts'), routeTypes)\r\n\tfs.writeFileSync(path.join(typesDir, 'metadata.d.ts'), metadataTypes)\r\n}\r\n\r\nexport async function generateSEOFiles(\r\n\tresolvedPagesDir: string,\r\n\topts: Required<Options>\r\n) {\r\n\tconst pages = await scanPages(resolvedPagesDir, opts)\r\n\tconst routesWithMetadata = pages\r\n\t\t.map(fp => {\r\n\t\t\tconst entry = createRouteEntry(fp, resolvedPagesDir, opts)\r\n\t\t\tconst metadata = extractMetadata(fp)\r\n\t\t\treturn {\r\n\t\t\t\tpath: entry.path,\r\n\t\t\t\tmetadata: metadata || undefined,\r\n\t\t\t}\r\n\t\t})\r\n\t\t.filter(\r\n\t\t\troute =>\r\n\t\t\t\t!opts.disallowPaths.some(disallow => route.path.startsWith(disallow))\r\n\t\t)\r\n\r\n\t// Генерируем sitemap.xml и robots.txt\r\n\tconst sitemap = generateSitemap(routesWithMetadata, opts.baseUrl)\r\n\tconst robots = generateRobots(opts.baseUrl, opts.disallowPaths)\r\n\r\n\tconst distDir = path.join(process.cwd(), 'dist')\r\n\tif (!fs.existsSync(distDir)) {\r\n\t\tfs.mkdirSync(distDir, { recursive: true })\r\n\t}\r\n\r\n\tfs.writeFileSync(path.join(distDir, 'sitemap.xml'), sitemap)\r\n\tfs.writeFileSync(path.join(distDir, 'robots.txt'), robots)\r\n}\r\n","import fs from 'node:fs'\r\nimport type { PageMetadata } from './types/types'\r\n\r\nexport function extractMetadata(filePath: string): PageMetadata | null {\r\n\ttry {\r\n\t\tconst content = fs.readFileSync(filePath, 'utf-8')\r\n\r\n\t\t// Парсинг JSDoc комментариев\r\n\t\tconst jsdocMetadata = extractJSDocMetadata(content)\r\n\t\tif (jsdocMetadata) {\r\n\t\t\treturn jsdocMetadata\r\n\t\t}\r\n\r\n\t\t// Парсинг экспорта metadata\r\n\t\tconst exportMetadata = extractExportMetadata(content)\r\n\t\tif (exportMetadata) {\r\n\t\t\treturn exportMetadata\r\n\t\t}\r\n\r\n\t\treturn null\r\n\t} catch (error) {\r\n\t\tconsole.warn(\r\n\t\t\t`[vite-plugin-file-router] Failed to extract metadata from ${filePath}:`,\r\n\t\t\terror\r\n\t\t)\r\n\t\treturn null\r\n\t}\r\n}\r\n\r\nfunction extractJSDocMetadata(content: string): PageMetadata | null {\r\n\tconst jsdocMatch = content.match(/\\/\\*\\*([\\s\\S]*?)\\*\\//)\r\n\tif (!jsdocMatch) return null\r\n\r\n\tconst jsdoc = jsdocMatch[1]\r\n\tconst metadata: PageMetadata = {}\r\n\r\n\t// Парсинг JSDoc тегов\r\n\tconst titleMatch = jsdoc.match(/@title\\s+(.+)/)\r\n\tif (titleMatch) metadata.title = titleMatch[1].trim()\r\n\r\n\tconst descMatch = jsdoc.match(/@description\\s+(.+)/)\r\n\tif (descMatch) metadata.description = descMatch[1].trim()\r\n\r\n\tconst keywordsMatch = jsdoc.match(/@keywords\\s+(.+)/)\r\n\tif (keywordsMatch) {\r\n\t\tmetadata.keywords = keywordsMatch[1].split(',').map(k => k.trim())\r\n\t}\r\n\r\n\tconst authorMatch = jsdoc.match(/@author\\s+(.+)/)\r\n\tif (authorMatch) metadata.author = authorMatch[1].trim()\r\n\r\n\tconst changefreqMatch = jsdoc.match(\r\n\t\t/@changefreq\\s+(always|hourly|daily|weekly|monthly|yearly|never)/\r\n\t)\r\n\tif (changefreqMatch) {\r\n\t\tmetadata.changefreq = changefreqMatch[1] as PageMetadata['changefreq']\r\n\t}\r\n\r\n\tconst priorityMatch = jsdoc.match(/@priority\\s+([0-9.]+)/)\r\n\tif (priorityMatch) {\r\n\t\tmetadata.priority = parseFloat(priorityMatch[1])\r\n\t}\r\n\r\n\treturn Object.keys(metadata).length > 0 ? metadata : null\r\n}\r\n\r\nfunction extractExportMetadata(content: string): PageMetadata | null {\r\n\t// Ищем экспорт const metadata = { ... }\r\n\tconst metadataMatch = content.match(\r\n\t\t/export\\s+const\\s+metadata\\s*=\\s*({[\\s\\S]*?});?/\r\n\t)\r\n\tif (!metadataMatch) return null\r\n\r\n\ttry {\r\n\t\t// Безопасное выполнение кода для извлечения объекта\r\n\t\tconst metadataCode = metadataMatch[1]\r\n\t\t// Заменяем возможные импорты и функции на безопасные значения\r\n\t\tconst safeCode = metadataCode\r\n\t\t\t.replace(/import\\s+.*?from\\s+['\"][^'\"]*['\"];?/g, '')\r\n\t\t\t.replace(/require\\s*\\([^)]*\\)/g, '\"\"')\r\n\t\t\t.replace(/process\\.env\\.[A-Z_]+/g, '\"\"')\r\n\r\n\t\t// Создаем функцию для безопасного выполнения\r\n\t\tconst func = new Function(`return ${safeCode}`)\r\n\t\treturn func()\r\n\t} catch (error) {\r\n\t\tconsole.warn(\r\n\t\t\t`[vite-plugin-file-router] Failed to parse metadata export:`,\r\n\t\t\terror\r\n\t\t)\r\n\t\treturn null\r\n\t}\r\n}\r\n\r\nexport function generateSitemap(\r\n\troutes: Array<{ path: string; metadata?: PageMetadata }>,\r\n\tbaseUrl: string\r\n): string {\r\n\tconst urls = routes\r\n\t\t.map(route => {\r\n\t\t\tconst lastmod = new Date().toISOString()\r\n\t\t\tconst changefreq = route.metadata?.changefreq || 'monthly'\r\n\t\t\tconst priority = route.metadata?.priority || 0.8\r\n\r\n\t\t\treturn ` <url>\r\n <loc>${baseUrl}${route.path}</loc>\r\n <lastmod>${lastmod}</lastmod>\r\n <changefreq>${changefreq}</changefreq>\r\n <priority>${priority}</priority>\r\n </url>`\r\n\t\t})\r\n\t\t.join('\\n')\r\n\r\n\treturn `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n<urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">\r\n${urls}\r\n</urlset>`\r\n}\r\n\r\nexport function generateRobots(\r\n\tbaseUrl: string,\r\n\tdisallowPaths: string[] = []\r\n): string {\r\n\tconst disallowRules = disallowPaths\r\n\t\t.map(path => `Disallow: ${path}`)\r\n\t\t.join('\\n')\r\n\r\n\treturn `User-agent: *\r\nAllow: /\r\n${disallowRules ? `\\n${disallowRules}` : ''}\r\n\r\nSitemap: ${baseUrl}/sitemap.xml`\r\n}\r\n","import path from 'node:path'\r\nimport { collectLayouts } from './scanner'\r\nimport type { Options, RouteEntry } from './types/types'\r\nimport { detectExportType, slash } from './utils'\r\n\r\nexport function segmentToRoute(seg: string): string {\r\n\tif (/^\\[\\.{3}.+\\]$/.test(seg)) {\r\n\t\tconst name = seg.slice(4, -1)\r\n\t\treturn `:${name}(.*)`\r\n\t}\r\n\tif (/^\\[.+\\]$/.test(seg)) {\r\n\t\tconst name = seg.slice(1, -1)\r\n\t\treturn `:${name}`\r\n\t}\r\n\treturn seg\r\n}\r\n\r\nexport function filePathToRoute(\r\n\tfilePath: string,\r\n\tresolvedPagesDir: string\r\n): string {\r\n\tconst rel = slash(path.relative(resolvedPagesDir, filePath))\r\n\tconst dir = path.dirname(rel)\r\n\tconst parts = dir === '.' ? [] : dir.split('/').filter(Boolean)\r\n\t// 1. Выбрасываем группы маршрутов (auth), (shop) …\r\n\t// 2. Добавляем фильтр папок, начинающихся с _\r\n\tconst filteredParts = parts.filter(\r\n\t\tpart =>\r\n\t\t\t(!part.startsWith('(') || !part.endsWith(')')) && !part.startsWith('_')\r\n\t)\r\n\tconst segments = filteredParts.map(segmentToRoute)\r\n\tconst route = '/' + segments.join('/')\r\n\treturn route === '/' ? '/' : route.replace(/\\/+/g, '/')\r\n}\r\n\r\nexport function createRouteEntry(\r\n\tfilePath: string,\r\n\tresolvedPagesDir: string,\r\n\topts: Required<Options>\r\n): RouteEntry {\r\n\tconst route = filePathToRoute(filePath, resolvedPagesDir)\r\n\tconst id = slash(path.relative(resolvedPagesDir, filePath))\r\n\t\t.replace(/\\//g, '_')\r\n\t\t.replace(/\\.[^.]+$/, '')\r\n\tconst exportType = detectExportType(filePath)\r\n\tconst loader = `() => import(${JSON.stringify(slash(filePath))})`\r\n\tconst layouts = collectLayouts(filePath, resolvedPagesDir, opts).map(\r\n\t\tlp => `() => import(${JSON.stringify(slash(lp))})`\r\n\t)\r\n\r\n\treturn {\r\n\t\tid,\r\n\t\tpath: route,\r\n\t\tfilePath: slash(filePath),\r\n\t\tloader,\r\n\t\texportType,\r\n\t\tlayouts,\r\n\t}\r\n}\r\n","import fg from 'fast-glob'\r\nimport fs from 'node:fs'\r\nimport path from 'node:path'\r\nimport type { Options } from './types/types'\r\nimport { slash } from './utils'\r\n\r\nexport async function scanPages(\r\n\tresolvedPagesDir: string,\r\n\topts: Required<Options>\r\n): Promise<string[]> {\r\n\t// pattern like /abs/path/**/page.tsx\r\n\tconst exts = opts.extensions.join('|')\r\n\tconst pattern = `${slash(resolvedPagesDir)}/**/${\r\n\t\topts.pageFileName\r\n\t}.+(${exts})`\r\n\tconst files = await fg(pattern, { dot: true })\r\n\t// return absolute normalized paths\r\n\treturn files.map((f: string) => path.resolve(f))\r\n}\r\n\r\nexport function collectLayouts(\r\n\tfilePath: string,\r\n\tresolvedPagesDir: string,\r\n\topts: Required<Options>\r\n): string[] {\r\n\tconst rel = slash(path.relative(resolvedPagesDir, filePath))\r\n\tconst dir = path.dirname(rel)\r\n\tconst parts = dir === '.' ? [] : dir.split('/').filter(Boolean)\r\n\r\n\tconst layouts: string[] = []\r\n\t// for each level from 0..parts.length include layout if exists\r\n\t// НЕ фильтруем группы маршрутов при поиске layout файлов\r\n\tfor (let i = 0; i <= parts.length; i++) {\r\n\t\tconst p = parts.slice(0, i).join('/')\r\n\t\tfor (const ext of opts.extensions) {\r\n\t\t\tconst candidate = path.resolve(\r\n\t\t\t\tresolvedPagesDir,\r\n\t\t\t\tp || '',\r\n\t\t\t\t`${opts.layoutFileName}.${ext}`\r\n\t\t\t)\r\n\t\t\tif (fs.existsSync(candidate)) {\r\n\t\t\t\tlayouts.push(candidate)\r\n\t\t\t\tbreak\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\treturn layouts\r\n}\r\n","import fs from 'node:fs'\r\nimport type { ExportType } from './types/types'\r\n\r\nexport const slash = (p: string) => p.replace(/\\\\/g, '/')\r\n\r\nexport function detectExportType(filePath: string): ExportType {\r\n\ttry {\r\n\t\tconst content = fs.readFileSync(filePath, 'utf-8')\r\n\r\n\t\t// Проверяем наличие default экспорта\r\n\t\tconst hasDefaultExport = /export\\s+default\\s+/.test(content)\r\n\r\n\t\t// Проверяем наличие любого именованного экспорта (функция, константа или класс)\r\n\t\tconst hasNamedExport = /export\\s+(const|function|class)\\s+\\w+\\s*[=(]/.test(\r\n\t\t\tcontent\r\n\t\t)\r\n\r\n\t\tif (hasDefaultExport) {\r\n\t\t\treturn 'default'\r\n\t\t} else if (hasNamedExport) {\r\n\t\t\treturn 'named'\r\n\t\t}\r\n\r\n\t\t// По умолчанию предполагаем default экспорт для обратной совместимости\r\n\t\treturn 'default'\r\n\t} catch (error) {\r\n\t\t// В случае ошибки чтения файла, предполагаем default экспорт\r\n\t\tconsole.warn(\r\n\t\t\t`[vite-plugin-file-router] Failed to read file ${filePath}:`,\r\n\t\t\terror\r\n\t\t)\r\n\t\treturn 'default'\r\n\t}\r\n}\r\n","import type { RouteEntry } from './types/types'\r\n\r\nexport function generateRouteTypes(routes: RouteEntry[]): string {\r\n\tconst routePaths = routes.map(route => `'${route.path}'`).join(' | ')\r\n\r\n\t// Извлекаем параметры из динамических маршрутов\r\n\tconst routeParams: Record<string, Record<string, string>> = {}\r\n\troutes.forEach(route => {\r\n\t\tconst params: Record<string, string> = {}\r\n\r\n\t\t// Парсим [id] параметры\r\n\t\tconst idMatches = route.path.match(/\\[([^\\]]+)\\]/g)\r\n\t\tif (idMatches) {\r\n\t\t\tidMatches.forEach(match => {\r\n\t\t\t\tconst paramName = match.slice(1, -1)\r\n\t\t\t\tif (paramName.startsWith('...')) {\r\n\t\t\t\t\t// Catch-all параметр\r\n\t\t\t\t\tparams[paramName.slice(3)] = 'string[]'\r\n\t\t\t\t} else {\r\n\t\t\t\t\tparams[paramName] = 'string'\r\n\t\t\t\t}\r\n\t\t\t})\r\n\t\t}\r\n\r\n\t\tif (Object.keys(params).length > 0) {\r\n\t\t\trouteParams[route.path] = params\r\n\t\t}\r\n\t})\r\n\r\n\tconst routeParamsType =\r\n\t\tObject.keys(routeParams).length > 0\r\n\t\t\t? `export type RouteParams = {\r\n${Object.entries(routeParams)\r\n\t.map(([path, params]) => {\r\n\t\tconst paramEntries = Object.entries(params)\r\n\t\t\t.map(([key, type]) => `${key}: ${type}`)\r\n\t\t\t.join(', ')\r\n\t\treturn ` '${path}': { ${paramEntries} }`\r\n\t})\r\n\t.join('\\n')}\r\n}`\r\n\t\t\t: 'export type RouteParams = Record<string, never>'\r\n\r\n\treturn `// Автогенерированные типы маршрутов\r\nexport type RoutePath = ${routePaths || 'never'}\r\n\r\n${routeParamsType}\r\n\r\nexport type PageProps<T extends RoutePath = RoutePath> = {\r\n params: RouteParams[T]\r\n searchParams?: Record<string, string>\r\n}\r\n\r\nexport interface LayoutProps {\r\n children: React.ReactNode\r\n}\r\n\r\nexport interface RouteInfo {\r\n id: string\r\n path: string\r\n filePath: string\r\n exportType: 'default' | 'named'\r\n layouts: string[]\r\n}\r\n\r\n// Утилиты для навигации\r\nexport function navigate<T extends RoutePath>(\r\n path: T, \r\n params?: RouteParams[T]\r\n): void {\r\n // Реализация навигации\r\n window.location.href = path\r\n}\r\n\r\nexport function useParams<T extends RoutePath>(): RouteParams[T] {\r\n // Реализация хука для получения параметров\r\n return {} as RouteParams[T]\r\n}\r\n`\r\n}\r\n\r\nexport function generateMetadataTypes(): string {\r\n\treturn `// Типы для метаданных страниц\r\nexport interface PageMetadata {\r\n title?: string\r\n description?: string\r\n keywords?: string[]\r\n author?: string\r\n changefreq?: 'always' | 'hourly' | 'daily' | 'weekly' | 'monthly' | 'yearly' | 'never'\r\n priority?: number\r\n}\r\n\r\nexport interface SEOConfig {\r\n baseUrl: string\r\n defaultTitle?: string\r\n defaultDescription?: string\r\n disallowPaths?: string[]\r\n}\r\n`\r\n}\r\n","import fs from 'node:fs'\r\n\r\nexport function createHMRHandlers(\r\n\tresolvedPagesDir: string,\r\n\tresolvedVirtualId: string,\r\n\troot: string\r\n) {\r\n\tconst configureServer = (srv: any) => {\r\n\t\tconst invalidateVirtual = async () => {\r\n\t\t\tconst mod = srv.moduleGraph?.getModuleById?.(resolvedVirtualId)\r\n\t\t\tif (mod) {\r\n\t\t\t\tsrv.moduleGraph?.invalidateModule?.(mod)\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tconst watchPath = fs.existsSync(resolvedPagesDir) ? resolvedPagesDir : root\r\n\t\tsrv.watcher?.add?.(watchPath)\r\n\r\n\t\tsrv.watcher?.on?.('add', (p: string) => {\r\n\t\t\tif (p.startsWith(resolvedPagesDir)) invalidateVirtual()\r\n\t\t})\r\n\t\tsrv.watcher?.on?.('unlink', (p: string) => {\r\n\t\t\tif (p.startsWith(resolvedPagesDir)) invalidateVirtual()\r\n\t\t})\r\n\t}\r\n\r\n\tconst handleHotUpdate = (ctx: any) => {\r\n\t\tconst f = ctx.file\r\n\t\tif (!f?.startsWith(resolvedPagesDir)) return\r\n\r\n\t\tconst mod = ctx.server.moduleGraph?.getModuleById?.(resolvedVirtualId)\r\n\t\tif (mod) {\r\n\t\t\tctx.server.moduleGraph?.invalidateModule?.(mod)\r\n\t\t\treturn [mod]\r\n\t\t}\r\n\t}\r\n\r\n\treturn { configureServer, handleHotUpdate }\r\n}\r\n","import fs from 'node:fs'\r\nimport path from 'node:path'\r\n\r\nexport async function loadGeneratedManifest(root: string): Promise<string> {\r\n\tconst manifestPath = path.join(root, 'dist', 'routes-manifest.js')\r\n\tif (fs.existsSync(manifestPath)) {\r\n\t\ttry {\r\n\t\t\tconst manifestContent = fs.readFileSync(manifestPath, 'utf-8')\r\n\t\t\tconst manifestRegex = /export const manifest = \\[.*?\\];/s\r\n\t\t\tconst manifestMatch = manifestRegex.exec(manifestContent)\r\n\t\t\tconst basePathRegex = /export const basePath = ['\"](.*?)['\"];/\r\n\t\t\tconst basePathMatch = basePathRegex.exec(manifestContent)\r\n\t\t\tconst basePath = basePathMatch ? basePathMatch[1] : '/'\r\n\t\t\t\r\n\t\t\tif (manifestMatch) {\r\n\t\t\t\treturn `// virtual routes (production mode - using generated manifest)\r\n${manifestMatch[0]}\r\nexport const basePath = ${JSON.stringify(basePath)};\r\nexport default manifest;\r\n`\r\n\t\t\t}\r\n\t\t} catch (error) {\r\n\t\t\tconsole.warn(\r\n\t\t\t\t'[vite-plugin-file-router] Failed to load generated manifest:',\r\n\t\t\t\terror\r\n\t\t\t)\r\n\t\t}\r\n\t}\r\n\r\n\t// Fallback - пустой манифест\r\n\treturn `// virtual routes (production mode - empty manifest)\r\nexport const manifest = [];\r\nexport const basePath = '/';\r\nexport default manifest;\r\n`\r\n}\r\n","import { createRouteEntry } from './route-generator'\r\nimport { scanPages } from './scanner'\r\nimport type { Options } from './types/types'\r\n\r\nexport async function generateVirtualModuleCode(\r\n\tresolvedPagesDir: string,\r\n\topts: Required<Options>\r\n): Promise<string> {\r\n\tconst pages = await scanPages(resolvedPagesDir, opts)\r\n\tconst entries = pages.map(fp => {\r\n\t\tconst entry = createRouteEntry(fp, resolvedPagesDir, opts)\r\n\t\treturn `{\r\n id: ${JSON.stringify(entry.id)},\r\n path: ${JSON.stringify(entry.path)},\r\n filePath: ${JSON.stringify(entry.filePath)},\r\n loader: ${entry.loader},\r\n exportType: ${JSON.stringify(entry.exportType)},\r\n layouts: [${entry.layouts.join(',')}]\r\n }`\r\n\t})\r\n\r\n\treturn `// Auto-generated routes manifest\r\nconst manifest = [${entries.join(',\\n')}];\r\n\r\nexport const basePath = ${JSON.stringify(opts.basePath ?? '/')};\r\n\r\nexport { manifest };\r\nexport default manifest;\r\n`\r\n}\r\n"],"mappings":"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","names":["import_node_fs","import_node_path","import_node_fs","import_node_path","fs","path","import_node_path","import_node_fs","import_node_fs","fs","fg","path","fs","path","path","path","fs","import_node_fs","fs","import_node_fs","import_node_path","path","fs","path","fs"]}
|
|
1
|
+
{"version":3,"sources":["../src/plugin.ts","../src/core/build-generator.ts","../src/core/metadata.ts","../src/core/route-generator.ts","../src/core/scanner.ts","../src/core/utils.ts","../src/core/type-generator.ts","../src/core/hmr-handlers.ts","../src/core/manifest-loader.ts","../src/core/virtual-module.ts"],"sourcesContent":["import fs from 'node:fs'\r\nimport path from 'node:path'\r\nimport type { Plugin, UserConfig } from 'vite'\r\nimport { generateSEOFiles, generateTypes } from './core/build-generator'\r\nimport { createHMRHandlers } from './core/hmr-handlers'\r\nimport { loadGeneratedManifest } from './core/manifest-loader'\r\nimport type { Options } from './core/types/types'\r\nimport { generateVirtualModuleCode } from './core/virtual-module'\r\n\r\nexport type { Options } from './core/types/types'\r\n\r\nexport function pathRushRouting(rawOpts: Options = {}): Plugin {\r\n\tconst opts: Required<Options> = {\r\n\t\tpagesDir: rawOpts.pagesDir ?? 'src/pages',\r\n\t\tpageFileName: rawOpts.pageFileName ?? 'page',\r\n\t\tlayoutFileName: rawOpts.layoutFileName ?? 'layout',\r\n\t\tloadingFileName: rawOpts.loadingFileName ?? 'loading',\r\n\t\tnotFoundFileName: rawOpts.notFoundFileName ?? 'not-found',\r\n\t\terrorFileName: rawOpts.errorFileName ?? 'error',\r\n\t\textensions: rawOpts.extensions ?? ['tsx'],\r\n\t\tbaseUrl: rawOpts.baseUrl ?? 'http://localhost:5173',\r\n\t\tbasePath: rawOpts.basePath ?? '/',\r\n\t\tdisallowPaths: rawOpts.disallowPaths ?? [],\r\n\t\tgenerateTypes: rawOpts.generateTypes ?? true,\r\n\t\tenableSEO: rawOpts.enableSEO ?? true,\r\n\t}\r\n\r\n\tconst VIRTUAL_ID = 'virtual:routes'\r\n\tconst RESOLVED_VIRTUAL_ID = '\\0' + VIRTUAL_ID\r\n\tlet root = process.cwd()\r\n\tlet resolvedPagesDir = path.resolve(root, opts.pagesDir)\r\n\r\n\tconst plugin: Plugin = {\r\n\t\tname: 'vite-plugin-file-router-mwv',\r\n\t\tenforce: 'pre',\r\n\r\n\t\t// Автоматическая настройка Vite конфигурации\r\n\t\tconfig(userConfig: UserConfig): UserConfig {\r\n\t\t\tconst existingAlias = userConfig.resolve?.alias\r\n\t\t\tconst existingExclude = userConfig.optimizeDeps?.exclude\r\n\r\n\t\t\t// Безопасно мерджим с существующей конфигурацией\r\n\t\t\treturn {\r\n\t\t\t\toptimizeDeps: {\r\n\t\t\t\t\texclude: [\r\n\t\t\t\t\t\t...(Array.isArray(existingExclude) ? existingExclude : []),\r\n\t\t\t\t\t\t'virtual:routes',\r\n\t\t\t\t\t],\r\n\t\t\t\t},\r\n\t\t\t\tresolve: {\r\n\t\t\t\t\talias: {\r\n\t\t\t\t\t\t...(typeof existingAlias === 'object' ? existingAlias : {}),\r\n\t\t\t\t\t\t'virtual:routes': 'virtual:routes',\r\n\t\t\t\t\t},\r\n\t\t\t\t},\r\n\t\t\t}\r\n\t\t},\r\n\r\n\t\tresolveId(id: string) {\r\n\t\t\tif (id === VIRTUAL_ID) return RESOLVED_VIRTUAL_ID\r\n\t\t\treturn null\r\n\t\t},\r\n\r\n\t\tasync load(id: string) {\r\n\t\t\tif (id === RESOLVED_VIRTUAL_ID) {\r\n\t\t\t\t// В production режиме проверяем существование директории pages\r\n\t\t\t\tif (!fs.existsSync(resolvedPagesDir)) {\r\n\t\t\t\t\t// В production пытаемся загрузить сгенерированный манифест\r\n\t\t\t\t\treturn await loadGeneratedManifest(root)\r\n\t\t\t\t}\r\n\r\n\t\t\t\treturn await generateVirtualModuleCode(resolvedPagesDir, opts)\r\n\t\t\t}\r\n\t\t\treturn null\r\n\t\t},\r\n\r\n\t\tasync buildStart() {\r\n\t\t\troot = process.cwd()\r\n\t\t\tresolvedPagesDir = path.resolve(root, opts.pagesDir)\r\n\r\n\t\t\tif (!fs.existsSync(resolvedPagesDir)) {\r\n\t\t\t\tconsole.warn(\r\n\t\t\t\t\t`[vite-plugin-file-router] pagesDir \"${resolvedPagesDir}\" not found.`\r\n\t\t\t\t)\r\n\t\t\t}\r\n\t\t},\r\n\r\n\t\tasync generateBundle() {\r\n\t\t\t// Проверяем существование директории pages\r\n\t\t\tif (!fs.existsSync(resolvedPagesDir)) {\r\n\t\t\t\tconsole.warn(\r\n\t\t\t\t\t`[vite-plugin-file-router] pagesDir \"${resolvedPagesDir}\" not found in production build. Skipping route generation.`\r\n\t\t\t\t)\r\n\t\t\t\treturn\r\n\t\t\t}\r\n\r\n\t\t\t// Генерируем TypeScript типы\r\n\t\t\tif (opts.generateTypes) {\r\n\t\t\t\ttry {\r\n\t\t\t\t\tawait generateTypes(resolvedPagesDir, opts)\r\n\t\t\t\t} catch (error) {\r\n\t\t\t\t\tconsole.warn(\r\n\t\t\t\t\t\t`[vite-plugin-file-router] Failed to generate types: ${error}`\r\n\t\t\t\t\t)\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\t// Генерируем SEO файлы\r\n\t\t\tif (opts.enableSEO) {\r\n\t\t\t\ttry {\r\n\t\t\t\t\tawait generateSEOFiles(resolvedPagesDir, opts)\r\n\t\t\t\t} catch (error) {\r\n\t\t\t\t\tconsole.warn(\r\n\t\t\t\t\t\t`[vite-plugin-file-router] Failed to generate SEO files: ${error}`\r\n\t\t\t\t\t)\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t},\r\n\t}\r\n\r\n\t// Добавляем HMR только если в development режиме\r\n\tif (process.env.NODE_ENV !== 'production') {\r\n\t\tconst { configureServer, handleHotUpdate } = createHMRHandlers(\r\n\t\t\tresolvedPagesDir,\r\n\t\t\tRESOLVED_VIRTUAL_ID,\r\n\t\t\troot\r\n\t\t)\r\n\t\tplugin.configureServer = configureServer\r\n\t\tplugin.handleHotUpdate = handleHotUpdate\r\n\t}\r\n\r\n\treturn plugin\r\n}\r\n","import fs from 'node:fs'\r\nimport path from 'node:path'\r\nimport { extractMetadata, generateRobots, generateSitemap } from './metadata'\r\nimport { createRouteEntry } from './route-generator'\r\nimport { scanPages } from './scanner'\r\nimport { generateMetadataTypes, generateRouteTypes } from './type-generator'\r\nimport type { Options } from './types/types'\r\n\r\nexport async function generateTypes(\r\n\tresolvedPagesDir: string,\r\n\topts: Required<Options>\r\n) {\r\n\tconst pages = await scanPages(resolvedPagesDir, opts)\r\n\tconst routes = pages.map(fp => createRouteEntry(fp, resolvedPagesDir, opts))\r\n\r\n\tconst routeTypes = generateRouteTypes(routes)\r\n\tconst metadataTypes = generateMetadataTypes()\r\n\r\n\t// Создаем директорию для типов\r\n\tconst typesDir = path.join(process.cwd(), 'dist', 'types')\r\n\tif (!fs.existsSync(typesDir)) {\r\n\t\tfs.mkdirSync(typesDir, { recursive: true })\r\n\t}\r\n\r\n\tfs.writeFileSync(path.join(typesDir, 'routes.d.ts'), routeTypes)\r\n\tfs.writeFileSync(path.join(typesDir, 'metadata.d.ts'), metadataTypes)\r\n}\r\n\r\nexport async function generateSEOFiles(\r\n\tresolvedPagesDir: string,\r\n\topts: Required<Options>\r\n) {\r\n\tconst pages = await scanPages(resolvedPagesDir, opts)\r\n\tconst routesWithMetadata = pages\r\n\t\t.map(fp => {\r\n\t\t\tconst entry = createRouteEntry(fp, resolvedPagesDir, opts)\r\n\t\t\tconst metadata = extractMetadata(fp)\r\n\t\t\treturn {\r\n\t\t\t\tpath: entry.path,\r\n\t\t\t\tmetadata: metadata || undefined,\r\n\t\t\t}\r\n\t\t})\r\n\t\t.filter(\r\n\t\t\troute =>\r\n\t\t\t\t!opts.disallowPaths.some(disallow => route.path.startsWith(disallow))\r\n\t\t)\r\n\r\n\t// Генерируем sitemap.xml и robots.txt\r\n\tconst sitemap = generateSitemap(routesWithMetadata, opts.baseUrl)\r\n\tconst robots = generateRobots(opts.baseUrl, opts.disallowPaths)\r\n\r\n\tconst distDir = path.join(process.cwd(), 'dist')\r\n\tif (!fs.existsSync(distDir)) {\r\n\t\tfs.mkdirSync(distDir, { recursive: true })\r\n\t}\r\n\r\n\tfs.writeFileSync(path.join(distDir, 'sitemap.xml'), sitemap)\r\n\tfs.writeFileSync(path.join(distDir, 'robots.txt'), robots)\r\n}\r\n","import fs from 'node:fs'\r\nimport type { PageMetadata } from './types/types'\r\n\r\nexport function extractMetadata(filePath: string): PageMetadata | null {\r\n\ttry {\r\n\t\tconst content = fs.readFileSync(filePath, 'utf-8')\r\n\r\n\t\t// Парсинг JSDoc комментариев\r\n\t\tconst jsdocMetadata = extractJSDocMetadata(content)\r\n\t\tif (jsdocMetadata) {\r\n\t\t\treturn jsdocMetadata\r\n\t\t}\r\n\r\n\t\t// Парсинг экспорта metadata\r\n\t\tconst exportMetadata = extractExportMetadata(content)\r\n\t\tif (exportMetadata) {\r\n\t\t\treturn exportMetadata\r\n\t\t}\r\n\r\n\t\treturn null\r\n\t} catch (error) {\r\n\t\tconsole.warn(\r\n\t\t\t`[vite-plugin-file-router] Failed to extract metadata from ${filePath}:`,\r\n\t\t\terror\r\n\t\t)\r\n\t\treturn null\r\n\t}\r\n}\r\n\r\nfunction extractJSDocMetadata(content: string): PageMetadata | null {\r\n\tconst jsdocMatch = content.match(/\\/\\*\\*([\\s\\S]*?)\\*\\//)\r\n\tif (!jsdocMatch) return null\r\n\r\n\tconst jsdoc = jsdocMatch[1]\r\n\tconst metadata: PageMetadata = {}\r\n\r\n\t// Парсинг JSDoc тегов\r\n\tconst titleMatch = jsdoc.match(/@title\\s+(.+)/)\r\n\tif (titleMatch) metadata.title = titleMatch[1].trim()\r\n\r\n\tconst descMatch = jsdoc.match(/@description\\s+(.+)/)\r\n\tif (descMatch) metadata.description = descMatch[1].trim()\r\n\r\n\tconst keywordsMatch = jsdoc.match(/@keywords\\s+(.+)/)\r\n\tif (keywordsMatch) {\r\n\t\tmetadata.keywords = keywordsMatch[1].split(',').map(k => k.trim())\r\n\t}\r\n\r\n\tconst authorMatch = jsdoc.match(/@author\\s+(.+)/)\r\n\tif (authorMatch) metadata.author = authorMatch[1].trim()\r\n\r\n\tconst changefreqMatch = jsdoc.match(\r\n\t\t/@changefreq\\s+(always|hourly|daily|weekly|monthly|yearly|never)/\r\n\t)\r\n\tif (changefreqMatch) {\r\n\t\tmetadata.changefreq = changefreqMatch[1] as PageMetadata['changefreq']\r\n\t}\r\n\r\n\tconst priorityMatch = jsdoc.match(/@priority\\s+([0-9.]+)/)\r\n\tif (priorityMatch) {\r\n\t\tmetadata.priority = parseFloat(priorityMatch[1])\r\n\t}\r\n\r\n\treturn Object.keys(metadata).length > 0 ? metadata : null\r\n}\r\n\r\nfunction extractExportMetadata(content: string): PageMetadata | null {\r\n\t// Ищем экспорт const metadata = { ... }\r\n\tconst metadataMatch = content.match(\r\n\t\t/export\\s+const\\s+metadata\\s*=\\s*({[\\s\\S]*?});?/\r\n\t)\r\n\tif (!metadataMatch) return null\r\n\r\n\ttry {\r\n\t\t// Безопасное выполнение кода для извлечения объекта\r\n\t\tconst metadataCode = metadataMatch[1]\r\n\t\t// Заменяем возможные импорты и функции на безопасные значения\r\n\t\tconst safeCode = metadataCode\r\n\t\t\t.replace(/import\\s+.*?from\\s+['\"][^'\"]*['\"];?/g, '')\r\n\t\t\t.replace(/require\\s*\\([^)]*\\)/g, '\"\"')\r\n\t\t\t.replace(/process\\.env\\.[A-Z_]+/g, '\"\"')\r\n\r\n\t\t// Создаем функцию для безопасного выполнения\r\n\t\tconst func = new Function(`return ${safeCode}`)\r\n\t\treturn func()\r\n\t} catch (error) {\r\n\t\tconsole.warn(\r\n\t\t\t`[vite-plugin-file-router] Failed to parse metadata export:`,\r\n\t\t\terror\r\n\t\t)\r\n\t\treturn null\r\n\t}\r\n}\r\n\r\nexport function generateSitemap(\r\n\troutes: Array<{ path: string; metadata?: PageMetadata }>,\r\n\tbaseUrl: string\r\n): string {\r\n\tconst urls = routes\r\n\t\t.map(route => {\r\n\t\t\tconst lastmod = new Date().toISOString()\r\n\t\t\tconst changefreq = route.metadata?.changefreq || 'monthly'\r\n\t\t\tconst priority = route.metadata?.priority || 0.8\r\n\r\n\t\t\treturn ` <url>\r\n <loc>${baseUrl}${route.path}</loc>\r\n <lastmod>${lastmod}</lastmod>\r\n <changefreq>${changefreq}</changefreq>\r\n <priority>${priority}</priority>\r\n </url>`\r\n\t\t})\r\n\t\t.join('\\n')\r\n\r\n\treturn `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n<urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">\r\n${urls}\r\n</urlset>`\r\n}\r\n\r\nexport function generateRobots(\r\n\tbaseUrl: string,\r\n\tdisallowPaths: string[] = []\r\n): string {\r\n\tconst disallowRules = disallowPaths\r\n\t\t.map(path => `Disallow: ${path}`)\r\n\t\t.join('\\n')\r\n\r\n\treturn `User-agent: *\r\nAllow: /\r\n${disallowRules ? `\\n${disallowRules}` : ''}\r\n\r\nSitemap: ${baseUrl}/sitemap.xml`\r\n}\r\n","import path from 'node:path'\r\nimport { collectLayouts, findSpecialFile } from './scanner'\r\nimport type { Options, RouteEntry } from './types/types'\r\nimport { detectExportType, slash } from './utils'\r\n\r\nexport function segmentToRoute(seg: string): string {\r\n\tif (/^\\[\\.{3}.+\\]$/.test(seg)) {\r\n\t\tconst name = seg.slice(4, -1)\r\n\t\treturn `:${name}(.*)`\r\n\t}\r\n\tif (/^\\[.+\\]$/.test(seg)) {\r\n\t\tconst name = seg.slice(1, -1)\r\n\t\treturn `:${name}`\r\n\t}\r\n\treturn seg\r\n}\r\n\r\nexport function filePathToRoute(\r\n\tfilePath: string,\r\n\tresolvedPagesDir: string\r\n): string {\r\n\tconst rel = slash(path.relative(resolvedPagesDir, filePath))\r\n\tconst dir = path.dirname(rel)\r\n\tconst parts = dir === '.' ? [] : dir.split('/').filter(Boolean)\r\n\t// 1. Выбрасываем группы маршрутов (auth), (shop) …\r\n\t// 2. Добавляем фильтр папок, начинающихся с _\r\n\tconst filteredParts = parts.filter(\r\n\t\tpart =>\r\n\t\t\t(!part.startsWith('(') || !part.endsWith(')')) && !part.startsWith('_')\r\n\t)\r\n\tconst segments = filteredParts.map(segmentToRoute)\r\n\tconst route = '/' + segments.join('/')\r\n\treturn route === '/' ? '/' : route.replace(/\\/+/g, '/')\r\n}\r\n\r\nexport function createRouteEntry(\r\n\tfilePath: string,\r\n\tresolvedPagesDir: string,\r\n\topts: Required<Options>\r\n): RouteEntry {\r\n\tconst route = filePathToRoute(filePath, resolvedPagesDir)\r\n\tconst id = slash(path.relative(resolvedPagesDir, filePath))\r\n\t\t.replace(/\\//g, '_')\r\n\t\t.replace(/\\.[^.]+$/, '')\r\n\tconst exportType = detectExportType(filePath)\r\n\tconst loader = `() => import(${JSON.stringify(slash(filePath))})`\r\n\tconst layouts = collectLayouts(filePath, resolvedPagesDir, opts).map(\r\n\t\tlp => `() => import(${JSON.stringify(slash(lp))})`\r\n\t)\r\n\r\n\t// Ищем специальные файлы\r\n\tconst loading = findSpecialFile(filePath, resolvedPagesDir, opts, 'loading')\r\n\tconst notFound = findSpecialFile(filePath, resolvedPagesDir, opts, 'not-found')\r\n\tconst error = findSpecialFile(filePath, resolvedPagesDir, opts, 'error')\r\n\r\n\treturn {\r\n\t\tid,\r\n\t\tpath: route,\r\n\t\tfilePath: slash(filePath),\r\n\t\tloader,\r\n\t\texportType,\r\n\t\tlayouts,\r\n\t\tloading: loading ? `() => import(${JSON.stringify(slash(loading))})` : undefined,\r\n\t\tnotFound: notFound ? `() => import(${JSON.stringify(slash(notFound))})` : undefined,\r\n\t\terror: error ? `() => import(${JSON.stringify(slash(error))})` : undefined,\r\n\t}\r\n}\r\n","import fg from 'fast-glob'\r\nimport fs from 'node:fs'\r\nimport path from 'node:path'\r\nimport type { Options } from './types/types'\r\nimport { slash } from './utils'\r\n\r\nexport async function scanPages(\r\n\tresolvedPagesDir: string,\r\n\topts: Required<Options>\r\n): Promise<string[]> {\r\n\t// pattern like /abs/path/**/page.tsx\r\n\tconst exts = opts.extensions.join('|')\r\n\tconst pattern = `${slash(resolvedPagesDir)}/**/${\r\n\t\topts.pageFileName\r\n\t}.+(${exts})`\r\n\tconst files = await fg(pattern, { dot: true })\r\n\t// return absolute normalized paths\r\n\treturn files.map((f: string) => path.resolve(f))\r\n}\r\n\r\nexport function collectLayouts(\r\n\tfilePath: string,\r\n\tresolvedPagesDir: string,\r\n\topts: Required<Options>\r\n): string[] {\r\n\tconst rel = slash(path.relative(resolvedPagesDir, filePath))\r\n\tconst dir = path.dirname(rel)\r\n\tconst parts = dir === '.' ? [] : dir.split('/').filter(Boolean)\r\n\r\n\tconst layouts: string[] = []\r\n\t// for each level from 0..parts.length include layout if exists\r\n\t// НЕ фильтруем группы маршрутов при поиске layout файлов\r\n\tfor (let i = 0; i <= parts.length; i++) {\r\n\t\tconst p = parts.slice(0, i).join('/')\r\n\t\tfor (const ext of opts.extensions) {\r\n\t\t\tconst candidate = path.resolve(\r\n\t\t\t\tresolvedPagesDir,\r\n\t\t\t\tp || '',\r\n\t\t\t\t`${opts.layoutFileName}.${ext}`\r\n\t\t\t)\r\n\t\t\tif (fs.existsSync(candidate)) {\r\n\t\t\t\tlayouts.push(candidate)\r\n\t\t\t\tbreak\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\treturn layouts\r\n}\r\n\r\n/**\r\n * Находит файл loading, not-found или error в директории страницы\r\n */\r\nexport function findSpecialFile(\r\n\tfilePath: string,\r\n\tresolvedPagesDir: string,\r\n\topts: Required<Options>,\r\n\tfileName: 'loading' | 'not-found' | 'error'\r\n): string | undefined {\r\n\tconst rel = slash(path.relative(resolvedPagesDir, filePath))\r\n\tconst dir = path.dirname(rel)\r\n\t\r\n\t// Ищем файл в той же директории, что и страница\r\n\tfor (const ext of opts.extensions) {\r\n\t\tconst candidate = path.resolve(\r\n\t\t\tresolvedPagesDir,\r\n\t\t\tdir === '.' ? '' : dir,\r\n\t\t\t`${opts[`${fileName}FileName` as keyof typeof opts]}.${ext}`\r\n\t\t)\r\n\t\tif (fs.existsSync(candidate)) {\r\n\t\t\treturn candidate\r\n\t\t}\r\n\t}\r\n\t\r\n\t// Если не найден, ищем в родительских директориях (как layouts)\r\n\tconst parts = dir === '.' ? [] : dir.split('/').filter(Boolean)\r\n\tfor (let i = parts.length; i >= 0; i--) {\r\n\t\tconst p = parts.slice(0, i).join('/')\r\n\t\tfor (const ext of opts.extensions) {\r\n\t\t\tconst candidate = path.resolve(\r\n\t\t\t\tresolvedPagesDir,\r\n\t\t\t\tp || '',\r\n\t\t\t\t`${opts[`${fileName}FileName` as keyof typeof opts]}.${ext}`\r\n\t\t\t)\r\n\t\t\tif (fs.existsSync(candidate)) {\r\n\t\t\t\treturn candidate\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t\r\n\treturn undefined\r\n}","import fs from 'node:fs'\r\nimport type { ExportType } from './types/types'\r\n\r\nexport const slash = (p: string) => p.replace(/\\\\/g, '/')\r\n\r\nexport function detectExportType(filePath: string): ExportType {\r\n\ttry {\r\n\t\tconst content = fs.readFileSync(filePath, 'utf-8')\r\n\r\n\t\t// Проверяем наличие default экспорта\r\n\t\tconst hasDefaultExport = /export\\s+default\\s+/.test(content)\r\n\r\n\t\t// Проверяем наличие любого именованного экспорта (функция, константа или класс)\r\n\t\tconst hasNamedExport = /export\\s+(const|function|class)\\s+\\w+\\s*[=(]/.test(\r\n\t\t\tcontent\r\n\t\t)\r\n\r\n\t\tif (hasDefaultExport) {\r\n\t\t\treturn 'default'\r\n\t\t} else if (hasNamedExport) {\r\n\t\t\treturn 'named'\r\n\t\t}\r\n\r\n\t\t// По умолчанию предполагаем default экспорт для обратной совместимости\r\n\t\treturn 'default'\r\n\t} catch (error) {\r\n\t\t// В случае ошибки чтения файла, предполагаем default экспорт\r\n\t\tconsole.warn(\r\n\t\t\t`[vite-plugin-file-router] Failed to read file ${filePath}:`,\r\n\t\t\terror\r\n\t\t)\r\n\t\treturn 'default'\r\n\t}\r\n}\r\n","import type { RouteEntry } from './types/types'\r\n\r\nexport function generateRouteTypes(routes: RouteEntry[]): string {\r\n\tconst routePaths = routes.map(route => `'${route.path}'`).join(' | ')\r\n\r\n\t// Извлекаем параметры из динамических маршрутов\r\n\tconst routeParams: Record<string, Record<string, string>> = {}\r\n\troutes.forEach(route => {\r\n\t\tconst params: Record<string, string> = {}\r\n\r\n\t\t// Парсим [id] параметры\r\n\t\tconst idMatches = route.path.match(/\\[([^\\]]+)\\]/g)\r\n\t\tif (idMatches) {\r\n\t\t\tidMatches.forEach(match => {\r\n\t\t\t\tconst paramName = match.slice(1, -1)\r\n\t\t\t\tif (paramName.startsWith('...')) {\r\n\t\t\t\t\t// Catch-all параметр\r\n\t\t\t\t\tparams[paramName.slice(3)] = 'string[]'\r\n\t\t\t\t} else {\r\n\t\t\t\t\tparams[paramName] = 'string'\r\n\t\t\t\t}\r\n\t\t\t})\r\n\t\t}\r\n\r\n\t\tif (Object.keys(params).length > 0) {\r\n\t\t\trouteParams[route.path] = params\r\n\t\t}\r\n\t})\r\n\r\n\tconst routeParamsType =\r\n\t\tObject.keys(routeParams).length > 0\r\n\t\t\t? `export type RouteParams = {\r\n${Object.entries(routeParams)\r\n\t.map(([path, params]) => {\r\n\t\tconst paramEntries = Object.entries(params)\r\n\t\t\t.map(([key, type]) => `${key}: ${type}`)\r\n\t\t\t.join(', ')\r\n\t\treturn ` '${path}': { ${paramEntries} }`\r\n\t})\r\n\t.join('\\n')}\r\n}`\r\n\t\t\t: 'export type RouteParams = Record<string, never>'\r\n\r\n\treturn `// Автогенерированные типы маршрутов\r\nexport type RoutePath = ${routePaths || 'never'}\r\n\r\n${routeParamsType}\r\n\r\nexport type PageProps<T extends RoutePath = RoutePath> = {\r\n params: RouteParams[T]\r\n searchParams?: Record<string, string>\r\n}\r\n\r\nexport interface LayoutProps {\r\n children: React.ReactNode\r\n}\r\n\r\nexport interface RouteInfo {\r\n id: string\r\n path: string\r\n filePath: string\r\n exportType: 'default' | 'named'\r\n layouts: string[]\r\n}\r\n\r\n// Утилиты для навигации\r\nexport function navigate<T extends RoutePath>(\r\n path: T, \r\n params?: RouteParams[T]\r\n): void {\r\n // Реализация навигации\r\n window.location.href = path\r\n}\r\n\r\nexport function useParams<T extends RoutePath>(): RouteParams[T] {\r\n // Реализация хука для получения параметров\r\n return {} as RouteParams[T]\r\n}\r\n`\r\n}\r\n\r\nexport function generateMetadataTypes(): string {\r\n\treturn `// Типы для метаданных страниц\r\nexport interface PageMetadata {\r\n title?: string\r\n description?: string\r\n keywords?: string[]\r\n author?: string\r\n changefreq?: 'always' | 'hourly' | 'daily' | 'weekly' | 'monthly' | 'yearly' | 'never'\r\n priority?: number\r\n}\r\n\r\nexport interface SEOConfig {\r\n baseUrl: string\r\n defaultTitle?: string\r\n defaultDescription?: string\r\n disallowPaths?: string[]\r\n}\r\n`\r\n}\r\n","import fs from 'node:fs'\r\n\r\nexport function createHMRHandlers(\r\n\tresolvedPagesDir: string,\r\n\tresolvedVirtualId: string,\r\n\troot: string\r\n) {\r\n\tconst configureServer = (srv: any) => {\r\n\t\tconst invalidateVirtual = async () => {\r\n\t\t\tconst mod = srv.moduleGraph?.getModuleById?.(resolvedVirtualId)\r\n\t\t\tif (mod) {\r\n\t\t\t\tsrv.moduleGraph?.invalidateModule?.(mod)\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tconst watchPath = fs.existsSync(resolvedPagesDir) ? resolvedPagesDir : root\r\n\t\tsrv.watcher?.add?.(watchPath)\r\n\r\n\t\tsrv.watcher?.on?.('add', (p: string) => {\r\n\t\t\tif (p.startsWith(resolvedPagesDir)) invalidateVirtual()\r\n\t\t})\r\n\t\tsrv.watcher?.on?.('unlink', (p: string) => {\r\n\t\t\tif (p.startsWith(resolvedPagesDir)) invalidateVirtual()\r\n\t\t})\r\n\t}\r\n\r\n\tconst handleHotUpdate = (ctx: any) => {\r\n\t\tconst f = ctx.file\r\n\t\tif (!f?.startsWith(resolvedPagesDir)) return\r\n\r\n\t\tconst mod = ctx.server.moduleGraph?.getModuleById?.(resolvedVirtualId)\r\n\t\tif (mod) {\r\n\t\t\tctx.server.moduleGraph?.invalidateModule?.(mod)\r\n\t\t\treturn [mod]\r\n\t\t}\r\n\t}\r\n\r\n\treturn { configureServer, handleHotUpdate }\r\n}\r\n","import fs from 'node:fs'\r\nimport path from 'node:path'\r\n\r\nexport async function loadGeneratedManifest(root: string): Promise<string> {\r\n\tconst manifestPath = path.join(root, 'dist', 'routes-manifest.js')\r\n\tif (fs.existsSync(manifestPath)) {\r\n\t\ttry {\r\n\t\t\tconst manifestContent = fs.readFileSync(manifestPath, 'utf-8')\r\n\t\t\tconst manifestRegex = /export const manifest = \\[.*?\\];/s\r\n\t\t\tconst manifestMatch = manifestRegex.exec(manifestContent)\r\n\t\t\tconst basePathRegex = /export const basePath = ['\"](.*?)['\"];/\r\n\t\t\tconst basePathMatch = basePathRegex.exec(manifestContent)\r\n\t\t\tconst basePath = basePathMatch ? basePathMatch[1] : '/'\r\n\t\t\t\r\n\t\t\tif (manifestMatch) {\r\n\t\t\t\treturn `// virtual routes (production mode - using generated manifest)\r\n${manifestMatch[0]}\r\nexport const basePath = ${JSON.stringify(basePath)};\r\nexport default manifest;\r\n`\r\n\t\t\t}\r\n\t\t} catch (error) {\r\n\t\t\tconsole.warn(\r\n\t\t\t\t'[vite-plugin-file-router] Failed to load generated manifest:',\r\n\t\t\t\terror\r\n\t\t\t)\r\n\t\t}\r\n\t}\r\n\r\n\t// Fallback - пустой манифест\r\n\treturn `// virtual routes (production mode - empty manifest)\r\nexport const manifest = [];\r\nexport const basePath = '/';\r\nexport default manifest;\r\n`\r\n}\r\n","import { createRouteEntry } from './route-generator'\r\nimport { scanPages } from './scanner'\r\nimport type { Options } from './types/types'\r\n\r\nexport async function generateVirtualModuleCode(\r\n\tresolvedPagesDir: string,\r\n\topts: Required<Options>\r\n): Promise<string> {\r\n\tconst pages = await scanPages(resolvedPagesDir, opts)\r\n\tconst entries = pages.map(fp => {\r\n\t\tconst entry = createRouteEntry(fp, resolvedPagesDir, opts)\r\n\t\treturn `{\r\n id: ${JSON.stringify(entry.id)},\r\n path: ${JSON.stringify(entry.path)},\r\n filePath: ${JSON.stringify(entry.filePath)},\r\n loader: ${entry.loader},\r\n exportType: ${JSON.stringify(entry.exportType)},\r\n layouts: [${entry.layouts.join(',')}],\r\n ${entry.loading ? `loading: ${entry.loading},` : ''}\r\n ${entry.notFound ? `notFound: ${entry.notFound},` : ''}\r\n ${entry.error ? `error: ${entry.error},` : ''}\r\n }`\r\n\t})\r\n\r\n\t// Ищем глобальный not-found в корне pages\r\n\tlet globalNotFound: string | undefined\r\n\tfor (const ext of opts.extensions) {\r\n\t\tconst notFoundPath = path.resolve(\r\n\t\t\tresolvedPagesDir,\r\n\t\t\t`${opts.notFoundFileName}.${ext}`\r\n\t\t)\r\n\t\tif (fs.existsSync(notFoundPath)) {\r\n\t\t\tglobalNotFound = `() => import(${JSON.stringify(slash(notFoundPath))})`\r\n\t\t\tbreak\r\n\t\t}\r\n\t}\r\n\r\n\treturn `// Auto-generated routes manifest\r\nconst manifest = [${entries.join(',\\n')}];\r\n\r\nexport const basePath = ${JSON.stringify(opts.basePath ?? '/')};\r\n${globalNotFound ? `export const globalNotFound = ${globalNotFound};` : 'export const globalNotFound = undefined;'}\r\n\r\nexport { manifest };\r\nexport default manifest;\r\n`\r\n}\r\n"],"mappings":"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","names":["import_node_fs","import_node_path","import_node_fs","import_node_path","fs","path","import_node_path","import_node_fs","import_node_fs","slash","fs","slash","fg","path","fs","slash","path","path","path","fs","import_node_fs","fs","import_node_fs","import_node_path","path","fs","path","fs"]}
|