aaex-file-router 1.1.0 → 1.2.0
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 +92 -56
- package/dist/core/RouteGenerator.d.ts +0 -1
- package/dist/core/RouteGenerator.d.ts.map +1 -1
- package/dist/core/RouteGenerator.js +101 -113
- package/dist/core/RouteGenerator.js.map +1 -1
- package/dist/pages/users/[id].d.ts +1 -0
- package/dist/pages/users/[id].d.ts.map +1 -0
- package/dist/pages/users/[id].js +2 -0
- package/dist/pages/users/[id].js.map +1 -0
- package/dist/test/index.js +3 -4
- package/dist/test/index.js.map +1 -1
- package/package.json +48 -48
package/README.md
CHANGED
|
@@ -2,13 +2,16 @@
|
|
|
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.
|
|
6
|
-
|
|
5
|
+
## V. 1.2.0
|
|
6
|
+
|
|
7
|
+
Added support for slugs in urls ex: - pages - users - [id].tsx
|
|
8
|
+
resolves to users/:id
|
|
7
9
|
|
|
8
10
|
## Features
|
|
9
11
|
|
|
10
12
|
- **Automatic Route Generation**: Routes are generated based on your file and folder structure
|
|
11
13
|
- **Layout Support**: Create `layout.tsx` files to wrap nested routes
|
|
14
|
+
- **Slug Support**: Creates dynamic routes for [slug] files
|
|
12
15
|
- **Static & Lazy Loading**: Top-level routes use static imports, nested routes use lazy loading
|
|
13
16
|
- **Hot Reload**: Vite plugin watches for file changes and regenerates routes automatically
|
|
14
17
|
- **TypeScript Support**: Full TypeScript support with generated route types
|
|
@@ -31,23 +34,24 @@ src/pages/
|
|
|
31
34
|
└── test/
|
|
32
35
|
├── layout.tsx # Layout wrapper for /test/* routes
|
|
33
36
|
├── index.tsx # Route "/test"
|
|
34
|
-
|
|
37
|
+
├── hello.tsx # Route "/test/hello"
|
|
38
|
+
└── [slug].tsx # Route "/test/:slug"
|
|
35
39
|
```
|
|
36
40
|
|
|
37
41
|
### 2. Configure Vite
|
|
38
42
|
|
|
39
43
|
```typescript
|
|
40
44
|
// vite.config.ts
|
|
41
|
-
import { defineConfig } from
|
|
42
|
-
import react from
|
|
43
|
-
import { aaexFileRouter } from
|
|
45
|
+
import { defineConfig } from "vite";
|
|
46
|
+
import react from "@vitejs/plugin-react";
|
|
47
|
+
import { aaexFileRouter } from "aaex-file-router";
|
|
44
48
|
|
|
45
49
|
export default defineConfig({
|
|
46
50
|
plugins: [
|
|
47
51
|
react(),
|
|
48
52
|
aaexFileRouter({
|
|
49
|
-
pagesDir:
|
|
50
|
-
outputFile:
|
|
53
|
+
pagesDir: "./src/pages", //page files location(optional: default ./src/pages)
|
|
54
|
+
outputFile: "./src/routes.ts", //generated routes (default: ./src/routes.ts)
|
|
51
55
|
}),
|
|
52
56
|
],
|
|
53
57
|
});
|
|
@@ -57,14 +61,14 @@ export default defineConfig({
|
|
|
57
61
|
|
|
58
62
|
```typescript
|
|
59
63
|
// src/main.tsx
|
|
60
|
-
import React from
|
|
61
|
-
import ReactDOM from
|
|
62
|
-
import { RouterProvider, createBrowserRouter } from
|
|
63
|
-
import routes from
|
|
64
|
+
import React from "react";
|
|
65
|
+
import ReactDOM from "react-dom/client";
|
|
66
|
+
import { RouterProvider, createBrowserRouter } from "react-router-dom";
|
|
67
|
+
import routes from "./routes";
|
|
64
68
|
|
|
65
69
|
const router = createBrowserRouter(routes);
|
|
66
70
|
|
|
67
|
-
ReactDOM.createRoot(document.getElementById(
|
|
71
|
+
ReactDOM.createRoot(document.getElementById("root")!).render(
|
|
68
72
|
<React.StrictMode>
|
|
69
73
|
<RouterProvider router={router} />
|
|
70
74
|
</React.StrictMode>
|
|
@@ -74,17 +78,21 @@ ReactDOM.createRoot(document.getElementById('root')!).render(
|
|
|
74
78
|
## File Conventions
|
|
75
79
|
|
|
76
80
|
### `index.tsx`
|
|
81
|
+
|
|
77
82
|
Renders at the parent route path.
|
|
83
|
+
|
|
78
84
|
```
|
|
79
85
|
pages/index.tsx → "/"
|
|
80
86
|
pages/about/index.tsx → "/about"
|
|
81
87
|
```
|
|
82
88
|
|
|
83
89
|
### `layout.tsx`
|
|
90
|
+
|
|
84
91
|
Wraps all sibling and nested routes. Children are rendered in an `<Outlet />`.
|
|
92
|
+
|
|
85
93
|
```typescript
|
|
86
94
|
// pages/admin/layout.tsx
|
|
87
|
-
import { Outlet } from
|
|
95
|
+
import { Outlet } from "react-router-dom";
|
|
88
96
|
|
|
89
97
|
export default function AdminLayout() {
|
|
90
98
|
return (
|
|
@@ -96,8 +104,31 @@ export default function AdminLayout() {
|
|
|
96
104
|
}
|
|
97
105
|
```
|
|
98
106
|
|
|
107
|
+
### Slug files
|
|
108
|
+
|
|
109
|
+
Filenames wrapper in hardbrackets `[filename]` will resolve to a dynamic route
|
|
110
|
+
|
|
111
|
+
```
|
|
112
|
+
pages/test/[<filename>].tsx → "/test/:<filename>"
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
```tsx
|
|
116
|
+
//pages/test/[slug].tsx
|
|
117
|
+
|
|
118
|
+
import { useParams } from "react-router-dom";
|
|
119
|
+
|
|
120
|
+
export default function TestWithSlug() {
|
|
121
|
+
// replace slug with what the file is called
|
|
122
|
+
const { slug } = useParams();
|
|
123
|
+
|
|
124
|
+
return <div>{slug}</div>;
|
|
125
|
+
}
|
|
126
|
+
```
|
|
127
|
+
|
|
99
128
|
### Named files
|
|
129
|
+
|
|
100
130
|
Any other `.tsx` file becomes a route based on its filename.
|
|
131
|
+
|
|
101
132
|
```
|
|
102
133
|
pages/about.tsx → "/about"
|
|
103
134
|
pages/blog/post.tsx → "/blog/post"
|
|
@@ -110,18 +141,18 @@ The plugin generates a `routes.ts` file with all your routes:
|
|
|
110
141
|
```typescript
|
|
111
142
|
// src/routes.ts
|
|
112
143
|
// AUTO GENERATED: DO NOT EDIT
|
|
113
|
-
import React from
|
|
114
|
-
import Index from
|
|
115
|
-
import AdminLayout from
|
|
116
|
-
import type { RouteObject } from
|
|
144
|
+
import React from "react";
|
|
145
|
+
import Index from "./pages/index.tsx";
|
|
146
|
+
import AdminLayout from "./pages/admin/layout.tsx";
|
|
147
|
+
import type { RouteObject } from "react-router-dom";
|
|
117
148
|
|
|
118
149
|
const routes: RouteObject[] = [
|
|
119
150
|
{
|
|
120
|
-
path:
|
|
151
|
+
path: "/",
|
|
121
152
|
element: React.createElement(Index),
|
|
122
153
|
},
|
|
123
154
|
{
|
|
124
|
-
path:
|
|
155
|
+
path: "admin",
|
|
125
156
|
element: React.createElement(AdminLayout),
|
|
126
157
|
children: [
|
|
127
158
|
// nested routes...
|
|
@@ -134,12 +165,12 @@ export default routes;
|
|
|
134
165
|
|
|
135
166
|
## Route Resolution Examples
|
|
136
167
|
|
|
137
|
-
| File Structure
|
|
138
|
-
|
|
139
|
-
| `pages/index.tsx`
|
|
140
|
-
| `pages/about.tsx`
|
|
141
|
-
| `pages/blog/index.tsx`
|
|
142
|
-
| `pages/blog/post.tsx`
|
|
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` |
|
|
143
174
|
| `pages/admin/layout.tsx` + children | `/admin/*` (grouped) |
|
|
144
175
|
|
|
145
176
|
## Layouts
|
|
@@ -148,7 +179,7 @@ Layouts wrap their child routes and provide shared UI:
|
|
|
148
179
|
|
|
149
180
|
```typescript
|
|
150
181
|
// pages/dashboard/layout.tsx
|
|
151
|
-
import { Outlet } from
|
|
182
|
+
import { Outlet } from "react-router-dom";
|
|
152
183
|
|
|
153
184
|
export default function DashboardLayout() {
|
|
154
185
|
return (
|
|
@@ -164,80 +195,79 @@ export default function DashboardLayout() {
|
|
|
164
195
|
|
|
165
196
|
All routes in `pages/dashboard/*` will render inside this layout.
|
|
166
197
|
|
|
167
|
-
|
|
168
198
|
## FileLink component
|
|
169
199
|
|
|
170
200
|
The FileLink component is a type safe wrapper for the Link component in react router that uses an autogenerated type to check which routes are available.
|
|
171
201
|
|
|
172
|
-
## Notice!
|
|
173
|
-
At the moment it can only do the basic routing where the "to" prop is a string.
|
|
174
|
-
React routers normal Link still works in cases where the advanced functionality is more important than type safe routing.
|
|
202
|
+
## Notice!
|
|
175
203
|
|
|
204
|
+
At the moment it can only do the basic routing where the "to" prop is a string.
|
|
205
|
+
React Router's normal Link still works in cases where type safety is less important.
|
|
176
206
|
|
|
177
207
|
## Usage
|
|
178
208
|
|
|
179
|
-
|
|
180
209
|
```ts
|
|
181
210
|
// src/routeTypes.ts
|
|
182
211
|
// * AUTO GENERATED: DO NOT EDIT
|
|
183
212
|
|
|
184
213
|
//this file is auto generated along with the route definition file
|
|
185
214
|
export type FileRoutes = "/" | "test";
|
|
186
|
-
|
|
187
|
-
```
|
|
215
|
+
```
|
|
188
216
|
|
|
189
|
-
```tsx
|
|
217
|
+
```tsx
|
|
190
218
|
//src/pages/index.tsx
|
|
191
|
-
import {FileLink} from "aaex-file-router"
|
|
192
|
-
import type { FileRoutes } from "../routeTypes"
|
|
193
|
-
|
|
194
|
-
export default function Home(){
|
|
195
|
-
return <>
|
|
196
|
-
Hello Home!
|
|
197
|
-
{/* FileRoutes is optional and not required it will work fine with any string if not passed */}
|
|
219
|
+
import { FileLink } from "aaex-file-router";
|
|
220
|
+
import type { FileRoutes } from "../routeTypes";
|
|
198
221
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
222
|
+
export default function Home() {
|
|
223
|
+
return (
|
|
224
|
+
<>
|
|
225
|
+
Hello Home!
|
|
226
|
+
{/* FileRoutes is optional and not required it will work fine with any string if not passed */}
|
|
227
|
+
<FileLink<FileRoutes> to="test">Test safe</FileLink>
|
|
228
|
+
//or //no type safety
|
|
229
|
+
<FileLink to="some-route">Non safe</FileLink>
|
|
230
|
+
</>
|
|
231
|
+
);
|
|
232
|
+
}
|
|
205
233
|
```
|
|
206
234
|
|
|
207
|
-
|
|
208
235
|
## API Reference
|
|
209
236
|
|
|
210
237
|
### FileScanner
|
|
238
|
+
|
|
211
239
|
Scans the file system and converts files into a structured format.
|
|
212
240
|
|
|
213
241
|
```typescript
|
|
214
|
-
import { FileScanner } from
|
|
242
|
+
import { FileScanner } from "aaex-file-router/core";
|
|
215
243
|
|
|
216
|
-
const scanner = new FileScanner(
|
|
244
|
+
const scanner = new FileScanner("./src/pages");
|
|
217
245
|
const fileData = await scanner.get_file_data();
|
|
218
246
|
```
|
|
219
247
|
|
|
220
248
|
### RouteGenerator
|
|
249
|
+
|
|
221
250
|
Converts file structure into React Router route configuration.
|
|
222
251
|
|
|
223
252
|
```typescript
|
|
224
|
-
import { RouteGenerator } from
|
|
253
|
+
import { RouteGenerator } from "aaex-file-router/core";
|
|
225
254
|
|
|
226
255
|
const generator = new RouteGenerator();
|
|
227
256
|
const routesCode = await generator.generateComponentsMap(fileData);
|
|
228
257
|
```
|
|
229
258
|
|
|
230
259
|
### aaexFileRouter (Vite Plugin)
|
|
260
|
+
|
|
231
261
|
Automatically watches for file changes and regenerates routes.
|
|
232
262
|
|
|
233
263
|
```typescript
|
|
234
|
-
import { aaexFileRouter } from
|
|
264
|
+
import { aaexFileRouter } from "aaex-file-router/core";
|
|
235
265
|
|
|
236
266
|
export default defineConfig({
|
|
237
267
|
plugins: [
|
|
238
268
|
aaexFileRouter({
|
|
239
|
-
pagesDir:
|
|
240
|
-
outputFile:
|
|
269
|
+
pagesDir: "./src/pages",
|
|
270
|
+
outputFile: "./src/routes.ts",
|
|
241
271
|
}),
|
|
242
272
|
],
|
|
243
273
|
});
|
|
@@ -247,7 +277,7 @@ export default defineConfig({
|
|
|
247
277
|
|
|
248
278
|
1. **File Scanning**: Recursively scans your pages directory and builds a file tree
|
|
249
279
|
2. **Route Generation**: Converts the file structure into React Router `RouteObject` format
|
|
250
|
-
3. **Smart Importing**:
|
|
280
|
+
3. **Smart Importing**:
|
|
251
281
|
- Top-level files use static imports for faster initial load
|
|
252
282
|
- Nested/grouped routes use lazy loading for code splitting
|
|
253
283
|
- Layout files are statically imported as route wrappers
|
|
@@ -262,6 +292,7 @@ export default defineConfig({
|
|
|
262
292
|
## Common Patterns
|
|
263
293
|
|
|
264
294
|
### Shared Layout
|
|
295
|
+
|
|
265
296
|
```sh
|
|
266
297
|
pages/
|
|
267
298
|
├── layout.tsx # Wraps entire app
|
|
@@ -270,6 +301,7 @@ pages/
|
|
|
270
301
|
```
|
|
271
302
|
|
|
272
303
|
### Nested Layouts
|
|
304
|
+
|
|
273
305
|
```sh
|
|
274
306
|
pages/
|
|
275
307
|
├── layout.tsx # Root layout
|
|
@@ -280,6 +312,7 @@ pages/
|
|
|
280
312
|
```
|
|
281
313
|
|
|
282
314
|
### Route Groups Without Layout
|
|
315
|
+
|
|
283
316
|
```sh
|
|
284
317
|
pages/
|
|
285
318
|
├── blog/
|
|
@@ -290,14 +323,17 @@ pages/
|
|
|
290
323
|
## Troubleshooting
|
|
291
324
|
|
|
292
325
|
### Routes not updating on file change
|
|
326
|
+
|
|
293
327
|
- Ensure Vite dev server is running (`npm run dev`)
|
|
294
328
|
- Check that `pagesDir` in vite config matches your actual pages directory
|
|
295
329
|
|
|
296
330
|
### Duplicate imports in generated file
|
|
331
|
+
|
|
297
332
|
- This shouldn't happen, but if it does, try restarting the dev server
|
|
298
333
|
- Check for files with the same name in different directories
|
|
299
334
|
|
|
300
335
|
### Unexpected route paths
|
|
336
|
+
|
|
301
337
|
- Remember: `index.tsx` files inherit their parent's path
|
|
302
338
|
- Directories without `layout.tsx` flatten their children into absolute routes
|
|
303
339
|
- File names are converted to lowercase for routes
|
|
@@ -3,7 +3,6 @@ export declare class RouteGenerator {
|
|
|
3
3
|
private topLevelImports;
|
|
4
4
|
private importSet;
|
|
5
5
|
private processedFiles;
|
|
6
|
-
private clearImports;
|
|
7
6
|
/**
|
|
8
7
|
* Recursively converts FileData tree into React Router RouteConfig array
|
|
9
8
|
* Handles layout files, index files, and nested routes with proper pathing
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RouteGenerator.d.ts","sourceRoot":"","sources":["../../src/core/RouteGenerator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AASzC,qBAAa,cAAc;IACzB,OAAO,CAAC,eAAe,CAAgB;IACvC,OAAO,CAAC,SAAS,CAA0B;IAC3C,OAAO,CAAC,cAAc,CAA0B;IAEhD
|
|
1
|
+
{"version":3,"file":"RouteGenerator.d.ts","sourceRoot":"","sources":["../../src/core/RouteGenerator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AASzC,qBAAa,cAAc;IACzB,OAAO,CAAC,eAAe,CAAgB;IACvC,OAAO,CAAC,SAAS,CAA0B;IAC3C,OAAO,CAAC,cAAc,CAA0B;IAEhD;;;;;OAKG;IACH,OAAO,CAAC,gBAAgB;IAkLxB;;;;;OAKG;IACU,qBAAqB,CAAC,QAAQ,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC;IA8BzE;;;;OAIG;IACS,qBAAqB,CAAC,QAAQ,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC;CAwCzE"}
|
|
@@ -2,9 +2,6 @@ export class RouteGenerator {
|
|
|
2
2
|
topLevelImports = [];
|
|
3
3
|
importSet = new Set();
|
|
4
4
|
processedFiles = new Set();
|
|
5
|
-
clearImports() {
|
|
6
|
-
this.topLevelImports = [];
|
|
7
|
-
}
|
|
8
5
|
/**
|
|
9
6
|
* Recursively converts FileData tree into React Router RouteConfig array
|
|
10
7
|
* Handles layout files, index files, and nested routes with proper pathing
|
|
@@ -14,6 +11,8 @@ export class RouteGenerator {
|
|
|
14
11
|
fileDataToRoutes(fileData, parentPath = "", flattenPrefix = "", inGroup = false) {
|
|
15
12
|
const routes = [];
|
|
16
13
|
const processedIndexes = new Set();
|
|
14
|
+
/** Converts `[slug]` → `:slug` */
|
|
15
|
+
const normalizeDynamicSegment = (name) => name.replace(/\[([^\]]+)\]/g, ":$1");
|
|
17
16
|
/**
|
|
18
17
|
* Utility function to safely join path segments
|
|
19
18
|
* - Filters out empty/falsy parts to avoid "///" in paths
|
|
@@ -23,119 +22,103 @@ export class RouteGenerator {
|
|
|
23
22
|
* Example: posixJoin("pages\\test", "hello") -> "pages/test/hello"
|
|
24
23
|
*/
|
|
25
24
|
const posixJoin = (...parts) => parts.filter(Boolean).join("/").replace(/\\/g, "/");
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
25
|
+
/** Converts "user", "[id]" → "User", "Id" */
|
|
26
|
+
const toPascal = (str) => str
|
|
27
|
+
.replace(/\[|\]/g, "")
|
|
28
|
+
.replace(/(^\w|[-_]\w)/g, (m) => m.replace(/[-_]/, "").toUpperCase());
|
|
29
|
+
/** Build import name from parent folder + file */
|
|
30
|
+
const getImportName = (file) => {
|
|
31
|
+
const segments = file.relative_path.replace(/^src[\/\\]/, "").split("/");
|
|
32
|
+
const parentFolder = segments.length > 1 ? segments[segments.length - 2] : "";
|
|
33
|
+
const parentName = parentFolder ? toPascal(parentFolder) : "";
|
|
34
|
+
const nameWithoutExt = file.name.replace(/\.[jt]sx?$/, "");
|
|
35
|
+
const fileNamePart = nameWithoutExt.toLowerCase() === "index"
|
|
36
|
+
? ""
|
|
37
|
+
: toPascal(nameWithoutExt);
|
|
38
|
+
return `${parentName}${fileNamePart}`;
|
|
39
|
+
};
|
|
40
|
+
/** Create route object (handles lazy vs top-level import) */
|
|
41
|
+
const createRoute = (file, path, importName, lazy = false) => {
|
|
42
|
+
const filePath = file.relative_path.replace(/^src[\/\\]/, "./");
|
|
43
|
+
const element = lazy
|
|
44
|
+
? `React.createElement(React.lazy(() => import('${filePath}')))`
|
|
45
|
+
: `React.createElement(${importName})`;
|
|
46
|
+
return { path: normalizeDynamicSegment(path), element };
|
|
47
|
+
};
|
|
48
|
+
/** Recursive processing */
|
|
49
|
+
const processFile = (file, currentParentPath, currentFlatten, group) => {
|
|
50
|
+
if (!file.isDirectory && this.processedFiles.has(file.relative_path))
|
|
51
|
+
return;
|
|
52
|
+
if (file.isDirectory && file.children?.length) {
|
|
53
|
+
const layoutFile = file.children.find((c) => !c.isDirectory && /^layout\.(tsx|jsx|ts|js)$/i.test(c.name));
|
|
54
|
+
if (!layoutFile) {
|
|
55
|
+
const newFlatten = posixJoin(currentFlatten, file.name.toLowerCase());
|
|
56
|
+
routes.push(...this.fileDataToRoutes(file.children, currentParentPath, newFlatten, false));
|
|
57
|
+
return;
|
|
38
58
|
}
|
|
39
|
-
|
|
40
|
-
const layoutPath =
|
|
41
|
-
const layoutImportName = `TestLayout`;
|
|
59
|
+
const layoutImportName = "TestLayout";
|
|
60
|
+
const layoutPath = layoutFile.relative_path.replace(/^src[\/\\]/, "./");
|
|
42
61
|
this.topLevelImports.push(`import ${layoutImportName} from '${layoutPath}';`);
|
|
43
|
-
this.processedFiles.add(
|
|
44
|
-
const
|
|
45
|
-
|
|
46
|
-
const nonLayoutChildren = file.children.filter((c) => !/^layout\.(tsx|jsx|ts|js)$/i.test(c.name));
|
|
47
|
-
for (const child of nonLayoutChildren) {
|
|
62
|
+
this.processedFiles.add(layoutFile.relative_path);
|
|
63
|
+
const childRoutes = [];
|
|
64
|
+
for (const child of file.children.filter((c) => !/^layout\.(tsx|jsx|ts|js)$/i.test(c.name))) {
|
|
48
65
|
if (child.isDirectory) {
|
|
49
|
-
|
|
50
|
-
childrenRoutes.push(...this.fileDataToRoutes([child], posixJoin(parentPath, file.name), "", true));
|
|
66
|
+
processFile(child, posixJoin(currentParentPath, file.name), "", true);
|
|
51
67
|
}
|
|
52
68
|
else {
|
|
53
69
|
const childNameWithoutExt = child.name.replace(/\.[jt]sx?$/, "");
|
|
54
|
-
const
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
path: "",
|
|
59
|
-
element: `React.createElement(React.lazy(() => import('${childPath}')))`,
|
|
60
|
-
});
|
|
61
|
-
}
|
|
62
|
-
else {
|
|
63
|
-
childrenRoutes.push({
|
|
64
|
-
path: childNameWithoutExt.toLowerCase(),
|
|
65
|
-
element: `React.createElement(React.lazy(() => import('${childPath}')))`,
|
|
66
|
-
});
|
|
67
|
-
}
|
|
68
|
-
// Mark child as processed so it doesn't get added as top-level
|
|
70
|
+
const path = childNameWithoutExt.toLowerCase() === "index"
|
|
71
|
+
? ""
|
|
72
|
+
: normalizeDynamicSegment(childNameWithoutExt.toLowerCase());
|
|
73
|
+
childRoutes.push(createRoute(child, path, undefined, true));
|
|
69
74
|
this.processedFiles.add(child.relative_path);
|
|
70
75
|
}
|
|
71
76
|
}
|
|
72
77
|
routes.push({
|
|
73
|
-
path: file.name.toLowerCase(),
|
|
78
|
+
path: normalizeDynamicSegment(file.name.toLowerCase()),
|
|
74
79
|
element: `React.createElement(${layoutImportName})`,
|
|
75
|
-
children:
|
|
80
|
+
children: childRoutes.length ? childRoutes : undefined,
|
|
76
81
|
});
|
|
82
|
+
return;
|
|
77
83
|
}
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
const siblingDirExists = fileData.some((f) => f.isDirectory &&
|
|
87
|
-
f.name.toLowerCase() === nameWithoutExt.toLowerCase());
|
|
88
|
-
if (siblingDirExists) {
|
|
89
|
-
this.processedFiles.add(file.relative_path);
|
|
90
|
-
continue;
|
|
91
|
-
}
|
|
92
|
-
// Skip layout files
|
|
93
|
-
if (/^layout\.(tsx|jsx|ts|js)$/i.test(file.name)) {
|
|
94
|
-
this.processedFiles.add(file.relative_path);
|
|
95
|
-
continue;
|
|
96
|
-
}
|
|
97
|
-
// Determine path
|
|
98
|
-
const fileSegment = isIndexFile ? "" : nameWithoutExt.toLowerCase();
|
|
99
|
-
let fullPath;
|
|
100
|
-
if (flattenPrefix) {
|
|
101
|
-
fullPath = posixJoin(flattenPrefix, fileSegment);
|
|
102
|
-
}
|
|
103
|
-
else if (inGroup) {
|
|
104
|
-
fullPath = fileSegment;
|
|
105
|
-
}
|
|
106
|
-
else if (parentPath) {
|
|
107
|
-
fullPath = posixJoin(parentPath, fileSegment);
|
|
108
|
-
}
|
|
109
|
-
else {
|
|
110
|
-
fullPath = isIndexFile ? "/" : fileSegment;
|
|
111
|
-
}
|
|
112
|
-
// Create import & avoid duplicates
|
|
113
|
-
const importNameBase = nameWithoutExt.replace(/[^a-zA-Z0-9]/g, "_");
|
|
114
|
-
const capitalized = importNameBase.charAt(0).toUpperCase() + importNameBase.slice(1);
|
|
115
|
-
const filePath = file.relative_path.replace(/^src[\/\\]/, "./");
|
|
116
|
-
if (inGroup) {
|
|
117
|
-
// Lazy-load child component inside group
|
|
118
|
-
routes.push({
|
|
119
|
-
path: fullPath === "/" ? "" : fullPath.replace(/^\/+/, ""),
|
|
120
|
-
element: `React.createElement(React.lazy(() => import('${filePath}')))`,
|
|
121
|
-
});
|
|
122
|
-
}
|
|
123
|
-
else {
|
|
124
|
-
// Top-level files use static imports
|
|
125
|
-
if (!this.importSet.has(filePath)) {
|
|
126
|
-
this.topLevelImports.push(`import ${capitalized} from '${filePath}';`);
|
|
127
|
-
this.importSet.add(filePath);
|
|
128
|
-
}
|
|
129
|
-
routes.push({
|
|
130
|
-
path: fullPath === "/" ? "/" : fullPath.replace(/^\/+/, ""),
|
|
131
|
-
element: `React.createElement(${capitalized})`,
|
|
132
|
-
});
|
|
133
|
-
}
|
|
84
|
+
// ---------------- FILES ----------------
|
|
85
|
+
const nameWithoutExt = file.name.replace(/\.[jt]sx?$/, "");
|
|
86
|
+
const isIndex = nameWithoutExt.toLowerCase() === "index";
|
|
87
|
+
if (isIndex && processedIndexes.has(file.relative_path))
|
|
88
|
+
return;
|
|
89
|
+
if (fileData.some((f) => f.isDirectory &&
|
|
90
|
+
f.name.toLowerCase() === nameWithoutExt.toLowerCase()) ||
|
|
91
|
+
/^layout\.(tsx|jsx|ts|js)$/i.test(file.name)) {
|
|
134
92
|
this.processedFiles.add(file.relative_path);
|
|
135
|
-
|
|
136
|
-
processedIndexes.add(file.relative_path);
|
|
93
|
+
return;
|
|
137
94
|
}
|
|
138
|
-
|
|
95
|
+
const rawSegment = isIndex ? "" : nameWithoutExt.toLowerCase();
|
|
96
|
+
const fileSegment = normalizeDynamicSegment(rawSegment);
|
|
97
|
+
let fullPath;
|
|
98
|
+
if (currentFlatten)
|
|
99
|
+
fullPath = posixJoin(currentFlatten, fileSegment);
|
|
100
|
+
else if (group)
|
|
101
|
+
fullPath = fileSegment;
|
|
102
|
+
else if (currentParentPath)
|
|
103
|
+
fullPath = posixJoin(currentParentPath, fileSegment);
|
|
104
|
+
else
|
|
105
|
+
fullPath = isIndex ? "/" : fileSegment;
|
|
106
|
+
const importName = getImportName(file);
|
|
107
|
+
if (group)
|
|
108
|
+
routes.push(createRoute(file, fullPath, undefined, true));
|
|
109
|
+
else {
|
|
110
|
+
if (!this.importSet.has(file.relative_path)) {
|
|
111
|
+
this.topLevelImports.push(`import ${importName} from './${file.relative_path.replace(/^src[\/\\]/, "")}';`);
|
|
112
|
+
this.importSet.add(file.relative_path);
|
|
113
|
+
}
|
|
114
|
+
routes.push(createRoute(file, fullPath, importName));
|
|
115
|
+
}
|
|
116
|
+
this.processedFiles.add(file.relative_path);
|
|
117
|
+
if (isIndex)
|
|
118
|
+
processedIndexes.add(file.relative_path);
|
|
119
|
+
};
|
|
120
|
+
for (const file of fileData)
|
|
121
|
+
processFile(file, parentPath, flattenPrefix, inGroup);
|
|
139
122
|
return routes;
|
|
140
123
|
}
|
|
141
124
|
/**
|
|
@@ -178,23 +161,28 @@ export default routes;
|
|
|
178
161
|
this.processedFiles = new Set();
|
|
179
162
|
const routes = this.fileDataToRoutes(fileData);
|
|
180
163
|
const routePaths = [];
|
|
181
|
-
|
|
182
|
-
|
|
164
|
+
const addRoute = (route, parentPath = "") => {
|
|
165
|
+
const fullPath = parentPath
|
|
166
|
+
? `${parentPath}/${route.path}`.replace(/\/+/g, "/")
|
|
167
|
+
: route.path;
|
|
168
|
+
// Replace ":param" with ${string} for TypeScript type
|
|
169
|
+
const tsPath = fullPath
|
|
170
|
+
.split("/")
|
|
171
|
+
.map((seg) => (seg.startsWith(":") ? "${string}" : seg))
|
|
172
|
+
.join("/");
|
|
173
|
+
routePaths.push(tsPath);
|
|
183
174
|
if (route.children?.length) {
|
|
184
|
-
route.children.
|
|
185
|
-
if (child.path != "") {
|
|
186
|
-
routePaths.push(`${route.path}/${child.path}`);
|
|
187
|
-
}
|
|
188
|
-
});
|
|
175
|
+
route.children.forEach((child) => addRoute(child, fullPath));
|
|
189
176
|
}
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
|
|
177
|
+
};
|
|
178
|
+
routes.forEach((route) => addRoute(route));
|
|
179
|
+
const uniquePaths = Array.from(new Set(routePaths))
|
|
180
|
+
.map((p) => `\`${p}\``) // wrap in backticks for template literal types
|
|
193
181
|
.join(" | ");
|
|
194
182
|
return `// * AUTO GENERATED: DO NOT EDIT
|
|
195
183
|
|
|
196
|
-
|
|
197
|
-
|
|
184
|
+
export type FileRoutes = ${uniquePaths};
|
|
185
|
+
`;
|
|
198
186
|
}
|
|
199
187
|
}
|
|
200
188
|
//# sourceMappingURL=RouteGenerator.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RouteGenerator.js","sourceRoot":"","sources":["../../src/core/RouteGenerator.ts"],"names":[],"mappings":"AASA,MAAM,OAAO,cAAc;IACjB,eAAe,GAAa,EAAE,CAAC;IAC/B,SAAS,GAAgB,IAAI,GAAG,EAAE,CAAC;IACnC,cAAc,GAAgB,IAAI,GAAG,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"RouteGenerator.js","sourceRoot":"","sources":["../../src/core/RouteGenerator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
//# sourceMappingURL=%5Bid%5D.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"[id].d.ts","sourceRoot":"","sources":["../../../src/pages/users/[id].tsx"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"[id].js","sourceRoot":"","sources":["../../../src/pages/users/[id].tsx"],"names":[],"mappings":""}
|
package/dist/test/index.js
CHANGED
|
@@ -1,18 +1,17 @@
|
|
|
1
1
|
import { fileURLToPath } from "url";
|
|
2
2
|
import { FileScanner } from "../core/FileScanner.js";
|
|
3
3
|
import { RouteGenerator } from "../core/RouteGenerator.js";
|
|
4
|
-
import path from "path";
|
|
5
4
|
const __filename = fileURLToPath(import.meta.url);
|
|
6
|
-
const __dirname = path.dirname(__filename);
|
|
7
5
|
const pagesDir = "/src/pages";
|
|
8
6
|
async function generateRoutes() {
|
|
9
7
|
try {
|
|
10
8
|
const scanner = new FileScanner(pagesDir);
|
|
11
9
|
const fileData = await scanner.get_file_data();
|
|
10
|
+
// console.log(fileData);
|
|
12
11
|
const generator = new RouteGenerator();
|
|
13
12
|
const routeMap = await generator.generateComponentsMap(fileData);
|
|
14
|
-
console.log("Route map: ", routeMap)
|
|
15
|
-
const routType = generator.generateRoutesTypeDef(fileData);
|
|
13
|
+
// console.log("Route map: ", routeMap)
|
|
14
|
+
const routType = await generator.generateRoutesTypeDef(fileData);
|
|
16
15
|
console.log(routType);
|
|
17
16
|
}
|
|
18
17
|
catch (error) {
|
package/dist/test/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/test/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AACpC,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/test/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AACpC,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAG3D,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,QAAQ,GAAG,YAAY,CAAC;AAE9B,KAAK,UAAU,cAAc;IAC3B,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,IAAI,WAAW,CAAC,QAAQ,CAAC,CAAC;QAC1C,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,aAAa,EAAE,CAAC;QAG/C,yBAAyB;QAGzB,MAAM,SAAS,GAAG,IAAI,cAAc,EAAE,CAAC;QACvC,MAAM,QAAQ,GAAG,MAAM,SAAS,CAAC,qBAAqB,CAAC,QAAQ,CAAC,CAAC;QAGjE,uCAAuC;QAEvC,MAAM,QAAQ,GAAG,MAAM,SAAS,CAAC,qBAAqB,CAAC,QAAQ,CAAC,CAAC;QAEjE,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAGxB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,0BAA0B,EAAE,KAAK,CAAC,CAAC;IACnD,CAAC;AACH,CAAC;AAED,cAAc,EAAE,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,48 +1,48 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "aaex-file-router",
|
|
3
|
-
"version": "1.
|
|
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
|
-
"main": "dist/index.js",
|
|
6
|
-
"scripts": {
|
|
7
|
-
"test": "echo \"Error: no test specified\" && exit 1",
|
|
8
|
-
"build": "npx tsc",
|
|
9
|
-
"dev": "npx tsc --watch"
|
|
10
|
-
},
|
|
11
|
-
"keywords": [
|
|
12
|
-
"react",
|
|
13
|
-
"router",
|
|
14
|
-
"vite-plugin"
|
|
15
|
-
],
|
|
16
|
-
|
|
17
|
-
"exports":{
|
|
18
|
-
".": "./dist/index.js",
|
|
19
|
-
"./core": "./dist/core/index.js"
|
|
20
|
-
},
|
|
21
|
-
"author": "TmRAaEx",
|
|
22
|
-
"license": "MIT",
|
|
23
|
-
"type": "module",
|
|
24
|
-
"files": [
|
|
25
|
-
"dist",
|
|
26
|
-
"README.md",
|
|
27
|
-
"LICENCE"
|
|
28
|
-
],
|
|
29
|
-
"types": "dist/index.d.ts",
|
|
30
|
-
"devDependencies": {
|
|
31
|
-
"@types/node": "^24.10.1",
|
|
32
|
-
"@types/react": "^19.2.7",
|
|
33
|
-
"@types/react-dom": "^19.2.3",
|
|
34
|
-
"react": "^19.2.0",
|
|
35
|
-
"react-dom": "^19.2.0",
|
|
36
|
-
"react-router-dom": "^7.9.6",
|
|
37
|
-
"typescript": "^5.9.3",
|
|
38
|
-
"vite": "^7.2.4",
|
|
39
|
-
"vite-plugin-dts": "^4.5.4"
|
|
40
|
-
},
|
|
41
|
-
|
|
42
|
-
"peerDependencies": {
|
|
43
|
-
"react": "^19.2.0",
|
|
44
|
-
"react-dom": "^19.2.0",
|
|
45
|
-
"react-router-dom": "^7.9.6",
|
|
46
|
-
"vite": "^7.2.4"
|
|
47
|
-
}
|
|
48
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "aaex-file-router",
|
|
3
|
+
"version": "1.2.0",
|
|
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
|
+
"main": "dist/index.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"test": "echo \"Error: no test specified\" && exit 1",
|
|
8
|
+
"build": "npx tsc",
|
|
9
|
+
"dev": "npx tsc --watch"
|
|
10
|
+
},
|
|
11
|
+
"keywords": [
|
|
12
|
+
"react",
|
|
13
|
+
"router",
|
|
14
|
+
"vite-plugin"
|
|
15
|
+
],
|
|
16
|
+
|
|
17
|
+
"exports":{
|
|
18
|
+
".": "./dist/index.js",
|
|
19
|
+
"./core": "./dist/core/index.js"
|
|
20
|
+
},
|
|
21
|
+
"author": "TmRAaEx",
|
|
22
|
+
"license": "MIT",
|
|
23
|
+
"type": "module",
|
|
24
|
+
"files": [
|
|
25
|
+
"dist",
|
|
26
|
+
"README.md",
|
|
27
|
+
"LICENCE"
|
|
28
|
+
],
|
|
29
|
+
"types": "dist/index.d.ts",
|
|
30
|
+
"devDependencies": {
|
|
31
|
+
"@types/node": "^24.10.1",
|
|
32
|
+
"@types/react": "^19.2.7",
|
|
33
|
+
"@types/react-dom": "^19.2.3",
|
|
34
|
+
"react": "^19.2.0",
|
|
35
|
+
"react-dom": "^19.2.0",
|
|
36
|
+
"react-router-dom": "^7.9.6",
|
|
37
|
+
"typescript": "^5.9.3",
|
|
38
|
+
"vite": "^7.2.4",
|
|
39
|
+
"vite-plugin-dts": "^4.5.4"
|
|
40
|
+
},
|
|
41
|
+
|
|
42
|
+
"peerDependencies": {
|
|
43
|
+
"react": "^19.2.0",
|
|
44
|
+
"react-dom": "^19.2.0",
|
|
45
|
+
"react-router-dom": "^7.9.6",
|
|
46
|
+
"vite": "^7.2.4"
|
|
47
|
+
}
|
|
48
|
+
}
|