prisma-guard 1.24.0 → 1.25.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
+ );
1242
1294
  }
1243
1295
  }
1244
- return fields;
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
+ );
1334
+ }
1335
+ }
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) {
@@ -1654,7 +1774,7 @@ function createWhereBuilder(typeMap, enumMap, scalarBase) {
1654
1774
  );
1655
1775
  }
1656
1776
  if (modeConfigValue === true) {
1657
- opSchemas["mode"] = z4.enum(["default", "insensitive"]).optional();
1777
+ opSchemas.mode = z4.enum(["default", "insensitive"]).optional();
1658
1778
  } else {
1659
1779
  const actualModeValue = isForcedValue(modeConfigValue) ? modeConfigValue.value : modeConfigValue;
1660
1780
  const modeSchema = z4.enum(["default", "insensitive"]);
@@ -1666,10 +1786,10 @@ function createWhereBuilder(typeMap, enumMap, scalarBase) {
1666
1786
  `Invalid forced value for "${model}.${fieldName}.mode": ${err.message}`
1667
1787
  );
1668
1788
  }
1669
- fieldForced["mode"] = parsed;
1789
+ fieldForced.mode = parsed;
1670
1790
  }
1671
1791
  } else if (hasModeCompatibleOp) {
1672
- opSchemas["mode"] = z4.enum(["default", "insensitive"]).optional();
1792
+ opSchemas.mode = z4.enum(["default", "insensitive"]).optional();
1673
1793
  }
1674
1794
  if (hasClientOps) {
1675
1795
  const opObj = z4.object(opSchemas).strict();
@@ -1697,12 +1817,60 @@ function createWhereBuilder(typeMap, enumMap, scalarBase) {
1697
1817
  scalarConditions[fieldName] = fieldForced;
1698
1818
  }
1699
1819
  }
