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

@objectstack/service-cache

v17.2.0

Published

Cache Service for ObjectStack — implements ICacheService with in-memory and Redis adapters

Readme

@objectstack/service-cache

The shipped provider for the kernel's cache service slot — an in-memory ICacheService implementation with metrics instrumentation.

Slot criticality: core (ServiceRequirementDef in @objectstack/spec/system): the kernel warns and degrades if the slot is empty, it does not fail to start.

⚠️ The Redis adapter is a skeleton, not a shipped capability. RedisCacheAdapter throws RedisCacheAdapter not yet implemented from every method, and new CacheServicePlugin({ adapter: 'redis' }) throws during init rather than falling back. The only working adapter today is MemoryCacheAdapter. For a shared cache, register your own ICacheService implementation under the slot (see Custom implementations).

Installation

pnpm add @objectstack/service-cache

Usage

import { ObjectKernel } from '@objectstack/core';
import type { ICacheService } from '@objectstack/spec/contracts';
import { CacheServicePlugin } from '@objectstack/service-cache';

const kernel = new ObjectKernel();
await kernel.use(new CacheServicePlugin({ memory: { maxSize: 1000, defaultTtl: 300 } }));
await kernel.bootstrap();

const cache = kernel.getService<ICacheService>('cache');
await cache.set('user:123', { name: 'Alice' }, 60);   // ttl in SECONDS, positional
const user = await cache.get<{ name: string }>('user:123');

Plugin options

CacheServicePluginOptions has exactly four fields, all optional.

| Option | Type | Default | Purpose | |:---|:---|:---|:---| | adapter | 'memory' \| 'redis' | 'memory' | 'redis' throws at init — see the warning above. | | memory | MemoryCacheAdapterOptions | {} | Forwarded to MemoryCacheAdapter. | | redisUrl | string | none | Read by nothing today; kept for the unimplemented Redis path. | | metrics | MetricsRegistry | resolved from the kernel | Explicit metrics backend; wins over the service-registry lookup. |

MemoryCacheAdapterOptions:

| Option | Type | Default | Purpose | |:---|:---|:---|:---| | maxSize | number | 0 (unlimited) | Entry cap. At the cap a set of a NEW key evicts the oldest-inserted entry (Map insertion order — reads do not refresh position). | | defaultTtl | number | 0 (no expiry) | Default TTL in seconds. | | metrics | MetricsRegistry | NoopMetricsRegistry | Instrumentation sink. |

Note the spelling: defaultTtl, not defaultTTL.

Service API

ICacheService (from @objectstack/spec/contracts) is deliberately small — six members, all required:

import type { ICacheService, CacheStats } from '@objectstack/spec/contracts';

// get<T>(key)              -> Promise<T | undefined>   (undefined, not null, on a miss)
// set<T>(key, value, ttl?) -> Promise<void>            (ttl in seconds, positional)
// delete(key)              -> Promise<boolean>         (true when the key existed)
// has(key)                 -> Promise<boolean>
// clear()                  -> Promise<void>
// stats()                  -> Promise<CacheStats>

There is no mget / mset, no del, no pattern deletion, no namespace(), no ttl() / expire() / persist(), no incr / decr, no getOrSet, and no tagging. Compose those on top of the six members above if you need them.

// cache-aside, written against the real surface
async function getUser(id: string): Promise<User> {
  const cached = await cache.get<User>(`user:${id}`);
  if (cached !== undefined) return cached;

  const user = await loadUser(id);
  await cache.set(`user:${id}`, user, 600);
  return user;
}

Statistics

CacheStats has four fields — note keyCount, and that there is no hitRate (compute it from hits and misses):

const s = await cache.stats();
// { hits: number, misses: number, keyCount: number, memoryUsage?: number }

MemoryCacheAdapter returns hits, misses and keyCount; it does not report memoryUsage (the contract declares it optional).

Metrics

MemoryCacheAdapter emits the cache_lookups_total and cache_writes_total counters (SEMCONV in @objectstack/observability). The registry is resolved in this order:

  1. options.metrics (explicit constructor wiring)
  2. ctx.getService('observability:metrics') — registered by ObservabilityServicePlugin
  3. NoopMetricsRegistry (silent)

No HTTP surface

This service is kernel-internal: it is consumed in-process via the service registry (kernel.getService('cache')) and mounts no REST routes. Discovery advertises no route for the cache slot and reports handlerReady: false — for this slot that is the fact itself, not a proxy for reduced capability (ADR-0076 D12).

Custom implementations

The slot is multi-provider. To back the cache with Redis, Memcached or anything else, register an object satisfying ICacheService under 'cache' from your own plugin:

import type { ICacheService } from '@objectstack/spec/contracts';

class MyCache implements ICacheService { /* the six members above */ }

// inside your plugin's init(ctx):
ctx.registerService('cache', new MyCache());

Exports

import {
  CacheServicePlugin, MemoryCacheAdapter, RedisCacheAdapter,
} from '@objectstack/service-cache';

Types: CacheServicePluginOptions, MemoryCacheAdapterOptions, RedisCacheAdapterOptions.

License

Apache-2.0. See LICENSING.md.

See Also