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

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-D8U59Syb.d.cts} +971 -785
  2. package/dist/{contract-DguafRNB.d.ts → contract-D8U59Syb.d.ts} +971 -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 +1787 -903
  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 +1758 -879
  14. package/dist/index.js.map +1 -1
  15. package/dist/plugins/{policy.cjs → policy/index.cjs} +472 -271
  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} +447 -236
  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 sql9 } 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";
283
- import { expressionBuilder as expressionBuilder2, sql as sql4 } from "kysely";
427
+ import { invariant as invariant7, isPlainObject as isPlainObject3 } from "@zenstackhq/common-helpers";
428
+ import { expressionBuilder as expressionBuilder3, 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
316
- import { sql } from "kysely";
317
- import invariant from "tiny-invariant";
318
- import { match, P } from "ts-pattern";
483
+ import { invariant, isPlainObject } from "@zenstackhq/common-helpers";
484
+ import { expressionBuilder, sql } from "kysely";
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 = this.fieldRef(fieldDef.originModel ?? model, key, 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, this.fieldRef(model, k, eb, modelAlias), field), sql.raw(this.negateSort(v, negated)));
676
874
  }
677
875
  continue;
678
876
  }
@@ -681,7 +879,7 @@ var BaseCrudDialect = class {
681
879
  invariant(value && typeof value === "object", 'invalid orderBy value for field "_count"');
682
880
  for (const [k, v] of Object.entries(value)) {
683
881
  invariant(v === "asc" || v === "desc", `invalid orderBy value for field "${field}"`);
684
- result = result.orderBy((eb) => eb.fn.count(sql.ref(k)), sql.raw(this.negateSort(v, negated)));
882
+ result = result.orderBy((eb) => eb.fn.count(this.fieldRef(model, k, eb, modelAlias)), sql.raw(this.negateSort(v, negated)));
685
883
  }
686
884
  continue;
687
885
  }
@@ -690,10 +888,11 @@ var BaseCrudDialect = class {
690
888
  }
691
889
  const fieldDef = requireField(this.schema, model, field);
692
890
  if (!fieldDef.relation) {
891
+ const fieldRef = this.fieldRef(model, field, expressionBuilder(), modelAlias);
693
892
  if (value === "asc" || value === "desc") {
694
- result = result.orderBy(sql.ref(`${modelAlias}.${field}`), this.negateSort(value, negated));
893
+ result = result.orderBy(fieldRef, this.negateSort(value, negated));
695
894
  } else if (value && typeof value === "object" && "nulls" in value && "sort" in value && (value.sort === "asc" || value.sort === "desc") && (value.nulls === "first" || value.nulls === "last")) {
696
- result = result.orderBy(sql.ref(`${modelAlias}.${field}`), sql.raw(`${this.negateSort(value.sort, negated)} nulls ${value.nulls}`));
895
+ result = result.orderBy(fieldRef, sql.raw(`${this.negateSort(value.sort, negated)} nulls ${value.nulls}`));
697
896
  }
698
897
  } else {
699
898
  const relationModel = fieldDef.type;
@@ -705,7 +904,7 @@ var BaseCrudDialect = class {
705
904
  invariant(value._count === "asc" || value._count === "desc", 'invalid orderBy value for field "_count"');
706
905
  const sort = this.negateSort(value._count, negated);
707
906
  result = result.orderBy((eb) => {
708
- let subQuery = eb.selectFrom(relationModel);
907
+ let subQuery = this.buildSelectModel(eb, relationModel);
709
908
  const joinPairs = buildJoinPairs(this.schema, model, modelAlias, field, relationModel);
710
909
  subQuery = subQuery.where(() => this.and(eb, ...joinPairs.map(([left, right]) => eb(sql.ref(left), "=", sql.ref(right)))));
711
910
  subQuery = subQuery.select(() => eb.fn.count(eb.lit(1)).as("_count"));
@@ -724,14 +923,90 @@ var BaseCrudDialect = class {
724
923
  });
725
924
  return result;
726
925
  }
926
+ buildSelectAllFields(model, query, omit) {
927
+ const modelDef = requireModel(this.schema, model);
928
+ let result = query;
929
+ for (const field of Object.keys(modelDef.fields)) {
930
+ if (isRelationField(this.schema, model, field)) {
931
+ continue;
932
+ }
933
+ if (omit?.[field] === true) {
934
+ continue;
935
+ }
936
+ result = this.buildSelectField(result, model, model, field);
937
+ }
938
+ const descendants = getDelegateDescendantModels(this.schema, model);
939
+ for (const subModel of descendants) {
940
+ result = this.buildDelegateJoin(model, subModel.name, result);
941
+ result = result.select((eb) => {
942
+ const jsonObject = {};
943
+ for (const field of Object.keys(subModel.fields)) {
944
+ if (isRelationField(this.schema, subModel.name, field) || isInheritedField(this.schema, subModel.name, field)) {
945
+ continue;
946
+ }
947
+ jsonObject[field] = eb.ref(`${subModel.name}.${field}`);
948
+ }
949
+ return this.buildJsonObject(eb, jsonObject).as(`${DELEGATE_JOINED_FIELD_PREFIX}${subModel.name}`);
950
+ });
951
+ }
952
+ return result;
953
+ }
954
+ buildSelectField(query, model, modelAlias, field) {
955
+ const fieldDef = requireField(this.schema, model, field);
956
+ if (fieldDef.computed) {
957
+ return query.select((eb) => this.fieldRef(model, field, eb, modelAlias).as(field));
958
+ } else if (!fieldDef.originModel) {
959
+ return query.select(sql.ref(`${modelAlias}.${field}`).as(field));
960
+ } else {
961
+ return this.buildSelectField(query, fieldDef.originModel, fieldDef.originModel, field);
962
+ }
963
+ }
964
+ buildDelegateJoin(thisModel, otherModel, query) {
965
+ const idFields = getIdFields(this.schema, thisModel);
966
+ query = query.leftJoin(otherModel, (qb) => {
967
+ for (const idField of idFields) {
968
+ qb = qb.onRef(`${thisModel}.${idField}`, "=", `${otherModel}.${idField}`);
969
+ }
970
+ return qb;
971
+ });
972
+ return query;
973
+ }
974
+ buildCountJson(model, eb, parentAlias, payload) {
975
+ const modelDef = requireModel(this.schema, model);
976
+ const toManyRelations = Object.entries(modelDef.fields).filter(([, field]) => field.relation && field.array);
977
+ const selections = payload === true ? {
978
+ select: toManyRelations.reduce((acc, [field]) => {
979
+ acc[field] = true;
980
+ return acc;
981
+ }, {})
982
+ } : payload;
983
+ const jsonObject = {};
984
+ for (const [field, value] of Object.entries(selections.select)) {
985
+ const fieldDef = requireField(this.schema, model, field);
986
+ const fieldModel = fieldDef.type;
987
+ const joinPairs = buildJoinPairs(this.schema, model, parentAlias, field, fieldModel);
988
+ let fieldCountQuery = eb.selectFrom(fieldModel).select(eb.fn.countAll().as(`_count$${field}`));
989
+ for (const [left, right] of joinPairs) {
990
+ fieldCountQuery = fieldCountQuery.whereRef(left, "=", right);
991
+ }
992
+ if (value && typeof value === "object" && "where" in value && value.where && typeof value.where === "object") {
993
+ const filter = this.buildFilter(eb, fieldModel, fieldModel, value.where);
994
+ fieldCountQuery = fieldCountQuery.where(filter);
995
+ }
996
+ jsonObject[field] = fieldCountQuery;
997
+ }
998
+ return this.buildJsonObject(eb, jsonObject);
999
+ }
1000
+ // #endregion
1001
+ // #region utils
727
1002
  negateSort(sort, negated) {
728
1003
  return negated ? sort === "asc" ? "desc" : "asc" : sort;
729
1004
  }
730
1005
  true(eb) {
731
- return eb.lit(this.transformPrimitive(true, "Boolean"));
1006
+ return eb.lit(this.transformPrimitive(true, "Boolean", false));
732
1007
  }
733
1008
  false(eb) {
734
- return eb.lit(this.transformPrimitive(false, "Boolean"));
1009
+ return eb.lit(this.transformPrimitive(false, "Boolean", false));
735
1010
  }
736
1011
  isTrue(expression) {
737
1012
  const node = expression.toOperationNode();
@@ -770,6 +1045,9 @@ var BaseCrudDialect = class {
770
1045
  not(eb, ...args) {
771
1046
  return eb.not(this.and(eb, ...args));
772
1047
  }
1048
+ fieldRef(model, field, eb, modelAlias) {
1049
+ return buildFieldRef(this.schema, model, field, this.options, eb, modelAlias);
1050
+ }
773
1051
  };
774
1052
 
775
1053
  // src/client/crud/dialects/postgresql.ts
@@ -780,14 +1058,18 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
780
1058
  get provider() {
781
1059
  return "postgresql";
782
1060
  }
783
- transformPrimitive(value, type) {
1061
+ transformPrimitive(value, type, forArrayField) {
784
1062
  if (value === void 0) {
785
1063
  return value;
786
1064
  }
787
1065
  if (Array.isArray(value)) {
788
- return value.map((v) => this.transformPrimitive(v, type));
1066
+ if (type === "Json" && !forArrayField) {
1067
+ return JSON.stringify(value);
1068
+ } else {
1069
+ return value.map((v) => this.transformPrimitive(v, type, false));
1070
+ }
789
1071
  } else {
790
- return match2(type).with("DateTime", () => value instanceof Date ? value : typeof value === "string" ? new Date(value) : value).otherwise(() => value);
1072
+ 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
1073
  }
792
1074
  }
793
1075
  buildRelationSelection(query, model, relationField, parentAlias, payload) {
@@ -801,7 +1083,8 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
801
1083
  const joinTableName = `${parentName}$${relationField}`;
802
1084
  let result = eb.selectFrom(`${relationModel} as ${joinTableName}`);
803
1085
  result = eb.selectFrom(() => {
804
- let subQuery = eb.selectFrom(`${relationModel}`).selectAll();
1086
+ let subQuery = this.buildSelectModel(eb, relationModel);
1087
+ subQuery = this.buildSelectAllFields(relationModel, subQuery, typeof payload === "object" ? payload?.omit : void 0);
805
1088
  if (payload && typeof payload === "object") {
806
1089
  if (payload.where) {
807
1090
  subQuery = subQuery.where((eb2) => this.buildFilter(eb2, relationModel, relationModel, payload.where));
@@ -845,34 +1128,57 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
845
1128
  });
846
1129
  return qb;
847
1130
  }
848
- buildRelationObjectArgs(relationModel, relationField, eb, payload, parentName) {
1131
+ buildRelationObjectArgs(relationModel, relationField, eb, payload, parentAlias) {
849
1132
  const relationModelDef = requireModel(this.schema, relationModel);
850
1133
  const objArgs = [];
1134
+ const descendantModels = getDelegateDescendantModels(this.schema, relationModel);
1135
+ if (descendantModels.length > 0) {
1136
+ objArgs.push(...descendantModels.map((subModel) => [
1137
+ sql2.lit(`${DELEGATE_JOINED_FIELD_PREFIX}${subModel.name}`),
1138
+ eb.ref(`${DELEGATE_JOINED_FIELD_PREFIX}${subModel.name}`)
1139
+ ]).flatMap((v) => v));
1140
+ }
851
1141
  if (payload === true || !payload.select) {
852
1142
  objArgs.push(...Object.entries(relationModelDef.fields).filter(([, value]) => !value.relation).filter(([name]) => !(typeof payload === "object" && payload.omit?.[name] === true)).map(([field]) => [
853
1143
  sql2.lit(field),
854
- buildFieldRef(this.schema, relationModel, field, this.options, eb)
1144
+ this.fieldRef(relationModel, field, eb)
855
1145
  ]).flatMap((v) => v));
856
1146
  } 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));
1147
+ objArgs.push(...Object.entries(payload.select).filter(([, value]) => value).map(([field, value]) => {
1148
+ if (field === "_count") {
1149
+ const subJson = this.buildCountJson(relationModel, eb, `${parentAlias}$${relationField}`, value);
1150
+ return [
1151
+ sql2.lit(field),
1152
+ subJson
1153
+ ];
1154
+ } else {
1155
+ const fieldDef = requireField(this.schema, relationModel, field);
1156
+ const fieldValue = fieldDef.relation ? eb.ref(`${parentAlias}$${relationField}$${field}.$j`) : this.fieldRef(relationModel, field, eb);
1157
+ return [
1158
+ sql2.lit(field),
1159
+ fieldValue
1160
+ ];
1161
+ }
1162
+ }).flatMap((v) => v));
861
1163
  }
862
1164
  if (typeof payload === "object" && payload.include && typeof payload.include === "object") {
863
1165
  objArgs.push(...Object.entries(payload.include).filter(([, value]) => value).map(([field]) => [
864
1166
  sql2.lit(field),
865
- eb.ref(`${parentName}$${relationField}$${field}.$j`)
1167
+ // reference the synthesized JSON field
1168
+ eb.ref(`${parentAlias}$${relationField}$${field}.$j`)
866
1169
  ]).flatMap((v) => v));
867
1170
  }
868
1171
  return objArgs;
869
1172
  }
870
- buildRelationJoins(model, relationField, qb, payload, parentName) {
1173
+ buildRelationJoins(relationModel, relationField, qb, payload, parentName) {
871
1174
  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
- });
1175
+ if (typeof payload === "object") {
1176
+ const selectInclude = payload.include ?? payload.select;
1177
+ if (selectInclude && typeof selectInclude === "object") {
1178
+ Object.entries(selectInclude).filter(([, value]) => value).filter(([field]) => isRelationField(this.schema, relationModel, field)).forEach(([field, value]) => {
1179
+ result = this.buildRelationJSON(relationModel, result, field, `${parentName}$${relationField}`, value);
1180
+ });
1181
+ }
876
1182
  }
877
1183
  return result;
878
1184
  }
@@ -912,12 +1218,15 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
912
1218
  return `ARRAY[${values.map((v) => typeof v === "string" ? `'${v}'` : v)}]`;
913
1219
  }
914
1220
  }
1221
+ get supportInsertWithDefault() {
1222
+ return true;
1223
+ }
915
1224
  };
916
1225
 
917
1226
  // src/client/crud/dialects/sqlite.ts
1227
+ import { invariant as invariant3 } from "@zenstackhq/common-helpers";
918
1228
  import { sql as sql3 } from "kysely";
