@zenstackhq/swr 2.0.0-alpha.7 → 2.0.0-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/generator.js +11 -49
- package/generator.js.map +1 -1
- package/package.json +4 -4
- package/runtime/index.d.mts +40 -11
- package/runtime/index.d.ts +40 -11
- package/runtime/index.js +29 -14
- package/runtime/index.js.map +1 -1
- package/runtime/index.mjs +29 -14
- package/runtime/index.mjs.map +1 -1
package/generator.js
CHANGED
|
@@ -15,7 +15,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
15
15
|
exports.generate = void 0;
|
|
16
16
|
const sdk_1 = require("@zenstackhq/sdk");
|
|
17
17
|
const change_case_1 = require("change-case");
|
|
18
|
-
const lower_case_first_1 = require("lower-case-first");
|
|
19
18
|
const path_1 = __importDefault(require("path"));
|
|
20
19
|
const semver_1 = __importDefault(require("semver"));
|
|
21
20
|
const upper_case_first_1 = require("upper-case-first");
|
|
@@ -26,10 +25,6 @@ function generate(model, options, dmmf) {
|
|
|
26
25
|
outDir = (0, sdk_1.resolvePath)(outDir, options);
|
|
27
26
|
const project = (0, sdk_1.createProject)();
|
|
28
27
|
const warnings = [];
|
|
29
|
-
if (options.useSuperJson !== undefined) {
|
|
30
|
-
warnings.push('The option "useSuperJson" is deprecated. The generated hooks always use superjson for serialization.');
|
|
31
|
-
}
|
|
32
|
-
const legacyMutations = options.legacyMutations !== false;
|
|
33
28
|
const models = (0, sdk_1.getDataModels)(model);
|
|
34
29
|
yield (0, sdk_1.generateModelMeta)(project, models, {
|
|
35
30
|
output: path_1.default.join(outDir, '__model_meta.ts'),
|
|
@@ -42,14 +37,14 @@ function generate(model, options, dmmf) {
|
|
|
42
37
|
warnings.push(`Unable to find mapping for model ${dataModel.name}`);
|
|
43
38
|
return;
|
|
44
39
|
}
|
|
45
|
-
generateModelHooks(project, outDir, dataModel, mapping,
|
|
40
|
+
generateModelHooks(project, outDir, dataModel, mapping, options);
|
|
46
41
|
});
|
|
47
42
|
yield (0, sdk_1.saveProject)(project);
|
|
48
43
|
return { warnings };
|
|
49
44
|
});
|
|
50
45
|
}
|
|
51
46
|
exports.generate = generate;
|
|
52
|
-
function generateModelHooks(project, outDir, model, mapping,
|
|
47
|
+
function generateModelHooks(project, outDir, model, mapping, options) {
|
|
53
48
|
const fileName = (0, change_case_1.paramCase)(model.name);
|
|
54
49
|
const sf = project.createSourceFile(path_1.default.join(outDir, `${fileName}.ts`), undefined, { overwrite: true });
|
|
55
50
|
sf.addStatements('/* eslint-disable */');
|
|
@@ -60,34 +55,23 @@ function generateModelHooks(project, outDir, model, mapping, legacyMutations, op
|
|
|
60
55
|
moduleSpecifier: prismaImport,
|
|
61
56
|
});
|
|
62
57
|
sf.addStatements([
|
|
63
|
-
`import { type GetNextArgs, type QueryOptions, type InfiniteQueryOptions, type MutationOptions, type PickEnumerable
|
|
58
|
+
`import { type GetNextArgs, type QueryOptions, type InfiniteQueryOptions, type MutationOptions, type PickEnumerable } from '@zenstackhq/swr/runtime';`,
|
|
64
59
|
`import metadata from './__model_meta';`,
|
|
65
60
|
`import * as request from '@zenstackhq/swr/runtime';`,
|
|
66
61
|
]);
|
|
67
62
|
const modelNameCap = (0, upper_case_first_1.upperCaseFirst)(model.name);
|
|
68
63
|
const prismaVersion = (0, sdk_1.getPrismaVersion)();
|
|
69
|
-
const useMutation = legacyMutations
|
|
70
|
-
? sf.addFunction({
|
|
71
|
-
name: `useMutate${model.name}`,
|
|
72
|
-
isExported: true,
|
|
73
|
-
statements: [
|
|
74
|
-
'const { endpoint, fetch } = useHooksContext();',
|
|
75
|
-
`const invalidate = request.useInvalidation('${model.name}', metadata);`,
|
|
76
|
-
],
|
|
77
|
-
docs: ['@deprecated Use mutation hooks (useCreateXXX, useUpdateXXX, etc.) instead.'],
|
|
78
|
-
})
|
|
79
|
-
: undefined;
|
|
80
64
|
const mutationFuncs = [];
|
|
81
65
|
// create is somehow named "createOne" in the DMMF
|
|
82
66
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
83
67
|
if (mapping.create || mapping.createOne) {
|
|
84
68
|
const argsType = `Prisma.${model.name}CreateArgs`;
|
|
85
|
-
mutationFuncs.push(generateMutation(sf,
|
|
69
|
+
mutationFuncs.push(generateMutation(sf, model, 'POST', 'create', argsType, false));
|
|
86
70
|
}
|
|
87
71
|
// createMany
|
|
88
72
|
if (mapping.createMany) {
|
|
89
73
|
const argsType = `Prisma.${model.name}CreateManyArgs`;
|
|
90
|
-
mutationFuncs.push(generateMutation(sf,
|
|
74
|
+
mutationFuncs.push(generateMutation(sf, model, 'POST', 'createMany', argsType, true));
|
|
91
75
|
}
|
|
92
76
|
// findMany
|
|
93
77
|
if (mapping.findMany) {
|
|
@@ -120,31 +104,31 @@ function generateModelHooks(project, outDir, model, mapping, legacyMutations, op
|
|
|
120
104
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
121
105
|
if (mapping.update || mapping.updateOne) {
|
|
122
106
|
const argsType = `Prisma.${model.name}UpdateArgs`;
|
|
123
|
-
mutationFuncs.push(generateMutation(sf,
|
|
107
|
+
mutationFuncs.push(generateMutation(sf, model, 'PUT', 'update', argsType, false));
|
|
124
108
|
}
|
|
125
109
|
// updateMany
|
|
126
110
|
if (mapping.updateMany) {
|
|
127
111
|
const argsType = `Prisma.${model.name}UpdateManyArgs`;
|
|
128
|
-
mutationFuncs.push(generateMutation(sf,
|
|
112
|
+
mutationFuncs.push(generateMutation(sf, model, 'PUT', 'updateMany', argsType, true));
|
|
129
113
|
}
|
|
130
114
|
// upsert
|
|
131
115
|
// upsert is somehow named "upsertOne" in the DMMF
|
|
132
116
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
133
117
|
if (mapping.upsert || mapping.upsertOne) {
|
|
134
118
|
const argsType = `Prisma.${model.name}UpsertArgs`;
|
|
135
|
-
mutationFuncs.push(generateMutation(sf,
|
|
119
|
+
mutationFuncs.push(generateMutation(sf, model, 'POST', 'upsert', argsType, false));
|
|
136
120
|
}
|
|
137
121
|
// del
|
|
138
122
|
// delete is somehow named "deleteOne" in the DMMF
|
|
139
123
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
140
124
|
if (mapping.delete || mapping.deleteOne) {
|
|
141
125
|
const argsType = `Prisma.${model.name}DeleteArgs`;
|
|
142
|
-
mutationFuncs.push(generateMutation(sf,
|
|
126
|
+
mutationFuncs.push(generateMutation(sf, model, 'DELETE', 'delete', argsType, false));
|
|
143
127
|
}
|
|
144
128
|
// deleteMany
|
|
145
129
|
if (mapping.deleteMany) {
|
|
146
130
|
const argsType = `Prisma.${model.name}DeleteManyArgs`;
|
|
147
|
-
mutationFuncs.push(generateMutation(sf,
|
|
131
|
+
mutationFuncs.push(generateMutation(sf, model, 'DELETE', 'deleteMany', argsType, true));
|
|
148
132
|
}
|
|
149
133
|
// aggregate
|
|
150
134
|
if (mapping.aggregate) {
|
|
@@ -233,7 +217,6 @@ function generateModelHooks(project, outDir, model, mapping, legacyMutations, op
|
|
|
233
217
|
const returnType = `T extends { select: any; } ? T['select'] extends true ? number : Prisma.GetScalarType<T['select'], Prisma.${modelNameCap}CountAggregateOutputType> : number`;
|
|
234
218
|
generateQueryHook(sf, model, 'count', argsType, inputType, returnType);
|
|
235
219
|
}
|
|
236
|
-
useMutation === null || useMutation === void 0 ? void 0 : useMutation.addStatements(`return { ${mutationFuncs.join(', ')} };`);
|
|
237
220
|
}
|
|
238
221
|
function makeOptimistic(returnType) {
|
|
239
222
|
return `${returnType} & { $optimistic?: boolean }`;
|
|
@@ -278,34 +261,13 @@ function generateQueryHook(sf, model, operation, argsType, inputType, returnType
|
|
|
278
261
|
: `return request.useInfiniteModelQuery('${model.name}', '${operation}', getNextArgs, options);`,
|
|
279
262
|
]);
|
|
280
263
|
}
|
|
281
|
-
function generateMutation(sf,
|
|
264
|
+
function generateMutation(sf, model, method, operation, argsType, batchResult) {
|
|
282
265
|
// non-batch mutations are subject to read-back check
|
|
283
266
|
const checkReadBack = !batchResult;
|
|
284
267
|
const genericReturnType = batchResult ? 'Prisma.BatchPayload' : `Prisma.${model.name}GetPayload<T> | undefined`;
|
|
285
268
|
const returnType = batchResult ? 'Prisma.BatchPayload' : `Prisma.${model.name}GetPayload<${argsType}> | undefined`;
|
|
286
269
|
const genericInputType = `Prisma.SelectSubset<T, ${argsType}>`;
|
|
287
|
-
const modelRouteName = (0, lower_case_first_1.lowerCaseFirst)(model.name);
|
|
288
270
|
const funcName = `${operation}${model.name}`;
|
|
289
|
-
if (useMutateModelFunc) {
|
|
290
|
-
// generate async mutation function (legacy)
|
|
291
|
-
const mutationFunc = useMutateModelFunc.addFunction({
|
|
292
|
-
name: funcName,
|
|
293
|
-
isAsync: true,
|
|
294
|
-
typeParameters: [`T extends ${argsType}`],
|
|
295
|
-
parameters: [
|
|
296
|
-
{
|
|
297
|
-
name: 'args',
|
|
298
|
-
type: genericInputType,
|
|
299
|
-
},
|
|
300
|
-
],
|
|
301
|
-
});
|
|
302
|
-
mutationFunc.addJsDoc(`@deprecated Use \`use${(0, upper_case_first_1.upperCaseFirst)(operation)}${model.name}\` hook instead.`);
|
|
303
|
-
mutationFunc
|
|
304
|
-
.addBody()
|
|
305
|
-
.addStatements([
|
|
306
|
-
`return await request.mutationRequest<${returnType}, ${checkReadBack}>('${method}', \`\${endpoint}/${modelRouteName}/${operation}\`, args, invalidate, fetch, ${checkReadBack});`,
|
|
307
|
-
]);
|
|
308
|
-
}
|
|
309
271
|
// generate mutation hook
|
|
310
272
|
sf.addFunction({
|
|
311
273
|
name: `use${(0, upper_case_first_1.upperCaseFirst)(operation)}${model.name}`,
|
package/generator.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generator.js","sourceRoot":"","sources":["../src/generator.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AACA,yCAUyB;AAEzB,6CAAwC;AACxC,
|
|
1
|
+
{"version":3,"file":"generator.js","sourceRoot":"","sources":["../src/generator.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zenstackhq/swr",
|
|
3
3
|
"displayName": "ZenStack plugin for generating SWR hooks",
|
|
4
|
-
"version": "2.0.0-
|
|
4
|
+
"version": "2.0.0-beta.2",
|
|
5
5
|
"description": "ZenStack plugin for generating SWR hooks",
|
|
6
6
|
"main": "index.js",
|
|
7
7
|
"repository": {
|
|
@@ -38,8 +38,8 @@
|
|
|
38
38
|
"semver": "^7.5.2",
|
|
39
39
|
"ts-morph": "^16.0.0",
|
|
40
40
|
"upper-case-first": "^2.0.2",
|
|
41
|
-
"@zenstackhq/
|
|
42
|
-
"@zenstackhq/
|
|
41
|
+
"@zenstackhq/runtime": "2.0.0-beta.2",
|
|
42
|
+
"@zenstackhq/sdk": "2.0.0-beta.2"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
45
45
|
"@tanstack/react-query": "^4.28.0",
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
"nock": "^13.3.6",
|
|
51
51
|
"react": "18.2.0",
|
|
52
52
|
"swr": "^2.2.4",
|
|
53
|
-
"@zenstackhq/testtools": "2.0.0-
|
|
53
|
+
"@zenstackhq/testtools": "2.0.0-beta.2"
|
|
54
54
|
},
|
|
55
55
|
"scripts": {
|
|
56
56
|
"clean": "rimraf dist",
|
package/runtime/index.d.mts
CHANGED
|
@@ -74,12 +74,6 @@ type QueryOptions<Result, Error = unknown> = {
|
|
|
74
74
|
* Disable data fetching
|
|
75
75
|
*/
|
|
76
76
|
disabled?: boolean;
|
|
77
|
-
/**
|
|
78
|
-
* @deprecated Use `fallbackData` instead
|
|
79
|
-
*
|
|
80
|
-
* Equivalent to @see SWRConfiguration.fallbackData
|
|
81
|
-
*/
|
|
82
|
-
initialData?: Result;
|
|
83
77
|
/**
|
|
84
78
|
* Whether to enable automatic optimistic update. Defaults to `true`.
|
|
85
79
|
*/
|
|
@@ -93,13 +87,44 @@ type InfiniteQueryOptions<Result, Error = unknown> = {
|
|
|
93
87
|
* Disable data fetching
|
|
94
88
|
*/
|
|
95
89
|
disabled?: boolean;
|
|
90
|
+
} & Omit<SWRInfiniteConfiguration<Result, Error, SWRInfiniteFetcher<Result>>, 'fetcher'>;
|
|
91
|
+
/**
|
|
92
|
+
* Result of optimistic data provider.
|
|
93
|
+
*/
|
|
94
|
+
type OptimisticDataProviderResult = {
|
|
95
|
+
/**
|
|
96
|
+
* Kind of the result.
|
|
97
|
+
* - Update: use the `data` field to update the query cache.
|
|
98
|
+
* - Skip: skip the optimistic update for this query.
|
|
99
|
+
* - ProceedDefault: proceed with the default optimistic update.
|
|
100
|
+
*/
|
|
101
|
+
kind: 'Update' | 'Skip' | 'ProceedDefault';
|
|
96
102
|
/**
|
|
97
|
-
*
|
|
103
|
+
* Data to update the query cache. Only applicable if `kind` is 'Update'.
|
|
98
104
|
*
|
|
99
|
-
*
|
|
105
|
+
* If the data is an object with fields updated, it should have a `$optimistic`
|
|
106
|
+
* field set to `true`. If it's an array and an element object is created or updated,
|
|
107
|
+
* the element should have a `$optimistic` field set to `true`.
|
|
100
108
|
*/
|
|
101
|
-
|
|
102
|
-
}
|
|
109
|
+
data?: any;
|
|
110
|
+
};
|
|
111
|
+
/**
|
|
112
|
+
* Optimistic data provider.
|
|
113
|
+
*
|
|
114
|
+
* @param args Arguments.
|
|
115
|
+
* @param args.queryModel The model of the query.
|
|
116
|
+
* @param args.queryOperation The operation of the query, `findMany`, `count`, etc.
|
|
117
|
+
* @param args.queryArgs The arguments of the query.
|
|
118
|
+
* @param args.currentData The current cache data for the query.
|
|
119
|
+
* @param args.mutationArgs The arguments of the mutation.
|
|
120
|
+
*/
|
|
121
|
+
type OptimisticDataProvider = (args: {
|
|
122
|
+
queryModel: string;
|
|
123
|
+
queryOperation: string;
|
|
124
|
+
queryArgs: any;
|
|
125
|
+
currentData: any;
|
|
126
|
+
mutationArgs: any;
|
|
127
|
+
}) => OptimisticDataProviderResult | Promise<OptimisticDataProviderResult>;
|
|
103
128
|
/**
|
|
104
129
|
* Mutation options.
|
|
105
130
|
*/
|
|
@@ -108,6 +133,10 @@ type MutationOptions<Result, Error, Args> = {
|
|
|
108
133
|
* Whether to automatically optimistic-update queries potentially impacted. Defaults to `false`.
|
|
109
134
|
*/
|
|
110
135
|
optimisticUpdate?: boolean;
|
|
136
|
+
/**
|
|
137
|
+
* A callback for computing optimistic update data for each query cache entry.
|
|
138
|
+
*/
|
|
139
|
+
optimisticDataProvider?: OptimisticDataProvider;
|
|
111
140
|
} & Omit<SWRMutationConfiguration<Result, Error, string, Args>, 'fetcher'>;
|
|
112
141
|
/**
|
|
113
142
|
* Computes query key for the given model, operation, query args, and options.
|
|
@@ -153,4 +182,4 @@ declare function useInvalidation(model: string, modelMeta: ModelMeta): Invalidat
|
|
|
153
182
|
*/
|
|
154
183
|
declare function fetcher<R, C extends boolean>(url: string, options?: RequestInit, fetch?: FetchFn, checkReadBack?: C): Promise<C extends true ? R | undefined : R>;
|
|
155
184
|
|
|
156
|
-
export { type CheckSelect, type Enumerable, type FetchFn, type GetNextArgs, type InfiniteQueryOptions, type MaybeTupleToUnion, type MutationOptions, type PickEnumerable, Provider, type QueryOptions, RequestHandlerContext, type TupleToUnion, fetcher, getQueryKey, mutationRequest, useHooksContext, useInfiniteModelQuery, useInvalidation, useModelMutation, useModelQuery };
|
|
185
|
+
export { type CheckSelect, type Enumerable, type FetchFn, type GetNextArgs, type InfiniteQueryOptions, type MaybeTupleToUnion, type MutationOptions, type OptimisticDataProvider, type OptimisticDataProviderResult, type PickEnumerable, Provider, type QueryOptions, RequestHandlerContext, type TupleToUnion, fetcher, getQueryKey, mutationRequest, useHooksContext, useInfiniteModelQuery, useInvalidation, useModelMutation, useModelQuery };
|
package/runtime/index.d.ts
CHANGED
|
@@ -74,12 +74,6 @@ type QueryOptions<Result, Error = unknown> = {
|
|
|
74
74
|
* Disable data fetching
|
|
75
75
|
*/
|
|
76
76
|
disabled?: boolean;
|
|
77
|
-
/**
|
|
78
|
-
* @deprecated Use `fallbackData` instead
|
|
79
|
-
*
|
|
80
|
-
* Equivalent to @see SWRConfiguration.fallbackData
|
|
81
|
-
*/
|
|
82
|
-
initialData?: Result;
|
|
83
77
|
/**
|
|
84
78
|
* Whether to enable automatic optimistic update. Defaults to `true`.
|
|
85
79
|
*/
|
|
@@ -93,13 +87,44 @@ type InfiniteQueryOptions<Result, Error = unknown> = {
|
|
|
93
87
|
* Disable data fetching
|
|
94
88
|
*/
|
|
95
89
|
disabled?: boolean;
|
|
90
|
+
} & Omit<SWRInfiniteConfiguration<Result, Error, SWRInfiniteFetcher<Result>>, 'fetcher'>;
|
|
91
|
+
/**
|
|
92
|
+
* Result of optimistic data provider.
|
|
93
|
+
*/
|
|
94
|
+
type OptimisticDataProviderResult = {
|
|
95
|
+
/**
|
|
96
|
+
* Kind of the result.
|
|
97
|
+
* - Update: use the `data` field to update the query cache.
|
|
98
|
+
* - Skip: skip the optimistic update for this query.
|
|
99
|
+
* - ProceedDefault: proceed with the default optimistic update.
|
|
100
|
+
*/
|
|
101
|
+
kind: 'Update' | 'Skip' | 'ProceedDefault';
|
|
96
102
|
/**
|
|
97
|
-
*
|
|
103
|
+
* Data to update the query cache. Only applicable if `kind` is 'Update'.
|
|
98
104
|
*
|
|
99
|
-
*
|
|
105
|
+
* If the data is an object with fields updated, it should have a `$optimistic`
|
|
106
|
+
* field set to `true`. If it's an array and an element object is created or updated,
|
|
107
|
+
* the element should have a `$optimistic` field set to `true`.
|
|
100
108
|
*/
|
|
101
|
-
|
|
102
|
-
}
|
|
109
|
+
data?: any;
|
|
110
|
+
};
|
|
111
|
+
/**
|
|
112
|
+
* Optimistic data provider.
|
|
113
|
+
*
|
|
114
|
+
* @param args Arguments.
|
|
115
|
+
* @param args.queryModel The model of the query.
|
|
116
|
+
* @param args.queryOperation The operation of the query, `findMany`, `count`, etc.
|
|
117
|
+
* @param args.queryArgs The arguments of the query.
|
|
118
|
+
* @param args.currentData The current cache data for the query.
|
|
119
|
+
* @param args.mutationArgs The arguments of the mutation.
|
|
120
|
+
*/
|
|
121
|
+
type OptimisticDataProvider = (args: {
|
|
122
|
+
queryModel: string;
|
|
123
|
+
queryOperation: string;
|
|
124
|
+
queryArgs: any;
|
|
125
|
+
currentData: any;
|
|
126
|
+
mutationArgs: any;
|
|
127
|
+
}) => OptimisticDataProviderResult | Promise<OptimisticDataProviderResult>;
|
|
103
128
|
/**
|
|
104
129
|
* Mutation options.
|
|
105
130
|
*/
|
|
@@ -108,6 +133,10 @@ type MutationOptions<Result, Error, Args> = {
|
|
|
108
133
|
* Whether to automatically optimistic-update queries potentially impacted. Defaults to `false`.
|
|
109
134
|
*/
|
|
110
135
|
optimisticUpdate?: boolean;
|
|
136
|
+
/**
|
|
137
|
+
* A callback for computing optimistic update data for each query cache entry.
|
|
138
|
+
*/
|
|
139
|
+
optimisticDataProvider?: OptimisticDataProvider;
|
|
111
140
|
} & Omit<SWRMutationConfiguration<Result, Error, string, Args>, 'fetcher'>;
|
|
112
141
|
/**
|
|
113
142
|
* Computes query key for the given model, operation, query args, and options.
|
|
@@ -153,4 +182,4 @@ declare function useInvalidation(model: string, modelMeta: ModelMeta): Invalidat
|
|
|
153
182
|
*/
|
|
154
183
|
declare function fetcher<R, C extends boolean>(url: string, options?: RequestInit, fetch?: FetchFn, checkReadBack?: C): Promise<C extends true ? R | undefined : R>;
|
|
155
184
|
|
|
156
|
-
export { type CheckSelect, type Enumerable, type FetchFn, type GetNextArgs, type InfiniteQueryOptions, type MaybeTupleToUnion, type MutationOptions, type PickEnumerable, Provider, type QueryOptions, RequestHandlerContext, type TupleToUnion, fetcher, getQueryKey, mutationRequest, useHooksContext, useInfiniteModelQuery, useInvalidation, useModelMutation, useModelQuery };
|
|
185
|
+
export { type CheckSelect, type Enumerable, type FetchFn, type GetNextArgs, type InfiniteQueryOptions, type MaybeTupleToUnion, type MutationOptions, type OptimisticDataProvider, type OptimisticDataProviderResult, type PickEnumerable, Provider, type QueryOptions, RequestHandlerContext, type TupleToUnion, fetcher, getQueryKey, mutationRequest, useHooksContext, useInfiniteModelQuery, useInvalidation, useModelMutation, useModelQuery };
|
package/runtime/index.js
CHANGED
|
@@ -136,16 +136,12 @@ function parseQueryKey(key) {
|
|
|
136
136
|
return (keyValue == null ? void 0 : keyValue.prefix) === QUERY_KEY_PREFIX ? keyValue : void 0;
|
|
137
137
|
}
|
|
138
138
|
function useModelQuery(model, operation, args, options) {
|
|
139
|
-
var _a;
|
|
140
139
|
const { endpoint, fetch: fetch2 } = useHooksContext();
|
|
141
140
|
const key = (options == null ? void 0 : options.disabled) ? null : getQueryKey(model, operation, args, false, (options == null ? void 0 : options.optimisticUpdate) !== false);
|
|
142
141
|
const url = makeUrl(`${endpoint}/${(0, import_lower_case_first.lowerCaseFirst)(model)}/${operation}`, args);
|
|
143
|
-
return (0, import_swr.default)(key, () => fetcher(url, void 0, fetch2, false),
|
|
144
|
-
fallbackData: (_a = options == null ? void 0 : options.initialData) != null ? _a : options == null ? void 0 : options.fallbackData
|
|
145
|
-
}));
|
|
142
|
+
return (0, import_swr.default)(key, () => fetcher(url, void 0, fetch2, false), options);
|
|
146
143
|
}
|
|
147
144
|
function useInfiniteModelQuery(model, operation, getNextArgs, options) {
|
|
148
|
-
var _a;
|
|
149
145
|
const { endpoint, fetch: fetch2 } = useHooksContext();
|
|
150
146
|
const getKey = (pageIndex, previousPageData) => {
|
|
151
147
|
if (options == null ? void 0 : options.disabled) {
|
|
@@ -166,9 +162,7 @@ function useInfiniteModelQuery(model, operation, getNextArgs, options) {
|
|
|
166
162
|
throw new Error("Invalid query key: " + key);
|
|
167
163
|
}
|
|
168
164
|
},
|
|
169
|
-
|
|
170
|
-
fallbackData: (_a = options == null ? void 0 : options.initialData) != null ? _a : options == null ? void 0 : options.fallbackData
|
|
171
|
-
})
|
|
165
|
+
options
|
|
172
166
|
);
|
|
173
167
|
}
|
|
174
168
|
function useModelMutation(model, method, operation, modelMeta, options, checkReadBack) {
|
|
@@ -179,7 +173,7 @@ function useModelMutation(model, method, operation, modelMeta, options, checkRea
|
|
|
179
173
|
getMutationKey(model, operation),
|
|
180
174
|
(_key, { arg }) => {
|
|
181
175
|
if (options == null ? void 0 : options.optimisticUpdate) {
|
|
182
|
-
optimisticUpdate(model, operation, arg, modelMeta, cache, mutate, logging);
|
|
176
|
+
optimisticUpdate(model, operation, arg, options, modelMeta, cache, mutate, logging);
|
|
183
177
|
}
|
|
184
178
|
const url = `${endpoint}/${(0, import_lower_case_first.lowerCaseFirst)(model)}/${operation}`;
|
|
185
179
|
return mutationRequest(method, url, arg, invalidate, fetch2, checkReadBack);
|
|
@@ -300,7 +294,7 @@ function getOperationFromUrl(url) {
|
|
|
300
294
|
return r;
|
|
301
295
|
}
|
|
302
296
|
}
|
|
303
|
-
function optimisticUpdate(mutationModel, mutationOp, mutationArgs, modelMeta, cache, mutator, logging = false) {
|
|
297
|
+
function optimisticUpdate(mutationModel, mutationOp, mutationArgs, options, modelMeta, cache, mutator, logging = false) {
|
|
304
298
|
return __async(this, null, function* () {
|
|
305
299
|
const optimisticPromises = [];
|
|
306
300
|
for (const key of cache.keys()) {
|
|
@@ -315,15 +309,36 @@ function optimisticUpdate(mutationModel, mutationOp, mutationArgs, modelMeta, ca
|
|
|
315
309
|
continue;
|
|
316
310
|
}
|
|
317
311
|
const cacheValue = cache.get(key);
|
|
318
|
-
if (
|
|
319
|
-
continue;
|
|
320
|
-
}
|
|
321
|
-
if (cacheValue.error) {
|
|
312
|
+
if (cacheValue == null ? void 0 : cacheValue.error) {
|
|
322
313
|
if (logging) {
|
|
323
314
|
console.warn(`Skipping optimistic update for ${key} due to error:`, cacheValue.error);
|
|
324
315
|
}
|
|
325
316
|
continue;
|
|
326
317
|
}
|
|
318
|
+
if (options == null ? void 0 : options.optimisticDataProvider) {
|
|
319
|
+
const providerResult = yield options.optimisticDataProvider({
|
|
320
|
+
queryModel: parsedKey.model,
|
|
321
|
+
queryOperation: parsedKey.operation,
|
|
322
|
+
queryArgs: parsedKey.args,
|
|
323
|
+
currentData: cacheValue == null ? void 0 : cacheValue.data,
|
|
324
|
+
mutationArgs
|
|
325
|
+
});
|
|
326
|
+
if ((providerResult == null ? void 0 : providerResult.kind) === "Skip") {
|
|
327
|
+
if (logging) {
|
|
328
|
+
console.log(`Skipping optimistic update for ${key} due to custom provider`);
|
|
329
|
+
}
|
|
330
|
+
continue;
|
|
331
|
+
} else if ((providerResult == null ? void 0 : providerResult.kind) === "Update") {
|
|
332
|
+
if (logging) {
|
|
333
|
+
console.log(`Optimistically updating query ${JSON.stringify(key)} due to provider`);
|
|
334
|
+
}
|
|
335
|
+
optimisticPromises.push(mutator(key, providerResult.data, { revalidate: false }));
|
|
336
|
+
continue;
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
if (!cacheValue) {
|
|
340
|
+
continue;
|
|
341
|
+
}
|
|
327
342
|
const mutatedData = yield (0, import_cross.applyMutation)(
|
|
328
343
|
parsedKey.model,
|
|
329
344
|
parsedKey.operation,
|
package/runtime/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/runtime/index.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { deserialize, serialize } from '@zenstackhq/runtime/browser';\nimport {\n applyMutation,\n getMutatedModels,\n getReadModels,\n type ModelMeta,\n type PrismaWriteActionType,\n} from '@zenstackhq/runtime/cross';\nimport * as crossFetch from 'cross-fetch';\nimport { lowerCaseFirst } from 'lower-case-first';\nimport { createContext, useContext } from 'react';\nimport type { Cache, Fetcher, SWRConfiguration, SWRResponse } from 'swr';\nimport useSWR, { useSWRConfig } from 'swr';\nimport { ScopedMutator } from 'swr/_internal';\nimport useSWRInfinite, {\n unstable_serialize,\n type SWRInfiniteConfiguration,\n type SWRInfiniteFetcher,\n type SWRInfiniteResponse,\n} from 'swr/infinite';\nimport useSWRMutation, { type SWRMutationConfiguration } from 'swr/mutation';\nexport * from './prisma-types';\n\n/**\n * Function signature for `fetch`.\n */\nexport type FetchFn = (url: string, options?: RequestInit) => Promise<Response>;\n\n/**\n * Context type for configuring react hooks.\n */\nexport type RequestHandlerContext = {\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\nconst DEFAULT_QUERY_ENDPOINT = '/api/model';\n\n/**\n * Context for configuring react hooks.\n */\nexport const RequestHandlerContext = createContext<RequestHandlerContext>({\n endpoint: DEFAULT_QUERY_ENDPOINT,\n fetch: undefined,\n});\n\n/**\n * Context provider.\n */\nexport const Provider = RequestHandlerContext.Provider;\n\n/**\n * Hooks context.\n */\nexport function useHooksContext() {\n const { endpoint, ...rest } = useContext(RequestHandlerContext);\n return { endpoint: endpoint ?? DEFAULT_QUERY_ENDPOINT, ...rest };\n}\n\n/**\n * Regular query options.\n */\nexport type QueryOptions<Result, Error = unknown> = {\n /**\n * Disable data fetching\n */\n disabled?: boolean;\n\n /**\n * @deprecated Use `fallbackData` instead\n *\n * Equivalent to @see SWRConfiguration.fallbackData\n */\n initialData?: Result;\n\n /**\n * Whether to enable automatic optimistic update. Defaults to `true`.\n */\n optimisticUpdate?: boolean;\n} & Omit<SWRConfiguration<Result, Error, Fetcher<Result>>, 'fetcher'>;\n\n/**\n * Infinite query options.\n */\nexport type InfiniteQueryOptions<Result, Error = unknown> = {\n /**\n * Disable data fetching\n */\n disabled?: boolean;\n\n /**\n * @deprecated Use `fallbackData` instead\n *\n * Equivalent to @see SWRInfiniteConfiguration.fallbackData\n */\n initialData?: Result[];\n} & Omit<SWRInfiniteConfiguration<Result, Error, SWRInfiniteFetcher<Result>>, 'fetcher'>;\n\nconst QUERY_KEY_PREFIX = 'zenstack:query';\nconst MUTATION_KEY_PREFIX = 'zenstack:mutation';\n\ntype QueryKey = {\n prefix: typeof QUERY_KEY_PREFIX;\n model: string;\n operation: string;\n args?: unknown;\n infinite?: boolean;\n optimisticUpdate?: boolean;\n};\n\n/**\n * Mutation options.\n */\nexport type MutationOptions<Result, Error, Args> = {\n /**\n * Whether to automatically optimistic-update queries potentially impacted. Defaults to `false`.\n */\n optimisticUpdate?: boolean;\n} & Omit<SWRMutationConfiguration<Result, Error, string, Args>, 'fetcher'>;\n\n/**\n * Computes query key for the given model, operation, query args, and options.\n */\nexport function getQueryKey(\n model: string,\n operation: string,\n args?: unknown,\n infinite?: boolean,\n optimisticUpdate?: boolean\n) {\n return JSON.stringify({\n prefix: QUERY_KEY_PREFIX,\n model,\n operation,\n args,\n infinite: infinite === true,\n optimisticUpdate: optimisticUpdate !== false,\n });\n}\n\nfunction getMutationKey(model: string, operation: string) {\n // use a random key since we don't have 1:1 mapping between mutation and query\n // https://github.com/vercel/swr/discussions/2461#discussioncomment-5281784\n return JSON.stringify({ prefix: MUTATION_KEY_PREFIX, model, operation, r: Date.now() });\n}\n\nfunction parseQueryKey(key: unknown): QueryKey | undefined {\n let keyValue: any = key;\n if (typeof key === 'string') {\n try {\n keyValue = JSON.parse(key);\n } catch {\n return undefined;\n }\n }\n return keyValue?.prefix === QUERY_KEY_PREFIX ? (keyValue as QueryKey) : undefined;\n}\n\n/**\n * Makes a model query with SWR.\n *\n * @param model Model name\n * @param operation Prisma operation (e.g, `findMany`)\n * @param args The request args object, which will be superjson-stringified and appended as \"?q=\" parameter\n * @param options Query options\n * @returns SWR response\n */\nexport function useModelQuery<Result, Error = unknown>(\n model: string,\n operation: string,\n args?: unknown,\n options?: QueryOptions<Result, Error>\n): SWRResponse<Result, Error> {\n const { endpoint, fetch } = useHooksContext();\n const key = options?.disabled\n ? null\n : getQueryKey(model, operation, args, false, options?.optimisticUpdate !== false);\n const url = makeUrl(`${endpoint}/${lowerCaseFirst(model)}/${operation}`, args);\n return useSWR<Result, Error>(key, () => fetcher<Result, false>(url, undefined, fetch, false), {\n ...options,\n fallbackData: options?.initialData ?? options?.fallbackData,\n });\n}\n\n/**\n * Function for computing the query args for fetching a page during an infinite query.\n */\nexport type GetNextArgs<Args, Result> = (pageIndex: number, previousPageData: Result | null) => Args | null;\n\n/**\n * Makes an infinite GET request with SWR.\n *\n * @param model Model name\n * @param operation Prisma operation (e.g, `findMany`)\n * @param getNextArgs Function for computing the query args for a page\n * @param options Query options\n * @returns SWR infinite query response\n */\nexport function useInfiniteModelQuery<Args, Result, Error = unknown>(\n model: string,\n operation: string,\n getNextArgs: GetNextArgs<Args, any>,\n options?: InfiniteQueryOptions<Result, Error>\n): SWRInfiniteResponse<Result, Error> {\n const { endpoint, fetch } = useHooksContext();\n\n const getKey = (pageIndex: number, previousPageData: Result | null) => {\n if (options?.disabled) {\n return null;\n }\n const nextArgs = getNextArgs(pageIndex, previousPageData);\n return nextArgs !== null // null means reached the end\n ? getQueryKey(model, operation, nextArgs, true, false)\n : null;\n };\n\n return useSWRInfinite<Result, Error>(\n getKey,\n (key: unknown) => {\n const parsedKey = parseQueryKey(key);\n if (parsedKey) {\n const { model, operation, args } = parsedKey;\n const url = makeUrl(`${endpoint}/${lowerCaseFirst(model)}/${operation}`, args);\n return fetcher<Result, false>(url, undefined, fetch, false);\n } else {\n throw new Error('Invalid query key: ' + key);\n }\n },\n {\n ...options,\n fallbackData: options?.initialData ?? options?.fallbackData,\n }\n );\n}\n\nexport function useModelMutation<Args, Result, CheckReadBack extends boolean = boolean>(\n model: string,\n method: 'POST' | 'PUT' | 'DELETE',\n operation: string,\n modelMeta: ModelMeta,\n options?: MutationOptions<CheckReadBack extends true ? Result | undefined : Result, unknown, Args>,\n checkReadBack?: CheckReadBack\n) {\n const { endpoint, fetch, logging } = useHooksContext();\n const invalidate = options?.revalidate !== false ? useInvalidation(model, modelMeta) : undefined;\n const { cache, mutate } = useSWRConfig();\n\n return useSWRMutation(\n getMutationKey(model, operation),\n (_key, { arg }: { arg: any }) => {\n if (options?.optimisticUpdate) {\n optimisticUpdate(model, operation, arg, modelMeta, cache, mutate, logging);\n }\n const url = `${endpoint}/${lowerCaseFirst(model)}/${operation}`;\n return mutationRequest(method, url, arg, invalidate, fetch, checkReadBack);\n },\n options\n );\n}\n\n/**\n * Makes a mutation request.\n *\n * @param url The request URL\n * @param data The request data\n * @param invalidate Function for invalidating a query\n */\nexport async function mutationRequest<Result, C extends boolean = boolean>(\n method: 'POST' | 'PUT' | 'DELETE',\n url: string,\n data: unknown,\n invalidate?: Invalidator,\n fetch?: FetchFn,\n checkReadBack?: C\n): Promise<C extends true ? Result | undefined : Result> {\n const reqUrl = method === 'DELETE' ? makeUrl(url, data) : url;\n const r = await fetcher<Result, C>(\n reqUrl,\n {\n method,\n headers: {\n 'content-type': 'application/json',\n },\n body: data ? marshal(data) : undefined,\n },\n fetch,\n checkReadBack\n );\n\n if (invalidate) {\n await invalidate(getOperationFromUrl(url), data);\n }\n return r;\n}\n\n// function for invalidating queries related to mutation represented by its operation and args\ntype Invalidator = (operation: string, args?: unknown) => ReturnType<ScopedMutator>;\n\nexport function useInvalidation(model: string, modelMeta: ModelMeta): Invalidator {\n // https://swr.vercel.app/docs/advanced/cache#mutate-multiple-keys-from-regex\n const { logging } = useHooksContext();\n const { cache, mutate } = useSWRConfig();\n return async (operation: string, args: unknown) => {\n if (!(cache instanceof Map)) {\n throw new Error('mutate requires the cache provider to be a Map instance');\n }\n\n const mutatedModels = await getMutatedModels(model, operation as PrismaWriteActionType, args, modelMeta);\n\n const keys = Array.from(cache.keys()).filter((key: unknown) => {\n const parsedKey = parseQueryKey(key);\n if (!parsedKey) {\n return false;\n }\n const modelsRead = getReadModels(parsedKey.model, modelMeta, parsedKey.args);\n return modelsRead.some((m) => mutatedModels.includes(m));\n });\n\n if (logging) {\n keys.forEach((key) => {\n console.log(`Invalidating query ${key} due to mutation \"${model}.${operation}\"`);\n });\n }\n\n const mutations = keys.map((key) => {\n const parsedKey = parseQueryKey(key);\n // FIX: special handling for infinite query keys, but still not working\n // https://github.com/vercel/swr/discussions/2843\n return mutate(parsedKey?.infinite ? unstable_serialize(() => key) : key);\n });\n return Promise.all(mutations);\n };\n}\n\n/**\n * Makes fetch request for queries and mutations.\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\nfunction 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\nfunction 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\nfunction 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\nfunction getOperationFromUrl(url: string) {\n const parts = url.split('/');\n const r = parts.pop();\n if (!r) {\n throw new Error(`Invalid URL: ${url}`);\n } else {\n return r;\n }\n}\n\nasync function optimisticUpdate(\n mutationModel: string,\n mutationOp: string,\n mutationArgs: any,\n modelMeta: ModelMeta,\n cache: Cache,\n mutator: ScopedMutator,\n logging = false\n) {\n const optimisticPromises: Array<Promise<void>> = [];\n for (const key of cache.keys()) {\n const parsedKey = parseQueryKey(key);\n if (!parsedKey) {\n continue;\n }\n\n if (!parsedKey.optimisticUpdate) {\n if (logging) {\n console.log(`Skipping optimistic update for ${key} due to opt-out`);\n }\n continue;\n }\n\n const cacheValue = cache.get(key);\n if (!cacheValue) {\n continue;\n }\n\n if (cacheValue.error) {\n if (logging) {\n console.warn(`Skipping optimistic update for ${key} due to error:`, cacheValue.error);\n }\n continue;\n }\n\n const mutatedData = await applyMutation(\n parsedKey.model,\n parsedKey.operation,\n cacheValue.data,\n mutationModel,\n mutationOp as PrismaWriteActionType,\n mutationArgs,\n modelMeta,\n logging\n );\n\n if (mutatedData !== undefined) {\n // mutation applicable to this query, update cache\n if (logging) {\n console.log(\n `Optimistically updating query ${JSON.stringify(\n key\n )} due to mutation \"${mutationModel}.${mutationOp}\"`\n );\n }\n optimisticPromises.push(\n mutator(key, mutatedData, {\n // don't trigger revalidation here since we will do it\n // when the remote mutation succeeds\n revalidate: false,\n })\n );\n }\n }\n\n return Promise.all(optimisticPromises);\n}\n"],"mappings":"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","names":["optimisticUpdate","fetch","useSWR","useSWRInfinite","model","operation","useSWRMutation"]}
|
|
1
|
+
{"version":3,"sources":["../../src/runtime/index.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { deserialize, serialize } from '@zenstackhq/runtime/browser';\nimport {\n applyMutation,\n getMutatedModels,\n getReadModels,\n type ModelMeta,\n type PrismaWriteActionType,\n} from '@zenstackhq/runtime/cross';\nimport * as crossFetch from 'cross-fetch';\nimport { lowerCaseFirst } from 'lower-case-first';\nimport { createContext, useContext } from 'react';\nimport type { Cache, Fetcher, SWRConfiguration, SWRResponse } from 'swr';\nimport useSWR, { useSWRConfig } from 'swr';\nimport { ScopedMutator } from 'swr/_internal';\nimport useSWRInfinite, {\n unstable_serialize,\n type SWRInfiniteConfiguration,\n type SWRInfiniteFetcher,\n type SWRInfiniteResponse,\n} from 'swr/infinite';\nimport useSWRMutation, { type SWRMutationConfiguration } from 'swr/mutation';\nexport * from './prisma-types';\n\n/**\n * Function signature for `fetch`.\n */\nexport type FetchFn = (url: string, options?: RequestInit) => Promise<Response>;\n\n/**\n * Context type for configuring react hooks.\n */\nexport type RequestHandlerContext = {\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\nconst DEFAULT_QUERY_ENDPOINT = '/api/model';\n\n/**\n * Context for configuring react hooks.\n */\nexport const RequestHandlerContext = createContext<RequestHandlerContext>({\n endpoint: DEFAULT_QUERY_ENDPOINT,\n fetch: undefined,\n});\n\n/**\n * Context provider.\n */\nexport const Provider = RequestHandlerContext.Provider;\n\n/**\n * Hooks context.\n */\nexport function useHooksContext() {\n const { endpoint, ...rest } = useContext(RequestHandlerContext);\n return { endpoint: endpoint ?? DEFAULT_QUERY_ENDPOINT, ...rest };\n}\n\n/**\n * Regular query options.\n */\nexport type QueryOptions<Result, Error = unknown> = {\n /**\n * Disable data fetching\n */\n disabled?: boolean;\n\n /**\n * Whether to enable automatic optimistic update. Defaults to `true`.\n */\n optimisticUpdate?: boolean;\n} & Omit<SWRConfiguration<Result, Error, Fetcher<Result>>, 'fetcher'>;\n\n/**\n * Infinite query options.\n */\nexport type InfiniteQueryOptions<Result, Error = unknown> = {\n /**\n * Disable data fetching\n */\n disabled?: boolean;\n} & Omit<SWRInfiniteConfiguration<Result, Error, SWRInfiniteFetcher<Result>>, 'fetcher'>;\n\nconst QUERY_KEY_PREFIX = 'zenstack:query';\nconst MUTATION_KEY_PREFIX = 'zenstack:mutation';\n\ntype QueryKey = {\n prefix: typeof QUERY_KEY_PREFIX;\n model: string;\n operation: string;\n args?: unknown;\n infinite?: boolean;\n optimisticUpdate?: boolean;\n};\n\n/**\n * Result of optimistic data provider.\n */\nexport type OptimisticDataProviderResult = {\n /**\n * Kind of the result.\n * - Update: use the `data` field to update the query cache.\n * - Skip: skip the optimistic update for this query.\n * - ProceedDefault: proceed with the default optimistic update.\n */\n kind: 'Update' | 'Skip' | 'ProceedDefault';\n\n /**\n * Data to update the query cache. Only applicable if `kind` is 'Update'.\n *\n * If the data is an object with fields updated, it should have a `$optimistic`\n * field set to `true`. If it's an array and an element object is created or updated,\n * the element should have a `$optimistic` field set to `true`.\n */\n data?: any;\n};\n\n/**\n * Optimistic data provider.\n *\n * @param args Arguments.\n * @param args.queryModel The model of the query.\n * @param args.queryOperation The operation of the query, `findMany`, `count`, etc.\n * @param args.queryArgs The arguments of the query.\n * @param args.currentData The current cache data for the query.\n * @param args.mutationArgs The arguments of the mutation.\n */\nexport type OptimisticDataProvider = (args: {\n queryModel: string;\n queryOperation: string;\n queryArgs: any;\n currentData: any;\n mutationArgs: any;\n}) => OptimisticDataProviderResult | Promise<OptimisticDataProviderResult>;\n\n/**\n * Mutation options.\n */\nexport type MutationOptions<Result, Error, Args> = {\n /**\n * Whether to automatically optimistic-update queries potentially impacted. Defaults to `false`.\n */\n optimisticUpdate?: boolean;\n\n /**\n * A callback for computing optimistic update data for each query cache entry.\n */\n optimisticDataProvider?: OptimisticDataProvider;\n} & Omit<SWRMutationConfiguration<Result, Error, string, Args>, 'fetcher'>;\n\n/**\n * Computes query key for the given model, operation, query args, and options.\n */\nexport function getQueryKey(\n model: string,\n operation: string,\n args?: unknown,\n infinite?: boolean,\n optimisticUpdate?: boolean\n) {\n return JSON.stringify({\n prefix: QUERY_KEY_PREFIX,\n model,\n operation,\n args,\n infinite: infinite === true,\n optimisticUpdate: optimisticUpdate !== false,\n });\n}\n\nfunction getMutationKey(model: string, operation: string) {\n // use a random key since we don't have 1:1 mapping between mutation and query\n // https://github.com/vercel/swr/discussions/2461#discussioncomment-5281784\n return JSON.stringify({ prefix: MUTATION_KEY_PREFIX, model, operation, r: Date.now() });\n}\n\nfunction parseQueryKey(key: unknown): QueryKey | undefined {\n let keyValue: any = key;\n if (typeof key === 'string') {\n try {\n keyValue = JSON.parse(key);\n } catch {\n return undefined;\n }\n }\n return keyValue?.prefix === QUERY_KEY_PREFIX ? (keyValue as QueryKey) : undefined;\n}\n\n/**\n * Makes a model query with SWR.\n *\n * @param model Model name\n * @param operation Prisma operation (e.g, `findMany`)\n * @param args The request args object, which will be superjson-stringified and appended as \"?q=\" parameter\n * @param options Query options\n * @returns SWR response\n */\nexport function useModelQuery<Result, Error = unknown>(\n model: string,\n operation: string,\n args?: unknown,\n options?: QueryOptions<Result, Error>\n): SWRResponse<Result, Error> {\n const { endpoint, fetch } = useHooksContext();\n const key = options?.disabled\n ? null\n : getQueryKey(model, operation, args, false, options?.optimisticUpdate !== false);\n const url = makeUrl(`${endpoint}/${lowerCaseFirst(model)}/${operation}`, args);\n return useSWR<Result, Error>(key, () => fetcher<Result, false>(url, undefined, fetch, false), options);\n}\n\n/**\n * Function for computing the query args for fetching a page during an infinite query.\n */\nexport type GetNextArgs<Args, Result> = (pageIndex: number, previousPageData: Result | null) => Args | null;\n\n/**\n * Makes an infinite GET request with SWR.\n *\n * @param model Model name\n * @param operation Prisma operation (e.g, `findMany`)\n * @param getNextArgs Function for computing the query args for a page\n * @param options Query options\n * @returns SWR infinite query response\n */\nexport function useInfiniteModelQuery<Args, Result, Error = unknown>(\n model: string,\n operation: string,\n getNextArgs: GetNextArgs<Args, any>,\n options?: InfiniteQueryOptions<Result, Error>\n): SWRInfiniteResponse<Result, Error> {\n const { endpoint, fetch } = useHooksContext();\n\n const getKey = (pageIndex: number, previousPageData: Result | null) => {\n if (options?.disabled) {\n return null;\n }\n const nextArgs = getNextArgs(pageIndex, previousPageData);\n return nextArgs !== null // null means reached the end\n ? getQueryKey(model, operation, nextArgs, true, false)\n : null;\n };\n\n return useSWRInfinite<Result, Error>(\n getKey,\n (key: unknown) => {\n const parsedKey = parseQueryKey(key);\n if (parsedKey) {\n const { model, operation, args } = parsedKey;\n const url = makeUrl(`${endpoint}/${lowerCaseFirst(model)}/${operation}`, args);\n return fetcher<Result, false>(url, undefined, fetch, false);\n } else {\n throw new Error('Invalid query key: ' + key);\n }\n },\n options\n );\n}\n\nexport function useModelMutation<Args, Result, CheckReadBack extends boolean = boolean>(\n model: string,\n method: 'POST' | 'PUT' | 'DELETE',\n operation: string,\n modelMeta: ModelMeta,\n options?: MutationOptions<CheckReadBack extends true ? Result | undefined : Result, unknown, Args>,\n checkReadBack?: CheckReadBack\n) {\n const { endpoint, fetch, logging } = useHooksContext();\n const invalidate = options?.revalidate !== false ? useInvalidation(model, modelMeta) : undefined;\n const { cache, mutate } = useSWRConfig();\n\n return useSWRMutation(\n getMutationKey(model, operation),\n (_key, { arg }: { arg: any }) => {\n if (options?.optimisticUpdate) {\n optimisticUpdate(model, operation, arg, options, modelMeta, cache, mutate, logging);\n }\n const url = `${endpoint}/${lowerCaseFirst(model)}/${operation}`;\n return mutationRequest(method, url, arg, invalidate, fetch, checkReadBack);\n },\n options\n );\n}\n\n/**\n * Makes a mutation request.\n *\n * @param url The request URL\n * @param data The request data\n * @param invalidate Function for invalidating a query\n */\nexport async function mutationRequest<Result, C extends boolean = boolean>(\n method: 'POST' | 'PUT' | 'DELETE',\n url: string,\n data: unknown,\n invalidate?: Invalidator,\n fetch?: FetchFn,\n checkReadBack?: C\n): Promise<C extends true ? Result | undefined : Result> {\n const reqUrl = method === 'DELETE' ? makeUrl(url, data) : url;\n const r = await fetcher<Result, C>(\n reqUrl,\n {\n method,\n headers: {\n 'content-type': 'application/json',\n },\n body: data ? marshal(data) : undefined,\n },\n fetch,\n checkReadBack\n );\n\n if (invalidate) {\n await invalidate(getOperationFromUrl(url), data);\n }\n return r;\n}\n\n// function for invalidating queries related to mutation represented by its operation and args\ntype Invalidator = (operation: string, args?: unknown) => ReturnType<ScopedMutator>;\n\nexport function useInvalidation(model: string, modelMeta: ModelMeta): Invalidator {\n // https://swr.vercel.app/docs/advanced/cache#mutate-multiple-keys-from-regex\n const { logging } = useHooksContext();\n const { cache, mutate } = useSWRConfig();\n return async (operation: string, args: unknown) => {\n if (!(cache instanceof Map)) {\n throw new Error('mutate requires the cache provider to be a Map instance');\n }\n\n const mutatedModels = await getMutatedModels(model, operation as PrismaWriteActionType, args, modelMeta);\n\n const keys = Array.from(cache.keys()).filter((key: unknown) => {\n const parsedKey = parseQueryKey(key);\n if (!parsedKey) {\n return false;\n }\n const modelsRead = getReadModels(parsedKey.model, modelMeta, parsedKey.args);\n return modelsRead.some((m) => mutatedModels.includes(m));\n });\n\n if (logging) {\n keys.forEach((key) => {\n console.log(`Invalidating query ${key} due to mutation \"${model}.${operation}\"`);\n });\n }\n\n const mutations = keys.map((key) => {\n const parsedKey = parseQueryKey(key);\n // FIX: special handling for infinite query keys, but still not working\n // https://github.com/vercel/swr/discussions/2843\n return mutate(parsedKey?.infinite ? unstable_serialize(() => key) : key);\n });\n return Promise.all(mutations);\n };\n}\n\n/**\n * Makes fetch request for queries and mutations.\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\nfunction 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\nfunction 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\nfunction 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\nfunction getOperationFromUrl(url: string) {\n const parts = url.split('/');\n const r = parts.pop();\n if (!r) {\n throw new Error(`Invalid URL: ${url}`);\n } else {\n return r;\n }\n}\n\nasync function optimisticUpdate(\n mutationModel: string,\n mutationOp: string,\n mutationArgs: any,\n options: MutationOptions<any, any, any> | undefined,\n modelMeta: ModelMeta,\n cache: Cache,\n mutator: ScopedMutator,\n logging = false\n) {\n const optimisticPromises: Array<Promise<void>> = [];\n for (const key of cache.keys()) {\n const parsedKey = parseQueryKey(key);\n if (!parsedKey) {\n continue;\n }\n\n if (!parsedKey.optimisticUpdate) {\n if (logging) {\n console.log(`Skipping optimistic update for ${key} due to opt-out`);\n }\n continue;\n }\n\n const cacheValue = cache.get(key);\n if (cacheValue?.error) {\n if (logging) {\n console.warn(`Skipping optimistic update for ${key} due to error:`, cacheValue.error);\n }\n continue;\n }\n\n if (options?.optimisticDataProvider) {\n const providerResult = await options.optimisticDataProvider({\n queryModel: parsedKey.model,\n queryOperation: parsedKey.operation,\n queryArgs: parsedKey.args,\n currentData: cacheValue?.data,\n mutationArgs,\n });\n\n if (providerResult?.kind === 'Skip') {\n if (logging) {\n console.log(`Skipping optimistic update for ${key} due to custom provider`);\n }\n continue;\n } else if (providerResult?.kind === 'Update') {\n if (logging) {\n console.log(`Optimistically updating query ${JSON.stringify(key)} due to provider`);\n }\n optimisticPromises.push(mutator(key, providerResult.data, { revalidate: false }));\n continue;\n }\n }\n\n if (!cacheValue) {\n continue;\n }\n\n const mutatedData = await applyMutation(\n parsedKey.model,\n parsedKey.operation,\n cacheValue.data,\n mutationModel,\n mutationOp as PrismaWriteActionType,\n mutationArgs,\n modelMeta,\n logging\n );\n\n if (mutatedData !== undefined) {\n // mutation applicable to this query, update cache\n if (logging) {\n console.log(\n `Optimistically updating query ${JSON.stringify(\n key\n )} due to mutation \"${mutationModel}.${mutationOp}\"`\n );\n }\n optimisticPromises.push(\n mutator(key, mutatedData, {\n // don't trigger revalidation here since we will do it\n // when the remote mutation succeeds\n revalidate: false,\n })\n );\n }\n }\n\n return Promise.all(optimisticPromises);\n}\n"],"mappings":"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","names":["optimisticUpdate","fetch","useSWR","useSWRInfinite","model","operation","useSWRMutation"]}
|
package/runtime/index.mjs
CHANGED
|
@@ -102,16 +102,12 @@ function parseQueryKey(key) {
|
|
|
102
102
|
return (keyValue == null ? void 0 : keyValue.prefix) === QUERY_KEY_PREFIX ? keyValue : void 0;
|
|
103
103
|
}
|
|
104
104
|
function useModelQuery(model, operation, args, options) {
|
|
105
|
-
var _a;
|
|
106
105
|
const { endpoint, fetch: fetch2 } = useHooksContext();
|
|
107
106
|
const key = (options == null ? void 0 : options.disabled) ? null : getQueryKey(model, operation, args, false, (options == null ? void 0 : options.optimisticUpdate) !== false);
|
|
108
107
|
const url = makeUrl(`${endpoint}/${lowerCaseFirst(model)}/${operation}`, args);
|
|
109
|
-
return useSWR(key, () => fetcher(url, void 0, fetch2, false),
|
|
110
|
-
fallbackData: (_a = options == null ? void 0 : options.initialData) != null ? _a : options == null ? void 0 : options.fallbackData
|
|
111
|
-
}));
|
|
108
|
+
return useSWR(key, () => fetcher(url, void 0, fetch2, false), options);
|
|
112
109
|
}
|
|
113
110
|
function useInfiniteModelQuery(model, operation, getNextArgs, options) {
|
|
114
|
-
var _a;
|
|
115
111
|
const { endpoint, fetch: fetch2 } = useHooksContext();
|
|
116
112
|
const getKey = (pageIndex, previousPageData) => {
|
|
117
113
|
if (options == null ? void 0 : options.disabled) {
|
|
@@ -132,9 +128,7 @@ function useInfiniteModelQuery(model, operation, getNextArgs, options) {
|
|
|
132
128
|
throw new Error("Invalid query key: " + key);
|
|
133
129
|
}
|
|
134
130
|
},
|
|
135
|
-
|
|
136
|
-
fallbackData: (_a = options == null ? void 0 : options.initialData) != null ? _a : options == null ? void 0 : options.fallbackData
|
|
137
|
-
})
|
|
131
|
+
options
|
|
138
132
|
);
|
|
139
133
|
}
|
|
140
134
|
function useModelMutation(model, method, operation, modelMeta, options, checkReadBack) {
|
|
@@ -145,7 +139,7 @@ function useModelMutation(model, method, operation, modelMeta, options, checkRea
|
|
|
145
139
|
getMutationKey(model, operation),
|
|
146
140
|
(_key, { arg }) => {
|
|
147
141
|
if (options == null ? void 0 : options.optimisticUpdate) {
|
|
148
|
-
optimisticUpdate(model, operation, arg, modelMeta, cache, mutate, logging);
|
|
142
|
+
optimisticUpdate(model, operation, arg, options, modelMeta, cache, mutate, logging);
|
|
149
143
|
}
|
|
150
144
|
const url = `${endpoint}/${lowerCaseFirst(model)}/${operation}`;
|
|
151
145
|
return mutationRequest(method, url, arg, invalidate, fetch2, checkReadBack);
|
|
@@ -266,7 +260,7 @@ function getOperationFromUrl(url) {
|
|
|
266
260
|
return r;
|
|
267
261
|
}
|
|
268
262
|
}
|
|
269
|
-
function optimisticUpdate(mutationModel, mutationOp, mutationArgs, modelMeta, cache, mutator, logging = false) {
|
|
263
|
+
function optimisticUpdate(mutationModel, mutationOp, mutationArgs, options, modelMeta, cache, mutator, logging = false) {
|
|
270
264
|
return __async(this, null, function* () {
|
|
271
265
|
const optimisticPromises = [];
|
|
272
266
|
for (const key of cache.keys()) {
|
|
@@ -281,15 +275,36 @@ function optimisticUpdate(mutationModel, mutationOp, mutationArgs, modelMeta, ca
|
|
|
281
275
|
continue;
|
|
282
276
|
}
|
|
283
277
|
const cacheValue = cache.get(key);
|
|
284
|
-
if (
|
|
285
|
-
continue;
|
|
286
|
-
}
|
|
287
|
-
if (cacheValue.error) {
|
|
278
|
+
if (cacheValue == null ? void 0 : cacheValue.error) {
|
|
288
279
|
if (logging) {
|
|
289
280
|
console.warn(`Skipping optimistic update for ${key} due to error:`, cacheValue.error);
|
|
290
281
|
}
|
|
291
282
|
continue;
|
|
292
283
|
}
|
|
284
|
+
if (options == null ? void 0 : options.optimisticDataProvider) {
|
|
285
|
+
const providerResult = yield options.optimisticDataProvider({
|
|
286
|
+
queryModel: parsedKey.model,
|
|
287
|
+
queryOperation: parsedKey.operation,
|
|
288
|
+
queryArgs: parsedKey.args,
|
|
289
|
+
currentData: cacheValue == null ? void 0 : cacheValue.data,
|
|
290
|
+
mutationArgs
|
|
291
|
+
});
|
|
292
|
+
if ((providerResult == null ? void 0 : providerResult.kind) === "Skip") {
|
|
293
|
+
if (logging) {
|
|
294
|
+
console.log(`Skipping optimistic update for ${key} due to custom provider`);
|
|
295
|
+
}
|
|
296
|
+
continue;
|
|
297
|
+
} else if ((providerResult == null ? void 0 : providerResult.kind) === "Update") {
|
|
298
|
+
if (logging) {
|
|
299
|
+
console.log(`Optimistically updating query ${JSON.stringify(key)} due to provider`);
|
|
300
|
+
}
|
|
301
|
+
optimisticPromises.push(mutator(key, providerResult.data, { revalidate: false }));
|
|
302
|
+
continue;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
if (!cacheValue) {
|
|
306
|
+
continue;
|
|
307
|
+
}
|
|
293
308
|
const mutatedData = yield applyMutation(
|
|
294
309
|
parsedKey.model,
|
|
295
310
|
parsedKey.operation,
|
package/runtime/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/runtime/index.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { deserialize, serialize } from '@zenstackhq/runtime/browser';\nimport {\n applyMutation,\n getMutatedModels,\n getReadModels,\n type ModelMeta,\n type PrismaWriteActionType,\n} from '@zenstackhq/runtime/cross';\nimport * as crossFetch from 'cross-fetch';\nimport { lowerCaseFirst } from 'lower-case-first';\nimport { createContext, useContext } from 'react';\nimport type { Cache, Fetcher, SWRConfiguration, SWRResponse } from 'swr';\nimport useSWR, { useSWRConfig } from 'swr';\nimport { ScopedMutator } from 'swr/_internal';\nimport useSWRInfinite, {\n unstable_serialize,\n type SWRInfiniteConfiguration,\n type SWRInfiniteFetcher,\n type SWRInfiniteResponse,\n} from 'swr/infinite';\nimport useSWRMutation, { type SWRMutationConfiguration } from 'swr/mutation';\nexport * from './prisma-types';\n\n/**\n * Function signature for `fetch`.\n */\nexport type FetchFn = (url: string, options?: RequestInit) => Promise<Response>;\n\n/**\n * Context type for configuring react hooks.\n */\nexport type RequestHandlerContext = {\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\nconst DEFAULT_QUERY_ENDPOINT = '/api/model';\n\n/**\n * Context for configuring react hooks.\n */\nexport const RequestHandlerContext = createContext<RequestHandlerContext>({\n endpoint: DEFAULT_QUERY_ENDPOINT,\n fetch: undefined,\n});\n\n/**\n * Context provider.\n */\nexport const Provider = RequestHandlerContext.Provider;\n\n/**\n * Hooks context.\n */\nexport function useHooksContext() {\n const { endpoint, ...rest } = useContext(RequestHandlerContext);\n return { endpoint: endpoint ?? DEFAULT_QUERY_ENDPOINT, ...rest };\n}\n\n/**\n * Regular query options.\n */\nexport type QueryOptions<Result, Error = unknown> = {\n /**\n * Disable data fetching\n */\n disabled?: boolean;\n\n /**\n * @deprecated Use `fallbackData` instead\n *\n * Equivalent to @see SWRConfiguration.fallbackData\n */\n initialData?: Result;\n\n /**\n * Whether to enable automatic optimistic update. Defaults to `true`.\n */\n optimisticUpdate?: boolean;\n} & Omit<SWRConfiguration<Result, Error, Fetcher<Result>>, 'fetcher'>;\n\n/**\n * Infinite query options.\n */\nexport type InfiniteQueryOptions<Result, Error = unknown> = {\n /**\n * Disable data fetching\n */\n disabled?: boolean;\n\n /**\n * @deprecated Use `fallbackData` instead\n *\n * Equivalent to @see SWRInfiniteConfiguration.fallbackData\n */\n initialData?: Result[];\n} & Omit<SWRInfiniteConfiguration<Result, Error, SWRInfiniteFetcher<Result>>, 'fetcher'>;\n\nconst QUERY_KEY_PREFIX = 'zenstack:query';\nconst MUTATION_KEY_PREFIX = 'zenstack:mutation';\n\ntype QueryKey = {\n prefix: typeof QUERY_KEY_PREFIX;\n model: string;\n operation: string;\n args?: unknown;\n infinite?: boolean;\n optimisticUpdate?: boolean;\n};\n\n/**\n * Mutation options.\n */\nexport type MutationOptions<Result, Error, Args> = {\n /**\n * Whether to automatically optimistic-update queries potentially impacted. Defaults to `false`.\n */\n optimisticUpdate?: boolean;\n} & Omit<SWRMutationConfiguration<Result, Error, string, Args>, 'fetcher'>;\n\n/**\n * Computes query key for the given model, operation, query args, and options.\n */\nexport function getQueryKey(\n model: string,\n operation: string,\n args?: unknown,\n infinite?: boolean,\n optimisticUpdate?: boolean\n) {\n return JSON.stringify({\n prefix: QUERY_KEY_PREFIX,\n model,\n operation,\n args,\n infinite: infinite === true,\n optimisticUpdate: optimisticUpdate !== false,\n });\n}\n\nfunction getMutationKey(model: string, operation: string) {\n // use a random key since we don't have 1:1 mapping between mutation and query\n // https://github.com/vercel/swr/discussions/2461#discussioncomment-5281784\n return JSON.stringify({ prefix: MUTATION_KEY_PREFIX, model, operation, r: Date.now() });\n}\n\nfunction parseQueryKey(key: unknown): QueryKey | undefined {\n let keyValue: any = key;\n if (typeof key === 'string') {\n try {\n keyValue = JSON.parse(key);\n } catch {\n return undefined;\n }\n }\n return keyValue?.prefix === QUERY_KEY_PREFIX ? (keyValue as QueryKey) : undefined;\n}\n\n/**\n * Makes a model query with SWR.\n *\n * @param model Model name\n * @param operation Prisma operation (e.g, `findMany`)\n * @param args The request args object, which will be superjson-stringified and appended as \"?q=\" parameter\n * @param options Query options\n * @returns SWR response\n */\nexport function useModelQuery<Result, Error = unknown>(\n model: string,\n operation: string,\n args?: unknown,\n options?: QueryOptions<Result, Error>\n): SWRResponse<Result, Error> {\n const { endpoint, fetch } = useHooksContext();\n const key = options?.disabled\n ? null\n : getQueryKey(model, operation, args, false, options?.optimisticUpdate !== false);\n const url = makeUrl(`${endpoint}/${lowerCaseFirst(model)}/${operation}`, args);\n return useSWR<Result, Error>(key, () => fetcher<Result, false>(url, undefined, fetch, false), {\n ...options,\n fallbackData: options?.initialData ?? options?.fallbackData,\n });\n}\n\n/**\n * Function for computing the query args for fetching a page during an infinite query.\n */\nexport type GetNextArgs<Args, Result> = (pageIndex: number, previousPageData: Result | null) => Args | null;\n\n/**\n * Makes an infinite GET request with SWR.\n *\n * @param model Model name\n * @param operation Prisma operation (e.g, `findMany`)\n * @param getNextArgs Function for computing the query args for a page\n * @param options Query options\n * @returns SWR infinite query response\n */\nexport function useInfiniteModelQuery<Args, Result, Error = unknown>(\n model: string,\n operation: string,\n getNextArgs: GetNextArgs<Args, any>,\n options?: InfiniteQueryOptions<Result, Error>\n): SWRInfiniteResponse<Result, Error> {\n const { endpoint, fetch } = useHooksContext();\n\n const getKey = (pageIndex: number, previousPageData: Result | null) => {\n if (options?.disabled) {\n return null;\n }\n const nextArgs = getNextArgs(pageIndex, previousPageData);\n return nextArgs !== null // null means reached the end\n ? getQueryKey(model, operation, nextArgs, true, false)\n : null;\n };\n\n return useSWRInfinite<Result, Error>(\n getKey,\n (key: unknown) => {\n const parsedKey = parseQueryKey(key);\n if (parsedKey) {\n const { model, operation, args } = parsedKey;\n const url = makeUrl(`${endpoint}/${lowerCaseFirst(model)}/${operation}`, args);\n return fetcher<Result, false>(url, undefined, fetch, false);\n } else {\n throw new Error('Invalid query key: ' + key);\n }\n },\n {\n ...options,\n fallbackData: options?.initialData ?? options?.fallbackData,\n }\n );\n}\n\nexport function useModelMutation<Args, Result, CheckReadBack extends boolean = boolean>(\n model: string,\n method: 'POST' | 'PUT' | 'DELETE',\n operation: string,\n modelMeta: ModelMeta,\n options?: MutationOptions<CheckReadBack extends true ? Result | undefined : Result, unknown, Args>,\n checkReadBack?: CheckReadBack\n) {\n const { endpoint, fetch, logging } = useHooksContext();\n const invalidate = options?.revalidate !== false ? useInvalidation(model, modelMeta) : undefined;\n const { cache, mutate } = useSWRConfig();\n\n return useSWRMutation(\n getMutationKey(model, operation),\n (_key, { arg }: { arg: any }) => {\n if (options?.optimisticUpdate) {\n optimisticUpdate(model, operation, arg, modelMeta, cache, mutate, logging);\n }\n const url = `${endpoint}/${lowerCaseFirst(model)}/${operation}`;\n return mutationRequest(method, url, arg, invalidate, fetch, checkReadBack);\n },\n options\n );\n}\n\n/**\n * Makes a mutation request.\n *\n * @param url The request URL\n * @param data The request data\n * @param invalidate Function for invalidating a query\n */\nexport async function mutationRequest<Result, C extends boolean = boolean>(\n method: 'POST' | 'PUT' | 'DELETE',\n url: string,\n data: unknown,\n invalidate?: Invalidator,\n fetch?: FetchFn,\n checkReadBack?: C\n): Promise<C extends true ? Result | undefined : Result> {\n const reqUrl = method === 'DELETE' ? makeUrl(url, data) : url;\n const r = await fetcher<Result, C>(\n reqUrl,\n {\n method,\n headers: {\n 'content-type': 'application/json',\n },\n body: data ? marshal(data) : undefined,\n },\n fetch,\n checkReadBack\n );\n\n if (invalidate) {\n await invalidate(getOperationFromUrl(url), data);\n }\n return r;\n}\n\n// function for invalidating queries related to mutation represented by its operation and args\ntype Invalidator = (operation: string, args?: unknown) => ReturnType<ScopedMutator>;\n\nexport function useInvalidation(model: string, modelMeta: ModelMeta): Invalidator {\n // https://swr.vercel.app/docs/advanced/cache#mutate-multiple-keys-from-regex\n const { logging } = useHooksContext();\n const { cache, mutate } = useSWRConfig();\n return async (operation: string, args: unknown) => {\n if (!(cache instanceof Map)) {\n throw new Error('mutate requires the cache provider to be a Map instance');\n }\n\n const mutatedModels = await getMutatedModels(model, operation as PrismaWriteActionType, args, modelMeta);\n\n const keys = Array.from(cache.keys()).filter((key: unknown) => {\n const parsedKey = parseQueryKey(key);\n if (!parsedKey) {\n return false;\n }\n const modelsRead = getReadModels(parsedKey.model, modelMeta, parsedKey.args);\n return modelsRead.some((m) => mutatedModels.includes(m));\n });\n\n if (logging) {\n keys.forEach((key) => {\n console.log(`Invalidating query ${key} due to mutation \"${model}.${operation}\"`);\n });\n }\n\n const mutations = keys.map((key) => {\n const parsedKey = parseQueryKey(key);\n // FIX: special handling for infinite query keys, but still not working\n // https://github.com/vercel/swr/discussions/2843\n return mutate(parsedKey?.infinite ? unstable_serialize(() => key) : key);\n });\n return Promise.all(mutations);\n };\n}\n\n/**\n * Makes fetch request for queries and mutations.\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\nfunction 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\nfunction 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\nfunction 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\nfunction getOperationFromUrl(url: string) {\n const parts = url.split('/');\n const r = parts.pop();\n if (!r) {\n throw new Error(`Invalid URL: ${url}`);\n } else {\n return r;\n }\n}\n\nasync function optimisticUpdate(\n mutationModel: string,\n mutationOp: string,\n mutationArgs: any,\n modelMeta: ModelMeta,\n cache: Cache,\n mutator: ScopedMutator,\n logging = false\n) {\n const optimisticPromises: Array<Promise<void>> = [];\n for (const key of cache.keys()) {\n const parsedKey = parseQueryKey(key);\n if (!parsedKey) {\n continue;\n }\n\n if (!parsedKey.optimisticUpdate) {\n if (logging) {\n console.log(`Skipping optimistic update for ${key} due to opt-out`);\n }\n continue;\n }\n\n const cacheValue = cache.get(key);\n if (!cacheValue) {\n continue;\n }\n\n if (cacheValue.error) {\n if (logging) {\n console.warn(`Skipping optimistic update for ${key} due to error:`, cacheValue.error);\n }\n continue;\n }\n\n const mutatedData = await applyMutation(\n parsedKey.model,\n parsedKey.operation,\n cacheValue.data,\n mutationModel,\n mutationOp as PrismaWriteActionType,\n mutationArgs,\n modelMeta,\n logging\n );\n\n if (mutatedData !== undefined) {\n // mutation applicable to this query, update cache\n if (logging) {\n console.log(\n `Optimistically updating query ${JSON.stringify(\n key\n )} due to mutation \"${mutationModel}.${mutationOp}\"`\n );\n }\n optimisticPromises.push(\n mutator(key, mutatedData, {\n // don't trigger revalidation here since we will do it\n // when the remote mutation succeeds\n revalidate: false,\n })\n );\n }\n }\n\n return Promise.all(optimisticPromises);\n}\n"],"mappings":"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","names":["optimisticUpdate","fetch","model","operation"]}
|
|
1
|
+
{"version":3,"sources":["../../src/runtime/index.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { deserialize, serialize } from '@zenstackhq/runtime/browser';\nimport {\n applyMutation,\n getMutatedModels,\n getReadModels,\n type ModelMeta,\n type PrismaWriteActionType,\n} from '@zenstackhq/runtime/cross';\nimport * as crossFetch from 'cross-fetch';\nimport { lowerCaseFirst } from 'lower-case-first';\nimport { createContext, useContext } from 'react';\nimport type { Cache, Fetcher, SWRConfiguration, SWRResponse } from 'swr';\nimport useSWR, { useSWRConfig } from 'swr';\nimport { ScopedMutator } from 'swr/_internal';\nimport useSWRInfinite, {\n unstable_serialize,\n type SWRInfiniteConfiguration,\n type SWRInfiniteFetcher,\n type SWRInfiniteResponse,\n} from 'swr/infinite';\nimport useSWRMutation, { type SWRMutationConfiguration } from 'swr/mutation';\nexport * from './prisma-types';\n\n/**\n * Function signature for `fetch`.\n */\nexport type FetchFn = (url: string, options?: RequestInit) => Promise<Response>;\n\n/**\n * Context type for configuring react hooks.\n */\nexport type RequestHandlerContext = {\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\nconst DEFAULT_QUERY_ENDPOINT = '/api/model';\n\n/**\n * Context for configuring react hooks.\n */\nexport const RequestHandlerContext = createContext<RequestHandlerContext>({\n endpoint: DEFAULT_QUERY_ENDPOINT,\n fetch: undefined,\n});\n\n/**\n * Context provider.\n */\nexport const Provider = RequestHandlerContext.Provider;\n\n/**\n * Hooks context.\n */\nexport function useHooksContext() {\n const { endpoint, ...rest } = useContext(RequestHandlerContext);\n return { endpoint: endpoint ?? DEFAULT_QUERY_ENDPOINT, ...rest };\n}\n\n/**\n * Regular query options.\n */\nexport type QueryOptions<Result, Error = unknown> = {\n /**\n * Disable data fetching\n */\n disabled?: boolean;\n\n /**\n * Whether to enable automatic optimistic update. Defaults to `true`.\n */\n optimisticUpdate?: boolean;\n} & Omit<SWRConfiguration<Result, Error, Fetcher<Result>>, 'fetcher'>;\n\n/**\n * Infinite query options.\n */\nexport type InfiniteQueryOptions<Result, Error = unknown> = {\n /**\n * Disable data fetching\n */\n disabled?: boolean;\n} & Omit<SWRInfiniteConfiguration<Result, Error, SWRInfiniteFetcher<Result>>, 'fetcher'>;\n\nconst QUERY_KEY_PREFIX = 'zenstack:query';\nconst MUTATION_KEY_PREFIX = 'zenstack:mutation';\n\ntype QueryKey = {\n prefix: typeof QUERY_KEY_PREFIX;\n model: string;\n operation: string;\n args?: unknown;\n infinite?: boolean;\n optimisticUpdate?: boolean;\n};\n\n/**\n * Result of optimistic data provider.\n */\nexport type OptimisticDataProviderResult = {\n /**\n * Kind of the result.\n * - Update: use the `data` field to update the query cache.\n * - Skip: skip the optimistic update for this query.\n * - ProceedDefault: proceed with the default optimistic update.\n */\n kind: 'Update' | 'Skip' | 'ProceedDefault';\n\n /**\n * Data to update the query cache. Only applicable if `kind` is 'Update'.\n *\n * If the data is an object with fields updated, it should have a `$optimistic`\n * field set to `true`. If it's an array and an element object is created or updated,\n * the element should have a `$optimistic` field set to `true`.\n */\n data?: any;\n};\n\n/**\n * Optimistic data provider.\n *\n * @param args Arguments.\n * @param args.queryModel The model of the query.\n * @param args.queryOperation The operation of the query, `findMany`, `count`, etc.\n * @param args.queryArgs The arguments of the query.\n * @param args.currentData The current cache data for the query.\n * @param args.mutationArgs The arguments of the mutation.\n */\nexport type OptimisticDataProvider = (args: {\n queryModel: string;\n queryOperation: string;\n queryArgs: any;\n currentData: any;\n mutationArgs: any;\n}) => OptimisticDataProviderResult | Promise<OptimisticDataProviderResult>;\n\n/**\n * Mutation options.\n */\nexport type MutationOptions<Result, Error, Args> = {\n /**\n * Whether to automatically optimistic-update queries potentially impacted. Defaults to `false`.\n */\n optimisticUpdate?: boolean;\n\n /**\n * A callback for computing optimistic update data for each query cache entry.\n */\n optimisticDataProvider?: OptimisticDataProvider;\n} & Omit<SWRMutationConfiguration<Result, Error, string, Args>, 'fetcher'>;\n\n/**\n * Computes query key for the given model, operation, query args, and options.\n */\nexport function getQueryKey(\n model: string,\n operation: string,\n args?: unknown,\n infinite?: boolean,\n optimisticUpdate?: boolean\n) {\n return JSON.stringify({\n prefix: QUERY_KEY_PREFIX,\n model,\n operation,\n args,\n infinite: infinite === true,\n optimisticUpdate: optimisticUpdate !== false,\n });\n}\n\nfunction getMutationKey(model: string, operation: string) {\n // use a random key since we don't have 1:1 mapping between mutation and query\n // https://github.com/vercel/swr/discussions/2461#discussioncomment-5281784\n return JSON.stringify({ prefix: MUTATION_KEY_PREFIX, model, operation, r: Date.now() });\n}\n\nfunction parseQueryKey(key: unknown): QueryKey | undefined {\n let keyValue: any = key;\n if (typeof key === 'string') {\n try {\n keyValue = JSON.parse(key);\n } catch {\n return undefined;\n }\n }\n return keyValue?.prefix === QUERY_KEY_PREFIX ? (keyValue as QueryKey) : undefined;\n}\n\n/**\n * Makes a model query with SWR.\n *\n * @param model Model name\n * @param operation Prisma operation (e.g, `findMany`)\n * @param args The request args object, which will be superjson-stringified and appended as \"?q=\" parameter\n * @param options Query options\n * @returns SWR response\n */\nexport function useModelQuery<Result, Error = unknown>(\n model: string,\n operation: string,\n args?: unknown,\n options?: QueryOptions<Result, Error>\n): SWRResponse<Result, Error> {\n const { endpoint, fetch } = useHooksContext();\n const key = options?.disabled\n ? null\n : getQueryKey(model, operation, args, false, options?.optimisticUpdate !== false);\n const url = makeUrl(`${endpoint}/${lowerCaseFirst(model)}/${operation}`, args);\n return useSWR<Result, Error>(key, () => fetcher<Result, false>(url, undefined, fetch, false), options);\n}\n\n/**\n * Function for computing the query args for fetching a page during an infinite query.\n */\nexport type GetNextArgs<Args, Result> = (pageIndex: number, previousPageData: Result | null) => Args | null;\n\n/**\n * Makes an infinite GET request with SWR.\n *\n * @param model Model name\n * @param operation Prisma operation (e.g, `findMany`)\n * @param getNextArgs Function for computing the query args for a page\n * @param options Query options\n * @returns SWR infinite query response\n */\nexport function useInfiniteModelQuery<Args, Result, Error = unknown>(\n model: string,\n operation: string,\n getNextArgs: GetNextArgs<Args, any>,\n options?: InfiniteQueryOptions<Result, Error>\n): SWRInfiniteResponse<Result, Error> {\n const { endpoint, fetch } = useHooksContext();\n\n const getKey = (pageIndex: number, previousPageData: Result | null) => {\n if (options?.disabled) {\n return null;\n }\n const nextArgs = getNextArgs(pageIndex, previousPageData);\n return nextArgs !== null // null means reached the end\n ? getQueryKey(model, operation, nextArgs, true, false)\n : null;\n };\n\n return useSWRInfinite<Result, Error>(\n getKey,\n (key: unknown) => {\n const parsedKey = parseQueryKey(key);\n if (parsedKey) {\n const { model, operation, args } = parsedKey;\n const url = makeUrl(`${endpoint}/${lowerCaseFirst(model)}/${operation}`, args);\n return fetcher<Result, false>(url, undefined, fetch, false);\n } else {\n throw new Error('Invalid query key: ' + key);\n }\n },\n options\n );\n}\n\nexport function useModelMutation<Args, Result, CheckReadBack extends boolean = boolean>(\n model: string,\n method: 'POST' | 'PUT' | 'DELETE',\n operation: string,\n modelMeta: ModelMeta,\n options?: MutationOptions<CheckReadBack extends true ? Result | undefined : Result, unknown, Args>,\n checkReadBack?: CheckReadBack\n) {\n const { endpoint, fetch, logging } = useHooksContext();\n const invalidate = options?.revalidate !== false ? useInvalidation(model, modelMeta) : undefined;\n const { cache, mutate } = useSWRConfig();\n\n return useSWRMutation(\n getMutationKey(model, operation),\n (_key, { arg }: { arg: any }) => {\n if (options?.optimisticUpdate) {\n optimisticUpdate(model, operation, arg, options, modelMeta, cache, mutate, logging);\n }\n const url = `${endpoint}/${lowerCaseFirst(model)}/${operation}`;\n return mutationRequest(method, url, arg, invalidate, fetch, checkReadBack);\n },\n options\n );\n}\n\n/**\n * Makes a mutation request.\n *\n * @param url The request URL\n * @param data The request data\n * @param invalidate Function for invalidating a query\n */\nexport async function mutationRequest<Result, C extends boolean = boolean>(\n method: 'POST' | 'PUT' | 'DELETE',\n url: string,\n data: unknown,\n invalidate?: Invalidator,\n fetch?: FetchFn,\n checkReadBack?: C\n): Promise<C extends true ? Result | undefined : Result> {\n const reqUrl = method === 'DELETE' ? makeUrl(url, data) : url;\n const r = await fetcher<Result, C>(\n reqUrl,\n {\n method,\n headers: {\n 'content-type': 'application/json',\n },\n body: data ? marshal(data) : undefined,\n },\n fetch,\n checkReadBack\n );\n\n if (invalidate) {\n await invalidate(getOperationFromUrl(url), data);\n }\n return r;\n}\n\n// function for invalidating queries related to mutation represented by its operation and args\ntype Invalidator = (operation: string, args?: unknown) => ReturnType<ScopedMutator>;\n\nexport function useInvalidation(model: string, modelMeta: ModelMeta): Invalidator {\n // https://swr.vercel.app/docs/advanced/cache#mutate-multiple-keys-from-regex\n const { logging } = useHooksContext();\n const { cache, mutate } = useSWRConfig();\n return async (operation: string, args: unknown) => {\n if (!(cache instanceof Map)) {\n throw new Error('mutate requires the cache provider to be a Map instance');\n }\n\n const mutatedModels = await getMutatedModels(model, operation as PrismaWriteActionType, args, modelMeta);\n\n const keys = Array.from(cache.keys()).filter((key: unknown) => {\n const parsedKey = parseQueryKey(key);\n if (!parsedKey) {\n return false;\n }\n const modelsRead = getReadModels(parsedKey.model, modelMeta, parsedKey.args);\n return modelsRead.some((m) => mutatedModels.includes(m));\n });\n\n if (logging) {\n keys.forEach((key) => {\n console.log(`Invalidating query ${key} due to mutation \"${model}.${operation}\"`);\n });\n }\n\n const mutations = keys.map((key) => {\n const parsedKey = parseQueryKey(key);\n // FIX: special handling for infinite query keys, but still not working\n // https://github.com/vercel/swr/discussions/2843\n return mutate(parsedKey?.infinite ? unstable_serialize(() => key) : key);\n });\n return Promise.all(mutations);\n };\n}\n\n/**\n * Makes fetch request for queries and mutations.\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\nfunction 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\nfunction 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\nfunction 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\nfunction getOperationFromUrl(url: string) {\n const parts = url.split('/');\n const r = parts.pop();\n if (!r) {\n throw new Error(`Invalid URL: ${url}`);\n } else {\n return r;\n }\n}\n\nasync function optimisticUpdate(\n mutationModel: string,\n mutationOp: string,\n mutationArgs: any,\n options: MutationOptions<any, any, any> | undefined,\n modelMeta: ModelMeta,\n cache: Cache,\n mutator: ScopedMutator,\n logging = false\n) {\n const optimisticPromises: Array<Promise<void>> = [];\n for (const key of cache.keys()) {\n const parsedKey = parseQueryKey(key);\n if (!parsedKey) {\n continue;\n }\n\n if (!parsedKey.optimisticUpdate) {\n if (logging) {\n console.log(`Skipping optimistic update for ${key} due to opt-out`);\n }\n continue;\n }\n\n const cacheValue = cache.get(key);\n if (cacheValue?.error) {\n if (logging) {\n console.warn(`Skipping optimistic update for ${key} due to error:`, cacheValue.error);\n }\n continue;\n }\n\n if (options?.optimisticDataProvider) {\n const providerResult = await options.optimisticDataProvider({\n queryModel: parsedKey.model,\n queryOperation: parsedKey.operation,\n queryArgs: parsedKey.args,\n currentData: cacheValue?.data,\n mutationArgs,\n });\n\n if (providerResult?.kind === 'Skip') {\n if (logging) {\n console.log(`Skipping optimistic update for ${key} due to custom provider`);\n }\n continue;\n } else if (providerResult?.kind === 'Update') {\n if (logging) {\n console.log(`Optimistically updating query ${JSON.stringify(key)} due to provider`);\n }\n optimisticPromises.push(mutator(key, providerResult.data, { revalidate: false }));\n continue;\n }\n }\n\n if (!cacheValue) {\n continue;\n }\n\n const mutatedData = await applyMutation(\n parsedKey.model,\n parsedKey.operation,\n cacheValue.data,\n mutationModel,\n mutationOp as PrismaWriteActionType,\n mutationArgs,\n modelMeta,\n logging\n );\n\n if (mutatedData !== undefined) {\n // mutation applicable to this query, update cache\n if (logging) {\n console.log(\n `Optimistically updating query ${JSON.stringify(\n key\n )} due to mutation \"${mutationModel}.${mutationOp}\"`\n );\n }\n optimisticPromises.push(\n mutator(key, mutatedData, {\n // don't trigger revalidation here since we will do it\n // when the remote mutation succeeds\n revalidate: false,\n })\n );\n }\n }\n\n return Promise.all(optimisticPromises);\n}\n"],"mappings":"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","names":["optimisticUpdate","fetch","model","operation"]}
|