@zenstackhq/runtime 1.8.1 → 2.0.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. package/constants.d.ts +5 -1
  2. package/constants.js +6 -2
  3. package/constants.js.map +1 -1
  4. package/cross/index.d.mts +60 -11
  5. package/cross/index.d.ts +60 -11
  6. package/cross/index.js +33 -7
  7. package/cross/index.js.map +1 -1
  8. package/cross/index.mjs +30 -7
  9. package/cross/index.mjs.map +1 -1
  10. package/enhance.d.ts +1 -0
  11. package/enhance.js +10 -0
  12. package/enhancements/create-enhancement.d.ts +78 -0
  13. package/enhancements/create-enhancement.js +86 -0
  14. package/enhancements/create-enhancement.js.map +1 -0
  15. package/enhancements/default-auth.d.ts +7 -0
  16. package/enhancements/default-auth.js +92 -0
  17. package/enhancements/default-auth.js.map +1 -0
  18. package/enhancements/delegate.d.ts +64 -0
  19. package/enhancements/delegate.js +903 -0
  20. package/enhancements/delegate.js.map +1 -0
  21. package/enhancements/index.d.ts +1 -6
  22. package/enhancements/index.js +1 -6
  23. package/enhancements/index.js.map +1 -1
  24. package/enhancements/logger.js.map +1 -0
  25. package/enhancements/omit.d.ts +4 -14
  26. package/enhancements/omit.js +14 -14
  27. package/enhancements/omit.js.map +1 -1
  28. package/enhancements/password.d.ts +4 -14
  29. package/enhancements/password.js +6 -10
  30. package/enhancements/password.js.map +1 -1
  31. package/enhancements/policy/handler.d.ts +19 -17
  32. package/enhancements/policy/handler.js +169 -157
  33. package/enhancements/policy/handler.js.map +1 -1
  34. package/enhancements/policy/index.d.ts +3 -37
  35. package/enhancements/policy/index.js +7 -24
  36. package/enhancements/policy/index.js.map +1 -1
  37. package/enhancements/policy/policy-utils.d.ts +23 -45
  38. package/enhancements/policy/policy-utils.js +34 -147
  39. package/enhancements/policy/policy-utils.js.map +1 -1
  40. package/enhancements/proxy.d.ts +11 -3
  41. package/enhancements/proxy.js +10 -9
  42. package/enhancements/proxy.js.map +1 -1
  43. package/enhancements/query-utils.d.ts +24 -0
  44. package/enhancements/query-utils.js +152 -0
  45. package/enhancements/query-utils.js.map +1 -0
  46. package/enhancements/types.d.ts +3 -3
  47. package/enhancements/utils.d.ts +3 -3
  48. package/enhancements/utils.js +9 -68
  49. package/enhancements/utils.js.map +1 -1
  50. package/index.d.ts +1 -1
  51. package/index.js +1 -1
  52. package/index.js.map +1 -1
  53. package/package.json +2 -2
  54. package/types.d.ts +9 -2
  55. package/version.d.ts +3 -4
  56. package/version.js +29 -46
  57. package/version.js.map +1 -1
  58. package/enhancements/enhance.d.ts +0 -18
  59. package/enhancements/enhance.js +0 -42
  60. package/enhancements/enhance.js.map +0 -1
  61. package/enhancements/policy/logger.js.map +0 -1
  62. package/enhancements/preset.d.ts +0 -15
  63. package/enhancements/preset.js +0 -21
  64. package/enhancements/preset.js.map +0 -1
  65. package/loader.d.ts +0 -22
  66. package/loader.js +0 -99
  67. package/loader.js.map +0 -1
  68. /package/enhancements/{policy/logger.d.ts → logger.d.ts} +0 -0
  69. /package/enhancements/{policy/logger.js → logger.js} +0 -0
