openapi-typesafe-react-query 1.0.0-rc.3 → 1.0.0-rc.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +398 -0
- package/README.md +10 -0
- package/dist/index.cjs +24 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +54 -14
- package/dist/index.d.mts +55 -15
- package/dist/index.d.ts +55 -15
- package/dist/index.mjs +20 -2
- package/dist/index.mjs.map +1 -1
- package/package.json +7 -9
- package/src/index.ts +106 -30
package/dist/index.d.cts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { UseQueryOptions, DataTag, SkipToken, QueryClient, UseQueryResult, UseSuspenseQueryOptions, UseSuspenseQueryResult, UseInfiniteQueryOptions, InfiniteData, UseInfiniteQueryResult, UseMutationOptions, UseMutationResult } from '@tanstack/react-query';
|
|
1
|
+
import { UseQueryOptions, DefaultError, DataTag, SkipToken, QueryClient, UseQueryResult, UseSuspenseQueryOptions, UseSuspenseQueryResult, UseInfiniteQueryOptions, InfiniteData, UseInfiniteQueryResult, UseMutationOptions, UseMutationResult } from '@tanstack/react-query';
|
|
2
2
|
import { MaybeOptionalInit, FetchResponse, PathOperation, Client } from 'openapi-typesafe-fetch';
|
|
3
|
-
import { HttpMethod, PathsWithMethod, MediaType, RequiredKeysOf } from 'openapi-typesafe-helpers';
|
|
3
|
+
import { HttpMethod, PathsWithMethod, MediaType, RequiredKeysOf } from 'openapi-typesafe-fetch/helpers';
|
|
4
4
|
|
|
5
5
|
type InferSelectReturnType<TData, TSelect> = TSelect extends (data: TData) => infer R ? R : TData;
|
|
6
6
|
/**
|
|
@@ -8,6 +8,40 @@ type InferSelectReturnType<TData, TSelect> = TSelect extends (data: TData) => in
|
|
|
8
8
|
* `null` in the query, as `queryFn` resolves it (upstream #2234, #2464).
|
|
9
9
|
*/
|
|
10
10
|
type QueryData<Data> = undefined extends Data ? Exclude<Data, undefined> | null : Data;
|
|
11
|
+
/**
|
|
12
|
+
* What the hooks throw when a request fails and the response has no error body: a non-OK status
|
|
13
|
+
* with an empty body, a JSON `null` body, or one whose operation declares no content for it. The
|
|
14
|
+
* fetch client gives `error: undefined` (or `null`) then; throwing that left `error` empty in
|
|
15
|
+
* TanStack Query while its type said there was an error body. Tell it apart with
|
|
16
|
+
* `isResponseError(error)`: `error instanceof Error` also matches a network or parse error. The
|
|
17
|
+
* message names the status, not the URL, which can carry secrets.
|
|
18
|
+
*/
|
|
19
|
+
interface ResponseError extends Error {
|
|
20
|
+
readonly name: "ResponseError";
|
|
21
|
+
/** The response that failed. */
|
|
22
|
+
readonly response: Response;
|
|
23
|
+
/** Its HTTP status, as `response.status`. */
|
|
24
|
+
readonly status: number;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* The error of a hook: the error body of a failed response, a `ResponseError` when it has none, or
|
|
28
|
+
* what the request threw before there was a response to read: a network error (`TypeError`), an
|
|
29
|
+
* abort, a body that is not JSON (`SyntaxError`) or a middleware error. TanStack Query types that
|
|
30
|
+
* last part as `DefaultError` (`Error` unless `Register` says otherwise; a registered `unknown`
|
|
31
|
+
* makes the whole type `unknown`, as for TanStack's own hooks). `undefined` and `null` are left
|
|
32
|
+
* out: a failed response without an error body throws a `ResponseError`.
|
|
33
|
+
*/
|
|
34
|
+
type QueryError<ErrorBody> = Exclude<ErrorBody, undefined | null> | ResponseError | DefaultError;
|
|
35
|
+
/**
|
|
36
|
+
* An object whose `queryKey` is tagged with the query's data and error types: the type that
|
|
37
|
+
* TanStack Query 5.102 exports as `QueryKeyWithDataTag`, for the whole peer range. A named object
|
|
38
|
+
* type, so the declarations of an exported `queryOptions` result print it by name. Spelled out,
|
|
39
|
+
* the tag prints TanStack's `dataTagSymbol` keys, which a declaration file cannot import, and
|
|
40
|
+
* the library's users get TS2304, or `any` cached data with `skipLibCheck`.
|
|
41
|
+
*/
|
|
42
|
+
type QueryKeyWithDataTag<Key, Data, Error> = {
|
|
43
|
+
queryKey: DataTag<Key, Data, Error>;
|
|
44
|
+
};
|
|
11
45
|
type InitWithUnknowns<Init> = Init & {
|
|
12
46
|
[key: string]: unknown;
|
|
13
47
|
};
|
|
@@ -24,16 +58,15 @@ type QueryKey<Paths extends {}, Method extends HttpMethod, Path extends PathsWit
|
|
|
24
58
|
/**
|
|
25
59
|
* The last element of an infinite query's key. `useQuery` and `useInfiniteQuery` cache different
|
|
26
60
|
* data (`TData` and `InfiniteData<TData>`), so the same request must not share one key (upstream
|
|
27
|
-
* #2184, ADR-022). A prefix such as `[method, path]` still matches both. Not exported:
|
|
28
|
-
*
|
|
61
|
+
* #2184, ADR-022). A prefix such as `[method, path]` still matches both. Not exported: it is not
|
|
62
|
+
* needed outside the package, and a named export is public API; `InfiniteQueryKey` types the key.
|
|
29
63
|
*/
|
|
30
64
|
declare const INFINITE_QUERY_KEY_MARKER = "infinite";
|
|
31
65
|
type InfiniteQueryKey<Paths extends {}, Method extends HttpMethod, Path extends PathsWithMethod<Paths, Method>> = readonly [...QueryKey<Paths, Method, Path>, typeof INFINITE_QUERY_KEY_MARKER];
|
|
32
|
-
type QueryOptionsFunction<Paths extends {}, Media extends MediaType> = <Method extends HttpMethod, Path extends PathsWithMethod<Paths, Method>, Init extends MaybeOptionalInit<Paths[Path], Method>, Response extends Required<FetchResponse<PathOperation<Paths, Path, Method>, Init, Media>>, Options extends Omit<UseQueryOptions<QueryData<Response["data"]>, Response["error"]
|
|
33
|
-
|
|
34
|
-
queryFn: Exclude<UseQueryOptions<QueryData<Response["data"]>, Response["error"], InferSelectReturnType<QueryData<Response["data"]>, Options["select"]>, QueryKey<Paths, Method, Path>>["queryFn"], SkipToken | undefined>;
|
|
66
|
+
type QueryOptionsFunction<Paths extends {}, Media extends MediaType> = <Method extends HttpMethod, Path extends PathsWithMethod<Paths, Method>, Init extends MaybeOptionalInit<Paths[Path], Method>, Response extends Required<FetchResponse<PathOperation<Paths, Path, Method>, Init, Media>>, Options extends Omit<UseQueryOptions<QueryData<Response["data"]>, QueryError<Response["error"]>, InferSelectReturnType<QueryData<Response["data"]>, Options["select"]>, QueryKey<Paths, Method, Path>>, "queryKey" | "queryFn">>(method: Method, path: Path, ...[init, options]: InitArguments<Init, [Options?]>) => NoInfer<Omit<UseQueryOptions<QueryData<Response["data"]>, QueryError<Response["error"]>, InferSelectReturnType<QueryData<Response["data"]>, Options["select"]>, QueryKey<Paths, Method, Path>>, "queryFn" | "queryKey"> & QueryKeyWithDataTag<QueryKey<Paths, Method, Path>, QueryData<Response["data"]>, QueryError<Response["error"]>> & {
|
|
67
|
+
queryFn: Exclude<UseQueryOptions<QueryData<Response["data"]>, QueryError<Response["error"]>, InferSelectReturnType<QueryData<Response["data"]>, Options["select"]>, QueryKey<Paths, Method, Path>>["queryFn"], SkipToken | undefined>;
|
|
35
68
|
}>;
|
|
36
|
-
type UseQueryMethod<Paths extends {}, Media extends MediaType> = <Method extends HttpMethod, Path extends PathsWithMethod<Paths, Method>, Init extends MaybeOptionalInit<Paths[Path], Method>, Response extends Required<FetchResponse<PathOperation<Paths, Path, Method>, Init, Media>>, Options extends Omit<UseQueryOptions<QueryData<Response["data"]>, Response["error"]
|
|
69
|
+
type UseQueryMethod<Paths extends {}, Media extends MediaType> = <Method extends HttpMethod, Path extends PathsWithMethod<Paths, Method>, Init extends MaybeOptionalInit<Paths[Path], Method>, Response extends Required<FetchResponse<PathOperation<Paths, Path, Method>, Init, Media>>, Options extends Omit<UseQueryOptions<QueryData<Response["data"]>, QueryError<Response["error"]>, InferSelectReturnType<QueryData<Response["data"]>, Options["select"]>, QueryKey<Paths, Method, Path>>, "queryKey" | "queryFn">>(method: Method, url: Path, ...[init, options, queryClient]: InitArguments<Init, [Options?, QueryClient?]>) => UseQueryResult<InferSelectReturnType<QueryData<Response["data"]>, Options["select"]>, QueryError<Response["error"]>>;
|
|
37
70
|
/**
|
|
38
71
|
* The type of the page params: the initial one and the ones `getNextPageParam` and
|
|
39
72
|
* `getPreviousPageParam` return (upstream #2458). It was `unknown`. It stays `unknown` when a
|
|
@@ -65,12 +98,12 @@ interface PageParamSources<Initial, Next, Previous> {
|
|
|
65
98
|
* `unknown` there and failed against the typed page param.
|
|
66
99
|
*/
|
|
67
100
|
type InfinitePlaceholderData<Data, Error, Paths extends {}, Method extends HttpMethod, Path extends PathsWithMethod<Paths, Method>> = UseInfiniteQueryOptions<Data, Error, InfiniteData<Data, unknown>, InfiniteQueryKey<Paths, Method, Path>, unknown>["placeholderData"];
|
|
68
|
-
type UseInfiniteQueryMethod<Paths extends {}, Media extends MediaType> = <Method extends HttpMethod, Path extends PathsWithMethod<Paths, Method>, Init extends MaybeOptionalInit<Paths[Path], Method>, Response extends Required<FetchResponse<PathOperation<Paths, Path, Method>, Init, Media>>, Options extends Omit<UseInfiniteQueryOptions<Response["data"], Response["error"]
|
|
69
|
-
placeholderData?: InfinitePlaceholderData<Response["data"], Response["error"]
|
|
101
|
+
type UseInfiniteQueryMethod<Paths extends {}, Media extends MediaType> = <Method extends HttpMethod, Path extends PathsWithMethod<Paths, Method>, Init extends MaybeOptionalInit<Paths[Path], Method>, Response extends Required<FetchResponse<PathOperation<Paths, Path, Method>, Init, Media>>, Options extends Omit<UseInfiniteQueryOptions<Response["data"], QueryError<Response["error"]>, InferSelectReturnType<InfiniteData<Response["data"], PageParam<Initial, Next, Previous>>, Options["select"]>, InfiniteQueryKey<Paths, Method, Path>, PageParam<Initial, Next, Previous>>, "queryKey" | "queryFn" | "placeholderData"> & {
|
|
102
|
+
placeholderData?: InfinitePlaceholderData<Response["data"], QueryError<Response["error"]>, Paths, Method, Path>;
|
|
70
103
|
pageParamName?: string;
|
|
71
|
-
}, Initial = unknown, Next = never, Previous = NoPreviousPageParam>(method: Method, url: Path, init: InitWithUnknowns<Init>, options: PageParamSources<Initial, Next, Previous> & Options, queryClient?: QueryClient) => UseInfiniteQueryResult<InferSelectReturnType<InfiniteData<Response["data"], PageParam<Initial, Next, Previous>>, Options["select"]>, Response["error"]
|
|
72
|
-
type UseSuspenseQueryMethod<Paths extends {}, Media extends MediaType> = <Method extends HttpMethod, Path extends PathsWithMethod<Paths, Method>, Init extends MaybeOptionalInit<Paths[Path], Method>, Response extends Required<FetchResponse<PathOperation<Paths, Path, Method>, Init, Media>>, Options extends Omit<UseSuspenseQueryOptions<QueryData<Response["data"]>, Response["error"]
|
|
73
|
-
type UseMutationMethod<Paths extends {}, Media extends MediaType> = <Method extends HttpMethod, Path extends PathsWithMethod<Paths, Method>, Init extends MaybeOptionalInit<Paths[Path], Method>, Response extends Required<FetchResponse<PathOperation<Paths, Path, Method>, Init, Media>>, TOnMutateResult = unknown>(method: Method, url: Path, options?: Omit<UseMutationOptions<Response["data"], Response["error"]
|
|
104
|
+
}, Initial = unknown, Next = never, Previous = NoPreviousPageParam>(method: Method, url: Path, init: InitWithUnknowns<Init>, options: PageParamSources<Initial, Next, Previous> & Options, queryClient?: QueryClient) => UseInfiniteQueryResult<InferSelectReturnType<InfiniteData<Response["data"], PageParam<Initial, Next, Previous>>, Options["select"]>, QueryError<Response["error"]>>;
|
|
105
|
+
type UseSuspenseQueryMethod<Paths extends {}, Media extends MediaType> = <Method extends HttpMethod, Path extends PathsWithMethod<Paths, Method>, Init extends MaybeOptionalInit<Paths[Path], Method>, Response extends Required<FetchResponse<PathOperation<Paths, Path, Method>, Init, Media>>, Options extends Omit<UseSuspenseQueryOptions<QueryData<Response["data"]>, QueryError<Response["error"]>, InferSelectReturnType<QueryData<Response["data"]>, Options["select"]>, QueryKey<Paths, Method, Path>>, "queryKey" | "queryFn">>(method: Method, url: Path, ...[init, options, queryClient]: InitArguments<Init, [Options?, QueryClient?]>) => UseSuspenseQueryResult<InferSelectReturnType<QueryData<Response["data"]>, Options["select"]>, QueryError<Response["error"]>>;
|
|
106
|
+
type UseMutationMethod<Paths extends {}, Media extends MediaType> = <Method extends HttpMethod, Path extends PathsWithMethod<Paths, Method>, Init extends MaybeOptionalInit<Paths[Path], Method>, Response extends Required<FetchResponse<PathOperation<Paths, Path, Method>, Init, Media>>, TOnMutateResult = unknown>(method: Method, url: Path, options?: Omit<UseMutationOptions<Response["data"], QueryError<Response["error"]>, Init, TOnMutateResult>, "mutationKey" | "mutationFn">, queryClient?: QueryClient) => UseMutationResult<Response["data"], QueryError<Response["error"]>, Init, TOnMutateResult>;
|
|
74
107
|
interface OpenapiQueryClient<Paths extends {}, Media extends MediaType = MediaType> {
|
|
75
108
|
queryOptions: QueryOptionsFunction<Paths, Media>;
|
|
76
109
|
useQuery: UseQueryMethod<Paths, Media>;
|
|
@@ -81,6 +114,13 @@ interface OpenapiQueryClient<Paths extends {}, Media extends MediaType = MediaTy
|
|
|
81
114
|
type MethodResponse<CreatedClient extends OpenapiQueryClient<any, any>, Method extends HttpMethod, Path extends CreatedClient extends OpenapiQueryClient<infer Paths, infer _Media> ? PathsWithMethod<Paths, Method> : never, Options = object> = CreatedClient extends OpenapiQueryClient<infer Paths extends {
|
|
82
115
|
[key: string]: any;
|
|
83
116
|
}, infer Media extends MediaType> ? NonNullable<FetchResponse<Paths[Path][Method], Options, Media>["data"]> : never;
|
|
117
|
+
/**
|
|
118
|
+
* Whether `error` is the `ResponseError` of a failed response without an error body. It narrows a
|
|
119
|
+
* hook's `error`, where `error instanceof Error` also matches network and parse errors. It checks
|
|
120
|
+
* the `name`, not the class, so a `ResponseError` of another copy of this package (its CommonJS and
|
|
121
|
+
* ES module builds loaded side by side) is one too. An error body from JSON is never an `Error`.
|
|
122
|
+
*/
|
|
123
|
+
declare function isResponseError(error: unknown): error is ResponseError;
|
|
84
124
|
/**
|
|
85
125
|
* Hooks and query options for a fetch client. A `QueryClient` other than the one from the React
|
|
86
126
|
* context is passed to each hook as its last argument; `createClient` does not take one.
|
|
@@ -88,6 +128,6 @@ type MethodResponse<CreatedClient extends OpenapiQueryClient<any, any>, Method e
|
|
|
88
128
|
declare function createClient<Paths extends {}, Media extends MediaType = MediaType>(client: Client<Paths, Media>): OpenapiQueryClient<Paths, Media>;
|
|
89
129
|
|
|
90
130
|
declare namespace createClient {
|
|
91
|
-
export { InfiniteQueryKey, MethodResponse, OpenapiQueryClient, QueryKey, QueryOptionsFunction, UseInfiniteQueryMethod, UseMutationMethod, UseQueryMethod, UseSuspenseQueryMethod };
|
|
131
|
+
export { createClient as default, isResponseError, InfiniteQueryKey, MethodResponse, OpenapiQueryClient, QueryError, QueryKey, QueryKeyWithDataTag, QueryOptionsFunction, ResponseError, UseInfiniteQueryMethod, UseMutationMethod, UseQueryMethod, UseSuspenseQueryMethod };
|
|
92
132
|
}
|
|
93
133
|
export = createClient;
|
package/dist/index.d.mts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { UseQueryOptions, DataTag, SkipToken, QueryClient, UseQueryResult, UseSuspenseQueryOptions, UseSuspenseQueryResult, UseInfiniteQueryOptions, InfiniteData, UseInfiniteQueryResult, UseMutationOptions, UseMutationResult } from '@tanstack/react-query';
|
|
1
|
+
import { UseQueryOptions, DefaultError, DataTag, SkipToken, QueryClient, UseQueryResult, UseSuspenseQueryOptions, UseSuspenseQueryResult, UseInfiniteQueryOptions, InfiniteData, UseInfiniteQueryResult, UseMutationOptions, UseMutationResult } from '@tanstack/react-query';
|
|
2
2
|
import { MaybeOptionalInit, FetchResponse, PathOperation, Client } from 'openapi-typesafe-fetch';
|
|
3
|
-
import { HttpMethod, PathsWithMethod, MediaType, RequiredKeysOf } from 'openapi-typesafe-helpers';
|
|
3
|
+
import { HttpMethod, PathsWithMethod, MediaType, RequiredKeysOf } from 'openapi-typesafe-fetch/helpers';
|
|
4
4
|
|
|
5
5
|
type InferSelectReturnType<TData, TSelect> = TSelect extends (data: TData) => infer R ? R : TData;
|
|
6
6
|
/**
|
|
@@ -8,6 +8,40 @@ type InferSelectReturnType<TData, TSelect> = TSelect extends (data: TData) => in
|
|
|
8
8
|
* `null` in the query, as `queryFn` resolves it (upstream #2234, #2464).
|
|
9
9
|
*/
|
|
10
10
|
type QueryData<Data> = undefined extends Data ? Exclude<Data, undefined> | null : Data;
|
|
11
|
+
/**
|
|
12
|
+
* What the hooks throw when a request fails and the response has no error body: a non-OK status
|
|
13
|
+
* with an empty body, a JSON `null` body, or one whose operation declares no content for it. The
|
|
14
|
+
* fetch client gives `error: undefined` (or `null`) then; throwing that left `error` empty in
|
|
15
|
+
* TanStack Query while its type said there was an error body. Tell it apart with
|
|
16
|
+
* `isResponseError(error)`: `error instanceof Error` also matches a network or parse error. The
|
|
17
|
+
* message names the status, not the URL, which can carry secrets.
|
|
18
|
+
*/
|
|
19
|
+
interface ResponseError extends Error {
|
|
20
|
+
readonly name: "ResponseError";
|
|
21
|
+
/** The response that failed. */
|
|
22
|
+
readonly response: Response;
|
|
23
|
+
/** Its HTTP status, as `response.status`. */
|
|
24
|
+
readonly status: number;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* The error of a hook: the error body of a failed response, a `ResponseError` when it has none, or
|
|
28
|
+
* what the request threw before there was a response to read: a network error (`TypeError`), an
|
|
29
|
+
* abort, a body that is not JSON (`SyntaxError`) or a middleware error. TanStack Query types that
|
|
30
|
+
* last part as `DefaultError` (`Error` unless `Register` says otherwise; a registered `unknown`
|
|
31
|
+
* makes the whole type `unknown`, as for TanStack's own hooks). `undefined` and `null` are left
|
|
32
|
+
* out: a failed response without an error body throws a `ResponseError`.
|
|
33
|
+
*/
|
|
34
|
+
type QueryError<ErrorBody> = Exclude<ErrorBody, undefined | null> | ResponseError | DefaultError;
|
|
35
|
+
/**
|
|
36
|
+
* An object whose `queryKey` is tagged with the query's data and error types: the type that
|
|
37
|
+
* TanStack Query 5.102 exports as `QueryKeyWithDataTag`, for the whole peer range. A named object
|
|
38
|
+
* type, so the declarations of an exported `queryOptions` result print it by name. Spelled out,
|
|
39
|
+
* the tag prints TanStack's `dataTagSymbol` keys, which a declaration file cannot import, and
|
|
40
|
+
* the library's users get TS2304, or `any` cached data with `skipLibCheck`.
|
|
41
|
+
*/
|
|
42
|
+
type QueryKeyWithDataTag<Key, Data, Error> = {
|
|
43
|
+
queryKey: DataTag<Key, Data, Error>;
|
|
44
|
+
};
|
|
11
45
|
type InitWithUnknowns<Init> = Init & {
|
|
12
46
|
[key: string]: unknown;
|
|
13
47
|
};
|
|
@@ -24,16 +58,15 @@ type QueryKey<Paths extends {}, Method extends HttpMethod, Path extends PathsWit
|
|
|
24
58
|
/**
|
|
25
59
|
* The last element of an infinite query's key. `useQuery` and `useInfiniteQuery` cache different
|
|
26
60
|
* data (`TData` and `InfiniteData<TData>`), so the same request must not share one key (upstream
|
|
27
|
-
* #2184, ADR-022). A prefix such as `[method, path]` still matches both. Not exported:
|
|
28
|
-
*
|
|
61
|
+
* #2184, ADR-022). A prefix such as `[method, path]` still matches both. Not exported: it is not
|
|
62
|
+
* needed outside the package, and a named export is public API; `InfiniteQueryKey` types the key.
|
|
29
63
|
*/
|
|
30
64
|
declare const INFINITE_QUERY_KEY_MARKER = "infinite";
|
|
31
65
|
type InfiniteQueryKey<Paths extends {}, Method extends HttpMethod, Path extends PathsWithMethod<Paths, Method>> = readonly [...QueryKey<Paths, Method, Path>, typeof INFINITE_QUERY_KEY_MARKER];
|
|
32
|
-
type QueryOptionsFunction<Paths extends {}, Media extends MediaType> = <Method extends HttpMethod, Path extends PathsWithMethod<Paths, Method>, Init extends MaybeOptionalInit<Paths[Path], Method>, Response extends Required<FetchResponse<PathOperation<Paths, Path, Method>, Init, Media>>, Options extends Omit<UseQueryOptions<QueryData<Response["data"]>, Response["error"]
|
|
33
|
-
|
|
34
|
-
queryFn: Exclude<UseQueryOptions<QueryData<Response["data"]>, Response["error"], InferSelectReturnType<QueryData<Response["data"]>, Options["select"]>, QueryKey<Paths, Method, Path>>["queryFn"], SkipToken | undefined>;
|
|
66
|
+
type QueryOptionsFunction<Paths extends {}, Media extends MediaType> = <Method extends HttpMethod, Path extends PathsWithMethod<Paths, Method>, Init extends MaybeOptionalInit<Paths[Path], Method>, Response extends Required<FetchResponse<PathOperation<Paths, Path, Method>, Init, Media>>, Options extends Omit<UseQueryOptions<QueryData<Response["data"]>, QueryError<Response["error"]>, InferSelectReturnType<QueryData<Response["data"]>, Options["select"]>, QueryKey<Paths, Method, Path>>, "queryKey" | "queryFn">>(method: Method, path: Path, ...[init, options]: InitArguments<Init, [Options?]>) => NoInfer<Omit<UseQueryOptions<QueryData<Response["data"]>, QueryError<Response["error"]>, InferSelectReturnType<QueryData<Response["data"]>, Options["select"]>, QueryKey<Paths, Method, Path>>, "queryFn" | "queryKey"> & QueryKeyWithDataTag<QueryKey<Paths, Method, Path>, QueryData<Response["data"]>, QueryError<Response["error"]>> & {
|
|
67
|
+
queryFn: Exclude<UseQueryOptions<QueryData<Response["data"]>, QueryError<Response["error"]>, InferSelectReturnType<QueryData<Response["data"]>, Options["select"]>, QueryKey<Paths, Method, Path>>["queryFn"], SkipToken | undefined>;
|
|
35
68
|
}>;
|
|
36
|
-
type UseQueryMethod<Paths extends {}, Media extends MediaType> = <Method extends HttpMethod, Path extends PathsWithMethod<Paths, Method>, Init extends MaybeOptionalInit<Paths[Path], Method>, Response extends Required<FetchResponse<PathOperation<Paths, Path, Method>, Init, Media>>, Options extends Omit<UseQueryOptions<QueryData<Response["data"]>, Response["error"]
|
|
69
|
+
type UseQueryMethod<Paths extends {}, Media extends MediaType> = <Method extends HttpMethod, Path extends PathsWithMethod<Paths, Method>, Init extends MaybeOptionalInit<Paths[Path], Method>, Response extends Required<FetchResponse<PathOperation<Paths, Path, Method>, Init, Media>>, Options extends Omit<UseQueryOptions<QueryData<Response["data"]>, QueryError<Response["error"]>, InferSelectReturnType<QueryData<Response["data"]>, Options["select"]>, QueryKey<Paths, Method, Path>>, "queryKey" | "queryFn">>(method: Method, url: Path, ...[init, options, queryClient]: InitArguments<Init, [Options?, QueryClient?]>) => UseQueryResult<InferSelectReturnType<QueryData<Response["data"]>, Options["select"]>, QueryError<Response["error"]>>;
|
|
37
70
|
/**
|
|
38
71
|
* The type of the page params: the initial one and the ones `getNextPageParam` and
|
|
39
72
|
* `getPreviousPageParam` return (upstream #2458). It was `unknown`. It stays `unknown` when a
|
|
@@ -65,12 +98,12 @@ interface PageParamSources<Initial, Next, Previous> {
|
|
|
65
98
|
* `unknown` there and failed against the typed page param.
|
|
66
99
|
*/
|
|
67
100
|
type InfinitePlaceholderData<Data, Error, Paths extends {}, Method extends HttpMethod, Path extends PathsWithMethod<Paths, Method>> = UseInfiniteQueryOptions<Data, Error, InfiniteData<Data, unknown>, InfiniteQueryKey<Paths, Method, Path>, unknown>["placeholderData"];
|
|
68
|
-
type UseInfiniteQueryMethod<Paths extends {}, Media extends MediaType> = <Method extends HttpMethod, Path extends PathsWithMethod<Paths, Method>, Init extends MaybeOptionalInit<Paths[Path], Method>, Response extends Required<FetchResponse<PathOperation<Paths, Path, Method>, Init, Media>>, Options extends Omit<UseInfiniteQueryOptions<Response["data"], Response["error"]
|
|
69
|
-
placeholderData?: InfinitePlaceholderData<Response["data"], Response["error"]
|
|
101
|
+
type UseInfiniteQueryMethod<Paths extends {}, Media extends MediaType> = <Method extends HttpMethod, Path extends PathsWithMethod<Paths, Method>, Init extends MaybeOptionalInit<Paths[Path], Method>, Response extends Required<FetchResponse<PathOperation<Paths, Path, Method>, Init, Media>>, Options extends Omit<UseInfiniteQueryOptions<Response["data"], QueryError<Response["error"]>, InferSelectReturnType<InfiniteData<Response["data"], PageParam<Initial, Next, Previous>>, Options["select"]>, InfiniteQueryKey<Paths, Method, Path>, PageParam<Initial, Next, Previous>>, "queryKey" | "queryFn" | "placeholderData"> & {
|
|
102
|
+
placeholderData?: InfinitePlaceholderData<Response["data"], QueryError<Response["error"]>, Paths, Method, Path>;
|
|
70
103
|
pageParamName?: string;
|
|
71
|
-
}, Initial = unknown, Next = never, Previous = NoPreviousPageParam>(method: Method, url: Path, init: InitWithUnknowns<Init>, options: PageParamSources<Initial, Next, Previous> & Options, queryClient?: QueryClient) => UseInfiniteQueryResult<InferSelectReturnType<InfiniteData<Response["data"], PageParam<Initial, Next, Previous>>, Options["select"]>, Response["error"]
|
|
72
|
-
type UseSuspenseQueryMethod<Paths extends {}, Media extends MediaType> = <Method extends HttpMethod, Path extends PathsWithMethod<Paths, Method>, Init extends MaybeOptionalInit<Paths[Path], Method>, Response extends Required<FetchResponse<PathOperation<Paths, Path, Method>, Init, Media>>, Options extends Omit<UseSuspenseQueryOptions<QueryData<Response["data"]>, Response["error"]
|
|
73
|
-
type UseMutationMethod<Paths extends {}, Media extends MediaType> = <Method extends HttpMethod, Path extends PathsWithMethod<Paths, Method>, Init extends MaybeOptionalInit<Paths[Path], Method>, Response extends Required<FetchResponse<PathOperation<Paths, Path, Method>, Init, Media>>, TOnMutateResult = unknown>(method: Method, url: Path, options?: Omit<UseMutationOptions<Response["data"], Response["error"]
|
|
104
|
+
}, Initial = unknown, Next = never, Previous = NoPreviousPageParam>(method: Method, url: Path, init: InitWithUnknowns<Init>, options: PageParamSources<Initial, Next, Previous> & Options, queryClient?: QueryClient) => UseInfiniteQueryResult<InferSelectReturnType<InfiniteData<Response["data"], PageParam<Initial, Next, Previous>>, Options["select"]>, QueryError<Response["error"]>>;
|
|
105
|
+
type UseSuspenseQueryMethod<Paths extends {}, Media extends MediaType> = <Method extends HttpMethod, Path extends PathsWithMethod<Paths, Method>, Init extends MaybeOptionalInit<Paths[Path], Method>, Response extends Required<FetchResponse<PathOperation<Paths, Path, Method>, Init, Media>>, Options extends Omit<UseSuspenseQueryOptions<QueryData<Response["data"]>, QueryError<Response["error"]>, InferSelectReturnType<QueryData<Response["data"]>, Options["select"]>, QueryKey<Paths, Method, Path>>, "queryKey" | "queryFn">>(method: Method, url: Path, ...[init, options, queryClient]: InitArguments<Init, [Options?, QueryClient?]>) => UseSuspenseQueryResult<InferSelectReturnType<QueryData<Response["data"]>, Options["select"]>, QueryError<Response["error"]>>;
|
|
106
|
+
type UseMutationMethod<Paths extends {}, Media extends MediaType> = <Method extends HttpMethod, Path extends PathsWithMethod<Paths, Method>, Init extends MaybeOptionalInit<Paths[Path], Method>, Response extends Required<FetchResponse<PathOperation<Paths, Path, Method>, Init, Media>>, TOnMutateResult = unknown>(method: Method, url: Path, options?: Omit<UseMutationOptions<Response["data"], QueryError<Response["error"]>, Init, TOnMutateResult>, "mutationKey" | "mutationFn">, queryClient?: QueryClient) => UseMutationResult<Response["data"], QueryError<Response["error"]>, Init, TOnMutateResult>;
|
|
74
107
|
interface OpenapiQueryClient<Paths extends {}, Media extends MediaType = MediaType> {
|
|
75
108
|
queryOptions: QueryOptionsFunction<Paths, Media>;
|
|
76
109
|
useQuery: UseQueryMethod<Paths, Media>;
|
|
@@ -81,11 +114,18 @@ interface OpenapiQueryClient<Paths extends {}, Media extends MediaType = MediaTy
|
|
|
81
114
|
type MethodResponse<CreatedClient extends OpenapiQueryClient<any, any>, Method extends HttpMethod, Path extends CreatedClient extends OpenapiQueryClient<infer Paths, infer _Media> ? PathsWithMethod<Paths, Method> : never, Options = object> = CreatedClient extends OpenapiQueryClient<infer Paths extends {
|
|
82
115
|
[key: string]: any;
|
|
83
116
|
}, infer Media extends MediaType> ? NonNullable<FetchResponse<Paths[Path][Method], Options, Media>["data"]> : never;
|
|
117
|
+
/**
|
|
118
|
+
* Whether `error` is the `ResponseError` of a failed response without an error body. It narrows a
|
|
119
|
+
* hook's `error`, where `error instanceof Error` also matches network and parse errors. It checks
|
|
120
|
+
* the `name`, not the class, so a `ResponseError` of another copy of this package (its CommonJS and
|
|
121
|
+
* ES module builds loaded side by side) is one too. An error body from JSON is never an `Error`.
|
|
122
|
+
*/
|
|
123
|
+
declare function isResponseError(error: unknown): error is ResponseError;
|
|
84
124
|
/**
|
|
85
125
|
* Hooks and query options for a fetch client. A `QueryClient` other than the one from the React
|
|
86
126
|
* context is passed to each hook as its last argument; `createClient` does not take one.
|
|
87
127
|
*/
|
|
88
128
|
declare function createClient<Paths extends {}, Media extends MediaType = MediaType>(client: Client<Paths, Media>): OpenapiQueryClient<Paths, Media>;
|
|
89
129
|
|
|
90
|
-
export { createClient as default };
|
|
91
|
-
export type { InfiniteQueryKey, MethodResponse, OpenapiQueryClient, QueryKey, QueryOptionsFunction, UseInfiniteQueryMethod, UseMutationMethod, UseQueryMethod, UseSuspenseQueryMethod };
|
|
130
|
+
export { createClient as default, isResponseError };
|
|
131
|
+
export type { InfiniteQueryKey, MethodResponse, OpenapiQueryClient, QueryError, QueryKey, QueryKeyWithDataTag, QueryOptionsFunction, ResponseError, UseInfiniteQueryMethod, UseMutationMethod, UseQueryMethod, UseSuspenseQueryMethod };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { UseQueryOptions, DataTag, SkipToken, QueryClient, UseQueryResult, UseSuspenseQueryOptions, UseSuspenseQueryResult, UseInfiniteQueryOptions, InfiniteData, UseInfiniteQueryResult, UseMutationOptions, UseMutationResult } from '@tanstack/react-query';
|
|
1
|
+
import { UseQueryOptions, DefaultError, DataTag, SkipToken, QueryClient, UseQueryResult, UseSuspenseQueryOptions, UseSuspenseQueryResult, UseInfiniteQueryOptions, InfiniteData, UseInfiniteQueryResult, UseMutationOptions, UseMutationResult } from '@tanstack/react-query';
|
|
2
2
|
import { MaybeOptionalInit, FetchResponse, PathOperation, Client } from 'openapi-typesafe-fetch';
|
|
3
|
-
import { HttpMethod, PathsWithMethod, MediaType, RequiredKeysOf } from 'openapi-typesafe-helpers';
|
|
3
|
+
import { HttpMethod, PathsWithMethod, MediaType, RequiredKeysOf } from 'openapi-typesafe-fetch/helpers';
|
|
4
4
|
|
|
5
5
|
type InferSelectReturnType<TData, TSelect> = TSelect extends (data: TData) => infer R ? R : TData;
|
|
6
6
|
/**
|
|
@@ -8,6 +8,40 @@ type InferSelectReturnType<TData, TSelect> = TSelect extends (data: TData) => in
|
|
|
8
8
|
* `null` in the query, as `queryFn` resolves it (upstream #2234, #2464).
|
|
9
9
|
*/
|
|
10
10
|
type QueryData<Data> = undefined extends Data ? Exclude<Data, undefined> | null : Data;
|
|
11
|
+
/**
|
|
12
|
+
* What the hooks throw when a request fails and the response has no error body: a non-OK status
|
|
13
|
+
* with an empty body, a JSON `null` body, or one whose operation declares no content for it. The
|
|
14
|
+
* fetch client gives `error: undefined` (or `null`) then; throwing that left `error` empty in
|
|
15
|
+
* TanStack Query while its type said there was an error body. Tell it apart with
|
|
16
|
+
* `isResponseError(error)`: `error instanceof Error` also matches a network or parse error. The
|
|
17
|
+
* message names the status, not the URL, which can carry secrets.
|
|
18
|
+
*/
|
|
19
|
+
interface ResponseError extends Error {
|
|
20
|
+
readonly name: "ResponseError";
|
|
21
|
+
/** The response that failed. */
|
|
22
|
+
readonly response: Response;
|
|
23
|
+
/** Its HTTP status, as `response.status`. */
|
|
24
|
+
readonly status: number;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* The error of a hook: the error body of a failed response, a `ResponseError` when it has none, or
|
|
28
|
+
* what the request threw before there was a response to read: a network error (`TypeError`), an
|
|
29
|
+
* abort, a body that is not JSON (`SyntaxError`) or a middleware error. TanStack Query types that
|
|
30
|
+
* last part as `DefaultError` (`Error` unless `Register` says otherwise; a registered `unknown`
|
|
31
|
+
* makes the whole type `unknown`, as for TanStack's own hooks). `undefined` and `null` are left
|
|
32
|
+
* out: a failed response without an error body throws a `ResponseError`.
|
|
33
|
+
*/
|
|
34
|
+
type QueryError<ErrorBody> = Exclude<ErrorBody, undefined | null> | ResponseError | DefaultError;
|
|
35
|
+
/**
|
|
36
|
+
* An object whose `queryKey` is tagged with the query's data and error types: the type that
|
|
37
|
+
* TanStack Query 5.102 exports as `QueryKeyWithDataTag`, for the whole peer range. A named object
|
|
38
|
+
* type, so the declarations of an exported `queryOptions` result print it by name. Spelled out,
|
|
39
|
+
* the tag prints TanStack's `dataTagSymbol` keys, which a declaration file cannot import, and
|
|
40
|
+
* the library's users get TS2304, or `any` cached data with `skipLibCheck`.
|
|
41
|
+
*/
|
|
42
|
+
type QueryKeyWithDataTag<Key, Data, Error> = {
|
|
43
|
+
queryKey: DataTag<Key, Data, Error>;
|
|
44
|
+
};
|
|
11
45
|
type InitWithUnknowns<Init> = Init & {
|
|
12
46
|
[key: string]: unknown;
|
|
13
47
|
};
|
|
@@ -24,16 +58,15 @@ type QueryKey<Paths extends {}, Method extends HttpMethod, Path extends PathsWit
|
|
|
24
58
|
/**
|
|
25
59
|
* The last element of an infinite query's key. `useQuery` and `useInfiniteQuery` cache different
|
|
26
60
|
* data (`TData` and `InfiniteData<TData>`), so the same request must not share one key (upstream
|
|
27
|
-
* #2184, ADR-022). A prefix such as `[method, path]` still matches both. Not exported:
|
|
28
|
-
*
|
|
61
|
+
* #2184, ADR-022). A prefix such as `[method, path]` still matches both. Not exported: it is not
|
|
62
|
+
* needed outside the package, and a named export is public API; `InfiniteQueryKey` types the key.
|
|
29
63
|
*/
|
|
30
64
|
declare const INFINITE_QUERY_KEY_MARKER = "infinite";
|
|
31
65
|
type InfiniteQueryKey<Paths extends {}, Method extends HttpMethod, Path extends PathsWithMethod<Paths, Method>> = readonly [...QueryKey<Paths, Method, Path>, typeof INFINITE_QUERY_KEY_MARKER];
|
|
32
|
-
type QueryOptionsFunction<Paths extends {}, Media extends MediaType> = <Method extends HttpMethod, Path extends PathsWithMethod<Paths, Method>, Init extends MaybeOptionalInit<Paths[Path], Method>, Response extends Required<FetchResponse<PathOperation<Paths, Path, Method>, Init, Media>>, Options extends Omit<UseQueryOptions<QueryData<Response["data"]>, Response["error"]
|
|
33
|
-
|
|
34
|
-
queryFn: Exclude<UseQueryOptions<QueryData<Response["data"]>, Response["error"], InferSelectReturnType<QueryData<Response["data"]>, Options["select"]>, QueryKey<Paths, Method, Path>>["queryFn"], SkipToken | undefined>;
|
|
66
|
+
type QueryOptionsFunction<Paths extends {}, Media extends MediaType> = <Method extends HttpMethod, Path extends PathsWithMethod<Paths, Method>, Init extends MaybeOptionalInit<Paths[Path], Method>, Response extends Required<FetchResponse<PathOperation<Paths, Path, Method>, Init, Media>>, Options extends Omit<UseQueryOptions<QueryData<Response["data"]>, QueryError<Response["error"]>, InferSelectReturnType<QueryData<Response["data"]>, Options["select"]>, QueryKey<Paths, Method, Path>>, "queryKey" | "queryFn">>(method: Method, path: Path, ...[init, options]: InitArguments<Init, [Options?]>) => NoInfer<Omit<UseQueryOptions<QueryData<Response["data"]>, QueryError<Response["error"]>, InferSelectReturnType<QueryData<Response["data"]>, Options["select"]>, QueryKey<Paths, Method, Path>>, "queryFn" | "queryKey"> & QueryKeyWithDataTag<QueryKey<Paths, Method, Path>, QueryData<Response["data"]>, QueryError<Response["error"]>> & {
|
|
67
|
+
queryFn: Exclude<UseQueryOptions<QueryData<Response["data"]>, QueryError<Response["error"]>, InferSelectReturnType<QueryData<Response["data"]>, Options["select"]>, QueryKey<Paths, Method, Path>>["queryFn"], SkipToken | undefined>;
|
|
35
68
|
}>;
|
|
36
|
-
type UseQueryMethod<Paths extends {}, Media extends MediaType> = <Method extends HttpMethod, Path extends PathsWithMethod<Paths, Method>, Init extends MaybeOptionalInit<Paths[Path], Method>, Response extends Required<FetchResponse<PathOperation<Paths, Path, Method>, Init, Media>>, Options extends Omit<UseQueryOptions<QueryData<Response["data"]>, Response["error"]
|
|
69
|
+
type UseQueryMethod<Paths extends {}, Media extends MediaType> = <Method extends HttpMethod, Path extends PathsWithMethod<Paths, Method>, Init extends MaybeOptionalInit<Paths[Path], Method>, Response extends Required<FetchResponse<PathOperation<Paths, Path, Method>, Init, Media>>, Options extends Omit<UseQueryOptions<QueryData<Response["data"]>, QueryError<Response["error"]>, InferSelectReturnType<QueryData<Response["data"]>, Options["select"]>, QueryKey<Paths, Method, Path>>, "queryKey" | "queryFn">>(method: Method, url: Path, ...[init, options, queryClient]: InitArguments<Init, [Options?, QueryClient?]>) => UseQueryResult<InferSelectReturnType<QueryData<Response["data"]>, Options["select"]>, QueryError<Response["error"]>>;
|
|
37
70
|
/**
|
|
38
71
|
* The type of the page params: the initial one and the ones `getNextPageParam` and
|
|
39
72
|
* `getPreviousPageParam` return (upstream #2458). It was `unknown`. It stays `unknown` when a
|
|
@@ -65,12 +98,12 @@ interface PageParamSources<Initial, Next, Previous> {
|
|
|
65
98
|
* `unknown` there and failed against the typed page param.
|
|
66
99
|
*/
|
|
67
100
|
type InfinitePlaceholderData<Data, Error, Paths extends {}, Method extends HttpMethod, Path extends PathsWithMethod<Paths, Method>> = UseInfiniteQueryOptions<Data, Error, InfiniteData<Data, unknown>, InfiniteQueryKey<Paths, Method, Path>, unknown>["placeholderData"];
|
|
68
|
-
type UseInfiniteQueryMethod<Paths extends {}, Media extends MediaType> = <Method extends HttpMethod, Path extends PathsWithMethod<Paths, Method>, Init extends MaybeOptionalInit<Paths[Path], Method>, Response extends Required<FetchResponse<PathOperation<Paths, Path, Method>, Init, Media>>, Options extends Omit<UseInfiniteQueryOptions<Response["data"], Response["error"]
|
|
69
|
-
placeholderData?: InfinitePlaceholderData<Response["data"], Response["error"]
|
|
101
|
+
type UseInfiniteQueryMethod<Paths extends {}, Media extends MediaType> = <Method extends HttpMethod, Path extends PathsWithMethod<Paths, Method>, Init extends MaybeOptionalInit<Paths[Path], Method>, Response extends Required<FetchResponse<PathOperation<Paths, Path, Method>, Init, Media>>, Options extends Omit<UseInfiniteQueryOptions<Response["data"], QueryError<Response["error"]>, InferSelectReturnType<InfiniteData<Response["data"], PageParam<Initial, Next, Previous>>, Options["select"]>, InfiniteQueryKey<Paths, Method, Path>, PageParam<Initial, Next, Previous>>, "queryKey" | "queryFn" | "placeholderData"> & {
|
|
102
|
+
placeholderData?: InfinitePlaceholderData<Response["data"], QueryError<Response["error"]>, Paths, Method, Path>;
|
|
70
103
|
pageParamName?: string;
|
|
71
|
-
}, Initial = unknown, Next = never, Previous = NoPreviousPageParam>(method: Method, url: Path, init: InitWithUnknowns<Init>, options: PageParamSources<Initial, Next, Previous> & Options, queryClient?: QueryClient) => UseInfiniteQueryResult<InferSelectReturnType<InfiniteData<Response["data"], PageParam<Initial, Next, Previous>>, Options["select"]>, Response["error"]
|
|
72
|
-
type UseSuspenseQueryMethod<Paths extends {}, Media extends MediaType> = <Method extends HttpMethod, Path extends PathsWithMethod<Paths, Method>, Init extends MaybeOptionalInit<Paths[Path], Method>, Response extends Required<FetchResponse<PathOperation<Paths, Path, Method>, Init, Media>>, Options extends Omit<UseSuspenseQueryOptions<QueryData<Response["data"]>, Response["error"]
|
|
73
|
-
type UseMutationMethod<Paths extends {}, Media extends MediaType> = <Method extends HttpMethod, Path extends PathsWithMethod<Paths, Method>, Init extends MaybeOptionalInit<Paths[Path], Method>, Response extends Required<FetchResponse<PathOperation<Paths, Path, Method>, Init, Media>>, TOnMutateResult = unknown>(method: Method, url: Path, options?: Omit<UseMutationOptions<Response["data"], Response["error"]
|
|
104
|
+
}, Initial = unknown, Next = never, Previous = NoPreviousPageParam>(method: Method, url: Path, init: InitWithUnknowns<Init>, options: PageParamSources<Initial, Next, Previous> & Options, queryClient?: QueryClient) => UseInfiniteQueryResult<InferSelectReturnType<InfiniteData<Response["data"], PageParam<Initial, Next, Previous>>, Options["select"]>, QueryError<Response["error"]>>;
|
|
105
|
+
type UseSuspenseQueryMethod<Paths extends {}, Media extends MediaType> = <Method extends HttpMethod, Path extends PathsWithMethod<Paths, Method>, Init extends MaybeOptionalInit<Paths[Path], Method>, Response extends Required<FetchResponse<PathOperation<Paths, Path, Method>, Init, Media>>, Options extends Omit<UseSuspenseQueryOptions<QueryData<Response["data"]>, QueryError<Response["error"]>, InferSelectReturnType<QueryData<Response["data"]>, Options["select"]>, QueryKey<Paths, Method, Path>>, "queryKey" | "queryFn">>(method: Method, url: Path, ...[init, options, queryClient]: InitArguments<Init, [Options?, QueryClient?]>) => UseSuspenseQueryResult<InferSelectReturnType<QueryData<Response["data"]>, Options["select"]>, QueryError<Response["error"]>>;
|
|
106
|
+
type UseMutationMethod<Paths extends {}, Media extends MediaType> = <Method extends HttpMethod, Path extends PathsWithMethod<Paths, Method>, Init extends MaybeOptionalInit<Paths[Path], Method>, Response extends Required<FetchResponse<PathOperation<Paths, Path, Method>, Init, Media>>, TOnMutateResult = unknown>(method: Method, url: Path, options?: Omit<UseMutationOptions<Response["data"], QueryError<Response["error"]>, Init, TOnMutateResult>, "mutationKey" | "mutationFn">, queryClient?: QueryClient) => UseMutationResult<Response["data"], QueryError<Response["error"]>, Init, TOnMutateResult>;
|
|
74
107
|
interface OpenapiQueryClient<Paths extends {}, Media extends MediaType = MediaType> {
|
|
75
108
|
queryOptions: QueryOptionsFunction<Paths, Media>;
|
|
76
109
|
useQuery: UseQueryMethod<Paths, Media>;
|
|
@@ -81,11 +114,18 @@ interface OpenapiQueryClient<Paths extends {}, Media extends MediaType = MediaTy
|
|
|
81
114
|
type MethodResponse<CreatedClient extends OpenapiQueryClient<any, any>, Method extends HttpMethod, Path extends CreatedClient extends OpenapiQueryClient<infer Paths, infer _Media> ? PathsWithMethod<Paths, Method> : never, Options = object> = CreatedClient extends OpenapiQueryClient<infer Paths extends {
|
|
82
115
|
[key: string]: any;
|
|
83
116
|
}, infer Media extends MediaType> ? NonNullable<FetchResponse<Paths[Path][Method], Options, Media>["data"]> : never;
|
|
117
|
+
/**
|
|
118
|
+
* Whether `error` is the `ResponseError` of a failed response without an error body. It narrows a
|
|
119
|
+
* hook's `error`, where `error instanceof Error` also matches network and parse errors. It checks
|
|
120
|
+
* the `name`, not the class, so a `ResponseError` of another copy of this package (its CommonJS and
|
|
121
|
+
* ES module builds loaded side by side) is one too. An error body from JSON is never an `Error`.
|
|
122
|
+
*/
|
|
123
|
+
declare function isResponseError(error: unknown): error is ResponseError;
|
|
84
124
|
/**
|
|
85
125
|
* Hooks and query options for a fetch client. A `QueryClient` other than the one from the React
|
|
86
126
|
* context is passed to each hook as its last argument; `createClient` does not take one.
|
|
87
127
|
*/
|
|
88
128
|
declare function createClient<Paths extends {}, Media extends MediaType = MediaType>(client: Client<Paths, Media>): OpenapiQueryClient<Paths, Media>;
|
|
89
129
|
|
|
90
|
-
export { createClient as default };
|
|
91
|
-
export type { InfiniteQueryKey, MethodResponse, OpenapiQueryClient, QueryKey, QueryOptionsFunction, UseInfiniteQueryMethod, UseMutationMethod, UseQueryMethod, UseSuspenseQueryMethod };
|
|
130
|
+
export { createClient as default, isResponseError };
|
|
131
|
+
export type { InfiniteQueryKey, MethodResponse, OpenapiQueryClient, QueryError, QueryKey, QueryKeyWithDataTag, QueryOptionsFunction, ResponseError, UseInfiniteQueryMethod, UseMutationMethod, UseQueryMethod, UseSuspenseQueryMethod };
|
package/dist/index.mjs
CHANGED
|
@@ -1,10 +1,28 @@
|
|
|
1
1
|
import { useMutation, useInfiniteQuery, useSuspenseQuery, useQuery } from '@tanstack/react-query';
|
|
2
2
|
|
|
3
3
|
const INFINITE_QUERY_KEY_MARKER = "infinite";
|
|
4
|
+
const RESPONSE_ERROR_NAME = "ResponseError";
|
|
5
|
+
class ResponseWithoutErrorBody extends Error {
|
|
6
|
+
name = RESPONSE_ERROR_NAME;
|
|
7
|
+
response;
|
|
8
|
+
status;
|
|
9
|
+
constructor(response) {
|
|
10
|
+
const statusText = response.statusText ? ` ${response.statusText}` : "";
|
|
11
|
+
super(`Request failed with status ${response.status}${statusText} and no error body`);
|
|
12
|
+
this.response = response;
|
|
13
|
+
this.status = response.status;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
function isResponseError(error) {
|
|
17
|
+
return error instanceof Error && error.name === RESPONSE_ERROR_NAME;
|
|
18
|
+
}
|
|
4
19
|
function throwIfFailed(result) {
|
|
5
|
-
if (result.error !== void 0
|
|
20
|
+
if (result.error !== void 0 && result.error !== null) {
|
|
6
21
|
throw result.error;
|
|
7
22
|
}
|
|
23
|
+
if (!result.response.ok) {
|
|
24
|
+
throw new ResponseWithoutErrorBody(result.response);
|
|
25
|
+
}
|
|
8
26
|
}
|
|
9
27
|
const DEFAULT_PAGE_PARAM_NAME = "cursor";
|
|
10
28
|
function pageInit(init, { pageParamName, pageParam, signal }) {
|
|
@@ -85,5 +103,5 @@ function createClient(client) {
|
|
|
85
103
|
};
|
|
86
104
|
}
|
|
87
105
|
|
|
88
|
-
export { createClient as default };
|
|
106
|
+
export { createClient as default, isResponseError };
|
|
89
107
|
//# sourceMappingURL=index.mjs.map
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","sources":["../src/index.ts"],"sourcesContent":["import {\n type DataTag,\n type InfiniteData,\n type QueryClient,\n type QueryFunctionContext,\n type SkipToken,\n type UseInfiniteQueryOptions,\n type UseInfiniteQueryResult,\n type UseMutationOptions,\n type UseMutationResult,\n type UseQueryOptions,\n type UseQueryResult,\n type UseSuspenseQueryOptions,\n type UseSuspenseQueryResult,\n useInfiniteQuery,\n useMutation,\n useQuery,\n useSuspenseQuery,\n} from \"@tanstack/react-query\";\nimport type {\n ClientMethod,\n DefaultParamsOption,\n Client as FetchClient,\n FetchResponse,\n MaybeOptionalInit,\n PathOperation,\n} from \"openapi-typesafe-fetch\";\nimport type {\n HttpMethod,\n MediaType,\n PathsWithMethod,\n RequiredKeysOf,\n} from \"openapi-typesafe-helpers\";\n\n// Helper type to dynamically infer the type from the `select` property\ntype InferSelectReturnType<TData, TSelect> = TSelect extends (data: TData) => infer R ? R : TData;\n\n/**\n * Query data of a response type: a success without a body is `undefined` in the fetch client and\n * `null` in the query, as `queryFn` resolves it (upstream #2234, #2464).\n */\ntype QueryData<Data> = undefined extends Data ? Exclude<Data, undefined> | null : Data;\n\ntype InitWithUnknowns<Init> = Init & { [key: string]: unknown };\n\n/**\n * The arguments after the path: the init, required when the operation requires a parameter or a\n * body, then `Rest`. The condition is openapi-react-query's, as `InitParam` of the fetch client\n * is openapi-fetch's (ADR-030, decision 2): TypeScript relates two conditional types only when\n * their `extends` types are the same, so a hook type copied from openapi-react-query takes these\n * hooks. For a union of inits, `MaybeOptionalInit` leaves out `undefined` when one is required,\n * so `Parameters<typeof $api.queryOptions>` still requires it then (upstream #2178).\n */\ntype InitArguments<Init, Rest extends unknown[]> =\n RequiredKeysOf<Init> extends never\n ? [InitWithUnknowns<Init>?, ...Rest]\n : [InitWithUnknowns<Init>, ...Rest];\n\nexport type QueryKey<\n Paths extends {},\n Method extends HttpMethod,\n Path extends PathsWithMethod<Paths, Method>,\n Init = MaybeOptionalInit<Paths[Path], Method>,\n> = Init extends undefined ? readonly [Method, Path] : readonly [Method, Path, Init];\n\n/**\n * The last element of an infinite query's key. `useQuery` and `useInfiniteQuery` cache different\n * data (`TData` and `InfiniteData<TData>`), so the same request must not share one key (upstream\n * #2184, ADR-022). A prefix such as `[method, path]` still matches both. Not exported: a runtime\n * named export next to the default export would change what `require()` returns.\n */\nconst INFINITE_QUERY_KEY_MARKER = \"infinite\";\n\nexport type InfiniteQueryKey<\n Paths extends {},\n Method extends HttpMethod,\n Path extends PathsWithMethod<Paths, Method>,\n> = readonly [...QueryKey<Paths, Method, Path>, typeof INFINITE_QUERY_KEY_MARKER];\n\nexport type QueryOptionsFunction<Paths extends {}, Media extends MediaType> = <\n Method extends HttpMethod,\n Path extends PathsWithMethod<Paths, Method>,\n Init extends MaybeOptionalInit<Paths[Path], Method>,\n // note: Required is used to avoid repeating NonNullable in UseQuery types\n Response extends Required<FetchResponse<PathOperation<Paths, Path, Method>, Init, Media>>,\n Options extends Omit<\n UseQueryOptions<\n QueryData<Response[\"data\"]>,\n Response[\"error\"],\n InferSelectReturnType<QueryData<Response[\"data\"]>, Options[\"select\"]>,\n QueryKey<Paths, Method, Path>\n >,\n \"queryKey\" | \"queryFn\"\n >,\n>(\n method: Method,\n path: Path,\n ...[init, options]: InitArguments<Init, [Options?]>\n) => NoInfer<\n Omit<\n UseQueryOptions<\n QueryData<Response[\"data\"]>,\n Response[\"error\"],\n InferSelectReturnType<QueryData<Response[\"data\"]>, Options[\"select\"]>,\n QueryKey<Paths, Method, Path>\n >,\n \"queryFn\" | \"queryKey\"\n > & {\n queryKey: DataTag<\n QueryKey<Paths, Method, Path>,\n QueryData<Response[\"data\"]>,\n Response[\"error\"]\n >;\n queryFn: Exclude<\n UseQueryOptions<\n QueryData<Response[\"data\"]>,\n Response[\"error\"],\n InferSelectReturnType<QueryData<Response[\"data\"]>, Options[\"select\"]>,\n QueryKey<Paths, Method, Path>\n >[\"queryFn\"],\n SkipToken | undefined\n >;\n }\n>;\n\nexport type UseQueryMethod<Paths extends {}, Media extends MediaType> = <\n Method extends HttpMethod,\n Path extends PathsWithMethod<Paths, Method>,\n Init extends MaybeOptionalInit<Paths[Path], Method>,\n // note: Required is used to avoid repeating NonNullable in UseQuery types\n Response extends Required<FetchResponse<PathOperation<Paths, Path, Method>, Init, Media>>,\n Options extends Omit<\n UseQueryOptions<\n QueryData<Response[\"data\"]>,\n Response[\"error\"],\n InferSelectReturnType<QueryData<Response[\"data\"]>, Options[\"select\"]>,\n QueryKey<Paths, Method, Path>\n >,\n \"queryKey\" | \"queryFn\"\n >,\n>(\n method: Method,\n url: Path,\n ...[init, options, queryClient]: InitArguments<Init, [Options?, QueryClient?]>\n) => UseQueryResult<\n InferSelectReturnType<QueryData<Response[\"data\"]>, Options[\"select\"]>,\n Response[\"error\"]\n>;\n\n/**\n * The type of the page params: the initial one and the ones `getNextPageParam` and\n * `getPreviousPageParam` return (upstream #2458). It was `unknown`. It stays `unknown` when a\n * return type is untyped, so code that compiled still compiles (roadmap §3): TypeScript cannot\n * infer the return type of a callback that computes it from an unannotated `lastPageParam`,\n * whose type depends on that return type, and gives `never` or `unknown`.\n */\ntype PageParam<Initial, Next, Previous> =\n IsUntyped<Next> extends true\n ? unknown\n : [Previous] extends [NoPreviousPageParam]\n ? NullishToUnknown<Initial | NonNullable<Next>>\n : IsUntyped<Previous> extends true\n ? unknown\n : NullishToUnknown<Initial | NonNullable<Next> | NonNullable<Previous>>;\n\n/** The `Previous` type parameter when the options have no `getPreviousPageParam`. */\ndeclare const NO_PREVIOUS_PAGE_PARAM: unique symbol;\ntype NoPreviousPageParam = typeof NO_PREVIOUS_PAGE_PARAM;\n\ntype IsUntyped<T> = [T] extends [never] ? true : unknown extends T ? true : false;\n\n/** Only `undefined` or `null` names no type: a cursor API's `initialPageParam: undefined`. */\ntype NullishToUnknown<T> = [T] extends [undefined | null] ? unknown : T;\n\n/** Read only for the return type; `never` arguments add no inference for TanStack's page param. */\ntype PageParamFunction<Result> = (...args: never) => Result;\n\n/**\n * Inference sites of the page param types. Intersected before `Options`, so TanStack's own\n * inference in the implementation reads the full signatures of `Options`.\n */\ninterface PageParamSources<Initial, Next, Previous> {\n initialPageParam: Initial;\n getNextPageParam: PageParamFunction<Next>;\n getPreviousPageParam?: PageParamFunction<Previous>;\n}\n\n/**\n * `placeholderData` of `useInfiniteQuery`, with an `unknown` page param as before: TypeScript types\n * a `(previousData) => previousData` callback while it still infers the page param, so it got\n * `unknown` there and failed against the typed page param.\n */\ntype InfinitePlaceholderData<\n Data,\n Error,\n Paths extends {},\n Method extends HttpMethod,\n Path extends PathsWithMethod<Paths, Method>,\n> = UseInfiniteQueryOptions<\n Data,\n Error,\n InfiniteData<Data, unknown>,\n InfiniteQueryKey<Paths, Method, Path>,\n unknown\n>[\"placeholderData\"];\n\nexport type UseInfiniteQueryMethod<Paths extends {}, Media extends MediaType> = <\n Method extends HttpMethod,\n Path extends PathsWithMethod<Paths, Method>,\n Init extends MaybeOptionalInit<Paths[Path], Method>,\n Response extends Required<FetchResponse<PathOperation<Paths, Path, Method>, Init, Media>>,\n Options extends Omit<\n UseInfiniteQueryOptions<\n Response[\"data\"],\n Response[\"error\"],\n InferSelectReturnType<\n InfiniteData<Response[\"data\"], PageParam<Initial, Next, Previous>>,\n Options[\"select\"]\n >,\n InfiniteQueryKey<Paths, Method, Path>,\n PageParam<Initial, Next, Previous>\n >,\n \"queryKey\" | \"queryFn\" | \"placeholderData\"\n > & {\n placeholderData?: InfinitePlaceholderData<\n Response[\"data\"],\n Response[\"error\"],\n Paths,\n Method,\n Path\n >;\n pageParamName?: string;\n },\n Initial = unknown,\n Next = never,\n Previous = NoPreviousPageParam,\n // biome-ignore lint/complexity/useMaxParams: public signature of 1.x (ADR-036)\n>(\n method: Method,\n url: Path,\n init: InitWithUnknowns<Init>,\n options: PageParamSources<Initial, Next, Previous> & Options,\n queryClient?: QueryClient,\n) => UseInfiniteQueryResult<\n InferSelectReturnType<\n InfiniteData<Response[\"data\"], PageParam<Initial, Next, Previous>>,\n Options[\"select\"]\n >,\n Response[\"error\"]\n>;\n\nexport type UseSuspenseQueryMethod<Paths extends {}, Media extends MediaType> = <\n Method extends HttpMethod,\n Path extends PathsWithMethod<Paths, Method>,\n Init extends MaybeOptionalInit<Paths[Path], Method>,\n // note: Required is used to avoid repeating NonNullable in UseQuery types\n Response extends Required<FetchResponse<PathOperation<Paths, Path, Method>, Init, Media>>,\n Options extends Omit<\n UseSuspenseQueryOptions<\n QueryData<Response[\"data\"]>,\n Response[\"error\"],\n InferSelectReturnType<QueryData<Response[\"data\"]>, Options[\"select\"]>,\n QueryKey<Paths, Method, Path>\n >,\n \"queryKey\" | \"queryFn\"\n >,\n>(\n method: Method,\n url: Path,\n ...[init, options, queryClient]: InitArguments<Init, [Options?, QueryClient?]>\n) => UseSuspenseQueryResult<\n InferSelectReturnType<QueryData<Response[\"data\"]>, Options[\"select\"]>,\n Response[\"error\"]\n>;\n\nexport type UseMutationMethod<Paths extends {}, Media extends MediaType> = <\n Method extends HttpMethod,\n Path extends PathsWithMethod<Paths, Method>,\n Init extends MaybeOptionalInit<Paths[Path], Method>,\n // note: Required is used to avoid repeating NonNullable in UseQuery types\n Response extends Required<FetchResponse<PathOperation<Paths, Path, Method>, Init, Media>>,\n TOnMutateResult = unknown,\n>(\n method: Method,\n url: Path,\n options?: Omit<\n UseMutationOptions<Response[\"data\"], Response[\"error\"], Init, TOnMutateResult>,\n \"mutationKey\" | \"mutationFn\"\n >,\n queryClient?: QueryClient,\n) => UseMutationResult<Response[\"data\"], Response[\"error\"], Init, TOnMutateResult>;\n\nexport interface OpenapiQueryClient<Paths extends {}, Media extends MediaType = MediaType> {\n queryOptions: QueryOptionsFunction<Paths, Media>;\n useQuery: UseQueryMethod<Paths, Media>;\n useSuspenseQuery: UseSuspenseQueryMethod<Paths, Media>;\n useInfiniteQuery: UseInfiniteQueryMethod<Paths, Media>;\n useMutation: UseMutationMethod<Paths, Media>;\n}\n\nexport type MethodResponse<\n // biome-ignore lint/suspicious/noExplicitAny: matches a client of any paths, as upstream's\n CreatedClient extends OpenapiQueryClient<any, any>,\n Method extends HttpMethod,\n Path extends CreatedClient extends OpenapiQueryClient<infer Paths, infer _Media>\n ? PathsWithMethod<Paths, Method>\n : never,\n Options = object,\n> =\n CreatedClient extends OpenapiQueryClient<\n // biome-ignore lint/suspicious/noExplicitAny: unknown rejects the generated interfaces\n infer Paths extends { [key: string]: any },\n infer Media extends MediaType\n >\n ? NonNullable<FetchResponse<Paths[Path][Method], Options, Media>[\"data\"]>\n : never;\n\n/**\n * Throw the error of a failed fetch result. `if (error)` missed two failures: a non-OK response\n * with an empty body (`error` is `undefined`, upstream #2070, #2829) and a falsy error body such as\n * `0`.\n */\nfunction throwIfFailed(result: { error?: unknown; response: Response }): void {\n if (result.error !== undefined || !result.response.ok) {\n throw result.error;\n }\n}\n\n/** The query parameter that carries the page param unless `pageParamName` names another. */\nconst DEFAULT_PAGE_PARAM_NAME = \"cursor\";\n\ninterface PageRequest {\n readonly pageParamName: string;\n readonly pageParam: unknown;\n readonly signal: AbortSignal;\n}\n\n/**\n * The request init of one page. An `undefined` page param (the first page with\n * `initialPageParam: undefined`) is left out instead of being sent as `0` (upstream #2715, #2340,\n * ADR-022), so a cursor API gets no cursor on the first page.\n */\nfunction pageInit(init: unknown, { pageParamName, pageParam, signal }: PageRequest) {\n const { params, ...rest } = (init ?? {}) as { params?: { query?: DefaultParamsOption } };\n const page = pageParam === undefined ? {} : { [pageParamName]: pageParam };\n return { ...rest, signal, params: { ...params, query: { ...params?.query, ...page } } };\n}\n\n/**\n * Hooks and query options for a fetch client. A `QueryClient` other than the one from the React\n * context is passed to each hook as its last argument; `createClient` does not take one.\n */\n// biome-ignore lint/complexity/noExcessiveLinesPerFunction: inherited, kept until 1.1 (ADR-036)\nexport default function createClient<Paths extends {}, Media extends MediaType = MediaType>(\n client: FetchClient<Paths, Media>,\n): OpenapiQueryClient<Paths, Media> {\n const queryFn = async <Method extends HttpMethod, Path extends PathsWithMethod<Paths, Method>>({\n queryKey,\n signal,\n }: QueryFunctionContext<QueryKey<Paths, Method, Path>>) => {\n // While `Path` is generic, TypeScript cannot work out that the key is a tuple: the init is a\n // conditional type per operation (`MaybeOptionalInit`), and the key's type waits for it.\n const [method, path, init] = queryKey as readonly [Method, Path, unknown?];\n const mth = method.toUpperCase() as Uppercase<typeof method>;\n const fn = client[mth] as ClientMethod<Paths, typeof method, Media>;\n // The init is `unknown` here. An `any` init lets the call infer the generic response type\n // that `queryOptions` declares; a typed init makes TypeScript compare two unresolved\n // conditional types, which it cannot do.\n // biome-ignore lint/suspicious/noExplicitAny: see the comment above\n const result = await fn(path, { signal, ...(init as any) });\n throwIfFailed(result);\n // TanStack Query rejects `undefined` query data. The fetch client gives `undefined` for every\n // success without a body: a 204, `Content-Length: 0`, an empty chunked body, a HEAD request\n // (upstream #2234). A parsed body is never `undefined`, so this changes nothing else.\n return result.data ?? null;\n };\n\n const queryOptions: QueryOptionsFunction<Paths, Media> = (method, path, ...[init, options]) => ({\n queryKey: (init === undefined\n ? ([method, path] as const)\n : ([method, path, init] as const)) as DataTag<\n QueryKey<Paths, typeof method, typeof path>,\n // biome-ignore lint/suspicious/noExplicitAny: the declared return type sets the data type\n any,\n // biome-ignore lint/suspicious/noExplicitAny: the declared return type sets the error type\n any\n >,\n queryFn,\n ...options,\n });\n\n return {\n queryOptions,\n useQuery: (method, path, ...[init, options, queryClient]) =>\n useQuery(\n queryOptions(method, path, init as InitWithUnknowns<typeof init>, options),\n queryClient,\n ),\n useSuspenseQuery: (method, path, ...[init, options, queryClient]) =>\n useSuspenseQuery(\n queryOptions(method, path, init as InitWithUnknowns<typeof init>, options),\n queryClient,\n ),\n // biome-ignore lint/complexity/useMaxParams: public signature of 1.x (ADR-036)\n useInfiniteQuery: (method, path, init, options, queryClient) => {\n const { pageParamName = DEFAULT_PAGE_PARAM_NAME, placeholderData, ...restOptions } = options;\n const { queryKey } = queryOptions(method, path, init);\n const mth = method.toUpperCase() as Uppercase<typeof method>;\n const fn = client[mth] as ClientMethod<Paths, typeof method, Media>;\n return useInfiniteQuery(\n {\n queryKey: [...queryKey, INFINITE_QUERY_KEY_MARKER] as const,\n // The request comes from the arguments; the key only identifies the cache entry.\n queryFn: async ({ pageParam, signal }) => {\n const result = await fn(\n path,\n // biome-ignore lint/suspicious/noExplicitAny: a generic init; see queryFn\n pageInit(init, { pageParamName, pageParam, signal }) as any,\n );\n throwIfFailed(result);\n // An empty page stays `undefined`, as in upstream: TanStack Query rejects only\n // `undefined` query data, and the infinite query data is the `{ pages }` object.\n return result.data;\n },\n ...restOptions,\n // Typed with an `unknown` page param for the caller (`InfinitePlaceholderData`). TanStack\n // passes the previous data of this query, with its own page params, and takes it back.\n // biome-ignore lint/suspicious/noExplicitAny: TanStack's type carries its own page params\n placeholderData: placeholderData as any,\n },\n queryClient,\n );\n },\n useMutation: (method, path, options, queryClient) =>\n useMutation(\n {\n mutationKey: [method, path],\n mutationFn: async (init) => {\n const mth = method.toUpperCase() as Uppercase<typeof method>;\n const fn = client[mth] as ClientMethod<Paths, typeof method, Media>;\n const result = await fn(path, init as InitWithUnknowns<typeof init>);\n throwIfFailed(result);\n // TanStack Query accepts `undefined` mutation data, so a success without a body stays\n // `undefined`, as in upstream; only query data needs `null` (upstream #2234). The cast\n // only bridges the generic types: `Response[\"data\"]` still has `undefined` for an\n // operation with a response without a body.\n const { data } = result;\n return data as Exclude<typeof data, undefined>;\n },\n ...options,\n },\n queryClient,\n ),\n };\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","sources":["../src/index.ts"],"sourcesContent":["import {\n type DataTag,\n type DefaultError,\n type InfiniteData,\n type QueryClient,\n type QueryFunctionContext,\n type SkipToken,\n type UseInfiniteQueryOptions,\n type UseInfiniteQueryResult,\n type UseMutationOptions,\n type UseMutationResult,\n type UseQueryOptions,\n type UseQueryResult,\n type UseSuspenseQueryOptions,\n type UseSuspenseQueryResult,\n useInfiniteQuery,\n useMutation,\n useQuery,\n useSuspenseQuery,\n} from \"@tanstack/react-query\";\nimport type {\n ClientMethod,\n DefaultParamsOption,\n Client as FetchClient,\n FetchResponse,\n MaybeOptionalInit,\n PathOperation,\n} from \"openapi-typesafe-fetch\";\n// The helper types come from the client, which declares them: types inferred from the hooks then\n// print the client's `helpers` entry, of a peer every user has, and not `openapi-typesafe-helpers`,\n// which Yarn PnP does not let a library reach (ADR-034).\nimport type {\n HttpMethod,\n MediaType,\n PathsWithMethod,\n RequiredKeysOf,\n} from \"openapi-typesafe-fetch/helpers\";\n\n// Helper type to dynamically infer the type from the `select` property\ntype InferSelectReturnType<TData, TSelect> = TSelect extends (data: TData) => infer R ? R : TData;\n\n/**\n * Query data of a response type: a success without a body is `undefined` in the fetch client and\n * `null` in the query, as `queryFn` resolves it (upstream #2234, #2464).\n */\ntype QueryData<Data> = undefined extends Data ? Exclude<Data, undefined> | null : Data;\n\n/**\n * What the hooks throw when a request fails and the response has no error body: a non-OK status\n * with an empty body, a JSON `null` body, or one whose operation declares no content for it. The\n * fetch client gives `error: undefined` (or `null`) then; throwing that left `error` empty in\n * TanStack Query while its type said there was an error body. Tell it apart with\n * `isResponseError(error)`: `error instanceof Error` also matches a network or parse error. The\n * message names the status, not the URL, which can carry secrets.\n */\nexport interface ResponseError extends Error {\n readonly name: \"ResponseError\";\n /** The response that failed. */\n readonly response: Response;\n /** Its HTTP status, as `response.status`. */\n readonly status: number;\n}\n\n/**\n * The error of a hook: the error body of a failed response, a `ResponseError` when it has none, or\n * what the request threw before there was a response to read: a network error (`TypeError`), an\n * abort, a body that is not JSON (`SyntaxError`) or a middleware error. TanStack Query types that\n * last part as `DefaultError` (`Error` unless `Register` says otherwise; a registered `unknown`\n * makes the whole type `unknown`, as for TanStack's own hooks). `undefined` and `null` are left\n * out: a failed response without an error body throws a `ResponseError`.\n */\nexport type QueryError<ErrorBody> =\n | Exclude<ErrorBody, undefined | null>\n | ResponseError\n | DefaultError;\n\n/**\n * An object whose `queryKey` is tagged with the query's data and error types: the type that\n * TanStack Query 5.102 exports as `QueryKeyWithDataTag`, for the whole peer range. A named object\n * type, so the declarations of an exported `queryOptions` result print it by name. Spelled out,\n * the tag prints TanStack's `dataTagSymbol` keys, which a declaration file cannot import, and\n * the library's users get TS2304, or `any` cached data with `skipLibCheck`.\n */\nexport type QueryKeyWithDataTag<Key, Data, Error> = {\n queryKey: DataTag<Key, Data, Error>;\n};\n\ntype InitWithUnknowns<Init> = Init & { [key: string]: unknown };\n\n/**\n * The arguments after the path: the init, required when the operation requires a parameter or a\n * body, then `Rest`. The condition is openapi-react-query's, as `InitParam` of the fetch client\n * is openapi-fetch's (ADR-030, decision 2): TypeScript relates two conditional types only when\n * their `extends` types are the same, so a hook type copied from openapi-react-query takes these\n * hooks. For a union of inits, `MaybeOptionalInit` leaves out `undefined` when one is required,\n * so `Parameters<typeof $api.queryOptions>` still requires it then (upstream #2178).\n */\ntype InitArguments<Init, Rest extends unknown[]> =\n RequiredKeysOf<Init> extends never\n ? [InitWithUnknowns<Init>?, ...Rest]\n : [InitWithUnknowns<Init>, ...Rest];\n\nexport type QueryKey<\n Paths extends {},\n Method extends HttpMethod,\n Path extends PathsWithMethod<Paths, Method>,\n Init = MaybeOptionalInit<Paths[Path], Method>,\n> = Init extends undefined ? readonly [Method, Path] : readonly [Method, Path, Init];\n\n/**\n * The last element of an infinite query's key. `useQuery` and `useInfiniteQuery` cache different\n * data (`TData` and `InfiniteData<TData>`), so the same request must not share one key (upstream\n * #2184, ADR-022). A prefix such as `[method, path]` still matches both. Not exported: it is not\n * needed outside the package, and a named export is public API; `InfiniteQueryKey` types the key.\n */\nconst INFINITE_QUERY_KEY_MARKER = \"infinite\";\n\nexport type InfiniteQueryKey<\n Paths extends {},\n Method extends HttpMethod,\n Path extends PathsWithMethod<Paths, Method>,\n> = readonly [...QueryKey<Paths, Method, Path>, typeof INFINITE_QUERY_KEY_MARKER];\n\nexport type QueryOptionsFunction<Paths extends {}, Media extends MediaType> = <\n Method extends HttpMethod,\n Path extends PathsWithMethod<Paths, Method>,\n Init extends MaybeOptionalInit<Paths[Path], Method>,\n // note: Required is used to avoid repeating NonNullable in UseQuery types\n Response extends Required<FetchResponse<PathOperation<Paths, Path, Method>, Init, Media>>,\n Options extends Omit<\n UseQueryOptions<\n QueryData<Response[\"data\"]>,\n QueryError<Response[\"error\"]>,\n InferSelectReturnType<QueryData<Response[\"data\"]>, Options[\"select\"]>,\n QueryKey<Paths, Method, Path>\n >,\n \"queryKey\" | \"queryFn\"\n >,\n>(\n method: Method,\n path: Path,\n ...[init, options]: InitArguments<Init, [Options?]>\n) => NoInfer<\n Omit<\n UseQueryOptions<\n QueryData<Response[\"data\"]>,\n QueryError<Response[\"error\"]>,\n InferSelectReturnType<QueryData<Response[\"data\"]>, Options[\"select\"]>,\n QueryKey<Paths, Method, Path>\n >,\n \"queryFn\" | \"queryKey\"\n > &\n QueryKeyWithDataTag<\n QueryKey<Paths, Method, Path>,\n QueryData<Response[\"data\"]>,\n QueryError<Response[\"error\"]>\n > & {\n queryFn: Exclude<\n UseQueryOptions<\n QueryData<Response[\"data\"]>,\n QueryError<Response[\"error\"]>,\n InferSelectReturnType<QueryData<Response[\"data\"]>, Options[\"select\"]>,\n QueryKey<Paths, Method, Path>\n >[\"queryFn\"],\n SkipToken | undefined\n >;\n }\n>;\n\nexport type UseQueryMethod<Paths extends {}, Media extends MediaType> = <\n Method extends HttpMethod,\n Path extends PathsWithMethod<Paths, Method>,\n Init extends MaybeOptionalInit<Paths[Path], Method>,\n // note: Required is used to avoid repeating NonNullable in UseQuery types\n Response extends Required<FetchResponse<PathOperation<Paths, Path, Method>, Init, Media>>,\n Options extends Omit<\n UseQueryOptions<\n QueryData<Response[\"data\"]>,\n QueryError<Response[\"error\"]>,\n InferSelectReturnType<QueryData<Response[\"data\"]>, Options[\"select\"]>,\n QueryKey<Paths, Method, Path>\n >,\n \"queryKey\" | \"queryFn\"\n >,\n>(\n method: Method,\n url: Path,\n ...[init, options, queryClient]: InitArguments<Init, [Options?, QueryClient?]>\n) => UseQueryResult<\n InferSelectReturnType<QueryData<Response[\"data\"]>, Options[\"select\"]>,\n QueryError<Response[\"error\"]>\n>;\n\n/**\n * The type of the page params: the initial one and the ones `getNextPageParam` and\n * `getPreviousPageParam` return (upstream #2458). It was `unknown`. It stays `unknown` when a\n * return type is untyped, so code that compiled still compiles (roadmap §3): TypeScript cannot\n * infer the return type of a callback that computes it from an unannotated `lastPageParam`,\n * whose type depends on that return type, and gives `never` or `unknown`.\n */\ntype PageParam<Initial, Next, Previous> =\n IsUntyped<Next> extends true\n ? unknown\n : [Previous] extends [NoPreviousPageParam]\n ? NullishToUnknown<Initial | NonNullable<Next>>\n : IsUntyped<Previous> extends true\n ? unknown\n : NullishToUnknown<Initial | NonNullable<Next> | NonNullable<Previous>>;\n\n/** The `Previous` type parameter when the options have no `getPreviousPageParam`. */\ndeclare const NO_PREVIOUS_PAGE_PARAM: unique symbol;\ntype NoPreviousPageParam = typeof NO_PREVIOUS_PAGE_PARAM;\n\ntype IsUntyped<T> = [T] extends [never] ? true : unknown extends T ? true : false;\n\n/** Only `undefined` or `null` names no type: a cursor API's `initialPageParam: undefined`. */\ntype NullishToUnknown<T> = [T] extends [undefined | null] ? unknown : T;\n\n/** Read only for the return type; `never` arguments add no inference for TanStack's page param. */\ntype PageParamFunction<Result> = (...args: never) => Result;\n\n/**\n * Inference sites of the page param types. Intersected before `Options`, so TanStack's own\n * inference in the implementation reads the full signatures of `Options`.\n */\ninterface PageParamSources<Initial, Next, Previous> {\n initialPageParam: Initial;\n getNextPageParam: PageParamFunction<Next>;\n getPreviousPageParam?: PageParamFunction<Previous>;\n}\n\n/**\n * `placeholderData` of `useInfiniteQuery`, with an `unknown` page param as before: TypeScript types\n * a `(previousData) => previousData` callback while it still infers the page param, so it got\n * `unknown` there and failed against the typed page param.\n */\ntype InfinitePlaceholderData<\n Data,\n Error,\n Paths extends {},\n Method extends HttpMethod,\n Path extends PathsWithMethod<Paths, Method>,\n> = UseInfiniteQueryOptions<\n Data,\n Error,\n InfiniteData<Data, unknown>,\n InfiniteQueryKey<Paths, Method, Path>,\n unknown\n>[\"placeholderData\"];\n\nexport type UseInfiniteQueryMethod<Paths extends {}, Media extends MediaType> = <\n Method extends HttpMethod,\n Path extends PathsWithMethod<Paths, Method>,\n Init extends MaybeOptionalInit<Paths[Path], Method>,\n Response extends Required<FetchResponse<PathOperation<Paths, Path, Method>, Init, Media>>,\n Options extends Omit<\n UseInfiniteQueryOptions<\n Response[\"data\"],\n QueryError<Response[\"error\"]>,\n InferSelectReturnType<\n InfiniteData<Response[\"data\"], PageParam<Initial, Next, Previous>>,\n Options[\"select\"]\n >,\n InfiniteQueryKey<Paths, Method, Path>,\n PageParam<Initial, Next, Previous>\n >,\n \"queryKey\" | \"queryFn\" | \"placeholderData\"\n > & {\n placeholderData?: InfinitePlaceholderData<\n Response[\"data\"],\n QueryError<Response[\"error\"]>,\n Paths,\n Method,\n Path\n >;\n pageParamName?: string;\n },\n Initial = unknown,\n Next = never,\n Previous = NoPreviousPageParam,\n // biome-ignore lint/complexity/useMaxParams: public signature of 1.x (ADR-036)\n>(\n method: Method,\n url: Path,\n init: InitWithUnknowns<Init>,\n options: PageParamSources<Initial, Next, Previous> & Options,\n queryClient?: QueryClient,\n) => UseInfiniteQueryResult<\n InferSelectReturnType<\n InfiniteData<Response[\"data\"], PageParam<Initial, Next, Previous>>,\n Options[\"select\"]\n >,\n QueryError<Response[\"error\"]>\n>;\n\nexport type UseSuspenseQueryMethod<Paths extends {}, Media extends MediaType> = <\n Method extends HttpMethod,\n Path extends PathsWithMethod<Paths, Method>,\n Init extends MaybeOptionalInit<Paths[Path], Method>,\n // note: Required is used to avoid repeating NonNullable in UseQuery types\n Response extends Required<FetchResponse<PathOperation<Paths, Path, Method>, Init, Media>>,\n Options extends Omit<\n UseSuspenseQueryOptions<\n QueryData<Response[\"data\"]>,\n QueryError<Response[\"error\"]>,\n InferSelectReturnType<QueryData<Response[\"data\"]>, Options[\"select\"]>,\n QueryKey<Paths, Method, Path>\n >,\n \"queryKey\" | \"queryFn\"\n >,\n>(\n method: Method,\n url: Path,\n ...[init, options, queryClient]: InitArguments<Init, [Options?, QueryClient?]>\n) => UseSuspenseQueryResult<\n InferSelectReturnType<QueryData<Response[\"data\"]>, Options[\"select\"]>,\n QueryError<Response[\"error\"]>\n>;\n\nexport type UseMutationMethod<Paths extends {}, Media extends MediaType> = <\n Method extends HttpMethod,\n Path extends PathsWithMethod<Paths, Method>,\n Init extends MaybeOptionalInit<Paths[Path], Method>,\n // note: Required is used to avoid repeating NonNullable in UseQuery types\n Response extends Required<FetchResponse<PathOperation<Paths, Path, Method>, Init, Media>>,\n TOnMutateResult = unknown,\n>(\n method: Method,\n url: Path,\n options?: Omit<\n UseMutationOptions<Response[\"data\"], QueryError<Response[\"error\"]>, Init, TOnMutateResult>,\n \"mutationKey\" | \"mutationFn\"\n >,\n queryClient?: QueryClient,\n) => UseMutationResult<Response[\"data\"], QueryError<Response[\"error\"]>, Init, TOnMutateResult>;\n\nexport interface OpenapiQueryClient<Paths extends {}, Media extends MediaType = MediaType> {\n queryOptions: QueryOptionsFunction<Paths, Media>;\n useQuery: UseQueryMethod<Paths, Media>;\n useSuspenseQuery: UseSuspenseQueryMethod<Paths, Media>;\n useInfiniteQuery: UseInfiniteQueryMethod<Paths, Media>;\n useMutation: UseMutationMethod<Paths, Media>;\n}\n\nexport type MethodResponse<\n // biome-ignore lint/suspicious/noExplicitAny: matches a client of any paths, as upstream's\n CreatedClient extends OpenapiQueryClient<any, any>,\n Method extends HttpMethod,\n Path extends CreatedClient extends OpenapiQueryClient<infer Paths, infer _Media>\n ? PathsWithMethod<Paths, Method>\n : never,\n Options = object,\n> =\n CreatedClient extends OpenapiQueryClient<\n // biome-ignore lint/suspicious/noExplicitAny: unknown rejects the generated interfaces\n infer Paths extends { [key: string]: any },\n infer Media extends MediaType\n >\n ? NonNullable<FetchResponse<Paths[Path][Method], Options, Media>[\"data\"]>\n : never;\n\n/** The `name` of every `ResponseError`. */\nconst RESPONSE_ERROR_NAME = \"ResponseError\";\n\n/** The `ResponseError` of a failed response without an error body. */\nclass ResponseWithoutErrorBody extends Error implements ResponseError {\n override readonly name = RESPONSE_ERROR_NAME;\n readonly response: Response;\n readonly status: number;\n\n constructor(response: Response) {\n const statusText = response.statusText ? ` ${response.statusText}` : \"\";\n super(`Request failed with status ${response.status}${statusText} and no error body`);\n this.response = response;\n this.status = response.status;\n }\n}\n\n/**\n * Whether `error` is the `ResponseError` of a failed response without an error body. It narrows a\n * hook's `error`, where `error instanceof Error` also matches network and parse errors. It checks\n * the `name`, not the class, so a `ResponseError` of another copy of this package (its CommonJS and\n * ES module builds loaded side by side) is one too. An error body from JSON is never an `Error`.\n */\nexport function isResponseError(error: unknown): error is ResponseError {\n return error instanceof Error && error.name === RESPONSE_ERROR_NAME;\n}\n\n/**\n * Throw the error of a failed fetch result. `if (error)` missed two failures: a non-OK response\n * with an empty body (`error` is `undefined`, upstream #2070, #2829) and a falsy error body such as\n * `0`. Without an error body a `ResponseError` is thrown, so the hooks' `error` is never\n * `undefined` (ADR-013, decision 3). A JSON `null` body is no error body either: thrown as is, it\n * left `error` `null` while the query's status was `\"error\"`.\n */\nfunction throwIfFailed(result: { error?: unknown; response: Response }): void {\n if (result.error !== undefined && result.error !== null) {\n throw result.error;\n }\n if (!result.response.ok) {\n throw new ResponseWithoutErrorBody(result.response);\n }\n}\n\n/** The query parameter that carries the page param unless `pageParamName` names another. */\nconst DEFAULT_PAGE_PARAM_NAME = \"cursor\";\n\ninterface PageRequest {\n readonly pageParamName: string;\n readonly pageParam: unknown;\n readonly signal: AbortSignal;\n}\n\n/**\n * The request init of one page. An `undefined` page param (the first page with\n * `initialPageParam: undefined`) is left out instead of being sent as `0` (upstream #2715, #2340,\n * ADR-022), so a cursor API gets no cursor on the first page.\n */\nfunction pageInit(init: unknown, { pageParamName, pageParam, signal }: PageRequest) {\n const { params, ...rest } = (init ?? {}) as { params?: { query?: DefaultParamsOption } };\n const page = pageParam === undefined ? {} : { [pageParamName]: pageParam };\n return { ...rest, signal, params: { ...params, query: { ...params?.query, ...page } } };\n}\n\n/**\n * Hooks and query options for a fetch client. A `QueryClient` other than the one from the React\n * context is passed to each hook as its last argument; `createClient` does not take one.\n */\n// biome-ignore lint/complexity/noExcessiveLinesPerFunction: inherited, kept until 1.1 (ADR-036)\nexport default function createClient<Paths extends {}, Media extends MediaType = MediaType>(\n client: FetchClient<Paths, Media>,\n): OpenapiQueryClient<Paths, Media> {\n const queryFn = async <Method extends HttpMethod, Path extends PathsWithMethod<Paths, Method>>({\n queryKey,\n signal,\n }: QueryFunctionContext<QueryKey<Paths, Method, Path>>) => {\n // While `Path` is generic, TypeScript cannot work out that the key is a tuple: the init is a\n // conditional type per operation (`MaybeOptionalInit`), and the key's type waits for it.\n const [method, path, init] = queryKey as readonly [Method, Path, unknown?];\n const mth = method.toUpperCase() as Uppercase<typeof method>;\n const fn = client[mth] as ClientMethod<Paths, typeof method, Media>;\n // The init is `unknown` here. An `any` init lets the call infer the generic response type\n // that `queryOptions` declares; a typed init makes TypeScript compare two unresolved\n // conditional types, which it cannot do.\n // biome-ignore lint/suspicious/noExplicitAny: see the comment above\n const result = await fn(path, { signal, ...(init as any) });\n throwIfFailed(result);\n // TanStack Query rejects `undefined` query data. The fetch client gives `undefined` for every\n // success without a body: a 204, `Content-Length: 0`, an empty chunked body, a HEAD request\n // (upstream #2234). A parsed body is never `undefined`, so this changes nothing else.\n return result.data ?? null;\n };\n\n const queryOptions: QueryOptionsFunction<Paths, Media> = (method, path, ...[init, options]) => ({\n queryKey: (init === undefined\n ? ([method, path] as const)\n : ([method, path, init] as const)) as DataTag<\n QueryKey<Paths, typeof method, typeof path>,\n // biome-ignore lint/suspicious/noExplicitAny: the declared return type sets the data type\n any,\n // biome-ignore lint/suspicious/noExplicitAny: the declared return type sets the error type\n any\n >,\n queryFn,\n ...options,\n });\n\n return {\n queryOptions,\n useQuery: (method, path, ...[init, options, queryClient]) =>\n useQuery(\n queryOptions(method, path, init as InitWithUnknowns<typeof init>, options),\n queryClient,\n ),\n useSuspenseQuery: (method, path, ...[init, options, queryClient]) =>\n useSuspenseQuery(\n queryOptions(method, path, init as InitWithUnknowns<typeof init>, options),\n queryClient,\n ),\n // biome-ignore lint/complexity/useMaxParams: public signature of 1.x (ADR-036)\n useInfiniteQuery: (method, path, init, options, queryClient) => {\n const { pageParamName = DEFAULT_PAGE_PARAM_NAME, placeholderData, ...restOptions } = options;\n const { queryKey } = queryOptions(method, path, init);\n const mth = method.toUpperCase() as Uppercase<typeof method>;\n const fn = client[mth] as ClientMethod<Paths, typeof method, Media>;\n return useInfiniteQuery(\n {\n queryKey: [...queryKey, INFINITE_QUERY_KEY_MARKER] as const,\n // The request comes from the arguments; the key only identifies the cache entry.\n queryFn: async ({ pageParam, signal }) => {\n const result = await fn(\n path,\n // biome-ignore lint/suspicious/noExplicitAny: a generic init; see queryFn\n pageInit(init, { pageParamName, pageParam, signal }) as any,\n );\n throwIfFailed(result);\n // An empty page stays `undefined`, as in upstream: TanStack Query rejects only\n // `undefined` query data, and the infinite query data is the `{ pages }` object.\n return result.data;\n },\n ...restOptions,\n // Typed with an `unknown` page param for the caller (`InfinitePlaceholderData`). TanStack\n // passes the previous data of this query, with its own page params, and takes it back.\n // biome-ignore lint/suspicious/noExplicitAny: TanStack's type carries its own page params\n placeholderData: placeholderData as any,\n },\n queryClient,\n );\n },\n useMutation: (method, path, options, queryClient) =>\n useMutation(\n {\n mutationKey: [method, path],\n mutationFn: async (init) => {\n const mth = method.toUpperCase() as Uppercase<typeof method>;\n const fn = client[mth] as ClientMethod<Paths, typeof method, Media>;\n const result = await fn(path, init as InitWithUnknowns<typeof init>);\n throwIfFailed(result);\n // TanStack Query accepts `undefined` mutation data, so a success without a body stays\n // `undefined`, as in upstream; only query data needs `null` (upstream #2234). The cast\n // only bridges the generic types: `Response[\"data\"]` still has `undefined` for an\n // operation with a response without a body.\n const { data } = result;\n return data as Exclude<typeof data, undefined>;\n },\n ...options,\n },\n queryClient,\n ),\n };\n}\n"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "openapi-typesafe-react-query",
|
|
3
3
|
"description": "Fast, type-safe @tanstack/react-query client to work with your OpenAPI schema.",
|
|
4
|
-
"version": "1.0.0-rc.
|
|
4
|
+
"version": "1.0.0-rc.4",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Fedor Chishchin",
|
|
7
7
|
"url": "https://github.com/fedorello"
|
|
@@ -24,6 +24,7 @@
|
|
|
24
24
|
"./*": "./*"
|
|
25
25
|
},
|
|
26
26
|
"files": [
|
|
27
|
+
"CHANGELOG.md",
|
|
27
28
|
"dist",
|
|
28
29
|
"src"
|
|
29
30
|
],
|
|
@@ -49,9 +50,6 @@
|
|
|
49
50
|
"react-query",
|
|
50
51
|
"tanstack"
|
|
51
52
|
],
|
|
52
|
-
"dependencies": {
|
|
53
|
-
"openapi-typesafe-helpers": "^1.0.0-rc.3"
|
|
54
|
-
},
|
|
55
53
|
"devDependencies": {
|
|
56
54
|
"@tanstack/react-query": "5.106.1",
|
|
57
55
|
"@testing-library/react": "16.3.3",
|
|
@@ -60,8 +58,9 @@
|
|
|
60
58
|
"@vitejs/plugin-react": "6.2.1",
|
|
61
59
|
"jsdom": "31.0.0",
|
|
62
60
|
"msw": "3.0.3",
|
|
63
|
-
"openapi-typesafe": "^1.0.0-rc.
|
|
64
|
-
"openapi-typesafe-fetch": "^1.0.0-rc.
|
|
61
|
+
"openapi-typesafe": "^1.0.0-rc.4",
|
|
62
|
+
"openapi-typesafe-fetch": "^1.0.0-rc.4",
|
|
63
|
+
"openapi-typesafe-helpers": "^1.0.0-rc.4",
|
|
65
64
|
"react": "19.3.1",
|
|
66
65
|
"react-dom": "19.3.1",
|
|
67
66
|
"react-error-boundary": "6.1.6",
|
|
@@ -69,7 +68,7 @@
|
|
|
69
68
|
},
|
|
70
69
|
"peerDependencies": {
|
|
71
70
|
"@tanstack/react-query": "^5.80.0",
|
|
72
|
-
"openapi-typesafe-fetch": "^1.0.0-rc.
|
|
71
|
+
"openapi-typesafe-fetch": "^1.0.0-rc.4"
|
|
73
72
|
},
|
|
74
73
|
"engines": {
|
|
75
74
|
"node": ">=22"
|
|
@@ -85,8 +84,7 @@
|
|
|
85
84
|
"generate-types": "openapi-typesafe test/fixtures/api.yaml -o test/fixtures/api.d.ts && openapi-typesafe test/fixtures/query.yaml -o test/fixtures/query.d.ts",
|
|
86
85
|
"test": "pnpm run generate-types && pnpm run test:js && pnpm run test:exports",
|
|
87
86
|
"test:js": "vitest run",
|
|
88
|
-
"test:exports": "
|
|
89
|
-
"version": "pnpm run prepare && pnpm run build",
|
|
87
|
+
"test:exports": "../../scripts/check-exports.sh",
|
|
90
88
|
"test:coverage": "vitest run --coverage"
|
|
91
89
|
}
|
|
92
90
|
}
|