react-fs-router 1.0.13 → 2.0.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 +721 -175
- package/dist/adapters/custom.d.ts +9 -0
- package/dist/adapters/custom.d.ts.map +1 -0
- package/dist/adapters/custom.js +11 -0
- package/dist/adapters/custom.js.map +1 -0
- package/dist/adapters/index.d.ts +8 -0
- package/dist/adapters/index.d.ts.map +1 -0
- package/dist/adapters/index.js +14 -0
- package/dist/adapters/index.js.map +1 -0
- package/dist/adapters/react-router.d.ts +18 -0
- package/dist/adapters/react-router.d.ts.map +1 -0
- package/dist/adapters/react-router.js +58 -0
- package/dist/adapters/react-router.js.map +1 -0
- package/dist/adapters/tanstack.d.ts +16 -0
- package/dist/adapters/tanstack.d.ts.map +1 -0
- package/dist/adapters/tanstack.js +75 -0
- package/dist/adapters/tanstack.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +59 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +24 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +81 -0
- package/dist/config.js.map +1 -0
- package/dist/generator.d.ts +48 -0
- package/dist/generator.d.ts.map +1 -0
- package/dist/generator.js +272 -0
- package/dist/generator.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -0
- package/dist/render.d.ts +53 -0
- package/dist/render.d.ts.map +1 -0
- package/dist/render.js +100 -0
- package/dist/render.js.map +1 -0
- package/dist/scanner.d.ts +27 -0
- package/dist/scanner.d.ts.map +1 -0
- package/dist/scanner.js +38 -0
- package/dist/scanner.js.map +1 -0
- package/dist/tree.d.ts +11 -0
- package/dist/tree.d.ts.map +1 -0
- package/dist/tree.js +83 -0
- package/dist/tree.js.map +1 -0
- package/dist/types.d.ts +98 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/vite.d.ts +14 -0
- package/dist/vite.d.ts.map +1 -0
- package/dist/vite.js +33 -0
- package/dist/vite.js.map +1 -0
- package/dist/webpack.d.ts +32 -0
- package/dist/webpack.d.ts.map +1 -0
- package/dist/webpack.js +26 -0
- package/dist/webpack.js.map +1 -0
- package/package.json +103 -35
- package/.idea/git_toolbox_prj.xml +0 -15
- package/.idea/modules.xml +0 -8
- package/.idea/react-filesystem-router.iml +0 -12
- package/.idea/vcs.xml +0 -6
- package/genPath.js +0 -212
- package/index.js +0 -19
- package/lib/components/Routes.js +0 -0
- package/tsconfig.json +0 -7
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { type ReactNode } from "react";
|
|
2
|
+
import type { ResolvedRoute, RouteAdapter } from "../render.js";
|
|
3
|
+
export type CustomRender = (routes: ResolvedRoute[]) => ReactNode;
|
|
4
|
+
/**
|
|
5
|
+
* Build an adapter for any custom routing solution. The provided render
|
|
6
|
+
* function receives the resolved route tree and returns router-specific output.
|
|
7
|
+
*/
|
|
8
|
+
export declare function createCustomAdapter(render: CustomRender): RouteAdapter;
|
|
9
|
+
//# sourceMappingURL=custom.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"custom.d.ts","sourceRoot":"","sources":["../../src/adapters/custom.ts"],"names":[],"mappings":"AAAA,OAAO,EAA2B,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAChE,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAEhE,MAAM,MAAM,YAAY,GAAG,CAAC,MAAM,EAAE,aAAa,EAAE,KAAK,SAAS,CAAC;AAElE;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,YAAY,GAAG,YAAY,CAItE"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Fragment, createElement } from "react";
|
|
2
|
+
/**
|
|
3
|
+
* Build an adapter for any custom routing solution. The provided render
|
|
4
|
+
* function receives the resolved route tree and returns router-specific output.
|
|
5
|
+
*/
|
|
6
|
+
export function createCustomAdapter(render) {
|
|
7
|
+
return function CustomAdapter({ routes }) {
|
|
8
|
+
return createElement(Fragment, null, render(routes));
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=custom.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"custom.js","sourceRoot":"","sources":["../../src/adapters/custom.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAkB,MAAM,OAAO,CAAC;AAKhE;;;GAGG;AACH,MAAM,UAAU,mBAAmB,CAAC,MAAoB;IACtD,OAAO,SAAS,aAAa,CAAC,EAAE,MAAM,EAAE;QACtC,OAAO,aAAa,CAAC,QAAQ,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;IACvD,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { RouteAdapter } from "../render.js";
|
|
2
|
+
/** Register a user-defined routing adapter by id. */
|
|
3
|
+
export declare function defineAdapter(id: string, adapter: RouteAdapter): void;
|
|
4
|
+
/** Look up a registered adapter by id. */
|
|
5
|
+
export declare function getAdapter(id: string): RouteAdapter | undefined;
|
|
6
|
+
/** Whether an adapter with the given id has been registered. */
|
|
7
|
+
export declare function hasAdapter(id: string): boolean;
|
|
8
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/adapters/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAIjD,qDAAqD;AACrD,wBAAgB,aAAa,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,GAAG,IAAI,CAErE;AAED,0CAA0C;AAC1C,wBAAgB,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS,CAE/D;AAED,gEAAgE;AAChE,wBAAgB,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAE9C"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
const registry = new Map();
|
|
2
|
+
/** Register a user-defined routing adapter by id. */
|
|
3
|
+
export function defineAdapter(id, adapter) {
|
|
4
|
+
registry.set(id, adapter);
|
|
5
|
+
}
|
|
6
|
+
/** Look up a registered adapter by id. */
|
|
7
|
+
export function getAdapter(id) {
|
|
8
|
+
return registry.get(id);
|
|
9
|
+
}
|
|
10
|
+
/** Whether an adapter with the given id has been registered. */
|
|
11
|
+
export function hasAdapter(id) {
|
|
12
|
+
return registry.has(id);
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/adapters/index.ts"],"names":[],"mappings":"AAEA,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAwB,CAAC;AAEjD,qDAAqD;AACrD,MAAM,UAAU,aAAa,CAAC,EAAU,EAAE,OAAqB;IAC7D,QAAQ,CAAC,GAAG,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;AAC5B,CAAC;AAED,0CAA0C;AAC1C,MAAM,UAAU,UAAU,CAAC,EAAU;IACnC,OAAO,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;AAC1B,CAAC;AAED,gEAAgE;AAChE,MAAM,UAAU,UAAU,CAAC,EAAU;IACnC,OAAO,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;AAC1B,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { RouteObject } from "react-router";
|
|
2
|
+
import type { ResolvedRoute, RouteAdapter } from "../render.js";
|
|
3
|
+
/** Convert resolved routes into react-router `useRoutes` route objects. */
|
|
4
|
+
export declare function toRouteObjects(routes: ResolvedRoute[]): RouteObject[];
|
|
5
|
+
/**
|
|
6
|
+
* Convert resolved routes into route objects ready for a data router
|
|
7
|
+
* (`createBrowserRouter`). Ensures a root route exists when needed.
|
|
8
|
+
*/
|
|
9
|
+
export declare function toDataRouterObjects(routes: ResolvedRoute[]): RouteObject[];
|
|
10
|
+
/** React Router adapter: renders the route tree via `useRoutes` (declarative). */
|
|
11
|
+
export declare const reactRouterAdapter: RouteAdapter;
|
|
12
|
+
/**
|
|
13
|
+
* React Router data adapter: renders via `createBrowserRouter` + `RouterProvider`,
|
|
14
|
+
* so route `loader`/`action` data functions are executed and exposed via
|
|
15
|
+
* `useLoaderData()`/`useActionData()`.
|
|
16
|
+
*/
|
|
17
|
+
export declare const reactRouterDataAdapter: RouteAdapter;
|
|
18
|
+
//# sourceMappingURL=react-router.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"react-router.d.ts","sourceRoot":"","sources":["../../src/adapters/react-router.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAchE,2EAA2E;AAC3E,wBAAgB,cAAc,CAAC,MAAM,EAAE,aAAa,EAAE,GAAG,WAAW,EAAE,CAsBrE;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,aAAa,EAAE,GAAG,WAAW,EAAE,CAI1E;AAED,kFAAkF;AAClF,eAAO,MAAM,kBAAkB,EAAE,YAEhC,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,EAAE,YAGpC,CAAC"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { createElement, useState } from "react";
|
|
2
|
+
import { Outlet, RouterProvider, createBrowserRouter, useRoutes } from "react-router";
|
|
3
|
+
/**
|
|
4
|
+
* React Router v7 matches splats with a bare "*" segment (read back via
|
|
5
|
+
* `params["*"]`); named forms like "*slug" no longer compile. Normalize any
|
|
6
|
+
* adapter-formatted "*slug" segment (e.g. `/docs/*slug`) to "/*".
|
|
7
|
+
*/
|
|
8
|
+
function toReactRouterPath(path) {
|
|
9
|
+
return path
|
|
10
|
+
.split("/")
|
|
11
|
+
.map((segment) => (segment.startsWith("*") && segment !== "*" ? "*" : segment))
|
|
12
|
+
.join("/");
|
|
13
|
+
}
|
|
14
|
+
/** Convert resolved routes into react-router `useRoutes` route objects. */
|
|
15
|
+
export function toRouteObjects(routes) {
|
|
16
|
+
return routes.map((route) => {
|
|
17
|
+
const outlet = createElement(Outlet);
|
|
18
|
+
const base = route.element ?? (route.children.length > 0 ? outlet : null);
|
|
19
|
+
const element = route.layout ? createElement(route.layout, null, outlet) : base;
|
|
20
|
+
const children = route.children.length > 0 ? toRouteObjects(route.children) : undefined;
|
|
21
|
+
const loader = route.loaders.loader;
|
|
22
|
+
const action = route.loaders.action;
|
|
23
|
+
if (route.index) {
|
|
24
|
+
return { index: true, element: element ?? undefined, loader, action };
|
|
25
|
+
}
|
|
26
|
+
return {
|
|
27
|
+
path: route.path ? toReactRouterPath(route.path) : undefined,
|
|
28
|
+
element: element ?? undefined,
|
|
29
|
+
children,
|
|
30
|
+
loader,
|
|
31
|
+
action,
|
|
32
|
+
};
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Convert resolved routes into route objects ready for a data router
|
|
37
|
+
* (`createBrowserRouter`). Ensures a root route exists when needed.
|
|
38
|
+
*/
|
|
39
|
+
export function toDataRouterObjects(routes) {
|
|
40
|
+
const objects = toRouteObjects(routes);
|
|
41
|
+
if (objects.some((route) => route.path === "/"))
|
|
42
|
+
return objects;
|
|
43
|
+
return [{ path: "/", element: createElement(Outlet), children: objects }];
|
|
44
|
+
}
|
|
45
|
+
/** React Router adapter: renders the route tree via `useRoutes` (declarative). */
|
|
46
|
+
export const reactRouterAdapter = function ReactRouterAdapter({ routes }) {
|
|
47
|
+
return useRoutes(toRouteObjects(routes));
|
|
48
|
+
};
|
|
49
|
+
/**
|
|
50
|
+
* React Router data adapter: renders via `createBrowserRouter` + `RouterProvider`,
|
|
51
|
+
* so route `loader`/`action` data functions are executed and exposed via
|
|
52
|
+
* `useLoaderData()`/`useActionData()`.
|
|
53
|
+
*/
|
|
54
|
+
export const reactRouterDataAdapter = function ReactRouterDataAdapter({ routes }) {
|
|
55
|
+
const [router] = useState(() => createBrowserRouter(toDataRouterObjects(routes)));
|
|
56
|
+
return createElement(RouterProvider, { router });
|
|
57
|
+
};
|
|
58
|
+
//# sourceMappingURL=react-router.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"react-router.js","sourceRoot":"","sources":["../../src/adapters/react-router.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { ResolvedRoute, RouteAdapter } from "../render.js";
|
|
2
|
+
export type TanstackRouteTree = any;
|
|
3
|
+
/**
|
|
4
|
+
* Convert resolved routes into a real TanStack Router route tree. The root
|
|
5
|
+
* route is created from the resolved "/" entry (applying its layout); every
|
|
6
|
+
* other resolved route is stitched into the tree with its parent via
|
|
7
|
+
* `getParentRoute`/`addChildren`.
|
|
8
|
+
*/
|
|
9
|
+
export declare function toTanstackRouteTree(routes: ResolvedRoute[]): TanstackRouteTree;
|
|
10
|
+
/**
|
|
11
|
+
* TanStack Router adapter: builds a router from the resolved routes and renders
|
|
12
|
+
* it via `<RouterProvider>`, so the generated default component works without
|
|
13
|
+
* manual route-tree wiring.
|
|
14
|
+
*/
|
|
15
|
+
export declare const tanstackRouterAdapter: RouteAdapter;
|
|
16
|
+
//# sourceMappingURL=tanstack.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tanstack.d.ts","sourceRoot":"","sources":["../../src/adapters/tanstack.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAA0B,MAAM,cAAc,CAAC;AAMxF,MAAM,MAAM,iBAAiB,GAAG,GAAG,CAAC;AAgDpC;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,aAAa,EAAE,GAAG,iBAAiB,CAiB9E;AAED;;;;GAIG;AACH,eAAO,MAAM,qBAAqB,EAAE,YAGnC,CAAC"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { createElement, useState } from "react";
|
|
2
|
+
import { Outlet, RouterProvider, createRootRoute, createRoute, createRouter, } from "@tanstack/react-router";
|
|
3
|
+
function LayoutOutlet({ layout }) {
|
|
4
|
+
return createElement(layout, null, createElement(Outlet));
|
|
5
|
+
}
|
|
6
|
+
/** The component a resolved route should render, or undefined for the default outlet. */
|
|
7
|
+
function routeComponent(node) {
|
|
8
|
+
if (node.element != null)
|
|
9
|
+
return () => node.element;
|
|
10
|
+
if (node.layout) {
|
|
11
|
+
return () => createElement(LayoutOutlet, { layout: node.layout });
|
|
12
|
+
}
|
|
13
|
+
return undefined;
|
|
14
|
+
}
|
|
15
|
+
/** Compute a route's path relative to its parent (TanStack normalizes slashes). */
|
|
16
|
+
function relativePath(childPath, parentPath) {
|
|
17
|
+
if (!parentPath || parentPath === "/")
|
|
18
|
+
return childPath.replace(/^\//, "");
|
|
19
|
+
const prefix = parentPath.endsWith("/") ? parentPath : `${parentPath}/`;
|
|
20
|
+
if (childPath.startsWith(prefix))
|
|
21
|
+
return childPath.slice(prefix.length);
|
|
22
|
+
return childPath.replace(/^\//, "");
|
|
23
|
+
}
|
|
24
|
+
/** Convert adapter-formatted splat segments (`*slug`) into TanStack's `$`. */
|
|
25
|
+
function toTanstackPath(path) {
|
|
26
|
+
if (!path)
|
|
27
|
+
return path;
|
|
28
|
+
return path
|
|
29
|
+
.split("/")
|
|
30
|
+
.map((segment) => (segment.startsWith("*") ? "$" : segment))
|
|
31
|
+
.join("/");
|
|
32
|
+
}
|
|
33
|
+
function buildRoute(parent, parentPath, node) {
|
|
34
|
+
const route = createRoute({
|
|
35
|
+
getParentRoute: () => parent,
|
|
36
|
+
// Index routes use "/"; every other route gets its parent-relative path.
|
|
37
|
+
path: node.index ? "/" : toTanstackPath(relativePath(node.path, parentPath)),
|
|
38
|
+
component: routeComponent(node),
|
|
39
|
+
});
|
|
40
|
+
const ownPath = node.index ? parentPath : node.path;
|
|
41
|
+
const children = node.children
|
|
42
|
+
.filter((child) => !(child.index && child.element == null))
|
|
43
|
+
.map((child) => buildRoute(route, ownPath, child));
|
|
44
|
+
return children.length > 0 ? route.addChildren(children) : route;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Convert resolved routes into a real TanStack Router route tree. The root
|
|
48
|
+
* route is created from the resolved "/" entry (applying its layout); every
|
|
49
|
+
* other resolved route is stitched into the tree with its parent via
|
|
50
|
+
* `getParentRoute`/`addChildren`.
|
|
51
|
+
*/
|
|
52
|
+
export function toTanstackRouteTree(routes) {
|
|
53
|
+
const rootEntry = routes.find((route) => !route.index && route.path === "/");
|
|
54
|
+
const rootLayout = rootEntry?.layout ?? null;
|
|
55
|
+
const rootRoute = rootLayout
|
|
56
|
+
? createRootRoute({
|
|
57
|
+
component: () => createElement(LayoutOutlet, { layout: rootLayout }),
|
|
58
|
+
})
|
|
59
|
+
: createRootRoute();
|
|
60
|
+
const topLevel = rootEntry
|
|
61
|
+
? [...rootEntry.children, ...routes.filter((route) => route !== rootEntry)]
|
|
62
|
+
: routes;
|
|
63
|
+
const children = topLevel.map((node) => buildRoute(rootRoute, "/", node));
|
|
64
|
+
return rootRoute.addChildren(children);
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* TanStack Router adapter: builds a router from the resolved routes and renders
|
|
68
|
+
* it via `<RouterProvider>`, so the generated default component works without
|
|
69
|
+
* manual route-tree wiring.
|
|
70
|
+
*/
|
|
71
|
+
export const tanstackRouterAdapter = function TanStackRouterAdapter({ routes }) {
|
|
72
|
+
const [router] = useState(() => createRouter({ routeTree: toTanstackRouteTree(routes) }));
|
|
73
|
+
return createElement(RouterProvider, { router });
|
|
74
|
+
};
|
|
75
|
+
//# sourceMappingURL=tanstack.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tanstack.js","sourceRoot":"","sources":["../../src/adapters/tanstack.ts"],"names":[],"mappings":"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"}
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAcA,wBAAsB,IAAI,CAAC,IAAI,GAAE,MAAM,EAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAiDvE"}
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { Command } from "commander";
|
|
3
|
+
import { watch } from "chokidar";
|
|
4
|
+
import { existsSync } from "node:fs";
|
|
5
|
+
import { createRequire } from "node:module";
|
|
6
|
+
import { resolve } from "node:path";
|
|
7
|
+
import { pathToFileURL } from "node:url";
|
|
8
|
+
import { loadConfig, resolveConfig } from "./config.js";
|
|
9
|
+
import { writeRoutes } from "./generator.js";
|
|
10
|
+
const require = createRequire(import.meta.url);
|
|
11
|
+
const pkg = require("../package.json");
|
|
12
|
+
export async function main(argv = process.argv) {
|
|
13
|
+
const program = new Command();
|
|
14
|
+
program
|
|
15
|
+
.name("rfr")
|
|
16
|
+
.version(pkg.version, "-v, --version", "Output the current version")
|
|
17
|
+
.option("-i, --input <directory>", "Path to the pages directory (overrides config)")
|
|
18
|
+
.option("-c, --config <file>", "Path to the config file", "rfr.config.ts")
|
|
19
|
+
.option("-o, --output <directory>", "Output directory (overrides config)")
|
|
20
|
+
.option("-a, --adapter <name>", "Routing adapter to use")
|
|
21
|
+
.option("-w, --watch", "Watch for changes and regenerate")
|
|
22
|
+
.option("-b, --build", "Generate once and exit (default)")
|
|
23
|
+
.parse(argv);
|
|
24
|
+
const opts = program.opts();
|
|
25
|
+
const userConfig = existsSync(opts.config)
|
|
26
|
+
? await loadConfig(opts.config)
|
|
27
|
+
: {};
|
|
28
|
+
const merged = {
|
|
29
|
+
...userConfig,
|
|
30
|
+
pages: opts.input ?? userConfig.pages,
|
|
31
|
+
outDir: opts.output ?? userConfig.outDir,
|
|
32
|
+
adapter: opts.adapter ?? userConfig.adapter,
|
|
33
|
+
};
|
|
34
|
+
const config = resolveConfig(merged, process.cwd());
|
|
35
|
+
writeRoutes(config);
|
|
36
|
+
console.log(`[react-fs-router] Generated ${config.outFile}`);
|
|
37
|
+
if (opts.watch) {
|
|
38
|
+
const watcher = watch(config.pages, { ignored: /(^|[\/\\])\../ });
|
|
39
|
+
const regenerate = () => {
|
|
40
|
+
try {
|
|
41
|
+
writeRoutes(config);
|
|
42
|
+
console.log(`[react-fs-router] Regenerated ${config.outFile}`);
|
|
43
|
+
}
|
|
44
|
+
catch (err) {
|
|
45
|
+
console.error("[react-fs-router]", err);
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
watcher.on("add", regenerate).on("change", regenerate).on("unlink", regenerate);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
const isDirectRun = process.argv[1] !== undefined &&
|
|
52
|
+
import.meta.url === pathToFileURL(resolve(process.argv[1])).href;
|
|
53
|
+
if (isDirectRun) {
|
|
54
|
+
main().catch((err) => {
|
|
55
|
+
console.error("[react-fs-router]", err);
|
|
56
|
+
process.exitCode = 1;
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { FileToFunction, PathFormatter, ResolvedConfig, UserConfig } from "./types.js";
|
|
2
|
+
export declare const DEFAULT_FUNCTIONS: Record<string, string>;
|
|
3
|
+
/** Default data-function file names (attached to the route rather than rendered). */
|
|
4
|
+
export declare const DEFAULT_LOADERS: Record<string, string>;
|
|
5
|
+
export declare const DEFAULT_EXTENSIONS: string[];
|
|
6
|
+
export declare const BUILTIN_ADAPTERS: readonly ["react-router", "custom", "tanstack-router"];
|
|
7
|
+
/** Default dynamic-segment formatting per adapter. */
|
|
8
|
+
export declare const DEFAULT_PATH_FORMATTERS: Record<string, PathFormatter>;
|
|
9
|
+
/** Typed identity helper for config files (provides intellisense without changing values). */
|
|
10
|
+
export declare function defineConfig(config: UserConfig): UserConfig;
|
|
11
|
+
/** Resolve a possibly-relative path against a base directory. */
|
|
12
|
+
export declare function toAbsolute(path: string, base: string): string;
|
|
13
|
+
/** Normalize a user "functions" mapping into a callable file-name -> function-name mapper. */
|
|
14
|
+
export declare function resolveFunctionMapper(functions: Record<string, string> | FileToFunction | undefined): FileToFunction;
|
|
15
|
+
/** Normalize a user "loaders" mapping into a callable file-name -> data-function-name mapper. */
|
|
16
|
+
export declare function resolveLoaderMapper(loaders: Record<string, string> | FileToFunction | undefined): FileToFunction;
|
|
17
|
+
/** Merge user config with defaults and resolve all paths to absolute. */
|
|
18
|
+
export declare function resolveConfig(user?: UserConfig, cwd?: string): ResolvedConfig;
|
|
19
|
+
/**
|
|
20
|
+
* Load a config module (.ts or .js). Supports `export default {...}` or a
|
|
21
|
+
* named `export const config`. Requires Node >= 20.6 for native .ts loading.
|
|
22
|
+
*/
|
|
23
|
+
export declare function loadConfig(configPath: string): Promise<UserConfig>;
|
|
24
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE5F,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAIpD,CAAC;AAEF,qFAAqF;AACrF,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAGlD,CAAC;AAEF,eAAO,MAAM,kBAAkB,UAAiC,CAAC;AAEjE,eAAO,MAAM,gBAAgB,wDAAyD,CAAC;AAEvF,sDAAsD;AACtD,eAAO,MAAM,uBAAuB,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAIjE,CAAC;AAEF,8FAA8F;AAC9F,wBAAgB,YAAY,CAAC,MAAM,EAAE,UAAU,GAAG,UAAU,CAE3D;AAED,iEAAiE;AACjE,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAE7D;AAED,8FAA8F;AAC9F,wBAAgB,qBAAqB,CACnC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,cAAc,GAAG,SAAS,GAC7D,cAAc,CAIhB;AAED,iGAAiG;AACjG,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,cAAc,GAAG,SAAS,GAC3D,cAAc,CAIhB;AAED,yEAAyE;AACzE,wBAAgB,aAAa,CAAC,IAAI,GAAE,UAAe,EAAE,GAAG,GAAE,MAAsB,GAAG,cAAc,CAyBhG;AAED;;;GAGG;AACH,wBAAsB,UAAU,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CASxE"}
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { isAbsolute, resolve } from "node:path";
|
|
2
|
+
import { pathToFileURL } from "node:url";
|
|
3
|
+
export const DEFAULT_FUNCTIONS = {
|
|
4
|
+
layout: "layout",
|
|
5
|
+
loading: "loading",
|
|
6
|
+
error: "error",
|
|
7
|
+
};
|
|
8
|
+
/** Default data-function file names (attached to the route rather than rendered). */
|
|
9
|
+
export const DEFAULT_LOADERS = {
|
|
10
|
+
loader: "loader",
|
|
11
|
+
action: "action",
|
|
12
|
+
};
|
|
13
|
+
export const DEFAULT_EXTENSIONS = [".js", ".jsx", ".ts", ".tsx"];
|
|
14
|
+
export const BUILTIN_ADAPTERS = ["react-router", "custom", "tanstack-router"];
|
|
15
|
+
/** Default dynamic-segment formatting per adapter. */
|
|
16
|
+
export const DEFAULT_PATH_FORMATTERS = {
|
|
17
|
+
"react-router": { dynamic: (name) => `:${name}`, catchAll: (name) => `*${name}` },
|
|
18
|
+
"tanstack-router": { dynamic: (name) => `$${name}`, catchAll: (name) => `*${name}` },
|
|
19
|
+
custom: { dynamic: (name) => `:${name}`, catchAll: (name) => `*${name}` },
|
|
20
|
+
};
|
|
21
|
+
/** Typed identity helper for config files (provides intellisense without changing values). */
|
|
22
|
+
export function defineConfig(config) {
|
|
23
|
+
return config;
|
|
24
|
+
}
|
|
25
|
+
/** Resolve a possibly-relative path against a base directory. */
|
|
26
|
+
export function toAbsolute(path, base) {
|
|
27
|
+
return isAbsolute(path) ? path : resolve(base, path);
|
|
28
|
+
}
|
|
29
|
+
/** Normalize a user "functions" mapping into a callable file-name -> function-name mapper. */
|
|
30
|
+
export function resolveFunctionMapper(functions) {
|
|
31
|
+
if (typeof functions === "function")
|
|
32
|
+
return functions;
|
|
33
|
+
const map = functions ?? DEFAULT_FUNCTIONS;
|
|
34
|
+
return (name) => map[name] ?? null;
|
|
35
|
+
}
|
|
36
|
+
/** Normalize a user "loaders" mapping into a callable file-name -> data-function-name mapper. */
|
|
37
|
+
export function resolveLoaderMapper(loaders) {
|
|
38
|
+
if (typeof loaders === "function")
|
|
39
|
+
return loaders;
|
|
40
|
+
const map = loaders ?? DEFAULT_LOADERS;
|
|
41
|
+
return (name) => map[name] ?? null;
|
|
42
|
+
}
|
|
43
|
+
/** Merge user config with defaults and resolve all paths to absolute. */
|
|
44
|
+
export function resolveConfig(user = {}, cwd = process.cwd()) {
|
|
45
|
+
const pages = toAbsolute(user.pages ?? "src/pages", cwd);
|
|
46
|
+
const outDir = toAbsolute(user.outDir ?? pages, cwd);
|
|
47
|
+
const adapter = user.adapter ?? "react-router";
|
|
48
|
+
const defaultFormatter = DEFAULT_PATH_FORMATTERS[adapter] ?? DEFAULT_PATH_FORMATTERS["react-router"];
|
|
49
|
+
return {
|
|
50
|
+
pages,
|
|
51
|
+
outDir,
|
|
52
|
+
outFile: toAbsolute(user.outFileName ?? "routes.tsx", outDir),
|
|
53
|
+
adapter,
|
|
54
|
+
fileToFunction: resolveFunctionMapper(user.functions),
|
|
55
|
+
fileToLoader: resolveLoaderMapper(user.loaders),
|
|
56
|
+
extensions: user.extensions ?? DEFAULT_EXTENSIONS,
|
|
57
|
+
ignore: user.ignore ?? [],
|
|
58
|
+
ignorePrefix: user.ignorePrefix ?? "_",
|
|
59
|
+
ignoreDotFiles: user.ignoreDotFiles ?? true,
|
|
60
|
+
inheritLayout: user.inheritLayout ?? true,
|
|
61
|
+
legacyBrowserRouter: user.legacyBrowserRouter ?? false,
|
|
62
|
+
pathFormatter: {
|
|
63
|
+
dynamic: user.formatDynamicSegment ?? defaultFormatter.dynamic,
|
|
64
|
+
catchAll: user.formatCatchAllSegment ?? defaultFormatter.catchAll,
|
|
65
|
+
},
|
|
66
|
+
importPrefix: user.importPrefix ?? null,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Load a config module (.ts or .js). Supports `export default {...}` or a
|
|
71
|
+
* named `export const config`. Requires Node >= 20.6 for native .ts loading.
|
|
72
|
+
*/
|
|
73
|
+
export async function loadConfig(configPath) {
|
|
74
|
+
const mod = await import(pathToFileURL(resolve(configPath)).href);
|
|
75
|
+
const namespace = mod;
|
|
76
|
+
const raw = namespace.default ?? namespace.config ?? mod;
|
|
77
|
+
if (raw && typeof raw === "object")
|
|
78
|
+
return raw;
|
|
79
|
+
throw new Error(`Config file "${configPath}" must export a config object (default export or named "config").`);
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { ResolvedConfig, RouteNode } from "./types.js";
|
|
2
|
+
interface FileRegistry {
|
|
3
|
+
fileToId: Map<string, string>;
|
|
4
|
+
}
|
|
5
|
+
/** Convert a file base name into a valid JS identifier. */
|
|
6
|
+
export declare function toIdentifier(file: string): string;
|
|
7
|
+
/** Assign a unique, readable import identifier to every referenced file. */
|
|
8
|
+
export declare function buildFileRegistry(tree: RouteNode[]): FileRegistry;
|
|
9
|
+
/** Compute the import specifier for a file, relative to the generated file (or aliased). */
|
|
10
|
+
export declare function importSpecifier(file: string, config: ResolvedConfig): string;
|
|
11
|
+
export type RouteSegmentKind = "literal" | "param" | "catch";
|
|
12
|
+
/** A parsed segment of a formatted route path (e.g. "/users/:id/edit"). */
|
|
13
|
+
export interface RouteSegment {
|
|
14
|
+
kind: RouteSegmentKind;
|
|
15
|
+
/** Literal text, param name, or catch-all name. */
|
|
16
|
+
name: string;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Split a formatted route path into segments. Dynamic segments start with
|
|
20
|
+
* ":" (react-router/custom) or "$" (tanstack); catch-all segments start with "*".
|
|
21
|
+
*/
|
|
22
|
+
export declare function parseRouteSegments(path: string): RouteSegment[];
|
|
23
|
+
/** Turn a segment into an uppercase object-key token ("about" -> "ABOUT"). */
|
|
24
|
+
export declare function segmentToken(segment: RouteSegment): string;
|
|
25
|
+
/** Build an object key from path segments; the root index route is "HOME". */
|
|
26
|
+
export declare function routeKeyForSegments(segments: RouteSegment[]): string;
|
|
27
|
+
/** An addressable route's entry in the generated `ROUTES` navigation map. */
|
|
28
|
+
export interface RouteMapEntry {
|
|
29
|
+
key: string;
|
|
30
|
+
path: string;
|
|
31
|
+
segments: RouteSegment[];
|
|
32
|
+
/** Param/catch-all names in path order (the function's arguments). */
|
|
33
|
+
params: string[];
|
|
34
|
+
hasCatch: boolean;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Collect every addressable route (files and directories that have an index
|
|
38
|
+
* page) into `ROUTES` entries, skipping duplicate keys.
|
|
39
|
+
*/
|
|
40
|
+
export declare function routeMapEntries(tree: RouteNode[]): RouteMapEntry[];
|
|
41
|
+
/** Render the body of `export const ROUTES = { ... }` for the given entries. */
|
|
42
|
+
export declare function routeMapSource(entries: RouteMapEntry[]): string;
|
|
43
|
+
/** Generate the routes module source for the resolved config. */
|
|
44
|
+
export declare function generateRoutesModule(config: ResolvedConfig): string;
|
|
45
|
+
/** Generate the routes module and write it to disk. Returns the output file path. */
|
|
46
|
+
export declare function writeRoutes(config: ResolvedConfig): string;
|
|
47
|
+
export {};
|
|
48
|
+
//# sourceMappingURL=generator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generator.d.ts","sourceRoot":"","sources":["../src/generator.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAa,SAAS,EAAE,MAAM,YAAY,CAAC;AAGvE,UAAU,YAAY;IACpB,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC/B;AAED,2DAA2D;AAC3D,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAIjD;AAED,4EAA4E;AAC5E,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,SAAS,EAAE,GAAG,YAAY,CA0BjE;AAED,4FAA4F;AAC5F,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,cAAc,GAAG,MAAM,CAU5E;AAkBD,MAAM,MAAM,gBAAgB,GAAG,SAAS,GAAG,OAAO,GAAG,OAAO,CAAC;AAE7D,2EAA2E;AAC3E,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,gBAAgB,CAAC;IACvB,mDAAmD;IACnD,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,EAAE,CAa/D;AAED,8EAA8E;AAC9E,wBAAgB,YAAY,CAAC,OAAO,EAAE,YAAY,GAAG,MAAM,CAG1D;AAED,8EAA8E;AAC9E,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,YAAY,EAAE,GAAG,MAAM,CAGpE;AAED,6EAA6E;AAC7E,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,YAAY,EAAE,CAAC;IACzB,sEAAsE;IACtE,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,SAAS,EAAE,GAAG,aAAa,EAAE,CA4BlE;AAkCD,gFAAgF;AAChF,wBAAgB,cAAc,CAAC,OAAO,EAAE,aAAa,EAAE,GAAG,MAAM,CAI/D;AAsBD,iEAAiE;AACjE,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,cAAc,GAAG,MAAM,CAuGnE;AAED,qFAAqF;AACrF,wBAAgB,WAAW,CAAC,MAAM,EAAE,cAAc,GAAG,MAAM,CAK1D"}
|