Contents
Node.js is one of the top preferences of programming languages In cloud native application development. Many micro services provide functionality by exposing REST APIs. It's important for developers of consuming applications as well as the provider application to be able to read the definition and capabilities of each and every REST endpoint. The apidoc node module comes handy, this module helps application developers define and document the REST APIs with very less effort.
What is apidoc?
apidoc is a node plugin that can be installed in the node application. This plugin helps to write and generate REST API documents for node.js applications.
How to generate API documents using apidoc ?
First we need to install apidoc in the node.js project. Then we can use the @ parameters and formats as comments in the node.js files. After that we need to run a command to create the documentation. Apidoc scans all .js files in the path. It creates a nice human readable HTML static file from the comments in the .js files. The comments can be added in-place on top of each node route that provides the REST functionality.
A better approach though, is to separate the comments for documentation separate from code. We also can write all comments for all APIs in a separate .js file. Also, we can write a code snippet that will generate the documents automatically. Let’s see an example to understand it better.
The package.json file
{
"name": "Test-App",
"version": "1.0.0",
"devDependencies": {
"apidoc": "^0.25.0"
},
"apidoc": {
"title": "Test-App API Documentation",
"order": [
"Users",
"User"
]
},
"engines": {
"node": "^12.18.0",
"npm": "^6.14.4"
}
}
In package.json we have mentioned the apidoc version under devDependencies. Note the app name and version, it will be used in the apidoc generated document. This file also has an apidoc element, here the title of the generated apidoc HTML file can be defined. The groups names and their order can also be defined here. Read along to know what groups are groups.
The .js file with apidoc comments
Here is a users.js file that contains all the comments. The file assumes creating a document for REST APIs for user management. It contains listing all users, creating and updating a user.
/**
* @api {get} /users Get all users
* @apiDescription Returns All user names.
* @apiPermission None
* @apiName GetUsers
* @apiGroup Users
*
* @apiSuccess {Object[]} response Services metadata.
* @apiSuccess {String} response.name user name.
*
* @apiSuccessExample {json} successful response(200 OK):
[
{
"name": "user name"
}
]
*
* @apiError (Error 4XX) 404 Not Found.
* @apiError (Error 5XX) 500 Internal Server Error.
*/
/**
* @apiDefine ErrorCodes
* @apiError (Error 4XX) 400 Bad Request.
* @apiError (Error 4XX) 401 Unauthorized.
* @apiError (Error 4XX) 403 Forbidden.
* @apiError (Error 4XX) 404 Not Found.
* @apiError (Error 5XX) 500 Internal Server Error.
*/
/**
* @apiDefine UserRequestBody
* @apiParam (Body/Json Parameter) {String} email Email of user.
* @apiParam (Body/Json Parameter) {Number} age Age of user.
* @apiParam (Body/Json Parameter) {String} name Name of user.
* @apiParam (Body/Json Parameter) {String} [expdate] Optional membership expiry date.
*
* @apiParamExample {json} example request body:
* {
* "email":"name@gmail.com",
* "age":"1",
* "name": "name",
* }
*
* @apiSuccess {String} msg operation successful.
*/
/**
* @api {post} /users Create user
* @apiDescription create an user
* @apiPermission Admin
* @apiName CreateUser
* @apiGroup User
* @apiUse UserRequestBody
* @apiSuccessExample {json} successful response(200 OK):
* {"Msg":"Successfully created user with email: ***** "}
* @apiUse ErrorCodes
*/
/**
* @api {put} /users Update User
* @apiDescription Update an user
* @apiPermission Admin
* @apiName UpdateUser
* @apiGroup User
* @apiUse UserRequestBody
* @apiSuccessExample {json} Success-Response(200 OK):
* {"Msg":"Successfully updated user with id: ***** "}
* @apiUse ErrorCodes
* @apiError (Error 4XX, 5XX) 400 Bad request.
*/
The apidoc Parameters
@api : This is a mandatory parameter. When this parameters is present after the beginning of comment block (/**) apidoc starts reading the comments. It reads the comments till the closing of comment block (*/). If this parameter is not present apidoc will ignore the comments. Only exception is @apiDefine parameter where we don't need @api parameter. We can see an example of @apiDefine also in the example. The example of @api parameter is
@api {get} /users Get all users
In the first part the REST method name is specified within curly braces({get}). Then after a space we specify the API path(/users). After that a small description of the API(Get all users).
@apiDescription : This parameter is used to provide a long description of the API.
@apiName : Defines the name of an APi document. The name is used as a sub-navigator under a group. An example for this parameter is
@apiName CreateUser
@apiGroup : We can group several API documents under one group. If multiple API documents have the same group name they are listed under that group. An example for the parameter is
@apiGroup User
In thi example there are two groups used to show that different API comes under different groups. In this example the groups used are Users and User.
@apiPermission : This parameter is used to explicitly document who has access in the API. The example has two @apiPermission parameters.
@apiPermission None - Shows everyone can access this API endpoint
@apiPermission Admin - Shows only users with Admin role can access the APi endpoint
@apiSuccess : This parameter defines the structure of the returned body when a request to the API endpoint is successful. The format for this parameter looks like
@apiSuccess [(group)] [{type}] field [description]
We have an example of @apiSuccess
* @apiSuccess {Object[]} response Services metadata.
* @apiSuccess {String} response.name user name.
The group is optional and we have omitted it. Next we have used two types in curls braces ({Object[]} and {String}). The first one says it's an object array, the second one says it's a string. After type comes the field name. Here we need to look carefully the field name of the first line is response and the second line is response.name. This will result in a nested structure in the final api document. It will show that the field response is the top level element. Under the response element exists another element name. That is how we can define nested elements which is required to define the json response structures. The last in the line is a short description of the field, in the example is metadata and user name corresponding to each field.
@apiSuccessExample : used to provide an example when a request is successful. First we need to define the type of the response within curly braces. Then the title followed by the example itself. In the example
@apiSuccessExample {json} successful response(200 OK):
[
{
"name": "user name"
}
]
The type of the response example is json and the description or title is “successful response(200 OK):”
@apiError : similarly using this parameter we can define what the APi will return when an error condition occurs.
@apiDefine and @apiUse : This parameter is usefully to define a reusable part of the document that can be referenced from anywhere after it is defined. Even the definition can be in a separate file. In our example we have defined two blocks one is UserRequestBody that defines how a request body should be. We have used the same definition for POST and PUT requests that creates and updates user information. The other definition is ErrorCodes.It is used to document what will be the different error codes in different error conditions.
@apiParam: this parameter is used to define a parameter which is part of the URL or part of the request body.
The format of @apiParam is like this
@apiParam [(group)] [{type}] [field=defaultValue] [description]
The group defines under which group the parameter is, then the type defines the type of the parameter. After that a default value for the parameter can be specified. At the end a short description of the parameter.
An example in our documentation is
@apiParam (Body/Json Parameter) {String} name Name of user
Now, I have written a code that can generate the documents automatically. The file name is genAPiDoc.js and its content is given below.
const apidoc = require('apidoc');
apidoc.createDoc({
dest: "./webapp/apidoc",
src: ["./apidoc_source"]
});
The source means the documents in commented form will be read from the apidoc_source folder and the docs will be generated under the webapp/apidoc folder.
The folder structure of our small project to generate api documentation I have depicted here
apidoc_source
/users.js
node_modules
webapp
/apidoc
genAPiDoc.js
package.json
At this point we have everything to generate the HTML document. To install all NPM modules we have to run the npm install command. Then we run the node genAPiDoc.js command to generate the human readable document. You will see lots of files and folders generated under the webapp/apidoc folder. Among them you will find the index.html. This is the file where we have the output of the document in a nice human readable format.
How the generated document look like?
Below I have given the screen shot of the index.html file.
For detailed information and definition of the parameters you can refer to the apidoc documentation.
Today we have learned how we can generate human readable REST API documents for node.js applications using the apidoc node module.
Comments