@tuyau/react-query 1.0.0-beta.0 → 1.0.0-beta.1

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 CHANGED
@@ -1,23 +1,24 @@
1
- import { AdonisEndpoint, RawRequestArgs, Method, UnionToIntersection, StrKeys, Split } from '@tuyau/core/types';
1
+ import { SchemaEndpoint, RawRequestArgs, TuyauRegistry, InferTree, AdonisEndpoint, InferRoutes } from '@tuyau/core/types';
2
2
  import * as _tanstack_react_query from '@tanstack/react-query';
3
3
  import { SkipToken, DataTag, QueryFilters, WithRequired as WithRequired$1, UseMutationOptions, InfiniteData, InfiniteQueryObserverOptions, DefinedInitialDataOptions, UndefinedInitialDataOptions, UnusedSkipTokenOptions, QueryClient } 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 AdonisEndpoint> extends TypeHelper<EDef> {
10
+ interface DecorateQueryFn<EDef extends SchemaEndpoint> {
10
11
  queryOptions: TuyauReactQueryOptions<EDef>;
11
- queryKey: (args?: RawRequestArgs<EDef>) => DataTag<TuyauQueryKey, EDef['types']['response']>;
12
- queryFilter: (args?: RawRequestArgs<EDef>, filters?: QueryFilters<DataTag<TuyauQueryKey, EDef['types']['response']>>) => WithRequired$1<QueryFilters<DataTag<TuyauQueryKey, EDef['types']['response']>>, 'queryKey'>;
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 AdonisEndpoint> {
18
- <TData = EDef['types']['response']>(input: RawRequestArgs<EDef> | SkipToken, opts: DefinedTuyauQueryOptionsIn<EDef['types']['response'], TData, unknown>): DefinedTuyauQueryOptionsOut<EDef['types']['response'], TData, unknown>;
19
- <TData = EDef['types']['response']>(input: RawRequestArgs<EDef>, opts?: UnusedSkipTokenTuyauQueryOptionsIn<EDef['types']['response'], TData, unknown>): UnusedSkipTokenTuyauQueryOptionsOut<EDef['types']['response'], TData, unknown>;
20
- <TData = EDef['types']['response']>(input?: RawRequestArgs<EDef> | SkipToken, opts?: UndefinedTuyauQueryOptionsIn<EDef['types']['response'], TData, unknown>): UndefinedTuyauQueryOptionsOut<EDef['types']['response'], TData, unknown>;
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 AdonisEndpoint> {
39
- <TContext = unknown>(opts?: TuyauMutationOptionsIn<RawRequestArgs<TDef>, any, TDef['types']['response'], TContext>): TuyauMutationOptionsOut<RawRequestArgs<TDef>, any, TDef['types']['response'], TContext>;
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 AdonisEndpoint> extends TypeHelper<EDef> {
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 AdonisEndpoint> {
76
- <TData = InfiniteData<EDef['types']['response']>>(input: RawRequestArgs<EDef> | SkipToken, opts: TuyauInfiniteQueryOptionsIn<EDef['types']['response'], unknown, TData>): TuyauInfiniteQueryOptionsOut<EDef['types']['response'], unknown, TData>;
77
- <TData = InfiniteData<EDef['types']['response']>>(input?: RawRequestArgs<EDef> | SkipToken, opts?: TuyauInfiniteQueryOptionsIn<EDef['types']['response'], unknown, TData>): TuyauInfiniteQueryOptionsOut<EDef['types']['response'], unknown, TData>;
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 AdonisEndpoint> extends TypeHelper<EDef> {
85
+ interface DecorateInfiniteQueryFn<EDef extends SchemaEndpoint> {
83
86
  infiniteQueryOptions: TuyauReactInfiniteQueryOptions<EDef>;
84
- infiniteQueryKey: (args?: RawRequestArgs<EDef>) => DataTag<TuyauQueryKey, InfiniteData<EDef['types']['response']>>;
85
- infiniteQueryFilter: (args?: RawRequestArgs<EDef>, filters?: QueryFilters<DataTag<TuyauQueryKey, InfiniteData<EDef['types']['response']>>>) => WithRequired$1<QueryFilters<DataTag<TuyauQueryKey, InfiniteData<EDef['types']['response']>>>, 'queryKey'>;
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,34 @@ interface DecorateRouterKeyable {
155
158
  pathKey: () => TuyauQueryKey;
156
159
  pathFilter: (filters?: QueryFilters<TuyauQueryKey>) => WithRequired<QueryFilters<TuyauQueryKey>, 'queryKey'>;
157
160
  }
158
- type EndpointNode<E extends AdonisEndpoint> = E extends {
159
- methods: readonly (infer M extends Method)[];
160
- } ? M extends 'GET' | 'HEAD' ? DecorateQueryFn<E> & DecorateInfiniteQueryFn<E> & DecorateRouterKeyable : DecorateMutationFn<E> & DecorateRouterKeyable : DecorateRouterKeyable;
161
- interface TypeHelper<EDef extends AdonisEndpoint> {
162
- /**
163
- * @internal
164
- */
165
- '~types': {
166
- request: EDef['types']['body'];
167
- response: EDef['types']['response'];
168
- };
169
- }
170
- type SetAtPathWithKeyable<Path extends string[], V> = Path extends [
171
- infer H extends string,
172
- ...infer T extends string[]
173
- ] ? {
174
- [K in H]: T['length'] extends 0 ? V : SetAtPathWithKeyable<T, V> & DecorateRouterKeyable;
175
- } : {};
176
- type BuildNamespaces<R extends Record<string, AdonisEndpoint>> = UnionToIntersection<{
177
- [K in StrKeys<R>]: SetAtPathWithKeyable<Split<K>, EndpointNode<R[K]>>;
178
- }[StrKeys<R>]> & DecorateRouterKeyable;
179
- type TuyauReactQuery<R extends Record<string, AdonisEndpoint>> = BuildNamespaces<R>;
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<D extends Record<string, AdonisEndpoint>>(options: {
182
- client: Tuyau<D>;
184
+ declare function createTuyauReactQueryClient<Reg extends TuyauRegistry, Tree = InferTree<Reg>, Routes extends Record<string, AdonisEndpoint> = InferRoutes<Reg>>(options: {
185
+ client: Tuyau<Reg, Routes>;
183
186
  queryClient: QueryClient | (() => QueryClient);
184
187
  globalOptions?: TuyauReactRequestOptions;
185
- }): TuyauReactQuery<D> & DecorateRouterKeyable;
188
+ }): TransformToReactQuery<Tree>;
186
189
 
187
190
  interface TuyauQueryOptionsOptions {
188
191
  request: RawRequestArgs<any> | SkipToken;
@@ -201,4 +204,4 @@ declare function tuyauQueryOptions(options: TuyauQueryOptionsOptions): _tanstack
201
204
  };
202
205
  };
203
206
 
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 TypeHelper, type UndefinedTuyauQueryOptionsIn, type UndefinedTuyauQueryOptionsOut, type UnusedSkipTokenTuyauQueryOptionsIn, type UnusedSkipTokenTuyauQueryOptionsOut, createTuyauReactQueryClient, getMutationKeyInternal, tuyauMutationOptions, tuyauQueryOptions };
207
+ 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
@@ -43,10 +43,7 @@ function tuyauQueryOptions(options) {
43
43
  }
44
44
 
45
45
  // src/infinite_query.ts
46
- import {
47
- infiniteQueryOptions,
48
- skipToken as skipToken3
49
- } from "@tanstack/react-query";
46
+ import { infiniteQueryOptions, skipToken as skipToken3 } from "@tanstack/react-query";
50
47
  function tuyauInfiniteQueryOptions(options) {
51
48
  const { request, routeName, opts, queryKey, client, globalOptions } = options;
52
49
  const queryFn = invoke(() => {
@@ -101,8 +98,11 @@ function tuyauMutationOptions(options) {
101
98
  }
102
99
 
103
100
  // src/main.ts
101
+ function toSnakeCase(str) {
102
+ return str.replace(/([a-z])([A-Z])/g, "$1_$2").toLowerCase();
103
+ }
104
104
  function segmentsToRouteName(segments) {
105
- return segments.join(".");
105
+ return segments.map(toSnakeCase).join(".");
106
106
  }
107
107
  function createTuyauReactQueryClient(options) {
108
108
  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.0",
4
+ "version": "1.0.0-beta.1",
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
24
  "@adonisjs/core": "^7.0.0-next.10",
25
+ "@faker-js/faker": "^10.1.0",
22
26
  "@happy-dom/global-registrator": "^20.0.10",
23
27
  "@tanstack/react-query": "^5.90.7",
24
28
  "@testing-library/react": "^16.3.0",
25
29
  "@types/react": "^19.2.2",
26
30
  "@vinejs/vine": "^4.1.0",
27
31
  "react": "^19.2.0",
28
- "@tuyau/core": "1.0.0-beta.2"
32
+ "@tuyau/core": "1.0.0-beta.4"
29
33
  },
30
34
  "tsup": {
31
35
  "entry": [