prisma-guard 1.2.0 → 1.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -33,12 +33,6 @@ function formatZodError(err) {
33
33
  }).join("; ");
34
34
  }
35
35
 
36
- // src/runtime/schema-builder.ts
37
- import { z as z3 } from "zod";
38
-
39
- // src/runtime/zod-type-map.ts
40
- import { z as z2 } from "zod";
41
-
42
36
  // src/shared/scalar-base.ts
43
37
  import { z } from "zod";
44
38
  function isJsonSafe(value) {
@@ -89,43 +83,54 @@ function isJsonSafe(value) {
89
83
  }
90
84
  return true;
91
85
  }
92
- var SCALAR_BASE = {
93
- String: () => z.string(),
94
- Int: () => z.number().int(),
95
- Float: () => z.number(),
96
- Decimal: () => z.union([
97
- z.number(),
98
- z.string().refine(
99
- (s) => /^-?(\d+\.?\d*|\.\d+)([eE]-?\d+)?$/.test(s),
100
- "Invalid decimal string"
101
- ),
102
- z.custom(
103
- (v) => v !== null && typeof v === "object" && typeof v.toFixed === "function" && typeof v.toNumber === "function",
104
- "Expected Decimal-compatible object"
105
- )
106
- ]),
107
- BigInt: () => z.union([
108
- z.bigint(),
109
- z.number().int().refine(
110
- (v) => v >= Number.MIN_SAFE_INTEGER && v <= Number.MAX_SAFE_INTEGER,
111
- "Number exceeds safe integer range for BigInt conversion"
112
- ).transform((v) => BigInt(v)),
113
- z.string().regex(/^-?\d+$/).transform((v) => BigInt(v))
114
- ]),
115
- Boolean: () => z.boolean(),
116
- DateTime: () => z.union([
117
- z.date(),
118
- z.string().datetime({ offset: true }),
119
- z.string().datetime()
120
- ]).pipe(z.coerce.date()),
121
- Json: () => z.unknown().refine(isJsonSafe, "Value must be JSON-serializable (no undefined, functions, symbols, class instances, NaN, Infinity, or circular references)"),
122
- Bytes: () => z.union([
123
- z.string(),
124
- z.custom((v) => v instanceof Uint8Array)
125
- ])
126
- };
86
+ var DECIMAL_REGEX = /^-?(\d+\.?\d*|\.\d+)([eE]-?\d+)?$/;
87
+ var decimalStringSchema = z.string().refine(
88
+ (s) => DECIMAL_REGEX.test(s),
89
+ "Invalid decimal string"
90
+ );
91
+ var decimalObjectSchema = z.custom(
92
+ (v) => v !== null && typeof v === "object" && typeof v.toFixed === "function" && typeof v.toNumber === "function",
93
+ "Expected Decimal-compatible object"
94
+ );
95
+ function createDecimalFactory(strict) {
96
+ if (strict) {
97
+ return () => z.union([decimalStringSchema, decimalObjectSchema]);
98
+ }
99
+ return () => z.union([z.number(), decimalStringSchema, decimalObjectSchema]);
100
+ }
101
+ function createScalarBase(strictDecimal) {
102
+ return {
103
+ String: () => z.string(),
104
+ Int: () => z.number().int(),
105
+ Float: () => z.number(),
106
+ Decimal: createDecimalFactory(strictDecimal),
107
+ BigInt: () => z.union([
108
+ z.bigint(),
109
+ z.number().int().refine(
110
+ (v) => v >= Number.MIN_SAFE_INTEGER && v <= Number.MAX_SAFE_INTEGER,
111
+ "Number exceeds safe integer range for BigInt conversion"
112
+ ).transform((v) => BigInt(v)),
113
+ z.string().regex(/^-?\d+$/).transform((v) => BigInt(v))
114
+ ]),
115
+ Boolean: () => z.boolean(),
116
+ DateTime: () => z.union([
117
+ z.date(),
118
+ z.string().datetime({ offset: true })
119
+ ]).pipe(z.coerce.date()),
120
+ Json: () => z.unknown().refine(isJsonSafe, "Value must be JSON-serializable (no undefined, functions, symbols, class instances, NaN, Infinity, or circular references)"),
121
+ Bytes: () => z.union([
122
+ z.string(),
123
+ z.custom((v) => v instanceof Uint8Array)
124
+ ])
125
+ };
126
+ }
127
+ var SCALAR_BASE = createScalarBase(false);
128
+
129
+ // src/runtime/schema-builder.ts
130
+ import { z as z3 } from "zod";
127
131
 
128
132
  // src/runtime/zod-type-map.ts
