@richie-rpc/react-query 1.0.6 → 1.0.8
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/README.md +277 -169
- package/dist/cjs/index.cjs +203 -38
- package/dist/cjs/index.cjs.map +3 -3
- package/dist/cjs/package.json +1 -1
- package/dist/mjs/index.mjs +206 -38
- package/dist/mjs/index.mjs.map +3 -3
- package/dist/mjs/package.json +1 -1
- package/dist/types/index.d.ts +195 -57
- package/package.json +9 -9
package/dist/cjs/index.cjs
CHANGED
|
@@ -30,71 +30,236 @@ var __export = (target, all) => {
|
|
|
30
30
|
// packages/react-query/index.ts
|
|
31
31
|
var exports_react_query = {};
|
|
32
32
|
__export(exports_react_query, {
|
|
33
|
-
|
|
33
|
+
isUnknownErrorResponse: () => isUnknownErrorResponse,
|
|
34
|
+
isNotKnownResponseError: () => isNotKnownResponseError,
|
|
35
|
+
isFetchError: () => isFetchError,
|
|
36
|
+
exhaustiveGuard: () => exhaustiveGuard,
|
|
37
|
+
createTypedQueryClient: () => createTypedQueryClient,
|
|
38
|
+
createTanstackQueryApi: () => createTanstackQueryApi
|
|
34
39
|
});
|
|
35
40
|
module.exports = __toCommonJS(exports_react_query);
|
|
36
41
|
var import_react_query = require("@tanstack/react-query");
|
|
37
|
-
function
|
|
38
|
-
|
|
42
|
+
function isFetchError(error) {
|
|
43
|
+
return error instanceof Error && !("status" in error);
|
|
44
|
+
}
|
|
45
|
+
function isUnknownErrorResponse(error, endpoint) {
|
|
46
|
+
if (!error || typeof error !== "object" || !("status" in error)) {
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
49
|
+
const status = error.status;
|
|
50
|
+
return !(status in endpoint.responses);
|
|
51
|
+
}
|
|
52
|
+
function isNotKnownResponseError(error, endpoint) {
|
|
53
|
+
return isFetchError(error) || isUnknownErrorResponse(error, endpoint);
|
|
54
|
+
}
|
|
55
|
+
function exhaustiveGuard(_value) {
|
|
56
|
+
throw new Error(`Unhandled case: ${JSON.stringify(_value)}`);
|
|
57
|
+
}
|
|
58
|
+
function streamToAsyncIterable(streamingMethod, options) {
|
|
59
|
+
return async () => {
|
|
60
|
+
const result = await streamingMethod(options);
|
|
61
|
+
return {
|
|
62
|
+
[Symbol.asyncIterator]() {
|
|
63
|
+
let resolveNext = null;
|
|
64
|
+
let rejectNext = null;
|
|
65
|
+
const queue = [];
|
|
66
|
+
let done = false;
|
|
67
|
+
let error = null;
|
|
68
|
+
result.on("chunk", (chunk) => {
|
|
69
|
+
if (resolveNext) {
|
|
70
|
+
resolveNext({ value: chunk, done: false });
|
|
71
|
+
resolveNext = null;
|
|
72
|
+
rejectNext = null;
|
|
73
|
+
} else {
|
|
74
|
+
queue.push(chunk);
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
result.on("close", () => {
|
|
78
|
+
done = true;
|
|
79
|
+
if (resolveNext) {
|
|
80
|
+
resolveNext({ value: undefined, done: true });
|
|
81
|
+
resolveNext = null;
|
|
82
|
+
rejectNext = null;
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
result.on("error", (err) => {
|
|
86
|
+
error = err;
|
|
87
|
+
done = true;
|
|
88
|
+
if (rejectNext) {
|
|
89
|
+
rejectNext(err);
|
|
90
|
+
resolveNext = null;
|
|
91
|
+
rejectNext = null;
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
return {
|
|
95
|
+
next() {
|
|
96
|
+
if (error) {
|
|
97
|
+
return Promise.reject(error);
|
|
98
|
+
}
|
|
99
|
+
if (queue.length > 0) {
|
|
100
|
+
return Promise.resolve({ value: queue.shift(), done: false });
|
|
101
|
+
}
|
|
102
|
+
if (done) {
|
|
103
|
+
return Promise.resolve({ value: undefined, done: true });
|
|
104
|
+
}
|
|
105
|
+
return new Promise((resolve, reject) => {
|
|
106
|
+
resolveNext = resolve;
|
|
107
|
+
rejectNext = reject;
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
function createTypedQueryClient(queryClient, client, contract) {
|
|
116
|
+
const typed = queryClient;
|
|
117
|
+
for (const [name, endpoint] of Object.entries(contract)) {
|
|
118
|
+
if (endpoint.type !== "standard")
|
|
119
|
+
continue;
|
|
120
|
+
const clientMethod = client[name];
|
|
121
|
+
const typedEndpoint = endpoint;
|
|
122
|
+
if (typedEndpoint.method === "GET" || typedEndpoint.method === "HEAD") {
|
|
123
|
+
typed[name] = {
|
|
124
|
+
getQueryData: (queryKey) => queryClient.getQueryData(queryKey),
|
|
125
|
+
setQueryData: (queryKey, updater) => queryClient.setQueryData(queryKey, updater),
|
|
126
|
+
getQueryState: (queryKey) => queryClient.getQueryState(queryKey),
|
|
127
|
+
fetchQuery: ({ queryKey, queryData, ...rest }) => queryClient.fetchQuery({
|
|
128
|
+
queryKey,
|
|
129
|
+
queryFn: () => clientMethod(queryData),
|
|
130
|
+
...rest
|
|
131
|
+
}),
|
|
132
|
+
prefetchQuery: ({ queryKey, queryData, ...rest }) => queryClient.prefetchQuery({
|
|
133
|
+
queryKey,
|
|
134
|
+
queryFn: () => clientMethod(queryData),
|
|
135
|
+
...rest
|
|
136
|
+
}),
|
|
137
|
+
ensureQueryData: ({ queryKey, queryData, ...rest }) => queryClient.ensureQueryData({
|
|
138
|
+
queryKey,
|
|
139
|
+
queryFn: () => clientMethod(queryData),
|
|
140
|
+
...rest
|
|
141
|
+
})
|
|
142
|
+
};
|
|
143
|
+
} else {
|
|
144
|
+
typed[name] = {};
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
return typed;
|
|
148
|
+
}
|
|
149
|
+
function createTanstackQueryApi(client, contract) {
|
|
150
|
+
const endpoints = {};
|
|
39
151
|
for (const [name, endpoint] of Object.entries(contract)) {
|
|
40
152
|
if (endpoint.type === "streaming") {
|
|
41
153
|
const streamMethod = client[name];
|
|
42
|
-
|
|
43
|
-
stream: streamMethod
|
|
154
|
+
endpoints[name] = {
|
|
155
|
+
stream: streamMethod,
|
|
156
|
+
useStreamQuery: ({ queryKey, queryData, refetchMode, ...rest }) => {
|
|
157
|
+
const result = import_react_query.useQuery({
|
|
158
|
+
queryKey,
|
|
159
|
+
queryFn: import_react_query.experimental_streamedQuery({
|
|
160
|
+
streamFn: streamToAsyncIterable(streamMethod, queryData),
|
|
161
|
+
refetchMode
|
|
162
|
+
}),
|
|
163
|
+
...rest
|
|
164
|
+
});
|
|
165
|
+
return {
|
|
166
|
+
...result,
|
|
167
|
+
contractEndpoint: endpoint
|
|
168
|
+
};
|
|
169
|
+
}
|
|
44
170
|
};
|
|
45
171
|
continue;
|
|
46
172
|
}
|
|
47
173
|
if (endpoint.type === "sse") {
|
|
48
174
|
const connectMethod = client[name];
|
|
49
|
-
|
|
175
|
+
endpoints[name] = {
|
|
50
176
|
connect: connectMethod
|
|
51
177
|
};
|
|
52
178
|
continue;
|
|
53
179
|
}
|
|
180
|
+
if (endpoint.type === "download") {
|
|
181
|
+
const downloadMethod = client[name];
|
|
182
|
+
endpoints[name] = {
|
|
183
|
+
download: downloadMethod
|
|
184
|
+
};
|
|
185
|
+
continue;
|
|
186
|
+
}
|
|
54
187
|
const method = endpoint.method;
|
|
55
188
|
const clientMethod = client[name];
|
|
56
189
|
if (method === "GET" || method === "HEAD") {
|
|
57
|
-
|
|
58
|
-
useQuery: (
|
|
59
|
-
|
|
60
|
-
queryKey
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
options.query ?? null,
|
|
64
|
-
options.headers ?? null,
|
|
65
|
-
options.body ?? null
|
|
66
|
-
],
|
|
67
|
-
queryFn: () => clientMethod(options),
|
|
68
|
-
...queryOptions
|
|
190
|
+
endpoints[name] = {
|
|
191
|
+
useQuery: ({ queryKey, queryData, ...rest }) => {
|
|
192
|
+
const result = import_react_query.useQuery({
|
|
193
|
+
queryKey,
|
|
194
|
+
queryFn: () => clientMethod(queryData),
|
|
195
|
+
...rest
|
|
69
196
|
});
|
|
197
|
+
return {
|
|
198
|
+
...result,
|
|
199
|
+
contractEndpoint: endpoint
|
|
200
|
+
};
|
|
70
201
|
},
|
|
71
|
-
useSuspenseQuery: (
|
|
72
|
-
|
|
73
|
-
queryKey
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
options.query ?? null,
|
|
77
|
-
options.headers ?? null,
|
|
78
|
-
options.body ?? null
|
|
79
|
-
],
|
|
80
|
-
queryFn: () => clientMethod(options),
|
|
81
|
-
...queryOptions
|
|
202
|
+
useSuspenseQuery: ({ queryKey, queryData, ...rest }) => {
|
|
203
|
+
const result = import_react_query.useSuspenseQuery({
|
|
204
|
+
queryKey,
|
|
205
|
+
queryFn: () => clientMethod(queryData),
|
|
206
|
+
...rest
|
|
82
207
|
});
|
|
83
|
-
|
|
208
|
+
return {
|
|
209
|
+
...result,
|
|
210
|
+
contractEndpoint: endpoint
|
|
211
|
+
};
|
|
212
|
+
},
|
|
213
|
+
useInfiniteQuery: ({
|
|
214
|
+
queryKey,
|
|
215
|
+
queryData,
|
|
216
|
+
...rest
|
|
217
|
+
}) => {
|
|
218
|
+
const result = import_react_query.useInfiniteQuery({
|
|
219
|
+
queryKey,
|
|
220
|
+
queryFn: (ctx) => clientMethod(queryData({ pageParam: ctx.pageParam })),
|
|
221
|
+
...rest
|
|
222
|
+
});
|
|
223
|
+
return {
|
|
224
|
+
...result,
|
|
225
|
+
contractEndpoint: endpoint
|
|
226
|
+
};
|
|
227
|
+
},
|
|
228
|
+
useSuspenseInfiniteQuery: ({
|
|
229
|
+
queryKey,
|
|
230
|
+
queryData,
|
|
231
|
+
...rest
|
|
232
|
+
}) => {
|
|
233
|
+
const result = import_react_query.useSuspenseInfiniteQuery({
|
|
234
|
+
queryKey,
|
|
235
|
+
queryFn: (ctx) => clientMethod(queryData({ pageParam: ctx.pageParam })),
|
|
236
|
+
...rest
|
|
237
|
+
});
|
|
238
|
+
return {
|
|
239
|
+
...result,
|
|
240
|
+
contractEndpoint: endpoint
|
|
241
|
+
};
|
|
242
|
+
},
|
|
243
|
+
query: (options) => clientMethod(options)
|
|
84
244
|
};
|
|
85
245
|
} else {
|
|
86
|
-
|
|
87
|
-
useMutation: (
|
|
88
|
-
|
|
89
|
-
mutationFn: (
|
|
90
|
-
...
|
|
246
|
+
endpoints[name] = {
|
|
247
|
+
useMutation: (options) => {
|
|
248
|
+
const result = import_react_query.useMutation({
|
|
249
|
+
mutationFn: (data) => clientMethod(data),
|
|
250
|
+
...options
|
|
91
251
|
});
|
|
92
|
-
|
|
252
|
+
return {
|
|
253
|
+
...result,
|
|
254
|
+
contractEndpoint: endpoint
|
|
255
|
+
};
|
|
256
|
+
},
|
|
257
|
+
mutate: (options) => clientMethod(options)
|
|
93
258
|
};
|
|
94
259
|
}
|
|
95
260
|
}
|
|
96
|
-
return
|
|
261
|
+
return endpoints;
|
|
97
262
|
}
|
|
98
263
|
})
|
|
99
264
|
|
|
100
|
-
//# debugId=
|
|
265
|
+
//# debugId=7C0EB4EFF12A14A164756E2164756E21
|
package/dist/cjs/index.cjs.map
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../index.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"import type {\n Client,\n ClientMethod,\n EndpointRequestOptions,\n EndpointResponse,\n SSEClientMethod,\n StreamingClientMethod,\n} from '@richie-rpc/client';\nimport type {\n Contract,\n SSEEndpointDefinition,\n StandardEndpointDefinition,\n StreamingEndpointDefinition,\n} from '@richie-rpc/core';\nimport {\n type UseMutationOptions,\n type UseMutationResult,\n type UseQueryOptions,\n type UseQueryResult,\n type UseSuspenseQueryOptions,\n type UseSuspenseQueryResult,\n useMutation,\n useQuery,\n useSuspenseQuery,\n} from '@tanstack/react-query';\n\n// HTTP methods that should use query hooks (read operations)\ntype QueryMethods = 'GET' | 'HEAD';\n\n// HTTP methods that should use mutation hooks (write operations)\ntype MutationMethods = 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'OPTIONS';\n\n/**\n * Hook wrapper for query endpoints (GET, HEAD)\n * Provides useQuery and useSuspenseQuery methods\n */\nexport type QueryHook<T extends StandardEndpointDefinition> = {\n /**\n * Standard query hook that returns loading states\n */\n useQuery: (\n options: EndpointRequestOptions<T>,\n queryOptions?: Omit<UseQueryOptions<EndpointResponse<T>, Error>, 'queryKey' | 'queryFn'>,\n ) => UseQueryResult<EndpointResponse<T>, Error>;\n\n /**\n * Suspense-enabled query hook that throws promises for React Suspense\n */\n useSuspenseQuery: (\n options: EndpointRequestOptions<T>,\n queryOptions?: Omit<\n UseSuspenseQueryOptions<EndpointResponse<T>, Error>,\n 'queryKey' | 'queryFn'\n >,\n ) => UseSuspenseQueryResult<EndpointResponse<T>, Error>;\n};\n\n/**\n * Hook wrapper for mutation endpoints (POST, PUT, PATCH, DELETE)\n * Provides useMutation method\n */\nexport type MutationHook<T extends StandardEndpointDefinition> = {\n /**\n * Mutation hook for write operations\n */\n useMutation: (\n mutationOptions?: Omit<\n UseMutationOptions<EndpointResponse<T>, Error, EndpointRequestOptions<T>>,\n 'mutationFn'\n >,\n ) => UseMutationResult<EndpointResponse<T>, Error, EndpointRequestOptions<T>>;\n};\n\n/**\n * Conditionally apply hook type based on HTTP method\n */\nexport type EndpointHook<T extends StandardEndpointDefinition> = T['method'] extends QueryMethods\n ? QueryHook<T>\n : T['method'] extends MutationMethods\n ? MutationHook<T>\n : never;\n\n/**\n * Hook wrapper for streaming endpoints\n * Exposes the streaming client method directly since React Query\n * doesn't fit well with long-lived streaming connections\n */\nexport type StreamingHook<T extends StreamingEndpointDefinition> = {\n /**\n * Start a streaming request\n */\n stream: StreamingClientMethod<T>;\n};\n\n/**\n * Hook wrapper for SSE endpoints\n * Exposes the SSE client method directly since React Query\n * doesn't fit well with long-lived SSE connections\n */\nexport type SSEHook<T extends SSEEndpointDefinition> = {\n /**\n * Create an SSE connection\n */\n connect: SSEClientMethod<T>;\n};\n\n/**\n * Complete hooks object for a contract\n * Each endpoint gets appropriate hooks based on its type and HTTP method\n */\nexport type Hooks<T extends Contract> = {\n [K in keyof T]: T[K] extends StandardEndpointDefinition\n ? EndpointHook<T[K]>\n : T[K] extends StreamingEndpointDefinition\n ? StreamingHook<T[K]>\n : T[K] extends SSEEndpointDefinition\n ? SSEHook<T[K]>\n : never;\n};\n\n/**\n * Create typed React hooks for all endpoints in a contract\n *\n * Query endpoints (GET, HEAD) get useQuery and useSuspenseQuery methods\n * Mutation endpoints (POST, PUT, PATCH, DELETE) get useMutation method\n *\n * @param client - The typed client created with createClient()\n * @param contract - The contract definition\n * @returns Hooks object with methods for each endpoint\n *\n * @example\n * ```tsx\n * const client = createClient(contract, { baseUrl: 'http://localhost:3000' });\n * const hooks = createHooks(client, contract);\n *\n * // In a component - Query\n * function UserList() {\n * const { data, isLoading } = hooks.listUsers.useQuery({\n * query: { limit: \"10\" }\n * });\n * // ...\n * }\n *\n * // In a component - Mutation\n * function CreateUser() {\n * const mutation = hooks.createUser.useMutation();\n * return (\n * <button onClick={() => mutation.mutate({\n * body: { name: \"Alice\", email: \"alice@example.com\" }\n * })}>\n * Create User\n * </button>\n * );\n * }\n * ```\n */\nexport function createHooks<T extends Contract>(client: Client<T>, contract: T): Hooks<T> {\n const hooks: Record<string, unknown> = {};\n\n for (const [name, endpoint] of Object.entries(contract)) {\n // Handle streaming endpoints\n if (endpoint.type === 'streaming') {\n const streamMethod = client[\n name as keyof T\n ] as unknown as StreamingClientMethod<StreamingEndpointDefinition>;\n hooks[name] = {\n stream: streamMethod,\n };\n continue;\n }\n\n // Handle SSE endpoints\n if (endpoint.type === 'sse') {\n const connectMethod = client[\n name as keyof T\n ] as unknown as SSEClientMethod<SSEEndpointDefinition>;\n hooks[name] = {\n connect: connectMethod,\n };\n continue;\n }\n\n // Handle standard endpoints\n const method = endpoint.method;\n const clientMethod = client[\n name as keyof T\n ] as unknown as ClientMethod<StandardEndpointDefinition>;\n\n if (method === 'GET' || method === 'HEAD') {\n // Create query hooks for read operations\n hooks[name] = {\n useQuery: (\n options: EndpointRequestOptions<StandardEndpointDefinition>,\n queryOptions?: Omit<\n UseQueryOptions<EndpointResponse<StandardEndpointDefinition>, Error>,\n 'queryKey' | 'queryFn'\n >,\n ) => {\n return useQuery({\n queryKey: [\n name,\n options.params ?? null,\n options.query ?? null,\n options.headers ?? null,\n options.body ?? null,\n ],\n queryFn: () => clientMethod(options),\n ...queryOptions,\n });\n },\n useSuspenseQuery: (\n options: EndpointRequestOptions<StandardEndpointDefinition>,\n queryOptions?: Omit<\n UseSuspenseQueryOptions<EndpointResponse<StandardEndpointDefinition>, Error>,\n 'queryKey' | 'queryFn'\n >,\n ) => {\n return useSuspenseQuery({\n queryKey: [\n name,\n options.params ?? null,\n options.query ?? null,\n options.headers ?? null,\n options.body ?? null,\n ],\n queryFn: () => clientMethod(options),\n ...queryOptions,\n });\n },\n };\n } else {\n // Create mutation hooks for write operations\n hooks[name] = {\n useMutation: (\n mutationOptions?: Omit<\n UseMutationOptions<\n EndpointResponse<StandardEndpointDefinition>,\n Error,\n EndpointRequestOptions<StandardEndpointDefinition>\n >,\n 'mutationFn'\n >,\n ) => {\n return useMutation({\n mutationFn: (options: EndpointRequestOptions<StandardEndpointDefinition>) =>\n clientMethod(options),\n ...mutationOptions,\n });\n },\n };\n }\n }\n\n return hooks as Hooks<T>;\n}\n"
|
|
5
|
+
"/* eslint-disable @typescript-eslint/no-explicit-any */\nimport type {\n Client,\n ClientMethod,\n DownloadClientMethod,\n EndpointRequestOptions,\n EndpointResponse,\n SSEClientMethod,\n StreamingClientMethod,\n} from '@richie-rpc/client';\nimport type {\n Contract,\n DownloadEndpointDefinition,\n ExtractChunk,\n SSEEndpointDefinition,\n StandardEndpointDefinition,\n StreamingEndpointDefinition,\n} from '@richie-rpc/core';\nimport {\n type InfiniteData,\n type QueryClient,\n type QueryKey,\n type Updater,\n type UseInfiniteQueryOptions,\n type UseInfiniteQueryResult,\n type UseMutationOptions,\n type UseMutationResult,\n type UseQueryOptions,\n type UseQueryResult,\n type UseSuspenseInfiniteQueryOptions,\n type UseSuspenseInfiniteQueryResult,\n type UseSuspenseQueryOptions,\n type UseSuspenseQueryResult,\n experimental_streamedQuery as streamedQuery,\n useInfiniteQuery,\n useMutation,\n useQuery,\n useSuspenseInfiniteQuery,\n useSuspenseQuery,\n} from '@tanstack/react-query';\n\n// ============================================\n// HTTP Method Categories\n// ============================================\n\ntype QueryMethods = 'GET' | 'HEAD';\ntype MutationMethods = 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'OPTIONS';\n\n// ============================================\n// Query Options Types (ts-rest style)\n// ============================================\n\n/**\n * Unified query options - combines queryKey, queryData, and TanStack Query options\n */\nexport type TsrQueryOptions<T extends StandardEndpointDefinition> = Omit<\n UseQueryOptions<EndpointResponse<T>, Error>,\n 'queryKey' | 'queryFn'\n> & {\n queryKey: QueryKey;\n queryData: EndpointRequestOptions<T>;\n};\n\n/**\n * Suspense query options\n */\nexport type TsrSuspenseQueryOptions<T extends StandardEndpointDefinition> = Omit<\n UseSuspenseQueryOptions<EndpointResponse<T>, Error>,\n 'queryKey' | 'queryFn'\n> & {\n queryKey: QueryKey;\n queryData: EndpointRequestOptions<T>;\n};\n\n/**\n * Infinite query options - queryData is a function that receives pageParam\n */\nexport type TsrInfiniteQueryOptions<\n T extends StandardEndpointDefinition,\n TPageParam = unknown,\n> = Omit<\n UseInfiniteQueryOptions<EndpointResponse<T>, Error, unknown, QueryKey, TPageParam>,\n 'queryKey' | 'queryFn'\n> & {\n queryKey: QueryKey;\n queryData: (context: { pageParam: TPageParam }) => EndpointRequestOptions<T>;\n};\n\n/**\n * Suspense infinite query options\n */\nexport type TsrSuspenseInfiniteQueryOptions<\n T extends StandardEndpointDefinition,\n TPageParam = unknown,\n> = Omit<\n UseSuspenseInfiniteQueryOptions<EndpointResponse<T>, Error, unknown, QueryKey, TPageParam>,\n 'queryKey' | 'queryFn'\n> & {\n queryKey: QueryKey;\n queryData: (context: { pageParam: TPageParam }) => EndpointRequestOptions<T>;\n};\n\n/**\n * Mutation options - same as TanStack Query but typed\n */\nexport type TsrMutationOptions<T extends StandardEndpointDefinition> = Omit<\n UseMutationOptions<EndpointResponse<T>, Error, EndpointRequestOptions<T>>,\n 'mutationFn'\n>;\n\n/**\n * Stream query options for streaming endpoints\n */\nexport type TsrStreamQueryOptions<T extends StreamingEndpointDefinition> = Omit<\n UseQueryOptions<ExtractChunk<T>[], Error>,\n 'queryKey' | 'queryFn'\n> & {\n queryKey: QueryKey;\n queryData: EndpointRequestOptions<T>;\n refetchMode?: 'reset' | 'append' | 'replace';\n};\n\n// ============================================\n// Error Handling Utilities\n// ============================================\n\n/**\n * Response type from hooks - includes status and body like ts-rest\n */\nexport type TsrResponse<T extends StandardEndpointDefinition> = EndpointResponse<T>;\n\n/**\n * Error response type - either fetch error or typed response error\n */\nexport type TsrError =\n | Error\n | {\n status: number;\n data: unknown;\n };\n\n/**\n * Check if an error is a fetch/network error (Error instance, not a response)\n */\nexport function isFetchError(error: unknown): error is Error {\n return error instanceof Error && !('status' in error);\n}\n\n/**\n * Check if error is a response with a status code not defined in the contract\n */\nexport function isUnknownErrorResponse<T extends StandardEndpointDefinition>(\n error: unknown,\n endpoint: T,\n): error is { status: number; data: unknown } {\n if (!error || typeof error !== 'object' || !('status' in error)) {\n return false;\n }\n const status = (error as { status: number }).status;\n return !(status in endpoint.responses);\n}\n\n/**\n * Check if error is either a fetch error or unknown response error\n */\nexport function isNotKnownResponseError<T extends StandardEndpointDefinition>(\n error: unknown,\n endpoint: T,\n): error is Error | { status: number; data: unknown } {\n return isFetchError(error) || isUnknownErrorResponse(error, endpoint);\n}\n\n/**\n * Exhaustive guard for compile-time exhaustiveness checking\n * Use after handling all known error cases to ensure nothing is missed\n */\nexport function exhaustiveGuard(_value: never): never {\n throw new Error(`Unhandled case: ${JSON.stringify(_value)}`);\n}\n\n// ============================================\n// Typed QueryClient Types\n// ============================================\n\n/**\n * Typed query client methods for a single query endpoint\n */\nexport type TypedQueryEndpointClient<T extends StandardEndpointDefinition> = {\n getQueryData: (queryKey: QueryKey) => EndpointResponse<T> | undefined;\n setQueryData: (\n queryKey: QueryKey,\n updater: Updater<EndpointResponse<T> | undefined, EndpointResponse<T> | undefined>,\n ) => EndpointResponse<T> | undefined;\n getQueryState: (queryKey: QueryKey) => ReturnType<QueryClient['getQueryState']>;\n fetchQuery: (options: TsrQueryOptions<T>) => Promise<EndpointResponse<T>>;\n prefetchQuery: (options: TsrQueryOptions<T>) => Promise<void>;\n ensureQueryData: (options: TsrQueryOptions<T>) => Promise<EndpointResponse<T>>;\n};\n\n/**\n * Typed query client methods for a single mutation endpoint\n * Mutations don't have query-specific cache methods\n */\nexport type TypedMutationEndpointClient<_T extends StandardEndpointDefinition> = object;\n\n/**\n * Full typed query client - extends QueryClient with per-endpoint methods\n */\nexport type TypedQueryClient<T extends Contract> = QueryClient & {\n [K in keyof T]: T[K] extends StandardEndpointDefinition\n ? T[K]['method'] extends QueryMethods\n ? TypedQueryEndpointClient<T[K]>\n : TypedMutationEndpointClient<T[K]>\n : Record<string, never>;\n};\n\n// ============================================\n// Endpoint API Types\n// ============================================\n\n/**\n * API for query endpoints (GET, HEAD)\n */\nexport type QueryEndpointApi<T extends StandardEndpointDefinition> = {\n /** Standard query hook */\n useQuery: (options: TsrQueryOptions<T>) => UseQueryResult<EndpointResponse<T>, Error> & {\n contractEndpoint: T;\n };\n /** Suspense query hook */\n useSuspenseQuery: (options: TsrSuspenseQueryOptions<T>) => UseSuspenseQueryResult<EndpointResponse<T>, Error> & {\n contractEndpoint: T;\n };\n /** Infinite query hook */\n useInfiniteQuery: <TPageParam = unknown>(\n options: TsrInfiniteQueryOptions<T, TPageParam>,\n ) => UseInfiniteQueryResult<InfiniteData<EndpointResponse<T>, TPageParam>, Error> & {\n contractEndpoint: T;\n };\n /** Suspense infinite query hook */\n useSuspenseInfiniteQuery: <TPageParam = unknown>(\n options: TsrSuspenseInfiniteQueryOptions<T, TPageParam>,\n ) => UseSuspenseInfiniteQueryResult<InfiniteData<EndpointResponse<T>, TPageParam>, Error> & {\n contractEndpoint: T;\n };\n /** Direct fetch without React Query */\n query: (options: EndpointRequestOptions<T>) => Promise<EndpointResponse<T>>;\n};\n\n/**\n * API for mutation endpoints (POST, PUT, PATCH, DELETE)\n */\nexport type MutationEndpointApi<T extends StandardEndpointDefinition> = {\n /** Mutation hook */\n useMutation: (\n options?: TsrMutationOptions<T>,\n ) => UseMutationResult<EndpointResponse<T>, Error, EndpointRequestOptions<T>> & {\n contractEndpoint: T;\n };\n /** Direct mutate without React Query */\n mutate: (options: EndpointRequestOptions<T>) => Promise<EndpointResponse<T>>;\n};\n\n/**\n * API for streaming endpoints\n */\nexport type StreamingEndpointApi<T extends StreamingEndpointDefinition> = {\n /** Direct stream access (event-based) */\n stream: StreamingClientMethod<T>;\n /** Query hook using experimental streamedQuery */\n useStreamQuery: (options: TsrStreamQueryOptions<T>) => UseQueryResult<ExtractChunk<T>[], Error> & {\n contractEndpoint: T;\n };\n};\n\n/**\n * API for SSE endpoints\n */\nexport type SSEEndpointApi<T extends SSEEndpointDefinition> = {\n /** Direct SSE connection access (event-based) */\n connect: SSEClientMethod<T>;\n};\n\n/**\n * API for download endpoints\n */\nexport type DownloadEndpointApi<T extends DownloadEndpointDefinition> = {\n /** Direct download without React Query */\n download: DownloadClientMethod<T>;\n};\n\n/**\n * Select appropriate API type based on endpoint type\n */\nexport type EndpointApi<T> = T extends StandardEndpointDefinition\n ? T['method'] extends QueryMethods\n ? QueryEndpointApi<T>\n : T['method'] extends MutationMethods\n ? MutationEndpointApi<T>\n : never\n : T extends StreamingEndpointDefinition\n ? StreamingEndpointApi<T>\n : T extends SSEEndpointDefinition\n ? SSEEndpointApi<T>\n : T extends DownloadEndpointDefinition\n ? DownloadEndpointApi<T>\n : never;\n\n// ============================================\n// Main TanStack Query API Type\n// ============================================\n\n/**\n * Full TanStack Query API for a contract\n */\nexport type TanstackQueryApi<T extends Contract> = {\n [K in keyof T]: EndpointApi<T[K]>;\n};\n\n\n// ============================================\n// Async Iterator Adapter for Streaming\n// ============================================\n\n/**\n * Convert StreamingResult to an AsyncIterable for use with streamedQuery\n */\nfunction streamToAsyncIterable<T extends StreamingEndpointDefinition>(\n streamingMethod: StreamingClientMethod<T>,\n options: EndpointRequestOptions<T>,\n): () => Promise<AsyncIterable<ExtractChunk<T>>> {\n return async () => {\n const result = await streamingMethod(options);\n\n return {\n [Symbol.asyncIterator](): AsyncIterator<ExtractChunk<T>> {\n let resolveNext: ((value: IteratorResult<ExtractChunk<T>>) => void) | null = null;\n let rejectNext: ((error: Error) => void) | null = null;\n const queue: ExtractChunk<T>[] = [];\n let done = false;\n let error: Error | null = null;\n\n result.on('chunk', (chunk) => {\n if (resolveNext) {\n resolveNext({ value: chunk, done: false });\n resolveNext = null;\n rejectNext = null;\n } else {\n queue.push(chunk);\n }\n });\n\n result.on('close', () => {\n done = true;\n if (resolveNext) {\n resolveNext({ value: undefined as any, done: true });\n resolveNext = null;\n rejectNext = null;\n }\n });\n\n result.on('error', (err) => {\n error = err;\n done = true;\n if (rejectNext) {\n rejectNext(err);\n resolveNext = null;\n rejectNext = null;\n }\n });\n\n return {\n next(): Promise<IteratorResult<ExtractChunk<T>>> {\n if (error) {\n return Promise.reject(error);\n }\n if (queue.length > 0) {\n return Promise.resolve({ value: queue.shift()!, done: false });\n }\n if (done) {\n return Promise.resolve({ value: undefined as any, done: true });\n }\n return new Promise((resolve, reject) => {\n resolveNext = resolve;\n rejectNext = reject;\n });\n },\n };\n },\n };\n };\n}\n\n// ============================================\n// Create Typed QueryClient\n// ============================================\n\n/**\n * Create a typed QueryClient wrapper with per-endpoint cache methods\n *\n * @param queryClient - The TanStack QueryClient instance\n * @param client - The typed client created with createClient()\n * @param contract - The contract definition\n * @returns A typed QueryClient with per-endpoint methods\n *\n * @example\n * ```tsx\n * const typedQueryClient = createTypedQueryClient(queryClient, client, contract);\n *\n * // Type-safe cache operations\n * typedQueryClient.listUsers.getQueryData(['users']);\n * typedQueryClient.listUsers.setQueryData(['users'], newData);\n * await typedQueryClient.listUsers.prefetchQuery({\n * queryKey: ['users'],\n * queryData: { query: { limit: '10' } }\n * });\n * ```\n */\nexport function createTypedQueryClient<T extends Contract>(\n queryClient: QueryClient,\n client: Client<T>,\n contract: T,\n): TypedQueryClient<T> {\n const typed = queryClient as TypedQueryClient<T>;\n\n for (const [name, endpoint] of Object.entries(contract)) {\n if (endpoint.type !== 'standard') continue;\n\n const clientMethod = client[name as keyof T] as unknown as ClientMethod<StandardEndpointDefinition>;\n const typedEndpoint = endpoint as StandardEndpointDefinition;\n\n if (typedEndpoint.method === 'GET' || typedEndpoint.method === 'HEAD') {\n (typed as any)[name] = {\n getQueryData: (queryKey: QueryKey) => queryClient.getQueryData(queryKey),\n setQueryData: (queryKey: QueryKey, updater: any) => queryClient.setQueryData(queryKey, updater),\n getQueryState: (queryKey: QueryKey) => queryClient.getQueryState(queryKey),\n fetchQuery: ({ queryKey, queryData, ...rest }: TsrQueryOptions<StandardEndpointDefinition>) =>\n queryClient.fetchQuery({\n queryKey,\n queryFn: () => clientMethod(queryData),\n ...rest,\n }),\n prefetchQuery: ({ queryKey, queryData, ...rest }: TsrQueryOptions<StandardEndpointDefinition>) =>\n queryClient.prefetchQuery({\n queryKey,\n queryFn: () => clientMethod(queryData),\n ...rest,\n }),\n ensureQueryData: ({ queryKey, queryData, ...rest }: TsrQueryOptions<StandardEndpointDefinition>) =>\n queryClient.ensureQueryData({\n queryKey,\n queryFn: () => clientMethod(queryData),\n ...rest,\n }),\n } as TypedQueryEndpointClient<StandardEndpointDefinition>;\n } else {\n (typed as any)[name] = {} as TypedMutationEndpointClient<StandardEndpointDefinition>;\n }\n }\n\n return typed;\n}\n\n// ============================================\n// Main Factory Function\n// ============================================\n\n/**\n * Create typed TanStack Query API for a contract\n *\n * @param client - The typed client created with createClient()\n * @param contract - The contract definition\n * @returns API object with hooks for each endpoint\n *\n * @example\n * ```tsx\n * const client = createClient(contract, { baseUrl: 'http://localhost:3000' });\n * const api = createTanstackQueryApi(client, contract);\n *\n * // Use in components - Query\n * function UserList() {\n * const { data, isLoading } = api.listUsers.useQuery({\n * queryKey: ['users'],\n * queryData: { query: { limit: '10' } }\n * });\n * }\n *\n * // Use in components - Mutation\n * function CreateUser() {\n * const { mutate } = api.createUser.useMutation();\n * return (\n * <button onClick={() => mutate({ body: { name: 'Alice' } })}>\n * Create\n * </button>\n * );\n * }\n *\n * // Direct fetch (no hooks)\n * const users = await api.listUsers.query({ query: { limit: '10' } });\n *\n * // Streaming with React Query\n * const { data: chunks, isFetching } = api.streamChat.useStreamQuery({\n * queryKey: ['chat', prompt],\n * queryData: { body: { prompt } }\n * });\n * ```\n */\nexport function createTanstackQueryApi<T extends Contract>(\n client: Client<T>,\n contract: T,\n): TanstackQueryApi<T> {\n // Build endpoint APIs\n const endpoints: Record<string, unknown> = {};\n\n for (const [name, endpoint] of Object.entries(contract)) {\n // Handle streaming endpoints\n if (endpoint.type === 'streaming') {\n const streamMethod = client[name as keyof T] as unknown as StreamingClientMethod<StreamingEndpointDefinition>;\n\n endpoints[name] = {\n stream: streamMethod,\n useStreamQuery: ({ queryKey, queryData, refetchMode, ...rest }: TsrStreamQueryOptions<StreamingEndpointDefinition>) => {\n const result = useQuery({\n queryKey,\n queryFn: streamedQuery({\n streamFn: streamToAsyncIterable(streamMethod, queryData),\n refetchMode,\n }),\n ...rest,\n });\n return {\n ...result,\n contractEndpoint: endpoint,\n };\n },\n } as StreamingEndpointApi<StreamingEndpointDefinition>;\n continue;\n }\n\n // Handle SSE endpoints\n if (endpoint.type === 'sse') {\n const connectMethod = client[name as keyof T] as unknown as SSEClientMethod<SSEEndpointDefinition>;\n endpoints[name] = {\n connect: connectMethod,\n } as SSEEndpointApi<SSEEndpointDefinition>;\n continue;\n }\n\n // Handle download endpoints\n if (endpoint.type === 'download') {\n const downloadMethod = client[name as keyof T] as unknown as DownloadClientMethod<DownloadEndpointDefinition>;\n endpoints[name] = {\n download: downloadMethod,\n } as DownloadEndpointApi<DownloadEndpointDefinition>;\n continue;\n }\n\n // Handle standard endpoints\n const method = endpoint.method;\n const clientMethod = client[name as keyof T] as unknown as ClientMethod<StandardEndpointDefinition>;\n\n if (method === 'GET' || method === 'HEAD') {\n // Query endpoint\n endpoints[name] = {\n useQuery: ({ queryKey, queryData, ...rest }: TsrQueryOptions<StandardEndpointDefinition>) => {\n const result = useQuery({\n queryKey,\n queryFn: () => clientMethod(queryData),\n ...rest,\n });\n return {\n ...result,\n contractEndpoint: endpoint,\n };\n },\n useSuspenseQuery: ({ queryKey, queryData, ...rest }: TsrSuspenseQueryOptions<StandardEndpointDefinition>) => {\n const result = useSuspenseQuery({\n queryKey,\n queryFn: () => clientMethod(queryData),\n ...rest,\n });\n return {\n ...result,\n contractEndpoint: endpoint,\n };\n },\n useInfiniteQuery: <TPageParam = unknown>({\n queryKey,\n queryData,\n ...rest\n }: TsrInfiniteQueryOptions<StandardEndpointDefinition, TPageParam>) => {\n const result = useInfiniteQuery({\n queryKey,\n queryFn: (ctx: { pageParam: TPageParam }) =>\n clientMethod(queryData({ pageParam: ctx.pageParam })),\n ...rest,\n } as any);\n return {\n ...result,\n contractEndpoint: endpoint,\n };\n },\n useSuspenseInfiniteQuery: <TPageParam = unknown>({\n queryKey,\n queryData,\n ...rest\n }: TsrSuspenseInfiniteQueryOptions<StandardEndpointDefinition, TPageParam>) => {\n const result = useSuspenseInfiniteQuery({\n queryKey,\n queryFn: (ctx: { pageParam: TPageParam }) =>\n clientMethod(queryData({ pageParam: ctx.pageParam })),\n ...rest,\n } as any);\n return {\n ...result,\n contractEndpoint: endpoint,\n };\n },\n query: (options: EndpointRequestOptions<StandardEndpointDefinition>) => clientMethod(options),\n } as QueryEndpointApi<StandardEndpointDefinition>;\n } else {\n // Mutation endpoint\n endpoints[name] = {\n useMutation: (options?: TsrMutationOptions<StandardEndpointDefinition>) => {\n const result = useMutation({\n mutationFn: (data: EndpointRequestOptions<StandardEndpointDefinition>) => clientMethod(data),\n ...options,\n });\n return {\n ...result,\n contractEndpoint: endpoint,\n };\n },\n mutate: (options: EndpointRequestOptions<StandardEndpointDefinition>) => clientMethod(options),\n } as MutationEndpointApi<StandardEndpointDefinition>;\n }\n }\n\n return endpoints as TanstackQueryApi<T>;\n}\n"
|
|
6
6
|
],
|
|
7
|
-
"mappings": "
|
|
8
|
-
"debugId": "
|
|
7
|
+
"mappings": "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",
|
|
8
|
+
"debugId": "7C0EB4EFF12A14A164756E2164756E21",
|
|
9
9
|
"names": []
|
|
10
10
|
}
|
package/dist/cjs/package.json
CHANGED
package/dist/mjs/index.mjs
CHANGED
|
@@ -1,73 +1,241 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
// packages/react-query/index.ts
|
|
3
3
|
import {
|
|
4
|
+
experimental_streamedQuery as streamedQuery,
|
|
5
|
+
useInfiniteQuery,
|
|
4
6
|
useMutation,
|
|
5
7
|
useQuery,
|
|
8
|
+
useSuspenseInfiniteQuery,
|
|
6
9
|
useSuspenseQuery
|
|
7
10
|
} from "@tanstack/react-query";
|
|
8
|
-
function
|
|
9
|
-
|
|
11
|
+
function isFetchError(error) {
|
|
12
|
+
return error instanceof Error && !("status" in error);
|
|
13
|
+
}
|
|
14
|
+
function isUnknownErrorResponse(error, endpoint) {
|
|
15
|
+
if (!error || typeof error !== "object" || !("status" in error)) {
|
|
16
|
+
return false;
|
|
17
|
+
}
|
|
18
|
+
const status = error.status;
|
|
19
|
+
return !(status in endpoint.responses);
|
|
20
|
+
}
|
|
21
|
+
function isNotKnownResponseError(error, endpoint) {
|
|
22
|
+
return isFetchError(error) || isUnknownErrorResponse(error, endpoint);
|
|
23
|
+
}
|
|
24
|
+
function exhaustiveGuard(_value) {
|
|
25
|
+
throw new Error(`Unhandled case: ${JSON.stringify(_value)}`);
|
|
26
|
+
}
|
|
27
|
+
function streamToAsyncIterable(streamingMethod, options) {
|
|
28
|
+
return async () => {
|
|
29
|
+
const result = await streamingMethod(options);
|
|
30
|
+
return {
|
|
31
|
+
[Symbol.asyncIterator]() {
|
|
32
|
+
let resolveNext = null;
|
|
33
|
+
let rejectNext = null;
|
|
34
|
+
const queue = [];
|
|
35
|
+
let done = false;
|
|
36
|
+
let error = null;
|
|
37
|
+
result.on("chunk", (chunk) => {
|
|
38
|
+
if (resolveNext) {
|
|
39
|
+
resolveNext({ value: chunk, done: false });
|
|
40
|
+
resolveNext = null;
|
|
41
|
+
rejectNext = null;
|
|
42
|
+
} else {
|
|
43
|
+
queue.push(chunk);
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
result.on("close", () => {
|
|
47
|
+
done = true;
|
|
48
|
+
if (resolveNext) {
|
|
49
|
+
resolveNext({ value: undefined, done: true });
|
|
50
|
+
resolveNext = null;
|
|
51
|
+
rejectNext = null;
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
result.on("error", (err) => {
|
|
55
|
+
error = err;
|
|
56
|
+
done = true;
|
|
57
|
+
if (rejectNext) {
|
|
58
|
+
rejectNext(err);
|
|
59
|
+
resolveNext = null;
|
|
60
|
+
rejectNext = null;
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
return {
|
|
64
|
+
next() {
|
|
65
|
+
if (error) {
|
|
66
|
+
return Promise.reject(error);
|
|
67
|
+
}
|
|
68
|
+
if (queue.length > 0) {
|
|
69
|
+
return Promise.resolve({ value: queue.shift(), done: false });
|
|
70
|
+
}
|
|
71
|
+
if (done) {
|
|
72
|
+
return Promise.resolve({ value: undefined, done: true });
|
|
73
|
+
}
|
|
74
|
+
return new Promise((resolve, reject) => {
|
|
75
|
+
resolveNext = resolve;
|
|
76
|
+
rejectNext = reject;
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
function createTypedQueryClient(queryClient, client, contract) {
|
|
85
|
+
const typed = queryClient;
|
|
86
|
+
for (const [name, endpoint] of Object.entries(contract)) {
|
|
87
|
+
if (endpoint.type !== "standard")
|
|
88
|
+
continue;
|
|
89
|
+
const clientMethod = client[name];
|
|
90
|
+
const typedEndpoint = endpoint;
|
|
91
|
+
if (typedEndpoint.method === "GET" || typedEndpoint.method === "HEAD") {
|
|
92
|
+
typed[name] = {
|
|
93
|
+
getQueryData: (queryKey) => queryClient.getQueryData(queryKey),
|
|
94
|
+
setQueryData: (queryKey, updater) => queryClient.setQueryData(queryKey, updater),
|
|
95
|
+
getQueryState: (queryKey) => queryClient.getQueryState(queryKey),
|
|
96
|
+
fetchQuery: ({ queryKey, queryData, ...rest }) => queryClient.fetchQuery({
|
|
97
|
+
queryKey,
|
|
98
|
+
queryFn: () => clientMethod(queryData),
|
|
99
|
+
...rest
|
|
100
|
+
}),
|
|
101
|
+
prefetchQuery: ({ queryKey, queryData, ...rest }) => queryClient.prefetchQuery({
|
|
102
|
+
queryKey,
|
|
103
|
+
queryFn: () => clientMethod(queryData),
|
|
104
|
+
...rest
|
|
105
|
+
}),
|
|
106
|
+
ensureQueryData: ({ queryKey, queryData, ...rest }) => queryClient.ensureQueryData({
|
|
107
|
+
queryKey,
|
|
108
|
+
queryFn: () => clientMethod(queryData),
|
|
109
|
+
...rest
|
|
110
|
+
})
|
|
111
|
+
};
|
|
112
|
+
} else {
|
|
113
|
+
typed[name] = {};
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
return typed;
|
|
117
|
+
}
|
|
118
|
+
function createTanstackQueryApi(client, contract) {
|
|
119
|
+
const endpoints = {};
|
|
10
120
|
for (const [name, endpoint] of Object.entries(contract)) {
|
|
11
121
|
if (endpoint.type === "streaming") {
|
|
12
122
|
const streamMethod = client[name];
|
|
13
|
-
|
|
14
|
-
stream: streamMethod
|
|
123
|
+
endpoints[name] = {
|
|
124
|
+
stream: streamMethod,
|
|
125
|
+
useStreamQuery: ({ queryKey, queryData, refetchMode, ...rest }) => {
|
|
126
|
+
const result = useQuery({
|
|
127
|
+
queryKey,
|
|
128
|
+
queryFn: streamedQuery({
|
|
129
|
+
streamFn: streamToAsyncIterable(streamMethod, queryData),
|
|
130
|
+
refetchMode
|
|
131
|
+
}),
|
|
132
|
+
...rest
|
|
133
|
+
});
|
|
134
|
+
return {
|
|
135
|
+
...result,
|
|
136
|
+
contractEndpoint: endpoint
|
|
137
|
+
};
|
|
138
|
+
}
|
|
15
139
|
};
|
|
16
140
|
continue;
|
|
17
141
|
}
|
|
18
142
|
if (endpoint.type === "sse") {
|
|
19
143
|
const connectMethod = client[name];
|
|
20
|
-
|
|
144
|
+
endpoints[name] = {
|
|
21
145
|
connect: connectMethod
|
|
22
146
|
};
|
|
23
147
|
continue;
|
|
24
148
|
}
|
|
149
|
+
if (endpoint.type === "download") {
|
|
150
|
+
const downloadMethod = client[name];
|
|
151
|
+
endpoints[name] = {
|
|
152
|
+
download: downloadMethod
|
|
153
|
+
};
|
|
154
|
+
continue;
|
|
155
|
+
}
|
|
25
156
|
const method = endpoint.method;
|
|
26
157
|
const clientMethod = client[name];
|
|
27
158
|
if (method === "GET" || method === "HEAD") {
|
|
28
|
-
|
|
29
|
-
useQuery: (
|
|
30
|
-
|
|
31
|
-
queryKey
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
options.query ?? null,
|
|
35
|
-
options.headers ?? null,
|
|
36
|
-
options.body ?? null
|
|
37
|
-
],
|
|
38
|
-
queryFn: () => clientMethod(options),
|
|
39
|
-
...queryOptions
|
|
159
|
+
endpoints[name] = {
|
|
160
|
+
useQuery: ({ queryKey, queryData, ...rest }) => {
|
|
161
|
+
const result = useQuery({
|
|
162
|
+
queryKey,
|
|
163
|
+
queryFn: () => clientMethod(queryData),
|
|
164
|
+
...rest
|
|
40
165
|
});
|
|
166
|
+
return {
|
|
167
|
+
...result,
|
|
168
|
+
contractEndpoint: endpoint
|
|
169
|
+
};
|
|
41
170
|
},
|
|
42
|
-
useSuspenseQuery: (
|
|
43
|
-
|
|
44
|
-
queryKey
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
options.query ?? null,
|
|
48
|
-
options.headers ?? null,
|
|
49
|
-
options.body ?? null
|
|
50
|
-
],
|
|
51
|
-
queryFn: () => clientMethod(options),
|
|
52
|
-
...queryOptions
|
|
171
|
+
useSuspenseQuery: ({ queryKey, queryData, ...rest }) => {
|
|
172
|
+
const result = useSuspenseQuery({
|
|
173
|
+
queryKey,
|
|
174
|
+
queryFn: () => clientMethod(queryData),
|
|
175
|
+
...rest
|
|
53
176
|
});
|
|
54
|
-
|
|
177
|
+
return {
|
|
178
|
+
...result,
|
|
179
|
+
contractEndpoint: endpoint
|
|
180
|
+
};
|
|
181
|
+
},
|
|
182
|
+
useInfiniteQuery: ({
|
|
183
|
+
queryKey,
|
|
184
|
+
queryData,
|
|
185
|
+
...rest
|
|
186
|
+
}) => {
|
|
187
|
+
const result = useInfiniteQuery({
|
|
188
|
+
queryKey,
|
|
189
|
+
queryFn: (ctx) => clientMethod(queryData({ pageParam: ctx.pageParam })),
|
|
190
|
+
...rest
|
|
191
|
+
});
|
|
192
|
+
return {
|
|
193
|
+
...result,
|
|
194
|
+
contractEndpoint: endpoint
|
|
195
|
+
};
|
|
196
|
+
},
|
|
197
|
+
useSuspenseInfiniteQuery: ({
|
|
198
|
+
queryKey,
|
|
199
|
+
queryData,
|
|
200
|
+
...rest
|
|
201
|
+
}) => {
|
|
202
|
+
const result = useSuspenseInfiniteQuery({
|
|
203
|
+
queryKey,
|
|
204
|
+
queryFn: (ctx) => clientMethod(queryData({ pageParam: ctx.pageParam })),
|
|
205
|
+
...rest
|
|
206
|
+
});
|
|
207
|
+
return {
|
|
208
|
+
...result,
|
|
209
|
+
contractEndpoint: endpoint
|
|
210
|
+
};
|
|
211
|
+
},
|
|
212
|
+
query: (options) => clientMethod(options)
|
|
55
213
|
};
|
|
56
214
|
} else {
|
|
57
|
-
|
|
58
|
-
useMutation: (
|
|
59
|
-
|
|
60
|
-
mutationFn: (
|
|
61
|
-
...
|
|
215
|
+
endpoints[name] = {
|
|
216
|
+
useMutation: (options) => {
|
|
217
|
+
const result = useMutation({
|
|
218
|
+
mutationFn: (data) => clientMethod(data),
|
|
219
|
+
...options
|
|
62
220
|
});
|
|
63
|
-
|
|
221
|
+
return {
|
|
222
|
+
...result,
|
|
223
|
+
contractEndpoint: endpoint
|
|
224
|
+
};
|
|
225
|
+
},
|
|
226
|
+
mutate: (options) => clientMethod(options)
|
|
64
227
|
};
|
|
65
228
|
}
|
|
66
229
|
}
|
|
67
|
-
return
|
|
230
|
+
return endpoints;
|
|
68
231
|
}
|
|
69
232
|
export {
|
|
70
|
-
|
|
233
|
+
isUnknownErrorResponse,
|
|
234
|
+
isNotKnownResponseError,
|
|
235
|
+
isFetchError,
|
|
236
|
+
exhaustiveGuard,
|
|
237
|
+
createTypedQueryClient,
|
|
238
|
+
createTanstackQueryApi
|
|
71
239
|
};
|
|
72
240
|
|
|
73
|
-
//# debugId=
|
|
241
|
+
//# debugId=8C0C3CC1741EF8A064756E2164756E21
|