@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
package/README.md ADDED
@@ -0,0 +1,637 @@
1
+ # @naman_deep_singh/cache
2
+
3
+ A flexible, extensible caching layer with support for Redis, Memcache, and in-memory caches. Includes session management, health checks, and Express middleware.
4
+
5
+ ## Features
6
+
7
+ - 🚀 **Multiple Adapters**: Redis, Memcache, and in-memory cache support
8
+ - 🔄 **Automatic Fallback**: Gracefully fall back to in-memory cache if primary adapter fails
9
+ - 📦 **Namespacing**: Organize cache keys with optional prefixes to prevent collisions
10
+ - 🎯 **Generic Types**: Full TypeScript support with generics for type-safe caching
11
+ - 📊 **Statistics**: Track cache hits, misses, sets, and deletes
12
+ - 💾 **Session Management**: Built-in SessionStore wrapper for session handling
13
+ - 🌐 **Express Middleware**: Pre-built middleware for session management and response caching
14
+ - ⚡ **Async/Await**: Modern async API throughout
15
+ - 🔌 **Production Ready**: Error handling, health checks, and connection management
16
+
17
+ ## Installation
18
+
19
+ ```bash
20
+ npm install @naman_deep_singh/cache redis memcached
21
+ ```
22
+
23
+ ### Peer Dependencies
24
+
25
+ - `redis` (for Redis adapter)
26
+ - `memcached` (for Memcache adapter)
27
+
28
+ Both are optional if you're only using the memory adapter.
29
+
30
+ ## Quick Start
31
+
32
+ ### Using the Factory
33
+
34
+ ```typescript
35
+ import { CacheFactory, SessionStore } from '@naman_deep_singh/cache';
36
+
37
+ // Create a Redis cache
38
+ const cache = CacheFactory.create({
39
+ adapter: 'redis',
40
+ host: 'localhost',
41
+ port: 6379,
42
+ namespace: 'myapp',
43
+ ttl: 3600
44
+ });
45
+
46
+ // Or with fallback support
47
+ const cacheWithFallback = await CacheFactory.createWithFallback({
48
+ adapter: 'redis',
49
+ host: 'localhost',
50
+ port: 6379,
51
+ fallback: true // Falls back to memory cache if Redis fails
52
+ });
53
+ ```
54
+
55
+ ### Basic Cache Operations
56
+
57
+ All adapters (Redis, Memcache, Memory) implement the same `ICache<T>` interface and work identically:
58
+
59
+ ```typescript
60
+ // Set a value (with TTL in seconds)
61
+ await cache.set('user:123', { id: 123, name: 'John' }, 3600); // 1 hour
62
+
63
+ // Get a value
64
+ const user = await cache.get('user:123');
65
+ console.log(user); // { id: 123, name: 'John' } or null if not found
66
+
67
+ // Check existence
68
+ const exists = await cache.exists('user:123'); // true or false
69
+
70
+ // Delete a value
71
+ const deleted = await cache.delete('user:123'); // true if existed, false otherwise
72
+
73
+ // Clear all cache (respects namespace)
74
+ await cache.clear();
75
+
76
+ // Increment/Decrement (for numeric values)
77
+ await cache.set('visits', 0);
78
+ const visits = await cache.increment('visits'); // 1
79
+ const decremented = await cache.decrement('visits'); // 0
80
+ await cache.increment('visits', 5); // increment by 5 -> 5
81
+ await cache.decrement('counter', 2); // decrement by 2
82
+
83
+ // Batch get operations
84
+ const users = await cache.getMultiple(['user:1', 'user:2', 'user:3']);
85
+ // Returns: { 'user:1': userData1, 'user:2': null, 'user:3': userData3 }
86
+
87
+ // Batch set operations
88
+ await cache.setMultiple({
89
+ 'user:1': user1,
90
+ 'user:2': user2,
91
+ 'user:3': user3
92
+ }, 3600); // All with same TTL
93
+
94
+ // Batch delete operations
95
+ const deletedCount = await cache.deleteMultiple(['user:1', 'user:2', 'user:3']);
96
+ console.log(`Deleted ${deletedCount} keys`);
97
+
98
+ // Get cache statistics
99
+ const stats = await cache.getStats();
100
+ console.log(`Cache hits: ${stats.hits}`);
101
+ console.log(`Cache misses: ${stats.misses}`);
102
+ console.log(`Total sets: ${stats.sets}`);
103
+ console.log(`Total deletes: ${stats.deletes}`);
104
+
105
+ // Health check (verify connection)
106
+ const health = await cache.isAlive();
107
+ console.log(`Cache status:`, health);
108
+ // { isAlive: true, adapter: 'redis', timestamp: Date, error?: undefined }
109
+
110
+ // Close connection (cleanup)
111
+ await cache.close();
112
+ ```
113
+
114
+ ## Session Management
115
+
116
+ SessionStore provides a convenient wrapper around any cache adapter for session handling.
117
+
118
+ ```typescript
119
+ import { CacheFactory, SessionStore } from '@naman_deep_singh/cache';
120
+
121
+ // Create cache (any adapter works the same way)
122
+ const cache = CacheFactory.create({
123
+ adapter: 'redis', // or 'memcache' or 'memory'
124
+ host: 'localhost',
125
+ port: 6379,
126
+ namespace: 'sessions'
127
+ });
128
+
129
+ // Initialize session store
130
+ const sessionStore = new SessionStore(cache, {
131
+ ttl: 86400, // 24 hours default
132
+ serialize: (data) => JSON.stringify(data),
133
+ deserialize: (data) => JSON.parse(data)
134
+ });
135
+
136
+ // Create a new session
137
+ await sessionStore.create('session:abc123', {
138
+ userId: 123,
139
+ username: 'john',
140
+ roles: ['admin'],
141
+ permissions: ['read', 'write']
142
+ });
143
+
144
+ // Retrieve session data
145
+ const session = await sessionStore.get('session:abc123');
146
+ console.log(session); // { userId: 123, username: 'john', ... }
147
+
148
+ // Check if session exists
149
+ const sessionExists = await sessionStore.exists('session:abc123'); // true
150
+
151
+ // Update/merge session data
152
+ await sessionStore.update('session:abc123', {
153
+ lastActivity: new Date(),
154
+ permissions: ['read', 'write', 'delete']
155
+ });
156
+
157
+ // Extend session expiry (keep user logged in)
158
+ await sessionStore.extend('session:abc123', 86400); // 24 more hours
159
+
160
+ // Get session and extend in one operation (useful for every request)
161
+ const sessionData = await sessionStore.getAndExtend('session:abc123');
162
+
163
+ // Get multiple sessions
164
+ const sessions = await sessionStore.getMultiple([
165
+ 'session:user1',
166
+ 'session:user2',
167
+ 'session:user3'
168
+ ]);
169
+
170
+ // Delete a single session (logout)
171
+ const deleted = await sessionStore.delete('session:abc123'); // true if existed
172
+
173
+ // Delete multiple sessions
174
+ const deletedCount = await sessionStore.deleteMultiple([
175
+ 'session:user1',
176
+ 'session:user2'
177
+ ]);
178
+
179
+ // Clear all sessions (e.g., on server maintenance)
180
+ await sessionStore.clear();
181
+ ```
182
+
183
+ ## Adapters
184
+
185
+ All adapters implement the same `ICache<T>` interface and can be used interchangeably. Switching between adapters requires only changing the configuration!
186
+
187
+ ### Redis Cache
188
+
189
+ ```typescript
190
+ import { RedisCache } from '@naman_deep_singh/cache';
191
+
192
+ const cache = new RedisCache({
193
+ adapter: 'redis',
194
+ host: 'localhost',
195
+ port: 6379,
196
+ username: 'default', // Optional, for auth
197
+ password: 'your_password', // Optional
198
+ db: 0, // Optional, database number (0-15)
199
+ tls: false, // Optional, enable TLS/SSL
200
+ namespace: 'myapp', // Optional, key prefix
201
+ ttl: 3600 // Default TTL in seconds
202
+ });
203
+
204
+ // All ICache methods available
205
+ await cache.set('key', value);
206
+ await cache.get('key');
207
+ await cache.delete('key');
208
+ // ... and all other methods
209
+ ```
210
+
211
+ ### Memcache Adapter
212
+
213
+ ```typescript
214
+ import { MemcacheCache } from '@naman_deep_singh/cache';
215
+
216
+ const cache = new MemcacheCache({
217
+ adapter: 'memcache',
218
+ servers: 'localhost:11211', // Single server as string
219
+ // OR
220
+ // servers: ['localhost:11211', 'localhost:11212'], // Multiple servers
221
+ username: 'user', // Optional
222
+ password: 'pass', // Optional
223
+ namespace: 'myapp', // Optional, key prefix
224
+ ttl: 3600 // Default TTL in seconds
225
+ });
226
+
227
+ // Same ICache interface as Redis
228
+ await cache.set('key', value);
229
+ await cache.get('key');
230
+ await cache.delete('key');
231
+ // ... and all other methods
232
+ ```
233
+
234
+ ### Memory Cache (For Development/Testing)
235
+
236
+ ```typescript
237
+ import { MemoryCache } from '@naman_deep_singh/cache';
238
+
239
+ const cache = new MemoryCache({
240
+ adapter: 'memory',
241
+ namespace: 'myapp', // Optional, key prefix
242
+ ttl: 3600, // Default TTL in seconds
243
+ maxSize: 1000 // Optional, max items (oldest removed when exceeded)
244
+ });
245
+
246
+ // Same ICache interface - perfect for testing without external dependencies
247
+ await cache.set('key', value);
248
+ await cache.get('key');
249
+ await cache.delete('key');
250
+ // ... and all other methods
251
+
252
+ // Note: Memory cache automatically cleans up expired items every 30 seconds
253
+ ```
254
+
255
+ ### Using Adapters Interchangeably
256
+
257
+ ```typescript
258
+ // Development: use memory cache
259
+ let cache: ICache;
260
+ if (process.env.NODE_ENV === 'development') {
261
+ cache = new MemoryCache({ adapter: 'memory' });
262
+ } else if (process.env.REDIS_URL) {
263
+ cache = new RedisCache({ adapter: 'redis', host: 'localhost' });
264
+ } else {
265
+ cache = new MemcacheCache({ adapter: 'memcache', servers: 'localhost:11211' });
266
+ }
267
+
268
+ // All subsequent code works the same regardless of adapter
269
+ await cache.set('user:1', userData);
270
+ const user = await cache.get('user:1');
271
+ const health = await cache.isAlive();
272
+ ```
273
+
274
+ ## Express Middleware
275
+
276
+ ### Session Management Middleware
277
+
278
+ ```typescript
279
+ import express from 'express';
280
+ import cookieParser from 'cookie-parser';
281
+ import { CacheFactory, SessionStore, cacheSessionMiddleware } from '@naman_deep_singh/cache';
282
+
283
+ const app = express();
284
+ app.use(cookieParser());
285
+
286
+ const cache = CacheFactory.create({
287
+ adapter: 'redis',
288
+ host: 'localhost',
289
+ port: 6379,
290
+ namespace: 'sessions'
291
+ });
292
+
293
+ const sessionStore = new SessionStore(cache);
294
+
295
+ app.use(
296
+ cacheSessionMiddleware(sessionStore, {
297
+ sessionIdHeader: 'x-session-id', // Or use cookie
298
+ sessionDataKey: 'session' // req.session
299
+ })
300
+ );
301
+
302
+ app.get('/profile', (req, res) => {
303
+ const session = (req as any).session;
304
+ if (!session) {
305
+ return res.status(401).json({ error: 'No session' });
306
+ }
307
+ res.json({ user: session });
308
+ });
309
+ ```
310
+
311
+ ### Cache Health Check Middleware
312
+
313
+ Expose cache health status at a dedicated endpoint:
314
+
315
+ ```typescript
316
+ import { CacheFactory, cacheHealthCheckMiddleware } from '@naman_deep_singh/cache';
317
+
318
+ const cache = CacheFactory.create({
319
+ adapter: 'redis',
320
+ host: 'localhost'
321
+ });
322
+
323
+ // Add middleware
324
+ app.use(cacheHealthCheckMiddleware(cache, '/.health/cache'));
325
+
326
+ // Usage:
327
+ // GET /.health/cache
328
+ // Response:
329
+ // {
330
+ // "isAlive": true,
331
+ // "adapter": "redis",
332
+ // "timestamp": "2024-01-01T12:00:00.000Z"
333
+ // }
334
+ ```
335
+
336
+ ### Response Caching Middleware
337
+
338
+ Automatically cache HTTP responses for GET requests:
339
+
340
+ ```typescript
341
+ import { CacheFactory, cacheResponseMiddleware } from '@naman_deep_singh/cache';
342
+
343
+ const cache = CacheFactory.create({
344
+ adapter: 'redis',
345
+ host: 'localhost'
346
+ });
347
+
348
+ // Add middleware
349
+ app.use(
350
+ cacheResponseMiddleware(cache, {
351
+ ttl: 300, // Cache for 5 minutes
352
+ keyPrefix: 'response:', // All keys start with this
353
+ excludeStatusCodes: [404, 500, 502, 503] // Don't cache errors
354
+ })
355
+ );
356
+
357
+ // Usage in routes
358
+ app.get('/api/users', (req, res) => {
359
+ // First request: fetches from database, caches response
360
+ // Subsequent requests: returns from cache
361
+ res.json({ users: [...] });
362
+ // Response headers will include X-Cache: HIT or MISS
363
+ });
364
+
365
+ app.get('/api/data', async (req, res) => {
366
+ // Expensive operation
367
+ const data = await expensiveQuery();
368
+ res.json(data);
369
+ // X-Cache: MISS (first time)
370
+ // X-Cache: HIT (subsequent requests within 5 minutes)
371
+ });
372
+
373
+ // Client can check cache status
374
+ app.get('/api/stats', (req, res) => {
375
+ // Not cached (responses with statusCode >= 300)
376
+ res.status(201).json({ created: true });
377
+ // X-Cache: MISS
378
+ });
379
+ ```
380
+
381
+ ## Error Handling
382
+
383
+ ```typescript
384
+ import { CacheError } from '@naman_deep_singh/cache';
385
+
386
+ try {
387
+ await cache.get('key');
388
+ } catch (err) {
389
+ if (err instanceof CacheError) {
390
+ console.log(`Error: ${err.message}`);
391
+ console.log(`Code: ${err.code}`);
392
+ console.log(`Adapter: ${err.adapter}`);
393
+ console.log(`Original error:`, err.originalError);
394
+ }
395
+ }
396
+
397
+ // Error codes:
398
+ // - CACHE_ERROR: Generic cache error
399
+ // - REDIS_CONNECTION_ERROR: Failed to connect to Redis
400
+ // - REDIS_GET_ERROR, REDIS_SET_ERROR, etc.
401
+ // - MEMCACHE_CONNECTION_ERROR: Failed to connect to Memcache
402
+ // - MEMCACHE_GET_ERROR, MEMCACHE_SET_ERROR, etc.
403
+ // - MEMORY_GET_ERROR, MEMORY_SET_ERROR, etc.
404
+ // - SESSION_NOT_FOUND: Session doesn't exist
405
+ // - SESSION_CREATE_ERROR, SESSION_UPDATE_ERROR, etc.
406
+ ```
407
+
408
+ ## Complete API Reference
409
+
410
+ ### ICache<T> Interface
411
+
412
+ Every adapter implements this interface:
413
+
414
+ ```typescript
415
+ interface ICache<T = unknown> {
416
+ // Single item operations
417
+ get(key: string): Promise<T | null>;
418
+ set(key: string, value: T, ttl?: number): Promise<void>;
419
+ delete(key: string): Promise<boolean>;
420
+ exists(key: string): Promise<boolean>;
421
+
422
+ // Batch operations
423
+ getMultiple(keys: string[]): Promise<Record<string, T | null>>;
424
+ setMultiple(data: Record<string, T>, ttl?: number): Promise<void>;
425
+ deleteMultiple(keys: string[]): Promise<number>;
426
+
427
+ // Numeric operations
428
+ increment(key: string, amount?: number): Promise<number>;
429
+ decrement(key: string, amount?: number): Promise<number>;
430
+
431
+ // Utility operations
432
+ clear(): Promise<void>;
433
+ getStats?(): Promise<CacheStats>;
434
+ isAlive(): Promise<HealthCheckResponse>;
435
+ close(): Promise<void>;
436
+ }
437
+ ```
438
+
439
+ ### CacheFactory
440
+
441
+ ```typescript
442
+ // Create a cache instance
443
+ const cache = CacheFactory.create({
444
+ adapter: 'redis' | 'memcache' | 'memory',
445
+ // ... adapter-specific config
446
+ });
447
+
448
+ // Create with automatic fallback to memory cache
449
+ const cacheWithFallback = await CacheFactory.createWithFallback({
450
+ adapter: 'redis',
451
+ // ... config
452
+ fallback: true // Falls back to memory if primary fails
453
+ });
454
+ ```
455
+
456
+ ### SessionStore
457
+
458
+ ```typescript
459
+ const sessionStore = new SessionStore(cache, {
460
+ ttl: 3600,
461
+ serialize: (data) => JSON.stringify(data),
462
+ deserialize: (data) => JSON.parse(data)
463
+ });
464
+
465
+ // Methods
466
+ await sessionStore.create(sessionId, data, ttl?);
467
+ await sessionStore.get(sessionId);
468
+ await sessionStore.update(sessionId, partialData);
469
+ await sessionStore.delete(sessionId);
470
+ await sessionStore.exists(sessionId);
471
+ await sessionStore.extend(sessionId, ttl?);
472
+ await sessionStore.getAndExtend(sessionId, ttl?);
473
+ await sessionStore.getMultiple(sessionIds);
474
+ await sessionStore.deleteMultiple(sessionIds);
475
+ await sessionStore.clear();
476
+ ```
477
+
478
+ ## Configuration Examples
479
+
480
+ ### Development
481
+
482
+ ```typescript
483
+ const cache = CacheFactory.create({
484
+ adapter: 'memory',
485
+ namespace: 'dev',
486
+ ttl: 600
487
+ });
488
+ ```
489
+
490
+ ### Production with Fallback
491
+
492
+ ```typescript
493
+ const cache = await CacheFactory.createWithFallback({
494
+ adapter: 'redis',
495
+ host: process.env.REDIS_HOST,
496
+ port: parseInt(process.env.REDIS_PORT),
497
+ password: process.env.REDIS_PASSWORD,
498
+ db: 0,
499
+ namespace: 'prod',
500
+ ttl: 3600,
501
+ fallback: true
502
+ });
503
+ ```
504
+
505
+ ### Multi-Tenant with Namespacing
506
+
507
+ ```typescript
508
+ const getTenantCache = (tenantId: string) => {
509
+ return CacheFactory.create({
510
+ adapter: 'redis',
511
+ host: 'localhost',
512
+ namespace: `tenant:${tenantId}`,
513
+ ttl: 3600
514
+ });
515
+ };
516
+
517
+ const tenant1Cache = getTenantCache('tenant-1');
518
+ const tenant2Cache = getTenantCache('tenant-2');
519
+
520
+ // Keys are isolated: tenant-1:key vs tenant-2:key
521
+ ```
522
+
523
+ ## Connecting and Disconnecting
524
+
525
+ ### Redis
526
+
527
+ ```typescript
528
+ const cache = new RedisCache({
529
+ adapter: 'redis',
530
+ host: 'localhost'
531
+ });
532
+
533
+ // Automatically connects on first use or explicitly:
534
+ // await (cache as any).connect();
535
+
536
+ // Close when done
537
+ await cache.close();
538
+ ```
539
+
540
+ ### Memcache
541
+
542
+ ```typescript
543
+ const cache = new MemcacheCache({
544
+ adapter: 'memcache',
545
+ servers: ['localhost:11211']
546
+ });
547
+
548
+ // Automatically connects
549
+ // Close when done
550
+ await cache.close();
551
+ ```
552
+
553
+ ## Adapter Comparison
554
+
555
+ All adapters implement the same `ICache<T>` interface and work identically. Choose based on your needs:
556
+
557
+ | Feature | Redis | Memcache | Memory |
558
+ |---------|-------|----------|--------|
559
+ | **Type** | External service | External service | In-process |
560
+ | **Setup** | Requires Redis server | Requires Memcache server | No setup needed |
561
+ | **Persistence** | Optional (configurable) | No persistence | Lost on restart |
562
+ | **Scalability** | Excellent (supports millions) | Good (scalable across servers) | Limited to RAM |
563
+ | **Best For** | Production (distributed systems) | High-traffic scenarios | Development & testing |
564
+ | **Cost** | Free (open source) | Free (open source) | Free |
565
+ | **Performance** | Fast | Very Fast | Fastest (in-memory) |
566
+ | **Cluster Support** | Yes (v2 planned) | Yes | N/A |
567
+ | **Authentication** | Username/Password/TLS | Optional | N/A |
568
+
569
+ ### When to Use Each
570
+
571
+ ```typescript
572
+ // Development: quick setup, no dependencies
573
+ const devCache = new MemoryCache({ adapter: 'memory' });
574
+
575
+ // Testing: mock external services
576
+ const testCache = new MemoryCache({ adapter: 'memory' });
577
+
578
+ // Production: single server, high performance
579
+ const prodCache = new RedisCache({
580
+ adapter: 'redis',
581
+ host: process.env.REDIS_HOST,
582
+ password: process.env.REDIS_PASSWORD
583
+ });
584
+
585
+ // High-traffic distributed system
586
+ const distributedCache = new RedisCache({
587
+ adapter: 'redis',
588
+ host: process.env.REDIS_CLUSTER_ENDPOINT
589
+ });
590
+
591
+ // Legacy system with Memcache
592
+ const legacyCache = new MemcacheCache({
593
+ adapter: 'memcache',
594
+ servers: ['memcache1:11211', 'memcache2:11211']
595
+ });
596
+ ```
597
+
598
+ ## Best Practices
599
+
600
+ 1. **Use Namespacing**: Always use namespaces in multi-tenant or complex applications to prevent key collisions.
601
+
602
+ 2. **Set Appropriate TTLs**: Balance cache size and data freshness.
603
+
604
+ 3. **Handle Cache Failures**: Use try-catch or fallback options to handle cache adapter failures gracefully.
605
+
606
+ 4. **Monitor Cache Health**: Use `isAlive()` in health check endpoints.
607
+
608
+ 5. **Clean Up Resources**: Always call `close()` when shutting down.
609
+
610
+ 6. **Use Batch Operations**: For multiple operations, prefer `getMultiple` and `setMultiple` over loops.
611
+
612
+ 7. **Session Security**: Use secure headers/cookies for session IDs in production.
613
+
614
+ 8. **Error Logging**: Log `CacheError` instances with their codes for debugging.
615
+
616
+ ## Types
617
+
618
+ See [types.ts](./src/types.ts) for detailed type definitions:
619
+
620
+ - `CacheConfig` - Cache configuration
621
+ - `RedisCacheConfig` - Redis-specific config
622
+ - `MemcacheCacheConfig` - Memcache-specific config
623
+ - `MemoryCacheConfig` - Memory cache config
624
+ - `SessionData` - Session data structure
625
+ - `SessionOptions` - Session store options
626
+ - `CacheStats` - Cache statistics
627
+ - `HealthCheckResponse` - Health check response
628
+ - `ICache<T>` - Cache interface
629
+ - `ISession` - Session interface
630
+
631
+ ## License
632
+
633
+ ISC
634
+
635
+ ## Author
636
+
637
+ Naman Deep Singh
@@ -0,0 +1,71 @@
1
+ import type { MemcacheCacheConfig, HealthCheckResponse } from '../../types';
2
+ import { BaseCache } from '../../core/BaseCache';
3
+ /**
4
+ * Memcache adapter
5
+ */
6
+ export declare class MemcacheCache<T = unknown> extends BaseCache<T> {
7
+ private memcacheConfig;
8
+ private client;
9
+ private isConnected;
10
+ constructor(memcacheConfig: MemcacheCacheConfig);
11
+ /**
12
+ * Connect to Memcache
13
+ */
14
+ connect(): Promise<void>;
15
+ /**
16
+ * Ensure client is connected
17
+ */
18
+ private ensureConnected;
19
+ /**
20
+ * Ping memcache
21
+ */
22
+ private ping;
23
+ /**
24
+ * Get a value from Memcache
25
+ */
26
+ get(key: string): Promise<T | null>;
27
+ /**
28
+ * Set a value in Memcache
29
+ */
30
+ set(key: string, value: T, ttl?: number): Promise<void>;
31
+ /**
32
+ * Delete a key from Memcache
33
+ */
34
+ delete(key: string): Promise<boolean>;
35
+ /**
36
+ * Check if key exists
37
+ */
38
+ exists(key: string): Promise<boolean>;
39
+ /**
40
+ * Clear all keys (Memcache limitation: flushes entire cache)
41
+ */
42
+ clear(): Promise<void>;
43
+ /**
44
+ * Get multiple values at once
45
+ */
46
+ getMultiple(keys: string[]): Promise<Record<string, T | null>>;
47
+ /**
48
+ * Set multiple values at once
49
+ */
50
+ setMultiple(data: Record<string, T>, ttl?: number): Promise<void>;
51
+ /**
52
+ * Delete multiple keys at once
53
+ */
54
+ deleteMultiple(keys: string[]): Promise<number>;
55
+ /**
56
+ * Increment a numeric value (not natively supported by Memcache in this library)
57
+ */
58
+ increment(key: string, amount?: number): Promise<number>;
59
+ /**
60
+ * Decrement a numeric value
61
+ */
62
+ decrement(key: string, amount?: number): Promise<number>;
63
+ /**
64
+ * Check if Memcache is alive
65
+ */
66
+ isAlive(): Promise<HealthCheckResponse>;
67
+ /**
68
+ * Close Memcache connection
69
+ */
70
+ close(): Promise<void>;
71
+ }