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

<Meta title='@dxtmisha/en/functional-basic/Classes/DataStorage - Local and Session Storage Wrapper'/>

# DataStorage Class

A versatile class for interacting with the browser's `localStorage` and `sessionStorage`. It features built-in prefixes, cache expiration, memory caching for active instances, and automatic JSON serialization.

> `DataStorage` is an **auxiliary class**, designed for low-level interaction with browser storage. In most cases, it is recommended to use higher-level classes like `Cookie` or `Api` for specific data needs.

## Key Features

- **Automatic Serialization** — seamlessly handles JSON parsing and stringifying for stored configurations and objects.
- **Time-based Caching** — allows saving objects with timestamps and respects age constraints during data retrieval.
- **Prefix Management** — supports global and instance-specific prefixes to isolate and group keys within `localStorage`.
- **Memory Efficiency** — creates singletons for identical keys, avoiding duplicate reads from disk.
- **SSR Ready** — uses request-specific isolation during server-side rendering to prevent data leaks between parallel requests.

## Initialization

To initialize the object, call the `DataStorage(name, isSession)` constructor.

### Generic Constraints

The class supports the following generic to ensure strict typing of the stored value:
- `T` — The type of the value being stored.

**Parameters:**
- `name: string` — the name of the storage key.
- `isSession: boolean = false` — whether to use `sessionStorage` (defaults to `localStorage`).

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

// 1. Create an instance for localStorage
const settings = new DataStorage('settings')

// 2. Create an instance for sessionStorage
const session = new DataStorage('user_session', true)
```

## Methods

### Storage Access

- `get(defaultValue?: T | (() => T), cache?: number): T | undefined` — Retrieves the currently saved value. If a cache time is provided, it returns `undefined` if the data is stale.
- `set(value?: T | (() => T)): T | undefined` — Sets or updates the value in the storage mechanism. Passing `undefined` deletes the item.
- `remove(): this` — Clears the corresponding key from the storage environment and the memory instance.
- `update(): this` — Forces the memory instance to synchronize with the current raw data inside the physical Storage APIs.

### Configuration

- `static setPrefix(newPrefix: string): void` — Changes the global prefix applied to new instances. The default prefix is `ui-storage`.

## SSR and Hydration

The `DataStorage` class is fully compatible with Server-Side Rendering (SSR). It uses a special registry to isolate instances between different HTTP requests on the server.

> To avoid hydration mismatches (when the server-rendered HTML differs from the client-rendered one), it is recommended to call `get()` inside `useEffect` or other client-only hooks. On the server, `get()` will return `undefined` (or the `defaultValue`), as `localStorage` is not available.

## Examples

### Using Default Values and Cache
```javascript
const settings = new DataStorage('user_settings')

// Get data, falling back to an empty object if not found
const currentSettings = settings.get({})

// Get data only if it was saved within the last 60 seconds
const cachedItem = settings.get(undefined, 60)
```

### Manual Synchronization
```javascript
const storage = new DataStorage('shared_data')

// ... data might be changed in another tab or part of the app
storage.update() // Sync memory instance with disk
console.log(storage.get())
```
