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

<Meta title='@dxtmisha/functional/ru/Execution Utils'/>

# Утилиты выполнения

Набор функций для универсального выполнения синхронных и асинхронных операций.

## `executeFunction`

Выполняет функцию и возвращает её результат, или возвращает входные данные, если это не функция.

**Параметры:**
- `callback: T | FunctionArgs<any, T>` — функция или любое значение

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

executeFunction(() => 'Hello World') // 'Hello World'
executeFunction('Static value') // 'Static value'
executeFunction(() => 42 + 8) // 50
executeFunction({ data: 'object' }) // { data: 'object' }
```

## `executePromise`

Выполняет асинхронную функцию или возвращает значение, автоматически обрабатывая Promise.

**Параметры:**
- `callback: (() => Promise<T>) | (() => T) | T` — асинхронная функция, синхронная функция или значение

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

await executePromise(async () => fetch('/api').then(r => r.json())) // Promise result
await executePromise(() => 'Sync result') // 'Sync result'
await executePromise('Static value') // 'Static value'
```

## `executeUse`

Возвращает функцию для кеширования и переиспользования результатов инициализации в Vue компонентах. Поддерживает различные режимы работы: локальное кеширование, глобальное состояние, наследование через provide/inject и автоматическую очистку при размонтировании.

**Параметры:**
- `callback: (...args: O) => R` — функция инициализации, результат которой будет кеширован
- `unmounted: boolean` — удалять ли данные из кеша при размонтировании компонента (по умолчанию `true`)
- `isGlobal: boolean` — является ли объект глобальным для всего приложения (по умолчанию `false`)
- `isProvide: boolean` — использовать ли provide/inject для наследования в дочерних компонентах (по умолчанию `true`)

**Возвращает:**
Функцию, которая при первом вызове выполняет callback и кеширует результат, а при последующих вызовах возвращает закешированное значение.

```javascript
import { executeUse } from '@dxtmisha/functional'
import { reactive, ref } from 'vue'

// Простое кеширование состояния
const useCounter = executeUse(() => {
  return reactive({
    count: 0,
    increment() { this.count++ },
    decrement() { this.count-- }
  })
})

// В компоненте
const counter = useCounter() // создается один раз
counter.increment()

// Кеширование с параметрами
const useStore = executeUse((initialData) => {
  return reactive({
    data: initialData,
    loading: false,
    error: null,
    async fetch() {
      this.loading = true
      try {
        this.data = await api.getData()
      } catch (err) {
        this.error = err
      } finally {
        this.loading = false
      }
    }
  })
})

// Глобальное состояние (сохраняется между компонентами)
const useGlobalTheme = executeUse(
  () => reactive({ theme: 'dark', language: 'ru' }),
  false,  // не удалять при размонтировании
  true,   // глобальное состояние
  false   // без provide/inject
)

// Локальное состояние с наследованием
const useFormState = executeUse(
  (formId) => reactive({
    formId,
    values: {},
    errors: {},
    isValid: false,
    setValue(key, value) {
      this.values[key] = value
      this.validate()
    },
    validate() {
      // логика валидации
      this.isValid = Object.keys(this.errors).length === 0
    }
  }),
  true,   // очищать при размонтировании
  false,  // не глобальное
  true    // с наследованием через provide/inject
)

// Кеширование API клиента
const useApiClient = executeUse(() => {
  const baseURL = process.env.VUE_APP_API_URL

  return {
    async get(endpoint) {
      const response = await fetch(`${baseURL}${endpoint}`)
      return response.json()
    },
    async post(endpoint, data) {
      const response = await fetch(`${baseURL}${endpoint}`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(data)
      })
      return response.json()
    }
  }
})

// Использование в компонентах
export default {
  setup() {
    // Все вызовы вернут один и тот же объект
    const counter = useCounter()
    const store = useStore({ items: [] })
    const theme = useGlobalTheme()
    const api = useApiClient()

    return { counter, store, theme, api }
  }
}
```