1820
+ function getUniqueConstraint(model, selector) {
1821
+ return (uniqueMap[model] ?? []).find(
1822
+ (constraint) => constraint.selector === selector
1823
+ ) ?? null;
1824
+ }
1825
+ function buildDirectUniqueSchema(fieldMeta) {
1826
+ const base = createBaseType(fieldMeta, enumMap, scalarBase);
1827
+ if (!fieldMeta.isEnum && !fieldMeta.isRelation && !fieldMeta.isUnsupported) {
1828
+ return wrapWithInputCoercion(fieldMeta.type, fieldMeta.isList, base);
1829
+ }
1830
+ return base;
1831
+ }
1832
+ function parseForcedUniqueValue(model, fieldName, fieldMeta, value) {
1833
+ const schema = buildDirectUniqueSchema(fieldMeta);
1834
+ const actual = isForcedValue(value) ? value.value : value;
1835
+ try {
1836
+ return schema.parse(actual);
1837
+ } catch (err) {
1838
+ throw new ShapeError(
1839
+ `Invalid forced value for unique where "${model}.${fieldName}": ${err.message}`
1840
+ );
1841
+ }
1842
+ }
1843
+ function assertCompoundSelectorConfig(model, selector, constraint, value) {
1844
+ const actual = isForcedValue(value) ? value.value : value;
1845
+ if (!isPlainObject(actual)) {
1846
+ throw new ShapeError(
1847
+ `Compound unique selector "${model}.${selector}" must be an object with fields: ${constraint.fields.join(", ")}`
1848
+ );
1849
+ }
1850
+ const allowed = new Set(constraint.fields);
1851
+ const keys = Object.keys(actual);
1852
+ for (const key of keys) {
1853
+ if (!allowed.has(key)) {
1854
+ throw new ShapeError(
1855
+ `Unknown field "${key}" in compound unique selector "${model}.${selector}". Allowed fields: ${constraint.fields.join(", ")}`
1856
+ );
1857
+ }
1858
+ }
1859
+ for (const field of constraint.fields) {
1860
+ if (!(field in actual)) {
1861
+ throw new ShapeError(
1862
+ `Missing field "${field}" in compound unique selector "${model}.${selector}"`
1863
+ );
1864
+ }
1865
+ }
1866
+ return actual;
1867
+ }
1700
1868
  function buildUniqueWhereSchema(model, whereConfig) {
1701
1869
  const modelFields = typeMap[model];
1702
1870
  if (!modelFields)
1703
1871
  throw new ShapeError(`Unknown model: ${model}`);
1704
1872
  const fieldSchemas = {};
1705
- const forced = {};
1873
+ const forcedConditions = {};
1706
1874
  const forcedOnlyKeys = /* @__PURE__ */ new Set();
1707
1875
  for (const [key, value] of Object.entries(whereConfig)) {
1708
1876
  if (COMBINATOR_KEYS.has(key)) {
@@ -1710,65 +1878,97 @@ function createWhereBuilder(typeMap, enumMap, scalarBase) {
1710
1878
  `Combinator "${key}" is not supported in unique where for model "${model}"`
1711
1879
  );
1712
1880
  }
1881
+ const constraint = getUniqueConstraint(model, key);
1882
+ if (constraint && constraint.fields.length > 1) {
1883
+ const compoundConfig = assertCompoundSelectorConfig(
1884
+ model,
1885
+ key,
1886
+ constraint,
1887
+ value
1888
+ );
1889
+ const nestedSchemas = {};
1890
+ const forcedCompound = {};
1891
+ for (const fieldName of constraint.fields) {
1892
+ const fieldMeta2 = modelFields[fieldName];
1893
+ if (!fieldMeta2) {
1894
+ throw new ShapeError(
1895
+ `Unknown field "${fieldName}" in compound unique selector "${model}.${key}"`
1896
+ );
1897
+ }
1898
+ if (fieldMeta2.isRelation) {
1899
+ throw new ShapeError(
1900
+ `Relation field "${fieldName}" cannot be used in compound unique selector "${model}.${key}"`
1901
+ );
1902
+ }
1903
+ const fieldValue = compoundConfig[fieldName];
1904
+ const forced2 = isForcedValue(fieldValue);
1905
+ if (!forced2 && isPlainObject(fieldValue)) {
1906
+ const operators = Object.keys(fieldValue);
1907
+ throw new ShapeError(
1908
+ `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.`
1909
+ );
1910
+ }
1911
+ const directSchema2 = buildDirectUniqueSchema(fieldMeta2);
1912
+ if (fieldValue === true) {
1913
+ nestedSchemas[fieldName] = directSchema2;
1914
+ } else {
1915
+ forcedCompound[fieldName] = parseForcedUniqueValue(
1916
+ model,
1917
+ fieldName,
1918
+ fieldMeta2,
1919
+ fieldValue
1920
+ );
1921
+ }
1922
+ }
1923
+ if (Object.keys(nestedSchemas).length > 0) {
1924
+ fieldSchemas[key] = z4.object(nestedSchemas).strict();
1925
+ }
1926
+ if (Object.keys(forcedCompound).length > 0) {
1927
+ forcedConditions[key] = forcedCompound;
1928
+ }
1929
+ if (Object.keys(nestedSchemas).length === 0) {
1930
+ forcedOnlyKeys.add(key);
1931
+ }
1932
+ continue;
1933
+ }
1713
1934
  const fieldMeta = modelFields[key];
1714
- if (!fieldMeta)
1715
- throw new ShapeError(`Unknown field "${key}" on model "${model}"`);
1716
- if (fieldMeta.isRelation)
1935
+ if (!fieldMeta) {
1936
+ const selectors = (uniqueMap[model] ?? []).map((constraint2) => constraint2.selector).join(", ");
1717
1937
  throw new ShapeError(
1718
- `Relation field "${key}" cannot be used in unique where for model "${model}"`
1719
- );
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
1938
+ `Unknown unique field or selector "${key}" on model "${model}"${selectors ? `. Unique selectors: ${selectors}` : ""}`
1727
1939
  );
1728
- } else {
1729
- directSchema = base;
1730
1940
  }
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;
1941
+ if (fieldMeta.isRelation) {
1942
+ throw new ShapeError(
1943
+ `Relation field "${key}" cannot be used in unique where for model "${model}"`
1944
+ );
1735
1945
  }
1736
- if (isPlainObject(value)) {
1946
+ const forced = isForcedValue(value);
1947
+ if (!forced && isPlainObject(value)) {
1737
1948
  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;
1949
+ if (keys.includes("equals")) {
1950
+ throw new ShapeError(
1951
+ `Invalid unique where shape for "${model}.${key}". Prisma WhereUniqueInput does not accept filter operator objects. Use { ${key}: true } instead of { ${key}: { equals: true } }.`
1952
+ );
1754
1953
  }
1755
1954
  throw new ShapeError(
1756
- `Unique where field "${key}" on model "${model}" only accepts true or { equals: true/value }. Got operators: ${keys.join(", ")}`
1955
+ `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
1956
  );
1758
1957
  }
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
- );
1958
+ const directSchema = buildDirectUniqueSchema(fieldMeta);
1959
+ if (value === true) {
1960
+ fieldSchemas[key] = directSchema;
1961
+ continue;
1766
1962
  }
1963
+ forcedConditions[key] = parseForcedUniqueValue(model, key, fieldMeta, value);
1767
1964
  forcedOnlyKeys.add(key);
1768
1965
  }
1769
1966
  return {
1770
1967
  schema: Object.keys(fieldSchemas).length > 0 ? z4.object(fieldSchemas).strict() : null,
1771
- forced,
1968
+ forced: {
1969
+ conditions: forcedConditions,
1970
+ relations: {}
1971
+ },
1772
1972
  forcedOnlyKeys
1773
1973
  };
1774
1974
  }
@@ -1787,6 +1987,15 @@ function requireConfigTrue(config, context) {
1787
1987
  }
1788
1988
  }
1789
1989
  }
1990
+ function isPlainRecord(value) {
1991
+ return value !== null && typeof value === "object" && !Array.isArray(value);
1992
+ }
1993
+ function formatUniqueConstraint2(constraint) {
1994
+ return constraint.fields.length === 1 ? constraint.selector : `${constraint.selector}(${constraint.fields.join(", ")})`;
1995
+ }
1996
+ function formatUniqueConstraints2(constraints) {
1997
+ return constraints.map(formatUniqueConstraint2).join(" | ");
1998
+ }
1790
1999
  function createArgsBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
1791
2000
  const sortEnum = z5.enum(["asc", "desc"]);
1792
2001
  const nullsEnum = z5.enum(["first", "last"]);
@@ -1797,11 +2006,17 @@ function createArgsBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
1797
2006
  if (!fieldMeta)
1798
2007
  throw new ShapeError(`Unknown field "${fieldName}" on model "${model}"`);
1799
2008
  if (fieldMeta.isRelation)
1800
- throw new ShapeError(`Relation field "${fieldName}" in orderBy requires a nested config object, not true`);
2009
+ throw new ShapeError(
2010
+ `Relation field "${fieldName}" in orderBy requires a nested config object, not true`
2011
+ );
1801
2012
  if (fieldMeta.type === "Json")
1802
- throw new ShapeError(`Json field "${fieldName}" cannot be used in orderBy`);
2013
+ throw new ShapeError(
2014
+ `Json field "${fieldName}" cannot be used in orderBy`
2015
+ );
1803
2016
  if (fieldMeta.isList)
1804
- throw new ShapeError(`List field "${fieldName}" cannot be used in orderBy`);
2017
+ throw new ShapeError(
2018
+ `List field "${fieldName}" cannot be used in orderBy`
2019
+ );
1805
2020
  }
1806
2021
  function buildOrderBySchema(model, orderByConfig) {
1807
2022
  const modelFields = typeMap[model];
@@ -1811,158 +2026,274 @@ function createArgsBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
1811
2026
  for (const [fieldName, config] of Object.entries(orderByConfig)) {
1812
2027
  const fieldMeta = modelFields[fieldName];
1813
2028
  if (!fieldMeta)
1814
- throw new ShapeError(`Unknown field "${fieldName}" on model "${model}"`);
2029
+ throw new ShapeError(
2030
+ `Unknown field "${fieldName}" on model "${model}"`
2031
+ );
1815
2032
  if (config === true) {
1816
2033
  validateScalarOrderByField(fieldName, model, modelFields);
1817
2034
  fieldSchemas[fieldName] = scalarOrderSchema.optional();
1818
2035
  continue;
1819
2036
  }
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`);
2037
+ if (!isPlainRecord(config)) {
2038
+ throw new ShapeError(
2039
+ `orderBy config for "${fieldName}" on model "${model}" must be true or a relation aggregate object`
2040
+ );
1822
2041
  }
1823
2042
  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.`);
2043
+ const allowedOps = getSupportedOperators(
2044
+ fieldMeta.type,
2045
+ fieldMeta.isList
2046
+ );
2047
+ const opSchemas = {};
2048
+ for (const [op, enabled] of Object.entries(config)) {
2049
+ if (enabled !== true) {
2050
+ throw new ShapeError(
2051
+ `orderBy operator config for "${model}.${fieldName}.${op}" must be true`
2052
+ );
2053
+ }
2054
+ if (!allowedOps.includes(op)) {
2055
+ throw new ShapeError(
2056
+ `Operator "${op}" not supported for orderBy field "${model}.${fieldName}"`
2057
+ );
2058
+ }
2059
+ opSchemas[op] = scalarOrderSchema.optional();
2060
+ }
2061
+ const opKeys = Object.keys(opSchemas);
2062
+ fieldSchemas[fieldName] = z5.object(opSchemas).strict().refine(
2063
+ (v) => opKeys.some(
2064
+ (k) => v[k] !== void 0
2065
+ ),
2066
+ {
2067
+ message: `orderBy field "${fieldName}" must specify at least one operator`
2068
+ }
2069
+ ).optional();
2070
+ continue;
1828
2071
  }
1829
2072
  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 }`);
2073
+ if (!("_count" in config)) {
2074
+ throw new ShapeError(
2075
+ `To-many relation orderBy "${fieldName}" only supports _count`
2076
+ );
1833
2077
  }
1834
2078
  if (config._count !== true) {
1835
- throw new ShapeError(`_count in orderBy for "${fieldName}" must be true`);
2079
+ throw new ShapeError(
2080
+ `orderBy relation aggregate "${fieldName}._count" must be true`
2081
+ );
1836
2082
  }
1837
- fieldSchemas[fieldName] = z5.object({ _count: sortEnum }).strict().optional();
2083
+ fieldSchemas[fieldName] = z5.object({
2084
+ _count: sortEnum.optional()
2085
+ }).strict().optional();
1838
2086
  continue;
1839
2087
  }
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();
2088
+ const nested = buildOrderBySchema(
2089
+ fieldMeta.type,
2090
+ config
2091
+ );
2092
+ fieldSchemas[fieldName] = nested;
1865
2093
  }
