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

state-manager-utility

v3.0.2

Published

Global state management library

Readme

State Manager Utility

npm version License: MIT

A tiny yet powerful state management library for front-end projects. Follows pub-sub architecture to maintain and broadcast state. Can be used as a lightweight alternative to Redux.

Features

Lightweight - Minimal footprint, maximum power
🔄 Pub-Sub Pattern - Simple event-based state management
💾 Persistence Support - Optional state persistence across sessions
📘 TypeScript Support - Full type definitions included
🎯 No Dependencies - Zero runtime dependencies (peer dependency optional for persistence)

Installation

npm install state-manager-utility --save

Quick Start

JavaScript

import { EmitEvent, SubscribeToEvent, UnsubscribeEvent } from 'state-manager-utility';

// Emit an event with data
EmitEvent({ 
  event: 'user:login', 
  data: { userId: 123, name: 'John' } 
});

// ⚠️ IMPORTANT: Always define callback as a named function (not inline)
// This ensures you can properly unsubscribe using the same reference
function handleUserLogin(data) {
  console.log('User logged in:', data);
}

// Subscribe to events
SubscribeToEvent({
  event: 'user:login',
  callback: handleUserLogin  // Named function reference
});

// Cleanup: Unsubscribe when no longer needed
UnsubscribeEvent({
  event: 'user:login',
  callback: handleUserLogin  // Same reference used for unsubscribing
});

TypeScript

import { EmitEvent, SubscribeToEvent, UnsubscribeEvent } from 'state-manager-utility';

interface User {
  userId: number;
  name: string;
}

// Emit typed events
EmitEvent({ 
  event: 'user:login', 
  data: { userId: 123, name: 'John' } as User
});

// Define callback as a named function for proper unsubscription
function handleUserLogin(data: User, meta?: { event: string, extraParams: any }) {
  console.log('User logged in:', data.name);
  console.log('Event name:', meta?.event);
}

// Subscribe with typed callback
SubscribeToEvent({
  event: 'user:login',
  callback: handleUserLogin  // Named function reference
});

// Cleanup: Unsubscribe when no longer needed
UnsubscribeEvent({
  event: 'user:login',
  callback: handleUserLogin  // Same reference
});

API Reference

EmitEvent

Broadcasts an event with data. The event can be stored for future subscribers or transmitted temporarily.

EmitEvent({
  event: string,
  data: any,
  isMemoryStore?: boolean,
  isTemp?: boolean,
  dontTransmit?: boolean
}): void

Parameters:

  • event (string) - Unique identifier for the event
  • data (any) - Data to be broadcasted
  • isMemoryStore (boolean, optional) - If true, persists event across sessions (requires storage utility initialization)
  • isTemp (boolean, optional) - If true, event is broadcasted only once without storing
  • dontTransmit (boolean, optional) - If true, stores the event but doesn't broadcast immediately

Example:

EmitEvent({ 
  event: 'cart:updated', 
  data: { items: 3, total: 99.99 },
  isMemoryStore: true  // Persist across sessions
});

SubscribeToEvent

Subscribes to an event and receives callbacks when the event is emitted.

SubscribeToEvent({
  event: string,
  callback: (payload?: any, meta?: { event: string, extraParams: any }) => void,
  extraParams?: any,
  isMemoryStore?: boolean,
  isTemp?: boolean,
  skipOldEvent?: boolean
}): void

Parameters:

  • event (string) - Event identifier to subscribe to
  • callback (function) - Function called when event is emitted. Receives (data, { event, extraParams })
  • extraParams (any, optional) - Additional parameters passed back in callback
  • isMemoryStore (boolean, optional) - Subscribe to persisted events
  • isTemp (boolean, optional) - Unsubscribe automatically after first callback
  • skipOldEvent (boolean, optional) - If true, doesn't trigger callback for existing event data

Example:

// Define callback as named function
function handleCartUpdate(data, meta) {
  console.log(`Cart has ${data.items} items`);
  console.log('Extra params:', meta.extraParams);
}

SubscribeToEvent({
  event: 'cart:updated',
  callback: handleCartUpdate,
  extraParams: { source: 'header-component' }
});

// Cleanup when done
UnsubscribeEvent({
  event: 'cart:updated',
  callback: handleCartUpdate
});

UnsubscribeEvent

Removes an event listener.

UnsubscribeEvent({
  event: string,
  callback: (payload?: any) => void,
  isMemoryStore?: boolean
}): void

Parameters:

  • event (string) - Event identifier
  • callback (function) - Same callback function reference used in SubscribeToEvent
  • isMemoryStore (boolean, optional) - Target persisted event store

Example:

// ⚠️ CRITICAL: Use the same function reference for both subscribe and unsubscribe
function handleCartUpdate(data) {
  console.log('Cart updated:', data);
}

// Subscribe
SubscribeToEvent({ 
  event: 'cart:updated', 
  callback: handleCartUpdate  // Store this reference
});

// Later, unsubscribe using the SAME reference
UnsubscribeEvent({ 
  event: 'cart:updated', 
  callback: handleCartUpdate  // Must be the same function
});

// ❌ WRONG: This will NOT work (inline functions create new references)
// SubscribeToEvent({ 
//   event: 'cart:updated', 
//   callback: (data) => console.log(data)  // New reference
// });
// UnsubscribeEvent({ 
//   event: 'cart:updated', 
//   callback: (data) => console.log(data)  // Different reference - won't unsubscribe!
// });

GetBroadcasterData

Retrieves stored event data without subscribing.

GetBroadcasterData({
  event: string,
  isMemoryStore?: boolean
}): { success: true, response: any } | { success: false }

Parameters:

  • event (string) - Event identifier
  • isMemoryStore (boolean, optional) - Retrieve from persisted store

