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

@codecaine/bun-redis-wrapper

v1.2.1

Published

Production-ready Redis wrapper for Bun with namespaces, controllers, and TypeScript support

Readme

Bun Redis Wrapper - Production Ready

npm version npm downloads license

A powerful Redis wrapper for Bun with production-ready controllers for building real applications. Drop-in solutions for sessions, caching, rate limiting, job queues, and more.

🎯 Quick Start for Beginners

Option 1: Use Production Controllers (Recommended)

import { createRedis } from "@codecaine/bun-redis-wrapper";
import { SessionController, CacheController } from "@codecaine/bun-redis-wrapper/controllers";

const redis = await createRedis();

// Sessions - ready to use!
const sessions = new SessionController(redis);
const sessionId = await sessions.create("user-123", { name: "Alice" });

// Caching - intelligent and automatic!
const cache = new CacheController(redis);
const user = await cache.getOrSet("user:123", () => db.getUser(123), 300);

📦 Available Controllers:

  • SessionController - User sessions with multi-device support
  • CacheController - Intelligent caching with cache-aside pattern
  • RateLimiterController - API rate limiting (fixed/sliding window, token bucket)
  • QueueController - Background job processing with priorities
  • StorageController - Simple key-value storage with JSON
  • AnalyticsController - Metrics tracking with HyperLogLog
  • PubSubController - Publish/subscribe messaging
  • LockController - Distributed locks (simple mutex)
  • LeaderboardController - Rankings and leaderboards (sorted sets)
  • CounterController - Atomic counters and stats
  • FormularyController - Example domain controller (healthcare formulary)
  • RadAppController - Example domain controller (RAD app patterns)

👉 Controllers Documentation - Complete guide with examples
👉 Example Application - Full app using all controllers

Option 2: Use Core Wrapper Directly

import { createRedis, createNamespacedRedis } from "@codecaine/bun-redis-wrapper";

await using redis = await createRedis("redis://localhost:6379");
await redis.set("key", "value");

// With namespaces
const authApp = createNamespacedRedis(redis, "auth");
const shopApp = createNamespacedRedis(redis, "shop");

✨ Features

Production-Ready Controllers - Drop-in solutions for common use cases ⭐ NEW
Beginner Friendly - Clear documentation and examples ⭐ NEW
Type-Safe - Full TypeScript support with proper types
Namespace Support - Automatic key prefixing to prevent collisions
Comprehensive API - All common Redis operations supported
JSON Helpers - Built-in JSON serialization/deserialization
Sorted Sets - Leaderboards, rankings, and priority queues
Streams - Event sourcing and real-time data processing
Geospatial - Location-based queries and proximity search
HyperLogLog - Memory-efficient unique counting
Async Dispose - Works with await using syntax
Zero Dependencies - Uses Bun's native RedisClient

📊 Supported Redis Data Types

  • Strings - GET, SET, INCR, DECR
  • Hashes - HGET, HSET, HGETALL
  • Lists - LPUSH, RPUSH, LRANGE
  • Sets - SADD, SREM, SMEMBERS
  • Sorted Sets - ZADD, ZRANGE, ZRANK (leaderboards)
  • Streams - XADD, XREAD, XRANGE (event logs)
  • Geospatial - GEOADD, GEODIST, GEORADIUS
  • HyperLogLog - PFADD, PFCOUNT (unique counting)

📚 Documentation

For Beginners

Run all demos locally:

bun run demos

For Advanced Users

🚀 Installation

# Using Bun
bun add @codecaine/bun-redis-wrapper

# Using npm
npm install @codecaine/bun-redis-wrapper

# Using pnpm
pnpm add @codecaine/bun-redis-wrapper

# Using yarn
yarn add @codecaine/bun-redis-wrapper

📖 Quick Examples

Sessions (Production-Ready)

import { SessionController } from "@codecaine/bun-redis-wrapper/controllers";

const sessions = new SessionController(redis);

// Create session
const sessionId = await sessions.create("user-123", {
  name: "Alice",
  email: "[email protected]"
});

// Validate session
const session = await sessions.validate(sessionId);
if (session) {
  console.log(`Welcome ${session.data.name}!`);
}

// Logout
await sessions.destroy(sessionId);

Caching (Production-Ready)

import { CacheController } from "@codecaine/bun-redis-wrapper/controllers";

const cache = new CacheController(redis);

// Cache-aside pattern (automatic!)
const user = await cache.getOrSet(
  "user:123",
  async () => await database.getUser(123), // Only called on cache miss
  300 // Cache for 5 minutes
);

// Check cache stats
const stats = await cache.getStats();
console.log(`Hit rate: ${stats.hitRate}%`);

Rate Limiting (Production-Ready)

import { RateLimiterController } from "@codecaine/bun-redis-wrapper/controllers";

const limiter = new RateLimiterController(redis);

// Check rate limit (10 requests per minute)
const result = await limiter.check("user-123", 10, 60);

if (!result.allowed) {
  throw new Error(`Rate limited. Retry after ${result.retryAfter}s`);
}

console.log(`${result.remaining} requests remaining`);

Background Jobs (Production-Ready)

import { QueueController } from "@codecaine/bun-redis-wrapper/controllers";

const queue = new QueueController(redis);

// Add job
await queue.add("send-email", {
  to: "[email protected]",
  subject: "Welcome!"
}, { priority: 8 });

// Process jobs (in worker)
const job = await queue.next();
if (job) {
  await sendEmail(job.data);
  await queue.complete(job.id);
}

Core Wrapper Usage


### Multi-Tenant Application

