Swagger Plugin
The Swagger plugin automatically generates OpenAPI 3.0 documentation for your Balda.js API.
Features
- Automatic Route Discovery: Automatically discovers and documents all your routes
- Multiple UI Options: Choose between Swagger UI, ReDoc, or RapiDoc
- Type Integration: Uses your validation schemas to generate accurate request/response documentation
- Security Support: Document authentication schemes and security requirements
- Custom Models: Define reusable data models for your API
Global Configuration
Basic Setup
import { Server } from 'balda-js';
const server = new Server({
port: 3000,
swagger: {
type: "standard", // "standard" | "redoc" | "rapidoc"
path: "/docs",
title: "My API Documentation",
description: "API documentation for my application",
version: "1.0.0",
servers: ["http://localhost:3000"]
}
});
Advanced Configuration
const server = new Server({
port: 3000,
swagger: {
type: "standard",
path: "/api-docs",
title: "E-Commerce API",
description: "Complete API for our e-commerce platform",
version: "2.1.0",
servers: [
"http://localhost:3000",
"https://api.staging.example.com",
"https://api.example.com"
],
models: {
User: {
type: "object",
properties: {
id: { type: "string", format: "uuid" },
email: { type: "string", format: "email" },
name: { type: "string" },
createdAt: { type: "string", format: "date-time" }
},
required: ["email", "name"]
},
Product: {
type: "object",
properties: {
id: { type: "string" },
name: { type: "string" },
price: { type: "number" },
category: { type: "string" }
},
required: ["name", "price"]
}
}
}
});
Route-Level Documentation
Basic Route Documentation
import { controller, get, post } from 'balda-js';
import { Request, Response } from 'balda-js';
@controller('/users')
export class UsersController {
@get('/', {
swagger: {
name: "Get All Users",
description: "Retrieve a list of all users",
service: "users",
responses: {
"200": {
type: "array",
items: { $ref: "#/components/schemas/User" }
}
}
}
})
async getAllUsers(req: Request, res: Response) {
const users = await getUsers();
res.json(users);
}
@post('/', {
swagger: {
name: "Create User",
description: "Create a new user account",
service: "users",
requestBody: {
type: "object",
properties: {
email: { type: "string", format: "email" },
name: { type: "string" },
password: { type: "string", minLength: 8 }
},
required: ["email", "name", "password"]
},
responses: {
"201": {
type: "object",
properties: {
user: { $ref: "#/components/schemas/User" },
message: { type: "string" }
}
},
"400": {
type: "object",
properties: {
error: { type: "string" },
details: { type: "array", items: { type: "string" } }
}
}
}
}
})
async createUser(req: Request, res: Response) {
const user = await createUser(req.body);
res.created({ user, message: "User created successfully" });
}
}
Path Parameters
@get('/:id', {
swagger: {
name: "Get User by ID",
description: "Retrieve a specific user by their ID",
service: "users",
params: {
type: "object",
properties: {
id: { type: "string", format: "uuid" }
}
},
responses: {
"200": { $ref: "#/components/schemas/User" },
"404": {
type: "object",
properties: {
error: { type: "string" }
}
}
}
}
})
async getUserById(req: Request, res: Response) {
const { id } = req.params;
const user = await getUserById(id);
if (!user) {
return res.notFound({ error: "User not found" });
}
res.json(user);
}
Query Parameters
@get('/search', {
swagger: {
name: "Search Users",
description: "Search users with filters",
service: "users",
query: {
type: "object",
properties: {
q: { type: "string", description: "Search query" },
limit: { type: "number", minimum: 1, maximum: 100, default: 10 },
offset: { type: "number", minimum: 0, default: 0 },
sort: { type: "string", enum: ["name", "email", "createdAt"] }
},
required: ["q"]
},
responses: {
"200": {
type: "object",
properties: {
users: {
type: "array",
items: { $ref: "#/components/schemas/User" }
},
total: { type: "number" },
limit: { type: "number" },
offset: { type: "number" }
}
}
}
}
})
async searchUsers(req: Request, res: Response) {
const { q, limit = 10, offset = 0, sort } = req.query;
const result = await searchUsers({ q, limit, offset, sort });
res.json(result);
}
Security Requirements
@post('/profile', {
swagger: {
name: "Update Profile",
description: "Update user profile (requires authentication)",
service: "users",
security: [
{ type: "bearer", bearerFormat: "JWT" }
],
requestBody: {
type: "object",
properties: {
name: { type: "string" },
bio: { type: "string" }
}
},
responses: {
"200": { $ref: "#/components/schemas/User" },
"401": {
type: "object",
properties: {
error: { type: "string" }
}
}
}
}
})
async updateProfile(req: Request, res: Response) {
// Implementation with authentication
const user = await updateUserProfile(req.user.id, req.body);
res.json(user);
}
File Upload Documentation
@post('/avatar', {
swagger: {
name: "Upload Avatar",
description: "Upload user avatar image",
service: "users",
bodyType: "form-data",
requestBody: {
type: "object",
properties: {
avatar: {
type: "string",
format: "binary",
description: "Avatar image file"
}
},
required: ["avatar"]
},
responses: {
"200": {
type: "object",
properties: {
url: { type: "string", format: "uri" },
message: { type: "string" }
}
}
}
}
})
async uploadAvatar(req: Request, res: Response) {
const file = req.files.avatar;
const url = await uploadFile(file);
res.json({ url, message: "Avatar uploaded successfully" });
}
Excluding Routes
@get('/internal/health', {
swagger: {
excludeFromSwagger: true
}
})
async healthCheck(req: Request, res: Response) {
res.json({ status: "ok" });
}
UI Options
Swagger UI (Standard)
swagger: {
type: "standard",
path: "/docs"
}
ReDoc
swagger: {
type: "redoc",
path: "/docs"
}
RapiDoc
swagger: {
type: "rapidoc",
path: "/docs"
}
Integration with Validation
Balda.js automatically integrates your validation schemas with Swagger documentation:
import z from 'zod';
const CreateUserSchema = z.object({
email: z.string().email(),
name: z.string().min(1),
password: z.string().min(8)
});
@post('/', {
validate: { body: CreateUserSchema },
swagger: {
name: "Create User",
requestBody: CreateUserSchema,
responses: {
"201": { $ref: "#/components/schemas/User" },
"400": { $ref: "#/components/schemas/ValidationError" }
}
}
})
async createUser(req: Request, res: Response) {
// The validation schema automatically becomes the OpenAPI schema
const user = await createUser(req.body);
res.created(user);
}
Accessing Documentation
Once configured, your API documentation will be available at:
- Swagger UI:
http://localhost:3000/docs - OpenAPI JSON:
http://localhost:3000/docs/json
The JSON specification can be used with other OpenAPI tools or imported into external documentation systems.
Best Practices
- Use Descriptive Names: Give your routes meaningful names and descriptions
- Group Related Routes: Use the
serviceproperty to group related endpoints - Document All Responses: Include success and error responses
- Use Reusable Models: Define models in the global configuration for reuse
- Keep Security Simple: Use standard security schemes when possible
- Test Your Documentation: Use the generated documentation to test your API