@@ -37,19 +37,27 @@ export type QueryKey<
3737 Init = MaybeOptionalInit < Paths [ Path ] , Method > ,
3838> = Init extends undefined ? readonly [ Method , Path ] : readonly [ Method , Path , Init ] ;
3939
40- export type QueryOptionsFunction < Paths extends Record < string , Record < HttpMethod , { } > > , Media extends MediaType > = <
40+ export type MutationKey <
41+ Method extends HttpMethod ,
42+ Path ,
43+ > = readonly [ Method , Path ] ;
44+
45+ export type QueryOptionsFunction <
46+ Paths extends Record < string , Record < HttpMethod , { } > > ,
47+ Media extends MediaType ,
48+ > = <
4149 Method extends HttpMethod ,
4250 Path extends PathsWithMethod < Paths , Method > ,
4351 Init extends MaybeOptionalInit < Paths [ Path ] , Method > ,
4452 Response extends Required < FetchResponse < Paths [ Path ] [ Method ] , Init , Media > > , // note: Required is used to avoid repeating NonNullable in UseQuery types
4553 Options extends Omit <
4654 UseQueryOptions <
47- Response [ " data" ] ,
48- Response [ " error" ] ,
49- InferSelectReturnType < Response [ " data" ] , Options [ " select" ] > ,
55+ Response [ ' data' ] ,
56+ Response [ ' error' ] ,
57+ InferSelectReturnType < Response [ ' data' ] , Options [ ' select' ] > ,
5058 QueryKey < Paths , Method , Path >
5159 > ,
52- " queryKey" | " queryFn"
60+ ' queryKey' | ' queryFn'
5361 > ,
5462> (
5563 method : Method ,
@@ -60,61 +68,148 @@ export type QueryOptionsFunction<Paths extends Record<string, Record<HttpMethod,
6068) => NoInfer <
6169 Omit <
6270 UseQueryOptions <
63- Response [ " data" ] ,
64- Response [ " error" ] ,
65- InferSelectReturnType < Response [ " data" ] , Options [ " select" ] > ,
71+ Response [ ' data' ] ,
72+ Response [ ' error' ] ,
73+ InferSelectReturnType < Response [ ' data' ] , Options [ ' select' ] > ,
6674 QueryKey < Paths , Method , Path >
6775 > ,
68- " queryFn"
76+ ' queryFn'
6977 > & {
7078 queryFn : Exclude <
7179 UseQueryOptions <
72- Response [ " data" ] ,
73- Response [ " error" ] ,
74- InferSelectReturnType < Response [ " data" ] , Options [ " select" ] > ,
80+ Response [ ' data' ] ,
81+ Response [ ' error' ] ,
82+ InferSelectReturnType < Response [ ' data' ] , Options [ ' select' ] > ,
7583 QueryKey < Paths , Method , Path >
76- > [ " queryFn" ] ,
84+ > [ ' queryFn' ] ,
7785 SkipToken | undefined
7886 > ;
7987 }
8088> ;
8189
82- export type UseQueryMethod < Paths extends Record < string , Record < HttpMethod , { } > > , Media extends MediaType > = <
90+ export type MutationOptionsFunction <
91+ Paths extends Record < string , Record < HttpMethod , { } > > ,
92+ Media extends MediaType ,
93+ > = <
94+ Method extends HttpMethod ,
95+ Path extends PathsWithMethod < Paths , Method > ,
96+ Init extends MaybeOptionalInit < Paths [ Path ] , Method > ,
97+ Response extends Required < FetchResponse < Paths [ Path ] [ Method ] , Init , Media > > ,
98+ Options extends Omit <
99+ UseMutationOptions < Response [ 'data' ] , Response [ 'error' ] , Init > ,
100+ 'mutationKey' | 'mutationFn'
101+ > ,
102+ > (
103+ method : Method ,
104+ path : Path ,
105+ options ?: Options
106+ ) => NoInfer <
107+ Omit <
108+ UseMutationOptions < Response [ 'data' ] , Response [ 'error' ] , Init > ,
109+ 'mutationFn'
110+ > & {
111+ mutationFn : Exclude <
112+ UseMutationOptions < Response [ 'data' ] , Response [ 'error' ] , Init > [ 'mutationFn' ] ,
113+ undefined
114+ > ;
115+ }
116+ > ;
117+
118+ // Helper type to infer TPageParam type
119+ type InferPageParamType < T > = T extends { initialPageParam : infer P } ? P : unknown ;
120+
121+ export type InfiniteQueryOptionsFunction <
122+ Paths extends Record < string , Record < HttpMethod , { } > > ,
123+ Media extends MediaType ,
124+ > = <
125+ Method extends HttpMethod ,
126+ Path extends PathsWithMethod < Paths , Method > ,
127+ Init extends MaybeOptionalInit < Paths [ Path ] , Method > ,
128+ Response extends Required < FetchResponse < Paths [ Path ] [ Method ] , Init , Media > > ,
129+ Options extends Omit <
130+ UseInfiniteQueryOptions <
131+ Response [ 'data' ] ,
132+ Response [ 'error' ] ,
133+ InferSelectReturnType < InfiniteData < Response [ 'data' ] > , Options [ 'select' ] > ,
134+ QueryKey < Paths , Method , Path > ,
135+ InferPageParamType < Options >
136+ > ,
137+ 'queryKey' | 'queryFn'
138+ > & {
139+ pageParamName ?: string ;
140+ initialPageParam : InferPageParamType < Options > ;
141+ } ,
142+ > (
143+ method : Method ,
144+ path : Path ,
145+ init : InitWithUnknowns < Init > ,
146+ options : Options
147+ ) => NoInfer <
148+ Omit <
149+ UseInfiniteQueryOptions <
150+ Response [ 'data' ] ,
151+ Response [ 'error' ] ,
152+ InferSelectReturnType < InfiniteData < Response [ 'data' ] > , Options [ 'select' ] > ,
153+ QueryKey < Paths , Method , Path > ,
154+ InferPageParamType < Options >
155+ > ,
156+ 'queryFn'
157+ > & {
158+ queryFn : Exclude <
159+ UseInfiniteQueryOptions <
160+ Response [ 'data' ] ,
161+ Response [ 'error' ] ,
162+ InferSelectReturnType < InfiniteData < Response [ 'data' ] > , Options [ 'select' ] > ,
163+ QueryKey < Paths , Method , Path > ,
164+ InferPageParamType < Options >
165+ > [ 'queryFn' ] ,
166+ SkipToken | undefined
167+ > ;
168+ }
169+ > ;
170+
171+ export type UseQueryMethod <
172+ Paths extends Record < string , Record < HttpMethod , { } > > ,
173+ Media extends MediaType ,
174+ > = <
83175 Method extends HttpMethod ,
84176 Path extends PathsWithMethod < Paths , Method > ,
85177 Init extends MaybeOptionalInit < Paths [ Path ] , Method > ,
86178 Response extends Required < FetchResponse < Paths [ Path ] [ Method ] , Init , Media > > , // note: Required is used to avoid repeating NonNullable in UseQuery types
87179 Options extends Omit <
88180 UseQueryOptions <
89- Response [ " data" ] ,
90- Response [ " error" ] ,
91- InferSelectReturnType < Response [ " data" ] , Options [ " select" ] > ,
181+ Response [ ' data' ] ,
182+ Response [ ' error' ] ,
183+ InferSelectReturnType < Response [ ' data' ] , Options [ ' select' ] > ,
92184 QueryKey < Paths , Method , Path >
93185 > ,
94- " queryKey" | " queryFn"
186+ ' queryKey' | ' queryFn'
95187 > ,
96188> (
97189 method : Method ,
98190 url : Path ,
99191 ...[ init , options , queryClient ] : RequiredKeysOf < Init > extends never
100192 ? [ InitWithUnknowns < Init > ?, Options ?, QueryClient ?]
101193 : [ InitWithUnknowns < Init > , Options ?, QueryClient ?]
102- ) => UseQueryResult < InferSelectReturnType < Response [ " data" ] , Options [ " select" ] > , Response [ " error" ] > ;
194+ ) => UseQueryResult < InferSelectReturnType < Response [ ' data' ] , Options [ ' select' ] > , Response [ ' error' ] > ;
103195
104- export type UseInfiniteQueryMethod < Paths extends Record < string , Record < HttpMethod , { } > > , Media extends MediaType > = <
196+ export type UseInfiniteQueryMethod <
197+ Paths extends Record < string , Record < HttpMethod , { } > > ,
198+ Media extends MediaType ,
199+ > = <
105200 Method extends HttpMethod ,
106201 Path extends PathsWithMethod < Paths , Method > ,
107202 Init extends MaybeOptionalInit < Paths [ Path ] , Method > ,
108203 Response extends Required < FetchResponse < Paths [ Path ] [ Method ] , Init , Media > > ,
109204 Options extends Omit <
110205 UseInfiniteQueryOptions <
111- Response [ " data" ] ,
112- Response [ " error" ] ,
113- InferSelectReturnType < InfiniteData < Response [ " data" ] > , Options [ " select" ] > ,
206+ Response [ ' data' ] ,
207+ Response [ ' error' ] ,
208+ InferSelectReturnType < InfiniteData < Response [ ' data' ] > , Options [ ' select' ] > ,
114209 QueryKey < Paths , Method , Path > ,
115210 unknown
116211 > ,
117- " queryKey" | " queryFn"
212+ ' queryKey' | ' queryFn'
118213 > & {
119214 pageParamName ?: string ;
120215 } ,
@@ -123,49 +218,62 @@ export type UseInfiniteQueryMethod<Paths extends Record<string, Record<HttpMetho
123218 url : Path ,
124219 init : InitWithUnknowns < Init > ,
125220 options : Options ,
126- queryClient ?: QueryClient ,
221+ queryClient ?: QueryClient
127222) => UseInfiniteQueryResult <
128- InferSelectReturnType < InfiniteData < Response [ " data" ] > , Options [ " select" ] > ,
129- Response [ " error" ]
223+ InferSelectReturnType < InfiniteData < Response [ ' data' ] > , Options [ ' select' ] > ,
224+ Response [ ' error' ]
130225> ;
131226
132- export type UseSuspenseQueryMethod < Paths extends Record < string , Record < HttpMethod , { } > > , Media extends MediaType > = <
227+ export type UseSuspenseQueryMethod <
228+ Paths extends Record < string , Record < HttpMethod , { } > > ,
229+ Media extends MediaType ,
230+ > = <
133231 Method extends HttpMethod ,
134232 Path extends PathsWithMethod < Paths , Method > ,
135233 Init extends MaybeOptionalInit < Paths [ Path ] , Method > ,
136234 Response extends Required < FetchResponse < Paths [ Path ] [ Method ] , Init , Media > > , // note: Required is used to avoid repeating NonNullable in UseQuery types
137235 Options extends Omit <
138236 UseSuspenseQueryOptions <
139- Response [ " data" ] ,
140- Response [ " error" ] ,
141- InferSelectReturnType < Response [ " data" ] , Options [ " select" ] > ,
237+ Response [ ' data' ] ,
238+ Response [ ' error' ] ,
239+ InferSelectReturnType < Response [ ' data' ] , Options [ ' select' ] > ,
142240 QueryKey < Paths , Method , Path >
143241 > ,
144- " queryKey" | " queryFn"
242+ ' queryKey' | ' queryFn'
145243 > ,
146244> (
147245 method : Method ,
148246 url : Path ,
149247 ...[ init , options , queryClient ] : RequiredKeysOf < Init > extends never
150248 ? [ InitWithUnknowns < Init > ?, Options ?, QueryClient ?]
151249 : [ InitWithUnknowns < Init > , Options ?, QueryClient ?]
152- ) => UseSuspenseQueryResult < InferSelectReturnType < Response [ "data" ] , Options [ "select" ] > , Response [ "error" ] > ;
250+ ) => UseSuspenseQueryResult <
251+ InferSelectReturnType < Response [ 'data' ] , Options [ 'select' ] > ,
252+ Response [ 'error' ]
253+ > ;
153254
154- export type UseMutationMethod < Paths extends Record < string , Record < HttpMethod , { } > > , Media extends MediaType > = <
255+ export type UseMutationMethod <
256+ Paths extends Record < string , Record < HttpMethod , { } > > ,
257+ Media extends MediaType ,
258+ > = <
155259 Method extends HttpMethod ,
156260 Path extends PathsWithMethod < Paths , Method > ,
157261 Init extends MaybeOptionalInit < Paths [ Path ] , Method > ,
158262 Response extends Required < FetchResponse < Paths [ Path ] [ Method ] , Init , Media > > , // note: Required is used to avoid repeating NonNullable in UseQuery types
159- Options extends Omit < UseMutationOptions < Response [ "data" ] , Response [ "error" ] , Init > , "mutationKey" | "mutationFn" > ,
263+ Options extends Omit <
264+ UseMutationOptions < Response [ 'data' ] , Response [ 'error' ] , Init > ,
265+ 'mutationKey' | 'mutationFn'
266+ > ,
160267> (
161268 method : Method ,
162269 url : Path ,
163270 options ?: Options ,
164- queryClient ?: QueryClient ,
165- ) => UseMutationResult < Response [ " data" ] , Response [ " error" ] , Init > ;
271+ queryClient ?: QueryClient
272+ ) => UseMutationResult < Response [ ' data' ] , Response [ ' error' ] , Init > ;
166273
167274export interface OpenapiQueryClient < Paths extends { } , Media extends MediaType = MediaType > {
168275 queryOptions : QueryOptionsFunction < Paths , Media > ;
276+ mutationOptions : MutationOptionsFunction < Paths , Media > ;
169277 useQuery : UseQueryMethod < Paths , Media > ;
170278 useSuspenseQuery : UseSuspenseQueryMethod < Paths , Media > ;
171279 useInfiniteQuery : UseInfiniteQueryMethod < Paths , Media > ;
@@ -179,13 +287,17 @@ export type MethodResponse<
179287 ? PathsWithMethod < Paths , Method >
180288 : never ,
181289 Options = object ,
182- > = CreatedClient extends OpenapiQueryClient < infer Paths extends { [ key : string ] : any } , infer Media extends MediaType >
183- ? NonNullable < FetchResponse < Paths [ Path ] [ Method ] , Options , Media > [ "data" ] >
184- : never ;
290+ > =
291+ CreatedClient extends OpenapiQueryClient <
292+ infer Paths extends { [ key : string ] : any } ,
293+ infer Media extends MediaType
294+ >
295+ ? NonNullable < FetchResponse < Paths [ Path ] [ Method ] , Options , Media > [ 'data' ] >
296+ : never ;
185297
186298// TODO: Add the ability to bring queryClient as argument
187299export default function createClient < Paths extends { } , Media extends MediaType = MediaType > (
188- client : FetchClient < Paths , Media > ,
300+ client : FetchClient < Paths , Media >
189301) : OpenapiQueryClient < Paths , Media > {
190302 const queryFn = async < Method extends HttpMethod , Path extends PathsWithMethod < Paths , Method > > ( {
191303 queryKey : [ method , path , init ] ,
@@ -197,27 +309,54 @@ export default function createClient<Paths extends {}, Media extends MediaType =
197309 if ( error ) {
198310 throw error ;
199311 }
200- if ( response . status === 204 || response . headers . get ( " Content-Length" ) === "0" ) {
312+ if ( response . status === 204 || response . headers . get ( ' Content-Length' ) === '0' ) {
201313 return data ?? null ;
202314 }
203315
204316 return data ;
205317 } ;
206318
319+ const createMutationFn = <
320+ Method extends HttpMethod ,
321+ Path extends PathsWithMethod < Paths , Method >
322+ > (
323+ method : Method ,
324+ path : Path
325+ ) => {
326+ return async ( init : any ) => {
327+ const mth = method . toUpperCase ( ) as Uppercase < typeof method > ;
328+ const fn = client [ mth ] as ClientMethod < Paths , typeof method , Media > ;
329+ const { data, error } = await fn ( path , init as any ) ;
330+ if ( error ) {
331+ throw error ;
332+ }
333+
334+ return data as Exclude < typeof data , undefined > ;
335+ } ;
336+ } ;
337+
207338 const queryOptions : QueryOptionsFunction < Paths , Media > = ( method , path , ...[ init , options ] ) => ( {
208- queryKey : ( init === undefined ? ( [ method , path ] as const ) : ( [ method , path , init ] as const ) ) as QueryKey <
209- Paths ,
210- typeof method ,
211- typeof path
212- > ,
339+ queryKey : ( init === undefined
340+ ? ( [ method , path ] as const )
341+ : ( [ method , path , init ] as const ) ) as QueryKey < Paths , typeof method , typeof path > ,
213342 queryFn,
214343 ...options ,
215344 } ) ;
216345
346+ const mutationOptions : MutationOptionsFunction < Paths , Media > = ( method , path , options ) => ( {
347+ mutationKey : [ method , path ] as MutationKey < typeof method , typeof path > ,
348+ mutationFn : createMutationFn ( method , path ) ,
349+ ...options ,
350+ } ) ;
351+
217352 return {
218353 queryOptions,
354+ mutationOptions,
219355 useQuery : ( method , path , ...[ init , options , queryClient ] ) =>
220- useQuery ( queryOptions ( method , path , init as InitWithUnknowns < typeof init > , options ) , queryClient ) ,
356+ useQuery (
357+ queryOptions ( method , path , init as InitWithUnknowns < typeof init > , options ) ,
358+ queryClient
359+ ) ,
221360 useSuspenseQuery : ( method , path , ...[ init , options , queryClient ] ) =>
222361 useSuspenseQuery ( queryOptions ( method , path , init as InitWithUnknowns < typeof init > , options ) , queryClient ) ,
223362 useInfiniteQuery : ( method , path , init , options , queryClient ) => {
@@ -256,19 +395,10 @@ export default function createClient<Paths extends {}, Media extends MediaType =
256395 useMutation (
257396 {
258397 mutationKey : [ method , path ] ,
259- mutationFn : async ( init ) => {
260- const mth = method . toUpperCase ( ) as Uppercase < typeof method > ;
261- const fn = client [ mth ] as ClientMethod < Paths , typeof method , Media > ;
262- const { data, error } = await fn ( path , init as InitWithUnknowns < typeof init > ) ;
263- if ( error ) {
264- throw error ;
265- }
266-
267- return data as Exclude < typeof data , undefined > ;
268- } ,
398+ mutationFn : createMutationFn ( method , path ) ,
269399 ...options ,
270400 } ,
271- queryClient ,
401+ queryClient
272402 ) ,
273403 } ;
274- }
404+ }
0 commit comments