Extensions
Cache
One cache contract, pluggable backends. @stone-js/cache gives you get/set/remember with TTL and tags, over a memory store (zero-config) or Redis, injected as cache, with decorators to cache method results declaratively. Provider KV follows.
#Install
npm i @stone-js/cache
npm i ioredis # only for the Redis store#Enable it
The principle
Caching should be a property of the call, not plumbing woven through it. Declare what to cache and for how long; let the store handle the rest.
In Stone.js
A single { get, set, remember, invalidateTags }contract backs every driver. The provider binds the manager as cacheManagerand the default store as cache.
import { StoneApp } from '@stone-js/core'
import { Cache } from '@stone-js/cache'
@Cache({ driver: 'memory' })
@StoneApp({ name: 'app' })
export class Application {}import { defineConfig } from '@stone-js/core'
import { defineCache } from '@stone-js/cache'
export const AppConfig = defineConfig(defineCache({
default: 'redis',
stores: [
{ name: 'redis', driver: 'redis', url: 'redis://localhost:6379', prefix: 'app' },
{ name: 'ram', driver: 'memory', ttl: 60 }
]
}))#Use it
Inject the default store as cache (or the manager as cacheManager). remember returns the cached value or computes, stores and returns it, and concurrent cold calls share one computation (stampede protection).
export class ReportService {
constructor (private readonly cache) {}
async monthly (year: number) {
return await this.cache.remember(
`report:${year}`,
async () => await this.compute(year),
{ ttl: 300, tags: ['reports'] }
)
}
}#Decorators
Cache method results without touching their bodies.
import { Cacheable, CacheEvict, CachePut } from '@stone-js/cache'
class UserService {
@Cacheable({ ttl: 300, tags: ['users'] })
async find (id: string) { return await this.repo.get(id) }
@CachePut({ key: (id) => `User.find:${id}` })
async update (id: string, data: object) { return await this.repo.save(id, data) }
@CacheEvict({ tags: ['users'] })
async purge () { await this.repo.clear() }
}| decorator | Type | Description |
|---|---|---|
| @Cacheable | method | Cache the result (cache-aside). Serves the cache on a hit; distinct arguments key distinct entries. |
| @CachePut | method | Always run, then refresh the cached value. Keeps the cache warm after writes. |
| @CacheEvict | method | Invalidate a key, tags, or the whole store after the method runs. |
#Drivers
| driver | Type | Description |
|---|---|---|
| memory | built-in | In-process Map with TTL, tags and counters. The zero-config default; single process. |
| redis | ioredis | Shared across instances. JSON values, native TTL, tags via Redis sets. Set url / options / client. |
| provider KV | coming next | Cloudflare / Vercel KV, same contract. |