prisma-guard 1.3.1 → 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 +535 -103
- package/dist/runtime/index.cjs.map +1 -1
- package/dist/runtime/index.d.cts +4 -3
- package/dist/runtime/index.d.ts +4 -3
- package/dist/runtime/index.js +535 -103
- 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) {
|
|
@@ -1284,23 +1348,80 @@ function requireConfigTrue(config, context) {
|
|
|
1284
1348
|
}
|
|
1285
1349
|
}
|
|
1286
1350
|
function createArgsBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
|
|
1351
|
+
const sortEnum = import_zod5.z.enum(["asc", "desc"]);
|
|
1352
|
+
const nullsEnum = import_zod5.z.enum(["first", "last"]);
|
|
1353
|
+
const sortWithNulls = import_zod5.z.object({ sort: sortEnum, nulls: nullsEnum.optional() }).strict();
|
|
1354
|
+
const scalarOrderSchema = import_zod5.z.union([sortEnum, sortWithNulls]);
|
|
1355
|
+
function validateScalarOrderByField(fieldName, model, modelFields) {
|
|
1356
|
+
const fieldMeta = modelFields[fieldName];
|
|
1357
|
+
if (!fieldMeta)
|
|
1358
|
+
throw new ShapeError(`Unknown field "${fieldName}" on model "${model}"`);
|
|
1359
|
+
if (fieldMeta.isRelation)
|
|
1360
|
+
throw new ShapeError(`Relation field "${fieldName}" in orderBy requires a nested config object, not true`);
|
|
1361
|
+
if (fieldMeta.type === "Json")
|
|
1362
|
+
throw new ShapeError(`Json field "${fieldName}" cannot be used in orderBy`);
|
|
1363
|
+
if (fieldMeta.isList)
|
|
1364
|
+
throw new ShapeError(`List field "${fieldName}" cannot be used in orderBy`);
|
|
1365
|
+
}
|
|
1287
1366
|
function buildOrderBySchema(model, orderByConfig) {
|
|
1288
1367
|
const modelFields = typeMap[model];
|
|
1289
1368
|
if (!modelFields)
|
|
1290
1369
|
throw new ShapeError(`Unknown model: ${model}`);
|
|
1291
|
-
requireConfigTrue(orderByConfig, `orderBy on model "${model}"`);
|
|
1292
1370
|
const fieldSchemas = {};
|
|
1293
|
-
for (const fieldName of Object.
|
|
1371
|
+
for (const [fieldName, config] of Object.entries(orderByConfig)) {
|
|
1294
1372
|
const fieldMeta = modelFields[fieldName];
|
|
1295
1373
|
if (!fieldMeta)
|
|
1296
1374
|
throw new ShapeError(`Unknown field "${fieldName}" on model "${model}"`);
|
|
1297
|
-
if (
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1375
|
+
if (config === true) {
|
|
1376
|
+
validateScalarOrderByField(fieldName, model, modelFields);
|
|
1377
|
+
fieldSchemas[fieldName] = scalarOrderSchema.optional();
|
|
1378
|
+
continue;
|
|
1379
|
+
}
|
|
1380
|
+
if (typeof config !== "object" || config === null) {
|
|
1381
|
+
throw new ShapeError(`Invalid orderBy config for "${fieldName}" on model "${model}": expected true or a nested config object`);
|
|
1382
|
+
}
|
|
1383
|
+
if (!fieldMeta.isRelation) {
|
|
1384
|
+
throw new ShapeError(`Scalar field "${fieldName}" in orderBy does not accept nested config`);
|
|
1385
|
+
}
|
|
1386
|
+
if (Object.keys(config).length === 0) {
|
|
1387
|
+
throw new ShapeError(`Empty orderBy config for relation "${fieldName}" on model "${model}". Define at least one nested field.`);
|
|
1388
|
+
}
|
|
1389
|
+
if (fieldMeta.isList) {
|
|
1390
|
+
const relKeys = Object.keys(config);
|
|
1391
|
+
if (relKeys.length !== 1 || relKeys[0] !== "_count") {
|
|
1392
|
+
throw new ShapeError(`To-many relation "${fieldName}" in orderBy only supports { _count: true }`);
|
|
1393
|
+
}
|
|
1394
|
+
if (config._count !== true) {
|
|
1395
|
+
throw new ShapeError(`_count in orderBy for "${fieldName}" must be true`);
|
|
1396
|
+
}
|
|
1397
|
+
fieldSchemas[fieldName] = import_zod5.z.object({ _count: sortEnum }).strict().optional();
|
|
1398
|
+
continue;
|
|
1399
|
+
}
|
|
1400
|
+
const relatedModel = fieldMeta.type;
|
|
1401
|
+
const relatedFields = typeMap[relatedModel];
|
|
1402
|
+
if (!relatedFields)
|
|
1403
|
+
throw new ShapeError(`Related model "${relatedModel}" not found in type map`);
|
|
1404
|
+
const nestedSchemas = {};
|
|
1405
|
+
for (const [nestedField, nestedVal] of Object.entries(config)) {
|
|
1406
|
+
if (nestedVal !== true) {
|
|
1407
|
+
throw new ShapeError(`Nested orderBy field "${nestedField}" on relation "${fieldName}" must be true`);
|
|
1408
|
+
}
|
|
1409
|
+
const nestedMeta = relatedFields[nestedField];
|
|
1410
|
+
if (!nestedMeta)
|
|
1411
|
+
throw new ShapeError(`Unknown field "${nestedField}" on model "${relatedModel}" in orderBy`);
|
|
1412
|
+
if (nestedMeta.isRelation)
|
|
1413
|
+
throw new ShapeError(`Nested relation "${nestedField}" in orderBy on "${fieldName}" is not supported`);
|
|
1414
|
+
if (nestedMeta.type === "Json")
|
|
1415
|
+
throw new ShapeError(`Json field "${nestedField}" cannot be used in orderBy`);
|
|
1416
|
+
if (nestedMeta.isList)
|
|
1417
|
+
throw new ShapeError(`List field "${nestedField}" cannot be used in orderBy`);
|
|
1418
|
+
nestedSchemas[nestedField] = scalarOrderSchema.optional();
|
|
1419
|
+
}
|
|
1420
|
+
const nestedKeys = Object.keys(nestedSchemas);
|
|
1421
|
+
fieldSchemas[fieldName] = import_zod5.z.object(nestedSchemas).strict().refine(
|
|
1422
|
+
(v) => nestedKeys.some((k) => v[k] !== void 0),
|
|
1423
|
+
{ message: `orderBy for relation "${fieldName}" must specify at least one field` }
|
|
1424
|
+
).optional();
|
|
1304
1425
|
}
|
|
1305
1426
|
const fieldKeys = Object.keys(fieldSchemas);
|
|
1306
1427
|
const singleSchema = import_zod5.z.object(fieldSchemas).strict().refine(
|
|
@@ -1870,19 +1991,77 @@ function createProjectionBuilder(typeMap, enumMap, deps) {
|
|
|
1870
1991
|
|
|
1871
1992
|
// src/runtime/query-builder.ts
|
|
1872
1993
|
var METHOD_ALLOWED_ARGS = {
|
|
1873
|
-
findMany: /* @__PURE__ */ new Set([
|
|
1874
|
-
|
|
1875
|
-
|
|
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
|
+
]),
|
|
1876
2024
|
findUnique: /* @__PURE__ */ new Set(["where", "include", "select"]),
|
|
1877
2025
|
findUniqueOrThrow: /* @__PURE__ */ new Set(["where", "include", "select"]),
|
|
1878
2026
|
count: /* @__PURE__ */ new Set(["where", "select", "cursor", "orderBy", "skip", "take"]),
|
|
1879
|
-
aggregate: /* @__PURE__ */ new Set([
|
|
1880
|
-
|
|
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
|
+
])
|
|
1881
2052
|
};
|
|
1882
|
-
var UNIQUE_WHERE_METHODS = /* @__PURE__ */ new Set([
|
|
2053
|
+
var UNIQUE_WHERE_METHODS = /* @__PURE__ */ new Set([
|
|
2054
|
+
"findUnique",
|
|
2055
|
+
"findUniqueOrThrow"
|
|
2056
|
+
]);
|
|
1883
2057
|
function createQueryBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
|
|
1884
2058
|
const whereBuilder = createWhereBuilder(typeMap, enumMap, scalarBase);
|
|
1885
|
-
const argsBuilder = createArgsBuilder(
|
|
2059
|
+
const argsBuilder = createArgsBuilder(
|
|
2060
|
+
typeMap,
|
|
2061
|
+
enumMap,
|
|
2062
|
+
uniqueMap,
|
|
2063
|
+
scalarBase
|
|
2064
|
+
);
|
|
1886
2065
|
const projectionBuilder = createProjectionBuilder(typeMap, enumMap, {
|
|
1887
2066
|
buildWhereSchema: whereBuilder.buildWhereSchema,
|
|
1888
2067
|
buildOrderBySchema: argsBuilder.buildOrderBySchema,
|
|
@@ -1907,7 +2086,9 @@ function createQueryBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
|
|
|
1907
2086
|
throw new ShapeError(`${method} shape must define "where"`);
|
|
1908
2087
|
}
|
|
1909
2088
|
if (shape.include && shape.select) {
|
|
1910
|
-
throw new ShapeError(
|
|
2089
|
+
throw new ShapeError(
|
|
2090
|
+
'Shape config cannot define both "include" and "select".'
|
|
2091
|
+
);
|
|
1911
2092
|
}
|
|
1912
2093
|
if (method === "groupBy" && !shape.by)
|
|
1913
2094
|
throw new ShapeError('groupBy shape must define "by"');
|
|
@@ -1923,7 +2104,9 @@ function createQueryBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
|
|
|
1923
2104
|
const bySet = new Set(shape.by);
|
|
1924
2105
|
for (const fieldName of Object.keys(shape.orderBy)) {
|
|
1925
2106
|
if (!bySet.has(fieldName)) {
|
|
1926
|
-
throw new ShapeError(
|
|
2107
|
+
throw new ShapeError(
|
|
2108
|
+
`orderBy field "${fieldName}" must be included in "by" for groupBy`
|
|
2109
|
+
);
|
|
1927
2110
|
}
|
|
1928
2111
|
}
|
|
1929
2112
|
}
|
|
@@ -1931,7 +2114,9 @@ function createQueryBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
|
|
|
1931
2114
|
const bySet = new Set(shape.by);
|
|
1932
2115
|
for (const fieldName of Object.keys(shape.having)) {
|
|
1933
2116
|
if (!bySet.has(fieldName)) {
|
|
1934
|
-
throw new ShapeError(
|
|
2117
|
+
throw new ShapeError(
|
|
2118
|
+
`having field "${fieldName}" must be included in "by" for groupBy`
|
|
2119
|
+
);
|
|
1935
2120
|
}
|
|
1936
2121
|
}
|
|
1937
2122
|
}
|
|
@@ -1948,7 +2133,9 @@ function createQueryBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
|
|
|
1948
2133
|
requireContext(ctx, "shape function");
|
|
1949
2134
|
const result = shapeOrFn(ctx);
|
|
1950
2135
|
if (!isPlainObject(result)) {
|
|
1951
|
-
throw new ShapeError(
|
|
2136
|
+
throw new ShapeError(
|
|
2137
|
+
"Dynamic shape function must return a plain object"
|
|
2138
|
+
);
|
|
1952
2139
|
}
|
|
1953
2140
|
return result;
|
|
1954
2141
|
}
|
|
@@ -1959,15 +2146,20 @@ function createQueryBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
|
|
|
1959
2146
|
validateUniqueWhere(model, method, shape);
|
|
1960
2147
|
const schemaFields = {};
|
|
1961
2148
|
let forcedWhere = EMPTY_WHERE_FORCED;
|
|
2149
|
+
let forcedOnlyWhereKeys = /* @__PURE__ */ new Set();
|
|
1962
2150
|
let forcedIncludeTree = {};
|
|
1963
2151
|
let forcedSelectTree = {};
|
|
1964
2152
|
let forcedIncludeCountWhere = {};
|
|
1965
2153
|
let forcedSelectCountWhere = {};
|
|
1966
2154
|
if (shape.where) {
|
|
1967
|
-
const { schema, forced } = whereBuilder.buildWhereSchema(
|
|
2155
|
+
const { schema, forced, forcedOnlyKeys } = whereBuilder.buildWhereSchema(
|
|
2156
|
+
model,
|
|
2157
|
+
shape.where
|
|
2158
|
+
);
|
|
1968
2159
|
if (schema)
|
|
1969
2160
|
schemaFields["where"] = schema;
|
|
1970
2161
|
forcedWhere = forced;
|
|
2162
|
+
forcedOnlyWhereKeys = forcedOnlyKeys;
|
|
1971
2163
|
}
|
|
1972
2164
|
if (shape.include) {
|
|
1973
2165
|
const result = projectionBuilder.buildIncludeSchema(model, shape.include);
|
|
@@ -1977,7 +2169,10 @@ function createQueryBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
|
|
|
1977
2169
|
}
|
|
1978
2170
|
if (shape.select) {
|
|
1979
2171
|
if (method === "count") {
|
|
1980
|
-
schemaFields["select"] = argsBuilder.buildCountSelectSchema(
|
|
2172
|
+
schemaFields["select"] = argsBuilder.buildCountSelectSchema(
|
|
2173
|
+
model,
|
|
2174
|
+
shape.select
|
|
2175
|
+
);
|
|
1981
2176
|
} else {
|
|
1982
2177
|
const result = projectionBuilder.buildSelectSchema(model, shape.select);
|
|
1983
2178
|
schemaFields["select"] = result.schema;
|
|
@@ -1986,9 +2181,15 @@ function createQueryBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
|
|
|
1986
2181
|
}
|
|
1987
2182
|
}
|
|
1988
2183
|
if (shape.orderBy)
|
|
1989
|
-
schemaFields["orderBy"] = argsBuilder.buildOrderBySchema(
|
|
2184
|
+
schemaFields["orderBy"] = argsBuilder.buildOrderBySchema(
|
|
2185
|
+
model,
|
|
2186
|
+
shape.orderBy
|
|
2187
|
+
);
|
|
1990
2188
|
if (shape.cursor)
|
|
1991
|
-
schemaFields["cursor"] = argsBuilder.buildCursorSchema(
|
|
2189
|
+
schemaFields["cursor"] = argsBuilder.buildCursorSchema(
|
|
2190
|
+
model,
|
|
2191
|
+
shape.cursor
|
|
2192
|
+
);
|
|
1992
2193
|
if (shape.take)
|
|
1993
2194
|
schemaFields["take"] = argsBuilder.buildTakeSchema(shape.take);
|
|
1994
2195
|
if (shape.skip !== void 0) {
|
|
@@ -1998,24 +2199,51 @@ function createQueryBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
|
|
|
1998
2199
|
schemaFields["skip"] = import_zod7.z.number().int().min(0).optional();
|
|
1999
2200
|
}
|
|
2000
2201
|
if (shape.distinct)
|
|
2001
|
-
schemaFields["distinct"] = argsBuilder.buildDistinctSchema(
|
|
2202
|
+
schemaFields["distinct"] = argsBuilder.buildDistinctSchema(
|
|
2203
|
+
model,
|
|
2204
|
+
shape.distinct
|
|
2205
|
+
);
|
|
2002
2206
|
if (shape._count)
|
|
2003
|
-
schemaFields["_count"] = argsBuilder.buildCountFieldSchema(
|
|
2207
|
+
schemaFields["_count"] = argsBuilder.buildCountFieldSchema(
|
|
2208
|
+
model,
|
|
2209
|
+
shape._count,
|
|
2210
|
+
"_count"
|
|
2211
|
+
);
|
|
2004
2212
|
if (shape._avg)
|
|
2005
|
-
schemaFields["_avg"] = argsBuilder.buildAggregateFieldSchema(
|
|
2213
|
+
schemaFields["_avg"] = argsBuilder.buildAggregateFieldSchema(
|
|
2214
|
+
model,
|
|
2215
|
+
"_avg",
|
|
2216
|
+
shape._avg
|
|
2217
|
+
);
|
|
2006
2218
|
if (shape._sum)
|
|
2007
|
-
schemaFields["_sum"] = argsBuilder.buildAggregateFieldSchema(
|
|
2219
|
+
schemaFields["_sum"] = argsBuilder.buildAggregateFieldSchema(
|
|
2220
|
+
model,
|
|
2221
|
+
"_sum",
|
|
2222
|
+
shape._sum
|
|
2223
|
+
);
|
|
2008
2224
|
if (shape._min)
|
|
2009
|
-
schemaFields["_min"] = argsBuilder.buildAggregateFieldSchema(
|
|
2225
|
+
schemaFields["_min"] = argsBuilder.buildAggregateFieldSchema(
|
|
2226
|
+
model,
|
|
2227
|
+
"_min",
|
|
2228
|
+
shape._min
|
|
2229
|
+
);
|
|
2010
2230
|
if (shape._max)
|
|
2011
|
-
schemaFields["_max"] = argsBuilder.buildAggregateFieldSchema(
|
|
2231
|
+
schemaFields["_max"] = argsBuilder.buildAggregateFieldSchema(
|
|
2232
|
+
model,
|
|
2233
|
+
"_max",
|
|
2234
|
+
shape._max
|
|
2235
|
+
);
|
|
2012
2236
|
if (shape.by)
|
|
2013
2237
|
schemaFields["by"] = argsBuilder.buildBySchema(model, shape.by);
|
|
2014
2238
|
if (shape.having)
|
|
2015
|
-
schemaFields["having"] = argsBuilder.buildHavingSchema(
|
|
2239
|
+
schemaFields["having"] = argsBuilder.buildHavingSchema(
|
|
2240
|
+
model,
|
|
2241
|
+
shape.having
|
|
2242
|
+
);
|
|
2016
2243
|
return {
|
|
2017
2244
|
zodSchema: import_zod7.z.object(schemaFields).strict(),
|
|
2018
2245
|
forcedWhere,
|
|
2246
|
+
forcedOnlyWhereKeys,
|
|
2019
2247
|
forcedIncludeTree,
|
|
2020
2248
|
forcedSelectTree,
|
|
2021
2249
|
forcedIncludeCountWhere,
|
|
@@ -2032,17 +2260,27 @@ function createQueryBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
|
|
|
2032
2260
|
const isSingle = typeof config === "function" || isShapeConfig(config);
|
|
2033
2261
|
const builtCache = /* @__PURE__ */ new Map();
|
|
2034
2262
|
if (isSingle && typeof config !== "function") {
|
|
2035
|
-
builtCache.set(
|
|
2263
|
+
builtCache.set(
|
|
2264
|
+
"_default",
|
|
2265
|
+
buildShapeZodSchema(model, method, config)
|
|
2266
|
+
);
|
|
2036
2267
|
}
|
|
2037
2268
|
if (!isSingle) {
|
|
2038
2269
|
for (const key of Object.keys(config)) {
|
|
2039
2270
|
if (SHAPE_CONFIG_KEYS.has(key)) {
|
|
2040
|
-
throw new ShapeError(
|
|
2271
|
+
throw new ShapeError(
|
|
2272
|
+
`Caller key "${key}" collides with reserved shape config key. Rename the caller path.`
|
|
2273
|
+
);
|
|
2041
2274
|
}
|
|
2042
2275
|
}
|
|
2043
|
-
for (const [key, shapeOrFn] of Object.entries(
|
|
2276
|
+
for (const [key, shapeOrFn] of Object.entries(
|
|
2277
|
+
config
|
|
2278
|
+
)) {
|
|
2044
2279
|
if (typeof shapeOrFn !== "function") {
|
|
2045
|
-
builtCache.set(
|
|
2280
|
+
builtCache.set(
|
|
2281
|
+
key,
|
|
2282
|
+
buildShapeZodSchema(model, method, shapeOrFn)
|
|
2283
|
+
);
|
|
2046
2284
|
}
|
|
2047
2285
|
}
|
|
2048
2286
|
}
|
|
@@ -2071,14 +2309,21 @@ function createQueryBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
|
|
|
2071
2309
|
}
|
|
2072
2310
|
const caller = opts?.caller;
|
|
2073
2311
|
if (typeof caller !== "string") {
|
|
2074
|
-
const allowed = Object.keys(
|
|
2312
|
+
const allowed = Object.keys(
|
|
2313
|
+
config
|
|
2314
|
+
);
|
|
2075
2315
|
throw new CallerError(
|
|
2076
2316
|
`Missing caller. This query uses named shape routing with keys: ${allowed.map((k) => `"${k}"`).join(", ")}. Provide caller via opts.caller.`
|
|
2077
2317
|
);
|
|
2078
2318
|
}
|
|
2079
|
-
const matched = matchCaller(
|
|
2319
|
+
const matched = matchCaller(
|
|
2320
|
+
config,
|
|
2321
|
+
caller
|
|
2322
|
+
);
|
|
2080
2323
|
if (!matched) {
|
|
2081
|
-
const allowed = Object.keys(
|
|
2324
|
+
const allowed = Object.keys(
|
|
2325
|
+
config
|
|
2326
|
+
);
|
|
2082
2327
|
throw new CallerError(
|
|
2083
2328
|
`Unknown caller: "${caller}". Allowed: ${allowed.map((k) => `"${k}"`).join(", ")}`
|
|
2084
2329
|
);
|
|
@@ -2711,7 +2956,10 @@ function resolveShape(input, body, contextFn, caller) {
|
|
|
2711
2956
|
|
|
2712
2957
|
// src/runtime/model-guard.ts
|
|
2713
2958
|
var UNIQUE_MUTATION_METHODS = /* @__PURE__ */ new Set(["update", "delete", "upsert"]);
|
|
2714
|
-
var UNIQUE_READ_METHODS = /* @__PURE__ */ new Set([
|
|
2959
|
+
var UNIQUE_READ_METHODS = /* @__PURE__ */ new Set([
|
|
2960
|
+
"findUnique",
|
|
2961
|
+
"findUniqueOrThrow"
|
|
2962
|
+
]);
|
|
2715
2963
|
var BULK_MUTATION_METHODS = /* @__PURE__ */ new Set([
|
|
2716
2964
|
"updateMany",
|
|
2717
2965
|
"updateManyAndReturn",
|
|
@@ -2725,15 +2973,14 @@ var PROJECTION_MUTATION_METHODS = /* @__PURE__ */ new Set([
|
|
|
2725
2973
|
"createManyAndReturn",
|
|
2726
2974
|
"updateManyAndReturn"
|
|
2727
2975
|
]);
|
|
2728
|
-
var BATCH_CREATE_METHODS = /* @__PURE__ */ new Set([
|
|
2729
|
-
"createMany",
|
|
2730
|
-
"createManyAndReturn"
|
|
2731
|
-
]);
|
|
2976
|
+
var BATCH_CREATE_METHODS = /* @__PURE__ */ new Set(["createMany", "createManyAndReturn"]);
|
|
2732
2977
|
function buildDefaultSelectInput(config) {
|
|
2733
2978
|
const result = {};
|
|
2734
2979
|
for (const [key, value] of Object.entries(config)) {
|
|
2735
2980
|
if (key === "_count") {
|
|
2736
|
-
result[key] = buildDefaultCountInput(
|
|
2981
|
+
result[key] = buildDefaultCountInput(
|
|
2982
|
+
value
|
|
2983
|
+
);
|
|
2737
2984
|
continue;
|
|
2738
2985
|
}
|
|
2739
2986
|
if (value === true) {
|
|
@@ -2751,7 +2998,9 @@ function buildDefaultIncludeInput(config) {
|
|
|
2751
2998
|
const result = {};
|
|
2752
2999
|
for (const [key, value] of Object.entries(config)) {
|
|
2753
3000
|
if (key === "_count") {
|
|
2754
|
-
result[key] = buildDefaultCountInput(
|
|
3001
|
+
result[key] = buildDefaultCountInput(
|
|
3002
|
+
value
|
|
3003
|
+
);
|
|
2755
3004
|
continue;
|
|
2756
3005
|
}
|
|
2757
3006
|
if (value === true) {
|
|
@@ -2865,12 +3114,32 @@ function hasNestedClientControlledArgs(shape) {
|
|
|
2865
3114
|
return false;
|
|
2866
3115
|
}
|
|
2867
3116
|
function createModelGuardExtension(config) {
|
|
2868
|
-
const {
|
|
3117
|
+
const {
|
|
3118
|
+
typeMap,
|
|
3119
|
+
enumMap,
|
|
3120
|
+
zodChains,
|
|
3121
|
+
zodDefaults,
|
|
3122
|
+
uniqueMap,
|
|
3123
|
+
scopeMap,
|
|
3124
|
+
guardConfig,
|
|
3125
|
+
contextFn
|
|
3126
|
+
} = config;
|
|
2869
3127
|
const wrapZodErrors = config.wrapZodErrors ?? false;
|
|
2870
3128
|
const enforceProjection = guardConfig.enforceProjection ?? false;
|
|
2871
3129
|
const scalarBase = createScalarBase(guardConfig.strictDecimal ?? false);
|
|
2872
|
-
const schemaBuilder = createSchemaBuilder(
|
|
2873
|
-
|
|
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
|
+
);
|
|
2874
3143
|
const modelScopeFks = /* @__PURE__ */ new Map();
|
|
2875
3144
|
for (const [model, entries] of Object.entries(scopeMap)) {
|
|
2876
3145
|
const fks = /* @__PURE__ */ new Set();
|
|
@@ -2888,7 +3157,9 @@ function createModelGuardExtension(config) {
|
|
|
2888
3157
|
function createGuardedMethods(modelName, modelDelegate, input, explicitCaller) {
|
|
2889
3158
|
function callDelegate(method, args) {
|
|
2890
3159
|
if (typeof modelDelegate[method] !== "function") {
|
|
2891
|
-
throw new ShapeError(
|
|
3160
|
+
throw new ShapeError(
|
|
3161
|
+
`Method "${method}" is not available on this model`
|
|
3162
|
+
);
|
|
2892
3163
|
}
|
|
2893
3164
|
return modelDelegate[method](args);
|
|
2894
3165
|
}
|
|
@@ -2911,11 +3182,19 @@ function createModelGuardExtension(config) {
|
|
|
2911
3182
|
const cached = readShapeCache.get(cacheKey);
|
|
2912
3183
|
if (cached)
|
|
2913
3184
|
return cached;
|
|
2914
|
-
const built = queryBuilder.buildShapeZodSchema(
|
|
3185
|
+
const built = queryBuilder.buildShapeZodSchema(
|
|
3186
|
+
modelName,
|
|
3187
|
+
method,
|
|
3188
|
+
queryShape
|
|
3189
|
+
);
|
|
2915
3190
|
readShapeCache.set(cacheKey, built);
|
|
2916
3191
|
return built;
|
|
2917
3192
|
}
|
|
2918
|
-
return queryBuilder.buildShapeZodSchema(
|
|
3193
|
+
return queryBuilder.buildShapeZodSchema(
|
|
3194
|
+
modelName,
|
|
3195
|
+
method,
|
|
3196
|
+
queryShape
|
|
3197
|
+
);
|
|
2919
3198
|
}
|
|
2920
3199
|
function getDataSchema(mode, dataConfig, matchedKey, wasDynamic) {
|
|
2921
3200
|
if (!wasDynamic && !hasDataRefines(dataConfig)) {
|
|
@@ -2923,11 +3202,25 @@ function createModelGuardExtension(config) {
|
|
|
2923
3202
|
const cached = dataSchemaCache.get(cacheKey);
|
|
2924
3203
|
if (cached)
|
|
2925
3204
|
return cached;
|
|
2926
|
-
const built = buildDataSchema(
|
|
3205
|
+
const built = buildDataSchema(
|
|
3206
|
+
modelName,
|
|
3207
|
+
dataConfig,
|
|
3208
|
+
mode,
|
|
3209
|
+
typeMap,
|
|
3210
|
+
schemaBuilder,
|
|
3211
|
+
zodDefaults
|
|
3212
|
+
);
|
|
2927
3213
|
dataSchemaCache.set(cacheKey, built);
|
|
2928
3214
|
return built;
|
|
2929
3215
|
}
|
|
2930
|
-
return buildDataSchema(
|
|
3216
|
+
return buildDataSchema(
|
|
3217
|
+
modelName,
|
|
3218
|
+
dataConfig,
|
|
3219
|
+
mode,
|
|
3220
|
+
typeMap,
|
|
3221
|
+
schemaBuilder,
|
|
3222
|
+
zodDefaults
|
|
3223
|
+
);
|
|
2931
3224
|
}
|
|
2932
3225
|
function getWhereBuilt(whereConfig, matchedKey, wasDynamic) {
|
|
2933
3226
|
if (!wasDynamic) {
|
|
@@ -3046,12 +3339,28 @@ function createModelGuardExtension(config) {
|
|
|
3046
3339
|
const built = getWhereBuilt(shape.where, matchedKey, wasDynamic);
|
|
3047
3340
|
let validatedWhere;
|
|
3048
3341
|
if (built.schema) {
|
|
3049
|
-
|
|
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);
|
|
3050
3351
|
} else if (bodyWhere !== void 0) {
|
|
3051
3352
|
if (bodyWhere === null || !isPlainObject(bodyWhere) || Object.keys(bodyWhere).length > 0) {
|
|
3052
|
-
|
|
3053
|
-
|
|
3054
|
-
|
|
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
|
+
}
|
|
3055
3364
|
}
|
|
3056
3365
|
}
|
|
3057
3366
|
if (hasWhereForced(built.forced)) {
|
|
@@ -3060,7 +3369,13 @@ function createModelGuardExtension(config) {
|
|
|
3060
3369
|
return validatedWhere ?? {};
|
|
3061
3370
|
}
|
|
3062
3371
|
function requireWhere(shape, bodyWhere, method, preserveUnique, matchedKey, wasDynamic) {
|
|
3063
|
-
const where = buildWhereFromShape(
|
|
3372
|
+
const where = buildWhereFromShape(
|
|
3373
|
+
shape,
|
|
3374
|
+
bodyWhere,
|
|
3375
|
+
preserveUnique,
|
|
3376
|
+
matchedKey,
|
|
3377
|
+
wasDynamic
|
|
3378
|
+
);
|
|
3064
3379
|
if (Object.keys(where).length === 0) {
|
|
3065
3380
|
throw new ShapeError(`${method} requires a where condition`);
|
|
3066
3381
|
}
|
|
@@ -3074,7 +3389,12 @@ function createModelGuardExtension(config) {
|
|
|
3074
3389
|
throw new ShapeError(`Guard shape "data" is not valid for ${method}`);
|
|
3075
3390
|
}
|
|
3076
3391
|
const { data: _, ...queryShape } = resolved.shape;
|
|
3077
|
-
const built = getReadShape(
|
|
3392
|
+
const built = getReadShape(
|
|
3393
|
+
method,
|
|
3394
|
+
queryShape,
|
|
3395
|
+
resolved.matchedKey,
|
|
3396
|
+
resolved.wasDynamic
|
|
3397
|
+
);
|
|
3078
3398
|
const isUnique = UNIQUE_READ_METHODS.has(method);
|
|
3079
3399
|
const args = applyBuiltShape(built, resolved.body, isUnique);
|
|
3080
3400
|
if (isUnique && args.where) {
|
|
@@ -3107,14 +3427,33 @@ function createModelGuardExtension(config) {
|
|
|
3107
3427
|
const resolved = resolveShape(input, body, contextFn, caller);
|
|
3108
3428
|
if (!resolved.shape.data)
|
|
3109
3429
|
throw new ShapeError(`Guard shape requires "data" for ${method}`);
|
|
3110
|
-
validateMutationShapeKeys(
|
|
3430
|
+
validateMutationShapeKeys(
|
|
3431
|
+
resolved.shape,
|
|
3432
|
+
allowedShapeKeys,
|
|
3433
|
+
method
|
|
3434
|
+
);
|
|
3111
3435
|
validateMutationBodyKeys(resolved.body, allowedBodyKeys, method);
|
|
3112
3436
|
const fks = modelScopeFks.get(modelName) ?? /* @__PURE__ */ new Set();
|
|
3113
|
-
validateCreateCompleteness(
|
|
3114
|
-
|
|
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
|
+
);
|
|
3115
3450
|
let args;
|
|
3116
3451
|
if (method === "create") {
|
|
3117
|
-
const data = validateAndMergeData(
|
|
3452
|
+
const data = validateAndMergeData(
|
|
3453
|
+
resolved.body.data,
|
|
3454
|
+
dataSchema,
|
|
3455
|
+
method
|
|
3456
|
+
);
|
|
3118
3457
|
args = { data };
|
|
3119
3458
|
} else {
|
|
3120
3459
|
if (!Array.isArray(resolved.body.data))
|
|
@@ -3133,7 +3472,13 @@ function createModelGuardExtension(config) {
|
|
|
3133
3472
|
args.skipDuplicates = resolved.body.skipDuplicates;
|
|
3134
3473
|
}
|
|
3135
3474
|
if (supportsProjection) {
|
|
3136
|
-
const projectionArgs = resolveProjection(
|
|
3475
|
+
const projectionArgs = resolveProjection(
|
|
3476
|
+
resolved.shape,
|
|
3477
|
+
resolved.body,
|
|
3478
|
+
method,
|
|
3479
|
+
resolved.matchedKey,
|
|
3480
|
+
resolved.wasDynamic
|
|
3481
|
+
);
|
|
3137
3482
|
Object.assign(args, projectionArgs);
|
|
3138
3483
|
}
|
|
3139
3484
|
return callDelegate(method, args);
|
|
@@ -3150,24 +3495,60 @@ function createModelGuardExtension(config) {
|
|
|
3150
3495
|
const resolved = resolveShape(input, body, contextFn, caller);
|
|
3151
3496
|
if (!resolved.shape.data)
|
|
3152
3497
|
throw new ShapeError(`Guard shape requires "data" for ${method}`);
|
|
3153
|
-
validateMutationShapeKeys(
|
|
3498
|
+
validateMutationShapeKeys(
|
|
3499
|
+
resolved.shape,
|
|
3500
|
+
allowedShapeKeys,
|
|
3501
|
+
method
|
|
3502
|
+
);
|
|
3154
3503
|
validateMutationBodyKeys(resolved.body, allowedBodyKeys, method);
|
|
3155
3504
|
if (isBulk && !resolved.shape.where) {
|
|
3156
|
-
throw new ShapeError(
|
|
3505
|
+
throw new ShapeError(
|
|
3506
|
+
`Guard shape requires "where" for ${method} to prevent unconstrained bulk mutations`
|
|
3507
|
+
);
|
|
3157
3508
|
}
|
|
3158
3509
|
maybeValidateUniqueWhere(modelName, resolved.shape, method);
|
|
3159
|
-
const dataSchema = getDataSchema(
|
|
3160
|
-
|
|
3161
|
-
|
|
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
|
+
);
|
|
3162
3535
|
if (isBulk && Object.keys(where).length === 0) {
|
|
3163
|
-
throw new ShapeError(
|
|
3536
|
+
throw new ShapeError(
|
|
3537
|
+
`${method} requires at least one where condition`
|
|
3538
|
+
);
|
|
3164
3539
|
}
|
|
3165
3540
|
if (isUniqueWhere) {
|
|
3166
3541
|
validateResolvedUniqueWhere(modelName, where, method, uniqueMap);
|
|
3167
3542
|
}
|
|
3168
3543
|
const args = { data, where };
|
|
3169
3544
|
if (supportsProjection) {
|
|
3170
|
-
const projectionArgs = resolveProjection(
|
|
3545
|
+
const projectionArgs = resolveProjection(
|
|
3546
|
+
resolved.shape,
|
|
3547
|
+
resolved.body,
|
|
3548
|
+
method,
|
|
3549
|
+
resolved.matchedKey,
|
|
3550
|
+
resolved.wasDynamic
|
|
3551
|
+
);
|
|
3171
3552
|
Object.assign(args, projectionArgs);
|
|
3172
3553
|
}
|
|
3173
3554
|
return callDelegate(method, args);
|
|
@@ -3184,22 +3565,49 @@ function createModelGuardExtension(config) {
|
|
|
3184
3565
|
const resolved = resolveShape(input, body, contextFn, caller);
|
|
3185
3566
|
if (resolved.shape.data)
|
|
3186
3567
|
throw new ShapeError(`Guard shape "data" is not valid for ${method}`);
|
|
3187
|
-
validateMutationShapeKeys(
|
|
3568
|
+
validateMutationShapeKeys(
|
|
3569
|
+
resolved.shape,
|
|
3570
|
+
allowedShapeKeys,
|
|
3571
|
+
method
|
|
3572
|
+
);
|
|
3188
3573
|
validateMutationBodyKeys(resolved.body, allowedBodyKeys, method);
|
|
3189
3574
|
if (isBulk && !resolved.shape.where) {
|
|
3190
|
-
throw new ShapeError(
|
|
3575
|
+
throw new ShapeError(
|
|
3576
|
+
`Guard shape requires "where" for ${method} to prevent unconstrained bulk mutations`
|
|
3577
|
+
);
|
|
3191
3578
|
}
|
|
3192
3579
|
maybeValidateUniqueWhere(modelName, resolved.shape, method);
|
|
3193
|
-
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
|
+
);
|
|
3194
3594
|
if (isBulk && Object.keys(where).length === 0) {
|
|
3195
|
-
throw new ShapeError(
|
|
3595
|
+
throw new ShapeError(
|
|
3596
|
+
`${method} requires at least one where condition`
|
|
3597
|
+
);
|
|
3196
3598
|
}
|
|
3197
3599
|
if (isUniqueWhere) {
|
|
3198
3600
|
validateResolvedUniqueWhere(modelName, where, method, uniqueMap);
|
|
3199
3601
|
}
|
|
3200
3602
|
const args = { where };
|
|
3201
3603
|
if (supportsProjection) {
|
|
3202
|
-
const projectionArgs = resolveProjection(
|
|
3604
|
+
const projectionArgs = resolveProjection(
|
|
3605
|
+
resolved.shape,
|
|
3606
|
+
resolved.body,
|
|
3607
|
+
method,
|
|
3608
|
+
resolved.matchedKey,
|
|
3609
|
+
resolved.wasDynamic
|
|
3610
|
+
);
|
|
3203
3611
|
Object.assign(args, projectionArgs);
|
|
3204
3612
|
}
|
|
3205
3613
|
return callDelegate(method, args);
|
|
@@ -3210,7 +3618,9 @@ function createModelGuardExtension(config) {
|
|
|
3210
3618
|
const caller = resolveCaller();
|
|
3211
3619
|
const resolved = resolveShape(input, body, contextFn, caller);
|
|
3212
3620
|
if (resolved.shape.data) {
|
|
3213
|
-
throw new ShapeError(
|
|
3621
|
+
throw new ShapeError(
|
|
3622
|
+
'Guard shape "data" is not valid for upsert. Use "create" and "update" instead.'
|
|
3623
|
+
);
|
|
3214
3624
|
}
|
|
3215
3625
|
if (!resolved.shape.create) {
|
|
3216
3626
|
throw new ShapeError('Guard shape requires "create" for upsert');
|
|
@@ -3226,24 +3636,42 @@ function createModelGuardExtension(config) {
|
|
|
3226
3636
|
VALID_SHAPE_KEYS_UPSERT,
|
|
3227
3637
|
"upsert"
|
|
3228
3638
|
);
|
|
3229
|
-
validateMutationBodyKeys(
|
|
3639
|
+
validateMutationBodyKeys(
|
|
3640
|
+
resolved.body,
|
|
3641
|
+
ALLOWED_BODY_KEYS_UPSERT,
|
|
3642
|
+
"upsert"
|
|
3643
|
+
);
|
|
3230
3644
|
maybeValidateUniqueWhere(modelName, resolved.shape, "upsert");
|
|
3231
3645
|
const fks = modelScopeFks.get(modelName) ?? /* @__PURE__ */ new Set();
|
|
3232
|
-
validateCreateCompleteness(
|
|
3646
|
+
validateCreateCompleteness(
|
|
3647
|
+
modelName,
|
|
3648
|
+
resolved.shape.create,
|
|
3649
|
+
typeMap,
|
|
3650
|
+
fks,
|
|
3651
|
+
zodDefaults
|
|
3652
|
+
);
|
|
3233
3653
|
const createDataSchema = getDataSchema(
|
|
3234
3654
|
"create",
|
|
3235
3655
|
resolved.shape.create,
|
|
3236
3656
|
`upsert:create\0${resolved.matchedKey}`,
|
|
3237
3657
|
resolved.wasDynamic
|
|
3238
3658
|
);
|
|
3239
|
-
const createData = validateAndMergeData(
|
|
3659
|
+
const createData = validateAndMergeData(
|
|
3660
|
+
resolved.body.create,
|
|
3661
|
+
createDataSchema,
|
|
3662
|
+
"upsert (create)"
|
|
3663
|
+
);
|
|
3240
3664
|
const updateDataSchema = getDataSchema(
|
|
3241
3665
|
"update",
|
|
3242
3666
|
resolved.shape.update,
|
|
3243
3667
|
`upsert:update\0${resolved.matchedKey}`,
|
|
3244
3668
|
resolved.wasDynamic
|
|
3245
3669
|
);
|
|
3246
|
-
const updateData = validateAndMergeData(
|
|
3670
|
+
const updateData = validateAndMergeData(
|
|
3671
|
+
resolved.body.update,
|
|
3672
|
+
updateDataSchema,
|
|
3673
|
+
"upsert (update)"
|
|
3674
|
+
);
|
|
3247
3675
|
const where = requireWhere(
|
|
3248
3676
|
resolved.shape,
|
|
3249
3677
|
resolved.body.where,
|
|
@@ -3297,10 +3725,9 @@ function createModelGuardExtension(config) {
|
|
|
3297
3725
|
return fn(body);
|
|
3298
3726
|
} catch (err) {
|
|
3299
3727
|
if (err instanceof import_zod9.z.ZodError) {
|
|
3300
|
-
throw new ShapeError(
|
|
3301
|
-
|
|
3302
|
-
|
|
3303
|
-
);
|
|
3728
|
+
throw new ShapeError(`Validation failed: ${formatZodError(err)}`, {
|
|
3729
|
+
cause: err
|
|
3730
|
+
});
|
|
3304
3731
|
}
|
|
3305
3732
|
throw err;
|
|
3306
3733
|
}
|
|
@@ -3319,7 +3746,12 @@ function createModelGuardExtension(config) {
|
|
|
3319
3746
|
`Could not resolve Prisma delegate for model "${modelName}" (key: "${delegateKey}")`
|
|
3320
3747
|
);
|
|
3321
3748
|
}
|
|
3322
|
-
const methods = createGuardedMethods(
|
|
3749
|
+
const methods = createGuardedMethods(
|
|
3750
|
+
modelName,
|
|
3751
|
+
modelDelegate,
|
|
3752
|
+
input,
|
|
3753
|
+
caller
|
|
3754
|
+
);
|
|
3323
3755
|
if (!wrapZodErrors)
|
|
3324
3756
|
return methods;
|
|
3325
3757
|
return wrapMethods(methods);
|