Skip to content

Instantly share code, notes, and snippets.

@notcod
Created July 18, 2024 08:25
Show Gist options
  • Save notcod/1ac86bdaa9b824a7f188b72064abd05b to your computer and use it in GitHub Desktop.
Save notcod/1ac86bdaa9b824a7f188b72064abd05b to your computer and use it in GitHub Desktop.
routes.tsx
import { generatePreservedRoutes, generateRegularRoutes } from '@generouted/react-router/core';
import { createBrowserRouter, Outlet, RouterProvider } from 'react-router-dom';
import type { RouteObject } from 'react-router-dom';
import { Fragment } from 'react';
type Module = { default: () => JSX.Element; Catch?: () => JSX.Element };
const patterns = {
route: [/^.*\/src\/pages\/|\.(jsx|tsx|mdx)$/g, ''],
splat: [/\[\.{3}\w+\]/g, '*'],
param: [/\[([^\]]+)\]/g, ':$1'],
slash: [/^index$|\./g, '/'],
optional: [/^-(:?[\w-]+|\*)/, '$1?'],
lazy: [/\.lazy/g, ''], // New pattern to handle the removal of .lazy
} as const;
type BaseRoute = { id?: string; path?: string; children?: BaseRoute[] } & Record<string, any>;
const generateLazyRoutes = <T extends BaseRoute, M>(files: Record<string, any>, buildRoute: (module: M, key: string) => T) => {
const filteredRoutes = Object.keys(files).filter((key) => !key.includes('/_') || /_layout\.(jsx|tsx)$/.test(key));
return filteredRoutes.reduce<T[]>((routes, key) => {
const module = files[key];
const route = { id: key.replace(...patterns.route), ...buildRoute(module, key) };
const segments = key
.replace(...patterns.route)
.replace(...patterns.splat)
.replace(...patterns.param)
.split('/')
.filter(Boolean);
segments.reduce((parent, segment, index) => {
const path = segment
.replace(...patterns.lazy) //added to remove .lazy
.replace(...patterns.slash)
.replace(...patterns.optional);
const root = index === 0;
const leaf = index === segments.length - 1 && segments.length > 1;
const node = !root && !leaf;
const layout = segment === '_layout';
const group = /\([\w-]+\)/.test(path);
const insert = /^\w|\//.test(path) ? 'unshift' : 'push';
if (root) {
const last = segments.length === 1;
if (last) {
routes.push({ path, ...route });
return parent;
}
}
if (root || node) {
const current = root ? routes : parent.children;
const found = current?.find((route) => route.path === path || route.id?.replace('/_layout', '').endsWith(path));
const props = group ? (route?.component ? { id: path, path: '/' } : { id: path }) : { path };
if (found) found.children ??= [];
else current?.[insert]({ ...props, children: [] });
return found || (current?.[insert === 'unshift' ? 0 : current.length - 1] as BaseRoute);
}
if (layout) {
return Object.assign(parent, route);
}
if (leaf) {
parent?.children?.[insert](route?.index ? route : { path, ...route });
}
return parent;
}, {} as BaseRoute);
return routes;
}, []);
};
const PRESERVED = import.meta.glob<Module>('/src/pages/(_app|404).tsx', { eager: true });
const ROUTES = import.meta.glob<Module>(['/src/pages/**/[\\w[-]*.tsx', '!/src/pages/**/(_!(layout)*(/*)?|_app|404|*.lazy)*'], { eager: true });
const LAZY = import.meta.glob<Module>(['/src/pages/**/[\\w[-]*.lazy.tsx', '!/src/pages/**/(_!(layout)*(/*)?|_app|404)*']);
const preservedRoutes = generatePreservedRoutes<Omit<Module, 'Action'>>(PRESERVED);
const regularRoutes = generateRegularRoutes<RouteObject, Partial<Module>>(ROUTES, (module, key) => {
const index = /index\.(jsx|tsx|mdx)$/.test(key) && !key.includes('pages/index') ? { index: true } : {};
return { ...index, Component: module?.default || Fragment, ErrorBoundary: module?.Catch };
});
const lazyRoutes = generateLazyRoutes<RouteObject, () => Promise<Partial<Module>>>(LAZY, (module, key) => {
const index = /index\.(jsx|tsx|mdx)$/.test(key) && !key.includes('pages/index') ? { index: true } : {};
return { ...index, lazy: async () => ({ Component: (await module())?.default || Fragment, ErrorBoundary: (await module())?.Catch }) };
});
const _app = preservedRoutes?.['_app'];
const _404 = preservedRoutes?.['404'];
const app = { Component: _app?.default || Outlet, ErrorBoundary: _app?.Catch };
const fallback = { path: '*', Component: _404?.default || Fragment };
const routes: RouteObject[] = [{ ...app, children: [...regularRoutes, ...lazyRoutes, fallback] }];
const router = createBrowserRouter(routes);
export const Routes = () => <RouterProvider router={router} />;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment