prisma-guard 1.4.0 → 1.5.0
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/runtime/index.cjs +506 -95
- package/dist/runtime/index.cjs.map +1 -1
- package/dist/runtime/index.js +506 -95
- package/dist/runtime/index.js.map +1 -1
- package/package.json +1 -1
package/dist/runtime/index.js
CHANGED
|
@@ -704,7 +704,24 @@ function mergeUniqueWhereForced(where, forced) {
|
|
|
704
704
|
return result;
|
|
705
705
|
}
|
|
706
706
|
function applyBuiltShape(built, body, isUniqueMethod) {
|
|
707
|
-
|
|
707
|
+
let parseable = body;
|
|
708
|
+
if (built.forcedOnlyWhereKeys.size > 0 && isPlainObject(body)) {
|
|
709
|
+
const bodyObj = body;
|
|
710
|
+
if (isPlainObject(bodyObj.where)) {
|
|
711
|
+
const where = { ...bodyObj.where };
|
|
712
|
+
let stripped = false;
|
|
713
|
+
for (const key of built.forcedOnlyWhereKeys) {
|
|
714
|
+
if (key in where) {
|
|
715
|
+
delete where[key];
|
|
716
|
+
stripped = true;
|
|
717
|
+
}
|
|
718
|
+
}
|
|
719
|
+
if (stripped) {
|
|
720
|
+
parseable = { ...bodyObj, where };
|
|
721
|
+
}
|
|
722
|
+
}
|
|
723
|
+
}
|
|
724
|
+
const validated = built.zodSchema.parse(parseable);
|
|
708
725
|
if (hasWhereForced(built.forcedWhere)) {
|
|
709
726
|
validated.where = isUniqueMethod ? mergeUniqueWhereForced(
|
|
710
727
|
validated.where,
|
|
@@ -928,7 +945,12 @@ function validateUniqueEquality(model, where, method, uniqueMap, typeMap) {
|
|
|
928
945
|
|
|
929
946
|
// src/runtime/query-builder-where.ts
|
|
930
947
|
var UNSUPPORTED_WHERE_TYPES = /* @__PURE__ */ new Set(["Json", "Bytes"]);
|
|
931
|
-
var STRING_MODE_OPS = /* @__PURE__ */ new Set([
|
|
948
|
+
var STRING_MODE_OPS = /* @__PURE__ */ new Set([
|
|
949
|
+
"contains",
|
|
950
|
+
"startsWith",
|
|
951
|
+
"endsWith",
|
|
952
|
+
"equals"
|
|
953
|
+
]);
|
|
932
954
|
var MAX_WHERE_DEPTH = 10;
|
|
933
955
|
function safeStringify(v) {
|
|
934
956
|
if (typeof v === "bigint")
|
|
@@ -998,9 +1020,7 @@ function mergeScalarConditions(target, source) {
|
|
|
998
1020
|
continue;
|
|
999
1021
|
}
|
|
1000
1022
|
if (!forcedValuesEqual(existing, ops)) {
|
|
1001
|
-
throw new ShapeError(
|
|
1002
|
-
`Conflicting forced where values for "${field}"`
|
|
1003
|
-
);
|
|
1023
|
+
throw new ShapeError(`Conflicting forced where values for "${field}"`);
|
|
1004
1024
|
}
|
|
1005
1025
|
}
|
|
1006
1026
|
}
|
|
@@ -1014,8 +1034,14 @@ function mergeRelationForcedMaps(target, source) {
|
|
|
1014
1034
|
if (!target[relName][op]) {
|
|
1015
1035
|
target[relName][op] = forced;
|
|
1016
1036
|
} else {
|
|
1017
|
-
mergeScalarConditions(
|
|
1018
|
-
|
|
1037
|
+
mergeScalarConditions(
|
|
1038
|
+
target[relName][op].conditions,
|
|
1039
|
+
forced.conditions
|
|
1040
|
+
);
|
|
1041
|
+
mergeRelationForcedMaps(
|
|
1042
|
+
target[relName][op].relations,
|
|
1043
|
+
forced.relations
|
|
1044
|
+
);
|
|
1019
1045
|
}
|
|
1020
1046
|
}
|
|
1021
1047
|
}
|
|
@@ -1067,20 +1093,38 @@ function createWhereBuilder(typeMap, enumMap, scalarBase) {
|
|
|
1067
1093
|
`${fieldMeta.type} field "${key}" cannot be used in where filters`
|
|
1068
1094
|
);
|
|
1069
1095
|
}
|
|
1070
|
-
processScalarField(
|
|
1096
|
+
processScalarField(
|
|
1097
|
+
key,
|
|
1098
|
+
value,
|
|
1099
|
+
model,
|
|
1100
|
+
fieldMeta,
|
|
1101
|
+
fieldSchemas,
|
|
1102
|
+
scalarConditions
|
|
1103
|
+
);
|
|
1071
1104
|
}
|
|
1072
1105
|
const schema = Object.keys(fieldSchemas).length > 0 ? z4.object(fieldSchemas).strict().optional() : null;
|
|
1106
|
+
const forcedOnlyKeys = /* @__PURE__ */ new Set();
|
|
1107
|
+
for (const key of Object.keys(whereConfig)) {
|
|
1108
|
+
if (COMBINATOR_KEYS.has(key))
|
|
1109
|
+
continue;
|
|
1110
|
+
if (!(key in fieldSchemas)) {
|
|
1111
|
+
forcedOnlyKeys.add(key);
|
|
1112
|
+
}
|
|
1113
|
+
}
|
|
1073
1114
|
return {
|
|
1074
1115
|
schema,
|
|
1075
1116
|
forced: {
|
|
1076
1117
|
conditions: scalarConditions,
|
|
1077
1118
|
relations: relationForced
|
|
1078
|
-
}
|
|
1119
|
+
},
|
|
1120
|
+
forcedOnlyKeys
|
|
1079
1121
|
};
|
|
1080
1122
|
}
|
|
1081
1123
|
function processCombinator(key, value, model, fieldSchemas, parentConditions, parentRelations, depth) {
|
|
1082
1124
|
if (!isPlainObject(value)) {
|
|
1083
|
-
throw new ShapeError(
|
|
1125
|
+
throw new ShapeError(
|
|
1126
|
+
`"${key}" in where shape must be an object defining allowed fields`
|
|
1127
|
+
);
|
|
1084
1128
|
}
|
|
1085
1129
|
const result = buildWhereSchema(model, value, depth + 1);
|
|
1086
1130
|
if (!result.schema && !hasWhereForced(result.forced)) {
|
|
@@ -1121,7 +1165,9 @@ function createWhereBuilder(typeMap, enumMap, scalarBase) {
|
|
|
1121
1165
|
}
|
|
1122
1166
|
function processRelationFilter(key, value, fieldMeta, model, fieldSchemas, parentRelations, depth) {
|
|
1123
1167
|
if (!isPlainObject(value)) {
|
|
1124
|
-
throw new ShapeError(
|
|
1168
|
+
throw new ShapeError(
|
|
1169
|
+
`Relation filter for "${key}" must be an object with operators (some, every, none, is, isNot)`
|
|
1170
|
+
);
|
|
1125
1171
|
}
|
|
1126
1172
|
const allowedOps = fieldMeta.isList ? TO_MANY_RELATION_OPS : TO_ONE_RELATION_OPS;
|
|
1127
1173
|
if (Object.keys(value).length === 0) {
|
|
@@ -1154,7 +1200,9 @@ function createWhereBuilder(typeMap, enumMap, scalarBase) {
|
|
|
1154
1200
|
if (!hasWhereForced(nested.forced)) {
|
|
1155
1201
|
opSchemas[op] = nested.schema.refine(
|
|
1156
1202
|
(v) => v === void 0 || Object.keys(v).length > 0,
|
|
1157
|
-
{
|
|
1203
|
+
{
|
|
1204
|
+
message: `Relation filter "${key}.${op}" requires at least one condition`
|
|
1205
|
+
}
|
|
1158
1206
|
);
|
|
1159
1207
|
} else {
|
|
1160
1208
|
opSchemas[op] = nested.schema;
|
|
@@ -1175,7 +1223,9 @@ function createWhereBuilder(typeMap, enumMap, scalarBase) {
|
|
|
1175
1223
|
const opObjSchema = z4.object(opSchemas).strict();
|
|
1176
1224
|
if (Object.keys(opForced).length === 0) {
|
|
1177
1225
|
fieldSchemas[key] = opObjSchema.refine(
|
|
1178
|
-
(v) => clientOpKeys.some(
|
|
1226
|
+
(v) => clientOpKeys.some(
|
|
1227
|
+
(k) => v[k] !== void 0
|
|
1228
|
+
),
|
|
1179
1229
|
{ message: `At least one relation operator required for "${key}"` }
|
|
1180
1230
|
).optional();
|
|
1181
1231
|
} else {
|
|
@@ -1197,9 +1247,21 @@ function createWhereBuilder(typeMap, enumMap, scalarBase) {
|
|
|
1197
1247
|
let hasClientOps = false;
|
|
1198
1248
|
let hasStringModeOp = false;
|
|
1199
1249
|
const clientOpKeys = [];
|
|
1250
|
+
let modeConfigValue = void 0;
|
|
1251
|
+
let hasModeConfig = false;
|
|
1200
1252
|
for (const [op, opValue] of Object.entries(operators)) {
|
|
1253
|
+
if (op === "mode") {
|
|
1254
|
+
hasModeConfig = true;
|
|
1255
|
+
modeConfigValue = opValue;
|
|
1256
|
+
continue;
|
|
1257
|
+
}
|
|
1201
1258
|
if (opValue === true) {
|
|
1202
|
-
opSchemas[op] = createOperatorSchema(
|
|
1259
|
+
opSchemas[op] = createOperatorSchema(
|
|
1260
|
+
fieldMeta,
|
|
1261
|
+
op,
|
|
1262
|
+
enumMap,
|
|
1263
|
+
scalarBase
|
|
1264
|
+
).optional();
|
|
1203
1265
|
hasClientOps = true;
|
|
1204
1266
|
clientOpKeys.push(op);
|
|
1205
1267
|
if (fieldMeta.type === "String" && !fieldMeta.isList && STRING_MODE_OPS.has(op)) {
|
|
@@ -1207,7 +1269,12 @@ function createWhereBuilder(typeMap, enumMap, scalarBase) {
|
|
|
1207
1269
|
}
|
|
1208
1270
|
} else {
|
|
1209
1271
|
const actualOpValue = isForcedValue(opValue) ? opValue.value : opValue;
|
|
1210
|
-
const opSchema = createOperatorSchema(
|
|
1272
|
+
const opSchema = createOperatorSchema(
|
|
1273
|
+
fieldMeta,
|
|
1274
|
+
op,
|
|
1275
|
+
enumMap,
|
|
1276
|
+
scalarBase
|
|
1277
|
+
);
|
|
1211
1278
|
let parsed;
|
|
1212
1279
|
try {
|
|
1213
1280
|
parsed = opSchema.parse(actualOpValue);
|
|
@@ -1217,21 +1284,54 @@ function createWhereBuilder(typeMap, enumMap, scalarBase) {
|
|
|
1217
1284
|
);
|
|
1218
1285
|
}
|
|
1219
1286
|
fieldForced[op] = parsed;
|
|
1287
|
+
if (fieldMeta.type === "String" && !fieldMeta.isList && STRING_MODE_OPS.has(op)) {
|
|
1288
|
+
hasStringModeOp = true;
|
|
1289
|
+
}
|
|
1220
1290
|
}
|
|
1221
1291
|
}
|
|
1222
1292
|
if (!hasClientOps && Object.keys(fieldForced).length === 0) {
|
|
1293
|
+
if (hasModeConfig) {
|
|
1294
|
+
throw new ShapeError(
|
|
1295
|
+
`Where field "${fieldName}" on model "${model}" has "mode" but no operators. Add at least one operator (contains, startsWith, endsWith, equals).`
|
|
1296
|
+
);
|
|
1297
|
+
}
|
|
1223
1298
|
throw new ShapeError(
|
|
1224
1299
|
`Empty operator config for where field "${fieldName}" on model "${model}". Define at least one operator.`
|
|
1225
1300
|
);
|
|
1226
1301
|
}
|
|
1227
|
-
if (
|
|
1302
|
+
if (hasModeConfig) {
|
|
1303
|
+
if (!hasStringModeOp) {
|
|
1304
|
+
throw new ShapeError(
|
|
1305
|
+
`"mode" on where field "${fieldName}" on model "${model}" requires a compatible String operator (contains, startsWith, endsWith, equals)`
|
|
1306
|
+
);
|
|
1307
|
+
}
|
|
1308
|
+
if (modeConfigValue === true) {
|
|
1309
|
+
opSchemas["mode"] = z4.enum(["default", "insensitive"]).optional();
|
|
1310
|
+
} else {
|
|
1311
|
+
const actualModeValue = isForcedValue(modeConfigValue) ? modeConfigValue.value : modeConfigValue;
|
|
1312
|
+
const modeSchema = z4.enum(["default", "insensitive"]);
|
|
1313
|
+
let parsed;
|
|
1314
|
+
try {
|
|
1315
|
+
parsed = modeSchema.parse(actualModeValue);
|
|
1316
|
+
} catch (err) {
|
|
1317
|
+
throw new ShapeError(
|
|
1318
|
+
`Invalid forced value for "${model}.${fieldName}.mode": ${err.message}`
|
|
1319
|
+
);
|
|
1320
|
+
}
|
|
1321
|
+
fieldForced["mode"] = parsed;
|
|
1322
|
+
}
|
|
1323
|
+
} else if (hasStringModeOp) {
|
|
1228
1324
|
opSchemas["mode"] = z4.enum(["default", "insensitive"]).optional();
|
|
1229
1325
|
}
|
|
1230
1326
|
if (hasClientOps) {
|
|
1231
1327
|
const opObj = z4.object(opSchemas).strict();
|
|
1232
1328
|
fieldSchemas[fieldName] = opObj.refine(
|
|
1233
|
-
(v) => clientOpKeys.some(
|
|
1234
|
-
|
|
1329
|
+
(v) => clientOpKeys.some(
|
|
1330
|
+
(k) => v[k] !== void 0
|
|
1331
|
+
),
|
|
1332
|
+
{
|
|
1333
|
+
message: `At least one operator required for where field "${fieldName}"`
|
|
1334
|
+
}
|
|
1235
1335
|
).optional();
|
|
1236
1336
|
}
|
|
1237
1337
|
if (Object.keys(fieldForced).length > 0) {
|
|
@@ -1897,19 +1997,77 @@ function createProjectionBuilder(typeMap, enumMap, deps) {
|
|
|
1897
1997
|
|
|
1898
1998
|
// src/runtime/query-builder.ts
|
|
1899
1999
|
var METHOD_ALLOWED_ARGS = {
|
|
1900
|
-
findMany: /* @__PURE__ */ new Set([
|
|
1901
|
-
|
|
1902
|
-
|
|
2000
|
+
findMany: /* @__PURE__ */ new Set([
|
|
2001
|
+
"where",
|
|
2002
|
+
"include",
|
|
2003
|
+
"select",
|
|
2004
|
+
"orderBy",
|
|
2005
|
+
"cursor",
|
|
2006
|
+
"take",
|
|
2007
|
+
"skip",
|
|
2008
|
+
"distinct"
|
|
2009
|
+
]),
|
|
2010
|
+
findFirst: /* @__PURE__ */ new Set([
|
|
2011
|
+
"where",
|
|
2012
|
+
"include",
|
|
2013
|
+
"select",
|
|
2014
|
+
"orderBy",
|
|
2015
|
+
"cursor",
|
|
2016
|
+
"take",
|
|
2017
|
+
"skip",
|
|
2018
|
+
"distinct"
|
|
2019
|
+
]),
|
|
2020
|
+
findFirstOrThrow: /* @__PURE__ */ new Set([
|
|
2021
|
+
"where",
|
|
2022
|
+
"include",
|
|
2023
|
+
"select",
|
|
2024
|
+
"orderBy",
|
|
2025
|
+
"cursor",
|
|
2026
|
+
"take",
|
|
2027
|
+
"skip",
|
|
2028
|
+
"distinct"
|
|
2029
|
+
]),
|
|
1903
2030
|
findUnique: /* @__PURE__ */ new Set(["where", "include", "select"]),
|
|
1904
2031
|
findUniqueOrThrow: /* @__PURE__ */ new Set(["where", "include", "select"]),
|
|
1905
2032
|
count: /* @__PURE__ */ new Set(["where", "select", "cursor", "orderBy", "skip", "take"]),
|
|
1906
|
-
aggregate: /* @__PURE__ */ new Set([
|
|
1907
|
-
|
|
2033
|
+
aggregate: /* @__PURE__ */ new Set([
|
|
2034
|
+
"where",
|
|
2035
|
+
"orderBy",
|
|
2036
|
+
"cursor",
|
|
2037
|
+
"take",
|
|
2038
|
+
"skip",
|
|
2039
|
+
"_count",
|
|
2040
|
+
"_avg",
|
|
2041
|
+
"_sum",
|
|
2042
|
+
"_min",
|
|
2043
|
+
"_max"
|
|
2044
|
+
]),
|
|
2045
|
+
groupBy: /* @__PURE__ */ new Set([
|
|
2046
|
+
"where",
|
|
2047
|
+
"by",
|
|
2048
|
+
"having",
|
|
2049
|
+
"_count",
|
|
2050
|
+
"_avg",
|
|
2051
|
+
"_sum",
|
|
2052
|
+
"_min",
|
|
2053
|
+
"_max",
|
|
2054
|
+
"orderBy",
|
|
2055
|
+
"take",
|
|
2056
|
+
"skip"
|
|
2057
|
+
])
|
|
1908
2058
|
};
|
|
1909
|
-
var UNIQUE_WHERE_METHODS = /* @__PURE__ */ new Set([
|
|
2059
|
+
var UNIQUE_WHERE_METHODS = /* @__PURE__ */ new Set([
|
|
2060
|
+
"findUnique",
|
|
2061
|
+
"findUniqueOrThrow"
|
|
2062
|
+
]);
|
|
1910
2063
|
function createQueryBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
|
|
1911
2064
|
const whereBuilder = createWhereBuilder(typeMap, enumMap, scalarBase);
|
|
1912
|
-
const argsBuilder = createArgsBuilder(
|
|
2065
|
+
const argsBuilder = createArgsBuilder(
|
|
2066
|
+
typeMap,
|
|
2067
|
+
enumMap,
|
|
2068
|
+
uniqueMap,
|
|
2069
|
+
scalarBase
|
|
2070
|
+
);
|
|
1913
2071
|
const projectionBuilder = createProjectionBuilder(typeMap, enumMap, {
|
|
1914
2072
|
buildWhereSchema: whereBuilder.buildWhereSchema,
|
|
1915
2073
|
buildOrderBySchema: argsBuilder.buildOrderBySchema,
|
|
@@ -1934,7 +2092,9 @@ function createQueryBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
|
|
|
1934
2092
|
throw new ShapeError(`${method} shape must define "where"`);
|
|
1935
2093
|
}
|
|
1936
2094
|
if (shape.include && shape.select) {
|
|
1937
|
-
throw new ShapeError(
|
|
2095
|
+
throw new ShapeError(
|
|
2096
|
+
'Shape config cannot define both "include" and "select".'
|
|
2097
|
+
);
|
|
1938
2098
|
}
|
|
1939
2099
|
if (method === "groupBy" && !shape.by)
|
|
1940
2100
|
throw new ShapeError('groupBy shape must define "by"');
|
|
@@ -1950,7 +2110,9 @@ function createQueryBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
|
|
|
1950
2110
|
const bySet = new Set(shape.by);
|
|
1951
2111
|
for (const fieldName of Object.keys(shape.orderBy)) {
|
|
1952
2112
|
if (!bySet.has(fieldName)) {
|
|
1953
|
-
throw new ShapeError(
|
|
2113
|
+
throw new ShapeError(
|
|
2114
|
+
`orderBy field "${fieldName}" must be included in "by" for groupBy`
|
|
2115
|
+
);
|
|
1954
2116
|
}
|
|
1955
2117
|
}
|
|
1956
2118
|
}
|
|
@@ -1958,7 +2120,9 @@ function createQueryBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
|
|
|
1958
2120
|
const bySet = new Set(shape.by);
|
|
1959
2121
|
for (const fieldName of Object.keys(shape.having)) {
|
|
1960
2122
|
if (!bySet.has(fieldName)) {
|
|
1961
|
-
throw new ShapeError(
|
|
2123
|
+
throw new ShapeError(
|
|
2124
|
+
`having field "${fieldName}" must be included in "by" for groupBy`
|
|
2125
|
+
);
|
|
1962
2126
|
}
|
|
1963
2127
|
}
|
|
1964
2128
|
}
|
|
@@ -1975,7 +2139,9 @@ function createQueryBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
|
|
|
1975
2139
|
requireContext(ctx, "shape function");
|
|
1976
2140
|
const result = shapeOrFn(ctx);
|
|
1977
2141
|
if (!isPlainObject(result)) {
|
|
1978
|
-
throw new ShapeError(
|
|
2142
|
+
throw new ShapeError(
|
|
2143
|
+
"Dynamic shape function must return a plain object"
|
|
2144
|
+
);
|
|
1979
2145
|
}
|
|
1980
2146
|
return result;
|
|
1981
2147
|
}
|
|
@@ -1986,15 +2152,20 @@ function createQueryBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
|
|
|
1986
2152
|
validateUniqueWhere(model, method, shape);
|
|
1987
2153
|
const schemaFields = {};
|
|
1988
2154
|
let forcedWhere = EMPTY_WHERE_FORCED;
|
|
2155
|
+
let forcedOnlyWhereKeys = /* @__PURE__ */ new Set();
|
|
1989
2156
|
let forcedIncludeTree = {};
|
|
1990
2157
|
let forcedSelectTree = {};
|
|
1991
2158
|
let forcedIncludeCountWhere = {};
|
|
1992
2159
|
let forcedSelectCountWhere = {};
|
|
1993
2160
|
if (shape.where) {
|
|
1994
|
-
const { schema, forced } = whereBuilder.buildWhereSchema(
|
|
2161
|
+
const { schema, forced, forcedOnlyKeys } = whereBuilder.buildWhereSchema(
|
|
2162
|
+
model,
|
|
2163
|
+
shape.where
|
|
2164
|
+
);
|
|
1995
2165
|
if (schema)
|
|
1996
2166
|
schemaFields["where"] = schema;
|
|
1997
2167
|
forcedWhere = forced;
|
|
2168
|
+
forcedOnlyWhereKeys = forcedOnlyKeys;
|
|
1998
2169
|
}
|
|
1999
2170
|
if (shape.include) {
|
|
2000
2171
|
const result = projectionBuilder.buildIncludeSchema(model, shape.include);
|
|
@@ -2004,7 +2175,10 @@ function createQueryBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
|
|
|
2004
2175
|
}
|
|
2005
2176
|
if (shape.select) {
|
|
2006
2177
|
if (method === "count") {
|
|
2007
|
-
schemaFields["select"] = argsBuilder.buildCountSelectSchema(
|
|
2178
|
+
schemaFields["select"] = argsBuilder.buildCountSelectSchema(
|
|
2179
|
+
model,
|
|
2180
|
+
shape.select
|
|
2181
|
+
);
|
|
2008
2182
|
} else {
|
|
2009
2183
|
const result = projectionBuilder.buildSelectSchema(model, shape.select);
|
|
2010
2184
|
schemaFields["select"] = result.schema;
|
|
@@ -2013,9 +2187,15 @@ function createQueryBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
|
|
|
2013
2187
|
}
|
|
2014
2188
|
}
|
|
2015
2189
|
if (shape.orderBy)
|
|
2016
|
-
schemaFields["orderBy"] = argsBuilder.buildOrderBySchema(
|
|
2190
|
+
schemaFields["orderBy"] = argsBuilder.buildOrderBySchema(
|
|
2191
|
+
model,
|
|
2192
|
+
shape.orderBy
|
|
2193
|
+
);
|
|
2017
2194
|
if (shape.cursor)
|
|
2018
|
-
schemaFields["cursor"] = argsBuilder.buildCursorSchema(
|
|
2195
|
+
schemaFields["cursor"] = argsBuilder.buildCursorSchema(
|
|
2196
|
+
model,
|
|
2197
|
+
shape.cursor
|
|
2198
|
+
);
|
|
2019
2199
|
if (shape.take)
|
|
2020
2200
|
schemaFields["take"] = argsBuilder.buildTakeSchema(shape.take);
|
|
2021
2201
|
if (shape.skip !== void 0) {
|
|
@@ -2025,24 +2205,51 @@ function createQueryBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
|
|
|
2025
2205
|
schemaFields["skip"] = z7.number().int().min(0).optional();
|
|
2026
2206
|
}
|
|
2027
2207
|
if (shape.distinct)
|
|
2028
|
-
schemaFields["distinct"] = argsBuilder.buildDistinctSchema(
|
|
2208
|
+
schemaFields["distinct"] = argsBuilder.buildDistinctSchema(
|
|
2209
|
+
model,
|
|
2210
|
+
shape.distinct
|
|
2211
|
+
);
|
|
2029
2212
|
if (shape._count)
|
|
2030
|
-
schemaFields["_count"] = argsBuilder.buildCountFieldSchema(
|
|
2213
|
+
schemaFields["_count"] = argsBuilder.buildCountFieldSchema(
|
|
2214
|
+
model,
|
|
2215
|
+
shape._count,
|
|
2216
|
+
"_count"
|
|
2217
|
+
);
|
|
2031
2218
|
if (shape._avg)
|
|
2032
|
-
schemaFields["_avg"] = argsBuilder.buildAggregateFieldSchema(
|
|
2219
|
+
schemaFields["_avg"] = argsBuilder.buildAggregateFieldSchema(
|
|
2220
|
+
model,
|
|
2221
|
+
"_avg",
|
|
2222
|
+
shape._avg
|
|
2223
|
+
);
|
|
2033
2224
|
if (shape._sum)
|
|
2034
|
-
schemaFields["_sum"] = argsBuilder.buildAggregateFieldSchema(
|
|
2225
|
+
schemaFields["_sum"] = argsBuilder.buildAggregateFieldSchema(
|
|
2226
|
+
model,
|
|
2227
|
+
"_sum",
|
|
2228
|
+
shape._sum
|
|
2229
|
+
);
|
|
2035
2230
|
if (shape._min)
|
|
2036
|
-
schemaFields["_min"] = argsBuilder.buildAggregateFieldSchema(
|
|
2231
|
+
schemaFields["_min"] = argsBuilder.buildAggregateFieldSchema(
|
|
2232
|
+
model,
|
|
2233
|
+
"_min",
|
|
2234
|
+
shape._min
|
|
2235
|
+
);
|
|
2037
2236
|
if (shape._max)
|
|
2038
|
-
schemaFields["_max"] = argsBuilder.buildAggregateFieldSchema(
|
|
2237
|
+
schemaFields["_max"] = argsBuilder.buildAggregateFieldSchema(
|
|
2238
|
+
model,
|
|
2239
|
+
"_max",
|
|
2240
|
+
shape._max
|
|
2241
|
+
);
|
|
2039
2242
|
if (shape.by)
|
|
2040
2243
|
schemaFields["by"] = argsBuilder.buildBySchema(model, shape.by);
|
|
2041
2244
|
if (shape.having)
|
|
2042
|
-
schemaFields["having"] = argsBuilder.buildHavingSchema(
|
|
2245
|
+
schemaFields["having"] = argsBuilder.buildHavingSchema(
|
|
2246
|
+
model,
|
|
2247
|
+
shape.having
|
|
2248
|
+
);
|
|
2043
2249
|
return {
|
|
2044
2250
|
zodSchema: z7.object(schemaFields).strict(),
|
|
2045
2251
|
forcedWhere,
|
|
2252
|
+
forcedOnlyWhereKeys,
|
|
2046
2253
|
forcedIncludeTree,
|
|
2047
2254
|
forcedSelectTree,
|
|
2048
2255
|
forcedIncludeCountWhere,
|
|
@@ -2059,17 +2266,27 @@ function createQueryBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
|
|
|
2059
2266
|
const isSingle = typeof config === "function" || isShapeConfig(config);
|
|
2060
2267
|
const builtCache = /* @__PURE__ */ new Map();
|
|
2061
2268
|
if (isSingle && typeof config !== "function") {
|
|
2062
|
-
builtCache.set(
|
|
2269
|
+
builtCache.set(
|
|
2270
|
+
"_default",
|
|
2271
|
+
buildShapeZodSchema(model, method, config)
|
|
2272
|
+
);
|
|
2063
2273
|
}
|
|
2064
2274
|
if (!isSingle) {
|
|
2065
2275
|
for (const key of Object.keys(config)) {
|
|
2066
2276
|
if (SHAPE_CONFIG_KEYS.has(key)) {
|
|
2067
|
-
throw new ShapeError(
|
|
2277
|
+
throw new ShapeError(
|
|
2278
|
+
`Caller key "${key}" collides with reserved shape config key. Rename the caller path.`
|
|
2279
|
+
);
|
|
2068
2280
|
}
|
|
2069
2281
|
}
|
|
2070
|
-
for (const [key, shapeOrFn] of Object.entries(
|
|
2282
|
+
for (const [key, shapeOrFn] of Object.entries(
|
|
2283
|
+
config
|
|
2284
|
+
)) {
|
|
2071
2285
|
if (typeof shapeOrFn !== "function") {
|
|
2072
|
-
builtCache.set(
|
|
2286
|
+
builtCache.set(
|
|
2287
|
+
key,
|
|
2288
|
+
buildShapeZodSchema(model, method, shapeOrFn)
|
|
2289
|
+
);
|
|
2073
2290
|
}
|
|
2074
2291
|
}
|
|
2075
2292
|
}
|
|
@@ -2098,14 +2315,21 @@ function createQueryBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
|
|
|
2098
2315
|
}
|
|
2099
2316
|
const caller = opts?.caller;
|
|
2100
2317
|
if (typeof caller !== "string") {
|
|
2101
|
-
const allowed = Object.keys(
|
|
2318
|
+
const allowed = Object.keys(
|
|
2319
|
+
config
|
|
2320
|
+
);
|
|
2102
2321
|
throw new CallerError(
|
|
2103
2322
|
`Missing caller. This query uses named shape routing with keys: ${allowed.map((k) => `"${k}"`).join(", ")}. Provide caller via opts.caller.`
|
|
2104
2323
|
);
|
|
2105
2324
|
}
|
|
2106
|
-
const matched = matchCaller(
|
|
2325
|
+
const matched = matchCaller(
|
|
2326
|
+
config,
|
|
2327
|
+
caller
|
|
2328
|
+
);
|
|
2107
2329
|
if (!matched) {
|
|
2108
|
-
const allowed = Object.keys(
|
|
2330
|
+
const allowed = Object.keys(
|
|
2331
|
+
config
|
|
2332
|
+
);
|
|
2109
2333
|
throw new CallerError(
|
|
2110
2334
|
`Unknown caller: "${caller}". Allowed: ${allowed.map((k) => `"${k}"`).join(", ")}`
|
|
2111
2335
|
);
|
|
@@ -2738,7 +2962,10 @@ function resolveShape(input, body, contextFn, caller) {
|
|
|
2738
2962
|
|
|
2739
2963
|
// src/runtime/model-guard.ts
|
|
2740
2964
|
var UNIQUE_MUTATION_METHODS = /* @__PURE__ */ new Set(["update", "delete", "upsert"]);
|
|
2741
|
-
var UNIQUE_READ_METHODS = /* @__PURE__ */ new Set([
|
|
2965
|
+
var UNIQUE_READ_METHODS = /* @__PURE__ */ new Set([
|
|
2966
|
+
"findUnique",
|
|
2967
|
+
"findUniqueOrThrow"
|
|
2968
|
+
]);
|
|
2742
2969
|
var BULK_MUTATION_METHODS = /* @__PURE__ */ new Set([
|
|
2743
2970
|
"updateMany",
|
|
2744
2971
|
"updateManyAndReturn",
|
|
@@ -2752,15 +2979,14 @@ var PROJECTION_MUTATION_METHODS = /* @__PURE__ */ new Set([
|
|
|
2752
2979
|
"createManyAndReturn",
|
|
2753
2980
|
"updateManyAndReturn"
|
|
2754
2981
|
]);
|
|
2755
|
-
var BATCH_CREATE_METHODS = /* @__PURE__ */ new Set([
|
|
2756
|
-
"createMany",
|
|
2757
|
-
"createManyAndReturn"
|
|
2758
|
-
]);
|
|
2982
|
+
var BATCH_CREATE_METHODS = /* @__PURE__ */ new Set(["createMany", "createManyAndReturn"]);
|
|
2759
2983
|
function buildDefaultSelectInput(config) {
|
|
2760
2984
|
const result = {};
|
|
2761
2985
|
for (const [key, value] of Object.entries(config)) {
|
|
2762
2986
|
if (key === "_count") {
|
|
2763
|
-
result[key] = buildDefaultCountInput(
|
|
2987
|
+
result[key] = buildDefaultCountInput(
|
|
2988
|
+
value
|
|
2989
|
+
);
|
|
2764
2990
|
continue;
|
|
2765
2991
|
}
|
|
2766
2992
|
if (value === true) {
|
|
@@ -2778,7 +3004,9 @@ function buildDefaultIncludeInput(config) {
|
|
|
2778
3004
|
const result = {};
|
|
2779
3005
|
for (const [key, value] of Object.entries(config)) {
|
|
2780
3006
|
if (key === "_count") {
|
|
2781
|
-
result[key] = buildDefaultCountInput(
|
|
3007
|
+
result[key] = buildDefaultCountInput(
|
|
3008
|
+
value
|
|
3009
|
+
);
|
|
2782
3010
|
continue;
|
|
2783
3011
|
}
|
|
2784
3012
|
if (value === true) {
|
|
@@ -2892,12 +3120,32 @@ function hasNestedClientControlledArgs(shape) {
|
|
|
2892
3120
|
return false;
|
|
2893
3121
|
}
|
|
2894
3122
|
function createModelGuardExtension(config) {
|
|
2895
|
-
const {
|
|
3123
|
+
const {
|
|
3124
|
+
typeMap,
|
|
3125
|
+
enumMap,
|
|
3126
|
+
zodChains,
|
|
3127
|
+
zodDefaults,
|
|
3128
|
+
uniqueMap,
|
|
3129
|
+
scopeMap,
|
|
3130
|
+
guardConfig,
|
|
3131
|
+
contextFn
|
|
3132
|
+
} = config;
|
|
2896
3133
|
const wrapZodErrors = config.wrapZodErrors ?? false;
|
|
2897
3134
|
const enforceProjection = guardConfig.enforceProjection ?? false;
|
|
2898
3135
|
const scalarBase = createScalarBase(guardConfig.strictDecimal ?? false);
|
|
2899
|
-
const schemaBuilder = createSchemaBuilder(
|
|
2900
|
-
|
|
3136
|
+
const schemaBuilder = createSchemaBuilder(
|
|
3137
|
+
typeMap,
|
|
3138
|
+
zodChains,
|
|
3139
|
+
enumMap,
|
|
3140
|
+
scalarBase,
|
|
3141
|
+
zodDefaults
|
|
3142
|
+
);
|
|
3143
|
+
const queryBuilder = createQueryBuilder(
|
|
3144
|
+
typeMap,
|
|
3145
|
+
enumMap,
|
|
3146
|
+
uniqueMap,
|
|
3147
|
+
scalarBase
|
|
3148
|
+
);
|
|
2901
3149
|
const modelScopeFks = /* @__PURE__ */ new Map();
|
|
2902
3150
|
for (const [model, entries] of Object.entries(scopeMap)) {
|
|
2903
3151
|
const fks = /* @__PURE__ */ new Set();
|
|
@@ -2915,7 +3163,9 @@ function createModelGuardExtension(config) {
|
|
|
2915
3163
|
function createGuardedMethods(modelName, modelDelegate, input, explicitCaller) {
|
|
2916
3164
|
function callDelegate(method, args) {
|
|
2917
3165
|
if (typeof modelDelegate[method] !== "function") {
|
|
2918
|
-
throw new ShapeError(
|
|
3166
|
+
throw new ShapeError(
|
|
3167
|
+
`Method "${method}" is not available on this model`
|
|
3168
|
+
);
|
|
2919
3169
|
}
|
|
2920
3170
|
return modelDelegate[method](args);
|
|
2921
3171
|
}
|
|
@@ -2938,11 +3188,19 @@ function createModelGuardExtension(config) {
|
|
|
2938
3188
|
const cached = readShapeCache.get(cacheKey);
|
|
2939
3189
|
if (cached)
|
|
2940
3190
|
return cached;
|
|
2941
|
-
const built = queryBuilder.buildShapeZodSchema(
|
|
3191
|
+
const built = queryBuilder.buildShapeZodSchema(
|
|
3192
|
+
modelName,
|
|
3193
|
+
method,
|
|
3194
|
+
queryShape
|
|
3195
|
+
);
|
|
2942
3196
|
readShapeCache.set(cacheKey, built);
|
|
2943
3197
|
return built;
|
|
2944
3198
|
}
|
|
2945
|
-
return queryBuilder.buildShapeZodSchema(
|
|
3199
|
+
return queryBuilder.buildShapeZodSchema(
|
|
3200
|
+
modelName,
|
|
3201
|
+
method,
|
|
3202
|
+
queryShape
|
|
3203
|
+
);
|
|
2946
3204
|
}
|
|
2947
3205
|
function getDataSchema(mode, dataConfig, matchedKey, wasDynamic) {
|
|
2948
3206
|
if (!wasDynamic && !hasDataRefines(dataConfig)) {
|
|
@@ -2950,11 +3208,25 @@ function createModelGuardExtension(config) {
|
|
|
2950
3208
|
const cached = dataSchemaCache.get(cacheKey);
|
|
2951
3209
|
if (cached)
|
|
2952
3210
|
return cached;
|
|
2953
|
-
const built = buildDataSchema(
|
|
3211
|
+
const built = buildDataSchema(
|
|
3212
|
+
modelName,
|
|
3213
|
+
dataConfig,
|
|
3214
|
+
mode,
|
|
3215
|
+
typeMap,
|
|
3216
|
+
schemaBuilder,
|
|
3217
|
+
zodDefaults
|
|
3218
|
+
);
|
|
2954
3219
|
dataSchemaCache.set(cacheKey, built);
|
|
2955
3220
|
return built;
|
|
2956
3221
|
}
|
|
2957
|
-
return buildDataSchema(
|
|
3222
|
+
return buildDataSchema(
|
|
3223
|
+
modelName,
|
|
3224
|
+
dataConfig,
|
|
3225
|
+
mode,
|
|
3226
|
+
typeMap,
|
|
3227
|
+
schemaBuilder,
|
|
3228
|
+
zodDefaults
|
|
3229
|
+
);
|
|
2958
3230
|
}
|
|
2959
3231
|
function getWhereBuilt(whereConfig, matchedKey, wasDynamic) {
|
|
2960
3232
|
if (!wasDynamic) {
|
|
@@ -3073,12 +3345,28 @@ function createModelGuardExtension(config) {
|
|
|
3073
3345
|
const built = getWhereBuilt(shape.where, matchedKey, wasDynamic);
|
|
3074
3346
|
let validatedWhere;
|
|
3075
3347
|
if (built.schema) {
|
|
3076
|
-
|
|
3348
|
+
let sanitizedWhere = bodyWhere;
|
|
3349
|
+
if (built.forcedOnlyKeys.size > 0 && isPlainObject(bodyWhere)) {
|
|
3350
|
+
const w = { ...bodyWhere };
|
|
3351
|
+
for (const key of built.forcedOnlyKeys) {
|
|
3352
|
+
delete w[key];
|
|
3353
|
+
}
|
|
3354
|
+
sanitizedWhere = w;
|
|
3355
|
+
}
|
|
3356
|
+
validatedWhere = built.schema.parse(sanitizedWhere);
|
|
3077
3357
|
} else if (bodyWhere !== void 0) {
|
|
3078
3358
|
if (bodyWhere === null || !isPlainObject(bodyWhere) || Object.keys(bodyWhere).length > 0) {
|
|
3079
|
-
|
|
3080
|
-
|
|
3081
|
-
|
|
3359
|
+
let hasOnlyForcedKeys = false;
|
|
3360
|
+
if (isPlainObject(bodyWhere) && built.forcedOnlyKeys.size > 0) {
|
|
3361
|
+
hasOnlyForcedKeys = Object.keys(bodyWhere).every(
|
|
3362
|
+
(k) => built.forcedOnlyKeys.has(k)
|
|
3363
|
+
);
|
|
3364
|
+
}
|
|
3365
|
+
if (!hasOnlyForcedKeys) {
|
|
3366
|
+
throw new ShapeError(
|
|
3367
|
+
"Guard shape where contains only forced conditions. Client where input is not accepted."
|
|
3368
|
+
);
|
|
3369
|
+
}
|
|
3082
3370
|
}
|
|
3083
3371
|
}
|
|
3084
3372
|
if (hasWhereForced(built.forced)) {
|
|
@@ -3087,7 +3375,13 @@ function createModelGuardExtension(config) {
|
|
|
3087
3375
|
return validatedWhere ?? {};
|
|
3088
3376
|
}
|
|
3089
3377
|
function requireWhere(shape, bodyWhere, method, preserveUnique, matchedKey, wasDynamic) {
|
|
3090
|
-
const where = buildWhereFromShape(
|
|
3378
|
+
const where = buildWhereFromShape(
|
|
3379
|
+
shape,
|
|
3380
|
+
bodyWhere,
|
|
3381
|
+
preserveUnique,
|
|
3382
|
+
matchedKey,
|
|
3383
|
+
wasDynamic
|
|
3384
|
+
);
|
|
3091
3385
|
if (Object.keys(where).length === 0) {
|
|
3092
3386
|
throw new ShapeError(`${method} requires a where condition`);
|
|
3093
3387
|
}
|
|
@@ -3101,7 +3395,12 @@ function createModelGuardExtension(config) {
|
|
|
3101
3395
|
throw new ShapeError(`Guard shape "data" is not valid for ${method}`);
|
|
3102
3396
|
}
|
|
3103
3397
|
const { data: _, ...queryShape } = resolved.shape;
|
|
3104
|
-
const built = getReadShape(
|
|
3398
|
+
const built = getReadShape(
|
|
3399
|
+
method,
|
|
3400
|
+
queryShape,
|
|
3401
|
+
resolved.matchedKey,
|
|
3402
|
+
resolved.wasDynamic
|
|
3403
|
+
);
|
|
3105
3404
|
const isUnique = UNIQUE_READ_METHODS.has(method);
|
|
3106
3405
|
const args = applyBuiltShape(built, resolved.body, isUnique);
|
|
3107
3406
|
if (isUnique && args.where) {
|
|
@@ -3134,14 +3433,33 @@ function createModelGuardExtension(config) {
|
|
|
3134
3433
|
const resolved = resolveShape(input, body, contextFn, caller);
|
|
3135
3434
|
if (!resolved.shape.data)
|
|
3136
3435
|
throw new ShapeError(`Guard shape requires "data" for ${method}`);
|
|
3137
|
-
validateMutationShapeKeys(
|
|
3436
|
+
validateMutationShapeKeys(
|
|
3437
|
+
resolved.shape,
|
|
3438
|
+
allowedShapeKeys,
|
|
3439
|
+
method
|
|
3440
|
+
);
|
|
3138
3441
|
validateMutationBodyKeys(resolved.body, allowedBodyKeys, method);
|
|
3139
3442
|
const fks = modelScopeFks.get(modelName) ?? /* @__PURE__ */ new Set();
|
|
3140
|
-
validateCreateCompleteness(
|
|
3141
|
-
|
|
3443
|
+
validateCreateCompleteness(
|
|
3444
|
+
modelName,
|
|
3445
|
+
resolved.shape.data,
|
|
3446
|
+
typeMap,
|
|
3447
|
+
fks,
|
|
3448
|
+
zodDefaults
|
|
3449
|
+
);
|
|
3450
|
+
const dataSchema = getDataSchema(
|
|
3451
|
+
"create",
|
|
3452
|
+
resolved.shape.data,
|
|
3453
|
+
resolved.matchedKey,
|
|
3454
|
+
resolved.wasDynamic
|
|
3455
|
+
);
|
|
3142
3456
|
let args;
|
|
3143
3457
|
if (method === "create") {
|
|
3144
|
-
const data = validateAndMergeData(
|
|
3458
|
+
const data = validateAndMergeData(
|
|
3459
|
+
resolved.body.data,
|
|
3460
|
+
dataSchema,
|
|
3461
|
+
method
|
|
3462
|
+
);
|
|
3145
3463
|
args = { data };
|
|
3146
3464
|
} else {
|
|
3147
3465
|
if (!Array.isArray(resolved.body.data))
|
|
@@ -3160,7 +3478,13 @@ function createModelGuardExtension(config) {
|
|
|
3160
3478
|
args.skipDuplicates = resolved.body.skipDuplicates;
|
|
3161
3479
|
}
|
|
3162
3480
|
if (supportsProjection) {
|
|
3163
|
-
const projectionArgs = resolveProjection(
|
|
3481
|
+
const projectionArgs = resolveProjection(
|
|
3482
|
+
resolved.shape,
|
|
3483
|
+
resolved.body,
|
|
3484
|
+
method,
|
|
3485
|
+
resolved.matchedKey,
|
|
3486
|
+
resolved.wasDynamic
|
|
3487
|
+
);
|
|
3164
3488
|
Object.assign(args, projectionArgs);
|
|
3165
3489
|
}
|
|
3166
3490
|
return callDelegate(method, args);
|
|
@@ -3177,24 +3501,60 @@ function createModelGuardExtension(config) {
|
|
|
3177
3501
|
const resolved = resolveShape(input, body, contextFn, caller);
|
|
3178
3502
|
if (!resolved.shape.data)
|
|
3179
3503
|
throw new ShapeError(`Guard shape requires "data" for ${method}`);
|
|
3180
|
-
validateMutationShapeKeys(
|
|
3504
|
+
validateMutationShapeKeys(
|
|
3505
|
+
resolved.shape,
|
|
3506
|
+
allowedShapeKeys,
|
|
3507
|
+
method
|
|
3508
|
+
);
|
|
3181
3509
|
validateMutationBodyKeys(resolved.body, allowedBodyKeys, method);
|
|
3182
3510
|
if (isBulk && !resolved.shape.where) {
|
|
3183
|
-
throw new ShapeError(
|
|
3511
|
+
throw new ShapeError(
|
|
3512
|
+
`Guard shape requires "where" for ${method} to prevent unconstrained bulk mutations`
|
|
3513
|
+
);
|
|
3184
3514
|
}
|
|
3185
3515
|
maybeValidateUniqueWhere(modelName, resolved.shape, method);
|
|
3186
|
-
const dataSchema = getDataSchema(
|
|
3187
|
-
|
|
3188
|
-
|
|
3516
|
+
const dataSchema = getDataSchema(
|
|
3517
|
+
"update",
|
|
3518
|
+
resolved.shape.data,
|
|
3519
|
+
resolved.matchedKey,
|
|
3520
|
+
resolved.wasDynamic
|
|
3521
|
+
);
|
|
3522
|
+
const data = validateAndMergeData(
|
|
3523
|
+
resolved.body.data,
|
|
3524
|
+
dataSchema,
|
|
3525
|
+
method
|
|
3526
|
+
);
|
|
3527
|
+
const where = isUniqueWhere ? requireWhere(
|
|
3528
|
+
resolved.shape,
|
|
3529
|
+
resolved.body.where,
|
|
3530
|
+
method,
|
|
3531
|
+
true,
|
|
3532
|
+
resolved.matchedKey,
|
|
3533
|
+
resolved.wasDynamic
|
|
3534
|
+
) : buildWhereFromShape(
|
|
3535
|
+
resolved.shape,
|
|
3536
|
+
resolved.body.where,
|
|
3537
|
+
false,
|
|
3538
|
+
resolved.matchedKey,
|
|
3539
|
+
resolved.wasDynamic
|
|
3540
|
+
);
|
|
3189
3541
|
if (isBulk && Object.keys(where).length === 0) {
|
|
3190
|
-
throw new ShapeError(
|
|
3542
|
+
throw new ShapeError(
|
|
3543
|
+
`${method} requires at least one where condition`
|
|
3544
|
+
);
|
|
3191
3545
|
}
|
|
3192
3546
|
if (isUniqueWhere) {
|
|
3193
3547
|
validateResolvedUniqueWhere(modelName, where, method, uniqueMap);
|
|
3194
3548
|
}
|
|
3195
3549
|
const args = { data, where };
|
|
3196
3550
|
if (supportsProjection) {
|
|
3197
|
-
const projectionArgs = resolveProjection(
|
|
3551
|
+
const projectionArgs = resolveProjection(
|
|
3552
|
+
resolved.shape,
|
|
3553
|
+
resolved.body,
|
|
3554
|
+
method,
|
|
3555
|
+
resolved.matchedKey,
|
|
3556
|
+
resolved.wasDynamic
|
|
3557
|
+
);
|
|
3198
3558
|
Object.assign(args, projectionArgs);
|
|
3199
3559
|
}
|
|
3200
3560
|
return callDelegate(method, args);
|
|
@@ -3211,22 +3571,49 @@ function createModelGuardExtension(config) {
|
|
|
3211
3571
|
const resolved = resolveShape(input, body, contextFn, caller);
|
|
3212
3572
|
if (resolved.shape.data)
|
|
3213
3573
|
throw new ShapeError(`Guard shape "data" is not valid for ${method}`);
|
|
3214
|
-
validateMutationShapeKeys(
|
|
3574
|
+
validateMutationShapeKeys(
|
|
3575
|
+
resolved.shape,
|
|
3576
|
+
allowedShapeKeys,
|
|
3577
|
+
method
|
|
3578
|
+
);
|
|
3215
3579
|
validateMutationBodyKeys(resolved.body, allowedBodyKeys, method);
|
|
3216
3580
|
if (isBulk && !resolved.shape.where) {
|
|
3217
|
-
throw new ShapeError(
|
|
3581
|
+
throw new ShapeError(
|
|
3582
|
+
`Guard shape requires "where" for ${method} to prevent unconstrained bulk mutations`
|
|
3583
|
+
);
|
|
3218
3584
|
}
|
|
3219
3585
|
maybeValidateUniqueWhere(modelName, resolved.shape, method);
|
|
3220
|
-
const where = isUniqueWhere ? requireWhere(
|
|
3586
|
+
const where = isUniqueWhere ? requireWhere(
|
|
3587
|
+
resolved.shape,
|
|
3588
|
+
resolved.body.where,
|
|
3589
|
+
method,
|
|
3590
|
+
true,
|
|
3591
|
+
resolved.matchedKey,
|
|
3592
|
+
resolved.wasDynamic
|
|
3593
|
+
) : buildWhereFromShape(
|
|
3594
|
+
resolved.shape,
|
|
3595
|
+
resolved.body.where,
|
|
3596
|
+
false,
|
|
3597
|
+
resolved.matchedKey,
|
|
3598
|
+
resolved.wasDynamic
|
|
3599
|
+
);
|
|
3221
3600
|
if (isBulk && Object.keys(where).length === 0) {
|
|
3222
|
-
throw new ShapeError(
|
|
3601
|
+
throw new ShapeError(
|
|
3602
|
+
`${method} requires at least one where condition`
|
|
3603
|
+
);
|
|
3223
3604
|
}
|
|
3224
3605
|
if (isUniqueWhere) {
|
|
3225
3606
|
validateResolvedUniqueWhere(modelName, where, method, uniqueMap);
|
|
3226
3607
|
}
|
|
3227
3608
|
const args = { where };
|
|
3228
3609
|
if (supportsProjection) {
|
|
3229
|
-
const projectionArgs = resolveProjection(
|
|
3610
|
+
const projectionArgs = resolveProjection(
|
|
3611
|
+
resolved.shape,
|
|
3612
|
+
resolved.body,
|
|
3613
|
+
method,
|
|
3614
|
+
resolved.matchedKey,
|
|
3615
|
+
resolved.wasDynamic
|
|
3616
|
+
);
|
|
3230
3617
|
Object.assign(args, projectionArgs);
|
|
3231
3618
|
}
|
|
3232
3619
|
return callDelegate(method, args);
|
|
@@ -3237,7 +3624,9 @@ function createModelGuardExtension(config) {
|
|
|
3237
3624
|
const caller = resolveCaller();
|
|
3238
3625
|
const resolved = resolveShape(input, body, contextFn, caller);
|
|
3239
3626
|
if (resolved.shape.data) {
|
|
3240
|
-
throw new ShapeError(
|
|
3627
|
+
throw new ShapeError(
|
|
3628
|
+
'Guard shape "data" is not valid for upsert. Use "create" and "update" instead.'
|
|
3629
|
+
);
|
|
3241
3630
|
}
|
|
3242
3631
|
if (!resolved.shape.create) {
|
|
3243
3632
|
throw new ShapeError('Guard shape requires "create" for upsert');
|
|
@@ -3253,24 +3642,42 @@ function createModelGuardExtension(config) {
|
|
|
3253
3642
|
VALID_SHAPE_KEYS_UPSERT,
|
|
3254
3643
|
"upsert"
|
|
3255
3644
|
);
|
|
3256
|
-
validateMutationBodyKeys(
|
|
3645
|
+
validateMutationBodyKeys(
|
|
3646
|
+
resolved.body,
|
|
3647
|
+
ALLOWED_BODY_KEYS_UPSERT,
|
|
3648
|
+
"upsert"
|
|
3649
|
+
);
|
|
3257
3650
|
maybeValidateUniqueWhere(modelName, resolved.shape, "upsert");
|
|
3258
3651
|
const fks = modelScopeFks.get(modelName) ?? /* @__PURE__ */ new Set();
|
|
3259
|
-
validateCreateCompleteness(
|
|
3652
|
+
validateCreateCompleteness(
|
|
3653
|
+
modelName,
|
|
3654
|
+
resolved.shape.create,
|
|
3655
|
+
typeMap,
|
|
3656
|
+
fks,
|
|
3657
|
+
zodDefaults
|
|
3658
|
+
);
|
|
3260
3659
|
const createDataSchema = getDataSchema(
|
|
3261
3660
|
"create",
|
|
3262
3661
|
resolved.shape.create,
|
|
3263
3662
|
`upsert:create\0${resolved.matchedKey}`,
|
|
3264
3663
|
resolved.wasDynamic
|
|
3265
3664
|
);
|
|
3266
|
-
const createData = validateAndMergeData(
|
|
3665
|
+
const createData = validateAndMergeData(
|
|
3666
|
+
resolved.body.create,
|
|
3667
|
+
createDataSchema,
|
|
3668
|
+
"upsert (create)"
|
|
3669
|
+
);
|
|
3267
3670
|
const updateDataSchema = getDataSchema(
|
|
3268
3671
|
"update",
|
|
3269
3672
|
resolved.shape.update,
|
|
3270
3673
|
`upsert:update\0${resolved.matchedKey}`,
|
|
3271
3674
|
resolved.wasDynamic
|
|
3272
3675
|
);
|
|
3273
|
-
const updateData = validateAndMergeData(
|
|
3676
|
+
const updateData = validateAndMergeData(
|
|
3677
|
+
resolved.body.update,
|
|
3678
|
+
updateDataSchema,
|
|
3679
|
+
"upsert (update)"
|
|
3680
|
+
);
|
|
3274
3681
|
const where = requireWhere(
|
|
3275
3682
|
resolved.shape,
|
|
3276
3683
|
resolved.body.where,
|
|
@@ -3324,10 +3731,9 @@ function createModelGuardExtension(config) {
|
|
|
3324
3731
|
return fn(body);
|
|
3325
3732
|
} catch (err) {
|
|
3326
3733
|
if (err instanceof z9.ZodError) {
|
|
3327
|
-
throw new ShapeError(
|
|
3328
|
-
|
|
3329
|
-
|
|
3330
|
-
);
|
|
3734
|
+
throw new ShapeError(`Validation failed: ${formatZodError(err)}`, {
|
|
3735
|
+
cause: err
|
|
3736
|
+
});
|
|
3331
3737
|
}
|
|
3332
3738
|
throw err;
|
|
3333
3739
|
}
|
|
@@ -3346,7 +3752,12 @@ function createModelGuardExtension(config) {
|
|
|
3346
3752
|
`Could not resolve Prisma delegate for model "${modelName}" (key: "${delegateKey}")`
|
|
3347
3753
|
);
|
|
3348
3754
|
}
|
|
3349
|
-
const methods = createGuardedMethods(
|
|
3755
|
+
const methods = createGuardedMethods(
|
|
3756
|
+
modelName,
|
|
3757
|
+
modelDelegate,
|
|
3758
|
+
input,
|
|
3759
|
+
caller
|
|
3760
|
+
);
|
|
3350
3761
|
if (!wrapZodErrors)
|
|
3351
3762
|
return methods;
|
|
3352
3763
|
return wrapMethods(methods);
|