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

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

# DataStorage Class

Class for working with browser localStorage and sessionStorage with automatic serialization, caching, and singleton pattern. Provides type-safe storage operations with cache time validation and automatic prefix management.

## Key Features

- **Type-safe storage** — full TypeScript support with generics for stored data
- **Dual storage support** — works with both localStorage and sessionStorage
- **Automatic serialization** — JSON serialization/deserialization handled automatically
- **Cache time validation** — optional cache expiration with automatic cleanup
- **Singleton pattern** — reuses instances for same storage keys
- **Prefix management** — configurable prefix for all storage keys (default 'ui-storage')
- **Function value support** — accepts functions as values for dynamic data generation
- **Browser compatibility** — safe usage with server-side rendering

## Configuration

### `static setPrefix`

Sets the global prefix for all storage keys. Should be called at application startup.

**Parameters:**
- `newPrefix: string` — new prefix for storage keys

**Returns:** `void`

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

// Set application-wide prefix
DataStorage.setPrefix('myapp-storage')

// All storage keys will now use this prefix:
// 'user-settings' → 'myapp-storage__user-settings'
// Default prefix: 'ui-storage'
```

## Constructor

### `constructor`

Creates DataStorage instance for specified key. Uses singleton pattern.

**Parameters:**
- `name: string` — storage key name
- `isSession?: boolean` — use sessionStorage instead of localStorage (default: false)

**Returns:** `DataStorage<T>` — class instance (or existing from cache)

```javascript
// localStorage instance
const userPrefs = new DataStorage('user-preferences')

// sessionStorage instance
const tempData = new DataStorage('temp-data', true)

// Singleton behavior
const sameInstance = new DataStorage('user-preferences')
console.log(userPrefs === sameInstance) // true
```

## Data Operations

### `get`

Retrieves data from storage with optional default value and cache validation.

**Parameters:**
- `defaultValue?: T | (() => T)` — default value or function if no data found (optional)
- `cache?: number` — cache time in **seconds** for validation (optional)

**Returns:** `T | undefined` — stored data, default value, or undefined

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

// Get data without default
const theme = settings.get()
console.log(theme) // undefined if no data stored

// Get with default value
const language = settings.get('en')
console.log(language) // 'en' if no stored data, or stored value

// Get with default function
const config = settings.get(() => ({
  theme: 'dark',
  notifications: true,
  created: Date.now()
}))

// Get with cache validation (600 seconds = 10 minutes)
const cachedData = settings.get(null, 600)
// Returns undefined if data older than 10 minutes
// Returns stored data if cache is valid
```

### `set`

Stores data in storage with automatic serialization.

**Parameters:**
- `value?: T | (() => T)` — value to store or function that returns value (optional)

**Returns:** `T | undefined` — stored value

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

// Store simple value
const stored = userStorage.set({ name: 'John', age: 30 })
console.log(stored) // { name: 'John', age: 30 }

// Store with function
userStorage.set(() => ({
  timestamp: Date.now(),
  sessionId: Math.random().toString(36)
}))

// Store undefined to clear
userStorage.set(undefined) // Removes from storage
```

### `remove`

Removes data from storage.

**Returns:** `this` — DataStorage instance for method chaining

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

// First set data
userStorage.set({ name: 'John', preferences: { theme: 'dark' } })
console.log(userStorage.get()) // { name: 'John', preferences: { theme: 'dark' } }

// Remove
userStorage.remove()
console.log(userStorage.get()) // undefined

// Method chaining
userStorage
  .set({ temp: 'data' })
  .remove() // Removes just saved data
```

### `update`

Updates data from storage by re-reading it.

**Returns:** `this` — DataStorage instance for method chaining

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

// Set data
storage.set({ value: 'initial' })
console.log(storage.get()) // { value: 'initial' }

// Data changed in another tab/browser window
// or directly via localStorage.setItem()

// Update data from storage
storage.update()
console.log(storage.get()) // Gets actual data from storage

// Method chaining
storage.update().get() // Update and get fresh data
```

## Practical Examples

### User Settings

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

// Get with default value
const theme = settings.get(() => 'light')
console.log(theme) // 'light' or saved value

// Save new value
settings.set('dark')

// Remove settings
settings.remove()
```

### Data Cache with TTL

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

  // Try to get from cache (cacheDuration in seconds)
  const cached = storage.get(undefined, cacheDuration)
  if (cached) return cached

  // Load fresh data
  const response = await fetch(url)
  const data = await response.json()

  // Save to cache
  storage.set(data)
  return data
}

// Usage
const users = await fetchWithCache('/api/users', 600) // Cache for 10 minutes
```

DataStorage class provides a unified interface for working with browser storage, ensuring type safety, automatic serialization, and flexible data lifetime management with singleton pattern support for efficient memory usage.
