@@ -7,35 +7,105 @@ export const parseSchema = (
77 schema : OpenAPIV3 . SchemaObject | OpenAPIV3 . ReferenceObject ,
88) : string => {
99 const parsed = refToObject ( docs , schema ) ;
10- const nullable = parsed . nullable ? ' | null' : '' ;
10+ const { ofType , nullable } = parseOf ( docs , parsed ) ;
1111
12- if ( parsed . enum ?. length ) {
13- return `${ parsed . enum . map ( ( item ) => ( typeof item === 'number' ? item : `"${ item } "` ) ) . join ( ' | ' ) } ${ nullable } ` ;
14- }
12+ if ( ofType ) return `(${ ofType } ${ nullable } )` ;
1513
16- if ( parsed . oneOf ) {
17- return parsed . oneOf . map ( ( schema ) => parseSchema ( docs , schema ) ) . join ( ' | ' ) ;
14+ if ( parsed . enum ?. length ) {
15+ return `( ${ parsed . enum . map ( ( item ) => ( typeof item === 'number' ? item : `" ${ item } "` ) ) . join ( ' | ' ) } ${ nullable } )` ;
1816 }
1917
2018 switch ( parsed . type ) {
21- case 'array' :
22- return `(${ parseSchema ( docs , parsed . items ) } )[]${ nullable } ` ;
2319 case 'boolean' :
24- return `boolean${ nullable } ` ;
20+ return `( boolean${ nullable } ) ` ;
2521 case 'integer' :
2622 case 'number' :
27- return `number${ nullable } ` ;
28- case 'object' :
23+ return `(number${ nullable } )` ;
24+ case 'string' :
25+ if ( parsed . format === 'binary' ) return `(Blob${ nullable } )` ;
26+ return `(string${ nullable } )` ;
27+ case 'array' :
28+ return `((${ parseSchema ( docs , parsed . items ) } )[]${ nullable } )` ;
29+ case 'object' : {
2930 const requiredProperties = parsed . required || [ ] ;
3031 const properties = Object . entries ( parsed . properties || { } ) . map ( ( [ key , schema ] ) => {
3132 const schemaObj = refToObject ( docs , schema ) ;
3233 return `${ generateComments ( schemaObj ) } ${ key } ${ requiredProperties . includes ( key ) ? '' : '?' } : ${ parseSchema ( docs , schemaObj ) } ` ;
3334 } ) ;
34- return `{ ${ properties . join ( ';' ) } }${ nullable } ` ;
35- case 'string' :
36- if ( parsed . format === 'binary' ) return `Blob${ nullable } ` ;
37- return `string${ nullable } ` ;
35+ return `({ ${ properties . join ( ';' ) } }${ nullable } )` ;
36+ }
37+ default :
38+ return 'unknown' ;
39+ }
40+ } ;
41+
42+ const parseOf = (
43+ docs : OpenAPIV3 . Document ,
44+ schema : OpenAPIV3 . SchemaObject ,
45+ ) : { nullable : string ; ofType : string } => {
46+ if ( ! schema . oneOf ?. length && ! schema . anyOf ?. length && ! schema . allOf ?. length ) {
47+ return {
48+ nullable : schema . nullable ? ' | null' : '' ,
49+ ofType : '' ,
50+ } ;
51+ }
52+
53+ const { oneOf = [ ] , anyOf = [ ] , allOf = [ ] , nullable = false , ...rest } = schema ;
54+ const oneTypes = new Set < string > ( ) ;
55+ const anyTypes = new Set < string > ( ) ;
56+ const allTypes = new Set < string > ( ) ;
57+
58+ const nullableSet = new Set < boolean > (
59+ oneOf
60+ . concat ( anyOf )
61+ . concat ( allOf )
62+ . map ( ( item ) => {
63+ const { nullable : itemNullable } = refToObject ( docs , item ) ;
64+ if ( itemNullable !== undefined ) return itemNullable ;
65+ return nullable ;
66+ } ) ,
67+ ) ;
68+ const additionalMergeOpts = nullableSet . size > 1 ? { nullable } : { } ;
69+
70+ for ( const one of oneOf ) {
71+ oneTypes . add (
72+ parseSchema ( docs , { ...rest , ...additionalMergeOpts , ...refToObject ( docs , one ) } ) ,
73+ ) ;
74+ }
75+
76+ for ( const any of anyOf ) {
77+ anyTypes . add (
78+ parseSchema ( docs , { ...rest , ...additionalMergeOpts , ...refToObject ( docs , any ) } ) ,
79+ ) ;
80+ }
81+
82+ for ( const all of allOf ) {
83+ allTypes . add (
84+ parseSchema ( docs , { ...rest , ...additionalMergeOpts , ...refToObject ( docs , all ) } ) ,
85+ ) ;
86+ }
87+
88+ let oneType = oneTypes . size ? `(${ [ ...oneTypes ] . join ( ' | ' ) } )` : '' ;
89+ let anyType = anyTypes . size ? `(${ [ ...anyTypes ] . join ( ' | ' ) } )` : '' ;
90+ let allType = allTypes . size ? `(${ [ ...allTypes ] . join ( ' & ' ) } )` : '' ;
91+
92+ if ( oneType && oneType === anyType ) anyType = '' ;
93+ if ( oneType && oneType === allType ) {
94+ allType = '' ;
95+ anyType = '' ;
96+ } else if ( anyType && anyType === allType ) {
97+ allType = '' ;
98+ oneType = '' ;
3899 }
39100
40- return 'unknown' ;
101+ let unionType = [ oneType , anyType ] . filter ( Boolean ) . join ( ' | ' ) ;
102+ if ( unionType ) unionType = `(${ unionType } )` ;
103+
104+ let finalType = [ unionType , allType ] . filter ( Boolean ) . join ( ' & ' ) ;
105+ if ( finalType ) finalType = `(${ finalType } )` ;
106+
107+ return {
108+ nullable : nullableSet . size === 1 && [ ...nullableSet ] [ 0 ] === true ? ' | null' : '' ,
109+ ofType : finalType ,
110+ } ;
41111} ;
0 commit comments