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

@onoxm/event

v0.4.4

Published

Event library by Typescript

Downloads

883

Readme

@onoxm/event

A lightweight, type-safe event emitter library for TypeScript.

Features

  • Type-safe: Full TypeScript generics support, event names and callback parameter types are automatically inferred.
  • Lightweight: Built with private fields (#), no extra runtime overhead.
  • Flexible API: Supports both factory function and class usage.
  • Global Singleton: Optional singleton mode for cross-module shared event bus.
  • Auto Unsubscribe: on / once return an unsubscribe function for easy cleanup.

Installation

npm install @onoxm/event
# or
pnpm add @onoxm/event
# or
yarn add @onoxm/event

Peer dependency: @onoxm/utils (required when using global singleton mode).

Usage

1. Factory Function (Recommended)

Use an event map to get full type inference:

import { createEventEmitter } from '@onoxm/event'

const event = createEventEmitter({
  LOGIN: {} as [username: string, password: string],
  LOGOUT: {} as [reason: string],
  CONSOLE: {} as [message: string, level: number],
})

// Emit - parameter types are inferred
event.emit('LOGIN', 'admin', '123456')

// Subscribe - callback parameters are inferred
const off = event.on('LOGIN', (username, password) => {
  console.log(`${username} logged in`)
})

// Unsubscribe
off()

2. Event Name Array (Weakly Typed)

For quick setup or when types are not a concern:

import { createEventEmitter } from '@onoxm/event'

const event = createEventEmitter(['API:LOGIN', 'API:CONSOLE'] as const)

event.on('API:LOGIN', (...args) => {
  console.log('login event', args)
})

event.emit('API:LOGIN', 'admin', '123456')

3. Global Singleton Mode

Pass isGlobal: true to share a single instance across modules:

// moduleA.ts
import { createEventEmitter } from '@onoxm/event'

export const event = createEventEmitter({
  DATA_UPDATED: {} as [payload: unknown],
}, true) // <-- global singleton

// moduleB.ts (different file)
import { createEventEmitter } from '@onoxm/event'

const event = createEventEmitter({
  DATA_UPDATED: {} as [payload: unknown],
}, true)

// Both `event` references point to the same instance,
// so events emitted in moduleA are received in moduleB.
event.on('DATA_UPDATED', (payload) => {
  console.log('received', payload)
})

API

createEventEmitter(eventMap, isGlobal?)

Creates an event emitter instance with full type inference.

  • eventMap: Record<string, unknown[]> — an object whose keys are event names and values are tuple types describing the callback parameters (use {} as [Tuple] syntax).
  • isGlobal: boolean (optional, default false) — when true, returns a singleton instance shared across all calls with the same configuration.

Returns an emitter instance with the methods below.

createEventEmitter(eventNames, isGlobal?)

Overload that accepts an array of event names (weakly typed, callback params are any[]).

  • eventNames: string[] | readonly string[]
  • isGlobal: boolean (optional, default false)

Returns an emitter instance with the methods below.

Emitter Instance Methods

The instance returned by createEventEmitter exposes the following methods:

emit(eventName, ...args)

Emits an event, calling all subscribed callbacks in subscription order.

  • Throws if eventName was not pre-registered.

on(eventName, callback)

Subscribes to an event.

  • Returns an unsubscribe function: calling it removes the callback (equivalent to off).

once(eventName, callback)

Subscribes to an event, but the callback is automatically removed after the first invocation.

  • Returns an unsubscribe function.

off(eventName, callback)

Removes a specific callback from an event.

clear(eventName?)

  • If eventName is provided, removes all callbacks for that event.
  • If eventName is omitted, removes all callbacks for all events.

Type Safety

The event-map form provides complete type inference for both emit and on:

const event = createEventEmitter({
  LOGIN: {} as [username: string, password: string],
})

// ✅ OK
event.emit('LOGIN', 'admin', '123456')

// ❌ Type Error: too few arguments
event.emit('LOGIN', 'admin')

// ❌ Type Error: wrong type
event.emit('LOGIN', 'admin', 123)

// ✅ Callback params are inferred as (username: string, password: string)
event.on('LOGIN', (username, password) => {
  // ...
})

License

MIT © ONO