prisma-guard 1.14.1 → 1.16.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.
@@ -187,5 +187,8 @@ declare class CallerError extends Error {
187
187
  declare function force<T>(value: T): {
188
188
  value: T;
189
189
  };
190
+ declare function unsupported(): {
191
+ __brand: 'unsupported';
192
+ };
190
193
 
191
- export { CallerError, type EnumMap, type FieldMeta, type GuardConfig, type GuardGeneratedConfig, type GuardInput, type GuardLogger, type GuardShape, type GuardShapeOrFn, type GuardedModel, type InputOpts, type InputSchema, type MissingScopeContextMode, type ModelOpts, type MutationMethod, type NestedIncludeArgs, type NestedSelectArgs, PolicyError, type QueryMethod, type QuerySchema, type ScopeEntry, type ScopeMap, type ShapeConfig, ShapeError, type ShapeOrFn, type TypeMap, type UniqueConstraint, type UniqueMap, type ZodChains, type ZodDefaults, createGuard, force };
194
+ export { CallerError, type EnumMap, type FieldMeta, type GuardConfig, type GuardGeneratedConfig, type GuardInput, type GuardLogger, type GuardShape, type GuardShapeOrFn, type GuardedModel, type InputOpts, type InputSchema, type MissingScopeContextMode, type ModelOpts, type MutationMethod, type NestedIncludeArgs, type NestedSelectArgs, PolicyError, type QueryMethod, type QuerySchema, type ScopeEntry, type ScopeMap, type ShapeConfig, ShapeError, type ShapeOrFn, type TypeMap, type UniqueConstraint, type UniqueMap, type ZodChains, type ZodDefaults, createGuard, force, unsupported };
@@ -187,5 +187,8 @@ declare class CallerError extends Error {
187
187
  declare function force<T>(value: T): {
188
188
  value: T;
189
189
  };
190
+ declare function unsupported(): {
191
+ __brand: 'unsupported';
192
+ };
190
193
 
191
- export { CallerError, type EnumMap, type FieldMeta, type GuardConfig, type GuardGeneratedConfig, type GuardInput, type GuardLogger, type GuardShape, type GuardShapeOrFn, type GuardedModel, type InputOpts, type InputSchema, type MissingScopeContextMode, type ModelOpts, type MutationMethod, type NestedIncludeArgs, type NestedSelectArgs, PolicyError, type QueryMethod, type QuerySchema, type ScopeEntry, type ScopeMap, type ShapeConfig, ShapeError, type ShapeOrFn, type TypeMap, type UniqueConstraint, type UniqueMap, type ZodChains, type ZodDefaults, createGuard, force };
194
+ export { CallerError, type EnumMap, type FieldMeta, type GuardConfig, type GuardGeneratedConfig, type GuardInput, type GuardLogger, type GuardShape, type GuardShapeOrFn, type GuardedModel, type InputOpts, type InputSchema, type MissingScopeContextMode, type ModelOpts, type MutationMethod, type NestedIncludeArgs, type NestedSelectArgs, PolicyError, type QueryMethod, type QuerySchema, type ScopeEntry, type ScopeMap, type ShapeConfig, ShapeError, type ShapeOrFn, type TypeMap, type UniqueConstraint, type UniqueMap, type ZodChains, type ZodDefaults, createGuard, force, unsupported };
@@ -84,10 +84,7 @@ function isJsonSafe(value) {
84
84
  return true;
85
85
  }
86
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
- );
87
+ var decimalStringSchema = z.string().refine((s) => DECIMAL_REGEX.test(s), "Invalid decimal string");
91
88
  var decimalObjectSchema = z.custom(
92
89
  (v) => v !== null && typeof v === "object" && typeof v.toFixed === "function" && typeof v.toNumber === "function",
93
90
  "Expected Decimal-compatible object"
@@ -113,18 +110,39 @@ function createScalarBase(strictDecimal) {
113
110
  z.string().regex(/^-?\d+$/).transform((v) => BigInt(v))
114
111
  ]),
115
112
  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
- ])
113
+ DateTime: () => z.union([z.date(), z.string().datetime({ offset: true })]).pipe(z.coerce.date()),
114
+ Json: () => z.unknown().refine(
115
+ isJsonSafe,
116
+ "Value must be JSON-serializable (no undefined, functions, symbols, class instances, NaN, Infinity, or circular references)"
117
+ ),
118
+ Bytes: () => z.union([z.string(), z.custom((v) => v instanceof Uint8Array)])
125
119
  };
