API
This page provides a complete API reference for all decorators, classes, and types in the @vercube/cache package.
@Cache() (Decorator)
Replaces the decorated method with a cached version of itself. The cache key is derived from the method's arguments, concurrent calls for the same key are coalesced into a single execution, and entries are dropped automatically when the method body or its options change.
Signature
function Cache(options?: CacheTypes.DecoratorOptions): Function
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
options | CacheTypes.DecoratorOptions | No | Cache options for this method. See Options. |
When name is not given it defaults to ClassName.methodName, so two classes declaring the same method name never share entries.
Example:
import { Cache } from '@vercube/cache';
export class UsersService {
@Cache({ maxAge: 300, swr: true, staleMaxAge: 900, storage: 'cache' })
public async getUser(id: string): Promise<User> {
return this.database.findUser(id);
}
}
Helpers on the decorated method
The decorated method exposes three helpers that resolve exactly the keys the cached calls use.
type CachedMethod<ArgsT extends unknown[], T> = {
(...args: ArgsT): Promise<T>;
resolveKeys(...args: ArgsT): Promise<string[]>;
invalidate(...args: ArgsT): Promise<void>;
expire(...args: ArgsT): Promise<void>;
};
| Helper | Description |
|---|---|
resolveKeys() | Returns every storage key (one per storage tier) the given arguments cache under. |
invalidate() | Removes the cached entries for the given arguments. The next call resolves again. |
expire() | Marks the entries stale without removing them. With swr the stale value is still served while the next access refreshes it. |
Example:
import type { CacheTypes } from '@vercube/cache';
const getUser = usersService.getUser as CacheTypes.CachedMethod<[string], User>;
await getUser.resolveKeys('123'); // ['/cache:functions:UsersServicegetUser.GuK_juM6...:NYOXd4T2....json']
await getUser.invalidate('123');
await getUser.expire('123');
CacheManager (Class)
The central service of the module. It wires the caching engine to the storages mounted in @vercube/storage, holds the application wide defaults, and exposes the imperative API used both directly and by the @Cache() decorator.
Signature
class CacheManager {
public get adapter(): CacheStorageAdapter | null;
public get defaults(): CacheTypes.Defaults;
public configure(defaults: CacheTypes.Defaults): void;
public cached<T, ArgsT>(fn: (...args: ArgsT) => T | Promise<T>, options?: CacheTypes.Options<T, ArgsT>): CacheTypes.CachedFunction<T, ArgsT>;
public invalidate<ArgsT>(options: CacheTypes.Options<any, ArgsT>, ...args: ArgsT): Promise<void>;
public expire<ArgsT>(options: CacheTypes.Options<any, ArgsT>, ...args: ArgsT): Promise<void>;
public resolveKeys<ArgsT>(options: CacheTypes.Options<any, ArgsT>, ...args: ArgsT): Promise<string[]>;
}
Methods
configure()
Sets the application wide cache defaults. Options passed per cached function always win. Repeated calls merge into the existing defaults.
public configure(defaults: CacheTypes.Defaults): void
Example:
container.get(CacheManager).configure({
storage: 'cache',
maxAge: 60,
swr: true,
staleMaxAge: 600,
onError: (error) => logger.error('Cache failure', error),
});
cached()
Wraps a function with caching. Use it for functions that are not class methods, or when the options are only known at runtime.
public cached<T, ArgsT extends unknown[]>(
fn: (...args: ArgsT) => T | Promise<T>,
options?: CacheTypes.Options<T, ArgsT>,
): CacheTypes.CachedFunction<T, ArgsT>
Returns: the cached function, carrying the same resolveKeys(), invalidate() and expire() helpers as a decorated method.
Throws: CacheError when fn is not a function.
Example:
const getRates = cacheManager.cached(
(currency: string) => http.get(`/rates/${currency}`),
{ name: 'getRates', maxAge: 60, swr: true, staleMaxAge: 300 },
);
await getRates('EUR');
await getRates.invalidate('EUR');
invalidate() / expire() / resolveKeys()
Act on entries without holding a reference to the cached function. Pass the same options (name, group, storage, getKey) the entry was cached with, so the very same keys are resolved.
public invalidate<ArgsT>(options: CacheTypes.Options<any, ArgsT>, ...args: ArgsT): Promise<void>
public expire<ArgsT>(options: CacheTypes.Options<any, ArgsT>, ...args: ArgsT): Promise<void>
public resolveKeys<ArgsT>(options: CacheTypes.Options<any, ArgsT>, ...args: ArgsT): Promise<string[]>
Example:
// drop what UsersService.getUser cached for user 123, from anywhere in the app
await cacheManager.invalidate({ name: 'UsersService.getUser', storage: 'cache' }, '123');
CacheTypes.Options (Interface)
Options accepted by @Cache() and CacheManager.cached().
| Option | Type | Default | Description |
|---|---|---|---|
name | string | ClassName.methodName | Name used as part of the cache key. |
group | string | 'functions' | Key group prefix, useful for grouping related entries. |
storage | string | string[] | 'default' | Mounted storage(s) backing the entries. An array reads in order and writes to all; it must not be empty, and a name must not contain a colon. |
maxAge | number | 1 | Seconds an entry stays fresh. |
swr | boolean | false | Serve a stale entry while refreshing it in the background. |
staleMaxAge | number | - | Seconds a stale entry may still be served while revalidating. 0 never serves stale. |
getKey | (...args) => string | Promise<string> | hash of the arguments | Derives the key segment from the arguments. |
getMaxAge | (entry) => number | { maxAge?, staleMaxAge? } | - | Derives the lifetime from the resolved value. |
validate | (entry, ctx) => boolean | Promise<boolean> | value is defined | Return false to treat an entry as invalid and re-resolve. |
shouldBypassCache | (...args) => boolean | Promise<boolean> | - | Return true to skip the cache entirely for this call. |
shouldInvalidateCache | (...args) => boolean | Promise<boolean> | - | Return true to drop the entry and re-resolve. |
serialize | (entry, ctx) => any | - | Convert the resolved value into a storable shape. Runs once per resolution. |
transform | (entry, ...args) => any | - | Rebuild the usable value when an entry is read back. Also receives entry.status. |
integrity | unknown | hash of the method and its options | Overrides the value that invalidates entries when the code changes. |
onError | (error: unknown) => void | logs to console | Called for every cache related error (read, write, background refresh). |
entry.status
Inside transform the entry carries how the value was served on that call:
| Status | Meaning |
|---|---|
hit | A fresh cached value was returned without re-resolving. |
stale | A stale value was served while a background refresh runs. |
revalidated | A prior value existed but was expired, so it was re-resolved before returning. |
miss | The value was resolved fresh on this call. |
@Cache({
maxAge: 60,
swr: true,
staleMaxAge: 300,
transform: (entry) => {
metrics.increment(`cache.${entry.status}`);
return entry.value;
},
})
public async getRates(currency: string): Promise<Rates> { /* ... */ }
CacheTypes.Defaults (Interface)
Application wide defaults passed to CacheManager.configure(). Every field is optional and is overridden by per-function options.
| Option | Type | Description |
|---|---|---|
maxAge | number | Default freshness window in seconds. |
swr | boolean | Default stale-while-revalidate behaviour. |
staleMaxAge | number | Default stale window in seconds. |
group | string | Default key group prefix. |
storage | string | string[] | Default storage(s) to keep entries in. |
onError | (error: unknown) => void | Default cache error handler. |
CacheStorageAdapter (Class)
Bridges the caching engine onto the Vercube StorageManager. You rarely touch it directly - CacheManager creates one during initialization and binds every cached function to it - but it defines how cache keys map onto storages.
Signature
class CacheStorageAdapter {
public get<T>(key: string): Promise<T | null>;
public set<T>(key: string, value: T, opts?: { ttl?: number }): Promise<void>;
}
Writing null deletes the entry, mirroring how the caching engine signals invalidation.
Key helpers
const CACHE_BASE_PREFIX = '/cache';
function cacheBaseForStorage(storage?: string): string;
function storageNameFromCacheKey(key: string): string;
| Function | Description |
|---|---|
cacheBaseForStorage() | Builds the key base for a mounted storage: 'redis' becomes /cache/redis, the default storage stays /cache. |
storageNameFromCacheKey() | Reads the storage name back out of a full cache key. |
A complete key looks like:
/cache/redis:functions:UsersServicegetUser.GuK_juM6...:NYOXd4T2....json
└─ base ──┘ └─ group ┘ └────── name ───────────────┘ └─ arg hash ─┘
The group and name segments are sanitized before they reach the key: every character outside [A-Za-z0-9_] is dropped and a hash of the original is appended when that changes the value, which is why UsersService.getUser reads as UsersServicegetUser.GuK_juM6.... Call resolveKeys() rather than assembling a key by hand.
MemoryStorage under that name on first use and logs a warning. Mounting the name yourself - before or after - is what swaps the backend for a real one.CacheError (Class)
Thrown for cache configuration and wiring failures: decorating a non-method, using the cache without a StorageManager bound, passing an empty storage list, or a storage name containing a colon (which would break key routing).
Signature
class CacheError extends Error {
public readonly operation: string;
public readonly cause?: Error;
public readonly metadata?: Record<string, unknown>;
}
| Property | Type | Description |
|---|---|---|
operation | string | The cache operation that failed. |
cause | Error | The underlying error, when there is one. |
metadata | Record<string, unknown> | Non-sensitive context about the failure. |
Storage failures that happen while serving a cached call are not thrown - they are routed to the onError option so a failing cache never takes the request down. Failures during an explicit invalidate() or expire() do propagate, since you asked for that write to happen.