Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,17 @@ Then go to `http://localhost:3000/openapi`.
@default true
Enable/Disable the plugin

## openapiVersion

@default '3.1.2'

OpenAPI document version to emit. Supports OpenAPI `3.0.x` and `3.1.x`.

## documentation

OpenAPI documentation information

@see https://spec.openapis.org/oas/v3.0.3.html
@see https://spec.openapis.org/oas/latest.html

## exclude

Expand Down
3 changes: 3 additions & 0 deletions src/gen/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,7 @@ export const fromTypes =
: ''

let distDir = join(tmpRoot, 'dist')
let rootDir = projectRoot

// Convert Windows path to Unix for TypeScript CLI
if (
Expand All @@ -269,6 +270,7 @@ export const fromTypes =
extendsRef = extendsRef.replace(/\\/g, '/')
src = src.replace(/\\/g, '/')
distDir = distDir.replace(/\\/g, '/')
rootDir = rootDir.replace(/\\/g, '/')
}

fs.writeFileSync(
Expand All @@ -287,6 +289,7 @@ export const fromTypes =
"moduleResolution": "bundler",
"skipLibCheck": true,
"skipDefaultLibCheck": true,
"rootDir": "${rootDir}",
"outDir": "${distDir}"
}`
},
Expand Down
57 changes: 46 additions & 11 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,32 @@ import { ScalarRender } from './scalar'

import { toOpenAPISchema } from './openapi'

import type { OpenAPIV3 } from 'openapi-types'
import type { ApiReferenceConfiguration } from '@scalar/types'
import type { ElysiaOpenAPIConfig } from './types'
import type { ElysiaOpenAPIConfig, OpenAPIVersion } from './types'

type OpenAPIDocument = {
openapi: OpenAPIVersion
[key: string]: unknown
}

const DEFAULT_OPENAPI_VERSION: OpenAPIVersion = '3.1.2'
const OPENAPI_VERSION_REGEX = /^3\.(0|1)\.\d+$/

const normalizeOpenAPIVersion = (
version: string | undefined
): OpenAPIVersion => {
if (!version) return DEFAULT_OPENAPI_VERSION

if (!OPENAPI_VERSION_REGEX.test(version)) {
console.warn(
`[@elysiajs/openapi] Invalid openapiVersion "${version}". Expected 3.0.x or 3.1.x. Falling back to ${DEFAULT_OPENAPI_VERSION}.`
)

return DEFAULT_OPENAPI_VERSION
}

return version as OpenAPIVersion
}

function isCloudflareWorker() {
try {
Expand Down Expand Up @@ -45,6 +68,7 @@ export const openapi = <
path = '/openapi' as Path,
provider = 'scalar',
specPath = `${path}/json`,
openapiVersion = DEFAULT_OPENAPI_VERSION,
documentation = {},
exclude,
swagger,
Expand All @@ -63,17 +87,19 @@ export const openapi = <
}

const relativePath = specPath.startsWith('/') ? specPath.slice(1) : specPath
const effectiveOpenAPIVersion: OpenAPIVersion =
normalizeOpenAPIVersion(openapiVersion)

let totalRoutes = 0
let cachedSchema: OpenAPIV3.Document | undefined
let cachedSchema: OpenAPIDocument | undefined

const toFullSchema = ({
paths,
components: { schemas }
}: ReturnType<typeof toOpenAPISchema>): OpenAPIV3.Document => {
return (cachedSchema = {
openapi: '3.0.3',
}: ReturnType<typeof toOpenAPISchema>): OpenAPIDocument => {
const schema: OpenAPIDocument = {
...documentation,
openapi: effectiveOpenAPIVersion as OpenAPIVersion,
tags: !exclude?.tags
? documentation.tags
: documentation.tags?.filter(
Expand All @@ -96,7 +122,9 @@ export const openapi = <
...(documentation.components?.schemas as any)
}
}
})
}

return (cachedSchema = schema)
}

const app = new Elysia({ name: '@elysiajs/openapi' })
Expand Down Expand Up @@ -132,7 +160,8 @@ export const openapi = <
app,
exclude,
references,
mapJsonSchema
mapJsonSchema,
effectiveOpenAPIVersion
)
)
)
Expand All @@ -156,14 +185,20 @@ export const openapi = <
)
}).get(
specPath,
function openAPISchema(): OpenAPIV3.Document {
function openAPISchema(): OpenAPIDocument {
if (totalRoutes === app.routes.length && cachedSchema)
return cachedSchema

totalRoutes = app.routes.length

return toFullSchema(
toOpenAPISchema(app, exclude, references, mapJsonSchema)
toOpenAPISchema(
app,
exclude,
references,
mapJsonSchema,
effectiveOpenAPIVersion
)
)
},
{
Expand All @@ -182,6 +217,6 @@ export const openapi = <

export { fromTypes } from './gen'
export { toOpenAPISchema, withHeaders } from './openapi'
export type { ElysiaOpenAPIConfig }
export type { ElysiaOpenAPIConfig, OpenAPIVersion } from './types'

export default openapi
Loading