prisma-guard 1.27.1 → 1.28.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -29,9 +29,6 @@ __export(runtime_exports, {
29
29
  });
30
30
  module.exports = __toCommonJS(runtime_exports);
31
31
 
32
- // src/runtime/guard.ts
33
- var import_zod10 = require("zod");
34
-
35
32
  // src/shared/errors.ts
36
33
  var PolicyError = class extends Error {
37
34
  status = 403;
@@ -61,10 +58,16 @@ function formatIssue(issue) {
61
58
  const path = issue.path.length > 0 ? `${issue.path.join(".")}: ` : "";
62
59
  const code = issue.code;
63
60
  if (code === "invalid_union") {
64
- const unionErrors = issue.unionErrors;
65
- if (unionErrors && unionErrors.length > 0) {
66
- const branches = unionErrors.map((ue, i) => {
67
- const nested = ue.issues.map(formatIssue).join(", ");
61
+ const raw = issue;
62
+ let branchIssues = null;
63
+ if (Array.isArray(raw.errors) && raw.errors.length > 0) {
64
+ branchIssues = raw.errors;
65
+ } else if (Array.isArray(raw.unionErrors) && raw.unionErrors.length > 0) {
66
+ branchIssues = raw.unionErrors.map((ue) => ue.issues);
67
+ }
68
+ if (branchIssues) {
69
+ const branches = branchIssues.map((issues, i) => {
70
+ const nested = issues.map(formatIssue).join(", ");
68
71
  return `branch ${i + 1}: [${nested}]`;
69
72
  }).join(" | ");
70
73
  return `${path}No matching variant (${branches})`;
@@ -83,6 +86,9 @@ function formatIssue(issue) {
83
86
  if (expected && received) {
84
87
  return `${path}Expected ${expected}, received ${received}`;
85
88
  }
89
+ if (expected) {
90
+ return `${path}Expected ${expected}`;
91
+ }
86
92
  }
87
93
  if (code === "invalid_enum_value") {
88
94
  const options = issue.options;
@@ -92,28 +98,28 @@ function formatIssue(issue) {
92
98
  }
93
99
  if (code === "too_small") {
94
100
  const minimum = issue.minimum;
95
- const type = issue.type;
96
- if (type === "string" && minimum !== void 0) {
101
+ const origin = issue.origin ?? issue.type;
102
+ if (origin === "string" && minimum !== void 0) {
97
103
  return `${path}String must contain at least ${minimum} character(s)`;
98
104
  }
99
- if (type === "array" && minimum !== void 0) {
105
+ if (origin === "array" && minimum !== void 0) {
100
106
  return `${path}Array must contain at least ${minimum} element(s)`;
101
107
  }
102
- if (type === "number" && minimum !== void 0) {
108
+ if (origin === "number" && minimum !== void 0) {
103
109
  return `${path}Number must be >= ${minimum}`;
104
110
  }
105
111
  return `${path}${issue.message}`;
106
112
  }
107
113
  if (code === "too_big") {
108
114
  const maximum = issue.maximum;
109
- const type = issue.type;
110
- if (type === "string" && maximum !== void 0) {
115
+ const origin = issue.origin ?? issue.type;
116
+ if (origin === "string" && maximum !== void 0) {
111
117
  return `${path}String must contain at most ${maximum} character(s)`;
112
118
  }
113
- if (type === "array" && maximum !== void 0) {
119
+ if (origin === "array" && maximum !== void 0) {
114
120
  return `${path}Array must contain at most ${maximum} element(s)`;
115
121
  }
116
- if (type === "number" && maximum !== void 0) {
122
+ if (origin === "number" && maximum !== void 0) {
117
123
  return `${path}Number must be <= ${maximum}`;
118
124
  }
119
125
  return `${path}${issue.message}`;
@@ -135,18 +141,42 @@ function formatIssue(issue) {
135
141
  function formatZodError(err) {
136
142
  return err.issues.map(formatIssue).join("; ");
137
143
  }
138
- function wrapParseError(err, context) {
144
+ function isZodErrorLike(err) {
145
+ return !!err && typeof err === "object" && "issues" in err;
146
+ }
147
+ function wrapZod(err, context) {
139
148
  if (err instanceof ShapeError) {
140
149
  throw new ShapeError(`${context}: ${err.message}`, { cause: err });
141
150
  }
142
- if (err && typeof err === "object" && "issues" in err) {
151
+ if (isZodErrorLike(err)) {
143
152
  throw new ShapeError(`${context}: ${formatZodError(err)}`, { cause: err });
144
153
  }
145
154
  throw err;
146
155
  }
156
+ function wrapParseError(err, context) {
157
+ return wrapZod(err, context);
158
+ }
159
+ function toShapeError(err, prefix = "Validation failed") {
160
+ if (isZodErrorLike(err)) {
161
+ return new ShapeError(`${prefix}: ${formatZodError(err)}`, { cause: err });
162
+ }
163
+ return err;
164
+ }
147
165
 
148
166
  // src/shared/scalar-base.ts
149
167
  var import_zod = require("zod");
168
+ function isPrismaNullSentinel(value) {
169
+ if (value === null || typeof value !== "object")
170
+ return false;
171
+ const tag = value._tag;
172
+ if (tag === "DbNull" || tag === "JsonNull" || tag === "AnyNull")
173
+ return true;
174
+ const constructorName = value.constructor?.name;
175
+ if (constructorName === "DbNull" || constructorName === "JsonNull" || constructorName === "AnyNull") {
176
+ return true;
177
+ }
178
+ return false;
179
+ }
150
180
  function isJsonSafe(value) {
151
181
  const stack = [{ tag: "visit", value }];
152
182
  const ancestors = /* @__PURE__ */ new Set();
@@ -161,6 +191,8 @@ function isJsonSafe(value) {
161
191
  return false;
162
192
  if (current === null)
163
193
  continue;
194
+ if (isPrismaNullSentinel(current))
195
+ continue;
164
196
  switch (typeof current) {
165
197
  case "string":
166
198
  case "boolean":
@@ -245,8 +277,8 @@ function wrapWithInputCoercion(fieldType, isList, schema) {
245
277
  break;
246
278
  case "Int":
247
279
  itemCoercion = import_zod.z.union([
248
- import_zod.z.number().transform((v) => Math.trunc(v)).pipe(import_zod.z.number().int()),
249
- import_zod.z.string().regex(/^-?\d+(\.\d+)?$/).transform((v) => Math.trunc(Number(v)))
280
+ import_zod.z.number().int(),
281
+ import_zod.z.string().regex(/^-?\d+$/).transform((v) => Number(v))
250
282
  ]);
251
283
  break;
252
284
  case "Float":
@@ -263,10 +295,10 @@ function wrapWithInputCoercion(fieldType, isList, schema) {
263
295
  }
264
296
 
265
297
  // src/runtime/schema-builder.ts
266
- var import_zod3 = require("zod");
298
+ var import_zod4 = require("zod");
267
299
 
268
300
  // src/runtime/zod-type-map.ts
269
- var import_zod2 = require("zod");
301
+ var import_zod3 = require("zod");
270
302
 
271
303
  // src/shared/utils.ts
272
304
  function isPlainObject(v) {
@@ -295,7 +327,7 @@ function coerceToArray(value) {
295
327
  const keys = Object.keys(value);
296
328
  if (keys.length === 0)
297
329
  return value;
298
- const allNumeric = keys.every((k) => /^\d+$/.test(k));
330
+ const allNumeric = keys.every((k) => /^\d+$/.test(k) && String(Number(k)) === k);
299
331
  if (!allNumeric)
300
332
  return value;
301
333
  const indices = keys.map(Number).sort((a, b) => a - b);
@@ -311,6 +343,48 @@ function coerceToArray(value) {
311
343
  return result;
312
344
  }
313
345
 
346
+ // src/shared/zod-helpers.ts
347
+ var import_zod2 = require("zod");
348
+ function strictObjectRequiringOne(shape, message) {
349
+ const keys = Object.keys(shape);
350
+ return import_zod2.z.object(shape).strict().refine(
351
+ (v) => keys.some((k) => v[k] !== void 0),
352
+ { message }
353
+ );
354
+ }
355
+ function singleOrArraySchema(single) {
356
+ return import_zod2.z.union([
357
+ single,
358
+ import_zod2.z.preprocess(coerceToArray, import_zod2.z.array(single).min(1))
359
+ ]);
360
+ }
361
+ function optionalOneOrMany(single) {
362
+ return import_zod2.z.union([single, import_zod2.z.preprocess(coerceToArray, import_zod2.z.array(single))]).optional();
363
+ }
364
+ function wrapRelationOp(isList, single) {
365
+ if (!isList)
366
+ return single.optional();
367
+ return optionalOneOrMany(single);
368
+ }
369
+ function buildLiteralTrueSchema(fieldNames, message, validate) {
370
+ const fieldSchemas = {};
371
+ for (const fieldName of fieldNames) {
372
+ if (validate)
373
+ validate(fieldName);
374
+ fieldSchemas[fieldName] = import_zod2.z.literal(true).optional();
375
+ }
376
+ return strictObjectRequiringOne(fieldSchemas, message).optional();
377
+ }
378
+ function requireConfigTrue(config, context) {
379
+ for (const [key, value] of Object.entries(config)) {
380
+ if (value !== true) {
381
+ throw new ShapeError(
382
+ `Config value for "${key}" in ${context} must be true, got ${typeof value}`
383
+ );
384
+ }
385
+ }
386
+ }
387
+
314
388
  // src/runtime/zod-type-map.ts
315
389
  var SCALAR_OPERATORS = {
316
390
  String: /* @__PURE__ */ new Set([
@@ -398,13 +472,13 @@ function getSupportedOperators(input, isList = false, isEnum = false) {
398
472
  function createBaseType(fieldMeta, enumMap, scalarBase) {
399
473
  let base;
400
474
  if (fieldMeta.isUnsupported) {
401
- base = import_zod2.z.unknown();
475
+ base = import_zod3.z.unknown();
402
476
  } else if (fieldMeta.isEnum) {
403
477
  const values = enumMap[fieldMeta.type];
404
478
  if (!values || values.length === 0) {
405
479
  throw new ShapeError(`Unknown enum: ${fieldMeta.type}`);
406
480
  }
407
- base = import_zod2.z.enum(values);
481
+ base = import_zod3.z.enum(values);
408
482
  } else {
409
483
  const factory = scalarBase[fieldMeta.type];
410
484
  if (!factory) {
@@ -413,7 +487,7 @@ function createBaseType(fieldMeta, enumMap, scalarBase) {
413
487
  base = factory();
414
488
  }
415
489
  if (fieldMeta.isList) {
416
- base = import_zod2.z.array(base);
490
+ base = import_zod3.z.array(base);
417
491
  }
418
492
  return base;
419
493
  }
@@ -424,35 +498,38 @@ function createScalarListOperatorSchema(fieldMeta, operator, enumMap, scalarBase
424
498
  );
425
499
  }
426
500
  if (operator === "isEmpty") {
427
- return import_zod2.z.boolean();
501
+ return import_zod3.z.boolean();
428
502
  }
429
503
  const itemMeta = { ...fieldMeta, isList: false };
430
504
  const itemBase = createBaseType(itemMeta, enumMap, scalarBase);
431
505
  if (operator === "has") {
432
- return !fieldMeta.isRequired ? import_zod2.z.union([itemBase, import_zod2.z.null()]) : itemBase;
506
+ return !fieldMeta.isRequired ? import_zod3.z.union([itemBase, import_zod3.z.null()]) : itemBase;
433
507
  }
434
508
  if (operator === "equals") {
435
- const arrSchema = import_zod2.z.array(itemBase);
436
- return fieldMeta.isRequired ? import_zod2.z.preprocess(coerceToArray, arrSchema) : import_zod2.z.union([import_zod2.z.preprocess(coerceToArray, arrSchema), import_zod2.z.null()]);
509
+ const arrSchema = import_zod3.z.array(itemBase);
510
+ return fieldMeta.isRequired ? import_zod3.z.preprocess(coerceToArray, arrSchema) : import_zod3.z.union([import_zod3.z.preprocess(coerceToArray, arrSchema), import_zod3.z.null()]);
437
511
  }
438
- return import_zod2.z.preprocess(coerceToArray, import_zod2.z.array(itemBase));
512
+ return import_zod3.z.preprocess(coerceToArray, import_zod3.z.array(itemBase));
439
513
  }
440
514
  function createJsonOperatorSchema(fieldMeta, operator) {
441
- const jsonValue = import_zod2.z.unknown();
515
+ const jsonValue = import_zod3.z.unknown();
442
516
  if (operator === "equals") {
443
- return !fieldMeta.isRequired ? import_zod2.z.union([jsonValue, import_zod2.z.null()]) : jsonValue;
517
+ return !fieldMeta.isRequired ? import_zod3.z.union([jsonValue, import_zod3.z.null()]) : jsonValue;
444
518
  }
445
519
  if (operator === "path") {
446
- return import_zod2.z.preprocess(coerceToArray, import_zod2.z.array(import_zod2.z.string()).min(1));
520
+ return import_zod3.z.preprocess(coerceToArray, import_zod3.z.array(import_zod3.z.string()).min(1));
447
521
  }
448
522
  if (JSON_STRING_OPERATORS.has(operator)) {
449
- return import_zod2.z.string();
523
+ return import_zod3.z.string();
450
524
  }
451
525
  if (JSON_ARRAY_OPERATORS.has(operator)) {
452
526
  return jsonValue;
453
527
  }
454
528
  throw new ShapeError(`Operator "${operator}" not supported for Json fields`);
455
529
  }
530
+ function nullableIfOptional(fieldMeta, base) {
531
+ return !fieldMeta.isRequired ? import_zod3.z.union([base, import_zod3.z.null()]) : base;
532
+ }
456
533
  function buildNotFilterSchema(fieldMeta, scalarSchema, enumMap, scalarBase) {
457
534
  const allOps = getSupportedOperators(fieldMeta);
458
535
  const nestedOps = allOps.filter((op) => op !== "not");
@@ -468,14 +545,15 @@ function buildNotFilterSchema(fieldMeta, scalarSchema, enumMap, scalarBase) {
468
545
  scalarBase
469
546
  ).optional();
470
547
  }
471
- const nestedKeys = Object.keys(nestedSchemas);
472
- const nestedObj = import_zod2.z.object(nestedSchemas).strict().refine(
473
- (value) => nestedKeys.some(
474
- (key) => value[key] !== void 0
475
- ),
476
- { message: "not filter must specify at least one operator" }
548
+ const nestedObj = strictObjectRequiringOne(
549
+ nestedSchemas,
550
+ "not filter must specify at least one operator"
477
551
  );
478
- return import_zod2.z.union([scalarSchema, nestedObj]);
552
+ return import_zod3.z.union([scalarSchema, nestedObj]);
553
+ }
554
+ function buildNotOperator(fieldMeta, scalarBaseSchema, enumMap, scalarBase) {
555
+ const scalarSchema = nullableIfOptional(fieldMeta, scalarBaseSchema);
556
+ return buildNotFilterSchema(fieldMeta, scalarSchema, enumMap, scalarBase);
479
557
  }
480
558
  function createOperatorSchema(fieldMeta, operator, enumMap, scalarBase) {
481
559
  const allowedOps = getSupportedOperators(fieldMeta);
@@ -512,32 +590,19 @@ function createOperatorSchema(fieldMeta, operator, enumMap, scalarBase) {
512
590
  if (!values || values.length === 0) {
513
591
  throw new ShapeError(`Unknown enum: ${fieldMeta.type}`);
514
592
  }
515
- const enumSchema = import_zod2.z.enum(values);
593
+ const enumSchema = import_zod3.z.enum(values);
516
594
  if (operator === "equals") {
517
- return !fieldMeta.isRequired ? import_zod2.z.union([enumSchema, import_zod2.z.null()]) : enumSchema;
595
+ return nullableIfOptional(fieldMeta, enumSchema);
518
596
  }
519
597
  if (operator === "not") {
520
- const scalarSchema = !fieldMeta.isRequired ? import_zod2.z.union([enumSchema, import_zod2.z.null()]) : enumSchema;
521
- return buildNotFilterSchema(
522
- fieldMeta,
523
- scalarSchema,
524
- enumMap,
525
- scalarBase
526
- );
598
+ return buildNotOperator(fieldMeta, enumSchema, enumMap, scalarBase);
527
599
  }
528
- const itemSchema = !fieldMeta.isRequired ? import_zod2.z.union([enumSchema, import_zod2.z.null()]) : enumSchema;
529
- return import_zod2.z.preprocess(coerceToArray, import_zod2.z.array(itemSchema));
600
+ const itemSchema = nullableIfOptional(fieldMeta, enumSchema);
601
+ return import_zod3.z.preprocess(coerceToArray, import_zod3.z.array(itemSchema));
530
602
  }
531
603
  if (fieldMeta.type === "Json") {
532
604
  if (operator === "not") {
533
- const jsonValue = import_zod2.z.unknown();
534
- const scalarSchema = !fieldMeta.isRequired ? import_zod2.z.union([jsonValue, import_zod2.z.null()]) : jsonValue;
535
- return buildNotFilterSchema(
536
- fieldMeta,
537
- scalarSchema,
538
- enumMap,
539
- scalarBase
540
- );
605
+ return buildNotOperator(fieldMeta, import_zod3.z.unknown(), enumMap, scalarBase);
541
606
  }
542
607
  return createJsonOperatorSchema(fieldMeta, operator);
543
608
  }
@@ -548,15 +613,14 @@ function createOperatorSchema(fieldMeta, operator, enumMap, scalarBase) {
548
613
  const scalar = factory();
549
614
  const coerced = wrapWithInputCoercion(fieldMeta.type, false, scalar);
550
615
  if (operator === "equals") {
551
- return !fieldMeta.isRequired ? import_zod2.z.union([coerced, import_zod2.z.null()]) : coerced;
616
+ return nullableIfOptional(fieldMeta, coerced);
552
617
  }
553
618
  if (operator === "not") {
554
- const scalarSchema = !fieldMeta.isRequired ? import_zod2.z.union([coerced, import_zod2.z.null()]) : coerced;
555
- return buildNotFilterSchema(fieldMeta, scalarSchema, enumMap, scalarBase);
619
+ return buildNotOperator(fieldMeta, coerced, enumMap, scalarBase);
556
620
  }
557
621
  if (operator === "in" || operator === "notIn") {
558
- const itemSchema = !fieldMeta.isRequired ? import_zod2.z.union([coerced, import_zod2.z.null()]) : coerced;
559
- return import_zod2.z.preprocess(coerceToArray, import_zod2.z.array(itemSchema));
622
+ const itemSchema = nullableIfOptional(fieldMeta, coerced);
623
+ return import_zod3.z.preprocess(coerceToArray, import_zod3.z.array(itemSchema));
560
624
  }
561
625
  return coerced;
562
626
  }
@@ -582,6 +646,26 @@ function lruSet(cache, key, value, maxSize) {
582
646
  cache.delete(oldest);
583
647
  }
584
648
  }
649
+ function applyCreateUpdateNullability(fieldMeta, fieldSchema, options) {
650
+ const { mode, handlesUndefined } = options;
651
+ const allowNull = options.allowNull ?? true;
652
+ if (mode === "create") {
653
+ if (!fieldMeta.isRequired) {
654
+ if (handlesUndefined) {
655
+ return allowNull ? fieldSchema.nullable() : fieldSchema;
656
+ }
657
+ return allowNull ? fieldSchema.nullable().optional() : fieldSchema.optional();
658
+ }
659
+ if (fieldMeta.hasDefault) {
660
+ return handlesUndefined ? fieldSchema : fieldSchema.optional();
661
+ }
662
+ return fieldSchema;
663
+ }
664
+ if (!fieldMeta.isRequired && allowNull) {
665
+ return fieldSchema.nullable().optional();
666
+ }
667
+ return fieldSchema.optional();
668
+ }
585
669
  function createSchemaBuilder(typeMap, zodChains, enumMap, scalarBase, zodDefaults) {
586
670
  const chainCache = /* @__PURE__ */ new Map();
587
671
  function buildFieldSchema(model, field) {
@@ -636,20 +720,25 @@ function createSchemaBuilder(typeMap, zodChains, enumMap, scalarBase, zodDefault
636
720
  const zodDefaultSet = zodDefaultFields ? new Set(zodDefaultFields) : void 0;
637
721
  let fieldNames = Object.keys(modelFields).filter((name) => {
638
722
  const meta = modelFields[name];
639
- return !meta.isRelation && !meta.isUpdatedAt;
723
+ return !meta.isRelation && !meta.isUpdatedAt && !meta.isUnsupported;
640
724
  });
641
725
  if (opts.pick) {
642
726
  for (const name of opts.pick) {
643
- if (!modelFields[name])
727
+ const meta = modelFields[name];
728
+ if (!meta)
644
729
  throw new ShapeError(`Unknown field "${name}" on model "${model}"`);
645
- if (modelFields[name].isRelation)
730
+ if (meta.isRelation)
646
731
  throw new ShapeError(
647
732
  `Field "${name}" cannot be used in input schema (relation field)`
648
733
  );
649
- if (modelFields[name].isUpdatedAt)
734
+ if (meta.isUpdatedAt)
650
735
  throw new ShapeError(
651
736
  `Field "${name}" cannot be used in input schema (updatedAt field)`
652
737
  );
738
+ if (meta.isUnsupported)
739
+ throw new ShapeError(
740
+ `Field "${name}" on model "${model}" has an Unsupported type and cannot be used in input schema`
741
+ );
653
742
  }
654
743
  fieldNames = fieldNames.filter((n) => opts.pick.includes(n));
655
744
  } else if (opts.omit) {
@@ -662,7 +751,7 @@ function createSchemaBuilder(typeMap, zodChains, enumMap, scalarBase, zodDefault
662
751
  const schemaMap = {};
663
752
  for (const name of fieldNames) {
664
753
  const fieldMeta = modelFields[name];
665
- let fieldSchema;
754
+ let baseSchema;
666
755
  let handlesUndefined;
667
756
  if (opts.refine?.[name]) {
668
757
  let refined;
@@ -679,34 +768,19 @@ function createSchemaBuilder(typeMap, zodChains, enumMap, scalarBase, zodDefault
679
768
  `Refine function for "${model}.${name}" must return a Zod schema`
680
769
  );
681
770
  }
682
- fieldSchema = refined;
683
- handlesUndefined = schemaProducesValueForUndefined(fieldSchema);
771
+ baseSchema = refined;
772
+ handlesUndefined = schemaProducesValueForUndefined(baseSchema);
684
773
  } else {
685
- fieldSchema = buildFieldSchema(model, name);
774
+ baseSchema = buildFieldSchema(model, name);
686
775
  handlesUndefined = zodDefaultSet !== void 0 && zodDefaultSet.has(name);
687
776
  }
688
- if (mode === "create") {
689
- if (!fieldMeta.isRequired) {
690
- if (handlesUndefined) {
691
- fieldSchema = allowNull ? fieldSchema.nullable() : fieldSchema;
692
- } else {
693
- fieldSchema = allowNull ? fieldSchema.nullable().optional() : fieldSchema.optional();
694
- }
695
- } else if (fieldMeta.hasDefault) {
696
- if (!handlesUndefined) {
697
- fieldSchema = fieldSchema.optional();
698
- }
699
- }
700
- } else {
701
- if (!fieldMeta.isRequired && allowNull) {
702
- fieldSchema = fieldSchema.nullable().optional();
703
- } else {
704
- fieldSchema = fieldSchema.optional();
705
- }
706
- }
707
- schemaMap[name] = fieldSchema;
777
+ schemaMap[name] = applyCreateUpdateNullability(fieldMeta, baseSchema, {
778
+ mode,
779
+ handlesUndefined,
780
+ allowNull
781
+ });
708
782
  }
709
- let schema = import_zod3.z.object(schemaMap).strict();
783
+ let schema = import_zod4.z.object(schemaMap).strict();
710
784
  if (opts.partial) {
711
785
  schema = schema.partial();
712
786
  }
@@ -733,13 +807,18 @@ function createSchemaBuilder(typeMap, zodChains, enumMap, scalarBase, zodDefault
733
807
  const includeKeys = new Set(Object.keys(opts.include ?? {}));
734
808
  if (opts.pick) {
735
809
  for (const name of opts.pick) {
736
- if (!modelFields[name])
810
+ const meta = modelFields[name];
811
+ if (!meta)
737
812
  throw new ShapeError(`Unknown field "${name}" on model "${model}"`);
738
- if (modelFields[name].isRelation && !includeKeys.has(name)) {
813
+ if (meta.isRelation && !includeKeys.has(name)) {
739
814
  throw new ShapeError(
740
815
  `Field "${name}" is a relation on model "${model}". Use include: { ${name}: ... } instead of pick.`
741
816
  );
742
817
  }
818
+ if (meta.isUnsupported)
819
+ throw new ShapeError(
820
+ `Field "${name}" on model "${model}" has an Unsupported type and cannot be used in output schema`
821
+ );
743
822
  }
744
823
  }
745
824
  if (opts.omit) {
@@ -750,7 +829,7 @@ function createSchemaBuilder(typeMap, zodChains, enumMap, scalarBase, zodDefault
750
829
  }
751
830
  let scalarNames = Object.keys(modelFields).filter((name) => {
752
831
  const meta = modelFields[name];
753
- return !meta.isRelation;
832
+ return !meta.isRelation && !meta.isUnsupported;
754
833
  });
755
834
  if (opts.pick) {
756
835
  scalarNames = scalarNames.filter((n) => opts.pick.includes(n));
@@ -787,7 +866,7 @@ function createSchemaBuilder(typeMap, zodChains, enumMap, scalarBase, zodDefault
787
866
  effectiveMaxDepth
788
867
  );
789
868
  if (fieldMeta.isList) {
790
- relSchema = import_zod3.z.array(relSchema);
869
+ relSchema = import_zod4.z.array(relSchema);
791
870
  } else if (!fieldMeta.isRequired) {
792
871
  relSchema = relSchema.nullable();
793
872
  }
@@ -800,9 +879,9 @@ function createSchemaBuilder(typeMap, zodChains, enumMap, scalarBase, zodDefault
800
879
  if (opts._count === true) {
801
880
  const countFields = {};
802
881
  for (const relName of listRelationNames) {
803
- countFields[relName] = import_zod3.z.number().int().min(0);
882
+ countFields[relName] = import_zod4.z.number().int().min(0);
804
883
  }
805
- schemaMap["_count"] = import_zod3.z.object(countFields);
884
+ schemaMap["_count"] = import_zod4.z.object(countFields);
806
885
  } else {
807
886
  const countFields = {};
808
887
  for (const relName of Object.keys(opts._count)) {
@@ -818,12 +897,12 @@ function createSchemaBuilder(typeMap, zodChains, enumMap, scalarBase, zodDefault
818
897
  throw new ShapeError(
819
898
  `Field "${relName}" is a to-one relation on model "${model}" in _count. Only to-many relations support _count.`
820
899
  );
821
- countFields[relName] = import_zod3.z.number().int().min(0);
900
+ countFields[relName] = import_zod4.z.number().int().min(0);
822
901
  }
823
- schemaMap["_count"] = import_zod3.z.object(countFields);
902
+ schemaMap["_count"] = import_zod4.z.object(countFields);
824
903
  }
825
904
  }
826
- let schema = import_zod3.z.object(schemaMap);
905
+ let schema = import_zod4.z.object(schemaMap);
827
906
  if (opts.strict) {
828
907
  schema = schema.strict();
829
908
  }
@@ -838,7 +917,7 @@ function createSchemaBuilder(typeMap, zodChains, enumMap, scalarBase, zodDefault
838
917
  }
839
918
 
840
919
  // src/runtime/query-builder.ts
841
- var import_zod7 = require("zod");
920
+ var import_zod8 = require("zod");
842
921
 
843
922
  // src/shared/constants.ts
844
923
  var SHAPE_CONFIG_KEY_LIST = [
@@ -894,6 +973,8 @@ function unsupported() {
894
973
 
895
974
  // src/shared/match-caller.ts
896
975
  function matchCallerPattern(patterns, caller) {
976
+ if (typeof caller !== "string" || caller.trim().length === 0)
977
+ return null;
897
978
  if (patterns.includes(caller))
898
979
  return caller;
899
980
  const matches = [];
@@ -947,7 +1028,7 @@ function validateContext(ctx) {
947
1028
  }
948
1029
 
949
1030
  // src/runtime/query-builder-where.ts
950
- var import_zod4 = require("zod");
1031
+ var import_zod5 = require("zod");
951
1032
 
952
1033
  // src/shared/deep-clone.ts
953
1034
  function deepClone(value) {
@@ -982,44 +1063,75 @@ function deepClone(value) {
982
1063
  }
983
1064
  }
984
1065
 
985
- // src/runtime/query-builder-forced.ts
986
- var EMPTY_WHERE_FORCED = {
987
- conditions: {},
988
- relations: {}
989
- };
990
- function hasWhereForced(f) {
991
- return Object.keys(f.conditions).length > 0 || Object.keys(f.relations).length > 0;
992
- }
993
- function forcedScalarsEqual(a, b) {
1066
+ // src/shared/deep-equal.ts
1067
+ function deepEqual(a, b) {
994
1068
  if (a === b)
995
1069
  return true;
996
1070
  if (a === null || b === null)
997
1071
  return false;
998
- if (typeof a !== typeof b)
1072
+ if (a === void 0 || b === void 0)
1073
+ return false;
1074
+ const ta = typeof a;
1075
+ const tb = typeof b;
1076
+ if (ta !== tb)
1077
+ return false;
1078
+ if (ta === "bigint")
1079
+ return a === b;
1080
+ if (ta !== "object")
999
1081
  return false;
1000
1082
  if (a instanceof Date && b instanceof Date) {
1001
1083
  return a.getTime() === b.getTime();
1002
1084
  }
1085
+ if (a instanceof Date || b instanceof Date)
1086
+ return false;
1003
1087
  if (a instanceof RegExp && b instanceof RegExp) {
1004
1088
  return a.source === b.source && a.flags === b.flags;
1005
1089
  }
1090
+ if (a instanceof RegExp || b instanceof RegExp)
1091
+ return false;
1006
1092
  if (Array.isArray(a)) {
1007
1093
  if (!Array.isArray(b))
1008
1094
  return false;
1009
1095
  if (a.length !== b.length)
1010
1096
  return false;
1011
- return a.every((v, i) => forcedScalarsEqual(v, b[i]));
1097
+ for (let i = 0; i < a.length; i++) {
1098
+ if (!deepEqual(a[i], b[i]))
1099
+ return false;
1100
+ }
1101
+ return true;
1012
1102
  }
1013
- if (isPlainObject(a) && isPlainObject(b)) {
1014
- const aKeys = Object.keys(a);
1015
- const bKeys = Object.keys(b);
1016
- if (aKeys.length !== bKeys.length)
1103
+ if (Array.isArray(b))
1104
+ return false;
1105
+ if (!isPlainObject(a) || !isPlainObject(b))
1106
+ return false;
1107
+ const aKeys = Object.keys(a);
1108
+ const bKeys = Object.keys(b);
1109
+ if (aKeys.length !== bKeys.length)
1110
+ return false;
1111
+ for (const key of aKeys) {
1112
+ if (!(key in b))
1113
+ return false;
1114
+ if (!deepEqual(a[key], b[key]))
1017
1115
  return false;
1018
- return aKeys.every(
1019
- (k) => k in b && forcedScalarsEqual(a[k], b[k])
1020
- );
1021
1116
  }
1022
- return false;
1117
+ return true;
1118
+ }
1119
+
1120
+ // src/shared/unique-constraints.ts
1121
+ function formatUniqueConstraint(constraint) {
1122
+ return constraint.fields.length === 1 ? constraint.selector : `${constraint.selector}(${constraint.fields.join(", ")})`;
1123
+ }
1124
+ function formatUniqueConstraints(constraints) {
1125
+ return constraints.map(formatUniqueConstraint).join(" | ");
1126
+ }
1127
+
1128
+ // src/runtime/query-builder-forced.ts
1129
+ var EMPTY_WHERE_FORCED = {
1130
+ conditions: {},
1131
+ relations: {}
1132
+ };
1133
+ function hasWhereForced(f) {
1134
+ return Object.keys(f.conditions).length > 0 || Object.keys(f.relations).length > 0;
1023
1135
  }
1024
1136
  function tryInlineForcedField(result, field, forcedValue) {
1025
1137
  if (!(field in result))
@@ -1038,7 +1150,7 @@ function tryInlineForcedField(result, field, forcedValue) {
1038
1150
  const merged = { ...existing };
1039
1151
  for (const [op, value] of Object.entries(forcedValue)) {
1040
1152
  if (op in merged) {
1041
- if (!forcedScalarsEqual(merged[op], value)) {
1153
+ if (!deepEqual(merged[op], value)) {
1042
1154
  throw new ShapeError(
1043
1155
  `Conflicting where values for "${field}.${op}": client provided a different value than the forced shape`
1044
1156
  );
@@ -1069,6 +1181,17 @@ function mergeWhereForced(where, forced) {
1069
1181
  if (Object.keys(forced.conditions).length > 0) {
1070
1182
  const remaining = {};
1071
1183
  for (const [field, forcedValue] of Object.entries(forced.conditions)) {
1184
+ if (field === "NOT") {
1185
+ const existing = result[field];
1186
+ const forcedArr = Array.isArray(forcedValue) ? forcedValue.map(deepClone) : [deepClone(forcedValue)];
1187
+ if (existing === void 0) {
1188
+ result[field] = forcedArr.length === 1 ? forcedArr[0] : forcedArr;
1189
+ } else {
1190
+ const existingArr = Array.isArray(existing) ? existing : [existing];
1191
+ result[field] = [...existingArr, ...forcedArr];
1192
+ }
1193
+ continue;
1194
+ }
1072
1195
  const inlined = tryInlineForcedField(result, field, forcedValue);
1073
1196
  if (!inlined) {
1074
1197
  remaining[field] = deepClone(forcedValue);
@@ -1084,32 +1207,6 @@ function mergeWhereForced(where, forced) {
1084
1207
  }
1085
1208
  return result;
1086
1209
  }
1087
- function uniqueValuesEqual(a, b) {
1088
- if (a === b)
1089
- return true;
1090
- if (a === null || b === null)
1091
- return false;
1092
- if (typeof a !== typeof b)
1093
- return false;
1094
- if (a instanceof Date && b instanceof Date) {
1095
- return a.getTime() === b.getTime();
1096
- }
1097
- if (Array.isArray(a)) {
1098
- if (!Array.isArray(b))
1099
- return false;
1100
- if (a.length !== b.length)
1101
- return false;
1102
- return a.every((v, i) => uniqueValuesEqual(v, b[i]));
1103
- }
1104
- if (isPlainObject(a) && isPlainObject(b)) {
1105
- const aKeys = Object.keys(a);
1106
- const bKeys = Object.keys(b);
1107
- if (aKeys.length !== bKeys.length)
1108
- return false;
1109
- return aKeys.every((key) => key in b && uniqueValuesEqual(a[key], b[key]));
1110
- }
1111
- return false;
1112
- }
1113
1210
  function mergeUniqueValue(target, key, value) {
1114
1211
  const cloned = deepClone(value);
1115
1212
  if (!(key in target)) {
@@ -1120,7 +1217,7 @@ function mergeUniqueValue(target, key, value) {
1120
1217
  if (isPlainObject(existing) && isPlainObject(cloned)) {
1121
1218
  const merged = { ...existing };
1122
1219
  for (const [nestedKey, nestedValue] of Object.entries(cloned)) {
1123
- if (nestedKey in merged && !uniqueValuesEqual(merged[nestedKey], nestedValue)) {
1220
+ if (nestedKey in merged && !deepEqual(merged[nestedKey], nestedValue)) {
1124
1221
  throw new ShapeError(
1125
1222
  `Conflicting unique where value for "${key}.${nestedKey}"`
1126
1223
  );
@@ -1130,7 +1227,7 @@ function mergeUniqueValue(target, key, value) {
1130
1227
  target[key] = merged;
1131
1228
  return;
1132
1229
  }
1133
- if (!uniqueValuesEqual(existing, cloned)) {
1230
+ if (!deepEqual(existing, cloned)) {
1134
1231
  throw new ShapeError(`Conflicting unique where value for "${key}"`);
1135
1232
  }
1136
1233
  }
@@ -1157,7 +1254,30 @@ function applyBuiltShape(built, body, isUniqueMethod, modelName) {
1157
1254
  throw new ShapeError('Request cannot define both "include" and "select"');
1158
1255
  }
1159
1256
  if ("where" in bodyObj) {
1160
- if (!hasWhereInSchema) {
1257
+ if (bodyObj.where === void 0 || bodyObj.where === null) {
1258
+ const { where: _, ...rest } = bodyObj;
1259
+ parseable = rest;
1260
+ } else if (!hasWhereInSchema) {
1261
+ const context = modelName ? ` on model "${modelName}"` : "";
1262
+ if (!hasWhereForced(built.forcedWhere)) {
1263
+ throw new ShapeError(
1264
+ `Guard shape does not allow "where"${context}`
1265
+ );
1266
+ }
1267
+ if (!isPlainObject(bodyObj.where)) {
1268
+ throw new ShapeError(
1269
+ `Invalid "where"${context}: must be a plain object`
1270
+ );
1271
+ }
1272
+ const remaining = stripUniqueWhereForcedInput(
1273
+ bodyObj.where,
1274
+ built.forcedWhere
1275
+ );
1276
+ if (Object.keys(remaining).length > 0) {
1277
+ throw new ShapeError(
1278
+ `Guard shape where${context} contains only forced conditions. Client where input is not accepted.`
1279
+ );
1280
+ }
1161
1281
  const { where: _, ...rest } = bodyObj;
1162
1282
  parseable = rest;
1163
1283
  } else if (isUniqueMethod && hasWhereForced(built.forcedWhere) && isPlainObject(bodyObj.where)) {
@@ -1233,6 +1353,86 @@ function buildCountForPlacement(countWhere) {
1233
1353
  }
1234
1354
  return { _count: { select: countSelect } };
1235
1355
  }
1356
+ function collectSubtree(forced) {
1357
+ const nested = {};
1358
+ if (forced.where && hasWhereForced(forced.where)) {
1359
+ nested.where = mergeWhereForced(void 0, forced.where);
1360
+ }
1361
+ if (forced.include) {
1362
+ nested.include = buildForcedOnlyContainer(forced.include);
1363
+ }
1364
+ if (forced.select) {
1365
+ nested.select = buildForcedOnlyContainer(forced.select);
1366
+ }
1367
+ if (forced._countWhere && Object.keys(forced._countWhere).length > 0) {
1368
+ const placement = forced._countWherePlacement ?? "include";
1369
+ if (!nested[placement])
1370
+ nested[placement] = {};
1371
+ const placementObj = nested[placement];
1372
+ Object.assign(placementObj, buildCountForPlacement(forced._countWhere));
1373
+ }
1374
+ return nested;
1375
+ }
1376
+ function applyForcedToRelValue(relName, relVal, forced) {
1377
+ if (relVal === true) {
1378
+ const expanded = collectSubtree(forced);
1379
+ if (forced.include) {
1380
+ applyForcedTree(expanded, "include", forced.include);
1381
+ }
1382
+ if (forced.select) {
1383
+ applyForcedTree(expanded, "select", forced.select);
1384
+ }
1385
+ if (expanded.include && expanded.select) {
1386
+ throw new ShapeError(
1387
+ `Forced tree for relation "${relName}" produces both "include" and "select". Prisma does not allow both at the same level.`
1388
+ );
1389
+ }
1390
+ return Object.keys(expanded).length > 0 ? expanded : true;
1391
+ }
1392
+ if (!isPlainObject(relVal))
1393
+ return relVal;
1394
+ const relObj = relVal;
1395
+ if (forced.where && hasWhereForced(forced.where)) {
1396
+ relObj.where = mergeWhereForced(
1397
+ relObj.where,
1398
+ forced.where
1399
+ );
1400
+ }
1401
+ if (forced.include) {
1402
+ if (!relObj.include) {
1403
+ relObj.include = buildForcedOnlyContainer(forced.include);
1404
+ }
1405
+ applyForcedTree(relObj, "include", forced.include);
1406
+ }
1407
+ if (forced.select) {
1408
+ if (!relObj.select) {
1409
+ relObj.select = buildForcedOnlyContainer(forced.select);
1410
+ }
1411
+ applyForcedTree(relObj, "select", forced.select);
1412
+ }
1413
+ if (forced._countWhere && Object.keys(forced._countWhere).length > 0) {
1414
+ const placement = forced._countWherePlacement ?? "include";
1415
+ const existing = relObj[placement];
1416
+ let placementObj;
1417
+ if (!isPlainObject(existing)) {
1418
+ placementObj = {};
1419
+ relObj[placement] = placementObj;
1420
+ } else {
1421
+ placementObj = existing;
1422
+ }
1423
+ if (!("_count" in placementObj)) {
1424
+ Object.assign(placementObj, buildCountForPlacement(forced._countWhere));
1425
+ } else {
1426
+ applyForcedCountWhere(placementObj, forced._countWhere);
1427
+ }
1428
+ }
1429
+ if (relObj.include && relObj.select) {
1430
+ throw new ShapeError(
1431
+ `Relation "${relName}" has both "include" and "select" after forced tree merge. Prisma does not allow both at the same level.`
1432
+ );
1433
+ }
1434
+ return relObj;
1435
+ }
1236
1436
  function applyForcedTree(validated, key, tree) {
1237
1437
  const container = validated[key];
1238
1438
  if (!container)
@@ -1241,89 +1441,13 @@ function applyForcedTree(validated, key, tree) {
1241
1441
  const relVal = container[relName];
1242
1442
  if (relVal === void 0)
1243
1443
  continue;
1244
- if (relVal === true) {
1245
- const expanded = {};
1246
- if (forced.where && hasWhereForced(forced.where)) {
1247
- expanded.where = mergeWhereForced(void 0, forced.where);
1248
- }
1249
- if (forced.include) {
1250
- expanded.include = buildForcedOnlyContainer(forced.include);
1251
- applyForcedTree(expanded, "include", forced.include);
1252
- }
1253
- if (forced.select) {
1254
- expanded.select = buildForcedOnlyContainer(forced.select);
1255
- applyForcedTree(expanded, "select", forced.select);
1256
- }
1257
- if (forced._countWhere && Object.keys(forced._countWhere).length > 0) {
1258
- const placement = forced._countWherePlacement ?? "include";
1259
- if (!expanded[placement])
1260
- expanded[placement] = {};
1261
- const placementObj = expanded[placement];
1262
- Object.assign(placementObj, buildCountForPlacement(forced._countWhere));
1263
- }
1264
- if (expanded.include && expanded.select) {
1265
- throw new ShapeError(
1266
- `Forced tree for relation "${relName}" produces both "include" and "select". Prisma does not allow both at the same level.`
1267
- );
1268
- }
1269
- container[relName] = Object.keys(expanded).length > 0 ? expanded : true;
1270
- continue;
1271
- }
1272
- if (isPlainObject(relVal)) {
1273
- const relObj = relVal;
1274
- if (forced.where && hasWhereForced(forced.where)) {
1275
- relObj.where = mergeWhereForced(
1276
- relObj.where,
1277
- forced.where
1278
- );
1279
- }
1280
- if (forced.include) {
1281
- if (!relObj.include) {
1282
- relObj.include = buildForcedOnlyContainer(forced.include);
1283
- }
1284
- applyForcedTree(relObj, "include", forced.include);
1285
- }
1286
- if (forced.select) {
1287
- if (!relObj.select) {
1288
- relObj.select = buildForcedOnlyContainer(forced.select);
1289
- }
1290
- applyForcedTree(relObj, "select", forced.select);
1291
- }
1292
- if (forced._countWhere && Object.keys(forced._countWhere).length > 0) {
1293
- const placement = forced._countWherePlacement ?? "include";
1294
- const projContainer = relObj[placement];
1295
- if (projContainer) {
1296
- applyForcedCountWhere(projContainer, forced._countWhere);
1297
- }
1298
- }
1299
- if (relObj.include && relObj.select) {
1300
- throw new ShapeError(
1301
- `Relation "${relName}" has both "include" and "select" after forced tree merge. Prisma does not allow both at the same level.`
1302
- );
1303
- }
1304
- }
1444
+ container[relName] = applyForcedToRelValue(relName, relVal, forced);
1305
1445
  }
1306
1446
  }
1307
1447
  function buildForcedOnlyContainer(tree) {
1308
1448
  const result = {};
1309
1449
  for (const [relName, forced] of Object.entries(tree)) {
1310
- const nested = {};
1311
- if (forced.where && hasWhereForced(forced.where)) {
1312
- nested.where = mergeWhereForced(void 0, forced.where);
1313
- }
1314
- if (forced.include) {
1315
- nested.include = buildForcedOnlyContainer(forced.include);
1316
- }
1317
- if (forced.select) {
1318
- nested.select = buildForcedOnlyContainer(forced.select);
1319
- }
1320
- if (forced._countWhere && Object.keys(forced._countWhere).length > 0) {
1321
- const placement = forced._countWherePlacement ?? "include";
1322
- if (!nested[placement])
1323
- nested[placement] = {};
1324
- const placementObj = nested[placement];
1325
- Object.assign(placementObj, buildCountForPlacement(forced._countWhere));
1326
- }
1450
+ const nested = collectSubtree(forced);
1327
1451
  result[relName] = Object.keys(nested).length > 0 ? nested : true;
1328
1452
  }
1329
1453
  return result;
@@ -1339,11 +1463,15 @@ function applyForcedCountWhere(container, forcedCountWhere) {
1339
1463
  const selectObj = selectVal;
1340
1464
  for (const [relName, forced] of Object.entries(forcedCountWhere)) {
1341
1465
  const relVal = selectObj[relName];
1342
- if (relVal === void 0)
1466
+ if (relVal === void 0) {
1467
+ selectObj[relName] = { where: mergeWhereForced(void 0, forced) };
1343
1468
  continue;
1469
+ }
1344
1470
  if (relVal === true) {
1345
1471
  selectObj[relName] = { where: mergeWhereForced(void 0, forced) };
1346
- } else if (isPlainObject(relVal)) {
1472
+ continue;
1473
+ }
1474
+ if (isPlainObject(relVal)) {
1347
1475
  const relObj = relVal;
1348
1476
  relObj.where = mergeWhereForced(
1349
1477
  relObj.where,
@@ -1352,12 +1480,6 @@ function applyForcedCountWhere(container, forcedCountWhere) {
1352
1480
  }
1353
1481
  }
1354
1482
  }
1355
- function formatUniqueConstraint(constraint) {
1356
- return constraint.fields.length === 1 ? constraint.selector : `${constraint.selector}(${constraint.fields.join(", ")})`;
1357
- }
1358
- function formatUniqueConstraints(constraints) {
1359
- return constraints.map(formatUniqueConstraint).join(" | ");
1360
- }
1361
1483
  function resolvedWhereCoversConstraint(where, constraint) {
1362
1484
  if (constraint.fields.length === 1) {
1363
1485
  return constraint.fields[0] in where;
@@ -1463,7 +1585,12 @@ function stripUniqueWhereForcedInput(where, forced) {
1463
1585
  const currentValue = result[key];
1464
1586
  if (isPlainObject(currentValue) && isPlainObject(forcedValue)) {
1465
1587
  const nested = { ...currentValue };
1466
- for (const nestedKey of Object.keys(forcedValue)) {
1588
+ for (const [nestedKey, nestedForcedValue] of Object.entries(forcedValue)) {
1589
+ if (nestedKey in nested && !deepEqual(nested[nestedKey], nestedForcedValue)) {
1590
+ throw new ShapeError(
1591
+ `Client unique where value for "${key}.${nestedKey}" conflicts with forced value`
1592
+ );
1593
+ }
1467
1594
  delete nested[nestedKey];
1468
1595
  }
1469
1596
  if (Object.keys(nested).length === 0) {
@@ -1473,11 +1600,25 @@ function stripUniqueWhereForcedInput(where, forced) {
1473
1600
  }
1474
1601
  continue;
1475
1602
  }
1603
+ if (!deepEqual(currentValue, forcedValue)) {
1604
+ throw new ShapeError(
1605
+ `Client unique where value for "${key}" conflicts with forced value`
1606
+ );
1607
+ }
1476
1608
  delete result[key];
1477
1609
  }
1478
1610
  return result;
1479
1611
  }
1480
1612
 
1613
+ // src/runtime/direct-scalar-schema.ts
1614
+ function buildDirectScalarSchema(fieldMeta, enumMap, scalarBase) {
1615
+ const base = createBaseType(fieldMeta, enumMap, scalarBase);
1616
+ if (!fieldMeta.isEnum && !fieldMeta.isRelation && !fieldMeta.isUnsupported) {
1617
+ return wrapWithInputCoercion(fieldMeta.type, fieldMeta.isList, base);
1618
+ }
1619
+ return base;
1620
+ }
1621
+
1481
1622
  // src/runtime/query-builder-where.ts
1482
1623
  var UNSUPPORTED_WHERE_TYPES = /* @__PURE__ */ new Set(["Bytes"]);
1483
1624
  var STRING_MODE_OPS = /* @__PURE__ */ new Set([
@@ -1491,47 +1632,40 @@ var JSON_STRING_MODE_OPS = /* @__PURE__ */ new Set([
1491
1632
  "string_starts_with",
1492
1633
  "string_ends_with"
1493
1634
  ]);
1635
+ var NEGATIVE_RELATION_OPS = /* @__PURE__ */ new Set(["none", "isNot"]);
1494
1636
  var MAX_WHERE_DEPTH = 10;
1495
- function safeStringify(v) {
1496
- if (typeof v === "bigint")
1497
- return `${v}n`;
1637
+ function safeStringify(value) {
1638
+ if (typeof value === "bigint")
1639
+ return `${value}n`;
1640
+ if (typeof value === "undefined")
1641
+ return "undefined";
1642
+ if (typeof value === "function")
1643
+ return "[function]";
1644
+ if (typeof value === "symbol")
1645
+ return value.toString();
1646
+ const seen = /* @__PURE__ */ new WeakSet();
1498
1647
  try {
1499
- return JSON.stringify(v);
1648
+ const json = JSON.stringify(value, (_key, current) => {
1649
+ if (typeof current === "bigint")
1650
+ return `${current}n`;
1651
+ if (typeof current === "undefined")
1652
+ return "[undefined]";
1653
+ if (typeof current === "function")
1654
+ return "[function]";
1655
+ if (typeof current === "symbol")
1656
+ return current.toString();
1657
+ if (current && typeof current === "object") {
1658
+ if (seen.has(current))
1659
+ return "[Circular]";
1660
+ seen.add(current);
1661
+ }
1662
+ return current;
1663
+ });
1664
+ return json === void 0 ? String(value) : json;
1500
1665
  } catch {
1501
- return String(v);
1666
+ return String(value);
1502
1667
  }
1503
1668
  }
1504
- function forcedValuesEqual(a, b) {
1505
- if (a === b)
1506
- return true;
1507
- if (a === null || b === null)
1508
- return false;
1509
- if (typeof a !== typeof b)
1510
- return false;
1511
- if (typeof a === "bigint")
1512
- return a === b;
1513
- if (a instanceof Date && b instanceof Date)
1514
- return a.getTime() === b.getTime();
1515
- if (a instanceof RegExp && b instanceof RegExp) {
1516
- return a.source === b.source && a.flags === b.flags;
1517
- }
1518
- if (typeof a !== "object")
1519
- return false;
1520
- if (Array.isArray(a)) {
1521
- if (!Array.isArray(b))
1522
- return false;
1523
- if (a.length !== b.length)
1524
- return false;
1525
- return a.every((v, i) => forcedValuesEqual(v, b[i]));
1526
- }
1527
- if (!isPlainObject(a) || !isPlainObject(b))
1528
- return false;
1529
- const aKeys = Object.keys(a);
1530
- const bKeys = Object.keys(b);
1531
- if (aKeys.length !== bKeys.length)
1532
- return false;
1533
- return aKeys.every((k) => k in b && forcedValuesEqual(a[k], b[k]));
1534
- }
1535
1669
  function mergeScalarConditions(target, source) {
1536
1670
  for (const [field, ops] of Object.entries(source)) {
1537
1671
  const existing = target[field];
@@ -1549,7 +1683,7 @@ function mergeScalarConditions(target, source) {
1549
1683
  for (const [op, val] of Object.entries(ops)) {
1550
1684
  if (op in existing) {
1551
1685
  const existingVal = existing[op];
1552
- if (!forcedValuesEqual(existingVal, val)) {
1686
+ if (!deepEqual(existingVal, val)) {
1553
1687
  throw new ShapeError(
1554
1688
  `Conflicting forced where values for "${field}.${op}": shape defines both ${safeStringify(existingVal)} and ${safeStringify(val)}`
1555
1689
  );
@@ -1559,7 +1693,7 @@ function mergeScalarConditions(target, source) {
1559
1693
  Object.assign(existing, ops);
1560
1694
  continue;
1561
1695
  }
1562
- if (!forcedValuesEqual(existing, ops)) {
1696
+ if (!deepEqual(existing, ops)) {
1563
1697
  throw new ShapeError(`Conflicting forced where values for "${field}"`);
1564
1698
  }
1565
1699
  }
@@ -1650,27 +1784,27 @@ function createWhereBuilder(typeMap, enumMap, scalarBase, uniqueMap = {}) {
1650
1784
  scalarConditions
1651
1785
  );
1652
1786
  }
1653
- for (const key of Object.keys(scalarConditions)) {
1787
+ const forcedOnlyKeys = /* @__PURE__ */ new Set();
1788
+ for (const key of Object.keys(whereConfig)) {
1654
1789
  if (COMBINATOR_KEYS.has(key))
1655
1790
  continue;
1656
1791
  if (!(key in fieldSchemas)) {
1657
- fieldSchemas[key] = import_zod4.z.object({}).strict().optional();
1792
+ forcedOnlyKeys.add(key);
1658
1793
  }
1659
1794
  }
1660
- for (const key of Object.keys(relationForced)) {
1795
+ for (const key of Object.keys(scalarConditions)) {
1796
+ if (COMBINATOR_KEYS.has(key))
1797
+ continue;
1661
1798
  if (!(key in fieldSchemas)) {
1662
- fieldSchemas[key] = import_zod4.z.object({}).strict().optional();
1799
+ fieldSchemas[key] = import_zod5.z.object({}).strict().optional();
1663
1800
  }
1664
1801
  }
1665
- const schema = Object.keys(fieldSchemas).length > 0 ? import_zod4.z.object(fieldSchemas).strict().optional() : null;
1666
- const forcedOnlyKeys = /* @__PURE__ */ new Set();
1667
- for (const key of Object.keys(whereConfig)) {
1668
- if (COMBINATOR_KEYS.has(key))
1669
- continue;
1802
+ for (const key of Object.keys(relationForced)) {
1670
1803
  if (!(key in fieldSchemas)) {
1671
- forcedOnlyKeys.add(key);
1804
+ fieldSchemas[key] = import_zod5.z.object({}).strict().optional();
1672
1805
  }
1673
1806
  }
1807
+ const schema = Object.keys(fieldSchemas).length > 0 ? import_zod5.z.object(fieldSchemas).strict().optional() : null;
1674
1808
  return {
1675
1809
  schema,
1676
1810
  forced: {
@@ -1701,12 +1835,12 @@ function createWhereBuilder(typeMap, enumMap, scalarBase, uniqueMap = {}) {
1701
1835
  );
1702
1836
  }
1703
1837
  if (key === "NOT") {
1704
- fieldSchemas[key] = import_zod4.z.union([
1838
+ fieldSchemas[key] = import_zod5.z.union([
1705
1839
  elementSchema,
1706
- import_zod4.z.preprocess(coerceToArray, import_zod4.z.array(elementSchema).min(1))
1840
+ import_zod5.z.preprocess(coerceToArray, import_zod5.z.array(elementSchema).min(1))
1707
1841
  ]).optional();
1708
1842
  } else {
1709
- fieldSchemas[key] = import_zod4.z.preprocess(coerceToArray, import_zod4.z.array(elementSchema).min(1)).optional();
1843
+ fieldSchemas[key] = import_zod5.z.preprocess(coerceToArray, import_zod5.z.array(elementSchema).min(1)).optional();
1710
1844
  }
1711
1845
  }
1712
1846
  if (hasWhereForced(result.forced)) {
@@ -1775,6 +1909,11 @@ function createWhereBuilder(typeMap, enumMap, scalarBase, uniqueMap = {}) {
1775
1909
  `Empty nested where for relation "${key}.${op}" on model "${model}". Define at least one field.`
1776
1910
  );
1777
1911
  }
1912
+ if (NEGATIVE_RELATION_OPS.has(op) && nested.schema && hasWhereForced(nested.forced)) {
1913
+ throw new ShapeError(
1914
+ `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.`
1915
+ );
1916
+ }
1778
1917
  if (nested.schema) {
1779
1918
  if (!hasWhereForced(nested.forced)) {
1780
1919
  opSchemas[op] = nested.schema.refine(
@@ -1799,7 +1938,7 @@ function createWhereBuilder(typeMap, enumMap, scalarBase, uniqueMap = {}) {
1799
1938
  }
1800
1939
  if (hasClientOps) {
1801
1940
  const clientOpKeys = Object.keys(opSchemas);
1802
- const opObjSchema = import_zod4.z.object(opSchemas).strict();
1941
+ const opObjSchema = import_zod5.z.object(opSchemas).strict();
1803
1942
  if (Object.keys(opForced).length === 0 && !hasForcedNull) {
1804
1943
  fieldSchemas[key] = opObjSchema.refine(
1805
1944
  (v) => clientOpKeys.some(
@@ -1885,10 +2024,10 @@ function createWhereBuilder(typeMap, enumMap, scalarBase, uniqueMap = {}) {
1885
2024
  );
1886
2025
  }
1887
2026
  if (modeConfigValue === true) {
1888
- opSchemas.mode = import_zod4.z.enum(["default", "insensitive"]).optional();
2027
+ opSchemas.mode = import_zod5.z.enum(["default", "insensitive"]).optional();
1889
2028
  } else {
1890
2029
  const actualModeValue = isForcedValue(modeConfigValue) ? modeConfigValue.value : modeConfigValue;
1891
- const modeSchema = import_zod4.z.enum(["default", "insensitive"]);
2030
+ const modeSchema = import_zod5.z.enum(["default", "insensitive"]);
1892
2031
  let parsed;
1893
2032
  try {
1894
2033
  parsed = modeSchema.parse(actualModeValue);
@@ -1900,10 +2039,10 @@ function createWhereBuilder(typeMap, enumMap, scalarBase, uniqueMap = {}) {
1900
2039
  fieldForced.mode = parsed;
1901
2040
  }
1902
2041
  } else if (hasModeCompatibleOp) {
1903
- opSchemas.mode = import_zod4.z.enum(["default", "insensitive"]).optional();
2042
+ opSchemas.mode = import_zod5.z.enum(["default", "insensitive"]).optional();
1904
2043
  }
1905
2044
  if (hasClientOps) {
1906
- const opObj = import_zod4.z.object(opSchemas).strict();
2045
+ const opObj = import_zod5.z.object(opSchemas).strict();
1907
2046
  const refined = opObj.refine(
1908
2047
  (v) => clientOpKeys.some(
1909
2048
  (k) => v[k] !== void 0
@@ -1919,7 +2058,7 @@ function createWhereBuilder(typeMap, enumMap, scalarBase, uniqueMap = {}) {
1919
2058
  enumMap,
1920
2059
  scalarBase
1921
2060
  );
1922
- fieldSchemas[fieldName] = import_zod4.z.union([refined, equalsBase]).optional();
2061
+ fieldSchemas[fieldName] = import_zod5.z.union([refined, equalsBase]).optional();
1923
2062
  } else {
1924
2063
  fieldSchemas[fieldName] = refined.optional();
1925
2064
  }
@@ -1933,15 +2072,8 @@ function createWhereBuilder(typeMap, enumMap, scalarBase, uniqueMap = {}) {
1933
2072
  (constraint) => constraint.selector === selector
1934
2073
  ) ?? null;
1935
2074
  }
1936
- function buildDirectUniqueSchema(fieldMeta) {
1937
- const base = createBaseType(fieldMeta, enumMap, scalarBase);
1938
- if (!fieldMeta.isEnum && !fieldMeta.isRelation && !fieldMeta.isUnsupported) {
1939
- return wrapWithInputCoercion(fieldMeta.type, fieldMeta.isList, base);
1940
- }
1941
- return base;
1942
- }
1943
2075
  function parseForcedUniqueValue(model, fieldName, fieldMeta, value) {
1944
- const schema = buildDirectUniqueSchema(fieldMeta);
2076
+ const schema = buildDirectScalarSchema(fieldMeta, enumMap, scalarBase);
1945
2077
  const actual = isForcedValue(value) ? value.value : value;
1946
2078
  try {
1947
2079
  return schema.parse(actual);
@@ -2019,7 +2151,11 @@ function createWhereBuilder(typeMap, enumMap, scalarBase, uniqueMap = {}) {
2019
2151
  `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.`
2020
2152
  );
2021
2153
  }
2022
- const directSchema2 = buildDirectUniqueSchema(fieldMeta2);
2154
+ const directSchema2 = buildDirectScalarSchema(
2155
+ fieldMeta2,
2156
+ enumMap,
2157
+ scalarBase
2158
+ );
2023
2159
  if (fieldValue === true) {
2024
2160
  nestedSchemas[fieldName] = directSchema2;
2025
2161
  } else {
@@ -2032,7 +2168,7 @@ function createWhereBuilder(typeMap, enumMap, scalarBase, uniqueMap = {}) {
2032
2168
  }
2033
2169
  }
2034
2170
  if (Object.keys(nestedSchemas).length > 0) {
2035
- fieldSchemas[key] = import_zod4.z.object(nestedSchemas).strict();
2171
+ fieldSchemas[key] = import_zod5.z.object(nestedSchemas).strict();
2036
2172
  }
2037
2173
  if (Object.keys(forcedCompound).length > 0) {
2038
2174
  forcedConditions[key] = forcedCompound;
@@ -2066,7 +2202,7 @@ function createWhereBuilder(typeMap, enumMap, scalarBase, uniqueMap = {}) {
2066
2202
  `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 }.`
2067
2203
  );
2068
2204
  }
2069
- const directSchema = buildDirectUniqueSchema(fieldMeta);
2205
+ const directSchema = buildDirectScalarSchema(fieldMeta, enumMap, scalarBase);
2070
2206
  if (value === true) {
2071
2207
  fieldSchemas[key] = directSchema;
2072
2208
  continue;
@@ -2080,7 +2216,7 @@ function createWhereBuilder(typeMap, enumMap, scalarBase, uniqueMap = {}) {
2080
2216
  forcedOnlyKeys.add(key);
2081
2217
  }
2082
2218
  return {
2083
- schema: Object.keys(fieldSchemas).length > 0 ? import_zod4.z.object(fieldSchemas).strict() : null,
2219
+ schema: Object.keys(fieldSchemas).length > 0 ? import_zod5.z.object(fieldSchemas).strict() : null,
2084
2220
  forced: {
2085
2221
  conditions: forcedConditions,
2086
2222
  relations: {}
@@ -2092,31 +2228,13 @@ function createWhereBuilder(typeMap, enumMap, scalarBase, uniqueMap = {}) {
2092
2228
  }
2093
2229
 
2094
2230
  // src/runtime/query-builder-args.ts
2095
- var import_zod5 = require("zod");
2231
+ var import_zod6 = require("zod");
2096
2232
  var UNSUPPORTED_BY_TYPES = /* @__PURE__ */ new Set(["Json", "Bytes"]);
2097
- function requireConfigTrue(config, context) {
2098
- for (const [key, value] of Object.entries(config)) {
2099
- if (value !== true) {
2100
- throw new ShapeError(
2101
- `Config value for "${key}" in ${context} must be true, got ${typeof value}`
2102
- );
2103
- }
2104
- }
2105
- }
2106
- function isPlainRecord(value) {
2107
- return value !== null && typeof value === "object" && !Array.isArray(value);
2108
- }
2109
- function formatUniqueConstraint2(constraint) {
2110
- return constraint.fields.length === 1 ? constraint.selector : `${constraint.selector}(${constraint.fields.join(", ")})`;
2111
- }
2112
- function formatUniqueConstraints2(constraints) {
2113
- return constraints.map(formatUniqueConstraint2).join(" | ");
2114
- }
2115
2233
  function createArgsBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
2116
- const sortEnum = import_zod5.z.enum(["asc", "desc"]);
2117
- const nullsEnum = import_zod5.z.enum(["first", "last"]);
2118
- const sortWithNulls = import_zod5.z.object({ sort: sortEnum, nulls: nullsEnum.optional() }).strict();
2119
- const scalarOrderSchema = import_zod5.z.union([sortEnum, sortWithNulls]);
2234
+ const sortEnum = import_zod6.z.enum(["asc", "desc"]);
2235
+ const nullsEnum = import_zod6.z.enum(["first", "last"]);
2236
+ const sortWithNulls = import_zod6.z.object({ sort: sortEnum, nulls: nullsEnum.optional() }).strict();
2237
+ const scalarOrderSchema = import_zod6.z.union([sortEnum, sortWithNulls]);
2120
2238
  function validateScalarOrderByField(fieldName, model, modelFields) {
2121
2239
  const fieldMeta = modelFields[fieldName];
2122
2240
  if (!fieldMeta)
@@ -2135,6 +2253,16 @@ function createArgsBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
2135
2253
  );
2136
2254
  }
2137
2255
  function buildOrderBySchema(model, orderByConfig) {
2256
+ if (!isPlainObject(orderByConfig)) {
2257
+ throw new ShapeError(
2258
+ `orderBy shape config on model "${model}" must be an object of fields`
2259
+ );
2260
+ }
2261
+ if (Object.keys(orderByConfig).length === 0) {
2262
+ throw new ShapeError(
2263
+ `Empty orderBy config on model "${model}". Define at least one field.`
2264
+ );
2265
+ }
2138
2266
  const modelFields = typeMap[model];
2139
2267
  if (!modelFields)
2140
2268
  throw new ShapeError(`Unknown model: ${model}`);
@@ -2150,53 +2278,35 @@ function createArgsBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
2150
2278
  fieldSchemas[fieldName] = scalarOrderSchema.optional();
2151
2279
  continue;
2152
2280
  }
2153
- if (!isPlainRecord(config)) {
2281
+ if (!isPlainObject(config)) {
2154
2282
  throw new ShapeError(
2155
- `orderBy config for "${fieldName}" on model "${model}" must be true or a relation aggregate object`
2283
+ `orderBy config for "${fieldName}" on model "${model}" must be true or a relation config object`
2156
2284
  );
2157
2285
  }
2158
2286
  if (!fieldMeta.isRelation) {
2159
- const allowedOps = getSupportedOperators(
2160
- fieldMeta.type,
2161
- fieldMeta.isList
2287
+ throw new ShapeError(
2288
+ `orderBy config for scalar field "${model}.${fieldName}" must be true. Operator objects are not valid in orderBy.`
2162
2289
  );
2163
- const opSchemas = {};
2164
- for (const [op, enabled] of Object.entries(config)) {
2165
- if (enabled !== true) {
2166
- throw new ShapeError(
2167
- `orderBy operator config for "${model}.${fieldName}.${op}" must be true`
2168
- );
2169
- }
2170
- if (!allowedOps.includes(op)) {
2171
- throw new ShapeError(
2172
- `Operator "${op}" not supported for orderBy field "${model}.${fieldName}"`
2173
- );
2174
- }
2175
- opSchemas[op] = scalarOrderSchema.optional();
2176
- }
2177
- const opKeys = Object.keys(opSchemas);
2178
- fieldSchemas[fieldName] = import_zod5.z.object(opSchemas).strict().refine(
2179
- (v) => opKeys.some(
2180
- (k) => v[k] !== void 0
2181
- ),
2182
- {
2183
- message: `orderBy field "${fieldName}" must specify at least one operator`
2184
- }
2185
- ).optional();
2186
- continue;
2187
2290
  }
2188
2291
  if (fieldMeta.isList) {
2189
- if (!("_count" in config)) {
2292
+ const configKeys = Object.keys(config);
2293
+ if (!configKeys.includes("_count")) {
2190
2294
  throw new ShapeError(
2191
2295
  `To-many relation orderBy "${fieldName}" only supports _count`
2192
2296
  );
2193
2297
  }
2298
+ const extraKeys = configKeys.filter((k) => k !== "_count");
2299
+ if (extraKeys.length > 0) {
2300
+ throw new ShapeError(
2301
+ `To-many relation orderBy "${fieldName}" only supports _count. Unexpected keys: ${extraKeys.join(", ")}`
2302
+ );
2303
+ }
2194
2304
  if (config._count !== true) {
2195
2305
  throw new ShapeError(
2196
2306
  `orderBy relation aggregate "${fieldName}._count" must be true`
2197
2307
  );
2198
2308
  }
2199
- fieldSchemas[fieldName] = import_zod5.z.object({
2309
+ fieldSchemas[fieldName] = import_zod6.z.object({
2200
2310
  _count: sortEnum.optional()
2201
2311
  }).strict().optional();
2202
2312
  continue;
@@ -2207,17 +2317,11 @@ function createArgsBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
2207
2317
  );
2208
2318
  fieldSchemas[fieldName] = nested;
2209
2319
  }
2210
- const fieldKeys = Object.keys(fieldSchemas);
2211
- const singleSchema = import_zod5.z.object(fieldSchemas).strict().refine(
2212
- (v) => fieldKeys.some(
2213
- (k) => v[k] !== void 0
2214
- ),
2215
- { message: "orderBy must specify at least one field" }
2320
+ const singleSchema = strictObjectRequiringOne(
2321
+ fieldSchemas,
2322
+ "orderBy must specify at least one field"
2216
2323
  );
2217
- return import_zod5.z.union([
2218
- singleSchema,
2219
- import_zod5.z.preprocess(coerceToArray, import_zod5.z.array(singleSchema).min(1))
2220
- ]).optional();
2324
+ return singleOrArraySchema(singleSchema).optional();
2221
2325
  }
2222
2326
  function buildTakeSchema(config) {
2223
2327
  if (typeof config === "number") {
@@ -2227,7 +2331,7 @@ function createArgsBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
2227
2331
  if (config <= 0) {
2228
2332
  throw new ShapeError("take must be a positive integer");
2229
2333
  }
2230
- return import_zod5.z.literal(config).optional();
2334
+ return import_zod6.z.number().int().min(1).max(config).default(config);
2231
2335
  }
2232
2336
  if (!config || typeof config !== "object" || Array.isArray(config)) {
2233
2337
  throw new ShapeError("take config must be a number or { max, default? }");
@@ -2252,9 +2356,9 @@ function createArgsBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
2252
2356
  if (config.default > config.max) {
2253
2357
  throw new ShapeError("take.default cannot exceed take.max");
2254
2358
  }
2255
- return import_zod5.z.number().int().min(1).max(config.max).default(config.default);
2359
+ return import_zod6.z.number().int().min(1).max(config.max).default(config.default);
2256
2360
  }
2257
- return import_zod5.z.number().int().min(1).max(config.max).optional();
2361
+ return import_zod6.z.number().int().min(1).max(config.max).optional();
2258
2362
  }
2259
2363
  function buildCursorFieldSchema(model, fieldName) {
2260
2364
  const modelFields = typeMap[model];
@@ -2276,11 +2380,7 @@ function createArgsBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
2276
2380
  `List field "${fieldName}" cannot be used in cursor`
2277
2381
  );
2278
2382
  }
2279
- const base = createBaseType(fieldMeta, enumMap, scalarBase);
2280
- if (!fieldMeta.isEnum && !fieldMeta.isRelation && !fieldMeta.isUnsupported) {
2281
- return wrapWithInputCoercion(fieldMeta.type, fieldMeta.isList, base);
2282
- }
2283
- return base;
2383
+ return buildDirectScalarSchema(fieldMeta, enumMap, scalarBase);
2284
2384
  }
2285
2385
  function cursorConfigMatchesConstraint(cursorConfig, constraint) {
2286
2386
  if (!(constraint.selector in cursorConfig))
@@ -2289,66 +2389,55 @@ function createArgsBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
2289
2389
  if (constraint.fields.length === 1) {
2290
2390
  return value === true;
2291
2391
  }
2292
- if (!isPlainRecord(value))
2392
+ if (!isPlainObject(value))
2293
2393
  return false;
2294
2394
  const keys = Object.keys(value);
2295
2395
  if (keys.length !== constraint.fields.length)
2296
2396
  return false;
2297
2397
  return constraint.fields.every((field) => value[field] === true);
2298
2398
  }
2299
- function getUniqueConstraints(model) {
2300
- const constraints = uniqueMap[model];
2301
- if (constraints && constraints.length > 0) {
2302
- return constraints;
2303
- }
2304
- const modelFields = typeMap[model];
2305
- if (!modelFields) {
2306
- throw new ShapeError(`Unknown model: ${model}`);
2307
- }
2308
- const inferred = [];
2309
- for (const [fieldName, fieldMeta] of Object.entries(modelFields)) {
2310
- if (fieldMeta.isRelation)
2311
- continue;
2312
- if (fieldMeta.isId || fieldMeta.isUnique) {
2313
- inferred.push({
2314
- selector: fieldName,
2315
- fields: [fieldName]
2316
- });
2317
- }
2318
- }
2319
- return inferred;
2320
- }
2321
2399
  function buildCursorSchema(model, cursorConfig) {
2322
- const constraints = getUniqueConstraints(model);
2400
+ const constraints = uniqueMap[model] ?? [];
2323
2401
  if (constraints.length === 0) {
2324
2402
  throw new ShapeError(
2325
2403
  `cursor on model "${model}" requires at least one unique constraint`
2326
2404
  );
2327
2405
  }
2328
- const matching = constraints.find(
2406
+ const matching = constraints.filter(
2329
2407
  (constraint) => cursorConfigMatchesConstraint(cursorConfig, constraint)
2330
2408
  );
2331
- if (!matching) {
2409
+ if (matching.length === 0) {
2332
2410
  throw new ShapeError(
2333
- `cursor on model "${model}" must exactly match a unique selector: ${formatUniqueConstraints2(constraints)}`
2411
+ `cursor on model "${model}" must match a unique selector: ${formatUniqueConstraints(constraints)}`
2334
2412
  );
2335
2413
  }
2414
+ const coveredKeys = new Set(matching.map((c) => c.selector));
2415
+ for (const key of Object.keys(cursorConfig)) {
2416
+ if (!coveredKeys.has(key)) {
2417
+ throw new ShapeError(
2418
+ `cursor field "${key}" on model "${model}" does not match any unique selector. Unique selectors: ${formatUniqueConstraints(constraints)}`
2419
+ );
2420
+ }
2421
+ }
2336
2422
  const fieldSchemas = {};
2337
- if (matching.fields.length === 1) {
2338
- fieldSchemas[matching.selector] = buildCursorFieldSchema(
2339
- model,
2340
- matching.fields[0]
2341
- ).optional();
2342
- } else {
2343
- const nestedSchemas = {};
2344
- for (const field of matching.fields) {
2345
- nestedSchemas[field] = buildCursorFieldSchema(model, field);
2423
+ for (const constraint of matching) {
2424
+ if (constraint.fields.length === 1) {
2425
+ fieldSchemas[constraint.selector] = buildCursorFieldSchema(
2426
+ model,
2427
+ constraint.fields[0]
2428
+ ).optional();
2429
+ } else {
2430
+ const nestedSchemas = {};
2431
+ for (const field of constraint.fields) {
2432
+ nestedSchemas[field] = buildCursorFieldSchema(model, field);
2433
+ }
2434
+ fieldSchemas[constraint.selector] = import_zod6.z.object(nestedSchemas).strict().optional();
2346
2435
  }
2347
- fieldSchemas[matching.selector] = import_zod5.z.object(nestedSchemas).strict().optional();
2348
2436
  }
2349
- return import_zod5.z.object(fieldSchemas).strict().refine(
2350
- (v) => v[matching.selector] !== void 0,
2351
- { message: `cursor must specify "${matching.selector}"` }
2437
+ const selectorKeys = matching.map((c) => c.selector);
2438
+ return strictObjectRequiringOne(
2439
+ fieldSchemas,
2440
+ `cursor must specify one of: ${selectorKeys.join(", ")}`
2352
2441
  ).optional();
2353
2442
  }
2354
2443
  function buildDistinctSchema(model, distinctConfig) {
@@ -2373,10 +2462,8 @@ function createArgsBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
2373
2462
  );
2374
2463
  allowedFields.add(fieldName);
2375
2464
  }
2376
- return import_zod5.z.union([
2377
- import_zod5.z.enum([...allowedFields]),
2378
- import_zod5.z.array(import_zod5.z.enum([...allowedFields])).min(1)
2379
- ]).optional();
2465
+ const fieldEnum = import_zod6.z.enum([...allowedFields]);
2466
+ return import_zod6.z.union([fieldEnum, import_zod6.z.array(fieldEnum).min(1)]).optional();
2380
2467
  }
2381
2468
  function buildBySchema(model, byConfig) {
2382
2469
  const modelFields = typeMap[model];
@@ -2409,7 +2496,7 @@ function createArgsBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
2409
2496
  }
2410
2497
  allowedFields.add(fieldName);
2411
2498
  }
2412
- return import_zod5.z.array(import_zod5.z.enum([...allowedFields])).min(1);
2499
+ return import_zod6.z.array(import_zod6.z.enum([...allowedFields])).min(1);
2413
2500
  }
2414
2501
  function buildHavingSchema(model, havingConfig) {
2415
2502
  const modelFields = typeMap[model];
@@ -2450,22 +2537,21 @@ function createArgsBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
2450
2537
  ).optional();
2451
2538
  }
2452
2539
  if (fieldMeta.type === "String") {
2453
- opSchemas.mode = import_zod5.z.enum(["default", "insensitive"]).optional();
2540
+ opSchemas.mode = import_zod6.z.enum(["default", "insensitive"]).optional();
2454
2541
  }
2455
2542
  const opKeys = Object.keys(opSchemas).filter((key) => key !== "mode");
2456
- fieldSchemas[fieldName] = import_zod5.z.object(opSchemas).strict().refine(
2543
+ const opShape = { ...opSchemas };
2544
+ const opObjSchema = import_zod6.z.object(opShape).strict().refine(
2457
2545
  (v) => opKeys.some((k) => v[k] !== void 0),
2458
2546
  {
2459
2547
  message: `having field "${fieldName}" must specify at least one operator`
2460
2548
  }
2461
- ).optional();
2549
+ );
2550
+ fieldSchemas[fieldName] = opObjSchema.optional();
2462
2551
  }
2463
- const fieldKeys = Object.keys(fieldSchemas);
2464
- return import_zod5.z.object(fieldSchemas).strict().refine(
2465
- (v) => fieldKeys.some(
2466
- (k) => v[k] !== void 0
2467
- ),
2468
- { message: "having must specify at least one field" }
2552
+ return strictObjectRequiringOne(
2553
+ fieldSchemas,
2554
+ "having must specify at least one field"
2469
2555
  ).optional();
2470
2556
  }
2471
2557
  function buildAggregateFieldSchema(model, op, config) {
@@ -2474,47 +2560,45 @@ function createArgsBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
2474
2560
  throw new ShapeError(`Unknown model: ${model}`);
2475
2561
  requireConfigTrue(config, `${op} on model "${model}"`);
2476
2562
  const allowedTypes = op === "_avg" || op === "_sum" ? NUMERIC_TYPES : COMPARABLE_TYPES;
2477
- const fieldSchemas = {};
2478
- for (const fieldName of Object.keys(config)) {
2479
- const fieldMeta = modelFields[fieldName];
2480
- if (!fieldMeta)
2481
- throw new ShapeError(
2482
- `Unknown field "${fieldName}" on model "${model}" in ${op}`
2483
- );
2484
- if (fieldMeta.isRelation)
2485
- throw new ShapeError(
2486
- `Relation field "${fieldName}" cannot be used in ${op}`
2487
- );
2488
- if (fieldMeta.isList)
2489
- throw new ShapeError(
2490
- `List field "${fieldName}" cannot be used in ${op}`
2491
- );
2492
- if (!allowedTypes.has(fieldMeta.type)) {
2493
- throw new ShapeError(
2494
- `Field "${fieldName}" of type "${fieldMeta.type}" cannot be used in ${op}`
2495
- );
2563
+ return buildLiteralTrueSchema(
2564
+ Object.keys(config),
2565
+ `${op} must specify at least one field`,
2566
+ (fieldName) => {
2567
+ const fieldMeta = modelFields[fieldName];
2568
+ if (!fieldMeta)
2569
+ throw new ShapeError(
2570
+ `Unknown field "${fieldName}" on model "${model}" in ${op}`
2571
+ );
2572
+ if (fieldMeta.isRelation)
2573
+ throw new ShapeError(
2574
+ `Relation field "${fieldName}" cannot be used in ${op}`
2575
+ );
2576
+ if (fieldMeta.isList)
2577
+ throw new ShapeError(
2578
+ `List field "${fieldName}" cannot be used in ${op}`
2579
+ );
2580
+ if (!allowedTypes.has(fieldMeta.type)) {
2581
+ throw new ShapeError(
2582
+ `Field "${fieldName}" of type "${fieldMeta.type}" cannot be used in ${op}`
2583
+ );
2584
+ }
2496
2585
  }
2497
- fieldSchemas[fieldName] = import_zod5.z.literal(true).optional();
2498
- }
2499
- const aggregateFieldKeys = Object.keys(fieldSchemas);
2500
- return import_zod5.z.object(fieldSchemas).strict().refine(
2501
- (v) => aggregateFieldKeys.some(
2502
- (k) => v[k] !== void 0
2503
- ),
2504
- { message: `${op} must specify at least one field` }
2505
- ).optional();
2586
+ );
2506
2587
  }
2507
2588
  function buildCountFieldSchema(model, config, context) {
2508
2589
  if (config === true) {
2509
- return import_zod5.z.literal(true).optional();
2590
+ return import_zod6.z.literal(true).optional();
2510
2591
  }
2511
2592
  const modelFields = typeMap[model];
2512
2593
  if (!modelFields)
2513
2594
  throw new ShapeError(`Unknown model: ${model}`);
2514
2595
  requireConfigTrue(config, `${context} on model "${model}"`);
2515
- const fieldSchemas = {};
2516
- for (const fieldName of Object.keys(config)) {
2517
- if (fieldName !== "_all") {
2596
+ return buildLiteralTrueSchema(
2597
+ Object.keys(config),
2598
+ `${context} must specify at least one field`,
2599
+ (fieldName) => {
2600
+ if (fieldName === "_all")
2601
+ return;
2518
2602
  const fieldMeta = modelFields[fieldName];
2519
2603
  if (!fieldMeta)
2520
2604
  throw new ShapeError(
@@ -2525,45 +2609,30 @@ function createArgsBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
2525
2609
  `Relation field "${fieldName}" cannot be used in ${context}`
2526
2610
  );
2527
2611
  }
2528
- fieldSchemas[fieldName] = import_zod5.z.literal(true).optional();
2529
- }
2530
- const countFieldKeys = Object.keys(fieldSchemas);
2531
- return import_zod5.z.object(fieldSchemas).strict().refine(
2532
- (v) => countFieldKeys.some(
2533
- (k) => v[k] !== void 0
2534
- ),
2535
- { message: `${context} must specify at least one field` }
2536
- ).optional();
2612
+ );
2537
2613
  }
2538
2614
  function buildCountSelectSchema(model, selectConfig) {
2539
2615
  const modelFields = typeMap[model];
2540
2616
  if (!modelFields)
2541
2617
  throw new ShapeError(`Unknown model: ${model}`);
2542
2618
  requireConfigTrue(selectConfig, `count select on model "${model}"`);
2543
- const fieldSchemas = {};
2544
- for (const fieldName of Object.keys(selectConfig)) {
2545
- if (fieldName === "_all") {
2546
- fieldSchemas._all = import_zod5.z.literal(true).optional();
2547
- continue;
2619
+ return buildLiteralTrueSchema(
2620
+ Object.keys(selectConfig),
2621
+ "count select must specify at least one field",
2622
+ (fieldName) => {
2623
+ if (fieldName === "_all")
2624
+ return;
2625
+ const fieldMeta = modelFields[fieldName];
2626
+ if (!fieldMeta)
2627
+ throw new ShapeError(
2628
+ `Unknown field "${fieldName}" on model "${model}" in count select`
2629
+ );
2630
+ if (fieldMeta.isRelation)
2631
+ throw new ShapeError(
2632
+ `Relation field "${fieldName}" cannot be used in count select`
2633
+ );
2548
2634
  }
2549
- const fieldMeta = modelFields[fieldName];
2550
- if (!fieldMeta)
2551
- throw new ShapeError(
2552
- `Unknown field "${fieldName}" on model "${model}" in count select`
2553
- );
2554
- if (fieldMeta.isRelation)
2555
- throw new ShapeError(
2556
- `Relation field "${fieldName}" cannot be used in count select`
2557
- );
2558
- fieldSchemas[fieldName] = import_zod5.z.literal(true).optional();
2559
- }
2560
- const countSelectKeys = Object.keys(fieldSchemas);
2561
- return import_zod5.z.object(fieldSchemas).strict().refine(
2562
- (v) => countSelectKeys.some(
2563
- (k) => v[k] !== void 0
2564
- ),
2565
- { message: "count select must specify at least one field" }
2566
- ).optional();
2635
+ );
2567
2636
  }
2568
2637
  return {
2569
2638
  buildOrderBySchema,
@@ -2579,25 +2648,64 @@ function createArgsBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
2579
2648
  }
2580
2649
 
2581
2650
  // src/runtime/query-builder-projection.ts
2582
- var import_zod6 = require("zod");
2583
- var KNOWN_NESTED_INCLUDE_KEYS = /* @__PURE__ */ new Set([
2584
- "where",
2585
- "include",
2586
- "select",
2587
- "orderBy",
2588
- "cursor",
2589
- "take",
2590
- "skip"
2591
- ]);
2592
- var KNOWN_NESTED_SELECT_KEYS = /* @__PURE__ */ new Set([
2593
- "select",
2594
- "include",
2595
- "where",
2596
- "orderBy",
2597
- "cursor",
2598
- "take",
2599
- "skip"
2600
- ]);
2651
+ var import_zod7 = require("zod");
2652
+
2653
+ // src/shared/projection-defaults.ts
2654
+ function buildDefaultProjectionInput(config) {
2655
+ const result = {};
2656
+ for (const [key, value] of Object.entries(config)) {
2657
+ if (key === "_count") {
2658
+ result[key] = buildDefaultCountInput(
2659
+ value
2660
+ );
2661
+ continue;
2662
+ }
2663
+ if (value === true) {
2664
+ result[key] = true;
2665
+ } else {
2666
+ result[key] = buildRelationArgsSkeleton(value);
2667
+ }
2668
+ }
2669
+ return result;
2670
+ }
2671
+ function buildRelationArgsSkeleton(config) {
2672
+ const skeleton = {};
2673
+ if (config.select) {
2674
+ skeleton.select = buildDefaultProjectionInput(config.select);
2675
+ }
2676
+ if (config.include) {
2677
+ skeleton.include = buildDefaultProjectionInput(config.include);
2678
+ }
2679
+ return skeleton;
2680
+ }
2681
+ function buildDefaultCountInput(config) {
2682
+ if (config === true)
2683
+ return true;
2684
+ if (!isPlainObject(config) || !config.select || !isPlainObject(config.select)) {
2685
+ return true;
2686
+ }
2687
+ const selectObj = config.select;
2688
+ const result = {};
2689
+ for (const key of Object.keys(selectObj)) {
2690
+ result[key] = true;
2691
+ }
2692
+ return { select: result };
2693
+ }
2694
+ function buildDefaultProjectionBody(shape) {
2695
+ if (shape.select) {
2696
+ return { select: buildDefaultProjectionInput(shape.select) };
2697
+ }
2698
+ if (shape.include) {
2699
+ return { include: buildDefaultProjectionInput(shape.include) };
2700
+ }
2701
+ return {};
2702
+ }
2703
+
2704
+ // src/runtime/query-builder-projection.ts
2705
+ var KNOWN_NESTED_KEYS = {
2706
+ include: /* @__PURE__ */ new Set(["where", "include", "select", "orderBy", "cursor", "take", "skip"]),
2707
+ select: /* @__PURE__ */ new Set(["select", "include", "where", "orderBy", "cursor", "take", "skip"])
2708
+ };
2601
2709
  var KNOWN_COUNT_SELECT_ENTRY_KEYS = /* @__PURE__ */ new Set(["where"]);
2602
2710
  var MAX_PROJECTION_DEPTH = 10;
2603
2711
  function validateNestedKeys(keys, allowed, context) {
@@ -2609,13 +2717,25 @@ function validateNestedKeys(keys, allowed, context) {
2609
2717
  }
2610
2718
  }
2611
2719
  }
2612
- function createProjectionBuilder(typeMap, enumMap, deps) {
2720
+ function hasDefinedKeys(v) {
2721
+ return Object.values(v).some((value) => value !== void 0);
2722
+ }
2723
+ function wrapRelationSchema(nestedObj, skeleton) {
2724
+ const collapsed = nestedObj.transform(
2725
+ (v) => isPlainObject(v) && !hasDefinedKeys(v) ? true : v
2726
+ );
2727
+ return import_zod7.z.preprocess(
2728
+ (v) => v === true ? deepClone(skeleton) : v,
2729
+ collapsed
2730
+ );
2731
+ }
2732
+ function createProjectionBuilder(typeMap, _enumMap, deps) {
2613
2733
  function buildIncludeCountSchema(model, config) {
2614
2734
  const modelFields = typeMap[model];
2615
2735
  if (!modelFields)
2616
2736
  throw new ShapeError(`Unknown model: ${model}`);
2617
2737
  if (config === true) {
2618
- return { schema: import_zod6.z.literal(true).optional(), forcedCountWhere: {} };
2738
+ return { schema: import_zod7.z.literal(true).optional(), forcedCountWhere: {} };
2619
2739
  }
2620
2740
  if (!isPlainObject(config) || !("select" in config)) {
2621
2741
  throw new ShapeError(
@@ -2651,273 +2771,175 @@ function createProjectionBuilder(typeMap, enumMap, deps) {
2651
2771
  if (!fieldMeta.isList)
2652
2772
  throw new ShapeError(`Field "${fieldName}" is a to-one relation on model "${model}" in _count.select. Only to-many relations support _count.`);
2653
2773
  if (fieldConfig === true) {
2654
- countSelectFields[fieldName] = import_zod6.z.literal(true).optional();
2655
- } else if (isPlainObject(fieldConfig)) {
2656
- if (Object.keys(fieldConfig).length === 0) {
2657
- throw new ShapeError(
2658
- `Empty config for _count.select.${fieldName} on model "${model}". Use true or { where: { ... } }.`
2659
- );
2660
- }
2661
- validateNestedKeys(
2662
- Object.keys(fieldConfig),
2663
- KNOWN_COUNT_SELECT_ENTRY_KEYS,
2664
- `_count.select.${fieldName} on model "${model}"`
2665
- );
2666
- if (fieldConfig.where) {
2667
- const relatedType = fieldMeta.type;
2668
- const { schema: whereSchema, forced } = deps.buildWhereSchema(
2669
- relatedType,
2670
- fieldConfig.where
2671
- );
2672
- const nestedSchemas = {};
2673
- if (whereSchema)
2674
- nestedSchemas["where"] = whereSchema;
2675
- const nestedObj = import_zod6.z.object(nestedSchemas).strict();
2676
- countSelectFields[fieldName] = import_zod6.z.union([import_zod6.z.literal(true), nestedObj]).optional();
2677
- if (hasWhereForced(forced)) {
2678
- forcedCountWhere[fieldName] = forced;
2679
- }
2680
- } else {
2681
- countSelectFields[fieldName] = import_zod6.z.literal(true).optional();
2682
- }
2683
- } else {
2774
+ countSelectFields[fieldName] = import_zod7.z.literal(true).optional();
2775
+ continue;
2776
+ }
2777
+ if (!isPlainObject(fieldConfig)) {
2684
2778
  throw new ShapeError(
2685
2779
  `Invalid config for _count.select.${fieldName} on model "${model}". Expected true or { where: { ... } }`
2686
2780
  );
2687
2781
  }
2782
+ if (Object.keys(fieldConfig).length === 0) {
2783
+ throw new ShapeError(
2784
+ `Empty config for _count.select.${fieldName} on model "${model}". Use true or { where: { ... } }.`
2785
+ );
2786
+ }
2787
+ validateNestedKeys(
2788
+ Object.keys(fieldConfig),
2789
+ KNOWN_COUNT_SELECT_ENTRY_KEYS,
2790
+ `_count.select.${fieldName} on model "${model}"`
2791
+ );
2792
+ if (fieldConfig.where) {
2793
+ const relatedType = fieldMeta.type;
2794
+ const { schema: whereSchema, forced } = deps.buildWhereSchema(
2795
+ relatedType,
2796
+ fieldConfig.where
2797
+ );
2798
+ const nestedSchemas = {};
2799
+ if (whereSchema)
2800
+ nestedSchemas["where"] = whereSchema;
2801
+ const nestedObj = import_zod7.z.object(nestedSchemas).strict();
2802
+ countSelectFields[fieldName] = import_zod7.z.union([import_zod7.z.literal(true), nestedObj]).optional();
2803
+ if (hasWhereForced(forced)) {
2804
+ forcedCountWhere[fieldName] = forced;
2805
+ }
2806
+ } else {
2807
+ countSelectFields[fieldName] = import_zod7.z.literal(true).optional();
2808
+ }
2688
2809
  }
2689
- const countSelectKeys = Object.keys(countSelectFields);
2690
- const selectSchema = import_zod6.z.object(countSelectFields).strict().refine(
2691
- (v) => countSelectKeys.some((k) => v[k] !== void 0),
2692
- { message: "_count.select must specify at least one field" }
2810
+ const selectSchema = strictObjectRequiringOne(
2811
+ countSelectFields,
2812
+ "_count.select must specify at least one field"
2693
2813
  );
2694
2814
  return {
2695
- schema: import_zod6.z.object({ select: selectSchema }).strict().optional(),
2815
+ schema: import_zod7.z.object({ select: selectSchema }).strict().optional(),
2696
2816
  forcedCountWhere
2697
2817
  };
2698
2818
  }
2699
- function buildIncludeSchema(model, includeConfig, depth) {
2819
+ function buildNestedRelSchemas(relatedType, config, depth) {
2820
+ const nestedSchemas = {};
2821
+ const relForced = {};
2822
+ if (config.where) {
2823
+ const { schema: whereSchema, forced } = deps.buildWhereSchema(
2824
+ relatedType,
2825
+ config.where
2826
+ );
2827
+ if (whereSchema)
2828
+ nestedSchemas["where"] = whereSchema;
2829
+ if (hasWhereForced(forced))
2830
+ relForced.where = forced;
2831
+ }
2832
+ if (config.include) {
2833
+ const nested = buildProjectionSchema("include", relatedType, config.include, depth + 1);
2834
+ nestedSchemas["include"] = nested.schema;
2835
+ if (Object.keys(nested.forcedTree).length > 0)
2836
+ relForced.include = nested.forcedTree;
2837
+ if (Object.keys(nested.forcedCountWhere).length > 0) {
2838
+ relForced._countWhere = nested.forcedCountWhere;
2839
+ relForced._countWherePlacement = "include";
2840
+ }
2841
+ }
2842
+ if (config.select) {
2843
+ const nested = buildProjectionSchema("select", relatedType, config.select, depth + 1);
2844
+ nestedSchemas["select"] = nested.schema;
2845
+ if (Object.keys(nested.forcedTree).length > 0)
2846
+ relForced.select = nested.forcedTree;
2847
+ if (Object.keys(nested.forcedCountWhere).length > 0) {
2848
+ relForced._countWhere = nested.forcedCountWhere;
2849
+ relForced._countWherePlacement = "select";
2850
+ }
2851
+ }
2852
+ if (config.orderBy) {
2853
+ nestedSchemas["orderBy"] = deps.buildOrderBySchema(relatedType, config.orderBy);
2854
+ }
2855
+ if (config.cursor) {
2856
+ nestedSchemas["cursor"] = deps.buildCursorSchema(relatedType, config.cursor);
2857
+ }
2858
+ if (config.take) {
2859
+ nestedSchemas["take"] = deps.buildTakeSchema(config.take);
2860
+ }
2861
+ if (config.skip) {
2862
+ nestedSchemas["skip"] = import_zod7.z.number().int().min(0).optional();
2863
+ }
2864
+ return { nestedSchemas, relForced };
2865
+ }
2866
+ function buildProjectionSchema(mode, model, projectionConfig, depth) {
2700
2867
  const currentDepth = depth ?? 0;
2701
2868
  if (currentDepth > MAX_PROJECTION_DEPTH) {
2702
2869
  throw new ShapeError(
2703
- `Include schema for model "${model}" exceeds maximum nesting depth (${MAX_PROJECTION_DEPTH}). Check for circular relation references in the shape.`
2870
+ `${mode === "include" ? "Include" : "Select"} schema for model "${model}" exceeds maximum nesting depth (${MAX_PROJECTION_DEPTH}). Check for circular relation references in the shape.`
2704
2871
  );
2705
2872
  }
2706
- if (Object.keys(includeConfig).length === 0) {
2873
+ if (Object.keys(projectionConfig).length === 0) {
2707
2874
  throw new ShapeError(
2708
- `Empty include config on model "${model}". Define at least one relation.`
2875
+ `Empty ${mode} config on model "${model}". Define at least one ${mode === "include" ? "relation" : "field"}.`
2709
2876
  );
2710
2877
  }
2711
2878
  const modelFields = typeMap[model];
2712
2879
  if (!modelFields)
2713
2880
  throw new ShapeError(`Unknown model: ${model}`);
2881
+ const allowedNestedKeys = KNOWN_NESTED_KEYS[mode];
2714
2882
  const fieldSchemas = {};
2715
2883
  const forcedTree = {};
2716
2884
  let topLevelForcedCountWhere = {};
2717
- for (const [relName, config] of Object.entries(includeConfig)) {
2718
- if (relName === "_count") {
2885
+ for (const [fieldName, config] of Object.entries(projectionConfig)) {
2886
+ if (fieldName === "_count") {
2719
2887
  const countResult = buildIncludeCountSchema(model, config);
2720
2888
  fieldSchemas["_count"] = countResult.schema;
2721
2889
  topLevelForcedCountWhere = countResult.forcedCountWhere;
2722
2890
  continue;
2723
2891
  }
2724
- const fieldMeta = modelFields[relName];
2892
+ const fieldMeta = modelFields[fieldName];
2725
2893
  if (!fieldMeta)
2726
- throw new ShapeError(`Unknown field "${relName}" on model "${model}"`);
2727
- if (!fieldMeta.isRelation)
2728
- throw new ShapeError(`Field "${relName}" is not a relation on model "${model}"`);
2894
+ throw new ShapeError(`Unknown field "${fieldName}" on model "${model}"`);
2895
+ if (mode === "include" && !fieldMeta.isRelation) {
2896
+ throw new ShapeError(`Field "${fieldName}" is not a relation on model "${model}"`);
2897
+ }
2729
2898
  if (config === true) {
2730
- fieldSchemas[relName] = import_zod6.z.literal(true).optional();
2731
- } else {
2732
- validateNestedKeys(
2733
- Object.keys(config),
2734
- KNOWN_NESTED_INCLUDE_KEYS,
2735
- `nested include for "${relName}" on model "${model}"`
2736
- );
2737
- if (config.select && config.include) {
2738
- throw new ShapeError(`Nested include for "${relName}" cannot define both "select" and "include".`);
2739
- }
2740
- if (!fieldMeta.isList) {
2741
- if (config.where || config.orderBy || config.cursor || config.take || config.skip) {
2742
- throw new ShapeError(
2743
- `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.`
2744
- );
2745
- }
2746
- }
2747
- const nestedSchemas = {};
2748
- const relForced = {};
2749
- if (config.where) {
2750
- const { schema: whereSchema, forced } = deps.buildWhereSchema(
2751
- fieldMeta.type,
2752
- config.where
2753
- );
2754
- if (whereSchema)
2755
- nestedSchemas["where"] = whereSchema;
2756
- if (hasWhereForced(forced))
2757
- relForced.where = forced;
2758
- }
2759
- if (config.include) {
2760
- const nested = buildIncludeSchema(fieldMeta.type, config.include, currentDepth + 1);
2761
- nestedSchemas["include"] = nested.schema;
2762
- if (Object.keys(nested.forcedTree).length > 0)
2763
- relForced.include = nested.forcedTree;
2764
- if (Object.keys(nested.forcedCountWhere).length > 0) {
2765
- relForced._countWhere = nested.forcedCountWhere;
2766
- relForced._countWherePlacement = "include";
2767
- }
2768
- }
2769
- if (config.select) {
2770
- const nested = buildSelectSchema(fieldMeta.type, config.select, currentDepth + 1);
2771
- nestedSchemas["select"] = nested.schema;
2772
- if (Object.keys(nested.forcedTree).length > 0)
2773
- relForced.select = nested.forcedTree;
2774
- if (Object.keys(nested.forcedCountWhere).length > 0) {
2775
- relForced._countWhere = nested.forcedCountWhere;
2776
- relForced._countWherePlacement = "select";
2777
- }
2778
- }
2779
- if (config.orderBy) {
2780
- nestedSchemas["orderBy"] = deps.buildOrderBySchema(fieldMeta.type, config.orderBy);
2781
- }
2782
- if (config.cursor) {
2783
- nestedSchemas["cursor"] = deps.buildCursorSchema(fieldMeta.type, config.cursor);
2784
- }
2785
- if (config.take) {
2786
- nestedSchemas["take"] = deps.buildTakeSchema(config.take);
2787
- }
2788
- if (config.skip) {
2789
- nestedSchemas["skip"] = import_zod6.z.number().int().min(0).optional();
2790
- }
2791
- const nestedObj = import_zod6.z.object(nestedSchemas).strict();
2792
- fieldSchemas[relName] = import_zod6.z.union([import_zod6.z.literal(true), nestedObj]).optional();
2793
- if (Object.keys(relForced).length > 0)
2794
- forcedTree[relName] = relForced;
2795
- }
2796
- }
2797
- const includeFieldKeys = Object.keys(fieldSchemas);
2798
- const baseSchema = import_zod6.z.object(fieldSchemas).strict();
2799
- const schema = includeFieldKeys.length > 0 ? baseSchema.refine(
2800
- (v) => includeFieldKeys.some((k) => v[k] !== void 0),
2801
- { message: "include must specify at least one field" }
2802
- ).optional() : baseSchema.optional();
2803
- return {
2804
- schema,
2805
- forcedTree,
2806
- forcedCountWhere: topLevelForcedCountWhere
2807
- };
2808
- }
2809
- function buildSelectSchema(model, selectConfig, depth) {
2810
- const currentDepth = depth ?? 0;
2811
- if (currentDepth > MAX_PROJECTION_DEPTH) {
2812
- throw new ShapeError(
2813
- `Select schema for model "${model}" exceeds maximum nesting depth (${MAX_PROJECTION_DEPTH}). Check for circular relation references in the shape.`
2814
- );
2815
- }
2816
- if (Object.keys(selectConfig).length === 0) {
2817
- throw new ShapeError(
2818
- `Empty select config on model "${model}". Define at least one field.`
2819
- );
2820
- }
2821
- const modelFields = typeMap[model];
2822
- if (!modelFields)
2823
- throw new ShapeError(`Unknown model: ${model}`);
2824
- const fieldSchemas = {};
2825
- const forcedTree = {};
2826
- let topLevelForcedCountWhere = {};
2827
- for (const [fieldName, config] of Object.entries(selectConfig)) {
2828
- if (fieldName === "_count") {
2829
- const countResult = buildIncludeCountSchema(model, config);
2830
- fieldSchemas["_count"] = countResult.schema;
2831
- topLevelForcedCountWhere = countResult.forcedCountWhere;
2899
+ fieldSchemas[fieldName] = import_zod7.z.literal(true).optional();
2832
2900
  continue;
2833
2901
  }
2834
- const fieldMeta = modelFields[fieldName];
2835
- if (!fieldMeta)
2836
- throw new ShapeError(`Unknown field "${fieldName}" on model "${model}"`);
2837
- if (config === true) {
2838
- fieldSchemas[fieldName] = import_zod6.z.literal(true).optional();
2839
- } else {
2840
- if (!fieldMeta.isRelation) {
2841
- throw new ShapeError(`Nested select args only valid for relations, not scalar "${fieldName}" on model "${model}"`);
2842
- }
2843
- validateNestedKeys(
2844
- Object.keys(config),
2845
- KNOWN_NESTED_SELECT_KEYS,
2846
- `nested select for "${fieldName}" on model "${model}"`
2847
- );
2848
- if (config.select && config.include) {
2849
- throw new ShapeError(`Nested select for "${fieldName}" cannot define both "select" and "include".`);
2850
- }
2851
- if (!fieldMeta.isList) {
2852
- if (config.where || config.orderBy || config.cursor || config.take || config.skip) {
2853
- throw new ShapeError(
2854
- `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.`
2855
- );
2856
- }
2857
- }
2858
- const nestedSchemas = {};
2859
- const relForced = {};
2860
- if (config.select) {
2861
- const nested = buildSelectSchema(fieldMeta.type, config.select, currentDepth + 1);
2862
- nestedSchemas["select"] = nested.schema;
2863
- if (Object.keys(nested.forcedTree).length > 0)
2864
- relForced.select = nested.forcedTree;
2865
- if (Object.keys(nested.forcedCountWhere).length > 0) {
2866
- relForced._countWhere = nested.forcedCountWhere;
2867
- relForced._countWherePlacement = "select";
2868
- }
2869
- }
2870
- if (config.include) {
2871
- const nested = buildIncludeSchema(fieldMeta.type, config.include, currentDepth + 1);
2872
- nestedSchemas["include"] = nested.schema;
2873
- if (Object.keys(nested.forcedTree).length > 0)
2874
- relForced.include = nested.forcedTree;
2875
- if (Object.keys(nested.forcedCountWhere).length > 0) {
2876
- relForced._countWhere = nested.forcedCountWhere;
2877
- relForced._countWherePlacement = "include";
2878
- }
2879
- }
2880
- if (config.where) {
2881
- const { schema: whereSchema, forced } = deps.buildWhereSchema(
2882
- fieldMeta.type,
2883
- config.where
2902
+ if (mode === "select" && !fieldMeta.isRelation) {
2903
+ throw new ShapeError(`Nested select args only valid for relations, not scalar "${fieldName}" on model "${model}"`);
2904
+ }
2905
+ const contextLabel = `nested ${mode} for "${fieldName}" on model "${model}"`;
2906
+ validateNestedKeys(Object.keys(config), allowedNestedKeys, contextLabel);
2907
+ if (config.select && config.include) {
2908
+ throw new ShapeError(`Nested ${mode} for "${fieldName}" cannot define both "select" and "include".`);
2909
+ }
2910
+ if (!fieldMeta.isList) {
2911
+ if (config.where || config.orderBy || config.cursor || config.take || config.skip) {
2912
+ throw new ShapeError(
2913
+ `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.`
2884
2914
  );
2885
- if (whereSchema)
2886
- nestedSchemas["where"] = whereSchema;
2887
- if (hasWhereForced(forced))
2888
- relForced.where = forced;
2889
- }
2890
- if (config.orderBy) {
2891
- nestedSchemas["orderBy"] = deps.buildOrderBySchema(fieldMeta.type, config.orderBy);
2892
- }
2893
- if (config.cursor) {
2894
- nestedSchemas["cursor"] = deps.buildCursorSchema(fieldMeta.type, config.cursor);
2895
- }
2896
- if (config.take) {
2897
- nestedSchemas["take"] = deps.buildTakeSchema(config.take);
2898
- }
2899
- if (config.skip) {
2900
- nestedSchemas["skip"] = import_zod6.z.number().int().min(0).optional();
2901
2915
  }
2902
- const nestedObj = import_zod6.z.object(nestedSchemas).strict();
2903
- fieldSchemas[fieldName] = import_zod6.z.union([import_zod6.z.literal(true), nestedObj]).optional();
2904
- if (Object.keys(relForced).length > 0)
2905
- forcedTree[fieldName] = relForced;
2906
- }
2907
- }
2908
- const selectFieldKeys = Object.keys(fieldSchemas);
2909
- const baseSchema = import_zod6.z.object(fieldSchemas).strict();
2910
- const schema = selectFieldKeys.length > 0 ? baseSchema.refine(
2911
- (v) => selectFieldKeys.some((k) => v[k] !== void 0),
2912
- { message: "select must specify at least one field" }
2913
- ).optional() : baseSchema.optional();
2916
+ }
2917
+ const { nestedSchemas, relForced } = buildNestedRelSchemas(fieldMeta.type, config, currentDepth);
2918
+ const nestedObj = import_zod7.z.object(nestedSchemas).strict();
2919
+ fieldSchemas[fieldName] = wrapRelationSchema(
2920
+ nestedObj,
2921
+ buildRelationArgsSkeleton(config)
2922
+ ).optional();
2923
+ if (Object.keys(relForced).length > 0)
2924
+ forcedTree[fieldName] = relForced;
2925
+ }
2926
+ const schema = Object.keys(fieldSchemas).length > 0 ? strictObjectRequiringOne(
2927
+ fieldSchemas,
2928
+ `${mode} must specify at least one field`
2929
+ ).optional() : import_zod7.z.object(fieldSchemas).strict().optional();
2914
2930
  return {
2915
2931
  schema,
2916
2932
  forcedTree,
2917
2933
  forcedCountWhere: topLevelForcedCountWhere
2918
2934
  };
2919
2935
  }
2920
- return { buildIncludeSchema, buildSelectSchema, buildIncludeCountSchema };
2936
+ function buildIncludeSchema(model, includeConfig, depth) {
2937
+ return buildProjectionSchema("include", model, includeConfig, depth);
2938
+ }
2939
+ function buildSelectSchema(model, selectConfig, depth) {
2940
+ return buildProjectionSchema("select", model, selectConfig, depth);
2941
+ }
2942
+ return { buildIncludeSchema, buildSelectSchema, buildIncludeCountSchema, buildProjectionSchema };
2921
2943
  }
2922
2944
 
2923
2945
  // src/shared/operation-shape-keys.ts
@@ -2927,7 +2949,6 @@ var OPERATION_SHAPE_KEYS = {
2927
2949
  findFirstOrThrow: ["where", "include", "select", "orderBy", "cursor", "take", "skip", "distinct"],
2928
2950
  findUnique: ["where", "include", "select"],
2929
2951
  findUniqueOrThrow: ["where", "include", "select"],
2930
- findManyPaginated: ["where", "include", "select", "orderBy", "cursor", "take", "skip", "distinct"],
2931
2952
  count: ["where", "select", "cursor", "orderBy", "skip", "take"],
2932
2953
  aggregate: ["where", "orderBy", "cursor", "take", "skip", "_count", "_avg", "_sum", "_min", "_max"],
2933
2954
  groupBy: ["where", "by", "having", "_count", "_avg", "_sum", "_min", "_max", "orderBy", "take", "skip"],
@@ -2962,6 +2983,99 @@ var MUTATION_SHAPE_KEYS = {
2962
2983
  delete: new Set(OPERATION_SHAPE_KEYS.delete),
2963
2984
  deleteMany: new Set(OPERATION_SHAPE_KEYS.deleteMany)
2964
2985
  };
2986
+ var MUTATION_OPERATION_SPECS = {
2987
+ create: {
2988
+ bodyKeysBase: ["data"],
2989
+ bodyKeysProjection: ["data", "select", "include"],
2990
+ shapeKeysBase: ["data"],
2991
+ shapeKeysProjection: ["data", "select", "include"],
2992
+ supportsProjection: true
2993
+ },
2994
+ createMany: {
2995
+ bodyKeysBase: ["data", "skipDuplicates"],
2996
+ bodyKeysProjection: ["data", "select", "include", "skipDuplicates"],
2997
+ shapeKeysBase: ["data"],
2998
+ shapeKeysProjection: ["data"],
2999
+ supportsProjection: false
3000
+ },
3001
+ createManyAndReturn: {
3002
+ bodyKeysBase: ["data", "skipDuplicates"],
3003
+ bodyKeysProjection: ["data", "select", "include", "skipDuplicates"],
3004
+ shapeKeysBase: ["data"],
3005
+ shapeKeysProjection: ["data", "select", "include"],
3006
+ supportsProjection: true
3007
+ },
3008
+ update: {
3009
+ bodyKeysBase: ["data", "where"],
3010
+ bodyKeysProjection: ["data", "where", "select", "include"],
3011
+ shapeKeysBase: ["data", "where"],
3012
+ shapeKeysProjection: ["data", "where", "select", "include"],
3013
+ supportsProjection: true
3014
+ },
3015
+ updateMany: {
3016
+ bodyKeysBase: ["data", "where"],
3017
+ bodyKeysProjection: ["data", "where"],
3018
+ shapeKeysBase: ["data", "where"],
3019
+ shapeKeysProjection: ["data", "where"],
3020
+ supportsProjection: false
3021
+ },
3022
+ updateManyAndReturn: {
3023
+ bodyKeysBase: ["data", "where"],
3024
+ bodyKeysProjection: ["data", "where", "select", "include"],
3025
+ shapeKeysBase: ["data", "where"],
3026
+ shapeKeysProjection: ["data", "where", "select", "include"],
3027
+ supportsProjection: true
3028
+ },
3029
+ upsert: {
3030
+ bodyKeysBase: ["where", "create", "update", "select", "include"],
3031
+ bodyKeysProjection: ["where", "create", "update", "select", "include"],
3032
+ shapeKeysBase: ["where", "create", "update", "select", "include"],
3033
+ shapeKeysProjection: ["where", "create", "update", "select", "include"],
3034
+ supportsProjection: true
3035
+ },
3036
+ delete: {
3037
+ bodyKeysBase: ["where"],
3038
+ bodyKeysProjection: ["where", "select", "include"],
3039
+ shapeKeysBase: ["where"],
3040
+ shapeKeysProjection: ["where", "select", "include"],
3041
+ supportsProjection: true
3042
+ },
3043
+ deleteMany: {
3044
+ bodyKeysBase: ["where"],
3045
+ bodyKeysProjection: ["where"],
3046
+ shapeKeysBase: ["where"],
3047
+ shapeKeysProjection: ["where"],
3048
+ supportsProjection: false
3049
+ }
3050
+ };
3051
+ var bodyKeyCache = /* @__PURE__ */ new Map();
3052
+ var shapeKeyCache = /* @__PURE__ */ new Map();
3053
+ function getAllowedBodyKeys(method, withProjection) {
3054
+ const cacheKey = `${method}\0${withProjection ? "p" : "b"}`;
3055
+ const cached = bodyKeyCache.get(cacheKey);
3056
+ if (cached)
3057
+ return cached;
3058
+ const spec = MUTATION_OPERATION_SPECS[method];
3059
+ if (!spec)
3060
+ throw new Error(`Unknown mutation method "${method}"`);
3061
+ const keys = withProjection && spec.supportsProjection ? spec.bodyKeysProjection : spec.bodyKeysBase;
3062
+ const set = new Set(keys);
3063
+ bodyKeyCache.set(cacheKey, set);
3064
+ return set;
3065
+ }
3066
+ function getAllowedShapeKeys(method, withProjection) {
3067
+ const cacheKey = `${method}\0${withProjection ? "p" : "b"}`;
3068
+ const cached = shapeKeyCache.get(cacheKey);
3069
+ if (cached)
3070
+ return cached;
3071
+ const spec = MUTATION_OPERATION_SPECS[method];
3072
+ if (!spec)
3073
+ throw new Error(`Unknown mutation method "${method}"`);
3074
+ const keys = withProjection && spec.supportsProjection ? spec.shapeKeysProjection : spec.shapeKeysBase;
3075
+ const set = new Set(keys);
3076
+ shapeKeyCache.set(cacheKey, set);
3077
+ return set;
3078
+ }
2965
3079
 
2966
3080
  // src/runtime/query-builder.ts
2967
3081
  var METHOD_ALLOWED_ARGS = READ_METHOD_ALLOWED_ARGS;
@@ -3062,6 +3176,90 @@ function createQueryBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
3062
3176
  }
3063
3177
  return shapeOrFn;
3064
3178
  }
3179
+ function buildGroupByOrderBySchema(model, orderBy, by, sortEnum) {
3180
+ const bySet = new Set(by);
3181
+ if (orderBy === true) {
3182
+ const groupByOrderFields2 = {};
3183
+ for (const field of by) {
3184
+ groupByOrderFields2[field] = sortEnum.optional();
3185
+ }
3186
+ groupByOrderFields2._count = sortEnum.optional();
3187
+ const singleSchema2 = strictObjectRequiringOne(
3188
+ groupByOrderFields2,
3189
+ "orderBy must specify at least one field"
3190
+ );
3191
+ return import_zod8.z.union([
3192
+ singleSchema2,
3193
+ import_zod8.z.preprocess(coerceToArray, import_zod8.z.array(singleSchema2).min(1))
3194
+ ]).optional();
3195
+ }
3196
+ if (!isPlainObject(orderBy)) {
3197
+ throw new ShapeError(
3198
+ `groupBy orderBy shape on model "${model}" must be true or an object of fields`
3199
+ );
3200
+ }
3201
+ if (Object.keys(orderBy).length === 0) {
3202
+ throw new ShapeError(
3203
+ `Empty groupBy orderBy config on model "${model}". Define at least one field.`
3204
+ );
3205
+ }
3206
+ const groupByOrderFields = {};
3207
+ for (const [fieldName, config] of Object.entries(orderBy)) {
3208
+ if (fieldName === "_count") {
3209
+ if (config === true) {
3210
+ groupByOrderFields._count = sortEnum.optional();
3211
+ } else if (isPlainObject(config)) {
3212
+ if (Object.keys(config).length === 0) {
3213
+ throw new ShapeError(
3214
+ `Empty groupBy orderBy "_count" config on model "${model}". Define at least one by-field.`
3215
+ );
3216
+ }
3217
+ const countFields = {};
3218
+ for (const [countField, countConfig] of Object.entries(config)) {
3219
+ if (countConfig !== true) {
3220
+ throw new ShapeError(
3221
+ `groupBy orderBy "_count.${countField}" config on model "${model}" must be true`
3222
+ );
3223
+ }
3224
+ if (!bySet.has(countField)) {
3225
+ throw new ShapeError(
3226
+ `orderBy _count field "${countField}" must be included in "by" for groupBy`
3227
+ );
3228
+ }
3229
+ countFields[countField] = sortEnum.optional();
3230
+ }
3231
+ groupByOrderFields._count = strictObjectRequiringOne(
3232
+ countFields,
3233
+ "orderBy._count must specify at least one field"
3234
+ ).optional();
3235
+ } else {
3236
+ throw new ShapeError(
3237
+ `groupBy orderBy "_count" config on model "${model}" must be true or an object of by-fields`
3238
+ );
3239
+ }
3240
+ continue;
3241
+ }
3242
+ if (config !== true) {
3243
+ throw new ShapeError(
3244
+ `groupBy orderBy field "${fieldName}" config on model "${model}" must be true`
3245
+ );
3246
+ }
3247
+ if (!bySet.has(fieldName)) {
3248
+ throw new ShapeError(
3249
+ `orderBy field "${fieldName}" must be included in "by" for groupBy`
3250
+ );
3251
+ }
3252
+ groupByOrderFields[fieldName] = sortEnum.optional();
3253
+ }
3254
+ const singleSchema = strictObjectRequiringOne(
3255
+ groupByOrderFields,
3256
+ "orderBy must specify at least one field"
3257
+ );
3258
+ return import_zod8.z.union([
3259
+ singleSchema,
3260
+ import_zod8.z.preprocess(coerceToArray, import_zod8.z.array(singleSchema).min(1))
3261
+ ]).optional();
3262
+ }
3065
3263
  function buildShapeZodSchema(model, method, shape) {
3066
3264
  validateShapeArgs(method, shape);
3067
3265
  validateUniqueWhere(model, method, shape);
@@ -3101,73 +3299,19 @@ function createQueryBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
3101
3299
  }
3102
3300
  if (shape.orderBy) {
3103
3301
  if (method === "groupBy" && shape.by) {
3104
- const sortEnum = import_zod7.z.enum(["asc", "desc"]);
3105
- const bySet = new Set(shape.by);
3302
+ const sortEnum = import_zod8.z.enum(["asc", "desc"]);
3303
+ schemaFields.orderBy = buildGroupByOrderBySchema(
3304
+ model,
3305
+ shape.orderBy,
3306
+ shape.by,
3307
+ sortEnum
3308
+ );
3309
+ } else {
3106
3310
  if (shape.orderBy === true) {
3107
- const groupByOrderFields = {};
3108
- for (const field of shape.by) {
3109
- groupByOrderFields[field] = sortEnum.optional();
3110
- }
3111
- groupByOrderFields._count = sortEnum.optional();
3112
- const fieldKeys = Object.keys(groupByOrderFields);
3113
- const singleSchema = import_zod7.z.object(groupByOrderFields).strict().refine(
3114
- (v) => fieldKeys.some(
3115
- (k) => v[k] !== void 0
3116
- ),
3117
- { message: "orderBy must specify at least one field" }
3118
- );
3119
- schemaFields.orderBy = import_zod7.z.union([
3120
- singleSchema,
3121
- import_zod7.z.preprocess(coerceToArray, import_zod7.z.array(singleSchema).min(1))
3122
- ]).optional();
3123
- } else {
3124
- const groupByOrderFields = {};
3125
- for (const [fieldName, config] of Object.entries(shape.orderBy)) {
3126
- if (fieldName === "_count") {
3127
- if (config === true) {
3128
- groupByOrderFields._count = sortEnum.optional();
3129
- } else if (typeof config === "object" && config !== null) {
3130
- const countFields = {};
3131
- for (const countField of Object.keys(config)) {
3132
- if (!bySet.has(countField)) {
3133
- throw new ShapeError(
3134
- `orderBy _count field "${countField}" must be included in "by" for groupBy`
3135
- );
3136
- }
3137
- countFields[countField] = sortEnum.optional();
3138
- }
3139
- const countKeys = Object.keys(countFields);
3140
- groupByOrderFields._count = import_zod7.z.object(countFields).strict().refine(
3141
- (v) => countKeys.some(
3142
- (k) => v[k] !== void 0
3143
- ),
3144
- {
3145
- message: "orderBy._count must specify at least one field"
3146
- }
3147
- ).optional();
3148
- }
3149
- continue;
3150
- }
3151
- if (!bySet.has(fieldName)) {
3152
- throw new ShapeError(
3153
- `orderBy field "${fieldName}" must be included in "by" for groupBy`
3154
- );
3155
- }
3156
- groupByOrderFields[fieldName] = sortEnum.optional();
3157
- }
3158
- const fieldKeys = Object.keys(groupByOrderFields);
3159
- const singleSchema = import_zod7.z.object(groupByOrderFields).strict().refine(
3160
- (v) => fieldKeys.some(
3161
- (k) => v[k] !== void 0
3162
- ),
3163
- { message: "orderBy must specify at least one field" }
3311
+ throw new ShapeError(
3312
+ `Shape config "orderBy: true" is only supported for groupBy. Define an object of allowed fields.`
3164
3313
  );
3165
- schemaFields.orderBy = import_zod7.z.union([
3166
- singleSchema,
3167
- import_zod7.z.preprocess(coerceToArray, import_zod7.z.array(singleSchema).min(1))
3168
- ]).optional();
3169
3314
  }
3170
- } else {
3171
3315
  schemaFields.orderBy = argsBuilder.buildOrderBySchema(
3172
3316
  model,
3173
3317
  shape.orderBy
@@ -3175,19 +3319,16 @@ function createQueryBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
3175
3319
  }
3176
3320
  }
3177
3321
  if (shape.cursor) {
3178
- schemaFields.cursor = argsBuilder.buildCursorSchema(
3179
- model,
3180
- shape.cursor
3181
- );
3322
+ schemaFields.cursor = argsBuilder.buildCursorSchema(model, shape.cursor);
3182
3323
  }
3183
- if (shape.take) {
3324
+ if (shape.take !== void 0) {
3184
3325
  schemaFields.take = argsBuilder.buildTakeSchema(shape.take);
3185
3326
  }
3186
3327
  if (shape.skip !== void 0) {
3187
3328
  if (shape.skip !== true) {
3188
3329
  throw new ShapeError('Shape config "skip" must be true');
3189
3330
  }
3190
- schemaFields.skip = import_zod7.z.number().int().min(0).optional();
3331
+ schemaFields.skip = import_zod8.z.number().int().min(0).optional();
3191
3332
  }
3192
3333
  if (shape.distinct) {
3193
3334
  schemaFields.distinct = argsBuilder.buildDistinctSchema(
@@ -3234,13 +3375,10 @@ function createQueryBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
3234
3375
  schemaFields.by = argsBuilder.buildBySchema(model, shape.by);
3235
3376
  }
3236
3377
  if (shape.having) {
3237
- schemaFields.having = argsBuilder.buildHavingSchema(
3238
- model,
3239
- shape.having
3240
- );
3378
+ schemaFields.having = argsBuilder.buildHavingSchema(model, shape.having);
3241
3379
  }
3242
3380
  return {
3243
- zodSchema: import_zod7.z.object(schemaFields).strict(),
3381
+ zodSchema: import_zod8.z.object(schemaFields).strict(),
3244
3382
  forcedWhere,
3245
3383
  forcedOnlyWhereKeys,
3246
3384
  forcedIncludeTree,
@@ -3433,22 +3571,18 @@ function buildScopedUniqueWhere(existingWhere, conditions, scopeFks, log, model)
3433
3571
  allConditions.push(...conditions);
3434
3572
  return { ...topLevel, AND: allConditions };
3435
3573
  }
3436
- function isComparableScopeValue(v) {
3437
- const t = typeof v;
3438
- return t === "string" || t === "number" || t === "bigint";
3439
- }
3440
- function looseEqual(a, b, log, fk) {
3574
+ function scopeValuesEqual(a, b) {
3441
3575
  if (a === b)
3442
3576
  return true;
3443
- if (!isComparableScopeValue(a) || !isComparableScopeValue(b))
3444
- return false;
3445
- const eq = String(a) === String(b);
3446
- if (eq && log && fk) {
3447
- log.warn(
3448
- `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.`
3449
- );
3577
+ const aIsBig = typeof a === "bigint";
3578
+ const bIsBig = typeof b === "bigint";
3579
+ if (aIsBig && typeof b === "number") {
3580
+ return Number.isInteger(b) && a === BigInt(b);
3450
3581
  }
3451
- return eq;
3582
+ if (bIsBig && typeof a === "number") {
3583
+ return Number.isInteger(a) && b === BigInt(a);
3584
+ }
3585
+ return false;
3452
3586
  }
3453
3587
  function buildFkSelect(fks) {
3454
3588
  const select = {};
@@ -3738,7 +3872,7 @@ async function handleFindUnique(args, query, conditions, scopes, operation, log,
3738
3872
  const result = await query(nextArgs);
3739
3873
  if (result === null)
3740
3874
  return result;
3741
- if (typeof result !== "object" || result === null) {
3875
+ if (typeof result !== "object") {
3742
3876
  throw new ShapeError(
3743
3877
  `${operation} on model "${model}" returned a non-object, non-null result`
3744
3878
  );
@@ -3769,7 +3903,7 @@ async function handleFindUnique(args, query, conditions, scopes, operation, log,
3769
3903
  `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.`
3770
3904
  );
3771
3905
  }
3772
- if (typeof verifyResult !== "object" || verifyResult === null) {
3906
+ if (typeof verifyResult !== "object") {
3773
3907
  throw new PolicyError(
3774
3908
  `prisma-guard: Scope verification re-query on model "${model}" returned a non-object result.`
3775
3909
  );
@@ -3783,7 +3917,7 @@ async function handleFindUnique(args, query, conditions, scopes, operation, log,
3783
3917
  `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).`
3784
3918
  );
3785
3919
  }
3786
- if (!looseEqual(verifyObj[fk], value, log, fk)) {
3920
+ if (!scopeValuesEqual(verifyObj[fk], value)) {
3787
3921
  if (operation === "findUniqueOrThrow") {
3788
3922
  throw new PolicyError(
3789
3923
  `prisma-guard: Record on model "${model}" not accessible in current scope`
@@ -3803,97 +3937,158 @@ async function handleFindUnique(args, query, conditions, scopes, operation, log,
3803
3937
  }
3804
3938
 
3805
3939
  // src/runtime/model-guard.ts
3940
+ var import_zod11 = require("zod");
3941
+
3942
+ // src/runtime/model-guard-data.ts
3943
+ var import_zod10 = require("zod");
3944
+
3945
+ // src/runtime/unique-selector-schema.ts
3806
3946
  var import_zod9 = require("zod");
3947
+ function buildUniqueSelectorSchema(parentModel, parentField, relatedModel, config, typeMap, uniqueMap, enumMap, scalarBase, context) {
3948
+ const modelFields = typeMap[relatedModel];
3949
+ if (!modelFields) {
3950
+ throw new ShapeError(
3951
+ `Unknown related model "${relatedModel}" for ${context} on "${parentModel}.${parentField}"`
3952
+ );
3953
+ }
3954
+ const constraints = uniqueMap[relatedModel] ?? [];
3955
+ if (constraints.length === 0) {
3956
+ throw new ShapeError(
3957
+ `${context} on "${parentModel}.${parentField}" requires related model "${relatedModel}" to have at least one unique constraint`
3958
+ );
3959
+ }
3960
+ const configKeys = Object.keys(config);
3961
+ if (configKeys.length === 0) {
3962
+ throw new ShapeError(
3963
+ `${context} on "${parentModel}.${parentField}" must define at least one unique selector. Available: ${formatUniqueConstraints(constraints)}`
3964
+ );
3965
+ }
3966
+ const fieldSchemas = {};
3967
+ const fieldKeys = [];
3968
+ for (const [key, value] of Object.entries(config)) {
3969
+ const compoundConstraint = constraints.find(
3970
+ (c) => c.selector === key && c.fields.length > 1
3971
+ );
3972
+ if (compoundConstraint) {
3973
+ if (!isPlainObject(value)) {
3974
+ throw new ShapeError(
3975
+ `Compound unique selector "${key}" in ${context} on "${parentModel}.${parentField}" must be an object with fields: ${compoundConstraint.fields.join(", ")}`
3976
+ );
3977
+ }
3978
+ const allowed = new Set(compoundConstraint.fields);
3979
+ const nestedKeys = Object.keys(value);
3980
+ for (const nestedKey of nestedKeys) {
3981
+ if (!allowed.has(nestedKey)) {
3982
+ throw new ShapeError(
3983
+ `Unknown field "${nestedKey}" in compound unique selector "${key}" on "${parentModel}.${parentField}". Allowed: ${compoundConstraint.fields.join(", ")}`
3984
+ );
3985
+ }
3986
+ }
3987
+ for (const field of compoundConstraint.fields) {
3988
+ if (!(field in value)) {
3989
+ throw new ShapeError(
3990
+ `Missing field "${field}" in compound unique selector "${key}" on "${parentModel}.${parentField}"`
3991
+ );
3992
+ }
3993
+ const fieldValue = value[field];
3994
+ if (fieldValue !== true) {
3995
+ throw new ShapeError(
3996
+ `Field "${field}" in compound unique selector "${key}" on "${parentModel}.${parentField}" must be true`
3997
+ );
3998
+ }
3999
+ }
4000
+ const nestedSchemas = {};
4001
+ for (const field of compoundConstraint.fields) {
4002
+ const fieldMeta2 = modelFields[field];
4003
+ if (!fieldMeta2) {
4004
+ throw new ShapeError(
4005
+ `Unknown field "${field}" on related model "${relatedModel}"`
4006
+ );
4007
+ }
4008
+ if (fieldMeta2.isRelation) {
4009
+ throw new ShapeError(
4010
+ `Relation field "${field}" cannot be used in compound unique selector`
4011
+ );
4012
+ }
4013
+ nestedSchemas[field] = buildDirectScalarSchema(
4014
+ fieldMeta2,
4015
+ enumMap,
4016
+ scalarBase
4017
+ );
4018
+ }
4019
+ fieldSchemas[key] = import_zod9.z.object(nestedSchemas).strict().optional();
4020
+ fieldKeys.push(key);
4021
+ continue;
4022
+ }
4023
+ const singleConstraint = constraints.find(
4024
+ (c) => c.fields.length === 1 && c.fields[0] === key && c.selector === key
4025
+ );
4026
+ if (!singleConstraint) {
4027
+ const available = formatUniqueConstraints(constraints);
4028
+ throw new ShapeError(
4029
+ `Field "${key}" in ${context} on "${parentModel}.${parentField}" is not a unique selector on model "${relatedModel}". Available: ${available}`
4030
+ );
4031
+ }
4032
+ if (value !== true) {
4033
+ throw new ShapeError(
4034
+ `Field "${key}" in ${context} on "${parentModel}.${parentField}" must be true`
4035
+ );
4036
+ }
4037
+ const fieldMeta = modelFields[key];
4038
+ if (!fieldMeta) {
4039
+ throw new ShapeError(
4040
+ `Unknown field "${key}" on related model "${relatedModel}"`
4041
+ );
4042
+ }
4043
+ if (fieldMeta.isRelation) {
4044
+ throw new ShapeError(
4045
+ `Relation field "${key}" cannot be used in unique selector`
4046
+ );
4047
+ }
4048
+ fieldSchemas[key] = buildDirectScalarSchema(
4049
+ fieldMeta,
4050
+ enumMap,
4051
+ scalarBase
4052
+ ).optional();
4053
+ fieldKeys.push(key);
4054
+ }
4055
+ return import_zod9.z.object(fieldSchemas).strict().refine(
4056
+ (v) => fieldKeys.some((k) => v[k] !== void 0),
4057
+ {
4058
+ message: `${context} on "${parentModel}.${parentField}" requires at least one unique selector value`
4059
+ }
4060
+ );
4061
+ }
3807
4062
 
3808
4063
  // src/runtime/model-guard-data.ts
3809
- var import_zod8 = require("zod");
3810
- var ALLOWED_BODY_KEYS_CREATE = /* @__PURE__ */ new Set(["data"]);
3811
- var ALLOWED_BODY_KEYS_CREATE_PROJECTION = /* @__PURE__ */ new Set([
3812
- "data",
3813
- "select",
3814
- "include"
3815
- ]);
3816
- var ALLOWED_BODY_KEYS_CREATE_MANY = /* @__PURE__ */ new Set([
3817
- "data",
3818
- "skipDuplicates"
3819
- ]);
3820
- var ALLOWED_BODY_KEYS_CREATE_MANY_PROJECTION = /* @__PURE__ */ new Set([
3821
- "data",
3822
- "select",
3823
- "include",
3824
- "skipDuplicates"
3825
- ]);
3826
- var ALLOWED_BODY_KEYS_UPDATE = /* @__PURE__ */ new Set(["data", "where"]);
3827
- var ALLOWED_BODY_KEYS_UPDATE_PROJECTION = /* @__PURE__ */ new Set([
3828
- "data",
3829
- "where",
3830
- "select",
3831
- "include"
3832
- ]);
3833
- var ALLOWED_BODY_KEYS_DELETE = /* @__PURE__ */ new Set(["where"]);
3834
- var ALLOWED_BODY_KEYS_DELETE_PROJECTION = /* @__PURE__ */ new Set([
3835
- "where",
3836
- "select",
3837
- "include"
3838
- ]);
3839
- var ALLOWED_BODY_KEYS_UPSERT = /* @__PURE__ */ new Set([
3840
- "where",
3841
- "create",
3842
- "update",
3843
- "select",
3844
- "include"
3845
- ]);
3846
- var VALID_SHAPE_KEYS_CREATE = /* @__PURE__ */ new Set(["data"]);
3847
- var VALID_SHAPE_KEYS_CREATE_PROJECTION = /* @__PURE__ */ new Set([
3848
- "data",
3849
- "select",
3850
- "include"
3851
- ]);
3852
- var VALID_SHAPE_KEYS_UPDATE = /* @__PURE__ */ new Set(["data", "where"]);
3853
- var VALID_SHAPE_KEYS_UPDATE_PROJECTION = /* @__PURE__ */ new Set([
3854
- "data",
3855
- "where",
3856
- "select",
3857
- "include"
3858
- ]);
3859
- var VALID_SHAPE_KEYS_DELETE = /* @__PURE__ */ new Set(["where"]);
3860
- var VALID_SHAPE_KEYS_DELETE_PROJECTION = /* @__PURE__ */ new Set([
3861
- "where",
3862
- "select",
3863
- "include"
3864
- ]);
3865
- var VALID_SHAPE_KEYS_UPSERT = /* @__PURE__ */ new Set([
3866
- "where",
3867
- "create",
3868
- "update",
3869
- "select",
3870
- "include"
3871
- ]);
3872
- var KNOWN_RELATION_WRITE_OPS = /* @__PURE__ */ new Set([
3873
- "connect",
3874
- "connectOrCreate",
3875
- "create",
3876
- "createMany",
3877
- "disconnect",
3878
- "delete",
3879
- "set",
3880
- "update",
3881
- "updateMany",
3882
- "upsert",
3883
- "deleteMany"
3884
- ]);
3885
- function validateMutationBodyKeys(body, allowed, method) {
3886
- for (const key of Object.keys(body)) {
4064
+ var RELATION_OP_ALLOWED_KEYS = {
4065
+ connectOrCreate: /* @__PURE__ */ new Set(["where", "create"]),
4066
+ createMany: /* @__PURE__ */ new Set(["data", "skipDuplicates"]),
4067
+ "update.toMany": /* @__PURE__ */ new Set(["where", "data"]),
4068
+ updateMany: /* @__PURE__ */ new Set(["where", "data"]),
4069
+ "upsert.toOne": /* @__PURE__ */ new Set(["where", "create", "update"]),
4070
+ "upsert.toMany": /* @__PURE__ */ new Set(["where", "create", "update"])
4071
+ };
4072
+ function validateRelationOpKeys(actual, opKey, model, field, opLabel) {
4073
+ const allowed = RELATION_OP_ALLOWED_KEYS[opKey];
4074
+ if (!allowed)
4075
+ return;
4076
+ for (const key of Object.keys(actual)) {
3887
4077
  if (!allowed.has(key)) {
3888
4078
  throw new ShapeError(
3889
- `Unexpected key "${key}" in ${method} body. Allowed keys: ${[...allowed].join(", ")}`
4079
+ `Unknown key "${key}" in ${opLabel} config on "${model}.${field}". Allowed: ${[...allowed].join(", ")}`
3890
4080
  );
3891
4081
  }
3892
4082
  }
3893
4083
  }
3894
- function validateMutationShapeKeys(shape, allowed, method) {
3895
- for (const key of Object.keys(shape)) {
4084
+ function validateAllowedKeys(value, allowed, method, kind) {
4085
+ for (const key of Object.keys(value)) {
3896
4086
  if (!allowed.has(key)) {
4087
+ if (kind === "body") {
4088
+ throw new ShapeError(
4089
+ `Unexpected key "${key}" in ${method} body. Allowed keys: ${[...allowed].join(", ")}`
4090
+ );
4091
+ }
3897
4092
  throw new ShapeError(
3898
4093
  `Shape key "${key}" not valid for ${method}. Allowed: ${[...allowed].join(", ")}`
3899
4094
  );
@@ -3935,24 +4130,24 @@ function buildWhereFieldsSchema(model, config, typeMap, schemaBuilder) {
3935
4130
  for (const [fieldName, value] of Object.entries(config)) {
3936
4131
  if (value !== true)
3937
4132
  throw new ShapeError(
3938
- `Field "${fieldName}" in connect/where config must be true`
4133
+ `Field "${fieldName}" in filter config must be true`
3939
4134
  );
3940
4135
  const meta = modelFields[fieldName];
3941
4136
  if (!meta)
3942
4137
  throw new ShapeError(`Unknown field "${fieldName}" on model "${model}"`);
3943
4138
  if (meta.isRelation)
3944
4139
  throw new ShapeError(
3945
- `Relation field "${fieldName}" cannot be used in connect/where`
4140
+ `Relation field "${fieldName}" cannot be used in filter`
3946
4141
  );
3947
4142
  fieldSchemas[fieldName] = schemaBuilder.buildFieldSchema(model, fieldName).optional();
3948
4143
  fieldKeys.push(fieldName);
3949
4144
  }
3950
- return import_zod8.z.object(fieldSchemas).strict().refine(
4145
+ return import_zod10.z.object(fieldSchemas).strict().refine(
3951
4146
  (v) => fieldKeys.some((k) => v[k] !== void 0),
3952
- { message: `At least one field required in connect/where` }
4147
+ { message: `At least one field required in filter` }
3953
4148
  );
3954
4149
  }
3955
- function buildNestedDataSchema(model, config, typeMap, schemaBuilder) {
4150
+ function buildNestedDataSchema(model, config, mode, typeMap, schemaBuilder) {
3956
4151
  const modelFields = typeMap[model];
3957
4152
  if (!modelFields)
3958
4153
  throw new ShapeError(`Unknown model: ${model}`);
@@ -3973,382 +4168,349 @@ function buildNestedDataSchema(model, config, typeMap, schemaBuilder) {
3973
4168
  throw new ShapeError(
3974
4169
  `updatedAt field "${fieldName}" cannot be used in nested data`
3975
4170
  );
3976
- let fieldSchema = schemaBuilder.buildFieldSchema(model, fieldName);
3977
- if (!meta.isRequired) {
3978
- fieldSchema = fieldSchema.nullable().optional();
3979
- } else if (meta.hasDefault) {
3980
- fieldSchema = fieldSchema.optional();
3981
- }
3982
- fieldSchemas[fieldName] = fieldSchema;
4171
+ if (meta.isUnsupported)
4172
+ throw new ShapeError(
4173
+ `Field "${fieldName}" on model "${model}" has an Unsupported type and cannot be used in nested data`
4174
+ );
4175
+ const baseSchema = schemaBuilder.buildFieldSchema(model, fieldName);
4176
+ fieldSchemas[fieldName] = applyCreateUpdateNullability(meta, baseSchema, {
4177
+ mode,
4178
+ handlesUndefined: false
4179
+ });
3983
4180
  }
3984
- return import_zod8.z.object(fieldSchemas).strict();
4181
+ return import_zod10.z.object(fieldSchemas).strict();
3985
4182
  }
3986
- function buildRelationWriteSchema(model, fieldName, relatedModelName, isList, config, typeMap, schemaBuilder) {
3987
- const relatedFields = typeMap[relatedModelName];
3988
- if (!relatedFields)
4183
+ function requirePlainObjectConfig(value, message) {
4184
+ if (!isPlainObject(value))
4185
+ throw new ShapeError(message);
4186
+ return value;
4187
+ }
4188
+ function requireNestedObject(cfg, key, message) {
4189
+ const v = cfg[key];
4190
+ if (!v || !isPlainObject(v))
4191
+ throw new ShapeError(message);
4192
+ return v;
4193
+ }
4194
+ function buildUniqueSelector(ctx, cfg, context) {
4195
+ return buildUniqueSelectorSchema(
4196
+ ctx.model,
4197
+ ctx.fieldName,
4198
+ ctx.relatedModelName,
4199
+ cfg,
4200
+ ctx.typeMap,
4201
+ ctx.uniqueMap,
4202
+ ctx.enumMap,
4203
+ ctx.scalarBase,
4204
+ context
4205
+ );
4206
+ }
4207
+ function buildNestedData(ctx, cfg, mode) {
4208
+ return buildNestedDataSchema(
4209
+ ctx.relatedModelName,
4210
+ cfg,
4211
+ mode,
4212
+ ctx.typeMap,
4213
+ ctx.schemaBuilder
4214
+ );
4215
+ }
4216
+ var handleConnect = (ctx) => {
4217
+ const cfg = requirePlainObjectConfig(
4218
+ ctx.config,
4219
+ `connect config on "${ctx.model}.${ctx.fieldName}" must be an object of unique selectors`
4220
+ );
4221
+ const schema = buildUniqueSelector(ctx, cfg, "connect");
4222
+ return wrapRelationOp(ctx.isList, schema);
4223
+ };
4224
+ var handleConnectOrCreate = (ctx) => {
4225
+ const cfg = requirePlainObjectConfig(
4226
+ ctx.config,
4227
+ `connectOrCreate config on "${ctx.model}.${ctx.fieldName}" must be an object with "where" and "create"`
4228
+ );
4229
+ validateRelationOpKeys(cfg, "connectOrCreate", ctx.model, ctx.fieldName, "connectOrCreate");
4230
+ const where = requireNestedObject(
4231
+ cfg,
4232
+ "where",
4233
+ `connectOrCreate on "${ctx.model}.${ctx.fieldName}" requires "where" object`
4234
+ );
4235
+ const create = requireNestedObject(
4236
+ cfg,
4237
+ "create",
4238
+ `connectOrCreate on "${ctx.model}.${ctx.fieldName}" requires "create" object`
4239
+ );
4240
+ const whereSchema = buildUniqueSelector(ctx, where, "connectOrCreate.where");
4241
+ const createSchema = buildNestedData(ctx, create, "create");
4242
+ const cocSchema = import_zod10.z.object({ where: whereSchema, create: createSchema }).strict();
4243
+ return wrapRelationOp(ctx.isList, cocSchema);
4244
+ };
4245
+ var handleCreate = (ctx) => {
4246
+ const cfg = requirePlainObjectConfig(
4247
+ ctx.config,
4248
+ `create config on "${ctx.model}.${ctx.fieldName}" must be an object of field names`
4249
+ );
4250
+ const createSchema = buildNestedData(ctx, cfg, "create");
4251
+ return wrapRelationOp(ctx.isList, createSchema);
4252
+ };
4253
+ var handleCreateMany = (ctx) => {
4254
+ if (!ctx.isList) {
3989
4255
  throw new ShapeError(
3990
- `Unknown related model "${relatedModelName}" for field "${model}.${fieldName}"`
4256
+ `createMany is only valid on to-many relations ("${ctx.model}.${ctx.fieldName}")`
3991
4257
  );
3992
- for (const key of Object.keys(config)) {
3993
- if (!KNOWN_RELATION_WRITE_OPS.has(key)) {
3994
- throw new ShapeError(
3995
- `Unknown relation write operation "${key}" on "${model}.${fieldName}". Allowed: ${[...KNOWN_RELATION_WRITE_OPS].join(", ")}`
3996
- );
3997
- }
3998
4258
  }
3999
- const opSchemas = {};
4000
- if (config.connect !== void 0) {
4001
- if (!isPlainObject(config.connect)) {
4259
+ const cfg = requirePlainObjectConfig(
4260
+ ctx.config,
4261
+ `createMany config on "${ctx.model}.${ctx.fieldName}" must be an object`
4262
+ );
4263
+ validateRelationOpKeys(cfg, "createMany", ctx.model, ctx.fieldName, "createMany");
4264
+ const data = requireNestedObject(
4265
+ cfg,
4266
+ "data",
4267
+ `createMany on "${ctx.model}.${ctx.fieldName}" requires "data" object`
4268
+ );
4269
+ const dataSchema = buildNestedData(ctx, data, "create");
4270
+ const cmSchemaFields = {
4271
+ data: import_zod10.z.preprocess(coerceToArray, import_zod10.z.array(dataSchema))
4272
+ };
4273
+ if ("skipDuplicates" in cfg) {
4274
+ cmSchemaFields["skipDuplicates"] = import_zod10.z.boolean().optional();
4275
+ }
4276
+ return import_zod10.z.object(cmSchemaFields).strict().optional();
4277
+ };
4278
+ var handleDisconnect = (ctx) => {
4279
+ if (ctx.config === true) {
4280
+ if (ctx.isList) {
4002
4281
  throw new ShapeError(
4003
- `connect config on "${model}.${fieldName}" must be an object of field names`
4282
+ `disconnect on to-many relation "${ctx.model}.${ctx.fieldName}" requires unique selector config, not true`
4004
4283
  );
4005
4284
  }
4006
- const connectSchema = buildWhereFieldsSchema(
4007
- relatedModelName,
4008
- config.connect,
4009
- typeMap,
4010
- schemaBuilder
4285
+ return import_zod10.z.literal(true).optional();
4286
+ }
4287
+ if (!isPlainObject(ctx.config)) {
4288
+ throw new ShapeError(
4289
+ `disconnect config on "${ctx.model}.${ctx.fieldName}" must be true (to-one) or an object of unique selectors`
4011
4290
  );
4012
- opSchemas["connect"] = isList ? import_zod8.z.union([
4013
- connectSchema,
4014
- import_zod8.z.preprocess(coerceToArray, import_zod8.z.array(connectSchema))
4015
- ]).optional() : connectSchema.optional();
4016
4291
  }
4017
- if (config.connectOrCreate !== void 0) {
4018
- if (!isPlainObject(config.connectOrCreate)) {
4019
- throw new ShapeError(
4020
- `connectOrCreate config on "${model}.${fieldName}" must be an object with "where" and "create"`
4021
- );
4022
- }
4023
- const coc = config.connectOrCreate;
4024
- if (!coc.where || !isPlainObject(coc.where)) {
4025
- throw new ShapeError(
4026
- `connectOrCreate on "${model}.${fieldName}" requires "where" object`
4027
- );
4028
- }
4029
- if (!coc.create || !isPlainObject(coc.create)) {
4292
+ const schema = buildUniqueSelector(ctx, ctx.config, "disconnect");
4293
+ if (ctx.isList)
4294
+ return wrapRelationOp(true, schema);
4295
+ return import_zod10.z.union([import_zod10.z.literal(true), schema]).optional();
4296
+ };
4297
+ var handleDelete = (ctx) => {
4298
+ if (ctx.config === true) {
4299
+ if (ctx.isList) {
4030
4300
  throw new ShapeError(
4031
- `connectOrCreate on "${model}.${fieldName}" requires "create" object`
4301
+ `delete on to-many relation "${ctx.model}.${ctx.fieldName}" requires unique selector config, not true`
4032
4302
  );
4033
4303
  }
4034
- const whereSchema = buildWhereFieldsSchema(
4035
- relatedModelName,
4036
- coc.where,
4037
- typeMap,
4038
- schemaBuilder
4039
- );
4040
- const createSchema = buildNestedDataSchema(
4041
- relatedModelName,
4042
- coc.create,
4043
- typeMap,
4044
- schemaBuilder
4304
+ return import_zod10.z.literal(true).optional();
4305
+ }
4306
+ if (!isPlainObject(ctx.config)) {
4307
+ throw new ShapeError(
4308
+ `delete config on "${ctx.model}.${ctx.fieldName}" must be true (to-one) or an object of unique selectors`
4045
4309
  );
4046
- const cocSchema = import_zod8.z.object({ where: whereSchema, create: createSchema }).strict();
4047
- opSchemas["connectOrCreate"] = isList ? import_zod8.z.union([cocSchema, import_zod8.z.preprocess(coerceToArray, import_zod8.z.array(cocSchema))]).optional() : cocSchema.optional();
4048
4310
  }
4049
- if (config.create !== void 0) {
4050
- if (!isPlainObject(config.create)) {
4051
- throw new ShapeError(
4052
- `create config on "${model}.${fieldName}" must be an object of field names`
4053
- );
4054
- }
4055
- const createSchema = buildNestedDataSchema(
4056
- relatedModelName,
4057
- config.create,
4058
- typeMap,
4059
- schemaBuilder
4311
+ const schema = buildUniqueSelector(ctx, ctx.config, "delete");
4312
+ if (ctx.isList)
4313
+ return wrapRelationOp(true, schema);
4314
+ return import_zod10.z.union([import_zod10.z.literal(true), schema]).optional();
4315
+ };
4316
+ var handleSet = (ctx) => {
4317
+ if (!ctx.isList) {
4318
+ throw new ShapeError(
4319
+ `set is only valid on to-many relations ("${ctx.model}.${ctx.fieldName}")`
4060
4320
  );
4061
- opSchemas["create"] = isList ? import_zod8.z.union([
4062
- createSchema,
4063
- import_zod8.z.preprocess(coerceToArray, import_zod8.z.array(createSchema))
4064
- ]).optional() : createSchema.optional();
4065
4321
  }
4066
- if (config.createMany !== void 0) {
4067
- if (!isList) {
4068
- throw new ShapeError(
4069
- `createMany is only valid on to-many relations ("${model}.${fieldName}")`
4070
- );
4071
- }
4072
- if (!isPlainObject(config.createMany)) {
4073
- throw new ShapeError(
4074
- `createMany config on "${model}.${fieldName}" must be an object`
4075
- );
4076
- }
4077
- const cmConfig = config.createMany;
4078
- if (!cmConfig.data || !isPlainObject(cmConfig.data)) {
4079
- throw new ShapeError(
4080
- `createMany on "${model}.${fieldName}" requires "data" object`
4081
- );
4082
- }
4083
- const dataSchema = buildNestedDataSchema(
4084
- relatedModelName,
4085
- cmConfig.data,
4086
- typeMap,
4087
- schemaBuilder
4322
+ const cfg = requirePlainObjectConfig(
4323
+ ctx.config,
4324
+ `set config on "${ctx.model}.${ctx.fieldName}" must be an object of unique selectors`
4325
+ );
4326
+ const schema = buildUniqueSelector(ctx, cfg, "set");
4327
+ return wrapRelationOp(true, schema);
4328
+ };
4329
+ var handleUpdate = (ctx) => {
4330
+ const cfg = requirePlainObjectConfig(
4331
+ ctx.config,
4332
+ `update config on "${ctx.model}.${ctx.fieldName}" must be an object`
4333
+ );
4334
+ if (ctx.isList) {
4335
+ validateRelationOpKeys(cfg, "update.toMany", ctx.model, ctx.fieldName, "update");
4336
+ const where = requireNestedObject(
4337
+ cfg,
4338
+ "where",
4339
+ `update on to-many "${ctx.model}.${ctx.fieldName}" requires "where" object`
4088
4340
  );
4089
- const cmSchemaFields = {
4090
- data: import_zod8.z.preprocess(coerceToArray, import_zod8.z.array(dataSchema))
4091
- };
4092
- if ("skipDuplicates" in cmConfig) {
4093
- cmSchemaFields["skipDuplicates"] = import_zod8.z.boolean().optional();
4094
- }
4095
- opSchemas["createMany"] = import_zod8.z.object(cmSchemaFields).strict().optional();
4341
+ const data = requireNestedObject(
4342
+ cfg,
4343
+ "data",
4344
+ `update on to-many "${ctx.model}.${ctx.fieldName}" requires "data" object`
4345
+ );
4346
+ const whereSchema = buildUniqueSelector(ctx, where, "update.where");
4347
+ const dataSchema2 = buildNestedData(ctx, data, "update");
4348
+ const updateSchema = import_zod10.z.object({ where: whereSchema, data: dataSchema2 }).strict();
4349
+ return wrapRelationOp(true, updateSchema);
4096
4350
  }
4097
- if (config.disconnect !== void 0) {
4098
- if (config.disconnect === true) {
4099
- if (isList) {
4100
- throw new ShapeError(
4101
- `disconnect on to-many relation "${model}.${fieldName}" requires field config, not true`
4102
- );
4103
- }
4104
- opSchemas["disconnect"] = import_zod8.z.literal(true).optional();
4105
- } else if (isPlainObject(config.disconnect)) {
4106
- const disconnectSchema = buildWhereFieldsSchema(
4107
- relatedModelName,
4108
- config.disconnect,
4109
- typeMap,
4110
- schemaBuilder
4111
- );
4112
- if (isList) {
4113
- opSchemas["disconnect"] = import_zod8.z.union([
4114
- disconnectSchema,
4115
- import_zod8.z.preprocess(coerceToArray, import_zod8.z.array(disconnectSchema))
4116
- ]).optional();
4117
- } else {
4118
- opSchemas["disconnect"] = import_zod8.z.union([import_zod8.z.literal(true), disconnectSchema]).optional();
4119
- }
4120
- } else {
4121
- throw new ShapeError(
4122
- `disconnect config on "${model}.${fieldName}" must be true (to-one) or an object of field names`
4123
- );
4124
- }
4351
+ const dataSchema = buildNestedData(ctx, cfg, "update");
4352
+ return dataSchema.optional();
4353
+ };
4354
+ var handleUpsert = (ctx) => {
4355
+ const cfg = requirePlainObjectConfig(
4356
+ ctx.config,
4357
+ `upsert config on "${ctx.model}.${ctx.fieldName}" must be an object`
4358
+ );
4359
+ validateRelationOpKeys(
4360
+ cfg,
4361
+ ctx.isList ? "upsert.toMany" : "upsert.toOne",
4362
+ ctx.model,
4363
+ ctx.fieldName,
4364
+ "upsert"
4365
+ );
4366
+ const create = requireNestedObject(
4367
+ cfg,
4368
+ "create",
4369
+ `upsert on "${ctx.model}.${ctx.fieldName}" requires "create" object`
4370
+ );
4371
+ const update = requireNestedObject(
4372
+ cfg,
4373
+ "update",
4374
+ `upsert on "${ctx.model}.${ctx.fieldName}" requires "update" object`
4375
+ );
4376
+ const createSchema = buildNestedData(ctx, create, "create");
4377
+ const updateSchema = buildNestedData(ctx, update, "update");
4378
+ if (ctx.isList) {
4379
+ const where = requireNestedObject(
4380
+ cfg,
4381
+ "where",
4382
+ `upsert on to-many "${ctx.model}.${ctx.fieldName}" requires "where" object`
4383
+ );
4384
+ const whereSchema = buildUniqueSelector(ctx, where, "upsert.where");
4385
+ const upsertSchema2 = import_zod10.z.object({ where: whereSchema, create: createSchema, update: updateSchema }).strict();
4386
+ return wrapRelationOp(true, upsertSchema2);
4125
4387
  }
4126
- if (config.delete !== void 0) {
4127
- if (config.delete === true) {
4128
- if (isList) {
4129
- throw new ShapeError(
4130
- `delete on to-many relation "${model}.${fieldName}" requires field config, not true`
4131
- );
4132
- }
4133
- opSchemas["delete"] = import_zod8.z.literal(true).optional();
4134
- } else if (isPlainObject(config.delete)) {
4135
- const deleteSchema = buildWhereFieldsSchema(
4136
- relatedModelName,
4137
- config.delete,
4138
- typeMap,
4139
- schemaBuilder
4140
- );
4141
- if (isList) {
4142
- opSchemas["delete"] = import_zod8.z.union([
4143
- deleteSchema,
4144
- import_zod8.z.preprocess(coerceToArray, import_zod8.z.array(deleteSchema))
4145
- ]).optional();
4146
- } else {
4147
- opSchemas["delete"] = import_zod8.z.union([import_zod8.z.literal(true), deleteSchema]).optional();
4148
- }
4149
- } else {
4388
+ const hasWhereKey = "where" in cfg;
4389
+ if (hasWhereKey) {
4390
+ if (!isPlainObject(cfg.where)) {
4150
4391
  throw new ShapeError(
4151
- `delete config on "${model}.${fieldName}" must be true (to-one) or an object of field names`
4392
+ `upsert on to-one "${ctx.model}.${ctx.fieldName}" has invalid "where": must be a plain object of unique selectors`
4152
4393
  );
4153
4394
  }
4395
+ const whereSchema = buildUniqueSelector(ctx, cfg.where, "upsert.where");
4396
+ const upsertSchema2 = import_zod10.z.object({ where: whereSchema, create: createSchema, update: updateSchema }).strict();
4397
+ return upsertSchema2.optional();
4154
4398
  }
4155
- if (config.set !== void 0) {
4156
- if (!isList) {
4157
- throw new ShapeError(
4158
- `set is only valid on to-many relations ("${model}.${fieldName}")`
4159
- );
4160
- }
4161
- if (!isPlainObject(config.set)) {
4162
- throw new ShapeError(
4163
- `set config on "${model}.${fieldName}" must be an object of field names`
4164
- );
4165
- }
4166
- const setSchema = buildWhereFieldsSchema(
4167
- relatedModelName,
4168
- config.set,
4169
- typeMap,
4170
- schemaBuilder
4399
+ const upsertSchema = import_zod10.z.object({ create: createSchema, update: updateSchema }).strict();
4400
+ return upsertSchema.optional();
4401
+ };
4402
+ var handleUpdateMany = (ctx) => {
4403
+ if (!ctx.isList) {
4404
+ throw new ShapeError(
4405
+ `updateMany is only valid on to-many relations ("${ctx.model}.${ctx.fieldName}")`
4171
4406
  );
4172
- opSchemas["set"] = import_zod8.z.preprocess(coerceToArray, import_zod8.z.array(setSchema)).optional();
4173
- }
4174
- if (config.update !== void 0) {
4175
- if (!isPlainObject(config.update)) {
4176
- throw new ShapeError(
4177
- `update config on "${model}.${fieldName}" must be an object`
4178
- );
4179
- }
4180
- const updateConfig = config.update;
4181
- if (isList) {
4182
- if (!updateConfig.where || !isPlainObject(updateConfig.where)) {
4183
- throw new ShapeError(
4184
- `update on to-many "${model}.${fieldName}" requires "where" object`
4185
- );
4186
- }
4187
- if (!updateConfig.data || !isPlainObject(updateConfig.data)) {
4188
- throw new ShapeError(
4189
- `update on to-many "${model}.${fieldName}" requires "data" object`
4190
- );
4191
- }
4192
- const whereSchema = buildWhereFieldsSchema(
4193
- relatedModelName,
4194
- updateConfig.where,
4195
- typeMap,
4196
- schemaBuilder
4197
- );
4198
- const dataSchema = buildNestedDataSchema(
4199
- relatedModelName,
4200
- updateConfig.data,
4201
- typeMap,
4202
- schemaBuilder
4203
- );
4204
- const updateSchema = import_zod8.z.object({ where: whereSchema, data: dataSchema }).strict();
4205
- opSchemas["update"] = import_zod8.z.union([
4206
- updateSchema,
4207
- import_zod8.z.preprocess(coerceToArray, import_zod8.z.array(updateSchema))
4208
- ]).optional();
4209
- } else {
4210
- const dataSchema = buildNestedDataSchema(
4211
- relatedModelName,
4212
- updateConfig,
4213
- typeMap,
4214
- schemaBuilder
4215
- );
4216
- opSchemas["update"] = dataSchema.optional();
4217
- }
4218
4407
  }
4219
- if (config.upsert !== void 0) {
4220
- if (!isPlainObject(config.upsert)) {
4221
- throw new ShapeError(
4222
- `upsert config on "${model}.${fieldName}" must be an object`
4223
- );
4224
- }
4225
- const upsertConfig = config.upsert;
4226
- if (!upsertConfig.create || !isPlainObject(upsertConfig.create)) {
4227
- throw new ShapeError(
4228
- `upsert on "${model}.${fieldName}" requires "create" object`
4229
- );
4230
- }
4231
- if (!upsertConfig.update || !isPlainObject(upsertConfig.update)) {
4232
- throw new ShapeError(
4233
- `upsert on "${model}.${fieldName}" requires "update" object`
4234
- );
4235
- }
4236
- const createSchema = buildNestedDataSchema(
4237
- relatedModelName,
4238
- upsertConfig.create,
4239
- typeMap,
4240
- schemaBuilder
4408
+ const cfg = requirePlainObjectConfig(
4409
+ ctx.config,
4410
+ `updateMany config on "${ctx.model}.${ctx.fieldName}" must be an object`
4411
+ );
4412
+ validateRelationOpKeys(cfg, "updateMany", ctx.model, ctx.fieldName, "updateMany");
4413
+ const where = requireNestedObject(
4414
+ cfg,
4415
+ "where",
4416
+ `updateMany on "${ctx.model}.${ctx.fieldName}" requires "where" object`
4417
+ );
4418
+ if (Object.keys(where).length === 0) {
4419
+ throw new ShapeError(
4420
+ `updateMany "where" on "${ctx.model}.${ctx.fieldName}" must define at least one filter field`
4241
4421
  );
4242
- const updateSchema = buildNestedDataSchema(
4243
- relatedModelName,
4244
- upsertConfig.update,
4245
- typeMap,
4246
- schemaBuilder
4422
+ }
4423
+ const data = requireNestedObject(
4424
+ cfg,
4425
+ "data",
4426
+ `updateMany on "${ctx.model}.${ctx.fieldName}" requires "data" object`
4427
+ );
4428
+ if (Object.keys(data).length === 0) {
4429
+ throw new ShapeError(
4430
+ `updateMany "data" on "${ctx.model}.${ctx.fieldName}" must define at least one field`
4247
4431
  );
4248
- if (isList) {
4249
- if (!upsertConfig.where || !isPlainObject(upsertConfig.where)) {
4250
- throw new ShapeError(
4251
- `upsert on to-many "${model}.${fieldName}" requires "where" object`
4252
- );
4253
- }
4254
- const whereSchema = buildWhereFieldsSchema(
4255
- relatedModelName,
4256
- upsertConfig.where,
4257
- typeMap,
4258
- schemaBuilder
4259
- );
4260
- const upsertSchema = import_zod8.z.object({
4261
- where: whereSchema,
4262
- create: createSchema,
4263
- update: updateSchema
4264
- }).strict();
4265
- opSchemas["upsert"] = import_zod8.z.union([
4266
- upsertSchema,
4267
- import_zod8.z.preprocess(coerceToArray, import_zod8.z.array(upsertSchema))
4268
- ]).optional();
4269
- } else {
4270
- if (upsertConfig.where) {
4271
- const whereSchema = buildWhereFieldsSchema(
4272
- relatedModelName,
4273
- upsertConfig.where,
4274
- typeMap,
4275
- schemaBuilder
4276
- );
4277
- const upsertSchema = import_zod8.z.object({
4278
- where: whereSchema,
4279
- create: createSchema,
4280
- update: updateSchema
4281
- }).strict();
4282
- opSchemas["upsert"] = upsertSchema.optional();
4283
- } else {
4284
- const upsertSchema = import_zod8.z.object({ create: createSchema, update: updateSchema }).strict();
4285
- opSchemas["upsert"] = upsertSchema.optional();
4286
- }
4287
- }
4288
4432
  }
4289
- if (config.updateMany !== void 0) {
4290
- if (!isList) {
4291
- throw new ShapeError(
4292
- `updateMany is only valid on to-many relations ("${model}.${fieldName}")`
4293
- );
4294
- }
4295
- if (!isPlainObject(config.updateMany)) {
4296
- throw new ShapeError(
4297
- `updateMany config on "${model}.${fieldName}" must be an object`
4298
- );
4299
- }
4300
- const umConfig = config.updateMany;
4301
- if (!umConfig.where || !isPlainObject(umConfig.where)) {
4302
- throw new ShapeError(
4303
- `updateMany on "${model}.${fieldName}" requires "where" object`
4304
- );
4305
- }
4306
- if (!umConfig.data || !isPlainObject(umConfig.data)) {
4307
- throw new ShapeError(
4308
- `updateMany on "${model}.${fieldName}" requires "data" object`
4309
- );
4310
- }
4311
- const whereSchema = buildWhereFieldsSchema(
4312
- relatedModelName,
4313
- umConfig.where,
4314
- typeMap,
4315
- schemaBuilder
4433
+ const whereSchema = buildWhereFieldsSchema(
4434
+ ctx.relatedModelName,
4435
+ where,
4436
+ ctx.typeMap,
4437
+ ctx.schemaBuilder
4438
+ );
4439
+ const dataSchema = buildNestedData(ctx, data, "update");
4440
+ const umSchema = import_zod10.z.object({ where: whereSchema, data: dataSchema }).strict();
4441
+ return wrapRelationOp(true, umSchema);
4442
+ };
4443
+ var handleDeleteMany = (ctx) => {
4444
+ if (!ctx.isList) {
4445
+ throw new ShapeError(
4446
+ `deleteMany is only valid on to-many relations ("${ctx.model}.${ctx.fieldName}")`
4316
4447
  );
4317
- const dataSchema = buildNestedDataSchema(
4318
- relatedModelName,
4319
- umConfig.data,
4320
- typeMap,
4321
- schemaBuilder
4448
+ }
4449
+ const cfg = requirePlainObjectConfig(
4450
+ ctx.config,
4451
+ `deleteMany config on "${ctx.model}.${ctx.fieldName}" must be an object of allowed filter fields`
4452
+ );
4453
+ if (Object.keys(cfg).length === 0) {
4454
+ throw new ShapeError(
4455
+ `deleteMany config on "${ctx.model}.${ctx.fieldName}" is empty. Unconstrained nested deletes are not allowed. Define at least one allowed filter field.`
4322
4456
  );
4323
- const umSchema = import_zod8.z.object({ where: whereSchema, data: dataSchema }).strict();
4324
- opSchemas["updateMany"] = import_zod8.z.union([umSchema, import_zod8.z.preprocess(coerceToArray, import_zod8.z.array(umSchema))]).optional();
4325
4457
  }
4326
- if (config.deleteMany !== void 0) {
4327
- if (!isList) {
4328
- throw new ShapeError(
4329
- `deleteMany is only valid on to-many relations ("${model}.${fieldName}")`
4330
- );
4331
- }
4332
- if (!isPlainObject(config.deleteMany)) {
4458
+ const filterSchema = buildWhereFieldsSchema(
4459
+ ctx.relatedModelName,
4460
+ cfg,
4461
+ ctx.typeMap,
4462
+ ctx.schemaBuilder
4463
+ );
4464
+ return wrapRelationOp(true, filterSchema);
4465
+ };
4466
+ var RELATION_OP_HANDLERS = {
4467
+ connect: handleConnect,
4468
+ connectOrCreate: handleConnectOrCreate,
4469
+ create: handleCreate,
4470
+ createMany: handleCreateMany,
4471
+ disconnect: handleDisconnect,
4472
+ delete: handleDelete,
4473
+ set: handleSet,
4474
+ update: handleUpdate,
4475
+ upsert: handleUpsert,
4476
+ updateMany: handleUpdateMany,
4477
+ deleteMany: handleDeleteMany
4478
+ };
4479
+ var KNOWN_RELATION_WRITE_OPS = new Set(Object.keys(RELATION_OP_HANDLERS));
4480
+ function buildRelationWriteSchema(model, fieldName, relatedModelName, isList, config, typeMap, uniqueMap, enumMap, scalarBase, schemaBuilder) {
4481
+ const relatedFields = typeMap[relatedModelName];
4482
+ if (!relatedFields)
4483
+ throw new ShapeError(
4484
+ `Unknown related model "${relatedModelName}" for field "${model}.${fieldName}"`
4485
+ );
4486
+ for (const key of Object.keys(config)) {
4487
+ if (!KNOWN_RELATION_WRITE_OPS.has(key)) {
4333
4488
  throw new ShapeError(
4334
- `deleteMany config on "${model}.${fieldName}" must be an object of allowed filter fields`
4489
+ `Unknown relation write operation "${key}" on "${model}.${fieldName}". Allowed: ${[...KNOWN_RELATION_WRITE_OPS].join(", ")}`
4335
4490
  );
4336
4491
  }
4337
- const filterSchema = buildWhereFieldsSchema(
4492
+ }
4493
+ const opSchemas = {};
4494
+ for (const [op, opConfig] of Object.entries(config)) {
4495
+ if (opConfig === void 0)
4496
+ continue;
4497
+ const handler = RELATION_OP_HANDLERS[op];
4498
+ opSchemas[op] = handler({
4499
+ model,
4500
+ fieldName,
4338
4501
  relatedModelName,
4339
- config.deleteMany,
4502
+ isList,
4503
+ config: opConfig,
4340
4504
  typeMap,
4505
+ uniqueMap,
4506
+ enumMap,
4507
+ scalarBase,
4341
4508
  schemaBuilder
4342
- );
4343
- opSchemas["deleteMany"] = import_zod8.z.union([
4344
- filterSchema,
4345
- import_zod8.z.preprocess(coerceToArray, import_zod8.z.array(filterSchema)),
4346
- import_zod8.z.object({}).strict()
4347
- ]).optional();
4509
+ });
4348
4510
  }
4349
- return import_zod8.z.object(opSchemas).strict();
4511
+ return import_zod10.z.object(opSchemas).strict();
4350
4512
  }
4351
- function buildDataSchema(model, dataConfig, mode, typeMap, schemaBuilder, zodDefaults) {
4513
+ function buildDataSchema(model, dataConfig, mode, typeMap, uniqueMap, enumMap, scalarBase, schemaBuilder, zodDefaults) {
4352
4514
  const modelFields = typeMap[model];
4353
4515
  if (!modelFields)
4354
4516
  throw new ShapeError(`Unknown model: ${model}`);
@@ -4360,11 +4522,23 @@ function buildDataSchema(model, dataConfig, mode, typeMap, schemaBuilder, zodDef
4360
4522
  const fieldMeta = modelFields[fieldName];
4361
4523
  if (!fieldMeta) {
4362
4524
  if (isUnsupportedMarker(value)) {
4363
- schemaMap[fieldName] = import_zod8.z.unknown().optional();
4364
4525
  continue;
4365
4526
  }
4366
4527
  throw new ShapeError(`Unknown field "${fieldName}" on model "${model}"`);
4367
4528
  }
4529
+ if (fieldMeta.isUnsupported) {
4530
+ if (isUnsupportedMarker(value)) {
4531
+ continue;
4532
+ }
4533
+ if (value === true || typeof value === "function") {
4534
+ throw new ShapeError(
4535
+ `Field "${fieldName}" on model "${model}" has an Unsupported type and cannot be client-controlled. Use unsupported() to acknowledge it or a forced server value.`
4536
+ );
4537
+ }
4538
+ const actualValue = isForcedValue(value) ? value.value : value;
4539
+ forced[fieldName] = deepClone(actualValue);
4540
+ continue;
4541
+ }
4368
4542
  if (fieldMeta.isRelation) {
4369
4543
  if (!isPlainObject(value)) {
4370
4544
  throw new ShapeError(
@@ -4378,6 +4552,9 @@ function buildDataSchema(model, dataConfig, mode, typeMap, schemaBuilder, zodDef
4378
4552
  fieldMeta.isList,
4379
4553
  value,
4380
4554
  typeMap,
4555
+ uniqueMap,
4556
+ enumMap,
4557
+ scalarBase,
4381
4558
  schemaBuilder
4382
4559
  ).optional();
4383
4560
  continue;
@@ -4387,7 +4564,7 @@ function buildDataSchema(model, dataConfig, mode, typeMap, schemaBuilder, zodDef
4387
4564
  `updatedAt field "${fieldName}" cannot be used in data shape`
4388
4565
  );
4389
4566
  if (typeof value === "function") {
4390
- let baseSchema = schemaBuilder.buildBaseFieldSchema(
4567
+ const baseSchema = schemaBuilder.buildBaseFieldSchema(
4391
4568
  model,
4392
4569
  fieldName
4393
4570
  );
@@ -4405,46 +4582,22 @@ function buildDataSchema(model, dataConfig, mode, typeMap, schemaBuilder, zodDef
4405
4582
  `Inline refine for "${model}.${fieldName}" must return a Zod schema`
4406
4583
  );
4407
4584
  }
4408
- let fieldSchema = refined;
4409
- const handlesUndefined = schemaProducesValueForUndefined(fieldSchema);
4410
- if (mode === "create") {
4411
- if (!fieldMeta.isRequired) {
4412
- fieldSchema = handlesUndefined ? fieldSchema.nullable() : fieldSchema.nullable().optional();
4413
- } else if (fieldMeta.hasDefault) {
4414
- if (!handlesUndefined) {
4415
- fieldSchema = fieldSchema.optional();
4416
- }
4417
- }
4418
- } else {
4419
- if (!fieldMeta.isRequired) {
4420
- fieldSchema = fieldSchema.nullable().optional();
4421
- } else {
4422
- fieldSchema = fieldSchema.optional();
4423
- }
4424
- }
4425
- schemaMap[fieldName] = fieldSchema;
4426
- } else if (value === true) {
4427
- let fieldSchema = schemaBuilder.buildFieldSchema(
4428
- model,
4429
- fieldName
4585
+ const handlesUndefined = schemaProducesValueForUndefined(
4586
+ refined
4587
+ );
4588
+ schemaMap[fieldName] = applyCreateUpdateNullability(
4589
+ fieldMeta,
4590
+ refined,
4591
+ { mode, handlesUndefined }
4430
4592
  );
4593
+ } else if (value === true) {
4594
+ const fieldSchema = schemaBuilder.buildFieldSchema(model, fieldName);
4431
4595
  const isZodDefaultField = zodDefaultSet !== void 0 && zodDefaultSet.has(fieldName);
4432
- if (mode === "create") {
4433
- if (!fieldMeta.isRequired) {
4434
- fieldSchema = isZodDefaultField ? fieldSchema.nullable() : fieldSchema.nullable().optional();
4435
- } else if (fieldMeta.hasDefault) {
4436
- if (!isZodDefaultField) {
4437
- fieldSchema = fieldSchema.optional();
4438
- }
4439
- }
4440
- } else {
4441
- if (!fieldMeta.isRequired) {
4442
- fieldSchema = fieldSchema.nullable().optional();
4443
- } else {
4444
- fieldSchema = fieldSchema.optional();
4445
- }
4446
- }
4447
- schemaMap[fieldName] = fieldSchema;
4596
+ schemaMap[fieldName] = applyCreateUpdateNullability(
4597
+ fieldMeta,
4598
+ fieldSchema,
4599
+ { mode, handlesUndefined: isZodDefaultField }
4600
+ );
4448
4601
  } else {
4449
4602
  const actualValue = isForcedValue(value) ? value.value : value;
4450
4603
  let fieldSchema = schemaBuilder.buildFieldSchema(
@@ -4488,7 +4641,7 @@ function buildDataSchema(model, dataConfig, mode, typeMap, schemaBuilder, zodDef
4488
4641
  }
4489
4642
  }
4490
4643
  return {
4491
- schema: import_zod8.z.object(schemaMap).strict(),
4644
+ schema: import_zod10.z.object(schemaMap).strict(),
4492
4645
  forced
4493
4646
  };
4494
4647
  }
@@ -4525,106 +4678,120 @@ function isGuardShape(obj) {
4525
4678
  const keys = Object.keys(obj);
4526
4679
  return keys.length === 0 || keys.every((k) => GUARD_SHAPE_KEYS.has(k));
4527
4680
  }
4528
- function isSingleShape(input) {
4529
- return typeof input === "function" || isGuardShape(input);
4530
- }
4531
- function toPlainObject(value) {
4532
- if (value === null || typeof value !== "object")
4533
- return value;
4534
- if (Array.isArray(value))
4535
- return value.map(toPlainObject);
4536
- if (value instanceof Date)
4537
- return value;
4538
- if (value instanceof Uint8Array)
4539
- return value;
4540
- if (value instanceof RegExp)
4541
- return value;
4542
- if (typeof value.toFixed === "function" && typeof value.toNumber === "function")
4543
- return value;
4544
- const result = {};
4545
- for (const [k, v] of Object.entries(value)) {
4546
- result[k] = toPlainObject(v);
4681
+ function requireBody(body) {
4682
+ if (body === void 0 || body === null)
4683
+ return {};
4684
+ if (!isPlainObject(body)) {
4685
+ throw new ShapeError("Request body must be a plain object");
4547
4686
  }
4548
- return result;
4687
+ return body;
4549
4688
  }
4550
- function requireBody(body) {
4551
- const normalized = toPlainObject(body);
4552
- if (!isPlainObject(normalized))
4553
- throw new ShapeError("Request body must be an object");
4554
- return normalized;
4689
+ function assertNoCallerInBody(body) {
4690
+ if ("caller" in body) {
4691
+ throw new CallerError(
4692
+ "Pass caller via the guard(input, caller) argument, not in the request body."
4693
+ );
4694
+ }
4555
4695
  }
4556
- function resolveDynamicShape(fn, contextFn) {
4557
- const ctx = validateContext(contextFn());
4696
+ function resolveDynamicShape(shapeFn, ctx, context) {
4697
+ if (ctx === void 0) {
4698
+ throw new ShapeError(
4699
+ `Dynamic ${context} requires a context. Provide contextFn on the extension.`
4700
+ );
4701
+ }
4558
4702
  let result;
4559
4703
  try {
4560
- result = fn(ctx);
4704
+ result = shapeFn(ctx);
4561
4705
  } catch (err) {
4562
4706
  throw new ShapeError(
4563
- `Dynamic shape function threw: ${err.message}`,
4707
+ `Dynamic ${context} function threw: ${err.message}`,
4564
4708
  { cause: err }
4565
4709
  );
4566
4710
  }
4567
- if (!isPlainObject(result)) {
4568
- throw new ShapeError("Dynamic shape function must return a plain object");
4711
+ if (!isGuardShape(result)) {
4712
+ throw new ShapeError(
4713
+ `Dynamic ${context} function must return a valid guard shape object`
4714
+ );
4569
4715
  }
4570
4716
  return result;
4571
4717
  }
4572
- function resolveShape(input, body, contextFn, caller) {
4573
- if (isSingleShape(input)) {
4574
- const wasDynamic2 = typeof input === "function";
4575
- const shape2 = wasDynamic2 ? resolveDynamicShape(input, contextFn) : input;
4576
- const parsed2 = body === void 0 || body === null ? {} : requireBody(body);
4577
- return { shape: shape2, body: parsed2, matchedKey: "_default", wasDynamic: wasDynamic2 };
4578
- }
4579
- const namedMap = input;
4580
- for (const key of Object.keys(namedMap)) {
4718
+ function resolveNamedShape(input, body, contextFn, explicitCaller) {
4719
+ assertNoCallerInBody(body);
4720
+ const caller = explicitCaller;
4721
+ const keys = Object.keys(input);
4722
+ for (const key of keys) {
4581
4723
  if (GUARD_SHAPE_KEYS.has(key)) {
4582
4724
  throw new ShapeError(
4583
- `Caller key "${key}" collides with reserved shape config key. Rename the caller path.`
4584
- );
4585
- }
4586
- const val = namedMap[key];
4587
- if (typeof val !== "function" && !isGuardShape(val)) {
4588
- throw new ShapeError(
4589
- `Named shape value for "${key}" must be a guard shape object or function`
4725
+ `Caller key "${key}" collides with reserved guard shape key. Rename the caller path.`
4590
4726
  );
4591
4727
  }
4592
4728
  }
4593
- const parsed = body === void 0 || body === null ? {} : requireBody(body);
4594
- if ("caller" in parsed) {
4595
- throw new CallerError(
4596
- "Pass caller as second argument to .guard() or via context function, not in the request body."
4597
- );
4598
- }
4599
4729
  if (typeof caller !== "string") {
4600
- if ("default" in namedMap) {
4601
- const shapeOrFn2 = namedMap["default"];
4602
- const wasDynamic2 = typeof shapeOrFn2 === "function";
4603
- const shape2 = wasDynamic2 ? resolveDynamicShape(shapeOrFn2, contextFn) : shapeOrFn2;
4604
- return { shape: shape2, body: parsed, matchedKey: "default", wasDynamic: wasDynamic2 };
4730
+ if ("default" in input) {
4731
+ return resolveShapeEntry(input.default, body, contextFn, "default");
4605
4732
  }
4606
- const patterns2 = Object.keys(namedMap);
4607
4733
  throw new CallerError(
4608
- `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.`
4734
+ `Missing caller. This guard uses named shape routing with keys: ${keys.map((k) => `"${k}"`).join(", ")}. Provide caller via guard(input, caller).`
4609
4735
  );
4610
4736
  }
4611
- const patterns = Object.keys(namedMap);
4612
- const matched = matchCallerPattern(patterns, caller);
4613
- if (!matched) {
4614
- if ("default" in namedMap) {
4615
- const shapeOrFn2 = namedMap["default"];
4616
- const wasDynamic2 = typeof shapeOrFn2 === "function";
4617
- const shape2 = wasDynamic2 ? resolveDynamicShape(shapeOrFn2, contextFn) : shapeOrFn2;
4618
- return { shape: shape2, body: parsed, matchedKey: "default", wasDynamic: wasDynamic2 };
4619
- }
4620
- throw new CallerError(
4621
- `Unknown caller: "${caller}". Allowed: ${patterns.map((k) => `"${k}"`).join(", ")}`
4622
- );
4737
+ const matched = matchCallerPattern(keys, caller);
4738
+ if (matched) {
4739
+ return resolveShapeEntry(input[matched], body, contextFn, matched);
4740
+ }
4741
+ if ("default" in input) {
4742
+ return resolveShapeEntry(input.default, body, contextFn, "default");
4743
+ }
4744
+ throw new CallerError(
4745
+ `Unknown caller: "${caller}". Allowed: ${keys.map((k) => `"${k}"`).join(", ")}`
4746
+ );
4747
+ }
4748
+ function resolveShapeEntry(entry, body, contextFn, matchedKey) {
4749
+ if (typeof entry === "function") {
4750
+ const ctx = validateContext(contextFn());
4751
+ const shape = resolveDynamicShape(entry, ctx, `shape "${matchedKey}"`);
4752
+ return {
4753
+ shape,
4754
+ body,
4755
+ matchedKey,
4756
+ wasDynamic: true
4757
+ };
4758
+ }
4759
+ return {
4760
+ shape: entry,
4761
+ body,
4762
+ matchedKey,
4763
+ wasDynamic: false
4764
+ };
4765
+ }
4766
+ function resolveShape(input, rawBody, contextFn, explicitCaller) {
4767
+ const body = requireBody(rawBody);
4768
+ if (typeof input === "function") {
4769
+ const ctx = validateContext(contextFn());
4770
+ const shape = resolveDynamicShape(input, ctx, "shape");
4771
+ return {
4772
+ shape,
4773
+ body,
4774
+ matchedKey: "_default",
4775
+ wasDynamic: true
4776
+ };
4777
+ }
4778
+ if (isGuardShape(input)) {
4779
+ return {
4780
+ shape: input,
4781
+ body,
4782
+ matchedKey: "_default",
4783
+ wasDynamic: false
4784
+ };
4623
4785
  }
4624
- const shapeOrFn = namedMap[matched];
4625
- const wasDynamic = typeof shapeOrFn === "function";
4626
- const shape = wasDynamic ? resolveDynamicShape(shapeOrFn, contextFn) : shapeOrFn;
4627
- return { shape, body: parsed, matchedKey: matched, wasDynamic };
4786
+ if (!isPlainObject(input)) {
4787
+ throw new ShapeError("Guard input must be a shape object or a named map of shapes");
4788
+ }
4789
+ return resolveNamedShape(
4790
+ input,
4791
+ body,
4792
+ contextFn,
4793
+ explicitCaller
4794
+ );
4628
4795
  }
4629
4796
 
4630
4797
  // src/runtime/model-guard.ts
@@ -4647,129 +4814,20 @@ var PROJECTION_MUTATION_METHODS = /* @__PURE__ */ new Set([
4647
4814
  "updateManyAndReturn"
4648
4815
  ]);
4649
4816
  var BATCH_CREATE_METHODS = /* @__PURE__ */ new Set(["createMany", "createManyAndReturn"]);
4650
- function buildDefaultSelectInput(config) {
4651
- const result = {};
4652
- for (const [key, value] of Object.entries(config)) {
4653
- if (key === "_count") {
4654
- result[key] = buildDefaultCountInput(
4655
- value
4656
- );
4657
- continue;
4658
- }
4659
- if (value === true) {
4660
- result[key] = true;
4661
- } else {
4662
- const nested = {};
4663
- if (value.select)
4664
- nested.select = buildDefaultSelectInput(value.select);
4665
- if (value.include) {
4666
- nested.include = buildDefaultIncludeInput(value.include);
4667
- }
4668
- result[key] = Object.keys(nested).length > 0 ? nested : true;
4669
- }
4670
- }
4671
- return result;
4672
- }
4673
- function buildDefaultIncludeInput(config) {
4674
- const result = {};
4675
- for (const [key, value] of Object.entries(config)) {
4676
- if (key === "_count") {
4677
- result[key] = buildDefaultCountInput(
4678
- value
4679
- );
4680
- continue;
4681
- }
4682
- if (value === true) {
4683
- result[key] = true;
4684
- } else {
4685
- const nested = {};
4686
- if (value.include) {
4687
- nested.include = buildDefaultIncludeInput(value.include);
4688
- }
4689
- if (value.select)
4690
- nested.select = buildDefaultSelectInput(value.select);
4691
- result[key] = Object.keys(nested).length > 0 ? nested : true;
4692
- }
4693
- }
4694
- return result;
4695
- }
4696
- function buildDefaultCountInput(config) {
4697
- if (config === true)
4698
- return true;
4699
- if (!isPlainObject(config) || !config.select || !isPlainObject(config.select)) {
4700
- return true;
4701
- }
4702
- const selectObj = config.select;
4703
- const result = {};
4704
- for (const key of Object.keys(selectObj)) {
4705
- result[key] = true;
4706
- }
4707
- return { select: result };
4708
- }
4709
- function buildDefaultProjectionBody(shape) {
4710
- if (shape.select) {
4711
- return { select: buildDefaultSelectInput(shape.select) };
4712
- }
4713
- if (shape.include) {
4714
- return { include: buildDefaultIncludeInput(shape.include) };
4715
- }
4716
- return {};
4717
- }
4718
- function applyClientProjectionOverrides(shapeDefault, clientProjection) {
4719
- const result = { ...shapeDefault };
4720
- for (const [key, clientValue] of Object.entries(clientProjection)) {
4721
- const defaultValue = result[key];
4722
- if (defaultValue === void 0) {
4723
- result[key] = clientValue;
4724
- continue;
4725
- }
4726
- if (clientValue === true) {
4727
- result[key] = true;
4728
- continue;
4729
- }
4730
- if (isPlainObject(clientValue)) {
4731
- if (!isPlainObject(defaultValue)) {
4732
- result[key] = clientValue;
4733
- continue;
4734
- }
4735
- const merged = { ...defaultValue };
4736
- const clientObj = clientValue;
4737
- for (const [argKey, argValue] of Object.entries(clientObj)) {
4738
- const defaultArgValue = merged[argKey];
4739
- if ((argKey === "select" || argKey === "include") && isPlainObject(argValue) && isPlainObject(defaultArgValue)) {
4740
- merged[argKey] = applyClientProjectionOverrides(
4741
- defaultArgValue,
4742
- argValue
4743
- );
4744
- } else {
4745
- merged[argKey] = argValue;
4746
- }
4747
- }
4748
- result[key] = merged;
4749
- }
4750
- }
4751
- return result;
4752
- }
4753
- function hasClientControlledValues(obj) {
4754
- for (const value of Object.values(obj)) {
4755
- if (isForcedValue(value))
4756
- continue;
4757
- if (value === true)
4758
- return true;
4759
- if (isPlainObject(value) && hasClientControlledValues(value))
4817
+ var MAX_PROJECTION_WALK_DEPTH = 10;
4818
+ function walkForClientContent(obj, predicate, depth) {
4819
+ if (depth > MAX_PROJECTION_WALK_DEPTH)
4820
+ return false;
4821
+ for (const [key, value] of Object.entries(obj)) {
4822
+ if (predicate(value, depth))
4760
4823
  return true;
4761
- }
4762
- return false;
4763
- }
4764
- function checkIncludeForClientArgs(config) {
4765
- for (const [key, value] of Object.entries(config)) {
4766
4824
  if (key === "_count") {
4767
4825
  if (value !== true && isPlainObject(value) && isPlainObject(value.select)) {
4768
4826
  const selectObj = value.select;
4769
4827
  for (const entryVal of Object.values(selectObj)) {
4770
4828
  if (isPlainObject(entryVal) && entryVal.where) {
4771
4829
  const w = entryVal.where;
4772
- if (isPlainObject(w) && hasClientControlledValues(w))
4830
+ if (isPlainObject(w) && hasClientControlledValues(w, depth + 1))
4773
4831
  return true;
4774
4832
  }
4775
4833
  }
@@ -4778,54 +4836,41 @@ function checkIncludeForClientArgs(config) {
4778
4836
  }
4779
4837
  if (value === true)
4780
4838
  continue;
4781
- if (value.orderBy || value.cursor || value.take || value.skip)
4839
+ const nested = value;
4840
+ if (nested.orderBy || nested.cursor || nested.take || nested.skip)
4782
4841
  return true;
4783
- if (value.where && isPlainObject(value.where) && hasClientControlledValues(value.where)) {
4842
+ if (nested.where && isPlainObject(nested.where) && hasClientControlledValues(nested.where, depth + 1)) {
4784
4843
  return true;
4785
4844
  }
4786
- if (value.include && checkIncludeForClientArgs(value.include))
4845
+ if (nested.include && walkForClientContent(nested.include, predicate, depth + 1))
4787
4846
  return true;
4788
- if (value.select && checkSelectForClientArgs(value.select))
4847
+ if (nested.select && walkForClientContent(nested.select, predicate, depth + 1))
4789
4848
  return true;
4790
4849
  }
4791
4850
  return false;
4792
4851
  }
4793
- function checkSelectForClientArgs(config) {
4794
- for (const [key, value] of Object.entries(config)) {
4795
- if (key === "_count") {
4796
- if (value !== true && isPlainObject(value) && isPlainObject(value.select)) {
4797
- const selectObj = value.select;
4798
- for (const entryVal of Object.values(selectObj)) {
4799
- if (isPlainObject(entryVal) && entryVal.where) {
4800
- const w = entryVal.where;
4801
- if (isPlainObject(w) && hasClientControlledValues(w))
4802
- return true;
4803
- }
4804
- }
4805
- }
4852
+ function hasClientControlledValues(obj, depth = 0) {
4853
+ if (depth > MAX_PROJECTION_WALK_DEPTH)
4854
+ return false;
4855
+ for (const value of Object.values(obj)) {
4856
+ if (isForcedValue(value))
4806
4857
  continue;
4807
- }
4808
4858
  if (value === true)
4809
- continue;
4810
- if (value.orderBy || value.cursor || value.take || value.skip)
4811
4859
  return true;
4812
- if (value.where && isPlainObject(value.where) && hasClientControlledValues(value.where)) {
4860
+ if (isPlainObject(value) && hasClientControlledValues(value, depth + 1)) {
4813
4861
  return true;
4814
4862
  }
4815
- if (value.select && checkSelectForClientArgs(value.select))
4816
- return true;
4817
- if (value.include && checkIncludeForClientArgs(value.include))
4818
- return true;
4819
4863
  }
4820
4864
  return false;
4821
4865
  }
4822
4866
  function hasNestedClientControlledArgs(shape) {
4867
+ const predicate = () => false;
4823
4868
  if (shape.include) {
4824
- if (checkIncludeForClientArgs(shape.include))
4869
+ if (walkForClientContent(shape.include, predicate, 0))
4825
4870
  return true;
4826
4871
  }
4827
4872
  if (shape.select) {
4828
- if (checkSelectForClientArgs(shape.select))
4873
+ if (walkForClientContent(shape.select, predicate, 0))
4829
4874
  return true;
4830
4875
  }
4831
4876
  return false;
@@ -4897,77 +4942,62 @@ function createModelGuardExtension(config) {
4897
4942
  const whereBuiltCache = /* @__PURE__ */ new Map();
4898
4943
  const projectionCache = /* @__PURE__ */ new Map();
4899
4944
  const uniqueWhereCache = /* @__PURE__ */ new Map();
4945
+ function memoize(cache, key, wasDynamic, build) {
4946
+ if (wasDynamic)
4947
+ return build();
4948
+ const cached = cache.get(key);
4949
+ if (cached)
4950
+ return cached;
4951
+ const built = build();
4952
+ cache.set(key, built);
4953
+ return built;
4954
+ }
4900
4955
  function getReadShape(method, queryShape, matchedKey, wasDynamic) {
4901
- if (!wasDynamic) {
4902
- const cacheKey = `${method}\0${matchedKey}`;
4903
- const cached = readShapeCache.get(cacheKey);
4904
- if (cached)
4905
- return cached;
4906
- const built = queryBuilder.buildShapeZodSchema(
4956
+ return memoize(
4957
+ readShapeCache,
4958
+ `${method}\0${matchedKey}`,
4959
+ wasDynamic,
4960
+ () => queryBuilder.buildShapeZodSchema(
4907
4961
  modelName,
4908
4962
  method,
4909
4963
  queryShape
4910
- );
4911
- readShapeCache.set(cacheKey, built);
4912
- return built;
4913
- }
4914
- return queryBuilder.buildShapeZodSchema(
4915
- modelName,
4916
- method,
4917
- queryShape
4964
+ )
4918
4965
  );
4919
4966
  }
4920
4967
  function getDataSchema(mode, dataConfig, matchedKey, wasDynamic) {
4921
- if (!wasDynamic && !hasDataRefines(dataConfig)) {
4922
- const cacheKey = `${mode}\0${matchedKey}`;
4923
- const cached = dataSchemaCache.get(cacheKey);
4924
- if (cached)
4925
- return cached;
4926
- const built = buildDataSchema(
4968
+ const skipCache = wasDynamic || hasDataRefines(dataConfig);
4969
+ return memoize(
4970
+ dataSchemaCache,
4971
+ `${mode}\0${matchedKey}`,
4972
+ skipCache,
4973
+ () => buildDataSchema(
4927
4974
  modelName,
4928
4975
  dataConfig,
4929
4976
  mode,
4930
4977
  typeMap,
4978
+ uniqueMap,
4979
+ enumMap,
4980
+ scalarBase,
4931
4981
  schemaBuilder,
4932
4982
  zodDefaults
4933
- );
4934
- dataSchemaCache.set(cacheKey, built);
4935
- return built;
4936
- }
4937
- return buildDataSchema(
4938
- modelName,
4939
- dataConfig,
4940
- mode,
4941
- typeMap,
4942
- schemaBuilder,
4943
- zodDefaults
4983
+ )
4944
4984
  );
4945
4985
  }
4946
4986
  function getWhereBuilt(whereConfig, matchedKey, wasDynamic) {
4947
- if (!wasDynamic) {
4948
- const cached = whereBuiltCache.get(matchedKey);
4949
- if (cached)
4950
- return cached;
4951
- const built = queryBuilder.buildWhereSchema(modelName, whereConfig);
4952
- whereBuiltCache.set(matchedKey, built);
4953
- return built;
4954
- }
4955
- return queryBuilder.buildWhereSchema(modelName, whereConfig);
4987
+ return memoize(
4988
+ whereBuiltCache,
4989
+ matchedKey,
4990
+ wasDynamic,
4991
+ () => queryBuilder.buildWhereSchema(modelName, whereConfig)
4992
+ );
4956
4993
  }
4957
4994
  function getUniqueWhereBuilt(whereConfig, matchedKey, wasDynamic) {
4958
- if (!wasDynamic) {
4959
- const cacheKey = `unique\0${matchedKey}`;
4960
- const cached = uniqueWhereCache.get(cacheKey);
4961
- if (cached)
4962
- return cached;
4963
- const built = queryBuilder.buildUniqueWhereSchema(
4964
- modelName,
4965
- whereConfig
4966
- );
4967
- uniqueWhereCache.set(cacheKey, built);
4968
- return built;
4969
- }
4970
- return queryBuilder.buildUniqueWhereSchema(modelName, whereConfig);
4995
+ return memoize(
4996
+ uniqueWhereCache,
4997
+ `unique\0${matchedKey}`,
4998
+ wasDynamic,
4999
+ () => queryBuilder.buildUniqueWhereSchema(modelName, whereConfig)
5000
+ );
4971
5001
  }
4972
5002
  function buildProjectionSchema(shape) {
4973
5003
  const schemaFields = {};
@@ -4994,7 +5024,7 @@ function createModelGuardExtension(config) {
4994
5024
  forcedSelectCountWhere = result.forcedCountWhere;
4995
5025
  }
4996
5026
  return {
4997
- zodSchema: import_zod9.z.object(schemaFields).strict(),
5027
+ zodSchema: import_zod11.z.object(schemaFields).strict(),
4998
5028
  forcedIncludeTree,
4999
5029
  forcedSelectTree,
5000
5030
  forcedIncludeCountWhere,
@@ -5002,16 +5032,12 @@ function createModelGuardExtension(config) {
5002
5032
  };
5003
5033
  }
5004
5034
  function getProjection(shape, matchedKey, wasDynamic) {
5005
- if (!wasDynamic) {
5006
- const cacheKey = `projection\0${matchedKey}`;
5007
- const cached = projectionCache.get(cacheKey);
5008
- if (cached)
5009
- return cached;
5010
- const built = buildProjectionSchema(shape);
5011
- projectionCache.set(cacheKey, built);
5012
- return built;
5013
- }
5014
- return buildProjectionSchema(shape);
5035
+ return memoize(
5036
+ projectionCache,
5037
+ `projection\0${matchedKey}`,
5038
+ wasDynamic,
5039
+ () => buildProjectionSchema(shape)
5040
+ );
5015
5041
  }
5016
5042
  function resolveProjection(shape, parsed, method, matchedKey, wasDynamic) {
5017
5043
  const hasBodyProjection = "select" in parsed || "include" in parsed;
@@ -5205,24 +5231,11 @@ function createModelGuardExtension(config) {
5205
5231
  const hasShapeProjection = !!resolved.shape.select || !!resolved.shape.include;
5206
5232
  if (!hasShapeProjection)
5207
5233
  return resolved.body;
5208
- const defaultProjection = buildDefaultProjectionBody(resolved.shape);
5209
5234
  const hasBodyProjection = "select" in resolved.body || "include" in resolved.body;
5210
- if (!hasBodyProjection) {
5211
- return { ...resolved.body, ...defaultProjection };
5212
- }
5213
- const merged = { ...resolved.body };
5214
- if ("select" in resolved.body && "select" in defaultProjection && isPlainObject(resolved.body.select) && isPlainObject(defaultProjection.select)) {
5215
- merged.select = applyClientProjectionOverrides(
5216
- defaultProjection.select,
5217
- resolved.body.select
5218
- );
5219
- } else if ("include" in resolved.body && "include" in defaultProjection && isPlainObject(resolved.body.include) && isPlainObject(defaultProjection.include)) {
5220
- merged.include = applyClientProjectionOverrides(
5221
- defaultProjection.include,
5222
- resolved.body.include
5223
- );
5224
- }
5225
- return merged;
5235
+ if (hasBodyProjection)
5236
+ return resolved.body;
5237
+ const defaultProjection = buildDefaultProjectionBody(resolved.shape);
5238
+ return { ...resolved.body, ...defaultProjection };
5226
5239
  }
5227
5240
  function makeReadMethod(method) {
5228
5241
  return (body) => {
@@ -5255,29 +5268,21 @@ function createModelGuardExtension(config) {
5255
5268
  function makeCreateMethod(method) {
5256
5269
  const isBatch = BATCH_CREATE_METHODS.has(method);
5257
5270
  const supportsProjection = PROJECTION_MUTATION_METHODS.has(method);
5258
- let allowedBodyKeys;
5259
- if (isBatch && supportsProjection) {
5260
- allowedBodyKeys = ALLOWED_BODY_KEYS_CREATE_MANY_PROJECTION;
5261
- } else if (isBatch) {
5262
- allowedBodyKeys = ALLOWED_BODY_KEYS_CREATE_MANY;
5263
- } else if (supportsProjection) {
5264
- allowedBodyKeys = ALLOWED_BODY_KEYS_CREATE_PROJECTION;
5265
- } else {
5266
- allowedBodyKeys = ALLOWED_BODY_KEYS_CREATE;
5267
- }
5268
- const allowedShapeKeys = supportsProjection ? VALID_SHAPE_KEYS_CREATE_PROJECTION : VALID_SHAPE_KEYS_CREATE;
5271
+ const allowedBodyKeys = getAllowedBodyKeys(method, supportsProjection);
5272
+ const allowedShapeKeys = getAllowedShapeKeys(method, supportsProjection);
5269
5273
  return (body) => {
5270
5274
  const caller = resolveCaller();
5271
5275
  const resolved = resolveShape(input, body, contextFn, caller);
5272
5276
  if (!resolved.shape.data) {
5273
5277
  throw new ShapeError(`Guard shape requires "data" for ${method}`);
5274
5278
  }
5275
- validateMutationShapeKeys(
5279
+ validateAllowedKeys(
5276
5280
  resolved.shape,
5277
5281
  allowedShapeKeys,
5278
- method
5282
+ method,
5283
+ "shape"
5279
5284
  );
5280
- validateMutationBodyKeys(resolved.body, allowedBodyKeys, method);
5285
+ validateAllowedKeys(resolved.body, allowedBodyKeys, method, "body");
5281
5286
  const fks = modelScopeFks.get(modelName) ?? /* @__PURE__ */ new Set();
5282
5287
  validateCreateCompleteness(
5283
5288
  modelName,
@@ -5336,20 +5341,21 @@ function createModelGuardExtension(config) {
5336
5341
  const isUniqueWhere = method === "update";
5337
5342
  const isBulk = BULK_MUTATION_METHODS.has(method);
5338
5343
  const supportsProjection = PROJECTION_MUTATION_METHODS.has(method);
5339
- const allowedBodyKeys = supportsProjection ? ALLOWED_BODY_KEYS_UPDATE_PROJECTION : ALLOWED_BODY_KEYS_UPDATE;
5340
- const allowedShapeKeys = supportsProjection ? VALID_SHAPE_KEYS_UPDATE_PROJECTION : VALID_SHAPE_KEYS_UPDATE;
5344
+ const allowedBodyKeys = getAllowedBodyKeys(method, supportsProjection);
5345
+ const allowedShapeKeys = getAllowedShapeKeys(method, supportsProjection);
5341
5346
  return (body) => {
5342
5347
  const caller = resolveCaller();
5343
5348
  const resolved = resolveShape(input, body, contextFn, caller);
5344
5349
  if (!resolved.shape.data) {
5345
5350
  throw new ShapeError(`Guard shape requires "data" for ${method}`);
5346
5351
  }
5347
- validateMutationShapeKeys(
5352
+ validateAllowedKeys(
5348
5353
  resolved.shape,
5349
5354
  allowedShapeKeys,
5350
- method
5355
+ method,
5356
+ "shape"
5351
5357
  );
5352
- validateMutationBodyKeys(resolved.body, allowedBodyKeys, method);
5358
+ validateAllowedKeys(resolved.body, allowedBodyKeys, method, "body");
5353
5359
  if (isBulk && !resolved.shape.where) {
5354
5360
  throw new ShapeError(
5355
5361
  `Guard shape requires "where" for ${method} to prevent unconstrained bulk mutations`
@@ -5417,20 +5423,21 @@ function createModelGuardExtension(config) {
5417
5423
  const isUniqueWhere = method === "delete";
5418
5424
  const isBulk = BULK_MUTATION_METHODS.has(method);
5419
5425
  const supportsProjection = PROJECTION_MUTATION_METHODS.has(method);
5420
- const allowedBodyKeys = supportsProjection ? ALLOWED_BODY_KEYS_DELETE_PROJECTION : ALLOWED_BODY_KEYS_DELETE;
5421
- const allowedShapeKeys = supportsProjection ? VALID_SHAPE_KEYS_DELETE_PROJECTION : VALID_SHAPE_KEYS_DELETE;
5426
+ const allowedBodyKeys = getAllowedBodyKeys(method, supportsProjection);
5427
+ const allowedShapeKeys = getAllowedShapeKeys(method, supportsProjection);
5422
5428
  return (body) => {
5423
5429
  const caller = resolveCaller();
5424
5430
  const resolved = resolveShape(input, body, contextFn, caller);
5425
5431
  if (resolved.shape.data) {
5426
5432
  throw new ShapeError(`Guard shape "data" is not valid for ${method}`);
5427
5433
  }
5428
- validateMutationShapeKeys(
5434
+ validateAllowedKeys(
5429
5435
  resolved.shape,
5430
5436
  allowedShapeKeys,
5431
- method
5437
+ method,
5438
+ "shape"
5432
5439
  );
5433
- validateMutationBodyKeys(resolved.body, allowedBodyKeys, method);
5440
+ validateAllowedKeys(resolved.body, allowedBodyKeys, method, "body");
5434
5441
  if (isBulk && !resolved.shape.where) {
5435
5442
  throw new ShapeError(
5436
5443
  `Guard shape requires "where" for ${method} to prevent unconstrained bulk mutations`
@@ -5483,6 +5490,8 @@ function createModelGuardExtension(config) {
5483
5490
  };
5484
5491
  }
5485
5492
  function makeUpsertMethod() {
5493
+ const allowedBodyKeys = getAllowedBodyKeys("upsert", true);
5494
+ const allowedShapeKeys = getAllowedShapeKeys("upsert", true);
5486
5495
  return (body) => {
5487
5496
  const caller = resolveCaller();
5488
5497
  const resolved = resolveShape(input, body, contextFn, caller);
@@ -5500,15 +5509,17 @@ function createModelGuardExtension(config) {
5500
5509
  if (!resolved.shape.where) {
5501
5510
  throw new ShapeError('Guard shape requires "where" for upsert');
5502
5511
  }
5503
- validateMutationShapeKeys(
5512
+ validateAllowedKeys(
5504
5513
  resolved.shape,
5505
- VALID_SHAPE_KEYS_UPSERT,
5506
- "upsert"
5514
+ allowedShapeKeys,
5515
+ "upsert",
5516
+ "shape"
5507
5517
  );
5508
- validateMutationBodyKeys(
5518
+ validateAllowedKeys(
5509
5519
  resolved.body,
5510
- ALLOWED_BODY_KEYS_UPSERT,
5511
- "upsert"
5520
+ allowedBodyKeys,
5521
+ "upsert",
5522
+ "body"
5512
5523
  );
5513
5524
  validateUniqueWhereShapeConfig(
5514
5525
  modelName,
@@ -5598,12 +5609,7 @@ function createModelGuardExtension(config) {
5598
5609
  try {
5599
5610
  return fn(body);
5600
5611
  } catch (err) {
5601
- if (err instanceof import_zod9.z.ZodError) {
5602
- throw new ShapeError(`Validation failed: ${formatZodError(err)}`, {
5603
- cause: err
5604
- });
5605
- }
5606
- throw err;
5612
+ throw toShapeError(err);
5607
5613
  }
5608
5614
  };
5609
5615
  }
@@ -5636,6 +5642,15 @@ function createModelGuardExtension(config) {
5636
5642
  }
5637
5643
 
5638
5644
  // src/runtime/guard.ts
5645
+ function wrapParseFn(fn) {
5646
+ return (...args) => {
5647
+ try {
5648
+ return fn(...args);
5649
+ } catch (err) {
5650
+ throw toShapeError(err);
5651
+ }
5652
+ };
5653
+ }
5639
5654
  function createGuard(config) {
5640
5655
  const scalarBase = createScalarBase(
5641
5656
  config.guardConfig.strictDecimal ?? false
@@ -5657,14 +5672,6 @@ function createGuard(config) {
5657
5672
  warn: (msg) => console.warn(msg)
5658
5673
  };
5659
5674
  const wrapZodErrors = config.wrapZodErrors ?? false;
5660
- function rethrowZod(err) {
5661
- if (err instanceof import_zod10.ZodError) {
5662
- throw new ShapeError(`Validation failed: ${formatZodError(err)}`, {
5663
- cause: err
5664
- });
5665
- }
5666
- throw err;
5667
- }
5668
5675
  return {
5669
5676
  input: (model, opts) => {
5670
5677
  const result = schemaBuilder.buildInputSchema(model, opts);
@@ -5672,13 +5679,7 @@ function createGuard(config) {
5672
5679
  return result;
5673
5680
  return {
5674
5681
  schema: result.schema,
5675
- parse(data) {
5676
- try {
5677
- return result.parse(data);
5678
- } catch (err) {
5679
- rethrowZod(err);
5680
- }
5681
- }
5682
+ parse: wrapParseFn(result.parse)
5682
5683
  };
5683
5684
  },
5684
5685
  model: (model, opts) => schemaBuilder.buildModelSchema(model, opts),
@@ -5688,13 +5689,7 @@ function createGuard(config) {
5688
5689
  return qs;
5689
5690
  return {
5690
5691
  schemas: qs.schemas,
5691
- parse(body, opts) {
5692
- try {
5693
- return qs.parse(body, opts);
5694
- } catch (err) {
5695
- rethrowZod(err);
5696
- }
5697
- }
5692
+ parse: wrapParseFn(qs.parse)
5698
5693
  };
5699
5694
  },
5700
5695
  extension: (contextFn) => {