Closed Towerss closed 1 year ago
In order to have the setup you want, move the swagger definition in both routes/v1/
and routes/v2
.
Even better, adopt a modular monolith approach https://github.com/mcollina/modular_monolith/tree/main/modular. See also https://www.youtube.com/watch?v=e1jkA-ee_aY.
Thank you, @mcollina, for taking the time to guide me. I watched the presentation and followed the Git repo you shared. I tried to implement a modular monolith, so I modified the app.ts file autoload:
fastify.register(AutoLoad, {
dir: join(__dirname, 'modules'),
encapsulate: false,
maxDepth: 1,
});
Created the modules folder, and inside the modules folder I moved my routes in, so it looks like this:
| ├── modules
| | ├── v1
| | | ├── index.ts
| | | ├── plugins
| | | | └── swagger.ts
| | | └── routes
| | | ├── auth
| | | └── root.ts
| | └── v2
| | ├── index.ts
| | ├── plugins
| | └── routes
| | └── root.ts
This is the consent of the index.ts files I have under both, v1 and v2 routes:
import { FastifyInstance } from 'fastify';
import fp from 'fastify-plugin';
import autoload from '@fastify/autoload';
import { join } from 'path';
export default fp(async (fastify: FastifyInstance, opts) => {
fastify.register(autoload, {
dir: join(__dirname, 'plugins'),
options: {
prefix: opts.prefix,
},
});
fastify.register(autoload, {
dir: join(__dirname, 'routes'),
options: {
prefix: opts.prefix,
},
});
console.log(`Prefix: ${opts.prefix}`);
});
And that works well rendering the swagger documentation under route v1, and I can see the docs added when I use fastify.printRoutes()
:
└── (empty root node)
├── /
│ └── v
│ ├── 1 (GET, HEAD)
│ │ └── / (GET, HEAD)
│ │ ├── documentation (GET, HEAD)
│ │ │ └── / (GET, HEAD)
│ │ │ ├── static/
│ │ │ │ ├── index.html (GET, HEAD)
│ │ │ │ ├── swagger-initializer.js (GET, HEAD)
│ │ │ │ └── * (HEAD, GET)
│ │ │ ├── json (GET, HEAD)
│ │ │ ├── yaml (GET, HEAD)
│ │ │ └── * (GET, HEAD)
│ │ └── auth/
│ └── 2 (GET, HEAD)
│ └── / (GET, HEAD)
└── * (OPTIONS)
However, when I add a second swagger file at v2/plugins/swagger.ts
, I receive this error, and the server does not start:
[ERROR] 14:00:27 FastifyError: The decorator 'swagger' has already been added!
I think there should be a way to make the routePrefix option for @fastify/swagger-ui
dynamic, or maybe somehow make it accessible in the swaggerObject
, so it can be modified with the transformSpecification: (swaggerObject, request, reply) => {}
function.
If you could, please give me more hints, that would be really appreciated.
Thank you for your time.
For this to work, you need to remove the use of fastify-plugin in your modules/v1/index.ts
and modules/v2/index.ts
.
Thank you, @mcollina for your help.
Prerequisites
Fastify version
4.17.0
Plugin version
8.4.0
Node.js version
18.16.0
Operating system
Windows
Operating system version (i.e. 20.04, 11.3, 10)
10
Description
Hello, Fastify community,
I'm currently working on a Fastify project where I aim to generate separate Swagger documentation for different versions of my API routes (e.g., v1, v2, etc.). I'm using @fastify/swagger@8.4.0, @fastify/swagger-ui@1.8.1, @fastify/autoload@5.7.1, fastify@4.17.0, and fastify-plugin@4.5.0.
I have the following folder structure:
├── src | ├── app.ts | ├── config | ├── controllers | ├── middleware | ├── models | ├── plugins | | ├── cors.ts | | ├── helmet.ts | | ├── sensible.ts | | └── swagger.ts | ├── routes | | ├── v1 | | └── v2 | ├── server.ts | ├── services | └── utils | └── tsconfig.json └── tsconfig.json
I'm running into issues where the paths object in the transformSpecification function seems to be empty. There are no paths for the @fastify/swagger-ui plugin to render:
So the UI renders without any data:
I wondered if anyone had any insights into what I might be doing wrong or if there are alternative approaches to achieve the same goal. Any help or guidance would be greatly appreciated!
Steps to Reproduce
Use @fastify/autoload@5.7.1 to load plugins and routes:
Register routes as plugins. this route is root in folder v1:
And this is the swagger plugin registration:
Expected Behavior
That documentation is generated for different root routes, in this case, for different versions of an API, so that visiting:
It would show only the documentation for the respective v1 or v2 routes and sub-routes.