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

asljs-eventful

v0.4.9

Published

Lightweight event helper adding on/off/emit to any object.

Readme

eventful

Part of Alexandrite Software Library – a set of high‑quality, performant JavaScript libraries for everyday use.

Lightweight event helper adding on/off/emit to any object.

Installation

npm install asljs-eventful

NPM Package: asljs-eventful

Public Exports

The package-root export surface includes:

  • eventful
  • EventfulBase
  • isEventfulLike
  • asEventfulLike
  • ListenerError
  • TypeScript types including EventfulLike, EventName, EventMap, Eventful, EventfulFactory, EventfulOptions, Listener, and TraceFn

Usage

Special Behavior

eventful is not only an object enhancer. The package-level eventful function also acts as a global emitter for lifecycle and error events.

If you change lifecycle, tracing, or listener-error behavior, then preserve that package-level emitter contract.

Stable Behavior

These behaviors are part of the supported contract, not just current examples:

  • eventful adds on, once, off, emit, emitAsync, and has
  • eventful also acts as a package-level global emitter
  • strict mode propagates listener errors
  • non-strict mode isolates listener failures through the configured error path
  • ListenerError protects against recursive failures in global error handling

Preferred Patterns

  • If you are enhancing a plain object, then use eventful(target).
  • If you are enhancing an existing class instance and cannot change inheritance, then call eventful(this) in the constructor.
  • If you control a new class hierarchy and event support is part of the type design, then extend EventfulBase.
  • If you are writing TypeScript and want typed listener signatures, then declare an event map and use the exported Eventful<...> types.

Basic (JavaScript)

Adding events to an object, add listeners, and emit events:

import { eventful } from 'asljs-eventful';

const obj = eventful({ name: 'Alice' });

obj.on('greet',
  msg => console.log(`${msg}, ${obj.name}!`));
 
// writes "Hello, Alice!" to console
obj.emit('greet', 'Hello');

Basic (TypeScript)

import { eventful, type Eventful } from 'asljs-eventful';

type Events =
  { greet: [msg: string] };

const obj: { name: string } & Eventful<Events> =
  eventful({ name: 'Alice' });

obj.on('greet',
  msg => console.log(`${msg}, ${obj.name}!`));

// writes "Hello, Alice!" to console
obj.emit('greet', 'Hello');

Inheritance (JavaScript)

Adding events to a class via inheritance:

import { EventfulBase } from 'asljs-eventful';

class MyClass extends EventfulBase {
  constructor(name) {
    super();

    this.name = name;
  }

  greet() {
    this.emit(
      'greet',
      `Hello, ${this.name}`);
  }
}

Inheritance (TypeScript)

import { EventfulBase } from 'asljs-eventful';

class MyClass extends EventfulBase {
  name: string;

  constructor(name: string) {
    super();

    this.name = name;
  }

  greet() {
    this.emit(
      'greet',
      `Hello, ${this.name}`);
  }
}

Construction (JavaScript)

Adding events to an existing class during construction:

import { eventful } from 'asljs-eventful';

export class MyClass {
  constructor(name) {
    eventful(this);

    this.name = name;
  }

  greet() {
    this.emit(
      'greet',
      `Hello, ${this.name}`);
  }
}

Construction (TypeScript)

import { eventful, type Eventful } from 'asljs-eventful';

type MyClassEvents =
  { greet: [message: string]; };

export class MyClass implements Eventful<MyClassEvents> {
  name: string;

  declare on: Eventful<MyClassEvents>['on'];
  declare once: Eventful<MyClassEvents>['once'];
  declare off: Eventful<MyClassEvents>['off'];
  declare emit: Eventful<MyClassEvents>['emit'];
  declare emitAsync: Eventful<MyClassEvents>['emitAsync'];
  declare has: Eventful<MyClassEvents>['has'];

  constructor(name: string) {
    eventful(this);

    this.name = name;
  }

  greet() {
    this.emit(
      'greet',
      `Hello, ${this.name}`);
  }
}

Advanced Options

Trace event invocations to console:

const obj =
  eventful(
    { },
    { trace:
        (action, payload) => {
          console.log(
            `Action: ${action}`,
            payload);
        } });

// Tracing (event, payload):
// - 'new' on creation, { object }
// - 'on' when subscribing, { object, event, listener }
// - 'off' when unsubscribing, { object, event, listener }
// - 'emit' for sync emit, { object, event, args, listeners }
// - 'emitAsync' for async emit, { object, event, args, listeners }

Custom error handler for listener errors:

const obj =
  eventful(
    { },
    { error:
        ({ error, object, event, listener }) => {
          console.error(
            `Error in listener for event "${event}"`,
            error);
        } });

Strict mode to propagate listener errors:

const obj =
  eventful(
    { },
    { strict: true });

Global Events

eventful is also a global emitter. When you create an enhanced object via eventful(target, options), its lifecycle and actions are traced via the per-instance trace hook and also emitted as global events on eventful.

const offNew =
  eventful.on(
    'new',
    ({ object }) => {
      console.log('created', object);
    });

const offError =
  eventful.on(
    'error',
    ({ error, object, event }) => {
      console.error('listener error', event, error);
    });

// Later
offNew();
offError();

Note: if a global eventful.on('error', ...) listener throws, eventful throws a ListenerError (an Error subclass with fields { error, object, event, listener }) to avoid an infinite error loop.

API

eventful([target], [options])

Wraps the target object with event capabilities. If no target is provided, a new empty object is created.

  • target (Object): The object to be enhanced with event capabilities.
  • options (Object): Configuration options.
    • error (Function | null): Optional error hook called with { error, object, event, listener }.
    • trace (Function | null): Optional trace hook called with (action, payload).
    • strict (Boolean): If true, propagates listener errors; otherwise they are isolated. Defaults to false.

on(event, listener)

Registers a listener for the specified event.

  • event (String | Symbol): The event name.
  • listener (Function): The callback function to be invoked when the event is emitted.

Returns a function to remove the listener.

once(event, listener)

Registers a one-time listener for the specified event. The listener is removed after its first invocation.

  • event (String | Symbol): The event name.
  • listener (Function): The callback function to be invoked when the event is emitted.

Returns a function to remove the listener.

Example:

obj.once(
  'tick',
  n => console.log('first only', n));

obj.emit('tick', 1); // logs
obj.emit('tick', 2); // no-op; already unsubscribed

off(event, listener)

Removes a listener for the specified event.

  • event (String | Symbol): The event name.
  • listener (Function): The callback function to be removed.

emit(event, ...args)

Emits the specified event, invoking all registered listeners with the provided arguments.

  • event (String | Symbol): The event name.
  • ...args (Any): Arguments to pass to the listeners.

emitAsync(event, ...args)

Emits the specified event asynchronously, running listeners in parallel. In non-strict mode, all listeners run and rejections are isolated; in strict mode, the first rejection causes the returned promise to reject.

  • event (String | Symbol): The event name.
  • ...args (Any): Arguments to pass to the listeners.

Returns a Promise that resolves when all listeners have been invoked.

has(event)

Checks if there are any listeners registered for the specified event.

  • event (String | Symbol): The event name.

Returns true if there are listeners, otherwise false.

Example:

const off =
  obj.on('e', () => {});

console.log(obj.has('e')); // true
off();
console.log(obj.has('e')); // false

License

MIT License. See LICENSE for details.

Related Packages

  • If you need property change tracking, see asljs-observable.
  • If you need DOM binding built on observable state, see asljs-data-binding.