1866
2094
  const fieldKeys = Object.keys(fieldSchemas);
1867
2095
  const singleSchema = z5.object(fieldSchemas).strict().refine(
1868
- (v) => fieldKeys.some((k) => v[k] !== void 0),
2096
+ (v) => fieldKeys.some(
2097
+ (k) => v[k] !== void 0
2098
+ ),
1869
2099
  { message: "orderBy must specify at least one field" }
1870
2100
  );
1871
- return z5.union([singleSchema, z5.preprocess(coerceToArray, z5.array(singleSchema).min(1))]).optional();
2101
+ return z5.union([
2102
+ singleSchema,
2103
+ z5.preprocess(coerceToArray, z5.array(singleSchema).min(1))
2104
+ ]).optional();
1872
2105
  }
1873
2106
  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}`);
2107
+ if (typeof config === "number") {
2108
+ if (!Number.isFinite(config) || !Number.isInteger(config)) {
2109
+ throw new ShapeError(`take must be a finite integer, got ${config}`);
2110
+ }
2111
+ if (config <= 0) {
2112
+ throw new ShapeError("take must be a positive integer");
2113
+ }
2114
+ return z5.literal(config).optional();
2115
+ }
2116
+ if (!config || typeof config !== "object" || Array.isArray(config)) {
2117
+ throw new ShapeError("take config must be a number or { max, default? }");
2118
+ }
2119
+ if (!Number.isFinite(config.max) || !Number.isInteger(config.max)) {
2120
+ throw new ShapeError(
2121
+ `take.max must be a finite integer, got ${config.max}`
2122
+ );
1877
2123
  }
1878
- if (normalized.max < 1) {
1879
- throw new ShapeError(`take max must be at least 1, got ${normalized.max}`);
2124
+ if (config.max <= 0) {
2125
+ throw new ShapeError("take.max must be a positive integer");
1880
2126
  }
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}`);
2127
+ if (config.default !== void 0) {
2128
+ if (!Number.isFinite(config.default) || !Number.isInteger(config.default)) {
2129
+ throw new ShapeError(
2130
+ `take.default must be a finite integer, got ${config.default}`
2131
+ );
1884
2132
  }
1885
- if (normalized.default < 1) {
1886
- throw new ShapeError(`take default must be at least 1, got ${normalized.default}`);
2133
+ if (config.default <= 0) {
2134
+ throw new ShapeError("take.default must be a positive integer");
1887
2135
  }
1888
- if (normalized.default > normalized.max) {
1889
- throw new ShapeError("take default cannot exceed max");
2136
+ if (config.default > config.max) {
2137
+ throw new ShapeError("take.default cannot exceed take.max");
1890
2138
  }
1891
- return z5.number().int().min(1).max(normalized.max).default(normalized.default);
2139
+ return z5.number().int().min(1).max(config.max).default(config.default);
1892
2140
  }
1893
- return z5.number().int().min(1).max(normalized.max).optional();
2141
+ return z5.number().int().min(1).max(config.max).optional();
1894
2142
  }
1895
- function buildCursorSchema(model, cursorConfig) {
2143
+ function buildCursorFieldSchema(model, fieldName) {
1896
2144
  const modelFields = typeMap[model];
1897
2145
  if (!modelFields)
1898
2146
  throw new ShapeError(`Unknown model: ${model}`);
1899
- requireConfigTrue(cursorConfig, `cursor on model "${model}"`);
1900
- const cursorFields = new Set(Object.keys(cursorConfig));
2147
+ const fieldMeta = modelFields[fieldName];
2148
+ if (!fieldMeta) {
2149
+ throw new ShapeError(
2150
+ `Unknown field "${fieldName}" on model "${model}" in cursor`
2151
+ );
2152
+ }
2153
+ if (fieldMeta.isRelation) {
2154
+ throw new ShapeError(
2155
+ `Relation field "${fieldName}" cannot be used in cursor`
2156
+ );
2157
+ }
2158
+ if (fieldMeta.isList) {
2159
+ throw new ShapeError(
2160
+ `List field "${fieldName}" cannot be used in cursor`
2161
+ );
2162
+ }
2163
+ const base = createBaseType(fieldMeta, enumMap, scalarBase);
2164
+ if (!fieldMeta.isEnum && !fieldMeta.isRelation && !fieldMeta.isUnsupported) {
2165
+ return wrapWithInputCoercion(fieldMeta.type, fieldMeta.isList, base);
2166
+ }
2167
+ return base;
2168
+ }
2169
+ function cursorConfigMatchesConstraint(cursorConfig, constraint) {
2170
+ if (!(constraint.selector in cursorConfig))
2171
+ return false;
2172
+ const value = cursorConfig[constraint.selector];
2173
+ if (constraint.fields.length === 1) {
2174
+ return value === true;
2175
+ }
2176
+ if (!isPlainRecord(value))
2177
+ return false;
2178
+ const keys = Object.keys(value);
2179
+ if (keys.length !== constraint.fields.length)
2180
+ return false;
2181
+ return constraint.fields.every((field) => value[field] === true);
2182
+ }
2183
+ function getUniqueConstraints(model) {
1901
2184
  const constraints = uniqueMap[model];
1902
2185
  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
- );
2186
+ return constraints;
2187
+ }
2188
+ const modelFields = typeMap[model];
2189
+ if (!modelFields) {
2190
+ throw new ShapeError(`Unknown model: ${model}`);
2191
+ }
2192
+ const inferred = [];
2193
+ for (const [fieldName, fieldMeta] of Object.entries(modelFields)) {
2194
+ if (fieldMeta.isRelation)
2195
+ continue;
2196
+ if (fieldMeta.isId || fieldMeta.isUnique) {
2197
+ inferred.push({
2198
+ selector: fieldName,
2199
+ fields: [fieldName]
2200
+ });
1911
2201
  }
1912
2202
  }
2203
+ return inferred;
2204
+ }
2205
+ function buildCursorSchema(model, cursorConfig) {
2206
+ const constraints = getUniqueConstraints(model);
2207
+ if (constraints.length === 0) {
2208
+ throw new ShapeError(
2209
+ `cursor on model "${model}" requires at least one unique constraint`
2210
+ );
2211
+ }
2212
+ const matching = constraints.find(
2213
+ (constraint) => cursorConfigMatchesConstraint(cursorConfig, constraint)
2214
+ );
2215
+ if (!matching) {
2216
+ throw new ShapeError(
2217
+ `cursor on model "${model}" must exactly match a unique selector: ${formatUniqueConstraints2(constraints)}`
2218
+ );
2219
+ }
1913
2220
  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);
