@@ -8,7 +8,7 @@ import { findSymbolInitializer } from './resolveInit';
8
8
import { errorLeft } from './error' ;
9
9
10
10
export type Parameter = {
11
- type : 'path' | 'query' ;
11
+ type : 'path' | 'query' | 'header' ;
12
12
name : string ;
13
13
schema : Schema ;
14
14
explode ?: boolean ;
@@ -84,6 +84,22 @@ function parseRequestObject(schema: Schema): E.Either<string, Request> {
84
84
}
85
85
}
86
86
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
+
87
103
return E . right ( {
88
104
parameters,
89
105
body : schema . properties [ 'body' ] ,
@@ -103,6 +119,7 @@ function parseRequestUnion(
103
119
// This isn't perfect but it's about as good as we can do in openapi
104
120
const parameters : Parameter [ ] = [ ] ;
105
121
const querySchema : Schema = { type : 'union' , schemas : [ ] } ;
122
+ const headerSchema : Schema = { type : 'union' , schemas : [ ] } ;
106
123
let body : Schema | undefined ;
107
124
108
125
for ( let subSchema of schema . schemas ) {
@@ -126,6 +143,9 @@ function parseRequestUnion(
126
143
}
127
144
( body as CombinedType ) . schemas . push ( subSchema . properties [ 'body' ] ) ;
128
145
}
146
+ if ( subSchema . properties [ 'headers' ] !== undefined ) {
147
+ headerSchema . schemas . push ( subSchema . properties [ 'headers' ] ) ;
148
+ }
129
149
}
130
150
if ( querySchema . schemas . length > 0 ) {
131
151
parameters . push ( {
@@ -136,6 +156,15 @@ function parseRequestUnion(
136
156
schema : querySchema ,
137
157
} ) ;
138
158
}
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
+ }
139
168
140
169
const firstSubSchema = schema . schemas [ 0 ] ;
141
170
if ( firstSubSchema !== undefined && firstSubSchema . type === 'object' ) {
@@ -203,28 +232,42 @@ function parseRequestSchema(
203
232
}
204
233
}
205
234
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
+
206
255
export function parseRoute ( project : Project , schema : Schema ) : E . Either < string , Route > {
207
256
if ( schema . type !== 'object' ) {
208
257
return errorLeft ( 'Route must be an object' ) ;
209
258
}
210
259
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 ;
218
263
}
264
+ const path = pathE . right ;
219
265
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 ;
227
269
}
270
+ const method = methodE . right ;
228
271
229
272
const requestSchema = schema . properties [ 'request' ] ;
230
273
if ( requestSchema === undefined ) {
@@ -243,8 +286,8 @@ export function parseRoute(project: Project, schema: Schema): E.Either<string, R
243
286
}
244
287
245
288
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,
248
291
parameters,
249
292
response : schema . properties [ 'response' ] . properties ,
250
293
...( body !== undefined ? { body } : { } ) ,
0 commit comments