UNPKG

8.05 kBTypeScriptView Raw
1
2import { Location } from "../router/history.js";
3import { DataStrategyResult, MiddlewareNextFunction } from "../router/utils.js";
4import { LinkDescriptor } from "../router/links.js";
5import { Func, Pretty } from "./utils.js";
6import { RouteModule } from "./route-module.js";
7import { ClientDataFunctionArgs, GetLoaderData, ServerDataFrom, ServerDataFunctionArgs } from "./route-data.js";
8import { MetaDescriptor } from "../dom/ssr/routeModules.js";
9
10//#region lib/types/route-module-annotations.d.ts
11type MaybePromise<T> = T | Promise<T>;
12type Props = {
13 params: unknown;
14 loaderData: unknown;
15 actionData: unknown;
16};
17type RouteInfo = Props & {
18 module: RouteModule;
19 matches: Array<MatchInfo>;
20};
21type MatchInfo = {
22 id: string;
23 module: RouteModule;
24};
25type MetaMatch<T extends MatchInfo> = Pretty<{
26 id: T["id"];
27 params: Record<string, string | undefined>;
28 pathname: string;
29 meta: MetaDescriptor[];
30 loaderData: GetLoaderData<T["module"]>;
31 handle?: unknown;
32 error?: unknown;
33}>;
34type MetaMatches<T extends Array<MatchInfo>> = T extends [infer F extends MatchInfo, ...infer R extends Array<MatchInfo>] ? [MetaMatch<F>, ...MetaMatches<R>] : Array<MetaMatch<MatchInfo> | undefined>;
35type HasErrorBoundary<T extends RouteInfo> = T["module"] extends {
36 ErrorBoundary: Func;
37} ? true : false;
38type CreateMetaArgs<T extends RouteInfo> = {
39 /** This is the current router `Location` object. This is useful for generating tags for routes at specific paths or query parameters. */location: Location; /** {@link https://reactrouter.com/start/framework/routing#dynamic-segments Dynamic route params} for the current route. */
40 params: T["params"]; /** The return value for this route's server loader function */
41 loaderData: T["loaderData"] | (HasErrorBoundary<T> extends true ? undefined : never); /** Thrown errors that trigger error boundaries will be passed to the meta function. This is useful for generating metadata for error pages. */
42 error?: unknown; /** An array of the current {@link https://api.reactrouter.com/v7/interfaces/react-router.UIMatch.html route matches}, including parent route matches. */
43 matches: MetaMatches<T["matches"]>;
44};
45type MetaDescriptors = MetaDescriptor[];
46type HeadersArgs = {
47 loaderHeaders: Headers;
48 parentHeaders: Headers;
49 actionHeaders: Headers;
50 errorHeaders: Headers | undefined;
51};
52type CreateServerMiddlewareFunction<T extends RouteInfo> = (args: ServerDataFunctionArgs<T["params"]>, next: MiddlewareNextFunction<Response>) => MaybePromise<Response | void>;
53type CreateClientMiddlewareFunction<T extends RouteInfo> = (args: ClientDataFunctionArgs<T["params"]>, next: MiddlewareNextFunction<Record<string, DataStrategyResult>>) => MaybePromise<Record<string, DataStrategyResult> | void>;
54type CreateServerLoaderArgs<T extends RouteInfo> = ServerDataFunctionArgs<T["params"]>;
55type CreateClientLoaderArgs<T extends RouteInfo> = ClientDataFunctionArgs<T["params"]> & {
56 /** This is an asynchronous function to get the data from the server loader for this route. On client-side navigations, this will make a {@link https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API fetch} call to the React Router server loader. If you opt-into running your clientLoader on hydration, then this function will return the data that was already loaded on the server (via Promise.resolve). */serverLoader: () => Promise<ServerDataFrom<T["module"]["loader"]>>;
57};
58type CreateServerActionArgs<T extends RouteInfo> = ServerDataFunctionArgs<T["params"]>;
59type CreateClientActionArgs<T extends RouteInfo> = ClientDataFunctionArgs<T["params"]> & {
60 /** This is an asynchronous function that makes the {@link https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API fetch} call to the React Router server action for this route. */serverAction: () => Promise<ServerDataFrom<T["module"]["action"]>>;
61};
62type CreateHydrateFallbackProps<T extends RouteInfo, RSCEnabled extends boolean> = {
63 params: T["params"];
64} & (RSCEnabled extends true ? {
65 /** The data returned from the `loader` */loaderData?: ServerDataFrom<T["module"]["loader"]>; /** The data returned from the `action` following an action submission. */
66 actionData?: ServerDataFrom<T["module"]["action"]>;
67} : {
68 /** The data returned from the `loader` or `clientLoader` */loaderData?: T["loaderData"]; /** The data returned from the `action` or `clientAction` following an action submission. */
69 actionData?: T["actionData"];
70});
71type Match<T extends MatchInfo> = Pretty<{
72 id: T["id"];
73 params: Record<string, string | undefined>;
74 pathname: string;
75 loaderData: GetLoaderData<T["module"]>;
76 handle: unknown;
77}>;
78type Matches<T extends Array<MatchInfo>> = T extends [infer F extends MatchInfo, ...infer R extends Array<MatchInfo>] ? [Match<F>, ...Matches<R>] : Array<Match<MatchInfo> | undefined>;
79type CreateComponentProps<T extends RouteInfo, RSCEnabled extends boolean> = {
80 /**
81 * {@link https://reactrouter.com/start/framework/routing#dynamic-segments Dynamic route params} for the current route.
82 * @example
83 * // app/routes.ts
84 * route("teams/:teamId", "./team.tsx"),
85 *
86 * // app/team.tsx
87 * export default function Component({
88 * params,
89 * }: Route.ComponentProps) {
90 * params.teamId;
91 * // ^ string
92 * }
93 **/
94 params: T["params"]; /** An array of the current {@link https://api.reactrouter.com/v7/interfaces/react-router.UIMatch.html route matches}, including parent route matches. */
95 matches: Matches<T["matches"]>;
96} & (RSCEnabled extends true ? {
97 /** The data returned from the `loader` */loaderData: ServerDataFrom<T["module"]["loader"]>; /** The data returned from the `action` following an action submission. */
98 actionData?: ServerDataFrom<T["module"]["action"]>;
99} : {
100 /** The data returned from the `loader` or `clientLoader` */loaderData: T["loaderData"]; /** The data returned from the `action` or `clientAction` following an action submission. */
101 actionData?: T["actionData"];
102});
103type CreateErrorBoundaryProps<T extends RouteInfo, RSCEnabled extends boolean> = {
104 /**
105 * {@link https://reactrouter.com/start/framework/routing#dynamic-segments Dynamic route params} for the current route.
106 * @example
107 * // app/routes.ts
108 * route("teams/:teamId", "./team.tsx"),
109 *
110 * // app/team.tsx
111 * export function ErrorBoundary({
112 * params,
113 * }: Route.ErrorBoundaryProps) {
114 * params.teamId;
115 * // ^ string
116 * }
117 **/
118 params: T["params"];
119 error: unknown;
120} & (RSCEnabled extends true ? {
121 /** The data returned from the `loader` */loaderData?: ServerDataFrom<T["module"]["loader"]>; /** The data returned from the `action` following an action submission. */
122 actionData?: ServerDataFrom<T["module"]["action"]>;
123} : {
124 /** The data returned from the `loader` or `clientLoader` */loaderData?: T["loaderData"]; /** The data returned from the `action` or `clientAction` following an action submission. */
125 actionData?: T["actionData"];
126});
127type GetAnnotations<Info extends RouteInfo> = {
128 LinkDescriptors: LinkDescriptor[];
129 LinksFunction: () => LinkDescriptor[];
130 MetaArgs: CreateMetaArgs<Info>;
131 MetaDescriptors: MetaDescriptors;
132 MetaFunction: (args: CreateMetaArgs<Info>) => MetaDescriptors;
133 HeadersArgs: HeadersArgs;
134 HeadersFunction: (args: HeadersArgs) => Headers | HeadersInit;
135 MiddlewareFunction: CreateServerMiddlewareFunction<Info>;
136 ClientMiddlewareFunction: CreateClientMiddlewareFunction<Info>;
137 LoaderArgs: CreateServerLoaderArgs<Info>;
138 ClientLoaderArgs: CreateClientLoaderArgs<Info>;
139 ActionArgs: CreateServerActionArgs<Info>;
140 ClientActionArgs: CreateClientActionArgs<Info>;
141 HydrateFallbackProps: CreateHydrateFallbackProps<Info, false>;
142 ServerHydrateFallbackProps: CreateHydrateFallbackProps<Info, true>;
143 ComponentProps: CreateComponentProps<Info, false>;
144 ServerComponentProps: CreateComponentProps<Info, true>;
145 ErrorBoundaryProps: CreateErrorBoundaryProps<Info, false>;
146 ServerErrorBoundaryProps: CreateErrorBoundaryProps<Info, true>;
147};
148//#endregion
149export { GetAnnotations };
\No newline at end of file