@zenstackhq/runtime 3.0.0-alpha.2 → 3.0.0-alpha.20

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 (43) hide show
  1. package/dist/{contract-DguafRNB.d.cts → contract-XFKcwhq7.d.cts} +970 -785
  2. package/dist/{contract-DguafRNB.d.ts → contract-XFKcwhq7.d.ts} +970 -785
  3. package/dist/{utils/pg-utils.cjs → helpers.cjs} +8 -16
  4. package/dist/helpers.cjs.map +1 -0
  5. package/dist/helpers.d.cts +1 -0
  6. package/dist/helpers.d.ts +1 -0
  7. package/dist/helpers.js +6 -0
  8. package/dist/helpers.js.map +1 -0
  9. package/dist/index.cjs +1774 -892
  10. package/dist/index.cjs.map +1 -1
  11. package/dist/index.d.cts +28 -6
  12. package/dist/index.d.ts +28 -6
  13. package/dist/index.js +1724 -847
  14. package/dist/index.js.map +1 -1
  15. package/dist/plugins/{policy.cjs → policy/index.cjs} +463 -266
  16. package/dist/plugins/policy/index.cjs.map +1 -0
  17. package/dist/plugins/{policy.d.ts → policy/index.d.cts} +2 -4
  18. package/dist/plugins/{policy.d.cts → policy/index.d.ts} +2 -4
  19. package/dist/plugins/{policy.js → policy/index.js} +435 -228
  20. package/dist/plugins/policy/index.js.map +1 -0
  21. package/dist/plugins/policy/plugin.zmodel +33 -0
  22. package/dist/schema.cjs.map +1 -1
  23. package/dist/schema.js.map +1 -1
  24. package/package.json +27 -49
  25. package/dist/client.cjs +0 -6094
  26. package/dist/client.cjs.map +0 -1
  27. package/dist/client.d.cts +0 -19
  28. package/dist/client.d.ts +0 -19
  29. package/dist/client.js +0 -6060
  30. package/dist/client.js.map +0 -1
  31. package/dist/plugins/policy.cjs.map +0 -1
  32. package/dist/plugins/policy.js.map +0 -1
  33. package/dist/utils/pg-utils.cjs.map +0 -1
  34. package/dist/utils/pg-utils.d.cts +0 -8
  35. package/dist/utils/pg-utils.d.ts +0 -8
  36. package/dist/utils/pg-utils.js +0 -16
  37. package/dist/utils/pg-utils.js.map +0 -1
  38. package/dist/utils/sqlite-utils.cjs +0 -55
  39. package/dist/utils/sqlite-utils.cjs.map +0 -1
  40. package/dist/utils/sqlite-utils.d.cts +0 -8
  41. package/dist/utils/sqlite-utils.d.ts +0 -8
  42. package/dist/utils/sqlite-utils.js +0 -22
  43. package/dist/utils/sqlite-utils.js.map +0 -1
package/dist/index.js CHANGED
@@ -6,29 +6,133 @@ var __export = (target, all) => {
6
6
  };
7
7
 
8
8
  // src/client/client-impl.ts
9
- import { DefaultConnectionProvider, DefaultQueryExecutor as DefaultQueryExecutor2, Kysely, Log, PostgresDialect, SqliteDialect } from "kysely";
10
- import { match as match19 } from "ts-pattern";
9
+ import { invariant as invariant12, lowerCaseFirst as lowerCaseFirst2 } from "@zenstackhq/common-helpers";
10
+ import { CompiledQuery, DefaultConnectionProvider, DefaultQueryExecutor as DefaultQueryExecutor2, Kysely, Log, sql as sql10 } from "kysely";
11
11
 
12
12
  // src/client/crud/operations/aggregate.ts
13
13
  import { sql as sql5 } from "kysely";
14
- import { match as match9 } from "ts-pattern";
14
+ import { match as match10 } from "ts-pattern";
15
+
16
+ // src/client/query-utils.ts
17
+ import { match } from "ts-pattern";
18
+
19
+ // src/schema/expression.ts
20
+ var ExpressionUtils = {
21
+ literal: /* @__PURE__ */ __name((value) => {
22
+ return {
23
+ kind: "literal",
24
+ value
25
+ };
26
+ }, "literal"),
27
+ array: /* @__PURE__ */ __name((items) => {
28
+ return {
29
+ kind: "array",
30
+ items
31
+ };
32
+ }, "array"),
33
+ call: /* @__PURE__ */ __name((functionName, args) => {
34
+ return {
35
+ kind: "call",
36
+ function: functionName,
37
+ args
38
+ };
39
+ }, "call"),
40
+ binary: /* @__PURE__ */ __name((left, op, right) => {
41
+ return {
42
+ kind: "binary",
43
+ op,
44
+ left,
45
+ right
46
+ };
47
+ }, "binary"),
48
+ unary: /* @__PURE__ */ __name((op, operand) => {
49
+ return {
50
+ kind: "unary",
51
+ op,
52
+ operand
53
+ };
54
+ }, "unary"),
55
+ field: /* @__PURE__ */ __name((field) => {
56
+ return {
57
+ kind: "field",
58
+ field
59
+ };
60
+ }, "field"),
61
+ member: /* @__PURE__ */ __name((receiver, members) => {
62
+ return {
63
+ kind: "member",
64
+ receiver,
65
+ members
66
+ };
67
+ }, "member"),
68
+ _this: /* @__PURE__ */ __name(() => {
69
+ return {
70
+ kind: "this"
71
+ };
72
+ }, "_this"),
73
+ _null: /* @__PURE__ */ __name(() => {
74
+ return {
75
+ kind: "null"
76
+ };
77
+ }, "_null"),
78
+ and: /* @__PURE__ */ __name((expr2, ...expressions) => {
79
+ return expressions.reduce((acc, exp) => ExpressionUtils.binary(acc, "&&", exp), expr2);
80
+ }, "and"),
81
+ or: /* @__PURE__ */ __name((expr2, ...expressions) => {
82
+ return expressions.reduce((acc, exp) => ExpressionUtils.binary(acc, "||", exp), expr2);
83
+ }, "or"),
84
+ is: /* @__PURE__ */ __name((value, kind) => {
85
+ return !!value && typeof value === "object" && "kind" in value && value.kind === kind;
86
+ }, "is"),
87
+ isLiteral: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "literal"), "isLiteral"),
88
+ isArray: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "array"), "isArray"),
89
+ isCall: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "call"), "isCall"),
90
+ isNull: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "null"), "isNull"),
91
+ isThis: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "this"), "isThis"),
92
+ isUnary: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "unary"), "isUnary"),
93
+ isBinary: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "binary"), "isBinary"),
94
+ isField: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "field"), "isField"),
95
+ isMember: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "member"), "isMember")
96
+ };
97
+
98
+ // src/utils/object-utils.ts
99
+ function extractFields(obj, fields) {
100
+ return Object.fromEntries(Object.entries(obj).filter(([key]) => fields.includes(key)));
101
+ }
102
+ __name(extractFields, "extractFields");
103
+ function fieldsToSelectObject(fields) {
104
+ return Object.fromEntries(fields.map((f) => [
105
+ f,
106
+ true
107
+ ]));
108
+ }
109
+ __name(fieldsToSelectObject, "fieldsToSelectObject");
15
110
 
16
111
  // src/client/errors.ts
