open-index/open-npm huggingface dataset:
npm package: @rupertsworld/emitter
Description: Typed event emitter with disposable subscriptions
Latest version: 0.2.0

# @rupertsworld/emitter

Typed event emitter with disposable subscriptions.

## Install

```bash
npm install @rupertsworld/emitter
```

## Usage

Extend `Emitter` with an event map to get a fully typed emitter. Subscriptions return a `Disposable` — call `dispose()` to unsubscribe.

```typescript
import { Emitter } from "@rupertsworld/emitter";

type Events = {
  message: string;
  error: Error;
  close: undefined;
};

class Chat extends Emitter<Events> {
  send(text: string) {
    this.emit("message", text);
  }

  disconnect() {
    this.emit("close");
  }
}

const chat = new Chat();

const sub = chat.on("message", (text) => {
  console.log("received:", text);
});

chat.send("hello"); // logs "received: hello"
sub.dispose();      // unsubscribed
chat.send("world"); // nothing logged
```

### One-time listeners

```typescript
chat.once("close", () => {
  console.log("disconnected");
});
```

## API

### `Emitter<T>`

Base class. `T` is a `Record<string, any>` mapping event names to payload types. Use `undefined` for events with no payload.

| Method | Description |
| --- | --- |
| `on(type, handler)` | Subscribe to an event. Returns a `Disposable`. |
| `once(type, handler)` | Subscribe to an event once. Returns a `Disposable`. |
| `off(type, handler)` | Unsubscribe a handler. |
| `emit(type, payload)` | Emit an event (protected — only available in subclasses). |

Wildcard `'*'` can be used with `on` and `once` to listen to all events.
npm package: @rupertsworld/event-target
Description: Typed EventTarget with convenient event type creation
Latest version: 0.1.1

# @rupertsworld/event-target

Typed `EventTarget` with convenient event type creation.

## Install

```bash
npm install @rupertsworld/event-target
```

## Usage

```ts
import { EventTarget, defineEvent } from "@rupertsworld/event-target";

// Define events
interface UserEvent extends Event {
  type: "user-login" | "user-logout";
  userId: string;
}
const UserEvent = defineEvent<UserEvent>();

interface CloseEvent extends Event {
  type: "close";
}
const CloseEvent = defineEvent<CloseEvent>();

// Define union
type ServerEvent = UserEvent | CloseEvent;

// Create typed EventTarget
class Server extends EventTarget<ServerEvent> {
  login(userId: string) {
    this.dispatchEvent(
      new UserEvent("user-login", { userId })
    );
  }

  logout(userId: string) {
    this.dispatchEvent(new UserEvent("user-logout", { userId }));
  }

  close() {
    this.dispatchEvent(new CloseEvent("close"));
  }
}

const server = new Server();

// Listeners are fully typed — no annotation needed
server.addEventListener("user-login", (e) => {
  console.log(e.userId);
});

server.addEventListener("close", () => {
  console.log("server closed");
}, { once: true });
```

## API

### `defineEvent<TEvent>()`

Creates a typed event constructor from an interface.

```ts
interface MyEvent extends Event {
  type: "my-event";
  payload: string;
}
const MyEvent = defineEvent<MyEvent>();

new MyEvent("my-event", { payload: "hello" });
new MyEvent("my-event", { payload: "hello", bubbles: true });
```

- Constructor signature: `(type: TEvent["type"], init?: Props & EventInit)` — `init` is optional when no custom props
- `type` argument is constrained to the interface's `type` literal
- `init` accepts custom props plus standard `EventInit` (`bubbles`, `cancelable`, `composed`)
- Throws at runtime if payload tries to overwrite reserved `Event` fields like `target` or `preventDefault`

### `EventTarget<TUnion>`

A typed replacement for native `EventTarget`.

- `addEventListener` and `removeEventListener` are typed by event `type`
- `dispatchEvent` only accepts events from the declared union
- Runtime behavior remains native `EventTarget`

## Environment Support

Works in browser and Node.js 18+ with native `EventTarget` / `Event`.