Clov Packages
    Preparing search index...

    Module @clov-std/kv-store - v2.0.1

    Clov KV Store logo

    🗃️ Clov KV Store

    A lightweight, abstract key-value store with TTL support, increment/decrement operations, and built-in input validation.
    Swap between in-memory and Redis without changing a single line of business logic.

    Every project eventually needs a key-value store — for caching, rate-limiting, sessions, counters, etc.
    You either couple yourself to a specific backend or build your own abstraction every time.

    @clov-std/kv-store gives you a clean KvStore base class with two ready-to-use adapters:

    • MemoryStore — in-memory Map with TTL, automatic expired-entry cleanup, and configurable max size.
    • BunRedisStore — thin wrapper around Bun's native RedisClient, same API, no surprises.

    Both share the same interface, so switching from memory to Redis (or writing your own adapter) is trivial.

    • 🔑 Unified API : get, set, del, increment, decrement, expire, ttl, clean — same interface for every adapter.
    • ⏱️ TTL Support : Set expiration in seconds on any key.
    • 🛡️ Built-in Validation : Keys, TTL values, and amounts are validated before reaching the storage layer.
    • 🧠 MemoryStore : Zero-dependency in-memory store with background cleanup and optional max size.
    • 🔴 BunRedisStore : Native Bun Redis adapter, async by default.
    • 📦 Zero External Dependencies : Only depends on @clov-std/error.
    bun add @clov-std/kv-store
    
    import { MemoryStore } from '@clov-std/kv-store';

    const store = new MemoryStore();

    store.set('user:42', { name: 'Alice' }, 300); // TTL of 5 minutes
    const user = store.get<{ name: string }>('user:42');

    store.set('hits', 0);
    store.increment('hits'); // 1
    store.increment('hits', 5); // 6
    store.decrement('hits'); // 5

    store.ttl('user:42'); // remaining seconds
    store.del('user:42'); // true
    store.clean(); // removes all keys, returns count

    store.destroy(); // stops cleanup timer and clears data

    You can configure the cleanup interval and max size:

    const store = new MemoryStore(
    60_000, // cleanup every 60 seconds (default: 5 minutes)
    10_000 // max 10 000 entries (default: Infinity)
    );
    import { BunRedisStore } from '@clov-std/kv-store';

    const store = new BunRedisStore('redis://localhost:6379');
    await store.connect();

    await store.set('session:abc', { userId: 1 }, 3600);
    const session = await store.get<{ userId: number }>('session:abc');

    await store.increment('rate:ip:127.0.0.1');
    await store.expire('rate:ip:127.0.0.1', 60);

    store.close();

    Redis values written by set are JSON-encoded, including strings, so values such as "123", "true", and "null" keep their string type. Numeric values remain compatible with Redis counters. Existing raw strings that look like JSON cannot be distinguished from previously encoded values; rewrite those keys from their source of truth or let their TTL expire when upgrading.

    Run the Redis contract test against a disposable instance with TEST_REDIS_URL=redis://127.0.0.1:6379 bun test test/bun-redis-store.spec.ts from this package. It only modifies keys with a unique kv-store-test: prefix.

    Extend KvStore and implement the abstract methods:

    import { KvStore } from '@clov-std/kv-store';

    class MyStore extends KvStore {
    get<T>(key: string): T | null {
    /* ... */
    }
    set<T>(key: string, value: T, ttlSec?: number): void {
    /* ... */
    }
    increment(key: string, amount?: number): number {
    /* ... */
    }
    decrement(key: string, amount?: number): number {
    /* ... */
    }
    del(key: string): boolean {
    /* ... */
    }
    expire(key: string, ttlSec: number): boolean {
    /* ... */
    }
    ttl(key: string): number {
    /* ... */
    }
    clean(): number {
    /* ... */
    }
    }

    Use KvStore._validateKey(), KvStore._validateTtl(), and KvStore._validateAmount() for built-in validation.

    Full docs: https://clovlabs.github.io/std/

    MIT — Feel free to use it.

    BunRedisStore
    KvStore
    MemoryStore
    BUN_REDIS_STORE_ERROR_CODES
    KV_STORE_ERROR_CODES
    MEMORY_STORE_ERROR_CODES