Decorators
Decorate your controllers for documentation
Decorators are the core of Adonis Open Swagger's documentation generation. Apply them to your controller methods to automatically generate comprehensive OpenAPI documentation without writing a single line of manual docs.
What are Decorators?
Decorators are TypeScript annotations that add metadata to your controller methods. Adonis Open Swagger reads these decorators to understand your API's structure, parameters, responses, and security requirements—then automatically generates beautiful, interactive documentation.
Why Use Decorators?
- Intentional Documentation: Only routes with decorators are documented—keeping your docs clean and purposeful
- Type-Safe: Works seamlessly with TypeBox, Zod, and VineJS schemas for end-to-end type safety
- Single Source of Truth: Your code defines both behavior and documentation
- Zero Maintenance: Documentation updates automatically when you change decorators
Available Decorators
All decorators support TypeBox schemas, Zod schemas, VineJS schemas, and raw JSON Schema objects for maximum flexibility.
@SwaggerInfo(options)
The primary decorator that defines your endpoint's basic information. This combines tags, summary, and description in a single, convenient decorator.
Purpose: Provide high-level information about what your endpoint does, how it's categorized, and any important details.
Parameters:
options(object):tags(string[]): Categories for grouping related endpoints (e.g.,['Users', 'Authentication'])summary(string): Short, one-line description of the endpointdescription(string, optional): Detailed explanation of the endpoint's behavior, requirements, or notes
Example Usage:
@SwaggerInfo({
summary: "Create User",
description: "Create a new user",
tags: ["Users"],
})@SwaggerParam(options, schema, required?)
Enhanced decorator for defining query parameters and path parameters with full schema validation support.
Purpose: Document URL parameters (path segments) and query string parameters with type validation and descriptions.
Parameters:
options(object):name(string): Parameter name (e.g.,'id','page','limit')location(string): Location of parameter -'query'or'path'description(string, optional): Explanation of what the parameter does
schema(TypeBox | Zod | VineJS | JSON Schema): Validation schema defining the parameter's type and constraintsrequired(boolean, optional): Whether the parameter is required (defaults tofalsefor query params,truefor path params)
Example Usage:
@SwaggerParam(
{
name: "userId",
location: "path",
description: "User ID",
},
vine.string(),
)@SwaggerParam(
{
name: "status",
location: "query",
description: "Status of the User",
},
vine.string(),
)@SwaggerHeader(options, schema, required?)
Decorator for defining HTTP header parameters that your endpoint expects or requires.
Purpose: Document custom headers, authentication headers, or any HTTP headers your endpoint needs.
Parameters:
options(object):name(string): Header name (e.g.,'X-API-Key','Authorization','Content-Type')description(string, optional): Explanation of the header's purpose
schema(TypeBox | Zod | VineJS | JSON Schema): Validation schema for the header valuerequired(boolean, optional): Whether the header is required (defaults tofalse)
Example Usage:
@SwaggerHeader(
{
name: "X-Api-Key",
description: "API Key for authentication",
},
vine.string(),
true
)@SwaggerResponse(status, description, schema?)
Define the structure and details of HTTP responses your endpoint can return.
Purpose: Document all possible responses (success and error cases) with their status codes, descriptions, and data structures.
Parameters:
status(number): HTTP status code (e.g.,200,201,400,404,500)description(string): Explanation of when this response occursschema(TypeBox | Zod | VineJS | JSON Schema, optional): Structure of the response body
Example Usage:
@SwaggerResponse(
201,
"User has been created.",
vine.object({
message: vine.string(),
}),
)@SwaggerRequestBody(description, schema, options?)
Define the structure and validation for request body data sent to your endpoint.
Purpose: Document POST, PUT, and PATCH request bodies with full schema validation, including file uploads.
Parameters:
description(string): Explanation of what data the request body should containschema(TypeBox | Zod | VineJS | JSON Schema): Validation schema for the request body structureoptions(boolean | object, optional): Either a boolean for backward compatibility (required), or an options object:required(boolean, optional): Whether the request body is required (defaults totrue)contentType(string, optional): Content type for the request body (defaults to'application/json')
Example Usage:
@SwaggerRequestBody(
"Create User",
vine.object({
full_name: vine.string(),
email: vine.string().email(),
password: vine.string(),
}),
)With Options Object:
@SwaggerRequestBody(
"Create User",
vine.object({
full_name: vine.string(),
email: vine.string().email(),
}),
{ required: true, contentType: "application/json" }
)Content Types:
| Content Type | Use Case |
|---|---|
application/json | Default for JSON payloads |
multipart/form-data | File uploads and mixed data |
application/x-www-form-urlencoded | Form submissions |
// JSON (default)
@SwaggerRequestBody("User data", userSchema)
// File upload
@SwaggerRequestBody("File upload", fileSchema, { contentType: "multipart/form-data" })
// Form data
@SwaggerRequestBody("Form data", formSchema, { contentType: "application/x-www-form-urlencoded" })
// Optional request body
@SwaggerRequestBody("Optional data", schema, { required: false })For file uploads, use the file helper functions (openapiFile, vineFile,
typeboxFile, zodFile) to define file schemas. See File
Helpers for detailed usage and examples.
@SwaggerDeprecated(deprecated?)
Mark an endpoint as deprecated to warn API consumers that it will be removed in the future.
Purpose: Signal that an endpoint is outdated and should not be used in new code.
Parameters:
deprecated(boolean, optional): Whether the endpoint is deprecated (defaults totrue)
Example Usage:
@SwaggerDeprecated(true)Best Practice: When deprecating an endpoint:
- Add this decorator to mark it as deprecated
- Update the
@SwaggerInfodescription to explain why it's deprecated - Provide information about the replacement endpoint
- Set a timeline for removal
@SwaggerSecurity(security)
Define security requirements for your endpoint, such as API keys, OAuth2, JWT, or Cookie authentication.
Purpose: Document authentication and authorization requirements for accessing the endpoint.
Parameters:
security(object[]): Security scheme requirements as an array of scheme objects.- Each object key is the security scheme name (defined in your OpenAPI config)
- Each value is an array of required scopes (empty array for schemes without scopes)
Example Usage:
// Cookie authentication (session-based)
@SwaggerSecurity([{ cookieAuth: [] }])
// Bearer token authentication
@SwaggerSecurity([{ bearerAuth: [] }])
// OAuth2 with scopes
@SwaggerSecurity([{ oauth2Auth: ["read:users", "write:users"] }])
// Public endpoint (no authentication)
@SwaggerSecurity([])Supported Security Schemes:
| Type | Description | Example Use Case |
|---|---|---|
apiKey (cookie) | API key sent in a cookie | Session-based auth, Better-Auth |
apiKey (header) | API key sent in a header | API key authentication |
apiKey (query) | API key sent as query param | Legacy API authentication |
http (bearer) | Bearer token in Authorization header | JWT authentication |
http (basic) | Basic HTTP authentication | Simple username/password |
oauth2 | OAuth 2.0 flows | Third-party integrations |
openIdConnect | OpenID Connect Discovery | SSO integrations |
Complete Example:
import {
SwaggerInfo,
SwaggerSecurity,
SwaggerResponse,
} from "adonis-open-swagger";
export default class UsersController {
// Use cookie authentication
@SwaggerInfo({
tags: ["Users"],
summary: "Get current user profile",
})
@SwaggerSecurity([{ cookieAuth: [] }])
@SwaggerResponse(200, "User profile retrieved")
async profile({ auth, response }: HttpContext) {
return response.ok(auth.user);
}
// Public endpoint (no authentication required)
@SwaggerInfo({
tags: ["Users"],
summary: "Get public user info",
})
@SwaggerSecurity([]) // Empty array = no security required
@SwaggerResponse(200, "Public user info")
async publicInfo({ response }: HttpContext) {
return response.ok({ message: "Public info" });
}
// OAuth2 with specific scopes
@SwaggerInfo({
tags: ["Admin"],
summary: "Delete user",
})
@SwaggerSecurity([{ oauth2Auth: ["write:users"] }])
@SwaggerResponse(204, "User deleted")
async destroy({ params, response }: HttpContext) {
return response.noContent();
}
}Security schemes must be defined in your config/swagger.ts file under
securitySchemes. See Basic Configuration for details on
configuring security schemes including cookie authentication.
Schema Support
All decorators that accept schemas support multiple validation libraries:
| Schema Type | Description | Documentation |
|---|---|---|
| TypeBox | TypeScript-first schema builder with excellent performance | TypeBox Docs |
| Zod | TypeScript-first schema validation with great DX | Zod Docs |
| VineJS | AdonisJS's official validation library | VineJS Docs |
| JSON Schema | Raw JSON Schema objects for maximum control | JSON Schema Spec |
Choose the schema library that best fits your project. Adonis Open Swagger automatically converts all schema types to OpenAPI-compatible JSON Schema.
Combining Decorators
You can apply multiple decorators to a single controller method to fully document your endpoint. Decorators are processed in the order they appear.
Example Usage:
@SwaggerInfo({
summary: "Create User",
description: "Create a new user",
tags: ["Users"],
})
@SwaggerRequestBody(
"Create User",
vine.object({
full_name: vine.string(),
email: vine.string().email(),
password: vine.string(),
}),
)
@SwaggerResponse(
201,
"User has been created.",
vine.object({
message: vine.string(),
}),
)
public async createUser() {
// Your implementation
}Single Action Controllers
Adonis Open Swagger fully supports AdonisJS Single Action Controllers. These are controllers that handle a single action through a handle method, providing a clean way to organize functionality into clearly named classes.
What are Single Action Controllers?
Single action controllers are classes with a single handle method that processes the request. Instead of having multiple methods in one controller, you create dedicated controllers for specific actions.
Using Decorators with Single Action Controllers
Apply decorators directly to the handle method:
import { SwaggerInfo, SwaggerResponse } from "adonis-open-swagger";
export default class RegisterNewsletterSubscriptionController {
@SwaggerInfo({
tags: ["Newsletter"],
summary: "Register newsletter subscription",
description: "Subscribe a user to the newsletter",
})
@SwaggerResponse(200, "User is registered on newsletter")
handle() {
return "User is registered on newsletter";
}
}Registering Single Action Controller Routes
In your routes file, reference the controller without specifying a method name:
import router from "@adonisjs/core/services/router";
const RegisterNewsletterSubscriptionController = () =>
import("#controllers/register_newsletter_subscription_controller");
router.post("newsletter/subscriptions", [
RegisterNewsletterSubscriptionController,
]);Adonis Open Swagger automatically detects that this is a single action controller and reads the decorators from the handle method.
Best Practices
1. Always Use @SwaggerInfo
Every documented endpoint should have @SwaggerInfo with at least tags and a summary. This ensures your documentation is organized and searchable.
2. Document All Responses
Include @SwaggerResponse decorators for all possible responses, including error cases. This helps API consumers handle errors properly.
3. Be Specific with Descriptions
Write clear, concise descriptions that explain:
- What the endpoint does
- What parameters mean
- When different responses occur
- Any important constraints or requirements
4. Use Consistent Tags
Group related endpoints with consistent tag names (e.g., all user-related endpoints use the 'Users' tag).
5. Validate Everything
Use schema validation for all inputs (params, headers, request bodies) to ensure type safety and automatic documentation.
Last updated on