🔧 fix: unfold ref to schema

This commit is contained in:
saltyaom
2025-02-19 17:46:45 +07:00
parent f2b62fadc8
commit 0d89db6118
5 changed files with 91 additions and 46 deletions

View File

@@ -1,3 +1,7 @@
# 1.2.1 - 19 Feb 2024
Bug fix:
- [elysia#1063](https://github.com/elysiajs/elysia/issues/1063) Using t.Ref as response schema results in invalid OpenAPI specification
- handle unfold recursive Ref to schema
# 1.2.0-rc.0 - 23 Dec 2024
Change:

View File

@@ -1,41 +1,56 @@
import { Elysia } from 'elysia'
import { Elysia, t } from 'elysia'
import { swagger } from '../src/index'
const schema = t.Object({
test: t.Literal('hello')
})
const app = new Elysia()
.use(
swagger({
provider: 'scalar',
documentation: {
info: {
title: 'Elysia Scalar',
version: '0.8.1'
},
tags: [
{
name: 'Test',
description: 'Hello'
}
],
components: {
schemas: {
User: {
description: 'string'
}
},
securitySchemes: {
JwtAuth: {
type: 'http',
scheme: 'bearer',
bearerFormat: 'JWT',
description: 'Enter JWT Bearer token **_only_**'
}
}
}
},
swaggerOptions: {
persistAuthorization: true
}
})
)
.get('/id/:id?', 'a')
.listen(3000)
.use(
swagger({
provider: 'scalar',
documentation: {
info: {
title: 'Elysia Scalar',
version: '0.8.1'
},
tags: [
{
name: 'Test',
description: 'Hello'
}
],
components: {
schemas: {
User: {
description: 'string'
}
},
securitySchemes: {
JwtAuth: {
type: 'http',
scheme: 'bearer',
bearerFormat: 'JWT',
description: 'Enter JWT Bearer token **_only_**'
}
}
}
},
swaggerOptions: {
persistAuthorization: true
}
})
)
.model({ schema })
.get(
'/',
() => {
test: 'hello'
},
{
response: t.Object({
a: t.Ref('schema')
})
}
)
.listen(3000)

View File

@@ -1,6 +1,6 @@
{
"name": "@elysiajs/swagger",
"version": "1.2.0",
"version": "1.2.1",
"description": "Plugin for Elysia to auto-generate Swagger page",
"author": {
"name": "saltyAom",

View File

@@ -117,7 +117,7 @@ export const swagger = async <Path extends string = '/swagger'>(
const ALLOWED_METHODS = ['GET', 'PUT', 'POST', 'DELETE', 'OPTIONS', 'HEAD', 'PATCH', 'TRACE']
totalRoutes = routes.length
routes.forEach((route: InternalRoute) => {
for(const route of routes) {
if (route.hooks?.detail?.hide === true) return
// TODO: route.hooks?.detail?.hide !== false add ability to hide: false to prevent excluding
if (excludeMethods.includes(route.method)) return
@@ -147,7 +147,7 @@ export const swagger = async <Path extends string = '/swagger'>(
models: app.definitions?.type,
contentType: route.hooks.type
})
})
}
}
return {

View File

@@ -1,7 +1,7 @@
/* eslint-disable @typescript-eslint/ban-ts-comment */
/* eslint-disable @typescript-eslint/no-unused-vars */
import { normalize } from 'pathe'
import type { HTTPMethod, LocalHook } from 'elysia'
import { replaceSchemaType, t, type HTTPMethod, type LocalHook } from 'elysia'
import { Kind, type TSchema } from '@sinclair/typebox'
import type { OpenAPIV3 } from 'openapi-types'
@@ -70,15 +70,39 @@ const mapTypesResponse = (
const responses: Record<string, OpenAPIV3.MediaTypeObject> = {}
for (const type of types) {
// console.log(schema)
responses[type] = {
schema:
typeof schema === 'string'
? {
$ref: `#/components/schemas/${schema}`
}
: { ...(schema as any) }
: '$ref' in schema &&
Kind in schema &&
schema[Kind] === 'Ref'
? {
...schema,
$ref: `#/components/schemas/${schema.$ref}`
}
: replaceSchemaType(
{ ...(schema as any) },
{
from: t.Ref(''),
// @ts-expect-error
to: ({ $ref, ...options }) => {
if (
!$ref.startsWith(
'#/components/schemas/'
)
)
return t.Ref(
`#/components/schemas/${$ref}`,
options
)
return t.Ref($ref, options)
}
}
)
}
}
@@ -154,6 +178,7 @@ export const registerSchemaPath = ({
required,
additionalProperties,
patternProperties,
$ref,
...rest
} = responseSchema as typeof responseSchema & {
type: string
@@ -246,6 +271,7 @@ export const registerSchemaPath = ({
type,
properties,
required,
$ref,
additionalProperties: _1,
patternProperties: _2,
...rest