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

@openally/emitt

v1.0.1

Published

Type-safe EventEmitter for Node.js and Browser

Readme

Emitter<Events> is a drop-in-shaped EventEmitter with no dependency on Node's events module or the DOM EventTarget: it runs unmodified in Node.js and the browser, and every method is typed against your own Events map instead of any[].

Requirements

Getting Started

This package is available in the Node Package Repository and can be easily installed with npm or yarn.

$ npm i @openally/emitt
# or
$ yarn add @openally/emitt

Usage example

import { Emitter } from "@openally/emitt";

interface MyEvents {
  connect: (host: string) => void;
  [key: symbol]: (payload: unknown) => void;
}

const emitter = new Emitter<MyEvents>();

emitter.on("connect", (host) => {
  console.log(`connected to ${host}`);
});

emitter.emit("connect", "localhost");

Events defaults to an untyped string | symbol event map when omitted:

type EventMap = Record<string | symbol, (...args: any[]) => void>;

Table of contents

Emitter API

Constructor

class Emitter<Events extends EventMap = Record<string | symbol, (...args: any[]) => void>> {
  constructor();
}

Both string and symbol keys are supported for event names.

const emitter = new Emitter<MyEvents>();

addListener, on

addListener<E extends keyof Events>(event: E, listener: Events[E]): this;
on<E extends keyof Events>(event: E, listener: Events[E]): this;

Register a listener for event. on is an alias of addListener. Warns via console.warn once the listener count for that event exceeds getMaxListeners() (see getMaxListeners, setMaxListeners).

emitter.on("connect", (host) => console.log(host));

once

once<E extends keyof Events>(event: E, listener: Events[E]): this;

Register a listener that is automatically removed after firing a single time.

emitter.once("connect", (host) => console.log(host));

emitter.emit("connect", "localhost"); // logs "localhost"
emitter.emit("connect", "localhost"); // listener already removed, does nothing

prependListener

prependListener<E extends keyof Events>(event: E, listener: Events[E]): this;

Same as on, but inserts the listener at the beginning of the list instead of the end.

emitter.on("bar", () => order.push("second"));
emitter.prependListener("bar", () => order.push("first"));

emitter.emit("bar"); // order === ["first", "second"]

prependOnceListener

prependOnceListener<E extends keyof Events>(event: E, listener: Events[E]): this;

Combines prependListener and once: runs first, and only once.

off, removeListener

off<E extends keyof Events>(event: E, listener: Events[E]): this;
removeListener<E extends keyof Events>(event: E, listener: Events[E]): this;

Remove a previously registered listener. off is an alias of removeListener. Works with the original function reference even when it was registered via once/prependOnceListener.

function listener(host: string) {
  console.log(host);
}

emitter.on("connect", listener);
emitter.off("connect", listener);

removeAllListeners

removeAllListeners<E extends keyof Events>(event?: E): this;

Remove every listener for event, or every listener for every event when called without an argument.

emitter.removeAllListeners("connect");
emitter.removeAllListeners(); // clears everything

emit

emit<E extends keyof Events>(event: E, ...args: Parameters<Events[E]>): boolean;

Synchronously call every listener registered for event with the given arguments, in registration order. Returns true if there was at least one listener, false otherwise.

emitter.emit("connect", "localhost"); // true
emitter.emit("unknown-event"); // false, no listeners

eventNames

eventNames(): (keyof Events | string | symbol)[];

List the event names (string and symbol) that currently have at least one listener.

emitter.eventNames(); // ["connect", Symbol(baz)]

rawListeners

rawListeners<E extends keyof Events>(event: E): Events[E][];

Same as listeners, but returns the internal wrapper function for listeners registered via once/prependOnceListener instead of the original function reference.

listeners

listeners<E extends keyof Events>(event: E): Events[E][];

Return a copy of the listeners registered for event, unwrapping once listeners back to the original function passed in.

emitter.once("connect", listener);
emitter.listeners("connect"); // [listener]

listenerCount

listenerCount<E extends keyof Events>(event: E): number;

Number of listeners currently registered for event.

getMaxListeners, setMaxListeners

getMaxListeners(): number;
setMaxListeners(maxListeners: number): this;

Get/set the listener-count threshold that triggers the memory-leak warning (default 10, matching Node's EventEmitter). Pass 0 to disable the warning.

emitter.setMaxListeners(0); // disable the warning

Helpers

Standalone helpers inspired by Node's events module, typed against a given Emitter<Events> instance (resolved argument/tuple types instead of Node's any[]).

import { Emitter, once, on, addAbortListener } from "@openally/emitt";

once (helper)

function once<Events extends EventMap, E extends keyof Events>(
  emitter: Emitter<Events>,
  event: E,
  options?: AbortOptions
): Promise<Parameters<Events[E]>>;

Resolve with the typed argument tuple of the next matching emit().

const [host] = await once(emitter, "connect");

Accepts an { signal } option (AbortOptions) to cancel waiting via an AbortSignal; rejects with the signal's reason (or a generic abort Error) when aborted, and always removes its internal listener on cleanup/rejection.

on (helper)

function on<Events extends EventMap, E extends keyof Events>(
  emitter: Emitter<Events>,
  event: E,
  options?: AbortOptions
): AsyncGenerator<Parameters<Events[E]>, void, void>;

Async-iterate every occurrence of event, queuing emissions that happen faster than they are consumed.

for await (const [host] of on(emitter, "connect")) {
  console.log(host);
}

Same { signal } option as once; throws with the signal's reason (or a generic abort Error) when aborted, and always removes its internal listener when the loop exits.

addAbortListener

function addAbortListener(signal: AbortSignal, listener: (event: Event) => void): Disposable;

Independent of Emitter — listens once for signal's abort event (firing immediately via queueMicrotask if already aborted) and returns a Disposable, so it works with using.

function example(signal: AbortSignal) {
  using _ = addAbortListener(signal, () => {
    // cleanup
  });
}

License

MIT