From 1476770ec8965cbca39e8e5dc2268a78bfddaa17 Mon Sep 17 00:00:00 2001 From: realrafi Date: Sun, 19 Jul 2026 04:12:17 +0330 Subject: [PATCH] feat: configured swagger --- package.json | 8 ++++---- pnpm-lock.yaml | 8 ++++---- pnpm-workspace.yaml | 4 ++-- src/config/swagger.config.ts | 35 ++++++++++++++++++++++++++++++++ src/main.ts | 5 ++++- src/users/DTO/create-user.dto.ts | 8 +++++++- 6 files changed, 56 insertions(+), 12 deletions(-) create mode 100644 src/config/swagger.config.ts diff --git a/package.json b/package.json index 2cfae7b..2dc24d6 100644 --- a/package.json +++ b/package.json @@ -20,10 +20,10 @@ "test:e2e": "jest --config ./test/jest-e2e.json" }, "dependencies": { - "@nestjs/common": "^11.0.1", + "@nestjs/common": "^11.1.28", "@nestjs/config": "^4.0.4", - "@nestjs/core": "^11.0.1", - "@nestjs/platform-express": "^11.0.1", + "@nestjs/core": "^11.1.28", + "@nestjs/platform-express": "^11.1.28", "@nestjs/swagger": "^11.4.6", "@nestjs/typeorm": "^11.0.3", "bcrypt": "^6.0.0", @@ -40,7 +40,7 @@ "@eslint/js": "^9.18.0", "@nestjs/cli": "^11.0.0", "@nestjs/schematics": "^11.0.0", - "@nestjs/testing": "^11.0.1", + "@nestjs/testing": "^11.1.28", "@types/bcrypt": "^6.0.0", "@types/express": "^5.0.0", "@types/jest": "^30.0.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3eca4ac..9643c98 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -9,16 +9,16 @@ importers: .: dependencies: '@nestjs/common': - specifier: ^11.0.1 + specifier: ^11.1.28 version: 11.1.28(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2) '@nestjs/config': specifier: ^4.0.4 version: 4.0.4(@nestjs/common@11.1.28(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(rxjs@7.8.2) '@nestjs/core': - specifier: ^11.0.1 + specifier: ^11.1.28 version: 11.1.28(@nestjs/common@11.1.28(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/platform-express@11.1.28)(reflect-metadata@0.2.2)(rxjs@7.8.2) '@nestjs/platform-express': - specifier: ^11.0.1 + specifier: ^11.1.28 version: 11.1.28(@nestjs/common@11.1.28(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.28) '@nestjs/swagger': specifier: ^11.4.6 @@ -64,7 +64,7 @@ importers: specifier: ^11.0.0 version: 11.1.0(chokidar@4.0.3)(prettier@3.9.5)(typescript@5.9.3) '@nestjs/testing': - specifier: ^11.0.1 + specifier: ^11.1.28 version: 11.1.28(@nestjs/common@11.1.28(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.28)(@nestjs/platform-express@11.1.28) '@types/bcrypt': specifier: ^6.0.0 diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 550ade2..cb54f9b 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -1,4 +1,4 @@ allowBuilds: - '@scarf/scarf': set this to true or false - bcrypt: set this to true or false + '@scarf/scarf': false + bcrypt: false unrs-resolver: false diff --git a/src/config/swagger.config.ts b/src/config/swagger.config.ts new file mode 100644 index 0000000..ff6ddaf --- /dev/null +++ b/src/config/swagger.config.ts @@ -0,0 +1,35 @@ +import { INestApplication } from '@nestjs/common'; +import { NestExpressApplication } from '@nestjs/platform-express'; +import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger'; + +export function setupSwagger(app: INestApplication) { + const swaggerConfig = new DocumentBuilder() + .setTitle('Governorate API Document') + .setDescription('The Governorate API description') + .addBearerAuth( + { + type: 'http', + scheme: 'bearer', + bearerFormat: 'JWT', + name: 'authorization', + in: 'header', + }, + 'authorization', + ) + .setVersion('1.0.0') + .build(); + + const swaggerDocument = SwaggerModule.createDocument(app, swaggerConfig); + SwaggerModule.setup('api-docs', app, swaggerDocument, { + customSiteTitle: 'Governorate API Doc', + swaggerOptions: { + persistAuthorization: true, + displayRequestDuration: true, + filter: true, + showExtensions: true, + docExpansion: 'none', + defaultModelsExpandDepth: -1, + defaultModelExpandDepth: -1, + }, + }); +} diff --git a/src/main.ts b/src/main.ts index 789fb1a..3df971c 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,6 +1,7 @@ import { NestFactory, Reflector } from '@nestjs/core'; import { AppModule } from './app.module'; import { ClassSerializerInterceptor, ValidationPipe } from '@nestjs/common'; +import { setupSwagger } from './config/swagger.config'; async function bootstrap() { const app = await NestFactory.create(AppModule); @@ -17,7 +18,9 @@ async function bootstrap() { app.useGlobalInterceptors( new ClassSerializerInterceptor(app.get(Reflector)) - ) + ); + + setupSwagger(app); await app.listen(process.env.PORT ?? 3000); } diff --git a/src/users/DTO/create-user.dto.ts b/src/users/DTO/create-user.dto.ts index 51b0fa6..bdc1a18 100644 --- a/src/users/DTO/create-user.dto.ts +++ b/src/users/DTO/create-user.dto.ts @@ -1,3 +1,4 @@ +import { ApiProperty } from '@nestjs/swagger'; import { Exclude } from 'class-transformer'; import { IsEmail, @@ -9,25 +10,30 @@ import { } from 'class-validator'; export class CreateUserDto { + @ApiProperty({ example: 'Mahdi' }) @IsString() @IsNotEmpty() @MaxLength(20) firstName: string; + @ApiProperty({ example: 'Rafie' }) @IsString() @IsNotEmpty() lastName: string; - @MaxLength(20) + @ApiProperty({ example: 'mahdirafie@gmail.com' }) + @MaxLength(20) @IsEmail() @MaxLength(100) email: string; + @ApiProperty({ example: '09123456789' }) @Matches(/^09\d{9}$/, { message: 'Phone number must be a valid Iranian mobile number.', }) phone: string; + @ApiProperty({ example: 'MahdiPassword@5!' }) @IsString() @MinLength(8) @Exclude()