npm package: @maxax/x-plugins-mitt
Description: A lightweight event bus wrapper based on mitt for Maxax projects
Latest version: 1.0.1

# @maxax/x-plugins-mitt

A lightweight event bus wrapper based on [mitt](https://github.com/developit/mitt) for Maxax projects. This package provides a powerful event bus system designed for micro-frontend architectures, supporting communication between master and slave applications.

[![npm version](https://img.shields.io/npm/v/@maxax/x-plugins-mitt.svg)](https://www.npmjs.com/package/@maxax/x-plugins-mitt)
[![License](https://img.shields.io/npm/l/@maxax/x-plugins-mitt.svg)](LICENSE)

## Features

- **Lightweight**: Built on top of mitt, minimal footprint
- **Type-safe**: Full TypeScript support with generic types
- **Micro-frontend Ready**: Built-in support for master-slave application communication
- **Flexible**: Multiple ways to get event bus instances (singleton, factory)
- **Powerful**: Supports wildcards, once events, and comprehensive event management

## Installation

```bash
npm install @maxax/x-plugins-mitt mitt
# or
pnpm add @maxax/x-plugins-mitt mitt
# or
yarn add @maxax/x-plugins-mitt mitt
```

## Quick Start

### Basic Usage

```typescript
import { getEventBus, createEventBus } from '@maxax/x-plugins-mitt'

// Option 1: Use singleton instance
const eventBus = getEventBus()

// Option 2: Create a new instance
const eventBus = createEventBus()

// Define event types
interface MyEvents {
  userLoggedIn: { userId: string; username: string }
  notification: { message: string; type: 'info' | 'warning' | 'error' }
  [key: string]: any
}

// Subscribe to events
eventBus.on('userLoggedIn', (data) => {
  console.log(`User ${data.username} logged in with ID: ${data.userId}`)
})

// Publish events
eventBus.emit('userLoggedIn', { userId: '123', username: 'john' })

// Unsubscribe
const unsubscribe = eventBus.on('notification', (data) => {
  console.log('Notification:', data.message)
})
unsubscribe()
```

### Manager Usage (Micro-frontend)

For micro-frontend architectures, use the `MaxEventBusManager` to coordinate events between master and slave applications:

```typescript
import { getMaxEventBusManager } from '@maxax/x-plugins-mitt'

// Get manager instance
const manager = getMaxEventBusManager()

// ============ Master Application ============

// Listen for events from any slave application
manager.onAnySlave('dataUpdated', (data, appName) => {
  console.log(`Received data update from ${appName}:`, data)
})

// Broadcast to all applications
manager.broadcast('globalNotification', {
  message: 'System will restart in 5 minutes',
  severity: 'warning'
})

// ============ Slave Application ============

// Send event to master
manager.toMaster('slaveReady', { appName: 'dashboard', timestamp: Date.now() })

// Send event to specific slave
manager.toSlave('orderApp', 'newOrder', { orderId: 'ORD-001', amount: 99.99 })

// Listen to master events
manager.onMaster('configChanged', (data) => {
  console.log('New configuration:', data)
})
```

## API Reference

### MaxEventBus

The core event bus class.

#### Constructor

```typescript
constructor()
```

Creates a new event bus instance.

#### Methods

##### emit

```typescript
emit<Key extends keyof MaxEvents>(type: Key, data: MaxEvents[Key]): void
```

Publishes an event with data.

```typescript
eventBus.emit('userCreated', { userId: '123', email: 'user@example.com' })
```

##### emitWithout

```typescript
emitWithout<Key extends keyof MaxEvents>(type: ...): void
```

Publishes an event without data.

##### on

```typescript
on<Key extends keyof MaxEvents>(event: Key, callback: Handler<MaxEvents[Key]>): () => void
```

Subscribes to an event. Returns an unsubscribe function.

```typescript
const unsubscribe = eventBus.on('message', (data) => {
  console.log('Received message:', data)
})

// Later, unsubscribe
unsubscribe()
```

##### once

```typescript
once<Key extends keyof MaxEvents>(event: Key, callback: Handler<MaxEvents[Key]>): () => void
```

Subscribes to an event that only fires once.

```typescript
eventBus.once('initComplete', () => {
  console.log('Initialization complete!')
})
```

##### onBoth

```typescript
onBoth(handler: WildcardHandler<MaxEvents>): () => void
```

Subscribes to all events (wildcard).

```typescript
eventBus.onBoth((event, data) => {
  console.log(`Event "${event}" fired with data:`, data)
})
```

##### off

```typescript
off<Key extends keyof MaxEvents>(event: Key, callback?: Handler<MaxEvents[Key]>): void
```

Unsubscribes from an event. If no callback provided, removes all listeners for that event.

##### clear

```typescript
clear(): void
```

Removes all event listeners.

### Factory Functions

```typescript
// Get or create singleton instance
function getEventBus(): MaxEventBus

// Create a new instance
function createEventBus(): MaxEventBus

// Reset singleton instance
function resetEventBus(): void
```

### MaxEventBusManager

Event bus manager for micro-frontend architectures.

#### Methods

##### getMasterBus

```typescript
getMasterBus(): MaxEventBus
```

Returns the master application event bus.

##### registerSlaveBus

```typescript
registerSlaveBus(appName: string, slaveEventBus: MaxEventBus): void
```

Registers a slave application event bus.

##### unregisterSlaveBus

```typescript
unregisterSlaveBus(appName: string): void
```

Unregisters a slave application.

##### broadcast

```typescript
broadcast<K extends string>(event: K, data?: any): void
```

Broadcasts an event to all applications (master + all slaves).

##### toMaster

```typescript
toMaster<K extends string>(event: K, data?: any): void
```

Sends an event to the master application.

##### toSlave

```typescript
toSlave<K extends string>(appName: string, event: K, data?: any): void
```

Sends an event to a specific slave application.

##### toSlaves

```typescript
toSlaves<K extends string>(appNames: string[], event: K, data?: any): void
```

Sends an event to multiple slave applications.

##### onMaster

```typescript
onMaster<K extends string>(event: K, callback: (data: any) => void): () => void
```

Listens to events from the master application.

##### onSlave

```typescript
onSlave<K extends string>(appName: string, event: K, callback: (data: any) => void): () => void
```

Listens to events from a specific slave application.

##### onAnySlave

```typescript
onAnySlave<K extends string>(event: K, callback: (data: any, appName: string) => void): () => void
```

Listens to events from any slave application. Callback receives the data and app name.

##### getRegisteredApps

```typescript
getRegisteredApps(): string[]
```

Returns a list of registered slave application names.

##### destroy

```typescript
destroy(): void
```

Destroys the manager and all associated event buses.

## Advanced Examples

### Complete Micro-frontend Setup

```typescript
// master.ts - Main application
import { getMaxEventBusManager, createEventBus } from '@maxax/x-plugins-mitt'

const masterBus = getMaxEventBusManager()

// Listen for all slave events
masterBus.onAnySlave('*', (event, data, appName) => {
  console.log(`[${appName}] ${event}:`, data)
})

// Send configuration to all apps
masterBus.broadcast('configUpdate', {
  theme: 'dark',
  language: 'en',
  apiUrl: 'https://api.example.com'
})

// Handle slave registration
masterBus.onSlave('reactApp', 'register', (data) => {
  console.log('React app registered:', data)
})

// -------------------------------------------------

// slave-react.ts - React micro-frontend
import { createEventBus, getMaxEventBusManager } from '@maxax/x-plugins-mitt'

const slaveBus = createEventBus()
const manager = getMaxEventBusManager()

// Register with master
manager.registerSlaveBus('reactApp', slaveBus)

// Notify master we're ready
manager.toMaster('register', {
  name: 'React Dashboard',
  version: '1.0.0',
  components: ['Chart', 'Table', 'Form']
})

// Listen for config changes
manager.onMaster('configUpdate', (config) => {
  applyConfig(config)
})

// Broadcast events to other apps
slaveBus.emit('dataLoaded', { count: 42, timestamp: Date.now() })

// -------------------------------------------------

// slave-vue.ts - Vue micro-frontend
import { createEventBus, getMaxEventBusManager } from '@maxax/x-plugins-mitt'

const slaveBus = createEventBus()
const manager = getMaxEventBusManager()

// Register with master
manager.registerSlaveBus('vueApp', slaveBus)

// Listen to all events from React app
manager.onSlave('reactApp', 'dataLoaded', (data) => {
  console.log('React app loaded data:', data)
})

// Send events to master
manager.toMaster('vueReady', { name: 'Vue Admin', status: 'active' })
```

### Using with React

```typescript
// useEventBus.ts
import { useEffect, useCallback } from 'react'
import { getEventBus } from '@maxax/x-plugins-mitt'

export function useEventBus<EventMap extends Record<string, any>>() {
  const eventBus = getEventBus()

  const subscribe = useCallback(<K extends keyof EventMap>(
    event: K,
    callback: (data: EventMap[K]) => void
  ) => {
    return eventBus.on(event, callback)
  }, [eventBus])

  const publish = useCallback(<K extends keyof EventMap>(
    event: K,
    data: EventMap[K]
  ) => {
    eventBus.emit(event, data)
  }, [eventBus])

  return { subscribe, publish }
}

// Component.tsx
import { useEventBus } from './useEventBus'

interface MyEvents {
  counterUpdate: { count: number }
  reset: void
}

function Counter() {
  const { subscribe, publish } = useEventBus<MyEvents>()
  const [count, setCount] = useState(0)

  useEffect(() => {
    return subscribe('counterUpdate', ({ count }) => {
      setCount(count)
    })
  }, [subscribe])

  const increment = () => {
    publish('counterUpdate', { count: count + 1 })
  }

  return <button onClick={increment}>{count}</button>
}
```

### Using with Vue 3 Composable

```typescript
// composables/useEventBus.ts
import { onUnmounted } from 'vue'
import { getEventBus } from '@maxax/x-plugins-mitt'

export function useEventBus<EventMap extends Record<string, any>>() {
  const eventBus = getEventBus()

  const on = <K extends keyof EventMap>(
    event: K,
    callback: (data: EventMap[K]) => void
  ) => {
    const unsubscribe = eventBus.on(event, callback)
    onUnmounted(unsubscribe)
    return unsubscribe
  }

  const emit = <K extends keyof EventMap>(
    event: K,
    data: EventMap[K]
  ) => {
    eventBus.emit(event, data)
  }

  return { on, emit }
}
```

## TypeScript Support

This library is written in TypeScript and provides full type safety:

```typescript
import { createEventBus } from '@maxax/x-plugins-mitt'

// Define your events
interface AppEvents {
  userLogin: { userId: string; username: string }
  userLogout: void
  notification: { message: string; type: string }
  [key: string]: any
}

// Create typed event bus
const eventBus = createEventBus<AppEvents>()

// Fully typed events
eventBus.on('userLogin', (data) => {
  // data is inferred as { userId: string; username: string }
  console.log(data.userId)
})

eventBus.emit('userLogin', { userId: '123', username: 'john' })
```

## Performance Tips

1. **Unsubscribe when done**: Always unsubscribe from events when components are destroyed to prevent memory leaks.

2. **Use `once` for one-time events**: For initialization logic that should run only once, use `once()` instead of `on()`.

3. **Manager for cross-app communication**: Use `MaxEventBusManager` for micro-frontend scenarios instead of creating multiple independent event buses.

## Contributing

Contributions are welcome! Please read our contributing guidelines before submitting PRs.

## License

MIT License - see [LICENSE](LICENSE) for details.