Skip to content

Commit 5ac589c

Browse files
committed
Break up index.ts into separate files
1 parent d9dc207 commit 5ac589c

File tree

5 files changed

+159
-142
lines changed

5 files changed

+159
-142
lines changed

src/index.ts

Lines changed: 4 additions & 142 deletions
Original file line numberDiff line numberDiff line change
@@ -1,142 +1,4 @@
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';

src/serviceContext.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { createContext, useContext } from 'react';
2+
import { RequestInitWithPathPrefix } from './types';
3+
4+
// Represents the context object for injecting request options.
5+
//
6+
// Example:
7+
//
8+
// <ServiceContext.Provider value={options}>
9+
// {children}
10+
// </ServiceContext.Provider>
11+
//
12+
// Where options can include `pathPrefix` or any of the options in `RequestInit`.
13+
//
14+
// https://microsoft.github.io/PowerBI-JavaScript/interfaces/_node_modules_typedoc_node_modules_typescript_lib_lib_dom_d_.requestinit.html
15+
export const ServiceContext = createContext({} as RequestInitWithPathPrefix);
16+
17+
// useServiceContext returns the current request options from the context.
18+
export const useServiceContext = () => {
19+
return useContext(ServiceContext);
20+
};

src/types.ts

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
// Note on generic types:
2+
// - I represents the input type for the service method, or the request.
3+
// - O represents the output type for the service method, or the response.
4+
// - M represents the service method itself.
5+
// - C represents a context.
6+
7+
import { UseMutationOptions, UseQueryOptions } from '@tanstack/react-query';
8+
9+
// Represents the static methods from the generated service client.
10+
export type ServiceMethod<I, O> = (req: I, initReq: RequestInitWithPathPrefix) => Promise<O>;
11+
12+
// Extends the standard `RequestInit` accepted by `fetch()` with a `pathPrefix`
13+
// property that is used by the generated gateway methods to prefix the URL.
14+
export interface RequestInitWithPathPrefix extends RequestInit {
15+
pathPrefix?: string;
16+
}
17+
18+
// Represents an error returned by calling a service method.
19+
export type ServiceError = Error | ErrorResponse;
20+
21+
// Represents a function that handles errors returned from a service method.
22+
export type OnErrorHandler<O> = (error: Error | ErrorResponse) => O | null;
23+
24+
// Represents the standard error response returned from the server.
25+
export interface ErrorResponse {
26+
// Non-standard, but a useful customization. Could be typed as `Code` from
27+
// google/rpc/code.pb.
28+
codeName?: string;
29+
code: number;
30+
message: string;
31+
details: unknown[];
32+
}
33+
34+
// Represents the `useServiceQuery` options. This is the same as
35+
// `UseQueryOptions` except that `queryFn` is handled internally, so must not
36+
// be provided. Additionally an `onError` handler can be provided to provide
37+
// customized error handling.
38+
export type UseServiceQueryOptions<M extends ServiceMethod<Parameters<M>[0], ReturnType<M>>> = Omit<
39+
UseQueryOptions<Awaited<ReturnType<M>>, ServiceError>,
40+
'queryFn'
41+
> & {
42+
onError?: OnErrorHandler<ReturnType<M>>;
43+
};
44+
45+
// Represents the `useServiceMutation` options. This is the same as
46+
// `UseMutationOptions` except that `mutationFn` is handled internally, so must
47+
// not be provided.
48+
export type UseServiceMutationOptions<
49+
M extends ServiceMethod<Parameters<M>[0], ReturnType<M>>,
50+
C = unknown,
51+
> = Omit<
52+
UseMutationOptions<Awaited<ReturnType<M>>, ServiceError, Parameters<M>[0], C>,
53+
'mutationFn'
54+
>;
55+
56+
// Returns true if the error is an error response.
57+
export function isErrorResponse(error: Error | ErrorResponse): error is ErrorResponse {
58+
return (error as ErrorResponse).code !== undefined;
59+
}

src/useServiceMutation.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// Wraps `useMutation` from react-query, pulling request configuration from
2+
3+
import { UseMutationResult, useMutation } from '@tanstack/react-query';
4+
import { useContext } from 'react';
5+
import { ServiceContext } from '.';
6+
import { ServiceMethod, UseServiceMutationOptions, ServiceError } from './types';
7+
8+
// context and making it easier to call generated service clients.
9+
export function useServiceMutation<
10+
M extends ServiceMethod<Parameters<M>[0], Awaited<ReturnType<M>>>,
11+
C = unknown,
12+
>(
13+
method: M,
14+
options?: UseServiceMutationOptions<M, C>,
15+
): UseMutationResult<Awaited<ReturnType<M>>, ServiceError, Partial<Parameters<M>[0]>, C> {
16+
const reqCtx = useContext(ServiceContext);
17+
return useMutation({
18+
...options!,
19+
mutationFn: (req) => {
20+
const resp = method(req, {
21+
...reqCtx,
22+
headers: {
23+
'Content-Type': 'application/json',
24+
...reqCtx.headers,
25+
},
26+
});
27+
return resp;
28+
},
29+
});
30+
}

src/useServiceQuery.ts

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import { UseQueryResult, useQuery, UseQueryOptions } from '@tanstack/react-query';
2+
import { useContext } from 'react';
3+
import { ServiceContext } from '.';
4+
import {
5+
RequestInitWithPathPrefix,
6+
ServiceError,
7+
ServiceMethod,
8+
UseServiceQueryOptions,
9+
} from './types';
10+
11+
// Wraps `useQuery` from react-query, pulling request configuration from context
12+
// and making it easier to call generated service clients.
13+
export function useServiceQuery<M extends ServiceMethod<Parameters<M>[0], Awaited<ReturnType<M>>>>(
14+
method: M,
15+
req: Parameters<M>[0],
16+
options?: UseServiceQueryOptions<M>,
17+
): UseQueryResult<Awaited<ReturnType<M>>, ServiceError> {
18+
const reqCtx = useContext(ServiceContext);
19+
return useQuery(queryOptions(method, req, reqCtx, options));
20+
}
21+
22+
// Returns the options object for `useQuery` based on the service method. Can
23+
// be used with `useSuspenseQuery` for data loading.
24+
export function queryOptions<M extends ServiceMethod<Parameters<M>[0], Awaited<ReturnType<M>>>>(
25+
method: M,
26+
req: Parameters<M>[0],
27+
reqInit?: RequestInitWithPathPrefix,
28+
options?: UseServiceQueryOptions<M>,
29+
): UseQueryOptions<Awaited<ReturnType<M>>, ServiceError> {
30+
return {
31+
...options!,
32+
queryFn: () => {
33+
const resp = method(req, {
34+
...reqInit,
35+
headers: {
36+
'Content-Type': 'application/json',
37+
...reqInit?.headers,
38+
},
39+
});
40+
if (options?.onError) {
41+
return resp.catch(options.onError) as Awaited<ReturnType<M>>;
42+
}
43+
return resp;
44+
},
45+
};
46+
}

0 commit comments

Comments
 (0)