|
1 |
| -import { createContext, useContext } from 'react'; |
2 |
| -import { |
3 |
| - useMutation, |
4 |
| - UseMutationOptions, |
5 |
| - UseMutationResult, |
6 |
| - useQuery, |
7 |
| - UseQueryOptions, |
8 |
| - UseQueryResult, |
9 |
| -} from '@tanstack/react-query'; |
10 |
| - |
11 |
| -// Note on generic types: |
12 |
| -// - I represents the input type for the service method, or the request. |
13 |
| -// - O represents the output type for the service method, or the response. |
14 |
| -// - M represents the service method itself. |
15 |
| -// - C represents a context. |
16 |
| - |
17 |
| -// Represents the static methods from the generated service client. |
18 |
| -export type ServiceMethod<I, O> = (req: I, initReq: RequestInitWithPathPrefix) => Promise<O>; |
19 |
| - |
20 |
| -// Extends the standard `RequestInit` accepted by `fetch()` with a `pathPrefix` |
21 |
| -// property that is used by the generated gateway methods to prefix the URL. |
22 |
| -export interface RequestInitWithPathPrefix extends RequestInit { |
23 |
| - pathPrefix?: string; |
24 |
| -} |
25 |
| - |
26 |
| -// Represents an error returned by calling a service method. |
27 |
| -export type ServiceError = Error | ErrorResponse; |
28 |
| - |
29 |
| -// Represents a function that handles errors returned from a service method. |
30 |
| -export type OnErrorHandler<O> = (error: Error | ErrorResponse) => O | null; |
31 |
| - |
32 |
| -// Represents the standard error response returned from the server. |
33 |
| -export interface ErrorResponse { |
34 |
| - // Non-standard, but a useful customization. Could be typed as `Code` from |
35 |
| - // google/rpc/code.pb. |
36 |
| - codeName?: string; |
37 |
| - code: number; |
38 |
| - message: string; |
39 |
| - details: unknown[]; |
40 |
| -} |
41 |
| - |
42 |
| -// Represents the `useServiceQuery` options. This is the same as |
43 |
| -// `UseQueryOptions` except that `queryFn` is handled internally, so must not |
44 |
| -// be provided. Additionally an `onError` handler can be provided to provide |
45 |
| -// customized error handling. |
46 |
| -type UseServiceQueryOptions<M extends ServiceMethod<Parameters<M>[0], ReturnType<M>>> = Omit< |
47 |
| - UseQueryOptions<Awaited<ReturnType<M>>, ServiceError>, |
48 |
| - 'queryFn' |
49 |
| -> & { |
50 |
| - onError?: OnErrorHandler<ReturnType<M>>; |
51 |
| -}; |
52 |
| - |
53 |
| -// Represents the `useServiceMutation` options. This is the same as |
54 |
| -// `UseMutationOptions` except that `mutationFn` is handled internally, so must |
55 |
| -// not be provided. |
56 |
| -type UseServiceMutationOptions< |
57 |
| - M extends ServiceMethod<Parameters<M>[0], ReturnType<M>>, |
58 |
| - C = unknown, |
59 |
| -> = Omit< |
60 |
| - UseMutationOptions<Awaited<ReturnType<M>>, ServiceError, Parameters<M>[0], C>, |
61 |
| - 'mutationFn' |
62 |
| ->; |
63 |
| - |
64 |
| -// Wraps `useQuery` from react-query, pulling request configuration from context |
65 |
| -// and making it easier to call generated service clients. |
66 |
| -export function useServiceQuery<M extends ServiceMethod<Parameters<M>[0], Awaited<ReturnType<M>>>>( |
67 |
| - method: M, |
68 |
| - req: Parameters<M>[0], |
69 |
| - options?: UseServiceQueryOptions<M>, |
70 |
| -): UseQueryResult<Awaited<ReturnType<M>>, ServiceError> { |
71 |
| - const reqCtx = useContext(ServiceContext); |
72 |
| - return useQuery(queryOptions(method, req, reqCtx, options)); |
73 |
| -} |
74 |
| - |
75 |
| -// Returns the options object for `useQuery` based on the service method. Can |
76 |
| -// be used with `useSuspenseQuery` for data loading. |
77 |
| -export function queryOptions<M extends ServiceMethod<Parameters<M>[0], Awaited<ReturnType<M>>>>( |
78 |
| - method: M, |
79 |
| - req: Parameters<M>[0], |
80 |
| - reqInit?: RequestInitWithPathPrefix, |
81 |
| - options?: UseServiceQueryOptions<M>, |
82 |
| -): UseQueryOptions<Awaited<ReturnType<M>>, ServiceError> { |
83 |
| - return { |
84 |
| - ...options!, |
85 |
| - queryFn: () => { |
86 |
| - const resp = method(req, { |
87 |
| - ...reqInit, |
88 |
| - headers: { |
89 |
| - 'Content-Type': 'application/json', |
90 |
| - ...reqInit?.headers, |
91 |
| - }, |
92 |
| - }); |
93 |
| - if (options?.onError) { |
94 |
| - return resp.catch(options.onError) as Awaited<ReturnType<M>>; |
95 |
| - } |
96 |
| - return resp; |
97 |
| - }, |
98 |
| - }; |
99 |
| -} |
100 |
| - |
101 |
| -// Wraps `useMutation` from react-query, pulling request configuration from |
102 |
| -// context and making it easier to call generated service clients. |
103 |
| -export function useServiceMutation< |
104 |
| - M extends ServiceMethod<Parameters<M>[0], Awaited<ReturnType<M>>>, |
105 |
| - C = unknown, |
106 |
| ->( |
107 |
| - method: M, |
108 |
| - options?: UseServiceMutationOptions<M, C>, |
109 |
| -): UseMutationResult<Awaited<ReturnType<M>>, ServiceError, Partial<Parameters<M>[0]>, C> { |
110 |
| - const reqCtx = useContext(ServiceContext); |
111 |
| - return useMutation({ |
112 |
| - ...options!, |
113 |
| - mutationFn: (req) => { |
114 |
| - const resp = method(req, { |
115 |
| - ...reqCtx, |
116 |
| - headers: { |
117 |
| - 'Content-Type': 'application/json', |
118 |
| - ...reqCtx.headers, |
119 |
| - }, |
120 |
| - }); |
121 |
| - return resp; |
122 |
| - }, |
123 |
| - }); |
124 |
| -} |
125 |
| - |
126 |
| -// Represents the context object for injecting request options. |
127 |
| -// |
128 |
| -// Example: |
129 |
| -// |
130 |
| -// <ServiceContext.Provider value={options}> |
131 |
| -// {children} |
132 |
| -// </ServiceContext.Provider> |
133 |
| -// |
134 |
| -// Where options can include `pathPrefix` or any of the options in `RequestInit`. |
135 |
| -// |
136 |
| -// https://microsoft.github.io/PowerBI-JavaScript/interfaces/_node_modules_typedoc_node_modules_typescript_lib_lib_dom_d_.requestinit.html |
137 |
| -export const ServiceContext = createContext({} as RequestInitWithPathPrefix); |
138 |
| - |
139 |
| -// Returns true if the error is an error response. |
140 |
| -export function isErrorResponse(error: Error | ErrorResponse): error is ErrorResponse { |
141 |
| - return (error as ErrorResponse).code !== undefined; |
142 |
| -} |
| 1 | +export * from './types'; |
| 2 | +export * from './useServiceMutation'; |
| 3 | +export * from './useServiceQuery'; |
| 4 | +export * from './serviceContext'; |
0 commit comments