11import type createClient from "openapi-fetch" ;
2- import type {
3- FetchOptions ,
4- FetchResponse ,
5- ParseAsResponse ,
6- } from "openapi-fetch" ;
2+ import type { FetchOptions , ParseAsResponse } from "openapi-fetch" ;
73import type {
84 ErrorResponse ,
95 FilterKeys ,
@@ -12,108 +8,89 @@ import type {
128 ResponseObjectMap ,
139 SuccessResponse ,
1410} from "openapi-typescript-helpers" ;
15- import useSWR , { Fetcher , type SWRConfiguration } from "swr" ;
16- import { SWRInfiniteKeyLoader } from "swr/infinite" ;
11+ import useSWR , { type SWRConfiguration } from "swr" ;
12+ import useSWRInfinite , { SWRInfiniteKeyLoader } from "swr/infinite" ;
1713
18- export function makeHookFactory < Paths extends { } > (
14+ export function createHooks < Paths extends { } > (
1915 api : ReturnType < typeof createClient < Paths > > ,
2016 keyPrefix : string ,
2117) {
22- // Define hook factory with typed paths
23- return function hookFactory <
18+ function use <
2419 Path extends PathsWithMethod < Paths , "get" > ,
2520 Req extends FilterKeys < Paths [ Path ] , "get" > ,
26- > ( path : Path , swrConfigDefaults ?: SWRConfiguration ) {
27- // Define hook that is returned for consumers with typed options
28- // based on the given path
29- function useHook <
30- Options extends FetchOptions < Req > ,
31- Data extends ParseAsResponse <
32- FilterKeys < SuccessResponse < ResponseObjectMap < Req > > , MediaType > ,
33- Options
34- > ,
35- Error extends FilterKeys <
36- ErrorResponse < ResponseObjectMap < Req > > ,
37- MediaType
38- > ,
39- Config extends SWRConfiguration < Data , Error > ,
40- > ( fetchOptions : Options | null , swrConfig ?: Config ) {
41- type Key = [ typeof keyPrefix , Path , Options ] | null ;
42-
43- return useSWR < Data , Error , Key , Config > (
44- // SWR key is based on the path and fetch options
45- // keyPrefix keeps each API's cache separate in case there are path collisions
46- fetchOptions ? [ keyPrefix , path , fetchOptions ] : null ,
47- // Fetcher function
48- // @ts -expect-error - This functions correctly, but we don't need to fix its types
49- // types since we rely on the generics passed to useSWR instead
50- async ( [ _ , url , options ] ) => {
51- const res = await api . GET ( url , options ) ;
52- if ( res . error ) {
53- throw res . error ;
54- }
55- return res . data ;
56- } ,
57- // SWR config
58- {
59- ...swrConfigDefaults ,
60- ...swrConfig ,
61- } ,
62- ) ;
63- }
64-
65- useHook . getKey = ( fetchOptions : FetchOptions < Req > ) =>
66- [ keyPrefix , path , fetchOptions ] as [
67- typeof keyPrefix ,
68- Path ,
69- typeof fetchOptions ,
70- ] ;
21+ Options extends FetchOptions < Req > ,
22+ Data extends ParseAsResponse <
23+ FilterKeys < SuccessResponse < ResponseObjectMap < Req > > , MediaType > ,
24+ Options
25+ > ,
26+ Error extends FilterKeys < ErrorResponse < ResponseObjectMap < Req > > , MediaType > ,
27+ Config extends SWRConfiguration < Data , Error > ,
28+ > ( path : Path , options : Options | null , swrConfig ?: Config ) {
29+ type Key = [ typeof keyPrefix , Path , Options ] | null ;
7130
72- return useHook ;
73- } ;
74- }
31+ return useSWR < Data , Error , Key , Config > (
32+ // SWR key is based on the path and fetch options
33+ // keyPrefix keeps each API's cache separate in case there are path collisions
34+ options ? [ keyPrefix , path , options ] : null ,
35+ // Fetcher function
36+ // @ts -expect-error - This functions correctly, but we don't need to fix its types
37+ // types since we rely on the generics passed to useSWR instead
38+ async ( [ _ , url , init ] ) => {
39+ const res = await api . GET ( url , init ) ;
40+ if ( res . error ) {
41+ throw res . error ;
42+ }
43+ return res . data ;
44+ } ,
45+ // SWR config
46+ swrConfig ,
47+ ) ;
48+ }
7549
76- export function makeSWRHelper < Paths extends { } > (
77- api : ReturnType < typeof createClient < Paths > > ,
78- keyPrefix : string ,
79- ) {
80- function swrHelper <
50+ function useInfinite <
8151 Path extends PathsWithMethod < Paths , "get" > ,
8252 Req extends FilterKeys < Paths [ Path ] , "get" > ,
8353 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 ) ,
54+ Data extends ParseAsResponse <
55+ FilterKeys < SuccessResponse < ResponseObjectMap < Req > > , MediaType > ,
56+ Options
57+ > ,
58+ Error extends FilterKeys < ErrorResponse < ResponseObjectMap < Req > > , MediaType > ,
59+ Config extends SWRConfiguration < Data , Error > ,
8960 > (
9061 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- } ;
62+ getOptionsFn : SWRInfiniteKeyLoader < Data , Options | null > ,
63+ swrConfig ?: Config ,
64+ ) {
65+ type Key = [ typeof keyPrefix , Path , Options ] | null ;
11366
114- // @ts -expect-error - TODO: Come back to make the types sound
115- return [ key , fetcher ] as const ;
67+ return useSWRInfinite < Data , Error , SWRInfiniteKeyLoader < Data , Key > > (
68+ // SWR key is based on the path and fetch options
69+ // keyPrefix keeps each API's cache separate in case there are path collisions
70+ ( index , previousPageData ) => {
71+ const options = getOptionsFn ( index , previousPageData ) ;
72+ if ( options === null ) {
73+ return null ;
74+ }
75+ return [ keyPrefix , path , options ] as const ;
76+ } ,
77+ // Fetcher function
78+ // @ts -expect-error - This functions correctly, but we don't need to fix its types
79+ // types since we rely on the generics passed to useSWR instead
80+ async ( [ _ , url , init ] ) => {
81+ const res = await api . GET ( url , init ) ;
82+ if ( res . error ) {
83+ throw res . error ;
84+ }
85+ return res . data ;
86+ } ,
87+ // SWR config
88+ swrConfig ,
89+ ) ;
11690 }
11791
118- return swrHelper ;
92+ return {
93+ use,
94+ useInfinite,
95+ } ;
11996}
0 commit comments