@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.
- package/dist/{contract-CusA0mQO.d.cts → contract-hoS-Sd87.d.cts} +4 -5
- package/dist/{contract-CusA0mQO.d.ts → contract-hoS-Sd87.d.ts} +4 -5
- package/dist/index.cjs +284 -190
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +287 -193
- package/dist/index.js.map +1 -1
- package/dist/plugins/policy/index.cjs +172 -88
- package/dist/plugins/policy/index.cjs.map +1 -1
- package/dist/plugins/policy/index.d.cts +1 -1
- package/dist/plugins/policy/index.d.ts +1 -1
- package/dist/plugins/policy/index.js +173 -89
- package/dist/plugins/policy/index.js.map +1 -1
- package/dist/schema.cjs +3 -0
- package/dist/schema.cjs.map +1 -1
- package/dist/schema.d.cts +1 -0
- package/dist/schema.d.ts +1 -0
- package/dist/schema.js +3 -0
- package/dist/schema.js.map +1 -1
- package/package.json +8 -8
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as kysely from 'kysely';
|
|
2
|
-
import { R as RuntimePlugin, V as OnKyselyQueryArgs } from '../../contract-
|
|
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-
|
|
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
|
|
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
|
|
153
|
-
if (!
|
|
159
|
+
const modelDef = getModel(schema, model);
|
|
160
|
+
if (!modelDef) {
|
|
154
161
|
throw new QueryError(`Model "${model}" not found in schema`);
|
|
155
162
|
}
|
|
156
|
-
return
|
|
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,
|
|
165
|
-
const modelDef =
|
|
166
|
-
if (
|
|
167
|
-
|
|
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
|
-
|
|
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) =>
|
|
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) =>
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
|
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),
|
|
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
|
-
|
|
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
|
-
|
|
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 =
|
|
2087
|
-
for (const member of
|
|
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 =
|
|
2097
|
-
const member =
|
|
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(
|
|
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 ===
|
|
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
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
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
|
-
|
|
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
|
|
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),
|
|
2396
|
+
await this.enforcePreCreatePolicyForOne(model, fields, values.map((v) => v.node), proceed);
|
|
2330
2397
|
}
|
|
2331
2398
|
}
|
|
2332
|
-
async enforcePreCreatePolicyForOne(model, fields, values,
|
|
2333
|
-
const
|
|
2334
|
-
const
|
|
2335
|
-
for (
|
|
2336
|
-
|
|
2337
|
-
|
|
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
|
|
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(
|
|
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
|
|
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
|
|
2467
|
-
const denies = policies.filter((policy) => policy.kind === "deny").map((policy) => this.transformPolicyCondition(model, alias, operation, policy
|
|
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
|
|
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
|
}
|