919
- import invariant3 from "tiny-invariant";
920
- import { match as match3 } from "ts-pattern";
1229
+ import { match as match4 } from "ts-pattern";
921
1230
  var SqliteCrudDialect = class extends BaseCrudDialect {
922
1231
  static {
923
1232
  __name(this, "SqliteCrudDialect");
@@ -925,26 +1234,31 @@ var SqliteCrudDialect = class extends BaseCrudDialect {
925
1234
  get provider() {
926
1235
  return "sqlite";
927
1236
  }
928
- transformPrimitive(value, type) {
1237
+ transformPrimitive(value, type, _forArrayField) {
929
1238
  if (value === void 0) {
930
1239
  return value;
931
1240
  }
932
1241
  if (Array.isArray(value)) {
933
- return value.map((v) => this.transformPrimitive(v, type));
1242
+ return value.map((v) => this.transformPrimitive(v, type, false));
934
1243
  } 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);
1244
+ if (this.schema.typeDefs && type in this.schema.typeDefs) {
1245
+ return JSON.stringify(value);
1246
+ } else {
1247
+ 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);
1248
+ }
936
1249
  }
937
1250
  }
938
1251
  buildRelationSelection(query, model, relationField, parentAlias, payload) {
939
1252
  return query.select((eb) => this.buildRelationJSON(model, eb, relationField, parentAlias, payload).as(relationField));
940
1253
  }
941
- buildRelationJSON(model, eb, relationField, parentName, payload) {
1254
+ buildRelationJSON(model, eb, relationField, parentAlias, payload) {
942
1255
  const relationFieldDef = requireField(this.schema, model, relationField);
943
1256
  const relationModel = relationFieldDef.type;
944
1257
  const relationModelDef = requireModel(this.schema, relationModel);
945
- const subQueryName = `${parentName}$${relationField}`;
1258
+ const subQueryName = `${parentAlias}$${relationField}`;
946
1259
  let tbl = eb.selectFrom(() => {
947
- let subQuery = eb.selectFrom(relationModel).selectAll();
1260
+ let subQuery = this.buildSelectModel(eb, relationModel);
1261
+ subQuery = this.buildSelectAllFields(relationModel, subQuery, typeof payload === "object" ? payload?.omit : void 0);
948
1262
  if (payload && typeof payload === "object") {
949
1263
  if (payload.where) {
950
1264
  subQuery = subQuery.where((eb2) => this.buildFilter(eb2, relationModel, relationModel, payload.where));
@@ -965,14 +1279,14 @@ var SqliteCrudDialect = class extends BaseCrudDialect {
965
1279
  const relationIds = getIdFields(this.schema, relationModel);
966
1280
  invariant3(parentIds.length === 1, "many-to-many relation must have exactly one id field");
967
1281
  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}`)));
1282
+ 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
1283
  } else {
970
1284
  const { keyPairs, ownedByModel } = getRelationForeignKeyFieldPairs(this.schema, model, relationField);
971
1285
  keyPairs.forEach(({ fk, pk }) => {
972
1286
  if (ownedByModel) {
973
- subQuery = subQuery.whereRef(`${relationModel}.${pk}`, "=", `${parentName}.${fk}`);
1287
+ subQuery = subQuery.whereRef(`${relationModel}.${pk}`, "=", `${parentAlias}.${fk}`);
974
1288
  } else {
975
- subQuery = subQuery.whereRef(`${relationModel}.${fk}`, "=", `${parentName}.${pk}`);
1289
+ subQuery = subQuery.whereRef(`${relationModel}.${fk}`, "=", `${parentAlias}.${pk}`);
976
1290
  }
977
1291
  });
978
1292
  }
@@ -980,167 +1294,106 @@ var SqliteCrudDialect = class extends BaseCrudDialect {
980
1294
  });
981
1295
  tbl = tbl.select(() => {
982
1296
  const objArgs = [];
1297
+ const descendantModels = getDelegateDescendantModels(this.schema, relationModel);
1298
+ if (descendantModels.length > 0) {
1299
+ objArgs.push(...descendantModels.map((subModel) => [
1300
+ sql3.lit(`${DELEGATE_JOINED_FIELD_PREFIX}${subModel.name}`),
1301
+ eb.ref(`${DELEGATE_JOINED_FIELD_PREFIX}${subModel.name}`)
1302
+ ]).flatMap((v) => v));
1303
+ }
983
1304
  if (payload === true || !payload.select) {
984
1305
  objArgs.push(...Object.entries(relationModelDef.fields).filter(([, value]) => !value.relation).filter(([name]) => !(typeof payload === "object" && payload.omit?.[name] === true)).map(([field]) => [
985
1306
  sql3.lit(field),
986
- buildFieldRef(this.schema, relationModel, field, this.options, eb)
1307
+ this.fieldRef(relationModel, field, eb)
987
1308
  ]).flatMap((v) => v));
988
1309
  } else if (payload.select) {
989
1310
  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);
1311
+ if (field === "_count") {
1312
+ const subJson = this.buildCountJson(relationModel, eb, `${parentAlias}$${relationField}`, value);
993
1313
  return [
994
1314
  sql3.lit(field),
995
1315
  subJson
996
1316
  ];
997
1317
  } else {
998
- return [
999
- sql3.lit(field),
1000
- buildFieldRef(this.schema, relationModel, field, this.options, eb)
1001
- ];
1318
+ const fieldDef = requireField(this.schema, relationModel, field);
1319
+ if (fieldDef.relation) {
1320
+ const subJson = this.buildRelationJSON(relationModel, eb, field, `${parentAlias}$${relationField}`, value);
1321
+ return [
1322
+ sql3.lit(field),
1323
+ subJson
1324
+ ];
1325
+ } else {
1326
+ return [
1327
+ sql3.lit(field),
1328
+ this.fieldRef(relationModel, field, eb)
1329
+ ];
1330
+ }
1002
1331
  }
1003
1332
  }).flatMap((v) => v));
1004
1333
  }
1005
1334
  if (typeof payload === "object" && payload.include && typeof payload.include === "object") {
1006
1335
  objArgs.push(...Object.entries(payload.include).filter(([, value]) => value).map(([field, value]) => {
1007
- const subJson = this.buildRelationJSON(relationModel, eb, field, `${parentName}$${relationField}`, value);
1336
+ const subJson = this.buildRelationJSON(relationModel, eb, field, `${parentAlias}$${relationField}`, value);
1008
1337
  return [
1009
1338
  sql3.lit(field),
1010
1339
  subJson
1011
1340
  ];
1012
1341
  }).flatMap((v) => v));
1013
1342
  }
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")
1343
+ if (relationFieldDef.array) {
1344
+ return eb.fn.coalesce(sql3`json_group_array(json_object(${sql3.join(objArgs)}))`, sql3`json_array()`).as("$j");
1345
+ } else {
1346
+ return sql3`json_object(${sql3.join(objArgs)})`.as("data");
1347
+ }
1348
+ });
1349
+ return tbl;
1350
+ }
1351
+ buildSkipTake(query, skip, take) {
1352
+ if (take !== void 0) {
1353
+ query = query.limit(take);
1354
+ }
1355
+ if (skip !== void 0) {
1356
+ query = query.offset(skip);
1357
+ if (take === void 0) {
1358
+ query = query.limit(-1);
1359
+ }
1360
+ }
1361
+ return query;
1362
+ }
1363
+ buildJsonObject(eb, value) {
1364
+ return eb.fn("json_object", Object.entries(value).flatMap(([key, value2]) => [
1365
+ sql3.lit(key),
1366
+ value2
1367
+ ]));
1368
+ }
1369
+ get supportsUpdateWithLimit() {
1370
+ return false;
1371
+ }
1372
+ get supportsDeleteWithLimit() {
1373
+ return false;
1374
+ }
1375
+ get supportsDistinctOn() {
1376
+ return false;
1377
+ }
1378
+ buildArrayLength(eb, array) {
1379
+ return eb.fn("json_array_length", [
1380
+ array
1381
+ ]);
1382
+ }
1383
+ buildArrayLiteralSQL(_values) {
1384
+ throw new Error("SQLite does not support array literals");
1385
+ }
1386
+ get supportInsertWithDefault() {
1387
+ return false;
1388
+ }
1142
1389
  };
1143
1390
 
1391
+ // src/client/crud/dialects/index.ts
1392
+ function getCrudDialect(schema, options) {
1393
+ return match5(schema.provider.type).with("sqlite", () => new SqliteCrudDialect(schema, options)).with("postgresql", () => new PostgresCrudDialect(schema, options)).exhaustive();
1394
+ }
1395
+ __name(getCrudDialect, "getCrudDialect");
1396
+
1144
1397
  // src/utils/default-operation-node-visitor.ts
1145
1398
  import { OperationNodeVisitor } from "kysely";
1146
1399
  var DefaultOperationNodeVisitor = class extends OperationNodeVisitor {
@@ -1460,19 +1713,19 @@ var ColumnCollector = class extends DefaultOperationNodeVisitor {
1460
1713
  };
1461
1714
 
1462
1715
  // src/plugins/policy/expression-transformer.ts
1463
- 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";
1716
+ import { invariant as invariant5 } from "@zenstackhq/common-helpers";
1717
+ import { AliasNode as AliasNode2, BinaryOperationNode as BinaryOperationNode2, ColumnNode, expressionBuilder as expressionBuilder2, FromNode, FunctionNode as FunctionNode2, IdentifierNode, OperatorNode as OperatorNode2, ReferenceNode as ReferenceNode2, SelectionNode, SelectQueryNode, TableNode as TableNode2, ValueListNode, ValueNode as ValueNode2, WhereNode } from "kysely";
1718
+ import { match as match7 } from "ts-pattern";
1466
1719
 
1467
1720
  // src/plugins/policy/expression-evaluator.ts
1468
- import invariant4 from "tiny-invariant";
1469
- import { match as match5 } from "ts-pattern";
1721
+ import { invariant as invariant4 } from "@zenstackhq/common-helpers";
1722
+ import { match as match6 } from "ts-pattern";
1470
1723
  var ExpressionEvaluator = class {
1471
1724
  static {
1472
1725
  __name(this, "ExpressionEvaluator");
1473
1726
  }
1474
1727
  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();
1728
+ 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
1729
  return result ?? null;
1477
1730
  }
1478
1731
  evaluateCall(expr2, context) {
@@ -1483,7 +1736,7 @@ var ExpressionEvaluator = class {
1483
1736
  }
1484
1737
  }
1485
1738
  evaluateUnary(expr2, context) {
1486
- return match5(expr2.op).with("!", () => !this.evaluate(expr2.operand, context)).exhaustive();
1739
+ return match6(expr2.op).with("!", () => !this.evaluate(expr2.operand, context)).exhaustive();
1487
1740
  }
1488
1741
  evaluateMember(expr2, context) {
1489
1742
  let val = this.evaluate(expr2.receiver, context);
@@ -1507,7 +1760,7 @@ var ExpressionEvaluator = class {
1507
1760
  }
1508
1761
  const left = this.evaluate(expr2.left, context);
1509
1762
  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", () => {
1763
+ 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
1764
  const _right = right ?? [];
1512
1765
  invariant4(Array.isArray(_right), 'expected array for "in" operator');
1513
1766
  return _right.includes(left);
@@ -1521,7 +1774,7 @@ var ExpressionEvaluator = class {
1521
1774
  return false;
1522
1775
  }
1523
1776
  invariant4(Array.isArray(left), "expected array");
1524
- return match5(op).with("?", () => left.some((item) => this.evaluate(expr2.right, {
1777
+ return match6(op).with("?", () => left.some((item) => this.evaluate(expr2.right, {
1525
1778
  ...context,
1526
1779
  thisValue: item
1527
1780
  }))).with("!", () => left.every((item) => this.evaluate(expr2.right, {
@@ -1537,11 +1790,11 @@ var ExpressionEvaluator = class {
1537
1790
  // src/plugins/policy/utils.ts
1538
1791
  import { AliasNode, AndNode, BinaryOperationNode, FunctionNode, OperatorNode, OrNode, ParensNode, ReferenceNode, TableNode, UnaryOperationNode, ValueNode } from "kysely";
1539
1792
  function trueNode(dialect) {
1540
- return ValueNode.createImmediate(dialect.transformPrimitive(true, "Boolean"));
1793
+ return ValueNode.createImmediate(dialect.transformPrimitive(true, "Boolean", false));
1541
1794
  }
1542
1795
  __name(trueNode, "trueNode");
1543
1796
  function falseNode(dialect) {
1544
- return ValueNode.createImmediate(dialect.transformPrimitive(false, "Boolean"));
1797
+ return ValueNode.createImmediate(dialect.transformPrimitive(false, "Boolean", false));
1545
1798
  }
1546
1799
  __name(falseNode, "falseNode");
1547
1800
  function isTrueNode(node) {
@@ -1775,7 +2028,7 @@ var ExpressionTransformer = class {
1775
2028
  const count = FunctionNode2.create("count", [
1776
2029
  ValueNode2.createImmediate(1)
1777
2030
  ]);
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();
2031
+ 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
2032
  return this.transform(expr2.left, {
1780
2033
  ...context,
1781
2034
  memberSelect: SelectionNode.create(AliasNode2.create(predicateResult, IdentifierNode.create("$t"))),
@@ -1799,14 +2052,14 @@ var ExpressionTransformer = class {
1799
2052
  }
1800
2053
  }
1801
2054
  transformValue(value, type) {
1802
- return ValueNode2.create(this.dialect.transformPrimitive(value, type) ?? null);
2055
+ return ValueNode2.create(this.dialect.transformPrimitive(value, type, false) ?? null);
1803
2056
  }
1804
2057
  _unary(expr2, context) {
1805
2058
  invariant5(expr2.op === "!", 'only "!" operator is supported');
1806
2059
  return BinaryOperationNode2.create(this.transform(expr2.operand, context), this.transformOperator("!="), trueNode(this.dialect));
1807
2060
  }
1808
2061
  transformOperator(op) {
1809
- const mappedOp = match6(op).with("==", () => "=").otherwise(() => op);
2062
+ const mappedOp = match7(op).with("==", () => "=").otherwise(() => op);
1810
2063
  return OperatorNode2.create(mappedOp);
1811
2064
  }
1812
2065
  _call(expr2, context) {
@@ -1818,7 +2071,7 @@ var ExpressionTransformer = class {
1818
2071
  if (!func) {
1819
2072
  throw new QueryError(`Function not implemented: ${expr2.function}`);
1820
2073
  }
1821
- const eb = expressionBuilder();
2074
+ const eb = expressionBuilder2();
1822
2075
  return func(eb, (expr2.args ?? []).map((arg) => this.transformCallArg(eb, arg, context)), {
1823
2076
  dialect: this.dialect,
1824
2077
  model: context.model,
@@ -2042,7 +2295,7 @@ var PolicyHandler = class extends OperationNodeTransformer {
2042
2295
  get kysely() {
2043
2296
  return this.client.$qb;
2044
2297
  }
2045
- async handle(node, proceed, transaction) {
2298
+ async handle(node, proceed) {
2046
2299
  if (!this.isCrudQueryNode(node)) {
2047
2300
  throw new RejectedByPolicyError(void 0, "non-CRUD queries are not allowed");
2048
2301
  }
@@ -2062,27 +2315,20 @@ var PolicyHandler = class extends OperationNodeTransformer {
2062
2315
  if (!mutationRequiresTransaction && !node.returning) {
2063
2316
  return proceed(this.transformNode(node));
2064
2317
  }
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;
2318
+ if (InsertQueryNode.is(node)) {
2319
+ await this.enforcePreCreatePolicy(node, proceed);
2320
+ }
2321
+ const transformedNode = this.transformNode(node);
2322
+ const result = await proceed(transformedNode);
2323
+ if (!this.onlyReturningId(node)) {
2324
+ const readBackResult = await this.processReadBack(node, result, proceed);
2325
+ if (readBackResult.rows.length !== result.rows.length) {
2326
+ throw new RejectedByPolicyError(mutationModel, "result is not allowed to be read back");
2080
2327
  }
2081
- });
2082
- if (readBackError) {
2083
- throw new RejectedByPolicyError(mutationModel, "result is not allowed to be read back");
2328
+ return readBackResult;
2329
+ } else {
2330
+ return result;
2084
2331
  }
2085
- return result;
2086
2332
  }
2087
2333
  onlyReturningId(node) {
2088
2334
  if (!node.returning) {
@@ -2143,11 +2389,11 @@ var PolicyHandler = class extends OperationNodeTransformer {
2143
2389
  if (typeof item === "object" && item && "kind" in item) {
2144
2390
  invariant6(item.kind === "ValueNode", "expecting a ValueNode");
2145
2391
  result.push({
2146
- node: ValueNode3.create(this.dialect.transformPrimitive(item.value, fieldDef.type)),
2392
+ node: ValueNode3.create(this.dialect.transformPrimitive(item.value, fieldDef.type, !!fieldDef.array)),
2147
2393
  raw: item.value
2148
2394
  });
2149
2395
  } else {
2150
- const value = this.dialect.transformPrimitive(item, fieldDef.type);
2396
+ const value = this.dialect.transformPrimitive(item, fieldDef.type, !!fieldDef.array);
2151
2397
  if (Array.isArray(value)) {
2152
2398
  result.push({
2153
2399
  node: RawNode.createWithSql(this.dialect.buildArrayLiteralSQL(value)),
@@ -2216,7 +2462,7 @@ var PolicyHandler = class extends OperationNodeTransformer {
2216
2462
  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
2463
  }
2218
2464
  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) => {
2465
+ const r = match8(node).when(InsertQueryNode.is, (node2) => getTableName(node2.into)).when(UpdateQueryNode.is, (node2) => getTableName(node2.table)).when(DeleteQueryNode.is, (node2) => {
2220
2466
  if (node2.from.froms.length !== 1) {
2221
2467
  throw new InternalError("Only one from table is supported for delete");
2222
2468
  }
@@ -2378,14 +2624,23 @@ var PolicyPlugin = class {
2378
2624
  get description() {
2379
2625
  return "Enforces access policies defined in the schema.";
2380
2626
  }
2381
- onKyselyQuery({ query, client, proceed, transaction }) {
2627
+ onKyselyQuery({
2628
+ query,
2629
+ client,
2630
+ proceed
2631
+ /*, transaction*/
2632
+ }) {
2382
2633
  const handler = new PolicyHandler(client);
2383
- return handler.handle(query, proceed, transaction);
2634
+ return handler.handle(
2635
+ query,
2636
+ proceed
2637
+ /*, transaction*/
2638
+ );
2384
2639
  }
2385
2640
  };
2386
2641
 
2387
2642
  // src/utils/clone.ts
2388
- import { isPlainObject as isPlainObject2 } from "is-plain-object";
2643
+ import { isPlainObject as isPlainObject2 } from "@zenstackhq/common-helpers";
2389
2644
  function clone(value) {
2390
2645
  if (Array.isArray(value)) {
2391
2646
  return value.map((v) => clone(v));
@@ -2404,28 +2659,6 @@ function clone(value) {
2404
2659
  }
2405
2660
  __name(clone, "clone");
2406
2661
 
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
2662
  // src/client/crud/operations/base.ts
2430
2663
  var BaseOperationHandler = class {
2431
2664
  static {
@@ -2469,17 +2702,17 @@ var BaseOperationHandler = class {
2469
2702
  getField(model, field) {
2470
2703
  return getField(this.schema, model, field);
2471
2704
  }
2472
- exists(kysely, model, filter) {
2705
+ async exists(kysely, model, filter) {
2473
2706
  const idFields = getIdFields(this.schema, model);
2474
2707
  const _filter = flattenCompoundUniqueFilters(this.schema, model, filter);
2475
2708
  const query = kysely.selectFrom(model).where((eb) => eb.and(_filter)).select(idFields.map((f) => kysely.dynamic.ref(f))).limit(1).modifyEnd(this.makeContextComment({
2476
2709
  model,
2477
2710
  operation: "read"
2478
2711
  }));
2479
- return query.executeTakeFirst();
2712
+ return this.executeQueryTakeFirst(kysely, query, "exists");
2480
2713
  }
2481
2714
  async read(kysely, model, args) {
2482
- let query = kysely.selectFrom(model);
2715
+ let query = this.dialect.buildSelectModel(expressionBuilder3(), model);
2483
2716
  if (args?.where) {
2484
2717
  query = query.where((eb) => this.dialect.buildFilter(eb, model, model, args?.where));
2485
2718
  }
@@ -2499,15 +2732,16 @@ var BaseOperationHandler = class {
2499
2732
  query = query.distinctOn(distinct.map((f) => sql4.ref(`${model}.${f}`)));
2500
2733
  } else {
2501
2734
  inMemoryDistinct = distinct;
2735
+ query = distinct.reduce((acc, field) => acc.select((eb) => this.dialect.fieldRef(model, field, eb).as(`$distinct$${field}`)), query);
2502
2736
  }
2503
2737
  }
2504
- if (args?.select) {
2505
- query = this.buildFieldSelection(model, query, args?.select, model);
2738
+ if (args && "select" in args && args.select) {
2739
+ query = this.buildFieldSelection(model, query, args.select, model);
2506
2740
  } else {
2507
- query = this.buildSelectAllScalarFields(model, query, args?.omit);
2741
+ query = this.dialect.buildSelectAllFields(model, query, args?.omit);
2508
2742
  }
2509
- if (args?.include) {
2510
- query = this.buildFieldSelection(model, query, args?.include, model);
2743
+ if (args && "include" in args && args.include) {
2744
+ query = this.buildFieldSelection(model, query, args.include, model);
2511
2745
  }
2512
2746
  if (args?.cursor) {
2513
2747
  query = this.buildCursorFilter(model, query, args.cursor, args.orderBy, negateOrderBy);
@@ -2517,23 +2751,35 @@ var BaseOperationHandler = class {
2517
2751
  operation: "read"
2518
2752
  }));
2519
2753
  let result = [];
2754
+ const queryId = {
2755
+ queryId: `zenstack-${createId()}`
2756
+ };
2757
+ const compiled = kysely.getExecutor().compileQuery(query.toOperationNode(), queryId);
2520
2758
  try {
2521
- result = await query.execute();
2759
+ const r = await kysely.getExecutor().executeQuery(compiled, queryId);
2760
+ result = r.rows;
2522
2761
  } catch (err) {
2523
- const { sql: sql10, parameters } = query.compile();
2524
- throw new QueryError(`Failed to execute query: ${err}, sql: ${sql10}, parameters: ${parameters}`);
2762
+ let message = `Failed to execute query: ${err}, sql: ${compiled.sql}`;
2763
+ if (this.options.debug) {
2764
+ message += `, parameters:
2765
+ ${compiled.parameters.map((p) => inspect(p)).join("\n")}`;
2766
+ }
2767
+ throw new QueryError(message, err);
2525
2768
  }
2526
2769
  if (inMemoryDistinct) {
2527
2770
  const distinctResult = [];
2528
2771
  const seen = /* @__PURE__ */ new Set();
2529
2772
  for (const r of result) {
2530
- const key = safeJSONStringify(inMemoryDistinct.map((f) => r[f]));
2773
+ const key = safeJSONStringify(inMemoryDistinct.map((f) => r[`$distinct$${f}`]));
2531
2774
  if (!seen.has(key)) {
2532
2775
  distinctResult.push(r);
2533
2776
  seen.add(key);
2534
2777
  }
2535
2778
  }
2536
2779
  result = distinctResult;
2780
+ for (const r of result) {
2781
+ Object.keys(r).filter((k) => k.startsWith("$distinct$")).forEach((k) => delete r[k]);
2782
+ }
2537
2783
  }
2538
2784
  return result;
2539
2785
  }
@@ -2556,72 +2802,29 @@ var BaseOperationHandler = class {
2556
2802
  }
2557
2803
  const fieldDef = this.requireField(model, field);
2558
2804
  if (!fieldDef.relation) {
2559
- result = this.selectField(result, model, parentAlias, field);
2805
+ result = this.dialect.buildSelectField(result, model, parentAlias, field);
2560
2806
  } else {
2561
2807
  if (!fieldDef.array && !fieldDef.optional && payload.where) {
2562
2808
  throw new QueryError(`Field "${field}" doesn't support filtering`);
2563
2809
  }
2564
- result = this.dialect.buildRelationSelection(result, model, field, parentAlias, payload);
2810
+ if (fieldDef.originModel) {
2811
+ result = this.dialect.buildRelationSelection(result, fieldDef.originModel, field, fieldDef.originModel, payload);
2812
+ } else {
2813
+ result = this.dialect.buildRelationSelection(result, model, field, parentAlias, payload);
2814
+ }
2565
2815
  }
2566
2816
  }
2567
2817
  return result;
2568
2818
  }
2569
2819
  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
- }
2820
+ return query.select((eb) => this.dialect.buildCountJson(model, eb, parentAlias, payload).as("_count"));
2618
2821
  }
2619
2822
  buildCursorFilter(model, query, cursor, orderBy, negateOrderBy) {
2620
2823
  if (!orderBy) {
2621
2824
  orderBy = makeDefaultOrderBy(this.schema, model);
2622
2825
  }
2623
2826
  const orderByItems = ensureArray(orderBy).flatMap((obj) => Object.entries(obj));
2624
- const eb = expressionBuilder2();
2827
+ const eb = expressionBuilder3();
2625
2828
  const cursorFilter = this.dialect.buildFilter(eb, model, model, cursor);
2626
2829
  let result = query;
2627
2830
  const filters = [];
@@ -2638,9 +2841,12 @@ var BaseOperationHandler = class {
2638
2841
  result = result.where((eb2) => eb2.or(filters));
2639
2842
  return result;
2640
2843
  }
2641
- async create(kysely, model, data, fromRelation) {
2844
+ async create(kysely, model, data, fromRelation, creatingForDelegate = false) {
2642
2845
  const modelDef = this.requireModel(model);
2643
- const createFields = {};
2846
+ if (modelDef.isDelegate && !creatingForDelegate) {
2847
+ throw new QueryError(`Model "${this.model}" is a delegate and cannot be created directly.`);
2848
+ }
2849
+ let createFields = {};
2644
2850
  let parentUpdateTask = void 0;
2645
2851
  let m2m = void 0;
2646
2852
  if (fromRelation) {
@@ -2659,7 +2865,7 @@ var BaseOperationHandler = class {
2659
2865
  model: fromRelation.model,
2660
2866
  operation: "update"
2661
2867
  }));
2662
- return query2.execute();
2868
+ return this.executeQuery(kysely, query2, "update");
2663
2869
  }, "parentUpdateTask");
2664
2870
  }
2665
2871
  }
@@ -2669,14 +2875,14 @@ var BaseOperationHandler = class {
2669
2875
  const fieldDef = this.requireField(model, field);
2670
2876
  if (isScalarField(this.schema, model, field) || isForeignKeyField(this.schema, model, field)) {
2671
2877
  if (fieldDef.array && value && typeof value === "object" && "set" in value && Array.isArray(value.set)) {
2672
- createFields[field] = this.dialect.transformPrimitive(value.set, fieldDef.type);
2878
+ createFields[field] = this.dialect.transformPrimitive(value.set, fieldDef.type, true);
2673
2879
  } else {
2674
- createFields[field] = this.dialect.transformPrimitive(value, fieldDef.type);
2880
+ createFields[field] = this.dialect.transformPrimitive(value, fieldDef.type, !!fieldDef.array);
2675
2881
  }
2676
2882
  } else {
2677
2883
  const subM2M = getManyToManyRelation(this.schema, model, field);
2678
2884
  if (!subM2M && fieldDef.relation?.fields && fieldDef.relation?.references) {
2679
- const fkValues = await this.processOwnedRelation(kysely, fieldDef, value);
2885
+ const fkValues = await this.processOwnedRelationForCreate(kysely, fieldDef, value);
2680
2886
  for (let i = 0; i < fieldDef.relation.fields.length; i++) {
2681
2887
  createFields[fieldDef.relation.fields[i]] = fkValues[fieldDef.relation.references[i]];
2682
2888
  }
@@ -2688,16 +2894,20 @@ var BaseOperationHandler = class {
2688
2894
  }
2689
2895
  }
2690
2896
  }
2897
+ if (modelDef.baseModel) {
2898
+ const baseCreateResult = await this.processBaseModelCreate(kysely, modelDef.baseModel, createFields, model);
2899
+ createFields = baseCreateResult.remainingFields;
2900
+ }
2691
2901
  const updatedData = this.fillGeneratedValues(modelDef, createFields);
2692
2902
  const idFields = getIdFields(this.schema, model);
2693
- const query = kysely.insertInto(model).values(updatedData).returning(idFields).modifyEnd(this.makeContextComment({
2903
+ 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
2904
  model,
2695
2905
  operation: "create"
2696
2906
  }));
2697
- const createdEntity = await query.executeTakeFirst();
2907
+ const createdEntity = await this.executeQueryTakeFirst(kysely, query, "create");
2698
2908
  if (Object.keys(postCreateRelations).length > 0) {
2699
2909
  const relationPromises = Object.entries(postCreateRelations).map(([field, subPayload]) => {
2700
- return this.processNoneOwnedRelation(kysely, model, field, subPayload, createdEntity);
2910
+ return this.processNoneOwnedRelationForCreate(kysely, model, field, subPayload, createdEntity);
2701
2911
  });
2702
2912
  await Promise.all(relationPromises);
2703
2913
  }
@@ -2709,6 +2919,28 @@ var BaseOperationHandler = class {
2709
2919
  }
2710
2920
  return createdEntity;
2711
2921
  }
2922
+ async processBaseModelCreate(kysely, model, createFields, forModel) {
2923
+ const thisCreateFields = {};
2924
+ const remainingFields = {};
2925
+ Object.entries(createFields).forEach(([field, value]) => {
2926
+ const fieldDef = this.getField(model, field);
2927
+ if (fieldDef) {
2928
+ thisCreateFields[field] = value;
2929
+ } else {
2930
+ remainingFields[field] = value;
2931
+ }
2932
+ });
2933
+ const discriminatorField = getDiscriminatorField(this.schema, model);
2934
+ invariant7(discriminatorField, `Base model "${model}" must have a discriminator field`);
2935
+ thisCreateFields[discriminatorField] = forModel;
2936
+ const baseEntity = await this.create(kysely, model, thisCreateFields, void 0, true);
2937
+ const idValues = extractIdFields(baseEntity, this.schema, model);
2938
+ Object.assign(remainingFields, idValues);
2939
+ return {
2940
+ baseEntity,
2941
+ remainingFields
2942
+ };
2943
+ }
2712
2944
  buildFkAssignments(model, relationField, entity) {
2713
2945
  const parentFkFields = {};
2714
2946
  invariant7(relationField, "parentField must be defined if parentModel is defined");
@@ -2751,7 +2983,7 @@ var BaseOperationHandler = class {
2751
2983
  ]).doNothing()).execute();
2752
2984
  return result[0];
2753
2985
  } else {
2754
- const eb = expressionBuilder2();
2986
+ const eb = expressionBuilder3();
2755
2987
  const result = await kysely.deleteFrom(joinTable).where(eb(`${joinTable}.A`, "=", sortedRecords[0].entity[firstIds[0]])).where(eb(`${joinTable}.B`, "=", sortedRecords[1].entity[secondIds[0]])).execute();
2756
2988
  return result[0];
2757
2989
  }
