@@ -4,12 +4,11 @@ import type { HookContainer, StandardSchemaV1Like } from 'elysia/types'
44import type { OpenAPIV3 } from 'openapi-types'
55import { Kind , type TProperties } from '@sinclair/typebox'
66
7- import { toJsonSchema } from 'xsschema'
8-
97import type {
108 AdditionalReference ,
119 AdditionalReferences ,
12- ElysiaOpenAPIConfig
10+ ElysiaOpenAPIConfig ,
11+ MapJsonSchema
1312} from './types'
1413
1514export const capitalize = ( word : string ) =>
@@ -69,29 +68,45 @@ export const getLoosePath = (path: string) => {
6968 return path + '/'
7069}
7170
72- type MaybePromise < T > = T | Promise < T >
73-
7471export const unwrapSchema = (
75- schema : InputSchema [ 'body' ]
76- ) : MaybePromise < OpenAPIV3 . SchemaObject | undefined > => {
72+ schema : InputSchema [ 'body' ] ,
73+ mapJsonSchema ?: MapJsonSchema
74+ ) : OpenAPIV3 . SchemaObject | undefined => {
7775 if ( ! schema ) return
7876
7977 if ( typeof schema === 'string' ) schema = toRef ( schema )
8078 if ( Kind in schema ) return schema
8179
82- if ( Kind in schema === false && schema [ '~standard' ] )
83- return toJsonSchema ( schema as any ) as Promise < OpenAPIV3 . SchemaObject >
80+ if ( Kind in schema || ! schema ?. [ '~standard' ] ) return
81+
82+ // @ts -ignore
83+ const vendor = schema [ '~standard' ] . vendor
84+
85+ if ( mapJsonSchema ?. [ vendor ] && typeof mapJsonSchema [ vendor ] === 'function' )
86+ return mapJsonSchema [ vendor ] ( schema )
87+
88+ if ( vendor === 'zod' || vendor === 'sury' )
89+ // @ts -ignore
90+ return schema . toJSONSchema ?.( )
91+
92+ if ( vendor === 'arktype' )
93+ // @ts -ignore
94+ return schema ?. toJsonSchema ?.( )
95+
96+ // @ts -ignore
97+ return schema . toJSONSchema ?.( ) ?? schema ?. toJsonSchema ?.( )
8498}
8599
86100/**
87101 * Converts Elysia routes to OpenAPI 3.0.3 paths schema
88102 * @param routes Array of Elysia route objects
89103 * @returns OpenAPI paths object
90104 */
91- export async function toOpenAPISchema (
105+ export function toOpenAPISchema (
92106 app : AnyElysia ,
93107 exclude ?: ElysiaOpenAPIConfig [ 'exclude' ] ,
94- references ?: AdditionalReferences
108+ references ?: AdditionalReferences ,
109+ vendors ?: MapJsonSchema
95110) {
96111 const {
97112 methods : excludeMethods = [ 'OPTIONS' ] ,
@@ -195,8 +210,7 @@ export async function toOpenAPISchema(
195210
196211 // Handle path parameters
197212 if ( hooks . params ) {
198- let params = unwrapSchema ( hooks . params )
199- if ( params ) params = await params
213+ const params = unwrapSchema ( hooks . params , vendors )
200214
201215 if ( params && params . type === 'object' && params . properties )
202216 for ( const [ paramName , paramSchema ] of Object . entries (
@@ -212,8 +226,7 @@ export async function toOpenAPISchema(
212226
213227 // Handle query parameters
214228 if ( hooks . query ) {
215- let query = unwrapSchema ( hooks . query )
216- if ( query ) query = await query
229+ let query = unwrapSchema ( hooks . query , vendors )
217230
218231 if ( query && query . type === 'object' && query . properties ) {
219232 const required = query . required || [ ]
@@ -231,8 +244,7 @@ export async function toOpenAPISchema(
231244
232245 // Handle header parameters
233246 if ( hooks . headers ) {
234- let headers = unwrapSchema ( hooks . query )
235- if ( headers ) headers = await headers
247+ const headers = unwrapSchema ( hooks . query , vendors )
236248
237249 if ( headers && headers . type === 'object' && headers . properties ) {
238250 const required = headers . required || [ ]
@@ -250,8 +262,7 @@ export async function toOpenAPISchema(
250262
251263 // Handle cookie parameters
252264 if ( hooks . cookie ) {
253- let cookie = unwrapSchema ( hooks . cookie )
254- if ( cookie ) cookie = await cookie
265+ const cookie = unwrapSchema ( hooks . cookie , vendors )
255266
256267 if ( cookie && cookie . type === 'object' && cookie . properties ) {
257268 const required = cookie . required || [ ]
@@ -272,8 +283,7 @@ export async function toOpenAPISchema(
272283
273284 // Handle request body
274285 if ( hooks . body && method !== 'get' && method !== 'head' ) {
275- let body = unwrapSchema ( hooks . body )
276- if ( body ) body = await body
286+ const body = unwrapSchema ( hooks . body , vendors )
277287
278288 if ( body ) {
279289 // @ts -ignore
@@ -363,8 +373,7 @@ export async function toOpenAPISchema(
363373 ! ( hooks . response as TSchema ) . $ref
364374 ) {
365375 for ( let [ status , schema ] of Object . entries ( hooks . response ) ) {
366- let response = unwrapSchema ( schema )
367- if ( response ) response = await response
376+ const response = unwrapSchema ( schema , vendors )
368377
369378 if ( ! response ) continue
370379
@@ -398,8 +407,7 @@ export async function toOpenAPISchema(
398407 }
399408 }
400409 } else {
401- let response = unwrapSchema ( hooks . response as any )
402- if ( response ) response = await response
410+ const response = unwrapSchema ( hooks . response as any , vendors )
403411
404412 if ( response ) {
405413 // @ts -ignore
@@ -470,17 +478,14 @@ export async function toOpenAPISchema(
470478
471479 // @ts -ignore private property
472480 const _schemas = app . getGlobalDefinitions ?.( ) . type
473-
474481 const schemas = Object . create ( null )
475482
476483 if ( _schemas )
477484 for ( const [ name , schema ] of Object . entries ( _schemas ) ) {
478- let jsonSchema = unwrapSchema ( schema as any ) as
485+ const jsonSchema = unwrapSchema ( schema as any , vendors ) as
479486 | OpenAPIV3 . SchemaObject
480487 | undefined
481488
482- if ( jsonSchema instanceof Promise ) jsonSchema = await jsonSchema
483-
484489 if ( jsonSchema ) schemas [ name ] = jsonSchema
485490 }
486491
0 commit comments