prisma-guard 1.27.1 → 1.28.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.
@@ -1,6 +1,3 @@
1
- // src/runtime/guard.ts
2
- import { ZodError } from "zod";
3
-
4
1
  // src/shared/errors.ts
5
2
  var PolicyError = class extends Error {
6
3
  status = 403;
@@ -30,10 +27,16 @@ function formatIssue(issue) {
30
27
  const path = issue.path.length > 0 ? `${issue.path.join(".")}: ` : "";
31
28
  const code = issue.code;
32
29
  if (code === "invalid_union") {
33
- const unionErrors = issue.unionErrors;
34
- if (unionErrors && unionErrors.length > 0) {
35
- const branches = unionErrors.map((ue, i) => {
36
- const nested = ue.issues.map(formatIssue).join(", ");
30
+ const raw = issue;
31
+ let branchIssues = null;
32
+ if (Array.isArray(raw.errors) && raw.errors.length > 0) {
33
+ branchIssues = raw.errors;
34
+ } else if (Array.isArray(raw.unionErrors) && raw.unionErrors.length > 0) {
35
+ branchIssues = raw.unionErrors.map((ue) => ue.issues);
36
+ }
37
+ if (branchIssues) {
38
+ const branches = branchIssues.map((issues, i) => {
39
+ const nested = issues.map(formatIssue).join(", ");
37
40
  return `branch ${i + 1}: [${nested}]`;
38
41
  }).join(" | ");
39
42
  return `${path}No matching variant (${branches})`;
@@ -52,6 +55,9 @@ function formatIssue(issue) {
52
55
  if (expected && received) {
53
56
  return `${path}Expected ${expected}, received ${received}`;
54
57
  }
58
+ if (expected) {
59
+ return `${path}Expected ${expected}`;
60
+ }
55
61
  }
56
62
  if (code === "invalid_enum_value") {
57
63
  const options = issue.options;
@@ -61,28 +67,28 @@ function formatIssue(issue) {
61
67
  }
62
68
  if (code === "too_small") {
63
69
  const minimum = issue.minimum;
64
- const type = issue.type;
65
- if (type === "string" && minimum !== void 0) {
70
+ const origin = issue.origin ?? issue.type;
71
+ if (origin === "string" && minimum !== void 0) {
66
72
  return `${path}String must contain at least ${minimum} character(s)`;
67
73
  }
68
- if (type === "array" && minimum !== void 0) {
74
+ if (origin === "array" && minimum !== void 0) {
69
75
  return `${path}Array must contain at least ${minimum} element(s)`;
70
76
  }
71
- if (type === "number" && minimum !== void 0) {
77
+ if (origin === "number" && minimum !== void 0) {
72
78
  return `${path}Number must be >= ${minimum}`;
73
79
  }
74
80
  return `${path}${issue.message}`;
75
81
  }
76
82
  if (code === "too_big") {
77
83
  const maximum = issue.maximum;
78
- const type = issue.type;
79
- if (type === "string" && maximum !== void 0) {
84
+ const origin = issue.origin ?? issue.type;
85
+ if (origin === "string" && maximum !== void 0) {
80
86
  return `${path}String must contain at most ${maximum} character(s)`;
81
87
  }
82
- if (type === "array" && maximum !== void 0) {
88
+ if (origin === "array" && maximum !== void 0) {
83
89
  return `${path}Array must contain at most ${maximum} element(s)`;
84
90
  }
85
- if (type === "number" && maximum !== void 0) {
91
+ if (origin === "number" && maximum !== void 0) {
86
92
  return `${path}Number must be <= ${maximum}`;
87
93
  }
88
94
  return `${path}${issue.message}`;
@@ -104,18 +110,42 @@ function formatIssue(issue) {
104
110
  function formatZodError(err) {
105
111
  return err.issues.map(formatIssue).join("; ");
106
112
  }
107
- function wrapParseError(err, context) {
113
+ function isZodErrorLike(err) {
114
+ return !!err && typeof err === "object" && "issues" in err;
115
+ }
116
+ function wrapZod(err, context) {
108
117
  if (err instanceof ShapeError) {
109
118
  throw new ShapeError(`${context}: ${err.message}`, { cause: err });
110
119
  }
111
- if (err && typeof err === "object" && "issues" in err) {
120
+ if (isZodErrorLike(err)) {
112
121
  throw new ShapeError(`${context}: ${formatZodError(err)}`, { cause: err });
113
122
  }
114
123
  throw err;
115
124
  }
125
+ function wrapParseError(err, context) {
126
+ return wrapZod(err, context);
127
+ }
128
+ function toShapeError(err, prefix = "Validation failed") {
129
+ if (isZodErrorLike(err)) {
130
+ return new ShapeError(`${prefix}: ${formatZodError(err)}`, { cause: err });
131
+ }
132
+ return err;
133
+ }
116
134
 
117
135
  // src/shared/scalar-base.ts
118
136
  import { z } from "zod";
137
+ function isPrismaNullSentinel(value) {
138
+ if (value === null || typeof value !== "object")
139
+ return false;
140
+ const tag = value._tag;
141
+ if (tag === "DbNull" || tag === "JsonNull" || tag === "AnyNull")
142
+ return true;
143
+ const constructorName = value.constructor?.name;
144
+ if (constructorName === "DbNull" || constructorName === "JsonNull" || constructorName === "AnyNull") {
145
+ return true;
146
+ }
147
+ return false;
148
+ }
119
149
  function isJsonSafe(value) {
120
150
  const stack = [{ tag: "visit", value }];
121
151
  const ancestors = /* @__PURE__ */ new Set();
@@ -130,6 +160,8 @@ function isJsonSafe(value) {
130
160
  return false;
131
161
  if (current === null)
132
162
  continue;
163
+ if (isPrismaNullSentinel(current))
164
+ continue;
133
165
  switch (typeof current) {
134
166
  case "string":
135
167
  case "boolean":
@@ -214,8 +246,8 @@ function wrapWithInputCoercion(fieldType, isList, schema) {
214
246
  break;
215
247
  case "Int":
216
248
  itemCoercion = z.union([
217
- z.number().transform((v) => Math.trunc(v)).pipe(z.number().int()),
218
- z.string().regex(/^-?\d+(\.\d+)?$/).transform((v) => Math.trunc(Number(v)))
249
+ z.number().int(),
250
+ z.string().regex(/^-?\d+$/).transform((v) => Number(v))
219
251
  ]);
220
252
  break;
221
253
  case "Float":
@@ -232,10 +264,10 @@ function wrapWithInputCoercion(fieldType, isList, schema) {
232
264
  }
233
265
 
234
266
  // src/runtime/schema-builder.ts
235
- import { z as z3 } from "zod";
267
+ import { z as z4 } from "zod";
236
268
 
237
269
  // src/runtime/zod-type-map.ts
238
- import { z as z2 } from "zod";
270
+ import { z as z3 } from "zod";
239
271
 
240
272
  // src/shared/utils.ts
241
273
  function isPlainObject(v) {
@@ -264,7 +296,7 @@ function coerceToArray(value) {
264
296
  const keys = Object.keys(value);
265
297
  if (keys.length === 0)
266
298
  return value;
267
- const allNumeric = keys.every((k) => /^\d+$/.test(k));
299
+ const allNumeric = keys.every((k) => /^\d+$/.test(k) && String(Number(k)) === k);
268
300
  if (!allNumeric)
269
301
  return value;
270
302
  const indices = keys.map(Number).sort((a, b) => a - b);
@@ -280,6 +312,48 @@ function coerceToArray(value) {
280
312
  return result;
281
313
  }
282
314
 
315
+ // src/shared/zod-helpers.ts
316
+ import { z as z2 } from "zod";
317
+ function strictObjectRequiringOne(shape, message) {
318
+ const keys = Object.keys(shape);
319
+ return z2.object(shape).strict().refine(
320
+ (v) => keys.some((k) => v[k] !== void 0),
321
+ { message }
322
+ );
323
+ }
324
+ function singleOrArraySchema(single) {
325
+ return z2.union([
326
+ single,
327
+ z2.preprocess(coerceToArray, z2.array(single).min(1))
328
+ ]);
329
+ }
330
+ function optionalOneOrMany(single) {
331
+ return z2.union([single, z2.preprocess(coerceToArray, z2.array(single))]).optional();
332
+ }
333
+ function wrapRelationOp(isList, single) {
334
+ if (!isList)
335
+ return single.optional();
336
+ return optionalOneOrMany(single);
337
+ }
338
+ function buildLiteralTrueSchema(fieldNames, message, validate) {
339
+ const fieldSchemas = {};
340
+ for (const fieldName of fieldNames) {
341
+ if (validate)
342
+ validate(fieldName);
343
+ fieldSchemas[fieldName] = z2.literal(true).optional();
344
+ }
345
+ return strictObjectRequiringOne(fieldSchemas, message).optional();
346
+ }
347
+ function requireConfigTrue(config, context) {
348
+ for (const [key, value] of Object.entries(config)) {
349
+ if (value !== true) {
350
+ throw new ShapeError(
351
+ `Config value for "${key}" in ${context} must be true, got ${typeof value}`
352
+ );
353
+ }
354
+ }
355
+ }
356
+
283
357
  // src/runtime/zod-type-map.ts
284
358
  var SCALAR_OPERATORS = {
285
359
  String: /* @__PURE__ */ new Set([
@@ -367,13 +441,13 @@ function getSupportedOperators(input, isList = false, isEnum = false) {
367
441
  function createBaseType(fieldMeta, enumMap, scalarBase) {
368
442
  let base;
369
443
  if (fieldMeta.isUnsupported) {
370
- base = z2.unknown();
444
+ base = z3.unknown();
371
445
  } else if (fieldMeta.isEnum) {
372
446
  const values = enumMap[fieldMeta.type];
373
447
  if (!values || values.length === 0) {
374
448
  throw new ShapeError(`Unknown enum: ${fieldMeta.type}`);
375
449
  }
376
- base = z2.enum(values);
450
+ base = z3.enum(values);
377
451
  } else {
378
452
  const factory = scalarBase[fieldMeta.type];
379
453
  if (!factory) {
@@ -382,7 +456,7 @@ function createBaseType(fieldMeta, enumMap, scalarBase) {
382
456
  base = factory();
383
457
  }
384
458
  if (fieldMeta.isList) {
385
- base = z2.array(base);
459
+ base = z3.array(base);
386
460
  }
387
461
  return base;
388
462
  }
@@ -393,35 +467,38 @@ function createScalarListOperatorSchema(fieldMeta, operator, enumMap, scalarBase
393
467
  );
394
468
  }
395
469
  if (operator === "isEmpty") {
396
- return z2.boolean();
470
+ return z3.boolean();
397
471
  }
398
472
  const itemMeta = { ...fieldMeta, isList: false };
399
473
  const itemBase = createBaseType(itemMeta, enumMap, scalarBase);
400
474
  if (operator === "has") {
401
- return !fieldMeta.isRequired ? z2.union([itemBase, z2.null()]) : itemBase;
475
+ return !fieldMeta.isRequired ? z3.union([itemBase, z3.null()]) : itemBase;
402
476
  }
403
477
  if (operator === "equals") {
404
- const arrSchema = z2.array(itemBase);
405
- return fieldMeta.isRequired ? z2.preprocess(coerceToArray, arrSchema) : z2.union([z2.preprocess(coerceToArray, arrSchema), z2.null()]);
478
+ const arrSchema = z3.array(itemBase);
479
+ return fieldMeta.isRequired ? z3.preprocess(coerceToArray, arrSchema) : z3.union([z3.preprocess(coerceToArray, arrSchema), z3.null()]);
406
480
  }
407
- return z2.preprocess(coerceToArray, z2.array(itemBase));
481
+ return z3.preprocess(coerceToArray, z3.array(itemBase));
408
482
  }
409
483
  function createJsonOperatorSchema(fieldMeta, operator) {
410
- const jsonValue = z2.unknown();
484
+ const jsonValue = z3.unknown();
411
485
  if (operator === "equals") {
412
- return !fieldMeta.isRequired ? z2.union([jsonValue, z2.null()]) : jsonValue;
486
+ return !fieldMeta.isRequired ? z3.union([jsonValue, z3.null()]) : jsonValue;
413
487
  }
414
488
  if (operator === "path") {
415
- return z2.preprocess(coerceToArray, z2.array(z2.string()).min(1));
489
+ return z3.preprocess(coerceToArray, z3.array(z3.string()).min(1));
416
490
  }
417
491
  if (JSON_STRING_OPERATORS.has(operator)) {
418
- return z2.string();
492
+ return z3.string();
419
493
  }
420
494
  if (JSON_ARRAY_OPERATORS.has(operator)) {
421
495
  return jsonValue;
422
496
  }
423
497
  throw new ShapeError(`Operator "${operator}" not supported for Json fields`);
424
498
  }
499
+ function nullableIfOptional(fieldMeta, base) {
500
+ return !fieldMeta.isRequired ? z3.union([base, z3.null()]) : base;
501
+ }
425
502
  function buildNotFilterSchema(fieldMeta, scalarSchema, enumMap, scalarBase) {
426
503
  const allOps = getSupportedOperators(fieldMeta);
427
504
  const nestedOps = allOps.filter((op) => op !== "not");
@@ -437,14 +514,15 @@ function buildNotFilterSchema(fieldMeta, scalarSchema, enumMap, scalarBase) {
437
514
  scalarBase
438
515
  ).optional();
439
516
  }
440
- const nestedKeys = Object.keys(nestedSchemas);
441
- const nestedObj = z2.object(nestedSchemas).strict().refine(
442
- (value) => nestedKeys.some(
443
- (key) => value[key] !== void 0
444
- ),
445
- { message: "not filter must specify at least one operator" }
517
+ const nestedObj = strictObjectRequiringOne(
518
+ nestedSchemas,
519
+ "not filter must specify at least one operator"
446
520
  );
447
- return z2.union([scalarSchema, nestedObj]);
521
+ return z3.union([scalarSchema, nestedObj]);
522
+ }
523
+ function buildNotOperator(fieldMeta, scalarBaseSchema, enumMap, scalarBase) {
524
+ const scalarSchema = nullableIfOptional(fieldMeta, scalarBaseSchema);
525
+ return buildNotFilterSchema(fieldMeta, scalarSchema, enumMap, scalarBase);
448
526
  }
449
527
  function createOperatorSchema(fieldMeta, operator, enumMap, scalarBase) {
450
528
  const allowedOps = getSupportedOperators(fieldMeta);
@@ -481,32 +559,19 @@ function createOperatorSchema(fieldMeta, operator, enumMap, scalarBase) {
481
559
  if (!values || values.length === 0) {
482
560
  throw new ShapeError(`Unknown enum: ${fieldMeta.type}`);
483
561
  }
484
- const enumSchema = z2.enum(values);
562
+ const enumSchema = z3.enum(values);
485
563
  if (operator === "equals") {
486
- return !fieldMeta.isRequired ? z2.union([enumSchema, z2.null()]) : enumSchema;
564
+ return nullableIfOptional(fieldMeta, enumSchema);
487
565
  }
488
566
  if (operator === "not") {
489
- const scalarSchema = !fieldMeta.isRequired ? z2.union([enumSchema, z2.null()]) : enumSchema;
490
- return buildNotFilterSchema(
491
- fieldMeta,
492
- scalarSchema,
493
- enumMap,
494
- scalarBase
495
- );
567
+ return buildNotOperator(fieldMeta, enumSchema, enumMap, scalarBase);
496
568
  }
497
- const itemSchema = !fieldMeta.isRequired ? z2.union([enumSchema, z2.null()]) : enumSchema;
498
- return z2.preprocess(coerceToArray, z2.array(itemSchema));
569
+ const itemSchema = nullableIfOptional(fieldMeta, enumSchema);
570
+ return z3.preprocess(coerceToArray, z3.array(itemSchema));
499
571
  }
500
572
  if (fieldMeta.type === "Json") {
501
573
  if (operator === "not") {
502
- const jsonValue = z2.unknown();
503
- const scalarSchema = !fieldMeta.isRequired ? z2.union([jsonValue, z2.null()]) : jsonValue;
504
- return buildNotFilterSchema(
505
- fieldMeta,
506
- scalarSchema,
507
- enumMap,
508
- scalarBase
509
- );
574
+ return buildNotOperator(fieldMeta, z3.unknown(), enumMap, scalarBase);
510
575
  }
511
576
  return createJsonOperatorSchema(fieldMeta, operator);
512
577
  }
@@ -517,15 +582,14 @@ function createOperatorSchema(fieldMeta, operator, enumMap, scalarBase) {
517
582
  const scalar = factory();
518
583
  const coerced = wrapWithInputCoercion(fieldMeta.type, false, scalar);
519
584
  if (operator === "equals") {
520
- return !fieldMeta.isRequired ? z2.union([coerced, z2.null()]) : coerced;
585
+ return nullableIfOptional(fieldMeta, coerced);
521
586
  }
522
587
  if (operator === "not") {
523
- const scalarSchema = !fieldMeta.isRequired ? z2.union([coerced, z2.null()]) : coerced;
524
- return buildNotFilterSchema(fieldMeta, scalarSchema, enumMap, scalarBase);
588
+ return buildNotOperator(fieldMeta, coerced, enumMap, scalarBase);
525
589
  }
526
590
  if (operator === "in" || operator === "notIn") {
527
- const itemSchema = !fieldMeta.isRequired ? z2.union([coerced, z2.null()]) : coerced;
528
- return z2.preprocess(coerceToArray, z2.array(itemSchema));
591
+ const itemSchema = nullableIfOptional(fieldMeta, coerced);
592
+ return z3.preprocess(coerceToArray, z3.array(itemSchema));
529
593
  }
530
594
  return coerced;
531
595
  }
@@ -551,6 +615,26 @@ function lruSet(cache, key, value, maxSize) {
551
615
  cache.delete(oldest);
552
616
  }
553
617
  }
618
+ function applyCreateUpdateNullability(fieldMeta, fieldSchema, options) {
619
+ const { mode, handlesUndefined } = options;
620
+ const allowNull = options.allowNull ?? true;
621
+ if (mode === "create") {
622
+ if (!fieldMeta.isRequired) {
623
+ if (handlesUndefined) {
624
+ return allowNull ? fieldSchema.nullable() : fieldSchema;
625
+ }
626
+ return allowNull ? fieldSchema.nullable().optional() : fieldSchema.optional();
627
+ }
628
+ if (fieldMeta.hasDefault) {
629
+ return handlesUndefined ? fieldSchema : fieldSchema.optional();
630
+ }
631
+ return fieldSchema;
632
+ }
633
+ if (!fieldMeta.isRequired && allowNull) {
634
+ return fieldSchema.nullable().optional();
635
+ }
636
+ return fieldSchema.optional();
637
+ }
554
638
  function createSchemaBuilder(typeMap, zodChains, enumMap, scalarBase, zodDefaults) {
555
639
  const chainCache = /* @__PURE__ */ new Map();
556
640
  function buildFieldSchema(model, field) {
@@ -605,20 +689,25 @@ function createSchemaBuilder(typeMap, zodChains, enumMap, scalarBase, zodDefault
605
689
  const zodDefaultSet = zodDefaultFields ? new Set(zodDefaultFields) : void 0;
606
690
  let fieldNames = Object.keys(modelFields).filter((name) => {
607
691
  const meta = modelFields[name];
608
- return !meta.isRelation && !meta.isUpdatedAt;
692
+ return !meta.isRelation && !meta.isUpdatedAt && !meta.isUnsupported;
609
693
  });
610
694
  if (opts.pick) {
611
695
  for (const name of opts.pick) {
612
- if (!modelFields[name])
696
+ const meta = modelFields[name];
697
+ if (!meta)
613
698
  throw new ShapeError(`Unknown field "${name}" on model "${model}"`);
614
- if (modelFields[name].isRelation)
699
+ if (meta.isRelation)
615
700
  throw new ShapeError(
616
701
  `Field "${name}" cannot be used in input schema (relation field)`
617
702
  );
618
- if (modelFields[name].isUpdatedAt)
703
+ if (meta.isUpdatedAt)
619
704
  throw new ShapeError(
620
705
  `Field "${name}" cannot be used in input schema (updatedAt field)`
621
706
  );
707
+ if (meta.isUnsupported)
708
+ throw new ShapeError(
709
+ `Field "${name}" on model "${model}" has an Unsupported type and cannot be used in input schema`
710
+ );
622
711
  }
623
712
  fieldNames = fieldNames.filter((n) => opts.pick.includes(n));
624
713
  } else if (opts.omit) {
@@ -631,7 +720,7 @@ function createSchemaBuilder(typeMap, zodChains, enumMap, scalarBase, zodDefault
631
720
  const schemaMap = {};
632
721
  for (const name of fieldNames) {
633
722
  const fieldMeta = modelFields[name];
634
- let fieldSchema;
723
+ let baseSchema;
635
724
  let handlesUndefined;
636
725
  if (opts.refine?.[name]) {
637
726
  let refined;
@@ -648,34 +737,19 @@ function createSchemaBuilder(typeMap, zodChains, enumMap, scalarBase, zodDefault
648
737
  `Refine function for "${model}.${name}" must return a Zod schema`
649
738
  );
650
739
  }
651
- fieldSchema = refined;
652
- handlesUndefined = schemaProducesValueForUndefined(fieldSchema);
740
+ baseSchema = refined;
741
+ handlesUndefined = schemaProducesValueForUndefined(baseSchema);
653
742
  } else {
654
- fieldSchema = buildFieldSchema(model, name);
743
+ baseSchema = buildFieldSchema(model, name);
655
744
  handlesUndefined = zodDefaultSet !== void 0 && zodDefaultSet.has(name);
656
745
  }
657
- if (mode === "create") {
658
- if (!fieldMeta.isRequired) {
659
- if (handlesUndefined) {
660
- fieldSchema = allowNull ? fieldSchema.nullable() : fieldSchema;
661
- } else {
662
- fieldSchema = allowNull ? fieldSchema.nullable().optional() : fieldSchema.optional();
663
- }
664
- } else if (fieldMeta.hasDefault) {
665
- if (!handlesUndefined) {
666
- fieldSchema = fieldSchema.optional();
667
- }
668
- }
669
- } else {
670
- if (!fieldMeta.isRequired && allowNull) {
671
- fieldSchema = fieldSchema.nullable().optional();
672
- } else {
673
- fieldSchema = fieldSchema.optional();
674
- }
675
- }
676
- schemaMap[name] = fieldSchema;
746
+ schemaMap[name] = applyCreateUpdateNullability(fieldMeta, baseSchema, {
747
+ mode,
748
+ handlesUndefined,
749
+ allowNull
750
+ });
677
751
  }
678
- let schema = z3.object(schemaMap).strict();
752
+ let schema = z4.object(schemaMap).strict();
679
753
  if (opts.partial) {
680
754
  schema = schema.partial();
681
755
  }
@@ -702,13 +776,18 @@ function createSchemaBuilder(typeMap, zodChains, enumMap, scalarBase, zodDefault
702
776
  const includeKeys = new Set(Object.keys(opts.include ?? {}));
703
777
  if (opts.pick) {
704
778
  for (const name of opts.pick) {
705
- if (!modelFields[name])
779
+ const meta = modelFields[name];
780
+ if (!meta)
706
781
  throw new ShapeError(`Unknown field "${name}" on model "${model}"`);
707
- if (modelFields[name].isRelation && !includeKeys.has(name)) {
782
+ if (meta.isRelation && !includeKeys.has(name)) {
708
783
  throw new ShapeError(
709
784
  `Field "${name}" is a relation on model "${model}". Use include: { ${name}: ... } instead of pick.`
710
785
  );
711
786
  }
787
+ if (meta.isUnsupported)
788
+ throw new ShapeError(
789
+ `Field "${name}" on model "${model}" has an Unsupported type and cannot be used in output schema`
790
+ );
712
791
  }
713
792
  }
714
793
  if (opts.omit) {
@@ -719,7 +798,7 @@ function createSchemaBuilder(typeMap, zodChains, enumMap, scalarBase, zodDefault
719
798
  }
720
799
  let scalarNames = Object.keys(modelFields).filter((name) => {
721
800
  const meta = modelFields[name];
722
- return !meta.isRelation;
801
+ return !meta.isRelation && !meta.isUnsupported;
723
802
  });
724
803
  if (opts.pick) {
725
804
  scalarNames = scalarNames.filter((n) => opts.pick.includes(n));
@@ -756,7 +835,7 @@ function createSchemaBuilder(typeMap, zodChains, enumMap, scalarBase, zodDefault
756
835
  effectiveMaxDepth
757
836
  );
758
837
  if (fieldMeta.isList) {
759
- relSchema = z3.array(relSchema);
838
+ relSchema = z4.array(relSchema);
760
839
  } else if (!fieldMeta.isRequired) {
761
840
  relSchema = relSchema.nullable();
762
841
  }
@@ -769,9 +848,9 @@ function createSchemaBuilder(typeMap, zodChains, enumMap, scalarBase, zodDefault
769
848
  if (opts._count === true) {
770
849
  const countFields = {};
771
850
  for (const relName of listRelationNames) {
772
- countFields[relName] = z3.number().int().min(0);
851
+ countFields[relName] = z4.number().int().min(0);
773
852
  }
774
- schemaMap["_count"] = z3.object(countFields);
853
+ schemaMap["_count"] = z4.object(countFields);
775
854
  } else {
776
855
  const countFields = {};
777
856
  for (const relName of Object.keys(opts._count)) {
@@ -787,12 +866,12 @@ function createSchemaBuilder(typeMap, zodChains, enumMap, scalarBase, zodDefault
787
866
  throw new ShapeError(
788
867
  `Field "${relName}" is a to-one relation on model "${model}" in _count. Only to-many relations support _count.`
789
868
  );
790
- countFields[relName] = z3.number().int().min(0);
869
+ countFields[relName] = z4.number().int().min(0);
791
870
  }
792
- schemaMap["_count"] = z3.object(countFields);
871
+ schemaMap["_count"] = z4.object(countFields);
793
872
  }
794
873
  }
795
- let schema = z3.object(schemaMap);
874
+ let schema = z4.object(schemaMap);
796
875
  if (opts.strict) {
797
876
  schema = schema.strict();
798
877
  }
@@ -807,7 +886,7 @@ function createSchemaBuilder(typeMap, zodChains, enumMap, scalarBase, zodDefault
807
886
  }
808
887
 
809
888
  // src/runtime/query-builder.ts
810
- import { z as z7 } from "zod";
889
+ import { z as z8 } from "zod";
811
890
 
812
891
  // src/shared/constants.ts
813
892
  var SHAPE_CONFIG_KEY_LIST = [
@@ -863,6 +942,8 @@ function unsupported() {
863
942
 
864
943
  // src/shared/match-caller.ts
865
944
  function matchCallerPattern(patterns, caller) {
945
+ if (typeof caller !== "string" || caller.trim().length === 0)
946
+ return null;
866
947
  if (patterns.includes(caller))
867
948
  return caller;
868
949
  const matches = [];
@@ -916,7 +997,7 @@ function validateContext(ctx) {
916
997
  }
917
998
 
918
999
  // src/runtime/query-builder-where.ts
919
- import { z as z4 } from "zod";
1000
+ import { z as z5 } from "zod";
920
1001
 
921
1002
  // src/shared/deep-clone.ts
922
1003
  function deepClone(value) {
@@ -951,44 +1032,75 @@ function deepClone(value) {
951
1032
  }
952
1033
  }
953
1034
 
954
- // src/runtime/query-builder-forced.ts
955
- var EMPTY_WHERE_FORCED = {
956
- conditions: {},
957
- relations: {}
958
- };
959
- function hasWhereForced(f) {
960
- return Object.keys(f.conditions).length > 0 || Object.keys(f.relations).length > 0;
961
- }
962
- function forcedScalarsEqual(a, b) {
1035
+ // src/shared/deep-equal.ts
1036
+ function deepEqual(a, b) {
963
1037
  if (a === b)
964
1038
  return true;
965
1039
  if (a === null || b === null)
966
1040
  return false;
967
- if (typeof a !== typeof b)
1041
+ if (a === void 0 || b === void 0)
1042
+ return false;
1043
+ const ta = typeof a;
1044
+ const tb = typeof b;
1045
+ if (ta !== tb)
1046
+ return false;
1047
+ if (ta === "bigint")
1048
+ return a === b;
1049
+ if (ta !== "object")
968
1050
  return false;
969
1051
  if (a instanceof Date && b instanceof Date) {
970
1052
  return a.getTime() === b.getTime();
971
1053
  }
1054
+ if (a instanceof Date || b instanceof Date)
1055
+ return false;
972
1056
  if (a instanceof RegExp && b instanceof RegExp) {
973
1057
  return a.source === b.source && a.flags === b.flags;
974
1058
  }
1059
+ if (a instanceof RegExp || b instanceof RegExp)
1060
+ return false;
975
1061
  if (Array.isArray(a)) {
976
1062
  if (!Array.isArray(b))
977
1063
  return false;
978
1064
  if (a.length !== b.length)
979
1065
  return false;
980
- return a.every((v, i) => forcedScalarsEqual(v, b[i]));
1066
+ for (let i = 0; i < a.length; i++) {
1067
+ if (!deepEqual(a[i], b[i]))
1068
+ return false;
1069
+ }
1070
+ return true;
981
1071
  }
982
- if (isPlainObject(a) && isPlainObject(b)) {
983
- const aKeys = Object.keys(a);
984
- const bKeys = Object.keys(b);
985
- if (aKeys.length !== bKeys.length)
1072
+ if (Array.isArray(b))
1073
+ return false;
1074
+ if (!isPlainObject(a) || !isPlainObject(b))
1075
+ return false;
1076
+ const aKeys = Object.keys(a);
1077
+ const bKeys = Object.keys(b);
1078
+ if (aKeys.length !== bKeys.length)
1079
+ return false;
1080
+ for (const key of aKeys) {
1081
+ if (!(key in b))
1082
+ return false;
1083
+ if (!deepEqual(a[key], b[key]))
986
1084
  return false;
987
- return aKeys.every(
988
- (k) => k in b && forcedScalarsEqual(a[k], b[k])
989
- );
990
1085
  }
991
- return false;
1086
+ return true;
1087
+ }
1088
+
1089
+ // src/shared/unique-constraints.ts
1090
+ function formatUniqueConstraint(constraint) {
1091
+ return constraint.fields.length === 1 ? constraint.selector : `${constraint.selector}(${constraint.fields.join(", ")})`;
1092
+ }
1093
+ function formatUniqueConstraints(constraints) {
1094
+ return constraints.map(formatUniqueConstraint).join(" | ");
1095
+ }
1096
+
1097
+ // src/runtime/query-builder-forced.ts
1098
+ var EMPTY_WHERE_FORCED = {
1099
+ conditions: {},
1100
+ relations: {}
1101
+ };
1102
+ function hasWhereForced(f) {
1103
+ return Object.keys(f.conditions).length > 0 || Object.keys(f.relations).length > 0;
992
1104
  }
993
1105
  function tryInlineForcedField(result, field, forcedValue) {
994
1106
  if (!(field in result))
@@ -1007,7 +1119,7 @@ function tryInlineForcedField(result, field, forcedValue) {
1007
1119
  const merged = { ...existing };
1008
1120
  for (const [op, value] of Object.entries(forcedValue)) {
1009
1121
  if (op in merged) {
1010
- if (!forcedScalarsEqual(merged[op], value)) {
1122
+ if (!deepEqual(merged[op], value)) {
1011
1123
  throw new ShapeError(
1012
1124
  `Conflicting where values for "${field}.${op}": client provided a different value than the forced shape`
1013
1125
  );
@@ -1038,6 +1150,17 @@ function mergeWhereForced(where, forced) {
1038
1150
  if (Object.keys(forced.conditions).length > 0) {
1039
1151
  const remaining = {};
1040
1152
  for (const [field, forcedValue] of Object.entries(forced.conditions)) {
1153
+ if (field === "NOT") {
1154
+ const existing = result[field];
1155
+ const forcedArr = Array.isArray(forcedValue) ? forcedValue.map(deepClone) : [deepClone(forcedValue)];
1156
+ if (existing === void 0) {
1157
+ result[field] = forcedArr.length === 1 ? forcedArr[0] : forcedArr;
1158
+ } else {
1159
+ const existingArr = Array.isArray(existing) ? existing : [existing];
1160
+ result[field] = [...existingArr, ...forcedArr];
1161
+ }
1162
+ continue;
1163
+ }
1041
1164
  const inlined = tryInlineForcedField(result, field, forcedValue);
1042
1165
  if (!inlined) {
1043
1166
  remaining[field] = deepClone(forcedValue);
@@ -1053,32 +1176,6 @@ function mergeWhereForced(where, forced) {
1053
1176
  }
1054
1177
  return result;
1055
1178
  }
1056
- function uniqueValuesEqual(a, b) {
1057
- if (a === b)
1058
- return true;
1059
- if (a === null || b === null)
1060
- return false;
1061
- if (typeof a !== typeof b)
1062
- return false;
1063
- if (a instanceof Date && b instanceof Date) {
1064
- return a.getTime() === b.getTime();
1065
- }
1066
- if (Array.isArray(a)) {
1067
- if (!Array.isArray(b))
1068
- return false;
1069
- if (a.length !== b.length)
1070
- return false;
1071
- return a.every((v, i) => uniqueValuesEqual(v, b[i]));
1072
- }
1073
- if (isPlainObject(a) && isPlainObject(b)) {
1074
- const aKeys = Object.keys(a);
1075
- const bKeys = Object.keys(b);
1076
- if (aKeys.length !== bKeys.length)
1077
- return false;
1078
- return aKeys.every((key) => key in b && uniqueValuesEqual(a[key], b[key]));
1079
- }
1080
- return false;
1081
- }
1082
1179
  function mergeUniqueValue(target, key, value) {
1083
1180
  const cloned = deepClone(value);
1084
1181
  if (!(key in target)) {
@@ -1089,7 +1186,7 @@ function mergeUniqueValue(target, key, value) {
1089
1186
  if (isPlainObject(existing) && isPlainObject(cloned)) {
1090
1187
  const merged = { ...existing };
1091
1188
  for (const [nestedKey, nestedValue] of Object.entries(cloned)) {
1092
- if (nestedKey in merged && !uniqueValuesEqual(merged[nestedKey], nestedValue)) {
1189
+ if (nestedKey in merged && !deepEqual(merged[nestedKey], nestedValue)) {
1093
1190
  throw new ShapeError(
1094
1191
  `Conflicting unique where value for "${key}.${nestedKey}"`
1095
1192
  );
@@ -1099,7 +1196,7 @@ function mergeUniqueValue(target, key, value) {
1099
1196
  target[key] = merged;
1100
1197
  return;
1101
1198
  }
1102
- if (!uniqueValuesEqual(existing, cloned)) {
1199
+ if (!deepEqual(existing, cloned)) {
1103
1200
  throw new ShapeError(`Conflicting unique where value for "${key}"`);
1104
1201
  }
1105
1202
  }
@@ -1126,7 +1223,30 @@ function applyBuiltShape(built, body, isUniqueMethod, modelName) {
1126
1223
  throw new ShapeError('Request cannot define both "include" and "select"');
1127
1224
  }
1128
1225
  if ("where" in bodyObj) {
1129
- if (!hasWhereInSchema) {
1226
+ if (bodyObj.where === void 0 || bodyObj.where === null) {
1227
+ const { where: _, ...rest } = bodyObj;
1228
+ parseable = rest;
1229
+ } else if (!hasWhereInSchema) {
1230
+ const context = modelName ? ` on model "${modelName}"` : "";
1231
+ if (!hasWhereForced(built.forcedWhere)) {
1232
+ throw new ShapeError(
1233
+ `Guard shape does not allow "where"${context}`
1234
+ );
1235
+ }
1236
+ if (!isPlainObject(bodyObj.where)) {
1237
+ throw new ShapeError(
1238
+ `Invalid "where"${context}: must be a plain object`
1239
+ );
1240
+ }
1241
+ const remaining = stripUniqueWhereForcedInput(
1242
+ bodyObj.where,
1243
+ built.forcedWhere
1244
+ );
1245
+ if (Object.keys(remaining).length > 0) {
1246
+ throw new ShapeError(
1247
+ `Guard shape where${context} contains only forced conditions. Client where input is not accepted.`
1248
+ );
1249
+ }
1130
1250
  const { where: _, ...rest } = bodyObj;
1131
1251
  parseable = rest;
1132
1252
  } else if (isUniqueMethod && hasWhereForced(built.forcedWhere) && isPlainObject(bodyObj.where)) {
@@ -1202,6 +1322,86 @@ function buildCountForPlacement(countWhere) {
1202
1322
  }
1203
1323
  return { _count: { select: countSelect } };
1204
1324
  }
1325
+ function collectSubtree(forced) {
1326
+ const nested = {};
1327
+ if (forced.where && hasWhereForced(forced.where)) {
1328
+ nested.where = mergeWhereForced(void 0, forced.where);
1329
+ }
1330
+ if (forced.include) {
1331
+ nested.include = buildForcedOnlyContainer(forced.include);
1332
+ }
1333
+ if (forced.select) {
1334
+ nested.select = buildForcedOnlyContainer(forced.select);
1335
+ }
1336
+ if (forced._countWhere && Object.keys(forced._countWhere).length > 0) {
1337
+ const placement = forced._countWherePlacement ?? "include";
1338
+ if (!nested[placement])
1339
+ nested[placement] = {};
1340
+ const placementObj = nested[placement];
1341
+ Object.assign(placementObj, buildCountForPlacement(forced._countWhere));
1342
+ }
1343
+ return nested;
1344
+ }
1345
+ function applyForcedToRelValue(relName, relVal, forced) {
1346
+ if (relVal === true) {
1347
+ const expanded = collectSubtree(forced);
1348
+ if (forced.include) {
1349
+ applyForcedTree(expanded, "include", forced.include);
1350
+ }
1351
+ if (forced.select) {
1352
+ applyForcedTree(expanded, "select", forced.select);
1353
+ }
1354
+ if (expanded.include && expanded.select) {
1355
+ throw new ShapeError(
1356
+ `Forced tree for relation "${relName}" produces both "include" and "select". Prisma does not allow both at the same level.`
1357
+ );
1358
+ }
1359
+ return Object.keys(expanded).length > 0 ? expanded : true;
1360
+ }
1361
+ if (!isPlainObject(relVal))
1362
+ return relVal;
1363
+ const relObj = relVal;
1364
+ if (forced.where && hasWhereForced(forced.where)) {
1365
+ relObj.where = mergeWhereForced(
1366
+ relObj.where,
1367
+ forced.where
1368
+ );
1369
+ }
1370
+ if (forced.include) {
1371
+ if (!relObj.include) {
1372
+ relObj.include = buildForcedOnlyContainer(forced.include);
1373
+ }
1374
+ applyForcedTree(relObj, "include", forced.include);
1375
+ }
1376
+ if (forced.select) {
1377
+ if (!relObj.select) {
1378
+ relObj.select = buildForcedOnlyContainer(forced.select);
1379
+ }
1380
+ applyForcedTree(relObj, "select", forced.select);
1381
+ }
1382
+ if (forced._countWhere && Object.keys(forced._countWhere).length > 0) {
1383
+ const placement = forced._countWherePlacement ?? "include";
1384
+ const existing = relObj[placement];
1385
+ let placementObj;
1386
+ if (!isPlainObject(existing)) {
1387
+ placementObj = {};
1388
+ relObj[placement] = placementObj;
1389
+ } else {
1390
+ placementObj = existing;
1391
+ }
1392
+ if (!("_count" in placementObj)) {
1393
+ Object.assign(placementObj, buildCountForPlacement(forced._countWhere));
1394
+ } else {
1395
+ applyForcedCountWhere(placementObj, forced._countWhere);
1396
+ }
1397
+ }
1398
+ if (relObj.include && relObj.select) {
1399
+ throw new ShapeError(
1400
+ `Relation "${relName}" has both "include" and "select" after forced tree merge. Prisma does not allow both at the same level.`
1401
+ );
1402
+ }
1403
+ return relObj;
1404
+ }
1205
1405
  function applyForcedTree(validated, key, tree) {
1206
1406
  const container = validated[key];
1207
1407
  if (!container)
@@ -1210,89 +1410,13 @@ function applyForcedTree(validated, key, tree) {
1210
1410
  const relVal = container[relName];
1211
1411
  if (relVal === void 0)
1212
1412
  continue;
1213
- if (relVal === true) {
1214
- const expanded = {};
1215
- if (forced.where && hasWhereForced(forced.where)) {
1216
- expanded.where = mergeWhereForced(void 0, forced.where);
1217
- }
1218
- if (forced.include) {
1219
- expanded.include = buildForcedOnlyContainer(forced.include);
1220
- applyForcedTree(expanded, "include", forced.include);
1221
- }
1222
- if (forced.select) {
1223
- expanded.select = buildForcedOnlyContainer(forced.select);
1224
- applyForcedTree(expanded, "select", forced.select);
1225
- }
1226
- if (forced._countWhere && Object.keys(forced._countWhere).length > 0) {
1227
- const placement = forced._countWherePlacement ?? "include";
1228
- if (!expanded[placement])
1229
- expanded[placement] = {};
1230
- const placementObj = expanded[placement];
1231
- Object.assign(placementObj, buildCountForPlacement(forced._countWhere));
1232
- }
1233
- if (expanded.include && expanded.select) {
1234
- throw new ShapeError(
1235
- `Forced tree for relation "${relName}" produces both "include" and "select". Prisma does not allow both at the same level.`
1236
- );
1237
- }
1238
- container[relName] = Object.keys(expanded).length > 0 ? expanded : true;
1239
- continue;
1240
- }
1241
- if (isPlainObject(relVal)) {
1242
- const relObj = relVal;
1243
- if (forced.where && hasWhereForced(forced.where)) {
1244
- relObj.where = mergeWhereForced(
1245
- relObj.where,
1246
- forced.where
1247
- );
1248
- }
1249
- if (forced.include) {
1250
- if (!relObj.include) {
1251
- relObj.include = buildForcedOnlyContainer(forced.include);
1252
- }
1253
- applyForcedTree(relObj, "include", forced.include);
1254
- }
1255
- if (forced.select) {
1256
- if (!relObj.select) {
1257
- relObj.select = buildForcedOnlyContainer(forced.select);
1258
- }
1259
- applyForcedTree(relObj, "select", forced.select);
1260
- }
1261
- if (forced._countWhere && Object.keys(forced._countWhere).length > 0) {
1262
- const placement = forced._countWherePlacement ?? "include";
1263
- const projContainer = relObj[placement];
1264
- if (projContainer) {
1265
- applyForcedCountWhere(projContainer, forced._countWhere);
1266
- }
1267
- }
1268
- if (relObj.include && relObj.select) {
1269
- throw new ShapeError(
1270
- `Relation "${relName}" has both "include" and "select" after forced tree merge. Prisma does not allow both at the same level.`
1271
- );
1272
- }
1273
- }
1413
+ container[relName] = applyForcedToRelValue(relName, relVal, forced);
1274
1414
  }
1275
1415
  }
1276
1416
  function buildForcedOnlyContainer(tree) {
1277
1417
  const result = {};
1278
1418
  for (const [relName, forced] of Object.entries(tree)) {
1279
- const nested = {};
1280
- if (forced.where && hasWhereForced(forced.where)) {
1281
- nested.where = mergeWhereForced(void 0, forced.where);
1282
- }
1283
- if (forced.include) {
1284
- nested.include = buildForcedOnlyContainer(forced.include);
1285
- }
1286
- if (forced.select) {
1287
- nested.select = buildForcedOnlyContainer(forced.select);
1288
- }
1289
- if (forced._countWhere && Object.keys(forced._countWhere).length > 0) {
1290
- const placement = forced._countWherePlacement ?? "include";
1291
- if (!nested[placement])
1292
- nested[placement] = {};
1293
- const placementObj = nested[placement];
1294
- Object.assign(placementObj, buildCountForPlacement(forced._countWhere));
1295
- }
1419
+ const nested = collectSubtree(forced);
1296
1420
  result[relName] = Object.keys(nested).length > 0 ? nested : true;
1297
1421
  }
1298
1422
  return result;
@@ -1308,11 +1432,15 @@ function applyForcedCountWhere(container, forcedCountWhere) {
1308
1432
  const selectObj = selectVal;
1309
1433
  for (const [relName, forced] of Object.entries(forcedCountWhere)) {
1310
1434
  const relVal = selectObj[relName];
1311
- if (relVal === void 0)
1435
+ if (relVal === void 0) {
1436
+ selectObj[relName] = { where: mergeWhereForced(void 0, forced) };
1312
1437
  continue;
1438
+ }
1313
1439
  if (relVal === true) {
1314
1440
  selectObj[relName] = { where: mergeWhereForced(void 0, forced) };
1315
- } else if (isPlainObject(relVal)) {
1441
+ continue;
1442
+ }
1443
+ if (isPlainObject(relVal)) {
1316
1444
  const relObj = relVal;
1317
1445
  relObj.where = mergeWhereForced(
1318
1446
  relObj.where,
@@ -1321,12 +1449,6 @@ function applyForcedCountWhere(container, forcedCountWhere) {
1321
1449
  }
1322
1450
  }
1323
1451
  }
1324
- function formatUniqueConstraint(constraint) {
1325
- return constraint.fields.length === 1 ? constraint.selector : `${constraint.selector}(${constraint.fields.join(", ")})`;
1326
- }
1327
- function formatUniqueConstraints(constraints) {
1328
- return constraints.map(formatUniqueConstraint).join(" | ");
1329
- }
1330
1452
  function resolvedWhereCoversConstraint(where, constraint) {
1331
1453
  if (constraint.fields.length === 1) {
1332
1454
  return constraint.fields[0] in where;
@@ -1432,7 +1554,12 @@ function stripUniqueWhereForcedInput(where, forced) {
1432
1554
  const currentValue = result[key];
1433
1555
  if (isPlainObject(currentValue) && isPlainObject(forcedValue)) {
1434
1556
  const nested = { ...currentValue };
1435
- for (const nestedKey of Object.keys(forcedValue)) {
1557
+ for (const [nestedKey, nestedForcedValue] of Object.entries(forcedValue)) {
1558
+ if (nestedKey in nested && !deepEqual(nested[nestedKey], nestedForcedValue)) {
1559
+ throw new ShapeError(
1560
+ `Client unique where value for "${key}.${nestedKey}" conflicts with forced value`
1561
+ );
1562
+ }
1436
1563
  delete nested[nestedKey];
1437
1564
  }
1438
1565
  if (Object.keys(nested).length === 0) {
@@ -1442,11 +1569,25 @@ function stripUniqueWhereForcedInput(where, forced) {
1442
1569
  }
1443
1570
  continue;
1444
1571
  }
1572
+ if (!deepEqual(currentValue, forcedValue)) {
1573
+ throw new ShapeError(
1574
+ `Client unique where value for "${key}" conflicts with forced value`
1575
+ );
1576
+ }
1445
1577
  delete result[key];
1446
1578
  }
1447
1579
  return result;
1448
1580
  }
1449
1581
 
1582
+ // src/runtime/direct-scalar-schema.ts
1583
+ function buildDirectScalarSchema(fieldMeta, enumMap, scalarBase) {
1584
+ const base = createBaseType(fieldMeta, enumMap, scalarBase);
1585
+ if (!fieldMeta.isEnum && !fieldMeta.isRelation && !fieldMeta.isUnsupported) {
1586
+ return wrapWithInputCoercion(fieldMeta.type, fieldMeta.isList, base);
1587
+ }
1588
+ return base;
1589
+ }
1590
+
1450
1591
  // src/runtime/query-builder-where.ts
1451
1592
  var UNSUPPORTED_WHERE_TYPES = /* @__PURE__ */ new Set(["Bytes"]);
1452
1593
  var STRING_MODE_OPS = /* @__PURE__ */ new Set([
@@ -1460,47 +1601,40 @@ var JSON_STRING_MODE_OPS = /* @__PURE__ */ new Set([
1460
1601
  "string_starts_with",
1461
1602
  "string_ends_with"
1462
1603
  ]);
1604
+ var NEGATIVE_RELATION_OPS = /* @__PURE__ */ new Set(["none", "isNot"]);
1463
1605
  var MAX_WHERE_DEPTH = 10;
1464
- function safeStringify(v) {
1465
- if (typeof v === "bigint")
1466
- return `${v}n`;
1606
+ function safeStringify(value) {
1607
+ if (typeof value === "bigint")
1608
+ return `${value}n`;
1609
+ if (typeof value === "undefined")
1610
+ return "undefined";
1611
+ if (typeof value === "function")
1612
+ return "[function]";
1613
+ if (typeof value === "symbol")
1614
+ return value.toString();
1615
+ const seen = /* @__PURE__ */ new WeakSet();
1467
1616
  try {
1468
- return JSON.stringify(v);
1617
+ const json = JSON.stringify(value, (_key, current) => {
1618
+ if (typeof current === "bigint")
1619
+ return `${current}n`;
1620
+ if (typeof current === "undefined")
1621
+ return "[undefined]";
1622
+ if (typeof current === "function")
1623
+ return "[function]";
1624
+ if (typeof current === "symbol")
1625
+ return current.toString();
1626
+ if (current && typeof current === "object") {
1627
+ if (seen.has(current))
1628
+ return "[Circular]";
1629
+ seen.add(current);
1630
+ }
1631
+ return current;
1632
+ });
1633
+ return json === void 0 ? String(value) : json;
1469
1634
  } catch {
1470
- return String(v);
1635
+ return String(value);
1471
1636
  }
1472
1637
  }
1473
- function forcedValuesEqual(a, b) {
1474
- if (a === b)
1475
- return true;
1476
- if (a === null || b === null)
1477
- return false;
1478
- if (typeof a !== typeof b)
1479
- return false;
1480
- if (typeof a === "bigint")
1481
- return a === b;
1482
- if (a instanceof Date && b instanceof Date)
1483
- return a.getTime() === b.getTime();
1484
- if (a instanceof RegExp && b instanceof RegExp) {
1485
- return a.source === b.source && a.flags === b.flags;
1486
- }
1487
- if (typeof a !== "object")
1488
- return false;
1489
- if (Array.isArray(a)) {
1490
- if (!Array.isArray(b))
1491
- return false;
1492
- if (a.length !== b.length)
1493
- return false;
1494
- return a.every((v, i) => forcedValuesEqual(v, b[i]));
1495
- }
1496
- if (!isPlainObject(a) || !isPlainObject(b))
1497
- return false;
1498
- const aKeys = Object.keys(a);
1499
- const bKeys = Object.keys(b);
1500
- if (aKeys.length !== bKeys.length)
1501
- return false;
1502
- return aKeys.every((k) => k in b && forcedValuesEqual(a[k], b[k]));
1503
- }
1504
1638
  function mergeScalarConditions(target, source) {
1505
1639
  for (const [field, ops] of Object.entries(source)) {
1506
1640
  const existing = target[field];
@@ -1518,7 +1652,7 @@ function mergeScalarConditions(target, source) {
1518
1652
  for (const [op, val] of Object.entries(ops)) {
1519
1653
  if (op in existing) {
1520
1654
  const existingVal = existing[op];
1521
- if (!forcedValuesEqual(existingVal, val)) {
1655
+ if (!deepEqual(existingVal, val)) {
1522
1656
  throw new ShapeError(
1523
1657
  `Conflicting forced where values for "${field}.${op}": shape defines both ${safeStringify(existingVal)} and ${safeStringify(val)}`
1524
1658
  );
@@ -1528,7 +1662,7 @@ function mergeScalarConditions(target, source) {
1528
1662
  Object.assign(existing, ops);
1529
1663
  continue;
1530
1664
  }
1531
- if (!forcedValuesEqual(existing, ops)) {
1665
+ if (!deepEqual(existing, ops)) {
1532
1666
  throw new ShapeError(`Conflicting forced where values for "${field}"`);
1533
1667
  }
1534
1668
  }
@@ -1619,27 +1753,27 @@ function createWhereBuilder(typeMap, enumMap, scalarBase, uniqueMap = {}) {
1619
1753
  scalarConditions
1620
1754
  );
1621
1755
  }
1622
- for (const key of Object.keys(scalarConditions)) {
1756
+ const forcedOnlyKeys = /* @__PURE__ */ new Set();
1757
+ for (const key of Object.keys(whereConfig)) {
1623
1758
  if (COMBINATOR_KEYS.has(key))
1624
1759
  continue;
1625
1760
  if (!(key in fieldSchemas)) {
1626
- fieldSchemas[key] = z4.object({}).strict().optional();
1761
+ forcedOnlyKeys.add(key);
1627
1762
  }
1628
1763
  }
1629
- for (const key of Object.keys(relationForced)) {
1764
+ for (const key of Object.keys(scalarConditions)) {
1765
+ if (COMBINATOR_KEYS.has(key))
1766
+ continue;
1630
1767
  if (!(key in fieldSchemas)) {
1631
- fieldSchemas[key] = z4.object({}).strict().optional();
1768
+ fieldSchemas[key] = z5.object({}).strict().optional();
1632
1769
  }
1633
1770
  }
1634
- const schema = Object.keys(fieldSchemas).length > 0 ? z4.object(fieldSchemas).strict().optional() : null;
1635
- const forcedOnlyKeys = /* @__PURE__ */ new Set();
1636
- for (const key of Object.keys(whereConfig)) {
1637
- if (COMBINATOR_KEYS.has(key))
1638
- continue;
1771
+ for (const key of Object.keys(relationForced)) {
1639
1772
  if (!(key in fieldSchemas)) {
1640
- forcedOnlyKeys.add(key);
1773
+ fieldSchemas[key] = z5.object({}).strict().optional();
1641
1774
  }
1642
1775
  }
1776
+ const schema = Object.keys(fieldSchemas).length > 0 ? z5.object(fieldSchemas).strict().optional() : null;
1643
1777
  return {
1644
1778
  schema,
1645
1779
  forced: {
@@ -1670,12 +1804,12 @@ function createWhereBuilder(typeMap, enumMap, scalarBase, uniqueMap = {}) {
1670
1804
  );
1671
1805
  }
1672
1806
  if (key === "NOT") {
1673
- fieldSchemas[key] = z4.union([
1807
+ fieldSchemas[key] = z5.union([
1674
1808
  elementSchema,
1675
- z4.preprocess(coerceToArray, z4.array(elementSchema).min(1))
1809
+ z5.preprocess(coerceToArray, z5.array(elementSchema).min(1))
1676
1810
  ]).optional();
1677
1811
  } else {
1678
- fieldSchemas[key] = z4.preprocess(coerceToArray, z4.array(elementSchema).min(1)).optional();
1812
+ fieldSchemas[key] = z5.preprocess(coerceToArray, z5.array(elementSchema).min(1)).optional();
1679
1813
  }
1680
1814
  }
1681
1815
  if (hasWhereForced(result.forced)) {
@@ -1744,6 +1878,11 @@ function createWhereBuilder(typeMap, enumMap, scalarBase, uniqueMap = {}) {
1744
1878
  `Empty nested where for relation "${key}.${op}" on model "${model}". Define at least one field.`
1745
1879
  );
1746
1880
  }
1881
+ if (NEGATIVE_RELATION_OPS.has(op) && nested.schema && hasWhereForced(nested.forced)) {
1882
+ throw new ShapeError(
1883
+ `Relation filter "${key}.${op}" on model "${model}" mixes client-controlled and forced conditions. Under negative relation operators (none, isNot), merging weakens the filter. Either move forced conditions to a separate top-level "${op}" branch, or make all conditions under this operator client-controlled or all forced.`
1884
+ );
1885
+ }
1747
1886
  if (nested.schema) {
1748
1887
  if (!hasWhereForced(nested.forced)) {
1749
1888
  opSchemas[op] = nested.schema.refine(
@@ -1768,7 +1907,7 @@ function createWhereBuilder(typeMap, enumMap, scalarBase, uniqueMap = {}) {
1768
1907
  }
1769
1908
  if (hasClientOps) {
1770
1909
  const clientOpKeys = Object.keys(opSchemas);
1771
- const opObjSchema = z4.object(opSchemas).strict();
1910
+ const opObjSchema = z5.object(opSchemas).strict();
1772
1911
  if (Object.keys(opForced).length === 0 && !hasForcedNull) {
1773
1912
  fieldSchemas[key] = opObjSchema.refine(
1774
1913
  (v) => clientOpKeys.some(
@@ -1854,10 +1993,10 @@ function createWhereBuilder(typeMap, enumMap, scalarBase, uniqueMap = {}) {
1854
1993
  );
1855
1994
  }
1856
1995
  if (modeConfigValue === true) {
1857
- opSchemas.mode = z4.enum(["default", "insensitive"]).optional();
1996
+ opSchemas.mode = z5.enum(["default", "insensitive"]).optional();
1858
1997
  } else {
1859
1998
  const actualModeValue = isForcedValue(modeConfigValue) ? modeConfigValue.value : modeConfigValue;
1860
- const modeSchema = z4.enum(["default", "insensitive"]);
1999
+ const modeSchema = z5.enum(["default", "insensitive"]);
1861
2000
  let parsed;
1862
2001
  try {
1863
2002
  parsed = modeSchema.parse(actualModeValue);
@@ -1869,10 +2008,10 @@ function createWhereBuilder(typeMap, enumMap, scalarBase, uniqueMap = {}) {
1869
2008
  fieldForced.mode = parsed;
1870
2009
  }
1871
2010
  } else if (hasModeCompatibleOp) {
1872
- opSchemas.mode = z4.enum(["default", "insensitive"]).optional();
2011
+ opSchemas.mode = z5.enum(["default", "insensitive"]).optional();
1873
2012
  }
1874
2013
  if (hasClientOps) {
1875
- const opObj = z4.object(opSchemas).strict();
2014
+ const opObj = z5.object(opSchemas).strict();
1876
2015
  const refined = opObj.refine(
1877
2016
  (v) => clientOpKeys.some(
1878
2017
  (k) => v[k] !== void 0
@@ -1888,7 +2027,7 @@ function createWhereBuilder(typeMap, enumMap, scalarBase, uniqueMap = {}) {
1888
2027
  enumMap,
1889
2028
  scalarBase
1890
2029
  );
1891
- fieldSchemas[fieldName] = z4.union([refined, equalsBase]).optional();
2030
+ fieldSchemas[fieldName] = z5.union([refined, equalsBase]).optional();
1892
2031
  } else {
1893
2032
  fieldSchemas[fieldName] = refined.optional();
1894
2033
  }
@@ -1902,15 +2041,8 @@ function createWhereBuilder(typeMap, enumMap, scalarBase, uniqueMap = {}) {
1902
2041
  (constraint) => constraint.selector === selector
1903
2042
  ) ?? null;
1904
2043
  }
1905
- function buildDirectUniqueSchema(fieldMeta) {
1906
- const base = createBaseType(fieldMeta, enumMap, scalarBase);
1907
- if (!fieldMeta.isEnum && !fieldMeta.isRelation && !fieldMeta.isUnsupported) {
1908
- return wrapWithInputCoercion(fieldMeta.type, fieldMeta.isList, base);
1909
- }
1910
- return base;
1911
- }
1912
2044
  function parseForcedUniqueValue(model, fieldName, fieldMeta, value) {
1913
- const schema = buildDirectUniqueSchema(fieldMeta);
2045
+ const schema = buildDirectScalarSchema(fieldMeta, enumMap, scalarBase);
1914
2046
  const actual = isForcedValue(value) ? value.value : value;
1915
2047
  try {
1916
2048
  return schema.parse(actual);
@@ -1988,7 +2120,11 @@ function createWhereBuilder(typeMap, enumMap, scalarBase, uniqueMap = {}) {
1988
2120
  `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.`
1989
2121
  );
1990
2122
  }
1991
- const directSchema2 = buildDirectUniqueSchema(fieldMeta2);
2123
+ const directSchema2 = buildDirectScalarSchema(
2124
+ fieldMeta2,
2125
+ enumMap,
2126
+ scalarBase
2127
+ );
1992
2128
  if (fieldValue === true) {
1993
2129
  nestedSchemas[fieldName] = directSchema2;
1994
2130
  } else {
@@ -2001,7 +2137,7 @@ function createWhereBuilder(typeMap, enumMap, scalarBase, uniqueMap = {}) {
2001
2137
  }
2002
2138
  }
2003
2139
  if (Object.keys(nestedSchemas).length > 0) {
2004
- fieldSchemas[key] = z4.object(nestedSchemas).strict();
2140
+ fieldSchemas[key] = z5.object(nestedSchemas).strict();
2005
2141
  }
2006
2142
  if (Object.keys(forcedCompound).length > 0) {
2007
2143
  forcedConditions[key] = forcedCompound;
@@ -2035,7 +2171,7 @@ function createWhereBuilder(typeMap, enumMap, scalarBase, uniqueMap = {}) {
2035
2171
  `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 }.`
2036
2172
  );
2037
2173
  }
2038
- const directSchema = buildDirectUniqueSchema(fieldMeta);
2174
+ const directSchema = buildDirectScalarSchema(fieldMeta, enumMap, scalarBase);
2039
2175
  if (value === true) {
2040
2176
  fieldSchemas[key] = directSchema;
2041
2177
  continue;
@@ -2049,7 +2185,7 @@ function createWhereBuilder(typeMap, enumMap, scalarBase, uniqueMap = {}) {
2049
2185
  forcedOnlyKeys.add(key);
2050
2186
  }
2051
2187
  return {
2052
- schema: Object.keys(fieldSchemas).length > 0 ? z4.object(fieldSchemas).strict() : null,
2188
+ schema: Object.keys(fieldSchemas).length > 0 ? z5.object(fieldSchemas).strict() : null,
2053
2189
  forced: {
2054
2190
  conditions: forcedConditions,
2055
2191
  relations: {}
@@ -2061,31 +2197,13 @@ function createWhereBuilder(typeMap, enumMap, scalarBase, uniqueMap = {}) {
2061
2197
  }
2062
2198
 
2063
2199
  // src/runtime/query-builder-args.ts
2064
- import { z as z5 } from "zod";
2200
+ import { z as z6 } from "zod";
2065
2201
  var UNSUPPORTED_BY_TYPES = /* @__PURE__ */ new Set(["Json", "Bytes"]);
2066
- function requireConfigTrue(config, context) {
2067
- for (const [key, value] of Object.entries(config)) {
2068
- if (value !== true) {
2069
- throw new ShapeError(
2070
- `Config value for "${key}" in ${context} must be true, got ${typeof value}`
2071
- );
2072
- }
2073
- }
2074
- }
2075
- function isPlainRecord(value) {
2076
- return value !== null && typeof value === "object" && !Array.isArray(value);
2077
- }
2078
- function formatUniqueConstraint2(constraint) {
2079
- return constraint.fields.length === 1 ? constraint.selector : `${constraint.selector}(${constraint.fields.join(", ")})`;
2080
- }
2081
- function formatUniqueConstraints2(constraints) {
2082
- return constraints.map(formatUniqueConstraint2).join(" | ");
2083
- }
2084
2202
  function createArgsBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
2085
- const sortEnum = z5.enum(["asc", "desc"]);
2086
- const nullsEnum = z5.enum(["first", "last"]);
2087
- const sortWithNulls = z5.object({ sort: sortEnum, nulls: nullsEnum.optional() }).strict();
2088
- const scalarOrderSchema = z5.union([sortEnum, sortWithNulls]);
2203
+ const sortEnum = z6.enum(["asc", "desc"]);
2204
+ const nullsEnum = z6.enum(["first", "last"]);
2205
+ const sortWithNulls = z6.object({ sort: sortEnum, nulls: nullsEnum.optional() }).strict();
2206
+ const scalarOrderSchema = z6.union([sortEnum, sortWithNulls]);
2089
2207
  function validateScalarOrderByField(fieldName, model, modelFields) {
2090
2208
  const fieldMeta = modelFields[fieldName];
2091
2209
  if (!fieldMeta)
@@ -2104,6 +2222,16 @@ function createArgsBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
2104
2222
  );
2105
2223
  }
2106
2224
  function buildOrderBySchema(model, orderByConfig) {
2225
+ if (!isPlainObject(orderByConfig)) {
2226
+ throw new ShapeError(
2227
+ `orderBy shape config on model "${model}" must be an object of fields`
2228
+ );
2229
+ }
2230
+ if (Object.keys(orderByConfig).length === 0) {
2231
+ throw new ShapeError(
2232
+ `Empty orderBy config on model "${model}". Define at least one field.`
2233
+ );
2234
+ }
2107
2235
  const modelFields = typeMap[model];
2108
2236
  if (!modelFields)
2109
2237
  throw new ShapeError(`Unknown model: ${model}`);
@@ -2119,53 +2247,35 @@ function createArgsBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
2119
2247
  fieldSchemas[fieldName] = scalarOrderSchema.optional();
2120
2248
  continue;
2121
2249
  }
2122
- if (!isPlainRecord(config)) {
2250
+ if (!isPlainObject(config)) {
2123
2251
  throw new ShapeError(
2124
- `orderBy config for "${fieldName}" on model "${model}" must be true or a relation aggregate object`
2252
+ `orderBy config for "${fieldName}" on model "${model}" must be true or a relation config object`
2125
2253
  );
2126
2254
  }
2127
2255
  if (!fieldMeta.isRelation) {
2128
- const allowedOps = getSupportedOperators(
2129
- fieldMeta.type,
2130
- fieldMeta.isList
2256
+ throw new ShapeError(
2257
+ `orderBy config for scalar field "${model}.${fieldName}" must be true. Operator objects are not valid in orderBy.`
2131
2258
  );
2132
- const opSchemas = {};
2133
- for (const [op, enabled] of Object.entries(config)) {
2134
- if (enabled !== true) {
2135
- throw new ShapeError(
2136
- `orderBy operator config for "${model}.${fieldName}.${op}" must be true`
2137
- );
2138
- }
2139
- if (!allowedOps.includes(op)) {
2140
- throw new ShapeError(
2141
- `Operator "${op}" not supported for orderBy field "${model}.${fieldName}"`
2142
- );
2143
- }
2144
- opSchemas[op] = scalarOrderSchema.optional();
2145
- }
2146
- const opKeys = Object.keys(opSchemas);
2147
- fieldSchemas[fieldName] = z5.object(opSchemas).strict().refine(
2148
- (v) => opKeys.some(
2149
- (k) => v[k] !== void 0
2150
- ),
2151
- {
2152
- message: `orderBy field "${fieldName}" must specify at least one operator`
2153
- }
2154
- ).optional();
2155
- continue;
2156
2259
  }
2157
2260
  if (fieldMeta.isList) {
2158
- if (!("_count" in config)) {
2261
+ const configKeys = Object.keys(config);
2262
+ if (!configKeys.includes("_count")) {
2159
2263
  throw new ShapeError(
2160
2264
  `To-many relation orderBy "${fieldName}" only supports _count`
2161
2265
  );
2162
2266
  }
2267
+ const extraKeys = configKeys.filter((k) => k !== "_count");
2268
+ if (extraKeys.length > 0) {
2269
+ throw new ShapeError(
2270
+ `To-many relation orderBy "${fieldName}" only supports _count. Unexpected keys: ${extraKeys.join(", ")}`
2271
+ );
2272
+ }
2163
2273
  if (config._count !== true) {
2164
2274
  throw new ShapeError(
2165
2275
  `orderBy relation aggregate "${fieldName}._count" must be true`
2166
2276
  );
2167
2277
  }
2168
- fieldSchemas[fieldName] = z5.object({
2278
+ fieldSchemas[fieldName] = z6.object({
2169
2279
  _count: sortEnum.optional()
2170
2280
  }).strict().optional();
2171
2281
  continue;
@@ -2176,17 +2286,11 @@ function createArgsBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
2176
2286
  );
2177
2287
  fieldSchemas[fieldName] = nested;
2178
2288
  }
2179
- const fieldKeys = Object.keys(fieldSchemas);
2180
- const singleSchema = z5.object(fieldSchemas).strict().refine(
2181
- (v) => fieldKeys.some(
2182
- (k) => v[k] !== void 0
2183
- ),
2184
- { message: "orderBy must specify at least one field" }
2289
+ const singleSchema = strictObjectRequiringOne(
2290
+ fieldSchemas,
2291
+ "orderBy must specify at least one field"
2185
2292
  );
2186
- return z5.union([
2187
- singleSchema,
2188
- z5.preprocess(coerceToArray, z5.array(singleSchema).min(1))
2189
- ]).optional();
2293
+ return singleOrArraySchema(singleSchema).optional();
2190
2294
  }
2191
2295
  function buildTakeSchema(config) {
2192
2296
  if (typeof config === "number") {
@@ -2196,7 +2300,7 @@ function createArgsBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
2196
2300
  if (config <= 0) {
2197
2301
  throw new ShapeError("take must be a positive integer");
2198
2302
  }
2199
- return z5.literal(config).optional();
2303
+ return z6.number().int().min(1).max(config).default(config);
2200
2304
  }
2201
2305
  if (!config || typeof config !== "object" || Array.isArray(config)) {
2202
2306
  throw new ShapeError("take config must be a number or { max, default? }");
@@ -2221,9 +2325,9 @@ function createArgsBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
2221
2325
  if (config.default > config.max) {
2222
2326
  throw new ShapeError("take.default cannot exceed take.max");
2223
2327
  }
2224
- return z5.number().int().min(1).max(config.max).default(config.default);
2328
+ return z6.number().int().min(1).max(config.max).default(config.default);
2225
2329
  }
2226
- return z5.number().int().min(1).max(config.max).optional();
2330
+ return z6.number().int().min(1).max(config.max).optional();
2227
2331
  }
2228
2332
  function buildCursorFieldSchema(model, fieldName) {
2229
2333
  const modelFields = typeMap[model];
@@ -2245,11 +2349,7 @@ function createArgsBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
2245
2349
  `List field "${fieldName}" cannot be used in cursor`
2246
2350
  );
2247
2351
  }
2248
- const base = createBaseType(fieldMeta, enumMap, scalarBase);
2249
- if (!fieldMeta.isEnum && !fieldMeta.isRelation && !fieldMeta.isUnsupported) {
2250
- return wrapWithInputCoercion(fieldMeta.type, fieldMeta.isList, base);
2251
- }
2252
- return base;
2352
+ return buildDirectScalarSchema(fieldMeta, enumMap, scalarBase);
2253
2353
  }
2254
2354
  function cursorConfigMatchesConstraint(cursorConfig, constraint) {
2255
2355
  if (!(constraint.selector in cursorConfig))
@@ -2258,66 +2358,55 @@ function createArgsBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
2258
2358
  if (constraint.fields.length === 1) {
2259
2359
  return value === true;
2260
2360
  }
2261
- if (!isPlainRecord(value))
2361
+ if (!isPlainObject(value))
2262
2362
  return false;
2263
2363
  const keys = Object.keys(value);
2264
2364
  if (keys.length !== constraint.fields.length)
2265
2365
  return false;
2266
2366
  return constraint.fields.every((field) => value[field] === true);
2267
2367
  }
2268
- function getUniqueConstraints(model) {
2269
- const constraints = uniqueMap[model];
2270
- if (constraints && constraints.length > 0) {
2271
- return constraints;
2272
- }
2273
- const modelFields = typeMap[model];
2274
- if (!modelFields) {
2275
- throw new ShapeError(`Unknown model: ${model}`);
2276
- }
2277
- const inferred = [];
2278
- for (const [fieldName, fieldMeta] of Object.entries(modelFields)) {
2279
- if (fieldMeta.isRelation)
2280
- continue;
2281
- if (fieldMeta.isId || fieldMeta.isUnique) {
2282
- inferred.push({
2283
- selector: fieldName,
2284
- fields: [fieldName]
2285
- });
2286
- }
2287
- }
2288
- return inferred;
2289
- }
2290
2368
  function buildCursorSchema(model, cursorConfig) {
2291
- const constraints = getUniqueConstraints(model);
2369
+ const constraints = uniqueMap[model] ?? [];
2292
2370
  if (constraints.length === 0) {
2293
2371
  throw new ShapeError(
2294
2372
  `cursor on model "${model}" requires at least one unique constraint`
2295
2373
  );
2296
2374
  }
2297
- const matching = constraints.find(
2375
+ const matching = constraints.filter(
2298
2376
  (constraint) => cursorConfigMatchesConstraint(cursorConfig, constraint)
2299
2377
  );
2300
- if (!matching) {
2378
+ if (matching.length === 0) {
2301
2379
  throw new ShapeError(
2302
- `cursor on model "${model}" must exactly match a unique selector: ${formatUniqueConstraints2(constraints)}`
2380
+ `cursor on model "${model}" must match a unique selector: ${formatUniqueConstraints(constraints)}`
2303
2381
  );
2304
2382
  }
2383
+ const coveredKeys = new Set(matching.map((c) => c.selector));
2384
+ for (const key of Object.keys(cursorConfig)) {
2385
+ if (!coveredKeys.has(key)) {
2386
+ throw new ShapeError(
2387
+ `cursor field "${key}" on model "${model}" does not match any unique selector. Unique selectors: ${formatUniqueConstraints(constraints)}`
2388
+ );
2389
+ }
2390
+ }
2305
2391
  const fieldSchemas = {};
2306
- if (matching.fields.length === 1) {
2307
- fieldSchemas[matching.selector] = buildCursorFieldSchema(
2308
- model,
2309
- matching.fields[0]
2310
- ).optional();
2311
- } else {
2312
- const nestedSchemas = {};
2313
- for (const field of matching.fields) {
2314
- nestedSchemas[field] = buildCursorFieldSchema(model, field);
2392
+ for (const constraint of matching) {
2393
+ if (constraint.fields.length === 1) {
2394
+ fieldSchemas[constraint.selector] = buildCursorFieldSchema(
2395
+ model,
2396
+ constraint.fields[0]
2397
+ ).optional();
2398
+ } else {
2399
+ const nestedSchemas = {};
2400
+ for (const field of constraint.fields) {
2401
+ nestedSchemas[field] = buildCursorFieldSchema(model, field);
2402
+ }
2403
+ fieldSchemas[constraint.selector] = z6.object(nestedSchemas).strict().optional();
2315
2404
  }
2316
- fieldSchemas[matching.selector] = z5.object(nestedSchemas).strict().optional();
2317
2405
  }
2318
- return z5.object(fieldSchemas).strict().refine(
2319
- (v) => v[matching.selector] !== void 0,
2320
- { message: `cursor must specify "${matching.selector}"` }
2406
+ const selectorKeys = matching.map((c) => c.selector);
2407
+ return strictObjectRequiringOne(
2408
+ fieldSchemas,
2409
+ `cursor must specify one of: ${selectorKeys.join(", ")}`
2321
2410
  ).optional();
2322
2411
  }
2323
2412
  function buildDistinctSchema(model, distinctConfig) {
@@ -2342,10 +2431,8 @@ function createArgsBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
2342
2431
  );
2343
2432
  allowedFields.add(fieldName);
2344
2433
  }
2345
- return z5.union([
2346
- z5.enum([...allowedFields]),
2347
- z5.array(z5.enum([...allowedFields])).min(1)
2348
- ]).optional();
2434
+ const fieldEnum = z6.enum([...allowedFields]);
2435
+ return z6.union([fieldEnum, z6.array(fieldEnum).min(1)]).optional();
2349
2436
  }
2350
2437
  function buildBySchema(model, byConfig) {
2351
2438
  const modelFields = typeMap[model];
@@ -2378,7 +2465,7 @@ function createArgsBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
2378
2465
  }
2379
2466
  allowedFields.add(fieldName);
2380
2467
  }
2381
- return z5.array(z5.enum([...allowedFields])).min(1);
2468
+ return z6.array(z6.enum([...allowedFields])).min(1);
2382
2469
  }
2383
2470
  function buildHavingSchema(model, havingConfig) {
2384
2471
  const modelFields = typeMap[model];
@@ -2419,22 +2506,21 @@ function createArgsBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
2419
2506
  ).optional();
2420
2507
  }
2421
2508
  if (fieldMeta.type === "String") {
2422
- opSchemas.mode = z5.enum(["default", "insensitive"]).optional();
2509
+ opSchemas.mode = z6.enum(["default", "insensitive"]).optional();
2423
2510
  }
2424
2511
  const opKeys = Object.keys(opSchemas).filter((key) => key !== "mode");
2425
- fieldSchemas[fieldName] = z5.object(opSchemas).strict().refine(
2512
+ const opShape = { ...opSchemas };
2513
+ const opObjSchema = z6.object(opShape).strict().refine(
2426
2514
  (v) => opKeys.some((k) => v[k] !== void 0),
2427
2515
  {
2428
2516
  message: `having field "${fieldName}" must specify at least one operator`
2429
2517
  }
2430
- ).optional();
2518
+ );
2519
+ fieldSchemas[fieldName] = opObjSchema.optional();
2431
2520
  }
2432
- const fieldKeys = Object.keys(fieldSchemas);
2433
- return z5.object(fieldSchemas).strict().refine(
2434
- (v) => fieldKeys.some(
2435
- (k) => v[k] !== void 0
2436
- ),
2437
- { message: "having must specify at least one field" }
2521
+ return strictObjectRequiringOne(
2522
+ fieldSchemas,
2523
+ "having must specify at least one field"
2438
2524
  ).optional();
2439
2525
  }
2440
2526
  function buildAggregateFieldSchema(model, op, config) {
@@ -2443,47 +2529,45 @@ function createArgsBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
2443
2529
  throw new ShapeError(`Unknown model: ${model}`);
2444
2530
  requireConfigTrue(config, `${op} on model "${model}"`);
2445
2531
  const allowedTypes = op === "_avg" || op === "_sum" ? NUMERIC_TYPES : COMPARABLE_TYPES;
2446
- const fieldSchemas = {};
2447
- for (const fieldName of Object.keys(config)) {
2448
- const fieldMeta = modelFields[fieldName];
2449
- if (!fieldMeta)
2450
- throw new ShapeError(
2451
- `Unknown field "${fieldName}" on model "${model}" in ${op}`
2452
- );
2453
- if (fieldMeta.isRelation)
2454
- throw new ShapeError(
2455
- `Relation field "${fieldName}" cannot be used in ${op}`
2456
- );
2457
- if (fieldMeta.isList)
2458
- throw new ShapeError(
2459
- `List field "${fieldName}" cannot be used in ${op}`
2460
- );
2461
- if (!allowedTypes.has(fieldMeta.type)) {
2462
- throw new ShapeError(
2463
- `Field "${fieldName}" of type "${fieldMeta.type}" cannot be used in ${op}`
2464
- );
2532
+ return buildLiteralTrueSchema(
2533
+ Object.keys(config),
2534
+ `${op} must specify at least one field`,
2535
+ (fieldName) => {
2536
+ const fieldMeta = modelFields[fieldName];
2537
+ if (!fieldMeta)
2538
+ throw new ShapeError(
2539
+ `Unknown field "${fieldName}" on model "${model}" in ${op}`
2540
+ );
2541
+ if (fieldMeta.isRelation)
2542
+ throw new ShapeError(
2543
+ `Relation field "${fieldName}" cannot be used in ${op}`
2544
+ );
2545
+ if (fieldMeta.isList)
2546
+ throw new ShapeError(
2547
+ `List field "${fieldName}" cannot be used in ${op}`
2548
+ );
2549
+ if (!allowedTypes.has(fieldMeta.type)) {
2550
+ throw new ShapeError(
2551
+ `Field "${fieldName}" of type "${fieldMeta.type}" cannot be used in ${op}`
2552
+ );
2553
+ }
2465
2554
  }
2466
- fieldSchemas[fieldName] = z5.literal(true).optional();
2467
- }
2468
- const aggregateFieldKeys = Object.keys(fieldSchemas);
2469
- return z5.object(fieldSchemas).strict().refine(
2470
- (v) => aggregateFieldKeys.some(
2471
- (k) => v[k] !== void 0
2472
- ),
2473
- { message: `${op} must specify at least one field` }
2474
- ).optional();
2555
+ );
2475
2556
  }
2476
2557
  function buildCountFieldSchema(model, config, context) {
2477
2558
  if (config === true) {
2478
- return z5.literal(true).optional();
2559
+ return z6.literal(true).optional();
2479
2560
  }
2480
2561
  const modelFields = typeMap[model];
2481
2562
  if (!modelFields)
2482
2563
  throw new ShapeError(`Unknown model: ${model}`);
2483
2564
  requireConfigTrue(config, `${context} on model "${model}"`);
2484
- const fieldSchemas = {};
2485
- for (const fieldName of Object.keys(config)) {
2486
- if (fieldName !== "_all") {
2565
+ return buildLiteralTrueSchema(
2566
+ Object.keys(config),
2567
+ `${context} must specify at least one field`,
2568
+ (fieldName) => {
2569
+ if (fieldName === "_all")
2570
+ return;
2487
2571
  const fieldMeta = modelFields[fieldName];
2488
2572
  if (!fieldMeta)
2489
2573
  throw new ShapeError(
@@ -2494,45 +2578,30 @@ function createArgsBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
2494
2578
  `Relation field "${fieldName}" cannot be used in ${context}`
2495
2579
  );
2496
2580
  }
2497
- fieldSchemas[fieldName] = z5.literal(true).optional();
2498
- }
2499
- const countFieldKeys = Object.keys(fieldSchemas);
2500
- return z5.object(fieldSchemas).strict().refine(
2501
- (v) => countFieldKeys.some(
2502
- (k) => v[k] !== void 0
2503
- ),
2504
- { message: `${context} must specify at least one field` }
2505
- ).optional();
2581
+ );
2506
2582
  }
2507
2583
  function buildCountSelectSchema(model, selectConfig) {
2508
2584
  const modelFields = typeMap[model];
2509
2585
  if (!modelFields)
2510
2586
  throw new ShapeError(`Unknown model: ${model}`);
2511
2587
  requireConfigTrue(selectConfig, `count select on model "${model}"`);
2512
- const fieldSchemas = {};
2513
- for (const fieldName of Object.keys(selectConfig)) {
2514
- if (fieldName === "_all") {
2515
- fieldSchemas._all = z5.literal(true).optional();
2516
- continue;
2588
+ return buildLiteralTrueSchema(
2589
+ Object.keys(selectConfig),
2590
+ "count select must specify at least one field",
2591
+ (fieldName) => {
2592
+ if (fieldName === "_all")
2593
+ return;
2594
+ const fieldMeta = modelFields[fieldName];
2595
+ if (!fieldMeta)
2596
+ throw new ShapeError(
2597
+ `Unknown field "${fieldName}" on model "${model}" in count select`
2598
+ );
2599
+ if (fieldMeta.isRelation)
2600
+ throw new ShapeError(
2601
+ `Relation field "${fieldName}" cannot be used in count select`
2602
+ );
2517
2603
  }
2518
- const fieldMeta = modelFields[fieldName];
2519
- if (!fieldMeta)
2520
- throw new ShapeError(
2521
- `Unknown field "${fieldName}" on model "${model}" in count select`
2522
- );
2523
- if (fieldMeta.isRelation)
2524
- throw new ShapeError(
2525
- `Relation field "${fieldName}" cannot be used in count select`
2526
- );
2527
- fieldSchemas[fieldName] = z5.literal(true).optional();
2528
- }
2529
- const countSelectKeys = Object.keys(fieldSchemas);
2530
- return z5.object(fieldSchemas).strict().refine(
2531
- (v) => countSelectKeys.some(
2532
- (k) => v[k] !== void 0
2533
- ),
2534
- { message: "count select must specify at least one field" }
2535
- ).optional();
2604
+ );
2536
2605
  }
2537
2606
  return {
2538
2607
  buildOrderBySchema,
@@ -2548,25 +2617,64 @@ function createArgsBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
2548
2617
  }
2549
2618
 
2550
2619
  // src/runtime/query-builder-projection.ts
2551
- import { z as z6 } from "zod";
2552
- var KNOWN_NESTED_INCLUDE_KEYS = /* @__PURE__ */ new Set([
2553
- "where",
2554
- "include",
2555
- "select",
2556
- "orderBy",
2557
- "cursor",
2558
- "take",
2559
- "skip"
2560
- ]);
2561
- var KNOWN_NESTED_SELECT_KEYS = /* @__PURE__ */ new Set([
2562
- "select",
2563
- "include",
2564
- "where",
2565
- "orderBy",
2566
- "cursor",
2567
- "take",
2568
- "skip"
2569
- ]);
2620
+ import { z as z7 } from "zod";
2621
+
2622
+ // src/shared/projection-defaults.ts
2623
+ function buildDefaultProjectionInput(config) {
2624
+ const result = {};
2625
+ for (const [key, value] of Object.entries(config)) {
2626
+ if (key === "_count") {
2627
+ result[key] = buildDefaultCountInput(
2628
+ value
2629
+ );
2630
+ continue;
2631
+ }
2632
+ if (value === true) {
2633
+ result[key] = true;
2634
+ } else {
2635
+ result[key] = buildRelationArgsSkeleton(value);
2636
+ }
2637
+ }
2638
+ return result;
2639
+ }
2640
+ function buildRelationArgsSkeleton(config) {
2641
+ const skeleton = {};
2642
+ if (config.select) {
2643
+ skeleton.select = buildDefaultProjectionInput(config.select);
2644
+ }
2645
+ if (config.include) {
2646
+ skeleton.include = buildDefaultProjectionInput(config.include);
2647
+ }
2648
+ return skeleton;
2649
+ }
2650
+ function buildDefaultCountInput(config) {
2651
+ if (config === true)
2652
+ return true;
2653
+ if (!isPlainObject(config) || !config.select || !isPlainObject(config.select)) {
2654
+ return true;
2655
+ }
2656
+ const selectObj = config.select;
2657
+ const result = {};
2658
+ for (const key of Object.keys(selectObj)) {
2659
+ result[key] = true;
2660
+ }
2661
+ return { select: result };
2662
+ }
2663
+ function buildDefaultProjectionBody(shape) {
2664
+ if (shape.select) {
2665
+ return { select: buildDefaultProjectionInput(shape.select) };
2666
+ }
2667
+ if (shape.include) {
2668
+ return { include: buildDefaultProjectionInput(shape.include) };
2669
+ }
2670
+ return {};
2671
+ }
2672
+
2673
+ // src/runtime/query-builder-projection.ts
2674
+ var KNOWN_NESTED_KEYS = {
2675
+ include: /* @__PURE__ */ new Set(["where", "include", "select", "orderBy", "cursor", "take", "skip"]),
2676
+ select: /* @__PURE__ */ new Set(["select", "include", "where", "orderBy", "cursor", "take", "skip"])
2677
+ };
2570
2678
  var KNOWN_COUNT_SELECT_ENTRY_KEYS = /* @__PURE__ */ new Set(["where"]);
2571
2679
  var MAX_PROJECTION_DEPTH = 10;
2572
2680
  function validateNestedKeys(keys, allowed, context) {
@@ -2578,13 +2686,25 @@ function validateNestedKeys(keys, allowed, context) {
2578
2686
  }
2579
2687
  }
2580
2688
  }
2581
- function createProjectionBuilder(typeMap, enumMap, deps) {
2689
+ function hasDefinedKeys(v) {
2690
+ return Object.values(v).some((value) => value !== void 0);
2691
+ }
2692
+ function wrapRelationSchema(nestedObj, skeleton) {
2693
+ const collapsed = nestedObj.transform(
2694
+ (v) => isPlainObject(v) && !hasDefinedKeys(v) ? true : v
2695
+ );
2696
+ return z7.preprocess(
2697
+ (v) => v === true ? deepClone(skeleton) : v,
2698
+ collapsed
2699
+ );
2700
+ }
2701
+ function createProjectionBuilder(typeMap, _enumMap, deps) {
2582
2702
  function buildIncludeCountSchema(model, config) {
2583
2703
  const modelFields = typeMap[model];
2584
2704
  if (!modelFields)
2585
2705
  throw new ShapeError(`Unknown model: ${model}`);
2586
2706
  if (config === true) {
2587
- return { schema: z6.literal(true).optional(), forcedCountWhere: {} };
2707
+ return { schema: z7.literal(true).optional(), forcedCountWhere: {} };
2588
2708
  }
2589
2709
  if (!isPlainObject(config) || !("select" in config)) {
2590
2710
  throw new ShapeError(
@@ -2620,273 +2740,175 @@ function createProjectionBuilder(typeMap, enumMap, deps) {
2620
2740
  if (!fieldMeta.isList)
2621
2741
  throw new ShapeError(`Field "${fieldName}" is a to-one relation on model "${model}" in _count.select. Only to-many relations support _count.`);
2622
2742
  if (fieldConfig === true) {
2623
- countSelectFields[fieldName] = z6.literal(true).optional();
2624
- } else if (isPlainObject(fieldConfig)) {
2625
- if (Object.keys(fieldConfig).length === 0) {
2626
- throw new ShapeError(
2627
- `Empty config for _count.select.${fieldName} on model "${model}". Use true or { where: { ... } }.`
2628
- );
2629
- }
2630
- validateNestedKeys(
2631
- Object.keys(fieldConfig),
2632
- KNOWN_COUNT_SELECT_ENTRY_KEYS,
2633
- `_count.select.${fieldName} on model "${model}"`
2634
- );
2635
- if (fieldConfig.where) {
2636
- const relatedType = fieldMeta.type;
2637
- const { schema: whereSchema, forced } = deps.buildWhereSchema(
2638
- relatedType,
2639
- fieldConfig.where
2640
- );
2641
- const nestedSchemas = {};
2642
- if (whereSchema)
2643
- nestedSchemas["where"] = whereSchema;
2644
- const nestedObj = z6.object(nestedSchemas).strict();
2645
- countSelectFields[fieldName] = z6.union([z6.literal(true), nestedObj]).optional();
2646
- if (hasWhereForced(forced)) {
2647
- forcedCountWhere[fieldName] = forced;
2648
- }
2649
- } else {
2650
- countSelectFields[fieldName] = z6.literal(true).optional();
2651
- }
2652
- } else {
2743
+ countSelectFields[fieldName] = z7.literal(true).optional();
2744
+ continue;
2745
+ }
2746
+ if (!isPlainObject(fieldConfig)) {
2653
2747
  throw new ShapeError(
2654
2748
  `Invalid config for _count.select.${fieldName} on model "${model}". Expected true or { where: { ... } }`
2655
2749
  );
2656
2750
  }
2751
+ if (Object.keys(fieldConfig).length === 0) {
2752
+ throw new ShapeError(
2753
+ `Empty config for _count.select.${fieldName} on model "${model}". Use true or { where: { ... } }.`
2754
+ );
2755
+ }
2756
+ validateNestedKeys(
2757
+ Object.keys(fieldConfig),
2758
+ KNOWN_COUNT_SELECT_ENTRY_KEYS,
2759
+ `_count.select.${fieldName} on model "${model}"`
2760
+ );
2761
+ if (fieldConfig.where) {
2762
+ const relatedType = fieldMeta.type;
2763
+ const { schema: whereSchema, forced } = deps.buildWhereSchema(
2764
+ relatedType,
2765
+ fieldConfig.where
2766
+ );
2767
+ const nestedSchemas = {};
2768
+ if (whereSchema)
2769
+ nestedSchemas["where"] = whereSchema;
2770
+ const nestedObj = z7.object(nestedSchemas).strict();
2771
+ countSelectFields[fieldName] = z7.union([z7.literal(true), nestedObj]).optional();
2772
+ if (hasWhereForced(forced)) {
2773
+ forcedCountWhere[fieldName] = forced;
2774
+ }
2775
+ } else {
2776
+ countSelectFields[fieldName] = z7.literal(true).optional();
2777
+ }
2657
2778
  }
2658
- const countSelectKeys = Object.keys(countSelectFields);
2659
- const selectSchema = z6.object(countSelectFields).strict().refine(
2660
- (v) => countSelectKeys.some((k) => v[k] !== void 0),
2661
- { message: "_count.select must specify at least one field" }
2779
+ const selectSchema = strictObjectRequiringOne(
2780
+ countSelectFields,
2781
+ "_count.select must specify at least one field"
2662
2782
  );
2663
2783
  return {
2664
- schema: z6.object({ select: selectSchema }).strict().optional(),
2784
+ schema: z7.object({ select: selectSchema }).strict().optional(),
2665
2785
  forcedCountWhere
2666
2786
  };
2667
2787
  }
2668
- function buildIncludeSchema(model, includeConfig, depth) {
2788
+ function buildNestedRelSchemas(relatedType, config, depth) {
2789
+ const nestedSchemas = {};
2790
+ const relForced = {};
2791
+ if (config.where) {
2792
+ const { schema: whereSchema, forced } = deps.buildWhereSchema(
2793
+ relatedType,
2794
+ config.where
2795
+ );
2796
+ if (whereSchema)
2797
+ nestedSchemas["where"] = whereSchema;
2798
+ if (hasWhereForced(forced))
2799
+ relForced.where = forced;
2800
+ }
2801
+ if (config.include) {
2802
+ const nested = buildProjectionSchema("include", relatedType, config.include, depth + 1);
2803
+ nestedSchemas["include"] = nested.schema;
2804
+ if (Object.keys(nested.forcedTree).length > 0)
2805
+ relForced.include = nested.forcedTree;
2806
+ if (Object.keys(nested.forcedCountWhere).length > 0) {
2807
+ relForced._countWhere = nested.forcedCountWhere;
2808
+ relForced._countWherePlacement = "include";
2809
+ }
2810
+ }
2811
+ if (config.select) {
2812
+ const nested = buildProjectionSchema("select", relatedType, config.select, depth + 1);
2813
+ nestedSchemas["select"] = nested.schema;
2814
+ if (Object.keys(nested.forcedTree).length > 0)
2815
+ relForced.select = nested.forcedTree;
2816
+ if (Object.keys(nested.forcedCountWhere).length > 0) {
2817
+ relForced._countWhere = nested.forcedCountWhere;
2818
+ relForced._countWherePlacement = "select";
2819
+ }
2820
+ }
2821
+ if (config.orderBy) {
2822
+ nestedSchemas["orderBy"] = deps.buildOrderBySchema(relatedType, config.orderBy);
2823
+ }
2824
+ if (config.cursor) {
2825
+ nestedSchemas["cursor"] = deps.buildCursorSchema(relatedType, config.cursor);
2826
+ }
2827
+ if (config.take) {
2828
+ nestedSchemas["take"] = deps.buildTakeSchema(config.take);
2829
+ }
2830
+ if (config.skip) {
2831
+ nestedSchemas["skip"] = z7.number().int().min(0).optional();
2832
+ }
2833
+ return { nestedSchemas, relForced };
2834
+ }
2835
+ function buildProjectionSchema(mode, model, projectionConfig, depth) {
2669
2836
  const currentDepth = depth ?? 0;
2670
2837
  if (currentDepth > MAX_PROJECTION_DEPTH) {
2671
2838
  throw new ShapeError(
2672
- `Include schema for model "${model}" exceeds maximum nesting depth (${MAX_PROJECTION_DEPTH}). Check for circular relation references in the shape.`
2839
+ `${mode === "include" ? "Include" : "Select"} schema for model "${model}" exceeds maximum nesting depth (${MAX_PROJECTION_DEPTH}). Check for circular relation references in the shape.`
2673
2840
  );
2674
2841
  }
2675
- if (Object.keys(includeConfig).length === 0) {
2842
+ if (Object.keys(projectionConfig).length === 0) {
2676
2843
  throw new ShapeError(
2677
- `Empty include config on model "${model}". Define at least one relation.`
2844
+ `Empty ${mode} config on model "${model}". Define at least one ${mode === "include" ? "relation" : "field"}.`
2678
2845
  );
2679
2846
  }
2680
2847
  const modelFields = typeMap[model];
2681
2848
  if (!modelFields)
2682
2849
  throw new ShapeError(`Unknown model: ${model}`);
2850
+ const allowedNestedKeys = KNOWN_NESTED_KEYS[mode];
2683
2851
  const fieldSchemas = {};
2684
2852
  const forcedTree = {};
2685
2853
  let topLevelForcedCountWhere = {};
2686
- for (const [relName, config] of Object.entries(includeConfig)) {
2687
- if (relName === "_count") {
2854
+ for (const [fieldName, config] of Object.entries(projectionConfig)) {
2855
+ if (fieldName === "_count") {
2688
2856
  const countResult = buildIncludeCountSchema(model, config);
2689
2857
  fieldSchemas["_count"] = countResult.schema;
2690
2858
  topLevelForcedCountWhere = countResult.forcedCountWhere;
2691
2859
  continue;
2692
2860
  }
2693
- const fieldMeta = modelFields[relName];
2861
+ const fieldMeta = modelFields[fieldName];
2694
2862
  if (!fieldMeta)
2695
- throw new ShapeError(`Unknown field "${relName}" on model "${model}"`);
2696
- if (!fieldMeta.isRelation)
2697
- throw new ShapeError(`Field "${relName}" is not a relation on model "${model}"`);
2863
+ throw new ShapeError(`Unknown field "${fieldName}" on model "${model}"`);
2864
+ if (mode === "include" && !fieldMeta.isRelation) {
2865
+ throw new ShapeError(`Field "${fieldName}" is not a relation on model "${model}"`);
2866
+ }
2698
2867
  if (config === true) {
2699
- fieldSchemas[relName] = z6.literal(true).optional();
2700
- } else {
2701
- validateNestedKeys(
2702
- Object.keys(config),
2703
- KNOWN_NESTED_INCLUDE_KEYS,
2704
- `nested include for "${relName}" on model "${model}"`
2705
- );
2706
- if (config.select && config.include) {
2707
- throw new ShapeError(`Nested include for "${relName}" cannot define both "select" and "include".`);
2708
- }
2709
- if (!fieldMeta.isList) {
2710
- if (config.where || config.orderBy || config.cursor || config.take || config.skip) {
2711
- throw new ShapeError(
2712
- `Relation "${relName}" on model "${model}" is to-one. Only "include" and "select" are supported for to-one nested reads, not where/orderBy/cursor/take/skip.`
2713
- );
2714
- }
2715
- }
2716
- const nestedSchemas = {};
2717
- const relForced = {};
2718
- if (config.where) {
2719
- const { schema: whereSchema, forced } = deps.buildWhereSchema(
2720
- fieldMeta.type,
2721
- config.where
2722
- );
2723
- if (whereSchema)
2724
- nestedSchemas["where"] = whereSchema;
2725
- if (hasWhereForced(forced))
2726
- relForced.where = forced;
2727
- }
2728
- if (config.include) {
2729
- const nested = buildIncludeSchema(fieldMeta.type, config.include, currentDepth + 1);
2730
- nestedSchemas["include"] = nested.schema;
2731
- if (Object.keys(nested.forcedTree).length > 0)
2732
- relForced.include = nested.forcedTree;
2733
- if (Object.keys(nested.forcedCountWhere).length > 0) {
2734
- relForced._countWhere = nested.forcedCountWhere;
2735
- relForced._countWherePlacement = "include";
2736
- }
2737
- }
2738
- if (config.select) {
2739
- const nested = buildSelectSchema(fieldMeta.type, config.select, currentDepth + 1);
2740
- nestedSchemas["select"] = nested.schema;
2741
- if (Object.keys(nested.forcedTree).length > 0)
2742
- relForced.select = nested.forcedTree;
2743
- if (Object.keys(nested.forcedCountWhere).length > 0) {
2744
- relForced._countWhere = nested.forcedCountWhere;
2745
- relForced._countWherePlacement = "select";
2746
- }
2747
- }
2748
- if (config.orderBy) {
2749
- nestedSchemas["orderBy"] = deps.buildOrderBySchema(fieldMeta.type, config.orderBy);
2750
- }
2751
- if (config.cursor) {
2752
- nestedSchemas["cursor"] = deps.buildCursorSchema(fieldMeta.type, config.cursor);
2753
- }
2754
- if (config.take) {
2755
- nestedSchemas["take"] = deps.buildTakeSchema(config.take);
2756
- }
2757
- if (config.skip) {
2758
- nestedSchemas["skip"] = z6.number().int().min(0).optional();
2759
- }
2760
- const nestedObj = z6.object(nestedSchemas).strict();
2761
- fieldSchemas[relName] = z6.union([z6.literal(true), nestedObj]).optional();
2762
- if (Object.keys(relForced).length > 0)
2763
- forcedTree[relName] = relForced;
2764
- }
2765
- }
2766
- const includeFieldKeys = Object.keys(fieldSchemas);
2767
- const baseSchema = z6.object(fieldSchemas).strict();
2768
- const schema = includeFieldKeys.length > 0 ? baseSchema.refine(
2769
- (v) => includeFieldKeys.some((k) => v[k] !== void 0),
2770
- { message: "include must specify at least one field" }
2771
- ).optional() : baseSchema.optional();
2772
- return {
2773
- schema,
2774
- forcedTree,
2775
- forcedCountWhere: topLevelForcedCountWhere
2776
- };
2777
- }
2778
- function buildSelectSchema(model, selectConfig, depth) {
2779
- const currentDepth = depth ?? 0;
2780
- if (currentDepth > MAX_PROJECTION_DEPTH) {
2781
- throw new ShapeError(
2782
- `Select schema for model "${model}" exceeds maximum nesting depth (${MAX_PROJECTION_DEPTH}). Check for circular relation references in the shape.`
2783
- );
2784
- }
2785
- if (Object.keys(selectConfig).length === 0) {
2786
- throw new ShapeError(
2787
- `Empty select config on model "${model}". Define at least one field.`
2788
- );
2789
- }
2790
- const modelFields = typeMap[model];
2791
- if (!modelFields)
2792
- throw new ShapeError(`Unknown model: ${model}`);
2793
- const fieldSchemas = {};
2794
- const forcedTree = {};
2795
- let topLevelForcedCountWhere = {};
2796
- for (const [fieldName, config] of Object.entries(selectConfig)) {
2797
- if (fieldName === "_count") {
2798
- const countResult = buildIncludeCountSchema(model, config);
2799
- fieldSchemas["_count"] = countResult.schema;
2800
- topLevelForcedCountWhere = countResult.forcedCountWhere;
2868
+ fieldSchemas[fieldName] = z7.literal(true).optional();
2801
2869
  continue;
2802
2870
  }
2803
- const fieldMeta = modelFields[fieldName];
2804
- if (!fieldMeta)
2805
- throw new ShapeError(`Unknown field "${fieldName}" on model "${model}"`);
2806
- if (config === true) {
2807
- fieldSchemas[fieldName] = z6.literal(true).optional();
2808
- } else {
2809
- if (!fieldMeta.isRelation) {
2810
- throw new ShapeError(`Nested select args only valid for relations, not scalar "${fieldName}" on model "${model}"`);
2811
- }
2812
- validateNestedKeys(
2813
- Object.keys(config),
2814
- KNOWN_NESTED_SELECT_KEYS,
2815
- `nested select for "${fieldName}" on model "${model}"`
2816
- );
2817
- if (config.select && config.include) {
2818
- throw new ShapeError(`Nested select for "${fieldName}" cannot define both "select" and "include".`);
2819
- }
2820
- if (!fieldMeta.isList) {
2821
- if (config.where || config.orderBy || config.cursor || config.take || config.skip) {
2822
- throw new ShapeError(
2823
- `Relation "${fieldName}" on model "${model}" is to-one. Only "select" and "include" are supported for to-one nested reads, not where/orderBy/cursor/take/skip.`
2824
- );
2825
- }
2826
- }
2827
- const nestedSchemas = {};
2828
- const relForced = {};
2829
- if (config.select) {
2830
- const nested = buildSelectSchema(fieldMeta.type, config.select, currentDepth + 1);
2831
- nestedSchemas["select"] = nested.schema;
2832
- if (Object.keys(nested.forcedTree).length > 0)
2833
- relForced.select = nested.forcedTree;
2834
- if (Object.keys(nested.forcedCountWhere).length > 0) {
2835
- relForced._countWhere = nested.forcedCountWhere;
2836
- relForced._countWherePlacement = "select";
2837
- }
2838
- }
2839
- if (config.include) {
2840
- const nested = buildIncludeSchema(fieldMeta.type, config.include, currentDepth + 1);
2841
- nestedSchemas["include"] = nested.schema;
2842
- if (Object.keys(nested.forcedTree).length > 0)
2843
- relForced.include = nested.forcedTree;
2844
- if (Object.keys(nested.forcedCountWhere).length > 0) {
2845
- relForced._countWhere = nested.forcedCountWhere;
2846
- relForced._countWherePlacement = "include";
2847
- }
2848
- }
2849
- if (config.where) {
2850
- const { schema: whereSchema, forced } = deps.buildWhereSchema(
2851
- fieldMeta.type,
2852
- config.where
2871
+ if (mode === "select" && !fieldMeta.isRelation) {
2872
+ throw new ShapeError(`Nested select args only valid for relations, not scalar "${fieldName}" on model "${model}"`);
2873
+ }
2874
+ const contextLabel = `nested ${mode} for "${fieldName}" on model "${model}"`;
2875
+ validateNestedKeys(Object.keys(config), allowedNestedKeys, contextLabel);
2876
+ if (config.select && config.include) {
2877
+ throw new ShapeError(`Nested ${mode} for "${fieldName}" cannot define both "select" and "include".`);
2878
+ }
2879
+ if (!fieldMeta.isList) {
2880
+ if (config.where || config.orderBy || config.cursor || config.take || config.skip) {
2881
+ throw new ShapeError(
2882
+ `Relation "${fieldName}" on model "${model}" is to-one. Only "select" and "include" are supported for to-one nested reads, not where/orderBy/cursor/take/skip.`
2853
2883
  );
2854
- if (whereSchema)
2855
- nestedSchemas["where"] = whereSchema;
2856
- if (hasWhereForced(forced))
2857
- relForced.where = forced;
2858
- }
2859
- if (config.orderBy) {
2860
- nestedSchemas["orderBy"] = deps.buildOrderBySchema(fieldMeta.type, config.orderBy);
2861
- }
2862
- if (config.cursor) {
2863
- nestedSchemas["cursor"] = deps.buildCursorSchema(fieldMeta.type, config.cursor);
2864
- }
2865
- if (config.take) {
2866
- nestedSchemas["take"] = deps.buildTakeSchema(config.take);
2867
- }
2868
- if (config.skip) {
2869
- nestedSchemas["skip"] = z6.number().int().min(0).optional();
2870
2884
  }
2871
- const nestedObj = z6.object(nestedSchemas).strict();
2872
- fieldSchemas[fieldName] = z6.union([z6.literal(true), nestedObj]).optional();
2873
- if (Object.keys(relForced).length > 0)
2874
- forcedTree[fieldName] = relForced;
2875
- }
2876
- }
2877
- const selectFieldKeys = Object.keys(fieldSchemas);
2878
- const baseSchema = z6.object(fieldSchemas).strict();
2879
- const schema = selectFieldKeys.length > 0 ? baseSchema.refine(
2880
- (v) => selectFieldKeys.some((k) => v[k] !== void 0),
2881
- { message: "select must specify at least one field" }
2882
- ).optional() : baseSchema.optional();
2885
+ }
2886
+ const { nestedSchemas, relForced } = buildNestedRelSchemas(fieldMeta.type, config, currentDepth);
2887
+ const nestedObj = z7.object(nestedSchemas).strict();
2888
+ fieldSchemas[fieldName] = wrapRelationSchema(
2889
+ nestedObj,
2890
+ buildRelationArgsSkeleton(config)
2891
+ ).optional();
2892
+ if (Object.keys(relForced).length > 0)
2893
+ forcedTree[fieldName] = relForced;
2894
+ }
2895
+ const schema = Object.keys(fieldSchemas).length > 0 ? strictObjectRequiringOne(
2896
+ fieldSchemas,
2897
+ `${mode} must specify at least one field`
2898
+ ).optional() : z7.object(fieldSchemas).strict().optional();
2883
2899
  return {
2884
2900
  schema,
2885
2901
  forcedTree,
2886
2902
  forcedCountWhere: topLevelForcedCountWhere
2887
2903
  };
2888
2904
  }
2889
- return { buildIncludeSchema, buildSelectSchema, buildIncludeCountSchema };
2905
+ function buildIncludeSchema(model, includeConfig, depth) {
2906
+ return buildProjectionSchema("include", model, includeConfig, depth);
2907
+ }
2908
+ function buildSelectSchema(model, selectConfig, depth) {
2909
+ return buildProjectionSchema("select", model, selectConfig, depth);
2910
+ }
2911
+ return { buildIncludeSchema, buildSelectSchema, buildIncludeCountSchema, buildProjectionSchema };
2890
2912
  }
2891
2913
 
2892
2914
  // src/shared/operation-shape-keys.ts
@@ -2896,7 +2918,6 @@ var OPERATION_SHAPE_KEYS = {
2896
2918
  findFirstOrThrow: ["where", "include", "select", "orderBy", "cursor", "take", "skip", "distinct"],
2897
2919
  findUnique: ["where", "include", "select"],
2898
2920
  findUniqueOrThrow: ["where", "include", "select"],
2899
- findManyPaginated: ["where", "include", "select", "orderBy", "cursor", "take", "skip", "distinct"],
2900
2921
  count: ["where", "select", "cursor", "orderBy", "skip", "take"],
2901
2922
  aggregate: ["where", "orderBy", "cursor", "take", "skip", "_count", "_avg", "_sum", "_min", "_max"],
2902
2923
  groupBy: ["where", "by", "having", "_count", "_avg", "_sum", "_min", "_max", "orderBy", "take", "skip"],
@@ -2931,6 +2952,99 @@ var MUTATION_SHAPE_KEYS = {
2931
2952
  delete: new Set(OPERATION_SHAPE_KEYS.delete),
2932
2953
  deleteMany: new Set(OPERATION_SHAPE_KEYS.deleteMany)
2933
2954
  };
2955
+ var MUTATION_OPERATION_SPECS = {
2956
+ create: {
2957
+ bodyKeysBase: ["data"],
2958
+ bodyKeysProjection: ["data", "select", "include"],
2959
+ shapeKeysBase: ["data"],
2960
+ shapeKeysProjection: ["data", "select", "include"],
2961
+ supportsProjection: true
2962
+ },
2963
+ createMany: {
2964
+ bodyKeysBase: ["data", "skipDuplicates"],
2965
+ bodyKeysProjection: ["data", "select", "include", "skipDuplicates"],
2966
+ shapeKeysBase: ["data"],
2967
+ shapeKeysProjection: ["data"],
2968
+ supportsProjection: false
2969
+ },
2970
+ createManyAndReturn: {
2971
+ bodyKeysBase: ["data", "skipDuplicates"],
2972
+ bodyKeysProjection: ["data", "select", "include", "skipDuplicates"],
2973
+ shapeKeysBase: ["data"],
2974
+ shapeKeysProjection: ["data", "select", "include"],
2975
+ supportsProjection: true
2976
+ },
2977
+ update: {
2978
+ bodyKeysBase: ["data", "where"],
2979
+ bodyKeysProjection: ["data", "where", "select", "include"],
2980
+ shapeKeysBase: ["data", "where"],
2981
+ shapeKeysProjection: ["data", "where", "select", "include"],
2982
+ supportsProjection: true
2983
+ },
2984
+ updateMany: {
2985
+ bodyKeysBase: ["data", "where"],
2986
+ bodyKeysProjection: ["data", "where"],
2987
+ shapeKeysBase: ["data", "where"],
2988
+ shapeKeysProjection: ["data", "where"],
2989
+ supportsProjection: false
2990
+ },
2991
+ updateManyAndReturn: {
2992
+ bodyKeysBase: ["data", "where"],
2993
+ bodyKeysProjection: ["data", "where", "select", "include"],
2994
+ shapeKeysBase: ["data", "where"],
2995
+ shapeKeysProjection: ["data", "where", "select", "include"],
2996
+ supportsProjection: true
2997
+ },
2998
+ upsert: {
2999
+ bodyKeysBase: ["where", "create", "update", "select", "include"],
3000
+ bodyKeysProjection: ["where", "create", "update", "select", "include"],
3001
+ shapeKeysBase: ["where", "create", "update", "select", "include"],
3002
+ shapeKeysProjection: ["where", "create", "update", "select", "include"],
3003
+ supportsProjection: true
3004
+ },
3005
+ delete: {
3006
+ bodyKeysBase: ["where"],
3007
+ bodyKeysProjection: ["where", "select", "include"],
3008
+ shapeKeysBase: ["where"],
3009
+ shapeKeysProjection: ["where", "select", "include"],
3010
+ supportsProjection: true
3011
+ },
3012
+ deleteMany: {
3013
+ bodyKeysBase: ["where"],
3014
+ bodyKeysProjection: ["where"],
3015
+ shapeKeysBase: ["where"],
3016
+ shapeKeysProjection: ["where"],
3017
+ supportsProjection: false
3018
+ }
3019
+ };
3020
+ var bodyKeyCache = /* @__PURE__ */ new Map();
3021
+ var shapeKeyCache = /* @__PURE__ */ new Map();
3022
+ function getAllowedBodyKeys(method, withProjection) {
3023
+ const cacheKey = `${method}\0${withProjection ? "p" : "b"}`;
3024
+ const cached = bodyKeyCache.get(cacheKey);
3025
+ if (cached)
3026
+ return cached;
3027
+ const spec = MUTATION_OPERATION_SPECS[method];
3028
+ if (!spec)
3029
+ throw new Error(`Unknown mutation method "${method}"`);
3030
+ const keys = withProjection && spec.supportsProjection ? spec.bodyKeysProjection : spec.bodyKeysBase;
3031
+ const set = new Set(keys);
3032
+ bodyKeyCache.set(cacheKey, set);
3033
+ return set;
3034
+ }
3035
+ function getAllowedShapeKeys(method, withProjection) {
3036
+ const cacheKey = `${method}\0${withProjection ? "p" : "b"}`;
3037
+ const cached = shapeKeyCache.get(cacheKey);
3038
+ if (cached)
3039
+ return cached;
3040
+ const spec = MUTATION_OPERATION_SPECS[method];
3041
+ if (!spec)
3042
+ throw new Error(`Unknown mutation method "${method}"`);
3043
+ const keys = withProjection && spec.supportsProjection ? spec.shapeKeysProjection : spec.shapeKeysBase;
3044
+ const set = new Set(keys);
3045
+ shapeKeyCache.set(cacheKey, set);
3046
+ return set;
3047
+ }
2934
3048
 
2935
3049
  // src/runtime/query-builder.ts
2936
3050
  var METHOD_ALLOWED_ARGS = READ_METHOD_ALLOWED_ARGS;
@@ -3031,6 +3145,90 @@ function createQueryBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
3031
3145
  }
3032
3146
  return shapeOrFn;
3033
3147
  }
3148
+ function buildGroupByOrderBySchema(model, orderBy, by, sortEnum) {
3149
+ const bySet = new Set(by);
3150
+ if (orderBy === true) {
3151
+ const groupByOrderFields2 = {};
3152
+ for (const field of by) {
3153
+ groupByOrderFields2[field] = sortEnum.optional();
3154
+ }
3155
+ groupByOrderFields2._count = sortEnum.optional();
3156
+ const singleSchema2 = strictObjectRequiringOne(
3157
+ groupByOrderFields2,
3158
+ "orderBy must specify at least one field"
3159
+ );
3160
+ return z8.union([
3161
+ singleSchema2,
3162
+ z8.preprocess(coerceToArray, z8.array(singleSchema2).min(1))
3163
+ ]).optional();
3164
+ }
3165
+ if (!isPlainObject(orderBy)) {
3166
+ throw new ShapeError(
3167
+ `groupBy orderBy shape on model "${model}" must be true or an object of fields`
3168
+ );
3169
+ }
3170
+ if (Object.keys(orderBy).length === 0) {
3171
+ throw new ShapeError(
3172
+ `Empty groupBy orderBy config on model "${model}". Define at least one field.`
3173
+ );
3174
+ }
3175
+ const groupByOrderFields = {};
3176
+ for (const [fieldName, config] of Object.entries(orderBy)) {
3177
+ if (fieldName === "_count") {
3178
+ if (config === true) {
3179
+ groupByOrderFields._count = sortEnum.optional();
3180
+ } else if (isPlainObject(config)) {
3181
+ if (Object.keys(config).length === 0) {
3182
+ throw new ShapeError(
3183
+ `Empty groupBy orderBy "_count" config on model "${model}". Define at least one by-field.`
3184
+ );
3185
+ }
3186
+ const countFields = {};
3187
+ for (const [countField, countConfig] of Object.entries(config)) {
3188
+ if (countConfig !== true) {
3189
+ throw new ShapeError(
3190
+ `groupBy orderBy "_count.${countField}" config on model "${model}" must be true`
3191
+ );
3192
+ }
3193
+ if (!bySet.has(countField)) {
3194
+ throw new ShapeError(
3195
+ `orderBy _count field "${countField}" must be included in "by" for groupBy`
3196
+ );
3197
+ }
3198
+ countFields[countField] = sortEnum.optional();
3199
+ }
3200
+ groupByOrderFields._count = strictObjectRequiringOne(
3201
+ countFields,
3202
+ "orderBy._count must specify at least one field"
3203
+ ).optional();
3204
+ } else {
3205
+ throw new ShapeError(
3206
+ `groupBy orderBy "_count" config on model "${model}" must be true or an object of by-fields`
3207
+ );
3208
+ }
3209
+ continue;
3210
+ }
3211
+ if (config !== true) {
3212
+ throw new ShapeError(
3213
+ `groupBy orderBy field "${fieldName}" config on model "${model}" must be true`
3214
+ );
3215
+ }
3216
+ if (!bySet.has(fieldName)) {
3217
+ throw new ShapeError(
3218
+ `orderBy field "${fieldName}" must be included in "by" for groupBy`
3219
+ );
3220
+ }
3221
+ groupByOrderFields[fieldName] = sortEnum.optional();
3222
+ }
3223
+ const singleSchema = strictObjectRequiringOne(
3224
+ groupByOrderFields,
3225
+ "orderBy must specify at least one field"
3226
+ );
3227
+ return z8.union([
3228
+ singleSchema,
3229
+ z8.preprocess(coerceToArray, z8.array(singleSchema).min(1))
3230
+ ]).optional();
3231
+ }
3034
3232
  function buildShapeZodSchema(model, method, shape) {
3035
3233
  validateShapeArgs(method, shape);
3036
3234
  validateUniqueWhere(model, method, shape);
@@ -3070,73 +3268,19 @@ function createQueryBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
3070
3268
  }
3071
3269
  if (shape.orderBy) {
3072
3270
  if (method === "groupBy" && shape.by) {
3073
- const sortEnum = z7.enum(["asc", "desc"]);
3074
- const bySet = new Set(shape.by);
3271
+ const sortEnum = z8.enum(["asc", "desc"]);
3272
+ schemaFields.orderBy = buildGroupByOrderBySchema(
3273
+ model,
3274
+ shape.orderBy,
3275
+ shape.by,
3276
+ sortEnum
3277
+ );
3278
+ } else {
3075
3279
  if (shape.orderBy === true) {
3076
- const groupByOrderFields = {};
3077
- for (const field of shape.by) {
3078
- groupByOrderFields[field] = sortEnum.optional();
3079
- }
3080
- groupByOrderFields._count = sortEnum.optional();
3081
- const fieldKeys = Object.keys(groupByOrderFields);
3082
- const singleSchema = z7.object(groupByOrderFields).strict().refine(
3083
- (v) => fieldKeys.some(
3084
- (k) => v[k] !== void 0
3085
- ),
3086
- { message: "orderBy must specify at least one field" }
3087
- );
3088
- schemaFields.orderBy = z7.union([
3089
- singleSchema,
3090
- z7.preprocess(coerceToArray, z7.array(singleSchema).min(1))
3091
- ]).optional();
3092
- } else {
3093
- const groupByOrderFields = {};
3094
- for (const [fieldName, config] of Object.entries(shape.orderBy)) {
3095
- if (fieldName === "_count") {
3096
- if (config === true) {
3097
- groupByOrderFields._count = sortEnum.optional();
3098
- } else if (typeof config === "object" && config !== null) {
3099
- const countFields = {};
3100
- for (const countField of Object.keys(config)) {
3101
- if (!bySet.has(countField)) {
3102
- throw new ShapeError(
3103
- `orderBy _count field "${countField}" must be included in "by" for groupBy`
3104
- );
3105
- }
3106
- countFields[countField] = sortEnum.optional();
3107
- }
3108
- const countKeys = Object.keys(countFields);
3109
- groupByOrderFields._count = z7.object(countFields).strict().refine(
3110
- (v) => countKeys.some(
3111
- (k) => v[k] !== void 0
3112
- ),
3113
- {
3114
- message: "orderBy._count must specify at least one field"
3115
- }
3116
- ).optional();
3117
- }
3118
- continue;
3119
- }
3120
- if (!bySet.has(fieldName)) {
3121
- throw new ShapeError(
3122
- `orderBy field "${fieldName}" must be included in "by" for groupBy`
3123
- );
3124
- }
3125
- groupByOrderFields[fieldName] = sortEnum.optional();
3126
- }
3127
- const fieldKeys = Object.keys(groupByOrderFields);
3128
- const singleSchema = z7.object(groupByOrderFields).strict().refine(
3129
- (v) => fieldKeys.some(
3130
- (k) => v[k] !== void 0
3131
- ),
3132
- { message: "orderBy must specify at least one field" }
3280
+ throw new ShapeError(
3281
+ `Shape config "orderBy: true" is only supported for groupBy. Define an object of allowed fields.`
3133
3282
  );
3134
- schemaFields.orderBy = z7.union([
3135
- singleSchema,
3136
- z7.preprocess(coerceToArray, z7.array(singleSchema).min(1))
3137
- ]).optional();
3138
3283
  }
3139
- } else {
3140
3284
  schemaFields.orderBy = argsBuilder.buildOrderBySchema(
3141
3285
  model,
3142
3286
  shape.orderBy
@@ -3144,19 +3288,16 @@ function createQueryBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
3144
3288
  }
3145
3289
  }
3146
3290
  if (shape.cursor) {
3147
- schemaFields.cursor = argsBuilder.buildCursorSchema(
3148
- model,
3149
- shape.cursor
3150
- );
3291
+ schemaFields.cursor = argsBuilder.buildCursorSchema(model, shape.cursor);
3151
3292
  }
3152
- if (shape.take) {
3293
+ if (shape.take !== void 0) {
3153
3294
  schemaFields.take = argsBuilder.buildTakeSchema(shape.take);
3154
3295
  }
3155
3296
  if (shape.skip !== void 0) {
3156
3297
  if (shape.skip !== true) {
3157
3298
  throw new ShapeError('Shape config "skip" must be true');
3158
3299
  }
3159
- schemaFields.skip = z7.number().int().min(0).optional();
3300
+ schemaFields.skip = z8.number().int().min(0).optional();
3160
3301
  }
3161
3302
  if (shape.distinct) {
3162
3303
  schemaFields.distinct = argsBuilder.buildDistinctSchema(
@@ -3203,13 +3344,10 @@ function createQueryBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
3203
3344
  schemaFields.by = argsBuilder.buildBySchema(model, shape.by);
3204
3345
  }
3205
3346
  if (shape.having) {
3206
- schemaFields.having = argsBuilder.buildHavingSchema(
3207
- model,
3208
- shape.having
3209
- );
3347
+ schemaFields.having = argsBuilder.buildHavingSchema(model, shape.having);
3210
3348
  }
3211
3349
  return {
3212
- zodSchema: z7.object(schemaFields).strict(),
3350
+ zodSchema: z8.object(schemaFields).strict(),
3213
3351
  forcedWhere,
3214
3352
  forcedOnlyWhereKeys,
3215
3353
  forcedIncludeTree,
@@ -3402,22 +3540,18 @@ function buildScopedUniqueWhere(existingWhere, conditions, scopeFks, log, model)
3402
3540
  allConditions.push(...conditions);
3403
3541
  return { ...topLevel, AND: allConditions };
3404
3542
  }
3405
- function isComparableScopeValue(v) {
3406
- const t = typeof v;
3407
- return t === "string" || t === "number" || t === "bigint";
3408
- }
3409
- function looseEqual(a, b, log, fk) {
3543
+ function scopeValuesEqual(a, b) {
3410
3544
  if (a === b)
3411
3545
  return true;
3412
- if (!isComparableScopeValue(a) || !isComparableScopeValue(b))
3413
- return false;
3414
- const eq = String(a) === String(b);
3415
- if (eq && log && fk) {
3416
- log.warn(
3417
- `prisma-guard: Scope value for "${fk}" matched via type coercion (${typeof a} ${String(a)} vs ${typeof b} ${String(b)}). Consider normalizing types in the context function.`
3418
- );
3546
+ const aIsBig = typeof a === "bigint";
3547
+ const bIsBig = typeof b === "bigint";
3548
+ if (aIsBig && typeof b === "number") {
3549
+ return Number.isInteger(b) && a === BigInt(b);
3419
3550
  }
3420
- return eq;
3551
+ if (bIsBig && typeof a === "number") {
3552
+ return Number.isInteger(a) && b === BigInt(a);
3553
+ }
3554
+ return false;
3421
3555
  }
3422
3556
  function buildFkSelect(fks) {
3423
3557
  const select = {};
@@ -3707,7 +3841,7 @@ async function handleFindUnique(args, query, conditions, scopes, operation, log,
3707
3841
  const result = await query(nextArgs);
3708
3842
  if (result === null)
3709
3843
  return result;
3710
- if (typeof result !== "object" || result === null) {
3844
+ if (typeof result !== "object") {
3711
3845
  throw new ShapeError(
3712
3846
  `${operation} on model "${model}" returned a non-object, non-null result`
3713
3847
  );
@@ -3738,7 +3872,7 @@ async function handleFindUnique(args, query, conditions, scopes, operation, log,
3738
3872
  `prisma-guard: Scope verification re-query on model "${model}" returned null for an existing ${operation} result. The record may have been deleted between the original query and verification.`
3739
3873
  );
3740
3874
  }
3741
- if (typeof verifyResult !== "object" || verifyResult === null) {
3875
+ if (typeof verifyResult !== "object") {
3742
3876
  throw new PolicyError(
3743
3877
  `prisma-guard: Scope verification re-query on model "${model}" returned a non-object result.`
3744
3878
  );
@@ -3752,7 +3886,7 @@ async function handleFindUnique(args, query, conditions, scopes, operation, log,
3752
3886
  `prisma-guard: Cannot verify scope on model "${model}" \u2014 FK field "${fk}" not present in verification result. Ensure "${fk}" is selectable on model "${model}" (not excluded by select or field-level access).`
3753
3887
  );
3754
3888
  }
3755
- if (!looseEqual(verifyObj[fk], value, log, fk)) {
3889
+ if (!scopeValuesEqual(verifyObj[fk], value)) {
3756
3890
  if (operation === "findUniqueOrThrow") {
3757
3891
  throw new PolicyError(
3758
3892
  `prisma-guard: Record on model "${model}" not accessible in current scope`
@@ -3772,97 +3906,158 @@ async function handleFindUnique(args, query, conditions, scopes, operation, log,
3772
3906
  }
3773
3907
 
3774
3908
  // src/runtime/model-guard.ts
3909
+ import { z as z11 } from "zod";
3910
+
3911
+ // src/runtime/model-guard-data.ts
3912
+ import { z as z10 } from "zod";
3913
+
3914
+ // src/runtime/unique-selector-schema.ts
3775
3915
  import { z as z9 } from "zod";
3916
+ function buildUniqueSelectorSchema(parentModel, parentField, relatedModel, config, typeMap, uniqueMap, enumMap, scalarBase, context) {
3917
+ const modelFields = typeMap[relatedModel];
3918
+ if (!modelFields) {
3919
+ throw new ShapeError(
3920
+ `Unknown related model "${relatedModel}" for ${context} on "${parentModel}.${parentField}"`
3921
+ );
3922
+ }
3923
+ const constraints = uniqueMap[relatedModel] ?? [];
3924
+ if (constraints.length === 0) {
3925
+ throw new ShapeError(
3926
+ `${context} on "${parentModel}.${parentField}" requires related model "${relatedModel}" to have at least one unique constraint`
3927
+ );
3928
+ }
3929
+ const configKeys = Object.keys(config);
3930
+ if (configKeys.length === 0) {
3931
+ throw new ShapeError(
3932
+ `${context} on "${parentModel}.${parentField}" must define at least one unique selector. Available: ${formatUniqueConstraints(constraints)}`
3933
+ );
3934
+ }
3935
+ const fieldSchemas = {};
3936
+ const fieldKeys = [];
3937
+ for (const [key, value] of Object.entries(config)) {
3938
+ const compoundConstraint = constraints.find(
3939
+ (c) => c.selector === key && c.fields.length > 1
3940
+ );
3941
+ if (compoundConstraint) {
3942
+ if (!isPlainObject(value)) {
3943
+ throw new ShapeError(
3944
+ `Compound unique selector "${key}" in ${context} on "${parentModel}.${parentField}" must be an object with fields: ${compoundConstraint.fields.join(", ")}`
3945
+ );
3946
+ }
3947
+ const allowed = new Set(compoundConstraint.fields);
3948
+ const nestedKeys = Object.keys(value);
3949
+ for (const nestedKey of nestedKeys) {
3950
+ if (!allowed.has(nestedKey)) {
3951
+ throw new ShapeError(
3952
+ `Unknown field "${nestedKey}" in compound unique selector "${key}" on "${parentModel}.${parentField}". Allowed: ${compoundConstraint.fields.join(", ")}`
3953
+ );
3954
+ }
3955
+ }
3956
+ for (const field of compoundConstraint.fields) {
3957
+ if (!(field in value)) {
3958
+ throw new ShapeError(
3959
+ `Missing field "${field}" in compound unique selector "${key}" on "${parentModel}.${parentField}"`
3960
+ );
3961
+ }
3962
+ const fieldValue = value[field];
3963
+ if (fieldValue !== true) {
3964
+ throw new ShapeError(
3965
+ `Field "${field}" in compound unique selector "${key}" on "${parentModel}.${parentField}" must be true`
3966
+ );
3967
+ }
3968
+ }
3969
+ const nestedSchemas = {};
3970
+ for (const field of compoundConstraint.fields) {
3971
+ const fieldMeta2 = modelFields[field];
3972
+ if (!fieldMeta2) {
3973
+ throw new ShapeError(
3974
+ `Unknown field "${field}" on related model "${relatedModel}"`
3975
+ );
3976
+ }
3977
+ if (fieldMeta2.isRelation) {
3978
+ throw new ShapeError(
3979
+ `Relation field "${field}" cannot be used in compound unique selector`
3980
+ );
3981
+ }
3982
+ nestedSchemas[field] = buildDirectScalarSchema(
3983
+ fieldMeta2,
3984
+ enumMap,
3985
+ scalarBase
3986
+ );
3987
+ }
3988
+ fieldSchemas[key] = z9.object(nestedSchemas).strict().optional();
3989
+ fieldKeys.push(key);
3990
+ continue;
3991
+ }
3992
+ const singleConstraint = constraints.find(
3993
+ (c) => c.fields.length === 1 && c.fields[0] === key && c.selector === key
3994
+ );
3995
+ if (!singleConstraint) {
3996
+ const available = formatUniqueConstraints(constraints);
3997
+ throw new ShapeError(
3998
+ `Field "${key}" in ${context} on "${parentModel}.${parentField}" is not a unique selector on model "${relatedModel}". Available: ${available}`
3999
+ );
4000
+ }
4001
+ if (value !== true) {
4002
+ throw new ShapeError(
4003
+ `Field "${key}" in ${context} on "${parentModel}.${parentField}" must be true`
4004
+ );
4005
+ }
4006
+ const fieldMeta = modelFields[key];
4007
+ if (!fieldMeta) {
4008
+ throw new ShapeError(
4009
+ `Unknown field "${key}" on related model "${relatedModel}"`
4010
+ );
4011
+ }
4012
+ if (fieldMeta.isRelation) {
4013
+ throw new ShapeError(
4014
+ `Relation field "${key}" cannot be used in unique selector`
4015
+ );
4016
+ }
4017
+ fieldSchemas[key] = buildDirectScalarSchema(
4018
+ fieldMeta,
4019
+ enumMap,
4020
+ scalarBase
4021
+ ).optional();
4022
+ fieldKeys.push(key);
4023
+ }
4024
+ return z9.object(fieldSchemas).strict().refine(
4025
+ (v) => fieldKeys.some((k) => v[k] !== void 0),
4026
+ {
4027
+ message: `${context} on "${parentModel}.${parentField}" requires at least one unique selector value`
4028
+ }
4029
+ );
4030
+ }
3776
4031
 
3777
4032
  // src/runtime/model-guard-data.ts
3778
- import { z as z8 } from "zod";
3779
- var ALLOWED_BODY_KEYS_CREATE = /* @__PURE__ */ new Set(["data"]);
3780
- var ALLOWED_BODY_KEYS_CREATE_PROJECTION = /* @__PURE__ */ new Set([
3781
- "data",
3782
- "select",
3783
- "include"
3784
- ]);
3785
- var ALLOWED_BODY_KEYS_CREATE_MANY = /* @__PURE__ */ new Set([
3786
- "data",
3787
- "skipDuplicates"
3788
- ]);
3789
- var ALLOWED_BODY_KEYS_CREATE_MANY_PROJECTION = /* @__PURE__ */ new Set([
3790
- "data",
3791
- "select",
3792
- "include",
3793
- "skipDuplicates"
3794
- ]);
3795
- var ALLOWED_BODY_KEYS_UPDATE = /* @__PURE__ */ new Set(["data", "where"]);
3796
- var ALLOWED_BODY_KEYS_UPDATE_PROJECTION = /* @__PURE__ */ new Set([
3797
- "data",
3798
- "where",
3799
- "select",
3800
- "include"
3801
- ]);
3802
- var ALLOWED_BODY_KEYS_DELETE = /* @__PURE__ */ new Set(["where"]);
3803
- var ALLOWED_BODY_KEYS_DELETE_PROJECTION = /* @__PURE__ */ new Set([
3804
- "where",
3805
- "select",
3806
- "include"
3807
- ]);
3808
- var ALLOWED_BODY_KEYS_UPSERT = /* @__PURE__ */ new Set([
3809
- "where",
3810
- "create",
3811
- "update",
3812
- "select",
3813
- "include"
3814
- ]);
3815
- var VALID_SHAPE_KEYS_CREATE = /* @__PURE__ */ new Set(["data"]);
3816
- var VALID_SHAPE_KEYS_CREATE_PROJECTION = /* @__PURE__ */ new Set([
3817
- "data",
3818
- "select",
3819
- "include"
3820
- ]);
3821
- var VALID_SHAPE_KEYS_UPDATE = /* @__PURE__ */ new Set(["data", "where"]);
3822
- var VALID_SHAPE_KEYS_UPDATE_PROJECTION = /* @__PURE__ */ new Set([
3823
- "data",
3824
- "where",
3825
- "select",
3826
- "include"
3827
- ]);
3828
- var VALID_SHAPE_KEYS_DELETE = /* @__PURE__ */ new Set(["where"]);
3829
- var VALID_SHAPE_KEYS_DELETE_PROJECTION = /* @__PURE__ */ new Set([
3830
- "where",
3831
- "select",
3832
- "include"
3833
- ]);
3834
- var VALID_SHAPE_KEYS_UPSERT = /* @__PURE__ */ new Set([
3835
- "where",
3836
- "create",
3837
- "update",
3838
- "select",
3839
- "include"
3840
- ]);
3841
- var KNOWN_RELATION_WRITE_OPS = /* @__PURE__ */ new Set([
3842
- "connect",
3843
- "connectOrCreate",
3844
- "create",
3845
- "createMany",
3846
- "disconnect",
3847
- "delete",
3848
- "set",
3849
- "update",
3850
- "updateMany",
3851
- "upsert",
3852
- "deleteMany"
3853
- ]);
3854
- function validateMutationBodyKeys(body, allowed, method) {
3855
- for (const key of Object.keys(body)) {
4033
+ var RELATION_OP_ALLOWED_KEYS = {
4034
+ connectOrCreate: /* @__PURE__ */ new Set(["where", "create"]),
4035
+ createMany: /* @__PURE__ */ new Set(["data", "skipDuplicates"]),
4036
+ "update.toMany": /* @__PURE__ */ new Set(["where", "data"]),
4037
+ updateMany: /* @__PURE__ */ new Set(["where", "data"]),
4038
+ "upsert.toOne": /* @__PURE__ */ new Set(["where", "create", "update"]),
4039
+ "upsert.toMany": /* @__PURE__ */ new Set(["where", "create", "update"])
4040
+ };
4041
+ function validateRelationOpKeys(actual, opKey, model, field, opLabel) {
4042
+ const allowed = RELATION_OP_ALLOWED_KEYS[opKey];
4043
+ if (!allowed)
4044
+ return;
4045
+ for (const key of Object.keys(actual)) {
3856
4046
  if (!allowed.has(key)) {
3857
4047
  throw new ShapeError(
3858
- `Unexpected key "${key}" in ${method} body. Allowed keys: ${[...allowed].join(", ")}`
4048
+ `Unknown key "${key}" in ${opLabel} config on "${model}.${field}". Allowed: ${[...allowed].join(", ")}`
3859
4049
  );
3860
4050
  }
3861
4051
  }
3862
4052
  }
3863
- function validateMutationShapeKeys(shape, allowed, method) {
3864
- for (const key of Object.keys(shape)) {
4053
+ function validateAllowedKeys(value, allowed, method, kind) {
4054
+ for (const key of Object.keys(value)) {
3865
4055
  if (!allowed.has(key)) {
4056
+ if (kind === "body") {
4057
+ throw new ShapeError(
4058
+ `Unexpected key "${key}" in ${method} body. Allowed keys: ${[...allowed].join(", ")}`
4059
+ );
4060
+ }
3866
4061
  throw new ShapeError(
3867
4062
  `Shape key "${key}" not valid for ${method}. Allowed: ${[...allowed].join(", ")}`
3868
4063
  );
@@ -3904,24 +4099,24 @@ function buildWhereFieldsSchema(model, config, typeMap, schemaBuilder) {
3904
4099
  for (const [fieldName, value] of Object.entries(config)) {
3905
4100
  if (value !== true)
3906
4101
  throw new ShapeError(
3907
- `Field "${fieldName}" in connect/where config must be true`
4102
+ `Field "${fieldName}" in filter config must be true`
3908
4103
  );
3909
4104
  const meta = modelFields[fieldName];
3910
4105
  if (!meta)
3911
4106
  throw new ShapeError(`Unknown field "${fieldName}" on model "${model}"`);
3912
4107
  if (meta.isRelation)
3913
4108
  throw new ShapeError(
3914
- `Relation field "${fieldName}" cannot be used in connect/where`
4109
+ `Relation field "${fieldName}" cannot be used in filter`
3915
4110
  );
3916
4111
  fieldSchemas[fieldName] = schemaBuilder.buildFieldSchema(model, fieldName).optional();
3917
4112
  fieldKeys.push(fieldName);
3918
4113
  }
3919
- return z8.object(fieldSchemas).strict().refine(
4114
+ return z10.object(fieldSchemas).strict().refine(
3920
4115
  (v) => fieldKeys.some((k) => v[k] !== void 0),
3921
- { message: `At least one field required in connect/where` }
4116
+ { message: `At least one field required in filter` }
3922
4117
  );
3923
4118
  }
3924
- function buildNestedDataSchema(model, config, typeMap, schemaBuilder) {
4119
+ function buildNestedDataSchema(model, config, mode, typeMap, schemaBuilder) {
3925
4120
  const modelFields = typeMap[model];
3926
4121
  if (!modelFields)
3927
4122
  throw new ShapeError(`Unknown model: ${model}`);
@@ -3942,382 +4137,349 @@ function buildNestedDataSchema(model, config, typeMap, schemaBuilder) {
3942
4137
  throw new ShapeError(
3943
4138
  `updatedAt field "${fieldName}" cannot be used in nested data`
3944
4139
  );
3945
- let fieldSchema = schemaBuilder.buildFieldSchema(model, fieldName);
3946
- if (!meta.isRequired) {
3947
- fieldSchema = fieldSchema.nullable().optional();
3948
- } else if (meta.hasDefault) {
3949
- fieldSchema = fieldSchema.optional();
3950
- }
3951
- fieldSchemas[fieldName] = fieldSchema;
4140
+ if (meta.isUnsupported)
4141
+ throw new ShapeError(
4142
+ `Field "${fieldName}" on model "${model}" has an Unsupported type and cannot be used in nested data`
4143
+ );
4144
+ const baseSchema = schemaBuilder.buildFieldSchema(model, fieldName);
4145
+ fieldSchemas[fieldName] = applyCreateUpdateNullability(meta, baseSchema, {
4146
+ mode,
4147
+ handlesUndefined: false
4148
+ });
3952
4149
  }
3953
- return z8.object(fieldSchemas).strict();
4150
+ return z10.object(fieldSchemas).strict();
3954
4151
  }
3955
- function buildRelationWriteSchema(model, fieldName, relatedModelName, isList, config, typeMap, schemaBuilder) {
3956
- const relatedFields = typeMap[relatedModelName];
3957
- if (!relatedFields)
4152
+ function requirePlainObjectConfig(value, message) {
4153
+ if (!isPlainObject(value))
4154
+ throw new ShapeError(message);
4155
+ return value;
4156
+ }
4157
+ function requireNestedObject(cfg, key, message) {
4158
+ const v = cfg[key];
4159
+ if (!v || !isPlainObject(v))
4160
+ throw new ShapeError(message);
4161
+ return v;
4162
+ }
4163
+ function buildUniqueSelector(ctx, cfg, context) {
4164
+ return buildUniqueSelectorSchema(
4165
+ ctx.model,
4166
+ ctx.fieldName,
4167
+ ctx.relatedModelName,
4168
+ cfg,
4169
+ ctx.typeMap,
4170
+ ctx.uniqueMap,
4171
+ ctx.enumMap,
4172
+ ctx.scalarBase,
4173
+ context
4174
+ );
4175
+ }
4176
+ function buildNestedData(ctx, cfg, mode) {
4177
+ return buildNestedDataSchema(
4178
+ ctx.relatedModelName,
4179
+ cfg,
4180
+ mode,
4181
+ ctx.typeMap,
4182
+ ctx.schemaBuilder
4183
+ );
4184
+ }
4185
+ var handleConnect = (ctx) => {
4186
+ const cfg = requirePlainObjectConfig(
4187
+ ctx.config,
4188
+ `connect config on "${ctx.model}.${ctx.fieldName}" must be an object of unique selectors`
4189
+ );
4190
+ const schema = buildUniqueSelector(ctx, cfg, "connect");
4191
+ return wrapRelationOp(ctx.isList, schema);
4192
+ };
4193
+ var handleConnectOrCreate = (ctx) => {
4194
+ const cfg = requirePlainObjectConfig(
4195
+ ctx.config,
4196
+ `connectOrCreate config on "${ctx.model}.${ctx.fieldName}" must be an object with "where" and "create"`
4197
+ );
4198
+ validateRelationOpKeys(cfg, "connectOrCreate", ctx.model, ctx.fieldName, "connectOrCreate");
4199
+ const where = requireNestedObject(
4200
+ cfg,
4201
+ "where",
4202
+ `connectOrCreate on "${ctx.model}.${ctx.fieldName}" requires "where" object`
4203
+ );
4204
+ const create = requireNestedObject(
4205
+ cfg,
4206
+ "create",
4207
+ `connectOrCreate on "${ctx.model}.${ctx.fieldName}" requires "create" object`
4208
+ );
4209
+ const whereSchema = buildUniqueSelector(ctx, where, "connectOrCreate.where");
4210
+ const createSchema = buildNestedData(ctx, create, "create");
4211
+ const cocSchema = z10.object({ where: whereSchema, create: createSchema }).strict();
4212
+ return wrapRelationOp(ctx.isList, cocSchema);
4213
+ };
4214
+ var handleCreate = (ctx) => {
4215
+ const cfg = requirePlainObjectConfig(
4216
+ ctx.config,
4217
+ `create config on "${ctx.model}.${ctx.fieldName}" must be an object of field names`
4218
+ );
4219
+ const createSchema = buildNestedData(ctx, cfg, "create");
4220
+ return wrapRelationOp(ctx.isList, createSchema);
4221
+ };
4222
+ var handleCreateMany = (ctx) => {
4223
+ if (!ctx.isList) {
3958
4224
  throw new ShapeError(
3959
- `Unknown related model "${relatedModelName}" for field "${model}.${fieldName}"`
4225
+ `createMany is only valid on to-many relations ("${ctx.model}.${ctx.fieldName}")`
3960
4226
  );
3961
- for (const key of Object.keys(config)) {
3962
- if (!KNOWN_RELATION_WRITE_OPS.has(key)) {
3963
- throw new ShapeError(
3964
- `Unknown relation write operation "${key}" on "${model}.${fieldName}". Allowed: ${[...KNOWN_RELATION_WRITE_OPS].join(", ")}`
3965
- );
3966
- }
3967
4227
  }
3968
- const opSchemas = {};
3969
- if (config.connect !== void 0) {
3970
- if (!isPlainObject(config.connect)) {
4228
+ const cfg = requirePlainObjectConfig(
4229
+ ctx.config,
4230
+ `createMany config on "${ctx.model}.${ctx.fieldName}" must be an object`
4231
+ );
4232
+ validateRelationOpKeys(cfg, "createMany", ctx.model, ctx.fieldName, "createMany");
4233
+ const data = requireNestedObject(
4234
+ cfg,
4235
+ "data",
4236
+ `createMany on "${ctx.model}.${ctx.fieldName}" requires "data" object`
4237
+ );
4238
+ const dataSchema = buildNestedData(ctx, data, "create");
4239
+ const cmSchemaFields = {
4240
+ data: z10.preprocess(coerceToArray, z10.array(dataSchema))
4241
+ };
4242
+ if ("skipDuplicates" in cfg) {
4243
+ cmSchemaFields["skipDuplicates"] = z10.boolean().optional();
4244
+ }
4245
+ return z10.object(cmSchemaFields).strict().optional();
4246
+ };
4247
+ var handleDisconnect = (ctx) => {
4248
+ if (ctx.config === true) {
4249
+ if (ctx.isList) {
3971
4250
  throw new ShapeError(
3972
- `connect config on "${model}.${fieldName}" must be an object of field names`
4251
+ `disconnect on to-many relation "${ctx.model}.${ctx.fieldName}" requires unique selector config, not true`
3973
4252
  );
3974
4253
  }
3975
- const connectSchema = buildWhereFieldsSchema(
3976
- relatedModelName,
3977
- config.connect,
3978
- typeMap,
3979
- schemaBuilder
4254
+ return z10.literal(true).optional();
4255
+ }
4256
+ if (!isPlainObject(ctx.config)) {
4257
+ throw new ShapeError(
4258
+ `disconnect config on "${ctx.model}.${ctx.fieldName}" must be true (to-one) or an object of unique selectors`
3980
4259
  );
3981
- opSchemas["connect"] = isList ? z8.union([
3982
- connectSchema,
3983
- z8.preprocess(coerceToArray, z8.array(connectSchema))
3984
- ]).optional() : connectSchema.optional();
3985
4260
  }
3986
- if (config.connectOrCreate !== void 0) {
3987
- if (!isPlainObject(config.connectOrCreate)) {
3988
- throw new ShapeError(
3989
- `connectOrCreate config on "${model}.${fieldName}" must be an object with "where" and "create"`
3990
- );
3991
- }
3992
- const coc = config.connectOrCreate;
3993
- if (!coc.where || !isPlainObject(coc.where)) {
3994
- throw new ShapeError(
3995
- `connectOrCreate on "${model}.${fieldName}" requires "where" object`
3996
- );
3997
- }
3998
- if (!coc.create || !isPlainObject(coc.create)) {
4261
+ const schema = buildUniqueSelector(ctx, ctx.config, "disconnect");
4262
+ if (ctx.isList)
4263
+ return wrapRelationOp(true, schema);
4264
+ return z10.union([z10.literal(true), schema]).optional();
4265
+ };
4266
+ var handleDelete = (ctx) => {
4267
+ if (ctx.config === true) {
4268
+ if (ctx.isList) {
3999
4269
  throw new ShapeError(
4000
- `connectOrCreate on "${model}.${fieldName}" requires "create" object`
4270
+ `delete on to-many relation "${ctx.model}.${ctx.fieldName}" requires unique selector config, not true`
4001
4271
  );
4002
4272
  }
4003
- const whereSchema = buildWhereFieldsSchema(
4004
- relatedModelName,
4005
- coc.where,
4006
- typeMap,
4007
- schemaBuilder
4008
- );
4009
- const createSchema = buildNestedDataSchema(
4010
- relatedModelName,
4011
- coc.create,
4012
- typeMap,
4013
- schemaBuilder
4273
+ return z10.literal(true).optional();
4274
+ }
4275
+ if (!isPlainObject(ctx.config)) {
4276
+ throw new ShapeError(
4277
+ `delete config on "${ctx.model}.${ctx.fieldName}" must be true (to-one) or an object of unique selectors`
4014
4278
  );
4015
- const cocSchema = z8.object({ where: whereSchema, create: createSchema }).strict();
4016
- opSchemas["connectOrCreate"] = isList ? z8.union([cocSchema, z8.preprocess(coerceToArray, z8.array(cocSchema))]).optional() : cocSchema.optional();
4017
4279
  }
4018
- if (config.create !== void 0) {
4019
- if (!isPlainObject(config.create)) {
4020
- throw new ShapeError(
4021
- `create config on "${model}.${fieldName}" must be an object of field names`
4022
- );
4023
- }
4024
- const createSchema = buildNestedDataSchema(
4025
- relatedModelName,
4026
- config.create,
4027
- typeMap,
4028
- schemaBuilder
4280
+ const schema = buildUniqueSelector(ctx, ctx.config, "delete");
4281
+ if (ctx.isList)
4282
+ return wrapRelationOp(true, schema);
4283
+ return z10.union([z10.literal(true), schema]).optional();
4284
+ };
4285
+ var handleSet = (ctx) => {
4286
+ if (!ctx.isList) {
4287
+ throw new ShapeError(
4288
+ `set is only valid on to-many relations ("${ctx.model}.${ctx.fieldName}")`
4029
4289
  );
4030
- opSchemas["create"] = isList ? z8.union([
4031
- createSchema,
4032
- z8.preprocess(coerceToArray, z8.array(createSchema))
4033
- ]).optional() : createSchema.optional();
4034
4290
  }
4035
- if (config.createMany !== void 0) {
4036
- if (!isList) {
4037
- throw new ShapeError(
4038
- `createMany is only valid on to-many relations ("${model}.${fieldName}")`
4039
- );
4040
- }
4041
- if (!isPlainObject(config.createMany)) {
4042
- throw new ShapeError(
4043
- `createMany config on "${model}.${fieldName}" must be an object`
4044
- );
4045
- }
4046
- const cmConfig = config.createMany;
4047
- if (!cmConfig.data || !isPlainObject(cmConfig.data)) {
4048
- throw new ShapeError(
4049
- `createMany on "${model}.${fieldName}" requires "data" object`
4050
- );
4051
- }
4052
- const dataSchema = buildNestedDataSchema(
4053
- relatedModelName,
4054
- cmConfig.data,
4055
- typeMap,
4056
- schemaBuilder
4291
+ const cfg = requirePlainObjectConfig(
4292
+ ctx.config,
4293
+ `set config on "${ctx.model}.${ctx.fieldName}" must be an object of unique selectors`
4294
+ );
4295
+ const schema = buildUniqueSelector(ctx, cfg, "set");
4296
+ return wrapRelationOp(true, schema);
4297
+ };
4298
+ var handleUpdate = (ctx) => {
4299
+ const cfg = requirePlainObjectConfig(
4300
+ ctx.config,
4301
+ `update config on "${ctx.model}.${ctx.fieldName}" must be an object`
4302
+ );
4303
+ if (ctx.isList) {
4304
+ validateRelationOpKeys(cfg, "update.toMany", ctx.model, ctx.fieldName, "update");
4305
+ const where = requireNestedObject(
4306
+ cfg,
4307
+ "where",
4308
+ `update on to-many "${ctx.model}.${ctx.fieldName}" requires "where" object`
4057
4309
  );
4058
- const cmSchemaFields = {
4059
- data: z8.preprocess(coerceToArray, z8.array(dataSchema))
4060
- };
4061
- if ("skipDuplicates" in cmConfig) {
4062
- cmSchemaFields["skipDuplicates"] = z8.boolean().optional();
4063
- }
4064
- opSchemas["createMany"] = z8.object(cmSchemaFields).strict().optional();
4310
+ const data = requireNestedObject(
4311
+ cfg,
4312
+ "data",
4313
+ `update on to-many "${ctx.model}.${ctx.fieldName}" requires "data" object`
4314
+ );
4315
+ const whereSchema = buildUniqueSelector(ctx, where, "update.where");
4316
+ const dataSchema2 = buildNestedData(ctx, data, "update");
4317
+ const updateSchema = z10.object({ where: whereSchema, data: dataSchema2 }).strict();
4318
+ return wrapRelationOp(true, updateSchema);
4065
4319
  }
4066
- if (config.disconnect !== void 0) {
4067
- if (config.disconnect === true) {
4068
- if (isList) {
4069
- throw new ShapeError(
4070
- `disconnect on to-many relation "${model}.${fieldName}" requires field config, not true`
4071
- );
4072
- }
4073
- opSchemas["disconnect"] = z8.literal(true).optional();
4074
- } else if (isPlainObject(config.disconnect)) {
4075
- const disconnectSchema = buildWhereFieldsSchema(
4076
- relatedModelName,
4077
- config.disconnect,
4078
- typeMap,
4079
- schemaBuilder
4080
- );
4081
- if (isList) {
4082
- opSchemas["disconnect"] = z8.union([
4083
- disconnectSchema,
4084
- z8.preprocess(coerceToArray, z8.array(disconnectSchema))
4085
- ]).optional();
4086
- } else {
4087
- opSchemas["disconnect"] = z8.union([z8.literal(true), disconnectSchema]).optional();
4088
- }
4089
- } else {
4090
- throw new ShapeError(
4091
- `disconnect config on "${model}.${fieldName}" must be true (to-one) or an object of field names`
4092
- );
4093
- }
4320
+ const dataSchema = buildNestedData(ctx, cfg, "update");
4321
+ return dataSchema.optional();
4322
+ };
4323
+ var handleUpsert = (ctx) => {
4324
+ const cfg = requirePlainObjectConfig(
4325
+ ctx.config,
4326
+ `upsert config on "${ctx.model}.${ctx.fieldName}" must be an object`
4327
+ );
4328
+ validateRelationOpKeys(
4329
+ cfg,
4330
+ ctx.isList ? "upsert.toMany" : "upsert.toOne",
4331
+ ctx.model,
4332
+ ctx.fieldName,
4333
+ "upsert"
4334
+ );
4335
+ const create = requireNestedObject(
4336
+ cfg,
4337
+ "create",
4338
+ `upsert on "${ctx.model}.${ctx.fieldName}" requires "create" object`
4339
+ );
4340
+ const update = requireNestedObject(
4341
+ cfg,
4342
+ "update",
4343
+ `upsert on "${ctx.model}.${ctx.fieldName}" requires "update" object`
4344
+ );
4345
+ const createSchema = buildNestedData(ctx, create, "create");
4346
+ const updateSchema = buildNestedData(ctx, update, "update");
4347
+ if (ctx.isList) {
4348
+ const where = requireNestedObject(
4349
+ cfg,
4350
+ "where",
4351
+ `upsert on to-many "${ctx.model}.${ctx.fieldName}" requires "where" object`
4352
+ );
4353
+ const whereSchema = buildUniqueSelector(ctx, where, "upsert.where");
4354
+ const upsertSchema2 = z10.object({ where: whereSchema, create: createSchema, update: updateSchema }).strict();
4355
+ return wrapRelationOp(true, upsertSchema2);
4094
4356
  }
4095
- if (config.delete !== void 0) {
4096
- if (config.delete === true) {
4097
- if (isList) {
4098
- throw new ShapeError(
4099
- `delete on to-many relation "${model}.${fieldName}" requires field config, not true`
4100
- );
4101
- }
4102
- opSchemas["delete"] = z8.literal(true).optional();
4103
- } else if (isPlainObject(config.delete)) {
4104
- const deleteSchema = buildWhereFieldsSchema(
4105
- relatedModelName,
4106
- config.delete,
4107
- typeMap,
4108
- schemaBuilder
4109
- );
4110
- if (isList) {
4111
- opSchemas["delete"] = z8.union([
4112
- deleteSchema,
4113
- z8.preprocess(coerceToArray, z8.array(deleteSchema))
4114
- ]).optional();
4115
- } else {
4116
- opSchemas["delete"] = z8.union([z8.literal(true), deleteSchema]).optional();
4117
- }
4118
- } else {
4357
+ const hasWhereKey = "where" in cfg;
4358
+ if (hasWhereKey) {
4359
+ if (!isPlainObject(cfg.where)) {
4119
4360
  throw new ShapeError(
4120
- `delete config on "${model}.${fieldName}" must be true (to-one) or an object of field names`
4361
+ `upsert on to-one "${ctx.model}.${ctx.fieldName}" has invalid "where": must be a plain object of unique selectors`
4121
4362
  );
4122
4363
  }
4364
+ const whereSchema = buildUniqueSelector(ctx, cfg.where, "upsert.where");
4365
+ const upsertSchema2 = z10.object({ where: whereSchema, create: createSchema, update: updateSchema }).strict();
4366
+ return upsertSchema2.optional();
4123
4367
  }
4124
- if (config.set !== void 0) {
4125
- if (!isList) {
4126
- throw new ShapeError(
4127
- `set is only valid on to-many relations ("${model}.${fieldName}")`
4128
- );
4129
- }
4130
- if (!isPlainObject(config.set)) {
4131
- throw new ShapeError(
4132
- `set config on "${model}.${fieldName}" must be an object of field names`
4133
- );
4134
- }
4135
- const setSchema = buildWhereFieldsSchema(
4136
- relatedModelName,
4137
- config.set,
4138
- typeMap,
4139
- schemaBuilder
4368
+ const upsertSchema = z10.object({ create: createSchema, update: updateSchema }).strict();
4369
+ return upsertSchema.optional();
4370
+ };
4371
+ var handleUpdateMany = (ctx) => {
4372
+ if (!ctx.isList) {
4373
+ throw new ShapeError(
4374
+ `updateMany is only valid on to-many relations ("${ctx.model}.${ctx.fieldName}")`
4140
4375
  );
4141
- opSchemas["set"] = z8.preprocess(coerceToArray, z8.array(setSchema)).optional();
4142
4376
  }
4143
- if (config.update !== void 0) {
4144
- if (!isPlainObject(config.update)) {
4145
- throw new ShapeError(
4146
- `update config on "${model}.${fieldName}" must be an object`
4147
- );
4148
- }
4149
- const updateConfig = config.update;
4150
- if (isList) {
4151
- if (!updateConfig.where || !isPlainObject(updateConfig.where)) {
4152
- throw new ShapeError(
4153
- `update on to-many "${model}.${fieldName}" requires "where" object`
4154
- );
4155
- }
4156
- if (!updateConfig.data || !isPlainObject(updateConfig.data)) {
4157
- throw new ShapeError(
4158
- `update on to-many "${model}.${fieldName}" requires "data" object`
4159
- );
4160
- }
4161
- const whereSchema = buildWhereFieldsSchema(
4162
- relatedModelName,
4163
- updateConfig.where,
4164
- typeMap,
4165
- schemaBuilder
4166
- );
4167
- const dataSchema = buildNestedDataSchema(
4168
- relatedModelName,
4169
- updateConfig.data,
4170
- typeMap,
4171
- schemaBuilder
4172
- );
4173
- const updateSchema = z8.object({ where: whereSchema, data: dataSchema }).strict();
4174
- opSchemas["update"] = z8.union([
4175
- updateSchema,
4176
- z8.preprocess(coerceToArray, z8.array(updateSchema))
4177
- ]).optional();
4178
- } else {
4179
- const dataSchema = buildNestedDataSchema(
4180
- relatedModelName,
4181
- updateConfig,
4182
- typeMap,
4183
- schemaBuilder
4184
- );
4185
- opSchemas["update"] = dataSchema.optional();
4186
- }
4187
- }
4188
- if (config.upsert !== void 0) {
4189
- if (!isPlainObject(config.upsert)) {
4190
- throw new ShapeError(
4191
- `upsert config on "${model}.${fieldName}" must be an object`
4192
- );
4193
- }
4194
- const upsertConfig = config.upsert;
4195
- if (!upsertConfig.create || !isPlainObject(upsertConfig.create)) {
4196
- throw new ShapeError(
4197
- `upsert on "${model}.${fieldName}" requires "create" object`
4198
- );
4199
- }
4200
- if (!upsertConfig.update || !isPlainObject(upsertConfig.update)) {
4201
- throw new ShapeError(
4202
- `upsert on "${model}.${fieldName}" requires "update" object`
4203
- );
4204
- }
4205
- const createSchema = buildNestedDataSchema(
4206
- relatedModelName,
4207
- upsertConfig.create,
4208
- typeMap,
4209
- schemaBuilder
4377
+ const cfg = requirePlainObjectConfig(
4378
+ ctx.config,
4379
+ `updateMany config on "${ctx.model}.${ctx.fieldName}" must be an object`
4380
+ );
4381
+ validateRelationOpKeys(cfg, "updateMany", ctx.model, ctx.fieldName, "updateMany");
4382
+ const where = requireNestedObject(
4383
+ cfg,
4384
+ "where",
4385
+ `updateMany on "${ctx.model}.${ctx.fieldName}" requires "where" object`
4386
+ );
4387
+ if (Object.keys(where).length === 0) {
4388
+ throw new ShapeError(
4389
+ `updateMany "where" on "${ctx.model}.${ctx.fieldName}" must define at least one filter field`
4210
4390
  );
4211
- const updateSchema = buildNestedDataSchema(
4212
- relatedModelName,
4213
- upsertConfig.update,
4214
- typeMap,
4215
- schemaBuilder
4391
+ }
4392
+ const data = requireNestedObject(
4393
+ cfg,
4394
+ "data",
4395
+ `updateMany on "${ctx.model}.${ctx.fieldName}" requires "data" object`
4396
+ );
4397
+ if (Object.keys(data).length === 0) {
4398
+ throw new ShapeError(
4399
+ `updateMany "data" on "${ctx.model}.${ctx.fieldName}" must define at least one field`
4216
4400
  );
4217
- if (isList) {
4218
- if (!upsertConfig.where || !isPlainObject(upsertConfig.where)) {
4219
- throw new ShapeError(
4220
- `upsert on to-many "${model}.${fieldName}" requires "where" object`
4221
- );
4222
- }
4223
- const whereSchema = buildWhereFieldsSchema(
4224
- relatedModelName,
4225
- upsertConfig.where,
4226
- typeMap,
4227
- schemaBuilder
4228
- );
4229
- const upsertSchema = z8.object({
4230
- where: whereSchema,
4231
- create: createSchema,
4232
- update: updateSchema
4233
- }).strict();
4234
- opSchemas["upsert"] = z8.union([
4235
- upsertSchema,
4236
- z8.preprocess(coerceToArray, z8.array(upsertSchema))
4237
- ]).optional();
4238
- } else {
4239
- if (upsertConfig.where) {
4240
- const whereSchema = buildWhereFieldsSchema(
4241
- relatedModelName,
4242
- upsertConfig.where,
4243
- typeMap,
4244
- schemaBuilder
4245
- );
4246
- const upsertSchema = z8.object({
4247
- where: whereSchema,
4248
- create: createSchema,
4249
- update: updateSchema
4250
- }).strict();
4251
- opSchemas["upsert"] = upsertSchema.optional();
4252
- } else {
4253
- const upsertSchema = z8.object({ create: createSchema, update: updateSchema }).strict();
4254
- opSchemas["upsert"] = upsertSchema.optional();
4255
- }
4256
- }
4257
4401
  }
4258
- if (config.updateMany !== void 0) {
4259
- if (!isList) {
4260
- throw new ShapeError(
4261
- `updateMany is only valid on to-many relations ("${model}.${fieldName}")`
4262
- );
4263
- }
4264
- if (!isPlainObject(config.updateMany)) {
4265
- throw new ShapeError(
4266
- `updateMany config on "${model}.${fieldName}" must be an object`
4267
- );
4268
- }
4269
- const umConfig = config.updateMany;
4270
- if (!umConfig.where || !isPlainObject(umConfig.where)) {
4271
- throw new ShapeError(
4272
- `updateMany on "${model}.${fieldName}" requires "where" object`
4273
- );
4274
- }
4275
- if (!umConfig.data || !isPlainObject(umConfig.data)) {
4276
- throw new ShapeError(
4277
- `updateMany on "${model}.${fieldName}" requires "data" object`
4278
- );
4279
- }
4280
- const whereSchema = buildWhereFieldsSchema(
4281
- relatedModelName,
4282
- umConfig.where,
4283
- typeMap,
4284
- schemaBuilder
4402
+ const whereSchema = buildWhereFieldsSchema(
4403
+ ctx.relatedModelName,
4404
+ where,
4405
+ ctx.typeMap,
4406
+ ctx.schemaBuilder
4407
+ );
4408
+ const dataSchema = buildNestedData(ctx, data, "update");
4409
+ const umSchema = z10.object({ where: whereSchema, data: dataSchema }).strict();
4410
+ return wrapRelationOp(true, umSchema);
4411
+ };
4412
+ var handleDeleteMany = (ctx) => {
4413
+ if (!ctx.isList) {
4414
+ throw new ShapeError(
4415
+ `deleteMany is only valid on to-many relations ("${ctx.model}.${ctx.fieldName}")`
4285
4416
  );
4286
- const dataSchema = buildNestedDataSchema(
4287
- relatedModelName,
4288
- umConfig.data,
4289
- typeMap,
4290
- schemaBuilder
4417
+ }
4418
+ const cfg = requirePlainObjectConfig(
4419
+ ctx.config,
4420
+ `deleteMany config on "${ctx.model}.${ctx.fieldName}" must be an object of allowed filter fields`
4421
+ );
4422
+ if (Object.keys(cfg).length === 0) {
4423
+ throw new ShapeError(
4424
+ `deleteMany config on "${ctx.model}.${ctx.fieldName}" is empty. Unconstrained nested deletes are not allowed. Define at least one allowed filter field.`
4291
4425
  );
4292
- const umSchema = z8.object({ where: whereSchema, data: dataSchema }).strict();
4293
- opSchemas["updateMany"] = z8.union([umSchema, z8.preprocess(coerceToArray, z8.array(umSchema))]).optional();
4294
4426
  }
4295
- if (config.deleteMany !== void 0) {
4296
- if (!isList) {
4297
- throw new ShapeError(
4298
- `deleteMany is only valid on to-many relations ("${model}.${fieldName}")`
4299
- );
4300
- }
4301
- if (!isPlainObject(config.deleteMany)) {
4427
+ const filterSchema = buildWhereFieldsSchema(
4428
+ ctx.relatedModelName,
4429
+ cfg,
4430
+ ctx.typeMap,
4431
+ ctx.schemaBuilder
4432
+ );
4433
+ return wrapRelationOp(true, filterSchema);
4434
+ };
4435
+ var RELATION_OP_HANDLERS = {
4436
+ connect: handleConnect,
4437
+ connectOrCreate: handleConnectOrCreate,
4438
+ create: handleCreate,
4439
+ createMany: handleCreateMany,
4440
+ disconnect: handleDisconnect,
4441
+ delete: handleDelete,
4442
+ set: handleSet,
4443
+ update: handleUpdate,
4444
+ upsert: handleUpsert,
4445
+ updateMany: handleUpdateMany,
4446
+ deleteMany: handleDeleteMany
4447
+ };
4448
+ var KNOWN_RELATION_WRITE_OPS = new Set(Object.keys(RELATION_OP_HANDLERS));
4449
+ function buildRelationWriteSchema(model, fieldName, relatedModelName, isList, config, typeMap, uniqueMap, enumMap, scalarBase, schemaBuilder) {
4450
+ const relatedFields = typeMap[relatedModelName];
4451
+ if (!relatedFields)
4452
+ throw new ShapeError(
4453
+ `Unknown related model "${relatedModelName}" for field "${model}.${fieldName}"`
4454
+ );
4455
+ for (const key of Object.keys(config)) {
4456
+ if (!KNOWN_RELATION_WRITE_OPS.has(key)) {
4302
4457
  throw new ShapeError(
4303
- `deleteMany config on "${model}.${fieldName}" must be an object of allowed filter fields`
4458
+ `Unknown relation write operation "${key}" on "${model}.${fieldName}". Allowed: ${[...KNOWN_RELATION_WRITE_OPS].join(", ")}`
4304
4459
  );
4305
4460
  }
4306
- const filterSchema = buildWhereFieldsSchema(
4461
+ }
4462
+ const opSchemas = {};
4463
+ for (const [op, opConfig] of Object.entries(config)) {
4464
+ if (opConfig === void 0)
4465
+ continue;
4466
+ const handler = RELATION_OP_HANDLERS[op];
4467
+ opSchemas[op] = handler({
4468
+ model,
4469
+ fieldName,
4307
4470
  relatedModelName,
4308
- config.deleteMany,
4471
+ isList,
4472
+ config: opConfig,
4309
4473
  typeMap,
4474
+ uniqueMap,
4475
+ enumMap,
4476
+ scalarBase,
4310
4477
  schemaBuilder
4311
- );
4312
- opSchemas["deleteMany"] = z8.union([
4313
- filterSchema,
4314
- z8.preprocess(coerceToArray, z8.array(filterSchema)),
4315
- z8.object({}).strict()
4316
- ]).optional();
4478
+ });
4317
4479
  }
4318
- return z8.object(opSchemas).strict();
4480
+ return z10.object(opSchemas).strict();
4319
4481
  }
4320
- function buildDataSchema(model, dataConfig, mode, typeMap, schemaBuilder, zodDefaults) {
4482
+ function buildDataSchema(model, dataConfig, mode, typeMap, uniqueMap, enumMap, scalarBase, schemaBuilder, zodDefaults) {
4321
4483
  const modelFields = typeMap[model];
4322
4484
  if (!modelFields)
4323
4485
  throw new ShapeError(`Unknown model: ${model}`);
@@ -4329,11 +4491,23 @@ function buildDataSchema(model, dataConfig, mode, typeMap, schemaBuilder, zodDef
4329
4491
  const fieldMeta = modelFields[fieldName];
4330
4492
  if (!fieldMeta) {
4331
4493
  if (isUnsupportedMarker(value)) {
4332
- schemaMap[fieldName] = z8.unknown().optional();
4333
4494
  continue;
4334
4495
  }
4335
4496
  throw new ShapeError(`Unknown field "${fieldName}" on model "${model}"`);
4336
4497
  }
4498
+ if (fieldMeta.isUnsupported) {
4499
+ if (isUnsupportedMarker(value)) {
4500
+ continue;
4501
+ }
4502
+ if (value === true || typeof value === "function") {
4503
+ throw new ShapeError(
4504
+ `Field "${fieldName}" on model "${model}" has an Unsupported type and cannot be client-controlled. Use unsupported() to acknowledge it or a forced server value.`
4505
+ );
4506
+ }
4507
+ const actualValue = isForcedValue(value) ? value.value : value;
4508
+ forced[fieldName] = deepClone(actualValue);
4509
+ continue;
4510
+ }
4337
4511
  if (fieldMeta.isRelation) {
4338
4512
  if (!isPlainObject(value)) {
4339
4513
  throw new ShapeError(
@@ -4347,6 +4521,9 @@ function buildDataSchema(model, dataConfig, mode, typeMap, schemaBuilder, zodDef
4347
4521
  fieldMeta.isList,
4348
4522
  value,
4349
4523
  typeMap,
4524
+ uniqueMap,
4525
+ enumMap,
4526
+ scalarBase,
4350
4527
  schemaBuilder
4351
4528
  ).optional();
4352
4529
  continue;
@@ -4356,7 +4533,7 @@ function buildDataSchema(model, dataConfig, mode, typeMap, schemaBuilder, zodDef
4356
4533
  `updatedAt field "${fieldName}" cannot be used in data shape`
4357
4534
  );
4358
4535
  if (typeof value === "function") {
4359
- let baseSchema = schemaBuilder.buildBaseFieldSchema(
4536
+ const baseSchema = schemaBuilder.buildBaseFieldSchema(
4360
4537
  model,
4361
4538
  fieldName
4362
4539
  );
@@ -4374,46 +4551,22 @@ function buildDataSchema(model, dataConfig, mode, typeMap, schemaBuilder, zodDef
4374
4551
  `Inline refine for "${model}.${fieldName}" must return a Zod schema`
4375
4552
  );
4376
4553
  }
4377
- let fieldSchema = refined;
4378
- const handlesUndefined = schemaProducesValueForUndefined(fieldSchema);
4379
- if (mode === "create") {
4380
- if (!fieldMeta.isRequired) {
4381
- fieldSchema = handlesUndefined ? fieldSchema.nullable() : fieldSchema.nullable().optional();
4382
- } else if (fieldMeta.hasDefault) {
4383
- if (!handlesUndefined) {
4384
- fieldSchema = fieldSchema.optional();
4385
- }
4386
- }
4387
- } else {
4388
- if (!fieldMeta.isRequired) {
4389
- fieldSchema = fieldSchema.nullable().optional();
4390
- } else {
4391
- fieldSchema = fieldSchema.optional();
4392
- }
4393
- }
4394
- schemaMap[fieldName] = fieldSchema;
4395
- } else if (value === true) {
4396
- let fieldSchema = schemaBuilder.buildFieldSchema(
4397
- model,
4398
- fieldName
4554
+ const handlesUndefined = schemaProducesValueForUndefined(
4555
+ refined
4556
+ );
4557
+ schemaMap[fieldName] = applyCreateUpdateNullability(
4558
+ fieldMeta,
4559
+ refined,
4560
+ { mode, handlesUndefined }
4399
4561
  );
4562
+ } else if (value === true) {
4563
+ const fieldSchema = schemaBuilder.buildFieldSchema(model, fieldName);
4400
4564
  const isZodDefaultField = zodDefaultSet !== void 0 && zodDefaultSet.has(fieldName);
4401
- if (mode === "create") {
4402
- if (!fieldMeta.isRequired) {
4403
- fieldSchema = isZodDefaultField ? fieldSchema.nullable() : fieldSchema.nullable().optional();
4404
- } else if (fieldMeta.hasDefault) {
4405
- if (!isZodDefaultField) {
4406
- fieldSchema = fieldSchema.optional();
4407
- }
4408
- }
4409
- } else {
4410
- if (!fieldMeta.isRequired) {
4411
- fieldSchema = fieldSchema.nullable().optional();
4412
- } else {
4413
- fieldSchema = fieldSchema.optional();
4414
- }
4415
- }
4416
- schemaMap[fieldName] = fieldSchema;
4565
+ schemaMap[fieldName] = applyCreateUpdateNullability(
4566
+ fieldMeta,
4567
+ fieldSchema,
4568
+ { mode, handlesUndefined: isZodDefaultField }
4569
+ );
4417
4570
  } else {
4418
4571
  const actualValue = isForcedValue(value) ? value.value : value;
4419
4572
  let fieldSchema = schemaBuilder.buildFieldSchema(
@@ -4457,7 +4610,7 @@ function buildDataSchema(model, dataConfig, mode, typeMap, schemaBuilder, zodDef
4457
4610
  }
4458
4611
  }
4459
4612
  return {
4460
- schema: z8.object(schemaMap).strict(),
4613
+ schema: z10.object(schemaMap).strict(),
4461
4614
  forced
4462
4615
  };
4463
4616
  }
@@ -4494,106 +4647,120 @@ function isGuardShape(obj) {
4494
4647
  const keys = Object.keys(obj);
4495
4648
  return keys.length === 0 || keys.every((k) => GUARD_SHAPE_KEYS.has(k));
4496
4649
  }
4497
- function isSingleShape(input) {
4498
- return typeof input === "function" || isGuardShape(input);
4499
- }
4500
- function toPlainObject(value) {
4501
- if (value === null || typeof value !== "object")
4502
- return value;
4503
- if (Array.isArray(value))
4504
- return value.map(toPlainObject);
4505
- if (value instanceof Date)
4506
- return value;
4507
- if (value instanceof Uint8Array)
4508
- return value;
4509
- if (value instanceof RegExp)
4510
- return value;
4511
- if (typeof value.toFixed === "function" && typeof value.toNumber === "function")
4512
- return value;
4513
- const result = {};
4514
- for (const [k, v] of Object.entries(value)) {
4515
- result[k] = toPlainObject(v);
4650
+ function requireBody(body) {
4651
+ if (body === void 0 || body === null)
4652
+ return {};
4653
+ if (!isPlainObject(body)) {
4654
+ throw new ShapeError("Request body must be a plain object");
4516
4655
  }
4517
- return result;
4656
+ return body;
4518
4657
  }
4519
- function requireBody(body) {
4520
- const normalized = toPlainObject(body);
4521
- if (!isPlainObject(normalized))
4522
- throw new ShapeError("Request body must be an object");
4523
- return normalized;
4658
+ function assertNoCallerInBody(body) {
4659
+ if ("caller" in body) {
4660
+ throw new CallerError(
4661
+ "Pass caller via the guard(input, caller) argument, not in the request body."
4662
+ );
4663
+ }
4524
4664
  }
4525
- function resolveDynamicShape(fn, contextFn) {
4526
- const ctx = validateContext(contextFn());
4665
+ function resolveDynamicShape(shapeFn, ctx, context) {
4666
+ if (ctx === void 0) {
4667
+ throw new ShapeError(
4668
+ `Dynamic ${context} requires a context. Provide contextFn on the extension.`
4669
+ );
4670
+ }
4527
4671
  let result;
4528
4672
  try {
4529
- result = fn(ctx);
4673
+ result = shapeFn(ctx);
4530
4674
  } catch (err) {
4531
4675
  throw new ShapeError(
4532
- `Dynamic shape function threw: ${err.message}`,
4676
+ `Dynamic ${context} function threw: ${err.message}`,
4533
4677
  { cause: err }
4534
4678
  );
4535
4679
  }
4536
- if (!isPlainObject(result)) {
4537
- throw new ShapeError("Dynamic shape function must return a plain object");
4680
+ if (!isGuardShape(result)) {
4681
+ throw new ShapeError(
4682
+ `Dynamic ${context} function must return a valid guard shape object`
4683
+ );
4538
4684
  }
4539
4685
  return result;
4540
4686
  }
4541
- function resolveShape(input, body, contextFn, caller) {
4542
- if (isSingleShape(input)) {
4543
- const wasDynamic2 = typeof input === "function";
4544
- const shape2 = wasDynamic2 ? resolveDynamicShape(input, contextFn) : input;
4545
- const parsed2 = body === void 0 || body === null ? {} : requireBody(body);
4546
- return { shape: shape2, body: parsed2, matchedKey: "_default", wasDynamic: wasDynamic2 };
4547
- }
4548
- const namedMap = input;
4549
- for (const key of Object.keys(namedMap)) {
4687
+ function resolveNamedShape(input, body, contextFn, explicitCaller) {
4688
+ assertNoCallerInBody(body);
4689
+ const caller = explicitCaller;
4690
+ const keys = Object.keys(input);
4691
+ for (const key of keys) {
4550
4692
  if (GUARD_SHAPE_KEYS.has(key)) {
4551
4693
  throw new ShapeError(
4552
- `Caller key "${key}" collides with reserved shape config key. Rename the caller path.`
4553
- );
4554
- }
4555
- const val = namedMap[key];
4556
- if (typeof val !== "function" && !isGuardShape(val)) {
4557
- throw new ShapeError(
4558
- `Named shape value for "${key}" must be a guard shape object or function`
4694
+ `Caller key "${key}" collides with reserved guard shape key. Rename the caller path.`
4559
4695
  );
4560
4696
  }
4561
4697
  }
4562
- const parsed = body === void 0 || body === null ? {} : requireBody(body);
4563
- if ("caller" in parsed) {
4564
- throw new CallerError(
4565
- "Pass caller as second argument to .guard() or via context function, not in the request body."
4566
- );
4567
- }
4568
4698
  if (typeof caller !== "string") {
4569
- if ("default" in namedMap) {
4570
- const shapeOrFn2 = namedMap["default"];
4571
- const wasDynamic2 = typeof shapeOrFn2 === "function";
4572
- const shape2 = wasDynamic2 ? resolveDynamicShape(shapeOrFn2, contextFn) : shapeOrFn2;
4573
- return { shape: shape2, body: parsed, matchedKey: "default", wasDynamic: wasDynamic2 };
4699
+ if ("default" in input) {
4700
+ return resolveShapeEntry(input.default, body, contextFn, "default");
4574
4701
  }
4575
- const patterns2 = Object.keys(namedMap);
4576
4702
  throw new CallerError(
4577
- `Missing caller. This guard uses named shape routing with keys: ${patterns2.map((k) => `"${k}"`).join(", ")}. Provide caller as second argument to .guard() or set "caller" in the context function, or add a "default" variant.`
4703
+ `Missing caller. This guard uses named shape routing with keys: ${keys.map((k) => `"${k}"`).join(", ")}. Provide caller via guard(input, caller).`
4578
4704
  );
4579
4705
  }
4580
- const patterns = Object.keys(namedMap);
4581
- const matched = matchCallerPattern(patterns, caller);
4582
- if (!matched) {
4583
- if ("default" in namedMap) {
4584
- const shapeOrFn2 = namedMap["default"];
4585
- const wasDynamic2 = typeof shapeOrFn2 === "function";
4586
- const shape2 = wasDynamic2 ? resolveDynamicShape(shapeOrFn2, contextFn) : shapeOrFn2;
4587
- return { shape: shape2, body: parsed, matchedKey: "default", wasDynamic: wasDynamic2 };
4588
- }
4589
- throw new CallerError(
4590
- `Unknown caller: "${caller}". Allowed: ${patterns.map((k) => `"${k}"`).join(", ")}`
4591
- );
4706
+ const matched = matchCallerPattern(keys, caller);
4707
+ if (matched) {
4708
+ return resolveShapeEntry(input[matched], body, contextFn, matched);
4709
+ }
4710
+ if ("default" in input) {
4711
+ return resolveShapeEntry(input.default, body, contextFn, "default");
4712
+ }
4713
+ throw new CallerError(
4714
+ `Unknown caller: "${caller}". Allowed: ${keys.map((k) => `"${k}"`).join(", ")}`
4715
+ );
4716
+ }
4717
+ function resolveShapeEntry(entry, body, contextFn, matchedKey) {
4718
+ if (typeof entry === "function") {
4719
+ const ctx = validateContext(contextFn());
4720
+ const shape = resolveDynamicShape(entry, ctx, `shape "${matchedKey}"`);
4721
+ return {
4722
+ shape,
4723
+ body,
4724
+ matchedKey,
4725
+ wasDynamic: true
4726
+ };
4727
+ }
4728
+ return {
4729
+ shape: entry,
4730
+ body,
4731
+ matchedKey,
4732
+ wasDynamic: false
4733
+ };
4734
+ }
4735
+ function resolveShape(input, rawBody, contextFn, explicitCaller) {
4736
+ const body = requireBody(rawBody);
4737
+ if (typeof input === "function") {
4738
+ const ctx = validateContext(contextFn());
4739
+ const shape = resolveDynamicShape(input, ctx, "shape");
4740
+ return {
4741
+ shape,
4742
+ body,
4743
+ matchedKey: "_default",
4744
+ wasDynamic: true
4745
+ };
4746
+ }
4747
+ if (isGuardShape(input)) {
4748
+ return {
4749
+ shape: input,
4750
+ body,
4751
+ matchedKey: "_default",
4752
+ wasDynamic: false
4753
+ };
4592
4754
  }
4593
- const shapeOrFn = namedMap[matched];
4594
- const wasDynamic = typeof shapeOrFn === "function";
4595
- const shape = wasDynamic ? resolveDynamicShape(shapeOrFn, contextFn) : shapeOrFn;
4596
- return { shape, body: parsed, matchedKey: matched, wasDynamic };
4755
+ if (!isPlainObject(input)) {
4756
+ throw new ShapeError("Guard input must be a shape object or a named map of shapes");
4757
+ }
4758
+ return resolveNamedShape(
4759
+ input,
4760
+ body,
4761
+ contextFn,
4762
+ explicitCaller
4763
+ );
4597
4764
  }
4598
4765
 
4599
4766
  // src/runtime/model-guard.ts
@@ -4616,129 +4783,20 @@ var PROJECTION_MUTATION_METHODS = /* @__PURE__ */ new Set([
4616
4783
  "updateManyAndReturn"
4617
4784
  ]);
4618
4785
  var BATCH_CREATE_METHODS = /* @__PURE__ */ new Set(["createMany", "createManyAndReturn"]);
4619
- function buildDefaultSelectInput(config) {
4620
- const result = {};
4621
- for (const [key, value] of Object.entries(config)) {
4622
- if (key === "_count") {
4623
- result[key] = buildDefaultCountInput(
4624
- value
4625
- );
4626
- continue;
4627
- }
4628
- if (value === true) {
4629
- result[key] = true;
4630
- } else {
4631
- const nested = {};
4632
- if (value.select)
4633
- nested.select = buildDefaultSelectInput(value.select);
4634
- if (value.include) {
4635
- nested.include = buildDefaultIncludeInput(value.include);
4636
- }
4637
- result[key] = Object.keys(nested).length > 0 ? nested : true;
4638
- }
4639
- }
4640
- return result;
4641
- }
4642
- function buildDefaultIncludeInput(config) {
4643
- const result = {};
4644
- for (const [key, value] of Object.entries(config)) {
4645
- if (key === "_count") {
4646
- result[key] = buildDefaultCountInput(
4647
- value
4648
- );
4649
- continue;
4650
- }
4651
- if (value === true) {
4652
- result[key] = true;
4653
- } else {
4654
- const nested = {};
4655
- if (value.include) {
4656
- nested.include = buildDefaultIncludeInput(value.include);
4657
- }
4658
- if (value.select)
4659
- nested.select = buildDefaultSelectInput(value.select);
4660
- result[key] = Object.keys(nested).length > 0 ? nested : true;
4661
- }
4662
- }
4663
- return result;
4664
- }
4665
- function buildDefaultCountInput(config) {
4666
- if (config === true)
4667
- return true;
4668
- if (!isPlainObject(config) || !config.select || !isPlainObject(config.select)) {
4669
- return true;
4670
- }
4671
- const selectObj = config.select;
4672
- const result = {};
4673
- for (const key of Object.keys(selectObj)) {
4674
- result[key] = true;
4675
- }
4676
- return { select: result };
4677
- }
4678
- function buildDefaultProjectionBody(shape) {
4679
- if (shape.select) {
4680
- return { select: buildDefaultSelectInput(shape.select) };
4681
- }
4682
- if (shape.include) {
4683
- return { include: buildDefaultIncludeInput(shape.include) };
4684
- }
4685
- return {};
4686
- }
4687
- function applyClientProjectionOverrides(shapeDefault, clientProjection) {
4688
- const result = { ...shapeDefault };
4689
- for (const [key, clientValue] of Object.entries(clientProjection)) {
4690
- const defaultValue = result[key];
4691
- if (defaultValue === void 0) {
4692
- result[key] = clientValue;
4693
- continue;
4694
- }
4695
- if (clientValue === true) {
4696
- result[key] = true;
4697
- continue;
4698
- }
4699
- if (isPlainObject(clientValue)) {
4700
- if (!isPlainObject(defaultValue)) {
4701
- result[key] = clientValue;
4702
- continue;
4703
- }
4704
- const merged = { ...defaultValue };
4705
- const clientObj = clientValue;
4706
- for (const [argKey, argValue] of Object.entries(clientObj)) {
4707
- const defaultArgValue = merged[argKey];
4708
- if ((argKey === "select" || argKey === "include") && isPlainObject(argValue) && isPlainObject(defaultArgValue)) {
4709
- merged[argKey] = applyClientProjectionOverrides(
4710
- defaultArgValue,
4711
- argValue
4712
- );
4713
- } else {
4714
- merged[argKey] = argValue;
4715
- }
4716
- }
4717
- result[key] = merged;
4718
- }
4719
- }
4720
- return result;
4721
- }
4722
- function hasClientControlledValues(obj) {
4723
- for (const value of Object.values(obj)) {
4724
- if (isForcedValue(value))
4725
- continue;
4726
- if (value === true)
4727
- return true;
4728
- if (isPlainObject(value) && hasClientControlledValues(value))
4786
+ var MAX_PROJECTION_WALK_DEPTH = 10;
4787
+ function walkForClientContent(obj, predicate, depth) {
4788
+ if (depth > MAX_PROJECTION_WALK_DEPTH)
4789
+ return false;
4790
+ for (const [key, value] of Object.entries(obj)) {
4791
+ if (predicate(value, depth))
4729
4792
  return true;
4730
- }
4731
- return false;
4732
- }
4733
- function checkIncludeForClientArgs(config) {
4734
- for (const [key, value] of Object.entries(config)) {
4735
4793
  if (key === "_count") {
4736
4794
  if (value !== true && isPlainObject(value) && isPlainObject(value.select)) {
4737
4795
  const selectObj = value.select;
4738
4796
  for (const entryVal of Object.values(selectObj)) {
4739
4797
  if (isPlainObject(entryVal) && entryVal.where) {
4740
4798
  const w = entryVal.where;
4741
- if (isPlainObject(w) && hasClientControlledValues(w))
4799
+ if (isPlainObject(w) && hasClientControlledValues(w, depth + 1))
4742
4800
  return true;
4743
4801
  }
4744
4802
  }
@@ -4747,54 +4805,41 @@ function checkIncludeForClientArgs(config) {
4747
4805
  }
4748
4806
  if (value === true)
4749
4807
  continue;
4750
- if (value.orderBy || value.cursor || value.take || value.skip)
4808
+ const nested = value;
4809
+ if (nested.orderBy || nested.cursor || nested.take || nested.skip)
4751
4810
  return true;
4752
- if (value.where && isPlainObject(value.where) && hasClientControlledValues(value.where)) {
4811
+ if (nested.where && isPlainObject(nested.where) && hasClientControlledValues(nested.where, depth + 1)) {
4753
4812
  return true;
4754
4813
  }
4755
- if (value.include && checkIncludeForClientArgs(value.include))
4814
+ if (nested.include && walkForClientContent(nested.include, predicate, depth + 1))
4756
4815
  return true;
4757
- if (value.select && checkSelectForClientArgs(value.select))
4816
+ if (nested.select && walkForClientContent(nested.select, predicate, depth + 1))
4758
4817
  return true;
4759
4818
  }
4760
4819
  return false;
4761
4820
  }
4762
- function checkSelectForClientArgs(config) {
4763
- for (const [key, value] of Object.entries(config)) {
4764
- if (key === "_count") {
4765
- if (value !== true && isPlainObject(value) && isPlainObject(value.select)) {
4766
- const selectObj = value.select;
4767
- for (const entryVal of Object.values(selectObj)) {
4768
- if (isPlainObject(entryVal) && entryVal.where) {
4769
- const w = entryVal.where;
4770
- if (isPlainObject(w) && hasClientControlledValues(w))
4771
- return true;
4772
- }
4773
- }
4774
- }
4821
+ function hasClientControlledValues(obj, depth = 0) {
4822
+ if (depth > MAX_PROJECTION_WALK_DEPTH)
4823
+ return false;
4824
+ for (const value of Object.values(obj)) {
4825
+ if (isForcedValue(value))
4775
4826
  continue;
4776
- }
4777
4827
  if (value === true)
4778
- continue;
4779
- if (value.orderBy || value.cursor || value.take || value.skip)
4780
4828
  return true;
4781
- if (value.where && isPlainObject(value.where) && hasClientControlledValues(value.where)) {
4829
+ if (isPlainObject(value) && hasClientControlledValues(value, depth + 1)) {
4782
4830
  return true;
4783
4831
  }
4784
- if (value.select && checkSelectForClientArgs(value.select))
4785
- return true;
4786
- if (value.include && checkIncludeForClientArgs(value.include))
4787
- return true;
4788
4832
  }
4789
4833
  return false;
4790
4834
  }
4791
4835
  function hasNestedClientControlledArgs(shape) {
4836
+ const predicate = () => false;
4792
4837
  if (shape.include) {
4793
- if (checkIncludeForClientArgs(shape.include))
4838
+ if (walkForClientContent(shape.include, predicate, 0))
4794
4839
  return true;
4795
4840
  }
4796
4841
  if (shape.select) {
4797
- if (checkSelectForClientArgs(shape.select))
4842
+ if (walkForClientContent(shape.select, predicate, 0))
4798
4843
  return true;
4799
4844
  }
4800
4845
  return false;
@@ -4866,77 +4911,62 @@ function createModelGuardExtension(config) {
4866
4911
  const whereBuiltCache = /* @__PURE__ */ new Map();
4867
4912
  const projectionCache = /* @__PURE__ */ new Map();
4868
4913
  const uniqueWhereCache = /* @__PURE__ */ new Map();
4914
+ function memoize(cache, key, wasDynamic, build) {
4915
+ if (wasDynamic)
4916
+ return build();
4917
+ const cached = cache.get(key);
4918
+ if (cached)
4919
+ return cached;
4920
+ const built = build();
4921
+ cache.set(key, built);
4922
+ return built;
4923
+ }
4869
4924
  function getReadShape(method, queryShape, matchedKey, wasDynamic) {
4870
- if (!wasDynamic) {
4871
- const cacheKey = `${method}\0${matchedKey}`;
4872
- const cached = readShapeCache.get(cacheKey);
4873
- if (cached)
4874
- return cached;
4875
- const built = queryBuilder.buildShapeZodSchema(
4925
+ return memoize(
4926
+ readShapeCache,
4927
+ `${method}\0${matchedKey}`,
4928
+ wasDynamic,
4929
+ () => queryBuilder.buildShapeZodSchema(
4876
4930
  modelName,
4877
4931
  method,
4878
4932
  queryShape
4879
- );
4880
- readShapeCache.set(cacheKey, built);
4881
- return built;
4882
- }
4883
- return queryBuilder.buildShapeZodSchema(
4884
- modelName,
4885
- method,
4886
- queryShape
4933
+ )
4887
4934
  );
4888
4935
  }
4889
4936
  function getDataSchema(mode, dataConfig, matchedKey, wasDynamic) {
4890
- if (!wasDynamic && !hasDataRefines(dataConfig)) {
4891
- const cacheKey = `${mode}\0${matchedKey}`;
4892
- const cached = dataSchemaCache.get(cacheKey);
4893
- if (cached)
4894
- return cached;
4895
- const built = buildDataSchema(
4937
+ const skipCache = wasDynamic || hasDataRefines(dataConfig);
4938
+ return memoize(
4939
+ dataSchemaCache,
4940
+ `${mode}\0${matchedKey}`,
4941
+ skipCache,
4942
+ () => buildDataSchema(
4896
4943
  modelName,
4897
4944
  dataConfig,
4898
4945
  mode,
4899
4946
  typeMap,
4947
+ uniqueMap,
4948
+ enumMap,
4949
+ scalarBase,
4900
4950
  schemaBuilder,
4901
4951
  zodDefaults
4902
- );
4903
- dataSchemaCache.set(cacheKey, built);
4904
- return built;
4905
- }
4906
- return buildDataSchema(
4907
- modelName,
4908
- dataConfig,
4909
- mode,
4910
- typeMap,
4911
- schemaBuilder,
4912
- zodDefaults
4952
+ )
4913
4953
  );
4914
4954
  }
4915
4955
  function getWhereBuilt(whereConfig, matchedKey, wasDynamic) {
4916
- if (!wasDynamic) {
4917
- const cached = whereBuiltCache.get(matchedKey);
4918
- if (cached)
4919
- return cached;
4920
- const built = queryBuilder.buildWhereSchema(modelName, whereConfig);
4921
- whereBuiltCache.set(matchedKey, built);
4922
- return built;
4923
- }
4924
- return queryBuilder.buildWhereSchema(modelName, whereConfig);
4956
+ return memoize(
4957
+ whereBuiltCache,
4958
+ matchedKey,
4959
+ wasDynamic,
4960
+ () => queryBuilder.buildWhereSchema(modelName, whereConfig)
4961
+ );
4925
4962
  }
4926
4963
  function getUniqueWhereBuilt(whereConfig, matchedKey, wasDynamic) {
4927
- if (!wasDynamic) {
4928
- const cacheKey = `unique\0${matchedKey}`;
4929
- const cached = uniqueWhereCache.get(cacheKey);
4930
- if (cached)
4931
- return cached;
4932
- const built = queryBuilder.buildUniqueWhereSchema(
4933
- modelName,
4934
- whereConfig
4935
- );
4936
- uniqueWhereCache.set(cacheKey, built);
4937
- return built;
4938
- }
4939
- return queryBuilder.buildUniqueWhereSchema(modelName, whereConfig);
4964
+ return memoize(
4965
+ uniqueWhereCache,
4966
+ `unique\0${matchedKey}`,
4967
+ wasDynamic,
4968
+ () => queryBuilder.buildUniqueWhereSchema(modelName, whereConfig)
4969
+ );
4940
4970
  }
4941
4971
  function buildProjectionSchema(shape) {
4942
4972
  const schemaFields = {};
@@ -4963,7 +4993,7 @@ function createModelGuardExtension(config) {
4963
4993
  forcedSelectCountWhere = result.forcedCountWhere;
4964
4994
  }
4965
4995
  return {
4966
- zodSchema: z9.object(schemaFields).strict(),
4996
+ zodSchema: z11.object(schemaFields).strict(),
4967
4997
  forcedIncludeTree,
4968
4998
  forcedSelectTree,
4969
4999
  forcedIncludeCountWhere,
@@ -4971,16 +5001,12 @@ function createModelGuardExtension(config) {
4971
5001
  };
4972
5002
  }
4973
5003
  function getProjection(shape, matchedKey, wasDynamic) {
4974
- if (!wasDynamic) {
4975
- const cacheKey = `projection\0${matchedKey}`;
4976
- const cached = projectionCache.get(cacheKey);
4977
- if (cached)
4978
- return cached;
4979
- const built = buildProjectionSchema(shape);
4980
- projectionCache.set(cacheKey, built);
4981
- return built;
4982
- }
4983
- return buildProjectionSchema(shape);
5004
+ return memoize(
5005
+ projectionCache,
5006
+ `projection\0${matchedKey}`,
5007
+ wasDynamic,
5008
+ () => buildProjectionSchema(shape)
5009
+ );
4984
5010
  }
4985
5011
  function resolveProjection(shape, parsed, method, matchedKey, wasDynamic) {
4986
5012
  const hasBodyProjection = "select" in parsed || "include" in parsed;
@@ -5174,24 +5200,11 @@ function createModelGuardExtension(config) {
5174
5200
  const hasShapeProjection = !!resolved.shape.select || !!resolved.shape.include;
5175
5201
  if (!hasShapeProjection)
5176
5202
  return resolved.body;
5177
- const defaultProjection = buildDefaultProjectionBody(resolved.shape);
5178
5203
  const hasBodyProjection = "select" in resolved.body || "include" in resolved.body;
5179
- if (!hasBodyProjection) {
5180
- return { ...resolved.body, ...defaultProjection };
5181
- }
5182
- const merged = { ...resolved.body };
5183
- if ("select" in resolved.body && "select" in defaultProjection && isPlainObject(resolved.body.select) && isPlainObject(defaultProjection.select)) {
5184
- merged.select = applyClientProjectionOverrides(
5185
- defaultProjection.select,
5186
- resolved.body.select
5187
- );
5188
- } else if ("include" in resolved.body && "include" in defaultProjection && isPlainObject(resolved.body.include) && isPlainObject(defaultProjection.include)) {
5189
- merged.include = applyClientProjectionOverrides(
5190
- defaultProjection.include,
5191
- resolved.body.include
5192
- );
5193
- }
5194
- return merged;
5204
+ if (hasBodyProjection)
5205
+ return resolved.body;
5206
+ const defaultProjection = buildDefaultProjectionBody(resolved.shape);
5207
+ return { ...resolved.body, ...defaultProjection };
5195
5208
  }
5196
5209
  function makeReadMethod(method) {
5197
5210
  return (body) => {
@@ -5224,29 +5237,21 @@ function createModelGuardExtension(config) {
5224
5237
  function makeCreateMethod(method) {
5225
5238
  const isBatch = BATCH_CREATE_METHODS.has(method);
5226
5239
  const supportsProjection = PROJECTION_MUTATION_METHODS.has(method);
5227
- let allowedBodyKeys;
5228
- if (isBatch && supportsProjection) {
5229
- allowedBodyKeys = ALLOWED_BODY_KEYS_CREATE_MANY_PROJECTION;
5230
- } else if (isBatch) {
5231
- allowedBodyKeys = ALLOWED_BODY_KEYS_CREATE_MANY;
5232
- } else if (supportsProjection) {
5233
- allowedBodyKeys = ALLOWED_BODY_KEYS_CREATE_PROJECTION;
5234
- } else {
5235
- allowedBodyKeys = ALLOWED_BODY_KEYS_CREATE;
5236
- }
5237
- const allowedShapeKeys = supportsProjection ? VALID_SHAPE_KEYS_CREATE_PROJECTION : VALID_SHAPE_KEYS_CREATE;
5240
+ const allowedBodyKeys = getAllowedBodyKeys(method, supportsProjection);
5241
+ const allowedShapeKeys = getAllowedShapeKeys(method, supportsProjection);
5238
5242
  return (body) => {
5239
5243
  const caller = resolveCaller();
5240
5244
  const resolved = resolveShape(input, body, contextFn, caller);
5241
5245
  if (!resolved.shape.data) {
5242
5246
  throw new ShapeError(`Guard shape requires "data" for ${method}`);
5243
5247
  }
5244
- validateMutationShapeKeys(
5248
+ validateAllowedKeys(
5245
5249
  resolved.shape,
5246
5250
  allowedShapeKeys,
5247
- method
5251
+ method,
5252
+ "shape"
5248
5253
  );
5249
- validateMutationBodyKeys(resolved.body, allowedBodyKeys, method);
5254
+ validateAllowedKeys(resolved.body, allowedBodyKeys, method, "body");
5250
5255
  const fks = modelScopeFks.get(modelName) ?? /* @__PURE__ */ new Set();
5251
5256
  validateCreateCompleteness(
5252
5257
  modelName,
@@ -5305,20 +5310,21 @@ function createModelGuardExtension(config) {
5305
5310
  const isUniqueWhere = method === "update";
5306
5311
  const isBulk = BULK_MUTATION_METHODS.has(method);
5307
5312
  const supportsProjection = PROJECTION_MUTATION_METHODS.has(method);
5308
- const allowedBodyKeys = supportsProjection ? ALLOWED_BODY_KEYS_UPDATE_PROJECTION : ALLOWED_BODY_KEYS_UPDATE;
5309
- const allowedShapeKeys = supportsProjection ? VALID_SHAPE_KEYS_UPDATE_PROJECTION : VALID_SHAPE_KEYS_UPDATE;
5313
+ const allowedBodyKeys = getAllowedBodyKeys(method, supportsProjection);
5314
+ const allowedShapeKeys = getAllowedShapeKeys(method, supportsProjection);
5310
5315
  return (body) => {
5311
5316
  const caller = resolveCaller();
5312
5317
  const resolved = resolveShape(input, body, contextFn, caller);
5313
5318
  if (!resolved.shape.data) {
5314
5319
  throw new ShapeError(`Guard shape requires "data" for ${method}`);
5315
5320
  }
5316
- validateMutationShapeKeys(
5321
+ validateAllowedKeys(
5317
5322
  resolved.shape,
5318
5323
  allowedShapeKeys,
5319
- method
5324
+ method,
5325
+ "shape"
5320
5326
  );
5321
- validateMutationBodyKeys(resolved.body, allowedBodyKeys, method);
5327
+ validateAllowedKeys(resolved.body, allowedBodyKeys, method, "body");
5322
5328
  if (isBulk && !resolved.shape.where) {
5323
5329
  throw new ShapeError(
5324
5330
  `Guard shape requires "where" for ${method} to prevent unconstrained bulk mutations`
@@ -5386,20 +5392,21 @@ function createModelGuardExtension(config) {
5386
5392
  const isUniqueWhere = method === "delete";
5387
5393
  const isBulk = BULK_MUTATION_METHODS.has(method);
5388
5394
  const supportsProjection = PROJECTION_MUTATION_METHODS.has(method);
5389
- const allowedBodyKeys = supportsProjection ? ALLOWED_BODY_KEYS_DELETE_PROJECTION : ALLOWED_BODY_KEYS_DELETE;
5390
- const allowedShapeKeys = supportsProjection ? VALID_SHAPE_KEYS_DELETE_PROJECTION : VALID_SHAPE_KEYS_DELETE;
5395
+ const allowedBodyKeys = getAllowedBodyKeys(method, supportsProjection);
5396
+ const allowedShapeKeys = getAllowedShapeKeys(method, supportsProjection);
5391
5397
  return (body) => {
5392
5398
  const caller = resolveCaller();
5393
5399
  const resolved = resolveShape(input, body, contextFn, caller);
5394
5400
  if (resolved.shape.data) {
5395
5401
  throw new ShapeError(`Guard shape "data" is not valid for ${method}`);
5396
5402
  }
5397
- validateMutationShapeKeys(
5403
+ validateAllowedKeys(
5398
5404
  resolved.shape,
5399
5405
  allowedShapeKeys,
5400
- method
5406
+ method,
5407
+ "shape"
5401
5408
  );
5402
- validateMutationBodyKeys(resolved.body, allowedBodyKeys, method);
5409
+ validateAllowedKeys(resolved.body, allowedBodyKeys, method, "body");
5403
5410
  if (isBulk && !resolved.shape.where) {
5404
5411
  throw new ShapeError(
5405
5412
  `Guard shape requires "where" for ${method} to prevent unconstrained bulk mutations`
@@ -5452,6 +5459,8 @@ function createModelGuardExtension(config) {
5452
5459
  };
5453
5460
  }
5454
5461
  function makeUpsertMethod() {
5462
+ const allowedBodyKeys = getAllowedBodyKeys("upsert", true);
5463
+ const allowedShapeKeys = getAllowedShapeKeys("upsert", true);
5455
5464
  return (body) => {
5456
5465
  const caller = resolveCaller();
5457
5466
  const resolved = resolveShape(input, body, contextFn, caller);
@@ -5469,15 +5478,17 @@ function createModelGuardExtension(config) {
5469
5478
  if (!resolved.shape.where) {
5470
5479
  throw new ShapeError('Guard shape requires "where" for upsert');
5471
5480
  }
5472
- validateMutationShapeKeys(
5481
+ validateAllowedKeys(
5473
5482
  resolved.shape,
5474
- VALID_SHAPE_KEYS_UPSERT,
5475
- "upsert"
5483
+ allowedShapeKeys,
5484
+ "upsert",
5485
+ "shape"
5476
5486
  );
5477
- validateMutationBodyKeys(
5487
+ validateAllowedKeys(
5478
5488
  resolved.body,
5479
- ALLOWED_BODY_KEYS_UPSERT,
5480
- "upsert"
5489
+ allowedBodyKeys,
5490
+ "upsert",
5491
+ "body"
5481
5492
  );
5482
5493
  validateUniqueWhereShapeConfig(
5483
5494
  modelName,
@@ -5567,12 +5578,7 @@ function createModelGuardExtension(config) {
5567
5578
  try {
5568
5579
  return fn(body);
5569
5580
  } catch (err) {
5570
- if (err instanceof z9.ZodError) {
5571
- throw new ShapeError(`Validation failed: ${formatZodError(err)}`, {
5572
- cause: err
5573
- });
5574
- }
5575
- throw err;
5581
+ throw toShapeError(err);
5576
5582
  }
5577
5583
  };
5578
5584
  }
@@ -5605,6 +5611,15 @@ function createModelGuardExtension(config) {
5605
5611
  }
5606
5612
 
5607
5613
  // src/runtime/guard.ts
5614
+ function wrapParseFn(fn) {
5615
+ return (...args) => {
5616
+ try {
5617
+ return fn(...args);
5618
+ } catch (err) {
5619
+ throw toShapeError(err);
5620
+ }
5621
+ };
5622
+ }
5608
5623
  function createGuard(config) {
5609
5624
  const scalarBase = createScalarBase(
5610
5625
  config.guardConfig.strictDecimal ?? false
@@ -5626,14 +5641,6 @@ function createGuard(config) {
5626
5641
  warn: (msg) => console.warn(msg)
5627
5642
  };
5628
5643
  const wrapZodErrors = config.wrapZodErrors ?? false;
5629
- function rethrowZod(err) {
5630
- if (err instanceof ZodError) {
5631
- throw new ShapeError(`Validation failed: ${formatZodError(err)}`, {
5632
- cause: err
5633
- });
5634
- }
5635
- throw err;
5636
- }
5637
5644
  return {
5638
5645
  input: (model, opts) => {
5639
5646
  const result = schemaBuilder.buildInputSchema(model, opts);
@@ -5641,13 +5648,7 @@ function createGuard(config) {
5641
5648
  return result;
5642
5649
  return {
5643
5650
  schema: result.schema,
5644
- parse(data) {
5645
- try {
5646
- return result.parse(data);
5647
- } catch (err) {
5648
- rethrowZod(err);
5649
- }
5650
- }
5651
+ parse: wrapParseFn(result.parse)
5651
5652
  };
5652
5653
  },
5653
5654
  model: (model, opts) => schemaBuilder.buildModelSchema(model, opts),
@@ -5657,13 +5658,7 @@ function createGuard(config) {
5657
5658
  return qs;
5658
5659
  return {
5659
5660
  schemas: qs.schemas,
5660
- parse(body, opts) {
5661
- try {
5662
- return qs.parse(body, opts);
5663
- } catch (err) {
5664
- rethrowZod(err);
5665
- }
5666
- }
5661
+ parse: wrapParseFn(qs.parse)
5667
5662
  };
5668
5663
  },
5669
5664
  extension: (contextFn) => {