@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.js CHANGED
@@ -6,7 +6,8 @@ var __export = (target, all) => {
6
6
  };
7
7
 
8
8
  // src/client/client-impl.ts
9
- import { DefaultConnectionProvider, DefaultQueryExecutor as DefaultQueryExecutor2, Kysely, Log, PostgresDialect, SqliteDialect } from "kysely";
9
+ import { invariant as invariant12, lowerCaseFirst as lowerCaseFirst2 } from "@zenstackhq/common-helpers";
10
+ import { CompiledQuery, DefaultConnectionProvider, DefaultQueryExecutor as DefaultQueryExecutor2, Kysely, Log, PostgresDialect, sql as sql10, SqliteDialect } from "kysely";
10
11
  import { match as match19 } from "ts-pattern";
11
12
 
12
13
  // src/client/crud/operations/aggregate.ts
@@ -14,21 +15,30 @@ import { sql as sql5 } from "kysely";
14
15
  import { match as match9 } from "ts-pattern";
15
16
 
16
17
  // src/client/errors.ts
18
+ var InputValidationError = class extends Error {
19
+ static {
20
+ __name(this, "InputValidationError");
21
+ }
22
+ constructor(message, cause) {
23
+ super(message, {
24
+ cause
25
+ });
26
+ }
27
+ };
17
28
  var QueryError = class extends Error {
18
29
  static {
19
30
  __name(this, "QueryError");
20
31
  }
21
- constructor(message) {
22
- super(message);
32
+ constructor(message, cause) {
33
+ super(message, {
34
+ cause
35
+ });
23
36
  }
24
37
  };
25
38
  var InternalError = class extends Error {
26
39
  static {
27
40
  __name(this, "InternalError");
28
41
  }
29
- constructor(message) {
30
- super(message);
31
- }
32
42
  };
33
43
  var NotFoundError = class extends Error {
34
44
  static {
@@ -47,7 +57,7 @@ __name(getModel, "getModel");
47
57
  function requireModel(schema, model) {
48
58
  const matchedName = Object.keys(schema.models).find((k) => k.toLowerCase() === model.toLowerCase());
49
59
  if (!matchedName) {
50
- throw new QueryError(`Model "${model}" not found`);
60
+ throw new QueryError(`Model "${model}" not found in schema`);
51
61
  }
52
62
  return schema.models[matchedName];
53
63
  }
@@ -172,7 +182,7 @@ function buildFieldRef(schema, model, field, options, eb, modelAlias) {
172
182
  computer = computedFields?.[model]?.[field];
173
183
  }
174
184
  if (!computer) {
175
- throw new QueryError(`Computed field "${field}" implementation not provided`);
185
+ throw new QueryError(`Computed field "${field}" implementation not provided for model "${model}"`);
176
186
  }
177
187
  return computer(eb);
178
188
  }
@@ -280,9 +290,10 @@ __name(safeJSONStringify, "safeJSONStringify");
280
290
 
281
291
  // src/client/crud/operations/base.ts
282
292
  import { createId } from "@paralleldrive/cuid2";
293
+ import { invariant as invariant7, isPlainObject as isPlainObject3 } from "@zenstackhq/common-helpers";
283
294
  import { expressionBuilder as expressionBuilder2, sql as sql4 } from "kysely";
284
295
  import { nanoid } from "nanoid";
285
- import invariant7 from "tiny-invariant";
296
+ import { inspect } from "util";
286
297
  import { match as match8 } from "ts-pattern";
287
298
  import { ulid } from "ulid";
288
299
  import * as uuid from "uuid";
@@ -300,21 +311,21 @@ var RejectedByPolicyError = class extends Error {
300
311
  };
301
312
 
302
313
  // src/plugins/policy/policy-handler.ts
314
+ import { invariant as invariant6 } from "@zenstackhq/common-helpers";
303
315
  import { AliasNode as AliasNode3, BinaryOperationNode as BinaryOperationNode3, ColumnNode as ColumnNode2, DeleteQueryNode, FromNode as FromNode2, IdentifierNode as IdentifierNode2, InsertQueryNode, OperationNodeTransformer, OperatorNode as OperatorNode3, PrimitiveValueListNode, RawNode, ReturningNode, SelectionNode as SelectionNode2, SelectQueryNode as SelectQueryNode2, TableNode as TableNode3, UpdateQueryNode, ValueNode as ValueNode3, ValuesNode, WhereNode as WhereNode2 } from "kysely";
304
- import invariant6 from "tiny-invariant";
305
316
  import { match as match7 } from "ts-pattern";
306
317
 
307
318
  // src/client/crud/dialects/index.ts
308
319
  import { match as match4 } from "ts-pattern";
309
320
 
310
321
  // src/client/crud/dialects/postgresql.ts
322
+ import { invariant as invariant2 } from "@zenstackhq/common-helpers";
311
323
  import { sql as sql2 } from "kysely";
312
- import invariant2 from "tiny-invariant";
313
324
  import { match as match2 } from "ts-pattern";
314
325
 
315
326
  // src/client/crud/dialects/base.ts
327
+ import { invariant, isPlainObject } from "@zenstackhq/common-helpers";
316
328
  import { sql } from "kysely";
317
- import invariant from "tiny-invariant";
318
329
  import { match, P } from "ts-pattern";
319
330
 
320
331
  // src/utils/enumerate.ts
@@ -332,7 +343,6 @@ function enumerate(x) {
332
343
  __name(enumerate, "enumerate");
333
344
 
334
345
  // src/client/crud/dialects/base.ts
335
- import { isPlainObject } from "is-plain-object";
336
346
  var BaseCrudDialect = class {
337
347
  static {
338
348
  __name(this, "BaseCrudDialect");
@@ -343,7 +353,7 @@ var BaseCrudDialect = class {
343
353
  this.schema = schema;
344
354
  this.options = options;
345
355
  }
346
- transformPrimitive(value, _type) {
356
+ transformPrimitive(value, _type, _forArrayField) {
347
357
  return value;
348
358
  }
349
359
  buildFilter(eb, model, modelAlias, where) {
@@ -486,7 +496,7 @@ var BaseCrudDialect = class {
486
496
  if (_value === void 0) {
487
497
  continue;
488
498
  }
489
- const value = this.transformPrimitive(_value, fieldType);
499
+ const value = this.transformPrimitive(_value, fieldType, !!fieldDef.array);
490
500
  switch (key) {
491
501
  case "equals": {
492
502
  clauses.push(this.buildLiteralFilter(eb, fieldRef, fieldType, eb.val(value)));
@@ -524,10 +534,14 @@ var BaseCrudDialect = class {
524
534
  if (isEnum(this.schema, fieldDef.type)) {
525
535
  return this.buildEnumFilter(eb, modelAlias, field, fieldDef, payload);
526
536
  }
527
- return match(fieldDef.type).with("String", () => this.buildStringFilter(eb, modelAlias, field, payload)).with(P.union("Int", "Float", "Decimal", "BigInt"), (type) => this.buildNumberFilter(eb, model, modelAlias, field, type, payload)).with("Boolean", () => this.buildBooleanFilter(eb, modelAlias, field, payload)).with("DateTime", () => this.buildDateTimeFilter(eb, modelAlias, field, payload)).with("Bytes", () => this.buildBytesFilter(eb, modelAlias, field, payload)).exhaustive();
537
+ return match(fieldDef.type).with("String", () => this.buildStringFilter(eb, modelAlias, field, payload)).with(P.union("Int", "Float", "Decimal", "BigInt"), (type) => this.buildNumberFilter(eb, model, modelAlias, field, type, payload)).with("Boolean", () => this.buildBooleanFilter(eb, modelAlias, field, payload)).with("DateTime", () => this.buildDateTimeFilter(eb, modelAlias, field, payload)).with("Bytes", () => this.buildBytesFilter(eb, modelAlias, field, payload)).with("Json", () => {
538
+ throw new InternalError("JSON filters are not supported yet");
539
+ }).with("Unsupported", () => {
540
+ throw new QueryError(`Unsupported field cannot be used in filters`);
541
+ }).exhaustive();
528
542
  }
529
543
  buildLiteralFilter(eb, lhs, type, rhs) {
530
- return eb(lhs, "=", rhs !== null && rhs !== void 0 ? this.transformPrimitive(rhs, type) : rhs);
544
+ return eb(lhs, "=", rhs !== null && rhs !== void 0 ? this.transformPrimitive(rhs, type, false) : rhs);
531
545
  }
532
546
  buildStandardFilter(eb, type, payload, lhs, getRhs, recurse, throwIfInvalid = false, onlyForKeys = void 0) {
533
547
  if (payload === null || !isPlainObject(payload)) {
@@ -614,22 +628,22 @@ var BaseCrudDialect = class {
614
628
  }
615
629
  }
616
630
  buildNumberFilter(eb, model, table, field, type, payload) {
617
- const { conditions } = this.buildStandardFilter(eb, type, payload, buildFieldRef(this.schema, model, field, this.options, eb), (value) => this.transformPrimitive(value, type), (value) => this.buildNumberFilter(eb, model, table, field, type, value));
631
+ 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));
618
632
  return this.and(eb, ...conditions);
619
633
  }
620
634
  buildBooleanFilter(eb, table, field, payload) {
621
- const { conditions } = this.buildStandardFilter(eb, "Boolean", payload, sql.ref(`${table}.${field}`), (value) => this.transformPrimitive(value, "Boolean"), (value) => this.buildBooleanFilter(eb, table, field, value), true, [
635
+ const { conditions } = this.buildStandardFilter(eb, "Boolean", payload, sql.ref(`${table}.${field}`), (value) => this.transformPrimitive(value, "Boolean", false), (value) => this.buildBooleanFilter(eb, table, field, value), true, [
622
636
  "equals",
623
637
  "not"
624
638
  ]);
625
639
  return this.and(eb, ...conditions);
626
640
  }
627
641
  buildDateTimeFilter(eb, table, field, payload) {
628
- const { conditions } = this.buildStandardFilter(eb, "DateTime", payload, sql.ref(`${table}.${field}`), (value) => this.transformPrimitive(value, "DateTime"), (value) => this.buildDateTimeFilter(eb, table, field, value), true);
642
+ const { conditions } = this.buildStandardFilter(eb, "DateTime", payload, sql.ref(`${table}.${field}`), (value) => this.transformPrimitive(value, "DateTime", false), (value) => this.buildDateTimeFilter(eb, table, field, value), true);
629
643
  return this.and(eb, ...conditions);
630
644
  }
631
645
  buildBytesFilter(eb, table, field, payload) {
632
- const conditions = this.buildStandardFilter(eb, "Bytes", payload, sql.ref(`${table}.${field}`), (value) => this.transformPrimitive(value, "Bytes"), (value) => this.buildBytesFilter(eb, table, field, value), true, [
646
+ const conditions = this.buildStandardFilter(eb, "Bytes", payload, sql.ref(`${table}.${field}`), (value) => this.transformPrimitive(value, "Bytes", false), (value) => this.buildBytesFilter(eb, table, field, value), true, [
633
647
  "equals",
634
648
  "in",
635
649
  "notIn",
@@ -728,10 +742,10 @@ var BaseCrudDialect = class {
728
742
  return negated ? sort === "asc" ? "desc" : "asc" : sort;
729
743
  }
730
744
  true(eb) {
731
- return eb.lit(this.transformPrimitive(true, "Boolean"));
745
+ return eb.lit(this.transformPrimitive(true, "Boolean", false));
732
746
  }
733
747
  false(eb) {
734
- return eb.lit(this.transformPrimitive(false, "Boolean"));
748
+ return eb.lit(this.transformPrimitive(false, "Boolean", false));
735
749
  }
736
750
  isTrue(expression) {
737
751
  const node = expression.toOperationNode();
@@ -780,14 +794,18 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
780
794
  get provider() {
781
795
  return "postgresql";
782
796
  }
783
- transformPrimitive(value, type) {
797
+ transformPrimitive(value, type, forArrayField) {
784
798
  if (value === void 0) {
785
799
  return value;
786
800
  }
787
801
  if (Array.isArray(value)) {
788
- return value.map((v) => this.transformPrimitive(v, type));
802
+ if (type === "Json" && !forArrayField) {
803
+ return JSON.stringify(value);
804
+ } else {
805
+ return value.map((v) => this.transformPrimitive(v, type, false));
806
+ }
789
807
  } else {
790
- return match2(type).with("DateTime", () => value instanceof Date ? value : typeof value === "string" ? new Date(value) : value).otherwise(() => value);
808
+ return match2(type).with("DateTime", () => value instanceof Date ? value : typeof value === "string" ? new Date(value) : value).with("Decimal", () => value !== null ? value.toString() : value).otherwise(() => value);
791
809
  }
792
810
  }
793
811
  buildRelationSelection(query, model, relationField, parentAlias, payload) {
@@ -854,25 +872,33 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
854
872
  buildFieldRef(this.schema, relationModel, field, this.options, eb)
855
873
  ]).flatMap((v) => v));
856
874
  } else if (payload.select) {
857
- objArgs.push(...Object.entries(payload.select).filter(([, value]) => value).map(([field]) => [
858
- sql2.lit(field),
859
- buildFieldRef(this.schema, relationModel, field, this.options, eb)
860
- ]).flatMap((v) => v));
875
+ objArgs.push(...Object.entries(payload.select).filter(([, value]) => value).map(([field]) => {
876
+ const fieldDef = requireField(this.schema, relationModel, field);
877
+ const fieldValue = fieldDef.relation ? eb.ref(`${parentName}$${relationField}$${field}.$j`) : buildFieldRef(this.schema, relationModel, field, this.options, eb);
878
+ return [
879
+ sql2.lit(field),
880
+ fieldValue
881
+ ];
882
+ }).flatMap((v) => v));
861
883
  }
862
884
  if (typeof payload === "object" && payload.include && typeof payload.include === "object") {
863
885
  objArgs.push(...Object.entries(payload.include).filter(([, value]) => value).map(([field]) => [
864
886
  sql2.lit(field),
887
+ // reference the synthesized JSON field
865
888
  eb.ref(`${parentName}$${relationField}$${field}.$j`)
866
889
  ]).flatMap((v) => v));
867
890
  }
868
891
  return objArgs;
869
892
  }
870
- buildRelationJoins(model, relationField, qb, payload, parentName) {
893
+ buildRelationJoins(relationModel, relationField, qb, payload, parentName) {
871
894
  let result = qb;
872
- if (typeof payload === "object" && payload.include && typeof payload.include === "object") {
873
- Object.entries(payload.include).filter(([, value]) => value).forEach(([field, value]) => {
874
- result = this.buildRelationJSON(model, result, field, `${parentName}$${relationField}`, value);
875
- });
895
+ if (typeof payload === "object") {
896
+ const selectInclude = payload.include ?? payload.select;
897
+ if (selectInclude && typeof selectInclude === "object") {
898
+ Object.entries(selectInclude).filter(([, value]) => value).filter(([field]) => isRelationField(this.schema, relationModel, field)).forEach(([field, value]) => {
899
+ result = this.buildRelationJSON(relationModel, result, field, `${parentName}$${relationField}`, value);
900
+ });
901
+ }
876
902
  }
877
903
  return result;
878
904
  }
@@ -915,8 +941,8 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
915
941
  };
916
942
 
917
943
  // src/client/crud/dialects/sqlite.ts
944
+ import { invariant as invariant3 } from "@zenstackhq/common-helpers";
918
945
  import { sql as sql3 } from "kysely";
919
- import invariant3 from "tiny-invariant";
920
946
  import { match as match3 } from "ts-pattern";
921
947
  var SqliteCrudDialect = class extends BaseCrudDialect {
922
948
  static {
@@ -925,14 +951,14 @@ var SqliteCrudDialect = class extends BaseCrudDialect {
925
951
  get provider() {
926
952
  return "sqlite";
927
953
  }
928
- transformPrimitive(value, type) {
954
+ transformPrimitive(value, type, _forArrayField) {
929
955
  if (value === void 0) {
930
956
  return value;
931
957
  }
932
958
  if (Array.isArray(value)) {
933
- return value.map((v) => this.transformPrimitive(v, type));
959
+ return value.map((v) => this.transformPrimitive(v, type, false));
934
960
  } else {
935
- return match3(type).with("Boolean", () => value ? 1 : 0).with("DateTime", () => value instanceof Date ? value.toISOString() : value).with("Decimal", () => value.toString()).with("Bytes", () => Buffer.from(value)).otherwise(() => value);
961
+ return match3(type).with("Boolean", () => value ? 1 : 0).with("DateTime", () => value instanceof Date ? value.toISOString() : value).with("Decimal", () => value.toString()).with("Bytes", () => Buffer.from(value)).with("Json", () => JSON.stringify(value)).otherwise(() => value);
936
962
  }
937
963
  }
938
964
  buildRelationSelection(query, model, relationField, parentAlias, payload) {
@@ -1460,12 +1486,12 @@ var ColumnCollector = class extends DefaultOperationNodeVisitor {
1460
1486
  };
1461
1487
 
1462
1488
  // src/plugins/policy/expression-transformer.ts
1489
+ import { invariant as invariant5 } from "@zenstackhq/common-helpers";
1463
1490
  import { AliasNode as AliasNode2, BinaryOperationNode as BinaryOperationNode2, ColumnNode, expressionBuilder, FromNode, FunctionNode as FunctionNode2, IdentifierNode, OperatorNode as OperatorNode2, ReferenceNode as ReferenceNode2, SelectionNode, SelectQueryNode, TableNode as TableNode2, ValueListNode, ValueNode as ValueNode2, WhereNode } from "kysely";
1464
- import invariant5 from "tiny-invariant";
1465
1491
  import { match as match6 } from "ts-pattern";
1466
1492
 
1467
1493
  // src/plugins/policy/expression-evaluator.ts
1468
- import invariant4 from "tiny-invariant";
1494
+ import { invariant as invariant4 } from "@zenstackhq/common-helpers";
1469
1495
  import { match as match5 } from "ts-pattern";
1470
1496
  var ExpressionEvaluator = class {
1471
1497
  static {
@@ -1537,11 +1563,11 @@ var ExpressionEvaluator = class {
1537
1563
  // src/plugins/policy/utils.ts
1538
1564
  import { AliasNode, AndNode, BinaryOperationNode, FunctionNode, OperatorNode, OrNode, ParensNode, ReferenceNode, TableNode, UnaryOperationNode, ValueNode } from "kysely";
1539
1565
  function trueNode(dialect) {
1540
- return ValueNode.createImmediate(dialect.transformPrimitive(true, "Boolean"));
1566
+ return ValueNode.createImmediate(dialect.transformPrimitive(true, "Boolean", false));
1541
1567
  }
1542
1568
  __name(trueNode, "trueNode");
1543
1569
  function falseNode(dialect) {
1544
- return ValueNode.createImmediate(dialect.transformPrimitive(false, "Boolean"));
1570
+ return ValueNode.createImmediate(dialect.transformPrimitive(false, "Boolean", false));
1545
1571
  }
1546
1572
  __name(falseNode, "falseNode");
1547
1573
  function isTrueNode(node) {
@@ -1799,7 +1825,7 @@ var ExpressionTransformer = class {
1799
1825
  }
1800
1826
  }
1801
1827
  transformValue(value, type) {
1802
- return ValueNode2.create(this.dialect.transformPrimitive(value, type) ?? null);
1828
+ return ValueNode2.create(this.dialect.transformPrimitive(value, type, false) ?? null);
1803
1829
  }
1804
1830
  _unary(expr2, context) {
1805
1831
  invariant5(expr2.op === "!", 'only "!" operator is supported');
@@ -2042,7 +2068,7 @@ var PolicyHandler = class extends OperationNodeTransformer {
2042
2068
  get kysely() {
2043
2069
  return this.client.$qb;
2044
2070
  }
2045
- async handle(node, proceed, transaction) {
2071
+ async handle(node, proceed) {
2046
2072
  if (!this.isCrudQueryNode(node)) {
2047
2073
  throw new RejectedByPolicyError(void 0, "non-CRUD queries are not allowed");
2048
2074
  }
@@ -2062,27 +2088,20 @@ var PolicyHandler = class extends OperationNodeTransformer {
2062
2088
  if (!mutationRequiresTransaction && !node.returning) {
2063
2089
  return proceed(this.transformNode(node));
2064
2090
  }
2065
- let readBackError = false;
2066
- const result = await transaction(async (txProceed) => {
2067
- if (InsertQueryNode.is(node)) {
2068
- await this.enforcePreCreatePolicy(node, txProceed);
2069
- }
2070
- const transformedNode = this.transformNode(node);
2071
- const result2 = await txProceed(transformedNode);
2072
- if (!this.onlyReturningId(node)) {
2073
- const readBackResult = await this.processReadBack(node, result2, txProceed);
2074
- if (readBackResult.rows.length !== result2.rows.length) {
2075
- readBackError = true;
2076
- }
2077
- return readBackResult;
2078
- } else {
2079
- return result2;
2091
+ if (InsertQueryNode.is(node)) {
2092
+ await this.enforcePreCreatePolicy(node, proceed);
2093
+ }
2094
+ const transformedNode = this.transformNode(node);
2095
+ const result = await proceed(transformedNode);
2096
+ if (!this.onlyReturningId(node)) {
2097
+ const readBackResult = await this.processReadBack(node, result, proceed);
2098
+ if (readBackResult.rows.length !== result.rows.length) {
2099
+ throw new RejectedByPolicyError(mutationModel, "result is not allowed to be read back");
2080
2100
  }
2081
- });
2082
- if (readBackError) {
2083
- throw new RejectedByPolicyError(mutationModel, "result is not allowed to be read back");
2101
+ return readBackResult;
2102
+ } else {
2103
+ return result;
2084
2104
  }
2085
- return result;
2086
2105
  }
2087
2106
  onlyReturningId(node) {
2088
2107
  if (!node.returning) {
@@ -2143,11 +2162,11 @@ var PolicyHandler = class extends OperationNodeTransformer {
2143
2162
  if (typeof item === "object" && item && "kind" in item) {
2144
2163
  invariant6(item.kind === "ValueNode", "expecting a ValueNode");
2145
2164
  result.push({
2146
- node: ValueNode3.create(this.dialect.transformPrimitive(item.value, fieldDef.type)),
2165
+ node: ValueNode3.create(this.dialect.transformPrimitive(item.value, fieldDef.type, !!fieldDef.array)),
2147
2166
  raw: item.value
2148
2167
  });
2149
2168
  } else {
2150
- const value = this.dialect.transformPrimitive(item, fieldDef.type);
2169
+ const value = this.dialect.transformPrimitive(item, fieldDef.type, !!fieldDef.array);
2151
2170
  if (Array.isArray(value)) {
2152
2171
  result.push({
2153
2172
  node: RawNode.createWithSql(this.dialect.buildArrayLiteralSQL(value)),
@@ -2378,14 +2397,23 @@ var PolicyPlugin = class {
2378
2397
  get description() {
2379
2398
  return "Enforces access policies defined in the schema.";
2380
2399
  }
2381
- onKyselyQuery({ query, client, proceed, transaction }) {
2400
+ onKyselyQuery({
2401
+ query,
2402
+ client,
2403
+ proceed
2404
+ /*, transaction*/
2405
+ }) {
2382
2406
  const handler = new PolicyHandler(client);
2383
- return handler.handle(query, proceed, transaction);
2407
+ return handler.handle(
2408
+ query,
2409
+ proceed
2410
+ /*, transaction*/
2411
+ );
2384
2412
  }
2385
2413
  };
2386
2414
 
2387
2415
  // src/utils/clone.ts
2388
- import { isPlainObject as isPlainObject2 } from "is-plain-object";
2416
+ import { isPlainObject as isPlainObject2 } from "@zenstackhq/common-helpers";
2389
2417
  function clone(value) {
2390
2418
  if (Array.isArray(value)) {
2391
2419
  return value.map((v) => clone(v));
@@ -2501,13 +2529,13 @@ var BaseOperationHandler = class {
2501
2529
  inMemoryDistinct = distinct;
2502
2530
  }
2503
2531
  }
2504
- if (args?.select) {
2505
- query = this.buildFieldSelection(model, query, args?.select, model);
2532
+ if (args && "select" in args && args.select) {
2533
+ query = this.buildFieldSelection(model, query, args.select, model);
2506
2534
  } else {
2507
2535
  query = this.buildSelectAllScalarFields(model, query, args?.omit);
2508
2536
  }
2509
- if (args?.include) {
2510
- query = this.buildFieldSelection(model, query, args?.include, model);
2537
+ if (args && "include" in args && args.include) {
2538
+ query = this.buildFieldSelection(model, query, args.include, model);
2511
2539
  }
2512
2540
  if (args?.cursor) {
2513
2541
  query = this.buildCursorFilter(model, query, args.cursor, args.orderBy, negateOrderBy);
@@ -2520,8 +2548,13 @@ var BaseOperationHandler = class {
2520
2548
  try {
2521
2549
  result = await query.execute();
2522
2550
  } catch (err) {
2523
- const { sql: sql10, parameters } = query.compile();
2524
- throw new QueryError(`Failed to execute query: ${err}, sql: ${sql10}, parameters: ${parameters}`);
2551
+ const { sql: sql11, parameters } = query.compile();
2552
+ let message = `Failed to execute query: ${err}, sql: ${sql11}`;
2553
+ if (this.options.debug) {
2554
+ message += `, parameters:
2555
+ ${parameters.map((p) => inspect(p)).join("\n")}`;
2556
+ }
2557
+ throw new QueryError(message, err);
2525
2558
  }
2526
2559
  if (inMemoryDistinct) {
2527
2560
  const distinctResult = [];
@@ -2580,30 +2613,20 @@ var BaseOperationHandler = class {
2580
2613
  for (const [field, value] of Object.entries(selections.select)) {
2581
2614
  const fieldDef = requireField(this.schema, model, field);
2582
2615
  const fieldModel = fieldDef.type;
2583
- const jointTable = `${parentAlias}$${field}$count`;
2584
- const joinPairs = buildJoinPairs(this.schema, model, parentAlias, field, jointTable);
2585
- query = query.leftJoin((eb2) => {
2586
- let result = eb2.selectFrom(fieldModel).selectAll();
2587
- if (value && typeof value === "object" && "where" in value && value.where && typeof value.where === "object") {
2588
- const filter = this.dialect.buildFilter(eb2, fieldModel, fieldModel, value.where);
2589
- result = result.where(filter);
2590
- }
2591
- return result.as(jointTable);
2592
- }, (join) => {
2593
- for (const [left, right] of joinPairs) {
2594
- join = join.onRef(left, "=", right);
2595
- }
2596
- return join;
2597
- });
2598
- jsonObject[field] = this.countIdDistinct(eb, fieldDef.type, jointTable);
2616
+ const joinPairs = buildJoinPairs(this.schema, model, parentAlias, field, fieldModel);
2617
+ let fieldCountQuery = eb.selectFrom(fieldModel).select(eb.fn.countAll().as(`_count$${field}`));
2618
+ for (const [left, right] of joinPairs) {
2619
+ fieldCountQuery = fieldCountQuery.whereRef(left, "=", right);
2620
+ }
2621
+ if (value && typeof value === "object" && "where" in value && value.where && typeof value.where === "object") {
2622
+ const filter = this.dialect.buildFilter(eb, fieldModel, fieldModel, value.where);
2623
+ fieldCountQuery = fieldCountQuery.where(filter);
2624
+ }
2625
+ jsonObject[field] = fieldCountQuery;
2599
2626
  }
2600
2627
  query = query.select((eb2) => this.dialect.buildJsonObject(eb2, jsonObject).as("_count"));
2601
2628
  return query;
2602
2629
  }
2603
- countIdDistinct(eb, model, table) {
2604
- const idFields = getIdFields(this.schema, model);
2605
- return eb.fn.count(sql4.join(idFields.map((f) => sql4.ref(`${table}.${f}`)))).distinct();
2606
- }
2607
2630
  buildSelectAllScalarFields(model, query, omit) {
2608
2631
  const modelDef = this.requireModel(model);
2609
2632
  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);
@@ -2669,14 +2692,14 @@ var BaseOperationHandler = class {
2669
2692
  const fieldDef = this.requireField(model, field);
2670
2693
  if (isScalarField(this.schema, model, field) || isForeignKeyField(this.schema, model, field)) {
2671
2694
  if (fieldDef.array && value && typeof value === "object" && "set" in value && Array.isArray(value.set)) {
2672
- createFields[field] = this.dialect.transformPrimitive(value.set, fieldDef.type);
2695
+ createFields[field] = this.dialect.transformPrimitive(value.set, fieldDef.type, true);
2673
2696
  } else {
2674
- createFields[field] = this.dialect.transformPrimitive(value, fieldDef.type);
2697
+ createFields[field] = this.dialect.transformPrimitive(value, fieldDef.type, !!fieldDef.array);
2675
2698
  }
2676
2699
  } else {
2677
2700
  const subM2M = getManyToManyRelation(this.schema, model, field);
2678
2701
  if (!subM2M && fieldDef.relation?.fields && fieldDef.relation?.references) {
2679
- const fkValues = await this.processOwnedRelation(kysely, fieldDef, value);
2702
+ const fkValues = await this.processOwnedRelationForCreate(kysely, fieldDef, value);
2680
2703
  for (let i = 0; i < fieldDef.relation.fields.length; i++) {
2681
2704
  createFields[fieldDef.relation.fields[i]] = fkValues[fieldDef.relation.references[i]];
2682
2705
  }
@@ -2697,7 +2720,7 @@ var BaseOperationHandler = class {
2697
2720
  const createdEntity = await query.executeTakeFirst();
2698
2721
  if (Object.keys(postCreateRelations).length > 0) {
2699
2722
  const relationPromises = Object.entries(postCreateRelations).map(([field, subPayload]) => {
2700
- return this.processNoneOwnedRelation(kysely, model, field, subPayload, createdEntity);
2723
+ return this.processNoneOwnedRelationForCreate(kysely, model, field, subPayload, createdEntity);
2701
2724
  });
2702
2725
  await Promise.all(relationPromises);
2703
2726
  }
@@ -2764,7 +2787,7 @@ var BaseOperationHandler = class {
2764
2787
  const eb = expressionBuilder2();
2765
2788
  return kysely.deleteFrom(m2m.joinTable).where(eb(`${m2m.joinTable}.${m2m.parentFkName}`, "=", parentId)).execute();
2766
2789
  }
2767
- async processOwnedRelation(kysely, relationField, payload) {
2790
+ async processOwnedRelationForCreate(kysely, relationField, payload) {
2768
2791
  if (!payload) {
2769
2792
  return;
2770
2793
  }
@@ -2814,21 +2837,27 @@ var BaseOperationHandler = class {
2814
2837
  }
2815
2838
  return result;
2816
2839
  }
2817
- processNoneOwnedRelation(kysely, contextModel, relationFieldName, payload, parentEntity) {
2840
+ processNoneOwnedRelationForCreate(kysely, contextModel, relationFieldName, payload, parentEntity) {
2818
2841
  const relationFieldDef = this.requireField(contextModel, relationFieldName);
2819
2842
  const relationModel = relationFieldDef.type;
2820
2843
  const tasks = [];
2844
+ const fromRelationContext = {
2845
+ model: contextModel,
2846
+ field: relationFieldName,
2847
+ ids: parentEntity
2848
+ };
2821
2849
  for (const [action, subPayload] of Object.entries(payload)) {
2822
2850
  if (!subPayload) {
2823
2851
  continue;
2824
2852
  }
2825
2853
  switch (action) {
2826
2854
  case "create": {
2827
- tasks.push(...enumerate(subPayload).map((item) => this.create(kysely, relationModel, item, {
2828
- model: contextModel,
2829
- field: relationFieldName,
2830
- ids: parentEntity
2831
- })));
2855
+ tasks.push(...enumerate(subPayload).map((item) => this.create(kysely, relationModel, item, fromRelationContext)));
2856
+ break;
2857
+ }
2858
+ case "createMany": {
2859
+ invariant7(relationFieldDef.array, "relation must be an array for createMany");
2860
+ tasks.push(this.createMany(kysely, relationModel, subPayload, false, fromRelationContext));
2832
2861
  break;
2833
2862
  }
2834
2863
  case "connect": {
@@ -2858,6 +2887,11 @@ var BaseOperationHandler = class {
2858
2887
  return Promise.all(tasks);
2859
2888
  }
2860
2889
  async createMany(kysely, model, input, returnData, fromRelation) {
2890
+ if (!input.data || Array.isArray(input.data) && input.data.length === 0) {
2891
+ return returnData ? [] : {
2892
+ count: 0
2893
+ };
2894
+ }
2861
2895
  const modelDef = this.requireModel(model);
2862
2896
  let relationKeyPairs = [];
2863
2897
  if (fromRelation) {
@@ -2872,7 +2906,7 @@ var BaseOperationHandler = class {
2872
2906
  for (const [name, value] of Object.entries(item)) {
2873
2907
  const fieldDef = this.requireField(model, name);
2874
2908
  invariant7(!fieldDef.relation, "createMany does not support relations");
2875
- newItem[name] = this.dialect.transformPrimitive(value, fieldDef.type);
2909
+ newItem[name] = this.dialect.transformPrimitive(value, fieldDef.type, !!fieldDef.array);
2876
2910
  }
2877
2911
  if (fromRelation) {
2878
2912
  for (const { fk, pk } of relationKeyPairs) {
@@ -2907,7 +2941,7 @@ var BaseOperationHandler = class {
2907
2941
  values[field] = generated;
2908
2942
  }
2909
2943
  } else if (fields[field]?.updatedAt) {
2910
- values[field] = this.dialect.transformPrimitive(/* @__PURE__ */ new Date(), "DateTime");
2944
+ values[field] = this.dialect.transformPrimitive(/* @__PURE__ */ new Date(), "DateTime", false);
2911
2945
  }
2912
2946
  }
2913
2947
  }
@@ -2972,7 +3006,7 @@ var BaseOperationHandler = class {
2972
3006
  if (finalData === data) {
2973
3007
  finalData = clone(data);
2974
3008
  }
2975
- finalData[fieldName] = this.dialect.transformPrimitive(/* @__PURE__ */ new Date(), "DateTime");
3009
+ finalData[fieldName] = this.dialect.transformPrimitive(/* @__PURE__ */ new Date(), "DateTime", false);
2976
3010
  }
2977
3011
  }
2978
3012
  if (Object.keys(finalData).length === 0) {
@@ -2997,7 +3031,7 @@ var BaseOperationHandler = class {
2997
3031
  updateFields[field] = this.transformScalarListUpdate(model, field, fieldDef, finalData[field]);
2998
3032
  continue;
2999
3033
  }
3000
- updateFields[field] = this.dialect.transformPrimitive(finalData[field], fieldDef.type);
3034
+ updateFields[field] = this.dialect.transformPrimitive(finalData[field], fieldDef.type, !!fieldDef.array);
3001
3035
  } else {
3002
3036
  if (!allowRelationUpdate) {
3003
3037
  throw new QueryError(`Relation update not allowed for field "${field}"`);
@@ -3042,7 +3076,7 @@ var BaseOperationHandler = class {
3042
3076
  transformIncrementalUpdate(model, field, fieldDef, payload) {
3043
3077
  invariant7(Object.keys(payload).length === 1, 'Only one of "set", "increment", "decrement", "multiply", or "divide" can be provided');
3044
3078
  const key = Object.keys(payload)[0];
3045
- const value = this.dialect.transformPrimitive(payload[key], fieldDef.type);
3079
+ const value = this.dialect.transformPrimitive(payload[key], fieldDef.type, false);
3046
3080
  const eb = expressionBuilder2();
3047
3081
  const fieldRef = buildFieldRef(this.schema, model, field, this.options, eb);
3048
3082
  return match8(key).with("set", () => value).with("increment", () => eb(fieldRef, "+", value)).with("decrement", () => eb(fieldRef, "-", value)).with("multiply", () => eb(fieldRef, "*", value)).with("divide", () => eb(fieldRef, "/", value)).otherwise(() => {
@@ -3052,7 +3086,7 @@ var BaseOperationHandler = class {
3052
3086
  transformScalarListUpdate(model, field, fieldDef, payload) {
3053
3087
  invariant7(Object.keys(payload).length === 1, 'Only one of "set", "push" can be provided');
3054
3088
  const key = Object.keys(payload)[0];
3055
- const value = this.dialect.transformPrimitive(payload[key], fieldDef.type);
3089
+ const value = this.dialect.transformPrimitive(payload[key], fieldDef.type, true);
3056
3090
  const eb = expressionBuilder2();
3057
3091
  const fieldRef = buildFieldRef(this.schema, model, field, this.options, eb);
3058
3092
  return match8(key).with("set", () => value).with("push", () => {
@@ -3082,7 +3116,7 @@ var BaseOperationHandler = class {
3082
3116
  if (isRelationField(this.schema, model, field)) {
3083
3117
  continue;
3084
3118
  }
3085
- updateFields[field] = this.dialect.transformPrimitive(data[field], fieldDef.type);
3119
+ updateFields[field] = this.dialect.transformPrimitive(data[field], fieldDef.type, !!fieldDef.array);
3086
3120
  }
3087
3121
  let query = kysely.updateTable(model).set(updateFields);
3088
3122
  if (limit === void 0) {
@@ -3100,20 +3134,15 @@ var BaseOperationHandler = class {
3100
3134
  model,
3101
3135
  operation: "update"
3102
3136
  }));
3103
- try {
3104
- if (!returnData) {
3105
- const result = await query.executeTakeFirstOrThrow();
3106
- return {
3107
- count: Number(result.numUpdatedRows)
3108
- };
3109
- } else {
3110
- const idFields = getIdFields(this.schema, model);
3111
- const result = await query.returning(idFields).execute();
3112
- return result;
3113
- }
3114
- } catch (err) {
3115
- const { sql: sql10, parameters } = query.compile();
3116
- throw new QueryError(`Error during updateMany: ${err}, sql: ${sql10}, parameters: ${parameters}`);
3137
+ if (!returnData) {
3138
+ const result = await query.executeTakeFirstOrThrow();
3139
+ return {
3140
+ count: Number(result.numUpdatedRows)
3141
+ };
3142
+ } else {
3143
+ const idFields = getIdFields(this.schema, model);
3144
+ const result = await query.returning(idFields).execute();
3145
+ return result;
3117
3146
  }
3118
3147
  }
3119
3148
  buildIdFieldRefs(kysely, model) {
@@ -3513,7 +3542,7 @@ var BaseOperationHandler = class {
3513
3542
  }, {});
3514
3543
  }
3515
3544
  trimResult(data, args) {
3516
- if (!args.select) {
3545
+ if (!("select" in args) || !args.select) {
3517
3546
  return data;
3518
3547
  }
3519
3548
  return Object.keys(args.select).reduce((acc, field) => {
@@ -3523,9 +3552,9 @@ var BaseOperationHandler = class {
3523
3552
  }
3524
3553
  needReturnRelations(model, args) {
3525
3554
  let returnRelation = false;
3526
- if (args.include) {
3555
+ if ("include" in args && args.include) {
3527
3556
  returnRelation = Object.keys(args.include).length > 0;
3528
- } else if (args.select) {
3557
+ } else if ("select" in args && args.select) {
3529
3558
  returnRelation = Object.entries(args.select).some(([K, v]) => {
3530
3559
  const fieldDef = this.requireField(model, K);
3531
3560
  return fieldDef.relation && v;
@@ -3533,11 +3562,15 @@ var BaseOperationHandler = class {
3533
3562
  }
3534
3563
  return returnRelation;
3535
3564
  }
3536
- async safeTransaction(callback) {
3565
+ async safeTransaction(callback, isolationLevel) {
3537
3566
  if (this.kysely.isTransaction) {
3538
3567
  return callback(this.kysely);
3539
3568
  } else {
3540
- return this.kysely.transaction().setIsolationLevel("repeatable read").execute(callback);
3569
+ let txBuilder = this.kysely.transaction();
3570
+ if (isolationLevel) {
3571
+ txBuilder = txBuilder.setIsolationLevel(isolationLevel);
3572
+ }
3573
+ return txBuilder.execute(callback);
3541
3574
  }
3542
3575
  }
3543
3576
  // Given a unique filter of a model, return the entity ids by trying to
@@ -3556,6 +3589,28 @@ var BaseOperationHandler = class {
3556
3589
  where: uniqueFilter
3557
3590
  });
3558
3591
  }
3592
+ /**
3593
+ * Normalize input args to strip `undefined` fields
3594
+ */
3595
+ normalizeArgs(args) {
3596
+ if (!args) {
3597
+ return;
3598
+ }
3599
+ const newArgs = clone(args);
3600
+ this.doNormalizeArgs(newArgs);
3601
+ return newArgs;
3602
+ }
3603
+ doNormalizeArgs(args) {
3604
+ if (args && typeof args === "object") {
3605
+ for (const [key, value] of Object.entries(args)) {
3606
+ if (value === void 0) {
3607
+ delete args[key];
3608
+ } else if (value && isPlainObject3(value)) {
3609
+ this.doNormalizeArgs(value);
3610
+ }
3611
+ }
3612
+ }
3613
+ }
3559
3614
  };
3560
3615
 
3561
3616
  // src/client/crud/operations/aggregate.ts
@@ -3564,21 +3619,22 @@ var AggregateOperationHandler = class extends BaseOperationHandler {
3564
3619
  __name(this, "AggregateOperationHandler");
3565
3620
  }
3566
3621
  async handle(_operation, args) {
3567
- const validatedArgs = this.inputValidator.validateAggregateArgs(this.model, args);
3622
+ const normalizedArgs = this.normalizeArgs(args);
3623
+ const parsedArgs = this.inputValidator.validateAggregateArgs(this.model, normalizedArgs);
3568
3624
  let query = this.kysely.selectFrom((eb) => {
3569
- let subQuery = eb.selectFrom(this.model).selectAll(this.model).where((eb1) => this.dialect.buildFilter(eb1, this.model, this.model, validatedArgs?.where));
3570
- const skip = validatedArgs?.skip;
3571
- let take = validatedArgs?.take;
3625
+ let subQuery = eb.selectFrom(this.model).selectAll(this.model).where((eb1) => this.dialect.buildFilter(eb1, this.model, this.model, parsedArgs?.where));
3626
+ const skip = parsedArgs?.skip;
3627
+ let take = parsedArgs?.take;
3572
3628
  let negateOrderBy = false;
3573
3629
  if (take !== void 0 && take < 0) {
3574
3630
  negateOrderBy = true;
3575
3631
  take = -take;
3576
3632
  }
3577
3633
  subQuery = this.dialect.buildSkipTake(subQuery, skip, take);
3578
- subQuery = this.dialect.buildOrderBy(subQuery, this.model, this.model, validatedArgs.orderBy, skip !== void 0 || take !== void 0, negateOrderBy);
3634
+ subQuery = this.dialect.buildOrderBy(subQuery, this.model, this.model, parsedArgs.orderBy, skip !== void 0 || take !== void 0, negateOrderBy);
3579
3635
  return subQuery.as("$sub");
3580
3636
  });
3581
- for (const [key, value] of Object.entries(validatedArgs)) {
3637
+ for (const [key, value] of Object.entries(parsedArgs)) {
3582
3638
  switch (key) {
3583
3639
  case "_count": {
3584
3640
  if (value === true) {
@@ -3657,14 +3713,15 @@ var CountOperationHandler = class extends BaseOperationHandler {
3657
3713
  __name(this, "CountOperationHandler");
3658
3714
  }
3659
3715
  async handle(_operation, args) {
3660
- const validatedArgs = this.inputValidator.validateCountArgs(this.model, args);
3716
+ const normalizedArgs = this.normalizeArgs(args);
3717
+ const parsedArgs = this.inputValidator.validateCountArgs(this.model, normalizedArgs);
3661
3718
  let query = this.kysely.selectFrom((eb) => {
3662
- let subQuery = eb.selectFrom(this.model).selectAll().where((eb1) => this.dialect.buildFilter(eb1, this.model, this.model, validatedArgs?.where));
3663
- subQuery = this.dialect.buildSkipTake(subQuery, validatedArgs?.skip, validatedArgs?.take);
3719
+ let subQuery = eb.selectFrom(this.model).selectAll().where((eb1) => this.dialect.buildFilter(eb1, this.model, this.model, parsedArgs?.where));
3720
+ subQuery = this.dialect.buildSkipTake(subQuery, parsedArgs?.skip, parsedArgs?.take);
3664
3721
  return subQuery.as("$sub");
3665
3722
  });
3666
- if (validatedArgs?.select && typeof validatedArgs.select === "object") {
3667
- query = query.select((eb) => Object.keys(validatedArgs.select).map((key) => key === "_all" ? eb.cast(eb.fn.countAll(), "integer").as("_all") : eb.cast(eb.fn.count(sql6.ref(`$sub.${key}`)), "integer").as(key)));
3723
+ if (parsedArgs?.select && typeof parsedArgs.select === "object") {
3724
+ query = query.select((eb) => Object.keys(parsedArgs.select).map((key) => key === "_all" ? eb.cast(eb.fn.countAll(), "integer").as("_all") : eb.cast(eb.fn.count(sql6.ref(`$sub.${key}`)), "integer").as(key)));
3668
3725
  return query.executeTakeFirstOrThrow();
3669
3726
  } else {
3670
3727
  query = query.select((eb) => eb.cast(eb.fn.countAll(), "integer").as("count"));
@@ -3681,10 +3738,11 @@ var CreateOperationHandler = class extends BaseOperationHandler {
3681
3738
  __name(this, "CreateOperationHandler");
3682
3739
  }
3683
3740
  async handle(operation, args) {
3684
- return match10(operation).with("create", () => this.runCreate(this.inputValidator.validateCreateArgs(this.model, args))).with("createMany", () => {
3685
- return this.runCreateMany(this.inputValidator.validateCreateManyArgs(this.model, args));
3741
+ const normalizedArgs = this.normalizeArgs(args);
3742
+ return match10(operation).with("create", () => this.runCreate(this.inputValidator.validateCreateArgs(this.model, normalizedArgs))).with("createMany", () => {
3743
+ return this.runCreateMany(this.inputValidator.validateCreateManyArgs(this.model, normalizedArgs));
3686
3744
  }).with("createManyAndReturn", () => {
3687
- return this.runCreateManyAndReturn(this.inputValidator.validateCreateManyAndReturnArgs(this.model, args));
3745
+ return this.runCreateManyAndReturn(this.inputValidator.validateCreateManyAndReturnArgs(this.model, normalizedArgs));
3688
3746
  }).exhaustive();
3689
3747
  }
3690
3748
  async runCreate(args) {
@@ -3734,7 +3792,8 @@ var DeleteOperationHandler = class extends BaseOperationHandler {
3734
3792
  __name(this, "DeleteOperationHandler");
3735
3793
  }
3736
3794
  async handle(operation, args) {
3737
- return match11(operation).with("delete", () => this.runDelete(this.inputValidator.validateDeleteArgs(this.model, args))).with("deleteMany", () => this.runDeleteMany(this.inputValidator.validateDeleteManyArgs(this.model, args))).exhaustive();
3795
+ const normalizedArgs = this.normalizeArgs(args);
3796
+ return match11(operation).with("delete", () => this.runDelete(this.inputValidator.validateDeleteArgs(this.model, normalizedArgs))).with("deleteMany", () => this.runDeleteMany(this.inputValidator.validateDeleteManyArgs(this.model, normalizedArgs))).exhaustive();
3738
3797
  }
3739
3798
  async runDelete(args) {
3740
3799
  const existing = await this.readUnique(this.kysely, this.model, {
@@ -3764,7 +3823,8 @@ var FindOperationHandler = class extends BaseOperationHandler {
3764
3823
  __name(this, "FindOperationHandler");
3765
3824
  }
3766
3825
  async handle(operation, args, validateArgs = true) {
3767
- const parsedArgs = validateArgs ? this.inputValidator.validateFindArgs(this.model, operation === "findUnique", args) : args;
3826
+ const normalizedArgs = this.normalizeArgs(args);
3827
+ const parsedArgs = validateArgs ? this.inputValidator.validateFindArgs(this.model, operation === "findUnique", normalizedArgs) : normalizedArgs;
3768
3828
  const result = await this.read(this.client.$qb, this.model, parsedArgs);
3769
3829
  const finalResult = operation === "findMany" ? result : result[0] ?? null;
3770
3830
  return finalResult;
@@ -3774,16 +3834,17 @@ var FindOperationHandler = class extends BaseOperationHandler {
3774
3834
  // src/client/crud/operations/group-by.ts
3775
3835
  import { sql as sql7 } from "kysely";
3776
3836
  import { match as match12 } from "ts-pattern";
3777
- var GroupByeOperationHandler = class extends BaseOperationHandler {
3837
+ var GroupByOperationHandler = class extends BaseOperationHandler {
3778
3838
  static {
3779
- __name(this, "GroupByeOperationHandler");
3839
+ __name(this, "GroupByOperationHandler");
3780
3840
  }
3781
3841
  async handle(_operation, args) {
3782
- const validatedArgs = this.inputValidator.validateGroupByArgs(this.model, args);
3842
+ const normalizedArgs = this.normalizeArgs(args);
3843
+ const parsedArgs = this.inputValidator.validateGroupByArgs(this.model, normalizedArgs);
3783
3844
  let query = this.kysely.selectFrom((eb) => {
3784
- let subQuery = eb.selectFrom(this.model).selectAll().where((eb1) => this.dialect.buildFilter(eb1, this.model, this.model, validatedArgs?.where));
3785
- const skip = validatedArgs?.skip;
3786
- let take = validatedArgs?.take;
3845
+ let subQuery = eb.selectFrom(this.model).selectAll().where((eb1) => this.dialect.buildFilter(eb1, this.model, this.model, parsedArgs?.where));
3846
+ const skip = parsedArgs?.skip;
3847
+ let take = parsedArgs?.take;
3787
3848
  let negateOrderBy = false;
3788
3849
  if (take !== void 0 && take < 0) {
3789
3850
  negateOrderBy = true;
@@ -3793,20 +3854,20 @@ var GroupByeOperationHandler = class extends BaseOperationHandler {
3793
3854
  subQuery = this.dialect.buildOrderBy(subQuery, this.model, this.model, void 0, skip !== void 0 || take !== void 0, negateOrderBy);
3794
3855
  return subQuery.as("$sub");
3795
3856
  });
3796
- const bys = typeof validatedArgs.by === "string" ? [
3797
- validatedArgs.by
3798
- ] : validatedArgs.by;
3857
+ const bys = typeof parsedArgs.by === "string" ? [
3858
+ parsedArgs.by
3859
+ ] : parsedArgs.by;
3799
3860
  query = query.groupBy(bys);
3800
- if (validatedArgs.orderBy) {
3801
- query = this.dialect.buildOrderBy(query, this.model, "$sub", validatedArgs.orderBy, false, false);
3861
+ if (parsedArgs.orderBy) {
3862
+ query = this.dialect.buildOrderBy(query, this.model, "$sub", parsedArgs.orderBy, false, false);
3802
3863
  }
3803
- if (validatedArgs.having) {
3804
- query = query.having((eb1) => this.dialect.buildFilter(eb1, this.model, "$sub", validatedArgs.having));
3864
+ if (parsedArgs.having) {
3865
+ query = query.having((eb1) => this.dialect.buildFilter(eb1, this.model, "$sub", parsedArgs.having));
3805
3866
  }
3806
3867
  for (const by of bys) {
3807
3868
  query = query.select(() => sql7.ref(`$sub.${by}`).as(by));
3808
3869
  }
3809
- for (const [key, value] of Object.entries(validatedArgs)) {
3870
+ for (const [key, value] of Object.entries(parsedArgs)) {
3810
3871
  switch (key) {
3811
3872
  case "_count": {
3812
3873
  if (value === true) {
@@ -3889,7 +3950,8 @@ var UpdateOperationHandler = class extends BaseOperationHandler {
3889
3950
  __name(this, "UpdateOperationHandler");
3890
3951
  }
3891
3952
  async handle(operation, args) {
3892
- return match13(operation).with("update", () => this.runUpdate(this.inputValidator.validateUpdateArgs(this.model, args))).with("updateMany", () => this.runUpdateMany(this.inputValidator.validateUpdateManyArgs(this.model, args))).with("updateManyAndReturn", () => this.runUpdateManyAndReturn(this.inputValidator.validateUpdateManyAndReturnArgs(this.model, args))).with("upsert", () => this.runUpsert(this.inputValidator.validateUpsertArgs(this.model, args))).exhaustive();
3953
+ const normalizedArgs = this.normalizeArgs(args);
3954
+ return match13(operation).with("update", () => this.runUpdate(this.inputValidator.validateUpdateArgs(this.model, normalizedArgs))).with("updateMany", () => this.runUpdateMany(this.inputValidator.validateUpdateManyArgs(this.model, normalizedArgs))).with("updateManyAndReturn", () => this.runUpdateManyAndReturn(this.inputValidator.validateUpdateManyAndReturnArgs(this.model, normalizedArgs))).with("upsert", () => this.runUpsert(this.inputValidator.validateUpsertArgs(this.model, normalizedArgs))).exhaustive();
3893
3955
  }
3894
3956
  async runUpdate(args) {
3895
3957
  const result = await this.safeTransaction(async (tx) => {
@@ -3945,6 +4007,7 @@ var UpdateOperationHandler = class extends BaseOperationHandler {
3945
4007
  };
3946
4008
 
3947
4009
  // src/client/crud/validator.ts
4010
+ import { invariant as invariant8 } from "@zenstackhq/common-helpers";
3948
4011
  import Decimal from "decimal.js";
3949
4012
  import stableStringify from "json-stable-stringify";
3950
4013
  import { match as match14, P as P2 } from "ts-pattern";
@@ -3954,10 +4017,9 @@ var InputValidator = class {
3954
4017
  __name(this, "InputValidator");
3955
4018
  }
3956
4019
  schema;
3957
- schemaCache;
4020
+ schemaCache = /* @__PURE__ */ new Map();
3958
4021
  constructor(schema) {
3959
4022
  this.schema = schema;
3960
- this.schemaCache = /* @__PURE__ */ new Map();
3961
4023
  }
3962
4024
  validateFindArgs(model, unique, args) {
3963
4025
  return this.validate(model, "find", {
@@ -4014,7 +4076,7 @@ var InputValidator = class {
4014
4076
  }
4015
4077
  const { error } = schema.safeParse(args);
4016
4078
  if (error) {
4017
- throw new QueryError(`Invalid ${operation} args: ${error.message}`);
4079
+ throw new InputValidationError(`Invalid ${operation} args: ${error.message}`, error);
4018
4080
  }
4019
4081
  return args;
4020
4082
  }
@@ -4061,7 +4123,7 @@ var InputValidator = class {
4061
4123
  makeWhereSchema(model, unique, withoutRelationFields = false) {
4062
4124
  const modelDef = getModel(this.schema, model);
4063
4125
  if (!modelDef) {
4064
- throw new QueryError(`Model "${model}" not found`);
4126
+ throw new QueryError(`Model "${model}" not found in schema`);
4065
4127
  }
4066
4128
  const fields = {};
4067
4129
  for (const field of Object.keys(modelDef.fields)) {
@@ -4111,14 +4173,28 @@ var InputValidator = class {
4111
4173
  const uniqueFields = getUniqueFields(this.schema, model);
4112
4174
  for (const uniqueField of uniqueFields) {
4113
4175
  if ("defs" in uniqueField) {
4114
- fields[uniqueField.name] = z.object(Object.fromEntries(Object.entries(uniqueField.defs).map(([key, def]) => [
4115
- key,
4116
- this.makePrimitiveFilterSchema(def.type, !!def.optional)
4117
- ]))).optional();
4176
+ fields[uniqueField.name] = z.object(Object.fromEntries(Object.entries(uniqueField.defs).map(([key, def]) => {
4177
+ invariant8(!def.relation, "unique field cannot be a relation");
4178
+ let fieldSchema;
4179
+ const enumDef = getEnum(this.schema, def.type);
4180
+ if (enumDef) {
4181
+ if (Object.keys(enumDef).length > 0) {
4182
+ fieldSchema = this.makeEnumFilterSchema(enumDef, !!def.optional);
4183
+ } else {
4184
+ fieldSchema = z.never();
4185
+ }
4186
+ } else {
4187
+ fieldSchema = this.makePrimitiveFilterSchema(def.type, !!def.optional);
4188
+ }
4189
+ return [
4190
+ key,
4191
+ fieldSchema
4192
+ ];
4193
+ }))).optional();
4118
4194
  }
4119
4195
  }
4120
4196
  }
4121
- fields["$expr"] = z.function().optional();
4197
+ fields["$expr"] = z.custom((v) => typeof v === "function").optional();
4122
4198
  fields["AND"] = this.orArray(z.lazy(() => this.makeWhereSchema(model, false, withoutRelationFields)), true).optional();
4123
4199
  fields["OR"] = z.lazy(() => this.makeWhereSchema(model, false, withoutRelationFields)).array().optional();
4124
4200
  fields["NOT"] = this.orArray(z.lazy(() => this.makeWhereSchema(model, false, withoutRelationFields)), true).optional();
@@ -4164,7 +4240,7 @@ var InputValidator = class {
4164
4240
  });
4165
4241
  }
4166
4242
  makePrimitiveFilterSchema(type, optional) {
4167
- return match14(type).with("String", () => this.makeStringFilterSchema(optional)).with(P2.union("Int", "Float", "Decimal", "BigInt"), (type2) => this.makeNumberFilterSchema(this.makePrimitiveSchema(type2), optional)).with("Boolean", () => this.makeBooleanFilterSchema(optional)).with("DateTime", () => this.makeDateTimeFilterSchema(optional)).with("Bytes", () => this.makeBytesFilterSchema(optional)).exhaustive();
4243
+ return match14(type).with("String", () => this.makeStringFilterSchema(optional)).with(P2.union("Int", "Float", "Decimal", "BigInt"), (type2) => this.makeNumberFilterSchema(this.makePrimitiveSchema(type2), optional)).with("Boolean", () => this.makeBooleanFilterSchema(optional)).with("DateTime", () => this.makeDateTimeFilterSchema(optional)).with("Bytes", () => this.makeBytesFilterSchema(optional)).with("Json", () => z.any()).with("Unsupported", () => z.never()).exhaustive();
4168
4244
  }
4169
4245
  makeDateTimeFilterSchema(optional) {
4170
4246
  return this.makeCommonPrimitiveFilterSchema(z.union([
@@ -4358,8 +4434,8 @@ var InputValidator = class {
4358
4434
  return this.refineForSelectOmitMutuallyExclusive(result).optional();
4359
4435
  }
4360
4436
  makeCreateDataSchema(model, canBeArray, withoutFields = [], withoutRelationFields = false) {
4361
- const regularAndFkFields = {};
4362
- const regularAndRelationFields = {};
4437
+ const uncheckedVariantFields = {};
4438
+ const checkedVariantFields = {};
4363
4439
  const modelDef = requireModel(this.schema, model);
4364
4440
  const hasRelation = !withoutRelationFields && Object.entries(modelDef.fields).some(([f, def]) => !withoutFields.includes(f) && def.relation);
4365
4441
  Object.keys(modelDef.fields).forEach((field) => {
@@ -4401,7 +4477,10 @@ var InputValidator = class {
4401
4477
  if (fieldDef.optional && !fieldDef.array) {
4402
4478
  fieldSchema = fieldSchema.nullable();
4403
4479
  }
4404
- regularAndRelationFields[field] = fieldSchema;
4480
+ checkedVariantFields[field] = fieldSchema;
4481
+ if (fieldDef.array || !fieldDef.relation.references) {
4482
+ uncheckedVariantFields[field] = fieldSchema;
4483
+ }
4405
4484
  } else {
4406
4485
  let fieldSchema = this.makePrimitiveSchema(fieldDef.type);
4407
4486
  if (fieldDef.array) {
@@ -4418,23 +4497,23 @@ var InputValidator = class {
4418
4497
  if (fieldDef.optional) {
4419
4498
  fieldSchema = fieldSchema.nullable();
4420
4499
  }
4421
- regularAndFkFields[field] = fieldSchema;
4500
+ uncheckedVariantFields[field] = fieldSchema;
4422
4501
  if (!fieldDef.foreignKeyFor) {
4423
- regularAndRelationFields[field] = fieldSchema;
4502
+ checkedVariantFields[field] = fieldSchema;
4424
4503
  }
4425
4504
  }
4426
4505
  });
4427
4506
  if (!hasRelation) {
4428
- return this.orArray(z.object(regularAndFkFields).strict(), canBeArray);
4507
+ return this.orArray(z.object(uncheckedVariantFields).strict(), canBeArray);
4429
4508
  } else {
4430
4509
  return z.union([
4431
- z.object(regularAndFkFields).strict(),
4432
- z.object(regularAndRelationFields).strict(),
4510
+ z.object(uncheckedVariantFields).strict(),
4511
+ z.object(checkedVariantFields).strict(),
4433
4512
  ...canBeArray ? [
4434
- z.array(z.object(regularAndFkFields).strict())
4513
+ z.array(z.object(uncheckedVariantFields).strict())
4435
4514
  ] : [],
4436
4515
  ...canBeArray ? [
4437
- z.array(z.object(regularAndRelationFields).strict())
4516
+ z.array(z.object(checkedVariantFields).strict())
4438
4517
  ] : []
4439
4518
  ]);
4440
4519
  }
@@ -4479,7 +4558,7 @@ var InputValidator = class {
4479
4558
  fields["deleteMany"] = this.makeDeleteRelationDataSchema(fieldType, true, false).optional();
4480
4559
  }
4481
4560
  }
4482
- return z.object(fields).strict().refine((v) => Object.keys(v).length > 0, "At least one action is required");
4561
+ return z.object(fields).strict();
4483
4562
  }
4484
4563
  makeSetDataSchema(model, canBeArray) {
4485
4564
  return this.orArray(this.makeWhereSchema(model, true), canBeArray);
@@ -4556,8 +4635,8 @@ var InputValidator = class {
4556
4635
  return this.refineForSelectIncludeMutuallyExclusive(schema);
4557
4636
  }
4558
4637
  makeUpdateDataSchema(model, withoutFields = [], withoutRelationFields = false) {
4559
- const regularAndFkFields = {};
4560
- const regularAndRelationFields = {};
4638
+ const uncheckedVariantFields = {};
4639
+ const checkedVariantFields = {};
4561
4640
  const modelDef = requireModel(this.schema, model);
4562
4641
  const hasRelation = Object.entries(modelDef.fields).some(([key, value]) => value.relation && !withoutFields.includes(key));
4563
4642
  Object.keys(modelDef.fields).forEach((field) => {
@@ -4582,7 +4661,10 @@ var InputValidator = class {
4582
4661
  if (fieldDef.optional && !fieldDef.array) {
4583
4662
  fieldSchema = fieldSchema.nullable();
4584
4663
  }
4585
- regularAndRelationFields[field] = fieldSchema;
4664
+ checkedVariantFields[field] = fieldSchema;
4665
+ if (fieldDef.array || !fieldDef.relation.references) {
4666
+ uncheckedVariantFields[field] = fieldSchema;
4667
+ }
4586
4668
  } else {
4587
4669
  let fieldSchema = this.makePrimitiveSchema(fieldDef.type).optional();
4588
4670
  if (this.isNumericField(fieldDef)) {
@@ -4609,18 +4691,18 @@ var InputValidator = class {
4609
4691
  if (fieldDef.optional) {
4610
4692
  fieldSchema = fieldSchema.nullable();
4611
4693
  }
4612
- regularAndFkFields[field] = fieldSchema;
4694
+ uncheckedVariantFields[field] = fieldSchema;
4613
4695
  if (!fieldDef.foreignKeyFor) {
4614
- regularAndRelationFields[field] = fieldSchema;
4696
+ checkedVariantFields[field] = fieldSchema;
4615
4697
  }
4616
4698
  }
4617
4699
  });
4618
4700
  if (!hasRelation) {
4619
- return z.object(regularAndFkFields).strict();
4701
+ return z.object(uncheckedVariantFields).strict();
4620
4702
  } else {
4621
4703
  return z.union([
4622
- z.object(regularAndFkFields).strict(),
4623
- z.object(regularAndRelationFields).strict()
4704
+ z.object(uncheckedVariantFields).strict(),
4705
+ z.object(checkedVariantFields).strict()
4624
4706
  ]);
4625
4707
  }
4626
4708
  }
@@ -4914,8 +4996,9 @@ function performanceNow() {
4914
4996
  __name(performanceNow, "performanceNow");
4915
4997
 
4916
4998
  // src/client/executor/zenstack-query-executor.ts
4917
- import { AndNode as AndNode2, DefaultQueryExecutor, DeleteQueryNode as DeleteQueryNode2, InsertQueryNode as InsertQueryNode2, ReturningNode as ReturningNode3, SelectionNode as SelectionNode4, SingleConnectionProvider, UpdateQueryNode as UpdateQueryNode2, WhereNode as WhereNode3 } from "kysely";
4999
+ import { AndNode as AndNode2, DefaultQueryExecutor, DeleteQueryNode as DeleteQueryNode2, InsertQueryNode as InsertQueryNode2, ReturningNode as ReturningNode3, SelectionNode as SelectionNode4, UpdateQueryNode as UpdateQueryNode2, WhereNode as WhereNode3 } from "kysely";
4918
5000
  import { nanoid as nanoid2 } from "nanoid";
5001
+ import { inspect as inspect2 } from "util";
4919
5002
  import { match as match15 } from "ts-pattern";
4920
5003
 
4921
5004
  // src/client/executor/name-mapper.ts
@@ -4925,11 +5008,11 @@ var QueryNameMapper = class extends OperationNodeTransformer2 {
4925
5008
  __name(this, "QueryNameMapper");
4926
5009
  }
4927
5010
  schema;
4928
- modelToTableMap;
4929
- fieldToColumnMap;
4930
- modelStack;
5011
+ modelToTableMap = /* @__PURE__ */ new Map();
5012
+ fieldToColumnMap = /* @__PURE__ */ new Map();
5013
+ modelStack = [];
4931
5014
  constructor(schema) {
4932
- super(), this.schema = schema, this.modelToTableMap = /* @__PURE__ */ new Map(), this.fieldToColumnMap = /* @__PURE__ */ new Map(), this.modelStack = [];
5015
+ super(), this.schema = schema;
4933
5016
  for (const [modelName, modelDef] of Object.entries(schema.models)) {
4934
5017
  const mappedName = this.getMappedName(modelDef);
4935
5018
  if (mappedName) {
@@ -5150,7 +5233,9 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends DefaultQueryExe
5150
5233
  mutationInterceptionInfo = await this.callMutationInterceptionFilters(queryNode);
5151
5234
  }
5152
5235
  const task = /* @__PURE__ */ __name(async () => {
5153
- await this.callBeforeMutationHooks(queryNode, mutationInterceptionInfo);
5236
+ if (this.isMutationNode(queryNode)) {
5237
+ await this.callBeforeMutationHooks(queryNode, mutationInterceptionInfo);
5238
+ }
5154
5239
  const oldQueryNode = queryNode;
5155
5240
  if ((InsertQueryNode2.is(queryNode) || DeleteQueryNode2.is(queryNode)) && mutationInterceptionInfo?.loadAfterMutationEntity) {
5156
5241
  queryNode = {
@@ -5160,19 +5245,19 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends DefaultQueryExe
5160
5245
  ])
5161
5246
  };
5162
5247
  }
5163
- const result = await this.proceedQueryWithKyselyInterceptors(queryNode, queryId);
5164
- await this.callAfterQueryInterceptionFilters(result, queryNode, mutationInterceptionInfo);
5248
+ const queryParams = compiledQuery.$raw ? compiledQuery.parameters : void 0;
5249
+ const result = await this.proceedQueryWithKyselyInterceptors(queryNode, queryParams, queryId);
5250
+ if (this.isMutationNode(queryNode)) {
5251
+ await this.callAfterQueryInterceptionFilters(result, queryNode, mutationInterceptionInfo);
5252
+ }
5165
5253
  if (oldQueryNode !== queryNode) {
5166
5254
  }
5167
5255
  return result;
5168
5256
  }, "task");
5169
- return this.executeWithTransaction(task, !!mutationInterceptionInfo?.useTransactionForMutation);
5257
+ return task();
5170
5258
  }
5171
- proceedQueryWithKyselyInterceptors(queryNode, queryId) {
5172
- let proceed = /* @__PURE__ */ __name((q) => this.proceedQuery(q, queryId), "proceed");
5173
- const makeTx = /* @__PURE__ */ __name((p) => (callback) => {
5174
- return this.executeWithTransaction(() => callback(p));
5175
- }, "makeTx");
5259
+ proceedQueryWithKyselyInterceptors(queryNode, parameters, queryId) {
5260
+ let proceed = /* @__PURE__ */ __name((q) => this.proceedQuery(q, parameters, queryId), "proceed");
5176
5261
  const hooks = this.options.plugins?.filter((plugin) => typeof plugin.onKyselyQuery === "function").map((plugin) => plugin.onKyselyQuery.bind(plugin)) ?? [];
5177
5262
  for (const hook of hooks) {
5178
5263
  const _proceed = proceed;
@@ -5182,20 +5267,30 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends DefaultQueryExe
5182
5267
  schema: this.client.$schema,
5183
5268
  kysely: this.kysely,
5184
5269
  query,
5185
- proceed: _proceed,
5186
- transaction: makeTx(_proceed)
5270
+ proceed: _proceed
5187
5271
  });
5188
5272
  }, "proceed");
5189
5273
  }
5190
5274
  return proceed(queryNode);
5191
5275
  }
5192
- async proceedQuery(query, queryId) {
5276
+ async proceedQuery(query, parameters, queryId) {
5193
5277
  const finalQuery = this.nameMapper.transformNode(query);
5194
- const compiled = this.compileQuery(finalQuery);
5278
+ let compiled = this.compileQuery(finalQuery);
5279
+ if (parameters) {
5280
+ compiled = {
5281
+ ...compiled,
5282
+ parameters
5283
+ };
5284
+ }
5195
5285
  try {
5196
- return this.driver.txConnection ? await super.withConnectionProvider(new SingleConnectionProvider(this.driver.txConnection)).executeQuery(compiled, queryId) : await super.executeQuery(compiled, queryId);
5286
+ return await super.executeQuery(compiled, queryId);
5197
5287
  } catch (err) {
5198
- throw new QueryError(`Failed to execute query: ${err}, sql: ${compiled.sql}, parameters: ${compiled.parameters}`);
5288
+ let message = `Failed to execute query: ${err}, sql: ${compiled.sql}`;
5289
+ if (this.options.debug) {
5290
+ message += `, parameters:
5291
+ ${compiled.parameters.map((p) => inspect2(p)).join("\n")}`;
5292
+ }
5293
+ throw new QueryError(message, err);
5199
5294
  }
5200
5295
  }
5201
5296
  isMutationNode(queryNode) {
@@ -5223,24 +5318,9 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends DefaultQueryExe
5223
5318
  return new _ZenStackQueryExecutor(this.client, this.driver, this.compiler, this.adapter, this.connectionProvider, []);
5224
5319
  }
5225
5320
  withConnectionProvider(connectionProvider) {
5226
- return new _ZenStackQueryExecutor(this.client, this.driver, this.compiler, this.adapter, connectionProvider);
5227
- }
5228
- async executeWithTransaction(callback, useTransaction = true) {
5229
- if (!useTransaction || this.driver.txConnection) {
5230
- return callback();
5231
- } else {
5232
- return this.provideConnection(async (connection) => {
5233
- try {
5234
- await this.driver.beginTransaction(connection, {});
5235
- const result = await callback();
5236
- await this.driver.commitTransaction(connection);
5237
- return result;
5238
- } catch (error) {
5239
- await this.driver.rollbackTransaction(connection);
5240
- throw error;
5241
- }
5242
- });
5243
- }
5321
+ const newExecutor = new _ZenStackQueryExecutor(this.client, this.driver, this.compiler, this.adapter, connectionProvider);
5322
+ newExecutor.client = this.client.withExecutor(newExecutor);
5323
+ return newExecutor;
5244
5324
  }
5245
5325
  get hasMutationHooks() {
5246
5326
  return this.client.$options.plugins?.some((plugin) => plugin.beforeEntityMutation || plugin.afterEntityMutation);
@@ -5282,14 +5362,13 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends DefaultQueryExe
5282
5362
  queryNode
5283
5363
  });
5284
5364
  result.intercept ||= filterResult.intercept;
5285
- result.useTransactionForMutation ||= filterResult.useTransactionForMutation;
5286
5365
  result.loadBeforeMutationEntity ||= filterResult.loadBeforeMutationEntity;
5287
5366
  result.loadAfterMutationEntity ||= filterResult.loadAfterMutationEntity;
5288
5367
  }
5289
5368
  }
5290
5369
  let beforeMutationEntities;
5291
5370
  if (result.loadBeforeMutationEntity && (UpdateQueryNode2.is(queryNode) || DeleteQueryNode2.is(queryNode))) {
5292
- beforeMutationEntities = await this.loadEntities(this.kysely, mutationModel, where);
5371
+ beforeMutationEntities = await this.loadEntities(mutationModel, where);
5293
5372
  }
5294
5373
  return {
5295
5374
  ...result,
@@ -5302,15 +5381,14 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends DefaultQueryExe
5302
5381
  return void 0;
5303
5382
  }
5304
5383
  }
5305
- callBeforeMutationHooks(queryNode, mutationInterceptionInfo) {
5384
+ async callBeforeMutationHooks(queryNode, mutationInterceptionInfo) {
5306
5385
  if (!mutationInterceptionInfo?.intercept) {
5307
5386
  return;
5308
5387
  }
5309
5388
  if (this.options.plugins) {
5310
5389
  for (const plugin of this.options.plugins) {
5311
5390
  if (plugin.beforeEntityMutation) {
5312
- plugin.beforeEntityMutation({
5313
- // context: this.queryContext,
5391
+ await plugin.beforeEntityMutation({
5314
5392
  model: this.getMutationModel(queryNode),
5315
5393
  action: mutationInterceptionInfo.action,
5316
5394
  queryNode,
@@ -5331,12 +5409,12 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends DefaultQueryExe
5331
5409
  let afterMutationEntities = void 0;
5332
5410
  if (mutationInterceptionInfo.loadAfterMutationEntity) {
5333
5411
  if (UpdateQueryNode2.is(queryNode)) {
5334
- afterMutationEntities = await this.loadEntities(this.kysely, mutationModel, mutationInterceptionInfo.where);
5412
+ afterMutationEntities = await this.loadEntities(mutationModel, mutationInterceptionInfo.where);
5335
5413
  } else {
5336
5414
  afterMutationEntities = queryResult.rows;
5337
5415
  }
5338
5416
  }
5339
- plugin.afterEntityMutation({
5417
+ await plugin.afterEntityMutation({
5340
5418
  model: this.getMutationModel(queryNode),
5341
5419
  action: mutationInterceptionInfo.action,
5342
5420
  queryNode,
@@ -5347,17 +5425,17 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends DefaultQueryExe
5347
5425
  }
5348
5426
  }
5349
5427
  }
5350
- async loadEntities(kysely, model, where) {
5351
- const selectQuery = kysely.selectFrom(model).selectAll();
5428
+ async loadEntities(model, where) {
5429
+ const selectQuery = this.kysely.selectFrom(model).selectAll();
5352
5430
  let selectQueryNode = selectQuery.toOperationNode();
5353
5431
  selectQueryNode = {
5354
5432
  ...selectQueryNode,
5355
5433
  where: this.andNodes(selectQueryNode.where, where)
5356
5434
  };
5357
- const compiled = kysely.getExecutor().compileQuery(selectQueryNode, {
5435
+ const compiled = this.compileQuery(selectQueryNode);
5436
+ const result = await this.executeQuery(compiled, {
5358
5437
  queryId: `zenstack-${nanoid2()}`
5359
5438
  });
5360
- const result = await kysely.executeQuery(compiled);
5361
5439
  return result.rows;
5362
5440
  }
5363
5441
  andNodes(condition1, condition2) {
@@ -5386,8 +5464,8 @@ __export(functions_exports, {
5386
5464
  search: () => search,
5387
5465
  startsWith: () => startsWith
5388
5466
  });
5467
+ import { invariant as invariant9, lowerCaseFirst, upperCaseFirst } from "@zenstackhq/common-helpers";
5389
5468
  import { sql as sql8, ValueNode as ValueNode4 } from "kysely";
5390
- import invariant8 from "tiny-invariant";
5391
5469
  import { match as match16 } from "ts-pattern";
5392
5470
  var contains = /* @__PURE__ */ __name((eb, args) => {
5393
5471
  const [field, search2, caseInsensitive = false] = args;
@@ -5493,8 +5571,8 @@ var currentOperation = /* @__PURE__ */ __name((_eb, args, { operation }) => {
5493
5571
  }, "currentOperation");
5494
5572
  function processCasing(casing, result, model) {
5495
5573
  const opNode = casing.toOperationNode();
5496
- invariant8(ValueNode4.is(opNode) && typeof opNode.value === "string", '"casting" parameter must be a string value');
5497
- result = match16(opNode.value).with("original", () => model).with("upper", () => result.toUpperCase()).with("lower", () => result.toLowerCase()).with("capitalize", () => `${result.charAt(0).toUpperCase() + result.slice(1)}`).with("uncapitalize", () => `${result.charAt(0).toLowerCase() + result.slice(1)}`).otherwise(() => {
5574
+ invariant9(ValueNode4.is(opNode) && typeof opNode.value === "string", '"casting" parameter must be a string value');
5575
+ result = match16(opNode.value).with("original", () => model).with("upper", () => result.toUpperCase()).with("lower", () => result.toLowerCase()).with("capitalize", () => upperCaseFirst(result)).with("uncapitalize", () => lowerCaseFirst(result)).otherwise(() => {
5498
5576
  throw new Error(`Invalid casing value: ${opNode.value}. Must be "original", "upper", "lower", "capitalize", or "uncapitalize".`);
5499
5577
  });
5500
5578
  return result;
@@ -5502,8 +5580,8 @@ function processCasing(casing, result, model) {
5502
5580
  __name(processCasing, "processCasing");
5503
5581
 
5504
5582
  // src/client/helpers/schema-db-pusher.ts
5583
+ import { invariant as invariant10 } from "@zenstackhq/common-helpers";
5505
5584
  import { sql as sql9 } from "kysely";
5506
- import invariant9 from "tiny-invariant";
5507
5585
  import { match as match17 } from "ts-pattern";
5508
5586
  var SchemaDbPusher = class {
5509
5587
  static {
@@ -5535,7 +5613,7 @@ var SchemaDbPusher = class {
5535
5613
  for (const [fieldName, fieldDef] of Object.entries(modelDef.fields)) {
5536
5614
  if (fieldDef.relation) {
5537
5615
  table = this.addForeignKeyConstraint(table, model, fieldName, fieldDef);
5538
- } else {
5616
+ } else if (!this.isComputedField(fieldDef)) {
5539
5617
  table = this.createModelField(table, fieldName, fieldDef, modelDef);
5540
5618
  }
5541
5619
  }
@@ -5543,6 +5621,9 @@ var SchemaDbPusher = class {
5543
5621
  table = this.addUniqueConstraint(table, modelDef);
5544
5622
  return table;
5545
5623
  }
5624
+ isComputedField(fieldDef) {
5625
+ return fieldDef.attributes?.some((a) => a.name === "@computed");
5626
+ }
5546
5627
  addPrimaryKeyConstraint(table, model, modelDef) {
5547
5628
  if (modelDef.idFields.length === 1) {
5548
5629
  if (Object.values(modelDef.fields).some((f) => f.id)) {
@@ -5556,7 +5637,7 @@ var SchemaDbPusher = class {
5556
5637
  }
5557
5638
  addUniqueConstraint(table, modelDef) {
5558
5639
  for (const [key, value] of Object.entries(modelDef.uniqueFields)) {
5559
- invariant9(typeof value === "object", "expecting an object");
5640
+ invariant10(typeof value === "object", "expecting an object");
5560
5641
  if ("type" in value) {
5561
5642
  const fieldDef = modelDef.fields[key];
5562
5643
  if (fieldDef.unique) {
@@ -5602,7 +5683,7 @@ var SchemaDbPusher = class {
5602
5683
  return "serial";
5603
5684
  }
5604
5685
  const type = fieldDef.type;
5605
- const result = match17(type).with("String", () => "text").with("Boolean", () => "boolean").with("Int", () => "integer").with("Float", () => "real").with("BigInt", () => "bigint").with("Decimal", () => "decimal").with("DateTime", () => "timestamp").with("Bytes", () => this.schema.provider.type === "postgresql" ? "bytea" : "blob").otherwise(() => {
5686
+ const result = match17(type).with("String", () => "text").with("Boolean", () => "boolean").with("Int", () => "integer").with("Float", () => "real").with("BigInt", () => "bigint").with("Decimal", () => "decimal").with("DateTime", () => "timestamp").with("Bytes", () => this.schema.provider.type === "postgresql" ? "bytea" : "blob").with("Json", () => "jsonb").otherwise(() => {
5606
5687
  throw new Error(`Unsupported field type: ${type}`);
5607
5688
  });
5608
5689
  if (fieldDef.array) {
@@ -5615,7 +5696,7 @@ var SchemaDbPusher = class {
5615
5696
  return fieldDef.default && ExpressionUtils.isCall(fieldDef.default) && fieldDef.default.function === "autoincrement";
5616
5697
  }
5617
5698
  addForeignKeyConstraint(table, model, fieldName, fieldDef) {
5618
- invariant9(fieldDef.relation, "field must be a relation");
5699
+ invariant10(fieldDef.relation, "field must be a relation");
5619
5700
  if (!fieldDef.relation.fields || !fieldDef.relation.references) {
5620
5701
  return table;
5621
5702
  }
@@ -5636,11 +5717,11 @@ var SchemaDbPusher = class {
5636
5717
  };
5637
5718
 
5638
5719
  // src/client/promise.ts
5639
- function createDeferredPromise(callback) {
5720
+ function createZenStackPromise(callback) {
5640
5721
  let promise;
5641
- const cb = /* @__PURE__ */ __name(() => {
5722
+ const cb = /* @__PURE__ */ __name((txClient) => {
5642
5723
  try {
5643
- return promise ??= valueToPromise(callback());
5724
+ return promise ??= valueToPromise(callback(txClient));
5644
5725
  } catch (err) {
5645
5726
  return Promise.reject(err);
5646
5727
  }
@@ -5655,10 +5736,11 @@ function createDeferredPromise(callback) {
5655
5736
  finally(onFinally) {
5656
5737
  return cb().finally(onFinally);
5657
5738
  },
5739
+ cb,
5658
5740
  [Symbol.toStringTag]: "ZenStackPromise"
5659
5741
  };
5660
5742
  }
5661
- __name(createDeferredPromise, "createDeferredPromise");
5743
+ __name(createZenStackPromise, "createZenStackPromise");
5662
5744
  function valueToPromise(thing) {
5663
5745
  if (typeof thing === "object" && typeof thing?.then === "function") {
5664
5746
  return thing;
@@ -5669,8 +5751,8 @@ function valueToPromise(thing) {
5669
5751
  __name(valueToPromise, "valueToPromise");
5670
5752
 
5671
5753
  // src/client/result-processor.ts
5754
+ import { invariant as invariant11 } from "@zenstackhq/common-helpers";
5672
5755
  import Decimal2 from "decimal.js";
5673
- import invariant10 from "tiny-invariant";
5674
5756
  import { match as match18 } from "ts-pattern";
5675
5757
  var ResultProcessor = class {
5676
5758
  static {
@@ -5744,20 +5826,20 @@ var ResultProcessor = class {
5744
5826
  return this.doProcessResult(relationData, fieldDef.type);
5745
5827
  }
5746
5828
  transformScalar(value, type) {
5747
- return match18(type).with("Boolean", () => this.transformBoolean(value)).with("DateTime", () => this.transformDate(value)).with("Bytes", () => this.transformBytes(value)).with("Decimal", () => this.transformDecimal(value)).with("BigInt", () => this.transformBigInt(value)).otherwise(() => value);
5829
+ return match18(type).with("Boolean", () => this.transformBoolean(value)).with("DateTime", () => this.transformDate(value)).with("Bytes", () => this.transformBytes(value)).with("Decimal", () => this.transformDecimal(value)).with("BigInt", () => this.transformBigInt(value)).with("Json", () => this.transformJson(value)).otherwise(() => value);
5748
5830
  }
5749
5831
  transformDecimal(value) {
5750
5832
  if (value instanceof Decimal2) {
5751
5833
  return value;
5752
5834
  }
5753
- invariant10(typeof value === "string" || typeof value === "number" || value instanceof Decimal2, `Expected string, number or Decimal, got ${typeof value}`);
5835
+ invariant11(typeof value === "string" || typeof value === "number" || value instanceof Decimal2, `Expected string, number or Decimal, got ${typeof value}`);
5754
5836
  return new Decimal2(value);
5755
5837
  }
5756
5838
  transformBigInt(value) {
5757
5839
  if (typeof value === "bigint") {
5758
5840
  return value;
5759
5841
  }
5760
- invariant10(typeof value === "string" || typeof value === "number", `Expected string or number, got ${typeof value}`);
5842
+ invariant11(typeof value === "string" || typeof value === "number", `Expected string or number, got ${typeof value}`);
5761
5843
  return BigInt(value);
5762
5844
  }
5763
5845
  transformBoolean(value) {
@@ -5776,6 +5858,9 @@ var ResultProcessor = class {
5776
5858
  return Buffer.isBuffer(value) ? Uint8Array.from(value) : value;
5777
5859
  }
5778
5860
  fixReversedResult(data, model, args) {
5861
+ if (!data) {
5862
+ return;
5863
+ }
5779
5864
  if (Array.isArray(data) && typeof args === "object" && args && args.take !== void 0 && args.take < 0) {
5780
5865
  data.reverse();
5781
5866
  }
@@ -5789,13 +5874,19 @@ var ResultProcessor = class {
5789
5874
  continue;
5790
5875
  }
5791
5876
  const fieldDef = getField(this.schema, model, field);
5792
- if (!fieldDef?.relation) {
5877
+ if (!fieldDef || !fieldDef.relation || !fieldDef.array) {
5793
5878
  continue;
5794
5879
  }
5795
5880
  this.fixReversedResult(row[field], fieldDef.type, value);
5796
5881
  }
5797
5882
  }
5798
5883
  }
5884
+ transformJson(value) {
5885
+ return match18(this.schema.provider.type).with("sqlite", () => {
5886
+ invariant11(typeof value === "string", "Expected string, got " + typeof value);
5887
+ return JSON.parse(value);
5888
+ }).otherwise(() => value);
5889
+ }
5799
5890
  };
5800
5891
 
5801
5892
  // src/client/client-impl.ts
@@ -5814,7 +5905,7 @@ var ClientImpl = class _ClientImpl {
5814
5905
  $schema;
5815
5906
  kyselyProps;
5816
5907
  auth;
5817
- constructor(schema, options, baseClient) {
5908
+ constructor(schema, options, baseClient, executor) {
5818
5909
  this.schema = schema;
5819
5910
  this.options = options;
5820
5911
  this.$schema = schema;
@@ -5826,16 +5917,16 @@ var ClientImpl = class _ClientImpl {
5826
5917
  if (baseClient) {
5827
5918
  this.kyselyProps = {
5828
5919
  ...baseClient.kyselyProps,
5829
- executor: new ZenStackQueryExecutor(this, baseClient.kyselyProps.driver, baseClient.kyselyProps.dialect.createQueryCompiler(), baseClient.kyselyProps.dialect.createAdapter(), new DefaultConnectionProvider(baseClient.kyselyProps.driver))
5920
+ executor: executor ?? new ZenStackQueryExecutor(this, baseClient.kyselyProps.driver, baseClient.kyselyProps.dialect.createQueryCompiler(), baseClient.kyselyProps.dialect.createAdapter(), new DefaultConnectionProvider(baseClient.kyselyProps.driver))
5830
5921
  };
5831
5922
  this.kyselyRaw = baseClient.kyselyRaw;
5923
+ this.auth = baseClient.auth;
5832
5924
  } else {
5833
5925
  const dialect = this.getKyselyDialect();
5834
5926
  const driver = new ZenStackDriver(dialect.createDriver(), new Log(this.$options.log ?? []));
5835
5927
  const compiler = dialect.createQueryCompiler();
5836
5928
  const adapter = dialect.createAdapter();
5837
5929
  const connectionProvider = new DefaultConnectionProvider(driver);
5838
- const executor = new ZenStackQueryExecutor(this, driver, compiler, adapter, connectionProvider);
5839
5930
  this.kyselyProps = {
5840
5931
  config: {
5841
5932
  dialect,
@@ -5843,7 +5934,7 @@ var ClientImpl = class _ClientImpl {
5843
5934
  },
5844
5935
  dialect,
5845
5936
  driver,
5846
- executor
5937
+ executor: executor ?? new ZenStackQueryExecutor(this, driver, compiler, adapter, connectionProvider)
5847
5938
  };
5848
5939
  this.kyselyRaw = new Kysely({
5849
5940
  ...this.kyselyProps,
@@ -5859,31 +5950,67 @@ var ClientImpl = class _ClientImpl {
5859
5950
  get $qbRaw() {
5860
5951
  return this.kyselyRaw;
5861
5952
  }
5953
+ get isTransaction() {
5954
+ return this.kysely.isTransaction;
5955
+ }
5956
+ /**
5957
+ * Create a new client with a new query executor.
5958
+ */
5959
+ withExecutor(executor) {
5960
+ return new _ClientImpl(this.schema, this.$options, this, executor);
5961
+ }
5862
5962
  getKyselyDialect() {
5863
5963
  return match19(this.schema.provider.type).with("sqlite", () => this.makeSqliteKyselyDialect()).with("postgresql", () => this.makePostgresKyselyDialect()).exhaustive();
5864
5964
  }
5865
5965
  makePostgresKyselyDialect() {
5866
- const { dialectConfigProvider } = this.schema.provider;
5867
- const mergedConfig = {
5868
- ...dialectConfigProvider(),
5869
- ...this.options?.dialectConfig
5870
- };
5871
- return new PostgresDialect(mergedConfig);
5966
+ return new PostgresDialect(this.options.dialectConfig);
5872
5967
  }
5873
5968
  makeSqliteKyselyDialect() {
5874
- const { dialectConfigProvider } = this.schema.provider;
5875
- const mergedConfig = {
5876
- ...dialectConfigProvider(),
5877
- ...this.options?.dialectConfig
5878
- };
5879
- return new SqliteDialect(mergedConfig);
5969
+ return new SqliteDialect(this.options.dialectConfig);
5970
+ }
5971
+ // implementation
5972
+ async $transaction(input, options) {
5973
+ invariant12(typeof input === "function" || Array.isArray(input) && input.every((p) => p.then && p.cb), "Invalid transaction input, expected a function or an array of ZenStackPromise");
5974
+ if (typeof input === "function") {
5975
+ return this.interactiveTransaction(input, options);
5976
+ } else {
5977
+ return this.sequentialTransaction(input, options);
5978
+ }
5880
5979
  }
5881
- async $transaction(callback) {
5882
- return this.kysely.transaction().execute((tx) => {
5883
- const txClient = new _ClientImpl(this.schema, this.$options);
5980
+ async interactiveTransaction(callback, options) {
5981
+ if (this.kysely.isTransaction) {
5982
+ return callback(this);
5983
+ } else {
5984
+ let txBuilder = this.kysely.transaction();
5985
+ if (options?.isolationLevel) {
5986
+ txBuilder = txBuilder.setIsolationLevel(options.isolationLevel);
5987
+ }
5988
+ return txBuilder.execute((tx) => {
5989
+ const txClient = new _ClientImpl(this.schema, this.$options, this);
5990
+ txClient.kysely = tx;
5991
+ return callback(txClient);
5992
+ });
5993
+ }
5994
+ }
5995
+ async sequentialTransaction(arg, options) {
5996
+ const execute = /* @__PURE__ */ __name(async (tx) => {
5997
+ const txClient = new _ClientImpl(this.schema, this.$options, this);
5884
5998
  txClient.kysely = tx;
5885
- return callback(txClient);
5886
- });
5999
+ const result = [];
6000
+ for (const promise of arg) {
6001
+ result.push(await promise.cb(txClient));
6002
+ }
6003
+ return result;
6004
+ }, "execute");
6005
+ if (this.kysely.isTransaction) {
6006
+ return execute(this.kysely);
6007
+ } else {
6008
+ let txBuilder = this.kysely.transaction();
6009
+ if (options?.isolationLevel) {
6010
+ txBuilder = txBuilder.setIsolationLevel(options.isolationLevel);
6011
+ }
6012
+ return txBuilder.execute((tx) => execute(tx));
6013
+ }
5887
6014
  }
5888
6015
  get $procedures() {
5889
6016
  return Object.keys(this.$schema.procedures ?? {}).reduce((acc, name) => {
@@ -5914,12 +6041,19 @@ var ClientImpl = class _ClientImpl {
5914
6041
  const newOptions = {
5915
6042
  ...this.options,
5916
6043
  plugins: [
5917
- ...this.options?.plugins ?? [],
6044
+ ...this.options.plugins ?? [],
5918
6045
  plugin
5919
6046
  ]
5920
6047
  };
5921
6048
  return new _ClientImpl(this.schema, newOptions, this);
5922
6049
  }
6050
+ $unuse(pluginId) {
6051
+ const newOptions = {
6052
+ ...this.options,
6053
+ plugins: this.options.plugins?.filter((p) => p.id !== pluginId)
6054
+ };
6055
+ return new _ClientImpl(this.schema, newOptions, this);
6056
+ }
5923
6057
  $unuseAll() {
5924
6058
  const newOptions = {
5925
6059
  ...this.options,
@@ -5938,6 +6072,39 @@ var ClientImpl = class _ClientImpl {
5938
6072
  get $auth() {
5939
6073
  return this.auth;
5940
6074
  }
6075
+ $executeRaw(query, ...values) {
6076
+ return createZenStackPromise(async () => {
6077
+ const result = await sql10(query, ...values).execute(this.kysely);
6078
+ return Number(result.numAffectedRows ?? 0);
6079
+ });
6080
+ }
6081
+ $executeRawUnsafe(query, ...values) {
6082
+ return createZenStackPromise(async () => {
6083
+ const compiledQuery = this.createRawCompiledQuery(query, values);
6084
+ const result = await this.kysely.executeQuery(compiledQuery);
6085
+ return Number(result.numAffectedRows ?? 0);
6086
+ });
6087
+ }
6088
+ $queryRaw(query, ...values) {
6089
+ return createZenStackPromise(async () => {
6090
+ const result = await sql10(query, ...values).execute(this.kysely);
6091
+ return result.rows;
6092
+ });
6093
+ }
6094
+ $queryRawUnsafe(query, ...values) {
6095
+ return createZenStackPromise(async () => {
6096
+ const compiledQuery = this.createRawCompiledQuery(query, values);
6097
+ const result = await this.kysely.executeQuery(compiledQuery);
6098
+ return result.rows;
6099
+ });
6100
+ }
6101
+ createRawCompiledQuery(query, values) {
6102
+ const q = CompiledQuery.raw(query, values);
6103
+ return {
6104
+ ...q,
6105
+ $raw: true
6106
+ };
6107
+ }
5941
6108
  };
5942
6109
  function createClientProxy(client) {
5943
6110
  const inputValidator = new InputValidator(client.$schema);
@@ -5960,9 +6127,9 @@ function createClientProxy(client) {
5960
6127
  __name(createClientProxy, "createClientProxy");
5961
6128
  function createModelCrudHandler(client, model, inputValidator, resultProcessor) {
5962
6129
  const createPromise = /* @__PURE__ */ __name((operation, args, handler, postProcess = false, throwIfNoResult = false) => {
5963
- return createDeferredPromise(async () => {
5964
- let proceed = /* @__PURE__ */ __name(async (_args, tx) => {
5965
- const _handler = tx ? handler.withClient(tx) : handler;
6130
+ return createZenStackPromise(async (txClient) => {
6131
+ let proceed = /* @__PURE__ */ __name(async (_args) => {
6132
+ const _handler = txClient ? handler.withClient(txClient) : handler;
5966
6133
  const r = await _handler.handle(operation, _args ?? args);
5967
6134
  if (!r && throwIfNoResult) {
5968
6135
  throw new NotFoundError(model);
@@ -5975,22 +6142,31 @@ function createModelCrudHandler(client, model, inputValidator, resultProcessor)
5975
6142
  }
5976
6143
  return result;
5977
6144
  }, "proceed");
5978
- const context = {
5979
- client,
5980
- model,
5981
- operation,
5982
- queryArgs: args
5983
- };
5984
6145
  const plugins = [
5985
6146
  ...client.$options.plugins ?? []
5986
6147
  ];
5987
6148
  for (const plugin of plugins) {
5988
- if (plugin.onQuery) {
5989
- const _proceed = proceed;
5990
- proceed = /* @__PURE__ */ __name(() => plugin.onQuery({
5991
- ...context,
5992
- proceed: _proceed
5993
- }), "proceed");
6149
+ if (plugin.onQuery && typeof plugin.onQuery === "object") {
6150
+ for (const [_model, modelHooks] of Object.entries(plugin.onQuery)) {
6151
+ if (_model === lowerCaseFirst2(model) || _model === "$allModels") {
6152
+ if (modelHooks && typeof modelHooks === "object") {
6153
+ for (const [op, opHooks] of Object.entries(modelHooks)) {
6154
+ if (op === operation || op === "$allOperations") {
6155
+ if (typeof opHooks === "function") {
6156
+ const _proceed = proceed;
6157
+ proceed = /* @__PURE__ */ __name(() => opHooks({
6158
+ client,
6159
+ model,
6160
+ operation,
6161
+ args,
6162
+ query: _proceed
6163
+ }), "proceed");
6164
+ }
6165
+ }
6166
+ }
6167
+ }
6168
+ }
6169
+ }
5994
6170
  }
5995
6171
  }
5996
6172
  return proceed(args);
@@ -6046,12 +6222,23 @@ function createModelCrudHandler(client, model, inputValidator, resultProcessor)
6046
6222
  return createPromise("aggregate", args, new AggregateOperationHandler(client, model, inputValidator), false);
6047
6223
  }, "aggregate"),
6048
6224
  groupBy: /* @__PURE__ */ __name((args) => {
6049
- return createPromise("groupBy", args, new GroupByeOperationHandler(client, model, inputValidator));
6225
+ return createPromise("groupBy", args, new GroupByOperationHandler(client, model, inputValidator));
6050
6226
  }, "groupBy")
6051
6227
  };
6052
6228
  }
6053
6229
  __name(createModelCrudHandler, "createModelCrudHandler");
6230
+
6231
+ // src/client/plugin.ts
6232
+ function definePlugin(plugin) {
6233
+ return plugin;
6234
+ }
6235
+ __name(definePlugin, "definePlugin");
6054
6236
  export {
6055
- ZenStackClient
6237
+ InputValidationError,
6238
+ InternalError,
6239
+ NotFoundError,
6240
+ QueryError,
6241
+ ZenStackClient,
6242
+ definePlugin
6056
6243
  };
6057
6244
  //# sourceMappingURL=index.js.map