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

@dokebi/cache

v0.4.1

Published

Named cache backends for Dokebi: in-process LRU or a shared Redis driver.

Readme

@dokebi/cache

An optional per-app JSON cache plugin. Each backend picks a driver: local (default, process memory) or redis (shared; needs @dokebi/cache-redis). core ^0.4.0, Node.js 24.0.0 or later, version 0.4.0 (unpublished). Named backends are configured under options.dokebi-cache.backends in the single YAML. AI agents start with AI.md.

schemaVersion: 1
options:
  dokebi-cache:
    backends:
      products:
        driver: local # may be omitted
        ttlMs: 30000
        maxEntries: 1000
        maxBytes: 16777216
        maxEntryBytes: 1048576
        maxKeyBytes: 1024
      shared:
        driver: redis
        connection: main # a name from dokebi-redis.connections
        namespace: my-service
        ttlMs: 60000
        maxEntryBytes: 65536

Registration and use

  • The factory input is { app, options?, entry? } (entry is the module of the entry file src/infra/cache/extension.ts, see "Extension" below). createPlugin({ app: app.view }) reads app.config['dokebi-cache']; given options are used instead. Invalid options are INVALID_PLUGIN_OPTIONS (cause: the core INVALID_OPTIONS, paths in details.issues). The options are one defineOptions declaration in src/options.ts, and the build generates options.schema.json from it (D-0063).
  • After app.register/start, get app.get(plugin).backend('products').
  • A consumer plugin puts import { dependency } from '@dokebi/cache' in metadata.dependencies and uses context.getDependency(dependency). An already registered dokebi-cache instance is reused.
  • backend.get(key) returns unknown, or undefined when missing; set(key, value, { ttlMs? }) returns Promise<void>; delete(key) returns whether a live value was removed. null is a normal value. TTL is the required default or a per-call override, 1–2147483647 ms. 0 or unlimited is not allowed.
  • backend.getOrSet(key, load, { ttlMs? }) (D-0106) returns the cached value, or stores and returns load()'s result. Concurrent calls of a process for the same key share one get, one load and one set (single flight, no stampede on the source); each caller gets its own copy, a failure reaches every waiter and is not cached. maxLoads (every backend, default 10000) bounds the keys loading at once; past it a call loads on its own.

Drivers

| Key (local) | Type | Default | Description | |---|---|---|---| | ttlMs | integer ms | — (required) | Default TTL | | maxEntries | integer | 1000 | Entry limit | | maxBytes | integer | 16777216 | Total key and value bytes | | maxEntryBytes | integer | 1048576 | One encoded value | | maxKeyBytes | integer | 1024 | Key UTF-8 bytes | | maxLoads | integer | 10000 | Keys whose getOrSet load is shared at once (also redis and app-driver backends) |

  • driver: local: follows "Local behavior" below. Not shared across apps, backends, threads or processes.
  • driver: redis: fields connection, namespace, ttlMs, maxEntryBytes (required), maxKeyBytes (1024), maxDepth (64), maxNodes (10000), maxPending (4096, 1–100000; old name maxPendingOperations, renamed in 0.4.0 by D-0071 and still accepted with a warning), maxPendingBytes (64 MiB of writes in flight, at least maxEntryBytes), maxLoads (10000). Size maxPending as at least the requests one worker serves at once times the cache operations each has in flight (AI.md "Sizing maxPending", D-0106: 128 refused 3,872 of 4,000 reads at once); past a limit a request answers a retryable 503 CACHE_BUSY. Behavior is described in @dokebi/cache-redis.
  • With at least one redis backend, dokebi-redis ^0.4.0 becomes a runtime dependency. When not registered, it is created from the @dokebi/redis package. With local only there is no dependency and the Redis package is never loaded.
  • The driver package is imported in setup. When it is not installed, start fails with CacheError DRIVER_NOT_INSTALLED and the fix says npm install @dokebi/cache-redis. A connection name missing from dokebi-redis is UNKNOWN_CONNECTION.
  • The driver contract is CacheDriver { view: CacheBackend; close(): Promise<void> }. Consumers get only view; only the plugin's cleanup calls close.

