@zenstackhq/runtime 3.0.0-alpha.17 → 3.0.0-alpha.19
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-C6xcEG6Q.d.cts → contract-CxX20JtH.d.cts} +74 -64
- package/dist/{contract-C6xcEG6Q.d.ts → contract-CxX20JtH.d.ts} +74 -64
- package/dist/index.cjs +236 -140
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +236 -140
- package/dist/index.js.map +1 -1
- package/dist/plugins/policy/index.cjs +104 -42
- 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 +104 -42
- package/dist/plugins/policy/index.js.map +1 -1
- package/package.json +9 -9
|
@@ -151,6 +151,10 @@ var InternalError = class extends Error {
|
|
|
151
151
|
};
|
|
152
152
|
|
|
153
153
|
// src/client/query-utils.ts
|
|
154
|
+
function getModel(schema, model) {
|
|
155
|
+
return schema.models[model];
|
|
156
|
+
}
|
|
157
|
+
__name(getModel, "getModel");
|
|
154
158
|
function requireModel(schema, model) {
|
|
155
159
|
const matchedName = Object.keys(schema.models).find((k) => k.toLowerCase() === model.toLowerCase());
|
|
156
160
|
if (!matchedName) {
|
|
@@ -159,6 +163,11 @@ function requireModel(schema, model) {
|
|
|
159
163
|
return schema.models[matchedName];
|
|
160
164
|
}
|
|
161
165
|
__name(requireModel, "requireModel");
|
|
166
|
+
function getField(schema, model, field) {
|
|
167
|
+
const modelDef = getModel(schema, model);
|
|
168
|
+
return modelDef?.fields[field];
|
|
169
|
+
}
|
|
170
|
+
__name(getField, "getField");
|
|
162
171
|
function requireField(schema, model, field) {
|
|
163
172
|
const modelDef = requireModel(schema, model);
|
|
164
173
|
if (!modelDef.fields[field]) {
|
|
@@ -213,13 +222,13 @@ function getRelationForeignKeyFieldPairs(schema, model, relationField) {
|
|
|
213
222
|
}
|
|
214
223
|
__name(getRelationForeignKeyFieldPairs, "getRelationForeignKeyFieldPairs");
|
|
215
224
|
function isRelationField(schema, model, field) {
|
|
216
|
-
const fieldDef =
|
|
217
|
-
return !!fieldDef
|
|
225
|
+
const fieldDef = getField(schema, model, field);
|
|
226
|
+
return !!fieldDef?.relation;
|
|
218
227
|
}
|
|
219
228
|
__name(isRelationField, "isRelationField");
|
|
220
229
|
function isInheritedField(schema, model, field) {
|
|
221
|
-
const fieldDef =
|
|
222
|
-
return !!fieldDef
|
|
230
|
+
const fieldDef = getField(schema, model, field);
|
|
231
|
+
return !!fieldDef?.originModel;
|
|
223
232
|
}
|
|
224
233
|
__name(isInheritedField, "isInheritedField");
|
|
225
234
|
function getUniqueFields(schema, model) {
|
|
@@ -589,7 +598,7 @@ var BaseCrudDialect = class {
|
|
|
589
598
|
buildLiteralFilter(eb, lhs, type, rhs) {
|
|
590
599
|
return eb(lhs, "=", rhs !== null && rhs !== void 0 ? this.transformPrimitive(rhs, type, false) : rhs);
|
|
591
600
|
}
|
|
592
|
-
buildStandardFilter(eb, type, payload, lhs, getRhs, recurse, throwIfInvalid = false, onlyForKeys = void 0) {
|
|
601
|
+
buildStandardFilter(eb, type, payload, lhs, getRhs, recurse, throwIfInvalid = false, onlyForKeys = void 0, excludeKeys = []) {
|
|
593
602
|
if (payload === null || !(0, import_common_helpers.isPlainObject)(payload)) {
|
|
594
603
|
return {
|
|
595
604
|
conditions: [
|
|
@@ -604,6 +613,9 @@ var BaseCrudDialect = class {
|
|
|
604
613
|
if (onlyForKeys && !onlyForKeys.includes(op)) {
|
|
605
614
|
continue;
|
|
606
615
|
}
|
|
616
|
+
if (excludeKeys.includes(op)) {
|
|
617
|
+
continue;
|
|
618
|
+
}
|
|
607
619
|
const rhs = Array.isArray(value) ? value.map(getRhs) : getRhs(value);
|
|
608
620
|
const condition = (0, import_ts_pattern.match)(op).with("equals", () => rhs === null ? eb(lhs, "is", null) : eb(lhs, "=", rhs)).with("in", () => {
|
|
609
621
|
(0, import_common_helpers.invariant)(Array.isArray(rhs), "right hand side must be an array");
|
|
@@ -637,21 +649,20 @@ var BaseCrudDialect = class {
|
|
|
637
649
|
};
|
|
638
650
|
}
|
|
639
651
|
buildStringFilter(eb, fieldRef, payload) {
|
|
640
|
-
let
|
|
641
|
-
if (payload && typeof payload === "object" && "mode" in payload
|
|
642
|
-
|
|
643
|
-
fieldRef = eb.fn("lower", [
|
|
644
|
-
fieldRef
|
|
645
|
-
]);
|
|
652
|
+
let mode;
|
|
653
|
+
if (payload && typeof payload === "object" && "mode" in payload) {
|
|
654
|
+
mode = payload.mode;
|
|
646
655
|
}
|
|
647
|
-
const { conditions, consumedKeys } = this.buildStandardFilter(eb, "String", payload,
|
|
656
|
+
const { conditions, consumedKeys } = this.buildStandardFilter(eb, "String", payload, mode === "insensitive" ? eb.fn("lower", [
|
|
657
|
+
fieldRef
|
|
658
|
+
]) : fieldRef, (value) => this.prepStringCasing(eb, value, mode), (value) => this.buildStringFilter(eb, fieldRef, value));
|
|
648
659
|
if (payload && typeof payload === "object") {
|
|
649
660
|
for (const [key, value] of Object.entries(payload)) {
|
|
650
661
|
if (key === "mode" || consumedKeys.includes(key)) {
|
|
651
662
|
continue;
|
|
652
663
|
}
|
|
653
|
-
const condition = (0, import_ts_pattern.match)(key).with("contains", () => insensitive ? eb(fieldRef, "ilike", import_kysely.sql.
|
|
654
|
-
throw new
|
|
664
|
+
const condition = (0, import_ts_pattern.match)(key).with("contains", () => mode === "insensitive" ? eb(fieldRef, "ilike", import_kysely.sql.val(`%${value}%`)) : eb(fieldRef, "like", import_kysely.sql.val(`%${value}%`))).with("startsWith", () => mode === "insensitive" ? eb(fieldRef, "ilike", import_kysely.sql.val(`${value}%`)) : eb(fieldRef, "like", import_kysely.sql.val(`${value}%`))).with("endsWith", () => mode === "insensitive" ? eb(fieldRef, "ilike", import_kysely.sql.val(`%${value}`)) : eb(fieldRef, "like", import_kysely.sql.val(`%${value}`))).otherwise(() => {
|
|
665
|
+
throw new QueryError(`Invalid string filter key: ${key}`);
|
|
655
666
|
});
|
|
656
667
|
if (condition) {
|
|
657
668
|
conditions.push(condition);
|
|
@@ -660,15 +671,18 @@ var BaseCrudDialect = class {
|
|
|
660
671
|
}
|
|
661
672
|
return this.and(eb, ...conditions);
|
|
662
673
|
}
|
|
663
|
-
prepStringCasing(eb, value,
|
|
674
|
+
prepStringCasing(eb, value, mode) {
|
|
675
|
+
if (!mode || mode === "default") {
|
|
676
|
+
return value === null ? value : import_kysely.sql.val(value);
|
|
677
|
+
}
|
|
664
678
|
if (typeof value === "string") {
|
|
665
|
-
return
|
|
666
|
-
import_kysely.sql.
|
|
667
|
-
])
|
|
679
|
+
return eb.fn("lower", [
|
|
680
|
+
import_kysely.sql.val(value)
|
|
681
|
+
]);
|
|
668
682
|
} else if (Array.isArray(value)) {
|
|
669
|
-
return value.map((v) => this.prepStringCasing(eb, v,
|
|
683
|
+
return value.map((v) => this.prepStringCasing(eb, v, mode));
|
|
670
684
|
} else {
|
|
671
|
-
return value === null ? null : import_kysely.sql.
|
|
685
|
+
return value === null ? null : import_kysely.sql.val(value);
|
|
672
686
|
}
|
|
673
687
|
}
|
|
674
688
|
buildNumberFilter(eb, fieldRef, type, payload) {
|
|
@@ -830,6 +844,32 @@ var BaseCrudDialect = class {
|
|
|
830
844
|
});
|
|
831
845
|
return query;
|
|
832
846
|
}
|
|
847
|
+
buildCountJson(model, eb, parentAlias, payload) {
|
|
848
|
+
const modelDef = requireModel(this.schema, model);
|
|
849
|
+
const toManyRelations = Object.entries(modelDef.fields).filter(([, field]) => field.relation && field.array);
|
|
850
|
+
const selections = payload === true ? {
|
|
851
|
+
select: toManyRelations.reduce((acc, [field]) => {
|
|
852
|
+
acc[field] = true;
|
|
853
|
+
return acc;
|
|
854
|
+
}, {})
|
|
855
|
+
} : payload;
|
|
856
|
+
const jsonObject = {};
|
|
857
|
+
for (const [field, value] of Object.entries(selections.select)) {
|
|
858
|
+
const fieldDef = requireField(this.schema, model, field);
|
|
859
|
+
const fieldModel = fieldDef.type;
|
|
860
|
+
const joinPairs = buildJoinPairs(this.schema, model, parentAlias, field, fieldModel);
|
|
861
|
+
let fieldCountQuery = eb.selectFrom(fieldModel).select(eb.fn.countAll().as(`_count$${field}`));
|
|
862
|
+
for (const [left, right] of joinPairs) {
|
|
863
|
+
fieldCountQuery = fieldCountQuery.whereRef(left, "=", right);
|
|
864
|
+
}
|
|
865
|
+
if (value && typeof value === "object" && "where" in value && value.where && typeof value.where === "object") {
|
|
866
|
+
const filter = this.buildFilter(eb, fieldModel, fieldModel, value.where);
|
|
867
|
+
fieldCountQuery = fieldCountQuery.where(filter);
|
|
868
|
+
}
|
|
869
|
+
jsonObject[field] = fieldCountQuery;
|
|
870
|
+
}
|
|
871
|
+
return this.buildJsonObject(eb, jsonObject);
|
|
872
|
+
}
|
|
833
873
|
// #endregion
|
|
834
874
|
// #region utils
|
|
835
875
|
negateSort(sort, negated) {
|
|
@@ -958,7 +998,7 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
|
|
|
958
998
|
});
|
|
959
999
|
return qb;
|
|
960
1000
|
}
|
|
961
|
-
buildRelationObjectArgs(relationModel, relationField, eb, payload,
|
|
1001
|
+
buildRelationObjectArgs(relationModel, relationField, eb, payload, parentAlias) {
|
|
962
1002
|
const relationModelDef = requireModel(this.schema, relationModel);
|
|
963
1003
|
const objArgs = [];
|
|
964
1004
|
const descendantModels = getDelegateDescendantModels(this.schema, relationModel);
|
|
@@ -974,20 +1014,28 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
|
|
|
974
1014
|
buildFieldRef(this.schema, relationModel, field, this.options, eb)
|
|
975
1015
|
]).flatMap((v) => v));
|
|
976
1016
|
} else if (payload.select) {
|
|
977
|
-
objArgs.push(...Object.entries(payload.select).filter(([, value]) => value).map(([field]) => {
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
1017
|
+
objArgs.push(...Object.entries(payload.select).filter(([, value]) => value).map(([field, value]) => {
|
|
1018
|
+
if (field === "_count") {
|
|
1019
|
+
const subJson = this.buildCountJson(relationModel, eb, `${parentAlias}$${relationField}`, value);
|
|
1020
|
+
return [
|
|
1021
|
+
import_kysely2.sql.lit(field),
|
|
1022
|
+
subJson
|
|
1023
|
+
];
|
|
1024
|
+
} else {
|
|
1025
|
+
const fieldDef = requireField(this.schema, relationModel, field);
|
|
1026
|
+
const fieldValue = fieldDef.relation ? eb.ref(`${parentAlias}$${relationField}$${field}.$j`) : buildFieldRef(this.schema, relationModel, field, this.options, eb);
|
|
1027
|
+
return [
|
|
1028
|
+
import_kysely2.sql.lit(field),
|
|
1029
|
+
fieldValue
|
|
1030
|
+
];
|
|
1031
|
+
}
|
|
984
1032
|
}).flatMap((v) => v));
|
|
985
1033
|
}
|
|
986
1034
|
if (typeof payload === "object" && payload.include && typeof payload.include === "object") {
|
|
987
1035
|
objArgs.push(...Object.entries(payload.include).filter(([, value]) => value).map(([field]) => [
|
|
988
1036
|
import_kysely2.sql.lit(field),
|
|
989
1037
|
// reference the synthesized JSON field
|
|
990
|
-
eb.ref(`${
|
|
1038
|
+
eb.ref(`${parentAlias}$${relationField}$${field}.$j`)
|
|
991
1039
|
]).flatMap((v) => v));
|
|
992
1040
|
}
|
|
993
1041
|
return objArgs;
|
|
@@ -1040,6 +1088,9 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
|
|
|
1040
1088
|
return `ARRAY[${values.map((v) => typeof v === "string" ? `'${v}'` : v)}]`;
|
|
1041
1089
|
}
|
|
1042
1090
|
}
|
|
1091
|
+
get supportInsertWithDefault() {
|
|
1092
|
+
return true;
|
|
1093
|
+
}
|
|
1043
1094
|
};
|
|
1044
1095
|
|
|
1045
1096
|
// src/client/crud/dialects/sqlite.ts
|
|
@@ -1070,11 +1121,11 @@ var SqliteCrudDialect = class extends BaseCrudDialect {
|
|
|
1070
1121
|
buildRelationSelection(query, model, relationField, parentAlias, payload) {
|
|
1071
1122
|
return query.select((eb) => this.buildRelationJSON(model, eb, relationField, parentAlias, payload).as(relationField));
|
|
1072
1123
|
}
|
|
1073
|
-
buildRelationJSON(model, eb, relationField,
|
|
1124
|
+
buildRelationJSON(model, eb, relationField, parentAlias, payload) {
|
|
1074
1125
|
const relationFieldDef = requireField(this.schema, model, relationField);
|
|
1075
1126
|
const relationModel = relationFieldDef.type;
|
|
1076
1127
|
const relationModelDef = requireModel(this.schema, relationModel);
|
|
1077
|
-
const subQueryName = `${
|
|
1128
|
+
const subQueryName = `${parentAlias}$${relationField}`;
|
|
1078
1129
|
let tbl = eb.selectFrom(() => {
|
|
1079
1130
|
let subQuery = this.buildSelectModel(eb, relationModel);
|
|
1080
1131
|
subQuery = this.buildSelectAllFields(relationModel, subQuery, typeof payload === "object" ? payload?.omit : void 0);
|
|
@@ -1098,14 +1149,14 @@ var SqliteCrudDialect = class extends BaseCrudDialect {
|
|
|
1098
1149
|
const relationIds = getIdFields(this.schema, relationModel);
|
|
1099
1150
|
(0, import_common_helpers3.invariant)(parentIds.length === 1, "many-to-many relation must have exactly one id field");
|
|
1100
1151
|
(0, import_common_helpers3.invariant)(relationIds.length === 1, "many-to-many relation must have exactly one id field");
|
|
1101
|
-
subQuery = subQuery.where(eb(eb.ref(`${relationModel}.${relationIds[0]}`), "in", eb.selectFrom(m2m.joinTable).select(`${m2m.joinTable}.${m2m.otherFkName}`).whereRef(`${
|
|
1152
|
+
subQuery = subQuery.where(eb(eb.ref(`${relationModel}.${relationIds[0]}`), "in", eb.selectFrom(m2m.joinTable).select(`${m2m.joinTable}.${m2m.otherFkName}`).whereRef(`${parentAlias}.${parentIds[0]}`, "=", `${m2m.joinTable}.${m2m.parentFkName}`)));
|
|
1102
1153
|
} else {
|
|
1103
1154
|
const { keyPairs, ownedByModel } = getRelationForeignKeyFieldPairs(this.schema, model, relationField);
|
|
1104
1155
|
keyPairs.forEach(({ fk, pk }) => {
|
|
1105
1156
|
if (ownedByModel) {
|
|
1106
|
-
subQuery = subQuery.whereRef(`${relationModel}.${pk}`, "=", `${
|
|
1157
|
+
subQuery = subQuery.whereRef(`${relationModel}.${pk}`, "=", `${parentAlias}.${fk}`);
|
|
1107
1158
|
} else {
|
|
1108
|
-
subQuery = subQuery.whereRef(`${relationModel}.${fk}`, "=", `${
|
|
1159
|
+
subQuery = subQuery.whereRef(`${relationModel}.${fk}`, "=", `${parentAlias}.${pk}`);
|
|
1109
1160
|
}
|
|
1110
1161
|
});
|
|
1111
1162
|
}
|
|
@@ -1127,24 +1178,32 @@ var SqliteCrudDialect = class extends BaseCrudDialect {
|
|
|
1127
1178
|
]).flatMap((v) => v));
|
|
1128
1179
|
} else if (payload.select) {
|
|
1129
1180
|
objArgs.push(...Object.entries(payload.select).filter(([, value]) => value).map(([field, value]) => {
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
const subJson = this.buildRelationJSON(relationModel, eb, field, `${parentName}$${relationField}`, value);
|
|
1181
|
+
if (field === "_count") {
|
|
1182
|
+
const subJson = this.buildCountJson(relationModel, eb, `${parentAlias}$${relationField}`, value);
|
|
1133
1183
|
return [
|
|
1134
1184
|
import_kysely3.sql.lit(field),
|
|
1135
1185
|
subJson
|
|
1136
1186
|
];
|
|
1137
1187
|
} else {
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1188
|
+
const fieldDef = requireField(this.schema, relationModel, field);
|
|
1189
|
+
if (fieldDef.relation) {
|
|
1190
|
+
const subJson = this.buildRelationJSON(relationModel, eb, field, `${parentAlias}$${relationField}`, value);
|
|
1191
|
+
return [
|
|
1192
|
+
import_kysely3.sql.lit(field),
|
|
1193
|
+
subJson
|
|
1194
|
+
];
|
|
1195
|
+
} else {
|
|
1196
|
+
return [
|
|
1197
|
+
import_kysely3.sql.lit(field),
|
|
1198
|
+
buildFieldRef(this.schema, relationModel, field, this.options, eb)
|
|
1199
|
+
];
|
|
1200
|
+
}
|
|
1142
1201
|
}
|
|
1143
1202
|
}).flatMap((v) => v));
|
|
1144
1203
|
}
|
|
1145
1204
|
if (typeof payload === "object" && payload.include && typeof payload.include === "object") {
|
|
1146
1205
|
objArgs.push(...Object.entries(payload.include).filter(([, value]) => value).map(([field, value]) => {
|
|
1147
|
-
const subJson = this.buildRelationJSON(relationModel, eb, field, `${
|
|
1206
|
+
const subJson = this.buildRelationJSON(relationModel, eb, field, `${parentAlias}$${relationField}`, value);
|
|
1148
1207
|
return [
|
|
1149
1208
|
import_kysely3.sql.lit(field),
|
|
1150
1209
|
subJson
|
|
@@ -1194,6 +1253,9 @@ var SqliteCrudDialect = class extends BaseCrudDialect {
|
|
|
1194
1253
|
buildArrayLiteralSQL(_values) {
|
|
1195
1254
|
throw new Error("SQLite does not support array literals");
|
|
1196
1255
|
}
|
|
1256
|
+
get supportInsertWithDefault() {
|
|
1257
|
+
return false;
|
|
1258
|
+
}
|
|
1197
1259
|
};
|
|
1198
1260
|
|
|
1199
1261
|
// src/client/crud/dialects/index.ts
|