@zenstackhq/runtime 3.0.0-alpha.1 → 3.0.0-alpha.11

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 (40) hide show
  1. package/dist/{contract-DguafRNB.d.cts → contract-BQGRBbOU.d.cts} +846 -734
  2. package/dist/{contract-DguafRNB.d.ts → contract-BQGRBbOU.d.ts} +846 -734
  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 +535 -343
  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 +484 -297
  14. package/dist/index.js.map +1 -1
  15. package/dist/plugins/policy.cjs +115 -104
  16. package/dist/plugins/policy.cjs.map +1 -1
  17. package/dist/plugins/policy.d.cts +2 -4
  18. package/dist/plugins/policy.d.ts +2 -4
  19. package/dist/plugins/policy.js +87 -66
  20. package/dist/plugins/policy.js.map +1 -1
  21. package/dist/schema.cjs.map +1 -1
  22. package/dist/schema.js.map +1 -1
  23. package/package.json +23 -46
  24. package/dist/client.cjs +0 -6094
  25. package/dist/client.cjs.map +0 -1
  26. package/dist/client.d.cts +0 -19
  27. package/dist/client.d.ts +0 -19
  28. package/dist/client.js +0 -6060
  29. package/dist/client.js.map +0 -1
  30. package/dist/utils/pg-utils.cjs.map +0 -1
  31. package/dist/utils/pg-utils.d.cts +0 -8
  32. package/dist/utils/pg-utils.d.ts +0 -8
  33. package/dist/utils/pg-utils.js +0 -16
  34. package/dist/utils/pg-utils.js.map +0 -1
  35. package/dist/utils/sqlite-utils.cjs +0 -55
  36. package/dist/utils/sqlite-utils.cjs.map +0 -1
  37. package/dist/utils/sqlite-utils.d.cts +0 -8
  38. package/dist/utils/sqlite-utils.d.ts +0 -8
  39. package/dist/utils/sqlite-utils.js +0 -22
  40. package/dist/utils/sqlite-utils.js.map +0 -1
package/dist/index.cjs CHANGED
@@ -31,11 +31,17 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
31
31
  // src/index.ts
32
32
  var src_exports = {};
33
33
  __export(src_exports, {
34
- ZenStackClient: () => ZenStackClient
34
+ InputValidationError: () => InputValidationError,
35
+ InternalError: () => InternalError,
36
+ NotFoundError: () => NotFoundError,
37
+ QueryError: () => QueryError,
38
+ ZenStackClient: () => ZenStackClient,
39
+ definePlugin: () => definePlugin
35
40
  });
36
41
  module.exports = __toCommonJS(src_exports);
37
42
 
38
43
  // src/client/client-impl.ts
44
+ var import_common_helpers13 = require("@zenstackhq/common-helpers");
39
45
  var import_kysely16 = require("kysely");
40
46
  var import_ts_pattern19 = require("ts-pattern");
41
47
 
@@ -44,21 +50,30 @@ var import_kysely9 = require("kysely");
44
50
  var import_ts_pattern9 = require("ts-pattern");
45
51
 
46
52
  // src/client/errors.ts