Extension (D-0064)

  • dokebi add creates the user-owned entry file src/infra/cache/extension.ts (an empty CacheExtension subclass). Left empty, behavior is the default and costs nothing (hooks you did not override are never called).
  • Hooks (protected override, three): dependencies(), createDriver(input), wrapBackend(input). Constructor parameters or shadowing a non-hook member fail with INVALID_EXTENSION (fix, data.reason) when the plugin is created.
  • Driver registry: the built-in local and redis stay, and app drivers are added with export const drivers = { <name>: (input) => driver } in the entry file or with defineCachePlugin({ drivers }). YAML uses driver: <name> and settings. Details in AI.md §9 and examples/29-extension.

Install (CLI)

  • Add it with npx dokebi add @dokebi/cache. @dokebi/cache-redis is not a plugin; add it with npm install.
  • planInstall and check of the install module (dist/install.js) return requires: ['dokebi-redis'] when a redis backend exists. So without dokebi-redis, add stops with MISSING_REQUIRED_PLUGIN, and removing a dokebi-redis in use is refused.
  • check reports an error diagnostic DRIVER_PACKAGE_MISSING per backend (path backends.<name>.driver) when the project's package.json lacks @dokebi/cache-redis.
  • The manifest is schemaVersion 2 and declares dokebi-redis as an optional dependency. @dokebi/redis and @dokebi/cache-redis are optional peerDependencies.

Local behavior

A JSON snapshot is made on write and independent data is returned on read. null, boolean, string, finite number, array and plain object are supported, and integers only within the safe range. undefined, bigint, functions, Date, Buffer, classes, getters, proxies, sparse arrays and cycles are rejected. -0 comes back as 0, as JSON does.

JsonCodec of @dokebi/cache/codec checks the JSON UTF-8 size including the J1: prefix. The defaults are depth 64 and 10000 nodes. maxEntryBytes is per value; maxBytes is the total of key and encoded value bytes and does not mean a JS heap limit. A failed replacement keeps the existing value. A corrupt value is CORRUPT_VALUE, never hidden as a miss.

LRU limits the entry count and bytes. Expiry is checked on the monotonic clock at read and delete. There are no full scans and no per-entry timers. Expired entries not read yet can still count toward capacity.

Shutdown and logs

  • After consumer cleanup the provider closes the drivers. Afterwards backend(name) is CLOSED. close and the internal Map are not public.
  • Logs: debug CACHE_BACKEND_READY when a backend is ready, error when a driver close fails (the driver's error code or CACHE_CLOSE_FAILED). Fields are backend and code only; never keys, values, namespaces or addresses.
  • A key is a non-empty, well-formed UTF-16 string with a limited UTF-8 length.

Main CacheError.code values: INVALID_OPTIONS, INVALID_KEY, UNKNOWN_BACKEND, UNKNOWN_CONNECTION, CLOSED, INVALID_VALUE, VALUE_TOO_LARGE, CORRUPT_VALUE, DRIVER_NOT_INSTALLED, DRIVER_INVALID, (redis) PROVIDER_FAILED, OUTCOME_UNKNOWN (both with the Redis error as cause), QUEUE_FULL. Through dokebi-web QUEUE_FULL answers 503 CACHE_BUSY and CLOSED 503 CACHE_UNAVAILABLE (Retry-After: 1); a transient Redis cause answers @dokebi/redis's 503 (D-0102). CacheError is a DokebiError (plugin: 'dokebi-cache', fix), and other packages classify it by code. Extension: UNKNOWN_DRIVER, DRIVER_CONFLICT, INVALID_ENTRY, INVALID_EXTENSION. Original values and keys never appear in error strings. Runnable examples: example 14 (local), example 15 (redis), and for extensions examples/29-extension.