@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
|
@@ -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;
|
|
@@ -1015,6 +1063,9 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
|
|
|
1015
1063
|
return `ARRAY[${values.map((v) => typeof v === "string" ? `'${v}'` : v)}]`;
|
|
1016
1064
|
}
|
|
1017
1065
|
}
|
|
1066
|
+
get supportInsertWithDefault() {
|
|
1067
|
+
return true;
|
|
1068
|
+
}
|
|
1018
1069
|
};
|
|
1019
1070
|
|
|
1020
1071
|
// src/client/crud/dialects/sqlite.ts
|
|
@@ -1045,11 +1096,11 @@ var SqliteCrudDialect = class extends BaseCrudDialect {
|
|
|
1045
1096
|
buildRelationSelection(query, model, relationField, parentAlias, payload) {
|
|
1046
1097
|
return query.select((eb) => this.buildRelationJSON(model, eb, relationField, parentAlias, payload).as(relationField));
|
|
1047
1098
|
}
|
|
1048
|
-
buildRelationJSON(model, eb, relationField,
|
|
1099
|
+
buildRelationJSON(model, eb, relationField, parentAlias, payload) {
|
|
1049
1100
|
const relationFieldDef = requireField(this.schema, model, relationField);
|
|
1050
1101
|
const relationModel = relationFieldDef.type;
|
|
1051
1102
|
const relationModelDef = requireModel(this.schema, relationModel);
|
|
1052
|
-
const subQueryName = `${
|
|
1103
|
+
const subQueryName = `${parentAlias}$${relationField}`;
|
|
1053
1104
|
let tbl = eb.selectFrom(() => {
|
|
1054
1105
|
let subQuery = this.buildSelectModel(eb, relationModel);
|
|
1055
1106
|
subQuery = this.buildSelectAllFields(relationModel, subQuery, typeof payload === "object" ? payload?.omit : void 0);
|
|
@@ -1073,14 +1124,14 @@ var SqliteCrudDialect = class extends BaseCrudDialect {
|
|
|
1073
1124
|
const relationIds = getIdFields(this.schema, relationModel);
|
|
1074
1125
|
invariant3(parentIds.length === 1, "many-to-many relation must have exactly one id field");
|
|
1075
1126
|
invariant3(relationIds.length === 1, "many-to-many relation must have exactly one id field");
|
|
1076
|
-
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}`)));
|
|
1077
1128
|
} else {
|
|
1078
1129
|
const { keyPairs, ownedByModel } = getRelationForeignKeyFieldPairs(this.schema, model, relationField);
|
|
1079
1130
|
keyPairs.forEach(({ fk, pk }) => {
|
|
1080
1131
|
if (ownedByModel) {
|
|
1081
|
-
subQuery = subQuery.whereRef(`${relationModel}.${pk}`, "=", `${
|
|
1132
|
+
subQuery = subQuery.whereRef(`${relationModel}.${pk}`, "=", `${parentAlias}.${fk}`);
|
|
1082
1133
|
} else {
|
|
1083
|
-
subQuery = subQuery.whereRef(`${relationModel}.${fk}`, "=", `${
|
|
1134
|
+
subQuery = subQuery.whereRef(`${relationModel}.${fk}`, "=", `${parentAlias}.${pk}`);
|
|
1084
1135
|
}
|
|
1085
1136
|
});
|
|
1086
1137
|
}
|
|
@@ -1102,24 +1153,32 @@ var SqliteCrudDialect = class extends BaseCrudDialect {
|
|
|
1102
1153
|
]).flatMap((v) => v));
|
|
1103
1154
|
} else if (payload.select) {
|
|
1104
1155
|
objArgs.push(...Object.entries(payload.select).filter(([, value]) => value).map(([field, value]) => {
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
const subJson = this.buildRelationJSON(relationModel, eb, field, `${parentName}$${relationField}`, value);
|
|
1156
|
+
if (field === "_count") {
|
|
1157
|
+
const subJson = this.buildCountJson(relationModel, eb, `${parentAlias}$${relationField}`, value);
|
|
1108
1158
|
return [
|
|
1109
1159
|
sql3.lit(field),
|
|
1110
1160
|
subJson
|
|
1111
1161
|
];
|
|
1112
1162
|
} else {
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
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
|
+
}
|
|
1117
1176
|
}
|
|
1118
1177
|
}).flatMap((v) => v));
|
|
1119
1178
|
}
|
|
1120
1179
|
if (typeof payload === "object" && payload.include && typeof payload.include === "object") {
|
|
1121
1180
|
objArgs.push(...Object.entries(payload.include).filter(([, value]) => value).map(([field, value]) => {
|
|
1122
|
-
const subJson = this.buildRelationJSON(relationModel, eb, field, `${
|
|
1181
|
+
const subJson = this.buildRelationJSON(relationModel, eb, field, `${parentAlias}$${relationField}`, value);
|
|
1123
1182
|
return [
|
|
1124
1183
|
sql3.lit(field),
|
|
1125
1184
|
subJson
|
|
@@ -1169,6 +1228,9 @@ var SqliteCrudDialect = class extends BaseCrudDialect {
|
|
|
1169
1228
|
buildArrayLiteralSQL(_values) {
|
|
1170
1229
|
throw new Error("SQLite does not support array literals");
|
|
1171
1230
|
}
|
|
1231
|
+
get supportInsertWithDefault() {
|
|
1232
|
+
return false;
|
|
1233
|
+
}
|
|
1172
1234
|
};
|
|
1173
1235
|
|
|
1174
1236
|
// src/client/crud/dialects/index.ts
|