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

@byrding/core

v0.10.0

Published

Vanilla JS core — Proxy reactivity, subscription map, store registry

Readme

@byrding/core

Framework-agnostic reactivity engine. App code does not call this package directly — it's the substrate for @byrding/react and @byrding/vue. Use this reference if you're writing a new adapter or debugging.

AI agents — if you're generating consumer code, see the consumer agent guidance. If you're implementing a new adapter, see the refactor agent guidance.

Install

npm install @byrding/core
# or
npx jsr add @byrding/core

createStore(id, definition)

function createStore<T>(
  id: string,
  definition: (new () => T) | (() => T),
): CoreStore<T>

Register (or retrieve) a store. First registration for a given id wins; subsequent calls return the same singleton and the definition argument is discarded.

Returns a CoreStore<T>:

interface CoreStore<T> {
  /** Live flat merged object — state getters/setters, computed getters, action functions. */
  store: T

  /** Register a subscriber. Returns an unsubscribe function. */
  subscribe(
    componentId: string,
    keyPaths: string[],
    callback: () => void,
  ): () => void

  /** Cached snapshot of raw state — new reference on each mutation. */
  getSnapshot(): Partial<T>
}

Class vs closure dispatch

Internally, createStore detects the definition style:

  • /^\s*class\s/ match on the function source → class strategy: _proxy is a new Proxy(_raw); actions bound to the proxy.
  • Anything else → closure factory strategy: each state property on the returned instance is redefined with Object.defineProperty(inst, key, { get, set }) that reads/writes a separate _raw values map and calls _notify.

Actions, getters, and state fields are then all bound/exposed on the flat merged store.

generateComponentId()

function generateComponentId(): string

Returns byrding_1, byrding_2, … — a process-unique opaque ID. Used by adapters to distinguish subscribers in the subscribe/notify map.

subscribe(store, componentId, keyPaths, callback)

function subscribe(
  store: StoreInstance,
  componentId: string,
  keyPaths: string[],
  callback: () => void,
): () => void

Low-level subscribe. Adapters call this from their own hook/composable. keyPaths may be either a list of dot paths or ['*'] (wildcard).

notify(store, keyPath)

function notify(store: StoreInstance, rawKeyPath: string): void

Low-level notify. Normalises keyPath (strips .<number> array indices and trailing .length), then fires callbacks for:

  1. exact match on keyPath
  2. every ancestor path (a.b.ca.ba)
  3. the * wildcard bucket

Each callback runs at most once per call, even if it matches multiple paths.

storeRegistry

const storeRegistry: Map<string, StoreInstance>

The module-level singleton map keyed by store id. This is what enables cross-framework sharing — both adapters touch the same map. Do not delete entries manually in production code; it breaks reactivity on any live subscriber.

Types

interface StoreInstance {
  id: string
  _raw: Record<string, unknown>
  _proxy: Record<string, unknown>
  _stateKeys: string[]
  _actionKeys: string[]
  _computedKeys: string[]
  _getterFns: Record<string, () => unknown>
  _actionFns: Record<string, (...args: unknown[]) => unknown>
  _updateMap: Map<string, Set<string>>
  _callbackMap: Map<string, () => void>
  _notify: (keyPath: string) => void
}

Helpers

function classify(instance: object): {
  stateKeys: string[]
  actionKeys: string[]
  computedKeys: string[]
}

function createReactiveState(
  target: Record<string, unknown>,
  notify: (keyPath: string) => void,
  prefix?: string,
): Record<string, unknown>

function normaliseKeyPath(keyPath: string): string
  • classify walks the prototype chain to separate state, getters, and methods using getOwnPropertyDescriptors (never a live read — that would trigger getters).
  • createReactiveState builds the Proxy used for class-style stores.
  • normaliseKeyPath collapses items.0items and items.lengthitems.