Backend utilities for Node.js applications with TypeScript support. This package provides robust, production-ready utilities for common backend operations.
- 🚀 Redis Client Wrapper - Simplified Redis operations with automatic connection management
- 🔒 Type-Safe - Full TypeScript support with comprehensive type definitions
- 🌳 Tree-Shakeable - Import only what you need
- 📦 ESM & CommonJS - Supports both module systems
- ⚡ Production Ready - Battle-tested utilities with graceful error handling
npm install @digicroz/node-backend-utilsimport { redisBase, createRedisClient } from "@digicroz/node-backend-utils"
// Initialize Redis connection
await redisBase.initialize()
// Create a client with namespace prefix
const userCache = createRedisClient("user", true)
// Use the client
await userCache.set("john", "John Doe")
const user = await userCache.get("john")The base singleton Redis client with automatic connection management:
import { redisBase } from "@digicroz/node-backend-utils/redis"
// Initialize (call once at app startup)
await redisBase.initialize()
// Check connection status
const isConnected = redisBase.isClientConnected()
// Get client for advanced operations
const client = redisBase.getClient()
// Safe execution with error handling
const result = await redisBase.safeExecute(async (client) => {
return await client.get("mykey")
})
// Disconnect when shutting down
await redisBase.disconnect()Environment Variables:
REDIS_URL- Redis connection URL (e.g.,redis://localhost:6379)
A feature-rich Redis client with namespace prefixing and type-safe object storage:
import { createRedisClient } from "@digicroz/node-backend-utils/redis"
// Create a namespaced client
const cache = createRedisClient("myapp", true)
// String operations
await cache.set("key", "value")
await cache.setEx("key", 3600, "value") // with expiration
const value = await cache.get("key")
// Object operations (automatic JSON serialization)
await cache.setObj("user:1", { name: "John", age: 30 })
await cache.setObjEx("user:2", 3600, { name: "Jane", age: 25 })
const user = await cache.getObj<User>("user:1")
// Key operations
await cache.del("key")
await cache.delMultiple(["key1", "key2"])
await cache.exists("key")
await cache.expire("key", 3600)
await cache.ttl("key")
// Counter operations
await cache.incr("counter")
await cache.incrBy("counter", 5)
await cache.decr("counter")
// Pattern matching
const keys = await cache.keys("user:*")
// Hash operations
await cache.hSet("hash", "field", "value")
await cache.hGet("hash", "field")
await cache.hGetAll("hash")
await cache.hDel("hash", "field")
// List operations
await cache.lPush("list", "item1", "item2")
await cache.rPush("list", "item3")
await cache.lPop("list")
await cache.rPop("list")
await cache.lRange("list", 0, -1)
// Set operations
await cache.sAdd("set", "member1", "member2")
await cache.sMembers("set")
await cache.sRem("set", "member1")
// Custom operations with prefix support
const result = await cache.safeExecute(async (client, addPrefix) => {
const key = addPrefix("mykey")
return await client.get(key)
})Features:
- ✅ Automatic namespace prefixing
- ✅ Object serialization/deserialization
- ✅ Graceful error handling (returns null on errors)
- ✅ Enable/disable without code changes
- ✅ Full TypeScript support
// app.ts
import { redisBase } from "@digicroz/node-backend-utils"
async function startServer() {
// Initialize Redis at startup
await redisBase.initialize()
// Your app initialization...
}
startServer()import { createRedisClient } from "@digicroz/node-backend-utils"
const sessionCache = createRedisClient("session", true)
interface Session {
userId: string
email: string
loginTime: number
}
// Store session with 1 hour expiration
async function createSession(sessionId: string, userId: string, email: string) {
const session: Session = {
userId,
email,
loginTime: Date.now(),
}
await sessionCache.setObjEx(sessionId, 3600, session)
}
// Get session
async function getSession(sessionId: string) {
return await sessionCache.getObj<Session>(sessionId)
}import { createRedisClient } from "@digicroz/node-backend-utils"
const rateLimitCache = createRedisClient("ratelimit", true)
async function checkRateLimit(userId: string, maxRequests: number = 100) {
const key = `${userId}:requests`
const count = await rateLimitCache.incr(key)
if (count === 1) {
// First request, set expiration to 1 minute
await rateLimitCache.expire(key, 60)
}
return count && count <= maxRequests
}import { createRedisClient } from "@digicroz/node-backend-utils"
const featureFlags = createRedisClient("feature", true)
interface FeatureFlag {
enabled: boolean
rolloutPercentage: number
enabledUsers?: string[]
}
async function isFeatureEnabled(featureName: string, userId: string) {
const flag = await featureFlags.getObj<FeatureFlag>(featureName)
if (!flag || !flag.enabled) return false
if (flag.enabledUsers?.includes(userId)) return true
// Implement percentage-based rollout
const hash = userId
.split("")
.reduce((acc, char) => acc + char.charCodeAt(0), 0)
return hash % 100 < flag.rolloutPercentage
}initialize()- Initialize Redis connectiongetClient()- Get the raw Redis clientisClientConnected()- Check connection statusdisconnect()- Close the connectionsafeExecute(operation)- Execute operation with error handlinggetStatus()- Get connection status details
Creates a new Redis client instance with the given prefix.
Parameters:
prefix- Namespace prefix for all keysisEnabled- Enable/disable Redis operations (default: true)
Returns: RedisGenericClient instance
All methods return null if the client is disabled or on error.
set(key, value)- Set a string valuesetEx(key, seconds, value)- Set with expirationget(key)- Get a string value
setObj<T>(key, value)- Set an object (auto-serialized)setObjEx<T>(key, seconds, value)- Set object with expirationgetObj<T>(key)- Get an object (auto-deserialized)
del(key)- Delete a keydelMultiple(keys)- Delete multiple keysexists(key)- Check if key existsexpire(key, seconds)- Set expirationttl(key)- Get time to livekeys(pattern)- Find keys by pattern
incr(key)- Increment by 1incrBy(key, amount)- Increment by amountdecr(key)- Decrement by 1
hSet(key, field, value)- Set hash fieldhGet(key, field)- Get hash fieldhGetAll(key)- Get all hash fieldshDel(key, fields)- Delete hash fields
lPush(key, ...elements)- Push to leftrPush(key, ...elements)- Push to rightlPop(key)- Pop from leftrPop(key)- Pop from rightlRange(key, start, stop)- Get range
sAdd(key, ...members)- Add memberssMembers(key)- Get all memberssRem(key, ...members)- Remove members
REDIS_URL=redis://localhost:6379- Initialize Once - Call
redisBase.initialize()at application startup - Use Prefixes - Use meaningful prefixes to organize your keys
- Set Expirations - Always set TTL for cache data
- Handle Nulls - All methods can return
null, always check results - Graceful Degradation - The client is designed to fail gracefully
MIT
Adarsh Hatkar - GitHub
Contributions are welcome! Please feel free to submit a Pull Request.