@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 CHANGED
@@ -1,6 +1,6 @@
1
- # linkr.js
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` (the consumer passes the glob result; the library does not call it).
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 deps: `react`, `react-dom`, `react-router` (v7+).
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
- - **`pagesGlob`** (required): result of `import.meta.glob("...")` from your app.
27
- - **`pagesDir`** (optional, default `"src/pages"`): base path used to normalize file paths. Must match the prefix you strip from glob keys (e.g. use `"pages"` when glob is `./pages/**/*.tsx` from `src/`).
28
- - **`layoutFileName`** (optional, default `"_layout"`).
29
- - **`notFoundFileName`** (optional, default `"404"`).
30
- - **`routeExtensions`** (optional, default `[".tsx", ".ts", ".jsx", ".js"]`).
31
- - **`defaultRedirectTo`** (optional, default `"/"`): default redirect path when a route's `protect` check fails and no `redirectTo` is set.
32
- - **`layoutsGlob`** (optional): result of `import.meta.glob("./layouts/**/*.tsx")`; when set with **`layoutMap`**, layouts are loaded from this folder and _layout files in pages are ignored. See [Layouts in a separate folder](#layouts-in-a-separate-folder).
33
- - **`layoutsDir`** (optional, default `"src/layouts"`): base path for layout files.
34
- - **`layoutMap`** (optional): path prefix → layout name. Use `""` or `"/"` for root, segment name (e.g. `blog`) for nested. Requires **`layoutsGlob`**.
35
-
36
- ## Conventions
37
-
38
- | File / pattern | Route |
39
- |-----------------------|---------------------------------|
40
- | `index.tsx` | `/` (index route) |
41
- | `about.tsx` | `/about` |
42
- | `blog/index.tsx` | `/blog` (index under blog) |
43
- | `blog/[id].tsx` | `/blog/:id` |
44
- | `docs/[...slug].tsx` | `/docs/*` (splat) |
45
- | `404.tsx` | `path: "*"` (last) |
46
- | `_layout.tsx` (any folder) | Layout route; children render in `<Outlet />` (ignored when using **layoutsGlob** + **layoutMap**) |
47
-
48
- - **Nested routes**: folder nesting = nested routes.
49
- - **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.
50
- - **Sort order**: among siblings, static segments first, then dynamic (`:id`), then splat (`*`).
51
- - **Lazy loading**: every route uses React Router's `lazy()` for code splitting.
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
- - **`default`**: React component used as the route element (required).
56
- - **`ErrorBoundary`**: optional; used as `errorElement`.
57
- - **`handle`**: optional; attached to the route's `handle`.
58
- - **`protect`**: optional; run a condition before rendering the route (or layout). When the check returns `false`, the user is redirected. See [Route protection](#route-protection).
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><Link to="/blog">Blog</Link></nav>
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() { return <div><h2>Blog</h2><Outlet /></div>; }
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** keys: `""` or `"/"` = root layout; `"blog"` = layout for `/blog` and its children. Value = layout filename without extension (e.g. `Root`, `Blog`).
97
- - The same layout component can be reused for multiple segments by mapping multiple keys to the same name.
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
- Pass a default redirect when creating routes:
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 (wrap a route or layout content)
211
+ ### 2. `<Protect>` component
148
212
 
149
- Use the `<Protect>` component when you want to guard content inside a layout (e.g. wrap `<Outlet />`) or need a stable condition with a fallback UI.
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 in a config file, then reuse with `<Protect {...config}>`.
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 (or src/lib/auth.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
- You can define multiple configs (e.g. `authProtect`, `adminProtect`) in the same file and import the one you need.
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 --filter linkr build
197
- pnpm --filter linkr test
287
+ pnpm build
288
+ pnpm test
198
289
  ```
package/dist/index.js CHANGED
@@ -223,6 +223,7 @@ function makeLazyRoute(loader, filePath, defaultRedirectTo) {
223
223
  if (!ok) throw redirect(redirectTo);
224
224
  return null;
225
225
  };
226
+ result.HydrateFallback = () => null;
226
227
  }
227
228
  return result;
228
229
  };
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":";AACA,SAAS,gBAAgB;;;ACElB,SAAS,cAAc,GAAmB;AAC/C,SAAO,EAAE,QAAQ,OAAO,GAAG;AAC7B;AAKO,SAAS,kBACd,UACA,YACe;AACf,QAAM,QAAQ,SAAS,YAAY;AACnC,aAAW,OAAO,YAAY;AAC5B,QAAI,MAAM,SAAS,GAAG,EAAG,QAAO;AAAA,EAClC;AACA,SAAO;AACT;AAeO,SAAS,aAAa,SAAgC;AAC3D,MAAI,QAAQ,WAAW,MAAM,KAAK,QAAQ,SAAS,GAAG,GAAG;AACvD,UAAM,QAAQ,QAAQ,MAAM,GAAG,EAAE;AACjC,WAAO,EAAE,KAAK,SAAS,MAAM,SAAS,WAAW,SAAS,QAAQ;AAAA,EACpE;AACA,MAAI,QAAQ,WAAW,GAAG,KAAK,QAAQ,SAAS,GAAG,GAAG;AACpD,UAAM,QAAQ,QAAQ,MAAM,GAAG,EAAE;AACjC,WAAO,EAAE,KAAK,SAAS,MAAM,WAAW,WAAW,SAAS,QAAQ;AAAA,EACtE;AACA,SAAO,EAAE,KAAK,SAAS,MAAM,SAAS;AACxC;AAKO,SAAS,gBAAgB,GAAkB,GAA0B;AAC1E,QAAM,QAAQ,EAAE,QAAQ,GAAG,SAAS,GAAG,OAAO,EAAE;AAChD,QAAM,OAAO,MAAM,EAAE,IAAI,IAAI,MAAM,EAAE,IAAI;AACzC,MAAI,SAAS,EAAG,QAAO;AACvB,SAAO,EAAE,IAAI,cAAc,EAAE,GAAG;AAClC;;;AD3CA,IAAM,oBAAoB;AAC1B,IAAM,sBAAsB;AAC5B,IAAM,sBAAsB;AAC5B,IAAM,yBAAyB;AAC/B,IAAM,qBAAqB,CAAC,QAAQ,OAAO,QAAQ,KAAK;AAGxD,SAAS,iBACP,aACA,YACA,YACqC;AACrC,QAAM,MAAM,oBAAI,IAAoC;AACpD,QAAM,MAAM,cAAc,UAAU,EAAE,QAAQ,OAAO,EAAE;AACvD,aAAW,OAAO,OAAO,KAAK,WAAW,GAAG;AAC1C,UAAM,aAAa,cAAc,GAAG,EAAE,QAAQ,SAAS,EAAE;AACzD,QAAI,WAAW;AACf,QAAI,SAAS,WAAW,MAAM,GAAG,EAAG,YAAW,SAAS,MAAM,IAAI,SAAS,CAAC;AAAA,aACnE,SAAS,WAAW,GAAG,EAAG,YAAW,SAAS,MAAM,IAAI,MAAM,EAAE,QAAQ,OAAO,EAAE;AAC1F,UAAM,MAAM,kBAAkB,UAAU,UAAU;AAClD,QAAI,CAAC,IAAK;AACV,UAAM,aAAa,SAAS,MAAM,GAAG,CAAC,IAAI,MAAM;AAChD,UAAM,QAAQ,WAAW,MAAM,GAAG,EAAE,OAAO,OAAO;AAClD,QAAI,MAAM,WAAW,EAAG;AACxB,UAAM,OAAO,MAAM,MAAM,SAAS,CAAC;AACnC,QAAI,IAAI,MAAM,YAAY,GAAG,CAAC;AAAA,EAChC;AACA,SAAO;AACT;AAYA,SAAS,eAAe,UAAkB,YAA8B;AACtE,QAAM,QAAQ,SAAS,YAAY;AACnC,aAAW,OAAO,YAAY;AAC5B,QAAI,MAAM,SAAS,GAAG,EAAG,QAAO,SAAS,MAAM,GAAG,CAAC,IAAI,MAAM;AAAA,EAC/D;AACA,SAAO;AACT;AAKA,SAAS,oBAAoB,SAA0B;AACrD,SAAO,qBAAqB,KAAK,OAAO;AAC1C;AAKA,SAAS,cAAc,MAAoB;AACzC,MAAI,OAAO,YAAY,eAAe,QAAQ,KAAK,aAAa,cAAc;AAC5E,YAAQ,KAAK,yDAAyD,IAAI,EAAE;AAAA,EAC9E;AACF;AAKA,SAAS,iBAAiB,MAAoB;AAC5C,MAAI,OAAO,YAAY,eAAe,QAAQ,KAAK,aAAa,cAAc;AAC5E,YAAQ;AAAA,MACN,sGAAsG,IAAI;AAAA,IAC5G;AAAA,EACF;AACF;AAWA,SAAS,aACP,KACA,MACkB;AAClB,QAAM,aAAa,cAAc,GAAG;AACpC,QAAM,sBAAsB,WAAW,QAAQ,SAAS,EAAE;AAC1D,QAAM,MAAM,cAAc,KAAK,QAAQ,EAAE,QAAQ,OAAO,EAAE;AAC1D,MAAI,WAAW;AACf,MAAI,SAAS,WAAW,MAAM,GAAG,GAAG;AAClC,eAAW,SAAS,MAAM,IAAI,SAAS,CAAC;AAAA,EAC1C,WAAW,SAAS,WAAW,GAAG,GAAG;AACnC,eAAW,SAAS,MAAM,IAAI,MAAM,EAAE,QAAQ,OAAO,EAAE;AAAA,EACzD,WAAW,IAAI,SAAS,GAAG,GAAG;AAC5B,UAAM,iBAAiB,IAAI,MAAM,GAAG,EAAE,IAAI;AAC1C,QAAI,SAAS,WAAW,iBAAiB,GAAG,GAAG;AAC7C,iBAAW,SAAS,MAAM,eAAe,SAAS,CAAC;AAAA,IACrD;AAAA,EACF;AAEA,QAAM,MAAM,kBAAkB,UAAU,KAAK,eAAe;AAC5D,MAAI,CAAC,IAAK,QAAO;AAEjB,QAAM,aAAa,SAAS,MAAM,GAAG,CAAC,IAAI,MAAM;AAChD,QAAM,QAAQ,WAAW,MAAM,GAAG,EAAE,OAAO,OAAO;AAClD,MAAI,MAAM,WAAW,EAAG,QAAO;AAE/B,QAAM,WAAW,MAAM,MAAM,SAAS,CAAC;AACvC,QAAM,WAAW,eAAe,UAAU,KAAK,eAAe,MAAM,KAAK;AACzE,QAAM,QAAQ,eAAe,UAAU,KAAK,eAAe,MAAM,KAAK;AACtE,QAAM,UAAU,SAAS,YAAY,EAAE,QAAQ,IAAI,OAAO,OAAO,MAAM,KAAK,GAAG,GAAG,EAAE,MAAM;AAC1F,QAAM,eAAe,UAAU,MAAM,MAAM,GAAG,EAAE,IAAI;AACpD,QAAM,iBAAiB,aAAa,IAAI,CAAC,GAAG,MAAM;AAChD,UAAM,SAAS,MAAM,aAAa,SAAS;AAC3C,WAAO,SAAS,eAAe,GAAG,KAAK,eAAe,IAAI;AAAA,EAC5D,CAAC;AAED,QAAM,eAAe,eAAe,IAAI,YAAY;AACpD,aAAW,KAAK,gBAAgB;AAC9B,QAAI,EAAE,SAAS,MAAM,KAAK,CAAC,oBAAoB,CAAC,GAAG;AACjD,uBAAiB,GAAG;AACpB,aAAO;AAAA,IACT;AAAA,EACF;AAEA,SAAO;AAAA,IACL,MAAM;AAAA,IACN,UAAU;AAAA,IACV;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAUA,SAAS,UAAU,SAAiC;AAClD,QAAM,OAAkB;AAAA,IACtB,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,YAAY;AAAA,IACZ,UAAU,oBAAI,IAAI;AAAA,IAClB,cAAc,oBAAI,IAAI;AAAA,EACxB;AAEA,aAAW,SAAS,SAAS;AAC3B,QAAI,MAAM,MAAO;AACjB,QAAI,MAAM,UAAU;AAClB,YAAM,iBAAiB,MAAM,SAAS,MAAM,GAAG,EAAE;AACjD,UAAIA,QAAO;AACX,eAAS,IAAI,GAAG,IAAI,eAAe,QAAQ,KAAK;AAC9C,cAAM,MAAM,eAAe,MAAM,GAAG,IAAI,CAAC,EAAE,KAAK,GAAG;AACnD,YAAI,CAACA,MAAK,aAAa,IAAI,GAAG,GAAG;AAC/B,UAAAA,MAAK,aAAa,IAAI,KAAK;AAAA,YACzB,MAAM;AAAA,YACN,QAAQ;AAAA,YACR,YAAY;AAAA,YACZ,UAAU,oBAAI,IAAI;AAAA,YAClB,cAAc,oBAAI,IAAI;AAAA,UACxB,CAAC;AAAA,QACH;AACA,QAAAA,QAAOA,MAAK,aAAa,IAAI,GAAG;AAAA,MAClC;AACA,MAAAA,MAAK,SAAS;AACd;AAAA,IACF;AAEA,QAAI,MAAM,WAAW,MAAM,SAAS,WAAW,GAAG;AAChD,WAAK,aAAa;AAClB;AAAA,IACF;AAEA,QAAI,MAAM,SAAS;AACjB,UAAIA,QAAO;AACX,YAAMC,QAAO,MAAM;AACnB,eAAS,IAAI,GAAG,IAAIA,MAAK,QAAQ,KAAK;AACpC,cAAM,MAAMA,MAAK,MAAM,GAAG,IAAI,CAAC,EAAE,KAAK,GAAG;AACzC,YAAID,MAAK,aAAa,IAAI,GAAG,GAAG;AAC9B,UAAAA,QAAOA,MAAK,aAAa,IAAI,GAAG;AAAA,QAClC,OAAO;AACL,gBAAM,OAAkB;AAAA,YACtB,MAAM;AAAA,YACN,QAAQ;AAAA,YACR,YAAY;AAAA,YACZ,UAAU,oBAAI,IAAI;AAAA,YAClB,cAAc,oBAAI,IAAI;AAAA,UACxB;AACA,UAAAA,MAAK,aAAa,IAAI,KAAK,IAAI;AAC/B,UAAAA,QAAO;AAAA,QACT;AAAA,MACF;AACA,MAAAA,MAAK,aAAa;AAClB;AAAA,IACF;AAEA,UAAM,OAAO,MAAM;AACnB,QAAI,OAAO;AACX,aAAS,IAAI,GAAG,IAAI,KAAK,SAAS,GAAG,KAAK;AACxC,YAAM,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC,EAAE,KAAK,GAAG;AACzC,UAAI,KAAK,aAAa,IAAI,GAAG,GAAG;AAC9B,eAAO,KAAK,aAAa,IAAI,GAAG;AAAA,MAClC,OAAO;AACL,cAAM,OAAkB;AAAA,UACtB,MAAM;AAAA,UACN,QAAQ;AAAA,UACR,YAAY;AAAA,UACZ,UAAU,oBAAI,IAAI;AAAA,UAClB,cAAc,oBAAI,IAAI;AAAA,QACxB;AACA,aAAK,aAAa,IAAI,KAAK,IAAI;AAC/B,eAAO;AAAA,MACT;AAAA,IACF;AACA,UAAM,UAAU,KAAK,KAAK,SAAS,CAAC;AACpC,SAAK,SAAS,IAAI,SAAS,EAAE,MAAM,CAAC;AAAA,EACtC;AAEA,SAAO;AACT;AAEA,SAAS,cAAc,SAAgC;AACrD,MAAI,QAAQ,SAAS,SAAU,QAAO,QAAQ;AAC9C,MAAI,QAAQ,SAAS,UAAW,QAAO,OAAO,QAAQ,aAAa;AACnE,MAAI,QAAQ,SAAS,QAAS,QAAO;AACrC,SAAO,QAAQ;AACjB;AAEA,SAAS,cACP,QACA,UACA,mBACqB;AACrB,SAAO,YAAY;AACjB,UAAM,MAAO,MAAM,OAAO;AAC1B,QAAI,CAAC,IAAI,SAAS;AAChB,oBAAc,QAAQ;AACtB,aAAO,EAAE,WAAW,MAAM,KAAK;AAAA,IACjC;AACA,UAAM,SAAkC,EAAE,WAAW,IAAI,QAAQ;AACjE,QAAI,IAAI,cAAe,QAAO,gBAAgB,IAAI;AAClD,QAAI,IAAI,WAAW,OAAW,QAAO,SAAS,IAAI;AAElD,QAAI,IAAI,SAAS;AACf,YAAM,QAAQ,OAAO,IAAI,YAAY,aAAa,IAAI,UAAU,IAAI,QAAQ;AAC5E,YAAM,cACH,OAAO,IAAI,YAAY,YAAY,IAAI,QAAQ,cAAc,OAC1D,IAAI,QAAQ,aACZ,sBAAsB;AAC5B,aAAO,SAAS,YAAY;AAC1B,cAAM,KAAK,MAAM,QAAQ,QAAQ,MAAM,CAAC;AACxC,YAAI,CAAC,GAAI,OAAM,SAAS,UAAU;AAClC,eAAO;AAAA,MACT;AAEA,aAAO,kBAAkB,MAAM;AAAA,IACjC;AAEA,WAAO;AAAA,EAOT;AACF;AAEA,SAAS,aACP,MACA,YACA,WACA,mBACA,WACA,eACe;AACf,QAAM,oBAAmC,CAAC;AAE1C,MAAI,KAAK,YAAY;AACnB,UAAM,SAAS,UAAU,KAAK,WAAW,IAAI;AAC7C,QAAI,QAAQ;AACV,wBAAkB,KAAK;AAAA,QACrB,OAAO;AAAA,QACP,MAAM,cAAc,QAAQ,KAAK,WAAW,MAAM,iBAAiB;AAAA,MACrE,CAAC;AAAA,IACH;AAAA,EACF;AAEA,QAAM,gBAAgB,MAAM,KAAK,KAAK,SAAS,QAAQ,CAAC;AACxD,gBAAc,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,gBAAgB,aAAa,CAAC,GAAG,aAAa,CAAC,CAAC,CAAC;AAElF,aAAW,CAAC,QAAQ,EAAE,MAAM,CAAC,KAAK,eAAe;AAC/C,UAAM,MAAM,aAAa,MAAM;AAC/B,UAAM,UAAU,cAAc,GAAG;AACjC,UAAM,SAAS,UAAU,MAAM,IAAI;AACnC,QAAI,CAAC,OAAQ;AACb,sBAAkB,KAAK;AAAA,MACrB,MAAM;AAAA,MACN,MAAM,cAAc,QAAQ,MAAM,MAAM,iBAAiB;AAAA,IAC3D,CAAC;AAAA,EACH;AAEA,QAAM,mBAAmB,MAAM,KAAK,KAAK,aAAa,KAAK,CAAC,EAAE,KAAK,CAAC,GAAG,MAAM;AAC3E,UAAM,QAAQ,EAAE,MAAM,GAAG,EAAE,IAAI,YAAY;AAC3C,UAAM,QAAQ,EAAE,MAAM,GAAG,EAAE,IAAI,YAAY;AAC3C,UAAM,MAAM,KAAK,IAAI,MAAM,QAAQ,MAAM,MAAM;AAC/C,aAAS,IAAI,GAAG,IAAI,KAAK,KAAK;AAC5B,YAAM,IAAI,gBAAgB,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC;AAC5C,UAAI,MAAM,EAAG,QAAO;AAAA,IACtB;AACA,WAAO,MAAM,SAAS,MAAM;AAAA,EAC9B,CAAC;AAED,aAAW,OAAO,kBAAkB;AAClC,UAAM,YAAY,KAAK,aAAa,IAAI,GAAG;AAC3C,UAAM,WAAW,IAAI,MAAM,GAAG,EAAE,CAAC;AACjC,UAAM,MAAM,aAAa,QAAQ;AACjC,UAAM,UAAU,cAAc,GAAG;AACjC,UAAM,SAAS;AAAA,MACb;AAAA,MACA,aAAa,aAAa,MAAM,UAAU;AAAA,MAC1C;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AACA,UAAM,aAAa,aAAa,gBAAgB,UAAU,GAAG,KAAK,UAAU,MAAM,GAAG,IAAI;AACzF,UAAM,eAAe,aAAa,cAAe,IAAI,UAAU,IAAI;AACnE,QAAI,cAAc;AAChB,wBAAkB,KAAK;AAAA,QACrB,MAAM;AAAA,QACN,MAAM,cAAc,cAAc,YAAY,YAAY,iBAAiB;AAAA,QAC3E,UAAU;AAAA,MACZ,CAAC;AAAA,IACH,WAAW,UAAU,UAAU,UAAU,OAAO,QAAQ,WAAW;AACjE,wBAAkB,KAAK,GAAG,MAAM;AAAA,IAClC,WAAW,UAAU,QAAQ;AAC3B,wBAAkB,KAAK,EAAE,MAAM,SAAS,UAAU,OAAO,CAAC;AAAA,IAC5D,WAAW,OAAO,SAAS,GAAG;AAC5B,wBAAkB,KAAK,EAAE,MAAM,SAAS,UAAU,OAAO,CAAC;AAAA,IAC5D;AAAA,EACF;AAEA,MAAI,KAAK,UAAU,KAAK,OAAO,QAAQ,WAAW;AAChD,UAAM,eAAe,UAAU,KAAK,OAAO,IAAI;AAC/C,WAAO,CAAC;AAAA,MACN,MAAM,eAAe,KAAK,MAAM;AAAA,MAChC,MAAM,cAAc,cAAc,KAAK,OAAO,MAAM,iBAAiB;AAAA,MACrE,UAAU,kBAAkB,SAAS,oBAAoB;AAAA,IAC3D,CAAC;AAAA,EACH;AAEA,SAAO;AACT;AAEA,SAAS,oBACP,MACA,WACA,mBACA,WACA,eACe;AACf,QAAM,SAAwB,CAAC;AAE/B,MAAI,KAAK,YAAY;AACnB,UAAM,SAAS,UAAU,KAAK,WAAW,IAAI;AAC7C,QAAI,QAAQ;AACV,aAAO,KAAK;AAAA,QACV,OAAO;AAAA,QACP,MAAM,cAAc,QAAQ,KAAK,WAAW,MAAM,iBAAiB;AAAA,MACrE,CAAC;AAAA,IACH;AAAA,EACF;AAEA,QAAM,gBAAgB,MAAM,KAAK,KAAK,SAAS,QAAQ,CAAC;AACxD,gBAAc,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,gBAAgB,aAAa,CAAC,GAAG,aAAa,CAAC,CAAC,CAAC;AAElF,aAAW,CAAC,QAAQ,EAAE,MAAM,CAAC,KAAK,eAAe;AAC/C,UAAM,MAAM,aAAa,MAAM;AAC/B,UAAM,UAAU,cAAc,GAAG;AACjC,UAAM,SAAS,UAAU,MAAM,IAAI;AACnC,QAAI,CAAC,OAAQ;AACb,WAAO,KAAK;AAAA,MACV,MAAM;AAAA,MACN,MAAM,cAAc,QAAQ,MAAM,MAAM,iBAAiB;AAAA,IAC3D,CAAC;AAAA,EACH;AAEA,QAAM,aAAa,MAAM,KAAK,KAAK,aAAa,KAAK,CAAC,EAAE,KAAK,CAAC,GAAG,MAAM;AACrE,UAAM,QAAQ,EAAE,MAAM,GAAG,EAAE,IAAI,YAAY;AAC3C,UAAM,QAAQ,EAAE,MAAM,GAAG,EAAE,IAAI,YAAY;AAC3C,UAAM,MAAM,KAAK,IAAI,MAAM,QAAQ,MAAM,MAAM;AAC/C,aAAS,IAAI,GAAG,IAAI,KAAK,KAAK;AAC5B,YAAM,IAAI,gBAAgB,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC;AAC5C,UAAI,MAAM,EAAG,QAAO;AAAA,IACtB;AACA,WAAO,MAAM,SAAS,MAAM;AAAA,EAC9B,CAAC;AAED,aAAW,OAAO,YAAY;AAC5B,UAAM,YAAY,KAAK,aAAa,IAAI,GAAG;AAC3C,UAAM,WAAW,IAAI,MAAM,GAAG,EAAE,CAAC;AACjC,UAAM,MAAM,aAAa,QAAQ;AACjC,UAAM,UAAU,cAAc,GAAG;AACjC,UAAM,SAAS;AAAA,MACb;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AACA,UAAM,aAAa,aAAa,gBAAgB,UAAU,GAAG,KAAK,UAAU,MAAM,GAAG,IAAI;AACzF,UAAM,eAAe,aAAa,cAAe,IAAI,UAAU,IAAI;AACnE,QAAI,cAAc;AAChB,aAAO,KAAK;AAAA,QACV,MAAM;AAAA,QACN,MAAM,cAAc,cAAc,YAAY,YAAY,iBAAiB;AAAA,QAC3E,UAAU;AAAA,MACZ,CAAC;AAAA,IACH,WAAW,UAAU,UAAU,UAAU,OAAO,QAAQ,WAAW;AACjE,aAAO,KAAK,GAAG,MAAM;AAAA,IACvB,WAAW,UAAU,QAAQ;AAC3B,aAAO,KAAK,EAAE,MAAM,SAAS,UAAU,OAAO,CAAC;AAAA,IACjD,WAAW,OAAO,SAAS,GAAG;AAC5B,aAAO,KAAK,EAAE,MAAM,SAAS,UAAU,OAAO,CAAC;AAAA,IACjD;AAAA,EACF;AAEA,QAAM,iBAAiB,aAAa,gBAAgB,UAAU,EAAE,KAAK,UAAU,GAAG,IAAI;AACtF,QAAM,mBAAmB,iBAAiB,cAAe,IAAI,cAAc,IAAI;AAC/E,MAAI,oBAAoB,OAAO,SAAS,GAAG;AACzC,WAAO,CAAC;AAAA,MACN,MAAM;AAAA,MACN,MAAM,cAAc,kBAAkB,YAAY,gBAAgB,iBAAiB;AAAA,MACnF,UAAU;AAAA,IACZ,CAAC;AAAA,EACH;AACA,SAAO;AACT;AAEO,SAAS,aAAa,SAA6C;AACxE,QAAM,WAAW,cAAc,QAAQ,YAAY,iBAAiB,EAAE,QAAQ,OAAO,EAAE;AACvF,QAAM,OAAO;AAAA,IACX;AAAA,IACA,gBAAgB,QAAQ,kBAAkB;AAAA,IAC1C,kBAAkB,QAAQ,oBAAoB;AAAA,IAC9C,iBAAiB,QAAQ,mBAAmB;AAAA,EAC9C;AAEA,QAAM,UAAuB,CAAC;AAC9B,aAAW,OAAO,OAAO,KAAK,QAAQ,SAAS,GAAG;AAChD,UAAM,QAAQ,aAAa,KAAK,IAAI;AACpC,QAAI,MAAO,SAAQ,KAAK,KAAK;AAAA,EAC/B;AAEA,QAAM,gBAAgB,QAAQ,KAAK,CAAC,MAAM,EAAE,KAAK;AACjD,QAAM,mBAAmB,QAAQ,eAAe,QAAQ,QAAQ,aAAa;AAC7E,QAAM,OAAO,mBACT,QAAQ,OAAO,CAAC,MAAM,CAAC,EAAE,SAAS,CAAC,EAAE,QAAQ,IAC7C,QAAQ,OAAO,CAAC,MAAM,CAAC,EAAE,KAAK;AAClC,QAAM,OAAO,UAAU,IAAI;AAE3B,QAAM,gBACJ,QAAQ,eAAe,QAAQ,YAC3B;AAAA,IACE,QAAQ;AAAA,IACR,QAAQ,cAAc;AAAA,IACtB,KAAK;AAAA,EACP,IACA;AAEN,MAAI;AAEJ,MAAI,iBAAiB,QAAQ,WAAW;AACtC,qBAAiB;AAAA,MACf;AAAA,MACA,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR;AAAA,IACF;AAAA,EACF,WAAW,KAAK,UAAU,KAAK,OAAO,QAAQ,QAAQ,WAAW;AAC/D,UAAM,eAAe,QAAQ,UAAU,KAAK,OAAO,IAAI;AACvD,qBAAiB,CAAC;AAAA,MAChB,MAAM;AAAA,MACN,MAAM,cAAc,cAAc,KAAK,OAAO,MAAM,QAAQ,iBAAiB;AAAA,MAC7E,UAAU,oBAAoB,MAAM,QAAQ,WAAW,QAAQ,iBAAiB;AAAA,IAClF,CAAC;AAAA,EACH,OAAO;AACL,qBAAiB,oBAAoB,MAAM,QAAQ,WAAW,QAAQ,iBAAiB;AAAA,EACzF;AAEA,MAAI,iBAAiB,cAAc,QAAQ,QAAQ,WAAW;AAC5D,UAAM,SAAS,QAAQ,UAAU,cAAc,IAAI;AACnD,mBAAe,KAAK;AAAA,MAClB,MAAM;AAAA,MACN,MAAM,cAAc,QAAQ,cAAc,MAAM,QAAQ,iBAAiB;AAAA,IAC3E,CAAC;AAAA,EACH;AAEA,SAAO;AACT;;;AE1gBA,SAAS,WAAW,gBAAgC;AACpD,SAAS,mBAAmB;AA6CG;AArBxB,SAAS,QAAQ,EAAE,WAAW,YAAY,WAAW,MAAM,SAAS,GAAiB;AAC1F,QAAM,WAAW,YAAY;AAC7B,QAAM,CAAC,SAAS,UAAU,IAAI,SAAyB,IAAI;AAE3D,YAAU,MAAM;AACd,QAAI,YAAY;AAChB,UAAM,SAAS,UAAU;AACzB,QAAI,OAAO,WAAW,WAAW;AAC/B,UAAI,CAAC,UAAW,YAAW,MAAM;AACjC,UAAI,CAAC,OAAQ,UAAS,YAAY,EAAE,SAAS,KAAK,CAAC;AACnD;AAAA,IACF;AACA,WAAO,KAAK,CAAC,OAAO;AAClB,UAAI,CAAC,UAAW,YAAW,EAAE;AAC7B,UAAI,CAAC,GAAI,UAAS,YAAY,EAAE,SAAS,KAAK,CAAC;AAAA,IACjD,CAAC;AACD,WAAO,MAAM;AACX,kBAAY;AAAA,IACd;AAAA,EACF,GAAG,CAAC,WAAW,YAAY,QAAQ,CAAC;AAEpC,MAAI,YAAY,KAAM,QAAO,gCAAG,oBAAS;AACzC,MAAI,CAAC,QAAS,QAAO;AACrB,SAAO,gCAAG,UAAS;AACrB;;;ACjDA,SAAS,YAAY,SAAS,cAAc;AAC5C,SAAS,kBAAkB;AAC3B,SAAS,qBAAqB,sBAAsB;AAqB3C,gBAAAE,YAAA;AAPF,SAAS,SAAS,SAA0B;AACjD,QAAM,aAAa,OAAO,OAAO;AACjC,aAAW,UAAU;AACrB,QAAM,SAAS;AAAA,IACb,MAAM,oBAAoB,aAAa,WAAW,OAAO,CAAC;AAAA,IAC1D,CAAC;AAAA,EACH;AACA,SAAO,gBAAAA,KAAC,kBAAe,QAAgB;AACzC;AAeO,SAAS,oBACd,aACA,SAC+B;AAC/B,QAAM,SAAS,oBAAoB,aAAa,OAAO,CAAC;AACxD,QAAM,OAAO,WAAW,WAAW;AACnC,OAAK;AAAA,IACH,gBAAAA,KAAC,cACC,0BAAAA,KAAC,kBAAe,QAAgB,GAClC;AAAA,EACF;AACA,SAAO;AACT;","names":["node","segs","jsx"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@epicabdou/linkr",
3
- "version": "0.0.3",
3
+ "version": "0.0.4",
4
4
  "description": "linkr.js — File-based routing for React Router (v7) with Vite",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",