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

<Meta title='@dxtmisha/ru/functional-basic/Classes/CookieStorage - Хранилище Cookie'/>

# Класс CookieStorage

Класс для управления хранением cookie с поддержкой пользовательских слушателей. Предоставляет низкоуровневый интерфейс для работы с cookie в различных окружениях (DOM, SSR) с автоматическим парсингом типов и безопасной обработкой данных.

Включает тесную интеграцию с `CookieBlock` для контроля доступа и поддерживает декодирование URL-encoded значений.

## Ключевые особенности

- **Гибкое хранение** — поддержка памяти процесса и внешних механизмов хранения через слушатели
- **Автоматическое преобразование** — интеллектуальное преобразование строковых значений в соответствующие типы данных
- **Интеграция с блокировкой** — уважает глобальную блокировку записи через `CookieBlock`
- **Безопасность окружения** — автоматическое определение DOM окружения и адаптация поведения
- **URL-декодирование** — автоматическое декодирование имен и значений при чтении из DOM

## Статические методы

### Действие

#### `get`

Получает значение cookie по имени с автоматическим преобразованием типов. Если значение не существует и указано значение по умолчанию, оно будет установлено и сохранено.

**Параметры:**
- `name: string` — имя cookie
- `defaultValue?: T | (() => T)` — значение по умолчанию или функция, возвращающая значение

**Возвращает:** `T | undefined` — преобразованное значение cookie или значение по умолчанию

#### `set`

Сохраняет значение cookie с указанными параметрами и автоматическим обновлением в памяти и DOM. Если активна блокировка через `CookieBlock`, значение сохраняется только в памяти.

**Параметры:**
- `name: string` — имя cookie
- `value: T | (() => T)` — значение или функция, возвращающая значение
- `options?: CookieOptions` — дополнительные параметры cookie

**Возвращает:** `T` — сохраненное значение

#### `remove`

Удаляет cookie, устанавливая пустое значение и отрицательный срок действия. Эквивалентно вызову `set(name, '', { age: -1 })`.

**Параметры:**
- `name: string` — имя cookie

### Конфигурация

- `init(getListener?, getListenerRaw?, setListener?)` — Инициализирует хранилище с пользовательскими слушателями для чтения и записи данных. Слушатель записи `setListener` принимает 4 аргумента: `(key, value, cookie, options)`.
- `reset()` — Сбрасывает хранилище, очищая все элементы в памяти и удаляя слушатели

### Вспомогательные

- `update()` — Обновляет данные в памяти, парся значения из `document.cookie`

## Типы

### `CookieOptions`

Объект конфигурации для параметров cookie:

- `age?: number` — время жизни в секундах (атрибут max-age)
- `sameSite?: 'strict' | 'lax'` — политика SameSite
- `path?: string` — путь для cookie (по умолчанию `/`)
- `domain?: string` — домен для cookie
- `secure?: boolean` — если true, добавляет атрибут Secure
- `httpOnly?: boolean` — если true, добавляет атрибут HttpOnly (только для серверных слушателей)
- `partitioned?: boolean` — если true, добавляет атрибут Partitioned (CHIPS)
- `arguments?: string[] | Record<string, any>` — дополнительные директивы для строки cookie

## Встроенное преобразование типов

`CookieStorage` автоматически преобразует строковые значения при чтении:

- `'undefined'` → `undefined`
- `'null'` → `null`
- `'true'` → `true`
- `'false'` → `false`
- `'123'` → `123` (число)
- `'{"key":"value"}'` → `{key: 'value'}` (объект JSON)

## Примеры

### Базовое использование

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

// Получение значения с дефолтным значением
const theme = CookieStorage.get<string>('theme', 'dark')

// Сохранение значения
CookieStorage.set('user', 'john', {
  age: 3600,
  sameSite: 'lax'
})

// Удаление
CookieStorage.remove('user')
```

### Инициализация с внешним хранилищем

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

CookieStorage.init(
  (key) => myStorage.get(key),
  undefined,
  (key, value, cookie, options) => {
    // cookie - это уже отформатированная строка типа "key=value; max-age=..."
    myStorage.set(key, value, cookie, options)
  }
)
```

### Инициализация для SSR (Raw)

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

// Для SSR получаем все куки в виде сырой строки
CookieStorage.init(
  undefined,
  () => request.headers.cookie
)
```

### Обновление и сброс

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

// Обновить данные в памяти из document.cookie
// Полезно, когда куки были установлены внешне
CookieStorage.update()

// Сбросить хранилище (очистить слушатели и данные в памяти)
// Полезно для тестирования или очистки
CookieStorage.reset()
```

### Полный рабочий процесс

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

// Инициализация с пользовательским хранилищем
CookieStorage.init(
  (key) => redis.get(key),
  undefined,
  (key, value, cookie, options) => redis.set(key, value, cookie, options)
)

// Установка значения с параметрами
CookieStorage.set('user', 'john', {
  age: 3600,           // 1 час
  sameSite: 'lax',     // Политика SameSite
  path: '/',           // Путь
  secure: true,        // Только HTTPS
  httpOnly: true,      // Защита от XSS (для SSR)
  arguments: ['Priority=High'] // Дополнительные директивы
})

// Получение значения с преобразованием типа
const user = CookieStorage.get<string>('user')

// Обновление из внешнего источника
CookieStorage.update()

// Очистка
CookieStorage.remove('user')
CookieStorage.reset()
```
