@naman_deep_singh/cache 1.1.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.
Files changed (97) hide show
  1. package/README.md +637 -0
  2. package/dist/cjs/adapters/memcache/MemcacheCache.d.ts +71 -0
  3. package/dist/cjs/adapters/memcache/MemcacheCache.js +347 -0
  4. package/dist/cjs/adapters/memcache/index.d.ts +1 -0
  5. package/dist/cjs/adapters/memcache/index.js +5 -0
  6. package/dist/cjs/adapters/memory/MemoryCache.d.ts +63 -0
  7. package/dist/cjs/adapters/memory/MemoryCache.js +273 -0
  8. package/dist/cjs/adapters/memory/index.d.ts +1 -0
  9. package/dist/cjs/adapters/memory/index.js +5 -0
  10. package/dist/cjs/adapters/redis/RedisCache.d.ts +67 -0
  11. package/dist/cjs/adapters/redis/RedisCache.js +288 -0
  12. package/dist/cjs/adapters/redis/index.d.ts +1 -0
  13. package/dist/cjs/adapters/redis/index.js +5 -0
  14. package/dist/cjs/core/BaseCache.d.ts +78 -0
  15. package/dist/cjs/core/BaseCache.js +138 -0
  16. package/dist/cjs/core/factory.d.ts +16 -0
  17. package/dist/cjs/core/factory.js +51 -0
  18. package/dist/cjs/core/interfaces/ICache.d.ts +58 -0
  19. package/dist/cjs/core/interfaces/ICache.js +2 -0
  20. package/dist/cjs/core/interfaces/ISession.d.ts +30 -0
  21. package/dist/cjs/core/interfaces/ISession.js +2 -0
  22. package/dist/cjs/core/interfaces/index.d.ts +2 -0
  23. package/dist/cjs/core/interfaces/index.js +2 -0
  24. package/dist/cjs/errors/CacheError.d.ts +9 -0
  25. package/dist/cjs/errors/CacheError.js +17 -0
  26. package/dist/cjs/errors/index.d.ts +1 -0
  27. package/dist/cjs/errors/index.js +5 -0
  28. package/dist/cjs/index.d.ts +10 -0
  29. package/dist/cjs/index.js +27 -0
  30. package/dist/cjs/middleware/express/cacheMiddleware.d.ts +22 -0
  31. package/dist/cjs/middleware/express/cacheMiddleware.js +100 -0
  32. package/dist/cjs/middleware/express/index.d.ts +1 -0
  33. package/dist/cjs/middleware/express/index.js +7 -0
  34. package/dist/cjs/session/SessionStore.d.ts +51 -0
  35. package/dist/cjs/session/SessionStore.js +153 -0
  36. package/dist/cjs/session/index.d.ts +2 -0
  37. package/dist/cjs/session/index.js +5 -0
  38. package/dist/cjs/types.d.ts +83 -0
  39. package/dist/cjs/types.js +2 -0
  40. package/dist/esm/adapters/memcache/MemcacheCache.d.ts +71 -0
  41. package/dist/esm/adapters/memcache/MemcacheCache.js +340 -0
  42. package/dist/esm/adapters/memcache/index.d.ts +1 -0
  43. package/dist/esm/adapters/memcache/index.js +1 -0
  44. package/dist/esm/adapters/memory/MemoryCache.d.ts +63 -0
  45. package/dist/esm/adapters/memory/MemoryCache.js +269 -0
  46. package/dist/esm/adapters/memory/index.d.ts +1 -0
  47. package/dist/esm/adapters/memory/index.js +1 -0
  48. package/dist/esm/adapters/redis/RedisCache.d.ts +67 -0
  49. package/dist/esm/adapters/redis/RedisCache.js +284 -0
  50. package/dist/esm/adapters/redis/index.d.ts +1 -0
  51. package/dist/esm/adapters/redis/index.js +1 -0
  52. package/dist/esm/core/BaseCache.d.ts +78 -0
  53. package/dist/esm/core/BaseCache.js +134 -0
  54. package/dist/esm/core/factory.d.ts +16 -0
  55. package/dist/esm/core/factory.js +47 -0
  56. package/dist/esm/core/interfaces/ICache.d.ts +58 -0
  57. package/dist/esm/core/interfaces/ICache.js +1 -0
  58. package/dist/esm/core/interfaces/ISession.d.ts +30 -0
  59. package/dist/esm/core/interfaces/ISession.js +1 -0
  60. package/dist/esm/core/interfaces/index.d.ts +2 -0
  61. package/dist/esm/core/interfaces/index.js +1 -0
  62. package/dist/esm/errors/CacheError.d.ts +9 -0
  63. package/dist/esm/errors/CacheError.js +13 -0
  64. package/dist/esm/errors/index.d.ts +1 -0
  65. package/dist/esm/errors/index.js +1 -0
  66. package/dist/esm/index.d.ts +10 -0
  67. package/dist/esm/index.js +14 -0
  68. package/dist/esm/middleware/express/cacheMiddleware.d.ts +22 -0
  69. package/dist/esm/middleware/express/cacheMiddleware.js +95 -0
  70. package/dist/esm/middleware/express/index.d.ts +1 -0
  71. package/dist/esm/middleware/express/index.js +1 -0
  72. package/dist/esm/session/SessionStore.d.ts +51 -0
  73. package/dist/esm/session/SessionStore.js +149 -0
  74. package/dist/esm/session/index.d.ts +2 -0
  75. package/dist/esm/session/index.js +1 -0
  76. package/dist/esm/types.d.ts +83 -0
  77. package/dist/esm/types.js +1 -0
  78. package/dist/types/adapters/memcache/MemcacheCache.d.ts +71 -0
  79. package/dist/types/adapters/memcache/index.d.ts +1 -0
  80. package/dist/types/adapters/memory/MemoryCache.d.ts +63 -0
  81. package/dist/types/adapters/memory/index.d.ts +1 -0
  82. package/dist/types/adapters/redis/RedisCache.d.ts +67 -0
  83. package/dist/types/adapters/redis/index.d.ts +1 -0
  84. package/dist/types/core/BaseCache.d.ts +78 -0
  85. package/dist/types/core/factory.d.ts +16 -0
  86. package/dist/types/core/interfaces/ICache.d.ts +58 -0
  87. package/dist/types/core/interfaces/ISession.d.ts +30 -0
  88. package/dist/types/core/interfaces/index.d.ts +2 -0
  89. package/dist/types/errors/CacheError.d.ts +9 -0
  90. package/dist/types/errors/index.d.ts +1 -0
  91. package/dist/types/index.d.ts +10 -0
  92. package/dist/types/middleware/express/cacheMiddleware.d.ts +22 -0
  93. package/dist/types/middleware/express/index.d.ts +1 -0
  94. package/dist/types/session/SessionStore.d.ts +51 -0
  95. package/dist/types/session/index.d.ts +2 -0
  96. package/dist/types/types.d.ts +83 -0
  97. package/package.json +48 -0
