6
6
7
7
import type { ZodTypeAny } from 'zod'
8
8
9
- import { isZodObject } from './zod.js'
9
+ import {
10
+ isZodArray ,
11
+ isZodBoolean ,
12
+ isZodNumber ,
13
+ isZodObject ,
14
+ isZodSchema ,
15
+ isZodString ,
16
+ } from './zod.js'
10
17
11
18
type ValueType =
12
19
| 'string'
@@ -23,15 +30,51 @@ interface ParamSchema {
23
30
export const zodSchemaToParamSchema = ( schema : ZodTypeAny ) : ParamSchema => {
24
31
if ( ! isZodObject ( schema ) ) {
25
32
throw new UnparseableSchemaError (
33
+ [ ] ,
26
34
'top level schema must be an object schema' ,
27
35
)
28
36
}
29
- return { }
37
+ const paramSchema = nestedZodSchemaToParamSchema ( schema , [ ] )
38
+ if ( typeof paramSchema === 'string' ) {
39
+ throw new Error ( 'Expected ParamSchema not ValueType' )
40
+ }
41
+ return paramSchema
42
+ }
43
+
44
+ const nestedZodSchemaToParamSchema = (
45
+ schema : ZodTypeAny ,
46
+ path : string [ ] ,
47
+ ) : ParamSchema | ValueType => {
48
+ if ( isZodObject ( schema ) ) {
49
+ const shape = schema . shape as unknown as Record < string , unknown >
50
+ const entries = Object . entries ( shape ) . reduce <
51
+ Array < [ string , ParamSchema | ValueType ] >
52
+ > ( ( acc , entry ) => {
53
+ const [ k , v ] = entry
54
+ const currentPath = [ ...path , k ]
55
+ if ( isZodSchema ( v ) ) {
56
+ return [ ...acc , [ k , nestedZodSchemaToParamSchema ( v , currentPath ) ] ]
57
+ }
58
+ throw new UnparseableSchemaError ( currentPath , 'unexpected non-zod schema' )
59
+ } , [ ] )
60
+ return Object . fromEntries ( entries )
61
+ }
62
+
63
+ if ( isZodNumber ( schema ) ) return 'number'
64
+ if ( isZodString ( schema ) ) return 'string'
65
+ if ( isZodBoolean ( schema ) ) return 'boolean'
66
+ if ( isZodArray ( schema ) ) {
67
+ // TODO: handle number_array
68
+ return 'string_array'
69
+ }
70
+
71
+ throw new UnparseableSchemaError ( path , `schema type is not supported` )
30
72
}
31
73
32
74
export class UnparseableSchemaError extends Error {
33
- constructor ( message : string ) {
34
- super ( `Could not parse Zod schema: ${ message } ` )
75
+ constructor ( path : string [ ] , message : string ) {
76
+ const part = path . length === 0 ? '' : ` at ${ path . join ( '.' ) } `
77
+ super ( `Could not parse Zod schema${ part } : ${ message } ` )
35
78
this . name = this . constructor . name
36
79
}
37
80
}
0 commit comments