@zenstackhq/runtime 3.0.0-beta.3 → 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
package/dist/index.cjs
CHANGED
|
@@ -42,7 +42,7 @@ __export(src_exports, {
|
|
|
42
42
|
module.exports = __toCommonJS(src_exports);
|
|
43
43
|
|
|
44
44
|
// src/client/client-impl.ts
|
|
45
|
-
var
|
|
45
|
+
var import_common_helpers15 = require("@zenstackhq/common-helpers");
|
|
46
46
|
var import_kysely17 = require("kysely");
|
|
47
47
|
|
|
48
48
|
// src/client/crud/operations/aggregate.ts
|
|
@@ -117,6 +117,9 @@ var ExpressionUtils = {
|
|
|
117
117
|
or: /* @__PURE__ */ __name((expr2, ...expressions) => {
|
|
118
118
|
return expressions.reduce((acc, exp) => ExpressionUtils.binary(acc, "||", exp), expr2);
|
|
119
119
|
}, "or"),
|
|
120
|
+
not: /* @__PURE__ */ __name((expr2) => {
|
|
121
|
+
return ExpressionUtils.unary("!", expr2);
|
|
122
|
+
}, "not"),
|
|
120
123
|
is: /* @__PURE__ */ __name((value, kind) => {
|
|
121
124
|
return !!value && typeof value === "object" && "kind" in value && value.kind === kind;
|
|
122
125
|
}, "is"),
|
|
@@ -177,22 +180,26 @@ var NotFoundError = class extends Error {
|
|
|
177
180
|
static {
|
|
178
181
|
__name(this, "NotFoundError");
|
|
179
182
|
}
|
|
180
|
-
constructor(model) {
|
|
181
|
-
super(`Entity not found for model "${model}"`);
|
|
183
|
+
constructor(model, details) {
|
|
184
|
+
super(`Entity not found for model "${model}"${details ? `: ${details}` : ""}`);
|
|
182
185
|
}
|
|
183
186
|
};
|
|
184
187
|
|
|
185
188
|
// src/client/query-utils.ts
|
|
186
189
|
function getModel(schema, model) {
|
|
187
|
-
return schema.models
|
|
190
|
+
return Object.values(schema.models).find((m) => m.name.toLowerCase() === model.toLowerCase());
|
|
188
191
|
}
|
|
189
192
|
__name(getModel, "getModel");
|
|
193
|
+
function getTypeDef(schema, type) {
|
|
194
|
+
return schema.typeDefs?.[type];
|
|
195
|
+
}
|
|
196
|
+
__name(getTypeDef, "getTypeDef");
|
|
190
197
|
function requireModel(schema, model) {
|
|
191
|
-
const
|
|
192
|
-
if (!
|
|
198
|
+
const modelDef = getModel(schema, model);
|
|
199
|
+
if (!modelDef) {
|
|
193
200
|
throw new QueryError(`Model "${model}" not found in schema`);
|
|
194
201
|
}
|
|
195
|
-
return
|
|
202
|
+
return modelDef;
|
|
196
203
|
}
|
|
197
204
|
__name(requireModel, "requireModel");
|
|
198
205
|
function getField(schema, model, field) {
|
|
@@ -200,12 +207,24 @@ function getField(schema, model, field) {
|
|
|
200
207
|
return modelDef?.fields[field];
|
|
201
208
|
}
|
|
202
209
|
__name(getField, "getField");
|
|
203
|
-
function requireField(schema,
|
|
204
|
-
const modelDef =
|
|
205
|
-
if (
|
|
206
|
-
|
|
210
|
+
function requireField(schema, modelOrType, field) {
|
|
211
|
+
const modelDef = getModel(schema, modelOrType);
|
|
212
|
+
if (modelDef) {
|
|
213
|
+
if (!modelDef.fields[field]) {
|
|
214
|
+
throw new QueryError(`Field "${field}" not found in model "${modelOrType}"`);
|
|
215
|
+
} else {
|
|
216
|
+
return modelDef.fields[field];
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
const typeDef = getTypeDef(schema, modelOrType);
|
|
220
|
+
if (typeDef) {
|
|
221
|
+
if (!typeDef.fields[field]) {
|
|
222
|
+
throw new QueryError(`Field "${field}" not found in type "${modelOrType}"`);
|
|
223
|
+
} else {
|
|
224
|
+
return typeDef.fields[field];
|
|
225
|
+
}
|
|
207
226
|
}
|
|
208
|
-
|
|
227
|
+
throw new QueryError(`Model or type "${modelOrType}" not found in schema`);
|
|
209
228
|
}
|
|
210
229
|
__name(requireField, "requireField");
|
|
211
230
|
function getIdFields(schema, model) {
|
|
@@ -533,7 +552,7 @@ var AGGREGATE_OPERATORS = [
|
|
|
533
552
|
"_max"
|
|
534
553
|
];
|
|
535
554
|
|
|
536
|
-
// src/client/crud/dialects/base.ts
|
|
555
|
+
// src/client/crud/dialects/base-dialect.ts
|
|
537
556
|
var import_common_helpers = require("@zenstackhq/common-helpers");
|
|
538
557
|
var import_kysely = require("kysely");
|
|
539
558
|
var import_ts_pattern2 = require("ts-pattern");
|
|
@@ -552,7 +571,7 @@ function enumerate(x) {
|
|
|
552
571
|
}
|
|
553
572
|
__name(enumerate, "enumerate");
|
|
554
573
|
|
|
555
|
-
// src/client/crud/dialects/base.ts
|
|
574
|
+
// src/client/crud/dialects/base-dialect.ts
|
|
556
575
|
var BaseCrudDialect = class {
|
|
557
576
|
static {
|
|
558
577
|
__name(this, "BaseCrudDialect");
|
|
@@ -1926,6 +1945,12 @@ function isFalseNode(node) {
|
|
|
1926
1945
|
}
|
|
1927
1946
|
__name(isFalseNode, "isFalseNode");
|
|
1928
1947
|
function conjunction(dialect, nodes) {
|
|
1948
|
+
if (nodes.length === 0) {
|
|
1949
|
+
return trueNode(dialect);
|
|
1950
|
+
}
|
|
1951
|
+
if (nodes.length === 1) {
|
|
1952
|
+
return nodes[0];
|
|
1953
|
+
}
|
|
1929
1954
|
if (nodes.some(isFalseNode)) {
|
|
1930
1955
|
return falseNode(dialect);
|
|
1931
1956
|
}
|
|
@@ -1933,10 +1958,16 @@ function conjunction(dialect, nodes) {
|
|
|
1933
1958
|
if (items.length === 0) {
|
|
1934
1959
|
return trueNode(dialect);
|
|
1935
1960
|
}
|
|
1936
|
-
return items.reduce((acc, node) => import_kysely5.
|
|
1961
|
+
return items.reduce((acc, node) => import_kysely5.AndNode.create(wrapParensIf(acc, import_kysely5.OrNode.is), wrapParensIf(node, import_kysely5.OrNode.is)));
|
|
1937
1962
|
}
|
|
1938
1963
|
__name(conjunction, "conjunction");
|
|
1939
1964
|
function disjunction(dialect, nodes) {
|
|
1965
|
+
if (nodes.length === 0) {
|
|
1966
|
+
return falseNode(dialect);
|
|
1967
|
+
}
|
|
1968
|
+
if (nodes.length === 1) {
|
|
1969
|
+
return nodes[0];
|
|
1970
|
+
}
|
|
1940
1971
|
if (nodes.some(isTrueNode)) {
|
|
1941
1972
|
return trueNode(dialect);
|
|
1942
1973
|
}
|
|
@@ -1944,13 +1975,23 @@ function disjunction(dialect, nodes) {
|
|
|
1944
1975
|
if (items.length === 0) {
|
|
1945
1976
|
return falseNode(dialect);
|
|
1946
1977
|
}
|
|
1947
|
-
return items.reduce((acc, node) => import_kysely5.
|
|
1978
|
+
return items.reduce((acc, node) => import_kysely5.OrNode.create(wrapParensIf(acc, import_kysely5.AndNode.is), wrapParensIf(node, import_kysely5.AndNode.is)));
|
|
1948
1979
|
}
|
|
1949
1980
|
__name(disjunction, "disjunction");
|
|
1950
|
-
function logicalNot(node) {
|
|
1951
|
-
|
|
1981
|
+
function logicalNot(dialect, node) {
|
|
1982
|
+
if (isTrueNode(node)) {
|
|
1983
|
+
return falseNode(dialect);
|
|
1984
|
+
}
|
|
1985
|
+
if (isFalseNode(node)) {
|
|
1986
|
+
return trueNode(dialect);
|
|
1987
|
+
}
|
|
1988
|
+
return import_kysely5.UnaryOperationNode.create(import_kysely5.OperatorNode.create("not"), wrapParensIf(node, (n) => import_kysely5.AndNode.is(n) || import_kysely5.OrNode.is(n)));
|
|
1952
1989
|
}
|
|
1953
1990
|
__name(logicalNot, "logicalNot");
|
|
1991
|
+
function wrapParensIf(node, predicate) {
|
|
1992
|
+
return predicate(node) ? import_kysely5.ParensNode.create(node) : node;
|
|
1993
|
+
}
|
|
1994
|
+
__name(wrapParensIf, "wrapParensIf");
|
|
1954
1995
|
function buildIsFalse(node, dialect) {
|
|
1955
1996
|
if (isFalseNode(node)) {
|
|
1956
1997
|
return trueNode(dialect);
|
|
@@ -2041,11 +2082,7 @@ var ExpressionTransformer = class {
|
|
|
2041
2082
|
_field(expr2, context) {
|
|
2042
2083
|
const fieldDef = requireField(this.schema, context.model, expr2.field);
|
|
2043
2084
|
if (!fieldDef.relation) {
|
|
2044
|
-
|
|
2045
|
-
return context.thisEntity[expr2.field];
|
|
2046
|
-
} else {
|
|
2047
|
-
return this.createColumnRef(expr2.field, context);
|
|
2048
|
-
}
|
|
2085
|
+
return this.createColumnRef(expr2.field, context);
|
|
2049
2086
|
} else {
|
|
2050
2087
|
const { memberFilter, memberSelect, ...restContext } = context;
|
|
2051
2088
|
const relation = this.transformRelationAccess(expr2.field, fieldDef.type, restContext);
|
|
@@ -2086,7 +2123,7 @@ var ExpressionTransformer = class {
|
|
|
2086
2123
|
]);
|
|
2087
2124
|
}
|
|
2088
2125
|
if (this.isAuthCall(expr2.left) || this.isAuthCall(expr2.right)) {
|
|
2089
|
-
return this.transformAuthBinary(expr2);
|
|
2126
|
+
return this.transformAuthBinary(expr2, context);
|
|
2090
2127
|
}
|
|
2091
2128
|
const op = expr2.op;
|
|
2092
2129
|
if (op === "?" || op === "!" || op === "^") {
|
|
@@ -2139,11 +2176,10 @@ var ExpressionTransformer = class {
|
|
|
2139
2176
|
let predicateFilter = this.transform(expr2.right, {
|
|
2140
2177
|
...context,
|
|
2141
2178
|
model: newContextModel,
|
|
2142
|
-
alias: void 0
|
|
2143
|
-
thisEntity: void 0
|
|
2179
|
+
alias: void 0
|
|
2144
2180
|
});
|
|
2145
2181
|
if (expr2.op === "!") {
|
|
2146
|
-
predicateFilter = logicalNot(predicateFilter);
|
|
2182
|
+
predicateFilter = logicalNot(this.dialect, predicateFilter);
|
|
2147
2183
|
}
|
|
2148
2184
|
const count = import_kysely6.FunctionNode.create("count", [
|
|
2149
2185
|
import_kysely6.ValueNode.createImmediate(1)
|
|
@@ -2155,20 +2191,38 @@ var ExpressionTransformer = class {
|
|
|
2155
2191
|
memberFilter: predicateFilter
|
|
2156
2192
|
});
|
|
2157
2193
|
}
|
|
2158
|
-
transformAuthBinary(expr2) {
|
|
2194
|
+
transformAuthBinary(expr2, context) {
|
|
2159
2195
|
if (expr2.op !== "==" && expr2.op !== "!=") {
|
|
2160
|
-
throw new
|
|
2196
|
+
throw new QueryError(`Unsupported operator for \`auth()\` in policy of model "${context.model}": ${expr2.op}`);
|
|
2161
2197
|
}
|
|
2198
|
+
let authExpr;
|
|
2162
2199
|
let other;
|
|
2163
2200
|
if (this.isAuthCall(expr2.left)) {
|
|
2201
|
+
authExpr = expr2.left;
|
|
2164
2202
|
other = expr2.right;
|
|
2165
2203
|
} else {
|
|
2204
|
+
authExpr = expr2.right;
|
|
2166
2205
|
other = expr2.left;
|
|
2167
2206
|
}
|
|
2168
2207
|
if (ExpressionUtils.isNull(other)) {
|
|
2169
2208
|
return this.transformValue(expr2.op === "==" ? !this.auth : !!this.auth, "Boolean");
|
|
2170
2209
|
} else {
|
|
2171
|
-
|
|
2210
|
+
const authModel = getModel(this.schema, this.authType);
|
|
2211
|
+
if (!authModel) {
|
|
2212
|
+
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`);
|
|
2213
|
+
}
|
|
2214
|
+
const idFields = Object.values(authModel.fields).filter((f) => f.id).map((f) => f.name);
|
|
2215
|
+
(0, import_common_helpers5.invariant)(idFields.length > 0, "auth type model must have at least one id field");
|
|
2216
|
+
const conditions = idFields.map((fieldName) => ExpressionUtils.binary(ExpressionUtils.member(authExpr, [
|
|
2217
|
+
fieldName
|
|
2218
|
+
]), "==", ExpressionUtils.member(other, [
|
|
2219
|
+
fieldName
|
|
2220
|
+
])));
|
|
2221
|
+
let result = this.buildAnd(conditions);
|
|
2222
|
+
if (expr2.op === "!=") {
|
|
2223
|
+
result = this.buildLogicalNot(result);
|
|
2224
|
+
}
|
|
2225
|
+
return this.transform(result, context);
|
|
2172
2226
|
}
|
|
2173
2227
|
}
|
|
2174
2228
|
transformValue(value, type) {
|
|
@@ -2176,7 +2230,7 @@ var ExpressionTransformer = class {
|
|
|
2176
2230
|
}
|
|
2177
2231
|
_unary(expr2, context) {
|
|
2178
2232
|
(0, import_common_helpers5.invariant)(expr2.op === "!", 'only "!" operator is supported');
|
|
2179
|
-
return
|
|
2233
|
+
return logicalNot(this.dialect, this.transform(expr2.operand, context));
|
|
2180
2234
|
}
|
|
2181
2235
|
transformOperator(op) {
|
|
2182
2236
|
const mappedOp = (0, import_ts_pattern7.match)(op).with("==", () => "=").otherwise(() => op);
|
|
@@ -2203,7 +2257,7 @@ var ExpressionTransformer = class {
|
|
|
2203
2257
|
return eb.val(arg.value);
|
|
2204
2258
|
}
|
|
2205
2259
|
if (ExpressionUtils.isField(arg)) {
|
|
2206
|
-
return
|
|
2260
|
+
return eb.ref(arg.field);
|
|
2207
2261
|
}
|
|
2208
2262
|
if (ExpressionUtils.isCall(arg)) {
|
|
2209
2263
|
return this.transformCall(arg, context);
|
|
@@ -2218,14 +2272,33 @@ var ExpressionTransformer = class {
|
|
|
2218
2272
|
if (this.isAuthCall(expr2.receiver)) {
|
|
2219
2273
|
return this.valueMemberAccess(this.auth, expr2, this.authType);
|
|
2220
2274
|
}
|
|
2221
|
-
(0, import_common_helpers5.invariant)(ExpressionUtils.isField(expr2.receiver),
|
|
2275
|
+
(0, import_common_helpers5.invariant)(ExpressionUtils.isField(expr2.receiver) || ExpressionUtils.isThis(expr2.receiver), 'expect receiver to be field expression or "this"');
|
|
2276
|
+
let members = expr2.members;
|
|
2277
|
+
let receiver;
|
|
2222
2278
|
const { memberFilter, memberSelect, ...restContext } = context;
|
|
2223
|
-
|
|
2279
|
+
if (ExpressionUtils.isThis(expr2.receiver)) {
|
|
2280
|
+
if (expr2.members.length === 1) {
|
|
2281
|
+
const fieldDef = requireField(this.schema, context.model, expr2.members[0]);
|
|
2282
|
+
(0, import_common_helpers5.invariant)(!fieldDef.relation, "this.relation access should have been transformed into relation access");
|
|
2283
|
+
return this.createColumnRef(expr2.members[0], restContext);
|
|
2284
|
+
}
|
|
2285
|
+
const firstMemberFieldDef = requireField(this.schema, context.model, expr2.members[0]);
|
|
2286
|
+
receiver = this.transformRelationAccess(expr2.members[0], firstMemberFieldDef.type, restContext);
|
|
2287
|
+
members = expr2.members.slice(1);
|
|
2288
|
+
} else {
|
|
2289
|
+
receiver = this.transform(expr2.receiver, restContext);
|
|
2290
|
+
}
|
|
2224
2291
|
(0, import_common_helpers5.invariant)(import_kysely6.SelectQueryNode.is(receiver), "expected receiver to be select query");
|
|
2225
|
-
|
|
2292
|
+
let startType;
|
|
2293
|
+
if (ExpressionUtils.isField(expr2.receiver)) {
|
|
2294
|
+
const receiverField = requireField(this.schema, context.model, expr2.receiver.field);
|
|
2295
|
+
startType = receiverField.type;
|
|
2296
|
+
} else {
|
|
2297
|
+
startType = context.model;
|
|
2298
|
+
}
|
|
2226
2299
|
const memberFields = [];
|
|
2227
|
-
let currType =
|
|
2228
|
-
for (const member of
|
|
2300
|
+
let currType = startType;
|
|
2301
|
+
for (const member of members) {
|
|
2229
2302
|
const fieldDef = requireField(this.schema, currType, member);
|
|
2230
2303
|
memberFields.push({
|
|
2231
2304
|
fieldDef,
|
|
@@ -2234,22 +2307,21 @@ var ExpressionTransformer = class {
|
|
|
2234
2307
|
currType = fieldDef.type;
|
|
2235
2308
|
}
|
|
2236
2309
|
let currNode = void 0;
|
|
2237
|
-
for (let i =
|
|
2238
|
-
const member =
|
|
2310
|
+
for (let i = members.length - 1; i >= 0; i--) {
|
|
2311
|
+
const member = members[i];
|
|
2239
2312
|
const { fieldDef, fromModel } = memberFields[i];
|
|
2240
2313
|
if (fieldDef.relation) {
|
|
2241
2314
|
const relation = this.transformRelationAccess(member, fieldDef.type, {
|
|
2242
2315
|
...restContext,
|
|
2243
2316
|
model: fromModel,
|
|
2244
|
-
alias: void 0
|
|
2245
|
-
thisEntity: void 0
|
|
2317
|
+
alias: void 0
|
|
2246
2318
|
});
|
|
2247
2319
|
if (currNode) {
|
|
2248
2320
|
(0, import_common_helpers5.invariant)(import_kysely6.SelectQueryNode.is(currNode), "expected select query node");
|
|
2249
2321
|
currNode = {
|
|
2250
2322
|
...relation,
|
|
2251
2323
|
selections: [
|
|
2252
|
-
import_kysely6.SelectionNode.create(import_kysely6.AliasNode.create(currNode, import_kysely6.IdentifierNode.create(
|
|
2324
|
+
import_kysely6.SelectionNode.create(import_kysely6.AliasNode.create(currNode, import_kysely6.IdentifierNode.create(members[i + 1])))
|
|
2253
2325
|
]
|
|
2254
2326
|
};
|
|
2255
2327
|
} else {
|
|
@@ -2262,7 +2334,7 @@ var ExpressionTransformer = class {
|
|
|
2262
2334
|
};
|
|
2263
2335
|
}
|
|
2264
2336
|
} else {
|
|
2265
|
-
(0, import_common_helpers5.invariant)(i ===
|
|
2337
|
+
(0, import_common_helpers5.invariant)(i === members.length - 1, "plain field access must be the last segment");
|
|
2266
2338
|
(0, import_common_helpers5.invariant)(!currNode, "plain field access must be the last segment");
|
|
2267
2339
|
currNode = import_kysely6.ColumnNode.create(member);
|
|
2268
2340
|
}
|
|
@@ -2289,35 +2361,19 @@ var ExpressionTransformer = class {
|
|
|
2289
2361
|
transformRelationAccess(field, relationModel, context) {
|
|
2290
2362
|
const fromModel = context.model;
|
|
2291
2363
|
const { keyPairs, ownedByModel } = getRelationForeignKeyFieldPairs(this.schema, fromModel, field);
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
condition = conjunction(this.dialect, keyPairs.map(({ fk, pk }) => import_kysely6.BinaryOperationNode.create(import_kysely6.ReferenceNode.create(import_kysely6.ColumnNode.create(pk), import_kysely6.TableNode.create(relationModel)), import_kysely6.OperatorNode.create("="), context.thisEntity[fk])));
|
|
2296
|
-
} else {
|
|
2297
|
-
condition = conjunction(this.dialect, keyPairs.map(({ fk, pk }) => import_kysely6.BinaryOperationNode.create(import_kysely6.ReferenceNode.create(import_kysely6.ColumnNode.create(fk), import_kysely6.TableNode.create(relationModel)), import_kysely6.OperatorNode.create("="), context.thisEntity[pk])));
|
|
2298
|
-
}
|
|
2299
|
-
return {
|
|
2300
|
-
kind: "SelectQueryNode",
|
|
2301
|
-
from: import_kysely6.FromNode.create([
|
|
2302
|
-
import_kysely6.TableNode.create(relationModel)
|
|
2303
|
-
]),
|
|
2304
|
-
where: import_kysely6.WhereNode.create(condition)
|
|
2305
|
-
};
|
|
2364
|
+
let condition;
|
|
2365
|
+
if (ownedByModel) {
|
|
2366
|
+
condition = conjunction(this.dialect, keyPairs.map(({ fk, pk }) => import_kysely6.BinaryOperationNode.create(import_kysely6.ReferenceNode.create(import_kysely6.ColumnNode.create(fk), import_kysely6.TableNode.create(context.alias ?? fromModel)), import_kysely6.OperatorNode.create("="), import_kysely6.ReferenceNode.create(import_kysely6.ColumnNode.create(pk), import_kysely6.TableNode.create(relationModel)))));
|
|
2306
2367
|
} else {
|
|
2307
|
-
|
|
2308
|
-
if (ownedByModel) {
|
|
2309
|
-
condition = conjunction(this.dialect, keyPairs.map(({ fk, pk }) => import_kysely6.BinaryOperationNode.create(import_kysely6.ReferenceNode.create(import_kysely6.ColumnNode.create(fk), import_kysely6.TableNode.create(context.alias ?? fromModel)), import_kysely6.OperatorNode.create("="), import_kysely6.ReferenceNode.create(import_kysely6.ColumnNode.create(pk), import_kysely6.TableNode.create(relationModel)))));
|
|
2310
|
-
} else {
|
|
2311
|
-
condition = conjunction(this.dialect, keyPairs.map(({ fk, pk }) => import_kysely6.BinaryOperationNode.create(import_kysely6.ReferenceNode.create(import_kysely6.ColumnNode.create(pk), import_kysely6.TableNode.create(context.alias ?? fromModel)), import_kysely6.OperatorNode.create("="), import_kysely6.ReferenceNode.create(import_kysely6.ColumnNode.create(fk), import_kysely6.TableNode.create(relationModel)))));
|
|
2312
|
-
}
|
|
2313
|
-
return {
|
|
2314
|
-
kind: "SelectQueryNode",
|
|
2315
|
-
from: import_kysely6.FromNode.create([
|
|
2316
|
-
import_kysely6.TableNode.create(relationModel)
|
|
2317
|
-
]),
|
|
2318
|
-
where: import_kysely6.WhereNode.create(condition)
|
|
2319
|
-
};
|
|
2368
|
+
condition = conjunction(this.dialect, keyPairs.map(({ fk, pk }) => import_kysely6.BinaryOperationNode.create(import_kysely6.ReferenceNode.create(import_kysely6.ColumnNode.create(pk), import_kysely6.TableNode.create(context.alias ?? fromModel)), import_kysely6.OperatorNode.create("="), import_kysely6.ReferenceNode.create(import_kysely6.ColumnNode.create(fk), import_kysely6.TableNode.create(relationModel)))));
|
|
2320
2369
|
}
|
|
2370
|
+
return {
|
|
2371
|
+
kind: "SelectQueryNode",
|
|
2372
|
+
from: import_kysely6.FromNode.create([
|
|
2373
|
+
import_kysely6.TableNode.create(relationModel)
|
|
2374
|
+
]),
|
|
2375
|
+
where: import_kysely6.WhereNode.create(condition)
|
|
2376
|
+
};
|
|
2321
2377
|
}
|
|
2322
2378
|
createColumnRef(column, context) {
|
|
2323
2379
|
return import_kysely6.ReferenceNode.create(import_kysely6.ColumnNode.create(column), import_kysely6.TableNode.create(context.alias ?? context.model));
|
|
@@ -2331,6 +2387,18 @@ var ExpressionTransformer = class {
|
|
|
2331
2387
|
isNullNode(node) {
|
|
2332
2388
|
return import_kysely6.ValueNode.is(node) && node.value === null;
|
|
2333
2389
|
}
|
|
2390
|
+
buildLogicalNot(result) {
|
|
2391
|
+
return ExpressionUtils.unary("!", result);
|
|
2392
|
+
}
|
|
2393
|
+
buildAnd(conditions) {
|
|
2394
|
+
if (conditions.length === 0) {
|
|
2395
|
+
return ExpressionUtils.literal(true);
|
|
2396
|
+
} else if (conditions.length === 1) {
|
|
2397
|
+
return conditions[0];
|
|
2398
|
+
} else {
|
|
2399
|
+
return conditions.reduce((acc, condition) => ExpressionUtils.binary(acc, "&&", condition));
|
|
2400
|
+
}
|
|
2401
|
+
}
|
|
2334
2402
|
};
|
|
2335
2403
|
_ts_decorate([
|
|
2336
2404
|
expr("literal"),
|
|
@@ -2460,29 +2528,47 @@ var PolicyHandler = class extends import_kysely7.OperationNodeTransformer {
|
|
|
2460
2528
|
return selectedColumns.every((c) => idFields.includes(c));
|
|
2461
2529
|
}
|
|
2462
2530
|
async enforcePreCreatePolicy(node, proceed) {
|
|
2463
|
-
if (!node.columns || !node.values) {
|
|
2464
|
-
return;
|
|
2465
|
-
}
|
|
2466
2531
|
const model = this.getMutationModel(node);
|
|
2467
|
-
const fields = node.columns
|
|
2468
|
-
const valueRows = this.unwrapCreateValueRows(node.values, model, fields)
|
|
2532
|
+
const fields = node.columns?.map((c) => c.column.name) ?? [];
|
|
2533
|
+
const valueRows = node.values ? this.unwrapCreateValueRows(node.values, model, fields) : [
|
|
2534
|
+
[]
|
|
2535
|
+
];
|
|
2469
2536
|
for (const values of valueRows) {
|
|
2470
|
-
await this.enforcePreCreatePolicyForOne(model, fields, values.map((v) => v.node),
|
|
2537
|
+
await this.enforcePreCreatePolicyForOne(model, fields, values.map((v) => v.node), proceed);
|
|
2471
2538
|
}
|
|
2472
2539
|
}
|
|
2473
|
-
async enforcePreCreatePolicyForOne(model, fields, values,
|
|
2474
|
-
const
|
|
2475
|
-
const
|
|
2476
|
-
for (
|
|
2477
|
-
|
|
2478
|
-
|
|
2540
|
+
async enforcePreCreatePolicyForOne(model, fields, values, proceed) {
|
|
2541
|
+
const allFields = Object.keys(requireModel(this.client.$schema, model).fields);
|
|
2542
|
+
const allValues = [];
|
|
2543
|
+
for (const fieldName of allFields) {
|
|
2544
|
+
const index = fields.indexOf(fieldName);
|
|
2545
|
+
if (index >= 0) {
|
|
2546
|
+
allValues.push(values[index]);
|
|
2547
|
+
} else {
|
|
2548
|
+
allValues.push(import_kysely7.ValueNode.createImmediate(null));
|
|
2549
|
+
}
|
|
2479
2550
|
}
|
|
2480
|
-
const
|
|
2551
|
+
const constTable = {
|
|
2552
|
+
kind: "SelectQueryNode",
|
|
2553
|
+
from: import_kysely7.FromNode.create([
|
|
2554
|
+
import_kysely7.AliasNode.create(import_kysely7.ParensNode.create(import_kysely7.ValuesNode.create([
|
|
2555
|
+
import_kysely7.ValueListNode.create(allValues)
|
|
2556
|
+
])), import_kysely7.IdentifierNode.create("$t"))
|
|
2557
|
+
]),
|
|
2558
|
+
selections: allFields.map((field, index) => import_kysely7.SelectionNode.create(import_kysely7.AliasNode.create(import_kysely7.ColumnNode.create(`column${index + 1}`), import_kysely7.IdentifierNode.create(field))))
|
|
2559
|
+
};
|
|
2560
|
+
const filter = this.buildPolicyFilter(model, void 0, "create");
|
|
2481
2561
|
const preCreateCheck = {
|
|
2482
2562
|
kind: "SelectQueryNode",
|
|
2563
|
+
from: import_kysely7.FromNode.create([
|
|
2564
|
+
import_kysely7.AliasNode.create(constTable, import_kysely7.IdentifierNode.create(model))
|
|
2565
|
+
]),
|
|
2483
2566
|
selections: [
|
|
2484
|
-
import_kysely7.SelectionNode.create(import_kysely7.AliasNode.create(
|
|
2485
|
-
|
|
2567
|
+
import_kysely7.SelectionNode.create(import_kysely7.AliasNode.create(import_kysely7.BinaryOperationNode.create(import_kysely7.FunctionNode.create("COUNT", [
|
|
2568
|
+
import_kysely7.ValueNode.createImmediate(1)
|
|
2569
|
+
]), import_kysely7.OperatorNode.create(">"), import_kysely7.ValueNode.createImmediate(0)), import_kysely7.IdentifierNode.create("$condition")))
|
|
2570
|
+
],
|
|
2571
|
+
where: import_kysely7.WhereNode.create(filter)
|
|
2486
2572
|
};
|
|
2487
2573
|
const result = await proceed(preCreateCheck);
|
|
2488
2574
|
if (!result.rows[0]?.$condition) {
|
|
@@ -2599,13 +2685,13 @@ var PolicyHandler = class extends import_kysely7.OperationNodeTransformer {
|
|
|
2599
2685
|
isMutationQueryNode(node) {
|
|
2600
2686
|
return import_kysely7.InsertQueryNode.is(node) || import_kysely7.UpdateQueryNode.is(node) || import_kysely7.DeleteQueryNode.is(node);
|
|
2601
2687
|
}
|
|
2602
|
-
buildPolicyFilter(model, alias, operation
|
|
2688
|
+
buildPolicyFilter(model, alias, operation) {
|
|
2603
2689
|
const policies = this.getModelPolicies(model, operation);
|
|
2604
2690
|
if (policies.length === 0) {
|
|
2605
2691
|
return falseNode(this.dialect);
|
|
2606
2692
|
}
|
|
2607
|
-
const allows = policies.filter((policy) => policy.kind === "allow").map((policy) => this.transformPolicyCondition(model, alias, operation, policy
|
|
2608
|
-
const denies = policies.filter((policy) => policy.kind === "deny").map((policy) => this.transformPolicyCondition(model, alias, operation, policy
|
|
2693
|
+
const allows = policies.filter((policy) => policy.kind === "allow").map((policy) => this.transformPolicyCondition(model, alias, operation, policy));
|
|
2694
|
+
const denies = policies.filter((policy) => policy.kind === "deny").map((policy) => this.transformPolicyCondition(model, alias, operation, policy));
|
|
2609
2695
|
let combinedPolicy;
|
|
2610
2696
|
if (allows.length === 0) {
|
|
2611
2697
|
combinedPolicy = falseNode(this.dialect);
|
|
@@ -2701,13 +2787,11 @@ var PolicyHandler = class extends import_kysely7.OperationNodeTransformer {
|
|
|
2701
2787
|
return void 0;
|
|
2702
2788
|
}
|
|
2703
2789
|
}
|
|
2704
|
-
transformPolicyCondition(model, alias, operation, policy
|
|
2790
|
+
transformPolicyCondition(model, alias, operation, policy) {
|
|
2705
2791
|
return new ExpressionTransformer(this.client.$schema, this.client.$options, this.client.$auth).transform(policy.condition, {
|
|
2706
2792
|
model,
|
|
2707
2793
|
alias,
|
|
2708
2794
|
operation,
|
|
2709
|
-
thisEntity,
|
|
2710
|
-
thisEntityRaw,
|
|
2711
2795
|
auth: this.client.$auth
|
|
2712
2796
|
});
|
|
2713
2797
|
}
|
|
@@ -2914,7 +2998,7 @@ var BaseOperationHandler = class {
|
|
|
2914
2998
|
throw new QueryError(`Model "${this.model}" is a delegate and cannot be created directly.`);
|
|
2915
2999
|
}
|
|
2916
3000
|
let createFields = {};
|
|
2917
|
-
let
|
|
3001
|
+
let updateParent = void 0;
|
|
2918
3002
|
let m2m = void 0;
|
|
2919
3003
|
if (fromRelation) {
|
|
2920
3004
|
m2m = getManyToManyRelation(this.schema, fromRelation.model, fromRelation.field);
|
|
@@ -2924,16 +3008,11 @@ var BaseOperationHandler = class {
|
|
|
2924
3008
|
const parentFkFields = this.buildFkAssignments(fromRelation.model, fromRelation.field, fromRelation.ids);
|
|
2925
3009
|
Object.assign(createFields, parentFkFields);
|
|
2926
3010
|
} else {
|
|
2927
|
-
|
|
2928
|
-
|
|
2929
|
-
|
|
2930
|
-
|
|
2931
|
-
|
|
2932
|
-
model: fromRelation.model,
|
|
2933
|
-
operation: "update"
|
|
2934
|
-
}));
|
|
2935
|
-
return this.executeQuery(kysely, query2, "update");
|
|
2936
|
-
}, "parentUpdateTask");
|
|
3011
|
+
updateParent = /* @__PURE__ */ __name((entity) => {
|
|
3012
|
+
for (const { fk, pk } of keyPairs) {
|
|
3013
|
+
fromRelation.parentUpdates[fk] = entity[pk];
|
|
3014
|
+
}
|
|
3015
|
+
}, "updateParent");
|
|
2937
3016
|
}
|
|
2938
3017
|
}
|
|
2939
3018
|
}
|
|
@@ -2965,7 +3044,7 @@ var BaseOperationHandler = class {
|
|
|
2965
3044
|
const baseCreateResult = await this.processBaseModelCreate(kysely, modelDef.baseModel, createFields, model);
|
|
2966
3045
|
createFields = baseCreateResult.remainingFields;
|
|
2967
3046
|
}
|
|
2968
|
-
const updatedData = this.
|
|
3047
|
+
const updatedData = this.fillGeneratedAndDefaultValues(modelDef, createFields);
|
|
2969
3048
|
const idFields = getIdFields(this.schema, model);
|
|
2970
3049
|
const query = kysely.insertInto(model).$if(Object.keys(updatedData).length === 0, (qb) => qb.defaultValues()).$if(Object.keys(updatedData).length > 0, (qb) => qb.values(updatedData)).returning(idFields).modifyEnd(this.makeContextComment({
|
|
2971
3050
|
model,
|
|
@@ -2981,8 +3060,8 @@ var BaseOperationHandler = class {
|
|
|
2981
3060
|
if (fromRelation && m2m) {
|
|
2982
3061
|
await this.handleManyToManyRelation(kysely, "connect", fromRelation.model, fromRelation.field, fromRelation.ids, m2m.otherModel, m2m.otherField, createdEntity, m2m.joinTable);
|
|
2983
3062
|
}
|
|
2984
|
-
if (
|
|
2985
|
-
|
|
3063
|
+
if (updateParent) {
|
|
3064
|
+
updateParent(createdEntity);
|
|
2986
3065
|
}
|
|
2987
3066
|
return createdEntity;
|
|
2988
3067
|
}
|
|
@@ -3096,7 +3175,7 @@ var BaseOperationHandler = class {
|
|
|
3096
3175
|
select: fieldsToSelectObject(referencedPkFields)
|
|
3097
3176
|
});
|
|
3098
3177
|
if (!relationEntity) {
|
|
3099
|
-
throw new NotFoundError(`Could not find the entity
|
|
3178
|
+
throw new NotFoundError(relationModel, `Could not find the entity to connect for the relation "${relationField.name}"`);
|
|
3100
3179
|
}
|
|
3101
3180
|
result = relationEntity;
|
|
3102
3181
|
}
|
|
@@ -3125,7 +3204,8 @@ var BaseOperationHandler = class {
|
|
|
3125
3204
|
const fromRelationContext = {
|
|
3126
3205
|
model: contextModel,
|
|
3127
3206
|
field: relationFieldName,
|
|
3128
|
-
ids: parentEntity
|
|
3207
|
+
ids: parentEntity,
|
|
3208
|
+
parentUpdates: {}
|
|
3129
3209
|
};
|
|
3130
3210
|
for (const [action, subPayload] of Object.entries(payload)) {
|
|
3131
3211
|
if (!subPayload) {
|
|
@@ -3142,23 +3222,11 @@ var BaseOperationHandler = class {
|
|
|
3142
3222
|
break;
|
|
3143
3223
|
}
|
|
3144
3224
|
case "connect": {
|
|
3145
|
-
tasks.push(this.connectRelation(kysely, relationModel, subPayload,
|
|
3146
|
-
model: contextModel,
|
|
3147
|
-
field: relationFieldName,
|
|
3148
|
-
ids: parentEntity
|
|
3149
|
-
}));
|
|
3225
|
+
tasks.push(this.connectRelation(kysely, relationModel, subPayload, fromRelationContext));
|
|
3150
3226
|
break;
|
|
3151
3227
|
}
|
|
3152
3228
|
case "connectOrCreate": {
|
|
3153
|
-
tasks.push(...enumerate(subPayload).map((item) => this.exists(kysely, relationModel, item.where).then((found) => !found ? this.create(kysely, relationModel, item.create,
|
|
3154
|
-
model: contextModel,
|
|
3155
|
-
field: relationFieldName,
|
|
3156
|
-
ids: parentEntity
|
|
3157
|
-
}) : this.connectRelation(kysely, relationModel, found, {
|
|
3158
|
-
model: contextModel,
|
|
3159
|
-
field: relationFieldName,
|
|
3160
|
-
ids: parentEntity
|
|
3161
|
-
}))));
|
|
3229
|
+
tasks.push(...enumerate(subPayload).map((item) => this.exists(kysely, relationModel, item.where).then((found) => !found ? this.create(kysely, relationModel, item.create, fromRelationContext) : this.connectRelation(kysely, relationModel, found, fromRelationContext))));
|
|
3162
3230
|
break;
|
|
3163
3231
|
}
|
|
3164
3232
|
default:
|
|
@@ -3194,7 +3262,7 @@ var BaseOperationHandler = class {
|
|
|
3194
3262
|
newItem[fk] = fromRelation.ids[pk];
|
|
3195
3263
|
}
|
|
3196
3264
|
}
|
|
3197
|
-
return this.
|
|
3265
|
+
return this.fillGeneratedAndDefaultValues(modelDef, newItem);
|
|
3198
3266
|
});
|
|
3199
3267
|
if (!this.dialect.supportInsertWithDefault) {
|
|
3200
3268
|
const allPassedFields = createData.reduce((acc, item) => {
|
|
@@ -3274,7 +3342,7 @@ var BaseOperationHandler = class {
|
|
|
3274
3342
|
remainingFieldRows
|
|
3275
3343
|
};
|
|
3276
3344
|
}
|
|
3277
|
-
|
|
3345
|
+
fillGeneratedAndDefaultValues(modelDef, data) {
|
|
3278
3346
|
const fields = modelDef.fields;
|
|
3279
3347
|
const values = clone(data);
|
|
3280
3348
|
for (const [field, fieldDef] of Object.entries(fields)) {
|
|
@@ -3289,6 +3357,16 @@ var BaseOperationHandler = class {
|
|
|
3289
3357
|
}
|
|
3290
3358
|
} else if (fields[field]?.updatedAt) {
|
|
3291
3359
|
values[field] = this.dialect.transformPrimitive(/* @__PURE__ */ new Date(), "DateTime", false);
|
|
3360
|
+
} else if (fields[field]?.default !== void 0) {
|
|
3361
|
+
let value = fields[field].default;
|
|
3362
|
+
if (fieldDef.type === "Json") {
|
|
3363
|
+
if (fieldDef.array && Array.isArray(value)) {
|
|
3364
|
+
value = value.map((v) => typeof v === "string" ? JSON.parse(v) : v);
|
|
3365
|
+
} else if (typeof value === "string") {
|
|
3366
|
+
value = JSON.parse(value);
|
|
3367
|
+
}
|
|
3368
|
+
}
|
|
3369
|
+
values[field] = this.dialect.transformPrimitive(value, fields[field].type, !!fields[field].array);
|
|
3292
3370
|
}
|
|
3293
3371
|
}
|
|
3294
3372
|
}
|
|
@@ -3401,7 +3479,10 @@ var BaseOperationHandler = class {
|
|
|
3401
3479
|
}
|
|
3402
3480
|
}
|
|
3403
3481
|
}
|
|
3404
|
-
await this.processRelationUpdates(kysely, model, field, fieldDef, thisEntity, finalData[field], throwIfNotFound);
|
|
3482
|
+
const parentUpdates = await this.processRelationUpdates(kysely, model, field, fieldDef, thisEntity, finalData[field], throwIfNotFound);
|
|
3483
|
+
if (Object.keys(parentUpdates).length > 0) {
|
|
3484
|
+
Object.assign(updateFields, parentUpdates);
|
|
3485
|
+
}
|
|
3405
3486
|
}
|
|
3406
3487
|
}
|
|
3407
3488
|
if (Object.keys(updateFields).length === 0) {
|
|
@@ -3589,7 +3670,8 @@ var BaseOperationHandler = class {
|
|
|
3589
3670
|
const fromRelationContext = {
|
|
3590
3671
|
model,
|
|
3591
3672
|
field,
|
|
3592
|
-
ids: parentIds
|
|
3673
|
+
ids: parentIds,
|
|
3674
|
+
parentUpdates: {}
|
|
3593
3675
|
};
|
|
3594
3676
|
for (const [key, value] of Object.entries(args)) {
|
|
3595
3677
|
switch (key) {
|
|
@@ -3664,6 +3746,7 @@ var BaseOperationHandler = class {
|
|
|
3664
3746
|
}
|
|
3665
3747
|
}
|
|
3666
3748
|
await Promise.all(tasks);
|
|
3749
|
+
return fromRelationContext.parentUpdates;
|
|
3667
3750
|
}
|
|
3668
3751
|
// #region relation manipulation
|
|
3669
3752
|
async connectRelation(kysely, model, data, fromRelation) {
|
|
@@ -3683,7 +3766,6 @@ var BaseOperationHandler = class {
|
|
|
3683
3766
|
}
|
|
3684
3767
|
} else {
|
|
3685
3768
|
const { ownedByModel, keyPairs } = getRelationForeignKeyFieldPairs(this.schema, fromRelation.model, fromRelation.field);
|
|
3686
|
-
let updateResult;
|
|
3687
3769
|
if (ownedByModel) {
|
|
3688
3770
|
(0, import_common_helpers8.invariant)(_data.length === 1, "only one entity can be connected");
|
|
3689
3771
|
const target = await this.readUnique(kysely, model, {
|
|
@@ -3692,14 +3774,9 @@ var BaseOperationHandler = class {
|
|
|
3692
3774
|
if (!target) {
|
|
3693
3775
|
throw new NotFoundError(model);
|
|
3694
3776
|
}
|
|
3695
|
-
|
|
3696
|
-
|
|
3697
|
-
|
|
3698
|
-
}), {})).modifyEnd(this.makeContextComment({
|
|
3699
|
-
model: fromRelation.model,
|
|
3700
|
-
operation: "update"
|
|
3701
|
-
}));
|
|
3702
|
-
updateResult = await this.executeQuery(kysely, query, "connect");
|
|
3777
|
+
for (const { fk, pk } of keyPairs) {
|
|
3778
|
+
fromRelation.parentUpdates[fk] = target[pk];
|
|
3779
|
+
}
|
|
3703
3780
|
} else {
|
|
3704
3781
|
const relationFieldDef = this.requireField(fromRelation.model, fromRelation.field);
|
|
3705
3782
|
if (!relationFieldDef.array) {
|
|
@@ -3719,10 +3796,10 @@ var BaseOperationHandler = class {
|
|
|
3719
3796
|
model,
|
|
3720
3797
|
operation: "update"
|
|
3721
3798
|
}));
|
|
3722
|
-
updateResult = await this.executeQuery(kysely, query, "connect");
|
|
3723
|
-
|
|
3724
|
-
|
|
3725
|
-
|
|
3799
|
+
const updateResult = await this.executeQuery(kysely, query, "connect");
|
|
3800
|
+
if (!updateResult.numAffectedRows || _data.length > updateResult.numAffectedRows) {
|
|
3801
|
+
throw new NotFoundError(model);
|
|
3802
|
+
}
|
|
3726
3803
|
}
|
|
3727
3804
|
}
|
|
3728
3805
|
}
|
|
@@ -3777,19 +3854,38 @@ var BaseOperationHandler = class {
|
|
|
3777
3854
|
if (ownedByModel) {
|
|
3778
3855
|
(0, import_common_helpers8.invariant)(disconnectConditions.length === 1, "only one entity can be disconnected");
|
|
3779
3856
|
const condition = disconnectConditions[0];
|
|
3780
|
-
|
|
3781
|
-
|
|
3782
|
-
|
|
3783
|
-
|
|
3784
|
-
|
|
3785
|
-
|
|
3786
|
-
|
|
3787
|
-
|
|
3788
|
-
|
|
3789
|
-
|
|
3790
|
-
|
|
3791
|
-
|
|
3792
|
-
|
|
3857
|
+
if (condition === true) {
|
|
3858
|
+
for (const { fk } of keyPairs) {
|
|
3859
|
+
fromRelation.parentUpdates[fk] = null;
|
|
3860
|
+
}
|
|
3861
|
+
} else {
|
|
3862
|
+
const fromEntity = await this.readUnique(kysely, fromRelation.model, {
|
|
3863
|
+
where: fromRelation.ids,
|
|
3864
|
+
select: fieldsToSelectObject(keyPairs.map(({ fk }) => fk))
|
|
3865
|
+
});
|
|
3866
|
+
if (!fromEntity || keyPairs.some(({ fk }) => fromEntity[fk] == null)) {
|
|
3867
|
+
return;
|
|
3868
|
+
}
|
|
3869
|
+
const relationFilter = {
|
|
3870
|
+
AND: [
|
|
3871
|
+
condition,
|
|
3872
|
+
Object.fromEntries(keyPairs.map(({ fk, pk }) => [
|
|
3873
|
+
pk,
|
|
3874
|
+
fromEntity[fk]
|
|
3875
|
+
]))
|
|
3876
|
+
]
|
|
3877
|
+
};
|
|
3878
|
+
const targetExists = await this.read(kysely, model, {
|
|
3879
|
+
where: relationFilter,
|
|
3880
|
+
take: 1,
|
|
3881
|
+
select: this.makeIdSelect(model)
|
|
3882
|
+
});
|
|
3883
|
+
if (targetExists.length > 0) {
|
|
3884
|
+
for (const { fk } of keyPairs) {
|
|
3885
|
+
fromRelation.parentUpdates[fk] = null;
|
|
3886
|
+
}
|
|
3887
|
+
}
|
|
3888
|
+
}
|
|
3793
3889
|
} else {
|
|
3794
3890
|
const query = kysely.updateTable(model).where(eb.and([
|
|
3795
3891
|
// fk filter
|
|
@@ -3854,7 +3950,7 @@ var BaseOperationHandler = class {
|
|
|
3854
3950
|
operation: "update"
|
|
3855
3951
|
}));
|
|
3856
3952
|
const r = await this.executeQuery(kysely, query2, "connect");
|
|
3857
|
-
if (_data.length > r.numAffectedRows) {
|
|
3953
|
+
if (!r.numAffectedRows || _data.length > r.numAffectedRows) {
|
|
3858
3954
|
throw new NotFoundError(model);
|
|
3859
3955
|
}
|
|
3860
3956
|
}
|
|
@@ -3880,8 +3976,10 @@ var BaseOperationHandler = class {
|
|
|
3880
3976
|
expectedDeleteCount = deleteConditions.length;
|
|
3881
3977
|
}
|
|
3882
3978
|
let deleteResult;
|
|
3979
|
+
let deleteFromModel;
|
|
3883
3980
|
const m2m = getManyToManyRelation(this.schema, fromRelation.model, fromRelation.field);
|
|
3884
3981
|
if (m2m) {
|
|
3982
|
+
deleteFromModel = model;
|
|
3885
3983
|
const fieldDef = this.requireField(fromRelation.model, fromRelation.field);
|
|
3886
3984
|
(0, import_common_helpers8.invariant)(fieldDef.relation?.opposite);
|
|
3887
3985
|
deleteResult = await this.delete(kysely, model, {
|
|
@@ -3899,11 +3997,12 @@ var BaseOperationHandler = class {
|
|
|
3899
3997
|
} else {
|
|
3900
3998
|
const { ownedByModel, keyPairs } = getRelationForeignKeyFieldPairs(this.schema, fromRelation.model, fromRelation.field);
|
|
3901
3999
|
if (ownedByModel) {
|
|
4000
|
+
deleteFromModel = fromRelation.model;
|
|
3902
4001
|
const fromEntity = await this.readUnique(kysely, fromRelation.model, {
|
|
3903
4002
|
where: fromRelation.ids
|
|
3904
4003
|
});
|
|
3905
4004
|
if (!fromEntity) {
|
|
3906
|
-
throw new NotFoundError(model);
|
|
4005
|
+
throw new NotFoundError(fromRelation.model);
|
|
3907
4006
|
}
|
|
3908
4007
|
const fieldDef = this.requireField(fromRelation.model, fromRelation.field);
|
|
3909
4008
|
(0, import_common_helpers8.invariant)(fieldDef.relation?.opposite);
|
|
@@ -3920,6 +4019,7 @@ var BaseOperationHandler = class {
|
|
|
3920
4019
|
]
|
|
3921
4020
|
});
|
|
3922
4021
|
} else {
|
|
4022
|
+
deleteFromModel = model;
|
|
3923
4023
|
deleteResult = await this.delete(kysely, model, {
|
|
3924
4024
|
AND: [
|
|
3925
4025
|
Object.fromEntries(keyPairs.map(({ fk, pk }) => [
|
|
@@ -3934,7 +4034,7 @@ var BaseOperationHandler = class {
|
|
|
3934
4034
|
}
|
|
3935
4035
|
}
|
|
3936
4036
|
if (throwForNotFound && expectedDeleteCount > deleteResult.count) {
|
|
3937
|
-
throw new NotFoundError(
|
|
4037
|
+
throw new NotFoundError(deleteFromModel);
|
|
3938
4038
|
}
|
|
3939
4039
|
}
|
|
3940
4040
|
normalizeRelationManipulationInput(model, data) {
|
|
@@ -4676,10 +4776,7 @@ var InputValidator = class {
|
|
|
4676
4776
|
return schema;
|
|
4677
4777
|
}
|
|
4678
4778
|
makeWhereSchema(model, unique, withoutRelationFields = false, withAggregations = false) {
|
|
4679
|
-
const modelDef =
|
|
4680
|
-
if (!modelDef) {
|
|
4681
|
-
throw new QueryError(`Model "${model}" not found in schema`);
|
|
4682
|
-
}
|
|
4779
|
+
const modelDef = requireModel(this.schema, model);
|
|
4683
4780
|
const fields = {};
|
|
4684
4781
|
for (const field of Object.keys(modelDef.fields)) {
|
|
4685
4782
|
const fieldDef = requireField(this.schema, model, field);
|
|
@@ -5725,18 +5822,16 @@ function performanceNow() {
|
|
|
5725
5822
|
__name(performanceNow, "performanceNow");
|
|
5726
5823
|
|
|
5727
5824
|
// src/client/executor/zenstack-query-executor.ts
|
|
5728
|
-
var
|
|
5825
|
+
var import_common_helpers11 = require("@zenstackhq/common-helpers");
|
|
5729
5826
|
var import_kysely14 = require("kysely");
|
|
5730
5827
|
var import_ts_pattern16 = require("ts-pattern");
|
|
5731
5828
|
|
|
5732
5829
|
// src/client/executor/kysely-utils.ts
|
|
5733
|
-
var import_common_helpers10 = require("@zenstackhq/common-helpers");
|
|
5734
5830
|
var import_kysely12 = require("kysely");
|
|
5735
5831
|
function stripAlias(node) {
|
|
5736
5832
|
if (import_kysely12.AliasNode.is(node)) {
|
|
5737
|
-
(0, import_common_helpers10.invariant)(import_kysely12.IdentifierNode.is(node.alias), "Expected identifier as alias");
|
|
5738
5833
|
return {
|
|
5739
|
-
alias: node.alias
|
|
5834
|
+
alias: node.alias,
|
|
5740
5835
|
node: node.node
|
|
5741
5836
|
};
|
|
5742
5837
|
} else {
|
|
@@ -5749,7 +5844,7 @@ function stripAlias(node) {
|
|
|
5749
5844
|
__name(stripAlias, "stripAlias");
|
|
5750
5845
|
|
|
5751
5846
|
// src/client/executor/name-mapper.ts
|
|
5752
|
-
var
|
|
5847
|
+
var import_common_helpers10 = require("@zenstackhq/common-helpers");
|
|
5753
5848
|
var import_kysely13 = require("kysely");
|
|
5754
5849
|
var QueryNameMapper = class extends import_kysely13.OperationNodeTransformer {
|
|
5755
5850
|
static {
|
|
@@ -5827,7 +5922,7 @@ var QueryNameMapper = class extends import_kysely13.OperationNodeTransformer {
|
|
|
5827
5922
|
const mappedFieldName = this.mapFieldName(scope.model, node.column.column.name);
|
|
5828
5923
|
let mappedTableName = node.table?.table.identifier.name;
|
|
5829
5924
|
if (mappedTableName) {
|
|
5830
|
-
if (scope.alias === mappedTableName) {
|
|
5925
|
+
if (scope.alias && import_kysely13.IdentifierNode.is(scope.alias) && scope.alias.name === mappedTableName) {
|
|
5831
5926
|
} else if (scope.model === mappedTableName) {
|
|
5832
5927
|
mappedTableName = this.mapTableName(scope.model);
|
|
5833
5928
|
}
|
|
@@ -5908,7 +6003,7 @@ var QueryNameMapper = class extends import_kysely13.OperationNodeTransformer {
|
|
|
5908
6003
|
const origFieldName = this.extractFieldName(selection.selection);
|
|
5909
6004
|
const fieldName = this.extractFieldName(transformed);
|
|
5910
6005
|
if (fieldName !== origFieldName) {
|
|
5911
|
-
selections.push(import_kysely13.SelectionNode.create(this.wrapAlias(transformed, origFieldName)));
|
|
6006
|
+
selections.push(import_kysely13.SelectionNode.create(this.wrapAlias(transformed, origFieldName ? import_kysely13.IdentifierNode.create(origFieldName) : void 0)));
|
|
5912
6007
|
} else {
|
|
5913
6008
|
selections.push(import_kysely13.SelectionNode.create(transformed));
|
|
5914
6009
|
}
|
|
@@ -5924,7 +6019,7 @@ var QueryNameMapper = class extends import_kysely13.OperationNodeTransformer {
|
|
|
5924
6019
|
const scope = this.scopes[i];
|
|
5925
6020
|
if (qualifier) {
|
|
5926
6021
|
if (scope.alias) {
|
|
5927
|
-
if (scope.alias === qualifier) {
|
|
6022
|
+
if (scope.alias && import_kysely13.IdentifierNode.is(scope.alias) && scope.alias.name === qualifier) {
|
|
5928
6023
|
return scope;
|
|
5929
6024
|
} else {
|
|
5930
6025
|
continue;
|
|
@@ -5970,7 +6065,7 @@ var QueryNameMapper = class extends import_kysely13.OperationNodeTransformer {
|
|
|
5970
6065
|
}
|
|
5971
6066
|
}
|
|
5972
6067
|
wrapAlias(node, alias) {
|
|
5973
|
-
return alias ? import_kysely13.AliasNode.create(node,
|
|
6068
|
+
return alias ? import_kysely13.AliasNode.create(node, alias) : node;
|
|
5974
6069
|
}
|
|
5975
6070
|
processTableRef(node) {
|
|
5976
6071
|
if (!node) {
|
|
@@ -6018,11 +6113,11 @@ var QueryNameMapper = class extends import_kysely13.OperationNodeTransformer {
|
|
|
6018
6113
|
if (innerNode && import_kysely13.TableNode.is(innerNode)) {
|
|
6019
6114
|
const modelName = innerNode.table.identifier.name;
|
|
6020
6115
|
const mappedName = this.mapTableName(modelName);
|
|
6021
|
-
const finalAlias = alias ?? (mappedName !== modelName ? modelName : void 0);
|
|
6116
|
+
const finalAlias = alias ?? (mappedName !== modelName ? import_kysely13.IdentifierNode.create(modelName) : void 0);
|
|
6022
6117
|
return {
|
|
6023
6118
|
node: this.wrapAlias(import_kysely13.TableNode.create(mappedName), finalAlias),
|
|
6024
6119
|
scope: {
|
|
6025
|
-
alias: alias ?? modelName,
|
|
6120
|
+
alias: alias ?? import_kysely13.IdentifierNode.create(modelName),
|
|
6026
6121
|
model: modelName,
|
|
6027
6122
|
namesMapped: !this.hasMappedColumns(modelName)
|
|
6028
6123
|
}
|
|
@@ -6042,7 +6137,7 @@ var QueryNameMapper = class extends import_kysely13.OperationNodeTransformer {
|
|
|
6042
6137
|
const modelDef = requireModel(this.schema, model);
|
|
6043
6138
|
return this.getModelFields(modelDef).map((fieldDef) => {
|
|
6044
6139
|
const columnName = this.mapFieldName(model, fieldDef.name);
|
|
6045
|
-
const columnRef = import_kysely13.ReferenceNode.create(import_kysely13.ColumnNode.create(columnName), alias ? import_kysely13.TableNode.create(alias) : void 0);
|
|
6140
|
+
const columnRef = import_kysely13.ReferenceNode.create(import_kysely13.ColumnNode.create(columnName), alias && import_kysely13.IdentifierNode.is(alias) ? import_kysely13.TableNode.create(alias.name) : void 0);
|
|
6046
6141
|
if (columnName !== fieldDef.name) {
|
|
6047
6142
|
const aliased = import_kysely13.AliasNode.create(columnRef, import_kysely13.IdentifierNode.create(fieldDef.name));
|
|
6048
6143
|
return import_kysely13.SelectionNode.create(aliased);
|
|
@@ -6076,11 +6171,11 @@ var QueryNameMapper = class extends import_kysely13.OperationNodeTransformer {
|
|
|
6076
6171
|
alias = this.extractFieldName(node);
|
|
6077
6172
|
}
|
|
6078
6173
|
const result = super.transformNode(node);
|
|
6079
|
-
return this.wrapAlias(result, alias);
|
|
6174
|
+
return this.wrapAlias(result, alias ? import_kysely13.IdentifierNode.create(alias) : void 0);
|
|
6080
6175
|
}
|
|
6081
6176
|
processSelectAll(node) {
|
|
6082
6177
|
const scope = this.scopes[this.scopes.length - 1];
|
|
6083
|
-
(0,
|
|
6178
|
+
(0, import_common_helpers10.invariant)(scope);
|
|
6084
6179
|
if (!scope.model || !this.hasMappedColumns(scope.model)) {
|
|
6085
6180
|
return super.transformSelectAll(node);
|
|
6086
6181
|
}
|
|
@@ -6088,7 +6183,7 @@ var QueryNameMapper = class extends import_kysely13.OperationNodeTransformer {
|
|
|
6088
6183
|
return this.getModelFields(modelDef).map((fieldDef) => {
|
|
6089
6184
|
const columnName = this.mapFieldName(modelDef.name, fieldDef.name);
|
|
6090
6185
|
const columnRef = import_kysely13.ReferenceNode.create(import_kysely13.ColumnNode.create(columnName));
|
|
6091
|
-
return columnName !== fieldDef.name ? this.wrapAlias(columnRef, fieldDef.name) : columnRef;
|
|
6186
|
+
return columnName !== fieldDef.name ? this.wrapAlias(columnRef, import_kysely13.IdentifierNode.create(fieldDef.name)) : columnRef;
|
|
6092
6187
|
});
|
|
6093
6188
|
}
|
|
6094
6189
|
extractModelName(node) {
|
|
@@ -6150,7 +6245,6 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends import_kysely14
|
|
|
6150
6245
|
const hookResult = await hook({
|
|
6151
6246
|
client: this.client,
|
|
6152
6247
|
schema: this.client.$schema,
|
|
6153
|
-
kysely: this.kysely,
|
|
6154
6248
|
query,
|
|
6155
6249
|
proceed: _p
|
|
6156
6250
|
});
|
|
@@ -6309,17 +6403,17 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends import_kysely14
|
|
|
6309
6403
|
}
|
|
6310
6404
|
getMutationModel(queryNode) {
|
|
6311
6405
|
return (0, import_ts_pattern16.match)(queryNode).when(import_kysely14.InsertQueryNode.is, (node) => {
|
|
6312
|
-
(0,
|
|
6406
|
+
(0, import_common_helpers11.invariant)(node.into, "InsertQueryNode must have an into clause");
|
|
6313
6407
|
return node.into.table.identifier.name;
|
|
6314
6408
|
}).when(import_kysely14.UpdateQueryNode.is, (node) => {
|
|
6315
|
-
(0,
|
|
6409
|
+
(0, import_common_helpers11.invariant)(node.table, "UpdateQueryNode must have a table");
|
|
6316
6410
|
const { node: tableNode } = stripAlias(node.table);
|
|
6317
|
-
(0,
|
|
6411
|
+
(0, import_common_helpers11.invariant)(import_kysely14.TableNode.is(tableNode), "UpdateQueryNode must use a TableNode");
|
|
6318
6412
|
return tableNode.table.identifier.name;
|
|
6319
6413
|
}).when(import_kysely14.DeleteQueryNode.is, (node) => {
|
|
6320
|
-
(0,
|
|
6414
|
+
(0, import_common_helpers11.invariant)(node.from.froms.length === 1, "Delete query must have exactly one from table");
|
|
6321
6415
|
const { node: tableNode } = stripAlias(node.from.froms[0]);
|
|
6322
|
-
(0,
|
|
6416
|
+
(0, import_common_helpers11.invariant)(import_kysely14.TableNode.is(tableNode), "DeleteQueryNode must use a TableNode");
|
|
6323
6417
|
return tableNode.table.identifier.name;
|
|
6324
6418
|
}).otherwise((node) => {
|
|
6325
6419
|
throw new InternalError(`Invalid query node: ${node}`);
|
|
@@ -6417,7 +6511,7 @@ __export(functions_exports, {
|
|
|
6417
6511
|
search: () => search,
|
|
6418
6512
|
startsWith: () => startsWith
|
|
6419
6513
|
});
|
|
6420
|
-
var
|
|
6514
|
+
var import_common_helpers12 = require("@zenstackhq/common-helpers");
|
|
6421
6515
|
var import_kysely15 = require("kysely");
|
|
6422
6516
|
var import_ts_pattern17 = require("ts-pattern");
|
|
6423
6517
|
var contains = /* @__PURE__ */ __name((eb, args) => {
|
|
@@ -6524,8 +6618,8 @@ var currentOperation = /* @__PURE__ */ __name((_eb, args, { operation }) => {
|
|
|
6524
6618
|
}, "currentOperation");
|
|
6525
6619
|
function processCasing(casing, result, model) {
|
|
6526
6620
|
const opNode = casing.toOperationNode();
|
|
6527
|
-
(0,
|
|
6528
|
-
result = (0, import_ts_pattern17.match)(opNode.value).with("original", () => model).with("upper", () => result.toUpperCase()).with("lower", () => result.toLowerCase()).with("capitalize", () => (0,
|
|
6621
|
+
(0, import_common_helpers12.invariant)(import_kysely15.ValueNode.is(opNode) && typeof opNode.value === "string", '"casting" parameter must be a string value');
|
|
6622
|
+
result = (0, import_ts_pattern17.match)(opNode.value).with("original", () => model).with("upper", () => result.toUpperCase()).with("lower", () => result.toLowerCase()).with("capitalize", () => (0, import_common_helpers12.upperCaseFirst)(result)).with("uncapitalize", () => (0, import_common_helpers12.lowerCaseFirst)(result)).otherwise(() => {
|
|
6529
6623
|
throw new Error(`Invalid casing value: ${opNode.value}. Must be "original", "upper", "lower", "capitalize", or "uncapitalize".`);
|
|
6530
6624
|
});
|
|
6531
6625
|
return result;
|
|
@@ -6533,7 +6627,7 @@ function processCasing(casing, result, model) {
|
|
|
6533
6627
|
__name(processCasing, "processCasing");
|
|
6534
6628
|
|
|
6535
6629
|
// src/client/helpers/schema-db-pusher.ts
|
|
6536
|
-
var
|
|
6630
|
+
var import_common_helpers13 = require("@zenstackhq/common-helpers");
|
|
6537
6631
|
var import_kysely16 = require("kysely");
|
|
6538
6632
|
var import_toposort = __toESM(require("toposort"), 1);
|
|
6539
6633
|
var import_ts_pattern18 = require("ts-pattern");
|
|
@@ -6649,7 +6743,7 @@ var SchemaDbPusher = class {
|
|
|
6649
6743
|
}
|
|
6650
6744
|
addUniqueConstraint(table, modelDef) {
|
|
6651
6745
|
for (const [key, value] of Object.entries(modelDef.uniqueFields)) {
|
|
6652
|
-
(0,
|
|
6746
|
+
(0, import_common_helpers13.invariant)(typeof value === "object", "expecting an object");
|
|
6653
6747
|
if ("type" in value) {
|
|
6654
6748
|
const fieldDef = modelDef.fields[key];
|
|
6655
6749
|
if (fieldDef.unique) {
|
|
@@ -6717,7 +6811,7 @@ var SchemaDbPusher = class {
|
|
|
6717
6811
|
return fieldDef.default && ExpressionUtils.isCall(fieldDef.default) && fieldDef.default.function === "autoincrement";
|
|
6718
6812
|
}
|
|
6719
6813
|
addForeignKeyConstraint(table, model, fieldName, fieldDef) {
|
|
6720
|
-
(0,
|
|
6814
|
+
(0, import_common_helpers13.invariant)(fieldDef.relation, "field must be a relation");
|
|
6721
6815
|
if (!fieldDef.relation.fields || !fieldDef.relation.references) {
|
|
6722
6816
|
return table;
|
|
6723
6817
|
}
|
|
@@ -6774,7 +6868,7 @@ function valueToPromise(thing) {
|
|
|
6774
6868
|
__name(valueToPromise, "valueToPromise");
|
|
6775
6869
|
|
|
6776
6870
|
// src/client/result-processor.ts
|
|
6777
|
-
var
|
|
6871
|
+
var import_common_helpers14 = require("@zenstackhq/common-helpers");
|
|
6778
6872
|
var import_decimal2 = __toESM(require("decimal.js"), 1);
|
|
6779
6873
|
var import_ts_pattern19 = require("ts-pattern");
|
|
6780
6874
|
var ResultProcessor = class {
|
|
@@ -6874,14 +6968,14 @@ var ResultProcessor = class {
|
|
|
6874
6968
|
if (value instanceof import_decimal2.default) {
|
|
6875
6969
|
return value;
|
|
6876
6970
|
}
|
|
6877
|
-
(0,
|
|
6971
|
+
(0, import_common_helpers14.invariant)(typeof value === "string" || typeof value === "number" || value instanceof import_decimal2.default, `Expected string, number or Decimal, got ${typeof value}`);
|
|
6878
6972
|
return new import_decimal2.default(value);
|
|
6879
6973
|
}
|
|
6880
6974
|
transformBigInt(value) {
|
|
6881
6975
|
if (typeof value === "bigint") {
|
|
6882
6976
|
return value;
|
|
6883
6977
|
}
|
|
6884
|
-
(0,
|
|
6978
|
+
(0, import_common_helpers14.invariant)(typeof value === "string" || typeof value === "number", `Expected string or number, got ${typeof value}`);
|
|
6885
6979
|
return BigInt(value);
|
|
6886
6980
|
}
|
|
6887
6981
|
transformBoolean(value) {
|
|
@@ -6925,7 +7019,7 @@ var ResultProcessor = class {
|
|
|
6925
7019
|
}
|
|
6926
7020
|
transformJson(value) {
|
|
6927
7021
|
return (0, import_ts_pattern19.match)(this.schema.provider.type).with("sqlite", () => {
|
|
6928
|
-
(0,
|
|
7022
|
+
(0, import_common_helpers14.invariant)(typeof value === "string", "Expected string, got " + typeof value);
|
|
6929
7023
|
return JSON.parse(value);
|
|
6930
7024
|
}).otherwise(() => value);
|
|
6931
7025
|
}
|
|
@@ -7002,7 +7096,7 @@ var ClientImpl = class _ClientImpl {
|
|
|
7002
7096
|
}
|
|
7003
7097
|
// implementation
|
|
7004
7098
|
async $transaction(input, options) {
|
|
7005
|
-
(0,
|
|
7099
|
+
(0, import_common_helpers15.invariant)(typeof input === "function" || Array.isArray(input) && input.every((p) => p.then && p.cb), "Invalid transaction input, expected a function or an array of ZenStackPromise");
|
|
7006
7100
|
if (typeof input === "function") {
|
|
7007
7101
|
return this.interactiveTransaction(input, options);
|
|
7008
7102
|
} else {
|