126
120
  }
127
121
  var SCALAR_BASE = createScalarBase(false);
122
+ function wrapWithInputCoercion(fieldType, isList, schema) {
123
+ let itemCoercion = null;
124
+ switch (fieldType) {
125
+ case "String":
126
+ itemCoercion = z.union([z.string(), z.number().transform(String)]);
127
+ break;
128
+ case "Int":
129
+ itemCoercion = z.union([
130
+ z.number().int(),
131
+ z.string().regex(/^-?\d+$/).transform(Number)
132
+ ]);
133
+ break;
134
+ case "Float":
135
+ itemCoercion = z.union([
136
+ z.number(),
137
+ z.string().regex(/^-?(\d+\.?\d*|\.\d+)([eE][+-]?\d+)?$/).transform(Number)
138
+ ]);
139
+ break;
140
+ default:
141
+ return schema;
142
+ }
143
+ const coercion = isList ? z.array(itemCoercion) : itemCoercion;
144
+ return coercion.pipe(schema);
145
+ }
128
146
 
129
147
  // src/runtime/schema-builder.ts
130
148
  import { z as z3 } from "zod";
@@ -173,7 +191,19 @@ function coerceToArray(value) {
173
191
 
174
192
  // src/runtime/zod-type-map.ts
175
193
  var SCALAR_OPERATORS = {
176
- String: /* @__PURE__ */ new Set(["equals", "not", "contains", "startsWith", "endsWith", "in", "notIn", "gt", "gte", "lt", "lte"]),
194
+ String: /* @__PURE__ */ new Set([
195
+ "equals",
196
+ "not",
197
+ "contains",
198
+ "startsWith",
199
+ "endsWith",
200
+ "in",
201
+ "notIn",
202
+ "gt",
203
+ "gte",
204
+ "lt",
205
+ "lte"
206
+ ]),
177
207
  Int: /* @__PURE__ */ new Set(["equals", "not", "gt", "gte", "lt", "lte", "in", "notIn"]),
178
208
  Float: /* @__PURE__ */ new Set(["equals", "not", "gt", "gte", "lt", "lte", "in", "notIn"]),
179
209
  Decimal: /* @__PURE__ */ new Set(["equals", "not", "gt", "gte", "lt", "lte", "in", "notIn"]),
@@ -182,10 +212,23 @@ var SCALAR_OPERATORS = {
182
212
  DateTime: /* @__PURE__ */ new Set(["equals", "not", "gt", "gte", "lt", "lte", "in", "notIn"]),
183
213
  Bytes: /* @__PURE__ */ new Set([])
184
214
  };
185
- var SCALAR_LIST_OPERATORS = /* @__PURE__ */ new Set(["has", "hasEvery", "hasSome", "isEmpty", "equals"]);
215
+ var SCALAR_LIST_OPERATORS = /* @__PURE__ */ new Set([
216
+ "has",
217
+ "hasEvery",
218
+ "hasSome",
219
+ "isEmpty",
220
+ "equals"
221
+ ]);
186
222
  var ENUM_OPERATORS = /* @__PURE__ */ new Set(["equals", "not", "in", "notIn"]);
187
223
  var NUMERIC_TYPES = /* @__PURE__ */ new Set(["Int", "Float", "Decimal", "BigInt"]);
188
- var COMPARABLE_TYPES = /* @__PURE__ */ new Set(["Int", "Float", "Decimal", "BigInt", "String", "DateTime"]);
224
+ var COMPARABLE_TYPES = /* @__PURE__ */ new Set([
225
+ "Int",
226
+ "Float",
227
+ "Decimal",
228
+ "BigInt",
229
+ "String",
230
+ "DateTime"
231
+ ]);
189
232
  function getSupportedOperators(fieldMeta) {
190
233
  if (fieldMeta.isList)
191
234
  return [...SCALAR_LIST_OPERATORS];
@@ -220,7 +263,9 @@ function createBaseType(fieldMeta, enumMap, scalarBase) {
220
263
  }
221
264
  function createScalarListOperatorSchema(fieldMeta, operator, enumMap, scalarBase) {
222
265
  if (!SCALAR_LIST_OPERATORS.has(operator)) {
223
- throw new ShapeError(`Operator "${operator}" not supported for scalar list fields`);
266
+ throw new ShapeError(
267
+ `Operator "${operator}" not supported for scalar list fields`
268
+ );
224
269
  }
225
270
  if (operator === "isEmpty") {
226
271
  return z2.boolean();
@@ -238,7 +283,12 @@ function createScalarListOperatorSchema(fieldMeta, operator, enumMap, scalarBase
238
283
  }
239
284
  function createOperatorSchema(fieldMeta, operator, enumMap, scalarBase) {
240
285
  if (fieldMeta.isList) {
241
- return createScalarListOperatorSchema(fieldMeta, operator, enumMap, scalarBase);
286
+ return createScalarListOperatorSchema(
287
+ fieldMeta,
288
+ operator,
289
+ enumMap,
290
+ scalarBase
291
+ );
242
292
  }
243
293
  if (fieldMeta.isEnum) {
244
294
  const values = enumMap[fieldMeta.type];
@@ -246,7 +296,9 @@ function createOperatorSchema(fieldMeta, operator, enumMap, scalarBase) {
246
296
  throw new ShapeError(`Unknown enum: ${fieldMeta.type}`);
247
297
  }
248
298
  if (!ENUM_OPERATORS.has(operator)) {
249
- throw new ShapeError(`Operator "${operator}" not supported for enum fields`);
299
+ throw new ShapeError(
300
+ `Operator "${operator}" not supported for enum fields`
301
+ );
250
302
  }
251
303
  const enumSchema = z2.enum(values);
252
304
  if (operator === "equals" || operator === "not") {
@@ -260,24 +312,29 @@ function createOperatorSchema(fieldMeta, operator, enumMap, scalarBase) {
260
312
  throw new ShapeError(`Unknown scalar type for operator: ${fieldMeta.type}`);
261
313
  }
262
314
  if (supportedOps.size === 0) {
263
- throw new ShapeError(`Type "${fieldMeta.type}" does not support filter operators`);
315
+ throw new ShapeError(
316
+ `Type "${fieldMeta.type}" does not support filter operators`
317
+ );
264
318
  }
265
319
  if (!supportedOps.has(operator)) {
266
- throw new ShapeError(`Operator "${operator}" not supported for type "${fieldMeta.type}"`);
320
+ throw new ShapeError(
321
+ `Operator "${operator}" not supported for type "${fieldMeta.type}"`
322
+ );
267
323
  }
268
324
  const factory = scalarBase[fieldMeta.type];
269
325
  if (!factory) {
270
326
  throw new ShapeError(`Unknown scalar type: ${fieldMeta.type}`);
271
327
  }
272
328
  const scalar = factory();
329
+ const coerced = wrapWithInputCoercion(fieldMeta.type, false, scalar);
273
330
  if (operator === "equals" || operator === "not") {
274
- return !fieldMeta.isRequired ? z2.union([scalar, z2.null()]) : scalar;
331
+ return !fieldMeta.isRequired ? z2.union([coerced, z2.null()]) : coerced;
275
332
  }
276
333
  if (operator === "in" || operator === "notIn") {
277
- const itemSchema = !fieldMeta.isRequired ? z2.union([scalar, z2.null()]) : scalar;
334
+ const itemSchema = !fieldMeta.isRequired ? z2.union([coerced, z2.null()]) : coerced;
278
335
  return z2.preprocess(coerceToArray, z2.array(itemSchema));
279
336
  }
280
- return scalar;
337
+ return coerced;
281
338
  }
282
339
 
283
340
  // src/runtime/schema-builder.ts
@@ -327,6 +384,9 @@ function createSchemaBuilder(typeMap, zodChains, enumMap, scalarBase, zodDefault
327
384
  );
328
385
  }
329
386
  }
387
+ if (!fieldMeta.isEnum && !fieldMeta.isRelation && !fieldMeta.isUnsupported) {
388
+ result = wrapWithInputCoercion(fieldMeta.type, fieldMeta.isList, result);
389
+ }
330
390
  lruSet(chainCache, cacheKey, result, DEFAULT_MAX_CACHE);
331
391
  return result;
332
392
  }
@@ -359,9 +419,13 @@ function createSchemaBuilder(typeMap, zodChains, enumMap, scalarBase, zodDefault
359
419
  if (!modelFields[name])
360
420
  throw new ShapeError(`Unknown field "${name}" on model "${model}"`);
361
421
  if (modelFields[name].isRelation)
362
- throw new ShapeError(`Field "${name}" cannot be used in input schema (relation field)`);
422
+ throw new ShapeError(
423
+ `Field "${name}" cannot be used in input schema (relation field)`
424
+ );
363
425
  if (modelFields[name].isUpdatedAt)
364
- throw new ShapeError(`Field "${name}" cannot be used in input schema (updatedAt field)`);
426
+ throw new ShapeError(
427
+ `Field "${name}" cannot be used in input schema (updatedAt field)`
428
+ );
365
429
  }
366
430
  fieldNames = fieldNames.filter((n) => opts.pick.includes(n));
367
431
  } else if (opts.omit) {
@@ -435,7 +499,9 @@ function createSchemaBuilder(typeMap, zodChains, enumMap, scalarBase, zodDefault
435
499
  }
436
500
  const effectiveMaxDepth = maxDepth ?? opts.maxDepth ?? DEFAULT_MAX_DEPTH;
437
501
  if (depth > effectiveMaxDepth) {
438
- throw new ShapeError(`Maximum include depth (${effectiveMaxDepth}) exceeded`);
502
+ throw new ShapeError(
503
+ `Maximum include depth (${effectiveMaxDepth}) exceeded`
504
+ );
439
505
  }
440
506
  const modelFields = typeMap[model];
441
507
  if (!modelFields)
@@ -446,7 +512,9 @@ function createSchemaBuilder(typeMap, zodChains, enumMap, scalarBase, zodDefault
446
512
  if (!modelFields[name])
447
513
  throw new ShapeError(`Unknown field "${name}" on model "${model}"`);
448
514
  if (modelFields[name].isRelation && !includeKeys.has(name)) {
449
- throw new ShapeError(`Field "${name}" is a relation on model "${model}". Use include: { ${name}: ... } instead of pick.`);
515
+ throw new ShapeError(
516
+ `Field "${name}" is a relation on model "${model}". Use include: { ${name}: ... } instead of pick.`
517
+ );
450
518
  }
451
519
  }
452
520
  }
@@ -479,10 +547,14 @@ function createSchemaBuilder(typeMap, zodChains, enumMap, scalarBase, zodDefault
479
547
  if (!fieldMeta)
480
548
  throw new ShapeError(`Unknown field "${relName}" on model "${model}"`);
481
549
  if (!fieldMeta.isRelation)
482
- throw new ShapeError(`Field "${relName}" is not a relation on model "${model}"`);
550
+ throw new ShapeError(
551
+ `Field "${relName}" is not a relation on model "${model}"`
552
+ );
483
553
  const relatedModel = fieldMeta.type;
484
554
  if (!typeMap[relatedModel]) {
485
- throw new ShapeError(`Related model "${relatedModel}" not found in type map`);
555
+ throw new ShapeError(
556
+ `Related model "${relatedModel}" not found in type map`
557
+ );
486
558
  }
487
559
  let relSchema = buildModelSchema(
488
560
  relatedModel,
@@ -511,11 +583,17 @@ function createSchemaBuilder(typeMap, zodChains, enumMap, scalarBase, zodDefault
511
583
  const countFields = {};
512
584
  for (const relName of Object.keys(opts._count)) {
513
585
  if (!modelFields[relName])
514
- throw new ShapeError(`Unknown field "${relName}" on model "${model}" in _count`);
586
+ throw new ShapeError(
587
+ `Unknown field "${relName}" on model "${model}" in _count`
588
+ );
515
589
  if (!modelFields[relName].isRelation)
516
- throw new ShapeError(`Field "${relName}" is not a relation on model "${model}" in _count`);
590
+ throw new ShapeError(
591
+ `Field "${relName}" is not a relation on model "${model}" in _count`
592
+ );
517
593
  if (!modelFields[relName].isList)
518
- throw new ShapeError(`Field "${relName}" is a to-one relation on model "${model}" in _count. Only to-many relations support _count.`);
594
+ throw new ShapeError(
595
+ `Field "${relName}" is a to-one relation on model "${model}" in _count. Only to-many relations support _count.`
596
+ );
519
597
  countFields[relName] = z3.number().int().min(0);
520
598
  }
521
599
  schemaMap["_count"] = z3.object(countFields);
@@ -527,7 +605,12 @@ function createSchemaBuilder(typeMap, zodChains, enumMap, scalarBase, zodDefault
527
605
  }
528
606
  return schema;
529
607
  }
530
- return { buildFieldSchema, buildBaseFieldSchema, buildInputSchema, buildModelSchema };
608
+ return {
609
+ buildFieldSchema,
610
+ buildBaseFieldSchema,
611
+ buildInputSchema,
612
+ buildModelSchema
613
+ };
531
614
  }
532
615
 
533
616
  // src/runtime/query-builder.ts
@@ -573,6 +656,15 @@ function force(value) {
573
656
  wrapper[FORCED_MARKER] = true;
574
657
  return wrapper;
575
658
  }
659
+ var UNSUPPORTED_MARKER = Symbol.for("prisma-guard.unsupported");
660
+ function isUnsupportedMarker(v) {
661
+ return v !== null && typeof v === "object" && v[UNSUPPORTED_MARKER] === true;
662
+ }
663
+ function unsupported() {
664
+ const marker = {};
665
+ marker[UNSUPPORTED_MARKER] = true;
666
+ return marker;
667
+ }
576
668
 
577
669
  // src/shared/match-caller.ts
578
670
  function matchCallerPattern(patterns, caller) {
@@ -3159,31 +3251,6 @@ function buildRelationWriteSchema(model, fieldName, relatedModelName, isList, co
3159
3251
  );
3160
3252
  }
3161
3253
  }
3162
- if (config.delete !== void 0) {
3163
- if (config.delete === true) {
3164
- if (isList) {
3165
- throw new ShapeError(
3166
- `delete on to-many relation "${model}.${fieldName}" requires field config, not true`
3167
- );
3168
- }
3169
- opSchemas["delete"] = z8.literal(true).optional();
3170
- } else if (isPlainObject(config.delete)) {
3171
- const deleteSchema = buildWhereFieldsSchema(
3172
- relatedModelName,
3173
- config.delete,
3174
- typeMap,
3175
- schemaBuilder
3176
- );
3177
- opSchemas["delete"] = isList ? z8.union([
3178
- deleteSchema,
3179
- z8.preprocess(coerceToArray, z8.array(deleteSchema))
3180
- ]).optional() : deleteSchema.optional();
3181
- } else {
3182
- throw new ShapeError(
3183
- `delete config on "${model}.${fieldName}" must be true (to-one) or an object of field names`
3184
- );
3185
- }
3186
- }
3187
3254
  if (config.set !== void 0) {
3188
3255
  if (!isList) {
3189
3256
  throw new ShapeError(
@@ -3390,8 +3457,13 @@ function buildDataSchema(model, dataConfig, mode, typeMap, schemaBuilder, zodDef
3390
3457
  const forced = {};
3391
3458
  for (const [fieldName, value] of Object.entries(dataConfig)) {
3392
3459
  const fieldMeta = modelFields[fieldName];
3393
- if (!fieldMeta)
3460
+ if (!fieldMeta) {
3461
+ if (isUnsupportedMarker(value)) {
3462
+ schemaMap[fieldName] = z8.unknown().optional();
3463
+ continue;
3464
+ }
3394
3465
  throw new ShapeError(`Unknown field "${fieldName}" on model "${model}"`);
3466
+ }
3395
3467
  if (fieldMeta.isRelation) {
3396
3468
  if (!isPlainObject(value)) {
3397
3469
  throw new ShapeError(
@@ -4599,6 +4671,7 @@ export {
4599
4671
  PolicyError,
4600
4672
  ShapeError,
4601
4673
  createGuard,
4602
- force
4674
+ force,
4675
+ unsupported
4603
4676
  };
4604
4677
  //# sourceMappingURL=index.js.map