Swagger / OpenAPI
Documentação completa de API com interface moderna e interativa
Swagger / OpenAPI 3.0
AzuraJS inclui suporte completo para documentação de API usando Swagger/OpenAPI 3.0, com uma interface moderna dark mode e funcionalidade "Try It Out" integrada.
Nota: O sistema Swagger do AzuraJS gera automaticamente documentação OpenAPI 3.0 a partir dos seus controllers e decorators, sem configuração manual.
Instalação
O Swagger já vem incluído no AzuraJS. Basta importar do submódulo azurajs/swagger:
import { setupSwaggerWithControllers } from "azurajs/swagger";Setup Rápido
A forma mais simples de adicionar Swagger à sua aplicação é com uma linha:
import { AzuraClient } from "azurajs";
import { setupSwaggerWithControllers } from "azurajs/swagger";
import { UserController } from "./controllers/UserController";
const app = new AzuraClient();
// Uma linha para configurar tudo!
setupSwaggerWithControllers(app, {
title: "My API",
description: "API documentation",
version: "1.0.0"
}, [UserController]);
app.listen();Acesse a documentação em:
- UI Interativa:
http://localhost:3000/docs- OpenAPI JSON:
http://localhost:3000/api-spec.json
Decorators de Documentação
@Swagger() - Nova API Simplificada ⭐
O decorator @Swagger unifica toda a documentação em um único lugar, tornando muito mais fácil e intuitivo documentar suas APIs:
import { Controller, Get, Post } from "azurajs/decorators";
import { Swagger } from "azurajs/swagger";
@Controller("/users")
class UserController {
@Get("/:id")
@Swagger({
summary: "Busca usuário por ID",
description: "Retorna informações detalhadas de um usuário específico",
tags: ["Users"],
parameters: [
{
name: "id",
in: "path",
description: "ID do usuário",
required: true,
schema: { type: "string" },
example: "123"
}
],
responses: {
200: {
description: "Usuário encontrado",
example: {
id: "123",
name: "John Doe",
email: "[email protected]"
}
},
404: {
description: "Usuário não encontrado",
example: { error: "User not found" }
}
}
})
async getUser(@Req() req, @Res() res) {
res.json({ id: req.params.id, name: "John Doe" });
}
@Post("/")
@Swagger({
summary: "Cria novo usuário",
tags: ["Users"],
requestBody: {
description: "Dados do usuário",
required: true,
content: {
"application/json": {
schema: {
type: "object",
properties: {
name: { type: "string" },
email: { type: "string", format: "email" }
},
required: ["name", "email"]
},
example: {
name: "Jane Doe",
email: "[email protected]"
}
}
}
},
responses: {
201: {
description: "Usuário criado com sucesso",
example: {
id: 456,
name: "Jane Doe",
email: "[email protected]"
}
},
400: {
description: "Dados inválidos",
example: { error: "Invalid data" }
}
}
})
async createUser(@Req() req, @Res() res) {
res.status(201).json(req.body);
}
}Vantagens do @Swagger:
- ✅ Tudo em um lugar - Não precisa usar múltiplos decorators
- ✅ Mais legível - Configuração agrupada e organizada
- ✅ Menos código - Uma única declaração ao invés de 4-5 decorators
- ✅ TypeScript - Autocompletar e validação de tipos
- ✅ Exemplos integrados - Defina exemplos direto nas responses
Decorators Individuais (API Tradicional)
Se preferir maior granularidade, você ainda pode usar os decorators individuais:
@ApiDoc()
Documenta informações básicas do endpoint:
import { Controller, Get } from "azurajs/decorators";
import { ApiDoc } from "azurajs/swagger";
@Controller("/users")
class UserController {
@Get("/:id")
@ApiDoc({
summary: "Get user by ID",
description: "Retrieve detailed information about a specific user"
})
async getUser(@Req() req, @Res() res) {
res.json({ id: req.params.id, name: "John Doe" });
}
}@ApiResponse()
Define as respostas possíveis do endpoint:
@Get("/:id")
@ApiResponse(200, "User found", {
example: {
id: 1,
name: "John Doe",
email: "[email protected]"
}
})
@ApiResponse(404, "User not found", {
example: { error: "User not found" }
})
async getUser(@Req() req, @Res() res) {
// ...
}@ApiParameter()
Documenta parâmetros da requisição:
@Get("/:id")
@ApiParameter("id", "path", {
description: "User ID",
required: true,
schema: { type: "integer" },
example: 123
})
async getUser(@Req() req, @Res() res) {
// ...
}Tipos de parâmetros:
path- Parâmetros na URL (/users/:id)query- Query strings (/users?page=1)header- Headers HTTPcookie- Cookies
@ApiBody()
Documenta o corpo da requisição:
@Post("/")
@ApiBody({
description: "User data",
required: true,
example: {
name: "Jane Doe",
email: "[email protected]",
age: 25
}
})
async createUser(@Req() req, @Res() res) {
res.status(201).json(req.body);
}@ApiTags()
Organiza endpoints por tags:
@Controller("/users")
@ApiTags("Users")
class UserController {
// Todos os endpoints terão a tag "Users"
}
// Ou em endpoints específicos:
@Get("/")
@ApiTags("Users", "Public")
async listUsers() {
// ...
}@ApiSecurity()
Especifica requisitos de autenticação:
@Get("/profile")
@ApiSecurity("bearerAuth")
async getProfile(@Req() req, @Res() res) {
// Endpoint protegido
}Configurando security schemes:
setupSwaggerWithControllers(app, {
title: "My API",
version: "1.0.0",
securitySchemes: {
bearerAuth: {
type: "http",
scheme: "bearer",
bearerFormat: "JWT"
},
apiKey: {
type: "apiKey",
in: "header",
name: "X-API-Key"
}
}
}, [UserController]);@ApiDeprecated()
Marca endpoints como deprecados:
@Get("/old-endpoint")
@ApiDeprecated()
@ApiDoc({ summary: "Old endpoint (use /new-endpoint instead)" })
async oldEndpoint(@Req() req, @Res() res) {
// ...
}JavaScript Simples (Sem Decorators)
Se você prefere JavaScript puro ou não quer usar decorators, use o método addDoc():
import { AzuraClient } from "azurajs";
import { setupSwagger, SwaggerGenerator } from "azurajs/swagger";
const app = new AzuraClient();
// Criar gerador Swagger
const swagger = new SwaggerGenerator({
title: "API Simples",
description: "API documentada de forma simples",
version: "1.0.0",
tags: [
{ name: "Users", description: "Gerenciamento de usuários" },
{ name: "Binary", description: "Operações de codificação" }
]
});
// Rota GET com query parameter
app.get("/binary/encode", (req, res) => {
const text = req.query.q;
if (!text) {
return res.status(400).json({ error: "Query 'q' is required" });
}
const binary = text.split("").map(c =>
c.charCodeAt(0).toString(2).padStart(8, "0")
).join("");
res.json({
input: text,
output: binary
});
});
// Documentar com addDoc() - FÁCIL! ⭐
swagger.addDoc({
method: "GET",
path: "/binary/encode",
summary: "Codifica texto em binário",
description: "Converte qualquer texto para representação binária",
tags: ["Binary"],
parameters: [
{
name: "q",
in: "query",
description: "Texto a ser codificado",
required: true,
schema: { type: "string" },
example: "Hello"
}
],
responses: {
200: {
description: "Texto codificado com sucesso",
example: {
input: "Hello",
output: "0100100001100101011011000110110001101111"
}
},
400: {
description: "Parâmetro ausente",
example: { error: "Query 'q' is required" }
}
}
});
// Rota POST com body
app.post("/users", (req, res) => {
const newUser = { id: Date.now(), ...req.body };
res.status(201).json(newUser);
});
swagger.addDoc({
method: "POST",
path: "/users",
summary: "Cria novo usuário",
tags: ["Users"],
requestBody: {
description: "Dados do usuário",
required: true,
example: {
name: "João Silva",
email: "[email protected]"
}
},
responses: {
201: {
description: "Usuário criado",
example: {
id: 1234567890,
name: "João Silva",
email: "[email protected]"
}
}
}
});
// Rota GET com path parameter
app.get("/users/:id", (req, res) => {
res.json({
id: req.params.id,
name: "John Doe",
email: "[email protected]"
});
});
swagger.addDoc({
method: "GET",
path: "/users/:id",
summary: "Busca usuário por ID",
tags: ["Users"],
parameters: [
{
name: "id",
in: "path",
description: "ID do usuário",
required: true,
schema: { type: "string" },
example: "123"
}
],
responses: {
200: {
description: "Usuário encontrado",
example: {
id: "123",
name: "John Doe",
email: "[email protected]"
}
},
404: {
description: "Usuário não encontrado"
}
}
});
// Setup Swagger UI
setupSwagger(app, swagger);
app.listen(3000).then(() => {
console.log("🚀 Server: http://localhost:3000");
console.log("📚 Docs: http://localhost:3000/docs");
});Vantagens do addDoc():
- ✅ JavaScript puro - Funciona sem TypeScript ou decorators
- ✅ Simples - Menos verboso que SwaggerHelpers.createResponse
- ✅ Automático - Gera responses OpenAPI a partir de exemplos
- ✅ Flexível - Misture com rotas tradicionais do AzuraJS
Exemplo Completo (TypeScript com Decorators)
import { Controller, Get, Post, Put, Delete, Req, Res } from "azurajs/decorators";
import { Swagger } from "azurajs/swagger";
@Controller("/users")
class UserController {
@Get("/")
@Swagger({
summary: "Lista todos os usuários",
tags: ["Users"],
parameters: [
{
name: "page",
in: "query",
schema: { type: "number" },
example: 1
},
{
name: "limit",
in: "query",
schema: { type: "number" },
example: 10
}
],
responses: {
200: {
description: "Lista de usuários",
example: [
{ id: 1, name: "John Doe" },
{ id: 2, name: "Jane Smith" }
]
}
}
})
async listUsers(@Req() req, @Res() res) {
res.json([
{ id: 1, name: "John Doe" },
{ id: 2, name: "Jane Smith" }
]);
}
@Get("/:id")
@Swagger({
summary: "Busca usuário por ID",
tags: ["Users"],
parameters: [
{
name: "id",
in: "path",
required: true,
schema: { type: "string" },
example: "123"
}
],
responses: {
200: {
description: "Usuário encontrado",
example: { id: "123", name: "John Doe", email: "[email protected]" }
},
404: {
description: "Usuário não encontrado"
}
}
})
async getUser(@Req() req, @Res() res) {
res.json({ id: req.params.id, name: "John Doe" });
}
@Post("/")
@Swagger({
summary: "Cria novo usuário",
tags: ["Users"],
requestBody: {
description: "Dados do usuário",
required: true,
content: {
"application/json": {
schema: {
type: "object",
properties: {
name: { type: "string" },
email: { type: "string", format: "email" }
},
required: ["name", "email"]
},
example: {
name: "Jane Doe",
email: "[email protected]"
}
}
}
},
responses: {
201: {
description: "Usuário criado",
example: { id: 123, name: "Jane Doe", email: "[email protected]" }
}
}
})
async createUser(@Req() req, @Res() res) {
res.status(201).json(req.body);
}
@Delete("/:id")
@Swagger({
summary: "Deleta usuário",
tags: ["Users"],
parameters: [
{
name: "id",
in: "path",
required: true,
schema: { type: "string" },
example: "123"
}
],
responses: {
204: {
description: "Usuário deletado"
},
404: {
description: "Usuário não encontrado"
}
}
})
async deleteUser(@Req() req, @Res() res) {
res.status(204).send();
}
}Decorators Individuais - Exemplo Completo
Se preferir usar os decorators tradicionais separadamente:
import {
ApiDoc,
ApiResponse,
ApiParameter,
ApiBody,
ApiTags
} from "azurajs/swagger";
@Controller("/users")
@ApiTags("Users")
class UserController {
@Get("/")
@ApiDoc({
summary: "List all users",
description: "Retrieve a paginated list of users"
})
@ApiParameter("page", "query", {
description: "Page number",
schema: { type: "integer", default: 1 }
})
@ApiParameter("limit", "query", {
description: "Items per page",
schema: { type: "integer", default: 10 }
})
@ApiResponse(200, "Success", {
example: {
users: [
{ id: 1, name: "John Doe" },
{ id: 2, name: "Jane Doe" }
],
total: 2,
page: 1
}
})
async listUsers(@Req() req, @Res() res) {
const page = req.query.page || 1;
const limit = req.query.limit || 10;
res.json({ users: [], total: 0, page });
}
@Get("/:id")
@ApiDoc({
summary: "Get user by ID",
description: "Retrieve detailed user information"
})
@ApiParameter("id", "path", {
description: "User ID",
required: true,
schema: { type: "integer" }
})
@ApiResponse(200, "User found", {
example: { id: 1, name: "John Doe", email: "[email protected]" }
})
@ApiResponse(404, "User not found")
async getUser(@Req() req, @Res() res) {
const userId = req.params.id;
res.json({ id: userId, name: "John Doe" });
}
@Post("/")
@ApiDoc({
summary: "Create new user",
description: "Create a new user in the system"
})
@ApiBody({
description: "User data",
required: true,
example: {
name: "Jane Doe",
email: "[email protected]",
age: 25
}
})
@ApiResponse(201, "User created", {
example: { id: 3, name: "Jane Doe", email: "[email protected]" }
})
@ApiResponse(400, "Invalid data")
async createUser(@Req() req, @Res() res) {
res.status(201).json({ id: 3, ...req.body });
}
@Put("/:id")
@ApiDoc({ summary: "Update user" })
@ApiParameter("id", "path", {
description: "User ID",
required: true,
schema: { type: "integer" }
})
@ApiBody({
description: "Updated user data",
example: { name: "John Updated" }
})
@ApiResponse(200, "User updated")
@ApiResponse(404, "User not found")
async updateUser(@Req() req, @Res() res) {
res.json({ id: req.params.id, ...req.body });
}
@Delete("/:id")
@ApiDoc({ summary: "Delete user" })
@ApiParameter("id", "path", {
description: "User ID",
required: true
})
@ApiResponse(204, "User deleted")
@ApiResponse(404, "User not found")
async deleteUser(@Req() req, @Res() res) {
res.status(204).send();
}
}Interface Swagger UI
A interface Swagger do AzuraJS oferece:
🎨 Design Moderno
- Dark mode premium (inspirado em Stripe/Vercel)
- Sidebar com navegação por tags
- Cards expansíveis para cada endpoint
- Syntax highlighting para código
🔍 Busca em Tempo Real
- Pesquise endpoints por método ou path
- Filtragem instantânea na sidebar
🚀 Try It Out
- Teste endpoints diretamente na UI
- Preencha parâmetros, query strings e body
- Veja a resposta em tempo real
- Exibe tempo de resposta
📋 Funcionalidades
- Copiar código com um clique
- Visualização de status codes
- Exemplos de request/response
- Documentação de tipos
- Badges para required/deprecated
Configuração Avançada
Múltiplos Servidores
setupSwaggerWithControllers(app, {
title: "My API",
version: "1.0.0",
servers: [
{
url: "http://localhost:3000",
description: "Development"
},
{
url: "https://api.example.com",
description: "Production"
},
{
url: "https://staging.example.com",
description: "Staging"
}
]
}, [UserController]);Security Schemes
setupSwaggerWithControllers(app, {
title: "My API",
version: "1.0.0",
securitySchemes: {
bearerAuth: {
type: "http",
scheme: "bearer",
bearerFormat: "JWT",
description: "JWT token from /auth/login"
},
apiKey: {
type: "apiKey",
in: "header",
name: "X-API-Key",
description: "API key from dashboard"
},
oauth2: {
type: "oauth2",
flows: {
authorizationCode: {
authorizationUrl: "https://example.com/oauth/authorize",
tokenUrl: "https://example.com/oauth/token",
scopes: {
"read:users": "Read user data",
"write:users": "Modify user data"
}
}
}
}
}
}, [UserController]);Contact & License
setupSwaggerWithControllers(app, {
title: "My API",
description: "Complete API documentation",
version: "1.0.0",
contact: {
name: "API Support",
email: "[email protected]",
url: "https://example.com/support"
},
license: {
name: "MIT",
url: "https://opensource.org/licenses/MIT"
}
}, [UserController]);Setup Manual (Avançado)
Se você precisa de mais controle, pode configurar manualmente:
import { AzuraClient } from "azurajs";
import { SwaggerIntegration, SwaggerGenerator } from "azurajs/swagger";
import { getControllerMetadata } from "azurajs/decorators";
const app = new AzuraClient();
// Criar gerador
const generator = new SwaggerGenerator({
title: "My API",
version: "1.0.0"
});
// Adicionar controllers
const metadata = getControllerMetadata(UserController);
generator.addController(metadata.prefix, metadata.routes);
// Configurar rotas Swagger
const swagger = new SwaggerIntegration(generator, {
title: "My API",
version: "1.0.0"
});
app.use("/docs", swagger.getUIRoute());
app.use("/api-spec.json", swagger.getSpecRoute());
// Registrar controllers normalmente
app.registerController(UserController);
app.listen();TypeScript Types
O AzuraJS fornece types completos para OpenAPI 3.0:
import type {
OpenAPIDocument,
SwaggerConfig,
ApiDocMetadata,
ApiResponseMetadata,
ParameterObject,
SchemaObject
} from "azurajs/swagger";
const config: SwaggerConfig = {
title: "My API",
version: "1.0.0",
servers: [{ url: "http://localhost:3000" }]
};Boas Práticas
1. Use @ApiTags para Organização
Agrupe endpoints relacionados com tags:
@Controller("/users")
@ApiTags("Users", "Management")
class UserController { }
@Controller("/products")
@ApiTags("Products", "E-commerce")
class ProductController { }2. Forneça Exemplos Detalhados
Exemplos ajudam desenvolvedores a entender o formato esperado:
@ApiBody({
description: "User registration data",
example: {
name: "John Doe",
email: "[email protected]",
password: "secure123",
preferences: {
newsletter: true,
notifications: ["email", "push"]
}
}
})3. Documente Todos os Status Codes
Inclua todas as respostas possíveis:
@ApiResponse(200, "Success")
@ApiResponse(400, "Bad request")
@ApiResponse(401, "Unauthorized")
@ApiResponse(403, "Forbidden")
@ApiResponse(404, "Not found")
@ApiResponse(500, "Server error")4. Use Descriptions Claras
Seja descritivo nas summaries e descriptions:
@ApiDoc({
summary: "Update user profile",
description: "Updates the authenticated user's profile information. Only provided fields will be updated. Requires valid JWT token."
})5. Marque Endpoints Deprecados
Informe quando endpoints estão deprecados:
@Get("/old-api")
@ApiDeprecated()
@ApiDoc({
summary: "Legacy API endpoint",
description: "⚠️ Deprecated: Use /api/v2/endpoint instead. This endpoint will be removed in v3.0.0"
})Troubleshooting
Documentação não aparece
Certifique-se de que:
- Você importou os decorators de
azurajs/swagger - Os decorators estão aplicados nos métodos
- Os controllers foram passados para
setupSwaggerWithControllers()
Try It Out não funciona
Verifique:
- CORS está configurado corretamente
- O servidor está rodando na URL esperada
- Os parâmetros estão sendo preenchidos corretamente
Tipos TypeScript não funcionam
Certifique-se de importar os types:
import type { SwaggerConfig } from "azurajs/swagger";Próximos Passos
- Exemplos - Veja exemplos completos de uso
- Decorators - Aprenda mais sobre decorators
- Controllers - Entenda como controllers funcionam
