@@ -8,7 +8,7 @@ import { findSymbolInitializer } from './resolveInit';
88import { errorLeft } from './error' ;
99
1010export type Parameter = {
11- type : 'path' | 'query' ;
11+ type : 'path' | 'query' | 'header' ;
1212 name : string ;
1313 schema : Schema ;
1414 explode ?: boolean ;
@@ -84,6 +84,22 @@ function parseRequestObject(schema: Schema): E.Either<string, Request> {
8484 }
8585 }
8686
87+ const headerSchema = schema . properties [ 'headers' ] ;
88+ if ( headerSchema !== undefined ) {
89+ if ( headerSchema . type !== 'object' ) {
90+ return errorLeft ( 'Route headers must be an object' ) ;
91+ } else {
92+ for ( const [ name , prop ] of Object . entries ( headerSchema . properties ) ) {
93+ parameters . push ( {
94+ type : 'header' ,
95+ name,
96+ schema : prop ,
97+ required : headerSchema . required . includes ( name ) ,
98+ } ) ;
99+ }
100+ }
101+ }
102+
87103 return E . right ( {
88104 parameters,
89105 body : schema . properties [ 'body' ] ,
@@ -103,6 +119,7 @@ function parseRequestUnion(
103119 // This isn't perfect but it's about as good as we can do in openapi
104120 const parameters : Parameter [ ] = [ ] ;
105121 const querySchema : Schema = { type : 'union' , schemas : [ ] } ;
122+ const headerSchema : Schema = { type : 'union' , schemas : [ ] } ;
106123 let body : Schema | undefined ;
107124
108125 for ( let subSchema of schema . schemas ) {
@@ -126,6 +143,9 @@ function parseRequestUnion(
126143 }
127144 ( body as CombinedType ) . schemas . push ( subSchema . properties [ 'body' ] ) ;
128145 }
146+ if ( subSchema . properties [ 'headers' ] !== undefined ) {
147+ headerSchema . schemas . push ( subSchema . properties [ 'headers' ] ) ;
148+ }
129149 }
130150 if ( querySchema . schemas . length > 0 ) {
131151 parameters . push ( {
@@ -136,6 +156,15 @@ function parseRequestUnion(
136156 schema : querySchema ,
137157 } ) ;
138158 }
159+ if ( headerSchema . schemas . length > 0 ) {
160+ parameters . push ( {
161+ type : 'header' ,
162+ name : 'union' ,
163+ explode : true ,
164+ required : true ,
165+ schema : headerSchema ,
166+ } ) ;
167+ }
139168
140169 const firstSubSchema = schema . schemas [ 0 ] ;
141170 if ( firstSubSchema !== undefined && firstSubSchema . type === 'object' ) {
@@ -203,28 +232,42 @@ function parseRequestSchema(
203232 }
204233}
205234
235+ export function resolveStringProperty (
236+ project : Project ,
237+ schema : Schema | undefined ,
238+ name : string ,
239+ ) : E . Either < string , string > {
240+ if ( schema === undefined ) {
241+ return errorLeft ( `Route ${ name } is missing` ) ;
242+ } else if ( schema . type === 'ref' ) {
243+ const derefE = derefRequestSchema ( project , schema ) ;
244+ if ( E . isLeft ( derefE ) ) {
245+ return derefE ;
246+ }
247+ return resolveStringProperty ( project , derefE . right , name ) ;
248+ } else if ( schema . type === 'string' && schema . enum ?. length === 1 ) {
249+ return E . right ( schema . enum [ 0 ] ! as string ) ;
250+ } else {
251+ return errorLeft ( `Route ${ name } must be a string literal` ) ;
252+ }
253+ }
254+
206255export function parseRoute ( project : Project , schema : Schema ) : E . Either < string , Route > {
207256 if ( schema . type !== 'object' ) {
208257 return errorLeft ( 'Route must be an object' ) ;
209258 }
210259
211- if ( schema . properties [ 'path' ] === undefined ) {
212- return errorLeft ( 'Route must have a path' ) ;
213- } else if (
214- schema . properties [ 'path' ] . type !== 'string' ||
215- schema . properties [ 'path' ] . enum ?. length !== 1
216- ) {
217- return errorLeft ( 'Route path must be a string literal' ) ;
260+ const pathE = resolveStringProperty ( project , schema . properties [ 'path' ] , 'path' ) ;
261+ if ( E . isLeft ( pathE ) ) {
262+ return pathE ;
218263 }
264+ const path = pathE . right ;
219265
220- if ( schema . properties [ 'method' ] === undefined ) {
221- return errorLeft ( 'Route must have a method' ) ;
222- } else if (
223- schema . properties [ 'method' ] . type !== 'string' ||
224- schema . properties [ 'method' ] . enum ?. length !== 1
225- ) {
226- return errorLeft ( 'Route method must be a string literal' ) ;
266+ const methodE = resolveStringProperty ( project , schema . properties [ 'method' ] , 'method' ) ;
267+ if ( E . isLeft ( methodE ) ) {
268+ return methodE ;
227269 }
270+ const method = methodE . right ;
228271
229272 const requestSchema = schema . properties [ 'request' ] ;
230273 if ( requestSchema === undefined ) {
@@ -243,8 +286,8 @@ export function parseRoute(project: Project, schema: Schema): E.Either<string, R
243286 }
244287
245288 return E . right ( {
246- path : schema . properties [ 'path' ] . enum ! [ 0 ] as string ,
247- method : schema . properties [ 'method' ] . enum ! [ 0 ] as string ,
289+ path,
290+ method,
248291 parameters,
249292 response : schema . properties [ 'response' ] . properties ,
250293 ...( body !== undefined ? { body } : { } ) ,
0 commit comments