Skip to content

Krivega/events-constructor

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

67 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

events-constructor

npm npm bundle size

Class for emitting events with strong TypeScript support

Install

npm

npm install events-constructor

yarn

yarn add events-constructor

Usage

Basic Events

import Events from 'events-constructor';

const eventNames = ['event1', 'event2'];
const events = new Events(eventNames);

events.on('event1', (data) => {
  console.log('event1 is called with data:', data);
});

events.trigger('event1', 'some data');

Typed Events (TypeScript)

import { TypedEvents } from 'events-constructor';

type EventMap = {
  userLoaded: { id: string; name: string };
  logout: never;
};

const eventNames = ['userLoaded', 'logout'] as const;
const events = new TypedEvents<EventMap>(eventNames);

// TypeScript will enforce correct payload types
events.on('userLoaded', (user) => {
  console.log('User loaded:', user.id, user.name);
});

// ✅ Correct - TypeScript knows the payload type
events.trigger('userLoaded', { id: '1', name: 'John' });

// ❌ TypeScript error - wrong payload type
events.trigger('userLoaded', { wrong: true });

// ✅ Correct - logout event has no payload
events.trigger('logout');

// ❌ TypeScript error - logout doesn't accept payload
events.trigger('logout', { data: 'wrong' });

Race Conditions

Handle multiple events with onRace conditions:

// onceRace - triggers only once, then automatically unsubscribes
events.onceRace(['userLogin', 'userError'], (data, eventName) => {
  console.log(`First event: ${eventName}`, data);
});

// onRace - triggers every time any of the events occur, stays active
const unsubscribe = events.onRace(['userLogin', 'userError'], (data, eventName) => {
  console.log(`Event occurred: ${eventName}`, data);
});

// Manually unsubscribe when no longer needed
unsubscribe();

API

Events (Base Class)

events.on

Add listener to event

events.on('event1', (data) => {
  console.log('event1 is called with data:', data);
});

events.once

Add a listener that will be called only once per event

events.once('event1', (data) => {
  console.log('event1 is called with data:', data);
});

events.off

Remove listener from event

events.off('event1', handler);

events.trigger

Trigger event with data

events.trigger('event1', 'some data');

events.emit

Alias for trigger (Node.js EventEmitter compatibility)

events.emit('event1', 'some data');

events.wait

Wait for an event to be triggered (returns Promise)

const data = await events.wait('event1');
console.log('Event triggered with:', data);

events.onceRace

Listen for the first occurrence of any event from a list (automatically unsubscribes after first trigger)

events.onceRace(['event1', 'event2'], (data, eventName) => {
  console.log(`${eventName} was triggered first with:`, data);
});

events.onRace

Listen for any occurrence of events from a list (stays active until manually unsubscribed)

const unsubscribe = events.onRace(['event1', 'event2'], (data, eventName) => {
  console.log(`${eventName} was triggered with:`, data);
});

// Unsubscribe when no longer needed
unsubscribe();

events.removeEventHandlers

Remove all listeners

events.removeEventHandlers();

events.offAll

Remove all listeners for specific event or all events

// Remove all listeners for specific event
events.offAll('event1');

// Remove all listeners for all events
events.offAll();

events.triggers

Get all triggers

events.triggers;

events.eachTriggers

Iterate through all triggers

events.eachTriggers((trigger, eventName) => {
  console.log(`Trigger for ${eventName}:`, trigger);
});

events.deactivate()

Disable event handlers. The trigger method will not produce any effect.

events.on('event1', (data) => {
  console.log('event1 is called with data:', data); //it's not called
});

events.deactivate();
events.trigger('event1', 'some data');

events.activate()

Enable event handlers.

events.on('event1', (data) => {
  console.log('event1 is called with data:', data);
});

events.deactivate();
events.trigger('event1', 'some data'); // no effect

events.activate();
events.trigger('event1', 'some data'); // handler is called

events.hasHandlers

Check if event has any handlers

if (events.hasHandlers('event1')) {
  console.log('Event has handlers');
}

events.destroy()

Destroy the events instance and clean up all handlers

events.destroy();
// All handlers are removed and triggers are undefined

TypedEvents (TypeScript)

TypedEvents extends the base Events class with strong TypeScript support:

Type Safety

type EventMap = {
  userLoaded: { id: string };
  logout: never;
  dataUpdated: { value: number };
};

const events = new TypedEvents<EventMap>(['userLoaded', 'logout', 'dataUpdated']);

// TypeScript enforces correct payload types
events.trigger('userLoaded', { id: '123' }); // ✅
events.trigger('logout'); // ✅ (no payload for 'never' type)
events.trigger('dataUpdated', { value: 42 }); // ✅

// TypeScript errors for incorrect usage
events.trigger('userLoaded', { wrong: true }); // ❌
events.trigger('logout', { data: 'wrong' }); // ❌

eachTriggersTyped

Strongly typed version of eachTriggers

events.eachTriggersTyped((trigger, eventName) => {
  // trigger is properly typed based on the event
  if (eventName === 'userLoaded') {
    trigger({ id: 'test' }); // TypeScript knows this is correct
  }
});

onRace (TypedEvents)

Strongly typed version of onRace with payload type safety

type EventMap = {
  userLoaded: { id: string; name: string };
  userError: { error: string };
  logout: never;
};

const events = new TypedEvents<EventMap>(['userLoaded', 'userError', 'logout']);

const unsubscribe = events.onRace(['userLoaded', 'userError'], (data, eventName) => {
  // TypeScript knows the exact payload type for each event
  if (eventName === 'userLoaded') {
    console.log('User loaded:', data.id, data.name); // data is { id: string; name: string }
  } else if (eventName === 'userError') {
    console.log('Error:', data.error); // data is { error: string }
  }
});

// Unsubscribe when no longer needed
unsubscribe();

Features

  • Type Safety: Full TypeScript support with compile-time type checking
  • Event Validation: Ensures only predefined events can be used
  • Memory Management: Automatic cleanup of one-time listeners
  • Error Handling: Built-in error handling with debug support
  • Promise Support: Async/await support with wait() method
  • Race Conditions: Handle multiple events with onceRace() and onRace()
  • Lifecycle Management: Activate/deactivate events as needed
  • Performance: Efficient event handling with Set-based listeners

Maintainer

👤 Krivega Dmitriy

Contributing

Contributions, issues and feature requests are welcome!
Feel free to check issues page. You can also take a look at the contributing guide.

📝 License

Copyright © 2025 Krivega Dmitriy.
This project is MIT licensed.

About

Events emitter

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 2

  •  
  •  

Languages