olova 2.0.55 → 2.0.56

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.
Files changed (84) hide show
  1. package/README.md +28 -288
  2. package/dist/chunk-23UAGQ6N.js +2208 -0
  3. package/dist/chunk-23UAGQ6N.js.map +1 -0
  4. package/dist/chunk-D7SIC5TC.js +367 -0
  5. package/dist/chunk-D7SIC5TC.js.map +1 -0
  6. package/dist/entry-server.cjs +2341 -0
  7. package/dist/entry-server.cjs.map +1 -0
  8. package/dist/entry-server.js +114 -0
  9. package/dist/entry-server.js.map +1 -0
  10. package/dist/entry-worker.cjs +2354 -0
  11. package/dist/entry-worker.cjs.map +1 -0
  12. package/dist/entry-worker.js +126 -0
  13. package/dist/entry-worker.js.map +1 -0
  14. package/dist/main.cjs +18 -0
  15. package/dist/main.cjs.map +1 -0
  16. package/dist/main.js +16 -0
  17. package/dist/main.js.map +1 -0
  18. package/dist/olova.cjs +1684 -0
  19. package/dist/olova.cjs.map +1 -0
  20. package/dist/olova.d.cts +72 -0
  21. package/dist/olova.d.ts +72 -0
  22. package/dist/olova.js +1325 -0
  23. package/dist/olova.js.map +1 -0
  24. package/dist/performance.cjs +386 -0
  25. package/dist/performance.cjs.map +1 -0
  26. package/dist/performance.js +3 -0
  27. package/dist/performance.js.map +1 -0
  28. package/dist/router.cjs +646 -0
  29. package/dist/router.cjs.map +1 -0
  30. package/dist/router.d.cts +113 -0
  31. package/dist/router.d.ts +113 -0
  32. package/dist/router.js +632 -0
  33. package/dist/router.js.map +1 -0
  34. package/main.tsx +76 -0
  35. package/olova.ts +619 -0
  36. package/package.json +42 -61
  37. package/src/entry-server.tsx +165 -0
  38. package/src/entry-worker.tsx +201 -0
  39. package/src/generator/index.ts +409 -0
  40. package/src/hydration/flight.ts +320 -0
  41. package/src/hydration/index.ts +12 -0
  42. package/src/hydration/types.ts +225 -0
  43. package/src/logger.ts +182 -0
  44. package/src/main.tsx +24 -0
  45. package/src/performance.ts +488 -0
  46. package/src/plugin/index.ts +204 -0
  47. package/src/router/ErrorBoundary.tsx +145 -0
  48. package/src/router/Link.tsx +117 -0
  49. package/src/router/OlovaRouter.tsx +354 -0
  50. package/src/router/Outlet.tsx +8 -0
  51. package/src/router/context.ts +117 -0
  52. package/src/router/index.ts +29 -0
  53. package/src/router/matching.ts +63 -0
  54. package/src/router/router.tsx +23 -0
  55. package/src/router/search-params.ts +29 -0
  56. package/src/scanner/index.ts +116 -0
  57. package/src/types/index.ts +191 -0
  58. package/src/utils/export.ts +85 -0
  59. package/src/utils/index.ts +4 -0
  60. package/src/utils/naming.ts +54 -0
  61. package/src/utils/path.ts +45 -0
  62. package/tsup.config.ts +35 -0
  63. package/CHANGELOG.md +0 -31
  64. package/LICENSE +0 -21
  65. package/dist/index.cjs +0 -883
  66. package/dist/index.cjs.map +0 -1
  67. package/dist/index.d.cts +0 -138
  68. package/dist/index.d.ts +0 -138
  69. package/dist/index.js +0 -832
  70. package/dist/index.js.map +0 -1
  71. package/dist/plugin.cjs +0 -927
  72. package/dist/plugin.cjs.map +0 -1
  73. package/dist/plugin.d.cts +0 -18
  74. package/dist/plugin.d.ts +0 -18
  75. package/dist/plugin.js +0 -894
  76. package/dist/plugin.js.map +0 -1
  77. package/dist/ssg.cjs +0 -637
  78. package/dist/ssg.cjs.map +0 -1
  79. package/dist/ssg.d.cts +0 -191
  80. package/dist/ssg.d.ts +0 -191
  81. package/dist/ssg.js +0 -585
  82. package/dist/ssg.js.map +0 -1
  83. package/dist/types-BT6YsBGO.d.cts +0 -143
  84. package/dist/types-BT6YsBGO.d.ts +0 -143
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/ssg/crawler.ts","../src/ssg/generator.ts","../src/ssg/renderer.ts","../src/ssg/html.ts","../src/ssg/prerender.ts","../src/ssg/index.ts","../src/plugin.ts"],"sourcesContent":["/**\r\n * SSG Route Crawler\r\n * \r\n * Discovers all routes from the app directory and determines\r\n * which pages should be statically generated.\r\n */\r\n\r\nimport fs from 'fs';\r\nimport path from 'path';\r\nimport type { SSGPageInfo, SSGConfig } from './types';\r\nimport type { Metadata } from '../types';\r\n\r\n/**\r\n * Crawl the app directory to discover all routes\r\n */\r\nexport async function crawlRoutes(config: SSGConfig): Promise<SSGPageInfo[]> {\r\n const appPath = path.resolve(config.root, config.appDir);\r\n \r\n if (!fs.existsSync(appPath)) {\r\n console.warn(`[olova-ssg] App directory not found: ${appPath}`);\r\n return [];\r\n }\r\n\r\n const pages: SSGPageInfo[] = [];\r\n await scanDirectory(appPath, '/', config, pages);\r\n \r\n return pages;\r\n}\r\n\r\n/**\r\n * Recursively scan directory for page files\r\n */\r\nasync function scanDirectory(\r\n dir: string,\r\n routePath: string,\r\n config: SSGConfig,\r\n pages: SSGPageInfo[]\r\n): Promise<void> {\r\n const entries = fs.readdirSync(dir, { withFileTypes: true });\r\n \r\n for (const entry of entries) {\r\n const fullPath = path.join(dir, entry.name);\r\n \r\n if (entry.isDirectory()) {\r\n // Handle different directory types\r\n const segment = entry.name;\r\n \r\n // Route group: (marketing) - doesn't add to URL\r\n if (segment.startsWith('(') && segment.endsWith(')')) {\r\n await scanDirectory(fullPath, routePath, config, pages);\r\n continue;\r\n }\r\n \r\n // Parallel routes: @modal - skip for static generation\r\n if (segment.startsWith('@')) {\r\n continue;\r\n }\r\n \r\n // Dynamic segment: [slug] or [...slug] or [[...slug]]\r\n if (segment.startsWith('[')) {\r\n // For automatic SSG without generateStaticParams, we skip dynamic routes\r\n // They will be handled as CSR-only\r\n // But still scan for any nested static pages\r\n const newRoutePath = buildDynamicRoutePath(routePath, segment);\r\n await scanDirectory(fullPath, newRoutePath, config, pages);\r\n continue;\r\n }\r\n \r\n // Static segment\r\n const newRoutePath = routePath === '/' \r\n ? `/${segment}` \r\n : `${routePath}/${segment}`;\r\n \r\n await scanDirectory(fullPath, newRoutePath, config, pages);\r\n } else if (entry.isFile()) {\r\n // Check if it's a page file\r\n const isPage = config.extensions.some(ext => entry.name === `page${ext}`);\r\n \r\n if (isPage) {\r\n // Determine if this is a static route (no dynamic segments in path)\r\n const isDynamicRoute = routePath.includes(':') || routePath.includes('*');\r\n \r\n // Extract metadata from the page file\r\n const { metadata, hasGenerateMetadata } = await extractPageMetadata(fullPath);\r\n \r\n pages.push({\r\n path: routePath || '/',\r\n componentPath: fullPath,\r\n isStatic: !isDynamicRoute,\r\n params: {},\r\n metadata,\r\n hasGenerateMetadata,\r\n });\r\n }\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Build route path for dynamic segments\r\n */\r\nfunction buildDynamicRoutePath(basePath: string, segment: string): string {\r\n let pathSegment: string;\r\n \r\n if (segment.startsWith('[[...') && segment.endsWith(']]')) {\r\n // Optional catch-all: [[...slug]]\r\n const paramName = segment.slice(5, -2);\r\n pathSegment = `:${paramName}*`;\r\n } else if (segment.startsWith('[...') && segment.endsWith(']')) {\r\n // Catch-all: [...slug]\r\n const paramName = segment.slice(4, -1);\r\n pathSegment = `:${paramName}*`;\r\n } else if (segment.startsWith('[') && segment.endsWith(']')) {\r\n // Dynamic: [slug]\r\n const paramName = segment.slice(1, -1);\r\n pathSegment = `:${paramName}`;\r\n } else {\r\n pathSegment = segment;\r\n }\r\n \r\n return basePath === '/' ? `/${pathSegment}` : `${basePath}/${pathSegment}`;\r\n}\r\n\r\n/**\r\n * Extract static metadata from a page file\r\n */\r\nasync function extractPageMetadata(filePath: string): Promise<{\r\n metadata: Metadata | null;\r\n hasGenerateMetadata: boolean;\r\n}> {\r\n try {\r\n const content = fs.readFileSync(filePath, 'utf-8');\r\n \r\n // Check for generateMetadata function\r\n const hasGenerateMetadata = /export\\s+(async\\s+)?function\\s+generateMetadata/.test(content);\r\n \r\n // Look for static metadata export\r\n const metadataMatch = content.match(/export\\s+const\\s+metadata\\s*=\\s*(\\{[\\s\\S]*?\\n\\};?)/);\r\n \r\n if (metadataMatch) {\r\n try {\r\n // Try to evaluate the metadata object\r\n const metadataStr = metadataMatch[1];\r\n const metadata = Function('\"use strict\"; return (' + metadataStr + ')')();\r\n return { metadata: metadata as Metadata, hasGenerateMetadata };\r\n } catch {\r\n // Fallback to simple extraction\r\n return { metadata: extractMetadataSimple(content), hasGenerateMetadata };\r\n }\r\n }\r\n \r\n return { metadata: null, hasGenerateMetadata };\r\n } catch (e) {\r\n console.warn(`[olova-ssg] Failed to extract metadata from ${filePath}`);\r\n return { metadata: null, hasGenerateMetadata: false };\r\n }\r\n}\r\n\r\n/**\r\n * Simple regex-based metadata extraction\r\n */\r\nfunction extractMetadataSimple(content: string): Metadata | null {\r\n const metadata: Metadata = {};\r\n \r\n const titleMatch = content.match(/title:\\s*['\"`]([^'\"`]+)['\"`]/);\r\n if (titleMatch) metadata.title = titleMatch[1];\r\n \r\n const descMatch = content.match(/description:\\s*['\"`]([^'\"`]+)['\"`]/);\r\n if (descMatch) metadata.description = descMatch[1];\r\n \r\n const keywordsMatch = content.match(/keywords:\\s*\\[([^\\]]+)\\]/);\r\n if (keywordsMatch) {\r\n const keywords = keywordsMatch[1]\r\n .split(',')\r\n .map(k => k.trim().replace(/['\"`]/g, ''))\r\n .filter(Boolean);\r\n if (keywords.length) metadata.keywords = keywords;\r\n }\r\n \r\n return Object.keys(metadata).length > 0 ? metadata : null;\r\n}\r\n\r\n/**\r\n * Get all static pages (pages without dynamic segments)\r\n */\r\nexport function getStaticPages(pages: SSGPageInfo[]): SSGPageInfo[] {\r\n return pages.filter(page => page.isStatic);\r\n}\r\n\r\n/**\r\n * Get all dynamic pages\r\n */\r\nexport function getDynamicPages(pages: SSGPageInfo[]): SSGPageInfo[] {\r\n return pages.filter(page => !page.isStatic);\r\n}\r\n","/**\r\n * SSG Entry Generator\r\n * \r\n * Generates a temporary SSR entry file that imports all page components\r\n * and exports a render function for pre-rendering.\r\n */\r\n\r\nimport fs from 'fs';\r\nimport path from 'path';\r\nimport type { SSGPageInfo, SSGConfig } from './types';\r\n\r\n/**\r\n * Generate the SSR entry file for pre-rendering\r\n */\r\nexport function generateSSREntry(\r\n pages: SSGPageInfo[],\r\n config: SSGConfig\r\n): string {\r\n const entryPath = path.resolve(config.root, '.olova-ssg-entry.tsx');\r\n \r\n // Generate imports for all page components\r\n const imports: string[] = [];\r\n const routeMap: string[] = [];\r\n \r\n // Find layout file in src/app\r\n const appDir = path.resolve(config.root, config.appDir);\r\n const layoutPath = findLayoutFile(appDir, config.extensions);\r\n \r\n if (layoutPath) {\r\n const relativePath = path.relative(config.root, layoutPath).replace(/\\\\/g, '/');\r\n imports.push(`import Layout from './${relativePath}';`);\r\n }\r\n \r\n pages.forEach((page, index) => {\r\n const relativePath = path.relative(config.root, page.componentPath).replace(/\\\\/g, '/');\r\n imports.push(`import Page${index} from './${relativePath}';`);\r\n routeMap.push(` '${page.path}': Page${index},`);\r\n });\r\n \r\n const entryContent = `\r\n// Auto-generated SSR entry for Olova SSG\r\nimport React from 'react';\r\nimport { renderToString } from 'react-dom/server';\r\nimport { setSSRContext } from 'olova';\r\n\r\n${imports.join('\\n')}\r\n\r\nconst routeComponents: Record<string, React.ComponentType<any>> = {\r\n${routeMap.join('\\n')}\r\n};\r\n\r\nexport async function render(routePath: string, params: Record<string, string> = {}) {\r\n const Component = routeComponents[routePath];\r\n \r\n if (!Component) {\r\n console.warn('[olova-ssg] No component found for route:', routePath);\r\n return '';\r\n }\r\n \r\n try {\r\n // Set the SSR context before rendering\r\n setSSRContext(routePath, params);\r\n \r\n // Build component hierarchy\r\n const pageElement = React.createElement(Component, { params, searchParams: {} });\r\n ${layoutPath \r\n ? `const element = React.createElement(Layout, { children: pageElement, params });`\r\n : `const element = pageElement;`\r\n }\r\n \r\n return renderToString(element);\r\n } catch (error: any) {\r\n console.error('[olova-ssg] SSR Error for', routePath, ':', error.message);\r\n throw error;\r\n }\r\n}\r\n\r\nexport const routes = ${JSON.stringify(pages.map(p => ({ path: p.path, isStatic: p.isStatic })), null, 2)};\r\n`;\r\n \r\n fs.writeFileSync(entryPath, entryContent, 'utf-8');\r\n \r\n return entryPath;\r\n}\r\n\r\n/**\r\n * Find layout file in directory\r\n */\r\nfunction findLayoutFile(dir: string, extensions: string[]): string | null {\r\n for (const ext of extensions) {\r\n const layoutPath = path.join(dir, `layout${ext}`);\r\n if (fs.existsSync(layoutPath)) {\r\n return layoutPath;\r\n }\r\n }\r\n return null;\r\n}\r\n\r\n/**\r\n * Clean up generated entry file\r\n */\r\nexport function cleanupSSREntry(entryPath: string): void {\r\n try {\r\n if (fs.existsSync(entryPath)) {\r\n fs.unlinkSync(entryPath);\r\n }\r\n } catch (e) {\r\n console.warn('[olova-ssg] Failed to cleanup SSR entry file');\r\n }\r\n}\r\n\r\n/**\r\n * Generate hydration script\r\n */\r\nexport function generateHydrationScript(routePath: string, params: Record<string, string>): string {\r\n return `\r\n<script>\r\n window.__OLOVA_DATA__ = ${JSON.stringify({ route: routePath, params, hydrated: false })};\r\n</script>\r\n`;\r\n}\r\n","/**\r\n * SSG Page Renderer\r\n * \r\n * Renders React components to HTML strings using react-dom/server.\r\n */\r\n\r\nimport fs from 'fs';\r\nimport path from 'path';\r\nimport { pathToFileURL } from 'url';\r\nimport { build as viteBuild } from 'vite';\r\nimport type { SSGPageInfo, SSGConfig } from './types';\r\nimport type { Metadata } from '../types';\r\n\r\ninterface RenderResult {\r\n content: string;\r\n metadata: Metadata | null;\r\n}\r\n\r\n/**\r\n * Render a page to static HTML\r\n */\r\nexport async function renderPage(\r\n page: SSGPageInfo,\r\n config: SSGConfig,\r\n ssrEntryPath: string\r\n): Promise<RenderResult> {\r\n const tempSSRDir = path.join(config.root, '.olova', 'ssr');\r\n \r\n // Ensure directory exists\r\n if (!fs.existsSync(tempSSRDir)) {\r\n fs.mkdirSync(tempSSRDir, { recursive: true });\r\n }\r\n \r\n // Ensure package.json for ESM\r\n const pkgPath = path.join(tempSSRDir, 'package.json');\r\n if (!fs.existsSync(pkgPath)) {\r\n fs.writeFileSync(pkgPath, JSON.stringify({ type: 'module' }));\r\n }\r\n \r\n const outputFileName = `ssr-entry-${Date.now()}.js`;\r\n const outputPath = path.join(tempSSRDir, outputFileName);\r\n \r\n try {\r\n // Build SSR bundle\r\n await viteBuild({\r\n configFile: false,\r\n root: config.root,\r\n logLevel: 'silent',\r\n build: {\r\n ssr: true,\r\n write: true,\r\n outDir: tempSSRDir,\r\n emptyOutDir: false,\r\n rollupOptions: {\r\n input: ssrEntryPath,\r\n output: {\r\n format: 'esm',\r\n entryFileNames: outputFileName,\r\n },\r\n onwarn: (warning, handler) => {\r\n // Suppress module level directive warnings\r\n if (warning.code === 'MODULE_LEVEL_DIRECTIVE') return;\r\n handler(warning);\r\n },\r\n },\r\n },\r\n plugins: [\r\n {\r\n name: 'olova-ssr-transforms',\r\n transform(code) {\r\n // Remove 'use client' and 'use static' directives\r\n return code\r\n .replace(/['\"]use client['\"];?/g, '')\r\n .replace(/['\"]use static['\"];?/g, '');\r\n },\r\n },\r\n ],\r\n });\r\n \r\n // Import and execute the SSR module\r\n if (fs.existsSync(outputPath)) {\r\n const moduleUrl = pathToFileURL(outputPath).href;\r\n const mod = await import(moduleUrl);\r\n \r\n const content = await mod.render(page.path, page.params);\r\n \r\n return {\r\n content: content || '',\r\n metadata: page.metadata,\r\n };\r\n }\r\n \r\n throw new Error('Built SSR artifact not found');\r\n } finally {\r\n // Cleanup\r\n if (fs.existsSync(outputPath)) {\r\n try {\r\n fs.unlinkSync(outputPath);\r\n } catch {\r\n // Ignore cleanup errors\r\n }\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Batch render multiple pages\r\n */\r\nexport async function renderPages(\r\n pages: SSGPageInfo[],\r\n config: SSGConfig,\r\n ssrEntryPath: string,\r\n onProgress?: (page: SSGPageInfo, index: number, total: number) => void\r\n): Promise<Map<string, RenderResult>> {\r\n const results = new Map<string, RenderResult>();\r\n \r\n for (let i = 0; i < pages.length; i++) {\r\n const page = pages[i];\r\n \r\n if (onProgress) {\r\n onProgress(page, i, pages.length);\r\n }\r\n \r\n try {\r\n const result = await renderPage(page, config, ssrEntryPath);\r\n results.set(page.path, result);\r\n } catch (error: any) {\r\n console.error(`[olova-ssg] Failed to render ${page.path}:`, error.message);\r\n results.set(page.path, { content: '', metadata: page.metadata });\r\n }\r\n }\r\n \r\n return results;\r\n}\r\n","/**\r\n * SSG HTML Generator\r\n * \r\n * Generates final HTML documents with pre-rendered content,\r\n * asset references, and hydration scripts.\r\n */\r\n\r\nimport fs from 'fs';\r\nimport path from 'path';\r\nimport type { HTMLGenerateOptions, SSGConfig } from './types';\r\nimport type { Metadata } from '../types';\r\n\r\n/**\r\n * Generate complete HTML document\r\n */\r\nexport function generateHTML(options: HTMLGenerateOptions): string {\r\n const {\r\n content,\r\n jsEntry,\r\n cssEntries,\r\n metadata,\r\n routePath,\r\n params,\r\n } = options;\r\n \r\n const metaTags = metadata ? generateMetaTags(metadata) : '';\r\n const cssLinks = cssEntries.map(css => `<link rel=\"stylesheet\" href=\"${css}\">`).join('\\n ');\r\n \r\n return `<!doctype html>\r\n<html lang=\"en\">\r\n <head>\r\n <meta charset=\"UTF-8\" />\r\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\r\n ${metaTags}\r\n ${cssLinks}\r\n </head>\r\n <body>\r\n <div id=\"root\">${content}</div>\r\n <script>\r\n window.__OLOVA_DATA__ = ${JSON.stringify({ route: routePath, params, hydrated: false })};\r\n </script>\r\n ${jsEntry ? `<script type=\"module\" src=\"${jsEntry}\"></script>` : ''}\r\n </body>\r\n</html>`;\r\n}\r\n\r\n/**\r\n * Generate meta tags from metadata\r\n */\r\nexport function generateMetaTags(metadata: Metadata): string {\r\n const tags: string[] = [];\r\n \r\n if (metadata.title) {\r\n tags.push(`<title>${escapeHtml(metadata.title)}</title>`);\r\n }\r\n \r\n if (metadata.description) {\r\n tags.push(`<meta name=\"description\" content=\"${escapeHtml(metadata.description)}\" />`);\r\n }\r\n \r\n if (metadata.keywords?.length) {\r\n tags.push(`<meta name=\"keywords\" content=\"${escapeHtml(metadata.keywords.join(', '))}\" />`);\r\n }\r\n \r\n if (metadata.robots) {\r\n tags.push(`<meta name=\"robots\" content=\"${escapeHtml(metadata.robots)}\" />`);\r\n }\r\n \r\n if (metadata.canonical) {\r\n tags.push(`<link rel=\"canonical\" href=\"${escapeHtml(metadata.canonical)}\" />`);\r\n }\r\n \r\n // Open Graph\r\n if (metadata.openGraph) {\r\n const og = metadata.openGraph;\r\n if (og.title) {\r\n tags.push(`<meta property=\"og:title\" content=\"${escapeHtml(og.title)}\" />`);\r\n }\r\n if (og.description) {\r\n tags.push(`<meta property=\"og:description\" content=\"${escapeHtml(og.description)}\" />`);\r\n }\r\n if (og.url) {\r\n tags.push(`<meta property=\"og:url\" content=\"${escapeHtml(og.url)}\" />`);\r\n }\r\n if (og.siteName) {\r\n tags.push(`<meta property=\"og:site_name\" content=\"${escapeHtml(og.siteName)}\" />`);\r\n }\r\n if (og.type) {\r\n tags.push(`<meta property=\"og:type\" content=\"${og.type}\" />`);\r\n }\r\n if (og.images?.length) {\r\n for (const image of og.images) {\r\n tags.push(`<meta property=\"og:image\" content=\"${escapeHtml(image.url)}\" />`);\r\n if (image.width) {\r\n tags.push(`<meta property=\"og:image:width\" content=\"${image.width}\" />`);\r\n }\r\n if (image.height) {\r\n tags.push(`<meta property=\"og:image:height\" content=\"${image.height}\" />`);\r\n }\r\n if (image.alt) {\r\n tags.push(`<meta property=\"og:image:alt\" content=\"${escapeHtml(image.alt)}\" />`);\r\n }\r\n }\r\n }\r\n }\r\n \r\n // Twitter Card\r\n if (metadata.twitter) {\r\n const tw = metadata.twitter;\r\n if (tw.card) {\r\n tags.push(`<meta name=\"twitter:card\" content=\"${tw.card}\" />`);\r\n }\r\n if (tw.title) {\r\n tags.push(`<meta name=\"twitter:title\" content=\"${escapeHtml(tw.title)}\" />`);\r\n }\r\n if (tw.description) {\r\n tags.push(`<meta name=\"twitter:description\" content=\"${escapeHtml(tw.description)}\" />`);\r\n }\r\n if (tw.creator) {\r\n tags.push(`<meta name=\"twitter:creator\" content=\"${escapeHtml(tw.creator)}\" />`);\r\n }\r\n if (tw.site) {\r\n tags.push(`<meta name=\"twitter:site\" content=\"${escapeHtml(tw.site)}\" />`);\r\n }\r\n if (tw.images?.length) {\r\n tags.push(`<meta name=\"twitter:image\" content=\"${escapeHtml(tw.images[0])}\" />`);\r\n }\r\n }\r\n \r\n // Authors\r\n if (metadata.authors?.length) {\r\n for (const author of metadata.authors) {\r\n tags.push(`<meta name=\"author\" content=\"${escapeHtml(author.name)}\" />`);\r\n }\r\n }\r\n \r\n return tags.join('\\n ');\r\n}\r\n\r\n/**\r\n * Discover JS and CSS entries from the build output\r\n */\r\nexport function discoverBuildAssets(distDir: string): { jsEntry: string; cssEntries: string[] } {\r\n let jsEntry = '';\r\n const cssEntries: string[] = [];\r\n \r\n const assetsDir = path.join(distDir, 'assets');\r\n \r\n if (fs.existsSync(assetsDir)) {\r\n const assets = fs.readdirSync(assetsDir);\r\n \r\n for (const asset of assets) {\r\n if (asset.startsWith('index') && asset.endsWith('.js')) {\r\n jsEntry = `/assets/${asset}`;\r\n } else if (asset.endsWith('.css')) {\r\n cssEntries.push(`/assets/${asset}`);\r\n }\r\n }\r\n }\r\n \r\n return { jsEntry, cssEntries };\r\n}\r\n\r\n/**\r\n * Update existing HTML with pre-rendered content\r\n */\r\nexport function injectContentIntoHTML(\r\n baseHtml: string,\r\n content: string,\r\n metadata: Metadata | null\r\n): string {\r\n let html = baseHtml;\r\n \r\n // Inject pre-rendered content into root div\r\n html = html.replace(\r\n /<div id=\"root\"[^>]*>[\\s\\S]*?<\\/div>/,\r\n `<div id=\"root\">${content}</div>`\r\n );\r\n \r\n // Inject metadata if provided\r\n if (metadata) {\r\n const metaTags = generateMetaTags(metadata);\r\n \r\n // Remove existing title if we have a new one\r\n if (metadata.title) {\r\n html = html.replace(/<title>[^<]*<\\/title>/g, '');\r\n }\r\n \r\n // Remove existing description\r\n if (metadata.description) {\r\n html = html.replace(/<meta\\s+name=\"description\"[^>]*>/g, '');\r\n }\r\n \r\n // Remove existing OG tags\r\n if (metadata.openGraph) {\r\n html = html.replace(/<meta\\s+property=\"og:[^\"]*\"[^>]*>/g, '');\r\n }\r\n \r\n // Remove existing Twitter tags\r\n if (metadata.twitter) {\r\n html = html.replace(/<meta\\s+name=\"twitter:[^\"]*\"[^>]*>/g, '');\r\n }\r\n \r\n // Inject new metadata after <head>\r\n html = html.replace(/<head>/, `<head>\\n ${metaTags}`);\r\n }\r\n \r\n return html;\r\n}\r\n\r\n/**\r\n * Escape HTML special characters\r\n */\r\nfunction escapeHtml(text: string): string {\r\n return text\r\n .replace(/&/g, '&amp;')\r\n .replace(/</g, '&lt;')\r\n .replace(/>/g, '&gt;')\r\n .replace(/\"/g, '&quot;')\r\n .replace(/'/g, '&#039;');\r\n}\r\n\r\n/**\r\n * Generate sitemap.xml\r\n */\r\nexport function generateSitemap(\r\n pages: { path: string }[],\r\n siteUrl: string\r\n): string {\r\n const urls = pages.map(page => ` <url>\r\n <loc>${siteUrl}${page.path === '/' ? '' : page.path}</loc>\r\n <lastmod>${new Date().toISOString().split('T')[0]}</lastmod>\r\n <changefreq>daily</changefreq>\r\n <priority>${page.path === '/' ? '1.0' : '0.8'}</priority>\r\n </url>`).join('\\n');\r\n \r\n return `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n<urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">\r\n${urls}\r\n</urlset>`;\r\n}\r\n\r\n/**\r\n * Generate robots.txt\r\n */\r\nexport function generateRobotsTxt(siteUrl: string): string {\r\n return `User-agent: *\r\nAllow: /\r\n\r\nSitemap: ${siteUrl}/sitemap.xml`;\r\n}\r\n","/**\r\n * SSG Pre-render Orchestrator\r\n * \r\n * Main entry point for the SSG build process.\r\n * Coordinates crawling, generating, rendering, and writing static HTML.\r\n */\r\n\r\nimport fs from 'fs';\r\nimport path from 'path';\r\nimport type { SSGConfig, SSGBuildResult, SSGPageInfo } from './types';\r\nimport { crawlRoutes, getStaticPages } from './crawler';\r\nimport { generateSSREntry, cleanupSSREntry } from './generator';\r\nimport { renderPage } from './renderer';\r\nimport { \r\n generateHTML, \r\n discoverBuildAssets, \r\n injectContentIntoHTML,\r\n generateSitemap,\r\n generateRobotsTxt,\r\n} from './html';\r\n\r\n/**\r\n * Run the SSG pre-rendering process\r\n */\r\nexport async function runSSG(config: SSGConfig): Promise<SSGBuildResult> {\r\n const startTime = Date.now();\r\n const failedPages: string[] = [];\r\n \r\n console.log('\\nšŸ“¦ Olova SSG - Starting static generation...\\n');\r\n \r\n // 1. Crawl routes\r\n console.log('šŸ” Discovering routes...');\r\n const allPages = await crawlRoutes(config);\r\n const staticPages = getStaticPages(allPages);\r\n \r\n console.log(` Found ${allPages.length} total routes`);\r\n console.log(` ${staticPages.length} static routes will be pre-rendered\\n`);\r\n \r\n if (staticPages.length === 0) {\r\n console.log('āš ļø No static pages found to pre-render\\n');\r\n return {\r\n totalPages: allPages.length,\r\n staticPages: 0,\r\n failedPages: [],\r\n duration: Date.now() - startTime,\r\n };\r\n }\r\n \r\n // 2. Generate SSR entry\r\n console.log('šŸ“ Generating SSR entry...');\r\n const ssrEntryPath = generateSSREntry(staticPages, config);\r\n \r\n // 3. Discover build assets\r\n const distDir = path.resolve(config.root, config.outDir);\r\n const { jsEntry, cssEntries } = discoverBuildAssets(distDir);\r\n \r\n console.log(` JS entry: ${jsEntry || '(none)'}`);\r\n console.log(` CSS files: ${cssEntries.length}\\n`);\r\n \r\n // 4. Read base HTML template\r\n const baseHtmlPath = path.join(distDir, 'index.html');\r\n let baseHtml = '';\r\n \r\n if (fs.existsSync(baseHtmlPath)) {\r\n baseHtml = fs.readFileSync(baseHtmlPath, 'utf-8');\r\n } else {\r\n console.warn('āš ļø No index.html found in dist, generating from scratch');\r\n }\r\n \r\n // 5. Render each page\r\n console.log('šŸ”Ø Pre-rendering pages...\\n');\r\n \r\n for (const page of staticPages) {\r\n const pageStartTime = Date.now();\r\n \r\n try {\r\n // Render the page\r\n const result = await renderPage(page, config, ssrEntryPath);\r\n \r\n // Determine output path\r\n const outputPath = page.path === '/'\r\n ? path.join(distDir, 'index.html')\r\n : path.join(distDir, page.path, 'index.html');\r\n \r\n // Ensure directory exists\r\n const outputDir = path.dirname(outputPath);\r\n if (!fs.existsSync(outputDir)) {\r\n fs.mkdirSync(outputDir, { recursive: true });\r\n }\r\n \r\n // Generate or inject HTML\r\n let html: string;\r\n \r\n if (baseHtml) {\r\n html = injectContentIntoHTML(baseHtml, result.content, result.metadata);\r\n } else {\r\n html = generateHTML({\r\n content: result.content,\r\n jsEntry,\r\n cssEntries,\r\n metadata: result.metadata,\r\n routePath: page.path,\r\n params: page.params,\r\n });\r\n }\r\n \r\n // Add hydration data\r\n if (!html.includes('__OLOVA_DATA__')) {\r\n html = html.replace(\r\n '</body>',\r\n `<script>window.__OLOVA_DATA__ = ${JSON.stringify({ route: page.path, params: page.params, hydrated: false })};</script>\\n</body>`\r\n );\r\n }\r\n \r\n // Write HTML file\r\n fs.writeFileSync(outputPath, html, 'utf-8');\r\n \r\n const duration = Date.now() - pageStartTime;\r\n console.log(` āœ… ${page.path} (${duration}ms)`);\r\n \r\n } catch (error: any) {\r\n failedPages.push(page.path);\r\n console.log(` āŒ ${page.path} - ${error.message}`);\r\n }\r\n }\r\n \r\n // 6. Generate SEO files\r\n console.log('\\nšŸ“„ Generating SEO files...');\r\n \r\n // Sitemap\r\n const siteUrl = 'https://example.com'; // TODO: Make configurable\r\n const sitemap = generateSitemap(staticPages, siteUrl);\r\n fs.writeFileSync(path.join(distDir, 'sitemap.xml'), sitemap, 'utf-8');\r\n console.log(' āœ… sitemap.xml');\r\n \r\n // Robots.txt (only if not exists)\r\n const robotsPath = path.join(distDir, 'robots.txt');\r\n if (!fs.existsSync(robotsPath)) {\r\n fs.writeFileSync(robotsPath, generateRobotsTxt(siteUrl), 'utf-8');\r\n console.log(' āœ… robots.txt');\r\n }\r\n \r\n // 7. Cleanup\r\n cleanupSSREntry(ssrEntryPath);\r\n \r\n // 8. Generate build manifest\r\n const buildManifest = {\r\n version: Date.now().toString(36),\r\n buildTime: new Date().toISOString(),\r\n pages: allPages.map(p => ({ path: p.path, isStatic: p.isStatic })),\r\n assets: { js: jsEntry, css: cssEntries },\r\n };\r\n fs.writeFileSync(\r\n path.join(distDir, 'build-manifest.json'),\r\n JSON.stringify(buildManifest, null, 2),\r\n 'utf-8'\r\n );\r\n \r\n const duration = Date.now() - startTime;\r\n const successCount = staticPages.length - failedPages.length;\r\n \r\n console.log(`\\n✨ SSG Complete!`);\r\n console.log(` ${successCount}/${staticPages.length} pages generated`);\r\n console.log(` Duration: ${duration}ms\\n`);\r\n \r\n return {\r\n totalPages: allPages.length,\r\n staticPages: successCount,\r\n failedPages,\r\n duration,\r\n };\r\n}\r\n\r\n/**\r\n * Create default SSG config\r\n */\r\nexport function createSSGConfig(\r\n root: string,\r\n options: Partial<SSGConfig> = {}\r\n): SSGConfig {\r\n return {\r\n root,\r\n appDir: options.appDir || 'src/app',\r\n outDir: options.outDir || 'dist',\r\n extensions: options.extensions || ['.tsx', '.ts', '.jsx', '.js'],\r\n basePath: options.basePath || '',\r\n };\r\n}\r\n","/**\r\n * Olova SSG Module\r\n * \r\n * Static Site Generation for Olova.\r\n * Exports all SSG utilities for use in the Vite plugin.\r\n */\r\n\r\n// Main runner\r\nexport { runSSG, createSSGConfig } from './prerender';\r\n\r\n// Crawler\r\nexport { crawlRoutes, getStaticPages, getDynamicPages } from './crawler';\r\n\r\n// Generator\r\nexport { generateSSREntry, cleanupSSREntry, generateHydrationScript } from './generator';\r\n\r\n// Renderer\r\nexport { renderPage, renderPages } from './renderer';\r\n\r\n// HTML utilities\r\nexport {\r\n generateHTML,\r\n generateMetaTags,\r\n discoverBuildAssets,\r\n injectContentIntoHTML,\r\n generateSitemap,\r\n generateRobotsTxt,\r\n} from './html';\r\n\r\n// Types\r\nexport type {\r\n SSGPageInfo,\r\n SSGConfig,\r\n SSGBuildResult,\r\n SSREntryMap,\r\n HTMLGenerateOptions,\r\n} from './types';\r\n","/**\r\n * Olova Vite Plugin\r\n * \r\n * This plugin scans your app directory for file-based routes\r\n * and generates a route manifest at build time.\r\n * \r\n * Features:\r\n * - File-based routing\r\n * - Metadata extraction from page files\r\n * - SSG with separate HTML files per route\r\n */\r\n\r\nimport type { Plugin } from 'vite';\r\nimport type { OlovaOptions, RouteManifest, Metadata, RouteMetadata } from './types';\r\nimport { generateMetadataHtml } from './components/Metadata';\r\n\r\n// Virtual module ID for the route manifest\r\nconst VIRTUAL_MODULE_ID = 'virtual:olova-routes';\r\nconst RESOLVED_VIRTUAL_MODULE_ID = '\\0' + VIRTUAL_MODULE_ID;\r\n\r\n// Virtual module for metadata\r\nconst VIRTUAL_METADATA_ID = 'virtual:olova-metadata';\r\nconst RESOLVED_VIRTUAL_METADATA_ID = '\\0' + VIRTUAL_METADATA_ID;\r\n\r\ninterface RouteInfo {\r\n path: string;\r\n filePath: string;\r\n metadata: Metadata | null;\r\n hasGenerateMetadata: boolean;\r\n}\r\n\r\nexport function olova(options: OlovaOptions = {}): Plugin {\r\n const {\r\n appDir = 'src/app',\r\n extensions = ['.tsx', '.ts', '.jsx', '.js'],\r\n basePath = '',\r\n trailingSlash = false,\r\n ssg = false,\r\n } = options;\r\n\r\n let root: string;\r\n let routeManifest: RouteManifest | null = null;\r\n let routeMetadataMap: Map<string, RouteMetadata> = new Map();\r\n let rootMetadata: Metadata | null = null;\r\n\r\n return {\r\n name: 'vite-plugin-olova',\r\n enforce: 'pre' as const,\r\n\r\n configResolved(config: { root: string }) {\r\n root = config.root;\r\n },\r\n\r\n resolveId(id: string) {\r\n if (id === VIRTUAL_MODULE_ID) {\r\n return RESOLVED_VIRTUAL_MODULE_ID;\r\n }\r\n if (id === VIRTUAL_METADATA_ID) {\r\n return RESOLVED_VIRTUAL_METADATA_ID;\r\n }\r\n },\r\n\r\n async load(id: string) {\r\n if (id === RESOLVED_VIRTUAL_MODULE_ID) {\r\n const manifest = await generateRouteManifest(root, appDir, extensions);\r\n return generateRouteCode(manifest, appDir);\r\n }\r\n if (id === RESOLVED_VIRTUAL_METADATA_ID) {\r\n // Generate metadata code\r\n const metadataEntries = Array.from(routeMetadataMap.entries());\r\n return generateMetadataCode(metadataEntries, rootMetadata);\r\n }\r\n },\r\n\r\n // Configure Vite for SPA mode\r\n config() {\r\n return {\r\n appType: 'spa' as const,\r\n };\r\n },\r\n\r\n configureServer(server: any) {\r\n // Watch for file changes in the app directory\r\n server.watcher.add(`${root}/${appDir}/**/*`);\r\n \r\n server.watcher.on('add', (file: string) => {\r\n if (isRouteFile(file, extensions)) {\r\n const mod = server.moduleGraph.getModuleById(RESOLVED_VIRTUAL_MODULE_ID);\r\n if (mod) {\r\n server.moduleGraph.invalidateModule(mod);\r\n server.ws.send({ type: 'full-reload' });\r\n }\r\n }\r\n });\r\n\r\n server.watcher.on('unlink', (file: string) => {\r\n if (isRouteFile(file, extensions)) {\r\n const mod = server.moduleGraph.getModuleById(RESOLVED_VIRTUAL_MODULE_ID);\r\n if (mod) {\r\n server.moduleGraph.invalidateModule(mod);\r\n server.ws.send({ type: 'full-reload' });\r\n }\r\n }\r\n });\r\n\r\n server.watcher.on('change', (file: string) => {\r\n if (isRouteFile(file, extensions)) {\r\n const mod = server.moduleGraph.getModuleById(RESOLVED_VIRTUAL_MODULE_ID);\r\n if (mod) {\r\n server.moduleGraph.invalidateModule(mod);\r\n }\r\n // Also invalidate metadata module\r\n const metaMod = server.moduleGraph.getModuleById(RESOLVED_VIRTUAL_METADATA_ID);\r\n if (metaMod) {\r\n server.moduleGraph.invalidateModule(metaMod);\r\n }\r\n }\r\n });\r\n\r\n // Add SPA fallback middleware BEFORE Vite's internal handling\r\n // This intercepts non-asset requests and serves index.html\r\n server.middlewares.use((req: any, res: any, next: any) => {\r\n const url = req.url || '';\r\n const accept = req.headers.accept || '';\r\n \r\n // Only intercept HTML requests (not assets, websockets, etc.)\r\n if (!accept.includes('text/html')) {\r\n return next();\r\n }\r\n \r\n // Skip requests that:\r\n // - Are for static assets (have file extensions)\r\n // - Start with /@, /node_modules, /__vite, /src (Vite internals)\r\n // - Are API routes\r\n // - Are the root path\r\n if (\r\n url === '/' ||\r\n url === '/index.html' ||\r\n /\\.[a-zA-Z0-9]+$/.test(url) ||\r\n url.startsWith('/@') ||\r\n url.startsWith('/node_modules') ||\r\n url.startsWith('/__vite') ||\r\n url.startsWith('/src') ||\r\n url.startsWith('/api')\r\n ) {\r\n return next();\r\n }\r\n \r\n // Rewrite URL to index.html for SPA routing\r\n // This makes Vite serve index.html for all app routes\r\n req.url = '/index.html';\r\n next();\r\n });\r\n },\r\n\r\n async buildStart() {\r\n // Generate route manifest at build start\r\n routeManifest = await generateRouteManifest(root, appDir, extensions);\r\n \r\n // Scan for metadata in page files\r\n const routes = await scanRoutesWithMetadata(root, appDir, extensions);\r\n routeMetadataMap.clear();\r\n \r\n for (const route of routes) {\r\n routeMetadataMap.set(route.path, {\r\n routePath: route.path,\r\n metadata: route.metadata,\r\n hasGenerateMetadata: route.hasGenerateMetadata,\r\n });\r\n \r\n // Store root metadata for fallback\r\n if (route.path === '/') {\r\n rootMetadata = route.metadata;\r\n }\r\n }\r\n },\r\n\r\n // SSG: Generate separate HTML files for each route with pre-rendered content\r\n async closeBundle() {\r\n if (!ssg) return;\r\n \r\n // Import SSG module\r\n const { runSSG, createSSGConfig } = await import('./ssg/index.js');\r\n \r\n // Create SSG config\r\n const ssgConfig = createSSGConfig(root, {\r\n appDir,\r\n outDir: 'dist',\r\n extensions,\r\n });\r\n \r\n // Run SSG pre-rendering\r\n try {\r\n await runSSG(ssgConfig);\r\n } catch (error: any) {\r\n console.error('[olova] SSG failed:', error.message);\r\n }\r\n },\r\n };\r\n}\r\n\r\nfunction isRouteFile(file: string, extensions: string[]): boolean {\r\n const routeFiles = ['page', 'layout', 'loading', 'error', 'not-found'];\r\n return extensions.some(ext => \r\n routeFiles.some(name => file.endsWith(`${name}${ext}`))\r\n );\r\n}\r\n\r\n// Scan for routes and extract metadata\r\nasync function scanRoutesWithMetadata(\r\n root: string,\r\n appDir: string,\r\n extensions: string[]\r\n): Promise<RouteInfo[]> {\r\n const fs = await import('fs');\r\n const path = await import('path');\r\n \r\n const routes: RouteInfo[] = [];\r\n const appPath = path.join(root, appDir);\r\n \r\n if (!fs.existsSync(appPath)) {\r\n return routes;\r\n }\r\n \r\n // Recursive function to scan directories\r\n async function scanDir(dir: string, routePath: string) {\r\n const entries = fs.readdirSync(dir, { withFileTypes: true });\r\n \r\n for (const entry of entries) {\r\n const fullPath = path.join(dir, entry.name);\r\n \r\n if (entry.isDirectory()) {\r\n // Determine the route segment\r\n let segment = entry.name;\r\n \r\n // Route group - doesn't add to URL\r\n if (segment.startsWith('(') && segment.endsWith(')')) {\r\n await scanDir(fullPath, routePath);\r\n continue;\r\n }\r\n \r\n // Dynamic segment\r\n if (segment.startsWith('[') && segment.endsWith(']')) {\r\n if (segment.startsWith('[...')) {\r\n // Catch-all\r\n segment = ':' + segment.slice(4, -1) + '*';\r\n } else if (segment.startsWith('[[...')) {\r\n // Optional catch-all\r\n segment = ':' + segment.slice(5, -2) + '*';\r\n } else {\r\n // Regular dynamic\r\n segment = ':' + segment.slice(1, -1);\r\n }\r\n }\r\n \r\n const newRoutePath = routePath === '/' \r\n ? `/${segment}` \r\n : `${routePath}/${segment}`;\r\n \r\n await scanDir(fullPath, newRoutePath);\r\n } else if (entry.isFile()) {\r\n // Check if it's a page file\r\n const isPage = extensions.some(ext => entry.name === `page${ext}`);\r\n \r\n if (isPage) {\r\n const metadata = await extractMetadataFromFile(fullPath);\r\n const hasGenerateMetadata = await checkForGenerateMetadata(fullPath);\r\n \r\n routes.push({\r\n path: routePath || '/',\r\n filePath: fullPath,\r\n metadata,\r\n hasGenerateMetadata,\r\n });\r\n }\r\n }\r\n }\r\n }\r\n \r\n await scanDir(appPath, '/');\r\n return routes;\r\n}\r\n\r\n// Extract static metadata export from a file\r\nasync function extractMetadataFromFile(filePath: string): Promise<Metadata | null> {\r\n const fs = await import('fs');\r\n \r\n try {\r\n const content = fs.readFileSync(filePath, 'utf-8');\r\n \r\n // Look for \"export const metadata = {\"\r\n const metadataMatch = content.match(/export\\s+const\\s+metadata\\s*=\\s*(\\{[\\s\\S]*?\\n\\};?)/);\r\n \r\n if (metadataMatch) {\r\n try {\r\n // Simple evaluation - works for basic object literals\r\n // Note: This is a simplified approach. For production, use a proper AST parser.\r\n const metadataStr = metadataMatch[1];\r\n \r\n // Convert to valid JSON-like format\r\n // Handle trailing commas, single quotes, etc.\r\n const jsonLike = metadataStr\r\n .replace(/'/g, '\"')\r\n .replace(/,(\\s*[}\\]])/g, '$1')\r\n .replace(/(\\w+):/g, '\"$1\":')\r\n .replace(/\"\"(\\w+)\"\":/g, '\"$1\":');\r\n \r\n // Try to parse - this is a best effort approach\r\n // For complex metadata, recommend using a proper transformer\r\n const metadata = Function('\"use strict\"; return (' + metadataStr + ')')();\r\n return metadata as Metadata;\r\n } catch (e) {\r\n // If parsing fails, try a simpler regex extraction\r\n return extractMetadataSimple(content);\r\n }\r\n }\r\n \r\n return null;\r\n } catch (e) {\r\n console.warn(`[olova] Failed to extract metadata from ${filePath}:`, e);\r\n return null;\r\n }\r\n}\r\n\r\n// Simple metadata extraction using regex\r\nfunction extractMetadataSimple(content: string): Metadata | null {\r\n const metadata: Metadata = {};\r\n \r\n // Extract title\r\n const titleMatch = content.match(/title:\\s*['\"`]([^'\"`]+)['\"`]/);\r\n if (titleMatch) metadata.title = titleMatch[1];\r\n \r\n // Extract description\r\n const descMatch = content.match(/description:\\s*['\"`]([^'\"`]+)['\"`]/);\r\n if (descMatch) metadata.description = descMatch[1];\r\n \r\n // Extract keywords (basic array support)\r\n const keywordsMatch = content.match(/keywords:\\s*\\[([^\\]]+)\\]/);\r\n if (keywordsMatch) {\r\n const keywords = keywordsMatch[1]\r\n .split(',')\r\n .map(k => k.trim().replace(/['\"`]/g, ''))\r\n .filter(Boolean);\r\n if (keywords.length) metadata.keywords = keywords;\r\n }\r\n \r\n return Object.keys(metadata).length > 0 ? metadata : null;\r\n}\r\n\r\n// Check if file has generateMetadata function\r\nasync function checkForGenerateMetadata(filePath: string): Promise<boolean> {\r\n const fs = await import('fs');\r\n \r\n try {\r\n const content = fs.readFileSync(filePath, 'utf-8');\r\n return /export\\s+(async\\s+)?function\\s+generateMetadata/.test(content);\r\n } catch (e) {\r\n return false;\r\n }\r\n}\r\n\r\n// Generate route manifest\r\nasync function generateRouteManifest(\r\n root: string, \r\n appDir: string, \r\n extensions: string[]\r\n): Promise<RouteManifest> {\r\n return {\r\n routes: [],\r\n staticPaths: new Map(),\r\n generatedAt: Date.now(),\r\n };\r\n}\r\n\r\n// Generate the route configuration code\r\nfunction generateRouteCode(manifest: RouteManifest, appDir: string): string {\r\n return `\r\nimport { lazy } from 'react';\r\n\r\n// Auto-generated by olova\r\n// This file is generated at build time based on your file structure\r\n\r\nexport const routes = [];\r\nexport const manifest = ${JSON.stringify({ generatedAt: manifest.generatedAt })};\r\n`;\r\n}\r\n\r\n// Generate metadata module code\r\nfunction generateMetadataCode(\r\n entries: [string, RouteMetadata][],\r\n rootMetadata: Metadata | null\r\n): string {\r\n const metadataMap: Record<string, Metadata | null> = {};\r\n \r\n for (const [path, routeMeta] of entries) {\r\n metadataMap[path] = routeMeta.metadata;\r\n }\r\n \r\n return `\r\n// Auto-generated by olova - Route Metadata\r\nexport const routeMetadata = ${JSON.stringify(metadataMap, null, 2)};\r\nexport const rootMetadata = ${JSON.stringify(rootMetadata, null, 2)};\r\n\r\nexport function getMetadataForRoute(path) {\r\n return routeMetadata[path] || rootMetadata || null;\r\n}\r\n`;\r\n}\r\n\r\nfunction escapeHtml(text: string): string {\r\n return text\r\n .replace(/&/g, '&amp;')\r\n .replace(/</g, '&lt;')\r\n .replace(/>/g, '&gt;')\r\n .replace(/\"/g, '&quot;')\r\n .replace(/'/g, '&#039;');\r\n}\r\n\r\nexport default olova;\r\n"],"mappings":"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","names":["newRoutePath","fs","path","fs","path","fs","path","fs","path","duration","runSSG","createSSGConfig","fs","path","extractMetadataSimple"]}