@epicabdou/linkr 0.0.3 → 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +137 -46
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
# linkr
|
|
1
|
+
# @epicabdou/linkr
|
|
2
2
|
|
|
3
|
-
File-based routing for **React Router v7** in Vite + React SPA apps. Generates a route tree from a `src/pages/` directory using `import.meta.glob`
|
|
3
|
+
File-based routing for **React Router v7** in Vite + React SPA apps. Generates a route tree from a `src/pages/` directory using `import.meta.glob` — the consumer passes the glob result; the library does not call it.
|
|
4
4
|
|
|
5
5
|
## Install
|
|
6
6
|
|
|
@@ -8,10 +8,12 @@ File-based routing for **React Router v7** in Vite + React SPA apps. Generates a
|
|
|
8
8
|
pnpm add @epicabdou/linkr react react-dom react-router
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
-
Peer
|
|
11
|
+
**Peer dependencies:** `react` (≥18), `react-dom` (≥18), `react-router` (≥7).
|
|
12
12
|
|
|
13
13
|
## Usage
|
|
14
14
|
|
|
15
|
+
### Basic setup
|
|
16
|
+
|
|
15
17
|
```tsx
|
|
16
18
|
import { createRoutes } from "@epicabdou/linkr";
|
|
17
19
|
import { createBrowserRouter, RouterProvider } from "react-router";
|
|
@@ -23,51 +25,108 @@ const router = createBrowserRouter(routes);
|
|
|
23
25
|
// Then render <RouterProvider router={router} />
|
|
24
26
|
```
|
|
25
27
|
|
|
26
|
-
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
28
|
+
### One-line app bootstrap
|
|
29
|
+
|
|
30
|
+
Use `createRootWithLinkr` to create the root, build routes, and render in one call:
|
|
31
|
+
|
|
32
|
+
```tsx
|
|
33
|
+
import { createRootWithLinkr } from "@epicabdou/linkr";
|
|
34
|
+
|
|
35
|
+
createRootWithLinkr(document.getElementById("root")!, {
|
|
36
|
+
pagesGlob: import.meta.glob("./pages/**/*.tsx"),
|
|
37
|
+
pagesDir: "pages",
|
|
38
|
+
});
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
This uses `createBrowserRouter`, `StrictMode`, and `RouterProvider` under the hood. No need to import React Router or call `createRoutes` yourself.
|
|
42
|
+
|
|
43
|
+
### Using `<LinkrApp>` (with custom providers)
|
|
44
|
+
|
|
45
|
+
When you need to wrap the app with your own providers, use the `<LinkrApp>` component and pass the same options as `createRoutes`:
|
|
46
|
+
|
|
47
|
+
```tsx
|
|
48
|
+
import { LinkrApp } from "@epicabdou/linkr";
|
|
49
|
+
|
|
50
|
+
const pages = import.meta.glob("./pages/**/*.tsx");
|
|
51
|
+
|
|
52
|
+
function App() {
|
|
53
|
+
return (
|
|
54
|
+
<YourProvider>
|
|
55
|
+
<LinkrApp
|
|
56
|
+
pagesGlob={pages}
|
|
57
|
+
pagesDir="pages"
|
|
58
|
+
defaultRedirectTo="/login"
|
|
59
|
+
/>
|
|
60
|
+
</YourProvider>
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
createRoot(document.getElementById("root")!).render(<App />);
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Options are read once on mount; the router is created with `useMemo`.
|
|
68
|
+
|
|
69
|
+
---
|
|
70
|
+
|
|
71
|
+
## `createRoutes` options
|
|
72
|
+
|
|
73
|
+
| Option | Type | Default | Description |
|
|
74
|
+
|--------|------|---------|-------------|
|
|
75
|
+
| **`pagesGlob`** | `Record<string, () => Promise<unknown>>` | *required* | Result of `import.meta.glob("...")` from your app. |
|
|
76
|
+
| **`pagesDir`** | `string` | `"src/pages"` | Base path used to normalize file paths. Must match the prefix you strip from glob keys (e.g. `"pages"` when glob is `./pages/**/*.tsx` from `src/`). |
|
|
77
|
+
| **`layoutFileName`** | `string` | `"_layout"` | Filename (without extension) for layout routes. |
|
|
78
|
+
| **`notFoundFileName`** | `string` | `"404"` | Filename for the catch-all not-found route. |
|
|
79
|
+
| **`routeExtensions`** | `string[]` | `[".tsx", ".ts", ".jsx", ".js"]` | Extensions that define route files. |
|
|
80
|
+
| **`defaultRedirectTo`** | `string` | `"/"` | Default redirect path when a route's `protect` check fails and no `redirectTo` is set. |
|
|
81
|
+
| **`layoutsGlob`** | `Record<string, () => Promise<unknown>>` | — | When set with **`layoutMap`**, layouts are loaded from this glob and `_layout` files in pages are ignored. Example: `import.meta.glob("./layouts/**/*.tsx")`. |
|
|
82
|
+
| **`layoutsDir`** | `string` | `"src/layouts"` | Base path for layout files when using **`layoutsGlob`**. |
|
|
83
|
+
| **`layoutMap`** | `Record<string, string>` | — | Path prefix → layout name. Use `""` or `"/"` for root; segment name (e.g. `blog`) for nested. Requires **`layoutsGlob`**. |
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## File conventions
|
|
88
|
+
|
|
89
|
+
| File / pattern | Route |
|
|
90
|
+
|----------------|-------|
|
|
91
|
+
| `index.tsx` | `/` (index route) |
|
|
92
|
+
| `about.tsx` | `/about` |
|
|
93
|
+
| `blog/index.tsx` | `/blog` (index under blog) |
|
|
94
|
+
| `blog/[id].tsx` | `/blog/:id` |
|
|
95
|
+
| `docs/[...slug].tsx` | `/docs/*` (splat) |
|
|
96
|
+
| `404.tsx` | `path: "*"` (catch-all, last) |
|
|
97
|
+
| `_layout.tsx` (in any folder) | Layout route; children render in `<Outlet />`. Ignored when using **layoutsGlob** + **layoutMap**. |
|
|
98
|
+
|
|
99
|
+
- **Nested routes:** folder nesting = nested routes.
|
|
100
|
+
- **Layouts:** Either put `_layout.tsx` in a folder (folder-based), or use a **separate layouts folder** with **layoutsGlob** and **layoutMap** so layouts are reusable components.
|
|
101
|
+
- **Sort order:** among siblings — static segments first, then dynamic (`:id`), then splat (`*`).
|
|
102
|
+
- **Lazy loading:** every route uses React Router's `lazy()` for code splitting.
|
|
103
|
+
|
|
104
|
+
---
|
|
52
105
|
|
|
53
106
|
## Page module exports
|
|
54
107
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
108
|
+
| Export | Description |
|
|
109
|
+
|--------|-------------|
|
|
110
|
+
| **`default`** | React component used as the route element (required). |
|
|
111
|
+
| **`ErrorBoundary`** | Optional; used as the route's `errorElement`. |
|
|
112
|
+
| **`handle`** | Optional; attached to the route's `handle`. |
|
|
113
|
+
| **`protect`** | Optional; runs before rendering. If it returns `false`, the user is redirected. See [Route protection](#route-protection). |
|
|
114
|
+
|
|
115
|
+
---
|
|
59
116
|
|
|
60
117
|
## Layouts in a separate folder
|
|
61
118
|
|
|
62
119
|
Keep layouts as reusable components in a dedicated folder and wire them by path with **layoutMap** (no `_layout.tsx` in pages).
|
|
63
120
|
|
|
121
|
+
**Example layouts:**
|
|
122
|
+
|
|
64
123
|
```tsx
|
|
65
124
|
// src/layouts/Root.tsx
|
|
66
125
|
import { Link, Outlet } from "react-router";
|
|
67
126
|
export default function RootLayout() {
|
|
68
127
|
return (
|
|
69
128
|
<div>
|
|
70
|
-
<nav><Link to="/">Home</Link
|
|
129
|
+
<nav><Link to="/">Home</Link> <Link to="/blog">Blog</Link></nav>
|
|
71
130
|
<Outlet />
|
|
72
131
|
</div>
|
|
73
132
|
);
|
|
@@ -77,11 +136,14 @@ export default function RootLayout() {
|
|
|
77
136
|
```tsx
|
|
78
137
|
// src/layouts/Blog.tsx
|
|
79
138
|
import { Outlet } from "react-router";
|
|
80
|
-
export default function BlogLayout() {
|
|
139
|
+
export default function BlogLayout() {
|
|
140
|
+
return <div><h2>Blog</h2><Outlet /></div>;
|
|
141
|
+
}
|
|
81
142
|
```
|
|
82
143
|
|
|
144
|
+
**Wire in router setup:**
|
|
145
|
+
|
|
83
146
|
```tsx
|
|
84
|
-
// main.tsx or router setup
|
|
85
147
|
const pages = import.meta.glob("./pages/**/*.tsx");
|
|
86
148
|
const layouts = import.meta.glob("./layouts/**/*.tsx");
|
|
87
149
|
const routes = createRoutes({
|
|
@@ -93,8 +155,10 @@ const routes = createRoutes({
|
|
|
93
155
|
});
|
|
94
156
|
```
|
|
95
157
|
|
|
96
|
-
- **layoutMap
|
|
97
|
-
- The same layout component can be reused
|
|
158
|
+
- **layoutMap keys:** `""` or `"/"` = root layout; `"blog"` = layout for `/blog` and its children. Value = layout filename without extension (e.g. `Root`, `Blog`).
|
|
159
|
+
- The same layout component can be reused by mapping multiple keys to the same name.
|
|
160
|
+
|
|
161
|
+
---
|
|
98
162
|
|
|
99
163
|
## Route protection
|
|
100
164
|
|
|
@@ -134,7 +198,7 @@ export default function SettingsLayout() {
|
|
|
134
198
|
}
|
|
135
199
|
```
|
|
136
200
|
|
|
137
|
-
|
|
201
|
+
Set a default redirect when creating routes:
|
|
138
202
|
|
|
139
203
|
```tsx
|
|
140
204
|
createRoutes({
|
|
@@ -144,14 +208,14 @@ createRoutes({
|
|
|
144
208
|
});
|
|
145
209
|
```
|
|
146
210
|
|
|
147
|
-
### 2. `<Protect>` component
|
|
211
|
+
### 2. `<Protect>` component
|
|
148
212
|
|
|
149
|
-
Use
|
|
213
|
+
Use `<Protect>` when you want to guard content inside a layout (e.g. wrap `<Outlet />`) or need a stable condition with a fallback UI.
|
|
150
214
|
|
|
151
|
-
**Predefined config (recommended):** define `condition`, `redirectTo`, and `fallback` once
|
|
215
|
+
**Predefined config (recommended):** define `condition`, `redirectTo`, and `fallback` once, then reuse with `<Protect {...config}>`.
|
|
152
216
|
|
|
153
217
|
```tsx
|
|
154
|
-
// src/config/protect.tsx
|
|
218
|
+
// src/config/protect.tsx
|
|
155
219
|
import type { ProtectConfig } from "@epicabdou/linkr";
|
|
156
220
|
|
|
157
221
|
export const authProtect: ProtectConfig = {
|
|
@@ -176,13 +240,31 @@ export default function DashboardLayout() {
|
|
|
176
240
|
}
|
|
177
241
|
```
|
|
178
242
|
|
|
179
|
-
|
|
243
|
+
**Props:**
|
|
180
244
|
|
|
181
245
|
- **`condition`**: sync or async function; return `true` to allow, `false` to redirect.
|
|
182
246
|
- **`redirectTo`**: path to redirect to when the condition fails.
|
|
183
247
|
- **`fallback`**: optional React node shown while an async condition is pending.
|
|
184
248
|
- **`children`**: content to render when the condition is true.
|
|
185
249
|
|
|
250
|
+
You can define multiple configs (e.g. `authProtect`, `adminProtect`) and import the one you need.
|
|
251
|
+
|
|
252
|
+
---
|
|
253
|
+
|
|
254
|
+
## API exports
|
|
255
|
+
|
|
256
|
+
| Export | Description |
|
|
257
|
+
|--------|-------------|
|
|
258
|
+
| `createRoutes` | Builds React Router route array from pages glob and options. |
|
|
259
|
+
| `LinkrApp` | Component that renders `RouterProvider` with routes from options. |
|
|
260
|
+
| `createRootWithLinkr` | One-shot: `createRoot`, `createRoutes`, `StrictMode` + `RouterProvider`. |
|
|
261
|
+
| `Protect` | Component for conditional redirect with fallback UI. |
|
|
262
|
+
| `normalizePath`, `parseSegment`, `compareSegments` | Path utilities (for advanced use). |
|
|
263
|
+
|
|
264
|
+
**Types:** `CreateRoutesOptions`, `LayoutMap`, `LayoutsGlob`, `PagesGlob`, `RouteObject`, `RouteProtect`, `ProtectProps`, `ProtectConfig`, `LinkrAppOptions`, `ParsedSegment`, `SegmentKind`.
|
|
265
|
+
|
|
266
|
+
---
|
|
267
|
+
|
|
186
268
|
## Quick start with CLI
|
|
187
269
|
|
|
188
270
|
```bash
|
|
@@ -192,7 +274,16 @@ cd my-app && pnpm dev
|
|
|
192
274
|
|
|
193
275
|
## Build & test
|
|
194
276
|
|
|
277
|
+
From the monorepo root:
|
|
278
|
+
|
|
279
|
+
```bash
|
|
280
|
+
pnpm --filter @epicabdou/linkr build
|
|
281
|
+
pnpm --filter @epicabdou/linkr test
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
Or from `packages/linkr`:
|
|
285
|
+
|
|
195
286
|
```bash
|
|
196
|
-
pnpm
|
|
197
|
-
pnpm
|
|
287
|
+
pnpm build
|
|
288
|
+
pnpm test
|
|
198
289
|
```
|
package/dist/index.js
CHANGED
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/createRoutes.ts","../src/pathUtils.ts","../src/Protect.tsx","../src/LinkrApp.tsx"],"sourcesContent":["import type { RouteObject } from \"react-router\";\r\nimport { redirect } from \"react-router\";\r\nimport type { CreateRoutesOptions, LayoutMap, LayoutsGlob, PagesGlob, RouteProtect } from \"./types\";\r\nimport {\r\n normalizePath,\r\n getRouteExtension,\r\n parseSegment,\r\n compareSegments,\r\n type ParsedSegment,\r\n} from \"./pathUtils\";\r\n\r\nconst DEFAULT_PAGES_DIR = \"src/pages\";\r\nconst DEFAULT_LAYOUTS_DIR = \"src/layouts\";\r\nconst DEFAULT_LAYOUT_FILE = \"_layout\";\r\nconst DEFAULT_NOT_FOUND_FILE = \"404\";\r\nconst DEFAULT_EXTENSIONS = [\".tsx\", \".ts\", \".jsx\", \".js\"];\r\n\r\n/** Build layout name -> loader from layoutsGlob. Layout name = filename without ext (one level). */\r\nfunction parseLayoutsGlob(\r\n layoutsGlob: LayoutsGlob,\r\n layoutsDir: string,\r\n extensions: string[]\r\n): Map<string, () => Promise<unknown>> {\r\n const map = new Map<string, () => Promise<unknown>>();\r\n const dir = normalizePath(layoutsDir).replace(/\\/$/, \"\");\r\n for (const key of Object.keys(layoutsGlob)) {\r\n const normalized = normalizePath(key).replace(/^\\.\\//, \"\");\r\n let relative = normalized;\r\n if (relative.startsWith(dir + \"/\")) relative = relative.slice(dir.length + 1);\r\n else if (relative.startsWith(dir)) relative = relative.slice(dir.length).replace(/^\\//, \"\");\r\n const ext = getRouteExtension(relative, extensions);\r\n if (!ext) continue;\r\n const withoutExt = relative.slice(0, -ext.length);\r\n const parts = withoutExt.split(\"/\").filter(Boolean);\r\n if (parts.length === 0) continue;\r\n const name = parts[parts.length - 1];\r\n map.set(name, layoutsGlob[key]);\r\n }\r\n return map;\r\n}\r\n\r\ntype LazyModule = {\r\n default?: React.ComponentType;\r\n ErrorBoundary?: React.ComponentType;\r\n handle?: unknown;\r\n protect?: RouteProtect;\r\n};\r\n\r\n/**\r\n * Strip extension from filename.\r\n */\r\nfunction stripExtension(filename: string, extensions: string[]): string {\r\n const lower = filename.toLowerCase();\r\n for (const ext of extensions) {\r\n if (lower.endsWith(ext)) return filename.slice(0, -ext.length);\r\n }\r\n return filename;\r\n}\r\n\r\n/**\r\n * Check if segment is a valid splat (exactly \"[...name]\").\r\n */\r\nfunction isValidSplatSegment(segment: string): boolean {\r\n return /^\\[\\.\\.\\.[^\\]]*\\]$/.test(segment);\r\n}\r\n\r\n/**\r\n * Warn in dev when a module has no default export (called from lazy).\r\n */\r\nfunction warnNoDefault(path: string): void {\r\n if (typeof process !== \"undefined\" && process.env?.NODE_ENV !== \"production\") {\r\n console.warn(`[linkr] Module has no default export, skipping route: ${path}`);\r\n }\r\n}\r\n\r\n/**\r\n * Warn when [...slug] is used with other segments in the same filename.\r\n */\r\nfunction warnInvalidSplat(path: string): void {\r\n if (typeof process !== \"undefined\" && process.env?.NODE_ENV !== \"production\") {\r\n console.warn(\r\n `[linkr] Invalid splat usage (e.g. foo[...slug].tsx); use only [...slug].tsx in filename. Skipping: ${path}`\r\n );\r\n }\r\n}\r\n\r\ninterface FileEntry {\r\n path: string;\r\n segments: string[];\r\n isLayout: boolean;\r\n is404: boolean;\r\n isIndex: boolean;\r\n segmentKinds: ReturnType<typeof parseSegment>[];\r\n}\r\n\r\nfunction parseGlobKey(\r\n key: string,\r\n opts: Required<Pick<CreateRoutesOptions, \"pagesDir\" | \"layoutFileName\" | \"notFoundFileName\" | \"routeExtensions\">>\r\n): FileEntry | null {\r\n const normalized = normalizePath(key);\r\n const withoutLeadingSlash = normalized.replace(/^\\.\\//, \"\");\r\n const dir = normalizePath(opts.pagesDir).replace(/\\/$/, \"\");\r\n let relative = withoutLeadingSlash;\r\n if (relative.startsWith(dir + \"/\")) {\r\n relative = relative.slice(dir.length + 1);\r\n } else if (relative.startsWith(dir)) {\r\n relative = relative.slice(dir.length).replace(/^\\//, \"\");\r\n } else if (dir.includes(\"/\")) {\r\n const lastDirSegment = dir.split(\"/\").pop()!;\r\n if (relative.startsWith(lastDirSegment + \"/\")) {\r\n relative = relative.slice(lastDirSegment.length + 1);\r\n }\r\n }\r\n\r\n const ext = getRouteExtension(relative, opts.routeExtensions);\r\n if (!ext) return null;\r\n\r\n const withoutExt = relative.slice(0, -ext.length);\r\n const parts = withoutExt.split(\"/\").filter(Boolean);\r\n if (parts.length === 0) return null;\r\n\r\n const lastPart = parts[parts.length - 1];\r\n const isLayout = stripExtension(lastPart, opts.routeExtensions) === opts.layoutFileName;\r\n const is404 = stripExtension(lastPart, opts.routeExtensions) === opts.notFoundFileName;\r\n const isIndex = lastPart.toLowerCase().replace(new RegExp(\"\\\\\" + ext + \"$\", \"i\"), \"\") === \"index\";\r\n const segmentParts = isIndex ? parts.slice(0, -1) : parts;\r\n const segmentStrings = segmentParts.map((p, i) => {\r\n const isLast = i === segmentParts.length - 1;\r\n return isLast ? stripExtension(p, opts.routeExtensions) : p;\r\n });\r\n\r\n const segmentKinds = segmentStrings.map(parseSegment);\r\n for (const s of segmentStrings) {\r\n if (s.includes(\"[...\") && !isValidSplatSegment(s)) {\r\n warnInvalidSplat(key);\r\n return null;\r\n }\r\n }\r\n\r\n return {\r\n path: key,\r\n segments: segmentStrings,\r\n isLayout,\r\n is404,\r\n isIndex,\r\n segmentKinds,\r\n };\r\n}\r\n\r\ninterface RouteNode {\r\n path: string;\r\n layout: FileEntry | null;\r\n indexRoute: FileEntry | null;\r\n children: Map<string, { entry: FileEntry }>;\r\n childLayouts: Map<string, RouteNode>;\r\n}\r\n\r\nfunction buildTree(entries: FileEntry[]): RouteNode {\r\n const root: RouteNode = {\r\n path: \"\",\r\n layout: null,\r\n indexRoute: null,\r\n children: new Map(),\r\n childLayouts: new Map(),\r\n };\r\n\r\n for (const entry of entries) {\r\n if (entry.is404) continue;\r\n if (entry.isLayout) {\r\n const layoutSegments = entry.segments.slice(0, -1);\r\n let node = root;\r\n for (let i = 0; i < layoutSegments.length; i++) {\r\n const key = layoutSegments.slice(0, i + 1).join(\"/\");\r\n if (!node.childLayouts.has(key)) {\r\n node.childLayouts.set(key, {\r\n path: key,\r\n layout: null,\r\n indexRoute: null,\r\n children: new Map(),\r\n childLayouts: new Map(),\r\n });\r\n }\r\n node = node.childLayouts.get(key)!;\r\n }\r\n node.layout = entry;\r\n continue;\r\n }\r\n\r\n if (entry.isIndex && entry.segments.length === 0) {\r\n root.indexRoute = entry;\r\n continue;\r\n }\r\n\r\n if (entry.isIndex) {\r\n let node = root;\r\n const segs = entry.segments;\r\n for (let i = 0; i < segs.length; i++) {\r\n const key = segs.slice(0, i + 1).join(\"/\");\r\n if (node.childLayouts.has(key)) {\r\n node = node.childLayouts.get(key)!;\r\n } else {\r\n const next: RouteNode = {\r\n path: key,\r\n layout: null,\r\n indexRoute: null,\r\n children: new Map(),\r\n childLayouts: new Map(),\r\n };\r\n node.childLayouts.set(key, next);\r\n node = next;\r\n }\r\n }\r\n node.indexRoute = entry;\r\n continue;\r\n }\r\n\r\n const segs = entry.segments;\r\n let node = root;\r\n for (let i = 0; i < segs.length - 1; i++) {\r\n const key = segs.slice(0, i + 1).join(\"/\");\r\n if (node.childLayouts.has(key)) {\r\n node = node.childLayouts.get(key)!;\r\n } else {\r\n const next: RouteNode = {\r\n path: key,\r\n layout: null,\r\n indexRoute: null,\r\n children: new Map(),\r\n childLayouts: new Map(),\r\n };\r\n node.childLayouts.set(key, next);\r\n node = next;\r\n }\r\n }\r\n const lastSeg = segs[segs.length - 1];\r\n node.children.set(lastSeg, { entry });\r\n }\r\n\r\n return root;\r\n}\r\n\r\nfunction segmentToPath(segment: ParsedSegment): string {\r\n if (segment.kind === \"static\") return segment.raw;\r\n if (segment.kind === \"dynamic\") return \":\" + (segment.paramName ?? \"param\");\r\n if (segment.kind === \"splat\") return \"*\";\r\n return segment.raw;\r\n}\r\n\r\nfunction makeLazyRoute(\r\n loader: () => Promise<unknown>,\r\n filePath: string,\r\n defaultRedirectTo?: string\r\n): RouteObject[\"lazy\"] {\r\n return async () => {\r\n const mod = (await loader()) as LazyModule;\r\n if (!mod.default) {\r\n warnNoDefault(filePath);\r\n return { Component: () => null };\r\n }\r\n const result: Record<string, unknown> = { Component: mod.default };\r\n if (mod.ErrorBoundary) result.ErrorBoundary = mod.ErrorBoundary;\r\n if (mod.handle !== undefined) result.handle = mod.handle;\r\n\r\n if (mod.protect) {\r\n const check = typeof mod.protect === \"function\" ? mod.protect : mod.protect.check;\r\n const redirectTo =\r\n (typeof mod.protect === \"object\" && mod.protect.redirectTo != null\r\n ? mod.protect.redirectTo\r\n : defaultRedirectTo) ?? \"/\";\r\n result.loader = async () => {\r\n const ok = await Promise.resolve(check());\r\n if (!ok) throw redirect(redirectTo);\r\n return null;\r\n };\r\n }\r\n\r\n return result as {\r\n Component: React.ComponentType;\r\n ErrorBoundary?: React.ComponentType;\r\n handle?: unknown;\r\n loader?: RouteObject[\"loader\"];\r\n };\r\n };\r\n}\r\n\r\nfunction nodeToRoutes(\r\n node: RouteNode,\r\n pathPrefix: string,\r\n pagesGlob: PagesGlob,\r\n defaultRedirectTo?: string,\r\n layoutMap?: LayoutMap,\r\n layoutLoaders?: Map<string, () => Promise<unknown>>\r\n): RouteObject[] {\r\n const childRouteObjects: RouteObject[] = [];\r\n\r\n if (node.indexRoute) {\r\n const loader = pagesGlob[node.indexRoute.path];\r\n if (loader) {\r\n childRouteObjects.push({\r\n index: true,\r\n lazy: makeLazyRoute(loader, node.indexRoute.path, defaultRedirectTo),\r\n });\r\n }\r\n }\r\n\r\n const childSegments = Array.from(node.children.entries());\r\n childSegments.sort(([a], [b]) => compareSegments(parseSegment(a), parseSegment(b)));\r\n\r\n for (const [segStr, { entry }] of childSegments) {\r\n const seg = parseSegment(segStr);\r\n const pathSeg = segmentToPath(seg);\r\n const loader = pagesGlob[entry.path];\r\n if (!loader) continue;\r\n childRouteObjects.push({\r\n path: pathSeg,\r\n lazy: makeLazyRoute(loader, entry.path, defaultRedirectTo),\r\n });\r\n }\r\n\r\n const sortedLayoutKeys = Array.from(node.childLayouts.keys()).sort((a, b) => {\r\n const segsA = a.split(\"/\").map(parseSegment);\r\n const segsB = b.split(\"/\").map(parseSegment);\r\n const len = Math.min(segsA.length, segsB.length);\r\n for (let i = 0; i < len; i++) {\r\n const c = compareSegments(segsA[i], segsB[i]);\r\n if (c !== 0) return c;\r\n }\r\n return segsA.length - segsB.length;\r\n });\r\n\r\n for (const key of sortedLayoutKeys) {\r\n const childNode = node.childLayouts.get(key)!;\r\n const firstSeg = key.split(\"/\")[0];\r\n const seg = parseSegment(firstSeg);\r\n const pathSeg = segmentToPath(seg);\r\n const nested = nodeToRoutes(\r\n childNode,\r\n pathPrefix ? pathPrefix + \"/\" + pathSeg : pathSeg,\r\n pagesGlob,\r\n defaultRedirectTo,\r\n layoutMap,\r\n layoutLoaders\r\n );\r\n const layoutName = layoutMap && layoutLoaders ? layoutMap[key] ?? layoutMap[\"/\" + key] : undefined;\r\n const layoutLoader = layoutName ? layoutLoaders!.get(layoutName) : undefined;\r\n if (layoutLoader) {\r\n childRouteObjects.push({\r\n path: pathSeg,\r\n lazy: makeLazyRoute(layoutLoader, \"layout:\" + layoutName, defaultRedirectTo),\r\n children: nested,\r\n });\r\n } else if (childNode.layout && childNode.layout.path in pagesGlob) {\r\n childRouteObjects.push(...nested);\r\n } else if (childNode.layout) {\r\n childRouteObjects.push({ path: pathSeg, children: nested });\r\n } else if (nested.length > 0) {\r\n childRouteObjects.push({ path: pathSeg, children: nested });\r\n }\r\n }\r\n\r\n if (node.layout && node.layout.path in pagesGlob) {\r\n const layoutLoader = pagesGlob[node.layout.path];\r\n return [{\r\n path: pathPrefix === \"\" ? \"/\" : pathPrefix,\r\n lazy: makeLazyRoute(layoutLoader, node.layout.path, defaultRedirectTo),\r\n children: childRouteObjects.length ? childRouteObjects : undefined,\r\n }];\r\n }\r\n\r\n return childRouteObjects;\r\n}\r\n\r\nfunction flattenRootChildren(\r\n root: RouteNode,\r\n pagesGlob: PagesGlob,\r\n defaultRedirectTo?: string,\r\n layoutMap?: LayoutMap,\r\n layoutLoaders?: Map<string, () => Promise<unknown>>\r\n): RouteObject[] {\r\n const result: RouteObject[] = [];\r\n\r\n if (root.indexRoute) {\r\n const loader = pagesGlob[root.indexRoute.path];\r\n if (loader) {\r\n result.push({\r\n index: true,\r\n lazy: makeLazyRoute(loader, root.indexRoute.path, defaultRedirectTo),\r\n });\r\n }\r\n }\r\n\r\n const childSegments = Array.from(root.children.entries());\r\n childSegments.sort(([a], [b]) => compareSegments(parseSegment(a), parseSegment(b)));\r\n\r\n for (const [segStr, { entry }] of childSegments) {\r\n const seg = parseSegment(segStr);\r\n const pathSeg = segmentToPath(seg);\r\n const loader = pagesGlob[entry.path];\r\n if (!loader) continue;\r\n result.push({\r\n path: pathSeg,\r\n lazy: makeLazyRoute(loader, entry.path, defaultRedirectTo),\r\n });\r\n }\r\n\r\n const layoutKeys = Array.from(root.childLayouts.keys()).sort((a, b) => {\r\n const segsA = a.split(\"/\").map(parseSegment);\r\n const segsB = b.split(\"/\").map(parseSegment);\r\n const len = Math.min(segsA.length, segsB.length);\r\n for (let i = 0; i < len; i++) {\r\n const c = compareSegments(segsA[i], segsB[i]);\r\n if (c !== 0) return c;\r\n }\r\n return segsA.length - segsB.length;\r\n });\r\n\r\n for (const key of layoutKeys) {\r\n const childNode = root.childLayouts.get(key)!;\r\n const firstSeg = key.split(\"/\")[0];\r\n const seg = parseSegment(firstSeg);\r\n const pathSeg = segmentToPath(seg);\r\n const nested = nodeToRoutes(\r\n childNode,\r\n pathSeg,\r\n pagesGlob,\r\n defaultRedirectTo,\r\n layoutMap,\r\n layoutLoaders\r\n );\r\n const layoutName = layoutMap && layoutLoaders ? layoutMap[key] ?? layoutMap[\"/\" + key] : undefined;\r\n const layoutLoader = layoutName ? layoutLoaders!.get(layoutName) : undefined;\r\n if (layoutLoader) {\r\n result.push({\r\n path: pathSeg,\r\n lazy: makeLazyRoute(layoutLoader, \"layout:\" + layoutName, defaultRedirectTo),\r\n children: nested,\r\n });\r\n } else if (childNode.layout && childNode.layout.path in pagesGlob) {\r\n result.push(...nested);\r\n } else if (childNode.layout) {\r\n result.push({ path: pathSeg, children: nested });\r\n } else if (nested.length > 0) {\r\n result.push({ path: pathSeg, children: nested });\r\n }\r\n }\r\n\r\n const rootLayoutName = layoutMap && layoutLoaders ? layoutMap[\"\"] ?? layoutMap[\"/\"] : undefined;\r\n const rootLayoutLoader = rootLayoutName ? layoutLoaders!.get(rootLayoutName) : undefined;\r\n if (rootLayoutLoader && result.length > 0) {\r\n return [{\r\n path: \"/\",\r\n lazy: makeLazyRoute(rootLayoutLoader, \"layout:\" + rootLayoutName, defaultRedirectTo),\r\n children: result,\r\n }];\r\n }\r\n return result;\r\n}\r\n\r\nexport function createRoutes(options: CreateRoutesOptions): RouteObject[] {\r\n const pagesDir = normalizePath(options.pagesDir ?? DEFAULT_PAGES_DIR).replace(/\\/$/, \"\");\r\n const opts = {\r\n pagesDir,\r\n layoutFileName: options.layoutFileName ?? DEFAULT_LAYOUT_FILE,\r\n notFoundFileName: options.notFoundFileName ?? DEFAULT_NOT_FOUND_FILE,\r\n routeExtensions: options.routeExtensions ?? DEFAULT_EXTENSIONS,\r\n };\r\n\r\n const entries: FileEntry[] = [];\r\n for (const key of Object.keys(options.pagesGlob)) {\r\n const entry = parseGlobKey(key, opts);\r\n if (entry) entries.push(entry);\r\n }\r\n\r\n const notFoundEntry = entries.find((e) => e.is404);\r\n const useLayoutsFolder = options.layoutsGlob != null && options.layoutMap != null;\r\n const rest = useLayoutsFolder\r\n ? entries.filter((e) => !e.is404 && !e.isLayout)\r\n : entries.filter((e) => !e.is404);\r\n const root = buildTree(rest);\r\n\r\n const layoutLoaders =\r\n options.layoutsGlob && options.layoutMap\r\n ? parseLayoutsGlob(\r\n options.layoutsGlob,\r\n options.layoutsDir ?? DEFAULT_LAYOUTS_DIR,\r\n opts.routeExtensions\r\n )\r\n : undefined;\r\n\r\n let topLevelRoutes: RouteObject[];\r\n\r\n if (layoutLoaders && options.layoutMap) {\r\n topLevelRoutes = flattenRootChildren(\r\n root,\r\n options.pagesGlob,\r\n options.defaultRedirectTo,\r\n options.layoutMap,\r\n layoutLoaders\r\n );\r\n } else if (root.layout && root.layout.path in options.pagesGlob) {\r\n const layoutLoader = options.pagesGlob[root.layout.path];\r\n topLevelRoutes = [{\r\n path: \"/\",\r\n lazy: makeLazyRoute(layoutLoader, root.layout.path, options.defaultRedirectTo),\r\n children: flattenRootChildren(root, options.pagesGlob, options.defaultRedirectTo),\r\n }];\r\n } else {\r\n topLevelRoutes = flattenRootChildren(root, options.pagesGlob, options.defaultRedirectTo);\r\n }\r\n\r\n if (notFoundEntry && notFoundEntry.path in options.pagesGlob) {\r\n const loader = options.pagesGlob[notFoundEntry.path];\r\n topLevelRoutes.push({\r\n path: \"*\",\r\n lazy: makeLazyRoute(loader, notFoundEntry.path, options.defaultRedirectTo),\r\n });\r\n }\r\n\r\n return topLevelRoutes;\r\n}\r\n","/**\r\n * Normalize path to use forward slashes (Windows-safe).\r\n */\r\nexport function normalizePath(p: string): string {\r\n return p.replace(/\\\\/g, \"/\");\r\n}\r\n\r\n/**\r\n * Get route extension from filename (e.g. \".tsx\") or null if not a route file.\r\n */\r\nexport function getRouteExtension(\r\n filename: string,\r\n extensions: string[]\r\n): string | null {\r\n const lower = filename.toLowerCase();\r\n for (const ext of extensions) {\r\n if (lower.endsWith(ext)) return ext;\r\n }\r\n return null;\r\n}\r\n\r\nexport type SegmentKind = \"static\" | \"dynamic\" | \"splat\";\r\n\r\nexport interface ParsedSegment {\r\n /** Original segment string, e.g. \"blog\", \"[id]\", \"[...slug]\" */\r\n raw: string;\r\n kind: SegmentKind;\r\n /** For dynamic: \"id\"; for splat: \"slug\"; for static: same as raw */\r\n paramName?: string;\r\n}\r\n\r\n/**\r\n * Parse a single path segment into kind and param name.\r\n */\r\nexport function parseSegment(segment: string): ParsedSegment {\r\n if (segment.startsWith(\"[...\") && segment.endsWith(\"]\")) {\r\n const param = segment.slice(4, -1);\r\n return { raw: segment, kind: \"splat\", paramName: param || \"splat\" };\r\n }\r\n if (segment.startsWith(\"[\") && segment.endsWith(\"]\")) {\r\n const param = segment.slice(1, -1);\r\n return { raw: segment, kind: \"dynamic\", paramName: param || \"param\" };\r\n }\r\n return { raw: segment, kind: \"static\" };\r\n}\r\n\r\n/**\r\n * Compare two segments for sort order: static < dynamic < splat.\r\n */\r\nexport function compareSegments(a: ParsedSegment, b: ParsedSegment): number {\r\n const order = { static: 0, dynamic: 1, splat: 2 };\r\n const diff = order[a.kind] - order[b.kind];\r\n if (diff !== 0) return diff;\r\n return a.raw.localeCompare(b.raw);\r\n}\r\n","import { useEffect, useState, type ReactNode } from \"react\";\r\nimport { useNavigate } from \"react-router\";\r\n\r\nexport interface ProtectProps {\r\n /** Sync or async function that returns true to allow access, false to redirect. */\r\n condition: () => boolean | Promise<boolean>;\r\n /** Where to redirect when condition returns false. */\r\n redirectTo: string;\r\n /** Optional content to show while an async condition is pending (e.g. a spinner). */\r\n fallback?: ReactNode;\r\n /** Content to render when condition is true. */\r\n children: ReactNode;\r\n}\r\n\r\n/**\r\n * Reusable protection config: condition, redirectTo, and optional fallback.\r\n * Define once in a config file and spread into <Protect {...config}>.\r\n */\r\nexport type ProtectConfig = Pick<ProtectProps, \"condition\" | \"redirectTo\" | \"fallback\">;\r\n\r\n/**\r\n * Protects content by checking a condition before rendering. If the condition\r\n * returns false (sync or async), redirects to redirectTo. Use this to guard\r\n * a single route's content or an entire layout's <Outlet />.\r\n */\r\nexport function Protect({ condition, redirectTo, fallback = null, children }: ProtectProps) {\r\n const navigate = useNavigate();\r\n const [allowed, setAllowed] = useState<boolean | null>(null);\r\n\r\n useEffect(() => {\r\n let cancelled = false;\r\n const result = condition();\r\n if (typeof result === \"boolean\") {\r\n if (!cancelled) setAllowed(result);\r\n if (!result) navigate(redirectTo, { replace: true });\r\n return;\r\n }\r\n result.then((ok) => {\r\n if (!cancelled) setAllowed(ok);\r\n if (!ok) navigate(redirectTo, { replace: true });\r\n });\r\n return () => {\r\n cancelled = true;\r\n };\r\n }, [condition, redirectTo, navigate]);\r\n\r\n if (allowed === null) return <>{fallback}</>;\r\n if (!allowed) return null;\r\n return <>{children}</>;\r\n}\r\n","import { StrictMode, useMemo, useRef } from \"react\";\r\nimport { createRoot } from \"react-dom/client\";\r\nimport { createBrowserRouter, RouterProvider } from \"react-router\";\r\nimport { createRoutes } from \"./createRoutes\";\r\nimport type { CreateRoutesOptions, PagesGlob } from \"./types\";\r\n\r\n/**\r\n * Options for LinkrApp and createRootWithLinkr.\r\n * Same as CreateRoutesOptions (pagesGlob required; rest optional).\r\n */\r\nexport type LinkrAppOptions = { pagesGlob: PagesGlob } & Omit<CreateRoutesOptions, \"pagesGlob\">;\r\n\r\n/**\r\n * Renders the file-based router. Options are read once on mount.\r\n * Use this when you need to wrap the app with your own providers.\r\n */\r\nexport function LinkrApp(options: LinkrAppOptions) {\r\n const optionsRef = useRef(options);\r\n optionsRef.current = options;\r\n const router = useMemo(\r\n () => createBrowserRouter(createRoutes(optionsRef.current)),\r\n []\r\n );\r\n return <RouterProvider router={router} />;\r\n}\r\n\r\n/**\r\n * One-shot setup: creates the root, builds routes from pagesGlob, and renders\r\n * with StrictMode + RouterProvider. Minimizes app entry to a single call.\r\n *\r\n * @example\r\n * ```tsx\r\n * import { createRootWithLinkr } from \"@epicabdou/linkr\";\r\n * createRootWithLinkr(document.getElementById(\"root\")!, {\r\n * pagesGlob: import.meta.glob(\"./pages/**\\/*.tsx\"),\r\n * pagesDir: \"pages\",\r\n * });\r\n * ```\r\n */\r\nexport function createRootWithLinkr(\r\n rootElement: HTMLElement,\r\n options: LinkrAppOptions\r\n): ReturnType<typeof createRoot> {\r\n const router = createBrowserRouter(createRoutes(options));\r\n const root = createRoot(rootElement);\r\n root.render(\r\n <StrictMode>\r\n <RouterProvider router={router} />\r\n </StrictMode>\r\n );\r\n return root;\r\n}\r\n"],"mappings":"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","names":["node","segs","jsx"]}
|
|
1
|
+
{"version":3,"sources":["../src/createRoutes.ts","../src/pathUtils.ts","../src/Protect.tsx","../src/LinkrApp.tsx"],"sourcesContent":["import type { RouteObject } from \"react-router\";\r\nimport { redirect } from \"react-router\";\r\nimport type { CreateRoutesOptions, LayoutMap, LayoutsGlob, PagesGlob, RouteProtect } from \"./types\";\r\nimport {\r\n normalizePath,\r\n getRouteExtension,\r\n parseSegment,\r\n compareSegments,\r\n type ParsedSegment,\r\n} from \"./pathUtils\";\r\n\r\nconst DEFAULT_PAGES_DIR = \"src/pages\";\r\nconst DEFAULT_LAYOUTS_DIR = \"src/layouts\";\r\nconst DEFAULT_LAYOUT_FILE = \"_layout\";\r\nconst DEFAULT_NOT_FOUND_FILE = \"404\";\r\nconst DEFAULT_EXTENSIONS = [\".tsx\", \".ts\", \".jsx\", \".js\"];\r\n\r\n/** Build layout name -> loader from layoutsGlob. Layout name = filename without ext (one level). */\r\nfunction parseLayoutsGlob(\r\n layoutsGlob: LayoutsGlob,\r\n layoutsDir: string,\r\n extensions: string[]\r\n): Map<string, () => Promise<unknown>> {\r\n const map = new Map<string, () => Promise<unknown>>();\r\n const dir = normalizePath(layoutsDir).replace(/\\/$/, \"\");\r\n for (const key of Object.keys(layoutsGlob)) {\r\n const normalized = normalizePath(key).replace(/^\\.\\//, \"\");\r\n let relative = normalized;\r\n if (relative.startsWith(dir + \"/\")) relative = relative.slice(dir.length + 1);\r\n else if (relative.startsWith(dir)) relative = relative.slice(dir.length).replace(/^\\//, \"\");\r\n const ext = getRouteExtension(relative, extensions);\r\n if (!ext) continue;\r\n const withoutExt = relative.slice(0, -ext.length);\r\n const parts = withoutExt.split(\"/\").filter(Boolean);\r\n if (parts.length === 0) continue;\r\n const name = parts[parts.length - 1];\r\n map.set(name, layoutsGlob[key]);\r\n }\r\n return map;\r\n}\r\n\r\ntype LazyModule = {\r\n default?: React.ComponentType;\r\n ErrorBoundary?: React.ComponentType;\r\n handle?: unknown;\r\n protect?: RouteProtect;\r\n};\r\n\r\n/**\r\n * Strip extension from filename.\r\n */\r\nfunction stripExtension(filename: string, extensions: string[]): string {\r\n const lower = filename.toLowerCase();\r\n for (const ext of extensions) {\r\n if (lower.endsWith(ext)) return filename.slice(0, -ext.length);\r\n }\r\n return filename;\r\n}\r\n\r\n/**\r\n * Check if segment is a valid splat (exactly \"[...name]\").\r\n */\r\nfunction isValidSplatSegment(segment: string): boolean {\r\n return /^\\[\\.\\.\\.[^\\]]*\\]$/.test(segment);\r\n}\r\n\r\n/**\r\n * Warn in dev when a module has no default export (called from lazy).\r\n */\r\nfunction warnNoDefault(path: string): void {\r\n if (typeof process !== \"undefined\" && process.env?.NODE_ENV !== \"production\") {\r\n console.warn(`[linkr] Module has no default export, skipping route: ${path}`);\r\n }\r\n}\r\n\r\n/**\r\n * Warn when [...slug] is used with other segments in the same filename.\r\n */\r\nfunction warnInvalidSplat(path: string): void {\r\n if (typeof process !== \"undefined\" && process.env?.NODE_ENV !== \"production\") {\r\n console.warn(\r\n `[linkr] Invalid splat usage (e.g. foo[...slug].tsx); use only [...slug].tsx in filename. Skipping: ${path}`\r\n );\r\n }\r\n}\r\n\r\ninterface FileEntry {\r\n path: string;\r\n segments: string[];\r\n isLayout: boolean;\r\n is404: boolean;\r\n isIndex: boolean;\r\n segmentKinds: ReturnType<typeof parseSegment>[];\r\n}\r\n\r\nfunction parseGlobKey(\r\n key: string,\r\n opts: Required<Pick<CreateRoutesOptions, \"pagesDir\" | \"layoutFileName\" | \"notFoundFileName\" | \"routeExtensions\">>\r\n): FileEntry | null {\r\n const normalized = normalizePath(key);\r\n const withoutLeadingSlash = normalized.replace(/^\\.\\//, \"\");\r\n const dir = normalizePath(opts.pagesDir).replace(/\\/$/, \"\");\r\n let relative = withoutLeadingSlash;\r\n if (relative.startsWith(dir + \"/\")) {\r\n relative = relative.slice(dir.length + 1);\r\n } else if (relative.startsWith(dir)) {\r\n relative = relative.slice(dir.length).replace(/^\\//, \"\");\r\n } else if (dir.includes(\"/\")) {\r\n const lastDirSegment = dir.split(\"/\").pop()!;\r\n if (relative.startsWith(lastDirSegment + \"/\")) {\r\n relative = relative.slice(lastDirSegment.length + 1);\r\n }\r\n }\r\n\r\n const ext = getRouteExtension(relative, opts.routeExtensions);\r\n if (!ext) return null;\r\n\r\n const withoutExt = relative.slice(0, -ext.length);\r\n const parts = withoutExt.split(\"/\").filter(Boolean);\r\n if (parts.length === 0) return null;\r\n\r\n const lastPart = parts[parts.length - 1];\r\n const isLayout = stripExtension(lastPart, opts.routeExtensions) === opts.layoutFileName;\r\n const is404 = stripExtension(lastPart, opts.routeExtensions) === opts.notFoundFileName;\r\n const isIndex = lastPart.toLowerCase().replace(new RegExp(\"\\\\\" + ext + \"$\", \"i\"), \"\") === \"index\";\r\n const segmentParts = isIndex ? parts.slice(0, -1) : parts;\r\n const segmentStrings = segmentParts.map((p, i) => {\r\n const isLast = i === segmentParts.length - 1;\r\n return isLast ? stripExtension(p, opts.routeExtensions) : p;\r\n });\r\n\r\n const segmentKinds = segmentStrings.map(parseSegment);\r\n for (const s of segmentStrings) {\r\n if (s.includes(\"[...\") && !isValidSplatSegment(s)) {\r\n warnInvalidSplat(key);\r\n return null;\r\n }\r\n }\r\n\r\n return {\r\n path: key,\r\n segments: segmentStrings,\r\n isLayout,\r\n is404,\r\n isIndex,\r\n segmentKinds,\r\n };\r\n}\r\n\r\ninterface RouteNode {\r\n path: string;\r\n layout: FileEntry | null;\r\n indexRoute: FileEntry | null;\r\n children: Map<string, { entry: FileEntry }>;\r\n childLayouts: Map<string, RouteNode>;\r\n}\r\n\r\nfunction buildTree(entries: FileEntry[]): RouteNode {\r\n const root: RouteNode = {\r\n path: \"\",\r\n layout: null,\r\n indexRoute: null,\r\n children: new Map(),\r\n childLayouts: new Map(),\r\n };\r\n\r\n for (const entry of entries) {\r\n if (entry.is404) continue;\r\n if (entry.isLayout) {\r\n const layoutSegments = entry.segments.slice(0, -1);\r\n let node = root;\r\n for (let i = 0; i < layoutSegments.length; i++) {\r\n const key = layoutSegments.slice(0, i + 1).join(\"/\");\r\n if (!node.childLayouts.has(key)) {\r\n node.childLayouts.set(key, {\r\n path: key,\r\n layout: null,\r\n indexRoute: null,\r\n children: new Map(),\r\n childLayouts: new Map(),\r\n });\r\n }\r\n node = node.childLayouts.get(key)!;\r\n }\r\n node.layout = entry;\r\n continue;\r\n }\r\n\r\n if (entry.isIndex && entry.segments.length === 0) {\r\n root.indexRoute = entry;\r\n continue;\r\n }\r\n\r\n if (entry.isIndex) {\r\n let node = root;\r\n const segs = entry.segments;\r\n for (let i = 0; i < segs.length; i++) {\r\n const key = segs.slice(0, i + 1).join(\"/\");\r\n if (node.childLayouts.has(key)) {\r\n node = node.childLayouts.get(key)!;\r\n } else {\r\n const next: RouteNode = {\r\n path: key,\r\n layout: null,\r\n indexRoute: null,\r\n children: new Map(),\r\n childLayouts: new Map(),\r\n };\r\n node.childLayouts.set(key, next);\r\n node = next;\r\n }\r\n }\r\n node.indexRoute = entry;\r\n continue;\r\n }\r\n\r\n const segs = entry.segments;\r\n let node = root;\r\n for (let i = 0; i < segs.length - 1; i++) {\r\n const key = segs.slice(0, i + 1).join(\"/\");\r\n if (node.childLayouts.has(key)) {\r\n node = node.childLayouts.get(key)!;\r\n } else {\r\n const next: RouteNode = {\r\n path: key,\r\n layout: null,\r\n indexRoute: null,\r\n children: new Map(),\r\n childLayouts: new Map(),\r\n };\r\n node.childLayouts.set(key, next);\r\n node = next;\r\n }\r\n }\r\n const lastSeg = segs[segs.length - 1];\r\n node.children.set(lastSeg, { entry });\r\n }\r\n\r\n return root;\r\n}\r\n\r\nfunction segmentToPath(segment: ParsedSegment): string {\r\n if (segment.kind === \"static\") return segment.raw;\r\n if (segment.kind === \"dynamic\") return \":\" + (segment.paramName ?? \"param\");\r\n if (segment.kind === \"splat\") return \"*\";\r\n return segment.raw;\r\n}\r\n\r\nfunction makeLazyRoute(\r\n loader: () => Promise<unknown>,\r\n filePath: string,\r\n defaultRedirectTo?: string\r\n): RouteObject[\"lazy\"] {\r\n return async () => {\r\n const mod = (await loader()) as LazyModule;\r\n if (!mod.default) {\r\n warnNoDefault(filePath);\r\n return { Component: () => null };\r\n }\r\n const result: Record<string, unknown> = { Component: mod.default };\r\n if (mod.ErrorBoundary) result.ErrorBoundary = mod.ErrorBoundary;\r\n if (mod.handle !== undefined) result.handle = mod.handle;\r\n\r\n if (mod.protect) {\r\n const check = typeof mod.protect === \"function\" ? mod.protect : mod.protect.check;\r\n const redirectTo =\r\n (typeof mod.protect === \"object\" && mod.protect.redirectTo != null\r\n ? mod.protect.redirectTo\r\n : defaultRedirectTo) ?? \"/\";\r\n result.loader = async () => {\r\n const ok = await Promise.resolve(check());\r\n if (!ok) throw redirect(redirectTo);\r\n return null;\r\n };\r\n // React Router v7 requires HydrateFallback when a route has a loader and no hydration data.\r\n result.HydrateFallback = () => null;\r\n }\r\n\r\n return result as {\r\n Component: React.ComponentType;\r\n ErrorBoundary?: React.ComponentType;\r\n handle?: unknown;\r\n loader?: RouteObject[\"loader\"];\r\n HydrateFallback?: React.ComponentType;\r\n };\r\n };\r\n}\r\n\r\nfunction nodeToRoutes(\r\n node: RouteNode,\r\n pathPrefix: string,\r\n pagesGlob: PagesGlob,\r\n defaultRedirectTo?: string,\r\n layoutMap?: LayoutMap,\r\n layoutLoaders?: Map<string, () => Promise<unknown>>\r\n): RouteObject[] {\r\n const childRouteObjects: RouteObject[] = [];\r\n\r\n if (node.indexRoute) {\r\n const loader = pagesGlob[node.indexRoute.path];\r\n if (loader) {\r\n childRouteObjects.push({\r\n index: true,\r\n lazy: makeLazyRoute(loader, node.indexRoute.path, defaultRedirectTo),\r\n });\r\n }\r\n }\r\n\r\n const childSegments = Array.from(node.children.entries());\r\n childSegments.sort(([a], [b]) => compareSegments(parseSegment(a), parseSegment(b)));\r\n\r\n for (const [segStr, { entry }] of childSegments) {\r\n const seg = parseSegment(segStr);\r\n const pathSeg = segmentToPath(seg);\r\n const loader = pagesGlob[entry.path];\r\n if (!loader) continue;\r\n childRouteObjects.push({\r\n path: pathSeg,\r\n lazy: makeLazyRoute(loader, entry.path, defaultRedirectTo),\r\n });\r\n }\r\n\r\n const sortedLayoutKeys = Array.from(node.childLayouts.keys()).sort((a, b) => {\r\n const segsA = a.split(\"/\").map(parseSegment);\r\n const segsB = b.split(\"/\").map(parseSegment);\r\n const len = Math.min(segsA.length, segsB.length);\r\n for (let i = 0; i < len; i++) {\r\n const c = compareSegments(segsA[i], segsB[i]);\r\n if (c !== 0) return c;\r\n }\r\n return segsA.length - segsB.length;\r\n });\r\n\r\n for (const key of sortedLayoutKeys) {\r\n const childNode = node.childLayouts.get(key)!;\r\n const firstSeg = key.split(\"/\")[0];\r\n const seg = parseSegment(firstSeg);\r\n const pathSeg = segmentToPath(seg);\r\n const nested = nodeToRoutes(\r\n childNode,\r\n pathPrefix ? pathPrefix + \"/\" + pathSeg : pathSeg,\r\n pagesGlob,\r\n defaultRedirectTo,\r\n layoutMap,\r\n layoutLoaders\r\n );\r\n const layoutName = layoutMap && layoutLoaders ? layoutMap[key] ?? layoutMap[\"/\" + key] : undefined;\r\n const layoutLoader = layoutName ? layoutLoaders!.get(layoutName) : undefined;\r\n if (layoutLoader) {\r\n childRouteObjects.push({\r\n path: pathSeg,\r\n lazy: makeLazyRoute(layoutLoader, \"layout:\" + layoutName, defaultRedirectTo),\r\n children: nested,\r\n });\r\n } else if (childNode.layout && childNode.layout.path in pagesGlob) {\r\n childRouteObjects.push(...nested);\r\n } else if (childNode.layout) {\r\n childRouteObjects.push({ path: pathSeg, children: nested });\r\n } else if (nested.length > 0) {\r\n childRouteObjects.push({ path: pathSeg, children: nested });\r\n }\r\n }\r\n\r\n if (node.layout && node.layout.path in pagesGlob) {\r\n const layoutLoader = pagesGlob[node.layout.path];\r\n return [{\r\n path: pathPrefix === \"\" ? \"/\" : pathPrefix,\r\n lazy: makeLazyRoute(layoutLoader, node.layout.path, defaultRedirectTo),\r\n children: childRouteObjects.length ? childRouteObjects : undefined,\r\n }];\r\n }\r\n\r\n return childRouteObjects;\r\n}\r\n\r\nfunction flattenRootChildren(\r\n root: RouteNode,\r\n pagesGlob: PagesGlob,\r\n defaultRedirectTo?: string,\r\n layoutMap?: LayoutMap,\r\n layoutLoaders?: Map<string, () => Promise<unknown>>\r\n): RouteObject[] {\r\n const result: RouteObject[] = [];\r\n\r\n if (root.indexRoute) {\r\n const loader = pagesGlob[root.indexRoute.path];\r\n if (loader) {\r\n result.push({\r\n index: true,\r\n lazy: makeLazyRoute(loader, root.indexRoute.path, defaultRedirectTo),\r\n });\r\n }\r\n }\r\n\r\n const childSegments = Array.from(root.children.entries());\r\n childSegments.sort(([a], [b]) => compareSegments(parseSegment(a), parseSegment(b)));\r\n\r\n for (const [segStr, { entry }] of childSegments) {\r\n const seg = parseSegment(segStr);\r\n const pathSeg = segmentToPath(seg);\r\n const loader = pagesGlob[entry.path];\r\n if (!loader) continue;\r\n result.push({\r\n path: pathSeg,\r\n lazy: makeLazyRoute(loader, entry.path, defaultRedirectTo),\r\n });\r\n }\r\n\r\n const layoutKeys = Array.from(root.childLayouts.keys()).sort((a, b) => {\r\n const segsA = a.split(\"/\").map(parseSegment);\r\n const segsB = b.split(\"/\").map(parseSegment);\r\n const len = Math.min(segsA.length, segsB.length);\r\n for (let i = 0; i < len; i++) {\r\n const c = compareSegments(segsA[i], segsB[i]);\r\n if (c !== 0) return c;\r\n }\r\n return segsA.length - segsB.length;\r\n });\r\n\r\n for (const key of layoutKeys) {\r\n const childNode = root.childLayouts.get(key)!;\r\n const firstSeg = key.split(\"/\")[0];\r\n const seg = parseSegment(firstSeg);\r\n const pathSeg = segmentToPath(seg);\r\n const nested = nodeToRoutes(\r\n childNode,\r\n pathSeg,\r\n pagesGlob,\r\n defaultRedirectTo,\r\n layoutMap,\r\n layoutLoaders\r\n );\r\n const layoutName = layoutMap && layoutLoaders ? layoutMap[key] ?? layoutMap[\"/\" + key] : undefined;\r\n const layoutLoader = layoutName ? layoutLoaders!.get(layoutName) : undefined;\r\n if (layoutLoader) {\r\n result.push({\r\n path: pathSeg,\r\n lazy: makeLazyRoute(layoutLoader, \"layout:\" + layoutName, defaultRedirectTo),\r\n children: nested,\r\n });\r\n } else if (childNode.layout && childNode.layout.path in pagesGlob) {\r\n result.push(...nested);\r\n } else if (childNode.layout) {\r\n result.push({ path: pathSeg, children: nested });\r\n } else if (nested.length > 0) {\r\n result.push({ path: pathSeg, children: nested });\r\n }\r\n }\r\n\r\n const rootLayoutName = layoutMap && layoutLoaders ? layoutMap[\"\"] ?? layoutMap[\"/\"] : undefined;\r\n const rootLayoutLoader = rootLayoutName ? layoutLoaders!.get(rootLayoutName) : undefined;\r\n if (rootLayoutLoader && result.length > 0) {\r\n return [{\r\n path: \"/\",\r\n lazy: makeLazyRoute(rootLayoutLoader, \"layout:\" + rootLayoutName, defaultRedirectTo),\r\n children: result,\r\n }];\r\n }\r\n return result;\r\n}\r\n\r\nexport function createRoutes(options: CreateRoutesOptions): RouteObject[] {\r\n const pagesDir = normalizePath(options.pagesDir ?? DEFAULT_PAGES_DIR).replace(/\\/$/, \"\");\r\n const opts = {\r\n pagesDir,\r\n layoutFileName: options.layoutFileName ?? DEFAULT_LAYOUT_FILE,\r\n notFoundFileName: options.notFoundFileName ?? DEFAULT_NOT_FOUND_FILE,\r\n routeExtensions: options.routeExtensions ?? DEFAULT_EXTENSIONS,\r\n };\r\n\r\n const entries: FileEntry[] = [];\r\n for (const key of Object.keys(options.pagesGlob)) {\r\n const entry = parseGlobKey(key, opts);\r\n if (entry) entries.push(entry);\r\n }\r\n\r\n const notFoundEntry = entries.find((e) => e.is404);\r\n const useLayoutsFolder = options.layoutsGlob != null && options.layoutMap != null;\r\n const rest = useLayoutsFolder\r\n ? entries.filter((e) => !e.is404 && !e.isLayout)\r\n : entries.filter((e) => !e.is404);\r\n const root = buildTree(rest);\r\n\r\n const layoutLoaders =\r\n options.layoutsGlob && options.layoutMap\r\n ? parseLayoutsGlob(\r\n options.layoutsGlob,\r\n options.layoutsDir ?? DEFAULT_LAYOUTS_DIR,\r\n opts.routeExtensions\r\n )\r\n : undefined;\r\n\r\n let topLevelRoutes: RouteObject[];\r\n\r\n if (layoutLoaders && options.layoutMap) {\r\n topLevelRoutes = flattenRootChildren(\r\n root,\r\n options.pagesGlob,\r\n options.defaultRedirectTo,\r\n options.layoutMap,\r\n layoutLoaders\r\n );\r\n } else if (root.layout && root.layout.path in options.pagesGlob) {\r\n const layoutLoader = options.pagesGlob[root.layout.path];\r\n topLevelRoutes = [{\r\n path: \"/\",\r\n lazy: makeLazyRoute(layoutLoader, root.layout.path, options.defaultRedirectTo),\r\n children: flattenRootChildren(root, options.pagesGlob, options.defaultRedirectTo),\r\n }];\r\n } else {\r\n topLevelRoutes = flattenRootChildren(root, options.pagesGlob, options.defaultRedirectTo);\r\n }\r\n\r\n if (notFoundEntry && notFoundEntry.path in options.pagesGlob) {\r\n const loader = options.pagesGlob[notFoundEntry.path];\r\n topLevelRoutes.push({\r\n path: \"*\",\r\n lazy: makeLazyRoute(loader, notFoundEntry.path, options.defaultRedirectTo),\r\n });\r\n }\r\n\r\n return topLevelRoutes;\r\n}\r\n","/**\r\n * Normalize path to use forward slashes (Windows-safe).\r\n */\r\nexport function normalizePath(p: string): string {\r\n return p.replace(/\\\\/g, \"/\");\r\n}\r\n\r\n/**\r\n * Get route extension from filename (e.g. \".tsx\") or null if not a route file.\r\n */\r\nexport function getRouteExtension(\r\n filename: string,\r\n extensions: string[]\r\n): string | null {\r\n const lower = filename.toLowerCase();\r\n for (const ext of extensions) {\r\n if (lower.endsWith(ext)) return ext;\r\n }\r\n return null;\r\n}\r\n\r\nexport type SegmentKind = \"static\" | \"dynamic\" | \"splat\";\r\n\r\nexport interface ParsedSegment {\r\n /** Original segment string, e.g. \"blog\", \"[id]\", \"[...slug]\" */\r\n raw: string;\r\n kind: SegmentKind;\r\n /** For dynamic: \"id\"; for splat: \"slug\"; for static: same as raw */\r\n paramName?: string;\r\n}\r\n\r\n/**\r\n * Parse a single path segment into kind and param name.\r\n */\r\nexport function parseSegment(segment: string): ParsedSegment {\r\n if (segment.startsWith(\"[...\") && segment.endsWith(\"]\")) {\r\n const param = segment.slice(4, -1);\r\n return { raw: segment, kind: \"splat\", paramName: param || \"splat\" };\r\n }\r\n if (segment.startsWith(\"[\") && segment.endsWith(\"]\")) {\r\n const param = segment.slice(1, -1);\r\n return { raw: segment, kind: \"dynamic\", paramName: param || \"param\" };\r\n }\r\n return { raw: segment, kind: \"static\" };\r\n}\r\n\r\n/**\r\n * Compare two segments for sort order: static < dynamic < splat.\r\n */\r\nexport function compareSegments(a: ParsedSegment, b: ParsedSegment): number {\r\n const order = { static: 0, dynamic: 1, splat: 2 };\r\n const diff = order[a.kind] - order[b.kind];\r\n if (diff !== 0) return diff;\r\n return a.raw.localeCompare(b.raw);\r\n}\r\n","import { useEffect, useState, type ReactNode } from \"react\";\r\nimport { useNavigate } from \"react-router\";\r\n\r\nexport interface ProtectProps {\r\n /** Sync or async function that returns true to allow access, false to redirect. */\r\n condition: () => boolean | Promise<boolean>;\r\n /** Where to redirect when condition returns false. */\r\n redirectTo: string;\r\n /** Optional content to show while an async condition is pending (e.g. a spinner). */\r\n fallback?: ReactNode;\r\n /** Content to render when condition is true. */\r\n children: ReactNode;\r\n}\r\n\r\n/**\r\n * Reusable protection config: condition, redirectTo, and optional fallback.\r\n * Define once in a config file and spread into <Protect {...config}>.\r\n */\r\nexport type ProtectConfig = Pick<ProtectProps, \"condition\" | \"redirectTo\" | \"fallback\">;\r\n\r\n/**\r\n * Protects content by checking a condition before rendering. If the condition\r\n * returns false (sync or async), redirects to redirectTo. Use this to guard\r\n * a single route's content or an entire layout's <Outlet />.\r\n */\r\nexport function Protect({ condition, redirectTo, fallback = null, children }: ProtectProps) {\r\n const navigate = useNavigate();\r\n const [allowed, setAllowed] = useState<boolean | null>(null);\r\n\r\n useEffect(() => {\r\n let cancelled = false;\r\n const result = condition();\r\n if (typeof result === \"boolean\") {\r\n if (!cancelled) setAllowed(result);\r\n if (!result) navigate(redirectTo, { replace: true });\r\n return;\r\n }\r\n result.then((ok) => {\r\n if (!cancelled) setAllowed(ok);\r\n if (!ok) navigate(redirectTo, { replace: true });\r\n });\r\n return () => {\r\n cancelled = true;\r\n };\r\n }, [condition, redirectTo, navigate]);\r\n\r\n if (allowed === null) return <>{fallback}</>;\r\n if (!allowed) return null;\r\n return <>{children}</>;\r\n}\r\n","import { StrictMode, useMemo, useRef } from \"react\";\r\nimport { createRoot } from \"react-dom/client\";\r\nimport { createBrowserRouter, RouterProvider } from \"react-router\";\r\nimport { createRoutes } from \"./createRoutes\";\r\nimport type { CreateRoutesOptions, PagesGlob } from \"./types\";\r\n\r\n/**\r\n * Options for LinkrApp and createRootWithLinkr.\r\n * Same as CreateRoutesOptions (pagesGlob required; rest optional).\r\n */\r\nexport type LinkrAppOptions = { pagesGlob: PagesGlob } & Omit<CreateRoutesOptions, \"pagesGlob\">;\r\n\r\n/**\r\n * Renders the file-based router. Options are read once on mount.\r\n * Use this when you need to wrap the app with your own providers.\r\n */\r\nexport function LinkrApp(options: LinkrAppOptions) {\r\n const optionsRef = useRef(options);\r\n optionsRef.current = options;\r\n const router = useMemo(\r\n () => createBrowserRouter(createRoutes(optionsRef.current)),\r\n []\r\n );\r\n return <RouterProvider router={router} />;\r\n}\r\n\r\n/**\r\n * One-shot setup: creates the root, builds routes from pagesGlob, and renders\r\n * with StrictMode + RouterProvider. Minimizes app entry to a single call.\r\n *\r\n * @example\r\n * ```tsx\r\n * import { createRootWithLinkr } from \"@epicabdou/linkr\";\r\n * createRootWithLinkr(document.getElementById(\"root\")!, {\r\n * pagesGlob: import.meta.glob(\"./pages/**\\/*.tsx\"),\r\n * pagesDir: \"pages\",\r\n * });\r\n * ```\r\n */\r\nexport function createRootWithLinkr(\r\n rootElement: HTMLElement,\r\n options: LinkrAppOptions\r\n): ReturnType<typeof createRoot> {\r\n const router = createBrowserRouter(createRoutes(options));\r\n const root = createRoot(rootElement);\r\n root.render(\r\n <StrictMode>\r\n <RouterProvider router={router} />\r\n </StrictMode>\r\n );\r\n return root;\r\n}\r\n"],"mappings":"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","names":["node","segs","jsx"]}
|