From 10638b9f6af66a15777c25f9d669a9b425c8fb15 Mon Sep 17 00:00:00 2001 From: Rob Campbell Date: Thu, 7 Nov 2024 21:02:27 -0500 Subject: [PATCH 1/6] add the ability to customize the decorator --- README.md | 80 ++++++++++++++++++++++++++++++++++++++------- lib/mode/dynamic.js | 3 +- lib/mode/static.js | 2 +- test/decorator.js | 12 +++++++ 4 files changed, 83 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index b6348104..5822dc9d 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,61 @@ 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 + + if (url.startsWith('/internal')) 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 + + if (url.startsWith('/external')) 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..580095af 100644 --- a/test/decorator.js +++ b/test/decorator.js @@ -33,3 +33,15 @@ 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() + + await fastify.ready() + t.ok(fastify.customSwaggerDecorator()) +}) From 9fd09334718d9fa4bff341d782aa207f801d1641 Mon Sep 17 00:00:00 2001 From: Robert Campbell Date: Sat, 9 Nov 2024 12:33:55 -0500 Subject: [PATCH 2/6] Update README.md fix inverted transform examples Signed-off-by: Robert Campbell --- README.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 5822dc9d..b38f5d5e 100644 --- a/README.md +++ b/README.md @@ -381,9 +381,10 @@ await fastify.register(require('@fastify/swagger'), { response, ...transformedSchema } = schema - let transformedUrl = url + let transformedUrl = URL - if (url.startsWith('/internal')) transformedSchema.hide = true + // Hide external URLs + if (url.startsWith('/external')) transformedSchema.hide = true return { schema: transformedSchema, url: transformedUrl } }, @@ -402,9 +403,10 @@ await fastify.register(require('@fastify/swagger'), { response, ...transformedSchema } = schema - let transformedUrl = url + let transformedUrl = URL - if (url.startsWith('/external')) transformedSchema.hide = true + // Hide internal URLs + if (url.startsWith('/internal')) transformedSchema.hide = true return { schema: transformedSchema, url: transformedUrl } }, From f7e6a455cc74eb0b1163878eb52aac7442548c9d Mon Sep 17 00:00:00 2001 From: Rob Campbell Date: Mon, 11 Nov 2024 22:37:36 -0500 Subject: [PATCH 3/6] remove extra ready --- test/decorator.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/decorator.js b/test/decorator.js index 580095af..99781874 100644 --- a/test/decorator.js +++ b/test/decorator.js @@ -40,8 +40,6 @@ test('decorator can be overridden', async (t) => { await fastify.register(fastifySwagger, { decorator: 'customSwaggerDecorator' }) - await fastify.ready() - await fastify.ready() t.ok(fastify.customSwaggerDecorator()) }) From 498dd1db963354625b9f2d45b376a6229ec1b14e Mon Sep 17 00:00:00 2001 From: Frazer Smith Date: Thu, 21 Nov 2024 19:14:12 +0000 Subject: [PATCH 4/6] Update README.md Signed-off-by: Frazer Smith --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b38f5d5e..5b66296c 100644 --- a/README.md +++ b/README.md @@ -391,7 +391,7 @@ await fastify.register(require('@fastify/swagger'), { decorator: 'internalSwagger' }) -// Create an external swagger doc +// Create an external Swagger doc await fastify.register(require('@fastify/swagger'), { swagger: { ... }, transform: ({ schema, url, route, swaggerObject }) => { From 906ee109e345335c762d86afdea3737cc2770690 Mon Sep 17 00:00:00 2001 From: Frazer Smith Date: Thu, 21 Nov 2024 19:14:24 +0000 Subject: [PATCH 5/6] Update README.md Signed-off-by: Frazer Smith --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5b66296c..83645d6f 100644 --- a/README.md +++ b/README.md @@ -369,7 +369,7 @@ To deep down the `buildLocalReference` arguments, you may read the [documentatio 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 +// Create an internal Swagger doc await fastify.register(require('@fastify/swagger'), { swagger: { ... }, transform: ({ schema, url, route, swaggerObject }) => { From e7207288548d8b5b33df2a97c365809991ba4910 Mon Sep 17 00:00:00 2001 From: Frazer Smith Date: Thu, 21 Nov 2024 19:14:42 +0000 Subject: [PATCH 6/6] Update README.md Signed-off-by: Frazer Smith --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 83645d6f..908c9f13 100644 --- a/README.md +++ b/README.md @@ -366,7 +366,7 @@ To deep down the `buildLocalReference` arguments, you may read the [documentatio #### 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: +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