navilo 1.2.2 → 1.2.4

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/README.md CHANGED
@@ -31,13 +31,17 @@ Navilo automatically generates a route tree from your `src/app` (or custom) dire
31
31
  ## Quick Start
32
32
 
33
33
  ### Vite Config
34
+
34
35
  1. Install react router dom since its our peer dependency
36
+
35
37
  ```bash
36
38
  npm install react-router-dom@6.16.0
37
39
 
38
- ```ts
40
+ ```
41
+
39
42
  2.Add the navilo to plugin in vite config
40
43
 
44
+ ```ts
41
45
  // vite.config.ts
42
46
  import {defineConfig} from 'vite';
43
47
  import react from '@vitejs/plugin-react';
package/dist/index.js CHANGED
@@ -50,7 +50,7 @@ var DEFAULT_OPTIONS = {
50
50
  pagesDir: "src/app",
51
51
  typescript: true
52
52
  };
53
- var VIRTUAL_ROUTE_MODULE_ID = "virtual:preluder-routes";
53
+ var VIRTUAL_ROUTE_MODULE_ID = "virtual:navilo-routes";
54
54
  var RESOLVED_VIRTUAL_ROUTE_MODULE_ID = "\0" + VIRTUAL_ROUTE_MODULE_ID;
55
55
 
