npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@ayu-sh-kr/dota-event

v0.0.5

Published

dota-event is a library that provides api for event-driven programming in dota ecosystem.

Downloads

600

Readme

dota-event

Lightweight application event primitives used across the monorepo.

This package provides a small publish/subscribe event system and a decorator-based way to bind instance methods as event handlers. It's designed to be simple and easy to use in both apps and libraries inside the workspace.

Features

  • A small ApplicationEvent type and handler callback signature.
  • DefaultApplicationEventManager — a Map/Set-backed manager for event handler storage.
  • DefaultApplicationEventBus — a singleton event bus (lazy) used to register, unregister and emit events.
  • DefaultApplicationEventPublisher / DefaultApplicationEventListener — lightweight facades for publishing and listening.
  • @OnEvent decorator and helpers to bind/unbind decorated instance methods to a listener.

Installation

In this monorepo you can import the package locally. For external usage (when published) replace the import path with the published package name.

Using pnpm (from repo root):

pnpm add @ayu-sh-kr/dota-event

Or (monorepo/local) import directly from the package path in your TypeScript project.

Note: the examples below use the package-style import path @ayu-sh-kr/dota-event. Replace it with your local/monorepo path if necessary.

Requirements

  • TypeScript
  • reflect-metadata (used by the @OnEvent decorator)
  • If using decorators, enable experimentalDecorators and emitDecoratorMetadata in your tsconfig.json.

Install reflect-metadata if you plan to use the decorator helpers:

pnpm add reflect-metadata

and import it once (for example in your app entry):

import 'reflect-metadata';

Quick API summary

Exports you will typically use:

  • Types

    • ApplicationEvent — { name: string; data?: any }
    • ApplicationEventCallback — (event: ApplicationEvent) => void
  • Manager

    • DefaultApplicationEventManager — add/remove/resolve/clear
  • Bus

    • DefaultApplicationEventBus — singleton via DefaultApplicationEventBus.getInstance()
      • Note: the bus class implements its on, off, and emit methods as async (Promise<void>), so you can await those calls. (The public Types interface is minimal; prefer checking the class behavior in code.)
  • Facades

    • DefaultApplicationEventPublisherpublish(event: ApplicationEvent): void and publishAsync(event): Promise<void>
    • DefaultApplicationEventListeneron(event, callback) and off(event, callback) (delegates to the bus)
  • Decorator & helpers (from on-event.decorator.ts)

    • OnEvent(name: string) — method decorator
    • getOnEventMetadata(targetOrInstance) — read metadata
    • bindInstanceEventHandlers(instance, listener) — register decorated methods on a listener
    • unbindInstanceEventHandlers(instance, listener) — unregister decorated methods from a listener

DefaultClassApplicationEventBindManager

DefaultClassApplicationEventBindManager is the package's class-level helper for managing decorated instance method bindings on a provided ApplicationEventListener. It:

  • Scans a target instance's @OnEvent metadata and binds each method to the listener.
  • Keeps an internal store of bound callbacks organized by event name and method key.
  • Prevents duplicate registrations: calling bind() multiple times will not re-register the same method for the same event because the manager checks the internal store before adding a listener.
  • Ensures precise unbinding: unbind() uses the stored bound callback references to remove the exact functions from the listener and cleans up empty entries.

This makes it safe for services or components that might initialize or call bind() repeatedly (for example during hot-reload or multiple init attempts) without producing duplicate listener invocations.

Quickstart examples

All snippets are TypeScript and assume the following import path — replace with your project-specific path if needed:

import { DefaultApplicationEventBus, DefaultApplicationEventPublisher, DefaultApplicationEventListener, OnEvent, bindInstanceEventHandlers, unbindInstanceEventHandlers, ApplicationEvent } from '@ayu-sh-kr/dota-event';

1) Basic singleton bus (on / emit / off)

// get the shared bus
const bus = DefaultApplicationEventBus.getInstance();

// register a handler (bus.on is async)
await bus.on('user:created', (event) => {
  console.log('user created:', event.data);
});

// emit an event (emit is async)
await bus.emit({ name: 'user:created', data: { id: 1, name: 'alice' } });

// remove all handlers for an event
await bus.off('user:created', null);

2) Using the publisher / publishAsync

const bus = DefaultApplicationEventBus.getInstance();
const publisher = new DefaultApplicationEventPublisher(bus);

// publish synchronously (note: the implementation delegates to the bus emit but the method itself is synchronous)
publisher.publish({ name: 'order:placed', data: { id: 42 } });

// publish asynchronously and await handlers
await publisher.publishAsync({ name: 'order:placed', data: { id: 43 } });

Note: publish calls the bus emit but does not await it; use publishAsync when you need to wait for handlers.

3) Decorator-based handlers (class methods)

import 'reflect-metadata'; // ensure this is imported somewhere in your app

class MyService {
  @OnEvent('payment:received')
  onPayment(event: ApplicationEvent) {
    console.log('payment received', event.data);
  }
}

const instance = new MyService();
const bus = DefaultApplicationEventBus.getInstance();
const listener = new DefaultApplicationEventListener(bus);

// register all decorated handlers from instance onto the listener
await bindInstanceEventHandlers(instance, listener);

// publish — handlers bound above will run
await bus.emit({ name: 'payment:received', data: { amount: 100 } });

// when shutting down or removing the instance
await unbindInstanceEventHandlers(instance, listener);

4) Advanced: multiple handlers and clearing

const bus = DefaultApplicationEventBus.getInstance();

await bus.on('metrics:tick', () => console.log('handler A'));
await bus.on('metrics:tick', () => console.log('handler B'));

await bus.emit({ name: 'metrics:tick' });
// -> handler A
// -> handler B

// Remove all handlers for the event
await bus.off('metrics:tick', null);