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

@plakboek/cache

v0.6.0

Published

Cache tags, the cache backend contract and a bounded in-process cache for Plakboek CMS installations

Readme

@plakboek/cache

Cache tags, the cache backend and invalidator contract, and a bounded in-process cache for Plakboek CMS installations. The visitor request handler in @plakboek/render reads and fills a CacheBackend; the page engine in @plakboek/pages purges a CacheInvalidator after a write commits. This package holds the contract both sides are written against, plus one implementation. It has no runtime dependency.

Install

pnpm add @plakboek/cache

Status

The tag vocabulary, the backend contract and the bounded memory cache are implemented and exported below. A shared backend (Redis, a CDN) is a later implementation of the same CacheBackend shape.

Ordering contract

Three rules keep a cache from serving stale content:

  1. Take ticket() before reading any data you will cache.
  2. set resolves false and stores nothing when any of its tags (or the global tag) was purged after that ticket was taken, so a fill that raced a purge is dropped instead of resurrecting stale content.
  3. A purge runs after the writing transaction commits, never before.

Process-local

createMemoryCache lives in one process. Two server processes behind a proxy each hold their own cache and do not share purges, so a purge in one does not reach the other until its entries expire (ttlMs, ten minutes by default). Run a single process, or put a shared backend behind the same contract.

Layers

The in-process LRU is one cache layer. A reverse proxy or a CDN in front of the server, added when the deployment is decided, is another. A writer holds one CacheInvalidator; composeInvalidators(lru, proxy) returns one that purges every layer in parallel. A layer that fails never stops the others: the composed purge still calls every layer and then rejects with a CachePurgeError carrying each failure, which the page engine reports after the publish has committed instead of failing it.

Public API

Every export of @plakboek/cache, grouped the way src/index.ts groups them. tests/unit/public-api.test.ts compares these tables with the entry point, so an export cannot be added or removed without updating them.

Tags

| Export | Kind | Purpose | | ---------------------- | -------- | ---------------------------------------------------------------- | | GLOBAL_TAG | constant | global: purging it removes every entry | | CACHE_TAG_PATTERN | constant | The pattern every well-formed tag matches | | pageTag | function | Builds page:<id> | | contentTypeTag | function | Builds content-type:<key> | | menuTag | function | Builds menu:<key> | | isCacheTag | function | Whether a value is a well-formed tag | | InvalidCacheTagError | class | Thrown by a tag helper when its input would not form a valid tag |

Backend contract

| Export | Kind | Purpose | | ------------------ | ---- | ------------------------------------------------------------------- | | CacheEntry | type | One cached response: body, etag, language, manifest hash, build id | | CacheSetOptions | type | The tags a fill depends on and the ticket taken before its read | | CacheInvalidator | type | The write side: purge(tags) | | CacheBackend | type | An invalidator plus ticket(), get(key) and set(key, entry, o) |

Layers

| Export | Kind | Purpose | | --------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------- | | composeInvalidators | function | Fans one purge out to every layer in parallel; one failure never stops the rest | | purgePageTags | function | Purges the page tag of each page id; an empty list makes no call | | CachePurgeError | class | Thrown by a composed purge when any layer failed; failures holds each error, failedLayers the position of each failed layer |

Memory cache

| Export | Kind | Purpose | | ---------------------------------- | -------- | ---------------------------------------------------------------- | | createMemoryCache | function | A bounded in-process LRU cache with a tag index and purge epochs | | MemoryCacheConfigError | class | Thrown by createMemoryCache with every invalid option | | DEFAULT_MEMORY_CACHE_MAX_ENTRIES | constant | 1000: the default entry-count bound | | DEFAULT_MEMORY_CACHE_MAX_BYTES | constant | 67108864 (64 MiB): the default byte bound | | DEFAULT_MEMORY_CACHE_TTL_MS | constant | 600000 (10 minutes): the backstop expiry | | MemoryCacheOptions | type | Input to createMemoryCache: the bounds and an injectable clock |