Skip to main content

Swagger Integration

Swagger, an open-source framework, supported by an extensive ecosystem of tools, facilitates the design, build, documentation, and consumption of RESTful Web services.

FortJs simplifies Swagger integration with its dedicated library - fortjs-swagger, enabling automatic generation of Swagger documents.

Install library

npm install fortjs-swagger

Initiate

Initiate the Swagger after the FortJs has started.

import * as path from "path";
import { Fort } from "fortjs";
import { routes } from "@/routes";
import { swagger } from "fortjs-swagger";

const swaggerPath = path.join(__dirname, "../dist/swagger/");
const initSwagger = async () => {
await swagger.create({
appInfo: {
title: "Swagger Test",
description: "Swagger Test",
version: "1.0"
},
servers: [{
description: "local",
url: "http://localhost:4000"
}],
outputPath: swaggerPath,
securitySchemes: {
basicAuth: {
type: "http",
scheme: "basic"
}
}
});
}

export const createApp = async () => {
Fort.folders = [
{
alias: "/",
path: path.join(__dirname, "../static")
},
{
alias: "/swagger",
path: swaggerPath
}
];

Fort.routes = routes;
await initSwagger();
await Fort.create();
process.env.APP_URL = `http://localhost:${Fort.port}`;
};

createApp().then(() => {
Fort.logger.debug(`Your fort has been forged and is now ready for exploration at ${process.env.APP_URL}`);
}).catch(err => {
console.error(err);
});

Start the server and navigate to the Swagger documentation path, which is http://localhost:4000/swagger/

You will see the available endpoints listed; however, documentation is currently absent. To enable proper Swagger configuration, we need to document each endpoint with relevant information.

Document API's

Fort.js includes special decorators for specifying the structure of your API endpoints. These decorators are:

  • summary: Provides a brief description of the endpoint.
  • response: Defines the expected structure of the response.
  • param: Specifies parameters in the request path.
  • query: Defines parameters in the query string.
  • security: Defines security type of the end point.

Let's apply these decorators on UserController which deals with operations related to users -

import { Controller, textResult, jsonResult, HTTP_STATUS_CODE, validate, shields, http, singleton } from 'fortjs';
import { UserService } from '@/services/user_service';
import { User } from '@/models/user';
import { swagger } from 'fortjs-swagger';
import { AuthenticationShield } from '@/shields/authentication_shield';

@shields(AuthenticationShield)
@swagger.security('basicAuth')
export class UserController extends Controller {

service: UserService;

constructor(@singleton(UserService) userService: UserService) {
super();
this.service = userService;
}


@swagger.summary('get all users')
@swagger.description('return all saved users')
@swagger.response(HTTP_STATUS_CODE.Ok, [User])
@swagger.query("offset", 1, "offset")
@swagger.query("limit", 10, "no of records in the response")
@http.get("/")
async getUsers() {
const { offset, limit } = this.query;
return jsonResult(this.service.getUsers());
}


@swagger.summary('Add user')
@swagger.response(HTTP_STATUS_CODE.Created, User)
@swagger.body(User, "User model")
@http.post("/")
@validate.body(User)
async addUser() {
const user = this.body as User;
const newUser = this.service.addUser(user);
return jsonResult(newUser, HTTP_STATUS_CODE.Created);
}

@swagger.summary('get a single user by id')
@swagger.response(HTTP_STATUS_CODE.Ok, User)
@swagger.response(HTTP_STATUS_CODE.NotFound, 'invalid user')
@swagger.param('id', 1, 'user id')
@http.get("/{id}")
async getUser() {
const userId = Number(this.param.id);
const user = this.service.getUser(userId);
if (user == null) {
return textResult("invalid user id", HTTP_STATUS_CODE.NotFound);
}
return jsonResult(user);

}
}

In the above snippet we have used swagger helpers decorators to document the API's structure. Now refresh the Swagger URL (http://localhost:4000/swagger/). You will now observe all the APIs with comprehensive documentation.

tip

Note: Certain decorators, such as response, query, etc., can be applied multiple times to represent various scenarios, providing a more thorough overview of the API's capabilities.

More resources