feat(swagger-uri): Add Full Configuration Parameters and Update Dependencies (#618)
* chore(swagger-ui): update swagger-ui-dist types * feat(swagger-ui): add swagger-ui parameters * chore(swagger-ui): fix typeerror add url parameter * chore(swagger-ui): refactor test case * chore: add versioning doc * chore(swagger-ui): remove useUnsafeMarkdown * chore(swagger-ui): add requestSnippetsEnabled * chore(swagger-ui): syntaxHighlight: boolean * chore(swagger-ui): fix propertykey * chore(swagger-ui): format code * chore(swagger-ui): add string function property commentedpull/629/head
parent
61cd9b6a57
commit
47be5c6956
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
'@hono/swagger-ui': minor
|
||||
---
|
||||
|
||||
Add Full Configuration Parameters and Update Dependencies for Swagger UI
|
|
@ -41,7 +41,7 @@
|
|||
"hono": "*"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/swagger-ui-dist": "^3.30.3",
|
||||
"@types/swagger-ui-dist": "^3.30.5",
|
||||
"hono": "^3.11.7",
|
||||
"publint": "^0.2.2",
|
||||
"tsup": "^7.2.0",
|
||||
|
|
|
@ -14,17 +14,60 @@ export type DistSwaggerUIOptions = {
|
|||
layout?: SwaggerConfigs['layout']
|
||||
docExpansion?: SwaggerConfigs['docExpansion']
|
||||
maxDisplayedTags?: SwaggerConfigs['maxDisplayedTags']
|
||||
/**
|
||||
* accepts function as a string.
|
||||
*
|
||||
* @example (a, b) => a.path.localeCompare(b.path)
|
||||
*/
|
||||
operationsSorter?: string
|
||||
/**
|
||||
* accepts function as a string.
|
||||
*
|
||||
* @example (req) => req
|
||||
*/
|
||||
requestInterceptor?: string
|
||||
/**
|
||||
* accepts function as a string.
|
||||
*
|
||||
* @example (res) => res
|
||||
*/
|
||||
responseInterceptor?: string
|
||||
persistAuthorization?: boolean
|
||||
defaultModelsExpandDepth?: number
|
||||
defaultModelExpandDepth?: number
|
||||
defaultModelRendering?: "example" | "model" | undefined
|
||||
defaultModelRendering?: 'example' | 'model' | undefined
|
||||
displayRequestDuration?: boolean
|
||||
filter?: boolean | string
|
||||
showExtensions?: boolean
|
||||
showCommonExtensions?: boolean
|
||||
queryConfigEnabled?: boolean
|
||||
displayOperationId?: boolean
|
||||
/**
|
||||
* accepts function as a string.
|
||||
* swagger-ui accepts alpha in the tagsSorter, but this middleware does not support it.
|
||||
*
|
||||
* @example (a, b) => a.name.localeCompare(b.name)
|
||||
*/
|
||||
tagsSorter?: string
|
||||
/**
|
||||
* accepts function as a string.
|
||||
* @example () => { console.log('Swagger UI Loaded'); }
|
||||
*/
|
||||
onComplete?: string
|
||||
syntaxHighlight?: boolean | { activated: boolean; theme: string[] }
|
||||
tryItOutEnabled?: boolean
|
||||
requestSnippetsEnabled?: boolean
|
||||
requestSnippets?: object
|
||||
oauth2RedirectUrl?: string
|
||||
showMutabledRequest?: boolean
|
||||
request?: {
|
||||
curlOptions?: string[]
|
||||
}
|
||||
supportedSubmitMethods?: string[]
|
||||
validatorUrl?: string
|
||||
withCredentials?: boolean
|
||||
modelPropertyMacro?: string
|
||||
parameterMacro?: string
|
||||
} & RequireOne<{
|
||||
url?: SwaggerConfigs['url']
|
||||
urls?: SwaggerConfigs['urls']
|
||||
|
@ -59,6 +102,22 @@ const RENDER_TYPE_MAP = {
|
|||
filter: RENDER_TYPE.RAW,
|
||||
showExtensions: RENDER_TYPE.RAW,
|
||||
showCommonExtensions: RENDER_TYPE.RAW,
|
||||
queryConfigEnabled: RENDER_TYPE.RAW,
|
||||
displayOperationId: RENDER_TYPE.RAW,
|
||||
tagsSorter: RENDER_TYPE.RAW,
|
||||
onComplete: RENDER_TYPE.RAW,
|
||||
syntaxHighlight: RENDER_TYPE.JSON_STRING,
|
||||
tryItOutEnabled: RENDER_TYPE.RAW,
|
||||
requestSnippetsEnabled: RENDER_TYPE.RAW,
|
||||
requestSnippets: RENDER_TYPE.JSON_STRING,
|
||||
oauth2RedirectUrl: RENDER_TYPE.STRING,
|
||||
showMutabledRequest: RENDER_TYPE.RAW,
|
||||
request: RENDER_TYPE.JSON_STRING,
|
||||
supportedSubmitMethods: RENDER_TYPE.JSON_STRING,
|
||||
validatorUrl: RENDER_TYPE.STRING,
|
||||
withCredentials: RENDER_TYPE.RAW,
|
||||
modelPropertyMacro: RENDER_TYPE.RAW,
|
||||
parameterMacro: RENDER_TYPE.RAW,
|
||||
} as const satisfies Record<
|
||||
keyof DistSwaggerUIOptions,
|
||||
(typeof RENDER_TYPE)[keyof typeof RENDER_TYPE]
|
||||
|
|
|
@ -1,174 +1,195 @@
|
|||
/*eslint quotes: ["off", "single"]*/
|
||||
|
||||
import type { DistSwaggerUIOptions } from '../src/swagger/renderer'
|
||||
import { renderSwaggerUIOptions } from '../src/swagger/renderer'
|
||||
|
||||
type TestCase = [description: string, config: DistSwaggerUIOptions, expected: string]
|
||||
|
||||
describe('SwaggerUIOption Rendering', () => {
|
||||
it('renders correctly with configUrl', () =>
|
||||
expect(
|
||||
renderSwaggerUIOptions({
|
||||
configUrl: 'https://petstore3.swagger.io/api/v3/openapi.json',
|
||||
})
|
||||
).toEqual("configUrl: 'https://petstore3.swagger.io/api/v3/openapi.json'"))
|
||||
|
||||
it('renders correctly with presets', () =>
|
||||
expect(
|
||||
renderSwaggerUIOptions({
|
||||
presets: ['SwaggerUIBundle.presets.apis', 'SwaggerUIStandalonePreset'],
|
||||
})
|
||||
).toEqual('presets: [SwaggerUIBundle.presets.apis,SwaggerUIStandalonePreset]'))
|
||||
|
||||
it('renders correctly with plugins', () =>
|
||||
expect(
|
||||
renderSwaggerUIOptions({
|
||||
plugins: ['SwaggerUIBundle.plugins.DownloadUrl'],
|
||||
})
|
||||
).toEqual('plugins: [SwaggerUIBundle.plugins.DownloadUrl]'))
|
||||
|
||||
it('renders correctly with deepLinking', () =>
|
||||
expect(
|
||||
renderSwaggerUIOptions({
|
||||
deepLinking: true,
|
||||
})
|
||||
).toEqual('deepLinking: true'))
|
||||
|
||||
it('renders correctly with spec', () =>
|
||||
expect(
|
||||
renderSwaggerUIOptions({
|
||||
const baseUrl = 'https://petstore3.swagger.io/api/v3/openapi.json'
|
||||
const commonTests: TestCase[] = [
|
||||
[
|
||||
'configUrl',
|
||||
{ configUrl: baseUrl, url: baseUrl },
|
||||
`configUrl: '${baseUrl}',url: '${baseUrl}'`,
|
||||
],
|
||||
[
|
||||
'presets',
|
||||
{ presets: ['SwaggerUIBundle.presets.apis', 'SwaggerUIStandalonePreset'], url: baseUrl },
|
||||
`presets: [SwaggerUIBundle.presets.apis,SwaggerUIStandalonePreset],url: '${baseUrl}'`,
|
||||
],
|
||||
[
|
||||
'plugins',
|
||||
{ plugins: ['SwaggerUIBundle.plugins.DownloadUrl'], url: baseUrl },
|
||||
`plugins: [SwaggerUIBundle.plugins.DownloadUrl],url: '${baseUrl}'`,
|
||||
],
|
||||
['deepLinking', { deepLinking: true, url: baseUrl }, `deepLinking: true,url: '${baseUrl}'`],
|
||||
[
|
||||
'spec',
|
||||
{
|
||||
spec: {
|
||||
openapi: '3.0.0',
|
||||
info: {
|
||||
title: 'Swagger Petstore',
|
||||
version: '1.0.0',
|
||||
},
|
||||
servers: [
|
||||
{
|
||||
url: 'https://petstore3.swagger.io/api/v3',
|
||||
},
|
||||
],
|
||||
info: { title: 'Swagger Petstore', version: '1.0.0' },
|
||||
servers: [{ url: 'https://petstore3.swagger.io/api/v3' }],
|
||||
},
|
||||
})
|
||||
).toEqual(
|
||||
'spec: {"openapi":"3.0.0","info":{"title":"Swagger Petstore","version":"1.0.0"},"servers":[{"url":"https://petstore3.swagger.io/api/v3"}]}'
|
||||
))
|
||||
url: baseUrl,
|
||||
},
|
||||
`spec: {"openapi":"3.0.0","info":{"title":"Swagger Petstore","version":"1.0.0"},"servers":[{"url":"https://petstore3.swagger.io/api/v3"}]},url: '${baseUrl}'`,
|
||||
],
|
||||
[
|
||||
'layout',
|
||||
{ layout: 'StandaloneLayout', url: baseUrl },
|
||||
`layout: 'StandaloneLayout',url: '${baseUrl}'`,
|
||||
],
|
||||
[
|
||||
'docExpansion',
|
||||
{ docExpansion: 'list', url: baseUrl },
|
||||
`docExpansion: 'list',url: '${baseUrl}'`,
|
||||
],
|
||||
[
|
||||
'maxDisplayedTags',
|
||||
{ maxDisplayedTags: 5, url: baseUrl },
|
||||
`maxDisplayedTags: 5,url: '${baseUrl}'`,
|
||||
],
|
||||
[
|
||||
'operationsSorter',
|
||||
{ operationsSorter: '(a, b) => a.path.localeCompare(b.path)', url: baseUrl },
|
||||
`operationsSorter: (a, b) => a.path.localeCompare(b.path),url: '${baseUrl}'`,
|
||||
],
|
||||
[
|
||||
'requestInterceptor',
|
||||
{ requestInterceptor: '(req) => req', url: baseUrl },
|
||||
`requestInterceptor: (req) => req,url: '${baseUrl}'`,
|
||||
],
|
||||
[
|
||||
'responseInterceptor',
|
||||
{ responseInterceptor: '(res) => res', url: baseUrl },
|
||||
`responseInterceptor: (res) => res,url: '${baseUrl}'`,
|
||||
],
|
||||
[
|
||||
'persistAuthorization',
|
||||
{ persistAuthorization: true, url: baseUrl },
|
||||
`persistAuthorization: true,url: '${baseUrl}'`,
|
||||
],
|
||||
[
|
||||
'defaultModelsExpandDepth',
|
||||
{ defaultModelsExpandDepth: 1, url: baseUrl },
|
||||
`defaultModelsExpandDepth: 1,url: '${baseUrl}'`,
|
||||
],
|
||||
[
|
||||
'defaultModelExpandDepth',
|
||||
{ defaultModelExpandDepth: 2, url: baseUrl },
|
||||
`defaultModelExpandDepth: 2,url: '${baseUrl}'`,
|
||||
],
|
||||
[
|
||||
'defaultModelRendering',
|
||||
{ defaultModelRendering: 'model', url: baseUrl },
|
||||
`defaultModelRendering: 'model',url: '${baseUrl}'`,
|
||||
],
|
||||
[
|
||||
'displayRequestDuration',
|
||||
{ displayRequestDuration: true, url: baseUrl },
|
||||
`displayRequestDuration: true,url: '${baseUrl}'`,
|
||||
],
|
||||
['filter', { filter: true, url: baseUrl }, `filter: true,url: '${baseUrl}'`],
|
||||
[
|
||||
'showExtensions',
|
||||
{ showExtensions: true, url: baseUrl },
|
||||
`showExtensions: true,url: '${baseUrl}'`,
|
||||
],
|
||||
[
|
||||
'showCommonExtensions',
|
||||
{ showCommonExtensions: true, url: baseUrl },
|
||||
`showCommonExtensions: true,url: '${baseUrl}'`,
|
||||
],
|
||||
[
|
||||
'queryConfigEnabled',
|
||||
{ queryConfigEnabled: true, url: baseUrl },
|
||||
`queryConfigEnabled: true,url: '${baseUrl}'`,
|
||||
],
|
||||
[
|
||||
'displayOperationId',
|
||||
{ displayOperationId: true, url: baseUrl },
|
||||
`displayOperationId: true,url: '${baseUrl}'`,
|
||||
],
|
||||
[
|
||||
'tagsSorter',
|
||||
{ tagsSorter: '(a, b) => a.name.localeCompare(b.name)', url: baseUrl },
|
||||
`tagsSorter: (a, b) => a.name.localeCompare(b.name),url: '${baseUrl}'`,
|
||||
],
|
||||
[
|
||||
'onComplete',
|
||||
{ onComplete: '() => console.log("Completed")', url: baseUrl },
|
||||
`onComplete: () => console.log("Completed"),url: '${baseUrl}'`,
|
||||
],
|
||||
[
|
||||
'syntaxHighlight as false',
|
||||
{ syntaxHighlight: false, url: baseUrl },
|
||||
`syntaxHighlight: false,url: '${baseUrl}'`,
|
||||
],
|
||||
[
|
||||
'syntaxHighlight as object',
|
||||
{ syntaxHighlight: { activated: true, theme: ['agate', 'arta'] }, url: baseUrl },
|
||||
`syntaxHighlight: {"activated":true,"theme":["agate","arta"]},url: '${baseUrl}'`,
|
||||
],
|
||||
[
|
||||
'tryItOutEnabled',
|
||||
{ tryItOutEnabled: true, url: baseUrl },
|
||||
`tryItOutEnabled: true,url: '${baseUrl}'`,
|
||||
],
|
||||
[
|
||||
'requestSnippetsEnabled',
|
||||
{ requestSnippetsEnabled: true, url: baseUrl },
|
||||
`requestSnippetsEnabled: true,url: '${baseUrl}'`,
|
||||
],
|
||||
[
|
||||
'requestSnippets',
|
||||
{ requestSnippets: { generators: { curl_bash: { title: 'cURL (bash)' } } }, url: baseUrl },
|
||||
`requestSnippets: {"generators":{"curl_bash":{"title":"cURL (bash)"}}},url: '${baseUrl}'`,
|
||||
],
|
||||
[
|
||||
'oauth2RedirectUrl',
|
||||
{ oauth2RedirectUrl: 'https://example.com/oauth2-redirect.html', url: baseUrl },
|
||||
`oauth2RedirectUrl: 'https://example.com/oauth2-redirect.html',url: '${baseUrl}'`,
|
||||
],
|
||||
[
|
||||
'showMutableRequest',
|
||||
{ showMutabledRequest: true, url: baseUrl },
|
||||
`showMutabledRequest: true,url: '${baseUrl}'`,
|
||||
],
|
||||
[
|
||||
'request',
|
||||
{ request: { curlOptions: ['--insecure'] }, url: baseUrl },
|
||||
`request: {"curlOptions":["--insecure"]},url: '${baseUrl}'`,
|
||||
],
|
||||
[
|
||||
'supportedSubmitMethods',
|
||||
{ supportedSubmitMethods: ['get', 'post', 'put'], url: baseUrl },
|
||||
`supportedSubmitMethods: ["get","post","put"],url: '${baseUrl}'`,
|
||||
],
|
||||
[
|
||||
'validatorUrl',
|
||||
{ validatorUrl: 'https://validator.swagger.io', url: baseUrl },
|
||||
`validatorUrl: 'https://validator.swagger.io',url: '${baseUrl}'`,
|
||||
],
|
||||
[
|
||||
'withCredentials',
|
||||
{ withCredentials: true, url: baseUrl },
|
||||
`withCredentials: true,url: '${baseUrl}'`,
|
||||
],
|
||||
[
|
||||
'modelPropertyMacro',
|
||||
{ modelPropertyMacro: '(property) => property', url: baseUrl },
|
||||
`modelPropertyMacro: (property) => property,url: '${baseUrl}'`,
|
||||
],
|
||||
[
|
||||
'parameterMacro',
|
||||
{ parameterMacro: '(parameter) => parameter', url: baseUrl },
|
||||
`parameterMacro: (parameter) => parameter,url: '${baseUrl}'`,
|
||||
],
|
||||
]
|
||||
|
||||
it('renders correctly with url', () => {
|
||||
expect(
|
||||
renderSwaggerUIOptions({
|
||||
url: 'https://petstore3.swagger.io/api/v3/openapi.json',
|
||||
})
|
||||
).toEqual("url: 'https://petstore3.swagger.io/api/v3/openapi.json'")
|
||||
it.each(commonTests)('renders correctly with %s', (_, input, expected) => {
|
||||
expect(renderSwaggerUIOptions(input)).toEqual(expected)
|
||||
})
|
||||
|
||||
it('renders correctly with urls', () => {
|
||||
expect(
|
||||
renderSwaggerUIOptions({
|
||||
urls: [
|
||||
{
|
||||
name: 'Petstore',
|
||||
url: 'https://petstore3.swagger.io/api/v3/openapi.json',
|
||||
},
|
||||
],
|
||||
})
|
||||
).toEqual(
|
||||
'urls: [{"name":"Petstore","url":"https://petstore3.swagger.io/api/v3/openapi.json"}]'
|
||||
)
|
||||
})
|
||||
|
||||
it('renders correctly with layout', () =>
|
||||
expect(
|
||||
renderSwaggerUIOptions({
|
||||
layout: 'StandaloneLayout',
|
||||
})
|
||||
).toEqual("layout: 'StandaloneLayout'"))
|
||||
|
||||
it('renders correctly with docExpansion', () =>
|
||||
expect(
|
||||
renderSwaggerUIOptions({
|
||||
docExpansion: 'list',
|
||||
})
|
||||
).toEqual("docExpansion: 'list'"))
|
||||
|
||||
it('renders correctly with maxDisplayedTags', () =>
|
||||
expect(
|
||||
renderSwaggerUIOptions({
|
||||
maxDisplayedTags: 5,
|
||||
})
|
||||
).toEqual('maxDisplayedTags: 5'))
|
||||
|
||||
it('renders correctly with operationsSorter', () =>
|
||||
expect(
|
||||
renderSwaggerUIOptions({
|
||||
operationsSorter: '(a, b) => a.path.localeCompare(b.path)',
|
||||
})
|
||||
).toEqual('operationsSorter: (a, b) => a.path.localeCompare(b.path)'))
|
||||
|
||||
it('renders correctly with requestInterceptor', () =>
|
||||
expect(
|
||||
renderSwaggerUIOptions({
|
||||
requestInterceptor: '(req) => req',
|
||||
})
|
||||
).toEqual('requestInterceptor: (req) => req'))
|
||||
|
||||
it('renders correctly with responseInterceptor', () =>
|
||||
expect(
|
||||
renderSwaggerUIOptions({
|
||||
responseInterceptor: '(res) => res',
|
||||
})
|
||||
).toEqual('responseInterceptor: (res) => res'))
|
||||
|
||||
it('renders correctly with persistAuthorization', () =>
|
||||
expect(
|
||||
renderSwaggerUIOptions({
|
||||
persistAuthorization: true,
|
||||
})
|
||||
).toEqual('persistAuthorization: true'))
|
||||
|
||||
it('renders correctly with defaultModelsExpandDepth', () =>
|
||||
expect(
|
||||
renderSwaggerUIOptions({
|
||||
defaultModelsExpandDepth: 1,
|
||||
})
|
||||
).toEqual('defaultModelsExpandDepth: 1'))
|
||||
|
||||
it('renders correctly with defaultModelExpandDepth', () =>
|
||||
expect(
|
||||
renderSwaggerUIOptions({
|
||||
defaultModelExpandDepth: 2,
|
||||
})
|
||||
).toEqual('defaultModelExpandDepth: 2'))
|
||||
|
||||
it('renders correctly with defaultModelRendering', () =>
|
||||
expect(
|
||||
renderSwaggerUIOptions({
|
||||
defaultModelRendering: 'model',
|
||||
})
|
||||
).toEqual("defaultModelRendering: 'model'"))
|
||||
|
||||
it('renders correctly with displayRequestDuration', () =>
|
||||
expect(
|
||||
renderSwaggerUIOptions({
|
||||
displayRequestDuration: true,
|
||||
})
|
||||
).toEqual('displayRequestDuration: true'))
|
||||
|
||||
it('renders correctly with filter', () =>
|
||||
expect(
|
||||
renderSwaggerUIOptions({
|
||||
filter: true,
|
||||
})
|
||||
).toEqual('filter: true'))
|
||||
|
||||
it('renders correctly with showExtensions', () =>
|
||||
expect(
|
||||
renderSwaggerUIOptions({
|
||||
showExtensions: true,
|
||||
})
|
||||
).toEqual('showExtensions: true'))
|
||||
|
||||
it('renders correctly with showCommonExtensions', () =>
|
||||
expect(
|
||||
renderSwaggerUIOptions({
|
||||
showCommonExtensions: true,
|
||||
})
|
||||
).toEqual('showCommonExtensions: true'))
|
||||
})
|
||||
|
|
10
yarn.lock
10
yarn.lock
|
@ -2278,7 +2278,7 @@ __metadata:
|
|||
version: 0.0.0-use.local
|
||||
resolution: "@hono/swagger-ui@workspace:packages/swagger-ui"
|
||||
dependencies:
|
||||
"@types/swagger-ui-dist": "npm:^3.30.3"
|
||||
"@types/swagger-ui-dist": "npm:^3.30.5"
|
||||
hono: "npm:^3.11.7"
|
||||
publint: "npm:^0.2.2"
|
||||
tsup: "npm:^7.2.0"
|
||||
|
@ -4352,10 +4352,10 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@types/swagger-ui-dist@npm:^3.30.3":
|
||||
version: 3.30.4
|
||||
resolution: "@types/swagger-ui-dist@npm:3.30.4"
|
||||
checksum: 106114fef47a29811a37810e00e52d3fb6f99bafa7ec00b49926827a9c502b27550e2de589af000e472d327c3fc32417f75befa37b2450e8fad81e0a79ad641f
|
||||
"@types/swagger-ui-dist@npm:^3.30.5":
|
||||
version: 3.30.5
|
||||
resolution: "@types/swagger-ui-dist@npm:3.30.5"
|
||||
checksum: 0e6ea1b6add4fb9cfd82dcdbd8156b3d0921a6bd2d511b92c05fc6d76e94a78d89eab81ffd6bb34c0c52e97b5e4a61eea77fab502698e9cf170aabf5d2c09510
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
|
|
Loading…
Reference in New Issue