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

<Meta title='@dxtmisha/en/functional/Composables/useApiRequest - API Request Execution'/>

# `useApiRequest`

Returns an object with a loading state and a `send` method for executing API requests. Accepts settings as a single `UseApiRequestSetup` object.

**Parameters:**
- `setup: UseApiRequestSetup` — Configuration setup object:
  - `path?: RefOrNormal<string | undefined>` — Path to the API endpoint (can be reactive).
  - `method?: ApiMethodItem` — HTTP method to use for the request. Defaults to `ApiMethodItem.post`.
  - `action?: (data: Return | undefined) => Promise<void> | void` — Callback action to perform after the request completes successfully.
  - `transformation?: (data: T) => Return` — Function to transform the response data before it is returned or passed to the `action`.
  - `validateRequestContract?: (data: Request) => ApiDataValidation & Return` — Request contract validation function.
  - `validateResponseContract?: (data: T) => ApiDataValidation & Return` — Response contract validation function.
  - `errorContract?: ApiErrorStorageList` — storage of response error contracts.
  - `toData?: boolean` — Whether to extract the `data` field from the response. Defaults to `true`.
  - `options?: ApiOptions` — Additional request options (`ApiFetch` object parameter).
  - `apiInstance?: ApiInstance` — API instance to use for the request. Defaults to `Api.getItem()`.

**Returns:**
An object with the following properties:
- `loading: Ref<boolean>` — Reactive loading state. It becomes `true` while the request is in progress and `false` after it completes or fails.
- `send(request?: Request): Promise<Return | undefined>` — An asynchronous method for sending the request. It automatically manages the `loading` state, validates the request and response contracts, applies the transformation function to the response, executes the `action` callback on success, and handles errors safely by logging them to the console.

## ApiOptions Object

`ApiOptions` — can accept a string with the `method` name (e.g., `'GET'`) or an object of type `ApiFetch`. Fields of the `ApiFetch` object:

- `path?: string` — path to the endpoint script relative to the base URL (e.g., `'users/list'`).
- `pathFull?: string` — full URL of the request. If specified, ignores `api` and `path`.
- `api?: boolean` — whether to add the base URL before `path`. Default: `true`.
- `method?: ApiMethod` — HTTP method (`'GET'`, `'POST'`, `'PUT'`, `'DELETE'`). Default: `'GET'`.
- `request?: FormData | Record<string, any> | string` — request body (for POST/PUT) or query parameters (for GET). Passed as JSON or `FormData`.
- `headers?: Record<string, string> | null` — additional request headers. `null` — disable all headers.
- `type?: string` — `Content-Type` value. Default: `'application/json;charset=UTF-8'`.
- `auth?: boolean` — whether to add authentication headers.
- `toData?: boolean` — if `true`, automatically unwraps `data` from the `{ data: ... }` wrapper. Default: `true`.
- `hideError?: boolean` — suppresses error output to `console.error` on failure. Default: `false`.
- `globalPreparation?: boolean` — whether to run the global `setPreparation` hook before this request. Default: `true`.
- `globalEnd?: boolean` — whether to run the global `setEnd` hook after the response. Default: `true`.
- `queryReturn?: (query: Response) => Promise<any>` — response handler instead of standard JSON reading.
- `init?: RequestInit` — additional options for native `fetch()` (CORS, cache mode, etc.).
- `controller?: AbortController` — controller for canceling the request.

```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('Action complete:', 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('Final Result:', result)
}
```