112
+ var InputValidationError = class extends Error {
113
+ static {
114
+ __name(this, "InputValidationError");
115
+ }
116
+ constructor(message, cause) {
117
+ super(message, {
118
+ cause
119
+ });
120
+ }
121
+ };
17
122
  var QueryError = class extends Error {
18
123
  static {
19
124
  __name(this, "QueryError");
20
125
  }
21
- constructor(message) {
22
- super(message);
126
+ constructor(message, cause) {
127
+ super(message, {
128
+ cause
129
+ });
23
130
  }
24
131
  };
25
132
  var InternalError = class extends Error {
26
133
  static {
27
134
  __name(this, "InternalError");
28
135
  }
29
- constructor(message) {
30
- super(message);
31
- }
32
136
  };
33
137
  var NotFoundError = class extends Error {
34
138
  static {
@@ -47,7 +151,7 @@ __name(getModel, "getModel");
47
151
  function requireModel(schema, model) {
48
152
  const matchedName = Object.keys(schema.models).find((k) => k.toLowerCase() === model.toLowerCase());
49
153
  if (!matchedName) {
50
- throw new QueryError(`Model "${model}" not found`);
154
+ throw new QueryError(`Model "${model}" not found in schema`);
51
155
  }
52
156
  return schema.models[matchedName];
53
157
  }
@@ -111,20 +215,25 @@ function getRelationForeignKeyFieldPairs(schema, model, relationField) {
111
215
  }
112
216
  __name(getRelationForeignKeyFieldPairs, "getRelationForeignKeyFieldPairs");
113
217
  function isScalarField(schema, model, field) {
114
- const fieldDef = requireField(schema, model, field);
115
- return !fieldDef.relation && !fieldDef.foreignKeyFor;
218
+ const fieldDef = getField(schema, model, field);
219
+ return !fieldDef?.relation && !fieldDef?.foreignKeyFor;
116
220
  }
117
221
  __name(isScalarField, "isScalarField");
118
222
  function isForeignKeyField(schema, model, field) {
119
- const fieldDef = requireField(schema, model, field);
120
- return !!fieldDef.foreignKeyFor;
223
+ const fieldDef = getField(schema, model, field);
224
+ return !!fieldDef?.foreignKeyFor;
121
225
  }
122
226
  __name(isForeignKeyField, "isForeignKeyField");
123
227
  function isRelationField(schema, model, field) {
124
- const fieldDef = requireField(schema, model, field);
125
- return !!fieldDef.relation;
228
+ const fieldDef = getField(schema, model, field);
229
+ return !!fieldDef?.relation;
126
230
  }
127
231
  __name(isRelationField, "isRelationField");
232
+ function isInheritedField(schema, model, field) {
233
+ const fieldDef = getField(schema, model, field);
234
+ return !!fieldDef?.originModel;
235
+ }
236
+ __name(isInheritedField, "isInheritedField");
128
237
  function getUniqueFields(schema, model) {
129
238
  const modelDef = requireModel(schema, model);
130
239
  const result = [];
@@ -172,7 +281,7 @@ function buildFieldRef(schema, model, field, options, eb, modelAlias) {
172
281
  computer = computedFields?.[model]?.[field];
173
282
  }
174
283
  if (!computer) {
175
- throw new QueryError(`Computed field "${field}" implementation not provided`);
284
+ throw new QueryError(`Computed field "${field}" implementation not provided for model "${model}"`);
176
285
  }
177
286
  return computer(eb);
178
287
  }
@@ -277,13 +386,49 @@ function safeJSONStringify(value) {
277
386
  });
278
387
  }
279
388
  __name(safeJSONStringify, "safeJSONStringify");
389
+ function extractIdFields(entity, schema, model) {
390
+ const idFields = getIdFields(schema, model);
391
+ return extractFields(entity, idFields);
392
+ }
393
+ __name(extractIdFields, "extractIdFields");
394
+ function getDiscriminatorField(schema, model) {
395
+ const modelDef = requireModel(schema, model);
396
+ const delegateAttr = modelDef.attributes?.find((attr) => attr.name === "@@delegate");
397
+ if (!delegateAttr) {
398
+ return void 0;
399
+ }
400
+ const discriminator = delegateAttr.args?.find((arg) => arg.name === "discriminator");
401
+ if (!discriminator || !ExpressionUtils.isField(discriminator.value)) {
402
+ throw new InternalError(`Discriminator field not defined for model "${model}"`);
403
+ }
404
+ return discriminator.value.field;
405
+ }
406
+ __name(getDiscriminatorField, "getDiscriminatorField");
407
+ function getDelegateDescendantModels(schema, model, collected = /* @__PURE__ */ new Set()) {
408
+ const subModels = Object.values(schema.models).filter((m) => m.baseModel === model);
409
+ subModels.forEach((def) => {
410
+ if (!collected.has(def)) {
411
+ collected.add(def);
412
+ getDelegateDescendantModels(schema, def.name, collected);
413
+ }
414
+ });
415
+ return [
416
+ ...collected
417
+ ];
418
+ }
419
+ __name(getDelegateDescendantModels, "getDelegateDescendantModels");
420
+ function aggregate(eb, expr2, op) {
421
+ return match(op).with("_count", () => eb.fn.count(expr2)).with("_sum", () => eb.fn.sum(expr2)).with("_avg", () => eb.fn.avg(expr2)).with("_min", () => eb.fn.min(expr2)).with("_max", () => eb.fn.max(expr2)).exhaustive();
422
+ }
423
+ __name(aggregate, "aggregate");
280
424
 
281
425
  // src/client/crud/operations/base.ts
282
426
  import { createId } from "@paralleldrive/cuid2";
427
+ import { invariant as invariant7, isPlainObject as isPlainObject3 } from "@zenstackhq/common-helpers";
283
428
  import { expressionBuilder as expressionBuilder2, sql as sql4 } from "kysely";
284
429
  import { nanoid } from "nanoid";
285
- import invariant7 from "tiny-invariant";
286
- import { match as match8 } from "ts-pattern";
430
+ import { inspect } from "util";
431
+ import { match as match9 } from "ts-pattern";
287
432
  import { ulid } from "ulid";
288
433
  import * as uuid from "uuid";
289
434
 
@@ -300,22 +445,44 @@ var RejectedByPolicyError = class extends Error {
300
445
  };
301
446
 
302
447
  // src/plugins/policy/policy-handler.ts
448
+ import { invariant as invariant6 } from "@zenstackhq/common-helpers";
303
449
  import { AliasNode as AliasNode3, BinaryOperationNode as BinaryOperationNode3, ColumnNode as ColumnNode2, DeleteQueryNode, FromNode as FromNode2, IdentifierNode as IdentifierNode2, InsertQueryNode, OperationNodeTransformer, OperatorNode as OperatorNode3, PrimitiveValueListNode, RawNode, ReturningNode, SelectionNode as SelectionNode2, SelectQueryNode as SelectQueryNode2, TableNode as TableNode3, UpdateQueryNode, ValueNode as ValueNode3, ValuesNode, WhereNode as WhereNode2 } from "kysely";
304
- import invariant6 from "tiny-invariant";
305
- import { match as match7 } from "ts-pattern";
450
+ import { match as match8 } from "ts-pattern";
306
451
 
307
452
  // src/client/crud/dialects/index.ts
308
- import { match as match4 } from "ts-pattern";
453
+ import { match as match5 } from "ts-pattern";
309
454
 
310
455
  // src/client/crud/dialects/postgresql.ts
456
+ import { invariant as invariant2 } from "@zenstackhq/common-helpers";
311
457
  import { sql as sql2 } from "kysely";
312
- import invariant2 from "tiny-invariant";
313
- import { match as match2 } from "ts-pattern";
458
+ import { match as match3 } from "ts-pattern";
459
+
460
+ // src/client/constants.ts
461
+ var CONTEXT_COMMENT_PREFIX = "-- $$context:";
462
+ var NUMERIC_FIELD_TYPES = [
463
+ "Int",
464
+ "Float",
465
+ "BigInt",
466
+ "Decimal"
467
+ ];
468
+ var DELEGATE_JOINED_FIELD_PREFIX = "$delegate$";
469
+ var LOGICAL_COMBINATORS = [
470
+ "AND",
471
+ "OR",
472
+ "NOT"
473
+ ];
474
+ var AGGREGATE_OPERATORS = [
475
+ "_count",
476
+ "_sum",
477
+ "_avg",
478
+ "_min",
479
+ "_max"
480
+ ];
314
481
 
315
482
  // src/client/crud/dialects/base.ts
483
+ import { invariant, isPlainObject } from "@zenstackhq/common-helpers";
316
484
  import { sql } from "kysely";
317
- import invariant from "tiny-invariant";
318
- import { match, P } from "ts-pattern";
485
+ import { match as match2, P } from "ts-pattern";
319
486
 
320
487
  // src/utils/enumerate.ts
321
488
  function enumerate(x) {
@@ -332,7 +499,6 @@ function enumerate(x) {
332
499
  __name(enumerate, "enumerate");
333
500
 
334
501
  // src/client/crud/dialects/base.ts
335
- import { isPlainObject } from "is-plain-object";
336
502
  var BaseCrudDialect = class {
337
503
  static {
338
504
  __name(this, "BaseCrudDialect");
@@ -343,9 +509,20 @@ var BaseCrudDialect = class {
343
509
  this.schema = schema;
344
510
  this.options = options;
345
511
  }
346
- transformPrimitive(value, _type) {
512
+ transformPrimitive(value, _type, _forArrayField) {
347
513
  return value;
348
514
  }
515
+ // #region common query builders
516
+ buildSelectModel(eb, model) {
517
+ const modelDef = requireModel(this.schema, model);
518
+ let result = eb.selectFrom(model);
519
+ let joinBase = modelDef.baseModel;
520
+ while (joinBase) {
521
+ result = this.buildDelegateJoin(model, joinBase, result);
522
+ joinBase = requireModel(this.schema, joinBase).baseModel;
523
+ }
524
+ return result;
525
+ }
349
526
  buildFilter(eb, model, modelAlias, where) {
350
527
  if (where === true || where === void 0) {
351
528
  return this.true(eb);
@@ -362,17 +539,20 @@ var BaseCrudDialect = class {
362
539
  if (key.startsWith("$")) {
363
540
  continue;
364
541
  }
365
- if (key === "AND" || key === "OR" || key === "NOT") {
542
+ if (this.isLogicalCombinator(key)) {
366
543
  result = this.and(eb, result, this.buildCompositeFilter(eb, model, modelAlias, key, payload));
367
544
  continue;
368
545
  }
369
546
  const fieldDef = requireField(this.schema, model, key);
370
547
  if (fieldDef.relation) {
371
548
  result = this.and(eb, result, this.buildRelationFilter(eb, model, modelAlias, key, fieldDef, payload));
372
- } else if (fieldDef.array) {
373
- result = this.and(eb, result, this.buildArrayFilter(eb, model, modelAlias, key, fieldDef, payload));
374
549
  } else {
375
- result = this.and(eb, result, this.buildPrimitiveFilter(eb, model, modelAlias, key, fieldDef, payload));
550
+ const fieldRef = buildFieldRef(this.schema, fieldDef.originModel ?? model, key, this.options, eb, fieldDef.originModel ?? modelAlias);
551
+ if (fieldDef.array) {
552
+ result = this.and(eb, result, this.buildArrayFilter(eb, fieldRef, fieldDef, payload));
553
+ } else {
554
+ result = this.and(eb, result, this.buildPrimitiveFilter(eb, fieldRef, fieldDef, payload));
555
+ }
376
556
  }
377
557
  }
378
558
  if ("$expr" in _where && typeof _where["$expr"] === "function") {
@@ -380,8 +560,11 @@ var BaseCrudDialect = class {
380
560
  }
381
561
  return result;
382
562
  }
563
+ isLogicalCombinator(key) {
564
+ return LOGICAL_COMBINATORS.includes(key);
565
+ }
383
566
  buildCompositeFilter(eb, model, modelAlias, key, payload) {
384
- return match(key).with("AND", () => this.and(eb, ...enumerate(payload).map((subPayload) => this.buildFilter(eb, model, modelAlias, subPayload)))).with("OR", () => this.or(eb, ...enumerate(payload).map((subPayload) => this.buildFilter(eb, model, modelAlias, subPayload)))).with("NOT", () => eb.not(this.buildCompositeFilter(eb, model, modelAlias, "AND", payload))).exhaustive();
567
+ return match2(key).with("AND", () => this.and(eb, ...enumerate(payload).map((subPayload) => this.buildFilter(eb, model, modelAlias, subPayload)))).with("OR", () => this.or(eb, ...enumerate(payload).map((subPayload) => this.buildFilter(eb, model, modelAlias, subPayload)))).with("NOT", () => eb.not(this.buildCompositeFilter(eb, model, modelAlias, "AND", payload))).exhaustive();
385
568
  }
386
569
  buildRelationFilter(eb, model, modelAlias, field, fieldDef, payload) {
387
570
  if (!fieldDef.array) {
@@ -390,19 +573,26 @@ var BaseCrudDialect = class {
390
573
  return this.buildToManyRelationFilter(eb, model, modelAlias, field, fieldDef, payload);
391
574
  }
392
575
  }
393
- buildToOneRelationFilter(eb, model, table, field, fieldDef, payload) {
576
+ buildToOneRelationFilter(eb, model, modelAlias, field, fieldDef, payload) {
394
577
  if (payload === null) {
395
578
  const { ownedByModel, keyPairs } = getRelationForeignKeyFieldPairs(this.schema, model, field);
396
- if (ownedByModel) {
397
- return this.and(eb, ...keyPairs.map(({ fk }) => eb(sql.ref(`${table}.${fk}`), "is", null)));
579
+ if (ownedByModel && !fieldDef.originModel) {
580
+ return this.and(eb, ...keyPairs.map(({ fk }) => eb(sql.ref(`${modelAlias}.${fk}`), "is", null)));
398
581
  } else {
399
- return this.buildToOneRelationFilter(eb, model, table, field, fieldDef, {
582
+ return this.buildToOneRelationFilter(eb, model, modelAlias, field, fieldDef, {
400
583
  is: null
401
584
  });
402
585
  }
403
586
  }
404
- const joinAlias = `${table}$${field}`;
405
- const joinPairs = buildJoinPairs(this.schema, model, table, field, joinAlias);
587
+ const joinAlias = `${modelAlias}$${field}`;
588
+ const joinPairs = buildJoinPairs(
589
+ this.schema,
590
+ model,
591
+ // if field is from a base, use the base model to join
592
+ fieldDef.originModel ?? modelAlias,
593
+ field,
594
+ joinAlias
595
+ );
406
596
  const filterResultField = `${field}$filter`;
407
597
  const joinSelect = eb.selectFrom(`${fieldDef.type} as ${joinAlias}`).where(() => this.and(eb, ...joinPairs.map(([left, right]) => eb(sql.ref(left), "=", sql.ref(right))))).select(() => eb.fn.count(eb.lit(1)).as(filterResultField));
408
598
  const conditions = [];
@@ -463,30 +653,29 @@ var BaseCrudDialect = class {
463
653
  }
464
654
  switch (key) {
465
655
  case "some": {
466
- result = this.and(eb, result, eb(eb.selectFrom(relationModel).select((eb1) => eb1.fn.count(eb1.lit(1)).as("count")).where(buildPkFkWhereRefs(eb)).where((eb1) => this.buildFilter(eb1, relationModel, relationModel, subPayload)), ">", 0));
656
+ result = this.and(eb, result, eb(this.buildSelectModel(eb, relationModel).select((eb1) => eb1.fn.count(eb1.lit(1)).as("$count")).where(buildPkFkWhereRefs(eb)).where((eb1) => this.buildFilter(eb1, relationModel, relationModel, subPayload)), ">", 0));
467
657
  break;
468
658
  }
469
659
  case "every": {
470
- result = this.and(eb, result, eb(eb.selectFrom(relationModel).select((eb1) => eb1.fn.count(eb1.lit(1)).as("count")).where(buildPkFkWhereRefs(eb)).where((eb1) => eb1.not(this.buildFilter(eb1, relationModel, relationModel, subPayload))), "=", 0));
660
+ result = this.and(eb, result, eb(this.buildSelectModel(eb, relationModel).select((eb1) => eb1.fn.count(eb1.lit(1)).as("$count")).where(buildPkFkWhereRefs(eb)).where((eb1) => eb1.not(this.buildFilter(eb1, relationModel, relationModel, subPayload))), "=", 0));
471
661
  break;
472
662
  }
473
663
  case "none": {
474
- result = this.and(eb, result, eb(eb.selectFrom(relationModel).select((eb1) => eb1.fn.count(eb1.lit(1)).as("count")).where(buildPkFkWhereRefs(eb)).where((eb1) => this.buildFilter(eb1, relationModel, relationModel, subPayload)), "=", 0));
664
+ result = this.and(eb, result, eb(this.buildSelectModel(eb, relationModel).select((eb1) => eb1.fn.count(eb1.lit(1)).as("$count")).where(buildPkFkWhereRefs(eb)).where((eb1) => this.buildFilter(eb1, relationModel, relationModel, subPayload)), "=", 0));
475
665
  break;
476
666
  }
477
667
  }
478
668
  }
479
669
  return result;
480
670
  }
481
- buildArrayFilter(eb, model, modelAlias, field, fieldDef, payload) {
671
+ buildArrayFilter(eb, fieldRef, fieldDef, payload) {
482
672
  const clauses = [];
483
673
  const fieldType = fieldDef.type;
484
- const fieldRef = buildFieldRef(this.schema, model, field, this.options, eb, modelAlias);
485
674
  for (const [key, _value] of Object.entries(payload)) {
486
675
  if (_value === void 0) {
487
676
  continue;
488
677
  }
489
- const value = this.transformPrimitive(_value, fieldType);
678
+ const value = this.transformPrimitive(_value, fieldType, !!fieldDef.array);
490
679
  switch (key) {
491
680
  case "equals": {
492
681
  clauses.push(this.buildLiteralFilter(eb, fieldRef, fieldType, eb.val(value)));
@@ -517,19 +706,23 @@ var BaseCrudDialect = class {
517
706
  }
518
707
  return this.and(eb, ...clauses);
519
708
  }
520
- buildPrimitiveFilter(eb, model, modelAlias, field, fieldDef, payload) {
709
+ buildPrimitiveFilter(eb, fieldRef, fieldDef, payload) {
521
710
  if (payload === null) {
522
- return eb(sql.ref(`${modelAlias}.${field}`), "is", null);
711
+ return eb(fieldRef, "is", null);
523
712
  }
524
713
  if (isEnum(this.schema, fieldDef.type)) {
525
- return this.buildEnumFilter(eb, modelAlias, field, fieldDef, payload);
714
+ return this.buildEnumFilter(eb, fieldRef, fieldDef, payload);
526
715
  }
527
- return match(fieldDef.type).with("String", () => this.buildStringFilter(eb, modelAlias, field, payload)).with(P.union("Int", "Float", "Decimal", "BigInt"), (type) => this.buildNumberFilter(eb, model, modelAlias, field, type, payload)).with("Boolean", () => this.buildBooleanFilter(eb, modelAlias, field, payload)).with("DateTime", () => this.buildDateTimeFilter(eb, modelAlias, field, payload)).with("Bytes", () => this.buildBytesFilter(eb, modelAlias, field, payload)).exhaustive();
716
+ return match2(fieldDef.type).with("String", () => this.buildStringFilter(eb, fieldRef, payload)).with(P.union("Int", "Float", "Decimal", "BigInt"), (type) => this.buildNumberFilter(eb, fieldRef, type, payload)).with("Boolean", () => this.buildBooleanFilter(eb, fieldRef, payload)).with("DateTime", () => this.buildDateTimeFilter(eb, fieldRef, payload)).with("Bytes", () => this.buildBytesFilter(eb, fieldRef, payload)).with("Json", () => {
717
+ throw new InternalError("JSON filters are not supported yet");
718
+ }).with("Unsupported", () => {
719
+ throw new QueryError(`Unsupported field cannot be used in filters`);
720
+ }).exhaustive();
528
721
  }
529
722
  buildLiteralFilter(eb, lhs, type, rhs) {
530
- return eb(lhs, "=", rhs !== null && rhs !== void 0 ? this.transformPrimitive(rhs, type) : rhs);
723
+ return eb(lhs, "=", rhs !== null && rhs !== void 0 ? this.transformPrimitive(rhs, type, false) : rhs);
531
724
  }
532
- buildStandardFilter(eb, type, payload, lhs, getRhs, recurse, throwIfInvalid = false, onlyForKeys = void 0) {
725
+ buildStandardFilter(eb, type, payload, lhs, getRhs, recurse, throwIfInvalid = false, onlyForKeys = void 0, excludeKeys = []) {
533
726
  if (payload === null || !isPlainObject(payload)) {
534
727
  return {
535
728
  conditions: [
@@ -544,8 +737,11 @@ var BaseCrudDialect = class {
544
737
  if (onlyForKeys && !onlyForKeys.includes(op)) {
545
738
  continue;
546
739
  }
740
+ if (excludeKeys.includes(op)) {
741
+ continue;
742
+ }
547
743
  const rhs = Array.isArray(value) ? value.map(getRhs) : getRhs(value);
548
- const condition = match(op).with("equals", () => rhs === null ? eb(lhs, "is", null) : eb(lhs, "=", rhs)).with("in", () => {
744
+ const condition = match2(op).with("equals", () => rhs === null ? eb(lhs, "is", null) : eb(lhs, "=", rhs)).with("in", () => {
549
745
  invariant(Array.isArray(rhs), "right hand side must be an array");
550
746
  if (rhs.length === 0) {
551
747
  return this.false(eb);
@@ -559,7 +755,11 @@ var BaseCrudDialect = class {
559
755
  } else {
560
756
  return eb.not(eb(lhs, "in", rhs));
561
757
  }
562
- }).with("lt", () => eb(lhs, "<", rhs)).with("lte", () => eb(lhs, "<=", rhs)).with("gt", () => eb(lhs, ">", rhs)).with("gte", () => eb(lhs, ">=", rhs)).with("not", () => eb.not(recurse(value))).otherwise(() => {
758
+ }).with("lt", () => eb(lhs, "<", rhs)).with("lte", () => eb(lhs, "<=", rhs)).with("gt", () => eb(lhs, ">", rhs)).with("gte", () => eb(lhs, ">=", rhs)).with("not", () => eb.not(recurse(value))).with(P.union(...AGGREGATE_OPERATORS), (op2) => {
759
+ const innerResult = this.buildStandardFilter(eb, type, value, aggregate(eb, lhs, op2), getRhs, recurse, throwIfInvalid);
760
+ consumedKeys.push(...innerResult.consumedKeys);
761
+ return this.and(eb, ...innerResult.conditions);
762
+ }).otherwise(() => {
563
763
  if (throwIfInvalid) {
564
764
  throw new QueryError(`Invalid filter key: ${op}`);
565
765
  } else {
@@ -576,24 +776,21 @@ var BaseCrudDialect = class {
576
776
  consumedKeys
577
777
  };
578
778
  }
579
- buildStringFilter(eb, table, field, payload) {
580
- const fieldDef = getField(this.schema, table, field);
581
- let fieldRef = fieldDef?.computed ? sql.ref(field) : sql.ref(`${table}.${field}`);
582
- let insensitive = false;
583
- if (payload && typeof payload === "object" && "mode" in payload && payload.mode === "insensitive") {
584
- insensitive = true;
585
- fieldRef = eb.fn("lower", [
586
- fieldRef
587
- ]);
779
+ buildStringFilter(eb, fieldRef, payload) {
780
+ let mode;
781
+ if (payload && typeof payload === "object" && "mode" in payload) {
782
+ mode = payload.mode;
588
783
  }
589
- const { conditions, consumedKeys } = this.buildStandardFilter(eb, "String", payload, fieldRef, (value) => this.prepStringCasing(eb, value, insensitive), (value) => this.buildStringFilter(eb, table, field, value));
784
+ const { conditions, consumedKeys } = this.buildStandardFilter(eb, "String", payload, mode === "insensitive" ? eb.fn("lower", [
785
+ fieldRef
786
+ ]) : fieldRef, (value) => this.prepStringCasing(eb, value, mode), (value) => this.buildStringFilter(eb, fieldRef, value));
590
787
  if (payload && typeof payload === "object") {
591
788
  for (const [key, value] of Object.entries(payload)) {
592
789
  if (key === "mode" || consumedKeys.includes(key)) {
593
790
  continue;
594
791
  }
595
- const condition = match(key).with("contains", () => insensitive ? eb(fieldRef, "ilike", sql.lit(`%${value}%`)) : eb(fieldRef, "like", sql.lit(`%${value}%`))).with("startsWith", () => insensitive ? eb(fieldRef, "ilike", sql.lit(`${value}%`)) : eb(fieldRef, "like", sql.lit(`${value}%`))).with("endsWith", () => insensitive ? eb(fieldRef, "ilike", sql.lit(`%${value}`)) : eb(fieldRef, "like", sql.lit(`%${value}`))).otherwise(() => {
596
- throw new Error(`Invalid string filter key: ${key}`);
792
+ const condition = match2(key).with("contains", () => mode === "insensitive" ? eb(fieldRef, "ilike", sql.val(`%${value}%`)) : eb(fieldRef, "like", sql.val(`%${value}%`))).with("startsWith", () => mode === "insensitive" ? eb(fieldRef, "ilike", sql.val(`${value}%`)) : eb(fieldRef, "like", sql.val(`${value}%`))).with("endsWith", () => mode === "insensitive" ? eb(fieldRef, "ilike", sql.val(`%${value}`)) : eb(fieldRef, "like", sql.val(`%${value}`))).otherwise(() => {
793
+ throw new QueryError(`Invalid string filter key: ${key}`);
597
794
  });
598
795
  if (condition) {
599
796
  conditions.push(condition);
@@ -602,34 +799,37 @@ var BaseCrudDialect = class {
602
799
  }
603
800
  return this.and(eb, ...conditions);
604
801
  }
605
- prepStringCasing(eb, value, toLower = true) {
802
+ prepStringCasing(eb, value, mode) {
803
+ if (!mode || mode === "default") {
804
+ return value === null ? value : sql.val(value);
805
+ }
606
806
  if (typeof value === "string") {
607
- return toLower ? eb.fn("lower", [
608
- sql.lit(value)
609
- ]) : sql.lit(value);
807
+ return eb.fn("lower", [
808
+ sql.val(value)
809
+ ]);
610
810
  } else if (Array.isArray(value)) {
611
- return value.map((v) => this.prepStringCasing(eb, v, toLower));
811
+ return value.map((v) => this.prepStringCasing(eb, v, mode));
612
812
  } else {
613
- return value === null ? null : sql.lit(value);
813
+ return value === null ? null : sql.val(value);
614
814
  }
615
815
  }
616
- buildNumberFilter(eb, model, table, field, type, payload) {
617
- const { conditions } = this.buildStandardFilter(eb, type, payload, buildFieldRef(this.schema, model, field, this.options, eb), (value) => this.transformPrimitive(value, type), (value) => this.buildNumberFilter(eb, model, table, field, type, value));
816
+ buildNumberFilter(eb, fieldRef, type, payload) {
817
+ const { conditions } = this.buildStandardFilter(eb, type, payload, fieldRef, (value) => this.transformPrimitive(value, type, false), (value) => this.buildNumberFilter(eb, fieldRef, type, value));
618
818
  return this.and(eb, ...conditions);
619
819
  }
620
- buildBooleanFilter(eb, table, field, payload) {
621
- const { conditions } = this.buildStandardFilter(eb, "Boolean", payload, sql.ref(`${table}.${field}`), (value) => this.transformPrimitive(value, "Boolean"), (value) => this.buildBooleanFilter(eb, table, field, value), true, [
820
+ buildBooleanFilter(eb, fieldRef, payload) {
821
+ const { conditions } = this.buildStandardFilter(eb, "Boolean", payload, fieldRef, (value) => this.transformPrimitive(value, "Boolean", false), (value) => this.buildBooleanFilter(eb, fieldRef, value), true, [
622
822
  "equals",
623
823
  "not"
624
824
  ]);
625
825
  return this.and(eb, ...conditions);
626
826
  }
627
- buildDateTimeFilter(eb, table, field, payload) {
628
- const { conditions } = this.buildStandardFilter(eb, "DateTime", payload, sql.ref(`${table}.${field}`), (value) => this.transformPrimitive(value, "DateTime"), (value) => this.buildDateTimeFilter(eb, table, field, value), true);
827
+ buildDateTimeFilter(eb, fieldRef, payload) {
828
+ const { conditions } = this.buildStandardFilter(eb, "DateTime", payload, fieldRef, (value) => this.transformPrimitive(value, "DateTime", false), (value) => this.buildDateTimeFilter(eb, fieldRef, value), true);
629
829
  return this.and(eb, ...conditions);
630
830
  }
631
- buildBytesFilter(eb, table, field, payload) {
632
- const conditions = this.buildStandardFilter(eb, "Bytes", payload, sql.ref(`${table}.${field}`), (value) => this.transformPrimitive(value, "Bytes"), (value) => this.buildBytesFilter(eb, table, field, value), true, [
831
+ buildBytesFilter(eb, fieldRef, payload) {
832
+ const conditions = this.buildStandardFilter(eb, "Bytes", payload, fieldRef, (value) => this.transformPrimitive(value, "Bytes", false), (value) => this.buildBytesFilter(eb, fieldRef, value), true, [
633
833
  "equals",
634
834
  "in",
635
835
  "notIn",
@@ -637,8 +837,8 @@ var BaseCrudDialect = class {
637
837
  ]);
638
838
  return this.and(eb, ...conditions.conditions);
639
839
  }
640
- buildEnumFilter(eb, table, field, fieldDef, payload) {
641
- const conditions = this.buildStandardFilter(eb, "String", payload, sql.ref(`${table}.${field}`), (value) => value, (value) => this.buildEnumFilter(eb, table, field, fieldDef, value), true, [
840
+ buildEnumFilter(eb, fieldRef, fieldDef, payload) {
841
+ const conditions = this.buildStandardFilter(eb, "String", payload, fieldRef, (value) => value, (value) => this.buildEnumFilter(eb, fieldRef, fieldDef, value), true, [
642
842
  "equals",
643
843
  "in",
644
844
  "notIn",
@@ -670,9 +870,7 @@ var BaseCrudDialect = class {
670
870
  invariant(value && typeof value === "object", `invalid orderBy value for field "${field}"`);
671
871
  for (const [k, v] of Object.entries(value)) {
672
872
  invariant(v === "asc" || v === "desc", `invalid orderBy value for field "${field}"`);
673
- result = result.orderBy((eb) => eb.fn(field.slice(1), [
674
- sql.ref(k)
675
- ]), sql.raw(this.negateSort(v, negated)));
873
+ result = result.orderBy((eb) => aggregate(eb, sql.ref(`${modelAlias}.${k}`), field), sql.raw(this.negateSort(v, negated)));
676
874
  }
677
875
  continue;
678
876
  }
@@ -705,7 +903,7 @@ var BaseCrudDialect = class {
705
903
  invariant(value._count === "asc" || value._count === "desc", 'invalid orderBy value for field "_count"');
706
904
  const sort = this.negateSort(value._count, negated);
707
905
  result = result.orderBy((eb) => {
708
- let subQuery = eb.selectFrom(relationModel);
906
+ let subQuery = this.buildSelectModel(eb, relationModel);
709
907
  const joinPairs = buildJoinPairs(this.schema, model, modelAlias, field, relationModel);
710
908
  subQuery = subQuery.where(() => this.and(eb, ...joinPairs.map(([left, right]) => eb(sql.ref(left), "=", sql.ref(right)))));
711
909
  subQuery = subQuery.select(() => eb.fn.count(eb.lit(1)).as("_count"));
@@ -724,14 +922,90 @@ var BaseCrudDialect = class {
724
922
  });
725
923
  return result;
726
924
  }
925
+ buildSelectAllFields(model, query, omit) {
926
+ const modelDef = requireModel(this.schema, model);
927
+ let result = query;
928
+ for (const field of Object.keys(modelDef.fields)) {
929
+ if (isRelationField(this.schema, model, field)) {
930
+ continue;
931
+ }
932
+ if (omit?.[field] === true) {
933
+ continue;
934
+ }
935
+ result = this.buildSelectField(result, model, model, field);
936
+ }
937
+ const descendants = getDelegateDescendantModels(this.schema, model);
938
+ for (const subModel of descendants) {
939
+ result = this.buildDelegateJoin(model, subModel.name, result);
940
+ result = result.select((eb) => {
941
+ const jsonObject = {};
942
+ for (const field of Object.keys(subModel.fields)) {
943
+ if (isRelationField(this.schema, subModel.name, field) || isInheritedField(this.schema, subModel.name, field)) {
944
+ continue;
945
+ }
946
+ jsonObject[field] = eb.ref(`${subModel.name}.${field}`);
947
+ }
948
+ return this.buildJsonObject(eb, jsonObject).as(`${DELEGATE_JOINED_FIELD_PREFIX}${subModel.name}`);
949
+ });
950
+ }
951
+ return result;
952
+ }
953
+ buildSelectField(query, model, modelAlias, field) {
954
+ const fieldDef = requireField(this.schema, model, field);
955
+ if (fieldDef.computed) {
956
+ return query.select((eb) => buildFieldRef(this.schema, model, field, this.options, eb).as(field));
957
+ } else if (!fieldDef.originModel) {
958
+ return query.select(sql.ref(`${modelAlias}.${field}`).as(field));
959
+ } else {
960
+ return this.buildSelectField(query, fieldDef.originModel, fieldDef.originModel, field);
961
+ }
962
+ }
963
+ buildDelegateJoin(thisModel, otherModel, query) {
964
+ const idFields = getIdFields(this.schema, thisModel);
965
+ query = query.leftJoin(otherModel, (qb) => {
966
+ for (const idField of idFields) {
967
+ qb = qb.onRef(`${thisModel}.${idField}`, "=", `${otherModel}.${idField}`);
968
+ }
969
+ return qb;
970
+ });
971
+ return query;
972
+ }
973
+ buildCountJson(model, eb, parentAlias, payload) {
974
+ const modelDef = requireModel(this.schema, model);
975
+ const toManyRelations = Object.entries(modelDef.fields).filter(([, field]) => field.relation && field.array);
976
+ const selections = payload === true ? {
977
+ select: toManyRelations.reduce((acc, [field]) => {
978
+ acc[field] = true;
979
+ return acc;
980
+ }, {})
981
+ } : payload;
982
+ const jsonObject = {};
983
+ for (const [field, value] of Object.entries(selections.select)) {
984
+ const fieldDef = requireField(this.schema, model, field);
985
+ const fieldModel = fieldDef.type;
986
+ const joinPairs = buildJoinPairs(this.schema, model, parentAlias, field, fieldModel);
987
+ let fieldCountQuery = eb.selectFrom(fieldModel).select(eb.fn.countAll().as(`_count$${field}`));
988
+ for (const [left, right] of joinPairs) {
989
+ fieldCountQuery = fieldCountQuery.whereRef(left, "=", right);
990
+ }
991
+ if (value && typeof value === "object" && "where" in value && value.where && typeof value.where === "object") {
992
+ const filter = this.buildFilter(eb, fieldModel, fieldModel, value.where);
993
+ fieldCountQuery = fieldCountQuery.where(filter);
994
+ }
995
+ jsonObject[field] = fieldCountQuery;
996
+ }
997
+ return this.buildJsonObject(eb, jsonObject);
998
+ }
999
+ // #endregion
1000
+ // #region utils
727
1001
  negateSort(sort, negated) {
728
1002
  return negated ? sort === "asc" ? "desc" : "asc" : sort;
729
1003
  }
730
1004
  true(eb) {
731
- return eb.lit(this.transformPrimitive(true, "Boolean"));
1005
+ return eb.lit(this.transformPrimitive(true, "Boolean", false));
732
1006
  }
733
1007
  false(eb) {
734
- return eb.lit(this.transformPrimitive(false, "Boolean"));
1008
+ return eb.lit(this.transformPrimitive(false, "Boolean", false));
735
1009
  }
736
1010
  isTrue(expression) {
737
1011
  const node = expression.toOperationNode();
@@ -780,14 +1054,18 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
780
1054
  get provider() {
781
1055
  return "postgresql";
782
1056
  }
783
- transformPrimitive(value, type) {
1057
+ transformPrimitive(value, type, forArrayField) {
784
1058
  if (value === void 0) {
785
1059
  return value;
786
1060
  }
787
1061
  if (Array.isArray(value)) {
788
- return value.map((v) => this.transformPrimitive(v, type));
1062
+ if (type === "Json" && !forArrayField) {
1063
+ return JSON.stringify(value);
1064
+ } else {
1065
+ return value.map((v) => this.transformPrimitive(v, type, false));
1066
+ }
789
1067
  } else {
790
- return match2(type).with("DateTime", () => value instanceof Date ? value : typeof value === "string" ? new Date(value) : value).otherwise(() => value);
1068
+ return match3(type).with("DateTime", () => value instanceof Date ? value : typeof value === "string" ? new Date(value) : value).with("Decimal", () => value !== null ? value.toString() : value).otherwise(() => value);
791
1069
  }
792
1070
  }
793
1071
  buildRelationSelection(query, model, relationField, parentAlias, payload) {
@@ -801,7 +1079,8 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
801
1079
  const joinTableName = `${parentName}$${relationField}`;
802
1080
  let result = eb.selectFrom(`${relationModel} as ${joinTableName}`);
803
1081
  result = eb.selectFrom(() => {
804
- let subQuery = eb.selectFrom(`${relationModel}`).selectAll();
1082
+ let subQuery = this.buildSelectModel(eb, relationModel);
1083
+ subQuery = this.buildSelectAllFields(relationModel, subQuery, typeof payload === "object" ? payload?.omit : void 0);
805
1084
  if (payload && typeof payload === "object") {
806
1085
  if (payload.where) {
807
1086
  subQuery = subQuery.where((eb2) => this.buildFilter(eb2, relationModel, relationModel, payload.where));
@@ -845,34 +1124,57 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
845
1124
  });
846
1125
  return qb;
847
1126
  }
848
- buildRelationObjectArgs(relationModel, relationField, eb, payload, parentName) {
1127
+ buildRelationObjectArgs(relationModel, relationField, eb, payload, parentAlias) {
849
1128
  const relationModelDef = requireModel(this.schema, relationModel);
850
1129
  const objArgs = [];
1130
+ const descendantModels = getDelegateDescendantModels(this.schema, relationModel);
1131
+ if (descendantModels.length > 0) {
1132
+ objArgs.push(...descendantModels.map((subModel) => [
1133
+ sql2.lit(`${DELEGATE_JOINED_FIELD_PREFIX}${subModel.name}`),
1134
+ eb.ref(`${DELEGATE_JOINED_FIELD_PREFIX}${subModel.name}`)
1135
+ ]).flatMap((v) => v));
1136
+ }
851
1137
  if (payload === true || !payload.select) {
852
1138
  objArgs.push(...Object.entries(relationModelDef.fields).filter(([, value]) => !value.relation).filter(([name]) => !(typeof payload === "object" && payload.omit?.[name] === true)).map(([field]) => [
853
1139
  sql2.lit(field),
854
1140
  buildFieldRef(this.schema, relationModel, field, this.options, eb)
855
1141
  ]).flatMap((v) => v));
856
1142
  } else if (payload.select) {
857
- objArgs.push(...Object.entries(payload.select).filter(([, value]) => value).map(([field]) => [
858
- sql2.lit(field),
859
- buildFieldRef(this.schema, relationModel, field, this.options, eb)
860
- ]).flatMap((v) => v));
1143
+ objArgs.push(...Object.entries(payload.select).filter(([, value]) => value).map(([field, value]) => {
1144
+ if (field === "_count") {
1145
+ const subJson = this.buildCountJson(relationModel, eb, `${parentAlias}$${relationField}`, value);
1146
+ return [
1147
+ sql2.lit(field),
1148
+ subJson
1149
+ ];
1150
+ } else {
1151
+ const fieldDef = requireField(this.schema, relationModel, field);
1152
+ const fieldValue = fieldDef.relation ? eb.ref(`${parentAlias}$${relationField}$${field}.$j`) : buildFieldRef(this.schema, relationModel, field, this.options, eb);
1153
+ return [
1154
+ sql2.lit(field),
1155
+ fieldValue
1156
+ ];
1157
+ }
1158
+ }).flatMap((v) => v));
861
1159
  }
862
1160
  if (typeof payload === "object" && payload.include && typeof payload.include === "object") {
863
1161
  objArgs.push(...Object.entries(payload.include).filter(([, value]) => value).map(([field]) => [
864
1162
  sql2.lit(field),
865
- eb.ref(`${parentName}$${relationField}$${field}.$j`)
1163
+ // reference the synthesized JSON field
1164
+ eb.ref(`${parentAlias}$${relationField}$${field}.$j`)
866
1165
  ]).flatMap((v) => v));
867
1166
  }
868
1167
  return objArgs;
869
1168
  }
870
- buildRelationJoins(model, relationField, qb, payload, parentName) {
1169
+ buildRelationJoins(relationModel, relationField, qb, payload, parentName) {
871
1170
  let result = qb;
872
- if (typeof payload === "object" && payload.include && typeof payload.include === "object") {
873
- Object.entries(payload.include).filter(([, value]) => value).forEach(([field, value]) => {
874
- result = this.buildRelationJSON(model, result, field, `${parentName}$${relationField}`, value);
875
- });
1171
+ if (typeof payload === "object") {
1172
+ const selectInclude = payload.include ?? payload.select;
1173
+ if (selectInclude && typeof selectInclude === "object") {
1174
+ Object.entries(selectInclude).filter(([, value]) => value).filter(([field]) => isRelationField(this.schema, relationModel, field)).forEach(([field, value]) => {
1175
+ result = this.buildRelationJSON(relationModel, result, field, `${parentName}$${relationField}`, value);
1176
+ });
1177
+ }
876
1178
  }
877
1179
  return result;
878
1180
  }
@@ -912,12 +1214,15 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
912
1214
  return `ARRAY[${values.map((v) => typeof v === "string" ? `'${v}'` : v)}]`;
913
1215
  }
914
1216
  }
1217
+ get supportInsertWithDefault() {
1218
+ return true;
1219
+ }
915
1220
  };
916
1221
 
917
1222
  // src/client/crud/dialects/sqlite.ts
1223
+ import { invariant as invariant3 } from "@zenstackhq/common-helpers";
918
1224
  import { sql as sql3 } from "kysely";
919
- import invariant3 from "tiny-invariant";
920
- import { match as match3 } from "ts-pattern";
1225
+ import { match as match4 } from "ts-pattern";
921
1226
  var SqliteCrudDialect = class extends BaseCrudDialect {
922
1227
  static {
923
1228
  __name(this, "SqliteCrudDialect");
@@ -925,26 +1230,31 @@ var SqliteCrudDialect = class extends BaseCrudDialect {
925
1230
  get provider() {
926
1231
  return "sqlite";
927
1232
  }
928
- transformPrimitive(value, type) {
1233
+ transformPrimitive(value, type, _forArrayField) {
929
1234
  if (value === void 0) {
930
1235
  return value;
931
1236
  }
932
1237
  if (Array.isArray(value)) {
933
- return value.map((v) => this.transformPrimitive(v, type));
1238
+ return value.map((v) => this.transformPrimitive(v, type, false));
934
1239
  } else {
935
- return match3(type).with("Boolean", () => value ? 1 : 0).with("DateTime", () => value instanceof Date ? value.toISOString() : value).with("Decimal", () => value.toString()).with("Bytes", () => Buffer.from(value)).otherwise(() => value);
1240
+ if (this.schema.typeDefs && type in this.schema.typeDefs) {
1241
+ return JSON.stringify(value);
1242
+ } else {
1243
+ return match4(type).with("Boolean", () => value ? 1 : 0).with("DateTime", () => value instanceof Date ? value.toISOString() : value).with("Decimal", () => value.toString()).with("Bytes", () => Buffer.from(value)).with("Json", () => JSON.stringify(value)).otherwise(() => value);
1244
+ }
936
1245
  }
937
1246
  }
938
1247
  buildRelationSelection(query, model, relationField, parentAlias, payload) {
939
1248
  return query.select((eb) => this.buildRelationJSON(model, eb, relationField, parentAlias, payload).as(relationField));
940
1249
  }
941
- buildRelationJSON(model, eb, relationField, parentName, payload) {
1250
+ buildRelationJSON(model, eb, relationField, parentAlias, payload) {
942
1251
  const relationFieldDef = requireField(this.schema, model, relationField);
943
1252
  const relationModel = relationFieldDef.type;
944
1253
  const relationModelDef = requireModel(this.schema, relationModel);
945
- const subQueryName = `${parentName}$${relationField}`;
1254
+ const subQueryName = `${parentAlias}$${relationField}`;
946
1255
  let tbl = eb.selectFrom(() => {
947
- let subQuery = eb.selectFrom(relationModel).selectAll();
1256
+ let subQuery = this.buildSelectModel(eb, relationModel);
1257
+ subQuery = this.buildSelectAllFields(relationModel, subQuery, typeof payload === "object" ? payload?.omit : void 0);
948
1258
  if (payload && typeof payload === "object") {
949
1259
  if (payload.where) {
950
1260
  subQuery = subQuery.where((eb2) => this.buildFilter(eb2, relationModel, relationModel, payload.where));
@@ -965,14 +1275,14 @@ var SqliteCrudDialect = class extends BaseCrudDialect {
965
1275
  const relationIds = getIdFields(this.schema, relationModel);
966
1276
  invariant3(parentIds.length === 1, "many-to-many relation must have exactly one id field");
967
1277
  invariant3(relationIds.length === 1, "many-to-many relation must have exactly one id field");
968
- subQuery = subQuery.where(eb(eb.ref(`${relationModel}.${relationIds[0]}`), "in", eb.selectFrom(m2m.joinTable).select(`${m2m.joinTable}.${m2m.otherFkName}`).whereRef(`${parentName}.${parentIds[0]}`, "=", `${m2m.joinTable}.${m2m.parentFkName}`)));
1278
+ subQuery = subQuery.where(eb(eb.ref(`${relationModel}.${relationIds[0]}`), "in", eb.selectFrom(m2m.joinTable).select(`${m2m.joinTable}.${m2m.otherFkName}`).whereRef(`${parentAlias}.${parentIds[0]}`, "=", `${m2m.joinTable}.${m2m.parentFkName}`)));
969
1279
  } else {
970
1280
  const { keyPairs, ownedByModel } = getRelationForeignKeyFieldPairs(this.schema, model, relationField);
971
1281
  keyPairs.forEach(({ fk, pk }) => {
972
1282
  if (ownedByModel) {
973
- subQuery = subQuery.whereRef(`${relationModel}.${pk}`, "=", `${parentName}.${fk}`);
1283
+ subQuery = subQuery.whereRef(`${relationModel}.${pk}`, "=", `${parentAlias}.${fk}`);
974
1284
  } else {
975
- subQuery = subQuery.whereRef(`${relationModel}.${fk}`, "=", `${parentName}.${pk}`);
1285
+ subQuery = subQuery.whereRef(`${relationModel}.${fk}`, "=", `${parentAlias}.${pk}`);
976
1286
  }
977
1287
  });
978
1288
  }
@@ -980,6 +1290,13 @@ var SqliteCrudDialect = class extends BaseCrudDialect {
980
1290
  });
981
1291
  tbl = tbl.select(() => {
982
1292
  const objArgs = [];
1293
+ const descendantModels = getDelegateDescendantModels(this.schema, relationModel);
1294
+ if (descendantModels.length > 0) {
1295
+ objArgs.push(...descendantModels.map((subModel) => [
1296
+ sql3.lit(`${DELEGATE_JOINED_FIELD_PREFIX}${subModel.name}`),
1297
+ eb.ref(`${DELEGATE_JOINED_FIELD_PREFIX}${subModel.name}`)
1298
+ ]).flatMap((v) => v));
1299
+ }
983
1300
  if (payload === true || !payload.select) {
984
1301
  objArgs.push(...Object.entries(relationModelDef.fields).filter(([, value]) => !value.relation).filter(([name]) => !(typeof payload === "object" && payload.omit?.[name] === true)).map(([field]) => [
985
1302
  sql3.lit(field),
@@ -987,160 +1304,92 @@ var SqliteCrudDialect = class extends BaseCrudDialect {
987
1304
  ]).flatMap((v) => v));
988
1305
  } else if (payload.select) {
989
1306
  objArgs.push(...Object.entries(payload.select).filter(([, value]) => value).map(([field, value]) => {
990
- const fieldDef = requireField(this.schema, relationModel, field);
991
- if (fieldDef.relation) {
992
- const subJson = this.buildRelationJSON(relationModel, eb, field, `${parentName}$${relationField}`, value);
1307
+ if (field === "_count") {
1308
+ const subJson = this.buildCountJson(relationModel, eb, `${parentAlias}$${relationField}`, value);
993
1309
  return [
994
1310
  sql3.lit(field),
995
1311
  subJson
996
1312
  ];
997
1313
  } else {
998
- return [
999
- sql3.lit(field),
1000
- buildFieldRef(this.schema, relationModel, field, this.options, eb)
1001
- ];
1314
+ const fieldDef = requireField(this.schema, relationModel, field);
1315
+ if (fieldDef.relation) {
1316
+ const subJson = this.buildRelationJSON(relationModel, eb, field, `${parentAlias}$${relationField}`, value);
1317
+ return [
1318
+ sql3.lit(field),
1319
+ subJson
1320
+ ];
1321
+ } else {
1322
+ return [
1323
+ sql3.lit(field),
1324
+ buildFieldRef(this.schema, relationModel, field, this.options, eb)
1325
+ ];
1326
+ }
1002
1327
  }
1003
1328
  }).flatMap((v) => v));
1004
1329
  }
1005
1330
  if (typeof payload === "object" && payload.include && typeof payload.include === "object") {
1006
1331
  objArgs.push(...Object.entries(payload.include).filter(([, value]) => value).map(([field, value]) => {
1007
- const subJson = this.buildRelationJSON(relationModel, eb, field, `${parentName}$${relationField}`, value);
1332
+ const subJson = this.buildRelationJSON(relationModel, eb, field, `${parentAlias}$${relationField}`, value);
1008
1333
  return [
1009
1334
  sql3.lit(field),
1010
1335
  subJson
1011
1336
  ];
1012
1337
  }).flatMap((v) => v));
1013
1338
  }
1014
- if (relationFieldDef.array) {
1015
- return eb.fn.coalesce(sql3`json_group_array(json_object(${sql3.join(objArgs)}))`, sql3`json_array()`).as("$j");
1016
- } else {
1017
- return sql3`json_object(${sql3.join(objArgs)})`.as("data");
1018
- }
1019
- });
1020
- return tbl;
1021
- }
1022
- buildSkipTake(query, skip, take) {
1023
- if (take !== void 0) {
1024
- query = query.limit(take);
1025
- }
1026
- if (skip !== void 0) {
1027
- query = query.offset(skip);
1028
- if (take === void 0) {
1029
- query = query.limit(-1);
1030
- }
1031
- }
1032
- return query;
1033
- }
1034
- buildJsonObject(eb, value) {
1035
- return eb.fn("json_object", Object.entries(value).flatMap(([key, value2]) => [
1036
- sql3.lit(key),
1037
- value2
1038
- ]));
1039
- }
1040
- get supportsUpdateWithLimit() {
1041
- return false;
1042
- }
1043
- get supportsDeleteWithLimit() {
1044
- return false;
1045
- }
1046
- get supportsDistinctOn() {
1047
- return false;
1048
- }
1049
- buildArrayLength(eb, array) {
1050
- return eb.fn("json_array_length", [
1051
- array
1052
- ]);
1053
- }
1054
- buildArrayLiteralSQL(_values) {
1055
- throw new Error("SQLite does not support array literals");
1056
- }
1057
- };
1058
-
1059
- // src/client/crud/dialects/index.ts
1060
- function getCrudDialect(schema, options) {
1061
- return match4(schema.provider.type).with("sqlite", () => new SqliteCrudDialect(schema, options)).with("postgresql", () => new PostgresCrudDialect(schema, options)).exhaustive();
1062
- }
1063
- __name(getCrudDialect, "getCrudDialect");
1064
-
1065
- // src/schema/expression.ts
1066
- var ExpressionUtils = {
1067
- literal: /* @__PURE__ */ __name((value) => {
1068
- return {
1069
- kind: "literal",
1070
- value
1071
- };
1072
- }, "literal"),
1073
- array: /* @__PURE__ */ __name((items) => {
1074
- return {
1075
- kind: "array",
1076
- items
1077
- };
1078
- }, "array"),
1079
- call: /* @__PURE__ */ __name((functionName, args) => {
1080
- return {
1081
- kind: "call",
1082
- function: functionName,
1083
- args
1084
- };
1085
- }, "call"),
1086
- binary: /* @__PURE__ */ __name((left, op, right) => {
1087
- return {
1088
- kind: "binary",
1089
- op,
1090
- left,
1091
- right
1092
- };
1093
- }, "binary"),
1094
- unary: /* @__PURE__ */ __name((op, operand) => {
1095
- return {
1096
- kind: "unary",
1097
- op,
1098
- operand
1099
- };
1100
- }, "unary"),
1101
- field: /* @__PURE__ */ __name((field) => {
1102
- return {
1103
- kind: "field",
1104
- field
1105
- };
1106
- }, "field"),
1107
- member: /* @__PURE__ */ __name((receiver, members) => {
1108
- return {
1109
- kind: "member",
1110
- receiver,
1111
- members
1112
- };
1113
- }, "member"),
1114
- _this: /* @__PURE__ */ __name(() => {
1115
- return {
1116
- kind: "this"
1117
- };
1118
- }, "_this"),
1119
- _null: /* @__PURE__ */ __name(() => {
1120
- return {
1121
- kind: "null"
1122
- };
1123
- }, "_null"),
1124
- and: /* @__PURE__ */ __name((expr2, ...expressions) => {
1125
- return expressions.reduce((acc, exp) => ExpressionUtils.binary(acc, "&&", exp), expr2);
1126
- }, "and"),
1127
- or: /* @__PURE__ */ __name((expr2, ...expressions) => {
1128
- return expressions.reduce((acc, exp) => ExpressionUtils.binary(acc, "||", exp), expr2);
1129
- }, "or"),
1130
- is: /* @__PURE__ */ __name((value, kind) => {
1131
- return !!value && typeof value === "object" && "kind" in value && value.kind === kind;
1132
- }, "is"),
1133
- isLiteral: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "literal"), "isLiteral"),
1134
- isArray: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "array"), "isArray"),
1135
- isCall: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "call"), "isCall"),
1136
- isNull: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "null"), "isNull"),
1137
- isThis: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "this"), "isThis"),
1138
- isUnary: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "unary"), "isUnary"),
1139
- isBinary: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "binary"), "isBinary"),
1140
- isField: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "field"), "isField"),
1141
- isMember: /* @__PURE__ */ __name((value) => ExpressionUtils.is(value, "member"), "isMember")
1339
+ if (relationFieldDef.array) {
1340
+ return eb.fn.coalesce(sql3`json_group_array(json_object(${sql3.join(objArgs)}))`, sql3`json_array()`).as("$j");
1341
+ } else {
1342
+ return sql3`json_object(${sql3.join(objArgs)})`.as("data");
1343
+ }
1344
+ });
1345
+ return tbl;
1346
+ }
1347
+ buildSkipTake(query, skip, take) {
1348
+ if (take !== void 0) {
1349
+ query = query.limit(take);
1350
+ }
1351
+ if (skip !== void 0) {
1352
+ query = query.offset(skip);
1353
+ if (take === void 0) {
1354
+ query = query.limit(-1);
1355
+ }
1356
+ }
1357
+ return query;
1358
+ }
1359
+ buildJsonObject(eb, value) {
1360
+ return eb.fn("json_object", Object.entries(value).flatMap(([key, value2]) => [
1361
+ sql3.lit(key),
1362
+ value2
1363
+ ]));
1364
+ }
1365
+ get supportsUpdateWithLimit() {
1366
+ return false;
1367
+ }
1368
+ get supportsDeleteWithLimit() {
1369
+ return false;
1370
+ }
1371
+ get supportsDistinctOn() {
1372
+ return false;
1373
+ }
1374
+ buildArrayLength(eb, array) {
1375
+ return eb.fn("json_array_length", [
1376
+ array
1377
+ ]);
1378
+ }
1379
+ buildArrayLiteralSQL(_values) {
1380
+ throw new Error("SQLite does not support array literals");
1381
+ }
1382
+ get supportInsertWithDefault() {
1383
+ return false;
1384
+ }
1142
1385
  };
1143
1386
 
1387
+ // src/client/crud/dialects/index.ts
1388
+ function getCrudDialect(schema, options) {
1389
+ return match5(schema.provider.type).with("sqlite", () => new SqliteCrudDialect(schema, options)).with("postgresql", () => new PostgresCrudDialect(schema, options)).exhaustive();
1390
+ }
1391
+ __name(getCrudDialect, "getCrudDialect");
1392
+
1144
1393
  // src/utils/default-operation-node-visitor.ts
1145
1394
  import { OperationNodeVisitor } from "kysely";
1146
1395
  var DefaultOperationNodeVisitor = class extends OperationNodeVisitor {
@@ -1460,19 +1709,19 @@ var ColumnCollector = class extends DefaultOperationNodeVisitor {
1460
1709
  };
1461
1710
 
1462
1711
  // src/plugins/policy/expression-transformer.ts
1712
+ import { invariant as invariant5 } from "@zenstackhq/common-helpers";
1463
1713
  import { AliasNode as AliasNode2, BinaryOperationNode as BinaryOperationNode2, ColumnNode, expressionBuilder, FromNode, FunctionNode as FunctionNode2, IdentifierNode, OperatorNode as OperatorNode2, ReferenceNode as ReferenceNode2, SelectionNode, SelectQueryNode, TableNode as TableNode2, ValueListNode, ValueNode as ValueNode2, WhereNode } from "kysely";
1464
- import invariant5 from "tiny-invariant";
1465
- import { match as match6 } from "ts-pattern";
1714
+ import { match as match7 } from "ts-pattern";
1466
1715
 
1467
1716
  // src/plugins/policy/expression-evaluator.ts
1468
- import invariant4 from "tiny-invariant";
1469
- import { match as match5 } from "ts-pattern";
1717
+ import { invariant as invariant4 } from "@zenstackhq/common-helpers";
1718
+ import { match as match6 } from "ts-pattern";
1470
1719
  var ExpressionEvaluator = class {
1471
1720
  static {
1472
1721
  __name(this, "ExpressionEvaluator");
1473
1722
  }
1474
1723
  evaluate(expression, context) {
1475
- const result = match5(expression).when(ExpressionUtils.isArray, (expr2) => this.evaluateArray(expr2, context)).when(ExpressionUtils.isBinary, (expr2) => this.evaluateBinary(expr2, context)).when(ExpressionUtils.isField, (expr2) => this.evaluateField(expr2, context)).when(ExpressionUtils.isLiteral, (expr2) => this.evaluateLiteral(expr2)).when(ExpressionUtils.isMember, (expr2) => this.evaluateMember(expr2, context)).when(ExpressionUtils.isUnary, (expr2) => this.evaluateUnary(expr2, context)).when(ExpressionUtils.isCall, (expr2) => this.evaluateCall(expr2, context)).when(ExpressionUtils.isThis, () => context.thisValue).when(ExpressionUtils.isNull, () => null).exhaustive();
1724
+ const result = match6(expression).when(ExpressionUtils.isArray, (expr2) => this.evaluateArray(expr2, context)).when(ExpressionUtils.isBinary, (expr2) => this.evaluateBinary(expr2, context)).when(ExpressionUtils.isField, (expr2) => this.evaluateField(expr2, context)).when(ExpressionUtils.isLiteral, (expr2) => this.evaluateLiteral(expr2)).when(ExpressionUtils.isMember, (expr2) => this.evaluateMember(expr2, context)).when(ExpressionUtils.isUnary, (expr2) => this.evaluateUnary(expr2, context)).when(ExpressionUtils.isCall, (expr2) => this.evaluateCall(expr2, context)).when(ExpressionUtils.isThis, () => context.thisValue).when(ExpressionUtils.isNull, () => null).exhaustive();
1476
1725
  return result ?? null;
1477
1726
  }
1478
1727
  evaluateCall(expr2, context) {
@@ -1483,7 +1732,7 @@ var ExpressionEvaluator = class {
1483
1732
  }
1484
1733
  }
1485
1734
  evaluateUnary(expr2, context) {
1486
- return match5(expr2.op).with("!", () => !this.evaluate(expr2.operand, context)).exhaustive();
1735
+ return match6(expr2.op).with("!", () => !this.evaluate(expr2.operand, context)).exhaustive();
1487
1736
  }
1488
1737
  evaluateMember(expr2, context) {
1489
1738
  let val = this.evaluate(expr2.receiver, context);
@@ -1507,7 +1756,7 @@ var ExpressionEvaluator = class {
1507
1756
  }
1508
1757
  const left = this.evaluate(expr2.left, context);
1509
1758
  const right = this.evaluate(expr2.right, context);
1510
- return match5(expr2.op).with("==", () => left === right).with("!=", () => left !== right).with(">", () => left > right).with(">=", () => left >= right).with("<", () => left < right).with("<=", () => left <= right).with("&&", () => left && right).with("||", () => left || right).with("in", () => {
1759
+ return match6(expr2.op).with("==", () => left === right).with("!=", () => left !== right).with(">", () => left > right).with(">=", () => left >= right).with("<", () => left < right).with("<=", () => left <= right).with("&&", () => left && right).with("||", () => left || right).with("in", () => {
1511
1760
  const _right = right ?? [];
1512
1761
  invariant4(Array.isArray(_right), 'expected array for "in" operator');
1513
1762
  return _right.includes(left);
@@ -1521,7 +1770,7 @@ var ExpressionEvaluator = class {
1521
1770
  return false;
1522
1771
  }
1523
1772
  invariant4(Array.isArray(left), "expected array");
1524
- return match5(op).with("?", () => left.some((item) => this.evaluate(expr2.right, {
1773
+ return match6(op).with("?", () => left.some((item) => this.evaluate(expr2.right, {
1525
1774
  ...context,
1526
1775
  thisValue: item
1527
1776
  }))).with("!", () => left.every((item) => this.evaluate(expr2.right, {
@@ -1537,11 +1786,11 @@ var ExpressionEvaluator = class {
1537
1786
  // src/plugins/policy/utils.ts
1538
1787
  import { AliasNode, AndNode, BinaryOperationNode, FunctionNode, OperatorNode, OrNode, ParensNode, ReferenceNode, TableNode, UnaryOperationNode, ValueNode } from "kysely";
1539
1788
  function trueNode(dialect) {
1540
- return ValueNode.createImmediate(dialect.transformPrimitive(true, "Boolean"));
1789
+ return ValueNode.createImmediate(dialect.transformPrimitive(true, "Boolean", false));
1541
1790
  }
1542
1791
  __name(trueNode, "trueNode");
1543
1792
  function falseNode(dialect) {
1544
- return ValueNode.createImmediate(dialect.transformPrimitive(false, "Boolean"));
1793
+ return ValueNode.createImmediate(dialect.transformPrimitive(false, "Boolean", false));
1545
1794
  }
1546
1795
  __name(falseNode, "falseNode");
1547
1796
  function isTrueNode(node) {
@@ -1775,7 +2024,7 @@ var ExpressionTransformer = class {
1775
2024
  const count = FunctionNode2.create("count", [
1776
2025
  ValueNode2.createImmediate(1)
1777
2026
  ]);
1778
- const predicateResult = match6(expr2.op).with("?", () => BinaryOperationNode2.create(count, OperatorNode2.create(">"), ValueNode2.createImmediate(0))).with("!", () => BinaryOperationNode2.create(count, OperatorNode2.create("="), ValueNode2.createImmediate(0))).with("^", () => BinaryOperationNode2.create(count, OperatorNode2.create("="), ValueNode2.createImmediate(0))).exhaustive();
2027
+ const predicateResult = match7(expr2.op).with("?", () => BinaryOperationNode2.create(count, OperatorNode2.create(">"), ValueNode2.createImmediate(0))).with("!", () => BinaryOperationNode2.create(count, OperatorNode2.create("="), ValueNode2.createImmediate(0))).with("^", () => BinaryOperationNode2.create(count, OperatorNode2.create("="), ValueNode2.createImmediate(0))).exhaustive();
1779
2028
  return this.transform(expr2.left, {
1780
2029
  ...context,
1781
2030
  memberSelect: SelectionNode.create(AliasNode2.create(predicateResult, IdentifierNode.create("$t"))),
@@ -1799,14 +2048,14 @@ var ExpressionTransformer = class {
1799
2048
  }
1800
2049
  }
1801
2050
  transformValue(value, type) {
1802
- return ValueNode2.create(this.dialect.transformPrimitive(value, type) ?? null);
2051
+ return ValueNode2.create(this.dialect.transformPrimitive(value, type, false) ?? null);
1803
2052
  }
1804
2053
  _unary(expr2, context) {
1805
2054
  invariant5(expr2.op === "!", 'only "!" operator is supported');
1806
2055
  return BinaryOperationNode2.create(this.transform(expr2.operand, context), this.transformOperator("!="), trueNode(this.dialect));
1807
2056
  }
1808
2057
  transformOperator(op) {
1809
- const mappedOp = match6(op).with("==", () => "=").otherwise(() => op);
2058
+ const mappedOp = match7(op).with("==", () => "=").otherwise(() => op);
1810
2059
  return OperatorNode2.create(mappedOp);
1811
2060
  }
1812
2061
  _call(expr2, context) {
@@ -2042,7 +2291,7 @@ var PolicyHandler = class extends OperationNodeTransformer {
2042
2291
  get kysely() {
2043
2292
  return this.client.$qb;
2044
2293
  }
2045
- async handle(node, proceed, transaction) {
2294
+ async handle(node, proceed) {
2046
2295
  if (!this.isCrudQueryNode(node)) {
2047
2296
  throw new RejectedByPolicyError(void 0, "non-CRUD queries are not allowed");
2048
2297
  }
@@ -2062,27 +2311,20 @@ var PolicyHandler = class extends OperationNodeTransformer {
2062
2311
  if (!mutationRequiresTransaction && !node.returning) {
2063
2312
  return proceed(this.transformNode(node));
2064
2313
  }
2065
- let readBackError = false;
2066
- const result = await transaction(async (txProceed) => {
2067
- if (InsertQueryNode.is(node)) {
2068
- await this.enforcePreCreatePolicy(node, txProceed);
2069
- }
2070
- const transformedNode = this.transformNode(node);
2071
- const result2 = await txProceed(transformedNode);
2072
- if (!this.onlyReturningId(node)) {
2073
- const readBackResult = await this.processReadBack(node, result2, txProceed);
2074
- if (readBackResult.rows.length !== result2.rows.length) {
2075
- readBackError = true;
2076
- }
2077
- return readBackResult;
2078
- } else {
2079
- return result2;
2314
+ if (InsertQueryNode.is(node)) {
2315
+ await this.enforcePreCreatePolicy(node, proceed);
2316
+ }
2317
+ const transformedNode = this.transformNode(node);
2318
+ const result = await proceed(transformedNode);
2319
+ if (!this.onlyReturningId(node)) {
2320
+ const readBackResult = await this.processReadBack(node, result, proceed);
2321
+ if (readBackResult.rows.length !== result.rows.length) {
2322
+ throw new RejectedByPolicyError(mutationModel, "result is not allowed to be read back");
2080
2323
  }
2081
- });
2082
- if (readBackError) {
2083
- throw new RejectedByPolicyError(mutationModel, "result is not allowed to be read back");
2324
+ return readBackResult;
2325
+ } else {
2326
+ return result;
2084
2327
  }
2085
- return result;
2086
2328
  }
2087
2329
  onlyReturningId(node) {
2088
2330
  if (!node.returning) {
@@ -2143,11 +2385,11 @@ var PolicyHandler = class extends OperationNodeTransformer {
2143
2385
  if (typeof item === "object" && item && "kind" in item) {
2144
2386
  invariant6(item.kind === "ValueNode", "expecting a ValueNode");
2145
2387
  result.push({
2146
- node: ValueNode3.create(this.dialect.transformPrimitive(item.value, fieldDef.type)),
2388
+ node: ValueNode3.create(this.dialect.transformPrimitive(item.value, fieldDef.type, !!fieldDef.array)),
2147
2389
  raw: item.value
2148
2390
  });
2149
2391
  } else {
2150
- const value = this.dialect.transformPrimitive(item, fieldDef.type);
2392
+ const value = this.dialect.transformPrimitive(item, fieldDef.type, !!fieldDef.array);
2151
2393
  if (Array.isArray(value)) {
2152
2394
  result.push({
2153
2395
  node: RawNode.createWithSql(this.dialect.buildArrayLiteralSQL(value)),
@@ -2216,7 +2458,7 @@ var PolicyHandler = class extends OperationNodeTransformer {
2216
2458
  return disjunction(this.dialect, rows.map((row) => conjunction(this.dialect, idFields.map((field) => BinaryOperationNode3.create(ColumnNode2.create(field), OperatorNode3.create("="), ValueNode3.create(row[field]))))));
2217
2459
  }
2218
2460
  getMutationModel(node) {
2219
- const r = match7(node).when(InsertQueryNode.is, (node2) => getTableName(node2.into)).when(UpdateQueryNode.is, (node2) => getTableName(node2.table)).when(DeleteQueryNode.is, (node2) => {
2461
+ const r = match8(node).when(InsertQueryNode.is, (node2) => getTableName(node2.into)).when(UpdateQueryNode.is, (node2) => getTableName(node2.table)).when(DeleteQueryNode.is, (node2) => {
2220
2462
  if (node2.from.froms.length !== 1) {
2221
2463
  throw new InternalError("Only one from table is supported for delete");
2222
2464
  }
@@ -2378,14 +2620,23 @@ var PolicyPlugin = class {
2378
2620
  get description() {
2379
2621
  return "Enforces access policies defined in the schema.";
2380
2622
  }
2381
- onKyselyQuery({ query, client, proceed, transaction }) {
2623
+ onKyselyQuery({
2624
+ query,
2625
+ client,
2626
+ proceed
2627
+ /*, transaction*/
2628
+ }) {
2382
2629
  const handler = new PolicyHandler(client);
2383
- return handler.handle(query, proceed, transaction);
2630
+ return handler.handle(
2631
+ query,
2632
+ proceed
2633
+ /*, transaction*/
2634
+ );
2384
2635
  }
2385
2636
  };
2386
2637
 
2387
2638
  // src/utils/clone.ts
2388
- import { isPlainObject as isPlainObject2 } from "is-plain-object";
2639
+ import { isPlainObject as isPlainObject2 } from "@zenstackhq/common-helpers";
2389
2640
  function clone(value) {
2390
2641
  if (Array.isArray(value)) {
2391
2642
  return value.map((v) => clone(v));
@@ -2404,28 +2655,6 @@ function clone(value) {
2404
2655
  }
2405
2656
  __name(clone, "clone");
2406
2657
 
2407
- // src/utils/object-utils.ts
2408
- function extractFields(obj, fields) {
2409
- return Object.fromEntries(Object.entries(obj).filter(([key]) => fields.includes(key)));
2410
- }
2411
- __name(extractFields, "extractFields");
2412
- function fieldsToSelectObject(fields) {
2413
- return Object.fromEntries(fields.map((f) => [
2414
- f,
2415
- true
2416
- ]));
2417
- }
2418
- __name(fieldsToSelectObject, "fieldsToSelectObject");
2419
-
2420
- // src/client/constants.ts
2421
- var CONTEXT_COMMENT_PREFIX = "-- $$context:";
2422
- var NUMERIC_FIELD_TYPES = [
2423
- "Int",
2424
- "Float",
2425
- "BigInt",
2426
- "Decimal"
2427
- ];
2428
-
2429
2658
  // src/client/crud/operations/base.ts
2430
2659
  var BaseOperationHandler = class {
2431
2660
  static {
@@ -2469,17 +2698,17 @@ var BaseOperationHandler = class {
2469
2698
  getField(model, field) {
2470
2699
  return getField(this.schema, model, field);
2471
2700
  }
2472
- exists(kysely, model, filter) {
2701
+ async exists(kysely, model, filter) {
2473
2702
  const idFields = getIdFields(this.schema, model);
2474
2703
  const _filter = flattenCompoundUniqueFilters(this.schema, model, filter);
2475
2704
  const query = kysely.selectFrom(model).where((eb) => eb.and(_filter)).select(idFields.map((f) => kysely.dynamic.ref(f))).limit(1).modifyEnd(this.makeContextComment({
2476
2705
  model,
2477
2706
  operation: "read"
2478
2707
  }));
2479
- return query.executeTakeFirst();
2708
+ return this.executeQueryTakeFirst(kysely, query, "exists");
2480
2709
  }
2481
2710
  async read(kysely, model, args) {
2482
- let query = kysely.selectFrom(model);
2711
+ let query = this.dialect.buildSelectModel(expressionBuilder2(), model);
2483
2712
  if (args?.where) {
2484
2713
  query = query.where((eb) => this.dialect.buildFilter(eb, model, model, args?.where));
2485
2714
  }
@@ -2499,15 +2728,16 @@ var BaseOperationHandler = class {
2499
2728
  query = query.distinctOn(distinct.map((f) => sql4.ref(`${model}.${f}`)));
2500
2729
  } else {
2501
2730
  inMemoryDistinct = distinct;
2731
+ query = distinct.reduce((acc, field) => acc.select((eb) => buildFieldRef(this.schema, model, field, this.options, eb).as(`$distinct$${field}`)), query);
2502
2732
  }
2503
2733
  }
2504
- if (args?.select) {
2505
- query = this.buildFieldSelection(model, query, args?.select, model);
2734
+ if (args && "select" in args && args.select) {
2735
+ query = this.buildFieldSelection(model, query, args.select, model);
2506
2736
  } else {
2507
- query = this.buildSelectAllScalarFields(model, query, args?.omit);
2737
+ query = this.dialect.buildSelectAllFields(model, query, args?.omit);
2508
2738
  }
2509
- if (args?.include) {
2510
- query = this.buildFieldSelection(model, query, args?.include, model);
2739
+ if (args && "include" in args && args.include) {
2740
+ query = this.buildFieldSelection(model, query, args.include, model);
2511
2741
  }
2512
2742
  if (args?.cursor) {
2513
2743
  query = this.buildCursorFilter(model, query, args.cursor, args.orderBy, negateOrderBy);
@@ -2517,23 +2747,35 @@ var BaseOperationHandler = class {
2517
2747
  operation: "read"
2518
2748
  }));
2519
2749
  let result = [];
2750
+ const queryId = {
2751
+ queryId: `zenstack-${createId()}`
2752
+ };
2753
+ const compiled = kysely.getExecutor().compileQuery(query.toOperationNode(), queryId);
2520
2754
  try {
2521
- result = await query.execute();
2755
+ const r = await kysely.getExecutor().executeQuery(compiled, queryId);
2756
+ result = r.rows;
2522
2757
  } catch (err) {
2523
- const { sql: sql10, parameters } = query.compile();
2524
- throw new QueryError(`Failed to execute query: ${err}, sql: ${sql10}, parameters: ${parameters}`);
2758
+ let message = `Failed to execute query: ${err}, sql: ${compiled.sql}`;
2759
+ if (this.options.debug) {
2760
+ message += `, parameters:
2761
+ ${compiled.parameters.map((p) => inspect(p)).join("\n")}`;
2762
+ }
2763
+ throw new QueryError(message, err);
2525
2764
  }
2526
2765
  if (inMemoryDistinct) {
2527
2766
  const distinctResult = [];
2528
2767
  const seen = /* @__PURE__ */ new Set();
2529
2768
  for (const r of result) {
2530
- const key = safeJSONStringify(inMemoryDistinct.map((f) => r[f]));
2769
+ const key = safeJSONStringify(inMemoryDistinct.map((f) => r[`$distinct$${f}`]));
2531
2770
  if (!seen.has(key)) {
2532
2771
  distinctResult.push(r);
2533
2772
  seen.add(key);
2534
2773
  }
2535
2774
  }
2536
2775
  result = distinctResult;
2776
+ for (const r of result) {
2777
+ Object.keys(r).filter((k) => k.startsWith("$distinct$")).forEach((k) => delete r[k]);
2778
+ }
2537
2779
  }
2538
2780
  return result;
2539
2781
  }
@@ -2556,65 +2798,22 @@ var BaseOperationHandler = class {
2556
2798
  }
2557
2799
  const fieldDef = this.requireField(model, field);
2558
2800
  if (!fieldDef.relation) {
2559
- result = this.selectField(result, model, parentAlias, field);
2801
+ result = this.dialect.buildSelectField(result, model, parentAlias, field);
2560
2802
  } else {
2561
2803
  if (!fieldDef.array && !fieldDef.optional && payload.where) {
2562
2804
  throw new QueryError(`Field "${field}" doesn't support filtering`);
2563
2805
  }
2564
- result = this.dialect.buildRelationSelection(result, model, field, parentAlias, payload);
2806
+ if (fieldDef.originModel) {
2807
+ result = this.dialect.buildRelationSelection(result, fieldDef.originModel, field, fieldDef.originModel, payload);
2808
+ } else {
2809
+ result = this.dialect.buildRelationSelection(result, model, field, parentAlias, payload);
2810
+ }
2565
2811
  }
2566
2812
  }
2567
2813
  return result;
2568
2814
  }
2569
2815
  buildCountSelection(query, model, parentAlias, payload) {
2570
- const modelDef = requireModel(this.schema, model);
2571
- const toManyRelations = Object.entries(modelDef.fields).filter(([, field]) => field.relation && field.array);
2572
- const selections = payload === true ? {
2573
- select: toManyRelations.reduce((acc, [field]) => {
2574
- acc[field] = true;
2575
- return acc;
2576
- }, {})
2577
- } : payload;
2578
- const eb = expressionBuilder2();
2579
- const jsonObject = {};
2580
- for (const [field, value] of Object.entries(selections.select)) {
2581
- const fieldDef = requireField(this.schema, model, field);
2582
- const fieldModel = fieldDef.type;
2583
- const jointTable = `${parentAlias}$${field}$count`;
2584
- const joinPairs = buildJoinPairs(this.schema, model, parentAlias, field, jointTable);
2585
- query = query.leftJoin((eb2) => {
2586
- let result = eb2.selectFrom(fieldModel).selectAll();
2587
- if (value && typeof value === "object" && "where" in value && value.where && typeof value.where === "object") {
2588
- const filter = this.dialect.buildFilter(eb2, fieldModel, fieldModel, value.where);
2589
- result = result.where(filter);
2590
- }
2591
- return result.as(jointTable);
2592
- }, (join) => {
2593
- for (const [left, right] of joinPairs) {
2594
- join = join.onRef(left, "=", right);
2595
- }
2596
- return join;
2597
- });
2598
- jsonObject[field] = this.countIdDistinct(eb, fieldDef.type, jointTable);
2599
- }
2600
- query = query.select((eb2) => this.dialect.buildJsonObject(eb2, jsonObject).as("_count"));
2601
- return query;
2602
- }
2603
- countIdDistinct(eb, model, table) {
2604
- const idFields = getIdFields(this.schema, model);
2605
- return eb.fn.count(sql4.join(idFields.map((f) => sql4.ref(`${table}.${f}`)))).distinct();
2606
- }
2607
- buildSelectAllScalarFields(model, query, omit) {
2608
- const modelDef = this.requireModel(model);
2609
- return Object.keys(modelDef.fields).filter((f) => !isRelationField(this.schema, model, f)).filter((f) => omit?.[f] !== true).reduce((acc, f) => this.selectField(acc, model, model, f), query);
2610
- }
2611
- selectField(query, model, modelAlias, field) {
2612
- const fieldDef = this.requireField(model, field);
2613
- if (!fieldDef.computed) {
2614
- return query.select(sql4.ref(`${modelAlias}.${field}`).as(field));
2615
- } else {
2616
- return query.select((eb) => buildFieldRef(this.schema, model, field, this.options, eb).as(field));
2617
- }
2816
+ return query.select((eb) => this.dialect.buildCountJson(model, eb, parentAlias, payload).as("_count"));
2618
2817
  }
2619
2818
  buildCursorFilter(model, query, cursor, orderBy, negateOrderBy) {
2620
2819
  if (!orderBy) {
@@ -2638,9 +2837,12 @@ var BaseOperationHandler = class {
2638
2837
  result = result.where((eb2) => eb2.or(filters));
2639
2838
  return result;
2640
2839
  }
2641
- async create(kysely, model, data, fromRelation) {
2840
+ async create(kysely, model, data, fromRelation, creatingForDelegate = false) {
2642
2841
  const modelDef = this.requireModel(model);
2643
- const createFields = {};
2842
+ if (modelDef.isDelegate && !creatingForDelegate) {
2843
+ throw new QueryError(`Model "${this.model}" is a delegate and cannot be created directly.`);
2844
+ }
2845
+ let createFields = {};
2644
2846
  let parentUpdateTask = void 0;
2645
2847
  let m2m = void 0;
2646
2848
  if (fromRelation) {
@@ -2659,7 +2861,7 @@ var BaseOperationHandler = class {
2659
2861
  model: fromRelation.model,
2660
2862
  operation: "update"
2661
2863
  }));
2662
- return query2.execute();
2864
+ return this.executeQuery(kysely, query2, "update");
2663
2865
  }, "parentUpdateTask");
2664
2866
  }
2665
2867
  }
@@ -2669,14 +2871,14 @@ var BaseOperationHandler = class {
2669
2871
  const fieldDef = this.requireField(model, field);
2670
2872
  if (isScalarField(this.schema, model, field) || isForeignKeyField(this.schema, model, field)) {
2671
2873
  if (fieldDef.array && value && typeof value === "object" && "set" in value && Array.isArray(value.set)) {
2672
- createFields[field] = this.dialect.transformPrimitive(value.set, fieldDef.type);
2874
+ createFields[field] = this.dialect.transformPrimitive(value.set, fieldDef.type, true);
2673
2875
  } else {
2674
- createFields[field] = this.dialect.transformPrimitive(value, fieldDef.type);
2876
+ createFields[field] = this.dialect.transformPrimitive(value, fieldDef.type, !!fieldDef.array);
2675
2877
  }
2676
2878
  } else {
2677
2879
  const subM2M = getManyToManyRelation(this.schema, model, field);
2678
2880
  if (!subM2M && fieldDef.relation?.fields && fieldDef.relation?.references) {
2679
- const fkValues = await this.processOwnedRelation(kysely, fieldDef, value);
2881
+ const fkValues = await this.processOwnedRelationForCreate(kysely, fieldDef, value);
2680
2882
  for (let i = 0; i < fieldDef.relation.fields.length; i++) {
2681
2883
  createFields[fieldDef.relation.fields[i]] = fkValues[fieldDef.relation.references[i]];
2682
2884
  }
@@ -2688,16 +2890,20 @@ var BaseOperationHandler = class {
2688
2890
  }
2689
2891
  }
2690
2892
  }
2893
+ if (modelDef.baseModel) {
2894
+ const baseCreateResult = await this.processBaseModelCreate(kysely, modelDef.baseModel, createFields, model);
2895
+ createFields = baseCreateResult.remainingFields;
2896
+ }
2691
2897
  const updatedData = this.fillGeneratedValues(modelDef, createFields);
2692
2898
  const idFields = getIdFields(this.schema, model);
2693
- const query = kysely.insertInto(model).values(updatedData).returning(idFields).modifyEnd(this.makeContextComment({
2899
+ const query = kysely.insertInto(model).$if(Object.keys(updatedData).length === 0, (qb) => qb.defaultValues()).$if(Object.keys(updatedData).length > 0, (qb) => qb.values(updatedData)).returning(idFields).modifyEnd(this.makeContextComment({
2694
2900
  model,
2695
2901
  operation: "create"
2696
2902
  }));
2697
- const createdEntity = await query.executeTakeFirst();
2903
+ const createdEntity = await this.executeQueryTakeFirst(kysely, query, "create");
2698
2904
  if (Object.keys(postCreateRelations).length > 0) {
2699
2905
  const relationPromises = Object.entries(postCreateRelations).map(([field, subPayload]) => {
2700
- return this.processNoneOwnedRelation(kysely, model, field, subPayload, createdEntity);
2906
+ return this.processNoneOwnedRelationForCreate(kysely, model, field, subPayload, createdEntity);
2701
2907
  });
2702
2908
  await Promise.all(relationPromises);
2703
2909
  }
@@ -2709,6 +2915,28 @@ var BaseOperationHandler = class {
2709
2915
  }
2710
2916
  return createdEntity;
2711
2917
  }
2918
+ async processBaseModelCreate(kysely, model, createFields, forModel) {
2919
+ const thisCreateFields = {};
2920
+ const remainingFields = {};
2921
+ Object.entries(createFields).forEach(([field, value]) => {
2922
+ const fieldDef = this.getField(model, field);
2923
+ if (fieldDef) {
2924
+ thisCreateFields[field] = value;
2925
+ } else {
2926
+ remainingFields[field] = value;
2927
+ }
2928
+ });
2929
+ const discriminatorField = getDiscriminatorField(this.schema, model);
2930
+ invariant7(discriminatorField, `Base model "${model}" must have a discriminator field`);
2931
+ thisCreateFields[discriminatorField] = forModel;
2932
+ const baseEntity = await this.create(kysely, model, thisCreateFields, void 0, true);
2933
+ const idValues = extractIdFields(baseEntity, this.schema, model);
2934
+ Object.assign(remainingFields, idValues);
2935
+ return {
2936
+ baseEntity,
2937
+ remainingFields
2938
+ };
2939
+ }
2712
2940
  buildFkAssignments(model, relationField, entity) {
2713
2941
  const parentFkFields = {};
2714
2942
  invariant7(relationField, "parentField must be defined if parentModel is defined");
@@ -2764,7 +2992,7 @@ var BaseOperationHandler = class {
2764
2992
  const eb = expressionBuilder2();
2765
2993
  return kysely.deleteFrom(m2m.joinTable).where(eb(`${m2m.joinTable}.${m2m.parentFkName}`, "=", parentId)).execute();
2766
2994
  }
2767
- async processOwnedRelation(kysely, relationField, payload) {
2995
+ async processOwnedRelationForCreate(kysely, relationField, payload) {
2768
2996
  if (!payload) {
2769
2997
  return;
2770
2998
  }
@@ -2814,21 +3042,27 @@ var BaseOperationHandler = class {
2814
3042
  }
2815
3043
  return result;
2816
3044
  }
2817
- processNoneOwnedRelation(kysely, contextModel, relationFieldName, payload, parentEntity) {
3045
+ processNoneOwnedRelationForCreate(kysely, contextModel, relationFieldName, payload, parentEntity) {
2818
3046
  const relationFieldDef = this.requireField(contextModel, relationFieldName);
2819
3047
  const relationModel = relationFieldDef.type;
2820
3048
  const tasks = [];
3049
+ const fromRelationContext = {
3050
+ model: contextModel,
3051
+ field: relationFieldName,
3052
+ ids: parentEntity
3053
+ };
2821
3054
  for (const [action, subPayload] of Object.entries(payload)) {
2822
3055
  if (!subPayload) {
2823
3056
  continue;
2824
3057
  }
2825
3058
  switch (action) {
2826
3059
  case "create": {
2827
- tasks.push(...enumerate(subPayload).map((item) => this.create(kysely, relationModel, item, {
2828
- model: contextModel,
2829
- field: relationFieldName,
2830
- ids: parentEntity
2831
- })));
3060
+ tasks.push(...enumerate(subPayload).map((item) => this.create(kysely, relationModel, item, fromRelationContext)));
3061
+ break;
3062
+ }
3063
+ case "createMany": {
3064
+ invariant7(relationFieldDef.array, "relation must be an array for createMany");
3065
+ tasks.push(this.createMany(kysely, relationModel, subPayload, false, fromRelationContext));
2832
3066
  break;
2833
3067
  }
2834
3068
  case "connect": {
@@ -2858,6 +3092,11 @@ var BaseOperationHandler = class {
2858
3092
  return Promise.all(tasks);
2859
3093
  }
2860
3094
  async createMany(kysely, model, input, returnData, fromRelation) {
3095
+ if (!input.data || Array.isArray(input.data) && input.data.length === 0) {
3096
+ return returnData ? [] : {
3097
+ count: 0
3098
+ };
3099
+ }
2861
3100
  const modelDef = this.requireModel(model);
2862
3101
  let relationKeyPairs = [];
2863
3102
  if (fromRelation) {
@@ -2867,12 +3106,12 @@ var BaseOperationHandler = class {
2867
3106
  }
2868
3107
  relationKeyPairs = keyPairs;
2869
3108
  }
2870
- const createData = enumerate(input.data).map((item) => {
3109
+ let createData = enumerate(input.data).map((item) => {
2871
3110
  const newItem = {};
2872
3111
  for (const [name, value] of Object.entries(item)) {
2873
3112
  const fieldDef = this.requireField(model, name);
2874
3113
  invariant7(!fieldDef.relation, "createMany does not support relations");
2875
- newItem[name] = this.dialect.transformPrimitive(value, fieldDef.type);
3114
+ newItem[name] = this.dialect.transformPrimitive(value, fieldDef.type, !!fieldDef.array);
2876
3115
  }
2877
3116
  if (fromRelation) {
2878
3117
  for (const { fk, pk } of relationKeyPairs) {
@@ -2881,14 +3120,44 @@ var BaseOperationHandler = class {
2881
3120
  }
2882
3121
  return this.fillGeneratedValues(modelDef, newItem);
2883
3122
  });
3123
+ if (!this.dialect.supportInsertWithDefault) {
3124
+ const allPassedFields = createData.reduce((acc, item) => {
3125
+ Object.keys(item).forEach((field) => {
3126
+ if (!acc.includes(field)) {
3127
+ acc.push(field);
3128
+ }
3129
+ });
3130
+ return acc;
3131
+ }, []);
3132
+ for (const item of createData) {
3133
+ if (Object.keys(item).length === allPassedFields.length) {
3134
+ continue;
3135
+ }
3136
+ for (const field of allPassedFields) {
3137
+ if (!(field in item)) {
3138
+ const fieldDef = this.requireField(model, field);
3139
+ if (fieldDef.default !== void 0 && fieldDef.default !== null && typeof fieldDef.default !== "object") {
3140
+ item[field] = this.dialect.transformPrimitive(fieldDef.default, fieldDef.type, !!fieldDef.array);
3141
+ }
3142
+ }
3143
+ }
3144
+ }
3145
+ }
3146
+ if (modelDef.baseModel) {
3147
+ if (input.skipDuplicates) {
3148
+ throw new QueryError('"skipDuplicates" options is not supported for polymorphic models');
3149
+ }
3150
+ const baseCreateResult = await this.processBaseModelCreateMany(kysely, modelDef.baseModel, createData, !!input.skipDuplicates, model);
3151
+ createData = baseCreateResult.remainingFieldRows;
3152
+ }
2884
3153
  const query = kysely.insertInto(model).values(createData).$if(!!input.skipDuplicates, (qb) => qb.onConflict((oc) => oc.doNothing())).modifyEnd(this.makeContextComment({
2885
3154
  model,
2886
3155
  operation: "create"
2887
3156
  }));
2888
3157
  if (!returnData) {
2889
- const result = await query.executeTakeFirstOrThrow();
3158
+ const result = await this.executeQuery(kysely, query, "createMany");
2890
3159
  return {
2891
- count: Number(result.numInsertedOrUpdatedRows)
3160
+ count: Number(result.numAffectedRows)
2892
3161
  };
2893
3162
  } else {
2894
3163
  const idFields = getIdFields(this.schema, model);
@@ -2896,10 +3165,46 @@ var BaseOperationHandler = class {
2896
3165
  return result;
2897
3166
  }
2898
3167
  }
3168
+ async processBaseModelCreateMany(kysely, model, createRows, skipDuplicates, forModel) {
3169
+ const thisCreateRows = [];
3170
+ const remainingFieldRows = [];
3171
+ const discriminatorField = getDiscriminatorField(this.schema, model);
3172
+ invariant7(discriminatorField, `Base model "${model}" must have a discriminator field`);
3173
+ for (const createFields of createRows) {
3174
+ const thisCreateFields = {};
3175
+ const remainingFields = {};
3176
+ Object.entries(createFields).forEach(([field, value]) => {
3177
+ const fieldDef = this.getField(model, field);
3178
+ if (fieldDef) {
3179
+ thisCreateFields[field] = value;
3180
+ } else {
3181
+ remainingFields[field] = value;
3182
+ }
3183
+ });
3184
+ thisCreateFields[discriminatorField] = forModel;
3185
+ thisCreateRows.push(thisCreateFields);
3186
+ remainingFieldRows.push(remainingFields);
3187
+ }
3188
+ const baseEntities = await this.createMany(kysely, model, {
3189
+ data: thisCreateRows,
3190
+ skipDuplicates
3191
+ }, true);
3192
+ for (let i = 0; i < baseEntities.length; i++) {
3193
+ const idValues = extractIdFields(baseEntities[i], this.schema, model);
3194
+ Object.assign(remainingFieldRows[i], idValues);
3195
+ }
3196
+ return {
3197
+ baseEntities,
3198
+ remainingFieldRows
3199
+ };
3200
+ }
2899
3201
  fillGeneratedValues(modelDef, data) {
2900
3202
  const fields = modelDef.fields;
2901
3203
  const values = clone(data);
2902
- for (const field in fields) {
3204
+ for (const [field, fieldDef] of Object.entries(fields)) {
3205
+ if (fieldDef.originModel) {
3206
+ continue;
3207
+ }
2903
3208
  if (!(field in data)) {
2904
3209
  if (typeof fields[field]?.default === "object" && "kind" in fields[field].default) {
2905
3210
  const generated = this.evalGenerator(fields[field].default);
@@ -2907,7 +3212,7 @@ var BaseOperationHandler = class {
2907
3212
  values[field] = generated;
2908
3213
  }
2909
3214
  } else if (fields[field]?.updatedAt) {
2910
- values[field] = this.dialect.transformPrimitive(/* @__PURE__ */ new Date(), "DateTime");
3215
+ values[field] = this.dialect.transformPrimitive(/* @__PURE__ */ new Date(), "DateTime", false);
2911
3216
  }
2912
3217
  }
2913
3218
  }
@@ -2915,7 +3220,7 @@ var BaseOperationHandler = class {
2915
3220
  }
2916
3221
  evalGenerator(defaultValue) {
2917
3222
  if (ExpressionUtils.isCall(defaultValue)) {
2918
- return match8(defaultValue.function).with("cuid", () => createId()).with("uuid", () => defaultValue.args?.[0] && ExpressionUtils.isLiteral(defaultValue.args?.[0]) && defaultValue.args[0].value === 7 ? uuid.v7() : uuid.v4()).with("nanoid", () => defaultValue.args?.[0] && ExpressionUtils.isLiteral(defaultValue.args[0]) && typeof defaultValue.args[0].value === "number" ? nanoid(defaultValue.args[0].value) : nanoid()).with("ulid", () => ulid()).otherwise(() => void 0);
3223
+ return match9(defaultValue.function).with("cuid", () => createId()).with("uuid", () => defaultValue.args?.[0] && ExpressionUtils.isLiteral(defaultValue.args?.[0]) && defaultValue.args[0].value === 7 ? uuid.v7() : uuid.v4()).with("nanoid", () => defaultValue.args?.[0] && ExpressionUtils.isLiteral(defaultValue.args[0]) && typeof defaultValue.args[0].value === "number" ? nanoid(defaultValue.args[0].value) : nanoid()).with("ulid", () => ulid()).otherwise(() => void 0);
2919
3224
  } else if (ExpressionUtils.isMember(defaultValue) && ExpressionUtils.isCall(defaultValue.receiver) && defaultValue.receiver.function === "auth") {
2920
3225
  let val = this.client.$auth;
2921
3226
  for (const member of defaultValue.members) {
@@ -2972,32 +3277,37 @@ var BaseOperationHandler = class {
2972
3277
  if (finalData === data) {
2973
3278
  finalData = clone(data);
2974
3279
  }
2975
- finalData[fieldName] = this.dialect.transformPrimitive(/* @__PURE__ */ new Date(), "DateTime");
3280
+ finalData[fieldName] = this.dialect.transformPrimitive(/* @__PURE__ */ new Date(), "DateTime", false);
2976
3281
  }
2977
3282
  }
2978
3283
  if (Object.keys(finalData).length === 0) {
2979
- const r = await this.readUnique(kysely, model, {
2980
- where: combinedWhere
3284
+ return combinedWhere;
3285
+ }
3286
+ let needIdRead = false;
3287
+ if (modelDef.baseModel && !this.isIdFilter(model, combinedWhere)) {
3288
+ needIdRead = true;
3289
+ }
3290
+ if (needIdRead) {
3291
+ const readResult = await this.readUnique(kysely, model, {
3292
+ where: combinedWhere,
3293
+ select: this.makeIdSelect(model)
2981
3294
  });
2982
- if (!r && throwIfNotFound) {
3295
+ if (!readResult && throwIfNotFound) {
2983
3296
  throw new NotFoundError(model);
2984
3297
  }
2985
- return r;
3298
+ combinedWhere = readResult;
3299
+ }
3300
+ if (modelDef.baseModel) {
3301
+ const baseUpdateResult = await this.processBaseModelUpdate(kysely, modelDef.baseModel, combinedWhere, finalData, throwIfNotFound);
3302
+ finalData = baseUpdateResult.remainingFields;
3303
+ combinedWhere = baseUpdateResult.baseEntity;
2986
3304
  }
2987
3305
  const updateFields = {};
2988
3306
  let thisEntity = void 0;
2989
3307
  for (const field in finalData) {
2990
3308
  const fieldDef = this.requireField(model, field);
2991
3309
  if (isScalarField(this.schema, model, field) || isForeignKeyField(this.schema, model, field)) {
2992
- if (this.isNumericField(fieldDef) && typeof finalData[field] === "object" && finalData[field]) {
2993
- updateFields[field] = this.transformIncrementalUpdate(model, field, fieldDef, finalData[field]);
2994
- continue;
2995
- }
2996
- if (fieldDef.array && typeof finalData[field] === "object" && !Array.isArray(finalData[field]) && finalData[field]) {
2997
- updateFields[field] = this.transformScalarListUpdate(model, field, fieldDef, finalData[field]);
2998
- continue;
2999
- }
3000
- updateFields[field] = this.dialect.transformPrimitive(finalData[field], fieldDef.type);
3310
+ updateFields[field] = this.processScalarFieldUpdateData(model, field, finalData);
3001
3311
  } else {
3002
3312
  if (!allowRelationUpdate) {
3003
3313
  throw new QueryError(`Relation update not allowed for field "${field}"`);
@@ -3019,16 +3329,14 @@ var BaseOperationHandler = class {
3019
3329
  }
3020
3330
  }
3021
3331
  if (Object.keys(updateFields).length === 0) {
3022
- return thisEntity ?? await this.readUnique(kysely, model, {
3023
- where: combinedWhere
3024
- });
3332
+ return combinedWhere;
3025
3333
  } else {
3026
3334
  const idFields = getIdFields(this.schema, model);
3027
3335
  const query = kysely.updateTable(model).where((eb) => this.dialect.buildFilter(eb, model, model, combinedWhere)).set(updateFields).returning(idFields).modifyEnd(this.makeContextComment({
3028
3336
  model,
3029
3337
  operation: "update"
3030
3338
  }));
3031
- const updatedEntity = await query.executeTakeFirst();
3339
+ const updatedEntity = await this.executeQueryTakeFirst(kysely, query, "update");
3032
3340
  if (!updatedEntity) {
3033
3341
  if (throwIfNotFound) {
3034
3342
  throw new NotFoundError(model);
@@ -3039,23 +3347,72 @@ var BaseOperationHandler = class {
3039
3347
  return updatedEntity;
3040
3348
  }
3041
3349
  }
3350
+ processScalarFieldUpdateData(model, field, data) {
3351
+ const fieldDef = this.requireField(model, field);
3352
+ if (this.isNumericIncrementalUpdate(fieldDef, data[field])) {
3353
+ return this.transformIncrementalUpdate(model, field, fieldDef, data[field]);
3354
+ }
3355
+ if (fieldDef.array && typeof data[field] === "object" && !Array.isArray(data[field]) && data[field]) {
3356
+ return this.transformScalarListUpdate(model, field, fieldDef, data[field]);
3357
+ }
3358
+ return this.dialect.transformPrimitive(data[field], fieldDef.type, !!fieldDef.array);
3359
+ }
3360
+ isNumericIncrementalUpdate(fieldDef, value) {
3361
+ if (!this.isNumericField(fieldDef)) {
3362
+ return false;
3363
+ }
3364
+ if (typeof value !== "object" || !value) {
3365
+ return false;
3366
+ }
3367
+ return [
3368
+ "increment",
3369
+ "decrement",
3370
+ "multiply",
3371
+ "divide",
3372
+ "set"
3373
+ ].some((key) => key in value);
3374
+ }
3375
+ isIdFilter(model, filter) {
3376
+ if (!filter || typeof filter !== "object") {
3377
+ return false;
3378
+ }
3379
+ const idFields = getIdFields(this.schema, model);
3380
+ return idFields.length === Object.keys(filter).length && idFields.every((field) => field in filter);
3381
+ }
3382
+ async processBaseModelUpdate(kysely, model, where, updateFields, throwIfNotFound) {
3383
+ const thisUpdateFields = {};
3384
+ const remainingFields = {};
3385
+ Object.entries(updateFields).forEach(([field, value]) => {
3386
+ const fieldDef = this.getField(model, field);
3387
+ if (fieldDef) {
3388
+ thisUpdateFields[field] = value;
3389
+ } else {
3390
+ remainingFields[field] = value;
3391
+ }
3392
+ });
3393
+ const baseEntity = await this.update(kysely, model, where, thisUpdateFields, void 0, void 0, throwIfNotFound);
3394
+ return {
3395
+ baseEntity,
3396
+ remainingFields
3397
+ };
3398
+ }
3042
3399
  transformIncrementalUpdate(model, field, fieldDef, payload) {
3043
3400
  invariant7(Object.keys(payload).length === 1, 'Only one of "set", "increment", "decrement", "multiply", or "divide" can be provided');
3044
3401
  const key = Object.keys(payload)[0];
3045
- const value = this.dialect.transformPrimitive(payload[key], fieldDef.type);
3402
+ const value = this.dialect.transformPrimitive(payload[key], fieldDef.type, false);
3046
3403
  const eb = expressionBuilder2();
3047
3404
  const fieldRef = buildFieldRef(this.schema, model, field, this.options, eb);
3048
- return match8(key).with("set", () => value).with("increment", () => eb(fieldRef, "+", value)).with("decrement", () => eb(fieldRef, "-", value)).with("multiply", () => eb(fieldRef, "*", value)).with("divide", () => eb(fieldRef, "/", value)).otherwise(() => {
3405
+ return match9(key).with("set", () => value).with("increment", () => eb(fieldRef, "+", value)).with("decrement", () => eb(fieldRef, "-", value)).with("multiply", () => eb(fieldRef, "*", value)).with("divide", () => eb(fieldRef, "/", value)).otherwise(() => {
3049
3406
  throw new InternalError(`Invalid incremental update operation: ${key}`);
3050
3407
  });
3051
3408
  }
3052
3409
  transformScalarListUpdate(model, field, fieldDef, payload) {
3053
3410
  invariant7(Object.keys(payload).length === 1, 'Only one of "set", "push" can be provided');
3054
3411
  const key = Object.keys(payload)[0];
3055
- const value = this.dialect.transformPrimitive(payload[key], fieldDef.type);
3412
+ const value = this.dialect.transformPrimitive(payload[key], fieldDef.type, true);
3056
3413
  const eb = expressionBuilder2();
3057
3414
  const fieldRef = buildFieldRef(this.schema, model, field, this.options, eb);
3058
- return match8(key).with("set", () => value).with("push", () => {
3415
+ return match9(key).with("set", () => value).with("push", () => {
3059
3416
  return eb(fieldRef, "||", eb.val(ensureArray(value)));
3060
3417
  }).otherwise(() => {
3061
3418
  throw new InternalError(`Invalid array update operation: ${key}`);
@@ -3067,7 +3424,7 @@ var BaseOperationHandler = class {
3067
3424
  makeContextComment(context) {
3068
3425
  return sql4.raw(`${CONTEXT_COMMENT_PREFIX}${JSON.stringify(context)}`);
3069
3426
  }
3070
- async updateMany(kysely, model, where, data, limit, returnData) {
3427
+ async updateMany(kysely, model, where, data, limit, returnData, filterModel) {
3071
3428
  if (typeof data !== "object") {
3072
3429
  throw new InternalError("data must be an object");
3073
3430
  }
@@ -3076,49 +3433,79 @@ var BaseOperationHandler = class {
3076
3433
  count: 0
3077
3434
  };
3078
3435
  }
3079
- const updateFields = {};
3436
+ const modelDef = this.requireModel(model);
3437
+ if (modelDef.baseModel && limit !== void 0) {
3438
+ throw new QueryError("Updating with a limit is not supported for polymorphic models");
3439
+ }
3440
+ filterModel ??= model;
3441
+ let updateFields = {};
3080
3442
  for (const field in data) {
3081
- const fieldDef = this.requireField(model, field);
3082
3443
  if (isRelationField(this.schema, model, field)) {
3083
3444
  continue;
3084
3445
  }
3085
- updateFields[field] = this.dialect.transformPrimitive(data[field], fieldDef.type);
3446
+ updateFields[field] = this.processScalarFieldUpdateData(model, field, data);
3447
+ }
3448
+ let shouldFallbackToIdFilter = false;
3449
+ if (limit !== void 0 && !this.dialect.supportsUpdateWithLimit) {
3450
+ shouldFallbackToIdFilter = true;
3451
+ }
3452
+ if (modelDef.isDelegate || modelDef.baseModel) {
3453
+ shouldFallbackToIdFilter = true;
3454
+ }
3455
+ let resultFromBaseModel = void 0;
3456
+ if (modelDef.baseModel) {
3457
+ const baseResult = await this.processBaseModelUpdateMany(kysely, modelDef.baseModel, where, updateFields, filterModel);
3458
+ updateFields = baseResult.remainingFields;
3459
+ resultFromBaseModel = baseResult.baseResult;
3460
+ }
3461
+ if (Object.keys(updateFields).length === 0) {
3462
+ return resultFromBaseModel ?? (returnData ? [] : {
3463
+ count: 0
3464
+ });
3086
3465
  }
3087
3466
  let query = kysely.updateTable(model).set(updateFields);
3088
- if (limit === void 0) {
3089
- query = query.where((eb) => this.dialect.buildFilter(eb, model, model, where));
3467
+ if (!shouldFallbackToIdFilter) {
3468
+ query = query.where((eb) => this.dialect.buildFilter(eb, model, model, where)).$if(limit !== void 0, (qb) => qb.limit(limit));
3090
3469
  } else {
3091
- if (this.dialect.supportsUpdateWithLimit) {
3092
- query = query.where((eb) => this.dialect.buildFilter(eb, model, model, where)).limit(limit);
3093
- } else {
3094
- query = query.where((eb) => eb(eb.refTuple(
3095
- ...this.buildIdFieldRefs(kysely, model)
3096
- ), "in", kysely.selectFrom(model).where((eb2) => this.dialect.buildFilter(eb2, model, model, where)).select(this.buildIdFieldRefs(kysely, model)).limit(limit)));
3097
- }
3470
+ query = query.where((eb) => eb(eb.refTuple(
3471
+ ...this.buildIdFieldRefs(kysely, model)
3472
+ ), "in", this.dialect.buildSelectModel(eb, filterModel).where(this.dialect.buildFilter(eb, filterModel, filterModel, where)).select(this.buildIdFieldRefs(kysely, filterModel)).$if(limit !== void 0, (qb) => qb.limit(limit))));
3098
3473
  }
3099
3474
  query = query.modifyEnd(this.makeContextComment({
3100
3475
  model,
3101
3476
  operation: "update"
3102
3477
  }));
3103
- try {
3104
- if (!returnData) {
3105
- const result = await query.executeTakeFirstOrThrow();
3106
- return {
3107
- count: Number(result.numUpdatedRows)
3108
- };
3478
+ if (!returnData) {
3479
+ const result = await this.executeQuery(kysely, query, "update");
3480
+ return {
3481
+ count: Number(result.numAffectedRows)
3482
+ };
3483
+ } else {
3484
+ const idFields = getIdFields(this.schema, model);
3485
+ const result = await query.returning(idFields).execute();
3486
+ return result;
3487
+ }
3488
+ }
3489
+ async processBaseModelUpdateMany(kysely, model, where, updateFields, filterModel) {
3490
+ const thisUpdateFields = {};
3491
+ const remainingFields = {};
3492
+ Object.entries(updateFields).forEach(([field, value]) => {
3493
+ const fieldDef = this.getField(model, field);
3494
+ if (fieldDef) {
3495
+ thisUpdateFields[field] = value;
3109
3496
  } else {
3110
- const idFields = getIdFields(this.schema, model);
3111
- const result = await query.returning(idFields).execute();
3112
- return result;
3497
+ remainingFields[field] = value;
3113
3498
  }
3114
- } catch (err) {
3115
- const { sql: sql10, parameters } = query.compile();
3116
- throw new QueryError(`Error during updateMany: ${err}, sql: ${sql10}, parameters: ${parameters}`);
3117
- }
3499
+ });
3500
+ const baseResult = await this.updateMany(kysely, model, where, thisUpdateFields, void 0, false, filterModel);
3501
+ return {
3502
+ baseResult,
3503
+ remainingFields
3504
+ };
3118
3505
  }
3119
3506
  buildIdFieldRefs(kysely, model) {
3120
3507
  const idFields = getIdFields(this.schema, model);
3121
- return idFields.map((f) => kysely.dynamic.ref(f));
3508
+ return idFields.map((f) => kysely.dynamic.ref(`${model}.${f}`));
3122
3509
  }
3123
3510
  async processRelationUpdates(kysely, model, field, fieldDef, parentIds, args, throwIfNotFound) {
3124
3511
  const tasks = [];
@@ -3236,7 +3623,7 @@ var BaseOperationHandler = class {
3236
3623
  model: fromRelation.model,
3237
3624
  operation: "update"
3238
3625
  }));
3239
- updateResult = await query.executeTakeFirstOrThrow();
3626
+ updateResult = await this.executeQuery(kysely, query, "connect");
3240
3627
  } else {
3241
3628
  const relationFieldDef = this.requireField(fromRelation.model, fromRelation.field);
3242
3629
  if (!relationFieldDef.array) {
@@ -3247,7 +3634,7 @@ var BaseOperationHandler = class {
3247
3634
  model: fromRelation.model,
3248
3635
  operation: "update"
3249
3636
  }));
3250
- await query2.execute();
3637
+ await this.executeQuery(kysely, query2, "disconnect");
3251
3638
  }
3252
3639
  const query = kysely.updateTable(model).where((eb) => eb.or(_data.map((d) => eb.and(d)))).set(keyPairs.reduce((acc, { fk, pk }) => ({
3253
3640
  ...acc,
@@ -3256,9 +3643,9 @@ var BaseOperationHandler = class {
3256
3643
  model,
3257
3644
  operation: "update"
3258
3645
  }));
3259
- updateResult = await query.executeTakeFirstOrThrow();
3646
+ updateResult = await this.executeQuery(kysely, query, "connect");
3260
3647
  }
3261
- if (_data.length > updateResult.numUpdatedRows) {
3648
+ if (_data.length > updateResult.numAffectedRows) {
3262
3649
  throw new NotFoundError(model);
3263
3650
  }
3264
3651
  }
@@ -3326,7 +3713,7 @@ var BaseOperationHandler = class {
3326
3713
  model: fromRelation.model,
3327
3714
  operation: "update"
3328
3715
  }));
3329
- await query.executeTakeFirstOrThrow();
3716
+ await this.executeQuery(kysely, query, "disconnect");
3330
3717
  } else {
3331
3718
  const query = kysely.updateTable(model).where(eb.and([
3332
3719
  // fk filter
@@ -3343,7 +3730,7 @@ var BaseOperationHandler = class {
3343
3730
  model,
3344
3731
  operation: "update"
3345
3732
  }));
3346
- await query.executeTakeFirstOrThrow();
3733
+ await this.executeQuery(kysely, query, "disconnect");
3347
3734
  }
3348
3735
  }
3349
3736
  }
@@ -3381,7 +3768,7 @@ var BaseOperationHandler = class {
3381
3768
  model,
3382
3769
  operation: "update"
3383
3770
  }));
3384
- await query.execute();
3771
+ await this.executeQuery(kysely, query, "disconnect");
3385
3772
  if (_data.length > 0) {
3386
3773
  const query2 = kysely.updateTable(model).where((eb) => eb.or(_data.map((d) => eb.and(d)))).set(keyPairs.reduce((acc, { fk, pk }) => ({
3387
3774
  ...acc,
@@ -3390,8 +3777,8 @@ var BaseOperationHandler = class {
3390
3777
  model,
3391
3778
  operation: "update"
3392
3779
  }));
3393
- const r = await query2.executeTakeFirstOrThrow();
3394
- if (_data.length > r.numUpdatedRows) {
3780
+ const r = await this.executeQuery(kysely, query2, "connect");
3781
+ if (_data.length > r.numAffectedRows) {
3395
3782
  throw new NotFoundError(model);
3396
3783
  }
3397
3784
  }
@@ -3432,7 +3819,7 @@ var BaseOperationHandler = class {
3432
3819
  OR: deleteConditions
3433
3820
  }
3434
3821
  ]
3435
- }, void 0, false);
3822
+ });
3436
3823
  } else {
3437
3824
  const { ownedByModel, keyPairs } = getRelationForeignKeyFieldPairs(this.schema, fromRelation.model, fromRelation.field);
3438
3825
  if (ownedByModel) {
@@ -3455,7 +3842,7 @@ var BaseOperationHandler = class {
3455
3842
  OR: deleteConditions
3456
3843
  }
3457
3844
  ]
3458
- }, void 0, false);
3845
+ });
3459
3846
  } else {
3460
3847
  deleteResult = await this.delete(kysely, model, {
3461
3848
  AND: [
@@ -3467,7 +3854,7 @@ var BaseOperationHandler = class {
3467
3854
  OR: deleteConditions
3468
3855
  }
3469
3856
  ]
3470
- }, void 0, false);
3857
+ });
3471
3858
  }
3472
3859
  }
3473
3860
  if (throwForNotFound && expectedDeleteCount > deleteResult.count) {
@@ -3478,33 +3865,59 @@ var BaseOperationHandler = class {
3478
3865
  return enumerate(data).map((item) => flattenCompoundUniqueFilters(this.schema, model, item));
3479
3866
  }
3480
3867
  // #endregion
3481
- async delete(kysely, model, where, limit, returnData) {
3868
+ async delete(kysely, model, where, limit, filterModel) {
3869
+ filterModel ??= model;
3870
+ const modelDef = this.requireModel(model);
3871
+ if (modelDef.baseModel) {
3872
+ if (limit !== void 0) {
3873
+ throw new QueryError("Deleting with a limit is not supported for polymorphic models");
3874
+ }
3875
+ return this.processBaseModelDelete(kysely, modelDef.baseModel, where, limit, filterModel);
3876
+ }
3482
3877
  let query = kysely.deleteFrom(model);
3483
- if (limit === void 0) {
3878
+ let needIdFilter = false;
3879
+ if (limit !== void 0 && !this.dialect.supportsDeleteWithLimit) {
3880
+ needIdFilter = true;
3881
+ }
3882
+ if (modelDef.isDelegate || modelDef.baseModel) {
3883
+ needIdFilter = true;
3884
+ }
3885
+ if (!needIdFilter) {
3484
3886
  query = query.where((eb) => this.dialect.buildFilter(eb, model, model, where));
3485
3887
  } else {
3486
- if (this.dialect.supportsDeleteWithLimit) {
3487
- query = query.where((eb) => this.dialect.buildFilter(eb, model, model, where)).limit(limit);
3488
- } else {
3489
- query = query.where((eb) => eb(eb.refTuple(
3490
- ...this.buildIdFieldRefs(kysely, model)
3491
- ), "in", kysely.selectFrom(model).where((eb2) => this.dialect.buildFilter(eb2, model, model, where)).select(this.buildIdFieldRefs(kysely, model)).limit(limit)));
3492
- }
3888
+ query = query.where((eb) => eb(eb.refTuple(
3889
+ ...this.buildIdFieldRefs(kysely, model)
3890
+ ), "in", this.dialect.buildSelectModel(eb, filterModel).where((eb2) => this.dialect.buildFilter(eb2, filterModel, filterModel, where)).select(this.buildIdFieldRefs(kysely, filterModel)).$if(limit !== void 0, (qb) => qb.limit(limit))));
3493
3891
  }
3892
+ await this.processDelegateRelationDelete(kysely, modelDef, where, limit);
3494
3893
  query = query.modifyEnd(this.makeContextComment({
3495
3894
  model,
3496
3895
  operation: "delete"
3497
3896
  }));
3498
- if (returnData) {
3499
- const result = await query.execute();
3500
- return result;
3501
- } else {
3502
- const result = await query.executeTakeFirstOrThrow();
3503
- return {
3504
- count: Number(result.numDeletedRows)
3505
- };
3897
+ const result = await this.executeQuery(kysely, query, "delete");
3898
+ return {
3899
+ count: Number(result.numAffectedRows)
3900
+ };
3901
+ }
3902
+ async processDelegateRelationDelete(kysely, modelDef, where, limit) {
3903
+ for (const fieldDef of Object.values(modelDef.fields)) {
3904
+ if (fieldDef.relation && fieldDef.relation.opposite) {
3905
+ const oppositeModelDef = this.requireModel(fieldDef.type);
3906
+ const oppositeRelation = this.requireField(fieldDef.type, fieldDef.relation.opposite);
3907
+ if (oppositeModelDef.baseModel && oppositeRelation.relation?.onDelete === "Cascade") {
3908
+ if (limit !== void 0) {
3909
+ throw new QueryError("Deleting with a limit is not supported for polymorphic models");
3910
+ }
3911
+ await this.delete(kysely, fieldDef.type, {
3912
+ [fieldDef.relation.opposite]: where
3913
+ }, void 0);
3914
+ }
3915
+ }
3506
3916
  }
3507
3917
  }
3918
+ async processBaseModelDelete(kysely, model, where, limit, filterModel) {
3919
+ return this.delete(kysely, model, where, limit, filterModel);
3920
+ }
3508
3921
  makeIdSelect(model) {
3509
3922
  const modelDef = this.requireModel(model);
3510
3923
  return modelDef.idFields.reduce((acc, f) => {
@@ -3513,7 +3926,7 @@ var BaseOperationHandler = class {
3513
3926
  }, {});
3514
3927
  }
3515
3928
  trimResult(data, args) {
3516
- if (!args.select) {
3929
+ if (!("select" in args) || !args.select) {
3517
3930
  return data;
3518
3931
  }
3519
3932
  return Object.keys(args.select).reduce((acc, field) => {
@@ -3523,9 +3936,9 @@ var BaseOperationHandler = class {
3523
3936
  }
3524
3937
  needReturnRelations(model, args) {
3525
3938
  let returnRelation = false;
3526
- if (args.include) {
3939
+ if ("include" in args && args.include) {
3527
3940
  returnRelation = Object.keys(args.include).length > 0;
3528
- } else if (args.select) {
3941
+ } else if ("select" in args && args.select) {
3529
3942
  returnRelation = Object.entries(args.select).some(([K, v]) => {
3530
3943
  const fieldDef = this.requireField(model, K);
3531
3944
  return fieldDef.relation && v;
@@ -3533,11 +3946,13 @@ var BaseOperationHandler = class {
3533
3946
  }
3534
3947
  return returnRelation;
3535
3948
  }
3536
- async safeTransaction(callback) {
3949
+ async safeTransaction(callback, isolationLevel) {
3537
3950
  if (this.kysely.isTransaction) {
3538
3951
  return callback(this.kysely);
3539
3952
  } else {
3540
- return this.kysely.transaction().setIsolationLevel("repeatable read").execute(callback);
3953
+ let txBuilder = this.kysely.transaction();
3954
+ txBuilder = txBuilder.setIsolationLevel(isolationLevel ?? "repeatable read");
3955
+ return txBuilder.execute(callback);
3541
3956
  }
3542
3957
  }
3543
3958
  // Given a unique filter of a model, return the entity ids by trying to
@@ -3552,9 +3967,50 @@ var BaseOperationHandler = class {
3552
3967
  ) {
3553
3968
  return uniqueFilter;
3554
3969
  }
3555
- return this.readUnique(kysely, model, {
3556
- where: uniqueFilter
3557
- });
3970
+ return this.readUnique(kysely, model, {
3971
+ where: uniqueFilter
3972
+ });
3973
+ }
3974
+ /**
3975
+ * Normalize input args to strip `undefined` fields
3976
+ */
3977
+ normalizeArgs(args) {
3978
+ if (!args) {
3979
+ return;
3980
+ }
3981
+ const newArgs = clone(args);
3982
+ this.doNormalizeArgs(newArgs);
3983
+ return newArgs;
3984
+ }
3985
+ doNormalizeArgs(args) {
3986
+ if (args && typeof args === "object") {
3987
+ for (const [key, value] of Object.entries(args)) {
3988
+ if (value === void 0) {
3989
+ delete args[key];
3990
+ } else if (value && isPlainObject3(value)) {
3991
+ this.doNormalizeArgs(value);
3992
+ }
3993
+ }
3994
+ }
3995
+ }
3996
+ makeQueryId(operation) {
3997
+ return {
3998
+ queryId: `${operation}-${createId()}`
3999
+ };
4000
+ }
4001
+ executeQuery(kysely, query, operation) {
4002
+ return kysely.executeQuery(query.compile(), this.makeQueryId(operation));
4003
+ }
4004
+ async executeQueryTakeFirst(kysely, query, operation) {
4005
+ const result = await kysely.executeQuery(query.compile(), this.makeQueryId(operation));
4006
+ return result.rows[0];
4007
+ }
4008
+ async executeQueryTakeFirstOrThrow(kysely, query, operation) {
4009
+ const result = await kysely.executeQuery(query.compile(), this.makeQueryId(operation));
4010
+ if (result.rows.length === 0) {
4011
+ throw new QueryError("No rows found");
4012
+ }
4013
+ return result.rows[0];
3558
4014
  }
3559
4015
  };
3560
4016
 
@@ -3564,21 +4020,37 @@ var AggregateOperationHandler = class extends BaseOperationHandler {
3564
4020
  __name(this, "AggregateOperationHandler");
3565
4021
  }
3566
4022
  async handle(_operation, args) {
3567
- const validatedArgs = this.inputValidator.validateAggregateArgs(this.model, args);
4023
+ const normalizedArgs = this.normalizeArgs(args);
4024
+ const parsedArgs = this.inputValidator.validateAggregateArgs(this.model, normalizedArgs);
3568
4025
  let query = this.kysely.selectFrom((eb) => {
3569
- let subQuery = eb.selectFrom(this.model).selectAll(this.model).where((eb1) => this.dialect.buildFilter(eb1, this.model, this.model, validatedArgs?.where));
3570
- const skip = validatedArgs?.skip;
3571
- let take = validatedArgs?.take;
4026
+ let subQuery = this.dialect.buildSelectModel(eb, this.model).where((eb1) => this.dialect.buildFilter(eb1, this.model, this.model, parsedArgs?.where));
4027
+ const selectedFields = [];
4028
+ for (const [key, value] of Object.entries(parsedArgs)) {
4029
+ if (key.startsWith("_") && value && typeof value === "object") {
4030
+ Object.entries(value).filter(([field]) => field !== "_all").filter(([, val]) => val === true).forEach(([field]) => {
4031
+ if (!selectedFields.includes(field)) selectedFields.push(field);
4032
+ });
4033
+ }
4034
+ }
4035
+ if (selectedFields.length > 0) {
4036
+ for (const field of selectedFields) {
4037
+ subQuery = this.dialect.buildSelectField(subQuery, this.model, this.model, field);
4038
+ }
4039
+ } else {
4040
+ subQuery = subQuery.select(() => eb.lit(1).as("_all"));
4041
+ }
4042
+ const skip = parsedArgs?.skip;
4043
+ let take = parsedArgs?.take;
3572
4044
  let negateOrderBy = false;
3573
4045
  if (take !== void 0 && take < 0) {
3574
4046
  negateOrderBy = true;
3575
4047
  take = -take;
3576
4048
  }
3577
4049
  subQuery = this.dialect.buildSkipTake(subQuery, skip, take);
3578
- subQuery = this.dialect.buildOrderBy(subQuery, this.model, this.model, validatedArgs.orderBy, skip !== void 0 || take !== void 0, negateOrderBy);
4050
+ subQuery = this.dialect.buildOrderBy(subQuery, this.model, this.model, parsedArgs.orderBy, skip !== void 0 || take !== void 0, negateOrderBy);
3579
4051
  return subQuery.as("$sub");
3580
4052
  });
3581
- for (const [key, value] of Object.entries(validatedArgs)) {
4053
+ for (const [key, value] of Object.entries(parsedArgs)) {
3582
4054
  switch (key) {
3583
4055
  case "_count": {
3584
4056
  if (value === true) {
@@ -3603,7 +4075,7 @@ var AggregateOperationHandler = class extends BaseOperationHandler {
3603
4075
  Object.entries(value).forEach(([field, val]) => {
3604
4076
  if (val === true) {
3605
4077
  query = query.select((eb) => {
3606
- const fn = match9(key).with("_sum", () => eb.fn.sum).with("_avg", () => eb.fn.avg).with("_max", () => eb.fn.max).with("_min", () => eb.fn.min).exhaustive();
4078
+ const fn = match10(key).with("_sum", () => eb.fn.sum).with("_avg", () => eb.fn.avg).with("_max", () => eb.fn.max).with("_min", () => eb.fn.min).exhaustive();
3607
4079
  return fn(sql5.ref(`$sub.${field}`)).as(`${key}.${field}`);
3608
4080
  });
3609
4081
  }
@@ -3612,9 +4084,9 @@ var AggregateOperationHandler = class extends BaseOperationHandler {
3612
4084
  }
3613
4085
  }
3614
4086
  }
3615
- const result = await query.executeTakeFirstOrThrow();
4087
+ const result = await this.executeQuery(this.kysely, query, "aggregate");
3616
4088
  const ret = {};
3617
- for (const [key, value] of Object.entries(result)) {
4089
+ for (const [key, value] of Object.entries(result.rows[0])) {
3618
4090
  if (key === "_count") {
3619
4091
  ret[key] = value;
3620
4092
  continue;
@@ -3636,7 +4108,7 @@ var AggregateOperationHandler = class extends BaseOperationHandler {
3636
4108
  val = parseFloat(val);
3637
4109
  } else {
3638
4110
  if (op === "_sum" || op === "_min" || op === "_max") {
3639
- val = match9(type).with("Int", () => parseInt(value, 10)).with("BigInt", () => BigInt(value)).with("Float", () => parseFloat(value)).with("Decimal", () => parseFloat(value)).otherwise(() => value);
4111
+ val = match10(type).with("Int", () => parseInt(value, 10)).with("BigInt", () => BigInt(value)).with("Float", () => parseFloat(value)).with("Decimal", () => parseFloat(value)).otherwise(() => value);
3640
4112
  }
3641
4113
  }
3642
4114
  }
@@ -3657,34 +4129,47 @@ var CountOperationHandler = class extends BaseOperationHandler {
3657
4129
  __name(this, "CountOperationHandler");
3658
4130
  }
3659
4131
  async handle(_operation, args) {
3660
- const validatedArgs = this.inputValidator.validateCountArgs(this.model, args);
4132
+ const normalizedArgs = this.normalizeArgs(args);
4133
+ const parsedArgs = this.inputValidator.validateCountArgs(this.model, normalizedArgs);
4134
+ const subQueryName = "$sub";
3661
4135
  let query = this.kysely.selectFrom((eb) => {
3662
- let subQuery = eb.selectFrom(this.model).selectAll().where((eb1) => this.dialect.buildFilter(eb1, this.model, this.model, validatedArgs?.where));
3663
- subQuery = this.dialect.buildSkipTake(subQuery, validatedArgs?.skip, validatedArgs?.take);
3664
- return subQuery.as("$sub");
4136
+ let subQuery = this.dialect.buildSelectModel(eb, this.model).where((eb1) => this.dialect.buildFilter(eb1, this.model, this.model, parsedArgs?.where));
4137
+ if (parsedArgs?.select && typeof parsedArgs.select === "object") {
4138
+ for (const [key, value] of Object.entries(parsedArgs.select)) {
4139
+ if (key !== "_all" && value === true) {
4140
+ subQuery = this.dialect.buildSelectField(subQuery, this.model, this.model, key);
4141
+ }
4142
+ }
4143
+ } else {
4144
+ subQuery = subQuery.select(() => eb.lit(1).as("_all"));
4145
+ }
4146
+ subQuery = this.dialect.buildSkipTake(subQuery, parsedArgs?.skip, parsedArgs?.take);
4147
+ return subQuery.as(subQueryName);
3665
4148
  });
3666
- if (validatedArgs?.select && typeof validatedArgs.select === "object") {
3667
- query = query.select((eb) => Object.keys(validatedArgs.select).map((key) => key === "_all" ? eb.cast(eb.fn.countAll(), "integer").as("_all") : eb.cast(eb.fn.count(sql6.ref(`$sub.${key}`)), "integer").as(key)));
3668
- return query.executeTakeFirstOrThrow();
4149
+ if (parsedArgs?.select && typeof parsedArgs.select === "object") {
4150
+ query = query.select((eb) => Object.keys(parsedArgs.select).map((key) => key === "_all" ? eb.cast(eb.fn.countAll(), "integer").as("_all") : eb.cast(eb.fn.count(sql6.ref(`${subQueryName}.${key}`)), "integer").as(key)));
4151
+ const result = await this.executeQuery(this.kysely, query, "count");
4152
+ return result.rows[0];
3669
4153
  } else {
3670
4154
  query = query.select((eb) => eb.cast(eb.fn.countAll(), "integer").as("count"));
3671
- const result = await query.executeTakeFirstOrThrow();
3672
- return result.count;
4155
+ const result = await this.executeQuery(this.kysely, query, "count");
4156
+ return result.rows[0].count;
3673
4157
  }
3674
4158
  }
3675
4159
  };
3676
4160
 
3677
4161
  // src/client/crud/operations/create.ts
3678
- import { match as match10 } from "ts-pattern";
4162
+ import { match as match11 } from "ts-pattern";
3679
4163
  var CreateOperationHandler = class extends BaseOperationHandler {
3680
4164
  static {
3681
4165
  __name(this, "CreateOperationHandler");
3682
4166
  }
3683
4167
  async handle(operation, args) {
3684
- return match10(operation).with("create", () => this.runCreate(this.inputValidator.validateCreateArgs(this.model, args))).with("createMany", () => {
3685
- return this.runCreateMany(this.inputValidator.validateCreateManyArgs(this.model, args));
4168
+ const normalizedArgs = this.normalizeArgs(args);
4169
+ return match11(operation).with("create", () => this.runCreate(this.inputValidator.validateCreateArgs(this.model, normalizedArgs))).with("createMany", () => {
4170
+ return this.runCreateMany(this.inputValidator.validateCreateManyArgs(this.model, normalizedArgs));
3686
4171
  }).with("createManyAndReturn", () => {
3687
- return this.runCreateManyAndReturn(this.inputValidator.validateCreateManyAndReturnArgs(this.model, args));
4172
+ return this.runCreateManyAndReturn(this.inputValidator.validateCreateManyAndReturnArgs(this.model, normalizedArgs));
3688
4173
  }).exhaustive();
3689
4174
  }
3690
4175
  async runCreate(args) {
@@ -3728,13 +4213,14 @@ var CreateOperationHandler = class extends BaseOperationHandler {
3728
4213
  };
3729
4214
 
3730
4215
  // src/client/crud/operations/delete.ts
3731
- import { match as match11 } from "ts-pattern";
4216
+ import { match as match12 } from "ts-pattern";
3732
4217
  var DeleteOperationHandler = class extends BaseOperationHandler {
3733
4218
  static {
3734
4219
  __name(this, "DeleteOperationHandler");
3735
4220
  }
3736
4221
  async handle(operation, args) {
3737
- return match11(operation).with("delete", () => this.runDelete(this.inputValidator.validateDeleteArgs(this.model, args))).with("deleteMany", () => this.runDeleteMany(this.inputValidator.validateDeleteManyArgs(this.model, args))).exhaustive();
4222
+ const normalizedArgs = this.normalizeArgs(args);
4223
+ return match12(operation).with("delete", () => this.runDelete(this.inputValidator.validateDeleteArgs(this.model, normalizedArgs))).with("deleteMany", () => this.runDeleteMany(this.inputValidator.validateDeleteManyArgs(this.model, normalizedArgs))).exhaustive();
3738
4224
  }
3739
4225
  async runDelete(args) {
3740
4226
  const existing = await this.readUnique(this.kysely, this.model, {
@@ -3746,15 +4232,19 @@ var DeleteOperationHandler = class extends BaseOperationHandler {
3746
4232
  if (!existing) {
3747
4233
  throw new NotFoundError(this.model);
3748
4234
  }
3749
- const result = await this.delete(this.kysely, this.model, args.where, void 0, false);
3750
- if (result.count === 0) {
3751
- throw new NotFoundError(this.model);
3752
- }
4235
+ await this.safeTransaction(async (tx) => {
4236
+ const result = await this.delete(tx, this.model, args.where);
4237
+ if (result.count === 0) {
4238
+ throw new NotFoundError(this.model);
4239
+ }
4240
+ });
3753
4241
  return existing;
3754
4242
  }
3755
4243
  async runDeleteMany(args) {
3756
- const result = await this.delete(this.kysely, this.model, args?.where, args?.limit, false);
3757
- return result;
4244
+ return await this.safeTransaction(async (tx) => {
4245
+ const result = await this.delete(tx, this.model, args?.where, args?.limit);
4246
+ return result;
4247
+ });
3758
4248
  }
3759
4249
  };
3760
4250
 
@@ -3764,7 +4254,8 @@ var FindOperationHandler = class extends BaseOperationHandler {
3764
4254
  __name(this, "FindOperationHandler");
3765
4255
  }
3766
4256
  async handle(operation, args, validateArgs = true) {
3767
- const parsedArgs = validateArgs ? this.inputValidator.validateFindArgs(this.model, operation === "findUnique", args) : args;
4257
+ const normalizedArgs = this.normalizeArgs(args);
4258
+ const parsedArgs = validateArgs ? this.inputValidator.validateFindArgs(this.model, operation === "findUnique", normalizedArgs) : normalizedArgs;
3768
4259
  const result = await this.read(this.client.$qb, this.model, parsedArgs);
3769
4260
  const finalResult = operation === "findMany" ? result : result[0] ?? null;
3770
4261
  return finalResult;
@@ -3773,17 +4264,18 @@ var FindOperationHandler = class extends BaseOperationHandler {
3773
4264
 
3774
4265
  // src/client/crud/operations/group-by.ts
3775
4266
  import { sql as sql7 } from "kysely";
3776
- import { match as match12 } from "ts-pattern";
3777
- var GroupByeOperationHandler = class extends BaseOperationHandler {
4267
+ import { match as match13 } from "ts-pattern";
4268
+ var GroupByOperationHandler = class extends BaseOperationHandler {
3778
4269
  static {
3779
- __name(this, "GroupByeOperationHandler");
4270
+ __name(this, "GroupByOperationHandler");
3780
4271
  }
3781
4272
  async handle(_operation, args) {
3782
- const validatedArgs = this.inputValidator.validateGroupByArgs(this.model, args);
4273
+ const normalizedArgs = this.normalizeArgs(args);
4274
+ const parsedArgs = this.inputValidator.validateGroupByArgs(this.model, normalizedArgs);
3783
4275
  let query = this.kysely.selectFrom((eb) => {
3784
- let subQuery = eb.selectFrom(this.model).selectAll().where((eb1) => this.dialect.buildFilter(eb1, this.model, this.model, validatedArgs?.where));
3785
- const skip = validatedArgs?.skip;
3786
- let take = validatedArgs?.take;
4276
+ let subQuery = eb.selectFrom(this.model).selectAll().where((eb1) => this.dialect.buildFilter(eb1, this.model, this.model, parsedArgs?.where));
4277
+ const skip = parsedArgs?.skip;
4278
+ let take = parsedArgs?.take;
3787
4279
  let negateOrderBy = false;
3788
4280
  if (take !== void 0 && take < 0) {
3789
4281
  negateOrderBy = true;
@@ -3793,20 +4285,20 @@ var GroupByeOperationHandler = class extends BaseOperationHandler {
3793
4285
  subQuery = this.dialect.buildOrderBy(subQuery, this.model, this.model, void 0, skip !== void 0 || take !== void 0, negateOrderBy);
3794
4286
  return subQuery.as("$sub");
3795
4287
  });
3796
- const bys = typeof validatedArgs.by === "string" ? [
3797
- validatedArgs.by
3798
- ] : validatedArgs.by;
3799
- query = query.groupBy(bys);
3800
- if (validatedArgs.orderBy) {
3801
- query = this.dialect.buildOrderBy(query, this.model, "$sub", validatedArgs.orderBy, false, false);
4288
+ const bys = typeof parsedArgs.by === "string" ? [
4289
+ parsedArgs.by
4290
+ ] : parsedArgs.by;
4291
+ query = query.groupBy(bys.map((by) => sql7.ref(`$sub.${by}`)));
4292
+ if (parsedArgs.orderBy) {
4293
+ query = this.dialect.buildOrderBy(query, this.model, "$sub", parsedArgs.orderBy, false, false);
3802
4294
  }
3803
- if (validatedArgs.having) {
3804
- query = query.having((eb1) => this.dialect.buildFilter(eb1, this.model, "$sub", validatedArgs.having));
4295
+ if (parsedArgs.having) {
4296
+ query = query.having((eb) => this.dialect.buildFilter(eb, this.model, "$sub", parsedArgs.having));
3805
4297
  }
3806
4298
  for (const by of bys) {
3807
4299
  query = query.select(() => sql7.ref(`$sub.${by}`).as(by));
3808
4300
  }
3809
- for (const [key, value] of Object.entries(validatedArgs)) {
4301
+ for (const [key, value] of Object.entries(parsedArgs)) {
3810
4302
  switch (key) {
3811
4303
  case "_count": {
3812
4304
  if (value === true) {
@@ -3831,7 +4323,7 @@ var GroupByeOperationHandler = class extends BaseOperationHandler {
3831
4323
  Object.entries(value).forEach(([field, val]) => {
3832
4324
  if (val === true) {
3833
4325
  query = query.select((eb) => {
3834
- const fn = match12(key).with("_sum", () => eb.fn.sum).with("_avg", () => eb.fn.avg).with("_max", () => eb.fn.max).with("_min", () => eb.fn.min).exhaustive();
4326
+ const fn = match13(key).with("_sum", () => eb.fn.sum).with("_avg", () => eb.fn.avg).with("_max", () => eb.fn.max).with("_min", () => eb.fn.min).exhaustive();
3835
4327
  return fn(sql7.ref(`$sub.${field}`)).as(`${key}.${field}`);
3836
4328
  });
3837
4329
  }
@@ -3840,8 +4332,8 @@ var GroupByeOperationHandler = class extends BaseOperationHandler {
3840
4332
  }
3841
4333
  }
3842
4334
  }
3843
- const result = await query.execute();
3844
- return result.map((row) => this.postProcessRow(row));
4335
+ const result = await this.executeQuery(this.kysely, query, "groupBy");
4336
+ return result.rows.map((row) => this.postProcessRow(row));
3845
4337
  }
3846
4338
  postProcessRow(row) {
3847
4339
  const ret = {};
@@ -3868,7 +4360,7 @@ var GroupByeOperationHandler = class extends BaseOperationHandler {
3868
4360
  val = parseFloat(val);
3869
4361
  } else {
3870
4362
  if (op === "_sum" || op === "_min" || op === "_max") {
3871
- val = match12(type).with("Int", () => parseInt(value, 10)).with("BigInt", () => BigInt(value)).with("Float", () => parseFloat(value)).with("Decimal", () => parseFloat(value)).otherwise(() => value);
4363
+ val = match13(type).with("Int", () => parseInt(value, 10)).with("BigInt", () => BigInt(value)).with("Float", () => parseFloat(value)).with("Decimal", () => parseFloat(value)).otherwise(() => value);
3872
4364
  }
3873
4365
  }
3874
4366
  }
@@ -3883,31 +4375,45 @@ var GroupByeOperationHandler = class extends BaseOperationHandler {
3883
4375
  };
3884
4376
 
3885
4377
  // src/client/crud/operations/update.ts
3886
- import { match as match13 } from "ts-pattern";
4378
+ import { match as match14 } from "ts-pattern";
3887
4379
  var UpdateOperationHandler = class extends BaseOperationHandler {
3888
4380
  static {
3889
4381
  __name(this, "UpdateOperationHandler");
3890
4382
  }
3891
4383
  async handle(operation, args) {
3892
- return match13(operation).with("update", () => this.runUpdate(this.inputValidator.validateUpdateArgs(this.model, args))).with("updateMany", () => this.runUpdateMany(this.inputValidator.validateUpdateManyArgs(this.model, args))).with("updateManyAndReturn", () => this.runUpdateManyAndReturn(this.inputValidator.validateUpdateManyAndReturnArgs(this.model, args))).with("upsert", () => this.runUpsert(this.inputValidator.validateUpsertArgs(this.model, args))).exhaustive();
4384
+ const normalizedArgs = this.normalizeArgs(args);
4385
+ return match14(operation).with("update", () => this.runUpdate(this.inputValidator.validateUpdateArgs(this.model, normalizedArgs))).with("updateMany", () => this.runUpdateMany(this.inputValidator.validateUpdateManyArgs(this.model, normalizedArgs))).with("updateManyAndReturn", () => this.runUpdateManyAndReturn(this.inputValidator.validateUpdateManyAndReturnArgs(this.model, normalizedArgs))).with("upsert", () => this.runUpsert(this.inputValidator.validateUpsertArgs(this.model, normalizedArgs))).exhaustive();
3893
4386
  }
3894
4387
  async runUpdate(args) {
3895
- const result = await this.safeTransaction(async (tx) => {
3896
- const updated = await this.update(tx, this.model, args.where, args.data);
3897
- return this.readUnique(tx, this.model, {
3898
- select: args.select,
3899
- include: args.include,
3900
- omit: args.omit,
3901
- where: getIdValues(this.schema, this.model, updated)
3902
- });
4388
+ const readBackResult = await this.safeTransaction(async (tx) => {
4389
+ const updateResult = await this.update(tx, this.model, args.where, args.data);
4390
+ const readFilter = updateResult ?? args.where;
4391
+ let readBackResult2 = void 0;
4392
+ try {
4393
+ readBackResult2 = await this.readUnique(tx, this.model, {
4394
+ select: args.select,
4395
+ include: args.include,
4396
+ omit: args.omit,
4397
+ where: readFilter
4398
+ });
4399
+ } catch {
4400
+ }
4401
+ return readBackResult2;
3903
4402
  });
3904
- if (!result && this.hasPolicyEnabled) {
3905
- throw new RejectedByPolicyError(this.model, "result is not allowed to be read back");
4403
+ if (!readBackResult) {
4404
+ if (this.hasPolicyEnabled) {
4405
+ throw new RejectedByPolicyError(this.model, "result is not allowed to be read back");
4406
+ } else {
4407
+ return null;
4408
+ }
4409
+ } else {
4410
+ return readBackResult;
3906
4411
  }
3907
- return result;
3908
4412
  }
3909
4413
  async runUpdateMany(args) {
3910
- return this.updateMany(this.kysely, this.model, args.where, args.data, args.limit, false);
4414
+ return this.safeTransaction(async (tx) => {
4415
+ return this.updateMany(tx, this.model, args.where, args.data, args.limit, false);
4416
+ });
3911
4417
  }
3912
4418
  async runUpdateManyAndReturn(args) {
3913
4419
  if (!args) {
@@ -3945,19 +4451,19 @@ var UpdateOperationHandler = class extends BaseOperationHandler {
3945
4451
  };
3946
4452
 
3947
4453
  // src/client/crud/validator.ts
4454
+ import { invariant as invariant8 } from "@zenstackhq/common-helpers";
3948
4455
  import Decimal from "decimal.js";
3949
4456
  import stableStringify from "json-stable-stringify";
3950
- import { match as match14, P as P2 } from "ts-pattern";
4457
+ import { match as match15, P as P2 } from "ts-pattern";
3951
4458
  import { z } from "zod";
3952
4459
  var InputValidator = class {
3953
4460
  static {
3954
4461
  __name(this, "InputValidator");
3955
4462
  }
3956
4463
  schema;
3957
- schemaCache;
4464
+ schemaCache = /* @__PURE__ */ new Map();
3958
4465
  constructor(schema) {
3959
4466
  this.schema = schema;
3960
- this.schemaCache = /* @__PURE__ */ new Map();
3961
4467
  }
3962
4468
  validateFindArgs(model, unique, args) {
3963
4469
  return this.validate(model, "find", {
@@ -4014,7 +4520,7 @@ var InputValidator = class {
4014
4520
  }
4015
4521
  const { error } = schema.safeParse(args);
4016
4522
  if (error) {
4017
- throw new QueryError(`Invalid ${operation} args: ${error.message}`);
4523
+ throw new InputValidationError(`Invalid ${operation} args: ${error.message}`, error);
4018
4524
  }
4019
4525
  return args;
4020
4526
  }
@@ -4033,11 +4539,11 @@ var InputValidator = class {
4033
4539
  fields["distinct"] = this.makeDistinctSchema(model).optional();
4034
4540
  fields["cursor"] = this.makeCursorSchema(model).optional();
4035
4541
  if (options.collection) {
4036
- fields["skip"] = z.number().int().nonnegative().optional();
4037
- fields["take"] = z.number().int().optional();
4542
+ fields["skip"] = this.makeSkipSchema().optional();
4543
+ fields["take"] = this.makeTakeSchema().optional();
4038
4544
  fields["orderBy"] = this.orArray(this.makeOrderBySchema(model, true, false), true).optional();
4039
4545
  }
4040
- let result = z.object(fields).strict();
4546
+ let result = z.strictObject(fields);
4041
4547
  result = this.refineForSelectIncludeMutuallyExclusive(result);
4042
4548
  result = this.refineForSelectOmitMutuallyExclusive(result);
4043
4549
  if (!options.unique) {
@@ -4046,22 +4552,50 @@ var InputValidator = class {
4046
4552
  return result;
4047
4553
  }
4048
4554
  makePrimitiveSchema(type) {
4049
- return match14(type).with("String", () => z.string()).with("Int", () => z.number()).with("Float", () => z.number()).with("Boolean", () => z.boolean()).with("BigInt", () => z.union([
4050
- z.number(),
4051
- z.bigint()
4052
- ])).with("Decimal", () => z.union([
4053
- z.number(),
4054
- z.instanceof(Decimal),
4055
- z.string()
4056
- ])).with("DateTime", () => z.union([
4057
- z.date(),
4058
- z.string().datetime()
4059
- ])).with("Bytes", () => z.instanceof(Uint8Array)).otherwise(() => z.unknown());
4060
- }
4061
- makeWhereSchema(model, unique, withoutRelationFields = false) {
4555
+ if (this.schema.typeDefs && type in this.schema.typeDefs) {
4556
+ return this.makeTypeDefSchema(type);
4557
+ } else {
4558
+ return match15(type).with("String", () => z.string()).with("Int", () => z.int()).with("Float", () => z.number()).with("Boolean", () => z.boolean()).with("BigInt", () => z.union([
4559
+ z.int(),
4560
+ z.bigint()
4561
+ ])).with("Decimal", () => z.union([
4562
+ z.number(),
4563
+ z.instanceof(Decimal),
4564
+ z.string()
4565
+ ])).with("DateTime", () => z.union([
4566
+ z.date(),
4567
+ z.string().datetime()
4568
+ ])).with("Bytes", () => z.instanceof(Uint8Array)).otherwise(() => z.unknown());
4569
+ }
4570
+ }
4571
+ makeTypeDefSchema(type) {
4572
+ const key = `$typedef-${type}`;
4573
+ let schema = this.schemaCache.get(key);
4574
+ if (schema) {
4575
+ return schema;
4576
+ }
4577
+ const typeDef = this.schema.typeDefs?.[type];
4578
+ invariant8(typeDef, `Type definition "${type}" not found in schema`);
4579
+ schema = z.looseObject(Object.fromEntries(Object.entries(typeDef.fields).map(([field, def]) => {
4580
+ let fieldSchema = this.makePrimitiveSchema(def.type);
4581
+ if (def.array) {
4582
+ fieldSchema = fieldSchema.array();
4583
+ }
4584
+ if (def.optional) {
4585
+ fieldSchema = fieldSchema.optional();
4586
+ }
4587
+ return [
4588
+ field,
4589
+ fieldSchema
4590
+ ];
4591
+ })));
4592
+ this.schemaCache.set(key, schema);
4593
+ return schema;
4594
+ }
4595
+ makeWhereSchema(model, unique, withoutRelationFields = false, withAggregations = false) {
4062
4596
  const modelDef = getModel(this.schema, model);
4063
4597
  if (!modelDef) {
4064
- throw new QueryError(`Model "${model}" not found`);
4598
+ throw new QueryError(`Model "${model}" not found in schema`);
4065
4599
  }
4066
4600
  const fields = {};
4067
4601
  for (const field of Object.keys(modelDef.fields)) {
@@ -4076,7 +4610,7 @@ var InputValidator = class {
4076
4610
  if (fieldDef.array) {
4077
4611
  fieldSchema = z.union([
4078
4612
  fieldSchema,
4079
- z.object({
4613
+ z.strictObject({
4080
4614
  some: fieldSchema.optional(),
4081
4615
  every: fieldSchema.optional(),
4082
4616
  none: fieldSchema.optional()
@@ -4085,7 +4619,7 @@ var InputValidator = class {
4085
4619
  } else {
4086
4620
  fieldSchema = z.union([
4087
4621
  fieldSchema,
4088
- z.object({
4622
+ z.strictObject({
4089
4623
  is: fieldSchema.optional(),
4090
4624
  isNot: fieldSchema.optional()
4091
4625
  })
@@ -4095,12 +4629,12 @@ var InputValidator = class {
4095
4629
  const enumDef = getEnum(this.schema, fieldDef.type);
4096
4630
  if (enumDef) {
4097
4631
  if (Object.keys(enumDef).length > 0) {
4098
- fieldSchema = this.makeEnumFilterSchema(enumDef, !!fieldDef.optional);
4632
+ fieldSchema = this.makeEnumFilterSchema(enumDef, !!fieldDef.optional, withAggregations);
4099
4633
  }
4100
4634
  } else if (fieldDef.array) {
4101
4635
  fieldSchema = this.makeArrayFilterSchema(fieldDef.type);
4102
4636
  } else {
4103
- fieldSchema = this.makePrimitiveFilterSchema(fieldDef.type, !!fieldDef.optional);
4637
+ fieldSchema = this.makePrimitiveFilterSchema(fieldDef.type, !!fieldDef.optional, withAggregations);
4104
4638
  }
4105
4639
  }
4106
4640
  if (fieldSchema) {
@@ -4111,18 +4645,32 @@ var InputValidator = class {
4111
4645
  const uniqueFields = getUniqueFields(this.schema, model);
4112
4646
  for (const uniqueField of uniqueFields) {
4113
4647
  if ("defs" in uniqueField) {
4114
- fields[uniqueField.name] = z.object(Object.fromEntries(Object.entries(uniqueField.defs).map(([key, def]) => [
4115
- key,
4116
- this.makePrimitiveFilterSchema(def.type, !!def.optional)
4117
- ]))).optional();
4648
+ fields[uniqueField.name] = z.object(Object.fromEntries(Object.entries(uniqueField.defs).map(([key, def]) => {
4649
+ invariant8(!def.relation, "unique field cannot be a relation");
4650
+ let fieldSchema;
4651
+ const enumDef = getEnum(this.schema, def.type);
4652
+ if (enumDef) {
4653
+ if (Object.keys(enumDef).length > 0) {
4654
+ fieldSchema = this.makeEnumFilterSchema(enumDef, !!def.optional, false);
4655
+ } else {
4656
+ fieldSchema = z.never();
4657
+ }
4658
+ } else {
4659
+ fieldSchema = this.makePrimitiveFilterSchema(def.type, !!def.optional, false);
4660
+ }
4661
+ return [
4662
+ key,
4663
+ fieldSchema
4664
+ ];
4665
+ }))).optional();
4118
4666
  }
4119
4667
  }
4120
4668
  }
4121
- fields["$expr"] = z.function().optional();
4669
+ fields["$expr"] = z.custom((v) => typeof v === "function").optional();
4122
4670
  fields["AND"] = this.orArray(z.lazy(() => this.makeWhereSchema(model, false, withoutRelationFields)), true).optional();
4123
4671
  fields["OR"] = z.lazy(() => this.makeWhereSchema(model, false, withoutRelationFields)).array().optional();
4124
4672
  fields["NOT"] = this.orArray(z.lazy(() => this.makeWhereSchema(model, false, withoutRelationFields)), true).optional();
4125
- const baseWhere = z.object(fields).strict();
4673
+ const baseWhere = z.strictObject(fields);
4126
4674
  let result = baseWhere;
4127
4675
  if (unique) {
4128
4676
  const uniqueFields = getUniqueFields(this.schema, model);
@@ -4141,21 +4689,25 @@ var InputValidator = class {
4141
4689
  }
4142
4690
  return result;
4143
4691
  }
4144
- makeEnumFilterSchema(enumDef, optional) {
4692
+ makeEnumFilterSchema(enumDef, optional, withAggregations) {
4145
4693
  const baseSchema = z.enum(Object.keys(enumDef));
4146
- const components = this.makeCommonPrimitiveFilterComponents(baseSchema, optional, () => z.lazy(() => this.makeEnumFilterSchema(enumDef, optional)));
4694
+ const components = this.makeCommonPrimitiveFilterComponents(baseSchema, optional, () => z.lazy(() => this.makeEnumFilterSchema(enumDef, optional, withAggregations)), [
4695
+ "equals",
4696
+ "in",
4697
+ "notIn",
4698
+ "not"
4699
+ ], withAggregations ? [
4700
+ "_count",
4701
+ "_min",
4702
+ "_max"
4703
+ ] : void 0);
4147
4704
  return z.union([
4148
4705
  this.nullableIf(baseSchema, optional),
4149
- z.object({
4150
- equals: components.equals,
4151
- in: components.in,
4152
- notIn: components.notIn,
4153
- not: components.not
4154
- })
4706
+ z.strictObject(components)
4155
4707
  ]);
4156
4708
  }
4157
4709
  makeArrayFilterSchema(type) {
4158
- return z.object({
4710
+ return z.strictObject({
4159
4711
  equals: this.makePrimitiveSchema(type).array().optional(),
4160
4712
  has: this.makePrimitiveSchema(type).optional(),
4161
4713
  hasEvery: this.makePrimitiveSchema(type).array().optional(),
@@ -4163,39 +4715,59 @@ var InputValidator = class {
4163
4715
  isEmpty: z.boolean().optional()
4164
4716
  });
4165
4717
  }
4166
- makePrimitiveFilterSchema(type, optional) {
4167
- return match14(type).with("String", () => this.makeStringFilterSchema(optional)).with(P2.union("Int", "Float", "Decimal", "BigInt"), (type2) => this.makeNumberFilterSchema(this.makePrimitiveSchema(type2), optional)).with("Boolean", () => this.makeBooleanFilterSchema(optional)).with("DateTime", () => this.makeDateTimeFilterSchema(optional)).with("Bytes", () => this.makeBytesFilterSchema(optional)).exhaustive();
4718
+ makePrimitiveFilterSchema(type, optional, withAggregations) {
4719
+ if (this.schema.typeDefs && type in this.schema.typeDefs) {
4720
+ return this.makeTypeDefFilterSchema(type, optional);
4721
+ }
4722
+ return match15(type).with("String", () => this.makeStringFilterSchema(optional, withAggregations)).with(P2.union("Int", "Float", "Decimal", "BigInt"), (type2) => this.makeNumberFilterSchema(this.makePrimitiveSchema(type2), optional, withAggregations)).with("Boolean", () => this.makeBooleanFilterSchema(optional, withAggregations)).with("DateTime", () => this.makeDateTimeFilterSchema(optional, withAggregations)).with("Bytes", () => this.makeBytesFilterSchema(optional, withAggregations)).with("Json", () => z.any()).with("Unsupported", () => z.never()).exhaustive();
4723
+ }
4724
+ makeTypeDefFilterSchema(_type, _optional) {
4725
+ return z.never();
4168
4726
  }
4169
- makeDateTimeFilterSchema(optional) {
4727
+ makeDateTimeFilterSchema(optional, withAggregations) {
4170
4728
  return this.makeCommonPrimitiveFilterSchema(z.union([
4171
- z.string().datetime(),
4729
+ z.iso.datetime(),
4172
4730
  z.date()
4173
- ]), optional, () => z.lazy(() => this.makeDateTimeFilterSchema(optional)));
4174
- }
4175
- makeBooleanFilterSchema(optional) {
4731
+ ]), optional, () => z.lazy(() => this.makeDateTimeFilterSchema(optional, withAggregations)), withAggregations ? [
4732
+ "_count",
4733
+ "_min",
4734
+ "_max"
4735
+ ] : void 0);
4736
+ }
4737
+ makeBooleanFilterSchema(optional, withAggregations) {
4738
+ const components = this.makeCommonPrimitiveFilterComponents(z.boolean(), optional, () => z.lazy(() => this.makeBooleanFilterSchema(optional, withAggregations)), [
4739
+ "equals",
4740
+ "not"
4741
+ ], withAggregations ? [
4742
+ "_count",
4743
+ "_min",
4744
+ "_max"
4745
+ ] : void 0);
4176
4746
  return z.union([
4177
4747
  this.nullableIf(z.boolean(), optional),
4178
- z.object({
4179
- equals: this.nullableIf(z.boolean(), optional).optional(),
4180
- not: z.lazy(() => this.makeBooleanFilterSchema(optional)).optional()
4181
- })
4748
+ z.strictObject(components)
4182
4749
  ]);
4183
4750
  }
4184
- makeBytesFilterSchema(optional) {
4751
+ makeBytesFilterSchema(optional, withAggregations) {
4185
4752
  const baseSchema = z.instanceof(Uint8Array);
4186
- const components = this.makeCommonPrimitiveFilterComponents(baseSchema, optional, () => z.instanceof(Uint8Array));
4753
+ const components = this.makeCommonPrimitiveFilterComponents(baseSchema, optional, () => z.instanceof(Uint8Array), [
4754
+ "equals",
4755
+ "in",
4756
+ "notIn",
4757
+ "not"
4758
+ ], withAggregations ? [
4759
+ "_count",
4760
+ "_min",
4761
+ "_max"
4762
+ ] : void 0);
4187
4763
  return z.union([
4188
4764
  this.nullableIf(baseSchema, optional),
4189
- z.object({
4190
- equals: components.equals,
4191
- in: components.in,
4192
- notIn: components.notIn,
4193
- not: components.not
4194
- })
4765
+ z.strictObject(components)
4195
4766
  ]);
4196
4767
  }
4197
- makeCommonPrimitiveFilterComponents(baseSchema, optional, makeThis) {
4198
- return {
4768
+ makeCommonPrimitiveFilterComponents(baseSchema, optional, makeThis, supportedOperators = void 0, withAggregations = void 0) {
4769
+ const commonAggSchema = /* @__PURE__ */ __name(() => this.makeCommonPrimitiveFilterSchema(baseSchema, false, makeThis, void 0).optional(), "commonAggSchema");
4770
+ let result = {
4199
4771
  equals: this.nullableIf(baseSchema.optional(), optional),
4200
4772
  notEquals: this.nullableIf(baseSchema.optional(), optional),
4201
4773
  in: baseSchema.array().optional(),
@@ -4204,20 +4776,70 @@ var InputValidator = class {
4204
4776
  lte: baseSchema.optional(),
4205
4777
  gt: baseSchema.optional(),
4206
4778
  gte: baseSchema.optional(),
4207
- not: makeThis().optional()
4779
+ not: makeThis().optional(),
4780
+ ...withAggregations?.includes("_count") ? {
4781
+ _count: this.makeNumberFilterSchema(z.int(), false, false).optional()
4782
+ } : {},
4783
+ ...withAggregations?.includes("_avg") ? {
4784
+ _avg: commonAggSchema()
4785
+ } : {},
4786
+ ...withAggregations?.includes("_sum") ? {
4787
+ _sum: commonAggSchema()
4788
+ } : {},
4789
+ ...withAggregations?.includes("_min") ? {
4790
+ _min: commonAggSchema()
4791
+ } : {},
4792
+ ...withAggregations?.includes("_max") ? {
4793
+ _max: commonAggSchema()
4794
+ } : {}
4208
4795
  };
4796
+ if (supportedOperators) {
4797
+ const keys = [
4798
+ ...supportedOperators,
4799
+ ...withAggregations ?? []
4800
+ ];
4801
+ result = extractFields(result, keys);
4802
+ }
4803
+ return result;
4209
4804
  }
4210
- makeCommonPrimitiveFilterSchema(baseSchema, optional, makeThis) {
4805
+ makeCommonPrimitiveFilterSchema(baseSchema, optional, makeThis, withAggregations = void 0) {
4211
4806
  return z.union([
4212
4807
  this.nullableIf(baseSchema, optional),
4213
- z.object(this.makeCommonPrimitiveFilterComponents(baseSchema, optional, makeThis))
4808
+ z.strictObject(this.makeCommonPrimitiveFilterComponents(baseSchema, optional, makeThis, void 0, withAggregations))
4214
4809
  ]);
4215
4810
  }
4216
- makeNumberFilterSchema(baseSchema, optional) {
4217
- return this.makeCommonPrimitiveFilterSchema(baseSchema, optional, () => z.lazy(() => this.makeNumberFilterSchema(baseSchema, optional)));
4811
+ makeNumberFilterSchema(baseSchema, optional, withAggregations) {
4812
+ return this.makeCommonPrimitiveFilterSchema(baseSchema, optional, () => z.lazy(() => this.makeNumberFilterSchema(baseSchema, optional, withAggregations)), withAggregations ? [
4813
+ "_count",
4814
+ "_avg",
4815
+ "_sum",
4816
+ "_min",
4817
+ "_max"
4818
+ ] : void 0);
4819
+ }
4820
+ makeStringFilterSchema(optional, withAggregations) {
4821
+ return z.union([
4822
+ this.nullableIf(z.string(), optional),
4823
+ z.strictObject({
4824
+ ...this.makeCommonPrimitiveFilterComponents(z.string(), optional, () => z.lazy(() => this.makeStringFilterSchema(optional, withAggregations)), void 0, withAggregations ? [
4825
+ "_count",
4826
+ "_min",
4827
+ "_max"
4828
+ ] : void 0),
4829
+ startsWith: z.string().optional(),
4830
+ endsWith: z.string().optional(),
4831
+ contains: z.string().optional(),
4832
+ ...this.providerSupportsCaseSensitivity ? {
4833
+ mode: this.makeStringModeSchema().optional()
4834
+ } : {}
4835
+ })
4836
+ ]);
4218
4837
  }
4219
- makeStringFilterSchema(optional) {
4220
- return this.makeCommonPrimitiveFilterSchema(z.string(), optional, () => z.lazy(() => this.makeStringFilterSchema(optional)));
4838
+ makeStringModeSchema() {
4839
+ return z.union([
4840
+ z.literal("default"),
4841
+ z.literal("insensitive")
4842
+ ]);
4221
4843
  }
4222
4844
  makeSelectSchema(model) {
4223
4845
  const modelDef = requireModel(this.schema, model);
@@ -4227,7 +4849,7 @@ var InputValidator = class {
4227
4849
  if (fieldDef.relation) {
4228
4850
  fields[field] = z.union([
4229
4851
  z.literal(true),
4230
- z.object({
4852
+ z.strictObject({
4231
4853
  select: z.lazy(() => this.makeSelectSchema(fieldDef.type)).optional(),
4232
4854
  include: z.lazy(() => this.makeIncludeSchema(fieldDef.type)).optional()
4233
4855
  })
@@ -4236,22 +4858,24 @@ var InputValidator = class {
4236
4858
  fields[field] = z.boolean().optional();
4237
4859
  }
4238
4860
  }
4239
- const toManyRelations = Object.entries(modelDef.fields).filter(([, value]) => value.relation && value.array);
4861
+ const toManyRelations = Object.values(modelDef.fields).filter((def) => def.relation && def.array);
4240
4862
  if (toManyRelations.length > 0) {
4241
4863
  fields["_count"] = z.union([
4242
4864
  z.literal(true),
4243
- z.object(toManyRelations.reduce((acc, [name, fieldDef]) => ({
4244
- ...acc,
4245
- [name]: z.union([
4246
- z.boolean(),
4247
- z.object({
4248
- where: this.makeWhereSchema(fieldDef.type, false, false)
4249
- })
4250
- ]).optional()
4251
- }), {}))
4865
+ z.strictObject({
4866
+ select: z.strictObject(toManyRelations.reduce((acc, fieldDef) => ({
4867
+ ...acc,
4868
+ [fieldDef.name]: z.union([
4869
+ z.boolean(),
4870
+ z.strictObject({
4871
+ where: this.makeWhereSchema(fieldDef.type, false, false)
4872
+ })
4873
+ ]).optional()
4874
+ }), {}))
4875
+ })
4252
4876
  ]).optional();
4253
4877
  }
4254
- return z.object(fields).strict();
4878
+ return z.strictObject(fields);
4255
4879
  }
4256
4880
  makeOmitSchema(model) {
4257
4881
  const modelDef = requireModel(this.schema, model);
@@ -4262,7 +4886,7 @@ var InputValidator = class {
4262
4886
  fields[field] = z.boolean().optional();
4263
4887
  }
4264
4888
  }
4265
- return z.object(fields).strict();
4889
+ return z.strictObject(fields);
4266
4890
  }
4267
4891
  makeIncludeSchema(model) {
4268
4892
  const modelDef = requireModel(this.schema, model);
@@ -4272,15 +4896,20 @@ var InputValidator = class {
4272
4896
  if (fieldDef.relation) {
4273
4897
  fields[field] = z.union([
4274
4898
  z.literal(true),
4275
- z.object({
4899
+ z.strictObject({
4276
4900
  select: z.lazy(() => this.makeSelectSchema(fieldDef.type)).optional(),
4277
4901
  include: z.lazy(() => this.makeIncludeSchema(fieldDef.type)).optional(),
4278
- where: z.lazy(() => this.makeWhereSchema(fieldDef.type, false)).optional()
4902
+ omit: z.lazy(() => this.makeOmitSchema(fieldDef.type)).optional(),
4903
+ where: z.lazy(() => this.makeWhereSchema(fieldDef.type, false)).optional(),
4904
+ orderBy: z.lazy(() => this.makeOrderBySchema(fieldDef.type, true, false)).optional(),
4905
+ skip: this.makeSkipSchema().optional(),
4906
+ take: this.makeTakeSchema().optional(),
4907
+ distinct: this.makeDistinctSchema(fieldDef.type).optional()
4279
4908
  })
4280
4909
  ]).optional();
4281
4910
  }
4282
4911
  }
4283
- return z.object(fields).strict();
4912
+ return z.strictObject(fields);
4284
4913
  }
4285
4914
  makeOrderBySchema(model, withRelation, WithAggregation) {
4286
4915
  const modelDef = requireModel(this.schema, model);
@@ -4293,13 +4922,21 @@ var InputValidator = class {
4293
4922
  const fieldDef = requireField(this.schema, model, field);
4294
4923
  if (fieldDef.relation) {
4295
4924
  if (withRelation) {
4296
- fields[field] = z.lazy(() => this.makeOrderBySchema(fieldDef.type, withRelation, WithAggregation).optional());
4925
+ fields[field] = z.lazy(() => {
4926
+ let relationOrderBy = this.makeOrderBySchema(fieldDef.type, withRelation, WithAggregation);
4927
+ if (fieldDef.array) {
4928
+ relationOrderBy = relationOrderBy.extend({
4929
+ _count: sort
4930
+ });
4931
+ }
4932
+ return relationOrderBy.optional();
4933
+ });
4297
4934
  }
4298
4935
  } else {
4299
4936
  if (fieldDef.optional) {
4300
4937
  fields[field] = z.union([
4301
4938
  sort,
4302
- z.object({
4939
+ z.strictObject({
4303
4940
  sort,
4304
4941
  nulls: z.union([
4305
4942
  z.literal("first"),
@@ -4324,7 +4961,7 @@ var InputValidator = class {
4324
4961
  fields[agg] = z.lazy(() => this.makeOrderBySchema(model, true, false).optional());
4325
4962
  }
4326
4963
  }
4327
- return z.object(fields);
4964
+ return z.strictObject(fields);
4328
4965
  }
4329
4966
  makeDistinctSchema(model) {
4330
4967
  const modelDef = requireModel(this.schema, model);
@@ -4343,7 +4980,7 @@ var InputValidator = class {
4343
4980
  select: this.makeSelectSchema(model).optional(),
4344
4981
  include: this.makeIncludeSchema(model).optional(),
4345
4982
  omit: this.makeOmitSchema(model).optional()
4346
- }).strict();
4983
+ });
4347
4984
  return this.refineForSelectIncludeMutuallyExclusive(schema);
4348
4985
  }
4349
4986
  makeCreateManySchema(model) {
@@ -4351,15 +4988,15 @@ var InputValidator = class {
4351
4988
  }
4352
4989
  makeCreateManyAndReturnSchema(model) {
4353
4990
  const base = this.makeCreateManyDataSchema(model, []);
4354
- const result = base.merge(z.object({
4991
+ const result = base.merge(z.strictObject({
4355
4992
  select: this.makeSelectSchema(model).optional(),
4356
4993
  omit: this.makeOmitSchema(model).optional()
4357
4994
  }));
4358
4995
  return this.refineForSelectOmitMutuallyExclusive(result).optional();
4359
4996
  }
4360
4997
  makeCreateDataSchema(model, canBeArray, withoutFields = [], withoutRelationFields = false) {
4361
- const regularAndFkFields = {};
4362
- const regularAndRelationFields = {};
4998
+ const uncheckedVariantFields = {};
4999
+ const checkedVariantFields = {};
4363
5000
  const modelDef = requireModel(this.schema, model);
4364
5001
  const hasRelation = !withoutRelationFields && Object.entries(modelDef.fields).some(([f, def]) => !withoutFields.includes(f) && def.relation);
4365
5002
  Object.keys(modelDef.fields).forEach((field) => {
@@ -4370,6 +5007,9 @@ var InputValidator = class {
4370
5007
  if (fieldDef.computed) {
4371
5008
  return;
4372
5009
  }
5010
+ if (this.isDelegateDiscriminator(fieldDef)) {
5011
+ return;
5012
+ }
4373
5013
  if (fieldDef.relation) {
4374
5014
  if (withoutRelationFields) {
4375
5015
  return;
@@ -4401,13 +5041,16 @@ var InputValidator = class {
4401
5041
  if (fieldDef.optional && !fieldDef.array) {
4402
5042
  fieldSchema = fieldSchema.nullable();
4403
5043
  }
4404
- regularAndRelationFields[field] = fieldSchema;
5044
+ checkedVariantFields[field] = fieldSchema;
5045
+ if (fieldDef.array || !fieldDef.relation.references) {
5046
+ uncheckedVariantFields[field] = fieldSchema;
5047
+ }
4405
5048
  } else {
4406
5049
  let fieldSchema = this.makePrimitiveSchema(fieldDef.type);
4407
5050
  if (fieldDef.array) {
4408
5051
  fieldSchema = z.union([
4409
5052
  z.array(fieldSchema),
4410
- z.object({
5053
+ z.strictObject({
4411
5054
  set: z.array(fieldSchema)
4412
5055
  })
4413
5056
  ]).optional();
@@ -4418,27 +5061,34 @@ var InputValidator = class {
4418
5061
  if (fieldDef.optional) {
4419
5062
  fieldSchema = fieldSchema.nullable();
4420
5063
  }
4421
- regularAndFkFields[field] = fieldSchema;
5064
+ uncheckedVariantFields[field] = fieldSchema;
4422
5065
  if (!fieldDef.foreignKeyFor) {
4423
- regularAndRelationFields[field] = fieldSchema;
5066
+ checkedVariantFields[field] = fieldSchema;
4424
5067
  }
4425
5068
  }
4426
5069
  });
4427
5070
  if (!hasRelation) {
4428
- return this.orArray(z.object(regularAndFkFields).strict(), canBeArray);
5071
+ return this.orArray(z.strictObject(uncheckedVariantFields), canBeArray);
4429
5072
  } else {
4430
5073
  return z.union([
4431
- z.object(regularAndFkFields).strict(),
4432
- z.object(regularAndRelationFields).strict(),
5074
+ z.strictObject(uncheckedVariantFields),
5075
+ z.strictObject(checkedVariantFields),
4433
5076
  ...canBeArray ? [
4434
- z.array(z.object(regularAndFkFields).strict())
5077
+ z.array(z.strictObject(uncheckedVariantFields))
4435
5078
  ] : [],
4436
5079
  ...canBeArray ? [
4437
- z.array(z.object(regularAndRelationFields).strict())
5080
+ z.array(z.strictObject(checkedVariantFields))
4438
5081
  ] : []
4439
5082
  ]);
4440
5083
  }
4441
5084
  }
5085
+ isDelegateDiscriminator(fieldDef) {
5086
+ if (!fieldDef.originModel) {
5087
+ return false;
5088
+ }
5089
+ const discriminatorField = getDiscriminatorField(this.schema, fieldDef.originModel);
5090
+ return discriminatorField === fieldDef.name;
5091
+ }
4442
5092
  makeRelationManipulationSchema(fieldDef, withoutFields, mode) {
4443
5093
  const fieldType = fieldDef.type;
4444
5094
  const array = !!fieldDef.array;
@@ -4455,31 +5105,31 @@ var InputValidator = class {
4455
5105
  fields["disconnect"] = this.makeDisconnectDataSchema(fieldType, array).optional();
4456
5106
  fields["delete"] = this.makeDeleteRelationDataSchema(fieldType, array, true).optional();
4457
5107
  }
4458
- fields["update"] = array ? this.orArray(z.object({
5108
+ fields["update"] = array ? this.orArray(z.strictObject({
4459
5109
  where: this.makeWhereSchema(fieldType, true),
4460
5110
  data: this.makeUpdateDataSchema(fieldType, withoutFields)
4461
5111
  }), true).optional() : z.union([
4462
- z.object({
5112
+ z.strictObject({
4463
5113
  where: this.makeWhereSchema(fieldType, true),
4464
5114
  data: this.makeUpdateDataSchema(fieldType, withoutFields)
4465
5115
  }),
4466
5116
  this.makeUpdateDataSchema(fieldType, withoutFields)
4467
5117
  ]).optional();
4468
- fields["upsert"] = this.orArray(z.object({
5118
+ fields["upsert"] = this.orArray(z.strictObject({
4469
5119
  where: this.makeWhereSchema(fieldType, true),
4470
5120
  create: this.makeCreateDataSchema(fieldType, false, withoutFields),
4471
5121
  update: this.makeUpdateDataSchema(fieldType, withoutFields)
4472
5122
  }), true).optional();
4473
5123
  if (array) {
4474
5124
  fields["set"] = this.makeSetDataSchema(fieldType, true).optional();
4475
- fields["updateMany"] = this.orArray(z.object({
5125
+ fields["updateMany"] = this.orArray(z.strictObject({
4476
5126
  where: this.makeWhereSchema(fieldType, false, true),
4477
5127
  data: this.makeUpdateDataSchema(fieldType, withoutFields)
4478
5128
  }), true).optional();
4479
5129
  fields["deleteMany"] = this.makeDeleteRelationDataSchema(fieldType, true, false).optional();
4480
5130
  }
4481
5131
  }
4482
- return z.object(fields).strict().refine((v) => Object.keys(v).length > 0, "At least one action is required");
5132
+ return z.strictObject(fields);
4483
5133
  }
4484
5134
  makeSetDataSchema(model, canBeArray) {
4485
5135
  return this.orArray(this.makeWhereSchema(model, true), canBeArray);
@@ -4509,13 +5159,13 @@ var InputValidator = class {
4509
5159
  return this.orArray(z.object({
4510
5160
  where: whereSchema,
4511
5161
  create: createSchema
4512
- }).strict(), canBeArray);
5162
+ }), canBeArray);
4513
5163
  }
4514
5164
  makeCreateManyDataSchema(model, withoutFields) {
4515
5165
  return z.object({
4516
5166
  data: this.makeCreateDataSchema(model, true, withoutFields, true),
4517
5167
  skipDuplicates: z.boolean().optional()
4518
- }).strict();
5168
+ });
4519
5169
  }
4520
5170
  // #endregion
4521
5171
  // #region Update
@@ -4526,19 +5176,19 @@ var InputValidator = class {
4526
5176
  select: this.makeSelectSchema(model).optional(),
4527
5177
  include: this.makeIncludeSchema(model).optional(),
4528
5178
  omit: this.makeOmitSchema(model).optional()
4529
- }).strict();
5179
+ });
4530
5180
  return this.refineForSelectIncludeMutuallyExclusive(schema);
4531
5181
  }
4532
5182
  makeUpdateManySchema(model) {
4533
5183
  return z.object({
4534
5184
  where: this.makeWhereSchema(model, false).optional(),
4535
5185
  data: this.makeUpdateDataSchema(model, [], true),
4536
- limit: z.number().int().nonnegative().optional()
4537
- }).strict();
5186
+ limit: z.int().nonnegative().optional()
5187
+ });
4538
5188
  }
4539
5189
  makeUpdateManyAndReturnSchema(model) {
4540
5190
  const base = this.makeUpdateManySchema(model);
4541
- const result = base.merge(z.object({
5191
+ const result = base.merge(z.strictObject({
4542
5192
  select: this.makeSelectSchema(model).optional(),
4543
5193
  omit: this.makeOmitSchema(model).optional()
4544
5194
  }));
@@ -4552,12 +5202,12 @@ var InputValidator = class {
4552
5202
  select: this.makeSelectSchema(model).optional(),
4553
5203
  include: this.makeIncludeSchema(model).optional(),
4554
5204
  omit: this.makeOmitSchema(model).optional()
4555
- }).strict();
5205
+ });
4556
5206
  return this.refineForSelectIncludeMutuallyExclusive(schema);
4557
5207
  }
4558
5208
  makeUpdateDataSchema(model, withoutFields = [], withoutRelationFields = false) {
4559
- const regularAndFkFields = {};
4560
- const regularAndRelationFields = {};
5209
+ const uncheckedVariantFields = {};
5210
+ const checkedVariantFields = {};
4561
5211
  const modelDef = requireModel(this.schema, model);
4562
5212
  const hasRelation = Object.entries(modelDef.fields).some(([key, value]) => value.relation && !withoutFields.includes(key));
4563
5213
  Object.keys(modelDef.fields).forEach((field) => {
@@ -4582,7 +5232,10 @@ var InputValidator = class {
4582
5232
  if (fieldDef.optional && !fieldDef.array) {
4583
5233
  fieldSchema = fieldSchema.nullable();
4584
5234
  }
4585
- regularAndRelationFields[field] = fieldSchema;
5235
+ checkedVariantFields[field] = fieldSchema;
5236
+ if (fieldDef.array || !fieldDef.relation.references) {
5237
+ uncheckedVariantFields[field] = fieldSchema;
5238
+ }
4586
5239
  } else {
4587
5240
  let fieldSchema = this.makePrimitiveSchema(fieldDef.type).optional();
4588
5241
  if (this.isNumericField(fieldDef)) {
@@ -4609,18 +5262,18 @@ var InputValidator = class {
4609
5262
  if (fieldDef.optional) {
4610
5263
  fieldSchema = fieldSchema.nullable();
4611
5264
  }
4612
- regularAndFkFields[field] = fieldSchema;
5265
+ uncheckedVariantFields[field] = fieldSchema;
4613
5266
  if (!fieldDef.foreignKeyFor) {
4614
- regularAndRelationFields[field] = fieldSchema;
5267
+ checkedVariantFields[field] = fieldSchema;
4615
5268
  }
4616
5269
  }
4617
5270
  });
4618
5271
  if (!hasRelation) {
4619
- return z.object(regularAndFkFields).strict();
5272
+ return z.strictObject(uncheckedVariantFields);
4620
5273
  } else {
4621
5274
  return z.union([
4622
- z.object(regularAndFkFields).strict(),
4623
- z.object(regularAndRelationFields).strict()
5275
+ z.strictObject(uncheckedVariantFields),
5276
+ z.strictObject(checkedVariantFields)
4624
5277
  ]);
4625
5278
  }
4626
5279
  }
@@ -4631,25 +5284,25 @@ var InputValidator = class {
4631
5284
  where: this.makeWhereSchema(model, true),
4632
5285
  select: this.makeSelectSchema(model).optional(),
4633
5286
  include: this.makeIncludeSchema(model).optional()
4634
- }).strict();
5287
+ });
4635
5288
  return this.refineForSelectIncludeMutuallyExclusive(schema);
4636
5289
  }
4637
5290
  makeDeleteManySchema(model) {
4638
5291
  return z.object({
4639
5292
  where: this.makeWhereSchema(model, false).optional(),
4640
- limit: z.number().int().nonnegative().optional()
4641
- }).strict().optional();
5293
+ limit: z.int().nonnegative().optional()
5294
+ }).optional();
4642
5295
  }
4643
5296
  // #endregion
4644
5297
  // #region Count
4645
5298
  makeCountSchema(model) {
4646
5299
  return z.object({
4647
5300
  where: this.makeWhereSchema(model, false).optional(),
4648
- skip: z.number().int().nonnegative().optional(),
4649
- take: z.number().int().optional(),
5301
+ skip: this.makeSkipSchema().optional(),
5302
+ take: this.makeTakeSchema().optional(),
4650
5303
  orderBy: this.orArray(this.makeOrderBySchema(model, true, false), true).optional(),
4651
5304
  select: this.makeCountAggregateInputSchema(model).optional()
4652
- }).strict().optional();
5305
+ }).optional();
4653
5306
  }
4654
5307
  makeCountAggregateInputSchema(model) {
4655
5308
  const modelDef = requireModel(this.schema, model);
@@ -4661,7 +5314,7 @@ var InputValidator = class {
4661
5314
  acc[field] = z.literal(true).optional();
4662
5315
  return acc;
4663
5316
  }, {})
4664
- }).strict()
5317
+ })
4665
5318
  ]);
4666
5319
  }
4667
5320
  // #endregion
@@ -4669,19 +5322,19 @@ var InputValidator = class {
4669
5322
  makeAggregateSchema(model) {
4670
5323
  return z.object({
4671
5324
  where: this.makeWhereSchema(model, false).optional(),
4672
- skip: z.number().int().nonnegative().optional(),
4673
- take: z.number().int().optional(),
5325
+ skip: this.makeSkipSchema().optional(),
5326
+ take: this.makeTakeSchema().optional(),
4674
5327
  orderBy: this.orArray(this.makeOrderBySchema(model, true, false), true).optional(),
4675
5328
  _count: this.makeCountAggregateInputSchema(model).optional(),
4676
5329
  _avg: this.makeSumAvgInputSchema(model).optional(),
4677
5330
  _sum: this.makeSumAvgInputSchema(model).optional(),
4678
5331
  _min: this.makeMinMaxInputSchema(model).optional(),
4679
5332
  _max: this.makeMinMaxInputSchema(model).optional()
4680
- }).strict().optional();
5333
+ }).optional();
4681
5334
  }
4682
5335
  makeSumAvgInputSchema(model) {
4683
5336
  const modelDef = requireModel(this.schema, model);
4684
- return z.object(Object.keys(modelDef.fields).reduce((acc, field) => {
5337
+ return z.strictObject(Object.keys(modelDef.fields).reduce((acc, field) => {
4685
5338
  const fieldDef = requireField(this.schema, model, field);
4686
5339
  if (this.isNumericField(fieldDef)) {
4687
5340
  acc[field] = z.literal(true).optional();
@@ -4691,7 +5344,7 @@ var InputValidator = class {
4691
5344
  }
4692
5345
  makeMinMaxInputSchema(model) {
4693
5346
  const modelDef = requireModel(this.schema, model);
4694
- return z.object(Object.keys(modelDef.fields).reduce((acc, field) => {
5347
+ return z.strictObject(Object.keys(modelDef.fields).reduce((acc, field) => {
4695
5348
  const fieldDef = requireField(this.schema, model, field);
4696
5349
  if (!fieldDef.relation && !fieldDef.array) {
4697
5350
  acc[field] = z.literal(true).optional();
@@ -4706,30 +5359,42 @@ var InputValidator = class {
4706
5359
  where: this.makeWhereSchema(model, false).optional(),
4707
5360
  orderBy: this.orArray(this.makeOrderBySchema(model, false, true), true).optional(),
4708
5361
  by: this.orArray(z.enum(nonRelationFields), true),
4709
- having: this.makeWhereSchema(model, false, true).optional(),
4710
- skip: z.number().int().nonnegative().optional(),
4711
- take: z.number().int().optional(),
5362
+ having: this.makeHavingSchema(model).optional(),
5363
+ skip: this.makeSkipSchema().optional(),
5364
+ take: this.makeTakeSchema().optional(),
4712
5365
  _count: this.makeCountAggregateInputSchema(model).optional(),
4713
5366
  _avg: this.makeSumAvgInputSchema(model).optional(),
4714
5367
  _sum: this.makeSumAvgInputSchema(model).optional(),
4715
5368
  _min: this.makeMinMaxInputSchema(model).optional(),
4716
5369
  _max: this.makeMinMaxInputSchema(model).optional()
4717
- }).strict();
5370
+ });
4718
5371
  schema = schema.refine((value) => {
4719
5372
  const bys = typeof value.by === "string" ? [
4720
5373
  value.by
4721
5374
  ] : value.by;
4722
- if (value.having && Object.keys(value.having).filter((f) => !f.startsWith("_")).some((key) => !bys.includes(key))) {
4723
- return false;
4724
- } else {
4725
- return true;
5375
+ if (value.having && typeof value.having === "object") {
5376
+ for (const [key, val] of Object.entries(value.having)) {
5377
+ if (AGGREGATE_OPERATORS.includes(key)) {
5378
+ continue;
5379
+ }
5380
+ if (bys.includes(key)) {
5381
+ continue;
5382
+ }
5383
+ if (!val || typeof val !== "object") {
5384
+ return false;
5385
+ }
5386
+ if (!this.onlyAggregationFields(val)) {
5387
+ return false;
5388
+ }
5389
+ }
4726
5390
  }
5391
+ return true;
4727
5392
  }, 'fields in "having" must be in "by"');
4728
5393
  schema = schema.refine((value) => {
4729
5394
  const bys = typeof value.by === "string" ? [
4730
5395
  value.by
4731
5396
  ] : value.by;
4732
- if (value.orderBy && Object.keys(value.orderBy).filter((f) => !f.startsWith("_")).some((key) => !bys.includes(key))) {
5397
+ if (value.orderBy && Object.keys(value.orderBy).filter((f) => !AGGREGATE_OPERATORS.includes(f)).some((key) => !bys.includes(key))) {
4733
5398
  return false;
4734
5399
  } else {
4735
5400
  return true;
@@ -4737,8 +5402,31 @@ var InputValidator = class {
4737
5402
  }, 'fields in "orderBy" must be in "by"');
4738
5403
  return schema;
4739
5404
  }
5405
+ onlyAggregationFields(val) {
5406
+ for (const [key, value] of Object.entries(val)) {
5407
+ if (AGGREGATE_OPERATORS.includes(key)) {
5408
+ continue;
5409
+ }
5410
+ if (LOGICAL_COMBINATORS.includes(key)) {
5411
+ if (enumerate(value).every((v) => this.onlyAggregationFields(v))) {
5412
+ continue;
5413
+ }
5414
+ }
5415
+ return false;
5416
+ }
5417
+ return true;
5418
+ }
5419
+ makeHavingSchema(model) {
5420
+ return this.makeWhereSchema(model, false, true, true);
5421
+ }
4740
5422
  // #endregion
4741
5423
  // #region Helpers
5424
+ makeSkipSchema() {
5425
+ return z.int().nonnegative();
5426
+ }
5427
+ makeTakeSchema() {
5428
+ return z.int();
5429
+ }
4742
5430
  refineForSelectIncludeMutuallyExclusive(schema) {
4743
5431
  return schema.refine((value) => !(value["select"] && value["include"]), '"select" and "include" cannot be used together');
4744
5432
  }
@@ -4757,6 +5445,9 @@ var InputValidator = class {
4757
5445
  isNumericField(fieldDef) {
4758
5446
  return NUMERIC_FIELD_TYPES.includes(fieldDef.type) && !fieldDef.array;
4759
5447
  }
5448
+ get providerSupportsCaseSensitivity() {
5449
+ return this.schema.provider.type === "postgresql";
5450
+ }
4760
5451
  };
4761
5452
 
4762
5453
  // src/client/executor/zenstack-driver.ts
@@ -4766,11 +5457,11 @@ var ZenStackDriver = class {
4766
5457
  }
4767
5458
  #driver;
4768
5459
  #log;
4769
- txConnection;
4770
5460
  #initPromise;
4771
5461
  #initDone;
4772
5462
  #destroyPromise;
4773
5463
  #connections = /* @__PURE__ */ new WeakSet();
5464
+ #txConnections = /* @__PURE__ */ new WeakMap();
4774
5465
  constructor(driver, log) {
4775
5466
  this.#initDone = false;
4776
5467
  this.#driver = driver;
@@ -4811,21 +5502,30 @@ var ZenStackDriver = class {
4811
5502
  }
4812
5503
  async beginTransaction(connection, settings) {
4813
5504
  const result = await this.#driver.beginTransaction(connection, settings);
4814
- this.txConnection = connection;
5505
+ this.#txConnections.set(connection, []);
4815
5506
  return result;
4816
5507
  }
4817
- commitTransaction(connection) {
5508
+ async commitTransaction(connection) {
4818
5509
  try {
4819
- return this.#driver.commitTransaction(connection);
4820
- } finally {
4821
- this.txConnection = void 0;
5510
+ const result = await this.#driver.commitTransaction(connection);
5511
+ const callbacks = this.#txConnections.get(connection);
5512
+ this.#txConnections.delete(connection);
5513
+ if (callbacks) {
5514
+ for (const callback of callbacks) {
5515
+ await callback();
5516
+ }
5517
+ }
5518
+ return result;
5519
+ } catch (err) {
5520
+ this.#txConnections.delete(connection);
5521
+ throw err;
4822
5522
  }
4823
5523
  }
4824
- rollbackTransaction(connection) {
5524
+ async rollbackTransaction(connection) {
4825
5525
  try {
4826
- return this.#driver.rollbackTransaction(connection);
5526
+ return await this.#driver.rollbackTransaction(connection);
4827
5527
  } finally {
4828
- this.txConnection = void 0;
5528
+ this.#txConnections.delete(connection);
4829
5529
  }
4830
5530
  }
4831
5531
  async destroy() {
@@ -4903,6 +5603,22 @@ var ZenStackDriver = class {
4903
5603
  #calculateDurationMillis(startTime) {
4904
5604
  return performanceNow() - startTime;
4905
5605
  }
5606
+ isTransactionConnection(connection) {
5607
+ return this.#txConnections.has(connection);
5608
+ }
5609
+ registerTransactionCommitCallback(connection, callback) {
5610
+ if (!this.#txConnections.has(connection)) {
5611
+ return;
5612
+ }
5613
+ const callbacks = this.#txConnections.get(connection);
5614
+ if (callbacks) {
5615
+ callbacks.push(callback);
5616
+ } else {
5617
+ this.#txConnections.set(connection, [
5618
+ callback
5619
+ ]);
5620
+ }
5621
+ }
4906
5622
  };
4907
5623
  function performanceNow() {
4908
5624
  if (typeof performance !== "undefined" && typeof performance.now === "function") {
@@ -4914,9 +5630,10 @@ function performanceNow() {
4914
5630
  __name(performanceNow, "performanceNow");
4915
5631
 
4916
5632
  // src/client/executor/zenstack-query-executor.ts
4917
- import { AndNode as AndNode2, DefaultQueryExecutor, DeleteQueryNode as DeleteQueryNode2, InsertQueryNode as InsertQueryNode2, ReturningNode as ReturningNode3, SelectionNode as SelectionNode4, SingleConnectionProvider, UpdateQueryNode as UpdateQueryNode2, WhereNode as WhereNode3 } from "kysely";
5633
+ import { AndNode as AndNode2, DefaultQueryExecutor, DeleteQueryNode as DeleteQueryNode2, InsertQueryNode as InsertQueryNode2, ReturningNode as ReturningNode3, SelectionNode as SelectionNode4, UpdateQueryNode as UpdateQueryNode2, WhereNode as WhereNode3 } from "kysely";
4918
5634
  import { nanoid as nanoid2 } from "nanoid";
4919
- import { match as match15 } from "ts-pattern";
5635
+ import { inspect as inspect2 } from "util";
5636
+ import { match as match16 } from "ts-pattern";
4920
5637
 
4921
5638
  // src/client/executor/name-mapper.ts
4922
5639
  import { AliasNode as AliasNode4, ColumnNode as ColumnNode3, IdentifierNode as IdentifierNode3, OperationNodeTransformer as OperationNodeTransformer2, ReferenceNode as ReferenceNode3, ReturningNode as ReturningNode2, SelectAllNode, SelectionNode as SelectionNode3, TableNode as TableNode4 } from "kysely";
@@ -4925,11 +5642,11 @@ var QueryNameMapper = class extends OperationNodeTransformer2 {
4925
5642
  __name(this, "QueryNameMapper");
4926
5643
  }
4927
5644
  schema;
4928
- modelToTableMap;
4929
- fieldToColumnMap;
4930
- modelStack;
5645
+ modelToTableMap = /* @__PURE__ */ new Map();
5646
+ fieldToColumnMap = /* @__PURE__ */ new Map();
5647
+ modelStack = [];
4931
5648
  constructor(schema) {
4932
- super(), this.schema = schema, this.modelToTableMap = /* @__PURE__ */ new Map(), this.fieldToColumnMap = /* @__PURE__ */ new Map(), this.modelStack = [];
5649
+ super(), this.schema = schema;
4933
5650
  for (const [modelName, modelDef] of Object.entries(schema.models)) {
4934
5651
  const mappedName = this.getMappedName(modelDef);
4935
5652
  if (mappedName) {
@@ -5118,7 +5835,7 @@ var QueryNameMapper = class extends OperationNodeTransformer2 {
5118
5835
  this.requireCurrentModel(contextNode);
5119
5836
  model = model ?? this.currentModel;
5120
5837
  const modelDef = requireModel(this.schema, model);
5121
- const scalarFields = Object.entries(modelDef.fields).filter(([, fieldDef]) => !fieldDef.relation && !fieldDef.computed).map(([fieldName]) => fieldName);
5838
+ const scalarFields = Object.entries(modelDef.fields).filter(([, fieldDef]) => !fieldDef.relation && !fieldDef.computed && !fieldDef.originModel).map(([fieldName]) => fieldName);
5122
5839
  return scalarFields;
5123
5840
  }
5124
5841
  };
@@ -5143,16 +5860,18 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends DefaultQueryExe
5143
5860
  get options() {
5144
5861
  return this.client.$options;
5145
5862
  }
5146
- async executeQuery(compiledQuery, queryId) {
5863
+ async executeQuery(compiledQuery, _queryId) {
5147
5864
  let queryNode = compiledQuery.query;
5148
5865
  let mutationInterceptionInfo;
5149
5866
  if (this.isMutationNode(queryNode) && this.hasMutationHooks) {
5150
5867
  mutationInterceptionInfo = await this.callMutationInterceptionFilters(queryNode);
5151
5868
  }
5152
5869
  const task = /* @__PURE__ */ __name(async () => {
5153
- await this.callBeforeMutationHooks(queryNode, mutationInterceptionInfo);
5870
+ if (this.isMutationNode(queryNode)) {
5871
+ await this.callBeforeMutationHooks(queryNode, mutationInterceptionInfo);
5872
+ }
5154
5873
  const oldQueryNode = queryNode;
5155
- if ((InsertQueryNode2.is(queryNode) || DeleteQueryNode2.is(queryNode)) && mutationInterceptionInfo?.loadAfterMutationEntity) {
5874
+ if ((InsertQueryNode2.is(queryNode) || UpdateQueryNode2.is(queryNode)) && mutationInterceptionInfo?.loadAfterMutationEntity) {
5156
5875
  queryNode = {
5157
5876
  ...queryNode,
5158
5877
  returning: ReturningNode3.create([
@@ -5160,42 +5879,73 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends DefaultQueryExe
5160
5879
  ])
5161
5880
  };
5162
5881
  }
5163
- const result = await this.proceedQueryWithKyselyInterceptors(queryNode, queryId);
5164
- await this.callAfterQueryInterceptionFilters(result, queryNode, mutationInterceptionInfo);
5882
+ const queryParams = compiledQuery.$raw ? compiledQuery.parameters : void 0;
5883
+ const result = await this.proceedQueryWithKyselyInterceptors(queryNode, queryParams);
5884
+ if (this.isMutationNode(queryNode)) {
5885
+ await this.callAfterMutationHooks(result.result, queryNode, mutationInterceptionInfo, result.connection);
5886
+ }
5165
5887
  if (oldQueryNode !== queryNode) {
5166
5888
  }
5167
- return result;
5889
+ return result.result;
5168
5890
  }, "task");
5169
- return this.executeWithTransaction(task, !!mutationInterceptionInfo?.useTransactionForMutation);
5170
- }
5171
- proceedQueryWithKyselyInterceptors(queryNode, queryId) {
5172
- let proceed = /* @__PURE__ */ __name((q) => this.proceedQuery(q, queryId), "proceed");
5173
- const makeTx = /* @__PURE__ */ __name((p) => (callback) => {
5174
- return this.executeWithTransaction(() => callback(p));
5175
- }, "makeTx");
5176
- const hooks = this.options.plugins?.filter((plugin) => typeof plugin.onKyselyQuery === "function").map((plugin) => plugin.onKyselyQuery.bind(plugin)) ?? [];
5891
+ return task();
5892
+ }
5893
+ proceedQueryWithKyselyInterceptors(queryNode, parameters) {
5894
+ let proceed = /* @__PURE__ */ __name((q) => this.proceedQuery(q, parameters), "proceed");
5895
+ const hooks = [];
5896
+ for (const plugin of this.client.$options.plugins ?? []) {
5897
+ if (plugin.onKyselyQuery) {
5898
+ hooks.push(plugin.onKyselyQuery.bind(plugin));
5899
+ }
5900
+ }
5177
5901
  for (const hook of hooks) {
5178
5902
  const _proceed = proceed;
5179
- proceed = /* @__PURE__ */ __name((query) => {
5180
- return hook({
5903
+ proceed = /* @__PURE__ */ __name(async (query) => {
5904
+ let connection;
5905
+ const _p = /* @__PURE__ */ __name(async (q) => {
5906
+ const r = await _proceed(q);
5907
+ connection = r.connection;
5908
+ return r.result;
5909
+ }, "_p");
5910
+ const hookResult = await hook({
5181
5911
  client: this.client,
5182
5912
  schema: this.client.$schema,
5183
5913
  kysely: this.kysely,
5184
5914
  query,
5185
- proceed: _proceed,
5186
- transaction: makeTx(_proceed)
5915
+ proceed: _p
5187
5916
  });
5917
+ return {
5918
+ result: hookResult,
5919
+ connection
5920
+ };
5188
5921
  }, "proceed");
5189
5922
  }
5190
5923
  return proceed(queryNode);
5191
5924
  }
5192
- async proceedQuery(query, queryId) {
5925
+ async proceedQuery(query, parameters) {
5193
5926
  const finalQuery = this.nameMapper.transformNode(query);
5194
- const compiled = this.compileQuery(finalQuery);
5927
+ let compiled = this.compileQuery(finalQuery);
5928
+ if (parameters) {
5929
+ compiled = {
5930
+ ...compiled,
5931
+ parameters
5932
+ };
5933
+ }
5195
5934
  try {
5196
- return this.driver.txConnection ? await super.withConnectionProvider(new SingleConnectionProvider(this.driver.txConnection)).executeQuery(compiled, queryId) : await super.executeQuery(compiled, queryId);
5935
+ return await this.provideConnection(async (connection) => {
5936
+ const result = await connection.executeQuery(compiled);
5937
+ return {
5938
+ result,
5939
+ connection
5940
+ };
5941
+ });
5197
5942
  } catch (err) {
5198
- throw new QueryError(`Failed to execute query: ${err}, sql: ${compiled.sql}, parameters: ${compiled.parameters}`);
5943
+ let message = `Failed to execute query: ${err}, sql: ${compiled.sql}`;
5944
+ if (this.options.debug) {
5945
+ message += `, parameters:
5946
+ ${compiled.parameters.map((p) => inspect2(p)).join("\n")}`;
5947
+ }
5948
+ throw new QueryError(message, err);
5199
5949
  }
5200
5950
  }
5201
5951
  isMutationNode(queryNode) {
@@ -5223,30 +5973,15 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends DefaultQueryExe
5223
5973
  return new _ZenStackQueryExecutor(this.client, this.driver, this.compiler, this.adapter, this.connectionProvider, []);
5224
5974
  }
5225
5975
  withConnectionProvider(connectionProvider) {
5226
- return new _ZenStackQueryExecutor(this.client, this.driver, this.compiler, this.adapter, connectionProvider);
5227
- }
5228
- async executeWithTransaction(callback, useTransaction = true) {
5229
- if (!useTransaction || this.driver.txConnection) {
5230
- return callback();
5231
- } else {
5232
- return this.provideConnection(async (connection) => {
5233
- try {
5234
- await this.driver.beginTransaction(connection, {});
5235
- const result = await callback();
5236
- await this.driver.commitTransaction(connection);
5237
- return result;
5238
- } catch (error) {
5239
- await this.driver.rollbackTransaction(connection);
5240
- throw error;
5241
- }
5242
- });
5243
- }
5976
+ const newExecutor = new _ZenStackQueryExecutor(this.client, this.driver, this.compiler, this.adapter, connectionProvider);
5977
+ newExecutor.client = this.client.withExecutor(newExecutor);
5978
+ return newExecutor;
5244
5979
  }
5245
5980
  get hasMutationHooks() {
5246
5981
  return this.client.$options.plugins?.some((plugin) => plugin.beforeEntityMutation || plugin.afterEntityMutation);
5247
5982
  }
5248
5983
  getMutationModel(queryNode) {
5249
- return match15(queryNode).when(InsertQueryNode2.is, (node) => node.into.table.identifier.name).when(UpdateQueryNode2.is, (node) => node.table.table.identifier.name).when(DeleteQueryNode2.is, (node) => {
5984
+ return match16(queryNode).when(InsertQueryNode2.is, (node) => node.into.table.identifier.name).when(UpdateQueryNode2.is, (node) => node.table.table.identifier.name).when(DeleteQueryNode2.is, (node) => {
5250
5985
  if (node.from.froms.length !== 1) {
5251
5986
  throw new InternalError(`Delete query must have exactly one from table`);
5252
5987
  }
@@ -5262,7 +5997,7 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends DefaultQueryExe
5262
5997
  const result = {
5263
5998
  intercept: false
5264
5999
  };
5265
- const { action, where } = match15(queryNode).when(InsertQueryNode2.is, () => ({
6000
+ const { action, where } = match16(queryNode).when(InsertQueryNode2.is, () => ({
5266
6001
  action: "create",
5267
6002
  where: void 0
5268
6003
  })).when(UpdateQueryNode2.is, (node) => ({
@@ -5282,14 +6017,13 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends DefaultQueryExe
5282
6017
  queryNode
5283
6018
  });
5284
6019
  result.intercept ||= filterResult.intercept;
5285
- result.useTransactionForMutation ||= filterResult.useTransactionForMutation;
5286
6020
  result.loadBeforeMutationEntity ||= filterResult.loadBeforeMutationEntity;
5287
6021
  result.loadAfterMutationEntity ||= filterResult.loadAfterMutationEntity;
5288
6022
  }
5289
6023
  }
5290
6024
  let beforeMutationEntities;
5291
6025
  if (result.loadBeforeMutationEntity && (UpdateQueryNode2.is(queryNode) || DeleteQueryNode2.is(queryNode))) {
5292
- beforeMutationEntities = await this.loadEntities(this.kysely, mutationModel, where);
6026
+ beforeMutationEntities = await this.loadEntities(mutationModel, where);
5293
6027
  }
5294
6028
  return {
5295
6029
  ...result,
@@ -5302,16 +6036,16 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends DefaultQueryExe
5302
6036
  return void 0;
5303
6037
  }
5304
6038
  }
5305
- callBeforeMutationHooks(queryNode, mutationInterceptionInfo) {
6039
+ async callBeforeMutationHooks(queryNode, mutationInterceptionInfo) {
5306
6040
  if (!mutationInterceptionInfo?.intercept) {
5307
6041
  return;
5308
6042
  }
5309
6043
  if (this.options.plugins) {
6044
+ const mutationModel = this.getMutationModel(queryNode);
5310
6045
  for (const plugin of this.options.plugins) {
5311
6046
  if (plugin.beforeEntityMutation) {
5312
- plugin.beforeEntityMutation({
5313
- // context: this.queryContext,
5314
- model: this.getMutationModel(queryNode),
6047
+ await plugin.beforeEntityMutation({
6048
+ model: mutationModel,
5315
6049
  action: mutationInterceptionInfo.action,
5316
6050
  queryNode,
5317
6051
  entities: mutationInterceptionInfo.beforeMutationEntities
@@ -5320,44 +6054,59 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends DefaultQueryExe
5320
6054
  }
5321
6055
  }
5322
6056
  }
5323
- async callAfterQueryInterceptionFilters(queryResult, queryNode, mutationInterceptionInfo) {
6057
+ async callAfterMutationHooks(queryResult, queryNode, mutationInterceptionInfo, connection) {
5324
6058
  if (!mutationInterceptionInfo?.intercept) {
5325
6059
  return;
5326
6060
  }
5327
- if (this.options.plugins) {
5328
- const mutationModel = this.getMutationModel(queryNode);
5329
- for (const plugin of this.options.plugins) {
5330
- if (plugin.afterEntityMutation) {
5331
- let afterMutationEntities = void 0;
5332
- if (mutationInterceptionInfo.loadAfterMutationEntity) {
5333
- if (UpdateQueryNode2.is(queryNode)) {
5334
- afterMutationEntities = await this.loadEntities(this.kysely, mutationModel, mutationInterceptionInfo.where);
5335
- } else {
5336
- afterMutationEntities = queryResult.rows;
5337
- }
5338
- }
5339
- plugin.afterEntityMutation({
5340
- model: this.getMutationModel(queryNode),
6061
+ const hooks = [];
6062
+ for (const plugin of this.options.plugins ?? []) {
6063
+ if (plugin.afterEntityMutation) {
6064
+ hooks.push(plugin.afterEntityMutation.bind(plugin));
6065
+ }
6066
+ }
6067
+ if (hooks.length === 0) {
6068
+ return;
6069
+ }
6070
+ const mutationModel = this.getMutationModel(queryNode);
6071
+ const inTransaction = this.driver.isTransactionConnection(connection);
6072
+ for (const hook of hooks) {
6073
+ let afterMutationEntities = void 0;
6074
+ if (mutationInterceptionInfo.loadAfterMutationEntity) {
6075
+ if (InsertQueryNode2.is(queryNode) || UpdateQueryNode2.is(queryNode)) {
6076
+ afterMutationEntities = queryResult.rows;
6077
+ }
6078
+ }
6079
+ const action = /* @__PURE__ */ __name(async () => {
6080
+ try {
6081
+ await hook({
6082
+ model: mutationModel,
5341
6083
  action: mutationInterceptionInfo.action,
5342
6084
  queryNode,
5343
6085
  beforeMutationEntities: mutationInterceptionInfo.beforeMutationEntities,
5344
6086
  afterMutationEntities
5345
6087
  });
6088
+ } catch (err) {
6089
+ console.error(`Error in afterEntityMutation hook for model "${mutationModel}": ${err}`);
5346
6090
  }
6091
+ }, "action");
6092
+ if (inTransaction) {
6093
+ this.driver.registerTransactionCommitCallback(connection, action);
6094
+ } else {
6095
+ await action();
5347
6096
  }
5348
6097
  }
5349
6098
  }
5350
- async loadEntities(kysely, model, where) {
5351
- const selectQuery = kysely.selectFrom(model).selectAll();
6099
+ async loadEntities(model, where) {
6100
+ const selectQuery = this.kysely.selectFrom(model).selectAll();
5352
6101
  let selectQueryNode = selectQuery.toOperationNode();
5353
6102
  selectQueryNode = {
5354
6103
  ...selectQueryNode,
5355
6104
  where: this.andNodes(selectQueryNode.where, where)
5356
6105
  };
5357
- const compiled = kysely.getExecutor().compileQuery(selectQueryNode, {
6106
+ const compiled = this.compileQuery(selectQueryNode);
6107
+ const result = await this.executeQuery(compiled, {
5358
6108
  queryId: `zenstack-${nanoid2()}`
5359
6109
  });
5360
- const result = await kysely.executeQuery(compiled);
5361
6110
  return result.rows;
5362
6111
  }
5363
6112
  andNodes(condition1, condition2) {
@@ -5386,9 +6135,9 @@ __export(functions_exports, {
5386
6135
  search: () => search,
5387
6136
  startsWith: () => startsWith
5388
6137
  });
6138
+ import { invariant as invariant9, lowerCaseFirst, upperCaseFirst } from "@zenstackhq/common-helpers";
5389
6139
  import { sql as sql8, ValueNode as ValueNode4 } from "kysely";
5390
- import invariant8 from "tiny-invariant";
5391
- import { match as match16 } from "ts-pattern";
6140
+ import { match as match17 } from "ts-pattern";
5392
6141
  var contains = /* @__PURE__ */ __name((eb, args) => {
5393
6142
  const [field, search2, caseInsensitive = false] = args;
5394
6143
  if (!field) {
@@ -5473,7 +6222,7 @@ var isEmpty = /* @__PURE__ */ __name((eb, args, { dialect }) => {
5473
6222
  return eb(dialect.buildArrayLength(eb, field), "=", sql8.lit(0));
5474
6223
  }, "isEmpty");
5475
6224
  var now = /* @__PURE__ */ __name((eb, _args, { dialect }) => {
5476
- return match16(dialect.provider).with("postgresql", () => eb.fn("now")).with("sqlite", () => sql8.raw("CURRENT_TIMESTAMP")).exhaustive();
6225
+ return match17(dialect.provider).with("postgresql", () => eb.fn("now")).with("sqlite", () => sql8.raw("CURRENT_TIMESTAMP")).exhaustive();
5477
6226
  }, "now");
5478
6227
  var currentModel = /* @__PURE__ */ __name((_eb, args, { model }) => {
5479
6228
  let result = model;
@@ -5493,8 +6242,8 @@ var currentOperation = /* @__PURE__ */ __name((_eb, args, { operation }) => {
5493
6242
  }, "currentOperation");
5494
6243
  function processCasing(casing, result, model) {
5495
6244
  const opNode = casing.toOperationNode();
5496
- invariant8(ValueNode4.is(opNode) && typeof opNode.value === "string", '"casting" parameter must be a string value');
5497
- result = match16(opNode.value).with("original", () => model).with("upper", () => result.toUpperCase()).with("lower", () => result.toLowerCase()).with("capitalize", () => `${result.charAt(0).toUpperCase() + result.slice(1)}`).with("uncapitalize", () => `${result.charAt(0).toLowerCase() + result.slice(1)}`).otherwise(() => {
6245
+ invariant9(ValueNode4.is(opNode) && typeof opNode.value === "string", '"casting" parameter must be a string value');
6246
+ result = match17(opNode.value).with("original", () => model).with("upper", () => result.toUpperCase()).with("lower", () => result.toLowerCase()).with("capitalize", () => upperCaseFirst(result)).with("uncapitalize", () => lowerCaseFirst(result)).otherwise(() => {
5498
6247
  throw new Error(`Invalid casing value: ${opNode.value}. Must be "original", "upper", "lower", "capitalize", or "uncapitalize".`);
5499
6248
  });
5500
6249
  return result;
@@ -5502,9 +6251,9 @@ function processCasing(casing, result, model) {
5502
6251
  __name(processCasing, "processCasing");
5503
6252
 
5504
6253
  // src/client/helpers/schema-db-pusher.ts
6254
+ import { invariant as invariant10 } from "@zenstackhq/common-helpers";
5505
6255
  import { sql as sql9 } from "kysely";
5506
- import invariant9 from "tiny-invariant";
5507
- import { match as match17 } from "ts-pattern";
6256
+ import { match as match18 } from "ts-pattern";
5508
6257
  var SchemaDbPusher = class {
5509
6258
  static {
5510
6259
  __name(this, "SchemaDbPusher");
@@ -5535,14 +6284,17 @@ var SchemaDbPusher = class {
5535
6284
  for (const [fieldName, fieldDef] of Object.entries(modelDef.fields)) {
5536
6285
  if (fieldDef.relation) {
5537
6286
  table = this.addForeignKeyConstraint(table, model, fieldName, fieldDef);
5538
- } else {
6287
+ } else if (!this.isComputedField(fieldDef)) {
5539
6288
  table = this.createModelField(table, fieldName, fieldDef, modelDef);
5540
6289
  }
5541
6290
  }
5542
6291
  table = this.addPrimaryKeyConstraint(table, model, modelDef);
5543
- table = this.addUniqueConstraint(table, modelDef);
6292
+ table = this.addUniqueConstraint(table, model, modelDef);
5544
6293
  return table;
5545
6294
  }
6295
+ isComputedField(fieldDef) {
6296
+ return fieldDef.attributes?.some((a) => a.name === "@computed");
6297
+ }
5546
6298
  addPrimaryKeyConstraint(table, model, modelDef) {
5547
6299
  if (modelDef.idFields.length === 1) {
5548
6300
  if (Object.values(modelDef.fields).some((f) => f.id)) {
@@ -5554,16 +6306,19 @@ var SchemaDbPusher = class {
5554
6306
  }
5555
6307
  return table;
5556
6308
  }
5557
- addUniqueConstraint(table, modelDef) {
6309
+ addUniqueConstraint(table, model, modelDef) {
5558
6310
  for (const [key, value] of Object.entries(modelDef.uniqueFields)) {
5559
- invariant9(typeof value === "object", "expecting an object");
6311
+ invariant10(typeof value === "object", "expecting an object");
5560
6312
  if ("type" in value) {
5561
6313
  const fieldDef = modelDef.fields[key];
5562
6314
  if (fieldDef.unique) {
5563
6315
  continue;
5564
6316
  }
6317
+ table = table.addUniqueConstraint(`unique_${model}_${key}`, [
6318
+ key
6319
+ ]);
5565
6320
  } else {
5566
- table = table.addUniqueConstraint(`unique_${key}`, Object.keys(value));
6321
+ table = table.addUniqueConstraint(`unique_${model}_${key}`, Object.keys(value));
5567
6322
  }
5568
6323
  }
5569
6324
  return table;
@@ -5602,7 +6357,7 @@ var SchemaDbPusher = class {
5602
6357
  return "serial";
5603
6358
  }
5604
6359
  const type = fieldDef.type;
5605
- const result = match17(type).with("String", () => "text").with("Boolean", () => "boolean").with("Int", () => "integer").with("Float", () => "real").with("BigInt", () => "bigint").with("Decimal", () => "decimal").with("DateTime", () => "timestamp").with("Bytes", () => this.schema.provider.type === "postgresql" ? "bytea" : "blob").otherwise(() => {
6360
+ const result = match18(type).with("String", () => "text").with("Boolean", () => "boolean").with("Int", () => "integer").with("Float", () => "real").with("BigInt", () => "bigint").with("Decimal", () => "decimal").with("DateTime", () => "timestamp").with("Bytes", () => this.schema.provider.type === "postgresql" ? "bytea" : "blob").with("Json", () => "jsonb").otherwise(() => {
5606
6361
  throw new Error(`Unsupported field type: ${type}`);
5607
6362
  });
5608
6363
  if (fieldDef.array) {
@@ -5615,7 +6370,7 @@ var SchemaDbPusher = class {
5615
6370
  return fieldDef.default && ExpressionUtils.isCall(fieldDef.default) && fieldDef.default.function === "autoincrement";
5616
6371
  }
5617
6372
  addForeignKeyConstraint(table, model, fieldName, fieldDef) {
5618
- invariant9(fieldDef.relation, "field must be a relation");
6373
+ invariant10(fieldDef.relation, "field must be a relation");
5619
6374
  if (!fieldDef.relation.fields || !fieldDef.relation.references) {
5620
6375
  return table;
5621
6376
  }
@@ -5631,16 +6386,16 @@ var SchemaDbPusher = class {
5631
6386
  return table;
5632
6387
  }
5633
6388
  mapCascadeAction(action) {
5634
- return match17(action).with("SetNull", () => "set null").with("Cascade", () => "cascade").with("Restrict", () => "restrict").with("NoAction", () => "no action").with("SetDefault", () => "set default").exhaustive();
6389
+ return match18(action).with("SetNull", () => "set null").with("Cascade", () => "cascade").with("Restrict", () => "restrict").with("NoAction", () => "no action").with("SetDefault", () => "set default").exhaustive();
5635
6390
  }
5636
6391
  };
5637
6392
 
5638
6393
  // src/client/promise.ts
5639
- function createDeferredPromise(callback) {
6394
+ function createZenStackPromise(callback) {
5640
6395
  let promise;
5641
- const cb = /* @__PURE__ */ __name(() => {
6396
+ const cb = /* @__PURE__ */ __name((txClient) => {
5642
6397
  try {
5643
- return promise ??= valueToPromise(callback());
6398
+ return promise ??= valueToPromise(callback(txClient));
5644
6399
  } catch (err) {
5645
6400
  return Promise.reject(err);
5646
6401
  }
@@ -5655,10 +6410,11 @@ function createDeferredPromise(callback) {
5655
6410
  finally(onFinally) {
5656
6411
  return cb().finally(onFinally);
5657
6412
  },
6413
+ cb,
5658
6414
  [Symbol.toStringTag]: "ZenStackPromise"
5659
6415
  };
5660
6416
  }
5661
- __name(createDeferredPromise, "createDeferredPromise");
6417
+ __name(createZenStackPromise, "createZenStackPromise");
5662
6418
  function valueToPromise(thing) {
5663
6419
  if (typeof thing === "object" && typeof thing?.then === "function") {
5664
6420
  return thing;
@@ -5669,9 +6425,9 @@ function valueToPromise(thing) {
5669
6425
  __name(valueToPromise, "valueToPromise");
5670
6426
 
5671
6427
  // src/client/result-processor.ts
6428
+ import { invariant as invariant11 } from "@zenstackhq/common-helpers";
5672
6429
  import Decimal2 from "decimal.js";
5673
- import invariant10 from "tiny-invariant";
5674
- import { match as match18 } from "ts-pattern";
6430
+ import { match as match19 } from "ts-pattern";
5675
6431
  var ResultProcessor = class {
5676
6432
  static {
5677
6433
  __name(this, "ResultProcessor");
@@ -5705,6 +6461,21 @@ var ResultProcessor = class {
5705
6461
  data[key] = typeof value === "string" ? JSON.parse(value) : value;
5706
6462
  continue;
5707
6463
  }
6464
+ if (key.startsWith(DELEGATE_JOINED_FIELD_PREFIX)) {
6465
+ if (value) {
6466
+ const subRow = this.transformJson(value);
6467
+ const subModel = key.slice(DELEGATE_JOINED_FIELD_PREFIX.length);
6468
+ const idValues = getIdValues(this.schema, subModel, subRow);
6469
+ if (Object.values(idValues).some((v) => v === null || v === void 0)) {
6470
+ delete data[key];
6471
+ continue;
6472
+ }
6473
+ const processedSubRow = this.processRow(subRow, subModel);
6474
+ Object.assign(data, processedSubRow);
6475
+ }
6476
+ delete data[key];
6477
+ continue;
6478
+ }
5708
6479
  const fieldDef = getField(this.schema, model, key);
5709
6480
  if (!fieldDef) {
5710
6481
  continue;
@@ -5744,20 +6515,24 @@ var ResultProcessor = class {
5744
6515
  return this.doProcessResult(relationData, fieldDef.type);
5745
6516
  }
5746
6517
  transformScalar(value, type) {
5747
- return match18(type).with("Boolean", () => this.transformBoolean(value)).with("DateTime", () => this.transformDate(value)).with("Bytes", () => this.transformBytes(value)).with("Decimal", () => this.transformDecimal(value)).with("BigInt", () => this.transformBigInt(value)).otherwise(() => value);
6518
+ if (this.schema.typeDefs && type in this.schema.typeDefs) {
6519
+ return this.transformJson(value);
6520
+ } else {
6521
+ return match19(type).with("Boolean", () => this.transformBoolean(value)).with("DateTime", () => this.transformDate(value)).with("Bytes", () => this.transformBytes(value)).with("Decimal", () => this.transformDecimal(value)).with("BigInt", () => this.transformBigInt(value)).with("Json", () => this.transformJson(value)).otherwise(() => value);
6522
+ }
5748
6523
  }
5749
6524
  transformDecimal(value) {
5750
6525
  if (value instanceof Decimal2) {
5751
6526
  return value;
5752
6527
  }
5753
- invariant10(typeof value === "string" || typeof value === "number" || value instanceof Decimal2, `Expected string, number or Decimal, got ${typeof value}`);
6528
+ invariant11(typeof value === "string" || typeof value === "number" || value instanceof Decimal2, `Expected string, number or Decimal, got ${typeof value}`);
5754
6529
  return new Decimal2(value);
5755
6530
  }
5756
6531
  transformBigInt(value) {
5757
6532
  if (typeof value === "bigint") {
5758
6533
  return value;
5759
6534
  }
5760
- invariant10(typeof value === "string" || typeof value === "number", `Expected string or number, got ${typeof value}`);
6535
+ invariant11(typeof value === "string" || typeof value === "number", `Expected string or number, got ${typeof value}`);
5761
6536
  return BigInt(value);
5762
6537
  }
5763
6538
  transformBoolean(value) {
@@ -5776,6 +6551,9 @@ var ResultProcessor = class {
5776
6551
  return Buffer.isBuffer(value) ? Uint8Array.from(value) : value;
5777
6552
  }
5778
6553
  fixReversedResult(data, model, args) {
6554
+ if (!data) {
6555
+ return;
6556
+ }
5779
6557
  if (Array.isArray(data) && typeof args === "object" && args && args.take !== void 0 && args.take < 0) {
5780
6558
  data.reverse();
5781
6559
  }
@@ -5789,13 +6567,19 @@ var ResultProcessor = class {
5789
6567
  continue;
5790
6568
  }
5791
6569
  const fieldDef = getField(this.schema, model, field);
5792
- if (!fieldDef?.relation) {
6570
+ if (!fieldDef || !fieldDef.relation || !fieldDef.array) {
5793
6571
  continue;
5794
6572
  }
5795
6573
  this.fixReversedResult(row[field], fieldDef.type, value);
5796
6574
  }
5797
6575
  }
5798
6576
  }
6577
+ transformJson(value) {
6578
+ return match19(this.schema.provider.type).with("sqlite", () => {
6579
+ invariant11(typeof value === "string", "Expected string, got " + typeof value);
6580
+ return JSON.parse(value);
6581
+ }).otherwise(() => value);
6582
+ }
5799
6583
  };
5800
6584
 
5801
6585
  // src/client/client-impl.ts
@@ -5814,7 +6598,7 @@ var ClientImpl = class _ClientImpl {
5814
6598
  $schema;
5815
6599
  kyselyProps;
5816
6600
  auth;
5817
- constructor(schema, options, baseClient) {
6601
+ constructor(schema, options, baseClient, executor) {
5818
6602
  this.schema = schema;
5819
6603
  this.options = options;
5820
6604
  this.$schema = schema;
@@ -5826,24 +6610,23 @@ var ClientImpl = class _ClientImpl {
5826
6610
  if (baseClient) {
5827
6611
  this.kyselyProps = {
5828
6612
  ...baseClient.kyselyProps,
5829
- executor: new ZenStackQueryExecutor(this, baseClient.kyselyProps.driver, baseClient.kyselyProps.dialect.createQueryCompiler(), baseClient.kyselyProps.dialect.createAdapter(), new DefaultConnectionProvider(baseClient.kyselyProps.driver))
6613
+ executor: executor ?? new ZenStackQueryExecutor(this, baseClient.kyselyProps.driver, baseClient.kyselyProps.dialect.createQueryCompiler(), baseClient.kyselyProps.dialect.createAdapter(), new DefaultConnectionProvider(baseClient.kyselyProps.driver))
5830
6614
  };
5831
6615
  this.kyselyRaw = baseClient.kyselyRaw;
6616
+ this.auth = baseClient.auth;
5832
6617
  } else {
5833
- const dialect = this.getKyselyDialect();
5834
- const driver = new ZenStackDriver(dialect.createDriver(), new Log(this.$options.log ?? []));
5835
- const compiler = dialect.createQueryCompiler();
5836
- const adapter = dialect.createAdapter();
6618
+ const driver = new ZenStackDriver(options.dialect.createDriver(), new Log(this.$options.log ?? []));
6619
+ const compiler = options.dialect.createQueryCompiler();
6620
+ const adapter = options.dialect.createAdapter();
5837
6621
  const connectionProvider = new DefaultConnectionProvider(driver);
5838
- const executor = new ZenStackQueryExecutor(this, driver, compiler, adapter, connectionProvider);
5839
6622
  this.kyselyProps = {
5840
6623
  config: {
5841
- dialect,
6624
+ dialect: options.dialect,
5842
6625
  log: this.$options.log
5843
6626
  },
5844
- dialect,
6627
+ dialect: options.dialect,
5845
6628
  driver,
5846
- executor
6629
+ executor: executor ?? new ZenStackQueryExecutor(this, driver, compiler, adapter, connectionProvider)
5847
6630
  };
5848
6631
  this.kyselyRaw = new Kysely({
5849
6632
  ...this.kyselyProps,
@@ -5859,31 +6642,58 @@ var ClientImpl = class _ClientImpl {
5859
6642
  get $qbRaw() {
5860
6643
  return this.kyselyRaw;
5861
6644
  }
5862
- getKyselyDialect() {
5863
- return match19(this.schema.provider.type).with("sqlite", () => this.makeSqliteKyselyDialect()).with("postgresql", () => this.makePostgresKyselyDialect()).exhaustive();
6645
+ get isTransaction() {
6646
+ return this.kysely.isTransaction;
5864
6647
  }
5865
- makePostgresKyselyDialect() {
5866
- const { dialectConfigProvider } = this.schema.provider;
5867
- const mergedConfig = {
5868
- ...dialectConfigProvider(),
5869
- ...this.options?.dialectConfig
5870
- };
5871
- return new PostgresDialect(mergedConfig);
6648
+ /**
6649
+ * Create a new client with a new query executor.
6650
+ */
6651
+ withExecutor(executor) {
6652
+ return new _ClientImpl(this.schema, this.$options, this, executor);
5872
6653
  }
5873
- makeSqliteKyselyDialect() {
5874
- const { dialectConfigProvider } = this.schema.provider;
5875
- const mergedConfig = {
5876
- ...dialectConfigProvider(),
5877
- ...this.options?.dialectConfig
5878
- };
5879
- return new SqliteDialect(mergedConfig);
6654
+ // implementation
6655
+ async $transaction(input, options) {
6656
+ invariant12(typeof input === "function" || Array.isArray(input) && input.every((p) => p.then && p.cb), "Invalid transaction input, expected a function or an array of ZenStackPromise");
6657
+ if (typeof input === "function") {
6658
+ return this.interactiveTransaction(input, options);
6659
+ } else {
6660
+ return this.sequentialTransaction(input, options);
6661
+ }
6662
+ }
6663
+ async interactiveTransaction(callback, options) {
6664
+ if (this.kysely.isTransaction) {
6665
+ return callback(this);
6666
+ } else {
6667
+ let txBuilder = this.kysely.transaction();
6668
+ if (options?.isolationLevel) {
6669
+ txBuilder = txBuilder.setIsolationLevel(options.isolationLevel);
6670
+ }
6671
+ return txBuilder.execute((tx) => {
6672
+ const txClient = new _ClientImpl(this.schema, this.$options, this);
6673
+ txClient.kysely = tx;
6674
+ return callback(txClient);
6675
+ });
6676
+ }
5880
6677
  }
5881
- async $transaction(callback) {
5882
- return this.kysely.transaction().execute((tx) => {
5883
- const txClient = new _ClientImpl(this.schema, this.$options);
6678
+ async sequentialTransaction(arg, options) {
6679
+ const execute = /* @__PURE__ */ __name(async (tx) => {
6680
+ const txClient = new _ClientImpl(this.schema, this.$options, this);
5884
6681
  txClient.kysely = tx;
5885
- return callback(txClient);
5886
- });
6682
+ const result = [];
6683
+ for (const promise of arg) {
6684
+ result.push(await promise.cb(txClient));
6685
+ }
6686
+ return result;
6687
+ }, "execute");
6688
+ if (this.kysely.isTransaction) {
6689
+ return execute(this.kysely);
6690
+ } else {
6691
+ let txBuilder = this.kysely.transaction();
6692
+ if (options?.isolationLevel) {
6693
+ txBuilder = txBuilder.setIsolationLevel(options.isolationLevel);
6694
+ }
6695
+ return txBuilder.execute((tx) => execute(tx));
6696
+ }
5887
6697
  }
5888
6698
  get $procedures() {
5889
6699
  return Object.keys(this.$schema.procedures ?? {}).reduce((acc, name) => {
@@ -5911,12 +6721,26 @@ var ClientImpl = class _ClientImpl {
5911
6721
  await new SchemaDbPusher(this.schema, this.kysely).push();
5912
6722
  }
5913
6723
  $use(plugin) {
6724
+ const newPlugins = [
6725
+ ...this.$options.plugins ?? [],
6726
+ plugin
6727
+ ];
5914
6728
  const newOptions = {
5915
6729
  ...this.options,
5916
- plugins: [
5917
- ...this.options?.plugins ?? [],
5918
- plugin
5919
- ]
6730
+ plugins: newPlugins
6731
+ };
6732
+ return new _ClientImpl(this.schema, newOptions, this);
6733
+ }
6734
+ $unuse(pluginId) {
6735
+ const newPlugins = [];
6736
+ for (const plugin of this.options.plugins ?? []) {
6737
+ if (plugin.id !== pluginId) {
6738
+ newPlugins.push(plugin);
6739
+ }
6740
+ }
6741
+ const newOptions = {
6742
+ ...this.options,
6743
+ plugins: newPlugins
5920
6744
  };
5921
6745
  return new _ClientImpl(this.schema, newOptions, this);
5922
6746
  }
@@ -5938,6 +6762,39 @@ var ClientImpl = class _ClientImpl {
5938
6762
  get $auth() {
5939
6763
  return this.auth;
5940
6764
  }
6765
+ $executeRaw(query, ...values) {
6766
+ return createZenStackPromise(async () => {
6767
+ const result = await sql10(query, ...values).execute(this.kysely);
6768
+ return Number(result.numAffectedRows ?? 0);
6769
+ });
6770
+ }
6771
+ $executeRawUnsafe(query, ...values) {
6772
+ return createZenStackPromise(async () => {
6773
+ const compiledQuery = this.createRawCompiledQuery(query, values);
6774
+ const result = await this.kysely.executeQuery(compiledQuery);
6775
+ return Number(result.numAffectedRows ?? 0);
6776
+ });
6777
+ }
6778
+ $queryRaw(query, ...values) {
6779
+ return createZenStackPromise(async () => {
6780
+ const result = await sql10(query, ...values).execute(this.kysely);
6781
+ return result.rows;
6782
+ });
6783
+ }
6784
+ $queryRawUnsafe(query, ...values) {
6785
+ return createZenStackPromise(async () => {
6786
+ const compiledQuery = this.createRawCompiledQuery(query, values);
6787
+ const result = await this.kysely.executeQuery(compiledQuery);
6788
+ return result.rows;
6789
+ });
6790
+ }
6791
+ createRawCompiledQuery(query, values) {
6792
+ const q = CompiledQuery.raw(query, values);
6793
+ return {
6794
+ ...q,
6795
+ $raw: true
6796
+ };
6797
+ }
5941
6798
  };
5942
6799
  function createClientProxy(client) {
5943
6800
  const inputValidator = new InputValidator(client.$schema);
@@ -5960,9 +6817,9 @@ function createClientProxy(client) {
5960
6817
  __name(createClientProxy, "createClientProxy");
5961
6818
  function createModelCrudHandler(client, model, inputValidator, resultProcessor) {
5962
6819
  const createPromise = /* @__PURE__ */ __name((operation, args, handler, postProcess = false, throwIfNoResult = false) => {
5963
- return createDeferredPromise(async () => {
5964
- let proceed = /* @__PURE__ */ __name(async (_args, tx) => {
5965
- const _handler = tx ? handler.withClient(tx) : handler;
6820
+ return createZenStackPromise(async (txClient) => {
6821
+ let proceed = /* @__PURE__ */ __name(async (_args) => {
6822
+ const _handler = txClient ? handler.withClient(txClient) : handler;
5966
6823
  const r = await _handler.handle(operation, _args ?? args);
5967
6824
  if (!r && throwIfNoResult) {
5968
6825
  throw new NotFoundError(model);
@@ -5975,22 +6832,31 @@ function createModelCrudHandler(client, model, inputValidator, resultProcessor)
5975
6832
  }
5976
6833
  return result;
5977
6834
  }, "proceed");
5978
- const context = {
5979
- client,
5980
- model,
5981
- operation,
5982
- queryArgs: args
5983
- };
5984
6835
  const plugins = [
5985
6836
  ...client.$options.plugins ?? []
5986
6837
  ];
5987
6838
  for (const plugin of plugins) {
5988
- if (plugin.onQuery) {
5989
- const _proceed = proceed;
5990
- proceed = /* @__PURE__ */ __name(() => plugin.onQuery({
5991
- ...context,
5992
- proceed: _proceed
5993
- }), "proceed");
6839
+ if (plugin.onQuery && typeof plugin.onQuery === "object") {
6840
+ for (const [_model, modelHooks] of Object.entries(plugin.onQuery)) {
6841
+ if (_model === lowerCaseFirst2(model) || _model === "$allModels") {
6842
+ if (modelHooks && typeof modelHooks === "object") {
6843
+ for (const [op, opHooks] of Object.entries(modelHooks)) {
6844
+ if (op === operation || op === "$allOperations") {
6845
+ if (typeof opHooks === "function") {
6846
+ const _proceed = proceed;
6847
+ proceed = /* @__PURE__ */ __name(() => opHooks({
6848
+ client,
6849
+ model,
6850
+ operation,
6851
+ args,
6852
+ query: _proceed
6853
+ }), "proceed");
6854
+ }
6855
+ }
6856
+ }
6857
+ }
6858
+ }
6859
+ }
5994
6860
  }
5995
6861
  }
5996
6862
  return proceed(args);
@@ -6046,12 +6912,23 @@ function createModelCrudHandler(client, model, inputValidator, resultProcessor)
6046
6912
  return createPromise("aggregate", args, new AggregateOperationHandler(client, model, inputValidator), false);
6047
6913
  }, "aggregate"),
6048
6914
  groupBy: /* @__PURE__ */ __name((args) => {
6049
- return createPromise("groupBy", args, new GroupByeOperationHandler(client, model, inputValidator));
6915
+ return createPromise("groupBy", args, new GroupByOperationHandler(client, model, inputValidator), true);
6050
6916
  }, "groupBy")
6051
6917
  };
6052
6918
  }
6053
6919
  __name(createModelCrudHandler, "createModelCrudHandler");
6920
+
6921
+ // src/client/plugin.ts
6922
+ function definePlugin(plugin) {
6923
+ return plugin;
6924
+ }
6925
+ __name(definePlugin, "definePlugin");
6054
6926
  export {
6055
- ZenStackClient
6927
+ InputValidationError,
6928
+ InternalError,
6929
+ NotFoundError,
6930
+ QueryError,
6931
+ ZenStackClient,
6932
+ definePlugin
6056
6933
  };
6057
6934
  //# sourceMappingURL=index.js.map