### Basic Cluster Setup in ioredis-mock Source: https://github.com/stipsan/ioredis-mock/blob/main/README.md Provides an example of setting up a minimal Cluster connection. Note that Cluster support is experimental and may have limitations. ```javascript const Redis = require('ioredis-mock') const cluster = new Redis.Cluster(['redis://localhost:7001']) const nodes = cluster.nodes() expect(nodes.length).toEqual(1) ``` -------------------------------- ### Browser Usage of ioredis-mock Source: https://github.com/stipsan/ioredis-mock/blob/main/README.md Import and use ioredis-mock directly in the browser using its browser build. This example demonstrates setting and getting a key. ```javascript import Redis from 'https://unpkg.com/ioredis-mock' const redis = new Redis() redis.set('foo', 'bar') console.log(await redis.get('foo')) ``` -------------------------------- ### Jest Test Suite Setup with ioredis-mock Source: https://context7.com/stipsan/ioredis-mock/llms.txt Example of setting up Jest tests using ioredis-mock. Use `flushall()` in `beforeEach` to clear data and `disconnect()` in `afterEach` to clean up. ```javascript const Redis = require('ioredis-mock') // Jest setup example describe('my redis feature', () => { let redis beforeEach(async () => { redis = new Redis() // Flush all keys before each test (clears all databases) await new Redis().flushall() }) afterEach(() => { redis.disconnect() }) it('should store and retrieve a value', async () => { await redis.set('name', 'Alice') expect(await redis.get('name')).toBe('Alice') }) it('should not see data from the previous test', async () => { expect(await redis.get('name')).toBeNull() }) }) ``` ```javascript jest.mock('ioredis', () => require('ioredis-mock')) // All imports of 'ioredis' now use the mock automatically ``` -------------------------------- ### Basic String Operations with ioredis-mock Source: https://context7.com/stipsan/ioredis-mock/llms.txt Perform core string operations like set, get, append, and range. The `set` command supports various options including TTL, NX, XX, and GET. ```javascript const Redis = require('ioredis-mock') const redis = new Redis() // Basic set/get await redis.set('foo', 'bar') console.log(await redis.get('foo')) // 'bar' // Set with TTL (expires in 10 seconds) await redis.set('session', 'abc123', 'EX', 10) // NX — only set if key does not exist await redis.set('lock', '1', 'NX') // 'OK' await redis.set('lock', '2', 'NX') // null (already exists) // GET option — returns old value while setting new one await redis.set('counter', '5') const old = await redis.set('counter', '10', 'GET') console.log(old) // '5' // Atomic increment/decrement await redis.set('views', '100') await redis.incr('views') // 101 await redis.incrby('views', 9) // 110 await redis.decr('views') // 109 // Multi-get / multi-set await redis.mset('k1', 'v1', 'k2', 'v2', 'k3', 'v3') console.log(await redis.mget('k1', 'k2', 'k3')) // ['v1', 'v2', 'v3'] // Append and range await redis.set('word', 'Hello') await redis.append('word', ' World') // 11 (new length) console.log(await redis.getrange('word', 0, 4)) // 'Hello' // getdel — get and delete atomically await redis.set('tmp', 'value') console.log(await redis.getdel('tmp')) // 'value' console.log(await redis.get('tmp')) // null ``` -------------------------------- ### Run End-to-End Tests with Docker Source: https://github.com/stipsan/ioredis-mock/blob/main/test/README.md This command starts a Redis instance using Docker, which is required for running end-to-end tests. Ensure Redis is running on localhost:6379. ```bash $ docker run --name ioredis-mock -p 6379:6379 --rm redis redis-server --save 60 1 --loglevel warning ``` -------------------------------- ### List Commands: lpush, rpush, lpop, rpop, lrange, llen, lindex, linsert, lmove, lpos Source: https://context7.com/stipsan/ioredis-mock/llms.txt Redis list operations with doubly-linked list semantics. Supports all push/pop variants, range slicing, position lookup, and atomic move between lists. Use `lrange` with 0 and -1 to get the full list. ```javascript const Redis = require('ioredis-mock') const redis = new Redis() // Push to left and right await redis.rpush('tasks', 'task1', 'task2', 'task3') await redis.lpush('tasks', 'task0') // Get a range (0 to -1 = full list) console.log(await redis.lrange('tasks', 0, -1)) // ['task0', 'task1', 'task2', 'task3'] console.log(await redis.llen('tasks')) // 4 // Pop from both ends console.log(await redis.lpop('tasks')) // 'task0' console.log(await redis.rpop('tasks')) // 'task3' // Get element by index console.log(await redis.lindex('tasks', 0)) // 'task1' // Insert before/after a pivot await redis.linsert('tasks', 'BEFORE', 'task2', 'task1.5') console.log(await redis.lrange('tasks', 0, -1)) // ['task1', 'task1.5', 'task2'] // Atomically move element between lists await redis.rpush('src', 'a', 'b', 'c') await redis.lmove('src', 'dst', 'LEFT', 'RIGHT') console.log(await redis.lrange('dst', 0, -1)) // ['a'] // Find position of an element await redis.rpush('nums', '1', '2', '3', '2', '1') console.log(await redis.lpos('nums', '2')) // 1 (first occurrence) console.log(await redis.lpos('nums', '2', 'RANK', 2)) // 3 (second occurrence) ``` -------------------------------- ### String Commands - set, get, getset, getdel, getex, mset, mget, incr, incrby, decr, append, getrange Source: https://context7.com/stipsan/ioredis-mock/llms.txt Core string operations mirroring Redis string commands. The `set` command supports various options like TTL, NX, XX, and GET. ```APIDOC ## String Commands — `set`, `get`, `getset`, `getdel`, `getex`, `mset`, `mget`, `incr`, `incrby`, `decr`, `append`, `getrange` Core string operations mirroring Redis string commands. `set` supports all Redis options: `EX` (seconds TTL), `PX` (milliseconds TTL), `EXAT` (Unix timestamp in seconds), `PXAT` (Unix timestamp in ms), `NX` (set if not exists), `XX` (set only if exists), and `GET` (return old value). ```js const Redis = require('ioredis-mock') const redis = new Redis() // Basic set/get await redis.set('foo', 'bar') console.log(await redis.get('foo')) // 'bar' // Set with TTL (expires in 10 seconds) await redis.set('session', 'abc123', 'EX', 10) // NX — only set if key does not exist await redis.set('lock', '1', 'NX') // 'OK' await redis.set('lock', '2', 'NX') // null (already exists) // GET option — returns old value while setting new one await redis.set('counter', '5') const old = await redis.set('counter', '10', 'GET') console.log(old) // '5' // Atomic increment/decrement await redis.set('views', '100') await redis.incr('views') // 101 await redis.incrby('views', 9) // 110 await redis.decr('views') // 109 // Multi-get / multi-set await redis.mset('k1', 'v1', 'k2', 'v2', 'k3', 'v3') console.log(await redis.mget('k1', 'k2', 'k3')) // ['v1', 'v2', 'v3'] // Append and range await redis.set('word', 'Hello') await redis.append('word', ' World') // 11 (new length) console.log(await redis.getrange('word', 0, 4)) // 'Hello' // getdel — get and delete atomically await redis.set('tmp', 'value') console.log(await redis.getdel('tmp')) // 'value' console.log(await redis.get('tmp')) // null ``` ``` -------------------------------- ### Initialize ioredis-mock with Data Source: https://github.com/stipsan/ioredis-mock/blob/main/README.md Instantiate ioredis-mock with initial data. This is useful for setting up a predictable state for testing. ```javascript const Redis = require('ioredis-mock') const redis = new Redis({ // `options.data` does not exist in `ioredis`, only `ioredis-mock` data: { user_next: '3', emails: { 'clark@daily.planet': '1', 'bruce@wayne.enterprises': '2', }, 'user:1': { id: '1', username: 'superman', email: 'clark@daily.planet' }, 'user:2': { id: '2', username: 'batman', email: 'bruce@wayne.enterprises' }, }, }) // Basically use it just like ioredis ``` -------------------------------- ### Constructor - new Redis(options) Source: https://context7.com/stipsan/ioredis-mock/llms.txt Creates a new in-memory Redis client. Accepts the same constructor signatures as ioredis, with an additional `data` option for pre-seeding the store. ```APIDOC ## Constructor — `new Redis(options)` Creates a new in-memory Redis client. Accepts the same constructor signatures as ioredis: no arguments (defaults to `localhost:6379/0`), a port number, a port + host, a URL string, or an options object. The `data` option (unique to ioredis-mock) allows pre-seeding the in-memory store with initial data at construction time. ```js const Redis = require('ioredis-mock') // Default connection (localhost:6379, db 0) const redis = new Redis() // With initial seed data const redis2 = new Redis({ data: { user_next: '3', emails: { 'clark@daily.planet': '1', 'bruce@wayne.enterprises': '2', }, 'user:1': { id: '1', username: 'superman', email: 'clark@daily.planet' }, 'user:2': { id: '2', username: 'batman', email: 'bruce@wayne.enterprises' }, }, }) // URL string form const redis3 = new Redis('redis://localhost:6380/1') // Port + host form const redis4 = new Redis(6380, 'localhost') // lazyConnect — does not connect until redis.connect() is called const redis5 = new Redis({ lazyConnect: true }) await redis5.connect() console.log(await redis2.get('user_next')) // '3' redis5.disconnect() ``` ``` -------------------------------- ### Pub/Sub Channels with ioredis-mock Source: https://github.com/stipsan/ioredis-mock/blob/main/README.md Demonstrates how to use publish/subscribe channels with two separate Redis clients. The 'message' event listener is crucial for receiving messages. ```javascript const Redis = require('ioredis-mock') const redisPub = new Redis() const redisSub = new Redis() redisSub.on('message', (channel, message) => { console.log(`Received ${message} from ${channel}`) }) redisSub.subscribe('emails') redisPub.publish('emails', 'clark@daily.planet') ``` -------------------------------- ### Pub/Sub Messaging in ioredis-mock Source: https://context7.com/stipsan/ioredis-mock/llms.txt Illustrates Redis publish/subscribe functionality using separate client instances for publishing and subscribing, mirroring ioredis. Supports simple channel subscriptions, pattern subscriptions, and handling message buffers. Remember to unsubscribe and disconnect clients when done. ```javascript const Redis = require('ioredis-mock') const redisSub = new Redis() const redisPub = new Redis() // Simple channel subscription redisSub.on('message', (channel, message) => { console.log(`[${channel}] ${message}`) // [emails] clark@daily.planet }) await redisSub.subscribe('emails') // Publish a message (returns number of subscribers that received it) const count = await redisPub.publish('emails', 'clark@daily.planet') console.log(count) // 1 // Pattern subscription (glob-style) const redisSub2 = new Redis() const redisPub2 = new Redis() redisSub2.on('pmessage', (pattern, channel, message) => { console.log(`pattern=${pattern} channel=${channel} msg=${message}`) // pattern=emails.* channel=emails.urgent msg=batman@wayne.enterprises }) await redisSub2.psubscribe('emails.*') await redisPub2.publish('emails.urgent', 'batman@wayne.enterprises') // Buffer messages are also supported redisSub.on('messageBuffer', (channel, buffer) => { console.log(Buffer.isBuffer(buffer)) // true }) // Cleanup await redisSub.unsubscribe('emails') await redisSub2.punsubscribe('emails.*') redisSub.disconnect() redisSub2.disconnect() ``` -------------------------------- ### Define Custom Lua Commands with ioredis-mock Source: https://github.com/stipsan/ioredis-mock/blob/main/README.md Shows how to define and use custom commands using Lua scripting with `defineCommand`. Ensure the `data` option is used to pre-populate keys if needed. ```javascript const Redis = require('ioredis-mock') const redis = new Redis({ data: { k1: 5 } }) const commandDefinition = { numberOfKeys: 1, lua: 'return redis.call("GET", KEYS[1]) * ARGV[1]', } redis.defineCommand('multiply', commandDefinition) // defineCommand(name, definition) // now we can call our brand new multiply command as an ordinary command redis.multiply('k1', 10).then(result => { expect(result).toBe(5 * 10) }) ``` -------------------------------- ### Browser Usage of ioredis-mock Source: https://context7.com/stipsan/ioredis-mock/llms.txt Use the `browser.js` bundle for browser environments, importable via npm or CDN. It includes Fengari for Lua execution and browser-compatible shims. Pub/Sub is also supported. ```javascript // Via npm package (ES module import) import Redis from 'ioredis-mock/browser.js' // Or via unpkg CDN import Redis from 'https://unpkg.com/ioredis-mock' const redis = new Redis({ data: { counter: '0' }, }) await redis.set('foo', 'bar') console.log(await redis.get('foo')) // 'bar' await redis.incr('counter') console.log(await redis.get('counter')) // '1' // Pub/Sub works in the browser too const sub = new Redis() const pub = new Redis() sub.on('message', (channel, msg) => console.log(channel, msg)) await sub.subscribe('news') await pub.publish('news', 'hello browser!') ``` -------------------------------- ### Key Expiry Management in ioredis-mock Source: https://context7.com/stipsan/ioredis-mock/llms.txt Covers setting and retrieving Time-To-Live (TTL) for keys using seconds, milliseconds, and absolute Unix timestamps. Demonstrates making keys persistent and setting TTL at key creation time. Expired keys are removed upon access. ```javascript const Redis = require('ioredis-mock') const redis = new Redis() await redis.set('token', 'abc123') // Set TTL in seconds await redis.expire('token', 60) console.log(await redis.ttl('token')) // ~60 // Set TTL in milliseconds await redis.pexpire('token', 30000) console.log(await redis.pttl('token')) // ~30000 // Set absolute expiry (Unix timestamp in seconds) const futureTs = Math.floor(Date.now() / 1000) + 120 await redis.expireat('token', futureTs) // Get absolute expiry time console.log(await redis.expiretime('token')) // futureTs // Remove TTL (make persistent) await redis.persist('token') console.log(await redis.ttl('token')) // -1 (no expiry) // Keys can also be set with TTL at creation time await redis.set('session', 'xyz', 'EX', 300) // 300 seconds await redis.set('cache', 'data', 'PX', 5000) // 5000 milliseconds ``` -------------------------------- ### Browser Usage Source: https://context7.com/stipsan/ioredis-mock/llms.txt ioredis-mock includes a pre-built browser bundle (`browser.js`) usable directly in browsers via import or unpkg. The browser build uses Fengari for Lua execution and browser-compatible shims for Node.js built-ins. ```APIDOC ## Browser Usage ### Description ioredis-mock includes a pre-built browser bundle (`browser.js`) usable directly in browsers via import or unpkg. The browser build uses Fengari for Lua execution and browser-compatible shims for Node.js built-ins. ### Usage Example (ES Module Import) ```javascript // Via npm package (ES module import) import Redis from 'ioredis-mock/browser.js' const redis = new Redis({ data: { counter: '0' }, }) await redis.set('foo', 'bar') console.log(await redis.get('foo')) // 'bar' await redis.incr('counter') console.log(await redis.get('counter')) // '1' // Pub/Sub works in the browser too const sub = new Redis() const pub = new Redis() sub.on('message', (channel, msg) => console.log(channel, msg)) await sub.subscribe('news') await pub.publish('news', 'hello browser!') ``` ### Usage Example (unpkg CDN) ```javascript // Or via unpkg CDN import Redis from 'https://unpkg.com/ioredis-mock' const redis = new Redis({ data: { counter: '0' } }) await redis.set('foo', 'bar') console.log(await redis.get('foo')) // 'bar' ``` ``` -------------------------------- ### Sorted Set Commands in ioredis-mock Source: https://context7.com/stipsan/ioredis-mock/llms.txt Demonstrates various sorted set operations including adding members, ranging by index and score, ranking, scoring, incrementing, removing members, and using the NX option for conditional additions. Ensure members are added with scores for proper ordering. ```javascript const Redis = require('ioredis-mock') const redis = new Redis() // Add members with scores await redis.zadd('leaderboard', 100, 'alice', 200, 'bob', 150, 'charlie') // Range by index (ascending by score) console.log(await redis.zrange('leaderboard', 0, -1)) // ['alice', 'charlie', 'bob'] // Range with scores console.log(await redis.zrange('leaderboard', 0, -1, 'WITHSCORES')) // ['alice', '100', 'charlie', '150', 'bob', '200'] // Range by score console.log(await redis.zrangebyscore('leaderboard', 100, 160)) // ['alice', 'charlie'] // Rank (0-based, ascending) console.log(await redis.zrank('leaderboard', 'bob')) // 2 console.log(await redis.zscore('leaderboard', 'bob')) // '200' // Increment score await redis.zincrby('leaderboard', 50, 'alice') console.log(await redis.zscore('leaderboard', 'alice')) // '150' // Remove a member await redis.zrem('leaderboard', 'charlie') console.log(await redis.zcard('leaderboard')) // 2 // NX option — only add new elements, never update await redis.zadd('scores', 'NX', 300, 'alice') // alice already exists — no update console.log(await redis.zscore('scores', 'alice')) // still '150' ``` -------------------------------- ### Keyspace Notifications with ioredis-mock Source: https://context7.com/stipsan/ioredis-mock/llms.txt Enable Redis keyspace notifications using the `notifyKeyspaceEvents` constructor option. The config string format matches Redis (e.g., 'KEA'). Subscribe to specific channels like `__keyspace@0__:mykey` or `__keyevent@0__:set` to receive event messages. ```javascript const Redis = require('ioredis-mock') const publisher = new Redis({ notifyKeyspaceEvents: 'KEA' }) const subscriber = new Redis() // Subscribe to keyspace events for a specific key await subscriber.subscribe('__keyspace@0__:mykey') // Subscribe to keyevent events for SET commands await subscriber.subscribe('__keyevent@0__:set') subscriber.on('message', (channel, message) => { if (channel === '__keyspace@0__:mykey') { console.log(`Key "mykey" had operation: ${message}`) // e.g. "set", "del", "expire" } if (channel === '__keyevent@0__:set') { console.log(`A SET was performed on key: ${message}`) // e.g. "mykey" } }) // This triggers keyspace notifications await publisher.set('mykey', 'hello') await publisher.expire('mykey', 60) await publisher.del('mykey') subscriber.disconnect() publisher.disconnect() ``` -------------------------------- ### Lua Scripting with ioredis-mock Source: https://context7.com/stipsan/ioredis-mock/llms.txt Execute Lua scripts using `eval` for inline scripts or `evalsha` for cached scripts. Scripts use `redis.call()` or `redis.pcall()` to interact with Redis data. `KEYS` and `ARGV` are populated automatically. `defineCommand` registers reusable Lua scripts as custom commands. ```javascript const Redis = require('ioredis-mock') const redis = new Redis() // --- eval: inline Lua script --- await redis.set('KEY1', '10') await redis.set('KEY2', '20') const result = await redis.eval( ` local val1 = redis.call("GET", KEYS[1]) local val2 = redis.call("GET", KEYS[2]) return (val1 + val2) * ARGV[1] + ARGV[2] `, 2, // numberOfKeys 'KEY1', // KEYS[1] 'KEY2', // KEYS[2] 100, // ARGV[1] 5 // ARGV[2] ) console.log(result) // 3005 ((10+20)*100 + 5) ``` ```javascript // --- pcall: ignore errors gracefully --- const safe = await redis.eval( ` local before = redis.pcall('GET', KEYS[1]) redis.pcall('invalid command') return before `, 1, 'KEY1' ) console.log(safe) // '10' ``` ```javascript // --- evalsha: reuse a cached script by SHA1 --- // SHA is stored automatically on first eval call const sha = Object.keys(redis.shaScripts)[0] const result2 = await redis.evalsha(sha, 0) ``` ```javascript // --- defineCommand: register a reusable custom command --- redis.defineCommand('multiply', { numberOfKeys: 1, lua: 'return redis.call("GET", KEYS[1]) * ARGV[1]', }) await redis.set('factor', '5') console.log(await redis.multiply('factor', 10)) // 50 ``` ```javascript // Works in multi and pipeline too const txResult = await redis.multi([['multiply', 'factor', 3]]).exec() console.log(txResult) // [[null, 15]] ``` -------------------------------- ### `duplicate(override?)` — Clone a Client Source: https://context7.com/stipsan/ioredis-mock/llms.txt Creates a new client instance that shares the same in-memory data store. Optionally overrides specific options. Useful for pub/sub patterns where subscriber and publisher must be separate client instances. ```APIDOC ## `duplicate(override?)` — Clone a Client ### Description Creates a new client instance that shares the same in-memory data store (same `host:port/db`). Optionally overrides specific options. Useful for pub/sub patterns where subscriber and publisher must be separate client instances. ### Method Signature `duplicate(override?: object)` ### Parameters * `override` (object, optional) - An object to override specific client options. ### Usage Example ```javascript const Redis = require('ioredis-mock') const redis = new Redis({ lazyConnect: true, db: 1 }) await redis.set('shared', 'value') // Duplicate preserves all options const redis2 = redis.duplicate() console.log(redis2.options.lazyConnect) // true console.log(await redis2.get('shared')) // 'value' — same data store // Duplicate with option override const redis3 = redis.duplicate({ lazyConnect: false }) console.log(redis3.options.lazyConnect) // false // Shared data: writes on one instance are visible on others with same host:port/db await redis.set('counter', '0') await redis2.incr('counter') console.log(await redis.get('counter')) // '1' console.log(await redis2.get('counter')) // '1' redis.disconnect() redis2.disconnect() redis3.disconnect() ``` ``` -------------------------------- ### `Redis.Command` — Command Transformers Source: https://context7.com/stipsan/ioredis-mock/llms.txt Exposes the ioredis `Command` class, which allows registering argument and reply transformers to customize how arguments are serialized before a command is sent, or how results are deserialized after a reply is received. ```APIDOC ## `Redis.Command` — Command Transformers ### Description Exposes the ioredis `Command` class, which allows registering argument and reply transformers to customize how arguments are serialized before a command is sent, or how results are deserialized after a reply is received. ### Methods * `Redis.Command.setReplyTransformer(commandName: string, transformer: function)` - Registers a reply transformer for a given command. * `Redis.Command.setArgumentTransformer(commandName: string, transformer: function)` - Registers an argument transformer for a given command. ### Usage Example (Reply Transformer) ```javascript const Redis = require('ioredis-mock') const redis = new Redis() // Reply transformer: transform hgetall result into an array of [k, v] pairs Redis.Command.setReplyTransformer('hgetall', result => { // result is the raw flat array ['field1', 'val1', 'field2', 'val2', ...] const pairs = [] for (let i = 0; i < result.length; i += 2) { pairs.push([String(result[i]), String(result[i + 1])]) } return pairs }) await redis.hset('user', 'name', 'Alice', 'age', '30') console.log(await redis.hgetall('user')) // [['name', 'Alice'], ['age', '30']] // Clean up delete Redis.Command.transformers.reply.hgetall ``` ### Usage Example (Argument Transformer) ```javascript const Redis = require('ioredis-mock') const redis = new Redis() // Argument transformer: allow passing a plain object to hmset Redis.Command.setArgumentTransformer('hmset', args => { if (args.length === 2 && typeof args[1] === 'object' && !(args[1] instanceof Map)) { return [args[0]].concat([].concat(...Object.entries(args[1]))) } return args }) await redis.hmset('config', { timeout: '30', retries: '3' }) console.log(await redis.hgetall('config')) // { timeout: '30', retries: '3' } delete Redis.Command.transformers.argument.hmset ``` ``` -------------------------------- ### Pub/Sub Source: https://context7.com/stipsan/ioredis-mock/llms.txt Provides full publish/subscribe support using two separate client instances (one for subscribing, one for publishing), mirroring the ioredis pub/sub pattern. Pattern subscriptions using `psubscribe` are also supported. ```APIDOC ## Pub/Sub ### Description Full publish/subscribe support using two separate client instances (one for subscribing, one for publishing), mirroring the ioredis pub/sub pattern. Pattern subscriptions using `psubscribe` are also supported. ### Methods - `subscribe(channel1, ..., channelN)` - `unsubscribe(channel1, ..., channelN)` - `publish(channel, message)` - `psubscribe(pattern1, ..., patternN)` - `punsubscribe(pattern1, ..., patternN)` ### Event Handlers - `message(channel, message)` - `pmessage(pattern, channel, message)` - `messageBuffer(channel, buffer)` ### Example Usage ```js const Redis = require('ioredis-mock') const redisSub = new Redis() const redisPub = new Redis() // Simple channel subscription redisSub.on('message', (channel, message) => { console.log(`[${channel}] ${message}`) // [emails] clark@daily.planet }) await redisSub.subscribe('emails') // Publish a message (returns number of subscribers that received it) const count = await redisPub.publish('emails', 'clark@daily.planet') console.log(count) // 1 // Pattern subscription (glob-style) const redisSub2 = new Redis() const redisPub2 = new Redis() redisSub2.on('pmessage', (pattern, channel, message) => { console.log(`pattern=${pattern} channel=${channel} msg=${message}`) // pattern=emails.* channel=emails.urgent msg=batman@wayne.enterprises }) await redisSub2.psubscribe('emails.*') await redisPub2.publish('emails.urgent', 'batman@wayne.enterprises') // Buffer messages are also supported redisSub.on('messageBuffer', (channel, buffer) => { console.log(Buffer.isBuffer(buffer)) // true }) // Cleanup await redisSub.unsubscribe('emails') await redisSub2.punsubscribe('emails.*') redisSub.disconnect() redisSub2.disconnect() ``` ``` -------------------------------- ### Mock Redis Cluster Instance Source: https://context7.com/stipsan/ioredis-mock/llms.txt Create a mock cluster using `Redis.Cluster` with an array of node connection strings or option objects. The `nodes()` method returns all mocked node instances. This feature is experimental. ```javascript const Redis = require('ioredis-mock') // Create a mock cluster from URL strings const cluster = new Redis.Cluster([ 'redis://localhost:7001', 'redis://localhost:7002', ]) console.log(cluster.connected) // true console.log(cluster.nodes().length) // 2 console.log(cluster.nodes().every(n => n instanceof Redis)) // true // Set and get work normally await cluster.set('key', 'value') console.log(await cluster.get('key')) // 'value' // Pass redisOptions to the underlying mock const lazyCluster = new Redis.Cluster( [{ host: 'localhost', port: 7001 }], { redisOptions: { lazyConnect: true } } ) console.log(lazyCluster.connected) // false ``` -------------------------------- ### Create New In-Memory Redis Client Source: https://context7.com/stipsan/ioredis-mock/llms.txt Instantiate a new in-memory Redis client. Supports various connection signatures and the `data` option for pre-seeding the store. `lazyConnect` defers connection until `redis.connect()` is called. ```javascript const Redis = require('ioredis-mock') // Default connection (localhost:6379, db 0) const redis = new Redis() // With initial seed data const redis2 = new Redis({ data: { user_next: '3', emails: { 'clark@daily.planet': '1', 'bruce@wayne.enterprises': '2', }, 'user:1': { id: '1', username: 'superman', email: 'clark@daily.planet' }, 'user:2': { id: '2', username: 'batman', email: 'bruce@wayne.enterprises' }, }, }) // URL string form const redis3 = new Redis('redis://localhost:6380/1') // Port + host form const redis4 = new Redis(6380, 'localhost') // lazyConnect — does not connect until redis.connect() is called const redis5 = new Redis({ lazyConnect: true }) await redis5.connect() console.log(await redis2.get('user_next')) // '3' redis5.disconnect() ``` -------------------------------- ### Hash Commands: hset, hget, hgetall, hmset, hmget, hdel, hexists, hkeys, hvals, hlen, hincrby Source: https://context7.com/stipsan/ioredis-mock/llms.txt Implementations for Redis hash commands. Hashes map string fields to string values within a single key. Use `hset` for single or multiple fields (Redis 4+), `hmset` with a Map, and `hgetall` to retrieve all fields. ```javascript const Redis = require('ioredis-mock') const redis = new Redis() // Set multiple fields with hset (Redis 4+ variadic form) await redis.hset('user:1', 'name', 'Alice', 'age', '30', 'email', 'alice@example.com') // Alternatively with hmset and a Map await redis.hmset('user:2', new Map([['name', 'Bob'], ['age', '25']])) // Get a single field console.log(await redis.hget('user:1', 'name')) // 'Alice' // Get all fields as an object console.log(await redis.hgetall('user:1')) // { name: 'Alice', age: '30', email: 'alice@example.com' } // Get multiple fields console.log(await redis.hmget('user:1', 'name', 'age', 'missing')) // ['Alice', '30', null] // Check existence and delete console.log(await redis.hexists('user:1', 'email')) // 1 await redis.hdel('user:1', 'email') console.log(await redis.hexists('user:1', 'email')) // 0 // Keys, values, length console.log(await redis.hkeys('user:1')) // ['name', 'age'] console.log(await redis.hvals('user:1')) // ['Alice', '30'] console.log(await redis.hlen('user:1')) // 2 // Atomic increment on a hash field await redis.hincrby('user:1', 'age', 5) console.log(await redis.hget('user:1', 'age')) // '35' ``` -------------------------------- ### Duplicate Redis Client Instance Source: https://context7.com/stipsan/ioredis-mock/llms.txt Use `duplicate()` to create a new client instance that shares the same in-memory data store. This is useful for pub/sub patterns. Options can be overridden during duplication. ```javascript const Redis = require('ioredis-mock') const redis = new Redis({ lazyConnect: true, db: 1 }) await redis.set('shared', 'value') // Duplicate preserves all options const redis2 = redis.duplicate() console.log(redis2.options.lazyConnect) // true console.log(await redis2.get('shared')) // 'value' — same data store // Duplicate with option override const redis3 = redis.duplicate({ lazyConnect: false }) console.log(redis3.options.lazyConnect) // false // Shared data: writes on one instance are visible on others with same host:port/db await redis.set('counter', '0') await redis2.incr('counter') console.log(await redis.get('counter')) // '1' console.log(await redis2.get('counter')) // '1' redis.disconnect() redis2.disconnect() redis3.disconnect() ``` -------------------------------- ### Hash Commands Source: https://context7.com/stipsan/ioredis-mock/llms.txt Full implementation of Redis hash commands. Hashes map string fields to string values within a single key. ```APIDOC ## Hash Commands ### Description Full implementation of Redis hash commands. Hashes map string fields to string values within a single key. ### Methods - `hset(key, field, value, ...)`: Sets multiple fields in a hash. Supports variadic form for Redis 4+. - `hmset(key, fields)`: Sets multiple fields in a hash using a Map. - `hget(key, field)`: Gets the value of a single field in a hash. - `hgetall(key)`: Gets all fields and values in a hash. - `hmget(key, field1, ...)`: Gets the values of multiple fields in a hash. - `hexists(key, field)`: Checks if a field exists in a hash. - `hdel(key, field, ...)`: Deletes one or more fields from a hash. - `hkeys(key)`: Gets all field names in a hash. - `hvals(key)`: Gets all values in a hash. - `hlen(key)`: Gets the number of fields in a hash. - `hincrby(key, field, increment)`: Atomically increments the value of a hash field by the given number. ``` -------------------------------- ### Set Commands Source: https://context7.com/stipsan/ioredis-mock/llms.txt Complete Redis set operations including membership tests, cardinality, remove, pop, and set algebra (union, intersection, difference). ```APIDOC ## Set Commands ### Description Complete Redis set operations including membership tests, cardinality, remove, pop, and set algebra (union, intersection, difference). ### Methods - `sadd(key, member, ...)`: Adds one or more members to a set. - `smembers(key)`: Gets all members of a set. - `sismember(key, member)`: Checks if a member is part of a set. - `scard(key)`: Gets the number of members in a set. - `srem(key, member, ...)`: Removes one or more members from a set. - `sunion(key1, ...)`: Gets the union of multiple sets. - `sinter(key1, ...)`: Gets the intersection of multiple sets. - `sdiff(key1, ...)`: Gets the difference between multiple sets. - `srandmember(key, [count])`: Gets one or more random members from a set. - `spop(key)`: Removes and returns a random member from a set. ``` -------------------------------- ### Execute Lua Scripts Directly with eval Source: https://github.com/stipsan/ioredis-mock/blob/main/README.md Illustrates executing Lua scripts directly using the `eval` command. This method is useful for one-off script executions without defining a custom command. ```javascript const Redis = require('ioredis-mock') const redis = new Redis({ data: { k1: 5 } }) const result = redis.eval(`return redis.call("GET", "k1") * 10`) expect(result).toBe(5 * 10) ``` -------------------------------- ### Pipelines - pipeline, exec Source: https://context7.com/stipsan/ioredis-mock/llms.txt Pipelines batch multiple commands and send them all at once, returning an array of [error, result] pairs. Unlike transactions, pipelines are not atomic but are more efficient for bulk operations. Pipelines can be chained or initiated with a batch array. ```APIDOC ## Pipelines — `pipeline`, `exec` Pipelines batch multiple commands and send them all at once, returning an array of `[error, result]` pairs. Unlike transactions, pipelines are not atomic but are more efficient for bulk operations. ```js const Redis = require('ioredis-mock') const redis = new Redis() // Chained pipeline const results = await redis .pipeline() .set('a', '1') .set('b', '2') .get('a') .get('b') .incr('a') .exec() console.log(results) // [ // [null, 'OK'], // [null, 'OK'], // [null, '1'], // [null, '2'], // [null, 2], // ] // pipeline() also accepts a batch array const results2 = await redis.pipeline([ ['hset', 'user', 'name', 'Alice'], ['hget', 'user', 'name'], ]).exec() console.log(results2) // [ [null, 1], [null, 'Alice'] ] // Check pipeline length before executing const pipe = redis.pipeline() pipe.set('k1', 'v1') pipe.set('k2', 'v2') console.log(pipe.length) // 2 await pipe.exec() ``` ``` -------------------------------- ### Set Commands: sadd, smembers, sismember, scard, srem, sunion, sinter, sdiff, srandmember, spop Source: https://context7.com/stipsan/ioredis-mock/llms.txt Complete Redis set operations including membership tests, cardinality, remove, pop, and set algebra (union, intersection, difference). Note that `smembers` returns a Set, and order is not guaranteed. ```javascript const Redis = require('ioredis-mock') const redis = new Redis() await redis.sadd('fruits', 'apple', 'banana', 'cherry') await redis.sadd('tropical', 'banana', 'mango', 'papaya') // Check membership and size console.log(await redis.sismember('fruits', 'apple')) // 1 console.log(await redis.sismember('fruits', 'mango')) // 0 console.log(await redis.scard('fruits')) // 3 // All members const members = await redis.smembers('fruits') // Set of ['apple', 'banana', 'cherry'] (order not guaranteed) // Remove member await redis.srem('fruits', 'cherry') console.log(await redis.scard('fruits')) // 2 // Set algebra console.log(await redis.sunion('fruits', 'tropical')) // ['apple', 'banana', 'mango', 'papaya'] console.log(await redis.sinter('fruits', 'tropical')) // ['banana'] console.log(await redis.sdiff('fruits', 'tropical')) // ['apple'] // Random member and pop const rand = await redis.srandmember('fruits') // random member, non-destructive const popped = await redis.spop('fruits') // random member, removes it ``` -------------------------------- ### Keyspace Notifications - notifyKeyspaceEvents option Source: https://context7.com/stipsan/ioredis-mock/llms.txt Enables Redis keyspace notification events via the `notifyKeyspaceEvents` constructor option. The config string follows the same format as Redis: `K` (keyspace), `E` (keyevent), and event type flags. The alias `A` expands to all event types. ```APIDOC ## Keyspace Notifications — `notifyKeyspaceEvents` option Enables Redis keyspace notification events via the `notifyKeyspaceEvents` constructor option. The config string follows the same format as Redis: `K` (keyspace), `E` (keyevent), and event type flags (`g`, `$`, `l`, `s`, `h`, `z`, `x`, `e`). The alias `A` expands to all event types. ```js const Redis = require('ioredis-mock') const publisher = new Redis({ notifyKeyspaceEvents: 'KEA' }) const subscriber = new Redis() // Subscribe to keyspace events for a specific key await subscriber.subscribe('__keyspace@0__:mykey') // Subscribe to keyevent events for SET commands await subscriber.subscribe('__keyevent@0__:set') subscriber.on('message', (channel, message) => { if (channel === '__keyspace@0__:mykey') { console.log(`Key "mykey" had operation: ${message}`) // e.g. "set", "del", "expire" } if (channel === '__keyevent@0__:set') { console.log(`A SET was performed on key: ${message}`) // e.g. "mykey" } }) // This triggers keyspace notifications await publisher.set('mykey', 'hello') await publisher.expire('mykey', 60) await publisher.del('mykey') subscriber.disconnect() publisher.disconnect() ``` ``` -------------------------------- ### Transactions - multi, exec, discard Source: https://context7.com/stipsan/ioredis-mock/llms.txt Supports atomic transactions using MULTI/EXEC. All queued commands execute atomically, and results are returned as an array of [error, result] pairs. Transactions can also be initiated with a batch array of commands. ```APIDOC ## Transactions — `multi`, `exec`, `discard` Atomic transaction support using `MULTI`/`EXEC`. All queued commands execute atomically and results are returned as an array of `[error, result]` pairs. ```js const Redis = require('ioredis-mock') const redis = new Redis() await redis.set('balance', '100') // Queue commands in a transaction const results = await redis .multi() .get('balance') .incrby('balance', 50) .set('audit', 'deposit:50') .exec() console.log(results) // [ [null, '100'], [null, 150], [null, 'OK'] ] // multi() also accepts a batch array const results2 = await redis.multi([ ['set', 'x', '1'], ['incr', 'x'], ['get', 'x'], ]).exec() console.log(results2) // [ [null, 'OK'], [null, 2], [null, '2'] ] // WATCH / optimistic locking: if a watched key is modified before EXEC, // the transaction returns null const redis2 = new Redis() await redis2.watch('balance') await redis2.set('balance', '999') // modify watched key from another "client" (same context) const txResult = await redis2.multi().get('balance').exec() console.log(txResult) // null — transaction was aborted ``` ```