bini-router 1.0.19 → 1.0.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -657,8 +657,12 @@ async function handleApiRequest(req, res, next, apiDir, enableCors, getCache, se
657
657
  }
658
658
  var ADAPTERS = {
659
659
  netlify: {
660
- // Netlify Edge Functions — uses hono/netlify adapter built into hono core
661
- importLine: `import { handle } from 'hono/netlify';`,
660
+ // Netlify Edge Functions — Deno runtime, use deno.land URL imports (zero npm)
661
+ // Entry file uses URL imports so Netlify bundles with no npm module errors.
662
+ // User route files import `from 'hono'` (npm) but Netlify resolves them fine
663
+ // since the entry provides Hono via URL import at bundle time.
664
+ importLine: `import { Hono } from 'https://deno.land/x/hono@v4.3.11/mod.ts';
665
+ import { handle } from 'https://deno.land/x/hono@v4.3.11/adapter/netlify/index.ts';`,
662
666
  exportLine: `export default handle(app);`,
663
667
  outFile: (cwd) => import_path.default.join(cwd, "netlify", "edge-functions", "api.ts"),
664
668
  stripsApiPrefix: false
@@ -739,7 +743,8 @@ function buildRouteImports(routes, outFile, enableCors, platform) {
739
743
  }
740
744
  }
741
745
  const corsPattern = stripPrefix ? "/*" : "/api/*";
742
- const corsLine = enableCors ? `app.use('${corsPattern}', cors({ origin: '*', allowMethods: ['GET','POST','PUT','PATCH','DELETE','OPTIONS'], allowHeaders: ['Content-Type','Authorization'] }));` : null;
746
+ const isNetlifyPlatform = platform === "netlify";
747
+ const corsLine = enableCors ? isNetlifyPlatform ? `app.use('${corsPattern}', async (c, next) => { await next(); c.res.headers.set('Access-Control-Allow-Origin', '*'); c.res.headers.set('Access-Control-Allow-Methods', 'GET,POST,PUT,PATCH,DELETE,OPTIONS'); c.res.headers.set('Access-Control-Allow-Headers', 'Content-Type,Authorization'); if (c.req.method === 'OPTIONS') return new Response(null, { status: 204, headers: c.res.headers }); });` : `app.use('${corsPattern}', cors({ origin: '*', allowMethods: ['GET','POST','PUT','PATCH','DELETE','OPTIONS'], allowHeaders: ['Content-Type','Authorization'] }));` : null;
743
748
  const corsImport = enableCors ? `import { cors } from 'hono/cors';` : null;
744
749
  return { imports, mountings, corsLine, corsImport };
745
750
  }
