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

@sprs/emitter

v0.0.2

Published

Simple event emitter

Readme

Emitter

This package provides a simple, slightly opinionated event emitter with a reduced inferface resembling Node.js's EventEmitter.

Listener registration is idempotent. Multiple registrations of the same function will not result in multiple invocations of that function.

Use .on/.off/.emit to register/remove listeners and emit events.

Use .xform to produce a XForm instance for a single event (see the next section for details on XForm).

Use the optional events parameter to Emitters constructor to specify known events. The emitter is still allowed to emit any event (no error will be thrown if you emit an event which is not declared in events). Specifying events pre-allocates containers for listeners, attaches known property names to an events property on the Emitter instance, and provides type annotations for known event names in instance methods.

The emitter factory wraps the Emitter class's constructor, and provides a way of creating an Emitter which does not require the new keyword.

Example 1: The basics


import { Emitter } from '@sprs/emitter';

const e = new Emitter(['a', 'b', 'c']);

const logIt = value => console.log('a emitted ', value);
e.on('a', logIt);

e.emit('a', 123);
// -> Message logged: 'a emitted 123'

e.off('a', logIt);
e.emit('a', 456);
// -> No message logged

Example 2: Emitter subclass


import { Emitter } from '@sprs/emitter';

class RequestEmitter extends Emitter {
  constructor(url, options) {
    super(['init', 'response', 'error'])
    this.url = url;
    this.options = options;
  }

  init() {
    this.emit('init', {
      url: this.url,
      options: this.options,
    });

    fetch(this.url, this.options)
      .then(response => {
        this.emit('response', response);
      })
      .catch(error => {
        this.emit('error', error);
      });
  }
}

const google = new RequestEmitter('https://www.google.com', { method: 'GET' });

google.on('init', (startValues) => console.log('Request started: ', startValues));
google.on('response', (response) => console.log('Request succeeded: ', response));
google.on('error', (error) => console.log('Request failed: ', error));

google.init();

Example 3: Transforming events

Following is a more complicated example using the fluent xform API to transform event payloads asynchronously. Most use cases shouldn't require this; if you can, just stick to plain old Emitters.


import { Emitter } from '@sprs/emitter';

class RequestEmitter extends Emitter {
  ...
}

const ddg = new RequestEmitter('https://www.duckduckgo.com', { method: 'GET' });
ddg
  .xform({ response: data => data.text() })
  .xform({ response: text => text.slice(0, 100) })
  .on('response', sliced => console.log('First 100 characters of the Duck Duck Go home page HTML...', sliced))

ddg.init();

XForm

The XForm class serves as an event transformer. It is constructed from an existing Emitter and a set of functions to transform event payloads with, and it has the same on/off methods as an Emitter, but it has no emit method.

XForm can be used to transform both Emitters from this package, and EventTargets from the standard browser API.

If a transformer function returns a Promise, XForm will wait for that Promise to resolve, and then will emit the resolved value, rather than immediately emitting the Promise itself.

The third (optional) parameter to the XForm constructor provides options. The multiReturn option requires a transformer function to return an array of values. This allows an XForm to transform event payloads from Emitters which emit multiple values to their events.

The xform factory function wraps the XForm class's constructor, and provides a method of creating an XForm that does not require the new keyword.


import { Emitter, XForm } from '@sprs/emitter';

const e1 = new Emitter();
const x1 = new XForm(e1, { myEvent: payload => payload.myProperty * 5 });
x1.on('myEvent', console.log);
e1.emit('myEvent', { myProperty: 6 });
// -> '30'

const e2 = new EventTarget();
const x2 = new XForm(e2, { myEvent: event => event.detail.myProperty * 5 });
x2.on('myEvent', console.log);
e2.dispatchEvent(new CustomEvent('myEvent', { detail: { myProperty: 6 } }));
// -> '30'

const emitsMultiple = new Emitter();
const x3 = new XForm(
  emitsMultiple,
  { myEvent: (a, b, c) => [a, b * 2, c * 3] },
  { multiReturn: true },
);
x3.on('myEvent', console.log);
emitsMultiple.emit('myEvent', 2, 4, 6);
// -> 2, 8, 18
//    Note that this is NOT [2, 8, 18]