olova 2.0.59 → 2.0.61

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.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/entry-worker.tsx"],"names":["routes","layouts","jsx","Outlet","QueryClient","dehydrate","renderToString","StrictMode","QueryClientProvider","HydrationBoundary","Suspense","OlovaRouter","notFoundPages"],"mappings":"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","file":"entry-worker.cjs","sourcesContent":["/**\r\n * Olova Cloudflare Workers Entry\r\n * Auto-generated by plugin - handles SSR for routes with loaders only\r\n */\r\n\r\nimport { renderToString } from 'react-dom/server';\r\nimport { StrictMode, Suspense } from 'react';\r\nimport { QueryClient, QueryClientProvider, dehydrate, HydrationBoundary } from '@tanstack/react-query';\r\n// @ts-expect-error - Virtual module resolved by vite-plugin-olova\r\nimport { layouts, notFoundPages, OlovaRouter, Outlet, routes } from 'virtual:olova-app';\r\n\r\n// =============================================================================\r\n// TYPES\r\n// =============================================================================\r\n\r\ninterface RouteMatch {\r\n route: any;\r\n params: Record<string, string>;\r\n}\r\n\r\n// =============================================================================\r\n// ROUTE MATCHING\r\n// =============================================================================\r\n\r\nfunction matchRoute(pathname: string): RouteMatch | null {\r\n for (const route of routes) {\r\n // Exact match\r\n if (route.path === pathname) {\r\n return { route, params: {} };\r\n }\r\n\r\n // Dynamic segments\r\n if (route.path.includes(':') || route.path.includes('*')) {\r\n const pattern = route.path\r\n .replace(/\\*/g, '(.*)')\r\n .replace(/:[^/]+/g, '([^/]+)');\r\n const regex = new RegExp(`^${pattern}$`);\r\n const match = pathname.match(regex);\r\n\r\n if (match) {\r\n const params: Record<string, string> = {};\r\n const paramNames = route.path.match(/:[^/]+|\\*/g) || [];\r\n\r\n paramNames.forEach((name: string, i: number) => {\r\n const key = name === '*' ? '*' : name.slice(1);\r\n params[key] = match[i + 1];\r\n });\r\n\r\n return { route, params };\r\n }\r\n }\r\n }\r\n\r\n return null;\r\n}\r\n\r\n// =============================================================================\r\n// SSR RENDERING\r\n// =============================================================================\r\n\r\n// Wrapper to support \"children\" prop style layouts\r\nconst wrappedLayouts = layouts.map((item: any) => ({\r\n ...item,\r\n layout: (props: any) => (\r\n <item.layout {...props}>\r\n <Outlet />\r\n </item.layout>\r\n )\r\n}));\r\n\r\nasync function render(\r\n pathname: string,\r\n loaderData?: Record<string, unknown>\r\n): Promise<{ html: string; queryState: unknown }> {\r\n // Mock browser globals\r\n const g = globalThis as any;\r\n g.window = {\r\n location: { pathname, search: '', hash: '' },\r\n addEventListener: () => {},\r\n removeEventListener: () => {},\r\n history: { pushState: () => {}, replaceState: () => {} },\r\n __LOADER_DATA__: loaderData\r\n };\r\n g.__LOADER_DATA__ = loaderData;\r\n\r\n // Create QueryClient with pre-loaded data\r\n const queryClient = new QueryClient({\r\n defaultOptions: {\r\n queries: {\r\n staleTime: Infinity,\r\n gcTime: Infinity,\r\n },\r\n },\r\n });\r\n\r\n // Pre-populate query client with loader data\r\n if (loaderData) {\r\n Object.entries(loaderData).forEach(([key, value]) => {\r\n queryClient.setQueryData([key], value);\r\n });\r\n }\r\n\r\n // Get dehydrated state for client hydration\r\n const queryState = dehydrate(queryClient);\r\n\r\n const html = renderToString(\r\n <StrictMode>\r\n <QueryClientProvider client={queryClient}>\r\n <HydrationBoundary state={queryState}>\r\n <Suspense fallback={null}>\r\n <OlovaRouter\r\n routes={routes}\r\n layouts={wrappedLayouts}\r\n notFoundPages={notFoundPages}\r\n />\r\n </Suspense>\r\n </HydrationBoundary>\r\n </QueryClientProvider>\r\n </StrictMode>\r\n );\r\n\r\n return { html, queryState };\r\n}\r\n\r\n// =============================================================================\r\n// WORKER EXPORT\r\n// =============================================================================\r\n\r\nexport interface WorkerEnv {\r\n ASSETS: { fetch: (request: Request | URL) => Promise<Response> };\r\n}\r\n\r\nexport default {\r\n async fetch(request: Request, env: WorkerEnv): Promise<Response> {\r\n const url = new URL(request.url);\r\n const pathname = url.pathname;\r\n\r\n // 1. Non-HTML requests → serve static assets directly\r\n if (!request.headers.get('accept')?.includes('text/html')) {\r\n return env.ASSETS.fetch(request);\r\n }\r\n\r\n // 2. Check if route has loader (needs SSR)\r\n const match = matchRoute(pathname);\r\n const needsSSR = match?.route?.loader;\r\n\r\n // 3. No SSR needed → serve pre-built static HTML\r\n if (!needsSSR) {\r\n const staticPath = pathname === '/' ? '/index.html' : `${pathname}/index.html`;\r\n try {\r\n const staticResponse = await env.ASSETS.fetch(new URL(staticPath, url));\r\n if (staticResponse.ok) {\r\n return new Response(staticResponse.body, {\r\n status: 200,\r\n headers: { 'Content-Type': 'text/html; charset=utf-8' }\r\n });\r\n }\r\n } catch {}\r\n \r\n // Fallback to 404.html\r\n try {\r\n const notFoundResponse = await env.ASSETS.fetch(new URL('/404.html', url));\r\n return new Response(notFoundResponse.body, { \r\n status: 404, \r\n headers: { 'Content-Type': 'text/html; charset=utf-8' } \r\n });\r\n } catch {}\r\n \r\n return new Response('Not Found', { status: 404 });\r\n }\r\n\r\n // 4. Route has loader → run SSR\r\n let loaderData: Record<string, unknown> | undefined;\r\n\r\n try {\r\n const result = await match.route.loader({\r\n request,\r\n params: match.params\r\n });\r\n\r\n if (!(result instanceof Response)) {\r\n loaderData = result;\r\n }\r\n } catch (error) {\r\n console.error('[Olova] Loader error:', error);\r\n }\r\n\r\n // 5. Render with loader data\r\n const { html: appHtml, queryState } = await render(pathname, loaderData);\r\n\r\n // Build full HTML document\r\n const html = `<!DOCTYPE html>${appHtml}<script>window.__QUERY_STATE__=${JSON.stringify(queryState)}</script><script type=\"module\" src=\"/assets/_olova/main.js\"></script>`;\r\n\r\n return new Response(html, {\r\n headers: { 'Content-Type': 'text/html; charset=utf-8' }\r\n });\r\n }\r\n};\r\n\r\n// Export for SSG builds\r\nexport { render, matchRoute };\r\n"]}
1
+ {"version":3,"sources":["../src/entry-worker.tsx"],"names":["routes","layouts","jsx","Outlet","QueryClient","dehydrate","renderToString","StrictMode","QueryClientProvider","HydrationBoundary","Suspense","OlovaRouter","notFoundPages"],"mappings":"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","file":"entry-worker.cjs","sourcesContent":["/**\n * Olova Cloudflare Workers Entry\n * Auto-generated by plugin - handles SSR for routes with loaders only\n */\n\nimport { renderToString } from 'react-dom/server';\nimport { StrictMode, Suspense } from 'react';\nimport { QueryClient, QueryClientProvider, dehydrate, HydrationBoundary } from '@tanstack/react-query';\n// @ts-expect-error - Virtual module resolved by vite-plugin-olova\nimport { layouts, notFoundPages, OlovaRouter, Outlet, routes } from 'virtual:olova-app';\n\n// =============================================================================\n// TYPES\n// =============================================================================\n\ninterface RouteMatch {\n route: any;\n params: Record<string, string>;\n}\n\n// =============================================================================\n// ROUTE MATCHING\n// =============================================================================\n\nfunction matchRoute(pathname: string): RouteMatch | null {\n for (const route of routes) {\n // Exact match\n if (route.path === pathname) {\n return { route, params: {} };\n }\n\n // Dynamic segments\n if (route.path.includes(':') || route.path.includes('*')) {\n const pattern = route.path\n .replace(/\\*/g, '(.*)')\n .replace(/:[^/]+/g, '([^/]+)');\n const regex = new RegExp(`^${pattern}$`);\n const match = pathname.match(regex);\n\n if (match) {\n const params: Record<string, string> = {};\n const paramNames = route.path.match(/:[^/]+|\\*/g) || [];\n\n paramNames.forEach((name: string, i: number) => {\n const key = name === '*' ? '*' : name.slice(1);\n params[key] = match[i + 1];\n });\n\n return { route, params };\n }\n }\n }\n\n return null;\n}\n\n// =============================================================================\n// SSR RENDERING\n// =============================================================================\n\n// Wrapper to support \"children\" prop style layouts\nconst wrappedLayouts = layouts.map((item: any) => ({\n ...item,\n layout: (props: any) => (\n <item.layout {...props}>\n <Outlet />\n </item.layout>\n )\n}));\n\nasync function render(\n pathname: string,\n loaderData?: Record<string, unknown>\n): Promise<{ html: string; queryState: unknown }> {\n // Mock browser globals\n const g = globalThis as any;\n g.window = {\n location: { pathname, search: '', hash: '' },\n addEventListener: () => {},\n removeEventListener: () => {},\n history: { pushState: () => {}, replaceState: () => {} },\n __LOADER_DATA__: loaderData\n };\n g.__LOADER_DATA__ = loaderData;\n\n // Create QueryClient with pre-loaded data\n const queryClient = new QueryClient({\n defaultOptions: {\n queries: {\n staleTime: Infinity,\n gcTime: Infinity,\n },\n },\n });\n\n // Pre-populate query client with loader data\n if (loaderData) {\n Object.entries(loaderData).forEach(([key, value]) => {\n queryClient.setQueryData([key], value);\n });\n }\n\n // Get dehydrated state for client hydration\n const queryState = dehydrate(queryClient);\n\n const html = renderToString(\n <StrictMode>\n <QueryClientProvider client={queryClient}>\n <HydrationBoundary state={queryState}>\n <Suspense fallback={null}>\n <OlovaRouter\n routes={routes}\n layouts={wrappedLayouts}\n notFoundPages={notFoundPages}\n />\n </Suspense>\n </HydrationBoundary>\n </QueryClientProvider>\n </StrictMode>\n );\n\n return { html, queryState };\n}\n\n// =============================================================================\n// WORKER EXPORT\n// =============================================================================\n\nexport interface WorkerEnv {\n ASSETS: { fetch: (request: Request | URL) => Promise<Response> };\n}\n\nexport default {\n async fetch(request: Request, env: WorkerEnv): Promise<Response> {\n const url = new URL(request.url);\n const pathname = url.pathname;\n\n // 1. Non-HTML requests → serve static assets directly\n if (!request.headers.get('accept')?.includes('text/html')) {\n return env.ASSETS.fetch(request);\n }\n\n // 2. Check if route has loader (needs SSR)\n const match = matchRoute(pathname);\n const needsSSR = match?.route?.loader;\n\n // 3. No SSR needed → serve pre-built static HTML\n if (!needsSSR) {\n const staticPath = pathname === '/' ? '/index.html' : `${pathname}/index.html`;\n try {\n const staticResponse = await env.ASSETS.fetch(new URL(staticPath, url));\n if (staticResponse.ok) {\n return new Response(staticResponse.body, {\n status: 200,\n headers: { 'Content-Type': 'text/html; charset=utf-8' }\n });\n }\n } catch {}\n \n // Fallback to 404.html\n try {\n const notFoundResponse = await env.ASSETS.fetch(new URL('/404.html', url));\n return new Response(notFoundResponse.body, { \n status: 404, \n headers: { 'Content-Type': 'text/html; charset=utf-8' } \n });\n } catch {}\n \n return new Response('Not Found', { status: 404 });\n }\n\n // 4. Route has loader → run SSR\n let loaderData: Record<string, unknown> | undefined;\n\n try {\n const result = await match.route.loader({\n request,\n params: match.params\n });\n\n if (!(result instanceof Response)) {\n loaderData = result;\n }\n } catch (error) {\n console.error('[Olova] Loader error:', error);\n }\n\n // 5. Render with loader data\n const { html: appHtml, queryState } = await render(pathname, loaderData);\n\n // Build full HTML document\n const html = `<!DOCTYPE html>${appHtml}<script>window.__QUERY_STATE__=${JSON.stringify(queryState)}</script><script type=\"module\" src=\"/assets/_olova/main.js\"></script>`;\n\n return new Response(html, {\n headers: { 'Content-Type': 'text/html; charset=utf-8' }\n });\n }\n};\n\n// Export for SSG builds\nexport { render, matchRoute };\n"]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/entry-worker.tsx"],"names":[],"mappings":"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","file":"entry-worker.js","sourcesContent":["/**\r\n * Olova Cloudflare Workers Entry\r\n * Auto-generated by plugin - handles SSR for routes with loaders only\r\n */\r\n\r\nimport { renderToString } from 'react-dom/server';\r\nimport { StrictMode, Suspense } from 'react';\r\nimport { QueryClient, QueryClientProvider, dehydrate, HydrationBoundary } from '@tanstack/react-query';\r\n// @ts-expect-error - Virtual module resolved by vite-plugin-olova\r\nimport { layouts, notFoundPages, OlovaRouter, Outlet, routes } from 'virtual:olova-app';\r\n\r\n// =============================================================================\r\n// TYPES\r\n// =============================================================================\r\n\r\ninterface RouteMatch {\r\n route: any;\r\n params: Record<string, string>;\r\n}\r\n\r\n// =============================================================================\r\n// ROUTE MATCHING\r\n// =============================================================================\r\n\r\nfunction matchRoute(pathname: string): RouteMatch | null {\r\n for (const route of routes) {\r\n // Exact match\r\n if (route.path === pathname) {\r\n return { route, params: {} };\r\n }\r\n\r\n // Dynamic segments\r\n if (route.path.includes(':') || route.path.includes('*')) {\r\n const pattern = route.path\r\n .replace(/\\*/g, '(.*)')\r\n .replace(/:[^/]+/g, '([^/]+)');\r\n const regex = new RegExp(`^${pattern}$`);\r\n const match = pathname.match(regex);\r\n\r\n if (match) {\r\n const params: Record<string, string> = {};\r\n const paramNames = route.path.match(/:[^/]+|\\*/g) || [];\r\n\r\n paramNames.forEach((name: string, i: number) => {\r\n const key = name === '*' ? '*' : name.slice(1);\r\n params[key] = match[i + 1];\r\n });\r\n\r\n return { route, params };\r\n }\r\n }\r\n }\r\n\r\n return null;\r\n}\r\n\r\n// =============================================================================\r\n// SSR RENDERING\r\n// =============================================================================\r\n\r\n// Wrapper to support \"children\" prop style layouts\r\nconst wrappedLayouts = layouts.map((item: any) => ({\r\n ...item,\r\n layout: (props: any) => (\r\n <item.layout {...props}>\r\n <Outlet />\r\n </item.layout>\r\n )\r\n}));\r\n\r\nasync function render(\r\n pathname: string,\r\n loaderData?: Record<string, unknown>\r\n): Promise<{ html: string; queryState: unknown }> {\r\n // Mock browser globals\r\n const g = globalThis as any;\r\n g.window = {\r\n location: { pathname, search: '', hash: '' },\r\n addEventListener: () => {},\r\n removeEventListener: () => {},\r\n history: { pushState: () => {}, replaceState: () => {} },\r\n __LOADER_DATA__: loaderData\r\n };\r\n g.__LOADER_DATA__ = loaderData;\r\n\r\n // Create QueryClient with pre-loaded data\r\n const queryClient = new QueryClient({\r\n defaultOptions: {\r\n queries: {\r\n staleTime: Infinity,\r\n gcTime: Infinity,\r\n },\r\n },\r\n });\r\n\r\n // Pre-populate query client with loader data\r\n if (loaderData) {\r\n Object.entries(loaderData).forEach(([key, value]) => {\r\n queryClient.setQueryData([key], value);\r\n });\r\n }\r\n\r\n // Get dehydrated state for client hydration\r\n const queryState = dehydrate(queryClient);\r\n\r\n const html = renderToString(\r\n <StrictMode>\r\n <QueryClientProvider client={queryClient}>\r\n <HydrationBoundary state={queryState}>\r\n <Suspense fallback={null}>\r\n <OlovaRouter\r\n routes={routes}\r\n layouts={wrappedLayouts}\r\n notFoundPages={notFoundPages}\r\n />\r\n </Suspense>\r\n </HydrationBoundary>\r\n </QueryClientProvider>\r\n </StrictMode>\r\n );\r\n\r\n return { html, queryState };\r\n}\r\n\r\n// =============================================================================\r\n// WORKER EXPORT\r\n// =============================================================================\r\n\r\nexport interface WorkerEnv {\r\n ASSETS: { fetch: (request: Request | URL) => Promise<Response> };\r\n}\r\n\r\nexport default {\r\n async fetch(request: Request, env: WorkerEnv): Promise<Response> {\r\n const url = new URL(request.url);\r\n const pathname = url.pathname;\r\n\r\n // 1. Non-HTML requests → serve static assets directly\r\n if (!request.headers.get('accept')?.includes('text/html')) {\r\n return env.ASSETS.fetch(request);\r\n }\r\n\r\n // 2. Check if route has loader (needs SSR)\r\n const match = matchRoute(pathname);\r\n const needsSSR = match?.route?.loader;\r\n\r\n // 3. No SSR needed → serve pre-built static HTML\r\n if (!needsSSR) {\r\n const staticPath = pathname === '/' ? '/index.html' : `${pathname}/index.html`;\r\n try {\r\n const staticResponse = await env.ASSETS.fetch(new URL(staticPath, url));\r\n if (staticResponse.ok) {\r\n return new Response(staticResponse.body, {\r\n status: 200,\r\n headers: { 'Content-Type': 'text/html; charset=utf-8' }\r\n });\r\n }\r\n } catch {}\r\n \r\n // Fallback to 404.html\r\n try {\r\n const notFoundResponse = await env.ASSETS.fetch(new URL('/404.html', url));\r\n return new Response(notFoundResponse.body, { \r\n status: 404, \r\n headers: { 'Content-Type': 'text/html; charset=utf-8' } \r\n });\r\n } catch {}\r\n \r\n return new Response('Not Found', { status: 404 });\r\n }\r\n\r\n // 4. Route has loader → run SSR\r\n let loaderData: Record<string, unknown> | undefined;\r\n\r\n try {\r\n const result = await match.route.loader({\r\n request,\r\n params: match.params\r\n });\r\n\r\n if (!(result instanceof Response)) {\r\n loaderData = result;\r\n }\r\n } catch (error) {\r\n console.error('[Olova] Loader error:', error);\r\n }\r\n\r\n // 5. Render with loader data\r\n const { html: appHtml, queryState } = await render(pathname, loaderData);\r\n\r\n // Build full HTML document\r\n const html = `<!DOCTYPE html>${appHtml}<script>window.__QUERY_STATE__=${JSON.stringify(queryState)}</script><script type=\"module\" src=\"/assets/_olova/main.js\"></script>`;\r\n\r\n return new Response(html, {\r\n headers: { 'Content-Type': 'text/html; charset=utf-8' }\r\n });\r\n }\r\n};\r\n\r\n// Export for SSG builds\r\nexport { render, matchRoute };\r\n"]}
1
+ {"version":3,"sources":["../src/entry-worker.tsx"],"names":[],"mappings":"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","file":"entry-worker.js","sourcesContent":["/**\n * Olova Cloudflare Workers Entry\n * Auto-generated by plugin - handles SSR for routes with loaders only\n */\n\nimport { renderToString } from 'react-dom/server';\nimport { StrictMode, Suspense } from 'react';\nimport { QueryClient, QueryClientProvider, dehydrate, HydrationBoundary } from '@tanstack/react-query';\n// @ts-expect-error - Virtual module resolved by vite-plugin-olova\nimport { layouts, notFoundPages, OlovaRouter, Outlet, routes } from 'virtual:olova-app';\n\n// =============================================================================\n// TYPES\n// =============================================================================\n\ninterface RouteMatch {\n route: any;\n params: Record<string, string>;\n}\n\n// =============================================================================\n// ROUTE MATCHING\n// =============================================================================\n\nfunction matchRoute(pathname: string): RouteMatch | null {\n for (const route of routes) {\n // Exact match\n if (route.path === pathname) {\n return { route, params: {} };\n }\n\n // Dynamic segments\n if (route.path.includes(':') || route.path.includes('*')) {\n const pattern = route.path\n .replace(/\\*/g, '(.*)')\n .replace(/:[^/]+/g, '([^/]+)');\n const regex = new RegExp(`^${pattern}$`);\n const match = pathname.match(regex);\n\n if (match) {\n const params: Record<string, string> = {};\n const paramNames = route.path.match(/:[^/]+|\\*/g) || [];\n\n paramNames.forEach((name: string, i: number) => {\n const key = name === '*' ? '*' : name.slice(1);\n params[key] = match[i + 1];\n });\n\n return { route, params };\n }\n }\n }\n\n return null;\n}\n\n// =============================================================================\n// SSR RENDERING\n// =============================================================================\n\n// Wrapper to support \"children\" prop style layouts\nconst wrappedLayouts = layouts.map((item: any) => ({\n ...item,\n layout: (props: any) => (\n <item.layout {...props}>\n <Outlet />\n </item.layout>\n )\n}));\n\nasync function render(\n pathname: string,\n loaderData?: Record<string, unknown>\n): Promise<{ html: string; queryState: unknown }> {\n // Mock browser globals\n const g = globalThis as any;\n g.window = {\n location: { pathname, search: '', hash: '' },\n addEventListener: () => {},\n removeEventListener: () => {},\n history: { pushState: () => {}, replaceState: () => {} },\n __LOADER_DATA__: loaderData\n };\n g.__LOADER_DATA__ = loaderData;\n\n // Create QueryClient with pre-loaded data\n const queryClient = new QueryClient({\n defaultOptions: {\n queries: {\n staleTime: Infinity,\n gcTime: Infinity,\n },\n },\n });\n\n // Pre-populate query client with loader data\n if (loaderData) {\n Object.entries(loaderData).forEach(([key, value]) => {\n queryClient.setQueryData([key], value);\n });\n }\n\n // Get dehydrated state for client hydration\n const queryState = dehydrate(queryClient);\n\n const html = renderToString(\n <StrictMode>\n <QueryClientProvider client={queryClient}>\n <HydrationBoundary state={queryState}>\n <Suspense fallback={null}>\n <OlovaRouter\n routes={routes}\n layouts={wrappedLayouts}\n notFoundPages={notFoundPages}\n />\n </Suspense>\n </HydrationBoundary>\n </QueryClientProvider>\n </StrictMode>\n );\n\n return { html, queryState };\n}\n\n// =============================================================================\n// WORKER EXPORT\n// =============================================================================\n\nexport interface WorkerEnv {\n ASSETS: { fetch: (request: Request | URL) => Promise<Response> };\n}\n\nexport default {\n async fetch(request: Request, env: WorkerEnv): Promise<Response> {\n const url = new URL(request.url);\n const pathname = url.pathname;\n\n // 1. Non-HTML requests → serve static assets directly\n if (!request.headers.get('accept')?.includes('text/html')) {\n return env.ASSETS.fetch(request);\n }\n\n // 2. Check if route has loader (needs SSR)\n const match = matchRoute(pathname);\n const needsSSR = match?.route?.loader;\n\n // 3. No SSR needed → serve pre-built static HTML\n if (!needsSSR) {\n const staticPath = pathname === '/' ? '/index.html' : `${pathname}/index.html`;\n try {\n const staticResponse = await env.ASSETS.fetch(new URL(staticPath, url));\n if (staticResponse.ok) {\n return new Response(staticResponse.body, {\n status: 200,\n headers: { 'Content-Type': 'text/html; charset=utf-8' }\n });\n }\n } catch {}\n \n // Fallback to 404.html\n try {\n const notFoundResponse = await env.ASSETS.fetch(new URL('/404.html', url));\n return new Response(notFoundResponse.body, { \n status: 404, \n headers: { 'Content-Type': 'text/html; charset=utf-8' } \n });\n } catch {}\n \n return new Response('Not Found', { status: 404 });\n }\n\n // 4. Route has loader → run SSR\n let loaderData: Record<string, unknown> | undefined;\n\n try {\n const result = await match.route.loader({\n request,\n params: match.params\n });\n\n if (!(result instanceof Response)) {\n loaderData = result;\n }\n } catch (error) {\n console.error('[Olova] Loader error:', error);\n }\n\n // 5. Render with loader data\n const { html: appHtml, queryState } = await render(pathname, loaderData);\n\n // Build full HTML document\n const html = `<!DOCTYPE html>${appHtml}<script>window.__QUERY_STATE__=${JSON.stringify(queryState)}</script><script type=\"module\" src=\"/assets/_olova/main.js\"></script>`;\n\n return new Response(html, {\n headers: { 'Content-Type': 'text/html; charset=utf-8' }\n });\n }\n};\n\n// Export for SSG builds\nexport { render, matchRoute };\n"]}
package/dist/main.cjs CHANGED
@@ -1,43 +1,18 @@
1
1
  'use strict';
2
2
 
3
- require('@/index.css');
4
- var route_tree = require('@/route.tree');
5
3
  var react = require('react');
6
4
  var client = require('react-dom/client');
7
- var reactQuery = require('@tanstack/react-query');
5
+ var virtual_olovaApp = require('virtual:olova-app');
8
6
  var jsxRuntime = require('react/jsx-runtime');
9
7
 
10
- // main.tsx
11
- var layouts = route_tree.layouts.map((item) => ({
8
+ // src/main.tsx
9
+ var wrappedLayouts = virtual_olovaApp.layouts.map((item) => ({
12
10
  ...item,
13
- layout: (props) => /* @__PURE__ */ jsxRuntime.jsx(item.layout, { ...props, children: /* @__PURE__ */ jsxRuntime.jsx(route_tree.Outlet, {}) })
11
+ layout: (props) => /* @__PURE__ */ jsxRuntime.jsx(item.layout, { ...props, children: /* @__PURE__ */ jsxRuntime.jsx(virtual_olovaApp.Outlet, {}) })
14
12
  }));
15
13
  var isBrowser = typeof window !== "undefined" && !undefined.SSR;
16
- function getOlova() {
17
- if (typeof globalThis === "undefined") return null;
18
- return globalThis.$OLOVA || null;
19
- }
20
- function getQueryState() {
21
- const olova = getOlova();
22
- return olova?.$query?.state || null;
23
- }
24
14
  if (isBrowser) {
25
- if (undefined?.DEV) {
26
- const olova = getOlova();
27
- if (olova) {
28
- console.log("[Olova] Flight hydrated:", Object.keys(olova));
29
- }
30
- }
31
- const queryState = getQueryState();
32
- const queryClient = new reactQuery.QueryClient({
33
- defaultOptions: {
34
- queries: {
35
- staleTime: 1e3 * 60 * 5,
36
- gcTime: 1e3 * 60 * 30
37
- }
38
- }
39
- });
40
- client.hydrateRoot(document, /* @__PURE__ */ jsxRuntime.jsx(react.StrictMode, { children: /* @__PURE__ */ jsxRuntime.jsx(reactQuery.QueryClientProvider, { client: queryClient, children: /* @__PURE__ */ jsxRuntime.jsx(reactQuery.HydrationBoundary, { state: queryState || {}, children: /* @__PURE__ */ jsxRuntime.jsx(route_tree.OlovaRouter, { routes: route_tree.routes, layouts, notFoundPages: route_tree.notFoundPages }) }) }) }));
15
+ client.hydrateRoot(document, /* @__PURE__ */ jsxRuntime.jsx(react.StrictMode, { children: /* @__PURE__ */ jsxRuntime.jsx(virtual_olovaApp.OlovaRouter, { routes: virtual_olovaApp.routes, layouts: wrappedLayouts, notFoundPages: virtual_olovaApp.notFoundPages }) }));
41
16
  }
42
17
  //# sourceMappingURL=main.cjs.map
43
18
  //# sourceMappingURL=main.cjs.map
package/dist/main.cjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../main.tsx"],"names":["originalLayouts","jsx","Outlet","QueryClient","hydrateRoot","StrictMode","QueryClientProvider","HydrationBoundary","OlovaRouter","routes","notFoundPages"],"mappings":";;;;;;;;;;AAQA,IAAM,OAAA,GAAUA,kBAAA,CAAgB,GAAA,CAAI,CAAC,IAAA,MAAe;AAAA,EAClD,GAAG,IAAA;AAAA,EACH,MAAA,EAAQ,CAAC,KAAA,qBACPC,cAAA,CAAC,IAAA,CAAK,MAAA,EAAL,EAAa,GAAG,KAAA,EACf,QAAA,kBAAAA,cAAA,CAACC,iBAAA,EAAA,EAAO,CAAA,EACV;AAEJ,CAAA,CAAE,CAAA;AAEF,IAAM,YAAY,OAAO,MAAA,KAAW,WAAA,IAAe,CAAE,SAAoB,CAAI,GAAA;AAK7E,SAAS,QAAA,GAAgB;AACvB,EAAA,IAAI,OAAO,UAAA,KAAe,WAAA,EAAa,OAAO,IAAA;AAC9C,EAAA,OAAQ,WAAmB,MAAA,IAAU,IAAA;AACvC;AAKA,SAAS,aAAA,GAAqB;AAC5B,EAAA,MAAM,QAAQ,QAAA,EAAS;AACvB,EAAA,OAAO,KAAA,EAAO,QAAQ,KAAA,IAAS,IAAA;AACjC;AAUA,IAAI,SAAA,EAAW;AAEb,EAAA,IAAI,WAAiB,GAAA,EAAK;AACxB,IAAA,MAAM,QAAQ,QAAA,EAAS;AACvB,IAAA,IAAI,KAAA,EAAO;AACT,MAAA,OAAA,CAAQ,GAAA,CAAI,0BAAA,EAA4B,MAAA,CAAO,IAAA,CAAK,KAAK,CAAC,CAAA;AAAA,IAC5D;AAAA,EACF;AAGA,EAAA,MAAM,aAAa,aAAA,EAAc;AAGjC,EAAA,MAAM,WAAA,GAAc,IAAIC,sBAAA,CAAY;AAAA,IAClC,cAAA,EAAgB;AAAA,MACd,OAAA,EAAS;AAAA,QACP,SAAA,EAAW,MAAO,EAAA,GAAK,CAAA;AAAA,QACvB,MAAA,EAAQ,MAAO,EAAA,GAAK;AAAA;AACtB;AACF,GACD,CAAA;AAGD,EAAAC,kBAAA,CAAY,QAAA,iCACTC,gBAAA,EAAA,EACC,QAAA,kBAAAJ,cAAA,CAACK,kCAAoB,MAAA,EAAQ,WAAA,EAC3B,yCAACC,4BAAA,EAAA,EAAkB,KAAA,EAAO,cAAc,EAAC,EACvC,yCAACC,sBAAA,EAAA,UAAYC,iBAAA,EAAgB,wBAAkBC,wBAAA,EAA8B,CAAA,EAC/E,CAAA,EACF,CAAA,EACF,CACD,CAAA;AACH","file":"main.cjs","sourcesContent":["// @ts-nocheck - Path aliases resolved by Vite at runtime; tsconfig conflicts with plugins/tsconfig.json\r\nimport \"@/index.css\";\r\nimport { notFoundPages, OlovaRouter, layouts as originalLayouts, Outlet, routes } from '@/route.tree';\r\nimport { StrictMode } from 'react';\r\nimport { hydrateRoot } from 'react-dom/client';\r\nimport { QueryClient, QueryClientProvider, HydrationBoundary } from '@tanstack/react-query';\r\n\r\n// Wrapper to support \"children\" prop style layouts (Next.js style)\r\nconst layouts = originalLayouts.map((item: any) => ({\r\n ...item,\r\n layout: (props: any) => (\r\n <item.layout {...props}>\r\n <Outlet />\r\n </item.layout>\r\n )\r\n}));\r\n\r\nconst isBrowser = typeof window !== 'undefined' && !(import.meta as any).env.SSR;\r\n\r\n/**\r\n * Get the global $OLOVA object (populated by Flight runtime)\r\n */\r\nfunction getOlova(): any {\r\n if (typeof globalThis === 'undefined') return null;\r\n return (globalThis as any).$OLOVA || null;\r\n}\r\n\r\n/**\r\n * Get TanStack Query state from Flight hydration\r\n */\r\nfunction getQueryState(): any {\r\n const olova = getOlova();\r\n return olova?.$query?.state || null;\r\n}\r\n\r\n/**\r\n * Get loader data from Flight hydration\r\n */\r\nfunction getLoaderData(): any {\r\n const olova = getOlova();\r\n return olova?.$loader?.data || null;\r\n}\r\n\r\nif (isBrowser) {\r\n // Dev logging\r\n if (import.meta.env?.DEV) {\r\n const olova = getOlova();\r\n if (olova) {\r\n console.log('[Olova] Flight hydrated:', Object.keys(olova));\r\n }\r\n }\r\n\r\n // Get pre-hydrated state from Flight runtime\r\n const queryState = getQueryState();\r\n \r\n // Create QueryClient\r\n const queryClient = new QueryClient({\r\n defaultOptions: {\r\n queries: {\r\n staleTime: 1000 * 60 * 5,\r\n gcTime: 1000 * 60 * 30,\r\n },\r\n },\r\n });\r\n\r\n // Hydrate with pre-loaded state\r\n hydrateRoot(document, (\r\n <StrictMode>\r\n <QueryClientProvider client={queryClient}>\r\n <HydrationBoundary state={queryState || {}}>\r\n <OlovaRouter routes={routes} layouts={layouts} notFoundPages={notFoundPages} />\r\n </HydrationBoundary>\r\n </QueryClientProvider>\r\n </StrictMode>\r\n ));\r\n}\r\n"]}
1
+ {"version":3,"sources":["../src/main.tsx"],"names":["layouts","jsx","Outlet","hydrateRoot","StrictMode","OlovaRouter","routes","notFoundPages"],"mappings":";;;;;;;;AAMA,IAAM,cAAA,GAAiBA,wBAAA,CAAQ,GAAA,CAAI,CAAC,IAAA,MAAe;AAAA,EACjD,GAAG,IAAA;AAAA,EACH,MAAA,EAAQ,CAAC,KAAA,qBACPC,cAAA,CAAC,IAAA,CAAK,MAAA,EAAL,EAAa,GAAG,KAAA,EACf,QAAA,kBAAAA,cAAA,CAACC,uBAAA,EAAA,EAAO,CAAA,EACV;AAEJ,CAAA,CAAE,CAAA;AAEF,IAAM,YAAY,OAAO,MAAA,KAAW,WAAA,IAAe,CAAE,SAAoB,CAAI,GAAA;AAE7E,IAAI,SAAA,EAAW;AACb,EAAAC,kBAAA,CAAY,QAAA,kBACVF,cAAA,CAACG,gBAAA,EAAA,EACC,QAAA,kBAAAH,cAAA,CAACI,4BAAA,EAAA,UAAYC,yBAAgB,OAAA,EAAS,cAAA,iBAAgBC,8BAAA,EAA8B,CAAA,EACtF,CACD,CAAA;AACH","file":"main.cjs","sourcesContent":["import { StrictMode } from 'react';\r\nimport { hydrateRoot } from 'react-dom/client';\r\n// @ts-expect-error - Virtual module resolved by vite-plugin-olova\r\nimport { layouts, notFoundPages, OlovaRouter, Outlet, routes } from 'virtual:olova-app';\r\n\r\n// Wrapper to support \"children\" prop style layouts (Next.js style)\r\nconst wrappedLayouts = layouts.map((item: any) => ({\r\n ...item,\r\n layout: (props: any) => (\r\n <item.layout {...props}>\r\n <Outlet />\r\n </item.layout>\r\n )\r\n}));\r\n\r\nconst isBrowser = typeof window !== 'undefined' && !(import.meta as any).env.SSR;\r\n\r\nif (isBrowser) {\r\n hydrateRoot(document, (\r\n <StrictMode>\r\n <OlovaRouter routes={routes} layouts={wrappedLayouts} notFoundPages={notFoundPages} />\r\n </StrictMode>\r\n ));\r\n}\r\n"]}
package/dist/main.js CHANGED
@@ -1,41 +1,16 @@
1
- import '@/index.css';
2
- import { layouts as layouts$1, Outlet, OlovaRouter, notFoundPages, routes } from '@/route.tree';
3
1
  import { StrictMode } from 'react';
4
2
  import { hydrateRoot } from 'react-dom/client';
5
- import { QueryClient, QueryClientProvider, HydrationBoundary } from '@tanstack/react-query';
3
+ import { layouts, Outlet, OlovaRouter, notFoundPages, routes } from 'virtual:olova-app';
6
4
  import { jsx } from 'react/jsx-runtime';
7
5
 
8
- // main.tsx
9
- var layouts = layouts$1.map((item) => ({
6
+ // src/main.tsx
7
+ var wrappedLayouts = layouts.map((item) => ({
10
8
  ...item,
11
9
  layout: (props) => /* @__PURE__ */ jsx(item.layout, { ...props, children: /* @__PURE__ */ jsx(Outlet, {}) })
12
10
  }));
13
11
  var isBrowser = typeof window !== "undefined" && !import.meta.env.SSR;
14
- function getOlova() {
15
- if (typeof globalThis === "undefined") return null;
16
- return globalThis.$OLOVA || null;
17
- }
18
- function getQueryState() {
19
- const olova = getOlova();
20
- return olova?.$query?.state || null;
21
- }
22
12
  if (isBrowser) {
23
- if (import.meta.env?.DEV) {
24
- const olova = getOlova();
25
- if (olova) {
26
- console.log("[Olova] Flight hydrated:", Object.keys(olova));
27
- }
28
- }
29
- const queryState = getQueryState();
30
- const queryClient = new QueryClient({
31
- defaultOptions: {
32
- queries: {
33
- staleTime: 1e3 * 60 * 5,
34
- gcTime: 1e3 * 60 * 30
35
- }
36
- }
37
- });
38
- hydrateRoot(document, /* @__PURE__ */ jsx(StrictMode, { children: /* @__PURE__ */ jsx(QueryClientProvider, { client: queryClient, children: /* @__PURE__ */ jsx(HydrationBoundary, { state: queryState || {}, children: /* @__PURE__ */ jsx(OlovaRouter, { routes, layouts, notFoundPages }) }) }) }));
13
+ hydrateRoot(document, /* @__PURE__ */ jsx(StrictMode, { children: /* @__PURE__ */ jsx(OlovaRouter, { routes, layouts: wrappedLayouts, notFoundPages }) }));
39
14
  }
40
15
  //# sourceMappingURL=main.js.map
41
16
  //# sourceMappingURL=main.js.map
package/dist/main.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../main.tsx"],"names":["originalLayouts"],"mappings":";;;;;;;;AAQA,IAAM,OAAA,GAAUA,SAAA,CAAgB,GAAA,CAAI,CAAC,IAAA,MAAe;AAAA,EAClD,GAAG,IAAA;AAAA,EACH,MAAA,EAAQ,CAAC,KAAA,qBACP,GAAA,CAAC,IAAA,CAAK,MAAA,EAAL,EAAa,GAAG,KAAA,EACf,QAAA,kBAAA,GAAA,CAAC,MAAA,EAAA,EAAO,CAAA,EACV;AAEJ,CAAA,CAAE,CAAA;AAEF,IAAM,YAAY,OAAO,MAAA,KAAW,WAAA,IAAe,CAAE,YAAoB,GAAA,CAAI,GAAA;AAK7E,SAAS,QAAA,GAAgB;AACvB,EAAA,IAAI,OAAO,UAAA,KAAe,WAAA,EAAa,OAAO,IAAA;AAC9C,EAAA,OAAQ,WAAmB,MAAA,IAAU,IAAA;AACvC;AAKA,SAAS,aAAA,GAAqB;AAC5B,EAAA,MAAM,QAAQ,QAAA,EAAS;AACvB,EAAA,OAAO,KAAA,EAAO,QAAQ,KAAA,IAAS,IAAA;AACjC;AAUA,IAAI,SAAA,EAAW;AAEb,EAAA,IAAI,MAAA,CAAA,IAAA,CAAY,KAAK,GAAA,EAAK;AACxB,IAAA,MAAM,QAAQ,QAAA,EAAS;AACvB,IAAA,IAAI,KAAA,EAAO;AACT,MAAA,OAAA,CAAQ,GAAA,CAAI,0BAAA,EAA4B,MAAA,CAAO,IAAA,CAAK,KAAK,CAAC,CAAA;AAAA,IAC5D;AAAA,EACF;AAGA,EAAA,MAAM,aAAa,aAAA,EAAc;AAGjC,EAAA,MAAM,WAAA,GAAc,IAAI,WAAA,CAAY;AAAA,IAClC,cAAA,EAAgB;AAAA,MACd,OAAA,EAAS;AAAA,QACP,SAAA,EAAW,MAAO,EAAA,GAAK,CAAA;AAAA,QACvB,MAAA,EAAQ,MAAO,EAAA,GAAK;AAAA;AACtB;AACF,GACD,CAAA;AAGD,EAAA,WAAA,CAAY,QAAA,sBACT,UAAA,EAAA,EACC,QAAA,kBAAA,GAAA,CAAC,uBAAoB,MAAA,EAAQ,WAAA,EAC3B,8BAAC,iBAAA,EAAA,EAAkB,KAAA,EAAO,cAAc,EAAC,EACvC,8BAAC,WAAA,EAAA,EAAY,MAAA,EAAgB,SAAkB,aAAA,EAA8B,CAAA,EAC/E,CAAA,EACF,CAAA,EACF,CACD,CAAA;AACH","file":"main.js","sourcesContent":["// @ts-nocheck - Path aliases resolved by Vite at runtime; tsconfig conflicts with plugins/tsconfig.json\r\nimport \"@/index.css\";\r\nimport { notFoundPages, OlovaRouter, layouts as originalLayouts, Outlet, routes } from '@/route.tree';\r\nimport { StrictMode } from 'react';\r\nimport { hydrateRoot } from 'react-dom/client';\r\nimport { QueryClient, QueryClientProvider, HydrationBoundary } from '@tanstack/react-query';\r\n\r\n// Wrapper to support \"children\" prop style layouts (Next.js style)\r\nconst layouts = originalLayouts.map((item: any) => ({\r\n ...item,\r\n layout: (props: any) => (\r\n <item.layout {...props}>\r\n <Outlet />\r\n </item.layout>\r\n )\r\n}));\r\n\r\nconst isBrowser = typeof window !== 'undefined' && !(import.meta as any).env.SSR;\r\n\r\n/**\r\n * Get the global $OLOVA object (populated by Flight runtime)\r\n */\r\nfunction getOlova(): any {\r\n if (typeof globalThis === 'undefined') return null;\r\n return (globalThis as any).$OLOVA || null;\r\n}\r\n\r\n/**\r\n * Get TanStack Query state from Flight hydration\r\n */\r\nfunction getQueryState(): any {\r\n const olova = getOlova();\r\n return olova?.$query?.state || null;\r\n}\r\n\r\n/**\r\n * Get loader data from Flight hydration\r\n */\r\nfunction getLoaderData(): any {\r\n const olova = getOlova();\r\n return olova?.$loader?.data || null;\r\n}\r\n\r\nif (isBrowser) {\r\n // Dev logging\r\n if (import.meta.env?.DEV) {\r\n const olova = getOlova();\r\n if (olova) {\r\n console.log('[Olova] Flight hydrated:', Object.keys(olova));\r\n }\r\n }\r\n\r\n // Get pre-hydrated state from Flight runtime\r\n const queryState = getQueryState();\r\n \r\n // Create QueryClient\r\n const queryClient = new QueryClient({\r\n defaultOptions: {\r\n queries: {\r\n staleTime: 1000 * 60 * 5,\r\n gcTime: 1000 * 60 * 30,\r\n },\r\n },\r\n });\r\n\r\n // Hydrate with pre-loaded state\r\n hydrateRoot(document, (\r\n <StrictMode>\r\n <QueryClientProvider client={queryClient}>\r\n <HydrationBoundary state={queryState || {}}>\r\n <OlovaRouter routes={routes} layouts={layouts} notFoundPages={notFoundPages} />\r\n </HydrationBoundary>\r\n </QueryClientProvider>\r\n </StrictMode>\r\n ));\r\n}\r\n"]}
1
+ {"version":3,"sources":["../src/main.tsx"],"names":[],"mappings":";;;;;;AAMA,IAAM,cAAA,GAAiB,OAAA,CAAQ,GAAA,CAAI,CAAC,IAAA,MAAe;AAAA,EACjD,GAAG,IAAA;AAAA,EACH,MAAA,EAAQ,CAAC,KAAA,qBACP,GAAA,CAAC,IAAA,CAAK,MAAA,EAAL,EAAa,GAAG,KAAA,EACf,QAAA,kBAAA,GAAA,CAAC,MAAA,EAAA,EAAO,CAAA,EACV;AAEJ,CAAA,CAAE,CAAA;AAEF,IAAM,YAAY,OAAO,MAAA,KAAW,WAAA,IAAe,CAAE,YAAoB,GAAA,CAAI,GAAA;AAE7E,IAAI,SAAA,EAAW;AACb,EAAA,WAAA,CAAY,QAAA,kBACV,GAAA,CAAC,UAAA,EAAA,EACC,QAAA,kBAAA,GAAA,CAAC,WAAA,EAAA,EAAY,QAAgB,OAAA,EAAS,cAAA,EAAgB,aAAA,EAA8B,CAAA,EACtF,CACD,CAAA;AACH","file":"main.js","sourcesContent":["import { StrictMode } from 'react';\r\nimport { hydrateRoot } from 'react-dom/client';\r\n// @ts-expect-error - Virtual module resolved by vite-plugin-olova\r\nimport { layouts, notFoundPages, OlovaRouter, Outlet, routes } from 'virtual:olova-app';\r\n\r\n// Wrapper to support \"children\" prop style layouts (Next.js style)\r\nconst wrappedLayouts = layouts.map((item: any) => ({\r\n ...item,\r\n layout: (props: any) => (\r\n <item.layout {...props}>\r\n <Outlet />\r\n </item.layout>\r\n )\r\n}));\r\n\r\nconst isBrowser = typeof window !== 'undefined' && !(import.meta as any).env.SSR;\r\n\r\nif (isBrowser) {\r\n hydrateRoot(document, (\r\n <StrictMode>\r\n <OlovaRouter routes={routes} layouts={wrappedLayouts} notFoundPages={notFoundPages} />\r\n </StrictMode>\r\n ));\r\n}\r\n"]}
package/dist/olova.cjs CHANGED
@@ -19,7 +19,7 @@ var mdx__default = /*#__PURE__*/_interopDefault(mdx);
19
19
  var pc__default = /*#__PURE__*/_interopDefault(pc);
20
20
  var zlib__default = /*#__PURE__*/_interopDefault(zlib);
21
21
 
22
- // node_modules/.pnpm/tsup@8.5.1_postcss@8.5.6_typescript@5.9.3/node_modules/tsup/assets/cjs_shims.js
22
+ // node_modules/tsup/assets/cjs_shims.js
23
23
  var getImportMetaUrl = () => typeof document === "undefined" ? new URL(`file:${__filename}`).href : document.currentScript && document.currentScript.tagName.toUpperCase() === "SCRIPT" ? document.currentScript.src : new URL("main.js", document.baseURI).href;
24
24
  var importMetaUrl = /* @__PURE__ */ getImportMetaUrl();
25
25
  function extractBalancedBraces(content, startIndex) {
@@ -206,7 +206,7 @@ function generateRouteTree(routes, notFoundPages, layouts, loadingPages, errorPa
206
206
  };
207
207
  const routeNames = [];
208
208
  const routeImports = routes.map((route) => {
209
- const relativePath = stripImportExtension("./" + path5__default.default.relative(srcDir, route.component).replace(/\\/g, "/"));
209
+ const relativePath = stripImportExtension("./app/" + path5__default.default.relative(srcDir, route.component).replace(/\\/g, "/"));
210
210
  const moduleName = getRouteName2(route.component, "RouteModule");
211
211
  const lazyName = getRouteName2(route.component, "Route");
212
212
  routeNames.push({ moduleName, lazyName, eager: true });
@@ -214,7 +214,7 @@ function generateRouteTree(routes, notFoundPages, layouts, loadingPages, errorPa
214
214
  }).join("\n");
215
215
  const notFoundNames = [];
216
216
  const notFoundImports = notFoundPages.map((nf) => {
217
- const relativePath = stripImportExtension("./" + path5__default.default.relative(srcDir, nf.filePath).replace(/\\/g, "/"));
217
+ const relativePath = stripImportExtension("./app/" + path5__default.default.relative(srcDir, nf.filePath).replace(/\\/g, "/"));
218
218
  if (nf.hasMetadata) {
219
219
  const moduleName = getRouteName2(nf.filePath, "NotFoundModule");
220
220
  notFoundNames.push(moduleName);
@@ -228,7 +228,7 @@ function generateRouteTree(routes, notFoundPages, layouts, loadingPages, errorPa
228
228
  }).join("\n");
229
229
  const layoutNames = [];
230
230
  const layoutImports = layouts.map((layout) => {
231
- const relativePath = stripImportExtension("./" + path5__default.default.relative(srcDir, layout.filePath).replace(/\\/g, "/"));
231
+ const relativePath = stripImportExtension("./app/" + path5__default.default.relative(srcDir, layout.filePath).replace(/\\/g, "/"));
232
232
  if (layout.hasMetadata) {
233
233
  const moduleName = getRouteName2(layout.filePath, "LayoutModule");
234
234
  layoutNames.push(moduleName);
@@ -242,7 +242,7 @@ function generateRouteTree(routes, notFoundPages, layouts, loadingPages, errorPa
242
242
  }).join("\n");
243
243
  const loadingNames = [];
244
244
  const loadingImports = loadingPages.map((lp) => {
245
- const relativePath = stripImportExtension("./" + path5__default.default.relative(srcDir, lp.filePath).replace(/\\/g, "/"));
245
+ const relativePath = stripImportExtension("./app/" + path5__default.default.relative(srcDir, lp.filePath).replace(/\\/g, "/"));
246
246
  const importName = getRouteName2(lp.filePath, "Loading");
247
247
  loadingNames.push(importName);
248
248
  if (lp.hasDefault) return `import ${importName} from '${relativePath}';`;
@@ -251,7 +251,7 @@ function generateRouteTree(routes, notFoundPages, layouts, loadingPages, errorPa
251
251
  }).join("\n");
252
252
  const errorNames = [];
253
253
  const errorImports = errorPages.map((ep) => {
254
- const relativePath = stripImportExtension("./" + path5__default.default.relative(srcDir, ep.filePath).replace(/\\/g, "/"));
254
+ const relativePath = stripImportExtension("./app/" + path5__default.default.relative(srcDir, ep.filePath).replace(/\\/g, "/"));
255
255
  const importName = getRouteName2(ep.filePath, "Error");
256
256
  errorNames.push(importName);
257
257
  if (ep.hasDefault) return `import ${importName} from '${relativePath}';`;
@@ -260,7 +260,7 @@ function generateRouteTree(routes, notFoundPages, layouts, loadingPages, errorPa
260
260
  }).join("\n");
261
261
  const middlewareNames = [];
262
262
  const middlewareImports = middlewares.map((mw) => {
263
- const relativePath = stripImportExtension("./" + path5__default.default.relative(srcDir, mw.filePath).replace(/\\/g, "/"));
263
+ const relativePath = stripImportExtension("./app/" + path5__default.default.relative(srcDir, mw.filePath).replace(/\\/g, "/"));
264
264
  const importName = getRouteName2(mw.filePath, "Middleware");
265
265
  middlewareNames.push(importName);
266
266
  if (mw.hasDefault) return `import ${importName} from '${relativePath}';`;
@@ -490,14 +490,12 @@ export type {
490
490
  `;
491
491
  }
492
492
  var RESERVED_NAMES = /* @__PURE__ */ new Set([
493
- "index",
493
+ "page",
494
494
  "layout",
495
495
  "loading",
496
496
  "error",
497
- "404",
497
+ "not-found",
498
498
  "middleware",
499
- "App",
500
- "main",
501
499
  "route.tree"
502
500
  ]);
503
501
  function scanDirectory(dir, rootDir, extensions, routes, notFoundPages, layouts, loadingPages, errorPages, middlewares, isRoot = false) {
@@ -539,15 +537,13 @@ function scanDirectory(dir, rootDir, extensions, routes, notFoundPages, layouts,
539
537
  path: isRoot ? "/" : routePath,
540
538
  filePath: fullPath
541
539
  });
542
- } else if (baseName === "404" && extensions.includes(ext)) {
540
+ } else if ((baseName === "not-found" || baseName === "404") && extensions.includes(ext)) {
543
541
  const relativeParts = path5__default.default.relative(rootDir, dir).split(path5__default.default.sep).filter(Boolean);
544
542
  const filteredParts = relativeParts.filter((p) => !isRouteGroup(p));
545
543
  const pathPrefix = isRoot ? "" : "/" + filteredParts.join("/");
546
544
  notFoundPages.push({ pathPrefix: pathPrefix || "", filePath: fullPath });
547
- } else if (isRoot && baseName === "App" && extensions.includes(ext)) {
548
- routes.push({ path: "/", filePath: fullPath, isDynamic: false, params: [] });
549
- } else if (!isRoot && baseName === "index" && extensions.includes(ext)) {
550
- const relativePath = path5__default.default.relative(rootDir, path5__default.default.dirname(fullPath));
545
+ } else if (baseName === "page" && extensions.includes(ext)) {
546
+ const relativePath = path5__default.default.relative(rootDir, dir);
551
547
  const { routePath, params } = pathToRoute(relativePath, path5__default.default.sep);
552
548
  routes.push({ path: routePath, filePath: fullPath, isDynamic: params.length > 0, params });
553
549
  } else if (!RESERVED_NAMES.has(baseName) && !baseName.endsWith(".d") && !baseName.startsWith("_") && extensions.includes(ext)) {
@@ -582,7 +578,7 @@ function scanRoutes(rootDir, extensions) {
582
578
 
583
579
  // src/plugin/index.ts
584
580
  function olovaRouter(options = {}) {
585
- const rootDir = options.rootDir || "src";
581
+ const rootDir = options.rootDir || "src/app";
586
582
  const extensions = options.extensions || [".tsx", ".ts", ".mdx"];
587
583
  const packageName = options.packageName || "olovastart";
588
584
  let config;
@@ -661,7 +657,7 @@ function olovaRouter(options = {}) {
661
657
  };
662
658
  });
663
659
  const content = generateRouteTree(routeConfigs, notFoundConfigs, layoutConfigs, loadingConfigs, errorConfigs, middlewareConfigs, absoluteRootDir, packageName);
664
- const treePath = path5__default.default.resolve(absoluteRootDir, "route.tree.ts");
660
+ const treePath = path5__default.default.resolve(config.root, "src", "route.tree.ts");
665
661
  const existing = fs3__default.default.existsSync(treePath) ? fs3__default.default.readFileSync(treePath, "utf-8") : "";
666
662
  if (existing !== content) {
667
663
  fs3__default.default.writeFileSync(treePath, content);
@@ -675,9 +671,9 @@ function olovaRouter(options = {}) {
675
671
  if (filename.includes("route.tree.ts")) return;
676
672
  const ext = path5__default.default.extname(filename);
677
673
  const isConfiguredExtension = extensions.includes(ext);
678
- const isIndexFile = filename.includes("index") && isConfiguredExtension;
679
- const isAppFile = filename.includes("App") && isConfiguredExtension;
674
+ const isPageFile = filename.includes("page") && isConfiguredExtension;
680
675
  const is404File = filename.includes("404") && isConfiguredExtension;
676
+ const isNotFoundFile = filename.includes("not-found") && isConfiguredExtension;
681
677
  const isLayoutFile = filename.includes("layout") && isConfiguredExtension;
682
678
  const isLoadingFile = filename.includes("loading") && isConfiguredExtension;
683
679
  const isErrorFile = filename.includes("error") && isConfiguredExtension;
@@ -685,8 +681,8 @@ function olovaRouter(options = {}) {
685
681
  const isDirectory = !filename.includes(".");
686
682
  const isDynamicSegment = filename.includes("[");
687
683
  const isRenameEvent = eventType === "rename";
688
- if (isIndexFile || isAppFile || is404File || isLayoutFile || isLoadingFile || isErrorFile || isMiddlewareFile || isDirectory || isDynamicSegment || isRenameEvent) {
689
- if (isIndexFile && filename) {
684
+ if (isPageFile || is404File || isNotFoundFile || isLayoutFile || isLoadingFile || isErrorFile || isMiddlewareFile || isDirectory || isDynamicSegment || isRenameEvent) {
685
+ if (isPageFile && filename) {
690
686
  const fullPath = path5__default.default.join(absoluteRootDir, filename);
691
687
  if (fs3__default.default.existsSync(fullPath)) {
692
688
  const stat = fs3__default.default.statSync(fullPath);