Returns:

  • Object with success: true and response (event data) if found
  • Object with success: false if event not found

Example:

const result = GetBroadcasterData({ event: 'user:login' });
if (result.success) {
  console.log('User data:', result.response);
}

DeleteEvent

Removes an event from the store. All listeners will stop receiving updates.

DeleteEvent({
  event: string,
  isMemoryStore?: boolean
}): void

Parameters:

  • event (string) - Event identifier to remove
  • isMemoryStore (boolean, optional) - Delete from persisted store

Example:

DeleteEvent({ event: 'temp:session', isMemoryStore: false });

HasEventSubscribed

Checks if anyone is currently subscribed to an event.

HasEventSubscribed({
  event: string,
  isMemoryStore?: boolean
}): boolean

Parameters:

  • event (string) - Event identifier
  • isMemoryStore (boolean, optional) - Check persisted store

Returns:

  • true if there are active subscribers
  • false if no subscribers

Example:

if (HasEventSubscribed({ event: 'notifications:new' })) {
  console.log('Someone is listening to notifications');
}

InitialiseStateManager

Initialize the library with storage utilities for persistence support. Only required if you want events to persist across sessions.

InitialiseStateManager({
  StorageUtils: {
    SetItem: (key: string, value: any) => void,
    GetItem: (key: string) => any
  }
}): void

Parameters:

  • StorageUtils (object) - Object with SetItem and GetItem functions from storage-utility

Example:

import { InitialiseStateManager } from 'state-manager-utility';
import { SetItem, GetItem } from 'storage-utility';

// Initialize with storage utilities
InitialiseStateManager({ 
  StorageUtils: { SetItem, GetItem } 
});

// Now you can use isMemoryStore option
EmitEvent({ 
  event: 'user:preferences', 
  data: { theme: 'dark' },
  isMemoryStore: true  // Will persist across sessions
});

Best Practices

⚠️ Always Use Named Functions for Callbacks

CRITICAL: When subscribing to events, always define callbacks as named functions (not inline arrow functions) if you plan to unsubscribe later. This is because UnsubscribeEvent requires the exact same function reference to properly remove the listener.

// ✅ CORRECT: Named function allows proper unsubscription
function handleEvent(data) {
  console.log(data);
}

SubscribeToEvent({ event: 'myEvent', callback: handleEvent });
UnsubscribeEvent({ event: 'myEvent', callback: handleEvent });  // Works!

// ❌ WRONG: Inline functions create different references
SubscribeToEvent({ 
  event: 'myEvent', 
  callback: (data) => console.log(data)  // Reference #1
});

UnsubscribeEvent({ 
  event: 'myEvent', 
  callback: (data) => console.log(data)  // Reference #2 - Different! Won't work!
});

Why this matters:

  • JavaScript compares function references, not function content
  • Each inline function creates a new reference, even if the code is identical
  • Without matching references, UnsubscribeEvent cannot find and remove the listener
  • This leads to memory leaks and unexpected behavior

Exception: You can use inline functions for temporary subscriptions (isTemp: true) since they auto-cleanup.

Usage Patterns

React Component Example

import React, { useEffect, useState } from 'react';
import { EmitEvent, SubscribeToEvent, UnsubscribeEvent } from 'state-manager-utility';

function CartComponent() {
  const [cartCount, setCartCount] = useState(0);

  useEffect(() => {
    const handleCartUpdate = (data) => {
      setCartCount(data.items);
    };

    // Subscribe to cart updates
    SubscribeToEvent({
      event: 'cart:updated',
      callback: handleCartUpdate
    });

    // Cleanup on unmount
    return () => {
      UnsubscribeEvent({
        event: 'cart:updated',
        callback: handleCartUpdate
      });
    };
  }, []);

  const addToCart = () => {
    EmitEvent({
      event: 'cart:updated',
      data: { items: cartCount + 1 }
    });
  };

  return (
    <div>
      <p>Cart Items: {cartCount}</p>
      <button onClick={addToCart}>Add to Cart</button>
    </div>
  );
}

Temporary Events (One-time Subscription)

// Note: For temp subscriptions, inline functions are acceptable since no manual cleanup needed
// The subscription auto-removes after first callback
SubscribeToEvent({
  event: 'modal:opened',
  callback: (data) => {
    console.log('Modal opened once:', data);
  },
  isTemp: true  // Auto-unsubscribes after first callback
});

// Or with named function if you need to cancel before it fires
function handleModalOpen(data) {
  console.log('Modal opened:', data);
}

SubscribeToEvent({
  event: 'modal:opened',
  callback: handleModalOpen,
  isTemp: true
});

// You can still manually unsubscribe before it fires if needed
UnsubscribeEvent({
  event: 'modal:opened',
  callback: handleModalOpen
});

Skip Old Events

// Define callback as named function
function handleLiveUpdate(data) {
  console.log('New update:', data);
}

// Don't trigger callback with existing data, only new emissions
SubscribeToEvent({
  event: 'live:updates',
  callback: handleLiveUpdate,
  skipOldEvent: true  // Only react to new events
});

// Cleanup when component unmounts
UnsubscribeEvent({
  event: 'live:updates',
  callback: handleLiveUpdate
});

When to Use

Good for:

  • Small to medium React/Vue/Angular applications
  • Component communication without prop drilling
  • Simple state sharing across unrelated components
  • Event-driven architectures
  • Lightweight state management needs

⚠️ Consider alternatives for:

  • Large applications with complex state logic (use Redux/MobX)
  • Applications requiring time-travel debugging
  • Heavy state transformations and middleware requirements

License

MIT © Shubham Kesarwani

Repository

GitHub Repository

Author

Shubham Kesarwani
📧 [email protected]
🔗 GitHub