Pull to refresh

Document your express API with swagger annotations

Reading time2 min
Views9.9K

Have you ever wanted to have a swagger documentation for your express API based on annotations? I have. And unfortunately didn’t find any way of doing it without having to manually create a swagger.json file. My wish was simple as this: I want to have a clean express app with multiple endpoints and I want to keep swagger documentation for every endpoint close to the endpoint implementation, not in a separate file.


Maybe I’m just lacking some google skills, but I decided that it’d be much easier for me to create such a tool. And here it is: mgr-swagger-express


Getting started


Example here will be written in TypeScript, but the same can be done in Javascript project.
So imagine a classical express app:


image


Here we have a resource “Book” and a some basic CRUD endpoints. The question is “How would you add a cool Swagger documentation to this API?” I really wanted to do it using annotations in order to keep every endpoint documentation close to the endpoint itself.


This is what you’ll be able to do with mgr-swagger-express:
index.ts:


image


BookService.ts:


image


There is a bot more code, but now we have all swagger documentation laying near the endpoint itself.
Let’s see what’s happening here:


  • In index file, we create out express app, as usual. Also we have to initialise all middlewares (the bodyParser being the most important).
  • After this we call the SET_EXPRESS_APP to set the app object globally. This way mgr-swagger-express will be able to attach handlers to endpoints
  • Only after this we can import the service with annotations. It does not have to be a class, it could be just functions.
  • Then we create an instance of our service (or call an init function in case of not using classes)
  • And we generate swagger config based on all of the annotations we have in the project and attach it to our app using swagger-ui-express package

Inside the service, there are multiple things going on, but let’s stop on a couple of them only. Everything else you can easily find in the mgr-swagger-express repo:


  • In the constructor we call addSwaggerDefinition function. It registers a swagger model with a given name. in our case we define BookDefinition under a Book name in order to reference it afterwards by #/definitions/Book
  • All handlers are annotated with @GET @POST @PUT @DELETE commands. All of them are taking in arguments an object of type SwaggerEndpoint:
    path: string;
    auth?: string;
    description?: string;
    tags?: string[];
    parameters?: SwaggerURLParameter[];
    query?: SwaggerQueryParameter;
    body?: SwaggerBodyParameter;
    success?: SwaggerSuccessResponse;

    It’s basically the classical swagger endpoint definition object, nothing special, except for the auth field, but I’ll come back to it in the future


    All handlers should have the following signature:
    (args: object, context: Context) => Promise<any>

    The args object contains all parameters pathed to your endpoint. It can be URL parameters (like book_id in our example), query parameters or even body value.



    The context object is used for handling authentication and security, but again, about it later.


    Conclusion


    Now we have a simple CRUD express API annotated with Swagger and a beautiful swagger UI, where all Swagger definitions are laying nearby the endpoint implementation. As usual — always glad to have any feedback! ️

Tags:
Hubs:
Total votes 1: ↑0 and ↓1-1
Comments3

Articles