feat: introduce Swagger Editor middleware (#800)
Closes https://github.com/honojs/hono/issues/1415 * chore(swagger-editor): 🔨 init * ci: 🎡 swagger editor workflow create workflow for swagger-editor package * docs: 📝 readme have writed documentation * test(test): ✅ create test for swagger-editor middleware * fix(swagger-editor): 🐛 fixed cdn url in html content * chore: 🔨 v0.1.0 release * format * fix the typos * remove unnecessary `.` * remove unnecessay `vite` and fix the `vitest.config.ts` * fix the relase workflow * update the changeset and `package.json` --------- Co-authored-by: Yusuke Wada <yusuke@kamawada.com>pull/805/head
parent
2c0c41faa5
commit
5fd80263f2
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
'@hono/swagger-editor': major
|
||||||
|
---
|
||||||
|
|
||||||
|
Create swagger editor middleware for hono
|
|
@ -0,0 +1,25 @@
|
||||||
|
name: ci-swagger-editor
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [main]
|
||||||
|
paths:
|
||||||
|
- 'packages/swagger-editor/**'
|
||||||
|
pull_request:
|
||||||
|
branches: ['*']
|
||||||
|
paths:
|
||||||
|
- 'packages/swagger-editor/**'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
ci:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
defaults:
|
||||||
|
run:
|
||||||
|
working-directory: ./packages/swagger-editor
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: 20.x
|
||||||
|
- run: yarn install --frozen-lockfile
|
||||||
|
- run: yarn build
|
||||||
|
- run: yarn test
|
|
@ -23,6 +23,7 @@
|
||||||
"build:zod-openapi": "yarn workspace @hono/zod-openapi install && yarn workspace @hono/zod-openapi build",
|
"build:zod-openapi": "yarn workspace @hono/zod-openapi install && yarn workspace @hono/zod-openapi build",
|
||||||
"build:typia-validator": "yarn workspace @hono/typia-validator build",
|
"build:typia-validator": "yarn workspace @hono/typia-validator build",
|
||||||
"build:swagger-ui": "yarn workspace @hono/swagger-ui build",
|
"build:swagger-ui": "yarn workspace @hono/swagger-ui build",
|
||||||
|
"build:swagger-editor": "yarn workspace @hono/swagger-editor build",
|
||||||
"build:esbuild-transpiler": "yarn workspace @hono/esbuild-transpiler build",
|
"build:esbuild-transpiler": "yarn workspace @hono/esbuild-transpiler build",
|
||||||
"build:event-emitter": "yarn workspace @hono/event-emitter build",
|
"build:event-emitter": "yarn workspace @hono/event-emitter build",
|
||||||
"build:oauth-providers": "yarn workspace @hono/oauth-providers build",
|
"build:oauth-providers": "yarn workspace @hono/oauth-providers build",
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
# Swagger Editor Middleware for Hono
|
||||||
|
|
||||||
|
This library, `@hono/swagger-editor` is the middleware for integrating Swagger Editor with Hono applications. The Swagger Editor is an open source editor to design, define and document RESTful APIs in the Swagger Specification.
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install @hono/swagger-editor
|
||||||
|
# or
|
||||||
|
yarn add @hono/swagger-editor
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
You can use the `swaggerEditor` middleware to serve Swagger Editor on a specific route in your Hono application. Here's how you can do it:
|
||||||
|
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import { Hono } from 'hono'
|
||||||
|
import { swaggerUI } from '@hono/swagger-ui'
|
||||||
|
|
||||||
|
const app = new Hono()
|
||||||
|
|
||||||
|
// Use the middleware to serve Swagger Editor at /swagger-editor
|
||||||
|
app.get('/swagger-editor', swaggerEditor({ url: '/doc' }))
|
||||||
|
|
||||||
|
export default app
|
||||||
|
```
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
Middleware supports almost all swagger-editor options. See full documentation: <https://swagger.io/docs/open-source-tools/swagger-editor/>
|
||||||
|
|
||||||
|
## Authors
|
||||||
|
|
||||||
|
- Ogabek Yuldoshev <https://github.com/OgabekYuldoshev>
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
MIT
|
|
@ -0,0 +1,48 @@
|
||||||
|
{
|
||||||
|
"name": "@hono/swagger-editor",
|
||||||
|
"version": "0.0.0",
|
||||||
|
"description": "A middleware for using Swagger Editor in Hono",
|
||||||
|
"type": "module",
|
||||||
|
"main": "dist/index.cjs",
|
||||||
|
"module": "dist/index.js",
|
||||||
|
"types": "dist/index.d.cts",
|
||||||
|
"exports": {
|
||||||
|
".": {
|
||||||
|
"import": {
|
||||||
|
"types": "./dist/index.d.ts",
|
||||||
|
"default": "./dist/index.js"
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"types": "./dist/index.d.cts",
|
||||||
|
"default": "./dist/index.cjs"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"dist"
|
||||||
|
],
|
||||||
|
"scripts": {
|
||||||
|
"test": "vitest run",
|
||||||
|
"build": "tsup ./src/index.ts --format esm,cjs --dts",
|
||||||
|
"prerelease": "yarn build && yarn test",
|
||||||
|
"release": "yarn publish"
|
||||||
|
},
|
||||||
|
"license": "MIT",
|
||||||
|
"publishConfig": {
|
||||||
|
"registry": "https://registry.npmjs.org",
|
||||||
|
"access": "public"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/honojs/middleware.git"
|
||||||
|
},
|
||||||
|
"homepage": "https://github.com/honojs/middleware",
|
||||||
|
"peerDependencies": {
|
||||||
|
"hono": "*"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"hono": "^3.11.7",
|
||||||
|
"tsup": "^7.2.0",
|
||||||
|
"vitest": "^0.34.5"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,195 @@
|
||||||
|
import type { Context } from 'hono'
|
||||||
|
import type { CustomSwaggerUIOptions } from './types'
|
||||||
|
|
||||||
|
const DEFAULT_VERSION = '4.13.1'
|
||||||
|
|
||||||
|
const CDN_LINK = 'https://cdn.jsdelivr.net/npm/swagger-editor-dist'
|
||||||
|
|
||||||
|
export const MODERN_NORMALIZE_CSS = `
|
||||||
|
*,
|
||||||
|
::before,
|
||||||
|
::after {
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
html {
|
||||||
|
font-family:
|
||||||
|
system-ui,
|
||||||
|
'Segoe UI',
|
||||||
|
Roboto,
|
||||||
|
Helvetica,
|
||||||
|
Arial,
|
||||||
|
sans-serif,
|
||||||
|
'Apple Color Emoji',
|
||||||
|
'Segoe UI Emoji';
|
||||||
|
line-height: 1.15; /* 1. Correct the line height in all browsers. */
|
||||||
|
-webkit-text-size-adjust: 100%; /* 2. Prevent adjustments of font size after orientation changes in iOS. */
|
||||||
|
tab-size: 4; /* 3. Use a more readable tab size (opinionated). */
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
b,
|
||||||
|
strong {
|
||||||
|
font-weight: bolder;
|
||||||
|
}
|
||||||
|
|
||||||
|
code,
|
||||||
|
kbd,
|
||||||
|
samp,
|
||||||
|
pre {
|
||||||
|
font-family:
|
||||||
|
ui-monospace,
|
||||||
|
SFMono-Regular,
|
||||||
|
Consolas,
|
||||||
|
'Liberation Mono',
|
||||||
|
Menlo,
|
||||||
|
monospace; /* 1 */
|
||||||
|
font-size: 1em; /* 2 */
|
||||||
|
}
|
||||||
|
|
||||||
|
small {
|
||||||
|
font-size: 80%;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub,
|
||||||
|
sup {
|
||||||
|
font-size: 75%;
|
||||||
|
line-height: 0;
|
||||||
|
position: relative;
|
||||||
|
vertical-align: baseline;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub {
|
||||||
|
bottom: -0.25em;
|
||||||
|
}
|
||||||
|
|
||||||
|
sup {
|
||||||
|
top: -0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
table {
|
||||||
|
border-color: currentcolor;
|
||||||
|
}
|
||||||
|
|
||||||
|
button,
|
||||||
|
input,
|
||||||
|
optgroup,
|
||||||
|
select,
|
||||||
|
textarea {
|
||||||
|
font-family: inherit; /* 1 */
|
||||||
|
font-size: 100%; /* 1 */
|
||||||
|
line-height: 1.15; /* 1 */
|
||||||
|
margin: 0; /* 2 */
|
||||||
|
}
|
||||||
|
|
||||||
|
button,
|
||||||
|
[type='button'],
|
||||||
|
[type='reset'],
|
||||||
|
[type='submit'] {
|
||||||
|
-webkit-appearance: button;
|
||||||
|
}
|
||||||
|
|
||||||
|
legend {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
progress {
|
||||||
|
vertical-align: baseline;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-inner-spin-button,
|
||||||
|
::-webkit-outer-spin-button {
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
[type='search'] {
|
||||||
|
-webkit-appearance: textfield; /* 1 */
|
||||||
|
outline-offset: -2px; /* 2 */
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-search-decoration {
|
||||||
|
-webkit-appearance: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-file-upload-button {
|
||||||
|
-webkit-appearance: button; /* 1 */
|
||||||
|
font: inherit; /* 2 */
|
||||||
|
}
|
||||||
|
|
||||||
|
summary {
|
||||||
|
display: list-item;
|
||||||
|
}
|
||||||
|
|
||||||
|
.Pane2 {
|
||||||
|
overflow-y: scroll;
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
function getUrl(version?: string) {
|
||||||
|
return `${CDN_LINK}@${version ? version : DEFAULT_VERSION}`
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SwaggerEditorOptions extends CustomSwaggerUIOptions {
|
||||||
|
version?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export function swaggerEditor(options: SwaggerEditorOptions = {}) {
|
||||||
|
const url = getUrl()
|
||||||
|
|
||||||
|
options.layout = 'StandaloneLayout'
|
||||||
|
|
||||||
|
const optionString = Object.entries(options)
|
||||||
|
.map(([key, value]) => {
|
||||||
|
if (typeof value === 'string') {
|
||||||
|
return `${key}:'${value}'`
|
||||||
|
}
|
||||||
|
if (Array.isArray(value)) {
|
||||||
|
return `${key}:${value.map((v) => `${v}`).join(', ')}`
|
||||||
|
}
|
||||||
|
if (typeof value === 'object') {
|
||||||
|
return `${key}:${JSON.stringify(value)}`
|
||||||
|
}
|
||||||
|
|
||||||
|
return `${key}: ${value}`
|
||||||
|
})
|
||||||
|
.join(',')
|
||||||
|
|
||||||
|
return async (c: Context) =>
|
||||||
|
c.html(`
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>Swagger Editor</title>
|
||||||
|
<style>
|
||||||
|
${MODERN_NORMALIZE_CSS}
|
||||||
|
</style>
|
||||||
|
<link href="${url}/swagger-editor.css" rel="stylesheet">
|
||||||
|
<link rel="icon" type="image/png" href="${url}/favicon-32x32.png" sizes="32x32" />
|
||||||
|
<link rel="icon" type="image/png" href="${url}/favicon-16x16.png" sizes="16x16" />
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div id="swagger-editor"></div>
|
||||||
|
<script src="${url}/swagger-editor-bundle.js"> </script>
|
||||||
|
<script src="${url}/swagger-editor-standalone-preset.js"> </script>
|
||||||
|
<script>
|
||||||
|
window.onload = function() {
|
||||||
|
const editor = SwaggerEditorBundle({
|
||||||
|
dom_id: '#swagger-editor',
|
||||||
|
presets: [
|
||||||
|
SwaggerEditorStandalonePreset
|
||||||
|
],
|
||||||
|
queryConfigEnabled: true,
|
||||||
|
${optionString}
|
||||||
|
})
|
||||||
|
window.editor = editor
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
`)
|
||||||
|
}
|
|
@ -0,0 +1,297 @@
|
||||||
|
export interface CustomSwaggerUIOptions {
|
||||||
|
/**
|
||||||
|
* URL to fetch external configuration document from.
|
||||||
|
*/
|
||||||
|
configUrl?: string | undefined
|
||||||
|
/**
|
||||||
|
* A JavaScript object describing the OpenAPI definition. When used, the url parameter will not be parsed. This is useful for testing manually-generated definitions without hosting them
|
||||||
|
*/
|
||||||
|
spec?: { [propName: string]: any } | undefined
|
||||||
|
/**
|
||||||
|
* The URL pointing to API definition (normally swagger.json or swagger.yaml). Will be ignored if urls or spec is used.
|
||||||
|
*/
|
||||||
|
url?: string | undefined
|
||||||
|
|
||||||
|
// Plugin system
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of a component available via the plugin system to use as the top-level layout
|
||||||
|
* for Swagger UI.
|
||||||
|
*/
|
||||||
|
layout?: string | undefined
|
||||||
|
/**
|
||||||
|
* A Javascript object to configure plugin integration and behaviors
|
||||||
|
*/
|
||||||
|
pluginsOptions?: PluginsOptions
|
||||||
|
/**
|
||||||
|
* An array of plugin functions to use in Swagger UI.
|
||||||
|
*/
|
||||||
|
plugins?: SwaggerUIPlugin[] | undefined
|
||||||
|
/**
|
||||||
|
* An array of presets to use in Swagger UI.
|
||||||
|
* Usually, you'll want to include ApisPreset if you use this option.
|
||||||
|
*/
|
||||||
|
presets?: SwaggerUIPlugin[] | undefined
|
||||||
|
|
||||||
|
// Display
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If set to true, enables deep linking for tags and operations.
|
||||||
|
* See the Deep Linking documentation for more information.
|
||||||
|
*/
|
||||||
|
deepLinking?: boolean | undefined
|
||||||
|
/**
|
||||||
|
* Controls the display of operationId in operations list. The default is false.
|
||||||
|
*/
|
||||||
|
displayOperationId?: boolean | undefined
|
||||||
|
/**
|
||||||
|
* The default expansion depth for models (set to -1 completely hide the models).
|
||||||
|
*/
|
||||||
|
defaultModelsExpandDepth?: number | undefined
|
||||||
|
/**
|
||||||
|
* The default expansion depth for the model on the model-example section.
|
||||||
|
*/
|
||||||
|
defaultModelExpandDepth?: number | undefined
|
||||||
|
/**
|
||||||
|
* Controls how the model is shown when the API is first rendered.
|
||||||
|
* (The user can always switch the rendering for a given model by clicking the
|
||||||
|
* 'Model' and 'Example Value' links.)
|
||||||
|
*/
|
||||||
|
defaultModelRendering?: 'example' | 'model' | undefined
|
||||||
|
/**
|
||||||
|
* Controls the display of the request duration (in milliseconds) for "Try it out" requests.
|
||||||
|
*/
|
||||||
|
displayRequestDuration?: boolean | undefined
|
||||||
|
/**
|
||||||
|
* Controls the default expansion setting for the operations and tags.
|
||||||
|
* It can be 'list' (expands only the tags), 'full' (expands the tags and operations)
|
||||||
|
* or 'none' (expands nothing).
|
||||||
|
*/
|
||||||
|
docExpansion?: 'list' | 'full' | 'none' | undefined
|
||||||
|
/**
|
||||||
|
* If set, enables filtering.
|
||||||
|
* The top bar will show an edit box that you can use to filter the tagged operations that are shown.
|
||||||
|
* Can be Boolean to enable or disable, or a string, in which case filtering will be enabled
|
||||||
|
* using that string as the filter expression.
|
||||||
|
* Filtering is case sensitive matching the filter expression anywhere inside the tag.
|
||||||
|
*/
|
||||||
|
filter?: boolean | string | undefined
|
||||||
|
/**
|
||||||
|
* If set, limits the number of tagged operations displayed to at most this many.
|
||||||
|
* The default is to show all operations.
|
||||||
|
*/
|
||||||
|
maxDisplayedTags?: number | undefined
|
||||||
|
/**
|
||||||
|
* Apply a sort to the operation list of each API.
|
||||||
|
* It can be 'alpha' (sort by paths alphanumerically),
|
||||||
|
* 'method' (sort by HTTP method) or a function (see Array.prototype.sort() to know how sort function works).
|
||||||
|
* Default is the order returned by the server unchanged.
|
||||||
|
*/
|
||||||
|
operationsSorter?: SorterLike | undefined
|
||||||
|
/**
|
||||||
|
* Controls the display of vendor extension (x-) fields and values for Operations,
|
||||||
|
* Parameters, Responses, and Schema.
|
||||||
|
*/
|
||||||
|
showExtensions?: boolean | undefined
|
||||||
|
/**
|
||||||
|
* Controls the display of extensions (pattern, maxLength, minLength, maximum, minimum) fields
|
||||||
|
* and values for Parameters.
|
||||||
|
*/
|
||||||
|
showCommonExtensions?: boolean | undefined
|
||||||
|
/**
|
||||||
|
* Apply a sort to the tag list of each API.
|
||||||
|
* It can be 'alpha' (sort by paths alphanumerically)
|
||||||
|
* or a function (see Array.prototype.sort() to learn how to write a sort function).
|
||||||
|
* Two tag name strings are passed to the sorter for each pass.
|
||||||
|
* Default is the order determined by Swagger UI.
|
||||||
|
*/
|
||||||
|
tagsSorter?: SorterLike | undefined
|
||||||
|
/**
|
||||||
|
* When enabled, sanitizer will leave style, class and data-* attributes untouched
|
||||||
|
* on all HTML Elements declared inside markdown strings.
|
||||||
|
* This parameter is Deprecated and will be removed in 4.0.0.
|
||||||
|
* @deprecated
|
||||||
|
*/
|
||||||
|
useUnsafeMarkdown?: boolean | undefined
|
||||||
|
/**
|
||||||
|
* Provides a mechanism to be notified when Swagger UI has finished rendering a newly provided definition.
|
||||||
|
*/
|
||||||
|
onComplete?: (() => any) | undefined
|
||||||
|
/**
|
||||||
|
* Set to false to deactivate syntax highlighting of payloads and cURL command,
|
||||||
|
* can be otherwise an object with the activate and theme properties.
|
||||||
|
*/
|
||||||
|
syntaxHighlight?:
|
||||||
|
| false
|
||||||
|
| {
|
||||||
|
/**
|
||||||
|
* Whether syntax highlighting should be activated or not.
|
||||||
|
*/
|
||||||
|
activate?: boolean | undefined
|
||||||
|
/**
|
||||||
|
* Highlight.js syntax coloring theme to use. (Only these 6 styles are available.)
|
||||||
|
*/
|
||||||
|
theme?:
|
||||||
|
| 'agate'
|
||||||
|
| 'arta'
|
||||||
|
| 'idea'
|
||||||
|
| 'monokai'
|
||||||
|
| 'nord'
|
||||||
|
| 'obsidian'
|
||||||
|
| 'tomorrow-night'
|
||||||
|
| undefined
|
||||||
|
}
|
||||||
|
| undefined
|
||||||
|
/**
|
||||||
|
* Controls whether the "Try it out" section should be enabled by default.
|
||||||
|
*/
|
||||||
|
tryItOutEnabled?: boolean | undefined
|
||||||
|
/**
|
||||||
|
* This is the default configuration section for the the requestSnippets plugin.
|
||||||
|
*/
|
||||||
|
requestSnippets?:
|
||||||
|
| {
|
||||||
|
generators?:
|
||||||
|
| {
|
||||||
|
[genName: string]: {
|
||||||
|
title: string
|
||||||
|
syntax: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
| undefined
|
||||||
|
defaultExpanded?: boolean | undefined
|
||||||
|
/**
|
||||||
|
* e.g. only show curl bash = ["curl_bash"]
|
||||||
|
*/
|
||||||
|
languagesMask?: string[] | undefined
|
||||||
|
}
|
||||||
|
| undefined
|
||||||
|
|
||||||
|
// Network
|
||||||
|
|
||||||
|
/**
|
||||||
|
* OAuth redirect URL.
|
||||||
|
*/
|
||||||
|
oauth2RedirectUrl?: string | undefined
|
||||||
|
/**
|
||||||
|
* MUST be a function. Function to intercept remote definition,
|
||||||
|
* "Try it out", and OAuth 2.0 requests.
|
||||||
|
* Accepts one argument requestInterceptor(request) and must return the modified request,
|
||||||
|
* or a Promise that resolves to the modified request.
|
||||||
|
*/
|
||||||
|
requestInterceptor?: ((a: Request) => Request | Promise<Request>) | undefined
|
||||||
|
/**
|
||||||
|
* MUST be a function. Function to intercept remote definition,
|
||||||
|
* "Try it out", and OAuth 2.0 responses.
|
||||||
|
* Accepts one argument responseInterceptor(response) and must return the modified response,
|
||||||
|
* or a Promise that resolves to the modified response.
|
||||||
|
*/
|
||||||
|
responseInterceptor?: ((a: Response) => Response | Promise<Response>) | undefined
|
||||||
|
/**
|
||||||
|
* If set to true, uses the mutated request returned from a requestInterceptor
|
||||||
|
* to produce the curl command in the UI, otherwise the request
|
||||||
|
* beforethe requestInterceptor was applied is used.
|
||||||
|
*/
|
||||||
|
showMutatedRequest?: boolean | undefined
|
||||||
|
/**
|
||||||
|
* List of HTTP methods that have the "Try it out" feature enabled.
|
||||||
|
* An empty array disables "Try it out" for all operations.
|
||||||
|
* This does not filter the operations from the display.
|
||||||
|
*/
|
||||||
|
supportedSubmitMethods?: SupportedHTTPMethods[] | undefined
|
||||||
|
/**
|
||||||
|
* By default, Swagger UI attempts to validate specs against swagger.io's online validator.
|
||||||
|
* You can use this parameter to set a different validator URL,
|
||||||
|
* for example for locally deployed validators (Validator Badge).
|
||||||
|
* Setting it to either none, 127.0.0.1 or localhost will disable validation.
|
||||||
|
*/
|
||||||
|
validatorUrl?: string | undefined
|
||||||
|
/**
|
||||||
|
* If set to true, enables passing credentials, as defined in the Fetch standard,
|
||||||
|
* in CORS requests that are sent by the browser.
|
||||||
|
* Note that Swagger UI cannot currently set cookies cross-domain (see swagger-js#1163)
|
||||||
|
* - as a result, you will have to rely on browser-supplied
|
||||||
|
* cookies (which this setting enables sending) that Swagger UI cannot control.
|
||||||
|
*/
|
||||||
|
withCredentials?: boolean | undefined
|
||||||
|
|
||||||
|
// Macros
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function to set default values to each property in model.
|
||||||
|
* Accepts one argument modelPropertyMacro(property), property is immutable
|
||||||
|
*/
|
||||||
|
modelPropertyMacro?: ((propName: Readonly<any>) => any) | undefined
|
||||||
|
/**
|
||||||
|
* Function to set default value to parameters.
|
||||||
|
* Accepts two arguments parameterMacro(operation, parameter).
|
||||||
|
* Operation and parameter are objects passed for context, both remain immutable
|
||||||
|
*/
|
||||||
|
parameterMacro?: ((operation: Readonly<any>, parameter: Readonly<any>) => any) | undefined
|
||||||
|
|
||||||
|
// Authorization
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If set to true, it persists authorization data and it would not be lost on browser close/refresh
|
||||||
|
*/
|
||||||
|
persistAuthorization?: boolean | undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
interface PluginsOptions {
|
||||||
|
/**
|
||||||
|
* Control behavior of plugins when targeting the same component with wrapComponent.<br/>
|
||||||
|
* - `legacy` (default) : last plugin takes precedence over the others<br/>
|
||||||
|
* - `chain` : chain wrapComponents when targeting the same core component,
|
||||||
|
* allowing multiple plugins to wrap the same component
|
||||||
|
* @default 'legacy'
|
||||||
|
*/
|
||||||
|
pluginLoadType?: PluginLoadType
|
||||||
|
}
|
||||||
|
|
||||||
|
type PluginLoadType = 'legacy' | 'chain'
|
||||||
|
|
||||||
|
type SupportedHTTPMethods =
|
||||||
|
| 'get'
|
||||||
|
| 'put'
|
||||||
|
| 'post'
|
||||||
|
| 'delete'
|
||||||
|
| 'options'
|
||||||
|
| 'head'
|
||||||
|
| 'patch'
|
||||||
|
| 'trace'
|
||||||
|
|
||||||
|
type SorterLike = 'alpha' | 'method' | ((name1: string, name2: string) => number)
|
||||||
|
|
||||||
|
interface Request {
|
||||||
|
[prop: string]: any
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Response {
|
||||||
|
[prop: string]: any
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* See https://swagger.io/docs/open-source-tools/swagger-ui/customization/plugin-api/
|
||||||
|
*/
|
||||||
|
type SwaggerUIPlugin = (system: any) => {
|
||||||
|
statePlugins?:
|
||||||
|
| {
|
||||||
|
[stateKey: string]: {
|
||||||
|
actions?: Indexable | undefined
|
||||||
|
reducers?: Indexable | undefined
|
||||||
|
selectors?: Indexable | undefined
|
||||||
|
wrapActions?: Indexable | undefined
|
||||||
|
wrapSelectors?: Indexable | undefined
|
||||||
|
}
|
||||||
|
}
|
||||||
|
| undefined
|
||||||
|
components?: Indexable | undefined
|
||||||
|
wrapComponents?: Indexable | undefined
|
||||||
|
rootInjects?: Indexable | undefined
|
||||||
|
afterLoad?: ((system: any) => any) | undefined
|
||||||
|
fn?: Indexable | undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Indexable {
|
||||||
|
[index: string]: any
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
import { Hono } from 'hono'
|
||||||
|
import { swaggerEditor } from '../src'
|
||||||
|
|
||||||
|
describe('Swagger Editor Middleware', () => {
|
||||||
|
let app: Hono
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
app = new Hono()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('responds with status 200', async () => {
|
||||||
|
app.get('/swagger-editor', swaggerEditor())
|
||||||
|
|
||||||
|
const res = await app.request('/swagger-editor')
|
||||||
|
expect(res.status).toBe(200)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should contents shown', async () => {
|
||||||
|
app.get(
|
||||||
|
'/swagger-editor',
|
||||||
|
swaggerEditor({
|
||||||
|
url: 'https://petstore3.swagger.io/api/v3/openapi.json',
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
|
const res = await app.request('/swagger-editor')
|
||||||
|
const html = await res.text()
|
||||||
|
|
||||||
|
expect(html).toContain('https://petstore3.swagger.io/api/v3/openapi.json')
|
||||||
|
expect(html).toContain('https://cdn.jsdelivr.net/npm/swagger-editor-dist')
|
||||||
|
})
|
||||||
|
})
|
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"extends": "../../tsconfig.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"types": ["vitest/globals"]
|
||||||
|
},
|
||||||
|
"include": ["src/**/*.ts", "src/**/*.tsx"]
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
/// <reference types="vitest" />
|
||||||
|
import { defineConfig } from 'vitest/config'
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
test: {
|
||||||
|
globals: true,
|
||||||
|
},
|
||||||
|
})
|
12
yarn.lock
12
yarn.lock
|
@ -2622,6 +2622,18 @@ __metadata:
|
||||||
languageName: unknown
|
languageName: unknown
|
||||||
linkType: soft
|
linkType: soft
|
||||||
|
|
||||||
|
"@hono/swagger-editor@workspace:packages/swagger-editor":
|
||||||
|
version: 0.0.0-use.local
|
||||||
|
resolution: "@hono/swagger-editor@workspace:packages/swagger-editor"
|
||||||
|
dependencies:
|
||||||
|
hono: "npm:^3.11.7"
|
||||||
|
tsup: "npm:^7.2.0"
|
||||||
|
vitest: "npm:^0.34.5"
|
||||||
|
peerDependencies:
|
||||||
|
hono: "*"
|
||||||
|
languageName: unknown
|
||||||
|
linkType: soft
|
||||||
|
|
||||||
"@hono/swagger-ui@workspace:packages/swagger-ui":
|
"@hono/swagger-ui@workspace:packages/swagger-ui":
|
||||||
version: 0.0.0-use.local
|
version: 0.0.0-use.local
|
||||||
resolution: "@hono/swagger-ui@workspace:packages/swagger-ui"
|
resolution: "@hono/swagger-ui@workspace:packages/swagger-ui"
|
||||||
|
|
Loading…
Reference in New Issue