133
+ import { z as z2 } from "zod";
129
134
  var SCALAR_OPERATORS = {
130
135
  String: /* @__PURE__ */ new Set(["equals", "not", "contains", "startsWith", "endsWith", "in", "notIn"]),
131
136
  Int: /* @__PURE__ */ new Set(["equals", "not", "gt", "gte", "lt", "lte", "in", "notIn"]),
@@ -150,7 +155,7 @@ function getSupportedOperators(fieldMeta) {
150
155
  return [];
151
156
  return [...ops];
152
157
  }
153
- function createBaseType(fieldMeta, enumMap) {
158
+ function createBaseType(fieldMeta, enumMap, scalarBase) {
154
159
  let base;
155
160
  if (fieldMeta.isEnum) {
156
161
  const values = enumMap[fieldMeta.type];
@@ -159,7 +164,7 @@ function createBaseType(fieldMeta, enumMap) {
159
164
  }
160
165
  base = z2.enum(values);
161
166
  } else {
162
- const factory = SCALAR_BASE[fieldMeta.type];
167
+ const factory = scalarBase[fieldMeta.type];
163
168
  if (!factory) {
164
169
  throw new ShapeError(`Unknown scalar type: ${fieldMeta.type}`);
165
170
  }
@@ -170,7 +175,7 @@ function createBaseType(fieldMeta, enumMap) {
170
175
  }
171
176
  return base;
172
177
  }
173
- function createScalarListOperatorSchema(fieldMeta, operator, enumMap) {
178
+ function createScalarListOperatorSchema(fieldMeta, operator, enumMap, scalarBase) {
174
179
  if (!SCALAR_LIST_OPERATORS.has(operator)) {
175
180
  throw new ShapeError(`Operator "${operator}" not supported for scalar list fields`);
176
181
  }
@@ -179,19 +184,19 @@ function createScalarListOperatorSchema(fieldMeta, operator, enumMap) {
179
184
  }
180
185
  if (operator === "equals") {
181
186
  const itemMeta2 = { ...fieldMeta, isList: false };
182
- const itemBase2 = createBaseType(itemMeta2, enumMap);
187
+ const itemBase2 = createBaseType(itemMeta2, enumMap, scalarBase);
183
188
  return fieldMeta.isRequired ? z2.array(itemBase2) : z2.union([z2.array(itemBase2), z2.null()]);
184
189
  }
185
190
  const itemMeta = { ...fieldMeta, isList: false };
186
- const itemBase = createBaseType(itemMeta, enumMap);
191
+ const itemBase = createBaseType(itemMeta, enumMap, scalarBase);
187
192
  if (operator === "has") {
188
193
  return !fieldMeta.isRequired ? z2.union([itemBase, z2.null()]) : itemBase;
189
194
  }
190
195
  return z2.array(itemBase);
191
196
  }
192
- function createOperatorSchema(fieldMeta, operator, enumMap) {
197
+ function createOperatorSchema(fieldMeta, operator, enumMap, scalarBase) {
193
198
  if (fieldMeta.isList) {
194
- return createScalarListOperatorSchema(fieldMeta, operator, enumMap);
199
+ return createScalarListOperatorSchema(fieldMeta, operator, enumMap, scalarBase);
195
200
  }
196
201
  if (fieldMeta.isEnum) {
197
202
  const values = enumMap[fieldMeta.type];
@@ -220,7 +225,7 @@ function createOperatorSchema(fieldMeta, operator, enumMap) {
220
225
  if (!supportedOps.has(operator)) {
221
226
  throw new ShapeError(`Operator "${operator}" not supported for type "${fieldMeta.type}"`);
222
227
  }
223
- const factory = SCALAR_BASE[fieldMeta.type];
228
+ const factory = scalarBase[fieldMeta.type];
224
229
  if (!factory) {
225
230
  throw new ShapeError(`Unknown scalar type: ${fieldMeta.type}`);
226
231
  }
@@ -237,6 +242,24 @@ function createOperatorSchema(fieldMeta, operator, enumMap) {
237
242
  return scalar;
238
243
  }
239
244
 
245
+ // src/shared/utils.ts
246
+ function isPlainObject(v) {
247
+ if (typeof v !== "object" || v === null || Array.isArray(v))
248
+ return false;
249
+ const proto = Object.getPrototypeOf(v);
250
+ return proto === Object.prototype || proto === null;
251
+ }
252
+ function schemaProducesValueForUndefined(schema) {
253
+ const result = schema.safeParse(void 0);
254
+ return result.success && result.data !== void 0;
255
+ }
256
+ function isZodSchema(value) {
257
+ if (value == null || typeof value !== "object")
258
+ return false;
259
+ const v = value;
260
+ return typeof v.parse === "function" && typeof v.optional === "function";
261
+ }
262
+
240
263
  // src/runtime/schema-builder.ts
241
264
  var DEFAULT_MAX_CACHE = 500;
242
265
  var DEFAULT_MAX_DEPTH = 5;
@@ -258,13 +281,7 @@ function lruSet(cache, key, value, maxSize) {
258
281
  cache.delete(oldest);
259
282
  }
260
283
  }
261
- function isZodSchema(value) {
262
- if (value == null || typeof value !== "object")
263
- return false;
264
- const v = value;
265
- return typeof v.parse === "function" && typeof v.optional === "function";
266
- }
267
- function createSchemaBuilder(typeMap, zodChains, enumMap) {
284
+ function createSchemaBuilder(typeMap, zodChains, enumMap, scalarBase, zodDefaults) {
268
285
  const chainCache = /* @__PURE__ */ new Map();
269
286
  function buildFieldSchema(model, field) {
270
287
  const cacheKey = `${model}.${field}`;
@@ -277,7 +294,7 @@ function createSchemaBuilder(typeMap, zodChains, enumMap) {
277
294
  const fieldMeta = modelFields[field];
278
295
  if (!fieldMeta)
279
296
  throw new ShapeError(`Unknown field "${field}" on model "${model}"`);
280
- const base = createBaseType(fieldMeta, enumMap);
297
+ const base = createBaseType(fieldMeta, enumMap, scalarBase);
281
298
  let result = base;
282
299
  const chainFn = zodChains[model]?.[field];
283
300
  if (chainFn) {
@@ -300,7 +317,7 @@ function createSchemaBuilder(typeMap, zodChains, enumMap) {
300
317
  const fieldMeta = modelFields[field];
301
318
  if (!fieldMeta)
302
319
  throw new ShapeError(`Unknown field "${field}" on model "${model}"`);
303
- return createBaseType(fieldMeta, enumMap);
320
+ return createBaseType(fieldMeta, enumMap, scalarBase);
304
321
  }
305
322
  function buildInputSchema(model, opts) {
306
323
  if (opts.pick && opts.omit) {
@@ -311,6 +328,8 @@ function createSchemaBuilder(typeMap, zodChains, enumMap) {
311
328
  const modelFields = typeMap[model];
312
329
  if (!modelFields)
313
330
  throw new ShapeError(`Unknown model: ${model}`);
331
+ const zodDefaultFields = zodDefaults[model];
332
+ const zodDefaultSet = zodDefaultFields ? new Set(zodDefaultFields) : void 0;
314
333
  let fieldNames = Object.keys(modelFields).filter((name) => {
315
334
  const meta = modelFields[name];
316
335
  return !meta.isRelation && !meta.isUpdatedAt;
@@ -336,6 +355,7 @@ function createSchemaBuilder(typeMap, zodChains, enumMap) {
336
355
  for (const name of fieldNames) {
337
356
  const fieldMeta = modelFields[name];
338
357
  let fieldSchema;
358
+ let handlesUndefined;
339
359
  if (opts.refine?.[name]) {
340
360
  let refined;
341
361
  try {
@@ -352,14 +372,22 @@ function createSchemaBuilder(typeMap, zodChains, enumMap) {
352
372
  );
353
373
  }
354
374
  fieldSchema = refined;
375
+ handlesUndefined = schemaProducesValueForUndefined(fieldSchema);
355
376
  } else {
356
377
  fieldSchema = buildFieldSchema(model, name);
378
+ handlesUndefined = zodDefaultSet !== void 0 && zodDefaultSet.has(name);
357
379
  }
358
380
  if (mode === "create") {
359
381
  if (!fieldMeta.isRequired) {
360
- fieldSchema = allowNull ? fieldSchema.nullable().optional() : fieldSchema.optional();
382
+ if (handlesUndefined) {
383
+ fieldSchema = allowNull ? fieldSchema.nullable() : fieldSchema;
384
+ } else {
385
+ fieldSchema = allowNull ? fieldSchema.nullable().optional() : fieldSchema.optional();
386
+ }
361
387
  } else if (fieldMeta.hasDefault) {
362
- fieldSchema = fieldSchema.optional();
388
+ if (!handlesUndefined) {
389
+ fieldSchema = fieldSchema.optional();
390
+ }
363
391
  }
364
392
  } else {
365
393
  if (!fieldMeta.isRequired && allowNull) {
@@ -420,7 +448,7 @@ function createSchemaBuilder(typeMap, zodChains, enumMap) {
420
448
  const schemaMap = {};
421
449
  for (const name of scalarNames) {
422
450
  const fieldMeta = modelFields[name];
423
- let fieldSchema = createBaseType(fieldMeta, enumMap);
451
+ let fieldSchema = createBaseType(fieldMeta, enumMap, scalarBase);
424
452
  if (!fieldMeta.isRequired) {
425
453
  fieldSchema = fieldSchema.nullable();
426
454
  }
@@ -505,6 +533,8 @@ var SHAPE_CONFIG_KEYS = /* @__PURE__ */ new Set([
505
533
  ]);
506
534
  var GUARD_SHAPE_KEYS = /* @__PURE__ */ new Set([
507
535
  "data",
536
+ "create",
537
+ "update",
508
538
  ...SHAPE_CONFIG_KEYS
509
539
  ]);
510
540
  var COMBINATOR_KEYS = /* @__PURE__ */ new Set(["AND", "OR", "NOT"]);
@@ -514,6 +544,15 @@ var ALL_RELATION_OPS = /* @__PURE__ */ new Set([...TO_MANY_RELATION_OPS, ...TO_O
514
544
  function toDelegateKey(modelName) {
515
545
  return modelName[0].toLowerCase() + modelName.slice(1);
516
546
  }
547
+ var FORCED_MARKER = Symbol.for("prisma-guard.forced");
548
+ function isForcedValue(v) {
549
+ return v !== null && typeof v === "object" && v[FORCED_MARKER] === true;
550
+ }
551
+ function force(value) {
552
+ const wrapper = { value };
553
+ wrapper[FORCED_MARKER] = true;
554
+ return wrapper;
555
+ }
517
556
 
518
557
  // src/shared/match-caller.ts
519
558
  function matchCallerPattern(patterns, caller) {
@@ -549,14 +588,6 @@ function matchCallerPattern(patterns, caller) {
549
588
  return matches[0];
550
589
  }
551
590
 
552
- // src/shared/is-plain-object.ts
553
- function isPlainObject(v) {
554
- if (typeof v !== "object" || v === null || Array.isArray(v))
555
- return false;
556
- const proto = Object.getPrototypeOf(v);
557
- return proto === Object.prototype || proto === null;
558
- }
559
-
560
591
  // src/runtime/policy.ts
561
592
  function requireContext(ctx, label) {
562
593
  if (ctx === void 0 || ctx === null) {
@@ -580,6 +611,37 @@ function validateContext(ctx) {
580
611
  // src/runtime/query-builder-where.ts
581
612
  import { z as z4 } from "zod";
582
613
 
614
+ // src/shared/deep-clone.ts
615
+ function deepClone(value) {
616
+ if (value === null || value === void 0)
617
+ return value;
618
+ switch (typeof value) {
619
+ case "string":
620
+ case "number":
621
+ case "boolean":
622
+ case "bigint":
623
+ return value;
624
+ case "object": {
625
+ if (value instanceof Date)
626
+ return new Date(value.getTime());
627
+ if (value instanceof Uint8Array)
628
+ return value.slice();
629
+ if (Array.isArray(value))
630
+ return value.map(deepClone);
631
+ const proto = Object.getPrototypeOf(value);
632
+ if (proto !== Object.prototype && proto !== null)
633
+ return value;
634
+ const result = {};
635
+ for (const [k, v] of Object.entries(value)) {
636
+ result[k] = deepClone(v);
637
+ }
638
+ return result;
639
+ }
640
+ default:
641
+ return value;
642
+ }
643
+ }
644
+
583
645
  // src/runtime/query-builder-forced.ts
584
646
  var EMPTY_WHERE_FORCED = { conditions: {}, relations: {} };
585
647
  function hasWhereForced(f) {
@@ -588,7 +650,7 @@ function hasWhereForced(f) {
588
650
  function mergeWhereForced(where, forced) {
589
651
  if (!hasWhereForced(forced))
590
652
  return where ?? {};
591
- let result = where ? structuredClone(where) : {};
653
+ let result = where ? deepClone(where) : {};
592
654
  for (const [relName, opMap] of Object.entries(forced.relations)) {
593
655
  if (!result[relName] || typeof result[relName] !== "object") {
594
656
  result[relName] = {};
@@ -602,7 +664,7 @@ function mergeWhereForced(where, forced) {
602
664
  }
603
665
  }
604
666
  if (Object.keys(forced.conditions).length > 0) {
605
- const scalarClone = structuredClone(forced.conditions);
667
+ const scalarClone = deepClone(forced.conditions);
606
668
  if (Object.keys(result).length === 0) {
607
669
  result = scalarClone;
608
670
  } else {
@@ -628,7 +690,7 @@ function mergeUniqueWhereForced(where, forced) {
628
690
  }
629
691
  }
630
692
  if (Object.keys(forced.conditions).length > 0) {
631
- const conditions = [structuredClone(forced.conditions)];
693
+ const conditions = [deepClone(forced.conditions)];
632
694
  const existing = result.AND;
633
695
  if (existing) {
634
696
  if (Array.isArray(existing)) {
@@ -670,6 +732,13 @@ function applyBuiltShape(built, body, isUniqueMethod) {
670
732
  }
671
733
  return validated;
672
734
  }
735
+ function buildCountForPlacement(countWhere) {
736
+ const countSelect = {};
737
+ for (const [countRel, countForced] of Object.entries(countWhere)) {
738
+ countSelect[countRel] = { where: mergeWhereForced(void 0, countForced) };
739
+ }
740
+ return { _count: { select: countSelect } };
741
+ }
673
742
  function applyForcedTree(validated, key, tree) {
674
743
  const container = validated[key];
675
744
  if (!container)
@@ -692,11 +761,11 @@ function applyForcedTree(validated, key, tree) {
692
761
  applyForcedTree(expanded, "select", forced.select);
693
762
  }
694
763
  if (forced._countWhere && Object.keys(forced._countWhere).length > 0) {
695
- const countSelect = {};
696
- for (const [countRel, countForced] of Object.entries(forced._countWhere)) {
697
- countSelect[countRel] = { where: mergeWhereForced(void 0, countForced) };
698
- }
699
- expanded._count = { select: countSelect };
764
+ const placement = forced._countWherePlacement ?? "include";
765
+ if (!expanded[placement])
766
+ expanded[placement] = {};
767
+ const placementObj = expanded[placement];
768
+ Object.assign(placementObj, buildCountForPlacement(forced._countWhere));
700
769
  }
701
770
  if (expanded.include && expanded.select) {
702
771
  throw new ShapeError(
@@ -725,7 +794,11 @@ function applyForcedTree(validated, key, tree) {
725
794
  applyForcedTree(relObj, "select", forced.select);
726
795
  }
727
796
  if (forced._countWhere && Object.keys(forced._countWhere).length > 0) {
728
- applyForcedCountWhere(relObj, forced._countWhere);
797
+ const placement = forced._countWherePlacement ?? "include";
798
+ const projContainer = relObj[placement];
799
+ if (projContainer) {
800
+ applyForcedCountWhere(projContainer, forced._countWhere);
801
+ }
729
802
  }
730
803
  if (relObj.include && relObj.select) {
731
804
  throw new ShapeError(
@@ -747,11 +820,11 @@ function buildForcedOnlyContainer(tree) {
747
820
  if (forced.select)
748
821
  nested.select = buildForcedOnlyContainer(forced.select);
749
822
  if (forced._countWhere && Object.keys(forced._countWhere).length > 0) {
750
- const countSelect = {};
751
- for (const [countRel, countForced] of Object.entries(forced._countWhere)) {
752
- countSelect[countRel] = { where: mergeWhereForced(void 0, countForced) };
753
- }
754
- nested._count = { select: countSelect };
823
+ const placement = forced._countWherePlacement ?? "include";
824
+ if (!nested[placement])
825
+ nested[placement] = {};
826
+ const placementObj = nested[placement];
827
+ Object.assign(placementObj, buildCountForPlacement(forced._countWhere));
755
828
  }
756
829
  result[relName] = Object.keys(nested).length > 0 ? nested : true;
757
830
  }
@@ -813,29 +886,38 @@ function validateResolvedUniqueWhere(model, where, method, uniqueMap) {
813
886
  );
814
887
  }
815
888
  }
816
- function validateUniqueEquality(model, where, method, uniqueMap, typeMap) {
817
- const constraints = uniqueMap[model];
818
- if (!constraints || constraints.length === 0)
819
- return;
889
+ function collectEqualityFields(where, model, typeMap) {
820
890
  const combinators = /* @__PURE__ */ new Set(["AND", "OR", "NOT"]);
821
- const whereFields = /* @__PURE__ */ new Set();
822
- for (const key of Object.keys(where)) {
891
+ const fields = /* @__PURE__ */ new Set();
892
+ for (const [key, value] of Object.entries(where)) {
893
+ if (key === "AND") {
894
+ if (isPlainObject(value)) {
895
+ for (const f of collectEqualityFields(value, model, typeMap)) {
896
+ fields.add(f);
897
+ }
898
+ }
899
+ continue;
900
+ }
823
901
  if (combinators.has(key))
824
902
  continue;
825
- if (typeMap && typeMap[model]?.[key]?.isRelation)
903
+ if (typeMap && model && typeMap[model]?.[key]?.isRelation)
904
+ continue;
905
+ if (!value || !isPlainObject(value))
826
906
  continue;
827
- whereFields.add(key);
907
+ if (Object.keys(value).every((op) => op === "equals")) {
908
+ fields.add(key);
909
+ }
828
910
  }
829
- const valid = constraints.some((constraint) => {
830
- if (!constraint.every((field) => whereFields.has(field)))
831
- return false;
832
- return constraint.every((field) => {
833
- const ops = where[field];
834
- if (!ops || !isPlainObject(ops))
835
- return false;
836
- return Object.keys(ops).every((op) => op === "equals");
837
- });
838
- });
911
+ return fields;
912
+ }
913
+ function validateUniqueEquality(model, where, method, uniqueMap, typeMap) {
914
+ const constraints = uniqueMap[model];
915
+ if (!constraints || constraints.length === 0)
916
+ return;
917
+ const equalityFields = collectEqualityFields(where, model, typeMap);
918
+ const valid = constraints.some(
919
+ (constraint) => constraint.every((field) => equalityFields.has(field))
920
+ );
839
921
  if (!valid) {
840
922
  const constraintDesc = constraints.map((c) => `(${c.join(", ")})`).join(" | ");
841
923
  throw new ShapeError(
@@ -847,6 +929,7 @@ function validateUniqueEquality(model, where, method, uniqueMap, typeMap) {
847
929
  // src/runtime/query-builder-where.ts
848
930
  var UNSUPPORTED_WHERE_TYPES = /* @__PURE__ */ new Set(["Json", "Bytes"]);
849
931
  var STRING_MODE_OPS = /* @__PURE__ */ new Set(["contains", "startsWith", "endsWith", "equals"]);
932
+ var MAX_WHERE_DEPTH = 10;
850
933
  function safeStringify(v) {
851
934
  if (typeof v === "bigint")
852
935
  return `${v}n`;
@@ -937,8 +1020,14 @@ function mergeRelationForcedMaps(target, source) {
937
1020
  }
938
1021
  }
939
1022
  }
940
- function createWhereBuilder(typeMap, enumMap) {
941
- function buildWhereSchema(model, whereConfig) {
1023
+ function createWhereBuilder(typeMap, enumMap, scalarBase) {
1024
+ function buildWhereSchema(model, whereConfig, depth) {
1025
+ const currentDepth = depth ?? 0;
1026
+ if (currentDepth > MAX_WHERE_DEPTH) {
1027
+ throw new ShapeError(
1028
+ `Where schema for model "${model}" exceeds maximum nesting depth (${MAX_WHERE_DEPTH}). Check for circular relation references in the shape.`
1029
+ );
1030
+ }
942
1031
  const modelFields = typeMap[model];
943
1032
  if (!modelFields)
944
1033
  throw new ShapeError(`Unknown model: ${model}`);
@@ -953,7 +1042,8 @@ function createWhereBuilder(typeMap, enumMap) {
953
1042
  model,
954
1043
  fieldSchemas,
955
1044
  scalarConditions,
956
- relationForced
1045
+ relationForced,
1046
+ currentDepth
957
1047
  );
958
1048
  continue;
959
1049
  }
@@ -965,8 +1055,10 @@ function createWhereBuilder(typeMap, enumMap) {
965
1055
  key,
966
1056
  value,
967
1057
  fieldMeta,
1058
+ model,
968
1059
  fieldSchemas,
969
- relationForced
1060
+ relationForced,
1061
+ currentDepth
970
1062
  );
971
1063
  continue;
972
1064
  }
@@ -986,16 +1078,28 @@ function createWhereBuilder(typeMap, enumMap) {
986
1078
  }
987
1079
  };
988
1080
  }
989
- function processCombinator(key, value, model, fieldSchemas, parentConditions, parentRelations) {
1081
+ function processCombinator(key, value, model, fieldSchemas, parentConditions, parentRelations, depth) {
990
1082
  if (!isPlainObject(value)) {
991
1083
  throw new ShapeError(`"${key}" in where shape must be an object defining allowed fields`);
992
1084
  }
993
- const result = buildWhereSchema(model, value);
1085
+ const result = buildWhereSchema(model, value, depth + 1);
1086
+ if (!result.schema && !hasWhereForced(result.forced)) {
1087
+ throw new ShapeError(
1088
+ `Empty "${key}" combinator in where shape for model "${model}". Define at least one field.`
1089
+ );
1090
+ }
994
1091
  if (result.schema) {
1092
+ let elementSchema = result.schema;
1093
+ if (!hasWhereForced(result.forced)) {
1094
+ elementSchema = result.schema.refine(
1095
+ (v) => v !== void 0 && v !== null && Object.keys(v).some((k) => v[k] !== void 0),
1096
+ { message: `"${key}" member must specify at least one condition` }
1097
+ );
1098
+ }
995
1099
  if (key === "NOT") {
996
- fieldSchemas[key] = z4.union([result.schema, z4.array(result.schema)]).optional();
1100
+ fieldSchemas[key] = z4.union([elementSchema, z4.array(elementSchema).min(1)]).optional();
997
1101
  } else {
998
- fieldSchemas[key] = z4.array(result.schema).optional();
1102
+ fieldSchemas[key] = z4.array(elementSchema).min(1).optional();
999
1103
  }
1000
1104
  }
1001
1105
  if (hasWhereForced(result.forced)) {
@@ -1015,11 +1119,16 @@ function createWhereBuilder(typeMap, enumMap) {
1015
1119
  }
1016
1120
  }
1017
1121
  }
1018
- function processRelationFilter(key, value, fieldMeta, fieldSchemas, parentRelations) {
1122
+ function processRelationFilter(key, value, fieldMeta, model, fieldSchemas, parentRelations, depth) {
1019
1123
  if (!isPlainObject(value)) {
1020
1124
  throw new ShapeError(`Relation filter for "${key}" must be an object with operators (some, every, none, is, isNot)`);
1021
1125
  }
1022
1126
  const allowedOps = fieldMeta.isList ? TO_MANY_RELATION_OPS : TO_ONE_RELATION_OPS;
1127
+ if (Object.keys(value).length === 0) {
1128
+ throw new ShapeError(
1129
+ `Empty relation filter for "${key}" on model "${model}". Define at least one operator: ${[...allowedOps].join(", ")}`
1130
+ );
1131
+ }
1023
1132
  const opSchemas = {};
1024
1133
  const opForced = {};
1025
1134
  let hasClientOps = false;
@@ -1035,7 +1144,12 @@ function createWhereBuilder(typeMap, enumMap) {
1035
1144
  `Relation filter operator "${op}" on "${key}" must be an object defining nested where fields`
1036
1145
  );
1037
1146
  }
1038
- const nested = buildWhereSchema(fieldMeta.type, opValue);
1147
+ const nested = buildWhereSchema(fieldMeta.type, opValue, depth + 1);
1148
+ if (!nested.schema && !hasWhereForced(nested.forced)) {
1149
+ throw new ShapeError(
1150
+ `Empty nested where for relation "${key}.${op}" on model "${model}". Define at least one field.`
1151
+ );
1152
+ }
1039
1153
  if (nested.schema) {
1040
1154
  if (!hasWhereForced(nested.forced)) {
1041
1155
  opSchemas[op] = nested.schema.refine(
@@ -1051,6 +1165,11 @@ function createWhereBuilder(typeMap, enumMap) {
1051
1165
  opForced[op] = nested.forced;
1052
1166
  }
1053
1167
  }
1168
+ if (!hasClientOps && Object.keys(opForced).length === 0) {
1169
+ throw new ShapeError(
1170
+ `Relation filter for "${key}" on model "${model}" produced no conditions. Define at least one nested field in the operator shape.`
1171
+ );
1172
+ }
1054
1173
  if (hasClientOps) {
1055
1174
  const clientOpKeys = Object.keys(opSchemas);
1056
1175
  const opObjSchema = z4.object(opSchemas).strict();
@@ -1080,17 +1199,18 @@ function createWhereBuilder(typeMap, enumMap) {
1080
1199
  const clientOpKeys = [];
1081
1200
  for (const [op, opValue] of Object.entries(operators)) {
1082
1201
  if (opValue === true) {
1083
- opSchemas[op] = createOperatorSchema(fieldMeta, op, enumMap).optional();
1202
+ opSchemas[op] = createOperatorSchema(fieldMeta, op, enumMap, scalarBase).optional();
1084
1203
  hasClientOps = true;
1085
1204
  clientOpKeys.push(op);
1086
1205
  if (fieldMeta.type === "String" && !fieldMeta.isList && STRING_MODE_OPS.has(op)) {
1087
1206
  hasStringModeOp = true;
1088
1207
  }
1089
1208
  } else {
1090
- const opSchema = createOperatorSchema(fieldMeta, op, enumMap);
1209
+ const actualOpValue = isForcedValue(opValue) ? opValue.value : opValue;
1210
+ const opSchema = createOperatorSchema(fieldMeta, op, enumMap, scalarBase);
1091
1211
  let parsed;
1092
1212
  try {
1093
- parsed = opSchema.parse(opValue);
1213
+ parsed = opSchema.parse(actualOpValue);
1094
1214
  } catch (err) {
1095
1215
  throw new ShapeError(
1096
1216
  `Invalid forced value for "${model}.${fieldName}.${op}": ${err.message}`
@@ -1124,11 +1244,21 @@ function createWhereBuilder(typeMap, enumMap) {
1124
1244
  // src/runtime/query-builder-args.ts
1125
1245
  import { z as z5 } from "zod";
1126
1246
  var UNSUPPORTED_BY_TYPES = /* @__PURE__ */ new Set(["Json", "Bytes"]);
1127
- function createArgsBuilder(typeMap, enumMap, uniqueMap) {
1247
+ function requireConfigTrue(config, context) {
1248
+ for (const [key, value] of Object.entries(config)) {
1249
+ if (value !== true) {
1250
+ throw new ShapeError(
1251
+ `Config value for "${key}" in ${context} must be true, got ${typeof value}`
1252
+ );
1253
+ }
1254
+ }
1255
+ }
1256
+ function createArgsBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
1128
1257
  function buildOrderBySchema(model, orderByConfig) {
1129
1258
  const modelFields = typeMap[model];
1130
1259
  if (!modelFields)
1131
1260
  throw new ShapeError(`Unknown model: ${model}`);
1261
+ requireConfigTrue(orderByConfig, `orderBy on model "${model}"`);
1132
1262
  const fieldSchemas = {};
1133
1263
  for (const fieldName of Object.keys(orderByConfig)) {
1134
1264
  const fieldMeta = modelFields[fieldName];
@@ -1174,16 +1304,17 @@ function createArgsBuilder(typeMap, enumMap, uniqueMap) {
1174
1304
  const modelFields = typeMap[model];
1175
1305
  if (!modelFields)
1176
1306
  throw new ShapeError(`Unknown model: ${model}`);
1307
+ requireConfigTrue(cursorConfig, `cursor on model "${model}"`);
1177
1308
  const cursorFields = new Set(Object.keys(cursorConfig));
1178
1309
  const constraints = uniqueMap[model];
1179
1310
  if (constraints && constraints.length > 0) {
1180
1311
  const covered = constraints.some(
1181
- (constraint) => constraint.every((field) => cursorFields.has(field))
1312
+ (constraint) => constraint.length === cursorFields.size && constraint.every((field) => cursorFields.has(field))
1182
1313
  );
1183
1314
  if (!covered) {
1184
1315
  const constraintDesc = constraints.map((c) => `(${c.join(", ")})`).join(" | ");
1185
1316
  throw new ShapeError(
1186
- `cursor on model "${model}" must cover a unique constraint: ${constraintDesc}`
1317
+ `cursor on model "${model}" must exactly match a unique constraint: ${constraintDesc}`
1187
1318
  );
1188
1319
  }
1189
1320
  }
@@ -1196,7 +1327,7 @@ function createArgsBuilder(typeMap, enumMap, uniqueMap) {
1196
1327
  throw new ShapeError(`Relation field "${fieldName}" cannot be used in cursor`);
1197
1328
  if (fieldMeta.isList)
1198
1329
  throw new ShapeError(`List field "${fieldName}" cannot be used in cursor`);
1199
- fieldSchemas[fieldName] = createBaseType(fieldMeta, enumMap);
1330
+ fieldSchemas[fieldName] = createBaseType(fieldMeta, enumMap, scalarBase);
1200
1331
  }
1201
1332
  return z5.object(fieldSchemas).strict().optional();
1202
1333
  }
@@ -1245,6 +1376,7 @@ function createArgsBuilder(typeMap, enumMap, uniqueMap) {
1245
1376
  const modelFields = typeMap[model];
1246
1377
  if (!modelFields)
1247
1378
  throw new ShapeError(`Unknown model: ${model}`);
1379
+ requireConfigTrue(havingConfig, `having on model "${model}"`);
1248
1380
  const fieldSchemas = {};
1249
1381
  for (const fieldName of Object.keys(havingConfig)) {
1250
1382
  const fieldMeta = modelFields[fieldName];
@@ -1261,7 +1393,7 @@ function createArgsBuilder(typeMap, enumMap, uniqueMap) {
1261
1393
  const opSchemas = {};
1262
1394
  const opKeys = [];
1263
1395
  for (const op of ops) {
1264
- opSchemas[op] = createOperatorSchema(fieldMeta, op, enumMap).optional();
1396
+ opSchemas[op] = createOperatorSchema(fieldMeta, op, enumMap, scalarBase).optional();
1265
1397
  opKeys.push(op);
1266
1398
  }
1267
1399
  if (fieldMeta.type === "String" && !fieldMeta.isList) {
@@ -1282,6 +1414,7 @@ function createArgsBuilder(typeMap, enumMap, uniqueMap) {
1282
1414
  const modelFields = typeMap[model];
1283
1415
  if (!modelFields)
1284
1416
  throw new ShapeError(`Unknown model: ${model}`);
1417
+ requireConfigTrue(fieldConfig, `${opName} on model "${model}"`);
1285
1418
  const isNumericOnly = opName === "_avg" || opName === "_sum";
1286
1419
  const isComparableOnly = opName === "_min" || opName === "_max";
1287
1420
  const fieldSchemas = {};
@@ -1295,6 +1428,8 @@ function createArgsBuilder(typeMap, enumMap, uniqueMap) {
1295
1428
  throw new ShapeError(`Unknown field "${fieldName}" on model "${model}" in ${opName}`);
1296
1429
  if (fieldMeta.isRelation)
1297
1430
  throw new ShapeError(`Relation field "${fieldName}" cannot be used in ${opName}`);
1431
+ if (fieldMeta.isList)
1432
+ throw new ShapeError(`List field "${fieldName}" cannot be used in ${opName}`);
1298
1433
  if (isNumericOnly && !NUMERIC_TYPES.has(fieldMeta.type)) {
1299
1434
  throw new ShapeError(
1300
1435
  `Field "${fieldName}" (${fieldMeta.type}) cannot be used in ${opName}. Only numeric types (Int, Float, Decimal, BigInt) are supported.`
@@ -1320,6 +1455,7 @@ function createArgsBuilder(typeMap, enumMap, uniqueMap) {
1320
1455
  const modelFields = typeMap[model];
1321
1456
  if (!modelFields)
1322
1457
  throw new ShapeError(`Unknown model: ${model}`);
1458
+ requireConfigTrue(config, `${context} on model "${model}"`);
1323
1459
  const fieldSchemas = {};
1324
1460
  for (const fieldName of Object.keys(config)) {
1325
1461
  if (fieldName !== "_all") {
@@ -1341,6 +1477,7 @@ function createArgsBuilder(typeMap, enumMap, uniqueMap) {
1341
1477
  const modelFields = typeMap[model];
1342
1478
  if (!modelFields)
1343
1479
  throw new ShapeError(`Unknown model: ${model}`);
1480
+ requireConfigTrue(selectConfig, `count select on model "${model}"`);
1344
1481
  const fieldSchemas = {};
1345
1482
  for (const fieldName of Object.keys(selectConfig)) {
1346
1483
  if (fieldName === "_all") {
@@ -1393,6 +1530,7 @@ var KNOWN_NESTED_SELECT_KEYS = /* @__PURE__ */ new Set([
1393
1530
  "skip"
1394
1531
  ]);
1395
1532
  var KNOWN_COUNT_SELECT_ENTRY_KEYS = /* @__PURE__ */ new Set(["where"]);
1533
+ var MAX_PROJECTION_DEPTH = 10;
1396
1534
  function validateNestedKeys(keys, allowed, context) {
1397
1535
  for (const key of keys) {
1398
1536
  if (!allowed.has(key)) {
@@ -1446,6 +1584,11 @@ function createProjectionBuilder(typeMap, enumMap, deps) {
1446
1584
  if (fieldConfig === true) {
1447
1585
  countSelectFields[fieldName] = z6.literal(true).optional();
1448
1586
  } else if (isPlainObject(fieldConfig)) {
1587
+ if (Object.keys(fieldConfig).length === 0) {
1588
+ throw new ShapeError(
1589
+ `Empty config for _count.select.${fieldName} on model "${model}". Use true or { where: { ... } }.`
1590
+ );
1591
+ }
1449
1592
  validateNestedKeys(
1450
1593
  Object.keys(fieldConfig),
1451
1594
  KNOWN_COUNT_SELECT_ENTRY_KEYS,
@@ -1474,13 +1617,28 @@ function createProjectionBuilder(typeMap, enumMap, deps) {
1474
1617
  );
1475
1618
  }
1476
1619
  }
1477
- const selectSchema = z6.object(countSelectFields).strict();
1620
+ const countSelectKeys = Object.keys(countSelectFields);
1621
+ const selectSchema = z6.object(countSelectFields).strict().refine(
1622
+ (v) => countSelectKeys.some((k) => v[k] !== void 0),
1623
+ { message: "_count.select must specify at least one field" }
1624
+ );
1478
1625
  return {
1479
1626
  schema: z6.object({ select: selectSchema }).strict().optional(),
1480
1627
  forcedCountWhere
1481
1628
  };
1482
1629
  }
1483
- function buildIncludeSchema(model, includeConfig) {
1630
+ function buildIncludeSchema(model, includeConfig, depth) {
1631
+ const currentDepth = depth ?? 0;
1632
+ if (currentDepth > MAX_PROJECTION_DEPTH) {
1633
+ throw new ShapeError(
1634
+ `Include schema for model "${model}" exceeds maximum nesting depth (${MAX_PROJECTION_DEPTH}). Check for circular relation references in the shape.`
1635
+ );
1636
+ }
1637
+ if (Object.keys(includeConfig).length === 0) {
1638
+ throw new ShapeError(
1639
+ `Empty include config on model "${model}". Define at least one relation.`
1640
+ );
1641
+ }
1484
1642
  const modelFields = typeMap[model];
1485
1643
  if (!modelFields)
1486
1644
  throw new ShapeError(`Unknown model: ${model}`);
@@ -1530,20 +1688,24 @@ function createProjectionBuilder(typeMap, enumMap, deps) {
1530
1688
  relForced.where = forced;
1531
1689
  }
1532
1690
  if (config.include) {
1533
- const nested = buildIncludeSchema(fieldMeta.type, config.include);
1691
+ const nested = buildIncludeSchema(fieldMeta.type, config.include, currentDepth + 1);
1534
1692
  nestedSchemas["include"] = nested.schema;
1535
1693
  if (Object.keys(nested.forcedTree).length > 0)
1536
1694
  relForced.include = nested.forcedTree;
1537
- if (Object.keys(nested.forcedCountWhere).length > 0)
1695
+ if (Object.keys(nested.forcedCountWhere).length > 0) {
1538
1696
  relForced._countWhere = nested.forcedCountWhere;
1697
+ relForced._countWherePlacement = "include";
1698
+ }
1539
1699
  }
1540
1700
  if (config.select) {
1541
- const nested = buildSelectSchema(fieldMeta.type, config.select);
1701
+ const nested = buildSelectSchema(fieldMeta.type, config.select, currentDepth + 1);
1542
1702
  nestedSchemas["select"] = nested.schema;
1543
1703
  if (Object.keys(nested.forcedTree).length > 0)
1544
1704
  relForced.select = nested.forcedTree;
1545
- if (Object.keys(nested.forcedCountWhere).length > 0)
1705
+ if (Object.keys(nested.forcedCountWhere).length > 0) {
1546
1706
  relForced._countWhere = nested.forcedCountWhere;
1707
+ relForced._countWherePlacement = "select";
1708
+ }
1547
1709
  }
1548
1710
  if (config.orderBy) {
1549
1711
  nestedSchemas["orderBy"] = deps.buildOrderBySchema(fieldMeta.type, config.orderBy);
@@ -1563,13 +1725,30 @@ function createProjectionBuilder(typeMap, enumMap, deps) {
1563
1725
  forcedTree[relName] = relForced;
1564
1726
  }
1565
1727
  }
1728
+ const includeFieldKeys = Object.keys(fieldSchemas);
1729
+ const baseSchema = z6.object(fieldSchemas).strict();
1730
+ const schema = includeFieldKeys.length > 0 ? baseSchema.refine(
1731
+ (v) => includeFieldKeys.some((k) => v[k] !== void 0),
1732
+ { message: "include must specify at least one field" }
1733
+ ).optional() : baseSchema.optional();
1566
1734
  return {
1567
- schema: z6.object(fieldSchemas).strict().optional(),
1735
+ schema,
1568
1736
  forcedTree,
1569
1737
  forcedCountWhere: topLevelForcedCountWhere
1570
1738
  };
1571
1739
  }
1572
- function buildSelectSchema(model, selectConfig) {
1740
+ function buildSelectSchema(model, selectConfig, depth) {
1741
+ const currentDepth = depth ?? 0;
1742
+ if (currentDepth > MAX_PROJECTION_DEPTH) {
1743
+ throw new ShapeError(
1744
+ `Select schema for model "${model}" exceeds maximum nesting depth (${MAX_PROJECTION_DEPTH}). Check for circular relation references in the shape.`
1745
+ );
1746
+ }
1747
+ if (Object.keys(selectConfig).length === 0) {
1748
+ throw new ShapeError(
1749
+ `Empty select config on model "${model}". Define at least one field.`
1750
+ );
1751
+ }
1573
1752
  const modelFields = typeMap[model];
1574
1753
  if (!modelFields)
1575
1754
  throw new ShapeError(`Unknown model: ${model}`);
@@ -1607,12 +1786,14 @@ function createProjectionBuilder(typeMap, enumMap, deps) {
1607
1786
  const nestedSchemas = {};
1608
1787
  const relForced = {};
1609
1788
  if (config.select) {
1610
- const nested = buildSelectSchema(fieldMeta.type, config.select);
1789
+ const nested = buildSelectSchema(fieldMeta.type, config.select, currentDepth + 1);
1611
1790
  nestedSchemas["select"] = nested.schema;
1612
1791
  if (Object.keys(nested.forcedTree).length > 0)
1613
1792
  relForced.select = nested.forcedTree;
1614
- if (Object.keys(nested.forcedCountWhere).length > 0)
1793
+ if (Object.keys(nested.forcedCountWhere).length > 0) {
1615
1794
  relForced._countWhere = nested.forcedCountWhere;
1795
+ relForced._countWherePlacement = "select";
1796
+ }
1616
1797
  }
1617
1798
  if (config.where) {
1618
1799
  const { schema: whereSchema, forced } = deps.buildWhereSchema(
@@ -1642,8 +1823,14 @@ function createProjectionBuilder(typeMap, enumMap, deps) {
1642
1823
  forcedTree[fieldName] = relForced;
1643
1824
  }
1644
1825
  }
1826
+ const selectFieldKeys = Object.keys(fieldSchemas);
1827
+ const baseSchema = z6.object(fieldSchemas).strict();
1828
+ const schema = selectFieldKeys.length > 0 ? baseSchema.refine(
1829
+ (v) => selectFieldKeys.some((k) => v[k] !== void 0),
1830
+ { message: "select must specify at least one field" }
1831
+ ).optional() : baseSchema.optional();
1645
1832
  return {
1646
- schema: z6.object(fieldSchemas).strict().optional(),
1833
+ schema,
1647
1834
  forcedTree,
1648
1835
  forcedCountWhere: topLevelForcedCountWhere
1649
1836
  };
@@ -1663,9 +1850,9 @@ var METHOD_ALLOWED_ARGS = {
1663
1850
  groupBy: /* @__PURE__ */ new Set(["where", "by", "having", "_count", "_avg", "_sum", "_min", "_max", "orderBy", "take", "skip"])
1664
1851
  };
1665
1852
  var UNIQUE_WHERE_METHODS = /* @__PURE__ */ new Set(["findUnique", "findUniqueOrThrow"]);
1666
- function createQueryBuilder(typeMap, enumMap, uniqueMap = {}) {
1667
- const whereBuilder = createWhereBuilder(typeMap, enumMap);
1668
- const argsBuilder = createArgsBuilder(typeMap, enumMap, uniqueMap);
1853
+ function createQueryBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
1854
+ const whereBuilder = createWhereBuilder(typeMap, enumMap, scalarBase);
1855
+ const argsBuilder = createArgsBuilder(typeMap, enumMap, uniqueMap, scalarBase);
1669
1856
  const projectionBuilder = createProjectionBuilder(typeMap, enumMap, {
1670
1857
  buildWhereSchema: whereBuilder.buildWhereSchema,
1671
1858
  buildOrderBySchema: argsBuilder.buildOrderBySchema,
@@ -1774,8 +1961,12 @@ function createQueryBuilder(typeMap, enumMap, uniqueMap = {}) {
1774
1961
  schemaFields["cursor"] = argsBuilder.buildCursorSchema(model, shape.cursor);
1775
1962
  if (shape.take)
1776
1963
  schemaFields["take"] = argsBuilder.buildTakeSchema(shape.take);
1777
- if (shape.skip)
1964
+ if (shape.skip !== void 0) {
1965
+ if (shape.skip !== true) {
1966
+ throw new ShapeError('Shape config "skip" must be true');
1967
+ }
1778
1968
  schemaFields["skip"] = z7.number().int().min(0).optional();
1969
+ }
1779
1970
  if (shape.distinct)
1780
1971
  schemaFields["distinct"] = argsBuilder.buildDistinctSchema(model, shape.distinct);
1781
1972
  if (shape._count)
@@ -1831,6 +2022,7 @@ function createQueryBuilder(typeMap, enumMap, uniqueMap = {}) {
1831
2022
  [...builtCache.entries()].map(([k, v]) => [k, v.zodSchema])
1832
2023
  ),
1833
2024
  parse(body, opts) {
2025
+ const normalizedBody = body === void 0 || body === null ? {} : body;
1834
2026
  let built;
1835
2027
  if (isSingle) {
1836
2028
  if (typeof config === "function") {
@@ -1840,9 +2032,9 @@ function createQueryBuilder(typeMap, enumMap, uniqueMap = {}) {
1840
2032
  built = builtCache.get("_default");
1841
2033
  }
1842
2034
  } else {
1843
- if (!isPlainObject(body))
2035
+ if (!isPlainObject(normalizedBody))
1844
2036
  throw new ShapeError("Request body must be an object");
1845
- if ("caller" in body) {
2037
+ if ("caller" in normalizedBody) {
1846
2038
  throw new CallerError(
1847
2039
  "Pass caller via opts.caller, not in the request body."
1848
2040
  );
@@ -1868,7 +2060,7 @@ function createQueryBuilder(typeMap, enumMap, uniqueMap = {}) {
1868
2060
  built = builtCache.get(matched.key);
1869
2061
  }
1870
2062
  }
1871
- return applyBuiltShape(built, body, isUnique);
2063
+ return applyBuiltShape(built, normalizedBody, isUnique);
1872
2064
  }
1873
2065
  };
1874
2066
  }
@@ -2055,10 +2247,24 @@ function createScopeExtension(scopeMap, contextFn, guardConfig, logger) {
2055
2247
  const overrides = Object.fromEntries(
2056
2248
  presentScopes.map((s) => [s.fk, ctx[s.root]])
2057
2249
  );
2250
+ const nextArgs = { ...args };
2058
2251
  if (operation === "upsert") {
2059
- throw new PolicyError(
2060
- `Scoped model "${model}" cannot use upsert via extension. Handle upsert explicitly in route logic.`
2061
- );
2252
+ nextArgs.where = buildScopedUniqueWhere(args.where, conditions);
2253
+ if (args.create !== void 0 && args.create !== null) {
2254
+ if (typeof args.create !== "object" || Array.isArray(args.create)) {
2255
+ throw new ShapeError(`upsert expects create to be an object`);
2256
+ }
2257
+ nextArgs.create = { ...args.create };
2258
+ enforceDataScope(nextArgs.create, scopes, overrides, log, model, operation, onScopeRelationWrite, "create");
2259
+ }
2260
+ if (args.update !== void 0 && args.update !== null) {
2261
+ if (typeof args.update !== "object" || Array.isArray(args.update)) {
2262
+ throw new ShapeError(`upsert expects update to be an object`);
2263
+ }
2264
+ nextArgs.update = { ...args.update };
2265
+ enforceDataScope(nextArgs.update, scopes, overrides, log, model, operation, onScopeRelationWrite, "mutate");
2266
+ }
2267
+ return query(nextArgs);
2062
2268
  }
2063
2269
  if (FIND_UNIQUE_OPS.has(operation)) {
2064
2270
  if (findUniqueMode === "reject") {
@@ -2068,7 +2274,6 @@ function createScopeExtension(scopeMap, contextFn, guardConfig, logger) {
2068
2274
  }
2069
2275
  return handleFindUnique(args, query, conditions, scopes, operation, log);
2070
2276
  }
2071
- const nextArgs = { ...args };
2072
2277
  if (READ_OPS.has(operation)) {
2073
2278
  nextArgs.where = buildAndConditions(args.where, conditions);
2074
2279
  return query(nextArgs);
@@ -2219,18 +2424,14 @@ var ALLOWED_BODY_KEYS_UPDATE = /* @__PURE__ */ new Set(["data", "where"]);
2219
2424
  var ALLOWED_BODY_KEYS_UPDATE_PROJECTION = /* @__PURE__ */ new Set(["data", "where", "select", "include"]);
2220
2425
  var ALLOWED_BODY_KEYS_DELETE = /* @__PURE__ */ new Set(["where"]);
2221
2426
  var ALLOWED_BODY_KEYS_DELETE_PROJECTION = /* @__PURE__ */ new Set(["where", "select", "include"]);
2427
+ var ALLOWED_BODY_KEYS_UPSERT = /* @__PURE__ */ new Set(["where", "create", "update", "select", "include"]);
2222
2428
  var VALID_SHAPE_KEYS_CREATE = /* @__PURE__ */ new Set(["data"]);
2223
2429
  var VALID_SHAPE_KEYS_CREATE_PROJECTION = /* @__PURE__ */ new Set(["data", "select", "include"]);
2224
2430
  var VALID_SHAPE_KEYS_UPDATE = /* @__PURE__ */ new Set(["data", "where"]);
2225
2431
  var VALID_SHAPE_KEYS_UPDATE_PROJECTION = /* @__PURE__ */ new Set(["data", "where", "select", "include"]);
2226
2432
  var VALID_SHAPE_KEYS_DELETE = /* @__PURE__ */ new Set(["where"]);
2227
2433
  var VALID_SHAPE_KEYS_DELETE_PROJECTION = /* @__PURE__ */ new Set(["where", "select", "include"]);
2228
- function isZodSchema2(value) {
2229
- if (value == null || typeof value !== "object")
2230
- return false;
2231
- const v = value;
2232
- return typeof v.parse === "function" && typeof v.optional === "function";
2233
- }
2434
+ var VALID_SHAPE_KEYS_UPSERT = /* @__PURE__ */ new Set(["where", "create", "update", "select", "include"]);
2234
2435
  function validateMutationBodyKeys(body, allowed, method) {
2235
2436
  for (const key of Object.keys(body)) {
2236
2437
  if (!allowed.has(key)) {
@@ -2275,10 +2476,12 @@ function validateCreateCompleteness(modelName, dataConfig, typeMap, scopeFks, zo
2275
2476
  );
2276
2477
  }
2277
2478
  }
2278
- function buildDataSchema(model, dataConfig, mode, typeMap, schemaBuilder) {
2479
+ function buildDataSchema(model, dataConfig, mode, typeMap, schemaBuilder, zodDefaults) {
2279
2480
  const modelFields = typeMap[model];
2280
2481
  if (!modelFields)
2281
2482
  throw new ShapeError(`Unknown model: ${model}`);
2483
+ const zodDefaultFields = zodDefaults[model];
2484
+ const zodDefaultSet = zodDefaultFields ? new Set(zodDefaultFields) : void 0;
2282
2485
  const schemaMap = {};
2283
2486
  const forced = {};
2284
2487
  for (const [fieldName, value] of Object.entries(dataConfig)) {
@@ -2300,15 +2503,18 @@ function buildDataSchema(model, dataConfig, mode, typeMap, schemaBuilder) {
2300
2503
  { cause: err }
2301
2504
  );
2302
2505
  }
2303
- if (!isZodSchema2(refined)) {
2506
+ if (!isZodSchema(refined)) {
2304
2507
  throw new ShapeError(`Inline refine for "${model}.${fieldName}" must return a Zod schema`);
2305
2508
  }
2306
2509
  let fieldSchema = refined;
2510
+ const handlesUndefined = schemaProducesValueForUndefined(fieldSchema);
2307
2511
  if (mode === "create") {
2308
2512
  if (!fieldMeta.isRequired) {
2309
- fieldSchema = fieldSchema.nullable().optional();
2513
+ fieldSchema = handlesUndefined ? fieldSchema.nullable() : fieldSchema.nullable().optional();
2310
2514
  } else if (fieldMeta.hasDefault) {
2311
- fieldSchema = fieldSchema.optional();
2515
+ if (!handlesUndefined) {
2516
+ fieldSchema = fieldSchema.optional();
2517
+ }
2312
2518
  }
2313
2519
  } else {
2314
2520
  if (!fieldMeta.isRequired) {
@@ -2320,11 +2526,14 @@ function buildDataSchema(model, dataConfig, mode, typeMap, schemaBuilder) {
2320
2526
  schemaMap[fieldName] = fieldSchema;
2321
2527
  } else if (value === true) {
2322
2528
  let fieldSchema = schemaBuilder.buildFieldSchema(model, fieldName);
2529
+ const isZodDefaultField = zodDefaultSet !== void 0 && zodDefaultSet.has(fieldName);
2323
2530
  if (mode === "create") {
2324
2531
  if (!fieldMeta.isRequired) {
2325
- fieldSchema = fieldSchema.nullable().optional();
2532
+ fieldSchema = isZodDefaultField ? fieldSchema.nullable() : fieldSchema.nullable().optional();
2326
2533
  } else if (fieldMeta.hasDefault) {
2327
- fieldSchema = fieldSchema.optional();
2534
+ if (!isZodDefaultField) {
2535
+ fieldSchema = fieldSchema.optional();
2536
+ }
2328
2537
  }
2329
2538
  } else {
2330
2539
  if (!fieldMeta.isRequired) {
@@ -2335,13 +2544,14 @@ function buildDataSchema(model, dataConfig, mode, typeMap, schemaBuilder) {
2335
2544
  }
2336
2545
  schemaMap[fieldName] = fieldSchema;
2337
2546
  } else {
2547
+ const actualValue = isForcedValue(value) ? value.value : value;
2338
2548
  let fieldSchema = schemaBuilder.buildFieldSchema(model, fieldName);
2339
2549
  if (!fieldMeta.isRequired) {
2340
2550
  fieldSchema = fieldSchema.nullable();
2341
2551
  }
2342
2552
  let parsed;
2343
2553
  try {
2344
- parsed = fieldSchema.parse(value);
2554
+ parsed = fieldSchema.parse(actualValue);
2345
2555
  } catch (err) {
2346
2556
  throw new ShapeError(
2347
2557
  `Invalid forced data value for "${model}.${fieldName}": ${err.message}`
@@ -2350,6 +2560,28 @@ function buildDataSchema(model, dataConfig, mode, typeMap, schemaBuilder) {
2350
2560
  forced[fieldName] = parsed;
2351
2561
  }
2352
2562
  }
2563
+ if (mode === "create" && zodDefaultFields) {
2564
+ for (const fieldName of zodDefaultFields) {
2565
+ if (fieldName in dataConfig)
2566
+ continue;
2567
+ const fieldMeta = modelFields[fieldName];
2568
+ if (!fieldMeta)
2569
+ continue;
2570
+ if (fieldMeta.isRelation)
2571
+ continue;
2572
+ if (fieldMeta.isUpdatedAt)
2573
+ continue;
2574
+ const fieldSchema = schemaBuilder.buildFieldSchema(model, fieldName);
2575
+ const result = fieldSchema.safeParse(void 0);
2576
+ if (result.success && result.data !== void 0) {
2577
+ forced[fieldName] = result.data;
2578
+ } else {
2579
+ throw new ShapeError(
2580
+ `Field "${fieldName}" on model "${model}" has @zod default/catch but its schema does not produce a value for undefined input`
2581
+ );
2582
+ }
2583
+ }
2584
+ }
2353
2585
  return {
2354
2586
  schema: z8.object(schemaMap).strict(),
2355
2587
  forced
@@ -2360,7 +2592,7 @@ function validateAndMergeData(bodyData, cached, method) {
2360
2592
  throw new ShapeError(`${method} requires "data" in request body`);
2361
2593
  }
2362
2594
  const validated = cached.schema.parse(bodyData);
2363
- return { ...validated, ...cached.forced };
2595
+ return { ...validated, ...deepClone(cached.forced) };
2364
2596
  }
2365
2597
  function hasDataRefines(dataConfig) {
2366
2598
  for (const value of Object.values(dataConfig)) {
@@ -2422,7 +2654,7 @@ function resolveShape(input, body, contextFn, caller) {
2422
2654
  );
2423
2655
  }
2424
2656
  }
2425
- const parsed = requireBody(body);
2657
+ const parsed = body === void 0 || body === null ? {} : requireBody(body);
2426
2658
  if ("caller" in parsed) {
2427
2659
  throw new CallerError(
2428
2660
  "Pass caller as second argument to .guard() or via context function, not in the request body."
@@ -2448,7 +2680,7 @@ function resolveShape(input, body, contextFn, caller) {
2448
2680
  }
2449
2681
 
2450
2682
  // src/runtime/model-guard.ts
2451
- var UNIQUE_MUTATION_METHODS = /* @__PURE__ */ new Set(["update", "delete"]);
2683
+ var UNIQUE_MUTATION_METHODS = /* @__PURE__ */ new Set(["update", "delete", "upsert"]);
2452
2684
  var UNIQUE_READ_METHODS = /* @__PURE__ */ new Set(["findUnique", "findUniqueOrThrow"]);
2453
2685
  var BULK_MUTATION_METHODS = /* @__PURE__ */ new Set([
2454
2686
  "updateMany",
@@ -2458,6 +2690,7 @@ var BULK_MUTATION_METHODS = /* @__PURE__ */ new Set([
2458
2690
  var PROJECTION_MUTATION_METHODS = /* @__PURE__ */ new Set([
2459
2691
  "create",
2460
2692
  "update",
2693
+ "upsert",
2461
2694
  "delete",
2462
2695
  "createManyAndReturn",
2463
2696
  "updateManyAndReturn"
@@ -2466,11 +2699,148 @@ var BATCH_CREATE_METHODS = /* @__PURE__ */ new Set([
2466
2699
  "createMany",
2467
2700
  "createManyAndReturn"
2468
2701
  ]);
2702
+ function buildDefaultSelectInput(config) {
2703
+ const result = {};
2704
+ for (const [key, value] of Object.entries(config)) {
2705
+ if (key === "_count") {
2706
+ result[key] = buildDefaultCountInput(value);
2707
+ continue;
2708
+ }
2709
+ if (value === true) {
2710
+ result[key] = true;
2711
+ } else {
2712
+ const nested = {};
2713
+ if (value.select)
2714
+ nested.select = buildDefaultSelectInput(value.select);
2715
+ result[key] = Object.keys(nested).length > 0 ? nested : true;
2716
+ }
2717
+ }
2718
+ return result;
2719
+ }
2720
+ function buildDefaultIncludeInput(config) {
2721
+ const result = {};
2722
+ for (const [key, value] of Object.entries(config)) {
2723
+ if (key === "_count") {
2724
+ result[key] = buildDefaultCountInput(value);
2725
+ continue;
2726
+ }
2727
+ if (value === true) {
2728
+ result[key] = true;
2729
+ } else {
2730
+ const nested = {};
2731
+ if (value.include)
2732
+ nested.include = buildDefaultIncludeInput(value.include);
2733
+ if (value.select)
2734
+ nested.select = buildDefaultSelectInput(value.select);
2735
+ result[key] = Object.keys(nested).length > 0 ? nested : true;
2736
+ }
2737
+ }
2738
+ return result;
2739
+ }
2740
+ function buildDefaultCountInput(config) {
2741
+ if (config === true)
2742
+ return true;
2743
+ if (!isPlainObject(config) || !config.select || !isPlainObject(config.select))
2744
+ return true;
2745
+ const selectObj = config.select;
2746
+ const result = {};
2747
+ for (const key of Object.keys(selectObj)) {
2748
+ result[key] = true;
2749
+ }
2750
+ return { select: result };
2751
+ }
2752
+ function buildDefaultProjectionBody(shape) {
2753
+ if (shape.select) {
2754
+ return { select: buildDefaultSelectInput(shape.select) };
2755
+ }
2756
+ if (shape.include) {
2757
+ return { include: buildDefaultIncludeInput(shape.include) };
2758
+ }
2759
+ return {};
2760
+ }
2761
+ function hasClientControlledValues(obj) {
2762
+ for (const value of Object.values(obj)) {
2763
+ if (isForcedValue(value))
2764
+ continue;
2765
+ if (value === true)
2766
+ return true;
2767
+ if (isPlainObject(value) && hasClientControlledValues(value))
2768
+ return true;
2769
+ }
2770
+ return false;
2771
+ }
2772
+ function checkIncludeForClientArgs(config) {
2773
+ for (const [key, value] of Object.entries(config)) {
2774
+ if (key === "_count") {
2775
+ if (value !== true && isPlainObject(value) && isPlainObject(value.select)) {
2776
+ const selectObj = value.select;
2777
+ for (const entryVal of Object.values(selectObj)) {
2778
+ if (isPlainObject(entryVal) && entryVal.where) {
2779
+ const w = entryVal.where;
2780
+ if (isPlainObject(w) && hasClientControlledValues(w))
2781
+ return true;
2782
+ }
2783
+ }
2784
+ }
2785
+ continue;
2786
+ }
2787
+ if (value === true)
2788
+ continue;
2789
+ if (value.orderBy || value.cursor || value.take || value.skip)
2790
+ return true;
2791
+ if (value.where && isPlainObject(value.where) && hasClientControlledValues(value.where))
2792
+ return true;
2793
+ if (value.include && checkIncludeForClientArgs(value.include))
2794
+ return true;
2795
+ if (value.select && checkSelectForClientArgs(value.select))
2796
+ return true;
2797
+ }
2798
+ return false;
2799
+ }
2800
+ function checkSelectForClientArgs(config) {
2801
+ for (const [key, value] of Object.entries(config)) {
2802
+ if (key === "_count") {
2803
+ if (value !== true && isPlainObject(value) && isPlainObject(value.select)) {
2804
+ const selectObj = value.select;
2805
+ for (const entryVal of Object.values(selectObj)) {
2806
+ if (isPlainObject(entryVal) && entryVal.where) {
2807
+ const w = entryVal.where;
2808
+ if (isPlainObject(w) && hasClientControlledValues(w))
2809
+ return true;
2810
+ }
2811
+ }
2812
+ }
2813
+ continue;
2814
+ }
2815
+ if (value === true)
2816
+ continue;
2817
+ if (value.orderBy || value.cursor || value.take || value.skip)
2818
+ return true;
2819
+ if (value.where && isPlainObject(value.where) && hasClientControlledValues(value.where))
2820
+ return true;
2821
+ if (value.select && checkSelectForClientArgs(value.select))
2822
+ return true;
2823
+ }
2824
+ return false;
2825
+ }
2826
+ function hasNestedClientControlledArgs(shape) {
2827
+ if (shape.include) {
2828
+ if (checkIncludeForClientArgs(shape.include))
2829
+ return true;
2830
+ }
2831
+ if (shape.select) {
2832
+ if (checkSelectForClientArgs(shape.select))
2833
+ return true;
2834
+ }
2835
+ return false;
2836
+ }
2469
2837
  function createModelGuardExtension(config) {
2470
- const { typeMap, enumMap, zodChains, zodDefaults, uniqueMap, scopeMap, contextFn } = config;
2838
+ const { typeMap, enumMap, zodChains, zodDefaults, uniqueMap, scopeMap, guardConfig, contextFn } = config;
2471
2839
  const wrapZodErrors = config.wrapZodErrors ?? false;
2472
- const schemaBuilder = createSchemaBuilder(typeMap, zodChains, enumMap);
2473
- const queryBuilder = createQueryBuilder(typeMap, enumMap, uniqueMap);
2840
+ const enforceProjection = guardConfig.enforceProjection ?? false;
2841
+ const scalarBase = createScalarBase(guardConfig.strictDecimal ?? false);
2842
+ const schemaBuilder = createSchemaBuilder(typeMap, zodChains, enumMap, scalarBase, zodDefaults);
2843
+ const queryBuilder = createQueryBuilder(typeMap, enumMap, uniqueMap, scalarBase);
2474
2844
  const modelScopeFks = /* @__PURE__ */ new Map();
2475
2845
  for (const [model, entries] of Object.entries(scopeMap)) {
2476
2846
  const fks = /* @__PURE__ */ new Set();
@@ -2523,11 +2893,11 @@ function createModelGuardExtension(config) {
2523
2893
  const cached = dataSchemaCache.get(cacheKey);
2524
2894
  if (cached)
2525
2895
  return cached;
2526
- const built = buildDataSchema(modelName, dataConfig, mode, typeMap, schemaBuilder);
2896
+ const built = buildDataSchema(modelName, dataConfig, mode, typeMap, schemaBuilder, zodDefaults);
2527
2897
  dataSchemaCache.set(cacheKey, built);
2528
2898
  return built;
2529
2899
  }
2530
- return buildDataSchema(modelName, dataConfig, mode, typeMap, schemaBuilder);
2900
+ return buildDataSchema(modelName, dataConfig, mode, typeMap, schemaBuilder, zodDefaults);
2531
2901
  }
2532
2902
  function getWhereBuilt(whereConfig, matchedKey, wasDynamic) {
2533
2903
  if (!wasDynamic) {
@@ -2597,12 +2967,26 @@ function createModelGuardExtension(config) {
2597
2967
  }
2598
2968
  if (!hasShapeProjection)
2599
2969
  return {};
2970
+ if (!hasBodyProjection && !enforceProjection)
2971
+ return {};
2972
+ if (!hasBodyProjection && enforceProjection) {
2973
+ if (hasNestedClientControlledArgs(shape)) {
2974
+ throw new ShapeError(
2975
+ `Guard shape defines nested client-controlled projection args (orderBy/take/cursor/skip/where) but the client did not provide select/include in the ${method} body. With enforceProjection enabled, either always provide projection in the body or remove client-controlled nested args from the shape.`
2976
+ );
2977
+ }
2978
+ }
2600
2979
  const projection = getProjection(shape, matchedKey, wasDynamic);
2601
- const projectionBody = {};
2602
- if ("select" in parsed)
2603
- projectionBody.select = parsed.select;
2604
- if ("include" in parsed)
2605
- projectionBody.include = parsed.include;
2980
+ let projectionBody;
2981
+ if (hasBodyProjection) {
2982
+ projectionBody = {};
2983
+ if ("select" in parsed)
2984
+ projectionBody.select = parsed.select;
2985
+ if ("include" in parsed)
2986
+ projectionBody.include = parsed.include;
2987
+ } else {
2988
+ projectionBody = buildDefaultProjectionBody(shape);
2989
+ }
2606
2990
  const validated = projection.zodSchema.parse(projectionBody);
2607
2991
  if (Object.keys(projection.forcedIncludeTree).length > 0) {
2608
2992
  applyForcedTree(validated, "include", projection.forcedIncludeTree);
@@ -2633,6 +3017,12 @@ function createModelGuardExtension(config) {
2633
3017
  let validatedWhere;
2634
3018
  if (built.schema) {
2635
3019
  validatedWhere = built.schema.parse(bodyWhere);
3020
+ } else if (bodyWhere !== void 0) {
3021
+ if (bodyWhere === null || !isPlainObject(bodyWhere) || Object.keys(bodyWhere).length > 0) {
3022
+ throw new ShapeError(
3023
+ "Guard shape where contains only forced conditions. Client where input is not accepted."
3024
+ );
3025
+ }
2636
3026
  }
2637
3027
  if (hasWhereForced(built.forced)) {
2638
3028
  return preserveUnique ? mergeUniqueWhereForced(validatedWhere, built.forced) : mergeWhereForced(validatedWhere, built.forced);
@@ -2785,6 +3175,70 @@ function createModelGuardExtension(config) {
2785
3175
  return callDelegate(method, args);
2786
3176
  };
2787
3177
  }
3178
+ function makeUpsertMethod() {
3179
+ return (body) => {
3180
+ const caller = resolveCaller();
3181
+ const resolved = resolveShape(input, body, contextFn, caller);
3182
+ if (resolved.shape.data) {
3183
+ throw new ShapeError('Guard shape "data" is not valid for upsert. Use "create" and "update" instead.');
3184
+ }
3185
+ if (!resolved.shape.create) {
3186
+ throw new ShapeError('Guard shape requires "create" for upsert');
3187
+ }
3188
+ if (!resolved.shape.update) {
3189
+ throw new ShapeError('Guard shape requires "update" for upsert');
3190
+ }
3191
+ if (!resolved.shape.where) {
3192
+ throw new ShapeError('Guard shape requires "where" for upsert');
3193
+ }
3194
+ validateMutationShapeKeys(
3195
+ resolved.shape,
3196
+ VALID_SHAPE_KEYS_UPSERT,
3197
+ "upsert"
3198
+ );
3199
+ validateMutationBodyKeys(resolved.body, ALLOWED_BODY_KEYS_UPSERT, "upsert");
3200
+ maybeValidateUniqueWhere(modelName, resolved.shape, "upsert");
3201
+ const fks = modelScopeFks.get(modelName) ?? /* @__PURE__ */ new Set();
3202
+ validateCreateCompleteness(modelName, resolved.shape.create, typeMap, fks, zodDefaults);
3203
+ const createDataSchema = getDataSchema(
3204
+ "create",
3205
+ resolved.shape.create,
3206
+ `upsert:create\0${resolved.matchedKey}`,
3207
+ resolved.wasDynamic
3208
+ );
3209
+ const createData = validateAndMergeData(resolved.body.create, createDataSchema, "upsert (create)");
3210
+ const updateDataSchema = getDataSchema(
3211
+ "update",
3212
+ resolved.shape.update,
3213
+ `upsert:update\0${resolved.matchedKey}`,
3214
+ resolved.wasDynamic
3215
+ );
3216
+ const updateData = validateAndMergeData(resolved.body.update, updateDataSchema, "upsert (update)");
3217
+ const where = requireWhere(
3218
+ resolved.shape,
3219
+ resolved.body.where,
3220
+ "upsert",
3221
+ true,
3222
+ resolved.matchedKey,
3223
+ resolved.wasDynamic
3224
+ );
3225
+ validateResolvedUniqueWhere(modelName, where, "upsert", uniqueMap);
3226
+ const args = {
3227
+ where,
3228
+ create: createData,
3229
+ update: updateData
3230
+ };
3231
+ const projectionArgs = resolveProjection(
3232
+ resolved.shape,
3233
+ resolved.body,
3234
+ "upsert",
3235
+ resolved.matchedKey,
3236
+ resolved.wasDynamic
3237
+ );
3238
+ Object.assign(args, projectionArgs);
3239
+ return callDelegate("upsert", args);
3240
+ };
3241
+ }
2788
3242
  return {
2789
3243
  findMany: makeReadMethod("findMany"),
2790
3244
  findFirst: makeReadMethod("findFirst"),
@@ -2800,6 +3254,7 @@ function createModelGuardExtension(config) {
2800
3254
  update: makeUpdateMethod("update"),
2801
3255
  updateMany: makeUpdateMethod("updateMany"),
2802
3256
  updateManyAndReturn: makeUpdateMethod("updateManyAndReturn"),
3257
+ upsert: makeUpsertMethod(),
2803
3258
  delete: makeDeleteMethod("delete"),
2804
3259
  deleteMany: makeDeleteMethod("deleteMany")
2805
3260
  };
@@ -2845,15 +3300,19 @@ function createModelGuardExtension(config) {
2845
3300
 
2846
3301
  // src/runtime/guard.ts
2847
3302
  function createGuard(config) {
3303
+ const scalarBase = createScalarBase(config.guardConfig.strictDecimal ?? false);
2848
3304
  const schemaBuilder = createSchemaBuilder(
2849
3305
  config.typeMap,
2850
3306
  config.zodChains,
2851
- config.enumMap
3307
+ config.enumMap,
3308
+ scalarBase,
3309
+ config.zodDefaults ?? {}
2852
3310
  );
2853
3311
  const queryBuilder = createQueryBuilder(
2854
3312
  config.typeMap,
2855
3313
  config.enumMap,
2856
- config.uniqueMap ?? {}
3314
+ config.uniqueMap ?? {},
3315
+ scalarBase
2857
3316
  );
2858
3317
  const log = config.logger ?? { warn: (msg) => console.warn(msg) };
2859
3318
  const wrapZodErrors = config.wrapZodErrors ?? false;
@@ -2912,8 +3371,8 @@ function createGuard(config) {
2912
3371
  if (typeof val === "string" || typeof val === "number" || typeof val === "bigint") {
2913
3372
  scopeCtx[key] = val;
2914
3373
  } else if (val !== null && val !== void 0) {
2915
- log.warn(
2916
- `prisma-guard: Scope root "${key}" has non-primitive value (${typeof val}). Only string, number, and bigint values are used for scope context.`
3374
+ throw new PolicyError(
3375
+ `prisma-guard: Scope root "${key}" has non-primitive value (${typeof val}). Only string, number, and bigint values are accepted for scope context.`
2917
3376
  );
2918
3377
  }
2919
3378
  }
@@ -2932,6 +3391,7 @@ function createGuard(config) {
2932
3391
  zodDefaults: config.zodDefaults ?? {},
2933
3392
  uniqueMap: config.uniqueMap ?? {},
2934
3393
  scopeMap: config.scopeMap,
3394
+ guardConfig: config.guardConfig,
2935
3395
  contextFn,
2936
3396
  wrapZodErrors
2937
3397
  });
@@ -2947,6 +3407,7 @@ export {
2947
3407
  CallerError,
2948
3408
  PolicyError,
2949
3409
  ShapeError,
2950
- createGuard
3410
+ createGuard,
3411
+ force
2951
3412
  };
2952
3413
  //# sourceMappingURL=index.js.map