The Simplest Way to Add Swagger to a Node.js Project
Install OpenAPI to an Existing Project
Install library
Run npm i swagger-ui-express to install Swagger UI Express.
Add Swagger documents
There are two choices from here for the format:
- JSON
- TypeScript extension
use the Typescript extension to create a good reusable and readable swagger document.
export const swaggerDocument = {
openapi: '3.0.1',
info: {
version: '1.0.0',
title: 'APIs Document',
description: 'your description here',
termsOfService: '',
contact: {
name: 'Tran Son hoang',
email: 'son.hoang01@gmail.com',
url: 'https://hoangtran.co'
},
license: {
name: 'Apache 2.0',
url: 'https://www.apache.org/licenses/LICENSE-2.0.html'
}
}
}
Inject the document into the project
We just need to import the library swagger-ui-express and your swagger.ts file to your server.
Here I add it into the project using the URL /api-docs
Simple Guide to Writing Good Documentation
To add more information for servers, we have DEV, SIT, UAT, and maybe Pre-Production environment for our API service.
export const swaggerDocument = {
...
servers: [
{
url: 'http://localhost:3000/api/v1',
description: 'Local server'
},
{
url: 'https://app-dev.herokuapp.com/api/v1',
description: 'DEV Env'
},
{
url: 'https://app-uat.herokuapp.com/api/v1',
description: 'UAT Env'
}
],
...
}
if you want to have dynamic ports, environment name, and a base path? We can apply variables for this.
export const swaggerDocument = {
...
servers: [
{
"url": "https://{env}.gigantic-server.com:{port}/{basePath}",
"description": "The production API server",
"variables": {
"env": {
"default": "app-dev",
"description": "DEV Environment"
},
"port": {
"enum": [
"8443",
"3000",
"443"
],
"default": "8443"
},
"basePath": {
"default": "v1"
}
}
}
],
...
}
How can you add authorization to Swagger?
export const swaggerDocument = {
...
components: {
schemas: {},
securitySchemes: {
bearerAuth: {
type: 'http',
scheme: 'bearer',
bearerFormat: 'JWT'
}
}
}
...
}
The sample code above is for adding JWT to a request header to authorize the user's permissions. We also have other authentication types like:
Basic Authentication
{
"type": "http",
"scheme": "basic"
}
API Key
{
"type": "apiKey",
"name": "api_key",
"in": "header"
}
Implicit OAuth2
{
"type": "oauth2",
"flows": {
"implicit": {
"authorizationUrl": "https://example.com/api/oauth/dialog",
"scopes": {
"write:pets": "modify pets in your account",
"read:pets": "read your pets"
}
}
}
}
Split out the swagger into smaller files
Create one file called pets.swagger.ts inside src/openAPI
export const getPets = {
tags: ['Pets'],
description: "Returns all pets from the system that the user has access to",
operationId: 'getPets',
security: [
{
bearerAuth: []
}
],
responses: {
"200": {
description: "A list of pets.",
"content": {
"application/json": {
schema: {
type: "array",
items: {
pet_name: {
type: 'string',
description: 'Pet Name'
},
pet_age: {
type: 'string',
description: 'Pet Age'
}
}
}
}
}
}
}
}
Import getPets to swagger.ts
import { getPets } from './openAPIs/pets.swagger';
export const swaggerDocument = {
...
tags: [
{
name: 'Pets'
}
],
paths: {
"/pets": {
"get": getPets
}
}
...
}
By using Typescript, we can split the document into many small files based on business logic. This makes our swagger document is more readable and maintainable.