2221
+ if (matching.fields.length === 1) {
2222
+ fieldSchemas[matching.selector] = buildCursorFieldSchema(
2223
+ model,
2224
+ matching.fields[0]
2225
+ ).optional();
2226
+ } else {
2227
+ const nestedSchemas = {};
2228
+ for (const field of matching.fields) {
2229
+ nestedSchemas[field] = buildCursorFieldSchema(model, field);
2230
+ }
2231
+ fieldSchemas[matching.selector] = z5.object(nestedSchemas).strict().optional();
1923
2232
  }
1924
- return z5.object(fieldSchemas).strict().optional();
2233
+ return z5.object(fieldSchemas).strict().refine(
2234
+ (v) => v[matching.selector] !== void 0,
2235
+ { message: `cursor must specify "${matching.selector}"` }
2236
+ ).optional();
1925
2237
  }
1926
2238
  function buildDistinctSchema(model, distinctConfig) {
1927
- if (distinctConfig.length === 0) {
1928
- throw new ShapeError("distinct must contain at least one field");
1929
- }
1930
2239
  const modelFields = typeMap[model];
1931
2240
  if (!modelFields)
1932
2241
  throw new ShapeError(`Unknown model: ${model}`);
2242
+ if (!Array.isArray(distinctConfig) || distinctConfig.length === 0) {
2243
+ throw new ShapeError(
2244
+ `distinct on model "${model}" must be a non-empty array of scalar fields`
2245
+ );
2246
+ }
2247
+ const allowedFields = /* @__PURE__ */ new Set();
1933
2248
  for (const fieldName of distinctConfig) {
1934
2249
  const fieldMeta = modelFields[fieldName];
1935
2250
  if (!fieldMeta)
1936
- throw new ShapeError(`Unknown field "${fieldName}" on model "${model}" in distinct`);
2251
+ throw new ShapeError(
2252
+ `Unknown field "${fieldName}" on model "${model}" in distinct`
2253
+ );
1937
2254
  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`);
2255
+ throw new ShapeError(
2256
+ `Relation field "${fieldName}" cannot be used in distinct`
2257
+ );
2258
+ allowedFields.add(fieldName);
1941
2259
  }
1942
- const enumSchema = z5.enum(distinctConfig);
1943
- return z5.union([enumSchema, z5.preprocess(coerceToArray, z5.array(enumSchema).min(1))]).optional();
2260
+ return z5.union([
2261
+ z5.enum([...allowedFields]),
2262
+ z5.array(z5.enum([...allowedFields])).min(1)
2263
+ ]).optional();
1944
2264
  }
1945
2265
  function buildBySchema(model, byConfig) {
1946
- if (byConfig.length === 0) {
1947
- throw new ShapeError('groupBy "by" must contain at least one field');
1948
- }
1949
2266
  const modelFields = typeMap[model];
1950
2267
  if (!modelFields)
1951
2268
  throw new ShapeError(`Unknown model: ${model}`);
2269
+ if (!Array.isArray(byConfig) || byConfig.length === 0) {
2270
+ throw new ShapeError(
2271
+ `groupBy "by" on model "${model}" must be a non-empty array`
2272
+ );
2273
+ }
2274
+ const allowedFields = /* @__PURE__ */ new Set();
1952
2275
  for (const fieldName of byConfig) {
1953
2276
  const fieldMeta = modelFields[fieldName];
1954
2277
  if (!fieldMeta)
1955
- throw new ShapeError(`Unknown field "${fieldName}" on model "${model}" in by`);
2278
+ throw new ShapeError(
2279
+ `Unknown field "${fieldName}" on model "${model}" in groupBy by`
2280
+ );
1956
2281
  if (fieldMeta.isRelation)
1957
- throw new ShapeError(`Relation field "${fieldName}" cannot be used in by`);
2282
+ throw new ShapeError(
2283
+ `Relation field "${fieldName}" cannot be used in groupBy by`
2284
+ );
2285
+ if (fieldMeta.isList)
2286
+ throw new ShapeError(
2287
+ `List field "${fieldName}" cannot be used in groupBy by`
2288
+ );
1958
2289
  if (UNSUPPORTED_BY_TYPES.has(fieldMeta.type)) {
1959
- throw new ShapeError(`${fieldMeta.type} field "${fieldName}" cannot be used in by`);
2290
+ throw new ShapeError(
2291
+ `${fieldMeta.type} field "${fieldName}" cannot be used in groupBy by`
2292
+ );
1960
2293
  }
1961
- if (fieldMeta.isList)
1962
- throw new ShapeError(`List field "${fieldName}" cannot be used in by`);
2294
+ allowedFields.add(fieldName);
1963
2295
  }
1964
- const enumSchema = z5.enum(byConfig);
1965
- return z5.union([enumSchema, z5.preprocess(coerceToArray, z5.array(enumSchema).min(1))]);
2296
+ return z5.array(z5.enum([...allowedFields])).min(1);
1966
2297
  }
1967
2298
  function buildHavingSchema(model, havingConfig) {
1968
2299
  const modelFields = typeMap[model];
@@ -1973,82 +2304,88 @@ function createArgsBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
1973
2304
  for (const fieldName of Object.keys(havingConfig)) {
1974
2305
  const fieldMeta = modelFields[fieldName];
1975
2306
  if (!fieldMeta)
1976
- throw new ShapeError(`Unknown field "${fieldName}" on model "${model}" in having`);
2307
+ throw new ShapeError(
2308
+ `Unknown field "${fieldName}" on model "${model}" in having`
2309
+ );
1977
2310
  if (fieldMeta.isRelation)
1978
- throw new ShapeError(`Relation field "${fieldName}" cannot be used in having`);
2311
+ throw new ShapeError(
2312
+ `Relation field "${fieldName}" cannot be used in having`
2313
+ );
1979
2314
  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`);
2315
+ throw new ShapeError(
2316
+ `List field "${fieldName}" cannot be used in having`
2317
+ );
2318
+ if (UNSUPPORTED_BY_TYPES.has(fieldMeta.type)) {
2319
+ throw new ShapeError(
2320
+ `${fieldMeta.type} field "${fieldName}" cannot be used in having`
2321
+ );
1984
2322
  }
2323
+ const allowedOps = getSupportedOperators(
2324
+ fieldMeta.type,
2325
+ fieldMeta.isList
2326
+ );
1985
2327
  const opSchemas = {};
1986
- const opKeys = [];
1987
- for (const op of ops) {
1988
- opSchemas[op] = createOperatorSchema(fieldMeta, op, enumMap, scalarBase).optional();
1989
- opKeys.push(op);
2328
+ for (const op of allowedOps) {
2329
+ opSchemas[op] = createOperatorSchema(
2330
+ fieldMeta,
2331
+ op,
2332
+ enumMap,
2333
+ scalarBase
2334
+ ).optional();
1990
2335
  }
1991
- if (fieldMeta.type === "String" && !fieldMeta.isList) {
1992
- opSchemas["mode"] = z5.enum(["default", "insensitive"]).optional();
2336
+ if (fieldMeta.type === "String") {
2337
+ opSchemas.mode = z5.enum(["default", "insensitive"]).optional();
1993
2338
  }
2339
+ const opKeys = Object.keys(opSchemas).filter((key) => key !== "mode");
1994
2340
  fieldSchemas[fieldName] = z5.object(opSchemas).strict().refine(
1995
2341
  (v) => opKeys.some((k) => v[k] !== void 0),
1996
- { message: `At least one operator required for having field "${fieldName}"` }
2342
+ {
2343
+ message: `having field "${fieldName}" must specify at least one operator`
2344
+ }
1997
2345
  ).optional();
1998
2346
  }
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();
2347
+ const fieldKeys = Object.keys(fieldSchemas);
2348
+ return z5.object(fieldSchemas).strict().refine(
2349
+ (v) => fieldKeys.some(
2350
+ (k) => v[k] !== void 0
2351
+ ),
2352
+ { message: "having must specify at least one field" }
2353
+ ).optional();
2015
2354
  }
2016
- function buildAggregateFieldSchema(model, opName, fieldConfig) {
2355
+ function buildAggregateFieldSchema(model, op, config) {
2017
2356
  const modelFields = typeMap[model];
2018
2357
  if (!modelFields)
2019
2358
  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";
2359
+ requireConfigTrue(config, `${op} on model "${model}"`);
2360
+ const allowedTypes = op === "_avg" || op === "_sum" ? NUMERIC_TYPES : COMPARABLE_TYPES;
2023
2361
  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
- }
2362
+ for (const fieldName of Object.keys(config)) {
2029
2363
  const fieldMeta = modelFields[fieldName];
2030
2364
  if (!fieldMeta)
2031
- throw new ShapeError(`Unknown field "${fieldName}" on model "${model}" in ${opName}`);
2365
+ throw new ShapeError(
2366
+ `Unknown field "${fieldName}" on model "${model}" in ${op}`
2367
+ );
2032
2368
  if (fieldMeta.isRelation)
2033
- throw new ShapeError(`Relation field "${fieldName}" cannot be used in ${opName}`);
2369
+ throw new ShapeError(
2370
+ `Relation field "${fieldName}" cannot be used in ${op}`
2371
+ );
2034
2372
  if (fieldMeta.isList)
2035
- throw new ShapeError(`List field "${fieldName}" cannot be used in ${opName}`);
2036
- if (isNumericOnly && !NUMERIC_TYPES.has(fieldMeta.type)) {
2037
2373
  throw new ShapeError(
2038
- `Field "${fieldName}" (${fieldMeta.type}) cannot be used in ${opName}. Only numeric types (Int, Float, Decimal, BigInt) are supported.`
2374
+ `List field "${fieldName}" cannot be used in ${op}`
2039
2375
  );
2040
- }
2041
- if (isComparableOnly && !COMPARABLE_TYPES.has(fieldMeta.type)) {
2376
+ if (!allowedTypes.has(fieldMeta.type)) {
2042
2377
  throw new ShapeError(
2043
- `Field "${fieldName}" (${fieldMeta.type}) cannot be used in ${opName}. Only comparable types (Int, Float, Decimal, BigInt, String, DateTime) are supported.`
2378
+ `Field "${fieldName}" of type "${fieldMeta.type}" cannot be used in ${op}`
2044
2379
  );
2045
2380
  }
2046
2381
  fieldSchemas[fieldName] = z5.literal(true).optional();
2047
2382
  }
2048
- const aggFieldKeys = Object.keys(fieldSchemas);
2383
+ const aggregateFieldKeys = Object.keys(fieldSchemas);
2049
2384
  return z5.object(fieldSchemas).strict().refine(
2050
- (v) => aggFieldKeys.some((k) => v[k] !== void 0),
2051
- { message: `${opName} must specify at least one field` }
2385
+ (v) => aggregateFieldKeys.some(
2386
+ (k) => v[k] !== void 0
2387
+ ),
2388
+ { message: `${op} must specify at least one field` }
2052
2389
  ).optional();
2053
2390
  }
2054
2391
  function buildCountFieldSchema(model, config, context) {
@@ -2064,15 +2401,21 @@ function createArgsBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
2064
2401
  if (fieldName !== "_all") {
2065
2402
  const fieldMeta = modelFields[fieldName];
2066
2403
  if (!fieldMeta)
2067
- throw new ShapeError(`Unknown field "${fieldName}" on model "${model}" in ${context}`);
2404
+ throw new ShapeError(
2405
+ `Unknown field "${fieldName}" on model "${model}" in ${context}`
2406
+ );
2068
2407
  if (fieldMeta.isRelation)
2069
- throw new ShapeError(`Relation field "${fieldName}" cannot be used in ${context}`);
2408
+ throw new ShapeError(
2409
+ `Relation field "${fieldName}" cannot be used in ${context}`
2410
+ );
2070
2411
  }
2071
2412
  fieldSchemas[fieldName] = z5.literal(true).optional();
2072
2413
  }
2073
2414
  const countFieldKeys = Object.keys(fieldSchemas);
2074
2415
  return z5.object(fieldSchemas).strict().refine(
2075
- (v) => countFieldKeys.some((k) => v[k] !== void 0),
2416
+ (v) => countFieldKeys.some(
2417
+ (k) => v[k] !== void 0
2418
+ ),
2076
2419
  { message: `${context} must specify at least one field` }
2077
2420
  ).optional();
2078
2421
  }
@@ -2084,19 +2427,25 @@ function createArgsBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
2084
2427
  const fieldSchemas = {};
2085
2428
  for (const fieldName of Object.keys(selectConfig)) {
2086
2429
  if (fieldName === "_all") {
2087
- fieldSchemas["_all"] = z5.literal(true).optional();
2430
+ fieldSchemas._all = z5.literal(true).optional();
2088
2431
  continue;
2089
2432
  }
2090
2433
  const fieldMeta = modelFields[fieldName];
2091
2434
  if (!fieldMeta)
2092
- throw new ShapeError(`Unknown field "${fieldName}" on model "${model}" in count select`);
2435
+ throw new ShapeError(
2436
+ `Unknown field "${fieldName}" on model "${model}" in count select`
2437
+ );
2093
2438
  if (fieldMeta.isRelation)
2094
- throw new ShapeError(`Relation field "${fieldName}" cannot be used in count select`);
2439
+ throw new ShapeError(
2440
+ `Relation field "${fieldName}" cannot be used in count select`
2441
+ );
2095
2442
  fieldSchemas[fieldName] = z5.literal(true).optional();
2096
2443
  }
2097
2444
  const countSelectKeys = Object.keys(fieldSchemas);
2098
2445
  return z5.object(fieldSchemas).strict().refine(
2099
- (v) => countSelectKeys.some((k) => v[k] !== void 0),
2446
+ (v) => countSelectKeys.some(
2447
+ (k) => v[k] !== void 0
2448
+ ),
2100
2449
  { message: "count select must specify at least one field" }
2101
2450
  ).optional();
2102
2451
  }
