|
1 | 1 | import AppRoot from "~/index";
|
2 | 2 |
|
| 3 | +import { data, type LoaderFunctionArgs } from "react-router"; |
| 4 | + |
| 5 | +import { ABSOLUTE_ROUTES } from "~/routing/routes.constants"; |
| 6 | + |
| 7 | +type RouteGroup = Record<string, string> | Record<string, unknown>; |
| 8 | +type Route = string | RouteGroup; |
| 9 | + |
| 10 | +function routeGroupToPaths(routeGroup: RouteGroup): string[] { |
| 11 | + return Object.entries(routeGroup).flatMap(([, route]) => |
| 12 | + routeToPaths(route as Route) |
| 13 | + ); |
| 14 | +} |
| 15 | + |
| 16 | +function routeToPaths(route: Route) { |
| 17 | + if (typeof route === "string") { |
| 18 | + return route == "/" ? [] : [route]; |
| 19 | + } |
| 20 | + return routeGroupToPaths(route as RouteGroup); |
| 21 | +} |
| 22 | + |
| 23 | +function routeToStaticPart(route: string) { |
| 24 | + const parts = route.split("/"); |
| 25 | + const staticParts = []; |
| 26 | + for (const part of parts) { |
| 27 | + if (part.startsWith(":") || part.startsWith("*")) break; |
| 28 | + staticParts.push(part); |
| 29 | + } |
| 30 | + return staticParts.join("/"); |
| 31 | +} |
| 32 | + |
| 33 | +const KNOWN_ROUTES_SET = new Set( |
| 34 | + routeGroupToPaths(ABSOLUTE_ROUTES).map((route) => routeToStaticPart(route)) |
| 35 | +); |
| 36 | +const KNOWN_ROUTES = [...Array.from(KNOWN_ROUTES_SET), "/v2", "/admin"]; |
| 37 | + |
| 38 | +export async function loader({ request }: LoaderFunctionArgs) { |
| 39 | + const url = new URL(request.url); |
| 40 | + const path = url.pathname; |
| 41 | + const isKnownRoute = |
| 42 | + path == "/" || KNOWN_ROUTES.some((route) => path.startsWith(route)); |
| 43 | + if (!isKnownRoute) { |
| 44 | + throw data("Not Found", { status: 404 }); |
| 45 | + } |
| 46 | + return data({}); |
| 47 | +} |
| 48 | + |
3 | 49 | export default function Component() {
|
4 | 50 | return <AppRoot />;
|
5 | 51 | }
|
0 commit comments