We use cookies to enhance your experience on the site
CodeWorlds

CLI Plugin - The Automatic Scribe

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 as
    required: false
  • @IsEnum()
    generates the list of allowed values
  • @Min()
    /
    @Max()
    sets
    minimum
    /
    maximum
  • @IsString()
    confirms the
    string
    type

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:

Go to CodeWorlds