Skip to content

Commit bacb98a

Browse files
committed
Create makeSWRHelper
1 parent 8ffb905 commit bacb98a

File tree

2 files changed

+83
-6
lines changed

2 files changed

+83
-6
lines changed

src/index.ts

Lines changed: 52 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
import type createClient from "openapi-fetch";
2-
import type { FetchOptions, ParseAsResponse } from "openapi-fetch";
2+
import type {
3+
FetchOptions,
4+
FetchResponse,
5+
ParseAsResponse,
6+
} from "openapi-fetch";
37
import type {
48
ErrorResponse,
59
FilterKeys,
@@ -8,7 +12,8 @@ import type {
812
ResponseObjectMap,
913
SuccessResponse,
1014
} from "openapi-typescript-helpers";
11-
import useSWR, { useSWRConfig, type SWRConfiguration } from "swr";
15+
import useSWR, { Fetcher, type SWRConfiguration } from "swr";
16+
import { SWRInfiniteKeyLoader } from "swr/infinite";
1217

1318
export function makeHookFactory<Paths extends {}>(
1419
api: ReturnType<typeof createClient<Paths>>,
@@ -67,3 +72,48 @@ export function makeHookFactory<Paths extends {}>(
6772
return useHook;
6873
};
6974
}
75+
76+
export function makeSWRHelper<Paths extends {}>(
77+
api: ReturnType<typeof createClient<Paths>>,
78+
keyPrefix: string,
79+
) {
80+
function swrHelper<
81+
Path extends PathsWithMethod<Paths, "get">,
82+
Req extends FilterKeys<Paths[Path], "get">,
83+
Options extends FetchOptions<Req>,
84+
Data extends NonNullable<FetchResponse<Req, Options>["data"]>,
85+
Key extends [string, Path, Options],
86+
OptionsInput extends
87+
| Options
88+
| ((index: number, previousPageData: Data | null) => Options | null),
89+
>(
90+
path: Path,
91+
optionsOrFn: OptionsInput,
92+
): OptionsInput extends Options
93+
? [Key, Fetcher<Data, Key>]
94+
: [SWRInfiniteKeyLoader<Data, Key>, Fetcher<Data, Key>] {
95+
const key =
96+
typeof optionsOrFn === "function"
97+
? (index: number, previousPageData: Data | null) => {
98+
const options = optionsOrFn(index, previousPageData);
99+
if (options === null) {
100+
return null;
101+
}
102+
return [keyPrefix, path, options] as const;
103+
}
104+
: ([keyPrefix, path, optionsOrFn] as const);
105+
106+
const fetcher = async ([, url, init]: Key) => {
107+
const { data, error } = await api.GET(url, init);
108+
if (error) {
109+
throw error;
110+
}
111+
return data!;
112+
};
113+
114+
// @ts-expect-error - TODO: Come back to make the types sound
115+
return [key, fetcher] as const;
116+
}
117+
118+
return swrHelper;
119+
}

test/index.spec.ts

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1-
import createClient from "openapi-fetch";
2-
import type { paths } from "../generated/petstore";
3-
import { makeHookFactory } from "../src/index";
4-
51
import { expectTypeOf } from "expect-type";
2+
import createClient from "openapi-fetch";
63
import { SuccessResponseJSON } from "openapi-typescript-helpers";
4+
import useSWR from "swr";
5+
import useSWRInfinite from "swr/infinite";
6+
import type { paths } from "../generated/petstore";
7+
import { makeHookFactory, makeSWRHelper } from "../src/index";
78

89
const petStoreApi = createClient<paths>({
910
baseUrl: "https://petstore3.swagger.io/api/v3",
@@ -42,3 +43,29 @@ const { data: suspenseData } = useOrder(
4243
);
4344

4445
expectTypeOf(suspenseData).toEqualTypeOf<OrderSuccessResponse>();
46+
47+
const swrPetStore = makeSWRHelper(petStoreApi, "pet-store");
48+
49+
swrPetStore("/store/order/{orderId}", {
50+
params: { path: { orderId: 1 } },
51+
});
52+
53+
swrPetStore("/store/order/{orderId}", () => ({
54+
params: { path: { orderId: 1 } },
55+
}));
56+
57+
useSWR(
58+
...swrPetStore("/store/order/{orderId}", {
59+
params: { path: { orderId: 1 } },
60+
}),
61+
);
62+
63+
useSWRInfinite(
64+
...swrPetStore("/pet/findByStatus", (index, previous) => ({
65+
params: {
66+
query: {
67+
status: "available",
68+
},
69+
},
70+
})),
71+
);

0 commit comments

Comments
 (0)