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

reactive-event-framework

v1.0.7

Published

[![Sponsor](https://img.shields.io/badge/Sponsor-GitHub%20Sponsors-ff69b4)](https://github.com/sponsors/BeTheCozmo) ![npm version](https://img.shields.io/npm/v/reactive-event-framework) ![downloads](https://img.shields.io/npm/dt/reactive-event-framework)

Readme

Reactive Event Framework

Sponsor npm version downloads

Reactive Event Framework is a Node.js library for building reactive, event-driven system flows with ease and flexibility. It provides tools to manage application lifecycles and simplify system interactions.


Table of Contents

  1. Installation
  2. Usage
  3. Configuration
  4. Examples
  5. API
  6. Contributing
  7. License

Installation

npm install reactive-event-framework
# or
yarn add reactive-event-framework

Usage

import { LifecycleManager } from "reactive-event-framework";

const lifecycleManager = new LifecycleManager();

const {envSystem, logSystem, monitoringSystem} = lifecycleManager.getBaseModules();

lifecycleManager.registerConfigurationStep(() => {
   /* Your configuration step goes here */
});

lifecycleManager.configure();

lifecycleManager.start(async () => {
  logSystem.info("Main", "Application started!");
});

Configuration

This lib requires some environment variables to work:

  • MONITORING_EVENTS_STACK_SIZE
    • Default: 1000

Examples

Example 1: Basic Usage

Here one implementation example of BaseEmitter

//sum.ts
import { BaseEmitter, LogSystem } from "reactive-event-framework";

export type SumConfig = {
  logger: LogSystem;
}
export type SumEvents = {
  sumRequest: number[];
  sumProcessed: number;
  sumError: string;
}

export class SumSystem extends BaseEmitter<SumConfig, SumEvents> {
  name: string = "SumSystem";
  private logger: LogSystem;

  configure(config: SumConfig) {
    this.logger = config.logger;
    this.configureAccepts();
    this.setConfigured();
  }
  configureAccepts() {
    this.accept("sumRequest", this.sum.bind(this));
  }

  sum(numbers: number[]) {
    this.ensureConfigured();
    if(typeof numbers != "object")
      return this.send("sumError", "The argument is not a list of numbers.");
    
    const sum = numbers.reduce((pv, cv) => cv + pv , 0);
    this.logger.info(this.name, "Sum processed");
    this.send("sumProcessed", sum);
  }
}

Example 1.1: Instantiating and executing

import { LifecycleManager } from "reactive-event-framework";
import { SumSystem } from "./sum";

// LifecycleManager will be responsible to all configuration and execution
const lifecycleManager = new LifecycleManager();

// It comes with some base modules that helps you to see what is occurring with your application
const {envSystem, logSystem, monitoringSystem} = lifecycleManager.getBaseModules();

// Here we instantiate our systems
// In this example we have only this one
const sumSystem = new SumSystem();

// Here we use registerConfigurationStep to configure all systems we have
// It have to be called before lifecycleManager.configure() !
lifecycleManager.registerConfigurationStep(() => {
  sumSystem.configure({logger: logSystem});
});

// configure() finishes the lifecycleManager configuration and prepares you to execute everything
lifecycleManager.configure();

/*
export type SumEvents = {
  sumRequest: number[];
  sumProcessed: number;
  sumError: string;
}
*/

// To start your apllication, use lifecycleManager.start() passing an async or not async function
lifecycleManager.start(() => {
  // Here we accept the event "sumProcessed", triggered when the sumSystem finishes the sum
  sumSystem.accept("sumProcessed", (sum) => {
    logSystem.debug(sumSystem.name, `The sum is ${sum}`); // The sum is 10
  });

  // Here we accept the event "sumError", triggered when occurred some error in sum
  sumSystem.accept("sumError", (message) => {
    logSystem.error(sumSystem.name, message);
  });

  // Then we send a request event to SumSystem with the type of key "sumRequest" in SumEvents
  sumSystem.send("sumRequest", [3, 5, 2]);
});

Example 2: Reactive but imperative

You can use waitForEvent to program like imperative programming: To have a type help, you can pass the Events that your system uses in waitForEvent<Events>, here we uses SumEvents.

/*
export type SumEvents = {
  sumRequest: number[];
  sumProcessed: number;
  sumError: string;
}
*/

lifecycleManager.start(async () => {
  const sum = await waitForEvent<SumEvents>(sumSystem, {
    requestEvent: "sumRequest",
    successEvent: "sumProcessed",
    errorEvent: "sumError",
    args: [5, 3, 2]
  }); // 10

  logSystem.debug(sumSystem.name, `The sum is ${sum}`);
});

API

BaseEmitter

Methods

  • configure(config: EmitterConfig): void
    • Used to configure all the dependencies that the implementer needs.
    • Obrigatory.
  • setConfigured(): void
    • Used inside your implementation of configure() to change the state of the class to configured.
    • Without calling this, your systems will fail.
  • ensureConfigured(): void
    • Should be called in the first line of your methods to guarantee that the class is configured.
  • send<K extends keyof T>(event: K, ...args: T[K] | any): boolean
    • If the class with this method is listening the event, then send args as argument.
    • It is like EventEmiiter.emit.
    • Returns true if the event had listeners, false otherwise.
  • accept<K extends keyof T>(event: K, listener: (arg: T[K]) => void): this
    • Register a event to listen the resonse.
    • Will be triggered when the system send a event that you are listening.
  • configureAccepts(): void
    • You need to implement this method;
    • This should be called to configure all the events your system accepts, like in Examples

LifecycleManager

Methods

  • getBaseModules(): object

    • Return the base modules to this library, it is EnvSystem, LogSystem and MonitoringSystem.
  • registerConfigurationStep(step: LifecycleStep) | type LifecycleStep = () => void

    • Register and step of configuration.
    • It should be used to configure your system using system.configure().
    • It should be used before LifecycleManager.configure()
  • configure()

    • Finishes all configuration steps and prepare you to execute your application.
  • start(func: () => void)

    • The callback that you put the code necessary to start your systems.

Contributing

  1. Fork the repository.
  2. Create a branch for your feature or fix: git checkout -b my-feature.
  3. Submit a pull request.

License

This library is licensed under the MIT License. See the LICENSE file for details.