@@ -97,6 +97,48 @@ export const unwrapSchema = (
9797 return schema . toJSONSchema ?.( ) ?? schema ?. toJsonSchema ?.( )
9898}
9999
100+ const convertEnumToOpenAPI = ( schema : any ) : any => {
101+ if ( ! schema || typeof schema !== 'object' ) return schema
102+
103+ if (
104+ schema [ Kind ] === 'Union' &&
105+ schema . anyOf &&
106+ Array . isArray ( schema . anyOf ) &&
107+ schema . anyOf . length > 0 &&
108+ schema . anyOf . every (
109+ ( item : any ) =>
110+ item && typeof item === 'object' && item . const !== undefined
111+ )
112+ ) {
113+ const enumValues = schema . anyOf . map ( ( item : any ) => item . const )
114+
115+ return {
116+ type : 'string' ,
117+ enum : enumValues
118+ }
119+ }
120+
121+ if ( schema . type === 'object' && schema . properties ) {
122+ const convertedProperties : any = { }
123+ for ( const [ key , value ] of Object . entries ( schema . properties ) ) {
124+ convertedProperties [ key ] = convertEnumToOpenAPI ( value )
125+ }
126+ return {
127+ ...schema ,
128+ properties : convertedProperties
129+ }
130+ }
131+
132+ if ( schema . type === 'array' && schema . items ) {
133+ return {
134+ ...schema ,
135+ items : convertEnumToOpenAPI ( schema . items )
136+ }
137+ }
138+
139+ return schema
140+ }
141+
100142/**
101143 * Converts Elysia routes to OpenAPI 3.0.3 paths schema
102144 * @param routes Array of Elysia route objects
@@ -212,26 +254,43 @@ export function toOpenAPISchema(
212254 if ( hooks . params ) {
213255 const params = unwrapSchema ( hooks . params , vendors )
214256
215- if ( params && params . type === 'object' && params . properties )
257+ if ( params && params . type === 'object' && params . properties ) {
258+ const convertedProperties : any = { }
216259 for ( const [ paramName , paramSchema ] of Object . entries (
217260 params . properties
261+ ) ) {
262+ convertedProperties [ paramName ] =
263+ convertEnumToOpenAPI ( paramSchema )
264+ }
265+
266+ for ( const [ paramName , paramSchema ] of Object . entries (
267+ convertedProperties
218268 ) )
219269 parameters . push ( {
220270 name : paramName ,
221271 in : 'path' ,
222272 required : true , // Path parameters are always required
223273 schema : paramSchema
224274 } )
275+ }
225276 }
226277
227278 // Handle query parameters
228279 if ( hooks . query ) {
229280 let query = unwrapSchema ( hooks . query , vendors )
230281
231282 if ( query && query . type === 'object' && query . properties ) {
232- const required = query . required || [ ]
283+ const convertedProperties : any = { }
233284 for ( const [ queryName , querySchema ] of Object . entries (
234285 query . properties
286+ ) ) {
287+ convertedProperties [ queryName ] =
288+ convertEnumToOpenAPI ( querySchema )
289+ }
290+
291+ const required = query . required || [ ]
292+ for ( const [ queryName , querySchema ] of Object . entries (
293+ convertedProperties
235294 ) )
236295 parameters . push ( {
237296 name : queryName ,
@@ -247,9 +306,17 @@ export function toOpenAPISchema(
247306 const headers = unwrapSchema ( hooks . query , vendors )
248307
249308 if ( headers && headers . type === 'object' && headers . properties ) {
250- const required = headers . required || [ ]
309+ const convertedProperties : any = { }
251310 for ( const [ headerName , headerSchema ] of Object . entries (
252311 headers . properties
312+ ) ) {
313+ convertedProperties [ headerName ] =
314+ convertEnumToOpenAPI ( headerSchema )
315+ }
316+
317+ const required = headers . required || [ ]
318+ for ( const [ headerName , headerSchema ] of Object . entries (
319+ convertedProperties
253320 ) )
254321 parameters . push ( {
255322 name : headerName ,
@@ -265,9 +332,17 @@ export function toOpenAPISchema(
265332 const cookie = unwrapSchema ( hooks . cookie , vendors )
266333
267334 if ( cookie && cookie . type === 'object' && cookie . properties ) {
268- const required = cookie . required || [ ]
335+ const convertedProperties : any = { }
269336 for ( const [ cookieName , cookieSchema ] of Object . entries (
270337 cookie . properties
338+ ) ) {
339+ convertedProperties [ cookieName ] =
340+ convertEnumToOpenAPI ( cookieSchema )
341+ }
342+
343+ const required = cookie . required || [ ]
344+ for ( const [ cookieName , cookieSchema ] of Object . entries (
345+ convertedProperties
271346 ) )
272347 parameters . push ( {
273348 name : cookieName ,
@@ -286,8 +361,10 @@ export function toOpenAPISchema(
286361 const body = unwrapSchema ( hooks . body , vendors )
287362
288363 if ( body ) {
364+ const convertedBody = convertEnumToOpenAPI ( body )
365+
289366 // @ts -ignore
290- const { type : _type , description, ...options } = body
367+ const { type : _type , description, ...options } = convertedBody
291368 const type = _type as string | undefined
292369
293370 // @ts -ignore
@@ -306,26 +383,24 @@ export function toOpenAPISchema(
306383 switch ( parser . fn ) {
307384 case 'text' :
308385 case 'text/plain' :
309- content [ 'text/plain' ] = { schema : body }
386+ content [ 'text/plain' ] = { schema : convertedBody }
310387 continue
311388
312389 case 'urlencoded' :
313390 case 'application/x-www-form-urlencoded' :
314391 content [ 'application/x-www-form-urlencoded' ] = {
315- schema : body
392+ schema : convertedBody
316393 }
317394 continue
318395
319396 case 'json' :
320397 case 'application/json' :
321- content [ 'application/json' ] = { schema : body }
398+ content [ 'application/json' ] = { schema : convertedBody }
322399 continue
323400
324401 case 'formdata' :
325402 case 'multipart/form-data' :
326- content [ 'multipart/form-data' ] = {
327- schema : body
328- }
403+ content [ 'multipart/form-data' ] = { schema : convertedBody }
329404 continue
330405 }
331406 }
@@ -344,17 +419,17 @@ export function toOpenAPISchema(
344419 type === 'integer' ||
345420 type === 'boolean'
346421 ? {
347- 'text/plain' : body
422+ 'text/plain' : convertedBody
348423 }
349424 : {
350425 'application/json' : {
351- schema : body
426+ schema : convertedBody
352427 } ,
353428 'application/x-www-form-urlencoded' : {
354- schema : body
429+ schema : convertedBody
355430 } ,
356431 'multipart/form-data' : {
357- schema : body
432+ schema : convertedBody
358433 }
359434 } ,
360435 required : true
@@ -377,8 +452,9 @@ export function toOpenAPISchema(
377452
378453 if ( ! response ) continue
379454
455+ const convertedResponse = convertEnumToOpenAPI ( response )
380456 // @ts -ignore Must exclude $ref from root options
381- const { type : _type , description, ...options } = response
457+ const { type : _type , description, ...options } = convertedResponse
382458 const type = _type as string | undefined
383459
384460 operation . responses [ status ] = {
@@ -389,19 +465,19 @@ export function toOpenAPISchema(
389465 type === 'void' ||
390466 type === 'null' ||
391467 type === 'undefined'
392- ? ( response as any )
468+ ? ( convertedResponse as any )
393469 : type === 'string' ||
394470 type === 'number' ||
395471 type === 'integer' ||
396472 type === 'boolean'
397473 ? {
398474 'text/plain' : {
399- schema : response
475+ schema : convertedResponse
400476 }
401477 }
402478 : {
403479 'application/json' : {
404- schema : response
480+ schema : convertedResponse
405481 }
406482 }
407483 }
@@ -410,8 +486,10 @@ export function toOpenAPISchema(
410486 const response = unwrapSchema ( hooks . response as any , vendors )
411487
412488 if ( response ) {
489+ const convertedResponse = convertEnumToOpenAPI ( response )
490+
413491 // @ts -ignore
414- const { type : _type , description, ...options } = response
492+ const { type : _type , description, ...options } = convertedResponse
415493 const type = _type as string | undefined
416494
417495 // It's a single schema, default to 200
@@ -421,19 +499,19 @@ export function toOpenAPISchema(
421499 type === 'void' ||
422500 type === 'null' ||
423501 type === 'undefined'
424- ? ( response as any )
502+ ? ( convertedResponse as any )
425503 : type === 'string' ||
426504 type === 'number' ||
427505 type === 'integer' ||
428506 type === 'boolean'
429507 ? {
430508 'text/plain' : {
431- schema : response
509+ schema : convertedResponse
432510 }
433511 }
434512 : {
435513 'application/json' : {
436- schema : response
514+ schema : convertedResponse
437515 }
438516 }
439517 }
0 commit comments