@openapi-qraft/react 1.0.0-beta.4 → 1.0.0-beta.6
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 +14 -0
- package/README.md +35 -0
- package/dist/ServiceOperation.d.ts +58 -9
- package/dist/ServiceOperation.d.ts.map +1 -1
- package/dist/callbacks/getMutationKey.d.ts +2 -2
- package/dist/callbacks/getMutationKey.d.ts.map +1 -1
- package/dist/callbacks/getMutationKey.js +2 -19
- package/dist/callbacks/getMutationKey.js.map +1 -1
- package/dist/callbacks/useInfiniteQuery.d.ts +0 -6
- package/dist/callbacks/useInfiniteQuery.d.ts.map +1 -1
- package/dist/callbacks/useInfiniteQuery.js +1 -27
- package/dist/callbacks/useInfiniteQuery.js.map +1 -1
- package/dist/callbacks/useMutation.d.ts.map +1 -1
- package/dist/callbacks/useMutation.js +4 -16
- package/dist/callbacks/useMutation.js.map +1 -1
- package/dist/callbacks/useMutationState.d.ts +7 -0
- package/dist/callbacks/useMutationState.d.ts.map +1 -0
- package/dist/callbacks/useMutationState.js +30 -0
- package/dist/callbacks/useMutationState.js.map +1 -0
- package/dist/callbacks/useSuspenseInfiniteQuery.d.ts +9 -0
- package/dist/callbacks/useSuspenseInfiniteQuery.d.ts.map +1 -0
- package/dist/callbacks/useSuspenseInfiniteQuery.js +25 -0
- package/dist/callbacks/useSuspenseInfiniteQuery.js.map +1 -0
- package/dist/callbacks/useSuspenseQuery.d.ts +9 -0
- package/dist/callbacks/useSuspenseQuery.d.ts.map +1 -0
- package/dist/callbacks/useSuspenseQuery.js +28 -0
- package/dist/callbacks/useSuspenseQuery.js.map +1 -0
- package/dist/lib/composeMutationKey.d.ts +10 -0
- package/dist/lib/composeMutationKey.d.ts.map +1 -0
- package/dist/lib/composeMutationKey.js +21 -0
- package/dist/lib/composeMutationKey.js.map +1 -0
- package/dist/lib/shelfMerge.d.ts +7 -0
- package/dist/lib/shelfMerge.d.ts.map +1 -0
- package/dist/lib/shelfMerge.js +28 -0
- package/dist/lib/shelfMerge.js.map +1 -0
- package/package.json +2 -2
- package/src/ServiceOperation.ts +156 -8
- package/src/callbacks/getMutationKey.ts +6 -34
- package/src/callbacks/useInfiniteQuery.ts +1 -36
- package/src/callbacks/useMutation.ts +7 -19
- package/src/callbacks/useMutationState.ts +73 -0
- package/src/callbacks/useSuspenseInfiniteQuery.ts +60 -0
- package/src/callbacks/useSuspenseQuery.ts +64 -0
- package/src/lib/composeMutationKey.test.ts +43 -0
- package/src/lib/composeMutationKey.ts +50 -0
- package/src/{callbacks → lib}/shelfMerge.test.ts +1 -1
- package/src/lib/shelfMerge.ts +35 -0
- package/src/qraftAPIClient.test.tsx +358 -2
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shelfMerge.js","sourceRoot":"","sources":["../../src/lib/shelfMerge.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,UAAU,UAAU,CAAI,KAAK,GAAG,CAAC,EAAE,GAAG,IAAS;IACnD,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;QAC9B,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ;YAAE,OAAO,GAAG,CAAC;QAEhD,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE;YAC3C,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;gBAC9B,GAAG,CAAC,GAAY,CAAC,GAAG,KAAc,CAAC;gBACnC,OAAO;YACT,CAAC;YAED,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;gBACzB,GAAG,CAAC,GAAY,CAAC,GAAG,KAAc,CAAC;gBACnC,OAAO;YACT,CAAC;YAED,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;gBACd,GAAG,CAAC,GAAY,CAAC,GAAG,UAAU,CAC5B,KAAK,GAAG,CAAC,EACT,GAAG,CAAC,GAAY,CAAC,EACjB,KAAK,CACG,CAAC;gBACX,OAAO;YACT,CAAC;YAED,GAAG,CAAC,GAAY,CAAC,GAAG,KAAc,CAAC;QACrC,CAAC,CAAC,CAAC;QAEH,OAAO,GAAG,CAAC;IACb,CAAC,EAAE,EAAO,CAAC,CAAC;AACd,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openapi-qraft/react",
|
|
3
|
-
"version": "1.0.0-beta.
|
|
3
|
+
"version": "1.0.0-beta.6",
|
|
4
4
|
"description": "API client for React, providing type-safe requests and dynamic Tanstack Query React Hooks via a modular, Proxy-based architecture.",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"build": "rimraf dist/ && tsc --project tsconfig.build.json",
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"type": "module",
|
|
14
14
|
"sideEffects": false,
|
|
15
15
|
"devDependencies": {
|
|
16
|
-
"@openapi-qraft/cli": "~1.0.0-beta.
|
|
16
|
+
"@openapi-qraft/cli": "~1.0.0-beta.4",
|
|
17
17
|
"@openapi-qraft/openapi-typescript": "^1.0.0-beta.1",
|
|
18
18
|
"@tanstack/react-query": "^5.17.3",
|
|
19
19
|
"@testing-library/jest-dom": "^5.17.0",
|
package/src/ServiceOperation.ts
CHANGED
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
import {
|
|
2
2
|
DefaultError,
|
|
3
3
|
InfiniteData,
|
|
4
|
-
QueryClient,
|
|
5
4
|
InfiniteQueryPageParamsOptions,
|
|
5
|
+
Mutation,
|
|
6
|
+
MutationState,
|
|
7
|
+
MutationStatus,
|
|
6
8
|
NoInfer,
|
|
9
|
+
QueryClient,
|
|
7
10
|
SetDataOptions,
|
|
8
11
|
Updater,
|
|
9
12
|
} from '@tanstack/query-core';
|
|
10
|
-
import
|
|
13
|
+
import {
|
|
11
14
|
DefinedInitialDataInfiniteOptions,
|
|
12
15
|
DefinedInitialDataOptions,
|
|
13
16
|
DefinedUseInfiniteQueryResult,
|
|
@@ -18,6 +21,10 @@ import type {
|
|
|
18
21
|
UseMutationOptions,
|
|
19
22
|
UseMutationResult,
|
|
20
23
|
UseQueryResult,
|
|
24
|
+
UseSuspenseInfiniteQueryOptions,
|
|
25
|
+
UseSuspenseInfiniteQueryResult,
|
|
26
|
+
UseSuspenseQueryOptions,
|
|
27
|
+
UseSuspenseQueryResult,
|
|
21
28
|
} from '@tanstack/react-query';
|
|
22
29
|
|
|
23
30
|
export type ServiceOperationQueryKey<S extends { url: string }, T> = [
|
|
@@ -32,8 +39,10 @@ export type ServiceOperationInfiniteQueryKey<S extends { url: string }, T> = [
|
|
|
32
39
|
|
|
33
40
|
export type ServiceOperationMutationKey<
|
|
34
41
|
S extends Record<'url' | 'method', string>,
|
|
35
|
-
T,
|
|
36
|
-
> =
|
|
42
|
+
T extends unknown,
|
|
43
|
+
> = NonNullable<T> extends never
|
|
44
|
+
? [Pick<S, 'url' | 'method'>]
|
|
45
|
+
: [Pick<S, 'url' | 'method'>, T];
|
|
37
46
|
|
|
38
47
|
export interface ServiceOperationQuery<
|
|
39
48
|
TSchema extends { url: string; method: string },
|
|
@@ -42,6 +51,8 @@ export interface ServiceOperationQuery<
|
|
|
42
51
|
TError = DefaultError,
|
|
43
52
|
> extends ServiceOperationUseQuery<TSchema, TData, TParams, TError>,
|
|
44
53
|
ServiceOperationUseInfiniteQuery<TSchema, TData, TParams, TError>,
|
|
54
|
+
ServiceOperationUseSuspenseQueryQuery<TSchema, TData, TParams, TError>,
|
|
55
|
+
ServiceOperationUseSuspenseInfiniteQuery<TSchema, TData, TParams, TError>,
|
|
45
56
|
ServiceOperationQueryFn<TSchema, TData, TParams>,
|
|
46
57
|
ServiceOperationGetQueryData<TData, TParams>,
|
|
47
58
|
ServiceOperationGetInfiniteQueryData<TData, TParams>,
|
|
@@ -144,6 +155,56 @@ interface ServiceOperationUseInfiniteQuery<
|
|
|
144
155
|
): DefinedUseInfiniteQueryResult<InfiniteData<TData>, TError | Error>;
|
|
145
156
|
}
|
|
146
157
|
|
|
158
|
+
interface ServiceOperationUseSuspenseInfiniteQuery<
|
|
159
|
+
TSchema extends { url: string; method: string },
|
|
160
|
+
TData,
|
|
161
|
+
TParams = {},
|
|
162
|
+
TError = DefaultError,
|
|
163
|
+
> {
|
|
164
|
+
useSuspenseInfiniteQuery<TPageParam extends TParams>(
|
|
165
|
+
params: TParams,
|
|
166
|
+
options: Omit<
|
|
167
|
+
UseSuspenseInfiniteQueryOptions<
|
|
168
|
+
TData,
|
|
169
|
+
TError,
|
|
170
|
+
InfiniteData<TData>,
|
|
171
|
+
TData,
|
|
172
|
+
| ServiceOperationInfiniteQueryKey<TSchema, TParams>
|
|
173
|
+
| readonly [...ServiceOperationInfiniteQueryKey<TSchema, TParams>],
|
|
174
|
+
PartialParams<TPageParam>
|
|
175
|
+
>,
|
|
176
|
+
| 'queryKey'
|
|
177
|
+
| 'getPreviousPageParam'
|
|
178
|
+
| 'getNextPageParam'
|
|
179
|
+
| 'initialPageParam'
|
|
180
|
+
> &
|
|
181
|
+
InfiniteQueryPageParamsOptions<TData, PartialParams<TPageParam>>,
|
|
182
|
+
queryClient?: QueryClient
|
|
183
|
+
): UseSuspenseInfiniteQueryResult<InfiniteData<TData>, TError | Error>;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
interface ServiceOperationUseSuspenseQueryQuery<
|
|
187
|
+
TSchema extends { url: string; method: string },
|
|
188
|
+
TData,
|
|
189
|
+
TParams = {},
|
|
190
|
+
TError = DefaultError,
|
|
191
|
+
> {
|
|
192
|
+
useSuspenseQuery(
|
|
193
|
+
params: TParams,
|
|
194
|
+
options?: Omit<
|
|
195
|
+
UseSuspenseQueryOptions<
|
|
196
|
+
TData,
|
|
197
|
+
TError,
|
|
198
|
+
TData,
|
|
199
|
+
| ServiceOperationQueryKey<TSchema, TParams>
|
|
200
|
+
| readonly [...ServiceOperationQueryKey<TSchema, TParams>]
|
|
201
|
+
>,
|
|
202
|
+
'queryKey'
|
|
203
|
+
>,
|
|
204
|
+
queryClient?: QueryClient
|
|
205
|
+
): UseSuspenseQueryResult<TData, TError | Error>;
|
|
206
|
+
}
|
|
207
|
+
|
|
147
208
|
export interface ServiceOperationMutation<
|
|
148
209
|
TSchema extends { url: string; method: string },
|
|
149
210
|
TBody,
|
|
@@ -151,6 +212,7 @@ export interface ServiceOperationMutation<
|
|
|
151
212
|
TParams,
|
|
152
213
|
TError = DefaultError,
|
|
153
214
|
> extends ServiceOperationUseMutation<TSchema, TBody, TData, TParams, TError>,
|
|
215
|
+
ServiceOperationUseMutationState<TSchema, TBody, TData, TParams, TError>,
|
|
154
216
|
ServiceOperationMutationFn<TSchema, TBody, TData, TParams>,
|
|
155
217
|
ServiceOperationSetQueryData<TData, TParams> {
|
|
156
218
|
schema: TSchema;
|
|
@@ -164,13 +226,11 @@ interface ServiceOperationUseMutation<
|
|
|
164
226
|
TError = DefaultError,
|
|
165
227
|
> {
|
|
166
228
|
getMutationKey<T extends TParams>(
|
|
167
|
-
params: T
|
|
229
|
+
params: T | undefined
|
|
168
230
|
): ServiceOperationMutationKey<TSchema, T>;
|
|
169
231
|
|
|
170
232
|
useMutation<
|
|
171
|
-
TVariables extends
|
|
172
|
-
? {}
|
|
173
|
-
: TParams),
|
|
233
|
+
TVariables extends MutationVariables<TBody, TParams>,
|
|
174
234
|
TContext = unknown,
|
|
175
235
|
>(
|
|
176
236
|
params?: undefined,
|
|
@@ -196,6 +256,94 @@ interface ServiceOperationUseMutation<
|
|
|
196
256
|
): UseMutationResult<TData, TError | Error, TVariables, TContext>;
|
|
197
257
|
}
|
|
198
258
|
|
|
259
|
+
type MutationFilters<
|
|
260
|
+
TSchema extends { url: string; method: string },
|
|
261
|
+
TBody,
|
|
262
|
+
TData,
|
|
263
|
+
TParams,
|
|
264
|
+
TError = DefaultError,
|
|
265
|
+
TContext = unknown,
|
|
266
|
+
> = {
|
|
267
|
+
/**
|
|
268
|
+
* Match mutation key exactly
|
|
269
|
+
*/
|
|
270
|
+
exact?: boolean;
|
|
271
|
+
/**
|
|
272
|
+
* Include mutations matching this predicate function
|
|
273
|
+
*/
|
|
274
|
+
predicate?: (
|
|
275
|
+
mutation: Mutation<
|
|
276
|
+
TData,
|
|
277
|
+
TError,
|
|
278
|
+
MutationVariables<TBody, TParams>,
|
|
279
|
+
TContext
|
|
280
|
+
>
|
|
281
|
+
) => boolean;
|
|
282
|
+
|
|
283
|
+
/**
|
|
284
|
+
* Filter by mutation status
|
|
285
|
+
*/
|
|
286
|
+
status?: MutationStatus;
|
|
287
|
+
} & (
|
|
288
|
+
| {
|
|
289
|
+
/**
|
|
290
|
+
* Include mutations matching this mutation key
|
|
291
|
+
*/
|
|
292
|
+
mutationKey?: ServiceOperationMutationKey<
|
|
293
|
+
TSchema,
|
|
294
|
+
PartialParams<TParams>
|
|
295
|
+
>;
|
|
296
|
+
}
|
|
297
|
+
| {
|
|
298
|
+
/**
|
|
299
|
+
* Include mutations matching these parameters
|
|
300
|
+
*/
|
|
301
|
+
parameters?: PartialParams<TParams>;
|
|
302
|
+
}
|
|
303
|
+
);
|
|
304
|
+
|
|
305
|
+
type MutationVariables<TBody, TParams> = {
|
|
306
|
+
body: TBody;
|
|
307
|
+
} & (NonNullable<TParams> extends never ? {} : TParams);
|
|
308
|
+
|
|
309
|
+
interface ServiceOperationUseMutationState<
|
|
310
|
+
TSchema extends { url: string; method: string },
|
|
311
|
+
TBody,
|
|
312
|
+
TData,
|
|
313
|
+
TParams,
|
|
314
|
+
TError = DefaultError,
|
|
315
|
+
> {
|
|
316
|
+
useMutationState<
|
|
317
|
+
TContext = unknown,
|
|
318
|
+
TResult = MutationState<
|
|
319
|
+
TData,
|
|
320
|
+
TError,
|
|
321
|
+
MutationVariables<TBody, TParams>,
|
|
322
|
+
TContext
|
|
323
|
+
>,
|
|
324
|
+
>(
|
|
325
|
+
options?: {
|
|
326
|
+
filters?: MutationFilters<
|
|
327
|
+
TSchema,
|
|
328
|
+
TBody,
|
|
329
|
+
TData,
|
|
330
|
+
TParams,
|
|
331
|
+
TError,
|
|
332
|
+
TContext
|
|
333
|
+
>;
|
|
334
|
+
select?: (
|
|
335
|
+
mutation: Mutation<
|
|
336
|
+
TData,
|
|
337
|
+
TError,
|
|
338
|
+
MutationVariables<TBody, TParams>,
|
|
339
|
+
TContext
|
|
340
|
+
>
|
|
341
|
+
) => TResult;
|
|
342
|
+
},
|
|
343
|
+
queryClient?: QueryClient
|
|
344
|
+
): Array<TResult>;
|
|
345
|
+
}
|
|
346
|
+
|
|
199
347
|
interface ServiceOperationQueryFn<
|
|
200
348
|
TSchema extends { url: string; method: string },
|
|
201
349
|
TData,
|
|
@@ -1,47 +1,19 @@
|
|
|
1
|
+
import { composeMutationKey } from '../lib/composeMutationKey.js';
|
|
1
2
|
import type { QraftClientOptions } from '../qraftAPIClient.js';
|
|
2
3
|
import type { RequestClientSchema } from '../RequestClient.js';
|
|
3
|
-
import {
|
|
4
|
-
ServiceOperationMutation,
|
|
5
|
-
ServiceOperationMutationKey,
|
|
6
|
-
} from '../ServiceOperation.js';
|
|
4
|
+
import { ServiceOperationMutation } from '../ServiceOperation.js';
|
|
7
5
|
|
|
8
6
|
export const getMutationKey = (
|
|
9
7
|
qraftOptions: QraftClientOptions | undefined,
|
|
10
8
|
schema: RequestClientSchema,
|
|
11
|
-
args:
|
|
12
|
-
) => {
|
|
13
|
-
const [parameters] = args as Parameters<
|
|
9
|
+
args: Parameters<
|
|
14
10
|
ServiceOperationMutation<
|
|
15
11
|
RequestClientSchema,
|
|
16
12
|
unknown,
|
|
17
13
|
unknown,
|
|
18
14
|
unknown
|
|
19
15
|
>['getMutationKey']
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
{
|
|
24
|
-
url: schema.url,
|
|
25
|
-
method: schema.method,
|
|
26
|
-
},
|
|
27
|
-
omitMutationPayload(parameters),
|
|
28
|
-
];
|
|
29
|
-
|
|
30
|
-
return key;
|
|
16
|
+
>
|
|
17
|
+
) => {
|
|
18
|
+
return composeMutationKey(schema, args[0]);
|
|
31
19
|
};
|
|
32
|
-
|
|
33
|
-
function omitMutationPayload<T>(params: T) {
|
|
34
|
-
if (!params || typeof params !== 'object')
|
|
35
|
-
throw new Error('`params` must be object');
|
|
36
|
-
|
|
37
|
-
if ('body' in params || 'requestBody' in params) {
|
|
38
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
39
|
-
const { body, requestBody, ...paramsRest } = params as Record<
|
|
40
|
-
'body' | 'requestBody',
|
|
41
|
-
unknown
|
|
42
|
-
>;
|
|
43
|
-
return paramsRest;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
return params as Omit<T, 'body' | 'requestBody'>;
|
|
47
|
-
}
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
UseInfiniteQueryResult,
|
|
9
9
|
} from '@tanstack/react-query';
|
|
10
10
|
|
|
11
|
+
import { shelfMerge } from '../lib/shelfMerge.js';
|
|
11
12
|
import type { QraftClientOptions } from '../qraftAPIClient.js';
|
|
12
13
|
import { QraftContext } from '../QraftContext.js';
|
|
13
14
|
import type { RequestClientSchema } from '../RequestClient.js';
|
|
@@ -52,39 +53,3 @@ export const useInfiniteQuery: <
|
|
|
52
53
|
...restArgs
|
|
53
54
|
) as never;
|
|
54
55
|
};
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* Merges objects with provided depth
|
|
58
|
-
* @param depth
|
|
59
|
-
* @param args
|
|
60
|
-
*/
|
|
61
|
-
export function shelfMerge<T>(depth = 2, ...args: T[]): T {
|
|
62
|
-
return args.reduce((acc, arg) => {
|
|
63
|
-
if (!arg || typeof arg !== 'object') return acc;
|
|
64
|
-
|
|
65
|
-
Object.entries(arg).forEach(([key, value]) => {
|
|
66
|
-
if (typeof value !== 'object') {
|
|
67
|
-
acc[key as never] = value as never;
|
|
68
|
-
return;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
if (Array.isArray(value)) {
|
|
72
|
-
acc[key as never] = value as never;
|
|
73
|
-
return;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
if (depth > 1) {
|
|
77
|
-
acc[key as never] = shelfMerge(
|
|
78
|
-
depth - 1,
|
|
79
|
-
acc[key as never],
|
|
80
|
-
value
|
|
81
|
-
) as never;
|
|
82
|
-
return;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
acc[key as never] = value as never;
|
|
86
|
-
});
|
|
87
|
-
|
|
88
|
-
return acc;
|
|
89
|
-
}, {} as T);
|
|
90
|
-
}
|
|
@@ -6,6 +6,7 @@ import type { DefaultError } from '@tanstack/query-core';
|
|
|
6
6
|
import type { UseMutationResult } from '@tanstack/react-query';
|
|
7
7
|
import { useMutation as useMutationBase } from '@tanstack/react-query';
|
|
8
8
|
|
|
9
|
+
import { composeMutationKey } from '../lib/composeMutationKey.js';
|
|
9
10
|
import type { QraftClientOptions } from '../qraftAPIClient.js';
|
|
10
11
|
import { QraftContext } from '../QraftContext.js';
|
|
11
12
|
import type { RequestClientSchema } from '../RequestClient.js';
|
|
@@ -53,25 +54,12 @@ export const useMutation: <
|
|
|
53
54
|
if (!requestClient) throw new Error(`QraftContext.requestClient not found`);
|
|
54
55
|
|
|
55
56
|
const mutationKey =
|
|
56
|
-
|
|
57
|
-
? (
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
parameters,
|
|
63
|
-
] as const)
|
|
64
|
-
: options && 'mutationKey' in options
|
|
65
|
-
? (options.mutationKey as ServiceOperationMutationKey<
|
|
66
|
-
typeof schema,
|
|
67
|
-
unknown
|
|
68
|
-
>)
|
|
69
|
-
: ([
|
|
70
|
-
{
|
|
71
|
-
url: schema.url,
|
|
72
|
-
method: schema.method,
|
|
73
|
-
},
|
|
74
|
-
] as const);
|
|
57
|
+
options && 'mutationKey' in options
|
|
58
|
+
? (options.mutationKey as ServiceOperationMutationKey<
|
|
59
|
+
typeof schema,
|
|
60
|
+
unknown
|
|
61
|
+
>)
|
|
62
|
+
: composeMutationKey(schema, parameters);
|
|
75
63
|
|
|
76
64
|
return useMutationBase(
|
|
77
65
|
{
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { useContext } from 'react';
|
|
4
|
+
|
|
5
|
+
import type { DefaultError } from '@tanstack/query-core';
|
|
6
|
+
import type { UseMutationResult } from '@tanstack/react-query';
|
|
7
|
+
import { useMutationState as useMutationStateTanstack } from '@tanstack/react-query';
|
|
8
|
+
|
|
9
|
+
import { composeMutationKey } from '../lib/composeMutationKey.js';
|
|
10
|
+
import type { QraftClientOptions } from '../qraftAPIClient.js';
|
|
11
|
+
import { QraftContext } from '../QraftContext.js';
|
|
12
|
+
import type { RequestClientSchema } from '../RequestClient.js';
|
|
13
|
+
import { ServiceOperationMutation } from '../ServiceOperation.js';
|
|
14
|
+
|
|
15
|
+
export const useMutationState: <
|
|
16
|
+
TData = unknown,
|
|
17
|
+
TError = DefaultError,
|
|
18
|
+
TVariables = unknown,
|
|
19
|
+
TContext = unknown,
|
|
20
|
+
>(
|
|
21
|
+
qraftOptions: QraftClientOptions | undefined,
|
|
22
|
+
schema: RequestClientSchema,
|
|
23
|
+
args: Parameters<
|
|
24
|
+
ServiceOperationMutation<
|
|
25
|
+
RequestClientSchema,
|
|
26
|
+
object | undefined,
|
|
27
|
+
TVariables,
|
|
28
|
+
TData
|
|
29
|
+
>['useMutationState']
|
|
30
|
+
>
|
|
31
|
+
) => UseMutationResult<TData, TError, TVariables, TContext> = (
|
|
32
|
+
qraftOptions,
|
|
33
|
+
schema,
|
|
34
|
+
args
|
|
35
|
+
) => {
|
|
36
|
+
const [options, ...restArgs] = args;
|
|
37
|
+
|
|
38
|
+
if (
|
|
39
|
+
options?.filters &&
|
|
40
|
+
'parameters' in options.filters &&
|
|
41
|
+
'mutationKey' in options.filters
|
|
42
|
+
) {
|
|
43
|
+
throw new Error(
|
|
44
|
+
`'useMutationState': 'parameters' and 'mutationKey' cannot be used together`
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const requestClient = useContext(qraftOptions?.context ?? QraftContext)
|
|
49
|
+
?.requestClient;
|
|
50
|
+
|
|
51
|
+
if (!requestClient) throw new Error(`QraftContext.requestClient not found`);
|
|
52
|
+
|
|
53
|
+
const filters = options?.filters;
|
|
54
|
+
|
|
55
|
+
return useMutationStateTanstack(
|
|
56
|
+
{
|
|
57
|
+
...options,
|
|
58
|
+
filters:
|
|
59
|
+
filters && 'mutationKey' in filters
|
|
60
|
+
? filters
|
|
61
|
+
: {
|
|
62
|
+
...filters,
|
|
63
|
+
mutationKey: composeMutationKey(
|
|
64
|
+
schema,
|
|
65
|
+
filters && 'parameters' in filters
|
|
66
|
+
? filters.parameters
|
|
67
|
+
: undefined
|
|
68
|
+
),
|
|
69
|
+
},
|
|
70
|
+
} as never,
|
|
71
|
+
...restArgs
|
|
72
|
+
) as never;
|
|
73
|
+
};
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { useContext } from 'react';
|
|
4
|
+
|
|
5
|
+
import type { DefaultError, InfiniteData } from '@tanstack/query-core';
|
|
6
|
+
import {
|
|
7
|
+
useSuspenseInfiniteQuery as useSuspenseInfiniteQueryTanstack,
|
|
8
|
+
UseSuspenseInfiniteQueryResult,
|
|
9
|
+
} from '@tanstack/react-query';
|
|
10
|
+
|
|
11
|
+
import { shelfMerge } from '../lib/shelfMerge.js';
|
|
12
|
+
import type { QraftClientOptions } from '../qraftAPIClient.js';
|
|
13
|
+
import { QraftContext } from '../QraftContext.js';
|
|
14
|
+
import type { RequestClientSchema } from '../RequestClient.js';
|
|
15
|
+
import {
|
|
16
|
+
ServiceOperationQuery,
|
|
17
|
+
ServiceOperationQueryKey,
|
|
18
|
+
} from '../ServiceOperation.js';
|
|
19
|
+
|
|
20
|
+
export const useSuspenseInfiniteQuery: <
|
|
21
|
+
TQueryFnData,
|
|
22
|
+
TError = DefaultError,
|
|
23
|
+
TData = InfiniteData<TQueryFnData>,
|
|
24
|
+
>(
|
|
25
|
+
qraftOptions: QraftClientOptions | undefined,
|
|
26
|
+
schema: RequestClientSchema,
|
|
27
|
+
args: Parameters<
|
|
28
|
+
ServiceOperationQuery<
|
|
29
|
+
RequestClientSchema,
|
|
30
|
+
unknown,
|
|
31
|
+
unknown
|
|
32
|
+
>['useSuspenseInfiniteQuery']
|
|
33
|
+
>
|
|
34
|
+
) => UseSuspenseInfiniteQueryResult<TData, TError> & {
|
|
35
|
+
queryKey: ServiceOperationQueryKey<RequestClientSchema, unknown>;
|
|
36
|
+
} = (qraftOptions, schema, args) => {
|
|
37
|
+
const [params, options, ...restArgs] = args;
|
|
38
|
+
|
|
39
|
+
const requestClient = useContext(qraftOptions?.context ?? QraftContext)
|
|
40
|
+
?.requestClient;
|
|
41
|
+
|
|
42
|
+
if (!requestClient) throw new Error(`QraftContext.requestClient not found`);
|
|
43
|
+
|
|
44
|
+
return useSuspenseInfiniteQueryTanstack(
|
|
45
|
+
{
|
|
46
|
+
...options,
|
|
47
|
+
queryKey: [{ url: schema.url, infinite: true }, params as never] as const,
|
|
48
|
+
queryFn:
|
|
49
|
+
options?.queryFn ??
|
|
50
|
+
function ({ queryKey: [, queryParams], signal, meta, pageParam }) {
|
|
51
|
+
return requestClient(schema, {
|
|
52
|
+
parameters: shelfMerge(2, queryParams, pageParam) as never,
|
|
53
|
+
signal,
|
|
54
|
+
meta,
|
|
55
|
+
});
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
...restArgs
|
|
59
|
+
) as never;
|
|
60
|
+
};
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { useContext } from 'react';
|
|
4
|
+
|
|
5
|
+
import type { DefaultError } from '@tanstack/query-core';
|
|
6
|
+
import {
|
|
7
|
+
UseQueryResult,
|
|
8
|
+
useSuspenseQuery as useSuspenseQueryTanstack,
|
|
9
|
+
} from '@tanstack/react-query';
|
|
10
|
+
|
|
11
|
+
import type { QraftClientOptions } from '../qraftAPIClient.js';
|
|
12
|
+
import { QraftContext } from '../QraftContext.js';
|
|
13
|
+
import type { RequestClientSchema } from '../RequestClient.js';
|
|
14
|
+
import {
|
|
15
|
+
ServiceOperationQuery,
|
|
16
|
+
ServiceOperationQueryKey,
|
|
17
|
+
} from '../ServiceOperation.js';
|
|
18
|
+
|
|
19
|
+
export const useSuspenseQuery: <
|
|
20
|
+
TQueryFnData = unknown,
|
|
21
|
+
TError = DefaultError,
|
|
22
|
+
TData = TQueryFnData,
|
|
23
|
+
>(
|
|
24
|
+
qraftOptions: QraftClientOptions | undefined,
|
|
25
|
+
schema: RequestClientSchema,
|
|
26
|
+
args: Parameters<
|
|
27
|
+
ServiceOperationQuery<
|
|
28
|
+
RequestClientSchema,
|
|
29
|
+
unknown,
|
|
30
|
+
unknown
|
|
31
|
+
>['useSuspenseQuery']
|
|
32
|
+
>
|
|
33
|
+
) => UseQueryResult<TData, TError> & {
|
|
34
|
+
queryKey: ServiceOperationQueryKey<RequestClientSchema, unknown>;
|
|
35
|
+
} = (qraftOptions, schema, args) => {
|
|
36
|
+
const [params, options, ...restArgs] = args;
|
|
37
|
+
|
|
38
|
+
const requestClient = useContext(qraftOptions?.context ?? QraftContext)
|
|
39
|
+
?.requestClient;
|
|
40
|
+
|
|
41
|
+
if (!requestClient) throw new Error(`QraftContext.requestClient not found`);
|
|
42
|
+
|
|
43
|
+
const queryKey: ServiceOperationQueryKey<RequestClientSchema, unknown> = [
|
|
44
|
+
{ url: schema.url },
|
|
45
|
+
params,
|
|
46
|
+
];
|
|
47
|
+
|
|
48
|
+
return useSuspenseQueryTanstack(
|
|
49
|
+
{
|
|
50
|
+
...options,
|
|
51
|
+
queryKey,
|
|
52
|
+
queryFn:
|
|
53
|
+
options?.queryFn ??
|
|
54
|
+
function ({ queryKey: [, queryParams], signal, meta }) {
|
|
55
|
+
return requestClient(schema, {
|
|
56
|
+
parameters: queryParams as never,
|
|
57
|
+
signal,
|
|
58
|
+
meta,
|
|
59
|
+
});
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
|
+
...restArgs
|
|
63
|
+
) as never;
|
|
64
|
+
};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { composeMutationKey } from './composeMutationKey.js';
|
|
2
|
+
|
|
3
|
+
describe('composeMutationKey', () => {
|
|
4
|
+
it('should return mutation key with parameters', () => {
|
|
5
|
+
const schema = {
|
|
6
|
+
url: 'https://example.com',
|
|
7
|
+
method: 'get',
|
|
8
|
+
} as const;
|
|
9
|
+
|
|
10
|
+
const parameters = {
|
|
11
|
+
body: 'body',
|
|
12
|
+
requestBody: 'requestBody',
|
|
13
|
+
other: 'other',
|
|
14
|
+
};
|
|
15
|
+
const result = composeMutationKey(schema, parameters);
|
|
16
|
+
|
|
17
|
+
expect(result).toEqual([
|
|
18
|
+
{
|
|
19
|
+
url: schema.url,
|
|
20
|
+
method: schema.method,
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
other: 'other',
|
|
24
|
+
},
|
|
25
|
+
]);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it('should return mutation key without parameters', () => {
|
|
29
|
+
const schema = {
|
|
30
|
+
url: 'https://example.com',
|
|
31
|
+
method: 'get',
|
|
32
|
+
} as const;
|
|
33
|
+
|
|
34
|
+
const result = composeMutationKey(schema, undefined);
|
|
35
|
+
|
|
36
|
+
expect(result).toEqual([
|
|
37
|
+
{
|
|
38
|
+
url: schema.url,
|
|
39
|
+
method: schema.method,
|
|
40
|
+
},
|
|
41
|
+
]);
|
|
42
|
+
});
|
|
43
|
+
});
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import type { RequestClientSchema } from '../RequestClient.js';
|
|
2
|
+
import { ServiceOperationMutationKey } from '../ServiceOperation.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Omit `body` or `requestBody` from mutation parameters if exists
|
|
6
|
+
* and return the rest of the parameters
|
|
7
|
+
*/
|
|
8
|
+
export function composeMutationKey<
|
|
9
|
+
TSchema extends RequestClientSchema,
|
|
10
|
+
TParams = undefined,
|
|
11
|
+
>(
|
|
12
|
+
schema: TSchema,
|
|
13
|
+
parameters: undefined
|
|
14
|
+
): ServiceOperationMutationKey<TSchema, undefined>;
|
|
15
|
+
export function composeMutationKey<
|
|
16
|
+
TSchema extends RequestClientSchema,
|
|
17
|
+
TParams,
|
|
18
|
+
>(
|
|
19
|
+
schema: TSchema,
|
|
20
|
+
parameters: TParams
|
|
21
|
+
): ServiceOperationMutationKey<TSchema, TParams>;
|
|
22
|
+
export function composeMutationKey<
|
|
23
|
+
TSchema extends RequestClientSchema,
|
|
24
|
+
TParams = unknown,
|
|
25
|
+
>(schema: TSchema, parameters: TParams | undefined) {
|
|
26
|
+
return parameters === undefined
|
|
27
|
+
? [{ url: schema.url, method: schema.method }]
|
|
28
|
+
: [
|
|
29
|
+
{
|
|
30
|
+
url: schema.url,
|
|
31
|
+
method: schema.method,
|
|
32
|
+
},
|
|
33
|
+
omitMutationPayload(parameters),
|
|
34
|
+
];
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function omitMutationPayload<T>(params: T) {
|
|
38
|
+
if (!params || typeof params !== 'object')
|
|
39
|
+
throw new Error('`params` must be object');
|
|
40
|
+
|
|
41
|
+
if ('body' in params || 'requestBody' in params) {
|
|
42
|
+
const { body, requestBody, ...paramsRest } = params as Record<
|
|
43
|
+
'body' | 'requestBody',
|
|
44
|
+
unknown
|
|
45
|
+
>;
|
|
46
|
+
return paramsRest;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return params as Omit<T, 'body' | 'requestBody'>;
|
|
50
|
+
}
|