@nestjs-redisx/core 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,4917 @@
1
+ import { Provider, Type, ModuleMetadata, DynamicModule, OnModuleDestroy, Logger, OnModuleInit } from '@nestjs/common';
2
+ import { ModuleRef } from '@nestjs/core';
3
+ import EventEmitter from 'events';
4
+ import Redis, { Cluster } from 'ioredis';
5
+ import { RedisClientType, RedisClusterType, RedisSentinelType } from 'redis';
6
+
7
+ /**
8
+ * Context provided to plugins during lifecycle methods.
9
+ * Gives access to core services and configuration.
10
+ */
11
+ interface IPluginContext {
12
+ /**
13
+ * Client manager for accessing and querying Redis clients.
14
+ *
15
+ * @example
16
+ * ```typescript
17
+ * if (context.clientManager.hasClient('cache')) {
18
+ * const client = await context.clientManager.getClient('cache');
19
+ * }
20
+ * ```
21
+ */
22
+ readonly clientManager: IClientManager$1;
23
+ /**
24
+ * Full module configuration.
25
+ * Includes global config and plugin-specific config.
26
+ *
27
+ * @example
28
+ * ```typescript
29
+ * const cacheConfig = context.config.cache;
30
+ * ```
31
+ */
32
+ readonly config: IRedisXConfig;
33
+ /**
34
+ * Logger instance scoped to the plugin.
35
+ * Automatically includes plugin name in logs.
36
+ *
37
+ * @example
38
+ * ```typescript
39
+ * context.logger.info('Cache initialized', { size: 1000 });
40
+ * ```
41
+ */
42
+ readonly logger: IRedisXLogger;
43
+ /**
44
+ * NestJS ModuleRef for advanced DI operations.
45
+ * Use sparingly, prefer explicit injection.
46
+ */
47
+ readonly moduleRef: ModuleRef;
48
+ /**
49
+ * Gets another plugin by name.
50
+ * Returns undefined if plugin not loaded.
51
+ *
52
+ * @example
53
+ * ```typescript
54
+ * const cachePlugin = context.getPlugin<CachePlugin>('cache');
55
+ * ```
56
+ */
57
+ getPlugin<T extends IRedisXPlugin>(name: string): T | undefined;
58
+ /**
59
+ * Checks if a plugin is loaded.
60
+ */
61
+ hasPlugin(name: string): boolean;
62
+ }
63
+ /**
64
+ * Client manager interface for plugin context.
65
+ * Delegates to the real RedisClientManager.
66
+ */
67
+ interface IClientManager$1 {
68
+ /**
69
+ * Gets Redis client by name.
70
+ * @param name Client name (defaults to 'default')
71
+ */
72
+ getClient(name?: string): Promise<IRedisDriver$1>;
73
+ /**
74
+ * Checks if client exists.
75
+ */
76
+ hasClient(name: string): boolean;
77
+ /**
78
+ * Gets all registered client names.
79
+ */
80
+ getClientNames(): string[];
81
+ }
82
+ /**
83
+ * RedisX configuration interface.
84
+ */
85
+ interface IRedisXConfig {
86
+ /**
87
+ * Redis client configurations.
88
+ */
89
+ clients: Record<string, IClientConfig>;
90
+ /**
91
+ * Registered plugins.
92
+ */
93
+ plugins?: IRedisXPlugin[];
94
+ /**
95
+ * Global configuration.
96
+ */
97
+ global?: {
98
+ /** Enable debug logging */
99
+ debug?: boolean;
100
+ /** Default TTL for operations */
101
+ defaultTtl?: number;
102
+ /** Key prefix for all keys */
103
+ keyPrefix?: string;
104
+ };
105
+ }
106
+ /**
107
+ * Client configuration.
108
+ */
109
+ interface IClientConfig {
110
+ host?: string;
111
+ port?: number;
112
+ password?: string;
113
+ db?: number;
114
+ keyPrefix?: string;
115
+ connectTimeout?: number;
116
+ commandTimeout?: number;
117
+ }
118
+ /**
119
+ * Logger interface.
120
+ */
121
+ interface IRedisXLogger {
122
+ debug(message: string, context?: Record<string, unknown>): void;
123
+ info(message: string, context?: Record<string, unknown>): void;
124
+ warn(message: string, context?: Record<string, unknown>): void;
125
+ error(message: string, error?: Error, context?: Record<string, unknown>): void;
126
+ }
127
+ /**
128
+ * Redis driver interface (re-export for context).
129
+ */
130
+ interface IRedisDriver$1 {
131
+ connect(): Promise<void>;
132
+ disconnect(): Promise<void>;
133
+ isConnected(): boolean;
134
+ get(key: string): Promise<string | null>;
135
+ set(key: string, value: string, options?: unknown): Promise<'OK' | null>;
136
+ del(keys: string | string[]): Promise<number>;
137
+ eval(script: string, keys: string[], args: (string | number)[]): Promise<unknown>;
138
+ evalsha(sha: string, keys: string[], args: (string | number)[]): Promise<unknown>;
139
+ pipeline(): unknown;
140
+ }
141
+
142
+ /**
143
+ * Base interface for all RedisX plugins.
144
+ *
145
+ * Plugins extend core functionality without modifying core code.
146
+ * They follow the Open/Closed Principle.
147
+ *
148
+ * ## Lifecycle hooks
149
+ *
150
+ * `onRegister()`, `onModuleInit()`, `onModuleDestroy()` and `dependencies`
151
+ * are managed by `PluginRegistryService`. Plugins are initialized in
152
+ * topological order based on `dependencies`. During shutdown, hooks are
153
+ * called in reverse dependency order.
154
+ *
155
+ * @example
156
+ * ```typescript
157
+ * export class CachePlugin implements IRedisXPlugin {
158
+ * readonly name = 'cache';
159
+ * readonly version = '1.0.0';
160
+ *
161
+ * getProviders() {
162
+ * return [CacheService, TagIndexService];
163
+ * }
164
+ * }
165
+ * ```
166
+ */
167
+ interface IRedisXPlugin {
168
+ /**
169
+ * Unique plugin identifier.
170
+ * Used for dependency resolution and configuration mapping.
171
+ * Must be lowercase, alphanumeric with hyphens.
172
+ *
173
+ * @example 'cache', 'locks', 'rate-limit'
174
+ */
175
+ readonly name: string;
176
+ /**
177
+ * Plugin version following semver.
178
+ * Used for compatibility checks.
179
+ *
180
+ * @example '1.0.0', '2.1.3'
181
+ */
182
+ readonly version: string;
183
+ /**
184
+ * Optional human-readable description.
185
+ */
186
+ readonly description?: string;
187
+ /**
188
+ * Names of plugins this plugin depends on.
189
+ * Core ensures dependencies are initialized first.
190
+ *
191
+ * @example ['cache'] - depends on cache plugin
192
+ */
193
+ readonly dependencies?: string[];
194
+ /**
195
+ * Called immediately when plugin is registered.
196
+ * Use for synchronous setup that doesn't require other plugins.
197
+ *
198
+ * @param context - Plugin context with core services
199
+ */
200
+ onRegister?(context: IPluginContext): void | Promise<void>;
201
+ /**
202
+ * Called after all plugins registered and Redis connected.
203
+ * Dependencies are guaranteed to be initialized.
204
+ * Use for async setup like loading Lua scripts.
205
+ *
206
+ * @param context - Plugin context with core services
207
+ */
208
+ onModuleInit?(context: IPluginContext): void | Promise<void>;
209
+ /**
210
+ * Called when application is shutting down.
211
+ * Use for cleanup (close connections, flush buffers).
212
+ * Called in reverse dependency order.
213
+ *
214
+ * @param context - Plugin context with core services
215
+ */
216
+ onModuleDestroy?(context: IPluginContext): void | Promise<void>;
217
+ /**
218
+ * Returns NestJS providers this plugin contributes.
219
+ * These are registered in the DI container.
220
+ */
221
+ getProviders?(): Provider[];
222
+ /**
223
+ * Returns exports that other modules can inject.
224
+ * Typically the main service of the plugin.
225
+ */
226
+ getExports?(): Array<Provider | string | symbol | Type>;
227
+ /**
228
+ * Returns NestJS controllers this plugin contributes.
229
+ * Controllers handle HTTP endpoints.
230
+ */
231
+ getControllers?(): Type[];
232
+ }
233
+
234
+ /**
235
+ * Configuration types for NestJS RedisX.
236
+ * Based on ARCHITECTURE.md - Configuration Schema.
237
+ */
238
+
239
+ /**
240
+ * Base connection options common to all connection types.
241
+ */
242
+ interface IBaseConnectionConfig {
243
+ /**
244
+ * Password for authentication.
245
+ */
246
+ password?: string;
247
+ /**
248
+ * Database number (0-15).
249
+ * @default 0
250
+ */
251
+ db?: number;
252
+ /**
253
+ * Key prefix for all operations.
254
+ * @example 'myapp:'
255
+ */
256
+ keyPrefix?: string;
257
+ /**
258
+ * Connection timeout in milliseconds.
259
+ * @default 10000
260
+ */
261
+ connectTimeout?: number;
262
+ /**
263
+ * Command timeout in milliseconds.
264
+ * @default 5000
265
+ */
266
+ commandTimeout?: number;
267
+ /**
268
+ * Keep-alive interval in milliseconds.
269
+ * @default 0 (disabled)
270
+ */
271
+ keepAlive?: number;
272
+ /**
273
+ * Enable offline queue.
274
+ * @default true
275
+ */
276
+ enableOfflineQueue?: boolean;
277
+ /**
278
+ * Enable auto-reconnect.
279
+ * @default true
280
+ */
281
+ enableAutoReconnect?: boolean;
282
+ /**
283
+ * Maximum retry attempts for commands.
284
+ * @default 3
285
+ */
286
+ maxRetriesPerRequest?: number;
287
+ /**
288
+ * Retry strategy function.
289
+ */
290
+ retryStrategy?: (times: number) => number | null;
291
+ /**
292
+ * Reconnect on error function.
293
+ */
294
+ reconnectOnError?: (error: Error) => boolean | 1 | 2;
295
+ }
296
+ /**
297
+ * Single instance Redis connection configuration.
298
+ */
299
+ interface ISingleConnectionConfig extends IBaseConnectionConfig {
300
+ /**
301
+ * Connection type discriminator.
302
+ */
303
+ type?: 'single';
304
+ /**
305
+ * Redis host.
306
+ * @default 'localhost'
307
+ */
308
+ host?: string;
309
+ /**
310
+ * Redis port.
311
+ * @default 6379
312
+ */
313
+ port?: number;
314
+ /**
315
+ * Optional TLS configuration.
316
+ */
317
+ tls?: ITlsConfig;
318
+ }
319
+ /**
320
+ * Redis Cluster connection configuration.
321
+ */
322
+ interface IClusterConnectionConfig extends IBaseConnectionConfig {
323
+ /**
324
+ * Connection type discriminator.
325
+ */
326
+ type: 'cluster';
327
+ /**
328
+ * Cluster nodes.
329
+ * @example [{ host: 'localhost', port: 6379 }, { host: 'localhost', port: 6380 }]
330
+ */
331
+ nodes: Array<{
332
+ host: string;
333
+ port: number;
334
+ }>;
335
+ /**
336
+ * Cluster-specific options.
337
+ */
338
+ clusterOptions?: {
339
+ /**
340
+ * Maximum number of redirections.
341
+ * @default 16
342
+ */
343
+ maxRedirections?: number;
344
+ /**
345
+ * Retry delay for cluster commands.
346
+ * @default 100
347
+ */
348
+ retryDelayOnClusterDown?: number;
349
+ /**
350
+ * Retry delay when all slots covered.
351
+ * @default 100
352
+ */
353
+ retryDelayOnFailover?: number;
354
+ /**
355
+ * Scale reads to slaves.
356
+ * @default 'master'
357
+ */
358
+ scaleReads?: 'master' | 'slave' | 'all';
359
+ /**
360
+ * Enable readonly mode for slave nodes.
361
+ * @default false
362
+ */
363
+ enableReadyCheck?: boolean;
364
+ /**
365
+ * NAT mapping for Docker/firewall scenarios.
366
+ * Maps internal IPs to external accessible addresses.
367
+ * @example { '172.17.0.2:6379': { host: 'localhost', port: 6379 } }
368
+ */
369
+ natMap?: Record<string, {
370
+ host: string;
371
+ port: number;
372
+ }>;
373
+ /**
374
+ * Additional ioredis cluster options.
375
+ * Allows passing any other ioredis ClusterOptions.
376
+ */
377
+ [key: string]: unknown;
378
+ };
379
+ }
380
+ /**
381
+ * Redis Sentinel connection configuration.
382
+ */
383
+ interface ISentinelConnectionConfig extends IBaseConnectionConfig {
384
+ /**
385
+ * Connection type discriminator.
386
+ */
387
+ type: 'sentinel';
388
+ /**
389
+ * Sentinel nodes.
390
+ */
391
+ sentinels: Array<{
392
+ host: string;
393
+ port: number;
394
+ }>;
395
+ /**
396
+ * Master name.
397
+ */
398
+ name: string;
399
+ /**
400
+ * Optional TLS configuration.
401
+ */
402
+ tls?: ITlsConfig;
403
+ /**
404
+ * Sentinel-specific options.
405
+ */
406
+ sentinelOptions?: {
407
+ /**
408
+ * Enable TLS for sentinel connections.
409
+ */
410
+ enableTLSForSentinelMode?: boolean;
411
+ /**
412
+ * Sentinel password (if different from node password).
413
+ */
414
+ sentinelPassword?: string;
415
+ /**
416
+ * Retry strategy for sentinel.
417
+ */
418
+ sentinelRetryStrategy?: (times: number) => number | null;
419
+ /**
420
+ * Prefer slave nodes for reads.
421
+ * @default false
422
+ */
423
+ preferredSlaves?: boolean;
424
+ /**
425
+ * NAT mapping for sentinel-managed instances.
426
+ * Maps internal master/slave addresses to external accessible addresses.
427
+ * @example { 'redis-master:6379': { host: 'localhost', port: 6379 } }
428
+ */
429
+ natMap?: Record<string, {
430
+ host: string;
431
+ port: number;
432
+ }>;
433
+ /**
434
+ * Master connection pool size.
435
+ * Number of connections to maintain to the master node.
436
+ * @default 1
437
+ */
438
+ masterPoolSize?: number;
439
+ /**
440
+ * Replica connection pool size per node.
441
+ * Set to 0 to disable replica connections.
442
+ * @default 0
443
+ */
444
+ replicaPoolSize?: number;
445
+ /**
446
+ * Interval in milliseconds to scan for topology changes.
447
+ * @default 10000
448
+ */
449
+ scanInterval?: number;
450
+ /**
451
+ * Maximum number of command rediscovers on topology change.
452
+ * @default 16
453
+ */
454
+ maxCommandRediscovers?: number;
455
+ /**
456
+ * Additional ioredis/node-redis sentinel options.
457
+ */
458
+ [key: string]: unknown;
459
+ };
460
+ }
461
+ /**
462
+ * TLS configuration.
463
+ */
464
+ interface ITlsConfig {
465
+ /**
466
+ * Enable TLS.
467
+ * @default false
468
+ */
469
+ enabled?: boolean;
470
+ /**
471
+ * CA certificate.
472
+ */
473
+ ca?: string | Buffer;
474
+ /**
475
+ * Client certificate.
476
+ */
477
+ cert?: string | Buffer;
478
+ /**
479
+ * Client key.
480
+ */
481
+ key?: string | Buffer;
482
+ /**
483
+ * Reject unauthorized certificates.
484
+ * @default true
485
+ */
486
+ rejectUnauthorized?: boolean;
487
+ }
488
+ /**
489
+ * Union type for all connection configurations.
490
+ */
491
+ type ConnectionConfig = ISingleConnectionConfig | IClusterConnectionConfig | ISentinelConnectionConfig;
492
+ /**
493
+ * Configuration for a single Redis client.
494
+ */
495
+ interface IRedisClientOptions {
496
+ /**
497
+ * Client name (for named clients).
498
+ * @default 'default'
499
+ */
500
+ name?: string;
501
+ /**
502
+ * Connection configuration.
503
+ */
504
+ connection: ConnectionConfig;
505
+ /**
506
+ * Namespace/prefix for this client.
507
+ * Overrides connection.keyPrefix.
508
+ */
509
+ namespace?: string;
510
+ }
511
+ /**
512
+ * Driver type for Redis connections.
513
+ */
514
+ type DriverType = 'ioredis' | 'node-redis';
515
+ /**
516
+ * Global module configuration options.
517
+ */
518
+ interface IGlobalConfig {
519
+ /**
520
+ * Redis driver to use.
521
+ * @default 'ioredis'
522
+ */
523
+ driver?: DriverType;
524
+ /**
525
+ * Enable debug logging.
526
+ * @default false
527
+ */
528
+ debug?: boolean;
529
+ /**
530
+ * Default TTL for cache operations (seconds).
531
+ * @default 3600
532
+ */
533
+ defaultTtl?: number;
534
+ /**
535
+ * Global key prefix for all clients.
536
+ */
537
+ keyPrefix?: string;
538
+ /**
539
+ * Enable graceful shutdown.
540
+ * @default true
541
+ */
542
+ gracefulShutdown?: boolean;
543
+ /**
544
+ * Graceful shutdown timeout (milliseconds).
545
+ * @default 5000
546
+ */
547
+ gracefulShutdownTimeout?: number;
548
+ /**
549
+ * Enable health checks.
550
+ * @default true
551
+ */
552
+ enableHealthChecks?: boolean;
553
+ /**
554
+ * Health check interval (milliseconds).
555
+ * @default 30000
556
+ */
557
+ healthCheckInterval?: number;
558
+ }
559
+ /**
560
+ * Synchronous module configuration.
561
+ */
562
+ interface IRedisModuleOptions {
563
+ /**
564
+ * Redis client configurations.
565
+ * Can be a single config or a map of named clients.
566
+ */
567
+ clients: ConnectionConfig | Record<string, ConnectionConfig>;
568
+ /**
569
+ * Registered plugins.
570
+ */
571
+ plugins?: IRedisXPlugin[];
572
+ /**
573
+ * Global configuration.
574
+ */
575
+ global?: IGlobalConfig;
576
+ }
577
+ /**
578
+ * Factory function for async configuration.
579
+ */
580
+ interface IRedisModuleOptionsFactory {
581
+ /**
582
+ * Creates module options asynchronously.
583
+ */
584
+ createRedisModuleOptions(): Promise<IRedisModuleOptions> | IRedisModuleOptions;
585
+ }
586
+ /**
587
+ * Asynchronous module configuration.
588
+ */
589
+ interface IRedisModuleAsyncOptions extends Pick<ModuleMetadata, 'imports'> {
590
+ /**
591
+ * Registered plugins.
592
+ * Plugins must be provided outside useFactory to ensure providers are available at module construction time.
593
+ * This is a standard NestJS pattern (similar to @nestjs/typeorm entities, @nestjs/graphql resolvers).
594
+ */
595
+ plugins?: IRedisXPlugin[];
596
+ /**
597
+ * Factory function returning options.
598
+ */
599
+ useFactory?: (...args: unknown[]) => Promise<IRedisModuleOptions> | IRedisModuleOptions;
600
+ /**
601
+ * Dependencies to inject into factory.
602
+ */
603
+ inject?: unknown[];
604
+ /**
605
+ * Use existing provider.
606
+ */
607
+ useExisting?: Type<IRedisModuleOptionsFactory>;
608
+ /**
609
+ * Use class provider.
610
+ */
611
+ useClass?: Type<IRedisModuleOptionsFactory>;
612
+ }
613
+ /**
614
+ * Client metadata stored in the registry.
615
+ */
616
+ interface IClientMetadata {
617
+ /**
618
+ * Client name.
619
+ */
620
+ name: string;
621
+ /**
622
+ * Connection configuration.
623
+ */
624
+ config: ConnectionConfig;
625
+ /**
626
+ * Connection status.
627
+ */
628
+ status: ConnectionStatus;
629
+ /**
630
+ * Last connection time.
631
+ */
632
+ connectedAt?: Date;
633
+ /**
634
+ * Last error.
635
+ */
636
+ lastError?: Error;
637
+ /**
638
+ * Number of reconnection attempts.
639
+ */
640
+ reconnectAttempts: number;
641
+ }
642
+ /**
643
+ * Connection status.
644
+ */
645
+ declare enum ConnectionStatus {
646
+ DISCONNECTED = "disconnected",
647
+ CONNECTING = "connecting",
648
+ CONNECTED = "connected",
649
+ RECONNECTING = "reconnecting",
650
+ ERROR = "error"
651
+ }
652
+ /**
653
+ * Health check result.
654
+ */
655
+ interface IHealthCheckResult {
656
+ /**
657
+ * Overall health status.
658
+ */
659
+ status: 'healthy' | 'unhealthy' | 'degraded';
660
+ /**
661
+ * Individual client statuses.
662
+ */
663
+ clients: Record<string, IClientHealthStatus>;
664
+ /**
665
+ * Timestamp of check.
666
+ */
667
+ timestamp: Date;
668
+ }
669
+ /**
670
+ * Client health status.
671
+ */
672
+ interface IClientHealthStatus {
673
+ /**
674
+ * Client name.
675
+ */
676
+ name: string;
677
+ /**
678
+ * Connection status.
679
+ */
680
+ status: ConnectionStatus;
681
+ /**
682
+ * Latency in milliseconds (ping).
683
+ */
684
+ latency?: number;
685
+ /**
686
+ * Last error message.
687
+ */
688
+ error?: string;
689
+ /**
690
+ * Uptime in milliseconds.
691
+ */
692
+ uptime?: number;
693
+ }
694
+ /**
695
+ * Type guard for single connection config.
696
+ */
697
+ declare function isSingleConnection(config: ConnectionConfig): config is ISingleConnectionConfig;
698
+ /**
699
+ * Type guard for cluster connection config.
700
+ */
701
+ declare function isClusterConnection(config: ConnectionConfig): config is IClusterConnectionConfig;
702
+ /**
703
+ * Type guard for sentinel connection config.
704
+ */
705
+ declare function isSentinelConnection(config: ConnectionConfig): config is ISentinelConnectionConfig;
706
+ /**
707
+ * Type guard for async options with factory.
708
+ */
709
+ declare function hasFactory(options: IRedisModuleAsyncOptions): options is Required<Pick<IRedisModuleAsyncOptions, 'useFactory'>> & IRedisModuleAsyncOptions;
710
+ /**
711
+ * Type guard for async options with existing provider.
712
+ */
713
+ declare function hasExisting(options: IRedisModuleAsyncOptions): options is Required<Pick<IRedisModuleAsyncOptions, 'useExisting'>> & IRedisModuleAsyncOptions;
714
+ /**
715
+ * Type guard for async options with class provider.
716
+ */
717
+ declare function hasClass(options: IRedisModuleAsyncOptions): options is Required<Pick<IRedisModuleAsyncOptions, 'useClass'>> & IRedisModuleAsyncOptions;
718
+
719
+ /**
720
+ * Redis module for NestJS.
721
+ *
722
+ * Global module that provides Redis client(s) with driver abstraction,
723
+ * health monitoring, automatic reconnection, and plugin system.
724
+ *
725
+ * Module is always global - no need to import in feature modules.
726
+ *
727
+ * @example
728
+ * **Synchronous configuration:**
729
+ * ```typescript
730
+ * @Module({
731
+ * imports: [
732
+ * RedisModule.forRoot({
733
+ * clients: {
734
+ * type: 'single',
735
+ * host: 'localhost',
736
+ * port: 6379,
737
+ * },
738
+ * }),
739
+ * ],
740
+ * })
741
+ * export class AppModule {}
742
+ * ```
743
+ *
744
+ * @example
745
+ * **Asynchronous configuration with factory:**
746
+ * ```typescript
747
+ * @Module({
748
+ * imports: [
749
+ * RedisModule.forRootAsync({
750
+ * useFactory: (config: ConfigService) => ({
751
+ * clients: {
752
+ * type: 'single',
753
+ * host: config.get('REDIS_HOST'),
754
+ * port: config.get('REDIS_PORT'),
755
+ * },
756
+ * }),
757
+ * inject: [ConfigService],
758
+ * }),
759
+ * ],
760
+ * })
761
+ * export class AppModule {}
762
+ * ```
763
+ *
764
+ * @example
765
+ * **With plugins:**
766
+ * ```typescript
767
+ * @Module({
768
+ * imports: [
769
+ * RedisModule.forRoot({
770
+ * clients: { type: 'single', host: 'localhost', port: 6379 },
771
+ * plugins: [new CachePlugin(), new LocksPlugin()],
772
+ * }),
773
+ * ],
774
+ * })
775
+ * export class AppModule {}
776
+ * ```
777
+ */
778
+ declare class RedisModule {
779
+ /**
780
+ * Configures Redis module synchronously.
781
+ *
782
+ * Creates a global module with Redis clients and plugins.
783
+ * All providers are available for injection everywhere.
784
+ *
785
+ * @param options - Redis module options
786
+ * @returns Dynamic module
787
+ *
788
+ * @example
789
+ * ```typescript
790
+ * RedisModule.forRoot({
791
+ * clients: {
792
+ * type: 'single',
793
+ * host: 'localhost',
794
+ * port: 6379,
795
+ * },
796
+ * plugins: [new CachePlugin(), new LocksPlugin()],
797
+ * })
798
+ * ```
799
+ */
800
+ static forRoot(options: IRedisModuleOptions): DynamicModule;
801
+ /**
802
+ * Configures Redis module asynchronously.
803
+ *
804
+ * Allows configuration to be loaded asynchronously using factory function,
805
+ * existing provider, or class-based factory. Supports plugins.
806
+ *
807
+ * Note: Plugins must be provided in the async options (outside useFactory),
808
+ * not in the factory result. This is a standard NestJS pattern — plugins
809
+ * must be available at module construction time for NestJS DI.
810
+ *
811
+ * @param options - Async Redis module options
812
+ * @returns Dynamic module
813
+ *
814
+ * @example
815
+ * **Using factory with plugins:**
816
+ * ```typescript
817
+ * RedisModule.forRootAsync({
818
+ * plugins: [new CachePlugin(), new LocksPlugin()],
819
+ * useFactory: (config: ConfigService) => ({
820
+ * clients: {
821
+ * type: 'single',
822
+ * host: config.get('REDIS_HOST'),
823
+ * port: config.get('REDIS_PORT'),
824
+ * },
825
+ * }),
826
+ * inject: [ConfigService],
827
+ * })
828
+ * ```
829
+ *
830
+ * @example
831
+ * **Using class:**
832
+ * ```typescript
833
+ * @Injectable()
834
+ * class RedisConfigService implements IRedisModuleOptionsFactory {
835
+ * createRedisModuleOptions(): IRedisModuleOptions {
836
+ * return {
837
+ * clients: { type: 'single', host: 'localhost', port: 6379 },
838
+ * };
839
+ * }
840
+ * }
841
+ *
842
+ * RedisModule.forRootAsync({
843
+ * plugins: [new CachePlugin()],
844
+ * useClass: RedisConfigService,
845
+ * })
846
+ * ```
847
+ */
848
+ static forRootAsync(options: IRedisModuleAsyncOptions): DynamicModule;
849
+ }
850
+
851
+ /**
852
+ * Redis driver abstraction interface.
853
+ *
854
+ * Complete interface for all Redis operations.
855
+ * All Redis operations MUST go through this interface.
856
+ * NEVER import ioredis or redis directly.
857
+ *
858
+ * @example
859
+ * ```typescript
860
+ * @Injectable()
861
+ * export class CacheService {
862
+ * constructor(
863
+ * @Inject(REDIS_DRIVER) private readonly driver: IRedisDriver
864
+ * ) {}
865
+ * }
866
+ * ```
867
+ */
868
+ interface IRedisDriver {
869
+ /**
870
+ * Connects to Redis.
871
+ * Called automatically by ClientManager.
872
+ */
873
+ connect(): Promise<void>;
874
+ /**
875
+ * Disconnects from Redis gracefully.
876
+ * Called automatically on module destroy.
877
+ */
878
+ disconnect(): Promise<void>;
879
+ /**
880
+ * Checks if connected to Redis.
881
+ */
882
+ isConnected(): boolean;
883
+ /**
884
+ * Pings Redis server.
885
+ * @returns 'PONG' or custom message
886
+ */
887
+ ping(message?: string): Promise<string>;
888
+ /**
889
+ * Selects database.
890
+ * @param db - Database number (0-15)
891
+ */
892
+ select(db: number): Promise<void>;
893
+ /**
894
+ * Gets value of a key.
895
+ * @returns Value or null if key doesn't exist
896
+ */
897
+ get(key: string): Promise<string | null>;
898
+ /**
899
+ * Sets value of a key with optional TTL.
900
+ * @returns 'OK' if successful, null otherwise
901
+ */
902
+ set(key: string, value: string, options?: ISetOptions): Promise<'OK' | null>;
903
+ /**
904
+ * Gets multiple values.
905
+ * @returns Array of values (null for non-existent keys)
906
+ */
907
+ mget(...keys: string[]): Promise<Array<string | null>>;
908
+ /**
909
+ * Sets multiple key-value pairs.
910
+ * @returns 'OK' if successful
911
+ */
912
+ mset(data: Record<string, string>): Promise<'OK'>;
913
+ /**
914
+ * Sets value only if key doesn't exist.
915
+ * @returns 1 if set, 0 if not set
916
+ */
917
+ setnx(key: string, value: string): Promise<number>;
918
+ /**
919
+ * Sets value with expiration in seconds.
920
+ * @returns 'OK' if successful
921
+ */
922
+ setex(key: string, seconds: number, value: string): Promise<'OK'>;
923
+ /**
924
+ * Gets value and deletes key atomically.
925
+ * @returns Value or null if key doesn't exist
926
+ */
927
+ getdel(key: string): Promise<string | null>;
928
+ /**
929
+ * Gets value and sets expiration atomically.
930
+ * @returns Value or null if key doesn't exist
931
+ */
932
+ getex(key: string, options: {
933
+ ex?: number;
934
+ px?: number;
935
+ }): Promise<string | null>;
936
+ /**
937
+ * Increments integer value by 1.
938
+ * @returns New value after increment
939
+ */
940
+ incr(key: string): Promise<number>;
941
+ /**
942
+ * Increments integer value by amount.
943
+ * @returns New value after increment
944
+ */
945
+ incrby(key: string, increment: number): Promise<number>;
946
+ /**
947
+ * Decrements integer value by 1.
948
+ * @returns New value after decrement
949
+ */
950
+ decr(key: string): Promise<number>;
951
+ /**
952
+ * Decrements integer value by amount.
953
+ * @returns New value after decrement
954
+ */
955
+ decrby(key: string, decrement: number): Promise<number>;
956
+ /**
957
+ * Appends value to key.
958
+ * @returns Length of string after append
959
+ */
960
+ append(key: string, value: string): Promise<number>;
961
+ /**
962
+ * Gets length of string value.
963
+ * @returns Length of string, 0 if key doesn't exist
964
+ */
965
+ strlen(key: string): Promise<number>;
966
+ /**
967
+ * Increments value by float amount.
968
+ * @returns New value after increment
969
+ */
970
+ incrbyfloat(key: string, increment: number): Promise<string>;
971
+ /**
972
+ * Gets substring of string value.
973
+ * @param start - Start offset (can be negative)
974
+ * @param end - End offset (can be negative)
975
+ * @returns Substring
976
+ */
977
+ getrange(key: string, start: number, end: number): Promise<string>;
978
+ /**
979
+ * Overwrites part of string at offset.
980
+ * @returns Length of string after modification
981
+ */
982
+ setrange(key: string, offset: number, value: string): Promise<number>;
983
+ /**
984
+ * Sets multiple keys only if none exist.
985
+ * @returns 1 if all keys set, 0 if no keys set
986
+ */
987
+ msetnx(data: Record<string, string>): Promise<number>;
988
+ /**
989
+ * Deletes one or more keys.
990
+ * @returns Number of keys deleted
991
+ */
992
+ del(...keys: string[]): Promise<number>;
993
+ /**
994
+ * Checks if key exists.
995
+ * @returns Number of existing keys
996
+ */
997
+ exists(...keys: string[]): Promise<number>;
998
+ /**
999
+ * Sets TTL on a key (seconds).
1000
+ * @returns 1 if timeout was set, 0 if key doesn't exist
1001
+ */
1002
+ expire(key: string, seconds: number): Promise<number>;
1003
+ /**
1004
+ * Sets TTL on a key (milliseconds).
1005
+ * @returns 1 if timeout was set, 0 if key doesn't exist
1006
+ */
1007
+ pexpire(key: string, milliseconds: number): Promise<number>;
1008
+ /**
1009
+ * Sets absolute expiration time (Unix timestamp in seconds).
1010
+ * @returns 1 if timeout was set, 0 if key doesn't exist
1011
+ */
1012
+ expireat(key: string, timestamp: number): Promise<number>;
1013
+ /**
1014
+ * Gets TTL of a key (seconds).
1015
+ * @returns TTL in seconds, -1 if no TTL, -2 if key doesn't exist
1016
+ */
1017
+ ttl(key: string): Promise<number>;
1018
+ /**
1019
+ * Gets TTL of a key (milliseconds).
1020
+ * @returns TTL in milliseconds, -1 if no TTL, -2 if key doesn't exist
1021
+ */
1022
+ pttl(key: string): Promise<number>;
1023
+ /**
1024
+ * Removes expiration from key.
1025
+ * @returns 1 if expiration removed, 0 if key has no expiration
1026
+ */
1027
+ persist(key: string): Promise<number>;
1028
+ /**
1029
+ * Renames key.
1030
+ * @returns 'OK' if successful
1031
+ * @throws Error if source key doesn't exist
1032
+ */
1033
+ rename(key: string, newKey: string): Promise<'OK'>;
1034
+ /**
1035
+ * Renames key only if new key doesn't exist.
1036
+ * @returns 1 if renamed, 0 if new key exists
1037
+ */
1038
+ renamenx(key: string, newKey: string): Promise<number>;
1039
+ /**
1040
+ * Gets type of value stored at key.
1041
+ * @returns Type name: 'string', 'list', 'set', 'zset', 'hash', 'stream', 'none'
1042
+ */
1043
+ type(key: string): Promise<string>;
1044
+ /**
1045
+ * Scans keys matching pattern.
1046
+ * @returns Cursor and array of keys
1047
+ */
1048
+ scan(cursor: number, options?: IScanOptions): Promise<[string, string[]]>;
1049
+ /**
1050
+ * Deletes keys asynchronously (non-blocking).
1051
+ * Better for large keys than del.
1052
+ * @returns Number of keys unlinked
1053
+ */
1054
+ unlink(...keys: string[]): Promise<number>;
1055
+ /**
1056
+ * Copies key to another key.
1057
+ * @param destination - Destination key
1058
+ * @param options - Copy options (replace, db)
1059
+ * @returns 1 if copied, 0 if not
1060
+ */
1061
+ copy(source: string, destination: string, options?: ICopyOptions): Promise<number>;
1062
+ /**
1063
+ * Finds all keys matching pattern.
1064
+ * WARNING: Use SCAN in production for large keyspaces.
1065
+ * @returns Array of matching keys
1066
+ */
1067
+ keys(pattern: string): Promise<string[]>;
1068
+ /**
1069
+ * Alters the last access time of keys.
1070
+ * @returns Number of keys touched
1071
+ */
1072
+ touch(...keys: string[]): Promise<number>;
1073
+ /**
1074
+ * Returns the internal encoding of a Redis object.
1075
+ * @param subcommand - ENCODING, FREQ, IDLETIME, REFCOUNT
1076
+ * @returns Object info
1077
+ */
1078
+ object(subcommand: 'ENCODING' | 'FREQ' | 'IDLETIME' | 'REFCOUNT', key: string): Promise<string | number | null>;
1079
+ /**
1080
+ * Serializes the value at key.
1081
+ * @returns Serialized value or null
1082
+ */
1083
+ dump(key: string): Promise<string | null>;
1084
+ /**
1085
+ * Deserializes and stores value at key.
1086
+ * @param ttl - TTL in milliseconds (0 = no expiry)
1087
+ * @param serializedValue - Serialized value from dump
1088
+ * @param options - Restore options
1089
+ * @returns 'OK' if successful
1090
+ */
1091
+ restore(key: string, ttl: number, serializedValue: string, options?: IRestoreOptions): Promise<'OK'>;
1092
+ /**
1093
+ * Returns server time.
1094
+ * @returns [unix timestamp in seconds, microseconds]
1095
+ */
1096
+ time(): Promise<[string, string]>;
1097
+ /**
1098
+ * Gets value of hash field.
1099
+ * @returns Value or null if field doesn't exist
1100
+ */
1101
+ hget(key: string, field: string): Promise<string | null>;
1102
+ /**
1103
+ * Sets value of hash field.
1104
+ * @returns 1 if new field, 0 if field updated
1105
+ */
1106
+ hset(key: string, field: string, value: string): Promise<number>;
1107
+ /**
1108
+ * Sets multiple hash fields.
1109
+ * @returns 'OK' if successful
1110
+ */
1111
+ hmset(key: string, data: Record<string, string>): Promise<'OK'>;
1112
+ /**
1113
+ * Gets multiple hash field values.
1114
+ * @returns Array of values (null for non-existent fields)
1115
+ */
1116
+ hmget(key: string, ...fields: string[]): Promise<Array<string | null>>;
1117
+ /**
1118
+ * Gets all fields and values of hash.
1119
+ * @returns Object with field-value pairs
1120
+ */
1121
+ hgetall(key: string): Promise<Record<string, string>>;
1122
+ /**
1123
+ * Deletes hash fields.
1124
+ * @returns Number of fields deleted
1125
+ */
1126
+ hdel(key: string, ...fields: string[]): Promise<number>;
1127
+ /**
1128
+ * Checks if hash field exists.
1129
+ * @returns 1 if field exists, 0 otherwise
1130
+ */
1131
+ hexists(key: string, field: string): Promise<number>;
1132
+ /**
1133
+ * Gets all field names in hash.
1134
+ */
1135
+ hkeys(key: string): Promise<string[]>;
1136
+ /**
1137
+ * Gets all values in hash.
1138
+ */
1139
+ hvals(key: string): Promise<string[]>;
1140
+ /**
1141
+ * Gets number of fields in hash.
1142
+ */
1143
+ hlen(key: string): Promise<number>;
1144
+ /**
1145
+ * Increments hash field by integer.
1146
+ * @returns New value after increment
1147
+ */
1148
+ hincrby(key: string, field: string, increment: number): Promise<number>;
1149
+ /**
1150
+ * Scans hash fields.
1151
+ * @returns Cursor and array of field-value pairs
1152
+ */
1153
+ hscan(key: string, cursor: number, options?: IScanOptions): Promise<[string, string[]]>;
1154
+ /**
1155
+ * Sets hash field only if it doesn't exist.
1156
+ * @returns 1 if field set, 0 if field exists
1157
+ */
1158
+ hsetnx(key: string, field: string, value: string): Promise<number>;
1159
+ /**
1160
+ * Increments hash field by float.
1161
+ * @returns New value as string
1162
+ */
1163
+ hincrbyfloat(key: string, field: string, increment: number): Promise<string>;
1164
+ /**
1165
+ * Gets string length of hash field value.
1166
+ * @returns Length of field value, 0 if field/key doesn't exist
1167
+ */
1168
+ hstrlen(key: string, field: string): Promise<number>;
1169
+ /**
1170
+ * Gets random fields from hash.
1171
+ * @param count - Number of fields (negative for duplicates allowed)
1172
+ * @param withValues - Include values
1173
+ * @returns Random field(s) or field-value pairs
1174
+ */
1175
+ hrandfield(key: string, count?: number, withValues?: boolean): Promise<string | string[] | null>;
1176
+ /**
1177
+ * Pushes values to left of list.
1178
+ * @returns Length of list after push
1179
+ */
1180
+ lpush(key: string, ...values: string[]): Promise<number>;
1181
+ /**
1182
+ * Pushes values to right of list.
1183
+ * @returns Length of list after push
1184
+ */
1185
+ rpush(key: string, ...values: string[]): Promise<number>;
1186
+ /**
1187
+ * Pops value from left of list.
1188
+ * @returns Value or null if list is empty
1189
+ */
1190
+ lpop(key: string): Promise<string | null>;
1191
+ /**
1192
+ * Pops value from right of list.
1193
+ * @returns Value or null if list is empty
1194
+ */
1195
+ rpop(key: string): Promise<string | null>;
1196
+ /**
1197
+ * Gets list length.
1198
+ * @returns Number of elements
1199
+ */
1200
+ llen(key: string): Promise<number>;
1201
+ /**
1202
+ * Gets list range.
1203
+ * @returns Array of values
1204
+ */
1205
+ lrange(key: string, start: number, stop: number): Promise<string[]>;
1206
+ /**
1207
+ * Trims list to specified range.
1208
+ * @returns 'OK' if successful
1209
+ */
1210
+ ltrim(key: string, start: number, stop: number): Promise<'OK'>;
1211
+ /**
1212
+ * Gets element at index.
1213
+ * @returns Value or null if index out of range
1214
+ */
1215
+ lindex(key: string, index: number): Promise<string | null>;
1216
+ /**
1217
+ * Sets element at index.
1218
+ * @returns 'OK' if successful
1219
+ */
1220
+ lset(key: string, index: number, value: string): Promise<'OK'>;
1221
+ /**
1222
+ * Inserts element before or after pivot.
1223
+ * @param position - BEFORE or AFTER
1224
+ * @param pivot - Reference element
1225
+ * @param element - Element to insert
1226
+ * @returns List length, -1 if pivot not found
1227
+ */
1228
+ linsert(key: string, position: 'BEFORE' | 'AFTER', pivot: string, element: string): Promise<number>;
1229
+ /**
1230
+ * Removes elements from list.
1231
+ * @param count - Number to remove (0=all, positive=head, negative=tail)
1232
+ * @param element - Element to remove
1233
+ * @returns Number of removed elements
1234
+ */
1235
+ lrem(key: string, count: number, element: string): Promise<number>;
1236
+ /**
1237
+ * Gets index of element in list.
1238
+ * @param options - RANK, COUNT, MAXLEN options
1239
+ * @returns Index or null if not found
1240
+ */
1241
+ lpos(key: string, element: string, options?: ILposOptions): Promise<number | number[] | null>;
1242
+ /**
1243
+ * Blocking left pop from list.
1244
+ * @param timeout - Timeout in seconds (0 = block forever)
1245
+ * @returns [key, element] or null on timeout
1246
+ */
1247
+ blpop(keys: string[], timeout: number): Promise<[string, string] | null>;
1248
+ /**
1249
+ * Blocking right pop from list.
1250
+ * @param timeout - Timeout in seconds (0 = block forever)
1251
+ * @returns [key, element] or null on timeout
1252
+ */
1253
+ brpop(keys: string[], timeout: number): Promise<[string, string] | null>;
1254
+ /**
1255
+ * Atomically moves element between lists.
1256
+ * @param source - Source list key
1257
+ * @param destination - Destination list key
1258
+ * @param from - LEFT or RIGHT
1259
+ * @param to - LEFT or RIGHT
1260
+ * @returns Moved element or null
1261
+ */
1262
+ lmove(source: string, destination: string, from: 'LEFT' | 'RIGHT', to: 'LEFT' | 'RIGHT'): Promise<string | null>;
1263
+ /**
1264
+ * Blocking version of lmove.
1265
+ * @param timeout - Timeout in seconds
1266
+ * @returns Moved element or null on timeout
1267
+ */
1268
+ blmove(source: string, destination: string, from: 'LEFT' | 'RIGHT', to: 'LEFT' | 'RIGHT', timeout: number): Promise<string | null>;
1269
+ /**
1270
+ * Adds members to set.
1271
+ * @returns Number of members added
1272
+ */
1273
+ sadd(key: string, ...members: string[]): Promise<number>;
1274
+ /**
1275
+ * Removes members from set.
1276
+ * @returns Number of members removed
1277
+ */
1278
+ srem(key: string, ...members: string[]): Promise<number>;
1279
+ /**
1280
+ * Gets all members of set.
1281
+ */
1282
+ smembers(key: string): Promise<string[]>;
1283
+ /**
1284
+ * Checks if member is in set.
1285
+ * @returns 1 if member exists, 0 otherwise
1286
+ */
1287
+ sismember(key: string, member: string): Promise<number>;
1288
+ /**
1289
+ * Gets number of members in set.
1290
+ */
1291
+ scard(key: string): Promise<number>;
1292
+ /**
1293
+ * Gets random member from set.
1294
+ * @returns Random member or null if set is empty
1295
+ */
1296
+ srandmember(key: string, count?: number): Promise<string | string[] | null>;
1297
+ /**
1298
+ * Pops random member from set.
1299
+ * @returns Random member or null if set is empty
1300
+ */
1301
+ spop(key: string, count?: number): Promise<string | string[] | null>;
1302
+ /**
1303
+ * Scans set members.
1304
+ * @returns Cursor and array of members
1305
+ */
1306
+ sscan(key: string, cursor: number, options?: IScanOptions): Promise<[string, string[]]>;
1307
+ /**
1308
+ * Moves member from one set to another.
1309
+ * @returns 1 if moved, 0 if member not in source
1310
+ */
1311
+ smove(source: string, destination: string, member: string): Promise<number>;
1312
+ /**
1313
+ * Returns intersection of sets.
1314
+ * @returns Array of common members
1315
+ */
1316
+ sinter(...keys: string[]): Promise<string[]>;
1317
+ /**
1318
+ * Stores intersection of sets.
1319
+ * @returns Number of members in result
1320
+ */
1321
+ sinterstore(destination: string, ...keys: string[]): Promise<number>;
1322
+ /**
1323
+ * Returns union of sets.
1324
+ * @returns Array of all unique members
1325
+ */
1326
+ sunion(...keys: string[]): Promise<string[]>;
1327
+ /**
1328
+ * Stores union of sets.
1329
+ * @returns Number of members in result
1330
+ */
1331
+ sunionstore(destination: string, ...keys: string[]): Promise<number>;
1332
+ /**
1333
+ * Returns difference of sets (first - others).
1334
+ * @returns Array of members in first set but not in others
1335
+ */
1336
+ sdiff(...keys: string[]): Promise<string[]>;
1337
+ /**
1338
+ * Stores difference of sets.
1339
+ * @returns Number of members in result
1340
+ */
1341
+ sdiffstore(destination: string, ...keys: string[]): Promise<number>;
1342
+ /**
1343
+ * Checks if multiple members are in set.
1344
+ * @returns Array of 1/0 for each member
1345
+ */
1346
+ smismember(key: string, ...members: string[]): Promise<number[]>;
1347
+ /**
1348
+ * Adds members to sorted set with scores.
1349
+ * @returns Number of members added
1350
+ */
1351
+ zadd(key: string, ...args: Array<number | string>): Promise<number>;
1352
+ /**
1353
+ * Removes members from sorted set.
1354
+ * @returns Number of members removed
1355
+ */
1356
+ zrem(key: string, ...members: string[]): Promise<number>;
1357
+ /**
1358
+ * Gets members in range by index.
1359
+ */
1360
+ zrange(key: string, start: number, stop: number, withScores?: boolean): Promise<string[]>;
1361
+ /**
1362
+ * Gets members in range by score.
1363
+ */
1364
+ zrangebyscore(key: string, min: number | string, max: number | string, withScores?: boolean): Promise<string[]>;
1365
+ /**
1366
+ * Gets score of member.
1367
+ * @returns Score or null if member doesn't exist
1368
+ */
1369
+ zscore(key: string, member: string): Promise<string | null>;
1370
+ /**
1371
+ * Gets number of members in sorted set.
1372
+ */
1373
+ zcard(key: string): Promise<number>;
1374
+ /**
1375
+ * Gets rank of member (0-based, lowest score first).
1376
+ * @returns Rank or null if member doesn't exist
1377
+ */
1378
+ zrank(key: string, member: string): Promise<number | null>;
1379
+ /**
1380
+ * Increments score of member.
1381
+ * @returns New score
1382
+ */
1383
+ zincrby(key: string, increment: number, member: string): Promise<string>;
1384
+ /**
1385
+ * Scans sorted set members.
1386
+ * @returns Cursor and array of member-score pairs
1387
+ */
1388
+ zscan(key: string, cursor: number, options?: IScanOptions): Promise<[string, string[]]>;
1389
+ /**
1390
+ * Gets reverse rank of member (highest score first).
1391
+ * @returns Rank or null if member doesn't exist
1392
+ */
1393
+ zrevrank(key: string, member: string): Promise<number | null>;
1394
+ /**
1395
+ * Counts members with scores in range.
1396
+ * @returns Number of members
1397
+ */
1398
+ zcount(key: string, min: number | string, max: number | string): Promise<number>;
1399
+ /**
1400
+ * Counts members in lexicographical range.
1401
+ * @returns Number of members
1402
+ */
1403
+ zlexcount(key: string, min: string, max: string): Promise<number>;
1404
+ /**
1405
+ * Removes and returns members with lowest scores.
1406
+ * @returns Array of [member, score] pairs
1407
+ */
1408
+ zpopmin(key: string, count?: number): Promise<string[]>;
1409
+ /**
1410
+ * Removes and returns members with highest scores.
1411
+ * @returns Array of [member, score] pairs
1412
+ */
1413
+ zpopmax(key: string, count?: number): Promise<string[]>;
1414
+ /**
1415
+ * Blocking pop from sorted set (lowest score).
1416
+ * @param timeout - Timeout in seconds
1417
+ * @returns [key, member, score] or null on timeout
1418
+ */
1419
+ bzpopmin(keys: string[], timeout: number): Promise<[string, string, string] | null>;
1420
+ /**
1421
+ * Blocking pop from sorted set (highest score).
1422
+ * @param timeout - Timeout in seconds
1423
+ * @returns [key, member, score] or null on timeout
1424
+ */
1425
+ bzpopmax(keys: string[], timeout: number): Promise<[string, string, string] | null>;
1426
+ /**
1427
+ * Computes union of sorted sets and stores result.
1428
+ * @param destination - Destination key
1429
+ * @param keys - Source keys
1430
+ * @param options - WEIGHTS and AGGREGATE options
1431
+ * @returns Number of elements in result
1432
+ */
1433
+ zunionstore(destination: string, keys: string[], options?: IZStoreOptions): Promise<number>;
1434
+ /**
1435
+ * Computes intersection of sorted sets and stores result.
1436
+ * @param destination - Destination key
1437
+ * @param keys - Source keys
1438
+ * @param options - WEIGHTS and AGGREGATE options
1439
+ * @returns Number of elements in result
1440
+ */
1441
+ zinterstore(destination: string, keys: string[], options?: IZStoreOptions): Promise<number>;
1442
+ /**
1443
+ * Gets scores of multiple members.
1444
+ * @returns Array of scores (null for non-existent members)
1445
+ */
1446
+ zmscore(key: string, ...members: string[]): Promise<Array<string | null>>;
1447
+ /**
1448
+ * Gets random members from sorted set.
1449
+ * @param count - Number of members (negative for duplicates allowed)
1450
+ * @param withScores - Include scores
1451
+ * @returns Random member(s) or member-score pairs
1452
+ */
1453
+ zrandmember(key: string, count?: number, withScores?: boolean): Promise<string | string[] | null>;
1454
+ /**
1455
+ * Gets members in score range in reverse order.
1456
+ * @returns Array of members (with scores if withScores)
1457
+ */
1458
+ zrevrangebyscore(key: string, max: number | string, min: number | string, options?: IZRangeByScoreOptions): Promise<string[]>;
1459
+ /**
1460
+ * Publishes message to channel.
1461
+ * @returns Number of subscribers that received the message
1462
+ */
1463
+ publish(channel: string, message: string): Promise<number>;
1464
+ /**
1465
+ * Subscribes to channels.
1466
+ */
1467
+ subscribe(...channels: string[]): Promise<void>;
1468
+ /**
1469
+ * Unsubscribes from channels.
1470
+ */
1471
+ unsubscribe(...channels: string[]): Promise<void>;
1472
+ /**
1473
+ * Subscribes to channels by pattern.
1474
+ */
1475
+ psubscribe(...patterns: string[]): Promise<void>;
1476
+ /**
1477
+ * Unsubscribes from channel patterns.
1478
+ */
1479
+ punsubscribe(...patterns: string[]): Promise<void>;
1480
+ /**
1481
+ * Adds entry to stream.
1482
+ * @param key - Stream key
1483
+ * @param id - Entry ID ('*' for auto-generated)
1484
+ * @param fields - Field-value pairs
1485
+ * @param options - Optional MAXLEN/MINID trimming
1486
+ * @returns Entry ID
1487
+ */
1488
+ xadd(key: string, id: string, fields: Record<string, string>, options?: IStreamAddOptions): Promise<string>;
1489
+ /**
1490
+ * Reads entries from streams.
1491
+ * @param streams - Stream keys and IDs to read from
1492
+ * @param options - Read options (COUNT, BLOCK)
1493
+ * @returns Array of stream entries or null
1494
+ */
1495
+ xread(streams: Array<{
1496
+ key: string;
1497
+ id: string;
1498
+ }>, options?: IStreamReadOptions): Promise<StreamReadResult | null>;
1499
+ /**
1500
+ * Reads entries from streams using consumer group.
1501
+ * @param group - Consumer group name
1502
+ * @param consumer - Consumer name
1503
+ * @param streams - Stream keys and IDs to read from
1504
+ * @param options - Read options (COUNT, BLOCK, NOACK)
1505
+ * @returns Array of stream entries or null
1506
+ */
1507
+ xreadgroup(group: string, consumer: string, streams: Array<{
1508
+ key: string;
1509
+ id: string;
1510
+ }>, options?: IStreamReadGroupOptions): Promise<StreamReadResult | null>;
1511
+ /**
1512
+ * Gets range of entries from stream.
1513
+ * @param key - Stream key
1514
+ * @param start - Start ID ('-' for oldest)
1515
+ * @param end - End ID ('+' for newest)
1516
+ * @param options - Optional COUNT
1517
+ * @returns Array of entries
1518
+ */
1519
+ xrange(key: string, start: string, end: string, options?: {
1520
+ count?: number;
1521
+ }): Promise<IStreamEntry[]>;
1522
+ /**
1523
+ * Gets range of entries in reverse order.
1524
+ * @param key - Stream key
1525
+ * @param end - End ID ('+' for newest)
1526
+ * @param start - Start ID ('-' for oldest)
1527
+ * @param options - Optional COUNT
1528
+ * @returns Array of entries
1529
+ */
1530
+ xrevrange(key: string, end: string, start: string, options?: {
1531
+ count?: number;
1532
+ }): Promise<IStreamEntry[]>;
1533
+ /**
1534
+ * Gets stream length.
1535
+ * @param key - Stream key
1536
+ * @returns Number of entries
1537
+ */
1538
+ xlen(key: string): Promise<number>;
1539
+ /**
1540
+ * Gets stream information.
1541
+ * @param key - Stream key
1542
+ * @returns Stream info object
1543
+ */
1544
+ xinfo(key: string): Promise<IStreamInfo>;
1545
+ /**
1546
+ * Trims stream to specified length.
1547
+ * @param key - Stream key
1548
+ * @param maxLen - Maximum length
1549
+ * @param approximate - Use '~' for approximate trimming (better performance)
1550
+ * @returns Number of entries removed
1551
+ */
1552
+ xtrim(key: string, maxLen: number, approximate?: boolean): Promise<number>;
1553
+ /**
1554
+ * Creates consumer group.
1555
+ * @param key - Stream key
1556
+ * @param group - Group name
1557
+ * @param id - Start ID ('$' for new entries only, '0' for all)
1558
+ * @param mkstream - Create stream if doesn't exist
1559
+ * @returns 'OK' if successful
1560
+ */
1561
+ xgroupCreate(key: string, group: string, id: string, mkstream?: boolean): Promise<'OK'>;
1562
+ /**
1563
+ * Destroys consumer group.
1564
+ * @param key - Stream key
1565
+ * @param group - Group name
1566
+ * @returns 1 if destroyed, 0 if didn't exist
1567
+ */
1568
+ xgroupDestroy(key: string, group: string): Promise<number>;
1569
+ /**
1570
+ * Deletes consumer from group.
1571
+ * @param key - Stream key
1572
+ * @param group - Group name
1573
+ * @param consumer - Consumer name
1574
+ * @returns Number of pending messages removed
1575
+ */
1576
+ xgroupDelConsumer(key: string, group: string, consumer: string): Promise<number>;
1577
+ /**
1578
+ * Sets consumer group last delivered ID.
1579
+ * @param key - Stream key
1580
+ * @param group - Group name
1581
+ * @param id - New last ID
1582
+ * @returns 'OK' if successful
1583
+ */
1584
+ xgroupSetId(key: string, group: string, id: string): Promise<'OK'>;
1585
+ /**
1586
+ * Acknowledges message processing.
1587
+ * @param key - Stream key
1588
+ * @param group - Group name
1589
+ * @param ids - Message IDs to acknowledge
1590
+ * @returns Number of messages acknowledged
1591
+ */
1592
+ xack(key: string, group: string, ...ids: string[]): Promise<number>;
1593
+ /**
1594
+ * Gets pending messages info.
1595
+ * @param key - Stream key
1596
+ * @param group - Group name
1597
+ * @returns Pending info summary
1598
+ */
1599
+ xpending(key: string, group: string): Promise<IStreamPendingInfo>;
1600
+ /**
1601
+ * Gets detailed pending messages.
1602
+ * @param key - Stream key
1603
+ * @param group - Group name
1604
+ * @param start - Start ID
1605
+ * @param end - End ID
1606
+ * @param count - Max entries to return
1607
+ * @param consumer - Optional consumer filter
1608
+ * @returns Array of pending entries
1609
+ */
1610
+ xpendingRange(key: string, group: string, start: string, end: string, count: number, consumer?: string): Promise<IStreamPendingEntry[]>;
1611
+ /**
1612
+ * Claims messages from another consumer.
1613
+ * @param key - Stream key
1614
+ * @param group - Group name
1615
+ * @param consumer - New consumer
1616
+ * @param minIdleTime - Minimum idle time in ms
1617
+ * @param ids - Message IDs to claim
1618
+ * @returns Claimed entries
1619
+ */
1620
+ xclaim(key: string, group: string, consumer: string, minIdleTime: number, ...ids: string[]): Promise<IStreamEntry[]>;
1621
+ /**
1622
+ * Deletes entries from stream.
1623
+ * @param key - Stream key
1624
+ * @param ids - Entry IDs to delete
1625
+ * @returns Number of entries deleted
1626
+ */
1627
+ xdel(key: string, ...ids: string[]): Promise<number>;
1628
+ /**
1629
+ * Creates a pipeline for batching commands.
1630
+ * Commands are executed atomically but not transactionally.
1631
+ */
1632
+ pipeline(): IPipeline;
1633
+ /**
1634
+ * Creates a multi/exec transaction.
1635
+ * Commands are executed atomically and transactionally.
1636
+ */
1637
+ multi(): IMulti;
1638
+ /**
1639
+ * Evaluates Lua script.
1640
+ * @param script - Lua script source
1641
+ * @param keys - KEYS array
1642
+ * @param args - ARGV array
1643
+ * @returns Script result
1644
+ */
1645
+ eval(script: string, keys: string[], args: Array<string | number>): Promise<unknown>;
1646
+ /**
1647
+ * Evaluates Lua script by SHA.
1648
+ * @param sha - Script SHA hash
1649
+ * @param keys - KEYS array
1650
+ * @param args - ARGV array
1651
+ * @returns Script result
1652
+ */
1653
+ evalsha(sha: string, keys: string[], args: Array<string | number>): Promise<unknown>;
1654
+ /**
1655
+ * Loads Lua script and returns SHA.
1656
+ * @param script - Lua script source
1657
+ * @returns SHA hash
1658
+ */
1659
+ scriptLoad(script: string): Promise<string>;
1660
+ /**
1661
+ * Checks if scripts exist.
1662
+ * @param shas - Script SHA hashes
1663
+ * @returns Array of 1/0 for each script
1664
+ */
1665
+ scriptExists(...shas: string[]): Promise<number[]>;
1666
+ /**
1667
+ * Flushes all scripts from cache.
1668
+ * @returns 'OK' if successful
1669
+ */
1670
+ scriptFlush(): Promise<'OK'>;
1671
+ /**
1672
+ * Flushes all keys from current database.
1673
+ * @returns 'OK' if successful
1674
+ */
1675
+ flushdb(): Promise<'OK'>;
1676
+ /**
1677
+ * Flushes all keys from all databases.
1678
+ * @returns 'OK' if successful
1679
+ */
1680
+ flushall(): Promise<'OK'>;
1681
+ /**
1682
+ * Gets server info.
1683
+ * @param section - Optional info section
1684
+ * @returns Info string
1685
+ */
1686
+ info(section?: string): Promise<string>;
1687
+ /**
1688
+ * Gets database size (number of keys).
1689
+ * @returns Number of keys
1690
+ */
1691
+ dbsize(): Promise<number>;
1692
+ /**
1693
+ * Adds elements to HyperLogLog.
1694
+ * @returns 1 if cardinality changed, 0 otherwise
1695
+ */
1696
+ pfadd(key: string, ...elements: string[]): Promise<number>;
1697
+ /**
1698
+ * Returns estimated cardinality.
1699
+ * @returns Estimated number of unique elements
1700
+ */
1701
+ pfcount(...keys: string[]): Promise<number>;
1702
+ /**
1703
+ * Merges HyperLogLogs into destination.
1704
+ * @returns 'OK' if successful
1705
+ */
1706
+ pfmerge(destination: string, ...sources: string[]): Promise<'OK'>;
1707
+ /**
1708
+ * Adds geospatial members.
1709
+ * @param members - Array of [longitude, latitude, member]
1710
+ * @returns Number of members added
1711
+ */
1712
+ geoadd(key: string, ...members: Array<number | string>): Promise<number>;
1713
+ /**
1714
+ * Returns distance between two members.
1715
+ * @param unit - m, km, mi, ft
1716
+ * @returns Distance or null if member doesn't exist
1717
+ */
1718
+ geodist(key: string, member1: string, member2: string, unit?: GeoUnit): Promise<string | null>;
1719
+ /**
1720
+ * Returns geohash strings for members.
1721
+ * @returns Array of geohash strings (null for non-existent)
1722
+ */
1723
+ geohash(key: string, ...members: string[]): Promise<Array<string | null>>;
1724
+ /**
1725
+ * Returns positions of members.
1726
+ * @returns Array of [longitude, latitude] or null
1727
+ */
1728
+ geopos(key: string, ...members: string[]): Promise<Array<[string, string] | null>>;
1729
+ /**
1730
+ * Searches for members in radius.
1731
+ * @returns Array of members with optional distance/coordinates
1732
+ */
1733
+ geosearch(key: string, options: IGeoSearchOptions): Promise<Array<string | IGeoSearchResult>>;
1734
+ /**
1735
+ * Searches and stores result.
1736
+ * @returns Number of members in result
1737
+ */
1738
+ geosearchstore(destination: string, source: string, options: IGeoSearchOptions & {
1739
+ storedist?: boolean;
1740
+ }): Promise<number>;
1741
+ /**
1742
+ * Sets bit at offset.
1743
+ * @returns Previous bit value
1744
+ */
1745
+ setbit(key: string, offset: number, value: 0 | 1): Promise<number>;
1746
+ /**
1747
+ * Gets bit at offset.
1748
+ * @returns Bit value (0 or 1)
1749
+ */
1750
+ getbit(key: string, offset: number): Promise<number>;
1751
+ /**
1752
+ * Counts set bits in range.
1753
+ * @param start - Start byte offset
1754
+ * @param end - End byte offset
1755
+ * @param mode - BYTE or BIT
1756
+ * @returns Number of set bits
1757
+ */
1758
+ bitcount(key: string, start?: number, end?: number, mode?: 'BYTE' | 'BIT'): Promise<number>;
1759
+ /**
1760
+ * Performs bitwise operations.
1761
+ * @param operation - AND, OR, XOR, NOT
1762
+ * @param destKey - Destination key
1763
+ * @param keys - Source keys (one for NOT)
1764
+ * @returns Size of result in bytes
1765
+ */
1766
+ bitop(operation: 'AND' | 'OR' | 'XOR' | 'NOT', destKey: string, ...keys: string[]): Promise<number>;
1767
+ /**
1768
+ * Finds first bit set to value.
1769
+ * @param bit - 0 or 1
1770
+ * @param start - Start byte offset
1771
+ * @param end - End byte offset
1772
+ * @param mode - BYTE or BIT
1773
+ * @returns Position of first bit, -1 if not found
1774
+ */
1775
+ bitpos(key: string, bit: 0 | 1, start?: number, end?: number, mode?: 'BYTE' | 'BIT'): Promise<number>;
1776
+ /**
1777
+ * Executes Redis Cluster commands.
1778
+ * @param subcommand - Cluster subcommand (INFO, NODES, etc.)
1779
+ * @param args - Additional arguments
1780
+ * @returns Command result
1781
+ */
1782
+ cluster(subcommand: string, ...args: Array<string | number>): Promise<unknown>;
1783
+ /**
1784
+ * Executes Redis Sentinel commands.
1785
+ * @param subcommand - Sentinel subcommand (masters, master, replicas, etc.)
1786
+ * @param args - Additional arguments
1787
+ * @returns Command result
1788
+ */
1789
+ sentinel(subcommand: string, ...args: Array<string | number>): Promise<unknown>;
1790
+ /**
1791
+ * Registers event handler.
1792
+ */
1793
+ on(event: DriverEvent, handler: DriverEventHandler): void;
1794
+ /**
1795
+ * Registers one-time event handler.
1796
+ */
1797
+ once(event: DriverEvent, handler: DriverEventHandler): void;
1798
+ /**
1799
+ * Unregisters event handler.
1800
+ */
1801
+ off(event: DriverEvent, handler: DriverEventHandler): void;
1802
+ /**
1803
+ * Removes all listeners for event.
1804
+ */
1805
+ removeAllListeners(event?: DriverEvent): void;
1806
+ }
1807
+ /**
1808
+ * Options for SET command.
1809
+ */
1810
+ interface ISetOptions {
1811
+ /**
1812
+ * Expiration in seconds (EX).
1813
+ */
1814
+ ex?: number;
1815
+ /**
1816
+ * Expiration in milliseconds (PX).
1817
+ */
1818
+ px?: number;
1819
+ /**
1820
+ * Expiration Unix timestamp in seconds (EXAT).
1821
+ */
1822
+ exat?: number;
1823
+ /**
1824
+ * Expiration Unix timestamp in milliseconds (PXAT).
1825
+ */
1826
+ pxat?: number;
1827
+ /**
1828
+ * Only set if key exists (XX).
1829
+ */
1830
+ xx?: boolean;
1831
+ /**
1832
+ * Only set if key doesn't exist (NX).
1833
+ */
1834
+ nx?: boolean;
1835
+ /**
1836
+ * Return previous value (GET).
1837
+ */
1838
+ get?: boolean;
1839
+ /**
1840
+ * Keep existing TTL (KEEPTTL).
1841
+ */
1842
+ keepttl?: boolean;
1843
+ }
1844
+ /**
1845
+ * Options for SCAN family commands.
1846
+ */
1847
+ interface IScanOptions {
1848
+ /**
1849
+ * Match pattern.
1850
+ */
1851
+ match?: string;
1852
+ /**
1853
+ * Count hint (not exact).
1854
+ */
1855
+ count?: number;
1856
+ /**
1857
+ * Type filter (for SCAN only).
1858
+ */
1859
+ type?: string;
1860
+ }
1861
+ /**
1862
+ * Pipeline for batching Redis commands.
1863
+ * Commands are buffered and sent to server in a single round-trip.
1864
+ */
1865
+ interface IPipeline {
1866
+ /**
1867
+ * Executes all queued commands.
1868
+ * @returns Array of [error, result] tuples for each command
1869
+ */
1870
+ exec(): Promise<Array<[Error | null, unknown]>>;
1871
+ get(key: string): this;
1872
+ set(key: string, value: string, options?: ISetOptions): this;
1873
+ del(...keys: string[]): this;
1874
+ mget(...keys: string[]): this;
1875
+ mset(data: Record<string, string>): this;
1876
+ expire(key: string, seconds: number): this;
1877
+ ttl(key: string): this;
1878
+ incr(key: string): this;
1879
+ incrby(key: string, increment: number): this;
1880
+ hget(key: string, field: string): this;
1881
+ hset(key: string, field: string, value: string): this;
1882
+ hmset(key: string, data: Record<string, string>): this;
1883
+ hgetall(key: string): this;
1884
+ lpush(key: string, ...values: string[]): this;
1885
+ rpush(key: string, ...values: string[]): this;
1886
+ sadd(key: string, ...members: string[]): this;
1887
+ srem(key: string, ...members: string[]): this;
1888
+ zadd(key: string, ...args: Array<number | string>): this;
1889
+ zrem(key: string, ...members: string[]): this;
1890
+ }
1891
+ /**
1892
+ * Multi/Exec transaction.
1893
+ * Commands are executed atomically and transactionally.
1894
+ */
1895
+ interface IMulti extends IPipeline {
1896
+ /**
1897
+ * Discards transaction.
1898
+ */
1899
+ discard(): void;
1900
+ }
1901
+ /**
1902
+ * Options for XADD command.
1903
+ */
1904
+ interface IStreamAddOptions {
1905
+ /**
1906
+ * Maximum stream length (MAXLEN).
1907
+ */
1908
+ maxLen?: number;
1909
+ /**
1910
+ * Use approximate trimming (~) for better performance.
1911
+ */
1912
+ approximate?: boolean;
1913
+ /**
1914
+ * Only add if stream exists (NOMKSTREAM).
1915
+ */
1916
+ noMkStream?: boolean;
1917
+ /**
1918
+ * Minimum ID for trimming (MINID).
1919
+ */
1920
+ minId?: string;
1921
+ }
1922
+ /**
1923
+ * Options for XREAD command.
1924
+ */
1925
+ interface IStreamReadOptions {
1926
+ /**
1927
+ * Maximum entries per stream.
1928
+ */
1929
+ count?: number;
1930
+ /**
1931
+ * Block timeout in milliseconds (0 = forever).
1932
+ */
1933
+ block?: number;
1934
+ }
1935
+ /**
1936
+ * Options for XREADGROUP command.
1937
+ */
1938
+ interface IStreamReadGroupOptions extends IStreamReadOptions {
1939
+ /**
1940
+ * Don't add to pending list.
1941
+ */
1942
+ noAck?: boolean;
1943
+ }
1944
+ /**
1945
+ * Single stream entry.
1946
+ */
1947
+ interface IStreamEntry {
1948
+ /**
1949
+ * Entry ID (timestamp-sequence).
1950
+ */
1951
+ id: string;
1952
+ /**
1953
+ * Entry fields.
1954
+ */
1955
+ fields: Record<string, string>;
1956
+ }
1957
+ /**
1958
+ * Result from XREAD/XREADGROUP.
1959
+ */
1960
+ type StreamReadResult = Array<{
1961
+ /**
1962
+ * Stream key.
1963
+ */
1964
+ key: string;
1965
+ /**
1966
+ * Entries read from stream.
1967
+ */
1968
+ entries: IStreamEntry[];
1969
+ }>;
1970
+ /**
1971
+ * Stream information from XINFO.
1972
+ */
1973
+ interface IStreamInfo {
1974
+ /**
1975
+ * Number of entries.
1976
+ */
1977
+ length: number;
1978
+ /**
1979
+ * Number of consumer groups.
1980
+ */
1981
+ groups: number;
1982
+ /**
1983
+ * First entry ID.
1984
+ */
1985
+ firstEntry: IStreamEntry | null;
1986
+ /**
1987
+ * Last entry ID.
1988
+ */
1989
+ lastEntry: IStreamEntry | null;
1990
+ /**
1991
+ * Last generated ID.
1992
+ */
1993
+ lastGeneratedId: string;
1994
+ /**
1995
+ * Radix tree keys.
1996
+ */
1997
+ radixTreeKeys: number;
1998
+ /**
1999
+ * Radix tree nodes.
2000
+ */
2001
+ radixTreeNodes: number;
2002
+ }
2003
+ /**
2004
+ * Pending messages summary from XPENDING.
2005
+ */
2006
+ interface IStreamPendingInfo {
2007
+ /**
2008
+ * Total pending count.
2009
+ */
2010
+ count: number;
2011
+ /**
2012
+ * Smallest pending ID.
2013
+ */
2014
+ minId: string | null;
2015
+ /**
2016
+ * Largest pending ID.
2017
+ */
2018
+ maxId: string | null;
2019
+ /**
2020
+ * Pending count per consumer.
2021
+ */
2022
+ consumers: Array<{
2023
+ name: string;
2024
+ count: number;
2025
+ }>;
2026
+ }
2027
+ /**
2028
+ * Single pending entry from XPENDING with range.
2029
+ */
2030
+ interface IStreamPendingEntry {
2031
+ /**
2032
+ * Entry ID.
2033
+ */
2034
+ id: string;
2035
+ /**
2036
+ * Consumer name.
2037
+ */
2038
+ consumer: string;
2039
+ /**
2040
+ * Idle time in milliseconds.
2041
+ */
2042
+ idleTime: number;
2043
+ /**
2044
+ * Delivery count.
2045
+ */
2046
+ deliveryCount: number;
2047
+ }
2048
+ /**
2049
+ * Driver events.
2050
+ */
2051
+ declare enum DriverEvent {
2052
+ CONNECT = "connect",
2053
+ READY = "ready",
2054
+ DISCONNECT = "disconnect",
2055
+ CLOSE = "close",
2056
+ ERROR = "error",
2057
+ RECONNECTING = "reconnecting",
2058
+ END = "end"
2059
+ }
2060
+ /**
2061
+ * Driver event handler.
2062
+ */
2063
+ type DriverEventHandler = (data?: unknown) => void;
2064
+ /**
2065
+ * Options for COPY command.
2066
+ */
2067
+ interface ICopyOptions {
2068
+ /**
2069
+ * Target database number.
2070
+ */
2071
+ db?: number;
2072
+ /**
2073
+ * Replace existing key.
2074
+ */
2075
+ replace?: boolean;
2076
+ }
2077
+ /**
2078
+ * Options for RESTORE command.
2079
+ */
2080
+ interface IRestoreOptions {
2081
+ /**
2082
+ * Replace existing key.
2083
+ */
2084
+ replace?: boolean;
2085
+ /**
2086
+ * Absolute Unix timestamp (milliseconds) for expiration.
2087
+ */
2088
+ absttl?: boolean;
2089
+ /**
2090
+ * Eviction time in seconds.
2091
+ */
2092
+ idletime?: number;
2093
+ /**
2094
+ * Eviction frequency.
2095
+ */
2096
+ freq?: number;
2097
+ }
2098
+ /**
2099
+ * Options for LPOS command.
2100
+ */
2101
+ interface ILposOptions {
2102
+ /**
2103
+ * Search from Nth match.
2104
+ */
2105
+ rank?: number;
2106
+ /**
2107
+ * Return count matches.
2108
+ */
2109
+ count?: number;
2110
+ /**
2111
+ * Limit comparisons.
2112
+ */
2113
+ maxlen?: number;
2114
+ }
2115
+ /**
2116
+ * Options for ZRANGEBYSCORE command.
2117
+ */
2118
+ interface IZRangeByScoreOptions {
2119
+ /**
2120
+ * Include scores in result.
2121
+ */
2122
+ withScores?: boolean;
2123
+ /**
2124
+ * Limit results.
2125
+ */
2126
+ limit?: {
2127
+ offset: number;
2128
+ count: number;
2129
+ };
2130
+ }
2131
+ /**
2132
+ * Options for ZUNIONSTORE/ZINTERSTORE commands.
2133
+ */
2134
+ interface IZStoreOptions {
2135
+ /**
2136
+ * Weight for each input key.
2137
+ */
2138
+ weights?: number[];
2139
+ /**
2140
+ * How to aggregate scores.
2141
+ */
2142
+ aggregate?: 'SUM' | 'MIN' | 'MAX';
2143
+ }
2144
+ /**
2145
+ * Geo distance unit.
2146
+ */
2147
+ type GeoUnit = 'm' | 'km' | 'mi' | 'ft';
2148
+ /**
2149
+ * Options for GEOSEARCH command.
2150
+ */
2151
+ interface IGeoSearchOptions {
2152
+ /**
2153
+ * Search from member.
2154
+ */
2155
+ member?: string;
2156
+ /**
2157
+ * Search from coordinates.
2158
+ */
2159
+ coord?: {
2160
+ longitude: number;
2161
+ latitude: number;
2162
+ };
2163
+ /**
2164
+ * Search by radius.
2165
+ */
2166
+ radius?: {
2167
+ value: number;
2168
+ unit: GeoUnit;
2169
+ };
2170
+ /**
2171
+ * Search by box.
2172
+ */
2173
+ box?: {
2174
+ width: number;
2175
+ height: number;
2176
+ unit: GeoUnit;
2177
+ };
2178
+ /**
2179
+ * Sort order.
2180
+ */
2181
+ sort?: 'ASC' | 'DESC';
2182
+ /**
2183
+ * Limit results.
2184
+ */
2185
+ count?: number;
2186
+ /**
2187
+ * Use ANY with count.
2188
+ */
2189
+ any?: boolean;
2190
+ /**
2191
+ * Include coordinates.
2192
+ */
2193
+ withCoord?: boolean;
2194
+ /**
2195
+ * Include distance.
2196
+ */
2197
+ withDist?: boolean;
2198
+ /**
2199
+ * Include hash.
2200
+ */
2201
+ withHash?: boolean;
2202
+ }
2203
+ /**
2204
+ * Geo search result with optional data.
2205
+ */
2206
+ interface IGeoSearchResult {
2207
+ member: string;
2208
+ distance?: string;
2209
+ hash?: number;
2210
+ coordinates?: [string, string];
2211
+ }
2212
+
2213
+ /**
2214
+ * Redis client interface.
2215
+ *
2216
+ * Wraps IRedisDriver with additional client-level functionality.
2217
+ * Manages connection lifecycle, health checks, and metadata.
2218
+ *
2219
+ * @example
2220
+ * ```typescript
2221
+ * @Injectable()
2222
+ * export class MyService {
2223
+ * constructor(
2224
+ * @Inject(REDIS_CLIENT) private readonly client: IRedisClient
2225
+ * ) {}
2226
+ *
2227
+ * async getData() {
2228
+ * if (this.client.isHealthy()) {
2229
+ * return await this.client.get('key');
2230
+ * }
2231
+ * }
2232
+ * }
2233
+ * ```
2234
+ */
2235
+ interface IRedisClient extends IRedisDriver {
2236
+ /**
2237
+ * Gets client name.
2238
+ */
2239
+ readonly name: string;
2240
+ /**
2241
+ * Gets connection configuration.
2242
+ */
2243
+ readonly config: ConnectionConfig;
2244
+ /**
2245
+ * Gets client metadata.
2246
+ */
2247
+ getMetadata(): IClientMetadata;
2248
+ /**
2249
+ * Checks if client is healthy (connected and responsive).
2250
+ */
2251
+ isHealthy(): boolean;
2252
+ /**
2253
+ * Gets connection uptime in milliseconds.
2254
+ * @returns Uptime or null if not connected
2255
+ */
2256
+ getUptime(): number | null;
2257
+ /**
2258
+ * Measures latency by pinging server.
2259
+ * @returns Latency in milliseconds or null if disconnected
2260
+ */
2261
+ getLatency(): Promise<number | null>;
2262
+ /**
2263
+ * Gets last error if any.
2264
+ */
2265
+ getLastError(): Error | null;
2266
+ /**
2267
+ * Clears last error.
2268
+ */
2269
+ clearLastError(): void;
2270
+ /**
2271
+ * Reconnects to Redis.
2272
+ * Disconnects if connected, then connects again.
2273
+ */
2274
+ reconnect(): Promise<void>;
2275
+ /**
2276
+ * Quits gracefully.
2277
+ * Waits for pending commands to complete before disconnecting.
2278
+ */
2279
+ quit(): Promise<void>;
2280
+ /**
2281
+ * Creates a namespaced client.
2282
+ * All keys will be prefixed with namespace.
2283
+ *
2284
+ * @example
2285
+ * ```typescript
2286
+ * const userClient = client.namespace('user');
2287
+ * await userClient.set('123', data); // Actually sets 'user:123'
2288
+ * ```
2289
+ */
2290
+ namespace(prefix: string): IRedisClient;
2291
+ /**
2292
+ * Gets current namespace prefix.
2293
+ */
2294
+ getNamespace(): string | null;
2295
+ }
2296
+ /**
2297
+ * Client manager interface.
2298
+ * Manages multiple named Redis clients.
2299
+ */
2300
+ interface IClientManager {
2301
+ /**
2302
+ * Gets client by name.
2303
+ * @throws Error if client not found
2304
+ */
2305
+ getClient(name?: string): IRedisClient;
2306
+ /**
2307
+ * Checks if client exists.
2308
+ */
2309
+ hasClient(name: string): boolean;
2310
+ /**
2311
+ * Gets all client names.
2312
+ */
2313
+ getClientNames(): string[];
2314
+ /**
2315
+ * Registers a new client.
2316
+ * @throws Error if client with same name already exists
2317
+ */
2318
+ registerClient(name: string, client: IRedisClient): Promise<void>;
2319
+ /**
2320
+ * Removes and disconnects client.
2321
+ */
2322
+ removeClient(name: string): Promise<void>;
2323
+ /**
2324
+ * Gets all clients.
2325
+ */
2326
+ getAllClients(): Map<string, IRedisClient>;
2327
+ /**
2328
+ * Checks health of all clients.
2329
+ */
2330
+ checkHealth(): Promise<Map<string, boolean>>;
2331
+ /**
2332
+ * Disconnects all clients.
2333
+ */
2334
+ disconnectAll(): Promise<void>;
2335
+ }
2336
+
2337
+ /**
2338
+ * Health check status for Redis client.
2339
+ */
2340
+ interface IHealthStatus {
2341
+ /**
2342
+ * Client name.
2343
+ */
2344
+ name: string;
2345
+ /**
2346
+ * Whether client is healthy (connected and responsive).
2347
+ */
2348
+ healthy: boolean;
2349
+ /**
2350
+ * Current connection status.
2351
+ */
2352
+ status: ConnectionStatus;
2353
+ /**
2354
+ * Latency in milliseconds (from PING command).
2355
+ * null if not connected or ping failed.
2356
+ */
2357
+ latency: number | null;
2358
+ /**
2359
+ * Last error if any.
2360
+ */
2361
+ lastError: string | null;
2362
+ /**
2363
+ * Timestamp of last successful check.
2364
+ */
2365
+ lastCheckAt: Date;
2366
+ /**
2367
+ * Additional metadata.
2368
+ */
2369
+ metadata: {
2370
+ /**
2371
+ * Driver type (ioredis or node-redis).
2372
+ */
2373
+ driverType: string;
2374
+ /**
2375
+ * Connection type (single, cluster, sentinel).
2376
+ */
2377
+ connectionType: string;
2378
+ /**
2379
+ * Number of reconnection attempts.
2380
+ */
2381
+ reconnectAttempts: number;
2382
+ /**
2383
+ * Uptime in milliseconds.
2384
+ */
2385
+ uptime: number;
2386
+ };
2387
+ }
2388
+ /**
2389
+ * Connection statistics for all clients.
2390
+ */
2391
+ interface IConnectionStats {
2392
+ /**
2393
+ * Total number of registered clients.
2394
+ */
2395
+ totalClients: number;
2396
+ /**
2397
+ * Number of connected clients.
2398
+ */
2399
+ connectedClients: number;
2400
+ /**
2401
+ * Number of disconnected clients.
2402
+ */
2403
+ disconnectedClients: number;
2404
+ /**
2405
+ * Number of clients with errors.
2406
+ */
2407
+ errorClients: number;
2408
+ /**
2409
+ * Per-client statistics.
2410
+ */
2411
+ clients: Record<string, IClientStats>;
2412
+ /**
2413
+ * Timestamp when stats were collected.
2414
+ */
2415
+ collectedAt: Date;
2416
+ }
2417
+ /**
2418
+ * Statistics for individual client.
2419
+ */
2420
+ interface IClientStats {
2421
+ /**
2422
+ * Client name.
2423
+ */
2424
+ name: string;
2425
+ /**
2426
+ * Current status.
2427
+ */
2428
+ status: ConnectionStatus;
2429
+ /**
2430
+ * Total commands executed.
2431
+ */
2432
+ commandsExecuted: number;
2433
+ /**
2434
+ * Total errors.
2435
+ */
2436
+ errors: number;
2437
+ /**
2438
+ * Total reconnections.
2439
+ */
2440
+ reconnections: number;
2441
+ /**
2442
+ * Average latency in milliseconds.
2443
+ */
2444
+ averageLatency: number;
2445
+ /**
2446
+ * Peak latency in milliseconds.
2447
+ */
2448
+ peakLatency: number;
2449
+ /**
2450
+ * Last activity timestamp.
2451
+ */
2452
+ lastActivityAt: Date | null;
2453
+ /**
2454
+ * Connected since timestamp.
2455
+ */
2456
+ connectedAt: Date | null;
2457
+ /**
2458
+ * Total uptime in milliseconds.
2459
+ */
2460
+ uptime: number;
2461
+ }
2462
+ /**
2463
+ * Reconnection options.
2464
+ */
2465
+ interface IReconnectionOptions {
2466
+ /**
2467
+ * Maximum number of reconnection attempts.
2468
+ * @default Infinity
2469
+ */
2470
+ maxAttempts?: number;
2471
+ /**
2472
+ * Initial delay in milliseconds.
2473
+ * @default 1000
2474
+ */
2475
+ initialDelay?: number;
2476
+ /**
2477
+ * Maximum delay in milliseconds.
2478
+ * @default 30000
2479
+ */
2480
+ maxDelay?: number;
2481
+ /**
2482
+ * Exponential backoff multiplier.
2483
+ * @default 2
2484
+ */
2485
+ backoffMultiplier?: number;
2486
+ /**
2487
+ * Enable jitter to prevent thundering herd.
2488
+ * @default true
2489
+ */
2490
+ enableJitter?: boolean;
2491
+ }
2492
+
2493
+ /**
2494
+ * Redis driver manager interface.
2495
+ *
2496
+ * Manages multiple Redis driver connections with:
2497
+ * - Lazy connection (connect on first use)
2498
+ * - Automatic reconnection with exponential backoff
2499
+ * - Health monitoring
2500
+ * - Graceful shutdown
2501
+ * - Connection pooling
2502
+ *
2503
+ * @example
2504
+ * ```typescript
2505
+ * @Injectable()
2506
+ * export class CacheService {
2507
+ * constructor(
2508
+ * @Inject(CLIENT_MANAGER) private readonly clientManager: IRedisDriverManager
2509
+ * ) {}
2510
+ *
2511
+ * async get(key: string): Promise<string | null> {
2512
+ * const driver = await this.clientManager.getClient('cache');
2513
+ * return driver.get(key);
2514
+ * }
2515
+ * }
2516
+ * ```
2517
+ */
2518
+ interface IRedisDriverManager {
2519
+ /**
2520
+ * Gets Redis driver by name.
2521
+ *
2522
+ * Performs lazy connection on first access.
2523
+ * Subsequent calls return the same connected driver.
2524
+ *
2525
+ * @param name - Client name (default: 'default')
2526
+ * @returns Redis driver instance
2527
+ * @throws Error if client not found or connection fails
2528
+ *
2529
+ * @example
2530
+ * ```typescript
2531
+ * const driver = await manager.getClient('cache');
2532
+ * await driver.set('key', 'value');
2533
+ * ```
2534
+ */
2535
+ getClient(name?: string): Promise<IRedisDriver>;
2536
+ /**
2537
+ * Creates and registers a new Redis driver.
2538
+ *
2539
+ * @param name - Unique client name
2540
+ * @param config - Redis connection configuration
2541
+ * @param options - Optional client options
2542
+ * @returns Created driver instance
2543
+ * @throws Error if client with this name already exists
2544
+ *
2545
+ * @example
2546
+ * ```typescript
2547
+ * const driver = await manager.createClient('sessions', {
2548
+ * type: 'single',
2549
+ * host: 'localhost',
2550
+ * port: 6379,
2551
+ * db: 1,
2552
+ * });
2553
+ * ```
2554
+ */
2555
+ createClient(name: string, config: ConnectionConfig, options?: {
2556
+ reconnection?: IReconnectionOptions;
2557
+ metadata?: Partial<IClientMetadata>;
2558
+ }): Promise<IRedisDriver>;
2559
+ /**
2560
+ * Checks if client exists.
2561
+ *
2562
+ * @param name - Client name
2563
+ * @returns true if client is registered
2564
+ */
2565
+ hasClient(name: string): boolean;
2566
+ /**
2567
+ * Gets all registered client names.
2568
+ *
2569
+ * @returns Array of client names
2570
+ */
2571
+ getClientNames(): string[];
2572
+ /**
2573
+ * Closes specific client connection.
2574
+ *
2575
+ * Gracefully disconnects and removes client from registry.
2576
+ *
2577
+ * @param name - Client name
2578
+ * @throws Error if client not found
2579
+ *
2580
+ * @example
2581
+ * ```typescript
2582
+ * await manager.closeClient('cache');
2583
+ * ```
2584
+ */
2585
+ closeClient(name: string): Promise<void>;
2586
+ /**
2587
+ * Closes all client connections.
2588
+ *
2589
+ * Performs graceful shutdown of all clients in parallel.
2590
+ * Safe to call multiple times.
2591
+ *
2592
+ * @example
2593
+ * ```typescript
2594
+ * await manager.closeAll();
2595
+ * ```
2596
+ */
2597
+ closeAll(): Promise<void>;
2598
+ /**
2599
+ * Performs health check on client(s).
2600
+ *
2601
+ * Executes PING command and measures latency.
2602
+ *
2603
+ * @param name - Client name (if omitted, checks all clients)
2604
+ * @returns Health status for specified client(s)
2605
+ *
2606
+ * @example
2607
+ * ```typescript
2608
+ * // Check single client
2609
+ * const health = await manager.healthCheck('cache');
2610
+ * if (!health.healthy) {
2611
+ * logger.error('Cache unhealthy', health);
2612
+ * }
2613
+ *
2614
+ * // Check all clients
2615
+ * const allHealth = await manager.healthCheck();
2616
+ * ```
2617
+ */
2618
+ healthCheck(name?: string): Promise<IHealthStatus | IHealthStatus[]>;
2619
+ /**
2620
+ * Gets connection statistics.
2621
+ *
2622
+ * Returns aggregate stats for all clients.
2623
+ *
2624
+ * @returns Connection statistics
2625
+ *
2626
+ * @example
2627
+ * ```typescript
2628
+ * const stats = manager.getStats();
2629
+ * console.log(`Connected: ${stats.connectedClients}/${stats.totalClients}`);
2630
+ * ```
2631
+ */
2632
+ getStats(): IConnectionStats;
2633
+ /**
2634
+ * Gets client metadata.
2635
+ *
2636
+ * @param name - Client name
2637
+ * @returns Client metadata
2638
+ * @throws Error if client not found
2639
+ */
2640
+ getMetadata(name: string): IClientMetadata;
2641
+ /**
2642
+ * Updates client metadata.
2643
+ *
2644
+ * @param name - Client name
2645
+ * @param metadata - Partial metadata to merge
2646
+ */
2647
+ updateMetadata(name: string, metadata: Partial<IClientMetadata>): void;
2648
+ /**
2649
+ * Registers event listener for all clients.
2650
+ *
2651
+ * @param event - Event name
2652
+ * @param handler - Event handler
2653
+ *
2654
+ * @example
2655
+ * ```typescript
2656
+ * manager.on('manager:reconnecting', (data) => {
2657
+ * logger.warn(`Client ${data.name} reconnecting...`);
2658
+ * });
2659
+ * ```
2660
+ */
2661
+ on(event: ManagerEvent, handler: ManagerEventHandler): void;
2662
+ /**
2663
+ * Unregisters event listener.
2664
+ *
2665
+ * @param event - Event name
2666
+ * @param handler - Event handler
2667
+ */
2668
+ off(event: ManagerEvent, handler: ManagerEventHandler): void;
2669
+ }
2670
+ /**
2671
+ * Manager-specific events.
2672
+ */
2673
+ declare enum ManagerEvent {
2674
+ /**
2675
+ * Client connected.
2676
+ */
2677
+ CONNECTED = "manager:connected",
2678
+ /**
2679
+ * Client disconnected.
2680
+ */
2681
+ DISCONNECTED = "manager:disconnected",
2682
+ /**
2683
+ * Client reconnecting.
2684
+ */
2685
+ RECONNECTING = "manager:reconnecting",
2686
+ /**
2687
+ * Client error.
2688
+ */
2689
+ ERROR = "manager:error",
2690
+ /**
2691
+ * Client created.
2692
+ */
2693
+ CREATED = "manager:created",
2694
+ /**
2695
+ * Client removed.
2696
+ */
2697
+ REMOVED = "manager:removed"
2698
+ }
2699
+ /**
2700
+ * Manager event data.
2701
+ */
2702
+ interface IManagerEventData {
2703
+ /**
2704
+ * Client name.
2705
+ */
2706
+ name: string;
2707
+ /**
2708
+ * Event timestamp.
2709
+ */
2710
+ timestamp: Date;
2711
+ /**
2712
+ * Error if any.
2713
+ */
2714
+ error?: Error;
2715
+ /**
2716
+ * Additional context.
2717
+ */
2718
+ metadata?: Record<string, unknown>;
2719
+ }
2720
+ /**
2721
+ * Manager event handler.
2722
+ */
2723
+ type ManagerEventHandler = (data: IManagerEventData) => void;
2724
+
2725
+ /**
2726
+ * Redis Client Manager.
2727
+ *
2728
+ * Manages multiple Redis client connections with:
2729
+ * - Lazy connection (connect on first use)
2730
+ * - Automatic reconnection with exponential backoff
2731
+ * - Health monitoring and statistics
2732
+ * - Graceful shutdown
2733
+ * - Event notifications
2734
+ *
2735
+ * @example
2736
+ * ```typescript
2737
+ * @Injectable()
2738
+ * export class AppService {
2739
+ * constructor(
2740
+ * @Inject(CLIENT_MANAGER) private readonly clientManager: RedisClientManager
2741
+ * ) {}
2742
+ *
2743
+ * async cacheValue(key: string, value: string): Promise<void> {
2744
+ * const client = await this.clientManager.getClient('cache');
2745
+ * await client.set(key, value, { ex: 3600 });
2746
+ * }
2747
+ * }
2748
+ * ```
2749
+ */
2750
+ declare class RedisClientManager implements IRedisDriverManager, OnModuleDestroy {
2751
+ private readonly logger;
2752
+ /**
2753
+ * Registered clients.
2754
+ */
2755
+ private readonly clients;
2756
+ /**
2757
+ * Event emitter for client events.
2758
+ */
2759
+ private readonly eventEmitter;
2760
+ /**
2761
+ * Whether manager is shutting down.
2762
+ */
2763
+ private isShuttingDown;
2764
+ /**
2765
+ * Default reconnection options.
2766
+ */
2767
+ private readonly defaultIReconnectionOptions;
2768
+ /**
2769
+ * Default driver type.
2770
+ */
2771
+ private readonly defaultDriverType;
2772
+ /**
2773
+ * Gets Redis client by name with lazy connection.
2774
+ */
2775
+ getClient(name?: string): Promise<IRedisDriver>;
2776
+ /**
2777
+ * Creates and registers a new Redis client.
2778
+ */
2779
+ createClient(name: string, config: ConnectionConfig, options?: {
2780
+ reconnection?: IReconnectionOptions;
2781
+ metadata?: Partial<IClientMetadata>;
2782
+ driverType?: DriverType;
2783
+ }): Promise<IRedisDriver>;
2784
+ /**
2785
+ * Checks if client exists.
2786
+ */
2787
+ hasClient(name: string): boolean;
2788
+ /**
2789
+ * Gets all registered client names.
2790
+ */
2791
+ getClientNames(): string[];
2792
+ /**
2793
+ * Closes specific client connection.
2794
+ */
2795
+ closeClient(name: string): Promise<void>;
2796
+ /**
2797
+ * Closes all client connections.
2798
+ */
2799
+ closeAll(): Promise<void>;
2800
+ /**
2801
+ * Performs health check on client(s).
2802
+ */
2803
+ healthCheck(name?: string): Promise<IHealthStatus | IHealthStatus[]>;
2804
+ /**
2805
+ * Gets connection statistics.
2806
+ */
2807
+ getStats(): IConnectionStats;
2808
+ /**
2809
+ * Gets client metadata.
2810
+ */
2811
+ getMetadata(name: string): IClientMetadata;
2812
+ /**
2813
+ * Updates client metadata.
2814
+ */
2815
+ updateMetadata(name: string, metadata: Partial<IClientMetadata>): void;
2816
+ /**
2817
+ * Registers event listener.
2818
+ */
2819
+ on(event: ManagerEvent, handler: ManagerEventHandler): void;
2820
+ /**
2821
+ * Unregisters event listener.
2822
+ */
2823
+ off(event: ManagerEvent, handler: ManagerEventHandler): void;
2824
+ /**
2825
+ * NestJS lifecycle hook - cleanup on module destroy.
2826
+ */
2827
+ onModuleDestroy(): Promise<void>;
2828
+ /**
2829
+ * Connects client with error handling.
2830
+ */
2831
+ private connectClient;
2832
+ /**
2833
+ * Disconnects client gracefully.
2834
+ */
2835
+ private disconnectClient;
2836
+ /**
2837
+ * Sets up driver event handlers for reconnection.
2838
+ */
2839
+ private setupDriverEventHandlers;
2840
+ /**
2841
+ * Schedules reconnection with exponential backoff.
2842
+ */
2843
+ private scheduleReconnection;
2844
+ /**
2845
+ * Performs health check on single client.
2846
+ */
2847
+ private checkClientHealth;
2848
+ /**
2849
+ * Creates initial statistics for new client.
2850
+ */
2851
+ private createInitialStats;
2852
+ /**
2853
+ * Updates latency statistics.
2854
+ */
2855
+ private updateLatencyStats;
2856
+ /**
2857
+ * Calculates client uptime in milliseconds.
2858
+ */
2859
+ private calculateUptime;
2860
+ /**
2861
+ * Emits manager event.
2862
+ */
2863
+ private emitEvent;
2864
+ }
2865
+
2866
+ /**
2867
+ * Redis service - convenient wrapper over RedisClientManager.
2868
+ *
2869
+ * Provides direct access to Redis operations without manual client management.
2870
+ * All methods are proxied to the default Redis driver.
2871
+ *
2872
+ * @example
2873
+ * ```typescript
2874
+ * @Injectable()
2875
+ * export class UserService {
2876
+ * constructor(private readonly redis: RedisService) {}
2877
+ *
2878
+ * async cacheUser(id: string, user: User): Promise<void> {
2879
+ * await this.redis.set(`user:${id}`, JSON.stringify(user), { ex: 3600 });
2880
+ * }
2881
+ *
2882
+ * async getUser(id: string): Promise<User | null> {
2883
+ * const data = await this.redis.get(`user:${id}`);
2884
+ * return data ? JSON.parse(data) : null;
2885
+ * }
2886
+ *
2887
+ * async deleteUser(id: string): Promise<void> {
2888
+ * await this.redis.del(`user:${id}`);
2889
+ * }
2890
+ * }
2891
+ * ```
2892
+ */
2893
+ declare class RedisService implements OnModuleDestroy {
2894
+ private readonly clientManager;
2895
+ /**
2896
+ * Default Redis driver instance.
2897
+ */
2898
+ private driver;
2899
+ constructor(clientManager: RedisClientManager);
2900
+ /**
2901
+ * Gets default Redis driver.
2902
+ * Lazy loads on first access.
2903
+ */
2904
+ private getDriver;
2905
+ /**
2906
+ * Gets a named Redis client.
2907
+ *
2908
+ * @param name - Client name
2909
+ * @returns Redis driver instance
2910
+ *
2911
+ * @example
2912
+ * ```typescript
2913
+ * const sessions = await this.redis.getClient('sessions');
2914
+ * await sessions.set('session:123', data);
2915
+ * ```
2916
+ */
2917
+ getClient(name?: string): Promise<IRedisDriver>;
2918
+ /**
2919
+ * Checks if default client is connected.
2920
+ */
2921
+ isConnected(): Promise<boolean>;
2922
+ /**
2923
+ * Pings Redis server.
2924
+ */
2925
+ ping(message?: string): Promise<string>;
2926
+ /**
2927
+ * Selects database.
2928
+ */
2929
+ select(db: number): Promise<void>;
2930
+ /**
2931
+ * Gets value by key.
2932
+ */
2933
+ get(key: string): Promise<string | null>;
2934
+ /**
2935
+ * Sets key-value pair with optional TTL.
2936
+ */
2937
+ set(key: string, value: string, options?: ISetOptions): Promise<'OK' | null>;
2938
+ /**
2939
+ * Gets multiple values.
2940
+ */
2941
+ mget(...keys: string[]): Promise<Array<string | null>>;
2942
+ /**
2943
+ * Sets multiple key-value pairs.
2944
+ */
2945
+ mset(data: Record<string, string>): Promise<'OK'>;
2946
+ /**
2947
+ * Sets value only if key doesn't exist.
2948
+ */
2949
+ setnx(key: string, value: string): Promise<number>;
2950
+ /**
2951
+ * Sets value with expiration in seconds.
2952
+ */
2953
+ setex(key: string, seconds: number, value: string): Promise<'OK'>;
2954
+ /**
2955
+ * Gets value and deletes key.
2956
+ */
2957
+ getdel(key: string): Promise<string | null>;
2958
+ /**
2959
+ * Gets value and sets expiration.
2960
+ */
2961
+ getex(key: string, options: {
2962
+ ex?: number;
2963
+ px?: number;
2964
+ }): Promise<string | null>;
2965
+ /**
2966
+ * Increments integer value by 1.
2967
+ */
2968
+ incr(key: string): Promise<number>;
2969
+ /**
2970
+ * Increments integer value by amount.
2971
+ */
2972
+ incrby(key: string, increment: number): Promise<number>;
2973
+ /**
2974
+ * Decrements integer value by 1.
2975
+ */
2976
+ decr(key: string): Promise<number>;
2977
+ /**
2978
+ * Decrements integer value by amount.
2979
+ */
2980
+ decrby(key: string, decrement: number): Promise<number>;
2981
+ /**
2982
+ * Appends value to key.
2983
+ */
2984
+ append(key: string, value: string): Promise<number>;
2985
+ /**
2986
+ * Deletes one or more keys.
2987
+ */
2988
+ del(...keys: string[]): Promise<number>;
2989
+ /**
2990
+ * Checks if keys exist.
2991
+ */
2992
+ exists(...keys: string[]): Promise<number>;
2993
+ /**
2994
+ * Sets TTL on key (seconds).
2995
+ */
2996
+ expire(key: string, seconds: number): Promise<number>;
2997
+ /**
2998
+ * Sets TTL on key (milliseconds).
2999
+ */
3000
+ pexpire(key: string, milliseconds: number): Promise<number>;
3001
+ /**
3002
+ * Sets absolute expiration time.
3003
+ */
3004
+ expireat(key: string, timestamp: number): Promise<number>;
3005
+ /**
3006
+ * Gets TTL of key (seconds).
3007
+ */
3008
+ ttl(key: string): Promise<number>;
3009
+ /**
3010
+ * Gets TTL of key (milliseconds).
3011
+ */
3012
+ pttl(key: string): Promise<number>;
3013
+ /**
3014
+ * Removes expiration from key.
3015
+ */
3016
+ persist(key: string): Promise<number>;
3017
+ /**
3018
+ * Renames key.
3019
+ */
3020
+ rename(key: string, newKey: string): Promise<'OK'>;
3021
+ /**
3022
+ * Renames key only if new key doesn't exist.
3023
+ */
3024
+ renamenx(key: string, newKey: string): Promise<number>;
3025
+ /**
3026
+ * Gets type of value stored at key.
3027
+ */
3028
+ type(key: string): Promise<string>;
3029
+ /**
3030
+ * Scans keys matching pattern.
3031
+ */
3032
+ scan(cursor: number, options?: IScanOptions): Promise<[string, string[]]>;
3033
+ /**
3034
+ * Gets hash field value.
3035
+ */
3036
+ hget(key: string, field: string): Promise<string | null>;
3037
+ /**
3038
+ * Sets hash field value.
3039
+ */
3040
+ hset(key: string, field: string, value: string): Promise<number>;
3041
+ /**
3042
+ * Sets multiple hash fields.
3043
+ */
3044
+ hmset(key: string, data: Record<string, string>): Promise<'OK'>;
3045
+ /**
3046
+ * Gets multiple hash field values.
3047
+ */
3048
+ hmget(key: string, ...fields: string[]): Promise<Array<string | null>>;
3049
+ /**
3050
+ * Gets all fields and values of hash.
3051
+ */
3052
+ hgetall(key: string): Promise<Record<string, string>>;
3053
+ /**
3054
+ * Deletes hash fields.
3055
+ */
3056
+ hdel(key: string, ...fields: string[]): Promise<number>;
3057
+ /**
3058
+ * Checks if hash field exists.
3059
+ */
3060
+ hexists(key: string, field: string): Promise<number>;
3061
+ /**
3062
+ * Gets all field names in hash.
3063
+ */
3064
+ hkeys(key: string): Promise<string[]>;
3065
+ /**
3066
+ * Gets all values in hash.
3067
+ */
3068
+ hvals(key: string): Promise<string[]>;
3069
+ /**
3070
+ * Gets number of fields in hash.
3071
+ */
3072
+ hlen(key: string): Promise<number>;
3073
+ /**
3074
+ * Increments hash field by integer.
3075
+ */
3076
+ hincrby(key: string, field: string, increment: number): Promise<number>;
3077
+ /**
3078
+ * Scans hash fields.
3079
+ */
3080
+ hscan(key: string, cursor: number, options?: IScanOptions): Promise<[string, string[]]>;
3081
+ /**
3082
+ * Pushes values to left of list.
3083
+ */
3084
+ lpush(key: string, ...values: string[]): Promise<number>;
3085
+ /**
3086
+ * Pushes values to right of list.
3087
+ */
3088
+ rpush(key: string, ...values: string[]): Promise<number>;
3089
+ /**
3090
+ * Pops value from left of list.
3091
+ */
3092
+ lpop(key: string): Promise<string | null>;
3093
+ /**
3094
+ * Pops value from right of list.
3095
+ */
3096
+ rpop(key: string): Promise<string | null>;
3097
+ /**
3098
+ * Gets list length.
3099
+ */
3100
+ llen(key: string): Promise<number>;
3101
+ /**
3102
+ * Gets list range.
3103
+ */
3104
+ lrange(key: string, start: number, stop: number): Promise<string[]>;
3105
+ /**
3106
+ * Trims list to specified range.
3107
+ */
3108
+ ltrim(key: string, start: number, stop: number): Promise<'OK'>;
3109
+ /**
3110
+ * Gets element at index.
3111
+ */
3112
+ lindex(key: string, index: number): Promise<string | null>;
3113
+ /**
3114
+ * Sets element at index.
3115
+ */
3116
+ lset(key: string, index: number, value: string): Promise<'OK'>;
3117
+ /**
3118
+ * Adds members to set.
3119
+ */
3120
+ sadd(key: string, ...members: string[]): Promise<number>;
3121
+ /**
3122
+ * Removes members from set.
3123
+ */
3124
+ srem(key: string, ...members: string[]): Promise<number>;
3125
+ /**
3126
+ * Gets all members of set.
3127
+ */
3128
+ smembers(key: string): Promise<string[]>;
3129
+ /**
3130
+ * Checks if member is in set.
3131
+ */
3132
+ sismember(key: string, member: string): Promise<number>;
3133
+ /**
3134
+ * Gets number of members in set.
3135
+ */
3136
+ scard(key: string): Promise<number>;
3137
+ /**
3138
+ * Gets random member from set.
3139
+ */
3140
+ srandmember(key: string, count?: number): Promise<string | string[] | null>;
3141
+ /**
3142
+ * Pops random member from set.
3143
+ */
3144
+ spop(key: string, count?: number): Promise<string | string[] | null>;
3145
+ /**
3146
+ * Scans set members.
3147
+ */
3148
+ sscan(key: string, cursor: number, options?: IScanOptions): Promise<[string, string[]]>;
3149
+ /**
3150
+ * Adds members to sorted set with scores.
3151
+ */
3152
+ zadd(key: string, ...args: Array<number | string>): Promise<number>;
3153
+ /**
3154
+ * Removes members from sorted set.
3155
+ */
3156
+ zrem(key: string, ...members: string[]): Promise<number>;
3157
+ /**
3158
+ * Gets members in range by index.
3159
+ */
3160
+ zrange(key: string, start: number, stop: number, withScores?: boolean): Promise<string[]>;
3161
+ /**
3162
+ * Gets members in range by score.
3163
+ */
3164
+ zrangebyscore(key: string, min: number | string, max: number | string, withScores?: boolean): Promise<string[]>;
3165
+ /**
3166
+ * Gets score of member.
3167
+ */
3168
+ zscore(key: string, member: string): Promise<string | null>;
3169
+ /**
3170
+ * Gets number of members in sorted set.
3171
+ */
3172
+ zcard(key: string): Promise<number>;
3173
+ /**
3174
+ * Gets rank of member.
3175
+ */
3176
+ zrank(key: string, member: string): Promise<number | null>;
3177
+ /**
3178
+ * Increments score of member.
3179
+ */
3180
+ zincrby(key: string, increment: number, member: string): Promise<string>;
3181
+ /**
3182
+ * Scans sorted set members.
3183
+ */
3184
+ zscan(key: string, cursor: number, options?: IScanOptions): Promise<[string, string[]]>;
3185
+ /**
3186
+ * Publishes message to channel.
3187
+ */
3188
+ publish(channel: string, message: string): Promise<number>;
3189
+ /**
3190
+ * Subscribes to channels.
3191
+ */
3192
+ subscribe(...channels: string[]): Promise<void>;
3193
+ /**
3194
+ * Unsubscribes from channels.
3195
+ */
3196
+ unsubscribe(...channels: string[]): Promise<void>;
3197
+ /**
3198
+ * Subscribes to channels by pattern.
3199
+ */
3200
+ psubscribe(...patterns: string[]): Promise<void>;
3201
+ /**
3202
+ * Unsubscribes from channel patterns.
3203
+ */
3204
+ punsubscribe(...patterns: string[]): Promise<void>;
3205
+ /**
3206
+ * Creates a pipeline for batching commands.
3207
+ */
3208
+ pipeline(): Promise<IPipeline>;
3209
+ /**
3210
+ * Creates a multi/exec transaction.
3211
+ */
3212
+ multi(): Promise<IMulti>;
3213
+ /**
3214
+ * Evaluates Lua script.
3215
+ */
3216
+ eval(script: string, keys: string[], args: Array<string | number>): Promise<unknown>;
3217
+ /**
3218
+ * Evaluates Lua script by SHA.
3219
+ */
3220
+ evalsha(sha: string, keys: string[], args: Array<string | number>): Promise<unknown>;
3221
+ /**
3222
+ * Loads Lua script and returns SHA.
3223
+ */
3224
+ scriptLoad(script: string): Promise<string>;
3225
+ /**
3226
+ * Checks if scripts exist.
3227
+ */
3228
+ scriptExists(...shas: string[]): Promise<number[]>;
3229
+ /**
3230
+ * Flushes all scripts from cache.
3231
+ */
3232
+ scriptFlush(): Promise<'OK'>;
3233
+ /**
3234
+ * Flushes all keys from current database.
3235
+ */
3236
+ flushdb(): Promise<'OK'>;
3237
+ /**
3238
+ * Flushes all keys from all databases.
3239
+ */
3240
+ flushall(): Promise<'OK'>;
3241
+ /**
3242
+ * Gets server info.
3243
+ */
3244
+ info(section?: string): Promise<string>;
3245
+ /**
3246
+ * Gets database size (number of keys).
3247
+ */
3248
+ dbsize(): Promise<number>;
3249
+ /**
3250
+ * NestJS lifecycle hook - cleanup on module destroy.
3251
+ */
3252
+ onModuleDestroy(): Promise<void>;
3253
+ }
3254
+
3255
+ /**
3256
+ * Injects Redis driver by name.
3257
+ *
3258
+ * Use this decorator to inject a specific Redis client into your service.
3259
+ * If no name is provided, the default client is injected.
3260
+ *
3261
+ * @param name - Client name (default: 'default')
3262
+ * @returns Property decorator
3263
+ *
3264
+ * @example
3265
+ * ```typescript
3266
+ * @Injectable()
3267
+ * export class CacheService {
3268
+ * constructor(
3269
+ * @InjectRedis() private readonly redis: IRedisDriver,
3270
+ * @InjectRedis('sessions') private readonly sessions: IRedisDriver,
3271
+ * ) {}
3272
+ *
3273
+ * async cacheUser(id: string, data: User): Promise<void> {
3274
+ * await this.redis.set(`user:${id}`, JSON.stringify(data), { ex: 3600 });
3275
+ * }
3276
+ *
3277
+ * async getSession(id: string): Promise<string | null> {
3278
+ * return this.sessions.get(`session:${id}`);
3279
+ * }
3280
+ * }
3281
+ * ```
3282
+ */
3283
+ declare function InjectRedis(name?: string): ParameterDecorator;
3284
+
3285
+ /**
3286
+ * Base Redis driver implementation.
3287
+ *
3288
+ * Provides common functionality for all driver implementations.
3289
+ * Subclasses must implement abstract methods for specific Redis clients.
3290
+ *
3291
+ * Features:
3292
+ * - Event handling
3293
+ * - Connection state management
3294
+ * - Error wrapping
3295
+ * - Optional operation logging
3296
+ *
3297
+ * @abstract
3298
+ */
3299
+ declare abstract class BaseRedisDriver implements IRedisDriver {
3300
+ protected readonly config: ConnectionConfig;
3301
+ protected readonly eventEmitter: EventEmitter;
3302
+ protected readonly logger: Logger;
3303
+ protected connected: boolean;
3304
+ protected connecting: boolean;
3305
+ protected readonly enableLogging: boolean;
3306
+ constructor(config: ConnectionConfig, options?: {
3307
+ enableLogging?: boolean;
3308
+ });
3309
+ /**
3310
+ * Establishes connection to Redis.
3311
+ * Must set `this.connected = true` on success.
3312
+ */
3313
+ protected abstract doConnect(): Promise<void>;
3314
+ /**
3315
+ * Closes connection to Redis.
3316
+ * Must set `this.connected = false` on completion.
3317
+ */
3318
+ protected abstract doDisconnect(): Promise<void>;
3319
+ /**
3320
+ * Executes raw Redis command.
3321
+ * @param command - Command name
3322
+ * @param args - Command arguments
3323
+ */
3324
+ protected abstract executeCommand(command: string, ...args: unknown[]): Promise<unknown>;
3325
+ /**
3326
+ * Creates pipeline instance.
3327
+ */
3328
+ protected abstract createPipeline(): IPipeline;
3329
+ /**
3330
+ * Creates multi/exec transaction instance.
3331
+ */
3332
+ protected abstract createMulti(): IMulti;
3333
+ connect(): Promise<void>;
3334
+ disconnect(): Promise<void>;
3335
+ isConnected(): boolean;
3336
+ ping(message?: string): Promise<string>;
3337
+ select(db: number): Promise<void>;
3338
+ get(key: string): Promise<string | null>;
3339
+ set(key: string, value: string, options?: ISetOptions): Promise<'OK' | null>;
3340
+ mget(...keys: string[]): Promise<Array<string | null>>;
3341
+ mset(data: Record<string, string>): Promise<'OK'>;
3342
+ setnx(key: string, value: string): Promise<number>;
3343
+ setex(key: string, seconds: number, value: string): Promise<'OK'>;
3344
+ getdel(key: string): Promise<string | null>;
3345
+ getex(key: string, options: {
3346
+ ex?: number;
3347
+ px?: number;
3348
+ }): Promise<string | null>;
3349
+ incr(key: string): Promise<number>;
3350
+ incrby(key: string, increment: number): Promise<number>;
3351
+ decr(key: string): Promise<number>;
3352
+ decrby(key: string, decrement: number): Promise<number>;
3353
+ append(key: string, value: string): Promise<number>;
3354
+ strlen(key: string): Promise<number>;
3355
+ incrbyfloat(key: string, increment: number): Promise<string>;
3356
+ getrange(key: string, start: number, end: number): Promise<string>;
3357
+ setrange(key: string, offset: number, value: string): Promise<number>;
3358
+ msetnx(data: Record<string, string>): Promise<number>;
3359
+ del(...keys: string[]): Promise<number>;
3360
+ exists(...keys: string[]): Promise<number>;
3361
+ expire(key: string, seconds: number): Promise<number>;
3362
+ pexpire(key: string, milliseconds: number): Promise<number>;
3363
+ expireat(key: string, timestamp: number): Promise<number>;
3364
+ ttl(key: string): Promise<number>;
3365
+ pttl(key: string): Promise<number>;
3366
+ persist(key: string): Promise<number>;
3367
+ rename(key: string, newKey: string): Promise<'OK'>;
3368
+ renamenx(key: string, newKey: string): Promise<number>;
3369
+ type(key: string): Promise<string>;
3370
+ scan(cursor: number, options?: IScanOptions): Promise<[string, string[]]>;
3371
+ unlink(...keys: string[]): Promise<number>;
3372
+ copy(source: string, destination: string, options?: ICopyOptions): Promise<number>;
3373
+ keys(pattern: string): Promise<string[]>;
3374
+ touch(...keys: string[]): Promise<number>;
3375
+ object(subcommand: 'ENCODING' | 'FREQ' | 'IDLETIME' | 'REFCOUNT', key: string): Promise<string | number | null>;
3376
+ dump(key: string): Promise<string | null>;
3377
+ restore(key: string, ttl: number, serializedValue: string, options?: IRestoreOptions): Promise<'OK'>;
3378
+ time(): Promise<[string, string]>;
3379
+ hget(key: string, field: string): Promise<string | null>;
3380
+ hset(key: string, field: string, value: string): Promise<number>;
3381
+ hmset(key: string, data: Record<string, string>): Promise<'OK'>;
3382
+ hmget(key: string, ...fields: string[]): Promise<Array<string | null>>;
3383
+ hgetall(key: string): Promise<Record<string, string>>;
3384
+ hdel(key: string, ...fields: string[]): Promise<number>;
3385
+ hexists(key: string, field: string): Promise<number>;
3386
+ hkeys(key: string): Promise<string[]>;
3387
+ hvals(key: string): Promise<string[]>;
3388
+ hlen(key: string): Promise<number>;
3389
+ hincrby(key: string, field: string, increment: number): Promise<number>;
3390
+ hscan(key: string, cursor: number, options?: IScanOptions): Promise<[string, string[]]>;
3391
+ hsetnx(key: string, field: string, value: string): Promise<number>;
3392
+ hincrbyfloat(key: string, field: string, increment: number): Promise<string>;
3393
+ hstrlen(key: string, field: string): Promise<number>;
3394
+ hrandfield(key: string, count?: number, withValues?: boolean): Promise<string | string[] | null>;
3395
+ lpush(key: string, ...values: string[]): Promise<number>;
3396
+ rpush(key: string, ...values: string[]): Promise<number>;
3397
+ lpop(key: string): Promise<string | null>;
3398
+ rpop(key: string): Promise<string | null>;
3399
+ llen(key: string): Promise<number>;
3400
+ lrange(key: string, start: number, stop: number): Promise<string[]>;
3401
+ ltrim(key: string, start: number, stop: number): Promise<'OK'>;
3402
+ lindex(key: string, index: number): Promise<string | null>;
3403
+ lset(key: string, index: number, value: string): Promise<'OK'>;
3404
+ linsert(key: string, position: 'BEFORE' | 'AFTER', pivot: string, element: string): Promise<number>;
3405
+ lrem(key: string, count: number, element: string): Promise<number>;
3406
+ lpos(key: string, element: string, options?: ILposOptions): Promise<number | number[] | null>;
3407
+ blpop(keys: string[], timeout: number): Promise<[string, string] | null>;
3408
+ brpop(keys: string[], timeout: number): Promise<[string, string] | null>;
3409
+ lmove(source: string, destination: string, from: 'LEFT' | 'RIGHT', to: 'LEFT' | 'RIGHT'): Promise<string | null>;
3410
+ blmove(source: string, destination: string, from: 'LEFT' | 'RIGHT', to: 'LEFT' | 'RIGHT', timeout: number): Promise<string | null>;
3411
+ sadd(key: string, ...members: string[]): Promise<number>;
3412
+ srem(key: string, ...members: string[]): Promise<number>;
3413
+ smembers(key: string): Promise<string[]>;
3414
+ sismember(key: string, member: string): Promise<number>;
3415
+ scard(key: string): Promise<number>;
3416
+ srandmember(key: string, count?: number): Promise<string | string[] | null>;
3417
+ spop(key: string, count?: number): Promise<string | string[] | null>;
3418
+ sscan(key: string, cursor: number, options?: IScanOptions): Promise<[string, string[]]>;
3419
+ smove(source: string, destination: string, member: string): Promise<number>;
3420
+ sinter(...keys: string[]): Promise<string[]>;
3421
+ sinterstore(destination: string, ...keys: string[]): Promise<number>;
3422
+ sunion(...keys: string[]): Promise<string[]>;
3423
+ sunionstore(destination: string, ...keys: string[]): Promise<number>;
3424
+ sdiff(...keys: string[]): Promise<string[]>;
3425
+ sdiffstore(destination: string, ...keys: string[]): Promise<number>;
3426
+ smismember(key: string, ...members: string[]): Promise<number[]>;
3427
+ zadd(key: string, ...args: Array<number | string>): Promise<number>;
3428
+ zrem(key: string, ...members: string[]): Promise<number>;
3429
+ zrange(key: string, start: number, stop: number, withScores?: boolean): Promise<string[]>;
3430
+ zrangebyscore(key: string, min: number | string, max: number | string, withScores?: boolean): Promise<string[]>;
3431
+ zscore(key: string, member: string): Promise<string | null>;
3432
+ zcard(key: string): Promise<number>;
3433
+ zrank(key: string, member: string): Promise<number | null>;
3434
+ zincrby(key: string, increment: number, member: string): Promise<string>;
3435
+ zscan(key: string, cursor: number, options?: IScanOptions): Promise<[string, string[]]>;
3436
+ zrevrank(key: string, member: string): Promise<number | null>;
3437
+ zcount(key: string, min: number | string, max: number | string): Promise<number>;
3438
+ zlexcount(key: string, min: string, max: string): Promise<number>;
3439
+ zpopmin(key: string, count?: number): Promise<string[]>;
3440
+ zpopmax(key: string, count?: number): Promise<string[]>;
3441
+ bzpopmin(keys: string[], timeout: number): Promise<[string, string, string] | null>;
3442
+ bzpopmax(keys: string[], timeout: number): Promise<[string, string, string] | null>;
3443
+ zunionstore(destination: string, keys: string[], options?: IZStoreOptions): Promise<number>;
3444
+ zinterstore(destination: string, keys: string[], options?: IZStoreOptions): Promise<number>;
3445
+ zmscore(key: string, ...members: string[]): Promise<Array<string | null>>;
3446
+ zrandmember(key: string, count?: number, withScores?: boolean): Promise<string | string[] | null>;
3447
+ zrevrangebyscore(key: string, max: number | string, min: number | string, options?: IZRangeByScoreOptions): Promise<string[]>;
3448
+ publish(channel: string, message: string): Promise<number>;
3449
+ subscribe(...channels: string[]): Promise<void>;
3450
+ unsubscribe(...channels: string[]): Promise<void>;
3451
+ psubscribe(...patterns: string[]): Promise<void>;
3452
+ punsubscribe(...patterns: string[]): Promise<void>;
3453
+ xadd(key: string, id: string, fields: Record<string, string>, options?: IStreamAddOptions): Promise<string>;
3454
+ xread(streams: Array<{
3455
+ key: string;
3456
+ id: string;
3457
+ }>, options?: IStreamReadOptions): Promise<StreamReadResult | null>;
3458
+ xreadgroup(group: string, consumer: string, streams: Array<{
3459
+ key: string;
3460
+ id: string;
3461
+ }>, options?: IStreamReadGroupOptions): Promise<StreamReadResult | null>;
3462
+ xrange(key: string, start: string, end: string, options?: {
3463
+ count?: number;
3464
+ }): Promise<IStreamEntry[]>;
3465
+ xrevrange(key: string, end: string, start: string, options?: {
3466
+ count?: number;
3467
+ }): Promise<IStreamEntry[]>;
3468
+ xlen(key: string): Promise<number>;
3469
+ xinfo(key: string): Promise<IStreamInfo>;
3470
+ xtrim(key: string, maxLen: number, approximate?: boolean): Promise<number>;
3471
+ xgroupCreate(key: string, group: string, id: string, mkstream?: boolean): Promise<'OK'>;
3472
+ xgroupDestroy(key: string, group: string): Promise<number>;
3473
+ xgroupDelConsumer(key: string, group: string, consumer: string): Promise<number>;
3474
+ xgroupSetId(key: string, group: string, id: string): Promise<'OK'>;
3475
+ xack(key: string, group: string, ...ids: string[]): Promise<number>;
3476
+ xpending(key: string, group: string): Promise<IStreamPendingInfo>;
3477
+ xpendingRange(key: string, group: string, start: string, end: string, count: number, consumer?: string): Promise<IStreamPendingEntry[]>;
3478
+ xclaim(key: string, group: string, consumer: string, minIdleTime: number, ...ids: string[]): Promise<IStreamEntry[]>;
3479
+ xdel(key: string, ...ids: string[]): Promise<number>;
3480
+ private parseStreamReadResult;
3481
+ private parseStreamEntries;
3482
+ private parseFieldArray;
3483
+ private parseIStreamInfo;
3484
+ private parseIStreamPendingInfo;
3485
+ private parseStreamPendingEntries;
3486
+ pipeline(): IPipeline;
3487
+ multi(): IMulti;
3488
+ /** Registry mapping SHA → script source for NOSCRIPT fallback */
3489
+ private readonly scriptRegistry;
3490
+ eval(script: string, keys: string[], args: Array<string | number>): Promise<unknown>;
3491
+ evalsha(sha: string, keys: string[], args: Array<string | number>): Promise<unknown>;
3492
+ scriptLoad(script: string): Promise<string>;
3493
+ private isNoscriptError;
3494
+ scriptExists(...shas: string[]): Promise<number[]>;
3495
+ scriptFlush(): Promise<'OK'>;
3496
+ pfadd(key: string, ...elements: string[]): Promise<number>;
3497
+ pfcount(...keys: string[]): Promise<number>;
3498
+ pfmerge(destination: string, ...sources: string[]): Promise<'OK'>;
3499
+ geoadd(key: string, ...members: Array<number | string>): Promise<number>;
3500
+ geodist(key: string, member1: string, member2: string, unit?: GeoUnit): Promise<string | null>;
3501
+ geohash(key: string, ...members: string[]): Promise<Array<string | null>>;
3502
+ geopos(key: string, ...members: string[]): Promise<Array<[string, string] | null>>;
3503
+ geosearch(key: string, options: IGeoSearchOptions): Promise<Array<string | IGeoSearchResult>>;
3504
+ geosearchstore(destination: string, source: string, options: IGeoSearchOptions & {
3505
+ storedist?: boolean;
3506
+ }): Promise<number>;
3507
+ private parseIGeoSearchResult;
3508
+ setbit(key: string, offset: number, value: 0 | 1): Promise<number>;
3509
+ getbit(key: string, offset: number): Promise<number>;
3510
+ bitcount(key: string, start?: number, end?: number, mode?: 'BYTE' | 'BIT'): Promise<number>;
3511
+ bitop(operation: 'AND' | 'OR' | 'XOR' | 'NOT', destKey: string, ...keys: string[]): Promise<number>;
3512
+ bitpos(key: string, bit: 0 | 1, start?: number, end?: number, mode?: 'BYTE' | 'BIT'): Promise<number>;
3513
+ flushdb(): Promise<'OK'>;
3514
+ flushall(): Promise<'OK'>;
3515
+ info(section?: string): Promise<string>;
3516
+ dbsize(): Promise<number>;
3517
+ cluster(subcommand: string, ...args: Array<string | number>): Promise<unknown>;
3518
+ sentinel(subcommand: string, ...args: Array<string | number>): Promise<unknown>;
3519
+ on(event: DriverEvent, handler: DriverEventHandler): void;
3520
+ once(event: DriverEvent, handler: DriverEventHandler): void;
3521
+ off(event: DriverEvent, handler: DriverEventHandler): void;
3522
+ removeAllListeners(event?: DriverEvent): void;
3523
+ /**
3524
+ * Asserts that driver is connected.
3525
+ * @throws DriverError if not connected
3526
+ */
3527
+ protected assertConnected(): void;
3528
+ /**
3529
+ * Emits driver event.
3530
+ */
3531
+ protected emit(event: DriverEvent, data?: unknown): void;
3532
+ /**
3533
+ * Logs message if logging is enabled.
3534
+ */
3535
+ protected log(message: string, data?: unknown): void;
3536
+ /**
3537
+ * Wraps execution with timeout.
3538
+ */
3539
+ protected withTimeout<T>(promise: Promise<T>, timeoutMs: number, operation: string): Promise<T>;
3540
+ }
3541
+
3542
+ /**
3543
+ * IoRedis driver adapter.
3544
+ *
3545
+ * Implements IRedisDriver using ioredis library.
3546
+ * Supports single instance, cluster, and sentinel configurations.
3547
+ *
3548
+ * @example
3549
+ * ```typescript
3550
+ * const driver = new IoRedisAdapter({
3551
+ * host: 'localhost',
3552
+ * port: 6379,
3553
+ * });
3554
+ * await driver.connect();
3555
+ * ```
3556
+ */
3557
+ declare class IoRedisAdapter extends BaseRedisDriver {
3558
+ private client;
3559
+ constructor(config: ConnectionConfig, options?: {
3560
+ enableLogging?: boolean;
3561
+ });
3562
+ protected doConnect(): Promise<void>;
3563
+ protected doDisconnect(): Promise<void>;
3564
+ protected executeCommand(command: string, ...args: unknown[]): Promise<unknown>;
3565
+ protected createPipeline(): IPipeline;
3566
+ protected createMulti(): IMulti;
3567
+ private createSingleClient;
3568
+ private createClusterClient;
3569
+ private createSentinelClient;
3570
+ private setupEventHandlers;
3571
+ /**
3572
+ * Gets underlying ioredis client.
3573
+ * For advanced usage only.
3574
+ */
3575
+ getClient(): Redis | Cluster | null;
3576
+ }
3577
+
3578
+ /**
3579
+ * Union type for all supported node-redis client types.
3580
+ */
3581
+ type NodeRedisClient = RedisClientType | RedisClusterType | RedisSentinelType;
3582
+ /**
3583
+ * Node-Redis driver adapter.
3584
+ *
3585
+ * Implements IRedisDriver using redis (node-redis v4+) library.
3586
+ * Supports single instance, cluster, and sentinel configurations.
3587
+ *
3588
+ * @example
3589
+ * ```typescript
3590
+ * // Single instance
3591
+ * const driver = new NodeRedisAdapter({
3592
+ * type: 'single',
3593
+ * host: 'localhost',
3594
+ * port: 6379,
3595
+ * });
3596
+ *
3597
+ * // Cluster
3598
+ * const clusterDriver = new NodeRedisAdapter({
3599
+ * type: 'cluster',
3600
+ * nodes: [{ host: 'node1', port: 7000 }],
3601
+ * });
3602
+ *
3603
+ * // Sentinel
3604
+ * const sentinelDriver = new NodeRedisAdapter({
3605
+ * type: 'sentinel',
3606
+ * sentinels: [{ host: 'sentinel1', port: 26379 }],
3607
+ * name: 'mymaster',
3608
+ * });
3609
+ *
3610
+ * await driver.connect();
3611
+ * ```
3612
+ */
3613
+ declare class NodeRedisAdapter extends BaseRedisDriver {
3614
+ private client;
3615
+ private isSentinel;
3616
+ private isCluster;
3617
+ private readonly keyPrefix;
3618
+ constructor(config: ConnectionConfig, options?: {
3619
+ enableLogging?: boolean;
3620
+ });
3621
+ protected doConnect(): Promise<void>;
3622
+ protected doDisconnect(): Promise<void>;
3623
+ protected executeCommand(command: string, ...args: unknown[]): Promise<unknown>;
3624
+ protected createPipeline(): IPipeline;
3625
+ protected createMulti(): IMulti;
3626
+ /**
3627
+ * Override hgetall to convert array response to object.
3628
+ * Node-redis sendCommand returns ['field1', 'value1', 'field2', 'value2']
3629
+ * but we need { field1: 'value1', field2: 'value2' }
3630
+ */
3631
+ hgetall(key: string): Promise<Record<string, string>>;
3632
+ /**
3633
+ * Override scan to normalize cursor response.
3634
+ * Node-redis sendCommand returns [cursor, [keys...]]
3635
+ */
3636
+ scan(cursor: number, options?: {
3637
+ match?: string;
3638
+ count?: number;
3639
+ }): Promise<[string, string[]]>;
3640
+ /**
3641
+ * Override hscan to normalize cursor response.
3642
+ */
3643
+ hscan(key: string, cursor: number, options?: {
3644
+ match?: string;
3645
+ count?: number;
3646
+ }): Promise<[string, string[]]>;
3647
+ /**
3648
+ * Override sscan to normalize cursor response.
3649
+ */
3650
+ sscan(key: string, cursor: number, options?: {
3651
+ match?: string;
3652
+ count?: number;
3653
+ }): Promise<[string, string[]]>;
3654
+ /**
3655
+ * Override zscan to normalize cursor response.
3656
+ */
3657
+ zscan(key: string, cursor: number, options?: {
3658
+ match?: string;
3659
+ count?: number;
3660
+ }): Promise<[string, string[]]>;
3661
+ /**
3662
+ * Override info to return string.
3663
+ */
3664
+ info(section?: string): Promise<string>;
3665
+ private createSingleClient;
3666
+ private createClusterClient;
3667
+ /**
3668
+ * Creates a Redis Sentinel client using the proper createSentinel API.
3669
+ * Returns already connected sentinel instance.
3670
+ *
3671
+ * NOTE: node-redis does not support natMap/nodeAddressMap for Sentinel.
3672
+ * For Docker/NAT environments, use ioredis driver which supports sentinelOptions.natMap.
3673
+ */
3674
+ private createSentinelClient;
3675
+ /**
3676
+ * Safely disconnect the client, ignoring errors.
3677
+ */
3678
+ private safeDisconnect;
3679
+ /**
3680
+ * Default reconnection strategy: exponential backoff with max 30s delay.
3681
+ * Returns a function that calculates delay based on retry count.
3682
+ */
3683
+ private getDefaultReconnectStrategy;
3684
+ /**
3685
+ * Get the first key from command arguments for cluster slot routing.
3686
+ * Returns undefined for commands that don't require a key.
3687
+ */
3688
+ private getFirstKey;
3689
+ /**
3690
+ * Check if a command is readonly (doesn't modify data).
3691
+ * Used for cluster to route reads to replicas if enabled.
3692
+ */
3693
+ private isReadonlyCommand;
3694
+ /**
3695
+ * Convert arguments to proper types for sendCommand.
3696
+ * sendCommand expects string[] but we need to handle numbers properly.
3697
+ */
3698
+ private convertArgs;
3699
+ /**
3700
+ * Apply key prefix to key-based commands.
3701
+ * This emulates ioredis keyPrefix functionality.
3702
+ */
3703
+ private applyKeyPrefix;
3704
+ private setupEventHandlers;
3705
+ /**
3706
+ * Gets underlying node-redis client.
3707
+ * For advanced usage only.
3708
+ */
3709
+ getClient(): NodeRedisClient | null;
3710
+ /**
3711
+ * Returns true if connected to Redis Sentinel.
3712
+ */
3713
+ isSentinelMode(): boolean;
3714
+ }
3715
+
3716
+ /**
3717
+ * Driver factory options.
3718
+ */
3719
+ interface IDriverFactoryOptions {
3720
+ /**
3721
+ * Driver type to create.
3722
+ * @default 'ioredis'
3723
+ */
3724
+ type?: DriverType;
3725
+ /**
3726
+ * Enable operation logging.
3727
+ * @default false
3728
+ */
3729
+ enableLogging?: boolean;
3730
+ }
3731
+ /**
3732
+ * Factory for creating Redis drivers.
3733
+ *
3734
+ * Creates driver instances based on configuration.
3735
+ * Drivers are interchangeable - switching between ioredis and node-redis
3736
+ * requires no code changes.
3737
+ *
3738
+ * @example
3739
+ * ```typescript
3740
+ * // Create ioredis driver
3741
+ * const driver = createDriver(
3742
+ * { host: 'localhost', port: 6379 },
3743
+ * { type: 'ioredis' }
3744
+ * );
3745
+ *
3746
+ * // Switch to node-redis (same interface)
3747
+ * const driver = createDriver(
3748
+ * { host: 'localhost', port: 6379 },
3749
+ * { type: 'node-redis' }
3750
+ * );
3751
+ * ```
3752
+ */
3753
+ declare function createDriver(config: ConnectionConfig, options?: IDriverFactoryOptions): IRedisDriver;
3754
+ /**
3755
+ * Driver factory class for dependency injection.
3756
+ *
3757
+ * @example
3758
+ * ```typescript
3759
+ * @Module({
3760
+ * providers: [
3761
+ * {
3762
+ * provide: DRIVER_FACTORY,
3763
+ * useClass: DriverFactory,
3764
+ * },
3765
+ * ],
3766
+ * })
3767
+ * export class MyModule {}
3768
+ * ```
3769
+ */
3770
+ declare class DriverFactory {
3771
+ /**
3772
+ * Creates a driver instance.
3773
+ */
3774
+ create(config: ConnectionConfig, options?: IDriverFactoryOptions): IRedisDriver;
3775
+ /**
3776
+ * Gets supported driver types.
3777
+ */
3778
+ getSupportedTypes(): DriverType[];
3779
+ /**
3780
+ * Checks if driver type is supported.
3781
+ */
3782
+ isSupported(type: string): type is DriverType;
3783
+ /**
3784
+ * Gets default driver type.
3785
+ */
3786
+ getDefaultType(): DriverType;
3787
+ }
3788
+ /**
3789
+ * Creates multiple drivers from configurations.
3790
+ *
3791
+ * @example
3792
+ * ```typescript
3793
+ * const drivers = createDrivers({
3794
+ * default: { host: 'localhost', port: 6379 },
3795
+ * cache: { host: 'cache.local', port: 6379 },
3796
+ * });
3797
+ * ```
3798
+ */
3799
+ declare function createDrivers(configs: Record<string, ConnectionConfig>, options?: IDriverFactoryOptions): Record<string, IRedisDriver>;
3800
+ /**
3801
+ * Driver type detection helper.
3802
+ * Attempts to detect available driver library.
3803
+ */
3804
+ declare function detectAvailableDriver(): DriverType | null;
3805
+ /**
3806
+ * Gets recommended driver type based on environment.
3807
+ */
3808
+ declare function getRecommendedDriver(): DriverType;
3809
+
3810
+ /**
3811
+ * Manages plugin lifecycle hooks and dependency ordering.
3812
+ *
3813
+ * Calls `onRegister()` and `onModuleInit()` on all plugins during
3814
+ * NestJS module initialization, and `onModuleDestroy()` during shutdown.
3815
+ * Plugins with `dependencies` are initialized in topological order.
3816
+ */
3817
+ declare class PluginRegistryService implements OnModuleInit, OnModuleDestroy {
3818
+ private readonly plugins;
3819
+ private readonly clientManager;
3820
+ private readonly options;
3821
+ private readonly moduleRef;
3822
+ private readonly logger;
3823
+ constructor(plugins: IRedisXPlugin[], clientManager: RedisClientManager, options: IRedisModuleOptions, moduleRef: ModuleRef);
3824
+ onModuleInit(): Promise<void>;
3825
+ onModuleDestroy(): Promise<void>;
3826
+ private createContext;
3827
+ /**
3828
+ * Topological sort of plugins by dependencies (Kahn's algorithm).
3829
+ * Plugins without dependencies maintain their original order.
3830
+ * Throws on circular dependencies.
3831
+ */
3832
+ sortByDependencies(plugins: IRedisXPlugin[]): IRedisXPlugin[];
3833
+ }
3834
+
3835
+ /**
3836
+ * All possible error codes in NestJS RedisX.
3837
+ * Organized by domain for easier categorization and handling.
3838
+ *
3839
+ * Naming convention: {DOMAIN}_{SPECIFIC_ERROR}
3840
+ *
3841
+ * Domains:
3842
+ * - CONN/DRIVER: Connection and networking errors
3843
+ * - OP: Redis operation errors
3844
+ * - CFG/CONFIG: Configuration and validation errors
3845
+ * - LOCK: Distributed lock errors
3846
+ * - CACHE: Caching errors
3847
+ * - RATE: Rate limiting errors
3848
+ * - STREAM: Stream processing errors
3849
+ * - PLUGIN: Plugin system errors
3850
+ * - IDEMPOTENCY: Idempotency errors
3851
+ */
3852
+ declare enum ErrorCode {
3853
+ /** Failed to establish connection to Redis server */
3854
+ CONN_FAILED = "CONN_FAILED",
3855
+ /** Connection attempt timed out */
3856
+ CONN_TIMEOUT = "CONN_TIMEOUT",
3857
+ /** Lost connection to Redis server */
3858
+ CONN_DISCONNECTED = "CONN_DISCONNECTED",
3859
+ /** Connection was refused by Redis server */
3860
+ CONN_REFUSED = "CONN_REFUSED",
3861
+ /** Authentication failed */
3862
+ CONN_AUTH_FAILED = "CONN_AUTH_FAILED",
3863
+ /** TLS/SSL connection error */
3864
+ CONN_TLS_ERROR = "CONN_TLS_ERROR",
3865
+ /** Redis cluster is down or unreachable */
3866
+ CONN_CLUSTER_DOWN = "CONN_CLUSTER_DOWN",
3867
+ /** Redis cluster slot migration in progress */
3868
+ CONN_CLUSTER_MOVED = "CONN_CLUSTER_MOVED",
3869
+ /** Redis cluster ASK redirection */
3870
+ CONN_CLUSTER_ASK = "CONN_CLUSTER_ASK",
3871
+ /** Redis cluster error */
3872
+ CONN_CLUSTER_ERROR = "CONN_CLUSTER_ERROR",
3873
+ /** Sentinel failover in progress */
3874
+ CONN_SENTINEL_FAILOVER = "CONN_SENTINEL_FAILOVER",
3875
+ /** No Sentinel master found */
3876
+ CONN_SENTINEL_NO_MASTER = "CONN_SENTINEL_NO_MASTER",
3877
+ /** Sentinel error */
3878
+ CONN_SENTINEL_ERROR = "CONN_SENTINEL_ERROR",
3879
+ /** Driver not connected */
3880
+ DRIVER_NOT_CONNECTED = "DRIVER_NOT_CONNECTED",
3881
+ /** Maximum connection retries exceeded */
3882
+ CONN_MAX_RETRIES = "CONN_MAX_RETRIES",
3883
+ /** Connection pool exhausted */
3884
+ CONN_POOL_EXHAUSTED = "CONN_POOL_EXHAUSTED",
3885
+ /** Redis operation failed */
3886
+ OP_FAILED = "OP_FAILED",
3887
+ /** Redis operation timed out */
3888
+ OP_TIMEOUT = "OP_TIMEOUT",
3889
+ /** Redis key not found */
3890
+ OP_KEY_NOT_FOUND = "OP_KEY_NOT_FOUND",
3891
+ /** Wrong Redis data type for operation */
3892
+ OP_TYPE_MISMATCH = "OP_TYPE_MISMATCH",
3893
+ /** Redis script execution failed */
3894
+ OP_SCRIPT_ERROR = "OP_SCRIPT_ERROR",
3895
+ /** Redis script timeout */
3896
+ OP_SCRIPT_TIMEOUT = "OP_SCRIPT_TIMEOUT",
3897
+ /** Redis transaction failed */
3898
+ OP_TRANSACTION_FAILED = "OP_TRANSACTION_FAILED",
3899
+ /** Redis pipeline execution failed */
3900
+ OP_PIPELINE_FAILED = "OP_PIPELINE_FAILED",
3901
+ /** Invalid operation arguments */
3902
+ OP_INVALID_ARGS = "OP_INVALID_ARGS",
3903
+ /** Operation not supported by driver */
3904
+ OP_NOT_SUPPORTED = "OP_NOT_SUPPORTED",
3905
+ /** Redis out of memory */
3906
+ OP_OUT_OF_MEMORY = "OP_OUT_OF_MEMORY",
3907
+ /** Redis NOAUTH error - authentication required */
3908
+ OP_NO_AUTH = "OP_NO_AUTH",
3909
+ /** Redis WRONGPASS error - invalid password */
3910
+ OP_WRONG_PASS = "OP_WRONG_PASS",
3911
+ /** Redis READONLY error - can't write to replica */
3912
+ OP_READONLY = "OP_READONLY",
3913
+ /** Redis BUSYKEY error - target key already exists */
3914
+ OP_BUSY_KEY = "OP_BUSY_KEY",
3915
+ /** Operation requires driver to be connected */
3916
+ OP_NOT_CONNECTED = "OP_NOT_CONNECTED",
3917
+ /** Invalid configuration */
3918
+ CFG_INVALID = "CFG_INVALID",
3919
+ /** Missing required configuration */
3920
+ CFG_MISSING_REQUIRED = "CFG_MISSING_REQUIRED",
3921
+ /** Invalid connection type */
3922
+ CFG_INVALID_CONNECTION_TYPE = "CFG_INVALID_CONNECTION_TYPE",
3923
+ /** Invalid host or port */
3924
+ CFG_INVALID_HOST_PORT = "CFG_INVALID_HOST_PORT",
3925
+ /** Invalid database number */
3926
+ CFG_INVALID_DB = "CFG_INVALID_DB",
3927
+ /** Invalid TTL value */
3928
+ CFG_INVALID_TTL = "CFG_INVALID_TTL",
3929
+ /** Invalid timeout value */
3930
+ CFG_INVALID_TIMEOUT = "CFG_INVALID_TIMEOUT",
3931
+ /** Invalid retry configuration */
3932
+ CFG_INVALID_RETRY = "CFG_INVALID_RETRY",
3933
+ /** Validation failed */
3934
+ CFG_VALIDATION_FAILED = "CFG_VALIDATION_FAILED",
3935
+ /** Incompatible configuration options */
3936
+ CFG_INCOMPATIBLE = "CFG_INCOMPATIBLE",
3937
+ /** Driver type not supported */
3938
+ CFG_DRIVER_NOT_SUPPORTED = "CFG_DRIVER_NOT_SUPPORTED",
3939
+ /** Invalid cluster nodes configuration */
3940
+ CFG_INVALID_CLUSTER_NODES = "CFG_INVALID_CLUSTER_NODES",
3941
+ /** Invalid sentinel configuration */
3942
+ CFG_INVALID_SENTINEL = "CFG_INVALID_SENTINEL",
3943
+ /** Invalid TLS configuration */
3944
+ CFG_INVALID_TLS = "CFG_INVALID_TLS",
3945
+ /** Cache key is invalid */
3946
+ CACHE_KEY_INVALID = "CACHE_KEY_INVALID",
3947
+ /** Cache key exceeds maximum length */
3948
+ CACHE_KEY_TOO_LONG = "CACHE_KEY_TOO_LONG",
3949
+ /** Failed to serialize value */
3950
+ CACHE_SERIALIZATION_FAILED = "CACHE_SERIALIZATION_FAILED",
3951
+ /** Failed to deserialize value */
3952
+ CACHE_DESERIALIZATION_FAILED = "CACHE_DESERIALIZATION_FAILED",
3953
+ /** Cache tag index corrupted */
3954
+ CACHE_TAG_INDEX_CORRUPTED = "CACHE_TAG_INDEX_CORRUPTED",
3955
+ /** Cache stampede protection timeout */
3956
+ CACHE_STAMPEDE_TIMEOUT = "CACHE_STAMPEDE_TIMEOUT",
3957
+ /** Cache loader function failed */
3958
+ CACHE_LOADER_FAILED = "CACHE_LOADER_FAILED",
3959
+ /** L1 cache error */
3960
+ CACHE_L1_ERROR = "CACHE_L1_ERROR",
3961
+ /** L2 cache error */
3962
+ CACHE_L2_ERROR = "CACHE_L2_ERROR",
3963
+ /** Cache set operation failed */
3964
+ CACHE_SET_FAILED = "CACHE_SET_FAILED",
3965
+ /** Cache delete operation failed */
3966
+ CACHE_DELETE_FAILED = "CACHE_DELETE_FAILED",
3967
+ /** Cache clear operation failed */
3968
+ CACHE_CLEAR_FAILED = "CACHE_CLEAR_FAILED",
3969
+ /** Cache operation failed */
3970
+ CACHE_OPERATION_FAILED = "CACHE_OPERATION_FAILED",
3971
+ /** Cache operation timeout */
3972
+ CACHE_OPERATION_TIMEOUT = "CACHE_OPERATION_TIMEOUT",
3973
+ /** Tag invalidation failed */
3974
+ CACHE_TAG_INVALIDATION_FAILED = "CACHE_TAG_INVALIDATION_FAILED",
3975
+ /** Failed to acquire lock */
3976
+ LOCK_ACQUISITION_FAILED = "LOCK_ACQUISITION_FAILED",
3977
+ /** Lock acquisition timed out */
3978
+ LOCK_ACQUISITION_TIMEOUT = "LOCK_ACQUISITION_TIMEOUT",
3979
+ /** Failed to extend lock TTL */
3980
+ LOCK_EXTENSION_FAILED = "LOCK_EXTENSION_FAILED",
3981
+ /** Failed to release lock */
3982
+ LOCK_RELEASE_FAILED = "LOCK_RELEASE_FAILED",
3983
+ /** Attempting to release lock not owned by caller */
3984
+ LOCK_NOT_OWNED = "LOCK_NOT_OWNED",
3985
+ /** Lock expired before operation completed */
3986
+ LOCK_EXPIRED = "LOCK_EXPIRED",
3987
+ /** Rate limit exceeded */
3988
+ RATE_LIMIT_EXCEEDED = "RATE_LIMIT_EXCEEDED",
3989
+ /** Rate limit script error */
3990
+ RATE_LIMIT_SCRIPT_ERROR = "RATE_LIMIT_SCRIPT_ERROR",
3991
+ /** Idempotency key is invalid */
3992
+ IDEMPOTENCY_KEY_INVALID = "IDEMPOTENCY_KEY_INVALID",
3993
+ /** Operation already in progress */
3994
+ IDEMPOTENCY_IN_PROGRESS = "IDEMPOTENCY_IN_PROGRESS",
3995
+ /** Previous operation failed */
3996
+ IDEMPOTENCY_PREVIOUS_FAILED = "IDEMPOTENCY_PREVIOUS_FAILED",
3997
+ /** Consumer group operation failed */
3998
+ STREAM_CONSUMER_GROUP_ERROR = "STREAM_CONSUMER_GROUP_ERROR",
3999
+ /** Stream ACK failed */
4000
+ STREAM_ACK_FAILED = "STREAM_ACK_FAILED",
4001
+ /** Stream read failed */
4002
+ STREAM_READ_FAILED = "STREAM_READ_FAILED",
4003
+ /** Plugin is invalid */
4004
+ PLUGIN_INVALID = "PLUGIN_INVALID",
4005
+ /** Plugin already registered */
4006
+ PLUGIN_DUPLICATE = "PLUGIN_DUPLICATE",
4007
+ /** Plugin not found */
4008
+ PLUGIN_NOT_FOUND = "PLUGIN_NOT_FOUND",
4009
+ /** Plugin registration failed */
4010
+ PLUGIN_REGISTER_FAILED = "PLUGIN_REGISTER_FAILED",
4011
+ /** Plugin initialization failed */
4012
+ PLUGIN_INIT_FAILED = "PLUGIN_INIT_FAILED",
4013
+ /** Circular plugin dependency */
4014
+ PLUGIN_CIRCULAR_DEPENDENCY = "PLUGIN_CIRCULAR_DEPENDENCY",
4015
+ /** Required plugin dependency missing */
4016
+ PLUGIN_DEPENDENCY_MISSING = "PLUGIN_DEPENDENCY_MISSING",
4017
+ /** Client not found */
4018
+ CLIENT_NOT_FOUND = "CLIENT_NOT_FOUND",
4019
+ /** Client already exists */
4020
+ CLIENT_ALREADY_EXISTS = "CLIENT_ALREADY_EXISTS",
4021
+ /** Service not initialized */
4022
+ NOT_INITIALIZED = "NOT_INITIALIZED",
4023
+ /** Generic operation failed */
4024
+ OPERATION_FAILED = "OPERATION_FAILED",
4025
+ /** Generic operation timeout */
4026
+ OPERATION_TIMEOUT = "OPERATION_TIMEOUT",
4027
+ /** Generic serialization failed */
4028
+ SERIALIZATION_FAILED = "SERIALIZATION_FAILED",
4029
+ /** Generic validation failed */
4030
+ VALIDATION_FAILED = "VALIDATION_FAILED",
4031
+ /** Unknown error */
4032
+ UNKNOWN = "UNKNOWN"
4033
+ }
4034
+ /**
4035
+ * Type guard to check if a string is a valid ErrorCode.
4036
+ */
4037
+ declare function isErrorCode(value: string): value is ErrorCode;
4038
+ /**
4039
+ * Get error domain from error code.
4040
+ *
4041
+ * @param code - Error code
4042
+ * @returns Domain prefix (e.g., 'CONN', 'OP', 'CFG')
4043
+ *
4044
+ * @example
4045
+ * ```typescript
4046
+ * getErrorDomain(ErrorCode.CONN_FAILED) // 'CONN'
4047
+ * getErrorDomain(ErrorCode.OP_TIMEOUT) // 'OP'
4048
+ * ```
4049
+ */
4050
+ declare function getErrorDomain(code: ErrorCode): string;
4051
+ /**
4052
+ * Check if error code belongs to a domain.
4053
+ *
4054
+ * @param code - Error code to check
4055
+ * @param domain - Domain to check against
4056
+ * @returns True if code belongs to domain
4057
+ *
4058
+ * @example
4059
+ * ```typescript
4060
+ * isErrorDomain(ErrorCode.CONN_FAILED, 'CONN') // true
4061
+ * isErrorDomain(ErrorCode.OP_TIMEOUT, 'CONN') // false
4062
+ * ```
4063
+ */
4064
+ declare function isErrorDomain(code: ErrorCode, domain: string): boolean;
4065
+
4066
+ /**
4067
+ * JSON representation of an error.
4068
+ * Used for serialization in logs and API responses.
4069
+ */
4070
+ interface IErrorJSON {
4071
+ /** Error class name */
4072
+ name: string;
4073
+ /** Human-readable error message */
4074
+ message: string;
4075
+ /** Error code for programmatic handling */
4076
+ code: string;
4077
+ /** ISO timestamp when error occurred */
4078
+ timestamp: string;
4079
+ /** Additional context for debugging */
4080
+ context?: Record<string, unknown>;
4081
+ /** Stack trace */
4082
+ stack?: string;
4083
+ /** Cause error if wrapped */
4084
+ cause?: {
4085
+ name: string;
4086
+ message: string;
4087
+ stack?: string;
4088
+ };
4089
+ }
4090
+ /**
4091
+ * Base error class for all RedisX errors.
4092
+ *
4093
+ * Features:
4094
+ * - Structured error codes for programmatic handling
4095
+ * - Context preservation for debugging
4096
+ * - JSON serialization for logging
4097
+ * - Proper error chaining with cause
4098
+ * - Timestamp tracking
4099
+ *
4100
+ * While this class can be instantiated directly, it's recommended
4101
+ * to use or extend specific error classes for better error handling.
4102
+ *
4103
+ * @example
4104
+ * ```typescript
4105
+ * export class CacheError extends RedisXError {
4106
+ * constructor(message: string, cause?: Error) {
4107
+ * super(message, ErrorCode.CACHE_LOADER_FAILED, cause, {
4108
+ * key: 'user:123',
4109
+ * ttl: 3600,
4110
+ * });
4111
+ * }
4112
+ * }
4113
+ * ```
4114
+ */
4115
+ declare class RedisXError extends Error {
4116
+ readonly code: ErrorCode;
4117
+ readonly cause?: Error | undefined;
4118
+ readonly context?: Record<string, unknown> | undefined;
4119
+ /**
4120
+ * Timestamp when error was created.
4121
+ */
4122
+ readonly timestamp: Date;
4123
+ /**
4124
+ * Creates a new RedisXError.
4125
+ *
4126
+ * @param message - Human-readable error message
4127
+ * @param code - Error code for programmatic handling
4128
+ * @param cause - Original error that caused this error
4129
+ * @param context - Additional context for debugging
4130
+ */
4131
+ constructor(message: string, code: ErrorCode, cause?: Error | undefined, context?: Record<string, unknown> | undefined);
4132
+ /**
4133
+ * Checks if error is of specific code.
4134
+ *
4135
+ * @param code - Error code to check
4136
+ * @returns True if error matches code
4137
+ *
4138
+ * @example
4139
+ * ```typescript
4140
+ * if (error.is(ErrorCode.CONN_FAILED)) {
4141
+ * // Handle connection error
4142
+ * }
4143
+ * ```
4144
+ */
4145
+ is(code: ErrorCode): boolean;
4146
+ /**
4147
+ * Checks if error is any of specified codes.
4148
+ *
4149
+ * @param codes - Array of error codes to check
4150
+ * @returns True if error matches any code
4151
+ *
4152
+ * @example
4153
+ * ```typescript
4154
+ * if (error.isAnyOf([ErrorCode.LOCK_EXPIRED, ErrorCode.LOCK_NOT_OWNED])) {
4155
+ * // Handle lock error
4156
+ * }
4157
+ * ```
4158
+ */
4159
+ isAnyOf(codes: ErrorCode[]): boolean;
4160
+ /**
4161
+ * Serializes error to JSON for logging.
4162
+ *
4163
+ * @returns JSON representation of error
4164
+ *
4165
+ * @example
4166
+ * ```typescript
4167
+ * logger.error('Operation failed', error.toJSON());
4168
+ * ```
4169
+ */
4170
+ toJSON(): IErrorJSON;
4171
+ /**
4172
+ * Creates error string for logging.
4173
+ *
4174
+ * @returns Formatted error string
4175
+ */
4176
+ toString(): string;
4177
+ /**
4178
+ * Wraps unknown error in RedisXError.
4179
+ *
4180
+ * @param error - Error to wrap
4181
+ * @param code - Error code to assign
4182
+ * @returns RedisXError instance
4183
+ *
4184
+ * @example
4185
+ * ```typescript
4186
+ * try {
4187
+ * await someOperation();
4188
+ * } catch (err) {
4189
+ * throw RedisXError.wrap(err, ErrorCode.CACHE_LOADER_FAILED);
4190
+ * }
4191
+ * ```
4192
+ */
4193
+ static wrap(error: unknown, code?: ErrorCode): RedisXError;
4194
+ /**
4195
+ * Checks if value is a RedisXError.
4196
+ *
4197
+ * @param error - Value to check
4198
+ * @returns True if value is RedisXError
4199
+ */
4200
+ static isRedisXError(error: unknown): error is RedisXError;
4201
+ }
4202
+
4203
+ /**
4204
+ * Base class for all connection-related errors.
4205
+ *
4206
+ * Provides common context for connection failures including
4207
+ * host, port, and connection type information.
4208
+ */
4209
+ declare class RedisConnectionError extends RedisXError {
4210
+ readonly host?: string | undefined;
4211
+ readonly port?: number | undefined;
4212
+ constructor(message: string, code: ErrorCode, host?: string | undefined, port?: number | undefined, cause?: Error, context?: Record<string, unknown>);
4213
+ /**
4214
+ * Creates connection error with default code.
4215
+ */
4216
+ static create(message: string, host?: string, port?: number, cause?: Error): RedisConnectionError;
4217
+ }
4218
+ /**
4219
+ * Error thrown when connection or operation times out.
4220
+ *
4221
+ * Includes timeout duration and operation details for debugging.
4222
+ *
4223
+ * @example
4224
+ * ```typescript
4225
+ * throw new RedisTimeoutError(
4226
+ * 'Connection',
4227
+ * 5000,
4228
+ * 'localhost',
4229
+ * 6379,
4230
+ * );
4231
+ * ```
4232
+ */
4233
+ declare class RedisTimeoutError extends RedisConnectionError {
4234
+ readonly operation: string;
4235
+ readonly timeoutMs: number;
4236
+ constructor(operation: string, timeoutMs: number, host?: string, port?: number, cause?: Error);
4237
+ }
4238
+ /**
4239
+ * Error thrown for Redis Cluster-specific failures.
4240
+ *
4241
+ * Handles cluster slot redirections (MOVED, ASK), cluster down states,
4242
+ * and other cluster topology issues.
4243
+ *
4244
+ * @example
4245
+ * ```typescript
4246
+ * // Cluster down
4247
+ * throw new RedisClusterError(
4248
+ * 'Cluster is down',
4249
+ * ErrorCode.CONN_CLUSTER_DOWN,
4250
+ * );
4251
+ *
4252
+ * // Slot migration
4253
+ * throw new RedisClusterError(
4254
+ * 'Key moved to different slot',
4255
+ * ErrorCode.CONN_CLUSTER_MOVED,
4256
+ * undefined,
4257
+ * undefined,
4258
+ * undefined,
4259
+ * { slot: 1234, targetNode: 'node2:7001' },
4260
+ * );
4261
+ * ```
4262
+ */
4263
+ declare class RedisClusterError extends RedisConnectionError {
4264
+ constructor(message: string, code: ErrorCode, host?: string, port?: number, cause?: Error, context?: Record<string, unknown>);
4265
+ /**
4266
+ * Creates cluster down error.
4267
+ */
4268
+ static clusterDown(host?: string, port?: number): RedisClusterError;
4269
+ /**
4270
+ * Creates MOVED redirection error.
4271
+ */
4272
+ static moved(slot: number, targetHost: string, targetPort: number, cause?: Error): RedisClusterError;
4273
+ /**
4274
+ * Creates ASK redirection error.
4275
+ */
4276
+ static ask(slot: number, targetHost: string, targetPort: number, cause?: Error): RedisClusterError;
4277
+ /**
4278
+ * Creates generic cluster error.
4279
+ */
4280
+ static generic(message: string, host?: string, port?: number, cause?: Error): RedisClusterError;
4281
+ }
4282
+ /**
4283
+ * Error thrown for Redis Sentinel-specific failures.
4284
+ *
4285
+ * Handles sentinel master discovery, failover events, and sentinel
4286
+ * connectivity issues.
4287
+ *
4288
+ * @example
4289
+ * ```typescript
4290
+ * // No master found
4291
+ * throw RedisSentinelError.noMaster('mymaster', [
4292
+ * { host: 'sentinel1', port: 26379 },
4293
+ * { host: 'sentinel2', port: 26379 },
4294
+ * ]);
4295
+ *
4296
+ * // Failover in progress
4297
+ * throw RedisSentinelError.failover(
4298
+ * 'mymaster',
4299
+ * 'old-master:6379',
4300
+ * 'new-master:6379',
4301
+ * );
4302
+ * ```
4303
+ */
4304
+ declare class RedisSentinelError extends RedisConnectionError {
4305
+ readonly masterName?: string | undefined;
4306
+ constructor(message: string, code: ErrorCode, masterName?: string | undefined, host?: string, port?: number, cause?: Error, context?: Record<string, unknown>);
4307
+ /**
4308
+ * Creates no master found error.
4309
+ */
4310
+ static noMaster(masterName: string, sentinels?: Array<{
4311
+ host: string;
4312
+ port: number;
4313
+ }>): RedisSentinelError;
4314
+ /**
4315
+ * Creates sentinel failover error.
4316
+ */
4317
+ static failover(masterName: string, oldMaster?: string, newMaster?: string): RedisSentinelError;
4318
+ /**
4319
+ * Creates generic sentinel error.
4320
+ */
4321
+ static generic(message: string, masterName?: string, cause?: Error): RedisSentinelError;
4322
+ }
4323
+ /**
4324
+ * Error thrown when authentication fails.
4325
+ *
4326
+ * @example
4327
+ * ```typescript
4328
+ * throw new RedisAuthError('Invalid password', 'localhost', 6379);
4329
+ * ```
4330
+ */
4331
+ declare class RedisAuthError extends RedisConnectionError {
4332
+ constructor(message?: string, host?: string, port?: number, cause?: Error);
4333
+ }
4334
+ /**
4335
+ * Error thrown when TLS/SSL connection fails.
4336
+ *
4337
+ * @example
4338
+ * ```typescript
4339
+ * throw new RedisTLSError(
4340
+ * 'Certificate verification failed',
4341
+ * 'secure.redis.example.com',
4342
+ * 6380,
4343
+ * originalError,
4344
+ * );
4345
+ * ```
4346
+ */
4347
+ declare class RedisTLSError extends RedisConnectionError {
4348
+ constructor(message?: string, host?: string, port?: number, cause?: Error);
4349
+ }
4350
+ /**
4351
+ * Error thrown when maximum connection retries exceeded.
4352
+ *
4353
+ * @example
4354
+ * ```typescript
4355
+ * throw new RedisMaxRetriesError(
4356
+ * 5,
4357
+ * 'localhost',
4358
+ * 6379,
4359
+ * lastError,
4360
+ * );
4361
+ * ```
4362
+ */
4363
+ declare class RedisMaxRetriesError extends RedisConnectionError {
4364
+ readonly maxRetries: number;
4365
+ constructor(maxRetries: number, host?: string, port?: number, cause?: Error);
4366
+ }
4367
+ /**
4368
+ * Error thrown when connection pool is exhausted.
4369
+ *
4370
+ * @example
4371
+ * ```typescript
4372
+ * throw new RedisPoolExhaustedError(10, 100);
4373
+ * ```
4374
+ */
4375
+ declare class RedisPoolExhaustedError extends RedisConnectionError {
4376
+ readonly poolSize: number;
4377
+ readonly waitingClients: number;
4378
+ constructor(poolSize: number, waitingClients: number, cause?: Error);
4379
+ }
4380
+
4381
+ /**
4382
+ * Base class for all Redis operation errors.
4383
+ *
4384
+ * Provides common context for operation failures including
4385
+ * command name and arguments.
4386
+ */
4387
+ declare class RedisOperationError extends RedisXError {
4388
+ readonly command?: string | undefined;
4389
+ constructor(message: string, code: ErrorCode, command?: string | undefined, cause?: Error, context?: Record<string, unknown>);
4390
+ /**
4391
+ * Creates operation error with default code.
4392
+ */
4393
+ static create(message: string, command?: string, cause?: Error): RedisOperationError;
4394
+ /**
4395
+ * Creates operation error from command and arguments.
4396
+ */
4397
+ static fromCommand(command: string, args: unknown[], cause?: Error): RedisOperationError;
4398
+ }
4399
+ /**
4400
+ * Error thrown when Redis key is not found.
4401
+ *
4402
+ * Used for operations that require a key to exist.
4403
+ *
4404
+ * @example
4405
+ * ```typescript
4406
+ * const value = await redis.get('user:123');
4407
+ * if (!value) {
4408
+ * throw new RedisKeyNotFoundError('user:123', 'GET');
4409
+ * }
4410
+ * ```
4411
+ */
4412
+ declare class RedisKeyNotFoundError extends RedisOperationError {
4413
+ readonly key: string;
4414
+ constructor(key: string, command?: string, cause?: Error);
4415
+ }
4416
+ /**
4417
+ * Error thrown when Redis value type doesn't match expected type.
4418
+ *
4419
+ * For example, trying to LPUSH to a string value.
4420
+ *
4421
+ * @example
4422
+ * ```typescript
4423
+ * // Trying to use list command on a string
4424
+ * throw new RedisTypeMismatchError(
4425
+ * 'mykey',
4426
+ * 'list',
4427
+ * 'string',
4428
+ * 'LPUSH',
4429
+ * );
4430
+ * ```
4431
+ */
4432
+ declare class RedisTypeMismatchError extends RedisOperationError {
4433
+ readonly key: string;
4434
+ readonly expected: string;
4435
+ readonly actual: string;
4436
+ constructor(key: string, expected: string, actual: string, command?: string, cause?: Error);
4437
+ /**
4438
+ * Creates type mismatch from Redis WRONGTYPE error.
4439
+ */
4440
+ static fromRedisError(key: string, command: string, cause: Error): RedisTypeMismatchError;
4441
+ }
4442
+ /**
4443
+ * Error thrown when Redis Lua script execution fails.
4444
+ *
4445
+ * Includes script SHA and error details for debugging.
4446
+ *
4447
+ * @example
4448
+ * ```typescript
4449
+ * throw new RedisScriptError(
4450
+ * 'Script execution failed: division by zero',
4451
+ * 'abc123...',
4452
+ * originalError,
4453
+ * { line: 42 },
4454
+ * );
4455
+ * ```
4456
+ */
4457
+ declare class RedisScriptError extends RedisOperationError {
4458
+ readonly scriptSha?: string | undefined;
4459
+ constructor(message: string, scriptSha?: string | undefined, cause?: Error, context?: Record<string, unknown>);
4460
+ /**
4461
+ * Creates script timeout error.
4462
+ */
4463
+ static timeout(timeoutMs: number, scriptSha?: string): RedisScriptError;
4464
+ /**
4465
+ * Creates script not found error (NOSCRIPT).
4466
+ */
4467
+ static notFound(scriptSha: string): RedisScriptError;
4468
+ }
4469
+ /**
4470
+ * Error thrown when Redis transaction (MULTI/EXEC) fails.
4471
+ *
4472
+ * @example
4473
+ * ```typescript
4474
+ * throw new RedisTransactionError(
4475
+ * 'Transaction aborted due to WATCH key modification',
4476
+ * originalError,
4477
+ * );
4478
+ * ```
4479
+ */
4480
+ declare class RedisTransactionError extends RedisOperationError {
4481
+ constructor(message: string, cause?: Error, context?: Record<string, unknown>);
4482
+ /**
4483
+ * Creates transaction aborted error (WATCH failure).
4484
+ */
4485
+ static aborted(): RedisTransactionError;
4486
+ }
4487
+ /**
4488
+ * Error thrown when Redis pipeline execution fails.
4489
+ *
4490
+ * @example
4491
+ * ```typescript
4492
+ * throw new RedisPipelineError(
4493
+ * 'Pipeline execution failed: 3 of 10 commands failed',
4494
+ * 10,
4495
+ * 3,
4496
+ * originalError,
4497
+ * );
4498
+ * ```
4499
+ */
4500
+ declare class RedisPipelineError extends RedisOperationError {
4501
+ readonly totalCommands: number;
4502
+ readonly failedCommands: number;
4503
+ constructor(message: string, totalCommands: number, failedCommands: number, cause?: Error);
4504
+ }
4505
+ /**
4506
+ * Error thrown when operation has invalid arguments.
4507
+ *
4508
+ * @example
4509
+ * ```typescript
4510
+ * throw new RedisInvalidArgsError(
4511
+ * 'SET',
4512
+ * 'TTL must be a positive number',
4513
+ * { ttl: -1 },
4514
+ * );
4515
+ * ```
4516
+ */
4517
+ declare class RedisInvalidArgsError extends RedisOperationError {
4518
+ readonly args?: Record<string, unknown> | undefined;
4519
+ constructor(command: string, reason: string, args?: Record<string, unknown> | undefined);
4520
+ }
4521
+ /**
4522
+ * Error thrown when Redis returns out of memory error.
4523
+ *
4524
+ * @example
4525
+ * ```typescript
4526
+ * throw new RedisOutOfMemoryError('SET', 'user:123');
4527
+ * ```
4528
+ */
4529
+ declare class RedisOutOfMemoryError extends RedisOperationError {
4530
+ readonly key?: string | undefined;
4531
+ constructor(command: string, key?: string | undefined, cause?: Error);
4532
+ }
4533
+ /**
4534
+ * Error thrown when attempting to write to a read-only replica.
4535
+ *
4536
+ * @example
4537
+ * ```typescript
4538
+ * throw new RedisReadOnlyError('SET', 'user:123');
4539
+ * ```
4540
+ */
4541
+ declare class RedisReadOnlyError extends RedisOperationError {
4542
+ readonly key?: string | undefined;
4543
+ constructor(command: string, key?: string | undefined, cause?: Error);
4544
+ }
4545
+ /**
4546
+ * Error thrown when operation is not supported by current driver.
4547
+ *
4548
+ * @example
4549
+ * ```typescript
4550
+ * throw new RedisNotSupportedError(
4551
+ * 'GEOSEARCH',
4552
+ * 'Requires Redis 6.2+',
4553
+ * );
4554
+ * ```
4555
+ */
4556
+ declare class RedisNotSupportedError extends RedisOperationError {
4557
+ readonly reason: string;
4558
+ constructor(command: string, reason: string);
4559
+ }
4560
+ /**
4561
+ * Error thrown when driver is not connected.
4562
+ *
4563
+ * @example
4564
+ * ```typescript
4565
+ * if (!this.isConnected()) {
4566
+ * throw new RedisNotConnectedError('GET');
4567
+ * }
4568
+ * ```
4569
+ */
4570
+ declare class RedisNotConnectedError extends RedisOperationError {
4571
+ constructor(command?: string);
4572
+ }
4573
+
4574
+ /**
4575
+ * Base class for all configuration errors.
4576
+ *
4577
+ * Thrown during module initialization when configuration is invalid.
4578
+ */
4579
+ declare class RedisConfigError extends RedisXError {
4580
+ constructor(message: string, code: ErrorCode, cause?: Error, context?: Record<string, unknown>);
4581
+ /**
4582
+ * Creates generic config error.
4583
+ */
4584
+ static create(message: string, cause?: Error, context?: Record<string, unknown>): RedisConfigError;
4585
+ /**
4586
+ * Creates missing required field error.
4587
+ */
4588
+ static missingRequired(field: string, parent?: string): RedisConfigError;
4589
+ /**
4590
+ * Creates invalid connection type error.
4591
+ */
4592
+ static invalidConnectionType(type: string, validTypes: string[]): RedisConfigError;
4593
+ /**
4594
+ * Creates invalid host/port error.
4595
+ */
4596
+ static invalidHostPort(host?: string, port?: number, reason?: string): RedisConfigError;
4597
+ /**
4598
+ * Creates invalid database number error.
4599
+ */
4600
+ static invalidDb(db: number, max?: number): RedisConfigError;
4601
+ /**
4602
+ * Creates invalid TTL error.
4603
+ */
4604
+ static invalidTTL(ttl: number, reason?: string): RedisConfigError;
4605
+ /**
4606
+ * Creates invalid timeout error.
4607
+ */
4608
+ static invalidTimeout(timeout: number, field: string, reason?: string): RedisConfigError;
4609
+ /**
4610
+ * Creates invalid retry configuration error.
4611
+ */
4612
+ static invalidRetry(reason: string, context?: Record<string, unknown>): RedisConfigError;
4613
+ /**
4614
+ * Creates incompatible configuration error.
4615
+ */
4616
+ static incompatible(option1: string, option2: string, reason?: string): RedisConfigError;
4617
+ /**
4618
+ * Creates driver not supported error.
4619
+ */
4620
+ static driverNotSupported(driver: string, supportedDrivers: string[]): RedisConfigError;
4621
+ /**
4622
+ * Creates invalid cluster nodes error.
4623
+ */
4624
+ static invalidClusterNodes(reason: string, nodes?: Array<{
4625
+ host: string;
4626
+ port: number;
4627
+ }>): RedisConfigError;
4628
+ /**
4629
+ * Creates invalid sentinel configuration error.
4630
+ */
4631
+ static invalidSentinel(reason: string, context?: Record<string, unknown>): RedisConfigError;
4632
+ /**
4633
+ * Creates invalid TLS configuration error.
4634
+ */
4635
+ static invalidTLS(reason: string, context?: Record<string, unknown>): RedisConfigError;
4636
+ }
4637
+ /**
4638
+ * Error thrown when configuration validation fails.
4639
+ *
4640
+ * Used for complex validation rules and schema validation.
4641
+ *
4642
+ * @example
4643
+ * ```typescript
4644
+ * throw new RedisValidationError(
4645
+ * 'clients',
4646
+ * [
4647
+ * { field: 'host', message: 'Host is required' },
4648
+ * { field: 'port', message: 'Port must be between 1 and 65535' },
4649
+ * ],
4650
+ * );
4651
+ * ```
4652
+ */
4653
+ declare class RedisValidationError extends RedisConfigError {
4654
+ readonly field: string;
4655
+ readonly errors: Array<{
4656
+ field: string;
4657
+ message: string;
4658
+ value?: unknown;
4659
+ }>;
4660
+ constructor(field: string, errors: Array<{
4661
+ field: string;
4662
+ message: string;
4663
+ value?: unknown;
4664
+ }>, cause?: Error);
4665
+ /**
4666
+ * Creates validation error from single field.
4667
+ */
4668
+ static single(field: string, message: string, value?: unknown): RedisValidationError;
4669
+ /**
4670
+ * Creates validation error from multiple fields.
4671
+ */
4672
+ static multiple(parent: string, errors: Array<{
4673
+ field: string;
4674
+ message: string;
4675
+ value?: unknown;
4676
+ }>): RedisValidationError;
4677
+ /**
4678
+ * Adds a validation error to the list.
4679
+ */
4680
+ addError(field: string, message: string, value?: unknown): this;
4681
+ /**
4682
+ * Checks if validation has errors.
4683
+ */
4684
+ hasErrors(): boolean;
4685
+ /**
4686
+ * Gets all error messages.
4687
+ */
4688
+ getMessages(): string[];
4689
+ /**
4690
+ * Gets errors for specific field.
4691
+ */
4692
+ getFieldErrors(field: string): Array<{
4693
+ field: string;
4694
+ message: string;
4695
+ value?: unknown;
4696
+ }>;
4697
+ }
4698
+ /**
4699
+ * Validation error collector for building up multiple validation errors.
4700
+ *
4701
+ * @example
4702
+ * ```typescript
4703
+ * const validator = new ValidationErrorCollector('connectionConfig');
4704
+ *
4705
+ * if (!config.host) {
4706
+ * validator.add('host', 'Host is required');
4707
+ * }
4708
+ *
4709
+ * if (config.port < 1 || config.port > 65535) {
4710
+ * validator.add('port', 'Port must be between 1 and 65535', config.port);
4711
+ * }
4712
+ *
4713
+ * validator.throwIfErrors();
4714
+ * ```
4715
+ */
4716
+ declare class ValidationErrorCollector {
4717
+ private readonly parent;
4718
+ private errors;
4719
+ constructor(parent: string);
4720
+ /**
4721
+ * Adds a validation error.
4722
+ */
4723
+ add(field: string, message: string, value?: unknown): this;
4724
+ /**
4725
+ * Checks if there are any errors.
4726
+ */
4727
+ hasErrors(): boolean;
4728
+ /**
4729
+ * Gets error count.
4730
+ */
4731
+ count(): number;
4732
+ /**
4733
+ * Throws if there are any errors.
4734
+ */
4735
+ throwIfErrors(): void;
4736
+ /**
4737
+ * Gets all errors.
4738
+ */
4739
+ getErrors(): Array<{
4740
+ field: string;
4741
+ message: string;
4742
+ value?: unknown;
4743
+ }>;
4744
+ /**
4745
+ * Clears all errors.
4746
+ */
4747
+ clear(): void;
4748
+ }
4749
+
4750
+ /**
4751
+ * Driver-specific error classes with simplified constructors.
4752
+ * Used internally by driver adapters (ioredis, node-redis).
4753
+ */
4754
+
4755
+ /**
4756
+ * Base class for driver-related errors.
4757
+ */
4758
+ declare class DriverError extends RedisConnectionError {
4759
+ constructor(message: string, code: ErrorCode, cause?: Error, context?: Record<string, unknown>);
4760
+ }
4761
+ /**
4762
+ * Error thrown when connection to Redis fails.
4763
+ */
4764
+ declare class ConnectionError extends RedisConnectionError {
4765
+ readonly host?: string | undefined;
4766
+ readonly port?: number | undefined;
4767
+ constructor(message: string, cause?: Error, host?: string | undefined, port?: number | undefined);
4768
+ }
4769
+ /**
4770
+ * Error thrown when operation times out.
4771
+ */
4772
+ declare class TimeoutError extends RedisTimeoutError {
4773
+ constructor(operation: string, timeoutMs: number, cause?: Error);
4774
+ }
4775
+ /**
4776
+ * Error thrown when Redis command fails.
4777
+ */
4778
+ declare class CommandError extends RedisOperationError {
4779
+ readonly command: string;
4780
+ readonly args: unknown[];
4781
+ constructor(command: string, args: unknown[], cause?: Error);
4782
+ }
4783
+
4784
+ /**
4785
+ * Dependency injection tokens for NestJS RedisX.
4786
+ */
4787
+ /**
4788
+ * Token for injecting module options.
4789
+ * Used for synchronous and asynchronous configuration.
4790
+ */
4791
+ declare const REDIS_MODULE_OPTIONS: unique symbol;
4792
+ /**
4793
+ * Token for injecting default Redis client.
4794
+ * Points to the 'default' named client.
4795
+ */
4796
+ declare const REDIS_CLIENT: unique symbol;
4797
+ /**
4798
+ * Token for injecting Redis clients map.
4799
+ * Contains all registered named clients.
4800
+ */
4801
+ declare const REDIS_CLIENTS_MAP: unique symbol;
4802
+ /**
4803
+ * Token for injecting client manager.
4804
+ * Manages lifecycle of all Redis clients.
4805
+ */
4806
+ declare const CLIENT_MANAGER: unique symbol;
4807
+ /**
4808
+ * Token for injecting Redis driver.
4809
+ * Abstracts ioredis/node-redis implementation.
4810
+ */
4811
+ declare const REDIS_DRIVER: unique symbol;
4812
+ /**
4813
+ * Token for injecting RedisX configuration.
4814
+ * Contains module-level and global configuration.
4815
+ */
4816
+ declare const REDISX_CONFIG: unique symbol;
4817
+ /**
4818
+ * Token for injecting plugin registry.
4819
+ * Manages plugin lifecycle and dependencies.
4820
+ */
4821
+ declare const PLUGIN_REGISTRY: unique symbol;
4822
+ /**
4823
+ * Token for injecting registered plugins array.
4824
+ * Used internally by PluginRegistryService.
4825
+ */
4826
+ declare const REGISTERED_PLUGINS: unique symbol;
4827
+ /**
4828
+ * Token for injecting logger.
4829
+ * Provides structured logging for RedisX.
4830
+ */
4831
+ declare const REDISX_LOGGER: unique symbol;
4832
+ /**
4833
+ * Creates a token for named Redis client.
4834
+ * @param name - Client name
4835
+ * @returns Injection token
4836
+ *
4837
+ * @example
4838
+ * ```typescript
4839
+ * @Injectable()
4840
+ * export class MyService {
4841
+ * constructor(
4842
+ * @Inject(getClientToken('cache'))
4843
+ * private readonly cacheClient: IRedisClient
4844
+ * ) {}
4845
+ * }
4846
+ * ```
4847
+ */
4848
+ declare function getClientToken(name: string): symbol;
4849
+ /**
4850
+ * Creates a token for named driver.
4851
+ * @param name - Driver name
4852
+ * @returns Injection token
4853
+ */
4854
+ declare function getDriverToken(name: string): symbol;
4855
+ /**
4856
+ * Default client name.
4857
+ */
4858
+ declare const DEFAULT_CLIENT_NAME = "default";
4859
+ /**
4860
+ * Default driver type.
4861
+ */
4862
+ declare const DEFAULT_DRIVER_TYPE = "ioredis";
4863
+ /**
4864
+ * Module name for logging.
4865
+ */
4866
+ declare const MODULE_NAME = "RedisXModule";
4867
+ /**
4868
+ * Default connection timeout (ms).
4869
+ */
4870
+ declare const DEFAULT_CONNECTION_TIMEOUT = 10000;
4871
+ /**
4872
+ * Default command timeout (ms).
4873
+ */
4874
+ declare const DEFAULT_COMMAND_TIMEOUT = 5000;
4875
+ /**
4876
+ * Default graceful shutdown timeout (ms).
4877
+ */
4878
+ declare const DEFAULT_GRACEFUL_SHUTDOWN_TIMEOUT = 5000;
4879
+ /**
4880
+ * Token for async clients initialization.
4881
+ * Used internally to ensure clients are created before injection.
4882
+ */
4883
+ declare const REDIS_CLIENTS_INITIALIZATION: unique symbol;
4884
+ /**
4885
+ * Default health check interval (ms).
4886
+ */
4887
+ declare const DEFAULT_HEALTH_CHECK_INTERVAL = 30000;
4888
+
4889
+ /**
4890
+ * Shared types for NestJS RedisX.
4891
+ */
4892
+ /**
4893
+ * Generic async function type.
4894
+ */
4895
+ type AsyncFunction<TArgs extends unknown[] = [], TReturn = unknown> = (...args: TArgs) => Promise<TReturn>;
4896
+ /**
4897
+ * Nullable type helper.
4898
+ */
4899
+ type Nullable<T> = T | null;
4900
+ /**
4901
+ * Optional type helper.
4902
+ */
4903
+ type Optional<T> = T | undefined;
4904
+ /**
4905
+ * Makes all properties optional recursively.
4906
+ */
4907
+ type DeepPartial<T> = {
4908
+ [P in keyof T]?: T[P] extends object ? DeepPartial<T[P]> : T[P];
4909
+ };
4910
+ /**
4911
+ * Makes all properties required recursively.
4912
+ */
4913
+ type DeepRequired<T> = {
4914
+ [P in keyof T]-?: T[P] extends object ? DeepRequired<T[P]> : T[P];
4915
+ };
4916
+
4917
+ export { type AsyncFunction, BaseRedisDriver, CLIENT_MANAGER, CommandError, type ConnectionConfig, ConnectionError, ConnectionStatus, DEFAULT_CLIENT_NAME, DEFAULT_COMMAND_TIMEOUT, DEFAULT_CONNECTION_TIMEOUT, DEFAULT_DRIVER_TYPE, DEFAULT_GRACEFUL_SHUTDOWN_TIMEOUT, DEFAULT_HEALTH_CHECK_INTERVAL, type DeepPartial, type DeepRequired, DriverError, DriverEvent, type DriverEventHandler, DriverFactory, type DriverType, ErrorCode, type GeoUnit, type IBaseConnectionConfig, type IClientHealthStatus, type IClientManager, type IClientMetadata, type IClientStats, type IClusterConnectionConfig, type IConnectionStats, type ICopyOptions, type IDriverFactoryOptions, type IErrorJSON, type IGeoSearchOptions, type IGeoSearchResult, type IGlobalConfig, type IHealthCheckResult, type IHealthStatus, type ILposOptions, type IManagerEventData, type IMulti, type IPipeline, type IPluginContext, type IReconnectionOptions, type IRedisClient, type IRedisClientOptions, type IRedisDriver, type IRedisDriverManager, type IRedisModuleAsyncOptions, type IRedisModuleOptions, type IRedisModuleOptionsFactory, type IRedisXPlugin, type IRestoreOptions, type IScanOptions, type ISentinelConnectionConfig, type ISetOptions, type ISingleConnectionConfig, type IStreamAddOptions, type IStreamEntry, type IStreamInfo, type IStreamPendingEntry, type IStreamPendingInfo, type IStreamReadGroupOptions, type IStreamReadOptions, type ITlsConfig, type IZRangeByScoreOptions, type IZStoreOptions, InjectRedis, IoRedisAdapter, MODULE_NAME, ManagerEvent, type ManagerEventHandler, NodeRedisAdapter, type Nullable, type Optional, PLUGIN_REGISTRY, PluginRegistryService, REDISX_CONFIG, REDISX_LOGGER, REDIS_CLIENT, REDIS_CLIENTS_INITIALIZATION, REDIS_CLIENTS_MAP, REDIS_DRIVER, REDIS_MODULE_OPTIONS, REGISTERED_PLUGINS, RedisAuthError, RedisClientManager, RedisClusterError, RedisConfigError, RedisConnectionError, RedisInvalidArgsError, RedisKeyNotFoundError, RedisMaxRetriesError, RedisModule, RedisNotConnectedError, RedisNotSupportedError, RedisOperationError, RedisOutOfMemoryError, RedisPipelineError, RedisPoolExhaustedError, RedisReadOnlyError, RedisScriptError, RedisSentinelError, RedisService, RedisTLSError, RedisTimeoutError, RedisTransactionError, RedisTypeMismatchError, RedisValidationError, RedisXError, type StreamReadResult, TimeoutError, ValidationErrorCollector, createDriver, createDrivers, detectAvailableDriver, getClientToken, getDriverToken, getErrorDomain, getRecommendedDriver, hasClass, hasExisting, hasFactory, isClusterConnection, isErrorCode, isErrorDomain, isSentinelConnection, isSingleConnection };