prisma-guard 1.27.0 → 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))
@@ -996,12 +1108,18 @@ function tryInlineForcedField(result, field, forcedValue) {
996
1108
  if (!isPlainObject(forcedValue))
997
1109
  return false;
998
1110
  const existing = result[field];
999
- if (!isPlainObject(existing))
1000
- return false;
1111
+ if (!isPlainObject(existing)) {
1112
+ const merged2 = { equals: existing };
1113
+ for (const [op, value] of Object.entries(forcedValue)) {
1114
+ merged2[op] = deepClone(value);
1115
+ }
1116
+ result[field] = merged2;
1117
+ return true;
1118
+ }
1001
1119
  const merged = { ...existing };
1002
1120
  for (const [op, value] of Object.entries(forcedValue)) {
1003
1121
  if (op in merged) {
1004
- if (!forcedScalarsEqual(merged[op], value)) {
1122
+ if (!deepEqual(merged[op], value)) {
1005
1123
  throw new ShapeError(
1006
1124
  `Conflicting where values for "${field}.${op}": client provided a different value than the forced shape`
1007
1125
  );
@@ -1032,6 +1150,17 @@ function mergeWhereForced(where, forced) {
1032
1150
  if (Object.keys(forced.conditions).length > 0) {
1033
1151
  const remaining = {};
1034
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
+ }
1035
1164
  const inlined = tryInlineForcedField(result, field, forcedValue);
1036
1165
  if (!inlined) {
1037
1166
  remaining[field] = deepClone(forcedValue);
@@ -1047,32 +1176,6 @@ function mergeWhereForced(where, forced) {
1047
1176
  }
1048
1177
  return result;
1049
1178
  }
1050
- function uniqueValuesEqual(a, b) {
1051
- if (a === b)
1052
- return true;
1053
- if (a === null || b === null)
1054
- return false;
1055
- if (typeof a !== typeof b)
1056
- return false;
1057
- if (a instanceof Date && b instanceof Date) {
1058
- return a.getTime() === b.getTime();
1059
- }
1060
- if (Array.isArray(a)) {
1061
- if (!Array.isArray(b))
1062
- return false;
1063
- if (a.length !== b.length)
1064
- return false;
1065
- return a.every((v, i) => uniqueValuesEqual(v, b[i]));
1066
- }
1067
- if (isPlainObject(a) && isPlainObject(b)) {
1068
- const aKeys = Object.keys(a);
1069
- const bKeys = Object.keys(b);
1070
- if (aKeys.length !== bKeys.length)
1071
- return false;
1072
- return aKeys.every((key) => key in b && uniqueValuesEqual(a[key], b[key]));
1073
- }
1074
- return false;
1075
- }
1076
1179
  function mergeUniqueValue(target, key, value) {
1077
1180
  const cloned = deepClone(value);
1078
1181
  if (!(key in target)) {
@@ -1083,7 +1186,7 @@ function mergeUniqueValue(target, key, value) {
1083
1186
  if (isPlainObject(existing) && isPlainObject(cloned)) {
1084
1187
  const merged = { ...existing };
1085
1188
  for (const [nestedKey, nestedValue] of Object.entries(cloned)) {
1086
- if (nestedKey in merged && !uniqueValuesEqual(merged[nestedKey], nestedValue)) {
1189
+ if (nestedKey in merged && !deepEqual(merged[nestedKey], nestedValue)) {
1087
1190
  throw new ShapeError(
1088
1191
  `Conflicting unique where value for "${key}.${nestedKey}"`
1089
1192
  );
@@ -1093,7 +1196,7 @@ function mergeUniqueValue(target, key, value) {
1093
1196
  target[key] = merged;
1094
1197
  return;
1095
1198
  }
1096
- if (!uniqueValuesEqual(existing, cloned)) {
1199
+ if (!deepEqual(existing, cloned)) {
1097
1200
  throw new ShapeError(`Conflicting unique where value for "${key}"`);
1098
1201
  }
1099
1202
  }
@@ -1120,7 +1223,30 @@ function applyBuiltShape(built, body, isUniqueMethod, modelName) {
1120
1223
  throw new ShapeError('Request cannot define both "include" and "select"');
1121
1224
  }
1122
1225
  if ("where" in bodyObj) {
1123
- 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
+ }
1124
1250
  const { where: _, ...rest } = bodyObj;
1125
1251
  parseable = rest;
1126
1252
  } else if (isUniqueMethod && hasWhereForced(built.forcedWhere) && isPlainObject(bodyObj.where)) {
@@ -1196,6 +1322,86 @@ function buildCountForPlacement(countWhere) {
1196
1322
  }
1197
1323
  return { _count: { select: countSelect } };
1198
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
+ }
1199
1405
  function applyForcedTree(validated, key, tree) {
1200
1406
  const container = validated[key];
1201
1407
  if (!container)
@@ -1204,89 +1410,13 @@ function applyForcedTree(validated, key, tree) {
1204
1410
  const relVal = container[relName];
1205
1411
  if (relVal === void 0)
1206
1412
  continue;
1207
- if (relVal === true) {
1208
- const expanded = {};
1209
- if (forced.where && hasWhereForced(forced.where)) {
1210
- expanded.where = mergeWhereForced(void 0, forced.where);
1211
- }
1212
- if (forced.include) {
1213
- expanded.include = buildForcedOnlyContainer(forced.include);
1214
- applyForcedTree(expanded, "include", forced.include);
1215
- }
1216
- if (forced.select) {
1217
- expanded.select = buildForcedOnlyContainer(forced.select);
1218
- applyForcedTree(expanded, "select", forced.select);
1219
- }
1220
- if (forced._countWhere && Object.keys(forced._countWhere).length > 0) {
1221
- const placement = forced._countWherePlacement ?? "include";
1222
- if (!expanded[placement])
1223
- expanded[placement] = {};
1224
- const placementObj = expanded[placement];
1225
- Object.assign(placementObj, buildCountForPlacement(forced._countWhere));
1226
- }
1227
- if (expanded.include && expanded.select) {
1228
- throw new ShapeError(
1229
- `Forced tree for relation "${relName}" produces both "include" and "select". Prisma does not allow both at the same level.`
1230
- );
1231
- }
1232
- container[relName] = Object.keys(expanded).length > 0 ? expanded : true;
1233
- continue;
1234
- }
1235
- if (isPlainObject(relVal)) {
1236
- const relObj = relVal;
1237
- if (forced.where && hasWhereForced(forced.where)) {
1238
- relObj.where = mergeWhereForced(
1239
- relObj.where,
1240
- forced.where
1241
- );
1242
- }
1243
- if (forced.include) {
1244
- if (!relObj.include) {
1245
- relObj.include = buildForcedOnlyContainer(forced.include);
1246
- }
1247
- applyForcedTree(relObj, "include", forced.include);
1248
- }
1249
- if (forced.select) {
1250
- if (!relObj.select) {
1251
- relObj.select = buildForcedOnlyContainer(forced.select);
1252
- }
1253
- applyForcedTree(relObj, "select", forced.select);
1254
- }
1255
- if (forced._countWhere && Object.keys(forced._countWhere).length > 0) {
1256
- const placement = forced._countWherePlacement ?? "include";
1257
- const projContainer = relObj[placement];
1258
- if (projContainer) {
1259
- applyForcedCountWhere(projContainer, forced._countWhere);
1260
- }
1261
- }
1262
- if (relObj.include && relObj.select) {
1263
- throw new ShapeError(
1264
- `Relation "${relName}" has both "include" and "select" after forced tree merge. Prisma does not allow both at the same level.`
1265
- );
1266
- }
1267
- }
1413
+ container[relName] = applyForcedToRelValue(relName, relVal, forced);
1268
1414
  }
1269
1415
  }
1270
1416
  function buildForcedOnlyContainer(tree) {
1271
1417
  const result = {};
1272
1418
  for (const [relName, forced] of Object.entries(tree)) {
1273
- const nested = {};
1274
- if (forced.where && hasWhereForced(forced.where)) {
1275
- nested.where = mergeWhereForced(void 0, forced.where);
1276
- }
1277
- if (forced.include) {
1278
- nested.include = buildForcedOnlyContainer(forced.include);
1279
- }
1280
- if (forced.select) {
1281
- nested.select = buildForcedOnlyContainer(forced.select);
1282
- }
1283
- if (forced._countWhere && Object.keys(forced._countWhere).length > 0) {
1284
- const placement = forced._countWherePlacement ?? "include";
1285
- if (!nested[placement])
1286
- nested[placement] = {};
1287
- const placementObj = nested[placement];
1288
- Object.assign(placementObj, buildCountForPlacement(forced._countWhere));
1289
- }
1419
+ const nested = collectSubtree(forced);
1290
1420
  result[relName] = Object.keys(nested).length > 0 ? nested : true;
1291
1421
  }
1292
1422
  return result;
@@ -1302,11 +1432,15 @@ function applyForcedCountWhere(container, forcedCountWhere) {
1302
1432
  const selectObj = selectVal;
1303
1433
  for (const [relName, forced] of Object.entries(forcedCountWhere)) {
1304
1434
  const relVal = selectObj[relName];
1305
- if (relVal === void 0)
1435
+ if (relVal === void 0) {
1436
+ selectObj[relName] = { where: mergeWhereForced(void 0, forced) };
1306
1437
  continue;
1438
+ }
1307
1439
  if (relVal === true) {
1308
1440
  selectObj[relName] = { where: mergeWhereForced(void 0, forced) };
1309
- } else if (isPlainObject(relVal)) {
1441
+ continue;
1442
+ }
1443
+ if (isPlainObject(relVal)) {
1310
1444
  const relObj = relVal;
1311
1445
  relObj.where = mergeWhereForced(
1312
1446
  relObj.where,
@@ -1315,12 +1449,6 @@ function applyForcedCountWhere(container, forcedCountWhere) {
1315
1449
  }
1316
1450
  }
1317
1451
  }
1318
- function formatUniqueConstraint(constraint) {
1319
- return constraint.fields.length === 1 ? constraint.selector : `${constraint.selector}(${constraint.fields.join(", ")})`;
1320
- }
1321
- function formatUniqueConstraints(constraints) {
1322
- return constraints.map(formatUniqueConstraint).join(" | ");
1323
- }
1324
1452
  function resolvedWhereCoversConstraint(where, constraint) {
1325
1453
  if (constraint.fields.length === 1) {
1326
1454
  return constraint.fields[0] in where;
@@ -1426,7 +1554,12 @@ function stripUniqueWhereForcedInput(where, forced) {
1426
1554
  const currentValue = result[key];
1427
1555
  if (isPlainObject(currentValue) && isPlainObject(forcedValue)) {
1428
1556
  const nested = { ...currentValue };
1429
- 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
+ }
1430
1563
  delete nested[nestedKey];
1431
1564
  }
1432
1565
  if (Object.keys(nested).length === 0) {
@@ -1436,11 +1569,25 @@ function stripUniqueWhereForcedInput(where, forced) {
1436
1569
  }
1437
1570
  continue;
1438
1571
  }
1572
+ if (!deepEqual(currentValue, forcedValue)) {
1573
+ throw new ShapeError(
1574
+ `Client unique where value for "${key}" conflicts with forced value`
1575
+ );
1576
+ }
1439
1577
  delete result[key];
1440
1578
  }
1441
1579
  return result;
1442
1580
  }
1443
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
+
1444
1591
  // src/runtime/query-builder-where.ts
1445
1592
  var UNSUPPORTED_WHERE_TYPES = /* @__PURE__ */ new Set(["Bytes"]);
1446
1593
  var STRING_MODE_OPS = /* @__PURE__ */ new Set([
@@ -1454,47 +1601,40 @@ var JSON_STRING_MODE_OPS = /* @__PURE__ */ new Set([
1454
1601
  "string_starts_with",
1455
1602
  "string_ends_with"
1456
1603
  ]);
1604
+ var NEGATIVE_RELATION_OPS = /* @__PURE__ */ new Set(["none", "isNot"]);
1457
1605
  var MAX_WHERE_DEPTH = 10;
1458
- function safeStringify(v) {
1459
- if (typeof v === "bigint")
1460
- 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();
1461
1616
  try {
1462
- 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;
1463
1634
  } catch {
1464
- return String(v);
1635
+ return String(value);
1465
1636
  }
1466
1637
  }
1467
- function forcedValuesEqual(a, b) {
1468
- if (a === b)
1469
- return true;
1470
- if (a === null || b === null)
1471
- return false;
1472
- if (typeof a !== typeof b)
1473
- return false;
1474
- if (typeof a === "bigint")
1475
- return a === b;
1476
- if (a instanceof Date && b instanceof Date)
1477
- return a.getTime() === b.getTime();
1478
- if (a instanceof RegExp && b instanceof RegExp) {
1479
- return a.source === b.source && a.flags === b.flags;
1480
- }
1481
- if (typeof a !== "object")
1482
- return false;
1483
- if (Array.isArray(a)) {
1484
- if (!Array.isArray(b))
1485
- return false;
1486
- if (a.length !== b.length)
1487
- return false;
1488
- return a.every((v, i) => forcedValuesEqual(v, b[i]));
1489
- }
1490
- if (!isPlainObject(a) || !isPlainObject(b))
1491
- return false;
1492
- const aKeys = Object.keys(a);
1493
- const bKeys = Object.keys(b);
1494
- if (aKeys.length !== bKeys.length)
1495
- return false;
1496
- return aKeys.every((k) => k in b && forcedValuesEqual(a[k], b[k]));
1497
- }
1498
1638
  function mergeScalarConditions(target, source) {
1499
1639
  for (const [field, ops] of Object.entries(source)) {
1500
1640
  const existing = target[field];
@@ -1512,7 +1652,7 @@ function mergeScalarConditions(target, source) {
1512
1652
  for (const [op, val] of Object.entries(ops)) {
1513
1653
  if (op in existing) {
1514
1654
  const existingVal = existing[op];
1515
- if (!forcedValuesEqual(existingVal, val)) {
1655
+ if (!deepEqual(existingVal, val)) {
1516
1656
  throw new ShapeError(
1517
1657
  `Conflicting forced where values for "${field}.${op}": shape defines both ${safeStringify(existingVal)} and ${safeStringify(val)}`
1518
1658
  );
@@ -1522,7 +1662,7 @@ function mergeScalarConditions(target, source) {
1522
1662
  Object.assign(existing, ops);
1523
1663
  continue;
1524
1664
  }
1525
- if (!forcedValuesEqual(existing, ops)) {
1665
+ if (!deepEqual(existing, ops)) {
1526
1666
  throw new ShapeError(`Conflicting forced where values for "${field}"`);
1527
1667
  }
1528
1668
  }
@@ -1613,27 +1753,27 @@ function createWhereBuilder(typeMap, enumMap, scalarBase, uniqueMap = {}) {
1613
1753
  scalarConditions
1614
1754
  );
1615
1755
  }
1616
- for (const key of Object.keys(scalarConditions)) {
1756
+ const forcedOnlyKeys = /* @__PURE__ */ new Set();
1757
+ for (const key of Object.keys(whereConfig)) {
1617
1758
  if (COMBINATOR_KEYS.has(key))
1618
1759
  continue;
1619
1760
  if (!(key in fieldSchemas)) {
1620
- fieldSchemas[key] = z4.object({}).strict().optional();
1761
+ forcedOnlyKeys.add(key);
1621
1762
  }
1622
1763
  }
1623
- for (const key of Object.keys(relationForced)) {
1764
+ for (const key of Object.keys(scalarConditions)) {
1765
+ if (COMBINATOR_KEYS.has(key))
1766
+ continue;
1624
1767
  if (!(key in fieldSchemas)) {
1625
- fieldSchemas[key] = z4.object({}).strict().optional();
1768
+ fieldSchemas[key] = z5.object({}).strict().optional();
1626
1769
  }
1627
1770
  }
1628
- const schema = Object.keys(fieldSchemas).length > 0 ? z4.object(fieldSchemas).strict().optional() : null;
1629
- const forcedOnlyKeys = /* @__PURE__ */ new Set();
1630
- for (const key of Object.keys(whereConfig)) {
1631
- if (COMBINATOR_KEYS.has(key))
1632
- continue;
1771
+ for (const key of Object.keys(relationForced)) {
1633
1772
  if (!(key in fieldSchemas)) {
1634
- forcedOnlyKeys.add(key);
1773
+ fieldSchemas[key] = z5.object({}).strict().optional();
1635
1774
  }
1636
1775
  }
1776
+ const schema = Object.keys(fieldSchemas).length > 0 ? z5.object(fieldSchemas).strict().optional() : null;
1637
1777
  return {
1638
1778
  schema,
1639
1779
  forced: {
@@ -1664,12 +1804,12 @@ function createWhereBuilder(typeMap, enumMap, scalarBase, uniqueMap = {}) {
1664
1804
  );
1665
1805
  }
1666
1806
  if (key === "NOT") {
1667
- fieldSchemas[key] = z4.union([
1807
+ fieldSchemas[key] = z5.union([
1668
1808
  elementSchema,
1669
- z4.preprocess(coerceToArray, z4.array(elementSchema).min(1))
1809
+ z5.preprocess(coerceToArray, z5.array(elementSchema).min(1))
1670
1810
  ]).optional();
1671
1811
  } else {
1672
- fieldSchemas[key] = z4.preprocess(coerceToArray, z4.array(elementSchema).min(1)).optional();
1812
+ fieldSchemas[key] = z5.preprocess(coerceToArray, z5.array(elementSchema).min(1)).optional();
1673
1813
  }
1674
1814
  }
1675
1815
  if (hasWhereForced(result.forced)) {
@@ -1738,6 +1878,11 @@ function createWhereBuilder(typeMap, enumMap, scalarBase, uniqueMap = {}) {
1738
1878
  `Empty nested where for relation "${key}.${op}" on model "${model}". Define at least one field.`
1739
1879
  );
1740
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
+ }
1741
1886
  if (nested.schema) {
1742
1887
  if (!hasWhereForced(nested.forced)) {
1743
1888
  opSchemas[op] = nested.schema.refine(
@@ -1762,7 +1907,7 @@ function createWhereBuilder(typeMap, enumMap, scalarBase, uniqueMap = {}) {
1762
1907
  }
1763
1908
  if (hasClientOps) {
1764
1909
  const clientOpKeys = Object.keys(opSchemas);
1765
- const opObjSchema = z4.object(opSchemas).strict();
1910
+ const opObjSchema = z5.object(opSchemas).strict();
1766
1911
  if (Object.keys(opForced).length === 0 && !hasForcedNull) {
1767
1912
  fieldSchemas[key] = opObjSchema.refine(
1768
1913
  (v) => clientOpKeys.some(
@@ -1848,10 +1993,10 @@ function createWhereBuilder(typeMap, enumMap, scalarBase, uniqueMap = {}) {
1848
1993
  );
1849
1994
  }
1850
1995
  if (modeConfigValue === true) {
1851
- opSchemas.mode = z4.enum(["default", "insensitive"]).optional();
1996
+ opSchemas.mode = z5.enum(["default", "insensitive"]).optional();
1852
1997
  } else {
1853
1998
  const actualModeValue = isForcedValue(modeConfigValue) ? modeConfigValue.value : modeConfigValue;
1854
- const modeSchema = z4.enum(["default", "insensitive"]);
1999
+ const modeSchema = z5.enum(["default", "insensitive"]);
1855
2000
  let parsed;
1856
2001
  try {
1857
2002
  parsed = modeSchema.parse(actualModeValue);
@@ -1863,10 +2008,10 @@ function createWhereBuilder(typeMap, enumMap, scalarBase, uniqueMap = {}) {
1863
2008
  fieldForced.mode = parsed;
1864
2009
  }
1865
2010
  } else if (hasModeCompatibleOp) {
1866
- opSchemas.mode = z4.enum(["default", "insensitive"]).optional();
2011
+ opSchemas.mode = z5.enum(["default", "insensitive"]).optional();
1867
2012
  }
1868
2013
  if (hasClientOps) {
1869
- const opObj = z4.object(opSchemas).strict();
2014
+ const opObj = z5.object(opSchemas).strict();
1870
2015
  const refined = opObj.refine(
1871
2016
  (v) => clientOpKeys.some(
1872
2017
  (k) => v[k] !== void 0
@@ -1882,7 +2027,7 @@ function createWhereBuilder(typeMap, enumMap, scalarBase, uniqueMap = {}) {
1882
2027
  enumMap,
1883
2028
  scalarBase
1884
2029
  );
1885
- fieldSchemas[fieldName] = z4.union([refined, equalsBase]).optional();
2030
+ fieldSchemas[fieldName] = z5.union([refined, equalsBase]).optional();
1886
2031
  } else {
1887
2032
  fieldSchemas[fieldName] = refined.optional();
1888
2033
  }
@@ -1896,15 +2041,8 @@ function createWhereBuilder(typeMap, enumMap, scalarBase, uniqueMap = {}) {
1896
2041
  (constraint) => constraint.selector === selector
1897
2042
  ) ?? null;
1898
2043
  }
1899
- function buildDirectUniqueSchema(fieldMeta) {
1900
- const base = createBaseType(fieldMeta, enumMap, scalarBase);
1901
- if (!fieldMeta.isEnum && !fieldMeta.isRelation && !fieldMeta.isUnsupported) {
1902
- return wrapWithInputCoercion(fieldMeta.type, fieldMeta.isList, base);
1903
- }
1904
- return base;
1905
- }
1906
2044
  function parseForcedUniqueValue(model, fieldName, fieldMeta, value) {
1907
- const schema = buildDirectUniqueSchema(fieldMeta);
2045
+ const schema = buildDirectScalarSchema(fieldMeta, enumMap, scalarBase);
1908
2046
  const actual = isForcedValue(value) ? value.value : value;
1909
2047
  try {
1910
2048
  return schema.parse(actual);
@@ -1982,7 +2120,11 @@ function createWhereBuilder(typeMap, enumMap, scalarBase, uniqueMap = {}) {
1982
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.`
1983
2121
  );
1984
2122
  }
1985
- const directSchema2 = buildDirectUniqueSchema(fieldMeta2);
2123
+ const directSchema2 = buildDirectScalarSchema(
2124
+ fieldMeta2,
2125
+ enumMap,
2126
+ scalarBase
2127
+ );
1986
2128
  if (fieldValue === true) {
1987
2129
  nestedSchemas[fieldName] = directSchema2;
1988
2130
  } else {
@@ -1995,7 +2137,7 @@ function createWhereBuilder(typeMap, enumMap, scalarBase, uniqueMap = {}) {
1995
2137
  }
1996
2138
  }
1997
2139
  if (Object.keys(nestedSchemas).length > 0) {
1998
- fieldSchemas[key] = z4.object(nestedSchemas).strict();
2140
+ fieldSchemas[key] = z5.object(nestedSchemas).strict();
1999
2141
  }
2000
2142
  if (Object.keys(forcedCompound).length > 0) {
2001
2143
  forcedConditions[key] = forcedCompound;
@@ -2029,7 +2171,7 @@ function createWhereBuilder(typeMap, enumMap, scalarBase, uniqueMap = {}) {
2029
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 }.`
2030
2172
  );
2031
2173
  }
2032
- const directSchema = buildDirectUniqueSchema(fieldMeta);
2174
+ const directSchema = buildDirectScalarSchema(fieldMeta, enumMap, scalarBase);
2033
2175
  if (value === true) {
2034
2176
  fieldSchemas[key] = directSchema;
2035
2177
  continue;
@@ -2043,7 +2185,7 @@ function createWhereBuilder(typeMap, enumMap, scalarBase, uniqueMap = {}) {
2043
2185
  forcedOnlyKeys.add(key);
2044
2186
  }
2045
2187
  return {
2046
- schema: Object.keys(fieldSchemas).length > 0 ? z4.object(fieldSchemas).strict() : null,
2188
+ schema: Object.keys(fieldSchemas).length > 0 ? z5.object(fieldSchemas).strict() : null,
2047
2189
  forced: {
2048
2190
  conditions: forcedConditions,
2049
2191
  relations: {}
@@ -2055,31 +2197,13 @@ function createWhereBuilder(typeMap, enumMap, scalarBase, uniqueMap = {}) {
2055
2197
  }
2056
2198
 
2057
2199
  // src/runtime/query-builder-args.ts
2058
- import { z as z5 } from "zod";
2200
+ import { z as z6 } from "zod";
2059
2201
  var UNSUPPORTED_BY_TYPES = /* @__PURE__ */ new Set(["Json", "Bytes"]);
2060
- function requireConfigTrue(config, context) {
2061
- for (const [key, value] of Object.entries(config)) {
2062
- if (value !== true) {
2063
- throw new ShapeError(
2064
- `Config value for "${key}" in ${context} must be true, got ${typeof value}`
2065
- );
2066
- }
2067
- }
2068
- }
2069
- function isPlainRecord(value) {
2070
- return value !== null && typeof value === "object" && !Array.isArray(value);
2071
- }
2072
- function formatUniqueConstraint2(constraint) {
2073
- return constraint.fields.length === 1 ? constraint.selector : `${constraint.selector}(${constraint.fields.join(", ")})`;
2074
- }
2075
- function formatUniqueConstraints2(constraints) {
2076
- return constraints.map(formatUniqueConstraint2).join(" | ");
2077
- }
2078
2202
  function createArgsBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
2079
- const sortEnum = z5.enum(["asc", "desc"]);
2080
- const nullsEnum = z5.enum(["first", "last"]);
2081
- const sortWithNulls = z5.object({ sort: sortEnum, nulls: nullsEnum.optional() }).strict();
2082
- 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]);
2083
2207
  function validateScalarOrderByField(fieldName, model, modelFields) {
2084
2208
  const fieldMeta = modelFields[fieldName];
2085
2209
  if (!fieldMeta)
@@ -2098,6 +2222,16 @@ function createArgsBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
2098
2222
  );
2099
2223
  }
2100
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
+ }
2101
2235
  const modelFields = typeMap[model];
2102
2236
  if (!modelFields)
2103
2237
  throw new ShapeError(`Unknown model: ${model}`);
@@ -2113,53 +2247,35 @@ function createArgsBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
2113
2247
  fieldSchemas[fieldName] = scalarOrderSchema.optional();
2114
2248
  continue;
2115
2249
  }
2116
- if (!isPlainRecord(config)) {
2250
+ if (!isPlainObject(config)) {
2117
2251
  throw new ShapeError(
2118
- `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`
2119
2253
  );
2120
2254
  }
2121
2255
  if (!fieldMeta.isRelation) {
2122
- const allowedOps = getSupportedOperators(
2123
- fieldMeta.type,
2124
- fieldMeta.isList
2256
+ throw new ShapeError(
2257
+ `orderBy config for scalar field "${model}.${fieldName}" must be true. Operator objects are not valid in orderBy.`
2125
2258
  );
2126
- const opSchemas = {};
2127
- for (const [op, enabled] of Object.entries(config)) {
2128
- if (enabled !== true) {
2129
- throw new ShapeError(
2130
- `orderBy operator config for "${model}.${fieldName}.${op}" must be true`
2131
- );
2132
- }
2133
- if (!allowedOps.includes(op)) {
2134
- throw new ShapeError(
2135
- `Operator "${op}" not supported for orderBy field "${model}.${fieldName}"`
2136
- );
2137
- }
2138
- opSchemas[op] = scalarOrderSchema.optional();
2139
- }
2140
- const opKeys = Object.keys(opSchemas);
2141
- fieldSchemas[fieldName] = z5.object(opSchemas).strict().refine(
2142
- (v) => opKeys.some(
2143
- (k) => v[k] !== void 0
2144
- ),
2145
- {
2146
- message: `orderBy field "${fieldName}" must specify at least one operator`
2147
- }
2148
- ).optional();
2149
- continue;
2150
2259
  }
2151
2260
  if (fieldMeta.isList) {
2152
- if (!("_count" in config)) {
2261
+ const configKeys = Object.keys(config);
2262
+ if (!configKeys.includes("_count")) {
2153
2263
  throw new ShapeError(
2154
2264
  `To-many relation orderBy "${fieldName}" only supports _count`
2155
2265
  );
2156
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
+ }
2157
2273
  if (config._count !== true) {
2158
2274
  throw new ShapeError(
2159
2275
  `orderBy relation aggregate "${fieldName}._count" must be true`
2160
2276
  );
2161
2277
  }
2162
- fieldSchemas[fieldName] = z5.object({
2278
+ fieldSchemas[fieldName] = z6.object({
2163
2279
  _count: sortEnum.optional()
2164
2280
  }).strict().optional();
2165
2281
  continue;
@@ -2170,17 +2286,11 @@ function createArgsBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
2170
2286
  );
2171
2287
  fieldSchemas[fieldName] = nested;
2172
2288
  }
2173
- const fieldKeys = Object.keys(fieldSchemas);
2174
- const singleSchema = z5.object(fieldSchemas).strict().refine(
2175
- (v) => fieldKeys.some(
2176
- (k) => v[k] !== void 0
2177
- ),
2178
- { message: "orderBy must specify at least one field" }
2289
+ const singleSchema = strictObjectRequiringOne(
2290
+ fieldSchemas,
2291
+ "orderBy must specify at least one field"
2179
2292
  );
2180
- return z5.union([
2181
- singleSchema,
2182
- z5.preprocess(coerceToArray, z5.array(singleSchema).min(1))
2183
- ]).optional();
2293
+ return singleOrArraySchema(singleSchema).optional();
2184
2294
  }
2185
2295
  function buildTakeSchema(config) {
2186
2296
  if (typeof config === "number") {
@@ -2190,7 +2300,7 @@ function createArgsBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
2190
2300
  if (config <= 0) {
2191
2301
  throw new ShapeError("take must be a positive integer");
2192
2302
  }
2193
- return z5.literal(config).optional();
2303
+ return z6.number().int().min(1).max(config).default(config);
2194
2304
  }
2195
2305
  if (!config || typeof config !== "object" || Array.isArray(config)) {
2196
2306
  throw new ShapeError("take config must be a number or { max, default? }");
@@ -2215,9 +2325,9 @@ function createArgsBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
2215
2325
  if (config.default > config.max) {
2216
2326
  throw new ShapeError("take.default cannot exceed take.max");
2217
2327
  }
2218
- 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);
2219
2329
  }
2220
- return z5.number().int().min(1).max(config.max).optional();
2330
+ return z6.number().int().min(1).max(config.max).optional();
2221
2331
  }
2222
2332
  function buildCursorFieldSchema(model, fieldName) {
2223
2333
  const modelFields = typeMap[model];
@@ -2239,11 +2349,7 @@ function createArgsBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
2239
2349
  `List field "${fieldName}" cannot be used in cursor`
2240
2350
  );
2241
2351
  }
2242
- const base = createBaseType(fieldMeta, enumMap, scalarBase);
2243
- if (!fieldMeta.isEnum && !fieldMeta.isRelation && !fieldMeta.isUnsupported) {
2244
- return wrapWithInputCoercion(fieldMeta.type, fieldMeta.isList, base);
2245
- }
2246
- return base;
2352
+ return buildDirectScalarSchema(fieldMeta, enumMap, scalarBase);
2247
2353
  }
2248
2354
  function cursorConfigMatchesConstraint(cursorConfig, constraint) {
2249
2355
  if (!(constraint.selector in cursorConfig))
@@ -2252,66 +2358,55 @@ function createArgsBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
2252
2358
  if (constraint.fields.length === 1) {
2253
2359
  return value === true;
2254
2360
  }
2255
- if (!isPlainRecord(value))
2361
+ if (!isPlainObject(value))
2256
2362
  return false;
2257
2363
  const keys = Object.keys(value);
2258
2364
  if (keys.length !== constraint.fields.length)
2259
2365
  return false;
2260
2366
  return constraint.fields.every((field) => value[field] === true);
2261
2367
  }
2262
- function getUniqueConstraints(model) {
2263
- const constraints = uniqueMap[model];
2264
- if (constraints && constraints.length > 0) {
2265
- return constraints;
2266
- }
2267
- const modelFields = typeMap[model];
2268
- if (!modelFields) {
2269
- throw new ShapeError(`Unknown model: ${model}`);
2270
- }
2271
- const inferred = [];
2272
- for (const [fieldName, fieldMeta] of Object.entries(modelFields)) {
2273
- if (fieldMeta.isRelation)
2274
- continue;
2275
- if (fieldMeta.isId || fieldMeta.isUnique) {
2276
- inferred.push({
2277
- selector: fieldName,
2278
- fields: [fieldName]
2279
- });
2280
- }
2281
- }
2282
- return inferred;
2283
- }
2284
2368
  function buildCursorSchema(model, cursorConfig) {
2285
- const constraints = getUniqueConstraints(model);
2369
+ const constraints = uniqueMap[model] ?? [];
2286
2370
  if (constraints.length === 0) {
2287
2371
  throw new ShapeError(
2288
2372
  `cursor on model "${model}" requires at least one unique constraint`
2289
2373
  );
2290
2374
  }
2291
- const matching = constraints.find(
2375
+ const matching = constraints.filter(
2292
2376
  (constraint) => cursorConfigMatchesConstraint(cursorConfig, constraint)
2293
2377
  );
2294
- if (!matching) {
2378
+ if (matching.length === 0) {
2295
2379
  throw new ShapeError(
2296
- `cursor on model "${model}" must exactly match a unique selector: ${formatUniqueConstraints2(constraints)}`
2380
+ `cursor on model "${model}" must match a unique selector: ${formatUniqueConstraints(constraints)}`
2297
2381
  );
2298
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
+ }
2299
2391
  const fieldSchemas = {};
2300
- if (matching.fields.length === 1) {
2301
- fieldSchemas[matching.selector] = buildCursorFieldSchema(
2302
- model,
2303
- matching.fields[0]
2304
- ).optional();
2305
- } else {
2306
- const nestedSchemas = {};
2307
- for (const field of matching.fields) {
2308
- 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();
2309
2404
  }
2310
- fieldSchemas[matching.selector] = z5.object(nestedSchemas).strict().optional();
2311
2405
  }
2312
- return z5.object(fieldSchemas).strict().refine(
2313
- (v) => v[matching.selector] !== void 0,
2314
- { 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(", ")}`
2315
2410
  ).optional();
2316
2411
  }
2317
2412
  function buildDistinctSchema(model, distinctConfig) {
@@ -2336,10 +2431,8 @@ function createArgsBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
2336
2431
  );
2337
2432
  allowedFields.add(fieldName);
2338
2433
  }
2339
- return z5.union([
2340
- z5.enum([...allowedFields]),
2341
- z5.array(z5.enum([...allowedFields])).min(1)
2342
- ]).optional();
2434
+ const fieldEnum = z6.enum([...allowedFields]);
2435
+ return z6.union([fieldEnum, z6.array(fieldEnum).min(1)]).optional();
2343
2436
  }
2344
2437
  function buildBySchema(model, byConfig) {
2345
2438
  const modelFields = typeMap[model];
@@ -2372,7 +2465,7 @@ function createArgsBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
2372
2465
  }
2373
2466
  allowedFields.add(fieldName);
2374
2467
  }
2375
- return z5.array(z5.enum([...allowedFields])).min(1);
2468
+ return z6.array(z6.enum([...allowedFields])).min(1);
2376
2469
  }
2377
2470
  function buildHavingSchema(model, havingConfig) {
2378
2471
  const modelFields = typeMap[model];
@@ -2413,22 +2506,21 @@ function createArgsBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
2413
2506
  ).optional();
2414
2507
  }
2415
2508
  if (fieldMeta.type === "String") {
2416
- opSchemas.mode = z5.enum(["default", "insensitive"]).optional();
2509
+ opSchemas.mode = z6.enum(["default", "insensitive"]).optional();
2417
2510
  }
2418
2511
  const opKeys = Object.keys(opSchemas).filter((key) => key !== "mode");
2419
- fieldSchemas[fieldName] = z5.object(opSchemas).strict().refine(
2512
+ const opShape = { ...opSchemas };
2513
+ const opObjSchema = z6.object(opShape).strict().refine(
2420
2514
  (v) => opKeys.some((k) => v[k] !== void 0),
2421
2515
  {
2422
2516
  message: `having field "${fieldName}" must specify at least one operator`
2423
2517
  }
2424
- ).optional();
2518
+ );
2519
+ fieldSchemas[fieldName] = opObjSchema.optional();
2425
2520
  }
2426
- const fieldKeys = Object.keys(fieldSchemas);
2427
- return z5.object(fieldSchemas).strict().refine(
2428
- (v) => fieldKeys.some(
2429
- (k) => v[k] !== void 0
2430
- ),
2431
- { message: "having must specify at least one field" }
2521
+ return strictObjectRequiringOne(
2522
+ fieldSchemas,
2523
+ "having must specify at least one field"
2432
2524
  ).optional();
2433
2525
  }
2434
2526
  function buildAggregateFieldSchema(model, op, config) {
@@ -2437,47 +2529,45 @@ function createArgsBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
2437
2529
  throw new ShapeError(`Unknown model: ${model}`);
2438
2530
  requireConfigTrue(config, `${op} on model "${model}"`);
2439
2531
  const allowedTypes = op === "_avg" || op === "_sum" ? NUMERIC_TYPES : COMPARABLE_TYPES;
2440
- const fieldSchemas = {};
2441
- for (const fieldName of Object.keys(config)) {
2442
- const fieldMeta = modelFields[fieldName];
2443
- if (!fieldMeta)
2444
- throw new ShapeError(
2445
- `Unknown field "${fieldName}" on model "${model}" in ${op}`
2446
- );
2447
- if (fieldMeta.isRelation)
2448
- throw new ShapeError(
2449
- `Relation field "${fieldName}" cannot be used in ${op}`
2450
- );
2451
- if (fieldMeta.isList)
2452
- throw new ShapeError(
2453
- `List field "${fieldName}" cannot be used in ${op}`
2454
- );
2455
- if (!allowedTypes.has(fieldMeta.type)) {
2456
- throw new ShapeError(
2457
- `Field "${fieldName}" of type "${fieldMeta.type}" cannot be used in ${op}`
2458
- );
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
+ }
2459
2554
  }
2460
- fieldSchemas[fieldName] = z5.literal(true).optional();
2461
- }
2462
- const aggregateFieldKeys = Object.keys(fieldSchemas);
2463
- return z5.object(fieldSchemas).strict().refine(
2464
- (v) => aggregateFieldKeys.some(
2465
- (k) => v[k] !== void 0
2466
- ),
2467
- { message: `${op} must specify at least one field` }
2468
- ).optional();
2555
+ );
2469
2556
  }
2470
2557
  function buildCountFieldSchema(model, config, context) {
2471
2558
  if (config === true) {
2472
- return z5.literal(true).optional();
2559
+ return z6.literal(true).optional();
2473
2560
  }
2474
2561
  const modelFields = typeMap[model];
2475
2562
  if (!modelFields)
2476
2563
  throw new ShapeError(`Unknown model: ${model}`);
2477
2564
  requireConfigTrue(config, `${context} on model "${model}"`);
2478
- const fieldSchemas = {};
2479
- for (const fieldName of Object.keys(config)) {
2480
- 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;
2481
2571
  const fieldMeta = modelFields[fieldName];
2482
2572
  if (!fieldMeta)
2483
2573
  throw new ShapeError(
@@ -2488,45 +2578,30 @@ function createArgsBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
2488
2578
  `Relation field "${fieldName}" cannot be used in ${context}`
2489
2579
  );
2490
2580
  }
2491
- fieldSchemas[fieldName] = z5.literal(true).optional();
2492
- }
2493
- const countFieldKeys = Object.keys(fieldSchemas);
2494
- return z5.object(fieldSchemas).strict().refine(
2495
- (v) => countFieldKeys.some(
2496
- (k) => v[k] !== void 0
2497
- ),
2498
- { message: `${context} must specify at least one field` }
2499
- ).optional();
2581
+ );
2500
2582
  }
2501
2583
  function buildCountSelectSchema(model, selectConfig) {
2502
2584
  const modelFields = typeMap[model];
2503
2585
  if (!modelFields)
2504
2586
  throw new ShapeError(`Unknown model: ${model}`);
2505
2587
  requireConfigTrue(selectConfig, `count select on model "${model}"`);
2506
- const fieldSchemas = {};
2507
- for (const fieldName of Object.keys(selectConfig)) {
2508
- if (fieldName === "_all") {
2509
- fieldSchemas._all = z5.literal(true).optional();
2510
- 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
+ );
2511
2603
  }
2512
- const fieldMeta = modelFields[fieldName];
2513
- if (!fieldMeta)
2514
- throw new ShapeError(
2515
- `Unknown field "${fieldName}" on model "${model}" in count select`
2516
- );
2517
- if (fieldMeta.isRelation)
2518
- throw new ShapeError(
2519
- `Relation field "${fieldName}" cannot be used in count select`
2520
- );
2521
- fieldSchemas[fieldName] = z5.literal(true).optional();
2522
- }
2523
- const countSelectKeys = Object.keys(fieldSchemas);
2524
- return z5.object(fieldSchemas).strict().refine(
2525
- (v) => countSelectKeys.some(
2526
- (k) => v[k] !== void 0
2527
- ),
2528
- { message: "count select must specify at least one field" }
2529
- ).optional();
2604
+ );
2530
2605
  }
2531
2606
  return {
2532
2607
  buildOrderBySchema,
@@ -2542,25 +2617,64 @@ function createArgsBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
2542
2617
  }
2543
2618
 
2544
2619
  // src/runtime/query-builder-projection.ts
2545
- import { z as z6 } from "zod";
2546
- var KNOWN_NESTED_INCLUDE_KEYS = /* @__PURE__ */ new Set([
2547
- "where",
2548
- "include",
2549
- "select",
2550
- "orderBy",
2551
- "cursor",
2552
- "take",
2553
- "skip"
2554
- ]);
2555
- var KNOWN_NESTED_SELECT_KEYS = /* @__PURE__ */ new Set([
2556
- "select",
2557
- "include",
2558
- "where",
2559
- "orderBy",
2560
- "cursor",
2561
- "take",
2562
- "skip"
2563
- ]);
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
+ };
2564
2678
  var KNOWN_COUNT_SELECT_ENTRY_KEYS = /* @__PURE__ */ new Set(["where"]);
2565
2679
  var MAX_PROJECTION_DEPTH = 10;
2566
2680
  function validateNestedKeys(keys, allowed, context) {
@@ -2572,13 +2686,25 @@ function validateNestedKeys(keys, allowed, context) {
2572
2686
  }
2573
2687
  }
2574
2688
  }
2575
- 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) {
2576
2702
  function buildIncludeCountSchema(model, config) {
2577
2703
  const modelFields = typeMap[model];
2578
2704
  if (!modelFields)
2579
2705
  throw new ShapeError(`Unknown model: ${model}`);
2580
2706
  if (config === true) {
2581
- return { schema: z6.literal(true).optional(), forcedCountWhere: {} };
2707
+ return { schema: z7.literal(true).optional(), forcedCountWhere: {} };
2582
2708
  }
2583
2709
  if (!isPlainObject(config) || !("select" in config)) {
2584
2710
  throw new ShapeError(
@@ -2614,273 +2740,175 @@ function createProjectionBuilder(typeMap, enumMap, deps) {
2614
2740
  if (!fieldMeta.isList)
2615
2741
  throw new ShapeError(`Field "${fieldName}" is a to-one relation on model "${model}" in _count.select. Only to-many relations support _count.`);
2616
2742
  if (fieldConfig === true) {
2617
- countSelectFields[fieldName] = z6.literal(true).optional();
2618
- } else if (isPlainObject(fieldConfig)) {
2619
- if (Object.keys(fieldConfig).length === 0) {
2620
- throw new ShapeError(
2621
- `Empty config for _count.select.${fieldName} on model "${model}". Use true or { where: { ... } }.`
2622
- );
2623
- }
2624
- validateNestedKeys(
2625
- Object.keys(fieldConfig),
2626
- KNOWN_COUNT_SELECT_ENTRY_KEYS,
2627
- `_count.select.${fieldName} on model "${model}"`
2628
- );
2629
- if (fieldConfig.where) {
2630
- const relatedType = fieldMeta.type;
2631
- const { schema: whereSchema, forced } = deps.buildWhereSchema(
2632
- relatedType,
2633
- fieldConfig.where
2634
- );
2635
- const nestedSchemas = {};
2636
- if (whereSchema)
2637
- nestedSchemas["where"] = whereSchema;
2638
- const nestedObj = z6.object(nestedSchemas).strict();
2639
- countSelectFields[fieldName] = z6.union([z6.literal(true), nestedObj]).optional();
2640
- if (hasWhereForced(forced)) {
2641
- forcedCountWhere[fieldName] = forced;
2642
- }
2643
- } else {
2644
- countSelectFields[fieldName] = z6.literal(true).optional();
2645
- }
2646
- } else {
2743
+ countSelectFields[fieldName] = z7.literal(true).optional();
2744
+ continue;
2745
+ }
2746
+ if (!isPlainObject(fieldConfig)) {
2647
2747
  throw new ShapeError(
2648
2748
  `Invalid config for _count.select.${fieldName} on model "${model}". Expected true or { where: { ... } }`
2649
2749
  );
2650
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
+ }
2651
2778
  }
2652
- const countSelectKeys = Object.keys(countSelectFields);
2653
- const selectSchema = z6.object(countSelectFields).strict().refine(
2654
- (v) => countSelectKeys.some((k) => v[k] !== void 0),
2655
- { message: "_count.select must specify at least one field" }
2779
+ const selectSchema = strictObjectRequiringOne(
2780
+ countSelectFields,
2781
+ "_count.select must specify at least one field"
2656
2782
  );
2657
2783
  return {
2658
- schema: z6.object({ select: selectSchema }).strict().optional(),
2784
+ schema: z7.object({ select: selectSchema }).strict().optional(),
2659
2785
  forcedCountWhere
2660
2786
  };
2661
2787
  }
2662
- 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) {
2663
2836
  const currentDepth = depth ?? 0;
2664
2837
  if (currentDepth > MAX_PROJECTION_DEPTH) {
2665
2838
  throw new ShapeError(
2666
- `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.`
2667
2840
  );
2668
2841
  }
2669
- if (Object.keys(includeConfig).length === 0) {
2842
+ if (Object.keys(projectionConfig).length === 0) {
2670
2843
  throw new ShapeError(
2671
- `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"}.`
2672
2845
  );
2673
2846
  }
2674
2847
  const modelFields = typeMap[model];
2675
2848
  if (!modelFields)
2676
2849
  throw new ShapeError(`Unknown model: ${model}`);
2850
+ const allowedNestedKeys = KNOWN_NESTED_KEYS[mode];
2677
2851
  const fieldSchemas = {};
2678
2852
  const forcedTree = {};
2679
2853
  let topLevelForcedCountWhere = {};
2680
- for (const [relName, config] of Object.entries(includeConfig)) {
2681
- if (relName === "_count") {
2854
+ for (const [fieldName, config] of Object.entries(projectionConfig)) {
2855
+ if (fieldName === "_count") {
2682
2856
  const countResult = buildIncludeCountSchema(model, config);
2683
2857
  fieldSchemas["_count"] = countResult.schema;
2684
2858
  topLevelForcedCountWhere = countResult.forcedCountWhere;
2685
2859
  continue;
2686
2860
  }
2687
- const fieldMeta = modelFields[relName];
2861
+ const fieldMeta = modelFields[fieldName];
2688
2862
  if (!fieldMeta)
2689
- throw new ShapeError(`Unknown field "${relName}" on model "${model}"`);
2690
- if (!fieldMeta.isRelation)
2691
- 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
+ }
2692
2867
  if (config === true) {
2693
- fieldSchemas[relName] = z6.literal(true).optional();
2694
- } else {
2695
- validateNestedKeys(
2696
- Object.keys(config),
2697
- KNOWN_NESTED_INCLUDE_KEYS,
2698
- `nested include for "${relName}" on model "${model}"`
2699
- );
2700
- if (config.select && config.include) {
2701
- throw new ShapeError(`Nested include for "${relName}" cannot define both "select" and "include".`);
2702
- }
2703
- if (!fieldMeta.isList) {
2704
- if (config.where || config.orderBy || config.cursor || config.take || config.skip) {
2705
- throw new ShapeError(
2706
- `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.`
2707
- );
2708
- }
2709
- }
2710
- const nestedSchemas = {};
2711
- const relForced = {};
2712
- if (config.where) {
2713
- const { schema: whereSchema, forced } = deps.buildWhereSchema(
2714
- fieldMeta.type,
2715
- config.where
2716
- );
2717
- if (whereSchema)
2718
- nestedSchemas["where"] = whereSchema;
2719
- if (hasWhereForced(forced))
2720
- relForced.where = forced;
2721
- }
2722
- if (config.include) {
2723
- const nested = buildIncludeSchema(fieldMeta.type, config.include, currentDepth + 1);
2724
- nestedSchemas["include"] = nested.schema;
2725
- if (Object.keys(nested.forcedTree).length > 0)
2726
- relForced.include = nested.forcedTree;
2727
- if (Object.keys(nested.forcedCountWhere).length > 0) {
2728
- relForced._countWhere = nested.forcedCountWhere;
2729
- relForced._countWherePlacement = "include";
2730
- }
2731
- }
2732
- if (config.select) {
2733
- const nested = buildSelectSchema(fieldMeta.type, config.select, currentDepth + 1);
2734
- nestedSchemas["select"] = nested.schema;
2735
- if (Object.keys(nested.forcedTree).length > 0)
2736
- relForced.select = nested.forcedTree;
2737
- if (Object.keys(nested.forcedCountWhere).length > 0) {
2738
- relForced._countWhere = nested.forcedCountWhere;
2739
- relForced._countWherePlacement = "select";
2740
- }
2741
- }
2742
- if (config.orderBy) {
2743
- nestedSchemas["orderBy"] = deps.buildOrderBySchema(fieldMeta.type, config.orderBy);
2744
- }
2745
- if (config.cursor) {
2746
- nestedSchemas["cursor"] = deps.buildCursorSchema(fieldMeta.type, config.cursor);
2747
- }
2748
- if (config.take) {
2749
- nestedSchemas["take"] = deps.buildTakeSchema(config.take);
2750
- }
2751
- if (config.skip) {
2752
- nestedSchemas["skip"] = z6.number().int().min(0).optional();
2753
- }
2754
- const nestedObj = z6.object(nestedSchemas).strict();
2755
- fieldSchemas[relName] = z6.union([z6.literal(true), nestedObj]).optional();
2756
- if (Object.keys(relForced).length > 0)
2757
- forcedTree[relName] = relForced;
2758
- }
2759
- }
2760
- const includeFieldKeys = Object.keys(fieldSchemas);
2761
- const baseSchema = z6.object(fieldSchemas).strict();
2762
- const schema = includeFieldKeys.length > 0 ? baseSchema.refine(
2763
- (v) => includeFieldKeys.some((k) => v[k] !== void 0),
2764
- { message: "include must specify at least one field" }
2765
- ).optional() : baseSchema.optional();
2766
- return {
2767
- schema,
2768
- forcedTree,
2769
- forcedCountWhere: topLevelForcedCountWhere
2770
- };
2771
- }
2772
- function buildSelectSchema(model, selectConfig, depth) {
2773
- const currentDepth = depth ?? 0;
2774
- if (currentDepth > MAX_PROJECTION_DEPTH) {
2775
- throw new ShapeError(
2776
- `Select schema for model "${model}" exceeds maximum nesting depth (${MAX_PROJECTION_DEPTH}). Check for circular relation references in the shape.`
2777
- );
2778
- }
2779
- if (Object.keys(selectConfig).length === 0) {
2780
- throw new ShapeError(
2781
- `Empty select config on model "${model}". Define at least one field.`
2782
- );
2783
- }
2784
- const modelFields = typeMap[model];
2785
- if (!modelFields)
2786
- throw new ShapeError(`Unknown model: ${model}`);
2787
- const fieldSchemas = {};
2788
- const forcedTree = {};
2789
- let topLevelForcedCountWhere = {};
2790
- for (const [fieldName, config] of Object.entries(selectConfig)) {
2791
- if (fieldName === "_count") {
2792
- const countResult = buildIncludeCountSchema(model, config);
2793
- fieldSchemas["_count"] = countResult.schema;
2794
- topLevelForcedCountWhere = countResult.forcedCountWhere;
2868
+ fieldSchemas[fieldName] = z7.literal(true).optional();
2795
2869
  continue;
2796
2870
  }
2797
- const fieldMeta = modelFields[fieldName];
2798
- if (!fieldMeta)
2799
- throw new ShapeError(`Unknown field "${fieldName}" on model "${model}"`);
2800
- if (config === true) {
2801
- fieldSchemas[fieldName] = z6.literal(true).optional();
2802
- } else {
2803
- if (!fieldMeta.isRelation) {
2804
- throw new ShapeError(`Nested select args only valid for relations, not scalar "${fieldName}" on model "${model}"`);
2805
- }
2806
- validateNestedKeys(
2807
- Object.keys(config),
2808
- KNOWN_NESTED_SELECT_KEYS,
2809
- `nested select for "${fieldName}" on model "${model}"`
2810
- );
2811
- if (config.select && config.include) {
2812
- throw new ShapeError(`Nested select for "${fieldName}" cannot define both "select" and "include".`);
2813
- }
2814
- if (!fieldMeta.isList) {
2815
- if (config.where || config.orderBy || config.cursor || config.take || config.skip) {
2816
- throw new ShapeError(
2817
- `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.`
2818
- );
2819
- }
2820
- }
2821
- const nestedSchemas = {};
2822
- const relForced = {};
2823
- if (config.select) {
2824
- const nested = buildSelectSchema(fieldMeta.type, config.select, currentDepth + 1);
2825
- nestedSchemas["select"] = nested.schema;
2826
- if (Object.keys(nested.forcedTree).length > 0)
2827
- relForced.select = nested.forcedTree;
2828
- if (Object.keys(nested.forcedCountWhere).length > 0) {
2829
- relForced._countWhere = nested.forcedCountWhere;
2830
- relForced._countWherePlacement = "select";
2831
- }
2832
- }
2833
- if (config.include) {
2834
- const nested = buildIncludeSchema(fieldMeta.type, config.include, currentDepth + 1);
2835
- nestedSchemas["include"] = nested.schema;
2836
- if (Object.keys(nested.forcedTree).length > 0)
2837
- relForced.include = nested.forcedTree;
2838
- if (Object.keys(nested.forcedCountWhere).length > 0) {
2839
- relForced._countWhere = nested.forcedCountWhere;
2840
- relForced._countWherePlacement = "include";
2841
- }
2842
- }
2843
- if (config.where) {
2844
- const { schema: whereSchema, forced } = deps.buildWhereSchema(
2845
- fieldMeta.type,
2846
- 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.`
2847
2883
  );
2848
- if (whereSchema)
2849
- nestedSchemas["where"] = whereSchema;
2850
- if (hasWhereForced(forced))
2851
- relForced.where = forced;
2852
- }
2853
- if (config.orderBy) {
2854
- nestedSchemas["orderBy"] = deps.buildOrderBySchema(fieldMeta.type, config.orderBy);
2855
2884
  }
2856
- if (config.cursor) {
2857
- nestedSchemas["cursor"] = deps.buildCursorSchema(fieldMeta.type, config.cursor);
2858
- }
2859
- if (config.take) {
2860
- nestedSchemas["take"] = deps.buildTakeSchema(config.take);
2861
- }
2862
- if (config.skip) {
2863
- nestedSchemas["skip"] = z6.number().int().min(0).optional();
2864
- }
2865
- const nestedObj = z6.object(nestedSchemas).strict();
2866
- fieldSchemas[fieldName] = z6.union([z6.literal(true), nestedObj]).optional();
2867
- if (Object.keys(relForced).length > 0)
2868
- forcedTree[fieldName] = relForced;
2869
- }
2870
- }
2871
- const selectFieldKeys = Object.keys(fieldSchemas);
2872
- const baseSchema = z6.object(fieldSchemas).strict();
2873
- const schema = selectFieldKeys.length > 0 ? baseSchema.refine(
2874
- (v) => selectFieldKeys.some((k) => v[k] !== void 0),
2875
- { message: "select must specify at least one field" }
2876
- ).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();
2877
2899
  return {
2878
2900
  schema,
2879
2901
  forcedTree,
2880
2902
  forcedCountWhere: topLevelForcedCountWhere
2881
2903
  };
2882
2904
  }
2883
- 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 };
2884
2912
  }
2885
2913
 
2886
2914
  // src/shared/operation-shape-keys.ts
@@ -2890,7 +2918,6 @@ var OPERATION_SHAPE_KEYS = {
2890
2918
  findFirstOrThrow: ["where", "include", "select", "orderBy", "cursor", "take", "skip", "distinct"],
2891
2919
  findUnique: ["where", "include", "select"],
2892
2920
  findUniqueOrThrow: ["where", "include", "select"],
2893
- findManyPaginated: ["where", "include", "select", "orderBy", "cursor", "take", "skip", "distinct"],
2894
2921
  count: ["where", "select", "cursor", "orderBy", "skip", "take"],
2895
2922
  aggregate: ["where", "orderBy", "cursor", "take", "skip", "_count", "_avg", "_sum", "_min", "_max"],
2896
2923
  groupBy: ["where", "by", "having", "_count", "_avg", "_sum", "_min", "_max", "orderBy", "take", "skip"],
@@ -2925,6 +2952,99 @@ var MUTATION_SHAPE_KEYS = {
2925
2952
  delete: new Set(OPERATION_SHAPE_KEYS.delete),
2926
2953
  deleteMany: new Set(OPERATION_SHAPE_KEYS.deleteMany)
2927
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
+ }
2928
3048
 
2929
3049
  // src/runtime/query-builder.ts
2930
3050
  var METHOD_ALLOWED_ARGS = READ_METHOD_ALLOWED_ARGS;
@@ -3025,6 +3145,90 @@ function createQueryBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
3025
3145
  }
3026
3146
  return shapeOrFn;
3027
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
+ }
3028
3232
  function buildShapeZodSchema(model, method, shape) {
3029
3233
  validateShapeArgs(method, shape);
3030
3234
  validateUniqueWhere(model, method, shape);
@@ -3064,73 +3268,19 @@ function createQueryBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
3064
3268
  }
3065
3269
  if (shape.orderBy) {
3066
3270
  if (method === "groupBy" && shape.by) {
3067
- const sortEnum = z7.enum(["asc", "desc"]);
3068
- 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 {
3069
3279
  if (shape.orderBy === true) {
3070
- const groupByOrderFields = {};
3071
- for (const field of shape.by) {
3072
- groupByOrderFields[field] = sortEnum.optional();
3073
- }
3074
- groupByOrderFields._count = sortEnum.optional();
3075
- const fieldKeys = Object.keys(groupByOrderFields);
3076
- const singleSchema = z7.object(groupByOrderFields).strict().refine(
3077
- (v) => fieldKeys.some(
3078
- (k) => v[k] !== void 0
3079
- ),
3080
- { message: "orderBy must specify at least one field" }
3081
- );
3082
- schemaFields.orderBy = z7.union([
3083
- singleSchema,
3084
- z7.preprocess(coerceToArray, z7.array(singleSchema).min(1))
3085
- ]).optional();
3086
- } else {
3087
- const groupByOrderFields = {};
3088
- for (const [fieldName, config] of Object.entries(shape.orderBy)) {
3089
- if (fieldName === "_count") {
3090
- if (config === true) {
3091
- groupByOrderFields._count = sortEnum.optional();
3092
- } else if (typeof config === "object" && config !== null) {
3093
- const countFields = {};
3094
- for (const countField of Object.keys(config)) {
3095
- if (!bySet.has(countField)) {
3096
- throw new ShapeError(
3097
- `orderBy _count field "${countField}" must be included in "by" for groupBy`
3098
- );
3099
- }
3100
- countFields[countField] = sortEnum.optional();
3101
- }
3102
- const countKeys = Object.keys(countFields);
3103
- groupByOrderFields._count = z7.object(countFields).strict().refine(
3104
- (v) => countKeys.some(
3105
- (k) => v[k] !== void 0
3106
- ),
3107
- {
3108
- message: "orderBy._count must specify at least one field"
3109
- }
3110
- ).optional();
3111
- }
3112
- continue;
3113
- }
3114
- if (!bySet.has(fieldName)) {
3115
- throw new ShapeError(
3116
- `orderBy field "${fieldName}" must be included in "by" for groupBy`
3117
- );
3118
- }
3119
- groupByOrderFields[fieldName] = sortEnum.optional();
3120
- }
3121
- const fieldKeys = Object.keys(groupByOrderFields);
3122
- const singleSchema = z7.object(groupByOrderFields).strict().refine(
3123
- (v) => fieldKeys.some(
3124
- (k) => v[k] !== void 0
3125
- ),
3126
- { 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.`
3127
3282
  );
3128
- schemaFields.orderBy = z7.union([
3129
- singleSchema,
3130
- z7.preprocess(coerceToArray, z7.array(singleSchema).min(1))
3131
- ]).optional();
3132
3283
  }
3133
- } else {
3134
3284
  schemaFields.orderBy = argsBuilder.buildOrderBySchema(
3135
3285
  model,
3136
3286
  shape.orderBy
@@ -3138,19 +3288,16 @@ function createQueryBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
3138
3288
  }
3139
3289
  }
3140
3290
  if (shape.cursor) {
3141
- schemaFields.cursor = argsBuilder.buildCursorSchema(
3142
- model,
3143
- shape.cursor
3144
- );
3291
+ schemaFields.cursor = argsBuilder.buildCursorSchema(model, shape.cursor);
3145
3292
  }
3146
- if (shape.take) {
3293
+ if (shape.take !== void 0) {
3147
3294
  schemaFields.take = argsBuilder.buildTakeSchema(shape.take);
3148
3295
  }
3149
3296
  if (shape.skip !== void 0) {
3150
3297
  if (shape.skip !== true) {
3151
3298
  throw new ShapeError('Shape config "skip" must be true');
3152
3299
  }
3153
- schemaFields.skip = z7.number().int().min(0).optional();
3300
+ schemaFields.skip = z8.number().int().min(0).optional();
3154
3301
  }
3155
3302
  if (shape.distinct) {
3156
3303
  schemaFields.distinct = argsBuilder.buildDistinctSchema(
@@ -3197,13 +3344,10 @@ function createQueryBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
3197
3344
  schemaFields.by = argsBuilder.buildBySchema(model, shape.by);
3198
3345
  }
3199
3346
  if (shape.having) {
3200
- schemaFields.having = argsBuilder.buildHavingSchema(
3201
- model,
3202
- shape.having
3203
- );
3347
+ schemaFields.having = argsBuilder.buildHavingSchema(model, shape.having);
3204
3348
  }
3205
3349
  return {
3206
- zodSchema: z7.object(schemaFields).strict(),
3350
+ zodSchema: z8.object(schemaFields).strict(),
3207
3351
  forcedWhere,
3208
3352
  forcedOnlyWhereKeys,
3209
3353
  forcedIncludeTree,
@@ -3396,22 +3540,18 @@ function buildScopedUniqueWhere(existingWhere, conditions, scopeFks, log, model)
3396
3540
  allConditions.push(...conditions);
3397
3541
  return { ...topLevel, AND: allConditions };
3398
3542
  }
3399
- function isComparableScopeValue(v) {
3400
- const t = typeof v;
3401
- return t === "string" || t === "number" || t === "bigint";
3402
- }
3403
- function looseEqual(a, b, log, fk) {
3543
+ function scopeValuesEqual(a, b) {
3404
3544
  if (a === b)
3405
3545
  return true;
3406
- if (!isComparableScopeValue(a) || !isComparableScopeValue(b))
3407
- return false;
3408
- const eq = String(a) === String(b);
3409
- if (eq && log && fk) {
3410
- log.warn(
3411
- `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.`
3412
- );
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);
3413
3550
  }
3414
- return eq;
3551
+ if (bIsBig && typeof a === "number") {
3552
+ return Number.isInteger(a) && b === BigInt(a);
3553
+ }
3554
+ return false;
3415
3555
  }
3416
3556
  function buildFkSelect(fks) {
3417
3557
  const select = {};
@@ -3701,7 +3841,7 @@ async function handleFindUnique(args, query, conditions, scopes, operation, log,
3701
3841
  const result = await query(nextArgs);
3702
3842
  if (result === null)
3703
3843
  return result;
3704
- if (typeof result !== "object" || result === null) {
3844
+ if (typeof result !== "object") {
3705
3845
  throw new ShapeError(
3706
3846
  `${operation} on model "${model}" returned a non-object, non-null result`
3707
3847
  );
@@ -3732,7 +3872,7 @@ async function handleFindUnique(args, query, conditions, scopes, operation, log,
3732
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.`
3733
3873
  );
3734
3874
  }
3735
- if (typeof verifyResult !== "object" || verifyResult === null) {
3875
+ if (typeof verifyResult !== "object") {
3736
3876
  throw new PolicyError(
3737
3877
  `prisma-guard: Scope verification re-query on model "${model}" returned a non-object result.`
3738
3878
  );
@@ -3746,7 +3886,7 @@ async function handleFindUnique(args, query, conditions, scopes, operation, log,
3746
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).`
3747
3887
  );
3748
3888
  }
3749
- if (!looseEqual(verifyObj[fk], value, log, fk)) {
3889
+ if (!scopeValuesEqual(verifyObj[fk], value)) {
3750
3890
  if (operation === "findUniqueOrThrow") {
3751
3891
  throw new PolicyError(
3752
3892
  `prisma-guard: Record on model "${model}" not accessible in current scope`
@@ -3766,97 +3906,158 @@ async function handleFindUnique(args, query, conditions, scopes, operation, log,
3766
3906
  }
3767
3907
 
3768
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
3769
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
+ }
3770
4031
 
3771
4032
  // src/runtime/model-guard-data.ts
3772
- import { z as z8 } from "zod";
3773
- var ALLOWED_BODY_KEYS_CREATE = /* @__PURE__ */ new Set(["data"]);
3774
- var ALLOWED_BODY_KEYS_CREATE_PROJECTION = /* @__PURE__ */ new Set([
3775
- "data",
3776
- "select",
3777
- "include"
3778
- ]);
3779
- var ALLOWED_BODY_KEYS_CREATE_MANY = /* @__PURE__ */ new Set([
3780
- "data",
3781
- "skipDuplicates"
3782
- ]);
3783
- var ALLOWED_BODY_KEYS_CREATE_MANY_PROJECTION = /* @__PURE__ */ new Set([
3784
- "data",
3785
- "select",
3786
- "include",
3787
- "skipDuplicates"
3788
- ]);
3789
- var ALLOWED_BODY_KEYS_UPDATE = /* @__PURE__ */ new Set(["data", "where"]);
3790
- var ALLOWED_BODY_KEYS_UPDATE_PROJECTION = /* @__PURE__ */ new Set([
3791
- "data",
3792
- "where",
3793
- "select",
3794
- "include"
3795
- ]);
3796
- var ALLOWED_BODY_KEYS_DELETE = /* @__PURE__ */ new Set(["where"]);
3797
- var ALLOWED_BODY_KEYS_DELETE_PROJECTION = /* @__PURE__ */ new Set([
3798
- "where",
3799
- "select",
3800
- "include"
3801
- ]);
3802
- var ALLOWED_BODY_KEYS_UPSERT = /* @__PURE__ */ new Set([
3803
- "where",
3804
- "create",
3805
- "update",
3806
- "select",
3807
- "include"
3808
- ]);
3809
- var VALID_SHAPE_KEYS_CREATE = /* @__PURE__ */ new Set(["data"]);
3810
- var VALID_SHAPE_KEYS_CREATE_PROJECTION = /* @__PURE__ */ new Set([
3811
- "data",
3812
- "select",
3813
- "include"
3814
- ]);
3815
- var VALID_SHAPE_KEYS_UPDATE = /* @__PURE__ */ new Set(["data", "where"]);
3816
- var VALID_SHAPE_KEYS_UPDATE_PROJECTION = /* @__PURE__ */ new Set([
3817
- "data",
3818
- "where",
3819
- "select",
3820
- "include"
3821
- ]);
3822
- var VALID_SHAPE_KEYS_DELETE = /* @__PURE__ */ new Set(["where"]);
3823
- var VALID_SHAPE_KEYS_DELETE_PROJECTION = /* @__PURE__ */ new Set([
3824
- "where",
3825
- "select",
3826
- "include"
3827
- ]);
3828
- var VALID_SHAPE_KEYS_UPSERT = /* @__PURE__ */ new Set([
3829
- "where",
3830
- "create",
3831
- "update",
3832
- "select",
3833
- "include"
3834
- ]);
3835
- var KNOWN_RELATION_WRITE_OPS = /* @__PURE__ */ new Set([
3836
- "connect",
3837
- "connectOrCreate",
3838
- "create",
3839
- "createMany",
3840
- "disconnect",
3841
- "delete",
3842
- "set",
3843
- "update",
3844
- "updateMany",
3845
- "upsert",
3846
- "deleteMany"
3847
- ]);
3848
- function validateMutationBodyKeys(body, allowed, method) {
3849
- 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)) {
3850
4046
  if (!allowed.has(key)) {
3851
4047
  throw new ShapeError(
3852
- `Unexpected key "${key}" in ${method} body. Allowed keys: ${[...allowed].join(", ")}`
4048
+ `Unknown key "${key}" in ${opLabel} config on "${model}.${field}". Allowed: ${[...allowed].join(", ")}`
3853
4049
  );
3854
4050
  }
3855
4051
  }
3856
4052
  }
3857
- function validateMutationShapeKeys(shape, allowed, method) {
3858
- for (const key of Object.keys(shape)) {
4053
+ function validateAllowedKeys(value, allowed, method, kind) {
4054
+ for (const key of Object.keys(value)) {
3859
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
+ }
3860
4061
  throw new ShapeError(
3861
4062
  `Shape key "${key}" not valid for ${method}. Allowed: ${[...allowed].join(", ")}`
3862
4063
  );
@@ -3898,24 +4099,24 @@ function buildWhereFieldsSchema(model, config, typeMap, schemaBuilder) {
3898
4099
  for (const [fieldName, value] of Object.entries(config)) {
3899
4100
  if (value !== true)
3900
4101
  throw new ShapeError(
3901
- `Field "${fieldName}" in connect/where config must be true`
4102
+ `Field "${fieldName}" in filter config must be true`
3902
4103
  );
3903
4104
  const meta = modelFields[fieldName];
3904
4105
  if (!meta)
3905
4106
  throw new ShapeError(`Unknown field "${fieldName}" on model "${model}"`);
3906
4107
  if (meta.isRelation)
3907
4108
  throw new ShapeError(
3908
- `Relation field "${fieldName}" cannot be used in connect/where`
4109
+ `Relation field "${fieldName}" cannot be used in filter`
3909
4110
  );
3910
4111
  fieldSchemas[fieldName] = schemaBuilder.buildFieldSchema(model, fieldName).optional();
3911
4112
  fieldKeys.push(fieldName);
3912
4113
  }
3913
- return z8.object(fieldSchemas).strict().refine(
4114
+ return z10.object(fieldSchemas).strict().refine(
3914
4115
  (v) => fieldKeys.some((k) => v[k] !== void 0),
3915
- { message: `At least one field required in connect/where` }
4116
+ { message: `At least one field required in filter` }
3916
4117
  );
3917
4118
  }
3918
- function buildNestedDataSchema(model, config, typeMap, schemaBuilder) {
4119
+ function buildNestedDataSchema(model, config, mode, typeMap, schemaBuilder) {
3919
4120
  const modelFields = typeMap[model];
3920
4121
  if (!modelFields)
3921
4122
  throw new ShapeError(`Unknown model: ${model}`);
@@ -3936,382 +4137,349 @@ function buildNestedDataSchema(model, config, typeMap, schemaBuilder) {
3936
4137
  throw new ShapeError(
3937
4138
  `updatedAt field "${fieldName}" cannot be used in nested data`
3938
4139
  );
3939
- let fieldSchema = schemaBuilder.buildFieldSchema(model, fieldName);
3940
- if (!meta.isRequired) {
3941
- fieldSchema = fieldSchema.nullable().optional();
3942
- } else if (meta.hasDefault) {
3943
- fieldSchema = fieldSchema.optional();
3944
- }
3945
- 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
+ });
3946
4149
  }
3947
- return z8.object(fieldSchemas).strict();
4150
+ return z10.object(fieldSchemas).strict();
3948
4151
  }
3949
- function buildRelationWriteSchema(model, fieldName, relatedModelName, isList, config, typeMap, schemaBuilder) {
3950
- const relatedFields = typeMap[relatedModelName];
3951
- 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) {
3952
4224
  throw new ShapeError(
3953
- `Unknown related model "${relatedModelName}" for field "${model}.${fieldName}"`
4225
+ `createMany is only valid on to-many relations ("${ctx.model}.${ctx.fieldName}")`
3954
4226
  );
3955
- for (const key of Object.keys(config)) {
3956
- if (!KNOWN_RELATION_WRITE_OPS.has(key)) {
3957
- throw new ShapeError(
3958
- `Unknown relation write operation "${key}" on "${model}.${fieldName}". Allowed: ${[...KNOWN_RELATION_WRITE_OPS].join(", ")}`
3959
- );
3960
- }
3961
4227
  }
3962
- const opSchemas = {};
3963
- if (config.connect !== void 0) {
3964
- 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) {
3965
4250
  throw new ShapeError(
3966
- `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`
3967
4252
  );
3968
4253
  }
3969
- const connectSchema = buildWhereFieldsSchema(
3970
- relatedModelName,
3971
- config.connect,
3972
- typeMap,
3973
- 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`
3974
4259
  );
3975
- opSchemas["connect"] = isList ? z8.union([
3976
- connectSchema,
3977
- z8.preprocess(coerceToArray, z8.array(connectSchema))
3978
- ]).optional() : connectSchema.optional();
3979
4260
  }
3980
- if (config.connectOrCreate !== void 0) {
3981
- if (!isPlainObject(config.connectOrCreate)) {
3982
- throw new ShapeError(
3983
- `connectOrCreate config on "${model}.${fieldName}" must be an object with "where" and "create"`
3984
- );
3985
- }
3986
- const coc = config.connectOrCreate;
3987
- if (!coc.where || !isPlainObject(coc.where)) {
3988
- throw new ShapeError(
3989
- `connectOrCreate on "${model}.${fieldName}" requires "where" object`
3990
- );
3991
- }
3992
- 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) {
3993
4269
  throw new ShapeError(
3994
- `connectOrCreate on "${model}.${fieldName}" requires "create" object`
4270
+ `delete on to-many relation "${ctx.model}.${ctx.fieldName}" requires unique selector config, not true`
3995
4271
  );
3996
4272
  }
3997
- const whereSchema = buildWhereFieldsSchema(
3998
- relatedModelName,
3999
- coc.where,
4000
- typeMap,
4001
- schemaBuilder
4002
- );
4003
- const createSchema = buildNestedDataSchema(
4004
- relatedModelName,
4005
- coc.create,
4006
- typeMap,
4007
- 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`
4008
4278
  );
4009
- const cocSchema = z8.object({ where: whereSchema, create: createSchema }).strict();
4010
- opSchemas["connectOrCreate"] = isList ? z8.union([cocSchema, z8.preprocess(coerceToArray, z8.array(cocSchema))]).optional() : cocSchema.optional();
4011
4279
  }
4012
- if (config.create !== void 0) {
4013
- if (!isPlainObject(config.create)) {
4014
- throw new ShapeError(
4015
- `create config on "${model}.${fieldName}" must be an object of field names`
4016
- );
4017
- }
4018
- const createSchema = buildNestedDataSchema(
4019
- relatedModelName,
4020
- config.create,
4021
- typeMap,
4022
- 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}")`
4023
4289
  );
4024
- opSchemas["create"] = isList ? z8.union([
4025
- createSchema,
4026
- z8.preprocess(coerceToArray, z8.array(createSchema))
4027
- ]).optional() : createSchema.optional();
4028
4290
  }
4029
- if (config.createMany !== void 0) {
4030
- if (!isList) {
4031
- throw new ShapeError(
4032
- `createMany is only valid on to-many relations ("${model}.${fieldName}")`
4033
- );
4034
- }
4035
- if (!isPlainObject(config.createMany)) {
4036
- throw new ShapeError(
4037
- `createMany config on "${model}.${fieldName}" must be an object`
4038
- );
4039
- }
4040
- const cmConfig = config.createMany;
4041
- if (!cmConfig.data || !isPlainObject(cmConfig.data)) {
4042
- throw new ShapeError(
4043
- `createMany on "${model}.${fieldName}" requires "data" object`
4044
- );
4045
- }
4046
- const dataSchema = buildNestedDataSchema(
4047
- relatedModelName,
4048
- cmConfig.data,
4049
- typeMap,
4050
- 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`
4051
4309
  );
4052
- const cmSchemaFields = {
4053
- data: z8.preprocess(coerceToArray, z8.array(dataSchema))
4054
- };
4055
- if ("skipDuplicates" in cmConfig) {
4056
- cmSchemaFields["skipDuplicates"] = z8.boolean().optional();
4057
- }
4058
- 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);
4059
4319
  }
4060
- if (config.disconnect !== void 0) {
4061
- if (config.disconnect === true) {
4062
- if (isList) {
4063
- throw new ShapeError(
4064
- `disconnect on to-many relation "${model}.${fieldName}" requires field config, not true`
4065
- );
4066
- }
4067
- opSchemas["disconnect"] = z8.literal(true).optional();
4068
- } else if (isPlainObject(config.disconnect)) {
4069
- const disconnectSchema = buildWhereFieldsSchema(
4070
- relatedModelName,
4071
- config.disconnect,
4072
- typeMap,
4073
- schemaBuilder
4074
- );
4075
- if (isList) {
4076
- opSchemas["disconnect"] = z8.union([
4077
- disconnectSchema,
4078
- z8.preprocess(coerceToArray, z8.array(disconnectSchema))
4079
- ]).optional();
4080
- } else {
4081
- opSchemas["disconnect"] = z8.union([z8.literal(true), disconnectSchema]).optional();
4082
- }
4083
- } else {
4084
- throw new ShapeError(
4085
- `disconnect config on "${model}.${fieldName}" must be true (to-one) or an object of field names`
4086
- );
4087
- }
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);
4088
4356
  }
4089
- if (config.delete !== void 0) {
4090
- if (config.delete === true) {
4091
- if (isList) {
4092
- throw new ShapeError(
4093
- `delete on to-many relation "${model}.${fieldName}" requires field config, not true`
4094
- );
4095
- }
4096
- opSchemas["delete"] = z8.literal(true).optional();
4097
- } else if (isPlainObject(config.delete)) {
4098
- const deleteSchema = buildWhereFieldsSchema(
4099
- relatedModelName,
4100
- config.delete,
4101
- typeMap,
4102
- schemaBuilder
4103
- );
4104
- if (isList) {
4105
- opSchemas["delete"] = z8.union([
4106
- deleteSchema,
4107
- z8.preprocess(coerceToArray, z8.array(deleteSchema))
4108
- ]).optional();
4109
- } else {
4110
- opSchemas["delete"] = z8.union([z8.literal(true), deleteSchema]).optional();
4111
- }
4112
- } else {
4357
+ const hasWhereKey = "where" in cfg;
4358
+ if (hasWhereKey) {
4359
+ if (!isPlainObject(cfg.where)) {
4113
4360
  throw new ShapeError(
4114
- `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`
4115
4362
  );
4116
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();
4117
4367
  }
4118
- if (config.set !== void 0) {
4119
- if (!isList) {
4120
- throw new ShapeError(
4121
- `set is only valid on to-many relations ("${model}.${fieldName}")`
4122
- );
4123
- }
4124
- if (!isPlainObject(config.set)) {
4125
- throw new ShapeError(
4126
- `set config on "${model}.${fieldName}" must be an object of field names`
4127
- );
4128
- }
4129
- const setSchema = buildWhereFieldsSchema(
4130
- relatedModelName,
4131
- config.set,
4132
- typeMap,
4133
- 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}")`
4134
4375
  );
4135
- opSchemas["set"] = z8.preprocess(coerceToArray, z8.array(setSchema)).optional();
4136
- }
4137
- if (config.update !== void 0) {
4138
- if (!isPlainObject(config.update)) {
4139
- throw new ShapeError(
4140
- `update config on "${model}.${fieldName}" must be an object`
4141
- );
4142
- }
4143
- const updateConfig = config.update;
4144
- if (isList) {
4145
- if (!updateConfig.where || !isPlainObject(updateConfig.where)) {
4146
- throw new ShapeError(
4147
- `update on to-many "${model}.${fieldName}" requires "where" object`
4148
- );
4149
- }
4150
- if (!updateConfig.data || !isPlainObject(updateConfig.data)) {
4151
- throw new ShapeError(
4152
- `update on to-many "${model}.${fieldName}" requires "data" object`
4153
- );
4154
- }
4155
- const whereSchema = buildWhereFieldsSchema(
4156
- relatedModelName,
4157
- updateConfig.where,
4158
- typeMap,
4159
- schemaBuilder
4160
- );
4161
- const dataSchema = buildNestedDataSchema(
4162
- relatedModelName,
4163
- updateConfig.data,
4164
- typeMap,
4165
- schemaBuilder
4166
- );
4167
- const updateSchema = z8.object({ where: whereSchema, data: dataSchema }).strict();
4168
- opSchemas["update"] = z8.union([
4169
- updateSchema,
4170
- z8.preprocess(coerceToArray, z8.array(updateSchema))
4171
- ]).optional();
4172
- } else {
4173
- const dataSchema = buildNestedDataSchema(
4174
- relatedModelName,
4175
- updateConfig,
4176
- typeMap,
4177
- schemaBuilder
4178
- );
4179
- opSchemas["update"] = dataSchema.optional();
4180
- }
4181
4376
  }
4182
- if (config.upsert !== void 0) {
4183
- if (!isPlainObject(config.upsert)) {
4184
- throw new ShapeError(
4185
- `upsert config on "${model}.${fieldName}" must be an object`
4186
- );
4187
- }
4188
- const upsertConfig = config.upsert;
4189
- if (!upsertConfig.create || !isPlainObject(upsertConfig.create)) {
4190
- throw new ShapeError(
4191
- `upsert on "${model}.${fieldName}" requires "create" object`
4192
- );
4193
- }
4194
- if (!upsertConfig.update || !isPlainObject(upsertConfig.update)) {
4195
- throw new ShapeError(
4196
- `upsert on "${model}.${fieldName}" requires "update" object`
4197
- );
4198
- }
4199
- const createSchema = buildNestedDataSchema(
4200
- relatedModelName,
4201
- upsertConfig.create,
4202
- typeMap,
4203
- 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`
4204
4390
  );
4205
- const updateSchema = buildNestedDataSchema(
4206
- relatedModelName,
4207
- upsertConfig.update,
4208
- typeMap,
4209
- 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`
4210
4400
  );
4211
- if (isList) {
4212
- if (!upsertConfig.where || !isPlainObject(upsertConfig.where)) {
4213
- throw new ShapeError(
4214
- `upsert on to-many "${model}.${fieldName}" requires "where" object`
4215
- );
4216
- }
4217
- const whereSchema = buildWhereFieldsSchema(
4218
- relatedModelName,
4219
- upsertConfig.where,
4220
- typeMap,
4221
- schemaBuilder
4222
- );
4223
- const upsertSchema = z8.object({
4224
- where: whereSchema,
4225
- create: createSchema,
4226
- update: updateSchema
4227
- }).strict();
4228
- opSchemas["upsert"] = z8.union([
4229
- upsertSchema,
4230
- z8.preprocess(coerceToArray, z8.array(upsertSchema))
4231
- ]).optional();
4232
- } else {
4233
- if (upsertConfig.where) {
4234
- const whereSchema = buildWhereFieldsSchema(
4235
- relatedModelName,
4236
- upsertConfig.where,
4237
- typeMap,
4238
- schemaBuilder
4239
- );
4240
- const upsertSchema = z8.object({
4241
- where: whereSchema,
4242
- create: createSchema,
4243
- update: updateSchema
4244
- }).strict();
4245
- opSchemas["upsert"] = upsertSchema.optional();
4246
- } else {
4247
- const upsertSchema = z8.object({ create: createSchema, update: updateSchema }).strict();
4248
- opSchemas["upsert"] = upsertSchema.optional();
4249
- }
4250
- }
4251
4401
  }
4252
- if (config.updateMany !== void 0) {
4253
- if (!isList) {
4254
- throw new ShapeError(
4255
- `updateMany is only valid on to-many relations ("${model}.${fieldName}")`
4256
- );
4257
- }
4258
- if (!isPlainObject(config.updateMany)) {
4259
- throw new ShapeError(
4260
- `updateMany config on "${model}.${fieldName}" must be an object`
4261
- );
4262
- }
4263
- const umConfig = config.updateMany;
4264
- if (!umConfig.where || !isPlainObject(umConfig.where)) {
4265
- throw new ShapeError(
4266
- `updateMany on "${model}.${fieldName}" requires "where" object`
4267
- );
4268
- }
4269
- if (!umConfig.data || !isPlainObject(umConfig.data)) {
4270
- throw new ShapeError(
4271
- `updateMany on "${model}.${fieldName}" requires "data" object`
4272
- );
4273
- }
4274
- const whereSchema = buildWhereFieldsSchema(
4275
- relatedModelName,
4276
- umConfig.where,
4277
- typeMap,
4278
- 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}")`
4279
4416
  );
4280
- const dataSchema = buildNestedDataSchema(
4281
- relatedModelName,
4282
- umConfig.data,
4283
- typeMap,
4284
- 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.`
4285
4425
  );
4286
- const umSchema = z8.object({ where: whereSchema, data: dataSchema }).strict();
4287
- opSchemas["updateMany"] = z8.union([umSchema, z8.preprocess(coerceToArray, z8.array(umSchema))]).optional();
4288
4426
  }
4289
- if (config.deleteMany !== void 0) {
4290
- if (!isList) {
4291
- throw new ShapeError(
4292
- `deleteMany is only valid on to-many relations ("${model}.${fieldName}")`
4293
- );
4294
- }
4295
- 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)) {
4296
4457
  throw new ShapeError(
4297
- `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(", ")}`
4298
4459
  );
4299
4460
  }
4300
- 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,
4301
4470
  relatedModelName,
4302
- config.deleteMany,
4471
+ isList,
4472
+ config: opConfig,
4303
4473
  typeMap,
4474
+ uniqueMap,
4475
+ enumMap,
4476
+ scalarBase,
4304
4477
  schemaBuilder
4305
- );
4306
- opSchemas["deleteMany"] = z8.union([
4307
- filterSchema,
4308
- z8.preprocess(coerceToArray, z8.array(filterSchema)),
4309
- z8.object({}).strict()
4310
- ]).optional();
4478
+ });
4311
4479
  }
4312
- return z8.object(opSchemas).strict();
4480
+ return z10.object(opSchemas).strict();
4313
4481
  }
4314
- function buildDataSchema(model, dataConfig, mode, typeMap, schemaBuilder, zodDefaults) {
4482
+ function buildDataSchema(model, dataConfig, mode, typeMap, uniqueMap, enumMap, scalarBase, schemaBuilder, zodDefaults) {
4315
4483
  const modelFields = typeMap[model];
4316
4484
  if (!modelFields)
4317
4485
  throw new ShapeError(`Unknown model: ${model}`);
@@ -4323,11 +4491,23 @@ function buildDataSchema(model, dataConfig, mode, typeMap, schemaBuilder, zodDef
4323
4491
  const fieldMeta = modelFields[fieldName];
4324
4492
  if (!fieldMeta) {
4325
4493
  if (isUnsupportedMarker(value)) {
4326
- schemaMap[fieldName] = z8.unknown().optional();
4327
4494
  continue;
4328
4495
  }
4329
4496
  throw new ShapeError(`Unknown field "${fieldName}" on model "${model}"`);
4330
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
+ }
4331
4511
  if (fieldMeta.isRelation) {
4332
4512
  if (!isPlainObject(value)) {
4333
4513
  throw new ShapeError(
@@ -4341,6 +4521,9 @@ function buildDataSchema(model, dataConfig, mode, typeMap, schemaBuilder, zodDef
4341
4521
  fieldMeta.isList,
4342
4522
  value,
4343
4523
  typeMap,
4524
+ uniqueMap,
4525
+ enumMap,
4526
+ scalarBase,
4344
4527
  schemaBuilder
4345
4528
  ).optional();
4346
4529
  continue;
@@ -4350,7 +4533,7 @@ function buildDataSchema(model, dataConfig, mode, typeMap, schemaBuilder, zodDef
4350
4533
  `updatedAt field "${fieldName}" cannot be used in data shape`
4351
4534
  );
4352
4535
  if (typeof value === "function") {
4353
- let baseSchema = schemaBuilder.buildBaseFieldSchema(
4536
+ const baseSchema = schemaBuilder.buildBaseFieldSchema(
4354
4537
  model,
4355
4538
  fieldName
4356
4539
  );
@@ -4368,46 +4551,22 @@ function buildDataSchema(model, dataConfig, mode, typeMap, schemaBuilder, zodDef
4368
4551
  `Inline refine for "${model}.${fieldName}" must return a Zod schema`
4369
4552
  );
4370
4553
  }
4371
- let fieldSchema = refined;
4372
- const handlesUndefined = schemaProducesValueForUndefined(fieldSchema);
4373
- if (mode === "create") {
4374
- if (!fieldMeta.isRequired) {
4375
- fieldSchema = handlesUndefined ? fieldSchema.nullable() : fieldSchema.nullable().optional();
4376
- } else if (fieldMeta.hasDefault) {
4377
- if (!handlesUndefined) {
4378
- fieldSchema = fieldSchema.optional();
4379
- }
4380
- }
4381
- } else {
4382
- if (!fieldMeta.isRequired) {
4383
- fieldSchema = fieldSchema.nullable().optional();
4384
- } else {
4385
- fieldSchema = fieldSchema.optional();
4386
- }
4387
- }
4388
- schemaMap[fieldName] = fieldSchema;
4389
- } else if (value === true) {
4390
- let fieldSchema = schemaBuilder.buildFieldSchema(
4391
- model,
4392
- fieldName
4554
+ const handlesUndefined = schemaProducesValueForUndefined(
4555
+ refined
4556
+ );
4557
+ schemaMap[fieldName] = applyCreateUpdateNullability(
4558
+ fieldMeta,
4559
+ refined,
4560
+ { mode, handlesUndefined }
4393
4561
  );
4562
+ } else if (value === true) {
4563
+ const fieldSchema = schemaBuilder.buildFieldSchema(model, fieldName);
4394
4564
  const isZodDefaultField = zodDefaultSet !== void 0 && zodDefaultSet.has(fieldName);
4395
- if (mode === "create") {
4396
- if (!fieldMeta.isRequired) {
4397
- fieldSchema = isZodDefaultField ? fieldSchema.nullable() : fieldSchema.nullable().optional();
4398
- } else if (fieldMeta.hasDefault) {
4399
- if (!isZodDefaultField) {
4400
- fieldSchema = fieldSchema.optional();
4401
- }
4402
- }
4403
- } else {
4404
- if (!fieldMeta.isRequired) {
4405
- fieldSchema = fieldSchema.nullable().optional();
4406
- } else {
4407
- fieldSchema = fieldSchema.optional();
4408
- }
4409
- }
4410
- schemaMap[fieldName] = fieldSchema;
4565
+ schemaMap[fieldName] = applyCreateUpdateNullability(
4566
+ fieldMeta,
4567
+ fieldSchema,
4568
+ { mode, handlesUndefined: isZodDefaultField }
4569
+ );
4411
4570
  } else {
4412
4571
  const actualValue = isForcedValue(value) ? value.value : value;
4413
4572
  let fieldSchema = schemaBuilder.buildFieldSchema(
@@ -4451,7 +4610,7 @@ function buildDataSchema(model, dataConfig, mode, typeMap, schemaBuilder, zodDef
4451
4610
  }
4452
4611
  }
4453
4612
  return {
4454
- schema: z8.object(schemaMap).strict(),
4613
+ schema: z10.object(schemaMap).strict(),
4455
4614
  forced
4456
4615
  };
4457
4616
  }
@@ -4488,106 +4647,120 @@ function isGuardShape(obj) {
4488
4647
  const keys = Object.keys(obj);
4489
4648
  return keys.length === 0 || keys.every((k) => GUARD_SHAPE_KEYS.has(k));
4490
4649
  }
4491
- function isSingleShape(input) {
4492
- return typeof input === "function" || isGuardShape(input);
4493
- }
4494
- function toPlainObject(value) {
4495
- if (value === null || typeof value !== "object")
4496
- return value;
4497
- if (Array.isArray(value))
4498
- return value.map(toPlainObject);
4499
- if (value instanceof Date)
4500
- return value;
4501
- if (value instanceof Uint8Array)
4502
- return value;
4503
- if (value instanceof RegExp)
4504
- return value;
4505
- if (typeof value.toFixed === "function" && typeof value.toNumber === "function")
4506
- return value;
4507
- const result = {};
4508
- for (const [k, v] of Object.entries(value)) {
4509
- 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");
4510
4655
  }
4511
- return result;
4656
+ return body;
4512
4657
  }
4513
- function requireBody(body) {
4514
- const normalized = toPlainObject(body);
4515
- if (!isPlainObject(normalized))
4516
- throw new ShapeError("Request body must be an object");
4517
- 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
+ }
4518
4664
  }
4519
- function resolveDynamicShape(fn, contextFn) {
4520
- 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
+ }
4521
4671
  let result;
4522
4672
  try {
4523
- result = fn(ctx);
4673
+ result = shapeFn(ctx);
4524
4674
  } catch (err) {
4525
4675
  throw new ShapeError(
4526
- `Dynamic shape function threw: ${err.message}`,
4676
+ `Dynamic ${context} function threw: ${err.message}`,
4527
4677
  { cause: err }
4528
4678
  );
4529
4679
  }
4530
- if (!isPlainObject(result)) {
4531
- 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
+ );
4532
4684
  }
4533
4685
  return result;
4534
4686
  }
4535
- function resolveShape(input, body, contextFn, caller) {
4536
- if (isSingleShape(input)) {
4537
- const wasDynamic2 = typeof input === "function";
4538
- const shape2 = wasDynamic2 ? resolveDynamicShape(input, contextFn) : input;
4539
- const parsed2 = body === void 0 || body === null ? {} : requireBody(body);
4540
- return { shape: shape2, body: parsed2, matchedKey: "_default", wasDynamic: wasDynamic2 };
4541
- }
4542
- const namedMap = input;
4543
- 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) {
4544
4692
  if (GUARD_SHAPE_KEYS.has(key)) {
4545
4693
  throw new ShapeError(
4546
- `Caller key "${key}" collides with reserved shape config key. Rename the caller path.`
4547
- );
4548
- }
4549
- const val = namedMap[key];
4550
- if (typeof val !== "function" && !isGuardShape(val)) {
4551
- throw new ShapeError(
4552
- `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.`
4553
4695
  );
4554
4696
  }
4555
4697
  }
4556
- const parsed = body === void 0 || body === null ? {} : requireBody(body);
4557
- if ("caller" in parsed) {
4558
- throw new CallerError(
4559
- "Pass caller as second argument to .guard() or via context function, not in the request body."
4560
- );
4561
- }
4562
4698
  if (typeof caller !== "string") {
4563
- if ("default" in namedMap) {
4564
- const shapeOrFn2 = namedMap["default"];
4565
- const wasDynamic2 = typeof shapeOrFn2 === "function";
4566
- const shape2 = wasDynamic2 ? resolveDynamicShape(shapeOrFn2, contextFn) : shapeOrFn2;
4567
- return { shape: shape2, body: parsed, matchedKey: "default", wasDynamic: wasDynamic2 };
4699
+ if ("default" in input) {
4700
+ return resolveShapeEntry(input.default, body, contextFn, "default");
4568
4701
  }
4569
- const patterns2 = Object.keys(namedMap);
4570
4702
  throw new CallerError(
4571
- `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).`
4572
4704
  );
4573
4705
  }
4574
- const patterns = Object.keys(namedMap);
4575
- const matched = matchCallerPattern(patterns, caller);
4576
- if (!matched) {
4577
- if ("default" in namedMap) {
4578
- const shapeOrFn2 = namedMap["default"];
4579
- const wasDynamic2 = typeof shapeOrFn2 === "function";
4580
- const shape2 = wasDynamic2 ? resolveDynamicShape(shapeOrFn2, contextFn) : shapeOrFn2;
4581
- return { shape: shape2, body: parsed, matchedKey: "default", wasDynamic: wasDynamic2 };
4582
- }
4583
- throw new CallerError(
4584
- `Unknown caller: "${caller}". Allowed: ${patterns.map((k) => `"${k}"`).join(", ")}`
4585
- );
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
+ };
4586
4754
  }
4587
- const shapeOrFn = namedMap[matched];
4588
- const wasDynamic = typeof shapeOrFn === "function";
4589
- const shape = wasDynamic ? resolveDynamicShape(shapeOrFn, contextFn) : shapeOrFn;
4590
- 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
+ );
4591
4764
  }
4592
4765
 
4593
4766
  // src/runtime/model-guard.ts
@@ -4610,129 +4783,20 @@ var PROJECTION_MUTATION_METHODS = /* @__PURE__ */ new Set([
4610
4783
  "updateManyAndReturn"
4611
4784
  ]);
4612
4785
  var BATCH_CREATE_METHODS = /* @__PURE__ */ new Set(["createMany", "createManyAndReturn"]);
4613
- function buildDefaultSelectInput(config) {
4614
- const result = {};
4615
- for (const [key, value] of Object.entries(config)) {
4616
- if (key === "_count") {
4617
- result[key] = buildDefaultCountInput(
4618
- value
4619
- );
4620
- continue;
4621
- }
4622
- if (value === true) {
4623
- result[key] = true;
4624
- } else {
4625
- const nested = {};
4626
- if (value.select)
4627
- nested.select = buildDefaultSelectInput(value.select);
4628
- if (value.include) {
4629
- nested.include = buildDefaultIncludeInput(value.include);
4630
- }
4631
- result[key] = Object.keys(nested).length > 0 ? nested : true;
4632
- }
4633
- }
4634
- return result;
4635
- }
4636
- function buildDefaultIncludeInput(config) {
4637
- const result = {};
4638
- for (const [key, value] of Object.entries(config)) {
4639
- if (key === "_count") {
4640
- result[key] = buildDefaultCountInput(
4641
- value
4642
- );
4643
- continue;
4644
- }
4645
- if (value === true) {
4646
- result[key] = true;
4647
- } else {
4648
- const nested = {};
4649
- if (value.include) {
4650
- nested.include = buildDefaultIncludeInput(value.include);
4651
- }
4652
- if (value.select)
4653
- nested.select = buildDefaultSelectInput(value.select);
4654
- result[key] = Object.keys(nested).length > 0 ? nested : true;
4655
- }
4656
- }
4657
- return result;
4658
- }
4659
- function buildDefaultCountInput(config) {
4660
- if (config === true)
4661
- return true;
4662
- if (!isPlainObject(config) || !config.select || !isPlainObject(config.select)) {
4663
- return true;
4664
- }
4665
- const selectObj = config.select;
4666
- const result = {};
4667
- for (const key of Object.keys(selectObj)) {
4668
- result[key] = true;
4669
- }
4670
- return { select: result };
4671
- }
4672
- function buildDefaultProjectionBody(shape) {
4673
- if (shape.select) {
4674
- return { select: buildDefaultSelectInput(shape.select) };
4675
- }
4676
- if (shape.include) {
4677
- return { include: buildDefaultIncludeInput(shape.include) };
4678
- }
4679
- return {};
4680
- }
4681
- function applyClientProjectionOverrides(shapeDefault, clientProjection) {
4682
- const result = { ...shapeDefault };
4683
- for (const [key, clientValue] of Object.entries(clientProjection)) {
4684
- const defaultValue = result[key];
4685
- if (defaultValue === void 0) {
4686
- result[key] = clientValue;
4687
- continue;
4688
- }
4689
- if (clientValue === true) {
4690
- result[key] = true;
4691
- continue;
4692
- }
4693
- if (isPlainObject(clientValue)) {
4694
- if (!isPlainObject(defaultValue)) {
4695
- result[key] = clientValue;
4696
- continue;
4697
- }
4698
- const merged = { ...defaultValue };
4699
- const clientObj = clientValue;
4700
- for (const [argKey, argValue] of Object.entries(clientObj)) {
4701
- const defaultArgValue = merged[argKey];
4702
- if ((argKey === "select" || argKey === "include") && isPlainObject(argValue) && isPlainObject(defaultArgValue)) {
4703
- merged[argKey] = applyClientProjectionOverrides(
4704
- defaultArgValue,
4705
- argValue
4706
- );
4707
- } else {
4708
- merged[argKey] = argValue;
4709
- }
4710
- }
4711
- result[key] = merged;
4712
- }
4713
- }
4714
- return result;
4715
- }
4716
- function hasClientControlledValues(obj) {
4717
- for (const value of Object.values(obj)) {
4718
- if (isForcedValue(value))
4719
- continue;
4720
- if (value === true)
4721
- return true;
4722
- 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))
4723
4792
  return true;
4724
- }
4725
- return false;
4726
- }
4727
- function checkIncludeForClientArgs(config) {
4728
- for (const [key, value] of Object.entries(config)) {
4729
4793
  if (key === "_count") {
4730
4794
  if (value !== true && isPlainObject(value) && isPlainObject(value.select)) {
4731
4795
  const selectObj = value.select;
4732
4796
  for (const entryVal of Object.values(selectObj)) {
4733
4797
  if (isPlainObject(entryVal) && entryVal.where) {
4734
4798
  const w = entryVal.where;
4735
- if (isPlainObject(w) && hasClientControlledValues(w))
4799
+ if (isPlainObject(w) && hasClientControlledValues(w, depth + 1))
4736
4800
  return true;
4737
4801
  }
4738
4802
  }
@@ -4741,54 +4805,41 @@ function checkIncludeForClientArgs(config) {
4741
4805
  }
4742
4806
  if (value === true)
4743
4807
  continue;
4744
- if (value.orderBy || value.cursor || value.take || value.skip)
4808
+ const nested = value;
4809
+ if (nested.orderBy || nested.cursor || nested.take || nested.skip)
4745
4810
  return true;
4746
- if (value.where && isPlainObject(value.where) && hasClientControlledValues(value.where)) {
4811
+ if (nested.where && isPlainObject(nested.where) && hasClientControlledValues(nested.where, depth + 1)) {
4747
4812
  return true;
4748
4813
  }
4749
- if (value.include && checkIncludeForClientArgs(value.include))
4814
+ if (nested.include && walkForClientContent(nested.include, predicate, depth + 1))
4750
4815
  return true;
4751
- if (value.select && checkSelectForClientArgs(value.select))
4816
+ if (nested.select && walkForClientContent(nested.select, predicate, depth + 1))
4752
4817
  return true;
4753
4818
  }
4754
4819
  return false;
4755
4820
  }
4756
- function checkSelectForClientArgs(config) {
4757
- for (const [key, value] of Object.entries(config)) {
4758
- if (key === "_count") {
4759
- if (value !== true && isPlainObject(value) && isPlainObject(value.select)) {
4760
- const selectObj = value.select;
4761
- for (const entryVal of Object.values(selectObj)) {
4762
- if (isPlainObject(entryVal) && entryVal.where) {
4763
- const w = entryVal.where;
4764
- if (isPlainObject(w) && hasClientControlledValues(w))
4765
- return true;
4766
- }
4767
- }
4768
- }
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))
4769
4826
  continue;
4770
- }
4771
4827
  if (value === true)
4772
- continue;
4773
- if (value.orderBy || value.cursor || value.take || value.skip)
4774
4828
  return true;
4775
- if (value.where && isPlainObject(value.where) && hasClientControlledValues(value.where)) {
4829
+ if (isPlainObject(value) && hasClientControlledValues(value, depth + 1)) {
4776
4830
  return true;
4777
4831
  }
4778
- if (value.select && checkSelectForClientArgs(value.select))
4779
- return true;
4780
- if (value.include && checkIncludeForClientArgs(value.include))
4781
- return true;
4782
4832
  }
4783
4833
  return false;
4784
4834
  }
4785
4835
  function hasNestedClientControlledArgs(shape) {
4836
+ const predicate = () => false;
4786
4837
  if (shape.include) {
4787
- if (checkIncludeForClientArgs(shape.include))
4838
+ if (walkForClientContent(shape.include, predicate, 0))
4788
4839
  return true;
4789
4840
  }
4790
4841
  if (shape.select) {
4791
- if (checkSelectForClientArgs(shape.select))
4842
+ if (walkForClientContent(shape.select, predicate, 0))
4792
4843
  return true;
4793
4844
  }
4794
4845
  return false;
@@ -4860,77 +4911,62 @@ function createModelGuardExtension(config) {
4860
4911
  const whereBuiltCache = /* @__PURE__ */ new Map();
4861
4912
  const projectionCache = /* @__PURE__ */ new Map();
4862
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
+ }
4863
4924
  function getReadShape(method, queryShape, matchedKey, wasDynamic) {
4864
- if (!wasDynamic) {
4865
- const cacheKey = `${method}\0${matchedKey}`;
4866
- const cached = readShapeCache.get(cacheKey);
4867
- if (cached)
4868
- return cached;
4869
- const built = queryBuilder.buildShapeZodSchema(
4925
+ return memoize(
4926
+ readShapeCache,
4927
+ `${method}\0${matchedKey}`,
4928
+ wasDynamic,
4929
+ () => queryBuilder.buildShapeZodSchema(
4870
4930
  modelName,
4871
4931
  method,
4872
4932
  queryShape
4873
- );
4874
- readShapeCache.set(cacheKey, built);
4875
- return built;
4876
- }
4877
- return queryBuilder.buildShapeZodSchema(
4878
- modelName,
4879
- method,
4880
- queryShape
4933
+ )
4881
4934
  );
4882
4935
  }
4883
4936
  function getDataSchema(mode, dataConfig, matchedKey, wasDynamic) {
4884
- if (!wasDynamic && !hasDataRefines(dataConfig)) {
4885
- const cacheKey = `${mode}\0${matchedKey}`;
4886
- const cached = dataSchemaCache.get(cacheKey);
4887
- if (cached)
4888
- return cached;
4889
- const built = buildDataSchema(
4937
+ const skipCache = wasDynamic || hasDataRefines(dataConfig);
4938
+ return memoize(
4939
+ dataSchemaCache,
4940
+ `${mode}\0${matchedKey}`,
4941
+ skipCache,
4942
+ () => buildDataSchema(
4890
4943
  modelName,
4891
4944
  dataConfig,
4892
4945
  mode,
4893
4946
  typeMap,
4947
+ uniqueMap,
4948
+ enumMap,
4949
+ scalarBase,
4894
4950
  schemaBuilder,
4895
4951
  zodDefaults
4896
- );
4897
- dataSchemaCache.set(cacheKey, built);
4898
- return built;
4899
- }
4900
- return buildDataSchema(
4901
- modelName,
4902
- dataConfig,
4903
- mode,
4904
- typeMap,
4905
- schemaBuilder,
4906
- zodDefaults
4952
+ )
4907
4953
  );
4908
4954
  }
4909
4955
  function getWhereBuilt(whereConfig, matchedKey, wasDynamic) {
4910
- if (!wasDynamic) {
4911
- const cached = whereBuiltCache.get(matchedKey);
4912
- if (cached)
4913
- return cached;
4914
- const built = queryBuilder.buildWhereSchema(modelName, whereConfig);
4915
- whereBuiltCache.set(matchedKey, built);
4916
- return built;
4917
- }
4918
- return queryBuilder.buildWhereSchema(modelName, whereConfig);
4956
+ return memoize(
4957
+ whereBuiltCache,
4958
+ matchedKey,
4959
+ wasDynamic,
4960
+ () => queryBuilder.buildWhereSchema(modelName, whereConfig)
4961
+ );
4919
4962
  }
4920
4963
  function getUniqueWhereBuilt(whereConfig, matchedKey, wasDynamic) {
4921
- if (!wasDynamic) {
4922
- const cacheKey = `unique\0${matchedKey}`;
4923
- const cached = uniqueWhereCache.get(cacheKey);
4924
- if (cached)
4925
- return cached;
4926
- const built = queryBuilder.buildUniqueWhereSchema(
4927
- modelName,
4928
- whereConfig
4929
- );
4930
- uniqueWhereCache.set(cacheKey, built);
4931
- return built;
4932
- }
4933
- return queryBuilder.buildUniqueWhereSchema(modelName, whereConfig);
4964
+ return memoize(
4965
+ uniqueWhereCache,
4966
+ `unique\0${matchedKey}`,
4967
+ wasDynamic,
4968
+ () => queryBuilder.buildUniqueWhereSchema(modelName, whereConfig)
4969
+ );
4934
4970
  }
4935
4971
  function buildProjectionSchema(shape) {
4936
4972
  const schemaFields = {};
@@ -4957,7 +4993,7 @@ function createModelGuardExtension(config) {
4957
4993
  forcedSelectCountWhere = result.forcedCountWhere;
4958
4994
  }
4959
4995
  return {
4960
- zodSchema: z9.object(schemaFields).strict(),
4996
+ zodSchema: z11.object(schemaFields).strict(),
4961
4997
  forcedIncludeTree,
4962
4998
  forcedSelectTree,
4963
4999
  forcedIncludeCountWhere,
@@ -4965,16 +5001,12 @@ function createModelGuardExtension(config) {
4965
5001
  };
4966
5002
  }
4967
5003
  function getProjection(shape, matchedKey, wasDynamic) {
4968
- if (!wasDynamic) {
4969
- const cacheKey = `projection\0${matchedKey}`;
4970
- const cached = projectionCache.get(cacheKey);
4971
- if (cached)
4972
- return cached;
4973
- const built = buildProjectionSchema(shape);
4974
- projectionCache.set(cacheKey, built);
4975
- return built;
4976
- }
4977
- return buildProjectionSchema(shape);
5004
+ return memoize(
5005
+ projectionCache,
5006
+ `projection\0${matchedKey}`,
5007
+ wasDynamic,
5008
+ () => buildProjectionSchema(shape)
5009
+ );
4978
5010
  }
4979
5011
  function resolveProjection(shape, parsed, method, matchedKey, wasDynamic) {
4980
5012
  const hasBodyProjection = "select" in parsed || "include" in parsed;
@@ -5168,24 +5200,11 @@ function createModelGuardExtension(config) {
5168
5200
  const hasShapeProjection = !!resolved.shape.select || !!resolved.shape.include;
5169
5201
  if (!hasShapeProjection)
5170
5202
  return resolved.body;
5171
- const defaultProjection = buildDefaultProjectionBody(resolved.shape);
5172
5203
  const hasBodyProjection = "select" in resolved.body || "include" in resolved.body;
5173
- if (!hasBodyProjection) {
5174
- return { ...resolved.body, ...defaultProjection };
5175
- }
5176
- const merged = { ...resolved.body };
5177
- if ("select" in resolved.body && "select" in defaultProjection && isPlainObject(resolved.body.select) && isPlainObject(defaultProjection.select)) {
5178
- merged.select = applyClientProjectionOverrides(
5179
- defaultProjection.select,
5180
- resolved.body.select
5181
- );
5182
- } else if ("include" in resolved.body && "include" in defaultProjection && isPlainObject(resolved.body.include) && isPlainObject(defaultProjection.include)) {
5183
- merged.include = applyClientProjectionOverrides(
5184
- defaultProjection.include,
5185
- resolved.body.include
5186
- );
5187
- }
5188
- return merged;
5204
+ if (hasBodyProjection)
5205
+ return resolved.body;
5206
+ const defaultProjection = buildDefaultProjectionBody(resolved.shape);
5207
+ return { ...resolved.body, ...defaultProjection };
5189
5208
  }
5190
5209
  function makeReadMethod(method) {
5191
5210
  return (body) => {
@@ -5218,29 +5237,21 @@ function createModelGuardExtension(config) {
5218
5237
  function makeCreateMethod(method) {
5219
5238
  const isBatch = BATCH_CREATE_METHODS.has(method);
5220
5239
  const supportsProjection = PROJECTION_MUTATION_METHODS.has(method);
5221
- let allowedBodyKeys;
5222
- if (isBatch && supportsProjection) {
5223
- allowedBodyKeys = ALLOWED_BODY_KEYS_CREATE_MANY_PROJECTION;
5224
- } else if (isBatch) {
5225
- allowedBodyKeys = ALLOWED_BODY_KEYS_CREATE_MANY;
5226
- } else if (supportsProjection) {
5227
- allowedBodyKeys = ALLOWED_BODY_KEYS_CREATE_PROJECTION;
5228
- } else {
5229
- allowedBodyKeys = ALLOWED_BODY_KEYS_CREATE;
5230
- }
5231
- const allowedShapeKeys = supportsProjection ? VALID_SHAPE_KEYS_CREATE_PROJECTION : VALID_SHAPE_KEYS_CREATE;
5240
+ const allowedBodyKeys = getAllowedBodyKeys(method, supportsProjection);
5241
+ const allowedShapeKeys = getAllowedShapeKeys(method, supportsProjection);
5232
5242
  return (body) => {
5233
5243
  const caller = resolveCaller();
5234
5244
  const resolved = resolveShape(input, body, contextFn, caller);
5235
5245
  if (!resolved.shape.data) {
5236
5246
  throw new ShapeError(`Guard shape requires "data" for ${method}`);
5237
5247
  }
5238
- validateMutationShapeKeys(
5248
+ validateAllowedKeys(
5239
5249
  resolved.shape,
5240
5250
  allowedShapeKeys,
5241
- method
5251
+ method,
5252
+ "shape"
5242
5253
  );
5243
- validateMutationBodyKeys(resolved.body, allowedBodyKeys, method);
5254
+ validateAllowedKeys(resolved.body, allowedBodyKeys, method, "body");
5244
5255
  const fks = modelScopeFks.get(modelName) ?? /* @__PURE__ */ new Set();
5245
5256
  validateCreateCompleteness(
5246
5257
  modelName,
@@ -5299,20 +5310,21 @@ function createModelGuardExtension(config) {
5299
5310
  const isUniqueWhere = method === "update";
5300
5311
  const isBulk = BULK_MUTATION_METHODS.has(method);
5301
5312
  const supportsProjection = PROJECTION_MUTATION_METHODS.has(method);
5302
- const allowedBodyKeys = supportsProjection ? ALLOWED_BODY_KEYS_UPDATE_PROJECTION : ALLOWED_BODY_KEYS_UPDATE;
5303
- const allowedShapeKeys = supportsProjection ? VALID_SHAPE_KEYS_UPDATE_PROJECTION : VALID_SHAPE_KEYS_UPDATE;
5313
+ const allowedBodyKeys = getAllowedBodyKeys(method, supportsProjection);
5314
+ const allowedShapeKeys = getAllowedShapeKeys(method, supportsProjection);
5304
5315
  return (body) => {
5305
5316
  const caller = resolveCaller();
5306
5317
  const resolved = resolveShape(input, body, contextFn, caller);
5307
5318
  if (!resolved.shape.data) {
5308
5319
  throw new ShapeError(`Guard shape requires "data" for ${method}`);
5309
5320
  }
5310
- validateMutationShapeKeys(
5321
+ validateAllowedKeys(
5311
5322
  resolved.shape,
5312
5323
  allowedShapeKeys,
5313
- method
5324
+ method,
5325
+ "shape"
5314
5326
  );
5315
- validateMutationBodyKeys(resolved.body, allowedBodyKeys, method);
5327
+ validateAllowedKeys(resolved.body, allowedBodyKeys, method, "body");
5316
5328
  if (isBulk && !resolved.shape.where) {
5317
5329
  throw new ShapeError(
5318
5330
  `Guard shape requires "where" for ${method} to prevent unconstrained bulk mutations`
@@ -5380,20 +5392,21 @@ function createModelGuardExtension(config) {
5380
5392
  const isUniqueWhere = method === "delete";
5381
5393
  const isBulk = BULK_MUTATION_METHODS.has(method);
5382
5394
  const supportsProjection = PROJECTION_MUTATION_METHODS.has(method);
5383
- const allowedBodyKeys = supportsProjection ? ALLOWED_BODY_KEYS_DELETE_PROJECTION : ALLOWED_BODY_KEYS_DELETE;
5384
- const allowedShapeKeys = supportsProjection ? VALID_SHAPE_KEYS_DELETE_PROJECTION : VALID_SHAPE_KEYS_DELETE;
5395
+ const allowedBodyKeys = getAllowedBodyKeys(method, supportsProjection);
5396
+ const allowedShapeKeys = getAllowedShapeKeys(method, supportsProjection);
5385
5397
  return (body) => {
5386
5398
  const caller = resolveCaller();
5387
5399
  const resolved = resolveShape(input, body, contextFn, caller);
5388
5400
  if (resolved.shape.data) {
5389
5401
  throw new ShapeError(`Guard shape "data" is not valid for ${method}`);
5390
5402
  }
5391
- validateMutationShapeKeys(
5403
+ validateAllowedKeys(
5392
5404
  resolved.shape,
5393
5405
  allowedShapeKeys,
5394
- method
5406
+ method,
5407
+ "shape"
5395
5408
  );
5396
- validateMutationBodyKeys(resolved.body, allowedBodyKeys, method);
5409
+ validateAllowedKeys(resolved.body, allowedBodyKeys, method, "body");
5397
5410
  if (isBulk && !resolved.shape.where) {
5398
5411
  throw new ShapeError(
5399
5412
  `Guard shape requires "where" for ${method} to prevent unconstrained bulk mutations`
@@ -5446,6 +5459,8 @@ function createModelGuardExtension(config) {
5446
5459
  };
5447
5460
  }
5448
5461
  function makeUpsertMethod() {
5462
+ const allowedBodyKeys = getAllowedBodyKeys("upsert", true);
5463
+ const allowedShapeKeys = getAllowedShapeKeys("upsert", true);
5449
5464
  return (body) => {
5450
5465
  const caller = resolveCaller();
5451
5466
  const resolved = resolveShape(input, body, contextFn, caller);
@@ -5463,15 +5478,17 @@ function createModelGuardExtension(config) {
5463
5478
  if (!resolved.shape.where) {
5464
5479
  throw new ShapeError('Guard shape requires "where" for upsert');
5465
5480
  }
5466
- validateMutationShapeKeys(
5481
+ validateAllowedKeys(
5467
5482
  resolved.shape,
5468
- VALID_SHAPE_KEYS_UPSERT,
5469
- "upsert"
5483
+ allowedShapeKeys,
5484
+ "upsert",
5485
+ "shape"
5470
5486
  );
5471
- validateMutationBodyKeys(
5487
+ validateAllowedKeys(
5472
5488
  resolved.body,
5473
- ALLOWED_BODY_KEYS_UPSERT,
5474
- "upsert"
5489
+ allowedBodyKeys,
5490
+ "upsert",
5491
+ "body"
5475
5492
  );
5476
5493
  validateUniqueWhereShapeConfig(
5477
5494
  modelName,
@@ -5561,12 +5578,7 @@ function createModelGuardExtension(config) {
5561
5578
  try {
5562
5579
  return fn(body);
5563
5580
  } catch (err) {
5564
- if (err instanceof z9.ZodError) {
5565
- throw new ShapeError(`Validation failed: ${formatZodError(err)}`, {
5566
- cause: err
5567
- });
5568
- }
5569
- throw err;
5581
+ throw toShapeError(err);
5570
5582
  }
5571
5583
  };
5572
5584
  }
@@ -5599,6 +5611,15 @@ function createModelGuardExtension(config) {
5599
5611
  }
5600
5612
 
5601
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
+ }
5602
5623
  function createGuard(config) {
5603
5624
  const scalarBase = createScalarBase(
5604
5625
  config.guardConfig.strictDecimal ?? false
@@ -5620,14 +5641,6 @@ function createGuard(config) {
5620
5641
  warn: (msg) => console.warn(msg)
5621
5642
  };
5622
5643
  const wrapZodErrors = config.wrapZodErrors ?? false;
5623
- function rethrowZod(err) {
5624
- if (err instanceof ZodError) {
5625
- throw new ShapeError(`Validation failed: ${formatZodError(err)}`, {
5626
- cause: err
5627
- });
5628
- }
5629
- throw err;
5630
- }
5631
5644
  return {
5632
5645
  input: (model, opts) => {
5633
5646
  const result = schemaBuilder.buildInputSchema(model, opts);
@@ -5635,13 +5648,7 @@ function createGuard(config) {
5635
5648
  return result;
5636
5649
  return {
5637
5650
  schema: result.schema,
5638
- parse(data) {
5639
- try {
5640
- return result.parse(data);
5641
- } catch (err) {
5642
- rethrowZod(err);
5643
- }
5644
- }
5651
+ parse: wrapParseFn(result.parse)
5645
5652
  };
5646
5653
  },
5647
5654
  model: (model, opts) => schemaBuilder.buildModelSchema(model, opts),
@@ -5651,13 +5658,7 @@ function createGuard(config) {
5651
5658
  return qs;
5652
5659
  return {
5653
5660
  schemas: qs.schemas,
5654
- parse(body, opts) {
5655
- try {
5656
- return qs.parse(body, opts);
5657
- } catch (err) {
5658
- rethrowZod(err);
5659
- }
5660
- }
5661
+ parse: wrapParseFn(qs.parse)
5661
5662
  };
5662
5663
  },
5663
5664
  extension: (contextFn) => {