@zenstackhq/tanstack-query 3.0.0-beta.17 → 3.0.0-beta.18
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/.turbo/turbo-build.log +27 -13
- package/dist/react.cjs +35 -33
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +26 -106
- package/dist/react.d.ts +26 -106
- package/dist/react.js +35 -33
- package/dist/react.js.map +1 -1
- package/dist/svelte.cjs +1224 -0
- package/dist/svelte.cjs.map +1 -0
- package/dist/svelte.d.cts +381 -0
- package/dist/svelte.d.ts +381 -0
- package/dist/svelte.js +1183 -0
- package/dist/svelte.js.map +1 -0
- package/dist/types-BRIDXxNC.d.cts +92 -0
- package/dist/types-BRIDXxNC.d.ts +92 -0
- package/dist/vue.cjs +1192 -0
- package/dist/vue.cjs.map +1 -0
- package/dist/vue.d.cts +382 -0
- package/dist/vue.d.ts +382 -0
- package/dist/vue.js +1152 -0
- package/dist/vue.js.map +1 -0
- package/package.json +43 -11
- package/src/react.ts +168 -155
- package/src/svelte.ts +483 -0
- package/src/utils/common.ts +4 -13
- package/src/utils/types.ts +13 -0
- package/src/vue.ts +429 -0
- package/test/react-typing-test.ts +109 -0
- package/test/schemas/basic/input.ts +40 -0
- package/test/schemas/basic/models.ts +2 -0
- package/test/schemas/basic/schema-lite.ts +48 -0
- package/test/schemas/basic/schema.zmodel +11 -1
- package/test/svelte-typing-test.ts +106 -0
- package/test/vue-typing-test.ts +107 -0
- package/tsup.config.ts +2 -0
package/src/vue.ts
ADDED
|
@@ -0,0 +1,429 @@
|
|
|
1
|
+
import {
|
|
2
|
+
useInfiniteQuery,
|
|
3
|
+
useMutation,
|
|
4
|
+
useQuery,
|
|
5
|
+
useQueryClient,
|
|
6
|
+
type DefaultError,
|
|
7
|
+
type InfiniteData,
|
|
8
|
+
type QueryKey,
|
|
9
|
+
type UseInfiniteQueryOptions,
|
|
10
|
+
type UseInfiniteQueryReturnType,
|
|
11
|
+
type UseMutationOptions,
|
|
12
|
+
type UseMutationReturnType,
|
|
13
|
+
type UseQueryOptions,
|
|
14
|
+
type UseQueryReturnType,
|
|
15
|
+
} from '@tanstack/vue-query';
|
|
16
|
+
import { lowerCaseFirst } from '@zenstackhq/common-helpers';
|
|
17
|
+
import type {
|
|
18
|
+
AggregateArgs,
|
|
19
|
+
AggregateResult,
|
|
20
|
+
BatchResult,
|
|
21
|
+
CountArgs,
|
|
22
|
+
CountResult,
|
|
23
|
+
CreateArgs,
|
|
24
|
+
CreateManyAndReturnArgs,
|
|
25
|
+
CreateManyArgs,
|
|
26
|
+
DeleteArgs,
|
|
27
|
+
DeleteManyArgs,
|
|
28
|
+
FindArgs,
|
|
29
|
+
FindUniqueArgs,
|
|
30
|
+
GroupByArgs,
|
|
31
|
+
GroupByResult,
|
|
32
|
+
ModelResult,
|
|
33
|
+
SelectIncludeOmit,
|
|
34
|
+
SelectSubset,
|
|
35
|
+
Subset,
|
|
36
|
+
UpdateArgs,
|
|
37
|
+
UpdateManyAndReturnArgs,
|
|
38
|
+
UpdateManyArgs,
|
|
39
|
+
UpsertArgs,
|
|
40
|
+
} from '@zenstackhq/orm';
|
|
41
|
+
import type { GetModels, SchemaDef } from '@zenstackhq/schema';
|
|
42
|
+
import { inject, provide, toValue, type MaybeRefOrGetter, type UnwrapRef } from 'vue';
|
|
43
|
+
import {
|
|
44
|
+
DEFAULT_QUERY_ENDPOINT,
|
|
45
|
+
fetcher,
|
|
46
|
+
getQueryKey,
|
|
47
|
+
makeUrl,
|
|
48
|
+
marshal,
|
|
49
|
+
setupInvalidation,
|
|
50
|
+
setupOptimisticUpdate,
|
|
51
|
+
type APIContext,
|
|
52
|
+
type ExtraMutationOptions,
|
|
53
|
+
type ExtraQueryOptions,
|
|
54
|
+
} from './utils/common';
|
|
55
|
+
import type { TrimDelegateModelOperations } from './utils/types';
|
|
56
|
+
|
|
57
|
+
export type { FetchFn } from './utils/common';
|
|
58
|
+
export const VueQueryContextKey = 'zenstack-vue-query-context';
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Provide context for query settings.
|
|
62
|
+
*
|
|
63
|
+
* @deprecated Use {@link provideQuerySettingsContext} instead.
|
|
64
|
+
*/
|
|
65
|
+
export function provideHooksContext(context: APIContext) {
|
|
66
|
+
provide<APIContext>(VueQueryContextKey, context);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Provide context for query settings.
|
|
71
|
+
*/
|
|
72
|
+
export function provideQuerySettingsContext(context: APIContext) {
|
|
73
|
+
provide<APIContext>(VueQueryContextKey, context);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function getQuerySettings() {
|
|
77
|
+
const { endpoint, ...rest } = inject<APIContext>(VueQueryContextKey, {
|
|
78
|
+
endpoint: DEFAULT_QUERY_ENDPOINT,
|
|
79
|
+
fetch: undefined,
|
|
80
|
+
logging: false,
|
|
81
|
+
});
|
|
82
|
+
return { endpoint: endpoint ?? DEFAULT_QUERY_ENDPOINT, ...rest };
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export type ModelQueryOptions<T> = MaybeRefOrGetter<
|
|
86
|
+
Omit<UnwrapRef<UseQueryOptions<T, DefaultError>>, 'queryKey'> & ExtraQueryOptions
|
|
87
|
+
>;
|
|
88
|
+
|
|
89
|
+
export type ModelQueryResult<T> = UseQueryReturnType<T, DefaultError> & { queryKey: QueryKey };
|
|
90
|
+
|
|
91
|
+
export type ModelInfiniteQueryOptions<T> = MaybeRefOrGetter<
|
|
92
|
+
Omit<UnwrapRef<UseInfiniteQueryOptions<T, DefaultError, InfiniteData<T>>>, 'queryKey' | 'initialPageParam'>
|
|
93
|
+
>;
|
|
94
|
+
|
|
95
|
+
export type ModelInfiniteQueryResult<T> = UseInfiniteQueryReturnType<T, DefaultError> & { queryKey: QueryKey };
|
|
96
|
+
|
|
97
|
+
export type ModelMutationOptions<T, TArgs> = MaybeRefOrGetter<
|
|
98
|
+
Omit<UnwrapRef<UseMutationOptions<T, DefaultError, TArgs>>, 'mutationFn'> & ExtraMutationOptions
|
|
99
|
+
>;
|
|
100
|
+
|
|
101
|
+
export type ModelMutationResult<T, TArgs> = UseMutationReturnType<T, DefaultError, TArgs, unknown>;
|
|
102
|
+
|
|
103
|
+
export type ModelMutationModelResult<
|
|
104
|
+
Schema extends SchemaDef,
|
|
105
|
+
Model extends GetModels<Schema>,
|
|
106
|
+
TArgs extends SelectIncludeOmit<Schema, Model, boolean>,
|
|
107
|
+
Array extends boolean = false,
|
|
108
|
+
> = Omit<ModelMutationResult<ModelResult<Schema, Model, TArgs>, TArgs>, 'mutateAsync'> & {
|
|
109
|
+
mutateAsync<T extends TArgs>(
|
|
110
|
+
args: T,
|
|
111
|
+
options?: ModelMutationOptions<ModelResult<Schema, Model, T>, T>,
|
|
112
|
+
): Promise<Array extends true ? ModelResult<Schema, Model, T>[] : ModelResult<Schema, Model, T>>;
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
export type ClientHooks<Schema extends SchemaDef> = {
|
|
116
|
+
[Model in GetModels<Schema> as `${Uncapitalize<Model>}`]: ModelQueryHooks<Schema, Model>;
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
// Note that we can potentially use TypeScript's mapped type to directly map from ORM contract, but that seems
|
|
120
|
+
// to significantly slow down tsc performance ...
|
|
121
|
+
export type ModelQueryHooks<Schema extends SchemaDef, Model extends GetModels<Schema>> = TrimDelegateModelOperations<
|
|
122
|
+
Schema,
|
|
123
|
+
Model,
|
|
124
|
+
{
|
|
125
|
+
useFindUnique<T extends FindUniqueArgs<Schema, Model>>(
|
|
126
|
+
args: SelectSubset<T, FindUniqueArgs<Schema, Model>>,
|
|
127
|
+
options?: ModelQueryOptions<ModelResult<Schema, Model, T> | null>,
|
|
128
|
+
): ModelQueryResult<ModelResult<Schema, Model, T> | null>;
|
|
129
|
+
|
|
130
|
+
useFindFirst<T extends FindArgs<Schema, Model, false>>(
|
|
131
|
+
args?: SelectSubset<T, FindArgs<Schema, Model, false>>,
|
|
132
|
+
options?: ModelQueryOptions<ModelResult<Schema, Model, T> | null>,
|
|
133
|
+
): ModelQueryResult<ModelResult<Schema, Model, T> | null>;
|
|
134
|
+
|
|
135
|
+
useFindMany<T extends FindArgs<Schema, Model, true>>(
|
|
136
|
+
args?: SelectSubset<T, FindArgs<Schema, Model, true>>,
|
|
137
|
+
options?: ModelQueryOptions<ModelResult<Schema, Model, T>[]>,
|
|
138
|
+
): ModelQueryResult<ModelResult<Schema, Model, T>[]>;
|
|
139
|
+
|
|
140
|
+
useInfiniteFindMany<T extends FindArgs<Schema, Model, true>>(
|
|
141
|
+
args?: SelectSubset<T, FindArgs<Schema, Model, true>>,
|
|
142
|
+
options?: ModelInfiniteQueryOptions<ModelResult<Schema, Model, T>[]>,
|
|
143
|
+
): ModelInfiniteQueryResult<InfiniteData<ModelResult<Schema, Model, T>[]>>;
|
|
144
|
+
|
|
145
|
+
useCreate<T extends CreateArgs<Schema, Model>>(
|
|
146
|
+
options?: ModelMutationOptions<ModelResult<Schema, Model, T>, T>,
|
|
147
|
+
): ModelMutationModelResult<Schema, Model, T>;
|
|
148
|
+
|
|
149
|
+
useCreateMany<T extends CreateManyArgs<Schema, Model>>(
|
|
150
|
+
options?: ModelMutationOptions<BatchResult, T>,
|
|
151
|
+
): ModelMutationResult<BatchResult, T>;
|
|
152
|
+
|
|
153
|
+
useCreateManyAndReturn<T extends CreateManyAndReturnArgs<Schema, Model>>(
|
|
154
|
+
options?: ModelMutationOptions<ModelResult<Schema, Model, T>[], T>,
|
|
155
|
+
): ModelMutationModelResult<Schema, Model, T, true>;
|
|
156
|
+
|
|
157
|
+
useUpdate<T extends UpdateArgs<Schema, Model>>(
|
|
158
|
+
options?: ModelMutationOptions<ModelResult<Schema, Model, T>, T>,
|
|
159
|
+
): ModelMutationModelResult<Schema, Model, T>;
|
|
160
|
+
|
|
161
|
+
useUpdateMany<T extends UpdateManyArgs<Schema, Model>>(
|
|
162
|
+
options?: ModelMutationOptions<BatchResult, T>,
|
|
163
|
+
): ModelMutationResult<BatchResult, T>;
|
|
164
|
+
|
|
165
|
+
useUpdateManyAndReturn<T extends UpdateManyAndReturnArgs<Schema, Model>>(
|
|
166
|
+
options?: ModelMutationOptions<ModelResult<Schema, Model, T>[], T>,
|
|
167
|
+
): ModelMutationModelResult<Schema, Model, T, true>;
|
|
168
|
+
|
|
169
|
+
useUpsert<T extends UpsertArgs<Schema, Model>>(
|
|
170
|
+
options?: ModelMutationOptions<ModelResult<Schema, Model, T>, T>,
|
|
171
|
+
): ModelMutationModelResult<Schema, Model, T>;
|
|
172
|
+
|
|
173
|
+
useDelete<T extends DeleteArgs<Schema, Model>>(
|
|
174
|
+
options?: ModelMutationOptions<ModelResult<Schema, Model, T>, T>,
|
|
175
|
+
): ModelMutationModelResult<Schema, Model, T>;
|
|
176
|
+
|
|
177
|
+
useDeleteMany<T extends DeleteManyArgs<Schema, Model>>(
|
|
178
|
+
options?: ModelMutationOptions<BatchResult, T>,
|
|
179
|
+
): ModelMutationResult<BatchResult, T>;
|
|
180
|
+
|
|
181
|
+
useCount<T extends CountArgs<Schema, Model>>(
|
|
182
|
+
args?: Subset<T, CountArgs<Schema, Model>>,
|
|
183
|
+
options?: ModelQueryOptions<CountResult<Schema, Model, T>>,
|
|
184
|
+
): ModelQueryResult<CountResult<Schema, Model, T>>;
|
|
185
|
+
|
|
186
|
+
useAggregate<T extends AggregateArgs<Schema, Model>>(
|
|
187
|
+
args: Subset<T, AggregateArgs<Schema, Model>>,
|
|
188
|
+
options?: ModelQueryOptions<AggregateResult<Schema, Model, T>>,
|
|
189
|
+
): ModelQueryResult<AggregateResult<Schema, Model, T>>;
|
|
190
|
+
|
|
191
|
+
useGroupBy<T extends GroupByArgs<Schema, Model>>(
|
|
192
|
+
args: Subset<T, GroupByArgs<Schema, Model>>,
|
|
193
|
+
options?: ModelQueryOptions<GroupByResult<Schema, Model, T>>,
|
|
194
|
+
): ModelQueryResult<GroupByResult<Schema, Model, T>>;
|
|
195
|
+
}
|
|
196
|
+
>;
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Gets data query hooks for all models in the schema.
|
|
200
|
+
*/
|
|
201
|
+
export function useClientQueries<Schema extends SchemaDef>(schema: Schema): ClientHooks<Schema> {
|
|
202
|
+
return Object.keys(schema.models).reduce((acc, model) => {
|
|
203
|
+
(acc as any)[lowerCaseFirst(model)] = useModelQueries(schema, model as GetModels<Schema>);
|
|
204
|
+
return acc;
|
|
205
|
+
}, {} as ClientHooks<Schema>);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Gets data query hooks for a specific model in the schema.
|
|
210
|
+
*/
|
|
211
|
+
export function useModelQueries<Schema extends SchemaDef, Model extends GetModels<Schema>>(
|
|
212
|
+
schema: Schema,
|
|
213
|
+
model: Model,
|
|
214
|
+
): ModelQueryHooks<Schema, Model> {
|
|
215
|
+
const modelDef = Object.values(schema.models).find((m) => m.name.toLowerCase() === model.toLowerCase());
|
|
216
|
+
if (!modelDef) {
|
|
217
|
+
throw new Error(`Model "${model}" not found in schema`);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
const modelName = modelDef.name;
|
|
221
|
+
|
|
222
|
+
return {
|
|
223
|
+
useFindUnique: (args: any, options?: any) => {
|
|
224
|
+
return useInternalQuery(schema, modelName, 'findUnique', args, options);
|
|
225
|
+
},
|
|
226
|
+
|
|
227
|
+
useFindFirst: (args: any, options?: any) => {
|
|
228
|
+
return useInternalQuery(schema, modelName, 'findFirst', args, options);
|
|
229
|
+
},
|
|
230
|
+
|
|
231
|
+
useFindMany: (args: any, options?: any) => {
|
|
232
|
+
return useInternalQuery(schema, modelName, 'findMany', args, options);
|
|
233
|
+
},
|
|
234
|
+
|
|
235
|
+
useInfiniteFindMany: (args: any, options?: any) => {
|
|
236
|
+
return useInternalInfiniteQuery(schema, modelName, 'findMany', args, options);
|
|
237
|
+
},
|
|
238
|
+
|
|
239
|
+
useCreate: (options?: any) => {
|
|
240
|
+
return useInternalMutation(schema, modelName, 'POST', 'create', options);
|
|
241
|
+
},
|
|
242
|
+
|
|
243
|
+
useCreateMany: (options?: any) => {
|
|
244
|
+
return useInternalMutation(schema, modelName, 'POST', 'createMany', options);
|
|
245
|
+
},
|
|
246
|
+
|
|
247
|
+
useCreateManyAndReturn: (options?: any) => {
|
|
248
|
+
return useInternalMutation(schema, modelName, 'POST', 'createManyAndReturn', options);
|
|
249
|
+
},
|
|
250
|
+
|
|
251
|
+
useUpdate: (options?: any) => {
|
|
252
|
+
return useInternalMutation(schema, modelName, 'PUT', 'update', options);
|
|
253
|
+
},
|
|
254
|
+
|
|
255
|
+
useUpdateMany: (options?: any) => {
|
|
256
|
+
return useInternalMutation(schema, modelName, 'PUT', 'updateMany', options);
|
|
257
|
+
},
|
|
258
|
+
|
|
259
|
+
useUpdateManyAndReturn: (options?: any) => {
|
|
260
|
+
return useInternalMutation(schema, modelName, 'PUT', 'updateManyAndReturn', options);
|
|
261
|
+
},
|
|
262
|
+
|
|
263
|
+
useUpsert: (options?: any) => {
|
|
264
|
+
return useInternalMutation(schema, modelName, 'POST', 'upsert', options);
|
|
265
|
+
},
|
|
266
|
+
|
|
267
|
+
useDelete: (options?: any) => {
|
|
268
|
+
return useInternalMutation(schema, modelName, 'DELETE', 'delete', options);
|
|
269
|
+
},
|
|
270
|
+
|
|
271
|
+
useDeleteMany: (options?: any) => {
|
|
272
|
+
return useInternalMutation(schema, modelName, 'DELETE', 'deleteMany', options);
|
|
273
|
+
},
|
|
274
|
+
|
|
275
|
+
useCount: (args: any, options?: any) => {
|
|
276
|
+
return useInternalQuery(schema, modelName, 'count', args, options);
|
|
277
|
+
},
|
|
278
|
+
|
|
279
|
+
useAggregate: (args: any, options?: any) => {
|
|
280
|
+
return useInternalQuery(schema, modelName, 'aggregate', args, options);
|
|
281
|
+
},
|
|
282
|
+
|
|
283
|
+
useGroupBy: (args: any, options?: any) => {
|
|
284
|
+
return useInternalQuery(schema, modelName, 'groupBy', args, options);
|
|
285
|
+
},
|
|
286
|
+
} as ModelQueryHooks<Schema, Model>;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
export function useInternalQuery<TQueryFnData, TData>(
|
|
290
|
+
_schema: SchemaDef,
|
|
291
|
+
model: string,
|
|
292
|
+
operation: string,
|
|
293
|
+
args?: MaybeRefOrGetter<unknown>,
|
|
294
|
+
options?: MaybeRefOrGetter<
|
|
295
|
+
Omit<UnwrapRef<UseQueryOptions<TQueryFnData, DefaultError, TData>>, 'queryKey'> & ExtraQueryOptions
|
|
296
|
+
>,
|
|
297
|
+
) {
|
|
298
|
+
const argsValue = toValue(args);
|
|
299
|
+
const { optimisticUpdate, ...restOptions } = toValue(options) ?? {};
|
|
300
|
+
const queryKey = getQueryKey(model, operation, argsValue, {
|
|
301
|
+
infinite: false,
|
|
302
|
+
optimisticUpdate: optimisticUpdate !== false,
|
|
303
|
+
});
|
|
304
|
+
const { endpoint, fetch } = getQuerySettings();
|
|
305
|
+
|
|
306
|
+
const finalOptions: any = {
|
|
307
|
+
queryKey,
|
|
308
|
+
queryFn: ({ queryKey, signal }: any) => {
|
|
309
|
+
const [_prefix, _model, _op, args] = queryKey;
|
|
310
|
+
const reqUrl = makeUrl(endpoint, model, operation, args);
|
|
311
|
+
return fetcher<TQueryFnData>(reqUrl, { signal }, fetch);
|
|
312
|
+
},
|
|
313
|
+
...restOptions,
|
|
314
|
+
};
|
|
315
|
+
return { queryKey, ...useQuery<TQueryFnData, DefaultError, TData>(finalOptions) };
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
export function useInternalInfiniteQuery<TQueryFnData, TData>(
|
|
319
|
+
_schema: SchemaDef,
|
|
320
|
+
model: string,
|
|
321
|
+
operation: string,
|
|
322
|
+
args: MaybeRefOrGetter<unknown>,
|
|
323
|
+
options:
|
|
324
|
+
| MaybeRefOrGetter<
|
|
325
|
+
Omit<
|
|
326
|
+
UnwrapRef<UseInfiniteQueryOptions<TQueryFnData, DefaultError, InfiniteData<TData>>>,
|
|
327
|
+
'queryKey' | 'initialPageParam'
|
|
328
|
+
>
|
|
329
|
+
>
|
|
330
|
+
| undefined,
|
|
331
|
+
) {
|
|
332
|
+
options = options ?? { getNextPageParam: () => undefined };
|
|
333
|
+
const { endpoint, fetch } = getQuerySettings();
|
|
334
|
+
const argsValue = toValue(args);
|
|
335
|
+
const optionsValue = toValue(options);
|
|
336
|
+
const queryKey = getQueryKey(model, operation, argsValue, { infinite: true, optimisticUpdate: false });
|
|
337
|
+
|
|
338
|
+
const finalOptions: any = {
|
|
339
|
+
queryKey,
|
|
340
|
+
queryFn: ({ queryKey, signal }: any) => {
|
|
341
|
+
const [_prefix, _model, _op, args] = queryKey;
|
|
342
|
+
const reqUrl = makeUrl(endpoint, model, operation, args);
|
|
343
|
+
return fetcher<TQueryFnData>(reqUrl, { signal }, fetch);
|
|
344
|
+
},
|
|
345
|
+
initialPageParam: argsValue,
|
|
346
|
+
...optionsValue,
|
|
347
|
+
};
|
|
348
|
+
return {
|
|
349
|
+
queryKey,
|
|
350
|
+
...useInfiniteQuery(finalOptions),
|
|
351
|
+
};
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
/**
|
|
355
|
+
* Creates a vue-query mutation
|
|
356
|
+
*
|
|
357
|
+
* @private
|
|
358
|
+
*
|
|
359
|
+
* @param model The name of the model under mutation.
|
|
360
|
+
* @param method The HTTP method.
|
|
361
|
+
* @param operation The mutation operation (e.g. `create`).
|
|
362
|
+
* @param options The vue-query options.
|
|
363
|
+
* @param checkReadBack Whether to check for read back errors and return undefined if found.
|
|
364
|
+
*/
|
|
365
|
+
export function useInternalMutation<TArgs, R = any>(
|
|
366
|
+
schema: SchemaDef,
|
|
367
|
+
model: string,
|
|
368
|
+
method: 'POST' | 'PUT' | 'DELETE',
|
|
369
|
+
operation: string,
|
|
370
|
+
options?: MaybeRefOrGetter<
|
|
371
|
+
Omit<UnwrapRef<UseMutationOptions<R, DefaultError, TArgs>>, 'mutationFn'> & ExtraMutationOptions
|
|
372
|
+
>,
|
|
373
|
+
) {
|
|
374
|
+
const { endpoint, fetch, logging } = getQuerySettings();
|
|
375
|
+
const queryClient = useQueryClient();
|
|
376
|
+
const mutationFn = (data: any) => {
|
|
377
|
+
const reqUrl =
|
|
378
|
+
method === 'DELETE' ? makeUrl(endpoint, model, operation, data) : makeUrl(endpoint, model, operation);
|
|
379
|
+
const fetchInit: RequestInit = {
|
|
380
|
+
method,
|
|
381
|
+
...(method !== 'DELETE' && {
|
|
382
|
+
headers: {
|
|
383
|
+
'content-type': 'application/json',
|
|
384
|
+
},
|
|
385
|
+
body: marshal(data),
|
|
386
|
+
}),
|
|
387
|
+
};
|
|
388
|
+
return fetcher<R>(reqUrl, fetchInit, fetch) as Promise<R>;
|
|
389
|
+
};
|
|
390
|
+
|
|
391
|
+
const optionsValue = toValue(options);
|
|
392
|
+
const finalOptions: any = { ...optionsValue, mutationFn };
|
|
393
|
+
const invalidateQueries = optionsValue?.invalidateQueries !== false;
|
|
394
|
+
const optimisticUpdate = !!optionsValue?.optimisticUpdate;
|
|
395
|
+
|
|
396
|
+
if (operation) {
|
|
397
|
+
if (invalidateQueries) {
|
|
398
|
+
setupInvalidation(
|
|
399
|
+
model,
|
|
400
|
+
operation,
|
|
401
|
+
schema,
|
|
402
|
+
finalOptions,
|
|
403
|
+
(predicate) => queryClient.invalidateQueries({ predicate }),
|
|
404
|
+
logging,
|
|
405
|
+
);
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
if (optimisticUpdate) {
|
|
409
|
+
setupOptimisticUpdate(
|
|
410
|
+
model,
|
|
411
|
+
operation,
|
|
412
|
+
schema,
|
|
413
|
+
finalOptions,
|
|
414
|
+
queryClient.getQueryCache().getAll(),
|
|
415
|
+
(queryKey, data) => {
|
|
416
|
+
// update query cache
|
|
417
|
+
queryClient.setQueryData<unknown>(queryKey, data);
|
|
418
|
+
// cancel on-flight queries to avoid redundant cache updates,
|
|
419
|
+
// the settlement of the current mutation will trigger a new revalidation
|
|
420
|
+
queryClient.cancelQueries({ queryKey }, { revert: false, silent: true });
|
|
421
|
+
},
|
|
422
|
+
invalidateQueries ? (predicate) => queryClient.invalidateQueries({ predicate }) : undefined,
|
|
423
|
+
logging,
|
|
424
|
+
);
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
return useMutation(finalOptions);
|
|
429
|
+
}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { useClientQueries } from '../src/react';
|
|
2
|
+
import { schema } from './schemas/basic/schema-lite';
|
|
3
|
+
|
|
4
|
+
const client = useClientQueries(schema);
|
|
5
|
+
|
|
6
|
+
// @ts-expect-error missing args
|
|
7
|
+
client.user.useFindUnique();
|
|
8
|
+
|
|
9
|
+
check(client.user.useFindUnique({ where: { id: '1' } }).data?.email);
|
|
10
|
+
check(client.user.useFindUnique({ where: { id: '1' } }).queryKey);
|
|
11
|
+
check(client.user.useFindUnique({ where: { id: '1' } }, { optimisticUpdate: true, enabled: false }));
|
|
12
|
+
|
|
13
|
+
// @ts-expect-error unselected field
|
|
14
|
+
check(client.user.useFindUnique({ select: { email: true } }).data.name);
|
|
15
|
+
|
|
16
|
+
check(client.user.useFindUnique({ where: { id: '1' }, include: { posts: true } }).data?.posts[0]?.title);
|
|
17
|
+
|
|
18
|
+
check(client.user.useFindFirst().data?.email);
|
|
19
|
+
|
|
20
|
+
check(client.user.useFindMany().data?.[0]?.email);
|
|
21
|
+
|
|
22
|
+
check(client.user.useInfiniteFindMany().data?.pages[0]?.[0]?.email);
|
|
23
|
+
check(
|
|
24
|
+
client.user.useInfiniteFindMany(
|
|
25
|
+
{},
|
|
26
|
+
{
|
|
27
|
+
getNextPageParam: () => ({ id: '2' }),
|
|
28
|
+
},
|
|
29
|
+
).data?.pages[1]?.[0]?.email,
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
check(client.user.useSuspenseFindMany().data[0]?.email);
|
|
33
|
+
check(client.user.useSuspenseInfiniteFindMany().data.pages[0]?.[0]?.email);
|
|
34
|
+
check(client.user.useCount().data?.toFixed(2));
|
|
35
|
+
check(client.user.useCount({ select: { email: true } }).data?.email.toFixed(2));
|
|
36
|
+
|
|
37
|
+
check(client.user.useAggregate({ _max: { email: true } }).data?._max.email);
|
|
38
|
+
|
|
39
|
+
check(client.user.useGroupBy({ by: ['email'], _max: { name: true } }).data?.[0]?._max.name);
|
|
40
|
+
|
|
41
|
+
// @ts-expect-error missing args
|
|
42
|
+
client.user.useCreate().mutate();
|
|
43
|
+
client.user.useCreate().mutate({ data: { email: 'test@example.com' } });
|
|
44
|
+
client.user
|
|
45
|
+
.useCreate({ optimisticUpdate: true, invalidateQueries: false, retry: 3 })
|
|
46
|
+
.mutate({ data: { email: 'test@example.com' } });
|
|
47
|
+
|
|
48
|
+
client.user
|
|
49
|
+
.useCreate()
|
|
50
|
+
.mutateAsync({ data: { email: 'test@example.com' }, include: { posts: true } })
|
|
51
|
+
.then((d) => check(d.posts[0]?.title));
|
|
52
|
+
|
|
53
|
+
client.user
|
|
54
|
+
.useCreateMany()
|
|
55
|
+
.mutateAsync({
|
|
56
|
+
data: [{ email: 'test@example.com' }, { email: 'test2@example.com' }],
|
|
57
|
+
skipDuplicates: true,
|
|
58
|
+
})
|
|
59
|
+
.then((d) => d.count);
|
|
60
|
+
|
|
61
|
+
client.user
|
|
62
|
+
.useCreateManyAndReturn()
|
|
63
|
+
.mutateAsync({
|
|
64
|
+
data: [{ email: 'test@example.com' }],
|
|
65
|
+
})
|
|
66
|
+
.then((d) => check(d[0]?.name));
|
|
67
|
+
|
|
68
|
+
client.user
|
|
69
|
+
.useCreateManyAndReturn()
|
|
70
|
+
.mutateAsync({
|
|
71
|
+
data: [{ email: 'test@example.com' }],
|
|
72
|
+
select: { email: true },
|
|
73
|
+
})
|
|
74
|
+
// @ts-expect-error unselected field
|
|
75
|
+
.then((d) => check(d[0].name));
|
|
76
|
+
|
|
77
|
+
client.user.useUpdate().mutate(
|
|
78
|
+
{ data: { email: 'updated@example.com' }, where: { id: '1' } },
|
|
79
|
+
{
|
|
80
|
+
onSuccess: (d) => {
|
|
81
|
+
check(d.email);
|
|
82
|
+
},
|
|
83
|
+
},
|
|
84
|
+
);
|
|
85
|
+
|
|
86
|
+
client.user.useUpdateMany().mutate({ data: { email: 'updated@example.com' } });
|
|
87
|
+
|
|
88
|
+
client.user
|
|
89
|
+
.useUpdateManyAndReturn()
|
|
90
|
+
.mutateAsync({ data: { email: 'updated@example.com' } })
|
|
91
|
+
.then((d) => check(d[0]?.email));
|
|
92
|
+
|
|
93
|
+
client.user
|
|
94
|
+
.useUpsert()
|
|
95
|
+
.mutate({ where: { id: '1' }, create: { email: 'new@example.com' }, update: { email: 'updated@example.com' } });
|
|
96
|
+
|
|
97
|
+
client.user.useDelete().mutate({ where: { id: '1' }, include: { posts: true } });
|
|
98
|
+
|
|
99
|
+
client.user.useDeleteMany().mutate({ where: { email: 'test@example.com' } });
|
|
100
|
+
|
|
101
|
+
function check(_value: unknown) {
|
|
102
|
+
// noop
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// @ts-expect-error delegate model
|
|
106
|
+
client.foo.useCreate();
|
|
107
|
+
|
|
108
|
+
client.foo.useUpdate();
|
|
109
|
+
client.bar.useCreate();
|
|
@@ -68,3 +68,43 @@ export type CategorySelect = $SelectInput<$Schema, "Category">;
|
|
|
68
68
|
export type CategoryInclude = $IncludeInput<$Schema, "Category">;
|
|
69
69
|
export type CategoryOmit = $OmitInput<$Schema, "Category">;
|
|
70
70
|
export type CategoryGetPayload<Args extends $SelectIncludeOmit<$Schema, "Category", true>> = $SimplifiedModelResult<$Schema, "Category", Args>;
|
|
71
|
+
export type FooFindManyArgs = $FindManyArgs<$Schema, "Foo">;
|
|
72
|
+
export type FooFindUniqueArgs = $FindUniqueArgs<$Schema, "Foo">;
|
|
73
|
+
export type FooFindFirstArgs = $FindFirstArgs<$Schema, "Foo">;
|
|
74
|
+
export type FooCreateArgs = $CreateArgs<$Schema, "Foo">;
|
|
75
|
+
export type FooCreateManyArgs = $CreateManyArgs<$Schema, "Foo">;
|
|
76
|
+
export type FooCreateManyAndReturnArgs = $CreateManyAndReturnArgs<$Schema, "Foo">;
|
|
77
|
+
export type FooUpdateArgs = $UpdateArgs<$Schema, "Foo">;
|
|
78
|
+
export type FooUpdateManyArgs = $UpdateManyArgs<$Schema, "Foo">;
|
|
79
|
+
export type FooUpdateManyAndReturnArgs = $UpdateManyAndReturnArgs<$Schema, "Foo">;
|
|
80
|
+
export type FooUpsertArgs = $UpsertArgs<$Schema, "Foo">;
|
|
81
|
+
export type FooDeleteArgs = $DeleteArgs<$Schema, "Foo">;
|
|
82
|
+
export type FooDeleteManyArgs = $DeleteManyArgs<$Schema, "Foo">;
|
|
83
|
+
export type FooCountArgs = $CountArgs<$Schema, "Foo">;
|
|
84
|
+
export type FooAggregateArgs = $AggregateArgs<$Schema, "Foo">;
|
|
85
|
+
export type FooGroupByArgs = $GroupByArgs<$Schema, "Foo">;
|
|
86
|
+
export type FooWhereInput = $WhereInput<$Schema, "Foo">;
|
|
87
|
+
export type FooSelect = $SelectInput<$Schema, "Foo">;
|
|
88
|
+
export type FooInclude = $IncludeInput<$Schema, "Foo">;
|
|
89
|
+
export type FooOmit = $OmitInput<$Schema, "Foo">;
|
|
90
|
+
export type FooGetPayload<Args extends $SelectIncludeOmit<$Schema, "Foo", true>> = $SimplifiedModelResult<$Schema, "Foo", Args>;
|
|
91
|
+
export type BarFindManyArgs = $FindManyArgs<$Schema, "Bar">;
|
|
92
|
+
export type BarFindUniqueArgs = $FindUniqueArgs<$Schema, "Bar">;
|
|
93
|
+
export type BarFindFirstArgs = $FindFirstArgs<$Schema, "Bar">;
|
|
94
|
+
export type BarCreateArgs = $CreateArgs<$Schema, "Bar">;
|
|
95
|
+
export type BarCreateManyArgs = $CreateManyArgs<$Schema, "Bar">;
|
|
96
|
+
export type BarCreateManyAndReturnArgs = $CreateManyAndReturnArgs<$Schema, "Bar">;
|
|
97
|
+
export type BarUpdateArgs = $UpdateArgs<$Schema, "Bar">;
|
|
98
|
+
export type BarUpdateManyArgs = $UpdateManyArgs<$Schema, "Bar">;
|
|
99
|
+
export type BarUpdateManyAndReturnArgs = $UpdateManyAndReturnArgs<$Schema, "Bar">;
|
|
100
|
+
export type BarUpsertArgs = $UpsertArgs<$Schema, "Bar">;
|
|
101
|
+
export type BarDeleteArgs = $DeleteArgs<$Schema, "Bar">;
|
|
102
|
+
export type BarDeleteManyArgs = $DeleteManyArgs<$Schema, "Bar">;
|
|
103
|
+
export type BarCountArgs = $CountArgs<$Schema, "Bar">;
|
|
104
|
+
export type BarAggregateArgs = $AggregateArgs<$Schema, "Bar">;
|
|
105
|
+
export type BarGroupByArgs = $GroupByArgs<$Schema, "Bar">;
|
|
106
|
+
export type BarWhereInput = $WhereInput<$Schema, "Bar">;
|
|
107
|
+
export type BarSelect = $SelectInput<$Schema, "Bar">;
|
|
108
|
+
export type BarInclude = $IncludeInput<$Schema, "Bar">;
|
|
109
|
+
export type BarOmit = $OmitInput<$Schema, "Bar">;
|
|
110
|
+
export type BarGetPayload<Args extends $SelectIncludeOmit<$Schema, "Bar", true>> = $SimplifiedModelResult<$Schema, "Bar", Args>;
|
|
@@ -10,3 +10,5 @@ import { type ModelResult as $ModelResult } from "@zenstackhq/orm";
|
|
|
10
10
|
export type User = $ModelResult<$Schema, "User">;
|
|
11
11
|
export type Post = $ModelResult<$Schema, "Post">;
|
|
12
12
|
export type Category = $ModelResult<$Schema, "Category">;
|
|
13
|
+
export type Foo = $ModelResult<$Schema, "Foo">;
|
|
14
|
+
export type Bar = $ModelResult<$Schema, "Bar">;
|
|
@@ -116,6 +116,54 @@ export const schema = {
|
|
|
116
116
|
id: { type: "String" },
|
|
117
117
|
name: { type: "String" }
|
|
118
118
|
}
|
|
119
|
+
},
|
|
120
|
+
Foo: {
|
|
121
|
+
name: "Foo",
|
|
122
|
+
fields: {
|
|
123
|
+
id: {
|
|
124
|
+
name: "id",
|
|
125
|
+
type: "String",
|
|
126
|
+
id: true,
|
|
127
|
+
default: ExpressionUtils.call("cuid")
|
|
128
|
+
},
|
|
129
|
+
type: {
|
|
130
|
+
name: "type",
|
|
131
|
+
type: "String",
|
|
132
|
+
isDiscriminator: true
|
|
133
|
+
}
|
|
134
|
+
},
|
|
135
|
+
idFields: ["id"],
|
|
136
|
+
uniqueFields: {
|
|
137
|
+
id: { type: "String" }
|
|
138
|
+
},
|
|
139
|
+
isDelegate: true,
|
|
140
|
+
subModels: ["Bar"]
|
|
141
|
+
},
|
|
142
|
+
Bar: {
|
|
143
|
+
name: "Bar",
|
|
144
|
+
baseModel: "Foo",
|
|
145
|
+
fields: {
|
|
146
|
+
id: {
|
|
147
|
+
name: "id",
|
|
148
|
+
type: "String",
|
|
149
|
+
id: true,
|
|
150
|
+
default: ExpressionUtils.call("cuid")
|
|
151
|
+
},
|
|
152
|
+
type: {
|
|
153
|
+
name: "type",
|
|
154
|
+
type: "String",
|
|
155
|
+
originModel: "Foo",
|
|
156
|
+
isDiscriminator: true
|
|
157
|
+
},
|
|
158
|
+
title: {
|
|
159
|
+
name: "title",
|
|
160
|
+
type: "String"
|
|
161
|
+
}
|
|
162
|
+
},
|
|
163
|
+
idFields: ["id"],
|
|
164
|
+
uniqueFields: {
|
|
165
|
+
id: { type: "String" }
|
|
166
|
+
}
|
|
119
167
|
}
|
|
120
168
|
},
|
|
121
169
|
authType: "User",
|