@zenstackhq/runtime 1.2.1 → 1.3.0
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/cross/index.d.mts +40 -8
- package/cross/index.d.ts +40 -8
- package/cross/index.js +236 -2
- package/cross/index.js.map +1 -1
- package/cross/index.mjs +223 -2
- package/cross/index.mjs.map +1 -1
- package/enhancements/omit.js +2 -1
- package/enhancements/omit.js.map +1 -1
- package/enhancements/policy/handler.js +2 -3
- package/enhancements/policy/handler.js.map +1 -1
- package/enhancements/policy/index.d.ts +1 -1
- package/enhancements/policy/index.js +13 -3
- package/enhancements/policy/index.js.map +1 -1
- package/enhancements/policy/policy-utils.js +19 -3
- package/enhancements/policy/policy-utils.js.map +1 -1
- package/enhancements/types.d.ts +1 -0
- package/enhancements/utils.d.ts +0 -5
- package/enhancements/utils.js +1 -22
- package/enhancements/utils.js.map +1 -1
- package/package.json +4 -2
- package/enhancements/model-data-visitor.d.ts +0 -16
- package/enhancements/model-data-visitor.js +0 -41
- package/enhancements/model-data-visitor.js.map +0 -1
package/cross/index.d.mts
CHANGED
|
@@ -1,3 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Callback for @see ModelDataVisitor.
|
|
3
|
+
*/
|
|
4
|
+
type ModelDataVisitorCallback = (model: string, data: any, scalarData: any) => void;
|
|
5
|
+
/**
|
|
6
|
+
* Visitor that traverses data returned by a Prisma query.
|
|
7
|
+
*/
|
|
8
|
+
declare class ModelDataVisitor {
|
|
9
|
+
private modelMeta;
|
|
10
|
+
constructor(modelMeta: ModelMeta);
|
|
11
|
+
/**
|
|
12
|
+
* Visits the given model data.
|
|
13
|
+
*/
|
|
14
|
+
visit(model: string, data: any, callback: ModelDataVisitorCallback): void;
|
|
15
|
+
}
|
|
16
|
+
|
|
1
17
|
/**
|
|
2
18
|
* Runtime information of a data model or field attribute
|
|
3
19
|
*/
|
|
@@ -23,23 +39,23 @@ type FieldInfo = {
|
|
|
23
39
|
/**
|
|
24
40
|
* If the field is an ID field or part of a multi-field ID
|
|
25
41
|
*/
|
|
26
|
-
isId
|
|
42
|
+
isId?: boolean;
|
|
27
43
|
/**
|
|
28
44
|
* If the field type is a data model (or an optional/array of data model)
|
|
29
45
|
*/
|
|
30
|
-
isDataModel
|
|
46
|
+
isDataModel?: boolean;
|
|
31
47
|
/**
|
|
32
48
|
* If the field is an array
|
|
33
49
|
*/
|
|
34
|
-
isArray
|
|
50
|
+
isArray?: boolean;
|
|
35
51
|
/**
|
|
36
52
|
* If the field is optional
|
|
37
53
|
*/
|
|
38
|
-
isOptional
|
|
54
|
+
isOptional?: boolean;
|
|
39
55
|
/**
|
|
40
56
|
* Attributes on the field
|
|
41
57
|
*/
|
|
42
|
-
attributes
|
|
58
|
+
attributes?: RuntimeAttribute[];
|
|
43
59
|
/**
|
|
44
60
|
* If the field is a relation field, the field name of the reverse side of the relation
|
|
45
61
|
*/
|
|
@@ -47,11 +63,11 @@ type FieldInfo = {
|
|
|
47
63
|
/**
|
|
48
64
|
* If the field is the owner side of a relation
|
|
49
65
|
*/
|
|
50
|
-
isRelationOwner
|
|
66
|
+
isRelationOwner?: boolean;
|
|
51
67
|
/**
|
|
52
68
|
* If the field is a foreign key field
|
|
53
69
|
*/
|
|
54
|
-
isForeignKey
|
|
70
|
+
isForeignKey?: boolean;
|
|
55
71
|
/**
|
|
56
72
|
* Mapping from foreign key field names to relation field names
|
|
57
73
|
*/
|
|
@@ -95,6 +111,21 @@ declare function resolveField(modelMeta: ModelMeta, model: string, field: string
|
|
|
95
111
|
*/
|
|
96
112
|
declare function getFields(modelMeta: ModelMeta, model: string): Record<string, FieldInfo>;
|
|
97
113
|
|
|
114
|
+
/**
|
|
115
|
+
* Tries to apply a mutation to a query result.
|
|
116
|
+
*
|
|
117
|
+
* @param queryModel the model of the query
|
|
118
|
+
* @param queryOp the operation of the query
|
|
119
|
+
* @param queryData the result data of the query
|
|
120
|
+
* @param mutationModel the model of the mutation
|
|
121
|
+
* @param mutationOp the operation of the mutation
|
|
122
|
+
* @param mutationArgs the arguments of the mutation
|
|
123
|
+
* @param modelMeta the model metadata
|
|
124
|
+
* @param logging whether to log the mutation application
|
|
125
|
+
* @returns the updated query data if the mutation is applicable, otherwise undefined
|
|
126
|
+
*/
|
|
127
|
+
declare function applyMutation(queryModel: string, queryOp: string, queryData: any, mutationModel: string, mutationOp: PrismaWriteActionType, mutationArgs: any, modelMeta: ModelMeta, logging: boolean): Promise<any>;
|
|
128
|
+
|
|
98
129
|
type NestedReadVisitorCallback = {
|
|
99
130
|
field?: (model: string, field: FieldInfo | undefined, kind: 'include' | 'select' | undefined, args: unknown) => void | boolean;
|
|
100
131
|
};
|
|
@@ -225,5 +256,6 @@ declare function enumerate<T>(x: Enumerable<T>): T[];
|
|
|
225
256
|
* Zip two arrays or scalars.
|
|
226
257
|
*/
|
|
227
258
|
declare function zip<T1, T2>(x: Enumerable<T1>, y: Enumerable<T2>): Array<[T1, T2]>;
|
|
259
|
+
declare function getIdFields(modelMeta: ModelMeta, model: string, throwIfNotFound?: boolean): FieldInfo[];
|
|
228
260
|
|
|
229
|
-
export { Enumerable, FieldInfo, MaybePromise, ModelMeta, NestedReadVisitor, NestedReadVisitorCallback, NestedWriteVisitor, NestedWriteVisitorContext, NestedWriterVisitorCallback, PrismaWriteActionType, PrismaWriteActions, RuntimeAttribute, UniqueConstraint, enumerate, getFields, getModelFields, getMutatedModels, getReadModels, resolveField, zip };
|
|
261
|
+
export { Enumerable, FieldInfo, MaybePromise, ModelDataVisitor, ModelDataVisitorCallback, ModelMeta, NestedReadVisitor, NestedReadVisitorCallback, NestedWriteVisitor, NestedWriteVisitorContext, NestedWriterVisitorCallback, PrismaWriteActionType, PrismaWriteActions, RuntimeAttribute, UniqueConstraint, applyMutation, enumerate, getFields, getIdFields, getModelFields, getMutatedModels, getReadModels, resolveField, zip };
|
package/cross/index.d.ts
CHANGED
|
@@ -1,3 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Callback for @see ModelDataVisitor.
|
|
3
|
+
*/
|
|
4
|
+
type ModelDataVisitorCallback = (model: string, data: any, scalarData: any) => void;
|
|
5
|
+
/**
|
|
6
|
+
* Visitor that traverses data returned by a Prisma query.
|
|
7
|
+
*/
|
|
8
|
+
declare class ModelDataVisitor {
|
|
9
|
+
private modelMeta;
|
|
10
|
+
constructor(modelMeta: ModelMeta);
|
|
11
|
+
/**
|
|
12
|
+
* Visits the given model data.
|
|
13
|
+
*/
|
|
14
|
+
visit(model: string, data: any, callback: ModelDataVisitorCallback): void;
|
|
15
|
+
}
|
|
16
|
+
|
|
1
17
|
/**
|
|
2
18
|
* Runtime information of a data model or field attribute
|
|
3
19
|
*/
|
|
@@ -23,23 +39,23 @@ type FieldInfo = {
|
|
|
23
39
|
/**
|
|
24
40
|
* If the field is an ID field or part of a multi-field ID
|
|
25
41
|
*/
|
|
26
|
-
isId
|
|
42
|
+
isId?: boolean;
|
|
27
43
|
/**
|
|
28
44
|
* If the field type is a data model (or an optional/array of data model)
|
|
29
45
|
*/
|
|
30
|
-
isDataModel
|
|
46
|
+
isDataModel?: boolean;
|
|
31
47
|
/**
|
|
32
48
|
* If the field is an array
|
|
33
49
|
*/
|
|
34
|
-
isArray
|
|
50
|
+
isArray?: boolean;
|
|
35
51
|
/**
|
|
36
52
|
* If the field is optional
|
|
37
53
|
*/
|
|
38
|
-
isOptional
|
|
54
|
+
isOptional?: boolean;
|
|
39
55
|
/**
|
|
40
56
|
* Attributes on the field
|
|
41
57
|
*/
|
|
42
|
-
attributes
|
|
58
|
+
attributes?: RuntimeAttribute[];
|
|
43
59
|
/**
|
|
44
60
|
* If the field is a relation field, the field name of the reverse side of the relation
|
|
45
61
|
*/
|
|
@@ -47,11 +63,11 @@ type FieldInfo = {
|
|
|
47
63
|
/**
|
|
48
64
|
* If the field is the owner side of a relation
|
|
49
65
|
*/
|
|
50
|
-
isRelationOwner
|
|
66
|
+
isRelationOwner?: boolean;
|
|
51
67
|
/**
|
|
52
68
|
* If the field is a foreign key field
|
|
53
69
|
*/
|
|
54
|
-
isForeignKey
|
|
70
|
+
isForeignKey?: boolean;
|
|
55
71
|
/**
|
|
56
72
|
* Mapping from foreign key field names to relation field names
|
|
57
73
|
*/
|
|
@@ -95,6 +111,21 @@ declare function resolveField(modelMeta: ModelMeta, model: string, field: string
|
|
|
95
111
|
*/
|
|
96
112
|
declare function getFields(modelMeta: ModelMeta, model: string): Record<string, FieldInfo>;
|
|
97
113
|
|
|
114
|
+
/**
|
|
115
|
+
* Tries to apply a mutation to a query result.
|
|
116
|
+
*
|
|
117
|
+
* @param queryModel the model of the query
|
|
118
|
+
* @param queryOp the operation of the query
|
|
119
|
+
* @param queryData the result data of the query
|
|
120
|
+
* @param mutationModel the model of the mutation
|
|
121
|
+
* @param mutationOp the operation of the mutation
|
|
122
|
+
* @param mutationArgs the arguments of the mutation
|
|
123
|
+
* @param modelMeta the model metadata
|
|
124
|
+
* @param logging whether to log the mutation application
|
|
125
|
+
* @returns the updated query data if the mutation is applicable, otherwise undefined
|
|
126
|
+
*/
|
|
127
|
+
declare function applyMutation(queryModel: string, queryOp: string, queryData: any, mutationModel: string, mutationOp: PrismaWriteActionType, mutationArgs: any, modelMeta: ModelMeta, logging: boolean): Promise<any>;
|
|
128
|
+
|
|
98
129
|
type NestedReadVisitorCallback = {
|
|
99
130
|
field?: (model: string, field: FieldInfo | undefined, kind: 'include' | 'select' | undefined, args: unknown) => void | boolean;
|
|
100
131
|
};
|
|
@@ -225,5 +256,6 @@ declare function enumerate<T>(x: Enumerable<T>): T[];
|
|
|
225
256
|
* Zip two arrays or scalars.
|
|
226
257
|
*/
|
|
227
258
|
declare function zip<T1, T2>(x: Enumerable<T1>, y: Enumerable<T2>): Array<[T1, T2]>;
|
|
259
|
+
declare function getIdFields(modelMeta: ModelMeta, model: string, throwIfNotFound?: boolean): FieldInfo[];
|
|
228
260
|
|
|
229
|
-
export { Enumerable, FieldInfo, MaybePromise, ModelMeta, NestedReadVisitor, NestedReadVisitorCallback, NestedWriteVisitor, NestedWriteVisitorContext, NestedWriterVisitorCallback, PrismaWriteActionType, PrismaWriteActions, RuntimeAttribute, UniqueConstraint, enumerate, getFields, getModelFields, getMutatedModels, getReadModels, resolveField, zip };
|
|
261
|
+
export { Enumerable, FieldInfo, MaybePromise, ModelDataVisitor, ModelDataVisitorCallback, ModelMeta, NestedReadVisitor, NestedReadVisitorCallback, NestedWriteVisitor, NestedWriteVisitorContext, NestedWriterVisitorCallback, PrismaWriteActionType, PrismaWriteActions, RuntimeAttribute, UniqueConstraint, applyMutation, enumerate, getFields, getIdFields, getModelFields, getMutatedModels, getReadModels, resolveField, zip };
|
package/cross/index.js
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
2
3
|
var __defProp = Object.defineProperty;
|
|
3
4
|
var __defProps = Object.defineProperties;
|
|
4
5
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
6
|
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
6
7
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
8
|
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
9
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
8
10
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
11
|
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
10
12
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
@@ -32,6 +34,14 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
32
34
|
}
|
|
33
35
|
return to;
|
|
34
36
|
};
|
|
37
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
38
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
39
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
40
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
41
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
42
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
43
|
+
mod
|
|
44
|
+
));
|
|
35
45
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
36
46
|
var __async = (__this, __arguments, generator) => {
|
|
37
47
|
return new Promise((resolve, reject) => {
|
|
@@ -57,11 +67,14 @@ var __async = (__this, __arguments, generator) => {
|
|
|
57
67
|
// src/cross/index.ts
|
|
58
68
|
var cross_exports = {};
|
|
59
69
|
__export(cross_exports, {
|
|
70
|
+
ModelDataVisitor: () => ModelDataVisitor,
|
|
60
71
|
NestedReadVisitor: () => NestedReadVisitor,
|
|
61
72
|
NestedWriteVisitor: () => NestedWriteVisitor,
|
|
62
73
|
PrismaWriteActions: () => PrismaWriteActions,
|
|
74
|
+
applyMutation: () => applyMutation,
|
|
63
75
|
enumerate: () => enumerate,
|
|
64
76
|
getFields: () => getFields,
|
|
77
|
+
getIdFields: () => getIdFields,
|
|
65
78
|
getModelFields: () => getModelFields,
|
|
66
79
|
getMutatedModels: () => getMutatedModels,
|
|
67
80
|
getReadModels: () => getReadModels,
|
|
@@ -70,6 +83,37 @@ __export(cross_exports, {
|
|
|
70
83
|
});
|
|
71
84
|
module.exports = __toCommonJS(cross_exports);
|
|
72
85
|
|
|
86
|
+
// src/cross/model-data-visitor.ts
|
|
87
|
+
var ModelDataVisitor = class {
|
|
88
|
+
constructor(modelMeta) {
|
|
89
|
+
this.modelMeta = modelMeta;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Visits the given model data.
|
|
93
|
+
*/
|
|
94
|
+
visit(model, data, callback) {
|
|
95
|
+
if (!data || typeof data !== "object") {
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
const scalarData = {};
|
|
99
|
+
const subTasks = [];
|
|
100
|
+
for (const [k, v] of Object.entries(data)) {
|
|
101
|
+
const field = resolveField(this.modelMeta, model, k);
|
|
102
|
+
if (field && field.isDataModel) {
|
|
103
|
+
if (field.isArray && Array.isArray(v)) {
|
|
104
|
+
subTasks.push(...v.map((item) => ({ model: field.type, data: item })));
|
|
105
|
+
} else {
|
|
106
|
+
subTasks.push({ model: field.type, data: v });
|
|
107
|
+
}
|
|
108
|
+
} else {
|
|
109
|
+
scalarData[k] = v;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
callback(model, data, scalarData);
|
|
113
|
+
subTasks.forEach(({ model: model2, data: data2 }) => this.visit(model2, data2, callback));
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
|
|
73
117
|
// src/cross/model-meta.ts
|
|
74
118
|
var import_lower_case_first = require("lower-case-first");
|
|
75
119
|
function resolveField(modelMeta, model, field) {
|
|
@@ -80,6 +124,177 @@ function getFields(modelMeta, model) {
|
|
|
80
124
|
return modelMeta.fields[(0, import_lower_case_first.lowerCaseFirst)(model)];
|
|
81
125
|
}
|
|
82
126
|
|
|
127
|
+
// src/cross/mutator.ts
|
|
128
|
+
var import_uuid = require("uuid");
|
|
129
|
+
var import_deepcopy = __toESM(require("deepcopy"));
|
|
130
|
+
function applyMutation(queryModel, queryOp, queryData, mutationModel, mutationOp, mutationArgs, modelMeta, logging) {
|
|
131
|
+
return __async(this, null, function* () {
|
|
132
|
+
if (["count", "aggregate", "groupBy"].includes(queryOp)) {
|
|
133
|
+
return void 0;
|
|
134
|
+
}
|
|
135
|
+
let resultData = queryData;
|
|
136
|
+
let updated = false;
|
|
137
|
+
const visitor = new NestedWriteVisitor(modelMeta, {
|
|
138
|
+
create: (model, args) => {
|
|
139
|
+
if (model === queryModel) {
|
|
140
|
+
const r = createMutate(queryModel, queryOp, resultData, args, modelMeta, logging);
|
|
141
|
+
if (r) {
|
|
142
|
+
resultData = r;
|
|
143
|
+
updated = true;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
},
|
|
147
|
+
createMany: (model, args) => {
|
|
148
|
+
if (model === queryModel && (args == null ? void 0 : args.data)) {
|
|
149
|
+
for (const oneArg of enumerate(args.data)) {
|
|
150
|
+
const r = createMutate(queryModel, queryOp, resultData, oneArg, modelMeta, logging);
|
|
151
|
+
if (r) {
|
|
152
|
+
resultData = r;
|
|
153
|
+
updated = true;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
},
|
|
158
|
+
update: (model, args) => {
|
|
159
|
+
const r = updateMutate(queryModel, resultData, model, args, modelMeta, logging);
|
|
160
|
+
if (r) {
|
|
161
|
+
resultData = r;
|
|
162
|
+
updated = true;
|
|
163
|
+
}
|
|
164
|
+
},
|
|
165
|
+
delete: (model, args) => {
|
|
166
|
+
const r = deleteMutate(queryModel, resultData, model, args, modelMeta, logging);
|
|
167
|
+
if (r) {
|
|
168
|
+
resultData = r;
|
|
169
|
+
updated = true;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
});
|
|
173
|
+
yield visitor.visit(mutationModel, mutationOp, mutationArgs);
|
|
174
|
+
return updated ? resultData : void 0;
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
function createMutate(queryModel, queryOp, currentData, newData, modelMeta, logging) {
|
|
178
|
+
if (!newData) {
|
|
179
|
+
return void 0;
|
|
180
|
+
}
|
|
181
|
+
if (queryOp !== "findMany") {
|
|
182
|
+
return void 0;
|
|
183
|
+
}
|
|
184
|
+
const modelFields = getFields(modelMeta, queryModel);
|
|
185
|
+
if (!modelFields) {
|
|
186
|
+
return void 0;
|
|
187
|
+
}
|
|
188
|
+
const insert = {};
|
|
189
|
+
const newDataFields = Object.keys(newData);
|
|
190
|
+
Object.entries(modelFields).forEach(([name, field]) => {
|
|
191
|
+
var _a, _b, _c, _d;
|
|
192
|
+
if (field.isDataModel) {
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
if (newDataFields.includes(name)) {
|
|
196
|
+
insert[name] = newData[name];
|
|
197
|
+
} else {
|
|
198
|
+
const defaultAttr = (_a = field.attributes) == null ? void 0 : _a.find((attr) => attr.name === "@default");
|
|
199
|
+
if (field.type === "DateTime") {
|
|
200
|
+
if (defaultAttr || ((_b = field.attributes) == null ? void 0 : _b.some((attr) => attr.name === "@updatedAt"))) {
|
|
201
|
+
insert[name] = /* @__PURE__ */ new Date();
|
|
202
|
+
}
|
|
203
|
+
} else if (((_d = (_c = defaultAttr == null ? void 0 : defaultAttr.args) == null ? void 0 : _c[0]) == null ? void 0 : _d.value) !== void 0) {
|
|
204
|
+
insert[name] = defaultAttr.args[0].value;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
});
|
|
208
|
+
const idFields = getIdFields(modelMeta, queryModel, false);
|
|
209
|
+
idFields.forEach((f) => {
|
|
210
|
+
if (insert[f.name] === void 0) {
|
|
211
|
+
if (f.type === "Int" || f.type === "BigInt") {
|
|
212
|
+
const currMax = Math.max(
|
|
213
|
+
...[...currentData].map((item) => {
|
|
214
|
+
const idv = parseInt(item[f.name]);
|
|
215
|
+
return isNaN(idv) ? 0 : idv;
|
|
216
|
+
})
|
|
217
|
+
);
|
|
218
|
+
insert[f.name] = currMax + 1;
|
|
219
|
+
} else {
|
|
220
|
+
insert[f.name] = (0, import_uuid.v4)();
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
});
|
|
224
|
+
insert.$optimistic = true;
|
|
225
|
+
if (logging) {
|
|
226
|
+
console.log(`Optimistic create for ${queryModel}:`, insert);
|
|
227
|
+
}
|
|
228
|
+
return [insert, ...currentData];
|
|
229
|
+
}
|
|
230
|
+
function updateMutate(queryModel, currentData, mutateModel, mutateArgs, modelMeta, logging) {
|
|
231
|
+
if (!currentData) {
|
|
232
|
+
return void 0;
|
|
233
|
+
}
|
|
234
|
+
if (!(mutateArgs == null ? void 0 : mutateArgs.where) || !(mutateArgs == null ? void 0 : mutateArgs.data)) {
|
|
235
|
+
return void 0;
|
|
236
|
+
}
|
|
237
|
+
let updated = false;
|
|
238
|
+
for (const item of enumerate(currentData)) {
|
|
239
|
+
const visitor = new ModelDataVisitor(modelMeta);
|
|
240
|
+
visitor.visit(queryModel, item, (model, _data, scalarData) => {
|
|
241
|
+
if (model === mutateModel && idFieldsMatch(model, scalarData, mutateArgs.where, modelMeta)) {
|
|
242
|
+
Object.keys(item).forEach((k) => {
|
|
243
|
+
if (mutateArgs.data[k] !== void 0) {
|
|
244
|
+
item[k] = mutateArgs.data[k];
|
|
245
|
+
}
|
|
246
|
+
});
|
|
247
|
+
item.$optimistic = true;
|
|
248
|
+
updated = true;
|
|
249
|
+
if (logging) {
|
|
250
|
+
console.log(`Optimistic update for ${queryModel}:`, item);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
return updated ? (0, import_deepcopy.default)(currentData) : void 0;
|
|
256
|
+
}
|
|
257
|
+
function deleteMutate(queryModel, currentData, mutateModel, mutateArgs, modelMeta, logging) {
|
|
258
|
+
if (!currentData || !mutateArgs) {
|
|
259
|
+
return void 0;
|
|
260
|
+
}
|
|
261
|
+
if (queryModel !== mutateModel) {
|
|
262
|
+
return void 0;
|
|
263
|
+
}
|
|
264
|
+
let updated = false;
|
|
265
|
+
let result = currentData;
|
|
266
|
+
if (Array.isArray(currentData)) {
|
|
267
|
+
for (const item of currentData) {
|
|
268
|
+
if (idFieldsMatch(mutateModel, item, mutateArgs, modelMeta)) {
|
|
269
|
+
result = result.filter((x) => x !== item);
|
|
270
|
+
updated = true;
|
|
271
|
+
if (logging) {
|
|
272
|
+
console.log(`Optimistic delete for ${queryModel}:`, item);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
} else {
|
|
277
|
+
if (idFieldsMatch(mutateModel, currentData, mutateArgs, modelMeta)) {
|
|
278
|
+
result = null;
|
|
279
|
+
updated = true;
|
|
280
|
+
if (logging) {
|
|
281
|
+
console.log(`Optimistic delete for ${queryModel}:`, currentData);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
return updated ? result : void 0;
|
|
286
|
+
}
|
|
287
|
+
function idFieldsMatch(model, x, y, modelMeta) {
|
|
288
|
+
if (!x || !y || typeof x !== "object" || typeof y !== "object") {
|
|
289
|
+
return false;
|
|
290
|
+
}
|
|
291
|
+
const idFields = getIdFields(modelMeta, model, false);
|
|
292
|
+
if (idFields.length === 0) {
|
|
293
|
+
return false;
|
|
294
|
+
}
|
|
295
|
+
return idFields.every((f) => x[f.name] === y[f.name]);
|
|
296
|
+
}
|
|
297
|
+
|
|
83
298
|
// src/cross/nested-read-visitor.ts
|
|
84
299
|
var NestedReadVisitor = class {
|
|
85
300
|
constructor(modelMeta, callback) {
|
|
@@ -139,6 +354,7 @@ var PrismaWriteActions = [
|
|
|
139
354
|
];
|
|
140
355
|
|
|
141
356
|
// src/cross/utils.ts
|
|
357
|
+
var import_lower_case_first2 = require("lower-case-first");
|
|
142
358
|
function getModelFields(data) {
|
|
143
359
|
return data ? Object.keys(data) : [];
|
|
144
360
|
}
|
|
@@ -167,6 +383,21 @@ function zip(x, y) {
|
|
|
167
383
|
return [[x, y]];
|
|
168
384
|
}
|
|
169
385
|
}
|
|
386
|
+
function getIdFields(modelMeta, model, throwIfNotFound = false) {
|
|
387
|
+
let fields = modelMeta.fields[(0, import_lower_case_first2.lowerCaseFirst)(model)];
|
|
388
|
+
if (!fields) {
|
|
389
|
+
if (throwIfNotFound) {
|
|
390
|
+
throw new Error(`Unable to load fields for ${model}`);
|
|
391
|
+
} else {
|
|
392
|
+
fields = {};
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
const result = Object.values(fields).filter((f) => f.isId);
|
|
396
|
+
if (result.length === 0 && throwIfNotFound) {
|
|
397
|
+
throw new Error(`model ${model} does not have an id field`);
|
|
398
|
+
}
|
|
399
|
+
return result;
|
|
400
|
+
}
|
|
170
401
|
|
|
171
402
|
// src/cross/nested-write-visitor.ts
|
|
172
403
|
var NestedWriteVisitor = class {
|
|
@@ -385,7 +616,7 @@ var NestedWriteVisitor = class {
|
|
|
385
616
|
};
|
|
386
617
|
|
|
387
618
|
// src/cross/query-analyzer.ts
|
|
388
|
-
var
|
|
619
|
+
var import_lower_case_first3 = require("lower-case-first");
|
|
389
620
|
function getReadModels(model, modelMeta, args) {
|
|
390
621
|
const result = /* @__PURE__ */ new Set();
|
|
391
622
|
result.add(model);
|
|
@@ -439,7 +670,7 @@ function collectDeleteCascades(model, modelMeta, result, visited) {
|
|
|
439
670
|
return;
|
|
440
671
|
}
|
|
441
672
|
visited.add(model);
|
|
442
|
-
const cascades = modelMeta.deleteCascade[(0,
|
|
673
|
+
const cascades = modelMeta.deleteCascade[(0, import_lower_case_first3.lowerCaseFirst)(model)];
|
|
443
674
|
if (!cascades) {
|
|
444
675
|
return;
|
|
445
676
|
}
|
|
@@ -450,11 +681,14 @@ function collectDeleteCascades(model, modelMeta, result, visited) {
|
|
|
450
681
|
}
|
|
451
682
|
// Annotate the CommonJS export names for ESM import in node:
|
|
452
683
|
0 && (module.exports = {
|
|
684
|
+
ModelDataVisitor,
|
|
453
685
|
NestedReadVisitor,
|
|
454
686
|
NestedWriteVisitor,
|
|
455
687
|
PrismaWriteActions,
|
|
688
|
+
applyMutation,
|
|
456
689
|
enumerate,
|
|
457
690
|
getFields,
|
|
691
|
+
getIdFields,
|
|
458
692
|
getModelFields,
|
|
459
693
|
getMutatedModels,
|
|
460
694
|
getReadModels,
|