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

@channel-state/core

v0.0.5

Published

Core-library for channel-state, providing framework-agnostic, zero-dependency state management with cross-context synchronization and persistence.

Downloads

15

Readme

📖 Overview

@channel-state/core is the foundational package of the channel-state ecosystem. It provides the ChannelStore class, a powerful, zero-dependency solution for state management that works in any JavaScript environment. It enables seamless, real-time state synchronization across browser tabs and windows using the native BroadcastChannel and IndexedDB APIs.

🛠️ Installation

npm install @channel-state/core
yarn add @channel-state/core
pnpm add @channel-state/core
bun add @channel-state/core

🌐 CDN Usage

For direct usage in the browser, you can use the UMD build from a CDN like jsDelivr or unpkg:

<script src="https://cdn.jsdelivr.net/npm/@channel-state/core@0"></script>

🚀 Playground

Explore and experiment with channel-state in a live environment using our interactive playground.

This playground provides a simple example of how to use @channel-state/core and @channel-state/react together.

Note: To see the cross-tab state synchronization in action, open the preview in a new tab.

📚 API Reference

ChannelStore<T>

The primary class for creating and managing a synchronized state.

Constructor

new ChannelStore<T>(options: ChannelStoreOptions<T>)

| Parameter | Type | Description | | --------- | --------------------- | ----------------------------------------------------- | | options | ChannelStoreOptions | An object containing the configuration for the store. |

ChannelStoreOptions

| Property | Type | Required | Default | Description | | --------- | --------- | -------- | ------- | ------------------------------------------------------------------------------------------------------------ | | name | string | Yes | - | A unique name for the channel. This is used for the BroadcastChannel and as the IndexedDB database name. | | initial | T | Yes | - | The initial value of the state. | | persist | boolean | No | false | If true, the state will be persisted to IndexedDB and restored on initialization. |

Properties

| Property | Type | Description | | -------- | ------------- | ------------------------------------------------------------------------------- | | status | StoreStatus | The current status of the store: 'initializing', 'ready', or 'destroyed'. |

Methods

| Method | Signature | Description | | ------------------- | ------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | get() | (): T | Synchronously returns the current state. | | set() | (value: T): void | Sets a new state, broadcasts it to other contexts, and persists it if persist is enabled. The method itself is synchronous, but persistence happens in the background. | | subscribe() | (callback: (value: T) => void): () => void | Subscribes to state changes. The callback receives the new state. Returns an unsubscribe function. | | subscribeStatus() | (callback: (status: StoreStatus) => void): () => void | Subscribes to store status changes. The callback receives the new status. Returns an unsubscribe function. | | destroy() | (): void | Closes the BroadcastChannel and IndexedDB connections and cleans up all subscribers. The store instance cannot be used afterward. | | reset() | (): Promise<void> | Resets the state to its initial value and broadcasts the change. |

🚀 Example Usage

import { ChannelStore } from '@channel-state/core'

// 1. Create a new store instance. This should be done once and shared.
const counterStore = new ChannelStore<number>({
  // A unique name for the channel, used for BroadcastChannel and IndexedDB.
  name: 'shared-counter',
  // The initial state of the store if no persisted state is found.
  initial: 0,
  // Set to true to persist the state to IndexedDB.
  persist: true,
})

// 2. Subscribe to status changes to know when the store is ready.
// This is crucial when `persist` is true, as it takes time to load from IndexedDB.
const unsubscribeStatus = counterStore.subscribeStatus((status) => {
  console.log('Store status is now:', status)

  // 3. Once the store is ready, you can safely interact with it.
  if (status === 'ready') {
    // Get the current state. This will be the persisted value if it exists.
    const currentCount = counterStore.get()
    console.log('Initial or persisted count:', currentCount)

    // Set a new state. This will be broadcast to other tabs.
    counterStore.set(currentCount + 1)
  }
})

// 4. Subscribe to state changes from any tab.
const unsubscribeState = counterStore.subscribe((newCount) => {
  console.log('Count has changed to:', newCount)
  // Here you would typically update your UI.
})

// 5. It's important to clean up when your application or component unmounts.
// The function below should be called from your framework's lifecycle hook
// (e.g., `useEffect` in React, `onUnmounted` in Vue, `onDestroy` in Svelte).
function cleanup() {
  unsubscribeStatus()
  unsubscribeState()
  counterStore.destroy()
}

// The line below is a generic example and is commented out because the specific
// implementation depends on your application's architecture.
// window.addEventListener('beforeunload', cleanup);