Cache#

In-memory caching with TTL support. Use for rate limiting, memoization, or temporary data storage.

Cache#

Basic Usage#

typescript
import { Cache } from "@buntok/core/cache";

const cache = new Cache();

// Set with TTL (seconds)
cache.set("key", "value", 60); // 1 minute

// Get (returns undefined if expired)
const value = cache.get("key");

// Delete
cache.delete("key");

// Clear all entries
cache.clear();

Cache API#

MethodReturnDescription
cache.get(key)Promise<T | null>Get value (null if expired)
cache.set(key, value, ttl?)Promise<void>Set value with optional TTL (seconds)
cache.delete(key)Promise<void>Delete a key
cache.clear()Promise<void>Clear all entries
cache.has(key)Promise<boolean>Check if key exists and hasn't expired
cache.getOrSet(key, factory, ttl?)Promise<T>Get from cache or compute and cache
cache.increment(key, amount?, ttl?)Promise<number>Increment numeric value (atomic)
cache.decrement(key, amount?, ttl?)Promise<number>Decrement numeric value (atomic)
cache.mget(keys)(T | null)[]Get multiple keys at once
cache.mset(entries, ttl?)voidSet multiple key-value pairs
cache.deletePattern(pattern)numberDelete keys matching glob pattern
cache.keys()string[]List all stored keys
Info
The keys() method is optional in the CacheDriver interface. Not all custom drivers implement it. If you call cache.keys() on a driver without keys(), it returns an empty array. The deletePattern method also depends on keys() being available.

Common Patterns#

typescript
// getOrSet - cache-aside pattern
const user = await cache.getOrSet(
  `user:${id}`,
  () => db.user.findUnique({ where: { id } }),
  300 // TTL in seconds
);

// Atomic counter
await cache.increment("page:views", 1, 3600);
const views = await cache.get<number>("page:views");

// Batch operations
await cache.mset([["user:1", data1], ["user:2", data2]], 300);
const [u1, u2] = await cache.mget(["user:1", "user:2"]);

// Pattern delete - clear all session keys
await cache.deletePattern("session:*");

AICache#

Cache for AI responses. Hashes messages to generate cache keys:

typescript
import { AICache } from "@buntok/core";
import { Cache, type CacheDriver } from "@buntok/core/cache";

const cacheDriver = new Cache();
const aiCache = new AICache(cacheDriver);

app.post("/chat", async (ctx) => {
  const { messages } = await ctx.body();

  // Check cache first
  const cached = await aiCache.get(messages);
  if (cached) return ctx.json({ response: cached });

  // Call AI
  const response = await callAI(messages);

  // Cache the result (default TTL: 3600s)
  await aiCache.set(messages, response);

  return ctx.json({ response });
});
Info
AICache automatically generates cache keys by hashing the message array. Duplicate conversations are served from cache.

Custom Drivers#

The Cache class accepts any object implementing CacheDriver. Here's an example using a custom Redis driver:

typescript
import { Cache, type CacheDriver } from "@buntok/core/cache";
import { createClient } from "redis";

class RedisCacheDriver implements CacheDriver {
  private client: ReturnType<typeof createClient>;
  private prefix: string;

  constructor(url = "redis://localhost:6379", prefix = "cache:") {
    this.client = createClient({ url });
    this.prefix = prefix;
  }

  async get<T>(key: string): Promise<T | null> {
    const raw = await this.client.get(this.prefix + key);
    return raw ? (JSON.parse(raw) as T) : null;
  }

  async set<T>(key: string, value: T, ttlSeconds?: number): Promise<void> {
    const serialized = JSON.stringify(value);
    if (ttlSeconds) {
      await this.client.setEx(this.prefix + key, ttlSeconds, serialized);
    } else {
      await this.client.set(this.prefix + key, serialized);
    }
  }

  async delete(key: string): Promise<void> {
    await this.client.del(this.prefix + key);
  }

  async clear(): Promise<void> {
    const keys = await this.client.keys(this.prefix + "*");
    if (keys.length) await Promise.all(keys.map((k) => this.client.del(k)));
  }

  async keys(): Promise<string[]> {
    const raw = await this.client.keys(this.prefix + "*");
    return raw.map((k) => k.slice(this.prefix.length));
  }
}

// Usage - drop-in replacement for the default memory driver
const cache = new Cache(new RedisCacheDriver());
await cache.set("user:1", userData, 3600); // TTL 1 hour
const user = await cache.get<User>("user:1");
Info
Install redis via bun add redis for persistent caching.