Creating API Documentation with Swagger on NodeJS

chauhoangminhnguyen

chauhoangminhnguyen

Posted on July 13, 2024

Creating API Documentation with Swagger on NodeJS

Introduction

Swagger is a popular, simple, and user-friendly tool for creating APIs. Most backend developers, regardless of the programming languages they use, are familiar with Swagger. This article will guide you through creating API documentation using Swagger on Node.js (specifically integrated with the Express framework). This is handy when you want to provide API documentation in a professional UI format for stakeholders involved in integration.

NodeJS Swagger

Restful API

REST stands for Representational State Transfer. It is an architectural style that defines a set of constraints for creating web services. RESTful APIs provide a simple and flexible way to access web services without complex processing.

Common HTTP Methods in RESTful APIs:

- GET: Used to read (retrieve) a representation of a resource. It returns data in XML or JSON format.

- POST: Creates new resources or subordinates to existing ones.

- PUT: Updates existing resources or creates new ones if the client chooses the resource ID.

- PATCH: Partially modifies resources, describing changes rather than sending the entire resource.

- DELETE: Removes a resource.

Building API and API Documentation with Swagger

In this example, we'll use Node.js, Express, and Swagger. First, let's set up a Node.js project and install the necessary packages:

yarn add express swagger-jsdoc swagger-ui-express
yarn add -D @types/swagger-jsdoc @types/swagger-ui-express
Enter fullscreen mode Exit fullscreen mode

Create a file named swagger.ts with Swagger document configuration as follows:

import * as swaggerJsdoc from 'swagger-jsdoc'
import * as swaggerUi from 'swagger-ui-express'

const options = {
  definition: {
    openapi: '3.0.0',
    info: {
      title: 'Employee API',
      description: 'Example of CRUD API ',
      version: '1.0.0',
    },
  },
  apis: ['./router/*.ts'], // path to routers
}

const swaggerSpec = swaggerJsdoc(options)

export function swaggerDocs(app, port) {
  app.use('/docs', swaggerUi.serve, swaggerUi.setup(swaggerSpec))
  app.get('/docs.json', (req, res) => {
    res.setHeader('Content-Type', 'application/json')
    res.send(swaggerSpec)
  })
}
Enter fullscreen mode Exit fullscreen mode

Next up is the index.ts file for integrating Express and Swagger.

import * as express from 'express'
import router from './router'
import {swaggerDocs} from './swagger'

const app = express()
const port = 3000
app
  .use(express.json())
  .use(router)
  .listen(port, () => {
    console.log(`Listening at http://localhost:${port}`)
    swaggerDocs(app, port)
  })
Enter fullscreen mode Exit fullscreen mode

To set up the API routers, I'll create a file named router.ts and define the API documentation right above the routers, identified by the keyword @openapi.

The APIs will include 4 methods: GET, POST, PUT, DELETE.

import * as express from 'express'
import {addEmployeeHandler, deleteEmployeeHandler, editEmployeeHandler, getEmployeesHandler} from './controller'

const router = express.Router()

/**
 * @openapi
 * '/api/employees':
 *  get:
 *     tags:
 *     - Employee
 *     summary: Get all employee
 *     responses:
 *       200:
 *         description: Success
 *         content:
 *          application/json:
 *            schema:
 *              type: array
 *              items:
 *                type: object
 *                properties:
 *                  id:
 *                    type: number
 *                  name:
 *                    type: string
 *       400:
 *         description: Bad request
 */
router.get('/api/employees', getEmployeesHandler)

/**
 * @openapi
 * '/api/employee':
 *  post:
 *     tags:
 *     - Employee
 *     summary: Create a employee
 *     requestBody:
 *      required: true
 *      content:
 *        application/json:
 *           schema:
 *            type: object
 *            required:
 *              - id
 *              - name
 *            properties:
 *              id:
 *                type: number
 *              name:
 *                type: string
 *     responses:
 *      201:
 *        description: Created
 *      409:
 *        description: Conflict
 *      404:
 *        description: Not Found
 */
router.post('/api/employee', addEmployeeHandler)

/**
 * @openapi
 * '/api/employee':
 *  put:
 *     tags:
 *     - Employee
 *     summary: Modify a employee
 *     requestBody:
 *      required: true
 *      content:
 *        application/json:
 *           schema:
 *            type: object
 *            required:
 *              - id
 *              - name
 *            properties:
 *              id:
 *                type: number
 *              name:
 *                type: string
 *     responses:
 *      200:
 *        description: Modified
 *      400:
 *        description: Bad Request
 *      404:
 *        description: Not Found
 */
router.put('/api/employee', editEmployeeHandler)

/**
 * @openapi
 * '/api/employee/{id}':
 *  delete:
 *     tags:
 *     - Employee
 *     summary: Remove employee by id
 *     parameters:
 *      - name: id
 *        in: path
 *        description: The unique id of the employee
 *        required: true
 *     responses:
 *      200:
 *        description: Removed
 *      400:
 *        description: Bad request
 *      404:
 *        description: Not Found
 */
router.delete('/api/employee/:id', deleteEmployeeHandler)

export default router
Enter fullscreen mode Exit fullscreen mode

I'll also provide an additional file named controller.ts, implemented in a simple way to handle API requests.

import {Request, Response} from 'express'

let employees = [
  {id: 1, name: 'Name 1'},
  {id: 2, name: 'Name 2'},
]

export function getEmployeesHandler(req: Request, res: Response) {
  res.status(200).json(employees)
}

export function addEmployeeHandler(req: Request, res: Response) {
  if (employees.find(employee => employee.id === req.body.id)) {
    res.status(409).json('Employee id must be unique')
  } else {
    employees.push(req.body)
    res.status(200).json(employees)
  }
}

export function deleteEmployeeHandler(req: Request, res: Response) {
  const index = employees.findIndex(employee => employee.id === +req?.params?.id)
  if (index >= 0) {
    employees.splice(index, 1)
    res.status(200).json(employees)
  } else {
    res.status(400).send()
  }
}

export function editEmployeeHandler(req: Request, res: Response) {
  const index = employees.findIndex(employee => employee.id == req.body.id)
  if (index >= 0) {
    employees.splice(index, 1, req.body)
    res.status(200).json(employees)
  } else {
    res.status(400).send()
  }
}
Enter fullscreen mode Exit fullscreen mode

After successfully starting the project, you can access the page http://localhost:3000/docs to view the API documentation in UI format generated by Swagger.

RestFul API Swagger

Conclusion

API Documentation is one of the crucial documents that back-end developers provide to stakeholders to facilitate integration (such as front-end teams).

Due to the popularity and convenience of Restful API and Swagger, it's an indispensable tool for creating API documentation in a simple, professional, and consistent UI format.

If you found this content helpful, please visit the original article on my blog to support the author and explore more interesting content.

BlogspotDev.toFacebookX

💖 💪 🙅 🚩
chauhoangminhnguyen
chauhoangminhnguyen

Posted on July 13, 2024

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related