Skip to content

Commit 4d483cb

Browse files
committed
wip
1 parent bd6a306 commit 4d483cb

File tree

3 files changed

+75
-64
lines changed

3 files changed

+75
-64
lines changed
Lines changed: 22 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import type { MetaArgs, UIMatch, UNSAFE_MetaMatch } from "@remix-run/react";
22
import type {
3-
LoaderFunctionArgs,
4-
ActionFunctionArgs,
3+
Loader,
4+
Action,
55
SerializeFrom,
66
TypedDeferredData,
77
TypedResponse,
@@ -11,90 +11,52 @@ import type {
1111
FetcherWithComponents,
1212
} from "react-router-dom";
1313

14-
type Serializable =
15-
| undefined
16-
| null
17-
| boolean
18-
| string
19-
| symbol
20-
| number
21-
| Array<Serializable>
22-
| { [key: PropertyKey]: Serializable }
23-
| bigint
24-
| Date
25-
| URL
26-
| RegExp
27-
| Error
28-
| Map<Serializable, Serializable>
29-
| Set<Serializable>
30-
| Promise<Serializable>;
31-
32-
type DataFunctionReturnValue =
33-
| Serializable
34-
| TypedDeferredData<Record<string, unknown>>
35-
| TypedResponse<Record<string, unknown>>;
36-
37-
type LoaderFunction_SingleFetch = (
38-
args: LoaderFunctionArgs
39-
) => Promise<DataFunctionReturnValue> | DataFunctionReturnValue;
40-
type ActionFunction_SingleFetch = (
41-
args: ActionFunctionArgs
42-
) => Promise<DataFunctionReturnValue> | DataFunctionReturnValue;
43-
4414
// Backwards-compatible type for Remix v2 where json/defer still use the old types,
4515
// and only non-json/defer returns use the new types. This allows for incremental
4616
// migration of loaders to return naked objects. In the next major version,
4717
// json/defer will be removed so everything will use the new simplified typings.
4818
// prettier-ignore
49-
type SingleFetchSerialize_V2<T extends LoaderFunction_SingleFetch | ActionFunction_SingleFetch> =
19+
type Serialize<T extends Loader | Action> =
5020
Awaited<ReturnType<T>> extends TypedDeferredData<infer D> ? D :
5121
Awaited<ReturnType<T>> extends TypedResponse<Record<string, unknown>> ? SerializeFrom<T> :
5222
Awaited<ReturnType<T>>;
5323

5424
declare module "@remix-run/react" {
55-
export function useLoaderData<T>(): T extends LoaderFunction_SingleFetch
56-
? SingleFetchSerialize_V2<T>
57-
: never;
25+
export function useLoaderData<T>(): T extends Loader ? Serialize<T> : T;
5826

59-
export function useActionData<T>(): T extends ActionFunction_SingleFetch
60-
? SingleFetchSerialize_V2<T> | undefined
61-
: never;
27+
export function useActionData<T>(): T extends Action
28+
? Serialize<T> | undefined
29+
: T;
6230

6331
export function useRouteLoaderData<T>(
6432
routeId: string
65-
): T extends LoaderFunction_SingleFetch ? SingleFetchSerialize_V2<T> : never;
33+
): T extends Loader ? Serialize<T> : never;
6634

6735
export function useFetcher<TData = unknown>(
6836
opts?: Parameters<typeof useFetcherRR>[0]
6937
): FetcherWithComponents<
70-
TData extends LoaderFunction_SingleFetch | ActionFunction_SingleFetch
71-
? SingleFetchSerialize_V2<TData>
72-
: never
38+
TData extends Loader | Action ? Serialize<TData> : TData
7339
>;
7440

7541
export type UIMatch_SingleFetch<D = unknown, H = unknown> = Omit<
7642
UIMatch<D, H>,
7743
"data"
7844
> & {
79-
data: D extends LoaderFunction_SingleFetch
80-
? SingleFetchSerialize_V2<D>
81-
: never;
45+
data: D extends Loader ? Serialize<D> : never;
8246
};
8347

8448
interface MetaMatch_SingleFetch<
8549
RouteId extends string = string,
86-
Loader extends LoaderFunction_SingleFetch | unknown = unknown
87-
> extends Omit<UNSAFE_MetaMatch<RouteId, Loader>, "data"> {
88-
data: Loader extends LoaderFunction_SingleFetch
89-
? SingleFetchSerialize_V2<Loader>
90-
: unknown;
50+
L extends Loader | unknown = unknown
51+
> extends Omit<UNSAFE_MetaMatch<RouteId, L>, "data"> {
52+
data: L extends Loader ? Serialize<L> : unknown;
9153
}
9254

9355
type MetaMatches_SingleFetch<
94-
MatchLoaders extends Record<
56+
MatchLoaders extends Record<string, Loader | unknown> = Record<
9557
string,
96-
LoaderFunction_SingleFetch | unknown
97-
> = Record<string, unknown>
58+
unknown
59+
>
9860
> = Array<
9961
{
10062
[K in keyof MatchLoaders]: MetaMatch_SingleFetch<
@@ -105,17 +67,13 @@ declare module "@remix-run/react" {
10567
>;
10668

10769
export interface MetaArgs_SingleFetch<
108-
Loader extends LoaderFunction_SingleFetch | unknown = unknown,
109-
MatchLoaders extends Record<
70+
L extends Loader | unknown = unknown,
71+
MatchLoaders extends Record<string, Loader | unknown> = Record<
11072
string,
111-
LoaderFunction_SingleFetch | unknown
112-
> = Record<string, unknown>
113-
> extends Omit<MetaArgs<Loader, MatchLoaders>, "data" | "matches"> {
114-
data:
115-
| (Loader extends LoaderFunction_SingleFetch
116-
? SingleFetchSerialize_V2<Loader>
117-
: unknown)
118-
| undefined;
73+
unknown
74+
>
75+
> extends Omit<MetaArgs<L, MatchLoaders>, "data" | "matches"> {
76+
data: (L extends Loader ? Serialize<L> : unknown) | undefined;
11977
matches: MetaMatches_SingleFetch<MatchLoaders>;
12078
}
12179
}

packages/remix-server-runtime/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ export {
66
} from "./formData";
77
export { defer, json, redirect, redirectDocument } from "./responses";
88
export type {
9+
Loader,
10+
Action,
911
SingleFetchResult as UNSAFE_SingleFetchResult,
1012
SingleFetchResults as UNSAFE_SingleFetchResults,
1113
} from "./single-fetch";

packages/remix-server-runtime/single-fetch.ts

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
import type {
2+
ActionFunctionArgs as RRActionArgs,
3+
LoaderFunctionArgs as RRLoaderArgs,
24
StaticHandler,
35
unstable_DataStrategyFunctionArgs as DataStrategyFunctionArgs,
46
unstable_DataStrategyFunction as DataStrategyFunction,
@@ -19,6 +21,7 @@ import type {
1921
ResponseStubOperation,
2022
} from "./routeModules";
2123
import { ResponseStubOperationsSymbol } from "./routeModules";
24+
import type { TypedDeferredData, TypedResponse } from "./responses";
2225
import { isDeferredData, isRedirectStatusCode, isResponse } from "./responses";
2326

2427
export const SingleFetchRedirectSymbol = Symbol("SingleFetchRedirect");
@@ -504,3 +507,51 @@ export function encodeViaTurboStream(
504507
],
505508
});
506509
}
510+
511+
type MaybePromise<T> = T | Promise<T>;
512+
513+
type Serializable =
514+
| undefined
515+
| null
516+
| boolean
517+
| string
518+
| symbol
519+
| number
520+
| Array<Serializable>
521+
| { [key: PropertyKey]: Serializable }
522+
| bigint
523+
| Date
524+
| URL
525+
| RegExp
526+
| Error
527+
| Map<Serializable, Serializable>
528+
| Set<Serializable>
529+
| Promise<Serializable>;
530+
531+
type DataFunctionReturnValue =
532+
| Serializable
533+
| TypedDeferredData<Record<string, unknown>>
534+
| TypedResponse<Record<string, unknown>>;
535+
536+
type LoaderArgs = RRLoaderArgs<AppLoadContext> & {
537+
// Context is always provided in Remix, and typed for module augmentation support.
538+
context: AppLoadContext;
539+
response: ResponseStub;
540+
};
541+
542+
export type Loader = (
543+
args: LoaderArgs
544+
) => MaybePromise<DataFunctionReturnValue>;
545+
546+
type ActionArgs = RRActionArgs<AppLoadContext> & {
547+
// Context is always provided in Remix, and typed for module augmentation support.
548+
context: AppLoadContext;
549+
response: ResponseStub;
550+
};
551+
552+
export type Action = (
553+
args: ActionArgs
554+
) => MaybePromise<DataFunctionReturnValue>;
555+
556+
export let defineLoader = <T extends Loader>(loader: T): T => loader;
557+
export let defineAction = <T extends Action>(action: T): T => action;

0 commit comments

Comments
 (0)