import { Meta } from '@storybook/addon-docs/blocks'

<Meta title='@dxtmisha/ru/functional/Composables/useApiRequest - Выполнение запросов'/>

# `useApiRequest`

Возвращает объект с состоянием загрузки и методом `send` для выполнения запросов к API. Принимает настройки в виде единого объекта `UseApiRequestSetup`.

**Параметры:**
- `setup: UseApiRequestSetup` — Объект настроек запроса:
  - `path?: RefOrNormal<string | undefined>` — Путь к endpoint API (может быть реактивным).
  - `method?: ApiMethodItem` — HTTP метод для запроса. По умолчанию `ApiMethodItem.post`.
  - `action?: (data: Return | undefined) => Promise<void> | void` — Действие (коллбэк), выполняемое после успешного завершения запроса.
  - `transformation?: (data: T) => Return` — Функция трансформации ответа от сервера перед возвращением или передачей в `action`.
  - `validateRequestContract?: (data: Request) => ApiDataValidation & Return` — Функция валидации контракта отправляемого запроса.
  - `validateResponseContract?: (data: T) => ApiDataValidation & Return` — Функция валидации контракта полученного ответа.
  - `errorContract?: ApiErrorStorageList` — хранилище контрактов ошибок ответа.
  - `toData?: boolean` — Извлекать ли поле `data` из ответа. По умолчанию `true`.
  - `options?: ApiOptions` — Дополнительные опции запроса (объект параметров `ApiFetch`).
  - `apiInstance?: ApiInstance` — Экземпляр API, используемый для выполнения запроса. По умолчанию `Api.getItem()`.

**Возвращает:**
Объект со следующими свойствами:
- `loading: Ref<boolean>` — Реактивное состояние загрузки. Принимает значение `true` во время выполнения запроса и `false` после его завершения или ошибки.
- `send(request?: Request): Promise<Return | undefined>` — Асинхронный метод для отправки запроса. Он автоматически управляет состоянием `loading`, проверяет контракты валидации запроса и ответа, применяет функцию трансформации к ответу, вызывает коллбэк `action` при успехе и безопасно обрабатывает ошибки, выводя их в консоль.

## Объект ApiOptions

`ApiOptions` — может принимать строку с названием `method` (например, `'GET'`) или объект типа `ApiFetch`. Поля объекта `ApiFetch`:

- `path?: string` — путь к endpoint-скрипту относительно базового URL (например: `'users/list'`).
- `pathFull?: string` — полный URL запроса. Если указан, игнорирует `api` и `path`.
- `api?: boolean` — добавлять ли базовый URL перед `path`. По умолчанию: `true`.
- `method?: ApiMethod` — HTTP-метод (`'GET'`, `'POST'`, `'PUT'`, `'DELETE'`). По умолчанию: `'GET'`.
- `request?: FormData | Record<string, any> | string` — тело запроса (для POST/PUT) или query-параметры (для GET). Передается как JSON или `FormData`.
- `headers?: Record<string, string> | null` — дополнительные заголовки запроса. `null` — отключить все заголовки.
- `type?: string` — значение `Content-Type`. По умолчанию: `'application/json;charset=UTF-8'`.
- `auth?: boolean` — добавить заголовки аутентификации.
- `toData?: boolean` — если `true`, автоматически разворачивает `data` из обертки `{ data: ... }`. По умолчанию: `true`.
- `hideError?: boolean` — подавляет вывод ошибок в `console.error` при сбое. По умолчанию: `false`.
- `globalPreparation?: boolean` — запускать ли глобальный хук `setPreparation` до этого запроса. По умолчанию: `true`.
- `globalEnd?: boolean` — запускать ли глобальный хук `setEnd` после ответа. По умолчанию: `true`.
- `queryReturn?: (query: Response) => Promise<any>` — обработчик ответа вместо стандартного чтения JSON.
- `init?: RequestInit` — дополнительные опции для нативного `fetch()` (CORS, режим кеша и др.).
- `controller?: AbortController` — контроллер для отмены запроса.

```typescript
import { useApiRequest } from '@dxtmisha/functional'
import { ApiMethodItem } from '@dxtmisha/functional-basic'

const { loading, send } = useApiRequest({
  path: '/api/submit',
  method: ApiMethodItem.post,
  action: (data) => console.log('Действие завершено:', data),
  transformation: (raw) => ({ ...raw, processed: true }),
  validateRequestContract: (req) => ({ success: true, ...req }),
  validateResponseContract: (res) => ({ success: true, ...res }),
  toData: true,
  options: { cache: false }
})

const handleSubmit = async () => {
  const result = await send({ name: 'User' })
  console.log('Итоговый результат:', result)
}
```
