Implement Swagger and tsoa to an existing Node application using webpack and pm2
Ahmed Khalil Bejaoui — https://abejaoui.com
In this article we will discover together to needed steps to implement swagger in our application.
For that please read the list of goals and especially the pre-requisites to make sure you are ready.
Goals:
Use an existing NodeJs application built with typescript, webpack and pm2 to implement Swagger with tsoa.
- Install and configure tsoa
- Generate routes and swagger config
- Create a new controller that have tsoa experimental decorators to get, tag and process data.
- Install Swagger-ui tool and add it to our server
- Write tests to check if our implementation is working
- run and test our application with swagger-ui
The final work can be accessible in this git repo.
Pre-requisites:
- Make sure you read this article talking about how to build and configure the full structure of nodejs with typescript, webpack and pm2.
- Make sure you cloned this repo and installed all the dependencies.
#clone the repo
git clone https://github.com/AhmedCommando/node-typescript-webpack.git#install all the dependencies
yarn install#check if everything is ok
yarn start:dev#navigate to localhost:3000 and check if you can see the hello world message. Or you can just run the test by
yarn test
What is Swagger ?
Swagger allows you to describe the structure of your APIs so that machines can read them.
So in general, the api will provide the full structure and give it to swagger through a JSON or a YAML configuration. This configuration will contain all the details about all the services the api gives. A list of routes presented by tags for each controller and for each function/endpoint in that controller.
Why Swagger ?
To answer this question you need to ask yourself these questions:
- Am I building a big project with many controllers/routes?
- Do i need a well documented REST API ?
- Do i have time to write the hole documentation?
Swagger is following the Open API Specifications to help you write a clean and well designed api. You don’t have time for writing? In this article you’ll learn how to generate it in seconds.
Also, Swagger is available in multiple languages.
Let’s Start
Step 1: Install tsoa
to do that just run
yarn add tsoa
Step 2: Let’s create our first controller.
Under root -> src -> create a folder named controller and a file named helloWorldController.ts
Then past this code inside it:
import { Controller, Route, Get, Tags } from 'tsoa';@Route('HelloWorld') // route name => localhost:xxx/helloWorld
@Tags('HelloWorldController') // => Under HelloWorldController tag
export class HelloWorldController extends Controller {
@Get() //specify the request type
hello(): HelloWorldInterface {
return {message: 'Hello World!'};
}
}export interface HelloWorldInterface { message: string;}
Now As soon as we started writing our code the tsconfig start working and the tslint start complaining because:
- We need to specify the moduleResolution in tsconfig file, so it can find the module of tsoa
- We need to enable the experimental decorators we are using
To do that just open your tsconfig file and add these two lines:
“moduleResolution”: “node”, #to specify that we are using node“experimentalDecorators”: true #to enable the use of @Get(),...
Step 3: Configure tsoa
In the root directory of your project create a file tsoa.json and past this JSON configuration in it:
{ "swagger": { #Swagger files to be generated
#output of files that will be generated by tsoa will be the
#root directory
"outputDirectory": ".",
#the path of entry file of our application
"entryFile": "./src/index.ts"
}, "routes": { #Routes files to be generated
"basePath": "/",
"entryFile": "./src/index.ts",
"routesDir": "./src/router"
}
}
Step 4: Generate the swagger and routes config by adding this to scripts
"tsoa:gen": "tsoa routes && tsoa swagger"#then you can call it by using this commandyarn tsoa:gen
Check you directory for swagger.json and your source folder for router/routes.ts
Step 5: Call and use the routes in our index.ts
import { RegisterRoutes } from './router/routes';#we start by importing our generated routes file
then we need to change the routes function to this
// Configure API endpoints.
private routes(): void {
// use generated routes by tsoa for swagger-ui
RegisterRoutes(this.express);
}
Step 6: Start swagger-ui
Now we should create a function, i will name it startSwagger but feel free to choose any name you want.
/**
* start swagger-ui express server and setup the documentation to be served
*/
private startSwagger(): void {
try {
#we call the generated swagger documentation
const swaggerDoc = require('../swagger.json');
#We start swaggerUi express server and setup the documentation
this.express.use('/doc', swaggerUI.serve, swaggerUI.setup(swaggerDoc)); # we are using /doc for swagger-ui
} catch (error) {
logger.error(error); #if error we will use winston to log it
}
}and in the constructor just add the call to this functionthis.startSwagger();
Step 7: Writing tests
In our helloWorld.test.ts file change the first test to
it('should GET', async () => {
#We call our new controller
const res = await request(App).get('/HelloWorld');
#We should get a 200 status
expect(res.status).to.equal(200)
#We should have json response type
expect(res.type).to.equal('application/json');
#We should get Hello World message
expect(res.body.message).to.equal('Hello World!');
});
And voilaa:
Now let’s generate and update once again our configruation by running
yarn tsoa:gen#you can add this to the build process so it will be called after every change
And navigate to localhost:3000/docs
What’s next
I will create more Typescript node.js projects by following this boilerplate. we will explore docker and use it to build our way to micro services.