243 lines
10 KiB
Markdown
243 lines
10 KiB
Markdown
# 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` даже в тестах, утилитах и других вспомогательных функциях.
|
||
|
||
|
||
## Структура клиента
|
||
```text
|
||
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"](#хуки-для-api-api-hooks).
|
||
|
||
|
||
## Типизация
|
||
|
||
- Все функции и DTO строго типизированы.
|
||
- Все интерфейсы, типы и enum размещены в папке `types/` на своём уровне абстракции.
|
||
- Все DTO размещены в папке `dto/` на своём уровне абстракции.
|
||
- Придерживайтесь [общих правил типизации проекта](#общие-правила-типизации).
|
||
|
||
|
||
## Документирование
|
||
|
||
- Документируйте только назначение функций и DTO.
|
||
- В описании указывается только смысл функции/типа.
|
||
|
||
|
||
## Экспорт
|
||
|
||
- Все функции и типы экспортируются через индексные файлы на каждом уровне (сущность, entities, клиент).
|
||
|
||
|
||
## Примеры
|
||
|
||
### Пример клиента API
|
||
|
||
```ts
|
||
// 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
|
||
|
||
```ts
|
||
// dto/create-user.dto.ts
|
||
/**
|
||
* DTO для создания пользователя.
|
||
*/
|
||
export interface CreateUserDto {
|
||
/** Email пользователя. */
|
||
email: string;
|
||
/** Пароль пользователя. */
|
||
password: string;
|
||
}
|
||
```
|
||
|
||
### Пример API-функции
|
||
|
||
```ts
|
||
// 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 (в папке сущности)
|
||
|
||
```ts
|
||
export * from './create-user.api';
|
||
export * from './get-user.api';
|
||
```
|
||
|
||
### Пример использования API-функции в компоненте
|
||
|
||
```tsx
|
||
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.
|
||
- [ ] Нет дублирования логики и неиспользуемого кода.
|