Complete API reference for the Bun Redis Namespace Wrapper.
- Installation
- Factory Functions
- RedisWrapper Class
- NamespacedRedisWrapper Interface
- Types
- Core Operations
- JSON Operations
- Multi Operations
- Hash Operations
- Counter Operations
- TTL Operations
- Pattern Matching
- Pub/Sub Operations
- List Operations
- Set Operations
- Cleanup Operations
// Import from main entry point (recommended)
import {
createRedis,
createNamespacedRedis,
clearNamespace,
copyNamespace,
RedisWrapper,
type NamespacedRedisWrapper,
type SetOptions
} from "./index.ts";
// Or import core wrapper directly
import { RedisWrapper, createRedis, type SetOptions } from "./redis-wrapper.ts";Creates and connects to a Redis server.
Parameters:
url(optional): Redis connection URL. Default:"redis://localhost:6379"
Returns: Promise<RedisWrapper> - Connected Redis wrapper instance
Example:
// Default connection
await using redis = await createRedis();
// Custom connection
await using redis = await createRedis("redis://user:pass@host:6380/0");Creates a namespaced wrapper that automatically prefixes all keys.
Parameters:
redis: Base Redis wrapper instancenamespace: Namespace prefix (e.g., "myapp", "auth:v1")
Returns: NamespacedRedisWrapper - Namespaced wrapper
Example:
await using redis = await createRedis();
const authApp = createNamespacedRedis(redis, "auth");
const shopApp = createNamespacedRedis(redis, "shop");
// Keys stored as "auth:user:123" and "shop:user:123"
await authApp.set("user:123", "data");
await shopApp.set("user:123", "data");Notes:
- Trailing colons are automatically handled
- Namespace prefixes are transparent to the caller
- Pattern matching is scoped to the namespace
Deletes all keys in a namespace.
Parameters:
redis: Base Redis wrapper instancenamespace: Namespace to clear
Returns: Promise<number> - Number of keys deleted
Example:
const deleted = await clearNamespace(redis, "test");
console.log(`Deleted ${deleted} keys`);Warning: This operation scans and deletes all matching keys. Use carefully in production.
copyNamespace(redis: RedisWrapper, fromNamespace: string, toNamespace: string, options?: CopyNamespaceOptions): Promise<CopyNamespaceResult>
Copies all keys from one namespace to another.
Parameters:
redis: Base Redis wrapper instancefromNamespace: Namespace to copy fromtoNamespace: Namespace to copy tooptions(optional):{ match?: string; count?: number; replace?: boolean; dryRun?: boolean }
Returns: Promise<{ scanned: number; copied: number; skipped: number }>
Example:
const result = await copyNamespace(redis, "myapp:dev", "myapp:staging", { replace: false });
console.log(result); // { scanned, copied, skipped }Notes:
- Preserves key type and TTL using
DUMP+RESTORE. - By default it will not overwrite destination keys (
replace: false).
The base Redis wrapper class. All methods are available on both RedisWrapper and NamespacedRedisWrapper.
Static factory method to create a connection.
Example:
const redis = await RedisWrapper.connect("redis://localhost:6379");Options for SET command.
interface SetOptions {
EX?: number; // Expire time in seconds
PX?: number; // Expire time in milliseconds
NX?: boolean; // Only set if key doesn't exist
XX?: boolean; // Only set if key exists
KEEPTTL?: boolean; // Retain existing TTL
}Example:
// Set with 1 hour expiration
await redis.set("key", "value", { EX: 3600 });
// Set only if doesn't exist
await redis.set("key", "value", { NX: true });
// Set with millisecond precision
await redis.set("key", "value", { PX: 5000 });Get the value of a key.
Parameters:
key: Key to retrieve
Returns: Value or null if key doesn't exist
Example:
const value = await redis.get("mykey");
if (value) {
console.log("Found:", value);
}Set the value of a key.
Parameters:
key: Key to setvalue: Value to store (string or number)options: Optional SET command options
Returns: "OK" on success, null if NX/XX condition not met
Example:
// Simple set
await redis.set("key", "value");
// Set with expiration
await redis.set("session", "data", { EX: 3600 });
// Atomic set-if-not-exists
const created = await redis.set("lock", "1", { NX: true, EX: 10 });Delete one or more keys.
Parameters:
...keys: Keys to delete
Returns: Number of keys deleted
Example:
const deleted = await redis.del("key1", "key2", "key3");
console.log(`Deleted ${deleted} keys`);Check if all specified keys exist.
Parameters:
...keys: Keys to check
Returns: true if all keys exist, false otherwise
Example:
if (await redis.exists("user:123")) {
console.log("User exists");
}
// Check multiple keys
if (await redis.exists("key1", "key2", "key3")) {
console.log("All keys exist");
}Get and parse a JSON value.
Parameters:
key: Key to retrieve
Returns: Parsed object or null if key doesn't exist or parsing fails
Example:
interface User {
id: number;
name: string;
email: string;
}
const user = await redis.getJSON<User>("user:123");
if (user) {
console.log(user.name);
}Store an object as JSON.
Parameters:
key: Key to setobj: Object to serializeoptions: Optional SET command options
Returns: "OK" on success
Example:
const user = {
id: 123,
name: "Alice",
email: "alice@example.com"
};
await redis.setJSON("user:123", user, { EX: 3600 });Get multiple values by keys.
Parameters:
...keys: Keys to retrieve
Returns: Array of values (null for non-existent keys)
Example:
const [val1, val2, val3] = await redis.mget("key1", "key2", "key3");Set multiple key-value pairs atomically.
Parameters:
data: Object mapping keys to values
Returns: "OK" on success
Example:
await redis.mset({
"key1": "value1",
"key2": "value2",
"key3": 123
});Get a hash field value.
Parameters:
key: Hash keyfield: Field name
Returns: Field value or null
Example:
const name = await redis.hget("user:123", "name");Set a hash field value.
Parameters:
key: Hash keyfield: Field namevalue: Field value
Returns: 1 if new field, 0 if updated
Example:
await redis.hset("user:123", "name", "Alice");
await redis.hset("user:123", "age", 30);Get multiple hash field values.
Parameters:
key: Hash key...fields: Field names
Returns: Array of field values or null
Example:
const [name, age] = await redis.hmget("user:123", "name", "age");Set multiple hash field values.
Parameters:
key: Hash keydata: Object mapping field names to values
Returns: "OK" on success
Example:
await redis.hmset("user:123", {
name: "Alice",
age: "30",
city: "NYC"
});Get all hash fields and values.
Parameters:
key: Hash key
Returns: Object mapping field names to values
Example:
const userData = await redis.hgetAll("user:123");
console.log(userData.name, userData.age);Increment a key's value by 1.
Parameters:
key: Key to increment
Returns: New value after increment
Example:
const views = await redis.incr("page:views");
console.log(`Total views: ${views}`);Decrement a key's value by 1.
Parameters:
key: Key to decrement
Returns: New value after decrement
Example:
const remaining = await redis.decr("inventory:item:123");Get remaining time to live in seconds.
Parameters:
key: Key to check
Returns:
- TTL in seconds
-1if key has no expiry-2if key doesn't exist
Example:
const ttl = await redis.ttl("session:abc");
if (ttl > 0) {
console.log(`Expires in ${ttl} seconds`);
}Set TTL on an existing key.
Parameters:
key: Key to set TTL onseconds: Expiration time in seconds
Returns: true if TTL was set, false if key doesn't exist
Example:
await redis.set("key", "value");
await redis.setTTL("key", 3600); // Expire in 1 hourSet key expiration.
Parameters:
key: Key to expireseconds: Expiration time in seconds
Returns: 1 if set, 0 if key doesn't exist
Example:
await redis.expire("temp:data", 300); // Expire in 5 minutesScan for keys matching a pattern.
Parameters:
pattern: Glob pattern (e.g.,"user:*","session:*:active")count: Keys to scan per iteration (default: 100)
Returns: Array of matching keys
Example:
// Find all user keys
const userKeys = await redis.scanAll("user:*");
// Find all session keys
const sessions = await redis.scanAll("session:*");
// Namespaced: only scans within namespace
const app = createNamespacedRedis(redis, "myapp");
const keys = await app.scanAll("user:*"); // Scans "myapp:user:*"Notes:
- Uses SCAN command for memory-efficient iteration
- For namespaced wrappers, pattern is automatically prefixed
- Returned keys have namespace prefix removed
subscribe(channel: string, callback: (message: string, channel: string) => void): Promise<() => Promise<void>>
Subscribe to a channel.
Parameters:
channel: Channel namecallback: Function called when message received
Returns: Unsubscribe function
Example:
const unsubscribe = await redis.subscribe("events", (message, channel) => {
console.log(`[${channel}] ${message}`);
});
// Later: unsubscribe
await unsubscribe();Publish message to channel.
Parameters:
channel: Channel namemessage: Message to publish
Returns: Number of subscribers that received the message
Example:
const subscribers = await redis.publish("events", "User logged in");
console.log(`Sent to ${subscribers} subscribers`);Namespaced Example:
const authApp = createNamespacedRedis(redis, "auth");
const shopApp = createNamespacedRedis(redis, "shop");
// Different namespaced channels
await authApp.subscribe("events", (msg) => console.log("Auth:", msg));
await shopApp.subscribe("events", (msg) => console.log("Shop:", msg));
await authApp.publish("events", "Auth event"); // Only auth subscribers
await shopApp.publish("events", "Shop event"); // Only shop subscribersPush values to the left (head) of a list.
Parameters:
key: List key...values: Values to push
Returns: Length of list after push
Example:
await redis.lpush("queue", "task1", "task2", "task3");Push values to the right (tail) of a list.
Parameters:
key: List key...values: Values to push
Returns: Length of list after push
Example:
await redis.rpush("queue", "task1", "task2");Get a range of elements from a list.
Parameters:
key: List keystart: Start index (default: 0)stop: Stop index (default: -1 for end)
Returns: Array of elements
Example:
// Get all elements
const all = await redis.lrange("queue", 0, -1);
// Get first 10 elements
const first10 = await redis.lrange("queue", 0, 9);Remove and return the first (leftmost) element.
Parameters:
key: List key
Returns: First element or null if list is empty
Example:
const task = await redis.lpop("queue");
if (task) {
console.log("Processing:", task);
}Remove and return the last (rightmost) element.
Parameters:
key: List key
Returns: Last element or null if list is empty
Example:
const last = await redis.rpop("history");Add members to a set.
Parameters:
key: Set key...members: Members to add
Returns: Number of elements added (excludes duplicates)
Example:
const added = await redis.sadd("tags", "redis", "cache", "database");Remove members from a set.
Parameters:
key: Set key...members: Members to remove
Returns: Number of elements removed
Example:
await redis.srem("tags", "cache");Get all members of a set.
Parameters:
key: Set key
Returns: Array of set members
Example:
const tags = await redis.smembers("article:tags");
console.log("Tags:", tags);Close the Redis connection.
Example:
const redis = await createRedis();
// ... use redis ...
await redis.close();Async dispose support for await using syntax.
Example:
await using redis = await createRedis();
// Connection automatically closed when out of scopeasync function getCachedData<T>(
cache: NamespacedRedisWrapper,
key: string,
fetchFn: () => Promise<T>,
ttl: number
): Promise<T> {
// Try cache first
const cached = await cache.getJSON<T>(key);
if (cached) return cached;
// Cache miss - fetch data
const data = await fetchFn();
// Store in cache
await cache.setJSON(key, data, { EX: ttl });
return data;
}async function checkRateLimit(
redis: NamespacedRedisWrapper,
userId: string,
maxRequests: number,
windowSeconds: number
): Promise<boolean> {
const key = `ratelimit:${userId}`;
const count = await redis.incr(key);
if (count === 1) {
await redis.setTTL(key, windowSeconds);
}
return count <= maxRequests;
}async function acquireLock(
redis: RedisWrapper,
lockKey: string,
ttl: number = 10
): Promise<boolean> {
const acquired = await redis.set(lockKey, "1", { NX: true, EX: ttl });
return acquired === "OK";
}
async function releaseLock(redis: RedisWrapper, lockKey: string): Promise<void> {
await redis.del(lockKey);
}interface Session {
userId: string;
loginAt: number;
data: Record<string, any>;
}
const sessions = createNamespacedRedis(redis, "sessions");
// Create session
async function createSession(sessionId: string, userId: string): Promise<void> {
const session: Session = {
userId,
loginAt: Date.now(),
data: {}
};
await sessions.setJSON(sessionId, session, { EX: 3600 });
}
// Get session
async function getSession(sessionId: string): Promise<Session | null> {
return await sessions.getJSON<Session>(sessionId);
}
// Extend session
async function extendSession(sessionId: string): Promise<void> {
await sessions.setTTL(sessionId, 3600);
}try {
await redis.set("key", "value");
} catch (error) {
console.error("Redis error:", error);
// Handle connection errors, timeouts, etc.
}-
Use
await usingfor automatic cleanup:await using redis = await createRedis();
-
Share base connection across namespaces:
await using redis = await createRedis(); const app1 = createNamespacedRedis(redis, "app1"); const app2 = createNamespacedRedis(redis, "app2");
-
Use type parameters for JSON operations:
const user = await redis.getJSON<User>("user:123");
-
Set appropriate TTLs:
await redis.setJSON("cache:data", data, { EX: 300 });
-
Use pattern matching carefully:
// ✅ Specific pattern await redis.scanAll("user:session:*"); // ❌ Too broad await redis.scanAll("*");
- Use
mget/msetfor batch operations - Set appropriate TTLs to manage memory
- Use namespaces to organize keys logically
- Scan with specific patterns to reduce overhead
- Reuse connections instead of creating new ones
All operations are fully typed with TypeScript:
// Type-safe JSON operations
interface User {
id: number;
name: string;
}
const user = await redis.getJSON<User>("user:123");
if (user) {
console.log(user.name); // TypeScript knows this is a string
}
// Options are type-checked
await redis.set("key", "value", {
EX: 3600,
NX: true
// TypeScript prevents invalid options
});