@@ -755,11 +760,12 @@ function buildProductionEntry(srcApiDir, platform, enableCors) {
755
760
  const adapter = ADAPTERS[platform];
756
761
  const outFile = adapter.outFile(cwd);
757
762
  const { imports, mountings, corsLine, corsImport } = buildRouteImports(routes, outFile, enableCors, platform);
763
+ const isNetlify = platform === "netlify";
758
764
  const lines = [
759
765
  ...header,
760
- `import { Hono } from 'hono';`,
766
+ ...isNetlify ? [] : [`import { Hono } from 'hono';`],
761
767
  ...adapter.importLine ? adapter.importLine.split("\n") : [],
762
- ...corsImport ? [corsImport] : [],
768
+ ...corsImport && !isNetlify ? [corsImport] : [],
763
769
  ...imports,
764
770
  ``,
765
771
  `const app = new Hono();`,
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["import fs from 'fs';\r\nimport path from 'path';\r\nimport type { Plugin, ViteDevServer } from 'vite';\r\n\r\n// ─── Constants ────────────────────────────────────────────────────────────────\r\n\r\nconst PAGE_FILES = ['page.tsx', 'page.jsx', 'page.ts', 'page.js'] as const;\r\nconst LAYOUT_FILES = ['layout.tsx', 'layout.jsx', 'layout.ts', 'layout.js'] as const;\r\nconst SUPPORTED_EXTS = ['.tsx', '.jsx', '.ts', '.js'] as const;\r\nconst NOT_FOUND_FILES = SUPPORTED_EXTS.map(e => `not-found${e}`);\r\nconst SPECIAL_BASES = new Set(['page', 'layout', 'not-found', 'loading', 'error']);\r\nconst API_EXTS = ['.ts', '.js'] as const;\r\nconst DEBOUNCE_MS = 60;\r\nconst EVENT_DEDUP_MS = 500;\r\nconst EVENT_TTL_MS = 2000;\r\n\r\n// ─── Metadata Types ───────────────────────────────────────────────────────────\r\n\r\nexport interface IconEntry {\r\n url : string;\r\n type ?: string;\r\n sizes?: string;\r\n}\r\n\r\nexport interface MetaTags {\r\n title ?: string;\r\n description ?: string;\r\n viewport ?: string;\r\n themeColor ?: string;\r\n keywords ?: string;\r\n author ?: string;\r\n charset ?: string;\r\n robots ?: string;\r\n canonical ?: string;\r\n manifest ?: string;\r\n openGraph ?: Partial<OGMeta>;\r\n twitter ?: Partial<TwitterMeta>;\r\n icons ?: {\r\n icon ?: IconEntry[];\r\n shortcut ?: IconEntry[];\r\n apple ?: IconEntry[];\r\n };\r\n}\r\n\r\ninterface OGMeta {\r\n title : string;\r\n description : string;\r\n url : string;\r\n image : string;\r\n type : string;\r\n}\r\n\r\ninterface TwitterMeta {\r\n card : string;\r\n title : string;\r\n description : string;\r\n creator : string;\r\n image : string;\r\n}\r\n\r\n// ─── Types ────────────────────────────────────────────────────────────────────\r\n\r\ninterface RouteNode {\r\n routePath : string;\r\n filePath : string;\r\n layouts : string[];\r\n dynamic : boolean;\r\n}\r\n\r\ninterface LayoutChainGroup {\r\n layouts : string[];\r\n routes : RouteNode[];\r\n}\r\n\r\ninterface ApiRoute {\r\n routePath : string;\r\n filePath : string;\r\n}\r\n\r\nexport interface BiniPluginOptions {\r\n /** Directory for page files. Default: src/app */\r\n appDir?: string;\r\n /** Directory for API routes. Default: src/app/api */\r\n apiDir?: string;\r\n /** Enable CORS headers in the dev-server API middleware. Default: true */\r\n cors?: boolean;\r\n /**\r\n * Target deployment platform. bini-router generates a production entry\r\n * file on every build — users only write code in src/app/api/.\r\n *\r\n * 'vercel' → .vercel/output/ (Vercel Build Output API — always fresh)\r\n * 'netlify' → netlify/functions/api.ts (no extra install needed)\r\n * 'cloudflare' → worker.ts (install: wrangler)\r\n * 'node' → server/index.ts (install: @hono/node-server)\r\n * 'deno' → server/index.ts (run with: deno run)\r\n * 'bun' → server/index.ts (run with: bun run)\r\n * 'aws' → handler.ts (install: @hono/aws-lambda)\r\n *\r\n * Default: undefined (no entry generated)\r\n */\r\n platform?: 'netlify' | 'cloudflare' | 'node' | 'deno' | 'bun' | 'aws';\r\n}\r\n\r\n// ─── Utilities ────────────────────────────────────────────────────────────────\r\n\r\nfunction norm(p: string): string {\r\n return p.replace(/\\\\/g, '/');\r\n}\r\n\r\nfunction isInDir(file: string, dir: string): boolean {\r\n const nFile = norm(file);\r\n const nDir = norm(dir).replace(/\\/$/, '');\r\n return nFile.startsWith(nDir + '/') || nFile === nDir;\r\n}\r\n\r\nfunction readTsconfigAliases(): Record<string, string> {\r\n const aliases: Record<string, string> = {};\r\n try {\r\n const tsconfigPath = path.join(process.cwd(), 'tsconfig.json');\r\n if (!fs.existsSync(tsconfigPath)) return aliases;\r\n const raw = fs.readFileSync(tsconfigPath, 'utf8')\r\n .replace(/\\/\\/.*$/gm, '')\r\n .replace(/\\/\\*[\\s\\S]*?\\*\\//g, '');\r\n const tsconfig = JSON.parse(raw);\r\n const paths = tsconfig?.compilerOptions?.paths ?? {};\r\n const baseUrl = tsconfig?.compilerOptions?.baseUrl ?? '.';\r\n for (const [alias, targets] of Object.entries(paths) as [string, string[]][]) {\r\n const cleanAlias = alias.replace(/\\/\\*$/, '');\r\n const cleanTarget = (targets[0] ?? '').replace(/\\/\\*$/, '');\r\n aliases[cleanAlias] = path.resolve(process.cwd(), baseUrl, cleanTarget);\r\n }\r\n } catch { /* tsconfig unreadable — fall back to relative paths */ }\r\n return aliases;\r\n}\r\n\r\nfunction toImportPath(filePath: string, aliases: Record<string, string>): string {\r\n for (const [alias, target] of Object.entries(aliases)) {\r\n if (norm(filePath).startsWith(norm(target) + '/')) {\r\n const rest = norm(filePath).slice(norm(target).length + 1).replace(/\\.(tsx|ts|jsx|js)$/, '');\r\n return `${alias}/${rest}`;\r\n }\r\n }\r\n return './' + norm(path.relative(path.join(process.cwd(), 'src'), filePath))\r\n .replace(/\\.(tsx|ts|jsx|js)$/, '');\r\n}\r\n\r\nfunction hasDefaultExport(filePath: string): boolean {\r\n try { return fs.readFileSync(filePath, 'utf8').includes('export default'); }\r\n catch { return false; }\r\n}\r\n\r\nfunction isHtmlShellLayout(filePath: string): boolean {\r\n try { return /<html[\\s>]/i.test(fs.readFileSync(filePath, 'utf8')); }\r\n catch { return false; }\r\n}\r\n\r\nfunction isUsableLayout(filePath: string): boolean {\r\n return hasDefaultExport(filePath) && !isHtmlShellLayout(filePath);\r\n}\r\n\r\nfunction findFile(dir: string, candidates: readonly string[]): string | null {\r\n return candidates.find(f => fs.existsSync(path.join(dir, f))) ?? null;\r\n}\r\n\r\nfunction getAppFile(): string {\r\n const ts = path.join(process.cwd(), 'src/App.tsx');\r\n return fs.existsSync(ts) ? ts : path.join(process.cwd(), 'src/App.jsx');\r\n}\r\n\r\n// ─── Layout Resolution ────────────────────────────────────────────────────────\r\n\r\nfunction resolveLayoutChain(pageDir: string, appDir: string): string[] {\r\n const chain: string[] = [];\r\n let current = pageDir;\r\n while (true) {\r\n const layout = findFile(current, LAYOUT_FILES);\r\n if (layout) chain.unshift(path.join(current, layout));\r\n if (path.resolve(current) === path.resolve(appDir)) break;\r\n const parent = path.dirname(current);\r\n if (parent === current) break;\r\n current = parent;\r\n }\r\n return chain;\r\n}\r\n\r\n// ─── Route Scanner ────────────────────────────────────────────────────────────\r\n\r\nfunction scanRoutes(dir: string, appDir: string, baseRoute = ''): RouteNode[] {\r\n const routes: RouteNode[] = [];\r\n if (!fs.existsSync(dir)) return routes;\r\n\r\n let entries: fs.Dirent[];\r\n try { entries = fs.readdirSync(dir, { withFileTypes: true }); }\r\n catch { return routes; }\r\n\r\n // File-based: about.tsx → /about\r\n for (const entry of entries) {\r\n if (!entry.isFile() || entry.name.startsWith('.') || entry.name.startsWith('_')) continue;\r\n const ext = path.extname(entry.name);\r\n const base = path.basename(entry.name, ext);\r\n if (!(SUPPORTED_EXTS as readonly string[]).includes(ext)) continue;\r\n if (SPECIAL_BASES.has(base)) continue;\r\n routes.push({\r\n routePath : `${baseRoute}/${base}`,\r\n filePath : path.join(dir, entry.name),\r\n layouts : resolveLayoutChain(dir, appDir),\r\n dynamic : false,\r\n });\r\n }\r\n\r\n // Directory-based: [id]/page.tsx → /:id\r\n for (const entry of entries) {\r\n if (!entry.isDirectory()) continue;\r\n if (entry.name === 'node_modules' || entry.name.startsWith('.') || entry.name === 'api') continue;\r\n\r\n const fullPath = path.join(dir, entry.name);\r\n const isDynamic = entry.name.startsWith('[') && entry.name.endsWith(']');\r\n const segment = isDynamic ? `:${entry.name.slice(1, -1)}` : entry.name;\r\n const routePath = `${baseRoute}/${segment}`;\r\n\r\n const pageFile = findFile(fullPath, PAGE_FILES);\r\n if (pageFile) {\r\n routes.push({\r\n routePath,\r\n filePath : path.join(fullPath, pageFile),\r\n layouts : resolveLayoutChain(fullPath, appDir),\r\n dynamic : isDynamic,\r\n });\r\n }\r\n routes.push(...scanRoutes(fullPath, appDir, routePath));\r\n }\r\n\r\n return routes;\r\n}\r\n\r\nfunction deduplicateRoutes(routes: RouteNode[]): RouteNode[] {\r\n const seen = new Set<string>();\r\n return routes.filter(r => {\r\n if (seen.has(r.routePath)) return false;\r\n seen.add(r.routePath);\r\n return true;\r\n });\r\n}\r\n\r\n// ─── Per-layout title extractor ──────────────────────────────────────────────\r\n\r\nfunction parseLayoutTitle(layoutFile: string): string | null {\r\n let src = '';\r\n try { src = fs.readFileSync(layoutFile, 'utf8'); }\r\n catch { return null; }\r\n\r\n const startIdx = src.indexOf('export const metadata');\r\n if (startIdx === -1) return null;\r\n const braceStart = src.indexOf('{', startIdx);\r\n if (braceStart === -1) return null;\r\n\r\n let depth = 0, end = braceStart;\r\n for (let i = braceStart; i < src.length; i++) {\r\n if (src[i] === '{') depth++;\r\n else if (src[i] === '}') { depth--; if (depth === 0) { end = i; break; } }\r\n }\r\n const block = src.slice(braceStart, end + 1);\r\n const match = /['\"]?title['\"]?\\s*:\\s*['\"`]([^'\"`]+)['\"`]/.exec(block);\r\n return match ? match[1] : null;\r\n}\r\n\r\n// ─── Route Tree Renderer ──────────────────────────────────────────────────────\r\n\r\nfunction renderChain(\r\n layouts : string[],\r\n routesInChain : RouteNode[],\r\n layoutNames : Map<string, string>,\r\n pageNames : Map<string, string>,\r\n layoutTitles : Map<string, string>,\r\n indent : number,\r\n): string {\r\n const pad = ' '.repeat(indent);\r\n if (layouts.length === 0) {\r\n return routesInChain.map(r =>\r\n `${pad}<Route path=\"${r.routePath}\" element={<Suspense fallback={<Spinner />}><ErrorBoundary><${pageNames.get(r.filePath)} /></ErrorBoundary></Suspense>} />`\r\n ).join('\\n');\r\n }\r\n const [head, ...tail] = layouts;\r\n const title = layoutTitles.get(head);\r\n const titleSetter = title ? `<TitleSetter title=${JSON.stringify(title)} />` : '';\r\n const inner = renderChain(tail, routesInChain, layoutNames, pageNames, layoutTitles, indent + 2);\r\n const name = layoutNames.get(head);\r\n return [\r\n `${pad}<Route element={<>${titleSetter}<Suspense fallback={<Spinner />}><ErrorBoundary><${name}><Outlet /></${name}></ErrorBoundary></Suspense></>}>`,\r\n inner,\r\n `${pad}</Route>`,\r\n ].join('\\n');\r\n}\r\n\r\n// ─── App Generator ────────────────────────────────────────────────────────────\r\n\r\nfunction generateApp(appDir: string): string {\r\n const aliases = readTsconfigAliases();\r\n const routes = scanRoutes(appDir, appDir);\r\n\r\n const rootPage = findFile(appDir, PAGE_FILES);\r\n if (rootPage) {\r\n routes.unshift({\r\n routePath : '/',\r\n filePath : path.join(appDir, rootPage),\r\n layouts : resolveLayoutChain(appDir, appDir),\r\n dynamic : false,\r\n });\r\n }\r\n\r\n const routesFiltered = routes.map(r => ({\r\n ...r,\r\n layouts: r.layouts.filter(l => isUsableLayout(l)),\r\n }));\r\n\r\n const validRoutes = deduplicateRoutes(\r\n routesFiltered.filter(r => hasDefaultExport(r.filePath))\r\n );\r\n\r\n validRoutes.sort((a, b) => {\r\n if (a.dynamic !== b.dynamic) return a.dynamic ? 1 : -1;\r\n return a.routePath.length - b.routePath.length;\r\n });\r\n\r\n const notFoundFile = NOT_FOUND_FILES.find(f => fs.existsSync(path.join(appDir, f)));\r\n const notFound = notFoundFile && hasDefaultExport(path.join(appDir, notFoundFile))\r\n ? notFoundFile\r\n : undefined;\r\n\r\n const allLayouts = new Set<string>();\r\n for (const r of validRoutes) r.layouts.forEach(l => {\r\n if (isUsableLayout(l)) allLayouts.add(l);\r\n });\r\n\r\n const layoutNames = new Map<string, string>();\r\n const pageNames = new Map<string, string>();\r\n const layoutTitles = new Map<string, string>();\r\n let li = 0, pi = 0;\r\n for (const l of allLayouts) {\r\n layoutNames.set(l, `Layout${li++}`);\r\n const title = parseLayoutTitle(l);\r\n if (title) layoutTitles.set(l, title);\r\n }\r\n for (const r of validRoutes) {\r\n if (!pageNames.has(r.filePath)) pageNames.set(r.filePath, `Page${pi++}`);\r\n }\r\n\r\n const lazyImports: string[] = [];\r\n for (const [fp, name] of layoutNames)\r\n lazyImports.push(`const ${name} = React.lazy(() => import('${toImportPath(fp, aliases)}'));`);\r\n if (notFound)\r\n lazyImports.push(`const NotFound = React.lazy(() => import('${toImportPath(path.join(appDir, notFound), aliases)}'));`);\r\n const emittedPages = new Set<string>();\r\n for (const r of validRoutes) {\r\n if (emittedPages.has(r.filePath)) continue;\r\n emittedPages.add(r.filePath);\r\n const name = pageNames.get(r.filePath);\r\n if (!name) continue;\r\n lazyImports.push(`const ${name} = React.lazy(() => import('${toImportPath(r.filePath, aliases)}'));`);\r\n }\r\n\r\n const chainMap = new Map<string, LayoutChainGroup>();\r\n for (const r of validRoutes) {\r\n const key = r.layouts.join('|');\r\n if (!chainMap.has(key)) chainMap.set(key, { layouts: r.layouts, routes: [] });\r\n chainMap.get(key)!.routes.push(r);\r\n }\r\n\r\n const routeLines: string[] = [];\r\n for (const [, { layouts, routes: cr }] of chainMap)\r\n routeLines.push(renderChain(layouts, cr, layoutNames, pageNames, layoutTitles, 8));\r\n\r\n const catchAll = notFound\r\n ? ` <Route path=\"*\" element={<Suspense fallback={<Spinner />}><NotFound /></Suspense>} />`\r\n : ` <Route path=\"*\" element={<Default404 />} />`;\r\n\r\n return `// ⚠️ Auto-generated by bini-router — do not edit.\r\nimport React, { Suspense } from 'react';\r\nimport { BrowserRouter, Routes, Route, Outlet } from 'react-router-dom';\r\nimport './app/globals.css';\r\n\r\n${lazyImports.join('\\n')}\r\n\r\n// ─── Error Boundary ───────────────────────────────────────────────────────────\r\nclass ErrorBoundary extends React.Component<\r\n { children: React.ReactNode },\r\n { error: Error | null }\r\n> {\r\n constructor(props: { children: React.ReactNode }) {\r\n super(props);\r\n this.state = { error: null };\r\n }\r\n static getDerivedStateFromError(error: Error) { return { error }; }\r\n override render() {\r\n if (this.state.error) return (\r\n <div style={{ minHeight: '100vh', display: 'flex', alignItems: 'center', justifyContent: 'center', fontFamily: 'system-ui,sans-serif', padding: '2rem' }}>\r\n <div style={{ maxWidth: 480, width: '100%', textAlign: 'center' }}>\r\n <h2 style={{ color: '#e74c3c', marginBottom: '1rem' }}>Something went wrong</h2>\r\n <pre style={{ background: '#fef2f2', padding: '1rem', borderRadius: '0.5rem', textAlign: 'left', fontSize: '0.8rem', color: '#e74c3c', overflow: 'auto' }}>{this.state.error.toString()}</pre>\r\n <button onClick={() => this.setState({ error: null })} style={{ marginTop: '1rem', padding: '0.5rem 1.5rem', background: '#00CFFF', color: 'white', border: 'none', borderRadius: '0.5rem', cursor: 'pointer', fontWeight: 600 }}>\r\n Try again\r\n </button>\r\n </div>\r\n </div>\r\n );\r\n return this.props.children;\r\n }\r\n}\r\n\r\nfunction Spinner() {\r\n return (\r\n <div style={{ minHeight: '100vh', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>\r\n <div style={{ width: 32, height: 32, border: '3px solid #eee', borderTop: '3px solid #00CFFF', borderRadius: '50%', animation: 'spin 0.8s linear infinite' }} />\r\n <style>{\\`@keyframes spin{to{transform:rotate(360deg)}}\\`}</style>\r\n </div>\r\n );\r\n}\r\n\r\nfunction TitleSetter({ title }: { title: string }) {\r\n React.useEffect(() => { document.title = title; }, [title]);\r\n return null;\r\n}\r\n\r\n${notFound ? '' : `function Default404() {\r\n return (\r\n <div style={{ minHeight: '100vh', display: 'flex', alignItems: 'center', justifyContent: 'center', background: 'linear-gradient(135deg,#00CFFF,#0077FF)', color: 'white', fontFamily: 'system-ui,sans-serif' }}>\r\n <div style={{ textAlign: 'center' }}>\r\n <h1 style={{ fontSize: '5rem', fontWeight: 800, margin: 0 }}>404</h1>\r\n <p style={{ fontSize: '1.25rem', margin: '0.5rem 0 2rem' }}>Page not found</p>\r\n <a href=\"/\" style={{ padding: '0.65rem 1.5rem', background: 'white', color: '#00CFFF', textDecoration: 'none', borderRadius: '0.5rem', fontWeight: 600 }}>← Back to Home</a>\r\n </div>\r\n </div>\r\n );\r\n}`}\r\n\r\nexport default function App() {\r\n return (\r\n <BrowserRouter>\r\n <Routes>\r\n${routeLines.join('\\n')}\r\n${catchAll}\r\n </Routes>\r\n </BrowserRouter>\r\n );\r\n}\r\n`;\r\n}\r\n\r\n// ─── Metadata Parser ──────────────────────────────────────────────────────────\r\n\r\nfunction parseAppMetadata(appDir: string): MetaTags {\r\n const layout = findFile(appDir, LAYOUT_FILES);\r\n if (!layout) return {};\r\n let src = '';\r\n try { src = fs.readFileSync(path.join(appDir, layout), 'utf8'); }\r\n catch { return {}; }\r\n\r\n const startIdx = src.indexOf('export const metadata');\r\n if (startIdx === -1) return {};\r\n const braceStart = src.indexOf('{', startIdx);\r\n if (braceStart === -1) return {};\r\n\r\n let depth = 0, end = braceStart;\r\n for (let i = braceStart; i < src.length; i++) {\r\n if (src[i] === '{') depth++;\r\n else if (src[i] === '}') { depth--; if (depth === 0) { end = i; break; } }\r\n }\r\n const block = src.slice(braceStart, end + 1);\r\n\r\n function extractBlock(source: string, key: string): string | undefined {\r\n const re = new RegExp(`['\"]?${key}['\"]?\\\\s*:\\\\s*\\\\{`);\r\n const match = re.exec(source);\r\n if (!match) return undefined;\r\n let d = 0, i = match.index + match[0].length - 1;\r\n const start = i;\r\n for (; i < source.length; i++) {\r\n if (source[i] === '{') d++;\r\n else if (source[i] === '}') { d--; if (d === 0) return source.slice(start, i + 1); }\r\n }\r\n return undefined;\r\n }\r\n\r\n function extractArray(source: string, key: string): string | undefined {\r\n const re = new RegExp(`['\"]?${key}['\"]?\\\\s*:\\\\s*\\\\[`);\r\n const match = re.exec(source);\r\n if (!match) return undefined;\r\n let d = 0, i = match.index + match[0].length - 1;\r\n const start = i;\r\n for (; i < source.length; i++) {\r\n if (source[i] === '[') d++;\r\n else if (source[i] === ']') { d--; if (d === 0) return source.slice(start, i + 1); }\r\n }\r\n return undefined;\r\n }\r\n\r\n function str(source: string, key: string): string | undefined {\r\n return source.match(\r\n new RegExp(`['\"]?${key}['\"]?\\\\s*:\\\\s*['\"\\`]([^'\"\\`\\n]+)['\"\\`]`)\r\n )?.[1];\r\n }\r\n\r\n function firstArrayStr(source: string, key: string): string | undefined {\r\n const arr = extractArray(source, key);\r\n if (!arr) return undefined;\r\n return arr.match(/url\\s*:\\s*['\"]([^'\"]+)['\"]/)?.[1]\r\n ?? arr.match(/['\"]([^'\"]+)['\"]/)?.[1];\r\n }\r\n\r\n function allArrayStrs(source: string, key: string): string[] {\r\n const arr = extractArray(source, key);\r\n if (!arr) return [];\r\n return [...arr.matchAll(/['\"]([^'\"]+)['\"]/g)].map(m => m[1]);\r\n }\r\n\r\n const meta: MetaTags = {};\r\n\r\n if (str(block, 'title')) meta.title = str(block, 'title');\r\n if (str(block, 'description')) meta.description = str(block, 'description');\r\n if (str(block, 'viewport')) meta.viewport = str(block, 'viewport');\r\n if (str(block, 'themeColor')) meta.themeColor = str(block, 'themeColor');\r\n if (str(block, 'charset')) meta.charset = str(block, 'charset');\r\n if (str(block, 'robots')) meta.robots = str(block, 'robots');\r\n if (str(block, 'canonical')) meta.canonical = str(block, 'canonical');\r\n if (str(block, 'manifest')) meta.manifest = str(block, 'manifest');\r\n\r\n const kwStr = str(block, 'keywords');\r\n if (kwStr) {\r\n meta.keywords = kwStr;\r\n } else {\r\n const kwArr = allArrayStrs(block, 'keywords');\r\n if (kwArr.length) meta.keywords = kwArr.join(', ');\r\n }\r\n\r\n const authorStr = str(block, 'author');\r\n if (authorStr) {\r\n meta.author = authorStr;\r\n } else {\r\n const authorsArr = extractArray(block, 'authors');\r\n if (authorsArr) {\r\n const name = authorsArr.match(/name\\s*:\\s*['\"]([^'\"]+)['\"]/)?.[1];\r\n if (name) meta.author = name;\r\n }\r\n }\r\n\r\n if (!meta.canonical) {\r\n const base = block.match(/metadataBase\\s*:\\s*new\\s+URL\\s*\\(\\s*['\"]([^'\"]+)['\"]/)?.[1];\r\n if (base) meta.canonical = base;\r\n }\r\n\r\n const ogBlock = extractBlock(block, 'openGraph');\r\n if (ogBlock) {\r\n meta.openGraph = {\r\n title : str(ogBlock, 'title'),\r\n description : str(ogBlock, 'description'),\r\n url : str(ogBlock, 'url'),\r\n type : str(ogBlock, 'type'),\r\n image : firstArrayStr(ogBlock, 'images') ?? str(ogBlock, 'image'),\r\n };\r\n }\r\n\r\n const twBlock = extractBlock(block, 'twitter');\r\n if (twBlock) {\r\n meta.twitter = {\r\n card : str(twBlock, 'card'),\r\n title : str(twBlock, 'title'),\r\n description : str(twBlock, 'description'),\r\n creator : str(twBlock, 'creator'),\r\n image : firstArrayStr(twBlock, 'images') ?? str(twBlock, 'image'),\r\n };\r\n }\r\n\r\n const iconsBlock = extractBlock(block, 'icons');\r\n if (iconsBlock) {\r\n meta.icons = {\r\n icon : collectIconEntries(iconsBlock, 'icon'),\r\n shortcut: collectIconEntries(iconsBlock, 'shortcut'),\r\n apple : collectIconEntries(iconsBlock, 'apple'),\r\n };\r\n }\r\n\r\n return meta;\r\n}\r\n\r\nfunction collectIconEntries(source: string, key: string): IconEntry[] {\r\n const arr = extractArrayRaw(source, key);\r\n if (!arr) return [];\r\n const entries: IconEntry[] = [];\r\n const objRe = /\\{([^}]+)\\}/g;\r\n let m: RegExpExecArray | null;\r\n while ((m = objRe.exec(arr)) !== null) {\r\n const obj = m[1];\r\n const url = obj.match(/url\\s*:\\s*['\"]([^'\"]+)['\"]/)?.[1];\r\n if (!url) continue;\r\n entries.push({\r\n url,\r\n type : obj.match(/type\\s*:\\s*['\"]([^'\"]+)['\"]/)?.[1],\r\n sizes: obj.match(/sizes\\s*:\\s*['\"]([^'\"]+)['\"]/)?.[1],\r\n });\r\n }\r\n if (!entries.length) {\r\n return [...arr.matchAll(/['\"]([^'\"]+)['\"]/g)].map(x => ({ url: x[1] }));\r\n }\r\n return entries;\r\n}\r\n\r\nfunction extractArrayRaw(source: string, key: string): string | undefined {\r\n const re = new RegExp(`['\"]?${key}['\"]?\\\\s*:\\\\s*\\\\[`);\r\n const match = re.exec(source);\r\n if (!match) return undefined;\r\n let d = 0, i = match.index + match[0].length - 1;\r\n const start = i;\r\n for (; i < source.length; i++) {\r\n if (source[i] === '[') d++;\r\n else if (source[i] === ']') { d--; if (d === 0) return source.slice(start, i + 1); }\r\n }\r\n return undefined;\r\n}\r\n\r\n// ─── API Route Scanner ────────────────────────────────────────────────────────\r\n\r\nfunction scanApiRoutes(dir: string, baseRoute = ''): ApiRoute[] {\r\n const routes: ApiRoute[] = [];\r\n if (!fs.existsSync(dir)) return routes;\r\n\r\n let entries: fs.Dirent[];\r\n try { entries = fs.readdirSync(dir, { withFileTypes: true }); }\r\n catch { return routes; }\r\n\r\n for (const entry of entries) {\r\n if (entry.name.startsWith('_') || entry.name.startsWith('.')) continue;\r\n const fullPath = path.join(dir, entry.name);\r\n\r\n if (entry.isDirectory()) {\r\n const isCatchAll = entry.name.startsWith('[...') && entry.name.endsWith(']');\r\n const isDynamic = entry.name.startsWith('[') && entry.name.endsWith(']');\r\n const segment = isCatchAll ? '*' : isDynamic ? `:${entry.name.slice(1, -1)}` : entry.name;\r\n routes.push(...scanApiRoutes(fullPath, `${baseRoute}/${segment}`));\r\n continue;\r\n }\r\n\r\n const ext = path.extname(entry.name);\r\n const base = path.basename(entry.name, ext);\r\n if (!(API_EXTS as readonly string[]).includes(ext)) continue;\r\n\r\n const isCatchAll = base.startsWith('[...') && base.endsWith(']');\r\n const isDynamic = base.startsWith('[') && base.endsWith(']');\r\n const routePath = isCatchAll\r\n ? `${baseRoute}/*`\r\n : base === 'index'\r\n ? baseRoute || '/'\r\n : isDynamic\r\n ? `${baseRoute}/:${base.slice(1, -1)}`\r\n : `${baseRoute}/${base}`;\r\n\r\n routes.push({ routePath, filePath: fullPath });\r\n }\r\n\r\n return routes;\r\n}\r\n\r\n// ─── Hono dev/preview server ──────────────────────────────────────────────────\r\n\r\nfunction matchRoute(pattern: string, pathname: string): Record<string, string> | null {\r\n const patParts = pattern.split('/').filter(Boolean);\r\n const urlParts = pathname.split('/').filter(Boolean);\r\n\r\n const isCatchAll = patParts[patParts.length - 1] === '*';\r\n if (isCatchAll) {\r\n const prefix = patParts.slice(0, -1);\r\n if (urlParts.length < prefix.length) return null;\r\n for (let i = 0; i < prefix.length; i++) {\r\n if (prefix[i].startsWith(':')) continue;\r\n if (prefix[i] !== urlParts[i]) return null;\r\n }\r\n return { '*': urlParts.slice(prefix.length).join('/') };\r\n }\r\n\r\n if (patParts.length !== urlParts.length) return null;\r\n\r\n const params: Record<string, string> = {};\r\n for (let i = 0; i < patParts.length; i++) {\r\n if (patParts[i].startsWith(':')) {\r\n params[patParts[i].slice(1)] = decodeURIComponent(urlParts[i]);\r\n } else if (patParts[i] !== urlParts[i]) {\r\n return null;\r\n }\r\n }\r\n return params;\r\n}\r\n\r\nconst moduleCache = new Map<string, { mtime: number; handler: unknown }>();\r\n\r\nasync function importHandler(filePath: string): Promise<unknown> {\r\n const { pathToFileURL } = await import('url');\r\n let mtime = 0;\r\n try { mtime = fs.statSync(filePath).mtimeMs; } catch { /* file vanished */ }\r\n\r\n const cached = moduleCache.get(filePath);\r\n if (cached && cached.mtime === mtime) return cached.handler;\r\n\r\n const mod = await import(pathToFileURL(filePath).href + '?t=' + mtime);\r\n const handler = mod.default ?? null;\r\n moduleCache.set(filePath, { mtime, handler });\r\n return handler;\r\n}\r\n\r\nasync function handleApiRequest(\r\n req : any,\r\n res : any,\r\n next : any,\r\n apiDir : string,\r\n enableCors : boolean,\r\n getCache : () => { routes: ApiRoute[] } | null,\r\n setCache : (v: { routes: ApiRoute[] }) => void,\r\n) {\r\n try {\r\n if (enableCors && req.method === 'OPTIONS') {\r\n res.statusCode = 204;\r\n res.setHeader('Access-Control-Allow-Origin', '*');\r\n res.setHeader('Access-Control-Allow-Methods', 'GET,POST,PUT,PATCH,DELETE,OPTIONS');\r\n res.setHeader('Access-Control-Allow-Headers', 'Content-Type,Authorization');\r\n res.setHeader('Access-Control-Max-Age', '86400');\r\n res.end();\r\n return;\r\n }\r\n\r\n let cache = getCache();\r\n if (!cache) {\r\n cache = { routes: scanApiRoutes(apiDir, '/api') };\r\n setCache(cache);\r\n }\r\n\r\n const host = req.headers.host ?? 'localhost';\r\n const url = `http://${host}${req.url}`;\r\n const pathname = new URL(url).pathname;\r\n\r\n const chunks: Buffer[] = [];\r\n for await (const chunk of req) chunks.push(chunk as Buffer);\r\n const body = chunks.length > 0 ? Buffer.concat(chunks) : undefined;\r\n\r\n const method = (req.method as string).toUpperCase();\r\n\r\n const webReq = new Request(url, {\r\n method,\r\n headers: req.headers as HeadersInit,\r\n body : !['GET', 'HEAD'].includes(method) && body?.length ? body : undefined,\r\n });\r\n\r\n for (const route of cache.routes) {\r\n const handler = await importHandler(route.filePath);\r\n if (!handler) continue;\r\n\r\n let webRes: Response;\r\n try {\r\n if (typeof (handler as any).fetch === 'function') {\r\n webRes = await (handler as any).fetch(webReq.clone());\r\n if (webRes.status === 404) continue;\r\n } else if (typeof handler === 'function') {\r\n const params = matchRoute(route.routePath, pathname);\r\n if (params === null) continue;\r\n\r\n const existingHeaders: Record<string, string> = {};\r\n webReq.headers.forEach((v, k) => { existingHeaders[k] = v; });\r\n const reqWithParams = new Request(webReq.clone(), {\r\n headers: { ...existingHeaders, 'x-bini-params': JSON.stringify(params) },\r\n });\r\n\r\n webRes = await (handler as (...args: any[]) => Promise<Response>)(reqWithParams);\r\n } else {\r\n continue;\r\n }\r\n } catch {\r\n continue;\r\n }\r\n\r\n const finalHeaders: Record<string, string> = {};\r\n webRes.headers.forEach((v, k) => { finalHeaders[k] = v; });\r\n if (enableCors) {\r\n finalHeaders['access-control-allow-origin'] = '*';\r\n finalHeaders['access-control-allow-methods'] = 'GET,POST,PUT,PATCH,DELETE,OPTIONS';\r\n finalHeaders['access-control-allow-headers'] = 'Content-Type,Authorization';\r\n }\r\n\r\n res.statusCode = webRes.status;\r\n for (const [k, v] of Object.entries(finalHeaders)) res.setHeader(k, v);\r\n res.end(Buffer.from(await webRes.arrayBuffer()));\r\n return;\r\n }\r\n\r\n res.statusCode = 404;\r\n res.setHeader('Content-Type', 'application/json');\r\n res.end(JSON.stringify({ error: `No API handler found for ${req.url}` }));\r\n } catch (e: any) {\r\n next(e);\r\n }\r\n}\r\n\r\n// ─── Production Entry Generator ───────────────────────────────────────────────\r\n\r\ntype Platform = 'netlify' | 'cloudflare' | 'node' | 'deno' | 'bun' | 'aws';\r\n\r\n// ─── Platform adapter config ─────────────────────────────────────────────────\r\n\r\ninterface AdapterConfig {\r\n pkg ?: string; // npm package to install (optional)\r\n importLine ?: string; // import statement for generated file\r\n exportLine : string; // export statement for generated file\r\n outFile : (cwd: string) => string;\r\n stripsApiPrefix: boolean; // platform strips /api before handler sees it\r\n}\r\n\r\n// All adapters use hono's built-in platform adapters — no extra packages needed\r\n// except @hono/node-server for Node.js (not built into hono core)\r\nconst ADAPTERS: Record<Platform, AdapterConfig> = {\r\n\r\n netlify: {\r\n // Netlify Edge Functions — uses hono/netlify adapter built into hono core\r\n importLine : `import { handle } from 'hono/netlify';`,\r\n exportLine : `export default handle(app);`,\r\n outFile : (cwd) => path.join(cwd, 'netlify', 'edge-functions', 'api.ts'),\r\n stripsApiPrefix: false,\r\n },\r\n cloudflare: {\r\n exportLine : `export default app;`,\r\n outFile : (cwd) => path.join(cwd, 'worker.ts'),\r\n stripsApiPrefix: false,\r\n },\r\n node: {\r\n pkg : '@hono/node-server',\r\n importLine : `import { serve } from '@hono/node-server';\r\nimport { serveStatic } from '@hono/node-server/serve-static';`,\r\n exportLine : `app.use('/*', serveStatic({ root: './dist' }));\r\napp.use('/*', serveStatic({ path: './dist/index.html' }));\r\n\r\nserve({ fetch: app.fetch, port: Number(process.env.PORT ?? 3000) }, (i) => {\r\n console.log(\\`Server running on http://localhost:\\${i.port}\\`);\r\n});`,\r\n outFile : (cwd) => path.join(cwd, 'server', 'index.ts'),\r\n stripsApiPrefix: false,\r\n },\r\n deno: {\r\n importLine : `import { serve } from 'hono/deno';`,\r\n exportLine : `serve(app.fetch);`,\r\n outFile : (cwd) => path.join(cwd, 'server', 'index.ts'),\r\n stripsApiPrefix: false,\r\n },\r\n bun: {\r\n exportLine : `export default app;`,\r\n outFile : (cwd) => path.join(cwd, 'server', 'index.ts'),\r\n stripsApiPrefix: false,\r\n },\r\n aws: {\r\n // Requires separate install: npm install @hono/aws-lambda\r\n pkg : '@hono/aws-lambda',\r\n importLine : `import { handle } from '@hono/aws-lambda';`,\r\n exportLine : `export const handler = handle(app);`,\r\n outFile : (cwd) => path.join(cwd, 'handler.ts'),\r\n stripsApiPrefix: false,\r\n },\r\n};\r\n\r\nfunction checkAdapter(platform: Platform): void {\r\n const adapter = ADAPTERS[platform];\r\n if (!adapter.pkg) return;\r\n try {\r\n require.resolve(adapter.pkg, { paths: [process.cwd()] });\r\n } catch {\r\n console.error(`\r\n[bini-router] ✗ Missing required package for platform '${platform}'.\r\n Run: npm install ${adapter.pkg}\r\n`);\r\n process.exit(1);\r\n }\r\n}\r\n\r\nfunction buildRouteImports(\r\n routes : ApiRoute[],\r\n outFile : string,\r\n enableCors: boolean,\r\n platform : Platform,\r\n): { imports: string[]; mountings: string[]; corsLine: string | null; corsImport: string | null } {\r\n const imports : string[] = [];\r\n const mountings : string[] = [];\r\n const adapter = ADAPTERS[platform];\r\n const stripPrefix = adapter.stripsApiPrefix;\r\n\r\n for (let i = 0; i < routes.length; i++) {\r\n const route = routes[i];\r\n const rel = norm(path.relative(path.dirname(outFile), route.filePath)).replace(/\\.(ts|tsx)$/, '');\r\n const imp = rel.startsWith('.') ? rel : `./${rel}`;\r\n const name = `_route${i}`;\r\n\r\n let src = '';\r\n try { src = fs.readFileSync(route.filePath, 'utf8'); } catch { /* skip */ }\r\n const isHonoApp = src.includes(\"from 'hono'\") || src.includes('from \"hono\"');\r\n\r\n imports.push(`import ${name} from '${imp}';`);\r\n\r\n if (isHonoApp) {\r\n mountings.push(`app.route('/', ${name});`);\r\n } else {\r\n // Some platforms strip /api prefix before the handler sees the request\r\n const mountPath = stripPrefix ? route.routePath : `/api${route.routePath}`;\r\n mountings.push(`app.all('${mountPath}', async (c) => { const r = await ${name}(c.req.raw); return r instanceof Response ? r : c.json(r); });`);\r\n }\r\n }\r\n\r\n const corsPattern = stripPrefix ? '/*' : '/api/*';\r\n const corsLine = enableCors\r\n ? `app.use('${corsPattern}', cors({ origin: '*', allowMethods: ['GET','POST','PUT','PATCH','DELETE','OPTIONS'], allowHeaders: ['Content-Type','Authorization'] }));`\r\n : null;\r\n const corsImport = enableCors ? `import { cors } from 'hono/cors';` : null;\r\n\r\n return { imports, mountings, corsLine, corsImport };\r\n}\r\n\r\nfunction buildProductionEntry(srcApiDir: string, platform: Platform, enableCors: boolean): void {\r\n if (!fs.existsSync(srcApiDir)) return;\r\n\r\n const routes = scanApiRoutes(srcApiDir);\r\n const cwd = process.cwd();\r\n\r\n const header = [\r\n `// ⚠️ Auto-generated by bini-router on every build — do not edit.`,\r\n `// Add routes by creating files in src/app/api/ only.`,\r\n ];\r\n\r\n // ── All platforms: use adapter config to generate entry file ────────────────\r\n checkAdapter(platform);\r\n\r\n const adapter = ADAPTERS[platform];\r\n const outFile = adapter.outFile(cwd);\r\n\r\n const { imports, mountings, corsLine, corsImport } = buildRouteImports(routes, outFile, enableCors, platform);\r\n\r\n const lines = [\r\n ...header,\r\n `import { Hono } from 'hono';`,\r\n ...(adapter.importLine ? adapter.importLine.split('\\n') : []),\r\n ...(corsImport ? [corsImport] : []),\r\n ...imports,\r\n ``,\r\n `const app = new Hono();`,\r\n ...(corsLine ? [corsLine] : []),\r\n ...mountings,\r\n ``,\r\n ...adapter.exportLine.split('\\n'),\r\n ];\r\n\r\n fs.mkdirSync(path.dirname(outFile), { recursive: true });\r\n fs.writeFileSync(outFile, lines.join('\\n') + '\\n', 'utf8');\r\n console.log(`[bini-router] ✓ Generated ${norm(path.relative(cwd, outFile))}`);\r\n}\r\n\r\n// ─── Plugin ───────────────────────────────────────────────────────────────────\r\n\r\nexport function biniroute(options: BiniPluginOptions = {}): Plugin {\r\n const { cors: enableCors = true, platform } = options;\r\n\r\n const getAppDir = () => path.join(process.cwd(), options.appDir ?? 'src/app');\r\n const getApiDir = () => path.join(process.cwd(), options.apiDir ?? 'src/app/api');\r\n\r\n let debounceTimer : ReturnType<typeof setTimeout> | null = null;\r\n let lastGeneratedCode = '';\r\n let honoCache : { routes: ApiRoute[] } | null = null;\r\n const eventLog = new Map<string, number>();\r\n\r\n function shouldProcess(file: string, event: string): boolean {\r\n const key = `${file}:${event}`;\r\n const now = Date.now();\r\n if (now - (eventLog.get(key) ?? 0) < EVENT_DEDUP_MS) return false;\r\n eventLog.set(key, now);\r\n for (const [k, v] of eventLog) if (now - v > EVENT_TTL_MS) eventLog.delete(k);\r\n return true;\r\n }\r\n\r\n function isPageFile(f: string): boolean {\r\n const nf = norm(f);\r\n const base = path.basename(f, path.extname(f));\r\n const ext = path.extname(f);\r\n if (!(SUPPORTED_EXTS as readonly string[]).includes(ext)) return false;\r\n if (!isInDir(nf, norm(getAppDir()))) return false;\r\n if (isInDir(nf, norm(getApiDir()))) return false;\r\n if (base.startsWith('_')) return false;\r\n return true;\r\n }\r\n\r\n function isApiFile(f: string): boolean {\r\n const nf = norm(f);\r\n return isInDir(nf, norm(getApiDir())) &&\r\n (API_EXTS as readonly string[]).includes(path.extname(f));\r\n }\r\n\r\n function applyApp(): string | null {\r\n const dir = getAppDir();\r\n if (!fs.existsSync(dir)) return null;\r\n const code = generateApp(dir);\r\n if (code === lastGeneratedCode) return null;\r\n fs.writeFileSync(getAppFile(), code, 'utf8');\r\n lastGeneratedCode = code;\r\n return code;\r\n }\r\n\r\n function scheduleRegen(server: ViteDevServer, delay = DEBOUNCE_MS) {\r\n if (debounceTimer) clearTimeout(debounceTimer);\r\n debounceTimer = setTimeout(() => {\r\n debounceTimer = null;\r\n if (applyApp() !== null) {\r\n server.ws.send({ type: 'full-reload', path: '*' });\r\n }\r\n }, delay);\r\n }\r\n\r\n function addSpaFallback(server: { middlewares: any }) {\r\n server.middlewares.use((req: any, res: any, next: any) => {\r\n const url = req.url as string;\r\n if (url.startsWith('/api') || url.includes('.')) return next();\r\n req.url = '/index.html';\r\n next();\r\n });\r\n }\r\n\r\n return {\r\n name : 'bini-router',\r\n enforce: 'pre',\r\n\r\n transform(code, id) {\r\n const nid = norm(id);\r\n if (!isInDir(nid, norm(getAppDir()))) return;\r\n const ext = path.extname(id);\r\n if (!(SUPPORTED_EXTS as readonly string[]).includes(ext)) return;\r\n if (!code.includes('export const metadata')) return;\r\n\r\n let result = code;\r\n let idx = result.indexOf('export const metadata');\r\n\r\n while (idx !== -1) {\r\n const braceIdx = result.indexOf('{', idx);\r\n if (braceIdx === -1) break;\r\n\r\n let depth = 0, end = braceIdx;\r\n for (let i = braceIdx; i < result.length; i++) {\r\n if (result[i] === '{') depth++;\r\n else if (result[i] === '}') { depth--; if (depth === 0) { end = i; break; } }\r\n }\r\n\r\n let tail = end + 1;\r\n while (tail < result.length && (result[tail] === ' ' || result[tail] === '\\t')) tail++;\r\n if (tail < result.length && result[tail] === ';') tail++;\r\n while (tail < result.length && (result[tail] === '\\n' || result[tail] === '\\r')) tail++;\r\n\r\n result = result.slice(0, idx) + result.slice(tail);\r\n idx = result.indexOf('export const metadata', idx);\r\n }\r\n\r\n return { code: result, map: null };\r\n },\r\n\r\n config() { applyApp(); },\r\n buildStart() { applyApp(); },\r\n\r\n closeBundle() {\r\n if (platform) buildProductionEntry(getApiDir(), platform, enableCors);\r\n },\r\n\r\n buildEnd() {\r\n honoCache = null;\r\n moduleCache.clear();\r\n if (debounceTimer) { clearTimeout(debounceTimer); debounceTimer = null; }\r\n },\r\n\r\n async configureServer(server) {\r\n const appDir = getAppDir();\r\n const apiDir = getApiDir();\r\n\r\n if (!fs.existsSync(appDir)) return;\r\n\r\n server.watcher.add(appDir);\r\n\r\n server.watcher.on('add', f => isPageFile(f) && shouldProcess(f, 'add') && scheduleRegen(server, 300));\r\n server.watcher.on('unlink', f => isPageFile(f) && shouldProcess(f, 'unlink') && scheduleRegen(server));\r\n server.watcher.on('change', f => isPageFile(f) && shouldProcess(f, 'change') && scheduleRegen(server));\r\n\r\n server.watcher.on('change', f => {\r\n const base = path.basename(f, path.extname(f));\r\n const inAppRoot = path.resolve(path.dirname(f)) === path.resolve(appDir);\r\n if (!inAppRoot || base !== 'layout') return;\r\n server.moduleGraph.invalidateAll();\r\n server.ws.send({ type: 'full-reload', path: '*' });\r\n });\r\n\r\n server.watcher.on('addDir', d => {\r\n const nd = norm(d);\r\n if (!isInDir(nd, norm(appDir)) || d.includes('node_modules') || isInDir(nd, norm(apiDir))) return;\r\n setTimeout(() => PAGE_FILES.some(f => fs.existsSync(path.join(d, f))) && scheduleRegen(server), 300);\r\n });\r\n\r\n server.watcher.on('unlinkDir', d => {\r\n const nd = norm(d);\r\n if (isInDir(nd, norm(appDir)) && !d.includes('node_modules') && !isInDir(nd, norm(apiDir)))\r\n scheduleRegen(server);\r\n });\r\n\r\n if (fs.existsSync(apiDir)) {\r\n server.watcher.add(apiDir);\r\n\r\n const resetApi = (f?: string) => {\r\n honoCache = null;\r\n if (f) moduleCache.delete(f);\r\n server.ws.send({ type: 'full-reload', path: '*' });\r\n };\r\n\r\n server.watcher.on('add', f => isApiFile(f) && resetApi(f));\r\n server.watcher.on('unlink', f => isApiFile(f) && resetApi(f));\r\n server.watcher.on('change', f => isApiFile(f) && resetApi(f));\r\n\r\n server.middlewares.use((req: any, res: any, next: any) => {\r\n if (!req.url?.startsWith('/api')) return next();\r\n handleApiRequest(req, res, next, apiDir, enableCors,\r\n () => honoCache, (v) => { honoCache = v; });\r\n });\r\n }\r\n },\r\n\r\n async configurePreviewServer(server) {\r\n addSpaFallback(server);\r\n\r\n const apiDir = getApiDir();\r\n if (!fs.existsSync(apiDir)) return;\r\n server.middlewares.use((req: any, res: any, next: any) => {\r\n if (!req.url?.startsWith('/api')) return next();\r\n handleApiRequest(req, res, next, apiDir, enableCors,\r\n () => honoCache, (v) => { honoCache = v; });\r\n });\r\n },\r\n\r\n transformIndexHtml: {\r\n order: 'pre',\r\n handler(html) {\r\n const meta = parseAppMetadata(getAppDir());\r\n\r\n if (!meta.title && !meta.description && !meta.canonical && !meta.manifest &&\r\n !meta.openGraph?.title && !meta.icons?.icon?.length) {\r\n return html;\r\n }\r\n\r\n const title = meta.title ?? 'Bini App';\r\n const vp = meta.viewport ?? 'width=device-width, initial-scale=1.0';\r\n\r\n const lines: string[] = [];\r\n\r\n lines.push(`<meta charset=\"${meta.charset ?? 'UTF-8'}\" />`);\r\n lines.push(`<meta name=\"viewport\" content=\"${vp}\" />`);\r\n lines.push(`<title>${title}</title>`);\r\n if (meta.description) lines.push(`<meta name=\"description\" content=\"${meta.description}\" />`);\r\n if (meta.themeColor) lines.push(`<meta name=\"theme-color\" content=\"${meta.themeColor}\" />`);\r\n if (meta.robots) lines.push(`<meta name=\"robots\" content=\"${meta.robots}\" />`);\r\n if (meta.keywords) lines.push(`<meta name=\"keywords\" content=\"${meta.keywords}\" />`);\r\n if (meta.author) lines.push(`<meta name=\"author\" content=\"${meta.author}\" />`);\r\n if (meta.canonical) lines.push(`<link rel=\"canonical\" href=\"${meta.canonical}\" />`);\r\n if (meta.manifest) lines.push(`<link rel=\"manifest\" href=\"${meta.manifest}\" />`);\r\n\r\n for (const entry of meta.icons?.icon ?? []) {\r\n const type = entry.type ? ` type=\"${entry.type}\"` : '';\r\n const sizes = entry.sizes ? ` sizes=\"${entry.sizes}\"` : '';\r\n lines.push(`<link rel=\"icon\" href=\"${entry.url}\"${type}${sizes} />`);\r\n }\r\n for (const entry of meta.icons?.shortcut ?? []) {\r\n lines.push(`<link rel=\"shortcut icon\" href=\"${entry.url}\" />`);\r\n }\r\n for (const entry of meta.icons?.apple ?? []) {\r\n const sizes = entry.sizes ? ` sizes=\"${entry.sizes}\"` : '';\r\n const type = entry.type ? ` type=\"${entry.type}\"` : '';\r\n lines.push(`<link rel=\"apple-touch-icon\" href=\"${entry.url}\"${sizes}${type} />`);\r\n }\r\n\r\n if (meta.openGraph?.title) {\r\n lines.push(`<meta property=\"og:type\" content=\"${meta.openGraph.type ?? 'website'}\" />`);\r\n lines.push(`<meta property=\"og:title\" content=\"${meta.openGraph.title}\" />`);\r\n if (meta.openGraph.description) lines.push(`<meta property=\"og:description\" content=\"${meta.openGraph.description}\" />`);\r\n if (meta.openGraph.url) lines.push(`<meta property=\"og:url\" content=\"${meta.openGraph.url}\" />`);\r\n if (meta.openGraph.image) lines.push(`<meta property=\"og:image\" content=\"${meta.openGraph.image}\" />`);\r\n }\r\n\r\n if (meta.twitter?.title) {\r\n lines.push(`<meta name=\"twitter:card\" content=\"${meta.twitter.card ?? 'summary_large_image'}\" />`);\r\n lines.push(`<meta name=\"twitter:title\" content=\"${meta.twitter.title}\" />`);\r\n if (meta.twitter.description) lines.push(`<meta name=\"twitter:description\" content=\"${meta.twitter.description}\" />`);\r\n if (meta.twitter.creator) lines.push(`<meta name=\"twitter:creator\" content=\"${meta.twitter.creator}\" />`);\r\n if (meta.twitter.image) lines.push(`<meta name=\"twitter:image\" content=\"${meta.twitter.image}\" />`);\r\n }\r\n\r\n const injected = lines.map(l => ` ${l}`).join('\\n');\r\n return html.replace('</head>', `${injected}\\n </head>`);\r\n },\r\n },\r\n };\r\n}\r\n\r\nexport default biniroute;"],"mappings":"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","names":["path","fs","isCatchAll","isDynamic"]}
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["import fs from 'fs';\r\nimport path from 'path';\r\nimport type { Plugin, ViteDevServer } from 'vite';\r\n\r\n// ─── Constants ────────────────────────────────────────────────────────────────\r\n\r\nconst PAGE_FILES = ['page.tsx', 'page.jsx', 'page.ts', 'page.js'] as const;\r\nconst LAYOUT_FILES = ['layout.tsx', 'layout.jsx', 'layout.ts', 'layout.js'] as const;\r\nconst SUPPORTED_EXTS = ['.tsx', '.jsx', '.ts', '.js'] as const;\r\nconst NOT_FOUND_FILES = SUPPORTED_EXTS.map(e => `not-found${e}`);\r\nconst SPECIAL_BASES = new Set(['page', 'layout', 'not-found', 'loading', 'error']);\r\nconst API_EXTS = ['.ts', '.js'] as const;\r\nconst DEBOUNCE_MS = 60;\r\nconst EVENT_DEDUP_MS = 500;\r\nconst EVENT_TTL_MS = 2000;\r\n\r\n// ─── Metadata Types ───────────────────────────────────────────────────────────\r\n\r\nexport interface IconEntry {\r\n url : string;\r\n type ?: string;\r\n sizes?: string;\r\n}\r\n\r\nexport interface MetaTags {\r\n title ?: string;\r\n description ?: string;\r\n viewport ?: string;\r\n themeColor ?: string;\r\n keywords ?: string;\r\n author ?: string;\r\n charset ?: string;\r\n robots ?: string;\r\n canonical ?: string;\r\n manifest ?: string;\r\n openGraph ?: Partial<OGMeta>;\r\n twitter ?: Partial<TwitterMeta>;\r\n icons ?: {\r\n icon ?: IconEntry[];\r\n shortcut ?: IconEntry[];\r\n apple ?: IconEntry[];\r\n };\r\n}\r\n\r\ninterface OGMeta {\r\n title : string;\r\n description : string;\r\n url : string;\r\n image : string;\r\n type : string;\r\n}\r\n\r\ninterface TwitterMeta {\r\n card : string;\r\n title : string;\r\n description : string;\r\n creator : string;\r\n image : string;\r\n}\r\n\r\n// ─── Types ────────────────────────────────────────────────────────────────────\r\n\r\ninterface RouteNode {\r\n routePath : string;\r\n filePath : string;\r\n layouts : string[];\r\n dynamic : boolean;\r\n}\r\n\r\ninterface LayoutChainGroup {\r\n layouts : string[];\r\n routes : RouteNode[];\r\n}\r\n\r\ninterface ApiRoute {\r\n routePath : string;\r\n filePath : string;\r\n}\r\n\r\nexport interface BiniPluginOptions {\r\n /** Directory for page files. Default: src/app */\r\n appDir?: string;\r\n /** Directory for API routes. Default: src/app/api */\r\n apiDir?: string;\r\n /** Enable CORS headers in the dev-server API middleware. Default: true */\r\n cors?: boolean;\r\n /**\r\n * Target deployment platform. bini-router generates a production entry\r\n * file on every build — users only write code in src/app/api/.\r\n *\r\n * 'netlify' → netlify/edge-functions/api.ts (default, zero config)\r\n * 'cloudflare' → worker.ts (install: wrangler)\r\n * 'node' → server/index.ts (install: @hono/node-server)\r\n * 'deno' → server/index.ts (run with: deno run)\r\n * 'bun' → server/index.ts (run with: bun run)\r\n * 'aws' → handler.ts (install: @hono/aws-lambda)\r\n *\r\n * Default: undefined (no entry generated)\r\n */\r\n platform?: 'netlify' | 'cloudflare' | 'node' | 'deno' | 'bun' | 'aws';\r\n}\r\n\r\n// ─── Utilities ────────────────────────────────────────────────────────────────\r\n\r\nfunction norm(p: string): string {\r\n return p.replace(/\\\\/g, '/');\r\n}\r\n\r\nfunction isInDir(file: string, dir: string): boolean {\r\n const nFile = norm(file);\r\n const nDir = norm(dir).replace(/\\/$/, '');\r\n return nFile.startsWith(nDir + '/') || nFile === nDir;\r\n}\r\n\r\nfunction readTsconfigAliases(): Record<string, string> {\r\n const aliases: Record<string, string> = {};\r\n try {\r\n const tsconfigPath = path.join(process.cwd(), 'tsconfig.json');\r\n if (!fs.existsSync(tsconfigPath)) return aliases;\r\n const raw = fs.readFileSync(tsconfigPath, 'utf8')\r\n .replace(/\\/\\/.*$/gm, '')\r\n .replace(/\\/\\*[\\s\\S]*?\\*\\//g, '');\r\n const tsconfig = JSON.parse(raw);\r\n const paths = tsconfig?.compilerOptions?.paths ?? {};\r\n const baseUrl = tsconfig?.compilerOptions?.baseUrl ?? '.';\r\n for (const [alias, targets] of Object.entries(paths) as [string, string[]][]) {\r\n const cleanAlias = alias.replace(/\\/\\*$/, '');\r\n const cleanTarget = (targets[0] ?? '').replace(/\\/\\*$/, '');\r\n aliases[cleanAlias] = path.resolve(process.cwd(), baseUrl, cleanTarget);\r\n }\r\n } catch { /* tsconfig unreadable — fall back to relative paths */ }\r\n return aliases;\r\n}\r\n\r\nfunction toImportPath(filePath: string, aliases: Record<string, string>): string {\r\n for (const [alias, target] of Object.entries(aliases)) {\r\n if (norm(filePath).startsWith(norm(target) + '/')) {\r\n const rest = norm(filePath).slice(norm(target).length + 1).replace(/\\.(tsx|ts|jsx|js)$/, '');\r\n return `${alias}/${rest}`;\r\n }\r\n }\r\n return './' + norm(path.relative(path.join(process.cwd(), 'src'), filePath))\r\n .replace(/\\.(tsx|ts|jsx|js)$/, '');\r\n}\r\n\r\nfunction hasDefaultExport(filePath: string): boolean {\r\n try { return fs.readFileSync(filePath, 'utf8').includes('export default'); }\r\n catch { return false; }\r\n}\r\n\r\nfunction isHtmlShellLayout(filePath: string): boolean {\r\n try { return /<html[\\s>]/i.test(fs.readFileSync(filePath, 'utf8')); }\r\n catch { return false; }\r\n}\r\n\r\nfunction isUsableLayout(filePath: string): boolean {\r\n return hasDefaultExport(filePath) && !isHtmlShellLayout(filePath);\r\n}\r\n\r\nfunction findFile(dir: string, candidates: readonly string[]): string | null {\r\n return candidates.find(f => fs.existsSync(path.join(dir, f))) ?? null;\r\n}\r\n\r\nfunction getAppFile(): string {\r\n const ts = path.join(process.cwd(), 'src/App.tsx');\r\n return fs.existsSync(ts) ? ts : path.join(process.cwd(), 'src/App.jsx');\r\n}\r\n\r\n// ─── Layout Resolution ────────────────────────────────────────────────────────\r\n\r\nfunction resolveLayoutChain(pageDir: string, appDir: string): string[] {\r\n const chain: string[] = [];\r\n let current = pageDir;\r\n while (true) {\r\n const layout = findFile(current, LAYOUT_FILES);\r\n if (layout) chain.unshift(path.join(current, layout));\r\n if (path.resolve(current) === path.resolve(appDir)) break;\r\n const parent = path.dirname(current);\r\n if (parent === current) break;\r\n current = parent;\r\n }\r\n return chain;\r\n}\r\n\r\n// ─── Route Scanner ────────────────────────────────────────────────────────────\r\n\r\nfunction scanRoutes(dir: string, appDir: string, baseRoute = ''): RouteNode[] {\r\n const routes: RouteNode[] = [];\r\n if (!fs.existsSync(dir)) return routes;\r\n\r\n let entries: fs.Dirent[];\r\n try { entries = fs.readdirSync(dir, { withFileTypes: true }); }\r\n catch { return routes; }\r\n\r\n // File-based: about.tsx → /about\r\n for (const entry of entries) {\r\n if (!entry.isFile() || entry.name.startsWith('.') || entry.name.startsWith('_')) continue;\r\n const ext = path.extname(entry.name);\r\n const base = path.basename(entry.name, ext);\r\n if (!(SUPPORTED_EXTS as readonly string[]).includes(ext)) continue;\r\n if (SPECIAL_BASES.has(base)) continue;\r\n routes.push({\r\n routePath : `${baseRoute}/${base}`,\r\n filePath : path.join(dir, entry.name),\r\n layouts : resolveLayoutChain(dir, appDir),\r\n dynamic : false,\r\n });\r\n }\r\n\r\n // Directory-based: [id]/page.tsx → /:id\r\n for (const entry of entries) {\r\n if (!entry.isDirectory()) continue;\r\n if (entry.name === 'node_modules' || entry.name.startsWith('.') || entry.name === 'api') continue;\r\n\r\n const fullPath = path.join(dir, entry.name);\r\n const isDynamic = entry.name.startsWith('[') && entry.name.endsWith(']');\r\n const segment = isDynamic ? `:${entry.name.slice(1, -1)}` : entry.name;\r\n const routePath = `${baseRoute}/${segment}`;\r\n\r\n const pageFile = findFile(fullPath, PAGE_FILES);\r\n if (pageFile) {\r\n routes.push({\r\n routePath,\r\n filePath : path.join(fullPath, pageFile),\r\n layouts : resolveLayoutChain(fullPath, appDir),\r\n dynamic : isDynamic,\r\n });\r\n }\r\n routes.push(...scanRoutes(fullPath, appDir, routePath));\r\n }\r\n\r\n return routes;\r\n}\r\n\r\nfunction deduplicateRoutes(routes: RouteNode[]): RouteNode[] {\r\n const seen = new Set<string>();\r\n return routes.filter(r => {\r\n if (seen.has(r.routePath)) return false;\r\n seen.add(r.routePath);\r\n return true;\r\n });\r\n}\r\n\r\n// ─── Per-layout title extractor ──────────────────────────────────────────────\r\n\r\nfunction parseLayoutTitle(layoutFile: string): string | null {\r\n let src = '';\r\n try { src = fs.readFileSync(layoutFile, 'utf8'); }\r\n catch { return null; }\r\n\r\n const startIdx = src.indexOf('export const metadata');\r\n if (startIdx === -1) return null;\r\n const braceStart = src.indexOf('{', startIdx);\r\n if (braceStart === -1) return null;\r\n\r\n let depth = 0, end = braceStart;\r\n for (let i = braceStart; i < src.length; i++) {\r\n if (src[i] === '{') depth++;\r\n else if (src[i] === '}') { depth--; if (depth === 0) { end = i; break; } }\r\n }\r\n const block = src.slice(braceStart, end + 1);\r\n const match = /['\"]?title['\"]?\\s*:\\s*['\"`]([^'\"`]+)['\"`]/.exec(block);\r\n return match ? match[1] : null;\r\n}\r\n\r\n// ─── Route Tree Renderer ──────────────────────────────────────────────────────\r\n\r\nfunction renderChain(\r\n layouts : string[],\r\n routesInChain : RouteNode[],\r\n layoutNames : Map<string, string>,\r\n pageNames : Map<string, string>,\r\n layoutTitles : Map<string, string>,\r\n indent : number,\r\n): string {\r\n const pad = ' '.repeat(indent);\r\n if (layouts.length === 0) {\r\n return routesInChain.map(r =>\r\n `${pad}<Route path=\"${r.routePath}\" element={<Suspense fallback={<Spinner />}><ErrorBoundary><${pageNames.get(r.filePath)} /></ErrorBoundary></Suspense>} />`\r\n ).join('\\n');\r\n }\r\n const [head, ...tail] = layouts;\r\n const title = layoutTitles.get(head);\r\n const titleSetter = title ? `<TitleSetter title=${JSON.stringify(title)} />` : '';\r\n const inner = renderChain(tail, routesInChain, layoutNames, pageNames, layoutTitles, indent + 2);\r\n const name = layoutNames.get(head);\r\n return [\r\n `${pad}<Route element={<>${titleSetter}<Suspense fallback={<Spinner />}><ErrorBoundary><${name}><Outlet /></${name}></ErrorBoundary></Suspense></>}>`,\r\n inner,\r\n `${pad}</Route>`,\r\n ].join('\\n');\r\n}\r\n\r\n// ─── App Generator ────────────────────────────────────────────────────────────\r\n\r\nfunction generateApp(appDir: string): string {\r\n const aliases = readTsconfigAliases();\r\n const routes = scanRoutes(appDir, appDir);\r\n\r\n const rootPage = findFile(appDir, PAGE_FILES);\r\n if (rootPage) {\r\n routes.unshift({\r\n routePath : '/',\r\n filePath : path.join(appDir, rootPage),\r\n layouts : resolveLayoutChain(appDir, appDir),\r\n dynamic : false,\r\n });\r\n }\r\n\r\n const routesFiltered = routes.map(r => ({\r\n ...r,\r\n layouts: r.layouts.filter(l => isUsableLayout(l)),\r\n }));\r\n\r\n const validRoutes = deduplicateRoutes(\r\n routesFiltered.filter(r => hasDefaultExport(r.filePath))\r\n );\r\n\r\n validRoutes.sort((a, b) => {\r\n if (a.dynamic !== b.dynamic) return a.dynamic ? 1 : -1;\r\n return a.routePath.length - b.routePath.length;\r\n });\r\n\r\n const notFoundFile = NOT_FOUND_FILES.find(f => fs.existsSync(path.join(appDir, f)));\r\n const notFound = notFoundFile && hasDefaultExport(path.join(appDir, notFoundFile))\r\n ? notFoundFile\r\n : undefined;\r\n\r\n const allLayouts = new Set<string>();\r\n for (const r of validRoutes) r.layouts.forEach(l => {\r\n if (isUsableLayout(l)) allLayouts.add(l);\r\n });\r\n\r\n const layoutNames = new Map<string, string>();\r\n const pageNames = new Map<string, string>();\r\n const layoutTitles = new Map<string, string>();\r\n let li = 0, pi = 0;\r\n for (const l of allLayouts) {\r\n layoutNames.set(l, `Layout${li++}`);\r\n const title = parseLayoutTitle(l);\r\n if (title) layoutTitles.set(l, title);\r\n }\r\n for (const r of validRoutes) {\r\n if (!pageNames.has(r.filePath)) pageNames.set(r.filePath, `Page${pi++}`);\r\n }\r\n\r\n const lazyImports: string[] = [];\r\n for (const [fp, name] of layoutNames)\r\n lazyImports.push(`const ${name} = React.lazy(() => import('${toImportPath(fp, aliases)}'));`);\r\n if (notFound)\r\n lazyImports.push(`const NotFound = React.lazy(() => import('${toImportPath(path.join(appDir, notFound), aliases)}'));`);\r\n const emittedPages = new Set<string>();\r\n for (const r of validRoutes) {\r\n if (emittedPages.has(r.filePath)) continue;\r\n emittedPages.add(r.filePath);\r\n const name = pageNames.get(r.filePath);\r\n if (!name) continue;\r\n lazyImports.push(`const ${name} = React.lazy(() => import('${toImportPath(r.filePath, aliases)}'));`);\r\n }\r\n\r\n const chainMap = new Map<string, LayoutChainGroup>();\r\n for (const r of validRoutes) {\r\n const key = r.layouts.join('|');\r\n if (!chainMap.has(key)) chainMap.set(key, { layouts: r.layouts, routes: [] });\r\n chainMap.get(key)!.routes.push(r);\r\n }\r\n\r\n const routeLines: string[] = [];\r\n for (const [, { layouts, routes: cr }] of chainMap)\r\n routeLines.push(renderChain(layouts, cr, layoutNames, pageNames, layoutTitles, 8));\r\n\r\n const catchAll = notFound\r\n ? ` <Route path=\"*\" element={<Suspense fallback={<Spinner />}><NotFound /></Suspense>} />`\r\n : ` <Route path=\"*\" element={<Default404 />} />`;\r\n\r\n return `// ⚠️ Auto-generated by bini-router — do not edit.\r\nimport React, { Suspense } from 'react';\r\nimport { BrowserRouter, Routes, Route, Outlet } from 'react-router-dom';\r\nimport './app/globals.css';\r\n\r\n${lazyImports.join('\\n')}\r\n\r\n// ─── Error Boundary ───────────────────────────────────────────────────────────\r\nclass ErrorBoundary extends React.Component<\r\n { children: React.ReactNode },\r\n { error: Error | null }\r\n> {\r\n constructor(props: { children: React.ReactNode }) {\r\n super(props);\r\n this.state = { error: null };\r\n }\r\n static getDerivedStateFromError(error: Error) { return { error }; }\r\n override render() {\r\n if (this.state.error) return (\r\n <div style={{ minHeight: '100vh', display: 'flex', alignItems: 'center', justifyContent: 'center', fontFamily: 'system-ui,sans-serif', padding: '2rem' }}>\r\n <div style={{ maxWidth: 480, width: '100%', textAlign: 'center' }}>\r\n <h2 style={{ color: '#e74c3c', marginBottom: '1rem' }}>Something went wrong</h2>\r\n <pre style={{ background: '#fef2f2', padding: '1rem', borderRadius: '0.5rem', textAlign: 'left', fontSize: '0.8rem', color: '#e74c3c', overflow: 'auto' }}>{this.state.error.toString()}</pre>\r\n <button onClick={() => this.setState({ error: null })} style={{ marginTop: '1rem', padding: '0.5rem 1.5rem', background: '#00CFFF', color: 'white', border: 'none', borderRadius: '0.5rem', cursor: 'pointer', fontWeight: 600 }}>\r\n Try again\r\n </button>\r\n </div>\r\n </div>\r\n );\r\n return this.props.children;\r\n }\r\n}\r\n\r\nfunction Spinner() {\r\n return (\r\n <div style={{ minHeight: '100vh', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>\r\n <div style={{ width: 32, height: 32, border: '3px solid #eee', borderTop: '3px solid #00CFFF', borderRadius: '50%', animation: 'spin 0.8s linear infinite' }} />\r\n <style>{\\`@keyframes spin{to{transform:rotate(360deg)}}\\`}</style>\r\n </div>\r\n );\r\n}\r\n\r\nfunction TitleSetter({ title }: { title: string }) {\r\n React.useEffect(() => { document.title = title; }, [title]);\r\n return null;\r\n}\r\n\r\n${notFound ? '' : `function Default404() {\r\n return (\r\n <div style={{ minHeight: '100vh', display: 'flex', alignItems: 'center', justifyContent: 'center', background: 'linear-gradient(135deg,#00CFFF,#0077FF)', color: 'white', fontFamily: 'system-ui,sans-serif' }}>\r\n <div style={{ textAlign: 'center' }}>\r\n <h1 style={{ fontSize: '5rem', fontWeight: 800, margin: 0 }}>404</h1>\r\n <p style={{ fontSize: '1.25rem', margin: '0.5rem 0 2rem' }}>Page not found</p>\r\n <a href=\"/\" style={{ padding: '0.65rem 1.5rem', background: 'white', color: '#00CFFF', textDecoration: 'none', borderRadius: '0.5rem', fontWeight: 600 }}>← Back to Home</a>\r\n </div>\r\n </div>\r\n );\r\n}`}\r\n\r\nexport default function App() {\r\n return (\r\n <BrowserRouter>\r\n <Routes>\r\n${routeLines.join('\\n')}\r\n${catchAll}\r\n </Routes>\r\n </BrowserRouter>\r\n );\r\n}\r\n`;\r\n}\r\n\r\n// ─── Metadata Parser ──────────────────────────────────────────────────────────\r\n\r\nfunction parseAppMetadata(appDir: string): MetaTags {\r\n const layout = findFile(appDir, LAYOUT_FILES);\r\n if (!layout) return {};\r\n let src = '';\r\n try { src = fs.readFileSync(path.join(appDir, layout), 'utf8'); }\r\n catch { return {}; }\r\n\r\n const startIdx = src.indexOf('export const metadata');\r\n if (startIdx === -1) return {};\r\n const braceStart = src.indexOf('{', startIdx);\r\n if (braceStart === -1) return {};\r\n\r\n let depth = 0, end = braceStart;\r\n for (let i = braceStart; i < src.length; i++) {\r\n if (src[i] === '{') depth++;\r\n else if (src[i] === '}') { depth--; if (depth === 0) { end = i; break; } }\r\n }\r\n const block = src.slice(braceStart, end + 1);\r\n\r\n function extractBlock(source: string, key: string): string | undefined {\r\n const re = new RegExp(`['\"]?${key}['\"]?\\\\s*:\\\\s*\\\\{`);\r\n const match = re.exec(source);\r\n if (!match) return undefined;\r\n let d = 0, i = match.index + match[0].length - 1;\r\n const start = i;\r\n for (; i < source.length; i++) {\r\n if (source[i] === '{') d++;\r\n else if (source[i] === '}') { d--; if (d === 0) return source.slice(start, i + 1); }\r\n }\r\n return undefined;\r\n }\r\n\r\n function extractArray(source: string, key: string): string | undefined {\r\n const re = new RegExp(`['\"]?${key}['\"]?\\\\s*:\\\\s*\\\\[`);\r\n const match = re.exec(source);\r\n if (!match) return undefined;\r\n let d = 0, i = match.index + match[0].length - 1;\r\n const start = i;\r\n for (; i < source.length; i++) {\r\n if (source[i] === '[') d++;\r\n else if (source[i] === ']') { d--; if (d === 0) return source.slice(start, i + 1); }\r\n }\r\n return undefined;\r\n }\r\n\r\n function str(source: string, key: string): string | undefined {\r\n return source.match(\r\n new RegExp(`['\"]?${key}['\"]?\\\\s*:\\\\s*['\"\\`]([^'\"\\`\\n]+)['\"\\`]`)\r\n )?.[1];\r\n }\r\n\r\n function firstArrayStr(source: string, key: string): string | undefined {\r\n const arr = extractArray(source, key);\r\n if (!arr) return undefined;\r\n return arr.match(/url\\s*:\\s*['\"]([^'\"]+)['\"]/)?.[1]\r\n ?? arr.match(/['\"]([^'\"]+)['\"]/)?.[1];\r\n }\r\n\r\n function allArrayStrs(source: string, key: string): string[] {\r\n const arr = extractArray(source, key);\r\n if (!arr) return [];\r\n return [...arr.matchAll(/['\"]([^'\"]+)['\"]/g)].map(m => m[1]);\r\n }\r\n\r\n const meta: MetaTags = {};\r\n\r\n if (str(block, 'title')) meta.title = str(block, 'title');\r\n if (str(block, 'description')) meta.description = str(block, 'description');\r\n if (str(block, 'viewport')) meta.viewport = str(block, 'viewport');\r\n if (str(block, 'themeColor')) meta.themeColor = str(block, 'themeColor');\r\n if (str(block, 'charset')) meta.charset = str(block, 'charset');\r\n if (str(block, 'robots')) meta.robots = str(block, 'robots');\r\n if (str(block, 'canonical')) meta.canonical = str(block, 'canonical');\r\n if (str(block, 'manifest')) meta.manifest = str(block, 'manifest');\r\n\r\n const kwStr = str(block, 'keywords');\r\n if (kwStr) {\r\n meta.keywords = kwStr;\r\n } else {\r\n const kwArr = allArrayStrs(block, 'keywords');\r\n if (kwArr.length) meta.keywords = kwArr.join(', ');\r\n }\r\n\r\n const authorStr = str(block, 'author');\r\n if (authorStr) {\r\n meta.author = authorStr;\r\n } else {\r\n const authorsArr = extractArray(block, 'authors');\r\n if (authorsArr) {\r\n const name = authorsArr.match(/name\\s*:\\s*['\"]([^'\"]+)['\"]/)?.[1];\r\n if (name) meta.author = name;\r\n }\r\n }\r\n\r\n if (!meta.canonical) {\r\n const base = block.match(/metadataBase\\s*:\\s*new\\s+URL\\s*\\(\\s*['\"]([^'\"]+)['\"]/)?.[1];\r\n if (base) meta.canonical = base;\r\n }\r\n\r\n const ogBlock = extractBlock(block, 'openGraph');\r\n if (ogBlock) {\r\n meta.openGraph = {\r\n title : str(ogBlock, 'title'),\r\n description : str(ogBlock, 'description'),\r\n url : str(ogBlock, 'url'),\r\n type : str(ogBlock, 'type'),\r\n image : firstArrayStr(ogBlock, 'images') ?? str(ogBlock, 'image'),\r\n };\r\n }\r\n\r\n const twBlock = extractBlock(block, 'twitter');\r\n if (twBlock) {\r\n meta.twitter = {\r\n card : str(twBlock, 'card'),\r\n title : str(twBlock, 'title'),\r\n description : str(twBlock, 'description'),\r\n creator : str(twBlock, 'creator'),\r\n image : firstArrayStr(twBlock, 'images') ?? str(twBlock, 'image'),\r\n };\r\n }\r\n\r\n const iconsBlock = extractBlock(block, 'icons');\r\n if (iconsBlock) {\r\n meta.icons = {\r\n icon : collectIconEntries(iconsBlock, 'icon'),\r\n shortcut: collectIconEntries(iconsBlock, 'shortcut'),\r\n apple : collectIconEntries(iconsBlock, 'apple'),\r\n };\r\n }\r\n\r\n return meta;\r\n}\r\n\r\nfunction collectIconEntries(source: string, key: string): IconEntry[] {\r\n const arr = extractArrayRaw(source, key);\r\n if (!arr) return [];\r\n const entries: IconEntry[] = [];\r\n const objRe = /\\{([^}]+)\\}/g;\r\n let m: RegExpExecArray | null;\r\n while ((m = objRe.exec(arr)) !== null) {\r\n const obj = m[1];\r\n const url = obj.match(/url\\s*:\\s*['\"]([^'\"]+)['\"]/)?.[1];\r\n if (!url) continue;\r\n entries.push({\r\n url,\r\n type : obj.match(/type\\s*:\\s*['\"]([^'\"]+)['\"]/)?.[1],\r\n sizes: obj.match(/sizes\\s*:\\s*['\"]([^'\"]+)['\"]/)?.[1],\r\n });\r\n }\r\n if (!entries.length) {\r\n return [...arr.matchAll(/['\"]([^'\"]+)['\"]/g)].map(x => ({ url: x[1] }));\r\n }\r\n return entries;\r\n}\r\n\r\nfunction extractArrayRaw(source: string, key: string): string | undefined {\r\n const re = new RegExp(`['\"]?${key}['\"]?\\\\s*:\\\\s*\\\\[`);\r\n const match = re.exec(source);\r\n if (!match) return undefined;\r\n let d = 0, i = match.index + match[0].length - 1;\r\n const start = i;\r\n for (; i < source.length; i++) {\r\n if (source[i] === '[') d++;\r\n else if (source[i] === ']') { d--; if (d === 0) return source.slice(start, i + 1); }\r\n }\r\n return undefined;\r\n}\r\n\r\n// ─── API Route Scanner ────────────────────────────────────────────────────────\r\n\r\nfunction scanApiRoutes(dir: string, baseRoute = ''): ApiRoute[] {\r\n const routes: ApiRoute[] = [];\r\n if (!fs.existsSync(dir)) return routes;\r\n\r\n let entries: fs.Dirent[];\r\n try { entries = fs.readdirSync(dir, { withFileTypes: true }); }\r\n catch { return routes; }\r\n\r\n for (const entry of entries) {\r\n if (entry.name.startsWith('_') || entry.name.startsWith('.')) continue;\r\n const fullPath = path.join(dir, entry.name);\r\n\r\n if (entry.isDirectory()) {\r\n const isCatchAll = entry.name.startsWith('[...') && entry.name.endsWith(']');\r\n const isDynamic = entry.name.startsWith('[') && entry.name.endsWith(']');\r\n const segment = isCatchAll ? '*' : isDynamic ? `:${entry.name.slice(1, -1)}` : entry.name;\r\n routes.push(...scanApiRoutes(fullPath, `${baseRoute}/${segment}`));\r\n continue;\r\n }\r\n\r\n const ext = path.extname(entry.name);\r\n const base = path.basename(entry.name, ext);\r\n if (!(API_EXTS as readonly string[]).includes(ext)) continue;\r\n\r\n const isCatchAll = base.startsWith('[...') && base.endsWith(']');\r\n const isDynamic = base.startsWith('[') && base.endsWith(']');\r\n const routePath = isCatchAll\r\n ? `${baseRoute}/*`\r\n : base === 'index'\r\n ? baseRoute || '/'\r\n : isDynamic\r\n ? `${baseRoute}/:${base.slice(1, -1)}`\r\n : `${baseRoute}/${base}`;\r\n\r\n routes.push({ routePath, filePath: fullPath });\r\n }\r\n\r\n return routes;\r\n}\r\n\r\n// ─── Hono dev/preview server ──────────────────────────────────────────────────\r\n\r\nfunction matchRoute(pattern: string, pathname: string): Record<string, string> | null {\r\n const patParts = pattern.split('/').filter(Boolean);\r\n const urlParts = pathname.split('/').filter(Boolean);\r\n\r\n const isCatchAll = patParts[patParts.length - 1] === '*';\r\n if (isCatchAll) {\r\n const prefix = patParts.slice(0, -1);\r\n if (urlParts.length < prefix.length) return null;\r\n for (let i = 0; i < prefix.length; i++) {\r\n if (prefix[i].startsWith(':')) continue;\r\n if (prefix[i] !== urlParts[i]) return null;\r\n }\r\n return { '*': urlParts.slice(prefix.length).join('/') };\r\n }\r\n\r\n if (patParts.length !== urlParts.length) return null;\r\n\r\n const params: Record<string, string> = {};\r\n for (let i = 0; i < patParts.length; i++) {\r\n if (patParts[i].startsWith(':')) {\r\n params[patParts[i].slice(1)] = decodeURIComponent(urlParts[i]);\r\n } else if (patParts[i] !== urlParts[i]) {\r\n return null;\r\n }\r\n }\r\n return params;\r\n}\r\n\r\nconst moduleCache = new Map<string, { mtime: number; handler: unknown }>();\r\n\r\nasync function importHandler(filePath: string): Promise<unknown> {\r\n const { pathToFileURL } = await import('url');\r\n let mtime = 0;\r\n try { mtime = fs.statSync(filePath).mtimeMs; } catch { /* file vanished */ }\r\n\r\n const cached = moduleCache.get(filePath);\r\n if (cached && cached.mtime === mtime) return cached.handler;\r\n\r\n const mod = await import(pathToFileURL(filePath).href + '?t=' + mtime);\r\n const handler = mod.default ?? null;\r\n moduleCache.set(filePath, { mtime, handler });\r\n return handler;\r\n}\r\n\r\nasync function handleApiRequest(\r\n req : any,\r\n res : any,\r\n next : any,\r\n apiDir : string,\r\n enableCors : boolean,\r\n getCache : () => { routes: ApiRoute[] } | null,\r\n setCache : (v: { routes: ApiRoute[] }) => void,\r\n) {\r\n try {\r\n if (enableCors && req.method === 'OPTIONS') {\r\n res.statusCode = 204;\r\n res.setHeader('Access-Control-Allow-Origin', '*');\r\n res.setHeader('Access-Control-Allow-Methods', 'GET,POST,PUT,PATCH,DELETE,OPTIONS');\r\n res.setHeader('Access-Control-Allow-Headers', 'Content-Type,Authorization');\r\n res.setHeader('Access-Control-Max-Age', '86400');\r\n res.end();\r\n return;\r\n }\r\n\r\n let cache = getCache();\r\n if (!cache) {\r\n cache = { routes: scanApiRoutes(apiDir, '/api') };\r\n setCache(cache);\r\n }\r\n\r\n const host = req.headers.host ?? 'localhost';\r\n const url = `http://${host}${req.url}`;\r\n const pathname = new URL(url).pathname;\r\n\r\n const chunks: Buffer[] = [];\r\n for await (const chunk of req) chunks.push(chunk as Buffer);\r\n const body = chunks.length > 0 ? Buffer.concat(chunks) : undefined;\r\n\r\n const method = (req.method as string).toUpperCase();\r\n\r\n const webReq = new Request(url, {\r\n method,\r\n headers: req.headers as HeadersInit,\r\n body : !['GET', 'HEAD'].includes(method) && body?.length ? body : undefined,\r\n });\r\n\r\n for (const route of cache.routes) {\r\n const handler = await importHandler(route.filePath);\r\n if (!handler) continue;\r\n\r\n let webRes: Response;\r\n try {\r\n if (typeof (handler as any).fetch === 'function') {\r\n webRes = await (handler as any).fetch(webReq.clone());\r\n if (webRes.status === 404) continue;\r\n } else if (typeof handler === 'function') {\r\n const params = matchRoute(route.routePath, pathname);\r\n if (params === null) continue;\r\n\r\n const existingHeaders: Record<string, string> = {};\r\n webReq.headers.forEach((v, k) => { existingHeaders[k] = v; });\r\n const reqWithParams = new Request(webReq.clone(), {\r\n headers: { ...existingHeaders, 'x-bini-params': JSON.stringify(params) },\r\n });\r\n\r\n webRes = await (handler as (...args: any[]) => Promise<Response>)(reqWithParams);\r\n } else {\r\n continue;\r\n }\r\n } catch {\r\n continue;\r\n }\r\n\r\n const finalHeaders: Record<string, string> = {};\r\n webRes.headers.forEach((v, k) => { finalHeaders[k] = v; });\r\n if (enableCors) {\r\n finalHeaders['access-control-allow-origin'] = '*';\r\n finalHeaders['access-control-allow-methods'] = 'GET,POST,PUT,PATCH,DELETE,OPTIONS';\r\n finalHeaders['access-control-allow-headers'] = 'Content-Type,Authorization';\r\n }\r\n\r\n res.statusCode = webRes.status;\r\n for (const [k, v] of Object.entries(finalHeaders)) res.setHeader(k, v);\r\n res.end(Buffer.from(await webRes.arrayBuffer()));\r\n return;\r\n }\r\n\r\n res.statusCode = 404;\r\n res.setHeader('Content-Type', 'application/json');\r\n res.end(JSON.stringify({ error: `No API handler found for ${req.url}` }));\r\n } catch (e: any) {\r\n next(e);\r\n }\r\n}\r\n\r\n// ─── Production Entry Generator ───────────────────────────────────────────────\r\n\r\ntype Platform = 'netlify' | 'cloudflare' | 'node' | 'deno' | 'bun' | 'aws';\r\n\r\n// ─── Platform adapter config ─────────────────────────────────────────────────\r\n\r\ninterface AdapterConfig {\r\n pkg ?: string; // npm package to install (optional)\r\n importLine ?: string; // import statement for generated file\r\n exportLine : string; // export statement for generated file\r\n outFile : (cwd: string) => string;\r\n stripsApiPrefix: boolean; // platform strips /api before handler sees it\r\n}\r\n\r\n// All adapters use hono's built-in platform adapters — no extra packages needed\r\n// except @hono/node-server for Node.js (not built into hono core)\r\nconst ADAPTERS: Record<Platform, AdapterConfig> = {\r\n\r\n netlify: {\r\n // Netlify Edge Functions — Deno runtime, use deno.land URL imports (zero npm)\r\n // Entry file uses URL imports so Netlify bundles with no npm module errors.\r\n // User route files import `from 'hono'` (npm) but Netlify resolves them fine\r\n // since the entry provides Hono via URL import at bundle time.\r\n importLine : `import { Hono } from 'https://deno.land/x/hono@v4.3.11/mod.ts';\\nimport { handle } from 'https://deno.land/x/hono@v4.3.11/adapter/netlify/index.ts';`,\r\n exportLine : `export default handle(app);`,\r\n outFile : (cwd) => path.join(cwd, 'netlify', 'edge-functions', 'api.ts'),\r\n stripsApiPrefix: false,\r\n },\r\n\r\n cloudflare: {\r\n exportLine : `export default app;`,\r\n outFile : (cwd) => path.join(cwd, 'worker.ts'),\r\n stripsApiPrefix: false,\r\n },\r\n node: {\r\n pkg : '@hono/node-server',\r\n importLine : `import { serve } from '@hono/node-server';\r\nimport { serveStatic } from '@hono/node-server/serve-static';`,\r\n exportLine : `app.use('/*', serveStatic({ root: './dist' }));\r\napp.use('/*', serveStatic({ path: './dist/index.html' }));\r\n\r\nserve({ fetch: app.fetch, port: Number(process.env.PORT ?? 3000) }, (i) => {\r\n console.log(\\`Server running on http://localhost:\\${i.port}\\`);\r\n});`,\r\n outFile : (cwd) => path.join(cwd, 'server', 'index.ts'),\r\n stripsApiPrefix: false,\r\n },\r\n deno: {\r\n importLine : `import { serve } from 'hono/deno';`,\r\n exportLine : `serve(app.fetch);`,\r\n outFile : (cwd) => path.join(cwd, 'server', 'index.ts'),\r\n stripsApiPrefix: false,\r\n },\r\n bun: {\r\n exportLine : `export default app;`,\r\n outFile : (cwd) => path.join(cwd, 'server', 'index.ts'),\r\n stripsApiPrefix: false,\r\n },\r\n aws: {\r\n // Requires separate install: npm install @hono/aws-lambda\r\n pkg : '@hono/aws-lambda',\r\n importLine : `import { handle } from '@hono/aws-lambda';`,\r\n exportLine : `export const handler = handle(app);`,\r\n outFile : (cwd) => path.join(cwd, 'handler.ts'),\r\n stripsApiPrefix: false,\r\n },\r\n};\r\n\r\nfunction checkAdapter(platform: Platform): void {\r\n const adapter = ADAPTERS[platform];\r\n if (!adapter.pkg) return;\r\n try {\r\n require.resolve(adapter.pkg, { paths: [process.cwd()] });\r\n } catch {\r\n console.error(`\r\n[bini-router] ✗ Missing required package for platform '${platform}'.\r\n Run: npm install ${adapter.pkg}\r\n`);\r\n process.exit(1);\r\n }\r\n}\r\n\r\nfunction buildRouteImports(\r\n routes : ApiRoute[],\r\n outFile : string,\r\n enableCors: boolean,\r\n platform : Platform,\r\n): { imports: string[]; mountings: string[]; corsLine: string | null; corsImport: string | null } {\r\n const imports : string[] = [];\r\n const mountings : string[] = [];\r\n const adapter = ADAPTERS[platform];\r\n const stripPrefix = adapter.stripsApiPrefix;\r\n\r\n for (let i = 0; i < routes.length; i++) {\r\n const route = routes[i];\r\n const rel = norm(path.relative(path.dirname(outFile), route.filePath)).replace(/\\.(ts|tsx)$/, '');\r\n const imp = rel.startsWith('.') ? rel : `./${rel}`;\r\n const name = `_route${i}`;\r\n\r\n let src = '';\r\n try { src = fs.readFileSync(route.filePath, 'utf8'); } catch { /* skip */ }\r\n const isHonoApp = src.includes(\"from 'hono'\") || src.includes('from \"hono\"');\r\n\r\n imports.push(`import ${name} from '${imp}';`);\r\n\r\n if (isHonoApp) {\r\n mountings.push(`app.route('/', ${name});`);\r\n } else {\r\n // Some platforms strip /api prefix before the handler sees the request\r\n const mountPath = stripPrefix ? route.routePath : `/api${route.routePath}`;\r\n mountings.push(`app.all('${mountPath}', async (c) => { const r = await ${name}(c.req.raw); return r instanceof Response ? r : c.json(r); });`);\r\n }\r\n\r\n }\r\n\r\n const corsPattern = stripPrefix ? '/*' : '/api/*';\r\n const isNetlifyPlatform = platform === 'netlify';\r\n // Netlify edge functions: use inline CORS middleware to avoid npm import errors\r\n const corsLine = enableCors\r\n ? isNetlifyPlatform\r\n ? `app.use('${corsPattern}', async (c, next) => { await next(); c.res.headers.set('Access-Control-Allow-Origin', '*'); c.res.headers.set('Access-Control-Allow-Methods', 'GET,POST,PUT,PATCH,DELETE,OPTIONS'); c.res.headers.set('Access-Control-Allow-Headers', 'Content-Type,Authorization'); if (c.req.method === 'OPTIONS') return new Response(null, { status: 204, headers: c.res.headers }); });`\r\n : `app.use('${corsPattern}', cors({ origin: '*', allowMethods: ['GET','POST','PUT','PATCH','DELETE','OPTIONS'], allowHeaders: ['Content-Type','Authorization'] }));`\r\n : null;\r\n const corsImport = enableCors ? `import { cors } from 'hono/cors';` : null;\r\n\r\n return { imports, mountings, corsLine, corsImport };\r\n}\r\n\r\nfunction buildProductionEntry(srcApiDir: string, platform: Platform, enableCors: boolean): void {\r\n if (!fs.existsSync(srcApiDir)) return;\r\n\r\n const routes = scanApiRoutes(srcApiDir);\r\n const cwd = process.cwd();\r\n\r\n const header = [\r\n `// ⚠️ Auto-generated by bini-router on every build — do not edit.`,\r\n `// Add routes by creating files in src/app/api/ only.`,\r\n ];\r\n\r\n // ── All platforms: use adapter config to generate entry file ────────────────\r\n checkAdapter(platform);\r\n\r\n const adapter = ADAPTERS[platform];\r\n const outFile = adapter.outFile(cwd);\r\n\r\n const { imports, mountings, corsLine, corsImport } = buildRouteImports(routes, outFile, enableCors, platform);\r\n\r\n // Netlify edge functions use deno.land URL imports — Hono is already in importLine\r\n const isNetlify = platform === 'netlify';\r\n const lines = [\r\n ...header,\r\n ...(isNetlify ? [] : [`import { Hono } from 'hono';`]),\r\n ...(adapter.importLine ? adapter.importLine.split('\\n') : []),\r\n ...(corsImport && !isNetlify ? [corsImport] : []),\r\n ...imports,\r\n ``,\r\n `const app = new Hono();`,\r\n ...(corsLine ? [corsLine] : []),\r\n ...mountings,\r\n ``,\r\n ...adapter.exportLine.split('\\n'),\r\n ];\r\n\r\n fs.mkdirSync(path.dirname(outFile), { recursive: true });\r\n fs.writeFileSync(outFile, lines.join('\\n') + '\\n', 'utf8');\r\n console.log(`[bini-router] ✓ Generated ${norm(path.relative(cwd, outFile))}`);\r\n}\r\n\r\n// ─── Plugin ───────────────────────────────────────────────────────────────────\r\n\r\nexport function biniroute(options: BiniPluginOptions = {}): Plugin {\r\n const { cors: enableCors = true, platform } = options;\r\n\r\n const getAppDir = () => path.join(process.cwd(), options.appDir ?? 'src/app');\r\n const getApiDir = () => path.join(process.cwd(), options.apiDir ?? 'src/app/api');\r\n\r\n let debounceTimer : ReturnType<typeof setTimeout> | null = null;\r\n let lastGeneratedCode = '';\r\n let honoCache : { routes: ApiRoute[] } | null = null;\r\n const eventLog = new Map<string, number>();\r\n\r\n function shouldProcess(file: string, event: string): boolean {\r\n const key = `${file}:${event}`;\r\n const now = Date.now();\r\n if (now - (eventLog.get(key) ?? 0) < EVENT_DEDUP_MS) return false;\r\n eventLog.set(key, now);\r\n for (const [k, v] of eventLog) if (now - v > EVENT_TTL_MS) eventLog.delete(k);\r\n return true;\r\n }\r\n\r\n function isPageFile(f: string): boolean {\r\n const nf = norm(f);\r\n const base = path.basename(f, path.extname(f));\r\n const ext = path.extname(f);\r\n if (!(SUPPORTED_EXTS as readonly string[]).includes(ext)) return false;\r\n if (!isInDir(nf, norm(getAppDir()))) return false;\r\n if (isInDir(nf, norm(getApiDir()))) return false;\r\n if (base.startsWith('_')) return false;\r\n return true;\r\n }\r\n\r\n function isApiFile(f: string): boolean {\r\n const nf = norm(f);\r\n return isInDir(nf, norm(getApiDir())) &&\r\n (API_EXTS as readonly string[]).includes(path.extname(f));\r\n }\r\n\r\n function applyApp(): string | null {\r\n const dir = getAppDir();\r\n if (!fs.existsSync(dir)) return null;\r\n const code = generateApp(dir);\r\n if (code === lastGeneratedCode) return null;\r\n fs.writeFileSync(getAppFile(), code, 'utf8');\r\n lastGeneratedCode = code;\r\n return code;\r\n }\r\n\r\n function scheduleRegen(server: ViteDevServer, delay = DEBOUNCE_MS) {\r\n if (debounceTimer) clearTimeout(debounceTimer);\r\n debounceTimer = setTimeout(() => {\r\n debounceTimer = null;\r\n if (applyApp() !== null) {\r\n server.ws.send({ type: 'full-reload', path: '*' });\r\n }\r\n }, delay);\r\n }\r\n\r\n function addSpaFallback(server: { middlewares: any }) {\r\n server.middlewares.use((req: any, res: any, next: any) => {\r\n const url = req.url as string;\r\n if (url.startsWith('/api') || url.includes('.')) return next();\r\n req.url = '/index.html';\r\n next();\r\n });\r\n }\r\n\r\n return {\r\n name : 'bini-router',\r\n enforce: 'pre',\r\n\r\n transform(code, id) {\r\n const nid = norm(id);\r\n if (!isInDir(nid, norm(getAppDir()))) return;\r\n const ext = path.extname(id);\r\n if (!(SUPPORTED_EXTS as readonly string[]).includes(ext)) return;\r\n if (!code.includes('export const metadata')) return;\r\n\r\n let result = code;\r\n let idx = result.indexOf('export const metadata');\r\n\r\n while (idx !== -1) {\r\n const braceIdx = result.indexOf('{', idx);\r\n if (braceIdx === -1) break;\r\n\r\n let depth = 0, end = braceIdx;\r\n for (let i = braceIdx; i < result.length; i++) {\r\n if (result[i] === '{') depth++;\r\n else if (result[i] === '}') { depth--; if (depth === 0) { end = i; break; } }\r\n }\r\n\r\n let tail = end + 1;\r\n while (tail < result.length && (result[tail] === ' ' || result[tail] === '\\t')) tail++;\r\n if (tail < result.length && result[tail] === ';') tail++;\r\n while (tail < result.length && (result[tail] === '\\n' || result[tail] === '\\r')) tail++;\r\n\r\n result = result.slice(0, idx) + result.slice(tail);\r\n idx = result.indexOf('export const metadata', idx);\r\n }\r\n\r\n return { code: result, map: null };\r\n },\r\n\r\n config() { applyApp(); },\r\n buildStart() { applyApp(); },\r\n\r\n closeBundle() {\r\n if (platform) buildProductionEntry(getApiDir(), platform, enableCors);\r\n },\r\n\r\n buildEnd() {\r\n honoCache = null;\r\n moduleCache.clear();\r\n if (debounceTimer) { clearTimeout(debounceTimer); debounceTimer = null; }\r\n },\r\n\r\n async configureServer(server) {\r\n const appDir = getAppDir();\r\n const apiDir = getApiDir();\r\n\r\n if (!fs.existsSync(appDir)) return;\r\n\r\n server.watcher.add(appDir);\r\n\r\n server.watcher.on('add', f => isPageFile(f) && shouldProcess(f, 'add') && scheduleRegen(server, 300));\r\n server.watcher.on('unlink', f => isPageFile(f) && shouldProcess(f, 'unlink') && scheduleRegen(server));\r\n server.watcher.on('change', f => isPageFile(f) && shouldProcess(f, 'change') && scheduleRegen(server));\r\n\r\n server.watcher.on('change', f => {\r\n const base = path.basename(f, path.extname(f));\r\n const inAppRoot = path.resolve(path.dirname(f)) === path.resolve(appDir);\r\n if (!inAppRoot || base !== 'layout') return;\r\n server.moduleGraph.invalidateAll();\r\n server.ws.send({ type: 'full-reload', path: '*' });\r\n });\r\n\r\n server.watcher.on('addDir', d => {\r\n const nd = norm(d);\r\n if (!isInDir(nd, norm(appDir)) || d.includes('node_modules') || isInDir(nd, norm(apiDir))) return;\r\n setTimeout(() => PAGE_FILES.some(f => fs.existsSync(path.join(d, f))) && scheduleRegen(server), 300);\r\n });\r\n\r\n server.watcher.on('unlinkDir', d => {\r\n const nd = norm(d);\r\n if (isInDir(nd, norm(appDir)) && !d.includes('node_modules') && !isInDir(nd, norm(apiDir)))\r\n scheduleRegen(server);\r\n });\r\n\r\n if (fs.existsSync(apiDir)) {\r\n server.watcher.add(apiDir);\r\n\r\n const resetApi = (f?: string) => {\r\n honoCache = null;\r\n if (f) moduleCache.delete(f);\r\n server.ws.send({ type: 'full-reload', path: '*' });\r\n };\r\n\r\n server.watcher.on('add', f => isApiFile(f) && resetApi(f));\r\n server.watcher.on('unlink', f => isApiFile(f) && resetApi(f));\r\n server.watcher.on('change', f => isApiFile(f) && resetApi(f));\r\n\r\n server.middlewares.use((req: any, res: any, next: any) => {\r\n if (!req.url?.startsWith('/api')) return next();\r\n handleApiRequest(req, res, next, apiDir, enableCors,\r\n () => honoCache, (v) => { honoCache = v; });\r\n });\r\n }\r\n },\r\n\r\n async configurePreviewServer(server) {\r\n addSpaFallback(server);\r\n\r\n const apiDir = getApiDir();\r\n if (!fs.existsSync(apiDir)) return;\r\n server.middlewares.use((req: any, res: any, next: any) => {\r\n if (!req.url?.startsWith('/api')) return next();\r\n handleApiRequest(req, res, next, apiDir, enableCors,\r\n () => honoCache, (v) => { honoCache = v; });\r\n });\r\n },\r\n\r\n transformIndexHtml: {\r\n order: 'pre',\r\n handler(html) {\r\n const meta = parseAppMetadata(getAppDir());\r\n\r\n if (!meta.title && !meta.description && !meta.canonical && !meta.manifest &&\r\n !meta.openGraph?.title && !meta.icons?.icon?.length) {\r\n return html;\r\n }\r\n\r\n const title = meta.title ?? 'Bini App';\r\n const vp = meta.viewport ?? 'width=device-width, initial-scale=1.0';\r\n\r\n const lines: string[] = [];\r\n\r\n lines.push(`<meta charset=\"${meta.charset ?? 'UTF-8'}\" />`);\r\n lines.push(`<meta name=\"viewport\" content=\"${vp}\" />`);\r\n lines.push(`<title>${title}</title>`);\r\n if (meta.description) lines.push(`<meta name=\"description\" content=\"${meta.description}\" />`);\r\n if (meta.themeColor) lines.push(`<meta name=\"theme-color\" content=\"${meta.themeColor}\" />`);\r\n if (meta.robots) lines.push(`<meta name=\"robots\" content=\"${meta.robots}\" />`);\r\n if (meta.keywords) lines.push(`<meta name=\"keywords\" content=\"${meta.keywords}\" />`);\r\n if (meta.author) lines.push(`<meta name=\"author\" content=\"${meta.author}\" />`);\r\n if (meta.canonical) lines.push(`<link rel=\"canonical\" href=\"${meta.canonical}\" />`);\r\n if (meta.manifest) lines.push(`<link rel=\"manifest\" href=\"${meta.manifest}\" />`);\r\n\r\n for (const entry of meta.icons?.icon ?? []) {\r\n const type = entry.type ? ` type=\"${entry.type}\"` : '';\r\n const sizes = entry.sizes ? ` sizes=\"${entry.sizes}\"` : '';\r\n lines.push(`<link rel=\"icon\" href=\"${entry.url}\"${type}${sizes} />`);\r\n }\r\n for (const entry of meta.icons?.shortcut ?? []) {\r\n lines.push(`<link rel=\"shortcut icon\" href=\"${entry.url}\" />`);\r\n }\r\n for (const entry of meta.icons?.apple ?? []) {\r\n const sizes = entry.sizes ? ` sizes=\"${entry.sizes}\"` : '';\r\n const type = entry.type ? ` type=\"${entry.type}\"` : '';\r\n lines.push(`<link rel=\"apple-touch-icon\" href=\"${entry.url}\"${sizes}${type} />`);\r\n }\r\n\r\n if (meta.openGraph?.title) {\r\n lines.push(`<meta property=\"og:type\" content=\"${meta.openGraph.type ?? 'website'}\" />`);\r\n lines.push(`<meta property=\"og:title\" content=\"${meta.openGraph.title}\" />`);\r\n if (meta.openGraph.description) lines.push(`<meta property=\"og:description\" content=\"${meta.openGraph.description}\" />`);\r\n if (meta.openGraph.url) lines.push(`<meta property=\"og:url\" content=\"${meta.openGraph.url}\" />`);\r\n if (meta.openGraph.image) lines.push(`<meta property=\"og:image\" content=\"${meta.openGraph.image}\" />`);\r\n }\r\n\r\n if (meta.twitter?.title) {\r\n lines.push(`<meta name=\"twitter:card\" content=\"${meta.twitter.card ?? 'summary_large_image'}\" />`);\r\n lines.push(`<meta name=\"twitter:title\" content=\"${meta.twitter.title}\" />`);\r\n if (meta.twitter.description) lines.push(`<meta name=\"twitter:description\" content=\"${meta.twitter.description}\" />`);\r\n if (meta.twitter.creator) lines.push(`<meta name=\"twitter:creator\" content=\"${meta.twitter.creator}\" />`);\r\n if (meta.twitter.image) lines.push(`<meta name=\"twitter:image\" content=\"${meta.twitter.image}\" />`);\r\n }\r\n\r\n const injected = lines.map(l => ` ${l}`).join('\\n');\r\n return html.replace('</head>', `${injected}\\n </head>`);\r\n },\r\n },\r\n };\r\n}\r\n\r\nexport default biniroute;"],"mappings":"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","names":["path","fs","isCatchAll","isDynamic"]}
package/dist/index.d.cts CHANGED
@@ -49,8 +49,7 @@ interface BiniPluginOptions {
49
49
  * Target deployment platform. bini-router generates a production entry
50
50
  * file on every build — users only write code in src/app/api/.
51
51
  *
52
- * 'vercel' .vercel/output/ (Vercel Build Output API — always fresh)
53
- * 'netlify' → netlify/functions/api.ts (no extra install needed)
52
+ * 'netlify' netlify/edge-functions/api.ts (default, zero config)
54
53
  * 'cloudflare' → worker.ts (install: wrangler)
55
54
  * 'node' → server/index.ts (install: @hono/node-server)
56
55
  * 'deno' → server/index.ts (run with: deno run)
package/dist/index.d.ts CHANGED
@@ -49,8 +49,7 @@ interface BiniPluginOptions {
49
49
  * Target deployment platform. bini-router generates a production entry
50
50
  * file on every build — users only write code in src/app/api/.
51
51
  *
52
- * 'vercel' .vercel/output/ (Vercel Build Output API — always fresh)
53
- * 'netlify' → netlify/functions/api.ts (no extra install needed)
52
+ * 'netlify' netlify/edge-functions/api.ts (default, zero config)
54
53
  * 'cloudflare' → worker.ts (install: wrangler)
55
54
  * 'node' → server/index.ts (install: @hono/node-server)
56
55
  * 'deno' → server/index.ts (run with: deno run)
package/dist/index.js CHANGED
@@ -629,8 +629,12 @@ async function handleApiRequest(req, res, next, apiDir, enableCors, getCache, se
629
629
  }
630
630
  var ADAPTERS = {
631
631
  netlify: {
632
- // Netlify Edge Functions — uses hono/netlify adapter built into hono core
633
- importLine: `import { handle } from 'hono/netlify';`,
632
+ // Netlify Edge Functions — Deno runtime, use deno.land URL imports (zero npm)
633
+ // Entry file uses URL imports so Netlify bundles with no npm module errors.
634
+ // User route files import `from 'hono'` (npm) but Netlify resolves them fine
635
+ // since the entry provides Hono via URL import at bundle time.
636
+ importLine: `import { Hono } from 'https://deno.land/x/hono@v4.3.11/mod.ts';
637
+ import { handle } from 'https://deno.land/x/hono@v4.3.11/adapter/netlify/index.ts';`,
634
638
  exportLine: `export default handle(app);`,
635
639
  outFile: (cwd) => path.join(cwd, "netlify", "edge-functions", "api.ts"),
636
640
  stripsApiPrefix: false
@@ -711,7 +715,8 @@ function buildRouteImports(routes, outFile, enableCors, platform) {
711
715
  }
712
716
  }
713
717
  const corsPattern = stripPrefix ? "/*" : "/api/*";
714
- const corsLine = enableCors ? `app.use('${corsPattern}', cors({ origin: '*', allowMethods: ['GET','POST','PUT','PATCH','DELETE','OPTIONS'], allowHeaders: ['Content-Type','Authorization'] }));` : null;
718
+ const isNetlifyPlatform = platform === "netlify";
719
+ const corsLine = enableCors ? isNetlifyPlatform ? `app.use('${corsPattern}', async (c, next) => { await next(); c.res.headers.set('Access-Control-Allow-Origin', '*'); c.res.headers.set('Access-Control-Allow-Methods', 'GET,POST,PUT,PATCH,DELETE,OPTIONS'); c.res.headers.set('Access-Control-Allow-Headers', 'Content-Type,Authorization'); if (c.req.method === 'OPTIONS') return new Response(null, { status: 204, headers: c.res.headers }); });` : `app.use('${corsPattern}', cors({ origin: '*', allowMethods: ['GET','POST','PUT','PATCH','DELETE','OPTIONS'], allowHeaders: ['Content-Type','Authorization'] }));` : null;
715
720
  const corsImport = enableCors ? `import { cors } from 'hono/cors';` : null;
716
721
  return { imports, mountings, corsLine, corsImport };
717
722
  }
@@ -727,11 +732,12 @@ function buildProductionEntry(srcApiDir, platform, enableCors) {
727
732
  const adapter = ADAPTERS[platform];
728
733
  const outFile = adapter.outFile(cwd);
729
734
  const { imports, mountings, corsLine, corsImport } = buildRouteImports(routes, outFile, enableCors, platform);
735
+ const isNetlify = platform === "netlify";
730
736
  const lines = [
731
737
  ...header,
732
- `import { Hono } from 'hono';`,
738
+ ...isNetlify ? [] : [`import { Hono } from 'hono';`],
733
739
  ...adapter.importLine ? adapter.importLine.split("\n") : [],
734
- ...corsImport ? [corsImport] : [],
740
+ ...corsImport && !isNetlify ? [corsImport] : [],
735
741
  ...imports,
736
742
  ``,
737
743
  `const app = new Hono();`,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["import fs from 'fs';\r\nimport path from 'path';\r\nimport type { Plugin, ViteDevServer } from 'vite';\r\n\r\n// ─── Constants ────────────────────────────────────────────────────────────────\r\n\r\nconst PAGE_FILES = ['page.tsx', 'page.jsx', 'page.ts', 'page.js'] as const;\r\nconst LAYOUT_FILES = ['layout.tsx', 'layout.jsx', 'layout.ts', 'layout.js'] as const;\r\nconst SUPPORTED_EXTS = ['.tsx', '.jsx', '.ts', '.js'] as const;\r\nconst NOT_FOUND_FILES = SUPPORTED_EXTS.map(e => `not-found${e}`);\r\nconst SPECIAL_BASES = new Set(['page', 'layout', 'not-found', 'loading', 'error']);\r\nconst API_EXTS = ['.ts', '.js'] as const;\r\nconst DEBOUNCE_MS = 60;\r\nconst EVENT_DEDUP_MS = 500;\r\nconst EVENT_TTL_MS = 2000;\r\n\r\n// ─── Metadata Types ───────────────────────────────────────────────────────────\r\n\r\nexport interface IconEntry {\r\n url : string;\r\n type ?: string;\r\n sizes?: string;\r\n}\r\n\r\nexport interface MetaTags {\r\n title ?: string;\r\n description ?: string;\r\n viewport ?: string;\r\n themeColor ?: string;\r\n keywords ?: string;\r\n author ?: string;\r\n charset ?: string;\r\n robots ?: string;\r\n canonical ?: string;\r\n manifest ?: string;\r\n openGraph ?: Partial<OGMeta>;\r\n twitter ?: Partial<TwitterMeta>;\r\n icons ?: {\r\n icon ?: IconEntry[];\r\n shortcut ?: IconEntry[];\r\n apple ?: IconEntry[];\r\n };\r\n}\r\n\r\ninterface OGMeta {\r\n title : string;\r\n description : string;\r\n url : string;\r\n image : string;\r\n type : string;\r\n}\r\n\r\ninterface TwitterMeta {\r\n card : string;\r\n title : string;\r\n description : string;\r\n creator : string;\r\n image : string;\r\n}\r\n\r\n// ─── Types ────────────────────────────────────────────────────────────────────\r\n\r\ninterface RouteNode {\r\n routePath : string;\r\n filePath : string;\r\n layouts : string[];\r\n dynamic : boolean;\r\n}\r\n\r\ninterface LayoutChainGroup {\r\n layouts : string[];\r\n routes : RouteNode[];\r\n}\r\n\r\ninterface ApiRoute {\r\n routePath : string;\r\n filePath : string;\r\n}\r\n\r\nexport interface BiniPluginOptions {\r\n /** Directory for page files. Default: src/app */\r\n appDir?: string;\r\n /** Directory for API routes. Default: src/app/api */\r\n apiDir?: string;\r\n /** Enable CORS headers in the dev-server API middleware. Default: true */\r\n cors?: boolean;\r\n /**\r\n * Target deployment platform. bini-router generates a production entry\r\n * file on every build — users only write code in src/app/api/.\r\n *\r\n * 'vercel' → .vercel/output/ (Vercel Build Output API — always fresh)\r\n * 'netlify' → netlify/functions/api.ts (no extra install needed)\r\n * 'cloudflare' → worker.ts (install: wrangler)\r\n * 'node' → server/index.ts (install: @hono/node-server)\r\n * 'deno' → server/index.ts (run with: deno run)\r\n * 'bun' → server/index.ts (run with: bun run)\r\n * 'aws' → handler.ts (install: @hono/aws-lambda)\r\n *\r\n * Default: undefined (no entry generated)\r\n */\r\n platform?: 'netlify' | 'cloudflare' | 'node' | 'deno' | 'bun' | 'aws';\r\n}\r\n\r\n// ─── Utilities ────────────────────────────────────────────────────────────────\r\n\r\nfunction norm(p: string): string {\r\n return p.replace(/\\\\/g, '/');\r\n}\r\n\r\nfunction isInDir(file: string, dir: string): boolean {\r\n const nFile = norm(file);\r\n const nDir = norm(dir).replace(/\\/$/, '');\r\n return nFile.startsWith(nDir + '/') || nFile === nDir;\r\n}\r\n\r\nfunction readTsconfigAliases(): Record<string, string> {\r\n const aliases: Record<string, string> = {};\r\n try {\r\n const tsconfigPath = path.join(process.cwd(), 'tsconfig.json');\r\n if (!fs.existsSync(tsconfigPath)) return aliases;\r\n const raw = fs.readFileSync(tsconfigPath, 'utf8')\r\n .replace(/\\/\\/.*$/gm, '')\r\n .replace(/\\/\\*[\\s\\S]*?\\*\\//g, '');\r\n const tsconfig = JSON.parse(raw);\r\n const paths = tsconfig?.compilerOptions?.paths ?? {};\r\n const baseUrl = tsconfig?.compilerOptions?.baseUrl ?? '.';\r\n for (const [alias, targets] of Object.entries(paths) as [string, string[]][]) {\r\n const cleanAlias = alias.replace(/\\/\\*$/, '');\r\n const cleanTarget = (targets[0] ?? '').replace(/\\/\\*$/, '');\r\n aliases[cleanAlias] = path.resolve(process.cwd(), baseUrl, cleanTarget);\r\n }\r\n } catch { /* tsconfig unreadable — fall back to relative paths */ }\r\n return aliases;\r\n}\r\n\r\nfunction toImportPath(filePath: string, aliases: Record<string, string>): string {\r\n for (const [alias, target] of Object.entries(aliases)) {\r\n if (norm(filePath).startsWith(norm(target) + '/')) {\r\n const rest = norm(filePath).slice(norm(target).length + 1).replace(/\\.(tsx|ts|jsx|js)$/, '');\r\n return `${alias}/${rest}`;\r\n }\r\n }\r\n return './' + norm(path.relative(path.join(process.cwd(), 'src'), filePath))\r\n .replace(/\\.(tsx|ts|jsx|js)$/, '');\r\n}\r\n\r\nfunction hasDefaultExport(filePath: string): boolean {\r\n try { return fs.readFileSync(filePath, 'utf8').includes('export default'); }\r\n catch { return false; }\r\n}\r\n\r\nfunction isHtmlShellLayout(filePath: string): boolean {\r\n try { return /<html[\\s>]/i.test(fs.readFileSync(filePath, 'utf8')); }\r\n catch { return false; }\r\n}\r\n\r\nfunction isUsableLayout(filePath: string): boolean {\r\n return hasDefaultExport(filePath) && !isHtmlShellLayout(filePath);\r\n}\r\n\r\nfunction findFile(dir: string, candidates: readonly string[]): string | null {\r\n return candidates.find(f => fs.existsSync(path.join(dir, f))) ?? null;\r\n}\r\n\r\nfunction getAppFile(): string {\r\n const ts = path.join(process.cwd(), 'src/App.tsx');\r\n return fs.existsSync(ts) ? ts : path.join(process.cwd(), 'src/App.jsx');\r\n}\r\n\r\n// ─── Layout Resolution ────────────────────────────────────────────────────────\r\n\r\nfunction resolveLayoutChain(pageDir: string, appDir: string): string[] {\r\n const chain: string[] = [];\r\n let current = pageDir;\r\n while (true) {\r\n const layout = findFile(current, LAYOUT_FILES);\r\n if (layout) chain.unshift(path.join(current, layout));\r\n if (path.resolve(current) === path.resolve(appDir)) break;\r\n const parent = path.dirname(current);\r\n if (parent === current) break;\r\n current = parent;\r\n }\r\n return chain;\r\n}\r\n\r\n// ─── Route Scanner ────────────────────────────────────────────────────────────\r\n\r\nfunction scanRoutes(dir: string, appDir: string, baseRoute = ''): RouteNode[] {\r\n const routes: RouteNode[] = [];\r\n if (!fs.existsSync(dir)) return routes;\r\n\r\n let entries: fs.Dirent[];\r\n try { entries = fs.readdirSync(dir, { withFileTypes: true }); }\r\n catch { return routes; }\r\n\r\n // File-based: about.tsx → /about\r\n for (const entry of entries) {\r\n if (!entry.isFile() || entry.name.startsWith('.') || entry.name.startsWith('_')) continue;\r\n const ext = path.extname(entry.name);\r\n const base = path.basename(entry.name, ext);\r\n if (!(SUPPORTED_EXTS as readonly string[]).includes(ext)) continue;\r\n if (SPECIAL_BASES.has(base)) continue;\r\n routes.push({\r\n routePath : `${baseRoute}/${base}`,\r\n filePath : path.join(dir, entry.name),\r\n layouts : resolveLayoutChain(dir, appDir),\r\n dynamic : false,\r\n });\r\n }\r\n\r\n // Directory-based: [id]/page.tsx → /:id\r\n for (const entry of entries) {\r\n if (!entry.isDirectory()) continue;\r\n if (entry.name === 'node_modules' || entry.name.startsWith('.') || entry.name === 'api') continue;\r\n\r\n const fullPath = path.join(dir, entry.name);\r\n const isDynamic = entry.name.startsWith('[') && entry.name.endsWith(']');\r\n const segment = isDynamic ? `:${entry.name.slice(1, -1)}` : entry.name;\r\n const routePath = `${baseRoute}/${segment}`;\r\n\r\n const pageFile = findFile(fullPath, PAGE_FILES);\r\n if (pageFile) {\r\n routes.push({\r\n routePath,\r\n filePath : path.join(fullPath, pageFile),\r\n layouts : resolveLayoutChain(fullPath, appDir),\r\n dynamic : isDynamic,\r\n });\r\n }\r\n routes.push(...scanRoutes(fullPath, appDir, routePath));\r\n }\r\n\r\n return routes;\r\n}\r\n\r\nfunction deduplicateRoutes(routes: RouteNode[]): RouteNode[] {\r\n const seen = new Set<string>();\r\n return routes.filter(r => {\r\n if (seen.has(r.routePath)) return false;\r\n seen.add(r.routePath);\r\n return true;\r\n });\r\n}\r\n\r\n// ─── Per-layout title extractor ──────────────────────────────────────────────\r\n\r\nfunction parseLayoutTitle(layoutFile: string): string | null {\r\n let src = '';\r\n try { src = fs.readFileSync(layoutFile, 'utf8'); }\r\n catch { return null; }\r\n\r\n const startIdx = src.indexOf('export const metadata');\r\n if (startIdx === -1) return null;\r\n const braceStart = src.indexOf('{', startIdx);\r\n if (braceStart === -1) return null;\r\n\r\n let depth = 0, end = braceStart;\r\n for (let i = braceStart; i < src.length; i++) {\r\n if (src[i] === '{') depth++;\r\n else if (src[i] === '}') { depth--; if (depth === 0) { end = i; break; } }\r\n }\r\n const block = src.slice(braceStart, end + 1);\r\n const match = /['\"]?title['\"]?\\s*:\\s*['\"`]([^'\"`]+)['\"`]/.exec(block);\r\n return match ? match[1] : null;\r\n}\r\n\r\n// ─── Route Tree Renderer ──────────────────────────────────────────────────────\r\n\r\nfunction renderChain(\r\n layouts : string[],\r\n routesInChain : RouteNode[],\r\n layoutNames : Map<string, string>,\r\n pageNames : Map<string, string>,\r\n layoutTitles : Map<string, string>,\r\n indent : number,\r\n): string {\r\n const pad = ' '.repeat(indent);\r\n if (layouts.length === 0) {\r\n return routesInChain.map(r =>\r\n `${pad}<Route path=\"${r.routePath}\" element={<Suspense fallback={<Spinner />}><ErrorBoundary><${pageNames.get(r.filePath)} /></ErrorBoundary></Suspense>} />`\r\n ).join('\\n');\r\n }\r\n const [head, ...tail] = layouts;\r\n const title = layoutTitles.get(head);\r\n const titleSetter = title ? `<TitleSetter title=${JSON.stringify(title)} />` : '';\r\n const inner = renderChain(tail, routesInChain, layoutNames, pageNames, layoutTitles, indent + 2);\r\n const name = layoutNames.get(head);\r\n return [\r\n `${pad}<Route element={<>${titleSetter}<Suspense fallback={<Spinner />}><ErrorBoundary><${name}><Outlet /></${name}></ErrorBoundary></Suspense></>}>`,\r\n inner,\r\n `${pad}</Route>`,\r\n ].join('\\n');\r\n}\r\n\r\n// ─── App Generator ────────────────────────────────────────────────────────────\r\n\r\nfunction generateApp(appDir: string): string {\r\n const aliases = readTsconfigAliases();\r\n const routes = scanRoutes(appDir, appDir);\r\n\r\n const rootPage = findFile(appDir, PAGE_FILES);\r\n if (rootPage) {\r\n routes.unshift({\r\n routePath : '/',\r\n filePath : path.join(appDir, rootPage),\r\n layouts : resolveLayoutChain(appDir, appDir),\r\n dynamic : false,\r\n });\r\n }\r\n\r\n const routesFiltered = routes.map(r => ({\r\n ...r,\r\n layouts: r.layouts.filter(l => isUsableLayout(l)),\r\n }));\r\n\r\n const validRoutes = deduplicateRoutes(\r\n routesFiltered.filter(r => hasDefaultExport(r.filePath))\r\n );\r\n\r\n validRoutes.sort((a, b) => {\r\n if (a.dynamic !== b.dynamic) return a.dynamic ? 1 : -1;\r\n return a.routePath.length - b.routePath.length;\r\n });\r\n\r\n const notFoundFile = NOT_FOUND_FILES.find(f => fs.existsSync(path.join(appDir, f)));\r\n const notFound = notFoundFile && hasDefaultExport(path.join(appDir, notFoundFile))\r\n ? notFoundFile\r\n : undefined;\r\n\r\n const allLayouts = new Set<string>();\r\n for (const r of validRoutes) r.layouts.forEach(l => {\r\n if (isUsableLayout(l)) allLayouts.add(l);\r\n });\r\n\r\n const layoutNames = new Map<string, string>();\r\n const pageNames = new Map<string, string>();\r\n const layoutTitles = new Map<string, string>();\r\n let li = 0, pi = 0;\r\n for (const l of allLayouts) {\r\n layoutNames.set(l, `Layout${li++}`);\r\n const title = parseLayoutTitle(l);\r\n if (title) layoutTitles.set(l, title);\r\n }\r\n for (const r of validRoutes) {\r\n if (!pageNames.has(r.filePath)) pageNames.set(r.filePath, `Page${pi++}`);\r\n }\r\n\r\n const lazyImports: string[] = [];\r\n for (const [fp, name] of layoutNames)\r\n lazyImports.push(`const ${name} = React.lazy(() => import('${toImportPath(fp, aliases)}'));`);\r\n if (notFound)\r\n lazyImports.push(`const NotFound = React.lazy(() => import('${toImportPath(path.join(appDir, notFound), aliases)}'));`);\r\n const emittedPages = new Set<string>();\r\n for (const r of validRoutes) {\r\n if (emittedPages.has(r.filePath)) continue;\r\n emittedPages.add(r.filePath);\r\n const name = pageNames.get(r.filePath);\r\n if (!name) continue;\r\n lazyImports.push(`const ${name} = React.lazy(() => import('${toImportPath(r.filePath, aliases)}'));`);\r\n }\r\n\r\n const chainMap = new Map<string, LayoutChainGroup>();\r\n for (const r of validRoutes) {\r\n const key = r.layouts.join('|');\r\n if (!chainMap.has(key)) chainMap.set(key, { layouts: r.layouts, routes: [] });\r\n chainMap.get(key)!.routes.push(r);\r\n }\r\n\r\n const routeLines: string[] = [];\r\n for (const [, { layouts, routes: cr }] of chainMap)\r\n routeLines.push(renderChain(layouts, cr, layoutNames, pageNames, layoutTitles, 8));\r\n\r\n const catchAll = notFound\r\n ? ` <Route path=\"*\" element={<Suspense fallback={<Spinner />}><NotFound /></Suspense>} />`\r\n : ` <Route path=\"*\" element={<Default404 />} />`;\r\n\r\n return `// ⚠️ Auto-generated by bini-router — do not edit.\r\nimport React, { Suspense } from 'react';\r\nimport { BrowserRouter, Routes, Route, Outlet } from 'react-router-dom';\r\nimport './app/globals.css';\r\n\r\n${lazyImports.join('\\n')}\r\n\r\n// ─── Error Boundary ───────────────────────────────────────────────────────────\r\nclass ErrorBoundary extends React.Component<\r\n { children: React.ReactNode },\r\n { error: Error | null }\r\n> {\r\n constructor(props: { children: React.ReactNode }) {\r\n super(props);\r\n this.state = { error: null };\r\n }\r\n static getDerivedStateFromError(error: Error) { return { error }; }\r\n override render() {\r\n if (this.state.error) return (\r\n <div style={{ minHeight: '100vh', display: 'flex', alignItems: 'center', justifyContent: 'center', fontFamily: 'system-ui,sans-serif', padding: '2rem' }}>\r\n <div style={{ maxWidth: 480, width: '100%', textAlign: 'center' }}>\r\n <h2 style={{ color: '#e74c3c', marginBottom: '1rem' }}>Something went wrong</h2>\r\n <pre style={{ background: '#fef2f2', padding: '1rem', borderRadius: '0.5rem', textAlign: 'left', fontSize: '0.8rem', color: '#e74c3c', overflow: 'auto' }}>{this.state.error.toString()}</pre>\r\n <button onClick={() => this.setState({ error: null })} style={{ marginTop: '1rem', padding: '0.5rem 1.5rem', background: '#00CFFF', color: 'white', border: 'none', borderRadius: '0.5rem', cursor: 'pointer', fontWeight: 600 }}>\r\n Try again\r\n </button>\r\n </div>\r\n </div>\r\n );\r\n return this.props.children;\r\n }\r\n}\r\n\r\nfunction Spinner() {\r\n return (\r\n <div style={{ minHeight: '100vh', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>\r\n <div style={{ width: 32, height: 32, border: '3px solid #eee', borderTop: '3px solid #00CFFF', borderRadius: '50%', animation: 'spin 0.8s linear infinite' }} />\r\n <style>{\\`@keyframes spin{to{transform:rotate(360deg)}}\\`}</style>\r\n </div>\r\n );\r\n}\r\n\r\nfunction TitleSetter({ title }: { title: string }) {\r\n React.useEffect(() => { document.title = title; }, [title]);\r\n return null;\r\n}\r\n\r\n${notFound ? '' : `function Default404() {\r\n return (\r\n <div style={{ minHeight: '100vh', display: 'flex', alignItems: 'center', justifyContent: 'center', background: 'linear-gradient(135deg,#00CFFF,#0077FF)', color: 'white', fontFamily: 'system-ui,sans-serif' }}>\r\n <div style={{ textAlign: 'center' }}>\r\n <h1 style={{ fontSize: '5rem', fontWeight: 800, margin: 0 }}>404</h1>\r\n <p style={{ fontSize: '1.25rem', margin: '0.5rem 0 2rem' }}>Page not found</p>\r\n <a href=\"/\" style={{ padding: '0.65rem 1.5rem', background: 'white', color: '#00CFFF', textDecoration: 'none', borderRadius: '0.5rem', fontWeight: 600 }}>← Back to Home</a>\r\n </div>\r\n </div>\r\n );\r\n}`}\r\n\r\nexport default function App() {\r\n return (\r\n <BrowserRouter>\r\n <Routes>\r\n${routeLines.join('\\n')}\r\n${catchAll}\r\n </Routes>\r\n </BrowserRouter>\r\n );\r\n}\r\n`;\r\n}\r\n\r\n// ─── Metadata Parser ──────────────────────────────────────────────────────────\r\n\r\nfunction parseAppMetadata(appDir: string): MetaTags {\r\n const layout = findFile(appDir, LAYOUT_FILES);\r\n if (!layout) return {};\r\n let src = '';\r\n try { src = fs.readFileSync(path.join(appDir, layout), 'utf8'); }\r\n catch { return {}; }\r\n\r\n const startIdx = src.indexOf('export const metadata');\r\n if (startIdx === -1) return {};\r\n const braceStart = src.indexOf('{', startIdx);\r\n if (braceStart === -1) return {};\r\n\r\n let depth = 0, end = braceStart;\r\n for (let i = braceStart; i < src.length; i++) {\r\n if (src[i] === '{') depth++;\r\n else if (src[i] === '}') { depth--; if (depth === 0) { end = i; break; } }\r\n }\r\n const block = src.slice(braceStart, end + 1);\r\n\r\n function extractBlock(source: string, key: string): string | undefined {\r\n const re = new RegExp(`['\"]?${key}['\"]?\\\\s*:\\\\s*\\\\{`);\r\n const match = re.exec(source);\r\n if (!match) return undefined;\r\n let d = 0, i = match.index + match[0].length - 1;\r\n const start = i;\r\n for (; i < source.length; i++) {\r\n if (source[i] === '{') d++;\r\n else if (source[i] === '}') { d--; if (d === 0) return source.slice(start, i + 1); }\r\n }\r\n return undefined;\r\n }\r\n\r\n function extractArray(source: string, key: string): string | undefined {\r\n const re = new RegExp(`['\"]?${key}['\"]?\\\\s*:\\\\s*\\\\[`);\r\n const match = re.exec(source);\r\n if (!match) return undefined;\r\n let d = 0, i = match.index + match[0].length - 1;\r\n const start = i;\r\n for (; i < source.length; i++) {\r\n if (source[i] === '[') d++;\r\n else if (source[i] === ']') { d--; if (d === 0) return source.slice(start, i + 1); }\r\n }\r\n return undefined;\r\n }\r\n\r\n function str(source: string, key: string): string | undefined {\r\n return source.match(\r\n new RegExp(`['\"]?${key}['\"]?\\\\s*:\\\\s*['\"\\`]([^'\"\\`\\n]+)['\"\\`]`)\r\n )?.[1];\r\n }\r\n\r\n function firstArrayStr(source: string, key: string): string | undefined {\r\n const arr = extractArray(source, key);\r\n if (!arr) return undefined;\r\n return arr.match(/url\\s*:\\s*['\"]([^'\"]+)['\"]/)?.[1]\r\n ?? arr.match(/['\"]([^'\"]+)['\"]/)?.[1];\r\n }\r\n\r\n function allArrayStrs(source: string, key: string): string[] {\r\n const arr = extractArray(source, key);\r\n if (!arr) return [];\r\n return [...arr.matchAll(/['\"]([^'\"]+)['\"]/g)].map(m => m[1]);\r\n }\r\n\r\n const meta: MetaTags = {};\r\n\r\n if (str(block, 'title')) meta.title = str(block, 'title');\r\n if (str(block, 'description')) meta.description = str(block, 'description');\r\n if (str(block, 'viewport')) meta.viewport = str(block, 'viewport');\r\n if (str(block, 'themeColor')) meta.themeColor = str(block, 'themeColor');\r\n if (str(block, 'charset')) meta.charset = str(block, 'charset');\r\n if (str(block, 'robots')) meta.robots = str(block, 'robots');\r\n if (str(block, 'canonical')) meta.canonical = str(block, 'canonical');\r\n if (str(block, 'manifest')) meta.manifest = str(block, 'manifest');\r\n\r\n const kwStr = str(block, 'keywords');\r\n if (kwStr) {\r\n meta.keywords = kwStr;\r\n } else {\r\n const kwArr = allArrayStrs(block, 'keywords');\r\n if (kwArr.length) meta.keywords = kwArr.join(', ');\r\n }\r\n\r\n const authorStr = str(block, 'author');\r\n if (authorStr) {\r\n meta.author = authorStr;\r\n } else {\r\n const authorsArr = extractArray(block, 'authors');\r\n if (authorsArr) {\r\n const name = authorsArr.match(/name\\s*:\\s*['\"]([^'\"]+)['\"]/)?.[1];\r\n if (name) meta.author = name;\r\n }\r\n }\r\n\r\n if (!meta.canonical) {\r\n const base = block.match(/metadataBase\\s*:\\s*new\\s+URL\\s*\\(\\s*['\"]([^'\"]+)['\"]/)?.[1];\r\n if (base) meta.canonical = base;\r\n }\r\n\r\n const ogBlock = extractBlock(block, 'openGraph');\r\n if (ogBlock) {\r\n meta.openGraph = {\r\n title : str(ogBlock, 'title'),\r\n description : str(ogBlock, 'description'),\r\n url : str(ogBlock, 'url'),\r\n type : str(ogBlock, 'type'),\r\n image : firstArrayStr(ogBlock, 'images') ?? str(ogBlock, 'image'),\r\n };\r\n }\r\n\r\n const twBlock = extractBlock(block, 'twitter');\r\n if (twBlock) {\r\n meta.twitter = {\r\n card : str(twBlock, 'card'),\r\n title : str(twBlock, 'title'),\r\n description : str(twBlock, 'description'),\r\n creator : str(twBlock, 'creator'),\r\n image : firstArrayStr(twBlock, 'images') ?? str(twBlock, 'image'),\r\n };\r\n }\r\n\r\n const iconsBlock = extractBlock(block, 'icons');\r\n if (iconsBlock) {\r\n meta.icons = {\r\n icon : collectIconEntries(iconsBlock, 'icon'),\r\n shortcut: collectIconEntries(iconsBlock, 'shortcut'),\r\n apple : collectIconEntries(iconsBlock, 'apple'),\r\n };\r\n }\r\n\r\n return meta;\r\n}\r\n\r\nfunction collectIconEntries(source: string, key: string): IconEntry[] {\r\n const arr = extractArrayRaw(source, key);\r\n if (!arr) return [];\r\n const entries: IconEntry[] = [];\r\n const objRe = /\\{([^}]+)\\}/g;\r\n let m: RegExpExecArray | null;\r\n while ((m = objRe.exec(arr)) !== null) {\r\n const obj = m[1];\r\n const url = obj.match(/url\\s*:\\s*['\"]([^'\"]+)['\"]/)?.[1];\r\n if (!url) continue;\r\n entries.push({\r\n url,\r\n type : obj.match(/type\\s*:\\s*['\"]([^'\"]+)['\"]/)?.[1],\r\n sizes: obj.match(/sizes\\s*:\\s*['\"]([^'\"]+)['\"]/)?.[1],\r\n });\r\n }\r\n if (!entries.length) {\r\n return [...arr.matchAll(/['\"]([^'\"]+)['\"]/g)].map(x => ({ url: x[1] }));\r\n }\r\n return entries;\r\n}\r\n\r\nfunction extractArrayRaw(source: string, key: string): string | undefined {\r\n const re = new RegExp(`['\"]?${key}['\"]?\\\\s*:\\\\s*\\\\[`);\r\n const match = re.exec(source);\r\n if (!match) return undefined;\r\n let d = 0, i = match.index + match[0].length - 1;\r\n const start = i;\r\n for (; i < source.length; i++) {\r\n if (source[i] === '[') d++;\r\n else if (source[i] === ']') { d--; if (d === 0) return source.slice(start, i + 1); }\r\n }\r\n return undefined;\r\n}\r\n\r\n// ─── API Route Scanner ────────────────────────────────────────────────────────\r\n\r\nfunction scanApiRoutes(dir: string, baseRoute = ''): ApiRoute[] {\r\n const routes: ApiRoute[] = [];\r\n if (!fs.existsSync(dir)) return routes;\r\n\r\n let entries: fs.Dirent[];\r\n try { entries = fs.readdirSync(dir, { withFileTypes: true }); }\r\n catch { return routes; }\r\n\r\n for (const entry of entries) {\r\n if (entry.name.startsWith('_') || entry.name.startsWith('.')) continue;\r\n const fullPath = path.join(dir, entry.name);\r\n\r\n if (entry.isDirectory()) {\r\n const isCatchAll = entry.name.startsWith('[...') && entry.name.endsWith(']');\r\n const isDynamic = entry.name.startsWith('[') && entry.name.endsWith(']');\r\n const segment = isCatchAll ? '*' : isDynamic ? `:${entry.name.slice(1, -1)}` : entry.name;\r\n routes.push(...scanApiRoutes(fullPath, `${baseRoute}/${segment}`));\r\n continue;\r\n }\r\n\r\n const ext = path.extname(entry.name);\r\n const base = path.basename(entry.name, ext);\r\n if (!(API_EXTS as readonly string[]).includes(ext)) continue;\r\n\r\n const isCatchAll = base.startsWith('[...') && base.endsWith(']');\r\n const isDynamic = base.startsWith('[') && base.endsWith(']');\r\n const routePath = isCatchAll\r\n ? `${baseRoute}/*`\r\n : base === 'index'\r\n ? baseRoute || '/'\r\n : isDynamic\r\n ? `${baseRoute}/:${base.slice(1, -1)}`\r\n : `${baseRoute}/${base}`;\r\n\r\n routes.push({ routePath, filePath: fullPath });\r\n }\r\n\r\n return routes;\r\n}\r\n\r\n// ─── Hono dev/preview server ──────────────────────────────────────────────────\r\n\r\nfunction matchRoute(pattern: string, pathname: string): Record<string, string> | null {\r\n const patParts = pattern.split('/').filter(Boolean);\r\n const urlParts = pathname.split('/').filter(Boolean);\r\n\r\n const isCatchAll = patParts[patParts.length - 1] === '*';\r\n if (isCatchAll) {\r\n const prefix = patParts.slice(0, -1);\r\n if (urlParts.length < prefix.length) return null;\r\n for (let i = 0; i < prefix.length; i++) {\r\n if (prefix[i].startsWith(':')) continue;\r\n if (prefix[i] !== urlParts[i]) return null;\r\n }\r\n return { '*': urlParts.slice(prefix.length).join('/') };\r\n }\r\n\r\n if (patParts.length !== urlParts.length) return null;\r\n\r\n const params: Record<string, string> = {};\r\n for (let i = 0; i < patParts.length; i++) {\r\n if (patParts[i].startsWith(':')) {\r\n params[patParts[i].slice(1)] = decodeURIComponent(urlParts[i]);\r\n } else if (patParts[i] !== urlParts[i]) {\r\n return null;\r\n }\r\n }\r\n return params;\r\n}\r\n\r\nconst moduleCache = new Map<string, { mtime: number; handler: unknown }>();\r\n\r\nasync function importHandler(filePath: string): Promise<unknown> {\r\n const { pathToFileURL } = await import('url');\r\n let mtime = 0;\r\n try { mtime = fs.statSync(filePath).mtimeMs; } catch { /* file vanished */ }\r\n\r\n const cached = moduleCache.get(filePath);\r\n if (cached && cached.mtime === mtime) return cached.handler;\r\n\r\n const mod = await import(pathToFileURL(filePath).href + '?t=' + mtime);\r\n const handler = mod.default ?? null;\r\n moduleCache.set(filePath, { mtime, handler });\r\n return handler;\r\n}\r\n\r\nasync function handleApiRequest(\r\n req : any,\r\n res : any,\r\n next : any,\r\n apiDir : string,\r\n enableCors : boolean,\r\n getCache : () => { routes: ApiRoute[] } | null,\r\n setCache : (v: { routes: ApiRoute[] }) => void,\r\n) {\r\n try {\r\n if (enableCors && req.method === 'OPTIONS') {\r\n res.statusCode = 204;\r\n res.setHeader('Access-Control-Allow-Origin', '*');\r\n res.setHeader('Access-Control-Allow-Methods', 'GET,POST,PUT,PATCH,DELETE,OPTIONS');\r\n res.setHeader('Access-Control-Allow-Headers', 'Content-Type,Authorization');\r\n res.setHeader('Access-Control-Max-Age', '86400');\r\n res.end();\r\n return;\r\n }\r\n\r\n let cache = getCache();\r\n if (!cache) {\r\n cache = { routes: scanApiRoutes(apiDir, '/api') };\r\n setCache(cache);\r\n }\r\n\r\n const host = req.headers.host ?? 'localhost';\r\n const url = `http://${host}${req.url}`;\r\n const pathname = new URL(url).pathname;\r\n\r\n const chunks: Buffer[] = [];\r\n for await (const chunk of req) chunks.push(chunk as Buffer);\r\n const body = chunks.length > 0 ? Buffer.concat(chunks) : undefined;\r\n\r\n const method = (req.method as string).toUpperCase();\r\n\r\n const webReq = new Request(url, {\r\n method,\r\n headers: req.headers as HeadersInit,\r\n body : !['GET', 'HEAD'].includes(method) && body?.length ? body : undefined,\r\n });\r\n\r\n for (const route of cache.routes) {\r\n const handler = await importHandler(route.filePath);\r\n if (!handler) continue;\r\n\r\n let webRes: Response;\r\n try {\r\n if (typeof (handler as any).fetch === 'function') {\r\n webRes = await (handler as any).fetch(webReq.clone());\r\n if (webRes.status === 404) continue;\r\n } else if (typeof handler === 'function') {\r\n const params = matchRoute(route.routePath, pathname);\r\n if (params === null) continue;\r\n\r\n const existingHeaders: Record<string, string> = {};\r\n webReq.headers.forEach((v, k) => { existingHeaders[k] = v; });\r\n const reqWithParams = new Request(webReq.clone(), {\r\n headers: { ...existingHeaders, 'x-bini-params': JSON.stringify(params) },\r\n });\r\n\r\n webRes = await (handler as (...args: any[]) => Promise<Response>)(reqWithParams);\r\n } else {\r\n continue;\r\n }\r\n } catch {\r\n continue;\r\n }\r\n\r\n const finalHeaders: Record<string, string> = {};\r\n webRes.headers.forEach((v, k) => { finalHeaders[k] = v; });\r\n if (enableCors) {\r\n finalHeaders['access-control-allow-origin'] = '*';\r\n finalHeaders['access-control-allow-methods'] = 'GET,POST,PUT,PATCH,DELETE,OPTIONS';\r\n finalHeaders['access-control-allow-headers'] = 'Content-Type,Authorization';\r\n }\r\n\r\n res.statusCode = webRes.status;\r\n for (const [k, v] of Object.entries(finalHeaders)) res.setHeader(k, v);\r\n res.end(Buffer.from(await webRes.arrayBuffer()));\r\n return;\r\n }\r\n\r\n res.statusCode = 404;\r\n res.setHeader('Content-Type', 'application/json');\r\n res.end(JSON.stringify({ error: `No API handler found for ${req.url}` }));\r\n } catch (e: any) {\r\n next(e);\r\n }\r\n}\r\n\r\n// ─── Production Entry Generator ───────────────────────────────────────────────\r\n\r\ntype Platform = 'netlify' | 'cloudflare' | 'node' | 'deno' | 'bun' | 'aws';\r\n\r\n// ─── Platform adapter config ─────────────────────────────────────────────────\r\n\r\ninterface AdapterConfig {\r\n pkg ?: string; // npm package to install (optional)\r\n importLine ?: string; // import statement for generated file\r\n exportLine : string; // export statement for generated file\r\n outFile : (cwd: string) => string;\r\n stripsApiPrefix: boolean; // platform strips /api before handler sees it\r\n}\r\n\r\n// All adapters use hono's built-in platform adapters — no extra packages needed\r\n// except @hono/node-server for Node.js (not built into hono core)\r\nconst ADAPTERS: Record<Platform, AdapterConfig> = {\r\n\r\n netlify: {\r\n // Netlify Edge Functions — uses hono/netlify adapter built into hono core\r\n importLine : `import { handle } from 'hono/netlify';`,\r\n exportLine : `export default handle(app);`,\r\n outFile : (cwd) => path.join(cwd, 'netlify', 'edge-functions', 'api.ts'),\r\n stripsApiPrefix: false,\r\n },\r\n cloudflare: {\r\n exportLine : `export default app;`,\r\n outFile : (cwd) => path.join(cwd, 'worker.ts'),\r\n stripsApiPrefix: false,\r\n },\r\n node: {\r\n pkg : '@hono/node-server',\r\n importLine : `import { serve } from '@hono/node-server';\r\nimport { serveStatic } from '@hono/node-server/serve-static';`,\r\n exportLine : `app.use('/*', serveStatic({ root: './dist' }));\r\napp.use('/*', serveStatic({ path: './dist/index.html' }));\r\n\r\nserve({ fetch: app.fetch, port: Number(process.env.PORT ?? 3000) }, (i) => {\r\n console.log(\\`Server running on http://localhost:\\${i.port}\\`);\r\n});`,\r\n outFile : (cwd) => path.join(cwd, 'server', 'index.ts'),\r\n stripsApiPrefix: false,\r\n },\r\n deno: {\r\n importLine : `import { serve } from 'hono/deno';`,\r\n exportLine : `serve(app.fetch);`,\r\n outFile : (cwd) => path.join(cwd, 'server', 'index.ts'),\r\n stripsApiPrefix: false,\r\n },\r\n bun: {\r\n exportLine : `export default app;`,\r\n outFile : (cwd) => path.join(cwd, 'server', 'index.ts'),\r\n stripsApiPrefix: false,\r\n },\r\n aws: {\r\n // Requires separate install: npm install @hono/aws-lambda\r\n pkg : '@hono/aws-lambda',\r\n importLine : `import { handle } from '@hono/aws-lambda';`,\r\n exportLine : `export const handler = handle(app);`,\r\n outFile : (cwd) => path.join(cwd, 'handler.ts'),\r\n stripsApiPrefix: false,\r\n },\r\n};\r\n\r\nfunction checkAdapter(platform: Platform): void {\r\n const adapter = ADAPTERS[platform];\r\n if (!adapter.pkg) return;\r\n try {\r\n require.resolve(adapter.pkg, { paths: [process.cwd()] });\r\n } catch {\r\n console.error(`\r\n[bini-router] ✗ Missing required package for platform '${platform}'.\r\n Run: npm install ${adapter.pkg}\r\n`);\r\n process.exit(1);\r\n }\r\n}\r\n\r\nfunction buildRouteImports(\r\n routes : ApiRoute[],\r\n outFile : string,\r\n enableCors: boolean,\r\n platform : Platform,\r\n): { imports: string[]; mountings: string[]; corsLine: string | null; corsImport: string | null } {\r\n const imports : string[] = [];\r\n const mountings : string[] = [];\r\n const adapter = ADAPTERS[platform];\r\n const stripPrefix = adapter.stripsApiPrefix;\r\n\r\n for (let i = 0; i < routes.length; i++) {\r\n const route = routes[i];\r\n const rel = norm(path.relative(path.dirname(outFile), route.filePath)).replace(/\\.(ts|tsx)$/, '');\r\n const imp = rel.startsWith('.') ? rel : `./${rel}`;\r\n const name = `_route${i}`;\r\n\r\n let src = '';\r\n try { src = fs.readFileSync(route.filePath, 'utf8'); } catch { /* skip */ }\r\n const isHonoApp = src.includes(\"from 'hono'\") || src.includes('from \"hono\"');\r\n\r\n imports.push(`import ${name} from '${imp}';`);\r\n\r\n if (isHonoApp) {\r\n mountings.push(`app.route('/', ${name});`);\r\n } else {\r\n // Some platforms strip /api prefix before the handler sees the request\r\n const mountPath = stripPrefix ? route.routePath : `/api${route.routePath}`;\r\n mountings.push(`app.all('${mountPath}', async (c) => { const r = await ${name}(c.req.raw); return r instanceof Response ? r : c.json(r); });`);\r\n }\r\n }\r\n\r\n const corsPattern = stripPrefix ? '/*' : '/api/*';\r\n const corsLine = enableCors\r\n ? `app.use('${corsPattern}', cors({ origin: '*', allowMethods: ['GET','POST','PUT','PATCH','DELETE','OPTIONS'], allowHeaders: ['Content-Type','Authorization'] }));`\r\n : null;\r\n const corsImport = enableCors ? `import { cors } from 'hono/cors';` : null;\r\n\r\n return { imports, mountings, corsLine, corsImport };\r\n}\r\n\r\nfunction buildProductionEntry(srcApiDir: string, platform: Platform, enableCors: boolean): void {\r\n if (!fs.existsSync(srcApiDir)) return;\r\n\r\n const routes = scanApiRoutes(srcApiDir);\r\n const cwd = process.cwd();\r\n\r\n const header = [\r\n `// ⚠️ Auto-generated by bini-router on every build — do not edit.`,\r\n `// Add routes by creating files in src/app/api/ only.`,\r\n ];\r\n\r\n // ── All platforms: use adapter config to generate entry file ────────────────\r\n checkAdapter(platform);\r\n\r\n const adapter = ADAPTERS[platform];\r\n const outFile = adapter.outFile(cwd);\r\n\r\n const { imports, mountings, corsLine, corsImport } = buildRouteImports(routes, outFile, enableCors, platform);\r\n\r\n const lines = [\r\n ...header,\r\n `import { Hono } from 'hono';`,\r\n ...(adapter.importLine ? adapter.importLine.split('\\n') : []),\r\n ...(corsImport ? [corsImport] : []),\r\n ...imports,\r\n ``,\r\n `const app = new Hono();`,\r\n ...(corsLine ? [corsLine] : []),\r\n ...mountings,\r\n ``,\r\n ...adapter.exportLine.split('\\n'),\r\n ];\r\n\r\n fs.mkdirSync(path.dirname(outFile), { recursive: true });\r\n fs.writeFileSync(outFile, lines.join('\\n') + '\\n', 'utf8');\r\n console.log(`[bini-router] ✓ Generated ${norm(path.relative(cwd, outFile))}`);\r\n}\r\n\r\n// ─── Plugin ───────────────────────────────────────────────────────────────────\r\n\r\nexport function biniroute(options: BiniPluginOptions = {}): Plugin {\r\n const { cors: enableCors = true, platform } = options;\r\n\r\n const getAppDir = () => path.join(process.cwd(), options.appDir ?? 'src/app');\r\n const getApiDir = () => path.join(process.cwd(), options.apiDir ?? 'src/app/api');\r\n\r\n let debounceTimer : ReturnType<typeof setTimeout> | null = null;\r\n let lastGeneratedCode = '';\r\n let honoCache : { routes: ApiRoute[] } | null = null;\r\n const eventLog = new Map<string, number>();\r\n\r\n function shouldProcess(file: string, event: string): boolean {\r\n const key = `${file}:${event}`;\r\n const now = Date.now();\r\n if (now - (eventLog.get(key) ?? 0) < EVENT_DEDUP_MS) return false;\r\n eventLog.set(key, now);\r\n for (const [k, v] of eventLog) if (now - v > EVENT_TTL_MS) eventLog.delete(k);\r\n return true;\r\n }\r\n\r\n function isPageFile(f: string): boolean {\r\n const nf = norm(f);\r\n const base = path.basename(f, path.extname(f));\r\n const ext = path.extname(f);\r\n if (!(SUPPORTED_EXTS as readonly string[]).includes(ext)) return false;\r\n if (!isInDir(nf, norm(getAppDir()))) return false;\r\n if (isInDir(nf, norm(getApiDir()))) return false;\r\n if (base.startsWith('_')) return false;\r\n return true;\r\n }\r\n\r\n function isApiFile(f: string): boolean {\r\n const nf = norm(f);\r\n return isInDir(nf, norm(getApiDir())) &&\r\n (API_EXTS as readonly string[]).includes(path.extname(f));\r\n }\r\n\r\n function applyApp(): string | null {\r\n const dir = getAppDir();\r\n if (!fs.existsSync(dir)) return null;\r\n const code = generateApp(dir);\r\n if (code === lastGeneratedCode) return null;\r\n fs.writeFileSync(getAppFile(), code, 'utf8');\r\n lastGeneratedCode = code;\r\n return code;\r\n }\r\n\r\n function scheduleRegen(server: ViteDevServer, delay = DEBOUNCE_MS) {\r\n if (debounceTimer) clearTimeout(debounceTimer);\r\n debounceTimer = setTimeout(() => {\r\n debounceTimer = null;\r\n if (applyApp() !== null) {\r\n server.ws.send({ type: 'full-reload', path: '*' });\r\n }\r\n }, delay);\r\n }\r\n\r\n function addSpaFallback(server: { middlewares: any }) {\r\n server.middlewares.use((req: any, res: any, next: any) => {\r\n const url = req.url as string;\r\n if (url.startsWith('/api') || url.includes('.')) return next();\r\n req.url = '/index.html';\r\n next();\r\n });\r\n }\r\n\r\n return {\r\n name : 'bini-router',\r\n enforce: 'pre',\r\n\r\n transform(code, id) {\r\n const nid = norm(id);\r\n if (!isInDir(nid, norm(getAppDir()))) return;\r\n const ext = path.extname(id);\r\n if (!(SUPPORTED_EXTS as readonly string[]).includes(ext)) return;\r\n if (!code.includes('export const metadata')) return;\r\n\r\n let result = code;\r\n let idx = result.indexOf('export const metadata');\r\n\r\n while (idx !== -1) {\r\n const braceIdx = result.indexOf('{', idx);\r\n if (braceIdx === -1) break;\r\n\r\n let depth = 0, end = braceIdx;\r\n for (let i = braceIdx; i < result.length; i++) {\r\n if (result[i] === '{') depth++;\r\n else if (result[i] === '}') { depth--; if (depth === 0) { end = i; break; } }\r\n }\r\n\r\n let tail = end + 1;\r\n while (tail < result.length && (result[tail] === ' ' || result[tail] === '\\t')) tail++;\r\n if (tail < result.length && result[tail] === ';') tail++;\r\n while (tail < result.length && (result[tail] === '\\n' || result[tail] === '\\r')) tail++;\r\n\r\n result = result.slice(0, idx) + result.slice(tail);\r\n idx = result.indexOf('export const metadata', idx);\r\n }\r\n\r\n return { code: result, map: null };\r\n },\r\n\r\n config() { applyApp(); },\r\n buildStart() { applyApp(); },\r\n\r\n closeBundle() {\r\n if (platform) buildProductionEntry(getApiDir(), platform, enableCors);\r\n },\r\n\r\n buildEnd() {\r\n honoCache = null;\r\n moduleCache.clear();\r\n if (debounceTimer) { clearTimeout(debounceTimer); debounceTimer = null; }\r\n },\r\n\r\n async configureServer(server) {\r\n const appDir = getAppDir();\r\n const apiDir = getApiDir();\r\n\r\n if (!fs.existsSync(appDir)) return;\r\n\r\n server.watcher.add(appDir);\r\n\r\n server.watcher.on('add', f => isPageFile(f) && shouldProcess(f, 'add') && scheduleRegen(server, 300));\r\n server.watcher.on('unlink', f => isPageFile(f) && shouldProcess(f, 'unlink') && scheduleRegen(server));\r\n server.watcher.on('change', f => isPageFile(f) && shouldProcess(f, 'change') && scheduleRegen(server));\r\n\r\n server.watcher.on('change', f => {\r\n const base = path.basename(f, path.extname(f));\r\n const inAppRoot = path.resolve(path.dirname(f)) === path.resolve(appDir);\r\n if (!inAppRoot || base !== 'layout') return;\r\n server.moduleGraph.invalidateAll();\r\n server.ws.send({ type: 'full-reload', path: '*' });\r\n });\r\n\r\n server.watcher.on('addDir', d => {\r\n const nd = norm(d);\r\n if (!isInDir(nd, norm(appDir)) || d.includes('node_modules') || isInDir(nd, norm(apiDir))) return;\r\n setTimeout(() => PAGE_FILES.some(f => fs.existsSync(path.join(d, f))) && scheduleRegen(server), 300);\r\n });\r\n\r\n server.watcher.on('unlinkDir', d => {\r\n const nd = norm(d);\r\n if (isInDir(nd, norm(appDir)) && !d.includes('node_modules') && !isInDir(nd, norm(apiDir)))\r\n scheduleRegen(server);\r\n });\r\n\r\n if (fs.existsSync(apiDir)) {\r\n server.watcher.add(apiDir);\r\n\r\n const resetApi = (f?: string) => {\r\n honoCache = null;\r\n if (f) moduleCache.delete(f);\r\n server.ws.send({ type: 'full-reload', path: '*' });\r\n };\r\n\r\n server.watcher.on('add', f => isApiFile(f) && resetApi(f));\r\n server.watcher.on('unlink', f => isApiFile(f) && resetApi(f));\r\n server.watcher.on('change', f => isApiFile(f) && resetApi(f));\r\n\r\n server.middlewares.use((req: any, res: any, next: any) => {\r\n if (!req.url?.startsWith('/api')) return next();\r\n handleApiRequest(req, res, next, apiDir, enableCors,\r\n () => honoCache, (v) => { honoCache = v; });\r\n });\r\n }\r\n },\r\n\r\n async configurePreviewServer(server) {\r\n addSpaFallback(server);\r\n\r\n const apiDir = getApiDir();\r\n if (!fs.existsSync(apiDir)) return;\r\n server.middlewares.use((req: any, res: any, next: any) => {\r\n if (!req.url?.startsWith('/api')) return next();\r\n handleApiRequest(req, res, next, apiDir, enableCors,\r\n () => honoCache, (v) => { honoCache = v; });\r\n });\r\n },\r\n\r\n transformIndexHtml: {\r\n order: 'pre',\r\n handler(html) {\r\n const meta = parseAppMetadata(getAppDir());\r\n\r\n if (!meta.title && !meta.description && !meta.canonical && !meta.manifest &&\r\n !meta.openGraph?.title && !meta.icons?.icon?.length) {\r\n return html;\r\n }\r\n\r\n const title = meta.title ?? 'Bini App';\r\n const vp = meta.viewport ?? 'width=device-width, initial-scale=1.0';\r\n\r\n const lines: string[] = [];\r\n\r\n lines.push(`<meta charset=\"${meta.charset ?? 'UTF-8'}\" />`);\r\n lines.push(`<meta name=\"viewport\" content=\"${vp}\" />`);\r\n lines.push(`<title>${title}</title>`);\r\n if (meta.description) lines.push(`<meta name=\"description\" content=\"${meta.description}\" />`);\r\n if (meta.themeColor) lines.push(`<meta name=\"theme-color\" content=\"${meta.themeColor}\" />`);\r\n if (meta.robots) lines.push(`<meta name=\"robots\" content=\"${meta.robots}\" />`);\r\n if (meta.keywords) lines.push(`<meta name=\"keywords\" content=\"${meta.keywords}\" />`);\r\n if (meta.author) lines.push(`<meta name=\"author\" content=\"${meta.author}\" />`);\r\n if (meta.canonical) lines.push(`<link rel=\"canonical\" href=\"${meta.canonical}\" />`);\r\n if (meta.manifest) lines.push(`<link rel=\"manifest\" href=\"${meta.manifest}\" />`);\r\n\r\n for (const entry of meta.icons?.icon ?? []) {\r\n const type = entry.type ? ` type=\"${entry.type}\"` : '';\r\n const sizes = entry.sizes ? ` sizes=\"${entry.sizes}\"` : '';\r\n lines.push(`<link rel=\"icon\" href=\"${entry.url}\"${type}${sizes} />`);\r\n }\r\n for (const entry of meta.icons?.shortcut ?? []) {\r\n lines.push(`<link rel=\"shortcut icon\" href=\"${entry.url}\" />`);\r\n }\r\n for (const entry of meta.icons?.apple ?? []) {\r\n const sizes = entry.sizes ? ` sizes=\"${entry.sizes}\"` : '';\r\n const type = entry.type ? ` type=\"${entry.type}\"` : '';\r\n lines.push(`<link rel=\"apple-touch-icon\" href=\"${entry.url}\"${sizes}${type} />`);\r\n }\r\n\r\n if (meta.openGraph?.title) {\r\n lines.push(`<meta property=\"og:type\" content=\"${meta.openGraph.type ?? 'website'}\" />`);\r\n lines.push(`<meta property=\"og:title\" content=\"${meta.openGraph.title}\" />`);\r\n if (meta.openGraph.description) lines.push(`<meta property=\"og:description\" content=\"${meta.openGraph.description}\" />`);\r\n if (meta.openGraph.url) lines.push(`<meta property=\"og:url\" content=\"${meta.openGraph.url}\" />`);\r\n if (meta.openGraph.image) lines.push(`<meta property=\"og:image\" content=\"${meta.openGraph.image}\" />`);\r\n }\r\n\r\n if (meta.twitter?.title) {\r\n lines.push(`<meta name=\"twitter:card\" content=\"${meta.twitter.card ?? 'summary_large_image'}\" />`);\r\n lines.push(`<meta name=\"twitter:title\" content=\"${meta.twitter.title}\" />`);\r\n if (meta.twitter.description) lines.push(`<meta name=\"twitter:description\" content=\"${meta.twitter.description}\" />`);\r\n if (meta.twitter.creator) lines.push(`<meta name=\"twitter:creator\" content=\"${meta.twitter.creator}\" />`);\r\n if (meta.twitter.image) lines.push(`<meta name=\"twitter:image\" content=\"${meta.twitter.image}\" />`);\r\n }\r\n\r\n const injected = lines.map(l => ` ${l}`).join('\\n');\r\n return html.replace('</head>', `${injected}\\n </head>`);\r\n },\r\n },\r\n };\r\n}\r\n\r\nexport default biniroute;"],"mappings":"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","names":["isCatchAll","isDynamic"]}
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["import fs from 'fs';\r\nimport path from 'path';\r\nimport type { Plugin, ViteDevServer } from 'vite';\r\n\r\n// ─── Constants ────────────────────────────────────────────────────────────────\r\n\r\nconst PAGE_FILES = ['page.tsx', 'page.jsx', 'page.ts', 'page.js'] as const;\r\nconst LAYOUT_FILES = ['layout.tsx', 'layout.jsx', 'layout.ts', 'layout.js'] as const;\r\nconst SUPPORTED_EXTS = ['.tsx', '.jsx', '.ts', '.js'] as const;\r\nconst NOT_FOUND_FILES = SUPPORTED_EXTS.map(e => `not-found${e}`);\r\nconst SPECIAL_BASES = new Set(['page', 'layout', 'not-found', 'loading', 'error']);\r\nconst API_EXTS = ['.ts', '.js'] as const;\r\nconst DEBOUNCE_MS = 60;\r\nconst EVENT_DEDUP_MS = 500;\r\nconst EVENT_TTL_MS = 2000;\r\n\r\n// ─── Metadata Types ───────────────────────────────────────────────────────────\r\n\r\nexport interface IconEntry {\r\n url : string;\r\n type ?: string;\r\n sizes?: string;\r\n}\r\n\r\nexport interface MetaTags {\r\n title ?: string;\r\n description ?: string;\r\n viewport ?: string;\r\n themeColor ?: string;\r\n keywords ?: string;\r\n author ?: string;\r\n charset ?: string;\r\n robots ?: string;\r\n canonical ?: string;\r\n manifest ?: string;\r\n openGraph ?: Partial<OGMeta>;\r\n twitter ?: Partial<TwitterMeta>;\r\n icons ?: {\r\n icon ?: IconEntry[];\r\n shortcut ?: IconEntry[];\r\n apple ?: IconEntry[];\r\n };\r\n}\r\n\r\ninterface OGMeta {\r\n title : string;\r\n description : string;\r\n url : string;\r\n image : string;\r\n type : string;\r\n}\r\n\r\ninterface TwitterMeta {\r\n card : string;\r\n title : string;\r\n description : string;\r\n creator : string;\r\n image : string;\r\n}\r\n\r\n// ─── Types ────────────────────────────────────────────────────────────────────\r\n\r\ninterface RouteNode {\r\n routePath : string;\r\n filePath : string;\r\n layouts : string[];\r\n dynamic : boolean;\r\n}\r\n\r\ninterface LayoutChainGroup {\r\n layouts : string[];\r\n routes : RouteNode[];\r\n}\r\n\r\ninterface ApiRoute {\r\n routePath : string;\r\n filePath : string;\r\n}\r\n\r\nexport interface BiniPluginOptions {\r\n /** Directory for page files. Default: src/app */\r\n appDir?: string;\r\n /** Directory for API routes. Default: src/app/api */\r\n apiDir?: string;\r\n /** Enable CORS headers in the dev-server API middleware. Default: true */\r\n cors?: boolean;\r\n /**\r\n * Target deployment platform. bini-router generates a production entry\r\n * file on every build — users only write code in src/app/api/.\r\n *\r\n * 'netlify' → netlify/edge-functions/api.ts (default, zero config)\r\n * 'cloudflare' → worker.ts (install: wrangler)\r\n * 'node' → server/index.ts (install: @hono/node-server)\r\n * 'deno' → server/index.ts (run with: deno run)\r\n * 'bun' → server/index.ts (run with: bun run)\r\n * 'aws' → handler.ts (install: @hono/aws-lambda)\r\n *\r\n * Default: undefined (no entry generated)\r\n */\r\n platform?: 'netlify' | 'cloudflare' | 'node' | 'deno' | 'bun' | 'aws';\r\n}\r\n\r\n// ─── Utilities ────────────────────────────────────────────────────────────────\r\n\r\nfunction norm(p: string): string {\r\n return p.replace(/\\\\/g, '/');\r\n}\r\n\r\nfunction isInDir(file: string, dir: string): boolean {\r\n const nFile = norm(file);\r\n const nDir = norm(dir).replace(/\\/$/, '');\r\n return nFile.startsWith(nDir + '/') || nFile === nDir;\r\n}\r\n\r\nfunction readTsconfigAliases(): Record<string, string> {\r\n const aliases: Record<string, string> = {};\r\n try {\r\n const tsconfigPath = path.join(process.cwd(), 'tsconfig.json');\r\n if (!fs.existsSync(tsconfigPath)) return aliases;\r\n const raw = fs.readFileSync(tsconfigPath, 'utf8')\r\n .replace(/\\/\\/.*$/gm, '')\r\n .replace(/\\/\\*[\\s\\S]*?\\*\\//g, '');\r\n const tsconfig = JSON.parse(raw);\r\n const paths = tsconfig?.compilerOptions?.paths ?? {};\r\n const baseUrl = tsconfig?.compilerOptions?.baseUrl ?? '.';\r\n for (const [alias, targets] of Object.entries(paths) as [string, string[]][]) {\r\n const cleanAlias = alias.replace(/\\/\\*$/, '');\r\n const cleanTarget = (targets[0] ?? '').replace(/\\/\\*$/, '');\r\n aliases[cleanAlias] = path.resolve(process.cwd(), baseUrl, cleanTarget);\r\n }\r\n } catch { /* tsconfig unreadable — fall back to relative paths */ }\r\n return aliases;\r\n}\r\n\r\nfunction toImportPath(filePath: string, aliases: Record<string, string>): string {\r\n for (const [alias, target] of Object.entries(aliases)) {\r\n if (norm(filePath).startsWith(norm(target) + '/')) {\r\n const rest = norm(filePath).slice(norm(target).length + 1).replace(/\\.(tsx|ts|jsx|js)$/, '');\r\n return `${alias}/${rest}`;\r\n }\r\n }\r\n return './' + norm(path.relative(path.join(process.cwd(), 'src'), filePath))\r\n .replace(/\\.(tsx|ts|jsx|js)$/, '');\r\n}\r\n\r\nfunction hasDefaultExport(filePath: string): boolean {\r\n try { return fs.readFileSync(filePath, 'utf8').includes('export default'); }\r\n catch { return false; }\r\n}\r\n\r\nfunction isHtmlShellLayout(filePath: string): boolean {\r\n try { return /<html[\\s>]/i.test(fs.readFileSync(filePath, 'utf8')); }\r\n catch { return false; }\r\n}\r\n\r\nfunction isUsableLayout(filePath: string): boolean {\r\n return hasDefaultExport(filePath) && !isHtmlShellLayout(filePath);\r\n}\r\n\r\nfunction findFile(dir: string, candidates: readonly string[]): string | null {\r\n return candidates.find(f => fs.existsSync(path.join(dir, f))) ?? null;\r\n}\r\n\r\nfunction getAppFile(): string {\r\n const ts = path.join(process.cwd(), 'src/App.tsx');\r\n return fs.existsSync(ts) ? ts : path.join(process.cwd(), 'src/App.jsx');\r\n}\r\n\r\n// ─── Layout Resolution ────────────────────────────────────────────────────────\r\n\r\nfunction resolveLayoutChain(pageDir: string, appDir: string): string[] {\r\n const chain: string[] = [];\r\n let current = pageDir;\r\n while (true) {\r\n const layout = findFile(current, LAYOUT_FILES);\r\n if (layout) chain.unshift(path.join(current, layout));\r\n if (path.resolve(current) === path.resolve(appDir)) break;\r\n const parent = path.dirname(current);\r\n if (parent === current) break;\r\n current = parent;\r\n }\r\n return chain;\r\n}\r\n\r\n// ─── Route Scanner ────────────────────────────────────────────────────────────\r\n\r\nfunction scanRoutes(dir: string, appDir: string, baseRoute = ''): RouteNode[] {\r\n const routes: RouteNode[] = [];\r\n if (!fs.existsSync(dir)) return routes;\r\n\r\n let entries: fs.Dirent[];\r\n try { entries = fs.readdirSync(dir, { withFileTypes: true }); }\r\n catch { return routes; }\r\n\r\n // File-based: about.tsx → /about\r\n for (const entry of entries) {\r\n if (!entry.isFile() || entry.name.startsWith('.') || entry.name.startsWith('_')) continue;\r\n const ext = path.extname(entry.name);\r\n const base = path.basename(entry.name, ext);\r\n if (!(SUPPORTED_EXTS as readonly string[]).includes(ext)) continue;\r\n if (SPECIAL_BASES.has(base)) continue;\r\n routes.push({\r\n routePath : `${baseRoute}/${base}`,\r\n filePath : path.join(dir, entry.name),\r\n layouts : resolveLayoutChain(dir, appDir),\r\n dynamic : false,\r\n });\r\n }\r\n\r\n // Directory-based: [id]/page.tsx → /:id\r\n for (const entry of entries) {\r\n if (!entry.isDirectory()) continue;\r\n if (entry.name === 'node_modules' || entry.name.startsWith('.') || entry.name === 'api') continue;\r\n\r\n const fullPath = path.join(dir, entry.name);\r\n const isDynamic = entry.name.startsWith('[') && entry.name.endsWith(']');\r\n const segment = isDynamic ? `:${entry.name.slice(1, -1)}` : entry.name;\r\n const routePath = `${baseRoute}/${segment}`;\r\n\r\n const pageFile = findFile(fullPath, PAGE_FILES);\r\n if (pageFile) {\r\n routes.push({\r\n routePath,\r\n filePath : path.join(fullPath, pageFile),\r\n layouts : resolveLayoutChain(fullPath, appDir),\r\n dynamic : isDynamic,\r\n });\r\n }\r\n routes.push(...scanRoutes(fullPath, appDir, routePath));\r\n }\r\n\r\n return routes;\r\n}\r\n\r\nfunction deduplicateRoutes(routes: RouteNode[]): RouteNode[] {\r\n const seen = new Set<string>();\r\n return routes.filter(r => {\r\n if (seen.has(r.routePath)) return false;\r\n seen.add(r.routePath);\r\n return true;\r\n });\r\n}\r\n\r\n// ─── Per-layout title extractor ──────────────────────────────────────────────\r\n\r\nfunction parseLayoutTitle(layoutFile: string): string | null {\r\n let src = '';\r\n try { src = fs.readFileSync(layoutFile, 'utf8'); }\r\n catch { return null; }\r\n\r\n const startIdx = src.indexOf('export const metadata');\r\n if (startIdx === -1) return null;\r\n const braceStart = src.indexOf('{', startIdx);\r\n if (braceStart === -1) return null;\r\n\r\n let depth = 0, end = braceStart;\r\n for (let i = braceStart; i < src.length; i++) {\r\n if (src[i] === '{') depth++;\r\n else if (src[i] === '}') { depth--; if (depth === 0) { end = i; break; } }\r\n }\r\n const block = src.slice(braceStart, end + 1);\r\n const match = /['\"]?title['\"]?\\s*:\\s*['\"`]([^'\"`]+)['\"`]/.exec(block);\r\n return match ? match[1] : null;\r\n}\r\n\r\n// ─── Route Tree Renderer ──────────────────────────────────────────────────────\r\n\r\nfunction renderChain(\r\n layouts : string[],\r\n routesInChain : RouteNode[],\r\n layoutNames : Map<string, string>,\r\n pageNames : Map<string, string>,\r\n layoutTitles : Map<string, string>,\r\n indent : number,\r\n): string {\r\n const pad = ' '.repeat(indent);\r\n if (layouts.length === 0) {\r\n return routesInChain.map(r =>\r\n `${pad}<Route path=\"${r.routePath}\" element={<Suspense fallback={<Spinner />}><ErrorBoundary><${pageNames.get(r.filePath)} /></ErrorBoundary></Suspense>} />`\r\n ).join('\\n');\r\n }\r\n const [head, ...tail] = layouts;\r\n const title = layoutTitles.get(head);\r\n const titleSetter = title ? `<TitleSetter title=${JSON.stringify(title)} />` : '';\r\n const inner = renderChain(tail, routesInChain, layoutNames, pageNames, layoutTitles, indent + 2);\r\n const name = layoutNames.get(head);\r\n return [\r\n `${pad}<Route element={<>${titleSetter}<Suspense fallback={<Spinner />}><ErrorBoundary><${name}><Outlet /></${name}></ErrorBoundary></Suspense></>}>`,\r\n inner,\r\n `${pad}</Route>`,\r\n ].join('\\n');\r\n}\r\n\r\n// ─── App Generator ────────────────────────────────────────────────────────────\r\n\r\nfunction generateApp(appDir: string): string {\r\n const aliases = readTsconfigAliases();\r\n const routes = scanRoutes(appDir, appDir);\r\n\r\n const rootPage = findFile(appDir, PAGE_FILES);\r\n if (rootPage) {\r\n routes.unshift({\r\n routePath : '/',\r\n filePath : path.join(appDir, rootPage),\r\n layouts : resolveLayoutChain(appDir, appDir),\r\n dynamic : false,\r\n });\r\n }\r\n\r\n const routesFiltered = routes.map(r => ({\r\n ...r,\r\n layouts: r.layouts.filter(l => isUsableLayout(l)),\r\n }));\r\n\r\n const validRoutes = deduplicateRoutes(\r\n routesFiltered.filter(r => hasDefaultExport(r.filePath))\r\n );\r\n\r\n validRoutes.sort((a, b) => {\r\n if (a.dynamic !== b.dynamic) return a.dynamic ? 1 : -1;\r\n return a.routePath.length - b.routePath.length;\r\n });\r\n\r\n const notFoundFile = NOT_FOUND_FILES.find(f => fs.existsSync(path.join(appDir, f)));\r\n const notFound = notFoundFile && hasDefaultExport(path.join(appDir, notFoundFile))\r\n ? notFoundFile\r\n : undefined;\r\n\r\n const allLayouts = new Set<string>();\r\n for (const r of validRoutes) r.layouts.forEach(l => {\r\n if (isUsableLayout(l)) allLayouts.add(l);\r\n });\r\n\r\n const layoutNames = new Map<string, string>();\r\n const pageNames = new Map<string, string>();\r\n const layoutTitles = new Map<string, string>();\r\n let li = 0, pi = 0;\r\n for (const l of allLayouts) {\r\n layoutNames.set(l, `Layout${li++}`);\r\n const title = parseLayoutTitle(l);\r\n if (title) layoutTitles.set(l, title);\r\n }\r\n for (const r of validRoutes) {\r\n if (!pageNames.has(r.filePath)) pageNames.set(r.filePath, `Page${pi++}`);\r\n }\r\n\r\n const lazyImports: string[] = [];\r\n for (const [fp, name] of layoutNames)\r\n lazyImports.push(`const ${name} = React.lazy(() => import('${toImportPath(fp, aliases)}'));`);\r\n if (notFound)\r\n lazyImports.push(`const NotFound = React.lazy(() => import('${toImportPath(path.join(appDir, notFound), aliases)}'));`);\r\n const emittedPages = new Set<string>();\r\n for (const r of validRoutes) {\r\n if (emittedPages.has(r.filePath)) continue;\r\n emittedPages.add(r.filePath);\r\n const name = pageNames.get(r.filePath);\r\n if (!name) continue;\r\n lazyImports.push(`const ${name} = React.lazy(() => import('${toImportPath(r.filePath, aliases)}'));`);\r\n }\r\n\r\n const chainMap = new Map<string, LayoutChainGroup>();\r\n for (const r of validRoutes) {\r\n const key = r.layouts.join('|');\r\n if (!chainMap.has(key)) chainMap.set(key, { layouts: r.layouts, routes: [] });\r\n chainMap.get(key)!.routes.push(r);\r\n }\r\n\r\n const routeLines: string[] = [];\r\n for (const [, { layouts, routes: cr }] of chainMap)\r\n routeLines.push(renderChain(layouts, cr, layoutNames, pageNames, layoutTitles, 8));\r\n\r\n const catchAll = notFound\r\n ? ` <Route path=\"*\" element={<Suspense fallback={<Spinner />}><NotFound /></Suspense>} />`\r\n : ` <Route path=\"*\" element={<Default404 />} />`;\r\n\r\n return `// ⚠️ Auto-generated by bini-router — do not edit.\r\nimport React, { Suspense } from 'react';\r\nimport { BrowserRouter, Routes, Route, Outlet } from 'react-router-dom';\r\nimport './app/globals.css';\r\n\r\n${lazyImports.join('\\n')}\r\n\r\n// ─── Error Boundary ───────────────────────────────────────────────────────────\r\nclass ErrorBoundary extends React.Component<\r\n { children: React.ReactNode },\r\n { error: Error | null }\r\n> {\r\n constructor(props: { children: React.ReactNode }) {\r\n super(props);\r\n this.state = { error: null };\r\n }\r\n static getDerivedStateFromError(error: Error) { return { error }; }\r\n override render() {\r\n if (this.state.error) return (\r\n <div style={{ minHeight: '100vh', display: 'flex', alignItems: 'center', justifyContent: 'center', fontFamily: 'system-ui,sans-serif', padding: '2rem' }}>\r\n <div style={{ maxWidth: 480, width: '100%', textAlign: 'center' }}>\r\n <h2 style={{ color: '#e74c3c', marginBottom: '1rem' }}>Something went wrong</h2>\r\n <pre style={{ background: '#fef2f2', padding: '1rem', borderRadius: '0.5rem', textAlign: 'left', fontSize: '0.8rem', color: '#e74c3c', overflow: 'auto' }}>{this.state.error.toString()}</pre>\r\n <button onClick={() => this.setState({ error: null })} style={{ marginTop: '1rem', padding: '0.5rem 1.5rem', background: '#00CFFF', color: 'white', border: 'none', borderRadius: '0.5rem', cursor: 'pointer', fontWeight: 600 }}>\r\n Try again\r\n </button>\r\n </div>\r\n </div>\r\n );\r\n return this.props.children;\r\n }\r\n}\r\n\r\nfunction Spinner() {\r\n return (\r\n <div style={{ minHeight: '100vh', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>\r\n <div style={{ width: 32, height: 32, border: '3px solid #eee', borderTop: '3px solid #00CFFF', borderRadius: '50%', animation: 'spin 0.8s linear infinite' }} />\r\n <style>{\\`@keyframes spin{to{transform:rotate(360deg)}}\\`}</style>\r\n </div>\r\n );\r\n}\r\n\r\nfunction TitleSetter({ title }: { title: string }) {\r\n React.useEffect(() => { document.title = title; }, [title]);\r\n return null;\r\n}\r\n\r\n${notFound ? '' : `function Default404() {\r\n return (\r\n <div style={{ minHeight: '100vh', display: 'flex', alignItems: 'center', justifyContent: 'center', background: 'linear-gradient(135deg,#00CFFF,#0077FF)', color: 'white', fontFamily: 'system-ui,sans-serif' }}>\r\n <div style={{ textAlign: 'center' }}>\r\n <h1 style={{ fontSize: '5rem', fontWeight: 800, margin: 0 }}>404</h1>\r\n <p style={{ fontSize: '1.25rem', margin: '0.5rem 0 2rem' }}>Page not found</p>\r\n <a href=\"/\" style={{ padding: '0.65rem 1.5rem', background: 'white', color: '#00CFFF', textDecoration: 'none', borderRadius: '0.5rem', fontWeight: 600 }}>← Back to Home</a>\r\n </div>\r\n </div>\r\n );\r\n}`}\r\n\r\nexport default function App() {\r\n return (\r\n <BrowserRouter>\r\n <Routes>\r\n${routeLines.join('\\n')}\r\n${catchAll}\r\n </Routes>\r\n </BrowserRouter>\r\n );\r\n}\r\n`;\r\n}\r\n\r\n// ─── Metadata Parser ──────────────────────────────────────────────────────────\r\n\r\nfunction parseAppMetadata(appDir: string): MetaTags {\r\n const layout = findFile(appDir, LAYOUT_FILES);\r\n if (!layout) return {};\r\n let src = '';\r\n try { src = fs.readFileSync(path.join(appDir, layout), 'utf8'); }\r\n catch { return {}; }\r\n\r\n const startIdx = src.indexOf('export const metadata');\r\n if (startIdx === -1) return {};\r\n const braceStart = src.indexOf('{', startIdx);\r\n if (braceStart === -1) return {};\r\n\r\n let depth = 0, end = braceStart;\r\n for (let i = braceStart; i < src.length; i++) {\r\n if (src[i] === '{') depth++;\r\n else if (src[i] === '}') { depth--; if (depth === 0) { end = i; break; } }\r\n }\r\n const block = src.slice(braceStart, end + 1);\r\n\r\n function extractBlock(source: string, key: string): string | undefined {\r\n const re = new RegExp(`['\"]?${key}['\"]?\\\\s*:\\\\s*\\\\{`);\r\n const match = re.exec(source);\r\n if (!match) return undefined;\r\n let d = 0, i = match.index + match[0].length - 1;\r\n const start = i;\r\n for (; i < source.length; i++) {\r\n if (source[i] === '{') d++;\r\n else if (source[i] === '}') { d--; if (d === 0) return source.slice(start, i + 1); }\r\n }\r\n return undefined;\r\n }\r\n\r\n function extractArray(source: string, key: string): string | undefined {\r\n const re = new RegExp(`['\"]?${key}['\"]?\\\\s*:\\\\s*\\\\[`);\r\n const match = re.exec(source);\r\n if (!match) return undefined;\r\n let d = 0, i = match.index + match[0].length - 1;\r\n const start = i;\r\n for (; i < source.length; i++) {\r\n if (source[i] === '[') d++;\r\n else if (source[i] === ']') { d--; if (d === 0) return source.slice(start, i + 1); }\r\n }\r\n return undefined;\r\n }\r\n\r\n function str(source: string, key: string): string | undefined {\r\n return source.match(\r\n new RegExp(`['\"]?${key}['\"]?\\\\s*:\\\\s*['\"\\`]([^'\"\\`\\n]+)['\"\\`]`)\r\n )?.[1];\r\n }\r\n\r\n function firstArrayStr(source: string, key: string): string | undefined {\r\n const arr = extractArray(source, key);\r\n if (!arr) return undefined;\r\n return arr.match(/url\\s*:\\s*['\"]([^'\"]+)['\"]/)?.[1]\r\n ?? arr.match(/['\"]([^'\"]+)['\"]/)?.[1];\r\n }\r\n\r\n function allArrayStrs(source: string, key: string): string[] {\r\n const arr = extractArray(source, key);\r\n if (!arr) return [];\r\n return [...arr.matchAll(/['\"]([^'\"]+)['\"]/g)].map(m => m[1]);\r\n }\r\n\r\n const meta: MetaTags = {};\r\n\r\n if (str(block, 'title')) meta.title = str(block, 'title');\r\n if (str(block, 'description')) meta.description = str(block, 'description');\r\n if (str(block, 'viewport')) meta.viewport = str(block, 'viewport');\r\n if (str(block, 'themeColor')) meta.themeColor = str(block, 'themeColor');\r\n if (str(block, 'charset')) meta.charset = str(block, 'charset');\r\n if (str(block, 'robots')) meta.robots = str(block, 'robots');\r\n if (str(block, 'canonical')) meta.canonical = str(block, 'canonical');\r\n if (str(block, 'manifest')) meta.manifest = str(block, 'manifest');\r\n\r\n const kwStr = str(block, 'keywords');\r\n if (kwStr) {\r\n meta.keywords = kwStr;\r\n } else {\r\n const kwArr = allArrayStrs(block, 'keywords');\r\n if (kwArr.length) meta.keywords = kwArr.join(', ');\r\n }\r\n\r\n const authorStr = str(block, 'author');\r\n if (authorStr) {\r\n meta.author = authorStr;\r\n } else {\r\n const authorsArr = extractArray(block, 'authors');\r\n if (authorsArr) {\r\n const name = authorsArr.match(/name\\s*:\\s*['\"]([^'\"]+)['\"]/)?.[1];\r\n if (name) meta.author = name;\r\n }\r\n }\r\n\r\n if (!meta.canonical) {\r\n const base = block.match(/metadataBase\\s*:\\s*new\\s+URL\\s*\\(\\s*['\"]([^'\"]+)['\"]/)?.[1];\r\n if (base) meta.canonical = base;\r\n }\r\n\r\n const ogBlock = extractBlock(block, 'openGraph');\r\n if (ogBlock) {\r\n meta.openGraph = {\r\n title : str(ogBlock, 'title'),\r\n description : str(ogBlock, 'description'),\r\n url : str(ogBlock, 'url'),\r\n type : str(ogBlock, 'type'),\r\n image : firstArrayStr(ogBlock, 'images') ?? str(ogBlock, 'image'),\r\n };\r\n }\r\n\r\n const twBlock = extractBlock(block, 'twitter');\r\n if (twBlock) {\r\n meta.twitter = {\r\n card : str(twBlock, 'card'),\r\n title : str(twBlock, 'title'),\r\n description : str(twBlock, 'description'),\r\n creator : str(twBlock, 'creator'),\r\n image : firstArrayStr(twBlock, 'images') ?? str(twBlock, 'image'),\r\n };\r\n }\r\n\r\n const iconsBlock = extractBlock(block, 'icons');\r\n if (iconsBlock) {\r\n meta.icons = {\r\n icon : collectIconEntries(iconsBlock, 'icon'),\r\n shortcut: collectIconEntries(iconsBlock, 'shortcut'),\r\n apple : collectIconEntries(iconsBlock, 'apple'),\r\n };\r\n }\r\n\r\n return meta;\r\n}\r\n\r\nfunction collectIconEntries(source: string, key: string): IconEntry[] {\r\n const arr = extractArrayRaw(source, key);\r\n if (!arr) return [];\r\n const entries: IconEntry[] = [];\r\n const objRe = /\\{([^}]+)\\}/g;\r\n let m: RegExpExecArray | null;\r\n while ((m = objRe.exec(arr)) !== null) {\r\n const obj = m[1];\r\n const url = obj.match(/url\\s*:\\s*['\"]([^'\"]+)['\"]/)?.[1];\r\n if (!url) continue;\r\n entries.push({\r\n url,\r\n type : obj.match(/type\\s*:\\s*['\"]([^'\"]+)['\"]/)?.[1],\r\n sizes: obj.match(/sizes\\s*:\\s*['\"]([^'\"]+)['\"]/)?.[1],\r\n });\r\n }\r\n if (!entries.length) {\r\n return [...arr.matchAll(/['\"]([^'\"]+)['\"]/g)].map(x => ({ url: x[1] }));\r\n }\r\n return entries;\r\n}\r\n\r\nfunction extractArrayRaw(source: string, key: string): string | undefined {\r\n const re = new RegExp(`['\"]?${key}['\"]?\\\\s*:\\\\s*\\\\[`);\r\n const match = re.exec(source);\r\n if (!match) return undefined;\r\n let d = 0, i = match.index + match[0].length - 1;\r\n const start = i;\r\n for (; i < source.length; i++) {\r\n if (source[i] === '[') d++;\r\n else if (source[i] === ']') { d--; if (d === 0) return source.slice(start, i + 1); }\r\n }\r\n return undefined;\r\n}\r\n\r\n// ─── API Route Scanner ────────────────────────────────────────────────────────\r\n\r\nfunction scanApiRoutes(dir: string, baseRoute = ''): ApiRoute[] {\r\n const routes: ApiRoute[] = [];\r\n if (!fs.existsSync(dir)) return routes;\r\n\r\n let entries: fs.Dirent[];\r\n try { entries = fs.readdirSync(dir, { withFileTypes: true }); }\r\n catch { return routes; }\r\n\r\n for (const entry of entries) {\r\n if (entry.name.startsWith('_') || entry.name.startsWith('.')) continue;\r\n const fullPath = path.join(dir, entry.name);\r\n\r\n if (entry.isDirectory()) {\r\n const isCatchAll = entry.name.startsWith('[...') && entry.name.endsWith(']');\r\n const isDynamic = entry.name.startsWith('[') && entry.name.endsWith(']');\r\n const segment = isCatchAll ? '*' : isDynamic ? `:${entry.name.slice(1, -1)}` : entry.name;\r\n routes.push(...scanApiRoutes(fullPath, `${baseRoute}/${segment}`));\r\n continue;\r\n }\r\n\r\n const ext = path.extname(entry.name);\r\n const base = path.basename(entry.name, ext);\r\n if (!(API_EXTS as readonly string[]).includes(ext)) continue;\r\n\r\n const isCatchAll = base.startsWith('[...') && base.endsWith(']');\r\n const isDynamic = base.startsWith('[') && base.endsWith(']');\r\n const routePath = isCatchAll\r\n ? `${baseRoute}/*`\r\n : base === 'index'\r\n ? baseRoute || '/'\r\n : isDynamic\r\n ? `${baseRoute}/:${base.slice(1, -1)}`\r\n : `${baseRoute}/${base}`;\r\n\r\n routes.push({ routePath, filePath: fullPath });\r\n }\r\n\r\n return routes;\r\n}\r\n\r\n// ─── Hono dev/preview server ──────────────────────────────────────────────────\r\n\r\nfunction matchRoute(pattern: string, pathname: string): Record<string, string> | null {\r\n const patParts = pattern.split('/').filter(Boolean);\r\n const urlParts = pathname.split('/').filter(Boolean);\r\n\r\n const isCatchAll = patParts[patParts.length - 1] === '*';\r\n if (isCatchAll) {\r\n const prefix = patParts.slice(0, -1);\r\n if (urlParts.length < prefix.length) return null;\r\n for (let i = 0; i < prefix.length; i++) {\r\n if (prefix[i].startsWith(':')) continue;\r\n if (prefix[i] !== urlParts[i]) return null;\r\n }\r\n return { '*': urlParts.slice(prefix.length).join('/') };\r\n }\r\n\r\n if (patParts.length !== urlParts.length) return null;\r\n\r\n const params: Record<string, string> = {};\r\n for (let i = 0; i < patParts.length; i++) {\r\n if (patParts[i].startsWith(':')) {\r\n params[patParts[i].slice(1)] = decodeURIComponent(urlParts[i]);\r\n } else if (patParts[i] !== urlParts[i]) {\r\n return null;\r\n }\r\n }\r\n return params;\r\n}\r\n\r\nconst moduleCache = new Map<string, { mtime: number; handler: unknown }>();\r\n\r\nasync function importHandler(filePath: string): Promise<unknown> {\r\n const { pathToFileURL } = await import('url');\r\n let mtime = 0;\r\n try { mtime = fs.statSync(filePath).mtimeMs; } catch { /* file vanished */ }\r\n\r\n const cached = moduleCache.get(filePath);\r\n if (cached && cached.mtime === mtime) return cached.handler;\r\n\r\n const mod = await import(pathToFileURL(filePath).href + '?t=' + mtime);\r\n const handler = mod.default ?? null;\r\n moduleCache.set(filePath, { mtime, handler });\r\n return handler;\r\n}\r\n\r\nasync function handleApiRequest(\r\n req : any,\r\n res : any,\r\n next : any,\r\n apiDir : string,\r\n enableCors : boolean,\r\n getCache : () => { routes: ApiRoute[] } | null,\r\n setCache : (v: { routes: ApiRoute[] }) => void,\r\n) {\r\n try {\r\n if (enableCors && req.method === 'OPTIONS') {\r\n res.statusCode = 204;\r\n res.setHeader('Access-Control-Allow-Origin', '*');\r\n res.setHeader('Access-Control-Allow-Methods', 'GET,POST,PUT,PATCH,DELETE,OPTIONS');\r\n res.setHeader('Access-Control-Allow-Headers', 'Content-Type,Authorization');\r\n res.setHeader('Access-Control-Max-Age', '86400');\r\n res.end();\r\n return;\r\n }\r\n\r\n let cache = getCache();\r\n if (!cache) {\r\n cache = { routes: scanApiRoutes(apiDir, '/api') };\r\n setCache(cache);\r\n }\r\n\r\n const host = req.headers.host ?? 'localhost';\r\n const url = `http://${host}${req.url}`;\r\n const pathname = new URL(url).pathname;\r\n\r\n const chunks: Buffer[] = [];\r\n for await (const chunk of req) chunks.push(chunk as Buffer);\r\n const body = chunks.length > 0 ? Buffer.concat(chunks) : undefined;\r\n\r\n const method = (req.method as string).toUpperCase();\r\n\r\n const webReq = new Request(url, {\r\n method,\r\n headers: req.headers as HeadersInit,\r\n body : !['GET', 'HEAD'].includes(method) && body?.length ? body : undefined,\r\n });\r\n\r\n for (const route of cache.routes) {\r\n const handler = await importHandler(route.filePath);\r\n if (!handler) continue;\r\n\r\n let webRes: Response;\r\n try {\r\n if (typeof (handler as any).fetch === 'function') {\r\n webRes = await (handler as any).fetch(webReq.clone());\r\n if (webRes.status === 404) continue;\r\n } else if (typeof handler === 'function') {\r\n const params = matchRoute(route.routePath, pathname);\r\n if (params === null) continue;\r\n\r\n const existingHeaders: Record<string, string> = {};\r\n webReq.headers.forEach((v, k) => { existingHeaders[k] = v; });\r\n const reqWithParams = new Request(webReq.clone(), {\r\n headers: { ...existingHeaders, 'x-bini-params': JSON.stringify(params) },\r\n });\r\n\r\n webRes = await (handler as (...args: any[]) => Promise<Response>)(reqWithParams);\r\n } else {\r\n continue;\r\n }\r\n } catch {\r\n continue;\r\n }\r\n\r\n const finalHeaders: Record<string, string> = {};\r\n webRes.headers.forEach((v, k) => { finalHeaders[k] = v; });\r\n if (enableCors) {\r\n finalHeaders['access-control-allow-origin'] = '*';\r\n finalHeaders['access-control-allow-methods'] = 'GET,POST,PUT,PATCH,DELETE,OPTIONS';\r\n finalHeaders['access-control-allow-headers'] = 'Content-Type,Authorization';\r\n }\r\n\r\n res.statusCode = webRes.status;\r\n for (const [k, v] of Object.entries(finalHeaders)) res.setHeader(k, v);\r\n res.end(Buffer.from(await webRes.arrayBuffer()));\r\n return;\r\n }\r\n\r\n res.statusCode = 404;\r\n res.setHeader('Content-Type', 'application/json');\r\n res.end(JSON.stringify({ error: `No API handler found for ${req.url}` }));\r\n } catch (e: any) {\r\n next(e);\r\n }\r\n}\r\n\r\n// ─── Production Entry Generator ───────────────────────────────────────────────\r\n\r\ntype Platform = 'netlify' | 'cloudflare' | 'node' | 'deno' | 'bun' | 'aws';\r\n\r\n// ─── Platform adapter config ─────────────────────────────────────────────────\r\n\r\ninterface AdapterConfig {\r\n pkg ?: string; // npm package to install (optional)\r\n importLine ?: string; // import statement for generated file\r\n exportLine : string; // export statement for generated file\r\n outFile : (cwd: string) => string;\r\n stripsApiPrefix: boolean; // platform strips /api before handler sees it\r\n}\r\n\r\n// All adapters use hono's built-in platform adapters — no extra packages needed\r\n// except @hono/node-server for Node.js (not built into hono core)\r\nconst ADAPTERS: Record<Platform, AdapterConfig> = {\r\n\r\n netlify: {\r\n // Netlify Edge Functions — Deno runtime, use deno.land URL imports (zero npm)\r\n // Entry file uses URL imports so Netlify bundles with no npm module errors.\r\n // User route files import `from 'hono'` (npm) but Netlify resolves them fine\r\n // since the entry provides Hono via URL import at bundle time.\r\n importLine : `import { Hono } from 'https://deno.land/x/hono@v4.3.11/mod.ts';\\nimport { handle } from 'https://deno.land/x/hono@v4.3.11/adapter/netlify/index.ts';`,\r\n exportLine : `export default handle(app);`,\r\n outFile : (cwd) => path.join(cwd, 'netlify', 'edge-functions', 'api.ts'),\r\n stripsApiPrefix: false,\r\n },\r\n\r\n cloudflare: {\r\n exportLine : `export default app;`,\r\n outFile : (cwd) => path.join(cwd, 'worker.ts'),\r\n stripsApiPrefix: false,\r\n },\r\n node: {\r\n pkg : '@hono/node-server',\r\n importLine : `import { serve } from '@hono/node-server';\r\nimport { serveStatic } from '@hono/node-server/serve-static';`,\r\n exportLine : `app.use('/*', serveStatic({ root: './dist' }));\r\napp.use('/*', serveStatic({ path: './dist/index.html' }));\r\n\r\nserve({ fetch: app.fetch, port: Number(process.env.PORT ?? 3000) }, (i) => {\r\n console.log(\\`Server running on http://localhost:\\${i.port}\\`);\r\n});`,\r\n outFile : (cwd) => path.join(cwd, 'server', 'index.ts'),\r\n stripsApiPrefix: false,\r\n },\r\n deno: {\r\n importLine : `import { serve } from 'hono/deno';`,\r\n exportLine : `serve(app.fetch);`,\r\n outFile : (cwd) => path.join(cwd, 'server', 'index.ts'),\r\n stripsApiPrefix: false,\r\n },\r\n bun: {\r\n exportLine : `export default app;`,\r\n outFile : (cwd) => path.join(cwd, 'server', 'index.ts'),\r\n stripsApiPrefix: false,\r\n },\r\n aws: {\r\n // Requires separate install: npm install @hono/aws-lambda\r\n pkg : '@hono/aws-lambda',\r\n importLine : `import { handle } from '@hono/aws-lambda';`,\r\n exportLine : `export const handler = handle(app);`,\r\n outFile : (cwd) => path.join(cwd, 'handler.ts'),\r\n stripsApiPrefix: false,\r\n },\r\n};\r\n\r\nfunction checkAdapter(platform: Platform): void {\r\n const adapter = ADAPTERS[platform];\r\n if (!adapter.pkg) return;\r\n try {\r\n require.resolve(adapter.pkg, { paths: [process.cwd()] });\r\n } catch {\r\n console.error(`\r\n[bini-router] ✗ Missing required package for platform '${platform}'.\r\n Run: npm install ${adapter.pkg}\r\n`);\r\n process.exit(1);\r\n }\r\n}\r\n\r\nfunction buildRouteImports(\r\n routes : ApiRoute[],\r\n outFile : string,\r\n enableCors: boolean,\r\n platform : Platform,\r\n): { imports: string[]; mountings: string[]; corsLine: string | null; corsImport: string | null } {\r\n const imports : string[] = [];\r\n const mountings : string[] = [];\r\n const adapter = ADAPTERS[platform];\r\n const stripPrefix = adapter.stripsApiPrefix;\r\n\r\n for (let i = 0; i < routes.length; i++) {\r\n const route = routes[i];\r\n const rel = norm(path.relative(path.dirname(outFile), route.filePath)).replace(/\\.(ts|tsx)$/, '');\r\n const imp = rel.startsWith('.') ? rel : `./${rel}`;\r\n const name = `_route${i}`;\r\n\r\n let src = '';\r\n try { src = fs.readFileSync(route.filePath, 'utf8'); } catch { /* skip */ }\r\n const isHonoApp = src.includes(\"from 'hono'\") || src.includes('from \"hono\"');\r\n\r\n imports.push(`import ${name} from '${imp}';`);\r\n\r\n if (isHonoApp) {\r\n mountings.push(`app.route('/', ${name});`);\r\n } else {\r\n // Some platforms strip /api prefix before the handler sees the request\r\n const mountPath = stripPrefix ? route.routePath : `/api${route.routePath}`;\r\n mountings.push(`app.all('${mountPath}', async (c) => { const r = await ${name}(c.req.raw); return r instanceof Response ? r : c.json(r); });`);\r\n }\r\n\r\n }\r\n\r\n const corsPattern = stripPrefix ? '/*' : '/api/*';\r\n const isNetlifyPlatform = platform === 'netlify';\r\n // Netlify edge functions: use inline CORS middleware to avoid npm import errors\r\n const corsLine = enableCors\r\n ? isNetlifyPlatform\r\n ? `app.use('${corsPattern}', async (c, next) => { await next(); c.res.headers.set('Access-Control-Allow-Origin', '*'); c.res.headers.set('Access-Control-Allow-Methods', 'GET,POST,PUT,PATCH,DELETE,OPTIONS'); c.res.headers.set('Access-Control-Allow-Headers', 'Content-Type,Authorization'); if (c.req.method === 'OPTIONS') return new Response(null, { status: 204, headers: c.res.headers }); });`\r\n : `app.use('${corsPattern}', cors({ origin: '*', allowMethods: ['GET','POST','PUT','PATCH','DELETE','OPTIONS'], allowHeaders: ['Content-Type','Authorization'] }));`\r\n : null;\r\n const corsImport = enableCors ? `import { cors } from 'hono/cors';` : null;\r\n\r\n return { imports, mountings, corsLine, corsImport };\r\n}\r\n\r\nfunction buildProductionEntry(srcApiDir: string, platform: Platform, enableCors: boolean): void {\r\n if (!fs.existsSync(srcApiDir)) return;\r\n\r\n const routes = scanApiRoutes(srcApiDir);\r\n const cwd = process.cwd();\r\n\r\n const header = [\r\n `// ⚠️ Auto-generated by bini-router on every build — do not edit.`,\r\n `// Add routes by creating files in src/app/api/ only.`,\r\n ];\r\n\r\n // ── All platforms: use adapter config to generate entry file ────────────────\r\n checkAdapter(platform);\r\n\r\n const adapter = ADAPTERS[platform];\r\n const outFile = adapter.outFile(cwd);\r\n\r\n const { imports, mountings, corsLine, corsImport } = buildRouteImports(routes, outFile, enableCors, platform);\r\n\r\n // Netlify edge functions use deno.land URL imports — Hono is already in importLine\r\n const isNetlify = platform === 'netlify';\r\n const lines = [\r\n ...header,\r\n ...(isNetlify ? [] : [`import { Hono } from 'hono';`]),\r\n ...(adapter.importLine ? adapter.importLine.split('\\n') : []),\r\n ...(corsImport && !isNetlify ? [corsImport] : []),\r\n ...imports,\r\n ``,\r\n `const app = new Hono();`,\r\n ...(corsLine ? [corsLine] : []),\r\n ...mountings,\r\n ``,\r\n ...adapter.exportLine.split('\\n'),\r\n ];\r\n\r\n fs.mkdirSync(path.dirname(outFile), { recursive: true });\r\n fs.writeFileSync(outFile, lines.join('\\n') + '\\n', 'utf8');\r\n console.log(`[bini-router] ✓ Generated ${norm(path.relative(cwd, outFile))}`);\r\n}\r\n\r\n// ─── Plugin ───────────────────────────────────────────────────────────────────\r\n\r\nexport function biniroute(options: BiniPluginOptions = {}): Plugin {\r\n const { cors: enableCors = true, platform } = options;\r\n\r\n const getAppDir = () => path.join(process.cwd(), options.appDir ?? 'src/app');\r\n const getApiDir = () => path.join(process.cwd(), options.apiDir ?? 'src/app/api');\r\n\r\n let debounceTimer : ReturnType<typeof setTimeout> | null = null;\r\n let lastGeneratedCode = '';\r\n let honoCache : { routes: ApiRoute[] } | null = null;\r\n const eventLog = new Map<string, number>();\r\n\r\n function shouldProcess(file: string, event: string): boolean {\r\n const key = `${file}:${event}`;\r\n const now = Date.now();\r\n if (now - (eventLog.get(key) ?? 0) < EVENT_DEDUP_MS) return false;\r\n eventLog.set(key, now);\r\n for (const [k, v] of eventLog) if (now - v > EVENT_TTL_MS) eventLog.delete(k);\r\n return true;\r\n }\r\n\r\n function isPageFile(f: string): boolean {\r\n const nf = norm(f);\r\n const base = path.basename(f, path.extname(f));\r\n const ext = path.extname(f);\r\n if (!(SUPPORTED_EXTS as readonly string[]).includes(ext)) return false;\r\n if (!isInDir(nf, norm(getAppDir()))) return false;\r\n if (isInDir(nf, norm(getApiDir()))) return false;\r\n if (base.startsWith('_')) return false;\r\n return true;\r\n }\r\n\r\n function isApiFile(f: string): boolean {\r\n const nf = norm(f);\r\n return isInDir(nf, norm(getApiDir())) &&\r\n (API_EXTS as readonly string[]).includes(path.extname(f));\r\n }\r\n\r\n function applyApp(): string | null {\r\n const dir = getAppDir();\r\n if (!fs.existsSync(dir)) return null;\r\n const code = generateApp(dir);\r\n if (code === lastGeneratedCode) return null;\r\n fs.writeFileSync(getAppFile(), code, 'utf8');\r\n lastGeneratedCode = code;\r\n return code;\r\n }\r\n\r\n function scheduleRegen(server: ViteDevServer, delay = DEBOUNCE_MS) {\r\n if (debounceTimer) clearTimeout(debounceTimer);\r\n debounceTimer = setTimeout(() => {\r\n debounceTimer = null;\r\n if (applyApp() !== null) {\r\n server.ws.send({ type: 'full-reload', path: '*' });\r\n }\r\n }, delay);\r\n }\r\n\r\n function addSpaFallback(server: { middlewares: any }) {\r\n server.middlewares.use((req: any, res: any, next: any) => {\r\n const url = req.url as string;\r\n if (url.startsWith('/api') || url.includes('.')) return next();\r\n req.url = '/index.html';\r\n next();\r\n });\r\n }\r\n\r\n return {\r\n name : 'bini-router',\r\n enforce: 'pre',\r\n\r\n transform(code, id) {\r\n const nid = norm(id);\r\n if (!isInDir(nid, norm(getAppDir()))) return;\r\n const ext = path.extname(id);\r\n if (!(SUPPORTED_EXTS as readonly string[]).includes(ext)) return;\r\n if (!code.includes('export const metadata')) return;\r\n\r\n let result = code;\r\n let idx = result.indexOf('export const metadata');\r\n\r\n while (idx !== -1) {\r\n const braceIdx = result.indexOf('{', idx);\r\n if (braceIdx === -1) break;\r\n\r\n let depth = 0, end = braceIdx;\r\n for (let i = braceIdx; i < result.length; i++) {\r\n if (result[i] === '{') depth++;\r\n else if (result[i] === '}') { depth--; if (depth === 0) { end = i; break; } }\r\n }\r\n\r\n let tail = end + 1;\r\n while (tail < result.length && (result[tail] === ' ' || result[tail] === '\\t')) tail++;\r\n if (tail < result.length && result[tail] === ';') tail++;\r\n while (tail < result.length && (result[tail] === '\\n' || result[tail] === '\\r')) tail++;\r\n\r\n result = result.slice(0, idx) + result.slice(tail);\r\n idx = result.indexOf('export const metadata', idx);\r\n }\r\n\r\n return { code: result, map: null };\r\n },\r\n\r\n config() { applyApp(); },\r\n buildStart() { applyApp(); },\r\n\r\n closeBundle() {\r\n if (platform) buildProductionEntry(getApiDir(), platform, enableCors);\r\n },\r\n\r\n buildEnd() {\r\n honoCache = null;\r\n moduleCache.clear();\r\n if (debounceTimer) { clearTimeout(debounceTimer); debounceTimer = null; }\r\n },\r\n\r\n async configureServer(server) {\r\n const appDir = getAppDir();\r\n const apiDir = getApiDir();\r\n\r\n if (!fs.existsSync(appDir)) return;\r\n\r\n server.watcher.add(appDir);\r\n\r\n server.watcher.on('add', f => isPageFile(f) && shouldProcess(f, 'add') && scheduleRegen(server, 300));\r\n server.watcher.on('unlink', f => isPageFile(f) && shouldProcess(f, 'unlink') && scheduleRegen(server));\r\n server.watcher.on('change', f => isPageFile(f) && shouldProcess(f, 'change') && scheduleRegen(server));\r\n\r\n server.watcher.on('change', f => {\r\n const base = path.basename(f, path.extname(f));\r\n const inAppRoot = path.resolve(path.dirname(f)) === path.resolve(appDir);\r\n if (!inAppRoot || base !== 'layout') return;\r\n server.moduleGraph.invalidateAll();\r\n server.ws.send({ type: 'full-reload', path: '*' });\r\n });\r\n\r\n server.watcher.on('addDir', d => {\r\n const nd = norm(d);\r\n if (!isInDir(nd, norm(appDir)) || d.includes('node_modules') || isInDir(nd, norm(apiDir))) return;\r\n setTimeout(() => PAGE_FILES.some(f => fs.existsSync(path.join(d, f))) && scheduleRegen(server), 300);\r\n });\r\n\r\n server.watcher.on('unlinkDir', d => {\r\n const nd = norm(d);\r\n if (isInDir(nd, norm(appDir)) && !d.includes('node_modules') && !isInDir(nd, norm(apiDir)))\r\n scheduleRegen(server);\r\n });\r\n\r\n if (fs.existsSync(apiDir)) {\r\n server.watcher.add(apiDir);\r\n\r\n const resetApi = (f?: string) => {\r\n honoCache = null;\r\n if (f) moduleCache.delete(f);\r\n server.ws.send({ type: 'full-reload', path: '*' });\r\n };\r\n\r\n server.watcher.on('add', f => isApiFile(f) && resetApi(f));\r\n server.watcher.on('unlink', f => isApiFile(f) && resetApi(f));\r\n server.watcher.on('change', f => isApiFile(f) && resetApi(f));\r\n\r\n server.middlewares.use((req: any, res: any, next: any) => {\r\n if (!req.url?.startsWith('/api')) return next();\r\n handleApiRequest(req, res, next, apiDir, enableCors,\r\n () => honoCache, (v) => { honoCache = v; });\r\n });\r\n }\r\n },\r\n\r\n async configurePreviewServer(server) {\r\n addSpaFallback(server);\r\n\r\n const apiDir = getApiDir();\r\n if (!fs.existsSync(apiDir)) return;\r\n server.middlewares.use((req: any, res: any, next: any) => {\r\n if (!req.url?.startsWith('/api')) return next();\r\n handleApiRequest(req, res, next, apiDir, enableCors,\r\n () => honoCache, (v) => { honoCache = v; });\r\n });\r\n },\r\n\r\n transformIndexHtml: {\r\n order: 'pre',\r\n handler(html) {\r\n const meta = parseAppMetadata(getAppDir());\r\n\r\n if (!meta.title && !meta.description && !meta.canonical && !meta.manifest &&\r\n !meta.openGraph?.title && !meta.icons?.icon?.length) {\r\n return html;\r\n }\r\n\r\n const title = meta.title ?? 'Bini App';\r\n const vp = meta.viewport ?? 'width=device-width, initial-scale=1.0';\r\n\r\n const lines: string[] = [];\r\n\r\n lines.push(`<meta charset=\"${meta.charset ?? 'UTF-8'}\" />`);\r\n lines.push(`<meta name=\"viewport\" content=\"${vp}\" />`);\r\n lines.push(`<title>${title}</title>`);\r\n if (meta.description) lines.push(`<meta name=\"description\" content=\"${meta.description}\" />`);\r\n if (meta.themeColor) lines.push(`<meta name=\"theme-color\" content=\"${meta.themeColor}\" />`);\r\n if (meta.robots) lines.push(`<meta name=\"robots\" content=\"${meta.robots}\" />`);\r\n if (meta.keywords) lines.push(`<meta name=\"keywords\" content=\"${meta.keywords}\" />`);\r\n if (meta.author) lines.push(`<meta name=\"author\" content=\"${meta.author}\" />`);\r\n if (meta.canonical) lines.push(`<link rel=\"canonical\" href=\"${meta.canonical}\" />`);\r\n if (meta.manifest) lines.push(`<link rel=\"manifest\" href=\"${meta.manifest}\" />`);\r\n\r\n for (const entry of meta.icons?.icon ?? []) {\r\n const type = entry.type ? ` type=\"${entry.type}\"` : '';\r\n const sizes = entry.sizes ? ` sizes=\"${entry.sizes}\"` : '';\r\n lines.push(`<link rel=\"icon\" href=\"${entry.url}\"${type}${sizes} />`);\r\n }\r\n for (const entry of meta.icons?.shortcut ?? []) {\r\n lines.push(`<link rel=\"shortcut icon\" href=\"${entry.url}\" />`);\r\n }\r\n for (const entry of meta.icons?.apple ?? []) {\r\n const sizes = entry.sizes ? ` sizes=\"${entry.sizes}\"` : '';\r\n const type = entry.type ? ` type=\"${entry.type}\"` : '';\r\n lines.push(`<link rel=\"apple-touch-icon\" href=\"${entry.url}\"${sizes}${type} />`);\r\n }\r\n\r\n if (meta.openGraph?.title) {\r\n lines.push(`<meta property=\"og:type\" content=\"${meta.openGraph.type ?? 'website'}\" />`);\r\n lines.push(`<meta property=\"og:title\" content=\"${meta.openGraph.title}\" />`);\r\n if (meta.openGraph.description) lines.push(`<meta property=\"og:description\" content=\"${meta.openGraph.description}\" />`);\r\n if (meta.openGraph.url) lines.push(`<meta property=\"og:url\" content=\"${meta.openGraph.url}\" />`);\r\n if (meta.openGraph.image) lines.push(`<meta property=\"og:image\" content=\"${meta.openGraph.image}\" />`);\r\n }\r\n\r\n if (meta.twitter?.title) {\r\n lines.push(`<meta name=\"twitter:card\" content=\"${meta.twitter.card ?? 'summary_large_image'}\" />`);\r\n lines.push(`<meta name=\"twitter:title\" content=\"${meta.twitter.title}\" />`);\r\n if (meta.twitter.description) lines.push(`<meta name=\"twitter:description\" content=\"${meta.twitter.description}\" />`);\r\n if (meta.twitter.creator) lines.push(`<meta name=\"twitter:creator\" content=\"${meta.twitter.creator}\" />`);\r\n if (meta.twitter.image) lines.push(`<meta name=\"twitter:image\" content=\"${meta.twitter.image}\" />`);\r\n }\r\n\r\n const injected = lines.map(l => ` ${l}`).join('\\n');\r\n return html.replace('</head>', `${injected}\\n </head>`);\r\n },\r\n },\r\n };\r\n}\r\n\r\nexport default biniroute;"],"mappings":"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","names":["isCatchAll","isDynamic"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bini-router",
3
- "version": "1.0.19",
3
+ "version": "1.0.20",
4
4
  "description": "File-based routing, nested layouts, and Hono-powered API routes for Vite + React",
5
5
  "author": "bini.js",
6
6
  "license": "MIT",