diff --git a/README.md b/README.md index 17dd3c14..713dc8bb 100644 --- a/README.md +++ b/README.md @@ -230,18 +230,19 @@ An example of using `@fastify/swagger` with `static` mode enabled can be found [ #### Options - | Option | Default | Description | - | ---------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------- | - | hiddenTag | X-HIDDEN | Tag to control hiding of routes. | - | hideUntagged | false | If `true` remove routes without tags from resulting Swagger/OpenAPI schema file. | - | initOAuth | {} | Configuration options for [Swagger UI initOAuth](https://swagger.io/docs/open-source-tools/swagger-ui/usage/oauth2/). | - | openapi | {} | [OpenAPI configuration](https://swagger.io/specification/#oasObject). | - | stripBasePath | true | Strips base path from routes in docs. | - | swagger | {} | [Swagger configuration](https://swagger.io/specification/v2/#swaggerObject). | - | transform | null | Transform method for the route's schema and url. [documentation](#register.options.transform). | | - | transformObject | null | Transform method for the swagger or openapi object before it is rendered. [documentation](#register.options.transformObject). | | - | refResolver | {} | Option to manage the `$ref`s of your application's schemas. Read the [`$ref` documentation](#register.options.refResolver) | - | exposeHeadRoutes | false | Include HEAD routes in the definitions | + | Option | Default | Description | + | ---------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------- | + | hiddenTag | X-HIDDEN | Tag to control hiding of routes. | + | hideUntagged | false | If `true` remove routes without tags from resulting Swagger/OpenAPI schema file. | + | initOAuth | {} | Configuration options for [Swagger UI initOAuth](https://swagger.io/docs/open-source-tools/swagger-ui/usage/oauth2/). | + | openapi | {} | [OpenAPI configuration](https://swagger.io/specification/#oasObject). | + | stripBasePath | true | Strips base path from routes in docs. | + | swagger | {} | [Swagger configuration](https://swagger.io/specification/v2/#swaggerObject). | + | transform | null | Transform method for the route's schema and url. [documentation](#register.options.transform). | + | transformObject | null | Transform method for the swagger or openapi object before it is rendered. [documentation](#register.options.transformObject). | + | refResolver | {} | Option to manage the `$ref`s of your application's schemas. Read the [`$ref` documentation](#register.options.refResolver) | + | exposeHeadRoutes | false | Include HEAD routes in the definitions | + | decorator | 'swagger' | Overrides the Fastify decorator. [documentation](#register.options.decorator). | #### Transform @@ -362,6 +363,63 @@ await fastify.register(require('@fastify/swagger'), { To deep down the `buildLocalReference` arguments, you may read the [documentation](https://github.com/Eomm/json-schema-resolver#usage-resolve-one-schema-against-external-schemas). + +#### Decorator + +By passing a string to the `decorator` option, you can override the default decorator function (`fastify.swagger()`) with a custom one. This allows you to create multiple documents by registering `@fastify/swagger` multiple times with different `transform` functions: + +```js +// Create an internal Swagger doc +await fastify.register(require('@fastify/swagger'), { + swagger: { ... }, + transform: ({ schema, url, route, swaggerObject }) => { + const { + params, + body, + querystring, + headers, + response, + ...transformedSchema + } = schema + let transformedUrl = URL + + // Hide external URLs + if (url.startsWith('/external')) transformedSchema.hide = true + + return { schema: transformedSchema, url: transformedUrl } + }, + decorator: 'internalSwagger' +}) + +// Create an external Swagger doc +await fastify.register(require('@fastify/swagger'), { + swagger: { ... }, + transform: ({ schema, url, route, swaggerObject }) => { + const { + params, + body, + querystring, + headers, + response, + ...transformedSchema + } = schema + let transformedUrl = URL + + // Hide internal URLs + if (url.startsWith('/internal')) transformedSchema.hide = true + + return { schema: transformedSchema, url: transformedUrl } + }, + decorator: 'externalSwagger' +}) +``` + +You can then call those decorators individually to retrieve them: +``` +fastify.internalSwagger() +fastify.externalSwagger() +``` + ### Route options diff --git a/lib/mode/dynamic.js b/lib/mode/dynamic.js index d5bb9bf4..9cbcc9cf 100644 --- a/lib/mode/dynamic.js +++ b/lib/mode/dynamic.js @@ -13,6 +13,7 @@ module.exports = function (fastify, opts, done) { swagger: {}, transform: null, transformObject: null, + decorator: 'swagger', refResolver: { buildLocalReference (json, baseUri, fragment, i) { if (!json.title && json.$id) { @@ -31,7 +32,7 @@ module.exports = function (fastify, opts, done) { } const swagger = resolveSwaggerFunction(opts, cache, routes, Ref, done) - fastify.decorate('swagger', swagger) + fastify.decorate(opts.decorator, swagger) done() } diff --git a/lib/mode/static.js b/lib/mode/static.js index f5ffe925..1d56c640 100644 --- a/lib/mode/static.js +++ b/lib/mode/static.js @@ -56,7 +56,7 @@ module.exports = function (fastify, opts, done) { swaggerObject = opts.specification.document } - fastify.decorate('swagger', swagger) + fastify.decorate(opts.decorator || 'swagger', swagger) const cache = { swaggerObject: null, diff --git a/test/decorator.js b/test/decorator.js index 6c2288be..99781874 100644 --- a/test/decorator.js +++ b/test/decorator.js @@ -33,3 +33,13 @@ test('fastify.swagger should throw if called before ready (openapi)', async (t) t.throws(fastify.swagger.bind(fastify)) }) + +test('decorator can be overridden', async (t) => { + t.plan(1) + const fastify = Fastify() + + await fastify.register(fastifySwagger, { decorator: 'customSwaggerDecorator' }) + + await fastify.ready() + t.ok(fastify.customSwaggerDecorator()) +})