prisma-guard 1.24.0 → 1.26.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.
@@ -342,12 +342,24 @@ var JSON_ARRAY_OPERATORS = /* @__PURE__ */ new Set([
342
342
  "array_starts_with",
343
343
  "array_ends_with"
344
344
  ]);
345
- function getSupportedOperators(fieldMeta) {
346
- if (fieldMeta.isList)
345
+ function getSupportedOperators(input, isList = false, isEnum = false) {
346
+ let fieldType;
347
+ let list;
348
+ let enumField;
349
+ if (typeof input === "string") {
350
+ fieldType = input;
351
+ list = isList;
352
+ enumField = isEnum;
353
+ } else {
354
+ fieldType = input.type;
355
+ list = input.isList;
356
+ enumField = input.isEnum === true;
357
+ }
358
+ if (list)
347
359
  return [...SCALAR_LIST_OPERATORS];
348
- if (fieldMeta.isEnum)
360
+ if (enumField)
349
361
  return [...ENUM_OPERATORS];
350
- const ops = SCALAR_OPERATORS[fieldMeta.type];
362
+ const ops = SCALAR_OPERATORS[fieldType];
351
363
  if (!ops)
352
364
  return [];
353
365
  return [...ops];
@@ -408,15 +420,14 @@ function createJsonOperatorSchema(fieldMeta, operator) {
408
420
  if (JSON_ARRAY_OPERATORS.has(operator)) {
409
421
  return jsonValue;
410
422
  }
411
- throw new ShapeError(
412
- `Operator "${operator}" not supported for Json fields`
413
- );
423
+ throw new ShapeError(`Operator "${operator}" not supported for Json fields`);
414
424
  }
415
425
  function buildNotFilterSchema(fieldMeta, scalarSchema, enumMap, scalarBase) {
416
426
  const allOps = getSupportedOperators(fieldMeta);
417
- const nestedOps = allOps.filter((o) => o !== "not");
418
- if (nestedOps.length === 0)
427
+ const nestedOps = allOps.filter((op) => op !== "not");
428
+ if (nestedOps.length === 0) {
419
429
  return scalarSchema;
430
+ }
420
431
  const nestedSchemas = {};
421
432
  for (const op of nestedOps) {
422
433
  nestedSchemas[op] = createOperatorSchema(
@@ -428,14 +439,35 @@ function buildNotFilterSchema(fieldMeta, scalarSchema, enumMap, scalarBase) {
428
439
  }
429
440
  const nestedKeys = Object.keys(nestedSchemas);
430
441
  const nestedObj = z2.object(nestedSchemas).strict().refine(
431
- (v) => nestedKeys.some(
432
- (k) => v[k] !== void 0
442
+ (value) => nestedKeys.some(
443
+ (key) => value[key] !== void 0
433
444
  ),
434
445
  { message: "not filter must specify at least one operator" }
435
446
  );
436
447
  return z2.union([scalarSchema, nestedObj]);
437
448
  }
438
449
  function createOperatorSchema(fieldMeta, operator, enumMap, scalarBase) {
450
+ const allowedOps = getSupportedOperators(fieldMeta);
451
+ if (!allowedOps.includes(operator)) {
452
+ if (fieldMeta.isList) {
453
+ throw new ShapeError(
454
+ `Operator "${operator}" not supported for scalar list fields`
455
+ );
456
+ }
457
+ if (fieldMeta.isEnum) {
458
+ throw new ShapeError(
459
+ `Operator "${operator}" not supported for enum fields`
460
+ );
461
+ }
462
+ if (fieldMeta.type === "Bytes" && allowedOps.length === 0) {
463
+ throw new ShapeError(
464
+ `Type "${fieldMeta.type}" does not support filter operators`
465
+ );
466
+ }
467
+ throw new ShapeError(
468
+ `Operator "${operator}" not supported for type "${fieldMeta.type}"`
469
+ );
470
+ }
439
471
  if (fieldMeta.isList) {
440
472
  return createScalarListOperatorSchema(
441
473
  fieldMeta,
@@ -449,50 +481,35 @@ function createOperatorSchema(fieldMeta, operator, enumMap, scalarBase) {
449
481
  if (!values || values.length === 0) {
450
482
  throw new ShapeError(`Unknown enum: ${fieldMeta.type}`);
451
483
  }
452
- if (!ENUM_OPERATORS.has(operator)) {
453
- throw new ShapeError(
454
- `Operator "${operator}" not supported for enum fields`
455
- );
456
- }
457
484
  const enumSchema = z2.enum(values);
458
485
  if (operator === "equals") {
459
486
  return !fieldMeta.isRequired ? z2.union([enumSchema, z2.null()]) : enumSchema;
460
487
  }
461
488
  if (operator === "not") {
462
489
  const scalarSchema = !fieldMeta.isRequired ? z2.union([enumSchema, z2.null()]) : enumSchema;
463
- return buildNotFilterSchema(fieldMeta, scalarSchema, enumMap, scalarBase);
490
+ return buildNotFilterSchema(
491
+ fieldMeta,
492
+ scalarSchema,
493
+ enumMap,
494
+ scalarBase
495
+ );
464
496
  }
465
497
  const itemSchema = !fieldMeta.isRequired ? z2.union([enumSchema, z2.null()]) : enumSchema;
466
498
  return z2.preprocess(coerceToArray, z2.array(itemSchema));
467
499
  }
468
500
  if (fieldMeta.type === "Json") {
469
- const supportedOps2 = SCALAR_OPERATORS["Json"];
470
- if (!supportedOps2 || !supportedOps2.has(operator)) {
471
- throw new ShapeError(
472
- `Operator "${operator}" not supported for type "Json"`
473
- );
474
- }
475
501
  if (operator === "not") {
476
502
  const jsonValue = z2.unknown();
477
503
  const scalarSchema = !fieldMeta.isRequired ? z2.union([jsonValue, z2.null()]) : jsonValue;
478
- return buildNotFilterSchema(fieldMeta, scalarSchema, enumMap, scalarBase);
504
+ return buildNotFilterSchema(
505
+ fieldMeta,
506
+ scalarSchema,
507
+ enumMap,
508
+ scalarBase
509
+ );
479
510
  }
480
511
  return createJsonOperatorSchema(fieldMeta, operator);
481
512
  }
482
- const supportedOps = SCALAR_OPERATORS[fieldMeta.type];
483
- if (!supportedOps) {
484
- throw new ShapeError(`Unknown scalar type for operator: ${fieldMeta.type}`);
485
- }
486
- if (supportedOps.size === 0) {
487
- throw new ShapeError(
488
- `Type "${fieldMeta.type}" does not support filter operators`
489
- );
490
- }
491
- if (!supportedOps.has(operator)) {
492
- throw new ShapeError(
493
- `Operator "${operator}" not supported for type "${fieldMeta.type}"`
494
- );
495
- }
496
513
  const factory = scalarBase[fieldMeta.type];
497
514
  if (!factory) {
498
515
  throw new ShapeError(`Unknown scalar type: ${fieldMeta.type}`);
@@ -968,33 +985,67 @@ function mergeWhereForced(where, forced) {
968
985
  }
969
986
  return result;
970
987
  }
988
+ function uniqueValuesEqual(a, b) {
989
+ if (a === b)
990
+ return true;
991
+ if (a === null || b === null)
992
+ return false;
993
+ if (typeof a !== typeof b)
994
+ return false;
995
+ if (a instanceof Date && b instanceof Date) {
996
+ return a.getTime() === b.getTime();
997
+ }
998
+ if (Array.isArray(a)) {
999
+ if (!Array.isArray(b))
1000
+ return false;
1001
+ if (a.length !== b.length)
1002
+ return false;
1003
+ return a.every((v, i) => uniqueValuesEqual(v, b[i]));
1004
+ }
1005
+ if (isPlainObject(a) && isPlainObject(b)) {
1006
+ const aKeys = Object.keys(a);
1007
+ const bKeys = Object.keys(b);
1008
+ if (aKeys.length !== bKeys.length)
1009
+ return false;
1010
+ return aKeys.every((key) => key in b && uniqueValuesEqual(a[key], b[key]));
1011
+ }
1012
+ return false;
1013
+ }
1014
+ function mergeUniqueValue(target, key, value) {
1015
+ const cloned = deepClone(value);
1016
+ if (!(key in target)) {
1017
+ target[key] = cloned;
1018
+ return;
1019
+ }
1020
+ const existing = target[key];
1021
+ if (isPlainObject(existing) && isPlainObject(cloned)) {
1022
+ const merged = { ...existing };
1023
+ for (const [nestedKey, nestedValue] of Object.entries(cloned)) {
1024
+ if (nestedKey in merged && !uniqueValuesEqual(merged[nestedKey], nestedValue)) {
1025
+ throw new ShapeError(
1026
+ `Conflicting unique where value for "${key}.${nestedKey}"`
1027
+ );
1028
+ }
1029
+ merged[nestedKey] = nestedValue;
1030
+ }
1031
+ target[key] = merged;
1032
+ return;
1033
+ }
1034
+ if (!uniqueValuesEqual(existing, cloned)) {
1035
+ throw new ShapeError(`Conflicting unique where value for "${key}"`);
1036
+ }
1037
+ }
971
1038
  function mergeUniqueWhereForced(where, forced) {
972
1039
  if (!hasWhereForced(forced))
973
1040
  return where ?? {};
974
- let result = where ? { ...where } : {};
975
- for (const [relName, opMap] of Object.entries(forced.relations)) {
976
- if (!result[relName] || typeof result[relName] !== "object") {
977
- result[relName] = {};
978
- }
979
- const relObj = result[relName];
980
- for (const [op, nestedForced] of Object.entries(opMap)) {
981
- relObj[op] = mergeWhereForced(
982
- relObj[op],
983
- nestedForced
984
- );
985
- }
1041
+ if (Object.keys(forced.relations).length > 0) {
1042
+ throw new ShapeError(
1043
+ "Unique where forced conditions cannot contain relation filters"
1044
+ );
986
1045
  }
987
- if (Object.keys(forced.conditions).length > 0) {
988
- const conditions = [deepClone(forced.conditions)];
989
- const existing = result.AND;
990
- if (existing) {
991
- if (Array.isArray(existing)) {
992
- conditions.unshift(...existing);
993
- } else {
994
- conditions.unshift(existing);
995
- }
996
- }
997
- result.AND = conditions;
1046
+ const result = where ? deepClone(where) : {};
1047
+ for (const [key, value] of Object.entries(forced.conditions)) {
1048
+ mergeUniqueValue(result, key, value);
998
1049
  }
999
1050
  return result;
1000
1051
  }
@@ -1010,6 +1061,17 @@ function applyBuiltShape(built, body, isUniqueMethod, modelName) {
1010
1061
  if (!hasWhereInSchema) {
1011
1062
  const { where: _, ...rest } = bodyObj;
1012
1063
  parseable = rest;
1064
+ } else if (isUniqueMethod && hasWhereForced(built.forcedWhere) && isPlainObject(bodyObj.where)) {
1065
+ const where = stripUniqueWhereForcedInput(
1066
+ bodyObj.where,
1067
+ built.forcedWhere
1068
+ );
1069
+ if (Object.keys(where).length === 0) {
1070
+ const { where: _, ...rest } = bodyObj;
1071
+ parseable = rest;
1072
+ } else {
1073
+ parseable = { ...bodyObj, where };
1074
+ }
1013
1075
  } else if (built.forcedOnlyWhereKeys.size > 0 && isPlainObject(bodyObj.where)) {
1014
1076
  const where = { ...bodyObj.where };
1015
1077
  for (const key of built.forcedOnlyWhereKeys) {
@@ -1117,13 +1179,15 @@ function applyForcedTree(validated, key, tree) {
1117
1179
  );
1118
1180
  }
1119
1181
  if (forced.include) {
1120
- if (!relObj.include)
1182
+ if (!relObj.include) {
1121
1183
  relObj.include = buildForcedOnlyContainer(forced.include);
1184
+ }
1122
1185
  applyForcedTree(relObj, "include", forced.include);
1123
1186
  }
1124
1187
  if (forced.select) {
1125
- if (!relObj.select)
1188
+ if (!relObj.select) {
1126
1189
  relObj.select = buildForcedOnlyContainer(forced.select);
1190
+ }
1127
1191
  applyForcedTree(relObj, "select", forced.select);
1128
1192
  }
1129
1193
  if (forced._countWhere && Object.keys(forced._countWhere).length > 0) {
@@ -1148,10 +1212,12 @@ function buildForcedOnlyContainer(tree) {
1148
1212
  if (forced.where && hasWhereForced(forced.where)) {
1149
1213
  nested.where = mergeWhereForced(void 0, forced.where);
1150
1214
  }
1151
- if (forced.include)
1215
+ if (forced.include) {
1152
1216
  nested.include = buildForcedOnlyContainer(forced.include);
1153
- if (forced.select)
1217
+ }
1218
+ if (forced.select) {
1154
1219
  nested.select = buildForcedOnlyContainer(forced.select);
1220
+ }
1155
1221
  if (forced._countWhere && Object.keys(forced._countWhere).length > 0) {
1156
1222
  const placement = forced._countWherePlacement ?? "include";
1157
1223
  if (!nested[placement])
@@ -1187,77 +1253,131 @@ function applyForcedCountWhere(container, forcedCountWhere) {
1187
1253
  }
1188
1254
  }
1189
1255
  }
1190
- function collectWhereFieldKeys(where) {
1191
- const keys = /* @__PURE__ */ new Set();
1192
- for (const [key, value] of Object.entries(where)) {
1193
- if (key === "AND") {
1194
- const items = Array.isArray(value) ? value : [value];
1195
- for (const item of items) {
1196
- if (isPlainObject(item)) {
1197
- for (const k of collectWhereFieldKeys(item))
1198
- keys.add(k);
1199
- }
1200
- }
1201
- } else if (key !== "OR" && key !== "NOT") {
1202
- keys.add(key);
1203
- }
1256
+ function formatUniqueConstraint(constraint) {
1257
+ return constraint.fields.length === 1 ? constraint.selector : `${constraint.selector}(${constraint.fields.join(", ")})`;
1258
+ }
1259
+ function formatUniqueConstraints(constraints) {
1260
+ return constraints.map(formatUniqueConstraint).join(" | ");
1261
+ }
1262
+ function resolvedWhereCoversConstraint(where, constraint) {
1263
+ if (constraint.fields.length === 1) {
1264
+ return constraint.fields[0] in where;
1204
1265
  }
1205
- return keys;
1266
+ const value = where[constraint.selector];
1267
+ if (!isPlainObject(value))
1268
+ return false;
1269
+ return constraint.fields.every((field) => field in value);
1206
1270
  }
1207
1271
  function validateResolvedUniqueWhere(model, where, method, uniqueMap) {
1208
1272
  const constraints = uniqueMap[model];
1209
1273
  if (!constraints || constraints.length === 0)
1210
1274
  return;
1211
- const fieldKeys = collectWhereFieldKeys(where);
1212
1275
  const covered = constraints.some(
1213
- (constraint) => constraint.every((field) => fieldKeys.has(field))
1276
+ (constraint) => resolvedWhereCoversConstraint(where, constraint)
1214
1277
  );
1215
1278
  if (!covered) {
1216
- const constraintDesc = constraints.map((c) => `(${c.join(", ")})`).join(" | ");
1217
1279
  throw new ShapeError(
1218
- `${method} on model "${model}" requires resolved where to cover a unique constraint: ${constraintDesc}`
1280
+ `${method} on model "${model}" requires resolved where to cover a unique constraint: ${formatUniqueConstraints(constraints)}`
1219
1281
  );
1220
1282
  }
1221
1283
  }
1222
- function collectEqualityFields(where, model, typeMap) {
1223
- const combinators = /* @__PURE__ */ new Set(["AND", "OR", "NOT"]);
1224
- const fields = /* @__PURE__ */ new Set();
1225
- for (const [key, value] of Object.entries(where)) {
1226
- if (key === "AND") {
1227
- if (isPlainObject(value)) {
1228
- for (const f of collectEqualityFields(value, model, typeMap)) {
1229
- fields.add(f);
1230
- }
1231
- }
1232
- continue;
1284
+ function assertDirectUniqueShapeValue(model, field, value, typeMap) {
1285
+ if (typeMap && model) {
1286
+ const fieldMeta = typeMap[model]?.[field];
1287
+ if (!fieldMeta) {
1288
+ throw new ShapeError(`Unknown unique where field "${model}.${field}"`);
1233
1289
  }
1234
- if (combinators.has(key))
1235
- continue;
1236
- if (typeMap && model && typeMap[model]?.[key]?.isRelation)
1237
- continue;
1238
- if (!value || !isPlainObject(value))
1239
- continue;
1240
- if ("equals" in value) {
1241
- fields.add(key);
1290
+ if (fieldMeta.isRelation) {
1291
+ throw new ShapeError(
1292
+ `Relation field "${model}.${field}" cannot be used in unique where`
1293
+ );
1294
+ }
1295
+ }
1296
+ if (isForcedValue(value))
1297
+ return;
1298
+ if (isPlainObject(value)) {
1299
+ const keys = Object.keys(value);
1300
+ throw new ShapeError(
1301
+ `Invalid unique where shape for "${model ?? "unknown"}.${field}". Prisma WhereUniqueInput does not accept filter operator objects${keys.length ? `: ${keys.join(", ")}` : ""}. Use { ${field}: true } in guard shape and { ${field}: value } in request args.`
1302
+ );
1303
+ }
1304
+ if (value === null || value === void 0) {
1305
+ throw new ShapeError(
1306
+ `Invalid unique where shape for "${model ?? "unknown"}.${field}". Unique fields must use true or a forced value.`
1307
+ );
1308
+ }
1309
+ }
1310
+ function shapeCoversConstraint(where, constraint, model, typeMap) {
1311
+ if (constraint.fields.length === 1) {
1312
+ const field = constraint.fields[0];
1313
+ if (!(field in where))
1314
+ return false;
1315
+ assertDirectUniqueShapeValue(model, field, where[field], typeMap);
1316
+ return true;
1317
+ }
1318
+ if (!(constraint.selector in where))
1319
+ return false;
1320
+ const selectorValue = where[constraint.selector];
1321
+ if (isForcedValue(selectorValue))
1322
+ return true;
1323
+ if (!isPlainObject(selectorValue)) {
1324
+ throw new ShapeError(
1325
+ `Compound unique selector "${model}.${constraint.selector}" must be an object with fields: ${constraint.fields.join(", ")}`
1326
+ );
1327
+ }
1328
+ const allowed = new Set(constraint.fields);
1329
+ for (const key of Object.keys(selectorValue)) {
1330
+ if (!allowed.has(key)) {
1331
+ throw new ShapeError(
1332
+ `Unknown field "${key}" in compound unique selector "${model}.${constraint.selector}". Allowed fields: ${constraint.fields.join(", ")}`
1333
+ );
1242
1334
  }
1243
1335
  }
1244
- return fields;
1336
+ for (const field of constraint.fields) {
1337
+ if (!(field in selectorValue)) {
1338
+ throw new ShapeError(
1339
+ `Missing field "${field}" in compound unique selector "${model}.${constraint.selector}"`
1340
+ );
1341
+ }
1342
+ assertDirectUniqueShapeValue(model, field, selectorValue[field], typeMap);
1343
+ }
1344
+ return true;
1245
1345
  }
1246
1346
  function validateUniqueEquality(model, where, method, uniqueMap, typeMap) {
1247
1347
  const constraints = uniqueMap[model];
1248
1348
  if (!constraints || constraints.length === 0)
1249
1349
  return;
1250
- const equalityFields = collectEqualityFields(where, model, typeMap);
1251
1350
  const valid = constraints.some(
1252
- (constraint) => constraint.every((field) => equalityFields.has(field))
1351
+ (constraint) => shapeCoversConstraint(where, constraint, model, typeMap)
1253
1352
  );
1254
1353
  if (!valid) {
1255
- const constraintDesc = constraints.map((c) => `(${c.join(", ")})`).join(" | ");
1256
1354
  throw new ShapeError(
1257
- `${method} on model "${model}" requires where to cover a unique constraint with equality operators only: ${constraintDesc}`
1355
+ `${method} on model "${model}" requires unique where shape to cover a unique constraint using Prisma unique selector syntax: ${formatUniqueConstraints(constraints)}`
1258
1356
  );
1259
1357
  }
1260
1358
  }
1359
+ function stripUniqueWhereForcedInput(where, forced) {
1360
+ const result = deepClone(where);
1361
+ for (const [key, forcedValue] of Object.entries(forced.conditions)) {
1362
+ if (!(key in result))
1363
+ continue;
1364
+ const currentValue = result[key];
1365
+ if (isPlainObject(currentValue) && isPlainObject(forcedValue)) {
1366
+ const nested = { ...currentValue };
1367
+ for (const nestedKey of Object.keys(forcedValue)) {
1368
+ delete nested[nestedKey];
1369
+ }
1370
+ if (Object.keys(nested).length === 0) {
1371
+ delete result[key];
1372
+ } else {
1373
+ result[key] = nested;
1374
+ }
1375
+ continue;
1376
+ }
1377
+ delete result[key];
1378
+ }
1379
+ return result;
1380
+ }
1261
1381
 
1262
1382
  // src/runtime/query-builder-where.ts
1263
1383
  var UNSUPPORTED_WHERE_TYPES = /* @__PURE__ */ new Set(["Bytes"]);
@@ -1374,7 +1494,7 @@ function isModeCompatibleOp(fieldType, op) {
1374
1494
  return JSON_STRING_MODE_OPS.has(op);
1375
1495
  return false;
1376
1496
  }
1377
- function createWhereBuilder(typeMap, enumMap, scalarBase) {
1497
+ function createWhereBuilder(typeMap, enumMap, scalarBase, uniqueMap = {}) {
1378
1498
  function buildWhereSchema(model, whereConfig, depth) {
1379
1499
  const currentDepth = depth ?? 0;
1380
1500
  if (currentDepth > MAX_WHERE_DEPTH) {
@@ -1431,6 +1551,18 @@ function createWhereBuilder(typeMap, enumMap, scalarBase) {
1431
1551
  scalarConditions
1432
1552
  );
1433
1553
  }
1554
+ for (const key of Object.keys(scalarConditions)) {
1555
+ if (COMBINATOR_KEYS.has(key))
1556
+ continue;
1557
+ if (!(key in fieldSchemas)) {
1558
+ fieldSchemas[key] = z4.object({}).strict().optional();
1559
+ }
1560
+ }
1561
+ for (const key of Object.keys(relationForced)) {
1562
+ if (!(key in fieldSchemas)) {
1563
+ fieldSchemas[key] = z4.object({}).strict().optional();
1564
+ }
1565
+ }
1434
1566
  const schema = Object.keys(fieldSchemas).length > 0 ? z4.object(fieldSchemas).strict().optional() : null;
1435
1567
  const forcedOnlyKeys = /* @__PURE__ */ new Set();
1436
1568
  for (const key of Object.keys(whereConfig)) {
@@ -1654,7 +1786,7 @@ function createWhereBuilder(typeMap, enumMap, scalarBase) {
1654
1786
  );
1655
1787
  }
1656
1788
  if (modeConfigValue === true) {
1657
- opSchemas["mode"] = z4.enum(["default", "insensitive"]).optional();
1789
+ opSchemas.mode = z4.enum(["default", "insensitive"]).optional();
1658
1790
  } else {
1659
1791
  const actualModeValue = isForcedValue(modeConfigValue) ? modeConfigValue.value : modeConfigValue;
1660
1792
  const modeSchema = z4.enum(["default", "insensitive"]);
@@ -1666,10 +1798,10 @@ function createWhereBuilder(typeMap, enumMap, scalarBase) {
1666
1798
  `Invalid forced value for "${model}.${fieldName}.mode": ${err.message}`
1667
1799
  );
1668
1800
  }
1669
- fieldForced["mode"] = parsed;
1801
+ fieldForced.mode = parsed;
1670
1802
  }
1671
1803
  } else if (hasModeCompatibleOp) {
1672
- opSchemas["mode"] = z4.enum(["default", "insensitive"]).optional();
1804
+ opSchemas.mode = z4.enum(["default", "insensitive"]).optional();
1673
1805
  }
1674
1806
  if (hasClientOps) {
1675
1807
  const opObj = z4.object(opSchemas).strict();
@@ -1697,12 +1829,60 @@ function createWhereBuilder(typeMap, enumMap, scalarBase) {
1697
1829
  scalarConditions[fieldName] = fieldForced;
1698
1830
  }
1699
1831
  }
1832
+ function getUniqueConstraint(model, selector) {
1833
+ return (uniqueMap[model] ?? []).find(
1834
+ (constraint) => constraint.selector === selector
1835
+ ) ?? null;
1836
+ }
1837
+ function buildDirectUniqueSchema(fieldMeta) {
1838
+ const base = createBaseType(fieldMeta, enumMap, scalarBase);
1839
+ if (!fieldMeta.isEnum && !fieldMeta.isRelation && !fieldMeta.isUnsupported) {
1840
+ return wrapWithInputCoercion(fieldMeta.type, fieldMeta.isList, base);
1841
+ }
1842
+ return base;
1843
+ }
1844
+ function parseForcedUniqueValue(model, fieldName, fieldMeta, value) {
1845
+ const schema = buildDirectUniqueSchema(fieldMeta);
1846
+ const actual = isForcedValue(value) ? value.value : value;
1847
+ try {
1848
+ return schema.parse(actual);
1849
+ } catch (err) {
1850
+ throw new ShapeError(
1851
+ `Invalid forced value for unique where "${model}.${fieldName}": ${err.message}`
1852
+ );
1853
+ }
1854
+ }
1855
+ function assertCompoundSelectorConfig(model, selector, constraint, value) {
1856
+ const actual = isForcedValue(value) ? value.value : value;
1857
+ if (!isPlainObject(actual)) {
1858
+ throw new ShapeError(
1859
+ `Compound unique selector "${model}.${selector}" must be an object with fields: ${constraint.fields.join(", ")}`
1860
+ );
1861
+ }
1862
+ const allowed = new Set(constraint.fields);
1863
+ const keys = Object.keys(actual);
1864
+ for (const key of keys) {
1865
+ if (!allowed.has(key)) {
1866
+ throw new ShapeError(
1867
+ `Unknown field "${key}" in compound unique selector "${model}.${selector}". Allowed fields: ${constraint.fields.join(", ")}`
1868
+ );
1869
+ }
1870
+ }
1871
+ for (const field of constraint.fields) {
1872
+ if (!(field in actual)) {
1873
+ throw new ShapeError(
1874
+ `Missing field "${field}" in compound unique selector "${model}.${selector}"`
1875
+ );
1876
+ }
1877
+ }
1878
+ return actual;
1879
+ }
1700
1880
  function buildUniqueWhereSchema(model, whereConfig) {
1701
1881
  const modelFields = typeMap[model];
1702
1882
  if (!modelFields)
1703
1883
  throw new ShapeError(`Unknown model: ${model}`);
1704
1884
  const fieldSchemas = {};
1705
- const forced = {};
1885
+ const forcedConditions = {};
1706
1886
  const forcedOnlyKeys = /* @__PURE__ */ new Set();
1707
1887
  for (const [key, value] of Object.entries(whereConfig)) {
1708
1888
  if (COMBINATOR_KEYS.has(key)) {
@@ -1710,65 +1890,102 @@ function createWhereBuilder(typeMap, enumMap, scalarBase) {
1710
1890
  `Combinator "${key}" is not supported in unique where for model "${model}"`
1711
1891
  );
1712
1892
  }
1893
+ const constraint = getUniqueConstraint(model, key);
1894
+ if (constraint && constraint.fields.length > 1) {
1895
+ const compoundConfig = assertCompoundSelectorConfig(
1896
+ model,
1897
+ key,
1898
+ constraint,
1899
+ value
1900
+ );
1901
+ const nestedSchemas = {};
1902
+ const forcedCompound = {};
1903
+ for (const fieldName of constraint.fields) {
1904
+ const fieldMeta2 = modelFields[fieldName];
1905
+ if (!fieldMeta2) {
1906
+ throw new ShapeError(
1907
+ `Unknown field "${fieldName}" in compound unique selector "${model}.${key}"`
1908
+ );
1909
+ }
1910
+ if (fieldMeta2.isRelation) {
1911
+ throw new ShapeError(
1912
+ `Relation field "${fieldName}" cannot be used in compound unique selector "${model}.${key}"`
1913
+ );
1914
+ }
1915
+ const fieldValue = compoundConfig[fieldName];
1916
+ const forced2 = isForcedValue(fieldValue);
1917
+ if (!forced2 && isPlainObject(fieldValue)) {
1918
+ const operators = Object.keys(fieldValue);
1919
+ throw new ShapeError(
1920
+ `Invalid compound unique where shape for "${model}.${key}.${fieldName}". Prisma compound unique selectors do not accept filter operator objects${operators.length ? `: ${operators.join(", ")}` : ""}. Use direct values only.`
1921
+ );
1922
+ }
1923
+ const directSchema2 = buildDirectUniqueSchema(fieldMeta2);
1924
+ if (fieldValue === true) {
1925
+ nestedSchemas[fieldName] = directSchema2;
1926
+ } else {
1927
+ forcedCompound[fieldName] = parseForcedUniqueValue(
1928
+ model,
1929
+ fieldName,
1930
+ fieldMeta2,
1931
+ fieldValue
1932
+ );
1933
+ }
1934
+ }
1935
+ if (Object.keys(nestedSchemas).length > 0) {
1936
+ fieldSchemas[key] = z4.object(nestedSchemas).strict();
1937
+ }
1938
+ if (Object.keys(forcedCompound).length > 0) {
1939
+ forcedConditions[key] = forcedCompound;
1940
+ }
1941
+ if (Object.keys(nestedSchemas).length === 0) {
1942
+ forcedOnlyKeys.add(key);
1943
+ }
1944
+ continue;
1945
+ }
1713
1946
  const fieldMeta = modelFields[key];
1714
- if (!fieldMeta)
1715
- throw new ShapeError(`Unknown field "${key}" on model "${model}"`);
1716
- if (fieldMeta.isRelation)
1947
+ if (!fieldMeta) {
1948
+ const selectors = (uniqueMap[model] ?? []).map((constraint2) => constraint2.selector).join(", ");
1717
1949
  throw new ShapeError(
1718
- `Relation field "${key}" cannot be used in unique where for model "${model}"`
1950
+ `Unknown unique field or selector "${key}" on model "${model}"${selectors ? `. Unique selectors: ${selectors}` : ""}`
1719
1951
  );
1720
- const base = createBaseType(fieldMeta, enumMap, scalarBase);
1721
- let directSchema;
1722
- if (!fieldMeta.isEnum && !fieldMeta.isRelation && !fieldMeta.isUnsupported) {
1723
- directSchema = wrapWithInputCoercion(
1724
- fieldMeta.type,
1725
- fieldMeta.isList,
1726
- base
1727
- );
1728
- } else {
1729
- directSchema = base;
1730
1952
  }
1731
- const equalsWrapper = z4.object({ equals: directSchema }).strict().transform((v) => v.equals);
1732
- if (value === true) {
1733
- fieldSchemas[key] = z4.union([directSchema, equalsWrapper]);
1734
- continue;
1953
+ if (fieldMeta.isRelation) {
1954
+ throw new ShapeError(
1955
+ `Relation field "${key}" cannot be used in unique where for model "${model}"`
1956
+ );
1735
1957
  }
1736
- if (isPlainObject(value)) {
1958
+ const forced = isForcedValue(value);
1959
+ if (!forced && isPlainObject(value)) {
1737
1960
  const keys = Object.keys(value);
1738
- if (keys.length === 1 && keys[0] === "equals") {
1739
- const equalsVal = value.equals;
1740
- if (equalsVal === true) {
1741
- fieldSchemas[key] = z4.union([directSchema, equalsWrapper]);
1742
- } else {
1743
- const actual2 = isForcedValue(equalsVal) ? equalsVal.value : equalsVal;
1744
- try {
1745
- forced[key] = directSchema.parse(actual2);
1746
- } catch (err) {
1747
- throw new ShapeError(
1748
- `Invalid forced value for unique where "${model}.${key}": ${err.message}`
1749
- );
1750
- }
1751
- forcedOnlyKeys.add(key);
1752
- }
1753
- continue;
1961
+ if (keys.includes("equals")) {
1962
+ throw new ShapeError(
1963
+ `Invalid unique where shape for "${model}.${key}". Prisma WhereUniqueInput does not accept filter operator objects. Use { ${key}: true } instead of { ${key}: { equals: true } }.`
1964
+ );
1754
1965
  }
1755
1966
  throw new ShapeError(
1756
- `Unique where field "${key}" on model "${model}" only accepts true or { equals: true/value }. Got operators: ${keys.join(", ")}`
1967
+ `Invalid unique where shape for "${model}.${key}". Prisma WhereUniqueInput does not accept operators: ${keys.join(", ")}. Use a direct unique value shape, for example { ${key}: true }.`
1757
1968
  );
1758
1969
  }
1759
- const actual = isForcedValue(value) ? value.value : value;
1760
- try {
1761
- forced[key] = directSchema.parse(actual);
1762
- } catch (err) {
1763
- throw new ShapeError(
1764
- `Invalid forced value for unique where "${model}.${key}": ${err.message}`
1765
- );
1970
+ const directSchema = buildDirectUniqueSchema(fieldMeta);
1971
+ if (value === true) {
1972
+ fieldSchemas[key] = directSchema;
1973
+ continue;
1766
1974
  }
1975
+ forcedConditions[key] = parseForcedUniqueValue(
1976
+ model,
1977
+ key,
1978
+ fieldMeta,
1979
+ value
1980
+ );
1767
1981
  forcedOnlyKeys.add(key);
1768
1982
  }
1769
1983
  return {
1770
1984
  schema: Object.keys(fieldSchemas).length > 0 ? z4.object(fieldSchemas).strict() : null,
1771
- forced,
1985
+ forced: {
1986
+ conditions: forcedConditions,
1987
+ relations: {}
1988
+ },
1772
1989
  forcedOnlyKeys
1773
1990
  };
1774
1991
  }
@@ -1787,6 +2004,15 @@ function requireConfigTrue(config, context) {
1787
2004
  }
1788
2005
  }
1789
2006
  }
2007
+ function isPlainRecord(value) {
2008
+ return value !== null && typeof value === "object" && !Array.isArray(value);
2009
+ }
2010
+ function formatUniqueConstraint2(constraint) {
2011
+ return constraint.fields.length === 1 ? constraint.selector : `${constraint.selector}(${constraint.fields.join(", ")})`;
2012
+ }
2013
+ function formatUniqueConstraints2(constraints) {
2014
+ return constraints.map(formatUniqueConstraint2).join(" | ");
2015
+ }
1790
2016
  function createArgsBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
1791
2017
  const sortEnum = z5.enum(["asc", "desc"]);
1792
2018
  const nullsEnum = z5.enum(["first", "last"]);
@@ -1797,11 +2023,17 @@ function createArgsBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
1797
2023
  if (!fieldMeta)
1798
2024
  throw new ShapeError(`Unknown field "${fieldName}" on model "${model}"`);
1799
2025
  if (fieldMeta.isRelation)
1800
- throw new ShapeError(`Relation field "${fieldName}" in orderBy requires a nested config object, not true`);
2026
+ throw new ShapeError(
2027
+ `Relation field "${fieldName}" in orderBy requires a nested config object, not true`
2028
+ );
1801
2029
  if (fieldMeta.type === "Json")
1802
- throw new ShapeError(`Json field "${fieldName}" cannot be used in orderBy`);
2030
+ throw new ShapeError(
2031
+ `Json field "${fieldName}" cannot be used in orderBy`
2032
+ );
1803
2033
  if (fieldMeta.isList)
1804
- throw new ShapeError(`List field "${fieldName}" cannot be used in orderBy`);
2034
+ throw new ShapeError(
2035
+ `List field "${fieldName}" cannot be used in orderBy`
2036
+ );
1805
2037
  }
1806
2038
  function buildOrderBySchema(model, orderByConfig) {
1807
2039
  const modelFields = typeMap[model];
@@ -1811,158 +2043,274 @@ function createArgsBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
1811
2043
  for (const [fieldName, config] of Object.entries(orderByConfig)) {
1812
2044
  const fieldMeta = modelFields[fieldName];
1813
2045
  if (!fieldMeta)
1814
- throw new ShapeError(`Unknown field "${fieldName}" on model "${model}"`);
2046
+ throw new ShapeError(
2047
+ `Unknown field "${fieldName}" on model "${model}"`
2048
+ );
1815
2049
  if (config === true) {
1816
2050
  validateScalarOrderByField(fieldName, model, modelFields);
1817
2051
  fieldSchemas[fieldName] = scalarOrderSchema.optional();
1818
2052
  continue;
1819
2053
  }
1820
- if (typeof config !== "object" || config === null) {
1821
- throw new ShapeError(`Invalid orderBy config for "${fieldName}" on model "${model}": expected true or a nested config object`);
2054
+ if (!isPlainRecord(config)) {
2055
+ throw new ShapeError(
2056
+ `orderBy config for "${fieldName}" on model "${model}" must be true or a relation aggregate object`
2057
+ );
1822
2058
  }
1823
2059
  if (!fieldMeta.isRelation) {
1824
- throw new ShapeError(`Scalar field "${fieldName}" in orderBy does not accept nested config`);
1825
- }
1826
- if (Object.keys(config).length === 0) {
1827
- throw new ShapeError(`Empty orderBy config for relation "${fieldName}" on model "${model}". Define at least one nested field.`);
2060
+ const allowedOps = getSupportedOperators(
2061
+ fieldMeta.type,
2062
+ fieldMeta.isList
2063
+ );
2064
+ const opSchemas = {};
2065
+ for (const [op, enabled] of Object.entries(config)) {
2066
+ if (enabled !== true) {
2067
+ throw new ShapeError(
2068
+ `orderBy operator config for "${model}.${fieldName}.${op}" must be true`
2069
+ );
2070
+ }
2071
+ if (!allowedOps.includes(op)) {
2072
+ throw new ShapeError(
2073
+ `Operator "${op}" not supported for orderBy field "${model}.${fieldName}"`
2074
+ );
2075
+ }
2076
+ opSchemas[op] = scalarOrderSchema.optional();
2077
+ }
2078
+ const opKeys = Object.keys(opSchemas);
2079
+ fieldSchemas[fieldName] = z5.object(opSchemas).strict().refine(
2080
+ (v) => opKeys.some(
2081
+ (k) => v[k] !== void 0
2082
+ ),
2083
+ {
2084
+ message: `orderBy field "${fieldName}" must specify at least one operator`
2085
+ }
2086
+ ).optional();
2087
+ continue;
1828
2088
  }
1829
2089
  if (fieldMeta.isList) {
1830
- const relKeys = Object.keys(config);
1831
- if (relKeys.length !== 1 || relKeys[0] !== "_count") {
1832
- throw new ShapeError(`To-many relation "${fieldName}" in orderBy only supports { _count: true }`);
2090
+ if (!("_count" in config)) {
2091
+ throw new ShapeError(
2092
+ `To-many relation orderBy "${fieldName}" only supports _count`
2093
+ );
1833
2094
  }
1834
2095
  if (config._count !== true) {
1835
- throw new ShapeError(`_count in orderBy for "${fieldName}" must be true`);
2096
+ throw new ShapeError(
2097
+ `orderBy relation aggregate "${fieldName}._count" must be true`
2098
+ );
1836
2099
  }
1837
- fieldSchemas[fieldName] = z5.object({ _count: sortEnum }).strict().optional();
2100
+ fieldSchemas[fieldName] = z5.object({
2101
+ _count: sortEnum.optional()
2102
+ }).strict().optional();
1838
2103
  continue;
1839
2104
  }
1840
- const relatedModel = fieldMeta.type;
1841
- const relatedFields = typeMap[relatedModel];
1842
- if (!relatedFields)
1843
- throw new ShapeError(`Related model "${relatedModel}" not found in type map`);
1844
- const nestedSchemas = {};
1845
- for (const [nestedField, nestedVal] of Object.entries(config)) {
1846
- if (nestedVal !== true) {
1847
- throw new ShapeError(`Nested orderBy field "${nestedField}" on relation "${fieldName}" must be true`);
1848
- }
1849
- const nestedMeta = relatedFields[nestedField];
1850
- if (!nestedMeta)
1851
- throw new ShapeError(`Unknown field "${nestedField}" on model "${relatedModel}" in orderBy`);
1852
- if (nestedMeta.isRelation)
1853
- throw new ShapeError(`Nested relation "${nestedField}" in orderBy on "${fieldName}" is not supported`);
1854
- if (nestedMeta.type === "Json")
1855
- throw new ShapeError(`Json field "${nestedField}" cannot be used in orderBy`);
1856
- if (nestedMeta.isList)
1857
- throw new ShapeError(`List field "${nestedField}" cannot be used in orderBy`);
1858
- nestedSchemas[nestedField] = scalarOrderSchema.optional();
1859
- }
1860
- const nestedKeys = Object.keys(nestedSchemas);
1861
- fieldSchemas[fieldName] = z5.object(nestedSchemas).strict().refine(
1862
- (v) => nestedKeys.some((k) => v[k] !== void 0),
1863
- { message: `orderBy for relation "${fieldName}" must specify at least one field` }
1864
- ).optional();
2105
+ const nested = buildOrderBySchema(
2106
+ fieldMeta.type,
2107
+ config
2108
+ );
2109
+ fieldSchemas[fieldName] = nested;
1865
2110
  }
1866
2111
  const fieldKeys = Object.keys(fieldSchemas);
1867
2112
  const singleSchema = z5.object(fieldSchemas).strict().refine(
1868
- (v) => fieldKeys.some((k) => v[k] !== void 0),
2113
+ (v) => fieldKeys.some(
2114
+ (k) => v[k] !== void 0
2115
+ ),
1869
2116
  { message: "orderBy must specify at least one field" }
1870
2117
  );
1871
- return z5.union([singleSchema, z5.preprocess(coerceToArray, z5.array(singleSchema).min(1))]).optional();
2118
+ return z5.union([
2119
+ singleSchema,
2120
+ z5.preprocess(coerceToArray, z5.array(singleSchema).min(1))
2121
+ ]).optional();
1872
2122
  }
1873
2123
  function buildTakeSchema(config) {
1874
- const normalized = typeof config === "number" ? { max: config, default: config } : config;
1875
- if (!Number.isFinite(normalized.max) || !Number.isInteger(normalized.max)) {
1876
- throw new ShapeError(`take max must be a finite integer, got ${normalized.max}`);
2124
+ if (typeof config === "number") {
2125
+ if (!Number.isFinite(config) || !Number.isInteger(config)) {
2126
+ throw new ShapeError(`take must be a finite integer, got ${config}`);
2127
+ }
2128
+ if (config <= 0) {
2129
+ throw new ShapeError("take must be a positive integer");
2130
+ }
2131
+ return z5.literal(config).optional();
2132
+ }
2133
+ if (!config || typeof config !== "object" || Array.isArray(config)) {
2134
+ throw new ShapeError("take config must be a number or { max, default? }");
2135
+ }
2136
+ if (!Number.isFinite(config.max) || !Number.isInteger(config.max)) {
2137
+ throw new ShapeError(
2138
+ `take.max must be a finite integer, got ${config.max}`
2139
+ );
1877
2140
  }
1878
- if (normalized.max < 1) {
1879
- throw new ShapeError(`take max must be at least 1, got ${normalized.max}`);
2141
+ if (config.max <= 0) {
2142
+ throw new ShapeError("take.max must be a positive integer");
1880
2143
  }
1881
- if (normalized.default !== void 0) {
1882
- if (!Number.isFinite(normalized.default) || !Number.isInteger(normalized.default)) {
1883
- throw new ShapeError(`take default must be a finite integer, got ${normalized.default}`);
2144
+ if (config.default !== void 0) {
2145
+ if (!Number.isFinite(config.default) || !Number.isInteger(config.default)) {
2146
+ throw new ShapeError(
2147
+ `take.default must be a finite integer, got ${config.default}`
2148
+ );
1884
2149
  }
1885
- if (normalized.default < 1) {
1886
- throw new ShapeError(`take default must be at least 1, got ${normalized.default}`);
2150
+ if (config.default <= 0) {
2151
+ throw new ShapeError("take.default must be a positive integer");
1887
2152
  }
1888
- if (normalized.default > normalized.max) {
1889
- throw new ShapeError("take default cannot exceed max");
2153
+ if (config.default > config.max) {
2154
+ throw new ShapeError("take.default cannot exceed take.max");
1890
2155
  }
1891
- return z5.number().int().min(1).max(normalized.max).default(normalized.default);
2156
+ return z5.number().int().min(1).max(config.max).default(config.default);
1892
2157
  }
1893
- return z5.number().int().min(1).max(normalized.max).optional();
2158
+ return z5.number().int().min(1).max(config.max).optional();
1894
2159
  }
1895
- function buildCursorSchema(model, cursorConfig) {
2160
+ function buildCursorFieldSchema(model, fieldName) {
1896
2161
  const modelFields = typeMap[model];
1897
2162
  if (!modelFields)
1898
2163
  throw new ShapeError(`Unknown model: ${model}`);
1899
- requireConfigTrue(cursorConfig, `cursor on model "${model}"`);
1900
- const cursorFields = new Set(Object.keys(cursorConfig));
2164
+ const fieldMeta = modelFields[fieldName];
2165
+ if (!fieldMeta) {
2166
+ throw new ShapeError(
2167
+ `Unknown field "${fieldName}" on model "${model}" in cursor`
2168
+ );
2169
+ }
2170
+ if (fieldMeta.isRelation) {
2171
+ throw new ShapeError(
2172
+ `Relation field "${fieldName}" cannot be used in cursor`
2173
+ );
2174
+ }
2175
+ if (fieldMeta.isList) {
2176
+ throw new ShapeError(
2177
+ `List field "${fieldName}" cannot be used in cursor`
2178
+ );
2179
+ }
2180
+ const base = createBaseType(fieldMeta, enumMap, scalarBase);
2181
+ if (!fieldMeta.isEnum && !fieldMeta.isRelation && !fieldMeta.isUnsupported) {
2182
+ return wrapWithInputCoercion(fieldMeta.type, fieldMeta.isList, base);
2183
+ }
2184
+ return base;
2185
+ }
2186
+ function cursorConfigMatchesConstraint(cursorConfig, constraint) {
2187
+ if (!(constraint.selector in cursorConfig))
2188
+ return false;
2189
+ const value = cursorConfig[constraint.selector];
2190
+ if (constraint.fields.length === 1) {
2191
+ return value === true;
2192
+ }
2193
+ if (!isPlainRecord(value))
2194
+ return false;
2195
+ const keys = Object.keys(value);
2196
+ if (keys.length !== constraint.fields.length)
2197
+ return false;
2198
+ return constraint.fields.every((field) => value[field] === true);
2199
+ }
2200
+ function getUniqueConstraints(model) {
1901
2201
  const constraints = uniqueMap[model];
1902
2202
  if (constraints && constraints.length > 0) {
1903
- const covered = constraints.some(
1904
- (constraint) => constraint.length === cursorFields.size && constraint.every((field) => cursorFields.has(field))
1905
- );
1906
- if (!covered) {
1907
- const constraintDesc = constraints.map((c) => `(${c.join(", ")})`).join(" | ");
1908
- throw new ShapeError(
1909
- `cursor on model "${model}" must exactly match a unique constraint: ${constraintDesc}`
1910
- );
2203
+ return constraints;
2204
+ }
2205
+ const modelFields = typeMap[model];
2206
+ if (!modelFields) {
2207
+ throw new ShapeError(`Unknown model: ${model}`);
2208
+ }
2209
+ const inferred = [];
2210
+ for (const [fieldName, fieldMeta] of Object.entries(modelFields)) {
2211
+ if (fieldMeta.isRelation)
2212
+ continue;
2213
+ if (fieldMeta.isId || fieldMeta.isUnique) {
2214
+ inferred.push({
2215
+ selector: fieldName,
2216
+ fields: [fieldName]
2217
+ });
1911
2218
  }
1912
2219
  }
2220
+ return inferred;
2221
+ }
2222
+ function buildCursorSchema(model, cursorConfig) {
2223
+ const constraints = getUniqueConstraints(model);
2224
+ if (constraints.length === 0) {
2225
+ throw new ShapeError(
2226
+ `cursor on model "${model}" requires at least one unique constraint`
2227
+ );
2228
+ }
2229
+ const matching = constraints.find(
2230
+ (constraint) => cursorConfigMatchesConstraint(cursorConfig, constraint)
2231
+ );
2232
+ if (!matching) {
2233
+ throw new ShapeError(
2234
+ `cursor on model "${model}" must exactly match a unique selector: ${formatUniqueConstraints2(constraints)}`
2235
+ );
2236
+ }
1913
2237
  const fieldSchemas = {};
1914
- for (const fieldName of Object.keys(cursorConfig)) {
1915
- const fieldMeta = modelFields[fieldName];
1916
- if (!fieldMeta)
1917
- throw new ShapeError(`Unknown field "${fieldName}" on model "${model}" in cursor`);
1918
- if (fieldMeta.isRelation)
1919
- throw new ShapeError(`Relation field "${fieldName}" cannot be used in cursor`);
1920
- if (fieldMeta.isList)
1921
- throw new ShapeError(`List field "${fieldName}" cannot be used in cursor`);
1922
- fieldSchemas[fieldName] = createBaseType(fieldMeta, enumMap, scalarBase);
2238
+ if (matching.fields.length === 1) {
2239
+ fieldSchemas[matching.selector] = buildCursorFieldSchema(
2240
+ model,
2241
+ matching.fields[0]
2242
+ ).optional();
2243
+ } else {
2244
+ const nestedSchemas = {};
2245
+ for (const field of matching.fields) {
2246
+ nestedSchemas[field] = buildCursorFieldSchema(model, field);
2247
+ }
2248
+ fieldSchemas[matching.selector] = z5.object(nestedSchemas).strict().optional();
1923
2249
  }
1924
- return z5.object(fieldSchemas).strict().optional();
2250
+ return z5.object(fieldSchemas).strict().refine(
2251
+ (v) => v[matching.selector] !== void 0,
2252
+ { message: `cursor must specify "${matching.selector}"` }
2253
+ ).optional();
1925
2254
  }
1926
2255
  function buildDistinctSchema(model, distinctConfig) {
1927
- if (distinctConfig.length === 0) {
1928
- throw new ShapeError("distinct must contain at least one field");
1929
- }
1930
2256
  const modelFields = typeMap[model];
1931
2257
  if (!modelFields)
1932
2258
  throw new ShapeError(`Unknown model: ${model}`);
2259
+ if (!Array.isArray(distinctConfig) || distinctConfig.length === 0) {
2260
+ throw new ShapeError(
2261
+ `distinct on model "${model}" must be a non-empty array of scalar fields`
2262
+ );
2263
+ }
2264
+ const allowedFields = /* @__PURE__ */ new Set();
1933
2265
  for (const fieldName of distinctConfig) {
1934
2266
  const fieldMeta = modelFields[fieldName];
1935
2267
  if (!fieldMeta)
1936
- throw new ShapeError(`Unknown field "${fieldName}" on model "${model}" in distinct`);
2268
+ throw new ShapeError(
2269
+ `Unknown field "${fieldName}" on model "${model}" in distinct`
2270
+ );
1937
2271
  if (fieldMeta.isRelation)
1938
- throw new ShapeError(`Relation field "${fieldName}" cannot be used in distinct`);
1939
- if (fieldMeta.isList)
1940
- throw new ShapeError(`List field "${fieldName}" cannot be used in distinct`);
2272
+ throw new ShapeError(
2273
+ `Relation field "${fieldName}" cannot be used in distinct`
2274
+ );
2275
+ allowedFields.add(fieldName);
1941
2276
  }
1942
- const enumSchema = z5.enum(distinctConfig);
1943
- return z5.union([enumSchema, z5.preprocess(coerceToArray, z5.array(enumSchema).min(1))]).optional();
2277
+ return z5.union([
2278
+ z5.enum([...allowedFields]),
2279
+ z5.array(z5.enum([...allowedFields])).min(1)
2280
+ ]).optional();
1944
2281
  }
1945
2282
  function buildBySchema(model, byConfig) {
1946
- if (byConfig.length === 0) {
1947
- throw new ShapeError('groupBy "by" must contain at least one field');
1948
- }
1949
2283
  const modelFields = typeMap[model];
1950
2284
  if (!modelFields)
1951
2285
  throw new ShapeError(`Unknown model: ${model}`);
2286
+ if (!Array.isArray(byConfig) || byConfig.length === 0) {
2287
+ throw new ShapeError(
2288
+ `groupBy "by" on model "${model}" must be a non-empty array`
2289
+ );
2290
+ }
2291
+ const allowedFields = /* @__PURE__ */ new Set();
1952
2292
  for (const fieldName of byConfig) {
1953
2293
  const fieldMeta = modelFields[fieldName];
1954
2294
  if (!fieldMeta)
1955
- throw new ShapeError(`Unknown field "${fieldName}" on model "${model}" in by`);
2295
+ throw new ShapeError(
2296
+ `Unknown field "${fieldName}" on model "${model}" in groupBy by`
2297
+ );
1956
2298
  if (fieldMeta.isRelation)
1957
- throw new ShapeError(`Relation field "${fieldName}" cannot be used in by`);
2299
+ throw new ShapeError(
2300
+ `Relation field "${fieldName}" cannot be used in groupBy by`
2301
+ );
2302
+ if (fieldMeta.isList)
2303
+ throw new ShapeError(
2304
+ `List field "${fieldName}" cannot be used in groupBy by`
2305
+ );
1958
2306
  if (UNSUPPORTED_BY_TYPES.has(fieldMeta.type)) {
1959
- throw new ShapeError(`${fieldMeta.type} field "${fieldName}" cannot be used in by`);
2307
+ throw new ShapeError(
2308
+ `${fieldMeta.type} field "${fieldName}" cannot be used in groupBy by`
2309
+ );
1960
2310
  }
1961
- if (fieldMeta.isList)
1962
- throw new ShapeError(`List field "${fieldName}" cannot be used in by`);
2311
+ allowedFields.add(fieldName);
1963
2312
  }
1964
- const enumSchema = z5.enum(byConfig);
1965
- return z5.union([enumSchema, z5.preprocess(coerceToArray, z5.array(enumSchema).min(1))]);
2313
+ return z5.array(z5.enum([...allowedFields])).min(1);
1966
2314
  }
1967
2315
  function buildHavingSchema(model, havingConfig) {
1968
2316
  const modelFields = typeMap[model];
@@ -1973,82 +2321,88 @@ function createArgsBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
1973
2321
  for (const fieldName of Object.keys(havingConfig)) {
1974
2322
  const fieldMeta = modelFields[fieldName];
1975
2323
  if (!fieldMeta)
1976
- throw new ShapeError(`Unknown field "${fieldName}" on model "${model}" in having`);
2324
+ throw new ShapeError(
2325
+ `Unknown field "${fieldName}" on model "${model}" in having`
2326
+ );
1977
2327
  if (fieldMeta.isRelation)
1978
- throw new ShapeError(`Relation field "${fieldName}" cannot be used in having`);
2328
+ throw new ShapeError(
2329
+ `Relation field "${fieldName}" cannot be used in having`
2330
+ );
1979
2331
  if (fieldMeta.isList)
1980
- throw new ShapeError(`List field "${fieldName}" cannot be used in having`);
1981
- const ops = getSupportedOperators(fieldMeta);
1982
- if (ops.length === 0) {
1983
- throw new ShapeError(`${fieldMeta.type} field "${fieldName}" cannot be used in having filters`);
2332
+ throw new ShapeError(
2333
+ `List field "${fieldName}" cannot be used in having`
2334
+ );
2335
+ if (UNSUPPORTED_BY_TYPES.has(fieldMeta.type)) {
2336
+ throw new ShapeError(
2337
+ `${fieldMeta.type} field "${fieldName}" cannot be used in having`
2338
+ );
1984
2339
  }
2340
+ const allowedOps = getSupportedOperators(
2341
+ fieldMeta.type,
2342
+ fieldMeta.isList
2343
+ );
1985
2344
  const opSchemas = {};
1986
- const opKeys = [];
1987
- for (const op of ops) {
1988
- opSchemas[op] = createOperatorSchema(fieldMeta, op, enumMap, scalarBase).optional();
1989
- opKeys.push(op);
2345
+ for (const op of allowedOps) {
2346
+ opSchemas[op] = createOperatorSchema(
2347
+ fieldMeta,
2348
+ op,
2349
+ enumMap,
2350
+ scalarBase
2351
+ ).optional();
1990
2352
  }
1991
- if (fieldMeta.type === "String" && !fieldMeta.isList) {
1992
- opSchemas["mode"] = z5.enum(["default", "insensitive"]).optional();
2353
+ if (fieldMeta.type === "String") {
2354
+ opSchemas.mode = z5.enum(["default", "insensitive"]).optional();
1993
2355
  }
2356
+ const opKeys = Object.keys(opSchemas).filter((key) => key !== "mode");
1994
2357
  fieldSchemas[fieldName] = z5.object(opSchemas).strict().refine(
1995
2358
  (v) => opKeys.some((k) => v[k] !== void 0),
1996
- { message: `At least one operator required for having field "${fieldName}"` }
2359
+ {
2360
+ message: `having field "${fieldName}" must specify at least one operator`
2361
+ }
1997
2362
  ).optional();
1998
2363
  }
1999
- const havingFieldKeys = Object.keys(fieldSchemas);
2000
- const havingSchema = z5.lazy(() => {
2001
- const allSchemas = { ...fieldSchemas };
2002
- allSchemas["AND"] = z5.preprocess(coerceToArray, z5.array(havingSchema).min(1)).optional();
2003
- allSchemas["OR"] = z5.preprocess(coerceToArray, z5.array(havingSchema).min(1)).optional();
2004
- allSchemas["NOT"] = z5.union([
2005
- havingSchema,
2006
- z5.preprocess(coerceToArray, z5.array(havingSchema).min(1))
2007
- ]).optional();
2008
- const allKeys = [...havingFieldKeys, "AND", "OR", "NOT"];
2009
- return z5.object(allSchemas).strict().refine(
2010
- (v) => allKeys.some((k) => v[k] !== void 0),
2011
- { message: "having must specify at least one field or combinator" }
2012
- );
2013
- });
2014
- return havingSchema.optional();
2364
+ const fieldKeys = Object.keys(fieldSchemas);
2365
+ return z5.object(fieldSchemas).strict().refine(
2366
+ (v) => fieldKeys.some(
2367
+ (k) => v[k] !== void 0
2368
+ ),
2369
+ { message: "having must specify at least one field" }
2370
+ ).optional();
2015
2371
  }
2016
- function buildAggregateFieldSchema(model, opName, fieldConfig) {
2372
+ function buildAggregateFieldSchema(model, op, config) {
2017
2373
  const modelFields = typeMap[model];
2018
2374
  if (!modelFields)
2019
2375
  throw new ShapeError(`Unknown model: ${model}`);
2020
- requireConfigTrue(fieldConfig, `${opName} on model "${model}"`);
2021
- const isNumericOnly = opName === "_avg" || opName === "_sum";
2022
- const isComparableOnly = opName === "_min" || opName === "_max";
2376
+ requireConfigTrue(config, `${op} on model "${model}"`);
2377
+ const allowedTypes = op === "_avg" || op === "_sum" ? NUMERIC_TYPES : COMPARABLE_TYPES;
2023
2378
  const fieldSchemas = {};
2024
- for (const fieldName of Object.keys(fieldConfig)) {
2025
- if (fieldName === "_all" && opName === "_count") {
2026
- fieldSchemas[fieldName] = z5.literal(true).optional();
2027
- continue;
2028
- }
2379
+ for (const fieldName of Object.keys(config)) {
2029
2380
  const fieldMeta = modelFields[fieldName];
2030
2381
  if (!fieldMeta)
2031
- throw new ShapeError(`Unknown field "${fieldName}" on model "${model}" in ${opName}`);
2382
+ throw new ShapeError(
2383
+ `Unknown field "${fieldName}" on model "${model}" in ${op}`
2384
+ );
2032
2385
  if (fieldMeta.isRelation)
2033
- throw new ShapeError(`Relation field "${fieldName}" cannot be used in ${opName}`);
2386
+ throw new ShapeError(
2387
+ `Relation field "${fieldName}" cannot be used in ${op}`
2388
+ );
2034
2389
  if (fieldMeta.isList)
2035
- throw new ShapeError(`List field "${fieldName}" cannot be used in ${opName}`);
2036
- if (isNumericOnly && !NUMERIC_TYPES.has(fieldMeta.type)) {
2037
2390
  throw new ShapeError(
2038
- `Field "${fieldName}" (${fieldMeta.type}) cannot be used in ${opName}. Only numeric types (Int, Float, Decimal, BigInt) are supported.`
2391
+ `List field "${fieldName}" cannot be used in ${op}`
2039
2392
  );
2040
- }
2041
- if (isComparableOnly && !COMPARABLE_TYPES.has(fieldMeta.type)) {
2393
+ if (!allowedTypes.has(fieldMeta.type)) {
2042
2394
  throw new ShapeError(
2043
- `Field "${fieldName}" (${fieldMeta.type}) cannot be used in ${opName}. Only comparable types (Int, Float, Decimal, BigInt, String, DateTime) are supported.`
2395
+ `Field "${fieldName}" of type "${fieldMeta.type}" cannot be used in ${op}`
2044
2396
  );
2045
2397
  }
2046
2398
  fieldSchemas[fieldName] = z5.literal(true).optional();
2047
2399
  }
2048
- const aggFieldKeys = Object.keys(fieldSchemas);
2400
+ const aggregateFieldKeys = Object.keys(fieldSchemas);
2049
2401
  return z5.object(fieldSchemas).strict().refine(
2050
- (v) => aggFieldKeys.some((k) => v[k] !== void 0),
2051
- { message: `${opName} must specify at least one field` }
2402
+ (v) => aggregateFieldKeys.some(
2403
+ (k) => v[k] !== void 0
2404
+ ),
2405
+ { message: `${op} must specify at least one field` }
2052
2406
  ).optional();
2053
2407
  }
2054
2408
  function buildCountFieldSchema(model, config, context) {
@@ -2064,15 +2418,21 @@ function createArgsBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
2064
2418
  if (fieldName !== "_all") {
2065
2419
  const fieldMeta = modelFields[fieldName];
2066
2420
  if (!fieldMeta)
2067
- throw new ShapeError(`Unknown field "${fieldName}" on model "${model}" in ${context}`);
2421
+ throw new ShapeError(
2422
+ `Unknown field "${fieldName}" on model "${model}" in ${context}`
2423
+ );
2068
2424
  if (fieldMeta.isRelation)
2069
- throw new ShapeError(`Relation field "${fieldName}" cannot be used in ${context}`);
2425
+ throw new ShapeError(
2426
+ `Relation field "${fieldName}" cannot be used in ${context}`
2427
+ );
2070
2428
  }
2071
2429
  fieldSchemas[fieldName] = z5.literal(true).optional();
2072
2430
  }
2073
2431
  const countFieldKeys = Object.keys(fieldSchemas);
2074
2432
  return z5.object(fieldSchemas).strict().refine(
2075
- (v) => countFieldKeys.some((k) => v[k] !== void 0),
2433
+ (v) => countFieldKeys.some(
2434
+ (k) => v[k] !== void 0
2435
+ ),
2076
2436
  { message: `${context} must specify at least one field` }
2077
2437
  ).optional();
2078
2438
  }
@@ -2084,19 +2444,25 @@ function createArgsBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
2084
2444
  const fieldSchemas = {};
2085
2445
  for (const fieldName of Object.keys(selectConfig)) {
2086
2446
  if (fieldName === "_all") {
2087
- fieldSchemas["_all"] = z5.literal(true).optional();
2447
+ fieldSchemas._all = z5.literal(true).optional();
2088
2448
  continue;
2089
2449
  }
2090
2450
  const fieldMeta = modelFields[fieldName];
2091
2451
  if (!fieldMeta)
2092
- throw new ShapeError(`Unknown field "${fieldName}" on model "${model}" in count select`);
2452
+ throw new ShapeError(
2453
+ `Unknown field "${fieldName}" on model "${model}" in count select`
2454
+ );
2093
2455
  if (fieldMeta.isRelation)
2094
- throw new ShapeError(`Relation field "${fieldName}" cannot be used in count select`);
2456
+ throw new ShapeError(
2457
+ `Relation field "${fieldName}" cannot be used in count select`
2458
+ );
2095
2459
  fieldSchemas[fieldName] = z5.literal(true).optional();
2096
2460
  }
2097
2461
  const countSelectKeys = Object.keys(fieldSchemas);
2098
2462
  return z5.object(fieldSchemas).strict().refine(
2099
- (v) => countSelectKeys.some((k) => v[k] !== void 0),
2463
+ (v) => countSelectKeys.some(
2464
+ (k) => v[k] !== void 0
2465
+ ),
2100
2466
  { message: "count select must specify at least one field" }
2101
2467
  ).optional();
2102
2468
  }
@@ -2505,7 +2871,12 @@ var UNIQUE_WHERE_METHODS = /* @__PURE__ */ new Set([
2505
2871
  "findUniqueOrThrow"
2506
2872
  ]);
2507
2873
  function createQueryBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
2508
- const whereBuilder = createWhereBuilder(typeMap, enumMap, scalarBase);
2874
+ const whereBuilder = createWhereBuilder(
2875
+ typeMap,
2876
+ enumMap,
2877
+ scalarBase,
2878
+ uniqueMap
2879
+ );
2509
2880
  const argsBuilder = createArgsBuilder(
2510
2881
  typeMap,
2511
2882
  enumMap,
@@ -2527,24 +2898,28 @@ function createQueryBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
2527
2898
  function validateShapeArgs(method, shape) {
2528
2899
  const allowed = METHOD_ALLOWED_ARGS[method];
2529
2900
  for (const key of Object.keys(shape)) {
2530
- if (!SHAPE_CONFIG_KEYS.has(key))
2901
+ if (!SHAPE_CONFIG_KEYS.has(key)) {
2531
2902
  throw new ShapeError(`Unknown shape config key "${key}"`);
2532
- if (!allowed.has(key))
2903
+ }
2904
+ if (!allowed.has(key)) {
2533
2905
  throw new ShapeError(`Arg "${key}" not allowed for method "${method}"`);
2906
+ }
2534
2907
  }
2535
2908
  if (UNIQUE_WHERE_METHODS.has(method) && !shape.where) {
2536
2909
  throw new ShapeError(`${method} shape must define "where"`);
2537
2910
  }
2538
- if (method === "groupBy" && !shape.by)
2911
+ if (method === "groupBy" && !shape.by) {
2539
2912
  throw new ShapeError('groupBy shape must define "by"');
2913
+ }
2540
2914
  if (method === "groupBy" && (shape.include || shape.select)) {
2541
2915
  throw new ShapeError('groupBy does not support "include" or "select"');
2542
2916
  }
2543
2917
  if (method === "aggregate" && (shape.include || shape.select)) {
2544
2918
  throw new ShapeError('aggregate does not support "include" or "select"');
2545
2919
  }
2546
- if (method === "count" && shape.include)
2920
+ if (method === "count" && shape.include) {
2547
2921
  throw new ShapeError('count does not support "include"');
2922
+ }
2548
2923
  if (method === "groupBy" && shape.orderBy && shape.orderBy !== true) {
2549
2924
  const bySet = new Set(shape.by);
2550
2925
  for (const fieldName of Object.keys(shape.orderBy)) {
@@ -2599,30 +2974,28 @@ function createQueryBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
2599
2974
  let forcedIncludeCountWhere = {};
2600
2975
  let forcedSelectCountWhere = {};
2601
2976
  if (shape.where) {
2602
- const { schema, forced, forcedOnlyKeys } = whereBuilder.buildWhereSchema(
2603
- model,
2604
- shape.where
2605
- );
2606
- if (schema)
2607
- schemaFields["where"] = schema;
2608
- forcedWhere = forced;
2609
- forcedOnlyWhereKeys = forcedOnlyKeys;
2977
+ const builtWhere = UNIQUE_WHERE_METHODS.has(method) ? whereBuilder.buildUniqueWhereSchema(model, shape.where) : whereBuilder.buildWhereSchema(model, shape.where);
2978
+ if (builtWhere.schema) {
2979
+ schemaFields.where = builtWhere.schema;
2980
+ }
2981
+ forcedWhere = builtWhere.forced;
2982
+ forcedOnlyWhereKeys = builtWhere.forcedOnlyKeys;
2610
2983
  }
2611
2984
  if (shape.include) {
2612
2985
  const result = projectionBuilder.buildIncludeSchema(model, shape.include);
2613
- schemaFields["include"] = result.schema;
2986
+ schemaFields.include = result.schema;
2614
2987
  forcedIncludeTree = result.forcedTree;
2615
2988
  forcedIncludeCountWhere = result.forcedCountWhere;
2616
2989
  }
2617
2990
  if (shape.select) {
2618
2991
  if (method === "count") {
2619
- schemaFields["select"] = argsBuilder.buildCountSelectSchema(
2992
+ schemaFields.select = argsBuilder.buildCountSelectSchema(
2620
2993
  model,
2621
2994
  shape.select
2622
2995
  );
2623
2996
  } else {
2624
2997
  const result = projectionBuilder.buildSelectSchema(model, shape.select);
2625
- schemaFields["select"] = result.schema;
2998
+ schemaFields.select = result.schema;
2626
2999
  forcedSelectTree = result.forcedTree;
2627
3000
  forcedSelectCountWhere = result.forcedCountWhere;
2628
3001
  }
@@ -2636,7 +3009,7 @@ function createQueryBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
2636
3009
  for (const field of shape.by) {
2637
3010
  groupByOrderFields[field] = sortEnum.optional();
2638
3011
  }
2639
- groupByOrderFields["_count"] = sortEnum.optional();
3012
+ groupByOrderFields._count = sortEnum.optional();
2640
3013
  const fieldKeys = Object.keys(groupByOrderFields);
2641
3014
  const singleSchema = z7.object(groupByOrderFields).strict().refine(
2642
3015
  (v) => fieldKeys.some(
@@ -2644,13 +3017,16 @@ function createQueryBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
2644
3017
  ),
2645
3018
  { message: "orderBy must specify at least one field" }
2646
3019
  );
2647
- schemaFields["orderBy"] = z7.union([singleSchema, z7.preprocess(coerceToArray, z7.array(singleSchema).min(1))]).optional();
3020
+ schemaFields.orderBy = z7.union([
3021
+ singleSchema,
3022
+ z7.preprocess(coerceToArray, z7.array(singleSchema).min(1))
3023
+ ]).optional();
2648
3024
  } else {
2649
3025
  const groupByOrderFields = {};
2650
3026
  for (const [fieldName, config] of Object.entries(shape.orderBy)) {
2651
3027
  if (fieldName === "_count") {
2652
3028
  if (config === true) {
2653
- groupByOrderFields["_count"] = sortEnum.optional();
3029
+ groupByOrderFields._count = sortEnum.optional();
2654
3030
  } else if (typeof config === "object" && config !== null) {
2655
3031
  const countFields = {};
2656
3032
  for (const countField of Object.keys(config)) {
@@ -2662,7 +3038,7 @@ function createQueryBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
2662
3038
  countFields[countField] = sortEnum.optional();
2663
3039
  }
2664
3040
  const countKeys = Object.keys(countFields);
2665
- groupByOrderFields["_count"] = z7.object(countFields).strict().refine(
3041
+ groupByOrderFields._count = z7.object(countFields).strict().refine(
2666
3042
  (v) => countKeys.some(
2667
3043
  (k) => v[k] !== void 0
2668
3044
  ),
@@ -2687,70 +3063,83 @@ function createQueryBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
2687
3063
  ),
2688
3064
  { message: "orderBy must specify at least one field" }
2689
3065
  );
2690
- schemaFields["orderBy"] = z7.union([singleSchema, z7.preprocess(coerceToArray, z7.array(singleSchema).min(1))]).optional();
3066
+ schemaFields.orderBy = z7.union([
3067
+ singleSchema,
3068
+ z7.preprocess(coerceToArray, z7.array(singleSchema).min(1))
3069
+ ]).optional();
2691
3070
  }
2692
3071
  } else {
2693
- schemaFields["orderBy"] = argsBuilder.buildOrderBySchema(
3072
+ schemaFields.orderBy = argsBuilder.buildOrderBySchema(
2694
3073
  model,
2695
3074
  shape.orderBy
2696
3075
  );
2697
3076
  }
2698
3077
  }
2699
- if (shape.cursor)
2700
- schemaFields["cursor"] = argsBuilder.buildCursorSchema(
3078
+ if (shape.cursor) {
3079
+ schemaFields.cursor = argsBuilder.buildCursorSchema(
2701
3080
  model,
2702
3081
  shape.cursor
2703
3082
  );
2704
- if (shape.take)
2705
- schemaFields["take"] = argsBuilder.buildTakeSchema(shape.take);
3083
+ }
3084
+ if (shape.take) {
3085
+ schemaFields.take = argsBuilder.buildTakeSchema(shape.take);
3086
+ }
2706
3087
  if (shape.skip !== void 0) {
2707
3088
  if (shape.skip !== true) {
2708
3089
  throw new ShapeError('Shape config "skip" must be true');
2709
3090
  }
2710
- schemaFields["skip"] = z7.number().int().min(0).optional();
3091
+ schemaFields.skip = z7.number().int().min(0).optional();
2711
3092
  }
2712
- if (shape.distinct)
2713
- schemaFields["distinct"] = argsBuilder.buildDistinctSchema(
3093
+ if (shape.distinct) {
3094
+ schemaFields.distinct = argsBuilder.buildDistinctSchema(
2714
3095
  model,
2715
3096
  shape.distinct
2716
3097
  );
2717
- if (shape._count)
2718
- schemaFields["_count"] = argsBuilder.buildCountFieldSchema(
3098
+ }
3099
+ if (shape._count) {
3100
+ schemaFields._count = argsBuilder.buildCountFieldSchema(
2719
3101
  model,
2720
3102
  shape._count,
2721
3103
  "_count"
2722
3104
  );
2723
- if (shape._avg)
2724
- schemaFields["_avg"] = argsBuilder.buildAggregateFieldSchema(
3105
+ }
3106
+ if (shape._avg) {
3107
+ schemaFields._avg = argsBuilder.buildAggregateFieldSchema(
2725
3108
  model,
2726
3109
  "_avg",
2727
3110
  shape._avg
2728
3111
  );
2729
- if (shape._sum)
2730
- schemaFields["_sum"] = argsBuilder.buildAggregateFieldSchema(
3112
+ }
3113
+ if (shape._sum) {
3114
+ schemaFields._sum = argsBuilder.buildAggregateFieldSchema(
2731
3115
  model,
2732
3116
  "_sum",
2733
3117
  shape._sum
2734
3118
  );
2735
- if (shape._min)
2736
- schemaFields["_min"] = argsBuilder.buildAggregateFieldSchema(
3119
+ }
3120
+ if (shape._min) {
3121
+ schemaFields._min = argsBuilder.buildAggregateFieldSchema(
2737
3122
  model,
2738
3123
  "_min",
2739
3124
  shape._min
2740
3125
  );
2741
- if (shape._max)
2742
- schemaFields["_max"] = argsBuilder.buildAggregateFieldSchema(
3126
+ }
3127
+ if (shape._max) {
3128
+ schemaFields._max = argsBuilder.buildAggregateFieldSchema(
2743
3129
  model,
2744
3130
  "_max",
2745
3131
  shape._max
2746
3132
  );
2747
- if (shape.by)
2748
- schemaFields["by"] = argsBuilder.buildBySchema(model, shape.by);
2749
- if (shape.having)
2750
- schemaFields["having"] = argsBuilder.buildHavingSchema(
3133
+ }
3134
+ if (shape.by) {
3135
+ schemaFields.by = argsBuilder.buildBySchema(model, shape.by);
3136
+ }
3137
+ if (shape.having) {
3138
+ schemaFields.having = argsBuilder.buildHavingSchema(
2751
3139
  model,
2752
3140
  shape.having
2753
3141
  );
3142
+ }
2754
3143
  return {
2755
3144
  zodSchema: z7.object(schemaFields).strict(),
2756
3145
  forcedWhere,
@@ -2768,7 +3157,7 @@ function createQueryBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
2768
3157
  return { key: matched, shape: shapes[matched] };
2769
3158
  }
2770
3159
  function resolveDefaultShape(config, model, method, normalizedBody, opts, builtCache, isUnique) {
2771
- const shapeOrFn = config["default"];
3160
+ const shapeOrFn = config.default;
2772
3161
  let built;
2773
3162
  if (typeof shapeOrFn === "function") {
2774
3163
  const resolved = resolveAndValidateShape(shapeOrFn, opts?.ctx);
@@ -2822,8 +3211,9 @@ function createQueryBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
2822
3211
  built = builtCache.get("_default");
2823
3212
  }
2824
3213
  } else {
2825
- if (!isPlainObject(normalizedBody))
3214
+ if (!isPlainObject(normalizedBody)) {
2826
3215
  throw new ShapeError("Request body must be an object");
3216
+ }
2827
3217
  if ("caller" in normalizedBody) {
2828
3218
  throw new CallerError(
2829
3219
  "Pass caller via opts.caller, not in the request body."
@@ -4153,8 +4543,9 @@ function buildDefaultSelectInput(config) {
4153
4543
  const nested = {};
4154
4544
  if (value.select)
4155
4545
  nested.select = buildDefaultSelectInput(value.select);
4156
- if (value.include)
4546
+ if (value.include) {
4157
4547
  nested.include = buildDefaultIncludeInput(value.include);
4548
+ }
4158
4549
  result[key] = Object.keys(nested).length > 0 ? nested : true;
4159
4550
  }
4160
4551
  }
@@ -4173,8 +4564,9 @@ function buildDefaultIncludeInput(config) {
4173
4564
  result[key] = true;
4174
4565
  } else {
4175
4566
  const nested = {};
4176
- if (value.include)
4567
+ if (value.include) {
4177
4568
  nested.include = buildDefaultIncludeInput(value.include);
4569
+ }
4178
4570
  if (value.select)
4179
4571
  nested.select = buildDefaultSelectInput(value.select);
4180
4572
  result[key] = Object.keys(nested).length > 0 ? nested : true;
@@ -4185,8 +4577,9 @@ function buildDefaultIncludeInput(config) {
4185
4577
  function buildDefaultCountInput(config) {
4186
4578
  if (config === true)
4187
4579
  return true;
4188
- if (!isPlainObject(config) || !config.select || !isPlainObject(config.select))
4580
+ if (!isPlainObject(config) || !config.select || !isPlainObject(config.select)) {
4189
4581
  return true;
4582
+ }
4190
4583
  const selectObj = config.select;
4191
4584
  const result = {};
4192
4585
  for (const key of Object.keys(selectObj)) {
@@ -4268,8 +4661,9 @@ function checkIncludeForClientArgs(config) {
4268
4661
  continue;
4269
4662
  if (value.orderBy || value.cursor || value.take || value.skip)
4270
4663
  return true;
4271
- if (value.where && isPlainObject(value.where) && hasClientControlledValues(value.where))
4664
+ if (value.where && isPlainObject(value.where) && hasClientControlledValues(value.where)) {
4272
4665
  return true;
4666
+ }
4273
4667
  if (value.include && checkIncludeForClientArgs(value.include))
4274
4668
  return true;
4275
4669
  if (value.select && checkSelectForClientArgs(value.select))
@@ -4296,8 +4690,9 @@ function checkSelectForClientArgs(config) {
4296
4690
  continue;
4297
4691
  if (value.orderBy || value.cursor || value.take || value.skip)
4298
4692
  return true;
4299
- if (value.where && isPlainObject(value.where) && hasClientControlledValues(value.where))
4693
+ if (value.where && isPlainObject(value.where) && hasClientControlledValues(value.where)) {
4300
4694
  return true;
4695
+ }
4301
4696
  if (value.select && checkSelectForClientArgs(value.select))
4302
4697
  return true;
4303
4698
  if (value.include && checkIncludeForClientArgs(value.include))
@@ -4358,36 +4753,7 @@ function createModelGuardExtension(config) {
4358
4753
  validateUniqueEquality(modelName, shape.where, method, uniqueMap, typeMap);
4359
4754
  }
4360
4755
  function validateUniqueWhereShapeConfig(modelName, where, method) {
4361
- const constraints = uniqueMap[modelName];
4362
- if (!constraints || constraints.length === 0)
4363
- return;
4364
- const equalityFields = /* @__PURE__ */ new Set();
4365
- for (const [key, value] of Object.entries(where)) {
4366
- if (key === "AND" || key === "OR" || key === "NOT")
4367
- continue;
4368
- if (value === true) {
4369
- equalityFields.add(key);
4370
- continue;
4371
- }
4372
- if (isPlainObject(value)) {
4373
- if ("equals" in value) {
4374
- equalityFields.add(key);
4375
- }
4376
- continue;
4377
- }
4378
- if (value !== null && value !== void 0) {
4379
- equalityFields.add(key);
4380
- }
4381
- }
4382
- const valid = constraints.some(
4383
- (constraint) => constraint.every((field) => equalityFields.has(field))
4384
- );
4385
- if (!valid) {
4386
- const constraintDesc = constraints.map((c) => `(${c.join(", ")})`).join(" | ");
4387
- throw new ShapeError(
4388
- `${method} on model "${modelName}" requires where to cover a unique constraint with equality operators only: ${constraintDesc}`
4389
- );
4390
- }
4756
+ validateUniqueEquality(modelName, where, method, uniqueMap, typeMap);
4391
4757
  }
4392
4758
  function createGuardedMethods(modelName, modelDelegate, input, explicitCaller) {
4393
4759
  function callDelegate(method, args) {
@@ -4661,10 +5027,10 @@ function createModelGuardExtension(config) {
4661
5027
  `Invalid "where" on model "${modelName}": unique where must be a plain object`
4662
5028
  );
4663
5029
  }
4664
- const sanitized = { ...bodyWhere };
4665
- for (const key of built.forcedOnlyKeys) {
4666
- delete sanitized[key];
4667
- }
5030
+ const sanitized = hasWhereForced(built.forced) ? stripUniqueWhereForcedInput(
5031
+ bodyWhere,
5032
+ built.forced
5033
+ ) : { ...bodyWhere };
4668
5034
  try {
4669
5035
  result = built.schema.parse(sanitized);
4670
5036
  } catch (err) {
@@ -4677,16 +5043,23 @@ function createModelGuardExtension(config) {
4677
5043
  }
4678
5044
  } else if (bodyWhere !== void 0 && bodyWhere !== null) {
4679
5045
  if (isPlainObject(bodyWhere)) {
4680
- const hasOnlyForcedKeys = built.forcedOnlyKeys.size > 0 && Object.keys(bodyWhere).every((k) => built.forcedOnlyKeys.has(k));
4681
- if (!hasOnlyForcedKeys && Object.keys(bodyWhere).length > 0) {
5046
+ const sanitized = hasWhereForced(built.forced) ? stripUniqueWhereForcedInput(
5047
+ bodyWhere,
5048
+ built.forced
5049
+ ) : { ...bodyWhere };
5050
+ if (Object.keys(sanitized).length > 0) {
4682
5051
  throw new ShapeError(
4683
5052
  `Unique where on model "${modelName}" contains only forced values. Client where input is not accepted.`
4684
5053
  );
4685
5054
  }
5055
+ } else {
5056
+ throw new ShapeError(
5057
+ `Invalid "where" on model "${modelName}": unique where must be a plain object`
5058
+ );
4686
5059
  }
4687
5060
  }
4688
- for (const [key, value] of Object.entries(built.forced)) {
4689
- result[key] = value;
5061
+ if (hasWhereForced(built.forced)) {
5062
+ result = mergeUniqueWhereForced(result, built.forced);
4690
5063
  }
4691
5064
  return result;
4692
5065
  }
@@ -4699,7 +5072,9 @@ function createModelGuardExtension(config) {
4699
5072
  );
4700
5073
  if (Object.keys(where).length === 0) {
4701
5074
  const constraints = uniqueMap[modelName];
4702
- const constraintDesc = constraints ? constraints.map((c) => `(${c.join(", ")})`).join(" | ") : "unknown";
5075
+ const constraintDesc = constraints ? constraints.map(
5076
+ (constraint) => constraint.fields.length === 1 ? constraint.selector : `${constraint.selector}(${constraint.fields.join(", ")})`
5077
+ ).join(" | ") : "unknown";
4703
5078
  const expectedFields = shape.where ? Object.keys(shape.where).join(", ") : "none defined";
4704
5079
  throw new ShapeError(
4705
5080
  `${method} on model "${modelName}" requires a unique where condition. Unique constraints: ${constraintDesc}. Shape allows: ${expectedFields}`
@@ -4775,8 +5150,9 @@ function createModelGuardExtension(config) {
4775
5150
  return (body) => {
4776
5151
  const caller = resolveCaller();
4777
5152
  const resolved = resolveShape(input, body, contextFn, caller);
4778
- if (!resolved.shape.data)
5153
+ if (!resolved.shape.data) {
4779
5154
  throw new ShapeError(`Guard shape requires "data" for ${method}`);
5155
+ }
4780
5156
  validateMutationShapeKeys(
4781
5157
  resolved.shape,
4782
5158
  allowedShapeKeys,
@@ -4807,10 +5183,12 @@ function createModelGuardExtension(config) {
4807
5183
  );
4808
5184
  args = { data };
4809
5185
  } else {
4810
- if (!Array.isArray(resolved.body.data))
5186
+ if (!Array.isArray(resolved.body.data)) {
4811
5187
  throw new ShapeError(`${method} expects data to be an array`);
4812
- if (resolved.body.data.length === 0)
5188
+ }
5189
+ if (resolved.body.data.length === 0) {
4813
5190
  throw new ShapeError(`${method} received empty data array`);
5191
+ }
4814
5192
  const data = resolved.body.data.map(
4815
5193
  (item) => validateAndMergeData(item, dataSchema, method, modelName)
4816
5194
  );
@@ -4844,8 +5222,9 @@ function createModelGuardExtension(config) {
4844
5222
  return (body) => {
4845
5223
  const caller = resolveCaller();
4846
5224
  const resolved = resolveShape(input, body, contextFn, caller);
4847
- if (!resolved.shape.data)
5225
+ if (!resolved.shape.data) {
4848
5226
  throw new ShapeError(`Guard shape requires "data" for ${method}`);
5227
+ }
4849
5228
  validateMutationShapeKeys(
4850
5229
  resolved.shape,
4851
5230
  allowedShapeKeys,
@@ -4924,8 +5303,9 @@ function createModelGuardExtension(config) {
4924
5303
  return (body) => {
4925
5304
  const caller = resolveCaller();
4926
5305
  const resolved = resolveShape(input, body, contextFn, caller);
4927
- if (resolved.shape.data)
5306
+ if (resolved.shape.data) {
4928
5307
  throw new ShapeError(`Guard shape "data" is not valid for ${method}`);
5308
+ }
4929
5309
  validateMutationShapeKeys(
4930
5310
  resolved.shape,
4931
5311
  allowedShapeKeys,