@@ -2505,7 +2854,12 @@ var UNIQUE_WHERE_METHODS = /* @__PURE__ */ new Set([
2505
2854
  "findUniqueOrThrow"
2506
2855
  ]);
2507
2856
  function createQueryBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
2508
- const whereBuilder = createWhereBuilder(typeMap, enumMap, scalarBase);
2857
+ const whereBuilder = createWhereBuilder(
2858
+ typeMap,
2859
+ enumMap,
2860
+ scalarBase,
2861
+ uniqueMap
2862
+ );
2509
2863
  const argsBuilder = createArgsBuilder(
2510
2864
  typeMap,
2511
2865
  enumMap,
@@ -2527,24 +2881,28 @@ function createQueryBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
2527
2881
  function validateShapeArgs(method, shape) {
2528
2882
  const allowed = METHOD_ALLOWED_ARGS[method];
2529
2883
  for (const key of Object.keys(shape)) {
2530
- if (!SHAPE_CONFIG_KEYS.has(key))
2884
+ if (!SHAPE_CONFIG_KEYS.has(key)) {
2531
2885
  throw new ShapeError(`Unknown shape config key "${key}"`);
2532
- if (!allowed.has(key))
2886
+ }
2887
+ if (!allowed.has(key)) {
2533
2888
  throw new ShapeError(`Arg "${key}" not allowed for method "${method}"`);
2889
+ }
2534
2890
  }
2535
2891
  if (UNIQUE_WHERE_METHODS.has(method) && !shape.where) {
2536
2892
  throw new ShapeError(`${method} shape must define "where"`);
2537
2893
  }
2538
- if (method === "groupBy" && !shape.by)
2894
+ if (method === "groupBy" && !shape.by) {
2539
2895
  throw new ShapeError('groupBy shape must define "by"');
2896
+ }
2540
2897
  if (method === "groupBy" && (shape.include || shape.select)) {
2541
2898
  throw new ShapeError('groupBy does not support "include" or "select"');
2542
2899
  }
2543
2900
  if (method === "aggregate" && (shape.include || shape.select)) {
2544
2901
  throw new ShapeError('aggregate does not support "include" or "select"');
2545
2902
  }
2546
- if (method === "count" && shape.include)
2903
+ if (method === "count" && shape.include) {
2547
2904
  throw new ShapeError('count does not support "include"');
2905
+ }
2548
2906
  if (method === "groupBy" && shape.orderBy && shape.orderBy !== true) {
2549
2907
  const bySet = new Set(shape.by);
2550
2908
  for (const fieldName of Object.keys(shape.orderBy)) {
@@ -2599,30 +2957,28 @@ function createQueryBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
2599
2957
  let forcedIncludeCountWhere = {};
2600
2958
  let forcedSelectCountWhere = {};
2601
2959
  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;
2960
+ const builtWhere = UNIQUE_WHERE_METHODS.has(method) ? whereBuilder.buildUniqueWhereSchema(model, shape.where) : whereBuilder.buildWhereSchema(model, shape.where);
2961
+ if (builtWhere.schema) {
2962
+ schemaFields.where = builtWhere.schema;
2963
+ }
2964
+ forcedWhere = builtWhere.forced;
2965
+ forcedOnlyWhereKeys = builtWhere.forcedOnlyKeys;
2610
2966
  }
2611
2967
  if (shape.include) {
2612
2968
  const result = projectionBuilder.buildIncludeSchema(model, shape.include);
2613
- schemaFields["include"] = result.schema;
2969
+ schemaFields.include = result.schema;
2614
2970
  forcedIncludeTree = result.forcedTree;
2615
2971
  forcedIncludeCountWhere = result.forcedCountWhere;
2616
2972
  }
2617
2973
  if (shape.select) {
2618
2974
  if (method === "count") {
2619
- schemaFields["select"] = argsBuilder.buildCountSelectSchema(
2975
+ schemaFields.select = argsBuilder.buildCountSelectSchema(
2620
2976
  model,
2621
2977
  shape.select
2622
2978
  );
2623
2979
  } else {
2624
2980
  const result = projectionBuilder.buildSelectSchema(model, shape.select);
2625
- schemaFields["select"] = result.schema;
2981
+ schemaFields.select = result.schema;
2626
2982
  forcedSelectTree = result.forcedTree;
2627
2983
  forcedSelectCountWhere = result.forcedCountWhere;
2628
2984
  }
@@ -2636,7 +2992,7 @@ function createQueryBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
2636
2992
  for (const field of shape.by) {
2637
2993
  groupByOrderFields[field] = sortEnum.optional();
2638
2994
  }
2639
- groupByOrderFields["_count"] = sortEnum.optional();
2995
+ groupByOrderFields._count = sortEnum.optional();
2640
2996
  const fieldKeys = Object.keys(groupByOrderFields);
2641
2997
  const singleSchema = z7.object(groupByOrderFields).strict().refine(
2642
2998
  (v) => fieldKeys.some(
@@ -2644,13 +3000,16 @@ function createQueryBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
2644
3000
  ),
2645
3001
  { message: "orderBy must specify at least one field" }
2646
3002
  );
2647
- schemaFields["orderBy"] = z7.union([singleSchema, z7.preprocess(coerceToArray, z7.array(singleSchema).min(1))]).optional();
3003
+ schemaFields.orderBy = z7.union([
3004
+ singleSchema,
3005
+ z7.preprocess(coerceToArray, z7.array(singleSchema).min(1))
3006
+ ]).optional();
2648
3007
  } else {
2649
3008
  const groupByOrderFields = {};
2650
3009
  for (const [fieldName, config] of Object.entries(shape.orderBy)) {
2651
3010
  if (fieldName === "_count") {
2652
3011
  if (config === true) {
2653
- groupByOrderFields["_count"] = sortEnum.optional();
3012
+ groupByOrderFields._count = sortEnum.optional();
2654
3013
  } else if (typeof config === "object" && config !== null) {
2655
3014
  const countFields = {};
2656
3015
  for (const countField of Object.keys(config)) {
@@ -2662,7 +3021,7 @@ function createQueryBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
2662
3021
  countFields[countField] = sortEnum.optional();
2663
3022
  }
2664
3023
  const countKeys = Object.keys(countFields);
2665
- groupByOrderFields["_count"] = z7.object(countFields).strict().refine(
3024
+ groupByOrderFields._count = z7.object(countFields).strict().refine(
2666
3025
  (v) => countKeys.some(
2667
3026
  (k) => v[k] !== void 0
2668
3027
  ),
@@ -2687,70 +3046,83 @@ function createQueryBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
2687
3046
  ),
2688
3047
  { message: "orderBy must specify at least one field" }
2689
3048
  );
2690
- schemaFields["orderBy"] = z7.union([singleSchema, z7.preprocess(coerceToArray, z7.array(singleSchema).min(1))]).optional();
3049
+ schemaFields.orderBy = z7.union([
3050
+ singleSchema,
3051
+ z7.preprocess(coerceToArray, z7.array(singleSchema).min(1))
3052
+ ]).optional();
2691
3053
  }
2692
3054
  } else {
2693
- schemaFields["orderBy"] = argsBuilder.buildOrderBySchema(
3055
+ schemaFields.orderBy = argsBuilder.buildOrderBySchema(
2694
3056
  model,
2695
3057
  shape.orderBy
2696
3058
  );
2697
3059
  }
2698
3060
  }
2699
- if (shape.cursor)
2700
- schemaFields["cursor"] = argsBuilder.buildCursorSchema(
3061
+ if (shape.cursor) {
3062
+ schemaFields.cursor = argsBuilder.buildCursorSchema(
2701
3063
  model,
2702
3064
  shape.cursor
2703
3065
  );
2704
- if (shape.take)
2705
- schemaFields["take"] = argsBuilder.buildTakeSchema(shape.take);
3066
+ }
3067
+ if (shape.take) {
3068
+ schemaFields.take = argsBuilder.buildTakeSchema(shape.take);
3069
+ }
2706
3070
  if (shape.skip !== void 0) {
2707
3071
  if (shape.skip !== true) {
2708
3072
  throw new ShapeError('Shape config "skip" must be true');
2709
3073
  }
2710
- schemaFields["skip"] = z7.number().int().min(0).optional();
3074
+ schemaFields.skip = z7.number().int().min(0).optional();
2711
3075
  }
2712
- if (shape.distinct)
2713
- schemaFields["distinct"] = argsBuilder.buildDistinctSchema(
3076
+ if (shape.distinct) {
3077
+ schemaFields.distinct = argsBuilder.buildDistinctSchema(
2714
3078
  model,
2715
3079
  shape.distinct
2716
3080
  );
2717
- if (shape._count)
2718
- schemaFields["_count"] = argsBuilder.buildCountFieldSchema(
3081
+ }
3082
+ if (shape._count) {
3083
+ schemaFields._count = argsBuilder.buildCountFieldSchema(
2719
3084
  model,
2720
3085
  shape._count,
2721
3086
  "_count"
2722
3087
  );
2723
- if (shape._avg)
2724
- schemaFields["_avg"] = argsBuilder.buildAggregateFieldSchema(
3088
+ }
3089
+ if (shape._avg) {
3090
+ schemaFields._avg = argsBuilder.buildAggregateFieldSchema(
2725
3091
  model,
2726
3092
  "_avg",
2727
3093
  shape._avg
2728
3094
  );
2729
- if (shape._sum)
2730
- schemaFields["_sum"] = argsBuilder.buildAggregateFieldSchema(
3095
+ }
3096
+ if (shape._sum) {
3097
+ schemaFields._sum = argsBuilder.buildAggregateFieldSchema(
2731
3098
  model,
2732
3099
  "_sum",
2733
3100
  shape._sum
2734
3101
  );
2735
- if (shape._min)
2736
- schemaFields["_min"] = argsBuilder.buildAggregateFieldSchema(
3102
+ }
3103
+ if (shape._min) {
3104
+ schemaFields._min = argsBuilder.buildAggregateFieldSchema(
2737
3105
  model,
2738
3106
  "_min",
2739
3107
  shape._min
2740
3108
  );
2741
- if (shape._max)
2742
- schemaFields["_max"] = argsBuilder.buildAggregateFieldSchema(
3109
+ }
3110
+ if (shape._max) {
3111
+ schemaFields._max = argsBuilder.buildAggregateFieldSchema(
2743
3112
  model,
2744
3113
  "_max",
2745
3114
  shape._max
2746
3115
  );
2747
- if (shape.by)
2748
- schemaFields["by"] = argsBuilder.buildBySchema(model, shape.by);
2749
- if (shape.having)
2750
- schemaFields["having"] = argsBuilder.buildHavingSchema(
3116
+ }
3117
+ if (shape.by) {
3118
+ schemaFields.by = argsBuilder.buildBySchema(model, shape.by);
3119
+ }
3120
+ if (shape.having) {
3121
+ schemaFields.having = argsBuilder.buildHavingSchema(
2751
3122
  model,
2752
3123
  shape.having
2753
3124
  );
3125
+ }
2754
3126
  return {
2755
3127
  zodSchema: z7.object(schemaFields).strict(),
2756
3128
  forcedWhere,
@@ -2768,7 +3140,7 @@ function createQueryBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
2768
3140
  return { key: matched, shape: shapes[matched] };
2769
3141
  }
2770
3142
  function resolveDefaultShape(config, model, method, normalizedBody, opts, builtCache, isUnique) {
2771
- const shapeOrFn = config["default"];
3143
+ const shapeOrFn = config.default;
2772
3144
  let built;
2773
3145
  if (typeof shapeOrFn === "function") {
2774
3146
  const resolved = resolveAndValidateShape(shapeOrFn, opts?.ctx);
@@ -2822,8 +3194,9 @@ function createQueryBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
2822
3194
  built = builtCache.get("_default");
2823
3195
  }
2824
3196
  } else {
2825
- if (!isPlainObject(normalizedBody))
3197
+ if (!isPlainObject(normalizedBody)) {
2826
3198
  throw new ShapeError("Request body must be an object");
3199
+ }
2827
3200
  if ("caller" in normalizedBody) {
2828
3201
  throw new CallerError(
2829
3202
  "Pass caller via opts.caller, not in the request body."
@@ -4153,8 +4526,9 @@ function buildDefaultSelectInput(config) {
4153
4526
  const nested = {};
4154
4527
  if (value.select)
4155
4528
  nested.select = buildDefaultSelectInput(value.select);
4156
- if (value.include)
4529
+ if (value.include) {
4157
4530
  nested.include = buildDefaultIncludeInput(value.include);
4531
+ }
4158
4532
  result[key] = Object.keys(nested).length > 0 ? nested : true;
4159
4533
  }
4160
4534
  }
@@ -4173,8 +4547,9 @@ function buildDefaultIncludeInput(config) {
4173
4547
  result[key] = true;
4174
4548
  } else {
4175
4549
  const nested = {};
4176
- if (value.include)
4550
+ if (value.include) {
4177
4551
  nested.include = buildDefaultIncludeInput(value.include);
4552
+ }
4178
4553
  if (value.select)
4179
4554
  nested.select = buildDefaultSelectInput(value.select);
4180
4555
  result[key] = Object.keys(nested).length > 0 ? nested : true;
@@ -4185,8 +4560,9 @@ function buildDefaultIncludeInput(config) {
4185
4560
  function buildDefaultCountInput(config) {
4186
4561
  if (config === true)
4187
4562
  return true;
4188
- if (!isPlainObject(config) || !config.select || !isPlainObject(config.select))
4563
+ if (!isPlainObject(config) || !config.select || !isPlainObject(config.select)) {
4189
4564
  return true;
4565
+ }
4190
4566
  const selectObj = config.select;
4191
4567
  const result = {};
4192
4568
  for (const key of Object.keys(selectObj)) {
@@ -4268,8 +4644,9 @@ function checkIncludeForClientArgs(config) {
4268
4644
  continue;
4269
4645
  if (value.orderBy || value.cursor || value.take || value.skip)
4270
4646
  return true;
4271
- if (value.where && isPlainObject(value.where) && hasClientControlledValues(value.where))
4647
+ if (value.where && isPlainObject(value.where) && hasClientControlledValues(value.where)) {
4272
4648
  return true;
4649
+ }
4273
4650
  if (value.include && checkIncludeForClientArgs(value.include))
4274
4651
  return true;
4275
4652
  if (value.select && checkSelectForClientArgs(value.select))
@@ -4296,8 +4673,9 @@ function checkSelectForClientArgs(config) {
4296
4673
  continue;
4297
4674
  if (value.orderBy || value.cursor || value.take || value.skip)
4298
4675
  return true;
4299
- if (value.where && isPlainObject(value.where) && hasClientControlledValues(value.where))
4676
+ if (value.where && isPlainObject(value.where) && hasClientControlledValues(value.where)) {
4300
4677
  return true;
4678
+ }
4301
4679
  if (value.select && checkSelectForClientArgs(value.select))
4302
4680
  return true;
4303
4681
  if (value.include && checkIncludeForClientArgs(value.include))
@@ -4358,36 +4736,7 @@ function createModelGuardExtension(config) {
4358
4736
  validateUniqueEquality(modelName, shape.where, method, uniqueMap, typeMap);
4359
4737
  }
4360
4738
  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
- }
4739
+ validateUniqueEquality(modelName, where, method, uniqueMap, typeMap);
4391
4740
  }
4392
4741
  function createGuardedMethods(modelName, modelDelegate, input, explicitCaller) {
4393
4742
  function callDelegate(method, args) {
@@ -4661,10 +5010,10 @@ function createModelGuardExtension(config) {
4661
5010
  `Invalid "where" on model "${modelName}": unique where must be a plain object`
4662
5011
  );
4663
5012
  }
4664
- const sanitized = { ...bodyWhere };
4665
- for (const key of built.forcedOnlyKeys) {
4666
- delete sanitized[key];
4667
- }
5013
+ const sanitized = hasWhereForced(built.forced) ? stripUniqueWhereForcedInput(
5014
+ bodyWhere,
5015
+ built.forced
5016
+ ) : { ...bodyWhere };
4668
5017
  try {
4669
5018
  result = built.schema.parse(sanitized);
4670
5019
  } catch (err) {
@@ -4677,16 +5026,23 @@ function createModelGuardExtension(config) {
4677
5026
  }
4678
5027
  } else if (bodyWhere !== void 0 && bodyWhere !== null) {
4679
5028
  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) {
5029
+ const sanitized = hasWhereForced(built.forced) ? stripUniqueWhereForcedInput(
5030
+ bodyWhere,
5031
+ built.forced
5032
+ ) : { ...bodyWhere };
5033
+ if (Object.keys(sanitized).length > 0) {
4682
5034
  throw new ShapeError(
4683
5035
  `Unique where on model "${modelName}" contains only forced values. Client where input is not accepted.`
4684
5036
  );
4685
5037
  }
5038
+ } else {
5039
+ throw new ShapeError(
5040
+ `Invalid "where" on model "${modelName}": unique where must be a plain object`
5041
+ );
4686
5042
  }
4687
5043
  }
4688
- for (const [key, value] of Object.entries(built.forced)) {
4689
- result[key] = value;
5044
+ if (hasWhereForced(built.forced)) {
5045
+ result = mergeUniqueWhereForced(result, built.forced);
4690
5046
  }
4691
5047
  return result;
4692
5048
  }
@@ -4699,7 +5055,9 @@ function createModelGuardExtension(config) {
4699
5055
  );
4700
5056
  if (Object.keys(where).length === 0) {
4701
5057
  const constraints = uniqueMap[modelName];
4702
- const constraintDesc = constraints ? constraints.map((c) => `(${c.join(", ")})`).join(" | ") : "unknown";
5058
+ const constraintDesc = constraints ? constraints.map(
5059
+ (constraint) => constraint.fields.length === 1 ? constraint.selector : `${constraint.selector}(${constraint.fields.join(", ")})`
5060
+ ).join(" | ") : "unknown";
4703
5061
  const expectedFields = shape.where ? Object.keys(shape.where).join(", ") : "none defined";
4704
5062
  throw new ShapeError(
4705
5063
  `${method} on model "${modelName}" requires a unique where condition. Unique constraints: ${constraintDesc}. Shape allows: ${expectedFields}`
@@ -4775,8 +5133,9 @@ function createModelGuardExtension(config) {
4775
5133
  return (body) => {
4776
5134
  const caller = resolveCaller();
4777
5135
  const resolved = resolveShape(input, body, contextFn, caller);
4778
- if (!resolved.shape.data)
5136
+ if (!resolved.shape.data) {
4779
5137
  throw new ShapeError(`Guard shape requires "data" for ${method}`);
5138
+ }
4780
5139
  validateMutationShapeKeys(
4781
5140
  resolved.shape,
4782
5141
  allowedShapeKeys,
@@ -4807,10 +5166,12 @@ function createModelGuardExtension(config) {
4807
5166
  );
4808
5167
  args = { data };
4809
5168
  } else {
4810
- if (!Array.isArray(resolved.body.data))
5169
+ if (!Array.isArray(resolved.body.data)) {
4811
5170
  throw new ShapeError(`${method} expects data to be an array`);
4812
- if (resolved.body.data.length === 0)
5171
+ }
5172
+ if (resolved.body.data.length === 0) {
4813
5173
  throw new ShapeError(`${method} received empty data array`);
5174
+ }
4814
5175
  const data = resolved.body.data.map(
4815
5176
  (item) => validateAndMergeData(item, dataSchema, method, modelName)
4816
5177
  );
@@ -4844,8 +5205,9 @@ function createModelGuardExtension(config) {
4844
5205
  return (body) => {
4845
5206
  const caller = resolveCaller();
4846
5207
  const resolved = resolveShape(input, body, contextFn, caller);
4847
- if (!resolved.shape.data)
5208
+ if (!resolved.shape.data) {
4848
5209
  throw new ShapeError(`Guard shape requires "data" for ${method}`);
5210
+ }
4849
5211
  validateMutationShapeKeys(
4850
5212
  resolved.shape,
4851
5213
  allowedShapeKeys,
@@ -4924,8 +5286,9 @@ function createModelGuardExtension(config) {
4924
5286
  return (body) => {
4925
5287
  const caller = resolveCaller();
4926
5288
  const resolved = resolveShape(input, body, contextFn, caller);
4927
- if (resolved.shape.data)
5289
+ if (resolved.shape.data) {
4928
5290
  throw new ShapeError(`Guard shape "data" is not valid for ${method}`);
5291
+ }
4929
5292
  validateMutationShapeKeys(
4930
5293
  resolved.shape,
4931
5294
  allowedShapeKeys,