A Beginner's Guide to Implementing API Documentation with Swagger (with Prisma Integration)
In today's world of web development, creating clear and comprehensive API documentation is crucial. One of the most popular tools for this purpose is Swagger (now part of the OpenAPI Initiative). This guide will walk you through the process of implementing API documentation using Swagger in a Node.js and Express environment.
What is Swagger?
Swagger is a set of open-source tools that helps developers design, build, document, and consume RESTful web services. It allows you to describe your API structure in a way that machines can read and understand.
Prerequisites
Before we begin, make sure you have the following installed:
- Node.js
- npm (Node Package Manager)
- An existing Express.js project (we'll assume you're using TypeScript)
Step 1: Installation
First, let's install the necessary packages. Open your terminal and run:
npm install swagger-jsdoc swagger-ui-express
npm install --save-dev @types/swagger-jsdoc @types/swagger-ui-express
These packages will allow us to generate Swagger documentation and serve it through a UI.
Step 2: Set Up Swagger Configuration
Create a new file named swagger.ts
in your project root and add the following code:
import swaggerJsdoc from "swagger-jsdoc";
const options = {
definition: {
openapi: "3.0.0",
info: {
title: "My API",
version: "1.0.0",
description: "A sample API for learning Swagger",
},
servers: [
{
url: "http://localhost:3000",
description: "Development server",
},
],
},
apis: ["./src/routes/*.ts"], // Path to the API docs
};
export const specs = swaggerJsdoc(options);
This configuration file sets up the basic information about your API and tells Swagger where to look for your API documentation.
Step 3: Integrate Swagger with Express
Now, let's integrate Swagger into your Express application. In your main application file (e.g., app.ts
), add the following:
import express from "express";
import swaggerUi from "swagger-ui-express";
import { specs } from "./swagger";
const app = express();
// Swagger UI
app.use("/api-docs", swaggerUi.serve, swaggerUi.setup(specs));
// Your routes and other middleware here...
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(`Server is running on port ${PORT}`);
});
This sets up a route /api-docs
which will serve your Swagger documentation.
Step 4: Document Your Routes
Now comes the fun part – documenting your actual API endpoints. You'll do this using JSDoc-style comments above your route handlers. Here's an example:
import express from "express";
const router = express.Router();
/**
* @swagger
* /api/users:
* get:
* summary: Retrieve a list of users
* description: Retrieve a list of users from the database.
* responses:
* 200:
* description: A list of users.
* content:
* application/json:
* schema:
* type: array
* items:
* type: object
* properties:
* id:
* type: integer
* description: The user ID.
* name:
* type: string
* description: The user's name.
*/
router.get("/users", (req, res) => {
// Your route logic here
});
export default router;
Adding Home Page and More routes
Okay lets Modify our index.ts file
import express from "express";
import {
createUser,
getUsers,
getUserById,
} from "../controllers/userController";
const router = express.Router();
/**
* @swagger
* /api/users:
* post:
* summary: Create a new user
* description: Creates a new user in the system.
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* properties:
* name:
* type: string
* email:
* type: string
* responses:
* 201:
* description: Created
* content:
* application/json:
* schema:
* type: object
* properties:
* id:
* type: integer
* name:
* type: string
* email:
* type: string
*/
router.post("/users", createUser);
/**
* @swagger
* /api/users:
* get:
* summary: Retrieve a list of users
* description: Retrieve a list of users from the database.
* responses:
* 200:
* description: A list of users.
* content:
* application/json:
* schema:
* type: array
* items:
* type: object
* properties:
* id:
* type: integer
* name:
* type: string
* email:
* type: string
*/
router.get("/users", getUsers);
/**
* @swagger
* /api/users/{id}:
* get:
* summary: Get a user by ID
* description: Retrieve a single user by their ID.
* parameters:
* - in: path
* name: id
* required: true
* schema:
* type: integer
* responses:
* 200:
* description: A single user.
* content:
* application/json:
* schema:
* type: object
* properties:
* id:
* type: integer
* name:
* type: string
* email:
* type: string
* 404:
* description: User not found.
*/
router.get("/users/:id", getUserById);
export default router;
Step 5: Create a Home page for the API
To create a home page for your API when a user visits the root URL ("/"), you can add a simple route in your main application file. Here's how you can do it:
- First, create a simple HTML file for your home page. You can name it
home.html
and place it in apublic
folder in your project root:
see API html with tailwind here https://play.tailwindcss.com/nn6kvKMomm (opens in a new tab)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>My API</title>
<style>
body {
font-family: Arial, sans-serif;
line-height: 1.6;
padding: 20px;
}
h1 {
color: #333;
}
a {
color: #007bff;
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
</style>
</head>
<body>
<h1>Welcome to My API</h1>
<p>
This is the home page for my API. To view the API documentation, please
visit the <a href="/api-docs">Swagger UI</a>.
</p>
</body>
</html>
- Then, in your main application file (e.g.,
app.ts
), add the following:
import express from "express";
import path from "path";
import swaggerUi from "swagger-ui-express";
import { specs } from "./swagger";
const app = express();
// Serve static files from the 'public' directory
app.use(express.static(path.join(__dirname, "public")));
// Home route
app.get("/", (req, res) => {
res.sendFile(path.join(__dirname, "public", "home.html"));
});
// Swagger UI
app.use("/api-docs", swaggerUi.serve, swaggerUi.setup(specs));
// Your API routes
app.use("/api", userRouter);
// ... rest of your server setup
Using Prisma Schema in Swagger Documentation
If you're using Prisma, you already have a well-defined schema for your database models. We can leverage this schema to generate TypeScript types and use them in our Swagger documentation. Here's how to do it:
- First, make sure you have your Prisma schema defined in
prisma/schema.prisma
. For example:
// prisma/schema.prisma
model User {
id Int @id @default(autoincrement())
name String
email String @unique
age Int?
}
- Generate Prisma client and TypeScript types:
npx prisma generate
This command generates TypeScript types based on your Prisma schema.
- Install
@prisma/client
if you haven't already:
npm install @prisma/client
- Create a file to export Prisma-generated types. Let's call it
src/models/prismaTypes.ts
:
// src/models/prismaTypes.ts
import { Prisma } from "@prisma/client";
export type User = Prisma.UserGetPayload<{}>;
export type CreateUserInput = Prisma.UserCreateInput;
- Now, we'll need to install a package that helps convert TypeScript to JSON Schema:
npm install typescript-json-schema
- Add a script to your
package.json
to generate JSON schemas:
"scripts": {
"generate-schemas": "typescript-json-schema ./src/models/prismaTypes.ts '*' --out ./src/schemas.json"
}
- Run this script to generate the JSON schemas:
npm run generate-schemas
- Update your Swagger configuration in
swagger.ts
:
import swaggerJsdoc from "swagger-jsdoc";
import schemas from "./schemas.json";
const options = {
definition: {
openapi: "3.0.0",
info: {
title: "My API",
version: "1.0.0",
description: "A sample API using Prisma and Swagger",
},
servers: [
{
url: "http://localhost:3000",
description: "Development server",
},
],
components: {
schemas: schemas,
},
},
apis: ["./src/routes/*.ts"],
};
export const specs = swaggerJsdoc(options);
- Update your route documentation to use these schemas:
// src/routes/userRoutes.ts
import express from "express";
import {
createUser,
getUsers,
getUserById,
} from "../controllers/userController";
const router = express.Router();
/**
* @swagger
* /api/users:
* post:
* summary: Create a new user
* requestBody:
* required: true
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/CreateUserInput'
* responses:
* 201:
* description: Created
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/User'
*/
router.post("/users", createUser);
/**
* @swagger
* /api/users:
* get:
* summary: Retrieve a list of users
* responses:
* 200:
* description: A list of users.
* content:
* application/json:
* schema:
* type: array
* items:
* $ref: '#/components/schemas/User'
*/
router.get("/users", getUsers);
/**
* @swagger
* /api/users/{id}:
* get:
* summary: Get a user by ID
* parameters:
* - in: path
* name: id
* required: true
* schema:
* type: integer
* responses:
* 200:
* description: A single user.
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/User'
* 404:
* description: User not found.
*/
router.get("/users/:id", getUserById);
export default router;
By following these steps, you're now using your Prisma schema to generate TypeScript types, which are then used to create JSON schemas for your Swagger documentation. This approach has several benefits:
- Your API documentation will always be in sync with your database schema.
- You can make changes to your Prisma schema and have them reflected in both your code and your documentation.
- It provides a single source of truth for your data models.
- You get the benefits of Prisma's powerful ORM along with comprehensive API documentation.
Remember to run the generate-schemas
script whenever you make changes to your Prisma schema to keep your documentation up to date.
This setup will serve the home.html
file when a user visits the root URL of your API.
Step 6: Test Your Documentation and Home Page
Start your Express server and navigate to http://localhost:3000
in your web browser. You should see your API home page. From there, you can click the link to view the Swagger UI at http://localhost:3000/api-docs
, where you'll see your documented endpoints.
Project Structure
Online Mermaid Live Editor: The easiest way is to use the Mermaid Live Editor:
Go to https://mermaid.live/ (opens in a new tab) Paste the Mermaid code into the left panel The diagram will render in the right panel Click on the "Download SVG" button at the top right In the dropdown, select "PNG" instead of SVG The PNG will be downloaded to your device
graph TD
A[Project Root] --> B[src/]
A --> C[public/]
A --> D[package.json]
A --> E[tsconfig.json]
A --> F[swagger.ts]
A --> P[prisma/]
B --> G[app.ts]
B --> H[routes/]
B --> I[controllers/]
B --> M[models/]
B --> N[schemas.json]
H --> J[userRoutes.ts]
I --> K[userController.ts]
M --> Q[prismaTypes.ts]
P --> R[schema.prisma]
C --> L[home.html]
style A fill:#f9f,stroke:#333,stroke-width:2px
style B fill:#bbf,stroke:#333,stroke-width:2px
style C fill:#bfb,stroke:#333,stroke-width:2px
style H fill:#fbb,stroke:#333,stroke-width:2px
style I fill:#fbf,stroke:#333,stroke-width:2px
style M fill:#bff,stroke:#333,stroke-width:2px
style P fill:#ffb,stroke:#333,stroke-width:2px