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

<Meta title='@dxtmisha/en/functional-basic/# Api'/>

# Api

The `Api` class is a central utility for making HTTP requests. It provides a simple interface for common methods and manages global settings like base URL, default headers, and lifecycle hooks.

### Key Capabilities

The class provides a comprehensive set of tools for managing network communication:
- **CRUD Methods** — execution of `GET`, `POST`, `PUT`, `PATCH`, `DELETE` requests.
- **Global Configuration** — setting up base URLs, headers, and parameters.
- **Lifecycle Hooks** — handling events before and after the request (e.g., for Refresh Token).
- **Hydration (SSR)** — transferring data from server to client to prevent duplicate requests.
- **Caching** — saving responses in memory or external storage (LocalStorage).
- **Response Emulation** — creating mock data for development and testing.
- **Loading and Error Management** — integration with global indicator components and error centers.

## Basic Usage

The simplest way to make a request is by using the static methods `get`, `post`, `put`, or `delete`. All methods support response typing via Generics.

```javascript
import { Api } from '@dxtmisha/functional-basic'

// Simple GET request with typing
const data = await Api.get<User[]>({ path: 'users' })

// POST request with data in the body
const newUser = await Api.post<User>({
  path: 'users',
  request: { name: 'John Doe', job: 'Developer' }
})
```

## Global Configuration

You can configure the API behavior globally, for example, during application initialization. This removes the need to specify full paths and common headers in every call.

```javascript
// Set the base URL for all relative paths
Api.setUrl('https://api.example.com/v1/')

// Add common headers (e.g., an authorization token)
Api.setHeaders({
  'Authorization': 'Bearer YOUR_TOKEN'
})

// Set common parameters to be added to every request
Api.setRequestDefault({
  app_version: '1.0.0'
})
```

## Lifecycle Hooks

The library allows you to inject global logic that will trigger for every request. This is useful for dynamically adding tokens, logging, or centralized server error handling.

### Preparation Hook (setPreparation)

Executed immediately before a request is sent to the server.

- **Parameters**: Receives the `apiFetch` object, which contains all parameters of the current request (path, method, data, etc.).
- **Usage**: Checking access rights, adding dynamic parameters to `apiFetch.request`, or simply logging the start of an operation.

```javascript
Api.setPreparation(async (apiFetch) => {
  // You can modify apiFetch before sending
  console.log(`Starting request to: ${apiFetch.path}`)
})
```

### End Hook (setEnd)

Executed after the server returns a response, but before the data reaches your code.

- **Parameters**: Receives the native `Response` object and the `apiFetch` settings object.
- **Returns**: A Promise with an object `{ reset?: boolean, data?: any }`.
- **Reset Flag**: If `true` is returned, the library will abort the current chain and execute the request again. This is useful for automatically handling an expired token (Refresh Token).
- **Data Field**: Allows you to replace or supplement the data returned by the `Api.request` method.

```javascript
Api.setEnd(async (response, apiFetch) => {
  // For example, handling a 401 Unauthorized error
  if (response.status === 401) {
    const isRefreshed = await myAuthService.refreshToken()
    
    if (isRefreshed) {
      return { reset: true } // Retry the request with the new token
    }
  }
  
  return {} // Continue with standard processing
})
```

## Hydration

Hydration allows transferring data obtained during server-side rendering (SSR) to the client side. This prevents the same requests from being executed again immediately after the page loads.

1. **On the Server**: Perform the necessary requests and get the script via `Api.getHydrationScript()`.
2. **In the Template**: Insert the resulting string into the HTML.
3. **On the Client**: Upon `Api` initialization, the data will be automatically loaded into the response manager.

```javascript
// SSR Example
await Api.get({ path: 'settings' });
const hydrationScript = Api.getHydrationScript(); // <script>...</script>
```

## Caching

The `Api` class supports automatic response caching. You can use either the built-in in-memory storage or connect external storage (e.g., `LocalStorage`).

```javascript
import { ApiCache, DataStorage } from '@dxtmisha/functional-basic';

// Connecting external storage (optional)
ApiCache.init(
  async (key) => DataStorage.get(key),
  async (key, value) => DataStorage.set(key, value)
);

// Usage in a request
const data = await Api.get({
  path: 'catalog/list',
  cache: 3600 // Cache for 1 hour (in seconds)
});
```

## Response Emulation

The built-in `ApiResponse` manager (accessible via `Api.getResponse()`) allows you to intercept requests and return mock data. This is extremely useful for UI development when the backend is not ready, or for writing tests.

### Registering Mocks

You can add both static responses and dynamic functions.

```javascript
const responseManager = Api.getResponse()

// 1. Static response for a GET request
responseManager.add({
  path: 'profile',
  method: 'GET',
  response: { id: 1, name: 'Admin' },
  lag: true // Simulate network delay (0-2 sec)
})

// 2. Dynamic response based on request parameters
responseManager.add({
  path: 'users/search',
  method: 'GET',
  response: (request) => {
    return {
      results: [`Result for: ${request.query}`],
      count: 1
    }
  }
})

// 3. Intercept a POST request with any body
responseManager.add({
  path: 'users/update',
  method: 'POST',
  request: '*any', // Ignore request body validation
  response: { success: true }
})
```

### Developer Mode

For easier debugging, you can enable emulation logging in the console. In this mode, the manager will warn in the console about every intercepted request.

```javascript
Api.getResponse().setDevMode(true)
```

The emulator triggers **before** the real `fetch` is executed. If no matching mock is found, `Api` will perform a regular network request.
