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

@pyreon/sized-map

v0.32.0

Published

Bounded `Map<K, V>` primitive — FIFO (default) or LRU-on-read mode. Used internally across Pyreon packages for sized cache eviction; safe to use directly.

Readme

@pyreon/sized-map

A bounded-Map<K, V> primitive that evicts the oldest entry when a size cap is exceeded. One implementation, two configurations:

  • FIFO (default, lru: false) — .get() does NOT touch ordering; eviction always drops the first-inserted entry. Cheapest semantics, fits hot paths where re-insert-on-read would dominate (runtime-dom's _tplCache).
  • LRU-on-read (lru: true) — .get() re-inserts the entry at the tail (making it most-recently-used); eviction drops the least-recently-used entry. Standard cache semantics; fits cases where frequently-read entries should survive small caps (@pyreon/lint's AstCache, @pyreon/zero's ISR createMemoryStore, rocketstyle theme memo, element-bundle intern).

.set() ALWAYS treats a key collision as a recency hit — the old entry is removed and the new entry is appended at the tail. This applies in both modes; it's what callers depend on to keep "just-written" entries from being evicted on the very next call.

Why

Before this package, 9 Pyreon files each carried their own ~10-line FIFO eviction snippet — same map.keys().next().value + map.delete(oldest) shape, slightly different (each had its own bugs at one point). The catalog of leaked-by-omission inline caches is documented in .claude/rules/anti-patterns.md under "Memory Leak Classes" (Class C).

This package collapses the 9 implementations to one. Each consumer passes an SizedMapOptions config; the eviction code lives in exactly one place.

Quick start

import { SizedMap } from '@pyreon/sized-map'

// FIFO — hot path (template cache, class-string splitter, route loader cache)
const tplCache = new SizedMap<string, HTMLTemplateElement>({ maxEntries: 1024 })

// LRU-on-read — frequently-read entries survive cap pressure
const themeMemo = new SizedMap<string, RsMemoEntry>({ maxEntries: 128, lru: true })

API

interface SizedMapOptions {
  /** Max entries before oldest is evicted. */
  maxEntries: number
  /**
   * When true, `.get()` moves the entry to the tail (LRU).
   * When false, `.get()` does NOT touch the entry (pure FIFO).
   * Default: false.
   */
  lru?: boolean
}

class SizedMap<K, V> {
  constructor(opts: SizedMapOptions)
  get(key: K): V | undefined
  set(key: K, value: V): void
  delete(key: K): boolean
  has(key: K): boolean
  clear(): void
  get size(): number
  keys(): IterableIterator<K>
  values(): IterableIterator<V>
  entries(): IterableIterator<[K, V]>
  [Symbol.iterator](): IterableIterator<[K, V]>
}