prisma-guard 1.27.1 → 1.28.1

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