@@ -2761,10 +2993,10 @@ var BaseOperationHandler = class {
2761
2993
  const parentId = Object.values(parentIds)[0];
2762
2994
  const m2m = getManyToManyRelation(this.schema, model, field);
2763
2995
  invariant7(m2m, "not a many-to-many relation");
2764
- const eb = expressionBuilder2();
2996
+ const eb = expressionBuilder3();
2765
2997
  return kysely.deleteFrom(m2m.joinTable).where(eb(`${m2m.joinTable}.${m2m.parentFkName}`, "=", parentId)).execute();
2766
2998
  }
2767
- async processOwnedRelation(kysely, relationField, payload) {
2999
+ async processOwnedRelationForCreate(kysely, relationField, payload) {
2768
3000
  if (!payload) {
2769
3001
  return;
2770
3002
  }
@@ -2814,21 +3046,27 @@ var BaseOperationHandler = class {
2814
3046
  }
2815
3047
  return result;
2816
3048
  }
2817
- processNoneOwnedRelation(kysely, contextModel, relationFieldName, payload, parentEntity) {
3049
+ processNoneOwnedRelationForCreate(kysely, contextModel, relationFieldName, payload, parentEntity) {
2818
3050
  const relationFieldDef = this.requireField(contextModel, relationFieldName);
2819
3051
  const relationModel = relationFieldDef.type;
2820
3052
  const tasks = [];
3053
+ const fromRelationContext = {
3054
+ model: contextModel,
3055
+ field: relationFieldName,
3056
+ ids: parentEntity
3057
+ };
2821
3058
  for (const [action, subPayload] of Object.entries(payload)) {
2822
3059
  if (!subPayload) {
2823
3060
  continue;
2824
3061
  }
2825
3062
  switch (action) {
2826
3063
  case "create": {
2827
- tasks.push(...enumerate(subPayload).map((item) => this.create(kysely, relationModel, item, {
2828
- model: contextModel,
2829
- field: relationFieldName,
2830
- ids: parentEntity
2831
- })));
3064
+ tasks.push(...enumerate(subPayload).map((item) => this.create(kysely, relationModel, item, fromRelationContext)));
3065
+ break;
3066
+ }
3067
+ case "createMany": {
3068
+ invariant7(relationFieldDef.array, "relation must be an array for createMany");
3069
+ tasks.push(this.createMany(kysely, relationModel, subPayload, false, fromRelationContext));
2832
3070
  break;
2833
3071
  }
2834
3072
  case "connect": {
@@ -2858,6 +3096,11 @@ var BaseOperationHandler = class {
2858
3096
  return Promise.all(tasks);
2859
3097
  }
2860
3098
  async createMany(kysely, model, input, returnData, fromRelation) {
3099
+ if (!input.data || Array.isArray(input.data) && input.data.length === 0) {
3100
+ return returnData ? [] : {
3101
+ count: 0
3102
+ };
3103
+ }
2861
3104
  const modelDef = this.requireModel(model);
2862
3105
  let relationKeyPairs = [];
2863
3106
  if (fromRelation) {
@@ -2867,12 +3110,12 @@ var BaseOperationHandler = class {
2867
3110
  }
2868
3111
  relationKeyPairs = keyPairs;
2869
3112
  }
2870
- const createData = enumerate(input.data).map((item) => {
3113
+ let createData = enumerate(input.data).map((item) => {
2871
3114
  const newItem = {};
2872
3115
  for (const [name, value] of Object.entries(item)) {
2873
3116
  const fieldDef = this.requireField(model, name);
2874
3117
  invariant7(!fieldDef.relation, "createMany does not support relations");
2875
- newItem[name] = this.dialect.transformPrimitive(value, fieldDef.type);
3118
+ newItem[name] = this.dialect.transformPrimitive(value, fieldDef.type, !!fieldDef.array);
2876
3119
  }
2877
3120
  if (fromRelation) {
2878
3121
  for (const { fk, pk } of relationKeyPairs) {
@@ -2881,14 +3124,44 @@ var BaseOperationHandler = class {
2881
3124
  }
2882
3125
  return this.fillGeneratedValues(modelDef, newItem);
2883
3126
  });
3127
+ if (!this.dialect.supportInsertWithDefault) {
3128
+ const allPassedFields = createData.reduce((acc, item) => {
3129
+ Object.keys(item).forEach((field) => {
3130
+ if (!acc.includes(field)) {
3131
+ acc.push(field);
3132
+ }
3133
+ });
3134
+ return acc;
3135
+ }, []);
3136
+ for (const item of createData) {
3137
+ if (Object.keys(item).length === allPassedFields.length) {
3138
+ continue;
3139
+ }
3140
+ for (const field of allPassedFields) {
3141
+ if (!(field in item)) {
3142
+ const fieldDef = this.requireField(model, field);
3143
+ if (fieldDef.default !== void 0 && fieldDef.default !== null && typeof fieldDef.default !== "object") {
3144
+ item[field] = this.dialect.transformPrimitive(fieldDef.default, fieldDef.type, !!fieldDef.array);
3145
+ }
3146
+ }
3147
+ }
3148
+ }
3149
+ }
3150
+ if (modelDef.baseModel) {
3151
+ if (input.skipDuplicates) {
3152
+ throw new QueryError('"skipDuplicates" options is not supported for polymorphic models');
3153
+ }
3154
+ const baseCreateResult = await this.processBaseModelCreateMany(kysely, modelDef.baseModel, createData, !!input.skipDuplicates, model);
3155
+ createData = baseCreateResult.remainingFieldRows;
3156
+ }
2884
3157
  const query = kysely.insertInto(model).values(createData).$if(!!input.skipDuplicates, (qb) => qb.onConflict((oc) => oc.doNothing())).modifyEnd(this.makeContextComment({
2885
3158
  model,
2886
3159
  operation: "create"
2887
3160
  }));
2888
3161
  if (!returnData) {
2889
- const result = await query.executeTakeFirstOrThrow();
3162
+ const result = await this.executeQuery(kysely, query, "createMany");
2890
3163
  return {
2891
- count: Number(result.numInsertedOrUpdatedRows)
3164
+ count: Number(result.numAffectedRows)
2892
3165
  };
2893
3166
  } else {
2894
3167
  const idFields = getIdFields(this.schema, model);
@@ -2896,10 +3169,46 @@ var BaseOperationHandler = class {
2896
3169
  return result;
2897
3170
  }
2898
3171
  }
3172
+ async processBaseModelCreateMany(kysely, model, createRows, skipDuplicates, forModel) {
3173
+ const thisCreateRows = [];
3174
+ const remainingFieldRows = [];
3175
+ const discriminatorField = getDiscriminatorField(this.schema, model);
3176
+ invariant7(discriminatorField, `Base model "${model}" must have a discriminator field`);
3177
+ for (const createFields of createRows) {
3178
+ const thisCreateFields = {};
3179
+ const remainingFields = {};
3180
+ Object.entries(createFields).forEach(([field, value]) => {
3181
+ const fieldDef = this.getField(model, field);
3182
+ if (fieldDef) {
3183
+ thisCreateFields[field] = value;
3184
+ } else {
3185
+ remainingFields[field] = value;
3186
+ }
3187
+ });
3188
+ thisCreateFields[discriminatorField] = forModel;
3189
+ thisCreateRows.push(thisCreateFields);
3190
+ remainingFieldRows.push(remainingFields);
3191
+ }
3192
+ const baseEntities = await this.createMany(kysely, model, {
3193
+ data: thisCreateRows,
3194
+ skipDuplicates
3195
+ }, true);
3196
+ for (let i = 0; i < baseEntities.length; i++) {
3197
+ const idValues = extractIdFields(baseEntities[i], this.schema, model);
3198
+ Object.assign(remainingFieldRows[i], idValues);
3199
+ }
3200
+ return {
3201
+ baseEntities,
3202
+ remainingFieldRows
3203
+ };
3204
+ }
2899
3205
  fillGeneratedValues(modelDef, data) {
2900
3206
  const fields = modelDef.fields;
2901
3207
  const values = clone(data);
2902
- for (const field in fields) {
3208
+ for (const [field, fieldDef] of Object.entries(fields)) {
3209
+ if (fieldDef.originModel) {
3210
+ continue;
3211
+ }
2903
3212
  if (!(field in data)) {
2904
3213
  if (typeof fields[field]?.default === "object" && "kind" in fields[field].default) {
2905
3214
  const generated = this.evalGenerator(fields[field].default);
@@ -2907,7 +3216,7 @@ var BaseOperationHandler = class {
2907
3216
  values[field] = generated;
2908
3217
  }
2909
3218
  } else if (fields[field]?.updatedAt) {
2910
- values[field] = this.dialect.transformPrimitive(/* @__PURE__ */ new Date(), "DateTime");
3219
+ values[field] = this.dialect.transformPrimitive(/* @__PURE__ */ new Date(), "DateTime", false);
2911
3220
  }
2912
3221
  }
2913
3222
  }
@@ -2915,7 +3224,7 @@ var BaseOperationHandler = class {
2915
3224
  }
2916
3225
  evalGenerator(defaultValue) {
2917
3226
  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);
3227
+ 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
3228
  } else if (ExpressionUtils.isMember(defaultValue) && ExpressionUtils.isCall(defaultValue.receiver) && defaultValue.receiver.function === "auth") {
2920
3229
  let val = this.client.$auth;
2921
3230
  for (const member of defaultValue.members) {
@@ -2972,32 +3281,37 @@ var BaseOperationHandler = class {
2972
3281
  if (finalData === data) {
2973
3282
  finalData = clone(data);
2974
3283
  }
2975
- finalData[fieldName] = this.dialect.transformPrimitive(/* @__PURE__ */ new Date(), "DateTime");
3284
+ finalData[fieldName] = this.dialect.transformPrimitive(/* @__PURE__ */ new Date(), "DateTime", false);
2976
3285
  }
2977
3286
  }
2978
3287
  if (Object.keys(finalData).length === 0) {
2979
- const r = await this.readUnique(kysely, model, {
2980
- where: combinedWhere
3288
+ return combinedWhere;
3289
+ }
3290
+ let needIdRead = false;
3291
+ if (modelDef.baseModel && !this.isIdFilter(model, combinedWhere)) {
3292
+ needIdRead = true;
3293
+ }
3294
+ if (needIdRead) {
3295
+ const readResult = await this.readUnique(kysely, model, {
3296
+ where: combinedWhere,
3297
+ select: this.makeIdSelect(model)
2981
3298
  });
2982
- if (!r && throwIfNotFound) {
3299
+ if (!readResult && throwIfNotFound) {
2983
3300
  throw new NotFoundError(model);
2984
3301
  }
2985
- return r;
3302
+ combinedWhere = readResult;
3303
+ }
3304
+ if (modelDef.baseModel) {
3305
+ const baseUpdateResult = await this.processBaseModelUpdate(kysely, modelDef.baseModel, combinedWhere, finalData, throwIfNotFound);
3306
+ finalData = baseUpdateResult.remainingFields;
3307
+ combinedWhere = baseUpdateResult.baseEntity;
2986
3308
  }
2987
3309
  const updateFields = {};
2988
3310
  let thisEntity = void 0;
2989
3311
  for (const field in finalData) {
2990
3312
  const fieldDef = this.requireField(model, field);
2991
3313
  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);
3314
+ updateFields[field] = this.processScalarFieldUpdateData(model, field, finalData);
3001
3315
  } else {
3002
3316
  if (!allowRelationUpdate) {
3003
3317
  throw new QueryError(`Relation update not allowed for field "${field}"`);
@@ -3019,16 +3333,14 @@ var BaseOperationHandler = class {
3019
3333
  }
3020
3334
  }
3021
3335
  if (Object.keys(updateFields).length === 0) {
3022
- return thisEntity ?? await this.readUnique(kysely, model, {
3023
- where: combinedWhere
3024
- });
3336
+ return combinedWhere;
3025
3337
  } else {
3026
3338
  const idFields = getIdFields(this.schema, model);
3027
3339
  const query = kysely.updateTable(model).where((eb) => this.dialect.buildFilter(eb, model, model, combinedWhere)).set(updateFields).returning(idFields).modifyEnd(this.makeContextComment({
3028
3340
  model,
3029
3341
  operation: "update"
3030
3342
  }));
3031
- const updatedEntity = await query.executeTakeFirst();
3343
+ const updatedEntity = await this.executeQueryTakeFirst(kysely, query, "update");
3032
3344
  if (!updatedEntity) {
3033
3345
  if (throwIfNotFound) {
3034
3346
  throw new NotFoundError(model);
@@ -3039,23 +3351,72 @@ var BaseOperationHandler = class {
3039
3351
  return updatedEntity;
3040
3352
  }
3041
3353
  }
3354
+ processScalarFieldUpdateData(model, field, data) {
3355
+ const fieldDef = this.requireField(model, field);
3356
+ if (this.isNumericIncrementalUpdate(fieldDef, data[field])) {
3357
+ return this.transformIncrementalUpdate(model, field, fieldDef, data[field]);
3358
+ }
3359
+ if (fieldDef.array && typeof data[field] === "object" && !Array.isArray(data[field]) && data[field]) {
3360
+ return this.transformScalarListUpdate(model, field, fieldDef, data[field]);
3361
+ }
3362
+ return this.dialect.transformPrimitive(data[field], fieldDef.type, !!fieldDef.array);
3363
+ }
3364
+ isNumericIncrementalUpdate(fieldDef, value) {
3365
+ if (!this.isNumericField(fieldDef)) {
3366
+ return false;
3367
+ }
3368
+ if (typeof value !== "object" || !value) {
3369
+ return false;
3370
+ }
3371
+ return [
3372
+ "increment",
3373
+ "decrement",
3374
+ "multiply",
3375
+ "divide",
3376
+ "set"
3377
+ ].some((key) => key in value);
3378
+ }
3379
+ isIdFilter(model, filter) {
3380
+ if (!filter || typeof filter !== "object") {
3381
+ return false;
3382
+ }
3383
+ const idFields = getIdFields(this.schema, model);
3384
+ return idFields.length === Object.keys(filter).length && idFields.every((field) => field in filter);
3385
+ }
3386
+ async processBaseModelUpdate(kysely, model, where, updateFields, throwIfNotFound) {
3387
+ const thisUpdateFields = {};
3388
+ const remainingFields = {};
3389
+ Object.entries(updateFields).forEach(([field, value]) => {
3390
+ const fieldDef = this.getField(model, field);
3391
+ if (fieldDef) {
3392
+ thisUpdateFields[field] = value;
3393
+ } else {
3394
+ remainingFields[field] = value;
3395
+ }
3396
+ });
3397
+ const baseEntity = await this.update(kysely, model, where, thisUpdateFields, void 0, void 0, throwIfNotFound);
3398
+ return {
3399
+ baseEntity,
3400
+ remainingFields
3401
+ };
3402
+ }
3042
3403
  transformIncrementalUpdate(model, field, fieldDef, payload) {
3043
3404
  invariant7(Object.keys(payload).length === 1, 'Only one of "set", "increment", "decrement", "multiply", or "divide" can be provided');
3044
3405
  const key = Object.keys(payload)[0];
3045
- const value = this.dialect.transformPrimitive(payload[key], fieldDef.type);
3046
- const eb = expressionBuilder2();
3047
- 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(() => {
3406
+ const value = this.dialect.transformPrimitive(payload[key], fieldDef.type, false);
3407
+ const eb = expressionBuilder3();
3408
+ const fieldRef = this.dialect.fieldRef(model, field, eb);
3409
+ 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
3410
  throw new InternalError(`Invalid incremental update operation: ${key}`);
3050
3411
  });
3051
3412
  }
3052
3413
  transformScalarListUpdate(model, field, fieldDef, payload) {
3053
3414
  invariant7(Object.keys(payload).length === 1, 'Only one of "set", "push" can be provided');
3054
3415
  const key = Object.keys(payload)[0];
3055
- const value = this.dialect.transformPrimitive(payload[key], fieldDef.type);
3056
- const eb = expressionBuilder2();
3057
- const fieldRef = buildFieldRef(this.schema, model, field, this.options, eb);
3058
- return match8(key).with("set", () => value).with("push", () => {
3416
+ const value = this.dialect.transformPrimitive(payload[key], fieldDef.type, true);
3417
+ const eb = expressionBuilder3();
3418
+ const fieldRef = this.dialect.fieldRef(model, field, eb);
3419
+ return match9(key).with("set", () => value).with("push", () => {
3059
3420
  return eb(fieldRef, "||", eb.val(ensureArray(value)));
3060
3421
  }).otherwise(() => {
3061
3422
  throw new InternalError(`Invalid array update operation: ${key}`);
@@ -3067,7 +3428,7 @@ var BaseOperationHandler = class {
3067
3428
  makeContextComment(context) {
3068
3429
  return sql4.raw(`${CONTEXT_COMMENT_PREFIX}${JSON.stringify(context)}`);
3069
3430
  }
3070
- async updateMany(kysely, model, where, data, limit, returnData) {
3431
+ async updateMany(kysely, model, where, data, limit, returnData, filterModel) {
3071
3432
  if (typeof data !== "object") {
3072
3433
  throw new InternalError("data must be an object");
3073
3434
  }
@@ -3076,49 +3437,79 @@ var BaseOperationHandler = class {
3076
3437
  count: 0
3077
3438
  };
3078
3439
  }
3079
- const updateFields = {};
3440
+ const modelDef = this.requireModel(model);
3441
+ if (modelDef.baseModel && limit !== void 0) {
3442
+ throw new QueryError("Updating with a limit is not supported for polymorphic models");
3443
+ }
3444
+ filterModel ??= model;
3445
+ let updateFields = {};
3080
3446
  for (const field in data) {
3081
- const fieldDef = this.requireField(model, field);
3082
3447
  if (isRelationField(this.schema, model, field)) {
3083
3448
  continue;
3084
3449
  }
3085
- updateFields[field] = this.dialect.transformPrimitive(data[field], fieldDef.type);
3450
+ updateFields[field] = this.processScalarFieldUpdateData(model, field, data);
3451
+ }
3452
+ let shouldFallbackToIdFilter = false;
3453
+ if (limit !== void 0 && !this.dialect.supportsUpdateWithLimit) {
3454
+ shouldFallbackToIdFilter = true;
3455
+ }
3456
+ if (modelDef.isDelegate || modelDef.baseModel) {
3457
+ shouldFallbackToIdFilter = true;
3458
+ }
3459
+ let resultFromBaseModel = void 0;
3460
+ if (modelDef.baseModel) {
3461
+ const baseResult = await this.processBaseModelUpdateMany(kysely, modelDef.baseModel, where, updateFields, filterModel);
3462
+ updateFields = baseResult.remainingFields;
3463
+ resultFromBaseModel = baseResult.baseResult;
3464
+ }
3465
+ if (Object.keys(updateFields).length === 0) {
3466
+ return resultFromBaseModel ?? (returnData ? [] : {
3467
+ count: 0
3468
+ });
3086
3469
  }
3087
3470
  let query = kysely.updateTable(model).set(updateFields);
3088
- if (limit === void 0) {
3089
- query = query.where((eb) => this.dialect.buildFilter(eb, model, model, where));
3471
+ if (!shouldFallbackToIdFilter) {
3472
+ query = query.where((eb) => this.dialect.buildFilter(eb, model, model, where)).$if(limit !== void 0, (qb) => qb.limit(limit));
3090
3473
  } 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
- }
3474
+ query = query.where((eb) => eb(eb.refTuple(
3475
+ ...this.buildIdFieldRefs(kysely, model)
3476
+ ), "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
3477
  }
3099
3478
  query = query.modifyEnd(this.makeContextComment({
3100
3479
  model,
3101
3480
  operation: "update"
3102
3481
  }));
3103
- try {
3104
- if (!returnData) {
3105
- const result = await query.executeTakeFirstOrThrow();
3106
- return {
3107
- count: Number(result.numUpdatedRows)
3108
- };
3482
+ if (!returnData) {
3483
+ const result = await this.executeQuery(kysely, query, "update");
3484
+ return {
3485
+ count: Number(result.numAffectedRows)
3486
+ };
3487
+ } else {
3488
+ const idFields = getIdFields(this.schema, model);
3489
+ const result = await query.returning(idFields).execute();
3490
+ return result;
3491
+ }
3492
+ }
3493
+ async processBaseModelUpdateMany(kysely, model, where, updateFields, filterModel) {
3494
+ const thisUpdateFields = {};
3495
+ const remainingFields = {};
3496
+ Object.entries(updateFields).forEach(([field, value]) => {
3497
+ const fieldDef = this.getField(model, field);
3498
+ if (fieldDef) {
3499
+ thisUpdateFields[field] = value;
3109
3500
  } else {
3110
- const idFields = getIdFields(this.schema, model);
3111
- const result = await query.returning(idFields).execute();
3112
- return result;
3501
+ remainingFields[field] = value;
3113
3502
  }
3114
- } catch (err) {
3115
- const { sql: sql10, parameters } = query.compile();
3116
- throw new QueryError(`Error during updateMany: ${err}, sql: ${sql10}, parameters: ${parameters}`);
3117
- }
3503
+ });
3504
+ const baseResult = await this.updateMany(kysely, model, where, thisUpdateFields, void 0, false, filterModel);
3505
+ return {
3506
+ baseResult,
3507
+ remainingFields
3508
+ };
3118
3509
  }
3119
3510
  buildIdFieldRefs(kysely, model) {
3120
3511
  const idFields = getIdFields(this.schema, model);
3121
- return idFields.map((f) => kysely.dynamic.ref(f));
3512
+ return idFields.map((f) => kysely.dynamic.ref(`${model}.${f}`));
3122
3513
  }
3123
3514
  async processRelationUpdates(kysely, model, field, fieldDef, parentIds, args, throwIfNotFound) {
3124
3515
  const tasks = [];
@@ -3236,7 +3627,7 @@ var BaseOperationHandler = class {
3236
3627
  model: fromRelation.model,
3237
3628
  operation: "update"
3238
3629
  }));
3239
- updateResult = await query.executeTakeFirstOrThrow();
3630
+ updateResult = await this.executeQuery(kysely, query, "connect");
3240
3631
  } else {
3241
3632
  const relationFieldDef = this.requireField(fromRelation.model, fromRelation.field);
3242
3633
  if (!relationFieldDef.array) {
@@ -3247,7 +3638,7 @@ var BaseOperationHandler = class {
3247
3638
  model: fromRelation.model,
3248
3639
  operation: "update"
3249
3640
  }));
3250
- await query2.execute();
3641
+ await this.executeQuery(kysely, query2, "disconnect");
3251
3642
  }
3252
3643
  const query = kysely.updateTable(model).where((eb) => eb.or(_data.map((d) => eb.and(d)))).set(keyPairs.reduce((acc, { fk, pk }) => ({
3253
3644
  ...acc,
@@ -3256,9 +3647,9 @@ var BaseOperationHandler = class {
3256
3647
  model,
3257
3648
  operation: "update"
3258
3649
  }));
3259
- updateResult = await query.executeTakeFirstOrThrow();
3650
+ updateResult = await this.executeQuery(kysely, query, "connect");
3260
3651
  }
3261
- if (_data.length > updateResult.numUpdatedRows) {
3652
+ if (_data.length > updateResult.numAffectedRows) {
3262
3653
  throw new NotFoundError(model);
3263
3654
  }
3264
3655
  }
@@ -3310,7 +3701,7 @@ var BaseOperationHandler = class {
3310
3701
  await Promise.all(actions);
3311
3702
  } else {
3312
3703
  const { ownedByModel, keyPairs } = getRelationForeignKeyFieldPairs(this.schema, fromRelation.model, fromRelation.field);
3313
- const eb = expressionBuilder2();
3704
+ const eb = expressionBuilder3();
3314
3705
  if (ownedByModel) {
3315
3706
  invariant7(disconnectConditions.length === 1, "only one entity can be disconnected");
3316
3707
  const condition = disconnectConditions[0];
@@ -3326,7 +3717,7 @@ var BaseOperationHandler = class {
3326
3717
  model: fromRelation.model,
3327
3718
  operation: "update"
3328
3719
  }));
3329
- await query.executeTakeFirstOrThrow();
3720
+ await this.executeQuery(kysely, query, "disconnect");
3330
3721
  } else {
3331
3722
  const query = kysely.updateTable(model).where(eb.and([
3332
3723
  // fk filter
@@ -3343,7 +3734,7 @@ var BaseOperationHandler = class {
3343
3734
  model,
3344
3735
  operation: "update"
3345
3736
  }));
3346
- await query.executeTakeFirstOrThrow();
3737
+ await this.executeQuery(kysely, query, "disconnect");
3347
3738
  }
3348
3739
  }
3349
3740
  }
@@ -3381,7 +3772,7 @@ var BaseOperationHandler = class {
3381
3772
  model,
3382
3773
  operation: "update"
3383
3774
  }));
3384
- await query.execute();
3775
+ await this.executeQuery(kysely, query, "disconnect");
3385
3776
  if (_data.length > 0) {
3386
3777
  const query2 = kysely.updateTable(model).where((eb) => eb.or(_data.map((d) => eb.and(d)))).set(keyPairs.reduce((acc, { fk, pk }) => ({
3387
3778
  ...acc,
@@ -3390,8 +3781,8 @@ var BaseOperationHandler = class {
3390
3781
  model,
3391
3782
  operation: "update"
3392
3783
  }));
3393
- const r = await query2.executeTakeFirstOrThrow();
3394
- if (_data.length > r.numUpdatedRows) {
3784
+ const r = await this.executeQuery(kysely, query2, "connect");
3785
+ if (_data.length > r.numAffectedRows) {
3395
3786
  throw new NotFoundError(model);
3396
3787
  }
3397
3788
  }
@@ -3432,7 +3823,7 @@ var BaseOperationHandler = class {
3432
3823
  OR: deleteConditions
3433
3824
  }
3434
3825
  ]
3435
- }, void 0, false);
3826
+ });
3436
3827
  } else {
3437
3828
  const { ownedByModel, keyPairs } = getRelationForeignKeyFieldPairs(this.schema, fromRelation.model, fromRelation.field);
3438
3829
  if (ownedByModel) {
@@ -3455,7 +3846,7 @@ var BaseOperationHandler = class {
3455
3846
  OR: deleteConditions
3456
3847
  }
3457
3848
  ]
3458
- }, void 0, false);
3849
+ });
3459
3850
  } else {
3460
3851
  deleteResult = await this.delete(kysely, model, {
3461
3852
  AND: [
@@ -3467,7 +3858,7 @@ var BaseOperationHandler = class {
3467
3858
  OR: deleteConditions
3468
3859
  }
3469
3860
  ]
3470
- }, void 0, false);
3861
+ });
3471
3862
  }
3472
3863
  }
3473
3864
  if (throwForNotFound && expectedDeleteCount > deleteResult.count) {
@@ -3478,33 +3869,59 @@ var BaseOperationHandler = class {
3478
3869
  return enumerate(data).map((item) => flattenCompoundUniqueFilters(this.schema, model, item));
3479
3870
  }
3480
3871
  // #endregion
3481
- async delete(kysely, model, where, limit, returnData) {
3872
+ async delete(kysely, model, where, limit, filterModel) {
3873
+ filterModel ??= model;
3874
+ const modelDef = this.requireModel(model);
3875
+ if (modelDef.baseModel) {
3876
+ if (limit !== void 0) {
3877
+ throw new QueryError("Deleting with a limit is not supported for polymorphic models");
3878
+ }
3879
+ return this.processBaseModelDelete(kysely, modelDef.baseModel, where, limit, filterModel);
3880
+ }
3482
3881
  let query = kysely.deleteFrom(model);
3483
- if (limit === void 0) {
3882
+ let needIdFilter = false;
3883
+ if (limit !== void 0 && !this.dialect.supportsDeleteWithLimit) {
3884
+ needIdFilter = true;
3885
+ }
3886
+ if (modelDef.isDelegate || modelDef.baseModel) {
3887
+ needIdFilter = true;
3888
+ }
3889
+ if (!needIdFilter) {
3484
3890
  query = query.where((eb) => this.dialect.buildFilter(eb, model, model, where));
3485
3891
  } 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
- }
3892
+ query = query.where((eb) => eb(eb.refTuple(
3893
+ ...this.buildIdFieldRefs(kysely, model)
3894
+ ), "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
3895
  }
3896
+ await this.processDelegateRelationDelete(kysely, modelDef, where, limit);
3494
3897
  query = query.modifyEnd(this.makeContextComment({
3495
3898
  model,
3496
3899
  operation: "delete"
3497
3900
  }));
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
- };
3901
+ const result = await this.executeQuery(kysely, query, "delete");
3902
+ return {
3903
+ count: Number(result.numAffectedRows)
3904
+ };
3905
+ }
3906
+ async processDelegateRelationDelete(kysely, modelDef, where, limit) {
3907
+ for (const fieldDef of Object.values(modelDef.fields)) {
3908
+ if (fieldDef.relation && fieldDef.relation.opposite) {
3909
+ const oppositeModelDef = this.requireModel(fieldDef.type);
3910
+ const oppositeRelation = this.requireField(fieldDef.type, fieldDef.relation.opposite);
3911
+ if (oppositeModelDef.baseModel && oppositeRelation.relation?.onDelete === "Cascade") {
3912
+ if (limit !== void 0) {
3913
+ throw new QueryError("Deleting with a limit is not supported for polymorphic models");
3914
+ }
3915
+ await this.delete(kysely, fieldDef.type, {
3916
+ [fieldDef.relation.opposite]: where
3917
+ }, void 0);
3918
+ }
3919
+ }
3506
3920
  }
3507
3921
  }
3922
+ async processBaseModelDelete(kysely, model, where, limit, filterModel) {
3923
+ return this.delete(kysely, model, where, limit, filterModel);
3924
+ }
3508
3925
  makeIdSelect(model) {
3509
3926
  const modelDef = this.requireModel(model);
3510
3927
  return modelDef.idFields.reduce((acc, f) => {
@@ -3513,7 +3930,7 @@ var BaseOperationHandler = class {
3513
3930
  }, {});
3514
3931
  }
3515
3932
  trimResult(data, args) {
3516
- if (!args.select) {
3933
+ if (!("select" in args) || !args.select) {
3517
3934
  return data;
3518
3935
  }
3519
3936
  return Object.keys(args.select).reduce((acc, field) => {
@@ -3523,9 +3940,9 @@ var BaseOperationHandler = class {
3523
3940
  }
3524
3941
  needReturnRelations(model, args) {
3525
3942
  let returnRelation = false;
3526
- if (args.include) {
3943
+ if ("include" in args && args.include) {
3527
3944
  returnRelation = Object.keys(args.include).length > 0;
3528
- } else if (args.select) {
3945
+ } else if ("select" in args && args.select) {
3529
3946
  returnRelation = Object.entries(args.select).some(([K, v]) => {
3530
3947
  const fieldDef = this.requireField(model, K);
3531
3948
  return fieldDef.relation && v;
@@ -3533,11 +3950,13 @@ var BaseOperationHandler = class {
3533
3950
  }
3534
3951
  return returnRelation;
3535
3952
  }
3536
- async safeTransaction(callback) {
3953
+ async safeTransaction(callback, isolationLevel) {
3537
3954
  if (this.kysely.isTransaction) {
3538
3955
  return callback(this.kysely);
3539
3956
  } else {
3540
- return this.kysely.transaction().setIsolationLevel("repeatable read").execute(callback);
3957
+ let txBuilder = this.kysely.transaction();
3958
+ txBuilder = txBuilder.setIsolationLevel(isolationLevel ?? "repeatable read");
3959
+ return txBuilder.execute(callback);
3541
3960
  }
3542
3961
  }
3543
3962
  // Given a unique filter of a model, return the entity ids by trying to
@@ -3556,6 +3975,47 @@ var BaseOperationHandler = class {
3556
3975
  where: uniqueFilter
3557
3976
  });
3558
3977
  }
3978
+ /**
3979
+ * Normalize input args to strip `undefined` fields
3980
+ */
3981
+ normalizeArgs(args) {
3982
+ if (!args) {
3983
+ return;
3984
+ }
3985
+ const newArgs = clone(args);
3986
+ this.doNormalizeArgs(newArgs);
3987
+ return newArgs;
3988
+ }
3989
+ doNormalizeArgs(args) {
3990
+ if (args && typeof args === "object") {
3991
+ for (const [key, value] of Object.entries(args)) {
3992
+ if (value === void 0) {
3993
+ delete args[key];
3994
+ } else if (value && isPlainObject3(value)) {
3995
+ this.doNormalizeArgs(value);
3996
+ }
3997
+ }
3998
+ }
3999
+ }
4000
+ makeQueryId(operation) {
4001
+ return {
4002
+ queryId: `${operation}-${createId()}`
4003
+ };
4004
+ }
4005
+ executeQuery(kysely, query, operation) {
4006
+ return kysely.executeQuery(query.compile(), this.makeQueryId(operation));
4007
+ }
4008
+ async executeQueryTakeFirst(kysely, query, operation) {
4009
+ const result = await kysely.executeQuery(query.compile(), this.makeQueryId(operation));
4010
+ return result.rows[0];
4011
+ }
4012
+ async executeQueryTakeFirstOrThrow(kysely, query, operation) {
4013
+ const result = await kysely.executeQuery(query.compile(), this.makeQueryId(operation));
4014
+ if (result.rows.length === 0) {
4015
+ throw new QueryError("No rows found");
4016
+ }
4017
+ return result.rows[0];
4018
+ }
3559
4019
  };
3560
4020
 
3561
4021
  // src/client/crud/operations/aggregate.ts
@@ -3564,21 +4024,37 @@ var AggregateOperationHandler = class extends BaseOperationHandler {
3564
4024
  __name(this, "AggregateOperationHandler");
3565
4025
  }
3566
4026
  async handle(_operation, args) {
3567
- const validatedArgs = this.inputValidator.validateAggregateArgs(this.model, args);
4027
+ const normalizedArgs = this.normalizeArgs(args);
4028
+ const parsedArgs = this.inputValidator.validateAggregateArgs(this.model, normalizedArgs);
3568
4029
  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;
4030
+ let subQuery = this.dialect.buildSelectModel(eb, this.model).where((eb1) => this.dialect.buildFilter(eb1, this.model, this.model, parsedArgs?.where));
4031
+ const selectedFields = [];
4032
+ for (const [key, value] of Object.entries(parsedArgs)) {
4033
+ if (key.startsWith("_") && value && typeof value === "object") {
4034
+ Object.entries(value).filter(([field]) => field !== "_all").filter(([, val]) => val === true).forEach(([field]) => {
4035
+ if (!selectedFields.includes(field)) selectedFields.push(field);
4036
+ });
4037
+ }
4038
+ }
4039
+ if (selectedFields.length > 0) {
4040
+ for (const field of selectedFields) {
4041
+ subQuery = this.dialect.buildSelectField(subQuery, this.model, this.model, field);
4042
+ }
4043
+ } else {
4044
+ subQuery = subQuery.select(() => eb.lit(1).as("_all"));
4045
+ }
4046
+ const skip = parsedArgs?.skip;
4047
+ let take = parsedArgs?.take;
3572
4048
  let negateOrderBy = false;
3573
4049
  if (take !== void 0 && take < 0) {
3574
4050
  negateOrderBy = true;
3575
4051
  take = -take;
3576
4052
  }
3577
4053
  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);
4054
+ subQuery = this.dialect.buildOrderBy(subQuery, this.model, this.model, parsedArgs.orderBy, skip !== void 0 || take !== void 0, negateOrderBy);
3579
4055
  return subQuery.as("$sub");
3580
4056
  });
3581
- for (const [key, value] of Object.entries(validatedArgs)) {
4057
+ for (const [key, value] of Object.entries(parsedArgs)) {
3582
4058
  switch (key) {
3583
4059
  case "_count": {
3584
4060
  if (value === true) {
@@ -3603,7 +4079,7 @@ var AggregateOperationHandler = class extends BaseOperationHandler {
3603
4079
  Object.entries(value).forEach(([field, val]) => {
3604
4080
  if (val === true) {
3605
4081
  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();
4082
+ 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
4083
  return fn(sql5.ref(`$sub.${field}`)).as(`${key}.${field}`);
3608
4084
  });
3609
4085
  }
@@ -3612,9 +4088,9 @@ var AggregateOperationHandler = class extends BaseOperationHandler {
3612
4088
  }
3613
4089
  }
3614
4090
  }
3615
- const result = await query.executeTakeFirstOrThrow();
4091
+ const result = await this.executeQuery(this.kysely, query, "aggregate");
3616
4092
  const ret = {};
3617
- for (const [key, value] of Object.entries(result)) {
4093
+ for (const [key, value] of Object.entries(result.rows[0])) {
3618
4094
  if (key === "_count") {
3619
4095
  ret[key] = value;
3620
4096
  continue;
@@ -3636,7 +4112,7 @@ var AggregateOperationHandler = class extends BaseOperationHandler {
3636
4112
  val = parseFloat(val);
3637
4113
  } else {
3638
4114
  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);
4115
+ val = match10(type).with("Int", () => parseInt(value, 10)).with("BigInt", () => BigInt(value)).with("Float", () => parseFloat(value)).with("Decimal", () => parseFloat(value)).otherwise(() => value);
3640
4116
  }
3641
4117
  }
3642
4118
  }
@@ -3657,34 +4133,47 @@ var CountOperationHandler = class extends BaseOperationHandler {
3657
4133
  __name(this, "CountOperationHandler");
3658
4134
  }
3659
4135
  async handle(_operation, args) {
3660
- const validatedArgs = this.inputValidator.validateCountArgs(this.model, args);
4136
+ const normalizedArgs = this.normalizeArgs(args);
4137
+ const parsedArgs = this.inputValidator.validateCountArgs(this.model, normalizedArgs);
4138
+ const subQueryName = "$sub";
3661
4139
  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");
4140
+ let subQuery = this.dialect.buildSelectModel(eb, this.model).where((eb1) => this.dialect.buildFilter(eb1, this.model, this.model, parsedArgs?.where));
4141
+ if (parsedArgs?.select && typeof parsedArgs.select === "object") {
4142
+ for (const [key, value] of Object.entries(parsedArgs.select)) {
4143
+ if (key !== "_all" && value === true) {
4144
+ subQuery = this.dialect.buildSelectField(subQuery, this.model, this.model, key);
4145
+ }
4146
+ }
4147
+ } else {
4148
+ subQuery = subQuery.select(() => eb.lit(1).as("_all"));
4149
+ }
4150
+ subQuery = this.dialect.buildSkipTake(subQuery, parsedArgs?.skip, parsedArgs?.take);
4151
+ return subQuery.as(subQueryName);
3665
4152
  });
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();
4153
+ if (parsedArgs?.select && typeof parsedArgs.select === "object") {
4154
+ 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)));
4155
+ const result = await this.executeQuery(this.kysely, query, "count");
4156
+ return result.rows[0];
3669
4157
  } else {
3670
4158
  query = query.select((eb) => eb.cast(eb.fn.countAll(), "integer").as("count"));
3671
- const result = await query.executeTakeFirstOrThrow();
3672
- return result.count;
4159
+ const result = await this.executeQuery(this.kysely, query, "count");
4160
+ return result.rows[0].count;
3673
4161
  }
3674
4162
  }
3675
4163
  };
3676
4164
 
3677
4165
  // src/client/crud/operations/create.ts
3678
- import { match as match10 } from "ts-pattern";
4166
+ import { match as match11 } from "ts-pattern";
3679
4167
  var CreateOperationHandler = class extends BaseOperationHandler {
3680
4168
  static {
3681
4169
  __name(this, "CreateOperationHandler");
3682
4170
  }
3683
4171
  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));
4172
+ const normalizedArgs = this.normalizeArgs(args);
4173
+ return match11(operation).with("create", () => this.runCreate(this.inputValidator.validateCreateArgs(this.model, normalizedArgs))).with("createMany", () => {
4174
+ return this.runCreateMany(this.inputValidator.validateCreateManyArgs(this.model, normalizedArgs));
3686
4175
  }).with("createManyAndReturn", () => {
3687
- return this.runCreateManyAndReturn(this.inputValidator.validateCreateManyAndReturnArgs(this.model, args));
4176
+ return this.runCreateManyAndReturn(this.inputValidator.validateCreateManyAndReturnArgs(this.model, normalizedArgs));
3688
4177
  }).exhaustive();
3689
4178
  }
3690
4179
  async runCreate(args) {
@@ -3728,13 +4217,14 @@ var CreateOperationHandler = class extends BaseOperationHandler {
3728
4217
  };
3729
4218
 
3730
4219
  // src/client/crud/operations/delete.ts
3731
- import { match as match11 } from "ts-pattern";
4220
+ import { match as match12 } from "ts-pattern";
3732
4221
  var DeleteOperationHandler = class extends BaseOperationHandler {
3733
4222
  static {
3734
4223
  __name(this, "DeleteOperationHandler");
3735
4224
  }
3736
4225
  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();
4226
+ const normalizedArgs = this.normalizeArgs(args);
4227
+ 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
4228
  }
3739
4229
  async runDelete(args) {
3740
4230
  const existing = await this.readUnique(this.kysely, this.model, {
@@ -3746,15 +4236,19 @@ var DeleteOperationHandler = class extends BaseOperationHandler {
3746
4236
  if (!existing) {
3747
4237
  throw new NotFoundError(this.model);
3748
4238
  }
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
- }
4239
+ await this.safeTransaction(async (tx) => {
4240
+ const result = await this.delete(tx, this.model, args.where);
4241
+ if (result.count === 0) {
4242
+ throw new NotFoundError(this.model);
4243
+ }
4244
+ });
3753
4245
  return existing;
3754
4246
  }
3755
4247
  async runDeleteMany(args) {
3756
- const result = await this.delete(this.kysely, this.model, args?.where, args?.limit, false);
3757
- return result;
4248
+ return await this.safeTransaction(async (tx) => {
4249
+ const result = await this.delete(tx, this.model, args?.where, args?.limit);
4250
+ return result;
4251
+ });
3758
4252
  }
3759
4253
  };
3760
4254
 
@@ -3764,7 +4258,8 @@ var FindOperationHandler = class extends BaseOperationHandler {
3764
4258
  __name(this, "FindOperationHandler");
3765
4259
  }
3766
4260
  async handle(operation, args, validateArgs = true) {
3767
- const parsedArgs = validateArgs ? this.inputValidator.validateFindArgs(this.model, operation === "findUnique", args) : args;
4261
+ const normalizedArgs = this.normalizeArgs(args);
4262
+ const parsedArgs = validateArgs ? this.inputValidator.validateFindArgs(this.model, operation === "findUnique", normalizedArgs) : normalizedArgs;
3768
4263
  const result = await this.read(this.client.$qb, this.model, parsedArgs);
3769
4264
  const finalResult = operation === "findMany" ? result : result[0] ?? null;
3770
4265
  return finalResult;
@@ -3772,18 +4267,19 @@ var FindOperationHandler = class extends BaseOperationHandler {
3772
4267
  };
3773
4268
 
3774
4269
  // src/client/crud/operations/group-by.ts
3775
- import { sql as sql7 } from "kysely";
3776
- import { match as match12 } from "ts-pattern";
3777
- var GroupByeOperationHandler = class extends BaseOperationHandler {
4270
+ import { expressionBuilder as expressionBuilder4 } from "kysely";
4271
+ import { match as match13 } from "ts-pattern";
4272
+ var GroupByOperationHandler = class extends BaseOperationHandler {
3778
4273
  static {
3779
- __name(this, "GroupByeOperationHandler");
4274
+ __name(this, "GroupByOperationHandler");
3780
4275
  }
3781
4276
  async handle(_operation, args) {
3782
- const validatedArgs = this.inputValidator.validateGroupByArgs(this.model, args);
4277
+ const normalizedArgs = this.normalizeArgs(args);
4278
+ const parsedArgs = this.inputValidator.validateGroupByArgs(this.model, normalizedArgs);
3783
4279
  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;
4280
+ let subQuery = eb.selectFrom(this.model).selectAll().where((eb1) => this.dialect.buildFilter(eb1, this.model, this.model, parsedArgs?.where));
4281
+ const skip = parsedArgs?.skip;
4282
+ let take = parsedArgs?.take;
3787
4283
  let negateOrderBy = false;
3788
4284
  if (take !== void 0 && take < 0) {
3789
4285
  negateOrderBy = true;
@@ -3793,20 +4289,21 @@ var GroupByeOperationHandler = class extends BaseOperationHandler {
3793
4289
  subQuery = this.dialect.buildOrderBy(subQuery, this.model, this.model, void 0, skip !== void 0 || take !== void 0, negateOrderBy);
3794
4290
  return subQuery.as("$sub");
3795
4291
  });
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);
4292
+ const fieldRef = /* @__PURE__ */ __name((field) => this.dialect.fieldRef(this.model, field, expressionBuilder4(), "$sub"), "fieldRef");
4293
+ const bys = typeof parsedArgs.by === "string" ? [
4294
+ parsedArgs.by
4295
+ ] : parsedArgs.by;
4296
+ query = query.groupBy(bys.map((by) => fieldRef(by)));
4297
+ if (parsedArgs.orderBy) {
4298
+ query = this.dialect.buildOrderBy(query, this.model, "$sub", parsedArgs.orderBy, false, false);
3802
4299
  }
3803
- if (validatedArgs.having) {
3804
- query = query.having((eb1) => this.dialect.buildFilter(eb1, this.model, "$sub", validatedArgs.having));
4300
+ if (parsedArgs.having) {
4301
+ query = query.having((eb) => this.dialect.buildFilter(eb, this.model, "$sub", parsedArgs.having));
3805
4302
  }
3806
4303
  for (const by of bys) {
3807
- query = query.select(() => sql7.ref(`$sub.${by}`).as(by));
4304
+ query = query.select(() => fieldRef(by).as(by));
3808
4305
  }
3809
- for (const [key, value] of Object.entries(validatedArgs)) {
4306
+ for (const [key, value] of Object.entries(parsedArgs)) {
3810
4307
  switch (key) {
3811
4308
  case "_count": {
3812
4309
  if (value === true) {
@@ -3817,7 +4314,7 @@ var GroupByeOperationHandler = class extends BaseOperationHandler {
3817
4314
  if (field === "_all") {
3818
4315
  query = query.select((eb) => eb.cast(eb.fn.countAll(), "integer").as(`_count._all`));
3819
4316
  } else {
3820
- query = query.select((eb) => eb.cast(eb.fn.count(sql7.ref(`$sub.${field}`)), "integer").as(`${key}.${field}`));
4317
+ query = query.select((eb) => eb.cast(eb.fn.count(fieldRef(field)), "integer").as(`${key}.${field}`));
3821
4318
  }
3822
4319
  }
3823
4320
  });
@@ -3830,18 +4327,15 @@ var GroupByeOperationHandler = class extends BaseOperationHandler {
3830
4327
  case "_min": {
3831
4328
  Object.entries(value).forEach(([field, val]) => {
3832
4329
  if (val === true) {
3833
- 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();
3835
- return fn(sql7.ref(`$sub.${field}`)).as(`${key}.${field}`);
3836
- });
4330
+ query = query.select((eb) => aggregate(eb, fieldRef(field), key).as(`${key}.${field}`));
3837
4331
  }
3838
4332
  });
3839
4333
  break;
3840
4334
  }
3841
4335
  }
3842
4336
  }
3843
- const result = await query.execute();
3844
- return result.map((row) => this.postProcessRow(row));
4337
+ const result = await this.executeQuery(this.kysely, query, "groupBy");
4338
+ return result.rows.map((row) => this.postProcessRow(row));
3845
4339
  }
3846
4340
  postProcessRow(row) {
3847
4341
  const ret = {};
@@ -3868,7 +4362,7 @@ var GroupByeOperationHandler = class extends BaseOperationHandler {
3868
4362
  val = parseFloat(val);
3869
4363
  } else {
3870
4364
  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);
4365
+ val = match13(type).with("Int", () => parseInt(value, 10)).with("BigInt", () => BigInt(value)).with("Float", () => parseFloat(value)).with("Decimal", () => parseFloat(value)).otherwise(() => value);
3872
4366
  }
3873
4367
  }
3874
4368
  }
@@ -3883,31 +4377,45 @@ var GroupByeOperationHandler = class extends BaseOperationHandler {
3883
4377
  };
3884
4378
 
3885
4379
  // src/client/crud/operations/update.ts
3886
- import { match as match13 } from "ts-pattern";
4380
+ import { match as match14 } from "ts-pattern";
3887
4381
  var UpdateOperationHandler = class extends BaseOperationHandler {
3888
4382
  static {
3889
4383
  __name(this, "UpdateOperationHandler");
3890
4384
  }
3891
4385
  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();
4386
+ const normalizedArgs = this.normalizeArgs(args);
4387
+ 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
4388
  }
3894
4389
  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
- });
4390
+ const readBackResult = await this.safeTransaction(async (tx) => {
4391
+ const updateResult = await this.update(tx, this.model, args.where, args.data);
4392
+ const readFilter = updateResult ?? args.where;
4393
+ let readBackResult2 = void 0;
4394
+ try {
4395
+ readBackResult2 = await this.readUnique(tx, this.model, {
4396
+ select: args.select,
4397
+ include: args.include,
4398
+ omit: args.omit,
4399
+ where: readFilter
4400
+ });
4401
+ } catch {
4402
+ }
4403
+ return readBackResult2;
3903
4404
  });
3904
- if (!result && this.hasPolicyEnabled) {
3905
- throw new RejectedByPolicyError(this.model, "result is not allowed to be read back");
4405
+ if (!readBackResult) {
4406
+ if (this.hasPolicyEnabled) {
4407
+ throw new RejectedByPolicyError(this.model, "result is not allowed to be read back");
4408
+ } else {
4409
+ return null;
4410
+ }
4411
+ } else {
4412
+ return readBackResult;
3906
4413
  }
3907
- return result;
3908
4414
  }
3909
4415
  async runUpdateMany(args) {
3910
- return this.updateMany(this.kysely, this.model, args.where, args.data, args.limit, false);
4416
+ return this.safeTransaction(async (tx) => {
4417
+ return this.updateMany(tx, this.model, args.where, args.data, args.limit, false);
4418
+ });
3911
4419
  }
3912
4420
  async runUpdateManyAndReturn(args) {
3913
4421
  if (!args) {
@@ -3945,19 +4453,19 @@ var UpdateOperationHandler = class extends BaseOperationHandler {
3945
4453
  };
3946
4454
 
3947
4455
  // src/client/crud/validator.ts
4456
+ import { invariant as invariant8 } from "@zenstackhq/common-helpers";
3948
4457
  import Decimal from "decimal.js";
3949
4458
  import stableStringify from "json-stable-stringify";
3950
- import { match as match14, P as P2 } from "ts-pattern";
4459
+ import { match as match15, P as P2 } from "ts-pattern";
3951
4460
  import { z } from "zod";
3952
4461
  var InputValidator = class {
3953
4462
  static {
3954
4463
  __name(this, "InputValidator");
3955
4464
  }
3956
4465
  schema;
3957
- schemaCache;
4466
+ schemaCache = /* @__PURE__ */ new Map();
3958
4467
  constructor(schema) {
3959
4468
  this.schema = schema;
3960
- this.schemaCache = /* @__PURE__ */ new Map();
3961
4469
  }
3962
4470
  validateFindArgs(model, unique, args) {
3963
4471
  return this.validate(model, "find", {
@@ -4014,7 +4522,7 @@ var InputValidator = class {
4014
4522
  }
4015
4523
  const { error } = schema.safeParse(args);
4016
4524
  if (error) {
4017
- throw new QueryError(`Invalid ${operation} args: ${error.message}`);
4525
+ throw new InputValidationError(`Invalid ${operation} args: ${error.message}`, error);
4018
4526
  }
4019
4527
  return args;
4020
4528
  }
@@ -4033,11 +4541,11 @@ var InputValidator = class {
4033
4541
  fields["distinct"] = this.makeDistinctSchema(model).optional();
4034
4542
  fields["cursor"] = this.makeCursorSchema(model).optional();
4035
4543
  if (options.collection) {
4036
- fields["skip"] = z.number().int().nonnegative().optional();
4037
- fields["take"] = z.number().int().optional();
4544
+ fields["skip"] = this.makeSkipSchema().optional();
4545
+ fields["take"] = this.makeTakeSchema().optional();
4038
4546
  fields["orderBy"] = this.orArray(this.makeOrderBySchema(model, true, false), true).optional();
4039
4547
  }
4040
- let result = z.object(fields).strict();
4548
+ let result = z.strictObject(fields);
4041
4549
  result = this.refineForSelectIncludeMutuallyExclusive(result);
4042
4550
  result = this.refineForSelectOmitMutuallyExclusive(result);
4043
4551
  if (!options.unique) {
@@ -4046,22 +4554,50 @@ var InputValidator = class {
4046
4554
  return result;
4047
4555
  }
4048
4556
  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) {
4557
+ if (this.schema.typeDefs && type in this.schema.typeDefs) {
4558
+ return this.makeTypeDefSchema(type);
4559
+ } else {
4560
+ return match15(type).with("String", () => z.string()).with("Int", () => z.int()).with("Float", () => z.number()).with("Boolean", () => z.boolean()).with("BigInt", () => z.union([
4561
+ z.int(),
4562
+ z.bigint()
4563
+ ])).with("Decimal", () => z.union([
4564
+ z.number(),
4565
+ z.instanceof(Decimal),
4566
+ z.string()
4567
+ ])).with("DateTime", () => z.union([
4568
+ z.date(),
4569
+ z.string().datetime()
4570
+ ])).with("Bytes", () => z.instanceof(Uint8Array)).otherwise(() => z.unknown());
4571
+ }
4572
+ }
4573
+ makeTypeDefSchema(type) {
4574
+ const key = `$typedef-${type}`;
4575
+ let schema = this.schemaCache.get(key);
4576
+ if (schema) {
4577
+ return schema;
4578
+ }
4579
+ const typeDef = this.schema.typeDefs?.[type];
4580
+ invariant8(typeDef, `Type definition "${type}" not found in schema`);
4581
+ schema = z.looseObject(Object.fromEntries(Object.entries(typeDef.fields).map(([field, def]) => {
4582
+ let fieldSchema = this.makePrimitiveSchema(def.type);
4583
+ if (def.array) {
4584
+ fieldSchema = fieldSchema.array();
4585
+ }
4586
+ if (def.optional) {
4587
+ fieldSchema = fieldSchema.optional();
4588
+ }
4589
+ return [
4590
+ field,
4591
+ fieldSchema
4592
+ ];
4593
+ })));
4594
+ this.schemaCache.set(key, schema);
4595
+ return schema;
4596
+ }
4597
+ makeWhereSchema(model, unique, withoutRelationFields = false, withAggregations = false) {
4062
4598
  const modelDef = getModel(this.schema, model);
4063
4599
  if (!modelDef) {
4064
- throw new QueryError(`Model "${model}" not found`);
4600
+ throw new QueryError(`Model "${model}" not found in schema`);
4065
4601
  }
4066
4602
  const fields = {};
4067
4603
  for (const field of Object.keys(modelDef.fields)) {
@@ -4076,7 +4612,7 @@ var InputValidator = class {
4076
4612
  if (fieldDef.array) {
4077
4613
  fieldSchema = z.union([
4078
4614
  fieldSchema,
4079
- z.object({
4615
+ z.strictObject({
4080
4616
  some: fieldSchema.optional(),
4081
4617
  every: fieldSchema.optional(),
4082
4618
  none: fieldSchema.optional()
@@ -4085,7 +4621,7 @@ var InputValidator = class {
4085
4621
  } else {
4086
4622
  fieldSchema = z.union([
4087
4623
  fieldSchema,
4088
- z.object({
4624
+ z.strictObject({
4089
4625
  is: fieldSchema.optional(),
4090
4626
  isNot: fieldSchema.optional()
4091
4627
  })
@@ -4095,12 +4631,12 @@ var InputValidator = class {
4095
4631
  const enumDef = getEnum(this.schema, fieldDef.type);
4096
4632
  if (enumDef) {
4097
4633
  if (Object.keys(enumDef).length > 0) {
4098
- fieldSchema = this.makeEnumFilterSchema(enumDef, !!fieldDef.optional);
4634
+ fieldSchema = this.makeEnumFilterSchema(enumDef, !!fieldDef.optional, withAggregations);
4099
4635
  }
4100
4636
  } else if (fieldDef.array) {
4101
4637
  fieldSchema = this.makeArrayFilterSchema(fieldDef.type);
4102
4638
  } else {
4103
- fieldSchema = this.makePrimitiveFilterSchema(fieldDef.type, !!fieldDef.optional);
4639
+ fieldSchema = this.makePrimitiveFilterSchema(fieldDef.type, !!fieldDef.optional, withAggregations);
4104
4640
  }
4105
4641
  }
4106
4642
  if (fieldSchema) {
@@ -4111,18 +4647,32 @@ var InputValidator = class {
4111
4647
  const uniqueFields = getUniqueFields(this.schema, model);
4112
4648
  for (const uniqueField of uniqueFields) {
4113
4649
  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();
4650
+ fields[uniqueField.name] = z.object(Object.fromEntries(Object.entries(uniqueField.defs).map(([key, def]) => {
4651
+ invariant8(!def.relation, "unique field cannot be a relation");
4652
+ let fieldSchema;
4653
+ const enumDef = getEnum(this.schema, def.type);
4654
+ if (enumDef) {
4655
+ if (Object.keys(enumDef).length > 0) {
4656
+ fieldSchema = this.makeEnumFilterSchema(enumDef, !!def.optional, false);
4657
+ } else {
4658
+ fieldSchema = z.never();
4659
+ }
4660
+ } else {
4661
+ fieldSchema = this.makePrimitiveFilterSchema(def.type, !!def.optional, false);
4662
+ }
4663
+ return [
4664
+ key,
4665
+ fieldSchema
4666
+ ];
4667
+ }))).optional();
4118
4668
  }
4119
4669
  }
4120
4670
  }
4121
- fields["$expr"] = z.function().optional();
4671
+ fields["$expr"] = z.custom((v) => typeof v === "function").optional();
4122
4672
  fields["AND"] = this.orArray(z.lazy(() => this.makeWhereSchema(model, false, withoutRelationFields)), true).optional();
4123
4673
  fields["OR"] = z.lazy(() => this.makeWhereSchema(model, false, withoutRelationFields)).array().optional();
4124
4674
  fields["NOT"] = this.orArray(z.lazy(() => this.makeWhereSchema(model, false, withoutRelationFields)), true).optional();
4125
- const baseWhere = z.object(fields).strict();
4675
+ const baseWhere = z.strictObject(fields);
4126
4676
  let result = baseWhere;
4127
4677
  if (unique) {
4128
4678
  const uniqueFields = getUniqueFields(this.schema, model);
@@ -4141,21 +4691,25 @@ var InputValidator = class {
4141
4691
  }
4142
4692
  return result;
4143
4693
  }
4144
- makeEnumFilterSchema(enumDef, optional) {
4694
+ makeEnumFilterSchema(enumDef, optional, withAggregations) {
4145
4695
  const baseSchema = z.enum(Object.keys(enumDef));
4146
- const components = this.makeCommonPrimitiveFilterComponents(baseSchema, optional, () => z.lazy(() => this.makeEnumFilterSchema(enumDef, optional)));
4696
+ const components = this.makeCommonPrimitiveFilterComponents(baseSchema, optional, () => z.lazy(() => this.makeEnumFilterSchema(enumDef, optional, withAggregations)), [
4697
+ "equals",
4698
+ "in",
4699
+ "notIn",
4700
+ "not"
4701
+ ], withAggregations ? [
4702
+ "_count",
4703
+ "_min",
4704
+ "_max"
4705
+ ] : void 0);
4147
4706
  return z.union([
4148
4707
  this.nullableIf(baseSchema, optional),
4149
- z.object({
4150
- equals: components.equals,
4151
- in: components.in,
4152
- notIn: components.notIn,
4153
- not: components.not
4154
- })
4708
+ z.strictObject(components)
4155
4709
  ]);
4156
4710
  }
4157
4711
  makeArrayFilterSchema(type) {
4158
- return z.object({
4712
+ return z.strictObject({
4159
4713
  equals: this.makePrimitiveSchema(type).array().optional(),
4160
4714
  has: this.makePrimitiveSchema(type).optional(),
4161
4715
  hasEvery: this.makePrimitiveSchema(type).array().optional(),
@@ -4163,39 +4717,59 @@ var InputValidator = class {
4163
4717
  isEmpty: z.boolean().optional()
4164
4718
  });
4165
4719
  }
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();
4720
+ makePrimitiveFilterSchema(type, optional, withAggregations) {
4721
+ if (this.schema.typeDefs && type in this.schema.typeDefs) {
4722
+ return this.makeTypeDefFilterSchema(type, optional);
4723
+ }
4724
+ 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();
4725
+ }
4726
+ makeTypeDefFilterSchema(_type, _optional) {
4727
+ return z.never();
4168
4728
  }
4169
- makeDateTimeFilterSchema(optional) {
4729
+ makeDateTimeFilterSchema(optional, withAggregations) {
4170
4730
  return this.makeCommonPrimitiveFilterSchema(z.union([
4171
- z.string().datetime(),
4731
+ z.iso.datetime(),
4172
4732
  z.date()
4173
- ]), optional, () => z.lazy(() => this.makeDateTimeFilterSchema(optional)));
4174
- }
4175
- makeBooleanFilterSchema(optional) {
4733
+ ]), optional, () => z.lazy(() => this.makeDateTimeFilterSchema(optional, withAggregations)), withAggregations ? [
4734
+ "_count",
4735
+ "_min",
4736
+ "_max"
4737
+ ] : void 0);
4738
+ }
4739
+ makeBooleanFilterSchema(optional, withAggregations) {
4740
+ const components = this.makeCommonPrimitiveFilterComponents(z.boolean(), optional, () => z.lazy(() => this.makeBooleanFilterSchema(optional, withAggregations)), [
4741
+ "equals",
4742
+ "not"
4743
+ ], withAggregations ? [
4744
+ "_count",
4745
+ "_min",
4746
+ "_max"
4747
+ ] : void 0);
4176
4748
  return z.union([
4177
4749
  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
- })
4750
+ z.strictObject(components)
4182
4751
  ]);
4183
4752
  }
4184
- makeBytesFilterSchema(optional) {
4753
+ makeBytesFilterSchema(optional, withAggregations) {
4185
4754
  const baseSchema = z.instanceof(Uint8Array);
4186
- const components = this.makeCommonPrimitiveFilterComponents(baseSchema, optional, () => z.instanceof(Uint8Array));
4755
+ const components = this.makeCommonPrimitiveFilterComponents(baseSchema, optional, () => z.instanceof(Uint8Array), [
4756
+ "equals",
4757
+ "in",
4758
+ "notIn",
4759
+ "not"
4760
+ ], withAggregations ? [
4761
+ "_count",
4762
+ "_min",
4763
+ "_max"
4764
+ ] : void 0);
4187
4765
  return z.union([
4188
4766
  this.nullableIf(baseSchema, optional),
4189
- z.object({
4190
- equals: components.equals,
4191
- in: components.in,
4192
- notIn: components.notIn,
4193
- not: components.not
4194
- })
4767
+ z.strictObject(components)
4195
4768
  ]);
4196
4769
  }
4197
- makeCommonPrimitiveFilterComponents(baseSchema, optional, makeThis) {
4198
- return {
4770
+ makeCommonPrimitiveFilterComponents(baseSchema, optional, makeThis, supportedOperators = void 0, withAggregations = void 0) {
4771
+ const commonAggSchema = /* @__PURE__ */ __name(() => this.makeCommonPrimitiveFilterSchema(baseSchema, false, makeThis, void 0).optional(), "commonAggSchema");
4772
+ let result = {
4199
4773
  equals: this.nullableIf(baseSchema.optional(), optional),
4200
4774
  notEquals: this.nullableIf(baseSchema.optional(), optional),
4201
4775
  in: baseSchema.array().optional(),
@@ -4204,20 +4778,70 @@ var InputValidator = class {
4204
4778
  lte: baseSchema.optional(),
4205
4779
  gt: baseSchema.optional(),
4206
4780
  gte: baseSchema.optional(),
4207
- not: makeThis().optional()
4781
+ not: makeThis().optional(),
4782
+ ...withAggregations?.includes("_count") ? {
4783
+ _count: this.makeNumberFilterSchema(z.int(), false, false).optional()
4784
+ } : {},
4785
+ ...withAggregations?.includes("_avg") ? {
4786
+ _avg: commonAggSchema()
4787
+ } : {},
4788
+ ...withAggregations?.includes("_sum") ? {
4789
+ _sum: commonAggSchema()
4790
+ } : {},
4791
+ ...withAggregations?.includes("_min") ? {
4792
+ _min: commonAggSchema()
4793
+ } : {},
4794
+ ...withAggregations?.includes("_max") ? {
4795
+ _max: commonAggSchema()
4796
+ } : {}
4208
4797
  };
4798
+ if (supportedOperators) {
4799
+ const keys = [
4800
+ ...supportedOperators,
4801
+ ...withAggregations ?? []
4802
+ ];
4803
+ result = extractFields(result, keys);
4804
+ }
4805
+ return result;
4209
4806
  }
4210
- makeCommonPrimitiveFilterSchema(baseSchema, optional, makeThis) {
4807
+ makeCommonPrimitiveFilterSchema(baseSchema, optional, makeThis, withAggregations = void 0) {
4211
4808
  return z.union([
4212
4809
  this.nullableIf(baseSchema, optional),
4213
- z.object(this.makeCommonPrimitiveFilterComponents(baseSchema, optional, makeThis))
4810
+ z.strictObject(this.makeCommonPrimitiveFilterComponents(baseSchema, optional, makeThis, void 0, withAggregations))
4214
4811
  ]);
4215
4812
  }
4216
- makeNumberFilterSchema(baseSchema, optional) {
4217
- return this.makeCommonPrimitiveFilterSchema(baseSchema, optional, () => z.lazy(() => this.makeNumberFilterSchema(baseSchema, optional)));
4813
+ makeNumberFilterSchema(baseSchema, optional, withAggregations) {
4814
+ return this.makeCommonPrimitiveFilterSchema(baseSchema, optional, () => z.lazy(() => this.makeNumberFilterSchema(baseSchema, optional, withAggregations)), withAggregations ? [
4815
+ "_count",
4816
+ "_avg",
4817
+ "_sum",
4818
+ "_min",
4819
+ "_max"
4820
+ ] : void 0);
4821
+ }
4822
+ makeStringFilterSchema(optional, withAggregations) {
4823
+ return z.union([
4824
+ this.nullableIf(z.string(), optional),
4825
+ z.strictObject({
4826
+ ...this.makeCommonPrimitiveFilterComponents(z.string(), optional, () => z.lazy(() => this.makeStringFilterSchema(optional, withAggregations)), void 0, withAggregations ? [
4827
+ "_count",
4828
+ "_min",
4829
+ "_max"
4830
+ ] : void 0),
4831
+ startsWith: z.string().optional(),
4832
+ endsWith: z.string().optional(),
4833
+ contains: z.string().optional(),
4834
+ ...this.providerSupportsCaseSensitivity ? {
4835
+ mode: this.makeStringModeSchema().optional()
4836
+ } : {}
4837
+ })
4838
+ ]);
4218
4839
  }
4219
- makeStringFilterSchema(optional) {
4220
- return this.makeCommonPrimitiveFilterSchema(z.string(), optional, () => z.lazy(() => this.makeStringFilterSchema(optional)));
4840
+ makeStringModeSchema() {
4841
+ return z.union([
4842
+ z.literal("default"),
4843
+ z.literal("insensitive")
4844
+ ]);
4221
4845
  }
4222
4846
  makeSelectSchema(model) {
4223
4847
  const modelDef = requireModel(this.schema, model);
@@ -4227,7 +4851,7 @@ var InputValidator = class {
4227
4851
  if (fieldDef.relation) {
4228
4852
  fields[field] = z.union([
4229
4853
  z.literal(true),
4230
- z.object({
4854
+ z.strictObject({
4231
4855
  select: z.lazy(() => this.makeSelectSchema(fieldDef.type)).optional(),
4232
4856
  include: z.lazy(() => this.makeIncludeSchema(fieldDef.type)).optional()
4233
4857
  })
@@ -4236,22 +4860,24 @@ var InputValidator = class {
4236
4860
  fields[field] = z.boolean().optional();
4237
4861
  }
4238
4862
  }
4239
- const toManyRelations = Object.entries(modelDef.fields).filter(([, value]) => value.relation && value.array);
4863
+ const toManyRelations = Object.values(modelDef.fields).filter((def) => def.relation && def.array);
4240
4864
  if (toManyRelations.length > 0) {
4241
4865
  fields["_count"] = z.union([
4242
4866
  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
- }), {}))
4867
+ z.strictObject({
4868
+ select: z.strictObject(toManyRelations.reduce((acc, fieldDef) => ({
4869
+ ...acc,
4870
+ [fieldDef.name]: z.union([
4871
+ z.boolean(),
4872
+ z.strictObject({
4873
+ where: this.makeWhereSchema(fieldDef.type, false, false)
4874
+ })
4875
+ ]).optional()
4876
+ }), {}))
4877
+ })
4252
4878
  ]).optional();
4253
4879
  }
4254
- return z.object(fields).strict();
4880
+ return z.strictObject(fields);
4255
4881
  }
4256
4882
  makeOmitSchema(model) {
4257
4883
  const modelDef = requireModel(this.schema, model);
@@ -4262,7 +4888,7 @@ var InputValidator = class {
4262
4888
  fields[field] = z.boolean().optional();
4263
4889
  }
4264
4890
  }
4265
- return z.object(fields).strict();
4891
+ return z.strictObject(fields);
4266
4892
  }
4267
4893
  makeIncludeSchema(model) {
4268
4894
  const modelDef = requireModel(this.schema, model);
@@ -4272,15 +4898,20 @@ var InputValidator = class {
4272
4898
  if (fieldDef.relation) {
4273
4899
  fields[field] = z.union([
4274
4900
  z.literal(true),
4275
- z.object({
4901
+ z.strictObject({
4276
4902
  select: z.lazy(() => this.makeSelectSchema(fieldDef.type)).optional(),
4277
4903
  include: z.lazy(() => this.makeIncludeSchema(fieldDef.type)).optional(),
4278
- where: z.lazy(() => this.makeWhereSchema(fieldDef.type, false)).optional()
4904
+ omit: z.lazy(() => this.makeOmitSchema(fieldDef.type)).optional(),
4905
+ where: z.lazy(() => this.makeWhereSchema(fieldDef.type, false)).optional(),
4906
+ orderBy: z.lazy(() => this.makeOrderBySchema(fieldDef.type, true, false)).optional(),
4907
+ skip: this.makeSkipSchema().optional(),
4908
+ take: this.makeTakeSchema().optional(),
4909
+ distinct: this.makeDistinctSchema(fieldDef.type).optional()
4279
4910
  })
4280
4911
  ]).optional();
4281
4912
  }
4282
4913
  }
4283
- return z.object(fields).strict();
4914
+ return z.strictObject(fields);
4284
4915
  }
4285
4916
  makeOrderBySchema(model, withRelation, WithAggregation) {
4286
4917
  const modelDef = requireModel(this.schema, model);
@@ -4293,13 +4924,21 @@ var InputValidator = class {
4293
4924
  const fieldDef = requireField(this.schema, model, field);
4294
4925
  if (fieldDef.relation) {
4295
4926
  if (withRelation) {
4296
- fields[field] = z.lazy(() => this.makeOrderBySchema(fieldDef.type, withRelation, WithAggregation).optional());
4927
+ fields[field] = z.lazy(() => {
4928
+ let relationOrderBy = this.makeOrderBySchema(fieldDef.type, withRelation, WithAggregation);
4929
+ if (fieldDef.array) {
4930
+ relationOrderBy = relationOrderBy.extend({
4931
+ _count: sort
4932
+ });
4933
+ }
4934
+ return relationOrderBy.optional();
4935
+ });
4297
4936
  }
4298
4937
  } else {
4299
4938
  if (fieldDef.optional) {
4300
4939
  fields[field] = z.union([
4301
4940
  sort,
4302
- z.object({
4941
+ z.strictObject({
4303
4942
  sort,
4304
4943
  nulls: z.union([
4305
4944
  z.literal("first"),
@@ -4324,7 +4963,7 @@ var InputValidator = class {
4324
4963
  fields[agg] = z.lazy(() => this.makeOrderBySchema(model, true, false).optional());
4325
4964
  }
4326
4965
  }
4327
- return z.object(fields);
4966
+ return z.strictObject(fields);
4328
4967
  }
4329
4968
  makeDistinctSchema(model) {
4330
4969
  const modelDef = requireModel(this.schema, model);
@@ -4343,7 +4982,7 @@ var InputValidator = class {
4343
4982
  select: this.makeSelectSchema(model).optional(),
4344
4983
  include: this.makeIncludeSchema(model).optional(),
4345
4984
  omit: this.makeOmitSchema(model).optional()
4346
- }).strict();
4985
+ });
4347
4986
  return this.refineForSelectIncludeMutuallyExclusive(schema);
4348
4987
  }
4349
4988
  makeCreateManySchema(model) {
@@ -4351,15 +4990,15 @@ var InputValidator = class {
4351
4990
  }
4352
4991
  makeCreateManyAndReturnSchema(model) {
4353
4992
  const base = this.makeCreateManyDataSchema(model, []);
4354
- const result = base.merge(z.object({
4993
+ const result = base.merge(z.strictObject({
4355
4994
  select: this.makeSelectSchema(model).optional(),
4356
4995
  omit: this.makeOmitSchema(model).optional()
4357
4996
  }));
4358
4997
  return this.refineForSelectOmitMutuallyExclusive(result).optional();
4359
4998
  }
4360
4999
  makeCreateDataSchema(model, canBeArray, withoutFields = [], withoutRelationFields = false) {
4361
- const regularAndFkFields = {};
4362
- const regularAndRelationFields = {};
5000
+ const uncheckedVariantFields = {};
5001
+ const checkedVariantFields = {};
4363
5002
  const modelDef = requireModel(this.schema, model);
4364
5003
  const hasRelation = !withoutRelationFields && Object.entries(modelDef.fields).some(([f, def]) => !withoutFields.includes(f) && def.relation);
4365
5004
  Object.keys(modelDef.fields).forEach((field) => {
@@ -4370,6 +5009,9 @@ var InputValidator = class {
4370
5009
  if (fieldDef.computed) {
4371
5010
  return;
4372
5011
  }
5012
+ if (this.isDelegateDiscriminator(fieldDef)) {
5013
+ return;
5014
+ }
4373
5015
  if (fieldDef.relation) {
4374
5016
  if (withoutRelationFields) {
4375
5017
  return;
@@ -4401,13 +5043,16 @@ var InputValidator = class {
4401
5043
  if (fieldDef.optional && !fieldDef.array) {
4402
5044
  fieldSchema = fieldSchema.nullable();
4403
5045
  }
4404
- regularAndRelationFields[field] = fieldSchema;
5046
+ checkedVariantFields[field] = fieldSchema;
5047
+ if (fieldDef.array || !fieldDef.relation.references) {
5048
+ uncheckedVariantFields[field] = fieldSchema;
5049
+ }
4405
5050
  } else {
4406
5051
  let fieldSchema = this.makePrimitiveSchema(fieldDef.type);
4407
5052
  if (fieldDef.array) {
4408
5053
  fieldSchema = z.union([
4409
5054
  z.array(fieldSchema),
4410
- z.object({
5055
+ z.strictObject({
4411
5056
  set: z.array(fieldSchema)
4412
5057
  })
4413
5058
  ]).optional();
@@ -4418,27 +5063,34 @@ var InputValidator = class {
4418
5063
  if (fieldDef.optional) {
4419
5064
  fieldSchema = fieldSchema.nullable();
4420
5065
  }
4421
- regularAndFkFields[field] = fieldSchema;
5066
+ uncheckedVariantFields[field] = fieldSchema;
4422
5067
  if (!fieldDef.foreignKeyFor) {
4423
- regularAndRelationFields[field] = fieldSchema;
5068
+ checkedVariantFields[field] = fieldSchema;
4424
5069
  }
4425
5070
  }
4426
5071
  });
4427
5072
  if (!hasRelation) {
4428
- return this.orArray(z.object(regularAndFkFields).strict(), canBeArray);
5073
+ return this.orArray(z.strictObject(uncheckedVariantFields), canBeArray);
4429
5074
  } else {
4430
5075
  return z.union([
4431
- z.object(regularAndFkFields).strict(),
4432
- z.object(regularAndRelationFields).strict(),
5076
+ z.strictObject(uncheckedVariantFields),
5077
+ z.strictObject(checkedVariantFields),
4433
5078
  ...canBeArray ? [
4434
- z.array(z.object(regularAndFkFields).strict())
5079
+ z.array(z.strictObject(uncheckedVariantFields))
4435
5080
  ] : [],
4436
5081
  ...canBeArray ? [
4437
- z.array(z.object(regularAndRelationFields).strict())
5082
+ z.array(z.strictObject(checkedVariantFields))
4438
5083
  ] : []
4439
5084
  ]);
4440
5085
  }
4441
5086
  }
5087
+ isDelegateDiscriminator(fieldDef) {
5088
+ if (!fieldDef.originModel) {
5089
+ return false;
5090
+ }
5091
+ const discriminatorField = getDiscriminatorField(this.schema, fieldDef.originModel);
5092
+ return discriminatorField === fieldDef.name;
5093
+ }
4442
5094
  makeRelationManipulationSchema(fieldDef, withoutFields, mode) {
4443
5095
  const fieldType = fieldDef.type;
4444
5096
  const array = !!fieldDef.array;
@@ -4455,31 +5107,31 @@ var InputValidator = class {
4455
5107
  fields["disconnect"] = this.makeDisconnectDataSchema(fieldType, array).optional();
4456
5108
  fields["delete"] = this.makeDeleteRelationDataSchema(fieldType, array, true).optional();
4457
5109
  }
4458
- fields["update"] = array ? this.orArray(z.object({
5110
+ fields["update"] = array ? this.orArray(z.strictObject({
4459
5111
  where: this.makeWhereSchema(fieldType, true),
4460
5112
  data: this.makeUpdateDataSchema(fieldType, withoutFields)
4461
5113
  }), true).optional() : z.union([
4462
- z.object({
5114
+ z.strictObject({
4463
5115
  where: this.makeWhereSchema(fieldType, true),
4464
5116
  data: this.makeUpdateDataSchema(fieldType, withoutFields)
4465
5117
  }),
4466
5118
  this.makeUpdateDataSchema(fieldType, withoutFields)
4467
5119
  ]).optional();
4468
- fields["upsert"] = this.orArray(z.object({
5120
+ fields["upsert"] = this.orArray(z.strictObject({
4469
5121
  where: this.makeWhereSchema(fieldType, true),
4470
5122
  create: this.makeCreateDataSchema(fieldType, false, withoutFields),
4471
5123
  update: this.makeUpdateDataSchema(fieldType, withoutFields)
4472
5124
  }), true).optional();
4473
5125
  if (array) {
4474
5126
  fields["set"] = this.makeSetDataSchema(fieldType, true).optional();
4475
- fields["updateMany"] = this.orArray(z.object({
5127
+ fields["updateMany"] = this.orArray(z.strictObject({
4476
5128
  where: this.makeWhereSchema(fieldType, false, true),
4477
5129
  data: this.makeUpdateDataSchema(fieldType, withoutFields)
4478
5130
  }), true).optional();
4479
5131
  fields["deleteMany"] = this.makeDeleteRelationDataSchema(fieldType, true, false).optional();
4480
5132
  }
4481
5133
  }
4482
- return z.object(fields).strict().refine((v) => Object.keys(v).length > 0, "At least one action is required");
5134
+ return z.strictObject(fields);
4483
5135
  }
4484
5136
  makeSetDataSchema(model, canBeArray) {
4485
5137
  return this.orArray(this.makeWhereSchema(model, true), canBeArray);
@@ -4509,13 +5161,13 @@ var InputValidator = class {
4509
5161
  return this.orArray(z.object({
4510
5162
  where: whereSchema,
4511
5163
  create: createSchema
4512
- }).strict(), canBeArray);
5164
+ }), canBeArray);
4513
5165
  }
4514
5166
  makeCreateManyDataSchema(model, withoutFields) {
4515
5167
  return z.object({
4516
5168
  data: this.makeCreateDataSchema(model, true, withoutFields, true),
4517
5169
  skipDuplicates: z.boolean().optional()
4518
- }).strict();
5170
+ });
4519
5171
  }
4520
5172
  // #endregion
4521
5173
  // #region Update
@@ -4526,19 +5178,19 @@ var InputValidator = class {
4526
5178
  select: this.makeSelectSchema(model).optional(),
4527
5179
  include: this.makeIncludeSchema(model).optional(),
4528
5180
  omit: this.makeOmitSchema(model).optional()
4529
- }).strict();
5181
+ });
4530
5182
  return this.refineForSelectIncludeMutuallyExclusive(schema);
4531
5183
  }
4532
5184
  makeUpdateManySchema(model) {
4533
5185
  return z.object({
4534
5186
  where: this.makeWhereSchema(model, false).optional(),
4535
5187
  data: this.makeUpdateDataSchema(model, [], true),
4536
- limit: z.number().int().nonnegative().optional()
4537
- }).strict();
5188
+ limit: z.int().nonnegative().optional()
5189
+ });
4538
5190
  }
4539
5191
  makeUpdateManyAndReturnSchema(model) {
4540
5192
  const base = this.makeUpdateManySchema(model);
4541
- const result = base.merge(z.object({
5193
+ const result = base.merge(z.strictObject({
4542
5194
  select: this.makeSelectSchema(model).optional(),
4543
5195
  omit: this.makeOmitSchema(model).optional()
4544
5196
  }));
@@ -4552,12 +5204,12 @@ var InputValidator = class {
4552
5204
  select: this.makeSelectSchema(model).optional(),
4553
5205
  include: this.makeIncludeSchema(model).optional(),
4554
5206
  omit: this.makeOmitSchema(model).optional()
4555
- }).strict();
5207
+ });
4556
5208
  return this.refineForSelectIncludeMutuallyExclusive(schema);
4557
5209
  }
4558
5210
  makeUpdateDataSchema(model, withoutFields = [], withoutRelationFields = false) {
4559
- const regularAndFkFields = {};
4560
- const regularAndRelationFields = {};
5211
+ const uncheckedVariantFields = {};
5212
+ const checkedVariantFields = {};
4561
5213
  const modelDef = requireModel(this.schema, model);
4562
5214
  const hasRelation = Object.entries(modelDef.fields).some(([key, value]) => value.relation && !withoutFields.includes(key));
4563
5215
  Object.keys(modelDef.fields).forEach((field) => {
@@ -4582,7 +5234,10 @@ var InputValidator = class {
4582
5234
  if (fieldDef.optional && !fieldDef.array) {
4583
5235
  fieldSchema = fieldSchema.nullable();
4584
5236
  }
4585
- regularAndRelationFields[field] = fieldSchema;
5237
+ checkedVariantFields[field] = fieldSchema;
5238
+ if (fieldDef.array || !fieldDef.relation.references) {
5239
+ uncheckedVariantFields[field] = fieldSchema;
5240
+ }
4586
5241
  } else {
4587
5242
  let fieldSchema = this.makePrimitiveSchema(fieldDef.type).optional();
4588
5243
  if (this.isNumericField(fieldDef)) {
@@ -4609,18 +5264,18 @@ var InputValidator = class {
4609
5264
  if (fieldDef.optional) {
4610
5265
  fieldSchema = fieldSchema.nullable();
4611
5266
  }
4612
- regularAndFkFields[field] = fieldSchema;
5267
+ uncheckedVariantFields[field] = fieldSchema;
4613
5268
  if (!fieldDef.foreignKeyFor) {
4614
- regularAndRelationFields[field] = fieldSchema;
5269
+ checkedVariantFields[field] = fieldSchema;
4615
5270
  }
4616
5271
  }
4617
5272
  });
4618
5273
  if (!hasRelation) {
4619
- return z.object(regularAndFkFields).strict();
5274
+ return z.strictObject(uncheckedVariantFields);
4620
5275
  } else {
4621
5276
  return z.union([
4622
- z.object(regularAndFkFields).strict(),
4623
- z.object(regularAndRelationFields).strict()
5277
+ z.strictObject(uncheckedVariantFields),
5278
+ z.strictObject(checkedVariantFields)
4624
5279
  ]);
4625
5280
  }
4626
5281
  }
@@ -4631,25 +5286,25 @@ var InputValidator = class {
4631
5286
  where: this.makeWhereSchema(model, true),
4632
5287
  select: this.makeSelectSchema(model).optional(),
4633
5288
  include: this.makeIncludeSchema(model).optional()
4634
- }).strict();
5289
+ });
4635
5290
  return this.refineForSelectIncludeMutuallyExclusive(schema);
4636
5291
  }
4637
5292
  makeDeleteManySchema(model) {
4638
5293
  return z.object({
4639
5294
  where: this.makeWhereSchema(model, false).optional(),
4640
- limit: z.number().int().nonnegative().optional()
4641
- }).strict().optional();
5295
+ limit: z.int().nonnegative().optional()
5296
+ }).optional();
4642
5297
  }
4643
5298
  // #endregion
4644
5299
  // #region Count
4645
5300
  makeCountSchema(model) {
4646
5301
  return z.object({
4647
5302
  where: this.makeWhereSchema(model, false).optional(),
4648
- skip: z.number().int().nonnegative().optional(),
4649
- take: z.number().int().optional(),
5303
+ skip: this.makeSkipSchema().optional(),
5304
+ take: this.makeTakeSchema().optional(),
4650
5305
  orderBy: this.orArray(this.makeOrderBySchema(model, true, false), true).optional(),
4651
5306
  select: this.makeCountAggregateInputSchema(model).optional()
4652
- }).strict().optional();
5307
+ }).optional();
4653
5308
  }
4654
5309
  makeCountAggregateInputSchema(model) {
4655
5310
  const modelDef = requireModel(this.schema, model);
@@ -4661,7 +5316,7 @@ var InputValidator = class {
4661
5316
  acc[field] = z.literal(true).optional();
4662
5317
  return acc;
4663
5318
  }, {})
4664
- }).strict()
5319
+ })
4665
5320
  ]);
4666
5321
  }
4667
5322
  // #endregion
@@ -4669,19 +5324,19 @@ var InputValidator = class {
4669
5324
  makeAggregateSchema(model) {
4670
5325
  return z.object({
4671
5326
  where: this.makeWhereSchema(model, false).optional(),
4672
- skip: z.number().int().nonnegative().optional(),
4673
- take: z.number().int().optional(),
5327
+ skip: this.makeSkipSchema().optional(),
5328
+ take: this.makeTakeSchema().optional(),
4674
5329
  orderBy: this.orArray(this.makeOrderBySchema(model, true, false), true).optional(),
4675
5330
  _count: this.makeCountAggregateInputSchema(model).optional(),
4676
5331
  _avg: this.makeSumAvgInputSchema(model).optional(),
4677
5332
  _sum: this.makeSumAvgInputSchema(model).optional(),
4678
5333
  _min: this.makeMinMaxInputSchema(model).optional(),
4679
5334
  _max: this.makeMinMaxInputSchema(model).optional()
4680
- }).strict().optional();
5335
+ }).optional();
4681
5336
  }
4682
5337
  makeSumAvgInputSchema(model) {
4683
5338
  const modelDef = requireModel(this.schema, model);
4684
- return z.object(Object.keys(modelDef.fields).reduce((acc, field) => {
5339
+ return z.strictObject(Object.keys(modelDef.fields).reduce((acc, field) => {
4685
5340
  const fieldDef = requireField(this.schema, model, field);
4686
5341
  if (this.isNumericField(fieldDef)) {
4687
5342
  acc[field] = z.literal(true).optional();
@@ -4691,7 +5346,7 @@ var InputValidator = class {
4691
5346
  }
4692
5347
  makeMinMaxInputSchema(model) {
4693
5348
  const modelDef = requireModel(this.schema, model);
4694
- return z.object(Object.keys(modelDef.fields).reduce((acc, field) => {
5349
+ return z.strictObject(Object.keys(modelDef.fields).reduce((acc, field) => {
4695
5350
  const fieldDef = requireField(this.schema, model, field);
4696
5351
  if (!fieldDef.relation && !fieldDef.array) {
4697
5352
  acc[field] = z.literal(true).optional();
@@ -4706,30 +5361,42 @@ var InputValidator = class {
4706
5361
  where: this.makeWhereSchema(model, false).optional(),
4707
5362
  orderBy: this.orArray(this.makeOrderBySchema(model, false, true), true).optional(),
4708
5363
  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(),
5364
+ having: this.makeHavingSchema(model).optional(),
5365
+ skip: this.makeSkipSchema().optional(),
5366
+ take: this.makeTakeSchema().optional(),
4712
5367
  _count: this.makeCountAggregateInputSchema(model).optional(),
4713
5368
  _avg: this.makeSumAvgInputSchema(model).optional(),
4714
5369
  _sum: this.makeSumAvgInputSchema(model).optional(),
4715
5370
  _min: this.makeMinMaxInputSchema(model).optional(),
4716
5371
  _max: this.makeMinMaxInputSchema(model).optional()
4717
- }).strict();
5372
+ });
4718
5373
  schema = schema.refine((value) => {
4719
5374
  const bys = typeof value.by === "string" ? [
4720
5375
  value.by
4721
5376
  ] : 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;
5377
+ if (value.having && typeof value.having === "object") {
5378
+ for (const [key, val] of Object.entries(value.having)) {
5379
+ if (AGGREGATE_OPERATORS.includes(key)) {
5380
+ continue;
5381
+ }
5382
+ if (bys.includes(key)) {
5383
+ continue;
5384
+ }
5385
+ if (!val || typeof val !== "object") {
5386
+ return false;
5387
+ }
5388
+ if (!this.onlyAggregationFields(val)) {
5389
+ return false;
5390
+ }
5391
+ }
4726
5392
  }
5393
+ return true;
4727
5394
  }, 'fields in "having" must be in "by"');
4728
5395
  schema = schema.refine((value) => {
4729
5396
  const bys = typeof value.by === "string" ? [
4730
5397
  value.by
4731
5398
  ] : value.by;
4732
- if (value.orderBy && Object.keys(value.orderBy).filter((f) => !f.startsWith("_")).some((key) => !bys.includes(key))) {
5399
+ if (value.orderBy && Object.keys(value.orderBy).filter((f) => !AGGREGATE_OPERATORS.includes(f)).some((key) => !bys.includes(key))) {
4733
5400
  return false;
4734
5401
  } else {
4735
5402
  return true;
@@ -4737,8 +5404,31 @@ var InputValidator = class {
4737
5404
  }, 'fields in "orderBy" must be in "by"');
4738
5405
  return schema;
4739
5406
  }
5407
+ onlyAggregationFields(val) {
5408
+ for (const [key, value] of Object.entries(val)) {
5409
+ if (AGGREGATE_OPERATORS.includes(key)) {
5410
+ continue;
5411
+ }
5412
+ if (LOGICAL_COMBINATORS.includes(key)) {
5413
+ if (enumerate(value).every((v) => this.onlyAggregationFields(v))) {
5414
+ continue;
5415
+ }
5416
+ }
5417
+ return false;
5418
+ }
5419
+ return true;
5420
+ }
5421
+ makeHavingSchema(model) {
5422
+ return this.makeWhereSchema(model, false, true, true);
5423
+ }
4740
5424
  // #endregion
4741
5425
  // #region Helpers
5426
+ makeSkipSchema() {
5427
+ return z.int().nonnegative();
5428
+ }
5429
+ makeTakeSchema() {
5430
+ return z.int();
5431
+ }
4742
5432
  refineForSelectIncludeMutuallyExclusive(schema) {
4743
5433
  return schema.refine((value) => !(value["select"] && value["include"]), '"select" and "include" cannot be used together');
4744
5434
  }
@@ -4757,6 +5447,9 @@ var InputValidator = class {
4757
5447
  isNumericField(fieldDef) {
4758
5448
  return NUMERIC_FIELD_TYPES.includes(fieldDef.type) && !fieldDef.array;
4759
5449
  }
5450
+ get providerSupportsCaseSensitivity() {
5451
+ return this.schema.provider.type === "postgresql";
5452
+ }
4760
5453
  };
4761
5454
 
4762
5455
  // src/client/executor/zenstack-driver.ts
@@ -4766,11 +5459,11 @@ var ZenStackDriver = class {
4766
5459
  }
4767
5460
  #driver;
4768
5461
  #log;
4769
- txConnection;
4770
5462
  #initPromise;
4771
5463
  #initDone;
4772
5464
  #destroyPromise;
4773
5465
  #connections = /* @__PURE__ */ new WeakSet();
5466
+ #txConnections = /* @__PURE__ */ new WeakMap();
4774
5467
  constructor(driver, log) {
4775
5468
  this.#initDone = false;
4776
5469
  this.#driver = driver;
@@ -4811,21 +5504,30 @@ var ZenStackDriver = class {
4811
5504
  }
4812
5505
  async beginTransaction(connection, settings) {
4813
5506
  const result = await this.#driver.beginTransaction(connection, settings);
4814
- this.txConnection = connection;
5507
+ this.#txConnections.set(connection, []);
4815
5508
  return result;
4816
5509
  }
4817
- commitTransaction(connection) {
5510
+ async commitTransaction(connection) {
4818
5511
  try {
4819
- return this.#driver.commitTransaction(connection);
4820
- } finally {
4821
- this.txConnection = void 0;
5512
+ const result = await this.#driver.commitTransaction(connection);
5513
+ const callbacks = this.#txConnections.get(connection);
5514
+ this.#txConnections.delete(connection);
5515
+ if (callbacks) {
5516
+ for (const callback of callbacks) {
5517
+ await callback();
5518
+ }
5519
+ }
5520
+ return result;
5521
+ } catch (err) {
5522
+ this.#txConnections.delete(connection);
5523
+ throw err;
4822
5524
  }
4823
5525
  }
4824
- rollbackTransaction(connection) {
5526
+ async rollbackTransaction(connection) {
4825
5527
  try {
4826
- return this.#driver.rollbackTransaction(connection);
5528
+ return await this.#driver.rollbackTransaction(connection);
4827
5529
  } finally {
4828
- this.txConnection = void 0;
5530
+ this.#txConnections.delete(connection);
4829
5531
  }
4830
5532
  }
4831
5533
  async destroy() {
@@ -4903,6 +5605,22 @@ var ZenStackDriver = class {
4903
5605
  #calculateDurationMillis(startTime) {
4904
5606
  return performanceNow() - startTime;
4905
5607
  }
5608
+ isTransactionConnection(connection) {
5609
+ return this.#txConnections.has(connection);
5610
+ }
5611
+ registerTransactionCommitCallback(connection, callback) {
5612
+ if (!this.#txConnections.has(connection)) {
5613
+ return;
5614
+ }
5615
+ const callbacks = this.#txConnections.get(connection);
5616
+ if (callbacks) {
5617
+ callbacks.push(callback);
5618
+ } else {
5619
+ this.#txConnections.set(connection, [
5620
+ callback
5621
+ ]);
5622
+ }
5623
+ }
4906
5624
  };
4907
5625
  function performanceNow() {
4908
5626
  if (typeof performance !== "undefined" && typeof performance.now === "function") {
@@ -4914,9 +5632,10 @@ function performanceNow() {
4914
5632
  __name(performanceNow, "performanceNow");
4915
5633
 
4916
5634
  // 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";
5635
+ 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
5636
  import { nanoid as nanoid2 } from "nanoid";
4919
- import { match as match15 } from "ts-pattern";
5637
+ import { inspect as inspect2 } from "util";
5638
+ import { match as match16 } from "ts-pattern";
4920
5639
 
4921
5640
  // src/client/executor/name-mapper.ts
4922
5641
  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 +5644,11 @@ var QueryNameMapper = class extends OperationNodeTransformer2 {
4925
5644
  __name(this, "QueryNameMapper");
4926
5645
  }
4927
5646
  schema;
4928
- modelToTableMap;
4929
- fieldToColumnMap;
4930
- modelStack;
5647
+ modelToTableMap = /* @__PURE__ */ new Map();
5648
+ fieldToColumnMap = /* @__PURE__ */ new Map();
5649
+ modelStack = [];
4931
5650
  constructor(schema) {
4932
- super(), this.schema = schema, this.modelToTableMap = /* @__PURE__ */ new Map(), this.fieldToColumnMap = /* @__PURE__ */ new Map(), this.modelStack = [];
5651
+ super(), this.schema = schema;
4933
5652
  for (const [modelName, modelDef] of Object.entries(schema.models)) {
4934
5653
  const mappedName = this.getMappedName(modelDef);
4935
5654
  if (mappedName) {
@@ -5118,7 +5837,7 @@ var QueryNameMapper = class extends OperationNodeTransformer2 {
5118
5837
  this.requireCurrentModel(contextNode);
5119
5838
  model = model ?? this.currentModel;
5120
5839
  const modelDef = requireModel(this.schema, model);
5121
- const scalarFields = Object.entries(modelDef.fields).filter(([, fieldDef]) => !fieldDef.relation && !fieldDef.computed).map(([fieldName]) => fieldName);
5840
+ const scalarFields = Object.entries(modelDef.fields).filter(([, fieldDef]) => !fieldDef.relation && !fieldDef.computed && !fieldDef.originModel).map(([fieldName]) => fieldName);
5122
5841
  return scalarFields;
5123
5842
  }
5124
5843
  };
@@ -5143,16 +5862,18 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends DefaultQueryExe
5143
5862
  get options() {
5144
5863
  return this.client.$options;
5145
5864
  }
5146
- async executeQuery(compiledQuery, queryId) {
5865
+ async executeQuery(compiledQuery, _queryId) {
5147
5866
  let queryNode = compiledQuery.query;
5148
5867
  let mutationInterceptionInfo;
5149
5868
  if (this.isMutationNode(queryNode) && this.hasMutationHooks) {
5150
5869
  mutationInterceptionInfo = await this.callMutationInterceptionFilters(queryNode);
5151
5870
  }
5152
5871
  const task = /* @__PURE__ */ __name(async () => {
5153
- await this.callBeforeMutationHooks(queryNode, mutationInterceptionInfo);
5872
+ if (this.isMutationNode(queryNode)) {
5873
+ await this.callBeforeMutationHooks(queryNode, mutationInterceptionInfo);
5874
+ }
5154
5875
  const oldQueryNode = queryNode;
5155
- if ((InsertQueryNode2.is(queryNode) || DeleteQueryNode2.is(queryNode)) && mutationInterceptionInfo?.loadAfterMutationEntity) {
5876
+ if ((InsertQueryNode2.is(queryNode) || UpdateQueryNode2.is(queryNode)) && mutationInterceptionInfo?.loadAfterMutationEntity) {
5156
5877
  queryNode = {
5157
5878
  ...queryNode,
5158
5879
  returning: ReturningNode3.create([
@@ -5160,42 +5881,73 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends DefaultQueryExe
5160
5881
  ])
5161
5882
  };
5162
5883
  }
5163
- const result = await this.proceedQueryWithKyselyInterceptors(queryNode, queryId);
5164
- await this.callAfterQueryInterceptionFilters(result, queryNode, mutationInterceptionInfo);
5884
+ const queryParams = compiledQuery.$raw ? compiledQuery.parameters : void 0;
5885
+ const result = await this.proceedQueryWithKyselyInterceptors(queryNode, queryParams);
5886
+ if (this.isMutationNode(queryNode)) {
5887
+ await this.callAfterMutationHooks(result.result, queryNode, mutationInterceptionInfo, result.connection);
5888
+ }
5165
5889
  if (oldQueryNode !== queryNode) {
5166
5890
  }
5167
- return result;
5891
+ return result.result;
5168
5892
  }, "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)) ?? [];
5893
+ return task();
5894
+ }
5895
+ proceedQueryWithKyselyInterceptors(queryNode, parameters) {
5896
+ let proceed = /* @__PURE__ */ __name((q) => this.proceedQuery(q, parameters), "proceed");
5897
+ const hooks = [];
5898
+ for (const plugin of this.client.$options.plugins ?? []) {
5899
+ if (plugin.onKyselyQuery) {
5900
+ hooks.push(plugin.onKyselyQuery.bind(plugin));
5901
+ }
5902
+ }
5177
5903
  for (const hook of hooks) {
5178
5904
  const _proceed = proceed;
5179
- proceed = /* @__PURE__ */ __name((query) => {
5180
- return hook({
5905
+ proceed = /* @__PURE__ */ __name(async (query) => {
5906
+ let connection;
5907
+ const _p = /* @__PURE__ */ __name(async (q) => {
5908
+ const r = await _proceed(q);
5909
+ connection = r.connection;
5910
+ return r.result;
5911
+ }, "_p");
5912
+ const hookResult = await hook({
5181
5913
  client: this.client,
5182
5914
  schema: this.client.$schema,
5183
5915
  kysely: this.kysely,
5184
5916
  query,
5185
- proceed: _proceed,
5186
- transaction: makeTx(_proceed)
5917
+ proceed: _p
5187
5918
  });
5919
+ return {
5920
+ result: hookResult,
5921
+ connection
5922
+ };
5188
5923
  }, "proceed");
5189
5924
  }
5190
5925
  return proceed(queryNode);
5191
5926
  }
5192
- async proceedQuery(query, queryId) {
5927
+ async proceedQuery(query, parameters) {
5193
5928
  const finalQuery = this.nameMapper.transformNode(query);
5194
- const compiled = this.compileQuery(finalQuery);
5929
+ let compiled = this.compileQuery(finalQuery);
5930
+ if (parameters) {
5931
+ compiled = {
5932
+ ...compiled,
5933
+ parameters
5934
+ };
5935
+ }
5195
5936
  try {
5196
- return this.driver.txConnection ? await super.withConnectionProvider(new SingleConnectionProvider(this.driver.txConnection)).executeQuery(compiled, queryId) : await super.executeQuery(compiled, queryId);
5937
+ return await this.provideConnection(async (connection) => {
5938
+ const result = await connection.executeQuery(compiled);
5939
+ return {
5940
+ result,
5941
+ connection
5942
+ };
5943
+ });
5197
5944
  } catch (err) {
5198
- throw new QueryError(`Failed to execute query: ${err}, sql: ${compiled.sql}, parameters: ${compiled.parameters}`);
5945
+ let message = `Failed to execute query: ${err}, sql: ${compiled.sql}`;
5946
+ if (this.options.debug) {
5947
+ message += `, parameters:
5948
+ ${compiled.parameters.map((p) => inspect2(p)).join("\n")}`;
5949
+ }
5950
+ throw new QueryError(message, err);
5199
5951
  }
5200
5952
  }
5201
5953
  isMutationNode(queryNode) {
@@ -5223,30 +5975,15 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends DefaultQueryExe
5223
5975
  return new _ZenStackQueryExecutor(this.client, this.driver, this.compiler, this.adapter, this.connectionProvider, []);
5224
5976
  }
5225
5977
  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
- }
5978
+ const newExecutor = new _ZenStackQueryExecutor(this.client, this.driver, this.compiler, this.adapter, connectionProvider);
5979
+ newExecutor.client = this.client.withExecutor(newExecutor);
5980
+ return newExecutor;
5244
5981
  }
5245
5982
  get hasMutationHooks() {
5246
5983
  return this.client.$options.plugins?.some((plugin) => plugin.beforeEntityMutation || plugin.afterEntityMutation);
5247
5984
  }
5248
5985
  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) => {
5986
+ 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
5987
  if (node.from.froms.length !== 1) {
5251
5988
  throw new InternalError(`Delete query must have exactly one from table`);
5252
5989
  }
@@ -5262,7 +5999,7 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends DefaultQueryExe
5262
5999
  const result = {
5263
6000
  intercept: false
5264
6001
  };
5265
- const { action, where } = match15(queryNode).when(InsertQueryNode2.is, () => ({
6002
+ const { action, where } = match16(queryNode).when(InsertQueryNode2.is, () => ({
5266
6003
  action: "create",
5267
6004
  where: void 0
5268
6005
  })).when(UpdateQueryNode2.is, (node) => ({
@@ -5282,14 +6019,13 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends DefaultQueryExe
5282
6019
  queryNode
5283
6020
  });
5284
6021
  result.intercept ||= filterResult.intercept;
5285
- result.useTransactionForMutation ||= filterResult.useTransactionForMutation;
5286
6022
  result.loadBeforeMutationEntity ||= filterResult.loadBeforeMutationEntity;
5287
6023
  result.loadAfterMutationEntity ||= filterResult.loadAfterMutationEntity;
5288
6024
  }
5289
6025
  }
5290
6026
  let beforeMutationEntities;
5291
6027
  if (result.loadBeforeMutationEntity && (UpdateQueryNode2.is(queryNode) || DeleteQueryNode2.is(queryNode))) {
5292
- beforeMutationEntities = await this.loadEntities(this.kysely, mutationModel, where);
6028
+ beforeMutationEntities = await this.loadEntities(mutationModel, where);
5293
6029
  }
5294
6030
  return {
5295
6031
  ...result,
@@ -5302,16 +6038,16 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends DefaultQueryExe
5302
6038
  return void 0;
5303
6039
  }
5304
6040
  }
5305
- callBeforeMutationHooks(queryNode, mutationInterceptionInfo) {
6041
+ async callBeforeMutationHooks(queryNode, mutationInterceptionInfo) {
5306
6042
  if (!mutationInterceptionInfo?.intercept) {
5307
6043
  return;
5308
6044
  }
5309
6045
  if (this.options.plugins) {
6046
+ const mutationModel = this.getMutationModel(queryNode);
5310
6047
  for (const plugin of this.options.plugins) {
5311
6048
  if (plugin.beforeEntityMutation) {
5312
- plugin.beforeEntityMutation({
5313
- // context: this.queryContext,
5314
- model: this.getMutationModel(queryNode),
6049
+ await plugin.beforeEntityMutation({
6050
+ model: mutationModel,
5315
6051
  action: mutationInterceptionInfo.action,
5316
6052
  queryNode,
5317
6053
  entities: mutationInterceptionInfo.beforeMutationEntities
@@ -5320,44 +6056,59 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends DefaultQueryExe
5320
6056
  }
5321
6057
  }
5322
6058
  }
5323
- async callAfterQueryInterceptionFilters(queryResult, queryNode, mutationInterceptionInfo) {
6059
+ async callAfterMutationHooks(queryResult, queryNode, mutationInterceptionInfo, connection) {
5324
6060
  if (!mutationInterceptionInfo?.intercept) {
5325
6061
  return;
5326
6062
  }
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),
6063
+ const hooks = [];
6064
+ for (const plugin of this.options.plugins ?? []) {
6065
+ if (plugin.afterEntityMutation) {
6066
+ hooks.push(plugin.afterEntityMutation.bind(plugin));
6067
+ }
6068
+ }
6069
+ if (hooks.length === 0) {
6070
+ return;
6071
+ }
6072
+ const mutationModel = this.getMutationModel(queryNode);
6073
+ const inTransaction = this.driver.isTransactionConnection(connection);
6074
+ for (const hook of hooks) {
6075
+ let afterMutationEntities = void 0;
6076
+ if (mutationInterceptionInfo.loadAfterMutationEntity) {
6077
+ if (InsertQueryNode2.is(queryNode) || UpdateQueryNode2.is(queryNode)) {
6078
+ afterMutationEntities = queryResult.rows;
6079
+ }
6080
+ }
6081
+ const action = /* @__PURE__ */ __name(async () => {
6082
+ try {
6083
+ await hook({
6084
+ model: mutationModel,
5341
6085
  action: mutationInterceptionInfo.action,
5342
6086
  queryNode,
5343
6087
  beforeMutationEntities: mutationInterceptionInfo.beforeMutationEntities,
5344
6088
  afterMutationEntities
5345
6089
  });
6090
+ } catch (err) {
6091
+ console.error(`Error in afterEntityMutation hook for model "${mutationModel}": ${err}`);
5346
6092
  }
6093
+ }, "action");
6094
+ if (inTransaction) {
6095
+ this.driver.registerTransactionCommitCallback(connection, action);
6096
+ } else {
6097
+ await action();
5347
6098
  }
5348
6099
  }
5349
6100
  }
5350
- async loadEntities(kysely, model, where) {
5351
- const selectQuery = kysely.selectFrom(model).selectAll();
6101
+ async loadEntities(model, where) {
6102
+ const selectQuery = this.kysely.selectFrom(model).selectAll();
5352
6103
  let selectQueryNode = selectQuery.toOperationNode();
5353
6104
  selectQueryNode = {
5354
6105
  ...selectQueryNode,
5355
6106
  where: this.andNodes(selectQueryNode.where, where)
5356
6107
  };
5357
- const compiled = kysely.getExecutor().compileQuery(selectQueryNode, {
6108
+ const compiled = this.compileQuery(selectQueryNode);
6109
+ const result = await this.executeQuery(compiled, {
5358
6110
  queryId: `zenstack-${nanoid2()}`
5359
6111
  });
5360
- const result = await kysely.executeQuery(compiled);
5361
6112
  return result.rows;
5362
6113
  }
5363
6114
  andNodes(condition1, condition2) {
@@ -5386,9 +6137,9 @@ __export(functions_exports, {
5386
6137
  search: () => search,
5387
6138
  startsWith: () => startsWith
5388
6139
  });
5389
- 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 { invariant as invariant9, lowerCaseFirst, upperCaseFirst } from "@zenstackhq/common-helpers";
6141
+ import { sql as sql7, ValueNode as ValueNode4 } from "kysely";
6142
+ import { match as match17 } from "ts-pattern";
5392
6143
  var contains = /* @__PURE__ */ __name((eb, args) => {
5393
6144
  const [field, search2, caseInsensitive = false] = args;
5394
6145
  if (!field) {
@@ -5398,9 +6149,9 @@ var contains = /* @__PURE__ */ __name((eb, args) => {
5398
6149
  throw new Error('"search" parameter is required');
5399
6150
  }
5400
6151
  const searchExpr = eb.fn("CONCAT", [
5401
- sql8.lit("%"),
6152
+ sql7.lit("%"),
5402
6153
  search2,
5403
- sql8.lit("%")
6154
+ sql7.lit("%")
5404
6155
  ]);
5405
6156
  return eb(field, caseInsensitive ? "ilike" : "like", searchExpr);
5406
6157
  }, "contains");
@@ -5417,7 +6168,7 @@ var startsWith = /* @__PURE__ */ __name((eb, args) => {
5417
6168
  }
5418
6169
  return eb(field, "like", eb.fn("CONCAT", [
5419
6170
  search2,
5420
- sql8.lit("%")
6171
+ sql7.lit("%")
5421
6172
  ]));
5422
6173
  }, "startsWith");
5423
6174
  var endsWith = /* @__PURE__ */ __name((eb, args) => {
@@ -5429,7 +6180,7 @@ var endsWith = /* @__PURE__ */ __name((eb, args) => {
5429
6180
  throw new Error('"search" parameter is required');
5430
6181
  }
5431
6182
  return eb(field, "like", eb.fn("CONCAT", [
5432
- sql8.lit("%"),
6183
+ sql7.lit("%"),
5433
6184
  search2
5434
6185
  ]));
5435
6186
  }, "endsWith");
@@ -5470,10 +6221,10 @@ var isEmpty = /* @__PURE__ */ __name((eb, args, { dialect }) => {
5470
6221
  if (!field) {
5471
6222
  throw new Error('"field" parameter is required');
5472
6223
  }
5473
- return eb(dialect.buildArrayLength(eb, field), "=", sql8.lit(0));
6224
+ return eb(dialect.buildArrayLength(eb, field), "=", sql7.lit(0));
5474
6225
  }, "isEmpty");
5475
6226
  var now = /* @__PURE__ */ __name((eb, _args, { dialect }) => {
5476
- return match16(dialect.provider).with("postgresql", () => eb.fn("now")).with("sqlite", () => sql8.raw("CURRENT_TIMESTAMP")).exhaustive();
6227
+ return match17(dialect.provider).with("postgresql", () => eb.fn("now")).with("sqlite", () => sql7.raw("CURRENT_TIMESTAMP")).exhaustive();
5477
6228
  }, "now");
5478
6229
  var currentModel = /* @__PURE__ */ __name((_eb, args, { model }) => {
5479
6230
  let result = model;
@@ -5481,7 +6232,7 @@ var currentModel = /* @__PURE__ */ __name((_eb, args, { model }) => {
5481
6232
  if (casing) {
5482
6233
  result = processCasing(casing, result, model);
5483
6234
  }
5484
- return sql8.lit(result);
6235
+ return sql7.lit(result);
5485
6236
  }, "currentModel");
5486
6237
  var currentOperation = /* @__PURE__ */ __name((_eb, args, { operation }) => {
5487
6238
  let result = operation;
@@ -5489,12 +6240,12 @@ var currentOperation = /* @__PURE__ */ __name((_eb, args, { operation }) => {
5489
6240
  if (casing) {
5490
6241
  result = processCasing(casing, result, operation);
5491
6242
  }
5492
- return sql8.lit(result);
6243
+ return sql7.lit(result);
5493
6244
  }, "currentOperation");
5494
6245
  function processCasing(casing, result, model) {
5495
6246
  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(() => {
6247
+ invariant9(ValueNode4.is(opNode) && typeof opNode.value === "string", '"casting" parameter must be a string value');
6248
+ 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
6249
  throw new Error(`Invalid casing value: ${opNode.value}. Must be "original", "upper", "lower", "capitalize", or "uncapitalize".`);
5499
6250
  });
5500
6251
  return result;
@@ -5502,9 +6253,9 @@ function processCasing(casing, result, model) {
5502
6253
  __name(processCasing, "processCasing");
5503
6254
 
5504
6255
  // src/client/helpers/schema-db-pusher.ts
5505
- import { sql as sql9 } from "kysely";
5506
- import invariant9 from "tiny-invariant";
5507
- import { match as match17 } from "ts-pattern";
6256
+ import { invariant as invariant10 } from "@zenstackhq/common-helpers";
6257
+ import { sql as sql8 } from "kysely";
6258
+ import { match as match18 } from "ts-pattern";
5508
6259
  var SchemaDbPusher = class {
5509
6260
  static {
5510
6261
  __name(this, "SchemaDbPusher");
@@ -5535,14 +6286,17 @@ var SchemaDbPusher = class {
5535
6286
  for (const [fieldName, fieldDef] of Object.entries(modelDef.fields)) {
5536
6287
  if (fieldDef.relation) {
5537
6288
  table = this.addForeignKeyConstraint(table, model, fieldName, fieldDef);
5538
- } else {
6289
+ } else if (!this.isComputedField(fieldDef)) {
5539
6290
  table = this.createModelField(table, fieldName, fieldDef, modelDef);
5540
6291
  }
5541
6292
  }
5542
6293
  table = this.addPrimaryKeyConstraint(table, model, modelDef);
5543
- table = this.addUniqueConstraint(table, modelDef);
6294
+ table = this.addUniqueConstraint(table, model, modelDef);
5544
6295
  return table;
5545
6296
  }
6297
+ isComputedField(fieldDef) {
6298
+ return fieldDef.attributes?.some((a) => a.name === "@computed");
6299
+ }
5546
6300
  addPrimaryKeyConstraint(table, model, modelDef) {
5547
6301
  if (modelDef.idFields.length === 1) {
5548
6302
  if (Object.values(modelDef.fields).some((f) => f.id)) {
@@ -5554,16 +6308,19 @@ var SchemaDbPusher = class {
5554
6308
  }
5555
6309
  return table;
5556
6310
  }
5557
- addUniqueConstraint(table, modelDef) {
6311
+ addUniqueConstraint(table, model, modelDef) {
5558
6312
  for (const [key, value] of Object.entries(modelDef.uniqueFields)) {
5559
- invariant9(typeof value === "object", "expecting an object");
6313
+ invariant10(typeof value === "object", "expecting an object");
5560
6314
  if ("type" in value) {
5561
6315
  const fieldDef = modelDef.fields[key];
5562
6316
  if (fieldDef.unique) {
5563
6317
  continue;
5564
6318
  }
6319
+ table = table.addUniqueConstraint(`unique_${model}_${key}`, [
6320
+ key
6321
+ ]);
5565
6322
  } else {
5566
- table = table.addUniqueConstraint(`unique_${key}`, Object.keys(value));
6323
+ table = table.addUniqueConstraint(`unique_${model}_${key}`, Object.keys(value));
5567
6324
  }
5568
6325
  }
5569
6326
  return table;
@@ -5576,7 +6333,7 @@ var SchemaDbPusher = class {
5576
6333
  if (fieldDef.default !== void 0) {
5577
6334
  if (typeof fieldDef.default === "object" && "kind" in fieldDef.default) {
5578
6335
  if (ExpressionUtils.isCall(fieldDef.default) && fieldDef.default.function === "now") {
5579
- col = col.defaultTo(sql9`CURRENT_TIMESTAMP`);
6336
+ col = col.defaultTo(sql8`CURRENT_TIMESTAMP`);
5580
6337
  }
5581
6338
  } else {
5582
6339
  col = col.defaultTo(fieldDef.default);
@@ -5596,17 +6353,17 @@ var SchemaDbPusher = class {
5596
6353
  }
5597
6354
  mapFieldType(fieldDef) {
5598
6355
  if (this.schema.enums?.[fieldDef.type]) {
5599
- return this.schema.provider.type === "postgresql" ? sql9.ref(fieldDef.type) : "text";
6356
+ return this.schema.provider.type === "postgresql" ? sql8.ref(fieldDef.type) : "text";
5600
6357
  }
5601
6358
  if (this.isAutoIncrement(fieldDef) && this.schema.provider.type === "postgresql") {
5602
6359
  return "serial";
5603
6360
  }
5604
6361
  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(() => {
6362
+ 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
6363
  throw new Error(`Unsupported field type: ${type}`);
5607
6364
  });
5608
6365
  if (fieldDef.array) {
5609
- return sql9.raw(`${result}[]`);
6366
+ return sql8.raw(`${result}[]`);
5610
6367
  } else {
5611
6368
  return result;
5612
6369
  }
@@ -5615,7 +6372,7 @@ var SchemaDbPusher = class {
5615
6372
  return fieldDef.default && ExpressionUtils.isCall(fieldDef.default) && fieldDef.default.function === "autoincrement";
5616
6373
  }
5617
6374
  addForeignKeyConstraint(table, model, fieldName, fieldDef) {
5618
- invariant9(fieldDef.relation, "field must be a relation");
6375
+ invariant10(fieldDef.relation, "field must be a relation");
5619
6376
  if (!fieldDef.relation.fields || !fieldDef.relation.references) {
5620
6377
  return table;
5621
6378
  }
@@ -5631,16 +6388,16 @@ var SchemaDbPusher = class {
5631
6388
  return table;
5632
6389
  }
5633
6390
  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();
6391
+ return match18(action).with("SetNull", () => "set null").with("Cascade", () => "cascade").with("Restrict", () => "restrict").with("NoAction", () => "no action").with("SetDefault", () => "set default").exhaustive();
5635
6392
  }
5636
6393
  };
5637
6394
 
5638
6395
  // src/client/promise.ts
5639
- function createDeferredPromise(callback) {
6396
+ function createZenStackPromise(callback) {
5640
6397
  let promise;
5641
- const cb = /* @__PURE__ */ __name(() => {
6398
+ const cb = /* @__PURE__ */ __name((txClient) => {
5642
6399
  try {
5643
- return promise ??= valueToPromise(callback());
6400
+ return promise ??= valueToPromise(callback(txClient));
5644
6401
  } catch (err) {
5645
6402
  return Promise.reject(err);
5646
6403
  }
@@ -5655,10 +6412,11 @@ function createDeferredPromise(callback) {
5655
6412
  finally(onFinally) {
5656
6413
  return cb().finally(onFinally);
5657
6414
  },
6415
+ cb,
5658
6416
  [Symbol.toStringTag]: "ZenStackPromise"
5659
6417
  };
5660
6418
  }
5661
- __name(createDeferredPromise, "createDeferredPromise");
6419
+ __name(createZenStackPromise, "createZenStackPromise");
5662
6420
  function valueToPromise(thing) {
5663
6421
  if (typeof thing === "object" && typeof thing?.then === "function") {
5664
6422
  return thing;
@@ -5669,9 +6427,9 @@ function valueToPromise(thing) {
5669
6427
  __name(valueToPromise, "valueToPromise");
5670
6428
 
5671
6429
  // src/client/result-processor.ts
6430
+ import { invariant as invariant11 } from "@zenstackhq/common-helpers";
5672
6431
  import Decimal2 from "decimal.js";
5673
- import invariant10 from "tiny-invariant";
5674
- import { match as match18 } from "ts-pattern";
6432
+ import { match as match19 } from "ts-pattern";
5675
6433
  var ResultProcessor = class {
5676
6434
  static {
5677
6435
  __name(this, "ResultProcessor");
@@ -5705,6 +6463,21 @@ var ResultProcessor = class {
5705
6463
  data[key] = typeof value === "string" ? JSON.parse(value) : value;
5706
6464
  continue;
5707
6465
  }
6466
+ if (key.startsWith(DELEGATE_JOINED_FIELD_PREFIX)) {
6467
+ if (value) {
6468
+ const subRow = this.transformJson(value);
6469
+ const subModel = key.slice(DELEGATE_JOINED_FIELD_PREFIX.length);
6470
+ const idValues = getIdValues(this.schema, subModel, subRow);
6471
+ if (Object.values(idValues).some((v) => v === null || v === void 0)) {
6472
+ delete data[key];
6473
+ continue;
6474
+ }
6475
+ const processedSubRow = this.processRow(subRow, subModel);
6476
+ Object.assign(data, processedSubRow);
6477
+ }
6478
+ delete data[key];
6479
+ continue;
6480
+ }
5708
6481
  const fieldDef = getField(this.schema, model, key);
5709
6482
  if (!fieldDef) {
5710
6483
  continue;
@@ -5744,20 +6517,24 @@ var ResultProcessor = class {
5744
6517
  return this.doProcessResult(relationData, fieldDef.type);
5745
6518
  }
5746
6519
  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);
6520
+ if (this.schema.typeDefs && type in this.schema.typeDefs) {
6521
+ return this.transformJson(value);
6522
+ } else {
6523
+ 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);
6524
+ }
5748
6525
  }
5749
6526
  transformDecimal(value) {
5750
6527
  if (value instanceof Decimal2) {
5751
6528
  return value;
5752
6529
  }
5753
- invariant10(typeof value === "string" || typeof value === "number" || value instanceof Decimal2, `Expected string, number or Decimal, got ${typeof value}`);
6530
+ invariant11(typeof value === "string" || typeof value === "number" || value instanceof Decimal2, `Expected string, number or Decimal, got ${typeof value}`);
5754
6531
  return new Decimal2(value);
5755
6532
  }
5756
6533
  transformBigInt(value) {
5757
6534
  if (typeof value === "bigint") {
5758
6535
  return value;
5759
6536
  }
5760
- invariant10(typeof value === "string" || typeof value === "number", `Expected string or number, got ${typeof value}`);
6537
+ invariant11(typeof value === "string" || typeof value === "number", `Expected string or number, got ${typeof value}`);
5761
6538
  return BigInt(value);
5762
6539
  }
5763
6540
  transformBoolean(value) {
@@ -5776,6 +6553,9 @@ var ResultProcessor = class {
5776
6553
  return Buffer.isBuffer(value) ? Uint8Array.from(value) : value;
5777
6554
  }
5778
6555
  fixReversedResult(data, model, args) {
6556
+ if (!data) {
6557
+ return;
6558
+ }
5779
6559
  if (Array.isArray(data) && typeof args === "object" && args && args.take !== void 0 && args.take < 0) {
5780
6560
  data.reverse();
5781
6561
  }
@@ -5789,13 +6569,19 @@ var ResultProcessor = class {
5789
6569
  continue;
5790
6570
  }
5791
6571
  const fieldDef = getField(this.schema, model, field);
5792
- if (!fieldDef?.relation) {
6572
+ if (!fieldDef || !fieldDef.relation || !fieldDef.array) {
5793
6573
  continue;
5794
6574
  }
5795
6575
  this.fixReversedResult(row[field], fieldDef.type, value);
5796
6576
  }
5797
6577
  }
5798
6578
  }
6579
+ transformJson(value) {
6580
+ return match19(this.schema.provider.type).with("sqlite", () => {
6581
+ invariant11(typeof value === "string", "Expected string, got " + typeof value);
6582
+ return JSON.parse(value);
6583
+ }).otherwise(() => value);
6584
+ }
5799
6585
  };
5800
6586
 
5801
6587
  // src/client/client-impl.ts
@@ -5814,7 +6600,7 @@ var ClientImpl = class _ClientImpl {
5814
6600
  $schema;
5815
6601
  kyselyProps;
5816
6602
  auth;
5817
- constructor(schema, options, baseClient) {
6603
+ constructor(schema, options, baseClient, executor) {
5818
6604
  this.schema = schema;
5819
6605
  this.options = options;
5820
6606
  this.$schema = schema;
@@ -5826,24 +6612,23 @@ var ClientImpl = class _ClientImpl {
5826
6612
  if (baseClient) {
5827
6613
  this.kyselyProps = {
5828
6614
  ...baseClient.kyselyProps,
5829
- executor: new ZenStackQueryExecutor(this, baseClient.kyselyProps.driver, baseClient.kyselyProps.dialect.createQueryCompiler(), baseClient.kyselyProps.dialect.createAdapter(), new DefaultConnectionProvider(baseClient.kyselyProps.driver))
6615
+ executor: executor ?? new ZenStackQueryExecutor(this, baseClient.kyselyProps.driver, baseClient.kyselyProps.dialect.createQueryCompiler(), baseClient.kyselyProps.dialect.createAdapter(), new DefaultConnectionProvider(baseClient.kyselyProps.driver))
5830
6616
  };
5831
6617
  this.kyselyRaw = baseClient.kyselyRaw;
6618
+ this.auth = baseClient.auth;
5832
6619
  } 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();
6620
+ const driver = new ZenStackDriver(options.dialect.createDriver(), new Log(this.$options.log ?? []));
6621
+ const compiler = options.dialect.createQueryCompiler();
6622
+ const adapter = options.dialect.createAdapter();
5837
6623
  const connectionProvider = new DefaultConnectionProvider(driver);
5838
- const executor = new ZenStackQueryExecutor(this, driver, compiler, adapter, connectionProvider);
5839
6624
  this.kyselyProps = {
5840
6625
  config: {
5841
- dialect,
6626
+ dialect: options.dialect,
5842
6627
  log: this.$options.log
5843
6628
  },
5844
- dialect,
6629
+ dialect: options.dialect,
5845
6630
  driver,
5846
- executor
6631
+ executor: executor ?? new ZenStackQueryExecutor(this, driver, compiler, adapter, connectionProvider)
5847
6632
  };
5848
6633
  this.kyselyRaw = new Kysely({
5849
6634
  ...this.kyselyProps,
@@ -5859,31 +6644,58 @@ var ClientImpl = class _ClientImpl {
5859
6644
  get $qbRaw() {
5860
6645
  return this.kyselyRaw;
5861
6646
  }
5862
- getKyselyDialect() {
5863
- return match19(this.schema.provider.type).with("sqlite", () => this.makeSqliteKyselyDialect()).with("postgresql", () => this.makePostgresKyselyDialect()).exhaustive();
6647
+ get isTransaction() {
6648
+ return this.kysely.isTransaction;
5864
6649
  }
5865
- makePostgresKyselyDialect() {
5866
- const { dialectConfigProvider } = this.schema.provider;
5867
- const mergedConfig = {
5868
- ...dialectConfigProvider(),
5869
- ...this.options?.dialectConfig
5870
- };
5871
- return new PostgresDialect(mergedConfig);
6650
+ /**
6651
+ * Create a new client with a new query executor.
6652
+ */
6653
+ withExecutor(executor) {
6654
+ return new _ClientImpl(this.schema, this.$options, this, executor);
5872
6655
  }
5873
- makeSqliteKyselyDialect() {
5874
- const { dialectConfigProvider } = this.schema.provider;
5875
- const mergedConfig = {
5876
- ...dialectConfigProvider(),
5877
- ...this.options?.dialectConfig
5878
- };
5879
- return new SqliteDialect(mergedConfig);
6656
+ // implementation
6657
+ async $transaction(input, options) {
6658
+ 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");
6659
+ if (typeof input === "function") {
6660
+ return this.interactiveTransaction(input, options);
6661
+ } else {
6662
+ return this.sequentialTransaction(input, options);
6663
+ }
6664
+ }
6665
+ async interactiveTransaction(callback, options) {
6666
+ if (this.kysely.isTransaction) {
6667
+ return callback(this);
6668
+ } else {
6669
+ let txBuilder = this.kysely.transaction();
6670
+ if (options?.isolationLevel) {
6671
+ txBuilder = txBuilder.setIsolationLevel(options.isolationLevel);
6672
+ }
6673
+ return txBuilder.execute((tx) => {
6674
+ const txClient = new _ClientImpl(this.schema, this.$options, this);
6675
+ txClient.kysely = tx;
6676
+ return callback(txClient);
6677
+ });
6678
+ }
5880
6679
  }
5881
- async $transaction(callback) {
5882
- return this.kysely.transaction().execute((tx) => {
5883
- const txClient = new _ClientImpl(this.schema, this.$options);
6680
+ async sequentialTransaction(arg, options) {
6681
+ const execute = /* @__PURE__ */ __name(async (tx) => {
6682
+ const txClient = new _ClientImpl(this.schema, this.$options, this);
5884
6683
  txClient.kysely = tx;
5885
- return callback(txClient);
5886
- });
6684
+ const result = [];
6685
+ for (const promise of arg) {
6686
+ result.push(await promise.cb(txClient));
6687
+ }
6688
+ return result;
6689
+ }, "execute");
6690
+ if (this.kysely.isTransaction) {
6691
+ return execute(this.kysely);
6692
+ } else {
6693
+ let txBuilder = this.kysely.transaction();
6694
+ if (options?.isolationLevel) {
6695
+ txBuilder = txBuilder.setIsolationLevel(options.isolationLevel);
6696
+ }
6697
+ return txBuilder.execute((tx) => execute(tx));
6698
+ }
5887
6699
  }
5888
6700
  get $procedures() {
5889
6701
  return Object.keys(this.$schema.procedures ?? {}).reduce((acc, name) => {
@@ -5911,12 +6723,26 @@ var ClientImpl = class _ClientImpl {
5911
6723
  await new SchemaDbPusher(this.schema, this.kysely).push();
5912
6724
  }
5913
6725
  $use(plugin) {
6726
+ const newPlugins = [
6727
+ ...this.$options.plugins ?? [],
6728
+ plugin
6729
+ ];
5914
6730
  const newOptions = {
5915
6731
  ...this.options,
5916
- plugins: [
5917
- ...this.options?.plugins ?? [],
5918
- plugin
5919
- ]
6732
+ plugins: newPlugins
6733
+ };
6734
+ return new _ClientImpl(this.schema, newOptions, this);
6735
+ }
6736
+ $unuse(pluginId) {
6737
+ const newPlugins = [];
6738
+ for (const plugin of this.options.plugins ?? []) {
6739
+ if (plugin.id !== pluginId) {
6740
+ newPlugins.push(plugin);
6741
+ }
6742
+ }
6743
+ const newOptions = {
6744
+ ...this.options,
6745
+ plugins: newPlugins
5920
6746
  };
5921
6747
  return new _ClientImpl(this.schema, newOptions, this);
5922
6748
  }
@@ -5938,6 +6764,39 @@ var ClientImpl = class _ClientImpl {
5938
6764
  get $auth() {
5939
6765
  return this.auth;
5940
6766
  }
6767
+ $executeRaw(query, ...values) {
6768
+ return createZenStackPromise(async () => {
6769
+ const result = await sql9(query, ...values).execute(this.kysely);
6770
+ return Number(result.numAffectedRows ?? 0);
6771
+ });
6772
+ }
6773
+ $executeRawUnsafe(query, ...values) {
6774
+ return createZenStackPromise(async () => {
6775
+ const compiledQuery = this.createRawCompiledQuery(query, values);
6776
+ const result = await this.kysely.executeQuery(compiledQuery);
6777
+ return Number(result.numAffectedRows ?? 0);
6778
+ });
6779
+ }
6780
+ $queryRaw(query, ...values) {
6781
+ return createZenStackPromise(async () => {
6782
+ const result = await sql9(query, ...values).execute(this.kysely);
6783
+ return result.rows;
6784
+ });
6785
+ }
6786
+ $queryRawUnsafe(query, ...values) {
6787
+ return createZenStackPromise(async () => {
6788
+ const compiledQuery = this.createRawCompiledQuery(query, values);
6789
+ const result = await this.kysely.executeQuery(compiledQuery);
6790
+ return result.rows;
6791
+ });
6792
+ }
6793
+ createRawCompiledQuery(query, values) {
6794
+ const q = CompiledQuery.raw(query, values);
6795
+ return {
6796
+ ...q,
6797
+ $raw: true
6798
+ };
6799
+ }
5941
6800
  };
5942
6801
  function createClientProxy(client) {
5943
6802
  const inputValidator = new InputValidator(client.$schema);
@@ -5960,9 +6819,9 @@ function createClientProxy(client) {
5960
6819
  __name(createClientProxy, "createClientProxy");
5961
6820
  function createModelCrudHandler(client, model, inputValidator, resultProcessor) {
5962
6821
  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;
6822
+ return createZenStackPromise(async (txClient) => {
6823
+ let proceed = /* @__PURE__ */ __name(async (_args) => {
6824
+ const _handler = txClient ? handler.withClient(txClient) : handler;
5966
6825
  const r = await _handler.handle(operation, _args ?? args);
5967
6826
  if (!r && throwIfNoResult) {
5968
6827
  throw new NotFoundError(model);
@@ -5975,22 +6834,31 @@ function createModelCrudHandler(client, model, inputValidator, resultProcessor)
5975
6834
  }
5976
6835
  return result;
5977
6836
  }, "proceed");
5978
- const context = {
5979
- client,
5980
- model,
5981
- operation,
5982
- queryArgs: args
5983
- };
5984
6837
  const plugins = [
5985
6838
  ...client.$options.plugins ?? []
5986
6839
  ];
5987
6840
  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");
6841
+ if (plugin.onQuery && typeof plugin.onQuery === "object") {
6842
+ for (const [_model, modelHooks] of Object.entries(plugin.onQuery)) {
6843
+ if (_model === lowerCaseFirst2(model) || _model === "$allModels") {
6844
+ if (modelHooks && typeof modelHooks === "object") {
6845
+ for (const [op, opHooks] of Object.entries(modelHooks)) {
6846
+ if (op === operation || op === "$allOperations") {
6847
+ if (typeof opHooks === "function") {
6848
+ const _proceed = proceed;
6849
+ proceed = /* @__PURE__ */ __name(() => opHooks({
6850
+ client,
6851
+ model,
6852
+ operation,
6853
+ args,
6854
+ query: _proceed
6855
+ }), "proceed");
6856
+ }
6857
+ }
6858
+ }
6859
+ }
6860
+ }
6861
+ }
5994
6862
  }
5995
6863
  }
5996
6864
  return proceed(args);
@@ -6046,12 +6914,23 @@ function createModelCrudHandler(client, model, inputValidator, resultProcessor)
6046
6914
  return createPromise("aggregate", args, new AggregateOperationHandler(client, model, inputValidator), false);
6047
6915
  }, "aggregate"),
6048
6916
  groupBy: /* @__PURE__ */ __name((args) => {
6049
- return createPromise("groupBy", args, new GroupByeOperationHandler(client, model, inputValidator));
6917
+ return createPromise("groupBy", args, new GroupByOperationHandler(client, model, inputValidator), true);
6050
6918
  }, "groupBy")
6051
6919
  };
6052
6920
  }
6053
6921
  __name(createModelCrudHandler, "createModelCrudHandler");
6922
+
6923
+ // src/client/plugin.ts
6924
+ function definePlugin(plugin) {
6925
+ return plugin;
6926
+ }
6927
+ __name(definePlugin, "definePlugin");
6054
6928
  export {
6055
- ZenStackClient
6929
+ InputValidationError,
6930
+ InternalError,
6931
+ NotFoundError,
6932
+ QueryError,
6933
+ ZenStackClient,
6934
+ definePlugin
6056
6935
  };
6057
6936
  //# sourceMappingURL=index.js.map