Skip to content

Commit

Permalink
feat: pass swagger-ui additional configuration (#351)
Browse files Browse the repository at this point in the history
* feat(index): xhr request for uiConfig

* fix(index): /uiConfig path

* fix(index): ../uiConfig path

* fix: test with resolveUrl

* fix: resolved path to uiConfig

* fix: completed configuration

* feat(tests): added test for uiConfig route

* fix: npm test script

* docs: updated README

* fix: npm run test

* test: refactor test

* feat: replace entire <script>

Co-authored-by: HighSoftWare96 <[email protected]>
  • Loading branch information
Giovanni Bertoncelli and gbertoncelli authored Feb 3, 2021
1 parent f41befc commit 3c2a38e
Show file tree
Hide file tree
Showing 6 changed files with 121 additions and 30 deletions.
42 changes: 28 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,10 @@ fastify.register(require('fastify-swagger'), {
}
}
},
uiConfig: {
docExpansion: 'full',
deepLinking: false
},
exposeRoute: true
})

Expand Down Expand Up @@ -167,14 +171,17 @@ fastify.ready(err => {

##### options

| option | default | description |
|---------------|----------|---------------------------------------|
| exposeRoute | false | Exposes documentation route. |
| hiddenTag | X-HIDDEN | Tag to control hiding of routes. |
| stripBasePath | true | Strips base path from routes in docs. |
| swagger | {} | Swagger configuration. |
| openapi | {} | Openapi configuration. |
| transform | null | Transform method for schema. |
| option | default | description |
| ------------- | -------- | ------------------------------------------------------------------------------------------------------------------------- |
| exposeRoute | false | Exposes documentation route. |
| hiddenTag | X-HIDDEN | Tag to control hiding of routes. |
| stripBasePath | true | Strips base path from routes in docs. |
| swagger | {} | Swagger configuration. |
| openapi | {} | Openapi configuration. |
| transform | null | Transform method for schema. |
| uiConfig* | {} | Configuration options for [Swagger UI](https://github.com/swagger-api/swagger-ui/blob/master/docs/usage/configuration.md) |

> `uiConfig` accepts only literal (number/string/object) configuration values since they are serialized in order to pass them to the generated UI. For more details see: [#5710](https://github.com/swagger-api/swagger-ui/issues/5710).
##### 2XX status code
`fastify` itself support the `2xx`, `3xx` status, however `swagger` itself do not support this featuer. We will help you to transform the `2xx` status code into `200` and we will omit `2xx` status code when you already declared `200` status code.
Expand Down Expand Up @@ -226,17 +233,20 @@ Example:
By default, this is the directory where the main spec file is located. Provided value should be an absolute path **without** trailing slash.
<a name="additional"></a>
#### additional

If you pass `{ exposeRoute: true }` during the registration the plugin will expose the documentation with the following apis:

| url | description |
|-------|----------------|
|`'/documentation/json'` | the json object representing the api |
|`'/documentation/yaml'` | the yaml object representing the api |
|`'/documentation/'` | the swagger ui |
|`'/documentation/*'`| external files which you may use in `$ref`|
| url | description |
| ----------------------- | ------------------------------------------ |
| `'/documentation/json'` | the json object representing the api |
| `'/documentation/yaml'` | the yaml object representing the api |
| `'/documentation/'` | the swagger ui |
| `'/documentation/*'` | external files which you may use in `$ref` |

##### Overwrite swagger url end-point

If you would like to overwrite the `/documentation` url you can use the `routePrefix` option.

```js
fastify.register(require('fastify-swagger'), {
swagger: {
Expand All @@ -254,7 +264,9 @@ fastify.register(require('fastify-swagger'), {
```
##### Convert routes schema
If you would like to use different schemas like, let's say [Joi](https://github.com/hapijs/joi), you can pass a synchronous `transform` method in the options to convert them back to standard JSON schemas expected by this plugin to generate the documentation (`dynamic` mode only).
```js
const convert = require('joi-to-json-schema')

Expand All @@ -280,7 +292,9 @@ fastify.register(require('fastify-swagger'), {
```
<a name="swagger.options"></a>
### swagger options
Calling `fastify.swagger` will return to you a JSON object representing your api, if you pass `{ yaml: true }` to `fastify.swagger`, it will return you a yaml string.
### Open API (OA) Parameter Options
Expand Down
3 changes: 2 additions & 1 deletion lib/mode/dynamic.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ module.exports = function (fastify, opts, done) {

if (opts.exposeRoute === true) {
const prefix = opts.routePrefix || '/documentation'
fastify.register(require('../routes'), { prefix })
const uiConfig = opts.uiConfig || {}
fastify.register(require('../routes'), { prefix, uiConfig })
}

const cache = {
Expand Down
9 changes: 9 additions & 0 deletions lib/routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,15 @@ function fastifySwagger (fastify, opts, done) {
}
})

fastify.route({
url: '/uiConfig',
method: 'GET',
schema: { hide: true },
handler: (req, reply) => {
reply.send(opts.uiConfig)
}
})

fastify.route({
url: '/json',
method: 'GET',
Expand Down
55 changes: 44 additions & 11 deletions lib/util/prepare-swagger-ui.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,18 +24,51 @@ filesToCopy.forEach(filename => {
})

const newIndex = fs.readFileSync(resolve('./static/index.html'), 'utf8')
.replace('window.ui = ui', `window.ui = ui
.replace(/<script>((.| |\n)*)<\/script>/, `
<script>
window.onload = function () {
function resolveUrl (url) {
const anchor = document.createElement('a')
anchor.href = url
return anchor.href
}
function resolveUrl (url) {
const anchor = document.createElement('a')
anchor.href = url
return anchor.href
}`)
.replace(
/url: "(.*)",/,
`url: resolveUrl('./json').replace('static/json', 'json'),
oauth2RedirectUrl: resolveUrl('./oauth2-redirect.html'),`
)
function resolveConfig (cb) {
return fetch(
resolveUrl('./uiConfig').replace('static/uiConfig', 'uiConfig')
)
.then(res => res.json())
.then((config) => {
const resConfig = Object.assign({}, {
dom_id: '#swagger-ui',
deepLinking: true,
presets: [
SwaggerUIBundle.presets.apis,
SwaggerUIStandalonePreset
],
plugins: [
SwaggerUIBundle.plugins.DownloadUrl
],
layout: "StandaloneLayout"
}, config, {
url: resolveUrl('./json').replace('static/json', 'json'),
oauth2RedirectUrl: resolveUrl('./oauth2-redirect.html')
});
return cb(resConfig);
})
}
// Begin Swagger UI call region
const buildUi = function (config) {
const ui = SwaggerUIBundle(config)
window.ui = ui
}
// End Swagger UI call region
resolveConfig(buildUi);
}
</script>
`)

fse.writeFileSync(resolve('./static/index.html'), newIndex)

Expand Down
8 changes: 4 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
"scripts": {
"prepare": "node lib/util/prepare-swagger-ui",
"prepublishOnly": "npm run prepare",
"test": "standard && tap --100 test/**/*.js && npm run typescript",
"test:ci": "standard && tap test/**/*.js --coverage-report=lcovonly && npm run typescript",
"test": "standard && tap --100 'test/**/*.js' && npm run typescript",
"test:ci": "standard && tap 'test/**/*.js' --coverage-report=lcovonly && npm run typescript",
"typescript": "tsd"
},
"repository": {
Expand Down Expand Up @@ -41,7 +41,7 @@
"standard": "^16.0.1",
"swagger-parser": "^10.0.2",
"swagger-ui-dist": "3.41.1",
"tap": "^14.10.8",
"tap": "^14.11.0",
"tsd": "^0.14.0"
},
"dependencies": {
Expand All @@ -60,4 +60,4 @@
"tsd": {
"directory": "test/types"
}
}
}
34 changes: 34 additions & 0 deletions test/route.js
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,40 @@ test('/documentation/json route', t => {
})
})

test('/documentation/uiConfig route', t => {
t.plan(2)
const fastify = Fastify()

const uiConfig = {
docExpansion: 'full'
}

const opts = {
...swaggerOption,
uiConfig
}

fastify.register(fastifySwagger, opts)

fastify.get('/', () => {})
fastify.post('/', () => {})
fastify.get('/example', schemaQuerystring, () => {})
fastify.post('/example', schemaBody, () => {})
fastify.get('/parameters/:id', schemaParams, () => {})
fastify.get('/example1', schemaSecurity, () => {})

fastify.inject({
method: 'GET',
url: '/documentation/uiConfig'
}, (err, res) => {
t.error(err)

const payload = JSON.parse(res.payload)

t.match(payload, uiConfig, 'uiConfig should be valid')
})
})

test('fastify.swagger should return a valid swagger yaml', t => {
t.plan(4)
const fastify = Fastify()
Expand Down

0 comments on commit 3c2a38e

Please sign in to comment.