@@ -4,17 +4,18 @@ import stableStringify from 'json-stable-stringify';
44import { match , P } from 'ts-pattern' ;
55import { z , ZodSchema , ZodType } from 'zod' ;
66import {
7+ type AttributeApplication ,
78 type BuiltinType ,
89 type EnumDef ,
910 type FieldDef ,
1011 type GetModels ,
1112 type ModelDef ,
1213 type SchemaDef ,
13- } from '../../schema' ;
14- import { enumerate } from '../../utils/enumerate' ;
15- import { extractFields } from '../../utils/object-utils' ;
16- import { formatError } from '../../utils/zod-utils' ;
17- import { AGGREGATE_OPERATORS , LOGICAL_COMBINATORS , NUMERIC_FIELD_TYPES } from '../constants' ;
14+ } from '../../../ schema' ;
15+ import { enumerate } from '../../../ utils/enumerate' ;
16+ import { extractFields } from '../../../ utils/object-utils' ;
17+ import { formatError } from '../../../ utils/zod-utils' ;
18+ import { AGGREGATE_OPERATORS , LOGICAL_COMBINATORS , NUMERIC_FIELD_TYPES } from '../../ constants' ;
1819import {
1920 type AggregateArgs ,
2021 type CountArgs ,
@@ -29,16 +30,23 @@ import {
2930 type UpdateManyAndReturnArgs ,
3031 type UpdateManyArgs ,
3132 type UpsertArgs ,
32- } from '../crud-types' ;
33- import { InputValidationError , InternalError } from '../errors' ;
33+ } from '../../ crud-types' ;
34+ import { InputValidationError , InternalError } from '../../ errors' ;
3435import {
3536 fieldHasDefaultValue ,
3637 getDiscriminatorField ,
3738 getEnum ,
3839 getUniqueFields ,
3940 requireField ,
4041 requireModel ,
41- } from '../query-utils' ;
42+ } from '../../query-utils' ;
43+ import {
44+ addBigIntValidation ,
45+ addCustomValidation ,
46+ addDecimalValidation ,
47+ addNumberValidation ,
48+ addStringValidation ,
49+ } from './utils' ;
4250
4351type GetSchemaFunc < Schema extends SchemaDef , Options > = ( model : GetModels < Schema > , options : Options ) => ZodType ;
4452
@@ -191,11 +199,14 @@ export class InputValidator<Schema extends SchemaDef> {
191199 schema = getSchema ( model , options ) ;
192200 this . schemaCache . set ( cacheKey ! , schema ) ;
193201 }
194- const { error } = schema . safeParse ( args ) ;
202+ const { error, data } = schema . safeParse ( args ) ;
195203 if ( error ) {
196- throw new InputValidationError ( `Invalid ${ operation } args: ${ formatError ( error ) } ` , error ) ;
204+ throw new InputValidationError (
205+ `Invalid ${ operation } args for model "${ model } ": ${ formatError ( error ) } ` ,
206+ error ,
207+ ) ;
197208 }
198- return args as T ;
209+ return data as T ;
199210 }
200211
201212 // #region Find
@@ -235,17 +246,28 @@ export class InputValidator<Schema extends SchemaDef> {
235246 return result ;
236247 }
237248
238- private makePrimitiveSchema ( type : string ) {
249+ private makePrimitiveSchema ( type : string , attributes ?: AttributeApplication [ ] ) {
239250 if ( this . schema . typeDefs && type in this . schema . typeDefs ) {
240251 return this . makeTypeDefSchema ( type ) ;
241252 } else {
242253 return match ( type )
243- . with ( 'String' , ( ) => z . string ( ) )
244- . with ( 'Int' , ( ) => z . number ( ) . int ( ) )
245- . with ( 'Float' , ( ) => z . number ( ) )
254+ . with ( 'String' , ( ) => addStringValidation ( z . string ( ) , attributes ) )
255+ . with ( 'Int' , ( ) => addNumberValidation ( z . number ( ) . int ( ) , attributes ) )
256+ . with ( 'Float' , ( ) => addNumberValidation ( z . number ( ) , attributes ) )
246257 . with ( 'Boolean' , ( ) => z . boolean ( ) )
247- . with ( 'BigInt' , ( ) => z . union ( [ z . number ( ) . int ( ) , z . bigint ( ) ] ) )
248- . with ( 'Decimal' , ( ) => z . union ( [ z . number ( ) , z . instanceof ( Decimal ) , z . string ( ) ] ) )
258+ . with ( 'BigInt' , ( ) =>
259+ z . union ( [
260+ addNumberValidation ( z . number ( ) . int ( ) , attributes ) ,
261+ addBigIntValidation ( z . bigint ( ) , attributes ) ,
262+ ] ) ,
263+ )
264+ . with ( 'Decimal' , ( ) =>
265+ z . union ( [
266+ addNumberValidation ( z . number ( ) , attributes ) ,
267+ addDecimalValidation ( z . instanceof ( Decimal ) , attributes ) ,
268+ addDecimalValidation ( z . string ( ) , attributes ) ,
269+ ] ) ,
270+ )
249271 . with ( 'DateTime' , ( ) => z . union ( [ z . date ( ) , z . string ( ) . datetime ( ) ] ) )
250272 . with ( 'Bytes' , ( ) => z . instanceof ( Uint8Array ) )
251273 . otherwise ( ( ) => z . unknown ( ) ) ;
@@ -860,7 +882,7 @@ export class InputValidator<Schema extends SchemaDef> {
860882 uncheckedVariantFields [ field ] = fieldSchema ;
861883 }
862884 } else {
863- let fieldSchema : ZodType = this . makePrimitiveSchema ( fieldDef . type ) ;
885+ let fieldSchema : ZodType = this . makePrimitiveSchema ( fieldDef . type , fieldDef . attributes ) ;
864886
865887 if ( fieldDef . array ) {
866888 fieldSchema = z
@@ -889,14 +911,17 @@ export class InputValidator<Schema extends SchemaDef> {
889911 }
890912 } ) ;
891913
914+ const uncheckedCreateSchema = addCustomValidation ( z . strictObject ( uncheckedVariantFields ) , modelDef . attributes ) ;
915+ const checkedCreateSchema = addCustomValidation ( z . strictObject ( checkedVariantFields ) , modelDef . attributes ) ;
916+
892917 if ( ! hasRelation ) {
893- return this . orArray ( z . strictObject ( uncheckedVariantFields ) , canBeArray ) ;
918+ return this . orArray ( uncheckedCreateSchema , canBeArray ) ;
894919 } else {
895920 return z . union ( [
896- z . strictObject ( uncheckedVariantFields ) ,
897- z . strictObject ( checkedVariantFields ) ,
898- ...( canBeArray ? [ z . array ( z . strictObject ( uncheckedVariantFields ) ) ] : [ ] ) ,
899- ...( canBeArray ? [ z . array ( z . strictObject ( checkedVariantFields ) ) ] : [ ] ) ,
921+ uncheckedCreateSchema ,
922+ checkedCreateSchema ,
923+ ...( canBeArray ? [ z . array ( uncheckedCreateSchema ) ] : [ ] ) ,
924+ ...( canBeArray ? [ z . array ( checkedCreateSchema ) ] : [ ] ) ,
900925 ] ) ;
901926 }
902927 }
@@ -1112,7 +1137,7 @@ export class InputValidator<Schema extends SchemaDef> {
11121137 uncheckedVariantFields [ field ] = fieldSchema ;
11131138 }
11141139 } else {
1115- let fieldSchema : ZodType = this . makePrimitiveSchema ( fieldDef . type ) . optional ( ) ;
1140+ let fieldSchema : ZodType = this . makePrimitiveSchema ( fieldDef . type , fieldDef . attributes ) . optional ( ) ;
11161141
11171142 if ( this . isNumericField ( fieldDef ) ) {
11181143 fieldSchema = z . union ( [
@@ -1161,10 +1186,12 @@ export class InputValidator<Schema extends SchemaDef> {
11611186 }
11621187 } ) ;
11631188
1189+ const uncheckedUpdateSchema = addCustomValidation ( z . strictObject ( uncheckedVariantFields ) , modelDef . attributes ) ;
1190+ const checkedUpdateSchema = addCustomValidation ( z . strictObject ( checkedVariantFields ) , modelDef . attributes ) ;
11641191 if ( ! hasRelation ) {
1165- return z . strictObject ( uncheckedVariantFields ) ;
1192+ return uncheckedUpdateSchema ;
11661193 } else {
1167- return z . union ( [ z . strictObject ( uncheckedVariantFields ) , z . strictObject ( checkedVariantFields ) ] ) ;
1194+ return z . union ( [ uncheckedUpdateSchema , checkedUpdateSchema ] ) ;
11681195 }
11691196 }
11701197
0 commit comments