@@ -0,0 +1,269 @@
1
+ import { BaseCache } from '../../core/BaseCache';
2
+ import { CacheError } from '../../errors';
3
+ /**
4
+ * In-memory cache adapter for development and testing
5
+ */
6
+ export class MemoryCache extends BaseCache {
7
+ constructor(memoryCacheConfig) {
8
+ super(memoryCacheConfig);
9
+ this.memoryCacheConfig = memoryCacheConfig;
10
+ this.store = new Map();
11
+ this.cleanupInterval = null;
12
+ this.startCleanup();
13
+ }
14
+ /**
15
+ * Start periodic cleanup of expired items
16
+ */
17
+ startCleanup() {
18
+ if (this.cleanupInterval)
19
+ return;
20
+ this.cleanupInterval = setInterval(() => {
21
+ const now = Date.now();
22
+ for (const [key, entry] of this.store.entries()) {
23
+ if (entry.expiresAt && entry.expiresAt < now) {
24
+ this.store.delete(key);
25
+ }
26
+ }
27
+ }, 30000); // Cleanup every 30 seconds
28
+ }
29
+ /**
30
+ * Get a value from memory
31
+ */
32
+ async get(key) {
33
+ try {
34
+ const fullKey = this.buildKey(key);
35
+ const entry = this.store.get(fullKey);
36
+ if (!entry) {
37
+ this.recordMiss();
38
+ return null;
39
+ }
40
+ // Check if expired
41
+ if (entry.expiresAt && entry.expiresAt < Date.now()) {
42
+ this.store.delete(fullKey);
43
+ this.recordMiss();
44
+ return null;
45
+ }
46
+ this.recordHit();
47
+ return entry.value;
48
+ }
49
+ catch (err) {
50
+ throw new CacheError(`Failed to get key "${key}" from memory cache`, 'MEMORY_GET_ERROR', 'memory', err);
51
+ }
52
+ }
53
+ /**
54
+ * Set a value in memory
55
+ */
56
+ async set(key, value, ttl) {
57
+ try {
58
+ const fullKey = this.buildKey(key);
59
+ const expiry = ttl ?? this.ttl;
60
+ const expiresAt = expiry > 0 ? Date.now() + expiry * 1000 : undefined;
61
+ // Check max size
62
+ const maxSize = this.memoryCacheConfig.maxSize;
63
+ if (maxSize && this.store.size >= maxSize && !this.store.has(fullKey)) {
64
+ // Remove oldest entry
65
+ const firstKey = this.store.keys().next().value;
66
+ if (firstKey) {
67
+ this.store.delete(firstKey);
68
+ }
69
+ }
70
+ this.store.set(fullKey, { value, expiresAt });
71
+ this.recordSet();
72
+ }
73
+ catch (err) {
74
+ throw new CacheError(`Failed to set key "${key}" in memory cache`, 'MEMORY_SET_ERROR', 'memory', err);
75
+ }
76
+ }
77
+ /**
78
+ * Delete a key from memory
79
+ */
80
+ async delete(key) {
81
+ try {
82
+ const fullKey = this.buildKey(key);
83
+ const deleted = this.store.delete(fullKey);
84
+ if (deleted) {
85
+ this.recordDelete();
86
+ }
87
+ return deleted;
88
+ }
89
+ catch (err) {
90
+ throw new CacheError(`Failed to delete key "${key}" from memory cache`, 'MEMORY_DELETE_ERROR', 'memory', err);
91
+ }
92
+ }
93
+ /**
94
+ * Check if key exists
95
+ */
96
+ async exists(key) {
97
+ try {
98
+ const fullKey = this.buildKey(key);
99
+ const entry = this.store.get(fullKey);
100
+ if (!entry) {
101
+ return false;
102
+ }
103
+ // Check if expired
104
+ if (entry.expiresAt && entry.expiresAt < Date.now()) {
105
+ this.store.delete(fullKey);
106
+ return false;
107
+ }
108
+ return true;
109
+ }
110
+ catch (err) {
111
+ throw new CacheError(`Failed to check existence of key "${key}" in memory cache`, 'MEMORY_EXISTS_ERROR', 'memory', err);
112
+ }
113
+ }
114
+ /**
115
+ * Clear all keys with current namespace
116
+ */
117
+ async clear() {
118
+ try {
119
+ if (this.namespace) {
120
+ // Clear only keys with current namespace
121
+ for (const key of this.store.keys()) {
122
+ if (key.startsWith(this.namespace)) {
123
+ this.store.delete(key);
124
+ }
125
+ }
126
+ }
127
+ else {
128
+ // Clear all
129
+ this.store.clear();
130
+ }
131
+ }
132
+ catch (err) {
133
+ throw new CacheError('Failed to clear memory cache', 'MEMORY_CLEAR_ERROR', 'memory', err);
134
+ }
135
+ }
136
+ /**
137
+ * Get multiple values at once
138
+ */
139
+ async getMultiple(keys) {
140
+ try {
141
+ const result = {};
142
+ const now = Date.now();
143
+ for (const key of keys) {
144
+ const fullKey = this.buildKey(key);
145
+ const entry = this.store.get(fullKey);
146
+ if (!entry) {
147
+ this.recordMiss();
148
+ result[key] = null;
149
+ continue;
150
+ }
151
+ // Check if expired
152
+ if (entry.expiresAt && entry.expiresAt < now) {
153
+ this.store.delete(fullKey);
154
+ this.recordMiss();
155
+ result[key] = null;
156
+ }
157
+ else {
158
+ this.recordHit();
159
+ result[key] = entry.value;
160
+ }
161
+ }
162
+ return result;
163
+ }
164
+ catch (err) {
165
+ throw new CacheError('Failed to get multiple keys from memory cache', 'MEMORY_GET_MULTIPLE_ERROR', 'memory', err);
166
+ }
167
+ }
168
+ /**
169
+ * Set multiple values at once
170
+ */
171
+ async setMultiple(data, ttl) {
172
+ try {
173
+ const expiry = ttl ?? this.ttl;
174
+ const expiresAt = expiry > 0 ? Date.now() + expiry * 1000 : undefined;
175
+ for (const [key, value] of Object.entries(data)) {
176
+ const fullKey = this.buildKey(key);
177
+ this.store.set(fullKey, { value, expiresAt });
178
+ }
179
+ this.stats.sets += Object.keys(data).length;
180
+ }
181
+ catch (err) {
182
+ throw new CacheError('Failed to set multiple keys in memory cache', 'MEMORY_SET_MULTIPLE_ERROR', 'memory', err);
183
+ }
184
+ }
185
+ /**
186
+ * Delete multiple keys at once
187
+ */
188
+ async deleteMultiple(keys) {
189
+ try {
190
+ let count = 0;
191
+ for (const key of keys) {
192
+ const fullKey = this.buildKey(key);
193
+ if (this.store.delete(fullKey)) {
194
+ count++;
195
+ }
196
+ }
197
+ this.stats.deletes += count;
198
+ return count;
199
+ }
200
+ catch (err) {
201
+ throw new CacheError('Failed to delete multiple keys from memory cache', 'MEMORY_DELETE_MULTIPLE_ERROR', 'memory', err);
202
+ }
203
+ }
204
+ /**
205
+ * Increment a numeric value
206
+ */
207
+ async increment(key, amount = 1) {
208
+ try {
209
+ const fullKey = this.buildKey(key);
210
+ const entry = this.store.get(fullKey);
211
+ const current = entry && (!entry.expiresAt || entry.expiresAt >= Date.now())
212
+ ? (typeof entry.value === 'number' ? entry.value : 0)
213
+ : 0;
214
+ const value = current + amount;
215
+ const expiry = this.ttl;
216
+ const expiresAt = expiry > 0 ? Date.now() + expiry * 1000 : undefined;
217
+ this.store.set(fullKey, { value: value, expiresAt });
218
+ return value;
219
+ }
220
+ catch (err) {
221
+ throw new CacheError(`Failed to increment key "${key}" in memory cache`, 'MEMORY_INCREMENT_ERROR', 'memory', err);
222
+ }
223
+ }
224
+ /**
225
+ * Decrement a numeric value
226
+ */
227
+ async decrement(key, amount = 1) {
228
+ try {
229
+ const fullKey = this.buildKey(key);
230
+ const entry = this.store.get(fullKey);
231
+ const current = entry && (!entry.expiresAt || entry.expiresAt >= Date.now())
232
+ ? (typeof entry.value === 'number' ? entry.value : 0)
233
+ : 0;
234
+ const value = current - amount;
235
+ const expiry = this.ttl;
236
+ const expiresAt = expiry > 0 ? Date.now() + expiry * 1000 : undefined;
237
+ this.store.set(fullKey, { value: value, expiresAt });
238
+ return value;
239
+ }
240
+ catch (err) {
241
+ throw new CacheError(`Failed to decrement key "${key}" in memory cache`, 'MEMORY_DECREMENT_ERROR', 'memory', err);
242
+ }
243
+ }
244
+ /**
245
+ * Check if memory cache is alive
246
+ */
247
+ async isAlive() {
248
+ return {
249
+ isAlive: true,
250
+ adapter: 'memory',
251
+ timestamp: new Date()
252
+ };
253
+ }
254
+ /**
255
+ * Close memory cache
256
+ */
257
+ async close() {
258
+ try {
259
+ if (this.cleanupInterval) {
260
+ clearInterval(this.cleanupInterval);
261
+ this.cleanupInterval = null;
262
+ }
263
+ this.store.clear();
264
+ }
265
+ catch (err) {
266
+ throw new CacheError('Failed to close memory cache', 'MEMORY_CLOSE_ERROR', 'memory', err);
267
+ }
268
+ }
269
+ }
@@ -0,0 +1 @@
1
+ export { MemoryCache } from './MemoryCache';
@@ -0,0 +1 @@
1
+ export { MemoryCache } from './MemoryCache';
@@ -0,0 +1,67 @@
1
+ import type { RedisCacheConfig, HealthCheckResponse } from '../../types';
2
+ import { BaseCache } from '../../core/BaseCache';
3
+ /**
4
+ * Redis cache adapter
5
+ */
6
+ export declare class RedisCache<T = unknown> extends BaseCache<T> {
7
+ private redisConfig;
8
+ private client;
9
+ private isConnected;
10
+ constructor(redisConfig: RedisCacheConfig);
11
+ /**
12
+ * Connect to Redis
13
+ */
14
+ connect(): Promise<void>;
15
+ /**
16
+ * Ensure client is connected
17
+ */
18
+ private ensureConnected;
19
+ /**
20
+ * Get a value from Redis
21
+ */
22
+ get(key: string): Promise<T | null>;
23
+ /**
24
+ * Set a value in Redis
25
+ */
26
+ set(key: string, value: T, ttl?: number): Promise<void>;
27
+ /**
28
+ * Delete a key from Redis
29
+ */
30
+ delete(key: string): Promise<boolean>;
31
+ /**
32
+ * Check if key exists
33
+ */
34
+ exists(key: string): Promise<boolean>;
35
+ /**
36
+ * Clear all keys with current namespace
37
+ */
38
+ clear(): Promise<void>;
39
+ /**
40
+ * Get multiple values at once
41
+ */
42
+ getMultiple(keys: string[]): Promise<Record<string, T | null>>;
43
+ /**
44
+ * Set multiple values at once
45
+ */
46
+ setMultiple(data: Record<string, T>, ttl?: number): Promise<void>;
47
+ /**
48
+ * Delete multiple keys at once
49
+ */
50
+ deleteMultiple(keys: string[]): Promise<number>;
51
+ /**
52
+ * Increment a numeric value
53
+ */
54
+ increment(key: string, amount?: number): Promise<number>;
55
+ /**
56
+ * Decrement a numeric value
57
+ */
58
+ decrement(key: string, amount?: number): Promise<number>;
59
+ /**
60
+ * Check if Redis is alive
61
+ */
62
+ isAlive(): Promise<HealthCheckResponse>;
63
+ /**
64
+ * Close Redis connection
65
+ */
66
+ close(): Promise<void>;
67
+ }
@@ -0,0 +1,284 @@
1
+ import { createClient } from 'redis';
2
+ import { BaseCache } from '../../core/BaseCache';
3
+ import { CacheError } from '../../errors';
4
+ /**
5
+ * Redis cache adapter
6
+ */
7
+ export class RedisCache extends BaseCache {
8
+ constructor(redisConfig) {
9
+ super(redisConfig);
10
+ this.redisConfig = redisConfig;
11
+ this.client = null;
12
+ this.isConnected = false;
13
+ }
14
+ /**
15
+ * Connect to Redis
16
+ */
17
+ async connect() {
18
+ try {
19
+ const options = {
20
+ host: this.redisConfig.host ?? 'localhost',
21
+ port: this.redisConfig.port ?? 6379,
22
+ db: this.redisConfig.db ?? 0
23
+ };
24
+ if (this.redisConfig.username) {
25
+ options.username = this.redisConfig.username;
26
+ }
27
+ if (this.redisConfig.password) {
28
+ options.password = this.redisConfig.password;
29
+ }
30
+ if (this.redisConfig.tls) {
31
+ options.tls = true;
32
+ }
33
+ this.client = createClient(options);
34
+ this.client.on('error', (err) => {
35
+ this.isConnected = false;
36
+ console.error('Redis connection error:', err);
37
+ });
38
+ this.client.on('connect', () => {
39
+ this.isConnected = true;
40
+ });
41
+ await this.client.connect();
42
+ this.isConnected = true;
43
+ }
44
+ catch (err) {
45
+ throw new CacheError('Failed to connect to Redis', 'REDIS_CONNECTION_ERROR', 'redis', err);
46
+ }
47
+ }
48
+ /**
49
+ * Ensure client is connected
50
+ */
51
+ async ensureConnected() {
52
+ if (!this.client) {
53
+ await this.connect();
54
+ }
55
+ }
56
+ /**
57
+ * Get a value from Redis
58
+ */
59
+ async get(key) {
60
+ try {
61
+ await this.ensureConnected();
62
+ const fullKey = this.buildKey(key);
63
+ const value = await this.client.get(fullKey);
64
+ if (value === null) {
65
+ this.recordMiss();
66
+ return null;
67
+ }
68
+ this.recordHit();
69
+ return this.deserialize(value);
70
+ }
71
+ catch (err) {
72
+ throw new CacheError(`Failed to get key "${key}" from Redis`, 'REDIS_GET_ERROR', 'redis', err);
73
+ }
74
+ }
75
+ /**
76
+ * Set a value in Redis
77
+ */
78
+ async set(key, value, ttl) {
79
+ try {
80
+ await this.ensureConnected();
81
+ const fullKey = this.buildKey(key);
82
+ const serialized = this.serialize(value);
83
+ const expiry = ttl ?? this.ttl;
84
+ if (expiry > 0) {
85
+ await this.client.setEx(fullKey, expiry, serialized);
86
+ }
87
+ else {
88
+ await this.client.set(fullKey, serialized);
89
+ }
90
+ this.recordSet();
91
+ }
92
+ catch (err) {
93
+ throw new CacheError(`Failed to set key "${key}" in Redis`, 'REDIS_SET_ERROR', 'redis', err);
94
+ }
95
+ }
96
+ /**
97
+ * Delete a key from Redis
98
+ */
99
+ async delete(key) {
100
+ try {
101
+ await this.ensureConnected();
102
+ const fullKey = this.buildKey(key);
103
+ const result = await this.client.del(fullKey);
104
+ this.recordDelete();
105
+ return result > 0;
106
+ }
107
+ catch (err) {
108
+ throw new CacheError(`Failed to delete key "${key}" from Redis`, 'REDIS_DELETE_ERROR', 'redis', err);
109
+ }
110
+ }
111
+ /**
112
+ * Check if key exists
113
+ */
114
+ async exists(key) {
115
+ try {
116
+ await this.ensureConnected();
117
+ const fullKey = this.buildKey(key);
118
+ const result = await this.client.exists(fullKey);
119
+ return result > 0;
120
+ }
121
+ catch (err) {
122
+ throw new CacheError(`Failed to check existence of key "${key}" in Redis`, 'REDIS_EXISTS_ERROR', 'redis', err);
123
+ }
124
+ }
125
+ /**
126
+ * Clear all keys with current namespace
127
+ */
128
+ async clear() {
129
+ try {
130
+ await this.ensureConnected();
131
+ if (this.namespace) {
132
+ // Clear only keys with the current namespace
133
+ const pattern = `${this.namespace}*`;
134
+ const keys = await this.client.keys(pattern);
135
+ if (keys.length > 0) {
136
+ await this.client.del(keys);
137
+ }
138
+ }
139
+ else {
140
+ // Clear all keys
141
+ await this.client.flushDb();
142
+ }
143
+ }
144
+ catch (err) {
145
+ throw new CacheError('Failed to clear Redis cache', 'REDIS_CLEAR_ERROR', 'redis', err);
146
+ }
147
+ }
148
+ /**
149
+ * Get multiple values at once
150
+ */
151
+ async getMultiple(keys) {
152
+ try {
153
+ await this.ensureConnected();
154
+ const fullKeys = keys.map(k => this.buildKey(k));
155
+ const values = await this.client.mGet(fullKeys);
156
+ const result = {};
157
+ keys.forEach((key, index) => {
158
+ const value = values[index];
159
+ if (value === null) {
160
+ this.recordMiss();
161
+ result[key] = null;
162
+ }
163
+ else {
164
+ this.recordHit();
165
+ result[key] = this.deserialize(value);
166
+ }
167
+ });
168
+ return result;
169
+ }
170
+ catch (err) {
171
+ throw new CacheError('Failed to get multiple keys from Redis', 'REDIS_GET_MULTIPLE_ERROR', 'redis', err);
172
+ }
173
+ }
174
+ /**
175
+ * Set multiple values at once
176
+ */
177
+ async setMultiple(data, ttl) {
178
+ try {
179
+ await this.ensureConnected();
180
+ const expiry = ttl ?? this.ttl;
181
+ if (expiry > 0) {
182
+ // Use pipeline for batch operations with TTL
183
+ const pipeline = this.client.multi();
184
+ for (const [key, value] of Object.entries(data)) {
185
+ const fullKey = this.buildKey(key);
186
+ const serialized = this.serialize(value);
187
+ pipeline.setEx(fullKey, expiry, serialized);
188
+ }
189
+ await pipeline.exec();
190
+ }
191
+ else {
192
+ // Use mSet for batch operations without TTL
193
+ const flatData = {};
194
+ for (const [key, value] of Object.entries(data)) {
195
+ const fullKey = this.buildKey(key);
196
+ flatData[fullKey] = this.serialize(value);
197
+ }
198
+ await this.client.mSet(flatData);
199
+ }
200
+ this.stats.sets += Object.keys(data).length;
201
+ }
202
+ catch (err) {
203
+ throw new CacheError('Failed to set multiple keys in Redis', 'REDIS_SET_MULTIPLE_ERROR', 'redis', err);
204
+ }
205
+ }
206
+ /**
207
+ * Delete multiple keys at once
208
+ */
209
+ async deleteMultiple(keys) {
210
+ try {
211
+ await this.ensureConnected();
212
+ const fullKeys = keys.map(k => this.buildKey(k));
213
+ const result = await this.client.del(fullKeys);
214
+ this.stats.deletes += result;
215
+ return result;
216
+ }
217
+ catch (err) {
218
+ throw new CacheError('Failed to delete multiple keys from Redis', 'REDIS_DELETE_MULTIPLE_ERROR', 'redis', err);
219
+ }
220
+ }
221
+ /**
222
+ * Increment a numeric value
223
+ */
224
+ async increment(key, amount = 1) {
225
+ try {
226
+ await this.ensureConnected();
227
+ const fullKey = this.buildKey(key);
228
+ return await this.client.incrBy(fullKey, amount);
229
+ }
230
+ catch (err) {
231
+ throw new CacheError(`Failed to increment key "${key}" in Redis`, 'REDIS_INCREMENT_ERROR', 'redis', err);
232
+ }
233
+ }
234
+ /**
235
+ * Decrement a numeric value
236
+ */
237
+ async decrement(key, amount = 1) {
238
+ try {
239
+ await this.ensureConnected();
240
+ const fullKey = this.buildKey(key);
241
+ return await this.client.decrBy(fullKey, amount);
242
+ }
243
+ catch (err) {
244
+ throw new CacheError(`Failed to decrement key "${key}" in Redis`, 'REDIS_DECREMENT_ERROR', 'redis', err);
245
+ }
246
+ }
247
+ /**
248
+ * Check if Redis is alive
249
+ */
250
+ async isAlive() {
251
+ try {
252
+ await this.ensureConnected();
253
+ await this.client.ping();
254
+ return {
255
+ isAlive: true,
256
+ adapter: 'redis',
257
+ timestamp: new Date()
258
+ };
259
+ }
260
+ catch (err) {
261
+ return {
262
+ isAlive: false,
263
+ adapter: 'redis',
264
+ timestamp: new Date(),
265
+ error: err.message
266
+ };
267
+ }
268
+ }
269
+ /**
270
+ * Close Redis connection
271
+ */
272
+ async close() {
273
+ try {
274
+ if (this.client && this.isConnected) {
275
+ await this.client.quit();
276
+ this.isConnected = false;
277
+ this.client = null;
278
+ }
279
+ }
280
+ catch (err) {
281
+ throw new CacheError('Failed to close Redis connection', 'REDIS_CLOSE_ERROR', 'redis', err);
282
+ }
283
+ }
284
+ }
@@ -0,0 +1 @@
1
+ export { RedisCache } from './RedisCache';
@@ -0,0 +1 @@
1
+ export { RedisCache } from './RedisCache';