# Swagger

## Introduction&#x20;

* To set the plugin, so that `nestjs/swagger` will add `@ApiProperty`to the dto class automatically

{% code title="nest-cli.json" %}

```json
{
  "$schema": "https://json.schemastore.org/nest-cli",
  "collection": "@nestjs/schematics",
  "sourceRoot": "src",
  "compilerOptions": {
    "deleteOutDir": true,
    "plugins": ["@nestjs/swagger/plugin"]
  }
}
```

{% endcode %}

* Create the setting

{% code title="swagger-document.ts" %}

```typescript
export const initializeSwaggerDoc = (app: INestApplication) => {
  const contextPath = process.env.CONTEXT_PATH || 'v1';
  app.setGlobalPrefix(contextPath);
  const config = new DocumentBuilder()
    .setTitle('Test API')
    .setDescription('Draft version')
    .setVersion('1.0')
    //   .addServer(process.env.BACKEND_ENV)
    .setBasePath(contextPath)
    .build();

  const options: SwaggerDocumentOptions = {
    include: [AppModule],
    deepScanRoutes: true,
    operationIdFactory: (controllerKey: string, methodKey: string) => methodKey,
  };

  const documentFactory = SwaggerModule.createDocument(app, config, options);

  // The ui will be generated on /v1/open-api
  // The open api spec will be generated on /v1/open-api-json
  SwaggerModule.setup(`${contextPath}/open-api`, app, documentFactory, {
    swaggerOptions: {
      tagsSorter: 'alpha',
      operationsSorter: 'alpha',
    },
  });
};
```

{% endcode %}

{% code title="main.ts" %}

```typescript
initializeSwaggerDoc(app);
```

{% endcode %}

* The `SwaggerModule` searches for all `@Body()`, `@Query()`, and `@Param()` decorators in route handlers to generate the API document
* In order to make the class properties visible to the `SwaggerModule`, we have to either annotate them with the `@ApiProperty()` decorator or use the CLI plugin (read more in the **Plugin** section) which will do it automatically

## Api Property

* To override the attributes of object, it can be declared through decorator

```typescript
export enum UserRole {
  Admin = 'Admin',
  Moderator = 'Moderator',
  User = 'User',
}

export class TestType {
  name: string;
  age: number;
  @ApiProperty({ enum: ['Admin', 'Moderator', 'User'], description: 'User Role' })
  role: UserRole;
}
```

## Api Response&#x20;

* In order to declare the schema of api response, it is needed to declare via api extra models and api response decorators

```typescript

 @ApiExtraModels(ContentPointEntity)
 @ApiResponse({
    status: 200,
    description: 'OK',
    content: {
      'application/json': {
        schema: {
          $ref: getSchemaPath(ContentPointEntity),
        },
      },
    },
  })
async createInsightCase(@Body() createInsightCaseDto: CreateInsightCaseDto) {
  return await this.insightService.createInsightCase(createInsightCaseDto);
}
```

* In order to make code clearer , it can be grouped into single decorator

<pre class="language-typescript"><code class="lang-typescript">import { applyDecorators, Type } from '@nestjs/common';
import { PaginatedDto2 } from './insight.dto';
import { ApiExtraModels, ApiResponse, getSchemaPath, PartialType } from '@nestjs/swagger';
<strong>export const ApiPaginatedResponse = 
</strong>&#x3C;TModel extends Type&#x3C;any>>(model: TModel) => {
  return applyDecorators(
    ApiExtraModels(PaginatedDto2, model),
    ApiResponse({
      status: 200,
      description: 'OK',
      schema: {
        allOf: [
          { $ref: getSchemaPath(PartialType(PaginatedDto2)) },
          {
            properties: {
              results: {
                type: 'array',
                items: { $ref: getSchemaPath(model) },
              },
            },
          },
        ],
      },
    }),
  );
};
</code></pre>