53
+ var InputValidationError = class extends Error {
54
+ static {
55
+ __name(this, "InputValidationError");
56
+ }
57
+ constructor(message, cause) {
58
+ super(message, {
59
+ cause
60
+ });
61
+ }
62
+ };
47
63
  var QueryError = class extends Error {
48
64
  static {
49
65
  __name(this, "QueryError");
50
66
  }
51
- constructor(message) {
52
- super(message);
67
+ constructor(message, cause) {
68
+ super(message, {
69
+ cause
70
+ });
53
71
  }
54
72
  };
55
73
  var InternalError = class extends Error {
56
74
  static {
57
75
  __name(this, "InternalError");
58
76
  }
59
- constructor(message) {
60
- super(message);
61
- }
62
77
  };
63
78
  var NotFoundError = class extends Error {
64
79
  static {
@@ -77,7 +92,7 @@ __name(getModel, "getModel");
77
92
  function requireModel(schema, model) {
78
93
  const matchedName = Object.keys(schema.models).find((k) => k.toLowerCase() === model.toLowerCase());
79
94
  if (!matchedName) {
80
- throw new QueryError(`Model "${model}" not found`);
95
+ throw new QueryError(`Model "${model}" not found in schema`);
81
96
  }
82
97
  return schema.models[matchedName];
83
98
  }
@@ -202,7 +217,7 @@ function buildFieldRef(schema, model, field, options, eb, modelAlias) {
202
217
  computer = computedFields?.[model]?.[field];
203
218
  }
204
219
  if (!computer) {
205
- throw new QueryError(`Computed field "${field}" implementation not provided`);
220
+ throw new QueryError(`Computed field "${field}" implementation not provided for model "${model}"`);
206
221
  }
207
222
  return computer(eb);
208
223
  }
@@ -310,9 +325,10 @@ __name(safeJSONStringify, "safeJSONStringify");
310
325
 
311
326
  // src/client/crud/operations/base.ts
312
327
  var import_cuid2 = require("@paralleldrive/cuid2");
328
+ var import_common_helpers8 = require("@zenstackhq/common-helpers");
313
329
  var import_kysely8 = require("kysely");
314
330
  var import_nanoid = require("nanoid");
315
- var import_tiny_invariant7 = __toESM(require("tiny-invariant"), 1);
331
+ var import_node_util = require("util");
316
332
  var import_ts_pattern8 = require("ts-pattern");
317
333
  var import_ulid = require("ulid");
318
334
  var uuid = __toESM(require("uuid"), 1);
@@ -330,21 +346,21 @@ var RejectedByPolicyError = class extends Error {
330
346
  };
331
347
 
332
348
  // src/plugins/policy/policy-handler.ts
349
+ var import_common_helpers6 = require("@zenstackhq/common-helpers");
333
350
  var import_kysely7 = require("kysely");
334
- var import_tiny_invariant6 = __toESM(require("tiny-invariant"), 1);
335
351
  var import_ts_pattern7 = require("ts-pattern");
336
352
 
337
353
  // src/client/crud/dialects/index.ts
338
354
  var import_ts_pattern4 = require("ts-pattern");
339
355
 
340
356
  // src/client/crud/dialects/postgresql.ts
357
+ var import_common_helpers2 = require("@zenstackhq/common-helpers");
341
358
  var import_kysely2 = require("kysely");
342
- var import_tiny_invariant2 = __toESM(require("tiny-invariant"), 1);
343
359
  var import_ts_pattern2 = require("ts-pattern");
344
360
 
345
361
  // src/client/crud/dialects/base.ts
362
+ var import_common_helpers = require("@zenstackhq/common-helpers");
346
363
  var import_kysely = require("kysely");
347
- var import_tiny_invariant = __toESM(require("tiny-invariant"), 1);
348
364
  var import_ts_pattern = require("ts-pattern");
349
365
 
350
366
  // src/utils/enumerate.ts
@@ -362,7 +378,6 @@ function enumerate(x) {
362
378
  __name(enumerate, "enumerate");
363
379
 
364
380
  // src/client/crud/dialects/base.ts
365
- var import_is_plain_object = require("is-plain-object");
366
381
  var BaseCrudDialect = class {
367
382
  static {
368
383
  __name(this, "BaseCrudDialect");
@@ -373,7 +388,7 @@ var BaseCrudDialect = class {
373
388
  this.schema = schema;
374
389
  this.options = options;
375
390
  }
376
- transformPrimitive(value, _type) {
391
+ transformPrimitive(value, _type, _forArrayField) {
377
392
  return value;
378
393
  }
379
394
  buildFilter(eb, model, modelAlias, where) {
@@ -516,7 +531,7 @@ var BaseCrudDialect = class {
516
531
  if (_value === void 0) {
517
532
  continue;
518
533
  }
519
- const value = this.transformPrimitive(_value, fieldType);
534
+ const value = this.transformPrimitive(_value, fieldType, !!fieldDef.array);
520
535
  switch (key) {
521
536
  case "equals": {
522
537
  clauses.push(this.buildLiteralFilter(eb, fieldRef, fieldType, eb.val(value)));
@@ -554,13 +569,17 @@ var BaseCrudDialect = class {
554
569
  if (isEnum(this.schema, fieldDef.type)) {
555
570
  return this.buildEnumFilter(eb, modelAlias, field, fieldDef, payload);
556
571
  }
557
- return (0, import_ts_pattern.match)(fieldDef.type).with("String", () => this.buildStringFilter(eb, modelAlias, field, payload)).with(import_ts_pattern.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();
572
+ return (0, import_ts_pattern.match)(fieldDef.type).with("String", () => this.buildStringFilter(eb, modelAlias, field, payload)).with(import_ts_pattern.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)).with("Json", () => {
573
+ throw new InternalError("JSON filters are not supported yet");
574
+ }).with("Unsupported", () => {
575
+ throw new QueryError(`Unsupported field cannot be used in filters`);
576
+ }).exhaustive();
558
577
  }
559
578
  buildLiteralFilter(eb, lhs, type, rhs) {
560
- return eb(lhs, "=", rhs !== null && rhs !== void 0 ? this.transformPrimitive(rhs, type) : rhs);
579
+ return eb(lhs, "=", rhs !== null && rhs !== void 0 ? this.transformPrimitive(rhs, type, false) : rhs);
561
580
  }
562
581
  buildStandardFilter(eb, type, payload, lhs, getRhs, recurse, throwIfInvalid = false, onlyForKeys = void 0) {
563
- if (payload === null || !(0, import_is_plain_object.isPlainObject)(payload)) {
582
+ if (payload === null || !(0, import_common_helpers.isPlainObject)(payload)) {
564
583
  return {
565
584
  conditions: [
566
585
  this.buildLiteralFilter(eb, lhs, type, payload)
@@ -576,14 +595,14 @@ var BaseCrudDialect = class {
576
595
  }
577
596
  const rhs = Array.isArray(value) ? value.map(getRhs) : getRhs(value);
578
597
  const condition = (0, import_ts_pattern.match)(op).with("equals", () => rhs === null ? eb(lhs, "is", null) : eb(lhs, "=", rhs)).with("in", () => {
579
- (0, import_tiny_invariant.default)(Array.isArray(rhs), "right hand side must be an array");
598
+ (0, import_common_helpers.invariant)(Array.isArray(rhs), "right hand side must be an array");
580
599
  if (rhs.length === 0) {
581
600
  return this.false(eb);
582
601
  } else {
583
602
  return eb(lhs, "in", rhs);
584
603
  }
585
604
  }).with("notIn", () => {
586
- (0, import_tiny_invariant.default)(Array.isArray(rhs), "right hand side must be an array");
605
+ (0, import_common_helpers.invariant)(Array.isArray(rhs), "right hand side must be an array");
587
606
  if (rhs.length === 0) {
588
607
  return this.true(eb);
589
608
  } else {
@@ -644,22 +663,22 @@ var BaseCrudDialect = class {
644
663
  }
645
664
  }
646
665
  buildNumberFilter(eb, model, table, field, type, payload) {
647
- 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));
666
+ const { conditions } = this.buildStandardFilter(eb, type, payload, buildFieldRef(this.schema, model, field, this.options, eb), (value) => this.transformPrimitive(value, type, false), (value) => this.buildNumberFilter(eb, model, table, field, type, value));
648
667
  return this.and(eb, ...conditions);
649
668
  }
650
669
  buildBooleanFilter(eb, table, field, payload) {
651
- const { conditions } = this.buildStandardFilter(eb, "Boolean", payload, import_kysely.sql.ref(`${table}.${field}`), (value) => this.transformPrimitive(value, "Boolean"), (value) => this.buildBooleanFilter(eb, table, field, value), true, [
670
+ const { conditions } = this.buildStandardFilter(eb, "Boolean", payload, import_kysely.sql.ref(`${table}.${field}`), (value) => this.transformPrimitive(value, "Boolean", false), (value) => this.buildBooleanFilter(eb, table, field, value), true, [
652
671
  "equals",
653
672
  "not"
654
673
  ]);
655
674
  return this.and(eb, ...conditions);
656
675
  }
657
676
  buildDateTimeFilter(eb, table, field, payload) {
658
- const { conditions } = this.buildStandardFilter(eb, "DateTime", payload, import_kysely.sql.ref(`${table}.${field}`), (value) => this.transformPrimitive(value, "DateTime"), (value) => this.buildDateTimeFilter(eb, table, field, value), true);
677
+ const { conditions } = this.buildStandardFilter(eb, "DateTime", payload, import_kysely.sql.ref(`${table}.${field}`), (value) => this.transformPrimitive(value, "DateTime", false), (value) => this.buildDateTimeFilter(eb, table, field, value), true);
659
678
  return this.and(eb, ...conditions);
660
679
  }
661
680
  buildBytesFilter(eb, table, field, payload) {
662
- const conditions = this.buildStandardFilter(eb, "Bytes", payload, import_kysely.sql.ref(`${table}.${field}`), (value) => this.transformPrimitive(value, "Bytes"), (value) => this.buildBytesFilter(eb, table, field, value), true, [
681
+ const conditions = this.buildStandardFilter(eb, "Bytes", payload, import_kysely.sql.ref(`${table}.${field}`), (value) => this.transformPrimitive(value, "Bytes", false), (value) => this.buildBytesFilter(eb, table, field, value), true, [
663
682
  "equals",
664
683
  "in",
665
684
  "notIn",
@@ -697,9 +716,9 @@ var BaseCrudDialect = class {
697
716
  "_min",
698
717
  "_max"
699
718
  ].includes(field)) {
700
- (0, import_tiny_invariant.default)(value && typeof value === "object", `invalid orderBy value for field "${field}"`);
719
+ (0, import_common_helpers.invariant)(value && typeof value === "object", `invalid orderBy value for field "${field}"`);
701
720
  for (const [k, v] of Object.entries(value)) {
702
- (0, import_tiny_invariant.default)(v === "asc" || v === "desc", `invalid orderBy value for field "${field}"`);
721
+ (0, import_common_helpers.invariant)(v === "asc" || v === "desc", `invalid orderBy value for field "${field}"`);
703
722
  result = result.orderBy((eb) => eb.fn(field.slice(1), [
704
723
  import_kysely.sql.ref(k)
705
724
  ]), import_kysely.sql.raw(this.negateSort(v, negated)));
@@ -708,9 +727,9 @@ var BaseCrudDialect = class {
708
727
  }
709
728
  switch (field) {
710
729
  case "_count": {
711
- (0, import_tiny_invariant.default)(value && typeof value === "object", 'invalid orderBy value for field "_count"');
730
+ (0, import_common_helpers.invariant)(value && typeof value === "object", 'invalid orderBy value for field "_count"');
712
731
  for (const [k, v] of Object.entries(value)) {
713
- (0, import_tiny_invariant.default)(v === "asc" || v === "desc", `invalid orderBy value for field "${field}"`);
732
+ (0, import_common_helpers.invariant)(v === "asc" || v === "desc", `invalid orderBy value for field "${field}"`);
714
733
  result = result.orderBy((eb) => eb.fn.count(import_kysely.sql.ref(k)), import_kysely.sql.raw(this.negateSort(v, negated)));
715
734
  }
716
735
  continue;
@@ -732,7 +751,7 @@ var BaseCrudDialect = class {
732
751
  throw new QueryError(`invalid orderBy value for field "${field}"`);
733
752
  }
734
753
  if ("_count" in value) {
735
- (0, import_tiny_invariant.default)(value._count === "asc" || value._count === "desc", 'invalid orderBy value for field "_count"');
754
+ (0, import_common_helpers.invariant)(value._count === "asc" || value._count === "desc", 'invalid orderBy value for field "_count"');
736
755
  const sort = this.negateSort(value._count, negated);
737
756
  result = result.orderBy((eb) => {
738
757
  let subQuery = eb.selectFrom(relationModel);
@@ -758,10 +777,10 @@ var BaseCrudDialect = class {
758
777
  return negated ? sort === "asc" ? "desc" : "asc" : sort;
759
778
  }
760
779
  true(eb) {
761
- return eb.lit(this.transformPrimitive(true, "Boolean"));
780
+ return eb.lit(this.transformPrimitive(true, "Boolean", false));
762
781
  }
763
782
  false(eb) {
764
- return eb.lit(this.transformPrimitive(false, "Boolean"));
783
+ return eb.lit(this.transformPrimitive(false, "Boolean", false));
765
784
  }
766
785
  isTrue(expression) {
767
786
  const node = expression.toOperationNode();
@@ -810,14 +829,18 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
810
829
  get provider() {
811
830
  return "postgresql";
812
831
  }
813
- transformPrimitive(value, type) {
832
+ transformPrimitive(value, type, forArrayField) {
814
833
  if (value === void 0) {
815
834
  return value;
816
835
  }
817
836
  if (Array.isArray(value)) {
818
- return value.map((v) => this.transformPrimitive(v, type));
837
+ if (type === "Json" && !forArrayField) {
838
+ return JSON.stringify(value);
839
+ } else {
840
+ return value.map((v) => this.transformPrimitive(v, type, false));
841
+ }
819
842
  } else {
820
- return (0, import_ts_pattern2.match)(type).with("DateTime", () => value instanceof Date ? value : typeof value === "string" ? new Date(value) : value).otherwise(() => value);
843
+ return (0, import_ts_pattern2.match)(type).with("DateTime", () => value instanceof Date ? value : typeof value === "string" ? new Date(value) : value).with("Decimal", () => value !== null ? value.toString() : value).otherwise(() => value);
821
844
  }
822
845
  }
823
846
  buildRelationSelection(query, model, relationField, parentAlias, payload) {
@@ -850,8 +873,8 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
850
873
  if (m2m) {
851
874
  const parentIds = getIdFields(this.schema, model);
852
875
  const relationIds = getIdFields(this.schema, relationModel);
853
- (0, import_tiny_invariant2.default)(parentIds.length === 1, "many-to-many relation must have exactly one id field");
854
- (0, import_tiny_invariant2.default)(relationIds.length === 1, "many-to-many relation must have exactly one id field");
876
+ (0, import_common_helpers2.invariant)(parentIds.length === 1, "many-to-many relation must have exactly one id field");
877
+ (0, import_common_helpers2.invariant)(relationIds.length === 1, "many-to-many relation must have exactly one id field");
855
878
  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}`)));
856
879
  } else {
857
880
  const joinPairs = buildJoinPairs(this.schema, model, parentName, relationField, relationModel);
@@ -884,25 +907,33 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
884
907
  buildFieldRef(this.schema, relationModel, field, this.options, eb)
885
908
  ]).flatMap((v) => v));
886
909
  } else if (payload.select) {
887
- objArgs.push(...Object.entries(payload.select).filter(([, value]) => value).map(([field]) => [
888
- import_kysely2.sql.lit(field),
889
- buildFieldRef(this.schema, relationModel, field, this.options, eb)
890
- ]).flatMap((v) => v));
910
+ objArgs.push(...Object.entries(payload.select).filter(([, value]) => value).map(([field]) => {
911
+ const fieldDef = requireField(this.schema, relationModel, field);
912
+ const fieldValue = fieldDef.relation ? eb.ref(`${parentName}$${relationField}$${field}.$j`) : buildFieldRef(this.schema, relationModel, field, this.options, eb);
913
+ return [
914
+ import_kysely2.sql.lit(field),
915
+ fieldValue
916
+ ];
917
+ }).flatMap((v) => v));
891
918
  }
892
919
  if (typeof payload === "object" && payload.include && typeof payload.include === "object") {
893
920
  objArgs.push(...Object.entries(payload.include).filter(([, value]) => value).map(([field]) => [
894
921
  import_kysely2.sql.lit(field),
922
+ // reference the synthesized JSON field
895
923
  eb.ref(`${parentName}$${relationField}$${field}.$j`)
896
924
  ]).flatMap((v) => v));
897
925
  }
898
926
  return objArgs;
899
927
  }
900
- buildRelationJoins(model, relationField, qb, payload, parentName) {
928
+ buildRelationJoins(relationModel, relationField, qb, payload, parentName) {
901
929
  let result = qb;
902
- if (typeof payload === "object" && payload.include && typeof payload.include === "object") {
903
- Object.entries(payload.include).filter(([, value]) => value).forEach(([field, value]) => {
904
- result = this.buildRelationJSON(model, result, field, `${parentName}$${relationField}`, value);
905
- });
930
+ if (typeof payload === "object") {
931
+ const selectInclude = payload.include ?? payload.select;
932
+ if (selectInclude && typeof selectInclude === "object") {
933
+ Object.entries(selectInclude).filter(([, value]) => value).filter(([field]) => isRelationField(this.schema, relationModel, field)).forEach(([field, value]) => {
934
+ result = this.buildRelationJSON(relationModel, result, field, `${parentName}$${relationField}`, value);
935
+ });
936
+ }
906
937
  }
907
938
  return result;
908
939
  }
@@ -945,8 +976,8 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
945
976
  };
946
977
 
947
978
  // src/client/crud/dialects/sqlite.ts
979
+ var import_common_helpers3 = require("@zenstackhq/common-helpers");
948
980
  var import_kysely3 = require("kysely");
949
- var import_tiny_invariant3 = __toESM(require("tiny-invariant"), 1);
950
981
  var import_ts_pattern3 = require("ts-pattern");
951
982
  var SqliteCrudDialect = class extends BaseCrudDialect {
952
983
  static {
@@ -955,14 +986,14 @@ var SqliteCrudDialect = class extends BaseCrudDialect {
955
986
  get provider() {
956
987
  return "sqlite";
957
988
  }
958
- transformPrimitive(value, type) {
989
+ transformPrimitive(value, type, _forArrayField) {
959
990
  if (value === void 0) {
960
991
  return value;
961
992
  }
962
993
  if (Array.isArray(value)) {
963
- return value.map((v) => this.transformPrimitive(v, type));
994
+ return value.map((v) => this.transformPrimitive(v, type, false));
964
995
  } else {
965
- return (0, import_ts_pattern3.match)(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);
996
+ return (0, import_ts_pattern3.match)(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);
966
997
  }
967
998
  }
968
999
  buildRelationSelection(query, model, relationField, parentAlias, payload) {
@@ -993,8 +1024,8 @@ var SqliteCrudDialect = class extends BaseCrudDialect {
993
1024
  if (m2m) {
994
1025
  const parentIds = getIdFields(this.schema, model);
995
1026
  const relationIds = getIdFields(this.schema, relationModel);
996
- (0, import_tiny_invariant3.default)(parentIds.length === 1, "many-to-many relation must have exactly one id field");
997
- (0, import_tiny_invariant3.default)(relationIds.length === 1, "many-to-many relation must have exactly one id field");
1027
+ (0, import_common_helpers3.invariant)(parentIds.length === 1, "many-to-many relation must have exactly one id field");
1028
+ (0, import_common_helpers3.invariant)(relationIds.length === 1, "many-to-many relation must have exactly one id field");
998
1029
  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}`)));
999
1030
  } else {
1000
1031
  const { keyPairs, ownedByModel } = getRelationForeignKeyFieldPairs(this.schema, model, relationField);
@@ -1490,12 +1521,12 @@ var ColumnCollector = class extends DefaultOperationNodeVisitor {
1490
1521
  };
1491
1522
 
1492
1523
  // src/plugins/policy/expression-transformer.ts
1524
+ var import_common_helpers5 = require("@zenstackhq/common-helpers");
1493
1525
  var import_kysely6 = require("kysely");
1494
- var import_tiny_invariant5 = __toESM(require("tiny-invariant"), 1);
1495
1526
  var import_ts_pattern6 = require("ts-pattern");
1496
1527
 
1497
1528
  // src/plugins/policy/expression-evaluator.ts
1498
- var import_tiny_invariant4 = __toESM(require("tiny-invariant"), 1);
1529
+ var import_common_helpers4 = require("@zenstackhq/common-helpers");
1499
1530
  var import_ts_pattern5 = require("ts-pattern");
1500
1531
  var ExpressionEvaluator = class {
1501
1532
  static {
@@ -1539,18 +1570,18 @@ var ExpressionEvaluator = class {
1539
1570
  const right = this.evaluate(expr2.right, context);
1540
1571
  return (0, import_ts_pattern5.match)(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", () => {
1541
1572
  const _right = right ?? [];
1542
- (0, import_tiny_invariant4.default)(Array.isArray(_right), 'expected array for "in" operator');
1573
+ (0, import_common_helpers4.invariant)(Array.isArray(_right), 'expected array for "in" operator');
1543
1574
  return _right.includes(left);
1544
1575
  }).exhaustive();
1545
1576
  }
1546
1577
  evaluateCollectionPredicate(expr2, context) {
1547
1578
  const op = expr2.op;
1548
- (0, import_tiny_invariant4.default)(op === "?" || op === "!" || op === "^", 'expected "?" or "!" or "^" operator');
1579
+ (0, import_common_helpers4.invariant)(op === "?" || op === "!" || op === "^", 'expected "?" or "!" or "^" operator');
1549
1580
  const left = this.evaluate(expr2.left, context);
1550
1581
  if (!left) {
1551
1582
  return false;
1552
1583
  }
1553
- (0, import_tiny_invariant4.default)(Array.isArray(left), "expected array");
1584
+ (0, import_common_helpers4.invariant)(Array.isArray(left), "expected array");
1554
1585
  return (0, import_ts_pattern5.match)(op).with("?", () => left.some((item) => this.evaluate(expr2.right, {
1555
1586
  ...context,
1556
1587
  thisValue: item
@@ -1567,11 +1598,11 @@ var ExpressionEvaluator = class {
1567
1598
  // src/plugins/policy/utils.ts
1568
1599
  var import_kysely5 = require("kysely");
1569
1600
  function trueNode(dialect) {
1570
- return import_kysely5.ValueNode.createImmediate(dialect.transformPrimitive(true, "Boolean"));
1601
+ return import_kysely5.ValueNode.createImmediate(dialect.transformPrimitive(true, "Boolean", false));
1571
1602
  }
1572
1603
  __name(trueNode, "trueNode");
1573
1604
  function falseNode(dialect) {
1574
- return import_kysely5.ValueNode.createImmediate(dialect.transformPrimitive(false, "Boolean"));
1605
+ return import_kysely5.ValueNode.createImmediate(dialect.transformPrimitive(false, "Boolean", false));
1575
1606
  }
1576
1607
  __name(falseNode, "falseNode");
1577
1608
  function isTrueNode(node) {
@@ -1772,20 +1803,20 @@ var ExpressionTransformer = class {
1772
1803
  return import_kysely6.BinaryOperationNode.create(left, this.transformOperator(op), right);
1773
1804
  }
1774
1805
  transformCollectionPredicate(expr2, context) {
1775
- (0, import_tiny_invariant5.default)(expr2.op === "?" || expr2.op === "!" || expr2.op === "^", 'expected "?" or "!" or "^" operator');
1806
+ (0, import_common_helpers5.invariant)(expr2.op === "?" || expr2.op === "!" || expr2.op === "^", 'expected "?" or "!" or "^" operator');
1776
1807
  if (this.isAuthCall(expr2.left) || this.isAuthMember(expr2.left)) {
1777
1808
  const value = new ExpressionEvaluator().evaluate(expr2, {
1778
1809
  auth: this.auth
1779
1810
  });
1780
1811
  return this.transformValue(value, "Boolean");
1781
1812
  }
1782
- (0, import_tiny_invariant5.default)(ExpressionUtils.isField(expr2.left) || ExpressionUtils.isMember(expr2.left), "left operand must be field or member access");
1813
+ (0, import_common_helpers5.invariant)(ExpressionUtils.isField(expr2.left) || ExpressionUtils.isMember(expr2.left), "left operand must be field or member access");
1783
1814
  let newContextModel;
1784
1815
  if (ExpressionUtils.isField(expr2.left)) {
1785
1816
  const fieldDef = requireField(this.schema, context.model, expr2.left.field);
1786
1817
  newContextModel = fieldDef.type;
1787
1818
  } else {
1788
- (0, import_tiny_invariant5.default)(ExpressionUtils.isField(expr2.left.receiver));
1819
+ (0, import_common_helpers5.invariant)(ExpressionUtils.isField(expr2.left.receiver));
1789
1820
  const fieldDef = requireField(this.schema, context.model, expr2.left.receiver.field);
1790
1821
  newContextModel = fieldDef.type;
1791
1822
  for (const member of expr2.left.members) {
@@ -1829,10 +1860,10 @@ var ExpressionTransformer = class {
1829
1860
  }
1830
1861
  }
1831
1862
  transformValue(value, type) {
1832
- return import_kysely6.ValueNode.create(this.dialect.transformPrimitive(value, type) ?? null);
1863
+ return import_kysely6.ValueNode.create(this.dialect.transformPrimitive(value, type, false) ?? null);
1833
1864
  }
1834
1865
  _unary(expr2, context) {
1835
- (0, import_tiny_invariant5.default)(expr2.op === "!", 'only "!" operator is supported');
1866
+ (0, import_common_helpers5.invariant)(expr2.op === "!", 'only "!" operator is supported');
1836
1867
  return import_kysely6.BinaryOperationNode.create(this.transform(expr2.operand, context), this.transformOperator("!="), trueNode(this.dialect));
1837
1868
  }
1838
1869
  transformOperator(op) {
@@ -1875,10 +1906,10 @@ var ExpressionTransformer = class {
1875
1906
  if (this.isAuthCall(expr2.receiver)) {
1876
1907
  return this.valueMemberAccess(this.auth, expr2, this.authType);
1877
1908
  }
1878
- (0, import_tiny_invariant5.default)(ExpressionUtils.isField(expr2.receiver), "expect receiver to be field expression");
1909
+ (0, import_common_helpers5.invariant)(ExpressionUtils.isField(expr2.receiver), "expect receiver to be field expression");
1879
1910
  const { memberFilter, memberSelect, ...restContext } = context;
1880
1911
  const receiver = this.transform(expr2.receiver, restContext);
1881
- (0, import_tiny_invariant5.default)(import_kysely6.SelectQueryNode.is(receiver), "expected receiver to be select query");
1912
+ (0, import_common_helpers5.invariant)(import_kysely6.SelectQueryNode.is(receiver), "expected receiver to be select query");
1882
1913
  const receiverField = requireField(this.schema, context.model, expr2.receiver.field);
1883
1914
  const memberFields = [];
1884
1915
  let currType = receiverField.type;
@@ -1902,7 +1933,7 @@ var ExpressionTransformer = class {
1902
1933
  thisEntity: void 0
1903
1934
  });
1904
1935
  if (currNode) {
1905
- (0, import_tiny_invariant5.default)(import_kysely6.SelectQueryNode.is(currNode), "expected select query node");
1936
+ (0, import_common_helpers5.invariant)(import_kysely6.SelectQueryNode.is(currNode), "expected select query node");
1906
1937
  currNode = {
1907
1938
  ...relation,
1908
1939
  selections: [
@@ -1919,8 +1950,8 @@ var ExpressionTransformer = class {
1919
1950
  };
1920
1951
  }
1921
1952
  } else {
1922
- (0, import_tiny_invariant5.default)(i === expr2.members.length - 1, "plain field access must be the last segment");
1923
- (0, import_tiny_invariant5.default)(!currNode, "plain field access must be the last segment");
1953
+ (0, import_common_helpers5.invariant)(i === expr2.members.length - 1, "plain field access must be the last segment");
1954
+ (0, import_common_helpers5.invariant)(!currNode, "plain field access must be the last segment");
1924
1955
  currNode = import_kysely6.ColumnNode.create(member);
1925
1956
  }
1926
1957
  }
@@ -2072,7 +2103,7 @@ var PolicyHandler = class extends import_kysely7.OperationNodeTransformer {
2072
2103
  get kysely() {
2073
2104
  return this.client.$qb;
2074
2105
  }
2075
- async handle(node, proceed, transaction) {
2106
+ async handle(node, proceed) {
2076
2107
  if (!this.isCrudQueryNode(node)) {
2077
2108
  throw new RejectedByPolicyError(void 0, "non-CRUD queries are not allowed");
2078
2109
  }
@@ -2092,27 +2123,20 @@ var PolicyHandler = class extends import_kysely7.OperationNodeTransformer {
2092
2123
  if (!mutationRequiresTransaction && !node.returning) {
2093
2124
  return proceed(this.transformNode(node));
2094
2125
  }
2095
- let readBackError = false;
2096
- const result = await transaction(async (txProceed) => {
2097
- if (import_kysely7.InsertQueryNode.is(node)) {
2098
- await this.enforcePreCreatePolicy(node, txProceed);
2099
- }
2100
- const transformedNode = this.transformNode(node);
2101
- const result2 = await txProceed(transformedNode);
2102
- if (!this.onlyReturningId(node)) {
2103
- const readBackResult = await this.processReadBack(node, result2, txProceed);
2104
- if (readBackResult.rows.length !== result2.rows.length) {
2105
- readBackError = true;
2106
- }
2107
- return readBackResult;
2108
- } else {
2109
- return result2;
2126
+ if (import_kysely7.InsertQueryNode.is(node)) {
2127
+ await this.enforcePreCreatePolicy(node, proceed);
2128
+ }
2129
+ const transformedNode = this.transformNode(node);
2130
+ const result = await proceed(transformedNode);
2131
+ if (!this.onlyReturningId(node)) {
2132
+ const readBackResult = await this.processReadBack(node, result, proceed);
2133
+ if (readBackResult.rows.length !== result.rows.length) {
2134
+ throw new RejectedByPolicyError(mutationModel, "result is not allowed to be read back");
2110
2135
  }
2111
- });
2112
- if (readBackError) {
2113
- throw new RejectedByPolicyError(mutationModel, "result is not allowed to be read back");
2136
+ return readBackResult;
2137
+ } else {
2138
+ return result;
2114
2139
  }
2115
- return result;
2116
2140
  }
2117
2141
  onlyReturningId(node) {
2118
2142
  if (!node.returning) {
@@ -2165,19 +2189,19 @@ var PolicyHandler = class extends import_kysely7.OperationNodeTransformer {
2165
2189
  }
2166
2190
  }
2167
2191
  unwrapCreateValueRow(data, model, fields) {
2168
- (0, import_tiny_invariant6.default)(data.length === fields.length, "data length must match fields length");
2192
+ (0, import_common_helpers6.invariant)(data.length === fields.length, "data length must match fields length");
2169
2193
  const result = [];
2170
2194
  for (let i = 0; i < data.length; i++) {
2171
2195
  const item = data[i];
2172
2196
  const fieldDef = requireField(this.client.$schema, model, fields[i]);
2173
2197
  if (typeof item === "object" && item && "kind" in item) {
2174
- (0, import_tiny_invariant6.default)(item.kind === "ValueNode", "expecting a ValueNode");
2198
+ (0, import_common_helpers6.invariant)(item.kind === "ValueNode", "expecting a ValueNode");
2175
2199
  result.push({
2176
- node: import_kysely7.ValueNode.create(this.dialect.transformPrimitive(item.value, fieldDef.type)),
2200
+ node: import_kysely7.ValueNode.create(this.dialect.transformPrimitive(item.value, fieldDef.type, !!fieldDef.array)),
2177
2201
  raw: item.value
2178
2202
  });
2179
2203
  } else {
2180
- const value = this.dialect.transformPrimitive(item, fieldDef.type);
2204
+ const value = this.dialect.transformPrimitive(item, fieldDef.type, !!fieldDef.array);
2181
2205
  if (Array.isArray(value)) {
2182
2206
  result.push({
2183
2207
  node: import_kysely7.RawNode.createWithSql(this.dialect.buildArrayLiteralSQL(value)),
@@ -2379,8 +2403,8 @@ var PolicyHandler = class extends import_kysely7.OperationNodeTransformer {
2379
2403
  const modelDef = requireModel(this.client.$schema, modelName);
2380
2404
  const result = [];
2381
2405
  const extractOperations = /* @__PURE__ */ __name((expr2) => {
2382
- (0, import_tiny_invariant6.default)(ExpressionUtils.isLiteral(expr2), "expecting a literal");
2383
- (0, import_tiny_invariant6.default)(typeof expr2.value === "string", "expecting a string literal");
2406
+ (0, import_common_helpers6.invariant)(ExpressionUtils.isLiteral(expr2), "expecting a literal");
2407
+ (0, import_common_helpers6.invariant)(typeof expr2.value === "string", "expecting a string literal");
2384
2408
  return expr2.value.split(",").filter((v) => !!v).map((v) => v.trim());
2385
2409
  }, "extractOperations");
2386
2410
  if (modelDef.attributes) {
@@ -2408,20 +2432,29 @@ var PolicyPlugin = class {
2408
2432
  get description() {
2409
2433
  return "Enforces access policies defined in the schema.";
2410
2434
  }
2411
- onKyselyQuery({ query, client, proceed, transaction }) {
2435
+ onKyselyQuery({
2436
+ query,
2437
+ client,
2438
+ proceed
2439
+ /*, transaction*/
2440
+ }) {
2412
2441
  const handler = new PolicyHandler(client);
2413
- return handler.handle(query, proceed, transaction);
2442
+ return handler.handle(
2443
+ query,
2444
+ proceed
2445
+ /*, transaction*/
2446
+ );
2414
2447
  }
2415
2448
  };
2416
2449
 
2417
2450
  // src/utils/clone.ts
2418
- var import_is_plain_object2 = require("is-plain-object");
2451
+ var import_common_helpers7 = require("@zenstackhq/common-helpers");
2419
2452
  function clone(value) {
2420
2453
  if (Array.isArray(value)) {
2421
2454
  return value.map((v) => clone(v));
2422
2455
  }
2423
2456
  if (typeof value === "object") {
2424
- if (!value || !(0, import_is_plain_object2.isPlainObject)(value)) {
2457
+ if (!value || !(0, import_common_helpers7.isPlainObject)(value)) {
2425
2458
  return value;
2426
2459
  }
2427
2460
  const result = {};
@@ -2531,13 +2564,13 @@ var BaseOperationHandler = class {
2531
2564
  inMemoryDistinct = distinct;
2532
2565
  }
2533
2566
  }
2534
- if (args?.select) {
2535
- query = this.buildFieldSelection(model, query, args?.select, model);
2567
+ if (args && "select" in args && args.select) {
2568
+ query = this.buildFieldSelection(model, query, args.select, model);
2536
2569
  } else {
2537
2570
  query = this.buildSelectAllScalarFields(model, query, args?.omit);
2538
2571
  }
2539
- if (args?.include) {
2540
- query = this.buildFieldSelection(model, query, args?.include, model);
2572
+ if (args && "include" in args && args.include) {
2573
+ query = this.buildFieldSelection(model, query, args.include, model);
2541
2574
  }
2542
2575
  if (args?.cursor) {
2543
2576
  query = this.buildCursorFilter(model, query, args.cursor, args.orderBy, negateOrderBy);
@@ -2550,8 +2583,13 @@ var BaseOperationHandler = class {
2550
2583
  try {
2551
2584
  result = await query.execute();
2552
2585
  } catch (err) {
2553
- const { sql: sql10, parameters } = query.compile();
2554
- throw new QueryError(`Failed to execute query: ${err}, sql: ${sql10}, parameters: ${parameters}`);
2586
+ const { sql: sql11, parameters } = query.compile();
2587
+ let message = `Failed to execute query: ${err}, sql: ${sql11}`;
2588
+ if (this.options.debug) {
2589
+ message += `, parameters:
2590
+ ${parameters.map((p) => (0, import_node_util.inspect)(p)).join("\n")}`;
2591
+ }
2592
+ throw new QueryError(message, err);
2555
2593
  }
2556
2594
  if (inMemoryDistinct) {
2557
2595
  const distinctResult = [];
@@ -2610,30 +2648,20 @@ var BaseOperationHandler = class {
2610
2648
  for (const [field, value] of Object.entries(selections.select)) {
2611
2649
  const fieldDef = requireField(this.schema, model, field);
2612
2650
  const fieldModel = fieldDef.type;
2613
- const jointTable = `${parentAlias}$${field}$count`;
2614
- const joinPairs = buildJoinPairs(this.schema, model, parentAlias, field, jointTable);
2615
- query = query.leftJoin((eb2) => {
2616
- let result = eb2.selectFrom(fieldModel).selectAll();
2617
- if (value && typeof value === "object" && "where" in value && value.where && typeof value.where === "object") {
2618
- const filter = this.dialect.buildFilter(eb2, fieldModel, fieldModel, value.where);
2619
- result = result.where(filter);
2620
- }
2621
- return result.as(jointTable);
2622
- }, (join) => {
2623
- for (const [left, right] of joinPairs) {
2624
- join = join.onRef(left, "=", right);
2625
- }
2626
- return join;
2627
- });
2628
- jsonObject[field] = this.countIdDistinct(eb, fieldDef.type, jointTable);
2651
+ const joinPairs = buildJoinPairs(this.schema, model, parentAlias, field, fieldModel);
2652
+ let fieldCountQuery = eb.selectFrom(fieldModel).select(eb.fn.countAll().as(`_count$${field}`));
2653
+ for (const [left, right] of joinPairs) {
2654
+ fieldCountQuery = fieldCountQuery.whereRef(left, "=", right);
2655
+ }
2656
+ if (value && typeof value === "object" && "where" in value && value.where && typeof value.where === "object") {
2657
+ const filter = this.dialect.buildFilter(eb, fieldModel, fieldModel, value.where);
2658
+ fieldCountQuery = fieldCountQuery.where(filter);
2659
+ }
2660
+ jsonObject[field] = fieldCountQuery;
2629
2661
  }
2630
2662
  query = query.select((eb2) => this.dialect.buildJsonObject(eb2, jsonObject).as("_count"));
2631
2663
  return query;
2632
2664
  }
2633
- countIdDistinct(eb, model, table) {
2634
- const idFields = getIdFields(this.schema, model);
2635
- return eb.fn.count(import_kysely8.sql.join(idFields.map((f) => import_kysely8.sql.ref(`${table}.${f}`)))).distinct();
2636
- }
2637
2665
  buildSelectAllScalarFields(model, query, omit) {
2638
2666
  const modelDef = this.requireModel(model);
2639
2667
  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);
@@ -2699,14 +2727,14 @@ var BaseOperationHandler = class {
2699
2727
  const fieldDef = this.requireField(model, field);
2700
2728
  if (isScalarField(this.schema, model, field) || isForeignKeyField(this.schema, model, field)) {
2701
2729
  if (fieldDef.array && value && typeof value === "object" && "set" in value && Array.isArray(value.set)) {
2702
- createFields[field] = this.dialect.transformPrimitive(value.set, fieldDef.type);
2730
+ createFields[field] = this.dialect.transformPrimitive(value.set, fieldDef.type, true);
2703
2731
  } else {
2704
- createFields[field] = this.dialect.transformPrimitive(value, fieldDef.type);
2732
+ createFields[field] = this.dialect.transformPrimitive(value, fieldDef.type, !!fieldDef.array);
2705
2733
  }
2706
2734
  } else {
2707
2735
  const subM2M = getManyToManyRelation(this.schema, model, field);
2708
2736
  if (!subM2M && fieldDef.relation?.fields && fieldDef.relation?.references) {
2709
- const fkValues = await this.processOwnedRelation(kysely, fieldDef, value);
2737
+ const fkValues = await this.processOwnedRelationForCreate(kysely, fieldDef, value);
2710
2738
  for (let i = 0; i < fieldDef.relation.fields.length; i++) {
2711
2739
  createFields[fieldDef.relation.fields[i]] = fkValues[fieldDef.relation.references[i]];
2712
2740
  }
@@ -2727,7 +2755,7 @@ var BaseOperationHandler = class {
2727
2755
  const createdEntity = await query.executeTakeFirst();
2728
2756
  if (Object.keys(postCreateRelations).length > 0) {
2729
2757
  const relationPromises = Object.entries(postCreateRelations).map(([field, subPayload]) => {
2730
- return this.processNoneOwnedRelation(kysely, model, field, subPayload, createdEntity);
2758
+ return this.processNoneOwnedRelationForCreate(kysely, model, field, subPayload, createdEntity);
2731
2759
  });
2732
2760
  await Promise.all(relationPromises);
2733
2761
  }
@@ -2741,8 +2769,8 @@ var BaseOperationHandler = class {
2741
2769
  }
2742
2770
  buildFkAssignments(model, relationField, entity) {
2743
2771
  const parentFkFields = {};
2744
- (0, import_tiny_invariant7.default)(relationField, "parentField must be defined if parentModel is defined");
2745
- (0, import_tiny_invariant7.default)(entity, "parentEntity must be defined if parentModel is defined");
2772
+ (0, import_common_helpers8.invariant)(relationField, "parentField must be defined if parentModel is defined");
2773
+ (0, import_common_helpers8.invariant)(entity, "parentEntity must be defined if parentModel is defined");
2746
2774
  const { keyPairs } = getRelationForeignKeyFieldPairs(this.schema, model, relationField);
2747
2775
  for (const pair of keyPairs) {
2748
2776
  if (!(pair.pk in entity)) {
@@ -2769,8 +2797,8 @@ var BaseOperationHandler = class {
2769
2797
  ].sort((a, b) => a.model.localeCompare(b.model));
2770
2798
  const firstIds = getIdFields(this.schema, sortedRecords[0].model);
2771
2799
  const secondIds = getIdFields(this.schema, sortedRecords[1].model);
2772
- (0, import_tiny_invariant7.default)(firstIds.length === 1, "many-to-many relation must have exactly one id field");
2773
- (0, import_tiny_invariant7.default)(secondIds.length === 1, "many-to-many relation must have exactly one id field");
2800
+ (0, import_common_helpers8.invariant)(firstIds.length === 1, "many-to-many relation must have exactly one id field");
2801
+ (0, import_common_helpers8.invariant)(secondIds.length === 1, "many-to-many relation must have exactly one id field");
2774
2802
  if (action === "connect") {
2775
2803
  const result = await kysely.insertInto(joinTable).values({
2776
2804
  A: sortedRecords[0].entity[firstIds[0]],
@@ -2787,14 +2815,14 @@ var BaseOperationHandler = class {
2787
2815
  }
2788
2816
  }
2789
2817
  resetManyToManyRelation(kysely, model, field, parentIds) {
2790
- (0, import_tiny_invariant7.default)(Object.keys(parentIds).length === 1, "parentIds must have exactly one field");
2818
+ (0, import_common_helpers8.invariant)(Object.keys(parentIds).length === 1, "parentIds must have exactly one field");
2791
2819
  const parentId = Object.values(parentIds)[0];
2792
2820
  const m2m = getManyToManyRelation(this.schema, model, field);
2793
- (0, import_tiny_invariant7.default)(m2m, "not a many-to-many relation");
2821
+ (0, import_common_helpers8.invariant)(m2m, "not a many-to-many relation");
2794
2822
  const eb = (0, import_kysely8.expressionBuilder)();
2795
2823
  return kysely.deleteFrom(m2m.joinTable).where(eb(`${m2m.joinTable}.${m2m.parentFkName}`, "=", parentId)).execute();
2796
2824
  }
2797
- async processOwnedRelation(kysely, relationField, payload) {
2825
+ async processOwnedRelationForCreate(kysely, relationField, payload) {
2798
2826
  if (!payload) {
2799
2827
  return;
2800
2828
  }
@@ -2812,7 +2840,7 @@ var BaseOperationHandler = class {
2812
2840
  }
2813
2841
  case "connect": {
2814
2842
  const referencedPkFields = relationField.relation.references;
2815
- (0, import_tiny_invariant7.default)(referencedPkFields, "relation must have fields info");
2843
+ (0, import_common_helpers8.invariant)(referencedPkFields, "relation must have fields info");
2816
2844
  const extractedFks = extractFields(subPayload, referencedPkFields);
2817
2845
  if (Object.keys(extractedFks).length === referencedPkFields.length) {
2818
2846
  result = extractedFks;
@@ -2844,21 +2872,27 @@ var BaseOperationHandler = class {
2844
2872
  }
2845
2873
  return result;
2846
2874
  }
2847
- processNoneOwnedRelation(kysely, contextModel, relationFieldName, payload, parentEntity) {
2875
+ processNoneOwnedRelationForCreate(kysely, contextModel, relationFieldName, payload, parentEntity) {
2848
2876
  const relationFieldDef = this.requireField(contextModel, relationFieldName);
2849
2877
  const relationModel = relationFieldDef.type;
2850
2878
  const tasks = [];
2879
+ const fromRelationContext = {
2880
+ model: contextModel,
2881
+ field: relationFieldName,
2882
+ ids: parentEntity
2883
+ };
2851
2884
  for (const [action, subPayload] of Object.entries(payload)) {
2852
2885
  if (!subPayload) {
2853
2886
  continue;
2854
2887
  }
2855
2888
  switch (action) {
2856
2889
  case "create": {
2857
- tasks.push(...enumerate(subPayload).map((item) => this.create(kysely, relationModel, item, {
2858
- model: contextModel,
2859
- field: relationFieldName,
2860
- ids: parentEntity
2861
- })));
2890
+ tasks.push(...enumerate(subPayload).map((item) => this.create(kysely, relationModel, item, fromRelationContext)));
2891
+ break;
2892
+ }
2893
+ case "createMany": {
2894
+ (0, import_common_helpers8.invariant)(relationFieldDef.array, "relation must be an array for createMany");
2895
+ tasks.push(this.createMany(kysely, relationModel, subPayload, false, fromRelationContext));
2862
2896
  break;
2863
2897
  }
2864
2898
  case "connect": {
@@ -2888,6 +2922,11 @@ var BaseOperationHandler = class {
2888
2922
  return Promise.all(tasks);
2889
2923
  }
2890
2924
  async createMany(kysely, model, input, returnData, fromRelation) {
2925
+ if (!input.data || Array.isArray(input.data) && input.data.length === 0) {
2926
+ return returnData ? [] : {
2927
+ count: 0
2928
+ };
2929
+ }
2891
2930
  const modelDef = this.requireModel(model);
2892
2931
  let relationKeyPairs = [];
2893
2932
  if (fromRelation) {
@@ -2901,8 +2940,8 @@ var BaseOperationHandler = class {
2901
2940
  const newItem = {};
2902
2941
  for (const [name, value] of Object.entries(item)) {
2903
2942
  const fieldDef = this.requireField(model, name);
2904
- (0, import_tiny_invariant7.default)(!fieldDef.relation, "createMany does not support relations");
2905
- newItem[name] = this.dialect.transformPrimitive(value, fieldDef.type);
2943
+ (0, import_common_helpers8.invariant)(!fieldDef.relation, "createMany does not support relations");
2944
+ newItem[name] = this.dialect.transformPrimitive(value, fieldDef.type, !!fieldDef.array);
2906
2945
  }
2907
2946
  if (fromRelation) {
2908
2947
  for (const { fk, pk } of relationKeyPairs) {
@@ -2937,7 +2976,7 @@ var BaseOperationHandler = class {
2937
2976
  values[field] = generated;
2938
2977
  }
2939
2978
  } else if (fields[field]?.updatedAt) {
2940
- values[field] = this.dialect.transformPrimitive(/* @__PURE__ */ new Date(), "DateTime");
2979
+ values[field] = this.dialect.transformPrimitive(/* @__PURE__ */ new Date(), "DateTime", false);
2941
2980
  }
2942
2981
  }
2943
2982
  }
@@ -2980,7 +3019,7 @@ var BaseOperationHandler = class {
2980
3019
  }
2981
3020
  } else {
2982
3021
  const fromRelationFieldDef = this.requireField(fromRelation.model, fromRelation.field);
2983
- (0, import_tiny_invariant7.default)(fromRelationFieldDef.relation?.opposite);
3022
+ (0, import_common_helpers8.invariant)(fromRelationFieldDef.relation?.opposite);
2984
3023
  parentWhere[fromRelationFieldDef.relation.opposite] = {
2985
3024
  some: fromRelation.ids
2986
3025
  };
@@ -3002,7 +3041,7 @@ var BaseOperationHandler = class {
3002
3041
  if (finalData === data) {
3003
3042
  finalData = clone(data);
3004
3043
  }
3005
- finalData[fieldName] = this.dialect.transformPrimitive(/* @__PURE__ */ new Date(), "DateTime");
3044
+ finalData[fieldName] = this.dialect.transformPrimitive(/* @__PURE__ */ new Date(), "DateTime", false);
3006
3045
  }
3007
3046
  }
3008
3047
  if (Object.keys(finalData).length === 0) {
@@ -3027,7 +3066,7 @@ var BaseOperationHandler = class {
3027
3066
  updateFields[field] = this.transformScalarListUpdate(model, field, fieldDef, finalData[field]);
3028
3067
  continue;
3029
3068
  }
3030
- updateFields[field] = this.dialect.transformPrimitive(finalData[field], fieldDef.type);
3069
+ updateFields[field] = this.dialect.transformPrimitive(finalData[field], fieldDef.type, !!fieldDef.array);
3031
3070
  } else {
3032
3071
  if (!allowRelationUpdate) {
3033
3072
  throw new QueryError(`Relation update not allowed for field "${field}"`);
@@ -3070,9 +3109,9 @@ var BaseOperationHandler = class {
3070
3109
  }
3071
3110
  }
3072
3111
  transformIncrementalUpdate(model, field, fieldDef, payload) {
3073
- (0, import_tiny_invariant7.default)(Object.keys(payload).length === 1, 'Only one of "set", "increment", "decrement", "multiply", or "divide" can be provided');
3112
+ (0, import_common_helpers8.invariant)(Object.keys(payload).length === 1, 'Only one of "set", "increment", "decrement", "multiply", or "divide" can be provided');
3074
3113
  const key = Object.keys(payload)[0];
3075
- const value = this.dialect.transformPrimitive(payload[key], fieldDef.type);
3114
+ const value = this.dialect.transformPrimitive(payload[key], fieldDef.type, false);
3076
3115
  const eb = (0, import_kysely8.expressionBuilder)();
3077
3116
  const fieldRef = buildFieldRef(this.schema, model, field, this.options, eb);
3078
3117
  return (0, import_ts_pattern8.match)(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(() => {
@@ -3080,9 +3119,9 @@ var BaseOperationHandler = class {
3080
3119
  });
3081
3120
  }
3082
3121
  transformScalarListUpdate(model, field, fieldDef, payload) {
3083
- (0, import_tiny_invariant7.default)(Object.keys(payload).length === 1, 'Only one of "set", "push" can be provided');
3122
+ (0, import_common_helpers8.invariant)(Object.keys(payload).length === 1, 'Only one of "set", "push" can be provided');
3084
3123
  const key = Object.keys(payload)[0];
3085
- const value = this.dialect.transformPrimitive(payload[key], fieldDef.type);
3124
+ const value = this.dialect.transformPrimitive(payload[key], fieldDef.type, true);
3086
3125
  const eb = (0, import_kysely8.expressionBuilder)();
3087
3126
  const fieldRef = buildFieldRef(this.schema, model, field, this.options, eb);
3088
3127
  return (0, import_ts_pattern8.match)(key).with("set", () => value).with("push", () => {
@@ -3112,7 +3151,7 @@ var BaseOperationHandler = class {
3112
3151
  if (isRelationField(this.schema, model, field)) {
3113
3152
  continue;
3114
3153
  }
3115
- updateFields[field] = this.dialect.transformPrimitive(data[field], fieldDef.type);
3154
+ updateFields[field] = this.dialect.transformPrimitive(data[field], fieldDef.type, !!fieldDef.array);
3116
3155
  }
3117
3156
  let query = kysely.updateTable(model).set(updateFields);
3118
3157
  if (limit === void 0) {
@@ -3130,20 +3169,15 @@ var BaseOperationHandler = class {
3130
3169
  model,
3131
3170
  operation: "update"
3132
3171
  }));
3133
- try {
3134
- if (!returnData) {
3135
- const result = await query.executeTakeFirstOrThrow();
3136
- return {
3137
- count: Number(result.numUpdatedRows)
3138
- };
3139
- } else {
3140
- const idFields = getIdFields(this.schema, model);
3141
- const result = await query.returning(idFields).execute();
3142
- return result;
3143
- }
3144
- } catch (err) {
3145
- const { sql: sql10, parameters } = query.compile();
3146
- throw new QueryError(`Error during updateMany: ${err}, sql: ${sql10}, parameters: ${parameters}`);
3172
+ if (!returnData) {
3173
+ const result = await query.executeTakeFirstOrThrow();
3174
+ return {
3175
+ count: Number(result.numUpdatedRows)
3176
+ };
3177
+ } else {
3178
+ const idFields = getIdFields(this.schema, model);
3179
+ const result = await query.returning(idFields).execute();
3180
+ return result;
3147
3181
  }
3148
3182
  }
3149
3183
  buildIdFieldRefs(kysely, model) {
@@ -3161,12 +3195,12 @@ var BaseOperationHandler = class {
3161
3195
  for (const [key, value] of Object.entries(args)) {
3162
3196
  switch (key) {
3163
3197
  case "create": {
3164
- (0, import_tiny_invariant7.default)(!Array.isArray(value) || fieldDef.array, "relation must be an array if create is an array");
3198
+ (0, import_common_helpers8.invariant)(!Array.isArray(value) || fieldDef.array, "relation must be an array if create is an array");
3165
3199
  tasks.push(...enumerate(value).map((item) => this.create(kysely, fieldModel, item, fromRelationContext)));
3166
3200
  break;
3167
3201
  }
3168
3202
  case "createMany": {
3169
- (0, import_tiny_invariant7.default)(fieldDef.array, "relation must be an array for createMany");
3203
+ (0, import_common_helpers8.invariant)(fieldDef.array, "relation must be an array for createMany");
3170
3204
  tasks.push(this.createMany(kysely, fieldModel, value, false, fromRelationContext));
3171
3205
  break;
3172
3206
  }
@@ -3183,7 +3217,7 @@ var BaseOperationHandler = class {
3183
3217
  break;
3184
3218
  }
3185
3219
  case "set": {
3186
- (0, import_tiny_invariant7.default)(fieldDef.array, "relation must be an array");
3220
+ (0, import_common_helpers8.invariant)(fieldDef.array, "relation must be an array");
3187
3221
  tasks.push(this.setRelation(kysely, fieldModel, value, fromRelationContext));
3188
3222
  break;
3189
3223
  }
@@ -3252,7 +3286,7 @@ var BaseOperationHandler = class {
3252
3286
  const { ownedByModel, keyPairs } = getRelationForeignKeyFieldPairs(this.schema, fromRelation.model, fromRelation.field);
3253
3287
  let updateResult;
3254
3288
  if (ownedByModel) {
3255
- (0, import_tiny_invariant7.default)(_data.length === 1, "only one entity can be connected");
3289
+ (0, import_common_helpers8.invariant)(_data.length === 1, "only one entity can be connected");
3256
3290
  const target = await this.readUnique(kysely, model, {
3257
3291
  where: _data[0]
3258
3292
  });
@@ -3342,7 +3376,7 @@ var BaseOperationHandler = class {
3342
3376
  const { ownedByModel, keyPairs } = getRelationForeignKeyFieldPairs(this.schema, fromRelation.model, fromRelation.field);
3343
3377
  const eb = (0, import_kysely8.expressionBuilder)();
3344
3378
  if (ownedByModel) {
3345
- (0, import_tiny_invariant7.default)(disconnectConditions.length === 1, "only one entity can be disconnected");
3379
+ (0, import_common_helpers8.invariant)(disconnectConditions.length === 1, "only one entity can be disconnected");
3346
3380
  const condition = disconnectConditions[0];
3347
3381
  const query = kysely.updateTable(fromRelation.model).where(eb.and(fromRelation.ids)).$if(condition !== true, (qb) => qb.where(eb(
3348
3382
  // @ts-ignore
@@ -3450,7 +3484,7 @@ var BaseOperationHandler = class {
3450
3484
  const m2m = getManyToManyRelation(this.schema, fromRelation.model, fromRelation.field);
3451
3485
  if (m2m) {
3452
3486
  const fieldDef = this.requireField(fromRelation.model, fromRelation.field);
3453
- (0, import_tiny_invariant7.default)(fieldDef.relation?.opposite);
3487
+ (0, import_common_helpers8.invariant)(fieldDef.relation?.opposite);
3454
3488
  deleteResult = await this.delete(kysely, model, {
3455
3489
  AND: [
3456
3490
  {
@@ -3473,7 +3507,7 @@ var BaseOperationHandler = class {
3473
3507
  throw new NotFoundError(model);
3474
3508
  }
3475
3509
  const fieldDef = this.requireField(fromRelation.model, fromRelation.field);
3476
- (0, import_tiny_invariant7.default)(fieldDef.relation?.opposite);
3510
+ (0, import_common_helpers8.invariant)(fieldDef.relation?.opposite);
3477
3511
  deleteResult = await this.delete(kysely, model, {
3478
3512
  AND: [
3479
3513
  // filter for parent
@@ -3543,7 +3577,7 @@ var BaseOperationHandler = class {
3543
3577
  }, {});
3544
3578
  }
3545
3579
  trimResult(data, args) {
3546
- if (!args.select) {
3580
+ if (!("select" in args) || !args.select) {
3547
3581
  return data;
3548
3582
  }
3549
3583
  return Object.keys(args.select).reduce((acc, field) => {
@@ -3553,9 +3587,9 @@ var BaseOperationHandler = class {
3553
3587
  }
3554
3588
  needReturnRelations(model, args) {
3555
3589
  let returnRelation = false;
3556
- if (args.include) {
3590
+ if ("include" in args && args.include) {
3557
3591
  returnRelation = Object.keys(args.include).length > 0;
3558
- } else if (args.select) {
3592
+ } else if ("select" in args && args.select) {
3559
3593
  returnRelation = Object.entries(args.select).some(([K, v]) => {
3560
3594
  const fieldDef = this.requireField(model, K);
3561
3595
  return fieldDef.relation && v;
@@ -3563,11 +3597,15 @@ var BaseOperationHandler = class {
3563
3597
  }
3564
3598
  return returnRelation;
3565
3599
  }
3566
- async safeTransaction(callback) {
3600
+ async safeTransaction(callback, isolationLevel) {
3567
3601
  if (this.kysely.isTransaction) {
3568
3602
  return callback(this.kysely);
3569
3603
  } else {
3570
- return this.kysely.transaction().setIsolationLevel("repeatable read").execute(callback);
3604
+ let txBuilder = this.kysely.transaction();
3605
+ if (isolationLevel) {
3606
+ txBuilder = txBuilder.setIsolationLevel(isolationLevel);
3607
+ }
3608
+ return txBuilder.execute(callback);
3571
3609
  }
3572
3610
  }
3573
3611
  // Given a unique filter of a model, return the entity ids by trying to
@@ -3586,6 +3624,28 @@ var BaseOperationHandler = class {
3586
3624
  where: uniqueFilter
3587
3625
  });
3588
3626
  }
3627
+ /**
3628
+ * Normalize input args to strip `undefined` fields
3629
+ */
3630
+ normalizeArgs(args) {
3631
+ if (!args) {
3632
+ return;
3633
+ }
3634
+ const newArgs = clone(args);
3635
+ this.doNormalizeArgs(newArgs);
3636
+ return newArgs;
3637
+ }
3638
+ doNormalizeArgs(args) {
3639
+ if (args && typeof args === "object") {
3640
+ for (const [key, value] of Object.entries(args)) {
3641
+ if (value === void 0) {
3642
+ delete args[key];
3643
+ } else if (value && (0, import_common_helpers8.isPlainObject)(value)) {
3644
+ this.doNormalizeArgs(value);
3645
+ }
3646
+ }
3647
+ }
3648
+ }
3589
3649
  };
3590
3650
 
3591
3651
  // src/client/crud/operations/aggregate.ts
@@ -3594,21 +3654,22 @@ var AggregateOperationHandler = class extends BaseOperationHandler {
3594
3654
  __name(this, "AggregateOperationHandler");
3595
3655
  }
3596
3656
  async handle(_operation, args) {
3597
- const validatedArgs = this.inputValidator.validateAggregateArgs(this.model, args);
3657
+ const normalizedArgs = this.normalizeArgs(args);
3658
+ const parsedArgs = this.inputValidator.validateAggregateArgs(this.model, normalizedArgs);
3598
3659
  let query = this.kysely.selectFrom((eb) => {
3599
- let subQuery = eb.selectFrom(this.model).selectAll(this.model).where((eb1) => this.dialect.buildFilter(eb1, this.model, this.model, validatedArgs?.where));
3600
- const skip = validatedArgs?.skip;
3601
- let take = validatedArgs?.take;
3660
+ let subQuery = eb.selectFrom(this.model).selectAll(this.model).where((eb1) => this.dialect.buildFilter(eb1, this.model, this.model, parsedArgs?.where));
3661
+ const skip = parsedArgs?.skip;
3662
+ let take = parsedArgs?.take;
3602
3663
  let negateOrderBy = false;
3603
3664
  if (take !== void 0 && take < 0) {
3604
3665
  negateOrderBy = true;
3605
3666
  take = -take;
3606
3667
  }
3607
3668
  subQuery = this.dialect.buildSkipTake(subQuery, skip, take);
3608
- subQuery = this.dialect.buildOrderBy(subQuery, this.model, this.model, validatedArgs.orderBy, skip !== void 0 || take !== void 0, negateOrderBy);
3669
+ subQuery = this.dialect.buildOrderBy(subQuery, this.model, this.model, parsedArgs.orderBy, skip !== void 0 || take !== void 0, negateOrderBy);
3609
3670
  return subQuery.as("$sub");
3610
3671
  });
3611
- for (const [key, value] of Object.entries(validatedArgs)) {
3672
+ for (const [key, value] of Object.entries(parsedArgs)) {
3612
3673
  switch (key) {
3613
3674
  case "_count": {
3614
3675
  if (value === true) {
@@ -3687,14 +3748,15 @@ var CountOperationHandler = class extends BaseOperationHandler {
3687
3748
  __name(this, "CountOperationHandler");
3688
3749
  }
3689
3750
  async handle(_operation, args) {
3690
- const validatedArgs = this.inputValidator.validateCountArgs(this.model, args);
3751
+ const normalizedArgs = this.normalizeArgs(args);
3752
+ const parsedArgs = this.inputValidator.validateCountArgs(this.model, normalizedArgs);
3691
3753
  let query = this.kysely.selectFrom((eb) => {
3692
- let subQuery = eb.selectFrom(this.model).selectAll().where((eb1) => this.dialect.buildFilter(eb1, this.model, this.model, validatedArgs?.where));
3693
- subQuery = this.dialect.buildSkipTake(subQuery, validatedArgs?.skip, validatedArgs?.take);
3754
+ let subQuery = eb.selectFrom(this.model).selectAll().where((eb1) => this.dialect.buildFilter(eb1, this.model, this.model, parsedArgs?.where));
3755
+ subQuery = this.dialect.buildSkipTake(subQuery, parsedArgs?.skip, parsedArgs?.take);
3694
3756
  return subQuery.as("$sub");
3695
3757
  });
3696
- if (validatedArgs?.select && typeof validatedArgs.select === "object") {
3697
- 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(import_kysely10.sql.ref(`$sub.${key}`)), "integer").as(key)));
3758
+ if (parsedArgs?.select && typeof parsedArgs.select === "object") {
3759
+ 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(import_kysely10.sql.ref(`$sub.${key}`)), "integer").as(key)));
3698
3760
  return query.executeTakeFirstOrThrow();
3699
3761
  } else {
3700
3762
  query = query.select((eb) => eb.cast(eb.fn.countAll(), "integer").as("count"));
@@ -3711,10 +3773,11 @@ var CreateOperationHandler = class extends BaseOperationHandler {
3711
3773
  __name(this, "CreateOperationHandler");
3712
3774
  }
3713
3775
  async handle(operation, args) {
3714
- return (0, import_ts_pattern10.match)(operation).with("create", () => this.runCreate(this.inputValidator.validateCreateArgs(this.model, args))).with("createMany", () => {
3715
- return this.runCreateMany(this.inputValidator.validateCreateManyArgs(this.model, args));
3776
+ const normalizedArgs = this.normalizeArgs(args);
3777
+ return (0, import_ts_pattern10.match)(operation).with("create", () => this.runCreate(this.inputValidator.validateCreateArgs(this.model, normalizedArgs))).with("createMany", () => {
3778
+ return this.runCreateMany(this.inputValidator.validateCreateManyArgs(this.model, normalizedArgs));
3716
3779
  }).with("createManyAndReturn", () => {
3717
- return this.runCreateManyAndReturn(this.inputValidator.validateCreateManyAndReturnArgs(this.model, args));
3780
+ return this.runCreateManyAndReturn(this.inputValidator.validateCreateManyAndReturnArgs(this.model, normalizedArgs));
3718
3781
  }).exhaustive();
3719
3782
  }
3720
3783
  async runCreate(args) {
@@ -3764,7 +3827,8 @@ var DeleteOperationHandler = class extends BaseOperationHandler {
3764
3827
  __name(this, "DeleteOperationHandler");
3765
3828
  }
3766
3829
  async handle(operation, args) {
3767
- return (0, import_ts_pattern11.match)(operation).with("delete", () => this.runDelete(this.inputValidator.validateDeleteArgs(this.model, args))).with("deleteMany", () => this.runDeleteMany(this.inputValidator.validateDeleteManyArgs(this.model, args))).exhaustive();
3830
+ const normalizedArgs = this.normalizeArgs(args);
3831
+ return (0, import_ts_pattern11.match)(operation).with("delete", () => this.runDelete(this.inputValidator.validateDeleteArgs(this.model, normalizedArgs))).with("deleteMany", () => this.runDeleteMany(this.inputValidator.validateDeleteManyArgs(this.model, normalizedArgs))).exhaustive();
3768
3832
  }
3769
3833
  async runDelete(args) {
3770
3834
  const existing = await this.readUnique(this.kysely, this.model, {
@@ -3794,7 +3858,8 @@ var FindOperationHandler = class extends BaseOperationHandler {
3794
3858
  __name(this, "FindOperationHandler");
3795
3859
  }
3796
3860
  async handle(operation, args, validateArgs = true) {
3797
- const parsedArgs = validateArgs ? this.inputValidator.validateFindArgs(this.model, operation === "findUnique", args) : args;
3861
+ const normalizedArgs = this.normalizeArgs(args);
3862
+ const parsedArgs = validateArgs ? this.inputValidator.validateFindArgs(this.model, operation === "findUnique", normalizedArgs) : normalizedArgs;
3798
3863
  const result = await this.read(this.client.$qb, this.model, parsedArgs);
3799
3864
  const finalResult = operation === "findMany" ? result : result[0] ?? null;
3800
3865
  return finalResult;
@@ -3804,16 +3869,17 @@ var FindOperationHandler = class extends BaseOperationHandler {
3804
3869
  // src/client/crud/operations/group-by.ts
3805
3870
  var import_kysely11 = require("kysely");
3806
3871
  var import_ts_pattern12 = require("ts-pattern");
3807
- var GroupByeOperationHandler = class extends BaseOperationHandler {
3872
+ var GroupByOperationHandler = class extends BaseOperationHandler {
3808
3873
  static {
3809
- __name(this, "GroupByeOperationHandler");
3874
+ __name(this, "GroupByOperationHandler");
3810
3875
  }
3811
3876
  async handle(_operation, args) {
3812
- const validatedArgs = this.inputValidator.validateGroupByArgs(this.model, args);
3877
+ const normalizedArgs = this.normalizeArgs(args);
3878
+ const parsedArgs = this.inputValidator.validateGroupByArgs(this.model, normalizedArgs);
3813
3879
  let query = this.kysely.selectFrom((eb) => {
3814
- let subQuery = eb.selectFrom(this.model).selectAll().where((eb1) => this.dialect.buildFilter(eb1, this.model, this.model, validatedArgs?.where));
3815
- const skip = validatedArgs?.skip;
3816
- let take = validatedArgs?.take;
3880
+ let subQuery = eb.selectFrom(this.model).selectAll().where((eb1) => this.dialect.buildFilter(eb1, this.model, this.model, parsedArgs?.where));
3881
+ const skip = parsedArgs?.skip;
3882
+ let take = parsedArgs?.take;
3817
3883
  let negateOrderBy = false;
3818
3884
  if (take !== void 0 && take < 0) {
3819
3885
  negateOrderBy = true;
@@ -3823,20 +3889,20 @@ var GroupByeOperationHandler = class extends BaseOperationHandler {
3823
3889
  subQuery = this.dialect.buildOrderBy(subQuery, this.model, this.model, void 0, skip !== void 0 || take !== void 0, negateOrderBy);
3824
3890
  return subQuery.as("$sub");
3825
3891
  });
3826
- const bys = typeof validatedArgs.by === "string" ? [
3827
- validatedArgs.by
3828
- ] : validatedArgs.by;
3892
+ const bys = typeof parsedArgs.by === "string" ? [
3893
+ parsedArgs.by
3894
+ ] : parsedArgs.by;
3829
3895
  query = query.groupBy(bys);
3830
- if (validatedArgs.orderBy) {
3831
- query = this.dialect.buildOrderBy(query, this.model, "$sub", validatedArgs.orderBy, false, false);
3896
+ if (parsedArgs.orderBy) {
3897
+ query = this.dialect.buildOrderBy(query, this.model, "$sub", parsedArgs.orderBy, false, false);
3832
3898
  }
3833
- if (validatedArgs.having) {
3834
- query = query.having((eb1) => this.dialect.buildFilter(eb1, this.model, "$sub", validatedArgs.having));
3899
+ if (parsedArgs.having) {
3900
+ query = query.having((eb1) => this.dialect.buildFilter(eb1, this.model, "$sub", parsedArgs.having));
3835
3901
  }
3836
3902
  for (const by of bys) {
3837
3903
  query = query.select(() => import_kysely11.sql.ref(`$sub.${by}`).as(by));
3838
3904
  }
3839
- for (const [key, value] of Object.entries(validatedArgs)) {
3905
+ for (const [key, value] of Object.entries(parsedArgs)) {
3840
3906
  switch (key) {
3841
3907
  case "_count": {
3842
3908
  if (value === true) {
@@ -3919,7 +3985,8 @@ var UpdateOperationHandler = class extends BaseOperationHandler {
3919
3985
  __name(this, "UpdateOperationHandler");
3920
3986
  }
3921
3987
  async handle(operation, args) {
3922
- return (0, import_ts_pattern13.match)(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();
3988
+ const normalizedArgs = this.normalizeArgs(args);
3989
+ return (0, import_ts_pattern13.match)(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();
3923
3990
  }
3924
3991
  async runUpdate(args) {
3925
3992
  const result = await this.safeTransaction(async (tx) => {
@@ -3975,6 +4042,7 @@ var UpdateOperationHandler = class extends BaseOperationHandler {
3975
4042
  };
3976
4043
 
3977
4044
  // src/client/crud/validator.ts
4045
+ var import_common_helpers9 = require("@zenstackhq/common-helpers");
3978
4046
  var import_decimal = __toESM(require("decimal.js"), 1);
3979
4047
  var import_json_stable_stringify = __toESM(require("json-stable-stringify"), 1);
3980
4048
  var import_ts_pattern14 = require("ts-pattern");
@@ -3984,10 +4052,9 @@ var InputValidator = class {
3984
4052
  __name(this, "InputValidator");
3985
4053
  }
3986
4054
  schema;
3987
- schemaCache;
4055
+ schemaCache = /* @__PURE__ */ new Map();
3988
4056
  constructor(schema) {
3989
4057
  this.schema = schema;
3990
- this.schemaCache = /* @__PURE__ */ new Map();
3991
4058
  }
3992
4059
  validateFindArgs(model, unique, args) {
3993
4060
  return this.validate(model, "find", {
@@ -4044,7 +4111,7 @@ var InputValidator = class {
4044
4111
  }
4045
4112
  const { error } = schema.safeParse(args);
4046
4113
  if (error) {
4047
- throw new QueryError(`Invalid ${operation} args: ${error.message}`);
4114
+ throw new InputValidationError(`Invalid ${operation} args: ${error.message}`, error);
4048
4115
  }
4049
4116
  return args;
4050
4117
  }
@@ -4091,7 +4158,7 @@ var InputValidator = class {
4091
4158
  makeWhereSchema(model, unique, withoutRelationFields = false) {
4092
4159
  const modelDef = getModel(this.schema, model);
4093
4160
  if (!modelDef) {
4094
- throw new QueryError(`Model "${model}" not found`);
4161
+ throw new QueryError(`Model "${model}" not found in schema`);
4095
4162
  }
4096
4163
  const fields = {};
4097
4164
  for (const field of Object.keys(modelDef.fields)) {
@@ -4141,14 +4208,28 @@ var InputValidator = class {
4141
4208
  const uniqueFields = getUniqueFields(this.schema, model);
4142
4209
  for (const uniqueField of uniqueFields) {
4143
4210
  if ("defs" in uniqueField) {
4144
- fields[uniqueField.name] = import_zod.z.object(Object.fromEntries(Object.entries(uniqueField.defs).map(([key, def]) => [
4145
- key,
4146
- this.makePrimitiveFilterSchema(def.type, !!def.optional)
4147
- ]))).optional();
4211
+ fields[uniqueField.name] = import_zod.z.object(Object.fromEntries(Object.entries(uniqueField.defs).map(([key, def]) => {
4212
+ (0, import_common_helpers9.invariant)(!def.relation, "unique field cannot be a relation");
4213
+ let fieldSchema;
4214
+ const enumDef = getEnum(this.schema, def.type);
4215
+ if (enumDef) {
4216
+ if (Object.keys(enumDef).length > 0) {
4217
+ fieldSchema = this.makeEnumFilterSchema(enumDef, !!def.optional);
4218
+ } else {
4219
+ fieldSchema = import_zod.z.never();
4220
+ }
4221
+ } else {
4222
+ fieldSchema = this.makePrimitiveFilterSchema(def.type, !!def.optional);
4223
+ }
4224
+ return [
4225
+ key,
4226
+ fieldSchema
4227
+ ];
4228
+ }))).optional();
4148
4229
  }
4149
4230
  }
4150
4231
  }
4151
- fields["$expr"] = import_zod.z.function().optional();
4232
+ fields["$expr"] = import_zod.z.custom((v) => typeof v === "function").optional();
4152
4233
  fields["AND"] = this.orArray(import_zod.z.lazy(() => this.makeWhereSchema(model, false, withoutRelationFields)), true).optional();
4153
4234
  fields["OR"] = import_zod.z.lazy(() => this.makeWhereSchema(model, false, withoutRelationFields)).array().optional();
4154
4235
  fields["NOT"] = this.orArray(import_zod.z.lazy(() => this.makeWhereSchema(model, false, withoutRelationFields)), true).optional();
@@ -4194,7 +4275,7 @@ var InputValidator = class {
4194
4275
  });
4195
4276
  }
4196
4277
  makePrimitiveFilterSchema(type, optional) {
4197
- return (0, import_ts_pattern14.match)(type).with("String", () => this.makeStringFilterSchema(optional)).with(import_ts_pattern14.P.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();
4278
+ return (0, import_ts_pattern14.match)(type).with("String", () => this.makeStringFilterSchema(optional)).with(import_ts_pattern14.P.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)).with("Json", () => import_zod.z.any()).with("Unsupported", () => import_zod.z.never()).exhaustive();
4198
4279
  }
4199
4280
  makeDateTimeFilterSchema(optional) {
4200
4281
  return this.makeCommonPrimitiveFilterSchema(import_zod.z.union([
@@ -4388,8 +4469,8 @@ var InputValidator = class {
4388
4469
  return this.refineForSelectOmitMutuallyExclusive(result).optional();
4389
4470
  }
4390
4471
  makeCreateDataSchema(model, canBeArray, withoutFields = [], withoutRelationFields = false) {
4391
- const regularAndFkFields = {};
4392
- const regularAndRelationFields = {};
4472
+ const uncheckedVariantFields = {};
4473
+ const checkedVariantFields = {};
4393
4474
  const modelDef = requireModel(this.schema, model);
4394
4475
  const hasRelation = !withoutRelationFields && Object.entries(modelDef.fields).some(([f, def]) => !withoutFields.includes(f) && def.relation);
4395
4476
  Object.keys(modelDef.fields).forEach((field) => {
@@ -4431,7 +4512,10 @@ var InputValidator = class {
4431
4512
  if (fieldDef.optional && !fieldDef.array) {
4432
4513
  fieldSchema = fieldSchema.nullable();
4433
4514
  }
4434
- regularAndRelationFields[field] = fieldSchema;
4515
+ checkedVariantFields[field] = fieldSchema;
4516
+ if (fieldDef.array || !fieldDef.relation.references) {
4517
+ uncheckedVariantFields[field] = fieldSchema;
4518
+ }
4435
4519
  } else {
4436
4520
  let fieldSchema = this.makePrimitiveSchema(fieldDef.type);
4437
4521
  if (fieldDef.array) {
@@ -4448,23 +4532,23 @@ var InputValidator = class {
4448
4532
  if (fieldDef.optional) {
4449
4533
  fieldSchema = fieldSchema.nullable();
4450
4534
  }
4451
- regularAndFkFields[field] = fieldSchema;
4535
+ uncheckedVariantFields[field] = fieldSchema;
4452
4536
  if (!fieldDef.foreignKeyFor) {
4453
- regularAndRelationFields[field] = fieldSchema;
4537
+ checkedVariantFields[field] = fieldSchema;
4454
4538
  }
4455
4539
  }
4456
4540
  });
4457
4541
  if (!hasRelation) {
4458
- return this.orArray(import_zod.z.object(regularAndFkFields).strict(), canBeArray);
4542
+ return this.orArray(import_zod.z.object(uncheckedVariantFields).strict(), canBeArray);
4459
4543
  } else {
4460
4544
  return import_zod.z.union([
4461
- import_zod.z.object(regularAndFkFields).strict(),
4462
- import_zod.z.object(regularAndRelationFields).strict(),
4545
+ import_zod.z.object(uncheckedVariantFields).strict(),
4546
+ import_zod.z.object(checkedVariantFields).strict(),
4463
4547
  ...canBeArray ? [
4464
- import_zod.z.array(import_zod.z.object(regularAndFkFields).strict())
4548
+ import_zod.z.array(import_zod.z.object(uncheckedVariantFields).strict())
4465
4549
  ] : [],
4466
4550
  ...canBeArray ? [
4467
- import_zod.z.array(import_zod.z.object(regularAndRelationFields).strict())
4551
+ import_zod.z.array(import_zod.z.object(checkedVariantFields).strict())
4468
4552
  ] : []
4469
4553
  ]);
4470
4554
  }
@@ -4509,7 +4593,7 @@ var InputValidator = class {
4509
4593
  fields["deleteMany"] = this.makeDeleteRelationDataSchema(fieldType, true, false).optional();
4510
4594
  }
4511
4595
  }
4512
- return import_zod.z.object(fields).strict().refine((v) => Object.keys(v).length > 0, "At least one action is required");
4596
+ return import_zod.z.object(fields).strict();
4513
4597
  }
4514
4598
  makeSetDataSchema(model, canBeArray) {
4515
4599
  return this.orArray(this.makeWhereSchema(model, true), canBeArray);
@@ -4586,8 +4670,8 @@ var InputValidator = class {
4586
4670
  return this.refineForSelectIncludeMutuallyExclusive(schema);
4587
4671
  }
4588
4672
  makeUpdateDataSchema(model, withoutFields = [], withoutRelationFields = false) {
4589
- const regularAndFkFields = {};
4590
- const regularAndRelationFields = {};
4673
+ const uncheckedVariantFields = {};
4674
+ const checkedVariantFields = {};
4591
4675
  const modelDef = requireModel(this.schema, model);
4592
4676
  const hasRelation = Object.entries(modelDef.fields).some(([key, value]) => value.relation && !withoutFields.includes(key));
4593
4677
  Object.keys(modelDef.fields).forEach((field) => {
@@ -4612,7 +4696,10 @@ var InputValidator = class {
4612
4696
  if (fieldDef.optional && !fieldDef.array) {
4613
4697
  fieldSchema = fieldSchema.nullable();
4614
4698
  }
4615
- regularAndRelationFields[field] = fieldSchema;
4699
+ checkedVariantFields[field] = fieldSchema;
4700
+ if (fieldDef.array || !fieldDef.relation.references) {
4701
+ uncheckedVariantFields[field] = fieldSchema;
4702
+ }
4616
4703
  } else {
4617
4704
  let fieldSchema = this.makePrimitiveSchema(fieldDef.type).optional();
4618
4705
  if (this.isNumericField(fieldDef)) {
@@ -4639,18 +4726,18 @@ var InputValidator = class {
4639
4726
  if (fieldDef.optional) {
4640
4727
  fieldSchema = fieldSchema.nullable();
4641
4728
  }
4642
- regularAndFkFields[field] = fieldSchema;
4729
+ uncheckedVariantFields[field] = fieldSchema;
4643
4730
  if (!fieldDef.foreignKeyFor) {
4644
- regularAndRelationFields[field] = fieldSchema;
4731
+ checkedVariantFields[field] = fieldSchema;
4645
4732
  }
4646
4733
  }
4647
4734
  });
4648
4735
  if (!hasRelation) {
4649
- return import_zod.z.object(regularAndFkFields).strict();
4736
+ return import_zod.z.object(uncheckedVariantFields).strict();
4650
4737
  } else {
4651
4738
  return import_zod.z.union([
4652
- import_zod.z.object(regularAndFkFields).strict(),
4653
- import_zod.z.object(regularAndRelationFields).strict()
4739
+ import_zod.z.object(uncheckedVariantFields).strict(),
4740
+ import_zod.z.object(checkedVariantFields).strict()
4654
4741
  ]);
4655
4742
  }
4656
4743
  }
@@ -4946,6 +5033,7 @@ __name(performanceNow, "performanceNow");
4946
5033
  // src/client/executor/zenstack-query-executor.ts
4947
5034
  var import_kysely13 = require("kysely");
4948
5035
  var import_nanoid2 = require("nanoid");
5036
+ var import_node_util2 = require("util");
4949
5037
  var import_ts_pattern15 = require("ts-pattern");
4950
5038
 
4951
5039
  // src/client/executor/name-mapper.ts
@@ -4955,11 +5043,11 @@ var QueryNameMapper = class extends import_kysely12.OperationNodeTransformer {
4955
5043
  __name(this, "QueryNameMapper");
4956
5044
  }
4957
5045
  schema;
4958
- modelToTableMap;
4959
- fieldToColumnMap;
4960
- modelStack;
5046
+ modelToTableMap = /* @__PURE__ */ new Map();
5047
+ fieldToColumnMap = /* @__PURE__ */ new Map();
5048
+ modelStack = [];
4961
5049
  constructor(schema) {
4962
- super(), this.schema = schema, this.modelToTableMap = /* @__PURE__ */ new Map(), this.fieldToColumnMap = /* @__PURE__ */ new Map(), this.modelStack = [];
5050
+ super(), this.schema = schema;
4963
5051
  for (const [modelName, modelDef] of Object.entries(schema.models)) {
4964
5052
  const mappedName = this.getMappedName(modelDef);
4965
5053
  if (mappedName) {
@@ -5180,7 +5268,9 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends import_kysely13
5180
5268
  mutationInterceptionInfo = await this.callMutationInterceptionFilters(queryNode);
5181
5269
  }
5182
5270
  const task = /* @__PURE__ */ __name(async () => {
5183
- await this.callBeforeMutationHooks(queryNode, mutationInterceptionInfo);
5271
+ if (this.isMutationNode(queryNode)) {
5272
+ await this.callBeforeMutationHooks(queryNode, mutationInterceptionInfo);
5273
+ }
5184
5274
  const oldQueryNode = queryNode;
5185
5275
  if ((import_kysely13.InsertQueryNode.is(queryNode) || import_kysely13.DeleteQueryNode.is(queryNode)) && mutationInterceptionInfo?.loadAfterMutationEntity) {
5186
5276
  queryNode = {
@@ -5190,19 +5280,19 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends import_kysely13
5190
5280
  ])
5191
5281
  };
5192
5282
  }
5193
- const result = await this.proceedQueryWithKyselyInterceptors(queryNode, queryId);
5194
- await this.callAfterQueryInterceptionFilters(result, queryNode, mutationInterceptionInfo);
5283
+ const queryParams = compiledQuery.$raw ? compiledQuery.parameters : void 0;
5284
+ const result = await this.proceedQueryWithKyselyInterceptors(queryNode, queryParams, queryId);
5285
+ if (this.isMutationNode(queryNode)) {
5286
+ await this.callAfterQueryInterceptionFilters(result, queryNode, mutationInterceptionInfo);
5287
+ }
5195
5288
  if (oldQueryNode !== queryNode) {
5196
5289
  }
5197
5290
  return result;
5198
5291
  }, "task");
5199
- return this.executeWithTransaction(task, !!mutationInterceptionInfo?.useTransactionForMutation);
5292
+ return task();
5200
5293
  }
5201
- proceedQueryWithKyselyInterceptors(queryNode, queryId) {
5202
- let proceed = /* @__PURE__ */ __name((q) => this.proceedQuery(q, queryId), "proceed");
5203
- const makeTx = /* @__PURE__ */ __name((p) => (callback) => {
5204
- return this.executeWithTransaction(() => callback(p));
5205
- }, "makeTx");
5294
+ proceedQueryWithKyselyInterceptors(queryNode, parameters, queryId) {
5295
+ let proceed = /* @__PURE__ */ __name((q) => this.proceedQuery(q, parameters, queryId), "proceed");
5206
5296
  const hooks = this.options.plugins?.filter((plugin) => typeof plugin.onKyselyQuery === "function").map((plugin) => plugin.onKyselyQuery.bind(plugin)) ?? [];
5207
5297
  for (const hook of hooks) {
5208
5298
  const _proceed = proceed;
@@ -5212,20 +5302,30 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends import_kysely13
5212
5302
  schema: this.client.$schema,
5213
5303
  kysely: this.kysely,
5214
5304
  query,
5215
- proceed: _proceed,
5216
- transaction: makeTx(_proceed)
5305
+ proceed: _proceed
5217
5306
  });
5218
5307
  }, "proceed");
5219
5308
  }
5220
5309
  return proceed(queryNode);
5221
5310
  }
5222
- async proceedQuery(query, queryId) {
5311
+ async proceedQuery(query, parameters, queryId) {
5223
5312
  const finalQuery = this.nameMapper.transformNode(query);
5224
- const compiled = this.compileQuery(finalQuery);
5313
+ let compiled = this.compileQuery(finalQuery);
5314
+ if (parameters) {
5315
+ compiled = {
5316
+ ...compiled,
5317
+ parameters
5318
+ };
5319
+ }
5225
5320
  try {
5226
- return this.driver.txConnection ? await super.withConnectionProvider(new import_kysely13.SingleConnectionProvider(this.driver.txConnection)).executeQuery(compiled, queryId) : await super.executeQuery(compiled, queryId);
5321
+ return await super.executeQuery(compiled, queryId);
5227
5322
  } catch (err) {
5228
- throw new QueryError(`Failed to execute query: ${err}, sql: ${compiled.sql}, parameters: ${compiled.parameters}`);
5323
+ let message = `Failed to execute query: ${err}, sql: ${compiled.sql}`;
5324
+ if (this.options.debug) {
5325
+ message += `, parameters:
5326
+ ${compiled.parameters.map((p) => (0, import_node_util2.inspect)(p)).join("\n")}`;
5327
+ }
5328
+ throw new QueryError(message, err);
5229
5329
  }
5230
5330
  }
5231
5331
  isMutationNode(queryNode) {
@@ -5253,24 +5353,9 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends import_kysely13
5253
5353
  return new _ZenStackQueryExecutor(this.client, this.driver, this.compiler, this.adapter, this.connectionProvider, []);
5254
5354
  }
5255
5355
  withConnectionProvider(connectionProvider) {
5256
- return new _ZenStackQueryExecutor(this.client, this.driver, this.compiler, this.adapter, connectionProvider);
5257
- }
5258
- async executeWithTransaction(callback, useTransaction = true) {
5259
- if (!useTransaction || this.driver.txConnection) {
5260
- return callback();
5261
- } else {
5262
- return this.provideConnection(async (connection) => {
5263
- try {
5264
- await this.driver.beginTransaction(connection, {});
5265
- const result = await callback();
5266
- await this.driver.commitTransaction(connection);
5267
- return result;
5268
- } catch (error) {
5269
- await this.driver.rollbackTransaction(connection);
5270
- throw error;
5271
- }
5272
- });
5273
- }
5356
+ const newExecutor = new _ZenStackQueryExecutor(this.client, this.driver, this.compiler, this.adapter, connectionProvider);
5357
+ newExecutor.client = this.client.withExecutor(newExecutor);
5358
+ return newExecutor;
5274
5359
  }
5275
5360
  get hasMutationHooks() {
5276
5361
  return this.client.$options.plugins?.some((plugin) => plugin.beforeEntityMutation || plugin.afterEntityMutation);
@@ -5312,14 +5397,13 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends import_kysely13
5312
5397
  queryNode
5313
5398
  });
5314
5399
  result.intercept ||= filterResult.intercept;
5315
- result.useTransactionForMutation ||= filterResult.useTransactionForMutation;
5316
5400
  result.loadBeforeMutationEntity ||= filterResult.loadBeforeMutationEntity;
5317
5401
  result.loadAfterMutationEntity ||= filterResult.loadAfterMutationEntity;
5318
5402
  }
5319
5403
  }
5320
5404
  let beforeMutationEntities;
5321
5405
  if (result.loadBeforeMutationEntity && (import_kysely13.UpdateQueryNode.is(queryNode) || import_kysely13.DeleteQueryNode.is(queryNode))) {
5322
- beforeMutationEntities = await this.loadEntities(this.kysely, mutationModel, where);
5406
+ beforeMutationEntities = await this.loadEntities(mutationModel, where);
5323
5407
  }
5324
5408
  return {
5325
5409
  ...result,
@@ -5332,15 +5416,14 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends import_kysely13
5332
5416
  return void 0;
5333
5417
  }
5334
5418
  }
5335
- callBeforeMutationHooks(queryNode, mutationInterceptionInfo) {
5419
+ async callBeforeMutationHooks(queryNode, mutationInterceptionInfo) {
5336
5420
  if (!mutationInterceptionInfo?.intercept) {
5337
5421
  return;
5338
5422
  }
5339
5423
  if (this.options.plugins) {
5340
5424
  for (const plugin of this.options.plugins) {
5341
5425
  if (plugin.beforeEntityMutation) {
5342
- plugin.beforeEntityMutation({
5343
- // context: this.queryContext,
5426
+ await plugin.beforeEntityMutation({
5344
5427
  model: this.getMutationModel(queryNode),
5345
5428
  action: mutationInterceptionInfo.action,
5346
5429
  queryNode,
@@ -5361,12 +5444,12 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends import_kysely13
5361
5444
  let afterMutationEntities = void 0;
5362
5445
  if (mutationInterceptionInfo.loadAfterMutationEntity) {
5363
5446
  if (import_kysely13.UpdateQueryNode.is(queryNode)) {
5364
- afterMutationEntities = await this.loadEntities(this.kysely, mutationModel, mutationInterceptionInfo.where);
5447
+ afterMutationEntities = await this.loadEntities(mutationModel, mutationInterceptionInfo.where);
5365
5448
  } else {
5366
5449
  afterMutationEntities = queryResult.rows;
5367
5450
  }
5368
5451
  }
5369
- plugin.afterEntityMutation({
5452
+ await plugin.afterEntityMutation({
5370
5453
  model: this.getMutationModel(queryNode),
5371
5454
  action: mutationInterceptionInfo.action,
5372
5455
  queryNode,
@@ -5377,17 +5460,17 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends import_kysely13
5377
5460
  }
5378
5461
  }
5379
5462
  }
5380
- async loadEntities(kysely, model, where) {
5381
- const selectQuery = kysely.selectFrom(model).selectAll();
5463
+ async loadEntities(model, where) {
5464
+ const selectQuery = this.kysely.selectFrom(model).selectAll();
5382
5465
  let selectQueryNode = selectQuery.toOperationNode();
5383
5466
  selectQueryNode = {
5384
5467
  ...selectQueryNode,
5385
5468
  where: this.andNodes(selectQueryNode.where, where)
5386
5469
  };
5387
- const compiled = kysely.getExecutor().compileQuery(selectQueryNode, {
5470
+ const compiled = this.compileQuery(selectQueryNode);
5471
+ const result = await this.executeQuery(compiled, {
5388
5472
  queryId: `zenstack-${(0, import_nanoid2.nanoid)()}`
5389
5473
  });
5390
- const result = await kysely.executeQuery(compiled);
5391
5474
  return result.rows;
5392
5475
  }
5393
5476
  andNodes(condition1, condition2) {
@@ -5416,8 +5499,8 @@ __export(functions_exports, {
5416
5499
  search: () => search,
5417
5500
  startsWith: () => startsWith
5418
5501
  });
5502
+ var import_common_helpers10 = require("@zenstackhq/common-helpers");
5419
5503
  var import_kysely14 = require("kysely");
5420
- var import_tiny_invariant8 = __toESM(require("tiny-invariant"), 1);
5421
5504
  var import_ts_pattern16 = require("ts-pattern");
5422
5505
  var contains = /* @__PURE__ */ __name((eb, args) => {
5423
5506
  const [field, search2, caseInsensitive = false] = args;
@@ -5523,8 +5606,8 @@ var currentOperation = /* @__PURE__ */ __name((_eb, args, { operation }) => {
5523
5606
  }, "currentOperation");
5524
5607
  function processCasing(casing, result, model) {
5525
5608
  const opNode = casing.toOperationNode();
5526
- (0, import_tiny_invariant8.default)(import_kysely14.ValueNode.is(opNode) && typeof opNode.value === "string", '"casting" parameter must be a string value');
5527
- result = (0, import_ts_pattern16.match)(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(() => {
5609
+ (0, import_common_helpers10.invariant)(import_kysely14.ValueNode.is(opNode) && typeof opNode.value === "string", '"casting" parameter must be a string value');
5610
+ result = (0, import_ts_pattern16.match)(opNode.value).with("original", () => model).with("upper", () => result.toUpperCase()).with("lower", () => result.toLowerCase()).with("capitalize", () => (0, import_common_helpers10.upperCaseFirst)(result)).with("uncapitalize", () => (0, import_common_helpers10.lowerCaseFirst)(result)).otherwise(() => {
5528
5611
  throw new Error(`Invalid casing value: ${opNode.value}. Must be "original", "upper", "lower", "capitalize", or "uncapitalize".`);
5529
5612
  });
5530
5613
  return result;
@@ -5532,8 +5615,8 @@ function processCasing(casing, result, model) {
5532
5615
  __name(processCasing, "processCasing");
5533
5616
 
5534
5617
  // src/client/helpers/schema-db-pusher.ts
5618
+ var import_common_helpers11 = require("@zenstackhq/common-helpers");
5535
5619
  var import_kysely15 = require("kysely");
5536
- var import_tiny_invariant9 = __toESM(require("tiny-invariant"), 1);
5537
5620
  var import_ts_pattern17 = require("ts-pattern");
5538
5621
  var SchemaDbPusher = class {
5539
5622
  static {
@@ -5565,7 +5648,7 @@ var SchemaDbPusher = class {
5565
5648
  for (const [fieldName, fieldDef] of Object.entries(modelDef.fields)) {
5566
5649
  if (fieldDef.relation) {
5567
5650
  table = this.addForeignKeyConstraint(table, model, fieldName, fieldDef);
5568
- } else {
5651
+ } else if (!this.isComputedField(fieldDef)) {
5569
5652
  table = this.createModelField(table, fieldName, fieldDef, modelDef);
5570
5653
  }
5571
5654
  }
@@ -5573,6 +5656,9 @@ var SchemaDbPusher = class {
5573
5656
  table = this.addUniqueConstraint(table, modelDef);
5574
5657
  return table;
5575
5658
  }
5659
+ isComputedField(fieldDef) {
5660
+ return fieldDef.attributes?.some((a) => a.name === "@computed");
5661
+ }
5576
5662
  addPrimaryKeyConstraint(table, model, modelDef) {
5577
5663
  if (modelDef.idFields.length === 1) {
5578
5664
  if (Object.values(modelDef.fields).some((f) => f.id)) {
@@ -5586,7 +5672,7 @@ var SchemaDbPusher = class {
5586
5672
  }
5587
5673
  addUniqueConstraint(table, modelDef) {
5588
5674
  for (const [key, value] of Object.entries(modelDef.uniqueFields)) {
5589
- (0, import_tiny_invariant9.default)(typeof value === "object", "expecting an object");
5675
+ (0, import_common_helpers11.invariant)(typeof value === "object", "expecting an object");
5590
5676
  if ("type" in value) {
5591
5677
  const fieldDef = modelDef.fields[key];
5592
5678
  if (fieldDef.unique) {
@@ -5632,7 +5718,7 @@ var SchemaDbPusher = class {
5632
5718
  return "serial";
5633
5719
  }
5634
5720
  const type = fieldDef.type;
5635
- const result = (0, import_ts_pattern17.match)(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(() => {
5721
+ const result = (0, import_ts_pattern17.match)(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(() => {
5636
5722
  throw new Error(`Unsupported field type: ${type}`);
5637
5723
  });
5638
5724
  if (fieldDef.array) {
@@ -5645,7 +5731,7 @@ var SchemaDbPusher = class {
5645
5731
  return fieldDef.default && ExpressionUtils.isCall(fieldDef.default) && fieldDef.default.function === "autoincrement";
5646
5732
  }
5647
5733
  addForeignKeyConstraint(table, model, fieldName, fieldDef) {
5648
- (0, import_tiny_invariant9.default)(fieldDef.relation, "field must be a relation");
5734
+ (0, import_common_helpers11.invariant)(fieldDef.relation, "field must be a relation");
5649
5735
  if (!fieldDef.relation.fields || !fieldDef.relation.references) {
5650
5736
  return table;
5651
5737
  }
@@ -5666,11 +5752,11 @@ var SchemaDbPusher = class {
5666
5752
  };
5667
5753
 
5668
5754
  // src/client/promise.ts
5669
- function createDeferredPromise(callback) {
5755
+ function createZenStackPromise(callback) {
5670
5756
  let promise;
5671
- const cb = /* @__PURE__ */ __name(() => {
5757
+ const cb = /* @__PURE__ */ __name((txClient) => {
5672
5758
  try {
5673
- return promise ??= valueToPromise(callback());
5759
+ return promise ??= valueToPromise(callback(txClient));
5674
5760
  } catch (err) {
5675
5761
  return Promise.reject(err);
5676
5762
  }
@@ -5685,10 +5771,11 @@ function createDeferredPromise(callback) {
5685
5771
  finally(onFinally) {
5686
5772
  return cb().finally(onFinally);
5687
5773
  },
5774
+ cb,
5688
5775
  [Symbol.toStringTag]: "ZenStackPromise"
5689
5776
  };
5690
5777
  }
5691
- __name(createDeferredPromise, "createDeferredPromise");
5778
+ __name(createZenStackPromise, "createZenStackPromise");
5692
5779
  function valueToPromise(thing) {
5693
5780
  if (typeof thing === "object" && typeof thing?.then === "function") {
5694
5781
  return thing;
@@ -5699,8 +5786,8 @@ function valueToPromise(thing) {
5699
5786
  __name(valueToPromise, "valueToPromise");
5700
5787
 
5701
5788
  // src/client/result-processor.ts
5789
+ var import_common_helpers12 = require("@zenstackhq/common-helpers");
5702
5790
  var import_decimal2 = __toESM(require("decimal.js"), 1);
5703
- var import_tiny_invariant10 = __toESM(require("tiny-invariant"), 1);
5704
5791
  var import_ts_pattern18 = require("ts-pattern");
5705
5792
  var ResultProcessor = class {
5706
5793
  static {
@@ -5774,20 +5861,20 @@ var ResultProcessor = class {
5774
5861
  return this.doProcessResult(relationData, fieldDef.type);
5775
5862
  }
5776
5863
  transformScalar(value, type) {
5777
- return (0, import_ts_pattern18.match)(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);
5864
+ return (0, import_ts_pattern18.match)(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);
5778
5865
  }
5779
5866
  transformDecimal(value) {
5780
5867
  if (value instanceof import_decimal2.default) {
5781
5868
  return value;
5782
5869
  }
5783
- (0, import_tiny_invariant10.default)(typeof value === "string" || typeof value === "number" || value instanceof import_decimal2.default, `Expected string, number or Decimal, got ${typeof value}`);
5870
+ (0, import_common_helpers12.invariant)(typeof value === "string" || typeof value === "number" || value instanceof import_decimal2.default, `Expected string, number or Decimal, got ${typeof value}`);
5784
5871
  return new import_decimal2.default(value);
5785
5872
  }
5786
5873
  transformBigInt(value) {
5787
5874
  if (typeof value === "bigint") {
5788
5875
  return value;
5789
5876
  }
5790
- (0, import_tiny_invariant10.default)(typeof value === "string" || typeof value === "number", `Expected string or number, got ${typeof value}`);
5877
+ (0, import_common_helpers12.invariant)(typeof value === "string" || typeof value === "number", `Expected string or number, got ${typeof value}`);
5791
5878
  return BigInt(value);
5792
5879
  }
5793
5880
  transformBoolean(value) {
@@ -5806,6 +5893,9 @@ var ResultProcessor = class {
5806
5893
  return Buffer.isBuffer(value) ? Uint8Array.from(value) : value;
5807
5894
  }
5808
5895
  fixReversedResult(data, model, args) {
5896
+ if (!data) {
5897
+ return;
5898
+ }
5809
5899
  if (Array.isArray(data) && typeof args === "object" && args && args.take !== void 0 && args.take < 0) {
5810
5900
  data.reverse();
5811
5901
  }
@@ -5819,13 +5909,19 @@ var ResultProcessor = class {
5819
5909
  continue;
5820
5910
  }
5821
5911
  const fieldDef = getField(this.schema, model, field);
5822
- if (!fieldDef?.relation) {
5912
+ if (!fieldDef || !fieldDef.relation || !fieldDef.array) {
5823
5913
  continue;
5824
5914
  }
5825
5915
  this.fixReversedResult(row[field], fieldDef.type, value);
5826
5916
  }
5827
5917
  }
5828
5918
  }
5919
+ transformJson(value) {
5920
+ return (0, import_ts_pattern18.match)(this.schema.provider.type).with("sqlite", () => {
5921
+ (0, import_common_helpers12.invariant)(typeof value === "string", "Expected string, got " + typeof value);
5922
+ return JSON.parse(value);
5923
+ }).otherwise(() => value);
5924
+ }
5829
5925
  };
5830
5926
 
5831
5927
  // src/client/client-impl.ts
@@ -5844,7 +5940,7 @@ var ClientImpl = class _ClientImpl {
5844
5940
  $schema;
5845
5941
  kyselyProps;
5846
5942
  auth;
5847
- constructor(schema, options, baseClient) {
5943
+ constructor(schema, options, baseClient, executor) {
5848
5944
  this.schema = schema;
5849
5945
  this.options = options;
5850
5946
  this.$schema = schema;
@@ -5856,16 +5952,16 @@ var ClientImpl = class _ClientImpl {
5856
5952
  if (baseClient) {
5857
5953
  this.kyselyProps = {
5858
5954
  ...baseClient.kyselyProps,
5859
- executor: new ZenStackQueryExecutor(this, baseClient.kyselyProps.driver, baseClient.kyselyProps.dialect.createQueryCompiler(), baseClient.kyselyProps.dialect.createAdapter(), new import_kysely16.DefaultConnectionProvider(baseClient.kyselyProps.driver))
5955
+ executor: executor ?? new ZenStackQueryExecutor(this, baseClient.kyselyProps.driver, baseClient.kyselyProps.dialect.createQueryCompiler(), baseClient.kyselyProps.dialect.createAdapter(), new import_kysely16.DefaultConnectionProvider(baseClient.kyselyProps.driver))
5860
5956
  };
5861
5957
  this.kyselyRaw = baseClient.kyselyRaw;
5958
+ this.auth = baseClient.auth;
5862
5959
  } else {
5863
5960
  const dialect = this.getKyselyDialect();
5864
5961
  const driver = new ZenStackDriver(dialect.createDriver(), new import_kysely16.Log(this.$options.log ?? []));
5865
5962
  const compiler = dialect.createQueryCompiler();
5866
5963
  const adapter = dialect.createAdapter();
5867
5964
  const connectionProvider = new import_kysely16.DefaultConnectionProvider(driver);
5868
- const executor = new ZenStackQueryExecutor(this, driver, compiler, adapter, connectionProvider);
5869
5965
  this.kyselyProps = {
5870
5966
  config: {
5871
5967
  dialect,
@@ -5873,7 +5969,7 @@ var ClientImpl = class _ClientImpl {
5873
5969
  },
5874
5970
  dialect,
5875
5971
  driver,
5876
- executor
5972
+ executor: executor ?? new ZenStackQueryExecutor(this, driver, compiler, adapter, connectionProvider)
5877
5973
  };
5878
5974
  this.kyselyRaw = new import_kysely16.Kysely({
5879
5975
  ...this.kyselyProps,
@@ -5889,31 +5985,67 @@ var ClientImpl = class _ClientImpl {
5889
5985
  get $qbRaw() {
5890
5986
  return this.kyselyRaw;
5891
5987
  }
5988
+ get isTransaction() {
5989
+ return this.kysely.isTransaction;
5990
+ }
5991
+ /**
5992
+ * Create a new client with a new query executor.
5993
+ */
5994
+ withExecutor(executor) {
5995
+ return new _ClientImpl(this.schema, this.$options, this, executor);
5996
+ }
5892
5997
  getKyselyDialect() {
5893
5998
  return (0, import_ts_pattern19.match)(this.schema.provider.type).with("sqlite", () => this.makeSqliteKyselyDialect()).with("postgresql", () => this.makePostgresKyselyDialect()).exhaustive();
5894
5999
  }
5895
6000
  makePostgresKyselyDialect() {
5896
- const { dialectConfigProvider } = this.schema.provider;
5897
- const mergedConfig = {
5898
- ...dialectConfigProvider(),
5899
- ...this.options?.dialectConfig
5900
- };
5901
- return new import_kysely16.PostgresDialect(mergedConfig);
6001
+ return new import_kysely16.PostgresDialect(this.options.dialectConfig);
5902
6002
  }
5903
6003
  makeSqliteKyselyDialect() {
5904
- const { dialectConfigProvider } = this.schema.provider;
5905
- const mergedConfig = {
5906
- ...dialectConfigProvider(),
5907
- ...this.options?.dialectConfig
5908
- };
5909
- return new import_kysely16.SqliteDialect(mergedConfig);
6004
+ return new import_kysely16.SqliteDialect(this.options.dialectConfig);
6005
+ }
6006
+ // implementation
6007
+ async $transaction(input, options) {
6008
+ (0, import_common_helpers13.invariant)(typeof input === "function" || Array.isArray(input) && input.every((p) => p.then && p.cb), "Invalid transaction input, expected a function or an array of ZenStackPromise");
6009
+ if (typeof input === "function") {
6010
+ return this.interactiveTransaction(input, options);
6011
+ } else {
6012
+ return this.sequentialTransaction(input, options);
6013
+ }
5910
6014
  }
5911
- async $transaction(callback) {
5912
- return this.kysely.transaction().execute((tx) => {
5913
- const txClient = new _ClientImpl(this.schema, this.$options);
6015
+ async interactiveTransaction(callback, options) {
6016
+ if (this.kysely.isTransaction) {
6017
+ return callback(this);
6018
+ } else {
6019
+ let txBuilder = this.kysely.transaction();
6020
+ if (options?.isolationLevel) {
6021
+ txBuilder = txBuilder.setIsolationLevel(options.isolationLevel);
6022
+ }
6023
+ return txBuilder.execute((tx) => {
6024
+ const txClient = new _ClientImpl(this.schema, this.$options, this);
6025
+ txClient.kysely = tx;
6026
+ return callback(txClient);
6027
+ });
6028
+ }
6029
+ }
6030
+ async sequentialTransaction(arg, options) {
6031
+ const execute = /* @__PURE__ */ __name(async (tx) => {
6032
+ const txClient = new _ClientImpl(this.schema, this.$options, this);
5914
6033
  txClient.kysely = tx;
5915
- return callback(txClient);
5916
- });
6034
+ const result = [];
6035
+ for (const promise of arg) {
6036
+ result.push(await promise.cb(txClient));
6037
+ }
6038
+ return result;
6039
+ }, "execute");
6040
+ if (this.kysely.isTransaction) {
6041
+ return execute(this.kysely);
6042
+ } else {
6043
+ let txBuilder = this.kysely.transaction();
6044
+ if (options?.isolationLevel) {
6045
+ txBuilder = txBuilder.setIsolationLevel(options.isolationLevel);
6046
+ }
6047
+ return txBuilder.execute((tx) => execute(tx));
6048
+ }
5917
6049
  }
5918
6050
  get $procedures() {
5919
6051
  return Object.keys(this.$schema.procedures ?? {}).reduce((acc, name) => {
@@ -5944,12 +6076,19 @@ var ClientImpl = class _ClientImpl {
5944
6076
  const newOptions = {
5945
6077
  ...this.options,
5946
6078
  plugins: [
5947
- ...this.options?.plugins ?? [],
6079
+ ...this.options.plugins ?? [],
5948
6080
  plugin
5949
6081
  ]
5950
6082
  };
5951
6083
  return new _ClientImpl(this.schema, newOptions, this);
5952
6084
  }
6085
+ $unuse(pluginId) {
6086
+ const newOptions = {
6087
+ ...this.options,
6088
+ plugins: this.options.plugins?.filter((p) => p.id !== pluginId)
6089
+ };
6090
+ return new _ClientImpl(this.schema, newOptions, this);
6091
+ }
5953
6092
  $unuseAll() {
5954
6093
  const newOptions = {
5955
6094
  ...this.options,
@@ -5968,6 +6107,39 @@ var ClientImpl = class _ClientImpl {
5968
6107
  get $auth() {
5969
6108
  return this.auth;
5970
6109
  }
6110
+ $executeRaw(query, ...values) {
6111
+ return createZenStackPromise(async () => {
6112
+ const result = await (0, import_kysely16.sql)(query, ...values).execute(this.kysely);
6113
+ return Number(result.numAffectedRows ?? 0);
6114
+ });
6115
+ }
6116
+ $executeRawUnsafe(query, ...values) {
6117
+ return createZenStackPromise(async () => {
6118
+ const compiledQuery = this.createRawCompiledQuery(query, values);
6119
+ const result = await this.kysely.executeQuery(compiledQuery);
6120
+ return Number(result.numAffectedRows ?? 0);
6121
+ });
6122
+ }
6123
+ $queryRaw(query, ...values) {
6124
+ return createZenStackPromise(async () => {
6125
+ const result = await (0, import_kysely16.sql)(query, ...values).execute(this.kysely);
6126
+ return result.rows;
6127
+ });
6128
+ }
6129
+ $queryRawUnsafe(query, ...values) {
6130
+ return createZenStackPromise(async () => {
6131
+ const compiledQuery = this.createRawCompiledQuery(query, values);
6132
+ const result = await this.kysely.executeQuery(compiledQuery);
6133
+ return result.rows;
6134
+ });
6135
+ }
6136
+ createRawCompiledQuery(query, values) {
6137
+ const q = import_kysely16.CompiledQuery.raw(query, values);
6138
+ return {
6139
+ ...q,
6140
+ $raw: true
6141
+ };
6142
+ }
5971
6143
  };
5972
6144
  function createClientProxy(client) {
5973
6145
  const inputValidator = new InputValidator(client.$schema);
@@ -5990,9 +6162,9 @@ function createClientProxy(client) {
5990
6162
  __name(createClientProxy, "createClientProxy");
5991
6163
  function createModelCrudHandler(client, model, inputValidator, resultProcessor) {
5992
6164
  const createPromise = /* @__PURE__ */ __name((operation, args, handler, postProcess = false, throwIfNoResult = false) => {
5993
- return createDeferredPromise(async () => {
5994
- let proceed = /* @__PURE__ */ __name(async (_args, tx) => {
5995
- const _handler = tx ? handler.withClient(tx) : handler;
6165
+ return createZenStackPromise(async (txClient) => {
6166
+ let proceed = /* @__PURE__ */ __name(async (_args) => {
6167
+ const _handler = txClient ? handler.withClient(txClient) : handler;
5996
6168
  const r = await _handler.handle(operation, _args ?? args);
5997
6169
  if (!r && throwIfNoResult) {
5998
6170
  throw new NotFoundError(model);
@@ -6005,22 +6177,31 @@ function createModelCrudHandler(client, model, inputValidator, resultProcessor)
6005
6177
  }
6006
6178
  return result;
6007
6179
  }, "proceed");
6008
- const context = {
6009
- client,
6010
- model,
6011
- operation,
6012
- queryArgs: args
6013
- };
6014
6180
  const plugins = [
6015
6181
  ...client.$options.plugins ?? []
6016
6182
  ];
6017
6183
  for (const plugin of plugins) {
6018
- if (plugin.onQuery) {
6019
- const _proceed = proceed;
6020
- proceed = /* @__PURE__ */ __name(() => plugin.onQuery({
6021
- ...context,
6022
- proceed: _proceed
6023
- }), "proceed");
6184
+ if (plugin.onQuery && typeof plugin.onQuery === "object") {
6185
+ for (const [_model, modelHooks] of Object.entries(plugin.onQuery)) {
6186
+ if (_model === (0, import_common_helpers13.lowerCaseFirst)(model) || _model === "$allModels") {
6187
+ if (modelHooks && typeof modelHooks === "object") {
6188
+ for (const [op, opHooks] of Object.entries(modelHooks)) {
6189
+ if (op === operation || op === "$allOperations") {
6190
+ if (typeof opHooks === "function") {
6191
+ const _proceed = proceed;
6192
+ proceed = /* @__PURE__ */ __name(() => opHooks({
6193
+ client,
6194
+ model,
6195
+ operation,
6196
+ args,
6197
+ query: _proceed
6198
+ }), "proceed");
6199
+ }
6200
+ }
6201
+ }
6202
+ }
6203
+ }
6204
+ }
6024
6205
  }
6025
6206
  }
6026
6207
  return proceed(args);
@@ -6076,13 +6257,24 @@ function createModelCrudHandler(client, model, inputValidator, resultProcessor)
6076
6257
  return createPromise("aggregate", args, new AggregateOperationHandler(client, model, inputValidator), false);
6077
6258
  }, "aggregate"),
6078
6259
  groupBy: /* @__PURE__ */ __name((args) => {
6079
- return createPromise("groupBy", args, new GroupByeOperationHandler(client, model, inputValidator));
6260
+ return createPromise("groupBy", args, new GroupByOperationHandler(client, model, inputValidator));
6080
6261
  }, "groupBy")
6081
6262
  };
6082
6263
  }
6083
6264
  __name(createModelCrudHandler, "createModelCrudHandler");
6265
+
6266
+ // src/client/plugin.ts
6267
+ function definePlugin(plugin) {
6268
+ return plugin;
6269
+ }
6270
+ __name(definePlugin, "definePlugin");
6084
6271
  // Annotate the CommonJS export names for ESM import in node:
6085
6272
  0 && (module.exports = {
6086
- ZenStackClient
6273
+ InputValidationError,
6274
+ InternalError,
6275
+ NotFoundError,
6276
+ QueryError,
6277
+ ZenStackClient,
6278
+ definePlugin
6087
6279
  });
6088
6280
  //# sourceMappingURL=index.cjs.map