# @mr-samani/event-bus

A lightweight, dependency-free Event Bus for JavaScript and TypeScript.  
Broadcast and listen to events anywhere in your application — no hard coupling, no complexity.

---

## 🚀 Installation

```bash
npm install @mr-samani/event-bus
````

or using Yarn:

```bash
yarn add @mr-samani/event-bus
```

---

## 🧠 Features

✅ Zero dependencies

✅ Ultra-lightweight (< 1 KB)

✅ Unlimited listeners per event

✅ Global usage via `app.event` (no imports required)

✅ Fully compatible with TypeScript, JavaScript, Angular, React, Vue, Node.js, Electron


---

## 🔧 Usage

## Method 1️⃣: Global Usage (Recommended)

To enable global usage without any imports, simply import the auto initializer once at your app entry:

### React / Vite / Webpack

`main.tsx` or `index.tsx`:

```ts
import '@mr-samani/event-bus/auto';

import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';

ReactDOM.createRoot(document.getElementById('root')!).render(<App />);
```

### Angular

`main.ts`:

```ts
import '@mr-samani/event-bus/auto';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app/app.module';

platformBrowserDynamic().bootstrapModule(AppModule);
```

### Vue 3

`main.ts`:

```ts
import '@mr-samani/event-bus/auto';
import { createApp } from 'vue';
import App from './App.vue';

createApp(App).mount('#app');
```

Now you can use the Event Bus anywhere **without importing**:

```ts
app.event.on('user:login', (user) => {
  console.log('User logged in:', user);
});

app.event.trigger('user:login', { id: 1, name: 'Samani' });
```

---

## Method 2️⃣: Direct Import

If you prefer explicit usage:

```ts
import eventBus from '@mr-samani/event-bus';

eventBus.on('user:login', (user) => {
  console.log('User logged in:', user);
});

eventBus.trigger('user:login', { id: 1, name: 'Samani' });
```

---

## 🎯 Practical Examples

### ⚛️ React Example (TypeScript)

`main.tsx`:

```ts
import '@mr-samani/event-bus/auto';
```

`LoginButton.tsx`:

```tsx
export default function LoginButton() {
  const handleLogin = () => {
    app.event.trigger('user:login', { id: 1, name: 'Ali' });
  };

  return <button onClick={handleLogin}>Login</button>;
}
```

`Header.tsx`:

```tsx
import { useEffect, useState } from 'react';

export default function Header() {
  const [user, setUser] = useState<any>(null);

  useEffect(() => {
    app.event.on('user:login', setUser);
    return () => app.event.off('user:login');
  }, []);

  return <div>{user ? `Welcome ${user.name}` : 'Guest'}</div>;
}
```

---

### ⚡ Angular Example

`main.ts`:

```ts
import '@mr-samani/event-bus/auto';
```

`login.component.ts`:

```ts
export class LoginComponent {
  login() {
    app.event.trigger('user:login', { id: 1, name: 'Mohammad' });
  }
}
```

`header.component.ts`:

```ts
export class HeaderComponent implements OnInit, OnDestroy {
  ngOnInit() {
    app.event.on('user:login', this.handleLogin.bind(this));
  }

  ngOnDestroy() {
    app.event.off('user:login');
  }

  handleLogin(user: any) {
    console.log('User logged in:', user);
  }
}
```

---

### 🖖 Vue 3 Example

```vue
<script setup lang="ts">
import { onMounted, onBeforeUnmount } from 'vue';

const handleTheme = (theme: string) => {
  console.log('Theme changed:', theme);
};

onMounted(() => {
  app.event.on('theme:change', handleTheme);
});

onBeforeUnmount(() => {
  app.event.off('theme:change');
});

const changeTheme = () => {
  app.event.trigger('theme:change', 'dark');
};
</script>
```

---

## 🧪 API Reference

| Method                   | Description                               |
| ------------------------ | ----------------------------------------- |
| `on(name, callback)`     | Registers a listener for an event         |
| `off(name)`              | Removes all listeners for an event        |
| `trigger(name, ...args)` | Triggers an event with optional arguments |

---

## 🧙 TypeScript Support

For full IntelliSense, update your `tsconfig.json`:

```json
{
  "compilerOptions": {
    "types": ["@mr-samani/event-bus"]
  }
}
```

Or create `global.d.ts`:

```ts
/// <reference types="@mr-samani/event-bus" />
```

---

## 🤓 Use Cases

* Global loading state management
* Open/close modals
* Shared form submission
* Global notifications
* Micro-frontend communication
* Theme management (dark/light)
* Data synchronization between components

---

## 🔥 Important Notes

1. **Import the auto initializer once** at your root file:
   `import '@mr-samani/event-bus/auto'`
2. **Always cleanup listeners** (`useEffect` cleanup / `ngOnDestroy`)
3. Use event naming convention `module:action` (e.g., `user:login`)
4. Add TypeScript types to avoid warnings

---

## 🐛 Fixing "app is not defined"

If you encounter `app is not defined`:

1. Ensure you imported `@mr-samani/event-bus/auto` in the entry point
2. Add `"types"` in your tsconfig
3. Check your bundler includes the auto entry file

---

## ✍️ Author

Created with ❤️ by [Mohammadreza Samani](https://github.com/mr-samani)

---

## 🪪 License

**ISC License** — do whatever you want.

---

## 📝 Changelog

### v3.0.0

* Added `/auto` entry point for global usage
* Improved TypeScript declarations
* Updated documentation with real examples
* Fixed `app is not defined`

### v2.0.0

* First release