@@ -9,19 +9,62 @@ import {
9
9
ZodObject ,
10
10
ZodEffects ,
11
11
ZodOptional ,
12
+ ZodNullable ,
13
+ ZodType ,
12
14
} from 'zod' ;
13
15
14
16
import { Entity } from '../../../types' ;
15
- import { FieldWithType , TypeField } from '../../orm' ;
17
+ import {
18
+ FieldWithType ,
19
+ PropsFieldItem ,
20
+ PropsForField ,
21
+ TypeField ,
22
+ } from '../../orm' ;
16
23
import { ObjectTyped } from '../../utils' ;
17
24
import { nonEmptyObject } from '../zod-utils' ;
18
25
26
+ const literalSchema = z . union ( [ z . string ( ) , z . number ( ) , z . boolean ( ) ] ) ;
27
+
28
+ const getZodSchemaForJson = ( isNull : boolean ) => {
29
+ const tmpSchema = isNull ? literalSchema . nullable ( ) : literalSchema ;
30
+ const jsonSchema : any = z . lazy ( ( ) =>
31
+ z . union ( [
32
+ tmpSchema ,
33
+ z . array ( jsonSchema . nullable ( ) ) ,
34
+ z . record ( jsonSchema . nullable ( ) ) ,
35
+ ] )
36
+ ) ;
37
+
38
+ return jsonSchema ;
39
+ } ;
40
+
41
+ type Literal = ReturnType < typeof getZodSchemaForJson > ;
42
+
43
+ type Json = Literal | { [ key : string ] : Json } | Json [ ] ;
44
+
45
+ type ZodTypeForArray =
46
+ | ZodString
47
+ | ZodDate
48
+ | ZodEffects < ZodNumber , number , unknown >
49
+ | ZodBoolean ;
50
+ type ZodArrayType =
51
+ | ZodArray < ZodTypeForArray , 'many' >
52
+ | ZodNullable < ZodArray < ZodTypeForArray , 'many' > > ;
53
+
19
54
type TypeMapToZod = {
20
- [ TypeField . array ] : ZodOptional < ZodArray < ZodString , 'many' > > ;
21
- [ TypeField . date ] : ZodOptional < ZodDate > ;
22
- [ TypeField . number ] : ZodOptional < ZodNumber > ;
23
- [ TypeField . boolean ] : ZodOptional < ZodBoolean > ;
24
- [ TypeField . string ] : ZodOptional < ZodString | ZodEnum < [ string , ...string [ ] ] > > ;
55
+ [ TypeField . array ] : ZodOptional < ZodArrayType > ;
56
+ [ TypeField . date ] : ZodOptional < ZodDate | ZodNullable < ZodDate > > ;
57
+ [ TypeField . number ] : ZodOptional <
58
+ | ZodEffects < ZodNumber , number , unknown >
59
+ | ZodNullable < ZodEffects < ZodNumber , number , unknown > >
60
+ > ;
61
+ [ TypeField . boolean ] : ZodOptional < ZodBoolean | ZodNullable < ZodBoolean > > ;
62
+ [ TypeField . string ] : ZodOptional <
63
+ | ZodString
64
+ | ZodEnum < [ string , ...string [ ] ] >
65
+ | ZodNullable < ZodString | ZodEnum < [ string , ...string [ ] ] > >
66
+ > ;
67
+ [ TypeField . object ] : ZodType < Json > | ZodNullable < ZodType < Json > > ;
25
68
} ;
26
69
27
70
type ZodShapeAttributes < E extends Entity > = Omit <
@@ -35,28 +78,92 @@ export type ZodAttributesSchema<E extends Entity> = ZodEffects<
35
78
ZodObject < ZodShapeAttributes < E > , 'strict' >
36
79
> ;
37
80
81
+ function getZodSchemaForArray ( props : PropsFieldItem ) : ZodTypeForArray {
82
+ if ( ! props ) return z . string ( ) ;
83
+ let zodSchema : ZodTypeForArray ;
84
+ switch ( props . type ) {
85
+ case 'number' :
86
+ case 'real' :
87
+ case 'integer' :
88
+ case 'bigint' :
89
+ case 'double' :
90
+ case 'numeric' :
91
+ case Number :
92
+ zodSchema = z . preprocess ( ( x ) => Number ( x ) , z . number ( ) ) ;
93
+ break ;
94
+ case 'date' :
95
+ case Date :
96
+ zodSchema = z . coerce . date ( ) ;
97
+ break ;
98
+ case 'boolean' :
99
+ case Boolean :
100
+ zodSchema = z . boolean ( ) ;
101
+ break ;
102
+ default :
103
+ zodSchema = z . string ( ) ;
104
+ }
105
+
106
+ return zodSchema ;
107
+ }
108
+
38
109
export const zodAttributesSchema = < E extends Entity > (
39
- fieldWithType : FieldWithType < E >
110
+ fieldWithType : FieldWithType < E > ,
111
+ propsDb : PropsForField < E >
40
112
) : ZodAttributesSchema < E > => {
41
113
const shape = ObjectTyped . entries ( fieldWithType ) . reduce (
42
114
( acum , [ props , type ] : [ keyof FieldWithType < E > , TypeField ] ) => {
43
115
let zodShema : TypeMapToZod [ typeof type ] ;
116
+ const propsDbType = propsDb [ props ] ;
44
117
switch ( type ) {
45
- case TypeField . array :
46
- zodShema = z . string ( ) . array ( ) . optional ( ) ;
118
+ case TypeField . array : {
119
+ const tmpSchema = getZodSchemaForArray ( propsDbType ) . array ( ) ;
120
+ zodShema = (
121
+ propsDbType && propsDbType . isNullable
122
+ ? tmpSchema . nullable ( )
123
+ : tmpSchema
124
+ ) . optional ( ) ;
125
+ break ;
126
+ }
127
+ case TypeField . date : {
128
+ const tmpSchema = z . coerce . date ( ) ;
129
+ zodShema = (
130
+ propsDbType && propsDbType . isNullable
131
+ ? tmpSchema . nullable ( )
132
+ : tmpSchema
133
+ ) . optional ( ) ;
47
134
break ;
48
- case TypeField . date :
49
- zodShema = z . coerce . date ( ) . optional ( ) ;
135
+ }
136
+ case TypeField . number : {
137
+ const tmpSchema = z . preprocess ( ( x ) => Number ( x ) , z . number ( ) ) ;
138
+ zodShema = (
139
+ propsDbType && propsDbType . isNullable
140
+ ? tmpSchema . nullable ( )
141
+ : tmpSchema
142
+ ) . optional ( ) ;
50
143
break ;
51
- case TypeField . number :
52
- zodShema = z . number ( ) . optional ( ) ;
144
+ }
145
+ case TypeField . boolean : {
146
+ const tmpSchema = z . boolean ( ) ;
147
+ zodShema = (
148
+ propsDbType && propsDbType . isNullable
149
+ ? tmpSchema . nullable ( )
150
+ : tmpSchema
151
+ ) . optional ( ) ;
53
152
break ;
54
- case TypeField . boolean :
55
- zodShema = z . boolean ( ) . optional ( ) ;
153
+ }
154
+ case TypeField . object : {
155
+ zodShema = getZodSchemaForJson ( propsDbType . isNullable ) . optional ( ) ;
56
156
break ;
57
- case TypeField . string :
58
- zodShema = z . string ( ) . optional ( ) ;
157
+ }
158
+ case TypeField . string : {
159
+ const tmpSchema = z . string ( ) ;
160
+ zodShema = (
161
+ propsDbType && propsDbType . isNullable
162
+ ? tmpSchema . nullable ( )
163
+ : tmpSchema
164
+ ) . optional ( ) ;
59
165
break ;
166
+ }
60
167
}
61
168
62
169
return {
0 commit comments