aaex-file-router 1.3.0 → 1.3.1

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
@@ -2,10 +2,34 @@
2
2
 
3
3
  A file-based routing system for React projects that automatically generates routes from your file structure. Similar to Next.js App Router or Remix file conventions.
4
4
 
5
- ## V. 1.3.0
6
- Routes are now able to be infinetly nested
7
-
8
- **Notice** Onlyt tested 3 levels deep but there is no reason i shouldnt work further
5
+ ## V. 1.3.1
6
+
7
+ Routes are now able to be infinitely nested
8
+
9
+ **Notice** Only tested 3 levels deep but there is no reason i shouldnt work further
10
+
11
+ ## Table of Contents
12
+
13
+ - [Features](#features)
14
+ - [Installation](#installation)
15
+ - [Quick Start](#quick-start)
16
+ - [1. Create your pages structure](#1-create-your-pages-structure)
17
+ - [2. Configure Vite](#2-configure-vite)
18
+ - [3. Use in your app](#3-use-in-your-app)
19
+ - [Using createBrowserRouter](#1-using-createbrowserrouter-recommended-for-most-users)
20
+ - [Using nested Route elements](#2-using-nested-route-elements)
21
+ - [File Conventions](#file-conventions)
22
+ - [Generated Routes File](#generated-routes-file)
23
+ - [Route Resolution Examples](#route-resolution-examples)
24
+ - [Layouts](#layouts)
25
+ - [FileLink component](#filelink-component)
26
+ - [Usage](#usage)
27
+ - [API Reference](#api-reference)
28
+ - [How It Works](#how-it-works)
29
+ - [Performance Considerations](#performance-considerations)
30
+ - [Common Patterns](#common-patterns)
31
+ - [Troubleshooting](#troubleshooting)
32
+ - [License](#license)
9
33
 
10
34
  ## Features
11
35
 
@@ -44,7 +68,7 @@ src/pages/
44
68
  // vite.config.ts
45
69
  import { defineConfig } from "vite";
46
70
  import react from "@vitejs/plugin-react";
47
- import { aaexFileRouter } from "aaex-file-router";
71
+ import { aaexFileRouter } from "aaex-file-router/plugin";
48
72
 
49
73
  export default defineConfig({
50
74
  plugins: [
@@ -59,20 +83,66 @@ export default defineConfig({
59
83
 
60
84
  ### 3. Use in your app
61
85
 
86
+ #### 1. Using createBrowserRouter (recommended for most users)
87
+
62
88
  ```typescript
63
- // src/main.tsx
64
- import React from "react";
65
- import ReactDOM from "react-dom/client";
66
- import { RouterProvider, createBrowserRouter } from "react-router-dom";
89
+ // src/App.tsx
90
+ import "./App.css";
67
91
  import routes from "./routes";
92
+ import { createBrowserRouter, RouterProvider } from "react-router-dom";
93
+ import { Suspense } from "react";
94
+
95
+ function App() {
96
+ const router = createBrowserRouter(routes);
97
+
98
+ return (
99
+ <Suspense fallback={<div>Loading...</div>}>
100
+ <RouterProvider router={router} />
101
+ </Suspense>
102
+ );
103
+ }
104
+
105
+ export default App;
106
+ ```
107
+
108
+ ## **OR**
109
+
110
+ ### 2. using nested Route elements
68
111
 
69
- const router = createBrowserRouter(routes);
112
+ **Note** I will probably create a custom route provider using this version later since this is the only solution that works with VITE-SSR if you wrap client in `<BrowserRouter/>` and server in `<StaticRouter/>`
113
+
114
+ ```tsx
115
+ //src/App.tsx
116
+ import {
117
+ BrowserRouter,
118
+ Routes,
119
+ Route,
120
+ type RouteObject,
121
+ } from "react-router-dom";
122
+ import routes from "./routes";
123
+ import { Suspense } from "react";
124
+ import "./App.css";
125
+
126
+ //recursivly creates nested routes
127
+ function createRoutes(route: RouteObject) {
128
+ return (
129
+ <Route key={route.path} path={route.path} element={route.element}>
130
+ {route.children?.map((child) => createRoutes(child))}
131
+ </Route>
132
+ );
133
+ }
134
+
135
+ function App() {
136
+ return (
137
+ <BrowserRouter>
138
+ <Suspense fallback={<div>Loading...</div>}>
139
+ <Routes>{routes.map((route) => createRoutes(route))}</Routes>
140
+ </Suspense>
141
+ </BrowserRouter>
142
+ );
143
+ }
70
144
 
71
- ReactDOM.createRoot(document.getElementById("root")!).render(
72
- <React.StrictMode>
73
- <RouterProvider router={router} />
74
- </React.StrictMode>
75
- );
145
+ export default App;
76
146
  ```
77
147
 
78
148
  ## File Conventions
@@ -106,14 +176,14 @@ export default function AdminLayout() {
106
176
 
107
177
  ### Slug files
108
178
 
109
- Filenames wrapper in hardbrackets `[filename]` will resolve to a dynamic route
179
+ Filenames wrapper in square brackets `[filename]` will resolve to a dynamic route
110
180
 
111
181
  ```
112
- pages/test/[<filename>].tsx → "/test/:<filename>"
182
+ src/pages/test/[<filename>].tsx → "/test/:<filename>"
113
183
  ```
114
184
 
115
185
  ```tsx
116
- //pages/test/[slug].tsx
186
+ // src/pages/test/[slug].tsx
117
187
 
118
188
  import { useParams } from "react-router-dom";
119
189
 
@@ -165,20 +235,20 @@ export default routes;
165
235
 
166
236
  ## Route Resolution Examples
167
237
 
168
- | File Structure | Route Path |
169
- | ----------------------------------- | -------------------- |
170
- | `pages/index.tsx` | `/` |
171
- | `pages/about.tsx` | `/about` |
172
- | `pages/blog/index.tsx` | `/blog` |
173
- | `pages/blog/post.tsx` | `/blog/post` |
174
- | `pages/admin/layout.tsx` + children | `/admin/*` (grouped) |
238
+ | File Structure | Route Path |
239
+ | --------------------------------------- | -------------------- |
240
+ | `src/pages/index.tsx` | `/` |
241
+ | `src/pages/about.tsx` | `/about` |
242
+ | `src/pages/blog/index.tsx` | `/blog` |
243
+ | `src/pages/blog/post.tsx` | `/blog/post` |
244
+ | `src/pages/admin/layout.tsx` + children | `/admin/*` (grouped) |
175
245
 
176
246
  ## Layouts
177
247
 
178
248
  Layouts wrap their child routes and provide shared UI:
179
249
 
180
250
  ```typescript
181
- // pages/dashboard/layout.tsx
251
+ // src/pages/dashboard/layout.tsx
182
252
  import { Outlet } from "react-router-dom";
183
253
 
184
254
  export default function DashboardLayout() {
@@ -193,7 +263,7 @@ export default function DashboardLayout() {
193
263
  }
194
264
  ```
195
265
 
196
- All routes in `pages/dashboard/*` will render inside this layout.
266
+ All routes in `src/pages/dashboard/*` will render inside this layout.
197
267
 
198
268
  ## FileLink component
199
269
 
@@ -215,7 +285,7 @@ export type FileRoutes = "/" | "test";
215
285
  ```
216
286
 
217
287
  ```tsx
218
- //src/pages/index.tsx
288
+ // src/pages/index.tsx
219
289
  import { FileLink } from "aaex-file-router";
220
290
  import type { FileRoutes } from "../routeTypes";
221
291
 
@@ -225,7 +295,7 @@ export default function Home() {
225
295
  Hello Home!
226
296
  {/* FileRoutes is optional and not required it will work fine with any string if not passed */}
227
297
  <FileLink<FileRoutes> to="test">Test safe</FileLink>
228
- //or //no type safety
298
+ {/* or without type safety */}
229
299
  <FileLink to="some-route">Non safe</FileLink>
230
300
  </>
231
301
  );
@@ -261,7 +331,7 @@ const routesCode = await generator.generateComponentsMap(fileData);
261
331
  Automatically watches for file changes and regenerates routes.
262
332
 
263
333
  ```typescript
264
- import { aaexFileRouter } from "aaex-file-router/core";
334
+ import { aaexFileRouter } from "aaex-file-router/plugin";
265
335
 
266
336
  export default defineConfig({
267
337
  plugins: [
@@ -1,5 +1,3 @@
1
1
  export { FileScanner } from './FileScanner.js';
2
2
  export { RouteGenerator } from './RouteGenerator.js';
3
- export { aaexFileRouter } from '../plugin.js';
4
- export type { VitePluginOptions } from '../plugin.js';
5
3
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAGrD,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,YAAY,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC"}
@@ -1,5 +1,4 @@
1
1
  export { FileScanner } from './FileScanner.js';
2
2
  export { RouteGenerator } from './RouteGenerator.js';
3
3
  // export type { FileData } from './core/types';
4
- export { aaexFileRouter } from '../plugin.js';
5
4
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,gDAAgD;AAEhD,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,gDAAgD"}
@@ -0,0 +1,3 @@
1
+ export { aaexFileRouter } from '../plugin/plugin.js';
2
+ export type { VitePluginOptions } from '../plugin/plugin.js';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/plugin/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,YAAY,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { aaexFileRouter } from '../plugin/plugin.js';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/plugin/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC"}
@@ -0,0 +1,11 @@
1
+ import { Plugin } from "vite";
2
+ export interface VitePluginOptions {
3
+ pagesDir?: string;
4
+ outputFile?: string;
5
+ }
6
+ /**
7
+ * Vite plugin that auto-generates routes when page files change
8
+ * Watches the pages directory and regenerates routes.ts on file create/delete
9
+ */
10
+ export declare function aaexFileRouter(options?: VitePluginOptions): Plugin;
11
+ //# sourceMappingURL=plugin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../../src/plugin/plugin.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAM9B,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,OAAO,GAAE,iBAAsB,GAAG,MAAM,CAmDtE"}
@@ -0,0 +1,48 @@
1
+ import { promises as fs } from "node:fs";
2
+ import path from "path";
3
+ import { FileScanner } from "../core/FileScanner.js";
4
+ import { RouteGenerator } from "../core/RouteGenerator.js";
5
+ /**
6
+ * Vite plugin that auto-generates routes when page files change
7
+ * Watches the pages directory and regenerates routes.ts on file create/delete
8
+ */
9
+ export function aaexFileRouter(options = {}) {
10
+ const pagesDir = options.pagesDir || "./src/pages";
11
+ const outputFile = options.outputFile || "./src/routes.ts";
12
+ let scanner;
13
+ let generator;
14
+ return {
15
+ name: "aaex-file-router",
16
+ apply: "serve", // Only run in dev mode
17
+ configResolved() {
18
+ scanner = new FileScanner(pagesDir);
19
+ generator = new RouteGenerator();
20
+ },
21
+ async configureServer(server) {
22
+ // Watch the pages directory for changes
23
+ server.watcher.add(path.resolve(process.cwd(), pagesDir));
24
+ server.watcher.on("all", async (event, filePath) => {
25
+ // Only regenerate on file add/unlink events
26
+ if (event === "add" || event === "unlink") {
27
+ try {
28
+ console.log(`📄 [aaex-file-router] ${event}: ${filePath}`);
29
+ // Regenerate routes
30
+ scanner = new FileScanner(pagesDir);
31
+ generator = new RouteGenerator();
32
+ const fileData = await scanner.get_file_data();
33
+ const routesCode = await generator.generateRoutesFile(fileData);
34
+ const routesType = await generator.generateRoutesTypeDef(fileData);
35
+ // Write routes file
36
+ await fs.writeFile(outputFile, routesCode, "utf-8");
37
+ await fs.writeFile("src/routeTypes.ts", routesType, "utf-8");
38
+ console.log(`✅ [aaex-file-router] Routes regenerated at ${outputFile}`);
39
+ }
40
+ catch (error) {
41
+ console.error("❌ [aaex-file-router] Error regenerating routes:", error);
42
+ }
43
+ }
44
+ });
45
+ },
46
+ };
47
+ }
48
+ //# sourceMappingURL=plugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin.js","sourceRoot":"","sources":["../../src/plugin/plugin.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,IAAI,EAAE,EAAE,MAAM,SAAS,CAAC;AACzC,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAO3D;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,UAA6B,EAAE;IAC5D,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,aAAa,CAAC;IACnD,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,iBAAiB,CAAC;IAE3D,IAAI,OAAoB,CAAC;IACzB,IAAI,SAAyB,CAAC;IAE9B,OAAO;QACL,IAAI,EAAE,kBAAkB;QACxB,KAAK,EAAE,OAAO,EAAE,uBAAuB;QAEvC,cAAc;YACZ,OAAO,GAAG,IAAI,WAAW,CAAC,QAAQ,CAAC,CAAC;YACpC,SAAS,GAAG,IAAI,cAAc,EAAE,CAAC;QACnC,CAAC;QAED,KAAK,CAAC,eAAe,CAAC,MAAM;YAC1B,wCAAwC;YACxC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,QAAQ,CAAC,CAAC,CAAC;YAE1D,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE;gBACjD,4CAA4C;gBAC5C,IAAI,KAAK,KAAK,KAAK,IAAI,KAAK,KAAK,QAAQ,EAAE,CAAC;oBAC1C,IAAI,CAAC;wBACH,OAAO,CAAC,GAAG,CAAC,yBAAyB,KAAK,KAAK,QAAQ,EAAE,CAAC,CAAC;wBAE3D,oBAAoB;wBACpB,OAAO,GAAG,IAAI,WAAW,CAAC,QAAQ,CAAC,CAAC;wBACpC,SAAS,GAAG,IAAI,cAAc,EAAE,CAAC;wBAEjC,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,aAAa,EAAE,CAAC;wBAC/C,MAAM,UAAU,GAAG,MAAM,SAAS,CAAC,kBAAkB,CAAC,QAAQ,CAAC,CAAC;wBAChE,MAAM,UAAU,GAAG,MAAM,SAAS,CAAC,qBAAqB,CAAC,QAAQ,CAAC,CAAC;wBAEnE,oBAAoB;wBACpB,MAAM,EAAE,CAAC,SAAS,CAAC,UAAU,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC;wBACpD,MAAM,EAAE,CAAC,SAAS,CAAC,mBAAmB,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC;wBAE7D,OAAO,CAAC,GAAG,CACT,8CAA8C,UAAU,EAAE,CAC3D,CAAC;oBACJ,CAAC;oBAAC,OAAO,KAAK,EAAE,CAAC;wBACf,OAAO,CAAC,KAAK,CACX,iDAAiD,EACjD,KAAK,CACN,CAAC;oBACJ,CAAC;gBACH,CAAC;YACH,CAAC,CAAC,CAAC;QACL,CAAC;KACF,CAAC;AACJ,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aaex-file-router",
3
- "version": "1.3.0",
3
+ "version": "1.3.1",
4
4
  "description": "A file-based routing system for React projects that automatically generates routes from your file structure. Similar to Next.js App Router or Remix file conventions.",
5
5
  "main": "dist/index.js",
6
6
  "scripts": {
@@ -16,7 +16,8 @@
16
16
 
17
17
  "exports":{
18
18
  ".": "./dist/index.js",
19
- "./core": "./dist/core/index.js"
19
+ "./core": "./dist/core/index.js",
20
+ "./plugin": "./dist/plugin/index.js"
20
21
  },
21
22
  "author": "TmRAaEx",
22
23
  "license": "MIT",