66
77import type { ZodTypeAny } from 'zod'
88
9- import { isZodObject } from './zod.js'
9+ import {
10+ isZodArray ,
11+ isZodBoolean ,
12+ isZodNumber ,
13+ isZodObject ,
14+ isZodSchema ,
15+ isZodString ,
16+ } from './zod.js'
1017
1118type ValueType =
1219 | 'string'
@@ -23,15 +30,51 @@ interface ParamSchema {
2330export const zodSchemaToParamSchema = ( schema : ZodTypeAny ) : ParamSchema => {
2431 if ( ! isZodObject ( schema ) ) {
2532 throw new UnparseableSchemaError (
33+ [ ] ,
2634 'top level schema must be an object schema' ,
2735 )
2836 }
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` )
3072}
3173
3274export 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 } ` )
3578 this . name = this . constructor . name
3679 }
3780}
0 commit comments