prisma-guard 1.4.0 → 1.4.1
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 +469 -94
- package/dist/runtime/index.cjs.map +1 -1
- package/dist/runtime/index.js +469 -94
- 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 {
|
|
@@ -1229,7 +1279,12 @@ function createWhereBuilder(typeMap, enumMap, scalarBase) {
|
|
|
1229
1279
|
const clientOpKeys = [];
|
|
1230
1280
|
for (const [op, opValue] of Object.entries(operators)) {
|
|
1231
1281
|
if (opValue === true) {
|
|
1232
|
-
opSchemas[op] = createOperatorSchema(
|
|
1282
|
+
opSchemas[op] = createOperatorSchema(
|
|
1283
|
+
fieldMeta,
|
|
1284
|
+
op,
|
|
1285
|
+
enumMap,
|
|
1286
|
+
scalarBase
|
|
1287
|
+
).optional();
|
|
1233
1288
|
hasClientOps = true;
|
|
1234
1289
|
clientOpKeys.push(op);
|
|
1235
1290
|
if (fieldMeta.type === "String" && !fieldMeta.isList && STRING_MODE_OPS.has(op)) {
|
|
@@ -1237,7 +1292,12 @@ function createWhereBuilder(typeMap, enumMap, scalarBase) {
|
|
|
1237
1292
|
}
|
|
1238
1293
|
} else {
|
|
1239
1294
|
const actualOpValue = isForcedValue(opValue) ? opValue.value : opValue;
|
|
1240
|
-
const opSchema = createOperatorSchema(
|
|
1295
|
+
const opSchema = createOperatorSchema(
|
|
1296
|
+
fieldMeta,
|
|
1297
|
+
op,
|
|
1298
|
+
enumMap,
|
|
1299
|
+
scalarBase
|
|
1300
|
+
);
|
|
1241
1301
|
let parsed;
|
|
1242
1302
|
try {
|
|
1243
1303
|
parsed = opSchema.parse(actualOpValue);
|
|
@@ -1260,8 +1320,12 @@ function createWhereBuilder(typeMap, enumMap, scalarBase) {
|
|
|
1260
1320
|
if (hasClientOps) {
|
|
1261
1321
|
const opObj = import_zod4.z.object(opSchemas).strict();
|
|
1262
1322
|
fieldSchemas[fieldName] = opObj.refine(
|
|
1263
|
-
(v) => clientOpKeys.some(
|
|
1264
|
-
|
|
1323
|
+
(v) => clientOpKeys.some(
|
|
1324
|
+
(k) => v[k] !== void 0
|
|
1325
|
+
),
|
|
1326
|
+
{
|
|
1327
|
+
message: `At least one operator required for where field "${fieldName}"`
|
|
1328
|
+
}
|
|
1265
1329
|
).optional();
|
|
1266
1330
|
}
|
|
1267
1331
|
if (Object.keys(fieldForced).length > 0) {
|
|
@@ -1927,19 +1991,77 @@ function createProjectionBuilder(typeMap, enumMap, deps) {
|
|
|
1927
1991
|
|
|
1928
1992
|
// src/runtime/query-builder.ts
|
|
1929
1993
|
var METHOD_ALLOWED_ARGS = {
|
|
1930
|
-
findMany: /* @__PURE__ */ new Set([
|
|
1931
|
-
|
|
1932
|
-
|
|
1994
|
+
findMany: /* @__PURE__ */ new Set([
|
|
1995
|
+
"where",
|
|
1996
|
+
"include",
|
|
1997
|
+
"select",
|
|
1998
|
+
"orderBy",
|
|
1999
|
+
"cursor",
|
|
2000
|
+
"take",
|
|
2001
|
+
"skip",
|
|
2002
|
+
"distinct"
|
|
2003
|
+
]),
|
|
2004
|
+
findFirst: /* @__PURE__ */ new Set([
|
|
2005
|
+
"where",
|
|
2006
|
+
"include",
|
|
2007
|
+
"select",
|
|
2008
|
+
"orderBy",
|
|
2009
|
+
"cursor",
|
|
2010
|
+
"take",
|
|
2011
|
+
"skip",
|
|
2012
|
+
"distinct"
|
|
2013
|
+
]),
|
|
2014
|
+
findFirstOrThrow: /* @__PURE__ */ new Set([
|
|
2015
|
+
"where",
|
|
2016
|
+
"include",
|
|
2017
|
+
"select",
|
|
2018
|
+
"orderBy",
|
|
2019
|
+
"cursor",
|
|
2020
|
+
"take",
|
|
2021
|
+
"skip",
|
|
2022
|
+
"distinct"
|
|
2023
|
+
]),
|
|
1933
2024
|
findUnique: /* @__PURE__ */ new Set(["where", "include", "select"]),
|
|
1934
2025
|
findUniqueOrThrow: /* @__PURE__ */ new Set(["where", "include", "select"]),
|
|
1935
2026
|
count: /* @__PURE__ */ new Set(["where", "select", "cursor", "orderBy", "skip", "take"]),
|
|
1936
|
-
aggregate: /* @__PURE__ */ new Set([
|
|
1937
|
-
|
|
2027
|
+
aggregate: /* @__PURE__ */ new Set([
|
|
2028
|
+
"where",
|
|
2029
|
+
"orderBy",
|
|
2030
|
+
"cursor",
|
|
2031
|
+
"take",
|
|
2032
|
+
"skip",
|
|
2033
|
+
"_count",
|
|
2034
|
+
"_avg",
|
|
2035
|
+
"_sum",
|
|
2036
|
+
"_min",
|
|
2037
|
+
"_max"
|
|
2038
|
+
]),
|
|
2039
|
+
groupBy: /* @__PURE__ */ new Set([
|
|
2040
|
+
"where",
|
|
2041
|
+
"by",
|
|
2042
|
+
"having",
|
|
2043
|
+
"_count",
|
|
2044
|
+
"_avg",
|
|
2045
|
+
"_sum",
|
|
2046
|
+
"_min",
|
|
2047
|
+
"_max",
|
|
2048
|
+
"orderBy",
|
|
2049
|
+
"take",
|
|
2050
|
+
"skip"
|
|
2051
|
+
])
|
|
1938
2052
|
};
|
|
1939
|
-
var UNIQUE_WHERE_METHODS = /* @__PURE__ */ new Set([
|
|
2053
|
+
var UNIQUE_WHERE_METHODS = /* @__PURE__ */ new Set([
|
|
2054
|
+
"findUnique",
|
|
2055
|
+
"findUniqueOrThrow"
|
|
2056
|
+
]);
|
|
1940
2057
|
function createQueryBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
|
|
1941
2058
|
const whereBuilder = createWhereBuilder(typeMap, enumMap, scalarBase);
|
|
1942
|
-
const argsBuilder = createArgsBuilder(
|
|
2059
|
+
const argsBuilder = createArgsBuilder(
|
|
2060
|
+
typeMap,
|
|
2061
|
+
enumMap,
|
|
2062
|
+
uniqueMap,
|
|
2063
|
+
scalarBase
|
|
2064
|
+
);
|
|
1943
2065
|
const projectionBuilder = createProjectionBuilder(typeMap, enumMap, {
|
|
1944
2066
|
buildWhereSchema: whereBuilder.buildWhereSchema,
|
|
1945
2067
|
buildOrderBySchema: argsBuilder.buildOrderBySchema,
|
|
@@ -1964,7 +2086,9 @@ function createQueryBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
|
|
|
1964
2086
|
throw new ShapeError(`${method} shape must define "where"`);
|
|
1965
2087
|
}
|
|
1966
2088
|
if (shape.include && shape.select) {
|
|
1967
|
-
throw new ShapeError(
|
|
2089
|
+
throw new ShapeError(
|
|
2090
|
+
'Shape config cannot define both "include" and "select".'
|
|
2091
|
+
);
|
|
1968
2092
|
}
|
|
1969
2093
|
if (method === "groupBy" && !shape.by)
|
|
1970
2094
|
throw new ShapeError('groupBy shape must define "by"');
|
|
@@ -1980,7 +2104,9 @@ function createQueryBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
|
|
|
1980
2104
|
const bySet = new Set(shape.by);
|
|
1981
2105
|
for (const fieldName of Object.keys(shape.orderBy)) {
|
|
1982
2106
|
if (!bySet.has(fieldName)) {
|
|
1983
|
-
throw new ShapeError(
|
|
2107
|
+
throw new ShapeError(
|
|
2108
|
+
`orderBy field "${fieldName}" must be included in "by" for groupBy`
|
|
2109
|
+
);
|
|
1984
2110
|
}
|
|
1985
2111
|
}
|
|
1986
2112
|
}
|
|
@@ -1988,7 +2114,9 @@ function createQueryBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
|
|
|
1988
2114
|
const bySet = new Set(shape.by);
|
|
1989
2115
|
for (const fieldName of Object.keys(shape.having)) {
|
|
1990
2116
|
if (!bySet.has(fieldName)) {
|
|
1991
|
-
throw new ShapeError(
|
|
2117
|
+
throw new ShapeError(
|
|
2118
|
+
`having field "${fieldName}" must be included in "by" for groupBy`
|
|
2119
|
+
);
|
|
1992
2120
|
}
|
|
1993
2121
|
}
|
|
1994
2122
|
}
|
|
@@ -2005,7 +2133,9 @@ function createQueryBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
|
|
|
2005
2133
|
requireContext(ctx, "shape function");
|
|
2006
2134
|
const result = shapeOrFn(ctx);
|
|
2007
2135
|
if (!isPlainObject(result)) {
|
|
2008
|
-
throw new ShapeError(
|
|
2136
|
+
throw new ShapeError(
|
|
2137
|
+
"Dynamic shape function must return a plain object"
|
|
2138
|
+
);
|
|
2009
2139
|
}
|
|
2010
2140
|
return result;
|
|
2011
2141
|
}
|
|
@@ -2016,15 +2146,20 @@ function createQueryBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
|
|
|
2016
2146
|
validateUniqueWhere(model, method, shape);
|
|
2017
2147
|
const schemaFields = {};
|
|
2018
2148
|
let forcedWhere = EMPTY_WHERE_FORCED;
|
|
2149
|
+
let forcedOnlyWhereKeys = /* @__PURE__ */ new Set();
|
|
2019
2150
|
let forcedIncludeTree = {};
|
|
2020
2151
|
let forcedSelectTree = {};
|
|
2021
2152
|
let forcedIncludeCountWhere = {};
|
|
2022
2153
|
let forcedSelectCountWhere = {};
|
|
2023
2154
|
if (shape.where) {
|
|
2024
|
-
const { schema, forced } = whereBuilder.buildWhereSchema(
|
|
2155
|
+
const { schema, forced, forcedOnlyKeys } = whereBuilder.buildWhereSchema(
|
|
2156
|
+
model,
|
|
2157
|
+
shape.where
|
|
2158
|
+
);
|
|
2025
2159
|
if (schema)
|
|
2026
2160
|
schemaFields["where"] = schema;
|
|
2027
2161
|
forcedWhere = forced;
|
|
2162
|
+
forcedOnlyWhereKeys = forcedOnlyKeys;
|
|
2028
2163
|
}
|
|
2029
2164
|
if (shape.include) {
|
|
2030
2165
|
const result = projectionBuilder.buildIncludeSchema(model, shape.include);
|
|
@@ -2034,7 +2169,10 @@ function createQueryBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
|
|
|
2034
2169
|
}
|
|
2035
2170
|
if (shape.select) {
|
|
2036
2171
|
if (method === "count") {
|
|
2037
|
-
schemaFields["select"] = argsBuilder.buildCountSelectSchema(
|
|
2172
|
+
schemaFields["select"] = argsBuilder.buildCountSelectSchema(
|
|
2173
|
+
model,
|
|
2174
|
+
shape.select
|
|
2175
|
+
);
|
|
2038
2176
|
} else {
|
|
2039
2177
|
const result = projectionBuilder.buildSelectSchema(model, shape.select);
|
|
2040
2178
|
schemaFields["select"] = result.schema;
|
|
@@ -2043,9 +2181,15 @@ function createQueryBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
|
|
|
2043
2181
|
}
|
|
2044
2182
|
}
|
|
2045
2183
|
if (shape.orderBy)
|
|
2046
|
-
schemaFields["orderBy"] = argsBuilder.buildOrderBySchema(
|
|
2184
|
+
schemaFields["orderBy"] = argsBuilder.buildOrderBySchema(
|
|
2185
|
+
model,
|
|
2186
|
+
shape.orderBy
|
|
2187
|
+
);
|
|
2047
2188
|
if (shape.cursor)
|
|
2048
|
-
schemaFields["cursor"] = argsBuilder.buildCursorSchema(
|
|
2189
|
+
schemaFields["cursor"] = argsBuilder.buildCursorSchema(
|
|
2190
|
+
model,
|
|
2191
|
+
shape.cursor
|
|
2192
|
+
);
|
|
2049
2193
|
if (shape.take)
|
|
2050
2194
|
schemaFields["take"] = argsBuilder.buildTakeSchema(shape.take);
|
|
2051
2195
|
if (shape.skip !== void 0) {
|
|
@@ -2055,24 +2199,51 @@ function createQueryBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
|
|
|
2055
2199
|
schemaFields["skip"] = import_zod7.z.number().int().min(0).optional();
|
|
2056
2200
|
}
|
|
2057
2201
|
if (shape.distinct)
|
|
2058
|
-
schemaFields["distinct"] = argsBuilder.buildDistinctSchema(
|
|
2202
|
+
schemaFields["distinct"] = argsBuilder.buildDistinctSchema(
|
|
2203
|
+
model,
|
|
2204
|
+
shape.distinct
|
|
2205
|
+
);
|
|
2059
2206
|
if (shape._count)
|
|
2060
|
-
schemaFields["_count"] = argsBuilder.buildCountFieldSchema(
|
|
2207
|
+
schemaFields["_count"] = argsBuilder.buildCountFieldSchema(
|
|
2208
|
+
model,
|
|
2209
|
+
shape._count,
|
|
2210
|
+
"_count"
|
|
2211
|
+
);
|
|
2061
2212
|
if (shape._avg)
|
|
2062
|
-
schemaFields["_avg"] = argsBuilder.buildAggregateFieldSchema(
|
|
2213
|
+
schemaFields["_avg"] = argsBuilder.buildAggregateFieldSchema(
|
|
2214
|
+
model,
|
|
2215
|
+
"_avg",
|
|
2216
|
+
shape._avg
|
|
2217
|
+
);
|
|
2063
2218
|
if (shape._sum)
|
|
2064
|
-
schemaFields["_sum"] = argsBuilder.buildAggregateFieldSchema(
|
|
2219
|
+
schemaFields["_sum"] = argsBuilder.buildAggregateFieldSchema(
|
|
2220
|
+
model,
|
|
2221
|
+
"_sum",
|
|
2222
|
+
shape._sum
|
|
2223
|
+
);
|
|
2065
2224
|
if (shape._min)
|
|
2066
|
-
schemaFields["_min"] = argsBuilder.buildAggregateFieldSchema(
|
|
2225
|
+
schemaFields["_min"] = argsBuilder.buildAggregateFieldSchema(
|
|
2226
|
+
model,
|
|
2227
|
+
"_min",
|
|
2228
|
+
shape._min
|
|
2229
|
+
);
|
|
2067
2230
|
if (shape._max)
|
|
2068
|
-
schemaFields["_max"] = argsBuilder.buildAggregateFieldSchema(
|
|
2231
|
+
schemaFields["_max"] = argsBuilder.buildAggregateFieldSchema(
|
|
2232
|
+
model,
|
|
2233
|
+
"_max",
|
|
2234
|
+
shape._max
|
|
2235
|
+
);
|
|
2069
2236
|
if (shape.by)
|
|
2070
2237
|
schemaFields["by"] = argsBuilder.buildBySchema(model, shape.by);
|
|
2071
2238
|
if (shape.having)
|
|
2072
|
-
schemaFields["having"] = argsBuilder.buildHavingSchema(
|
|
2239
|
+
schemaFields["having"] = argsBuilder.buildHavingSchema(
|
|
2240
|
+
model,
|
|
2241
|
+
shape.having
|
|
2242
|
+
);
|
|
2073
2243
|
return {
|
|
2074
2244
|
zodSchema: import_zod7.z.object(schemaFields).strict(),
|
|
2075
2245
|
forcedWhere,
|
|
2246
|
+
forcedOnlyWhereKeys,
|
|
2076
2247
|
forcedIncludeTree,
|
|
2077
2248
|
forcedSelectTree,
|
|
2078
2249
|
forcedIncludeCountWhere,
|
|
@@ -2089,17 +2260,27 @@ function createQueryBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
|
|
|
2089
2260
|
const isSingle = typeof config === "function" || isShapeConfig(config);
|
|
2090
2261
|
const builtCache = /* @__PURE__ */ new Map();
|
|
2091
2262
|
if (isSingle && typeof config !== "function") {
|
|
2092
|
-
builtCache.set(
|
|
2263
|
+
builtCache.set(
|
|
2264
|
+
"_default",
|
|
2265
|
+
buildShapeZodSchema(model, method, config)
|
|
2266
|
+
);
|
|
2093
2267
|
}
|
|
2094
2268
|
if (!isSingle) {
|
|
2095
2269
|
for (const key of Object.keys(config)) {
|
|
2096
2270
|
if (SHAPE_CONFIG_KEYS.has(key)) {
|
|
2097
|
-
throw new ShapeError(
|
|
2271
|
+
throw new ShapeError(
|
|
2272
|
+
`Caller key "${key}" collides with reserved shape config key. Rename the caller path.`
|
|
2273
|
+
);
|
|
2098
2274
|
}
|
|
2099
2275
|
}
|
|
2100
|
-
for (const [key, shapeOrFn] of Object.entries(
|
|
2276
|
+
for (const [key, shapeOrFn] of Object.entries(
|
|
2277
|
+
config
|
|
2278
|
+
)) {
|
|
2101
2279
|
if (typeof shapeOrFn !== "function") {
|
|
2102
|
-
builtCache.set(
|
|
2280
|
+
builtCache.set(
|
|
2281
|
+
key,
|
|
2282
|
+
buildShapeZodSchema(model, method, shapeOrFn)
|
|
2283
|
+
);
|
|
2103
2284
|
}
|
|
2104
2285
|
}
|
|
2105
2286
|
}
|
|
@@ -2128,14 +2309,21 @@ function createQueryBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
|
|
|
2128
2309
|
}
|
|
2129
2310
|
const caller = opts?.caller;
|
|
2130
2311
|
if (typeof caller !== "string") {
|
|
2131
|
-
const allowed = Object.keys(
|
|
2312
|
+
const allowed = Object.keys(
|
|
2313
|
+
config
|
|
2314
|
+
);
|
|
2132
2315
|
throw new CallerError(
|
|
2133
2316
|
`Missing caller. This query uses named shape routing with keys: ${allowed.map((k) => `"${k}"`).join(", ")}. Provide caller via opts.caller.`
|
|
2134
2317
|
);
|
|
2135
2318
|
}
|
|
2136
|
-
const matched = matchCaller(
|
|
2319
|
+
const matched = matchCaller(
|
|
2320
|
+
config,
|
|
2321
|
+
caller
|
|
2322
|
+
);
|
|
2137
2323
|
if (!matched) {
|
|
2138
|
-
const allowed = Object.keys(
|
|
2324
|
+
const allowed = Object.keys(
|
|
2325
|
+
config
|
|
2326
|
+
);
|
|
2139
2327
|
throw new CallerError(
|
|
2140
2328
|
`Unknown caller: "${caller}". Allowed: ${allowed.map((k) => `"${k}"`).join(", ")}`
|
|
2141
2329
|
);
|
|
@@ -2768,7 +2956,10 @@ function resolveShape(input, body, contextFn, caller) {
|
|
|
2768
2956
|
|
|
2769
2957
|
// src/runtime/model-guard.ts
|
|
2770
2958
|
var UNIQUE_MUTATION_METHODS = /* @__PURE__ */ new Set(["update", "delete", "upsert"]);
|
|
2771
|
-
var UNIQUE_READ_METHODS = /* @__PURE__ */ new Set([
|
|
2959
|
+
var UNIQUE_READ_METHODS = /* @__PURE__ */ new Set([
|
|
2960
|
+
"findUnique",
|
|
2961
|
+
"findUniqueOrThrow"
|
|
2962
|
+
]);
|
|
2772
2963
|
var BULK_MUTATION_METHODS = /* @__PURE__ */ new Set([
|
|
2773
2964
|
"updateMany",
|
|
2774
2965
|
"updateManyAndReturn",
|
|
@@ -2782,15 +2973,14 @@ var PROJECTION_MUTATION_METHODS = /* @__PURE__ */ new Set([
|
|
|
2782
2973
|
"createManyAndReturn",
|
|
2783
2974
|
"updateManyAndReturn"
|
|
2784
2975
|
]);
|
|
2785
|
-
var BATCH_CREATE_METHODS = /* @__PURE__ */ new Set([
|
|
2786
|
-
"createMany",
|
|
2787
|
-
"createManyAndReturn"
|
|
2788
|
-
]);
|
|
2976
|
+
var BATCH_CREATE_METHODS = /* @__PURE__ */ new Set(["createMany", "createManyAndReturn"]);
|
|
2789
2977
|
function buildDefaultSelectInput(config) {
|
|
2790
2978
|
const result = {};
|
|
2791
2979
|
for (const [key, value] of Object.entries(config)) {
|
|
2792
2980
|
if (key === "_count") {
|
|
2793
|
-
result[key] = buildDefaultCountInput(
|
|
2981
|
+
result[key] = buildDefaultCountInput(
|
|
2982
|
+
value
|
|
2983
|
+
);
|
|
2794
2984
|
continue;
|
|
2795
2985
|
}
|
|
2796
2986
|
if (value === true) {
|
|
@@ -2808,7 +2998,9 @@ function buildDefaultIncludeInput(config) {
|
|
|
2808
2998
|
const result = {};
|
|
2809
2999
|
for (const [key, value] of Object.entries(config)) {
|
|
2810
3000
|
if (key === "_count") {
|
|
2811
|
-
result[key] = buildDefaultCountInput(
|
|
3001
|
+
result[key] = buildDefaultCountInput(
|
|
3002
|
+
value
|
|
3003
|
+
);
|
|
2812
3004
|
continue;
|
|
2813
3005
|
}
|
|
2814
3006
|
if (value === true) {
|
|
@@ -2922,12 +3114,32 @@ function hasNestedClientControlledArgs(shape) {
|
|
|
2922
3114
|
return false;
|
|
2923
3115
|
}
|
|
2924
3116
|
function createModelGuardExtension(config) {
|
|
2925
|
-
const {
|
|
3117
|
+
const {
|
|
3118
|
+
typeMap,
|
|
3119
|
+
enumMap,
|
|
3120
|
+
zodChains,
|
|
3121
|
+
zodDefaults,
|
|
3122
|
+
uniqueMap,
|
|
3123
|
+
scopeMap,
|
|
3124
|
+
guardConfig,
|
|
3125
|
+
contextFn
|
|
3126
|
+
} = config;
|
|
2926
3127
|
const wrapZodErrors = config.wrapZodErrors ?? false;
|
|
2927
3128
|
const enforceProjection = guardConfig.enforceProjection ?? false;
|
|
2928
3129
|
const scalarBase = createScalarBase(guardConfig.strictDecimal ?? false);
|
|
2929
|
-
const schemaBuilder = createSchemaBuilder(
|
|
2930
|
-
|
|
3130
|
+
const schemaBuilder = createSchemaBuilder(
|
|
3131
|
+
typeMap,
|
|
3132
|
+
zodChains,
|
|
3133
|
+
enumMap,
|
|
3134
|
+
scalarBase,
|
|
3135
|
+
zodDefaults
|
|
3136
|
+
);
|
|
3137
|
+
const queryBuilder = createQueryBuilder(
|
|
3138
|
+
typeMap,
|
|
3139
|
+
enumMap,
|
|
3140
|
+
uniqueMap,
|
|
3141
|
+
scalarBase
|
|
3142
|
+
);
|
|
2931
3143
|
const modelScopeFks = /* @__PURE__ */ new Map();
|
|
2932
3144
|
for (const [model, entries] of Object.entries(scopeMap)) {
|
|
2933
3145
|
const fks = /* @__PURE__ */ new Set();
|
|
@@ -2945,7 +3157,9 @@ function createModelGuardExtension(config) {
|
|
|
2945
3157
|
function createGuardedMethods(modelName, modelDelegate, input, explicitCaller) {
|
|
2946
3158
|
function callDelegate(method, args) {
|
|
2947
3159
|
if (typeof modelDelegate[method] !== "function") {
|
|
2948
|
-
throw new ShapeError(
|
|
3160
|
+
throw new ShapeError(
|
|
3161
|
+
`Method "${method}" is not available on this model`
|
|
3162
|
+
);
|
|
2949
3163
|
}
|
|
2950
3164
|
return modelDelegate[method](args);
|
|
2951
3165
|
}
|
|
@@ -2968,11 +3182,19 @@ function createModelGuardExtension(config) {
|
|
|
2968
3182
|
const cached = readShapeCache.get(cacheKey);
|
|
2969
3183
|
if (cached)
|
|
2970
3184
|
return cached;
|
|
2971
|
-
const built = queryBuilder.buildShapeZodSchema(
|
|
3185
|
+
const built = queryBuilder.buildShapeZodSchema(
|
|
3186
|
+
modelName,
|
|
3187
|
+
method,
|
|
3188
|
+
queryShape
|
|
3189
|
+
);
|
|
2972
3190
|
readShapeCache.set(cacheKey, built);
|
|
2973
3191
|
return built;
|
|
2974
3192
|
}
|
|
2975
|
-
return queryBuilder.buildShapeZodSchema(
|
|
3193
|
+
return queryBuilder.buildShapeZodSchema(
|
|
3194
|
+
modelName,
|
|
3195
|
+
method,
|
|
3196
|
+
queryShape
|
|
3197
|
+
);
|
|
2976
3198
|
}
|
|
2977
3199
|
function getDataSchema(mode, dataConfig, matchedKey, wasDynamic) {
|
|
2978
3200
|
if (!wasDynamic && !hasDataRefines(dataConfig)) {
|
|
@@ -2980,11 +3202,25 @@ function createModelGuardExtension(config) {
|
|
|
2980
3202
|
const cached = dataSchemaCache.get(cacheKey);
|
|
2981
3203
|
if (cached)
|
|
2982
3204
|
return cached;
|
|
2983
|
-
const built = buildDataSchema(
|
|
3205
|
+
const built = buildDataSchema(
|
|
3206
|
+
modelName,
|
|
3207
|
+
dataConfig,
|
|
3208
|
+
mode,
|
|
3209
|
+
typeMap,
|
|
3210
|
+
schemaBuilder,
|
|
3211
|
+
zodDefaults
|
|
3212
|
+
);
|
|
2984
3213
|
dataSchemaCache.set(cacheKey, built);
|
|
2985
3214
|
return built;
|
|
2986
3215
|
}
|
|
2987
|
-
return buildDataSchema(
|
|
3216
|
+
return buildDataSchema(
|
|
3217
|
+
modelName,
|
|
3218
|
+
dataConfig,
|
|
3219
|
+
mode,
|
|
3220
|
+
typeMap,
|
|
3221
|
+
schemaBuilder,
|
|
3222
|
+
zodDefaults
|
|
3223
|
+
);
|
|
2988
3224
|
}
|
|
2989
3225
|
function getWhereBuilt(whereConfig, matchedKey, wasDynamic) {
|
|
2990
3226
|
if (!wasDynamic) {
|
|
@@ -3103,12 +3339,28 @@ function createModelGuardExtension(config) {
|
|
|
3103
3339
|
const built = getWhereBuilt(shape.where, matchedKey, wasDynamic);
|
|
3104
3340
|
let validatedWhere;
|
|
3105
3341
|
if (built.schema) {
|
|
3106
|
-
|
|
3342
|
+
let sanitizedWhere = bodyWhere;
|
|
3343
|
+
if (built.forcedOnlyKeys.size > 0 && isPlainObject(bodyWhere)) {
|
|
3344
|
+
const w = { ...bodyWhere };
|
|
3345
|
+
for (const key of built.forcedOnlyKeys) {
|
|
3346
|
+
delete w[key];
|
|
3347
|
+
}
|
|
3348
|
+
sanitizedWhere = w;
|
|
3349
|
+
}
|
|
3350
|
+
validatedWhere = built.schema.parse(sanitizedWhere);
|
|
3107
3351
|
} else if (bodyWhere !== void 0) {
|
|
3108
3352
|
if (bodyWhere === null || !isPlainObject(bodyWhere) || Object.keys(bodyWhere).length > 0) {
|
|
3109
|
-
|
|
3110
|
-
|
|
3111
|
-
|
|
3353
|
+
let hasOnlyForcedKeys = false;
|
|
3354
|
+
if (isPlainObject(bodyWhere) && built.forcedOnlyKeys.size > 0) {
|
|
3355
|
+
hasOnlyForcedKeys = Object.keys(bodyWhere).every(
|
|
3356
|
+
(k) => built.forcedOnlyKeys.has(k)
|
|
3357
|
+
);
|
|
3358
|
+
}
|
|
3359
|
+
if (!hasOnlyForcedKeys) {
|
|
3360
|
+
throw new ShapeError(
|
|
3361
|
+
"Guard shape where contains only forced conditions. Client where input is not accepted."
|
|
3362
|
+
);
|
|
3363
|
+
}
|
|
3112
3364
|
}
|
|
3113
3365
|
}
|
|
3114
3366
|
if (hasWhereForced(built.forced)) {
|
|
@@ -3117,7 +3369,13 @@ function createModelGuardExtension(config) {
|
|
|
3117
3369
|
return validatedWhere ?? {};
|
|
3118
3370
|
}
|
|
3119
3371
|
function requireWhere(shape, bodyWhere, method, preserveUnique, matchedKey, wasDynamic) {
|
|
3120
|
-
const where = buildWhereFromShape(
|
|
3372
|
+
const where = buildWhereFromShape(
|
|
3373
|
+
shape,
|
|
3374
|
+
bodyWhere,
|
|
3375
|
+
preserveUnique,
|
|
3376
|
+
matchedKey,
|
|
3377
|
+
wasDynamic
|
|
3378
|
+
);
|
|
3121
3379
|
if (Object.keys(where).length === 0) {
|
|
3122
3380
|
throw new ShapeError(`${method} requires a where condition`);
|
|
3123
3381
|
}
|
|
@@ -3131,7 +3389,12 @@ function createModelGuardExtension(config) {
|
|
|
3131
3389
|
throw new ShapeError(`Guard shape "data" is not valid for ${method}`);
|
|
3132
3390
|
}
|
|
3133
3391
|
const { data: _, ...queryShape } = resolved.shape;
|
|
3134
|
-
const built = getReadShape(
|
|
3392
|
+
const built = getReadShape(
|
|
3393
|
+
method,
|
|
3394
|
+
queryShape,
|
|
3395
|
+
resolved.matchedKey,
|
|
3396
|
+
resolved.wasDynamic
|
|
3397
|
+
);
|
|
3135
3398
|
const isUnique = UNIQUE_READ_METHODS.has(method);
|
|
3136
3399
|
const args = applyBuiltShape(built, resolved.body, isUnique);
|
|
3137
3400
|
if (isUnique && args.where) {
|
|
@@ -3164,14 +3427,33 @@ function createModelGuardExtension(config) {
|
|
|
3164
3427
|
const resolved = resolveShape(input, body, contextFn, caller);
|
|
3165
3428
|
if (!resolved.shape.data)
|
|
3166
3429
|
throw new ShapeError(`Guard shape requires "data" for ${method}`);
|
|
3167
|
-
validateMutationShapeKeys(
|
|
3430
|
+
validateMutationShapeKeys(
|
|
3431
|
+
resolved.shape,
|
|
3432
|
+
allowedShapeKeys,
|
|
3433
|
+
method
|
|
3434
|
+
);
|
|
3168
3435
|
validateMutationBodyKeys(resolved.body, allowedBodyKeys, method);
|
|
3169
3436
|
const fks = modelScopeFks.get(modelName) ?? /* @__PURE__ */ new Set();
|
|
3170
|
-
validateCreateCompleteness(
|
|
3171
|
-
|
|
3437
|
+
validateCreateCompleteness(
|
|
3438
|
+
modelName,
|
|
3439
|
+
resolved.shape.data,
|
|
3440
|
+
typeMap,
|
|
3441
|
+
fks,
|
|
3442
|
+
zodDefaults
|
|
3443
|
+
);
|
|
3444
|
+
const dataSchema = getDataSchema(
|
|
3445
|
+
"create",
|
|
3446
|
+
resolved.shape.data,
|
|
3447
|
+
resolved.matchedKey,
|
|
3448
|
+
resolved.wasDynamic
|
|
3449
|
+
);
|
|
3172
3450
|
let args;
|
|
3173
3451
|
if (method === "create") {
|
|
3174
|
-
const data = validateAndMergeData(
|
|
3452
|
+
const data = validateAndMergeData(
|
|
3453
|
+
resolved.body.data,
|
|
3454
|
+
dataSchema,
|
|
3455
|
+
method
|
|
3456
|
+
);
|
|
3175
3457
|
args = { data };
|
|
3176
3458
|
} else {
|
|
3177
3459
|
if (!Array.isArray(resolved.body.data))
|
|
@@ -3190,7 +3472,13 @@ function createModelGuardExtension(config) {
|
|
|
3190
3472
|
args.skipDuplicates = resolved.body.skipDuplicates;
|
|
3191
3473
|
}
|
|
3192
3474
|
if (supportsProjection) {
|
|
3193
|
-
const projectionArgs = resolveProjection(
|
|
3475
|
+
const projectionArgs = resolveProjection(
|
|
3476
|
+
resolved.shape,
|
|
3477
|
+
resolved.body,
|
|
3478
|
+
method,
|
|
3479
|
+
resolved.matchedKey,
|
|
3480
|
+
resolved.wasDynamic
|
|
3481
|
+
);
|
|
3194
3482
|
Object.assign(args, projectionArgs);
|
|
3195
3483
|
}
|
|
3196
3484
|
return callDelegate(method, args);
|
|
@@ -3207,24 +3495,60 @@ function createModelGuardExtension(config) {
|
|
|
3207
3495
|
const resolved = resolveShape(input, body, contextFn, caller);
|
|
3208
3496
|
if (!resolved.shape.data)
|
|
3209
3497
|
throw new ShapeError(`Guard shape requires "data" for ${method}`);
|
|
3210
|
-
validateMutationShapeKeys(
|
|
3498
|
+
validateMutationShapeKeys(
|
|
3499
|
+
resolved.shape,
|
|
3500
|
+
allowedShapeKeys,
|
|
3501
|
+
method
|
|
3502
|
+
);
|
|
3211
3503
|
validateMutationBodyKeys(resolved.body, allowedBodyKeys, method);
|
|
3212
3504
|
if (isBulk && !resolved.shape.where) {
|
|
3213
|
-
throw new ShapeError(
|
|
3505
|
+
throw new ShapeError(
|
|
3506
|
+
`Guard shape requires "where" for ${method} to prevent unconstrained bulk mutations`
|
|
3507
|
+
);
|
|
3214
3508
|
}
|
|
3215
3509
|
maybeValidateUniqueWhere(modelName, resolved.shape, method);
|
|
3216
|
-
const dataSchema = getDataSchema(
|
|
3217
|
-
|
|
3218
|
-
|
|
3510
|
+
const dataSchema = getDataSchema(
|
|
3511
|
+
"update",
|
|
3512
|
+
resolved.shape.data,
|
|
3513
|
+
resolved.matchedKey,
|
|
3514
|
+
resolved.wasDynamic
|
|
3515
|
+
);
|
|
3516
|
+
const data = validateAndMergeData(
|
|
3517
|
+
resolved.body.data,
|
|
3518
|
+
dataSchema,
|
|
3519
|
+
method
|
|
3520
|
+
);
|
|
3521
|
+
const where = isUniqueWhere ? requireWhere(
|
|
3522
|
+
resolved.shape,
|
|
3523
|
+
resolved.body.where,
|
|
3524
|
+
method,
|
|
3525
|
+
true,
|
|
3526
|
+
resolved.matchedKey,
|
|
3527
|
+
resolved.wasDynamic
|
|
3528
|
+
) : buildWhereFromShape(
|
|
3529
|
+
resolved.shape,
|
|
3530
|
+
resolved.body.where,
|
|
3531
|
+
false,
|
|
3532
|
+
resolved.matchedKey,
|
|
3533
|
+
resolved.wasDynamic
|
|
3534
|
+
);
|
|
3219
3535
|
if (isBulk && Object.keys(where).length === 0) {
|
|
3220
|
-
throw new ShapeError(
|
|
3536
|
+
throw new ShapeError(
|
|
3537
|
+
`${method} requires at least one where condition`
|
|
3538
|
+
);
|
|
3221
3539
|
}
|
|
3222
3540
|
if (isUniqueWhere) {
|
|
3223
3541
|
validateResolvedUniqueWhere(modelName, where, method, uniqueMap);
|
|
3224
3542
|
}
|
|
3225
3543
|
const args = { data, where };
|
|
3226
3544
|
if (supportsProjection) {
|
|
3227
|
-
const projectionArgs = resolveProjection(
|
|
3545
|
+
const projectionArgs = resolveProjection(
|
|
3546
|
+
resolved.shape,
|
|
3547
|
+
resolved.body,
|
|
3548
|
+
method,
|
|
3549
|
+
resolved.matchedKey,
|
|
3550
|
+
resolved.wasDynamic
|
|
3551
|
+
);
|
|
3228
3552
|
Object.assign(args, projectionArgs);
|
|
3229
3553
|
}
|
|
3230
3554
|
return callDelegate(method, args);
|
|
@@ -3241,22 +3565,49 @@ function createModelGuardExtension(config) {
|
|
|
3241
3565
|
const resolved = resolveShape(input, body, contextFn, caller);
|
|
3242
3566
|
if (resolved.shape.data)
|
|
3243
3567
|
throw new ShapeError(`Guard shape "data" is not valid for ${method}`);
|
|
3244
|
-
validateMutationShapeKeys(
|
|
3568
|
+
validateMutationShapeKeys(
|
|
3569
|
+
resolved.shape,
|
|
3570
|
+
allowedShapeKeys,
|
|
3571
|
+
method
|
|
3572
|
+
);
|
|
3245
3573
|
validateMutationBodyKeys(resolved.body, allowedBodyKeys, method);
|
|
3246
3574
|
if (isBulk && !resolved.shape.where) {
|
|
3247
|
-
throw new ShapeError(
|
|
3575
|
+
throw new ShapeError(
|
|
3576
|
+
`Guard shape requires "where" for ${method} to prevent unconstrained bulk mutations`
|
|
3577
|
+
);
|
|
3248
3578
|
}
|
|
3249
3579
|
maybeValidateUniqueWhere(modelName, resolved.shape, method);
|
|
3250
|
-
const where = isUniqueWhere ? requireWhere(
|
|
3580
|
+
const where = isUniqueWhere ? requireWhere(
|
|
3581
|
+
resolved.shape,
|
|
3582
|
+
resolved.body.where,
|
|
3583
|
+
method,
|
|
3584
|
+
true,
|
|
3585
|
+
resolved.matchedKey,
|
|
3586
|
+
resolved.wasDynamic
|
|
3587
|
+
) : buildWhereFromShape(
|
|
3588
|
+
resolved.shape,
|
|
3589
|
+
resolved.body.where,
|
|
3590
|
+
false,
|
|
3591
|
+
resolved.matchedKey,
|
|
3592
|
+
resolved.wasDynamic
|
|
3593
|
+
);
|
|
3251
3594
|
if (isBulk && Object.keys(where).length === 0) {
|
|
3252
|
-
throw new ShapeError(
|
|
3595
|
+
throw new ShapeError(
|
|
3596
|
+
`${method} requires at least one where condition`
|
|
3597
|
+
);
|
|
3253
3598
|
}
|
|
3254
3599
|
if (isUniqueWhere) {
|
|
3255
3600
|
validateResolvedUniqueWhere(modelName, where, method, uniqueMap);
|
|
3256
3601
|
}
|
|
3257
3602
|
const args = { where };
|
|
3258
3603
|
if (supportsProjection) {
|
|
3259
|
-
const projectionArgs = resolveProjection(
|
|
3604
|
+
const projectionArgs = resolveProjection(
|
|
3605
|
+
resolved.shape,
|
|
3606
|
+
resolved.body,
|
|
3607
|
+
method,
|
|
3608
|
+
resolved.matchedKey,
|
|
3609
|
+
resolved.wasDynamic
|
|
3610
|
+
);
|
|
3260
3611
|
Object.assign(args, projectionArgs);
|
|
3261
3612
|
}
|
|
3262
3613
|
return callDelegate(method, args);
|
|
@@ -3267,7 +3618,9 @@ function createModelGuardExtension(config) {
|
|
|
3267
3618
|
const caller = resolveCaller();
|
|
3268
3619
|
const resolved = resolveShape(input, body, contextFn, caller);
|
|
3269
3620
|
if (resolved.shape.data) {
|
|
3270
|
-
throw new ShapeError(
|
|
3621
|
+
throw new ShapeError(
|
|
3622
|
+
'Guard shape "data" is not valid for upsert. Use "create" and "update" instead.'
|
|
3623
|
+
);
|
|
3271
3624
|
}
|
|
3272
3625
|
if (!resolved.shape.create) {
|
|
3273
3626
|
throw new ShapeError('Guard shape requires "create" for upsert');
|
|
@@ -3283,24 +3636,42 @@ function createModelGuardExtension(config) {
|
|
|
3283
3636
|
VALID_SHAPE_KEYS_UPSERT,
|
|
3284
3637
|
"upsert"
|
|
3285
3638
|
);
|
|
3286
|
-
validateMutationBodyKeys(
|
|
3639
|
+
validateMutationBodyKeys(
|
|
3640
|
+
resolved.body,
|
|
3641
|
+
ALLOWED_BODY_KEYS_UPSERT,
|
|
3642
|
+
"upsert"
|
|
3643
|
+
);
|
|
3287
3644
|
maybeValidateUniqueWhere(modelName, resolved.shape, "upsert");
|
|
3288
3645
|
const fks = modelScopeFks.get(modelName) ?? /* @__PURE__ */ new Set();
|
|
3289
|
-
validateCreateCompleteness(
|
|
3646
|
+
validateCreateCompleteness(
|
|
3647
|
+
modelName,
|
|
3648
|
+
resolved.shape.create,
|
|
3649
|
+
typeMap,
|
|
3650
|
+
fks,
|
|
3651
|
+
zodDefaults
|
|
3652
|
+
);
|
|
3290
3653
|
const createDataSchema = getDataSchema(
|
|
3291
3654
|
"create",
|
|
3292
3655
|
resolved.shape.create,
|
|
3293
3656
|
`upsert:create\0${resolved.matchedKey}`,
|
|
3294
3657
|
resolved.wasDynamic
|
|
3295
3658
|
);
|
|
3296
|
-
const createData = validateAndMergeData(
|
|
3659
|
+
const createData = validateAndMergeData(
|
|
3660
|
+
resolved.body.create,
|
|
3661
|
+
createDataSchema,
|
|
3662
|
+
"upsert (create)"
|
|
3663
|
+
);
|
|
3297
3664
|
const updateDataSchema = getDataSchema(
|
|
3298
3665
|
"update",
|
|
3299
3666
|
resolved.shape.update,
|
|
3300
3667
|
`upsert:update\0${resolved.matchedKey}`,
|
|
3301
3668
|
resolved.wasDynamic
|
|
3302
3669
|
);
|
|
3303
|
-
const updateData = validateAndMergeData(
|
|
3670
|
+
const updateData = validateAndMergeData(
|
|
3671
|
+
resolved.body.update,
|
|
3672
|
+
updateDataSchema,
|
|
3673
|
+
"upsert (update)"
|
|
3674
|
+
);
|
|
3304
3675
|
const where = requireWhere(
|
|
3305
3676
|
resolved.shape,
|
|
3306
3677
|
resolved.body.where,
|
|
@@ -3354,10 +3725,9 @@ function createModelGuardExtension(config) {
|
|
|
3354
3725
|
return fn(body);
|
|
3355
3726
|
} catch (err) {
|
|
3356
3727
|
if (err instanceof import_zod9.z.ZodError) {
|
|
3357
|
-
throw new ShapeError(
|
|
3358
|
-
|
|
3359
|
-
|
|
3360
|
-
);
|
|
3728
|
+
throw new ShapeError(`Validation failed: ${formatZodError(err)}`, {
|
|
3729
|
+
cause: err
|
|
3730
|
+
});
|
|
3361
3731
|
}
|
|
3362
3732
|
throw err;
|
|
3363
3733
|
}
|
|
@@ -3376,7 +3746,12 @@ function createModelGuardExtension(config) {
|
|
|
3376
3746
|
`Could not resolve Prisma delegate for model "${modelName}" (key: "${delegateKey}")`
|
|
3377
3747
|
);
|
|
3378
3748
|
}
|
|
3379
|
-
const methods = createGuardedMethods(
|
|
3749
|
+
const methods = createGuardedMethods(
|
|
3750
|
+
modelName,
|
|
3751
|
+
modelDelegate,
|
|
3752
|
+
input,
|
|
3753
|
+
caller
|
|
3754
|
+
);
|
|
3380
3755
|
if (!wrapZodErrors)
|
|
3381
3756
|
return methods;
|
|
3382
3757
|
return wrapMethods(methods);
|