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 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.1.0
6
- Added type safe <FileLink> component and auto generation of the FileRoutes type for it to use
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
- └── hello.tsx # Route "/test/hello"
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 'vite';
42
- import react from '@vitejs/plugin-react';
43
- import { aaexFileRouter } from 'aaex-file-router';
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: './src/pages', //page files location(optional: default ./src/pages)
50
- outputFile: './src/routes.ts', //generated routes (default: ./src/routes.ts)
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 'react';
61
- import ReactDOM from 'react-dom/client';
62
- import { RouterProvider, createBrowserRouter } from 'react-router-dom';
63
- import routes from './routes';
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('root')!).render(
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 'react-router-dom';
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 'react';
114
- import Index from './pages/index.tsx';
115
- import AdminLayout from './pages/admin/layout.tsx';
116
- import type { RouteObject } from 'react-router-dom';
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: 'admin',
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 | Route Path |
138
- |---|---|
139
- | `pages/index.tsx` | `/` |
140
- | `pages/about.tsx` | `/about` |
141
- | `pages/blog/index.tsx` | `/blog` |
142
- | `pages/blog/post.tsx` | `/blog/post` |
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 'react-router-dom';
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
- <FileLink<FileRoutes> to="test">Test safe</FileLink></>
200
-
201
- //or
202
- //no type safety
203
- <FileLink to="some-route">Non safe</FileLink>
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 'aaex-file-router';
242
+ import { FileScanner } from "aaex-file-router/core";
215
243
 
216
- const scanner = new FileScanner('./src/pages');
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 'aaex-file-router';
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 'aaex-file-router';
264
+ import { aaexFileRouter } from "aaex-file-router/core";
235
265
 
236
266
  export default defineConfig({
237
267
  plugins: [
238
268
  aaexFileRouter({
239
- pagesDir: './src/pages',
240
- outputFile: './src/routes.ts',
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,OAAO,CAAC,YAAY;IAGpB;;;;;OAKG;IACH,OAAO,CAAC,gBAAgB;IA6KxB;;;;;OAKG;IACU,qBAAqB,CAAC,QAAQ,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC;IA8BzE;;;;OAIG;IACU,qBAAqB,CAAC,QAAQ,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC;CA8B1E"}
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
- for (const file of fileData) {
27
- // Skip files already emitted during this generation
28
- if (!file.isDirectory && this.processedFiles.has(file.relative_path)) {
29
- continue;
30
- }
31
- if (file.isDirectory && file.children && file.children.length > 0) {
32
- const layoutChild = file.children.find((c) => !c.isDirectory && /^layout\.(tsx|jsx|ts|js)$/i.test(c.name));
33
- if (!layoutChild) {
34
- // No layout -> flatten children into absolute routes
35
- const newFlatten = posixJoin(flattenPrefix, file.name.toLowerCase());
36
- routes.push(...this.fileDataToRoutes(file.children, parentPath, newFlatten, false));
37
- continue;
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
- // Directory has layout -> import layout statically
40
- const layoutPath = layoutChild.relative_path.replace(/^src[\/\\]/, "./");
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(layoutChild.relative_path); // Mark layout as processed
44
- const childrenRoutes = [];
45
- // Process children - filter out layout files
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
- // Recursively handle child directories
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 childPath = child.relative_path.replace(/^src[\/\\]/, "./");
55
- const isIndexFile = childNameWithoutExt.toLowerCase() === "index";
56
- if (isIndexFile) {
57
- childrenRoutes.push({
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: childrenRoutes.length ? childrenRoutes : undefined,
80
+ children: childRoutes.length ? childRoutes : undefined,
76
81
  });
82
+ return;
77
83
  }
78
- else if (!file.isDirectory) {
79
- const nameWithoutExt = file.name.replace(/\.[jt]sx?$/, "");
80
- const isIndexFile = nameWithoutExt.toLowerCase() === "index";
81
- // Skip if already processed
82
- if (isIndexFile && processedIndexes.has(file.relative_path)) {
83
- continue;
84
- }
85
- // If a sibling directory with the same name exists, skip this file
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
- if (isIndexFile)
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
- for (let route of routes) {
182
- routePaths.push(route.path);
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.map((child) => {
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
- const paths = Array.from(new Set(routePaths))
192
- .map((p) => `"${p}"`)
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
- export type FileRoutes = ${paths};
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":"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"}
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,2 @@
1
+ "use strict";
2
+ //# sourceMappingURL=%5Bid%5D.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"[id].js","sourceRoot":"","sources":["../../../src/pages/users/[id].tsx"],"names":[],"mappings":""}
@@ -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) {
@@ -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;AAE3D,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;AAC3C,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;QAE/C,MAAM,SAAS,GAAG,IAAI,cAAc,EAAE,CAAC;QACvC,MAAM,QAAQ,GAAG,MAAM,SAAS,CAAC,qBAAqB,CAAC,QAAQ,CAAC,CAAC;QAGjE,OAAO,CAAC,GAAG,CAAC,aAAa,EAAE,QAAQ,CAAC,CAAA;QAEpC,MAAM,QAAQ,GAAG,SAAS,CAAC,qBAAqB,CAAC,QAAQ,CAAC,CAAC;QAE3D,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"}
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.1.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
- }
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
+ }