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

<Meta title='@dxtmisha/en/functional-basic/Classes/ServerStorage - Data Isolation in SSR'/>

# ServerStorage Class

`ServerStorage` is a mechanism for managing **isolated global state** in applications with SSR (Server-Side Rendering) support.

The class allows you to work with data as easily as with static variables, but ensures that user data on the server does not intermingle between parallel requests.

## Key Features

- **Request Isolation** — data on the server is bound to the context of the current human or machine request.
- **Hydration** — ability to automatically transfer state from the server to the client via JSON.
- **Security** — automatic XSS escaping during data transfer.

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

// Save data with a hydration flag (will be available on the client)
ServerStorage.set('theme', () => 'dark', true)

// Retrieve data
const theme = ServerStorage.get('theme') // 'dark'
```

## Data Access Methods

### `get`

Retrieves a value by key. If it doesn't exist, creates it using the default value factory.

**Parameters:**
- `key: string` — unique storage key.
- `defaultValue?: () => T` — function that returns the default value if not found.
- `hydration: boolean` — if `true`, the value will be included in the JSON for the client (default: `false`).

**Returns:** `T`

### `set`

Saves a value to the storage.

**Parameters:**
- `key: string` — unique storage key.
- `value: () => T` — function that returns the value to save.
- `hydration: boolean` — if `true`, the value will be included in the JSON for the client (default: `false`).

**Returns:** `T`

## Utility & Lifecycle Methods

- `init(listener: () => Record<string, any>): typeof ServerStorage` — Initializes the storage with a context listener. On the server, this listener should return an object unique to each request.
- `has(key: string): boolean` — Checks for the existence of a key in the current context.
- `remove(key: string): void` — Removes a value by key from the storage.
- `setErrorStatus(hide: boolean): void` — Sets whether to hide context missing errors in the console/error center.
- `reset(): void` — Resets the storage, clearing all stored data and the listener. Useful for performing cleanup.
- `toString(): string` — Generates an HTML `<script type="application/json">` tag containing all data marked for hydration.

## Isolation in SSR

In standard client-side applications, global state belongs to a single user. However, in an SSR environment, one Node.js process handles many concurrent requests simultaneously. To prevent user data from "leaking" between these requests (State Pollution), `ServerStorage` must be correctly isolated.

To achieve this, you must initialize `ServerStorage` with the `init` method. This method accepts a listener function that returns a data object unique to the current request context.

> Important: Correct isolation is critical for security. If not configured, data from one user could be served to another.

### Node.js (AsyncLocalStorage)

The recommended way for Node.js is to use `AsyncLocalStorage` to store context throughout an asynchronous request.

```typescript
import { AsyncLocalStorage } from 'node:async_hooks'
import { ServerStorage } from '@dxtmisha/functional-basic'

const als = new AsyncLocalStorage<Record<string, any>>()

// Initialization
ServerStorage.init(() => als.getStore() || {})

// Usage in server
http.createServer((req, res) => {
  als.run({}, () => {
    // All calls to ServerStorage inside this block will be isolated
    ServerStorage.set('requestId', () => req.id)
  })
})
```

### Nuxt / Nitro

In Nuxt/Nitro, isolation is managed via the `h3` event context using `useEvent()` within a server plugin.

```typescript
// server/plugins/server-storage.ts
import { ServerStorage } from '@dxtmisha/functional-basic'

export default defineNitroPlugin(() => {
  ServerStorage.init(() => {
    try {
      return useEvent().context
    } catch {
      return {}
    }
  })
})
```

## Hydration (Transferring Data to Client)

Hydration is the process of transferring the application state set on the server to the client. This allows the browser to pick up where the server left off, ensuring consistency and preventing redundant data fetching or "flickering" during page load.

### 1. Identify Data for Hydration

When using `set()` or `get()`, pass `true` as the third parameter (`hydration`). Only values marked this way will be transferred to the client.

```typescript
// Set on server
ServerStorage.set('userSettings', () => ({ fontSize: 16 }), true)
```

### 2. Injecting State into HTML

On the server, you must call `ServerStorage.toString()` and insert its result into your page template (usually at the very end of the `<body>` tag, before your application scripts).

This method generates a special script tag:
```html
<script id="__ui:server:storage:id__" type="application/json">
  {"userSettings":{"fontSize":16}}
</script>
```
