bini-router 1.0.21 → 1.0.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Readme.md +31 -8
- package/dist/index.cjs +70 -16
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +70 -16
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/Readme.md
CHANGED
|
@@ -19,7 +19,7 @@ Like Next.js — but pure SPA, zero server required.
|
|
|
19
19
|
|
|
20
20
|
## Features
|
|
21
21
|
|
|
22
|
-
- 🗂️ **File-based routing** — `page.tsx` files map directly to URLs
|
|
22
|
+
- 🗂️ **File-based routing** — `page.tsx` / `page.jsx` files map directly to URLs
|
|
23
23
|
- 🪆 **Nested layouts** — layouts wrap their segment and all children
|
|
24
24
|
- 🏷️ **Per-route metadata** — `export const metadata` in any layout or page
|
|
25
25
|
- 🔀 **Dynamic segments** — `[id]/page.tsx` → `/:id`
|
|
@@ -28,6 +28,7 @@ Like Next.js — but pure SPA, zero server required.
|
|
|
28
28
|
- ⏳ **Lazy loading** — every route is code-split automatically
|
|
29
29
|
- 🔄 **HMR** — file watcher with smart debounce and dedup
|
|
30
30
|
- 📦 **Zero config** — works out of the box
|
|
31
|
+
- 💛 **JavaScript & TypeScript** — full support for both, auto-detected
|
|
31
32
|
- 🚀 **Deploy anywhere** — bring your own [Hono adapter](https://hono.dev/docs/getting-started) for any platform
|
|
32
33
|
|
|
33
34
|
---
|
|
@@ -44,7 +45,7 @@ npm install bini-router hono
|
|
|
44
45
|
|
|
45
46
|
## Setup
|
|
46
47
|
|
|
47
|
-
### `vite.config.ts`
|
|
48
|
+
### `vite.config.ts` / `vite.config.js`
|
|
48
49
|
|
|
49
50
|
```ts
|
|
50
51
|
import { defineConfig } from 'vite'
|
|
@@ -76,11 +77,29 @@ export default defineConfig({
|
|
|
76
77
|
|
|
77
78
|
---
|
|
78
79
|
|
|
80
|
+
## JavaScript & TypeScript
|
|
81
|
+
|
|
82
|
+
bini-router supports both JavaScript and TypeScript projects out of the box — no extra configuration needed.
|
|
83
|
+
|
|
84
|
+
**Auto-detection:** if `tsconfig.json` exists in the project root, bini-router treats the project as TypeScript and generates `App.tsx` with full type annotations. Otherwise it generates `App.jsx` with clean JavaScript.
|
|
85
|
+
|
|
86
|
+
| | TypeScript project | JavaScript project |
|
|
87
|
+
|---|---|---|
|
|
88
|
+
| Auto-generated app entry | `src/App.tsx` | `src/App.jsx` |
|
|
89
|
+
| `ErrorBoundary` | Full generic types | Plain JS class |
|
|
90
|
+
| `TitleSetter` | Typed props | Plain JS function |
|
|
91
|
+
| Your pages / layouts | `.tsx` | `.jsx` |
|
|
92
|
+
| API routes | `.ts` | `.js` |
|
|
93
|
+
|
|
94
|
+
> bini-router scans for both `.tsx`/`.ts` and `.jsx`/`.js` page and layout files — mixed projects work fine too.
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
|
|
79
98
|
## File Structure
|
|
80
99
|
|
|
81
100
|
```
|
|
82
101
|
src/
|
|
83
|
-
main.tsx ← mounts <App /> as usual
|
|
102
|
+
main.tsx ← mounts <App /> as usual (main.jsx for JS projects)
|
|
84
103
|
App.tsx ← auto-generated by bini-router — do not edit
|
|
85
104
|
app/
|
|
86
105
|
globals.css ← global styles
|
|
@@ -107,6 +126,8 @@ src/
|
|
|
107
126
|
not-found.tsx ← custom 404 page (optional)
|
|
108
127
|
```
|
|
109
128
|
|
|
129
|
+
> JavaScript projects use `.jsx` / `.js` extensions throughout. Everything else stays identical.
|
|
130
|
+
|
|
110
131
|
---
|
|
111
132
|
|
|
112
133
|
## Pages
|
|
@@ -327,7 +348,7 @@ export default app
|
|
|
327
348
|
|
|
328
349
|
## Custom 404
|
|
329
350
|
|
|
330
|
-
Create `src/app/not-found.tsx` with a default export. If missing, bini-router renders a built-in 404 page.
|
|
351
|
+
Create `src/app/not-found.tsx` (or `not-found.jsx` for JavaScript projects) with a default export. If missing, bini-router renders a built-in 404 page.
|
|
331
352
|
|
|
332
353
|
```tsx
|
|
333
354
|
export default function NotFound() {
|
|
@@ -394,10 +415,9 @@ Add `netlify.toml`:
|
|
|
394
415
|
command = "vite build"
|
|
395
416
|
publish = "dist"
|
|
396
417
|
|
|
397
|
-
[[
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
status = 200
|
|
418
|
+
[[edge_functions]]
|
|
419
|
+
path = "/api/*"
|
|
420
|
+
function = "api"
|
|
401
421
|
|
|
402
422
|
[[redirects]]
|
|
403
423
|
from = "/*"
|
|
@@ -405,6 +425,9 @@ Add `netlify.toml`:
|
|
|
405
425
|
status = 200
|
|
406
426
|
```
|
|
407
427
|
|
|
428
|
+
> **Important:** Use `[[edge_functions]]` to wire up the API — **not** `[[redirects]]`.
|
|
429
|
+
> Using a redirect to `/.netlify/edge-functions/api` will result in a 404 for all API routes.
|
|
430
|
+
|
|
408
431
|
Push and deploy — no other config needed.
|
|
409
432
|
|
|
410
433
|
---
|
package/dist/index.cjs
CHANGED
|
@@ -100,9 +100,38 @@ function isUsableLayout(filePath) {
|
|
|
100
100
|
function findFile(dir, candidates) {
|
|
101
101
|
return candidates.find((f) => import_fs.default.existsSync(import_path.default.join(dir, f))) ?? null;
|
|
102
102
|
}
|
|
103
|
+
function isTypeScriptProject() {
|
|
104
|
+
const cwd = process.cwd();
|
|
105
|
+
if (import_fs.default.existsSync(import_path.default.join(cwd, "src/main.tsx")) || import_fs.default.existsSync(import_path.default.join(cwd, "src/main.ts"))) return true;
|
|
106
|
+
if (import_fs.default.existsSync(import_path.default.join(cwd, "src/main.jsx")) || import_fs.default.existsSync(import_path.default.join(cwd, "src/main.js"))) return false;
|
|
107
|
+
const appDir = import_path.default.join(cwd, "src/app");
|
|
108
|
+
if (import_fs.default.existsSync(appDir)) {
|
|
109
|
+
const hasTsFile = (dir) => {
|
|
110
|
+
let entries;
|
|
111
|
+
try {
|
|
112
|
+
entries = import_fs.default.readdirSync(dir, { withFileTypes: true });
|
|
113
|
+
} catch {
|
|
114
|
+
return false;
|
|
115
|
+
}
|
|
116
|
+
for (const entry of entries) {
|
|
117
|
+
if (entry.isDirectory()) {
|
|
118
|
+
if (hasTsFile(import_path.default.join(dir, entry.name))) return true;
|
|
119
|
+
} else {
|
|
120
|
+
const ext = import_path.default.extname(entry.name);
|
|
121
|
+
if (ext === ".tsx" || ext === ".ts") return true;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
return false;
|
|
125
|
+
};
|
|
126
|
+
if (hasTsFile(appDir)) return true;
|
|
127
|
+
}
|
|
128
|
+
return false;
|
|
129
|
+
}
|
|
103
130
|
function getAppFile() {
|
|
104
131
|
const ts = import_path.default.join(process.cwd(), "src/App.tsx");
|
|
105
|
-
|
|
132
|
+
const jsx = import_path.default.join(process.cwd(), "src/App.jsx");
|
|
133
|
+
if (import_fs.default.existsSync(ts)) return ts;
|
|
134
|
+
return isTypeScriptProject() ? ts : jsx;
|
|
106
135
|
}
|
|
107
136
|
function resolveLayoutChain(pageDir, appDir) {
|
|
108
137
|
const chain = [];
|
|
@@ -214,6 +243,7 @@ function renderChain(layouts, routesInChain, layoutNames, pageNames, layoutTitle
|
|
|
214
243
|
function generateApp(appDir) {
|
|
215
244
|
const aliases = readTsconfigAliases();
|
|
216
245
|
const routes = scanRoutes(appDir, appDir);
|
|
246
|
+
const ts = isTypeScriptProject();
|
|
217
247
|
const rootPage = findFile(appDir, PAGE_FILES);
|
|
218
248
|
if (rootPage) {
|
|
219
249
|
routes.unshift({
|
|
@@ -275,15 +305,7 @@ function generateApp(appDir) {
|
|
|
275
305
|
for (const [, { layouts, routes: cr }] of chainMap)
|
|
276
306
|
routeLines.push(renderChain(layouts, cr, layoutNames, pageNames, layoutTitles, 8));
|
|
277
307
|
const catchAll = notFound ? ` <Route path="*" element={<Suspense fallback={<Spinner />}><NotFound /></Suspense>} />` : ` <Route path="*" element={<Default404 />} />`;
|
|
278
|
-
|
|
279
|
-
import React, { Suspense } from 'react';
|
|
280
|
-
import { BrowserRouter, Routes, Route, Outlet } from 'react-router-dom';
|
|
281
|
-
import './app/globals.css';
|
|
282
|
-
|
|
283
|
-
${lazyImports.join("\n")}
|
|
284
|
-
|
|
285
|
-
// \u2500\u2500\u2500 Error Boundary \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
286
|
-
class ErrorBoundary extends React.Component<
|
|
308
|
+
const errorBoundaryClass = ts ? `class ErrorBoundary extends React.Component<
|
|
287
309
|
{ children: React.ReactNode },
|
|
288
310
|
{ error: Error | null }
|
|
289
311
|
> {
|
|
@@ -306,7 +328,43 @@ class ErrorBoundary extends React.Component<
|
|
|
306
328
|
);
|
|
307
329
|
return this.props.children;
|
|
308
330
|
}
|
|
309
|
-
}
|
|
331
|
+
}` : `class ErrorBoundary extends React.Component {
|
|
332
|
+
constructor(props) {
|
|
333
|
+
super(props);
|
|
334
|
+
this.state = { error: null };
|
|
335
|
+
}
|
|
336
|
+
static getDerivedStateFromError(error) { return { error }; }
|
|
337
|
+
render() {
|
|
338
|
+
if (this.state.error) return (
|
|
339
|
+
<div style={{ minHeight: '100vh', display: 'flex', alignItems: 'center', justifyContent: 'center', fontFamily: 'system-ui,sans-serif', padding: '2rem' }}>
|
|
340
|
+
<div style={{ maxWidth: 480, width: '100%', textAlign: 'center' }}>
|
|
341
|
+
<h2 style={{ color: '#e74c3c', marginBottom: '1rem' }}>Something went wrong</h2>
|
|
342
|
+
<pre style={{ background: '#fef2f2', padding: '1rem', borderRadius: '0.5rem', textAlign: 'left', fontSize: '0.8rem', color: '#e74c3c', overflow: 'auto' }}>{this.state.error.toString()}</pre>
|
|
343
|
+
<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 }}>
|
|
344
|
+
Try again
|
|
345
|
+
</button>
|
|
346
|
+
</div>
|
|
347
|
+
</div>
|
|
348
|
+
);
|
|
349
|
+
return this.props.children;
|
|
350
|
+
}
|
|
351
|
+
}`;
|
|
352
|
+
const titleSetterFn = ts ? `function TitleSetter({ title }: { title: string }) {
|
|
353
|
+
React.useEffect(() => { document.title = title; }, [title]);
|
|
354
|
+
return null;
|
|
355
|
+
}` : `function TitleSetter({ title }) {
|
|
356
|
+
React.useEffect(() => { document.title = title; }, [title]);
|
|
357
|
+
return null;
|
|
358
|
+
}`;
|
|
359
|
+
return `// \u26A0\uFE0F Auto-generated by bini-router \u2014 do not edit.
|
|
360
|
+
import React, { Suspense } from 'react';
|
|
361
|
+
import { BrowserRouter, Routes, Route, Outlet } from 'react-router-dom';
|
|
362
|
+
import './app/globals.css';
|
|
363
|
+
|
|
364
|
+
${lazyImports.join("\n")}
|
|
365
|
+
|
|
366
|
+
// \u2500\u2500\u2500 Error Boundary \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
367
|
+
${errorBoundaryClass}
|
|
310
368
|
|
|
311
369
|
function Spinner() {
|
|
312
370
|
return (
|
|
@@ -317,10 +375,7 @@ function Spinner() {
|
|
|
317
375
|
);
|
|
318
376
|
}
|
|
319
377
|
|
|
320
|
-
|
|
321
|
-
React.useEffect(() => { document.title = title; }, [title]);
|
|
322
|
-
return null;
|
|
323
|
-
}
|
|
378
|
+
${titleSetterFn}
|
|
324
379
|
|
|
325
380
|
${notFound ? "" : `function Default404() {
|
|
326
381
|
return (
|
|
@@ -663,7 +718,6 @@ import { handle } from 'https://deno.land/x/hono@v4.3.11/adapter/netlify/index.t
|
|
|
663
718
|
outFile: (cwd) => import_path.default.join(cwd, "netlify", "edge-functions", "api.ts"),
|
|
664
719
|
stripsApiPrefix: false,
|
|
665
720
|
denoRuntime: true
|
|
666
|
-
// ← Deno needs explicit .ts extensions
|
|
667
721
|
},
|
|
668
722
|
cloudflare: {
|
|
669
723
|
exportLine: `export default app;`,
|
package/dist/index.cjs.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 * 'netlify' → netlify/edge-functions/api.ts (Deno runtime, zero npm)\r\n * 'cloudflare' → worker.ts\r\n * 'node' → server/index.ts (requires: @hono/node-server)\r\n * 'deno' → server/index.ts\r\n * 'bun' → server/index.ts\r\n * 'aws' → handler.ts (requires: @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\ninterface AdapterConfig {\r\n pkg ?: string;\r\n importLine ?: string;\r\n exportLine : string;\r\n outFile : (cwd: string) => string;\r\n stripsApiPrefix : boolean;\r\n /** Deno runtime: requires explicit .ts extensions in imports */\r\n denoRuntime ?: boolean;\r\n}\r\n\r\nconst ADAPTERS: Record<Platform, AdapterConfig> = {\r\n\r\n netlify: {\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 denoRuntime : true, // ← Deno needs explicit .ts extensions\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\r\n node: {\r\n pkg : '@hono/node-server',\r\n importLine : `import { serve } from '@hono/node-server';\\nimport { serveStatic } from '@hono/node-server/serve-static';`,\r\n exportLine : `app.use('/*', serveStatic({ root: './dist' }));\\napp.use('/*', serveStatic({ path: './dist/index.html' }));\\n\\nserve({ fetch: app.fetch, port: Number(process.env.PORT ?? 3000) }, (i) => {\\n console.log(\\`Server running on http://localhost:\\${i.port}\\`);\\n});`,\r\n outFile : (cwd) => path.join(cwd, 'server', 'index.ts'),\r\n stripsApiPrefix: false,\r\n },\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 denoRuntime : true,\r\n },\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\r\n aws: {\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\n// ─── Resolve import path for production entry ────────────────────────────────\r\n// For Deno runtimes (Netlify edge functions, deno platform) we must keep the\r\n// .ts extension — Deno resolves modules by exact URL/path and will throw\r\n// \"Could not find file\" if the extension is omitted.\r\n// All other platforms (Node bundlers, esbuild, etc.) expect extensionless\r\n// imports, so we strip the extension as before.\r\nfunction resolveEntryImportPath(\r\n filePath : string,\r\n outFile : string,\r\n denoRuntime: boolean,\r\n): string {\r\n const rel = norm(path.relative(path.dirname(outFile), filePath));\r\n if (denoRuntime) {\r\n // Normalise to .ts (drop .tsx which Deno can't handle either)\r\n const withTs = rel.replace(/\\.tsx$/, '.ts');\r\n return withTs.startsWith('.') ? withTs : `./${withTs}`;\r\n }\r\n const stripped = rel.replace(/\\.(ts|tsx|js|jsx)$/, '');\r\n return stripped.startsWith('.') ? stripped : `./${stripped}`;\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 { stripsApiPrefix, denoRuntime = false } = adapter;\r\n const isNetlify = platform === 'netlify';\r\n\r\n for (let i = 0; i < routes.length; i++) {\r\n const route = routes[i];\r\n const imp = resolveEntryImportPath(route.filePath, outFile, denoRuntime);\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 const mountPath = stripsApiPrefix ? 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 = stripsApiPrefix ? '/*' : '/api/*';\r\n const corsLine = enableCors\r\n ? isNetlify\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\r\n const corsImport = enableCors && !isNetlify ? `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 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 isNetlify = platform === 'netlify';\r\n const lines = [\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 ...(isNetlify ? [] : [`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 (Deno runtime, zero npm)\r\n * 'cloudflare' → worker.ts\r\n * 'node' → server/index.ts (requires: @hono/node-server)\r\n * 'deno' → server/index.ts\r\n * 'bun' → server/index.ts\r\n * 'aws' → handler.ts (requires: @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\n// ─── TypeScript detection ─────────────────────────────────────────────────────\r\n// We cannot rely on tsconfig.json — Vite scaffolds it even for plain JS projects.\r\n// Instead we check whether the user's own entry point (main.tsx / main.ts) exists.\r\n// If neither exists yet we fall back to checking for any .tsx/.ts file in src/app.\r\n// Only if none of those signals are present do we treat the project as JavaScript.\r\n\r\nfunction isTypeScriptProject(): boolean {\r\n const cwd = process.cwd();\r\n\r\n // 1. Explicit TypeScript entry point\r\n if (\r\n fs.existsSync(path.join(cwd, 'src/main.tsx')) ||\r\n fs.existsSync(path.join(cwd, 'src/main.ts'))\r\n ) return true;\r\n\r\n // 2. Explicit JavaScript entry point\r\n if (\r\n fs.existsSync(path.join(cwd, 'src/main.jsx')) ||\r\n fs.existsSync(path.join(cwd, 'src/main.js'))\r\n ) return false;\r\n\r\n // 3. Fallback: scan src/app for any .tsx or .ts user file\r\n const appDir = path.join(cwd, 'src/app');\r\n if (fs.existsSync(appDir)) {\r\n const hasTsFile = (dir: string): boolean => {\r\n let entries: fs.Dirent[];\r\n try { entries = fs.readdirSync(dir, { withFileTypes: true }); }\r\n catch { return false; }\r\n for (const entry of entries) {\r\n if (entry.isDirectory()) {\r\n if (hasTsFile(path.join(dir, entry.name))) return true;\r\n } else {\r\n const ext = path.extname(entry.name);\r\n if (ext === '.tsx' || ext === '.ts') return true;\r\n }\r\n }\r\n return false;\r\n };\r\n if (hasTsFile(appDir)) return true;\r\n }\r\n\r\n // 4. Default to JavaScript\r\n return false;\r\n}\r\n\r\nfunction getAppFile(): string {\r\n const ts = path.join(process.cwd(), 'src/App.tsx');\r\n const jsx = path.join(process.cwd(), 'src/App.jsx');\r\n // If App.tsx already exists (e.g. from a previous regen), keep using it.\r\n // Otherwise choose the extension based on the detected project type.\r\n if (fs.existsSync(ts)) return ts;\r\n return isTypeScriptProject() ? ts : 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 const ts = isTypeScriptProject();\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 // ── ErrorBoundary — TypeScript vs JavaScript ─────────────────────────────\r\n // TypeScript projects get full generic type annotations.\r\n // JavaScript projects get clean JS class syntax — no generics, no type params.\r\n const errorBoundaryClass = ts\r\n ? `class 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 : `class ErrorBoundary extends React.Component {\r\n constructor(props) {\r\n super(props);\r\n this.state = { error: null };\r\n }\r\n static getDerivedStateFromError(error) { return { error }; }\r\n 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\n // ── TitleSetter — TypeScript vs JavaScript ───────────────────────────────\r\n const titleSetterFn = ts\r\n ? `function TitleSetter({ title }: { title: string }) {\r\n React.useEffect(() => { document.title = title; }, [title]);\r\n return null;\r\n}`\r\n : `function TitleSetter({ title }) {\r\n React.useEffect(() => { document.title = title; }, [title]);\r\n return null;\r\n}`;\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\n${errorBoundaryClass}\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\n${titleSetterFn}\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\ninterface AdapterConfig {\r\n pkg ?: string;\r\n importLine ?: string;\r\n exportLine : string;\r\n outFile : (cwd: string) => string;\r\n stripsApiPrefix : boolean;\r\n /** Deno runtime: requires explicit .ts extensions in imports */\r\n denoRuntime ?: boolean;\r\n}\r\n\r\nconst ADAPTERS: Record<Platform, AdapterConfig> = {\r\n\r\n netlify: {\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 denoRuntime : true,\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\r\n node: {\r\n pkg : '@hono/node-server',\r\n importLine : `import { serve } from '@hono/node-server';\\nimport { serveStatic } from '@hono/node-server/serve-static';`,\r\n exportLine : `app.use('/*', serveStatic({ root: './dist' }));\\napp.use('/*', serveStatic({ path: './dist/index.html' }));\\n\\nserve({ fetch: app.fetch, port: Number(process.env.PORT ?? 3000) }, (i) => {\\n console.log(\\`Server running on http://localhost:\\${i.port}\\`);\\n});`,\r\n outFile : (cwd) => path.join(cwd, 'server', 'index.ts'),\r\n stripsApiPrefix: false,\r\n },\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 denoRuntime : true,\r\n },\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\r\n aws: {\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 resolveEntryImportPath(\r\n filePath : string,\r\n outFile : string,\r\n denoRuntime: boolean,\r\n): string {\r\n const rel = norm(path.relative(path.dirname(outFile), filePath));\r\n if (denoRuntime) {\r\n const withTs = rel.replace(/\\.tsx$/, '.ts');\r\n return withTs.startsWith('.') ? withTs : `./${withTs}`;\r\n }\r\n const stripped = rel.replace(/\\.(ts|tsx|js|jsx)$/, '');\r\n return stripped.startsWith('.') ? stripped : `./${stripped}`;\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 { stripsApiPrefix, denoRuntime = false } = adapter;\r\n const isNetlify = platform === 'netlify';\r\n\r\n for (let i = 0; i < routes.length; i++) {\r\n const route = routes[i];\r\n const imp = resolveEntryImportPath(route.filePath, outFile, denoRuntime);\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 const mountPath = stripsApiPrefix ? 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 = stripsApiPrefix ? '/*' : '/api/*';\r\n const corsLine = enableCors\r\n ? isNetlify\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\r\n const corsImport = enableCors && !isNetlify ? `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 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 isNetlify = platform === 'netlify';\r\n const lines = [\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 ...(isNetlify ? [] : [`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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,gBAAe;AACf,kBAAiB;AAKjB,IAAM,aAAkB,CAAC,YAAY,YAAY,WAAW,SAAS;AACrE,IAAM,eAAkB,CAAC,cAAc,cAAc,aAAa,WAAW;AAC7E,IAAM,iBAAkB,CAAC,QAAQ,QAAQ,OAAO,KAAK;AACrD,IAAM,kBAAkB,eAAe,IAAI,OAAK,YAAY,CAAC,EAAE;AAC/D,IAAM,gBAAkB,oBAAI,IAAI,CAAC,QAAQ,UAAU,aAAa,WAAW,OAAO,CAAC;AACnF,IAAM,WAAkB,CAAC,OAAO,KAAK;AACrC,IAAM,cAAkB;AACxB,IAAM,iBAAkB;AACxB,IAAM,eAAkB;AA0FxB,SAAS,KAAK,GAAmB;AAC/B,SAAO,EAAE,QAAQ,OAAO,GAAG;AAC7B;AAEA,SAAS,QAAQ,MAAc,KAAsB;AACnD,QAAM,QAAQ,KAAK,IAAI;AACvB,QAAM,OAAQ,KAAK,GAAG,EAAE,QAAQ,OAAO,EAAE;AACzC,SAAO,MAAM,WAAW,OAAO,GAAG,KAAK,UAAU;AACnD;AAEA,SAAS,sBAA8C;AACrD,QAAM,UAAkC,CAAC;AACzC,MAAI;AACF,UAAM,eAAe,YAAAA,QAAK,KAAK,QAAQ,IAAI,GAAG,eAAe;AAC7D,QAAI,CAAC,UAAAC,QAAG,WAAW,YAAY,EAAG,QAAO;AACzC,UAAM,MAAM,UAAAA,QAAG,aAAa,cAAc,MAAM,EAC7C,QAAQ,aAAa,EAAE,EACvB,QAAQ,qBAAqB,EAAE;AAClC,UAAM,WAAY,KAAK,MAAM,GAAG;AAChC,UAAM,QAAY,UAAU,iBAAiB,SAAS,CAAC;AACvD,UAAM,UAAY,UAAU,iBAAiB,WAAW;AACxD,eAAW,CAAC,OAAO,OAAO,KAAK,OAAO,QAAQ,KAAK,GAA2B;AAC5E,YAAM,aAAc,MAAM,QAAQ,SAAS,EAAE;AAC7C,YAAM,eAAe,QAAQ,CAAC,KAAK,IAAI,QAAQ,SAAS,EAAE;AAC1D,cAAQ,UAAU,IAAI,YAAAD,QAAK,QAAQ,QAAQ,IAAI,GAAG,SAAS,WAAW;AAAA,IACxE;AAAA,EACF,QAAQ;AAAA,EAA0D;AAClE,SAAO;AACT;AAEA,SAAS,aAAa,UAAkB,SAAyC;AAC/E,aAAW,CAAC,OAAO,MAAM,KAAK,OAAO,QAAQ,OAAO,GAAG;AACrD,QAAI,KAAK,QAAQ,EAAE,WAAW,KAAK,MAAM,IAAI,GAAG,GAAG;AACjD,YAAM,OAAO,KAAK,QAAQ,EAAE,MAAM,KAAK,MAAM,EAAE,SAAS,CAAC,EAAE,QAAQ,sBAAsB,EAAE;AAC3F,aAAO,GAAG,KAAK,IAAI,IAAI;AAAA,IACzB;AAAA,EACF;AACA,SAAO,OAAO,KAAK,YAAAA,QAAK,SAAS,YAAAA,QAAK,KAAK,QAAQ,IAAI,GAAG,KAAK,GAAG,QAAQ,CAAC,EACxE,QAAQ,sBAAsB,EAAE;AACrC;AAEA,SAAS,iBAAiB,UAA2B;AACnD,MAAI;AAAE,WAAO,UAAAC,QAAG,aAAa,UAAU,MAAM,EAAE,SAAS,gBAAgB;AAAA,EAAG,QACrE;AAAE,WAAO;AAAA,EAAO;AACxB;AAEA,SAAS,kBAAkB,UAA2B;AACpD,MAAI;AAAE,WAAO,cAAc,KAAK,UAAAA,QAAG,aAAa,UAAU,MAAM,CAAC;AAAA,EAAG,QAC9D;AAAE,WAAO;AAAA,EAAO;AACxB;AAEA,SAAS,eAAe,UAA2B;AACjD,SAAO,iBAAiB,QAAQ,KAAK,CAAC,kBAAkB,QAAQ;AAClE;AAEA,SAAS,SAAS,KAAa,YAA8C;AAC3E,SAAO,WAAW,KAAK,OAAK,UAAAA,QAAG,WAAW,YAAAD,QAAK,KAAK,KAAK,CAAC,CAAC,CAAC,KAAK;AACnE;AAQA,SAAS,sBAA+B;AACtC,QAAM,MAAM,QAAQ,IAAI;AAGxB,MACE,UAAAC,QAAG,WAAW,YAAAD,QAAK,KAAK,KAAK,cAAc,CAAC,KAC5C,UAAAC,QAAG,WAAW,YAAAD,QAAK,KAAK,KAAK,aAAa,CAAC,EAC3C,QAAO;AAGT,MACE,UAAAC,QAAG,WAAW,YAAAD,QAAK,KAAK,KAAK,cAAc,CAAC,KAC5C,UAAAC,QAAG,WAAW,YAAAD,QAAK,KAAK,KAAK,aAAa,CAAC,EAC3C,QAAO;AAGT,QAAM,SAAS,YAAAA,QAAK,KAAK,KAAK,SAAS;AACvC,MAAI,UAAAC,QAAG,WAAW,MAAM,GAAG;AACzB,UAAM,YAAY,CAAC,QAAyB;AAC1C,UAAI;AACJ,UAAI;AAAE,kBAAU,UAAAA,QAAG,YAAY,KAAK,EAAE,eAAe,KAAK,CAAC;AAAA,MAAG,QACxD;AAAE,eAAO;AAAA,MAAO;AACtB,iBAAW,SAAS,SAAS;AAC3B,YAAI,MAAM,YAAY,GAAG;AACvB,cAAI,UAAU,YAAAD,QAAK,KAAK,KAAK,MAAM,IAAI,CAAC,EAAG,QAAO;AAAA,QACpD,OAAO;AACL,gBAAM,MAAM,YAAAA,QAAK,QAAQ,MAAM,IAAI;AACnC,cAAI,QAAQ,UAAU,QAAQ,MAAO,QAAO;AAAA,QAC9C;AAAA,MACF;AACA,aAAO;AAAA,IACT;AACA,QAAI,UAAU,MAAM,EAAG,QAAO;AAAA,EAChC;AAGA,SAAO;AACT;AAEA,SAAS,aAAqB;AAC5B,QAAM,KAAM,YAAAA,QAAK,KAAK,QAAQ,IAAI,GAAG,aAAa;AAClD,QAAM,MAAM,YAAAA,QAAK,KAAK,QAAQ,IAAI,GAAG,aAAa;AAGlD,MAAI,UAAAC,QAAG,WAAW,EAAE,EAAG,QAAO;AAC9B,SAAO,oBAAoB,IAAI,KAAK;AACtC;AAIA,SAAS,mBAAmB,SAAiB,QAA0B;AACrE,QAAM,QAAkB,CAAC;AACzB,MAAI,UAAU;AACd,SAAO,MAAM;AACX,UAAM,SAAS,SAAS,SAAS,YAAY;AAC7C,QAAI,OAAQ,OAAM,QAAQ,YAAAD,QAAK,KAAK,SAAS,MAAM,CAAC;AACpD,QAAI,YAAAA,QAAK,QAAQ,OAAO,MAAM,YAAAA,QAAK,QAAQ,MAAM,EAAG;AACpD,UAAM,SAAS,YAAAA,QAAK,QAAQ,OAAO;AACnC,QAAI,WAAW,QAAS;AACxB,cAAU;AAAA,EACZ;AACA,SAAO;AACT;AAIA,SAAS,WAAW,KAAa,QAAgB,YAAY,IAAiB;AAC5E,QAAM,SAAsB,CAAC;AAC7B,MAAI,CAAC,UAAAC,QAAG,WAAW,GAAG,EAAG,QAAO;AAEhC,MAAI;AACJ,MAAI;AAAE,cAAU,UAAAA,QAAG,YAAY,KAAK,EAAE,eAAe,KAAK,CAAC;AAAA,EAAG,QACxD;AAAE,WAAO;AAAA,EAAQ;AAGvB,aAAW,SAAS,SAAS;AAC3B,QAAI,CAAC,MAAM,OAAO,KAAK,MAAM,KAAK,WAAW,GAAG,KAAK,MAAM,KAAK,WAAW,GAAG,EAAG;AACjF,UAAM,MAAO,YAAAD,QAAK,QAAQ,MAAM,IAAI;AACpC,UAAM,OAAO,YAAAA,QAAK,SAAS,MAAM,MAAM,GAAG;AAC1C,QAAI,CAAE,eAAqC,SAAS,GAAG,EAAG;AAC1D,QAAI,cAAc,IAAI,IAAI,EAAG;AAC7B,WAAO,KAAK;AAAA,MACV,WAAY,GAAG,SAAS,IAAI,IAAI;AAAA,MAChC,UAAY,YAAAA,QAAK,KAAK,KAAK,MAAM,IAAI;AAAA,MACrC,SAAY,mBAAmB,KAAK,MAAM;AAAA,MAC1C,SAAY;AAAA,IACd,CAAC;AAAA,EACH;AAGA,aAAW,SAAS,SAAS;AAC3B,QAAI,CAAC,MAAM,YAAY,EAAG;AAC1B,QAAI,MAAM,SAAS,kBAAkB,MAAM,KAAK,WAAW,GAAG,KAAK,MAAM,SAAS,MAAO;AAEzF,UAAM,WAAY,YAAAA,QAAK,KAAK,KAAK,MAAM,IAAI;AAC3C,UAAM,YAAY,MAAM,KAAK,WAAW,GAAG,KAAK,MAAM,KAAK,SAAS,GAAG;AACvE,UAAM,UAAY,YAAY,IAAI,MAAM,KAAK,MAAM,GAAG,EAAE,CAAC,KAAK,MAAM;AACpE,UAAM,YAAY,GAAG,SAAS,IAAI,OAAO;AAEzC,UAAM,WAAW,SAAS,UAAU,UAAU;AAC9C,QAAI,UAAU;AACZ,aAAO,KAAK;AAAA,QACV;AAAA,QACA,UAAW,YAAAA,QAAK,KAAK,UAAU,QAAQ;AAAA,QACvC,SAAW,mBAAmB,UAAU,MAAM;AAAA,QAC9C,SAAW;AAAA,MACb,CAAC;AAAA,IACH;AACA,WAAO,KAAK,GAAG,WAAW,UAAU,QAAQ,SAAS,CAAC;AAAA,EACxD;AAEA,SAAO;AACT;AAEA,SAAS,kBAAkB,QAAkC;AAC3D,QAAM,OAAO,oBAAI,IAAY;AAC7B,SAAO,OAAO,OAAO,OAAK;AACxB,QAAI,KAAK,IAAI,EAAE,SAAS,EAAG,QAAO;AAClC,SAAK,IAAI,EAAE,SAAS;AACpB,WAAO;AAAA,EACT,CAAC;AACH;AAIA,SAAS,iBAAiB,YAAmC;AAC3D,MAAI,MAAM;AACV,MAAI;AAAE,UAAM,UAAAC,QAAG,aAAa,YAAY,MAAM;AAAA,EAAG,QAC3C;AAAE,WAAO;AAAA,EAAM;AAErB,QAAM,WAAW,IAAI,QAAQ,uBAAuB;AACpD,MAAI,aAAa,GAAI,QAAO;AAC5B,QAAM,aAAa,IAAI,QAAQ,KAAK,QAAQ;AAC5C,MAAI,eAAe,GAAI,QAAO;AAE9B,MAAI,QAAQ,GAAG,MAAM;AACrB,WAAS,IAAI,YAAY,IAAI,IAAI,QAAQ,KAAK;AAC5C,QAAI,IAAI,CAAC,MAAM,IAAK;AAAA,aACX,IAAI,CAAC,MAAM,KAAK;AAAE;AAAS,UAAI,UAAU,GAAG;AAAE,cAAM;AAAG;AAAA,MAAO;AAAA,IAAE;AAAA,EAC3E;AACA,QAAM,QAAQ,IAAI,MAAM,YAAY,MAAM,CAAC;AAC3C,QAAM,QAAQ,4CAA4C,KAAK,KAAK;AACpE,SAAO,QAAQ,MAAM,CAAC,IAAI;AAC5B;AAIA,SAAS,YACP,SACA,eACA,aACA,WACA,cACA,QACQ;AACR,QAAM,MAAM,IAAI,OAAO,MAAM;AAC7B,MAAI,QAAQ,WAAW,GAAG;AACxB,WAAO,cAAc;AAAA,MAAI,OACvB,GAAG,GAAG,gBAAgB,EAAE,SAAS,+DAA+D,UAAU,IAAI,EAAE,QAAQ,CAAC;AAAA,IAC3H,EAAE,KAAK,IAAI;AAAA,EACb;AACA,QAAM,CAAC,MAAM,GAAG,IAAI,IAAI;AACxB,QAAM,QAAc,aAAa,IAAI,IAAI;AACzC,QAAM,cAAc,QAAQ,sBAAsB,KAAK,UAAU,KAAK,CAAC,QAAQ;AAC/E,QAAM,QAAc,YAAY,MAAM,eAAe,aAAa,WAAW,cAAc,SAAS,CAAC;AACrG,QAAM,OAAc,YAAY,IAAI,IAAI;AACxC,SAAO;AAAA,IACL,GAAG,GAAG,qBAAqB,WAAW,oDAAoD,IAAI,gBAAgB,IAAI;AAAA,IAClH;AAAA,IACA,GAAG,GAAG;AAAA,EACR,EAAE,KAAK,IAAI;AACb;AAIA,SAAS,YAAY,QAAwB;AAC3C,QAAM,UAAU,oBAAoB;AACpC,QAAM,SAAU,WAAW,QAAQ,MAAM;AACzC,QAAM,KAAU,oBAAoB;AAEpC,QAAM,WAAW,SAAS,QAAQ,UAAU;AAC5C,MAAI,UAAU;AACZ,WAAO,QAAQ;AAAA,MACb,WAAY;AAAA,MACZ,UAAY,YAAAD,QAAK,KAAK,QAAQ,QAAQ;AAAA,MACtC,SAAY,mBAAmB,QAAQ,MAAM;AAAA,MAC7C,SAAY;AAAA,IACd,CAAC;AAAA,EACH;AAEA,QAAM,iBAAiB,OAAO,IAAI,QAAM;AAAA,IACtC,GAAG;AAAA,IACH,SAAS,EAAE,QAAQ,OAAO,OAAK,eAAe,CAAC,CAAC;AAAA,EAClD,EAAE;AAEF,QAAM,cAAc;AAAA,IAClB,eAAe,OAAO,OAAK,iBAAiB,EAAE,QAAQ,CAAC;AAAA,EACzD;AAEA,cAAY,KAAK,CAAC,GAAG,MAAM;AACzB,QAAI,EAAE,YAAY,EAAE,QAAS,QAAO,EAAE,UAAU,IAAI;AACpD,WAAO,EAAE,UAAU,SAAS,EAAE,UAAU;AAAA,EAC1C,CAAC;AAED,QAAM,eAAe,gBAAgB,KAAK,OAAK,UAAAC,QAAG,WAAW,YAAAD,QAAK,KAAK,QAAQ,CAAC,CAAC,CAAC;AAClF,QAAM,WAAe,gBAAgB,iBAAiB,YAAAA,QAAK,KAAK,QAAQ,YAAY,CAAC,IACjF,eACA;AAEJ,QAAM,aAAa,oBAAI,IAAY;AACnC,aAAW,KAAK,YAAa,GAAE,QAAQ,QAAQ,OAAK;AAClD,QAAI,eAAe,CAAC,EAAG,YAAW,IAAI,CAAC;AAAA,EACzC,CAAC;AAED,QAAM,cAAe,oBAAI,IAAoB;AAC7C,QAAM,YAAe,oBAAI,IAAoB;AAC7C,QAAM,eAAe,oBAAI,IAAoB;AAC7C,MAAI,KAAK,GAAG,KAAK;AACjB,aAAW,KAAK,YAAY;AAC1B,gBAAY,IAAI,GAAG,SAAS,IAAI,EAAE;AAClC,UAAM,QAAQ,iBAAiB,CAAC;AAChC,QAAI,MAAO,cAAa,IAAI,GAAG,KAAK;AAAA,EACtC;AACA,aAAW,KAAK,aAAa;AAC3B,QAAI,CAAC,UAAU,IAAI,EAAE,QAAQ,EAAG,WAAU,IAAI,EAAE,UAAU,OAAO,IAAI,EAAE;AAAA,EACzE;AAEA,QAAM,cAAwB,CAAC;AAC/B,aAAW,CAAC,IAAI,IAAI,KAAK;AACvB,gBAAY,KAAK,SAAS,IAAI,+BAA+B,aAAa,IAAI,OAAO,CAAC,MAAM;AAC9F,MAAI;AACF,gBAAY,KAAK,6CAA6C,aAAa,YAAAA,QAAK,KAAK,QAAQ,QAAQ,GAAG,OAAO,CAAC,MAAM;AACxH,QAAM,eAAe,oBAAI,IAAY;AACrC,aAAW,KAAK,aAAa;AAC3B,QAAI,aAAa,IAAI,EAAE,QAAQ,EAAG;AAClC,iBAAa,IAAI,EAAE,QAAQ;AAC3B,UAAM,OAAO,UAAU,IAAI,EAAE,QAAQ;AACrC,QAAI,CAAC,KAAM;AACX,gBAAY,KAAK,SAAS,IAAI,+BAA+B,aAAa,EAAE,UAAU,OAAO,CAAC,MAAM;AAAA,EACtG;AAEA,QAAM,WAAW,oBAAI,IAA8B;AACnD,aAAW,KAAK,aAAa;AAC3B,UAAM,MAAM,EAAE,QAAQ,KAAK,GAAG;AAC9B,QAAI,CAAC,SAAS,IAAI,GAAG,EAAG,UAAS,IAAI,KAAK,EAAE,SAAS,EAAE,SAAS,QAAQ,CAAC,EAAE,CAAC;AAC5E,aAAS,IAAI,GAAG,EAAG,OAAO,KAAK,CAAC;AAAA,EAClC;AAEA,QAAM,aAAuB,CAAC;AAC9B,aAAW,CAAC,EAAE,EAAE,SAAS,QAAQ,GAAG,CAAC,KAAK;AACxC,eAAW,KAAK,YAAY,SAAS,IAAI,aAAa,WAAW,cAAc,CAAC,CAAC;AAEnF,QAAM,WAAW,WACb,kGACA;AAKJ,QAAM,qBAAqB,KACvB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,KAwBA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAuBJ,QAAM,gBAAgB,KAClB;AAAA;AAAA;AAAA,KAIA;AAAA;AAAA;AAAA;AAKJ,SAAO;AAAA;AAAA;AAAA;AAAA;AAAA,EAKP,YAAY,KAAK,IAAI,CAAC;AAAA;AAAA;AAAA,EAGtB,kBAAkB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWlB,aAAa;AAAA;AAAA,EAEb,WAAW,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUhB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,WAAW,KAAK,IAAI,CAAC;AAAA,EACrB,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAMV;AAIA,SAAS,iBAAiB,QAA0B;AAClD,QAAM,SAAS,SAAS,QAAQ,YAAY;AAC5C,MAAI,CAAC,OAAQ,QAAO,CAAC;AACrB,MAAI,MAAM;AACV,MAAI;AAAE,UAAM,UAAAC,QAAG,aAAa,YAAAD,QAAK,KAAK,QAAQ,MAAM,GAAG,MAAM;AAAA,EAAG,QAC1D;AAAE,WAAO,CAAC;AAAA,EAAG;AAEnB,QAAM,WAAW,IAAI,QAAQ,uBAAuB;AACpD,MAAI,aAAa,GAAI,QAAO,CAAC;AAC7B,QAAM,aAAa,IAAI,QAAQ,KAAK,QAAQ;AAC5C,MAAI,eAAe,GAAI,QAAO,CAAC;AAE/B,MAAI,QAAQ,GAAG,MAAM;AACrB,WAAS,IAAI,YAAY,IAAI,IAAI,QAAQ,KAAK;AAC5C,QAAI,IAAI,CAAC,MAAM,IAAK;AAAA,aACX,IAAI,CAAC,MAAM,KAAK;AAAE;AAAS,UAAI,UAAU,GAAG;AAAE,cAAM;AAAG;AAAA,MAAO;AAAA,IAAE;AAAA,EAC3E;AACA,QAAM,QAAQ,IAAI,MAAM,YAAY,MAAM,CAAC;AAE3C,WAAS,aAAa,QAAgB,KAAiC;AACrE,UAAM,KAAQ,IAAI,OAAO,QAAQ,GAAG,mBAAmB;AACvD,UAAM,QAAQ,GAAG,KAAK,MAAM;AAC5B,QAAI,CAAC,MAAO,QAAO;AACnB,QAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,MAAM,CAAC,EAAE,SAAS;AAC/C,UAAM,QAAQ;AACd,WAAO,IAAI,OAAO,QAAQ,KAAK;AAC7B,UAAI,OAAO,CAAC,MAAM,IAAK;AAAA,eACd,OAAO,CAAC,MAAM,KAAK;AAAE;AAAK,YAAI,MAAM,EAAG,QAAO,OAAO,MAAM,OAAO,IAAI,CAAC;AAAA,MAAG;AAAA,IACrF;AACA,WAAO;AAAA,EACT;AAEA,WAAS,aAAa,QAAgB,KAAiC;AACrE,UAAM,KAAQ,IAAI,OAAO,QAAQ,GAAG,mBAAmB;AACvD,UAAM,QAAQ,GAAG,KAAK,MAAM;AAC5B,QAAI,CAAC,MAAO,QAAO;AACnB,QAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,MAAM,CAAC,EAAE,SAAS;AAC/C,UAAM,QAAQ;AACd,WAAO,IAAI,OAAO,QAAQ,KAAK;AAC7B,UAAI,OAAO,CAAC,MAAM,IAAK;AAAA,eACd,OAAO,CAAC,MAAM,KAAK;AAAE;AAAK,YAAI,MAAM,EAAG,QAAO,OAAO,MAAM,OAAO,IAAI,CAAC;AAAA,MAAG;AAAA,IACrF;AACA,WAAO;AAAA,EACT;AAEA,WAAS,IAAI,QAAgB,KAAiC;AAC5D,WAAO,OAAO;AAAA,MACZ,IAAI,OAAO,QAAQ,GAAG;AAAA,UAAwC;AAAA,IAChE,IAAI,CAAC;AAAA,EACP;AAEA,WAAS,cAAc,QAAgB,KAAiC;AACtE,UAAM,MAAM,aAAa,QAAQ,GAAG;AACpC,QAAI,CAAC,IAAK,QAAO;AACjB,WAAO,IAAI,MAAM,4BAA4B,IAAI,CAAC,KAC7C,IAAI,MAAM,kBAAkB,IAAI,CAAC;AAAA,EACxC;AAEA,WAAS,aAAa,QAAgB,KAAuB;AAC3D,UAAM,MAAM,aAAa,QAAQ,GAAG;AACpC,QAAI,CAAC,IAAK,QAAO,CAAC;AAClB,WAAO,CAAC,GAAG,IAAI,SAAS,mBAAmB,CAAC,EAAE,IAAI,OAAK,EAAE,CAAC,CAAC;AAAA,EAC7D;AAEA,QAAM,OAAiB,CAAC;AAExB,MAAI,IAAI,OAAO,OAAO,EAAS,MAAK,QAAc,IAAI,OAAO,OAAO;AACpE,MAAI,IAAI,OAAO,aAAa,EAAG,MAAK,cAAc,IAAI,OAAO,aAAa;AAC1E,MAAI,IAAI,OAAO,UAAU,EAAM,MAAK,WAAc,IAAI,OAAO,UAAU;AACvE,MAAI,IAAI,OAAO,YAAY,EAAI,MAAK,aAAc,IAAI,OAAO,YAAY;AACzE,MAAI,IAAI,OAAO,SAAS,EAAO,MAAK,UAAc,IAAI,OAAO,SAAS;AACtE,MAAI,IAAI,OAAO,QAAQ,EAAQ,MAAK,SAAc,IAAI,OAAO,QAAQ;AACrE,MAAI,IAAI,OAAO,WAAW,EAAK,MAAK,YAAc,IAAI,OAAO,WAAW;AACxE,MAAI,IAAI,OAAO,UAAU,EAAM,MAAK,WAAc,IAAI,OAAO,UAAU;AAEvE,QAAM,QAAQ,IAAI,OAAO,UAAU;AACnC,MAAI,OAAO;AACT,SAAK,WAAW;AAAA,EAClB,OAAO;AACL,UAAM,QAAQ,aAAa,OAAO,UAAU;AAC5C,QAAI,MAAM,OAAQ,MAAK,WAAW,MAAM,KAAK,IAAI;AAAA,EACnD;AAEA,QAAM,YAAY,IAAI,OAAO,QAAQ;AACrC,MAAI,WAAW;AACb,SAAK,SAAS;AAAA,EAChB,OAAO;AACL,UAAM,aAAa,aAAa,OAAO,SAAS;AAChD,QAAI,YAAY;AACd,YAAM,OAAO,WAAW,MAAM,6BAA6B,IAAI,CAAC;AAChE,UAAI,KAAM,MAAK,SAAS;AAAA,IAC1B;AAAA,EACF;AAEA,MAAI,CAAC,KAAK,WAAW;AACnB,UAAM,OAAO,MAAM,MAAM,sDAAsD,IAAI,CAAC;AACpF,QAAI,KAAM,MAAK,YAAY;AAAA,EAC7B;AAEA,QAAM,UAAU,aAAa,OAAO,WAAW;AAC/C,MAAI,SAAS;AACX,SAAK,YAAY;AAAA,MACf,OAAc,IAAI,SAAS,OAAO;AAAA,MAClC,aAAc,IAAI,SAAS,aAAa;AAAA,MACxC,KAAc,IAAI,SAAS,KAAK;AAAA,MAChC,MAAc,IAAI,SAAS,MAAM;AAAA,MACjC,OAAc,cAAc,SAAS,QAAQ,KAAK,IAAI,SAAS,OAAO;AAAA,IACxE;AAAA,EACF;AAEA,QAAM,UAAU,aAAa,OAAO,SAAS;AAC7C,MAAI,SAAS;AACX,SAAK,UAAU;AAAA,MACb,MAAc,IAAI,SAAS,MAAM;AAAA,MACjC,OAAc,IAAI,SAAS,OAAO;AAAA,MAClC,aAAc,IAAI,SAAS,aAAa;AAAA,MACxC,SAAc,IAAI,SAAS,SAAS;AAAA,MACpC,OAAc,cAAc,SAAS,QAAQ,KAAK,IAAI,SAAS,OAAO;AAAA,IACxE;AAAA,EACF;AAEA,QAAM,aAAa,aAAa,OAAO,OAAO;AAC9C,MAAI,YAAY;AACd,SAAK,QAAQ;AAAA,MACX,MAAU,mBAAmB,YAAY,MAAM;AAAA,MAC/C,UAAU,mBAAmB,YAAY,UAAU;AAAA,MACnD,OAAU,mBAAmB,YAAY,OAAO;AAAA,IAClD;AAAA,EACF;AAEA,SAAO;AACT;AAEA,SAAS,mBAAmB,QAAgB,KAA0B;AACpE,QAAM,MAAM,gBAAgB,QAAQ,GAAG;AACvC,MAAI,CAAC,IAAK,QAAO,CAAC;AAClB,QAAM,UAAuB,CAAC;AAC9B,QAAM,QAAQ;AACd,MAAI;AACJ,UAAQ,IAAI,MAAM,KAAK,GAAG,OAAO,MAAM;AACrC,UAAM,MAAM,EAAE,CAAC;AACf,UAAM,MAAM,IAAI,MAAM,4BAA4B,IAAI,CAAC;AACvD,QAAI,CAAC,IAAK;AACV,YAAQ,KAAK;AAAA,MACX;AAAA,MACA,MAAO,IAAI,MAAM,6BAA6B,IAAI,CAAC;AAAA,MACnD,OAAO,IAAI,MAAM,8BAA8B,IAAI,CAAC;AAAA,IACtD,CAAC;AAAA,EACH;AACA,MAAI,CAAC,QAAQ,QAAQ;AACnB,WAAO,CAAC,GAAG,IAAI,SAAS,mBAAmB,CAAC,EAAE,IAAI,QAAM,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;AAAA,EACxE;AACA,SAAO;AACT;AAEA,SAAS,gBAAgB,QAAgB,KAAiC;AACxE,QAAM,KAAQ,IAAI,OAAO,QAAQ,GAAG,mBAAmB;AACvD,QAAM,QAAQ,GAAG,KAAK,MAAM;AAC5B,MAAI,CAAC,MAAO,QAAO;AACnB,MAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,MAAM,CAAC,EAAE,SAAS;AAC/C,QAAM,QAAQ;AACd,SAAO,IAAI,OAAO,QAAQ,KAAK;AAC7B,QAAI,OAAO,CAAC,MAAM,IAAK;AAAA,aACd,OAAO,CAAC,MAAM,KAAK;AAAE;AAAK,UAAI,MAAM,EAAG,QAAO,OAAO,MAAM,OAAO,IAAI,CAAC;AAAA,IAAG;AAAA,EACrF;AACA,SAAO;AACT;AAIA,SAAS,cAAc,KAAa,YAAY,IAAgB;AAC9D,QAAM,SAAqB,CAAC;AAC5B,MAAI,CAAC,UAAAC,QAAG,WAAW,GAAG,EAAG,QAAO;AAEhC,MAAI;AACJ,MAAI;AAAE,cAAU,UAAAA,QAAG,YAAY,KAAK,EAAE,eAAe,KAAK,CAAC;AAAA,EAAG,QACxD;AAAE,WAAO;AAAA,EAAQ;AAEvB,aAAW,SAAS,SAAS;AAC3B,QAAI,MAAM,KAAK,WAAW,GAAG,KAAK,MAAM,KAAK,WAAW,GAAG,EAAG;AAC9D,UAAM,WAAW,YAAAD,QAAK,KAAK,KAAK,MAAM,IAAI;AAE1C,QAAI,MAAM,YAAY,GAAG;AACvB,YAAME,cAAa,MAAM,KAAK,WAAW,MAAM,KAAK,MAAM,KAAK,SAAS,GAAG;AAC3E,YAAMC,aAAa,MAAM,KAAK,WAAW,GAAG,KAAK,MAAM,KAAK,SAAS,GAAG;AACxE,YAAM,UAAaD,cAAa,MAAMC,aAAY,IAAI,MAAM,KAAK,MAAM,GAAG,EAAE,CAAC,KAAK,MAAM;AACxF,aAAO,KAAK,GAAG,cAAc,UAAU,GAAG,SAAS,IAAI,OAAO,EAAE,CAAC;AACjE;AAAA,IACF;AAEA,UAAM,MAAO,YAAAH,QAAK,QAAQ,MAAM,IAAI;AACpC,UAAM,OAAO,YAAAA,QAAK,SAAS,MAAM,MAAM,GAAG;AAC1C,QAAI,CAAE,SAA+B,SAAS,GAAG,EAAG;AAEpD,UAAM,aAAa,KAAK,WAAW,MAAM,KAAK,KAAK,SAAS,GAAG;AAC/D,UAAM,YAAa,KAAK,WAAW,GAAG,KAAK,KAAK,SAAS,GAAG;AAC5D,UAAM,YAAa,aACf,GAAG,SAAS,OACZ,SAAS,UACP,aAAa,MACb,YACE,GAAG,SAAS,KAAK,KAAK,MAAM,GAAG,EAAE,CAAC,KAClC,GAAG,SAAS,IAAI,IAAI;AAE5B,WAAO,KAAK,EAAE,WAAW,UAAU,SAAS,CAAC;AAAA,EAC/C;AAEA,SAAO;AACT;AAIA,SAAS,WAAW,SAAiB,UAAiD;AACpF,QAAM,WAAW,QAAQ,MAAM,GAAG,EAAE,OAAO,OAAO;AAClD,QAAM,WAAW,SAAS,MAAM,GAAG,EAAE,OAAO,OAAO;AAEnD,QAAM,aAAa,SAAS,SAAS,SAAS,CAAC,MAAM;AACrD,MAAI,YAAY;AACd,UAAM,SAAS,SAAS,MAAM,GAAG,EAAE;AACnC,QAAI,SAAS,SAAS,OAAO,OAAQ,QAAO;AAC5C,aAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;AACtC,UAAI,OAAO,CAAC,EAAE,WAAW,GAAG,EAAG;AAC/B,UAAI,OAAO,CAAC,MAAM,SAAS,CAAC,EAAG,QAAO;AAAA,IACxC;AACA,WAAO,EAAE,KAAK,SAAS,MAAM,OAAO,MAAM,EAAE,KAAK,GAAG,EAAE;AAAA,EACxD;AAEA,MAAI,SAAS,WAAW,SAAS,OAAQ,QAAO;AAEhD,QAAM,SAAiC,CAAC;AACxC,WAAS,IAAI,GAAG,IAAI,SAAS,QAAQ,KAAK;AACxC,QAAI,SAAS,CAAC,EAAE,WAAW,GAAG,GAAG;AAC/B,aAAO,SAAS,CAAC,EAAE,MAAM,CAAC,CAAC,IAAI,mBAAmB,SAAS,CAAC,CAAC;AAAA,IAC/D,WAAW,SAAS,CAAC,MAAM,SAAS,CAAC,GAAG;AACtC,aAAO;AAAA,IACT;AAAA,EACF;AACA,SAAO;AACT;AAEA,IAAM,cAAc,oBAAI,IAAiD;AAEzE,eAAe,cAAc,UAAoC;AAC/D,QAAM,EAAE,cAAc,IAAI,MAAM,OAAO,KAAK;AAC5C,MAAI,QAAQ;AACZ,MAAI;AAAE,YAAQ,UAAAC,QAAG,SAAS,QAAQ,EAAE;AAAA,EAAS,QAAQ;AAAA,EAAsB;AAE3E,QAAM,SAAS,YAAY,IAAI,QAAQ;AACvC,MAAI,UAAU,OAAO,UAAU,MAAO,QAAO,OAAO;AAEpD,QAAM,MAAU,MAAM,OAAO,cAAc,QAAQ,EAAE,OAAO,QAAQ;AACpE,QAAM,UAAU,IAAI,WAAW;AAC/B,cAAY,IAAI,UAAU,EAAE,OAAO,QAAQ,CAAC;AAC5C,SAAO;AACT;AAEA,eAAe,iBACb,KACA,KACA,MACA,QACA,YACA,UACA,UACA;AACA,MAAI;AACF,QAAI,cAAc,IAAI,WAAW,WAAW;AAC1C,UAAI,aAAa;AACjB,UAAI,UAAU,+BAA+B,GAAG;AAChD,UAAI,UAAU,gCAAgC,mCAAmC;AACjF,UAAI,UAAU,gCAAgC,4BAA4B;AAC1E,UAAI,UAAU,0BAA0B,OAAO;AAC/C,UAAI,IAAI;AACR;AAAA,IACF;AAEA,QAAI,QAAQ,SAAS;AACrB,QAAI,CAAC,OAAO;AACV,cAAQ,EAAE,QAAQ,cAAc,QAAQ,MAAM,EAAE;AAChD,eAAS,KAAK;AAAA,IAChB;AAEA,UAAM,OAAW,IAAI,QAAQ,QAAQ;AACrC,UAAM,MAAW,UAAU,IAAI,GAAG,IAAI,GAAG;AACzC,UAAM,WAAW,IAAI,IAAI,GAAG,EAAE;AAE9B,UAAM,SAAmB,CAAC;AAC1B,qBAAiB,SAAS,IAAK,QAAO,KAAK,KAAe;AAC1D,UAAM,OAAO,OAAO,SAAS,IAAI,OAAO,OAAO,MAAM,IAAI;AAEzD,UAAM,SAAU,IAAI,OAAkB,YAAY;AAElD,UAAM,SAAS,IAAI,QAAQ,KAAK;AAAA,MAC9B;AAAA,MACA,SAAS,IAAI;AAAA,MACb,MAAS,CAAC,CAAC,OAAO,MAAM,EAAE,SAAS,MAAM,KAAK,MAAM,SAAS,OAAO;AAAA,IACtE,CAAC;AAED,eAAW,SAAS,MAAM,QAAQ;AAChC,YAAM,UAAU,MAAM,cAAc,MAAM,QAAQ;AAClD,UAAI,CAAC,QAAS;AAEd,UAAI;AACJ,UAAI;AACF,YAAI,OAAQ,QAAgB,UAAU,YAAY;AAChD,mBAAS,MAAO,QAAgB,MAAM,OAAO,MAAM,CAAC;AACpD,cAAI,OAAO,WAAW,IAAK;AAAA,QAC7B,WAAW,OAAO,YAAY,YAAY;AACxC,gBAAM,SAAS,WAAW,MAAM,WAAW,QAAQ;AACnD,cAAI,WAAW,KAAM;AAErB,gBAAM,kBAA0C,CAAC;AACjD,iBAAO,QAAQ,QAAQ,CAAC,GAAG,MAAM;AAAE,4BAAgB,CAAC,IAAI;AAAA,UAAG,CAAC;AAC5D,gBAAM,gBAAgB,IAAI,QAAQ,OAAO,MAAM,GAAG;AAAA,YAChD,SAAS,EAAE,GAAG,iBAAiB,iBAAiB,KAAK,UAAU,MAAM,EAAE;AAAA,UACzE,CAAC;AAED,mBAAS,MAAO,QAAkD,aAAa;AAAA,QACjF,OAAO;AACL;AAAA,QACF;AAAA,MACF,QAAQ;AACN;AAAA,MACF;AAEA,YAAM,eAAuC,CAAC;AAC9C,aAAO,QAAQ,QAAQ,CAAC,GAAG,MAAM;AAAE,qBAAa,CAAC,IAAI;AAAA,MAAG,CAAC;AACzD,UAAI,YAAY;AACd,qBAAa,6BAA6B,IAAK;AAC/C,qBAAa,8BAA8B,IAAI;AAC/C,qBAAa,8BAA8B,IAAI;AAAA,MACjD;AAEA,UAAI,aAAa,OAAO;AACxB,iBAAW,CAAC,GAAG,CAAC,KAAK,OAAO,QAAQ,YAAY,EAAG,KAAI,UAAU,GAAG,CAAC;AACrE,UAAI,IAAI,OAAO,KAAK,MAAM,OAAO,YAAY,CAAC,CAAC;AAC/C;AAAA,IACF;AAEA,QAAI,aAAa;AACjB,QAAI,UAAU,gBAAgB,kBAAkB;AAChD,QAAI,IAAI,KAAK,UAAU,EAAE,OAAO,4BAA4B,IAAI,GAAG,GAAG,CAAC,CAAC;AAAA,EAC1E,SAAS,GAAQ;AACf,SAAK,CAAC;AAAA,EACR;AACF;AAgBA,IAAM,WAA4C;AAAA,EAEhD,SAAS;AAAA,IACP,YAAiB;AAAA;AAAA,IACjB,YAAiB;AAAA,IACjB,SAAiB,CAAC,QAAQ,YAAAD,QAAK,KAAK,KAAK,WAAW,kBAAkB,QAAQ;AAAA,IAC9E,iBAAiB;AAAA,IACjB,aAAiB;AAAA,EACnB;AAAA,EAEA,YAAY;AAAA,IACV,YAAiB;AAAA,IACjB,SAAiB,CAAC,QAAQ,YAAAA,QAAK,KAAK,KAAK,WAAW;AAAA,IACpD,iBAAiB;AAAA,EACnB;AAAA,EAEA,MAAM;AAAA,IACJ,KAAiB;AAAA,IACjB,YAAiB;AAAA;AAAA,IACjB,YAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IACjB,SAAiB,CAAC,QAAQ,YAAAA,QAAK,KAAK,KAAK,UAAU,UAAU;AAAA,IAC7D,iBAAiB;AAAA,EACnB;AAAA,EAEA,MAAM;AAAA,IACJ,YAAiB;AAAA,IACjB,YAAiB;AAAA,IACjB,SAAiB,CAAC,QAAQ,YAAAA,QAAK,KAAK,KAAK,UAAU,UAAU;AAAA,IAC7D,iBAAiB;AAAA,IACjB,aAAiB;AAAA,EACnB;AAAA,EAEA,KAAK;AAAA,IACH,YAAiB;AAAA,IACjB,SAAiB,CAAC,QAAQ,YAAAA,QAAK,KAAK,KAAK,UAAU,UAAU;AAAA,IAC7D,iBAAiB;AAAA,EACnB;AAAA,EAEA,KAAK;AAAA,IACH,KAAiB;AAAA,IACjB,YAAiB;AAAA,IACjB,YAAiB;AAAA,IACjB,SAAiB,CAAC,QAAQ,YAAAA,QAAK,KAAK,KAAK,YAAY;AAAA,IACrD,iBAAiB;AAAA,EACnB;AACF;AAEA,SAAS,aAAa,UAA0B;AAC9C,QAAM,UAAU,SAAS,QAAQ;AACjC,MAAI,CAAC,QAAQ,IAAK;AAClB,MAAI;AACF,YAAQ,QAAQ,QAAQ,KAAK,EAAE,OAAO,CAAC,QAAQ,IAAI,CAAC,EAAE,CAAC;AAAA,EACzD,QAAQ;AACN,YAAQ,MAAM;AAAA,8DACuC,QAAQ;AAAA,qBAC5C,QAAQ,GAAG;AAAA,CAC/B;AACG,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF;AAEA,SAAS,uBACP,UACA,SACA,aACQ;AACR,QAAM,MAAM,KAAK,YAAAA,QAAK,SAAS,YAAAA,QAAK,QAAQ,OAAO,GAAG,QAAQ,CAAC;AAC/D,MAAI,aAAa;AACf,UAAM,SAAS,IAAI,QAAQ,UAAU,KAAK;AAC1C,WAAO,OAAO,WAAW,GAAG,IAAI,SAAS,KAAK,MAAM;AAAA,EACtD;AACA,QAAM,WAAW,IAAI,QAAQ,sBAAsB,EAAE;AACrD,SAAO,SAAS,WAAW,GAAG,IAAI,WAAW,KAAK,QAAQ;AAC5D;AAEA,SAAS,kBACP,QACA,SACA,YACA,UACgG;AAChG,QAAM,UAAuB,CAAC;AAC9B,QAAM,YAAuB,CAAC;AAC9B,QAAM,UAAa,SAAS,QAAQ;AACpC,QAAM,EAAE,iBAAiB,cAAc,MAAM,IAAI;AACjD,QAAM,YAAa,aAAa;AAEhC,WAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;AACtC,UAAM,QAAQ,OAAO,CAAC;AACtB,UAAM,MAAQ,uBAAuB,MAAM,UAAU,SAAS,WAAW;AACzE,UAAM,OAAQ,SAAS,CAAC;AAExB,QAAI,MAAM;AACV,QAAI;AAAE,YAAM,UAAAC,QAAG,aAAa,MAAM,UAAU,MAAM;AAAA,IAAG,QAAQ;AAAA,IAAa;AAC1E,UAAM,YAAY,IAAI,SAAS,aAAa,KAAK,IAAI,SAAS,aAAa;AAE3E,YAAQ,KAAK,UAAU,IAAI,UAAU,GAAG,IAAI;AAE5C,QAAI,WAAW;AACb,gBAAU,KAAK,kBAAkB,IAAI,IAAI;AAAA,IAC3C,OAAO;AACL,YAAM,YAAY,kBAAkB,MAAM,YAAY,OAAO,MAAM,SAAS;AAC5E,gBAAU,KAAK,YAAY,SAAS,qCAAqC,IAAI,gEAAgE;AAAA,IAC/I;AAAA,EACF;AAEA,QAAM,cAAc,kBAAkB,OAAO;AAC7C,QAAM,WAAc,aAChB,YACE,YAAY,WAAW,kXACvB,YAAY,WAAW,8IACzB;AAEJ,QAAM,aAAa,cAAc,CAAC,YAAY,sCAAsC;AAEpF,SAAO,EAAE,SAAS,WAAW,UAAU,WAAW;AACpD;AAEA,SAAS,qBAAqB,WAAmB,UAAoB,YAA2B;AAC9F,MAAI,CAAC,UAAAA,QAAG,WAAW,SAAS,EAAG;AAE/B,QAAM,SAAS,cAAc,SAAS;AACtC,QAAM,MAAS,QAAQ,IAAI;AAE3B,eAAa,QAAQ;AAErB,QAAM,UAAU,SAAS,QAAQ;AACjC,QAAM,UAAU,QAAQ,QAAQ,GAAG;AAEnC,QAAM,EAAE,SAAS,WAAW,UAAU,WAAW,IAAI,kBAAkB,QAAQ,SAAS,YAAY,QAAQ;AAE5G,QAAM,YAAY,aAAa;AAC/B,QAAM,QAAQ;AAAA,IACZ;AAAA,IACA;AAAA,IACA,GAAI,YAAY,CAAC,IAAI,CAAC,8BAA8B;AAAA,IACpD,GAAI,QAAQ,aAAa,QAAQ,WAAW,MAAM,IAAI,IAAI,CAAC;AAAA,IAC3D,GAAI,aAAa,CAAC,UAAU,IAAI,CAAC;AAAA,IACjC,GAAG;AAAA,IACH;AAAA,IACA;AAAA,IACA,GAAI,WAAW,CAAC,QAAQ,IAAI,CAAC;AAAA,IAC7B,GAAG;AAAA,IACH;AAAA,IACA,GAAG,QAAQ,WAAW,MAAM,IAAI;AAAA,EAClC;AAEA,YAAAA,QAAG,UAAU,YAAAD,QAAK,QAAQ,OAAO,GAAG,EAAE,WAAW,KAAK,CAAC;AACvD,YAAAC,QAAG,cAAc,SAAS,MAAM,KAAK,IAAI,IAAI,MAAM,MAAM;AACzD,UAAQ,IAAI,kCAA6B,KAAK,YAAAD,QAAK,SAAS,KAAK,OAAO,CAAC,CAAC,EAAE;AAC9E;AAIO,SAAS,UAAU,UAA6B,CAAC,GAAW;AACjE,QAAM,EAAE,MAAM,aAAa,MAAM,SAAS,IAAI;AAE9C,QAAM,YAAY,MAAM,YAAAA,QAAK,KAAK,QAAQ,IAAI,GAAG,QAAQ,UAAU,SAAS;AAC5E,QAAM,YAAY,MAAM,YAAAA,QAAK,KAAK,QAAQ,IAAI,GAAG,QAAQ,UAAU,aAAa;AAEhF,MAAI,gBAA0D;AAC9D,MAAI,oBAAoB;AACxB,MAAI,YAAmD;AACvD,QAAM,WAAkB,oBAAI,IAAoB;AAEhD,WAAS,cAAc,MAAc,OAAwB;AAC3D,UAAM,MAAM,GAAG,IAAI,IAAI,KAAK;AAC5B,UAAM,MAAM,KAAK,IAAI;AACrB,QAAI,OAAO,SAAS,IAAI,GAAG,KAAK,KAAK,eAAgB,QAAO;AAC5D,aAAS,IAAI,KAAK,GAAG;AACrB,eAAW,CAAC,GAAG,CAAC,KAAK,SAAU,KAAI,MAAM,IAAI,aAAc,UAAS,OAAO,CAAC;AAC5E,WAAO;AAAA,EACT;AAEA,WAAS,WAAW,GAAoB;AACtC,UAAM,KAAO,KAAK,CAAC;AACnB,UAAM,OAAO,YAAAA,QAAK,SAAS,GAAG,YAAAA,QAAK,QAAQ,CAAC,CAAC;AAC7C,UAAM,MAAO,YAAAA,QAAK,QAAQ,CAAC;AAC3B,QAAI,CAAE,eAAqC,SAAS,GAAG,EAAG,QAAO;AACjE,QAAI,CAAC,QAAQ,IAAI,KAAK,UAAU,CAAC,CAAC,EAAG,QAAO;AAC5C,QAAI,QAAQ,IAAI,KAAK,UAAU,CAAC,CAAC,EAAG,QAAO;AAC3C,QAAI,KAAK,WAAW,GAAG,EAAG,QAAO;AACjC,WAAO;AAAA,EACT;AAEA,WAAS,UAAU,GAAoB;AACrC,UAAM,KAAK,KAAK,CAAC;AACjB,WAAO,QAAQ,IAAI,KAAK,UAAU,CAAC,CAAC,KACjC,SAA+B,SAAS,YAAAA,QAAK,QAAQ,CAAC,CAAC;AAAA,EAC5D;AAEA,WAAS,WAA0B;AACjC,UAAM,MAAM,UAAU;AACtB,QAAI,CAAC,UAAAC,QAAG,WAAW,GAAG,EAAG,QAAO;AAChC,UAAM,OAAO,YAAY,GAAG;AAC5B,QAAI,SAAS,kBAAmB,QAAO;AACvC,cAAAA,QAAG,cAAc,WAAW,GAAG,MAAM,MAAM;AAC3C,wBAAoB;AACpB,WAAO;AAAA,EACT;AAEA,WAAS,cAAc,QAAuB,QAAQ,aAAa;AACjE,QAAI,cAAe,cAAa,aAAa;AAC7C,oBAAgB,WAAW,MAAM;AAC/B,sBAAgB;AAChB,UAAI,SAAS,MAAM,MAAM;AACvB,eAAO,GAAG,KAAK,EAAE,MAAM,eAAe,MAAM,IAAI,CAAC;AAAA,MACnD;AAAA,IACF,GAAG,KAAK;AAAA,EACV;AAEA,WAAS,eAAe,QAA8B;AACpD,WAAO,YAAY,IAAI,CAAC,KAAU,KAAU,SAAc;AACxD,YAAM,MAAM,IAAI;AAChB,UAAI,IAAI,WAAW,MAAM,KAAK,IAAI,SAAS,GAAG,EAAG,QAAO,KAAK;AAC7D,UAAI,MAAM;AACV,WAAK;AAAA,IACP,CAAC;AAAA,EACH;AAEA,SAAO;AAAA,IACL,MAAS;AAAA,IACT,SAAS;AAAA,IAET,UAAU,MAAM,IAAI;AAClB,YAAM,MAAM,KAAK,EAAE;AACnB,UAAI,CAAC,QAAQ,KAAK,KAAK,UAAU,CAAC,CAAC,EAAG;AACtC,YAAM,MAAM,YAAAD,QAAK,QAAQ,EAAE;AAC3B,UAAI,CAAE,eAAqC,SAAS,GAAG,EAAG;AAC1D,UAAI,CAAC,KAAK,SAAS,uBAAuB,EAAG;AAE7C,UAAI,SAAS;AACb,UAAI,MAAS,OAAO,QAAQ,uBAAuB;AAEnD,aAAO,QAAQ,IAAI;AACjB,cAAM,WAAW,OAAO,QAAQ,KAAK,GAAG;AACxC,YAAI,aAAa,GAAI;AAErB,YAAI,QAAQ,GAAG,MAAM;AACrB,iBAAS,IAAI,UAAU,IAAI,OAAO,QAAQ,KAAK;AAC7C,cAAI,OAAO,CAAC,MAAM,IAAU;AAAA,mBACnB,OAAO,CAAC,MAAM,KAAK;AAAE;AAAS,gBAAI,UAAU,GAAG;AAAE,oBAAM;AAAG;AAAA,YAAO;AAAA,UAAE;AAAA,QAC9E;AAEA,YAAI,OAAO,MAAM;AACjB,eAAO,OAAO,OAAO,WAAW,OAAO,IAAI,MAAM,OAAO,OAAO,IAAI,MAAM,KAAO;AAChF,YAAI,OAAO,OAAO,UAAU,OAAO,IAAI,MAAM,IAAK;AAClD,eAAO,OAAO,OAAO,WAAW,OAAO,IAAI,MAAM,QAAQ,OAAO,IAAI,MAAM,MAAO;AAEjF,iBAAS,OAAO,MAAM,GAAG,GAAG,IAAI,OAAO,MAAM,IAAI;AACjD,cAAS,OAAO,QAAQ,yBAAyB,GAAG;AAAA,MACtD;AAEA,aAAO,EAAE,MAAM,QAAQ,KAAK,KAAK;AAAA,IACnC;AAAA,IAEA,SAAa;AAAE,eAAS;AAAA,IAAG;AAAA,IAC3B,aAAa;AAAE,eAAS;AAAA,IAAG;AAAA,IAE3B,cAAc;AACZ,UAAI,SAAU,sBAAqB,UAAU,GAAG,UAAU,UAAU;AAAA,IACtE;AAAA,IAEA,WAAW;AACT,kBAAY;AACZ,kBAAY,MAAM;AAClB,UAAI,eAAe;AAAE,qBAAa,aAAa;AAAG,wBAAgB;AAAA,MAAM;AAAA,IAC1E;AAAA,IAEA,MAAM,gBAAgB,QAAQ;AAC5B,YAAM,SAAS,UAAU;AACzB,YAAM,SAAS,UAAU;AAEzB,UAAI,CAAC,UAAAC,QAAG,WAAW,MAAM,EAAG;AAE5B,aAAO,QAAQ,IAAI,MAAM;AAEzB,aAAO,QAAQ,GAAG,OAAU,OAAK,WAAW,CAAC,KAAK,cAAc,GAAG,KAAK,KAAQ,cAAc,QAAQ,GAAG,CAAC;AAC1G,aAAO,QAAQ,GAAG,UAAU,OAAK,WAAW,CAAC,KAAK,cAAc,GAAG,QAAQ,KAAK,cAAc,MAAM,CAAC;AACrG,aAAO,QAAQ,GAAG,UAAU,OAAK,WAAW,CAAC,KAAK,cAAc,GAAG,QAAQ,KAAK,cAAc,MAAM,CAAC;AAErG,aAAO,QAAQ,GAAG,UAAU,OAAK;AAC/B,cAAM,OAAY,YAAAD,QAAK,SAAS,GAAG,YAAAA,QAAK,QAAQ,CAAC,CAAC;AAClD,cAAM,YAAY,YAAAA,QAAK,QAAQ,YAAAA,QAAK,QAAQ,CAAC,CAAC,MAAM,YAAAA,QAAK,QAAQ,MAAM;AACvE,YAAI,CAAC,aAAa,SAAS,SAAU;AACrC,eAAO,YAAY,cAAc;AACjC,eAAO,GAAG,KAAK,EAAE,MAAM,eAAe,MAAM,IAAI,CAAC;AAAA,MACnD,CAAC;AAED,aAAO,QAAQ,GAAG,UAAU,OAAK;AAC/B,cAAM,KAAK,KAAK,CAAC;AACjB,YAAI,CAAC,QAAQ,IAAI,KAAK,MAAM,CAAC,KAAK,EAAE,SAAS,cAAc,KAAK,QAAQ,IAAI,KAAK,MAAM,CAAC,EAAG;AAC3F,mBAAW,MAAM,WAAW,KAAK,OAAK,UAAAC,QAAG,WAAW,YAAAD,QAAK,KAAK,GAAG,CAAC,CAAC,CAAC,KAAK,cAAc,MAAM,GAAG,GAAG;AAAA,MACrG,CAAC;AAED,aAAO,QAAQ,GAAG,aAAa,OAAK;AAClC,cAAM,KAAK,KAAK,CAAC;AACjB,YAAI,QAAQ,IAAI,KAAK,MAAM,CAAC,KAAK,CAAC,EAAE,SAAS,cAAc,KAAK,CAAC,QAAQ,IAAI,KAAK,MAAM,CAAC;AACvF,wBAAc,MAAM;AAAA,MACxB,CAAC;AAED,UAAI,UAAAC,QAAG,WAAW,MAAM,GAAG;AACzB,eAAO,QAAQ,IAAI,MAAM;AAEzB,cAAM,WAAW,CAAC,MAAe;AAC/B,sBAAY;AACZ,cAAI,EAAG,aAAY,OAAO,CAAC;AAC3B,iBAAO,GAAG,KAAK,EAAE,MAAM,eAAe,MAAM,IAAI,CAAC;AAAA,QACnD;AAEA,eAAO,QAAQ,GAAG,OAAU,OAAK,UAAU,CAAC,KAAK,SAAS,CAAC,CAAC;AAC5D,eAAO,QAAQ,GAAG,UAAU,OAAK,UAAU,CAAC,KAAK,SAAS,CAAC,CAAC;AAC5D,eAAO,QAAQ,GAAG,UAAU,OAAK,UAAU,CAAC,KAAK,SAAS,CAAC,CAAC;AAE5D,eAAO,YAAY,IAAI,CAAC,KAAU,KAAU,SAAc;AACxD,cAAI,CAAC,IAAI,KAAK,WAAW,MAAM,EAAG,QAAO,KAAK;AAC9C;AAAA,YAAiB;AAAA,YAAK;AAAA,YAAK;AAAA,YAAM;AAAA,YAAQ;AAAA,YACvC,MAAM;AAAA,YAAW,CAAC,MAAM;AAAE,0BAAY;AAAA,YAAG;AAAA,UAAC;AAAA,QAC9C,CAAC;AAAA,MACH;AAAA,IACF;AAAA,IAEA,MAAM,uBAAuB,QAAQ;AACnC,qBAAe,MAAM;AAErB,YAAM,SAAS,UAAU;AACzB,UAAI,CAAC,UAAAA,QAAG,WAAW,MAAM,EAAG;AAC5B,aAAO,YAAY,IAAI,CAAC,KAAU,KAAU,SAAc;AACxD,YAAI,CAAC,IAAI,KAAK,WAAW,MAAM,EAAG,QAAO,KAAK;AAC9C;AAAA,UAAiB;AAAA,UAAK;AAAA,UAAK;AAAA,UAAM;AAAA,UAAQ;AAAA,UACvC,MAAM;AAAA,UAAW,CAAC,MAAM;AAAE,wBAAY;AAAA,UAAG;AAAA,QAAC;AAAA,MAC9C,CAAC;AAAA,IACH;AAAA,IAEA,oBAAoB;AAAA,MAClB,OAAO;AAAA,MACP,QAAQ,MAAM;AACZ,cAAM,OAAO,iBAAiB,UAAU,CAAC;AAEzC,YAAI,CAAC,KAAK,SAAS,CAAC,KAAK,eAAe,CAAC,KAAK,aAAa,CAAC,KAAK,YAC7D,CAAC,KAAK,WAAW,SAAS,CAAC,KAAK,OAAO,MAAM,QAAQ;AACvD,iBAAO;AAAA,QACT;AAEA,cAAM,QAAQ,KAAK,SAAY;AAC/B,cAAM,KAAQ,KAAK,YAAY;AAE/B,cAAM,QAAkB,CAAC;AAEzB,cAAM,KAAK,kBAAkB,KAAK,WAAW,OAAO,MAAM;AAC1D,cAAM,KAAK,kCAAkC,EAAE,MAAM;AACrD,cAAM,KAAK,UAAU,KAAK,UAAU;AACpC,YAAI,KAAK,YAAa,OAAM,KAAK,qCAAqC,KAAK,WAAW,MAAM;AAC5F,YAAI,KAAK,WAAa,OAAM,KAAK,qCAAqC,KAAK,UAAU,MAAM;AAC3F,YAAI,KAAK,OAAa,OAAM,KAAK,gCAAgC,KAAK,MAAM,MAAM;AAClF,YAAI,KAAK,SAAa,OAAM,KAAK,kCAAkC,KAAK,QAAQ,MAAM;AACtF,YAAI,KAAK,OAAa,OAAM,KAAK,gCAAgC,KAAK,MAAM,MAAM;AAClF,YAAI,KAAK,UAAa,OAAM,KAAK,+BAA+B,KAAK,SAAS,MAAM;AACpF,YAAI,KAAK,SAAa,OAAM,KAAK,8BAA8B,KAAK,QAAQ,MAAM;AAElF,mBAAW,SAAS,KAAK,OAAO,QAAQ,CAAC,GAAG;AAC1C,gBAAM,OAAQ,MAAM,OAAQ,UAAU,MAAM,IAAI,MAAQ;AACxD,gBAAM,QAAQ,MAAM,QAAQ,WAAW,MAAM,KAAK,MAAM;AACxD,gBAAM,KAAK,0BAA0B,MAAM,GAAG,IAAI,IAAI,GAAG,KAAK,KAAK;AAAA,QACrE;AACA,mBAAW,SAAS,KAAK,OAAO,YAAY,CAAC,GAAG;AAC9C,gBAAM,KAAK,mCAAmC,MAAM,GAAG,MAAM;AAAA,QAC/D;AACA,mBAAW,SAAS,KAAK,OAAO,SAAS,CAAC,GAAG;AAC3C,gBAAM,QAAQ,MAAM,QAAQ,WAAW,MAAM,KAAK,MAAM;AACxD,gBAAM,OAAQ,MAAM,OAAQ,UAAU,MAAM,IAAI,MAAQ;AACxD,gBAAM,KAAK,sCAAsC,MAAM,GAAG,IAAI,KAAK,GAAG,IAAI,KAAK;AAAA,QACjF;AAEA,YAAI,KAAK,WAAW,OAAO;AACzB,gBAAM,KAAK,4CAA4C,KAAK,UAAU,QAAQ,SAAS,MAAM;AAC7F,gBAAM,KAAK,4CAA4C,KAAK,UAAU,KAAK,MAAM;AACjF,cAAI,KAAK,UAAU,YAAa,OAAM,KAAK,4CAA4C,KAAK,UAAU,WAAW,MAAM;AACvH,cAAI,KAAK,UAAU,IAAa,OAAM,KAAK,4CAA4C,KAAK,UAAU,GAAG,MAAM;AAC/G,cAAI,KAAK,UAAU,MAAa,OAAM,KAAK,4CAA4C,KAAK,UAAU,KAAK,MAAM;AAAA,QACnH;AAEA,YAAI,KAAK,SAAS,OAAO;AACvB,gBAAM,KAAK,6CAA6C,KAAK,QAAQ,QAAQ,qBAAqB,MAAM;AACxG,gBAAM,KAAK,6CAA6C,KAAK,QAAQ,KAAK,MAAM;AAChF,cAAI,KAAK,QAAQ,YAAa,OAAM,KAAK,6CAA6C,KAAK,QAAQ,WAAW,MAAM;AACpH,cAAI,KAAK,QAAQ,QAAa,OAAM,KAAK,6CAA6C,KAAK,QAAQ,OAAO,MAAM;AAChH,cAAI,KAAK,QAAQ,MAAa,OAAM,KAAK,6CAA6C,KAAK,QAAQ,KAAK,MAAM;AAAA,QAChH;AAEA,cAAM,WAAW,MAAM,IAAI,OAAK,OAAO,CAAC,EAAE,EAAE,KAAK,IAAI;AACrD,eAAO,KAAK,QAAQ,WAAW,GAAG,QAAQ;AAAA,UAAa;AAAA,MACzD;AAAA,IACF;AAAA,EACF;AACF;AAEA,IAAO,gBAAQ;","names":["path","fs","isCatchAll","isDynamic"]}
|
package/dist/index.js
CHANGED
|
@@ -72,9 +72,38 @@ function isUsableLayout(filePath) {
|
|
|
72
72
|
function findFile(dir, candidates) {
|
|
73
73
|
return candidates.find((f) => fs.existsSync(path.join(dir, f))) ?? null;
|
|
74
74
|
}
|
|
75
|
+
function isTypeScriptProject() {
|
|
76
|
+
const cwd = process.cwd();
|
|
77
|
+
if (fs.existsSync(path.join(cwd, "src/main.tsx")) || fs.existsSync(path.join(cwd, "src/main.ts"))) return true;
|
|
78
|
+
if (fs.existsSync(path.join(cwd, "src/main.jsx")) || fs.existsSync(path.join(cwd, "src/main.js"))) return false;
|
|
79
|
+
const appDir = path.join(cwd, "src/app");
|
|
80
|
+
if (fs.existsSync(appDir)) {
|
|
81
|
+
const hasTsFile = (dir) => {
|
|
82
|
+
let entries;
|
|
83
|
+
try {
|
|
84
|
+
entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
85
|
+
} catch {
|
|
86
|
+
return false;
|
|
87
|
+
}
|
|
88
|
+
for (const entry of entries) {
|
|
89
|
+
if (entry.isDirectory()) {
|
|
90
|
+
if (hasTsFile(path.join(dir, entry.name))) return true;
|
|
91
|
+
} else {
|
|
92
|
+
const ext = path.extname(entry.name);
|
|
93
|
+
if (ext === ".tsx" || ext === ".ts") return true;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return false;
|
|
97
|
+
};
|
|
98
|
+
if (hasTsFile(appDir)) return true;
|
|
99
|
+
}
|
|
100
|
+
return false;
|
|
101
|
+
}
|
|
75
102
|
function getAppFile() {
|
|
76
103
|
const ts = path.join(process.cwd(), "src/App.tsx");
|
|
77
|
-
|
|
104
|
+
const jsx = path.join(process.cwd(), "src/App.jsx");
|
|
105
|
+
if (fs.existsSync(ts)) return ts;
|
|
106
|
+
return isTypeScriptProject() ? ts : jsx;
|
|
78
107
|
}
|
|
79
108
|
function resolveLayoutChain(pageDir, appDir) {
|
|
80
109
|
const chain = [];
|
|
@@ -186,6 +215,7 @@ function renderChain(layouts, routesInChain, layoutNames, pageNames, layoutTitle
|
|
|
186
215
|
function generateApp(appDir) {
|
|
187
216
|
const aliases = readTsconfigAliases();
|
|
188
217
|
const routes = scanRoutes(appDir, appDir);
|
|
218
|
+
const ts = isTypeScriptProject();
|
|
189
219
|
const rootPage = findFile(appDir, PAGE_FILES);
|
|
190
220
|
if (rootPage) {
|
|
191
221
|
routes.unshift({
|
|
@@ -247,15 +277,7 @@ function generateApp(appDir) {
|
|
|
247
277
|
for (const [, { layouts, routes: cr }] of chainMap)
|
|
248
278
|
routeLines.push(renderChain(layouts, cr, layoutNames, pageNames, layoutTitles, 8));
|
|
249
279
|
const catchAll = notFound ? ` <Route path="*" element={<Suspense fallback={<Spinner />}><NotFound /></Suspense>} />` : ` <Route path="*" element={<Default404 />} />`;
|
|
250
|
-
|
|
251
|
-
import React, { Suspense } from 'react';
|
|
252
|
-
import { BrowserRouter, Routes, Route, Outlet } from 'react-router-dom';
|
|
253
|
-
import './app/globals.css';
|
|
254
|
-
|
|
255
|
-
${lazyImports.join("\n")}
|
|
256
|
-
|
|
257
|
-
// \u2500\u2500\u2500 Error Boundary \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
258
|
-
class ErrorBoundary extends React.Component<
|
|
280
|
+
const errorBoundaryClass = ts ? `class ErrorBoundary extends React.Component<
|
|
259
281
|
{ children: React.ReactNode },
|
|
260
282
|
{ error: Error | null }
|
|
261
283
|
> {
|
|
@@ -278,7 +300,43 @@ class ErrorBoundary extends React.Component<
|
|
|
278
300
|
);
|
|
279
301
|
return this.props.children;
|
|
280
302
|
}
|
|
281
|
-
}
|
|
303
|
+
}` : `class ErrorBoundary extends React.Component {
|
|
304
|
+
constructor(props) {
|
|
305
|
+
super(props);
|
|
306
|
+
this.state = { error: null };
|
|
307
|
+
}
|
|
308
|
+
static getDerivedStateFromError(error) { return { error }; }
|
|
309
|
+
render() {
|
|
310
|
+
if (this.state.error) return (
|
|
311
|
+
<div style={{ minHeight: '100vh', display: 'flex', alignItems: 'center', justifyContent: 'center', fontFamily: 'system-ui,sans-serif', padding: '2rem' }}>
|
|
312
|
+
<div style={{ maxWidth: 480, width: '100%', textAlign: 'center' }}>
|
|
313
|
+
<h2 style={{ color: '#e74c3c', marginBottom: '1rem' }}>Something went wrong</h2>
|
|
314
|
+
<pre style={{ background: '#fef2f2', padding: '1rem', borderRadius: '0.5rem', textAlign: 'left', fontSize: '0.8rem', color: '#e74c3c', overflow: 'auto' }}>{this.state.error.toString()}</pre>
|
|
315
|
+
<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 }}>
|
|
316
|
+
Try again
|
|
317
|
+
</button>
|
|
318
|
+
</div>
|
|
319
|
+
</div>
|
|
320
|
+
);
|
|
321
|
+
return this.props.children;
|
|
322
|
+
}
|
|
323
|
+
}`;
|
|
324
|
+
const titleSetterFn = ts ? `function TitleSetter({ title }: { title: string }) {
|
|
325
|
+
React.useEffect(() => { document.title = title; }, [title]);
|
|
326
|
+
return null;
|
|
327
|
+
}` : `function TitleSetter({ title }) {
|
|
328
|
+
React.useEffect(() => { document.title = title; }, [title]);
|
|
329
|
+
return null;
|
|
330
|
+
}`;
|
|
331
|
+
return `// \u26A0\uFE0F Auto-generated by bini-router \u2014 do not edit.
|
|
332
|
+
import React, { Suspense } from 'react';
|
|
333
|
+
import { BrowserRouter, Routes, Route, Outlet } from 'react-router-dom';
|
|
334
|
+
import './app/globals.css';
|
|
335
|
+
|
|
336
|
+
${lazyImports.join("\n")}
|
|
337
|
+
|
|
338
|
+
// \u2500\u2500\u2500 Error Boundary \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
339
|
+
${errorBoundaryClass}
|
|
282
340
|
|
|
283
341
|
function Spinner() {
|
|
284
342
|
return (
|
|
@@ -289,10 +347,7 @@ function Spinner() {
|
|
|
289
347
|
);
|
|
290
348
|
}
|
|
291
349
|
|
|
292
|
-
|
|
293
|
-
React.useEffect(() => { document.title = title; }, [title]);
|
|
294
|
-
return null;
|
|
295
|
-
}
|
|
350
|
+
${titleSetterFn}
|
|
296
351
|
|
|
297
352
|
${notFound ? "" : `function Default404() {
|
|
298
353
|
return (
|
|
@@ -635,7 +690,6 @@ import { handle } from 'https://deno.land/x/hono@v4.3.11/adapter/netlify/index.t
|
|
|
635
690
|
outFile: (cwd) => path.join(cwd, "netlify", "edge-functions", "api.ts"),
|
|
636
691
|
stripsApiPrefix: false,
|
|
637
692
|
denoRuntime: true
|
|
638
|
-
// ← Deno needs explicit .ts extensions
|
|
639
693
|
},
|
|
640
694
|
cloudflare: {
|
|
641
695
|
exportLine: `export default app;`,
|
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 * 'netlify' → netlify/edge-functions/api.ts (Deno runtime, zero npm)\r\n * 'cloudflare' → worker.ts\r\n * 'node' → server/index.ts (requires: @hono/node-server)\r\n * 'deno' → server/index.ts\r\n * 'bun' → server/index.ts\r\n * 'aws' → handler.ts (requires: @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\ninterface AdapterConfig {\r\n pkg ?: string;\r\n importLine ?: string;\r\n exportLine : string;\r\n outFile : (cwd: string) => string;\r\n stripsApiPrefix : boolean;\r\n /** Deno runtime: requires explicit .ts extensions in imports */\r\n denoRuntime ?: boolean;\r\n}\r\n\r\nconst ADAPTERS: Record<Platform, AdapterConfig> = {\r\n\r\n netlify: {\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 denoRuntime : true, // ← Deno needs explicit .ts extensions\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\r\n node: {\r\n pkg : '@hono/node-server',\r\n importLine : `import { serve } from '@hono/node-server';\\nimport { serveStatic } from '@hono/node-server/serve-static';`,\r\n exportLine : `app.use('/*', serveStatic({ root: './dist' }));\\napp.use('/*', serveStatic({ path: './dist/index.html' }));\\n\\nserve({ fetch: app.fetch, port: Number(process.env.PORT ?? 3000) }, (i) => {\\n console.log(\\`Server running on http://localhost:\\${i.port}\\`);\\n});`,\r\n outFile : (cwd) => path.join(cwd, 'server', 'index.ts'),\r\n stripsApiPrefix: false,\r\n },\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 denoRuntime : true,\r\n },\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\r\n aws: {\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\n// ─── Resolve import path for production entry ────────────────────────────────\r\n// For Deno runtimes (Netlify edge functions, deno platform) we must keep the\r\n// .ts extension — Deno resolves modules by exact URL/path and will throw\r\n// \"Could not find file\" if the extension is omitted.\r\n// All other platforms (Node bundlers, esbuild, etc.) expect extensionless\r\n// imports, so we strip the extension as before.\r\nfunction resolveEntryImportPath(\r\n filePath : string,\r\n outFile : string,\r\n denoRuntime: boolean,\r\n): string {\r\n const rel = norm(path.relative(path.dirname(outFile), filePath));\r\n if (denoRuntime) {\r\n // Normalise to .ts (drop .tsx which Deno can't handle either)\r\n const withTs = rel.replace(/\\.tsx$/, '.ts');\r\n return withTs.startsWith('.') ? withTs : `./${withTs}`;\r\n }\r\n const stripped = rel.replace(/\\.(ts|tsx|js|jsx)$/, '');\r\n return stripped.startsWith('.') ? stripped : `./${stripped}`;\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 { stripsApiPrefix, denoRuntime = false } = adapter;\r\n const isNetlify = platform === 'netlify';\r\n\r\n for (let i = 0; i < routes.length; i++) {\r\n const route = routes[i];\r\n const imp = resolveEntryImportPath(route.filePath, outFile, denoRuntime);\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 const mountPath = stripsApiPrefix ? 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 = stripsApiPrefix ? '/*' : '/api/*';\r\n const corsLine = enableCors\r\n ? isNetlify\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\r\n const corsImport = enableCors && !isNetlify ? `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 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 isNetlify = platform === 'netlify';\r\n const lines = [\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 ...(isNetlify ? [] : [`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 (Deno runtime, zero npm)\r\n * 'cloudflare' → worker.ts\r\n * 'node' → server/index.ts (requires: @hono/node-server)\r\n * 'deno' → server/index.ts\r\n * 'bun' → server/index.ts\r\n * 'aws' → handler.ts (requires: @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\n// ─── TypeScript detection ─────────────────────────────────────────────────────\r\n// We cannot rely on tsconfig.json — Vite scaffolds it even for plain JS projects.\r\n// Instead we check whether the user's own entry point (main.tsx / main.ts) exists.\r\n// If neither exists yet we fall back to checking for any .tsx/.ts file in src/app.\r\n// Only if none of those signals are present do we treat the project as JavaScript.\r\n\r\nfunction isTypeScriptProject(): boolean {\r\n const cwd = process.cwd();\r\n\r\n // 1. Explicit TypeScript entry point\r\n if (\r\n fs.existsSync(path.join(cwd, 'src/main.tsx')) ||\r\n fs.existsSync(path.join(cwd, 'src/main.ts'))\r\n ) return true;\r\n\r\n // 2. Explicit JavaScript entry point\r\n if (\r\n fs.existsSync(path.join(cwd, 'src/main.jsx')) ||\r\n fs.existsSync(path.join(cwd, 'src/main.js'))\r\n ) return false;\r\n\r\n // 3. Fallback: scan src/app for any .tsx or .ts user file\r\n const appDir = path.join(cwd, 'src/app');\r\n if (fs.existsSync(appDir)) {\r\n const hasTsFile = (dir: string): boolean => {\r\n let entries: fs.Dirent[];\r\n try { entries = fs.readdirSync(dir, { withFileTypes: true }); }\r\n catch { return false; }\r\n for (const entry of entries) {\r\n if (entry.isDirectory()) {\r\n if (hasTsFile(path.join(dir, entry.name))) return true;\r\n } else {\r\n const ext = path.extname(entry.name);\r\n if (ext === '.tsx' || ext === '.ts') return true;\r\n }\r\n }\r\n return false;\r\n };\r\n if (hasTsFile(appDir)) return true;\r\n }\r\n\r\n // 4. Default to JavaScript\r\n return false;\r\n}\r\n\r\nfunction getAppFile(): string {\r\n const ts = path.join(process.cwd(), 'src/App.tsx');\r\n const jsx = path.join(process.cwd(), 'src/App.jsx');\r\n // If App.tsx already exists (e.g. from a previous regen), keep using it.\r\n // Otherwise choose the extension based on the detected project type.\r\n if (fs.existsSync(ts)) return ts;\r\n return isTypeScriptProject() ? ts : 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 const ts = isTypeScriptProject();\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 // ── ErrorBoundary — TypeScript vs JavaScript ─────────────────────────────\r\n // TypeScript projects get full generic type annotations.\r\n // JavaScript projects get clean JS class syntax — no generics, no type params.\r\n const errorBoundaryClass = ts\r\n ? `class 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 : `class ErrorBoundary extends React.Component {\r\n constructor(props) {\r\n super(props);\r\n this.state = { error: null };\r\n }\r\n static getDerivedStateFromError(error) { return { error }; }\r\n 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\n // ── TitleSetter — TypeScript vs JavaScript ───────────────────────────────\r\n const titleSetterFn = ts\r\n ? `function TitleSetter({ title }: { title: string }) {\r\n React.useEffect(() => { document.title = title; }, [title]);\r\n return null;\r\n}`\r\n : `function TitleSetter({ title }) {\r\n React.useEffect(() => { document.title = title; }, [title]);\r\n return null;\r\n}`;\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\n${errorBoundaryClass}\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\n${titleSetterFn}\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\ninterface AdapterConfig {\r\n pkg ?: string;\r\n importLine ?: string;\r\n exportLine : string;\r\n outFile : (cwd: string) => string;\r\n stripsApiPrefix : boolean;\r\n /** Deno runtime: requires explicit .ts extensions in imports */\r\n denoRuntime ?: boolean;\r\n}\r\n\r\nconst ADAPTERS: Record<Platform, AdapterConfig> = {\r\n\r\n netlify: {\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 denoRuntime : true,\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\r\n node: {\r\n pkg : '@hono/node-server',\r\n importLine : `import { serve } from '@hono/node-server';\\nimport { serveStatic } from '@hono/node-server/serve-static';`,\r\n exportLine : `app.use('/*', serveStatic({ root: './dist' }));\\napp.use('/*', serveStatic({ path: './dist/index.html' }));\\n\\nserve({ fetch: app.fetch, port: Number(process.env.PORT ?? 3000) }, (i) => {\\n console.log(\\`Server running on http://localhost:\\${i.port}\\`);\\n});`,\r\n outFile : (cwd) => path.join(cwd, 'server', 'index.ts'),\r\n stripsApiPrefix: false,\r\n },\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 denoRuntime : true,\r\n },\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\r\n aws: {\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 resolveEntryImportPath(\r\n filePath : string,\r\n outFile : string,\r\n denoRuntime: boolean,\r\n): string {\r\n const rel = norm(path.relative(path.dirname(outFile), filePath));\r\n if (denoRuntime) {\r\n const withTs = rel.replace(/\\.tsx$/, '.ts');\r\n return withTs.startsWith('.') ? withTs : `./${withTs}`;\r\n }\r\n const stripped = rel.replace(/\\.(ts|tsx|js|jsx)$/, '');\r\n return stripped.startsWith('.') ? stripped : `./${stripped}`;\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 { stripsApiPrefix, denoRuntime = false } = adapter;\r\n const isNetlify = platform === 'netlify';\r\n\r\n for (let i = 0; i < routes.length; i++) {\r\n const route = routes[i];\r\n const imp = resolveEntryImportPath(route.filePath, outFile, denoRuntime);\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 const mountPath = stripsApiPrefix ? 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 = stripsApiPrefix ? '/*' : '/api/*';\r\n const corsLine = enableCors\r\n ? isNetlify\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\r\n const corsImport = enableCors && !isNetlify ? `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 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 isNetlify = platform === 'netlify';\r\n const lines = [\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 ...(isNetlify ? [] : [`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"]}
|