@zenstackhq/runtime 3.0.0-beta.7 → 3.0.0-beta.8

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.
package/dist/index.cjs CHANGED
@@ -36,6 +36,7 @@ __export(src_exports, {
36
36
  NotFoundError: () => NotFoundError,
37
37
  QueryError: () => QueryError,
38
38
  ZenStackClient: () => ZenStackClient,
39
+ ZenStackError: () => ZenStackError,
39
40
  definePlugin: () => definePlugin,
40
41
  sql: () => import_kysely19.sql
41
42
  });
@@ -47,7 +48,7 @@ var import_kysely18 = require("kysely");
47
48
 
48
49
  // src/client/crud/operations/aggregate.ts
49
50
  var import_kysely11 = require("kysely");
50
- var import_ts_pattern10 = require("ts-pattern");
51
+ var import_ts_pattern11 = require("ts-pattern");
51
52
 
52
53
  // src/client/query-utils.ts
53
54
  var import_common_helpers = require("@zenstackhq/common-helpers");
@@ -152,7 +153,12 @@ function fieldsToSelectObject(fields) {
152
153
  __name(fieldsToSelectObject, "fieldsToSelectObject");
153
154
 
154
155
  // src/client/errors.ts
155
- var InputValidationError = class extends Error {
156
+ var ZenStackError = class extends Error {
157
+ static {
158
+ __name(this, "ZenStackError");
159
+ }
160
+ };
161
+ var InputValidationError = class extends ZenStackError {
156
162
  static {
157
163
  __name(this, "InputValidationError");
158
164
  }
@@ -162,7 +168,7 @@ var InputValidationError = class extends Error {
162
168
  });
163
169
  }
164
170
  };
165
- var QueryError = class extends Error {
171
+ var QueryError = class extends ZenStackError {
166
172
  static {
167
173
  __name(this, "QueryError");
168
174
  }
@@ -172,12 +178,12 @@ var QueryError = class extends Error {
172
178
  });
173
179
  }
174
180
  };
