NestJS course Β· Module 11: Swagger and OpenAPI
CLI Plugin - The Automatic Scribe
In this lesson8
Imagine that in the imperial chancellery you have a scribe who automatically documents every decree based on its content - you don't need to tell him what to write, he understands the document structure on his own. This is exactly how the @nestjs/swagger CLI Plugin works.
The Problem with Manual Documentation
Without the CLI Plugin, you have to manually add @ApiProperty() to every field in every DTO:
1// Without CLI Plugin - lots of repetitive code
2export class CreateLegionaryDto {
3 @ApiProperty({ description: 'Name of the legionary' })
4 name: string;
5
6 @ApiProperty({ description: 'Rank', required: false })
7 rank?: string;
8
9 @ApiProperty({ description: 'Experience' })
10 experience: number;
11
12 @ApiProperty({ description: 'Is active' })
13 isActive: boolean;
14}CLI Plugin - Automatic Generation
The CLI Plugin analyzes TypeScript types and automatically generates Swagger metadata. A simple class is enough:
1// With CLI Plugin - clean code, automatic documentation
2export class CreateLegionaryDto {
3 /** Name of the legionary */
4 name: string;
5
6 /** Rank in the legion */
7 rank?: string;
8
9 /** Years of experience */
10 experience: number;
11
12 /** Whether the legionary is active */
13 isActive: boolean;
14}The plugin automatically:
- Recognizes field types (
string,number,boolean) - Marks fields with
?as optional - Converts JSDoc comments into Swagger descriptions
- Generates appropriate
@ApiProperty()at compile time
Configuration in nest-cli.json
To enable the CLI Plugin, add the appropriate configuration in the nest-cli.json file:
1{
2 "collection": "@nestjs/schematics",
3 "sourceRoot": "src",
4 "compilerOptions": {
5 "deleteOutDir": true,
6 "plugins": [
7 {
8 "name": "@nestjs/swagger",
9 "options": {
10 "classValidatorShim": true,
11 "introspectComments": true,
12 "dtoFileNameSuffix": [".dto.ts", ".entity.ts"]
13 }
14 }
15 ]
16 }
17}CLI Plugin Options
| Option | Description | Default |
|---|---|---|
classValidatorShim | Automatically adds validation rules from class-validator | true |
introspectComments | Uses JSDoc comments as descriptions | false |
dtoFileNameSuffix | Which files to analyze | ['.dto.ts', '.entity.ts'] |
controllerFileNameSuffix | Controller file suffix | '.controller.ts' |
controllerKeyOfComment | Comment key for controllers | 'description' |
introspectComments - Comments as Documentation
When introspectComments is enabled, JSDoc comments become Swagger descriptions:
1export class LegionDto {
2 /**
3 * Unique legion name in the Empire
4 * @example 'Legio X Gemina'
5 */
6 name: string;
7
8 /**
9 * Stationing province
10 * @example 'Pannonia'
11 */
12 province: string;
13
14 /**
15 * Number of soldiers in the legion
16 * @example 5000
17 */
18 soldiers: number;
19}The @example tag automatically generates an example value in Swagger UI.
classValidatorShim - Integration with Validation
When classValidatorShim is enabled, class-validator decorators affect Swagger documentation:
1import { IsString, IsNumber, IsOptional, Min, Max, IsEnum } from 'class-validator';
2
3export class CreateLegionaryDto {
4 /** Name of the legionary */
5 @IsString()
6 name: string;
7
8 /** Rank in the legion */
9 @IsEnum(LegionaryRank)
10 @IsOptional()
11 rank?: LegionaryRank;
12
13 /** Years of experience */
14 @IsNumber()
15 @Min(0)
16 @Max(40)
17 experience: number;
18}The plugin automatically:
@IsOptional()marks the field asrequired: false@IsEnum()generates the list of allowed values@Min()/@Max()setsminimum/maximum@IsString()confirms thestringtype
When to Still Use @ApiProperty?
The CLI Plugin does not replace all use cases of @ApiProperty(). You still need it for:
- Nested types (
type: () => AddressDto) - Arrays of objects (
type: [LegionaryDto]) - Complex examples
- Overriding automatically generated descriptions
Practical Exercise
Configure the CLI Plugin and create a DTO with JSDoc comments:
Code for this lesson: src/nest-cli.config.ts
1// CLI Plugin configuration for @nestjs/swagger
2// This file presents the nest-cli.json configuration
3
4const nestCliConfig = {
5 collection: "@nestjs/schematics",
6 sourceRoot: "src",
7 compilerOptions: {
8 deleteOutDir: true,
9 plugins: [
10 {
11 name: "@nestjs/swagger",
12 options: {
13 // TODO: Enable classValidatorShim (true)
14 // TODO: Enable introspectComments (true)
15 // TODO: Set dtoFileNameSuffix to ['.dto.ts', '.entity.ts']
16 }
17 }
18 ]
19 }
20};
21
22console.log("=== nest-cli.json config ===");
23console.log(JSON.stringify(nestCliConfig, null, 2));
24
25// Example DTO with JSDoc comments (instead of @ApiProperty)
26class LegionaryDto {
27 /** Unique name of the legionary
28 * @example 'Marcus Aurelius'
29 */
30 name: string;
31
32 /** Rank in the legion hierarchy
33 * @example 'Centurio'
34 */
35 rank?: string;
36
37 /** Years of service in the legion
38 * @example 8
39 */
40 experience: number;
41
42 /** Whether the legionary is active in service
43 * @example true
44 */
45 isActive: boolean;
46}
47
48console.log("");
49console.log("With the CLI Plugin, JSDoc comments become Swagger descriptions");
50console.log("The @example tag generates example values");
51console.log("Fields with ? are automatically marked as optional");
52console.log("classValidatorShim integrates validation with the documentation");
53Spotted a mistake in this lesson?
Check yourself
Answer the questions from this lesson. Pick an answer to see right away whether it is correct.
1. What does the @nestjs/swagger CLI Plugin do?
2. What does the introspectComments option do in the @nestjs/swagger CLI Plugin?
These are 2 of 3 questions for this lesson. Solve the rest in the game.
Hands-on tasks in the game
- Vertical ordering
Order the steps for enabling the CLI Plugin from the configuration file to the result:
- Code editor
Add JSDoc comments with a description and @example to each DTO field
- Horizontal ordering
Arrange the elements of a JSDoc comment with the @example tag:
- Click in order
Arrange the plugin configuration elements in nest-cli.json from the outer key to the options:
- Code editor
Create SenatorResponseDto and CreateSenatorDto, then use them as the type in response decorators