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

<Meta title='@dxtmisha/en/functional/Classes/DesignAsyncAbstract - Base Async Design Class'/>

# DesignAsyncAbstract Class

An asynchronous abstract base class for managing constructor properties and state changes. It extends `DesignAbstract` to support asynchronous initialization of events, making it ideal for designs that require data fetching or async computations.

## Key Features

- **Asynchronous Initialization** — supports `Promise` based event initialization via `initEvent`.
- **Property Management** — inherited structured handling of input data (`props`) and event storage (`event`).
- **Async Workflow** — ensures that callbacks are triggered only after asynchronous state preparation is complete.

## Initialization

`DesignAsyncAbstract` is an abstract class and cannot be initialized directly. It is intended to be extended by other classes that must implement the `initEvent` method for asynchronous data preparation.

### Generic Constraints

The class uses two types of generics to ensure strict typing:
- `T extends Record<string, any>` — Type for input properties (`props`). Defines the data structure passed to the constructor.
- `C extends Record<string, any>` — Type for internal state or cache (`event`). Defines the data structure available in callbacks after asynchronous initialization.

**Constructor Parameters:**
- `props: T` — an object with the initial data.
- `callback?: (event: C) => void` — a callback function that will be called after each successful update (including asynchronous ones).
- `changed?: string[]` — optional list of keys from `props` to watch. If not provided, all keys in `props` are tracked.

**Internal Properties:**
- `protected readonly event: C` — the state object. This is what you should populate with data in `initEvent`. It will be passed to the `callback`.

**Required Method to Implement:**
- `protected abstract initEvent(): Promise<void>` — an asynchronous method called whenever tracked properties change. This is where `this.event` should be prepared.

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

// 1. Defining interfaces
interface MyProps { userId: number }
interface MyState { userName: string; avatar: string }

// 2. Implementing a concrete class
class UserDesign extends DesignAsyncAbstract<MyProps, MyState> {
  protected async initEvent(): Promise<void> {
    const response = await fetch(`https://api.example.com/users/${this.props.userId}`)
    const data = await response.json()
    
    this.event.userName = data.name
    this.event.avatar = data.image
  }
}

// 3. Usage
const user = new UserDesign(
  { userId: 1 }, 
  (state) => {
    console.log('User data loaded:', state.userName)
  },
  ['userId'] // Only track changes to userId
)
```

## Data Management Methods

### `make`

Initiates the asynchronous callback update process. It calls `makeCallback` (without waiting for its completion) and returns the instance for chaining.

**Parameters:**
- `compelled?: boolean` — if `true`, forces the data update regardless of whether changes were detected.

**Returns:** `this`

### `makeCallback`

The primary asynchronous execution logic for updating the state. It waits for `initEvent` to complete before triggering callbacks and updating the change tracker.

**Parameters:**
- `compelled?: boolean` — forces data update.

**Returns:** `Promise<void>`

## Protected Methods (for Subclasses)

### `is`

Checks for the existence of a key in the `props` object.

**Parameters:**
- `name: keyof T` — property name.

**Returns:** `boolean`

### `isChanged`

Checks if the value of a specified property has changed compared to its previous state. Useful inside `initEvent` to optimize requests (only perform an action if a specific ID has changed).

**Parameters:**
- `name: keyof C` — property name in the state.
- `nameProp?: keyof T | (keyof T)[]` — property name or list of property names in `props` that the change is based on. Defaults to `name`.

**Returns:** `boolean`

### `makeCallbackItem`

Executes the callback function passed to the constructor.

**Returns:** `void`

### `initEvent` (abstract)

An asynchronous method that must be implemented in the subclass. It populates `this.event` based on `this.props`.

**Returns:** `Promise<void>`