56
56
  // src/generator/createRoutes.ts
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/plugin.ts","../src/constants.ts","../src/generator/createRoutes.ts","../src/generator/parser/segmentParser.ts","../src/generator/parser/routeTreeBuilder.ts","../src/generator/parser/routeDefinitionGenerator.ts"],"sourcesContent":["export { navilo } from './plugin';\n\nexport type {\n RouteFile,\n RouteType,\n RouteNode,\n ParserOptions\n} from './types';\n\nexport {\n normalizeFilePath,\n getRouteType,\n getComponentName,\n findRouteFiles\n} from './generator/createRoutes';\n\nexport { SegmentParser } from './generator/parser/segmentParser';\nexport { RouteTreeBuilder } from './generator/parser/routeTreeBuilder';\nexport { RouteDefinitionGenerator } from './generator/parser/routeDefinitionGenerator';","// src/plugin.ts\nimport { Plugin } from 'vite';\nimport path from 'path';\nimport fs from 'fs';\nimport { DEFAULT_OPTIONS, RESOLVED_VIRTUAL_ROUTE_MODULE_ID, VIRTUAL_ROUTE_MODULE_ID } from './constants';\nimport {naviloOptions, RouteFile} from './types';\nimport { findRouteFiles } from './generator/createRoutes';\nimport {RouteTreeBuilder} from \"./generator/parser/routeTreeBuilder\";\nimport {RouteDefinitionGenerator} from \"./generator/parser/routeDefinitionGenerator\";\n\nexport function navilo(options: naviloOptions = {}): Plugin {\n const resolvedOptions = { ...DEFAULT_OPTIONS, ...options };\n let root: string;\n const routeTreeBuilder = new RouteTreeBuilder();\n\n return {\n name: 'navilo',\n\n configResolved(config) {\n root = config.root;\n },\n\n configureServer(server) {\n const pagesDir = path.resolve(root, resolvedOptions.pagesDir);\n\n server.watcher.add(pagesDir);\n\n const handleFileChange = (file: string) => {\n if (file.startsWith(pagesDir)) {\n const module = server.moduleGraph.getModuleById(RESOLVED_VIRTUAL_ROUTE_MODULE_ID);\n if (module) {\n server.moduleGraph.invalidateModule(module);\n }\n server.ws.send({ type: 'full-reload' });\n }\n };\n\n server.watcher.on('add', handleFileChange);\n server.watcher.on('unlink', handleFileChange);\n server.watcher.on('change', handleFileChange);\n },\n\n resolveId(id) {\n if (id === VIRTUAL_ROUTE_MODULE_ID) {\n return RESOLVED_VIRTUAL_ROUTE_MODULE_ID;\n }\n },\n\n async load(id) {\n if (id === RESOLVED_VIRTUAL_ROUTE_MODULE_ID) {\n const pagesDir = path.resolve(root, resolvedOptions.pagesDir);\n\n if (!fs.existsSync(pagesDir)) {\n fs.mkdirSync(pagesDir, { recursive: true });\n return `export const router = null;`;\n }\n\n const routes = await findRouteFiles(pagesDir);\n\n if (routes.length === 0) {\n return `export const router = null;`;\n }\n\n const routeTree = routeTreeBuilder.build(routes, {\n strict: true,\n dynamicSegmentTransform: (segment) => `:${segment.toLowerCase()}`\n });\n\n const routeDefinitions = RouteDefinitionGenerator.generate(routeTree);\n\n return routerJSX(routes, routeDefinitions);\n }\n }\n };\n}\n\nexport function routerJSX(routes: RouteFile[], routeDefinitions: string): string {\n const importMap = new Map<string, string>();\n routes.forEach(route => importMap.set(route.filePath, route.componentName));\n\n const imports = Array.from(importMap.entries())\n .map(([filePath, componentName]) => `import ${componentName} from '${filePath}';`)\n .join('\\n');\n\n return `\nimport React, { Suspense } from 'react';\nimport { createBrowserRouter, useParams, Outlet, useRouteError, isRouteErrorResponse } from 'react-router-dom';\n${imports}\n\nfunction ErrorBoundary({ Component }) {\n const error = useRouteError();\n const params = useParams();\n\n if (!Component) {\n return React.createElement('div', { className: 'error-container' },\n React.createElement('div', { className: 'error-content' }, [\n React.createElement('h1', null, \n isRouteErrorResponse(error) ? \\`\\${error.status} - \\${error.statusText}\\` : 'Error'\n ),\n React.createElement('pre', { className: 'error-stack' },\n error instanceof Error ? error.stack : JSON.stringify(error, null, 2)\n ),\n React.createElement('button', {\n onClick: () => window.location.reload()\n }, 'Try again')\n ])\n );\n }\n\n return React.createElement(Component, { error, params });\n}\n\nfunction LoadingBoundary({ Component, children }) {\n if (!Component) {\n return children;\n }\n\n return React.createElement(Suspense, {\n fallback: React.createElement(Component)\n }, children);\n}\n\nfunction RouteWrapper({ Component, isLayout, loading, notFound }) {\n const params = useParams();\n \n if (isLayout) {\n const outlet = React.createElement(Outlet);\n const content = loading ? \n React.createElement(LoadingBoundary, { Component: loading }, outlet) :\n outlet;\n\n return React.createElement(Component, {\n children: content,\n params\n });\n }\n \n return React.createElement(Component, { params });\n}\n\n// Add global error listener\nwindow.addEventListener('error', (event) => {\n console.error('Global error:', event.error);\n});\n\n// Add global promise rejection handler\nwindow.addEventListener('unhandledrejection', (event) => {\n console.error('Unhandled promise rejection:', event.reason);\n});\n\nconst router = createBrowserRouter([\n${routeDefinitions}\n], {\n defaultErrorElement: React.createElement(ErrorBoundary, { Component: ${routes.find(r => r.type === 'not-found')?.componentName || 'null'} })\n});\n\nexport { router };\n`;\n}","export const DEFAULT_OPTIONS = {\n pagesDir: 'src/app',\n typescript: true,\n};\n\nexport const VIRTUAL_ROUTE_MODULE_ID = 'virtual:preluder-routes';\nexport const RESOLVED_VIRTUAL_ROUTE_MODULE_ID = '\\0' + VIRTUAL_ROUTE_MODULE_ID;","import path from 'path';\nimport glob from 'fast-glob';\nimport { RouteFile, RouteType } from '../types';\n\n/** Normalize Windows paths to forward slashes */\nexport function normalizeFilePath(filePath: string): string {\n return filePath.replace(/\\\\/g, '/');\n}\n\n/** Determine the type of a route file */\nexport function getRouteType(filePath: string): RouteType {\n const basename = path.basename(filePath);\n const fileTypes: Record<string, RouteType> = {\n 'layout.jsx': 'layout',\n 'layout.tsx': 'layout',\n 'page.jsx': 'page',\n 'page.tsx': 'page',\n 'error.jsx': 'error',\n 'error.tsx': 'error',\n 'loading.jsx': 'loading',\n 'loading.tsx': 'loading',\n 'not-found.jsx': 'not-found',\n 'not-found.tsx': 'not-found'\n };\n return fileTypes[basename] || 'page';\n}\n\n/** Generate a PascalCase component name based on folder structure */\nexport function getComponentName(filePath: string, pagesDir: string): string {\n const segments = normalizeFilePath(path.relative(pagesDir, filePath)).split('/');\n const fileNameWithExt = segments.pop()!;\n const fileName = path.basename(fileNameWithExt, path.extname(fileNameWithExt));\n\n const relevantSegments = segments.map(segment => {\n if (segment.startsWith('[') && segment.endsWith(']')) {\n return segment.slice(1, -1)\n .replace(/^\\.\\.\\./, 'CatchAll')\n .split(/[^a-zA-Z0-9]/)\n .map(p => p.charAt(0).toUpperCase() + p.slice(1))\n .join('');\n }\n return segment\n .split(/[^a-zA-Z0-9]/)\n .map(p => p.charAt(0).toUpperCase() + p.slice(1))\n .join('');\n });\n\n const typeSuffix = {\n page: 'Page',\n layout: 'Layout',\n error: 'Error',\n loading: 'Loading',\n 'not-found': 'NotFound'\n }[fileName] || 'Component';\n\n return relevantSegments.length === 0 ? `Root${typeSuffix}` : `${relevantSegments.join('')}${typeSuffix}`;\n}\n\n/** Extract segments from file path for building route tree */\nexport function getPathSegments(filePath: string, pagesDir: string): string[] {\n const relativePath = normalizeFilePath(path.relative(pagesDir, filePath));\n const segments = relativePath.split('/');\n const fileName = segments.pop()!;\n\n const filteredSegments = segments.filter(seg => !(seg.startsWith('(') && seg.endsWith(')')));\n\n if (/^page\\.(jsx|tsx)$/.test(fileName)) {\n filteredSegments.push('');\n }\n\n return filteredSegments;\n}\n\n/** Find all route files in the pages directory */\nexport async function findRouteFiles(pagesDir: string): Promise<RouteFile[]> {\n const files = await glob(['**/*.{jsx,tsx}'], {\n cwd: pagesDir,\n absolute: true,\n ignore: ['**/node_modules/**', '**/.*/**', '**/_*/**'],\n });\n\n const validFiles = files.filter(file => {\n const base = path.basename(file);\n return /^(layout|page|error|loading|not-found)\\.(jsx|tsx)$/.test(base);\n });\n\n return validFiles.map(file => {\n const type = getRouteType(file);\n return {\n type,\n path: '/' + normalizeFilePath(path.relative(pagesDir, path.dirname(file))),\n filePath: normalizeFilePath(file),\n componentName: getComponentName(file, pagesDir),\n segments: getPathSegments(file, pagesDir),\n };\n });\n}\n","import {ParserOptions} from \"../../types\";\n\nexport class SegmentParser {\n private static readonly SEGMENT_PATTERNS = {\n OPTIONAL_CATCH_ALL: /^\\[\\[\\.{3}(.+)\\]\\]$/,\n CATCH_ALL: /^\\[\\.{3}(.+)\\]$/,\n DYNAMIC: /^\\[(.+)\\]$/,\n GROUP: /^\\((.+)\\)$/\n };\n\n static normalize(segment: string, options?: ParserOptions): string | null {\n if (this.isGroupSegment(segment)) return null;\n\n if (segment.includes('/')) {\n return segment.split('/')\n .map(seg => this.normalizeSegment(seg, options))\n .filter(Boolean)\n .join('/');\n }\n\n return this.normalizeSegment(segment, options);\n }\n\n private static normalizeSegment(segment: string, options?: ParserOptions): string | null {\n const transform = options?.dynamicSegmentTransform || this.defaultTransform;\n\n if (this.isOptionalCatchAll(segment)) {\n const name = segment.match(this.SEGMENT_PATTERNS.OPTIONAL_CATCH_ALL)![1];\n return transform(`${name}*?`);\n }\n\n if (this.isCatchAll(segment)) {\n const name = segment.match(this.SEGMENT_PATTERNS.CATCH_ALL)![1];\n return transform(`${name}*`);\n }\n\n if (this.isDynamicSegment(segment)) {\n const name = segment.match(this.SEGMENT_PATTERNS.DYNAMIC)![1];\n return transform(name);\n }\n\n return segment;\n }\n\n private static defaultTransform(name: string): string {\n return `:${name}`;\n }\n\n private static isGroupSegment(segment: string): boolean {\n return this.SEGMENT_PATTERNS.GROUP.test(segment);\n }\n\n private static isOptionalCatchAll(segment: string): boolean {\n return this.SEGMENT_PATTERNS.OPTIONAL_CATCH_ALL.test(segment);\n }\n\n private static isCatchAll(segment: string): boolean {\n return this.SEGMENT_PATTERNS.CATCH_ALL.test(segment);\n }\n\n private static isDynamicSegment(segment: string): boolean {\n return this.SEGMENT_PATTERNS.DYNAMIC.test(segment);\n }\n}","import {SegmentParser} from './segmentParser';\nimport {ParserOptions, RouteFile, RouteNode} from \"../../types\";\n\nexport class RouteTreeBuilder {\n private readonly typeSetters: Record<string, (node: RouteNode, route: RouteFile) => void>;\n\n constructor() {\n this.typeSetters = {\n layout: (node, route) => {\n node.layout = route.componentName;\n },\n error: (node, route) => {\n node.error = route.componentName;\n },\n loading: (node, route) => {\n node.loading = route.componentName;\n },\n 'not-found': (node, route) => {\n node.notFound = route.componentName;\n },\n page: this.handlePageType.bind(this)\n };\n }\n\n build(routes: RouteFile[], options?: ParserOptions): RouteNode {\n const root: RouteNode = {\n segment: '',\n path: '/',\n fullPath: '/',\n children: new Map(),\n metadata: options?.metadata\n };\n\n const sortedRoutes = this.sortRoutes(routes);\n sortedRoutes.forEach(route => {\n this.processRoute(root, route, options);\n });\n\n return root;\n }\n\n private sortRoutes(routes: RouteFile[]): RouteFile[] {\n return [...routes].sort((a, b) =>\n a.type === 'layout' && b.type !== 'layout' ? -1 :\n a.type !== 'layout' && b.type === 'layout' ? 1 : 0\n );\n }\n\n private processRoute(root: RouteNode, route: RouteFile, options?: ParserOptions): void {\n const segments = route.segments.map(seg => String(seg));\n\n if (segments.length === 0) {\n this.applyTypeHandler(root, route);\n if (route.type === 'page') root.isIndex = true;\n return;\n }\n\n let current = root;\n let currentPath = '';\n\n segments.forEach((seg, idx) => {\n const isLast = idx === segments.length - 1;\n const key = SegmentParser.normalize(seg, options);\n\n if (key === null) return;\n\n currentPath = this.buildFullPath(currentPath, key);\n\n if (!current.children.has(key)) {\n current.children.set(key, {\n segment: key,\n path: key,\n fullPath: currentPath,\n children: new Map(),\n metadata: options?.metadata\n });\n }\n\n current = current.children.get(key)!;\n\n if (isLast) this.applyTypeHandler(current, route);\n });\n }\n\n private buildFullPath(currentPath: string, key: string): string {\n if (currentPath === '' || currentPath === '/') {\n return key === '' ? '/' : `/${key}`;\n }\n return `${currentPath}/${key}`;\n }\n\n private applyTypeHandler(node: RouteNode, route: RouteFile): void {\n const handler = this.typeSetters[route.type];\n if (handler) handler(node, route);\n }\n\n private handlePageType(node: RouteNode, route: RouteFile): void {\n const lastSegment = route.segments[route.segments.length - 1];\n const isDynamic = lastSegment?.startsWith('[');\n\n if (isDynamic || lastSegment === '') {\n node.component = route.componentName;\n node.isIndex = false;\n } else {\n node.indexPage = route.componentName;\n }\n }\n}","import { RouteNode } from \"../../types\";\n\nexport class RouteDefinitionGenerator {\n static generate(node: RouteNode, indent = ' '): string {\n const childNodes = Array.from(node.children.values());\n const children: string[] = [];\n\n if (node.indexPage) {\n children.push(this.generateIndexRoute(node, indent));\n }\n\n children.push(...childNodes.map(child =>\n this.generate(child, indent + ' ')\n ));\n\n return this.generateRouteObject(node, children, indent);\n }\n\n private static generateIndexRoute(node: RouteNode, indent: string): string {\n return `${indent} {\n${indent} index: true,\n${indent} element: React.createElement(RouteWrapper, {\n${indent} Component: ${node.indexPage}\n${indent} })\n${indent} }`;\n }\n\n private static generateRouteObject(node: RouteNode, children: string[], indent: string): string {\n const pathStr = node.fullPath;\n const elementStr = this.generateElementString(node, indent);\n const errorStr = this.generateErrorString(node, indent);\n\n return [\n `${indent}{`,\n `${indent} path: '${pathStr}'${elementStr}${errorStr}`,\n children.length > 0 ? `,\\n${indent} children: [\\n${children.join(',\\n')}\\n${indent} ]` : '',\n `${indent}}`\n ].filter(Boolean).join('');\n }\n\n private static generateElementString(node: RouteNode, indent: string): string {\n if (!node.layout && !node.component) return '';\n\n const props = node.layout\n ? this.generateLayoutProps(node, indent)\n : this.generateComponentProps(node, indent);\n\n return `,\\n${indent} element: React.createElement(RouteWrapper, ${props})`;\n }\n\n private static generateLayoutProps(node: RouteNode, indent: string): string {\n return `{\n${indent} Component: ${node.layout},\n${indent} isLayout: true,\n${indent} loading: ${node.loading || 'undefined'},\n${indent} notFound: ${node.notFound || 'undefined'}\n${indent} }`;\n }\n\n private static generateComponentProps(node: RouteNode, indent: string): string {\n return `{\n${indent} Component: ${node.component}\n${indent} }`;\n }\n\n private static generateErrorString(node: RouteNode, indent: string): string {\n if (!node.error) return '';\n\n return `,\\n${indent} errorElement: React.createElement(ErrorBoundary, {\n${indent} Component: ${node.error}\n${indent} })`;\n }\n}"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACEA,IAAAA,eAAiB;AACjB,gBAAe;;;ACHR,IAAM,kBAAkB;AAAA,EAC3B,UAAU;AAAA,EACV,YAAY;AAChB;AAEO,IAAM,0BAA0B;AAChC,IAAM,mCAAmC,OAAO;;;ACNvD,kBAAiB;AACjB,uBAAiB;AAIV,SAAS,kBAAkB,UAA0B;AACxD,SAAO,SAAS,QAAQ,OAAO,GAAG;AACtC;AAGO,SAAS,aAAa,UAA6B;AACtD,QAAM,WAAW,YAAAC,QAAK,SAAS,QAAQ;AACvC,QAAM,YAAuC;AAAA,IACzC,cAAc;AAAA,IACd,cAAc;AAAA,IACd,YAAY;AAAA,IACZ,YAAY;AAAA,IACZ,aAAa;AAAA,IACb,aAAa;AAAA,IACb,eAAe;AAAA,IACf,eAAe;AAAA,IACf,iBAAiB;AAAA,IACjB,iBAAiB;AAAA,EACrB;AACA,SAAO,UAAU,QAAQ,KAAK;AAClC;AAGO,SAAS,iBAAiB,UAAkB,UAA0B;AACzE,QAAM,WAAW,kBAAkB,YAAAA,QAAK,SAAS,UAAU,QAAQ,CAAC,EAAE,MAAM,GAAG;AAC/E,QAAM,kBAAkB,SAAS,IAAI;AACrC,QAAM,WAAW,YAAAA,QAAK,SAAS,iBAAiB,YAAAA,QAAK,QAAQ,eAAe,CAAC;AAE7E,QAAM,mBAAmB,SAAS,IAAI,aAAW;AAC7C,QAAI,QAAQ,WAAW,GAAG,KAAK,QAAQ,SAAS,GAAG,GAAG;AAClD,aAAO,QAAQ,MAAM,GAAG,EAAE,EACrB,QAAQ,WAAW,UAAU,EAC7B,MAAM,cAAc,EACpB,IAAI,OAAK,EAAE,OAAO,CAAC,EAAE,YAAY,IAAI,EAAE,MAAM,CAAC,CAAC,EAC/C,KAAK,EAAE;AAAA,IAChB;AACA,WAAO,QACF,MAAM,cAAc,EACpB,IAAI,OAAK,EAAE,OAAO,CAAC,EAAE,YAAY,IAAI,EAAE,MAAM,CAAC,CAAC,EAC/C,KAAK,EAAE;AAAA,EAChB,CAAC;AAED,QAAM,aAAa;AAAA,IACf,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,OAAO;AAAA,IACP,SAAS;AAAA,IACT,aAAa;AAAA,EACjB,EAAE,QAAQ,KAAK;AAEf,SAAO,iBAAiB,WAAW,IAAI,OAAO,UAAU,KAAK,GAAG,iBAAiB,KAAK,EAAE,CAAC,GAAG,UAAU;AAC1G;AAGO,SAAS,gBAAgB,UAAkB,UAA4B;AAC1E,QAAM,eAAe,kBAAkB,YAAAA,QAAK,SAAS,UAAU,QAAQ,CAAC;AACxE,QAAM,WAAW,aAAa,MAAM,GAAG;AACvC,QAAM,WAAW,SAAS,IAAI;AAE9B,QAAM,mBAAmB,SAAS,OAAO,SAAO,EAAE,IAAI,WAAW,GAAG,KAAK,IAAI,SAAS,GAAG,EAAE;AAE3F,MAAI,oBAAoB,KAAK,QAAQ,GAAG;AACpC,qBAAiB,KAAK,EAAE;AAAA,EAC5B;AAEA,SAAO;AACX;AAGA,eAAsB,eAAe,UAAwC;AACzE,QAAM,QAAQ,UAAM,iBAAAC,SAAK,CAAC,gBAAgB,GAAG;AAAA,IACzC,KAAK;AAAA,IACL,UAAU;AAAA,IACV,QAAQ,CAAC,sBAAsB,YAAY,UAAU;AAAA,EACzD,CAAC;AAED,QAAM,aAAa,MAAM,OAAO,UAAQ;AACpC,UAAM,OAAO,YAAAD,QAAK,SAAS,IAAI;AAC/B,WAAO,qDAAqD,KAAK,IAAI;AAAA,EACzE,CAAC;AAED,SAAO,WAAW,IAAI,UAAQ;AAC1B,UAAM,OAAO,aAAa,IAAI;AAC9B,WAAO;AAAA,MACH;AAAA,MACA,MAAM,MAAM,kBAAkB,YAAAA,QAAK,SAAS,UAAU,YAAAA,QAAK,QAAQ,IAAI,CAAC,CAAC;AAAA,MACzE,UAAU,kBAAkB,IAAI;AAAA,MAChC,eAAe,iBAAiB,MAAM,QAAQ;AAAA,MAC9C,UAAU,gBAAgB,MAAM,QAAQ;AAAA,IAC5C;AAAA,EACJ,CAAC;AACL;;;AC9FO,IAAM,gBAAN,MAAoB;AAAA,EAQvB,OAAO,UAAU,SAAiB,SAAwC;AACtE,QAAI,KAAK,eAAe,OAAO;AAAG,aAAO;AAEzC,QAAI,QAAQ,SAAS,GAAG,GAAG;AACvB,aAAO,QAAQ,MAAM,GAAG,EACnB,IAAI,SAAO,KAAK,iBAAiB,KAAK,OAAO,CAAC,EAC9C,OAAO,OAAO,EACd,KAAK,GAAG;AAAA,IACjB;AAEA,WAAO,KAAK,iBAAiB,SAAS,OAAO;AAAA,EACjD;AAAA,EAEA,OAAe,iBAAiB,SAAiB,SAAwC;AACrF,UAAM,YAAY,SAAS,2BAA2B,KAAK;AAE3D,QAAI,KAAK,mBAAmB,OAAO,GAAG;AAClC,YAAM,OAAO,QAAQ,MAAM,KAAK,iBAAiB,kBAAkB,EAAG,CAAC;AACvE,aAAO,UAAU,GAAG,IAAI,IAAI;AAAA,IAChC;AAEA,QAAI,KAAK,WAAW,OAAO,GAAG;AAC1B,YAAM,OAAO,QAAQ,MAAM,KAAK,iBAAiB,SAAS,EAAG,CAAC;AAC9D,aAAO,UAAU,GAAG,IAAI,GAAG;AAAA,IAC/B;AAEA,QAAI,KAAK,iBAAiB,OAAO,GAAG;AAChC,YAAM,OAAO,QAAQ,MAAM,KAAK,iBAAiB,OAAO,EAAG,CAAC;AAC5D,aAAO,UAAU,IAAI;AAAA,IACzB;AAEA,WAAO;AAAA,EACX;AAAA,EAEA,OAAe,iBAAiB,MAAsB;AAClD,WAAO,IAAI,IAAI;AAAA,EACnB;AAAA,EAEA,OAAe,eAAe,SAA0B;AACpD,WAAO,KAAK,iBAAiB,MAAM,KAAK,OAAO;AAAA,EACnD;AAAA,EAEA,OAAe,mBAAmB,SAA0B;AACxD,WAAO,KAAK,iBAAiB,mBAAmB,KAAK,OAAO;AAAA,EAChE;AAAA,EAEA,OAAe,WAAW,SAA0B;AAChD,WAAO,KAAK,iBAAiB,UAAU,KAAK,OAAO;AAAA,EACvD;AAAA,EAEA,OAAe,iBAAiB,SAA0B;AACtD,WAAO,KAAK,iBAAiB,QAAQ,KAAK,OAAO;AAAA,EACrD;AACJ;AA7Da,cACe,mBAAmB;AAAA,EACvC,oBAAoB;AAAA,EACpB,WAAW;AAAA,EACX,SAAS;AAAA,EACT,OAAO;AACX;;;ACLG,IAAM,mBAAN,MAAuB;AAAA,EAG1B,cAAc;AACV,SAAK,cAAc;AAAA,MACf,QAAQ,CAAC,MAAM,UAAU;AACrB,aAAK,SAAS,MAAM;AAAA,MACxB;AAAA,MACA,OAAO,CAAC,MAAM,UAAU;AACpB,aAAK,QAAQ,MAAM;AAAA,MACvB;AAAA,MACA,SAAS,CAAC,MAAM,UAAU;AACtB,aAAK,UAAU,MAAM;AAAA,MACzB;AAAA,MACA,aAAa,CAAC,MAAM,UAAU;AAC1B,aAAK,WAAW,MAAM;AAAA,MAC1B;AAAA,MACA,MAAM,KAAK,eAAe,KAAK,IAAI;AAAA,IACvC;AAAA,EACJ;AAAA,EAEA,MAAM,QAAqB,SAAoC;AAC3D,UAAM,OAAkB;AAAA,MACpB,SAAS;AAAA,MACT,MAAM;AAAA,MACN,UAAU;AAAA,MACV,UAAU,oBAAI,IAAI;AAAA,MAClB,UAAU,SAAS;AAAA,IACvB;AAEA,UAAM,eAAe,KAAK,WAAW,MAAM;AAC3C,iBAAa,QAAQ,WAAS;AAC1B,WAAK,aAAa,MAAM,OAAO,OAAO;AAAA,IAC1C,CAAC;AAED,WAAO;AAAA,EACX;AAAA,EAEQ,WAAW,QAAkC;AACjD,WAAO,CAAC,GAAG,MAAM,EAAE;AAAA,MAAK,CAAC,GAAG,MACxB,EAAE,SAAS,YAAY,EAAE,SAAS,WAAW,KACzC,EAAE,SAAS,YAAY,EAAE,SAAS,WAAW,IAAI;AAAA,IACzD;AAAA,EACJ;AAAA,EAEQ,aAAa,MAAiB,OAAkB,SAA+B;AACnF,UAAM,WAAW,MAAM,SAAS,IAAI,SAAO,OAAO,GAAG,CAAC;AAEtD,QAAI,SAAS,WAAW,GAAG;AACvB,WAAK,iBAAiB,MAAM,KAAK;AACjC,UAAI,MAAM,SAAS;AAAQ,aAAK,UAAU;AAC1C;AAAA,IACJ;AAEA,QAAI,UAAU;AACd,QAAI,cAAc;AAElB,aAAS,QAAQ,CAAC,KAAK,QAAQ;AAC3B,YAAM,SAAS,QAAQ,SAAS,SAAS;AACzC,YAAM,MAAM,cAAc,UAAU,KAAK,OAAO;AAEhD,UAAI,QAAQ;AAAM;AAElB,oBAAc,KAAK,cAAc,aAAa,GAAG;AAEjD,UAAI,CAAC,QAAQ,SAAS,IAAI,GAAG,GAAG;AAC5B,gBAAQ,SAAS,IAAI,KAAK;AAAA,UACtB,SAAS;AAAA,UACT,MAAM;AAAA,UACN,UAAU;AAAA,UACV,UAAU,oBAAI,IAAI;AAAA,UAClB,UAAU,SAAS;AAAA,QACvB,CAAC;AAAA,MACL;AAEA,gBAAU,QAAQ,SAAS,IAAI,GAAG;AAElC,UAAI;AAAQ,aAAK,iBAAiB,SAAS,KAAK;AAAA,IACpD,CAAC;AAAA,EACL;AAAA,EAEQ,cAAc,aAAqB,KAAqB;AAC5D,QAAI,gBAAgB,MAAM,gBAAgB,KAAK;AAC3C,aAAO,QAAQ,KAAK,MAAM,IAAI,GAAG;AAAA,IACrC;AACA,WAAO,GAAG,WAAW,IAAI,GAAG;AAAA,EAChC;AAAA,EAEQ,iBAAiB,MAAiB,OAAwB;AAC9D,UAAM,UAAU,KAAK,YAAY,MAAM,IAAI;AAC3C,QAAI;AAAS,cAAQ,MAAM,KAAK;AAAA,EACpC;AAAA,EAEQ,eAAe,MAAiB,OAAwB;AAC5D,UAAM,cAAc,MAAM,SAAS,MAAM,SAAS,SAAS,CAAC;AAC5D,UAAM,YAAY,aAAa,WAAW,GAAG;AAE7C,QAAI,aAAa,gBAAgB,IAAI;AACjC,WAAK,YAAY,MAAM;AACvB,WAAK,UAAU;AAAA,IACnB,OAAO;AACH,WAAK,YAAY,MAAM;AAAA,IAC3B;AAAA,EACJ;AACJ;;;ACzGO,IAAM,2BAAN,MAA+B;AAAA,EAClC,OAAO,SAAS,MAAiB,SAAS,MAAc;AACpD,UAAM,aAAa,MAAM,KAAK,KAAK,SAAS,OAAO,CAAC;AACpD,UAAM,WAAqB,CAAC;AAE5B,QAAI,KAAK,WAAW;AAChB,eAAS,KAAK,KAAK,mBAAmB,MAAM,MAAM,CAAC;AAAA,IACvD;AAEA,aAAS,KAAK,GAAG,WAAW;AAAA,MAAI,WAC5B,KAAK,SAAS,OAAO,SAAS,MAAM;AAAA,IACxC,CAAC;AAED,WAAO,KAAK,oBAAoB,MAAM,UAAU,MAAM;AAAA,EAC1D;AAAA,EAEA,OAAe,mBAAmB,MAAiB,QAAwB;AACvE,WAAO,GAAG,MAAM;AAAA,EACtB,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM,sBAAsB,KAAK,SAAS;AAAA,EAC1C,MAAM;AAAA,EACN,MAAM;AAAA,EACJ;AAAA,EAEA,OAAe,oBAAoB,MAAiB,UAAoB,QAAwB;AAC5F,UAAM,UAAU,KAAK;AACrB,UAAM,aAAa,KAAK,sBAAsB,MAAM,MAAM;AAC1D,UAAM,WAAW,KAAK,oBAAoB,MAAM,MAAM;AAEtD,WAAO;AAAA,MACH,GAAG,MAAM;AAAA,MACT,GAAG,MAAM,YAAY,OAAO,IAAI,UAAU,GAAG,QAAQ;AAAA,MACrD,SAAS,SAAS,IAAI;AAAA,EAAM,MAAM;AAAA,EAAkB,SAAS,KAAK,KAAK,CAAC;AAAA,EAAK,MAAM,QAAQ;AAAA,MAC3F,GAAG,MAAM;AAAA,IACb,EAAE,OAAO,OAAO,EAAE,KAAK,EAAE;AAAA,EAC7B;AAAA,EAEA,OAAe,sBAAsB,MAAiB,QAAwB;AAC1E,QAAI,CAAC,KAAK,UAAU,CAAC,KAAK;AAAW,aAAO;AAE5C,UAAM,QAAQ,KAAK,SACb,KAAK,oBAAoB,MAAM,MAAM,IACrC,KAAK,uBAAuB,MAAM,MAAM;AAE9C,WAAO;AAAA,EAAM,MAAM,gDAAgD,KAAK;AAAA,EAC5E;AAAA,EAEA,OAAe,oBAAoB,MAAiB,QAAwB;AACxE,WAAO;AAAA,EACb,MAAM,kBAAkB,KAAK,MAAM;AAAA,EACnC,MAAM;AAAA,EACN,MAAM,gBAAgB,KAAK,WAAW,WAAW;AAAA,EACjD,MAAM,iBAAiB,KAAK,YAAY,WAAW;AAAA,EACnD,MAAM;AAAA,EACJ;AAAA,EAEA,OAAe,uBAAuB,MAAiB,QAAwB;AAC3E,WAAO;AAAA,EACb,MAAM,kBAAkB,KAAK,SAAS;AAAA,EACtC,MAAM;AAAA,EACJ;AAAA,EAEA,OAAe,oBAAoB,MAAiB,QAAwB;AACxE,QAAI,CAAC,KAAK;AAAO,aAAO;AAExB,WAAO;AAAA,EAAM,MAAM;AAAA,EACzB,MAAM,kBAAkB,KAAK,KAAK;AAAA,EAClC,MAAM;AAAA,EACJ;AACJ;;;AL9DO,SAAS,OAAO,UAAyB,CAAC,GAAW;AACxD,QAAM,kBAAkB,EAAE,GAAG,iBAAiB,GAAG,QAAQ;AACzD,MAAI;AACJ,QAAM,mBAAmB,IAAI,iBAAiB;AAE9C,SAAO;AAAA,IACH,MAAM;AAAA,IAEN,eAAe,QAAQ;AACnB,aAAO,OAAO;AAAA,IAClB;AAAA,IAEA,gBAAgB,QAAQ;AACpB,YAAM,WAAW,aAAAE,QAAK,QAAQ,MAAM,gBAAgB,QAAQ;AAE5D,aAAO,QAAQ,IAAI,QAAQ;AAE3B,YAAM,mBAAmB,CAAC,SAAiB;AACvC,YAAI,KAAK,WAAW,QAAQ,GAAG;AAC3B,gBAAMC,UAAS,OAAO,YAAY,cAAc,gCAAgC;AAChF,cAAIA,SAAQ;AACR,mBAAO,YAAY,iBAAiBA,OAAM;AAAA,UAC9C;AACA,iBAAO,GAAG,KAAK,EAAE,MAAM,cAAc,CAAC;AAAA,QAC1C;AAAA,MACJ;AAEA,aAAO,QAAQ,GAAG,OAAO,gBAAgB;AACzC,aAAO,QAAQ,GAAG,UAAU,gBAAgB;AAC5C,aAAO,QAAQ,GAAG,UAAU,gBAAgB;AAAA,IAChD;AAAA,IAEA,UAAU,IAAI;AACV,UAAI,OAAO,yBAAyB;AAChC,eAAO;AAAA,MACX;AAAA,IACJ;AAAA,IAEA,MAAM,KAAK,IAAI;AACX,UAAI,OAAO,kCAAkC;AACzC,cAAM,WAAW,aAAAD,QAAK,QAAQ,MAAM,gBAAgB,QAAQ;AAE5D,YAAI,CAAC,UAAAE,QAAG,WAAW,QAAQ,GAAG;AAC1B,oBAAAA,QAAG,UAAU,UAAU,EAAE,WAAW,KAAK,CAAC;AAC1C,iBAAO;AAAA,QACX;AAEA,cAAM,SAAS,MAAM,eAAe,QAAQ;AAE5C,YAAI,OAAO,WAAW,GAAG;AACrB,iBAAO;AAAA,QACX;AAEA,cAAM,YAAY,iBAAiB,MAAM,QAAQ;AAAA,UAC7C,QAAQ;AAAA,UACR,yBAAyB,CAAC,YAAY,IAAI,QAAQ,YAAY,CAAC;AAAA,QACnE,CAAC;AAED,cAAM,mBAAmB,yBAAyB,SAAS,SAAS;AAEpE,eAAO,UAAU,QAAQ,gBAAgB;AAAA,MAC7C;AAAA,IACJ;AAAA,EACJ;AACJ;AAEO,SAAS,UAAU,QAAqB,kBAAkC;AAC7E,QAAM,YAAY,oBAAI,IAAoB;AAC1C,SAAO,QAAQ,WAAS,UAAU,IAAI,MAAM,UAAU,MAAM,aAAa,CAAC;AAE1E,QAAM,UAAU,MAAM,KAAK,UAAU,QAAQ,CAAC,EACzC,IAAI,CAAC,CAAC,UAAU,aAAa,MAAM,UAAU,aAAa,UAAU,QAAQ,IAAI,EAChF,KAAK,IAAI;AAEd,SAAO;AAAA;AAAA;AAAA,EAGT,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAgEP,gBAAgB;AAAA;AAAA,2EAEyD,OAAO,KAAK,OAAK,EAAE,SAAS,WAAW,GAAG,iBAAiB,MAAM;AAAA;AAAA;AAAA;AAAA;AAK5I;","names":["import_path","path","glob","path","module","fs"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/plugin.ts","../src/constants.ts","../src/generator/createRoutes.ts","../src/generator/parser/segmentParser.ts","../src/generator/parser/routeTreeBuilder.ts","../src/generator/parser/routeDefinitionGenerator.ts"],"sourcesContent":["export { navilo } from './plugin';\n\nexport type {\n RouteFile,\n RouteType,\n RouteNode,\n ParserOptions\n} from './types';\n\nexport {\n normalizeFilePath,\n getRouteType,\n getComponentName,\n findRouteFiles\n} from './generator/createRoutes';\n\nexport { SegmentParser } from './generator/parser/segmentParser';\nexport { RouteTreeBuilder } from './generator/parser/routeTreeBuilder';\nexport { RouteDefinitionGenerator } from './generator/parser/routeDefinitionGenerator';","// src/plugin.ts\nimport { Plugin } from 'vite';\nimport path from 'path';\nimport fs from 'fs';\nimport { DEFAULT_OPTIONS, RESOLVED_VIRTUAL_ROUTE_MODULE_ID, VIRTUAL_ROUTE_MODULE_ID } from './constants';\nimport {naviloOptions, RouteFile} from './types';\nimport { findRouteFiles } from './generator/createRoutes';\nimport {RouteTreeBuilder} from \"./generator/parser/routeTreeBuilder\";\nimport {RouteDefinitionGenerator} from \"./generator/parser/routeDefinitionGenerator\";\n\nexport function navilo(options: naviloOptions = {}): Plugin {\n const resolvedOptions = { ...DEFAULT_OPTIONS, ...options };\n let root: string;\n const routeTreeBuilder = new RouteTreeBuilder();\n\n return {\n name: 'navilo',\n\n configResolved(config) {\n root = config.root;\n },\n\n configureServer(server) {\n const pagesDir = path.resolve(root, resolvedOptions.pagesDir);\n\n server.watcher.add(pagesDir);\n\n const handleFileChange = (file: string) => {\n if (file.startsWith(pagesDir)) {\n const module = server.moduleGraph.getModuleById(RESOLVED_VIRTUAL_ROUTE_MODULE_ID);\n if (module) {\n server.moduleGraph.invalidateModule(module);\n }\n server.ws.send({ type: 'full-reload' });\n }\n };\n\n server.watcher.on('add', handleFileChange);\n server.watcher.on('unlink', handleFileChange);\n server.watcher.on('change', handleFileChange);\n },\n\n resolveId(id) {\n if (id === VIRTUAL_ROUTE_MODULE_ID) {\n return RESOLVED_VIRTUAL_ROUTE_MODULE_ID;\n }\n },\n\n async load(id) {\n if (id === RESOLVED_VIRTUAL_ROUTE_MODULE_ID) {\n const pagesDir = path.resolve(root, resolvedOptions.pagesDir);\n\n if (!fs.existsSync(pagesDir)) {\n fs.mkdirSync(pagesDir, { recursive: true });\n return `export const router = null;`;\n }\n\n const routes = await findRouteFiles(pagesDir);\n\n if (routes.length === 0) {\n return `export const router = null;`;\n }\n\n const routeTree = routeTreeBuilder.build(routes, {\n strict: true,\n dynamicSegmentTransform: (segment) => `:${segment.toLowerCase()}`\n });\n\n const routeDefinitions = RouteDefinitionGenerator.generate(routeTree);\n\n return routerJSX(routes, routeDefinitions);\n }\n }\n };\n}\n\nexport function routerJSX(routes: RouteFile[], routeDefinitions: string): string {\n const importMap = new Map<string, string>();\n routes.forEach(route => importMap.set(route.filePath, route.componentName));\n\n const imports = Array.from(importMap.entries())\n .map(([filePath, componentName]) => `import ${componentName} from '${filePath}';`)\n .join('\\n');\n\n return `\nimport React, { Suspense } from 'react';\nimport { createBrowserRouter, useParams, Outlet, useRouteError, isRouteErrorResponse } from 'react-router-dom';\n${imports}\n\nfunction ErrorBoundary({ Component }) {\n const error = useRouteError();\n const params = useParams();\n\n if (!Component) {\n return React.createElement('div', { className: 'error-container' },\n React.createElement('div', { className: 'error-content' }, [\n React.createElement('h1', null, \n isRouteErrorResponse(error) ? \\`\\${error.status} - \\${error.statusText}\\` : 'Error'\n ),\n React.createElement('pre', { className: 'error-stack' },\n error instanceof Error ? error.stack : JSON.stringify(error, null, 2)\n ),\n React.createElement('button', {\n onClick: () => window.location.reload()\n }, 'Try again')\n ])\n );\n }\n\n return React.createElement(Component, { error, params });\n}\n\nfunction LoadingBoundary({ Component, children }) {\n if (!Component) {\n return children;\n }\n\n return React.createElement(Suspense, {\n fallback: React.createElement(Component)\n }, children);\n}\n\nfunction RouteWrapper({ Component, isLayout, loading, notFound }) {\n const params = useParams();\n \n if (isLayout) {\n const outlet = React.createElement(Outlet);\n const content = loading ? \n React.createElement(LoadingBoundary, { Component: loading }, outlet) :\n outlet;\n\n return React.createElement(Component, {\n children: content,\n params\n });\n }\n \n return React.createElement(Component, { params });\n}\n\n// Add global error listener\nwindow.addEventListener('error', (event) => {\n console.error('Global error:', event.error);\n});\n\n// Add global promise rejection handler\nwindow.addEventListener('unhandledrejection', (event) => {\n console.error('Unhandled promise rejection:', event.reason);\n});\n\nconst router = createBrowserRouter([\n${routeDefinitions}\n], {\n defaultErrorElement: React.createElement(ErrorBoundary, { Component: ${routes.find(r => r.type === 'not-found')?.componentName || 'null'} })\n});\n\nexport { router };\n`;\n}","export const DEFAULT_OPTIONS = {\n pagesDir: 'src/app',\n typescript: true,\n};\n\nexport const VIRTUAL_ROUTE_MODULE_ID = 'virtual:navilo-routes';\nexport const RESOLVED_VIRTUAL_ROUTE_MODULE_ID = '\\0' + VIRTUAL_ROUTE_MODULE_ID;","import path from 'path';\nimport glob from 'fast-glob';\nimport { RouteFile, RouteType } from '../types';\n\n/** Normalize Windows paths to forward slashes */\nexport function normalizeFilePath(filePath: string): string {\n return filePath.replace(/\\\\/g, '/');\n}\n\n/** Determine the type of a route file */\nexport function getRouteType(filePath: string): RouteType {\n const basename = path.basename(filePath);\n const fileTypes: Record<string, RouteType> = {\n 'layout.jsx': 'layout',\n 'layout.tsx': 'layout',\n 'page.jsx': 'page',\n 'page.tsx': 'page',\n 'error.jsx': 'error',\n 'error.tsx': 'error',\n 'loading.jsx': 'loading',\n 'loading.tsx': 'loading',\n 'not-found.jsx': 'not-found',\n 'not-found.tsx': 'not-found'\n };\n return fileTypes[basename] || 'page';\n}\n\n/** Generate a PascalCase component name based on folder structure */\nexport function getComponentName(filePath: string, pagesDir: string): string {\n const segments = normalizeFilePath(path.relative(pagesDir, filePath)).split('/');\n const fileNameWithExt = segments.pop()!;\n const fileName = path.basename(fileNameWithExt, path.extname(fileNameWithExt));\n\n const relevantSegments = segments.map(segment => {\n if (segment.startsWith('[') && segment.endsWith(']')) {\n return segment.slice(1, -1)\n .replace(/^\\.\\.\\./, 'CatchAll')\n .split(/[^a-zA-Z0-9]/)\n .map(p => p.charAt(0).toUpperCase() + p.slice(1))\n .join('');\n }\n return segment\n .split(/[^a-zA-Z0-9]/)\n .map(p => p.charAt(0).toUpperCase() + p.slice(1))\n .join('');\n });\n\n const typeSuffix = {\n page: 'Page',\n layout: 'Layout',\n error: 'Error',\n loading: 'Loading',\n 'not-found': 'NotFound'\n }[fileName] || 'Component';\n\n return relevantSegments.length === 0 ? `Root${typeSuffix}` : `${relevantSegments.join('')}${typeSuffix}`;\n}\n\n/** Extract segments from file path for building route tree */\nexport function getPathSegments(filePath: string, pagesDir: string): string[] {\n const relativePath = normalizeFilePath(path.relative(pagesDir, filePath));\n const segments = relativePath.split('/');\n const fileName = segments.pop()!;\n\n const filteredSegments = segments.filter(seg => !(seg.startsWith('(') && seg.endsWith(')')));\n\n if (/^page\\.(jsx|tsx)$/.test(fileName)) {\n filteredSegments.push('');\n }\n\n return filteredSegments;\n}\n\n/** Find all route files in the pages directory */\nexport async function findRouteFiles(pagesDir: string): Promise<RouteFile[]> {\n const files = await glob(['**/*.{jsx,tsx}'], {\n cwd: pagesDir,\n absolute: true,\n ignore: ['**/node_modules/**', '**/.*/**', '**/_*/**'],\n });\n\n const validFiles = files.filter(file => {\n const base = path.basename(file);\n return /^(layout|page|error|loading|not-found)\\.(jsx|tsx)$/.test(base);\n });\n\n return validFiles.map(file => {\n const type = getRouteType(file);\n return {\n type,\n path: '/' + normalizeFilePath(path.relative(pagesDir, path.dirname(file))),\n filePath: normalizeFilePath(file),\n componentName: getComponentName(file, pagesDir),\n segments: getPathSegments(file, pagesDir),\n };\n });\n}\n","import {ParserOptions} from \"../../types\";\n\nexport class SegmentParser {\n private static readonly SEGMENT_PATTERNS = {\n OPTIONAL_CATCH_ALL: /^\\[\\[\\.{3}(.+)\\]\\]$/,\n CATCH_ALL: /^\\[\\.{3}(.+)\\]$/,\n DYNAMIC: /^\\[(.+)\\]$/,\n GROUP: /^\\((.+)\\)$/\n };\n\n static normalize(segment: string, options?: ParserOptions): string | null {\n if (this.isGroupSegment(segment)) return null;\n\n if (segment.includes('/')) {\n return segment.split('/')\n .map(seg => this.normalizeSegment(seg, options))\n .filter(Boolean)\n .join('/');\n }\n\n return this.normalizeSegment(segment, options);\n }\n\n private static normalizeSegment(segment: string, options?: ParserOptions): string | null {\n const transform = options?.dynamicSegmentTransform || this.defaultTransform;\n\n if (this.isOptionalCatchAll(segment)) {\n const name = segment.match(this.SEGMENT_PATTERNS.OPTIONAL_CATCH_ALL)![1];\n return transform(`${name}*?`);\n }\n\n if (this.isCatchAll(segment)) {\n const name = segment.match(this.SEGMENT_PATTERNS.CATCH_ALL)![1];\n return transform(`${name}*`);\n }\n\n if (this.isDynamicSegment(segment)) {\n const name = segment.match(this.SEGMENT_PATTERNS.DYNAMIC)![1];\n return transform(name);\n }\n\n return segment;\n }\n\n private static defaultTransform(name: string): string {\n return `:${name}`;\n }\n\n private static isGroupSegment(segment: string): boolean {\n return this.SEGMENT_PATTERNS.GROUP.test(segment);\n }\n\n private static isOptionalCatchAll(segment: string): boolean {\n return this.SEGMENT_PATTERNS.OPTIONAL_CATCH_ALL.test(segment);\n }\n\n private static isCatchAll(segment: string): boolean {\n return this.SEGMENT_PATTERNS.CATCH_ALL.test(segment);\n }\n\n private static isDynamicSegment(segment: string): boolean {\n return this.SEGMENT_PATTERNS.DYNAMIC.test(segment);\n }\n}","import {SegmentParser} from './segmentParser';\nimport {ParserOptions, RouteFile, RouteNode} from \"../../types\";\n\nexport class RouteTreeBuilder {\n private readonly typeSetters: Record<string, (node: RouteNode, route: RouteFile) => void>;\n\n constructor() {\n this.typeSetters = {\n layout: (node, route) => {\n node.layout = route.componentName;\n },\n error: (node, route) => {\n node.error = route.componentName;\n },\n loading: (node, route) => {\n node.loading = route.componentName;\n },\n 'not-found': (node, route) => {\n node.notFound = route.componentName;\n },\n page: this.handlePageType.bind(this)\n };\n }\n\n build(routes: RouteFile[], options?: ParserOptions): RouteNode {\n const root: RouteNode = {\n segment: '',\n path: '/',\n fullPath: '/',\n children: new Map(),\n metadata: options?.metadata\n };\n\n const sortedRoutes = this.sortRoutes(routes);\n sortedRoutes.forEach(route => {\n this.processRoute(root, route, options);\n });\n\n return root;\n }\n\n private sortRoutes(routes: RouteFile[]): RouteFile[] {\n return [...routes].sort((a, b) =>\n a.type === 'layout' && b.type !== 'layout' ? -1 :\n a.type !== 'layout' && b.type === 'layout' ? 1 : 0\n );\n }\n\n private processRoute(root: RouteNode, route: RouteFile, options?: ParserOptions): void {\n const segments = route.segments.map(seg => String(seg));\n\n if (segments.length === 0) {\n this.applyTypeHandler(root, route);\n if (route.type === 'page') root.isIndex = true;\n return;\n }\n\n let current = root;\n let currentPath = '';\n\n segments.forEach((seg, idx) => {\n const isLast = idx === segments.length - 1;\n const key = SegmentParser.normalize(seg, options);\n\n if (key === null) return;\n\n currentPath = this.buildFullPath(currentPath, key);\n\n if (!current.children.has(key)) {\n current.children.set(key, {\n segment: key,\n path: key,\n fullPath: currentPath,\n children: new Map(),\n metadata: options?.metadata\n });\n }\n\n current = current.children.get(key)!;\n\n if (isLast) this.applyTypeHandler(current, route);\n });\n }\n\n private buildFullPath(currentPath: string, key: string): string {\n if (currentPath === '' || currentPath === '/') {\n return key === '' ? '/' : `/${key}`;\n }\n return `${currentPath}/${key}`;\n }\n\n private applyTypeHandler(node: RouteNode, route: RouteFile): void {\n const handler = this.typeSetters[route.type];\n if (handler) handler(node, route);\n }\n\n private handlePageType(node: RouteNode, route: RouteFile): void {\n const lastSegment = route.segments[route.segments.length - 1];\n const isDynamic = lastSegment?.startsWith('[');\n\n if (isDynamic || lastSegment === '') {\n node.component = route.componentName;\n node.isIndex = false;\n } else {\n node.indexPage = route.componentName;\n }\n }\n}","import { RouteNode } from \"../../types\";\n\nexport class RouteDefinitionGenerator {\n static generate(node: RouteNode, indent = ' '): string {\n const childNodes = Array.from(node.children.values());\n const children: string[] = [];\n\n if (node.indexPage) {\n children.push(this.generateIndexRoute(node, indent));\n }\n\n children.push(...childNodes.map(child =>\n this.generate(child, indent + ' ')\n ));\n\n return this.generateRouteObject(node, children, indent);\n }\n\n private static generateIndexRoute(node: RouteNode, indent: string): string {\n return `${indent} {\n${indent} index: true,\n${indent} element: React.createElement(RouteWrapper, {\n${indent} Component: ${node.indexPage}\n${indent} })\n${indent} }`;\n }\n\n private static generateRouteObject(node: RouteNode, children: string[], indent: string): string {\n const pathStr = node.fullPath;\n const elementStr = this.generateElementString(node, indent);\n const errorStr = this.generateErrorString(node, indent);\n\n return [\n `${indent}{`,\n `${indent} path: '${pathStr}'${elementStr}${errorStr}`,\n children.length > 0 ? `,\\n${indent} children: [\\n${children.join(',\\n')}\\n${indent} ]` : '',\n `${indent}}`\n ].filter(Boolean).join('');\n }\n\n private static generateElementString(node: RouteNode, indent: string): string {\n if (!node.layout && !node.component) return '';\n\n const props = node.layout\n ? this.generateLayoutProps(node, indent)\n : this.generateComponentProps(node, indent);\n\n return `,\\n${indent} element: React.createElement(RouteWrapper, ${props})`;\n }\n\n private static generateLayoutProps(node: RouteNode, indent: string): string {\n return `{\n${indent} Component: ${node.layout},\n${indent} isLayout: true,\n${indent} loading: ${node.loading || 'undefined'},\n${indent} notFound: ${node.notFound || 'undefined'}\n${indent} }`;\n }\n\n private static generateComponentProps(node: RouteNode, indent: string): string {\n return `{\n${indent} Component: ${node.component}\n${indent} }`;\n }\n\n private static generateErrorString(node: RouteNode, indent: string): string {\n if (!node.error) return '';\n\n return `,\\n${indent} errorElement: React.createElement(ErrorBoundary, {\n${indent} Component: ${node.error}\n${indent} })`;\n }\n}"],"mappings":"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","names":["import_path","path","glob","path","module","fs"]}
package/dist/index.mjs CHANGED
@@ -7,7 +7,7 @@ var DEFAULT_OPTIONS = {
7
7
  pagesDir: "src/app",
8
8
  typescript: true
9
9
  };
