توثيق OpenAPI / Swagger
الواجهات البرمجية الجيدة ليست وظيفية فحسب — بل هي قابلة للاكتشاف. يمنح OpenAPI (المواصفة) وواجهة Swagger UI (متصفّح التوثيق التفاعلي) كلّ مستهلك عقدًا حيًّا وموصوفًا ذاتيًّا لنقاط النهاية. يقدّم NestJS دعمًا متكاملًا عبر @nestjs/swagger، الذي يقرأ مزخرفات TypeScript الخاصة بك ويولّد المواصفة تلقائيًّا.
التثبيت والإعداد
npm install @nestjs/swagger
شغّل Swagger في main.ts باستخدام SwaggerModule وDocumentBuilder:
import { NestFactory } from '@nestjs/core';
import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
const config = new DocumentBuilder()
.setTitle('Tasks API')
.setDescription('Manage user tasks')
.setVersion('1.0')
.addBearerAuth() // يُضيف زرّ التفويض لـ JWT
.build();
const document = SwaggerModule.createDocument(app, config);
SwaggerModule.setup('api-docs', app, document); // الواجهة على /api-docs
await app.listen(3000);
}
bootstrap();
يُولَّد مرّة واحدة ويُخدَم للأبد. تفحص SwaggerModule.createDocument() كلّ متحكّم وكائن DTO في رسم بيانات تطبيقك وتنتج مستندًا JSON يتوافق مع مواصفة OpenAPI 3.0. يتوفّر JSON الخام على /api-docs-json لدمجه مع الأدوات الخارجية.
@ApiTags — تجميع المتحكّمات
ضع علامةً على متحكّم ليُجمَّع ضمن قسم مُسمَّى في الواجهة:
import { Controller, Get } from '@nestjs/common';
import { ApiTags } from '@nestjs/swagger';
@ApiTags('tasks')
@Controller('tasks')
export class TasksController {
@Get()
findAll() { /* ... */ }
}
توثيق كائنات DTO باستخدام @ApiProperty
تُزيّن @ApiProperty كلّ حقل في كائن DTO، مانحةً Swagger النوع والوصف وقيمة المثال وقيود التحقّق الخاصة بمخطّط جسم الطلب:
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
import { IsString, IsNotEmpty, IsOptional, IsEnum } from 'class-validator';
export enum TaskStatus {
OPEN = 'OPEN',
IN_PROGRESS = 'IN_PROGRESS',
DONE = 'DONE',
}
export class CreateTaskDto {
@ApiProperty({ description: 'Short task title', example: 'Write unit tests' })
@IsString()
@IsNotEmpty()
title: string;
@ApiPropertyOptional({
description: 'Longer description',
example: 'Cover all service methods with Jest',
})
@IsOptional()
@IsString()
description?: string;
@ApiProperty({ enum: TaskStatus, default: TaskStatus.OPEN })
@IsEnum(TaskStatus)
status: TaskStatus;
}
استخدم @ApiPropertyOptional للحقول الاختيارية. هو اختصار لـ @ApiProperty({ required: false }) ويُبقي مزخرفات DTO موجزة. أضف قيمة example دائمًا — فهي تجعل ميزة "جرّبها الآن" مفيدة فعلًا.
@ApiResponse — توثيق أنواع البيانات المُعادة
زيّن معالجات المسارات الفردية لوصف استجابات HTTP المحتملة، بما فيها شكل البيانات المُعادة:
import { Get, Param } from '@nestjs/common';
import {
ApiOkResponse,
ApiNotFoundResponse,
ApiUnauthorizedResponse,
} from '@nestjs/swagger';
import { Task } from './task.entity';
@Get(':id')
@ApiOkResponse({ type: Task, description: 'The task record' })
@ApiNotFoundResponse({ description: 'Task not found' })
@ApiUnauthorizedResponse({ description: 'Missing or invalid JWT' })
findOne(@Param('id') id: string) {
return this.tasksService.findOne(id);
}
بالنسبة لصنف الكيان نفسه، زيّن خصائصه بالطريقة ذاتها التي تُزيّن بها حقول DTO:
import { ApiProperty } from '@nestjs/swagger';
export class Task {
@ApiProperty({ example: 'f47ac10b-58cc-4372-a567-0e02b2c3d479' })
id: string;
@ApiProperty({ example: 'Write unit tests' })
title: string;
@ApiProperty({ enum: TaskStatus })
status: TaskStatus;
}
@ApiBearerAuth — حماية المسارات في الواجهة
حين تستلزم مسارًا توكن JWT، أضف @ApiBearerAuth() لتجعل واجهة Swagger UI ترسل التوكن من نافذة التفويض:
import { UseGuards } from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';
import { ApiBearerAuth, ApiTags } from '@nestjs/swagger';
@ApiTags('tasks')
@ApiBearerAuth()
@UseGuards(AuthGuard('jwt'))
@Controller('tasks')
export class TasksController { /* ... */ }
لا تكشف Swagger في الإنتاج بلا مصادقة. يمكن تغليف استدعاء SwaggerModule.setup() بشرط مثل if (process.env.NODE_ENV !== 'production')، أو حمايته خلف HTTP basic auth. تُسرّب واجهة Swagger العامة كامل سطح API للمهاجمين.
الخلاصة
يولّد @nestjs/swagger مستند OpenAPI 3.0 مباشرةً من مزخرفاتك. ثبّت الحزمة، واستدعِ SwaggerModule.setup() في main.ts، ثم زيّن المتحكّمات بـ @ApiTags، وكائنات DTO بـ @ApiProperty، والمعالجات بمتغيّرات @ApiResponse، والمسارات المحمية بـ @ApiBearerAuth(). والنتيجة واجهة Swagger UI حيّة وتفاعلية تضاعف دورها توثيقًا قابلًا للتنفيذ لكلّ مستهلك API في فريقك.