diff --git a/README.md b/README.md
index 82c03957..a4a04d08 100644
--- a/README.md
+++ b/README.md
@@ -14,7 +14,7 @@
Nest Redis Module
- Redis(ioredis) module for Nest framework (node.js).
+ Redis(ioredis & node-redis) module for Nest framework (node.js).
Explore the docs ยป
@@ -76,8 +76,12 @@ This lib requires **Node.js >=16.13.0**, **NestJS ^10.0.0**, **ioredis ^5.0.0**.
- If you depend on **ioredis 5** & **NestJS 10**, please use version **10** of the lib.
- If you depend on **ioredis 5** & **NestJS 9**, please use version **9** of the lib.
-- If you depend on **ioredis 4**, please use [version 7](https://github.com/liaoliaots/nestjs-redis/tree/v7.0.0) of the lib.
- If you depend on **ioredis 5**, **NestJS 7** or **8**, please use [version 8](https://github.com/liaoliaots/nestjs-redis/tree/v8.2.2) of the lib.
+- If you depend on **ioredis 4**, please use [version 7](https://github.com/liaoliaots/nestjs-redis/tree/v7.0.0) of the lib.
+
+### Node-Redis
+
+If you prefre [node-redis](https://github.com/redis/node-redis), check out [this guide](), but it is in working progress.
### Installation
diff --git a/docs/v9/cluster.md b/docs/v9/cluster.md
new file mode 100644
index 00000000..635f078a
--- /dev/null
+++ b/docs/v9/cluster.md
@@ -0,0 +1,359 @@
+## Usage
+
+**First**, we need to import the `ClusterModule` into our root module:
+
+```ts
+import { Module } from '@nestjs/common';
+import { ClusterModule } from '@liaoliaots/nestjs-redis';
+
+@Module({
+ imports: [
+ ClusterModule.forRoot({
+ config: {
+ nodes: [{ host: 'localhost', port: 16380 }],
+ redisOptions: { password: 'authpassword' }
+ }
+ })
+ ]
+})
+export class AppModule {}
+```
+
+**Now**, we can use cluster in two ways.
+
+via decorator:
+
+```ts
+import { Injectable } from '@nestjs/common';
+import { InjectCluster, DEFAULT_CLUSTER_NAMESPACE } from '@liaoliaots/nestjs-redis';
+import { Cluster } from 'ioredis';
+
+@Injectable()
+export class AppService {
+ constructor(
+ @InjectCluster() private readonly cluster: Cluster // or // @InjectCluster(DEFAULT_CLUSTER_NAMESPACE) private readonly cluster: Cluster
+ ) {}
+
+ async set() {
+ return await this.cluster.set('key', 'value', 'EX', 10);
+ }
+}
+```
+
+via service:
+
+```ts
+import { Injectable } from '@nestjs/common';
+import { ClusterService, DEFAULT_CLUSTER_NAMESPACE } from '@liaoliaots/nestjs-redis';
+import { Cluster } from 'ioredis';
+
+@Injectable()
+export class AppService {
+ private readonly cluster: Cluster;
+
+ constructor(private readonly clusterService: ClusterService) {
+ this.cluster = this.clusterService.getClient();
+ // or
+ // this.cluster = this.clusterService.getClient(DEFAULT_CLUSTER_NAMESPACE);
+ }
+
+ async set() {
+ return await this.cluster.set('key', 'value', 'EX', 10);
+ }
+}
+```
+
+> HINT: By default, the `ClusterModule` is a [**Global module**](https://docs.nestjs.com/modules#global-modules).
+
+> HINT: If you don't set the `namespace` for a client, its namespace is set to `"default"`. Please note that you shouldn't have multiple client without a namespace, or with the same namespace, otherwise they will get overridden.
+
+## Configuration
+
+### [ClusterModuleOptions](/packages/redis/lib/cluster/interfaces/cluster-module-options.interface.ts)
+
+| Name | Type | Default | Required | Description |
+| ----------- | -------------------------------------------------- | ----------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| closeClient | `boolean` | `true` | `false` | If set to `true`, all clients will be closed automatically on nestjs application shutdown. To use `closeClient`, you **must enable listeners** by calling `app.enableShutdownHooks()`. [Read more about the application shutdown.](https://docs.nestjs.com/fundamentals/lifecycle-events#application-shutdown) |
+| readyLog | `boolean` | `false` | `false` | If set to `true`, then ready logging will be displayed when the client is ready. |
+| errorLog | `boolean` | `true` | `false` | If set to `true`, then errors that occurred while connecting will be displayed by the built-in logger. |
+| config | `ClusterClientOptions` \| `ClusterClientOptions`[] | `undefined` | `true` | Used to specify single or multiple clients. |
+
+### [ClusterClientOptions](/packages/redis/lib/cluster/interfaces/cluster-module-options.interface.ts)
+
+| Name | Type | Default | Required | Description |
+| ---------------------- | ---------------------------------------------------------------- | ----------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| namespace | `string` \| `symbol` | `'default'` | `false` | Client name. If client name is not given then it will be called "default". Different clients must have different names. You can import `DEFAULT_CLUSTER_NAMESPACE` to use it. |
+| nodes | `{ host?: string; port?: number }[]` \| `string[]` \| `number[]` | `undefined` | `true` | List of cluster nodes. |
+| onClientCreated | `function` | `undefined` | `false` | Function to be executed as soon as the client is created. |
+| **...** ClusterOptions | `ClusterOptions` | - | `false` | Inherits from [ClusterOptions](https://luin.github.io/ioredis/interfaces/ClusterOptions.html). |
+
+### Asynchronous configuration
+
+via `useFactory`:
+
+```ts
+import { Module } from '@nestjs/common';
+import { ClusterModule, ClusterModuleOptions } from '@liaoliaots/nestjs-redis';
+import { ConfigService, ConfigModule } from '@nestjs/config';
+
+@Module({
+ imports: [
+ ClusterModule.forRootAsync({
+ imports: [ConfigModule],
+ inject: [ConfigService],
+ useFactory: async (configService: ConfigService): Promise => {
+ await somePromise();
+
+ return {
+ config: {
+ nodes: [{ host: 'localhost', port: 16380 }],
+ redisOptions: { password: 'authpassword' }
+ }
+ };
+ }
+ })
+ ]
+})
+export class AppModule {}
+```
+
+via `useClass`:
+
+```ts
+import { Module, Injectable } from '@nestjs/common';
+import { ClusterModule, ClusterOptionsFactory, ClusterModuleOptions } from '@liaoliaots/nestjs-redis';
+
+@Injectable()
+export class ClusterConfigService implements ClusterOptionsFactory {
+ async createClusterOptions(): Promise {
+ await somePromise();
+
+ return {
+ config: {
+ nodes: [{ host: 'localhost', port: 16380 }],
+ redisOptions: { password: 'authpassword' }
+ }
+ };
+ }
+}
+
+@Module({
+ imports: [
+ ClusterModule.forRootAsync({
+ useClass: ClusterConfigService
+ })
+ ]
+})
+export class AppModule {}
+```
+
+via `extraProviders`:
+
+```ts
+// just a simple example
+
+import { Module, ValueProvider } from '@nestjs/common';
+import { ClusterModule, ClusterModuleOptions } from '@liaoliaots/nestjs-redis';
+
+const MyOptionsSymbol = Symbol('options');
+const MyOptionsProvider: ValueProvider = {
+ provide: MyOptionsSymbol,
+ useValue: {
+ config: {
+ nodes: [{ host: 'localhost', port: 16380 }],
+ redisOptions: { password: 'authpassword' }
+ }
+ }
+};
+
+@Module({
+ imports: [
+ ClusterModule.forRootAsync({
+ useFactory(options: ClusterModuleOptions) {
+ return options;
+ },
+ inject: [MyOptionsSymbol],
+ extraProviders: [MyOptionsProvider]
+ })
+ ]
+})
+export class AppModule {}
+```
+
+... or via `useExisting`, if you wish to use an existing configuration provider imported from a different module.
+
+```ts
+ClusterModule.forRootAsync({
+ imports: [ConfigModule],
+ useExisting: ConfigService
+});
+```
+
+### readyLog
+
+```ts
+import { Module } from '@nestjs/common';
+import { ClusterModule } from '@liaoliaots/nestjs-redis';
+
+@Module({
+ imports: [
+ ClusterModule.forRoot({
+ readyLog: true,
+ config: {
+ nodes: [{ host: 'localhost', port: 16380 }],
+ redisOptions: { password: 'authpassword' }
+ }
+ })
+ ]
+})
+export class AppModule {}
+```
+
+The `ClusterModule` will display a message when `CLUSTER INFO` reporting the cluster is able to receive commands.
+
+```sh
+[Nest] 18886 - 09/16/2021, 6:19:56 PM LOG [ClusterModule] default: connected successfully to the server
+```
+
+### Single client
+
+```ts
+import { Module } from '@nestjs/common';
+import { ClusterModule } from '@liaoliaots/nestjs-redis';
+
+@Module({
+ imports: [
+ ClusterModule.forRoot({
+ config: {
+ nodes: [{ host: 'localhost', port: 16380 }],
+ redisOptions: { password: 'authpassword' }
+
+ // or with URL
+ // nodes: ['redis://:authpassword@localhost:16380']
+ }
+ })
+ ]
+})
+export class AppModule {}
+```
+
+### Multiple clients
+
+```ts
+import { Module } from '@nestjs/common';
+import { ClusterModule } from '@liaoliaots/nestjs-redis';
+
+@Module({
+ imports: [
+ ClusterModule.forRoot({
+ config: [
+ {
+ nodes: [{ host: 'localhost', port: 16380 }],
+ redisOptions: { password: 'authpassword' }
+ },
+ {
+ namespace: 'cluster2',
+ nodes: [{ host: 'localhost', port: 16480 }],
+ redisOptions: { password: 'authpassword' }
+ }
+ ]
+ })
+ ]
+})
+export class AppModule {}
+```
+
+with URL:
+
+```ts
+import { Module } from '@nestjs/common';
+import { ClusterModule } from '@liaoliaots/nestjs-redis';
+
+@Module({
+ imports: [
+ ClusterModule.forRoot({
+ config: [
+ {
+ nodes: ['redis://:authpassword@localhost:16380']
+ },
+ {
+ namespace: 'cluster2',
+ nodes: ['redis://:authpassword@localhost:16480']
+ }
+ ]
+ })
+ ]
+})
+export class AppModule {}
+```
+
+### onClientCreated
+
+For example, we can listen to some events of the cluster instance.
+
+```ts
+import { Module } from '@nestjs/common';
+import { ClusterModule } from '@liaoliaots/nestjs-redis';
+
+@Module({
+ imports: [
+ ClusterModule.forRoot({
+ config: {
+ nodes: [{ host: 'localhost', port: 16380 }],
+ redisOptions: { password: 'authpassword' },
+ onClientCreated(client) {
+ client.on('error', err => {});
+ client.on('ready', () => {});
+ }
+ }
+ })
+ ]
+})
+export class AppModule {}
+```
+
+### Non-Global
+
+By default, the `ClusterModule` is a **Global module**, `ClusterService` and all cluster instances are registered in the global scope. Once defined, they're available everywhere.
+
+You can change this behavior by `isGlobal` parameter:
+
+```ts
+// cats.module.ts
+import { Module } from '@nestjs/common';
+import { ClusterModule } from '@liaoliaots/nestjs-redis';
+import { CatsService } from './cats.service';
+import { CatsController } from './cats.controller';
+
+@Module({
+ imports: [
+ ClusterModule.forRoot(
+ {
+ config: {
+ nodes: [{ host: 'localhost', port: 16380 }],
+ redisOptions: { password: 'authpassword' }
+ }
+ },
+ false // <-- providers are registered in the module scope
+ )
+ ],
+ providers: [CatsService],
+ controllers: [CatsController]
+})
+export class CatsModule {}
+```
+
+### Testing
+
+This package exposes `getClusterToken()` function that returns an internal injection token based on the provided context. Using this token, you can provide a mock implementation of the cluster instance using any of the standard custom provider techniques, including `useClass`, `useValue`, and `useFactory`.
+
+```ts
+import { Test, TestingModule } from '@nestjs/testing';
+import { getRedisToken } from '@liaoliaots/nestjs-redis';
+
+const module: TestingModule = await Test.createTestingModule({
+ providers: [{ provide: getClusterToken('namespace'), useValue: mockedInstance }, YourService]
+}).compile();
+```
+
+A working example is available [here](/sample).
diff --git a/docs/v9/examples.md b/docs/v9/examples.md
new file mode 100644
index 00000000..20081c0b
--- /dev/null
+++ b/docs/v9/examples.md
@@ -0,0 +1,57 @@
+## Redis
+
+### Sentinel
+
+| name | address | port | password |
+| ---------------------- | --------- | ---- | ----------- |
+| master | localhost | 6380 | my_password |
+| slave1 | localhost | 6480 | my_password |
+| slave2 | localhost | 6481 | my_password |
+| sentinel1 (`mymaster`) | localhost | 7380 | sentinel |
+| sentinel2 (`mymaster`) | localhost | 7381 | sentinel |
+
+> INFO: Read more about ioredis sentinel [here](https://github.com/luin/ioredis#sentinel).
+
+> HINT: When using Sentinel in Master-Slave setup, if you want to set the passwords for Master and Slave nodes, consider having the same password for them ([#7292](https://github.com/redis/redis/issues/7292)).
+
+```ts
+// app.module.ts
+import { Module } from '@nestjs/common';
+import { RedisModule } from '@liaoliaots/nestjs-redis';
+
+@Module({
+ imports: [
+ RedisModule.forRoot({
+ readyLog: true,
+ commonOptions: {
+ name: 'mymaster',
+ sentinels: [
+ {
+ host: 'localhost',
+ port: 7380
+ },
+ {
+ host: 'localhost',
+ port: 7381
+ }
+ ],
+ sentinelPassword: 'sentinel',
+ password: 'my_password'
+ },
+ config: [
+ {
+ // get master node from the sentinel group
+ role: 'master',
+ namespace: "I'm master"
+ },
+ {
+ // get a random slave node from the sentinel group
+ role: 'slave',
+ namespace: "I'm slave"
+ }
+ ]
+ })
+ ]
+})
+export class AppModule {}
+```
diff --git a/docs/v9/redis.md b/docs/v9/redis.md
new file mode 100644
index 00000000..9db5898c
--- /dev/null
+++ b/docs/v9/redis.md
@@ -0,0 +1,514 @@
+## Usage
+
+**First**, we need to import the `RedisModule` into our root module:
+
+```ts
+import { Module } from '@nestjs/common';
+import { RedisModule } from '@liaoliaots/nestjs-redis';
+
+@Module({
+ imports: [
+ RedisModule.forRoot({
+ config: {
+ host: 'localhost',
+ port: 6379,
+ password: 'authpassword'
+ }
+ })
+ ]
+})
+export class AppModule {}
+```
+
+**Now**, we can use redis in two ways.
+
+via decorator:
+
+```ts
+import { Injectable } from '@nestjs/common';
+import { InjectRedis, DEFAULT_REDIS_NAMESPACE } from '@liaoliaots/nestjs-redis';
+import Redis from 'ioredis';
+
+@Injectable()
+export class AppService {
+ constructor(
+ @InjectRedis() private readonly redis: Redis // or // @InjectRedis(DEFAULT_REDIS_NAMESPACE) private readonly redis: Redis
+ ) {}
+
+ async set() {
+ return await this.redis.set('key', 'value', 'EX', 10);
+ }
+}
+```
+
+via service:
+
+```ts
+import { Injectable } from '@nestjs/common';
+import { RedisService, DEFAULT_REDIS_NAMESPACE } from '@liaoliaots/nestjs-redis';
+import Redis from 'ioredis';
+
+@Injectable()
+export class AppService {
+ private readonly redis: Redis;
+
+ constructor(private readonly redisService: RedisService) {
+ this.redis = this.redisService.getClient();
+ // or
+ // this.redis = this.redisService.getClient(DEFAULT_REDIS_NAMESPACE);
+ }
+
+ async set() {
+ return await this.redis.set('key', 'value', 'EX', 10);
+ }
+}
+```
+
+> HINT: By default, the `RedisModule` is a [**Global module**](https://docs.nestjs.com/modules#global-modules).
+
+> HINT: If you don't set the `namespace` for a client, its namespace is set to `"default"`. Please note that you shouldn't have multiple client without a namespace, or with the same namespace, otherwise they will get overridden.
+
+### Use with other libs
+
+```ts
+// an example
+import { Module } from '@nestjs/common';
+import { RedisModule, RedisService } from '@liaoliaots/nestjs-redis';
+import { ThrottlerModule } from '@nestjs/throttler';
+import { ThrottlerStorageRedisService } from 'nestjs-throttler-storage-redis';
+
+@Module({
+ imports: [
+ RedisModule.forRoot({
+ config: {
+ host: 'localhost',
+ port: 6379,
+ password: 'authpassword'
+ }
+ }),
+ ThrottlerModule.forRootAsync({
+ useFactory(redisService: RedisService) {
+ const redis = redisService.getClient();
+ return { ttl: 60, limit: 600, storage: new ThrottlerStorageRedisService(redis, 1000) };
+ },
+ inject: [RedisService]
+ })
+ ]
+})
+export class AppModule {}
+```
+
+## Configuration
+
+### [RedisModuleOptions](/packages/redis/lib/redis/interfaces/redis-module-options.interface.ts)
+
+| Name | Type | Default | Required | Description |
+| ------------- | ---------------------------------------------------------------------- | ----------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| closeClient | `boolean` | `true` | `false` | If set to `true`, all clients will be closed automatically on nestjs application shutdown. To use `closeClient`, you **must enable listeners** by calling `app.enableShutdownHooks()`. [Read more about the application shutdown.](https://docs.nestjs.com/fundamentals/lifecycle-events#application-shutdown) |
+| commonOptions | [RedisOptions](https://luin.github.io/ioredis/index.html#RedisOptions) | `undefined` | `false` | Common options to be passed to each client. |
+| readyLog | `boolean` | `false` | `false` | If set to `true`, then ready logging will be displayed when the client is ready. |
+| errorLog | `boolean` | `true` | `false` | If set to `true`, then errors that occurred while connecting will be displayed by the built-in logger. |
+| config | `RedisClientOptions` \| `RedisClientOptions`[] | `undefined` | `false` | Used to specify single or multiple clients. |
+
+### [RedisClientOptions](/packages/redis/lib/redis/interfaces/redis-module-options.interface.ts)
+
+| Name | Type | Default | Required | Description |
+| -------------------- | -------------------- | ----------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| namespace | `string` \| `symbol` | `'default'` | `false` | Client name. If client name is not given then it will be called `"default"`. Different clients must have different names. You can import `DEFAULT_REDIS_NAMESPACE` to use it. |
+| url | `string` | `undefined` | `false` | URI scheme to be used to specify connection options as a [redis://](https://www.iana.org/assignments/uri-schemes/prov/redis) URL or [rediss://](https://www.iana.org/assignments/uri-schemes/prov/rediss) URL. |
+| path | `string` | `undefined` | `false` | Path to be used for Unix domain sockets. |
+| onClientCreated | `function` | `undefined` | `false` | Function to be executed as soon as the client is created. |
+| **...** RedisOptions | `RedisOptions` | - | `false` | Inherits from [RedisOptions](https://luin.github.io/ioredis/index.html#RedisOptions). |
+
+### Asynchronous configuration
+
+via `useFactory`:
+
+```ts
+import { Module } from '@nestjs/common';
+import { RedisModule, RedisModuleOptions } from '@liaoliaots/nestjs-redis';
+import { ConfigService, ConfigModule } from '@nestjs/config';
+
+@Module({
+ imports: [
+ RedisModule.forRootAsync({
+ imports: [ConfigModule],
+ inject: [ConfigService],
+ useFactory: async (configService: ConfigService): Promise => {
+ await somePromise();
+
+ return {
+ config: {
+ host: 'localhost',
+ port: 6379,
+ password: 'authpassword'
+ }
+ };
+ }
+ })
+ ]
+})
+export class AppModule {}
+```
+
+via `useClass`:
+
+```ts
+import { Module, Injectable } from '@nestjs/common';
+import { RedisModule, RedisOptionsFactory, RedisModuleOptions } from '@liaoliaots/nestjs-redis';
+
+@Injectable()
+export class RedisConfigService implements RedisOptionsFactory {
+ async createRedisOptions(): Promise {
+ await somePromise();
+
+ return {
+ config: {
+ host: 'localhost',
+ port: 6379,
+ password: 'authpassword'
+ }
+ };
+ }
+}
+
+@Module({
+ imports: [
+ RedisModule.forRootAsync({
+ useClass: RedisConfigService
+ })
+ ]
+})
+export class AppModule {}
+```
+
+via `extraProviders`:
+
+```ts
+// an example
+
+import { Module, ValueProvider } from '@nestjs/common';
+import { RedisModule, RedisModuleOptions } from '@liaoliaots/nestjs-redis';
+
+const MyOptionsSymbol = Symbol('options');
+const MyOptionsProvider: ValueProvider = {
+ provide: MyOptionsSymbol,
+ useValue: {
+ config: {
+ host: 'localhost',
+ port: 6379,
+ password: 'authpassword'
+ }
+ }
+};
+
+@Module({
+ imports: [
+ RedisModule.forRootAsync({
+ useFactory(options: RedisModuleOptions) {
+ return options;
+ },
+ inject: [MyOptionsSymbol],
+ extraProviders: [MyOptionsProvider]
+ })
+ ]
+})
+export class AppModule {}
+```
+
+... or via `useExisting`, if you wish to use an existing configuration provider imported from a different module.
+
+```ts
+RedisModule.forRootAsync({
+ imports: [ConfigModule],
+ useExisting: ConfigService
+});
+```
+
+### readyLog
+
+```ts
+import { Module } from '@nestjs/common';
+import { RedisModule } from '@liaoliaots/nestjs-redis';
+
+@Module({
+ imports: [
+ RedisModule.forRoot({
+ readyLog: true,
+ config: {
+ host: 'localhost',
+ port: 6379,
+ password: 'authpassword'
+ }
+ })
+ ]
+})
+export class AppModule {}
+```
+
+The `RedisModule` will display a message when the server reports that it is ready to receive commands.
+
+```sh
+[Nest] 17581 - 09/16/2021, 6:03:35 PM LOG [RedisModule] default: connected successfully to the server
+```
+
+### Single client
+
+```ts
+import { Module } from '@nestjs/common';
+import { RedisModule } from '@liaoliaots/nestjs-redis';
+
+@Module({
+ imports: [
+ RedisModule.forRoot({
+ config: {
+ host: 'localhost',
+ port: 6379,
+ password: 'authpassword'
+
+ // or with URL
+ // url: 'redis://:authpassword@localhost:6379/0'
+ }
+ })
+ ]
+})
+export class AppModule {}
+```
+
+### Multiple clients
+
+```ts
+import { Module } from '@nestjs/common';
+import { RedisModule } from '@liaoliaots/nestjs-redis';
+
+@Module({
+ imports: [
+ RedisModule.forRoot({
+ config: [
+ {
+ host: 'localhost',
+ port: 6379,
+ password: 'authpassword'
+ },
+ {
+ namespace: 'master2',
+ host: 'localhost',
+ port: 6380,
+ password: 'authpassword'
+ }
+ ]
+ })
+ ]
+})
+export class AppModule {}
+```
+
+with URL:
+
+```ts
+import { Module } from '@nestjs/common';
+import { RedisModule } from '@liaoliaots/nestjs-redis';
+
+@Module({
+ imports: [
+ RedisModule.forRoot({
+ config: [
+ {
+ url: 'redis://:authpassword@localhost:6379/0'
+ },
+ {
+ namespace: 'master2',
+ url: 'redis://:authpassword@localhost:6380/0'
+ }
+ ]
+ })
+ ]
+})
+export class AppModule {}
+```
+
+### commonOptions
+
+**In some cases**, you can move the same config of multiple clients to `commonOptions`.
+
+> HINT: The `commonOptions` option works only with multiple clients.
+
+```ts
+import { Module } from '@nestjs/common';
+import { RedisModule } from '@liaoliaots/nestjs-redis';
+
+@Module({
+ imports: [
+ RedisModule.forRoot({
+ commonOptions: {
+ enableAutoPipelining: true
+ },
+ config: [
+ {
+ host: 'localhost',
+ port: 6379,
+ password: 'authpassword'
+ },
+ {
+ namespace: 'master2',
+ host: 'localhost',
+ port: 6380,
+ password: 'authpassword'
+ }
+ ]
+ })
+ ]
+})
+export class AppModule {}
+```
+
+You can also override the `commonOptions`:
+
+```ts
+import { Module } from '@nestjs/common';
+import { RedisModule } from '@liaoliaots/nestjs-redis';
+
+@Module({
+ imports: [
+ RedisModule.forRoot({
+ commonOptions: {
+ enableAutoPipelining: true
+ },
+ config: [
+ {
+ host: 'localhost',
+ port: 6379,
+ password: 'authpassword'
+ },
+ {
+ namespace: 'master2',
+ host: 'localhost',
+ port: 6380,
+ password: 'authpassword',
+ enableAutoPipelining: false
+ }
+ ]
+ })
+ ]
+})
+export class AppModule {}
+```
+
+### onClientCreated
+
+For example, we can listen to some events of the redis instance.
+
+```ts
+import { Module } from '@nestjs/common';
+import { RedisModule } from '@liaoliaots/nestjs-redis';
+
+@Module({
+ imports: [
+ RedisModule.forRoot({
+ config: {
+ host: 'localhost',
+ port: 6379,
+ password: 'authpassword',
+ onClientCreated(client) {
+ client.on('error', err => {});
+ client.on('ready', () => {});
+ }
+ }
+ })
+ ]
+})
+export class AppModule {}
+```
+
+### Non-Global
+
+By default, the `RedisModule` is a **Global module**, `RedisService` and all redis instances are registered in the global scope. Once defined, they're available everywhere.
+
+You can change this behavior by `isGlobal` parameter:
+
+```ts
+// cats.module.ts
+import { Module } from '@nestjs/common';
+import { RedisModule } from '@liaoliaots/nestjs-redis';
+import { CatsService } from './cats.service';
+import { CatsController } from './cats.controller';
+
+@Module({
+ imports: [
+ RedisModule.forRoot(
+ {
+ config: {
+ host: 'localhost',
+ port: 6379,
+ password: 'authpassword'
+ }
+ },
+ false // <-- providers are registered in the module scope
+ )
+ ],
+ providers: [CatsService],
+ controllers: [CatsController]
+})
+export class CatsModule {}
+```
+
+### Unix domain socket
+
+**1**, open your **_redis.conf_** in a text editor and scroll down until you get to the unix socket section:
+
+```
+# Unix socket.
+#
+# Specify the path for the Unix socket that will be used to listen for
+# incoming connections. There is no default, so Redis will not listen
+# on a unix socket when not specified.
+#
+# unixsocket /run/redis.sock
+# unixsocketperm 700
+```
+
+**2**, uncomment these lines, now look like this:
+
+```
+# create a unix domain socket
+unixsocket /run/redis.sock
+# set permissions to 777
+unixsocketperm 777
+```
+
+**3**, save and exit, then restart your redis server.
+
+**4**, let's setup our application:
+
+```ts
+import { Module } from '@nestjs/common';
+import { RedisModule } from '@liaoliaots/nestjs-redis';
+
+@Module({
+ imports: [
+ RedisModule.forRoot({
+ config: {
+ path: '/run/redis.sock'
+ }
+ })
+ ]
+})
+export class AppModule {}
+```
+
+And there we go.
+
+### Testing
+
+This package exposes `getRedisToken()` function that returns an internal injection token based on the provided context. Using this token, you can provide a mock implementation of the redis instance using any of the standard custom provider techniques, including `useClass`, `useValue`, and `useFactory`.
+
+```ts
+import { Test, TestingModule } from '@nestjs/testing';
+import { getRedisToken } from '@liaoliaots/nestjs-redis';
+
+const module: TestingModule = await Test.createTestingModule({
+ providers: [{ provide: getRedisToken('namespace'), useValue: mockedInstance }, YourService]
+}).compile();
+```
+
+A working example is available [here](/sample).