Files
2026-01-29 16:00:19 +03:00

10 KiB
Raw Permalink Blame History

API

В этом разделе собраны основные правила и рекомендации по созданию, оформлению и использованию API-клиентов и функций для работы с сервером. Следуйте этим принципам, чтобы обеспечить единый стиль, безопасность и удобство поддержки API-слоя в проекте.

Описание и назначение API-клиента

API-клиент — это модуль (папка), отвечающий за взаимодействие с конкретным внешним или внутренним API.
В проекте для HTTP-запросов используется только Axios.
API-клиент инкапсулирует:

  • инициализацию экземпляра Axios,
  • настройку базового URL, интерцепторов, обработчиков ошибок,
  • организацию всех сущностей и методов для работы с этим API (например, users, auth, orders и т.д.),
  • экспорт всех функций, типов и fetcher через индексные файлы.

Каждый API-клиент размещается в папке src/shared/api/<client-name>/ и имеет собственную структуру согласно архитектуре проекта.

Использование методов API

  • Все методы API должны использоваться строго внутри блока try...catch.
  • При вызове методов API всегда используйте полный путь, например:
    await api.backend.createUser({ email, password });
  • Запрещено вызывать методы API вне блока try...catch даже в тестах, утилитах и других вспомогательных функциях.

Структура клиента

src/shared/api/backend/
│
├── client.ts
├── index.ts
└── entities/
    ├── users/
    │   ├── get-me.api.ts
    │   ├── create-user.api.ts
    │   ├── update-user.api.ts
    │   └── index.ts
    ├── auth/
    │   ├── login.api.ts
    │   ├── register.api.ts
    │   └── index.ts
    └── index.ts

Описание ключевых элементов

  • client.ts
    Экземпляр Axios с настройками, интерцепторами, экспортом fetcher для SWR.

  • index.ts
    Главная точка экспорта: экспортирует client, fetcher, все сущности и их методы.

  • entities/
    Папка для бизнес-сущностей (например, users, auth, orders и т.д.).

  • <entity>/
    Папка для отдельной сущности. Имя — в kebab-case, отражает бизнес-область (например, users, auth).

  • <operation>.api.ts
    Файл для каждой операции (CRUD, спец. действия).
    Внутри:

    • DTO (интерфейсы запроса/ответа)
    • Функция, реализующая запрос через client
  • index.ts (внутри <entity>/)
    Экспортирует все методы и типы этой сущности.

  • index.ts (внутри entities/)
    Экспортирует все сущности (users, auth и т.д.).

Именование

  • Соблюдайте правила именования файлов и папок:
    • Файл клиента — client.ts.
    • Файл функции — <operation>-<entity>.api.ts (например, create-user.api.ts).
    • DTO — в папке dto/ (например, create-user.dto.ts).
    • Все функции и типы экспортируются через индексные файлы на каждом уровне (сущность, entities, клиент).

Требования

  • Для каждого действия (CRUD, спец. действия) — отдельная функция и файл.
  • Все функции используют общий экземпляр Axios из client.ts.
  • Все функции строго типизированы (используются DTO).
  • DTO объявляется в отдельном файле в папке dto/ перед функцией, которая его использует.
  • Для каждого GET метода обязательно должен быть создан API-хук.
  • Все API-хуки должны создаваться строго по документации раздела "Хуки для API".

Типизация

  • Все функции и DTO строго типизированы.
  • Все интерфейсы, типы и enum размещены в папке types/ на своём уровне абстракции.
  • Все DTO размещены в папке dto/ на своём уровне абстракции.
  • Придерживайтесь общих правил типизации проекта.

Документирование

  • Документируйте только назначение функций и DTO.
  • В описании указывается только смысл функции/типа.

Экспорт

  • Все функции и типы экспортируются через индексные файлы на каждом уровне (сущность, entities, клиент).

Примеры

Пример клиента API

// client.ts
import axios, { AxiosInstance } from "axios";
export { AxiosError, isAxiosError } from 'axios';
export type { AxiosResponse } from 'axios';

/**
 * Экземпляр HTTP-клиента для работы с backend API.
 */
export const backendHttpClient: AxiosInstance = axios.create({
  baseURL: '/api',
  timeout: 10000,
});

// Интерцептор запроса
backendHttpClient.interceptors.request.use(
  (config) => {
    // Здесь можно добавить авторизационные заголовки или другую логику
    return config;
  },
  (error) => Promise.reject(error)
);

// Интерцептор ответа
backendHttpClient.interceptors.response.use(
  (response) => response,
  (error) => {
    // Здесь можно обработать ошибки (например, показать уведомление)
    return Promise.reject(error);
  }
);

Пример DTO

// dto/create-user.dto.ts
/**
 * DTO для создания пользователя.
 */
export interface CreateUserDto {
  /** Email пользователя. */
  email: string;
  /** Пароль пользователя. */
  password: string;
}

Пример API-функции

// create-user.api.ts
import { backendHttpClient } from '../client';
import { CreateUserDto } from './dto/create-user.dto';

/**
 * Создать пользователя.
 */
export const createUser = (data: CreateUserDto) => backendHttpClient.post('/users', data);

Пример index.ts (в папке сущности)

export * from './create-user.api';
export * from './get-user.api';

Пример использования API-функции в компоненте

import React, { useState } from 'react';
import { api } from 'shared/api';

export const CreateUserForm: React.FC = () => {
  const [email, setEmail] = useState('');
  const [password, setPassword] = useState('');

  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault();
    try {
      await api.backend.createUser({ email, password });
      console.log('Пользователь создан!');
    } catch {
      console.log('Ошибка создания пользователя');
    }
  };

  return (
    <form onSubmit={handleSubmit}>
      <input
        type="email"
        value={email}
        onChange={e => setEmail(e.target.value)}
        placeholder="Email"
        required
      />
      <input
        type="password"
        value={password}
        onChange={e => setPassword(e.target.value)}
        placeholder="Пароль"
        required
      />
      <button type="submit">Создать пользователя</button>
    </form>
  );
};

Чек-лист для создания клиента

  • Новый клиент размещён в src/shared/api/<client-name>/.
  • В корне клиента есть client.ts (экземпляр Axios) и index.ts (главный экспорт).
  • Все бизнес-сущности размещены в entities/, каждая — в отдельной папке.
  • Для каждой операции создан отдельный файл <operation>.api.ts с DTO и функцией.
  • DTO объявлен непосредственно перед функцией.
  • В каждой папке сущности есть свой index.ts для экспорта методов и типов.
  • В папке entities/ есть общий index.ts для экспорта всех сущностей.
  • Все экспорты организованы через индексные файлы.
  • Для каждого GET-метода создан отдельный SWR-хук (см. правила API-хуков).
  • Нет дублирования кода и неиспользуемых файлов.

Чек-лист для использования API

  • Импортируется только нужный метод через публичные экспорты (index.ts).
  • Все вызовы API обёрнуты в try...catch.
  • Используются только строго типизированные методы.
  • Не происходит обращения к Axios напрямую — только через client.
  • Нет дублирования логики и неиспользуемого кода.