Skip to content

Стандарты API

Обёртка ответа

typescript
// Все успешные ответы следуют этому формату
interface SuccessResponse<T> {
  success: true;
  data: T;
  meta?: {
    pagination?: PaginationMeta;
    [key: string]: unknown;
  };
}

interface PaginationMeta {
  total: number;
  page: number;
  pageSize: number;
  totalPages: number;
  hasNext: boolean;
  hasPrevious: boolean;
}

Примеры

Один элемент

json
{
  "success": true,
  "data": {
    "id": "uuid",
    "email": "user@example.com"
  }
}

Список с пагинацией

json
{
  "success": true,
  "data": [
    { "id": "uuid1", "name": "Product 1" },
    { "id": "uuid2", "name": "Product 2" }
  ],
  "meta": {
    "pagination": {
      "total": 100,
      "page": 1,
      "pageSize": 20,
      "totalPages": 5,
      "hasNext": true,
      "hasPrevious": false
    }
  }
}

Пагинация

typescript
// Offset пагинация с query параметрами: ?page=1&pageSize=20

interface PaginationQuery {
  page?: number;      // По умолчанию: 1, минимум: 1
  pageSize?: number;  // По умолчанию: 20, максимум: 100
}

// Использование в контроллере
@Get()
async findAll(
  @Query() pagination: PaginationQuery,
): Promise<SuccessResponse<Product[]>> {
  const { page = 1, pageSize = 20 } = pagination;
  const result = await this.productService.findAll({ page, pageSize });

  return {
    success: true,
    data: result.items,
    meta: { pagination: result.pagination },
  };
}

Фильтрация и сортировка

typescript
// Query параметры для фильтрации
// GET /api/v1/products?status=ACTIVE&categoryId=uuid&minPrice=100&maxPrice=500

// Query параметры для сортировки
// GET /api/v1/products?sortBy=price&sortOrder=asc

interface ProductFilterQuery {
  status?: ProductStatus;
  categoryId?: string;
  minPrice?: number;
  maxPrice?: number;
  search?: string;       // Полнотекстовый поиск по названию/описанию
  sortBy?: 'price' | 'name' | 'createdAt';
  sortOrder?: 'asc' | 'desc';
}

Версионирование API

/api/v1/...  ← Текущая версия

В будущем:
/api/v2/...  ← Только для критических изменений

Стратегия: Версионирование через URL (самый простой способ). Создавать v2 только при неизбежных критических изменениях.


Документация API (Scalar)

Интерактивная документация API с использованием Scalar — современная альтернатива Swagger UI с лучшим UX, тёмной темой и быстрым рендерингом.

Установка

bash
npm install @nestjs/swagger @scalar/nestjs-api-reference

Настройка

typescript
// main.ts
import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger';
import { apiReference } from '@scalar/nestjs-api-reference';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);

  // Спецификация OpenAPI
  const config = new DocumentBuilder()
    .setTitle('IWM Platform API')
    .setDescription('MLM Platform with Investment and Product Marketplaces')
    .setVersion('1.0')
    .addBearerAuth()
    .addTag('auth', 'Authentication endpoints')
    .addTag('users', 'User management')
    .addTag('mlm', 'MLM/Partner operations')
    .addTag('products', 'E-commerce products')
    .addTag('orders', 'Order management')
    .addTag('investments', 'Investment operations')
    .build();

  const document = SwaggerModule.createDocument(app, config);

  // Scalar UI по адресу /api/docs (заменяет Swagger UI)
  app.use('/api/docs', apiReference({
    spec: { content: document },
    theme: 'purple',  // или 'default', 'moon', 'mars'
  }));

  // Опционально: JSON endpoint для внешних инструментов
  app.use('/api/docs/openapi.json', (req, res) => res.json(document));

  await app.listen(3000);
}

Возможности

ФункцияОписание
Try ItИнтерактивный конструктор запросов с поддержкой авторизации
SearchПолнотекстовый поиск по всем эндпоинтам
Dark ModeВстроенное переключение тем
Code SamplesАвтогенерируемые примеры на разных языках
OpenAPI 3.1Полная поддержка спецификации

Доступ

  • Интерактивная документация: http://localhost:3000/api/docs
  • OpenAPI JSON: http://localhost:3000/api/docs/openapi.json

Связанные документы