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