Streamlined API documentation for NestJS applications
https://github.com/Kimsoo0119/nest-swagger-builder.git
A utility library that makes Swagger documentation in NestJS functional, type-safe, and intuitive.
npm install nest-swagger-builder
npm install @nestjs/common @nestjs/swagger class-transformer class-validator
// src/controllers/swagger/user.swagger.ts
import { HttpStatus } from "@nestjs/common";
import { ApiDecoratorBuilder, ApiOperator } from "nest-swagger-builder";
import { UserController } from "../user.controller";
import { UserDto } from "../../dto/user.dto";
export const ApiUser: ApiOperator<keyof UserController> = {
GetUsers: (apiOperationOptions) =>
new ApiDecoratorBuilder()
.withOperation(apiOperationOptions)
.withBearerAuth()
.withBodyResponse(HttpStatus.OK, "ApiUser_GetUsers", [UserDto])
.build(),
};
@ApiTags("users")
@Controller("users")
export class UserController {
@ApiUser.GetUsers({ summary: "Get all users" })
@Get()
getUsers() {
return this.users;
}
}
In professional environments, each team/service may return different JSON structures from their interceptors.
Examples:
// Service A
{ "statusCode": 200, "data": { ... } }
// Service B
{ "status": 200, "result": { ... } }
By default, nest-swagger-builder returns pure Swagger structure ({}).
However, you can easily reflect customized response structures in Swagger in two ways:
new ApiDecoratorBuilder()
.withOperation(apiOperationOptions)
.withBodyResponse(HttpStatus.OK, "UserDetail", UserDto, {
statusKey: "status",
wrapperKey: "data",
})
.build();
// src/config/custom-swagger-builder.ts
export const CustomSwaggerBuilder = new ApiDecoratorBuilder({
statusKey: "status",
wrapperKey: "data",
});
Usage example:
CustomSwaggerBuilder.withOperation(apiOperationOptions)
.withBodyResponse(HttpStatus.OK, "UserDetail", UserDto)
.build();
new ApiDecoratorBuilder()
.withOperation(apiOperationOptions)
.withBearerAuth()
.withStatusResponse(HttpStatus.CREATED, "UserCreated", {
statusKey: "statusCode",
})
.build();
new ApiDecoratorBuilder()
.withOperation(apiOperationOptions)
.withBearerAuth()
.withBodyResponse(HttpStatus.OK, "UserProfile", UserDto, {
statusKey: "status",
wrapperKey: "data",
})
.build();
new ApiDecoratorBuilder()
.withOperation({ summary: "Get all users" })
.withBearerAuth()
.withBodyResponse(HttpStatus.OK, "UsersList", [UserDto], {
statusKey: "status",
wrapperKey: "data",
})
.build();
new ApiDecoratorBuilder()
.withOperation({ summary: "Delete user" })
.withBearerAuth()
.withStatusResponse(HttpStatus.NO_CONTENT, "UserDeleted")
.withUnauthorizedResponse([
{
name: "InvalidToken",
error: "Invalid Token",
description: "The provided authentication token is invalid",
},
])
.withNotFoundResponse([
{
name: "UserNotFound",
error: "User Not Found",
description: "The user with the given ID was not found",
},
])
.build();
// Single File Upload
new ApiDecoratorBuilder()
.withOperation(apiOperationOptions)
.withFormDataRequest("ProfileImage", "image")
.withBodyResponse(HttpStatus.CREATED, "ImageUploaded", ImageDto)
.build();
// Multiple Files Upload
new ApiDecoratorBuilder()
.withOperation(apiOperationOptions)
.withFormDataRequest("GalleryImages", "images", { isArray: true })
.withBodyResponse(HttpStatus.CREATED, "ImagesUploaded", [ImageDto])
.build();
Usage example in controller:
import { FileInterceptor, FilesInterceptor } from '@nestjs/platform-express';
@ApiUser.UploadImageFile({ summary: "Upload single image" })
@UseInterceptors(FileInterceptor('image'))
@Post('upload')
uploadFile(@UploadedFile() file: Express.Multer.File) {
return { filename: file.originalname, size: file.size };
}
A class that creates Swagger decorators through method chaining.
new ApiDecoratorBuilder(config?: ApiDecoratorBuilderConfig)
| Parameter | Description | Type |
|---|---|---|
config | Default response format configuration (optional) | ApiDecoratorBuilderConfig |
interface ApiDecoratorBuilderConfig {
wrapperKey?: string | undefined; // Property name that wraps response data (e.g., "data")
statusKey?: string | undefined; // Status code property name (e.g., "statusCode")
}
| Method | Description | Parameters |
|---|---|---|
withOperation | Add API operation information | options: ApiOperationOptions |
withBearerAuth | Add Bearer authentication | name?: string |
withStatusResponse | Add response with status code only | status: number, key: string, options?: ResponseOptions |
withBodyResponse | Add response with data | status: number, key: string, type: Type \| Type[], options?: ResponseOptions |
withFormDataRequest | Add file upload support | key: string, fileFieldName: string, options?: Record<string, any> |
withErrorResponses | Add 400 error responses | errors: ApiErrorResponse[] |
withUnauthorizedResponse | Add 401 error responses | errors: ApiErrorResponse[] |
withForbiddenResponse | Add 403 error responses | errors: ApiErrorResponse[] |
withNotFoundResponse | Add 404 error responses | errors: ApiErrorResponse[] |
withDecorator | Add custom decorator | decorator: MethodDecorator \| PropertyDecorator |
build | Combine all decorators and return | - |
interface ResponseOptions {
statusKey?: string; // Status code field name in the response
wrapperKey?: string; // Data field name in the response
}
type ApiOperator<M extends string> = {
[key in Capitalize<M>]: (
apiOperationOptions: Required<Pick<ApiOperationOptions, "summary">> & ApiOperationOptions
) => PropertyDecorator;
};
The repository includes an example NestJS application demonstrating how to use the library:
# Clone the repository
git clone https://github.com/Kimsoo0119/nest-swagger-builder.git
# Install dependencies in the main project
cd nest-swagger-builder
npm install
npm run build
# Run the example application
cd examples
npm install
npm run start:dev
# Access Swagger UI
Open http://localhost:3000/api in your browser
This library is licensed under the MIT License - see the LICENSE file for details.