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

@supercat1337/store

v1.1.1

Published

A lightweight, zero-dependency reactive state manager with automated dependency tracking, cyclic loop detection, and atomic/computed architecture.

Downloads

478

Readme

@supercat1337/store

A lightweight, high-performance reactive state manager for modern JavaScript applications. Built on clean vanilla JS with strict JSDoc typing and a powerful internal dependency graph.

License: MIT Size

Key Features

  • ⚡ Lightweight & Fast: Only ~13 KB bundled, with minimal dependencies.
  • 🔄 Automated Dependency Tracking: Computed properties automatically discover their dependencies during execution. No manual dependency arrays required.
  • 🛡️ Cycle Protection: Internal validation (DependencyGraph) actively prevents synchronous cyclic loops before they can crash your app.
  • 📦 Atomic Data Structures: Clean separation of concerns using primitives (Atom), arrays (Collection), and derived state (Computed).
  • ⏱️ Built-in Optimization: Supports smart caching (is_hard evaluation mode) to skip expensive computations unless deep dependencies change, and built-in debouncing for subscriptions.
  • 🔮 Agnostic: Works flawlessly with standard DOM API, React, Vue, Lit, or backend environments.

Installation

npm install @supercat1337/store

Core Concepts

The store architecture is split into three main reactive building blocks:

  1. Atom: Represents a single primitive or object state slot.
  2. Collection: A specialized wrapper designed for reactive arrays, supporting granular item mutations without breaking reactivity.
  3. Computed: Derived states calculated from values of Atoms, Collections, or other Computed values.

Code Examples

1. Basic Reactive State & Computed Properties

import { Store } from '@supercat1337/store';

const store = new Store();

// Create basic state primitives (value first, optional name second)
const price = store.createAtom(10, 'apple_price');
const quantity = store.createAtom(3, 'apple_quantity');

// Create derived state (automatically tracks price and quantity)
const totalCost = store.createComputed(() => price.value * quantity.value, 'total_cost');

// Subscribe to changes (with optional debounce in ms)
const unsubscribe = totalCost.subscribe(details => {
    console.log(`Total cost updated to: ${details.value}`);
}, 100); // debounced to at most once per 100ms

// Trigger reactivity
price.value = 12; // Console logs: Total cost updated to: 36
quantity.value = 5; // Console logs: Total cost updated to: 60

// Clean up
unsubscribe();

2. Working with Collections (Arrays)

import { Store } from '@supercat1337/store';

const store = new Store();
const todoList = store.createCollection(
    [
        { text: 'Write code', done: false },
        { text: 'Test code', done: false },
    ],
    'todos'
);

// Derived state counting uncompleted tasks
const pendingCount = store.createComputed(
    () => todoList.value.filter(todo => !todo.done).length,
    'pending_todos'
);

console.log(pendingCount.value); // 2

// Update an object inside a specific index safely and immutably
todoList.updateItemValue(0, { done: true });

console.log(pendingCount.value); // 1 (Reacts instantly)

3. Asynchronous Scheduling via when()

The store provides a native when utility that returns a Promise resolving as soon as a condition becomes true.

import { Store } from '@supercat1337/store';

const store = new Store();
const counter = store.createAtom(0, 'counter');

// Wait until counter reaches 3
(async () => {
    await store.when(() => counter.value >= 3);
    console.log('Condition met! Counter is 3 or higher.');
})();

// Simulating increments over time
counter.value = 1;
counter.value = 2;
counter.value = 3; // Triggers the async block above

4. Debounced Subscriptions

You can pass a debounce time (in milliseconds) as the second argument to subscribe(). This is useful for performance‑intensive UI updates.

const store = new Store();
const width = store.createAtom(window.innerWidth, 'windowWidth');

const unsubscribe = width.subscribe(details => {
    console.log(`Window width changed to ${details.value}px`);
}, 200); // at most once per 200ms

window.addEventListener('resize', () => {
    width.value = window.innerWidth;
});

// Later: unsubscribe()

5. Autorun and Reaction

For automatic side effects that re‑run whenever their dependencies change, use autorun. For finer control, use reaction which only reacts to data accessed in the first function.

import { Store } from '@supercat1337/store';

const store = new Store();
const firstName = store.createAtom('John', 'first');
const lastName = store.createAtom('Doe', 'last');

// autorun runs immediately and then on every dependency change
store.autorun(() => {
    console.log(`Full name: ${firstName.value} ${lastName.value}`);
});
// Logs: "Full name: John Doe"

// reaction tracks only firstName and executes effect when it changes
store.reaction(
    () => firstName.value, // data function (tracked)
    () => console.log(`First name changed to ${firstName.value}`) // effect
);

firstName.value = 'Jane';
// Logs: "First name changed to Jane" and autorun logs "Full name: Jane Doe"

Advanced Options

Deep Evaluation Optimization (is_hard)

By default, Computed values re-evaluate lazily based on structural versions. If you have computationally heavy logic, you can enforce hard evaluation constraints to double-check structural equivalence before declaring the node stale:

const heavyCalculation = store.createComputed(
    () => {
        // Heavy tasks here...
        return result;
    },
    'heavy',
    { is_hard: true }
);

Custom Naming Conventions

The store allows names containing alphanumeric characters, dashes, dots, and colons to facilitate predictable hierarchical namespaces:

const userFirstName = store.createAtom('John', 'user:profile.first_name');

Documentation

Full generated API reports and class specs can be found in the repository:

📖 For AI agents: see AI_DOCS.md – structured documentation for LLMs.

License

MIT [Albert Bazaleev]