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

<Meta title='@dxtmisha/functional/ru/Classes/DataStorage'/>

# Класс DataStorage

Класс для работы с браузерным localStorage и sessionStorage с автоматической сериализацией, кешированием и singleton паттерном. Предоставляет типобезопасные операции хранения с валидацией времени кеширования и автоматическим управлением префиксами.

## Основные возможности

- **Типобезопасное хранение** — полная поддержка TypeScript с дженериками для хранимых данных
- **Поддержка двух типов хранилища** — работает как с localStorage, так и с sessionStorage
- **Автоматическая сериализация** — JSON сериализация/десериализация обрабатывается автоматически
- **Валидация времени кеша** — опциональное истечение кеша с автоматической очисткой
- **Singleton паттерн** — переиспользует экземпляры для одинаковых ключей хранения
- **Управление префиксами** — настраиваемый префикс для всех ключей хранения (по умолчанию 'ui-storage')
- **Поддержка функций как значений** — принимает функции как значения для динамической генерации данных
- **Совместимость с браузерами** — безопасное использование с серверным рендерингом

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

### `static setPrefix`

Устанавливает глобальный префикс для всех ключей хранения. Должен вызываться при запуске приложения.

**Параметры:**
- `newPrefix: string` — новый префикс для ключей хранения

**Возвращает:** `void`

```javascript
import { DataStorage } from '@dxtmisha/functional'

// Установить префикс для всего приложения
DataStorage.setPrefix('myapp-storage')

// Все ключи хранения теперь будут использовать этот префикс:
// 'user-settings' → 'myapp-storage__user-settings'
// По умолчанию префикс: 'ui-storage'
```

## Конструктор

### `constructor`

Создаёт экземпляр DataStorage для указанного ключа. Использует singleton паттерн.

**Параметры:**
- `name: string` — имя ключа хранения
- `isSession?: boolean` — использовать sessionStorage вместо localStorage (по умолчанию: false)

**Возвращает:** `DataStorage<T>` — экземпляр класса (или существующий из кеша)

```javascript
// Экземпляр localStorage
const userPrefs = new DataStorage('user-preferences')

// Экземпляр sessionStorage
const tempData = new DataStorage('temp-data', true)

// Поведение singleton
const sameInstance = new DataStorage('user-preferences')
console.log(userPrefs === sameInstance) // true
```

## Операции с данными

### `get`

Получает данные из хранилища с опциональным значением по умолчанию и валидацией кеша.

**Параметры:**
- `defaultValue?: T | (() => T)` — значение по умолчанию или функция, если данные не найдены (опционально)
- `cache?: number` — время кеширования в **секундах** для валидации (опционально)

**Возвращает:** `T | undefined` — сохранённые данные, значение по умолчанию или undefined

```javascript
const settings = new DataStorage('app-settings')

// Получить данные без значения по умолчанию
const theme = settings.get()
console.log(theme) // undefined если данные не сохранены

// Получить со значением по умолчанию
const language = settings.get('ru')
console.log(language) // 'ru' если нет сохранённых данных, или сохранённое значение

// Получить с функцией по умолчанию
const config = settings.get(() => ({
  theme: 'dark',
  notifications: true,
  created: Date.now()
}))

// Получить с валидацией кеша (600 секунд = 10 минут)
const cachedData = settings.get(null, 600)
// Возвращает undefined если данные старше 10 минут
// Если кеш валиден - возвращает сохранённые данные
```

### `set`

Сохраняет данные в хранилище с автоматической сериализацией.

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

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

```javascript
const userStorage = new DataStorage('user-data')

// Сохранить простое значение
const stored = userStorage.set({ name: 'Иван', age: 30 })
console.log(stored) // { name: 'Иван', age: 30 }

// Сохранить с функцией
userStorage.set(() => ({
  timestamp: Date.now(),
  sessionId: Math.random().toString(36)
}))

// Сохранить undefined для очистки
userStorage.set(undefined) // Удаляет из хранилища
```

### `remove`

Удаляет данные из хранилища.

**Возвращает:** `this` — экземпляр DataStorage для цепочки вызовов

```javascript
const userStorage = new DataStorage('user-data')

// Сначала установить данные
userStorage.set({ name: 'Иван', preferences: { theme: 'dark' } })
console.log(userStorage.get()) // { name: 'Иван', preferences: { theme: 'dark' } }

// Удаление
userStorage.remove()
console.log(userStorage.get()) // undefined

// Цепочка вызовов
userStorage
  .set({ temp: 'data' })
  .remove() // Удаляет только что сохранённые данные
```

### `update`

Обновляет данные из хранилища, перечитывая их заново.

**Возвращает:** `this` — экземпляр DataStorage для цепочки вызовов

```javascript
const storage = new DataStorage('shared-data')

// Установить данные
storage.set({ value: 'initial' })
console.log(storage.get()) // { value: 'initial' }

// Данные изменились в другой вкладке/окне браузера
// или напрямую через localStorage.setItem()

// Обновить данные из хранилища
storage.update()
console.log(storage.get()) // Получит актуальные данные из хранилища

// Цепочка вызовов
storage.update().get() // Обновить и получить свежие данные
```

## Практические примеры

### Настройки пользователя

```javascript
const settings = new DataStorage('user-settings')

// Получить с значением по умолчанию
const theme = settings.get(() => 'light')
console.log(theme) // 'light' или сохранённое значение

// Сохранить новое значение
settings.set('dark')

// Удалить настройки
settings.remove()
```

### Кеш данных с TTL

```javascript
async function fetchWithCache(url, cacheDuration = 300) {
  const storage = new DataStorage(`api_${url}`)

  // Попытка получить из кеша (cacheDuration в секундах)
  const cached = storage.get(undefined, cacheDuration)
  if (cached) return cached

  // Загрузка свежих данных
  const response = await fetch(url)
  const data = await response.json()

  // Сохранение в кеш
  storage.set(data)
  return data
}

// Использование
const users = await fetchWithCache('/api/users', 600) // Кеш на 10 минут
```

Класс DataStorage предоставляет единый интерфейс для работы с браузерными хранилищами, обеспечивая типобезопасность, автоматическую сериализацию и гибкое управление временем жизни данных с поддержкой singleton паттерна для эффективного использования памяти.