175
- var InternalError = class extends Error {
181
+ var InternalError = class extends ZenStackError {
176
182
  static {
177
183
  __name(this, "InternalError");
178
184
  }
179
185
  };
180
- var NotFoundError = class extends Error {
186
+ var NotFoundError = class extends ZenStackError {
181
187
  static {
182
188
  __name(this, "NotFoundError");
183
189
  }
@@ -518,7 +524,7 @@ var import_cuid2 = require("@paralleldrive/cuid2");
518
524
  var import_common_helpers10 = require("@zenstackhq/common-helpers");
519
525
  var import_kysely10 = require("kysely");
520
526
  var import_nanoid = require("nanoid");
521
- var import_ts_pattern9 = require("ts-pattern");
527
+ var import_ts_pattern10 = require("ts-pattern");
522
528
  var import_ulid = require("ulid");
523
529
  var uuid = __toESM(require("uuid"), 1);
524
530
 
@@ -529,7 +535,7 @@ var RejectedByPolicyReason = /* @__PURE__ */ function(RejectedByPolicyReason2) {
529
535
  RejectedByPolicyReason2["OTHER"] = "other";
530
536
  return RejectedByPolicyReason2;
531
537
  }({});
532
- var RejectedByPolicyError = class extends Error {
538
+ var RejectedByPolicyError = class extends ZenStackError {
533
539
  static {
534
540
  __name(this, "RejectedByPolicyError");
535
541
  }
@@ -559,6 +565,10 @@ var CRUD = [
559
565
  "update",
560
566
  "delete"
561
567
  ];
568
+ var CRUD_EXT = [
569
+ ...CRUD,
570
+ "post-update"
571
+ ];
562
572
 
563
573
  // src/client/kysely-utils.ts
564
574
  var import_kysely = require("kysely");
@@ -595,7 +605,7 @@ __name(extractFieldName, "extractFieldName");
595
605
  // src/plugins/policy/policy-handler.ts
596
606
  var import_common_helpers7 = require("@zenstackhq/common-helpers");
597
607
  var import_kysely8 = require("kysely");
598
- var import_ts_pattern8 = require("ts-pattern");
608
+ var import_ts_pattern9 = require("ts-pattern");
599
609
 
600
610
  // src/client/crud/dialects/index.ts
601
611
  var import_ts_pattern5 = require("ts-pattern");
@@ -1742,6 +1752,59 @@ function getCrudDialect(schema, options) {
1742
1752
  }
1743
1753
  __name(getCrudDialect, "getCrudDialect");
1744
1754
 
1755
+ // src/utils/expression-utils.ts
1756
+ var import_ts_pattern6 = require("ts-pattern");
1757
+ var ExpressionVisitor = class {
1758
+ static {
1759
+ __name(this, "ExpressionVisitor");
1760
+ }
1761
+ visit(expr2) {
1762
+ (0, import_ts_pattern6.match)(expr2).with({
1763
+ kind: "literal"
1764
+ }, (e) => this.visitLiteral(e)).with({
1765
+ kind: "array"
1766
+ }, (e) => this.visitArray(e)).with({
1767
+ kind: "field"
1768
+ }, (e) => this.visitField(e)).with({
1769
+ kind: "member"
1770
+ }, (e) => this.visitMember(e)).with({
1771
+ kind: "binary"
1772
+ }, (e) => this.visitBinary(e)).with({
1773
+ kind: "unary"
1774
+ }, (e) => this.visitUnary(e)).with({
1775
+ kind: "call"
1776
+ }, (e) => this.visitCall(e)).with({
1777
+ kind: "this"
1778
+ }, (e) => this.visitThis(e)).with({
1779
+ kind: "null"
1780
+ }, (e) => this.visitNull(e)).exhaustive();
1781
+ }
1782
+ visitLiteral(_e) {
1783
+ }
1784
+ visitArray(e) {
1785
+ e.items.forEach((item) => this.visit(item));
1786
+ }
1787
+ visitField(_e) {
1788
+ }
1789
+ visitMember(e) {
1790
+ this.visit(e.receiver);
1791
+ }
1792
+ visitBinary(e) {
1793
+ this.visit(e.left);
1794
+ this.visit(e.right);
1795
+ }
1796
+ visitUnary(e) {
1797
+ this.visit(e.operand);
1798
+ }
1799
+ visitCall(e) {
1800
+ e.args?.forEach((arg) => this.visit(arg));
1801
+ }
1802
+ visitThis(_e) {
1803
+ }
1804
+ visitNull(_e) {
1805
+ }
1806
+ };
1807
+
1745
1808
  // src/utils/default-operation-node-visitor.ts
1746
1809
  var import_kysely5 = require("kysely");
1747
1810
  var DefaultOperationNodeVisitor = class extends import_kysely5.OperationNodeVisitor {
@@ -2063,17 +2126,17 @@ var ColumnCollector = class extends DefaultOperationNodeVisitor {
2063
2126
  // src/plugins/policy/expression-transformer.ts
2064
2127
  var import_common_helpers6 = require("@zenstackhq/common-helpers");
2065
2128
  var import_kysely7 = require("kysely");
2066
- var import_ts_pattern7 = require("ts-pattern");
2129
+ var import_ts_pattern8 = require("ts-pattern");
2067
2130
 
2068
2131
  // src/plugins/policy/expression-evaluator.ts
2069
2132
  var import_common_helpers5 = require("@zenstackhq/common-helpers");
2070
- var import_ts_pattern6 = require("ts-pattern");
2133
+ var import_ts_pattern7 = require("ts-pattern");
2071
2134
  var ExpressionEvaluator = class {
2072
2135
  static {
2073
2136
  __name(this, "ExpressionEvaluator");
2074
2137
  }
2075
2138
  evaluate(expression, context) {
2076
- const result = (0, import_ts_pattern6.match)(expression).when(ExpressionUtils.isArray, (expr2) => this.evaluateArray(expr2, context)).when(ExpressionUtils.isBinary, (expr2) => this.evaluateBinary(expr2, context)).when(ExpressionUtils.isField, (expr2) => this.evaluateField(expr2, context)).when(ExpressionUtils.isLiteral, (expr2) => this.evaluateLiteral(expr2)).when(ExpressionUtils.isMember, (expr2) => this.evaluateMember(expr2, context)).when(ExpressionUtils.isUnary, (expr2) => this.evaluateUnary(expr2, context)).when(ExpressionUtils.isCall, (expr2) => this.evaluateCall(expr2, context)).when(ExpressionUtils.isThis, () => context.thisValue).when(ExpressionUtils.isNull, () => null).exhaustive();
2139
+ const result = (0, import_ts_pattern7.match)(expression).when(ExpressionUtils.isArray, (expr2) => this.evaluateArray(expr2, context)).when(ExpressionUtils.isBinary, (expr2) => this.evaluateBinary(expr2, context)).when(ExpressionUtils.isField, (expr2) => this.evaluateField(expr2, context)).when(ExpressionUtils.isLiteral, (expr2) => this.evaluateLiteral(expr2)).when(ExpressionUtils.isMember, (expr2) => this.evaluateMember(expr2, context)).when(ExpressionUtils.isUnary, (expr2) => this.evaluateUnary(expr2, context)).when(ExpressionUtils.isCall, (expr2) => this.evaluateCall(expr2, context)).when(ExpressionUtils.isThis, () => context.thisValue).when(ExpressionUtils.isNull, () => null).exhaustive();
2077
2140
  return result ?? null;
2078
2141
  }
2079
2142
  evaluateCall(expr2, context) {
@@ -2084,7 +2147,7 @@ var ExpressionEvaluator = class {
2084
2147
  }
2085
2148
  }
2086
2149
  evaluateUnary(expr2, context) {
2087
- return (0, import_ts_pattern6.match)(expr2.op).with("!", () => !this.evaluate(expr2.operand, context)).exhaustive();
2150
+ return (0, import_ts_pattern7.match)(expr2.op).with("!", () => !this.evaluate(expr2.operand, context)).exhaustive();
2088
2151
  }
2089
2152
  evaluateMember(expr2, context) {
2090
2153
  let val = this.evaluate(expr2.receiver, context);
@@ -2108,7 +2171,7 @@ var ExpressionEvaluator = class {
2108
2171
  }
2109
2172
  const left = this.evaluate(expr2.left, context);
2110
2173
  const right = this.evaluate(expr2.right, context);
2111
- return (0, import_ts_pattern6.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", () => {
2174
+ return (0, import_ts_pattern7.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", () => {
2112
2175
  const _right = right ?? [];
2113
2176
  (0, import_common_helpers5.invariant)(Array.isArray(_right), 'expected array for "in" operator');
2114
2177
  return _right.includes(left);
@@ -2122,7 +2185,7 @@ var ExpressionEvaluator = class {
2122
2185
  return false;
2123
2186
  }
2124
2187
  (0, import_common_helpers5.invariant)(Array.isArray(left), "expected array");
2125
- return (0, import_ts_pattern6.match)(op).with("?", () => left.some((item) => this.evaluate(expr2.right, {
2188
+ return (0, import_ts_pattern7.match)(op).with("?", () => left.some((item) => this.evaluate(expr2.right, {
2126
2189
  ...context,
2127
2190
  thisValue: item
2128
2191
  }))).with("!", () => left.every((item) => this.evaluate(expr2.right, {
@@ -2232,6 +2295,10 @@ function getTableName(node) {
2232
2295
  return void 0;
2233
2296
  }
2234
2297
  __name(getTableName, "getTableName");
2298
+ function isBeforeInvocation(expr2) {
2299
+ return ExpressionUtils.isCall(expr2) && expr2.function === "before";
2300
+ }
2301
+ __name(isBeforeInvocation, "isBeforeInvocation");
2235
2302
 
2236
2303
  // src/plugins/policy/expression-transformer.ts
2237
2304
  function _ts_decorate(decorators, target, key, desc) {
@@ -2435,7 +2502,7 @@ var ExpressionTransformer = class {
2435
2502
  const count = import_kysely7.FunctionNode.create("count", [
2436
2503
  import_kysely7.ValueNode.createImmediate(1)
2437
2504
  ]);
2438
- const predicateResult = (0, import_ts_pattern7.match)(expr2.op).with("?", () => import_kysely7.BinaryOperationNode.create(count, import_kysely7.OperatorNode.create(">"), import_kysely7.ValueNode.createImmediate(0))).with("!", () => import_kysely7.BinaryOperationNode.create(count, import_kysely7.OperatorNode.create("="), import_kysely7.ValueNode.createImmediate(0))).with("^", () => import_kysely7.BinaryOperationNode.create(count, import_kysely7.OperatorNode.create("="), import_kysely7.ValueNode.createImmediate(0))).exhaustive();
2505
+ const predicateResult = (0, import_ts_pattern8.match)(expr2.op).with("?", () => import_kysely7.BinaryOperationNode.create(count, import_kysely7.OperatorNode.create(">"), import_kysely7.ValueNode.createImmediate(0))).with("!", () => import_kysely7.BinaryOperationNode.create(count, import_kysely7.OperatorNode.create("="), import_kysely7.ValueNode.createImmediate(0))).with("^", () => import_kysely7.BinaryOperationNode.create(count, import_kysely7.OperatorNode.create("="), import_kysely7.ValueNode.createImmediate(0))).exhaustive();
2439
2506
  return this.transform(expr2.left, {
2440
2507
  ...context,
2441
2508
  memberSelect: import_kysely7.SelectionNode.create(import_kysely7.AliasNode.create(predicateResult, import_kysely7.IdentifierNode.create("$t"))),
@@ -2500,7 +2567,7 @@ var ExpressionTransformer = class {
2500
2567
  return logicalNot(this.dialect, this.transform(expr2.operand, context));
2501
2568
  }
2502
2569
  transformOperator(op) {
2503
- const mappedOp = (0, import_ts_pattern7.match)(op).with("==", () => "=").otherwise(() => op);
2570
+ const mappedOp = (0, import_ts_pattern8.match)(op).with("==", () => "=").otherwise(() => op);
2504
2571
  return import_kysely7.OperatorNode.create(mappedOp);
2505
2572
  }
2506
2573
  _call(expr2, context) {
@@ -2544,7 +2611,7 @@ var ExpressionTransformer = class {
2544
2611
  return this.transformCall(arg, context);
2545
2612
  }
2546
2613
  if (this.isAuthMember(arg)) {
2547
- const valNode = this.valueMemberAccess(context.auth, arg, this.authType);
2614
+ const valNode = this.valueMemberAccess(this.auth, arg, this.authType);
2548
2615
  return valNode ? eb.val(valNode.value) : eb.val(null);
2549
2616
  }
2550
2617
  throw new InternalError(`Unsupported argument expression: ${arg.kind}`);
@@ -2553,6 +2620,11 @@ var ExpressionTransformer = class {
2553
2620
  if (this.isAuthCall(expr2.receiver)) {
2554
2621
  return this.valueMemberAccess(this.auth, expr2, this.authType);
2555
2622
  }
2623
+ if (isBeforeInvocation(expr2.receiver)) {
2624
+ (0, import_common_helpers6.invariant)(context.operation === "post-update", "before() can only be used in post-update policy");
2625
+ (0, import_common_helpers6.invariant)(expr2.members.length === 1, "before() can only be followed by a scalar field access");
2626
+ return import_kysely7.ReferenceNode.create(import_kysely7.ColumnNode.create(expr2.members[0]), import_kysely7.TableNode.create("$before"));
2627
+ }
2556
2628
  (0, import_common_helpers6.invariant)(ExpressionUtils.isField(expr2.receiver) || ExpressionUtils.isThis(expr2.receiver), 'expect receiver to be field expression or "this"');
2557
2629
  let members = expr2.members;
2558
2630
  let receiver;
@@ -2597,7 +2669,6 @@ var ExpressionTransformer = class {
2597
2669
  alias: void 0
2598
2670
  });
2599
2671
  if (currNode) {
2600
- (0, import_common_helpers6.invariant)(import_kysely7.SelectQueryNode.is(currNode), "expected select query node");
2601
2672
  currNode = {
2602
2673
  ...relation,
2603
2674
  selections: [
@@ -2808,9 +2879,45 @@ var PolicyHandler = class extends import_kysely8.OperationNodeTransformer {
2808
2879
  await this.enforcePreCreatePolicy(node, mutationModel, isManyToManyJoinTable, proceed);
2809
2880
  }
2810
2881
  }
2882
+ const hasPostUpdatePolicies = import_kysely8.UpdateQueryNode.is(node) && this.hasPostUpdatePolicies(mutationModel);
2883
+ let beforeUpdateInfo;
2884
+ if (hasPostUpdatePolicies) {
2885
+ beforeUpdateInfo = await this.loadBeforeUpdateEntities(mutationModel, node.where, proceed);
2886
+ }
2811
2887
  const result = await proceed(this.transformNode(node));
2888
+ if (hasPostUpdatePolicies && result.rows.length > 0) {
2889
+ const idConditions = this.buildIdConditions(mutationModel, result.rows);
2890
+ const postUpdateFilter = this.buildPolicyFilter(mutationModel, void 0, "post-update");
2891
+ const eb = (0, import_kysely8.expressionBuilder)();
2892
+ const beforeUpdateTable = beforeUpdateInfo ? {
2893
+ kind: "SelectQueryNode",
2894
+ from: import_kysely8.FromNode.create([
2895
+ import_kysely8.ParensNode.create(import_kysely8.ValuesNode.create(beforeUpdateInfo.rows.map((r) => import_kysely8.PrimitiveValueListNode.create(beforeUpdateInfo.fields.map((f) => r[f])))))
2896
+ ]),
2897
+ selections: beforeUpdateInfo.fields.map((name, index) => {
2898
+ const def = requireField(this.client.$schema, mutationModel, name);
2899
+ const castedColumnRef = import_kysely8.sql`CAST(${eb.ref(`column${index + 1}`)} as ${import_kysely8.sql.raw(this.dialect.getFieldSqlType(def))})`.as(name);
2900
+ return import_kysely8.SelectionNode.create(castedColumnRef.toOperationNode());
2901
+ })
2902
+ } : void 0;
2903
+ const postUpdateQuery = eb.selectFrom(mutationModel).select(() => [
2904
+ eb(eb.fn("COUNT", [
2905
+ eb.lit(1)
2906
+ ]), "=", result.rows.length).as("$condition")
2907
+ ]).where(() => new import_kysely8.ExpressionWrapper(conjunction(this.dialect, [
2908
+ idConditions,
2909
+ postUpdateFilter
2910
+ ]))).$if(!!beforeUpdateInfo, (qb) => qb.leftJoin(() => new import_kysely8.ExpressionWrapper(beforeUpdateTable).as("$before"), (join) => {
2911
+ const idFields = requireIdFields(this.client.$schema, mutationModel);
2912
+ return idFields.reduce((acc, f) => acc.onRef(`${mutationModel}.${f}`, "=", `$before.${f}`), join);
2913
+ }));
2914
+ const postUpdateResult = await proceed(postUpdateQuery.toOperationNode());
2915
+ if (!postUpdateResult.rows[0]?.$condition) {
2916
+ throw new RejectedByPolicyError(mutationModel, RejectedByPolicyReason.NO_ACCESS, "some or all updated rows failed to pass post-update policy check");
2917
+ }
2918
+ }
2812
2919
  if (!node.returning || this.onlyReturningId(node)) {
2813
- return result;
2920
+ return this.postProcessMutationResult(result, node);
2814
2921
  } else {
2815
2922
  const readBackResult = await this.processReadBack(node, result, proceed);
2816
2923
  if (readBackResult.rows.length !== result.rows.length) {
@@ -2819,6 +2926,68 @@ var PolicyHandler = class extends import_kysely8.OperationNodeTransformer {
2819
2926
  return readBackResult;
2820
2927
  }
2821
2928
  }
2929
+ // correction to kysely mutation result may be needed because we might have added
2930
+ // returning clause to the query and caused changes to the result shape
2931
+ postProcessMutationResult(result, node) {
2932
+ if (node.returning) {
2933
+ return result;
2934
+ } else {
2935
+ return {
2936
+ ...result,
2937
+ rows: [],
2938
+ numAffectedRows: result.numAffectedRows ?? BigInt(result.rows.length)
2939
+ };
2940
+ }
2941
+ }
2942
+ hasPostUpdatePolicies(model) {
2943
+ const policies = this.getModelPolicies(model, "post-update");
2944
+ return policies.length > 0;
2945
+ }
2946
+ async loadBeforeUpdateEntities(model, where, proceed) {
2947
+ const beforeUpdateAccessFields = this.getFieldsAccessForBeforeUpdatePolicies(model);
2948
+ if (!beforeUpdateAccessFields || beforeUpdateAccessFields.length === 0) {
2949
+ return void 0;
2950
+ }
2951
+ const query = {
2952
+ kind: "SelectQueryNode",
2953
+ from: import_kysely8.FromNode.create([
2954
+ import_kysely8.TableNode.create(model)
2955
+ ]),
2956
+ where,
2957
+ selections: [
2958
+ ...beforeUpdateAccessFields.map((f) => import_kysely8.SelectionNode.create(import_kysely8.ColumnNode.create(f)))
2959
+ ]
2960
+ };
2961
+ const result = await proceed(query);
2962
+ return {
2963
+ fields: beforeUpdateAccessFields,
2964
+ rows: result.rows
2965
+ };
2966
+ }
2967
+ getFieldsAccessForBeforeUpdatePolicies(model) {
2968
+ const policies = this.getModelPolicies(model, "post-update");
2969
+ if (policies.length === 0) {
2970
+ return void 0;
2971
+ }
2972
+ const fields = /* @__PURE__ */ new Set();
2973
+ const fieldCollector = new class extends ExpressionVisitor {
2974
+ visitMember(e) {
2975
+ if (isBeforeInvocation(e.receiver)) {
2976
+ (0, import_common_helpers7.invariant)(e.members.length === 1, "before() can only be followed by a scalar field access");
2977
+ fields.add(e.members[0]);
2978
+ }
2979
+ super.visitMember(e);
2980
+ }
2981
+ }();
2982
+ for (const policy of policies) {
2983
+ fieldCollector.visit(policy.condition);
2984
+ }
2985
+ if (fields.size === 0) {
2986
+ return void 0;
2987
+ }
2988
+ requireIdFields(this.client.$schema, model).forEach((f) => fields.add(f));
2989
+ return Array.from(fields).sort();
2990
+ }
2822
2991
  // #region overrides
2823
2992
  transformSelectQuery(node) {
2824
2993
  let whereNode = this.transformNode(node.where);
@@ -2884,19 +3053,16 @@ var PolicyHandler = class extends import_kysely8.OperationNodeTransformer {
2884
3053
  onConflict
2885
3054
  } : node;
2886
3055
  const result = super.transformInsertQuery(processedNode);
2887
- if (!node.returning) {
2888
- return result;
2889
- }
2890
- if (this.onlyReturningId(node)) {
2891
- return result;
2892
- } else {
3056
+ let returning = result.returning;
3057
+ if (returning) {
2893
3058
  const { mutationModel } = this.getMutationModel(node);
2894
3059
  const idFields = requireIdFields(this.client.$schema, mutationModel);
2895
- return {
2896
- ...result,
2897
- returning: import_kysely8.ReturningNode.create(idFields.map((field) => import_kysely8.SelectionNode.create(import_kysely8.ColumnNode.create(field))))
2898
- };
3060
+ returning = import_kysely8.ReturningNode.create(idFields.map((f) => import_kysely8.SelectionNode.create(import_kysely8.ColumnNode.create(f))));
2899
3061
  }
3062
+ return {
3063
+ ...result,
3064
+ returning
3065
+ };
2900
3066
  }
2901
3067
  transformUpdateQuery(node) {
2902
3068
  const result = super.transformUpdateQuery(node);
@@ -2911,12 +3077,18 @@ var PolicyHandler = class extends import_kysely8.OperationNodeTransformer {
2911
3077
  ]);
2912
3078
  }
2913
3079
  }
3080
+ let returning = result.returning;
3081
+ if (returning || this.hasPostUpdatePolicies(mutationModel)) {
3082
+ const idFields = requireIdFields(this.client.$schema, mutationModel);
3083
+ returning = import_kysely8.ReturningNode.create(idFields.map((f) => import_kysely8.SelectionNode.create(import_kysely8.ColumnNode.create(f))));
3084
+ }
2914
3085
  return {
2915
3086
  ...result,
2916
3087
  where: import_kysely8.WhereNode.create(result.where ? conjunction(this.dialect, [
2917
3088
  result.where.where,
2918
3089
  filter
2919
- ]) : filter)
3090
+ ]) : filter),
3091
+ returning
2920
3092
  };
2921
3093
  }
2922
3094
  transformDeleteQuery(node) {
@@ -2948,6 +3120,14 @@ var PolicyHandler = class extends import_kysely8.OperationNodeTransformer {
2948
3120
  }
2949
3121
  const { mutationModel } = this.getMutationModel(node);
2950
3122
  const idFields = requireIdFields(this.client.$schema, mutationModel);
3123
+ if (node.returning.selections.some((s) => import_kysely8.SelectAllNode.is(s.selection))) {
3124
+ const modelDef = requireModel(this.client.$schema, mutationModel);
3125
+ if (Object.keys(modelDef.fields).some((f) => !idFields.includes(f))) {
3126
+ return false;
3127
+ } else {
3128
+ return true;
3129
+ }
3130
+ }
2951
3131
  const collector = new ColumnCollector();
2952
3132
  const selectedColumns = collector.collect(node.returning);
2953
3133
  return selectedColumns.every((c) => idFields.includes(c));
@@ -3131,10 +3311,10 @@ var PolicyHandler = class extends import_kysely8.OperationNodeTransformer {
3131
3311
  }
3132
3312
  buildIdConditions(table, rows) {
3133
3313
  const idFields = requireIdFields(this.client.$schema, table);
3134
- return disjunction(this.dialect, rows.map((row) => conjunction(this.dialect, idFields.map((field) => import_kysely8.BinaryOperationNode.create(import_kysely8.ColumnNode.create(field), import_kysely8.OperatorNode.create("="), import_kysely8.ValueNode.create(row[field]))))));
3314
+ return disjunction(this.dialect, rows.map((row) => conjunction(this.dialect, idFields.map((field) => import_kysely8.BinaryOperationNode.create(import_kysely8.ReferenceNode.create(import_kysely8.ColumnNode.create(field), import_kysely8.TableNode.create(table)), import_kysely8.OperatorNode.create("="), import_kysely8.ValueNode.create(row[field]))))));
3135
3315
  }
3136
3316
  getMutationModel(node) {
3137
- const r = (0, import_ts_pattern8.match)(node).when(import_kysely8.InsertQueryNode.is, (node2) => ({
3317
+ const r = (0, import_ts_pattern9.match)(node).when(import_kysely8.InsertQueryNode.is, (node2) => ({
3138
3318
  mutationModel: getTableName(node2.into),
3139
3319
  alias: void 0
3140
3320
  })).when(import_kysely8.UpdateQueryNode.is, (node2) => {
@@ -3173,23 +3353,24 @@ var PolicyHandler = class extends import_kysely8.OperationNodeTransformer {
3173
3353
  return m2mFilter;
3174
3354
  }
3175
3355
  const policies = this.getModelPolicies(model, operation);
3176
- if (policies.length === 0) {
3177
- return falseNode(this.dialect);
3178
- }
3179
3356
  const allows = policies.filter((policy) => policy.kind === "allow").map((policy) => this.compilePolicyCondition(model, alias, operation, policy));
3180
3357
  const denies = policies.filter((policy) => policy.kind === "deny").map((policy) => this.compilePolicyCondition(model, alias, operation, policy));
3181
3358
  let combinedPolicy;
3182
3359
  if (allows.length === 0) {
3183
- combinedPolicy = falseNode(this.dialect);
3360
+ if (operation === "post-update") {
3361
+ combinedPolicy = trueNode(this.dialect);
3362
+ } else {
3363
+ combinedPolicy = falseNode(this.dialect);
3364
+ }
3184
3365
  } else {
3185
3366
  combinedPolicy = disjunction(this.dialect, allows);
3186
- if (denies.length !== 0) {
3187
- const combinedDenies = conjunction(this.dialect, denies.map((d) => buildIsFalse(d, this.dialect)));
3188
- combinedPolicy = conjunction(this.dialect, [
3189
- combinedPolicy,
3190
- combinedDenies
3191
- ]);
3192
- }
3367
+ }
3368
+ if (denies.length !== 0) {
3369
+ const combinedDenies = conjunction(this.dialect, denies.map((d) => buildIsFalse(d, this.dialect)));
3370
+ combinedPolicy = conjunction(this.dialect, [
3371
+ combinedPolicy,
3372
+ combinedDenies
3373
+ ]);
3193
3374
  }
3194
3375
  return combinedPolicy;
3195
3376
  }
@@ -3236,8 +3417,7 @@ var PolicyHandler = class extends import_kysely8.OperationNodeTransformer {
3236
3417
  return new ExpressionTransformer(this.client).transform(policy.condition, {
3237
3418
  model,
3238
3419
  alias,
3239
- operation,
3240
- auth: this.client.$auth
3420
+ operation
3241
3421
  });
3242
3422
  }
3243
3423
  getModelPolicies(model, operation) {
@@ -3253,7 +3433,7 @@ var PolicyHandler = class extends import_kysely8.OperationNodeTransformer {
3253
3433
  kind: attr.name === "@@allow" ? "allow" : "deny",
3254
3434
  operations: extractOperations(attr.args[0].value),
3255
3435
  condition: attr.args[1].value
3256
- })).filter((policy) => policy.operations.includes("all") || policy.operations.includes(operation)));
3436
+ })).filter((policy) => operation !== "post-update" && policy.operations.includes("all") || policy.operations.includes(operation)));
3257
3437
  }
3258
3438
  return result;
3259
3439
  }
@@ -3354,18 +3534,9 @@ var PolicyPlugin = class {
3354
3534
  check
3355
3535
  };
3356
3536
  }
3357
- onKyselyQuery({
3358
- query,
3359
- client,
3360
- proceed
3361
- /*, transaction*/
3362
- }) {
3537
+ onKyselyQuery({ query, client, proceed }) {
3363
3538
  const handler = new PolicyHandler(client);
3364
- return handler.handle(
3365
- query,
3366
- proceed
3367
- /*, transaction*/
3368
- );
3539
+ return handler.handle(query, proceed);
3369
3540
  }
3370
3541
  };
3371
3542
 
@@ -3906,7 +4077,7 @@ var BaseOperationHandler = class {
3906
4077
  }
3907
4078
  evalGenerator(defaultValue) {
3908
4079
  if (ExpressionUtils.isCall(defaultValue)) {
3909
- return (0, import_ts_pattern9.match)(defaultValue.function).with("cuid", () => (0, import_cuid2.createId)()).with("uuid", () => defaultValue.args?.[0] && ExpressionUtils.isLiteral(defaultValue.args?.[0]) && defaultValue.args[0].value === 7 ? uuid.v7() : uuid.v4()).with("nanoid", () => defaultValue.args?.[0] && ExpressionUtils.isLiteral(defaultValue.args[0]) && typeof defaultValue.args[0].value === "number" ? (0, import_nanoid.nanoid)(defaultValue.args[0].value) : (0, import_nanoid.nanoid)()).with("ulid", () => (0, import_ulid.ulid)()).otherwise(() => void 0);
4080
+ return (0, import_ts_pattern10.match)(defaultValue.function).with("cuid", () => (0, import_cuid2.createId)()).with("uuid", () => defaultValue.args?.[0] && ExpressionUtils.isLiteral(defaultValue.args?.[0]) && defaultValue.args[0].value === 7 ? uuid.v7() : uuid.v4()).with("nanoid", () => defaultValue.args?.[0] && ExpressionUtils.isLiteral(defaultValue.args[0]) && typeof defaultValue.args[0].value === "number" ? (0, import_nanoid.nanoid)(defaultValue.args[0].value) : (0, import_nanoid.nanoid)()).with("ulid", () => (0, import_ulid.ulid)()).otherwise(() => void 0);
3910
4081
  } else if (ExpressionUtils.isMember(defaultValue) && ExpressionUtils.isCall(defaultValue.receiver) && defaultValue.receiver.function === "auth") {
3911
4082
  let val = this.client.$auth;
3912
4083
  for (const member of defaultValue.members) {
@@ -4088,7 +4259,7 @@ var BaseOperationHandler = class {
4088
4259
  const value = this.dialect.transformPrimitive(payload[key], fieldDef.type, false);
4089
4260
  const eb = (0, import_kysely10.expressionBuilder)();
4090
4261
  const fieldRef = this.dialect.fieldRef(model, field, eb);
4091
- return (0, import_ts_pattern9.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(() => {
4262
+ return (0, import_ts_pattern10.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(() => {
4092
4263
  throw new InternalError(`Invalid incremental update operation: ${key}`);
4093
4264
  });
4094
4265
  }
@@ -4098,7 +4269,7 @@ var BaseOperationHandler = class {
4098
4269
  const value = this.dialect.transformPrimitive(payload[key], fieldDef.type, true);
4099
4270
  const eb = (0, import_kysely10.expressionBuilder)();
4100
4271
  const fieldRef = this.dialect.fieldRef(model, field, eb);
4101
- return (0, import_ts_pattern9.match)(key).with("set", () => value).with("push", () => {
4272
+ return (0, import_ts_pattern10.match)(key).with("set", () => value).with("push", () => {
4102
4273
  return eb(fieldRef, "||", eb.val(ensureArray(value)));
4103
4274
  }).otherwise(() => {
4104
4275
  throw new InternalError(`Invalid array update operation: ${key}`);
@@ -4168,8 +4339,9 @@ var BaseOperationHandler = class {
4168
4339
  };
4169
4340
  } else {
4170
4341
  const idFields = requireIdFields(this.schema, model);
4171
- const result = await query.returning(idFields).execute();
4172
- return result;
4342
+ const finalQuery = query.returning(idFields);
4343
+ const result = await this.executeQuery(kysely, finalQuery, "update");
4344
+ return result.rows;
4173
4345
  }
4174
4346
  }
4175
4347
  async processBaseModelUpdateMany(kysely, model, where, updateFields, filterModel) {
@@ -4789,7 +4961,7 @@ var AggregateOperationHandler = class extends BaseOperationHandler {
4789
4961
  Object.entries(value).forEach(([field, val]) => {
4790
4962
  if (val === true) {
4791
4963
  query = query.select((eb) => {
4792
- const fn = (0, import_ts_pattern10.match)(key).with("_sum", () => eb.fn.sum).with("_avg", () => eb.fn.avg).with("_max", () => eb.fn.max).with("_min", () => eb.fn.min).exhaustive();
4964
+ const fn = (0, import_ts_pattern11.match)(key).with("_sum", () => eb.fn.sum).with("_avg", () => eb.fn.avg).with("_max", () => eb.fn.max).with("_min", () => eb.fn.min).exhaustive();
4793
4965
  return fn(import_kysely11.sql.ref(`$sub.${field}`)).as(`${key}.${field}`);
4794
4966
  });
4795
4967
  }
@@ -4822,7 +4994,7 @@ var AggregateOperationHandler = class extends BaseOperationHandler {
4822
4994
  val = parseFloat(val);
4823
4995
  } else {
4824
4996
  if (op === "_sum" || op === "_min" || op === "_max") {
4825
- val = (0, import_ts_pattern10.match)(type).with("Int", () => parseInt(value, 10)).with("BigInt", () => BigInt(value)).with("Float", () => parseFloat(value)).with("Decimal", () => parseFloat(value)).otherwise(() => value);
4997
+ val = (0, import_ts_pattern11.match)(type).with("Int", () => parseInt(value, 10)).with("BigInt", () => BigInt(value)).with("Float", () => parseFloat(value)).with("Decimal", () => parseFloat(value)).otherwise(() => value);
4826
4998
  }
4827
4999
  }
4828
5000
  }
@@ -4873,14 +5045,14 @@ var CountOperationHandler = class extends BaseOperationHandler {
4873
5045
  };
4874
5046
 
4875
5047
  // src/client/crud/operations/create.ts
4876
- var import_ts_pattern11 = require("ts-pattern");
5048
+ var import_ts_pattern12 = require("ts-pattern");
4877
5049
  var CreateOperationHandler = class extends BaseOperationHandler {
4878
5050
  static {
4879
5051
  __name(this, "CreateOperationHandler");
4880
5052
  }
4881
5053
  async handle(operation, args) {
4882
5054
  const normalizedArgs = this.normalizeArgs(args);
4883
- return (0, import_ts_pattern11.match)(operation).with("create", () => this.runCreate(this.inputValidator.validateCreateArgs(this.model, normalizedArgs))).with("createMany", () => {
5055
+ return (0, import_ts_pattern12.match)(operation).with("create", () => this.runCreate(this.inputValidator.validateCreateArgs(this.model, normalizedArgs))).with("createMany", () => {
4884
5056
  return this.runCreateMany(this.inputValidator.validateCreateManyArgs(this.model, normalizedArgs));
4885
5057
  }).with("createManyAndReturn", () => {
4886
5058
  return this.runCreateManyAndReturn(this.inputValidator.validateCreateManyAndReturnArgs(this.model, normalizedArgs));
@@ -4927,14 +5099,14 @@ var CreateOperationHandler = class extends BaseOperationHandler {
4927
5099
  };
4928
5100
 
4929
5101
  // src/client/crud/operations/delete.ts
4930
- var import_ts_pattern12 = require("ts-pattern");
5102
+ var import_ts_pattern13 = require("ts-pattern");
4931
5103
  var DeleteOperationHandler = class extends BaseOperationHandler {
4932
5104
  static {
4933
5105
  __name(this, "DeleteOperationHandler");
4934
5106
  }
4935
5107
  async handle(operation, args) {
4936
5108
  const normalizedArgs = this.normalizeArgs(args);
4937
- return (0, import_ts_pattern12.match)(operation).with("delete", () => this.runDelete(this.inputValidator.validateDeleteArgs(this.model, normalizedArgs))).with("deleteMany", () => this.runDeleteMany(this.inputValidator.validateDeleteManyArgs(this.model, normalizedArgs))).exhaustive();
5109
+ return (0, import_ts_pattern13.match)(operation).with("delete", () => this.runDelete(this.inputValidator.validateDeleteArgs(this.model, normalizedArgs))).with("deleteMany", () => this.runDeleteMany(this.inputValidator.validateDeleteManyArgs(this.model, normalizedArgs))).exhaustive();
4938
5110
  }
4939
5111
  async runDelete(args) {
4940
5112
  const existing = await this.readUnique(this.kysely, this.model, {
@@ -4986,7 +5158,7 @@ var FindOperationHandler = class extends BaseOperationHandler {
4986
5158
 
4987
5159
  // src/client/crud/operations/group-by.ts
4988
5160
  var import_kysely13 = require("kysely");
4989
- var import_ts_pattern13 = require("ts-pattern");
5161
+ var import_ts_pattern14 = require("ts-pattern");
4990
5162
  var GroupByOperationHandler = class extends BaseOperationHandler {
4991
5163
  static {
4992
5164
  __name(this, "GroupByOperationHandler");
@@ -5080,7 +5252,7 @@ var GroupByOperationHandler = class extends BaseOperationHandler {
5080
5252
  val = parseFloat(val);
5081
5253
  } else {
5082
5254
  if (op === "_sum" || op === "_min" || op === "_max") {
5083
- val = (0, import_ts_pattern13.match)(type).with("Int", () => parseInt(value, 10)).with("BigInt", () => BigInt(value)).with("Float", () => parseFloat(value)).with("Decimal", () => parseFloat(value)).otherwise(() => value);
5255
+ val = (0, import_ts_pattern14.match)(type).with("Int", () => parseInt(value, 10)).with("BigInt", () => BigInt(value)).with("Float", () => parseFloat(value)).with("Decimal", () => parseFloat(value)).otherwise(() => value);
5084
5256
  }
5085
5257
  }
5086
5258
  }
@@ -5095,14 +5267,14 @@ var GroupByOperationHandler = class extends BaseOperationHandler {
5095
5267
  };
5096
5268
 
5097
5269
  // src/client/crud/operations/update.ts
5098
- var import_ts_pattern14 = require("ts-pattern");
5270
+ var import_ts_pattern15 = require("ts-pattern");
5099
5271
  var UpdateOperationHandler = class extends BaseOperationHandler {
5100
5272
  static {
5101
5273
  __name(this, "UpdateOperationHandler");
5102
5274
  }
5103
5275
  async handle(operation, args) {
5104
5276
  const normalizedArgs = this.normalizeArgs(args);
5105
- return (0, import_ts_pattern14.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();
5277
+ return (0, import_ts_pattern15.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();
5106
5278
  }
5107
5279
  async runUpdate(args) {
5108
5280
  const readBackResult = await this.safeTransaction(async (tx) => {
@@ -5182,7 +5354,7 @@ var UpdateOperationHandler = class extends BaseOperationHandler {
5182
5354
  var import_common_helpers11 = require("@zenstackhq/common-helpers");
5183
5355
  var import_decimal3 = __toESM(require("decimal.js"), 1);
5184
5356
  var import_json_stable_stringify = __toESM(require("json-stable-stringify"), 1);
5185
- var import_ts_pattern15 = require("ts-pattern");
5357
+ var import_ts_pattern16 = require("ts-pattern");
5186
5358
  var import_zod = require("zod");
5187
5359
 
5188
5360
  // src/utils/zod-utils.ts
@@ -5298,7 +5470,7 @@ var InputValidator = class {
5298
5470
  if (this.schema.typeDefs && type in this.schema.typeDefs) {
5299
5471
  return this.makeTypeDefSchema(type);
5300
5472
  } else {
5301
- return (0, import_ts_pattern15.match)(type).with("String", () => import_zod.z.string()).with("Int", () => import_zod.z.number().int()).with("Float", () => import_zod.z.number()).with("Boolean", () => import_zod.z.boolean()).with("BigInt", () => import_zod.z.union([
5473
+ return (0, import_ts_pattern16.match)(type).with("String", () => import_zod.z.string()).with("Int", () => import_zod.z.number().int()).with("Float", () => import_zod.z.number()).with("Boolean", () => import_zod.z.boolean()).with("BigInt", () => import_zod.z.union([
5302
5474
  import_zod.z.number().int(),
5303
5475
  import_zod.z.bigint()
5304
5476
  ])).with("Decimal", () => import_zod.z.union([
@@ -5459,7 +5631,7 @@ var InputValidator = class {
5459
5631
  if (this.schema.typeDefs && type in this.schema.typeDefs) {
5460
5632
  return this.makeTypeDefFilterSchema(type, optional);
5461
5633
  }
5462
- return (0, import_ts_pattern15.match)(type).with("String", () => this.makeStringFilterSchema(optional, withAggregations)).with(import_ts_pattern15.P.union("Int", "Float", "Decimal", "BigInt"), (type2) => this.makeNumberFilterSchema(this.makePrimitiveSchema(type2), optional, withAggregations)).with("Boolean", () => this.makeBooleanFilterSchema(optional, withAggregations)).with("DateTime", () => this.makeDateTimeFilterSchema(optional, withAggregations)).with("Bytes", () => this.makeBytesFilterSchema(optional, withAggregations)).with("Json", () => import_zod.z.any()).with("Unsupported", () => import_zod.z.never()).exhaustive();
5634
+ return (0, import_ts_pattern16.match)(type).with("String", () => this.makeStringFilterSchema(optional, withAggregations)).with(import_ts_pattern16.P.union("Int", "Float", "Decimal", "BigInt"), (type2) => this.makeNumberFilterSchema(this.makePrimitiveSchema(type2), optional, withAggregations)).with("Boolean", () => this.makeBooleanFilterSchema(optional, withAggregations)).with("DateTime", () => this.makeDateTimeFilterSchema(optional, withAggregations)).with("Bytes", () => this.makeBytesFilterSchema(optional, withAggregations)).with("Json", () => import_zod.z.any()).with("Unsupported", () => import_zod.z.never()).exhaustive();
5463
5635
  }
5464
5636
  makeTypeDefFilterSchema(_type, _optional) {
5465
5637
  return import_zod.z.never();
@@ -6405,7 +6577,7 @@ __name(performanceNow, "performanceNow");
6405
6577
  // src/client/executor/zenstack-query-executor.ts
6406
6578
  var import_common_helpers13 = require("@zenstackhq/common-helpers");
6407
6579
  var import_kysely15 = require("kysely");
6408
- var import_ts_pattern16 = require("ts-pattern");
6580
+ var import_ts_pattern17 = require("ts-pattern");
6409
6581
 
6410
6582
  // src/client/executor/name-mapper.ts
6411
6583
  var import_common_helpers12 = require("@zenstackhq/common-helpers");
@@ -6773,13 +6945,37 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends import_kysely15
6773
6945
  get options() {
6774
6946
  return this.client.$options;
6775
6947
  }
6776
- async executeQuery(compiledQuery, queryId) {
6948
+ executeQuery(compiledQuery, queryId) {
6777
6949
  const queryParams = compiledQuery.$raw ? compiledQuery.parameters : void 0;
6778
- const result = await this.proceedQueryWithKyselyInterceptors(compiledQuery.query, queryParams, queryId.queryId);
6779
- return result.result;
6950
+ return this.provideConnection(async (connection) => {
6951
+ let startedTx = false;
6952
+ try {
6953
+ if (this.isMutationNode(compiledQuery.query) && !this.driver.isTransactionConnection(connection)) {
6954
+ await this.driver.beginTransaction(connection, {
6955
+ isolationLevel: TransactionIsolationLevel.RepeatableRead
6956
+ });
6957
+ startedTx = true;
6958
+ }
6959
+ const result = await this.proceedQueryWithKyselyInterceptors(connection, compiledQuery.query, queryParams, queryId.queryId);
6960
+ if (startedTx) {
6961
+ await this.driver.commitTransaction(connection);
6962
+ }
6963
+ return result;
6964
+ } catch (err) {
6965
+ if (startedTx) {
6966
+ await this.driver.rollbackTransaction(connection);
6967
+ }
6968
+ if (err instanceof ZenStackError) {
6969
+ throw err;
6970
+ } else {
6971
+ const message = `Failed to execute query: ${err}, sql: ${compiledQuery?.sql}`;
6972
+ throw new QueryError(message, err);
6973
+ }
6974
+ }
6975
+ });
6780
6976
  }
6781
- async proceedQueryWithKyselyInterceptors(queryNode, parameters, queryId) {
6782
- let proceed = /* @__PURE__ */ __name((q) => this.proceedQuery(q, parameters, queryId), "proceed");
6977
+ async proceedQueryWithKyselyInterceptors(connection, queryNode, parameters, queryId) {
6978
+ let proceed = /* @__PURE__ */ __name((q) => this.proceedQuery(connection, q, parameters, queryId), "proceed");
6783
6979
  const hooks = [];
6784
6980
  for (const plugin of this.client.$options.plugins ?? []) {
6785
6981
  if (plugin.onKyselyQuery) {
@@ -6789,19 +6985,14 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends import_kysely15
6789
6985
  for (const hook of hooks) {
6790
6986
  const _proceed = proceed;
6791
6987
  proceed = /* @__PURE__ */ __name(async (query) => {
6792
- const _p = /* @__PURE__ */ __name(async (q) => {
6793
- const r = await _proceed(q);
6794
- return r.result;
6795
- }, "_p");
6988
+ const _p = /* @__PURE__ */ __name((q) => _proceed(q), "_p");
6796
6989
  const hookResult = await hook({
6797
6990
  client: this.client,
6798
6991
  schema: this.client.$schema,
6799
6992
  query,
6800
6993
  proceed: _p
6801
6994
  });
6802
- return {
6803
- result: hookResult
6804
- };
6995
+ return hookResult;
6805
6996
  }, "proceed");
6806
6997
  }
6807
6998
  const result = await proceed(queryNode);
@@ -6809,7 +7000,7 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends import_kysely15
6809
7000
  }
6810
7001
  getMutationInfo(queryNode) {
6811
7002
  const model = this.getMutationModel(queryNode);
6812
- const { action, where } = (0, import_ts_pattern16.match)(queryNode).when(import_kysely15.InsertQueryNode.is, () => ({
7003
+ const { action, where } = (0, import_ts_pattern17.match)(queryNode).when(import_kysely15.InsertQueryNode.is, () => ({
6813
7004
  action: "create",
6814
7005
  where: void 0
6815
7006
  })).when(import_kysely15.UpdateQueryNode.is, (node) => ({
@@ -6825,85 +7016,54 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends import_kysely15
6825
7016
  where
6826
7017
  };
6827
7018
  }
6828
- async proceedQuery(query, parameters, queryId) {
7019
+ async proceedQuery(connection, query, parameters, queryId) {
6829
7020
  let compiled;
6830
- try {
6831
- return await this.provideConnection(async (connection) => {
6832
- if (this.suppressMutationHooks || !this.isMutationNode(query) || !this.hasEntityMutationPlugins) {
6833
- const finalQuery2 = this.nameMapper.transformNode(query);
6834
- compiled = this.compileQuery(finalQuery2);
6835
- if (parameters) {
6836
- compiled = {
6837
- ...compiled,
6838
- parameters
6839
- };
6840
- }
6841
- const result = await connection.executeQuery(compiled);
6842
- return {
6843
- result
6844
- };
6845
- }
6846
- if ((import_kysely15.InsertQueryNode.is(query) || import_kysely15.UpdateQueryNode.is(query)) && this.hasEntityMutationPluginsWithAfterMutationHooks) {
6847
- query = {
6848
- ...query,
6849
- returning: import_kysely15.ReturningNode.create([
6850
- import_kysely15.SelectionNode.createSelectAll()
6851
- ])
6852
- };
6853
- }
6854
- const finalQuery = this.nameMapper.transformNode(query);
6855
- compiled = this.compileQuery(finalQuery);
6856
- if (parameters) {
6857
- compiled = {
6858
- ...compiled,
6859
- parameters
6860
- };
6861
- }
6862
- const currentlyInTx = this.driver.isTransactionConnection(connection);
6863
- const connectionClient = this.createClientForConnection(connection, currentlyInTx);
6864
- const mutationInfo = this.getMutationInfo(finalQuery);
6865
- let beforeMutationEntities;
6866
- const loadBeforeMutationEntities = /* @__PURE__ */ __name(async () => {
6867
- if (beforeMutationEntities === void 0 && (import_kysely15.UpdateQueryNode.is(query) || import_kysely15.DeleteQueryNode.is(query))) {
6868
- beforeMutationEntities = await this.loadEntities(mutationInfo.model, mutationInfo.where, connection);
6869
- }
6870
- return beforeMutationEntities;
6871
- }, "loadBeforeMutationEntities");
6872
- await this.callBeforeMutationHooks(finalQuery, mutationInfo, loadBeforeMutationEntities, connectionClient, queryId);
6873
- const shouldCreateTx = this.hasPluginRequestingAfterMutationWithinTransaction && !this.driver.isTransactionConnection(connection);
6874
- if (!shouldCreateTx) {
6875
- const result = await connection.executeQuery(compiled);
6876
- if (!this.driver.isTransactionConnection(connection)) {
6877
- await this.callAfterMutationHooks(result, finalQuery, mutationInfo, connectionClient, "all", queryId);
6878
- } else {
6879
- await this.callAfterMutationHooks(result, finalQuery, mutationInfo, connectionClient, "inTx", queryId);
6880
- this.driver.registerTransactionCommitCallback(connection, () => this.callAfterMutationHooks(result, finalQuery, mutationInfo, connectionClient, "outTx", queryId));
6881
- }
6882
- return {
6883
- result
6884
- };
6885
- } else {
6886
- await this.driver.beginTransaction(connection, {
6887
- isolationLevel: TransactionIsolationLevel.ReadCommitted
6888
- });
6889
- try {
6890
- const result = await connection.executeQuery(compiled);
6891
- await this.callAfterMutationHooks(result, finalQuery, mutationInfo, connectionClient, "inTx", queryId);
6892
- await this.driver.commitTransaction(connection);
6893
- await this.callAfterMutationHooks(result, finalQuery, mutationInfo, connectionClient, "outTx", queryId);
6894
- return {
6895
- result
6896
- };
6897
- } catch (err) {
6898
- await this.driver.rollbackTransaction(connection);
6899
- throw err;
6900
- }
6901
- }
6902
- });
6903
- } catch (err) {
6904
- const message = `Failed to execute query: ${err}, sql: ${compiled?.sql}`;
6905
- throw new QueryError(message, err);
7021
+ if (this.suppressMutationHooks || !this.isMutationNode(query) || !this.hasEntityMutationPlugins) {
7022
+ const finalQuery2 = this.nameMapper.transformNode(query);
7023
+ compiled = this.compileQuery(finalQuery2);
7024
+ if (parameters) {
7025
+ compiled = {
7026
+ ...compiled,
7027
+ parameters
7028
+ };
7029
+ }
7030
+ return connection.executeQuery(compiled);
7031
+ }
7032
+ if ((import_kysely15.InsertQueryNode.is(query) || import_kysely15.UpdateQueryNode.is(query)) && this.hasEntityMutationPluginsWithAfterMutationHooks) {
7033
+ query = {
7034
+ ...query,
7035
+ returning: import_kysely15.ReturningNode.create([
7036
+ import_kysely15.SelectionNode.createSelectAll()
7037
+ ])
7038
+ };
6906
7039
  }
7040
+ const finalQuery = this.nameMapper.transformNode(query);
7041
+ compiled = this.compileQuery(finalQuery);
7042
+ if (parameters) {
7043
+ compiled = {
7044
+ ...compiled,
7045
+ parameters
7046
+ };
7047
+ }
7048
+ const currentlyInTx = this.driver.isTransactionConnection(connection);
7049
+ const connectionClient = this.createClientForConnection(connection, currentlyInTx);
7050
+ const mutationInfo = this.getMutationInfo(finalQuery);
7051
+ let beforeMutationEntities;
7052
+ const loadBeforeMutationEntities = /* @__PURE__ */ __name(async () => {
7053
+ if (beforeMutationEntities === void 0 && (import_kysely15.UpdateQueryNode.is(query) || import_kysely15.DeleteQueryNode.is(query))) {
7054
+ beforeMutationEntities = await this.loadEntities(mutationInfo.model, mutationInfo.where, connection);
7055
+ }
7056
+ return beforeMutationEntities;
7057
+ }, "loadBeforeMutationEntities");
7058
+ await this.callBeforeMutationHooks(finalQuery, mutationInfo, loadBeforeMutationEntities, connectionClient, queryId);
7059
+ const result = await connection.executeQuery(compiled);
7060
+ if (!this.driver.isTransactionConnection(connection)) {
7061
+ await this.callAfterMutationHooks(result, finalQuery, mutationInfo, connectionClient, "all", queryId);
7062
+ } else {
7063
+ await this.callAfterMutationHooks(result, finalQuery, mutationInfo, connectionClient, "inTx", queryId);
7064
+ this.driver.registerTransactionCommitCallback(connection, () => this.callAfterMutationHooks(result, finalQuery, mutationInfo, connectionClient, "outTx", queryId));
7065
+ }
7066
+ return result;
6907
7067
  }
6908
7068
  createClientForConnection(connection, inTx) {
6909
7069
  const innerExecutor = this.withConnectionProvider(new import_kysely15.SingleConnectionProvider(connection));
@@ -6920,9 +7080,6 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends import_kysely15
6920
7080
  get hasEntityMutationPluginsWithAfterMutationHooks() {
6921
7081
  return (this.client.$options.plugins ?? []).some((plugin) => plugin.onEntityMutation?.afterEntityMutation);
6922
7082
  }
6923
- get hasPluginRequestingAfterMutationWithinTransaction() {
6924
- return (this.client.$options.plugins ?? []).some((plugin) => plugin.onEntityMutation?.runAfterMutationWithinTransaction);
6925
- }
6926
7083
  isMutationNode(queryNode) {
6927
7084
  return import_kysely15.InsertQueryNode.is(queryNode) || import_kysely15.UpdateQueryNode.is(queryNode) || import_kysely15.DeleteQueryNode.is(queryNode);
6928
7085
  }
@@ -6953,7 +7110,7 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends import_kysely15
6953
7110
  return newExecutor;
6954
7111
  }
6955
7112
  getMutationModel(queryNode) {
6956
- return (0, import_ts_pattern16.match)(queryNode).when(import_kysely15.InsertQueryNode.is, (node) => {
7113
+ return (0, import_ts_pattern17.match)(queryNode).when(import_kysely15.InsertQueryNode.is, (node) => {
6957
7114
  (0, import_common_helpers13.invariant)(node.into, "InsertQueryNode must have an into clause");
6958
7115
  return node.into.table.identifier.name;
6959
7116
  }).when(import_kysely15.UpdateQueryNode.is, (node) => {
@@ -7064,7 +7221,7 @@ __export(functions_exports, {
7064
7221
  });
7065
7222
  var import_common_helpers14 = require("@zenstackhq/common-helpers");
7066
7223
  var import_kysely16 = require("kysely");
7067
- var import_ts_pattern17 = require("ts-pattern");
7224
+ var import_ts_pattern18 = require("ts-pattern");
7068
7225
  var contains = /* @__PURE__ */ __name((eb, args, context) => textMatch(eb, args, context, "contains"), "contains");
7069
7226
  var search = /* @__PURE__ */ __name((_eb, _args) => {
7070
7227
  throw new Error(`"search" function is not implemented yet`);
@@ -7101,7 +7258,7 @@ var textMatch = /* @__PURE__ */ __name((eb, args, { dialect }, method) => {
7101
7258
  } else {
7102
7259
  op = "like";
7103
7260
  }
7104
- searchExpr = (0, import_ts_pattern17.match)(method).with("contains", () => eb.fn("CONCAT", [
7261
+ searchExpr = (0, import_ts_pattern18.match)(method).with("contains", () => eb.fn("CONCAT", [
7105
7262
  import_kysely16.sql.lit("%"),
7106
7263
  import_kysely16.sql`CAST(${searchExpr} as text)`,
7107
7264
  import_kysely16.sql.lit("%")
@@ -7173,7 +7330,7 @@ var currentOperation = /* @__PURE__ */ __name((_eb, args, { operation }) => {
7173
7330
  function processCasing(casing, result, model) {
7174
7331
  const opNode = casing.toOperationNode();
7175
7332
  (0, import_common_helpers14.invariant)(import_kysely16.ValueNode.is(opNode) && typeof opNode.value === "string", '"casting" parameter must be a string value');
7176
- result = (0, import_ts_pattern17.match)(opNode.value).with("original", () => model).with("upper", () => result.toUpperCase()).with("lower", () => result.toLowerCase()).with("capitalize", () => (0, import_common_helpers14.upperCaseFirst)(result)).with("uncapitalize", () => (0, import_common_helpers14.lowerCaseFirst)(result)).otherwise(() => {
7333
+ result = (0, import_ts_pattern18.match)(opNode.value).with("original", () => model).with("upper", () => result.toUpperCase()).with("lower", () => result.toLowerCase()).with("capitalize", () => (0, import_common_helpers14.upperCaseFirst)(result)).with("uncapitalize", () => (0, import_common_helpers14.lowerCaseFirst)(result)).otherwise(() => {
7177
7334
  throw new Error(`Invalid casing value: ${opNode.value}. Must be "original", "upper", "lower", "capitalize", or "uncapitalize".`);
7178
7335
  });
7179
7336
  return result;
@@ -7193,7 +7350,7 @@ __name(readBoolean, "readBoolean");
7193
7350
  var import_common_helpers15 = require("@zenstackhq/common-helpers");
7194
7351
  var import_kysely17 = require("kysely");
7195
7352
  var import_toposort = __toESM(require("toposort"), 1);
7196
- var import_ts_pattern18 = require("ts-pattern");
7353
+ var import_ts_pattern19 = require("ts-pattern");
7197
7354
  var SchemaDbPusher = class {
7198
7355
  static {
7199
7356
  __name(this, "SchemaDbPusher");
@@ -7359,7 +7516,7 @@ var SchemaDbPusher = class {
7359
7516
  return "jsonb";
7360
7517
  }
7361
7518
  const type = fieldDef.type;
7362
- const result = (0, import_ts_pattern18.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(() => {
7519
+ const result = (0, import_ts_pattern19.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(() => {
7363
7520
  throw new Error(`Unsupported field type: ${type}`);
7364
7521
  });
7365
7522
  if (fieldDef.array) {
@@ -7393,7 +7550,7 @@ var SchemaDbPusher = class {
7393
7550
  return table;
7394
7551
  }
7395
7552
  mapCascadeAction(action) {
7396
- return (0, import_ts_pattern18.match)(action).with("SetNull", () => "set null").with("Cascade", () => "cascade").with("Restrict", () => "restrict").with("NoAction", () => "no action").with("SetDefault", () => "set default").exhaustive();
7553
+ return (0, import_ts_pattern19.match)(action).with("SetNull", () => "set null").with("Cascade", () => "cascade").with("Restrict", () => "restrict").with("NoAction", () => "no action").with("SetDefault", () => "set default").exhaustive();
7397
7554
  }
7398
7555
  };
7399
7556
 
@@ -7893,6 +8050,7 @@ var import_kysely19 = require("kysely");
7893
8050
  NotFoundError,
7894
8051
  QueryError,
7895
8052
  ZenStackClient,
8053
+ ZenStackError,
7896
8054
  definePlugin,
7897
8055
  sql
7898
8056
  });