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

<Meta title='@dxtmisha/ru/functional/# Управляемые синглтоны'/>

# Управляемые синглтоны (executeUse)

Функция **executeUse** — это продвинутая фабрика для создания управляемых синглтонов в экосистеме **Vue 3**. Она решает проблему инициализации и переиспользования реактивных состояний, глобальных сервисов (например, мета-тегов) или компонентов, предоставляя гибкий контроль над контекстом выполнения (глобальный, локальный или через `provide/inject`).

## Режимы работы

**executeUse** поддерживает три режима инициализации (enum `ExecuteUseType`), каждый из которых предназначен для своих архитектурных задач:

1. **global** (`executeUseGlobal`) — единственный экземпляр на всё приложение. Удобно для создания сервисов, которые живут вне конкретного компонента.
2. **provide** (`executeUseProvide`) — разделение состояния через дерево компонентов (`provide`/`inject`). Гарантирует, что дочерние компоненты получат один и тот же экземпляр от ближайшего родителя.
3. **local** (`executeUseLocal`) — единственный экземпляр в замыкании, изолированный внутри собственного `effectScope`. 

### Различия между `global` и `local`

Главное архитектурное отличие между режимами `global` и `local` заключается во **времени инициализации** (когда именно создается экземпляр):

1. **`global` (Отложенная, но массовая инициализация):**
   - Все коллбеки, обернутые в `global`, складываются в глобальный реестр. Они **сразу же выполняются все вместе**, когда в точке входа приложения (например, в `main.ts` или при SSR) вызывается функция `executeUseGlobalInit()`. 
   - **Сценарий использования:** Критически важные сервисы (Настройки, Мета-теги, Переводы, Пользовательские сессии), которые должны быть полностью готовы к работе *до* первой отрисовки компонента или должны централизованно пересоздаваться при сбросе приложения.

2. **`local` (Ленивая инициализация):**
   - Экземпляр создается **только в момент самого первого вызова** этой функции внутри компонента или другого сервиса. При этом, так как инициализация обернута в глобальный `effectScope`, этот синглтон, так же как и глобальный, будет "жить вечно" и не уничтожится при демонтаже компонента, из которого был вызван.
   - **Сценарий использования:** Тяжелые или специфические сервисы (например, сложная фильтрация, вебсокет-чат на отдельной странице, аналитика), которые:
     - Могут вообще не понадобиться во время текущей сессии.
     - Должны инициализироваться ровно тогда, когда пользователь заходит в нужный раздел.

## Использование (на примере глобального сервиса)

Самый частый сценарий — создание глобального хранилища или сервиса (например, для работы с мета-тегами).

```typescript
import { ref } from 'vue'
import { executeUseGlobal } from '@dxtmisha/functional'

// 1. Определение синглтона
const item = executeUseGlobal(() => {
  const title = ref('Мой заголовок')
  
  const updateTitle = (newTitle: string) => {
    title.value = newTitle
  }

  return { title, updateTitle }
})

// 2. Экспорт composable-функции (по конвенции Vue)
export const useMeta = () => item()
```

Внутри любого компонента Vue:

```typescript
import { useMeta } from './useMeta'

const { title, updateTitle } = useMeta() // title будет общим для всех вызовов
```

## Использование Provide / Inject

Если нужно, чтобы состояние жило только в рамках конкретного дерева компонентов (например, форма и её внутренние поля), используется `executeUseProvide`.

```typescript
import { executeUseProvide } from '@dxtmisha/functional'

const useFormState = executeUseProvide((initialData: any) => {
  // ... логика инициализации реактивного состояния
  return { /* ... */ }
})
```

При первом вызове `useFormState(data)` в компоненте-родителе состояние проинициализируется и будет передано вниз (через `provide`). Любой дочерний компонент, вызвав `useFormState()`, получит этот же экземпляр через `inject`.

## Управление экземпляром

Функции `executeUse` оборачивают результат вашей фабрики и добавляют специальные методы для управления жизненным циклом (зависит от режима).

### Метод init()

Метод `init()` — это просто заглушка, которая возвращает сам объект. Она нужна исключительно для того, чтобы в коде компонента можно было явно выделить место первоначального вызова.

```typescript
const service = useMeta()

// Явное определение точки входа
service.init()
```

### Сброс и переинициализация

```typescript
const service = useMeta()

// Сброс закешированного экземпляра (доступно для local и global).
// При следующем вызове composable будет создан новый экземпляр.
if (service.destroyExecute) {
  service.destroyExecute()
}
```

Кроме того, для глобальных синглтонов доступна функция `executeUseGlobalInit()`, которая принудительно переинициализирует все зарегистрированные глобальные `callback` методы (может быть полезно при SSR инициализации или полном сбросе приложения).

Если в вашем приложении подключен плагин `dxtFunctionalPlugin`, вызывать `executeUseGlobalInit()` вручную при старте приложения **не нужно** — плагин делает это автоматически под капотом.