@@ -0,0 +1,903 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.DelegateProxyHandler = exports.withDelegate = void 0;
16
+ /* eslint-disable @typescript-eslint/no-explicit-any */
17
+ const deepcopy_1 = __importDefault(require("deepcopy"));
18
+ const deepmerge_1 = __importDefault(require("deepmerge"));
19
+ const lower_case_first_1 = require("lower-case-first");
20
+ const constants_1 = require("../constants");
21
+ const cross_1 = require("../cross");
22
+ const logger_1 = require("./logger");
23
+ const proxy_1 = require("./proxy");
24
+ const query_utils_1 = require("./query-utils");
25
+ const utils_1 = require("./utils");
26
+ function withDelegate(prisma, options) {
27
+ return (0, proxy_1.makeProxy)(prisma, options.modelMeta, (_prisma, model) => new DelegateProxyHandler(_prisma, model, options), 'delegate');
28
+ }
29
+ exports.withDelegate = withDelegate;
30
+ class DelegateProxyHandler extends proxy_1.DefaultPrismaProxyHandler {
31
+ constructor(prisma, model, options) {
32
+ super(prisma, model, options);
33
+ this.logger = new logger_1.Logger(prisma);
34
+ this.queryUtils = new query_utils_1.QueryUtils(prisma, this.options);
35
+ }
36
+ // #region find
37
+ findFirst(args) {
38
+ return this.doFind(this.prisma, this.model, 'findFirst', args);
39
+ }
40
+ findFirstOrThrow(args) {
41
+ return this.doFind(this.prisma, this.model, 'findFirstOrThrow', args);
42
+ }
43
+ findUnique(args) {
44
+ return this.doFind(this.prisma, this.model, 'findUnique', args);
45
+ }
46
+ findUniqueOrThrow(args) {
47
+ return this.doFind(this.prisma, this.model, 'findUniqueOrThrow', args);
48
+ }
49
+ findMany(args) {
50
+ return __awaiter(this, void 0, void 0, function* () {
51
+ return this.doFind(this.prisma, this.model, 'findMany', args);
52
+ });
53
+ }
54
+ doFind(db, model, method, args) {
55
+ const _superIndex = name => super[name];
56
+ return __awaiter(this, void 0, void 0, function* () {
57
+ if (!this.involvesDelegateModel(model)) {
58
+ return _superIndex(method).call(this, args);
59
+ }
60
+ args = args ? (0, deepcopy_1.default)(args) : {};
61
+ this.injectWhereHierarchy(model, args === null || args === void 0 ? void 0 : args.where);
62
+ this.injectSelectIncludeHierarchy(model, args);
63
+ if (this.options.logPrismaQuery) {
64
+ this.logger.info(`[delegate] \`${method}\` ${this.getModelName(model)}: ${(0, utils_1.formatObject)(args)}`);
65
+ }
66
+ const entity = yield db[model][method](args);
67
+ if (Array.isArray(entity)) {
68
+ return entity.map((item) => this.assembleHierarchy(model, item));
69
+ }
70
+ else {
71
+ return this.assembleHierarchy(model, entity);
72
+ }
73
+ });
74
+ }
75
+ injectWhereHierarchy(model, where) {
76
+ if (!where || typeof where !== 'object') {
77
+ return;
78
+ }
79
+ Object.entries(where).forEach(([field, value]) => {
80
+ const fieldInfo = (0, cross_1.resolveField)(this.options.modelMeta, model, field);
81
+ if (!(fieldInfo === null || fieldInfo === void 0 ? void 0 : fieldInfo.inheritedFrom)) {
82
+ return;
83
+ }
84
+ let base = this.getBaseModel(model);
85
+ let target = where;
86
+ while (base) {
87
+ const baseRelationName = this.makeAuxRelationName(base);
88
+ // prepare base layer where
89
+ let thisLayer;
90
+ if (target[baseRelationName]) {
91
+ thisLayer = target[baseRelationName];
92
+ }
93
+ else {
94
+ thisLayer = target[baseRelationName] = {};
95
+ }
96
+ if (base.name === fieldInfo.inheritedFrom) {
97
+ thisLayer[field] = value;
98
+ delete where[field];
99
+ break;
100
+ }
101
+ else {
102
+ target = thisLayer;
103
+ base = this.getBaseModel(base.name);
104
+ }
105
+ }
106
+ });
107
+ }
108
+ buildWhereHierarchy(where) {
109
+ if (!where) {
110
+ return undefined;
111
+ }
112
+ where = (0, deepcopy_1.default)(where);
113
+ Object.entries(where).forEach(([field, value]) => {
114
+ const fieldInfo = (0, cross_1.resolveField)(this.options.modelMeta, this.model, field);
115
+ if (!(fieldInfo === null || fieldInfo === void 0 ? void 0 : fieldInfo.inheritedFrom)) {
116
+ return;
117
+ }
118
+ let base = this.getBaseModel(this.model);
119
+ let target = where;
120
+ while (base) {
121
+ const baseRelationName = this.makeAuxRelationName(base);
122
+ // prepare base layer where
123
+ let thisLayer;
124
+ if (target[baseRelationName]) {
125
+ thisLayer = target[baseRelationName];
126
+ }
127
+ else {
128
+ thisLayer = target[baseRelationName] = {};
129
+ }
130
+ if (base.name === fieldInfo.inheritedFrom) {
131
+ thisLayer[field] = value;
132
+ delete where[field];
133
+ break;
134
+ }
135
+ else {
136
+ target = thisLayer;
137
+ base = this.getBaseModel(base.name);
138
+ }
139
+ }
140
+ });
141
+ return where;
142
+ }
143
+ injectSelectIncludeHierarchy(model, args) {
144
+ if (!args || typeof args !== 'object') {
145
+ return;
146
+ }
147
+ for (const kind of ['select', 'include']) {
148
+ if (args[kind] && typeof args[kind] === 'object') {
149
+ for (const [field, value] of Object.entries(args[kind])) {
150
+ if (value !== undefined) {
151
+ if (this.injectBaseFieldSelect(model, field, value, args, kind)) {
152
+ delete args[kind][field];
153
+ }
154
+ else {
155
+ const fieldInfo = (0, cross_1.resolveField)(this.options.modelMeta, model, field);
156
+ if (fieldInfo && this.isDelegateOrDescendantOfDelegate(fieldInfo.type)) {
157
+ let nextValue = value;
158
+ if (nextValue === true) {
159
+ // make sure the payload is an object
160
+ args[kind][field] = nextValue = {};
161
+ }
162
+ this.injectSelectIncludeHierarchy(fieldInfo.type, nextValue);
163
+ }
164
+ }
165
+ }
166
+ }
167
+ }
168
+ }
169
+ if (!args.select) {
170
+ this.injectBaseIncludeRecursively(model, args);
171
+ }
172
+ }
173
+ buildSelectIncludeHierarchy(model, args) {
174
+ args = (0, deepcopy_1.default)(args);
175
+ const selectInclude = this.extractSelectInclude(args) || {};
176
+ if (selectInclude.select && typeof selectInclude.select === 'object') {
177
+ Object.entries(selectInclude.select).forEach(([field, value]) => {
178
+ if (value) {
179
+ if (this.injectBaseFieldSelect(model, field, value, selectInclude, 'select')) {
180
+ delete selectInclude.select[field];
181
+ }
182
+ }
183
+ });
184
+ }
185
+ else if (selectInclude.include && typeof selectInclude.include === 'object') {
186
+ Object.entries(selectInclude.include).forEach(([field, value]) => {
187
+ if (value) {
188
+ if (this.injectBaseFieldSelect(model, field, value, selectInclude, 'include')) {
189
+ delete selectInclude.include[field];
190
+ }
191
+ }
192
+ });
193
+ }
194
+ if (!selectInclude.select) {
195
+ this.injectBaseIncludeRecursively(model, selectInclude);
196
+ }
197
+ return selectInclude;
198
+ }
199
+ injectBaseFieldSelect(model, field, value, selectInclude, context) {
200
+ const fieldInfo = (0, cross_1.resolveField)(this.options.modelMeta, model, field);
201
+ if (!(fieldInfo === null || fieldInfo === void 0 ? void 0 : fieldInfo.inheritedFrom)) {
202
+ return false;
203
+ }
204
+ let base = this.getBaseModel(model);
205
+ let target = selectInclude;
206
+ while (base) {
207
+ const baseRelationName = this.makeAuxRelationName(base);
208
+ // prepare base layer select/include
209
+ // let selectOrInclude = 'select';
210
+ let thisLayer;
211
+ if (target.include) {
212
+ // selectOrInclude = 'include';
213
+ thisLayer = target.include;
214
+ }
215
+ else if (target.select) {
216
+ // selectOrInclude = 'select';
217
+ thisLayer = target.select;
218
+ }
219
+ else {
220
+ // selectInclude = 'include';
221
+ thisLayer = target.select = {};
222
+ }
223
+ if (base.name === fieldInfo.inheritedFrom) {
224
+ if (!thisLayer[baseRelationName]) {
225
+ thisLayer[baseRelationName] = { [context]: {} };
226
+ }
227
+ thisLayer[baseRelationName][context][field] = value;
228
+ break;
229
+ }
230
+ else {
231
+ if (!thisLayer[baseRelationName]) {
232
+ thisLayer[baseRelationName] = { select: {} };
233
+ }
234
+ target = thisLayer[baseRelationName];
235
+ base = this.getBaseModel(base.name);
236
+ }
237
+ }
238
+ return true;
239
+ }
240
+ injectBaseIncludeRecursively(model, selectInclude) {
241
+ const base = this.getBaseModel(model);
242
+ if (!base) {
243
+ return;
244
+ }
245
+ const baseRelationName = this.makeAuxRelationName(base);
246
+ if (selectInclude.select) {
247
+ selectInclude.include = Object.assign({ [baseRelationName]: {} }, selectInclude.select);
248
+ delete selectInclude.select;
249
+ }
250
+ else {
251
+ selectInclude.include = Object.assign({ [baseRelationName]: {} }, selectInclude.include);
252
+ }
253
+ this.injectBaseIncludeRecursively(base.name, selectInclude.include[baseRelationName]);
254
+ }
255
+ // #endregion
256
+ // #region create
257
+ create(args) {
258
+ const _super = Object.create(null, {
259
+ create: { get: () => super.create }
260
+ });
261
+ return __awaiter(this, void 0, void 0, function* () {
262
+ if (!args) {
263
+ throw (0, utils_1.prismaClientValidationError)(this.prisma, this.options.prismaModule, 'query argument is required');
264
+ }
265
+ if (!args.data) {
266
+ throw (0, utils_1.prismaClientValidationError)(this.prisma, this.options.prismaModule, 'data field is required in query argument');
267
+ }
268
+ if ((0, cross_1.isDelegateModel)(this.options.modelMeta, this.model)) {
269
+ throw (0, utils_1.prismaClientValidationError)(this.prisma, this.options.prismaModule, `Model "${this.model}" is a delegate and cannot be created directly`);
270
+ }
271
+ if (!this.involvesDelegateModel(this.model)) {
272
+ return _super.create.call(this, args);
273
+ }
274
+ return this.doCreate(this.prisma, this.model, args);
275
+ });
276
+ }
277
+ createMany(args) {
278
+ if (!args) {
279
+ throw (0, utils_1.prismaClientValidationError)(this.prisma, this.options.prismaModule, 'query argument is required');
280
+ }
281
+ if (!args.data) {
282
+ throw (0, utils_1.prismaClientValidationError)(this.prisma, this.options.prismaModule, 'data field is required in query argument');
283
+ }
284
+ if (!this.involvesDelegateModel(this.model)) {
285
+ return super.createMany(args);
286
+ }
287
+ if (this.isDelegateOrDescendantOfDelegate(this.model) && args.skipDuplicates) {
288
+ throw (0, utils_1.prismaClientValidationError)(this.prisma, this.options.prismaModule, '`createMany` with `skipDuplicates` set to true is not supported for delegated models');
289
+ }
290
+ // note that we can't call `createMany` directly because it doesn't support
291
+ // nested created, which is needed for creating base entities
292
+ return this.queryUtils.transaction(this.prisma, (tx) => __awaiter(this, void 0, void 0, function* () {
293
+ const r = yield Promise.all((0, cross_1.enumerate)(args.data).map((item) => __awaiter(this, void 0, void 0, function* () {
294
+ return this.doCreate(tx, this.model, item);
295
+ })));
296
+ // filter out undefined value (due to skipping duplicates)
297
+ return { count: r.filter((item) => !!item).length };
298
+ }));
299
+ }
300
+ doCreate(db, model, args) {
301
+ return __awaiter(this, void 0, void 0, function* () {
302
+ args = (0, deepcopy_1.default)(args);
303
+ yield this.injectCreateHierarchy(model, args);
304
+ this.injectSelectIncludeHierarchy(model, args);
305
+ if (this.options.logPrismaQuery) {
306
+ this.logger.info(`[delegate] \`create\` ${this.getModelName(model)}: ${(0, utils_1.formatObject)(args)}`);
307
+ }
308
+ const result = yield db[model].create(args);
309
+ return this.assembleHierarchy(model, result);
310
+ });
311
+ }
312
+ injectCreateHierarchy(model, args) {
313
+ return __awaiter(this, void 0, void 0, function* () {
314
+ const visitor = new cross_1.NestedWriteVisitor(this.options.modelMeta, {
315
+ create: (model, args, _context) => {
316
+ this.doProcessCreatePayload(model, args);
317
+ },
318
+ createMany: (model, args, _context) => {
319
+ if (args.skipDuplicates) {
320
+ throw (0, utils_1.prismaClientValidationError)(this.prisma, this.options.prismaModule, '`createMany` with `skipDuplicates` set to true is not supported for delegated models');
321
+ }
322
+ for (const item of (0, cross_1.enumerate)(args === null || args === void 0 ? void 0 : args.data)) {
323
+ this.doProcessCreatePayload(model, item);
324
+ }
325
+ },
326
+ });
327
+ yield visitor.visit(model, 'create', args);
328
+ });
329
+ }
330
+ doProcessCreatePayload(model, args) {
331
+ if (!args) {
332
+ return;
333
+ }
334
+ this.ensureBaseCreateHierarchy(model, args);
335
+ for (const [field, value] of Object.entries(args)) {
336
+ const fieldInfo = (0, cross_1.resolveField)(this.options.modelMeta, model, field);
337
+ if (fieldInfo === null || fieldInfo === void 0 ? void 0 : fieldInfo.inheritedFrom) {
338
+ this.injectBaseFieldData(model, fieldInfo, value, args, 'create');
339
+ delete args[field];
340
+ }
341
+ }
342
+ }
343
+ // ensure the full nested "create" structure is created for base types
344
+ ensureBaseCreateHierarchy(model, result) {
345
+ let curr = result;
346
+ let base = this.getBaseModel(model);
347
+ let sub = this.getModelInfo(model);
348
+ while (base) {
349
+ const baseRelationName = this.makeAuxRelationName(base);
350
+ if (!curr[baseRelationName]) {
351
+ curr[baseRelationName] = {};
352
+ }
353
+ if (!curr[baseRelationName].create) {
354
+ curr[baseRelationName].create = {};
355
+ if (base.discriminator) {
356
+ // set discriminator field
357
+ curr[baseRelationName].create[base.discriminator] = sub.name;
358
+ }
359
+ }
360
+ curr = curr[baseRelationName].create;
361
+ sub = base;
362
+ base = this.getBaseModel(base.name);
363
+ }
364
+ }
365
+ // inject field data that belongs to base type into proper nesting structure
366
+ injectBaseFieldData(model, fieldInfo, value, args, mode) {
367
+ let base = this.getBaseModel(model);
368
+ let curr = args;
369
+ while (base) {
370
+ if (base.discriminator === fieldInfo.name) {
371
+ throw (0, utils_1.prismaClientValidationError)(this.prisma, this.options.prismaModule, `fields "${fieldInfo.name}" is a discriminator and cannot be set directly`);
372
+ }
373
+ const baseRelationName = this.makeAuxRelationName(base);
374
+ if (!curr[baseRelationName]) {
375
+ curr[baseRelationName] = {};
376
+ }
377
+ if (!curr[baseRelationName][mode]) {
378
+ curr[baseRelationName][mode] = {};
379
+ }
380
+ curr = curr[baseRelationName][mode];
381
+ if (fieldInfo.inheritedFrom === base.name) {
382
+ curr[fieldInfo.name] = value;
383
+ break;
384
+ }
385
+ base = this.getBaseModel(base.name);
386
+ }
387
+ }
388
+ // #endregion
389
+ // #region update
390
+ update(args) {
391
+ if (!args) {
392
+ throw (0, utils_1.prismaClientValidationError)(this.prisma, this.options.prismaModule, 'query argument is required');
393
+ }
394
+ if (!args.data) {
395
+ throw (0, utils_1.prismaClientValidationError)(this.prisma, this.options.prismaModule, 'data field is required in query argument');
396
+ }
397
+ if (!this.involvesDelegateModel(this.model)) {
398
+ return super.update(args);
399
+ }
400
+ return this.queryUtils.transaction(this.prisma, (tx) => this.doUpdate(tx, this.model, args));
401
+ }
402
+ updateMany(args) {
403
+ const _super = Object.create(null, {
404
+ updateMany: { get: () => super.updateMany }
405
+ });
406
+ return __awaiter(this, void 0, void 0, function* () {
407
+ if (!args) {
408
+ throw (0, utils_1.prismaClientValidationError)(this.prisma, this.options.prismaModule, 'query argument is required');
409
+ }
410
+ if (!args.data) {
411
+ throw (0, utils_1.prismaClientValidationError)(this.prisma, this.options.prismaModule, 'data field is required in query argument');
412
+ }
413
+ if (!this.involvesDelegateModel(this.model)) {
414
+ return _super.updateMany.call(this, args);
415
+ }
416
+ const simpleUpdateMany = Object.keys(args.data).every((key) => {
417
+ // check if the `data` clause involves base fields
418
+ const fieldInfo = (0, cross_1.resolveField)(this.options.modelMeta, this.model, key);
419
+ return !(fieldInfo === null || fieldInfo === void 0 ? void 0 : fieldInfo.inheritedFrom);
420
+ });
421
+ return this.queryUtils.transaction(this.prisma, (tx) => this.doUpdateMany(tx, this.model, args, simpleUpdateMany));
422
+ });
423
+ }
424
+ upsert(args) {
425
+ const _super = Object.create(null, {
426
+ upsert: { get: () => super.upsert }
427
+ });
428
+ return __awaiter(this, void 0, void 0, function* () {
429
+ if (!args) {
430
+ throw (0, utils_1.prismaClientValidationError)(this.prisma, this.options.prismaModule, 'query argument is required');
431
+ }
432
+ if (!args.where) {
433
+ throw (0, utils_1.prismaClientValidationError)(this.prisma, this.options.prismaModule, 'where field is required in query argument');
434
+ }
435
+ if ((0, cross_1.isDelegateModel)(this.options.modelMeta, this.model)) {
436
+ throw (0, utils_1.prismaClientValidationError)(this.prisma, this.options.prismaModule, `Model "${this.model}" is a delegate and doesn't support upsert`);
437
+ }
438
+ if (!this.involvesDelegateModel(this.model)) {
439
+ return _super.upsert.call(this, args);
440
+ }
441
+ args = (0, deepcopy_1.default)(args);
442
+ this.injectWhereHierarchy(this.model, args === null || args === void 0 ? void 0 : args.where);
443
+ this.injectSelectIncludeHierarchy(this.model, args);
444
+ if (args.create) {
445
+ this.doProcessCreatePayload(this.model, args.create);
446
+ }
447
+ if (args.update) {
448
+ this.doProcessUpdatePayload(this.model, args.update);
449
+ }
450
+ if (this.options.logPrismaQuery) {
451
+ this.logger.info(`[delegate] \`upsert\` ${this.getModelName(this.model)}: ${(0, utils_1.formatObject)(args)}`);
452
+ }
453
+ const result = yield this.prisma[this.model].upsert(args);
454
+ return this.assembleHierarchy(this.model, result);
455
+ });
456
+ }
457
+ doUpdate(db, model, args) {
458
+ return __awaiter(this, void 0, void 0, function* () {
459
+ args = (0, deepcopy_1.default)(args);
460
+ yield this.injectUpdateHierarchy(db, model, args);
461
+ this.injectSelectIncludeHierarchy(model, args);
462
+ if (this.options.logPrismaQuery) {
463
+ this.logger.info(`[delegate] \`update\` ${this.getModelName(model)}: ${(0, utils_1.formatObject)(args)}`);
464
+ }
465
+ const result = yield db[model].update(args);
466
+ return this.assembleHierarchy(model, result);
467
+ });
468
+ }
469
+ doUpdateMany(db, model, args, simpleUpdateMany) {
470
+ return __awaiter(this, void 0, void 0, function* () {
471
+ if (simpleUpdateMany) {
472
+ // do a direct `updateMany`
473
+ args = (0, deepcopy_1.default)(args);
474
+ yield this.injectUpdateHierarchy(db, model, args);
475
+ if (this.options.logPrismaQuery) {
476
+ this.logger.info(`[delegate] \`updateMany\` ${this.getModelName(model)}: ${(0, utils_1.formatObject)(args)}`);
477
+ }
478
+ return db[model].updateMany(args);
479
+ }
480
+ else {
481
+ // translate to plain `update` for nested write into base fields
482
+ const findArgs = {
483
+ where: (0, deepcopy_1.default)(args.where),
484
+ select: this.queryUtils.makeIdSelection(model),
485
+ };
486
+ yield this.injectUpdateHierarchy(db, model, findArgs);
487
+ if (this.options.logPrismaQuery) {
488
+ this.logger.info(`[delegate] \`updateMany\` find candidates: ${this.getModelName(model)}: ${(0, utils_1.formatObject)(findArgs)}`);
489
+ }
490
+ const entities = yield db[model].findMany(findArgs);
491
+ const updatePayload = { data: (0, deepcopy_1.default)(args.data), select: this.queryUtils.makeIdSelection(model) };
492
+ yield this.injectUpdateHierarchy(db, model, updatePayload);
493
+ const result = yield Promise.all(entities.map((entity) => {
494
+ const updateArgs = Object.assign({ where: entity }, updatePayload);
495
+ this.logger.info(`[delegate] \`updateMany\` update: ${this.getModelName(model)}: ${(0, utils_1.formatObject)(updateArgs)}`);
496
+ return db[model].update(updateArgs);
497
+ }));
498
+ return { count: result.length };
499
+ }
500
+ });
501
+ }
502
+ injectUpdateHierarchy(db, model, args) {
503
+ return __awaiter(this, void 0, void 0, function* () {
504
+ const visitor = new cross_1.NestedWriteVisitor(this.options.modelMeta, {
505
+ update: (model, args, _context) => {
506
+ this.injectWhereHierarchy(model, args === null || args === void 0 ? void 0 : args.where);
507
+ this.doProcessUpdatePayload(model, args === null || args === void 0 ? void 0 : args.data);
508
+ },
509
+ updateMany: (model, args, context) => __awaiter(this, void 0, void 0, function* () {
510
+ let simpleUpdateMany = Object.keys(args.data).every((key) => {
511
+ // check if the `data` clause involves base fields
512
+ const fieldInfo = (0, cross_1.resolveField)(this.options.modelMeta, model, key);
513
+ return !(fieldInfo === null || fieldInfo === void 0 ? void 0 : fieldInfo.inheritedFrom);
514
+ });
515
+ if (simpleUpdateMany) {
516
+ // check if the `where` clause involves base fields
517
+ simpleUpdateMany = Object.keys(args.where || {}).every((key) => {
518
+ const fieldInfo = (0, cross_1.resolveField)(this.options.modelMeta, model, key);
519
+ return !(fieldInfo === null || fieldInfo === void 0 ? void 0 : fieldInfo.inheritedFrom);
520
+ });
521
+ }
522
+ if (simpleUpdateMany) {
523
+ this.injectWhereHierarchy(model, args === null || args === void 0 ? void 0 : args.where);
524
+ this.doProcessUpdatePayload(model, args === null || args === void 0 ? void 0 : args.data);
525
+ }
526
+ else {
527
+ const where = this.queryUtils.buildReversedQuery(context, false, false);
528
+ yield this.queryUtils.transaction(db, (tx) => __awaiter(this, void 0, void 0, function* () {
529
+ yield this.doUpdateMany(tx, model, Object.assign(Object.assign({}, args), { where }), simpleUpdateMany);
530
+ }));
531
+ delete context.parent['updateMany'];
532
+ }
533
+ }),
534
+ upsert: (model, args, _context) => {
535
+ this.injectWhereHierarchy(model, args === null || args === void 0 ? void 0 : args.where);
536
+ if (args.create) {
537
+ this.doProcessCreatePayload(model, args === null || args === void 0 ? void 0 : args.create);
538
+ }
539
+ if (args.update) {
540
+ this.doProcessUpdatePayload(model, args === null || args === void 0 ? void 0 : args.update);
541
+ }
542
+ },
543
+ create: (model, args, _context) => {
544
+ if ((0, cross_1.isDelegateModel)(this.options.modelMeta, model)) {
545
+ throw (0, utils_1.prismaClientValidationError)(this.prisma, this.options.prismaModule, `Model "${model}" is a delegate and cannot be created directly`);
546
+ }
547
+ this.doProcessCreatePayload(model, args);
548
+ },
549
+ createMany: (model, args, _context) => {
550
+ if (args.skipDuplicates) {
551
+ throw (0, utils_1.prismaClientValidationError)(this.prisma, this.options.prismaModule, '`createMany` with `skipDuplicates` set to true is not supported for delegated models');
552
+ }
553
+ for (const item of (0, cross_1.enumerate)(args === null || args === void 0 ? void 0 : args.data)) {
554
+ this.doProcessCreatePayload(model, item);
555
+ }
556
+ },
557
+ connect: (model, args, _context) => {
558
+ this.injectWhereHierarchy(model, args);
559
+ },
560
+ connectOrCreate: (model, args, _context) => {
561
+ this.injectWhereHierarchy(model, args.where);
562
+ if (args.create) {
563
+ this.doProcessCreatePayload(model, args.create);
564
+ }
565
+ },
566
+ disconnect: (model, args, _context) => {
567
+ this.injectWhereHierarchy(model, args);
568
+ },
569
+ set: (model, args, _context) => {
570
+ this.injectWhereHierarchy(model, args);
571
+ },
572
+ delete: (model, _args, context) => __awaiter(this, void 0, void 0, function* () {
573
+ const where = this.queryUtils.buildReversedQuery(context, false, false);
574
+ yield this.queryUtils.transaction(db, (tx) => __awaiter(this, void 0, void 0, function* () {
575
+ yield this.doDelete(tx, model, { where });
576
+ }));
577
+ delete context.parent['delete'];
578
+ }),
579
+ deleteMany: (model, _args, context) => __awaiter(this, void 0, void 0, function* () {
580
+ const where = this.queryUtils.buildReversedQuery(context, false, false);
581
+ yield this.queryUtils.transaction(db, (tx) => __awaiter(this, void 0, void 0, function* () {
582
+ yield this.doDeleteMany(tx, model, where);
583
+ }));
584
+ delete context.parent['deleteMany'];
585
+ }),
586
+ });
587
+ yield visitor.visit(model, 'update', args);
588
+ });
589
+ }
590
+ doProcessUpdatePayload(model, data) {
591
+ if (!data) {
592
+ return;
593
+ }
594
+ for (const [field, value] of Object.entries(data)) {
595
+ const fieldInfo = (0, cross_1.resolveField)(this.options.modelMeta, model, field);
596
+ if (fieldInfo === null || fieldInfo === void 0 ? void 0 : fieldInfo.inheritedFrom) {
597
+ this.injectBaseFieldData(model, fieldInfo, value, data, 'update');
598
+ delete data[field];
599
+ }
600
+ }
601
+ }
602
+ // #endregion
603
+ // #region delete
604
+ delete(args) {
605
+ if (!args) {
606
+ throw (0, utils_1.prismaClientValidationError)(this.prisma, this.options.prismaModule, 'query argument is required');
607
+ }
608
+ if (!this.involvesDelegateModel(this.model)) {
609
+ return super.delete(args);
610
+ }
611
+ return this.queryUtils.transaction(this.prisma, (tx) => __awaiter(this, void 0, void 0, function* () {
612
+ const selectInclude = this.buildSelectIncludeHierarchy(this.model, args);
613
+ // make sure id fields are selected
614
+ const idFields = this.getIdFields(this.model);
615
+ for (const idField of idFields) {
616
+ if ((selectInclude === null || selectInclude === void 0 ? void 0 : selectInclude.select) && !(idField.name in selectInclude.select)) {
617
+ selectInclude.select[idField.name] = true;
618
+ }
619
+ }
620
+ const deleteArgs = Object.assign(Object.assign({}, (0, deepcopy_1.default)(args)), selectInclude);
621
+ return this.doDelete(tx, this.model, deleteArgs);
622
+ }));
623
+ }
624
+ deleteMany(args) {
625
+ if (!this.involvesDelegateModel(this.model)) {
626
+ return super.deleteMany(args);
627
+ }
628
+ return this.queryUtils.transaction(this.prisma, (tx) => this.doDeleteMany(tx, this.model, args === null || args === void 0 ? void 0 : args.where));
629
+ }
630
+ doDeleteMany(db, model, where) {
631
+ return __awaiter(this, void 0, void 0, function* () {
632
+ // query existing entities with id
633
+ const idSelection = this.queryUtils.makeIdSelection(model);
634
+ const findArgs = { where: (0, deepcopy_1.default)(where), select: idSelection };
635
+ this.injectWhereHierarchy(model, findArgs.where);
636
+ if (this.options.logPrismaQuery) {
637
+ this.logger.info(`[delegate] \`deleteMany\` find candidates: ${this.getModelName(model)}: ${(0, utils_1.formatObject)(findArgs)}`);
638
+ }
639
+ const entities = yield db[model].findMany(findArgs);
640
+ // recursively delete base entities (they all have the same id values)
641
+ yield Promise.all(entities.map((entity) => this.doDelete(db, model, { where: entity })));
642
+ return { count: entities.length };
643
+ });
644
+ }
645
+ deleteBaseRecursively(db, model, idValues) {
646
+ return __awaiter(this, void 0, void 0, function* () {
647
+ let base = this.getBaseModel(model);
648
+ while (base) {
649
+ yield db[base.name].delete({ where: idValues });
650
+ base = this.getBaseModel(base.name);
651
+ }
652
+ });
653
+ }
654
+ doDelete(db, model, args) {
655
+ return __awaiter(this, void 0, void 0, function* () {
656
+ this.injectWhereHierarchy(model, args.where);
657
+ if (this.options.logPrismaQuery) {
658
+ this.logger.info(`[delegate] \`delete\` ${this.getModelName(model)}: ${(0, utils_1.formatObject)(args)}`);
659
+ }
660
+ const result = yield db[model].delete(args);
661
+ const idValues = this.queryUtils.getEntityIds(model, result);
662
+ // recursively delete base entities (they all have the same id values)
663
+ yield this.deleteBaseRecursively(db, model, idValues);
664
+ return this.assembleHierarchy(model, result);
665
+ });
666
+ }
667
+ // #endregion
668
+ // #region aggregation
669
+ aggregate(args) {
670
+ if (!args) {
671
+ throw (0, utils_1.prismaClientValidationError)(this.prisma, this.options.prismaModule, 'query argument is required');
672
+ }
673
+ if (!this.involvesDelegateModel(this.model)) {
674
+ return super.aggregate(args);
675
+ }
676
+ // check if any aggregation operator is using fields from base
677
+ this.checkAggregationArgs('aggregate', args);
678
+ args = (0, deepcopy_1.default)(args);
679
+ if (args.cursor) {
680
+ args.cursor = this.buildWhereHierarchy(args.cursor);
681
+ }
682
+ if (args.orderBy) {
683
+ args.orderBy = this.buildWhereHierarchy(args.orderBy);
684
+ }
685
+ if (args.where) {
686
+ args.where = this.buildWhereHierarchy(args.where);
687
+ }
688
+ if (this.options.logPrismaQuery) {
689
+ this.logger.info(`[delegate] \`aggregate\` ${this.getModelName(this.model)}: ${(0, utils_1.formatObject)(args)}`);
690
+ }
691
+ return super.aggregate(args);
692
+ }
693
+ count(args) {
694
+ if (!this.involvesDelegateModel(this.model)) {
695
+ return super.count(args);
696
+ }
697
+ // check if count select is using fields from base
698
+ this.checkAggregationArgs('count', args);
699
+ args = (0, deepcopy_1.default)(args);
700
+ if (args === null || args === void 0 ? void 0 : args.cursor) {
701
+ args.cursor = this.buildWhereHierarchy(args.cursor);
702
+ }
703
+ if (args === null || args === void 0 ? void 0 : args.where) {
704
+ args.where = this.buildWhereHierarchy(args.where);
705
+ }
706
+ if (this.options.logPrismaQuery) {
707
+ this.logger.info(`[delegate] \`count\` ${this.getModelName(this.model)}: ${(0, utils_1.formatObject)(args)}`);
708
+ }
709
+ return super.count(args);
710
+ }
711
+ groupBy(args) {
712
+ if (!args) {
713
+ throw (0, utils_1.prismaClientValidationError)(this.prisma, this.options.prismaModule, 'query argument is required');
714
+ }
715
+ if (!this.involvesDelegateModel(this.model)) {
716
+ return super.groupBy(args);
717
+ }
718
+ // check if count select is using fields from base
719
+ this.checkAggregationArgs('groupBy', args);
720
+ if (args.by) {
721
+ for (const by of (0, cross_1.enumerate)(args.by)) {
722
+ const fieldInfo = (0, cross_1.resolveField)(this.options.modelMeta, this.model, by);
723
+ if (fieldInfo && fieldInfo.inheritedFrom) {
724
+ throw (0, utils_1.prismaClientValidationError)(this.prisma, this.options.prismaModule, `groupBy with fields from base type is not supported yet: "${by}"`);
725
+ }
726
+ }
727
+ }
728
+ args = (0, deepcopy_1.default)(args);
729
+ if (args.where) {
730
+ args.where = this.buildWhereHierarchy(args.where);
731
+ }
732
+ if (this.options.logPrismaQuery) {
733
+ this.logger.info(`[delegate] \`groupBy\` ${this.getModelName(this.model)}: ${(0, utils_1.formatObject)(args)}`);
734
+ }
735
+ return super.groupBy(args);
736
+ }
737
+ checkAggregationArgs(operation, args) {
738
+ if (!args) {
739
+ return;
740
+ }
741
+ for (const op of ['_count', '_sum', '_avg', '_min', '_max', 'select', 'having']) {
742
+ if (args[op] && typeof args[op] === 'object') {
743
+ for (const field of Object.keys(args[op])) {
744
+ const fieldInfo = (0, cross_1.resolveField)(this.options.modelMeta, this.model, field);
745
+ if (fieldInfo === null || fieldInfo === void 0 ? void 0 : fieldInfo.inheritedFrom) {
746
+ throw (0, utils_1.prismaClientValidationError)(this.prisma, this.options.prismaModule, `${operation} with fields from base type is not supported yet: "${field}"`);
747
+ }
748
+ }
749
+ }
750
+ }
751
+ }
752
+ // #endregion
753
+ // #region utils
754
+ extractSelectInclude(args) {
755
+ if (!args) {
756
+ return undefined;
757
+ }
758
+ args = (0, deepcopy_1.default)(args);
759
+ return 'select' in args
760
+ ? { select: args['select'] }
761
+ : 'include' in args
762
+ ? { include: args['include'] }
763
+ : undefined;
764
+ }
765
+ makeAuxRelationName(model) {
766
+ return `${constants_1.DELEGATE_AUX_RELATION_PREFIX}_${(0, lower_case_first_1.lowerCaseFirst)(model.name)}`;
767
+ }
768
+ getModelName(model) {
769
+ const info = (0, cross_1.getModelInfo)(this.options.modelMeta, model, true);
770
+ return info.name;
771
+ }
772
+ getIdFields(model) {
773
+ const idFields = (0, cross_1.getIdFields)(this.options.modelMeta, model);
774
+ if (idFields && idFields.length > 0) {
775
+ return idFields;
776
+ }
777
+ const base = this.getBaseModel(model);
778
+ return base ? this.getIdFields(base.name) : [];
779
+ }
780
+ getModelInfo(model) {
781
+ return (0, cross_1.getModelInfo)(this.options.modelMeta, model, true);
782
+ }
783
+ getBaseModel(model) {
784
+ const baseNames = (0, cross_1.getModelInfo)(this.options.modelMeta, model, true).baseTypes;
785
+ if (!baseNames) {
786
+ return undefined;
787
+ }
788
+ if (baseNames.length > 1) {
789
+ throw new Error('Multi-inheritance is not supported');
790
+ }
791
+ return this.options.modelMeta.models[(0, lower_case_first_1.lowerCaseFirst)(baseNames[0])];
792
+ }
793
+ involvesDelegateModel(model, visited) {
794
+ if (this.isDelegateOrDescendantOfDelegate(model)) {
795
+ return true;
796
+ }
797
+ visited = visited !== null && visited !== void 0 ? visited : new Set();
798
+ if (visited.has(model)) {
799
+ return false;
800
+ }
801
+ visited.add(model);
802
+ const modelInfo = (0, cross_1.getModelInfo)(this.options.modelMeta, model, true);
803
+ return Object.values(modelInfo.fields).some((field) => field.isDataModel && this.involvesDelegateModel(field.type, visited));
804
+ }
805
+ isDelegateOrDescendantOfDelegate(model) {
806
+ var _a;
807
+ if ((0, cross_1.isDelegateModel)(this.options.modelMeta, model)) {
808
+ return true;
809
+ }
810
+ const baseTypes = (_a = (0, cross_1.getModelInfo)(this.options.modelMeta, model)) === null || _a === void 0 ? void 0 : _a.baseTypes;
811
+ return !!(baseTypes &&
812
+ baseTypes.length > 0 &&
813
+ baseTypes.some((base) => this.isDelegateOrDescendantOfDelegate(base)));
814
+ }
815
+ assembleHierarchy(model, entity) {
816
+ if (!entity || typeof entity !== 'object') {
817
+ return entity;
818
+ }
819
+ const result = {};
820
+ const base = this.getBaseModel(model);
821
+ if (base) {
822
+ // merge base fields
823
+ const baseRelationName = this.makeAuxRelationName(base);
824
+ const baseData = entity[baseRelationName];
825
+ if (baseData && typeof baseData === 'object') {
826
+ const baseAssembled = this.assembleHierarchy(base.name, baseData);
827
+ Object.assign(result, baseAssembled);
828
+ }
829
+ }
830
+ const modelInfo = (0, cross_1.getModelInfo)(this.options.modelMeta, model, true);
831
+ for (const field of Object.values(modelInfo.fields)) {
832
+ if (field.inheritedFrom) {
833
+ // already merged from base
834
+ continue;
835
+ }
836
+ if (field.name in entity) {
837
+ const fieldValue = entity[field.name];
838
+ if (field.isDataModel) {
839
+ if (Array.isArray(fieldValue)) {
840
+ result[field.name] = fieldValue.map((item) => this.assembleHierarchy(field.type, item));
841
+ }
842
+ else {
843
+ result[field.name] = this.assembleHierarchy(field.type, fieldValue);
844
+ }
845
+ }
846
+ else {
847
+ result[field.name] = fieldValue;
848
+ }
849
+ }
850
+ }
851
+ return result;
852
+ }
853
+ // #endregion
854
+ // #region backup
855
+ transformWhereHierarchy(where, contextModel, forModel) {
856
+ if (!where || typeof where !== 'object') {
857
+ return where;
858
+ }
859
+ let curr = contextModel;
860
+ const inheritStack = [];
861
+ while (curr) {
862
+ inheritStack.unshift(curr);
863
+ curr = this.getBaseModel(curr.name);
864
+ }
865
+ let result = {};
866
+ for (const [key, value] of Object.entries(where)) {
867
+ const fieldInfo = (0, cross_1.requireField)(this.options.modelMeta, contextModel.name, key);
868
+ const fieldHierarchy = this.transformFieldHierarchy(fieldInfo, value, contextModel, forModel, inheritStack);
869
+ result = (0, deepmerge_1.default)(result, fieldHierarchy);
870
+ }
871
+ return result;
872
+ }
873
+ transformFieldHierarchy(fieldInfo, value, contextModel, forModel, inheritStack) {
874
+ const fieldModel = fieldInfo.inheritedFrom ? this.getModelInfo(fieldInfo.inheritedFrom) : contextModel;
875
+ if (fieldModel === forModel) {
876
+ return { [fieldInfo.name]: value };
877
+ }
878
+ const fieldModelPos = inheritStack.findIndex((m) => m === fieldModel);
879
+ const forModelPos = inheritStack.findIndex((m) => m === forModel);
880
+ const result = {};
881
+ let curr = result;
882
+ if (fieldModelPos > forModelPos) {
883
+ // walk down hierarchy
884
+ for (let i = forModelPos + 1; i <= fieldModelPos; i++) {
885
+ const rel = this.makeAuxRelationName(inheritStack[i]);
886
+ curr[rel] = {};
887
+ curr = curr[rel];
888
+ }
889
+ }
890
+ else {
891
+ // walk up hierarchy
892
+ for (let i = forModelPos - 1; i >= fieldModelPos; i--) {
893
+ const rel = this.makeAuxRelationName(inheritStack[i]);
894
+ curr[rel] = {};
895
+ curr = curr[rel];
896
+ }
897
+ }
898
+ curr[fieldInfo.name] = value;
899
+ return result;
900
+ }
901
+ }
902
+ exports.DelegateProxyHandler = DelegateProxyHandler;
903
+ //# sourceMappingURL=delegate.js.map