@zenstackhq/runtime 3.0.0-beta.2 → 3.0.0-beta.4

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.
@@ -1,5 +1,5 @@
1
1
  import * as kysely from 'kysely';
2
- import { R as RuntimePlugin, V as OnKyselyQueryArgs } from '../../contract-CusA0mQO.cjs';
2
+ import { R as RuntimePlugin, V as OnKyselyQueryArgs } from '../../contract-hoS-Sd87.cjs';
3
3
  import { SchemaDef } from '@zenstackhq/sdk/schema';
4
4
  import 'decimal.js';
5
5
 
@@ -1,5 +1,5 @@
1
1
  import * as kysely from 'kysely';
2
- import { R as RuntimePlugin, V as OnKyselyQueryArgs } from '../../contract-CusA0mQO.js';
2
+ import { R as RuntimePlugin, V as OnKyselyQueryArgs } from '../../contract-hoS-Sd87.js';
3
3
  import { SchemaDef } from '@zenstackhq/sdk/schema';
4
4
  import 'decimal.js';
5
5
 
@@ -15,7 +15,7 @@ var RejectedByPolicyError = class extends Error {
15
15
 
16
16
  // src/plugins/policy/policy-handler.ts
17
17
  import { invariant as invariant6 } from "@zenstackhq/common-helpers";
18
- 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";
18
+ import { AliasNode as AliasNode3, BinaryOperationNode as BinaryOperationNode3, ColumnNode as ColumnNode2, DeleteQueryNode, FromNode as FromNode2, FunctionNode as FunctionNode3, IdentifierNode as IdentifierNode2, InsertQueryNode, OperationNodeTransformer, OperatorNode as OperatorNode3, ParensNode as ParensNode2, PrimitiveValueListNode, RawNode, ReturningNode, SelectionNode as SelectionNode2, SelectQueryNode as SelectQueryNode2, TableNode as TableNode3, UpdateQueryNode, ValueListNode as ValueListNode2, ValueNode as ValueNode3, ValuesNode, WhereNode as WhereNode2 } from "kysely";
19
19
  import { match as match8 } from "ts-pattern";
20
20
 
21
21
  // src/client/crud/dialects/index.ts
@@ -109,6 +109,9 @@ var ExpressionUtils = {
109
109
  or: /* @__PURE__ */ __name((expr2, ...expressions) => {
110
110
  return expressions.reduce((acc, exp) => ExpressionUtils.binary(acc, "||", exp), expr2);
111
111
  }, "or"),
112
+ not: /* @__PURE__ */ __name((expr2) => {
113
+ return ExpressionUtils.unary("!", expr2);
114
+ }, "not"),
112
115
  is: /* @__PURE__ */ __name((value, kind) => {
113
116
  return !!value && typeof value === "object" && "kind" in value && value.kind === kind;
114
117
  }, "is"),
@@ -145,15 +148,19 @@ var InternalError = class extends Error {
145
148
 
146
149
  // src/client/query-utils.ts
147
150
  function getModel(schema, model) {
148
- return schema.models[model];
151
+ return Object.values(schema.models).find((m) => m.name.toLowerCase() === model.toLowerCase());
149
152
  }
150
153
  __name(getModel, "getModel");
154
+ function getTypeDef(schema, type) {
155
+ return schema.typeDefs?.[type];
156
+ }
157
+ __name(getTypeDef, "getTypeDef");
151
158
  function requireModel(schema, model) {
152
- const matchedName = Object.keys(schema.models).find((k) => k.toLowerCase() === model.toLowerCase());
153
- if (!matchedName) {
159
+ const modelDef = getModel(schema, model);
160
+ if (!modelDef) {
154
161
  throw new QueryError(`Model "${model}" not found in schema`);
155
162
  }
156
- return schema.models[matchedName];
163
+ return modelDef;
157
164
  }
158
165
  __name(requireModel, "requireModel");
159
166
  function getField(schema, model, field) {
@@ -161,12 +168,24 @@ function getField(schema, model, field) {
161
168
  return modelDef?.fields[field];
162
169
  }
163
170
  __name(getField, "getField");
164
- function requireField(schema, model, field) {
165
- const modelDef = requireModel(schema, model);
166
- if (!modelDef.fields[field]) {
167
- throw new QueryError(`Field "${field}" not found in model "${model}"`);
171
+ function requireField(schema, modelOrType, field) {
172
+ const modelDef = getModel(schema, modelOrType);
173
+ if (modelDef) {
174
+ if (!modelDef.fields[field]) {
175
+ throw new QueryError(`Field "${field}" not found in model "${modelOrType}"`);
176
+ } else {
177
+ return modelDef.fields[field];
178
+ }
179
+ }
180
+ const typeDef = getTypeDef(schema, modelOrType);
181
+ if (typeDef) {
182
+ if (!typeDef.fields[field]) {
183
+ throw new QueryError(`Field "${field}" not found in type "${modelOrType}"`);
184
+ } else {
185
+ return typeDef.fields[field];
186
+ }
168
187
  }
169
- return modelDef.fields[field];
188
+ throw new QueryError(`Model or type "${modelOrType}" not found in schema`);
170
189
  }
171
190
  __name(requireField, "requireField");
172
191
  function getIdFields(schema, model) {
@@ -392,7 +411,7 @@ function aggregate(eb, expr2, op) {
392
411
  }
393
412
  __name(aggregate, "aggregate");
394
413
 
395
- // src/client/crud/dialects/base.ts
414
+ // src/client/crud/dialects/base-dialect.ts
396
415
  import { invariant, isPlainObject } from "@zenstackhq/common-helpers";
397
416
  import { expressionBuilder, sql } from "kysely";
398
417
  import { match as match2, P } from "ts-pattern";
@@ -411,7 +430,7 @@ function enumerate(x) {
411
430
  }
412
431
  __name(enumerate, "enumerate");
413
432
 
414
- // src/client/crud/dialects/base.ts
433
+ // src/client/crud/dialects/base-dialect.ts
415
434
  var BaseCrudDialect = class {
416
435
  static {
417
436
  __name(this, "BaseCrudDialect");
@@ -1785,6 +1804,12 @@ function isFalseNode(node) {
1785
1804
  }
1786
1805
  __name(isFalseNode, "isFalseNode");
1787
1806
  function conjunction(dialect, nodes) {
1807
+ if (nodes.length === 0) {
1808
+ return trueNode(dialect);
1809
+ }
1810
+ if (nodes.length === 1) {
1811
+ return nodes[0];
1812
+ }
1788
1813
  if (nodes.some(isFalseNode)) {
1789
1814
  return falseNode(dialect);
1790
1815
  }
@@ -1792,10 +1817,16 @@ function conjunction(dialect, nodes) {
1792
1817
  if (items.length === 0) {
1793
1818
  return trueNode(dialect);
1794
1819
  }
1795
- return items.reduce((acc, node) => OrNode.is(node) ? AndNode.create(acc, ParensNode.create(node)) : AndNode.create(acc, node));
1820
+ return items.reduce((acc, node) => AndNode.create(wrapParensIf(acc, OrNode.is), wrapParensIf(node, OrNode.is)));
1796
1821
  }
1797
1822
  __name(conjunction, "conjunction");
1798
1823
  function disjunction(dialect, nodes) {
1824
+ if (nodes.length === 0) {
1825
+ return falseNode(dialect);
1826
+ }
1827
+ if (nodes.length === 1) {
1828
+ return nodes[0];
1829
+ }
1799
1830
  if (nodes.some(isTrueNode)) {
1800
1831
  return trueNode(dialect);
1801
1832
  }
@@ -1803,13 +1834,23 @@ function disjunction(dialect, nodes) {
1803
1834
  if (items.length === 0) {
1804
1835
  return falseNode(dialect);
1805
1836
  }
1806
- return items.reduce((acc, node) => AndNode.is(node) ? OrNode.create(acc, ParensNode.create(node)) : OrNode.create(acc, node));
1837
+ return items.reduce((acc, node) => OrNode.create(wrapParensIf(acc, AndNode.is), wrapParensIf(node, AndNode.is)));
1807
1838
  }
1808
1839
  __name(disjunction, "disjunction");
1809
- function logicalNot(node) {
1810
- return UnaryOperationNode.create(OperatorNode.create("not"), AndNode.is(node) || OrNode.is(node) ? ParensNode.create(node) : node);
1840
+ function logicalNot(dialect, node) {
1841
+ if (isTrueNode(node)) {
1842
+ return falseNode(dialect);
1843
+ }
1844
+ if (isFalseNode(node)) {
1845
+ return trueNode(dialect);
1846
+ }
1847
+ return UnaryOperationNode.create(OperatorNode.create("not"), wrapParensIf(node, (n) => AndNode.is(n) || OrNode.is(n)));
1811
1848
  }
1812
1849
  __name(logicalNot, "logicalNot");
1850
+ function wrapParensIf(node, predicate) {
1851
+ return predicate(node) ? ParensNode.create(node) : node;
1852
+ }
1853
+ __name(wrapParensIf, "wrapParensIf");
1813
1854
  function buildIsFalse(node, dialect) {
1814
1855
  if (isFalseNode(node)) {
1815
1856
  return trueNode(dialect);
@@ -1900,11 +1941,7 @@ var ExpressionTransformer = class {
1900
1941
  _field(expr2, context) {
1901
1942
  const fieldDef = requireField(this.schema, context.model, expr2.field);
1902
1943
  if (!fieldDef.relation) {
1903
- if (context.thisEntity) {
1904
- return context.thisEntity[expr2.field];
1905
- } else {
1906
- return this.createColumnRef(expr2.field, context);
1907
- }
1944
+ return this.createColumnRef(expr2.field, context);
1908
1945
  } else {
1909
1946
  const { memberFilter, memberSelect, ...restContext } = context;
1910
1947
  const relation = this.transformRelationAccess(expr2.field, fieldDef.type, restContext);
@@ -1945,7 +1982,7 @@ var ExpressionTransformer = class {
1945
1982
  ]);
1946
1983
  }
1947
1984
  if (this.isAuthCall(expr2.left) || this.isAuthCall(expr2.right)) {
1948
- return this.transformAuthBinary(expr2);
1985
+ return this.transformAuthBinary(expr2, context);
1949
1986
  }
1950
1987
  const op = expr2.op;
1951
1988
  if (op === "?" || op === "!" || op === "^") {
@@ -1998,11 +2035,10 @@ var ExpressionTransformer = class {
1998
2035
  let predicateFilter = this.transform(expr2.right, {
1999
2036
  ...context,
2000
2037
  model: newContextModel,
2001
- alias: void 0,
2002
- thisEntity: void 0
2038
+ alias: void 0
2003
2039
  });
2004
2040
  if (expr2.op === "!") {
2005
- predicateFilter = logicalNot(predicateFilter);
2041
+ predicateFilter = logicalNot(this.dialect, predicateFilter);
2006
2042
  }
2007
2043
  const count = FunctionNode2.create("count", [
2008
2044
  ValueNode2.createImmediate(1)
@@ -2014,20 +2050,38 @@ var ExpressionTransformer = class {
2014
2050
  memberFilter: predicateFilter
2015
2051
  });
2016
2052
  }
2017
- transformAuthBinary(expr2) {
2053
+ transformAuthBinary(expr2, context) {
2018
2054
  if (expr2.op !== "==" && expr2.op !== "!=") {
2019
- throw new Error(`Unsupported operator for auth call: ${expr2.op}`);
2055
+ throw new QueryError(`Unsupported operator for \`auth()\` in policy of model "${context.model}": ${expr2.op}`);
2020
2056
  }
2057
+ let authExpr;
2021
2058
  let other;
2022
2059
  if (this.isAuthCall(expr2.left)) {
2060
+ authExpr = expr2.left;
2023
2061
  other = expr2.right;
2024
2062
  } else {
2063
+ authExpr = expr2.right;
2025
2064
  other = expr2.left;
2026
2065
  }
2027
2066
  if (ExpressionUtils.isNull(other)) {
2028
2067
  return this.transformValue(expr2.op === "==" ? !this.auth : !!this.auth, "Boolean");
2029
2068
  } else {
2030
- throw new Error("Unsupported binary expression with `auth()`");
2069
+ const authModel = getModel(this.schema, this.authType);
2070
+ if (!authModel) {
2071
+ throw new QueryError(`Unsupported use of \`auth()\` in policy of model "${context.model}", comparing with \`auth()\` is only possible when auth type is a model`);
2072
+ }
2073
+ const idFields = Object.values(authModel.fields).filter((f) => f.id).map((f) => f.name);
2074
+ invariant5(idFields.length > 0, "auth type model must have at least one id field");
2075
+ const conditions = idFields.map((fieldName) => ExpressionUtils.binary(ExpressionUtils.member(authExpr, [
2076
+ fieldName
2077
+ ]), "==", ExpressionUtils.member(other, [
2078
+ fieldName
2079
+ ])));
2080
+ let result = this.buildAnd(conditions);
2081
+ if (expr2.op === "!=") {
2082
+ result = this.buildLogicalNot(result);
2083
+ }
2084
+ return this.transform(result, context);
2031
2085
  }
2032
2086
  }
2033
2087
  transformValue(value, type) {
@@ -2035,7 +2089,7 @@ var ExpressionTransformer = class {
2035
2089
  }
2036
2090
  _unary(expr2, context) {
2037
2091
  invariant5(expr2.op === "!", 'only "!" operator is supported');
2038
- return BinaryOperationNode2.create(this.transform(expr2.operand, context), this.transformOperator("!="), trueNode(this.dialect));
2092
+ return logicalNot(this.dialect, this.transform(expr2.operand, context));
2039
2093
  }
2040
2094
  transformOperator(op) {
2041
2095
  const mappedOp = match7(op).with("==", () => "=").otherwise(() => op);
@@ -2062,7 +2116,7 @@ var ExpressionTransformer = class {
2062
2116
  return eb.val(arg.value);
2063
2117
  }
2064
2118
  if (ExpressionUtils.isField(arg)) {
2065
- return context.thisEntityRaw ? eb.val(context.thisEntityRaw[arg.field]) : eb.ref(arg.field);
2119
+ return eb.ref(arg.field);
2066
2120
  }
2067
2121
  if (ExpressionUtils.isCall(arg)) {
2068
2122
  return this.transformCall(arg, context);
@@ -2077,14 +2131,33 @@ var ExpressionTransformer = class {
2077
2131
  if (this.isAuthCall(expr2.receiver)) {
2078
2132
  return this.valueMemberAccess(this.auth, expr2, this.authType);
2079
2133
  }
2080
- invariant5(ExpressionUtils.isField(expr2.receiver), "expect receiver to be field expression");
2134
+ invariant5(ExpressionUtils.isField(expr2.receiver) || ExpressionUtils.isThis(expr2.receiver), 'expect receiver to be field expression or "this"');
2135
+ let members = expr2.members;
2136
+ let receiver;
2081
2137
  const { memberFilter, memberSelect, ...restContext } = context;
2082
- const receiver = this.transform(expr2.receiver, restContext);
2138
+ if (ExpressionUtils.isThis(expr2.receiver)) {
2139
+ if (expr2.members.length === 1) {
2140
+ const fieldDef = requireField(this.schema, context.model, expr2.members[0]);
2141
+ invariant5(!fieldDef.relation, "this.relation access should have been transformed into relation access");
2142
+ return this.createColumnRef(expr2.members[0], restContext);
2143
+ }
2144
+ const firstMemberFieldDef = requireField(this.schema, context.model, expr2.members[0]);
2145
+ receiver = this.transformRelationAccess(expr2.members[0], firstMemberFieldDef.type, restContext);
2146
+ members = expr2.members.slice(1);
2147
+ } else {
2148
+ receiver = this.transform(expr2.receiver, restContext);
2149
+ }
2083
2150
  invariant5(SelectQueryNode.is(receiver), "expected receiver to be select query");
2084
- const receiverField = requireField(this.schema, context.model, expr2.receiver.field);
2151
+ let startType;
2152
+ if (ExpressionUtils.isField(expr2.receiver)) {
2153
+ const receiverField = requireField(this.schema, context.model, expr2.receiver.field);
2154
+ startType = receiverField.type;
2155
+ } else {
2156
+ startType = context.model;
2157
+ }
2085
2158
  const memberFields = [];
2086
- let currType = receiverField.type;
2087
- for (const member of expr2.members) {
2159
+ let currType = startType;
2160
+ for (const member of members) {
2088
2161
  const fieldDef = requireField(this.schema, currType, member);
2089
2162
  memberFields.push({
2090
2163
  fieldDef,
@@ -2093,22 +2166,21 @@ var ExpressionTransformer = class {
2093
2166
  currType = fieldDef.type;
2094
2167
  }
2095
2168
  let currNode = void 0;
2096
- for (let i = expr2.members.length - 1; i >= 0; i--) {
2097
- const member = expr2.members[i];
2169
+ for (let i = members.length - 1; i >= 0; i--) {
2170
+ const member = members[i];
2098
2171
  const { fieldDef, fromModel } = memberFields[i];
2099
2172
  if (fieldDef.relation) {
2100
2173
  const relation = this.transformRelationAccess(member, fieldDef.type, {
2101
2174
  ...restContext,
2102
2175
  model: fromModel,
2103
- alias: void 0,
2104
- thisEntity: void 0
2176
+ alias: void 0
2105
2177
  });
2106
2178
  if (currNode) {
2107
2179
  invariant5(SelectQueryNode.is(currNode), "expected select query node");
2108
2180
  currNode = {
2109
2181
  ...relation,
2110
2182
  selections: [
2111
- SelectionNode.create(AliasNode2.create(currNode, IdentifierNode.create(expr2.members[i + 1])))
2183
+ SelectionNode.create(AliasNode2.create(currNode, IdentifierNode.create(members[i + 1])))
2112
2184
  ]
2113
2185
  };
2114
2186
  } else {
@@ -2121,7 +2193,7 @@ var ExpressionTransformer = class {
2121
2193
  };
2122
2194
  }
2123
2195
  } else {
2124
- invariant5(i === expr2.members.length - 1, "plain field access must be the last segment");
2196
+ invariant5(i === members.length - 1, "plain field access must be the last segment");
2125
2197
  invariant5(!currNode, "plain field access must be the last segment");
2126
2198
  currNode = ColumnNode.create(member);
2127
2199
  }
@@ -2148,35 +2220,19 @@ var ExpressionTransformer = class {
2148
2220
  transformRelationAccess(field, relationModel, context) {
2149
2221
  const fromModel = context.model;
2150
2222
  const { keyPairs, ownedByModel } = getRelationForeignKeyFieldPairs(this.schema, fromModel, field);
2151
- if (context.thisEntity) {
2152
- let condition;
2153
- if (ownedByModel) {
2154
- condition = conjunction(this.dialect, keyPairs.map(({ fk, pk }) => BinaryOperationNode2.create(ReferenceNode2.create(ColumnNode.create(pk), TableNode2.create(relationModel)), OperatorNode2.create("="), context.thisEntity[fk])));
2155
- } else {
2156
- condition = conjunction(this.dialect, keyPairs.map(({ fk, pk }) => BinaryOperationNode2.create(ReferenceNode2.create(ColumnNode.create(fk), TableNode2.create(relationModel)), OperatorNode2.create("="), context.thisEntity[pk])));
2157
- }
2158
- return {
2159
- kind: "SelectQueryNode",
2160
- from: FromNode.create([
2161
- TableNode2.create(relationModel)
2162
- ]),
2163
- where: WhereNode.create(condition)
2164
- };
2223
+ let condition;
2224
+ if (ownedByModel) {
2225
+ condition = conjunction(this.dialect, keyPairs.map(({ fk, pk }) => BinaryOperationNode2.create(ReferenceNode2.create(ColumnNode.create(fk), TableNode2.create(context.alias ?? fromModel)), OperatorNode2.create("="), ReferenceNode2.create(ColumnNode.create(pk), TableNode2.create(relationModel)))));
2165
2226
  } else {
2166
- let condition;
2167
- if (ownedByModel) {
2168
- condition = conjunction(this.dialect, keyPairs.map(({ fk, pk }) => BinaryOperationNode2.create(ReferenceNode2.create(ColumnNode.create(fk), TableNode2.create(context.alias ?? fromModel)), OperatorNode2.create("="), ReferenceNode2.create(ColumnNode.create(pk), TableNode2.create(relationModel)))));
2169
- } else {
2170
- condition = conjunction(this.dialect, keyPairs.map(({ fk, pk }) => BinaryOperationNode2.create(ReferenceNode2.create(ColumnNode.create(pk), TableNode2.create(context.alias ?? fromModel)), OperatorNode2.create("="), ReferenceNode2.create(ColumnNode.create(fk), TableNode2.create(relationModel)))));
2171
- }
2172
- return {
2173
- kind: "SelectQueryNode",
2174
- from: FromNode.create([
2175
- TableNode2.create(relationModel)
2176
- ]),
2177
- where: WhereNode.create(condition)
2178
- };
2227
+ condition = conjunction(this.dialect, keyPairs.map(({ fk, pk }) => BinaryOperationNode2.create(ReferenceNode2.create(ColumnNode.create(pk), TableNode2.create(context.alias ?? fromModel)), OperatorNode2.create("="), ReferenceNode2.create(ColumnNode.create(fk), TableNode2.create(relationModel)))));
2179
2228
  }
2229
+ return {
2230
+ kind: "SelectQueryNode",
2231
+ from: FromNode.create([
2232
+ TableNode2.create(relationModel)
2233
+ ]),
2234
+ where: WhereNode.create(condition)
2235
+ };
2180
2236
  }
2181
2237
  createColumnRef(column, context) {
2182
2238
  return ReferenceNode2.create(ColumnNode.create(column), TableNode2.create(context.alias ?? context.model));
@@ -2190,6 +2246,18 @@ var ExpressionTransformer = class {
2190
2246
  isNullNode(node) {
2191
2247
  return ValueNode2.is(node) && node.value === null;
2192
2248
  }
2249
+ buildLogicalNot(result) {
2250
+ return ExpressionUtils.unary("!", result);
2251
+ }
2252
+ buildAnd(conditions) {
2253
+ if (conditions.length === 0) {
2254
+ return ExpressionUtils.literal(true);
2255
+ } else if (conditions.length === 1) {
2256
+ return conditions[0];
2257
+ } else {
2258
+ return conditions.reduce((acc, condition) => ExpressionUtils.binary(acc, "&&", condition));
2259
+ }
2260
+ }
2193
2261
  };
2194
2262
  _ts_decorate([
2195
2263
  expr("literal"),
@@ -2319,29 +2387,47 @@ var PolicyHandler = class extends OperationNodeTransformer {
2319
2387
  return selectedColumns.every((c) => idFields.includes(c));
2320
2388
  }
2321
2389
  async enforcePreCreatePolicy(node, proceed) {
2322
- if (!node.columns || !node.values) {
2323
- return;
2324
- }
2325
2390
  const model = this.getMutationModel(node);
2326
- const fields = node.columns.map((c) => c.column.name);
2327
- const valueRows = this.unwrapCreateValueRows(node.values, model, fields);
2391
+ const fields = node.columns?.map((c) => c.column.name) ?? [];
2392
+ const valueRows = node.values ? this.unwrapCreateValueRows(node.values, model, fields) : [
2393
+ []
2394
+ ];
2328
2395
  for (const values of valueRows) {
2329
- await this.enforcePreCreatePolicyForOne(model, fields, values.map((v) => v.node), values.map((v) => v.raw), proceed);
2396
+ await this.enforcePreCreatePolicyForOne(model, fields, values.map((v) => v.node), proceed);
2330
2397
  }
2331
2398
  }
2332
- async enforcePreCreatePolicyForOne(model, fields, values, valuesRaw, proceed) {
2333
- const thisEntity = {};
2334
- const thisEntityRaw = {};
2335
- for (let i = 0; i < fields.length; i++) {
2336
- thisEntity[fields[i]] = values[i];
2337
- thisEntityRaw[fields[i]] = valuesRaw[i];
2399
+ async enforcePreCreatePolicyForOne(model, fields, values, proceed) {
2400
+ const allFields = Object.keys(requireModel(this.client.$schema, model).fields);
2401
+ const allValues = [];
2402
+ for (const fieldName of allFields) {
2403
+ const index = fields.indexOf(fieldName);
2404
+ if (index >= 0) {
2405
+ allValues.push(values[index]);
2406
+ } else {
2407
+ allValues.push(ValueNode3.createImmediate(null));
2408
+ }
2338
2409
  }
2339
- const filter = this.buildPolicyFilter(model, void 0, "create", thisEntity, thisEntityRaw);
2410
+ const constTable = {
2411
+ kind: "SelectQueryNode",
2412
+ from: FromNode2.create([
2413
+ AliasNode3.create(ParensNode2.create(ValuesNode.create([
2414
+ ValueListNode2.create(allValues)
2415
+ ])), IdentifierNode2.create("$t"))
2416
+ ]),
2417
+ selections: allFields.map((field, index) => SelectionNode2.create(AliasNode3.create(ColumnNode2.create(`column${index + 1}`), IdentifierNode2.create(field))))
2418
+ };
2419
+ const filter = this.buildPolicyFilter(model, void 0, "create");
2340
2420
  const preCreateCheck = {
2341
2421
  kind: "SelectQueryNode",
2422
+ from: FromNode2.create([
2423
+ AliasNode3.create(constTable, IdentifierNode2.create(model))
2424
+ ]),
2342
2425
  selections: [
2343
- SelectionNode2.create(AliasNode3.create(filter, IdentifierNode2.create("$condition")))
2344
- ]
2426
+ SelectionNode2.create(AliasNode3.create(BinaryOperationNode3.create(FunctionNode3.create("COUNT", [
2427
+ ValueNode3.createImmediate(1)
2428
+ ]), OperatorNode3.create(">"), ValueNode3.createImmediate(0)), IdentifierNode2.create("$condition")))
2429
+ ],
2430
+ where: WhereNode2.create(filter)
2345
2431
  };
2346
2432
  const result = await proceed(preCreateCheck);
2347
2433
  if (!result.rows[0]?.$condition) {
@@ -2458,13 +2544,13 @@ var PolicyHandler = class extends OperationNodeTransformer {
2458
2544
  isMutationQueryNode(node) {
2459
2545
  return InsertQueryNode.is(node) || UpdateQueryNode.is(node) || DeleteQueryNode.is(node);
2460
2546
  }
2461
- buildPolicyFilter(model, alias, operation, thisEntity, thisEntityRaw) {
2547
+ buildPolicyFilter(model, alias, operation) {
2462
2548
  const policies = this.getModelPolicies(model, operation);
2463
2549
  if (policies.length === 0) {
2464
2550
  return falseNode(this.dialect);
2465
2551
  }
2466
- const allows = policies.filter((policy) => policy.kind === "allow").map((policy) => this.transformPolicyCondition(model, alias, operation, policy, thisEntity, thisEntityRaw));
2467
- const denies = policies.filter((policy) => policy.kind === "deny").map((policy) => this.transformPolicyCondition(model, alias, operation, policy, thisEntity, thisEntityRaw));
2552
+ const allows = policies.filter((policy) => policy.kind === "allow").map((policy) => this.transformPolicyCondition(model, alias, operation, policy));
2553
+ const denies = policies.filter((policy) => policy.kind === "deny").map((policy) => this.transformPolicyCondition(model, alias, operation, policy));
2468
2554
  let combinedPolicy;
2469
2555
  if (allows.length === 0) {
2470
2556
  combinedPolicy = falseNode(this.dialect);
@@ -2560,13 +2646,11 @@ var PolicyHandler = class extends OperationNodeTransformer {
2560
2646
  return void 0;
2561
2647
  }
2562
2648
  }
2563
- transformPolicyCondition(model, alias, operation, policy, thisEntity, thisEntityRaw) {
2649
+ transformPolicyCondition(model, alias, operation, policy) {
2564
2650
  return new ExpressionTransformer(this.client.$schema, this.client.$options, this.client.$auth).transform(policy.condition, {
2565
2651
  model,
2566
2652
  alias,
2567
2653
  operation,
2568
- thisEntity,
2569
- thisEntityRaw,
2570
2654
  auth: this.client.$auth
2571
2655
  });
2572
2656
  }