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

<Meta title='@dxtmisha/en/functional-basic/Classes/ApiCache - API Response Caching'/>

# ApiCache Class

A class for caching API responses. It allows storing query results in memory or an external storage, preventing redundant network calls within a specified period. In the current implementation, caching is active by default only on the server side (SSR) to speed up rendering and reduce API load during concurrent requests.

> `ApiCache` is an **auxiliary class**, designed for low-level cache management. In most cases, it is recommended to interact with caching through the `cache` parameter in `ApiInstance` or the global `Api` object.

## Key Features

- **Automated Key Management** — generates unique cache keys based on request parameters (path, method, body, etc.).
- **Flexible TTL (Time To Live)** — allows setting the storage duration for each request individually or using a default (24 hours).
- **SSR Optimization** — prevents unnecessary API calls in the Node.js environment. Disabled by default in the browser (only works if explicitly enabled through configuration parameters).
- **Listener Support** — ability to connect external storage (e.g., Redis, Nitro Storage) via callback functions.
- **Background Cleanup** — automatically removes expired entries when accessing the cache.

## Methods

### Action

Methods for managing cache entries.

- `get<T>(key: string): Promise<T | undefined>` — Retrieves a value from the cache.
- `getByFetch<T>(fetch: ApiFetch): Promise<T | undefined>` — Retrieves a value using request options as the key source.
- `set<T>(key: string, value: T, age?: number): Promise<void>` — Stores a value in the cache.
- `setByFetch<T>(fetch: ApiFetch, value: T): Promise<void>` — Stores a value using request options.
- `remove(key: string): Promise<void>` — Manually removes an entry.

### Configuration

- `init(getListener, setListener, removeListener, cacheStepAgeClearOld?): void` — Configures the cache with storage listeners.
- `reset(): void` — Clears in-memory items and detaches listeners.

## Types

#### `ApiCacheItem<T>`
The structure of a cached record.
- `value: T` — The cached data.
- `age: number` — TTL in seconds.
- `cacheAge: number` — Creation timestamp (ms).

#### `ApiCacheList`
An internal dictionary for in-memory storage fallback.
- `[key: string]: ApiCacheItem` — Key-value pairs of cached items.

## Initialization and External Storage

By default, `ApiCache` stores records in the process RAM and works only on the server side. While this is fast, it has limitations in production environments:
1. **Cluster Synchronization**: In a multi-instance setup, caches are not shared between processes.
2. **Process Restarts**: Memory is cleared whenever the server restarts or a serverless function "cold starts".
3. **Memory Limits**: Storing large amounts of data in RAM can lead to increased memory consumption.

To solve these issues, you must initialize `ApiCache` with the `init` method, providing listeners that bridge it to an external storage mechanism.

> Important: You must call `ApiCache.init()` during your application's bootstrap phase (before the first API request) to ensure the cache is correctly configured.

### Node.js (Custom Storage)

In a standard Node.js environment, you can use listeners to interact with a centralized database or a persistent cache like Redis.

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

// Configuration with storage listeners
ApiCache.init(
  // 1. Get data from external storage
  async (key) => await myExternalStorage.get(key),
  
  // 2. Save data to external storage
  async (key, value) => {
    await myExternalStorage.put(key, value)
    return true // Return true to indicate successful external storage
  },
  
  // 3. Remove data from external storage
  async (key) => {
    await myExternalStorage.delete(key)
    return true
  },
  
  // 4. Optional: threshold for background cleanup trigger
  16384
)
```

### Nuxt / Nitro

In Nuxt/Nitro, the recommended approach is to use the built-in `useStorage` helper within a server plugin. This allows you to leverage Redis, FS, or other Nitro-supported storage drivers.

```typescript
// server/plugins/api-cache.ts
import { ApiCache } from '@dxtmisha/functional-basic'

export default defineNitroPlugin(() => {
  const storage = useStorage('cache') // Nitro Cache region

  ApiCache.init(
    async (key) => await storage.getItem(key),
    async (key, value) => {
      await storage.setItem(key, value)
      return true
    },
    async (key) => {
      await storage.removeItem(key)
      return true
    }
  )
})
```