```typescript
import { createRedis, createNamespacedRedis } from "@codecaine/bun-redis-wrapper";

await using redis = await createRedis();

// Each tenant gets isolated namespace
const tenant1 = createNamespacedRedis(redis, "tenant:acme");
const tenant2 = createNamespacedRedis(redis, "tenant:globex");

await tenant1.setJSON("config", { theme: "dark" });
await tenant2.setJSON("config", { theme: "light" });

// No collisions - each tenant has separate data

Environment-Based Isolation

const env = process.env.NODE_ENV || "development";
const namespace = `myapp:${env}`;
const redis = createNamespacedRedis(baseRedis, namespace);

// Keys stored as: "myapp:development:..." or "myapp:production:..."

API Reference

Factory Functions

createRedis(url?: string)

Creates a base Redis connection.

await using redis = await createRedis("redis://localhost:6379");

createNamespacedRedis(redis, namespace)

Creates a namespaced wrapper with automatic key prefixing.

const app = createNamespacedRedis(redis, "myapp");

clearNamespace(redis, namespace)

Deletes all keys in a namespace.

const deleted = await clearNamespace(redis, "myapp");

#### `copyNamespace(redis, fromNamespace, toNamespace, options?)`

Copies all keys from one namespace to another (useful for dev → staging → prod promotions within the same Redis instance).

```typescript
const result = await copyNamespace(redis, "myapp:dev", "myapp:staging", { replace: false });
console.log(result); // { scanned, copied, skipped }

### Available Operations

All operations support both the base `RedisWrapper` and `NamespacedRedisWrapper`:

**Core Operations**
- `get(key)`, `set(key, value, options?)`
- `del(...keys)`, `exists(...keys)`

**JSON Operations**
- `getJSON<T>(key)`, `setJSON<T>(key, value, options?)`

**Multi Operations**
- `mget(...keys)`, `mset(data)`

**Hash Operations**
- `hget(key, field)`, `hset(key, field, value)`
- `hmget(key, ...fields)`, `hmset(key, data)`
- `hgetAll(key)`

**Counter Operations**
- `incr(key)`, `decr(key)`

**TTL Operations**
- `ttl(key)`, `setTTL(key, seconds)`, `expire(key, seconds)`

**Pattern Matching**
- `scanAll(pattern, count?)`

**Pub/Sub**
- `subscribe(channel, callback)`, `publish(channel, message)`

**List Operations**
- `lpush(key, ...values)`, `rpush(key, ...values)`
- `lrange(key, start?, stop?)`, `lpop(key)`, `rpop(key)`

**Set Operations**
- `sadd(key, ...members)`, `srem(key, ...members)`, `smembers(key)`

## Examples

### JSON Storage with TTL

```typescript
interface UserSession {
  userId: number;
  username: string;
  loginAt: number;
}

const sessions = createNamespacedRedis(redis, "sessions");

const session: UserSession = {
  userId: 123,
  username: "alice",
  loginAt: Date.now()
};

// Store with 1 hour expiration
await sessions.setJSON("user:123", session, { EX: 3600 });

// Retrieve
const active = await sessions.getJSON<UserSession>("user:123");

Rate Limiting

async function checkRateLimit(
  client: NamespacedRedisWrapper,
  userId: string,
  maxRequests: number,
  windowSeconds: number
): Promise<boolean> {
  const key = `ratelimit:${userId}`;
  const count = await client.incr(key);
  
  if (count === 1) {
    await client.setTTL(key, windowSeconds);
  }
  
  return count <= maxRequests;
}

const api = createNamespacedRedis(redis, "api:v1");
const allowed = await checkRateLimit(api, "user:123", 10, 60);

Pattern Matching

const app = createNamespacedRedis(redis, "myapp");

// Store user sessions
await app.set("session:user:1", "data1");
await app.set("session:user:2", "data2");
await app.set("config:timeout", "30");

// Find all sessions (scoped to namespace)
const sessionKeys = await app.scanAll("session:*");
console.log(sessionKeys); // ["session:user:1", "session:user:2"]

Best Practices

1. Use Consistent Naming

// ✅ Good: Clear hierarchy with colons
"app:entity:id:field"
"myapp:user:12345:profile"

// ❌ Avoid: Inconsistent separators
"myapp_user_12345"

2. Share Base Connection

// ✅ Good: One connection, multiple namespaces
await using redis = await createRedis();
const app1 = createNamespacedRedis(redis, "app1");
const app2 = createNamespacedRedis(redis, "app2");

// ❌ Bad: Multiple connections
const redis1 = await createRedis();
const redis2 = await createRedis();

3. Clean Up in Tests

import { test, afterEach } from "bun:test";

afterEach(async () => {
  await clearNamespace(redis, "test");
});

Use Cases

  • 🏢 Microservices - Isolate data per service
  • 👥 Multi-tenant SaaS - Separate data per customer
  • 🌍 Environment Isolation - dev/staging/prod separation
  • 🔄 API Versioning - v1/v2 namespace isolation
  • 👨‍💻 Team Resources - Team-based access control

Performance

The namespace wrapper adds minimal overhead - just string concatenation. No additional network calls or memory overhead.

📝 Testing

Run the comprehensive test suite:

# Run all tests
bun test

# Run tests in watch mode
bun test --watch

The test suite includes 83 tests covering:

  • Core Redis operations
  • JSON operations
  • Multi operations
  • Hash operations
  • Counter operations
  • TTL operations
  • Pattern matching
  • List operations
  • Set operations
  • Namespace isolation
  • Multi-tenant scenarios
  • Integration tests

Requirements

  • Bun v1.0+
  • Redis server

License

MIT