@zenstackhq/orm 3.0.0-beta.19 → 3.0.0-beta.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +479 -194
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +172 -140
- package/dist/index.d.ts +172 -140
- package/dist/index.js +483 -194
- package/dist/index.js.map +1 -1
- package/package.json +7 -7
package/dist/index.js
CHANGED
|
@@ -80,63 +80,110 @@ function fieldsToSelectObject(fields) {
|
|
|
80
80
|
}
|
|
81
81
|
__name(fieldsToSelectObject, "fieldsToSelectObject");
|
|
82
82
|
|
|
83
|
-
// src/client/
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
var InputValidationError = class extends ZenStackError {
|
|
90
|
-
static {
|
|
91
|
-
__name(this, "InputValidationError");
|
|
92
|
-
}
|
|
93
|
-
model;
|
|
94
|
-
constructor(model, message, cause) {
|
|
95
|
-
super(message, {
|
|
96
|
-
cause
|
|
97
|
-
}), this.model = model;
|
|
98
|
-
}
|
|
99
|
-
};
|
|
100
|
-
var QueryError = class extends ZenStackError {
|
|
101
|
-
static {
|
|
102
|
-
__name(this, "QueryError");
|
|
103
|
-
}
|
|
104
|
-
constructor(message, cause) {
|
|
105
|
-
super(message, {
|
|
106
|
-
cause
|
|
107
|
-
});
|
|
108
|
-
}
|
|
109
|
-
};
|
|
110
|
-
var InternalError = class extends ZenStackError {
|
|
111
|
-
static {
|
|
112
|
-
__name(this, "InternalError");
|
|
113
|
-
}
|
|
114
|
-
};
|
|
115
|
-
var NotFoundError = class extends ZenStackError {
|
|
116
|
-
static {
|
|
117
|
-
__name(this, "NotFoundError");
|
|
118
|
-
}
|
|
119
|
-
model;
|
|
120
|
-
constructor(model, details) {
|
|
121
|
-
super(`Entity not found for model "${model}"${details ? `: ${details}` : ""}`), this.model = model;
|
|
83
|
+
// src/client/executor/error-processor.ts
|
|
84
|
+
function getDbErrorCode(error) {
|
|
85
|
+
if (error instanceof Error && "code" in error) {
|
|
86
|
+
return error.code;
|
|
87
|
+
} else {
|
|
88
|
+
return void 0;
|
|
122
89
|
}
|
|
123
|
-
}
|
|
90
|
+
}
|
|
91
|
+
__name(getDbErrorCode, "getDbErrorCode");
|
|
92
|
+
|
|
93
|
+
// src/client/errors.ts
|
|
94
|
+
var ORMErrorReason = /* @__PURE__ */ function(ORMErrorReason2) {
|
|
95
|
+
ORMErrorReason2["CONFIG_ERROR"] = "config-error";
|
|
96
|
+
ORMErrorReason2["INVALID_INPUT"] = "invalid-input";
|
|
97
|
+
ORMErrorReason2["NOT_FOUND"] = "not-found";
|
|
98
|
+
ORMErrorReason2["REJECTED_BY_POLICY"] = "rejected-by-policy";
|
|
99
|
+
ORMErrorReason2["DB_QUERY_ERROR"] = "db-query-error";
|
|
100
|
+
ORMErrorReason2["NOT_SUPPORTED"] = "not-supported";
|
|
101
|
+
ORMErrorReason2["INTERNAL_ERROR"] = "internal-error";
|
|
102
|
+
return ORMErrorReason2;
|
|
103
|
+
}({});
|
|
124
104
|
var RejectedByPolicyReason = /* @__PURE__ */ function(RejectedByPolicyReason2) {
|
|
125
105
|
RejectedByPolicyReason2["NO_ACCESS"] = "no-access";
|
|
126
106
|
RejectedByPolicyReason2["CANNOT_READ_BACK"] = "cannot-read-back";
|
|
127
107
|
RejectedByPolicyReason2["OTHER"] = "other";
|
|
128
108
|
return RejectedByPolicyReason2;
|
|
129
109
|
}({});
|
|
130
|
-
var
|
|
110
|
+
var ORMError = class extends Error {
|
|
131
111
|
static {
|
|
132
|
-
__name(this, "
|
|
112
|
+
__name(this, "ORMError");
|
|
133
113
|
}
|
|
134
|
-
model;
|
|
135
114
|
reason;
|
|
136
|
-
constructor(
|
|
137
|
-
super(message
|
|
115
|
+
constructor(reason, message, options) {
|
|
116
|
+
super(message, options), this.reason = reason;
|
|
138
117
|
}
|
|
118
|
+
/**
|
|
119
|
+
* The name of the model that the error pertains to.
|
|
120
|
+
*/
|
|
121
|
+
model;
|
|
122
|
+
/**
|
|
123
|
+
* The error code given by the underlying database driver.
|
|
124
|
+
*/
|
|
125
|
+
dbErrorCode;
|
|
126
|
+
/**
|
|
127
|
+
* The error message given by the underlying database driver.
|
|
128
|
+
*/
|
|
129
|
+
dbErrorMessage;
|
|
130
|
+
/**
|
|
131
|
+
* The reason code for policy rejection. Only available when `reason` is `REJECTED_BY_POLICY`.
|
|
132
|
+
*/
|
|
133
|
+
rejectedByPolicyReason;
|
|
134
|
+
/**
|
|
135
|
+
* The SQL query that was executed. Only available when `reason` is `DB_QUERY_ERROR`.
|
|
136
|
+
*/
|
|
137
|
+
sql;
|
|
138
|
+
/**
|
|
139
|
+
* The parameters used in the SQL query. Only available when `reason` is `DB_QUERY_ERROR`.
|
|
140
|
+
*/
|
|
141
|
+
sqlParams;
|
|
139
142
|
};
|
|
143
|
+
function createConfigError(message, options) {
|
|
144
|
+
return new ORMError("config-error", message, options);
|
|
145
|
+
}
|
|
146
|
+
__name(createConfigError, "createConfigError");
|
|
147
|
+
function createNotFoundError(model, message, options) {
|
|
148
|
+
const error = new ORMError("not-found", message ?? "Record not found", options);
|
|
149
|
+
error.model = model;
|
|
150
|
+
return error;
|
|
151
|
+
}
|
|
152
|
+
__name(createNotFoundError, "createNotFoundError");
|
|
153
|
+
function createInvalidInputError(message, model, options) {
|
|
154
|
+
const error = new ORMError("invalid-input", message, options);
|
|
155
|
+
error.model = model;
|
|
156
|
+
return error;
|
|
157
|
+
}
|
|
158
|
+
__name(createInvalidInputError, "createInvalidInputError");
|
|
159
|
+
function createDBQueryError(message, dbError, sql8, parameters) {
|
|
160
|
+
const error = new ORMError("db-query-error", message, {
|
|
161
|
+
cause: dbError
|
|
162
|
+
});
|
|
163
|
+
error.dbErrorCode = getDbErrorCode(dbError);
|
|
164
|
+
error.dbErrorMessage = dbError instanceof Error ? dbError.message : void 0;
|
|
165
|
+
error.sql = sql8;
|
|
166
|
+
error.sqlParams = parameters;
|
|
167
|
+
return error;
|
|
168
|
+
}
|
|
169
|
+
__name(createDBQueryError, "createDBQueryError");
|
|
170
|
+
function createRejectedByPolicyError(model, reason, message, options) {
|
|
171
|
+
const error = new ORMError("rejected-by-policy", message, options);
|
|
172
|
+
error.model = model;
|
|
173
|
+
error.rejectedByPolicyReason = reason;
|
|
174
|
+
return error;
|
|
175
|
+
}
|
|
176
|
+
__name(createRejectedByPolicyError, "createRejectedByPolicyError");
|
|
177
|
+
function createNotSupportedError(message, options) {
|
|
178
|
+
return new ORMError("not-supported", message, options);
|
|
179
|
+
}
|
|
180
|
+
__name(createNotSupportedError, "createNotSupportedError");
|
|
181
|
+
function createInternalError(message, model, options) {
|
|
182
|
+
const error = new ORMError("internal-error", message, options);
|
|
183
|
+
error.model = model;
|
|
184
|
+
return error;
|
|
185
|
+
}
|
|
186
|
+
__name(createInternalError, "createInternalError");
|
|
140
187
|
|
|
141
188
|
// src/client/query-utils.ts
|
|
142
189
|
function hasModel(schema, model) {
|
|
@@ -154,7 +201,7 @@ __name(getTypeDef, "getTypeDef");
|
|
|
154
201
|
function requireModel(schema, model) {
|
|
155
202
|
const modelDef = getModel(schema, model);
|
|
156
203
|
if (!modelDef) {
|
|
157
|
-
throw
|
|
204
|
+
throw createInternalError(`Model "${model}" not found in schema`, model);
|
|
158
205
|
}
|
|
159
206
|
return modelDef;
|
|
160
207
|
}
|
|
@@ -168,7 +215,7 @@ function requireField(schema, modelOrType, field) {
|
|
|
168
215
|
const modelDef = getModel(schema, modelOrType);
|
|
169
216
|
if (modelDef) {
|
|
170
217
|
if (!modelDef.fields[field]) {
|
|
171
|
-
throw
|
|
218
|
+
throw createInternalError(`Field "${field}" not found in model "${modelOrType}"`, modelOrType);
|
|
172
219
|
} else {
|
|
173
220
|
return modelDef.fields[field];
|
|
174
221
|
}
|
|
@@ -176,12 +223,12 @@ function requireField(schema, modelOrType, field) {
|
|
|
176
223
|
const typeDef = getTypeDef(schema, modelOrType);
|
|
177
224
|
if (typeDef) {
|
|
178
225
|
if (!typeDef.fields[field]) {
|
|
179
|
-
throw
|
|
226
|
+
throw createInternalError(`Field "${field}" not found in type "${modelOrType}"`, modelOrType);
|
|
180
227
|
} else {
|
|
181
228
|
return typeDef.fields[field];
|
|
182
229
|
}
|
|
183
230
|
}
|
|
184
|
-
throw
|
|
231
|
+
throw createInternalError(`Model or type "${modelOrType}" not found in schema`, modelOrType);
|
|
185
232
|
}
|
|
186
233
|
__name(requireField, "requireField");
|
|
187
234
|
function getIdFields(schema, model) {
|
|
@@ -193,7 +240,7 @@ function requireIdFields(schema, model) {
|
|
|
193
240
|
const modelDef = requireModel(schema, model);
|
|
194
241
|
const result = modelDef?.idFields;
|
|
195
242
|
if (!result) {
|
|
196
|
-
throw
|
|
243
|
+
throw createInternalError(`Model "${model}" does not have ID field(s)`, model);
|
|
197
244
|
}
|
|
198
245
|
return result;
|
|
199
246
|
}
|
|
@@ -201,11 +248,11 @@ __name(requireIdFields, "requireIdFields");
|
|
|
201
248
|
function getRelationForeignKeyFieldPairs(schema, model, relationField) {
|
|
202
249
|
const fieldDef = requireField(schema, model, relationField);
|
|
203
250
|
if (!fieldDef?.relation) {
|
|
204
|
-
throw
|
|
251
|
+
throw createInternalError(`Field "${relationField}" is not a relation`, model);
|
|
205
252
|
}
|
|
206
253
|
if (fieldDef.relation.fields) {
|
|
207
254
|
if (!fieldDef.relation.references) {
|
|
208
|
-
throw
|
|
255
|
+
throw createInternalError(`Relation references not defined for field "${relationField}"`, model);
|
|
209
256
|
}
|
|
210
257
|
return {
|
|
211
258
|
keyPairs: fieldDef.relation.fields.map((f, i) => ({
|
|
@@ -216,17 +263,17 @@ function getRelationForeignKeyFieldPairs(schema, model, relationField) {
|
|
|
216
263
|
};
|
|
217
264
|
} else {
|
|
218
265
|
if (!fieldDef.relation.opposite) {
|
|
219
|
-
throw
|
|
266
|
+
throw createInternalError(`Opposite relation not defined for field "${relationField}"`, model);
|
|
220
267
|
}
|
|
221
268
|
const oppositeField = requireField(schema, fieldDef.type, fieldDef.relation.opposite);
|
|
222
269
|
if (!oppositeField.relation) {
|
|
223
|
-
throw
|
|
270
|
+
throw createInternalError(`Field "${fieldDef.relation.opposite}" is not a relation`, model);
|
|
224
271
|
}
|
|
225
272
|
if (!oppositeField.relation.fields) {
|
|
226
|
-
throw
|
|
273
|
+
throw createInternalError(`Relation fields not defined for field "${relationField}"`, model);
|
|
227
274
|
}
|
|
228
275
|
if (!oppositeField.relation.references) {
|
|
229
|
-
throw
|
|
276
|
+
throw createInternalError(`Relation references not defined for field "${relationField}"`, model);
|
|
230
277
|
}
|
|
231
278
|
return {
|
|
232
279
|
keyPairs: oppositeField.relation.fields.map((f, i) => ({
|
|
@@ -263,7 +310,7 @@ function getUniqueFields(schema, model) {
|
|
|
263
310
|
const result = [];
|
|
264
311
|
for (const [key, value] of Object.entries(modelDef.uniqueFields)) {
|
|
265
312
|
if (typeof value !== "object") {
|
|
266
|
-
throw
|
|
313
|
+
throw createInternalError(`Invalid unique field definition for "${key}"`, model);
|
|
267
314
|
}
|
|
268
315
|
if (typeof value.type === "string") {
|
|
269
316
|
result.push({
|
|
@@ -286,7 +333,7 @@ __name(getUniqueFields, "getUniqueFields");
|
|
|
286
333
|
function getIdValues(schema, model, data) {
|
|
287
334
|
const idFields = getIdFields(schema, model);
|
|
288
335
|
if (!idFields) {
|
|
289
|
-
throw
|
|
336
|
+
throw createInternalError(`ID fields not defined for model "${model}"`, model);
|
|
290
337
|
}
|
|
291
338
|
return idFields.reduce((acc, field) => ({
|
|
292
339
|
...acc,
|
|
@@ -445,7 +492,7 @@ function getDiscriminatorField(schema, model) {
|
|
|
445
492
|
}
|
|
446
493
|
const discriminator = delegateAttr.args?.find((arg) => arg.name === "discriminator");
|
|
447
494
|
if (!discriminator || !schema_exports.ExpressionUtils.isField(discriminator.value)) {
|
|
448
|
-
throw
|
|
495
|
+
throw createInternalError(`Discriminator field not defined for model "${model}"`, model);
|
|
449
496
|
}
|
|
450
497
|
return discriminator.value.field;
|
|
451
498
|
}
|
|
@@ -500,7 +547,7 @@ __name(extractFieldName, "extractFieldName");
|
|
|
500
547
|
// src/client/crud/operations/base.ts
|
|
501
548
|
import { createId } from "@paralleldrive/cuid2";
|
|
502
549
|
import { clone, enumerate as enumerate2, invariant as invariant5, isPlainObject as isPlainObject2 } from "@zenstackhq/common-helpers";
|
|
503
|
-
import { expressionBuilder as expressionBuilder2, sql as sql4 } from "kysely";
|
|
550
|
+
import { createQueryId, expressionBuilder as expressionBuilder2, sql as sql4 } from "kysely";
|
|
504
551
|
import { nanoid } from "nanoid";
|
|
505
552
|
import { match as match6 } from "ts-pattern";
|
|
506
553
|
import { ulid } from "ulid";
|
|
@@ -607,7 +654,7 @@ var BaseCrudDialect = class {
|
|
|
607
654
|
if (this.supportsDistinctOn) {
|
|
608
655
|
result = result.distinctOn(distinct.map((f) => this.eb.ref(`${modelAlias}.${f}`)));
|
|
609
656
|
} else {
|
|
610
|
-
throw
|
|
657
|
+
throw createNotSupportedError(`"distinct" is not supported by "${this.schema.provider.type}" provider`);
|
|
611
658
|
}
|
|
612
659
|
}
|
|
613
660
|
if (args.cursor) {
|
|
@@ -814,7 +861,7 @@ var BaseCrudDialect = class {
|
|
|
814
861
|
break;
|
|
815
862
|
}
|
|
816
863
|
default: {
|
|
817
|
-
throw
|
|
864
|
+
throw createInvalidInputError(`Invalid array filter key: ${key}`);
|
|
818
865
|
}
|
|
819
866
|
}
|
|
820
867
|
}
|
|
@@ -828,9 +875,9 @@ var BaseCrudDialect = class {
|
|
|
828
875
|
return this.buildEnumFilter(fieldRef, fieldDef, payload);
|
|
829
876
|
}
|
|
830
877
|
return match2(fieldDef.type).with("String", () => this.buildStringFilter(fieldRef, payload)).with(P.union("Int", "Float", "Decimal", "BigInt"), (type) => this.buildNumberFilter(fieldRef, type, payload)).with("Boolean", () => this.buildBooleanFilter(fieldRef, payload)).with("DateTime", () => this.buildDateTimeFilter(fieldRef, payload)).with("Bytes", () => this.buildBytesFilter(fieldRef, payload)).with("Json", () => {
|
|
831
|
-
throw
|
|
878
|
+
throw createNotSupportedError("JSON filters are not supported yet");
|
|
832
879
|
}).with("Unsupported", () => {
|
|
833
|
-
throw
|
|
880
|
+
throw createInvalidInputError(`Unsupported field cannot be used in filters`);
|
|
834
881
|
}).exhaustive();
|
|
835
882
|
}
|
|
836
883
|
buildLiteralFilter(lhs, type, rhs) {
|
|
@@ -875,7 +922,7 @@ var BaseCrudDialect = class {
|
|
|
875
922
|
return this.and(...innerResult.conditions);
|
|
876
923
|
}).otherwise(() => {
|
|
877
924
|
if (throwIfInvalid) {
|
|
878
|
-
throw
|
|
925
|
+
throw createInvalidInputError(`Invalid filter key: ${op}`);
|
|
879
926
|
} else {
|
|
880
927
|
return void 0;
|
|
881
928
|
}
|
|
@@ -904,7 +951,7 @@ var BaseCrudDialect = class {
|
|
|
904
951
|
continue;
|
|
905
952
|
}
|
|
906
953
|
const condition = match2(key).with("contains", () => mode === "insensitive" ? this.eb(fieldRef, "ilike", sql.val(`%${value}%`)) : this.eb(fieldRef, "like", sql.val(`%${value}%`))).with("startsWith", () => mode === "insensitive" ? this.eb(fieldRef, "ilike", sql.val(`${value}%`)) : this.eb(fieldRef, "like", sql.val(`${value}%`))).with("endsWith", () => mode === "insensitive" ? this.eb(fieldRef, "ilike", sql.val(`%${value}`)) : this.eb(fieldRef, "like", sql.val(`%${value}`))).otherwise(() => {
|
|
907
|
-
throw
|
|
954
|
+
throw createInvalidInputError(`Invalid string filter key: ${key}`);
|
|
908
955
|
});
|
|
909
956
|
if (condition) {
|
|
910
957
|
conditions.push(condition);
|
|
@@ -984,7 +1031,7 @@ var BaseCrudDialect = class {
|
|
|
984
1031
|
invariant2(value && typeof value === "object", `invalid orderBy value for field "${field}"`);
|
|
985
1032
|
for (const [k, v] of Object.entries(value)) {
|
|
986
1033
|
invariant2(v === "asc" || v === "desc", `invalid orderBy value for field "${field}"`);
|
|
987
|
-
result = result.orderBy((eb) => aggregate(eb, buildFieldRef(model, k, modelAlias), field),
|
|
1034
|
+
result = result.orderBy((eb) => aggregate(eb, buildFieldRef(model, k, modelAlias), field), this.negateSort(v, negated));
|
|
988
1035
|
}
|
|
989
1036
|
continue;
|
|
990
1037
|
}
|
|
@@ -993,7 +1040,7 @@ var BaseCrudDialect = class {
|
|
|
993
1040
|
invariant2(value && typeof value === "object", 'invalid orderBy value for field "_count"');
|
|
994
1041
|
for (const [k, v] of Object.entries(value)) {
|
|
995
1042
|
invariant2(v === "asc" || v === "desc", `invalid orderBy value for field "${field}"`);
|
|
996
|
-
result = result.orderBy((eb) => eb.fn.count(buildFieldRef(model, k, modelAlias)),
|
|
1043
|
+
result = result.orderBy((eb) => eb.fn.count(buildFieldRef(model, k, modelAlias)), this.negateSort(v, negated));
|
|
997
1044
|
}
|
|
998
1045
|
continue;
|
|
999
1046
|
}
|
|
@@ -1006,13 +1053,18 @@ var BaseCrudDialect = class {
|
|
|
1006
1053
|
if (value === "asc" || value === "desc") {
|
|
1007
1054
|
result = result.orderBy(fieldRef, this.negateSort(value, negated));
|
|
1008
1055
|
} else if (value && typeof value === "object" && "nulls" in value && "sort" in value && (value.sort === "asc" || value.sort === "desc") && (value.nulls === "first" || value.nulls === "last")) {
|
|
1009
|
-
result = result.orderBy(fieldRef,
|
|
1056
|
+
result = result.orderBy(fieldRef, (ob) => {
|
|
1057
|
+
const dir = this.negateSort(value.sort, negated);
|
|
1058
|
+
ob = dir === "asc" ? ob.asc() : ob.desc();
|
|
1059
|
+
ob = value.nulls === "first" ? ob.nullsFirst() : ob.nullsLast();
|
|
1060
|
+
return ob;
|
|
1061
|
+
});
|
|
1010
1062
|
}
|
|
1011
1063
|
} else {
|
|
1012
1064
|
const relationModel = fieldDef.type;
|
|
1013
1065
|
if (fieldDef.array) {
|
|
1014
1066
|
if (typeof value !== "object") {
|
|
1015
|
-
throw
|
|
1067
|
+
throw createInvalidInputError(`invalid orderBy value for field "${field}"`);
|
|
1016
1068
|
}
|
|
1017
1069
|
if ("_count" in value) {
|
|
1018
1070
|
invariant2(value._count === "asc" || value._count === "desc", 'invalid orderBy value for field "_count"');
|
|
@@ -1183,7 +1235,7 @@ var BaseCrudDialect = class {
|
|
|
1183
1235
|
computer = computedFields?.[fieldDef.originModel ?? model]?.[field];
|
|
1184
1236
|
}
|
|
1185
1237
|
if (!computer) {
|
|
1186
|
-
throw
|
|
1238
|
+
throw createConfigError(`Computed field "${field}" implementation not provided for model "${model}"`);
|
|
1187
1239
|
}
|
|
1188
1240
|
return computer(this.eb, {
|
|
1189
1241
|
modelAlias
|
|
@@ -1414,7 +1466,7 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
|
|
|
1414
1466
|
}
|
|
1415
1467
|
getFieldSqlType(fieldDef) {
|
|
1416
1468
|
if (fieldDef.relation) {
|
|
1417
|
-
throw
|
|
1469
|
+
throw createInternalError("Cannot get SQL type of a relation field");
|
|
1418
1470
|
}
|
|
1419
1471
|
let result;
|
|
1420
1472
|
if (this.schema.enums?.[fieldDef.type]) {
|
|
@@ -1504,7 +1556,9 @@ var SqliteCrudDialect = class extends BaseCrudDialect {
|
|
|
1504
1556
|
try {
|
|
1505
1557
|
return JSON.parse(value);
|
|
1506
1558
|
} catch (e) {
|
|
1507
|
-
throw
|
|
1559
|
+
throw createInternalError("Invalid JSON returned", void 0, {
|
|
1560
|
+
cause: e
|
|
1561
|
+
});
|
|
1508
1562
|
}
|
|
1509
1563
|
}
|
|
1510
1564
|
return value;
|
|
@@ -1647,10 +1701,10 @@ var SqliteCrudDialect = class extends BaseCrudDialect {
|
|
|
1647
1701
|
}
|
|
1648
1702
|
getFieldSqlType(fieldDef) {
|
|
1649
1703
|
if (fieldDef.relation) {
|
|
1650
|
-
throw
|
|
1704
|
+
throw createInternalError("Cannot get SQL type of a relation field");
|
|
1651
1705
|
}
|
|
1652
1706
|
if (fieldDef.array) {
|
|
1653
|
-
throw
|
|
1707
|
+
throw createInternalError("SQLite does not support scalar list type");
|
|
1654
1708
|
}
|
|
1655
1709
|
if (this.schema.enums?.[fieldDef.type]) {
|
|
1656
1710
|
return "text";
|
|
@@ -1738,16 +1792,12 @@ var BaseOperationHandler = class {
|
|
|
1738
1792
|
operation: "read"
|
|
1739
1793
|
}));
|
|
1740
1794
|
let result = [];
|
|
1741
|
-
const
|
|
1742
|
-
queryId: `zenstack-${createId()}`
|
|
1743
|
-
};
|
|
1744
|
-
const compiled = kysely.getExecutor().compileQuery(query.toOperationNode(), queryId);
|
|
1795
|
+
const compiled = kysely.getExecutor().compileQuery(query.toOperationNode(), createQueryId());
|
|
1745
1796
|
try {
|
|
1746
|
-
const r = await kysely.getExecutor().executeQuery(compiled
|
|
1797
|
+
const r = await kysely.getExecutor().executeQuery(compiled);
|
|
1747
1798
|
result = r.rows;
|
|
1748
1799
|
} catch (err) {
|
|
1749
|
-
|
|
1750
|
-
throw new QueryError(message, err);
|
|
1800
|
+
throw createDBQueryError("Failed to execute query", err, compiled.sql, compiled.parameters);
|
|
1751
1801
|
}
|
|
1752
1802
|
return result;
|
|
1753
1803
|
}
|
|
@@ -1773,7 +1823,7 @@ var BaseOperationHandler = class {
|
|
|
1773
1823
|
result = this.dialect.buildSelectField(result, model, parentAlias, field);
|
|
1774
1824
|
} else {
|
|
1775
1825
|
if (!fieldDef.array && !fieldDef.optional && payload.where) {
|
|
1776
|
-
throw
|
|
1826
|
+
throw createInternalError(`Field "${field}" does not support filtering`, model);
|
|
1777
1827
|
}
|
|
1778
1828
|
if (fieldDef.originModel) {
|
|
1779
1829
|
result = this.dialect.buildRelationSelection(result, fieldDef.originModel, field, fieldDef.originModel, payload);
|
|
@@ -1790,7 +1840,7 @@ var BaseOperationHandler = class {
|
|
|
1790
1840
|
async create(kysely, model, data, fromRelation, creatingForDelegate = false, returnFields) {
|
|
1791
1841
|
const modelDef = this.requireModel(model);
|
|
1792
1842
|
if (modelDef.isDelegate && !creatingForDelegate) {
|
|
1793
|
-
throw
|
|
1843
|
+
throw createNotSupportedError(`Model "${model}" is a delegate and cannot be created directly.`);
|
|
1794
1844
|
}
|
|
1795
1845
|
let createFields = {};
|
|
1796
1846
|
let updateParent = void 0;
|
|
@@ -1895,7 +1945,7 @@ var BaseOperationHandler = class {
|
|
|
1895
1945
|
}
|
|
1896
1946
|
});
|
|
1897
1947
|
if (!extraRead) {
|
|
1898
|
-
throw
|
|
1948
|
+
throw createInternalError(`Field "${pair.pk}" not found in parent created data`, model);
|
|
1899
1949
|
} else {
|
|
1900
1950
|
Object.assign(entity, extraRead);
|
|
1901
1951
|
}
|
|
@@ -1979,7 +2029,7 @@ var BaseOperationHandler = class {
|
|
|
1979
2029
|
select: fieldsToSelectObject(referencedPkFields)
|
|
1980
2030
|
});
|
|
1981
2031
|
if (!relationEntity) {
|
|
1982
|
-
throw
|
|
2032
|
+
throw createNotFoundError(relationModel, `Could not find the entity to connect for the relation "${relationField.name}"`);
|
|
1983
2033
|
}
|
|
1984
2034
|
result = relationEntity;
|
|
1985
2035
|
}
|
|
@@ -1996,7 +2046,7 @@ var BaseOperationHandler = class {
|
|
|
1996
2046
|
break;
|
|
1997
2047
|
}
|
|
1998
2048
|
default:
|
|
1999
|
-
throw
|
|
2049
|
+
throw createInvalidInputError(`Invalid relation action: ${action}`);
|
|
2000
2050
|
}
|
|
2001
2051
|
}
|
|
2002
2052
|
return result;
|
|
@@ -2042,7 +2092,7 @@ var BaseOperationHandler = class {
|
|
|
2042
2092
|
break;
|
|
2043
2093
|
}
|
|
2044
2094
|
default:
|
|
2045
|
-
throw
|
|
2095
|
+
throw createInvalidInputError(`Invalid relation action: ${action}`);
|
|
2046
2096
|
}
|
|
2047
2097
|
}
|
|
2048
2098
|
}
|
|
@@ -2057,7 +2107,7 @@ var BaseOperationHandler = class {
|
|
|
2057
2107
|
if (fromRelation) {
|
|
2058
2108
|
const { ownedByModel, keyPairs } = getRelationForeignKeyFieldPairs(this.schema, fromRelation.model, fromRelation.field);
|
|
2059
2109
|
if (ownedByModel) {
|
|
2060
|
-
throw
|
|
2110
|
+
throw createInvalidInputError("incorrect relation hierarchy for createMany", model);
|
|
2061
2111
|
}
|
|
2062
2112
|
relationKeyPairs = keyPairs;
|
|
2063
2113
|
}
|
|
@@ -2100,7 +2150,7 @@ var BaseOperationHandler = class {
|
|
|
2100
2150
|
}
|
|
2101
2151
|
if (modelDef.baseModel) {
|
|
2102
2152
|
if (input.skipDuplicates) {
|
|
2103
|
-
throw
|
|
2153
|
+
throw createNotSupportedError('"skipDuplicates" options is not supported for polymorphic models');
|
|
2104
2154
|
}
|
|
2105
2155
|
const baseCreateResult = await this.processBaseModelCreateMany(kysely, modelDef.baseModel, createData, !!input.skipDuplicates, model);
|
|
2106
2156
|
createData = baseCreateResult.remainingFieldRows;
|
|
@@ -2198,7 +2248,7 @@ var BaseOperationHandler = class {
|
|
|
2198
2248
|
}
|
|
2199
2249
|
async update(kysely, model, where, data, fromRelation, allowRelationUpdate = true, throwIfNotFound = true, fieldsToReturn) {
|
|
2200
2250
|
if (!data || typeof data !== "object") {
|
|
2201
|
-
throw
|
|
2251
|
+
throw createInvalidInputError("data must be an object");
|
|
2202
2252
|
}
|
|
2203
2253
|
const parentWhere = {};
|
|
2204
2254
|
let m2m = void 0;
|
|
@@ -2260,7 +2310,7 @@ var BaseOperationHandler = class {
|
|
|
2260
2310
|
select: this.makeIdSelect(model)
|
|
2261
2311
|
});
|
|
2262
2312
|
if (!readResult && throwIfNotFound) {
|
|
2263
|
-
throw
|
|
2313
|
+
throw createNotFoundError(model);
|
|
2264
2314
|
}
|
|
2265
2315
|
combinedWhere = readResult;
|
|
2266
2316
|
}
|
|
@@ -2277,13 +2327,13 @@ var BaseOperationHandler = class {
|
|
|
2277
2327
|
updateFields[field] = this.processScalarFieldUpdateData(model, field, finalData);
|
|
2278
2328
|
} else {
|
|
2279
2329
|
if (!allowRelationUpdate) {
|
|
2280
|
-
throw
|
|
2330
|
+
throw createNotSupportedError(`Relation update not allowed for field "${field}"`);
|
|
2281
2331
|
}
|
|
2282
2332
|
if (!thisEntity) {
|
|
2283
2333
|
thisEntity = await this.getEntityIds(kysely, model, combinedWhere);
|
|
2284
2334
|
if (!thisEntity) {
|
|
2285
2335
|
if (throwIfNotFound) {
|
|
2286
|
-
throw
|
|
2336
|
+
throw createNotFoundError(model);
|
|
2287
2337
|
} else {
|
|
2288
2338
|
return null;
|
|
2289
2339
|
}
|
|
@@ -2310,7 +2360,7 @@ var BaseOperationHandler = class {
|
|
|
2310
2360
|
const updatedEntity = await this.executeQueryTakeFirst(kysely, query, "update");
|
|
2311
2361
|
if (!updatedEntity) {
|
|
2312
2362
|
if (throwIfNotFound) {
|
|
2313
|
-
throw
|
|
2363
|
+
throw createNotFoundError(model);
|
|
2314
2364
|
} else {
|
|
2315
2365
|
return null;
|
|
2316
2366
|
}
|
|
@@ -2374,7 +2424,7 @@ var BaseOperationHandler = class {
|
|
|
2374
2424
|
const eb = expressionBuilder2();
|
|
2375
2425
|
const fieldRef = this.dialect.fieldRef(model, field);
|
|
2376
2426
|
return match6(key).with("set", () => value).with("increment", () => eb(fieldRef, "+", value)).with("decrement", () => eb(fieldRef, "-", value)).with("multiply", () => eb(fieldRef, "*", value)).with("divide", () => eb(fieldRef, "/", value)).otherwise(() => {
|
|
2377
|
-
throw
|
|
2427
|
+
throw createInvalidInputError(`Invalid incremental update operation: ${key}`);
|
|
2378
2428
|
});
|
|
2379
2429
|
}
|
|
2380
2430
|
transformScalarListUpdate(model, field, fieldDef, payload) {
|
|
@@ -2386,7 +2436,7 @@ var BaseOperationHandler = class {
|
|
|
2386
2436
|
return match6(key).with("set", () => value).with("push", () => {
|
|
2387
2437
|
return eb(fieldRef, "||", eb.val(ensureArray(value)));
|
|
2388
2438
|
}).otherwise(() => {
|
|
2389
|
-
throw
|
|
2439
|
+
throw createInvalidInputError(`Invalid array update operation: ${key}`);
|
|
2390
2440
|
});
|
|
2391
2441
|
}
|
|
2392
2442
|
isNumericField(fieldDef) {
|
|
@@ -2397,7 +2447,7 @@ var BaseOperationHandler = class {
|
|
|
2397
2447
|
}
|
|
2398
2448
|
async updateMany(kysely, model, where, data, limit, returnData, filterModel, fieldsToReturn) {
|
|
2399
2449
|
if (typeof data !== "object") {
|
|
2400
|
-
throw
|
|
2450
|
+
throw createInvalidInputError("data must be an object");
|
|
2401
2451
|
}
|
|
2402
2452
|
if (Object.keys(data).length === 0) {
|
|
2403
2453
|
return returnData ? [] : {
|
|
@@ -2406,7 +2456,7 @@ var BaseOperationHandler = class {
|
|
|
2406
2456
|
}
|
|
2407
2457
|
const modelDef = this.requireModel(model);
|
|
2408
2458
|
if (modelDef.baseModel && limit !== void 0) {
|
|
2409
|
-
throw
|
|
2459
|
+
throw createNotSupportedError("Updating with a limit is not supported for polymorphic models");
|
|
2410
2460
|
}
|
|
2411
2461
|
filterModel ??= model;
|
|
2412
2462
|
let updateFields = {};
|
|
@@ -2560,7 +2610,7 @@ var BaseOperationHandler = class {
|
|
|
2560
2610
|
break;
|
|
2561
2611
|
}
|
|
2562
2612
|
default: {
|
|
2563
|
-
throw
|
|
2613
|
+
throw createInvalidInputError(`Invalid relation update operation: ${key}`);
|
|
2564
2614
|
}
|
|
2565
2615
|
}
|
|
2566
2616
|
}
|
|
@@ -2578,13 +2628,13 @@ var BaseOperationHandler = class {
|
|
|
2578
2628
|
for (const d of _data) {
|
|
2579
2629
|
const ids = await this.getEntityIds(kysely, model, d);
|
|
2580
2630
|
if (!ids) {
|
|
2581
|
-
throw
|
|
2631
|
+
throw createNotFoundError(model);
|
|
2582
2632
|
}
|
|
2583
2633
|
const r = await this.handleManyToManyRelation(kysely, "connect", fromRelation.model, fromRelation.field, fromRelation.ids, m2m.otherModel, m2m.otherField, ids, m2m.joinTable);
|
|
2584
2634
|
results.push(r);
|
|
2585
2635
|
}
|
|
2586
2636
|
if (_data.length > results.filter((r) => !!r).length) {
|
|
2587
|
-
throw
|
|
2637
|
+
throw createNotFoundError(model);
|
|
2588
2638
|
}
|
|
2589
2639
|
} else {
|
|
2590
2640
|
const { ownedByModel, keyPairs } = getRelationForeignKeyFieldPairs(this.schema, fromRelation.model, fromRelation.field);
|
|
@@ -2594,7 +2644,7 @@ var BaseOperationHandler = class {
|
|
|
2594
2644
|
where: _data[0]
|
|
2595
2645
|
});
|
|
2596
2646
|
if (!target) {
|
|
2597
|
-
throw
|
|
2647
|
+
throw createNotFoundError(model);
|
|
2598
2648
|
}
|
|
2599
2649
|
for (const { fk, pk } of keyPairs) {
|
|
2600
2650
|
fromRelation.parentUpdates[fk] = target[pk];
|
|
@@ -2620,7 +2670,7 @@ var BaseOperationHandler = class {
|
|
|
2620
2670
|
}));
|
|
2621
2671
|
const updateResult = await this.executeQuery(kysely, query, "connect");
|
|
2622
2672
|
if (!updateResult.numAffectedRows || _data.length > updateResult.numAffectedRows) {
|
|
2623
|
-
throw
|
|
2673
|
+
throw createNotFoundError(model);
|
|
2624
2674
|
}
|
|
2625
2675
|
}
|
|
2626
2676
|
}
|
|
@@ -2736,17 +2786,17 @@ var BaseOperationHandler = class {
|
|
|
2736
2786
|
for (const d of _data) {
|
|
2737
2787
|
const ids = await this.getEntityIds(kysely, model, d);
|
|
2738
2788
|
if (!ids) {
|
|
2739
|
-
throw
|
|
2789
|
+
throw createNotFoundError(model);
|
|
2740
2790
|
}
|
|
2741
2791
|
results.push(await this.handleManyToManyRelation(kysely, "connect", fromRelation.model, fromRelation.field, fromRelation.ids, m2m.otherModel, m2m.otherField, ids, m2m.joinTable));
|
|
2742
2792
|
}
|
|
2743
2793
|
if (_data.length > results.filter((r) => !!r).length) {
|
|
2744
|
-
throw
|
|
2794
|
+
throw createNotFoundError(model);
|
|
2745
2795
|
}
|
|
2746
2796
|
} else {
|
|
2747
2797
|
const { ownedByModel, keyPairs } = getRelationForeignKeyFieldPairs(this.schema, fromRelation.model, fromRelation.field);
|
|
2748
2798
|
if (ownedByModel) {
|
|
2749
|
-
throw
|
|
2799
|
+
throw createInternalError("relation can only be set from the non-owning side", fromRelation.model);
|
|
2750
2800
|
}
|
|
2751
2801
|
const fkConditions = keyPairs.reduce((acc, { fk, pk }) => ({
|
|
2752
2802
|
...acc,
|
|
@@ -2775,7 +2825,7 @@ var BaseOperationHandler = class {
|
|
|
2775
2825
|
}));
|
|
2776
2826
|
const r = await this.executeQuery(kysely, query2, "connect");
|
|
2777
2827
|
if (!r.numAffectedRows || _data.length > r.numAffectedRows) {
|
|
2778
|
-
throw
|
|
2828
|
+
throw createNotFoundError(model);
|
|
2779
2829
|
}
|
|
2780
2830
|
}
|
|
2781
2831
|
}
|
|
@@ -2826,7 +2876,7 @@ var BaseOperationHandler = class {
|
|
|
2826
2876
|
where: fromRelation.ids
|
|
2827
2877
|
});
|
|
2828
2878
|
if (!fromEntity) {
|
|
2829
|
-
throw
|
|
2879
|
+
throw createNotFoundError(fromRelation.model);
|
|
2830
2880
|
}
|
|
2831
2881
|
const fieldDef = this.requireField(fromRelation.model, fromRelation.field);
|
|
2832
2882
|
invariant5(fieldDef.relation?.opposite);
|
|
@@ -2858,7 +2908,7 @@ var BaseOperationHandler = class {
|
|
|
2858
2908
|
}
|
|
2859
2909
|
}
|
|
2860
2910
|
if (throwForNotFound && expectedDeleteCount > deleteResult.rows.length) {
|
|
2861
|
-
throw
|
|
2911
|
+
throw createNotFoundError(deleteFromModel);
|
|
2862
2912
|
}
|
|
2863
2913
|
}
|
|
2864
2914
|
normalizeRelationManipulationInput(model, data) {
|
|
@@ -2870,7 +2920,7 @@ var BaseOperationHandler = class {
|
|
|
2870
2920
|
const modelDef = this.requireModel(model);
|
|
2871
2921
|
if (modelDef.baseModel) {
|
|
2872
2922
|
if (limit !== void 0) {
|
|
2873
|
-
throw
|
|
2923
|
+
throw createNotSupportedError("Deleting with a limit is not supported for polymorphic models");
|
|
2874
2924
|
}
|
|
2875
2925
|
return this.processBaseModelDelete(kysely, modelDef.baseModel, where, limit, filterModel);
|
|
2876
2926
|
}
|
|
@@ -2904,7 +2954,7 @@ var BaseOperationHandler = class {
|
|
|
2904
2954
|
const oppositeRelation = this.requireField(fieldDef.type, fieldDef.relation.opposite);
|
|
2905
2955
|
if (oppositeModelDef.baseModel && oppositeRelation.relation?.onDelete === "Cascade") {
|
|
2906
2956
|
if (limit !== void 0) {
|
|
2907
|
-
throw
|
|
2957
|
+
throw createNotSupportedError("Deleting with a limit is not supported for polymorphic models");
|
|
2908
2958
|
}
|
|
2909
2959
|
await this.delete(kysely, fieldDef.type, {
|
|
2910
2960
|
[fieldDef.relation.opposite]: where
|
|
@@ -2982,22 +3032,17 @@ var BaseOperationHandler = class {
|
|
|
2982
3032
|
}
|
|
2983
3033
|
}
|
|
2984
3034
|
}
|
|
2985
|
-
|
|
2986
|
-
return
|
|
2987
|
-
queryId: `${operation}-${createId()}`
|
|
2988
|
-
};
|
|
2989
|
-
}
|
|
2990
|
-
executeQuery(kysely, query, operation) {
|
|
2991
|
-
return kysely.executeQuery(query.compile(), this.makeQueryId(operation));
|
|
3035
|
+
executeQuery(kysely, query, _operation) {
|
|
3036
|
+
return kysely.executeQuery(query.compile());
|
|
2992
3037
|
}
|
|
2993
|
-
async executeQueryTakeFirst(kysely, query,
|
|
2994
|
-
const result = await kysely.executeQuery(query.compile()
|
|
3038
|
+
async executeQueryTakeFirst(kysely, query, _operation) {
|
|
3039
|
+
const result = await kysely.executeQuery(query.compile());
|
|
2995
3040
|
return result.rows[0];
|
|
2996
3041
|
}
|
|
2997
|
-
async executeQueryTakeFirstOrThrow(kysely, query,
|
|
2998
|
-
const result = await kysely.executeQuery(query.compile()
|
|
3042
|
+
async executeQueryTakeFirstOrThrow(kysely, query, _operation) {
|
|
3043
|
+
const result = await kysely.executeQuery(query.compile());
|
|
2999
3044
|
if (result.rows.length === 0) {
|
|
3000
|
-
throw new
|
|
3045
|
+
throw new ORMError(ORMErrorReason.NOT_FOUND, "No rows found");
|
|
3001
3046
|
}
|
|
3002
3047
|
return result.rows[0];
|
|
3003
3048
|
}
|
|
@@ -3218,7 +3263,7 @@ var CreateOperationHandler = class extends BaseOperationHandler {
|
|
|
3218
3263
|
}
|
|
3219
3264
|
});
|
|
3220
3265
|
if (!result && this.hasPolicyEnabled) {
|
|
3221
|
-
throw
|
|
3266
|
+
throw createRejectedByPolicyError(this.model, RejectedByPolicyReason.CANNOT_READ_BACK, `result is not allowed to be read back`);
|
|
3222
3267
|
}
|
|
3223
3268
|
return result;
|
|
3224
3269
|
}
|
|
@@ -3276,12 +3321,12 @@ var DeleteOperationHandler = class extends BaseOperationHandler {
|
|
|
3276
3321
|
}
|
|
3277
3322
|
const deleteResult = await this.delete(tx, this.model, args.where, void 0, void 0, selectedFields);
|
|
3278
3323
|
if (deleteResult.rows.length === 0) {
|
|
3279
|
-
throw
|
|
3324
|
+
throw createNotFoundError(this.model);
|
|
3280
3325
|
}
|
|
3281
3326
|
return needReadBack ? preDeleteRead : deleteResult.rows[0];
|
|
3282
3327
|
});
|
|
3283
3328
|
if (!result && this.hasPolicyEnabled) {
|
|
3284
|
-
throw
|
|
3329
|
+
throw createRejectedByPolicyError(this.model, RejectedByPolicyReason.CANNOT_READ_BACK, "result is not allowed to be read back");
|
|
3285
3330
|
}
|
|
3286
3331
|
return result;
|
|
3287
3332
|
}
|
|
@@ -3450,7 +3495,7 @@ var UpdateOperationHandler = class extends BaseOperationHandler {
|
|
|
3450
3495
|
});
|
|
3451
3496
|
if (!result) {
|
|
3452
3497
|
if (this.hasPolicyEnabled) {
|
|
3453
|
-
throw
|
|
3498
|
+
throw createRejectedByPolicyError(this.model, RejectedByPolicyReason.CANNOT_READ_BACK, "result is not allowed to be read back");
|
|
3454
3499
|
} else {
|
|
3455
3500
|
return null;
|
|
3456
3501
|
}
|
|
@@ -3490,7 +3535,7 @@ var UpdateOperationHandler = class extends BaseOperationHandler {
|
|
|
3490
3535
|
}
|
|
3491
3536
|
});
|
|
3492
3537
|
if (readBackResult.length < updateResult.length && this.hasPolicyEnabled) {
|
|
3493
|
-
throw
|
|
3538
|
+
throw createRejectedByPolicyError(this.model, RejectedByPolicyReason.CANNOT_READ_BACK, "result is not allowed to be read back");
|
|
3494
3539
|
}
|
|
3495
3540
|
return readBackResult;
|
|
3496
3541
|
}
|
|
@@ -3513,7 +3558,7 @@ var UpdateOperationHandler = class extends BaseOperationHandler {
|
|
|
3513
3558
|
}
|
|
3514
3559
|
});
|
|
3515
3560
|
if (!result && this.hasPolicyEnabled) {
|
|
3516
|
-
throw
|
|
3561
|
+
throw createRejectedByPolicyError(this.model, RejectedByPolicyReason.CANNOT_READ_BACK, "result is not allowed to be read back");
|
|
3517
3562
|
}
|
|
3518
3563
|
return result;
|
|
3519
3564
|
}
|
|
@@ -3910,7 +3955,7 @@ function evalCall(data, expr) {
|
|
|
3910
3955
|
invariant6(Array.isArray(fieldArg), `"${f}" first argument must be an array field`);
|
|
3911
3956
|
return fieldArg.length === 0;
|
|
3912
3957
|
}).otherwise(() => {
|
|
3913
|
-
throw
|
|
3958
|
+
throw createNotSupportedError(`Unsupported function "${expr.function}"`);
|
|
3914
3959
|
});
|
|
3915
3960
|
}
|
|
3916
3961
|
__name(evalCall, "evalCall");
|
|
@@ -4001,7 +4046,9 @@ var InputValidator = class {
|
|
|
4001
4046
|
}
|
|
4002
4047
|
const { error, data } = schema.safeParse(args);
|
|
4003
4048
|
if (error) {
|
|
4004
|
-
throw
|
|
4049
|
+
throw createInvalidInputError(`Invalid ${operation} args for model "${model}": ${formatError(error)}`, model, {
|
|
4050
|
+
cause: error
|
|
4051
|
+
});
|
|
4005
4052
|
}
|
|
4006
4053
|
return data;
|
|
4007
4054
|
}
|
|
@@ -4039,6 +4086,8 @@ var InputValidator = class {
|
|
|
4039
4086
|
makePrimitiveSchema(type, attributes) {
|
|
4040
4087
|
if (this.schema.typeDefs && type in this.schema.typeDefs) {
|
|
4041
4088
|
return this.makeTypeDefSchema(type);
|
|
4089
|
+
} else if (this.schema.enums && type in this.schema.enums) {
|
|
4090
|
+
return this.makeEnumSchema(type);
|
|
4042
4091
|
} else {
|
|
4043
4092
|
return match13(type).with("String", () => this.extraValidationsEnabled ? addStringValidation(z2.string(), attributes) : z2.string()).with("Int", () => this.extraValidationsEnabled ? addNumberValidation(z2.number().int(), attributes) : z2.number().int()).with("Float", () => this.extraValidationsEnabled ? addNumberValidation(z2.number(), attributes) : z2.number()).with("Boolean", () => z2.boolean()).with("BigInt", () => z2.union([
|
|
4044
4093
|
this.extraValidationsEnabled ? addNumberValidation(z2.number().int(), attributes) : z2.number().int(),
|
|
@@ -4055,6 +4104,21 @@ var InputValidator = class {
|
|
|
4055
4104
|
])).with("Bytes", () => z2.instanceof(Uint8Array)).otherwise(() => z2.unknown());
|
|
4056
4105
|
}
|
|
4057
4106
|
}
|
|
4107
|
+
makeEnumSchema(type) {
|
|
4108
|
+
const key = stableStringify({
|
|
4109
|
+
type: "enum",
|
|
4110
|
+
name: type
|
|
4111
|
+
});
|
|
4112
|
+
let schema = this.getSchemaCache(key);
|
|
4113
|
+
if (schema) {
|
|
4114
|
+
return schema;
|
|
4115
|
+
}
|
|
4116
|
+
const enumDef = getEnum(this.schema, type);
|
|
4117
|
+
invariant7(enumDef, `Enum "${type}" not found in schema`);
|
|
4118
|
+
schema = z2.enum(Object.keys(enumDef.values));
|
|
4119
|
+
this.setSchemaCache(key, schema);
|
|
4120
|
+
return schema;
|
|
4121
|
+
}
|
|
4058
4122
|
makeTypeDefSchema(type) {
|
|
4059
4123
|
const key = stableStringify({
|
|
4060
4124
|
type: "typedef",
|
|
@@ -4065,9 +4129,9 @@ var InputValidator = class {
|
|
|
4065
4129
|
if (schema) {
|
|
4066
4130
|
return schema;
|
|
4067
4131
|
}
|
|
4068
|
-
const typeDef = this.schema
|
|
4132
|
+
const typeDef = getTypeDef(this.schema, type);
|
|
4069
4133
|
invariant7(typeDef, `Type definition "${type}" not found in schema`);
|
|
4070
|
-
schema = z2.
|
|
4134
|
+
schema = z2.looseObject(Object.fromEntries(Object.entries(typeDef.fields).map(([field, def]) => {
|
|
4071
4135
|
let fieldSchema = this.makePrimitiveSchema(def.type);
|
|
4072
4136
|
if (def.array) {
|
|
4073
4137
|
fieldSchema = fieldSchema.array();
|
|
@@ -4079,7 +4143,7 @@ var InputValidator = class {
|
|
|
4079
4143
|
field,
|
|
4080
4144
|
fieldSchema
|
|
4081
4145
|
];
|
|
4082
|
-
})))
|
|
4146
|
+
})));
|
|
4083
4147
|
this.setSchemaCache(key, schema);
|
|
4084
4148
|
return schema;
|
|
4085
4149
|
}
|
|
@@ -4116,7 +4180,7 @@ var InputValidator = class {
|
|
|
4116
4180
|
} else {
|
|
4117
4181
|
const enumDef = getEnum(this.schema, fieldDef.type);
|
|
4118
4182
|
if (enumDef) {
|
|
4119
|
-
if (Object.keys(enumDef).length > 0) {
|
|
4183
|
+
if (Object.keys(enumDef.values).length > 0) {
|
|
4120
4184
|
fieldSchema = this.makeEnumFilterSchema(enumDef, !!fieldDef.optional, withAggregations);
|
|
4121
4185
|
}
|
|
4122
4186
|
} else if (fieldDef.array) {
|
|
@@ -4138,7 +4202,7 @@ var InputValidator = class {
|
|
|
4138
4202
|
let fieldSchema;
|
|
4139
4203
|
const enumDef = getEnum(this.schema, def.type);
|
|
4140
4204
|
if (enumDef) {
|
|
4141
|
-
if (Object.keys(enumDef).length > 0) {
|
|
4205
|
+
if (Object.keys(enumDef.values).length > 0) {
|
|
4142
4206
|
fieldSchema = this.makeEnumFilterSchema(enumDef, !!def.optional, false);
|
|
4143
4207
|
} else {
|
|
4144
4208
|
fieldSchema = z2.never();
|
|
@@ -4163,7 +4227,7 @@ var InputValidator = class {
|
|
|
4163
4227
|
if (unique) {
|
|
4164
4228
|
const uniqueFields = getUniqueFields(this.schema, model);
|
|
4165
4229
|
if (uniqueFields.length === 0) {
|
|
4166
|
-
throw
|
|
4230
|
+
throw createInternalError(`Model "${model}" has no unique fields`);
|
|
4167
4231
|
}
|
|
4168
4232
|
if (uniqueFields.length === 1) {
|
|
4169
4233
|
result = baseWhere.required({
|
|
@@ -4178,7 +4242,7 @@ var InputValidator = class {
|
|
|
4178
4242
|
return result;
|
|
4179
4243
|
}
|
|
4180
4244
|
makeEnumFilterSchema(enumDef, optional, withAggregations) {
|
|
4181
|
-
const baseSchema = z2.enum(Object.keys(enumDef));
|
|
4245
|
+
const baseSchema = z2.enum(Object.keys(enumDef.values));
|
|
4182
4246
|
const components = this.makeCommonPrimitiveFilterComponents(baseSchema, optional, () => z2.lazy(() => this.makeEnumFilterSchema(enumDef, optional, withAggregations)), [
|
|
4183
4247
|
"equals",
|
|
4184
4248
|
"in",
|
|
@@ -5166,12 +5230,12 @@ __name(performanceNow, "performanceNow");
|
|
|
5166
5230
|
|
|
5167
5231
|
// src/client/executor/zenstack-query-executor.ts
|
|
5168
5232
|
import { invariant as invariant9 } from "@zenstackhq/common-helpers";
|
|
5169
|
-
import { AndNode, DefaultQueryExecutor, DeleteQueryNode, InsertQueryNode, ReturningNode, SelectionNode as SelectionNode2, SingleConnectionProvider, TableNode as TableNode3, UpdateQueryNode, WhereNode } from "kysely";
|
|
5233
|
+
import { AndNode, createQueryId as createQueryId2, DefaultQueryExecutor, DeleteQueryNode, InsertQueryNode, ReturningNode, SelectionNode as SelectionNode2, SingleConnectionProvider, TableNode as TableNode3, UpdateQueryNode, WhereNode } from "kysely";
|
|
5170
5234
|
import { match as match14 } from "ts-pattern";
|
|
5171
5235
|
|
|
5172
5236
|
// src/client/executor/name-mapper.ts
|
|
5173
5237
|
import { invariant as invariant8 } from "@zenstackhq/common-helpers";
|
|
5174
|
-
import { AliasNode as AliasNode2, ColumnNode as ColumnNode2, FromNode, IdentifierNode, OperationNodeTransformer, ReferenceNode as ReferenceNode2, SelectAllNode, SelectionNode, TableNode as TableNode2 } from "kysely";
|
|
5238
|
+
import { AliasNode as AliasNode2, ColumnNode as ColumnNode2, ColumnUpdateNode, expressionBuilder as expressionBuilder3, ExpressionWrapper, FromNode, IdentifierNode, OperationNodeTransformer, PrimitiveValueListNode, ReferenceNode as ReferenceNode2, SelectAllNode, SelectionNode, TableNode as TableNode2, ValueListNode, ValueNode, ValuesNode } from "kysely";
|
|
5175
5239
|
var QueryNameMapper = class extends OperationNodeTransformer {
|
|
5176
5240
|
static {
|
|
5177
5241
|
__name(this, "QueryNameMapper");
|
|
@@ -5226,13 +5290,26 @@ var QueryNameMapper = class extends OperationNodeTransformer {
|
|
|
5226
5290
|
if (!node.into) {
|
|
5227
5291
|
return super.transformInsertQuery(node);
|
|
5228
5292
|
}
|
|
5293
|
+
const model = extractModelName(node.into);
|
|
5294
|
+
invariant8(model, 'InsertQueryNode must have a model name in the "into" clause');
|
|
5229
5295
|
return this.withScope({
|
|
5230
|
-
model
|
|
5231
|
-
}, () =>
|
|
5232
|
-
|
|
5233
|
-
|
|
5234
|
-
|
|
5235
|
-
|
|
5296
|
+
model
|
|
5297
|
+
}, () => {
|
|
5298
|
+
const baseResult = super.transformInsertQuery(node);
|
|
5299
|
+
let values = baseResult.values;
|
|
5300
|
+
if (node.columns && values) {
|
|
5301
|
+
values = this.processEnumMappingForColumns(model, node.columns, values);
|
|
5302
|
+
}
|
|
5303
|
+
return {
|
|
5304
|
+
...baseResult,
|
|
5305
|
+
// map table name
|
|
5306
|
+
into: this.processTableRef(node.into),
|
|
5307
|
+
values
|
|
5308
|
+
};
|
|
5309
|
+
});
|
|
5310
|
+
}
|
|
5311
|
+
isOperationNode(value) {
|
|
5312
|
+
return !!value && typeof value === "object" && "kind" in value;
|
|
5236
5313
|
}
|
|
5237
5314
|
transformReturning(node) {
|
|
5238
5315
|
return {
|
|
@@ -5255,7 +5332,7 @@ var QueryNameMapper = class extends OperationNodeTransformer {
|
|
|
5255
5332
|
mappedTableName = this.mapTableName(scope.model);
|
|
5256
5333
|
}
|
|
5257
5334
|
}
|
|
5258
|
-
return ReferenceNode2.create(ColumnNode2.create(mappedFieldName), mappedTableName ?
|
|
5335
|
+
return ReferenceNode2.create(ColumnNode2.create(mappedFieldName), mappedTableName ? this.createTableNode(mappedTableName, void 0) : void 0);
|
|
5259
5336
|
} else {
|
|
5260
5337
|
return node;
|
|
5261
5338
|
}
|
|
@@ -5276,12 +5353,24 @@ var QueryNameMapper = class extends OperationNodeTransformer {
|
|
|
5276
5353
|
if (!innerTable || !TableNode2.is(innerTable)) {
|
|
5277
5354
|
return super.transformUpdateQuery(node);
|
|
5278
5355
|
}
|
|
5356
|
+
const model = extractModelName(innerTable);
|
|
5357
|
+
invariant8(model, 'UpdateQueryNode must have a model name in the "table" clause');
|
|
5279
5358
|
return this.withScope({
|
|
5280
|
-
model
|
|
5359
|
+
model,
|
|
5281
5360
|
alias
|
|
5282
5361
|
}, () => {
|
|
5362
|
+
const baseResult = super.transformUpdateQuery(node);
|
|
5363
|
+
const updates = baseResult.updates?.map((update, i) => {
|
|
5364
|
+
if (ColumnNode2.is(update.column)) {
|
|
5365
|
+
const origColumn = node.updates[i].column;
|
|
5366
|
+
return ColumnUpdateNode.create(update.column, this.processEnumMappingForValue(model, origColumn, update.value));
|
|
5367
|
+
} else {
|
|
5368
|
+
return update;
|
|
5369
|
+
}
|
|
5370
|
+
});
|
|
5283
5371
|
return {
|
|
5284
|
-
...
|
|
5372
|
+
...baseResult,
|
|
5373
|
+
updates,
|
|
5285
5374
|
// map table name
|
|
5286
5375
|
table: this.wrapAlias(this.processTableRef(innerTable), alias)
|
|
5287
5376
|
};
|
|
@@ -5316,29 +5405,54 @@ var QueryNameMapper = class extends OperationNodeTransformer {
|
|
|
5316
5405
|
processSelectQuerySelections(node) {
|
|
5317
5406
|
const selections = [];
|
|
5318
5407
|
for (const selection of node.selections ?? []) {
|
|
5408
|
+
const processedSelections = [];
|
|
5319
5409
|
if (SelectAllNode.is(selection.selection)) {
|
|
5320
|
-
const scope = this.
|
|
5410
|
+
const scope = this.requireCurrentScope();
|
|
5321
5411
|
if (scope?.model && !scope.namesMapped) {
|
|
5322
|
-
|
|
5412
|
+
processedSelections.push(...this.createSelectAllFields(scope.model, scope.alias));
|
|
5323
5413
|
} else {
|
|
5324
|
-
|
|
5414
|
+
processedSelections.push({
|
|
5415
|
+
originalField: void 0,
|
|
5416
|
+
selection: super.transformSelection(selection)
|
|
5417
|
+
});
|
|
5325
5418
|
}
|
|
5326
5419
|
} else if (ReferenceNode2.is(selection.selection) || ColumnNode2.is(selection.selection)) {
|
|
5327
5420
|
const transformed = this.transformNode(selection.selection);
|
|
5421
|
+
const originalField = extractFieldName(selection.selection);
|
|
5328
5422
|
if (AliasNode2.is(transformed)) {
|
|
5329
|
-
|
|
5423
|
+
processedSelections.push({
|
|
5424
|
+
originalField,
|
|
5425
|
+
selection: SelectionNode.create(transformed)
|
|
5426
|
+
});
|
|
5330
5427
|
} else {
|
|
5331
|
-
const origFieldName = extractFieldName(selection.selection);
|
|
5332
5428
|
const fieldName = extractFieldName(transformed);
|
|
5333
|
-
if (fieldName !==
|
|
5334
|
-
|
|
5429
|
+
if (fieldName !== originalField) {
|
|
5430
|
+
processedSelections.push({
|
|
5431
|
+
originalField,
|
|
5432
|
+
selection: SelectionNode.create(this.wrapAlias(transformed, originalField ? IdentifierNode.create(originalField) : void 0))
|
|
5433
|
+
});
|
|
5335
5434
|
} else {
|
|
5336
|
-
|
|
5435
|
+
processedSelections.push({
|
|
5436
|
+
originalField,
|
|
5437
|
+
selection: SelectionNode.create(transformed)
|
|
5438
|
+
});
|
|
5337
5439
|
}
|
|
5338
5440
|
}
|
|
5339
5441
|
} else {
|
|
5340
|
-
|
|
5442
|
+
const { node: innerNode } = stripAlias(selection.selection);
|
|
5443
|
+
processedSelections.push({
|
|
5444
|
+
originalField: extractFieldName(innerNode),
|
|
5445
|
+
selection: super.transformSelection(selection)
|
|
5446
|
+
});
|
|
5341
5447
|
}
|
|
5448
|
+
const enumProcessedSelections = processedSelections.map(({ originalField, selection: selection2 }) => {
|
|
5449
|
+
if (!originalField) {
|
|
5450
|
+
return selection2;
|
|
5451
|
+
} else {
|
|
5452
|
+
return SelectionNode.create(this.processEnumSelection(selection2.selection, originalField));
|
|
5453
|
+
}
|
|
5454
|
+
});
|
|
5455
|
+
selections.push(...enumProcessedSelections);
|
|
5342
5456
|
}
|
|
5343
5457
|
return selections;
|
|
5344
5458
|
}
|
|
@@ -5402,7 +5516,9 @@ var QueryNameMapper = class extends OperationNodeTransformer {
|
|
|
5402
5516
|
if (!TableNode2.is(node)) {
|
|
5403
5517
|
return super.transformNode(node);
|
|
5404
5518
|
}
|
|
5405
|
-
|
|
5519
|
+
const mappedName = this.mapTableName(node.table.identifier.name);
|
|
5520
|
+
const tableSchema = this.getTableSchema(node.table.identifier.name);
|
|
5521
|
+
return this.createTableNode(mappedName, tableSchema);
|
|
5406
5522
|
}
|
|
5407
5523
|
getMappedName(def) {
|
|
5408
5524
|
const mapAttr = def.attributes?.find((attr) => attr.name === "@@map" || attr.name === "@map");
|
|
@@ -5442,8 +5558,9 @@ var QueryNameMapper = class extends OperationNodeTransformer {
|
|
|
5442
5558
|
const modelName = innerNode.table.identifier.name;
|
|
5443
5559
|
const mappedName = this.mapTableName(modelName);
|
|
5444
5560
|
const finalAlias = alias ?? (mappedName !== modelName ? IdentifierNode.create(modelName) : void 0);
|
|
5561
|
+
const tableSchema = this.getTableSchema(modelName);
|
|
5445
5562
|
return {
|
|
5446
|
-
node: this.wrapAlias(
|
|
5563
|
+
node: this.wrapAlias(this.createTableNode(mappedName, tableSchema), finalAlias),
|
|
5447
5564
|
scope: {
|
|
5448
5565
|
alias: alias ?? IdentifierNode.create(modelName),
|
|
5449
5566
|
model: modelName,
|
|
@@ -5461,6 +5578,20 @@ var QueryNameMapper = class extends OperationNodeTransformer {
|
|
|
5461
5578
|
};
|
|
5462
5579
|
}
|
|
5463
5580
|
}
|
|
5581
|
+
getTableSchema(model) {
|
|
5582
|
+
if (this.schema.provider.type !== "postgresql") {
|
|
5583
|
+
return void 0;
|
|
5584
|
+
}
|
|
5585
|
+
let schema = this.schema.provider.defaultSchema ?? "public";
|
|
5586
|
+
const schemaAttr = this.schema.models[model]?.attributes?.find((attr) => attr.name === "@@schema");
|
|
5587
|
+
if (schemaAttr) {
|
|
5588
|
+
const nameArg = schemaAttr.args?.find((arg) => arg.name === "map");
|
|
5589
|
+
if (nameArg && nameArg.value.kind === "literal") {
|
|
5590
|
+
schema = nameArg.value.value;
|
|
5591
|
+
}
|
|
5592
|
+
}
|
|
5593
|
+
return schema;
|
|
5594
|
+
}
|
|
5464
5595
|
createSelectAllFields(model, alias) {
|
|
5465
5596
|
const modelDef = requireModel(this.schema, model);
|
|
5466
5597
|
return this.getModelFields(modelDef).map((fieldDef) => {
|
|
@@ -5468,9 +5599,15 @@ var QueryNameMapper = class extends OperationNodeTransformer {
|
|
|
5468
5599
|
const columnRef = ReferenceNode2.create(ColumnNode2.create(columnName), alias && IdentifierNode.is(alias) ? TableNode2.create(alias.name) : void 0);
|
|
5469
5600
|
if (columnName !== fieldDef.name) {
|
|
5470
5601
|
const aliased = AliasNode2.create(columnRef, IdentifierNode.create(fieldDef.name));
|
|
5471
|
-
return
|
|
5602
|
+
return {
|
|
5603
|
+
originalField: fieldDef.name,
|
|
5604
|
+
selection: SelectionNode.create(aliased)
|
|
5605
|
+
};
|
|
5472
5606
|
} else {
|
|
5473
|
-
return
|
|
5607
|
+
return {
|
|
5608
|
+
originalField: fieldDef.name,
|
|
5609
|
+
selection: SelectionNode.create(columnRef)
|
|
5610
|
+
};
|
|
5474
5611
|
}
|
|
5475
5612
|
});
|
|
5476
5613
|
}
|
|
@@ -5494,26 +5631,155 @@ var QueryNameMapper = class extends OperationNodeTransformer {
|
|
|
5494
5631
|
return result;
|
|
5495
5632
|
}
|
|
5496
5633
|
processSelection(node) {
|
|
5497
|
-
|
|
5498
|
-
|
|
5499
|
-
|
|
5634
|
+
const { alias, node: innerNode } = stripAlias(node);
|
|
5635
|
+
const originalField = extractFieldName(innerNode);
|
|
5636
|
+
let result = super.transformNode(node);
|
|
5637
|
+
if (originalField) {
|
|
5638
|
+
result = this.processEnumSelection(result, originalField);
|
|
5639
|
+
}
|
|
5640
|
+
if (!AliasNode2.is(result)) {
|
|
5641
|
+
const addAlias = alias ?? (originalField ? IdentifierNode.create(originalField) : void 0);
|
|
5642
|
+
if (addAlias) {
|
|
5643
|
+
result = this.wrapAlias(result, addAlias);
|
|
5644
|
+
}
|
|
5500
5645
|
}
|
|
5501
|
-
|
|
5502
|
-
return this.wrapAlias(result, alias ? IdentifierNode.create(alias) : void 0);
|
|
5646
|
+
return result;
|
|
5503
5647
|
}
|
|
5504
5648
|
processSelectAll(node) {
|
|
5505
|
-
const scope = this.
|
|
5506
|
-
|
|
5507
|
-
if (!scope.model || !this.hasMappedColumns(scope.model)) {
|
|
5649
|
+
const scope = this.requireCurrentScope();
|
|
5650
|
+
if (!scope.model || !(this.hasMappedColumns(scope.model) || this.modelUsesEnumWithMappedValues(scope.model))) {
|
|
5508
5651
|
return super.transformSelectAll(node);
|
|
5509
5652
|
}
|
|
5510
5653
|
const modelDef = requireModel(this.schema, scope.model);
|
|
5511
5654
|
return this.getModelFields(modelDef).map((fieldDef) => {
|
|
5512
5655
|
const columnName = this.mapFieldName(modelDef.name, fieldDef.name);
|
|
5513
5656
|
const columnRef = ReferenceNode2.create(ColumnNode2.create(columnName));
|
|
5514
|
-
|
|
5657
|
+
const enumProcessed = this.processEnumSelection(columnRef, fieldDef.name);
|
|
5658
|
+
return columnName !== fieldDef.name && !AliasNode2.is(enumProcessed) ? this.wrapAlias(enumProcessed, IdentifierNode.create(fieldDef.name)) : enumProcessed;
|
|
5659
|
+
});
|
|
5660
|
+
}
|
|
5661
|
+
createTableNode(tableName, schemaName) {
|
|
5662
|
+
return schemaName ? TableNode2.createWithSchema(schemaName, tableName) : TableNode2.create(tableName);
|
|
5663
|
+
}
|
|
5664
|
+
requireCurrentScope() {
|
|
5665
|
+
const scope = this.scopes[this.scopes.length - 1];
|
|
5666
|
+
invariant8(scope, "No scope available");
|
|
5667
|
+
return scope;
|
|
5668
|
+
}
|
|
5669
|
+
// #endregion
|
|
5670
|
+
// #region enum value mapping
|
|
5671
|
+
modelUsesEnumWithMappedValues(model) {
|
|
5672
|
+
const modelDef = getModel(this.schema, model);
|
|
5673
|
+
if (!modelDef) {
|
|
5674
|
+
return false;
|
|
5675
|
+
}
|
|
5676
|
+
return this.getModelFields(modelDef).some((fieldDef) => {
|
|
5677
|
+
const enumDef = getEnum(this.schema, fieldDef.type);
|
|
5678
|
+
if (!enumDef) {
|
|
5679
|
+
return false;
|
|
5680
|
+
}
|
|
5681
|
+
return Object.values(enumDef.fields ?? {}).some((f) => f.attributes?.some((attr) => attr.name === "@map"));
|
|
5515
5682
|
});
|
|
5516
5683
|
}
|
|
5684
|
+
getEnumValueMapping(enumDef) {
|
|
5685
|
+
const mapping = {};
|
|
5686
|
+
for (const [key, field] of Object.entries(enumDef.fields ?? {})) {
|
|
5687
|
+
const mappedName = this.getMappedName(field);
|
|
5688
|
+
if (mappedName) {
|
|
5689
|
+
mapping[key] = mappedName;
|
|
5690
|
+
}
|
|
5691
|
+
}
|
|
5692
|
+
return mapping;
|
|
5693
|
+
}
|
|
5694
|
+
processEnumMappingForColumns(model, columns, values) {
|
|
5695
|
+
if (ValuesNode.is(values)) {
|
|
5696
|
+
return ValuesNode.create(values.values.map((valueItems) => {
|
|
5697
|
+
if (PrimitiveValueListNode.is(valueItems)) {
|
|
5698
|
+
return PrimitiveValueListNode.create(this.processEnumMappingForValues(model, columns, valueItems.values));
|
|
5699
|
+
} else {
|
|
5700
|
+
return ValueListNode.create(this.processEnumMappingForValues(model, columns, valueItems.values));
|
|
5701
|
+
}
|
|
5702
|
+
}));
|
|
5703
|
+
} else if (PrimitiveValueListNode.is(values)) {
|
|
5704
|
+
return PrimitiveValueListNode.create(this.processEnumMappingForValues(model, columns, values.values));
|
|
5705
|
+
} else {
|
|
5706
|
+
return values;
|
|
5707
|
+
}
|
|
5708
|
+
}
|
|
5709
|
+
processEnumMappingForValues(model, columns, values) {
|
|
5710
|
+
const result = [];
|
|
5711
|
+
for (let i = 0; i < columns.length; i++) {
|
|
5712
|
+
const value = values[i];
|
|
5713
|
+
if (value === null || value === void 0) {
|
|
5714
|
+
result.push(value);
|
|
5715
|
+
continue;
|
|
5716
|
+
}
|
|
5717
|
+
result.push(this.processEnumMappingForValue(model, columns[i], value));
|
|
5718
|
+
}
|
|
5719
|
+
return result;
|
|
5720
|
+
}
|
|
5721
|
+
processEnumMappingForValue(model, column, value) {
|
|
5722
|
+
const fieldDef = getField(this.schema, model, column.column.name);
|
|
5723
|
+
if (!fieldDef) {
|
|
5724
|
+
return value;
|
|
5725
|
+
}
|
|
5726
|
+
if (!isEnum(this.schema, fieldDef.type)) {
|
|
5727
|
+
return value;
|
|
5728
|
+
}
|
|
5729
|
+
const enumDef = getEnum(this.schema, fieldDef.type);
|
|
5730
|
+
if (!enumDef) {
|
|
5731
|
+
return value;
|
|
5732
|
+
}
|
|
5733
|
+
const enumValueMapping = this.getEnumValueMapping(enumDef);
|
|
5734
|
+
if (this.isOperationNode(value) && ValueNode.is(value) && typeof value.value === "string") {
|
|
5735
|
+
const mappedValue = enumValueMapping[value.value];
|
|
5736
|
+
if (mappedValue) {
|
|
5737
|
+
return ValueNode.create(mappedValue);
|
|
5738
|
+
}
|
|
5739
|
+
} else if (typeof value === "string") {
|
|
5740
|
+
const mappedValue = enumValueMapping[value];
|
|
5741
|
+
if (mappedValue) {
|
|
5742
|
+
return mappedValue;
|
|
5743
|
+
}
|
|
5744
|
+
}
|
|
5745
|
+
return value;
|
|
5746
|
+
}
|
|
5747
|
+
processEnumSelection(selection, fieldName) {
|
|
5748
|
+
const { alias, node } = stripAlias(selection);
|
|
5749
|
+
const fieldScope = this.resolveFieldFromScopes(fieldName);
|
|
5750
|
+
if (!fieldScope || !fieldScope.model) {
|
|
5751
|
+
return selection;
|
|
5752
|
+
}
|
|
5753
|
+
const aliasName = alias && IdentifierNode.is(alias) ? alias.name : fieldName;
|
|
5754
|
+
const fieldDef = getField(this.schema, fieldScope.model, fieldName);
|
|
5755
|
+
if (!fieldDef) {
|
|
5756
|
+
return selection;
|
|
5757
|
+
}
|
|
5758
|
+
const enumDef = getEnum(this.schema, fieldDef.type);
|
|
5759
|
+
if (!enumDef) {
|
|
5760
|
+
return selection;
|
|
5761
|
+
}
|
|
5762
|
+
const enumValueMapping = this.getEnumValueMapping(enumDef);
|
|
5763
|
+
if (Object.keys(enumValueMapping).length === 0) {
|
|
5764
|
+
return selection;
|
|
5765
|
+
}
|
|
5766
|
+
const eb = expressionBuilder3();
|
|
5767
|
+
const caseBuilder = eb.case();
|
|
5768
|
+
let caseWhen;
|
|
5769
|
+
for (const [key, value] of Object.entries(enumValueMapping)) {
|
|
5770
|
+
if (!caseWhen) {
|
|
5771
|
+
caseWhen = caseBuilder.when(new ExpressionWrapper(node), "=", value).then(key);
|
|
5772
|
+
} else {
|
|
5773
|
+
caseWhen = caseWhen.when(new ExpressionWrapper(node), "=", value).then(key);
|
|
5774
|
+
}
|
|
5775
|
+
}
|
|
5776
|
+
const finalExpr = caseWhen.else(eb.cast(new ExpressionWrapper(node), "text")).end();
|
|
5777
|
+
if (aliasName) {
|
|
5778
|
+
return finalExpr.as(aliasName).toOperationNode();
|
|
5779
|
+
} else {
|
|
5780
|
+
return finalExpr.toOperationNode();
|
|
5781
|
+
}
|
|
5782
|
+
}
|
|
5517
5783
|
};
|
|
5518
5784
|
|
|
5519
5785
|
// src/client/executor/zenstack-query-executor.ts
|
|
@@ -5529,7 +5795,8 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends DefaultQueryExe
|
|
|
5529
5795
|
nameMapper;
|
|
5530
5796
|
constructor(client, driver, compiler, adapter, connectionProvider, plugins = [], suppressMutationHooks = false) {
|
|
5531
5797
|
super(compiler, adapter, connectionProvider, plugins), this.client = client, this.driver = driver, this.compiler = compiler, this.connectionProvider = connectionProvider, this.suppressMutationHooks = suppressMutationHooks;
|
|
5532
|
-
if (
|
|
5798
|
+
if (client.$schema.provider.type === "postgresql" || // postgres queries need to be schema-qualified
|
|
5799
|
+
this.schemaHasMappedNames(client.$schema)) {
|
|
5533
5800
|
this.nameMapper = new QueryNameMapper(client.$schema);
|
|
5534
5801
|
}
|
|
5535
5802
|
}
|
|
@@ -5548,7 +5815,7 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends DefaultQueryExe
|
|
|
5548
5815
|
get options() {
|
|
5549
5816
|
return this.client.$options;
|
|
5550
5817
|
}
|
|
5551
|
-
executeQuery(compiledQuery
|
|
5818
|
+
executeQuery(compiledQuery) {
|
|
5552
5819
|
const queryParams = compiledQuery.$raw ? compiledQuery.parameters : void 0;
|
|
5553
5820
|
return this.provideConnection(async (connection) => {
|
|
5554
5821
|
let startedTx = false;
|
|
@@ -5559,7 +5826,7 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends DefaultQueryExe
|
|
|
5559
5826
|
});
|
|
5560
5827
|
startedTx = true;
|
|
5561
5828
|
}
|
|
5562
|
-
const result = await this.proceedQueryWithKyselyInterceptors(connection, compiledQuery.query, queryParams,
|
|
5829
|
+
const result = await this.proceedQueryWithKyselyInterceptors(connection, compiledQuery.query, queryParams, compiledQuery.queryId);
|
|
5563
5830
|
if (startedTx) {
|
|
5564
5831
|
await this.driver.commitTransaction(connection);
|
|
5565
5832
|
}
|
|
@@ -5568,11 +5835,10 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends DefaultQueryExe
|
|
|
5568
5835
|
if (startedTx) {
|
|
5569
5836
|
await this.driver.rollbackTransaction(connection);
|
|
5570
5837
|
}
|
|
5571
|
-
if (err instanceof
|
|
5838
|
+
if (err instanceof ORMError) {
|
|
5572
5839
|
throw err;
|
|
5573
5840
|
} else {
|
|
5574
|
-
|
|
5575
|
-
throw new QueryError(message, err);
|
|
5841
|
+
throw createDBQueryError("Failed to execute query", err, compiledQuery.sql, compiledQuery.parameters);
|
|
5576
5842
|
}
|
|
5577
5843
|
}
|
|
5578
5844
|
});
|
|
@@ -5623,7 +5889,7 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends DefaultQueryExe
|
|
|
5623
5889
|
let compiled;
|
|
5624
5890
|
if (this.suppressMutationHooks || !this.isMutationNode(query) || !this.hasEntityMutationPlugins) {
|
|
5625
5891
|
const finalQuery2 = this.processNameMapping(query);
|
|
5626
|
-
compiled = this.compileQuery(finalQuery2);
|
|
5892
|
+
compiled = this.compileQuery(finalQuery2, queryId);
|
|
5627
5893
|
if (parameters) {
|
|
5628
5894
|
compiled = {
|
|
5629
5895
|
...compiled,
|
|
@@ -5641,7 +5907,7 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends DefaultQueryExe
|
|
|
5641
5907
|
};
|
|
5642
5908
|
}
|
|
5643
5909
|
const finalQuery = this.processNameMapping(query);
|
|
5644
|
-
compiled = this.compileQuery(finalQuery);
|
|
5910
|
+
compiled = this.compileQuery(finalQuery, queryId);
|
|
5645
5911
|
if (parameters) {
|
|
5646
5912
|
compiled = {
|
|
5647
5913
|
...compiled,
|
|
@@ -5730,7 +5996,7 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends DefaultQueryExe
|
|
|
5730
5996
|
invariant9(TableNode3.is(tableNode), "DeleteQueryNode must use a TableNode");
|
|
5731
5997
|
return tableNode.table.identifier.name;
|
|
5732
5998
|
}).otherwise((node) => {
|
|
5733
|
-
throw
|
|
5999
|
+
throw createInternalError(`Invalid query node: ${node}`);
|
|
5734
6000
|
});
|
|
5735
6001
|
}
|
|
5736
6002
|
async callBeforeMutationHooks(queryNode, mutationInfo, loadBeforeMutationEntities, client, queryId) {
|
|
@@ -5795,7 +6061,7 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends DefaultQueryExe
|
|
|
5795
6061
|
...selectQueryNode,
|
|
5796
6062
|
where: this.andNodes(selectQueryNode.where, where)
|
|
5797
6063
|
};
|
|
5798
|
-
const compiled = this.compileQuery(selectQueryNode);
|
|
6064
|
+
const compiled = this.compileQuery(selectQueryNode, createQueryId2());
|
|
5799
6065
|
const result = await connection.executeQuery(compiled);
|
|
5800
6066
|
return result.rows;
|
|
5801
6067
|
}
|
|
@@ -5826,7 +6092,7 @@ __export(functions_exports, {
|
|
|
5826
6092
|
startsWith: () => startsWith
|
|
5827
6093
|
});
|
|
5828
6094
|
import { invariant as invariant10, lowerCaseFirst, upperCaseFirst } from "@zenstackhq/common-helpers";
|
|
5829
|
-
import { sql as sql5, ValueNode } from "kysely";
|
|
6095
|
+
import { sql as sql5, ValueNode as ValueNode2 } from "kysely";
|
|
5830
6096
|
import { match as match15 } from "ts-pattern";
|
|
5831
6097
|
var contains = /* @__PURE__ */ __name((eb, args, context) => textMatch(eb, args, context, "contains"), "contains");
|
|
5832
6098
|
var search = /* @__PURE__ */ __name((_eb, _args) => {
|
|
@@ -5935,7 +6201,7 @@ var currentOperation = /* @__PURE__ */ __name((_eb, args, { operation }) => {
|
|
|
5935
6201
|
}, "currentOperation");
|
|
5936
6202
|
function processCasing(casing, result, model) {
|
|
5937
6203
|
const opNode = casing.toOperationNode();
|
|
5938
|
-
invariant10(
|
|
6204
|
+
invariant10(ValueNode2.is(opNode) && typeof opNode.value === "string", '"casting" parameter must be a string value');
|
|
5939
6205
|
result = match15(opNode.value).with("original", () => model).with("upper", () => result.toUpperCase()).with("lower", () => result.toLowerCase()).with("capitalize", () => upperCaseFirst(result)).with("uncapitalize", () => lowerCaseFirst(result)).otherwise(() => {
|
|
5940
6206
|
throw new Error(`Invalid casing value: ${opNode.value}. Must be "original", "upper", "lower", "capitalize", or "uncapitalize".`);
|
|
5941
6207
|
});
|
|
@@ -5947,7 +6213,7 @@ function readBoolean(expr, defaultValue) {
|
|
|
5947
6213
|
return defaultValue;
|
|
5948
6214
|
}
|
|
5949
6215
|
const opNode = expr.toOperationNode();
|
|
5950
|
-
invariant10(
|
|
6216
|
+
invariant10(ValueNode2.is(opNode), "expression must be a literal value");
|
|
5951
6217
|
return !!opNode.value;
|
|
5952
6218
|
}
|
|
5953
6219
|
__name(readBoolean, "readBoolean");
|
|
@@ -5971,7 +6237,22 @@ var SchemaDbPusher = class {
|
|
|
5971
6237
|
await this.kysely.transaction().execute(async (tx) => {
|
|
5972
6238
|
if (this.schema.enums && this.schema.provider.type === "postgresql") {
|
|
5973
6239
|
for (const [name, enumDef] of Object.entries(this.schema.enums)) {
|
|
5974
|
-
|
|
6240
|
+
let enumValues;
|
|
6241
|
+
if (enumDef.fields) {
|
|
6242
|
+
enumValues = Object.values(enumDef.fields).map((f) => {
|
|
6243
|
+
const mapAttr = f.attributes?.find((a) => a.name === "@map");
|
|
6244
|
+
if (!mapAttr || !mapAttr.args?.[0]) {
|
|
6245
|
+
return f.name;
|
|
6246
|
+
} else {
|
|
6247
|
+
const mappedName = schema_exports.ExpressionUtils.getLiteralValue(mapAttr.args[0].value);
|
|
6248
|
+
invariant11(mappedName && typeof mappedName === "string", `Invalid @map attribute for enum field ${f.name}`);
|
|
6249
|
+
return mappedName;
|
|
6250
|
+
}
|
|
6251
|
+
});
|
|
6252
|
+
} else {
|
|
6253
|
+
enumValues = Object.values(enumDef.values);
|
|
6254
|
+
}
|
|
6255
|
+
const createEnum = tx.schema.createType(name).asEnum(enumValues);
|
|
5975
6256
|
await createEnum.execute();
|
|
5976
6257
|
}
|
|
5977
6258
|
}
|
|
@@ -6450,7 +6731,7 @@ var ClientImpl = class _ClientImpl {
|
|
|
6450
6731
|
}
|
|
6451
6732
|
async handleProc(name, args) {
|
|
6452
6733
|
if (!("procedures" in this.$options) || !this.$options || typeof this.$options.procedures !== "object") {
|
|
6453
|
-
throw
|
|
6734
|
+
throw createConfigError("Procedures are not configured for the client.");
|
|
6454
6735
|
}
|
|
6455
6736
|
const procOptions = this.$options.procedures;
|
|
6456
6737
|
if (!procOptions[name] || typeof procOptions[name] !== "function") {
|
|
@@ -6581,7 +6862,7 @@ function createModelCrudHandler(client, model, inputValidator, resultProcessor)
|
|
|
6581
6862
|
const _handler = txClient ? handler.withClient(txClient) : handler;
|
|
6582
6863
|
const r = await _handler.handle(operation, _args);
|
|
6583
6864
|
if (!r && throwIfNoResult) {
|
|
6584
|
-
throw
|
|
6865
|
+
throw createNotFoundError(model);
|
|
6585
6866
|
}
|
|
6586
6867
|
let result;
|
|
6587
6868
|
if (r && postProcess) {
|
|
@@ -6976,6 +7257,18 @@ var DefaultOperationNodeVisitor = class extends OperationNodeVisitor {
|
|
|
6976
7257
|
visitOutput(node) {
|
|
6977
7258
|
this.defaultVisit(node);
|
|
6978
7259
|
}
|
|
7260
|
+
visitRenameConstraint(node) {
|
|
7261
|
+
this.defaultVisit(node);
|
|
7262
|
+
}
|
|
7263
|
+
visitRefreshMaterializedView(node) {
|
|
7264
|
+
this.defaultVisit(node);
|
|
7265
|
+
}
|
|
7266
|
+
visitOrAction(node) {
|
|
7267
|
+
this.defaultVisit(node);
|
|
7268
|
+
}
|
|
7269
|
+
visitCollate(node) {
|
|
7270
|
+
this.defaultVisit(node);
|
|
7271
|
+
}
|
|
6979
7272
|
};
|
|
6980
7273
|
|
|
6981
7274
|
// src/utils/schema-utils.ts
|
|
@@ -7038,18 +7331,14 @@ export {
|
|
|
7038
7331
|
BaseCrudDialect,
|
|
7039
7332
|
CRUD,
|
|
7040
7333
|
CRUD_EXT,
|
|
7041
|
-
InputValidationError,
|
|
7042
|
-
InternalError,
|
|
7043
7334
|
kysely_utils_exports as KyselyUtils,
|
|
7044
|
-
|
|
7045
|
-
|
|
7335
|
+
ORMError,
|
|
7336
|
+
ORMErrorReason,
|
|
7046
7337
|
query_utils_exports as QueryUtils,
|
|
7047
|
-
RejectedByPolicyError,
|
|
7048
7338
|
RejectedByPolicyReason,
|
|
7049
7339
|
schema_utils_exports as SchemaUtils,
|
|
7050
7340
|
TransactionIsolationLevel,
|
|
7051
7341
|
ZenStackClient,
|
|
7052
|
-
ZenStackError,
|
|
7053
7342
|
definePlugin,
|
|
7054
7343
|
getCrudDialect
|
|
7055
7344
|
};
|