redis-growth
v1.0.2
Published
A modern, datatype-oriented Redis client wrapper for Node.js and TypeScript (redisInstance.datatype.action).
Maintainers
Readme
redis-growth 🚀
A modern, type-safe, datatype-oriented Redis client for Node.js and TypeScript.
Instead of flat, hard-to-navigate command lists, redis-growth groups Redis commands logically by data type under redisInstance.<datatype>.<action>().
🌟 Highlights
- Datatype-Driven API: Clean, self-documenting syntax (
redis.string.*,redis.hash.*,redis.list.*,redis.set.*,redis.sortedSet.*, etc.). - Automatic JSON Serialization: Built-in methods like
getJson<T>(),setJson<T>(),getAllParsed<T>(),rangeJson<T>(). - Full TypeScript Support: Generic types and autocompletion for keys, options, return values, and payloads.
- Enterprise-Ready: Powered by
ioredis, with full support for Standalone, Cluster, Sentinel, and TLS. - Dual Build: Native support for both CommonJS (
require) and ESM (import). - Escape Hatch: Access the underlying raw client at any time via
redis.raw.
📦 Installation
npm install redis-growth ioredis
# or
yarn add redis-growth ioredis
# or
pnpm add redis-growth ioredis🚀 Quick Start
import { createRedisGrowthClient } from 'redis-growth';
// Connect to Redis
const redis = createRedisGrowthClient({
host: 'localhost',
port: 6379,
// or url: 'redis://:password@localhost:6379/0'
});
await redis.connect();
// 1. Strings
await redis.string.set('user:name', 'Alice', { ttl: 3600 });
const name = await redis.string.get('user:name');
// 2. Hashes
await redis.hash.setObject('user:100', {
name: 'Alice',
role: 'admin',
verified: true,
});
const profile = await redis.hash.getAllParsed<{ name: string; role: string; verified: boolean }>('user:100');
// 3. Lists (Queues & Stacks)
await redis.list.pushRight('task:queue', 'task_1', 'task_2');
const nextTask = await redis.list.popLeft('task:queue');
// 4. Sets
await redis.set.add('tags:post:1', 'nodejs', 'typescript', 'redis');
const isTagged = await redis.set.isMember('tags:post:1', 'redis'); // true
// 5. Sorted Sets (Leaderboards)
await redis.sortedSet.add('leaderboard', 1500, 'player1');
await redis.sortedSet.addMany('leaderboard', [
{ score: 2000, member: 'player2' },
{ score: 1800, member: 'player3' },
]);
const topPlayers = await redis.sortedSet.rangeWithScores('leaderboard', 0, -1, { reverse: true });
// 6. Pub/Sub
await redis.pubsub.subscribeJson('notifications', (data) => {
console.log('Received notification:', data);
});
await redis.pubsub.publishJson('notifications', { alert: 'Disk usage high', level: 'warning' });📖 API Reference by Datatype
1. Strings & Key-Value (redis.string)
| Method | Description |
|---|---|
| set(key, value, options?) | Set value with optional TTL (ttl, ttlMs, keepTtl), conditions (onlyIfAbsent, onlyIfPresent), and getOldValue. |
| get(key) | Get string value of key. |
| setJson(key, value, options?) | Serializes value to JSON and sets key. |
| getJson<T>(key) | Gets and parses JSON value with TypeScript generic <T>. |
| getSet(key, value) | Sets value and returns previous value atomically. |
| getDel(key) | Gets value and deletes key atomically. |
| mget(...keys) | Gets values for multiple keys. |
| mgetJson<T>(...keys) | Gets and parses multiple JSON values. |
| mset(data) | Sets multiple key/value pairs. |
| msetJson(data) | Sets multiple key/value pairs with JSON serialization. |
| incr(key) / incrBy(key, amount) | Increment integer value. |
| incrByFloat(key, amount) | Increment floating-point value. |
| decr(key) / decrBy(key, amount) | Decrement integer value. |
| append(key, value) | Append string to existing value. |
| strlen(key) | Get string length. |
| setNx(key, value) | Set only if key does not exist. |
| setEx(key, seconds, value) | Set with expiration in seconds. |
| setPx(key, ms, value) | Set with expiration in milliseconds. |
| getRange(key, start, end) | Get substring. |
| setRange(key, offset, value) | Overwrite part of a string. |
2. Hashes (redis.hash)
| Method | Description |
|---|---|
| set(key, field, value) | Set a single hash field. |
| setObject(key, object) | Set multiple fields from an object (with auto-serialization). |
| get(key, field) | Get single field value. |
| getJson<T>(key, field) | Get and parse JSON value in hash field. |
| setJson(key, field, value) | Set JSON-serialized value in hash field. |
| getAll(key) | Get all fields as a Record<string, string>. |
| getAllParsed<T>(key) | Get all fields with JSON deserialization. |
| mget(key, ...fields) | Get multiple fields. |
| mgetJson<T>(key, ...fields)| Get and parse multiple fields. |
| mset(key, data) | Set multiple fields. |
| del(key, ...fields) | Delete one or more fields. |
| exists(key, field) | Check if a field exists. |
| keys(key) / values(key) | Get all field names or values. |
| len(key) | Get number of fields. |
| incrBy(key, field, amount) | Increment integer field. |
| incrByFloat(key, field, amount)| Increment float field. |
| setNx(key, field, value) | Set field only if it does not exist. |
| randomField(key, count?) | Get random field(s). |
3. Lists (redis.list)
| Method | Description |
|---|---|
| pushLeft(key, ...values) | Prepend element(s) (LPUSH). |
| pushRight(key, ...values) | Append element(s) (RPUSH). |
| pushLeftJson<T>(key, ...values)| Prepend JSON-serialized element(s). |
| pushRightJson<T>(key, ...values)| Append JSON-serialized element(s). |
| popLeft(key, count?) | Remove and get first element(s) (LPOP). |
| popRight(key, count?) | Remove and get last element(s) (RPOP). |
| popLeftJson<T>(key) | Remove and get first JSON element. |
| popRightJson<T>(key) | Remove and get last JSON element. |
| bPopLeft(keys, timeout) | Blocking pop from left (BLPOP). |
| bPopRight(keys, timeout) | Blocking pop from right (BRPOP). |
| range(key, start, stop) | Get slice of list (LRANGE). |
| rangeJson<T>(key, start, stop)| Get slice of parsed JSON items. |
| get(key, index) / getJson<T>(key, index) | Get element at index. |
| set(key, index, value) | Set element at index. |
| len(key) | Get list length. |
| trim(key, start, stop) | Trim list to range. |
| remove(key, count, value) | Remove elements matching value. |
| insertAfter(key, pivot, value) / insertBefore(...) | Insert relative to pivot. |
| move(source, dest, from, to) | Move element atomically between lists (LMOVE). |
4. Sets (redis.set)
| Method | Description |
|---|---|
| add(key, ...members) | Add member(s) to set. |
| remove(key, ...members) | Remove member(s) from set. |
| members(key) | Get all members. |
| isMember(key, member) | Check if element is in set. |
| mIsMember(key, ...members) | Check multiple elements membership. |
| card(key) | Get set cardinality (size). |
| pop(key, count?) | Pop random member(s). |
| random(key, count?) | Return random member(s) without removing. |
| move(source, dest, member) | Move member from one set to another. |
| union(...keys) / unionStore(dest, ...keys) | Set union. |
| intersect(...keys) / intersectStore(dest, ...keys) | Set intersection. |
| diff(...keys) / diffStore(dest, ...keys) | Set difference. |
5. Sorted Sets (redis.sortedSet or redis.zset)
| Method | Description |
|---|---|
| add(key, score, member, options?) | Add member with score. |
| addMany(key, members, options?) | Add array of { score, member }. |
| score(key, member) | Get score of member. |
| mScore(key, ...members) | Get scores for multiple members. |
| rank(key, member) | Get rank (ascending). |
| revRank(key, member) | Get rank (descending). |
| range(key, min, max, options?) | Get members by index/score/lex. |
| rangeWithScores(key, min, max, options?) | Get members with scores ([{ member, score }]). |
| rangeByScore(key, min, max, options?) | Get members by score range. |
| rangeByScoreWithScores(...) | Get members and scores by score range. |
| remove(key, ...members) | Remove member(s). |
| removeRangeByRank(key, start, stop) | Remove by rank. |
| removeRangeByScore(key, min, max) | Remove by score. |
| count(key, min, max) | Count members within score range. |
| card(key) | Get cardinality. |
| incrBy(key, increment, member) | Increment member score. |
| popMin(key, count?) / popMax(key, count?) | Pop minimum/maximum score member(s). |
6. RedisJSON (redis.json)
| Method | Description |
|---|---|
| set(key, path, value, options?) | Set JSON value (JSON.SET). |
| get<T>(key, ...paths) | Get JSON value (JSON.GET). |
| del(key, path?) | Delete JSON value (JSON.DEL). |
| type(key, path?) | Get JSON data type (JSON.TYPE). |
| numIncrBy(key, path, value) | Increment numeric JSON value (JSON.NUMINCRBY). |
| arrAppend(key, path, ...values)| Append to JSON array (JSON.ARRAPPEND). |
| arrLen(key, path?) | Get JSON array length. |
| arrPop<T>(key, path?, index?) | Pop from JSON array. |
| objKeys(key, path?) | Get object keys. |
| objLen(key, path?) | Get object field count. |
| toggle(key, path?) | Toggle boolean value. |
7. Pub/Sub (redis.pubsub)
// Subscribe to messages
await redis.pubsub.subscribe('chat', (message, channel) => {
console.log(`[${channel}] ${message}`);
});
// Subscribe to JSON objects
await redis.pubsub.subscribeJson<{ user: string; text: string }>('chat:json', (data) => {
console.log(`${data.user}: ${data.text}`);
});
// Pattern subscribe
await redis.pubsub.pSubscribe('logs:*', (message, channel, pattern) => {
console.log(`Matching ${pattern}: ${message}`);
});
// Publish
await redis.pubsub.publish('chat', 'Hello!');
await redis.pubsub.publishJson('chat:json', { user: 'Alice', text: 'Hey everyone!' });
// Unsubscribe
await redis.pubsub.unsubscribe('chat');8. Streams (redis.stream)
// Add event
const id = await redis.stream.add('sensor:logs', {
sensorId: 'temp-101',
temperature: 24.5,
timestamp: Date.now(),
});
// Read range
const entries = await redis.stream.range('sensor:logs', '-', '+');
// Consumer Groups
await redis.stream.createGroup('sensor:logs', 'processing-group', '$');
const messages = await redis.stream.readGroup(
'processing-group',
'consumer-1',
{ 'sensor:logs': '>' },
{ count: 10 }
);
// Acknowledge
await redis.stream.ack('sensor:logs', 'processing-group', entries[0].id);9. Geospatial (redis.geo)
await redis.geo.add('locations',
{ longitude: 13.361389, latitude: 38.115556, member: 'Palermo' },
{ longitude: 15.087269, latitude: 37.502669, member: 'Catania' }
);
const distanceKm = await redis.geo.dist('locations', 'Palermo', 'Catania', 'km');
const nearby = await redis.geo.searchFromMember('locations', 'Palermo', 200, {
unit: 'km',
withDist: true,
withCoord: true,
});10. Bitmaps (redis.bitmap) & HyperLogLog (redis.hyperLogLog / redis.hll)
// Bitmaps
await redis.bitmap.setBit('user:activity:day1', 105, 1);
const isActive = await redis.bitmap.getBit('user:activity:day1', 105); // 1
const activeCount = await redis.bitmap.count('user:activity:day1');
// HyperLogLog (Cardinality Estimation)
await redis.hyperLogLog.add('unique_visitors', 'ip1', 'ip2', 'ip3', 'ip1');
const estimatedCount = await redis.hll.count('unique_visitors'); // 311. Generic Keys & Server Operations (redis.keys)
await redis.keys.exists('user:1', 'user:2');
await redis.keys.expire('session:abc', 3600);
await redis.keys.ttl('session:abc');
await redis.keys.persist('session:abc');
await redis.keys.del('temp:1', 'temp:2');
await redis.keys.unlink('large:key');
// Safe scanning
const matchingKeys = await redis.keys.scanAll('user:*');⚙️ Configuration & Connection
You can configure RedisGrowthClient in multiple ways:
1. Connection URL
const redis = createRedisGrowthClient('redis://:[email protected]:6379/0');2. Options Object
const redis = createRedisGrowthClient({
host: '127.0.0.1',
port: 6379,
password: 'secret',
db: 0,
retryStrategy(times) {
return Math.min(times * 50, 2000);
},
});3. Cluster
const redis = createRedisGrowthClient({
cluster: {
nodes: [
{ host: '127.0.0.1', port: 7000 },
{ host: '127.0.0.1', port: 7001 },
],
options: {
redisOptions: { password: 'secret' },
},
},
});4. Existing IORedis Instance
import Redis from 'ioredis';
const existingClient = new Redis();
const redis = createRedisGrowthClient({ client: existingClient });🧪 Testing
The package is thoroughly tested with unit tests and mocks:
npm run test🏢 Maintainer & Website
Maintained by Growth Catalyst Pvt Ltd.
For questions, enterprise support, or collaborations, visit https://www.growthcatalyst.com.np or email [email protected].
