npm package: @mirawision/wings
Description: Advanced state management library for TypeScript with deep merge, request lifecycle tracking, event-driven updates, and local storage caching.
Author: Yelysei Lukin
Latest version: 1.0.0

# @mirawision/wings

Advanced state management library for TypeScript with deep merge, request lifecycle tracking, event-driven updates, and local storage caching. Built on top of the observer pattern, Wings provides a sophisticated yet simple way to manage complex application state.

## Features

- **Deep Merge State Updates**: Support for nested structures and complex state updates
- **Request Lifecycle Management**: Automatic tracking of API requests (loading, success, error, finished)
- **Event-Driven Updates**: Named events with conditions for fine-grained state change handling
- **Local Storage Caching**: Selective data persistence with version control
- **Type Safety**: Full TypeScript support with generics
- **Observer Pattern Integration**: Reactive state updates
- **Concurrent Request Tracking**: Manage multiple simultaneous operations
- **Cache Versioning**: Automatic cache migration and invalidation

## Installation

```bash
npm install @mirawision/wings
```

or 

```bash
yarn add @mirawision/wings
```

**Note**: Wings depends on `@mirawision/observer`. It will be installed automatically.

## Usage

### Basic Example

```typescript
import { Wing } from '@mirawision/wings';

interface UserState {
  users: User[];
  settings: Settings;
  requests?: RequestsState;
}

class UserService extends Wing<UserState> {
  constructor() {
    super({
      users: [],
      settings: {},
      requests: {}
    });
    
    // Define named events
    this.defineEvent('userAdded', (prev, curr) => 
      curr.users.length > prev.users.length
    );
    
    this.defineEvent('settingsChanged', (prev, curr) => 
      JSON.stringify(prev.settings) !== JSON.stringify(curr.settings)
    );
  }

  async fetchUsers() {
    return this.executeRequest('fetchUsers', 
      () => api.getUsers(),
      (users) => this.setState({ users }),
      (error) => console.error(error)
    );
  }

  updateSettings(newSettings: Partial<Settings>) {
    this.setState({ settings: { ...this.getState().settings, ...newSettings } });
  }
}
```

### Request Lifecycle Management

```typescript
class DataService extends Wing<DataState> {
  async fetchData() {
    // Automatically manages loading, success, error states
    return this.executeRequest('fetchData', 
      () => api.getData(),
      (data) => this.setState({ data }),
      (error) => console.error('Failed to fetch data:', error)
    );
  }

  // Check request states
  isDataLoading() {
    return this.isRequestLoading('fetchData');
  }

  getDataError() {
    return this.getRequestError('fetchData');
  }

  isDataSuccess() {
    return this.isRequestSuccess('fetchData');
  }
}
```

### Event-Driven State Management

```typescript
class NotificationService extends Wing<NotificationState> {
  constructor() {
    super({ notifications: [], requests: {} });
    
    // Define events with conditions
    this.defineEvent('newNotification', (prev, curr) => 
      curr.notifications.length > prev.notifications.length
    );
    
    this.defineEvent('notificationRead', (prev, curr) => {
      const prevUnread = prev.notifications.filter(n => !n.read).length;
      const currUnread = curr.notifications.filter(n => !n.read).length;
      return currUnread < prevUnread;
    });
  }

  // Subscribe to events
  setupEventListeners() {
    this.subscribeToEvent('newNotification', (prev, curr) => {
      console.log('New notification received!');
      this.showNotificationBadge();
    });

    this.subscribeToEvent('notificationRead', (prev, curr) => {
      console.log('Notification marked as read');
      this.updateUnreadCount();
    });
  }

  addNotification(notification: Notification) {
    this.setState({
      notifications: [...this.getState().notifications, notification]
    });
  }
}
```

### Deep Merge State Updates

```typescript
class ComplexStateService extends Wing<ComplexState> {
  // Deep nested state updates
  setLoadingState() {
    this.setState({
      requests: {
        fetchNotebooks: {
          loading: true,
          success: false,
          error: null,
          finished: false
        }
      }
    });
  }

  updateUserProfile(userId: string, updates: Partial<UserProfile>) {
    this.setState({
      users: {
        [userId]: {
          ...this.getState().users[userId],
          ...updates
        }
      }
    });
  }
}
```

### Local Storage Caching

```typescript
class CachedService extends Wing<CachedState> {
  constructor() {
    super({
      users: [],
      settings: {},
      requests: {}
    }, {
      enabled: true,
      cacheKeys: ['users', 'settings'], // Only cache users and settings
      storageKey: 'user-service-cache',
      version: '1.0.0'
    });
  }

  // Cache will be automatically saved and loaded
  // Clear cache when needed
  clearCache() {
    this.clearCache();
  }

  // Check cache status
  isCacheEnabled() {
    return this.isCacheEnabled();
  }
}
```

### React Integration

```typescript
import React, { useEffect, useState } from 'react';
import { Wing } from '@mirawision/wings';

interface AppState {
  theme: 'light' | 'dark';
  user: User | null;
  requests?: RequestsState;
}

class AppService extends Wing<AppState> {
  constructor() {
    super({
      theme: 'light',
      user: null,
      requests: {}
    });
  }

  toggleTheme() {
    const currentTheme = this.getState().theme;
    this.setState({ theme: currentTheme === 'light' ? 'dark' : 'light' });
  }
}

// React Hook
function useWing<T>(wing: Wing<T>): T {
  const [state, setState] = useState<T>(wing.getState());

  useEffect(() => {
    const unsubscribe = wing.subscribe((message) => {
      setState(message.payload.currentState);
    });

    return unsubscribe;
  }, [wing]);

  return state;
}

// Usage in component
function App() {
  const appService = new AppService();
  const state = useWing(appService);

  return (
    <div>
      <button onClick={() => appService.toggleTheme()}>
        Current theme: {state.theme}
      </button>
    </div>
  );
}
```

## API Reference

### Wing<T extends BaseState>

Advanced state management class that extends the Observer pattern.

#### Constructor

```typescript
constructor(initialState: T, cacheConfig?: CacheConfig)
```

#### Methods

- `setState(newState: T | Partial<T>): void`
  - Updates state with deep merge support
  - Triggers event notifications
  - Persists to cache if enabled

- `getState(): T`
  - Returns current state

- `defineEvent(eventName: string, condition: EventCondition<T>): void`
  - Defines a named event with condition

- `subscribeToEvent(eventName: string, callback: (prev: T, curr: T) => void): () => void`
  - Subscribes to a named event
  - Returns unsubscribe function

- `executeRequest<TResult>(requestName: string, apiCall: () => Promise<TResult>, onSuccess?: (result: TResult) => void, onError?: (error: string) => void): Promise<TResult | null>`
  - Executes API request with automatic state management

- `isRequestLoading(requestName: string): boolean`
  - Checks if request is loading

- `isRequestSuccess(requestName: string): boolean`
  - Checks if request succeeded

- `getRequestError(requestName: string): string | null`
  - Gets request error message

- `clearCache(): void`
  - Clears cached data

#### Type Definitions

```typescript
interface BaseState {
  requests?: RequestsState;
}

interface RequestState {
  loading: boolean;
  success: boolean;
  error: string | null;
  finished: boolean;
}

interface CacheConfig {
  enabled: boolean;
  cacheKeys: (keyof any)[];
  storageKey?: string;
  version?: string;
}
```

## Contributing

Contributions are always welcome! Feel free to open issues or submit pull requests.

## License

This project is licensed under the MIT License.