@zenstackhq/tanstack-query 1.1.1 → 1.2.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/generator.js +70 -37
- package/generator.js.map +1 -1
- package/package.json +40 -9
- package/runtime/common-5e18c135.d.ts +32 -0
- package/runtime/index.d.mts +1 -1
- package/runtime/index.d.ts +1 -1
- package/runtime/index.js +34 -0
- package/runtime/index.js.map +1 -1
- package/runtime/index.mjs +15 -0
- package/runtime/index.mjs.map +1 -1
- package/runtime/react.d.mts +17 -26
- package/runtime/react.d.ts +17 -26
- package/runtime/react.js +105 -72
- package/runtime/react.js.map +1 -1
- package/runtime/react.mjs +102 -68
- package/runtime/react.mjs.map +1 -1
- package/runtime/svelte.d.mts +16 -25
- package/runtime/svelte.d.ts +16 -25
- package/runtime/svelte.js +97 -71
- package/runtime/svelte.js.map +1 -1
- package/runtime/svelte.mjs +93 -66
- package/runtime/svelte.mjs.map +1 -1
- package/runtime/vue.d.mts +17 -27
- package/runtime/vue.d.ts +17 -27
- package/runtime/vue.js +105 -77
- package/runtime/vue.js.map +1 -1
- package/runtime/vue.mjs +101 -71
- package/runtime/vue.mjs.map +1 -1
- package/runtime-v5/common-5e18c135.d.ts +32 -0
- package/runtime-v5/index.d.mts +20 -0
- package/runtime-v5/index.d.ts +20 -0
- package/runtime-v5/index.js +53 -0
- package/runtime-v5/index.js.map +1 -0
- package/runtime-v5/index.mjs +16 -0
- package/runtime-v5/index.mjs.map +1 -0
- package/runtime-v5/react.d.mts +45 -0
- package/runtime-v5/react.d.ts +45 -0
- package/runtime-v5/react.js +269 -0
- package/runtime-v5/react.js.map +1 -0
- package/runtime-v5/react.mjs +237 -0
- package/runtime-v5/react.mjs.map +1 -0
- package/runtime-v5/svelte.d.mts +56 -0
- package/runtime-v5/svelte.d.ts +56 -0
- package/runtime-v5/svelte.js +296 -0
- package/runtime-v5/svelte.js.map +1 -0
- package/runtime-v5/svelte.mjs +264 -0
- package/runtime-v5/svelte.mjs.map +1 -0
- package/runtime-v5/vue.d.mts +52 -0
- package/runtime-v5/vue.d.ts +52 -0
- package/runtime-v5/vue.js +274 -0
- package/runtime-v5/vue.js.map +1 -0
- package/runtime-v5/vue.mjs +240 -0
- package/runtime-v5/vue.mjs.map +1 -0
- package/runtime/common-83308e88.d.ts +0 -19
package/runtime/react.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import * as _tanstack_react_query from '@tanstack/react-query';
|
|
2
2
|
import { UseQueryOptions, UseInfiniteQueryOptions, UseMutationOptions } from '@tanstack/react-query';
|
|
3
3
|
import * as react from 'react';
|
|
4
|
-
import {
|
|
4
|
+
import { ModelMeta } from '@zenstackhq/runtime/cross';
|
|
5
|
+
import { A as APIContext, F as FetchFn } from './common-5e18c135.js';
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* Context for configuring react hooks.
|
|
@@ -11,6 +12,14 @@ declare const RequestHandlerContext: react.Context<APIContext>;
|
|
|
11
12
|
* Context provider.
|
|
12
13
|
*/
|
|
13
14
|
declare const Provider: react.Provider<APIContext>;
|
|
15
|
+
/**
|
|
16
|
+
* Hooks context.
|
|
17
|
+
*/
|
|
18
|
+
declare function getHooksContext(): {
|
|
19
|
+
fetch?: FetchFn | undefined;
|
|
20
|
+
logging?: boolean | undefined;
|
|
21
|
+
endpoint: string;
|
|
22
|
+
};
|
|
14
23
|
/**
|
|
15
24
|
* Creates a react-query query.
|
|
16
25
|
*
|
|
@@ -20,7 +29,7 @@ declare const Provider: react.Provider<APIContext>;
|
|
|
20
29
|
* @param options The react-query options object
|
|
21
30
|
* @returns useQuery hook
|
|
22
31
|
*/
|
|
23
|
-
declare function
|
|
32
|
+
declare function useModelQuery<R>(model: string, url: string, args?: unknown, options?: Omit<UseQueryOptions<R>, 'queryKey'>, fetch?: FetchFn): _tanstack_react_query.UseQueryResult<R, unknown>;
|
|
24
33
|
/**
|
|
25
34
|
* Creates a react-query infinite query.
|
|
26
35
|
*
|
|
@@ -30,36 +39,18 @@ declare function query<R>(model: string, url: string, args?: unknown, options?:
|
|
|
30
39
|
* @param options The react-query infinite query options object
|
|
31
40
|
* @returns useInfiniteQuery hook
|
|
32
41
|
*/
|
|
33
|
-
declare function
|
|
34
|
-
/**
|
|
35
|
-
* Creates a POST mutation with react-query.
|
|
36
|
-
*
|
|
37
|
-
* @param model The name of the model under mutation.
|
|
38
|
-
* @param url The request URL.
|
|
39
|
-
* @param options The react-query options.
|
|
40
|
-
* @param invalidateQueries Whether to invalidate queries after mutation.
|
|
41
|
-
* @returns useMutation hooks
|
|
42
|
-
*/
|
|
43
|
-
declare function postMutation<T, R = any, C extends boolean = boolean, Result = C extends true ? R | undefined : R>(model: string, url: string, options?: Omit<UseMutationOptions<Result, unknown, T>, 'mutationFn'>, fetch?: FetchFn, invalidateQueries?: boolean, checkReadBack?: C): _tanstack_react_query.UseMutationResult<Result, unknown, T, unknown>;
|
|
44
|
-
/**
|
|
45
|
-
* Creates a PUT mutation with react-query.
|
|
46
|
-
*
|
|
47
|
-
* @param model The name of the model under mutation.
|
|
48
|
-
* @param url The request URL.
|
|
49
|
-
* @param options The react-query options.
|
|
50
|
-
* @param invalidateQueries Whether to invalidate queries after mutation.
|
|
51
|
-
* @returns useMutation hooks
|
|
52
|
-
*/
|
|
53
|
-
declare function putMutation<T, R = any, C extends boolean = boolean, Result = C extends true ? R | undefined : R>(model: string, url: string, options?: Omit<UseMutationOptions<Result, unknown, T>, 'mutationFn'>, fetch?: FetchFn, invalidateQueries?: boolean, checkReadBack?: C): _tanstack_react_query.UseMutationResult<Result, unknown, T, unknown>;
|
|
42
|
+
declare function useInfiniteModelQuery<R>(model: string, url: string, args?: unknown, options?: Omit<UseInfiniteQueryOptions<R>, 'queryKey'>, fetch?: FetchFn): _tanstack_react_query.UseInfiniteQueryResult<R, unknown>;
|
|
54
43
|
/**
|
|
55
|
-
* Creates a
|
|
44
|
+
* Creates a mutation with react-query.
|
|
56
45
|
*
|
|
57
46
|
* @param model The name of the model under mutation.
|
|
47
|
+
* @param method The HTTP method.
|
|
48
|
+
* @param modelMeta The model metadata.
|
|
58
49
|
* @param url The request URL.
|
|
59
50
|
* @param options The react-query options.
|
|
60
51
|
* @param invalidateQueries Whether to invalidate queries after mutation.
|
|
61
52
|
* @returns useMutation hooks
|
|
62
53
|
*/
|
|
63
|
-
declare function
|
|
54
|
+
declare function useModelMutation<T, R = any, C extends boolean = boolean, Result = C extends true ? R | undefined : R>(model: string, method: 'POST' | 'PUT' | 'DELETE', url: string, modelMeta: ModelMeta, options?: Omit<UseMutationOptions<Result, unknown, T>, 'mutationFn'>, fetch?: FetchFn, invalidateQueries?: boolean, checkReadBack?: C): _tanstack_react_query.UseMutationResult<Result, unknown, T, unknown>;
|
|
64
55
|
|
|
65
|
-
export { Provider, RequestHandlerContext,
|
|
56
|
+
export { Provider, RequestHandlerContext, getHooksContext, useInfiniteModelQuery, useModelMutation, useModelQuery };
|
package/runtime/react.js
CHANGED
|
@@ -22,6 +22,18 @@ var __spreadValues = (a, b) => {
|
|
|
22
22
|
return a;
|
|
23
23
|
};
|
|
24
24
|
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
25
|
+
var __objRest = (source, exclude) => {
|
|
26
|
+
var target = {};
|
|
27
|
+
for (var prop in source)
|
|
28
|
+
if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)
|
|
29
|
+
target[prop] = source[prop];
|
|
30
|
+
if (source != null && __getOwnPropSymbols)
|
|
31
|
+
for (var prop of __getOwnPropSymbols(source)) {
|
|
32
|
+
if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
|
|
33
|
+
target[prop] = source[prop];
|
|
34
|
+
}
|
|
35
|
+
return target;
|
|
36
|
+
};
|
|
25
37
|
var __export = (target, all) => {
|
|
26
38
|
for (var name in all)
|
|
27
39
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
@@ -69,11 +81,10 @@ var react_exports = {};
|
|
|
69
81
|
__export(react_exports, {
|
|
70
82
|
Provider: () => Provider,
|
|
71
83
|
RequestHandlerContext: () => RequestHandlerContext,
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
query: () => query
|
|
84
|
+
getHooksContext: () => getHooksContext,
|
|
85
|
+
useInfiniteModelQuery: () => useInfiniteModelQuery,
|
|
86
|
+
useModelMutation: () => useModelMutation,
|
|
87
|
+
useModelQuery: () => useModelQuery
|
|
77
88
|
});
|
|
78
89
|
module.exports = __toCommonJS(react_exports);
|
|
79
90
|
var import_react_query = require("@tanstack/react-query");
|
|
@@ -81,9 +92,10 @@ var import_react = require("react");
|
|
|
81
92
|
|
|
82
93
|
// src/runtime/common.ts
|
|
83
94
|
var import_browser = require("@zenstackhq/runtime/browser");
|
|
95
|
+
var import_cross = require("@zenstackhq/runtime/cross");
|
|
84
96
|
var crossFetch = __toESM(require("cross-fetch"));
|
|
85
97
|
var DEFAULT_QUERY_ENDPOINT = "/api/model";
|
|
86
|
-
var QUERY_KEY_PREFIX = "zenstack
|
|
98
|
+
var QUERY_KEY_PREFIX = "zenstack";
|
|
87
99
|
function fetcher(url, options, fetch2, checkReadBack) {
|
|
88
100
|
return __async(this, null, function* () {
|
|
89
101
|
var _a, _b, _c;
|
|
@@ -110,6 +122,13 @@ function fetcher(url, options, fetch2, checkReadBack) {
|
|
|
110
122
|
}
|
|
111
123
|
});
|
|
112
124
|
}
|
|
125
|
+
function getQueryKey(model, urlOrOperation, args) {
|
|
126
|
+
if (!urlOrOperation) {
|
|
127
|
+
throw new Error("Invalid urlOrOperation");
|
|
128
|
+
}
|
|
129
|
+
const operation = urlOrOperation.split("/").pop();
|
|
130
|
+
return [QUERY_KEY_PREFIX, model, operation, args];
|
|
131
|
+
}
|
|
113
132
|
function marshal(value) {
|
|
114
133
|
const { data, meta } = (0, import_browser.serialize)(value);
|
|
115
134
|
if (meta) {
|
|
@@ -139,99 +158,113 @@ function makeUrl(url, args) {
|
|
|
139
158
|
}
|
|
140
159
|
return result;
|
|
141
160
|
}
|
|
161
|
+
function setupInvalidation(model, operation, modelMeta, options, invalidate, logging = false) {
|
|
162
|
+
const origOnSuccess = options == null ? void 0 : options.onSuccess;
|
|
163
|
+
options.onSuccess = (...args) => __async(this, null, function* () {
|
|
164
|
+
const [_, variables] = args;
|
|
165
|
+
const predicate = yield getInvalidationPredicate(
|
|
166
|
+
model,
|
|
167
|
+
operation,
|
|
168
|
+
variables,
|
|
169
|
+
modelMeta,
|
|
170
|
+
logging
|
|
171
|
+
);
|
|
172
|
+
yield invalidate(predicate);
|
|
173
|
+
return origOnSuccess == null ? void 0 : origOnSuccess(...args);
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
function getInvalidationPredicate(model, operation, mutationArgs, modelMeta, logging = false) {
|
|
177
|
+
return __async(this, null, function* () {
|
|
178
|
+
const mutatedModels = yield (0, import_cross.getMutatedModels)(model, operation, mutationArgs, modelMeta);
|
|
179
|
+
return ({ queryKey }) => {
|
|
180
|
+
const [_model, queryModel, queryOp, args] = queryKey;
|
|
181
|
+
if (mutatedModels.includes(queryModel)) {
|
|
182
|
+
if (logging) {
|
|
183
|
+
console.log(`Invalidating query [${queryKey}] due to mutation "${model}.${operation}"`);
|
|
184
|
+
}
|
|
185
|
+
return true;
|
|
186
|
+
}
|
|
187
|
+
if (args) {
|
|
188
|
+
if (findNestedRead(queryModel, mutatedModels, modelMeta, args)) {
|
|
189
|
+
if (logging) {
|
|
190
|
+
console.log(`Invalidating query [${queryKey}] due to mutation "${model}.${operation}"`);
|
|
191
|
+
}
|
|
192
|
+
return true;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
return false;
|
|
196
|
+
};
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
function findNestedRead(visitingModel, targetModels, modelMeta, args) {
|
|
200
|
+
const modelsRead = (0, import_cross.getReadModels)(visitingModel, modelMeta, args);
|
|
201
|
+
return targetModels.some((m) => modelsRead.includes(m));
|
|
202
|
+
}
|
|
142
203
|
|
|
143
204
|
// src/runtime/react.ts
|
|
144
205
|
var RequestHandlerContext = (0, import_react.createContext)({
|
|
145
206
|
endpoint: DEFAULT_QUERY_ENDPOINT,
|
|
146
|
-
fetch: void 0
|
|
207
|
+
fetch: void 0,
|
|
208
|
+
logging: false
|
|
147
209
|
});
|
|
148
210
|
var Provider = RequestHandlerContext.Provider;
|
|
149
|
-
function
|
|
211
|
+
function getHooksContext() {
|
|
212
|
+
const _a = (0, import_react.useContext)(RequestHandlerContext), { endpoint } = _a, rest = __objRest(_a, ["endpoint"]);
|
|
213
|
+
return __spreadValues({ endpoint: endpoint != null ? endpoint : DEFAULT_QUERY_ENDPOINT }, rest);
|
|
214
|
+
}
|
|
215
|
+
function useModelQuery(model, url, args, options, fetch2) {
|
|
150
216
|
const reqUrl = makeUrl(url, args);
|
|
151
217
|
return (0, import_react_query.useQuery)(__spreadValues({
|
|
152
|
-
queryKey:
|
|
218
|
+
queryKey: getQueryKey(model, url, args),
|
|
153
219
|
queryFn: () => fetcher(reqUrl, void 0, fetch2, false)
|
|
154
220
|
}, options));
|
|
155
221
|
}
|
|
156
|
-
function
|
|
222
|
+
function useInfiniteModelQuery(model, url, args, options, fetch2) {
|
|
157
223
|
return (0, import_react_query.useInfiniteQuery)(__spreadValues({
|
|
158
|
-
queryKey:
|
|
224
|
+
queryKey: getQueryKey(model, url, args),
|
|
159
225
|
queryFn: ({ pageParam }) => {
|
|
160
226
|
return fetcher(makeUrl(url, pageParam != null ? pageParam : args), void 0, fetch2, false);
|
|
161
227
|
}
|
|
162
228
|
}, options));
|
|
163
229
|
}
|
|
164
|
-
function
|
|
230
|
+
function useModelMutation(model, method, url, modelMeta, options, fetch2, invalidateQueries = true, checkReadBack) {
|
|
165
231
|
const queryClient = (0, import_react_query.useQueryClient)();
|
|
166
|
-
const mutationFn = (data) =>
|
|
167
|
-
url,
|
|
168
|
-
{
|
|
169
|
-
method
|
|
232
|
+
const mutationFn = (data) => {
|
|
233
|
+
const reqUrl = method === "DELETE" ? makeUrl(url, data) : url;
|
|
234
|
+
const fetchInit = __spreadValues({
|
|
235
|
+
method
|
|
236
|
+
}, method !== "DELETE" && {
|
|
170
237
|
headers: {
|
|
171
238
|
"content-type": "application/json"
|
|
172
239
|
},
|
|
173
240
|
body: marshal(data)
|
|
174
|
-
}
|
|
175
|
-
fetch2,
|
|
176
|
-
|
|
177
|
-
);
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
body: marshal(data)
|
|
192
|
-
},
|
|
193
|
-
fetch2,
|
|
194
|
-
checkReadBack
|
|
195
|
-
);
|
|
196
|
-
const finalOptions = mergeOptions(model, options, invalidateQueries, mutationFn, queryClient);
|
|
197
|
-
const mutation = (0, import_react_query.useMutation)(finalOptions);
|
|
198
|
-
return mutation;
|
|
199
|
-
}
|
|
200
|
-
function deleteMutation(model, url, options, fetch2, invalidateQueries = true, checkReadBack) {
|
|
201
|
-
const queryClient = (0, import_react_query.useQueryClient)();
|
|
202
|
-
const mutationFn = (data) => fetcher(
|
|
203
|
-
makeUrl(url, data),
|
|
204
|
-
{
|
|
205
|
-
method: "DELETE"
|
|
206
|
-
},
|
|
207
|
-
fetch2,
|
|
208
|
-
checkReadBack
|
|
209
|
-
);
|
|
210
|
-
const finalOptions = mergeOptions(model, options, invalidateQueries, mutationFn, queryClient);
|
|
211
|
-
const mutation = (0, import_react_query.useMutation)(finalOptions);
|
|
212
|
-
return mutation;
|
|
213
|
-
}
|
|
214
|
-
function mergeOptions(model, options, invalidateQueries, mutationFn, queryClient) {
|
|
215
|
-
const result = __spreadProps(__spreadValues({}, options), { mutationFn });
|
|
216
|
-
if ((options == null ? void 0 : options.onSuccess) || invalidateQueries) {
|
|
217
|
-
result.onSuccess = (...args) => {
|
|
218
|
-
var _a;
|
|
219
|
-
if (invalidateQueries) {
|
|
220
|
-
queryClient.invalidateQueries([QUERY_KEY_PREFIX + model]);
|
|
221
|
-
}
|
|
222
|
-
return (_a = options == null ? void 0 : options.onSuccess) == null ? void 0 : _a.call(options, ...args);
|
|
223
|
-
};
|
|
241
|
+
});
|
|
242
|
+
return fetcher(reqUrl, fetchInit, fetch2, checkReadBack);
|
|
243
|
+
};
|
|
244
|
+
const finalOptions = __spreadProps(__spreadValues({}, options), { mutationFn });
|
|
245
|
+
if (invalidateQueries) {
|
|
246
|
+
const { logging } = (0, import_react.useContext)(RequestHandlerContext);
|
|
247
|
+
const operation = url.split("/").pop();
|
|
248
|
+
if (operation) {
|
|
249
|
+
setupInvalidation(
|
|
250
|
+
model,
|
|
251
|
+
operation,
|
|
252
|
+
modelMeta,
|
|
253
|
+
finalOptions,
|
|
254
|
+
(predicate) => queryClient.invalidateQueries({ predicate }),
|
|
255
|
+
logging
|
|
256
|
+
);
|
|
257
|
+
}
|
|
224
258
|
}
|
|
225
|
-
return
|
|
259
|
+
return (0, import_react_query.useMutation)(finalOptions);
|
|
226
260
|
}
|
|
227
261
|
// Annotate the CommonJS export names for ESM import in node:
|
|
228
262
|
0 && (module.exports = {
|
|
229
263
|
Provider,
|
|
230
264
|
RequestHandlerContext,
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
query
|
|
265
|
+
getHooksContext,
|
|
266
|
+
useInfiniteModelQuery,
|
|
267
|
+
useModelMutation,
|
|
268
|
+
useModelQuery
|
|
236
269
|
});
|
|
237
270
|
//# sourceMappingURL=react.js.map
|
package/runtime/react.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/runtime/react.ts","../../src/runtime/common.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any */\nimport {\n useInfiniteQuery,\n useMutation,\n useQuery,\n useQueryClient,\n type MutateFunction,\n type QueryClient,\n type UseInfiniteQueryOptions,\n type UseMutationOptions,\n type UseQueryOptions,\n} from '@tanstack/react-query';\nimport { createContext } from 'react';\nimport {\n DEFAULT_QUERY_ENDPOINT,\n FetchFn,\n QUERY_KEY_PREFIX,\n fetcher,\n makeUrl,\n marshal,\n type APIContext,\n} from './common';\n\n/**\n * Context for configuring react hooks.\n */\nexport const RequestHandlerContext = createContext<APIContext>({\n endpoint: DEFAULT_QUERY_ENDPOINT,\n fetch: undefined,\n});\n\n/**\n * Context provider.\n */\nexport const Provider = RequestHandlerContext.Provider;\n\n/**\n * Creates a react-query query.\n *\n * @param model The name of the model under query.\n * @param url The request URL.\n * @param args The request args object, URL-encoded and appended as \"?q=\" parameter\n * @param options The react-query options object\n * @returns useQuery hook\n */\nexport function query<R>(model: string, url: string, args?: unknown, options?: UseQueryOptions<R>, fetch?: FetchFn) {\n const reqUrl = makeUrl(url, args);\n return useQuery<R>({\n queryKey: [QUERY_KEY_PREFIX + model, url, args],\n queryFn: () => fetcher<R, false>(reqUrl, undefined, fetch, false),\n ...options,\n });\n}\n\n/**\n * Creates a react-query infinite query.\n *\n * @param model The name of the model under query.\n * @param url The request URL.\n * @param args The initial request args object, URL-encoded and appended as \"?q=\" parameter\n * @param options The react-query infinite query options object\n * @returns useInfiniteQuery hook\n */\nexport function infiniteQuery<R>(\n model: string,\n url: string,\n args?: unknown,\n options?: UseInfiniteQueryOptions<R>,\n fetch?: FetchFn\n) {\n return useInfiniteQuery<R>({\n queryKey: [QUERY_KEY_PREFIX + model, url, args],\n queryFn: ({ pageParam }) => {\n return fetcher<R, false>(makeUrl(url, pageParam ?? args), undefined, fetch, false);\n },\n ...options,\n });\n}\n\n/**\n * Creates a POST mutation with react-query.\n *\n * @param model The name of the model under mutation.\n * @param url The request URL.\n * @param options The react-query options.\n * @param invalidateQueries Whether to invalidate queries after mutation.\n * @returns useMutation hooks\n */\nexport function postMutation<T, R = any, C extends boolean = boolean, Result = C extends true ? R | undefined : R>(\n model: string,\n url: string,\n options?: Omit<UseMutationOptions<Result, unknown, T>, 'mutationFn'>,\n fetch?: FetchFn,\n invalidateQueries = true,\n checkReadBack?: C\n) {\n const queryClient = useQueryClient();\n const mutationFn = (data: any) =>\n fetcher<R, C>(\n url,\n {\n method: 'POST',\n headers: {\n 'content-type': 'application/json',\n },\n body: marshal(data),\n },\n fetch,\n checkReadBack\n ) as Promise<Result>;\n\n const finalOptions = mergeOptions<T, Result>(model, options, invalidateQueries, mutationFn, queryClient);\n const mutation = useMutation<Result, unknown, T>(finalOptions);\n return mutation;\n}\n\n/**\n * Creates a PUT mutation with react-query.\n *\n * @param model The name of the model under mutation.\n * @param url The request URL.\n * @param options The react-query options.\n * @param invalidateQueries Whether to invalidate queries after mutation.\n * @returns useMutation hooks\n */\nexport function putMutation<T, R = any, C extends boolean = boolean, Result = C extends true ? R | undefined : R>(\n model: string,\n url: string,\n options?: Omit<UseMutationOptions<Result, unknown, T>, 'mutationFn'>,\n fetch?: FetchFn,\n invalidateQueries = true,\n checkReadBack?: C\n) {\n const queryClient = useQueryClient();\n const mutationFn = (data: any) =>\n fetcher<R, C>(\n url,\n {\n method: 'PUT',\n headers: {\n 'content-type': 'application/json',\n },\n body: marshal(data),\n },\n fetch,\n checkReadBack\n ) as Promise<Result>;\n\n const finalOptions = mergeOptions<T, Result>(model, options, invalidateQueries, mutationFn, queryClient);\n const mutation = useMutation<Result, unknown, T>(finalOptions);\n return mutation;\n}\n\n/**\n * Creates a DELETE mutation with react-query.\n *\n * @param model The name of the model under mutation.\n * @param url The request URL.\n * @param options The react-query options.\n * @param invalidateQueries Whether to invalidate queries after mutation.\n * @returns useMutation hooks\n */\nexport function deleteMutation<T, R = any, C extends boolean = boolean, Result = C extends true ? R | undefined : R>(\n model: string,\n url: string,\n options?: Omit<UseMutationOptions<Result, unknown, T>, 'mutationFn'>,\n fetch?: FetchFn,\n invalidateQueries = true,\n checkReadBack?: C\n) {\n const queryClient = useQueryClient();\n const mutationFn = (data: any) =>\n fetcher<R, C>(\n makeUrl(url, data),\n {\n method: 'DELETE',\n },\n fetch,\n checkReadBack\n ) as Promise<Result>;\n\n const finalOptions = mergeOptions<T, Result>(model, options, invalidateQueries, mutationFn, queryClient);\n const mutation = useMutation<Result, unknown, T>(finalOptions);\n return mutation;\n}\n\nfunction mergeOptions<T, R = any>(\n model: string,\n options: Omit<UseMutationOptions<R, unknown, T, unknown>, 'mutationFn'> | undefined,\n invalidateQueries: boolean,\n mutationFn: MutateFunction<R, unknown, T>,\n queryClient: QueryClient\n): UseMutationOptions<R, unknown, T, unknown> {\n const result = { ...options, mutationFn };\n if (options?.onSuccess || invalidateQueries) {\n result.onSuccess = (...args) => {\n if (invalidateQueries) {\n queryClient.invalidateQueries([QUERY_KEY_PREFIX + model]);\n }\n return options?.onSuccess?.(...args);\n };\n }\n return result;\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { deserialize, serialize } from '@zenstackhq/runtime/browser';\nimport * as crossFetch from 'cross-fetch';\n\n/**\n * The default query endpoint.\n */\nexport const DEFAULT_QUERY_ENDPOINT = '/api/model';\n\n/**\n * Prefix for react-query keys.\n */\nexport const QUERY_KEY_PREFIX = 'zenstack:';\n\n/**\n * Function signature for `fetch`.\n */\nexport type FetchFn = (url: string, options?: RequestInit) => Promise<Response>;\n\n/**\n * Context type for configuring the hooks.\n */\nexport type APIContext = {\n /**\n * The endpoint to use for the queries.\n */\n endpoint?: string;\n\n /**\n * A custom fetch function for sending the HTTP requests.\n */\n fetch?: FetchFn;\n};\n\nexport async function fetcher<R, C extends boolean>(\n url: string,\n options?: RequestInit,\n fetch?: FetchFn,\n checkReadBack?: C\n): Promise<C extends true ? R | undefined : R> {\n const _fetch = fetch ?? crossFetch.fetch;\n const res = await _fetch(url, options);\n if (!res.ok) {\n const errData = unmarshal(await res.text());\n if (\n checkReadBack !== false &&\n errData.error?.prisma &&\n errData.error?.code === 'P2004' &&\n errData.error?.reason === 'RESULT_NOT_READABLE'\n ) {\n // policy doesn't allow mutation result to be read back, just return undefined\n return undefined as any;\n }\n const error: Error & { info?: unknown; status?: number } = new Error(\n 'An error occurred while fetching the data.'\n );\n error.info = errData.error;\n error.status = res.status;\n throw error;\n }\n\n const textResult = await res.text();\n try {\n return unmarshal(textResult).data as R;\n } catch (err) {\n console.error(`Unable to deserialize data:`, textResult);\n throw err;\n }\n}\n\nexport function marshal(value: unknown) {\n const { data, meta } = serialize(value);\n if (meta) {\n return JSON.stringify({ ...(data as any), meta: { serialization: meta } });\n } else {\n return JSON.stringify(data);\n }\n}\n\nexport function unmarshal(value: string) {\n const parsed = JSON.parse(value);\n if (parsed.data && parsed.meta?.serialization) {\n const deserializedData = deserialize(parsed.data, parsed.meta.serialization);\n return { ...parsed, data: deserializedData };\n } else {\n return parsed;\n }\n}\n\nexport function makeUrl(url: string, args: unknown) {\n if (!args) {\n return url;\n }\n\n const { data, meta } = serialize(args);\n let result = `${url}?q=${encodeURIComponent(JSON.stringify(data))}`;\n if (meta) {\n result += `&meta=${encodeURIComponent(JSON.stringify({ serialization: meta }))}`;\n }\n return result;\n}\n"],"mappings":"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","names":["fetch","fetch"]}
|
|
1
|
+
{"version":3,"sources":["../../src/runtime/react.ts","../../src/runtime/common.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any */\nimport {\n useInfiniteQuery,\n useMutation,\n useQuery,\n useQueryClient,\n type UseInfiniteQueryOptions,\n type UseMutationOptions,\n type UseQueryOptions,\n} from '@tanstack/react-query';\nimport type { ModelMeta } from '@zenstackhq/runtime/cross';\nimport { createContext, useContext } from 'react';\nimport {\n DEFAULT_QUERY_ENDPOINT,\n FetchFn,\n fetcher,\n getQueryKey,\n makeUrl,\n marshal,\n setupInvalidation,\n type APIContext,\n} from './common';\n\n/**\n * Context for configuring react hooks.\n */\nexport const RequestHandlerContext = createContext<APIContext>({\n endpoint: DEFAULT_QUERY_ENDPOINT,\n fetch: undefined,\n logging: false,\n});\n\n/**\n * Context provider.\n */\nexport const Provider = RequestHandlerContext.Provider;\n\n/**\n * Hooks context.\n */\nexport function getHooksContext() {\n const { endpoint, ...rest } = useContext(RequestHandlerContext);\n return { endpoint: endpoint ?? DEFAULT_QUERY_ENDPOINT, ...rest };\n}\n\n/**\n * Creates a react-query query.\n *\n * @param model The name of the model under query.\n * @param url The request URL.\n * @param args The request args object, URL-encoded and appended as \"?q=\" parameter\n * @param options The react-query options object\n * @returns useQuery hook\n */\nexport function useModelQuery<R>(\n model: string,\n url: string,\n args?: unknown,\n options?: Omit<UseQueryOptions<R>, 'queryKey'>,\n fetch?: FetchFn\n) {\n const reqUrl = makeUrl(url, args);\n return useQuery<R>({\n queryKey: getQueryKey(model, url, args),\n queryFn: () => fetcher<R, false>(reqUrl, undefined, fetch, false),\n ...options,\n });\n}\n\n/**\n * Creates a react-query infinite query.\n *\n * @param model The name of the model under query.\n * @param url The request URL.\n * @param args The initial request args object, URL-encoded and appended as \"?q=\" parameter\n * @param options The react-query infinite query options object\n * @returns useInfiniteQuery hook\n */\nexport function useInfiniteModelQuery<R>(\n model: string,\n url: string,\n args?: unknown,\n options?: Omit<UseInfiniteQueryOptions<R>, 'queryKey'>,\n fetch?: FetchFn\n) {\n return useInfiniteQuery<R>({\n queryKey: getQueryKey(model, url, args),\n queryFn: ({ pageParam }) => {\n return fetcher<R, false>(makeUrl(url, pageParam ?? args), undefined, fetch, false);\n },\n ...options,\n });\n}\n\n/**\n * Creates a mutation with react-query.\n *\n * @param model The name of the model under mutation.\n * @param method The HTTP method.\n * @param modelMeta The model metadata.\n * @param url The request URL.\n * @param options The react-query options.\n * @param invalidateQueries Whether to invalidate queries after mutation.\n * @returns useMutation hooks\n */\nexport function useModelMutation<T, R = any, C extends boolean = boolean, Result = C extends true ? R | undefined : R>(\n model: string,\n method: 'POST' | 'PUT' | 'DELETE',\n url: string,\n modelMeta: ModelMeta,\n options?: Omit<UseMutationOptions<Result, unknown, T>, 'mutationFn'>,\n fetch?: FetchFn,\n invalidateQueries = true,\n checkReadBack?: C\n) {\n const queryClient = useQueryClient();\n const mutationFn = (data: any) => {\n const reqUrl = method === 'DELETE' ? makeUrl(url, data) : url;\n const fetchInit: RequestInit = {\n method,\n ...(method !== 'DELETE' && {\n headers: {\n 'content-type': 'application/json',\n },\n body: marshal(data),\n }),\n };\n return fetcher<R, C>(reqUrl, fetchInit, fetch, checkReadBack) as Promise<Result>;\n };\n\n const finalOptions = { ...options, mutationFn };\n if (invalidateQueries) {\n const { logging } = useContext(RequestHandlerContext);\n const operation = url.split('/').pop();\n if (operation) {\n setupInvalidation(\n model,\n operation,\n modelMeta,\n finalOptions,\n (predicate) => queryClient.invalidateQueries({ predicate }),\n logging\n );\n }\n }\n\n return useMutation(finalOptions);\n}\n","/* eslint-disable @typescript-eslint/no-unused-vars */\n/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { deserialize, serialize } from '@zenstackhq/runtime/browser';\nimport { getMutatedModels, getReadModels, type ModelMeta, type PrismaWriteActionType } from '@zenstackhq/runtime/cross';\nimport * as crossFetch from 'cross-fetch';\n\n/**\n * The default query endpoint.\n */\nexport const DEFAULT_QUERY_ENDPOINT = '/api/model';\n\n/**\n * Prefix for react-query keys.\n */\nexport const QUERY_KEY_PREFIX = 'zenstack';\n\n/**\n * Function signature for `fetch`.\n */\nexport type FetchFn = (url: string, options?: RequestInit) => Promise<Response>;\n\n/**\n * Context type for configuring the hooks.\n */\nexport type APIContext = {\n /**\n * The endpoint to use for the queries.\n */\n endpoint?: string;\n\n /**\n * A custom fetch function for sending the HTTP requests.\n */\n fetch?: FetchFn;\n\n /**\n * If logging is enabled.\n */\n logging?: boolean;\n};\n\nexport async function fetcher<R, C extends boolean>(\n url: string,\n options?: RequestInit,\n fetch?: FetchFn,\n checkReadBack?: C\n): Promise<C extends true ? R | undefined : R> {\n const _fetch = fetch ?? crossFetch.fetch;\n const res = await _fetch(url, options);\n if (!res.ok) {\n const errData = unmarshal(await res.text());\n if (\n checkReadBack !== false &&\n errData.error?.prisma &&\n errData.error?.code === 'P2004' &&\n errData.error?.reason === 'RESULT_NOT_READABLE'\n ) {\n // policy doesn't allow mutation result to be read back, just return undefined\n return undefined as any;\n }\n const error: Error & { info?: unknown; status?: number } = new Error(\n 'An error occurred while fetching the data.'\n );\n error.info = errData.error;\n error.status = res.status;\n throw error;\n }\n\n const textResult = await res.text();\n try {\n return unmarshal(textResult).data as R;\n } catch (err) {\n console.error(`Unable to deserialize data:`, textResult);\n throw err;\n }\n}\n\ntype QueryKey = [string /* prefix */, string /* model */, string /* operation */, unknown /* args */];\n\n/**\n * Computes query key for the given model, operation and query args.\n * @param model Model name.\n * @param urlOrOperation Prisma operation (e.g, `findMany`) or request URL. If it's a URL, the last path segment will be used as the operation name.\n * @param args Prisma query arguments.\n * @returns Query key\n */\nexport function getQueryKey(model: string, urlOrOperation: string, args: unknown): QueryKey {\n if (!urlOrOperation) {\n throw new Error('Invalid urlOrOperation');\n }\n const operation = urlOrOperation.split('/').pop();\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n return [QUERY_KEY_PREFIX, model, operation!, args];\n}\n\nexport function marshal(value: unknown) {\n const { data, meta } = serialize(value);\n if (meta) {\n return JSON.stringify({ ...(data as any), meta: { serialization: meta } });\n } else {\n return JSON.stringify(data);\n }\n}\n\nexport function unmarshal(value: string) {\n const parsed = JSON.parse(value);\n if (parsed.data && parsed.meta?.serialization) {\n const deserializedData = deserialize(parsed.data, parsed.meta.serialization);\n return { ...parsed, data: deserializedData };\n } else {\n return parsed;\n }\n}\n\nexport function makeUrl(url: string, args: unknown) {\n if (!args) {\n return url;\n }\n\n const { data, meta } = serialize(args);\n let result = `${url}?q=${encodeURIComponent(JSON.stringify(data))}`;\n if (meta) {\n result += `&meta=${encodeURIComponent(JSON.stringify({ serialization: meta }))}`;\n }\n return result;\n}\n\ntype InvalidationPredicate = ({ queryKey }: { queryKey: readonly unknown[] }) => boolean;\n\n// sets up invalidation hook for a mutation\nexport function setupInvalidation(\n model: string,\n operation: string,\n modelMeta: ModelMeta,\n options: { onSuccess?: (...args: any[]) => any },\n invalidate: (predicate: InvalidationPredicate) => Promise<void>,\n logging = false\n) {\n const origOnSuccess = options?.onSuccess;\n options.onSuccess = async (...args: unknown[]) => {\n const [_, variables] = args;\n const predicate = await getInvalidationPredicate(\n model,\n operation as PrismaWriteActionType,\n variables,\n modelMeta,\n logging\n );\n await invalidate(predicate);\n return origOnSuccess?.(...args);\n };\n}\n\n// gets a predicate for evaluating whether a query should be invalidated\nasync function getInvalidationPredicate(\n model: string,\n operation: PrismaWriteActionType,\n mutationArgs: any,\n modelMeta: ModelMeta,\n logging = false\n) {\n const mutatedModels = await getMutatedModels(model, operation, mutationArgs, modelMeta);\n\n return ({ queryKey }: { queryKey: readonly unknown[] }) => {\n const [_model, queryModel, queryOp, args] = queryKey as QueryKey;\n\n if (mutatedModels.includes(queryModel)) {\n // direct match\n if (logging) {\n console.log(`Invalidating query [${queryKey}] due to mutation \"${model}.${operation}\"`);\n }\n return true;\n }\n\n if (args) {\n // traverse query args to find nested reads that match the model under mutation\n if (findNestedRead(queryModel, mutatedModels, modelMeta, args)) {\n if (logging) {\n console.log(`Invalidating query [${queryKey}] due to mutation \"${model}.${operation}\"`);\n }\n return true;\n }\n }\n\n return false;\n };\n}\n\n// find nested reads that match the given models\nfunction findNestedRead(visitingModel: string, targetModels: string[], modelMeta: ModelMeta, args: any) {\n const modelsRead = getReadModels(visitingModel, modelMeta, args);\n return targetModels.some((m) => modelsRead.includes(m));\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,yBAQO;AAEP,mBAA0C;;;ACT1C,qBAAuC;AACvC,mBAA4F;AAC5F,iBAA4B;AAKrB,IAAM,yBAAyB;AAK/B,IAAM,mBAAmB;AA2BhC,SAAsB,QAClB,KACA,SACAA,QACA,eAC2C;AAAA;AA9C/C;AA+CI,UAAM,SAASA,UAAA,OAAAA,SAAoB;AACnC,UAAM,MAAM,MAAM,OAAO,KAAK,OAAO;AACrC,QAAI,CAAC,IAAI,IAAI;AACT,YAAM,UAAU,UAAU,MAAM,IAAI,KAAK,CAAC;AAC1C,UACI,kBAAkB,WAClB,aAAQ,UAAR,mBAAe,aACf,aAAQ,UAAR,mBAAe,UAAS,aACxB,aAAQ,UAAR,mBAAe,YAAW,uBAC5B;AAEE,eAAO;AAAA,MACX;AACA,YAAM,QAAqD,IAAI;AAAA,QAC3D;AAAA,MACJ;AACA,YAAM,OAAO,QAAQ;AACrB,YAAM,SAAS,IAAI;AACnB,YAAM;AAAA,IACV;AAEA,UAAM,aAAa,MAAM,IAAI,KAAK;AAClC,QAAI;AACA,aAAO,UAAU,UAAU,EAAE;AAAA,IACjC,SAAS,KAAK;AACV,cAAQ,MAAM,+BAA+B,UAAU;AACvD,YAAM;AAAA,IACV;AAAA,EACJ;AAAA;AAWO,SAAS,YAAY,OAAe,gBAAwB,MAAyB;AACxF,MAAI,CAAC,gBAAgB;AACjB,UAAM,IAAI,MAAM,wBAAwB;AAAA,EAC5C;AACA,QAAM,YAAY,eAAe,MAAM,GAAG,EAAE,IAAI;AAEhD,SAAO,CAAC,kBAAkB,OAAO,WAAY,IAAI;AACrD;AAEO,SAAS,QAAQ,OAAgB;AACpC,QAAM,EAAE,MAAM,KAAK,QAAI,0BAAU,KAAK;AACtC,MAAI,MAAM;AACN,WAAO,KAAK,UAAU,iCAAM,OAAN,EAAoB,MAAM,EAAE,eAAe,KAAK,EAAE,EAAC;AAAA,EAC7E,OAAO;AACH,WAAO,KAAK,UAAU,IAAI;AAAA,EAC9B;AACJ;AAEO,SAAS,UAAU,OAAe;AAxGzC;AAyGI,QAAM,SAAS,KAAK,MAAM,KAAK;AAC/B,MAAI,OAAO,UAAQ,YAAO,SAAP,mBAAa,gBAAe;AAC3C,UAAM,uBAAmB,4BAAY,OAAO,MAAM,OAAO,KAAK,aAAa;AAC3E,WAAO,iCAAK,SAAL,EAAa,MAAM,iBAAiB;AAAA,EAC/C,OAAO;AACH,WAAO;AAAA,EACX;AACJ;AAEO,SAAS,QAAQ,KAAa,MAAe;AAChD,MAAI,CAAC,MAAM;AACP,WAAO;AAAA,EACX;AAEA,QAAM,EAAE,MAAM,KAAK,QAAI,0BAAU,IAAI;AACrC,MAAI,SAAS,GAAG,GAAG,MAAM,mBAAmB,KAAK,UAAU,IAAI,CAAC,CAAC;AACjE,MAAI,MAAM;AACN,cAAU,SAAS,mBAAmB,KAAK,UAAU,EAAE,eAAe,KAAK,CAAC,CAAC,CAAC;AAAA,EAClF;AACA,SAAO;AACX;AAKO,SAAS,kBACZ,OACA,WACA,WACA,SACA,YACA,UAAU,OACZ;AACE,QAAM,gBAAgB,mCAAS;AAC/B,UAAQ,YAAY,IAAU,SAAoB;AAC9C,UAAM,CAAC,GAAG,SAAS,IAAI;AACvB,UAAM,YAAY,MAAM;AAAA,MACpB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACJ;AACA,UAAM,WAAW,SAAS;AAC1B,WAAO,+CAAgB,GAAG;AAAA,EAC9B;AACJ;AAGA,SAAe,yBACX,OACA,WACA,cACA,WACA,UAAU,OACZ;AAAA;AACE,UAAM,gBAAgB,UAAM,+BAAiB,OAAO,WAAW,cAAc,SAAS;AAEtF,WAAO,CAAC,EAAE,SAAS,MAAwC;AACvD,YAAM,CAAC,QAAQ,YAAY,SAAS,IAAI,IAAI;AAE5C,UAAI,cAAc,SAAS,UAAU,GAAG;AAEpC,YAAI,SAAS;AACT,kBAAQ,IAAI,uBAAuB,QAAQ,sBAAsB,KAAK,IAAI,SAAS,GAAG;AAAA,QAC1F;AACA,eAAO;AAAA,MACX;AAEA,UAAI,MAAM;AAEN,YAAI,eAAe,YAAY,eAAe,WAAW,IAAI,GAAG;AAC5D,cAAI,SAAS;AACT,oBAAQ,IAAI,uBAAuB,QAAQ,sBAAsB,KAAK,IAAI,SAAS,GAAG;AAAA,UAC1F;AACA,iBAAO;AAAA,QACX;AAAA,MACJ;AAEA,aAAO;AAAA,IACX;AAAA,EACJ;AAAA;AAGA,SAAS,eAAe,eAAuB,cAAwB,WAAsB,MAAW;AACpG,QAAM,iBAAa,4BAAc,eAAe,WAAW,IAAI;AAC/D,SAAO,aAAa,KAAK,CAAC,MAAM,WAAW,SAAS,CAAC,CAAC;AAC1D;;;ADtKO,IAAM,4BAAwB,4BAA0B;AAAA,EAC3D,UAAU;AAAA,EACV,OAAO;AAAA,EACP,SAAS;AACb,CAAC;AAKM,IAAM,WAAW,sBAAsB;AAKvC,SAAS,kBAAkB;AAC9B,QAA8B,kCAAW,qBAAqB,GAAtD,WAzCZ,IAyCkC,IAAT,iBAAS,IAAT,CAAb;AACR,SAAO,iBAAE,UAAU,8BAAY,0BAA2B;AAC9D;AAWO,SAAS,cACZ,OACA,KACA,MACA,SACAC,QACF;AACE,QAAM,SAAS,QAAQ,KAAK,IAAI;AAChC,aAAO,6BAAY;AAAA,IACf,UAAU,YAAY,OAAO,KAAK,IAAI;AAAA,IACtC,SAAS,MAAM,QAAkB,QAAQ,QAAWA,QAAO,KAAK;AAAA,KAC7D,QACN;AACL;AAWO,SAAS,sBACZ,OACA,KACA,MACA,SACAA,QACF;AACE,aAAO,qCAAoB;AAAA,IACvB,UAAU,YAAY,OAAO,KAAK,IAAI;AAAA,IACtC,SAAS,CAAC,EAAE,UAAU,MAAM;AACxB,aAAO,QAAkB,QAAQ,KAAK,gCAAa,IAAI,GAAG,QAAWA,QAAO,KAAK;AAAA,IACrF;AAAA,KACG,QACN;AACL;AAaO,SAAS,iBACZ,OACA,QACA,KACA,WACA,SACAA,QACA,oBAAoB,MACpB,eACF;AACE,QAAM,kBAAc,mCAAe;AACnC,QAAM,aAAa,CAAC,SAAc;AAC9B,UAAM,SAAS,WAAW,WAAW,QAAQ,KAAK,IAAI,IAAI;AAC1D,UAAM,YAAyB;AAAA,MAC3B;AAAA,OACI,WAAW,YAAY;AAAA,MACvB,SAAS;AAAA,QACL,gBAAgB;AAAA,MACpB;AAAA,MACA,MAAM,QAAQ,IAAI;AAAA,IACtB;AAEJ,WAAO,QAAc,QAAQ,WAAWA,QAAO,aAAa;AAAA,EAChE;AAEA,QAAM,eAAe,iCAAK,UAAL,EAAc,WAAW;AAC9C,MAAI,mBAAmB;AACnB,UAAM,EAAE,QAAQ,QAAI,yBAAW,qBAAqB;AACpD,UAAM,YAAY,IAAI,MAAM,GAAG,EAAE,IAAI;AACrC,QAAI,WAAW;AACX;AAAA,QACI;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,CAAC,cAAc,YAAY,kBAAkB,EAAE,UAAU,CAAC;AAAA,QAC1D;AAAA,MACJ;AAAA,IACJ;AAAA,EACJ;AAEA,aAAO,gCAAY,YAAY;AACnC;","names":["fetch","fetch"]}
|
package/runtime/react.mjs
CHANGED
|
@@ -17,6 +17,18 @@ var __spreadValues = (a, b) => {
|
|
|
17
17
|
return a;
|
|
18
18
|
};
|
|
19
19
|
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
20
|
+
var __objRest = (source, exclude) => {
|
|
21
|
+
var target = {};
|
|
22
|
+
for (var prop in source)
|
|
23
|
+
if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)
|
|
24
|
+
target[prop] = source[prop];
|
|
25
|
+
if (source != null && __getOwnPropSymbols)
|
|
26
|
+
for (var prop of __getOwnPropSymbols(source)) {
|
|
27
|
+
if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
|
|
28
|
+
target[prop] = source[prop];
|
|
29
|
+
}
|
|
30
|
+
return target;
|
|
31
|
+
};
|
|
20
32
|
var __async = (__this, __arguments, generator) => {
|
|
21
33
|
return new Promise((resolve, reject) => {
|
|
22
34
|
var fulfilled = (value) => {
|
|
@@ -45,13 +57,14 @@ import {
|
|
|
45
57
|
useQuery,
|
|
46
58
|
useQueryClient
|
|
47
59
|
} from "@tanstack/react-query";
|
|
48
|
-
import { createContext } from "react";
|
|
60
|
+
import { createContext, useContext } from "react";
|
|
49
61
|
|
|
50
62
|
// src/runtime/common.ts
|
|
51
63
|
import { deserialize, serialize } from "@zenstackhq/runtime/browser";
|
|
64
|
+
import { getMutatedModels, getReadModels } from "@zenstackhq/runtime/cross";
|
|
52
65
|
import * as crossFetch from "cross-fetch";
|
|
53
66
|
var DEFAULT_QUERY_ENDPOINT = "/api/model";
|
|
54
|
-
var QUERY_KEY_PREFIX = "zenstack
|
|
67
|
+
var QUERY_KEY_PREFIX = "zenstack";
|
|
55
68
|
function fetcher(url, options, fetch2, checkReadBack) {
|
|
56
69
|
return __async(this, null, function* () {
|
|
57
70
|
var _a, _b, _c;
|
|
@@ -78,6 +91,13 @@ function fetcher(url, options, fetch2, checkReadBack) {
|
|
|
78
91
|
}
|
|
79
92
|
});
|
|
80
93
|
}
|
|
94
|
+
function getQueryKey(model, urlOrOperation, args) {
|
|
95
|
+
if (!urlOrOperation) {
|
|
96
|
+
throw new Error("Invalid urlOrOperation");
|
|
97
|
+
}
|
|
98
|
+
const operation = urlOrOperation.split("/").pop();
|
|
99
|
+
return [QUERY_KEY_PREFIX, model, operation, args];
|
|
100
|
+
}
|
|
81
101
|
function marshal(value) {
|
|
82
102
|
const { data, meta } = serialize(value);
|
|
83
103
|
if (meta) {
|
|
@@ -107,98 +127,112 @@ function makeUrl(url, args) {
|
|
|
107
127
|
}
|
|
108
128
|
return result;
|
|
109
129
|
}
|
|
130
|
+
function setupInvalidation(model, operation, modelMeta, options, invalidate, logging = false) {
|
|
131
|
+
const origOnSuccess = options == null ? void 0 : options.onSuccess;
|
|
132
|
+
options.onSuccess = (...args) => __async(this, null, function* () {
|
|
133
|
+
const [_, variables] = args;
|
|
134
|
+
const predicate = yield getInvalidationPredicate(
|
|
135
|
+
model,
|
|
136
|
+
operation,
|
|
137
|
+
variables,
|
|
138
|
+
modelMeta,
|
|
139
|
+
logging
|
|
140
|
+
);
|
|
141
|
+
yield invalidate(predicate);
|
|
142
|
+
return origOnSuccess == null ? void 0 : origOnSuccess(...args);
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
function getInvalidationPredicate(model, operation, mutationArgs, modelMeta, logging = false) {
|
|
146
|
+
return __async(this, null, function* () {
|
|
147
|
+
const mutatedModels = yield getMutatedModels(model, operation, mutationArgs, modelMeta);
|
|
148
|
+
return ({ queryKey }) => {
|
|
149
|
+
const [_model, queryModel, queryOp, args] = queryKey;
|
|
150
|
+
if (mutatedModels.includes(queryModel)) {
|
|
151
|
+
if (logging) {
|
|
152
|
+
console.log(`Invalidating query [${queryKey}] due to mutation "${model}.${operation}"`);
|
|
153
|
+
}
|
|
154
|
+
return true;
|
|
155
|
+
}
|
|
156
|
+
if (args) {
|
|
157
|
+
if (findNestedRead(queryModel, mutatedModels, modelMeta, args)) {
|
|
158
|
+
if (logging) {
|
|
159
|
+
console.log(`Invalidating query [${queryKey}] due to mutation "${model}.${operation}"`);
|
|
160
|
+
}
|
|
161
|
+
return true;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
return false;
|
|
165
|
+
};
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
function findNestedRead(visitingModel, targetModels, modelMeta, args) {
|
|
169
|
+
const modelsRead = getReadModels(visitingModel, modelMeta, args);
|
|
170
|
+
return targetModels.some((m) => modelsRead.includes(m));
|
|
171
|
+
}
|
|
110
172
|
|
|
111
173
|
// src/runtime/react.ts
|
|
112
174
|
var RequestHandlerContext = createContext({
|
|
113
175
|
endpoint: DEFAULT_QUERY_ENDPOINT,
|
|
114
|
-
fetch: void 0
|
|
176
|
+
fetch: void 0,
|
|
177
|
+
logging: false
|
|
115
178
|
});
|
|
116
179
|
var Provider = RequestHandlerContext.Provider;
|
|
117
|
-
function
|
|
180
|
+
function getHooksContext() {
|
|
181
|
+
const _a = useContext(RequestHandlerContext), { endpoint } = _a, rest = __objRest(_a, ["endpoint"]);
|
|
182
|
+
return __spreadValues({ endpoint: endpoint != null ? endpoint : DEFAULT_QUERY_ENDPOINT }, rest);
|
|
183
|
+
}
|
|
184
|
+
function useModelQuery(model, url, args, options, fetch2) {
|
|
118
185
|
const reqUrl = makeUrl(url, args);
|
|
119
186
|
return useQuery(__spreadValues({
|
|
120
|
-
queryKey:
|
|
187
|
+
queryKey: getQueryKey(model, url, args),
|
|
121
188
|
queryFn: () => fetcher(reqUrl, void 0, fetch2, false)
|
|
122
189
|
}, options));
|
|
123
190
|
}
|
|
124
|
-
function
|
|
191
|
+
function useInfiniteModelQuery(model, url, args, options, fetch2) {
|
|
125
192
|
return useInfiniteQuery(__spreadValues({
|
|
126
|
-
queryKey:
|
|
193
|
+
queryKey: getQueryKey(model, url, args),
|
|
127
194
|
queryFn: ({ pageParam }) => {
|
|
128
195
|
return fetcher(makeUrl(url, pageParam != null ? pageParam : args), void 0, fetch2, false);
|
|
129
196
|
}
|
|
130
197
|
}, options));
|
|
131
198
|
}
|
|
132
|
-
function
|
|
199
|
+
function useModelMutation(model, method, url, modelMeta, options, fetch2, invalidateQueries = true, checkReadBack) {
|
|
133
200
|
const queryClient = useQueryClient();
|
|
134
|
-
const mutationFn = (data) =>
|
|
135
|
-
url,
|
|
136
|
-
{
|
|
137
|
-
method
|
|
201
|
+
const mutationFn = (data) => {
|
|
202
|
+
const reqUrl = method === "DELETE" ? makeUrl(url, data) : url;
|
|
203
|
+
const fetchInit = __spreadValues({
|
|
204
|
+
method
|
|
205
|
+
}, method !== "DELETE" && {
|
|
138
206
|
headers: {
|
|
139
207
|
"content-type": "application/json"
|
|
140
208
|
},
|
|
141
209
|
body: marshal(data)
|
|
142
|
-
}
|
|
143
|
-
fetch2,
|
|
144
|
-
|
|
145
|
-
);
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
body: marshal(data)
|
|
160
|
-
},
|
|
161
|
-
fetch2,
|
|
162
|
-
checkReadBack
|
|
163
|
-
);
|
|
164
|
-
const finalOptions = mergeOptions(model, options, invalidateQueries, mutationFn, queryClient);
|
|
165
|
-
const mutation = useMutation(finalOptions);
|
|
166
|
-
return mutation;
|
|
167
|
-
}
|
|
168
|
-
function deleteMutation(model, url, options, fetch2, invalidateQueries = true, checkReadBack) {
|
|
169
|
-
const queryClient = useQueryClient();
|
|
170
|
-
const mutationFn = (data) => fetcher(
|
|
171
|
-
makeUrl(url, data),
|
|
172
|
-
{
|
|
173
|
-
method: "DELETE"
|
|
174
|
-
},
|
|
175
|
-
fetch2,
|
|
176
|
-
checkReadBack
|
|
177
|
-
);
|
|
178
|
-
const finalOptions = mergeOptions(model, options, invalidateQueries, mutationFn, queryClient);
|
|
179
|
-
const mutation = useMutation(finalOptions);
|
|
180
|
-
return mutation;
|
|
181
|
-
}
|
|
182
|
-
function mergeOptions(model, options, invalidateQueries, mutationFn, queryClient) {
|
|
183
|
-
const result = __spreadProps(__spreadValues({}, options), { mutationFn });
|
|
184
|
-
if ((options == null ? void 0 : options.onSuccess) || invalidateQueries) {
|
|
185
|
-
result.onSuccess = (...args) => {
|
|
186
|
-
var _a;
|
|
187
|
-
if (invalidateQueries) {
|
|
188
|
-
queryClient.invalidateQueries([QUERY_KEY_PREFIX + model]);
|
|
189
|
-
}
|
|
190
|
-
return (_a = options == null ? void 0 : options.onSuccess) == null ? void 0 : _a.call(options, ...args);
|
|
191
|
-
};
|
|
210
|
+
});
|
|
211
|
+
return fetcher(reqUrl, fetchInit, fetch2, checkReadBack);
|
|
212
|
+
};
|
|
213
|
+
const finalOptions = __spreadProps(__spreadValues({}, options), { mutationFn });
|
|
214
|
+
if (invalidateQueries) {
|
|
215
|
+
const { logging } = useContext(RequestHandlerContext);
|
|
216
|
+
const operation = url.split("/").pop();
|
|
217
|
+
if (operation) {
|
|
218
|
+
setupInvalidation(
|
|
219
|
+
model,
|
|
220
|
+
operation,
|
|
221
|
+
modelMeta,
|
|
222
|
+
finalOptions,
|
|
223
|
+
(predicate) => queryClient.invalidateQueries({ predicate }),
|
|
224
|
+
logging
|
|
225
|
+
);
|
|
226
|
+
}
|
|
192
227
|
}
|
|
193
|
-
return
|
|
228
|
+
return useMutation(finalOptions);
|
|
194
229
|
}
|
|
195
230
|
export {
|
|
196
231
|
Provider,
|
|
197
232
|
RequestHandlerContext,
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
query
|
|
233
|
+
getHooksContext,
|
|
234
|
+
useInfiniteModelQuery,
|
|
235
|
+
useModelMutation,
|
|
236
|
+
useModelQuery
|
|
203
237
|
};
|
|
204
238
|
//# sourceMappingURL=react.mjs.map
|