@tuyau/react-query 1.0.0-beta.0 → 1.0.0-beta.2
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/build/index.d.ts +47 -45
- package/build/index.js +25 -9
- package/package.json +11 -7
package/build/index.d.ts
CHANGED
|
@@ -1,23 +1,24 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { SchemaEndpoint, RawRequestArgs, TuyauRegistry, InferTree, AdonisEndpoint, InferRoutes } from '@tuyau/core/types';
|
|
2
2
|
import * as _tanstack_react_query from '@tanstack/react-query';
|
|
3
|
-
import { SkipToken, DataTag, QueryFilters, WithRequired as WithRequired$1, UseMutationOptions, InfiniteData, InfiniteQueryObserverOptions, DefinedInitialDataOptions, UndefinedInitialDataOptions, UnusedSkipTokenOptions
|
|
3
|
+
import { SkipToken, DataTag, QueryFilters, WithRequired as WithRequired$1, UseMutationOptions, InfiniteData, InfiniteQueryObserverOptions, DefinedInitialDataOptions, UndefinedInitialDataOptions, UnusedSkipTokenOptions } from '@tanstack/react-query';
|
|
4
4
|
import { Tuyau } from '@tuyau/core/client';
|
|
5
5
|
|
|
6
|
+
type Response$2<E extends SchemaEndpoint> = E['types']['response'];
|
|
6
7
|
/**
|
|
7
8
|
* Decorate query endpoints with Tanstack queries abilities
|
|
8
9
|
*/
|
|
9
|
-
interface DecorateQueryFn<EDef extends
|
|
10
|
+
interface DecorateQueryFn<EDef extends SchemaEndpoint> {
|
|
10
11
|
queryOptions: TuyauReactQueryOptions<EDef>;
|
|
11
|
-
queryKey: (args?: RawRequestArgs<EDef>) => DataTag<TuyauQueryKey, EDef
|
|
12
|
-
queryFilter: (args?: RawRequestArgs<EDef>, filters?: QueryFilters<DataTag<TuyauQueryKey, EDef
|
|
12
|
+
queryKey: (args?: RawRequestArgs<EDef>) => DataTag<TuyauQueryKey, Response$2<EDef>>;
|
|
13
|
+
queryFilter: (args?: RawRequestArgs<EDef>, filters?: QueryFilters<DataTag<TuyauQueryKey, Response$2<EDef>>>) => WithRequired$1<QueryFilters<DataTag<TuyauQueryKey, Response$2<EDef>>>, 'queryKey'>;
|
|
13
14
|
}
|
|
14
15
|
/**
|
|
15
16
|
* Type definition for query options with overloads for different scenarios
|
|
16
17
|
*/
|
|
17
|
-
interface TuyauReactQueryOptions<EDef extends
|
|
18
|
-
<TData = EDef
|
|
19
|
-
<TData = EDef
|
|
20
|
-
<TData = EDef
|
|
18
|
+
interface TuyauReactQueryOptions<EDef extends SchemaEndpoint> {
|
|
19
|
+
<TData = Response$2<EDef>>(input: RawRequestArgs<EDef> | SkipToken, opts: DefinedTuyauQueryOptionsIn<Response$2<EDef>, TData, unknown>): DefinedTuyauQueryOptionsOut<Response$2<EDef>, TData, unknown>;
|
|
20
|
+
<TData = Response$2<EDef>>(input: RawRequestArgs<EDef>, opts?: UnusedSkipTokenTuyauQueryOptionsIn<Response$2<EDef>, TData, unknown>): UnusedSkipTokenTuyauQueryOptionsOut<Response$2<EDef>, TData, unknown>;
|
|
21
|
+
<TData = Response$2<EDef>>(input?: RawRequestArgs<EDef> | SkipToken, opts?: UndefinedTuyauQueryOptionsIn<Response$2<EDef>, TData, unknown>): UndefinedTuyauQueryOptionsOut<Response$2<EDef>, TData, unknown>;
|
|
21
22
|
}
|
|
22
23
|
|
|
23
24
|
/**
|
|
@@ -30,18 +31,19 @@ type DistributiveOmit<TObj, TKey extends keyof any> = TObj extends any ? Omit<TO
|
|
|
30
31
|
type WithRequired<T, K extends keyof T> = T & Required<Pick<T, K>>;
|
|
31
32
|
|
|
32
33
|
type ReservedOptions = 'mutationKey' | 'mutationFn';
|
|
34
|
+
type Response$1<E extends SchemaEndpoint> = E['types']['response'];
|
|
33
35
|
interface TuyauMutationOptionsIn<TInput, TError, TOutput, TContext> extends DistributiveOmit<UseMutationOptions<TOutput, TError, TInput, TContext>, ReservedOptions>, TuyauQueryBaseOptions {
|
|
34
36
|
}
|
|
35
37
|
interface TuyauMutationOptionsOut<TInput, TError, TOutput, TContext> extends UseMutationOptions<TOutput, TError, TInput, TContext> {
|
|
36
38
|
mutationKey: TuyauMutationKey;
|
|
37
39
|
}
|
|
38
|
-
interface TuyauReactMutationOptions<TDef extends
|
|
39
|
-
<TContext = unknown>(opts?: TuyauMutationOptionsIn<RawRequestArgs<TDef>, any, TDef
|
|
40
|
+
interface TuyauReactMutationOptions<TDef extends SchemaEndpoint> {
|
|
41
|
+
<TContext = unknown>(opts?: TuyauMutationOptionsIn<RawRequestArgs<TDef>, any, Response$1<TDef>, TContext>): TuyauMutationOptionsOut<RawRequestArgs<TDef>, any, Response$1<TDef>, TContext>;
|
|
40
42
|
}
|
|
41
43
|
declare function getMutationKeyInternal(options: {
|
|
42
44
|
segments: string[];
|
|
43
45
|
}): TuyauMutationKey;
|
|
44
|
-
interface DecorateMutationFn<EDef extends
|
|
46
|
+
interface DecorateMutationFn<EDef extends SchemaEndpoint> {
|
|
45
47
|
mutationOptions: TuyauReactMutationOptions<EDef>;
|
|
46
48
|
mutationKey: () => TuyauMutationKey;
|
|
47
49
|
}
|
|
@@ -52,6 +54,7 @@ interface TuyauMutationOptionsOptions {
|
|
|
52
54
|
}
|
|
53
55
|
declare function tuyauMutationOptions(options: TuyauMutationOptionsOptions): _tanstack_react_query.WithRequired<UseMutationOptions<unknown, any, any, any>, "mutationKey">;
|
|
54
56
|
|
|
57
|
+
type Response<E extends SchemaEndpoint> = E['types']['response'];
|
|
55
58
|
/**
|
|
56
59
|
* Infinite query options input type
|
|
57
60
|
*/
|
|
@@ -72,17 +75,17 @@ interface TuyauInfiniteQueryOptionsOut<TQueryFnData, TError, TData> extends Omit
|
|
|
72
75
|
/**
|
|
73
76
|
* Type definition for infinite query options
|
|
74
77
|
*/
|
|
75
|
-
interface TuyauReactInfiniteQueryOptions<EDef extends
|
|
76
|
-
<TData = InfiniteData<EDef
|
|
77
|
-
<TData = InfiniteData<EDef
|
|
78
|
+
interface TuyauReactInfiniteQueryOptions<EDef extends SchemaEndpoint> {
|
|
79
|
+
<TData = InfiniteData<Response<EDef>>>(input: RawRequestArgs<EDef> | SkipToken, opts: TuyauInfiniteQueryOptionsIn<Response<EDef>, unknown, TData>): TuyauInfiniteQueryOptionsOut<Response<EDef>, unknown, TData>;
|
|
80
|
+
<TData = InfiniteData<Response<EDef>>>(input?: RawRequestArgs<EDef> | SkipToken, opts?: TuyauInfiniteQueryOptionsIn<Response<EDef>, unknown, TData>): TuyauInfiniteQueryOptionsOut<Response<EDef>, unknown, TData>;
|
|
78
81
|
}
|
|
79
82
|
/**
|
|
80
83
|
* Decorate query endpoints with infinite query capabilities
|
|
81
84
|
*/
|
|
82
|
-
interface DecorateInfiniteQueryFn<EDef extends
|
|
85
|
+
interface DecorateInfiniteQueryFn<EDef extends SchemaEndpoint> {
|
|
83
86
|
infiniteQueryOptions: TuyauReactInfiniteQueryOptions<EDef>;
|
|
84
|
-
infiniteQueryKey: (args?: RawRequestArgs<EDef>) => DataTag<TuyauQueryKey, InfiniteData<EDef
|
|
85
|
-
infiniteQueryFilter: (args?: RawRequestArgs<EDef>, filters?: QueryFilters<DataTag<TuyauQueryKey, InfiniteData<EDef
|
|
87
|
+
infiniteQueryKey: (args?: RawRequestArgs<EDef>) => DataTag<TuyauQueryKey, InfiniteData<Response<EDef>>>;
|
|
88
|
+
infiniteQueryFilter: (args?: RawRequestArgs<EDef>, filters?: QueryFilters<DataTag<TuyauQueryKey, InfiniteData<Response<EDef>>>>) => WithRequired$1<QueryFilters<DataTag<TuyauQueryKey, InfiniteData<Response<EDef>>>>, 'queryKey'>;
|
|
86
89
|
}
|
|
87
90
|
|
|
88
91
|
/**
|
|
@@ -155,34 +158,33 @@ interface DecorateRouterKeyable {
|
|
|
155
158
|
pathKey: () => TuyauQueryKey;
|
|
156
159
|
pathFilter: (filters?: QueryFilters<TuyauQueryKey>) => WithRequired<QueryFilters<TuyauQueryKey>, 'queryKey'>;
|
|
157
160
|
}
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
type
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
type
|
|
177
|
-
[K in
|
|
178
|
-
}
|
|
179
|
-
type TuyauReactQuery<R extends Record<string,
|
|
161
|
+
/**
|
|
162
|
+
* Keys that identify an endpoint-like structure
|
|
163
|
+
*/
|
|
164
|
+
type EndpointKeys = 'methods' | 'pattern' | 'types';
|
|
165
|
+
/**
|
|
166
|
+
* Determines if endpoint is a query (GET/HEAD) or mutation
|
|
167
|
+
*/
|
|
168
|
+
type IsQueryMethod<E extends SchemaEndpoint> = E['methods'][number] extends infer M ? M extends 'GET' | 'HEAD' ? true : false : false;
|
|
169
|
+
/**
|
|
170
|
+
* Endpoint node with query or mutation decorators
|
|
171
|
+
* Optimized: uses direct conditional instead of nested extends
|
|
172
|
+
*/
|
|
173
|
+
type EndpointNode<E extends SchemaEndpoint> = (IsQueryMethod<E> extends true ? DecorateQueryFn<E> & DecorateInfiniteQueryFn<E> : DecorateMutationFn<E>) & DecorateRouterKeyable;
|
|
174
|
+
/**
|
|
175
|
+
* Transform a pre-computed tree structure into react-query decorated endpoints
|
|
176
|
+
* Uses the $tree from the registry to avoid recomputing the structure
|
|
177
|
+
* Handles the case where a node is both an endpoint AND has children
|
|
178
|
+
*/
|
|
179
|
+
type TransformToReactQuery<T> = {
|
|
180
|
+
[K in keyof T]: T[K] extends SchemaEndpoint ? EndpointNode<T[K]> & TransformToReactQuery<Omit<T[K], EndpointKeys>> : TransformToReactQuery<T[K]>;
|
|
181
|
+
} & DecorateRouterKeyable;
|
|
182
|
+
type TuyauReactQuery<R extends Record<string, SchemaEndpoint>> = TransformToReactQuery<R>;
|
|
180
183
|
|
|
181
|
-
declare function createTuyauReactQueryClient<
|
|
182
|
-
client: Tuyau<
|
|
183
|
-
queryClient: QueryClient | (() => QueryClient);
|
|
184
|
+
declare function createTuyauReactQueryClient<Reg extends TuyauRegistry, Tree = InferTree<Reg>, Routes extends Record<string, AdonisEndpoint> = InferRoutes<Reg>>(options: {
|
|
185
|
+
client: Tuyau<Reg, Routes>;
|
|
184
186
|
globalOptions?: TuyauReactRequestOptions;
|
|
185
|
-
}):
|
|
187
|
+
}): TransformToReactQuery<Tree>;
|
|
186
188
|
|
|
187
189
|
interface TuyauQueryOptionsOptions {
|
|
188
190
|
request: RawRequestArgs<any> | SkipToken;
|
|
@@ -201,4 +203,4 @@ declare function tuyauQueryOptions(options: TuyauQueryOptionsOptions): _tanstack
|
|
|
201
203
|
};
|
|
202
204
|
};
|
|
203
205
|
|
|
204
|
-
export { type DecorateMutationFn, type DecorateRouterKeyable, type DefinedTuyauQueryOptionsIn, type DefinedTuyauQueryOptionsOut, type EndpointNode, type QueryType, type TuyauMutationKey, type TuyauMutationOptionsIn, type TuyauMutationOptionsOptions, type TuyauMutationOptionsOut, type TuyauQueryBaseOptions, type TuyauQueryKey, type TuyauQueryOptionsOptions, type TuyauReactMutationOptions, type TuyauReactQuery, type TuyauReactRequestOptions, type
|
|
206
|
+
export { type DecorateMutationFn, type DecorateRouterKeyable, type DefinedTuyauQueryOptionsIn, type DefinedTuyauQueryOptionsOut, type EndpointNode, type QueryType, type TransformToReactQuery, type TuyauMutationKey, type TuyauMutationOptionsIn, type TuyauMutationOptionsOptions, type TuyauMutationOptionsOut, type TuyauQueryBaseOptions, type TuyauQueryKey, type TuyauQueryOptionsOptions, type TuyauReactMutationOptions, type TuyauReactQuery, type TuyauReactRequestOptions, type UndefinedTuyauQueryOptionsIn, type UndefinedTuyauQueryOptionsOut, type UnusedSkipTokenTuyauQueryOptionsIn, type UnusedSkipTokenTuyauQueryOptionsOut, createTuyauReactQueryClient, getMutationKeyInternal, tuyauMutationOptions, tuyauQueryOptions };
|
package/build/index.js
CHANGED
|
@@ -12,9 +12,23 @@ function buildKey(opts) {
|
|
|
12
12
|
if (!request && type === "any") {
|
|
13
13
|
return splitPath.length ? [splitPath] : [];
|
|
14
14
|
}
|
|
15
|
-
if (type === "infinite" && isObject(request)
|
|
16
|
-
const
|
|
17
|
-
|
|
15
|
+
if (type === "infinite" && isObject(request)) {
|
|
16
|
+
const query = request.query;
|
|
17
|
+
const body = request.body;
|
|
18
|
+
const hasCursorInQuery = isObject(query) && ("direction" in query || "cursor" in query);
|
|
19
|
+
const hasCursorInBody = isObject(body) && ("direction" in body || "cursor" in body);
|
|
20
|
+
if (hasCursorInQuery || hasCursorInBody) {
|
|
21
|
+
const cleanedRequest = { ...request };
|
|
22
|
+
if (hasCursorInQuery && isObject(query)) {
|
|
23
|
+
const { cursor: _, direction: __, ...cleanQuery } = query;
|
|
24
|
+
cleanedRequest.query = cleanQuery;
|
|
25
|
+
}
|
|
26
|
+
if (hasCursorInBody && isObject(body)) {
|
|
27
|
+
const { cursor: _, direction: __, ...cleanBody } = body;
|
|
28
|
+
cleanedRequest.body = cleanBody;
|
|
29
|
+
}
|
|
30
|
+
return [splitPath, { request: cleanedRequest, type: "infinite" }];
|
|
31
|
+
}
|
|
18
32
|
}
|
|
19
33
|
return [
|
|
20
34
|
splitPath,
|
|
@@ -35,6 +49,7 @@ function tuyauQueryOptions(options) {
|
|
|
35
49
|
const effectiveAbortOnUnmount = opts?.tuyau?.abortOnUnmount ?? globalOptions?.abortOnUnmount ?? false;
|
|
36
50
|
return await client.request(routeName, {
|
|
37
51
|
...request,
|
|
52
|
+
retry: 0,
|
|
38
53
|
...effectiveAbortOnUnmount ? { signal: queryFnContext.signal } : {}
|
|
39
54
|
});
|
|
40
55
|
};
|
|
@@ -43,10 +58,7 @@ function tuyauQueryOptions(options) {
|
|
|
43
58
|
}
|
|
44
59
|
|
|
45
60
|
// src/infinite_query.ts
|
|
46
|
-
import {
|
|
47
|
-
infiniteQueryOptions,
|
|
48
|
-
skipToken as skipToken3
|
|
49
|
-
} from "@tanstack/react-query";
|
|
61
|
+
import { infiniteQueryOptions, skipToken as skipToken3 } from "@tanstack/react-query";
|
|
50
62
|
function tuyauInfiniteQueryOptions(options) {
|
|
51
63
|
const { request, routeName, opts, queryKey, client, globalOptions } = options;
|
|
52
64
|
const queryFn = invoke(() => {
|
|
@@ -70,6 +82,7 @@ function tuyauInfiniteQueryOptions(options) {
|
|
|
70
82
|
}
|
|
71
83
|
return await client.request(routeName, {
|
|
72
84
|
...requestArgs,
|
|
85
|
+
retry: 0,
|
|
73
86
|
...effectiveAbortOnUnmount ? { signal: queryFnContext.signal } : {}
|
|
74
87
|
});
|
|
75
88
|
};
|
|
@@ -95,14 +108,17 @@ function tuyauMutationOptions(options) {
|
|
|
95
108
|
const mutationKey = getMutationKeyInternal({ segments: routeName.split(".") });
|
|
96
109
|
const mutationFn = async (request) => {
|
|
97
110
|
const requestArgs = request || {};
|
|
98
|
-
return await client.request(routeName, requestArgs);
|
|
111
|
+
return await client.request(routeName, { ...requestArgs, retry: 0 });
|
|
99
112
|
};
|
|
100
113
|
return mutationOptions({ ...opts, mutationKey, mutationFn });
|
|
101
114
|
}
|
|
102
115
|
|
|
103
116
|
// src/main.ts
|
|
117
|
+
function toSnakeCase(str) {
|
|
118
|
+
return str.replace(/([a-z])([A-Z])/g, "$1_$2").toLowerCase();
|
|
119
|
+
}
|
|
104
120
|
function segmentsToRouteName(segments) {
|
|
105
|
-
return segments.join(".");
|
|
121
|
+
return segments.map(toSnakeCase).join(".");
|
|
106
122
|
}
|
|
107
123
|
function createTuyauReactQueryClient(options) {
|
|
108
124
|
const { client, globalOptions } = options;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tuyau/react-query",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "1.0.0-beta.
|
|
4
|
+
"version": "1.0.0-beta.2",
|
|
5
5
|
"description": "React Query plugin for Tuyau",
|
|
6
6
|
"author": "Julien Ripouteau <julien@ripouteau.com>",
|
|
7
7
|
"license": "ISC",
|
|
@@ -13,19 +13,23 @@
|
|
|
13
13
|
"files": [
|
|
14
14
|
"build"
|
|
15
15
|
],
|
|
16
|
+
"engines": {
|
|
17
|
+
"node": ">=24.0.0"
|
|
18
|
+
},
|
|
16
19
|
"peerDependencies": {
|
|
17
20
|
"@tanstack/react-query": "^5.74.7",
|
|
18
21
|
"@tuyau/core": "1.0.0-beta.2"
|
|
19
22
|
},
|
|
20
23
|
"devDependencies": {
|
|
21
|
-
"@adonisjs/core": "^7.0.0-next.
|
|
22
|
-
"@
|
|
23
|
-
"@
|
|
24
|
+
"@adonisjs/core": "^7.0.0-next.13",
|
|
25
|
+
"@faker-js/faker": "^10.1.0",
|
|
26
|
+
"@happy-dom/global-registrator": "^20.0.11",
|
|
27
|
+
"@tanstack/react-query": "^5.90.12",
|
|
24
28
|
"@testing-library/react": "^16.3.0",
|
|
25
|
-
"@types/react": "^19.2.
|
|
29
|
+
"@types/react": "^19.2.7",
|
|
26
30
|
"@vinejs/vine": "^4.1.0",
|
|
27
|
-
"react": "^19.2.
|
|
28
|
-
"@tuyau/core": "1.0.0-beta.
|
|
31
|
+
"react": "^19.2.1",
|
|
32
|
+
"@tuyau/core": "1.0.0-beta.6"
|
|
29
33
|
},
|
|
30
34
|
"tsup": {
|
|
31
35
|
"entry": [
|