Fix routes typing with any
Signed-off-by: Émile Ré <nemile.re@gmail.com>
This commit is contained in:
@@ -4,11 +4,12 @@ import {
|
|||||||
redirect,
|
redirect,
|
||||||
useLoaderData,
|
useLoaderData,
|
||||||
useRouteError,
|
useRouteError,
|
||||||
|
type LoaderFunction,
|
||||||
type RouteObject,
|
type RouteObject,
|
||||||
} from "react-router";
|
} from "react-router";
|
||||||
import { MainLayout } from "./layouts/MainLayout";
|
import { MainLayout } from "./layouts/MainLayout";
|
||||||
import { AuthLayout, CenteredLayout, CenteredLayoutSkeleton } from "@probo/ui";
|
import { AuthLayout, CenteredLayout, CenteredLayoutSkeleton } from "@probo/ui";
|
||||||
import { Fragment, Suspense } from "react";
|
import { Fragment, Suspense, type ComponentType, type LazyExoticComponent } from "react";
|
||||||
import {
|
import {
|
||||||
relayEnvironment,
|
relayEnvironment,
|
||||||
UnAuthenticatedError,
|
UnAuthenticatedError,
|
||||||
@@ -16,7 +17,7 @@ import {
|
|||||||
ForbiddenError,
|
ForbiddenError,
|
||||||
} from "./providers/RelayProviders";
|
} from "./providers/RelayProviders";
|
||||||
import { PageSkeleton } from "./components/skeletons/PageSkeleton.tsx";
|
import { PageSkeleton } from "./components/skeletons/PageSkeleton.tsx";
|
||||||
import { loadQuery, type PreloadedQuery } from "react-relay";
|
import { loadQuery, type EnvironmentProviderOptions, type PreloadedQuery } from "react-relay";
|
||||||
import { useCleanup } from "./hooks/useDelayedEffect.ts";
|
import { useCleanup } from "./hooks/useDelayedEffect.ts";
|
||||||
import { riskRoutes } from "./routes/riskRoutes.ts";
|
import { riskRoutes } from "./routes/riskRoutes.ts";
|
||||||
import { measureRoutes } from "./routes/measureRoutes.ts";
|
import { measureRoutes } from "./routes/measureRoutes.ts";
|
||||||
@@ -38,13 +39,25 @@ import { snapshotsRoutes } from "./routes/snapshotsRoutes.ts";
|
|||||||
import { continualImprovementRoutes } from "./routes/continualImprovementRoutes.ts";
|
import { continualImprovementRoutes } from "./routes/continualImprovementRoutes.ts";
|
||||||
import { processingActivityRoutes } from "./routes/processingActivityRoutes.ts";
|
import { processingActivityRoutes } from "./routes/processingActivityRoutes.ts";
|
||||||
import { lazy } from "@probo/react-lazy";
|
import { lazy } from "@probo/react-lazy";
|
||||||
|
import type { OperationType, VariablesOf } from "relay-runtime";
|
||||||
|
import type { OrganizationGraph_ViewQuery } from "./hooks/graph/__generated__/OrganizationGraph_ViewQuery.graphql.ts";
|
||||||
|
|
||||||
export type AppRoute = Omit<RouteObject, "Component" | "children"> & {
|
type AppRouteWithoutQuery<TQuery extends OperationType> = Omit<RouteObject, "Component" | "children"> & {
|
||||||
Component?: React.ComponentType<any>;
|
Component?: React.ComponentType;
|
||||||
children?: AppRoute[];
|
children?: AppRoute<TQuery>[];
|
||||||
fallback?: React.ComponentType;
|
fallback?: React.ComponentType;
|
||||||
queryLoader?: (params: any) => PreloadedQuery<any>;
|
queryLoader?: undefined;
|
||||||
};
|
}
|
||||||
|
|
||||||
|
type AppRouteWithQuery<TQuery extends OperationType> = Omit<RouteObject, "Component" | "children"> & {
|
||||||
|
Component?:
|
||||||
|
LazyExoticComponent<ComponentType<{ queryRef: PreloadedQuery<TQuery, EnvironmentProviderOptions> }>>;
|
||||||
|
children?: AppRoute<TQuery>[];
|
||||||
|
fallback?: React.ComponentType;
|
||||||
|
queryLoader?: (params: VariablesOf<TQuery>) => PreloadedQuery<TQuery, EnvironmentProviderOptions>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type AppRoute<TQuery extends OperationType> = AppRouteWithoutQuery<TQuery> | AppRouteWithQuery<TQuery>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Top level error boundary
|
* Top level error boundary
|
||||||
@@ -141,7 +154,7 @@ const routes = [
|
|||||||
{
|
{
|
||||||
path: "settings",
|
path: "settings",
|
||||||
fallback: PageSkeleton,
|
fallback: PageSkeleton,
|
||||||
queryLoader: ({ organizationId }) =>
|
queryLoader: ({ organizationId }: VariablesOf<OrganizationGraph_ViewQuery>) =>
|
||||||
loadQuery(relayEnvironment, organizationViewQuery, {
|
loadQuery(relayEnvironment, organizationViewQuery, {
|
||||||
organizationId,
|
organizationId,
|
||||||
}),
|
}),
|
||||||
@@ -199,40 +212,40 @@ const routes = [
|
|||||||
path: "*",
|
path: "*",
|
||||||
Component: PageError,
|
Component: PageError,
|
||||||
},
|
},
|
||||||
] satisfies AppRoute[];
|
] as AppRoute<OperationType>[];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wrap components with suspense to handle lazy loading & relay loading states
|
* Wrap components with suspense to handle lazy loading & relay loading states
|
||||||
*/
|
*/
|
||||||
function routeTransformer({
|
function routeTransformer<TQuery extends OperationType>({
|
||||||
|
Component,
|
||||||
fallback: FallbackComponent,
|
fallback: FallbackComponent,
|
||||||
queryLoader,
|
queryLoader,
|
||||||
...route
|
children,
|
||||||
}: AppRoute): RouteObject {
|
...rest
|
||||||
let result = { ...route };
|
}: AppRoute<TQuery>): RouteObject {
|
||||||
if (FallbackComponent && route.Component) {
|
let route: RouteObject = { ...rest };
|
||||||
const OriginalComponent = route.Component;
|
|
||||||
result = {
|
if (Component) {
|
||||||
...result,
|
let RouteComponent = Component;
|
||||||
Component: (props) => (
|
|
||||||
|
if (FallbackComponent && typeof queryLoader === "undefined") {
|
||||||
|
const OriginalComponent = Component as ComponentType;
|
||||||
|
|
||||||
|
RouteComponent = () => (
|
||||||
<Suspense fallback={<FallbackComponent />}>
|
<Suspense fallback={<FallbackComponent />}>
|
||||||
<OriginalComponent {...props} />
|
<OriginalComponent />
|
||||||
</Suspense>
|
</Suspense>
|
||||||
),
|
);
|
||||||
};
|
|
||||||
}
|
route = {
|
||||||
if (queryLoader && route.Component) {
|
...route,
|
||||||
const OriginalComponent = route.Component;
|
Component: RouteComponent,
|
||||||
result = {
|
};
|
||||||
...result,
|
} else if (queryLoader) {
|
||||||
loader: ({ params }) => {
|
const OriginalComponent = Component as LazyExoticComponent<ComponentType<{ queryRef: PreloadedQuery<TQuery, EnvironmentProviderOptions> }>>;
|
||||||
const query = queryLoader(params as Record<string, string>);
|
|
||||||
return {
|
RouteComponent = () => {
|
||||||
queryRef: query,
|
|
||||||
dispose: query.dispose,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
Component: () => {
|
|
||||||
const { queryRef, dispose } = useLoaderData();
|
const { queryRef, dispose } = useLoaderData();
|
||||||
|
|
||||||
useCleanup(dispose, 1000);
|
useCleanup(dispose, 1000);
|
||||||
@@ -242,12 +255,27 @@ function routeTransformer({
|
|||||||
<OriginalComponent queryRef={queryRef} />
|
<OriginalComponent queryRef={queryRef} />
|
||||||
</Suspense>
|
</Suspense>
|
||||||
);
|
);
|
||||||
},
|
};
|
||||||
};
|
|
||||||
|
const loader: LoaderFunction = ({ params }) => {
|
||||||
|
const query = queryLoader(params as VariablesOf<TQuery>);
|
||||||
|
return {
|
||||||
|
queryRef: query,
|
||||||
|
dispose: query.dispose,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
route = {
|
||||||
|
...route,
|
||||||
|
loader: loader,
|
||||||
|
Component: RouteComponent,
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...result,
|
...route,
|
||||||
children: route.children?.map(routeTransformer),
|
children: children?.map(routeTransformer<TQuery>),
|
||||||
} as RouteObject;
|
} as RouteObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user