prisma-guard 1.27.0 → 1.28.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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))
@@ -1027,12 +1139,18 @@ function tryInlineForcedField(result, field, forcedValue) {
1027
1139
  if (!isPlainObject(forcedValue))
1028
1140
  return false;
1029
1141
  const existing = result[field];
1030
- if (!isPlainObject(existing))
1031
- return false;
1142
+ if (!isPlainObject(existing)) {
1143
+ const merged2 = { equals: existing };
1144
+ for (const [op, value] of Object.entries(forcedValue)) {
1145
+ merged2[op] = deepClone(value);
1146
+ }
1147
+ result[field] = merged2;
1148
+ return true;
1149
+ }
1032
1150
  const merged = { ...existing };
1033
1151
  for (const [op, value] of Object.entries(forcedValue)) {
1034
1152
  if (op in merged) {
1035
- if (!forcedScalarsEqual(merged[op], value)) {
1153
+ if (!deepEqual(merged[op], value)) {
1036
1154
  throw new ShapeError(
1037
1155
  `Conflicting where values for "${field}.${op}": client provided a different value than the forced shape`
1038
1156
  );
@@ -1063,6 +1181,17 @@ function mergeWhereForced(where, forced) {
1063
1181
  if (Object.keys(forced.conditions).length > 0) {
1064
1182
  const remaining = {};
1065
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
+ }
1066
1195
  const inlined = tryInlineForcedField(result, field, forcedValue);
1067
1196
  if (!inlined) {
1068
1197
  remaining[field] = deepClone(forcedValue);
@@ -1078,32 +1207,6 @@ function mergeWhereForced(where, forced) {
1078
1207
  }
1079
1208
  return result;
1080
1209
  }
1081
- function uniqueValuesEqual(a, b) {
1082
- if (a === b)
1083
- return true;
1084
- if (a === null || b === null)
1085
- return false;
1086
- if (typeof a !== typeof b)
1087
- return false;
1088
- if (a instanceof Date && b instanceof Date) {
1089
- return a.getTime() === b.getTime();
1090
- }
1091
- if (Array.isArray(a)) {
1092
- if (!Array.isArray(b))
1093
- return false;
1094
- if (a.length !== b.length)
1095
- return false;
1096
- return a.every((v, i) => uniqueValuesEqual(v, b[i]));
1097
- }
1098
- if (isPlainObject(a) && isPlainObject(b)) {
1099
- const aKeys = Object.keys(a);
1100
- const bKeys = Object.keys(b);
1101
- if (aKeys.length !== bKeys.length)
1102
- return false;
1103
- return aKeys.every((key) => key in b && uniqueValuesEqual(a[key], b[key]));
1104
- }
1105
- return false;
1106
- }
1107
1210
  function mergeUniqueValue(target, key, value) {
1108
1211
  const cloned = deepClone(value);
1109
1212
  if (!(key in target)) {
@@ -1114,7 +1217,7 @@ function mergeUniqueValue(target, key, value) {
1114
1217
  if (isPlainObject(existing) && isPlainObject(cloned)) {
1115
1218
  const merged = { ...existing };
1116
1219
  for (const [nestedKey, nestedValue] of Object.entries(cloned)) {
1117
- if (nestedKey in merged && !uniqueValuesEqual(merged[nestedKey], nestedValue)) {
1220
+ if (nestedKey in merged && !deepEqual(merged[nestedKey], nestedValue)) {
1118
1221
  throw new ShapeError(
1119
1222
  `Conflicting unique where value for "${key}.${nestedKey}"`
1120
1223
  );
@@ -1124,7 +1227,7 @@ function mergeUniqueValue(target, key, value) {
1124
1227
  target[key] = merged;
1125
1228
  return;
1126
1229
  }
1127
- if (!uniqueValuesEqual(existing, cloned)) {
1230
+ if (!deepEqual(existing, cloned)) {
1128
1231
  throw new ShapeError(`Conflicting unique where value for "${key}"`);
1129
1232
  }
1130
1233
  }
@@ -1151,7 +1254,30 @@ function applyBuiltShape(built, body, isUniqueMethod, modelName) {
1151
1254
  throw new ShapeError('Request cannot define both "include" and "select"');
1152
1255
  }
1153
1256
  if ("where" in bodyObj) {
1154
- 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
+ }
1155
1281
  const { where: _, ...rest } = bodyObj;
1156
1282
  parseable = rest;
1157
1283
  } else if (isUniqueMethod && hasWhereForced(built.forcedWhere) && isPlainObject(bodyObj.where)) {
@@ -1227,6 +1353,86 @@ function buildCountForPlacement(countWhere) {
1227
1353
  }
1228
1354
  return { _count: { select: countSelect } };
1229
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
+ }
1230
1436
  function applyForcedTree(validated, key, tree) {
1231
1437
  const container = validated[key];
1232
1438
  if (!container)
@@ -1235,89 +1441,13 @@ function applyForcedTree(validated, key, tree) {
1235
1441
  const relVal = container[relName];
1236
1442
  if (relVal === void 0)
1237
1443
  continue;
1238
- if (relVal === true) {
1239
- const expanded = {};
1240
- if (forced.where && hasWhereForced(forced.where)) {
1241
- expanded.where = mergeWhereForced(void 0, forced.where);
1242
- }
1243
- if (forced.include) {
1244
- expanded.include = buildForcedOnlyContainer(forced.include);
1245
- applyForcedTree(expanded, "include", forced.include);
1246
- }
1247
- if (forced.select) {
1248
- expanded.select = buildForcedOnlyContainer(forced.select);
1249
- applyForcedTree(expanded, "select", forced.select);
1250
- }
1251
- if (forced._countWhere && Object.keys(forced._countWhere).length > 0) {
1252
- const placement = forced._countWherePlacement ?? "include";
1253
- if (!expanded[placement])
1254
- expanded[placement] = {};
1255
- const placementObj = expanded[placement];
1256
- Object.assign(placementObj, buildCountForPlacement(forced._countWhere));
1257
- }
1258
- if (expanded.include && expanded.select) {
1259
- throw new ShapeError(
1260
- `Forced tree for relation "${relName}" produces both "include" and "select". Prisma does not allow both at the same level.`
1261
- );
1262
- }
1263
- container[relName] = Object.keys(expanded).length > 0 ? expanded : true;
1264
- continue;
1265
- }
1266
- if (isPlainObject(relVal)) {
1267
- const relObj = relVal;
1268
- if (forced.where && hasWhereForced(forced.where)) {
1269
- relObj.where = mergeWhereForced(
1270
- relObj.where,
1271
- forced.where
1272
- );
1273
- }
1274
- if (forced.include) {
1275
- if (!relObj.include) {
1276
- relObj.include = buildForcedOnlyContainer(forced.include);
1277
- }
1278
- applyForcedTree(relObj, "include", forced.include);
1279
- }
1280
- if (forced.select) {
1281
- if (!relObj.select) {
1282
- relObj.select = buildForcedOnlyContainer(forced.select);
1283
- }
1284
- applyForcedTree(relObj, "select", forced.select);
1285
- }
1286
- if (forced._countWhere && Object.keys(forced._countWhere).length > 0) {
1287
- const placement = forced._countWherePlacement ?? "include";
1288
- const projContainer = relObj[placement];
1289
- if (projContainer) {
1290
- applyForcedCountWhere(projContainer, forced._countWhere);
1291
- }
1292
- }
1293
- if (relObj.include && relObj.select) {
1294
- throw new ShapeError(
1295
- `Relation "${relName}" has both "include" and "select" after forced tree merge. Prisma does not allow both at the same level.`
1296
- );
1297
- }
1298
- }
1444
+ container[relName] = applyForcedToRelValue(relName, relVal, forced);
1299
1445
  }
1300
1446
  }
1301
1447
  function buildForcedOnlyContainer(tree) {
1302
1448
  const result = {};
1303
1449
  for (const [relName, forced] of Object.entries(tree)) {
1304
- const nested = {};
1305
- if (forced.where && hasWhereForced(forced.where)) {
1306
- nested.where = mergeWhereForced(void 0, forced.where);
1307
- }
1308
- if (forced.include) {
1309
- nested.include = buildForcedOnlyContainer(forced.include);
1310
- }
1311
- if (forced.select) {
1312
- nested.select = buildForcedOnlyContainer(forced.select);
1313
- }
1314
- if (forced._countWhere && Object.keys(forced._countWhere).length > 0) {
1315
- const placement = forced._countWherePlacement ?? "include";
1316
- if (!nested[placement])
1317
- nested[placement] = {};
1318
- const placementObj = nested[placement];
1319
- Object.assign(placementObj, buildCountForPlacement(forced._countWhere));
1320
- }
1450
+ const nested = collectSubtree(forced);
1321
1451
  result[relName] = Object.keys(nested).length > 0 ? nested : true;
1322
1452
  }
1323
1453
  return result;
@@ -1333,11 +1463,15 @@ function applyForcedCountWhere(container, forcedCountWhere) {
1333
1463
  const selectObj = selectVal;
1334
1464
  for (const [relName, forced] of Object.entries(forcedCountWhere)) {
1335
1465
  const relVal = selectObj[relName];
1336
- if (relVal === void 0)
1466
+ if (relVal === void 0) {
1467
+ selectObj[relName] = { where: mergeWhereForced(void 0, forced) };
1337
1468
  continue;
1469
+ }
1338
1470
  if (relVal === true) {
1339
1471
  selectObj[relName] = { where: mergeWhereForced(void 0, forced) };
1340
- } else if (isPlainObject(relVal)) {
1472
+ continue;
1473
+ }
1474
+ if (isPlainObject(relVal)) {
1341
1475
  const relObj = relVal;
1342
1476
  relObj.where = mergeWhereForced(
1343
1477
  relObj.where,
@@ -1346,12 +1480,6 @@ function applyForcedCountWhere(container, forcedCountWhere) {
1346
1480
  }
1347
1481
  }
1348
1482
  }
1349
- function formatUniqueConstraint(constraint) {
1350
- return constraint.fields.length === 1 ? constraint.selector : `${constraint.selector}(${constraint.fields.join(", ")})`;
1351
- }
1352
- function formatUniqueConstraints(constraints) {
1353
- return constraints.map(formatUniqueConstraint).join(" | ");
1354
- }
1355
1483
  function resolvedWhereCoversConstraint(where, constraint) {
1356
1484
  if (constraint.fields.length === 1) {
1357
1485
  return constraint.fields[0] in where;
@@ -1457,7 +1585,12 @@ function stripUniqueWhereForcedInput(where, forced) {
1457
1585
  const currentValue = result[key];
1458
1586
  if (isPlainObject(currentValue) && isPlainObject(forcedValue)) {
1459
1587
  const nested = { ...currentValue };
1460
- 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
+ }
1461
1594
  delete nested[nestedKey];
1462
1595
  }
1463
1596
  if (Object.keys(nested).length === 0) {
@@ -1467,11 +1600,25 @@ function stripUniqueWhereForcedInput(where, forced) {
1467
1600
  }
1468
1601
  continue;
1469
1602
  }
1603
+ if (!deepEqual(currentValue, forcedValue)) {
1604
+ throw new ShapeError(
1605
+ `Client unique where value for "${key}" conflicts with forced value`
1606
+ );
1607
+ }
1470
1608
  delete result[key];
1471
1609
  }
1472
1610
  return result;
1473
1611
  }
1474
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
+
1475
1622
  // src/runtime/query-builder-where.ts
1476
1623
  var UNSUPPORTED_WHERE_TYPES = /* @__PURE__ */ new Set(["Bytes"]);
1477
1624
  var STRING_MODE_OPS = /* @__PURE__ */ new Set([
@@ -1485,47 +1632,40 @@ var JSON_STRING_MODE_OPS = /* @__PURE__ */ new Set([
1485
1632
  "string_starts_with",
1486
1633
  "string_ends_with"
1487
1634
  ]);
1635
+ var NEGATIVE_RELATION_OPS = /* @__PURE__ */ new Set(["none", "isNot"]);
1488
1636
  var MAX_WHERE_DEPTH = 10;
1489
- function safeStringify(v) {
1490
- if (typeof v === "bigint")
1491
- 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();
1492
1647
  try {
1493
- 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;
1494
1665
  } catch {
1495
- return String(v);
1666
+ return String(value);
1496
1667
  }
1497
1668
  }
1498
- function forcedValuesEqual(a, b) {
1499
- if (a === b)
1500
- return true;
1501
- if (a === null || b === null)
1502
- return false;
1503
- if (typeof a !== typeof b)
1504
- return false;
1505
- if (typeof a === "bigint")
1506
- return a === b;
1507
- if (a instanceof Date && b instanceof Date)
1508
- return a.getTime() === b.getTime();
1509
- if (a instanceof RegExp && b instanceof RegExp) {
1510
- return a.source === b.source && a.flags === b.flags;
1511
- }
1512
- if (typeof a !== "object")
1513
- return false;
1514
- if (Array.isArray(a)) {
1515
- if (!Array.isArray(b))
1516
- return false;
1517
- if (a.length !== b.length)
1518
- return false;
1519
- return a.every((v, i) => forcedValuesEqual(v, b[i]));
1520
- }
1521
- if (!isPlainObject(a) || !isPlainObject(b))
1522
- return false;
1523
- const aKeys = Object.keys(a);
1524
- const bKeys = Object.keys(b);
1525
- if (aKeys.length !== bKeys.length)
1526
- return false;
1527
- return aKeys.every((k) => k in b && forcedValuesEqual(a[k], b[k]));
1528
- }
1529
1669
  function mergeScalarConditions(target, source) {
1530
1670
  for (const [field, ops] of Object.entries(source)) {
1531
1671
  const existing = target[field];
@@ -1543,7 +1683,7 @@ function mergeScalarConditions(target, source) {
1543
1683
  for (const [op, val] of Object.entries(ops)) {
1544
1684
  if (op in existing) {
1545
1685
  const existingVal = existing[op];
1546
- if (!forcedValuesEqual(existingVal, val)) {
1686
+ if (!deepEqual(existingVal, val)) {
1547
1687
  throw new ShapeError(
1548
1688
  `Conflicting forced where values for "${field}.${op}": shape defines both ${safeStringify(existingVal)} and ${safeStringify(val)}`
1549
1689
  );
@@ -1553,7 +1693,7 @@ function mergeScalarConditions(target, source) {
1553
1693
  Object.assign(existing, ops);
1554
1694
  continue;
1555
1695
  }
1556
- if (!forcedValuesEqual(existing, ops)) {
1696
+ if (!deepEqual(existing, ops)) {
1557
1697
  throw new ShapeError(`Conflicting forced where values for "${field}"`);
1558
1698
  }
1559
1699
  }
@@ -1644,27 +1784,27 @@ function createWhereBuilder(typeMap, enumMap, scalarBase, uniqueMap = {}) {
1644
1784
  scalarConditions
1645
1785
  );
1646
1786
  }
1647
- for (const key of Object.keys(scalarConditions)) {
1787
+ const forcedOnlyKeys = /* @__PURE__ */ new Set();
1788
+ for (const key of Object.keys(whereConfig)) {
1648
1789
  if (COMBINATOR_KEYS.has(key))
1649
1790
  continue;
1650
1791
  if (!(key in fieldSchemas)) {
1651
- fieldSchemas[key] = import_zod4.z.object({}).strict().optional();
1792
+ forcedOnlyKeys.add(key);
1652
1793
  }
1653
1794
  }
1654
- for (const key of Object.keys(relationForced)) {
1795
+ for (const key of Object.keys(scalarConditions)) {
1796
+ if (COMBINATOR_KEYS.has(key))
1797
+ continue;
1655
1798
  if (!(key in fieldSchemas)) {
1656
- fieldSchemas[key] = import_zod4.z.object({}).strict().optional();
1799
+ fieldSchemas[key] = import_zod5.z.object({}).strict().optional();
1657
1800
  }
1658
1801
  }
1659
- const schema = Object.keys(fieldSchemas).length > 0 ? import_zod4.z.object(fieldSchemas).strict().optional() : null;
1660
- const forcedOnlyKeys = /* @__PURE__ */ new Set();
1661
- for (const key of Object.keys(whereConfig)) {
1662
- if (COMBINATOR_KEYS.has(key))
1663
- continue;
1802
+ for (const key of Object.keys(relationForced)) {
1664
1803
  if (!(key in fieldSchemas)) {
1665
- forcedOnlyKeys.add(key);
1804
+ fieldSchemas[key] = import_zod5.z.object({}).strict().optional();
1666
1805
  }
1667
1806
  }
1807
+ const schema = Object.keys(fieldSchemas).length > 0 ? import_zod5.z.object(fieldSchemas).strict().optional() : null;
1668
1808
  return {
1669
1809
  schema,
1670
1810
  forced: {
@@ -1695,12 +1835,12 @@ function createWhereBuilder(typeMap, enumMap, scalarBase, uniqueMap = {}) {
1695
1835
  );
1696
1836
  }
1697
1837
  if (key === "NOT") {
1698
- fieldSchemas[key] = import_zod4.z.union([
1838
+ fieldSchemas[key] = import_zod5.z.union([
1699
1839
  elementSchema,
1700
- 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))
1701
1841
  ]).optional();
1702
1842
  } else {
1703
- 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();
1704
1844
  }
1705
1845
  }
1706
1846
  if (hasWhereForced(result.forced)) {
@@ -1769,6 +1909,11 @@ function createWhereBuilder(typeMap, enumMap, scalarBase, uniqueMap = {}) {
1769
1909
  `Empty nested where for relation "${key}.${op}" on model "${model}". Define at least one field.`
1770
1910
  );
1771
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
+ }
1772
1917
  if (nested.schema) {
1773
1918
  if (!hasWhereForced(nested.forced)) {
1774
1919
  opSchemas[op] = nested.schema.refine(
@@ -1793,7 +1938,7 @@ function createWhereBuilder(typeMap, enumMap, scalarBase, uniqueMap = {}) {
1793
1938
  }
1794
1939
  if (hasClientOps) {
1795
1940
  const clientOpKeys = Object.keys(opSchemas);
1796
- const opObjSchema = import_zod4.z.object(opSchemas).strict();
1941
+ const opObjSchema = import_zod5.z.object(opSchemas).strict();
1797
1942
  if (Object.keys(opForced).length === 0 && !hasForcedNull) {
1798
1943
  fieldSchemas[key] = opObjSchema.refine(
1799
1944
  (v) => clientOpKeys.some(
@@ -1879,10 +2024,10 @@ function createWhereBuilder(typeMap, enumMap, scalarBase, uniqueMap = {}) {
1879
2024
  );
1880
2025
  }
1881
2026
  if (modeConfigValue === true) {
1882
- opSchemas.mode = import_zod4.z.enum(["default", "insensitive"]).optional();
2027
+ opSchemas.mode = import_zod5.z.enum(["default", "insensitive"]).optional();
1883
2028
  } else {
1884
2029
  const actualModeValue = isForcedValue(modeConfigValue) ? modeConfigValue.value : modeConfigValue;
1885
- const modeSchema = import_zod4.z.enum(["default", "insensitive"]);
2030
+ const modeSchema = import_zod5.z.enum(["default", "insensitive"]);
1886
2031
  let parsed;
1887
2032
  try {
1888
2033
  parsed = modeSchema.parse(actualModeValue);
@@ -1894,10 +2039,10 @@ function createWhereBuilder(typeMap, enumMap, scalarBase, uniqueMap = {}) {
1894
2039
  fieldForced.mode = parsed;
1895
2040
  }
1896
2041
  } else if (hasModeCompatibleOp) {
1897
- opSchemas.mode = import_zod4.z.enum(["default", "insensitive"]).optional();
2042
+ opSchemas.mode = import_zod5.z.enum(["default", "insensitive"]).optional();
1898
2043
  }
1899
2044
  if (hasClientOps) {
1900
- const opObj = import_zod4.z.object(opSchemas).strict();
2045
+ const opObj = import_zod5.z.object(opSchemas).strict();
1901
2046
  const refined = opObj.refine(
1902
2047
  (v) => clientOpKeys.some(
1903
2048
  (k) => v[k] !== void 0
@@ -1913,7 +2058,7 @@ function createWhereBuilder(typeMap, enumMap, scalarBase, uniqueMap = {}) {
1913
2058
  enumMap,
1914
2059
  scalarBase
1915
2060
  );
1916
- fieldSchemas[fieldName] = import_zod4.z.union([refined, equalsBase]).optional();
2061
+ fieldSchemas[fieldName] = import_zod5.z.union([refined, equalsBase]).optional();
1917
2062
  } else {
1918
2063
  fieldSchemas[fieldName] = refined.optional();
1919
2064
  }
@@ -1927,15 +2072,8 @@ function createWhereBuilder(typeMap, enumMap, scalarBase, uniqueMap = {}) {
1927
2072
  (constraint) => constraint.selector === selector
1928
2073
  ) ?? null;
1929
2074
  }
1930
- function buildDirectUniqueSchema(fieldMeta) {
1931
- const base = createBaseType(fieldMeta, enumMap, scalarBase);
1932
- if (!fieldMeta.isEnum && !fieldMeta.isRelation && !fieldMeta.isUnsupported) {
1933
- return wrapWithInputCoercion(fieldMeta.type, fieldMeta.isList, base);
1934
- }
1935
- return base;
1936
- }
1937
2075
  function parseForcedUniqueValue(model, fieldName, fieldMeta, value) {
1938
- const schema = buildDirectUniqueSchema(fieldMeta);
2076
+ const schema = buildDirectScalarSchema(fieldMeta, enumMap, scalarBase);
1939
2077
  const actual = isForcedValue(value) ? value.value : value;
1940
2078
  try {
1941
2079
  return schema.parse(actual);
@@ -2013,7 +2151,11 @@ function createWhereBuilder(typeMap, enumMap, scalarBase, uniqueMap = {}) {
2013
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.`
2014
2152
  );
2015
2153
  }
2016
- const directSchema2 = buildDirectUniqueSchema(fieldMeta2);
2154
+ const directSchema2 = buildDirectScalarSchema(
2155
+ fieldMeta2,
2156
+ enumMap,
2157
+ scalarBase
2158
+ );
2017
2159
  if (fieldValue === true) {
2018
2160
  nestedSchemas[fieldName] = directSchema2;
2019
2161
  } else {
@@ -2026,7 +2168,7 @@ function createWhereBuilder(typeMap, enumMap, scalarBase, uniqueMap = {}) {
2026
2168
  }
2027
2169
  }
2028
2170
  if (Object.keys(nestedSchemas).length > 0) {
2029
- fieldSchemas[key] = import_zod4.z.object(nestedSchemas).strict();
2171
+ fieldSchemas[key] = import_zod5.z.object(nestedSchemas).strict();
2030
2172
  }
2031
2173
  if (Object.keys(forcedCompound).length > 0) {
2032
2174
  forcedConditions[key] = forcedCompound;
@@ -2060,7 +2202,7 @@ function createWhereBuilder(typeMap, enumMap, scalarBase, uniqueMap = {}) {
2060
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 }.`
2061
2203
  );
2062
2204
  }
2063
- const directSchema = buildDirectUniqueSchema(fieldMeta);
2205
+ const directSchema = buildDirectScalarSchema(fieldMeta, enumMap, scalarBase);
2064
2206
  if (value === true) {
2065
2207
  fieldSchemas[key] = directSchema;
2066
2208
  continue;
@@ -2074,7 +2216,7 @@ function createWhereBuilder(typeMap, enumMap, scalarBase, uniqueMap = {}) {
2074
2216
  forcedOnlyKeys.add(key);
2075
2217
  }
2076
2218
  return {
2077
- 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,
2078
2220
  forced: {
2079
2221
  conditions: forcedConditions,
2080
2222
  relations: {}
@@ -2086,31 +2228,13 @@ function createWhereBuilder(typeMap, enumMap, scalarBase, uniqueMap = {}) {
2086
2228
  }
2087
2229
 
2088
2230
  // src/runtime/query-builder-args.ts
2089
- var import_zod5 = require("zod");
2231
+ var import_zod6 = require("zod");
2090
2232
  var UNSUPPORTED_BY_TYPES = /* @__PURE__ */ new Set(["Json", "Bytes"]);
2091
- function requireConfigTrue(config, context) {
2092
- for (const [key, value] of Object.entries(config)) {
2093
- if (value !== true) {
2094
- throw new ShapeError(
2095
- `Config value for "${key}" in ${context} must be true, got ${typeof value}`
2096
- );
2097
- }
2098
- }
2099
- }
2100
- function isPlainRecord(value) {
2101
- return value !== null && typeof value === "object" && !Array.isArray(value);
2102
- }
2103
- function formatUniqueConstraint2(constraint) {
2104
- return constraint.fields.length === 1 ? constraint.selector : `${constraint.selector}(${constraint.fields.join(", ")})`;
2105
- }
2106
- function formatUniqueConstraints2(constraints) {
2107
- return constraints.map(formatUniqueConstraint2).join(" | ");
2108
- }
2109
2233
  function createArgsBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
2110
- const sortEnum = import_zod5.z.enum(["asc", "desc"]);
2111
- const nullsEnum = import_zod5.z.enum(["first", "last"]);
2112
- const sortWithNulls = import_zod5.z.object({ sort: sortEnum, nulls: nullsEnum.optional() }).strict();
2113
- 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]);
2114
2238
  function validateScalarOrderByField(fieldName, model, modelFields) {
2115
2239
  const fieldMeta = modelFields[fieldName];
2116
2240
  if (!fieldMeta)
@@ -2129,6 +2253,16 @@ function createArgsBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
2129
2253
  );
2130
2254
  }
2131
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
+ }
2132
2266
  const modelFields = typeMap[model];
2133
2267
  if (!modelFields)
2134
2268
  throw new ShapeError(`Unknown model: ${model}`);
@@ -2144,53 +2278,35 @@ function createArgsBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
2144
2278
  fieldSchemas[fieldName] = scalarOrderSchema.optional();
2145
2279
  continue;
2146
2280
  }
2147
- if (!isPlainRecord(config)) {
2281
+ if (!isPlainObject(config)) {
2148
2282
  throw new ShapeError(
2149
- `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`
2150
2284
  );
2151
2285
  }
2152
2286
  if (!fieldMeta.isRelation) {
2153
- const allowedOps = getSupportedOperators(
2154
- fieldMeta.type,
2155
- fieldMeta.isList
2287
+ throw new ShapeError(
2288
+ `orderBy config for scalar field "${model}.${fieldName}" must be true. Operator objects are not valid in orderBy.`
2156
2289
  );
2157
- const opSchemas = {};
2158
- for (const [op, enabled] of Object.entries(config)) {
2159
- if (enabled !== true) {
2160
- throw new ShapeError(
2161
- `orderBy operator config for "${model}.${fieldName}.${op}" must be true`
2162
- );
2163
- }
2164
- if (!allowedOps.includes(op)) {
2165
- throw new ShapeError(
2166
- `Operator "${op}" not supported for orderBy field "${model}.${fieldName}"`
2167
- );
2168
- }
2169
- opSchemas[op] = scalarOrderSchema.optional();
2170
- }
2171
- const opKeys = Object.keys(opSchemas);
2172
- fieldSchemas[fieldName] = import_zod5.z.object(opSchemas).strict().refine(
2173
- (v) => opKeys.some(
2174
- (k) => v[k] !== void 0
2175
- ),
2176
- {
2177
- message: `orderBy field "${fieldName}" must specify at least one operator`
2178
- }
2179
- ).optional();
2180
- continue;
2181
2290
  }
2182
2291
  if (fieldMeta.isList) {
2183
- if (!("_count" in config)) {
2292
+ const configKeys = Object.keys(config);
2293
+ if (!configKeys.includes("_count")) {
2184
2294
  throw new ShapeError(
2185
2295
  `To-many relation orderBy "${fieldName}" only supports _count`
2186
2296
  );
2187
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
+ }
2188
2304
  if (config._count !== true) {
2189
2305
  throw new ShapeError(
2190
2306
  `orderBy relation aggregate "${fieldName}._count" must be true`
2191
2307
  );
2192
2308
  }
2193
- fieldSchemas[fieldName] = import_zod5.z.object({
2309
+ fieldSchemas[fieldName] = import_zod6.z.object({
2194
2310
  _count: sortEnum.optional()
2195
2311
  }).strict().optional();
2196
2312
  continue;
@@ -2201,17 +2317,11 @@ function createArgsBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
2201
2317
  );
2202
2318
  fieldSchemas[fieldName] = nested;
2203
2319
  }
2204
- const fieldKeys = Object.keys(fieldSchemas);
2205
- const singleSchema = import_zod5.z.object(fieldSchemas).strict().refine(
2206
- (v) => fieldKeys.some(
2207
- (k) => v[k] !== void 0
2208
- ),
2209
- { message: "orderBy must specify at least one field" }
2320
+ const singleSchema = strictObjectRequiringOne(
2321
+ fieldSchemas,
2322
+ "orderBy must specify at least one field"
2210
2323
  );
2211
- return import_zod5.z.union([
2212
- singleSchema,
2213
- import_zod5.z.preprocess(coerceToArray, import_zod5.z.array(singleSchema).min(1))
2214
- ]).optional();
2324
+ return singleOrArraySchema(singleSchema).optional();
2215
2325
  }
2216
2326
  function buildTakeSchema(config) {
2217
2327
  if (typeof config === "number") {
@@ -2221,7 +2331,7 @@ function createArgsBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
2221
2331
  if (config <= 0) {
2222
2332
  throw new ShapeError("take must be a positive integer");
2223
2333
  }
2224
- return import_zod5.z.literal(config).optional();
2334
+ return import_zod6.z.number().int().min(1).max(config).default(config);
2225
2335
  }
2226
2336
  if (!config || typeof config !== "object" || Array.isArray(config)) {
2227
2337
  throw new ShapeError("take config must be a number or { max, default? }");
@@ -2246,9 +2356,9 @@ function createArgsBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
2246
2356
  if (config.default > config.max) {
2247
2357
  throw new ShapeError("take.default cannot exceed take.max");
2248
2358
  }
2249
- 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);
2250
2360
  }
2251
- 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();
2252
2362
  }
2253
2363
  function buildCursorFieldSchema(model, fieldName) {
2254
2364
  const modelFields = typeMap[model];
@@ -2270,11 +2380,7 @@ function createArgsBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
2270
2380
  `List field "${fieldName}" cannot be used in cursor`
2271
2381
  );
2272
2382
  }
2273
- const base = createBaseType(fieldMeta, enumMap, scalarBase);
2274
- if (!fieldMeta.isEnum && !fieldMeta.isRelation && !fieldMeta.isUnsupported) {
2275
- return wrapWithInputCoercion(fieldMeta.type, fieldMeta.isList, base);
2276
- }
2277
- return base;
2383
+ return buildDirectScalarSchema(fieldMeta, enumMap, scalarBase);
2278
2384
  }
2279
2385
  function cursorConfigMatchesConstraint(cursorConfig, constraint) {
2280
2386
  if (!(constraint.selector in cursorConfig))
@@ -2283,66 +2389,55 @@ function createArgsBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
2283
2389
  if (constraint.fields.length === 1) {
2284
2390
  return value === true;
2285
2391
  }
2286
- if (!isPlainRecord(value))
2392
+ if (!isPlainObject(value))
2287
2393
  return false;
2288
2394
  const keys = Object.keys(value);
2289
2395
  if (keys.length !== constraint.fields.length)
2290
2396
  return false;
2291
2397
  return constraint.fields.every((field) => value[field] === true);
2292
2398
  }
2293
- function getUniqueConstraints(model) {
2294
- const constraints = uniqueMap[model];
2295
- if (constraints && constraints.length > 0) {
2296
- return constraints;
2297
- }
2298
- const modelFields = typeMap[model];
2299
- if (!modelFields) {
2300
- throw new ShapeError(`Unknown model: ${model}`);
2301
- }
2302
- const inferred = [];
2303
- for (const [fieldName, fieldMeta] of Object.entries(modelFields)) {
2304
- if (fieldMeta.isRelation)
2305
- continue;
2306
- if (fieldMeta.isId || fieldMeta.isUnique) {
2307
- inferred.push({
2308
- selector: fieldName,
2309
- fields: [fieldName]
2310
- });
2311
- }
2312
- }
2313
- return inferred;
2314
- }
2315
2399
  function buildCursorSchema(model, cursorConfig) {
2316
- const constraints = getUniqueConstraints(model);
2400
+ const constraints = uniqueMap[model] ?? [];
2317
2401
  if (constraints.length === 0) {
2318
2402
  throw new ShapeError(
2319
2403
  `cursor on model "${model}" requires at least one unique constraint`
2320
2404
  );
2321
2405
  }
2322
- const matching = constraints.find(
2406
+ const matching = constraints.filter(
2323
2407
  (constraint) => cursorConfigMatchesConstraint(cursorConfig, constraint)
2324
2408
  );
2325
- if (!matching) {
2409
+ if (matching.length === 0) {
2326
2410
  throw new ShapeError(
2327
- `cursor on model "${model}" must exactly match a unique selector: ${formatUniqueConstraints2(constraints)}`
2411
+ `cursor on model "${model}" must match a unique selector: ${formatUniqueConstraints(constraints)}`
2328
2412
  );
2329
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
+ }
2330
2422
  const fieldSchemas = {};
2331
- if (matching.fields.length === 1) {
2332
- fieldSchemas[matching.selector] = buildCursorFieldSchema(
2333
- model,
2334
- matching.fields[0]
2335
- ).optional();
2336
- } else {
2337
- const nestedSchemas = {};
2338
- for (const field of matching.fields) {
2339
- 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();
2340
2435
  }
2341
- fieldSchemas[matching.selector] = import_zod5.z.object(nestedSchemas).strict().optional();
2342
2436
  }
2343
- return import_zod5.z.object(fieldSchemas).strict().refine(
2344
- (v) => v[matching.selector] !== void 0,
2345
- { 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(", ")}`
2346
2441
  ).optional();
2347
2442
  }
2348
2443
  function buildDistinctSchema(model, distinctConfig) {
@@ -2367,10 +2462,8 @@ function createArgsBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
2367
2462
  );
2368
2463
  allowedFields.add(fieldName);
2369
2464
  }
2370
- return import_zod5.z.union([
2371
- import_zod5.z.enum([...allowedFields]),
2372
- import_zod5.z.array(import_zod5.z.enum([...allowedFields])).min(1)
2373
- ]).optional();
2465
+ const fieldEnum = import_zod6.z.enum([...allowedFields]);
2466
+ return import_zod6.z.union([fieldEnum, import_zod6.z.array(fieldEnum).min(1)]).optional();
2374
2467
  }
2375
2468
  function buildBySchema(model, byConfig) {
2376
2469
  const modelFields = typeMap[model];
@@ -2403,7 +2496,7 @@ function createArgsBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
2403
2496
  }
2404
2497
  allowedFields.add(fieldName);
2405
2498
  }
2406
- 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);
2407
2500
  }
2408
2501
  function buildHavingSchema(model, havingConfig) {
2409
2502
  const modelFields = typeMap[model];
@@ -2444,22 +2537,21 @@ function createArgsBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
2444
2537
  ).optional();
2445
2538
  }
2446
2539
  if (fieldMeta.type === "String") {
2447
- opSchemas.mode = import_zod5.z.enum(["default", "insensitive"]).optional();
2540
+ opSchemas.mode = import_zod6.z.enum(["default", "insensitive"]).optional();
2448
2541
  }
2449
2542
  const opKeys = Object.keys(opSchemas).filter((key) => key !== "mode");
2450
- fieldSchemas[fieldName] = import_zod5.z.object(opSchemas).strict().refine(
2543
+ const opShape = { ...opSchemas };
2544
+ const opObjSchema = import_zod6.z.object(opShape).strict().refine(
2451
2545
  (v) => opKeys.some((k) => v[k] !== void 0),
2452
2546
  {
2453
2547
  message: `having field "${fieldName}" must specify at least one operator`
2454
2548
  }
2455
- ).optional();
2549
+ );
2550
+ fieldSchemas[fieldName] = opObjSchema.optional();
2456
2551
  }
2457
- const fieldKeys = Object.keys(fieldSchemas);
2458
- return import_zod5.z.object(fieldSchemas).strict().refine(
2459
- (v) => fieldKeys.some(
2460
- (k) => v[k] !== void 0
2461
- ),
2462
- { message: "having must specify at least one field" }
2552
+ return strictObjectRequiringOne(
2553
+ fieldSchemas,
2554
+ "having must specify at least one field"
2463
2555
  ).optional();
2464
2556
  }
2465
2557
  function buildAggregateFieldSchema(model, op, config) {
@@ -2468,47 +2560,45 @@ function createArgsBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
2468
2560
  throw new ShapeError(`Unknown model: ${model}`);
2469
2561
  requireConfigTrue(config, `${op} on model "${model}"`);
2470
2562
  const allowedTypes = op === "_avg" || op === "_sum" ? NUMERIC_TYPES : COMPARABLE_TYPES;
2471
- const fieldSchemas = {};
2472
- for (const fieldName of Object.keys(config)) {
2473
- const fieldMeta = modelFields[fieldName];
2474
- if (!fieldMeta)
2475
- throw new ShapeError(
2476
- `Unknown field "${fieldName}" on model "${model}" in ${op}`
2477
- );
2478
- if (fieldMeta.isRelation)
2479
- throw new ShapeError(
2480
- `Relation field "${fieldName}" cannot be used in ${op}`
2481
- );
2482
- if (fieldMeta.isList)
2483
- throw new ShapeError(
2484
- `List field "${fieldName}" cannot be used in ${op}`
2485
- );
2486
- if (!allowedTypes.has(fieldMeta.type)) {
2487
- throw new ShapeError(
2488
- `Field "${fieldName}" of type "${fieldMeta.type}" cannot be used in ${op}`
2489
- );
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
+ }
2490
2585
  }
2491
- fieldSchemas[fieldName] = import_zod5.z.literal(true).optional();
2492
- }
2493
- const aggregateFieldKeys = Object.keys(fieldSchemas);
2494
- return import_zod5.z.object(fieldSchemas).strict().refine(
2495
- (v) => aggregateFieldKeys.some(
2496
- (k) => v[k] !== void 0
2497
- ),
2498
- { message: `${op} must specify at least one field` }
2499
- ).optional();
2586
+ );
2500
2587
  }
2501
2588
  function buildCountFieldSchema(model, config, context) {
2502
2589
  if (config === true) {
2503
- return import_zod5.z.literal(true).optional();
2590
+ return import_zod6.z.literal(true).optional();
2504
2591
  }
2505
2592
  const modelFields = typeMap[model];
2506
2593
  if (!modelFields)
2507
2594
  throw new ShapeError(`Unknown model: ${model}`);
2508
2595
  requireConfigTrue(config, `${context} on model "${model}"`);
2509
- const fieldSchemas = {};
2510
- for (const fieldName of Object.keys(config)) {
2511
- 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;
2512
2602
  const fieldMeta = modelFields[fieldName];
2513
2603
  if (!fieldMeta)
2514
2604
  throw new ShapeError(
@@ -2519,45 +2609,30 @@ function createArgsBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
2519
2609
  `Relation field "${fieldName}" cannot be used in ${context}`
2520
2610
  );
2521
2611
  }
2522
- fieldSchemas[fieldName] = import_zod5.z.literal(true).optional();
2523
- }
2524
- const countFieldKeys = Object.keys(fieldSchemas);
2525
- return import_zod5.z.object(fieldSchemas).strict().refine(
2526
- (v) => countFieldKeys.some(
2527
- (k) => v[k] !== void 0
2528
- ),
2529
- { message: `${context} must specify at least one field` }
2530
- ).optional();
2612
+ );
2531
2613
  }
2532
2614
  function buildCountSelectSchema(model, selectConfig) {
2533
2615
  const modelFields = typeMap[model];
2534
2616
  if (!modelFields)
2535
2617
  throw new ShapeError(`Unknown model: ${model}`);
2536
2618
  requireConfigTrue(selectConfig, `count select on model "${model}"`);
2537
- const fieldSchemas = {};
2538
- for (const fieldName of Object.keys(selectConfig)) {
2539
- if (fieldName === "_all") {
2540
- fieldSchemas._all = import_zod5.z.literal(true).optional();
2541
- 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
+ );
2542
2634
  }
2543
- const fieldMeta = modelFields[fieldName];
2544
- if (!fieldMeta)
2545
- throw new ShapeError(
2546
- `Unknown field "${fieldName}" on model "${model}" in count select`
2547
- );
2548
- if (fieldMeta.isRelation)
2549
- throw new ShapeError(
2550
- `Relation field "${fieldName}" cannot be used in count select`
2551
- );
2552
- fieldSchemas[fieldName] = import_zod5.z.literal(true).optional();
2553
- }
2554
- const countSelectKeys = Object.keys(fieldSchemas);
2555
- return import_zod5.z.object(fieldSchemas).strict().refine(
2556
- (v) => countSelectKeys.some(
2557
- (k) => v[k] !== void 0
2558
- ),
2559
- { message: "count select must specify at least one field" }
2560
- ).optional();
2635
+ );
2561
2636
  }
2562
2637
  return {
2563
2638
  buildOrderBySchema,
@@ -2573,25 +2648,64 @@ function createArgsBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
2573
2648
  }
2574
2649
 
2575
2650
  // src/runtime/query-builder-projection.ts
2576
- var import_zod6 = require("zod");
2577
- var KNOWN_NESTED_INCLUDE_KEYS = /* @__PURE__ */ new Set([
2578
- "where",
2579
- "include",
2580
- "select",
2581
- "orderBy",
2582
- "cursor",
2583
- "take",
2584
- "skip"
2585
- ]);
2586
- var KNOWN_NESTED_SELECT_KEYS = /* @__PURE__ */ new Set([
2587
- "select",
2588
- "include",
2589
- "where",
2590
- "orderBy",
2591
- "cursor",
2592
- "take",
2593
- "skip"
2594
- ]);
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
+ };
2595
2709
  var KNOWN_COUNT_SELECT_ENTRY_KEYS = /* @__PURE__ */ new Set(["where"]);
2596
2710
  var MAX_PROJECTION_DEPTH = 10;
2597
2711
  function validateNestedKeys(keys, allowed, context) {
@@ -2603,13 +2717,25 @@ function validateNestedKeys(keys, allowed, context) {
2603
2717
  }
2604
2718
  }
2605
2719
  }
2606
- 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) {
2607
2733
  function buildIncludeCountSchema(model, config) {
2608
2734
  const modelFields = typeMap[model];
2609
2735
  if (!modelFields)
2610
2736
  throw new ShapeError(`Unknown model: ${model}`);
2611
2737
  if (config === true) {
2612
- return { schema: import_zod6.z.literal(true).optional(), forcedCountWhere: {} };
2738
+ return { schema: import_zod7.z.literal(true).optional(), forcedCountWhere: {} };
2613
2739
  }
2614
2740
  if (!isPlainObject(config) || !("select" in config)) {
2615
2741
  throw new ShapeError(
@@ -2645,273 +2771,175 @@ function createProjectionBuilder(typeMap, enumMap, deps) {
2645
2771
  if (!fieldMeta.isList)
2646
2772
  throw new ShapeError(`Field "${fieldName}" is a to-one relation on model "${model}" in _count.select. Only to-many relations support _count.`);
2647
2773
  if (fieldConfig === true) {
2648
- countSelectFields[fieldName] = import_zod6.z.literal(true).optional();
2649
- } else if (isPlainObject(fieldConfig)) {
2650
- if (Object.keys(fieldConfig).length === 0) {
2651
- throw new ShapeError(
2652
- `Empty config for _count.select.${fieldName} on model "${model}". Use true or { where: { ... } }.`
2653
- );
2654
- }
2655
- validateNestedKeys(
2656
- Object.keys(fieldConfig),
2657
- KNOWN_COUNT_SELECT_ENTRY_KEYS,
2658
- `_count.select.${fieldName} on model "${model}"`
2659
- );
2660
- if (fieldConfig.where) {
2661
- const relatedType = fieldMeta.type;
2662
- const { schema: whereSchema, forced } = deps.buildWhereSchema(
2663
- relatedType,
2664
- fieldConfig.where
2665
- );
2666
- const nestedSchemas = {};
2667
- if (whereSchema)
2668
- nestedSchemas["where"] = whereSchema;
2669
- const nestedObj = import_zod6.z.object(nestedSchemas).strict();
2670
- countSelectFields[fieldName] = import_zod6.z.union([import_zod6.z.literal(true), nestedObj]).optional();
2671
- if (hasWhereForced(forced)) {
2672
- forcedCountWhere[fieldName] = forced;
2673
- }
2674
- } else {
2675
- countSelectFields[fieldName] = import_zod6.z.literal(true).optional();
2676
- }
2677
- } else {
2774
+ countSelectFields[fieldName] = import_zod7.z.literal(true).optional();
2775
+ continue;
2776
+ }
2777
+ if (!isPlainObject(fieldConfig)) {
2678
2778
  throw new ShapeError(
2679
2779
  `Invalid config for _count.select.${fieldName} on model "${model}". Expected true or { where: { ... } }`
2680
2780
  );
2681
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
+ }
2682
2809
  }
2683
- const countSelectKeys = Object.keys(countSelectFields);
2684
- const selectSchema = import_zod6.z.object(countSelectFields).strict().refine(
2685
- (v) => countSelectKeys.some((k) => v[k] !== void 0),
2686
- { message: "_count.select must specify at least one field" }
2810
+ const selectSchema = strictObjectRequiringOne(
2811
+ countSelectFields,
2812
+ "_count.select must specify at least one field"
2687
2813
  );
2688
2814
  return {
2689
- schema: import_zod6.z.object({ select: selectSchema }).strict().optional(),
2815
+ schema: import_zod7.z.object({ select: selectSchema }).strict().optional(),
2690
2816
  forcedCountWhere
2691
2817
  };
2692
2818
  }
2693
- 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) {
2694
2867
  const currentDepth = depth ?? 0;
2695
2868
  if (currentDepth > MAX_PROJECTION_DEPTH) {
2696
2869
  throw new ShapeError(
2697
- `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.`
2698
2871
  );
2699
2872
  }
2700
- if (Object.keys(includeConfig).length === 0) {
2873
+ if (Object.keys(projectionConfig).length === 0) {
2701
2874
  throw new ShapeError(
2702
- `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"}.`
2703
2876
  );
2704
2877
  }
2705
2878
  const modelFields = typeMap[model];
2706
2879
  if (!modelFields)
2707
2880
  throw new ShapeError(`Unknown model: ${model}`);
2881
+ const allowedNestedKeys = KNOWN_NESTED_KEYS[mode];
2708
2882
  const fieldSchemas = {};
2709
2883
  const forcedTree = {};
2710
2884
  let topLevelForcedCountWhere = {};
2711
- for (const [relName, config] of Object.entries(includeConfig)) {
2712
- if (relName === "_count") {
2885
+ for (const [fieldName, config] of Object.entries(projectionConfig)) {
2886
+ if (fieldName === "_count") {
2713
2887
  const countResult = buildIncludeCountSchema(model, config);
2714
2888
  fieldSchemas["_count"] = countResult.schema;
2715
2889
  topLevelForcedCountWhere = countResult.forcedCountWhere;
2716
2890
  continue;
2717
2891
  }
2718
- const fieldMeta = modelFields[relName];
2719
- if (!fieldMeta)
2720
- throw new ShapeError(`Unknown field "${relName}" on model "${model}"`);
2721
- if (!fieldMeta.isRelation)
2722
- throw new ShapeError(`Field "${relName}" is not a relation on model "${model}"`);
2723
- if (config === true) {
2724
- fieldSchemas[relName] = import_zod6.z.literal(true).optional();
2725
- } else {
2726
- validateNestedKeys(
2727
- Object.keys(config),
2728
- KNOWN_NESTED_INCLUDE_KEYS,
2729
- `nested include for "${relName}" on model "${model}"`
2730
- );
2731
- if (config.select && config.include) {
2732
- throw new ShapeError(`Nested include for "${relName}" cannot define both "select" and "include".`);
2733
- }
2734
- if (!fieldMeta.isList) {
2735
- if (config.where || config.orderBy || config.cursor || config.take || config.skip) {
2736
- throw new ShapeError(
2737
- `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.`
2738
- );
2739
- }
2740
- }
2741
- const nestedSchemas = {};
2742
- const relForced = {};
2743
- if (config.where) {
2744
- const { schema: whereSchema, forced } = deps.buildWhereSchema(
2745
- fieldMeta.type,
2746
- config.where
2747
- );
2748
- if (whereSchema)
2749
- nestedSchemas["where"] = whereSchema;
2750
- if (hasWhereForced(forced))
2751
- relForced.where = forced;
2752
- }
2753
- if (config.include) {
2754
- const nested = buildIncludeSchema(fieldMeta.type, config.include, currentDepth + 1);
2755
- nestedSchemas["include"] = nested.schema;
2756
- if (Object.keys(nested.forcedTree).length > 0)
2757
- relForced.include = nested.forcedTree;
2758
- if (Object.keys(nested.forcedCountWhere).length > 0) {
2759
- relForced._countWhere = nested.forcedCountWhere;
2760
- relForced._countWherePlacement = "include";
2761
- }
2762
- }
2763
- if (config.select) {
2764
- const nested = buildSelectSchema(fieldMeta.type, config.select, currentDepth + 1);
2765
- nestedSchemas["select"] = nested.schema;
2766
- if (Object.keys(nested.forcedTree).length > 0)
2767
- relForced.select = nested.forcedTree;
2768
- if (Object.keys(nested.forcedCountWhere).length > 0) {
2769
- relForced._countWhere = nested.forcedCountWhere;
2770
- relForced._countWherePlacement = "select";
2771
- }
2772
- }
2773
- if (config.orderBy) {
2774
- nestedSchemas["orderBy"] = deps.buildOrderBySchema(fieldMeta.type, config.orderBy);
2775
- }
2776
- if (config.cursor) {
2777
- nestedSchemas["cursor"] = deps.buildCursorSchema(fieldMeta.type, config.cursor);
2778
- }
2779
- if (config.take) {
2780
- nestedSchemas["take"] = deps.buildTakeSchema(config.take);
2781
- }
2782
- if (config.skip) {
2783
- nestedSchemas["skip"] = import_zod6.z.number().int().min(0).optional();
2784
- }
2785
- const nestedObj = import_zod6.z.object(nestedSchemas).strict();
2786
- fieldSchemas[relName] = import_zod6.z.union([import_zod6.z.literal(true), nestedObj]).optional();
2787
- if (Object.keys(relForced).length > 0)
2788
- forcedTree[relName] = relForced;
2789
- }
2790
- }
2791
- const includeFieldKeys = Object.keys(fieldSchemas);
2792
- const baseSchema = import_zod6.z.object(fieldSchemas).strict();
2793
- const schema = includeFieldKeys.length > 0 ? baseSchema.refine(
2794
- (v) => includeFieldKeys.some((k) => v[k] !== void 0),
2795
- { message: "include must specify at least one field" }
2796
- ).optional() : baseSchema.optional();
2797
- return {
2798
- schema,
2799
- forcedTree,
2800
- forcedCountWhere: topLevelForcedCountWhere
2801
- };
2802
- }
2803
- function buildSelectSchema(model, selectConfig, depth) {
2804
- const currentDepth = depth ?? 0;
2805
- if (currentDepth > MAX_PROJECTION_DEPTH) {
2806
- throw new ShapeError(
2807
- `Select schema for model "${model}" exceeds maximum nesting depth (${MAX_PROJECTION_DEPTH}). Check for circular relation references in the shape.`
2808
- );
2809
- }
2810
- if (Object.keys(selectConfig).length === 0) {
2811
- throw new ShapeError(
2812
- `Empty select config on model "${model}". Define at least one field.`
2813
- );
2814
- }
2815
- const modelFields = typeMap[model];
2816
- if (!modelFields)
2817
- throw new ShapeError(`Unknown model: ${model}`);
2818
- const fieldSchemas = {};
2819
- const forcedTree = {};
2820
- let topLevelForcedCountWhere = {};
2821
- for (const [fieldName, config] of Object.entries(selectConfig)) {
2822
- if (fieldName === "_count") {
2823
- const countResult = buildIncludeCountSchema(model, config);
2824
- fieldSchemas["_count"] = countResult.schema;
2825
- topLevelForcedCountWhere = countResult.forcedCountWhere;
2826
- continue;
2827
- }
2828
- const fieldMeta = modelFields[fieldName];
2892
+ const fieldMeta = modelFields[fieldName];
2829
2893
  if (!fieldMeta)
2830
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
+ }
2831
2898
  if (config === true) {
2832
- fieldSchemas[fieldName] = import_zod6.z.literal(true).optional();
2833
- } else {
2834
- if (!fieldMeta.isRelation) {
2835
- throw new ShapeError(`Nested select args only valid for relations, not scalar "${fieldName}" on model "${model}"`);
2836
- }
2837
- validateNestedKeys(
2838
- Object.keys(config),
2839
- KNOWN_NESTED_SELECT_KEYS,
2840
- `nested select for "${fieldName}" on model "${model}"`
2841
- );
2842
- if (config.select && config.include) {
2843
- throw new ShapeError(`Nested select for "${fieldName}" cannot define both "select" and "include".`);
2844
- }
2845
- if (!fieldMeta.isList) {
2846
- if (config.where || config.orderBy || config.cursor || config.take || config.skip) {
2847
- throw new ShapeError(
2848
- `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.`
2849
- );
2850
- }
2851
- }
2852
- const nestedSchemas = {};
2853
- const relForced = {};
2854
- if (config.select) {
2855
- const nested = buildSelectSchema(fieldMeta.type, config.select, currentDepth + 1);
2856
- nestedSchemas["select"] = nested.schema;
2857
- if (Object.keys(nested.forcedTree).length > 0)
2858
- relForced.select = nested.forcedTree;
2859
- if (Object.keys(nested.forcedCountWhere).length > 0) {
2860
- relForced._countWhere = nested.forcedCountWhere;
2861
- relForced._countWherePlacement = "select";
2862
- }
2863
- }
2864
- if (config.include) {
2865
- const nested = buildIncludeSchema(fieldMeta.type, config.include, currentDepth + 1);
2866
- nestedSchemas["include"] = nested.schema;
2867
- if (Object.keys(nested.forcedTree).length > 0)
2868
- relForced.include = nested.forcedTree;
2869
- if (Object.keys(nested.forcedCountWhere).length > 0) {
2870
- relForced._countWhere = nested.forcedCountWhere;
2871
- relForced._countWherePlacement = "include";
2872
- }
2873
- }
2874
- if (config.where) {
2875
- const { schema: whereSchema, forced } = deps.buildWhereSchema(
2876
- fieldMeta.type,
2877
- config.where
2899
+ fieldSchemas[fieldName] = import_zod7.z.literal(true).optional();
2900
+ continue;
2901
+ }
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.`
2878
2914
  );
2879
- if (whereSchema)
2880
- nestedSchemas["where"] = whereSchema;
2881
- if (hasWhereForced(forced))
2882
- relForced.where = forced;
2883
- }
2884
- if (config.orderBy) {
2885
- nestedSchemas["orderBy"] = deps.buildOrderBySchema(fieldMeta.type, config.orderBy);
2886
- }
2887
- if (config.cursor) {
2888
- nestedSchemas["cursor"] = deps.buildCursorSchema(fieldMeta.type, config.cursor);
2889
- }
2890
- if (config.take) {
2891
- nestedSchemas["take"] = deps.buildTakeSchema(config.take);
2892
2915
  }
2893
- if (config.skip) {
2894
- nestedSchemas["skip"] = import_zod6.z.number().int().min(0).optional();
2895
- }
2896
- const nestedObj = import_zod6.z.object(nestedSchemas).strict();
2897
- fieldSchemas[fieldName] = import_zod6.z.union([import_zod6.z.literal(true), nestedObj]).optional();
2898
- if (Object.keys(relForced).length > 0)
2899
- forcedTree[fieldName] = relForced;
2900
- }
2901
- }
2902
- const selectFieldKeys = Object.keys(fieldSchemas);
2903
- const baseSchema = import_zod6.z.object(fieldSchemas).strict();
2904
- const schema = selectFieldKeys.length > 0 ? baseSchema.refine(
2905
- (v) => selectFieldKeys.some((k) => v[k] !== void 0),
2906
- { message: "select must specify at least one field" }
2907
- ).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();
2908
2930
  return {
2909
2931
  schema,
2910
2932
  forcedTree,
2911
2933
  forcedCountWhere: topLevelForcedCountWhere
2912
2934
  };
2913
2935
  }
2914
- 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 };
2915
2943
  }
2916
2944
 
2917
2945
  // src/shared/operation-shape-keys.ts
@@ -2921,7 +2949,6 @@ var OPERATION_SHAPE_KEYS = {
2921
2949
  findFirstOrThrow: ["where", "include", "select", "orderBy", "cursor", "take", "skip", "distinct"],
2922
2950
  findUnique: ["where", "include", "select"],
2923
2951
  findUniqueOrThrow: ["where", "include", "select"],
2924
- findManyPaginated: ["where", "include", "select", "orderBy", "cursor", "take", "skip", "distinct"],
2925
2952
  count: ["where", "select", "cursor", "orderBy", "skip", "take"],
2926
2953
  aggregate: ["where", "orderBy", "cursor", "take", "skip", "_count", "_avg", "_sum", "_min", "_max"],
2927
2954
  groupBy: ["where", "by", "having", "_count", "_avg", "_sum", "_min", "_max", "orderBy", "take", "skip"],
@@ -2956,6 +2983,99 @@ var MUTATION_SHAPE_KEYS = {
2956
2983
  delete: new Set(OPERATION_SHAPE_KEYS.delete),
2957
2984
  deleteMany: new Set(OPERATION_SHAPE_KEYS.deleteMany)
2958
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
+ }
2959
3079
 
2960
3080
  // src/runtime/query-builder.ts
2961
3081
  var METHOD_ALLOWED_ARGS = READ_METHOD_ALLOWED_ARGS;
@@ -3056,6 +3176,90 @@ function createQueryBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
3056
3176
  }
3057
3177
  return shapeOrFn;
3058
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
+ }
3059
3263
  function buildShapeZodSchema(model, method, shape) {
3060
3264
  validateShapeArgs(method, shape);
3061
3265
  validateUniqueWhere(model, method, shape);
@@ -3095,73 +3299,19 @@ function createQueryBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
3095
3299
  }
3096
3300
  if (shape.orderBy) {
3097
3301
  if (method === "groupBy" && shape.by) {
3098
- const sortEnum = import_zod7.z.enum(["asc", "desc"]);
3099
- 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 {
3100
3310
  if (shape.orderBy === true) {
3101
- const groupByOrderFields = {};
3102
- for (const field of shape.by) {
3103
- groupByOrderFields[field] = sortEnum.optional();
3104
- }
3105
- groupByOrderFields._count = sortEnum.optional();
3106
- const fieldKeys = Object.keys(groupByOrderFields);
3107
- const singleSchema = import_zod7.z.object(groupByOrderFields).strict().refine(
3108
- (v) => fieldKeys.some(
3109
- (k) => v[k] !== void 0
3110
- ),
3111
- { message: "orderBy must specify at least one field" }
3112
- );
3113
- schemaFields.orderBy = import_zod7.z.union([
3114
- singleSchema,
3115
- import_zod7.z.preprocess(coerceToArray, import_zod7.z.array(singleSchema).min(1))
3116
- ]).optional();
3117
- } else {
3118
- const groupByOrderFields = {};
3119
- for (const [fieldName, config] of Object.entries(shape.orderBy)) {
3120
- if (fieldName === "_count") {
3121
- if (config === true) {
3122
- groupByOrderFields._count = sortEnum.optional();
3123
- } else if (typeof config === "object" && config !== null) {
3124
- const countFields = {};
3125
- for (const countField of Object.keys(config)) {
3126
- if (!bySet.has(countField)) {
3127
- throw new ShapeError(
3128
- `orderBy _count field "${countField}" must be included in "by" for groupBy`
3129
- );
3130
- }
3131
- countFields[countField] = sortEnum.optional();
3132
- }
3133
- const countKeys = Object.keys(countFields);
3134
- groupByOrderFields._count = import_zod7.z.object(countFields).strict().refine(
3135
- (v) => countKeys.some(
3136
- (k) => v[k] !== void 0
3137
- ),
3138
- {
3139
- message: "orderBy._count must specify at least one field"
3140
- }
3141
- ).optional();
3142
- }
3143
- continue;
3144
- }
3145
- if (!bySet.has(fieldName)) {
3146
- throw new ShapeError(
3147
- `orderBy field "${fieldName}" must be included in "by" for groupBy`
3148
- );
3149
- }
3150
- groupByOrderFields[fieldName] = sortEnum.optional();
3151
- }
3152
- const fieldKeys = Object.keys(groupByOrderFields);
3153
- const singleSchema = import_zod7.z.object(groupByOrderFields).strict().refine(
3154
- (v) => fieldKeys.some(
3155
- (k) => v[k] !== void 0
3156
- ),
3157
- { 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.`
3158
3313
  );
3159
- schemaFields.orderBy = import_zod7.z.union([
3160
- singleSchema,
3161
- import_zod7.z.preprocess(coerceToArray, import_zod7.z.array(singleSchema).min(1))
3162
- ]).optional();
3163
3314
  }
3164
- } else {
3165
3315
  schemaFields.orderBy = argsBuilder.buildOrderBySchema(
3166
3316
  model,
3167
3317
  shape.orderBy
@@ -3169,19 +3319,16 @@ function createQueryBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
3169
3319
  }
3170
3320
  }
3171
3321
  if (shape.cursor) {
3172
- schemaFields.cursor = argsBuilder.buildCursorSchema(
3173
- model,
3174
- shape.cursor
3175
- );
3322
+ schemaFields.cursor = argsBuilder.buildCursorSchema(model, shape.cursor);
3176
3323
  }
3177
- if (shape.take) {
3324
+ if (shape.take !== void 0) {
3178
3325
  schemaFields.take = argsBuilder.buildTakeSchema(shape.take);
3179
3326
  }
3180
3327
  if (shape.skip !== void 0) {
3181
3328
  if (shape.skip !== true) {
3182
3329
  throw new ShapeError('Shape config "skip" must be true');
3183
3330
  }
3184
- schemaFields.skip = import_zod7.z.number().int().min(0).optional();
3331
+ schemaFields.skip = import_zod8.z.number().int().min(0).optional();
3185
3332
  }
3186
3333
  if (shape.distinct) {
3187
3334
  schemaFields.distinct = argsBuilder.buildDistinctSchema(
@@ -3228,13 +3375,10 @@ function createQueryBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
3228
3375
  schemaFields.by = argsBuilder.buildBySchema(model, shape.by);
3229
3376
  }
3230
3377
  if (shape.having) {
3231
- schemaFields.having = argsBuilder.buildHavingSchema(
3232
- model,
3233
- shape.having
3234
- );
3378
+ schemaFields.having = argsBuilder.buildHavingSchema(model, shape.having);
3235
3379
  }
3236
3380
  return {
3237
- zodSchema: import_zod7.z.object(schemaFields).strict(),
3381
+ zodSchema: import_zod8.z.object(schemaFields).strict(),
3238
3382
  forcedWhere,
3239
3383
  forcedOnlyWhereKeys,
3240
3384
  forcedIncludeTree,
@@ -3427,22 +3571,18 @@ function buildScopedUniqueWhere(existingWhere, conditions, scopeFks, log, model)
3427
3571
  allConditions.push(...conditions);
3428
3572
  return { ...topLevel, AND: allConditions };
3429
3573
  }
3430
- function isComparableScopeValue(v) {
3431
- const t = typeof v;
3432
- return t === "string" || t === "number" || t === "bigint";
3433
- }
3434
- function looseEqual(a, b, log, fk) {
3574
+ function scopeValuesEqual(a, b) {
3435
3575
  if (a === b)
3436
3576
  return true;
3437
- if (!isComparableScopeValue(a) || !isComparableScopeValue(b))
3438
- return false;
3439
- const eq = String(a) === String(b);
3440
- if (eq && log && fk) {
3441
- log.warn(
3442
- `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.`
3443
- );
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);
3444
3581
  }
3445
- return eq;
3582
+ if (bIsBig && typeof a === "number") {
3583
+ return Number.isInteger(a) && b === BigInt(a);
3584
+ }
3585
+ return false;
3446
3586
  }
3447
3587
  function buildFkSelect(fks) {
3448
3588
  const select = {};
@@ -3732,7 +3872,7 @@ async function handleFindUnique(args, query, conditions, scopes, operation, log,
3732
3872
  const result = await query(nextArgs);
3733
3873
  if (result === null)
3734
3874
  return result;
3735
- if (typeof result !== "object" || result === null) {
3875
+ if (typeof result !== "object") {
3736
3876
  throw new ShapeError(
3737
3877
  `${operation} on model "${model}" returned a non-object, non-null result`
3738
3878
  );
@@ -3763,7 +3903,7 @@ async function handleFindUnique(args, query, conditions, scopes, operation, log,
3763
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.`
3764
3904
  );
3765
3905
  }
3766
- if (typeof verifyResult !== "object" || verifyResult === null) {
3906
+ if (typeof verifyResult !== "object") {
3767
3907
  throw new PolicyError(
3768
3908
  `prisma-guard: Scope verification re-query on model "${model}" returned a non-object result.`
3769
3909
  );
@@ -3777,7 +3917,7 @@ async function handleFindUnique(args, query, conditions, scopes, operation, log,
3777
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).`
3778
3918
  );
3779
3919
  }
3780
- if (!looseEqual(verifyObj[fk], value, log, fk)) {
3920
+ if (!scopeValuesEqual(verifyObj[fk], value)) {
3781
3921
  if (operation === "findUniqueOrThrow") {
3782
3922
  throw new PolicyError(
3783
3923
  `prisma-guard: Record on model "${model}" not accessible in current scope`
@@ -3797,97 +3937,158 @@ async function handleFindUnique(args, query, conditions, scopes, operation, log,
3797
3937
  }
3798
3938
 
3799
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
3800
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
+ }
3801
4062
 
3802
4063
  // src/runtime/model-guard-data.ts
3803
- var import_zod8 = require("zod");
3804
- var ALLOWED_BODY_KEYS_CREATE = /* @__PURE__ */ new Set(["data"]);
3805
- var ALLOWED_BODY_KEYS_CREATE_PROJECTION = /* @__PURE__ */ new Set([
3806
- "data",
3807
- "select",
3808
- "include"
3809
- ]);
3810
- var ALLOWED_BODY_KEYS_CREATE_MANY = /* @__PURE__ */ new Set([
3811
- "data",
3812
- "skipDuplicates"
3813
- ]);
3814
- var ALLOWED_BODY_KEYS_CREATE_MANY_PROJECTION = /* @__PURE__ */ new Set([
3815
- "data",
3816
- "select",
3817
- "include",
3818
- "skipDuplicates"
3819
- ]);
3820
- var ALLOWED_BODY_KEYS_UPDATE = /* @__PURE__ */ new Set(["data", "where"]);
3821
- var ALLOWED_BODY_KEYS_UPDATE_PROJECTION = /* @__PURE__ */ new Set([
3822
- "data",
3823
- "where",
3824
- "select",
3825
- "include"
3826
- ]);
3827
- var ALLOWED_BODY_KEYS_DELETE = /* @__PURE__ */ new Set(["where"]);
3828
- var ALLOWED_BODY_KEYS_DELETE_PROJECTION = /* @__PURE__ */ new Set([
3829
- "where",
3830
- "select",
3831
- "include"
3832
- ]);
3833
- var ALLOWED_BODY_KEYS_UPSERT = /* @__PURE__ */ new Set([
3834
- "where",
3835
- "create",
3836
- "update",
3837
- "select",
3838
- "include"
3839
- ]);
3840
- var VALID_SHAPE_KEYS_CREATE = /* @__PURE__ */ new Set(["data"]);
3841
- var VALID_SHAPE_KEYS_CREATE_PROJECTION = /* @__PURE__ */ new Set([
3842
- "data",
3843
- "select",
3844
- "include"
3845
- ]);
3846
- var VALID_SHAPE_KEYS_UPDATE = /* @__PURE__ */ new Set(["data", "where"]);
3847
- var VALID_SHAPE_KEYS_UPDATE_PROJECTION = /* @__PURE__ */ new Set([
3848
- "data",
3849
- "where",
3850
- "select",
3851
- "include"
3852
- ]);
3853
- var VALID_SHAPE_KEYS_DELETE = /* @__PURE__ */ new Set(["where"]);
3854
- var VALID_SHAPE_KEYS_DELETE_PROJECTION = /* @__PURE__ */ new Set([
3855
- "where",
3856
- "select",
3857
- "include"
3858
- ]);
3859
- var VALID_SHAPE_KEYS_UPSERT = /* @__PURE__ */ new Set([
3860
- "where",
3861
- "create",
3862
- "update",
3863
- "select",
3864
- "include"
3865
- ]);
3866
- var KNOWN_RELATION_WRITE_OPS = /* @__PURE__ */ new Set([
3867
- "connect",
3868
- "connectOrCreate",
3869
- "create",
3870
- "createMany",
3871
- "disconnect",
3872
- "delete",
3873
- "set",
3874
- "update",
3875
- "updateMany",
3876
- "upsert",
3877
- "deleteMany"
3878
- ]);
3879
- function validateMutationBodyKeys(body, allowed, method) {
3880
- 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)) {
3881
4077
  if (!allowed.has(key)) {
3882
4078
  throw new ShapeError(
3883
- `Unexpected key "${key}" in ${method} body. Allowed keys: ${[...allowed].join(", ")}`
4079
+ `Unknown key "${key}" in ${opLabel} config on "${model}.${field}". Allowed: ${[...allowed].join(", ")}`
3884
4080
  );
3885
4081
  }
3886
4082
  }
3887
4083
  }
3888
- function validateMutationShapeKeys(shape, allowed, method) {
3889
- for (const key of Object.keys(shape)) {
4084
+ function validateAllowedKeys(value, allowed, method, kind) {
4085
+ for (const key of Object.keys(value)) {
3890
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
+ }
3891
4092
  throw new ShapeError(
3892
4093
  `Shape key "${key}" not valid for ${method}. Allowed: ${[...allowed].join(", ")}`
3893
4094
  );
@@ -3929,24 +4130,24 @@ function buildWhereFieldsSchema(model, config, typeMap, schemaBuilder) {
3929
4130
  for (const [fieldName, value] of Object.entries(config)) {
3930
4131
  if (value !== true)
3931
4132
  throw new ShapeError(
3932
- `Field "${fieldName}" in connect/where config must be true`
4133
+ `Field "${fieldName}" in filter config must be true`
3933
4134
  );
3934
4135
  const meta = modelFields[fieldName];
3935
4136
  if (!meta)
3936
4137
  throw new ShapeError(`Unknown field "${fieldName}" on model "${model}"`);
3937
4138
  if (meta.isRelation)
3938
4139
  throw new ShapeError(
3939
- `Relation field "${fieldName}" cannot be used in connect/where`
4140
+ `Relation field "${fieldName}" cannot be used in filter`
3940
4141
  );
3941
4142
  fieldSchemas[fieldName] = schemaBuilder.buildFieldSchema(model, fieldName).optional();
3942
4143
  fieldKeys.push(fieldName);
3943
4144
  }
3944
- return import_zod8.z.object(fieldSchemas).strict().refine(
4145
+ return import_zod10.z.object(fieldSchemas).strict().refine(
3945
4146
  (v) => fieldKeys.some((k) => v[k] !== void 0),
3946
- { message: `At least one field required in connect/where` }
4147
+ { message: `At least one field required in filter` }
3947
4148
  );
3948
4149
  }
3949
- function buildNestedDataSchema(model, config, typeMap, schemaBuilder) {
4150
+ function buildNestedDataSchema(model, config, mode, typeMap, schemaBuilder) {
3950
4151
  const modelFields = typeMap[model];
3951
4152
  if (!modelFields)
3952
4153
  throw new ShapeError(`Unknown model: ${model}`);
@@ -3967,382 +4168,349 @@ function buildNestedDataSchema(model, config, typeMap, schemaBuilder) {
3967
4168
  throw new ShapeError(
3968
4169
  `updatedAt field "${fieldName}" cannot be used in nested data`
3969
4170
  );
3970
- let fieldSchema = schemaBuilder.buildFieldSchema(model, fieldName);
3971
- if (!meta.isRequired) {
3972
- fieldSchema = fieldSchema.nullable().optional();
3973
- } else if (meta.hasDefault) {
3974
- fieldSchema = fieldSchema.optional();
3975
- }
3976
- 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
+ });
3977
4180
  }
3978
- return import_zod8.z.object(fieldSchemas).strict();
4181
+ return import_zod10.z.object(fieldSchemas).strict();
3979
4182
  }
3980
- function buildRelationWriteSchema(model, fieldName, relatedModelName, isList, config, typeMap, schemaBuilder) {
3981
- const relatedFields = typeMap[relatedModelName];
3982
- 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) {
3983
4255
  throw new ShapeError(
3984
- `Unknown related model "${relatedModelName}" for field "${model}.${fieldName}"`
4256
+ `createMany is only valid on to-many relations ("${ctx.model}.${ctx.fieldName}")`
3985
4257
  );
3986
- for (const key of Object.keys(config)) {
3987
- if (!KNOWN_RELATION_WRITE_OPS.has(key)) {
3988
- throw new ShapeError(
3989
- `Unknown relation write operation "${key}" on "${model}.${fieldName}". Allowed: ${[...KNOWN_RELATION_WRITE_OPS].join(", ")}`
3990
- );
3991
- }
3992
4258
  }
3993
- const opSchemas = {};
3994
- if (config.connect !== void 0) {
3995
- 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) {
3996
4281
  throw new ShapeError(
3997
- `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`
3998
4283
  );
3999
4284
  }
4000
- const connectSchema = buildWhereFieldsSchema(
4001
- relatedModelName,
4002
- config.connect,
4003
- typeMap,
4004
- 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`
4005
4290
  );
4006
- opSchemas["connect"] = isList ? import_zod8.z.union([
4007
- connectSchema,
4008
- import_zod8.z.preprocess(coerceToArray, import_zod8.z.array(connectSchema))
4009
- ]).optional() : connectSchema.optional();
4010
4291
  }
4011
- if (config.connectOrCreate !== void 0) {
4012
- if (!isPlainObject(config.connectOrCreate)) {
4013
- throw new ShapeError(
4014
- `connectOrCreate config on "${model}.${fieldName}" must be an object with "where" and "create"`
4015
- );
4016
- }
4017
- const coc = config.connectOrCreate;
4018
- if (!coc.where || !isPlainObject(coc.where)) {
4019
- throw new ShapeError(
4020
- `connectOrCreate on "${model}.${fieldName}" requires "where" object`
4021
- );
4022
- }
4023
- 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) {
4024
4300
  throw new ShapeError(
4025
- `connectOrCreate on "${model}.${fieldName}" requires "create" object`
4301
+ `delete on to-many relation "${ctx.model}.${ctx.fieldName}" requires unique selector config, not true`
4026
4302
  );
4027
4303
  }
4028
- const whereSchema = buildWhereFieldsSchema(
4029
- relatedModelName,
4030
- coc.where,
4031
- typeMap,
4032
- schemaBuilder
4033
- );
4034
- const createSchema = buildNestedDataSchema(
4035
- relatedModelName,
4036
- coc.create,
4037
- typeMap,
4038
- 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`
4039
4309
  );
4040
- const cocSchema = import_zod8.z.object({ where: whereSchema, create: createSchema }).strict();
4041
- opSchemas["connectOrCreate"] = isList ? import_zod8.z.union([cocSchema, import_zod8.z.preprocess(coerceToArray, import_zod8.z.array(cocSchema))]).optional() : cocSchema.optional();
4042
4310
  }
4043
- if (config.create !== void 0) {
4044
- if (!isPlainObject(config.create)) {
4045
- throw new ShapeError(
4046
- `create config on "${model}.${fieldName}" must be an object of field names`
4047
- );
4048
- }
4049
- const createSchema = buildNestedDataSchema(
4050
- relatedModelName,
4051
- config.create,
4052
- typeMap,
4053
- 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}")`
4054
4320
  );
4055
- opSchemas["create"] = isList ? import_zod8.z.union([
4056
- createSchema,
4057
- import_zod8.z.preprocess(coerceToArray, import_zod8.z.array(createSchema))
4058
- ]).optional() : createSchema.optional();
4059
4321
  }
4060
- if (config.createMany !== void 0) {
4061
- if (!isList) {
4062
- throw new ShapeError(
4063
- `createMany is only valid on to-many relations ("${model}.${fieldName}")`
4064
- );
4065
- }
4066
- if (!isPlainObject(config.createMany)) {
4067
- throw new ShapeError(
4068
- `createMany config on "${model}.${fieldName}" must be an object`
4069
- );
4070
- }
4071
- const cmConfig = config.createMany;
4072
- if (!cmConfig.data || !isPlainObject(cmConfig.data)) {
4073
- throw new ShapeError(
4074
- `createMany on "${model}.${fieldName}" requires "data" object`
4075
- );
4076
- }
4077
- const dataSchema = buildNestedDataSchema(
4078
- relatedModelName,
4079
- cmConfig.data,
4080
- typeMap,
4081
- 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`
4082
4340
  );
4083
- const cmSchemaFields = {
4084
- data: import_zod8.z.preprocess(coerceToArray, import_zod8.z.array(dataSchema))
4085
- };
4086
- if ("skipDuplicates" in cmConfig) {
4087
- cmSchemaFields["skipDuplicates"] = import_zod8.z.boolean().optional();
4088
- }
4089
- 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);
4090
4350
  }
4091
- if (config.disconnect !== void 0) {
4092
- if (config.disconnect === true) {
4093
- if (isList) {
4094
- throw new ShapeError(
4095
- `disconnect on to-many relation "${model}.${fieldName}" requires field config, not true`
4096
- );
4097
- }
4098
- opSchemas["disconnect"] = import_zod8.z.literal(true).optional();
4099
- } else if (isPlainObject(config.disconnect)) {
4100
- const disconnectSchema = buildWhereFieldsSchema(
4101
- relatedModelName,
4102
- config.disconnect,
4103
- typeMap,
4104
- schemaBuilder
4105
- );
4106
- if (isList) {
4107
- opSchemas["disconnect"] = import_zod8.z.union([
4108
- disconnectSchema,
4109
- import_zod8.z.preprocess(coerceToArray, import_zod8.z.array(disconnectSchema))
4110
- ]).optional();
4111
- } else {
4112
- opSchemas["disconnect"] = import_zod8.z.union([import_zod8.z.literal(true), disconnectSchema]).optional();
4113
- }
4114
- } else {
4115
- throw new ShapeError(
4116
- `disconnect config on "${model}.${fieldName}" must be true (to-one) or an object of field names`
4117
- );
4118
- }
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);
4119
4387
  }
4120
- if (config.delete !== void 0) {
4121
- if (config.delete === true) {
4122
- if (isList) {
4123
- throw new ShapeError(
4124
- `delete on to-many relation "${model}.${fieldName}" requires field config, not true`
4125
- );
4126
- }
4127
- opSchemas["delete"] = import_zod8.z.literal(true).optional();
4128
- } else if (isPlainObject(config.delete)) {
4129
- const deleteSchema = buildWhereFieldsSchema(
4130
- relatedModelName,
4131
- config.delete,
4132
- typeMap,
4133
- schemaBuilder
4134
- );
4135
- if (isList) {
4136
- opSchemas["delete"] = import_zod8.z.union([
4137
- deleteSchema,
4138
- import_zod8.z.preprocess(coerceToArray, import_zod8.z.array(deleteSchema))
4139
- ]).optional();
4140
- } else {
4141
- opSchemas["delete"] = import_zod8.z.union([import_zod8.z.literal(true), deleteSchema]).optional();
4142
- }
4143
- } else {
4388
+ const hasWhereKey = "where" in cfg;
4389
+ if (hasWhereKey) {
4390
+ if (!isPlainObject(cfg.where)) {
4144
4391
  throw new ShapeError(
4145
- `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`
4146
4393
  );
4147
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();
4148
4398
  }
4149
- if (config.set !== void 0) {
4150
- if (!isList) {
4151
- throw new ShapeError(
4152
- `set is only valid on to-many relations ("${model}.${fieldName}")`
4153
- );
4154
- }
4155
- if (!isPlainObject(config.set)) {
4156
- throw new ShapeError(
4157
- `set config on "${model}.${fieldName}" must be an object of field names`
4158
- );
4159
- }
4160
- const setSchema = buildWhereFieldsSchema(
4161
- relatedModelName,
4162
- config.set,
4163
- typeMap,
4164
- 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}")`
4165
4406
  );
4166
- opSchemas["set"] = import_zod8.z.preprocess(coerceToArray, import_zod8.z.array(setSchema)).optional();
4167
4407
  }
4168
- if (config.update !== void 0) {
4169
- if (!isPlainObject(config.update)) {
4170
- throw new ShapeError(
4171
- `update config on "${model}.${fieldName}" must be an object`
4172
- );
4173
- }
4174
- const updateConfig = config.update;
4175
- if (isList) {
4176
- if (!updateConfig.where || !isPlainObject(updateConfig.where)) {
4177
- throw new ShapeError(
4178
- `update on to-many "${model}.${fieldName}" requires "where" object`
4179
- );
4180
- }
4181
- if (!updateConfig.data || !isPlainObject(updateConfig.data)) {
4182
- throw new ShapeError(
4183
- `update on to-many "${model}.${fieldName}" requires "data" object`
4184
- );
4185
- }
4186
- const whereSchema = buildWhereFieldsSchema(
4187
- relatedModelName,
4188
- updateConfig.where,
4189
- typeMap,
4190
- schemaBuilder
4191
- );
4192
- const dataSchema = buildNestedDataSchema(
4193
- relatedModelName,
4194
- updateConfig.data,
4195
- typeMap,
4196
- schemaBuilder
4197
- );
4198
- const updateSchema = import_zod8.z.object({ where: whereSchema, data: dataSchema }).strict();
4199
- opSchemas["update"] = import_zod8.z.union([
4200
- updateSchema,
4201
- import_zod8.z.preprocess(coerceToArray, import_zod8.z.array(updateSchema))
4202
- ]).optional();
4203
- } else {
4204
- const dataSchema = buildNestedDataSchema(
4205
- relatedModelName,
4206
- updateConfig,
4207
- typeMap,
4208
- schemaBuilder
4209
- );
4210
- opSchemas["update"] = dataSchema.optional();
4211
- }
4212
- }
4213
- if (config.upsert !== void 0) {
4214
- if (!isPlainObject(config.upsert)) {
4215
- throw new ShapeError(
4216
- `upsert config on "${model}.${fieldName}" must be an object`
4217
- );
4218
- }
4219
- const upsertConfig = config.upsert;
4220
- if (!upsertConfig.create || !isPlainObject(upsertConfig.create)) {
4221
- throw new ShapeError(
4222
- `upsert on "${model}.${fieldName}" requires "create" object`
4223
- );
4224
- }
4225
- if (!upsertConfig.update || !isPlainObject(upsertConfig.update)) {
4226
- throw new ShapeError(
4227
- `upsert on "${model}.${fieldName}" requires "update" object`
4228
- );
4229
- }
4230
- const createSchema = buildNestedDataSchema(
4231
- relatedModelName,
4232
- upsertConfig.create,
4233
- typeMap,
4234
- 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`
4235
4421
  );
4236
- const updateSchema = buildNestedDataSchema(
4237
- relatedModelName,
4238
- upsertConfig.update,
4239
- typeMap,
4240
- 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`
4241
4431
  );
4242
- if (isList) {
4243
- if (!upsertConfig.where || !isPlainObject(upsertConfig.where)) {
4244
- throw new ShapeError(
4245
- `upsert on to-many "${model}.${fieldName}" requires "where" object`
4246
- );
4247
- }
4248
- const whereSchema = buildWhereFieldsSchema(
4249
- relatedModelName,
4250
- upsertConfig.where,
4251
- typeMap,
4252
- schemaBuilder
4253
- );
4254
- const upsertSchema = import_zod8.z.object({
4255
- where: whereSchema,
4256
- create: createSchema,
4257
- update: updateSchema
4258
- }).strict();
4259
- opSchemas["upsert"] = import_zod8.z.union([
4260
- upsertSchema,
4261
- import_zod8.z.preprocess(coerceToArray, import_zod8.z.array(upsertSchema))
4262
- ]).optional();
4263
- } else {
4264
- if (upsertConfig.where) {
4265
- const whereSchema = buildWhereFieldsSchema(
4266
- relatedModelName,
4267
- upsertConfig.where,
4268
- typeMap,
4269
- schemaBuilder
4270
- );
4271
- const upsertSchema = import_zod8.z.object({
4272
- where: whereSchema,
4273
- create: createSchema,
4274
- update: updateSchema
4275
- }).strict();
4276
- opSchemas["upsert"] = upsertSchema.optional();
4277
- } else {
4278
- const upsertSchema = import_zod8.z.object({ create: createSchema, update: updateSchema }).strict();
4279
- opSchemas["upsert"] = upsertSchema.optional();
4280
- }
4281
- }
4282
4432
  }
4283
- if (config.updateMany !== void 0) {
4284
- if (!isList) {
4285
- throw new ShapeError(
4286
- `updateMany is only valid on to-many relations ("${model}.${fieldName}")`
4287
- );
4288
- }
4289
- if (!isPlainObject(config.updateMany)) {
4290
- throw new ShapeError(
4291
- `updateMany config on "${model}.${fieldName}" must be an object`
4292
- );
4293
- }
4294
- const umConfig = config.updateMany;
4295
- if (!umConfig.where || !isPlainObject(umConfig.where)) {
4296
- throw new ShapeError(
4297
- `updateMany on "${model}.${fieldName}" requires "where" object`
4298
- );
4299
- }
4300
- if (!umConfig.data || !isPlainObject(umConfig.data)) {
4301
- throw new ShapeError(
4302
- `updateMany on "${model}.${fieldName}" requires "data" object`
4303
- );
4304
- }
4305
- const whereSchema = buildWhereFieldsSchema(
4306
- relatedModelName,
4307
- umConfig.where,
4308
- typeMap,
4309
- 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}")`
4310
4447
  );
4311
- const dataSchema = buildNestedDataSchema(
4312
- relatedModelName,
4313
- umConfig.data,
4314
- typeMap,
4315
- 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.`
4316
4456
  );
4317
- const umSchema = import_zod8.z.object({ where: whereSchema, data: dataSchema }).strict();
4318
- opSchemas["updateMany"] = import_zod8.z.union([umSchema, import_zod8.z.preprocess(coerceToArray, import_zod8.z.array(umSchema))]).optional();
4319
4457
  }
4320
- if (config.deleteMany !== void 0) {
4321
- if (!isList) {
4322
- throw new ShapeError(
4323
- `deleteMany is only valid on to-many relations ("${model}.${fieldName}")`
4324
- );
4325
- }
4326
- 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)) {
4327
4488
  throw new ShapeError(
4328
- `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(", ")}`
4329
4490
  );
4330
4491
  }
4331
- 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,
4332
4501
  relatedModelName,
4333
- config.deleteMany,
4502
+ isList,
4503
+ config: opConfig,
4334
4504
  typeMap,
4505
+ uniqueMap,
4506
+ enumMap,
4507
+ scalarBase,
4335
4508
  schemaBuilder
4336
- );
4337
- opSchemas["deleteMany"] = import_zod8.z.union([
4338
- filterSchema,
4339
- import_zod8.z.preprocess(coerceToArray, import_zod8.z.array(filterSchema)),
4340
- import_zod8.z.object({}).strict()
4341
- ]).optional();
4509
+ });
4342
4510
  }
4343
- return import_zod8.z.object(opSchemas).strict();
4511
+ return import_zod10.z.object(opSchemas).strict();
4344
4512
  }
4345
- function buildDataSchema(model, dataConfig, mode, typeMap, schemaBuilder, zodDefaults) {
4513
+ function buildDataSchema(model, dataConfig, mode, typeMap, uniqueMap, enumMap, scalarBase, schemaBuilder, zodDefaults) {
4346
4514
  const modelFields = typeMap[model];
4347
4515
  if (!modelFields)
4348
4516
  throw new ShapeError(`Unknown model: ${model}`);
@@ -4354,11 +4522,23 @@ function buildDataSchema(model, dataConfig, mode, typeMap, schemaBuilder, zodDef
4354
4522
  const fieldMeta = modelFields[fieldName];
4355
4523
  if (!fieldMeta) {
4356
4524
  if (isUnsupportedMarker(value)) {
4357
- schemaMap[fieldName] = import_zod8.z.unknown().optional();
4358
4525
  continue;
4359
4526
  }
4360
4527
  throw new ShapeError(`Unknown field "${fieldName}" on model "${model}"`);
4361
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
+ }
4362
4542
  if (fieldMeta.isRelation) {
4363
4543
  if (!isPlainObject(value)) {
4364
4544
  throw new ShapeError(
@@ -4372,6 +4552,9 @@ function buildDataSchema(model, dataConfig, mode, typeMap, schemaBuilder, zodDef
4372
4552
  fieldMeta.isList,
4373
4553
  value,
4374
4554
  typeMap,
4555
+ uniqueMap,
4556
+ enumMap,
4557
+ scalarBase,
4375
4558
  schemaBuilder
4376
4559
  ).optional();
4377
4560
  continue;
@@ -4381,7 +4564,7 @@ function buildDataSchema(model, dataConfig, mode, typeMap, schemaBuilder, zodDef
4381
4564
  `updatedAt field "${fieldName}" cannot be used in data shape`
4382
4565
  );
4383
4566
  if (typeof value === "function") {
4384
- let baseSchema = schemaBuilder.buildBaseFieldSchema(
4567
+ const baseSchema = schemaBuilder.buildBaseFieldSchema(
4385
4568
  model,
4386
4569
  fieldName
4387
4570
  );
@@ -4399,46 +4582,22 @@ function buildDataSchema(model, dataConfig, mode, typeMap, schemaBuilder, zodDef
4399
4582
  `Inline refine for "${model}.${fieldName}" must return a Zod schema`
4400
4583
  );
4401
4584
  }
4402
- let fieldSchema = refined;
4403
- const handlesUndefined = schemaProducesValueForUndefined(fieldSchema);
4404
- if (mode === "create") {
4405
- if (!fieldMeta.isRequired) {
4406
- fieldSchema = handlesUndefined ? fieldSchema.nullable() : fieldSchema.nullable().optional();
4407
- } else if (fieldMeta.hasDefault) {
4408
- if (!handlesUndefined) {
4409
- fieldSchema = fieldSchema.optional();
4410
- }
4411
- }
4412
- } else {
4413
- if (!fieldMeta.isRequired) {
4414
- fieldSchema = fieldSchema.nullable().optional();
4415
- } else {
4416
- fieldSchema = fieldSchema.optional();
4417
- }
4418
- }
4419
- schemaMap[fieldName] = fieldSchema;
4420
- } else if (value === true) {
4421
- let fieldSchema = schemaBuilder.buildFieldSchema(
4422
- model,
4423
- fieldName
4585
+ const handlesUndefined = schemaProducesValueForUndefined(
4586
+ refined
4587
+ );
4588
+ schemaMap[fieldName] = applyCreateUpdateNullability(
4589
+ fieldMeta,
4590
+ refined,
4591
+ { mode, handlesUndefined }
4424
4592
  );
4593
+ } else if (value === true) {
4594
+ const fieldSchema = schemaBuilder.buildFieldSchema(model, fieldName);
4425
4595
  const isZodDefaultField = zodDefaultSet !== void 0 && zodDefaultSet.has(fieldName);
4426
- if (mode === "create") {
4427
- if (!fieldMeta.isRequired) {
4428
- fieldSchema = isZodDefaultField ? fieldSchema.nullable() : fieldSchema.nullable().optional();
4429
- } else if (fieldMeta.hasDefault) {
4430
- if (!isZodDefaultField) {
4431
- fieldSchema = fieldSchema.optional();
4432
- }
4433
- }
4434
- } else {
4435
- if (!fieldMeta.isRequired) {
4436
- fieldSchema = fieldSchema.nullable().optional();
4437
- } else {
4438
- fieldSchema = fieldSchema.optional();
4439
- }
4440
- }
4441
- schemaMap[fieldName] = fieldSchema;
4596
+ schemaMap[fieldName] = applyCreateUpdateNullability(
4597
+ fieldMeta,
4598
+ fieldSchema,
4599
+ { mode, handlesUndefined: isZodDefaultField }
4600
+ );
4442
4601
  } else {
4443
4602
  const actualValue = isForcedValue(value) ? value.value : value;
4444
4603
  let fieldSchema = schemaBuilder.buildFieldSchema(
@@ -4482,7 +4641,7 @@ function buildDataSchema(model, dataConfig, mode, typeMap, schemaBuilder, zodDef
4482
4641
  }
4483
4642
  }
4484
4643
  return {
4485
- schema: import_zod8.z.object(schemaMap).strict(),
4644
+ schema: import_zod10.z.object(schemaMap).strict(),
4486
4645
  forced
4487
4646
  };
4488
4647
  }
@@ -4519,106 +4678,120 @@ function isGuardShape(obj) {
4519
4678
  const keys = Object.keys(obj);
4520
4679
  return keys.length === 0 || keys.every((k) => GUARD_SHAPE_KEYS.has(k));
4521
4680
  }
4522
- function isSingleShape(input) {
4523
- return typeof input === "function" || isGuardShape(input);
4524
- }
4525
- function toPlainObject(value) {
4526
- if (value === null || typeof value !== "object")
4527
- return value;
4528
- if (Array.isArray(value))
4529
- return value.map(toPlainObject);
4530
- if (value instanceof Date)
4531
- return value;
4532
- if (value instanceof Uint8Array)
4533
- return value;
4534
- if (value instanceof RegExp)
4535
- return value;
4536
- if (typeof value.toFixed === "function" && typeof value.toNumber === "function")
4537
- return value;
4538
- const result = {};
4539
- for (const [k, v] of Object.entries(value)) {
4540
- 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");
4541
4686
  }
4542
- return result;
4687
+ return body;
4543
4688
  }
4544
- function requireBody(body) {
4545
- const normalized = toPlainObject(body);
4546
- if (!isPlainObject(normalized))
4547
- throw new ShapeError("Request body must be an object");
4548
- 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
+ }
4549
4695
  }
4550
- function resolveDynamicShape(fn, contextFn) {
4551
- 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
+ }
4552
4702
  let result;
4553
4703
  try {
4554
- result = fn(ctx);
4704
+ result = shapeFn(ctx);
4555
4705
  } catch (err) {
4556
4706
  throw new ShapeError(
4557
- `Dynamic shape function threw: ${err.message}`,
4707
+ `Dynamic ${context} function threw: ${err.message}`,
4558
4708
  { cause: err }
4559
4709
  );
4560
4710
  }
4561
- if (!isPlainObject(result)) {
4562
- 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
+ );
4563
4715
  }
4564
4716
  return result;
4565
4717
  }
4566
- function resolveShape(input, body, contextFn, caller) {
4567
- if (isSingleShape(input)) {
4568
- const wasDynamic2 = typeof input === "function";
4569
- const shape2 = wasDynamic2 ? resolveDynamicShape(input, contextFn) : input;
4570
- const parsed2 = body === void 0 || body === null ? {} : requireBody(body);
4571
- return { shape: shape2, body: parsed2, matchedKey: "_default", wasDynamic: wasDynamic2 };
4572
- }
4573
- const namedMap = input;
4574
- 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) {
4575
4723
  if (GUARD_SHAPE_KEYS.has(key)) {
4576
4724
  throw new ShapeError(
4577
- `Caller key "${key}" collides with reserved shape config key. Rename the caller path.`
4578
- );
4579
- }
4580
- const val = namedMap[key];
4581
- if (typeof val !== "function" && !isGuardShape(val)) {
4582
- throw new ShapeError(
4583
- `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.`
4584
4726
  );
4585
4727
  }
4586
4728
  }
4587
- const parsed = body === void 0 || body === null ? {} : requireBody(body);
4588
- if ("caller" in parsed) {
4589
- throw new CallerError(
4590
- "Pass caller as second argument to .guard() or via context function, not in the request body."
4591
- );
4592
- }
4593
4729
  if (typeof caller !== "string") {
4594
- if ("default" in namedMap) {
4595
- const shapeOrFn2 = namedMap["default"];
4596
- const wasDynamic2 = typeof shapeOrFn2 === "function";
4597
- const shape2 = wasDynamic2 ? resolveDynamicShape(shapeOrFn2, contextFn) : shapeOrFn2;
4598
- return { shape: shape2, body: parsed, matchedKey: "default", wasDynamic: wasDynamic2 };
4730
+ if ("default" in input) {
4731
+ return resolveShapeEntry(input.default, body, contextFn, "default");
4599
4732
  }
4600
- const patterns2 = Object.keys(namedMap);
4601
4733
  throw new CallerError(
4602
- `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).`
4603
4735
  );
4604
4736
  }
4605
- const patterns = Object.keys(namedMap);
4606
- const matched = matchCallerPattern(patterns, caller);
4607
- if (!matched) {
4608
- if ("default" in namedMap) {
4609
- const shapeOrFn2 = namedMap["default"];
4610
- const wasDynamic2 = typeof shapeOrFn2 === "function";
4611
- const shape2 = wasDynamic2 ? resolveDynamicShape(shapeOrFn2, contextFn) : shapeOrFn2;
4612
- return { shape: shape2, body: parsed, matchedKey: "default", wasDynamic: wasDynamic2 };
4613
- }
4614
- throw new CallerError(
4615
- `Unknown caller: "${caller}". Allowed: ${patterns.map((k) => `"${k}"`).join(", ")}`
4616
- );
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
+ };
4617
4785
  }
4618
- const shapeOrFn = namedMap[matched];
4619
- const wasDynamic = typeof shapeOrFn === "function";
4620
- const shape = wasDynamic ? resolveDynamicShape(shapeOrFn, contextFn) : shapeOrFn;
4621
- 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
+ );
4622
4795
  }
4623
4796
 
4624
4797
  // src/runtime/model-guard.ts
@@ -4641,129 +4814,20 @@ var PROJECTION_MUTATION_METHODS = /* @__PURE__ */ new Set([
4641
4814
  "updateManyAndReturn"
4642
4815
  ]);
4643
4816
  var BATCH_CREATE_METHODS = /* @__PURE__ */ new Set(["createMany", "createManyAndReturn"]);
4644
- function buildDefaultSelectInput(config) {
4645
- const result = {};
4646
- for (const [key, value] of Object.entries(config)) {
4647
- if (key === "_count") {
4648
- result[key] = buildDefaultCountInput(
4649
- value
4650
- );
4651
- continue;
4652
- }
4653
- if (value === true) {
4654
- result[key] = true;
4655
- } else {
4656
- const nested = {};
4657
- if (value.select)
4658
- nested.select = buildDefaultSelectInput(value.select);
4659
- if (value.include) {
4660
- nested.include = buildDefaultIncludeInput(value.include);
4661
- }
4662
- result[key] = Object.keys(nested).length > 0 ? nested : true;
4663
- }
4664
- }
4665
- return result;
4666
- }
4667
- function buildDefaultIncludeInput(config) {
4668
- const result = {};
4669
- for (const [key, value] of Object.entries(config)) {
4670
- if (key === "_count") {
4671
- result[key] = buildDefaultCountInput(
4672
- value
4673
- );
4674
- continue;
4675
- }
4676
- if (value === true) {
4677
- result[key] = true;
4678
- } else {
4679
- const nested = {};
4680
- if (value.include) {
4681
- nested.include = buildDefaultIncludeInput(value.include);
4682
- }
4683
- if (value.select)
4684
- nested.select = buildDefaultSelectInput(value.select);
4685
- result[key] = Object.keys(nested).length > 0 ? nested : true;
4686
- }
4687
- }
4688
- return result;
4689
- }
4690
- function buildDefaultCountInput(config) {
4691
- if (config === true)
4692
- return true;
4693
- if (!isPlainObject(config) || !config.select || !isPlainObject(config.select)) {
4694
- return true;
4695
- }
4696
- const selectObj = config.select;
4697
- const result = {};
4698
- for (const key of Object.keys(selectObj)) {
4699
- result[key] = true;
4700
- }
4701
- return { select: result };
4702
- }
4703
- function buildDefaultProjectionBody(shape) {
4704
- if (shape.select) {
4705
- return { select: buildDefaultSelectInput(shape.select) };
4706
- }
4707
- if (shape.include) {
4708
- return { include: buildDefaultIncludeInput(shape.include) };
4709
- }
4710
- return {};
4711
- }
4712
- function applyClientProjectionOverrides(shapeDefault, clientProjection) {
4713
- const result = { ...shapeDefault };
4714
- for (const [key, clientValue] of Object.entries(clientProjection)) {
4715
- const defaultValue = result[key];
4716
- if (defaultValue === void 0) {
4717
- result[key] = clientValue;
4718
- continue;
4719
- }
4720
- if (clientValue === true) {
4721
- result[key] = true;
4722
- continue;
4723
- }
4724
- if (isPlainObject(clientValue)) {
4725
- if (!isPlainObject(defaultValue)) {
4726
- result[key] = clientValue;
4727
- continue;
4728
- }
4729
- const merged = { ...defaultValue };
4730
- const clientObj = clientValue;
4731
- for (const [argKey, argValue] of Object.entries(clientObj)) {
4732
- const defaultArgValue = merged[argKey];
4733
- if ((argKey === "select" || argKey === "include") && isPlainObject(argValue) && isPlainObject(defaultArgValue)) {
4734
- merged[argKey] = applyClientProjectionOverrides(
4735
- defaultArgValue,
4736
- argValue
4737
- );
4738
- } else {
4739
- merged[argKey] = argValue;
4740
- }
4741
- }
4742
- result[key] = merged;
4743
- }
4744
- }
4745
- return result;
4746
- }
4747
- function hasClientControlledValues(obj) {
4748
- for (const value of Object.values(obj)) {
4749
- if (isForcedValue(value))
4750
- continue;
4751
- if (value === true)
4752
- return true;
4753
- 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))
4754
4823
  return true;
4755
- }
4756
- return false;
4757
- }
4758
- function checkIncludeForClientArgs(config) {
4759
- for (const [key, value] of Object.entries(config)) {
4760
4824
  if (key === "_count") {
4761
4825
  if (value !== true && isPlainObject(value) && isPlainObject(value.select)) {
4762
4826
  const selectObj = value.select;
4763
4827
  for (const entryVal of Object.values(selectObj)) {
4764
4828
  if (isPlainObject(entryVal) && entryVal.where) {
4765
4829
  const w = entryVal.where;
4766
- if (isPlainObject(w) && hasClientControlledValues(w))
4830
+ if (isPlainObject(w) && hasClientControlledValues(w, depth + 1))
4767
4831
  return true;
4768
4832
  }
4769
4833
  }
@@ -4772,54 +4836,41 @@ function checkIncludeForClientArgs(config) {
4772
4836
  }
4773
4837
  if (value === true)
4774
4838
  continue;
4775
- if (value.orderBy || value.cursor || value.take || value.skip)
4839
+ const nested = value;
4840
+ if (nested.orderBy || nested.cursor || nested.take || nested.skip)
4776
4841
  return true;
4777
- if (value.where && isPlainObject(value.where) && hasClientControlledValues(value.where)) {
4842
+ if (nested.where && isPlainObject(nested.where) && hasClientControlledValues(nested.where, depth + 1)) {
4778
4843
  return true;
4779
4844
  }
4780
- if (value.include && checkIncludeForClientArgs(value.include))
4845
+ if (nested.include && walkForClientContent(nested.include, predicate, depth + 1))
4781
4846
  return true;
4782
- if (value.select && checkSelectForClientArgs(value.select))
4847
+ if (nested.select && walkForClientContent(nested.select, predicate, depth + 1))
4783
4848
  return true;
4784
4849
  }
4785
4850
  return false;
4786
4851
  }
4787
- function checkSelectForClientArgs(config) {
4788
- for (const [key, value] of Object.entries(config)) {
4789
- if (key === "_count") {
4790
- if (value !== true && isPlainObject(value) && isPlainObject(value.select)) {
4791
- const selectObj = value.select;
4792
- for (const entryVal of Object.values(selectObj)) {
4793
- if (isPlainObject(entryVal) && entryVal.where) {
4794
- const w = entryVal.where;
4795
- if (isPlainObject(w) && hasClientControlledValues(w))
4796
- return true;
4797
- }
4798
- }
4799
- }
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))
4800
4857
  continue;
4801
- }
4802
4858
  if (value === true)
4803
- continue;
4804
- if (value.orderBy || value.cursor || value.take || value.skip)
4805
4859
  return true;
4806
- if (value.where && isPlainObject(value.where) && hasClientControlledValues(value.where)) {
4860
+ if (isPlainObject(value) && hasClientControlledValues(value, depth + 1)) {
4807
4861
  return true;
4808
4862
  }
4809
- if (value.select && checkSelectForClientArgs(value.select))
4810
- return true;
4811
- if (value.include && checkIncludeForClientArgs(value.include))
4812
- return true;
4813
4863
  }
4814
4864
  return false;
4815
4865
  }
4816
4866
  function hasNestedClientControlledArgs(shape) {
4867
+ const predicate = () => false;
4817
4868
  if (shape.include) {
4818
- if (checkIncludeForClientArgs(shape.include))
4869
+ if (walkForClientContent(shape.include, predicate, 0))
4819
4870
  return true;
4820
4871
  }
4821
4872
  if (shape.select) {
4822
- if (checkSelectForClientArgs(shape.select))
4873
+ if (walkForClientContent(shape.select, predicate, 0))
4823
4874
  return true;
4824
4875
  }
4825
4876
  return false;
@@ -4891,77 +4942,62 @@ function createModelGuardExtension(config) {
4891
4942
  const whereBuiltCache = /* @__PURE__ */ new Map();
4892
4943
  const projectionCache = /* @__PURE__ */ new Map();
4893
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
+ }
4894
4955
  function getReadShape(method, queryShape, matchedKey, wasDynamic) {
4895
- if (!wasDynamic) {
4896
- const cacheKey = `${method}\0${matchedKey}`;
4897
- const cached = readShapeCache.get(cacheKey);
4898
- if (cached)
4899
- return cached;
4900
- const built = queryBuilder.buildShapeZodSchema(
4956
+ return memoize(
4957
+ readShapeCache,
4958
+ `${method}\0${matchedKey}`,
4959
+ wasDynamic,
4960
+ () => queryBuilder.buildShapeZodSchema(
4901
4961
  modelName,
4902
4962
  method,
4903
4963
  queryShape
4904
- );
4905
- readShapeCache.set(cacheKey, built);
4906
- return built;
4907
- }
4908
- return queryBuilder.buildShapeZodSchema(
4909
- modelName,
4910
- method,
4911
- queryShape
4964
+ )
4912
4965
  );
4913
4966
  }
4914
4967
  function getDataSchema(mode, dataConfig, matchedKey, wasDynamic) {
4915
- if (!wasDynamic && !hasDataRefines(dataConfig)) {
4916
- const cacheKey = `${mode}\0${matchedKey}`;
4917
- const cached = dataSchemaCache.get(cacheKey);
4918
- if (cached)
4919
- return cached;
4920
- const built = buildDataSchema(
4968
+ const skipCache = wasDynamic || hasDataRefines(dataConfig);
4969
+ return memoize(
4970
+ dataSchemaCache,
4971
+ `${mode}\0${matchedKey}`,
4972
+ skipCache,
4973
+ () => buildDataSchema(
4921
4974
  modelName,
4922
4975
  dataConfig,
4923
4976
  mode,
4924
4977
  typeMap,
4978
+ uniqueMap,
4979
+ enumMap,
4980
+ scalarBase,
4925
4981
  schemaBuilder,
4926
4982
  zodDefaults
4927
- );
4928
- dataSchemaCache.set(cacheKey, built);
4929
- return built;
4930
- }
4931
- return buildDataSchema(
4932
- modelName,
4933
- dataConfig,
4934
- mode,
4935
- typeMap,
4936
- schemaBuilder,
4937
- zodDefaults
4983
+ )
4938
4984
  );
4939
4985
  }
4940
4986
  function getWhereBuilt(whereConfig, matchedKey, wasDynamic) {
4941
- if (!wasDynamic) {
4942
- const cached = whereBuiltCache.get(matchedKey);
4943
- if (cached)
4944
- return cached;
4945
- const built = queryBuilder.buildWhereSchema(modelName, whereConfig);
4946
- whereBuiltCache.set(matchedKey, built);
4947
- return built;
4948
- }
4949
- return queryBuilder.buildWhereSchema(modelName, whereConfig);
4987
+ return memoize(
4988
+ whereBuiltCache,
4989
+ matchedKey,
4990
+ wasDynamic,
4991
+ () => queryBuilder.buildWhereSchema(modelName, whereConfig)
4992
+ );
4950
4993
  }
4951
4994
  function getUniqueWhereBuilt(whereConfig, matchedKey, wasDynamic) {
4952
- if (!wasDynamic) {
4953
- const cacheKey = `unique\0${matchedKey}`;
4954
- const cached = uniqueWhereCache.get(cacheKey);
4955
- if (cached)
4956
- return cached;
4957
- const built = queryBuilder.buildUniqueWhereSchema(
4958
- modelName,
4959
- whereConfig
4960
- );
4961
- uniqueWhereCache.set(cacheKey, built);
4962
- return built;
4963
- }
4964
- return queryBuilder.buildUniqueWhereSchema(modelName, whereConfig);
4995
+ return memoize(
4996
+ uniqueWhereCache,
4997
+ `unique\0${matchedKey}`,
4998
+ wasDynamic,
4999
+ () => queryBuilder.buildUniqueWhereSchema(modelName, whereConfig)
5000
+ );
4965
5001
  }
4966
5002
  function buildProjectionSchema(shape) {
4967
5003
  const schemaFields = {};
@@ -4988,7 +5024,7 @@ function createModelGuardExtension(config) {
4988
5024
  forcedSelectCountWhere = result.forcedCountWhere;
4989
5025
  }
4990
5026
  return {
4991
- zodSchema: import_zod9.z.object(schemaFields).strict(),
5027
+ zodSchema: import_zod11.z.object(schemaFields).strict(),
4992
5028
  forcedIncludeTree,
4993
5029
  forcedSelectTree,
4994
5030
  forcedIncludeCountWhere,
@@ -4996,16 +5032,12 @@ function createModelGuardExtension(config) {
4996
5032
  };
4997
5033
  }
4998
5034
  function getProjection(shape, matchedKey, wasDynamic) {
4999
- if (!wasDynamic) {
5000
- const cacheKey = `projection\0${matchedKey}`;
5001
- const cached = projectionCache.get(cacheKey);
5002
- if (cached)
5003
- return cached;
5004
- const built = buildProjectionSchema(shape);
5005
- projectionCache.set(cacheKey, built);
5006
- return built;
5007
- }
5008
- return buildProjectionSchema(shape);
5035
+ return memoize(
5036
+ projectionCache,
5037
+ `projection\0${matchedKey}`,
5038
+ wasDynamic,
5039
+ () => buildProjectionSchema(shape)
5040
+ );
5009
5041
  }
5010
5042
  function resolveProjection(shape, parsed, method, matchedKey, wasDynamic) {
5011
5043
  const hasBodyProjection = "select" in parsed || "include" in parsed;
@@ -5199,24 +5231,11 @@ function createModelGuardExtension(config) {
5199
5231
  const hasShapeProjection = !!resolved.shape.select || !!resolved.shape.include;
5200
5232
  if (!hasShapeProjection)
5201
5233
  return resolved.body;
5202
- const defaultProjection = buildDefaultProjectionBody(resolved.shape);
5203
5234
  const hasBodyProjection = "select" in resolved.body || "include" in resolved.body;
5204
- if (!hasBodyProjection) {
5205
- return { ...resolved.body, ...defaultProjection };
5206
- }
5207
- const merged = { ...resolved.body };
5208
- if ("select" in resolved.body && "select" in defaultProjection && isPlainObject(resolved.body.select) && isPlainObject(defaultProjection.select)) {
5209
- merged.select = applyClientProjectionOverrides(
5210
- defaultProjection.select,
5211
- resolved.body.select
5212
- );
5213
- } else if ("include" in resolved.body && "include" in defaultProjection && isPlainObject(resolved.body.include) && isPlainObject(defaultProjection.include)) {
5214
- merged.include = applyClientProjectionOverrides(
5215
- defaultProjection.include,
5216
- resolved.body.include
5217
- );
5218
- }
5219
- return merged;
5235
+ if (hasBodyProjection)
5236
+ return resolved.body;
5237
+ const defaultProjection = buildDefaultProjectionBody(resolved.shape);
5238
+ return { ...resolved.body, ...defaultProjection };
5220
5239
  }
5221
5240
  function makeReadMethod(method) {
5222
5241
  return (body) => {
@@ -5249,29 +5268,21 @@ function createModelGuardExtension(config) {
5249
5268
  function makeCreateMethod(method) {
5250
5269
  const isBatch = BATCH_CREATE_METHODS.has(method);
5251
5270
  const supportsProjection = PROJECTION_MUTATION_METHODS.has(method);
5252
- let allowedBodyKeys;
5253
- if (isBatch && supportsProjection) {
5254
- allowedBodyKeys = ALLOWED_BODY_KEYS_CREATE_MANY_PROJECTION;
5255
- } else if (isBatch) {
5256
- allowedBodyKeys = ALLOWED_BODY_KEYS_CREATE_MANY;
5257
- } else if (supportsProjection) {
5258
- allowedBodyKeys = ALLOWED_BODY_KEYS_CREATE_PROJECTION;
5259
- } else {
5260
- allowedBodyKeys = ALLOWED_BODY_KEYS_CREATE;
5261
- }
5262
- const allowedShapeKeys = supportsProjection ? VALID_SHAPE_KEYS_CREATE_PROJECTION : VALID_SHAPE_KEYS_CREATE;
5271
+ const allowedBodyKeys = getAllowedBodyKeys(method, supportsProjection);
5272
+ const allowedShapeKeys = getAllowedShapeKeys(method, supportsProjection);
5263
5273
  return (body) => {
5264
5274
  const caller = resolveCaller();
5265
5275
  const resolved = resolveShape(input, body, contextFn, caller);
5266
5276
  if (!resolved.shape.data) {
5267
5277
  throw new ShapeError(`Guard shape requires "data" for ${method}`);
5268
5278
  }
5269
- validateMutationShapeKeys(
5279
+ validateAllowedKeys(
5270
5280
  resolved.shape,
5271
5281
  allowedShapeKeys,
5272
- method
5282
+ method,
5283
+ "shape"
5273
5284
  );
5274
- validateMutationBodyKeys(resolved.body, allowedBodyKeys, method);
5285
+ validateAllowedKeys(resolved.body, allowedBodyKeys, method, "body");
5275
5286
  const fks = modelScopeFks.get(modelName) ?? /* @__PURE__ */ new Set();
5276
5287
  validateCreateCompleteness(
5277
5288
  modelName,
@@ -5330,20 +5341,21 @@ function createModelGuardExtension(config) {
5330
5341
  const isUniqueWhere = method === "update";
5331
5342
  const isBulk = BULK_MUTATION_METHODS.has(method);
5332
5343
  const supportsProjection = PROJECTION_MUTATION_METHODS.has(method);
5333
- const allowedBodyKeys = supportsProjection ? ALLOWED_BODY_KEYS_UPDATE_PROJECTION : ALLOWED_BODY_KEYS_UPDATE;
5334
- const allowedShapeKeys = supportsProjection ? VALID_SHAPE_KEYS_UPDATE_PROJECTION : VALID_SHAPE_KEYS_UPDATE;
5344
+ const allowedBodyKeys = getAllowedBodyKeys(method, supportsProjection);
5345
+ const allowedShapeKeys = getAllowedShapeKeys(method, supportsProjection);
5335
5346
  return (body) => {
5336
5347
  const caller = resolveCaller();
5337
5348
  const resolved = resolveShape(input, body, contextFn, caller);
5338
5349
  if (!resolved.shape.data) {
5339
5350
  throw new ShapeError(`Guard shape requires "data" for ${method}`);
5340
5351
  }
5341
- validateMutationShapeKeys(
5352
+ validateAllowedKeys(
5342
5353
  resolved.shape,
5343
5354
  allowedShapeKeys,
5344
- method
5355
+ method,
5356
+ "shape"
5345
5357
  );
5346
- validateMutationBodyKeys(resolved.body, allowedBodyKeys, method);
5358
+ validateAllowedKeys(resolved.body, allowedBodyKeys, method, "body");
5347
5359
  if (isBulk && !resolved.shape.where) {
5348
5360
  throw new ShapeError(
5349
5361
  `Guard shape requires "where" for ${method} to prevent unconstrained bulk mutations`
@@ -5411,20 +5423,21 @@ function createModelGuardExtension(config) {
5411
5423
  const isUniqueWhere = method === "delete";
5412
5424
  const isBulk = BULK_MUTATION_METHODS.has(method);
5413
5425
  const supportsProjection = PROJECTION_MUTATION_METHODS.has(method);
5414
- const allowedBodyKeys = supportsProjection ? ALLOWED_BODY_KEYS_DELETE_PROJECTION : ALLOWED_BODY_KEYS_DELETE;
5415
- const allowedShapeKeys = supportsProjection ? VALID_SHAPE_KEYS_DELETE_PROJECTION : VALID_SHAPE_KEYS_DELETE;
5426
+ const allowedBodyKeys = getAllowedBodyKeys(method, supportsProjection);
5427
+ const allowedShapeKeys = getAllowedShapeKeys(method, supportsProjection);
5416
5428
  return (body) => {
5417
5429
  const caller = resolveCaller();
5418
5430
  const resolved = resolveShape(input, body, contextFn, caller);
5419
5431
  if (resolved.shape.data) {
5420
5432
  throw new ShapeError(`Guard shape "data" is not valid for ${method}`);
5421
5433
  }
5422
- validateMutationShapeKeys(
5434
+ validateAllowedKeys(
5423
5435
  resolved.shape,
5424
5436
  allowedShapeKeys,
5425
- method
5437
+ method,
5438
+ "shape"
5426
5439
  );
5427
- validateMutationBodyKeys(resolved.body, allowedBodyKeys, method);
5440
+ validateAllowedKeys(resolved.body, allowedBodyKeys, method, "body");
5428
5441
  if (isBulk && !resolved.shape.where) {
5429
5442
  throw new ShapeError(
5430
5443
  `Guard shape requires "where" for ${method} to prevent unconstrained bulk mutations`
@@ -5477,6 +5490,8 @@ function createModelGuardExtension(config) {
5477
5490
  };
5478
5491
  }
5479
5492
  function makeUpsertMethod() {
5493
+ const allowedBodyKeys = getAllowedBodyKeys("upsert", true);
5494
+ const allowedShapeKeys = getAllowedShapeKeys("upsert", true);
5480
5495
  return (body) => {
5481
5496
  const caller = resolveCaller();
5482
5497
  const resolved = resolveShape(input, body, contextFn, caller);
@@ -5494,15 +5509,17 @@ function createModelGuardExtension(config) {
5494
5509
  if (!resolved.shape.where) {
5495
5510
  throw new ShapeError('Guard shape requires "where" for upsert');
5496
5511
  }
5497
- validateMutationShapeKeys(
5512
+ validateAllowedKeys(
5498
5513
  resolved.shape,
5499
- VALID_SHAPE_KEYS_UPSERT,
5500
- "upsert"
5514
+ allowedShapeKeys,
5515
+ "upsert",
5516
+ "shape"
5501
5517
  );
5502
- validateMutationBodyKeys(
5518
+ validateAllowedKeys(
5503
5519
  resolved.body,
5504
- ALLOWED_BODY_KEYS_UPSERT,
5505
- "upsert"
5520
+ allowedBodyKeys,
5521
+ "upsert",
5522
+ "body"
5506
5523
  );
5507
5524
  validateUniqueWhereShapeConfig(
5508
5525
  modelName,
@@ -5592,12 +5609,7 @@ function createModelGuardExtension(config) {
5592
5609
  try {
5593
5610
  return fn(body);
5594
5611
  } catch (err) {
5595
- if (err instanceof import_zod9.z.ZodError) {
5596
- throw new ShapeError(`Validation failed: ${formatZodError(err)}`, {
5597
- cause: err
5598
- });
5599
- }
5600
- throw err;
5612
+ throw toShapeError(err);
5601
5613
  }
5602
5614
  };
5603
5615
  }
@@ -5630,6 +5642,15 @@ function createModelGuardExtension(config) {
5630
5642
  }
5631
5643
 
5632
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
+ }
5633
5654
  function createGuard(config) {
5634
5655
  const scalarBase = createScalarBase(
5635
5656
  config.guardConfig.strictDecimal ?? false
@@ -5651,14 +5672,6 @@ function createGuard(config) {
5651
5672
  warn: (msg) => console.warn(msg)
5652
5673
  };
5653
5674
  const wrapZodErrors = config.wrapZodErrors ?? false;
5654
- function rethrowZod(err) {
5655
- if (err instanceof import_zod10.ZodError) {
5656
- throw new ShapeError(`Validation failed: ${formatZodError(err)}`, {
5657
- cause: err
5658
- });
5659
- }
5660
- throw err;
5661
- }
5662
5675
  return {
5663
5676
  input: (model, opts) => {
5664
5677
  const result = schemaBuilder.buildInputSchema(model, opts);
@@ -5666,13 +5679,7 @@ function createGuard(config) {
5666
5679
  return result;
5667
5680
  return {
5668
5681
  schema: result.schema,
5669
- parse(data) {
5670
- try {
5671
- return result.parse(data);
5672
- } catch (err) {
5673
- rethrowZod(err);
5674
- }
5675
- }
5682
+ parse: wrapParseFn(result.parse)
5676
5683
  };
5677
5684
  },
5678
5685
  model: (model, opts) => schemaBuilder.buildModelSchema(model, opts),
@@ -5682,13 +5689,7 @@ function createGuard(config) {
5682
5689
  return qs;
5683
5690
  return {
5684
5691
  schemas: qs.schemas,
5685
- parse(body, opts) {
5686
- try {
5687
- return qs.parse(body, opts);
5688
- } catch (err) {
5689
- rethrowZod(err);
5690
- }
5691
- }
5692
+ parse: wrapParseFn(qs.parse)
5692
5693
  };
5693
5694
  },
5694
5695
  extension: (contextFn) => {