10
- var VIRTUAL_ROUTE_MODULE_ID = "virtual:preluder-routes";
10
+ var VIRTUAL_ROUTE_MODULE_ID = "virtual:navilo-routes";
11
11
  var RESOLVED_VIRTUAL_ROUTE_MODULE_ID = "\0" + VIRTUAL_ROUTE_MODULE_ID;
12
12
 
13
13
  // src/generator/createRoutes.ts
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/plugin.ts","../src/constants.ts","../src/generator/createRoutes.ts","../src/generator/parser/segmentParser.ts","../src/generator/parser/routeTreeBuilder.ts","../src/generator/parser/routeDefinitionGenerator.ts"],"sourcesContent":["// src/plugin.ts\nimport { Plugin } from 'vite';\nimport path from 'path';\nimport fs from 'fs';\nimport { DEFAULT_OPTIONS, RESOLVED_VIRTUAL_ROUTE_MODULE_ID, VIRTUAL_ROUTE_MODULE_ID } from './constants';\nimport {naviloOptions, RouteFile} from './types';\nimport { findRouteFiles } from './generator/createRoutes';\nimport {RouteTreeBuilder} from \"./generator/parser/routeTreeBuilder\";\nimport {RouteDefinitionGenerator} from \"./generator/parser/routeDefinitionGenerator\";\n\nexport function navilo(options: naviloOptions = {}): Plugin {\n const resolvedOptions = { ...DEFAULT_OPTIONS, ...options };\n let root: string;\n const routeTreeBuilder = new RouteTreeBuilder();\n\n return {\n name: 'navilo',\n\n configResolved(config) {\n root = config.root;\n },\n\n configureServer(server) {\n const pagesDir = path.resolve(root, resolvedOptions.pagesDir);\n\n server.watcher.add(pagesDir);\n\n const handleFileChange = (file: string) => {\n if (file.startsWith(pagesDir)) {\n const module = server.moduleGraph.getModuleById(RESOLVED_VIRTUAL_ROUTE_MODULE_ID);\n if (module) {\n server.moduleGraph.invalidateModule(module);\n }\n server.ws.send({ type: 'full-reload' });\n }\n };\n\n server.watcher.on('add', handleFileChange);\n server.watcher.on('unlink', handleFileChange);\n server.watcher.on('change', handleFileChange);\n },\n\n resolveId(id) {\n if (id === VIRTUAL_ROUTE_MODULE_ID) {\n return RESOLVED_VIRTUAL_ROUTE_MODULE_ID;\n }\n },\n\n async load(id) {\n if (id === RESOLVED_VIRTUAL_ROUTE_MODULE_ID) {\n const pagesDir = path.resolve(root, resolvedOptions.pagesDir);\n\n if (!fs.existsSync(pagesDir)) {\n fs.mkdirSync(pagesDir, { recursive: true });\n return `export const router = null;`;\n }\n\n const routes = await findRouteFiles(pagesDir);\n\n if (routes.length === 0) {\n return `export const router = null;`;\n }\n\n const routeTree = routeTreeBuilder.build(routes, {\n strict: true,\n dynamicSegmentTransform: (segment) => `:${segment.toLowerCase()}`\n });\n\n const routeDefinitions = RouteDefinitionGenerator.generate(routeTree);\n\n return routerJSX(routes, routeDefinitions);\n }\n }\n };\n}\n\nexport function routerJSX(routes: RouteFile[], routeDefinitions: string): string {\n const importMap = new Map<string, string>();\n routes.forEach(route => importMap.set(route.filePath, route.componentName));\n\n const imports = Array.from(importMap.entries())\n .map(([filePath, componentName]) => `import ${componentName} from '${filePath}';`)\n .join('\\n');\n\n return `\nimport React, { Suspense } from 'react';\nimport { createBrowserRouter, useParams, Outlet, useRouteError, isRouteErrorResponse } from 'react-router-dom';\n${imports}\n\nfunction ErrorBoundary({ Component }) {\n const error = useRouteError();\n const params = useParams();\n\n if (!Component) {\n return React.createElement('div', { className: 'error-container' },\n React.createElement('div', { className: 'error-content' }, [\n React.createElement('h1', null, \n isRouteErrorResponse(error) ? \\`\\${error.status} - \\${error.statusText}\\` : 'Error'\n ),\n React.createElement('pre', { className: 'error-stack' },\n error instanceof Error ? error.stack : JSON.stringify(error, null, 2)\n ),\n React.createElement('button', {\n onClick: () => window.location.reload()\n }, 'Try again')\n ])\n );\n }\n\n return React.createElement(Component, { error, params });\n}\n\nfunction LoadingBoundary({ Component, children }) {\n if (!Component) {\n return children;\n }\n\n return React.createElement(Suspense, {\n fallback: React.createElement(Component)\n }, children);\n}\n\nfunction RouteWrapper({ Component, isLayout, loading, notFound }) {\n const params = useParams();\n \n if (isLayout) {\n const outlet = React.createElement(Outlet);\n const content = loading ? \n React.createElement(LoadingBoundary, { Component: loading }, outlet) :\n outlet;\n\n return React.createElement(Component, {\n children: content,\n params\n });\n }\n \n return React.createElement(Component, { params });\n}\n\n// Add global error listener\nwindow.addEventListener('error', (event) => {\n console.error('Global error:', event.error);\n});\n\n// Add global promise rejection handler\nwindow.addEventListener('unhandledrejection', (event) => {\n console.error('Unhandled promise rejection:', event.reason);\n});\n\nconst router = createBrowserRouter([\n${routeDefinitions}\n], {\n defaultErrorElement: React.createElement(ErrorBoundary, { Component: ${routes.find(r => r.type === 'not-found')?.componentName || 'null'} })\n});\n\nexport { router };\n`;\n}","export const DEFAULT_OPTIONS = {\n pagesDir: 'src/app',\n typescript: true,\n};\n\nexport const VIRTUAL_ROUTE_MODULE_ID = 'virtual:preluder-routes';\nexport const RESOLVED_VIRTUAL_ROUTE_MODULE_ID = '\\0' + VIRTUAL_ROUTE_MODULE_ID;","import path from 'path';\nimport glob from 'fast-glob';\nimport { RouteFile, RouteType } from '../types';\n\n/** Normalize Windows paths to forward slashes */\nexport function normalizeFilePath(filePath: string): string {\n return filePath.replace(/\\\\/g, '/');\n}\n\n/** Determine the type of a route file */\nexport function getRouteType(filePath: string): RouteType {\n const basename = path.basename(filePath);\n const fileTypes: Record<string, RouteType> = {\n 'layout.jsx': 'layout',\n 'layout.tsx': 'layout',\n 'page.jsx': 'page',\n 'page.tsx': 'page',\n 'error.jsx': 'error',\n 'error.tsx': 'error',\n 'loading.jsx': 'loading',\n 'loading.tsx': 'loading',\n 'not-found.jsx': 'not-found',\n 'not-found.tsx': 'not-found'\n };\n return fileTypes[basename] || 'page';\n}\n\n/** Generate a PascalCase component name based on folder structure */\nexport function getComponentName(filePath: string, pagesDir: string): string {\n const segments = normalizeFilePath(path.relative(pagesDir, filePath)).split('/');\n const fileNameWithExt = segments.pop()!;\n const fileName = path.basename(fileNameWithExt, path.extname(fileNameWithExt));\n\n const relevantSegments = segments.map(segment => {\n if (segment.startsWith('[') && segment.endsWith(']')) {\n return segment.slice(1, -1)\n .replace(/^\\.\\.\\./, 'CatchAll')\n .split(/[^a-zA-Z0-9]/)\n .map(p => p.charAt(0).toUpperCase() + p.slice(1))\n .join('');\n }\n return segment\n .split(/[^a-zA-Z0-9]/)\n .map(p => p.charAt(0).toUpperCase() + p.slice(1))\n .join('');\n });\n\n const typeSuffix = {\n page: 'Page',\n layout: 'Layout',\n error: 'Error',\n loading: 'Loading',\n 'not-found': 'NotFound'\n }[fileName] || 'Component';\n\n return relevantSegments.length === 0 ? `Root${typeSuffix}` : `${relevantSegments.join('')}${typeSuffix}`;\n}\n\n/** Extract segments from file path for building route tree */\nexport function getPathSegments(filePath: string, pagesDir: string): string[] {\n const relativePath = normalizeFilePath(path.relative(pagesDir, filePath));\n const segments = relativePath.split('/');\n const fileName = segments.pop()!;\n\n const filteredSegments = segments.filter(seg => !(seg.startsWith('(') && seg.endsWith(')')));\n\n if (/^page\\.(jsx|tsx)$/.test(fileName)) {\n filteredSegments.push('');\n }\n\n return filteredSegments;\n}\n\n/** Find all route files in the pages directory */\nexport async function findRouteFiles(pagesDir: string): Promise<RouteFile[]> {\n const files = await glob(['**/*.{jsx,tsx}'], {\n cwd: pagesDir,\n absolute: true,\n ignore: ['**/node_modules/**', '**/.*/**', '**/_*/**'],\n });\n\n const validFiles = files.filter(file => {\n const base = path.basename(file);\n return /^(layout|page|error|loading|not-found)\\.(jsx|tsx)$/.test(base);\n });\n\n return validFiles.map(file => {\n const type = getRouteType(file);\n return {\n type,\n path: '/' + normalizeFilePath(path.relative(pagesDir, path.dirname(file))),\n filePath: normalizeFilePath(file),\n componentName: getComponentName(file, pagesDir),\n segments: getPathSegments(file, pagesDir),\n };\n });\n}\n","import {ParserOptions} from \"../../types\";\n\nexport class SegmentParser {\n private static readonly SEGMENT_PATTERNS = {\n OPTIONAL_CATCH_ALL: /^\\[\\[\\.{3}(.+)\\]\\]$/,\n CATCH_ALL: /^\\[\\.{3}(.+)\\]$/,\n DYNAMIC: /^\\[(.+)\\]$/,\n GROUP: /^\\((.+)\\)$/\n };\n\n static normalize(segment: string, options?: ParserOptions): string | null {\n if (this.isGroupSegment(segment)) return null;\n\n if (segment.includes('/')) {\n return segment.split('/')\n .map(seg => this.normalizeSegment(seg, options))\n .filter(Boolean)\n .join('/');\n }\n\n return this.normalizeSegment(segment, options);\n }\n\n private static normalizeSegment(segment: string, options?: ParserOptions): string | null {\n const transform = options?.dynamicSegmentTransform || this.defaultTransform;\n\n if (this.isOptionalCatchAll(segment)) {\n const name = segment.match(this.SEGMENT_PATTERNS.OPTIONAL_CATCH_ALL)![1];\n return transform(`${name}*?`);\n }\n\n if (this.isCatchAll(segment)) {\n const name = segment.match(this.SEGMENT_PATTERNS.CATCH_ALL)![1];\n return transform(`${name}*`);\n }\n\n if (this.isDynamicSegment(segment)) {\n const name = segment.match(this.SEGMENT_PATTERNS.DYNAMIC)![1];\n return transform(name);\n }\n\n return segment;\n }\n\n private static defaultTransform(name: string): string {\n return `:${name}`;\n }\n\n private static isGroupSegment(segment: string): boolean {\n return this.SEGMENT_PATTERNS.GROUP.test(segment);\n }\n\n private static isOptionalCatchAll(segment: string): boolean {\n return this.SEGMENT_PATTERNS.OPTIONAL_CATCH_ALL.test(segment);\n }\n\n private static isCatchAll(segment: string): boolean {\n return this.SEGMENT_PATTERNS.CATCH_ALL.test(segment);\n }\n\n private static isDynamicSegment(segment: string): boolean {\n return this.SEGMENT_PATTERNS.DYNAMIC.test(segment);\n }\n}","import {SegmentParser} from './segmentParser';\nimport {ParserOptions, RouteFile, RouteNode} from \"../../types\";\n\nexport class RouteTreeBuilder {\n private readonly typeSetters: Record<string, (node: RouteNode, route: RouteFile) => void>;\n\n constructor() {\n this.typeSetters = {\n layout: (node, route) => {\n node.layout = route.componentName;\n },\n error: (node, route) => {\n node.error = route.componentName;\n },\n loading: (node, route) => {\n node.loading = route.componentName;\n },\n 'not-found': (node, route) => {\n node.notFound = route.componentName;\n },\n page: this.handlePageType.bind(this)\n };\n }\n\n build(routes: RouteFile[], options?: ParserOptions): RouteNode {\n const root: RouteNode = {\n segment: '',\n path: '/',\n fullPath: '/',\n children: new Map(),\n metadata: options?.metadata\n };\n\n const sortedRoutes = this.sortRoutes(routes);\n sortedRoutes.forEach(route => {\n this.processRoute(root, route, options);\n });\n\n return root;\n }\n\n private sortRoutes(routes: RouteFile[]): RouteFile[] {\n return [...routes].sort((a, b) =>\n a.type === 'layout' && b.type !== 'layout' ? -1 :\n a.type !== 'layout' && b.type === 'layout' ? 1 : 0\n );\n }\n\n private processRoute(root: RouteNode, route: RouteFile, options?: ParserOptions): void {\n const segments = route.segments.map(seg => String(seg));\n\n if (segments.length === 0) {\n this.applyTypeHandler(root, route);\n if (route.type === 'page') root.isIndex = true;\n return;\n }\n\n let current = root;\n let currentPath = '';\n\n segments.forEach((seg, idx) => {\n const isLast = idx === segments.length - 1;\n const key = SegmentParser.normalize(seg, options);\n\n if (key === null) return;\n\n currentPath = this.buildFullPath(currentPath, key);\n\n if (!current.children.has(key)) {\n current.children.set(key, {\n segment: key,\n path: key,\n fullPath: currentPath,\n children: new Map(),\n metadata: options?.metadata\n });\n }\n\n current = current.children.get(key)!;\n\n if (isLast) this.applyTypeHandler(current, route);\n });\n }\n\n private buildFullPath(currentPath: string, key: string): string {\n if (currentPath === '' || currentPath === '/') {\n return key === '' ? '/' : `/${key}`;\n }\n return `${currentPath}/${key}`;\n }\n\n private applyTypeHandler(node: RouteNode, route: RouteFile): void {\n const handler = this.typeSetters[route.type];\n if (handler) handler(node, route);\n }\n\n private handlePageType(node: RouteNode, route: RouteFile): void {\n const lastSegment = route.segments[route.segments.length - 1];\n const isDynamic = lastSegment?.startsWith('[');\n\n if (isDynamic || lastSegment === '') {\n node.component = route.componentName;\n node.isIndex = false;\n } else {\n node.indexPage = route.componentName;\n }\n }\n}","import { RouteNode } from \"../../types\";\n\nexport class RouteDefinitionGenerator {\n static generate(node: RouteNode, indent = ' '): string {\n const childNodes = Array.from(node.children.values());\n const children: string[] = [];\n\n if (node.indexPage) {\n children.push(this.generateIndexRoute(node, indent));\n }\n\n children.push(...childNodes.map(child =>\n this.generate(child, indent + ' ')\n ));\n\n return this.generateRouteObject(node, children, indent);\n }\n\n private static generateIndexRoute(node: RouteNode, indent: string): string {\n return `${indent} {\n${indent} index: true,\n${indent} element: React.createElement(RouteWrapper, {\n${indent} Component: ${node.indexPage}\n${indent} })\n${indent} }`;\n }\n\n private static generateRouteObject(node: RouteNode, children: string[], indent: string): string {\n const pathStr = node.fullPath;\n const elementStr = this.generateElementString(node, indent);\n const errorStr = this.generateErrorString(node, indent);\n\n return [\n `${indent}{`,\n `${indent} path: '${pathStr}'${elementStr}${errorStr}`,\n children.length > 0 ? `,\\n${indent} children: [\\n${children.join(',\\n')}\\n${indent} ]` : '',\n `${indent}}`\n ].filter(Boolean).join('');\n }\n\n private static generateElementString(node: RouteNode, indent: string): string {\n if (!node.layout && !node.component) return '';\n\n const props = node.layout\n ? this.generateLayoutProps(node, indent)\n : this.generateComponentProps(node, indent);\n\n return `,\\n${indent} element: React.createElement(RouteWrapper, ${props})`;\n }\n\n private static generateLayoutProps(node: RouteNode, indent: string): string {\n return `{\n${indent} Component: ${node.layout},\n${indent} isLayout: true,\n${indent} loading: ${node.loading || 'undefined'},\n${indent} notFound: ${node.notFound || 'undefined'}\n${indent} }`;\n }\n\n private static generateComponentProps(node: RouteNode, indent: string): string {\n return `{\n${indent} Component: ${node.component}\n${indent} }`;\n }\n\n private static generateErrorString(node: RouteNode, indent: string): string {\n if (!node.error) return '';\n\n return `,\\n${indent} errorElement: React.createElement(ErrorBoundary, {\n${indent} Component: ${node.error}\n${indent} })`;\n }\n}"],"mappings":"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","names":["path","path"]}
1
+ {"version":3,"sources":["../src/plugin.ts","../src/constants.ts","../src/generator/createRoutes.ts","../src/generator/parser/segmentParser.ts","../src/generator/parser/routeTreeBuilder.ts","../src/generator/parser/routeDefinitionGenerator.ts"],"sourcesContent":["// src/plugin.ts\nimport { Plugin } from 'vite';\nimport path from 'path';\nimport fs from 'fs';\nimport { DEFAULT_OPTIONS, RESOLVED_VIRTUAL_ROUTE_MODULE_ID, VIRTUAL_ROUTE_MODULE_ID } from './constants';\nimport {naviloOptions, RouteFile} from './types';\nimport { findRouteFiles } from './generator/createRoutes';\nimport {RouteTreeBuilder} from \"./generator/parser/routeTreeBuilder\";\nimport {RouteDefinitionGenerator} from \"./generator/parser/routeDefinitionGenerator\";\n\nexport function navilo(options: naviloOptions = {}): Plugin {\n const resolvedOptions = { ...DEFAULT_OPTIONS, ...options };\n let root: string;\n const routeTreeBuilder = new RouteTreeBuilder();\n\n return {\n name: 'navilo',\n\n configResolved(config) {\n root = config.root;\n },\n\n configureServer(server) {\n const pagesDir = path.resolve(root, resolvedOptions.pagesDir);\n\n server.watcher.add(pagesDir);\n\n const handleFileChange = (file: string) => {\n if (file.startsWith(pagesDir)) {\n const module = server.moduleGraph.getModuleById(RESOLVED_VIRTUAL_ROUTE_MODULE_ID);\n if (module) {\n server.moduleGraph.invalidateModule(module);\n }\n server.ws.send({ type: 'full-reload' });\n }\n };\n\n server.watcher.on('add', handleFileChange);\n server.watcher.on('unlink', handleFileChange);\n server.watcher.on('change', handleFileChange);\n },\n\n resolveId(id) {\n if (id === VIRTUAL_ROUTE_MODULE_ID) {\n return RESOLVED_VIRTUAL_ROUTE_MODULE_ID;\n }\n },\n\n async load(id) {\n if (id === RESOLVED_VIRTUAL_ROUTE_MODULE_ID) {\n const pagesDir = path.resolve(root, resolvedOptions.pagesDir);\n\n if (!fs.existsSync(pagesDir)) {\n fs.mkdirSync(pagesDir, { recursive: true });\n return `export const router = null;`;\n }\n\n const routes = await findRouteFiles(pagesDir);\n\n if (routes.length === 0) {\n return `export const router = null;`;\n }\n\n const routeTree = routeTreeBuilder.build(routes, {\n strict: true,\n dynamicSegmentTransform: (segment) => `:${segment.toLowerCase()}`\n });\n\n const routeDefinitions = RouteDefinitionGenerator.generate(routeTree);\n\n return routerJSX(routes, routeDefinitions);\n }\n }\n };\n}\n\nexport function routerJSX(routes: RouteFile[], routeDefinitions: string): string {\n const importMap = new Map<string, string>();\n routes.forEach(route => importMap.set(route.filePath, route.componentName));\n\n const imports = Array.from(importMap.entries())\n .map(([filePath, componentName]) => `import ${componentName} from '${filePath}';`)\n .join('\\n');\n\n return `\nimport React, { Suspense } from 'react';\nimport { createBrowserRouter, useParams, Outlet, useRouteError, isRouteErrorResponse } from 'react-router-dom';\n${imports}\n\nfunction ErrorBoundary({ Component }) {\n const error = useRouteError();\n const params = useParams();\n\n if (!Component) {\n return React.createElement('div', { className: 'error-container' },\n React.createElement('div', { className: 'error-content' }, [\n React.createElement('h1', null, \n isRouteErrorResponse(error) ? \\`\\${error.status} - \\${error.statusText}\\` : 'Error'\n ),\n React.createElement('pre', { className: 'error-stack' },\n error instanceof Error ? error.stack : JSON.stringify(error, null, 2)\n ),\n React.createElement('button', {\n onClick: () => window.location.reload()\n }, 'Try again')\n ])\n );\n }\n\n return React.createElement(Component, { error, params });\n}\n\nfunction LoadingBoundary({ Component, children }) {\n if (!Component) {\n return children;\n }\n\n return React.createElement(Suspense, {\n fallback: React.createElement(Component)\n }, children);\n}\n\nfunction RouteWrapper({ Component, isLayout, loading, notFound }) {\n const params = useParams();\n \n if (isLayout) {\n const outlet = React.createElement(Outlet);\n const content = loading ? \n React.createElement(LoadingBoundary, { Component: loading }, outlet) :\n outlet;\n\n return React.createElement(Component, {\n children: content,\n params\n });\n }\n \n return React.createElement(Component, { params });\n}\n\n// Add global error listener\nwindow.addEventListener('error', (event) => {\n console.error('Global error:', event.error);\n});\n\n// Add global promise rejection handler\nwindow.addEventListener('unhandledrejection', (event) => {\n console.error('Unhandled promise rejection:', event.reason);\n});\n\nconst router = createBrowserRouter([\n${routeDefinitions}\n], {\n defaultErrorElement: React.createElement(ErrorBoundary, { Component: ${routes.find(r => r.type === 'not-found')?.componentName || 'null'} })\n});\n\nexport { router };\n`;\n}","export const DEFAULT_OPTIONS = {\n pagesDir: 'src/app',\n typescript: true,\n};\n\nexport const VIRTUAL_ROUTE_MODULE_ID = 'virtual:navilo-routes';\nexport const RESOLVED_VIRTUAL_ROUTE_MODULE_ID = '\\0' + VIRTUAL_ROUTE_MODULE_ID;","import path from 'path';\nimport glob from 'fast-glob';\nimport { RouteFile, RouteType } from '../types';\n\n/** Normalize Windows paths to forward slashes */\nexport function normalizeFilePath(filePath: string): string {\n return filePath.replace(/\\\\/g, '/');\n}\n\n/** Determine the type of a route file */\nexport function getRouteType(filePath: string): RouteType {\n const basename = path.basename(filePath);\n const fileTypes: Record<string, RouteType> = {\n 'layout.jsx': 'layout',\n 'layout.tsx': 'layout',\n 'page.jsx': 'page',\n 'page.tsx': 'page',\n 'error.jsx': 'error',\n 'error.tsx': 'error',\n 'loading.jsx': 'loading',\n 'loading.tsx': 'loading',\n 'not-found.jsx': 'not-found',\n 'not-found.tsx': 'not-found'\n };\n return fileTypes[basename] || 'page';\n}\n\n/** Generate a PascalCase component name based on folder structure */\nexport function getComponentName(filePath: string, pagesDir: string): string {\n const segments = normalizeFilePath(path.relative(pagesDir, filePath)).split('/');\n const fileNameWithExt = segments.pop()!;\n const fileName = path.basename(fileNameWithExt, path.extname(fileNameWithExt));\n\n const relevantSegments = segments.map(segment => {\n if (segment.startsWith('[') && segment.endsWith(']')) {\n return segment.slice(1, -1)\n .replace(/^\\.\\.\\./, 'CatchAll')\n .split(/[^a-zA-Z0-9]/)\n .map(p => p.charAt(0).toUpperCase() + p.slice(1))\n .join('');\n }\n return segment\n .split(/[^a-zA-Z0-9]/)\n .map(p => p.charAt(0).toUpperCase() + p.slice(1))\n .join('');\n });\n\n const typeSuffix = {\n page: 'Page',\n layout: 'Layout',\n error: 'Error',\n loading: 'Loading',\n 'not-found': 'NotFound'\n }[fileName] || 'Component';\n\n return relevantSegments.length === 0 ? `Root${typeSuffix}` : `${relevantSegments.join('')}${typeSuffix}`;\n}\n\n/** Extract segments from file path for building route tree */\nexport function getPathSegments(filePath: string, pagesDir: string): string[] {\n const relativePath = normalizeFilePath(path.relative(pagesDir, filePath));\n const segments = relativePath.split('/');\n const fileName = segments.pop()!;\n\n const filteredSegments = segments.filter(seg => !(seg.startsWith('(') && seg.endsWith(')')));\n\n if (/^page\\.(jsx|tsx)$/.test(fileName)) {\n filteredSegments.push('');\n }\n\n return filteredSegments;\n}\n\n/** Find all route files in the pages directory */\nexport async function findRouteFiles(pagesDir: string): Promise<RouteFile[]> {\n const files = await glob(['**/*.{jsx,tsx}'], {\n cwd: pagesDir,\n absolute: true,\n ignore: ['**/node_modules/**', '**/.*/**', '**/_*/**'],\n });\n\n const validFiles = files.filter(file => {\n const base = path.basename(file);\n return /^(layout|page|error|loading|not-found)\\.(jsx|tsx)$/.test(base);\n });\n\n return validFiles.map(file => {\n const type = getRouteType(file);\n return {\n type,\n path: '/' + normalizeFilePath(path.relative(pagesDir, path.dirname(file))),\n filePath: normalizeFilePath(file),\n componentName: getComponentName(file, pagesDir),\n segments: getPathSegments(file, pagesDir),\n };\n });\n}\n","import {ParserOptions} from \"../../types\";\n\nexport class SegmentParser {\n private static readonly SEGMENT_PATTERNS = {\n OPTIONAL_CATCH_ALL: /^\\[\\[\\.{3}(.+)\\]\\]$/,\n CATCH_ALL: /^\\[\\.{3}(.+)\\]$/,\n DYNAMIC: /^\\[(.+)\\]$/,\n GROUP: /^\\((.+)\\)$/\n };\n\n static normalize(segment: string, options?: ParserOptions): string | null {\n if (this.isGroupSegment(segment)) return null;\n\n if (segment.includes('/')) {\n return segment.split('/')\n .map(seg => this.normalizeSegment(seg, options))\n .filter(Boolean)\n .join('/');\n }\n\n return this.normalizeSegment(segment, options);\n }\n\n private static normalizeSegment(segment: string, options?: ParserOptions): string | null {\n const transform = options?.dynamicSegmentTransform || this.defaultTransform;\n\n if (this.isOptionalCatchAll(segment)) {\n const name = segment.match(this.SEGMENT_PATTERNS.OPTIONAL_CATCH_ALL)![1];\n return transform(`${name}*?`);\n }\n\n if (this.isCatchAll(segment)) {\n const name = segment.match(this.SEGMENT_PATTERNS.CATCH_ALL)![1];\n return transform(`${name}*`);\n }\n\n if (this.isDynamicSegment(segment)) {\n const name = segment.match(this.SEGMENT_PATTERNS.DYNAMIC)![1];\n return transform(name);\n }\n\n return segment;\n }\n\n private static defaultTransform(name: string): string {\n return `:${name}`;\n }\n\n private static isGroupSegment(segment: string): boolean {\n return this.SEGMENT_PATTERNS.GROUP.test(segment);\n }\n\n private static isOptionalCatchAll(segment: string): boolean {\n return this.SEGMENT_PATTERNS.OPTIONAL_CATCH_ALL.test(segment);\n }\n\n private static isCatchAll(segment: string): boolean {\n return this.SEGMENT_PATTERNS.CATCH_ALL.test(segment);\n }\n\n private static isDynamicSegment(segment: string): boolean {\n return this.SEGMENT_PATTERNS.DYNAMIC.test(segment);\n }\n}","import {SegmentParser} from './segmentParser';\nimport {ParserOptions, RouteFile, RouteNode} from \"../../types\";\n\nexport class RouteTreeBuilder {\n private readonly typeSetters: Record<string, (node: RouteNode, route: RouteFile) => void>;\n\n constructor() {\n this.typeSetters = {\n layout: (node, route) => {\n node.layout = route.componentName;\n },\n error: (node, route) => {\n node.error = route.componentName;\n },\n loading: (node, route) => {\n node.loading = route.componentName;\n },\n 'not-found': (node, route) => {\n node.notFound = route.componentName;\n },\n page: this.handlePageType.bind(this)\n };\n }\n\n build(routes: RouteFile[], options?: ParserOptions): RouteNode {\n const root: RouteNode = {\n segment: '',\n path: '/',\n fullPath: '/',\n children: new Map(),\n metadata: options?.metadata\n };\n\n const sortedRoutes = this.sortRoutes(routes);\n sortedRoutes.forEach(route => {\n this.processRoute(root, route, options);\n });\n\n return root;\n }\n\n private sortRoutes(routes: RouteFile[]): RouteFile[] {\n return [...routes].sort((a, b) =>\n a.type === 'layout' && b.type !== 'layout' ? -1 :\n a.type !== 'layout' && b.type === 'layout' ? 1 : 0\n );\n }\n\n private processRoute(root: RouteNode, route: RouteFile, options?: ParserOptions): void {\n const segments = route.segments.map(seg => String(seg));\n\n if (segments.length === 0) {\n this.applyTypeHandler(root, route);\n if (route.type === 'page') root.isIndex = true;\n return;\n }\n\n let current = root;\n let currentPath = '';\n\n segments.forEach((seg, idx) => {\n const isLast = idx === segments.length - 1;\n const key = SegmentParser.normalize(seg, options);\n\n if (key === null) return;\n\n currentPath = this.buildFullPath(currentPath, key);\n\n if (!current.children.has(key)) {\n current.children.set(key, {\n segment: key,\n path: key,\n fullPath: currentPath,\n children: new Map(),\n metadata: options?.metadata\n });\n }\n\n current = current.children.get(key)!;\n\n if (isLast) this.applyTypeHandler(current, route);\n });\n }\n\n private buildFullPath(currentPath: string, key: string): string {\n if (currentPath === '' || currentPath === '/') {\n return key === '' ? '/' : `/${key}`;\n }\n return `${currentPath}/${key}`;\n }\n\n private applyTypeHandler(node: RouteNode, route: RouteFile): void {\n const handler = this.typeSetters[route.type];\n if (handler) handler(node, route);\n }\n\n private handlePageType(node: RouteNode, route: RouteFile): void {\n const lastSegment = route.segments[route.segments.length - 1];\n const isDynamic = lastSegment?.startsWith('[');\n\n if (isDynamic || lastSegment === '') {\n node.component = route.componentName;\n node.isIndex = false;\n } else {\n node.indexPage = route.componentName;\n }\n }\n}","import { RouteNode } from \"../../types\";\n\nexport class RouteDefinitionGenerator {\n static generate(node: RouteNode, indent = ' '): string {\n const childNodes = Array.from(node.children.values());\n const children: string[] = [];\n\n if (node.indexPage) {\n children.push(this.generateIndexRoute(node, indent));\n }\n\n children.push(...childNodes.map(child =>\n this.generate(child, indent + ' ')\n ));\n\n return this.generateRouteObject(node, children, indent);\n }\n\n private static generateIndexRoute(node: RouteNode, indent: string): string {\n return `${indent} {\n${indent} index: true,\n${indent} element: React.createElement(RouteWrapper, {\n${indent} Component: ${node.indexPage}\n${indent} })\n${indent} }`;\n }\n\n private static generateRouteObject(node: RouteNode, children: string[], indent: string): string {\n const pathStr = node.fullPath;\n const elementStr = this.generateElementString(node, indent);\n const errorStr = this.generateErrorString(node, indent);\n\n return [\n `${indent}{`,\n `${indent} path: '${pathStr}'${elementStr}${errorStr}`,\n children.length > 0 ? `,\\n${indent} children: [\\n${children.join(',\\n')}\\n${indent} ]` : '',\n `${indent}}`\n ].filter(Boolean).join('');\n }\n\n private static generateElementString(node: RouteNode, indent: string): string {\n if (!node.layout && !node.component) return '';\n\n const props = node.layout\n ? this.generateLayoutProps(node, indent)\n : this.generateComponentProps(node, indent);\n\n return `,\\n${indent} element: React.createElement(RouteWrapper, ${props})`;\n }\n\n private static generateLayoutProps(node: RouteNode, indent: string): string {\n return `{\n${indent} Component: ${node.layout},\n${indent} isLayout: true,\n${indent} loading: ${node.loading || 'undefined'},\n${indent} notFound: ${node.notFound || 'undefined'}\n${indent} }`;\n }\n\n private static generateComponentProps(node: RouteNode, indent: string): string {\n return `{\n${indent} Component: ${node.component}\n${indent} }`;\n }\n\n private static generateErrorString(node: RouteNode, indent: string): string {\n if (!node.error) return '';\n\n return `,\\n${indent} errorElement: React.createElement(ErrorBoundary, {\n${indent} Component: ${node.error}\n${indent} })`;\n }\n}"],"mappings":"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","names":["path","path"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "navilo",
3
- "version": "1.2.2",
3
+ "version": "1.2.4",
4
4
  "description": "File-based routing plugin for Vite + React applications",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",