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.cjs
CHANGED
|
@@ -734,7 +734,24 @@ function mergeUniqueWhereForced(where, forced) {
|
|
|
734
734
|
return result;
|
|
735
735
|
}
|
|
736
736
|
function applyBuiltShape(built, body, isUniqueMethod) {
|
|
737
|
-
|
|
737
|
+
let parseable = body;
|
|
738
|
+
if (built.forcedOnlyWhereKeys.size > 0 && isPlainObject(body)) {
|
|
739
|
+
const bodyObj = body;
|
|
740
|
+
if (isPlainObject(bodyObj.where)) {
|
|
741
|
+
const where = { ...bodyObj.where };
|
|
742
|
+
let stripped = false;
|
|
743
|
+
for (const key of built.forcedOnlyWhereKeys) {
|
|
744
|
+
if (key in where) {
|
|
745
|
+
delete where[key];
|
|
746
|
+
stripped = true;
|
|
747
|
+
}
|
|
748
|
+
}
|
|
749
|
+
if (stripped) {
|
|
750
|
+
parseable = { ...bodyObj, where };
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
}
|
|
754
|
+
const validated = built.zodSchema.parse(parseable);
|
|
738
755
|
if (hasWhereForced(built.forcedWhere)) {
|
|
739
756
|
validated.where = isUniqueMethod ? mergeUniqueWhereForced(
|
|
740
757
|
validated.where,
|
|
@@ -958,7 +975,12 @@ function validateUniqueEquality(model, where, method, uniqueMap, typeMap) {
|
|
|
958
975
|
|
|
959
976
|
// src/runtime/query-builder-where.ts
|
|
960
977
|
var UNSUPPORTED_WHERE_TYPES = /* @__PURE__ */ new Set(["Json", "Bytes"]);
|
|
961
|
-
var STRING_MODE_OPS = /* @__PURE__ */ new Set([
|
|
978
|
+
var STRING_MODE_OPS = /* @__PURE__ */ new Set([
|
|
979
|
+
"contains",
|
|
980
|
+
"startsWith",
|
|
981
|
+
"endsWith",
|
|
982
|
+
"equals"
|
|
983
|
+
]);
|
|
962
984
|
var MAX_WHERE_DEPTH = 10;
|
|
963
985
|
function safeStringify(v) {
|
|
964
986
|
if (typeof v === "bigint")
|
|
@@ -1028,9 +1050,7 @@ function mergeScalarConditions(target, source) {
|
|
|
1028
1050
|
continue;
|
|
1029
1051
|
}
|
|
1030
1052
|
if (!forcedValuesEqual(existing, ops)) {
|
|
1031
|
-
throw new ShapeError(
|
|
1032
|
-
`Conflicting forced where values for "${field}"`
|
|
1033
|
-
);
|
|
1053
|
+
throw new ShapeError(`Conflicting forced where values for "${field}"`);
|
|
1034
1054
|
}
|
|
1035
1055
|
}
|
|
1036
1056
|
}
|
|
@@ -1044,8 +1064,14 @@ function mergeRelationForcedMaps(target, source) {
|
|
|
1044
1064
|
if (!target[relName][op]) {
|
|
1045
1065
|
target[relName][op] = forced;
|
|
1046
1066
|
} else {
|
|
1047
|
-
mergeScalarConditions(
|
|
1048
|
-
|
|
1067
|
+
mergeScalarConditions(
|
|
1068
|
+
target[relName][op].conditions,
|
|
1069
|
+
forced.conditions
|
|
1070
|
+
);
|
|
1071
|
+
mergeRelationForcedMaps(
|
|
1072
|
+
target[relName][op].relations,
|
|
1073
|
+
forced.relations
|
|
1074
|
+
);
|
|
1049
1075
|
}
|
|
1050
1076
|
}
|
|
1051
1077
|
}
|
|
@@ -1097,20 +1123,38 @@ function createWhereBuilder(typeMap, enumMap, scalarBase) {
|
|
|
1097
1123
|
`${fieldMeta.type} field "${key}" cannot be used in where filters`
|
|
1098
1124
|
);
|
|
1099
1125
|
}
|
|
1100
|
-
processScalarField(
|
|
1126
|
+
processScalarField(
|
|
1127
|
+
key,
|
|
1128
|
+
value,
|
|
1129
|
+
model,
|
|
1130
|
+
fieldMeta,
|
|
1131
|
+
fieldSchemas,
|
|
1132
|
+
scalarConditions
|
|
1133
|
+
);
|
|
1101
1134
|
}
|
|
1102
1135
|
const schema = Object.keys(fieldSchemas).length > 0 ? import_zod4.z.object(fieldSchemas).strict().optional() : null;
|
|
1136
|
+
const forcedOnlyKeys = /* @__PURE__ */ new Set();
|
|
1137
|
+
for (const key of Object.keys(whereConfig)) {
|
|
1138
|
+
if (COMBINATOR_KEYS.has(key))
|
|
1139
|
+
continue;
|
|
1140
|
+
if (!(key in fieldSchemas)) {
|
|
1141
|
+
forcedOnlyKeys.add(key);
|
|
1142
|
+
}
|
|
1143
|
+
}
|
|
1103
1144
|
return {
|
|
1104
1145
|
schema,
|
|
1105
1146
|
forced: {
|
|
1106
1147
|
conditions: scalarConditions,
|
|
1107
1148
|
relations: relationForced
|
|
1108
|
-
}
|
|
1149
|
+
},
|
|
1150
|
+
forcedOnlyKeys
|
|
1109
1151
|
};
|
|
1110
1152
|
}
|
|
1111
1153
|
function processCombinator(key, value, model, fieldSchemas, parentConditions, parentRelations, depth) {
|
|
1112
1154
|
if (!isPlainObject(value)) {
|
|
1113
|
-
throw new ShapeError(
|
|
1155
|
+
throw new ShapeError(
|
|
1156
|
+
`"${key}" in where shape must be an object defining allowed fields`
|
|
1157
|
+
);
|
|
1114
1158
|
}
|
|
1115
1159
|
const result = buildWhereSchema(model, value, depth + 1);
|
|
1116
1160
|
if (!result.schema && !hasWhereForced(result.forced)) {
|
|
@@ -1151,7 +1195,9 @@ function createWhereBuilder(typeMap, enumMap, scalarBase) {
|
|
|
1151
1195
|
}
|
|
1152
1196
|
function processRelationFilter(key, value, fieldMeta, model, fieldSchemas, parentRelations, depth) {
|
|
1153
1197
|
if (!isPlainObject(value)) {
|
|
1154
|
-
throw new ShapeError(
|
|
1198
|
+
throw new ShapeError(
|
|
1199
|
+
`Relation filter for "${key}" must be an object with operators (some, every, none, is, isNot)`
|
|
1200
|
+
);
|
|
1155
1201
|
}
|
|
1156
1202
|
const allowedOps = fieldMeta.isList ? TO_MANY_RELATION_OPS : TO_ONE_RELATION_OPS;
|
|
1157
1203
|
if (Object.keys(value).length === 0) {
|
|
@@ -1184,7 +1230,9 @@ function createWhereBuilder(typeMap, enumMap, scalarBase) {
|
|
|
1184
1230
|
if (!hasWhereForced(nested.forced)) {
|
|
1185
1231
|
opSchemas[op] = nested.schema.refine(
|
|
1186
1232
|
(v) => v === void 0 || Object.keys(v).length > 0,
|
|
1187
|
-
{
|
|
1233
|
+
{
|
|
1234
|
+
message: `Relation filter "${key}.${op}" requires at least one condition`
|
|
1235
|
+
}
|
|
1188
1236
|
);
|
|
1189
1237
|
} else {
|
|
1190
1238
|
opSchemas[op] = nested.schema;
|
|
@@ -1205,7 +1253,9 @@ function createWhereBuilder(typeMap, enumMap, scalarBase) {
|
|
|
1205
1253
|
const opObjSchema = import_zod4.z.object(opSchemas).strict();
|
|
1206
1254
|
if (Object.keys(opForced).length === 0) {
|
|
1207
1255
|
fieldSchemas[key] = opObjSchema.refine(
|
|
1208
|
-
(v) => clientOpKeys.some(
|
|
1256
|
+
(v) => clientOpKeys.some(
|
|
1257
|
+
(k) => v[k] !== void 0
|
|
1258
|
+
),
|
|
1209
1259
|
{ message: `At least one relation operator required for "${key}"` }
|
|
1210
1260
|
).optional();
|
|
1211
1261
|
} else {
|
|
@@ -1227,9 +1277,21 @@ function createWhereBuilder(typeMap, enumMap, scalarBase) {
|
|
|
1227
1277
|
let hasClientOps = false;
|
|
1228
1278
|
let hasStringModeOp = false;
|
|
1229
1279
|
const clientOpKeys = [];
|
|
1280
|
+
let modeConfigValue = void 0;
|
|
1281
|
+
let hasModeConfig = false;
|
|
1230
1282
|
for (const [op, opValue] of Object.entries(operators)) {
|
|
1283
|
+
if (op === "mode") {
|
|
1284
|
+
hasModeConfig = true;
|
|
1285
|
+
modeConfigValue = opValue;
|
|
1286
|
+
continue;
|
|
1287
|
+
}
|
|
1231
1288
|
if (opValue === true) {
|
|
1232
|
-
opSchemas[op] = createOperatorSchema(
|
|
1289
|
+
opSchemas[op] = createOperatorSchema(
|
|
1290
|
+
fieldMeta,
|
|
1291
|
+
op,
|
|
1292
|
+
enumMap,
|
|
1293
|
+
scalarBase
|
|
1294
|
+
).optional();
|
|
1233
1295
|
hasClientOps = true;
|
|
1234
1296
|
clientOpKeys.push(op);
|
|
1235
1297
|
if (fieldMeta.type === "String" && !fieldMeta.isList && STRING_MODE_OPS.has(op)) {
|
|
@@ -1237,7 +1299,12 @@ function createWhereBuilder(typeMap, enumMap, scalarBase) {
|
|
|
1237
1299
|
}
|
|
1238
1300
|
} else {
|
|
1239
1301
|
const actualOpValue = isForcedValue(opValue) ? opValue.value : opValue;
|
|
1240
|
-
const opSchema = createOperatorSchema(
|
|
1302
|
+
const opSchema = createOperatorSchema(
|
|
1303
|
+
fieldMeta,
|
|
1304
|
+
op,
|
|
1305
|
+
enumMap,
|
|
1306
|
+
scalarBase
|
|
1307
|
+
);
|
|
1241
1308
|
let parsed;
|
|
1242
1309
|
try {
|
|
1243
1310
|
parsed = opSchema.parse(actualOpValue);
|
|
@@ -1247,21 +1314,54 @@ function createWhereBuilder(typeMap, enumMap, scalarBase) {
|
|
|
1247
1314
|
);
|
|
1248
1315
|
}
|
|
1249
1316
|
fieldForced[op] = parsed;
|
|
1317
|
+
if (fieldMeta.type === "String" && !fieldMeta.isList && STRING_MODE_OPS.has(op)) {
|
|
1318
|
+
hasStringModeOp = true;
|
|
1319
|
+
}
|
|
1250
1320
|
}
|
|
1251
1321
|
}
|
|
1252
1322
|
if (!hasClientOps && Object.keys(fieldForced).length === 0) {
|
|
1323
|
+
if (hasModeConfig) {
|
|
1324
|
+
throw new ShapeError(
|
|
1325
|
+
`Where field "${fieldName}" on model "${model}" has "mode" but no operators. Add at least one operator (contains, startsWith, endsWith, equals).`
|
|
1326
|
+
);
|
|
1327
|
+
}
|
|
1253
1328
|
throw new ShapeError(
|
|
1254
1329
|
`Empty operator config for where field "${fieldName}" on model "${model}". Define at least one operator.`
|
|
1255
1330
|
);
|
|
1256
1331
|
}
|
|
1257
|
-
if (
|
|
1332
|
+
if (hasModeConfig) {
|
|
1333
|
+
if (!hasStringModeOp) {
|
|
1334
|
+
throw new ShapeError(
|
|
1335
|
+
`"mode" on where field "${fieldName}" on model "${model}" requires a compatible String operator (contains, startsWith, endsWith, equals)`
|
|
1336
|
+
);
|
|
1337
|
+
}
|
|
1338
|
+
if (modeConfigValue === true) {
|
|
1339
|
+
opSchemas["mode"] = import_zod4.z.enum(["default", "insensitive"]).optional();
|
|
1340
|
+
} else {
|
|
1341
|
+
const actualModeValue = isForcedValue(modeConfigValue) ? modeConfigValue.value : modeConfigValue;
|
|
1342
|
+
const modeSchema = import_zod4.z.enum(["default", "insensitive"]);
|
|
1343
|
+
let parsed;
|
|
1344
|
+
try {
|
|
1345
|
+
parsed = modeSchema.parse(actualModeValue);
|
|
1346
|
+
} catch (err) {
|
|
1347
|
+
throw new ShapeError(
|
|
1348
|
+
`Invalid forced value for "${model}.${fieldName}.mode": ${err.message}`
|
|
1349
|
+
);
|
|
1350
|
+
}
|
|
1351
|
+
fieldForced["mode"] = parsed;
|
|
1352
|
+
}
|
|
1353
|
+
} else if (hasStringModeOp) {
|
|
1258
1354
|
opSchemas["mode"] = import_zod4.z.enum(["default", "insensitive"]).optional();
|
|
1259
1355
|
}
|
|
1260
1356
|
if (hasClientOps) {
|
|
1261
1357
|
const opObj = import_zod4.z.object(opSchemas).strict();
|
|
1262
1358
|
fieldSchemas[fieldName] = opObj.refine(
|
|
1263
|
-
(v) => clientOpKeys.some(
|
|
1264
|
-
|
|
1359
|
+
(v) => clientOpKeys.some(
|
|
1360
|
+
(k) => v[k] !== void 0
|
|
1361
|
+
),
|
|
1362
|
+
{
|
|
1363
|
+
message: `At least one operator required for where field "${fieldName}"`
|
|
1364
|
+
}
|
|
1265
1365
|
).optional();
|
|
1266
1366
|
}
|
|
1267
1367
|
if (Object.keys(fieldForced).length > 0) {
|
|
@@ -1927,19 +2027,77 @@ function createProjectionBuilder(typeMap, enumMap, deps) {
|
|
|
1927
2027
|
|
|
1928
2028
|
// src/runtime/query-builder.ts
|
|
1929
2029
|
var METHOD_ALLOWED_ARGS = {
|
|
1930
|
-
findMany: /* @__PURE__ */ new Set([
|
|
1931
|
-
|
|
1932
|
-
|
|
2030
|
+
findMany: /* @__PURE__ */ new Set([
|
|
2031
|
+
"where",
|
|
2032
|
+
"include",
|
|
2033
|
+
"select",
|
|
2034
|
+
"orderBy",
|
|
2035
|
+
"cursor",
|
|
2036
|
+
"take",
|
|
2037
|
+
"skip",
|
|
2038
|
+
"distinct"
|
|
2039
|
+
]),
|
|
2040
|
+
findFirst: /* @__PURE__ */ new Set([
|
|
2041
|
+
"where",
|
|
2042
|
+
"include",
|
|
2043
|
+
"select",
|
|
2044
|
+
"orderBy",
|
|
2045
|
+
"cursor",
|
|
2046
|
+
"take",
|
|
2047
|
+
"skip",
|
|
2048
|
+
"distinct"
|
|
2049
|
+
]),
|
|
2050
|
+
findFirstOrThrow: /* @__PURE__ */ new Set([
|
|
2051
|
+
"where",
|
|
2052
|
+
"include",
|
|
2053
|
+
"select",
|
|
2054
|
+
"orderBy",
|
|
2055
|
+
"cursor",
|
|
2056
|
+
"take",
|
|
2057
|
+
"skip",
|
|
2058
|
+
"distinct"
|
|
2059
|
+
]),
|
|
1933
2060
|
findUnique: /* @__PURE__ */ new Set(["where", "include", "select"]),
|
|
1934
2061
|
findUniqueOrThrow: /* @__PURE__ */ new Set(["where", "include", "select"]),
|
|
1935
2062
|
count: /* @__PURE__ */ new Set(["where", "select", "cursor", "orderBy", "skip", "take"]),
|
|
1936
|
-
aggregate: /* @__PURE__ */ new Set([
|
|
1937
|
-
|
|
2063
|
+
aggregate: /* @__PURE__ */ new Set([
|
|
2064
|
+
"where",
|
|
2065
|
+
"orderBy",
|
|
2066
|
+
"cursor",
|
|
2067
|
+
"take",
|
|
2068
|
+
"skip",
|
|
2069
|
+
"_count",
|
|
2070
|
+
"_avg",
|
|
2071
|
+
"_sum",
|
|
2072
|
+
"_min",
|
|
2073
|
+
"_max"
|
|
2074
|
+
]),
|
|
2075
|
+
groupBy: /* @__PURE__ */ new Set([
|
|
2076
|
+
"where",
|
|
2077
|
+
"by",
|
|
2078
|
+
"having",
|
|
2079
|
+
"_count",
|
|
2080
|
+
"_avg",
|
|
2081
|
+
"_sum",
|
|
2082
|
+
"_min",
|
|
2083
|
+
"_max",
|
|
2084
|
+
"orderBy",
|
|
2085
|
+
"take",
|
|
2086
|
+
"skip"
|
|
2087
|
+
])
|
|
1938
2088
|
};
|
|
1939
|
-
var UNIQUE_WHERE_METHODS = /* @__PURE__ */ new Set([
|
|
2089
|
+
var UNIQUE_WHERE_METHODS = /* @__PURE__ */ new Set([
|
|
2090
|
+
"findUnique",
|
|
2091
|
+
"findUniqueOrThrow"
|
|
2092
|
+
]);
|
|
1940
2093
|
function createQueryBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
|
|
1941
2094
|
const whereBuilder = createWhereBuilder(typeMap, enumMap, scalarBase);
|
|
1942
|
-
const argsBuilder = createArgsBuilder(
|
|
2095
|
+
const argsBuilder = createArgsBuilder(
|
|
2096
|
+
typeMap,
|
|
2097
|
+
enumMap,
|
|
2098
|
+
uniqueMap,
|
|
2099
|
+
scalarBase
|
|
2100
|
+
);
|
|
1943
2101
|
const projectionBuilder = createProjectionBuilder(typeMap, enumMap, {
|
|
1944
2102
|
buildWhereSchema: whereBuilder.buildWhereSchema,
|
|
1945
2103
|
buildOrderBySchema: argsBuilder.buildOrderBySchema,
|
|
@@ -1964,7 +2122,9 @@ function createQueryBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
|
|
|
1964
2122
|
throw new ShapeError(`${method} shape must define "where"`);
|
|
1965
2123
|
}
|
|
1966
2124
|
if (shape.include && shape.select) {
|
|
1967
|
-
throw new ShapeError(
|
|
2125
|
+
throw new ShapeError(
|
|
2126
|
+
'Shape config cannot define both "include" and "select".'
|
|
2127
|
+
);
|
|
1968
2128
|
}
|
|
1969
2129
|
if (method === "groupBy" && !shape.by)
|
|
1970
2130
|
throw new ShapeError('groupBy shape must define "by"');
|
|
@@ -1980,7 +2140,9 @@ function createQueryBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
|
|
|
1980
2140
|
const bySet = new Set(shape.by);
|
|
1981
2141
|
for (const fieldName of Object.keys(shape.orderBy)) {
|
|
1982
2142
|
if (!bySet.has(fieldName)) {
|
|
1983
|
-
throw new ShapeError(
|
|
2143
|
+
throw new ShapeError(
|
|
2144
|
+
`orderBy field "${fieldName}" must be included in "by" for groupBy`
|
|
2145
|
+
);
|
|
1984
2146
|
}
|
|
1985
2147
|
}
|
|
1986
2148
|
}
|
|
@@ -1988,7 +2150,9 @@ function createQueryBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
|
|
|
1988
2150
|
const bySet = new Set(shape.by);
|
|
1989
2151
|
for (const fieldName of Object.keys(shape.having)) {
|
|
1990
2152
|
if (!bySet.has(fieldName)) {
|
|
1991
|
-
throw new ShapeError(
|
|
2153
|
+
throw new ShapeError(
|
|
2154
|
+
`having field "${fieldName}" must be included in "by" for groupBy`
|
|
2155
|
+
);
|
|
1992
2156
|
}
|
|
1993
2157
|
}
|
|
1994
2158
|
}
|
|
@@ -2005,7 +2169,9 @@ function createQueryBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
|
|
|
2005
2169
|
requireContext(ctx, "shape function");
|
|
2006
2170
|
const result = shapeOrFn(ctx);
|
|
2007
2171
|
if (!isPlainObject(result)) {
|
|
2008
|
-
throw new ShapeError(
|
|
2172
|
+
throw new ShapeError(
|
|
2173
|
+
"Dynamic shape function must return a plain object"
|
|
2174
|
+
);
|
|
2009
2175
|
}
|
|
2010
2176
|
return result;
|
|
2011
2177
|
}
|
|
@@ -2016,15 +2182,20 @@ function createQueryBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
|
|
|
2016
2182
|
validateUniqueWhere(model, method, shape);
|
|
2017
2183
|
const schemaFields = {};
|
|
2018
2184
|
let forcedWhere = EMPTY_WHERE_FORCED;
|
|
2185
|
+
let forcedOnlyWhereKeys = /* @__PURE__ */ new Set();
|
|
2019
2186
|
let forcedIncludeTree = {};
|
|
2020
2187
|
let forcedSelectTree = {};
|
|
2021
2188
|
let forcedIncludeCountWhere = {};
|
|
2022
2189
|
let forcedSelectCountWhere = {};
|
|
2023
2190
|
if (shape.where) {
|
|
2024
|
-
const { schema, forced } = whereBuilder.buildWhereSchema(
|
|
2191
|
+
const { schema, forced, forcedOnlyKeys } = whereBuilder.buildWhereSchema(
|
|
2192
|
+
model,
|
|
2193
|
+
shape.where
|
|
2194
|
+
);
|
|
2025
2195
|
if (schema)
|
|
2026
2196
|
schemaFields["where"] = schema;
|
|
2027
2197
|
forcedWhere = forced;
|
|
2198
|
+
forcedOnlyWhereKeys = forcedOnlyKeys;
|
|
2028
2199
|
}
|
|
2029
2200
|
if (shape.include) {
|
|
2030
2201
|
const result = projectionBuilder.buildIncludeSchema(model, shape.include);
|
|
@@ -2034,7 +2205,10 @@ function createQueryBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
|
|
|
2034
2205
|
}
|
|
2035
2206
|
if (shape.select) {
|
|
2036
2207
|
if (method === "count") {
|
|
2037
|
-
schemaFields["select"] = argsBuilder.buildCountSelectSchema(
|
|
2208
|
+
schemaFields["select"] = argsBuilder.buildCountSelectSchema(
|
|
2209
|
+
model,
|
|
2210
|
+
shape.select
|
|
2211
|
+
);
|
|
2038
2212
|
} else {
|
|
2039
2213
|
const result = projectionBuilder.buildSelectSchema(model, shape.select);
|
|
2040
2214
|
schemaFields["select"] = result.schema;
|
|
@@ -2043,9 +2217,15 @@ function createQueryBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
|
|
|
2043
2217
|
}
|
|
2044
2218
|
}
|
|
2045
2219
|
if (shape.orderBy)
|
|
2046
|
-
schemaFields["orderBy"] = argsBuilder.buildOrderBySchema(
|
|
2220
|
+
schemaFields["orderBy"] = argsBuilder.buildOrderBySchema(
|
|
2221
|
+
model,
|
|
2222
|
+
shape.orderBy
|
|
2223
|
+
);
|
|
2047
2224
|
if (shape.cursor)
|
|
2048
|
-
schemaFields["cursor"] = argsBuilder.buildCursorSchema(
|
|
2225
|
+
schemaFields["cursor"] = argsBuilder.buildCursorSchema(
|
|
2226
|
+
model,
|
|
2227
|
+
shape.cursor
|
|
2228
|
+
);
|
|
2049
2229
|
if (shape.take)
|
|
2050
2230
|
schemaFields["take"] = argsBuilder.buildTakeSchema(shape.take);
|
|
2051
2231
|
if (shape.skip !== void 0) {
|
|
@@ -2055,24 +2235,51 @@ function createQueryBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
|
|
|
2055
2235
|
schemaFields["skip"] = import_zod7.z.number().int().min(0).optional();
|
|
2056
2236
|
}
|
|
2057
2237
|
if (shape.distinct)
|
|
2058
|
-
schemaFields["distinct"] = argsBuilder.buildDistinctSchema(
|
|
2238
|
+
schemaFields["distinct"] = argsBuilder.buildDistinctSchema(
|
|
2239
|
+
model,
|
|
2240
|
+
shape.distinct
|
|
2241
|
+
);
|
|
2059
2242
|
if (shape._count)
|
|
2060
|
-
schemaFields["_count"] = argsBuilder.buildCountFieldSchema(
|
|
2243
|
+
schemaFields["_count"] = argsBuilder.buildCountFieldSchema(
|
|
2244
|
+
model,
|
|
2245
|
+
shape._count,
|
|
2246
|
+
"_count"
|
|
2247
|
+
);
|
|
2061
2248
|
if (shape._avg)
|
|
2062
|
-
schemaFields["_avg"] = argsBuilder.buildAggregateFieldSchema(
|
|
2249
|
+
schemaFields["_avg"] = argsBuilder.buildAggregateFieldSchema(
|
|
2250
|
+
model,
|
|
2251
|
+
"_avg",
|
|
2252
|
+
shape._avg
|
|
2253
|
+
);
|
|
2063
2254
|
if (shape._sum)
|
|
2064
|
-
schemaFields["_sum"] = argsBuilder.buildAggregateFieldSchema(
|
|
2255
|
+
schemaFields["_sum"] = argsBuilder.buildAggregateFieldSchema(
|
|
2256
|
+
model,
|
|
2257
|
+
"_sum",
|
|
2258
|
+
shape._sum
|
|
2259
|
+
);
|
|
2065
2260
|
if (shape._min)
|
|
2066
|
-
schemaFields["_min"] = argsBuilder.buildAggregateFieldSchema(
|
|
2261
|
+
schemaFields["_min"] = argsBuilder.buildAggregateFieldSchema(
|
|
2262
|
+
model,
|
|
2263
|
+
"_min",
|
|
2264
|
+
shape._min
|
|
2265
|
+
);
|
|
2067
2266
|
if (shape._max)
|
|
2068
|
-
schemaFields["_max"] = argsBuilder.buildAggregateFieldSchema(
|
|
2267
|
+
schemaFields["_max"] = argsBuilder.buildAggregateFieldSchema(
|
|
2268
|
+
model,
|
|
2269
|
+
"_max",
|
|
2270
|
+
shape._max
|
|
2271
|
+
);
|
|
2069
2272
|
if (shape.by)
|
|
2070
2273
|
schemaFields["by"] = argsBuilder.buildBySchema(model, shape.by);
|
|
2071
2274
|
if (shape.having)
|
|
2072
|
-
schemaFields["having"] = argsBuilder.buildHavingSchema(
|
|
2275
|
+
schemaFields["having"] = argsBuilder.buildHavingSchema(
|
|
2276
|
+
model,
|
|
2277
|
+
shape.having
|
|
2278
|
+
);
|
|
2073
2279
|
return {
|
|
2074
2280
|
zodSchema: import_zod7.z.object(schemaFields).strict(),
|
|
2075
2281
|
forcedWhere,
|
|
2282
|
+
forcedOnlyWhereKeys,
|
|
2076
2283
|
forcedIncludeTree,
|
|
2077
2284
|
forcedSelectTree,
|
|
2078
2285
|
forcedIncludeCountWhere,
|
|
@@ -2089,17 +2296,27 @@ function createQueryBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
|
|
|
2089
2296
|
const isSingle = typeof config === "function" || isShapeConfig(config);
|
|
2090
2297
|
const builtCache = /* @__PURE__ */ new Map();
|
|
2091
2298
|
if (isSingle && typeof config !== "function") {
|
|
2092
|
-
builtCache.set(
|
|
2299
|
+
builtCache.set(
|
|
2300
|
+
"_default",
|
|
2301
|
+
buildShapeZodSchema(model, method, config)
|
|
2302
|
+
);
|
|
2093
2303
|
}
|
|
2094
2304
|
if (!isSingle) {
|
|
2095
2305
|
for (const key of Object.keys(config)) {
|
|
2096
2306
|
if (SHAPE_CONFIG_KEYS.has(key)) {
|
|
2097
|
-
throw new ShapeError(
|
|
2307
|
+
throw new ShapeError(
|
|
2308
|
+
`Caller key "${key}" collides with reserved shape config key. Rename the caller path.`
|
|
2309
|
+
);
|
|
2098
2310
|
}
|
|
2099
2311
|
}
|
|
2100
|
-
for (const [key, shapeOrFn] of Object.entries(
|
|
2312
|
+
for (const [key, shapeOrFn] of Object.entries(
|
|
2313
|
+
config
|
|
2314
|
+
)) {
|
|
2101
2315
|
if (typeof shapeOrFn !== "function") {
|
|
2102
|
-
builtCache.set(
|
|
2316
|
+
builtCache.set(
|
|
2317
|
+
key,
|
|
2318
|
+
buildShapeZodSchema(model, method, shapeOrFn)
|
|
2319
|
+
);
|
|
2103
2320
|
}
|
|
2104
2321
|
}
|
|
2105
2322
|
}
|
|
@@ -2128,14 +2345,21 @@ function createQueryBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
|
|
|
2128
2345
|
}
|
|
2129
2346
|
const caller = opts?.caller;
|
|
2130
2347
|
if (typeof caller !== "string") {
|
|
2131
|
-
const allowed = Object.keys(
|
|
2348
|
+
const allowed = Object.keys(
|
|
2349
|
+
config
|
|
2350
|
+
);
|
|
2132
2351
|
throw new CallerError(
|
|
2133
2352
|
`Missing caller. This query uses named shape routing with keys: ${allowed.map((k) => `"${k}"`).join(", ")}. Provide caller via opts.caller.`
|
|
2134
2353
|
);
|
|
2135
2354
|
}
|
|
2136
|
-
const matched = matchCaller(
|
|
2355
|
+
const matched = matchCaller(
|
|
2356
|
+
config,
|
|
2357
|
+
caller
|
|
2358
|
+
);
|
|
2137
2359
|
if (!matched) {
|
|
2138
|
-
const allowed = Object.keys(
|
|
2360
|
+
const allowed = Object.keys(
|
|
2361
|
+
config
|
|
2362
|
+
);
|
|
2139
2363
|
throw new CallerError(
|
|
2140
2364
|
`Unknown caller: "${caller}". Allowed: ${allowed.map((k) => `"${k}"`).join(", ")}`
|
|
2141
2365
|
);
|
|
@@ -2768,7 +2992,10 @@ function resolveShape(input, body, contextFn, caller) {
|
|
|
2768
2992
|
|
|
2769
2993
|
// src/runtime/model-guard.ts
|
|
2770
2994
|
var UNIQUE_MUTATION_METHODS = /* @__PURE__ */ new Set(["update", "delete", "upsert"]);
|
|
2771
|
-
var UNIQUE_READ_METHODS = /* @__PURE__ */ new Set([
|
|
2995
|
+
var UNIQUE_READ_METHODS = /* @__PURE__ */ new Set([
|
|
2996
|
+
"findUnique",
|
|
2997
|
+
"findUniqueOrThrow"
|
|
2998
|
+
]);
|
|
2772
2999
|
var BULK_MUTATION_METHODS = /* @__PURE__ */ new Set([
|
|
2773
3000
|
"updateMany",
|
|
2774
3001
|
"updateManyAndReturn",
|
|
@@ -2782,15 +3009,14 @@ var PROJECTION_MUTATION_METHODS = /* @__PURE__ */ new Set([
|
|
|
2782
3009
|
"createManyAndReturn",
|
|
2783
3010
|
"updateManyAndReturn"
|
|
2784
3011
|
]);
|
|
2785
|
-
var BATCH_CREATE_METHODS = /* @__PURE__ */ new Set([
|
|
2786
|
-
"createMany",
|
|
2787
|
-
"createManyAndReturn"
|
|
2788
|
-
]);
|
|
3012
|
+
var BATCH_CREATE_METHODS = /* @__PURE__ */ new Set(["createMany", "createManyAndReturn"]);
|
|
2789
3013
|
function buildDefaultSelectInput(config) {
|
|
2790
3014
|
const result = {};
|
|
2791
3015
|
for (const [key, value] of Object.entries(config)) {
|
|
2792
3016
|
if (key === "_count") {
|
|
2793
|
-
result[key] = buildDefaultCountInput(
|
|
3017
|
+
result[key] = buildDefaultCountInput(
|
|
3018
|
+
value
|
|
3019
|
+
);
|
|
2794
3020
|
continue;
|
|
2795
3021
|
}
|
|
2796
3022
|
if (value === true) {
|
|
@@ -2808,7 +3034,9 @@ function buildDefaultIncludeInput(config) {
|
|
|
2808
3034
|
const result = {};
|
|
2809
3035
|
for (const [key, value] of Object.entries(config)) {
|
|
2810
3036
|
if (key === "_count") {
|
|
2811
|
-
result[key] = buildDefaultCountInput(
|
|
3037
|
+
result[key] = buildDefaultCountInput(
|
|
3038
|
+
value
|
|
3039
|
+
);
|
|
2812
3040
|
continue;
|
|
2813
3041
|
}
|
|
2814
3042
|
if (value === true) {
|
|
@@ -2922,12 +3150,32 @@ function hasNestedClientControlledArgs(shape) {
|
|
|
2922
3150
|
return false;
|
|
2923
3151
|
}
|
|
2924
3152
|
function createModelGuardExtension(config) {
|
|
2925
|
-
const {
|
|
3153
|
+
const {
|
|
3154
|
+
typeMap,
|
|
3155
|
+
enumMap,
|
|
3156
|
+
zodChains,
|
|
3157
|
+
zodDefaults,
|
|
3158
|
+
uniqueMap,
|
|
3159
|
+
scopeMap,
|
|
3160
|
+
guardConfig,
|
|
3161
|
+
contextFn
|
|
3162
|
+
} = config;
|
|
2926
3163
|
const wrapZodErrors = config.wrapZodErrors ?? false;
|
|
2927
3164
|
const enforceProjection = guardConfig.enforceProjection ?? false;
|
|
2928
3165
|
const scalarBase = createScalarBase(guardConfig.strictDecimal ?? false);
|
|
2929
|
-
const schemaBuilder = createSchemaBuilder(
|
|
2930
|
-
|
|
3166
|
+
const schemaBuilder = createSchemaBuilder(
|
|
3167
|
+
typeMap,
|
|
3168
|
+
zodChains,
|
|
3169
|
+
enumMap,
|
|
3170
|
+
scalarBase,
|
|
3171
|
+
zodDefaults
|
|
3172
|
+
);
|
|
3173
|
+
const queryBuilder = createQueryBuilder(
|
|
3174
|
+
typeMap,
|
|
3175
|
+
enumMap,
|
|
3176
|
+
uniqueMap,
|
|
3177
|
+
scalarBase
|
|
3178
|
+
);
|
|
2931
3179
|
const modelScopeFks = /* @__PURE__ */ new Map();
|
|
2932
3180
|
for (const [model, entries] of Object.entries(scopeMap)) {
|
|
2933
3181
|
const fks = /* @__PURE__ */ new Set();
|
|
@@ -2945,7 +3193,9 @@ function createModelGuardExtension(config) {
|
|
|
2945
3193
|
function createGuardedMethods(modelName, modelDelegate, input, explicitCaller) {
|
|
2946
3194
|
function callDelegate(method, args) {
|
|
2947
3195
|
if (typeof modelDelegate[method] !== "function") {
|
|
2948
|
-
throw new ShapeError(
|
|
3196
|
+
throw new ShapeError(
|
|
3197
|
+
`Method "${method}" is not available on this model`
|
|
3198
|
+
);
|
|
2949
3199
|
}
|
|
2950
3200
|
return modelDelegate[method](args);
|
|
2951
3201
|
}
|
|
@@ -2968,11 +3218,19 @@ function createModelGuardExtension(config) {
|
|
|
2968
3218
|
const cached = readShapeCache.get(cacheKey);
|
|
2969
3219
|
if (cached)
|
|
2970
3220
|
return cached;
|
|
2971
|
-
const built = queryBuilder.buildShapeZodSchema(
|
|
3221
|
+
const built = queryBuilder.buildShapeZodSchema(
|
|
3222
|
+
modelName,
|
|
3223
|
+
method,
|
|
3224
|
+
queryShape
|
|
3225
|
+
);
|
|
2972
3226
|
readShapeCache.set(cacheKey, built);
|
|
2973
3227
|
return built;
|
|
2974
3228
|
}
|
|
2975
|
-
return queryBuilder.buildShapeZodSchema(
|
|
3229
|
+
return queryBuilder.buildShapeZodSchema(
|
|
3230
|
+
modelName,
|
|
3231
|
+
method,
|
|
3232
|
+
queryShape
|
|
3233
|
+
);
|
|
2976
3234
|
}
|
|
2977
3235
|
function getDataSchema(mode, dataConfig, matchedKey, wasDynamic) {
|
|
2978
3236
|
if (!wasDynamic && !hasDataRefines(dataConfig)) {
|
|
@@ -2980,11 +3238,25 @@ function createModelGuardExtension(config) {
|
|
|
2980
3238
|
const cached = dataSchemaCache.get(cacheKey);
|
|
2981
3239
|
if (cached)
|
|
2982
3240
|
return cached;
|
|
2983
|
-
const built = buildDataSchema(
|
|
3241
|
+
const built = buildDataSchema(
|
|
3242
|
+
modelName,
|
|
3243
|
+
dataConfig,
|
|
3244
|
+
mode,
|
|
3245
|
+
typeMap,
|
|
3246
|
+
schemaBuilder,
|
|
3247
|
+
zodDefaults
|
|
3248
|
+
);
|
|
2984
3249
|
dataSchemaCache.set(cacheKey, built);
|
|
2985
3250
|
return built;
|
|
2986
3251
|
}
|
|
2987
|
-
return buildDataSchema(
|
|
3252
|
+
return buildDataSchema(
|
|
3253
|
+
modelName,
|
|
3254
|
+
dataConfig,
|
|
3255
|
+
mode,
|
|
3256
|
+
typeMap,
|
|
3257
|
+
schemaBuilder,
|
|
3258
|
+
zodDefaults
|
|
3259
|
+
);
|
|
2988
3260
|
}
|
|
2989
3261
|
function getWhereBuilt(whereConfig, matchedKey, wasDynamic) {
|
|
2990
3262
|
if (!wasDynamic) {
|
|
@@ -3103,12 +3375,28 @@ function createModelGuardExtension(config) {
|
|
|
3103
3375
|
const built = getWhereBuilt(shape.where, matchedKey, wasDynamic);
|
|
3104
3376
|
let validatedWhere;
|
|
3105
3377
|
if (built.schema) {
|
|
3106
|
-
|
|
3378
|
+
let sanitizedWhere = bodyWhere;
|
|
3379
|
+
if (built.forcedOnlyKeys.size > 0 && isPlainObject(bodyWhere)) {
|
|
3380
|
+
const w = { ...bodyWhere };
|
|
3381
|
+
for (const key of built.forcedOnlyKeys) {
|
|
3382
|
+
delete w[key];
|
|
3383
|
+
}
|
|
3384
|
+
sanitizedWhere = w;
|
|
3385
|
+
}
|
|
3386
|
+
validatedWhere = built.schema.parse(sanitizedWhere);
|
|
3107
3387
|
} else if (bodyWhere !== void 0) {
|
|
3108
3388
|
if (bodyWhere === null || !isPlainObject(bodyWhere) || Object.keys(bodyWhere).length > 0) {
|
|
3109
|
-
|
|
3110
|
-
|
|
3111
|
-
|
|
3389
|
+
let hasOnlyForcedKeys = false;
|
|
3390
|
+
if (isPlainObject(bodyWhere) && built.forcedOnlyKeys.size > 0) {
|
|
3391
|
+
hasOnlyForcedKeys = Object.keys(bodyWhere).every(
|
|
3392
|
+
(k) => built.forcedOnlyKeys.has(k)
|
|
3393
|
+
);
|
|
3394
|
+
}
|
|
3395
|
+
if (!hasOnlyForcedKeys) {
|
|
3396
|
+
throw new ShapeError(
|
|
3397
|
+
"Guard shape where contains only forced conditions. Client where input is not accepted."
|
|
3398
|
+
);
|
|
3399
|
+
}
|
|
3112
3400
|
}
|
|
3113
3401
|
}
|
|
3114
3402
|
if (hasWhereForced(built.forced)) {
|
|
@@ -3117,7 +3405,13 @@ function createModelGuardExtension(config) {
|
|
|
3117
3405
|
return validatedWhere ?? {};
|
|
3118
3406
|
}
|
|
3119
3407
|
function requireWhere(shape, bodyWhere, method, preserveUnique, matchedKey, wasDynamic) {
|
|
3120
|
-
const where = buildWhereFromShape(
|
|
3408
|
+
const where = buildWhereFromShape(
|
|
3409
|
+
shape,
|
|
3410
|
+
bodyWhere,
|
|
3411
|
+
preserveUnique,
|
|
3412
|
+
matchedKey,
|
|
3413
|
+
wasDynamic
|
|
3414
|
+
);
|
|
3121
3415
|
if (Object.keys(where).length === 0) {
|
|
3122
3416
|
throw new ShapeError(`${method} requires a where condition`);
|
|
3123
3417
|
}
|
|
@@ -3131,7 +3425,12 @@ function createModelGuardExtension(config) {
|
|
|
3131
3425
|
throw new ShapeError(`Guard shape "data" is not valid for ${method}`);
|
|
3132
3426
|
}
|
|
3133
3427
|
const { data: _, ...queryShape } = resolved.shape;
|
|
3134
|
-
const built = getReadShape(
|
|
3428
|
+
const built = getReadShape(
|
|
3429
|
+
method,
|
|
3430
|
+
queryShape,
|
|
3431
|
+
resolved.matchedKey,
|
|
3432
|
+
resolved.wasDynamic
|
|
3433
|
+
);
|
|
3135
3434
|
const isUnique = UNIQUE_READ_METHODS.has(method);
|
|
3136
3435
|
const args = applyBuiltShape(built, resolved.body, isUnique);
|
|
3137
3436
|
if (isUnique && args.where) {
|
|
@@ -3164,14 +3463,33 @@ function createModelGuardExtension(config) {
|
|
|
3164
3463
|
const resolved = resolveShape(input, body, contextFn, caller);
|
|
3165
3464
|
if (!resolved.shape.data)
|
|
3166
3465
|
throw new ShapeError(`Guard shape requires "data" for ${method}`);
|
|
3167
|
-
validateMutationShapeKeys(
|
|
3466
|
+
validateMutationShapeKeys(
|
|
3467
|
+
resolved.shape,
|
|
3468
|
+
allowedShapeKeys,
|
|
3469
|
+
method
|
|
3470
|
+
);
|
|
3168
3471
|
validateMutationBodyKeys(resolved.body, allowedBodyKeys, method);
|
|
3169
3472
|
const fks = modelScopeFks.get(modelName) ?? /* @__PURE__ */ new Set();
|
|
3170
|
-
validateCreateCompleteness(
|
|
3171
|
-
|
|
3473
|
+
validateCreateCompleteness(
|
|
3474
|
+
modelName,
|
|
3475
|
+
resolved.shape.data,
|
|
3476
|
+
typeMap,
|
|
3477
|
+
fks,
|
|
3478
|
+
zodDefaults
|
|
3479
|
+
);
|
|
3480
|
+
const dataSchema = getDataSchema(
|
|
3481
|
+
"create",
|
|
3482
|
+
resolved.shape.data,
|
|
3483
|
+
resolved.matchedKey,
|
|
3484
|
+
resolved.wasDynamic
|
|
3485
|
+
);
|
|
3172
3486
|
let args;
|
|
3173
3487
|
if (method === "create") {
|
|
3174
|
-
const data = validateAndMergeData(
|
|
3488
|
+
const data = validateAndMergeData(
|
|
3489
|
+
resolved.body.data,
|
|
3490
|
+
dataSchema,
|
|
3491
|
+
method
|
|
3492
|
+
);
|
|
3175
3493
|
args = { data };
|
|
3176
3494
|
} else {
|
|
3177
3495
|
if (!Array.isArray(resolved.body.data))
|
|
@@ -3190,7 +3508,13 @@ function createModelGuardExtension(config) {
|
|
|
3190
3508
|
args.skipDuplicates = resolved.body.skipDuplicates;
|
|
3191
3509
|
}
|
|
3192
3510
|
if (supportsProjection) {
|
|
3193
|
-
const projectionArgs = resolveProjection(
|
|
3511
|
+
const projectionArgs = resolveProjection(
|
|
3512
|
+
resolved.shape,
|
|
3513
|
+
resolved.body,
|
|
3514
|
+
method,
|
|
3515
|
+
resolved.matchedKey,
|
|
3516
|
+
resolved.wasDynamic
|
|
3517
|
+
);
|
|
3194
3518
|
Object.assign(args, projectionArgs);
|
|
3195
3519
|
}
|
|
3196
3520
|
return callDelegate(method, args);
|
|
@@ -3207,24 +3531,60 @@ function createModelGuardExtension(config) {
|
|
|
3207
3531
|
const resolved = resolveShape(input, body, contextFn, caller);
|
|
3208
3532
|
if (!resolved.shape.data)
|
|
3209
3533
|
throw new ShapeError(`Guard shape requires "data" for ${method}`);
|
|
3210
|
-
validateMutationShapeKeys(
|
|
3534
|
+
validateMutationShapeKeys(
|
|
3535
|
+
resolved.shape,
|
|
3536
|
+
allowedShapeKeys,
|
|
3537
|
+
method
|
|
3538
|
+
);
|
|
3211
3539
|
validateMutationBodyKeys(resolved.body, allowedBodyKeys, method);
|
|
3212
3540
|
if (isBulk && !resolved.shape.where) {
|
|
3213
|
-
throw new ShapeError(
|
|
3541
|
+
throw new ShapeError(
|
|
3542
|
+
`Guard shape requires "where" for ${method} to prevent unconstrained bulk mutations`
|
|
3543
|
+
);
|
|
3214
3544
|
}
|
|
3215
3545
|
maybeValidateUniqueWhere(modelName, resolved.shape, method);
|
|
3216
|
-
const dataSchema = getDataSchema(
|
|
3217
|
-
|
|
3218
|
-
|
|
3546
|
+
const dataSchema = getDataSchema(
|
|
3547
|
+
"update",
|
|
3548
|
+
resolved.shape.data,
|
|
3549
|
+
resolved.matchedKey,
|
|
3550
|
+
resolved.wasDynamic
|
|
3551
|
+
);
|
|
3552
|
+
const data = validateAndMergeData(
|
|
3553
|
+
resolved.body.data,
|
|
3554
|
+
dataSchema,
|
|
3555
|
+
method
|
|
3556
|
+
);
|
|
3557
|
+
const where = isUniqueWhere ? requireWhere(
|
|
3558
|
+
resolved.shape,
|
|
3559
|
+
resolved.body.where,
|
|
3560
|
+
method,
|
|
3561
|
+
true,
|
|
3562
|
+
resolved.matchedKey,
|
|
3563
|
+
resolved.wasDynamic
|
|
3564
|
+
) : buildWhereFromShape(
|
|
3565
|
+
resolved.shape,
|
|
3566
|
+
resolved.body.where,
|
|
3567
|
+
false,
|
|
3568
|
+
resolved.matchedKey,
|
|
3569
|
+
resolved.wasDynamic
|
|
3570
|
+
);
|
|
3219
3571
|
if (isBulk && Object.keys(where).length === 0) {
|
|
3220
|
-
throw new ShapeError(
|
|
3572
|
+
throw new ShapeError(
|
|
3573
|
+
`${method} requires at least one where condition`
|
|
3574
|
+
);
|
|
3221
3575
|
}
|
|
3222
3576
|
if (isUniqueWhere) {
|
|
3223
3577
|
validateResolvedUniqueWhere(modelName, where, method, uniqueMap);
|
|
3224
3578
|
}
|
|
3225
3579
|
const args = { data, where };
|
|
3226
3580
|
if (supportsProjection) {
|
|
3227
|
-
const projectionArgs = resolveProjection(
|
|
3581
|
+
const projectionArgs = resolveProjection(
|
|
3582
|
+
resolved.shape,
|
|
3583
|
+
resolved.body,
|
|
3584
|
+
method,
|
|
3585
|
+
resolved.matchedKey,
|
|
3586
|
+
resolved.wasDynamic
|
|
3587
|
+
);
|
|
3228
3588
|
Object.assign(args, projectionArgs);
|
|
3229
3589
|
}
|
|
3230
3590
|
return callDelegate(method, args);
|
|
@@ -3241,22 +3601,49 @@ function createModelGuardExtension(config) {
|
|
|
3241
3601
|
const resolved = resolveShape(input, body, contextFn, caller);
|
|
3242
3602
|
if (resolved.shape.data)
|
|
3243
3603
|
throw new ShapeError(`Guard shape "data" is not valid for ${method}`);
|
|
3244
|
-
validateMutationShapeKeys(
|
|
3604
|
+
validateMutationShapeKeys(
|
|
3605
|
+
resolved.shape,
|
|
3606
|
+
allowedShapeKeys,
|
|
3607
|
+
method
|
|
3608
|
+
);
|
|
3245
3609
|
validateMutationBodyKeys(resolved.body, allowedBodyKeys, method);
|
|
3246
3610
|
if (isBulk && !resolved.shape.where) {
|
|
3247
|
-
throw new ShapeError(
|
|
3611
|
+
throw new ShapeError(
|
|
3612
|
+
`Guard shape requires "where" for ${method} to prevent unconstrained bulk mutations`
|
|
3613
|
+
);
|
|
3248
3614
|
}
|
|
3249
3615
|
maybeValidateUniqueWhere(modelName, resolved.shape, method);
|
|
3250
|
-
const where = isUniqueWhere ? requireWhere(
|
|
3616
|
+
const where = isUniqueWhere ? requireWhere(
|
|
3617
|
+
resolved.shape,
|
|
3618
|
+
resolved.body.where,
|
|
3619
|
+
method,
|
|
3620
|
+
true,
|
|
3621
|
+
resolved.matchedKey,
|
|
3622
|
+
resolved.wasDynamic
|
|
3623
|
+
) : buildWhereFromShape(
|
|
3624
|
+
resolved.shape,
|
|
3625
|
+
resolved.body.where,
|
|
3626
|
+
false,
|
|
3627
|
+
resolved.matchedKey,
|
|
3628
|
+
resolved.wasDynamic
|
|
3629
|
+
);
|
|
3251
3630
|
if (isBulk && Object.keys(where).length === 0) {
|
|
3252
|
-
throw new ShapeError(
|
|
3631
|
+
throw new ShapeError(
|
|
3632
|
+
`${method} requires at least one where condition`
|
|
3633
|
+
);
|
|
3253
3634
|
}
|
|
3254
3635
|
if (isUniqueWhere) {
|
|
3255
3636
|
validateResolvedUniqueWhere(modelName, where, method, uniqueMap);
|
|
3256
3637
|
}
|
|
3257
3638
|
const args = { where };
|
|
3258
3639
|
if (supportsProjection) {
|
|
3259
|
-
const projectionArgs = resolveProjection(
|
|
3640
|
+
const projectionArgs = resolveProjection(
|
|
3641
|
+
resolved.shape,
|
|
3642
|
+
resolved.body,
|
|
3643
|
+
method,
|
|
3644
|
+
resolved.matchedKey,
|
|
3645
|
+
resolved.wasDynamic
|
|
3646
|
+
);
|
|
3260
3647
|
Object.assign(args, projectionArgs);
|
|
3261
3648
|
}
|
|
3262
3649
|
return callDelegate(method, args);
|
|
@@ -3267,7 +3654,9 @@ function createModelGuardExtension(config) {
|
|
|
3267
3654
|
const caller = resolveCaller();
|
|
3268
3655
|
const resolved = resolveShape(input, body, contextFn, caller);
|
|
3269
3656
|
if (resolved.shape.data) {
|
|
3270
|
-
throw new ShapeError(
|
|
3657
|
+
throw new ShapeError(
|
|
3658
|
+
'Guard shape "data" is not valid for upsert. Use "create" and "update" instead.'
|
|
3659
|
+
);
|
|
3271
3660
|
}
|
|
3272
3661
|
if (!resolved.shape.create) {
|
|
3273
3662
|
throw new ShapeError('Guard shape requires "create" for upsert');
|
|
@@ -3283,24 +3672,42 @@ function createModelGuardExtension(config) {
|
|
|
3283
3672
|
VALID_SHAPE_KEYS_UPSERT,
|
|
3284
3673
|
"upsert"
|
|
3285
3674
|
);
|
|
3286
|
-
validateMutationBodyKeys(
|
|
3675
|
+
validateMutationBodyKeys(
|
|
3676
|
+
resolved.body,
|
|
3677
|
+
ALLOWED_BODY_KEYS_UPSERT,
|
|
3678
|
+
"upsert"
|
|
3679
|
+
);
|
|
3287
3680
|
maybeValidateUniqueWhere(modelName, resolved.shape, "upsert");
|
|
3288
3681
|
const fks = modelScopeFks.get(modelName) ?? /* @__PURE__ */ new Set();
|
|
3289
|
-
validateCreateCompleteness(
|
|
3682
|
+
validateCreateCompleteness(
|
|
3683
|
+
modelName,
|
|
3684
|
+
resolved.shape.create,
|
|
3685
|
+
typeMap,
|
|
3686
|
+
fks,
|
|
3687
|
+
zodDefaults
|
|
3688
|
+
);
|
|
3290
3689
|
const createDataSchema = getDataSchema(
|
|
3291
3690
|
"create",
|
|
3292
3691
|
resolved.shape.create,
|
|
3293
3692
|
`upsert:create\0${resolved.matchedKey}`,
|
|
3294
3693
|
resolved.wasDynamic
|
|
3295
3694
|
);
|
|
3296
|
-
const createData = validateAndMergeData(
|
|
3695
|
+
const createData = validateAndMergeData(
|
|
3696
|
+
resolved.body.create,
|
|
3697
|
+
createDataSchema,
|
|
3698
|
+
"upsert (create)"
|
|
3699
|
+
);
|
|
3297
3700
|
const updateDataSchema = getDataSchema(
|
|
3298
3701
|
"update",
|
|
3299
3702
|
resolved.shape.update,
|
|
3300
3703
|
`upsert:update\0${resolved.matchedKey}`,
|
|
3301
3704
|
resolved.wasDynamic
|
|
3302
3705
|
);
|
|
3303
|
-
const updateData = validateAndMergeData(
|
|
3706
|
+
const updateData = validateAndMergeData(
|
|
3707
|
+
resolved.body.update,
|
|
3708
|
+
updateDataSchema,
|
|
3709
|
+
"upsert (update)"
|
|
3710
|
+
);
|
|
3304
3711
|
const where = requireWhere(
|
|
3305
3712
|
resolved.shape,
|
|
3306
3713
|
resolved.body.where,
|
|
@@ -3354,10 +3761,9 @@ function createModelGuardExtension(config) {
|
|
|
3354
3761
|
return fn(body);
|
|
3355
3762
|
} catch (err) {
|
|
3356
3763
|
if (err instanceof import_zod9.z.ZodError) {
|
|
3357
|
-
throw new ShapeError(
|
|
3358
|
-
|
|
3359
|
-
|
|
3360
|
-
);
|
|
3764
|
+
throw new ShapeError(`Validation failed: ${formatZodError(err)}`, {
|
|
3765
|
+
cause: err
|
|
3766
|
+
});
|
|
3361
3767
|
}
|
|
3362
3768
|
throw err;
|
|
3363
3769
|
}
|
|
@@ -3376,7 +3782,12 @@ function createModelGuardExtension(config) {
|
|
|
3376
3782
|
`Could not resolve Prisma delegate for model "${modelName}" (key: "${delegateKey}")`
|
|
3377
3783
|
);
|
|
3378
3784
|
}
|
|
3379
|
-
const methods = createGuardedMethods(
|
|
3785
|
+
const methods = createGuardedMethods(
|
|
3786
|
+
modelName,
|
|
3787
|
+
modelDelegate,
|
|
3788
|
+
input,
|
|
3789
|
+
caller
|
|
3790
|
+
);
|
|
3380
3791
|
if (!wrapZodErrors)
|
|
3381
3792
|
return methods;
|
|
3382
3793
|
return wrapMethods(methods);
|