@zenstackhq/runtime 3.0.0-alpha.18 → 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-Cn4sSxg8.d.cts → contract-CxX20JtH.d.cts} +16 -10
- package/dist/{contract-Cn4sSxg8.d.ts → contract-CxX20JtH.d.ts} +16 -10
- package/dist/index.cjs +207 -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 +207 -140
- package/dist/index.js.map +1 -1
- package/dist/plugins/policy/index.cjs +98 -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 +98 -42
- package/dist/plugins/policy/index.js.map +1 -1
- package/package.json +9 -9
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as kysely from 'kysely';
|
|
2
|
-
import { R as RuntimePlugin, V as OnKyselyQueryArgs } from '../../contract-
|
|
2
|
+
import { R as RuntimePlugin, V as OnKyselyQueryArgs } from '../../contract-CxX20JtH.cjs';
|
|
3
3
|
import { SchemaDef } from '@zenstackhq/sdk/schema';
|
|
4
4
|
import 'decimal.js';
|
|
5
5
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as kysely from 'kysely';
|
|
2
|
-
import { R as RuntimePlugin, V as OnKyselyQueryArgs } from '../../contract-
|
|
2
|
+
import { R as RuntimePlugin, V as OnKyselyQueryArgs } from '../../contract-CxX20JtH.js';
|
|
3
3
|
import { SchemaDef } from '@zenstackhq/sdk/schema';
|
|
4
4
|
import 'decimal.js';
|
|
5
5
|
|
|
@@ -126,6 +126,10 @@ var InternalError = class extends Error {
|
|
|
126
126
|
};
|
|
127
127
|
|
|
128
128
|
// src/client/query-utils.ts
|
|
129
|
+
function getModel(schema, model) {
|
|
130
|
+
return schema.models[model];
|
|
131
|
+
}
|
|
132
|
+
__name(getModel, "getModel");
|
|
129
133
|
function requireModel(schema, model) {
|
|
130
134
|
const matchedName = Object.keys(schema.models).find((k) => k.toLowerCase() === model.toLowerCase());
|
|
131
135
|
if (!matchedName) {
|
|
@@ -134,6 +138,11 @@ function requireModel(schema, model) {
|
|
|
134
138
|
return schema.models[matchedName];
|
|
135
139
|
}
|
|
136
140
|
__name(requireModel, "requireModel");
|
|
141
|
+
function getField(schema, model, field) {
|
|
142
|
+
const modelDef = getModel(schema, model);
|
|
143
|
+
return modelDef?.fields[field];
|
|
144
|
+
}
|
|
145
|
+
__name(getField, "getField");
|
|
137
146
|
function requireField(schema, model, field) {
|
|
138
147
|
const modelDef = requireModel(schema, model);
|
|
139
148
|
if (!modelDef.fields[field]) {
|
|
@@ -188,13 +197,13 @@ function getRelationForeignKeyFieldPairs(schema, model, relationField) {
|
|
|
188
197
|
}
|
|
189
198
|
__name(getRelationForeignKeyFieldPairs, "getRelationForeignKeyFieldPairs");
|
|
190
199
|
function isRelationField(schema, model, field) {
|
|
191
|
-
const fieldDef =
|
|
192
|
-
return !!fieldDef
|
|
200
|
+
const fieldDef = getField(schema, model, field);
|
|
201
|
+
return !!fieldDef?.relation;
|
|
193
202
|
}
|
|
194
203
|
__name(isRelationField, "isRelationField");
|
|
195
204
|
function isInheritedField(schema, model, field) {
|
|
196
|
-
const fieldDef =
|
|
197
|
-
return !!fieldDef
|
|
205
|
+
const fieldDef = getField(schema, model, field);
|
|
206
|
+
return !!fieldDef?.originModel;
|
|
198
207
|
}
|
|
199
208
|
__name(isInheritedField, "isInheritedField");
|
|
200
209
|
function getUniqueFields(schema, model) {
|
|
@@ -564,7 +573,7 @@ var BaseCrudDialect = class {
|
|
|
564
573
|
buildLiteralFilter(eb, lhs, type, rhs) {
|
|
565
574
|
return eb(lhs, "=", rhs !== null && rhs !== void 0 ? this.transformPrimitive(rhs, type, false) : rhs);
|
|
566
575
|
}
|
|
567
|
-
buildStandardFilter(eb, type, payload, lhs, getRhs, recurse, throwIfInvalid = false, onlyForKeys = void 0) {
|
|
576
|
+
buildStandardFilter(eb, type, payload, lhs, getRhs, recurse, throwIfInvalid = false, onlyForKeys = void 0, excludeKeys = []) {
|
|
568
577
|
if (payload === null || !isPlainObject(payload)) {
|
|
569
578
|
return {
|
|
570
579
|
conditions: [
|
|
@@ -579,6 +588,9 @@ var BaseCrudDialect = class {
|
|
|
579
588
|
if (onlyForKeys && !onlyForKeys.includes(op)) {
|
|
580
589
|
continue;
|
|
581
590
|
}
|
|
591
|
+
if (excludeKeys.includes(op)) {
|
|
592
|
+
continue;
|
|
593
|
+
}
|
|
582
594
|
const rhs = Array.isArray(value) ? value.map(getRhs) : getRhs(value);
|
|
583
595
|
const condition = match(op).with("equals", () => rhs === null ? eb(lhs, "is", null) : eb(lhs, "=", rhs)).with("in", () => {
|
|
584
596
|
invariant(Array.isArray(rhs), "right hand side must be an array");
|
|
@@ -612,21 +624,20 @@ var BaseCrudDialect = class {
|
|
|
612
624
|
};
|
|
613
625
|
}
|
|
614
626
|
buildStringFilter(eb, fieldRef, payload) {
|
|
615
|
-
let
|
|
616
|
-
if (payload && typeof payload === "object" && "mode" in payload
|
|
617
|
-
|
|
618
|
-
fieldRef = eb.fn("lower", [
|
|
619
|
-
fieldRef
|
|
620
|
-
]);
|
|
627
|
+
let mode;
|
|
628
|
+
if (payload && typeof payload === "object" && "mode" in payload) {
|
|
629
|
+
mode = payload.mode;
|
|
621
630
|
}
|
|
622
|
-
const { conditions, consumedKeys } = this.buildStandardFilter(eb, "String", payload,
|
|
631
|
+
const { conditions, consumedKeys } = this.buildStandardFilter(eb, "String", payload, mode === "insensitive" ? eb.fn("lower", [
|
|
632
|
+
fieldRef
|
|
633
|
+
]) : fieldRef, (value) => this.prepStringCasing(eb, value, mode), (value) => this.buildStringFilter(eb, fieldRef, value));
|
|
623
634
|
if (payload && typeof payload === "object") {
|
|
624
635
|
for (const [key, value] of Object.entries(payload)) {
|
|
625
636
|
if (key === "mode" || consumedKeys.includes(key)) {
|
|
626
637
|
continue;
|
|
627
638
|
}
|
|
628
|
-
const condition = match(key).with("contains", () => insensitive ? eb(fieldRef, "ilike", sql.
|
|
629
|
-
throw new
|
|
639
|
+
const condition = match(key).with("contains", () => mode === "insensitive" ? eb(fieldRef, "ilike", sql.val(`%${value}%`)) : eb(fieldRef, "like", sql.val(`%${value}%`))).with("startsWith", () => mode === "insensitive" ? eb(fieldRef, "ilike", sql.val(`${value}%`)) : eb(fieldRef, "like", sql.val(`${value}%`))).with("endsWith", () => mode === "insensitive" ? eb(fieldRef, "ilike", sql.val(`%${value}`)) : eb(fieldRef, "like", sql.val(`%${value}`))).otherwise(() => {
|
|
640
|
+
throw new QueryError(`Invalid string filter key: ${key}`);
|
|
630
641
|
});
|
|
631
642
|
if (condition) {
|
|
632
643
|
conditions.push(condition);
|
|
@@ -635,15 +646,18 @@ var BaseCrudDialect = class {
|
|
|
635
646
|
}
|
|
636
647
|
return this.and(eb, ...conditions);
|
|
637
648
|
}
|
|
638
|
-
prepStringCasing(eb, value,
|
|
649
|
+
prepStringCasing(eb, value, mode) {
|
|
650
|
+
if (!mode || mode === "default") {
|
|
651
|
+
return value === null ? value : sql.val(value);
|
|
652
|
+
}
|
|
639
653
|
if (typeof value === "string") {
|
|
640
|
-
return
|
|
641
|
-
sql.
|
|
642
|
-
])
|
|
654
|
+
return eb.fn("lower", [
|
|
655
|
+
sql.val(value)
|
|
656
|
+
]);
|
|
643
657
|
} else if (Array.isArray(value)) {
|
|
644
|
-
return value.map((v) => this.prepStringCasing(eb, v,
|
|
658
|
+
return value.map((v) => this.prepStringCasing(eb, v, mode));
|
|
645
659
|
} else {
|
|
646
|
-
return value === null ? null : sql.
|
|
660
|
+
return value === null ? null : sql.val(value);
|
|
647
661
|
}
|
|
648
662
|
}
|
|
649
663
|
buildNumberFilter(eb, fieldRef, type, payload) {
|
|
@@ -805,6 +819,32 @@ var BaseCrudDialect = class {
|
|
|
805
819
|
});
|
|
806
820
|
return query;
|
|
807
821
|
}
|
|
822
|
+
buildCountJson(model, eb, parentAlias, payload) {
|
|
823
|
+
const modelDef = requireModel(this.schema, model);
|
|
824
|
+
const toManyRelations = Object.entries(modelDef.fields).filter(([, field]) => field.relation && field.array);
|
|
825
|
+
const selections = payload === true ? {
|
|
826
|
+
select: toManyRelations.reduce((acc, [field]) => {
|
|
827
|
+
acc[field] = true;
|
|
828
|
+
return acc;
|
|
829
|
+
}, {})
|
|
830
|
+
} : payload;
|
|
831
|
+
const jsonObject = {};
|
|
832
|
+
for (const [field, value] of Object.entries(selections.select)) {
|
|
833
|
+
const fieldDef = requireField(this.schema, model, field);
|
|
834
|
+
const fieldModel = fieldDef.type;
|
|
835
|
+
const joinPairs = buildJoinPairs(this.schema, model, parentAlias, field, fieldModel);
|
|
836
|
+
let fieldCountQuery = eb.selectFrom(fieldModel).select(eb.fn.countAll().as(`_count$${field}`));
|
|
837
|
+
for (const [left, right] of joinPairs) {
|
|
838
|
+
fieldCountQuery = fieldCountQuery.whereRef(left, "=", right);
|
|
839
|
+
}
|
|
840
|
+
if (value && typeof value === "object" && "where" in value && value.where && typeof value.where === "object") {
|
|
841
|
+
const filter = this.buildFilter(eb, fieldModel, fieldModel, value.where);
|
|
842
|
+
fieldCountQuery = fieldCountQuery.where(filter);
|
|
843
|
+
}
|
|
844
|
+
jsonObject[field] = fieldCountQuery;
|
|
845
|
+
}
|
|
846
|
+
return this.buildJsonObject(eb, jsonObject);
|
|
847
|
+
}
|
|
808
848
|
// #endregion
|
|
809
849
|
// #region utils
|
|
810
850
|
negateSort(sort, negated) {
|
|
@@ -933,7 +973,7 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
|
|
|
933
973
|
});
|
|
934
974
|
return qb;
|
|
935
975
|
}
|
|
936
|
-
buildRelationObjectArgs(relationModel, relationField, eb, payload,
|
|
976
|
+
buildRelationObjectArgs(relationModel, relationField, eb, payload, parentAlias) {
|
|
937
977
|
const relationModelDef = requireModel(this.schema, relationModel);
|
|
938
978
|
const objArgs = [];
|
|
939
979
|
const descendantModels = getDelegateDescendantModels(this.schema, relationModel);
|
|
@@ -949,20 +989,28 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
|
|
|
949
989
|
buildFieldRef(this.schema, relationModel, field, this.options, eb)
|
|
950
990
|
]).flatMap((v) => v));
|
|
951
991
|
} else if (payload.select) {
|
|
952
|
-
objArgs.push(...Object.entries(payload.select).filter(([, value]) => value).map(([field]) => {
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
992
|
+
objArgs.push(...Object.entries(payload.select).filter(([, value]) => value).map(([field, value]) => {
|
|
993
|
+
if (field === "_count") {
|
|
994
|
+
const subJson = this.buildCountJson(relationModel, eb, `${parentAlias}$${relationField}`, value);
|
|
995
|
+
return [
|
|
996
|
+
sql2.lit(field),
|
|
997
|
+
subJson
|
|
998
|
+
];
|
|
999
|
+
} else {
|
|
1000
|
+
const fieldDef = requireField(this.schema, relationModel, field);
|
|
1001
|
+
const fieldValue = fieldDef.relation ? eb.ref(`${parentAlias}$${relationField}$${field}.$j`) : buildFieldRef(this.schema, relationModel, field, this.options, eb);
|
|
1002
|
+
return [
|
|
1003
|
+
sql2.lit(field),
|
|
1004
|
+
fieldValue
|
|
1005
|
+
];
|
|
1006
|
+
}
|
|
959
1007
|
}).flatMap((v) => v));
|
|
960
1008
|
}
|
|
961
1009
|
if (typeof payload === "object" && payload.include && typeof payload.include === "object") {
|
|
962
1010
|
objArgs.push(...Object.entries(payload.include).filter(([, value]) => value).map(([field]) => [
|
|
963
1011
|
sql2.lit(field),
|
|
964
1012
|
// reference the synthesized JSON field
|
|
965
|
-
eb.ref(`${
|
|
1013
|
+
eb.ref(`${parentAlias}$${relationField}$${field}.$j`)
|
|
966
1014
|
]).flatMap((v) => v));
|
|
967
1015
|
}
|
|
968
1016
|
return objArgs;
|
|
@@ -1048,11 +1096,11 @@ var SqliteCrudDialect = class extends BaseCrudDialect {
|
|
|
1048
1096
|
buildRelationSelection(query, model, relationField, parentAlias, payload) {
|
|
1049
1097
|
return query.select((eb) => this.buildRelationJSON(model, eb, relationField, parentAlias, payload).as(relationField));
|
|
1050
1098
|
}
|
|
1051
|
-
buildRelationJSON(model, eb, relationField,
|
|
1099
|
+
buildRelationJSON(model, eb, relationField, parentAlias, payload) {
|
|
1052
1100
|
const relationFieldDef = requireField(this.schema, model, relationField);
|
|
1053
1101
|
const relationModel = relationFieldDef.type;
|
|
1054
1102
|
const relationModelDef = requireModel(this.schema, relationModel);
|
|
1055
|
-
const subQueryName = `${
|
|
1103
|
+
const subQueryName = `${parentAlias}$${relationField}`;
|
|
1056
1104
|
let tbl = eb.selectFrom(() => {
|
|
1057
1105
|
let subQuery = this.buildSelectModel(eb, relationModel);
|
|
1058
1106
|
subQuery = this.buildSelectAllFields(relationModel, subQuery, typeof payload === "object" ? payload?.omit : void 0);
|
|
@@ -1076,14 +1124,14 @@ var SqliteCrudDialect = class extends BaseCrudDialect {
|
|
|
1076
1124
|
const relationIds = getIdFields(this.schema, relationModel);
|
|
1077
1125
|
invariant3(parentIds.length === 1, "many-to-many relation must have exactly one id field");
|
|
1078
1126
|
invariant3(relationIds.length === 1, "many-to-many relation must have exactly one id field");
|
|
1079
|
-
subQuery = subQuery.where(eb(eb.ref(`${relationModel}.${relationIds[0]}`), "in", eb.selectFrom(m2m.joinTable).select(`${m2m.joinTable}.${m2m.otherFkName}`).whereRef(`${
|
|
1127
|
+
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}`)));
|
|
1080
1128
|
} else {
|
|
1081
1129
|
const { keyPairs, ownedByModel } = getRelationForeignKeyFieldPairs(this.schema, model, relationField);
|
|
1082
1130
|
keyPairs.forEach(({ fk, pk }) => {
|
|
1083
1131
|
if (ownedByModel) {
|
|
1084
|
-
subQuery = subQuery.whereRef(`${relationModel}.${pk}`, "=", `${
|
|
1132
|
+
subQuery = subQuery.whereRef(`${relationModel}.${pk}`, "=", `${parentAlias}.${fk}`);
|
|
1085
1133
|
} else {
|
|
1086
|
-
subQuery = subQuery.whereRef(`${relationModel}.${fk}`, "=", `${
|
|
1134
|
+
subQuery = subQuery.whereRef(`${relationModel}.${fk}`, "=", `${parentAlias}.${pk}`);
|
|
1087
1135
|
}
|
|
1088
1136
|
});
|
|
1089
1137
|
}
|
|
@@ -1105,24 +1153,32 @@ var SqliteCrudDialect = class extends BaseCrudDialect {
|
|
|
1105
1153
|
]).flatMap((v) => v));
|
|
1106
1154
|
} else if (payload.select) {
|
|
1107
1155
|
objArgs.push(...Object.entries(payload.select).filter(([, value]) => value).map(([field, value]) => {
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
const subJson = this.buildRelationJSON(relationModel, eb, field, `${parentName}$${relationField}`, value);
|
|
1156
|
+
if (field === "_count") {
|
|
1157
|
+
const subJson = this.buildCountJson(relationModel, eb, `${parentAlias}$${relationField}`, value);
|
|
1111
1158
|
return [
|
|
1112
1159
|
sql3.lit(field),
|
|
1113
1160
|
subJson
|
|
1114
1161
|
];
|
|
1115
1162
|
} else {
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1163
|
+
const fieldDef = requireField(this.schema, relationModel, field);
|
|
1164
|
+
if (fieldDef.relation) {
|
|
1165
|
+
const subJson = this.buildRelationJSON(relationModel, eb, field, `${parentAlias}$${relationField}`, value);
|
|
1166
|
+
return [
|
|
1167
|
+
sql3.lit(field),
|
|
1168
|
+
subJson
|
|
1169
|
+
];
|
|
1170
|
+
} else {
|
|
1171
|
+
return [
|
|
1172
|
+
sql3.lit(field),
|
|
1173
|
+
buildFieldRef(this.schema, relationModel, field, this.options, eb)
|
|
1174
|
+
];
|
|
1175
|
+
}
|
|
1120
1176
|
}
|
|
1121
1177
|
}).flatMap((v) => v));
|
|
1122
1178
|
}
|
|
1123
1179
|
if (typeof payload === "object" && payload.include && typeof payload.include === "object") {
|
|
1124
1180
|
objArgs.push(...Object.entries(payload.include).filter(([, value]) => value).map(([field, value]) => {
|
|
1125
|
-
const subJson = this.buildRelationJSON(relationModel, eb, field, `${
|
|
1181
|
+
const subJson = this.buildRelationJSON(relationModel, eb, field, `${parentAlias}$${relationField}`, value);
|
|
1126
1182
|
return [
|
|
1127
1183
|
sql3.lit(field),
|
|
1128
1184
|
subJson
|