@naman_deep_singh/cache 1.3.0 → 1.3.2
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.
- package/README.md +1 -1
- package/dist/cjs/adapters/memcache/MemcacheCache.d.ts +1 -1
- package/dist/cjs/adapters/memcache/MemcacheCache.js +8 -6
- package/dist/cjs/adapters/memory/MemoryCache.d.ts +1 -1
- package/dist/cjs/adapters/memory/MemoryCache.js +7 -3
- package/dist/cjs/adapters/redis/RedisCache.d.ts +1 -1
- package/dist/cjs/adapters/redis/RedisCache.js +16 -9
- package/dist/cjs/core/BaseCache.d.ts +1 -1
- package/dist/cjs/core/BaseCache.js +2 -2
- package/dist/cjs/core/factory.js +2 -2
- package/dist/cjs/core/interfaces/ICache.d.ts +1 -1
- package/dist/cjs/index.d.ts +2 -2
- package/dist/cjs/middleware/express/cacheMiddleware.d.ts +3 -3
- package/dist/cjs/middleware/express/cacheMiddleware.js +7 -4
- package/dist/cjs/middleware/express/index.d.ts +1 -1
- package/dist/cjs/session/SessionStore.js +1 -1
- package/dist/esm/adapters/memcache/MemcacheCache.d.ts +1 -1
- package/dist/esm/adapters/memcache/MemcacheCache.js +8 -6
- package/dist/esm/adapters/memory/MemoryCache.d.ts +1 -1
- package/dist/esm/adapters/memory/MemoryCache.js +7 -3
- package/dist/esm/adapters/redis/RedisCache.d.ts +1 -1
- package/dist/esm/adapters/redis/RedisCache.js +16 -9
- package/dist/esm/core/BaseCache.d.ts +1 -1
- package/dist/esm/core/BaseCache.js +2 -2
- package/dist/esm/core/factory.js +2 -2
- package/dist/esm/core/interfaces/ICache.d.ts +1 -1
- package/dist/esm/index.d.ts +2 -2
- package/dist/esm/index.js +1 -1
- package/dist/esm/middleware/express/cacheMiddleware.d.ts +3 -3
- package/dist/esm/middleware/express/cacheMiddleware.js +7 -4
- package/dist/esm/middleware/express/index.d.ts +1 -1
- package/dist/esm/middleware/express/index.js +1 -1
- package/dist/esm/session/SessionStore.js +1 -1
- package/dist/types/adapters/memcache/MemcacheCache.d.ts +1 -1
- package/dist/types/adapters/memory/MemoryCache.d.ts +1 -1
- package/dist/types/adapters/redis/RedisCache.d.ts +1 -1
- package/dist/types/core/BaseCache.d.ts +1 -1
- package/dist/types/core/interfaces/ICache.d.ts +1 -1
- package/dist/types/index.d.ts +2 -2
- package/dist/types/middleware/express/cacheMiddleware.d.ts +3 -3
- package/dist/types/middleware/express/index.d.ts +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @naman_deep_singh/cache
|
|
2
2
|
|
|
3
|
-
**Version:** 1.3.
|
|
3
|
+
**Version:** 1.3.2 (with Redis Clustering support)
|
|
4
4
|
|
|
5
5
|
A flexible, extensible caching layer with support for Redis, Memcache, and in-memory caches. Includes session management, health checks, and Express middleware.
|
|
6
6
|
|
|
@@ -31,12 +31,14 @@ class MemcacheCache extends BaseCache_1.BaseCache {
|
|
|
31
31
|
remove: true,
|
|
32
32
|
failOverServers: [],
|
|
33
33
|
maxValue: 1048576, // 1MB default
|
|
34
|
-
idle: 30000
|
|
34
|
+
idle: 30000,
|
|
35
35
|
};
|
|
36
36
|
if (this.memcacheConfig.username) {
|
|
37
|
+
;
|
|
37
38
|
options.username = this.memcacheConfig.username;
|
|
38
39
|
}
|
|
39
40
|
if (this.memcacheConfig.password) {
|
|
41
|
+
;
|
|
40
42
|
options.password = this.memcacheConfig.password;
|
|
41
43
|
}
|
|
42
44
|
this.client = new memcached_1.default(servers, options);
|
|
@@ -202,7 +204,7 @@ class MemcacheCache extends BaseCache_1.BaseCache {
|
|
|
202
204
|
async getMultiple(keys) {
|
|
203
205
|
try {
|
|
204
206
|
await this.ensureConnected();
|
|
205
|
-
const fullKeys = keys.map(k => this.buildKey(k));
|
|
207
|
+
const fullKeys = keys.map((k) => this.buildKey(k));
|
|
206
208
|
return new Promise((resolve, reject) => {
|
|
207
209
|
this.client.getMulti(fullKeys, (err, data) => {
|
|
208
210
|
if (err) {
|
|
@@ -289,9 +291,9 @@ class MemcacheCache extends BaseCache_1.BaseCache {
|
|
|
289
291
|
async deleteMultiple(keys) {
|
|
290
292
|
try {
|
|
291
293
|
await this.ensureConnected();
|
|
292
|
-
const fullKeys = keys.map(k => this.buildKey(k));
|
|
294
|
+
const fullKeys = keys.map((k) => this.buildKey(k));
|
|
293
295
|
let deletedCount = 0;
|
|
294
|
-
await Promise.all(fullKeys.map(key => new Promise((resolve, reject) => {
|
|
296
|
+
await Promise.all(fullKeys.map((key) => new Promise((resolve, reject) => {
|
|
295
297
|
this.client.del(key, (err) => {
|
|
296
298
|
if (err) {
|
|
297
299
|
reject(err);
|
|
@@ -346,7 +348,7 @@ class MemcacheCache extends BaseCache_1.BaseCache {
|
|
|
346
348
|
return {
|
|
347
349
|
isAlive: true,
|
|
348
350
|
adapter: 'memcache',
|
|
349
|
-
timestamp: new Date()
|
|
351
|
+
timestamp: new Date(),
|
|
350
352
|
};
|
|
351
353
|
}
|
|
352
354
|
catch (err) {
|
|
@@ -354,7 +356,7 @@ class MemcacheCache extends BaseCache_1.BaseCache {
|
|
|
354
356
|
isAlive: false,
|
|
355
357
|
adapter: 'memcache',
|
|
356
358
|
timestamp: new Date(),
|
|
357
|
-
error: err.message
|
|
359
|
+
error: err.message,
|
|
358
360
|
};
|
|
359
361
|
}
|
|
360
362
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { MemoryCacheConfig, HealthCheckResponse } from '../../types';
|
|
2
1
|
import { BaseCache } from '../../core/BaseCache';
|
|
2
|
+
import type { HealthCheckResponse, MemoryCacheConfig } from '../../types';
|
|
3
3
|
/**
|
|
4
4
|
* In-memory cache adapter for development and testing
|
|
5
5
|
*/
|
|
@@ -212,7 +212,9 @@ class MemoryCache extends BaseCache_1.BaseCache {
|
|
|
212
212
|
const fullKey = this.buildKey(key);
|
|
213
213
|
const entry = this.store.get(fullKey);
|
|
214
214
|
const current = entry && (!entry.expiresAt || entry.expiresAt >= Date.now())
|
|
215
|
-
?
|
|
215
|
+
? typeof entry.value === 'number'
|
|
216
|
+
? entry.value
|
|
217
|
+
: 0
|
|
216
218
|
: 0;
|
|
217
219
|
const value = current + amount;
|
|
218
220
|
const expiry = this.ttl;
|
|
@@ -232,7 +234,9 @@ class MemoryCache extends BaseCache_1.BaseCache {
|
|
|
232
234
|
const fullKey = this.buildKey(key);
|
|
233
235
|
const entry = this.store.get(fullKey);
|
|
234
236
|
const current = entry && (!entry.expiresAt || entry.expiresAt >= Date.now())
|
|
235
|
-
?
|
|
237
|
+
? typeof entry.value === 'number'
|
|
238
|
+
? entry.value
|
|
239
|
+
: 0
|
|
236
240
|
: 0;
|
|
237
241
|
const value = current - amount;
|
|
238
242
|
const expiry = this.ttl;
|
|
@@ -251,7 +255,7 @@ class MemoryCache extends BaseCache_1.BaseCache {
|
|
|
251
255
|
return {
|
|
252
256
|
isAlive: true,
|
|
253
257
|
adapter: 'memory',
|
|
254
|
-
timestamp: new Date()
|
|
258
|
+
timestamp: new Date(),
|
|
255
259
|
};
|
|
256
260
|
}
|
|
257
261
|
/**
|
|
@@ -20,7 +20,10 @@ class RedisCache extends BaseCache_1.BaseCache {
|
|
|
20
20
|
async connect() {
|
|
21
21
|
try {
|
|
22
22
|
const cluster = this.redisConfig.cluster;
|
|
23
|
-
const hasCluster = cluster &&
|
|
23
|
+
const hasCluster = cluster &&
|
|
24
|
+
(Array.isArray(cluster)
|
|
25
|
+
? cluster.length > 0
|
|
26
|
+
: cluster.nodes?.length > 0);
|
|
24
27
|
if (hasCluster && cluster) {
|
|
25
28
|
// Cluster mode
|
|
26
29
|
let nodes = [];
|
|
@@ -31,7 +34,9 @@ class RedisCache extends BaseCache_1.BaseCache {
|
|
|
31
34
|
nodes = cluster.nodes;
|
|
32
35
|
}
|
|
33
36
|
this.client = (0, redis_1.createCluster)({
|
|
34
|
-
rootNodes: nodes.map(node => ({
|
|
37
|
+
rootNodes: nodes.map((node) => ({
|
|
38
|
+
url: `redis://${node.host}:${node.port}`,
|
|
39
|
+
})),
|
|
35
40
|
});
|
|
36
41
|
}
|
|
37
42
|
else {
|
|
@@ -39,7 +44,7 @@ class RedisCache extends BaseCache_1.BaseCache {
|
|
|
39
44
|
const options = {
|
|
40
45
|
host: this.redisConfig.host ?? 'localhost',
|
|
41
46
|
port: this.redisConfig.port ?? 6379,
|
|
42
|
-
db: this.redisConfig.db ?? 0
|
|
47
|
+
db: this.redisConfig.db ?? 0,
|
|
43
48
|
};
|
|
44
49
|
if (this.redisConfig.username) {
|
|
45
50
|
options.username = this.redisConfig.username;
|
|
@@ -177,7 +182,7 @@ class RedisCache extends BaseCache_1.BaseCache {
|
|
|
177
182
|
async getMultiple(keys) {
|
|
178
183
|
try {
|
|
179
184
|
await this.ensureConnected();
|
|
180
|
-
const fullKeys = keys.map(k => this.buildKey(k));
|
|
185
|
+
const fullKeys = keys.map((k) => this.buildKey(k));
|
|
181
186
|
const values = await this.client.mGet(fullKeys);
|
|
182
187
|
const result = {};
|
|
183
188
|
keys.forEach((key, index) => {
|
|
@@ -235,7 +240,7 @@ class RedisCache extends BaseCache_1.BaseCache {
|
|
|
235
240
|
async deleteMultiple(keys) {
|
|
236
241
|
try {
|
|
237
242
|
await this.ensureConnected();
|
|
238
|
-
const fullKeys = keys.map(k => this.buildKey(k));
|
|
243
|
+
const fullKeys = keys.map((k) => this.buildKey(k));
|
|
239
244
|
const result = await this.client.del(fullKeys);
|
|
240
245
|
this.stats.deletes += result;
|
|
241
246
|
return result;
|
|
@@ -278,16 +283,18 @@ class RedisCache extends BaseCache_1.BaseCache {
|
|
|
278
283
|
await this.ensureConnected();
|
|
279
284
|
// Use sendCommand which works for both single and cluster
|
|
280
285
|
// `sendCommand` exists on both single and cluster clients in runtime; cast narrowly for the call
|
|
281
|
-
if (this.client &&
|
|
286
|
+
if (this.client &&
|
|
287
|
+
typeof this.client.sendCommand === 'function') {
|
|
282
288
|
await this.client.sendCommand(['PING']);
|
|
283
289
|
}
|
|
284
|
-
else if (this.client &&
|
|
290
|
+
else if (this.client &&
|
|
291
|
+
typeof this.client.ping === 'function') {
|
|
285
292
|
await this.client.ping();
|
|
286
293
|
}
|
|
287
294
|
return {
|
|
288
295
|
isAlive: true,
|
|
289
296
|
adapter: 'redis',
|
|
290
|
-
timestamp: new Date()
|
|
297
|
+
timestamp: new Date(),
|
|
291
298
|
};
|
|
292
299
|
}
|
|
293
300
|
catch (err) {
|
|
@@ -295,7 +302,7 @@ class RedisCache extends BaseCache_1.BaseCache {
|
|
|
295
302
|
isAlive: false,
|
|
296
303
|
adapter: 'redis',
|
|
297
304
|
timestamp: new Date(),
|
|
298
|
-
error: err.message
|
|
305
|
+
error: err.message,
|
|
299
306
|
};
|
|
300
307
|
}
|
|
301
308
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { CacheConfig, CacheStats, HealthCheckResponse
|
|
1
|
+
import type { BatchResult, CacheConfig, CacheStats, HealthCheckResponse } from '../types';
|
|
2
2
|
import type { ICache } from './interfaces';
|
|
3
3
|
/**
|
|
4
4
|
* Abstract base class for all cache adapters
|
|
@@ -12,7 +12,7 @@ class BaseCache {
|
|
|
12
12
|
hits: 0,
|
|
13
13
|
misses: 0,
|
|
14
14
|
sets: 0,
|
|
15
|
-
deletes: 0
|
|
15
|
+
deletes: 0,
|
|
16
16
|
};
|
|
17
17
|
this.namespace = config.namespace ? `${config.namespace}:` : '';
|
|
18
18
|
this.ttl = config.ttl ?? 3600; // 1 hour default
|
|
@@ -77,7 +77,7 @@ class BaseCache {
|
|
|
77
77
|
hits: 0,
|
|
78
78
|
misses: 0,
|
|
79
79
|
sets: 0,
|
|
80
|
-
deletes: 0
|
|
80
|
+
deletes: 0,
|
|
81
81
|
};
|
|
82
82
|
}
|
|
83
83
|
/**
|
package/dist/cjs/core/factory.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.CacheFactory = void 0;
|
|
4
|
-
const redis_1 = require("../adapters/redis");
|
|
5
4
|
const memcache_1 = require("../adapters/memcache");
|
|
6
5
|
const memory_1 = require("../adapters/memory");
|
|
6
|
+
const redis_1 = require("../adapters/redis");
|
|
7
7
|
const errors_1 = require("../errors");
|
|
8
8
|
/**
|
|
9
9
|
* Factory for creating cache instances
|
|
@@ -50,7 +50,7 @@ class CacheFactory {
|
|
|
50
50
|
return new memory_1.MemoryCache({
|
|
51
51
|
adapter: 'memory',
|
|
52
52
|
namespace: config.namespace,
|
|
53
|
-
ttl: config.ttl
|
|
53
|
+
ttl: config.ttl,
|
|
54
54
|
});
|
|
55
55
|
}
|
|
56
56
|
// No fallback, throw error
|
package/dist/cjs/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type { CacheConfig, RedisCacheConfig, MemcacheCacheConfig, MemoryCacheConfig, SessionData, SessionOptions, CacheStats, HealthCheckResponse, BatchResult, CacheEntry } from './types';
|
|
1
|
+
export type { CacheConfig, RedisCacheConfig, MemcacheCacheConfig, MemoryCacheConfig, SessionData, SessionOptions, CacheStats, HealthCheckResponse, BatchResult, CacheEntry, } from './types';
|
|
2
2
|
export { CacheError } from './errors';
|
|
3
3
|
export type { ICache, ISession } from './core/interfaces';
|
|
4
4
|
export { BaseCache } from './core/BaseCache';
|
|
@@ -7,4 +7,4 @@ export { MemcacheCache } from './adapters/memcache';
|
|
|
7
7
|
export { MemoryCache } from './adapters/memory';
|
|
8
8
|
export { CacheFactory } from './core/factory';
|
|
9
9
|
export { SessionStore } from './session';
|
|
10
|
-
export { cacheSessionMiddleware, cacheHealthCheckMiddleware, cacheResponseMiddleware } from './middleware/express';
|
|
10
|
+
export { cacheSessionMiddleware, cacheHealthCheckMiddleware, cacheResponseMiddleware, } from './middleware/express';
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import type { Request, Response
|
|
1
|
+
import type { NextFunction, Request, Response } from 'express';
|
|
2
2
|
import type { ICache } from '../../core/interfaces';
|
|
3
|
-
import { SessionStore } from '../../session/SessionStore';
|
|
3
|
+
import type { SessionStore } from '../../session/SessionStore';
|
|
4
4
|
/**
|
|
5
5
|
* Express middleware for session management using cache
|
|
6
6
|
*/
|
|
7
7
|
export declare function cacheSessionMiddleware(sessionStore: SessionStore, options?: {
|
|
8
8
|
sessionIdHeader?: string;
|
|
9
9
|
sessionDataKey?: string;
|
|
10
|
-
}): (req: Request,
|
|
10
|
+
}): (req: Request, _res: Response, next: NextFunction) => Promise<void>;
|
|
11
11
|
/**
|
|
12
12
|
* Express middleware for cache health check
|
|
13
13
|
*/
|
|
@@ -9,7 +9,7 @@ exports.cacheResponseMiddleware = cacheResponseMiddleware;
|
|
|
9
9
|
function cacheSessionMiddleware(sessionStore, options) {
|
|
10
10
|
const sessionIdHeader = options?.sessionIdHeader ?? 'x-session-id';
|
|
11
11
|
const sessionDataKey = options?.sessionDataKey ?? 'session';
|
|
12
|
-
return async (req,
|
|
12
|
+
return async (req, _res, next) => {
|
|
13
13
|
try {
|
|
14
14
|
// Get session ID from header or cookie
|
|
15
15
|
const sessionId = req.get(sessionIdHeader) || req.cookies?.[sessionIdHeader];
|
|
@@ -17,6 +17,7 @@ function cacheSessionMiddleware(sessionStore, options) {
|
|
|
17
17
|
// Fetch session data and extend expiry
|
|
18
18
|
const sessionData = await sessionStore.getAndExtend(sessionId);
|
|
19
19
|
if (sessionData) {
|
|
20
|
+
;
|
|
20
21
|
req[sessionDataKey] = sessionData;
|
|
21
22
|
}
|
|
22
23
|
}
|
|
@@ -44,7 +45,7 @@ function cacheHealthCheckMiddleware(cache, endpoint = '/.health/cache') {
|
|
|
44
45
|
isAlive: false,
|
|
45
46
|
adapter: 'unknown',
|
|
46
47
|
timestamp: new Date(),
|
|
47
|
-
error: err.message
|
|
48
|
+
error: err.message,
|
|
48
49
|
});
|
|
49
50
|
});
|
|
50
51
|
return;
|
|
@@ -58,7 +59,9 @@ function cacheHealthCheckMiddleware(cache, endpoint = '/.health/cache') {
|
|
|
58
59
|
function cacheResponseMiddleware(cache, options) {
|
|
59
60
|
const ttl = options?.ttl ?? 300; // 5 minutes default
|
|
60
61
|
const keyPrefix = options?.keyPrefix ?? 'response:';
|
|
61
|
-
const excludeStatusCodes = options?.excludeStatusCodes ?? [
|
|
62
|
+
const excludeStatusCodes = options?.excludeStatusCodes ?? [
|
|
63
|
+
300, 301, 302, 303, 304, 307, 308, 404, 500, 501, 502, 503,
|
|
64
|
+
];
|
|
62
65
|
return (req, res, next) => {
|
|
63
66
|
// Only cache GET requests
|
|
64
67
|
if (req.method !== 'GET') {
|
|
@@ -90,7 +93,7 @@ function cacheResponseMiddleware(cache, options) {
|
|
|
90
93
|
try {
|
|
91
94
|
responseData = JSON.stringify(data);
|
|
92
95
|
}
|
|
93
|
-
catch (
|
|
96
|
+
catch (_e) {
|
|
94
97
|
responseData = null;
|
|
95
98
|
}
|
|
96
99
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { cacheSessionMiddleware, cacheHealthCheckMiddleware, cacheResponseMiddleware } from './cacheMiddleware';
|
|
1
|
+
export { cacheSessionMiddleware, cacheHealthCheckMiddleware, cacheResponseMiddleware, } from './cacheMiddleware';
|
|
@@ -12,7 +12,7 @@ class SessionStore {
|
|
|
12
12
|
this.options = {
|
|
13
13
|
ttl: options.ttl ?? 3600, // 1 hour default
|
|
14
14
|
serialize: options.serialize ?? ((data) => JSON.stringify(data)),
|
|
15
|
-
deserialize: options.deserialize ?? ((data) => JSON.parse(data))
|
|
15
|
+
deserialize: options.deserialize ?? ((data) => JSON.parse(data)),
|
|
16
16
|
};
|
|
17
17
|
}
|
|
18
18
|
/**
|
|
@@ -25,12 +25,14 @@ export class MemcacheCache extends BaseCache {
|
|
|
25
25
|
remove: true,
|
|
26
26
|
failOverServers: [],
|
|
27
27
|
maxValue: 1048576, // 1MB default
|
|
28
|
-
idle: 30000
|
|
28
|
+
idle: 30000,
|
|
29
29
|
};
|
|
30
30
|
if (this.memcacheConfig.username) {
|
|
31
|
+
;
|
|
31
32
|
options.username = this.memcacheConfig.username;
|
|
32
33
|
}
|
|
33
34
|
if (this.memcacheConfig.password) {
|
|
35
|
+
;
|
|
34
36
|
options.password = this.memcacheConfig.password;
|
|
35
37
|
}
|
|
36
38
|
this.client = new Memcached(servers, options);
|
|
@@ -196,7 +198,7 @@ export class MemcacheCache extends BaseCache {
|
|
|
196
198
|
async getMultiple(keys) {
|
|
197
199
|
try {
|
|
198
200
|
await this.ensureConnected();
|
|
199
|
-
const fullKeys = keys.map(k => this.buildKey(k));
|
|
201
|
+
const fullKeys = keys.map((k) => this.buildKey(k));
|
|
200
202
|
return new Promise((resolve, reject) => {
|
|
201
203
|
this.client.getMulti(fullKeys, (err, data) => {
|
|
202
204
|
if (err) {
|
|
@@ -283,9 +285,9 @@ export class MemcacheCache extends BaseCache {
|
|
|
283
285
|
async deleteMultiple(keys) {
|
|
284
286
|
try {
|
|
285
287
|
await this.ensureConnected();
|
|
286
|
-
const fullKeys = keys.map(k => this.buildKey(k));
|
|
288
|
+
const fullKeys = keys.map((k) => this.buildKey(k));
|
|
287
289
|
let deletedCount = 0;
|
|
288
|
-
await Promise.all(fullKeys.map(key => new Promise((resolve, reject) => {
|
|
290
|
+
await Promise.all(fullKeys.map((key) => new Promise((resolve, reject) => {
|
|
289
291
|
this.client.del(key, (err) => {
|
|
290
292
|
if (err) {
|
|
291
293
|
reject(err);
|
|
@@ -340,7 +342,7 @@ export class MemcacheCache extends BaseCache {
|
|
|
340
342
|
return {
|
|
341
343
|
isAlive: true,
|
|
342
344
|
adapter: 'memcache',
|
|
343
|
-
timestamp: new Date()
|
|
345
|
+
timestamp: new Date(),
|
|
344
346
|
};
|
|
345
347
|
}
|
|
346
348
|
catch (err) {
|
|
@@ -348,7 +350,7 @@ export class MemcacheCache extends BaseCache {
|
|
|
348
350
|
isAlive: false,
|
|
349
351
|
adapter: 'memcache',
|
|
350
352
|
timestamp: new Date(),
|
|
351
|
-
error: err.message
|
|
353
|
+
error: err.message,
|
|
352
354
|
};
|
|
353
355
|
}
|
|
354
356
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { MemoryCacheConfig, HealthCheckResponse } from '../../types';
|
|
2
1
|
import { BaseCache } from '../../core/BaseCache';
|
|
2
|
+
import type { HealthCheckResponse, MemoryCacheConfig } from '../../types';
|
|
3
3
|
/**
|
|
4
4
|
* In-memory cache adapter for development and testing
|
|
5
5
|
*/
|
|
@@ -209,7 +209,9 @@ export class MemoryCache extends BaseCache {
|
|
|
209
209
|
const fullKey = this.buildKey(key);
|
|
210
210
|
const entry = this.store.get(fullKey);
|
|
211
211
|
const current = entry && (!entry.expiresAt || entry.expiresAt >= Date.now())
|
|
212
|
-
?
|
|
212
|
+
? typeof entry.value === 'number'
|
|
213
|
+
? entry.value
|
|
214
|
+
: 0
|
|
213
215
|
: 0;
|
|
214
216
|
const value = current + amount;
|
|
215
217
|
const expiry = this.ttl;
|
|
@@ -229,7 +231,9 @@ export class MemoryCache extends BaseCache {
|
|
|
229
231
|
const fullKey = this.buildKey(key);
|
|
230
232
|
const entry = this.store.get(fullKey);
|
|
231
233
|
const current = entry && (!entry.expiresAt || entry.expiresAt >= Date.now())
|
|
232
|
-
?
|
|
234
|
+
? typeof entry.value === 'number'
|
|
235
|
+
? entry.value
|
|
236
|
+
: 0
|
|
233
237
|
: 0;
|
|
234
238
|
const value = current - amount;
|
|
235
239
|
const expiry = this.ttl;
|
|
@@ -248,7 +252,7 @@ export class MemoryCache extends BaseCache {
|
|
|
248
252
|
return {
|
|
249
253
|
isAlive: true,
|
|
250
254
|
adapter: 'memory',
|
|
251
|
-
timestamp: new Date()
|
|
255
|
+
timestamp: new Date(),
|
|
252
256
|
};
|
|
253
257
|
}
|
|
254
258
|
/**
|
|
@@ -17,7 +17,10 @@ export class RedisCache extends BaseCache {
|
|
|
17
17
|
async connect() {
|
|
18
18
|
try {
|
|
19
19
|
const cluster = this.redisConfig.cluster;
|
|
20
|
-
const hasCluster = cluster &&
|
|
20
|
+
const hasCluster = cluster &&
|
|
21
|
+
(Array.isArray(cluster)
|
|
22
|
+
? cluster.length > 0
|
|
23
|
+
: cluster.nodes?.length > 0);
|
|
21
24
|
if (hasCluster && cluster) {
|
|
22
25
|
// Cluster mode
|
|
23
26
|
let nodes = [];
|
|
@@ -28,7 +31,9 @@ export class RedisCache extends BaseCache {
|
|
|
28
31
|
nodes = cluster.nodes;
|
|
29
32
|
}
|
|
30
33
|
this.client = createCluster({
|
|
31
|
-
rootNodes: nodes.map(node => ({
|
|
34
|
+
rootNodes: nodes.map((node) => ({
|
|
35
|
+
url: `redis://${node.host}:${node.port}`,
|
|
36
|
+
})),
|
|
32
37
|
});
|
|
33
38
|
}
|
|
34
39
|
else {
|
|
@@ -36,7 +41,7 @@ export class RedisCache extends BaseCache {
|
|
|
36
41
|
const options = {
|
|
37
42
|
host: this.redisConfig.host ?? 'localhost',
|
|
38
43
|
port: this.redisConfig.port ?? 6379,
|
|
39
|
-
db: this.redisConfig.db ?? 0
|
|
44
|
+
db: this.redisConfig.db ?? 0,
|
|
40
45
|
};
|
|
41
46
|
if (this.redisConfig.username) {
|
|
42
47
|
options.username = this.redisConfig.username;
|
|
@@ -174,7 +179,7 @@ export class RedisCache extends BaseCache {
|
|
|
174
179
|
async getMultiple(keys) {
|
|
175
180
|
try {
|
|
176
181
|
await this.ensureConnected();
|
|
177
|
-
const fullKeys = keys.map(k => this.buildKey(k));
|
|
182
|
+
const fullKeys = keys.map((k) => this.buildKey(k));
|
|
178
183
|
const values = await this.client.mGet(fullKeys);
|
|
179
184
|
const result = {};
|
|
180
185
|
keys.forEach((key, index) => {
|
|
@@ -232,7 +237,7 @@ export class RedisCache extends BaseCache {
|
|
|
232
237
|
async deleteMultiple(keys) {
|
|
233
238
|
try {
|
|
234
239
|
await this.ensureConnected();
|
|
235
|
-
const fullKeys = keys.map(k => this.buildKey(k));
|
|
240
|
+
const fullKeys = keys.map((k) => this.buildKey(k));
|
|
236
241
|
const result = await this.client.del(fullKeys);
|
|
237
242
|
this.stats.deletes += result;
|
|
238
243
|
return result;
|
|
@@ -275,16 +280,18 @@ export class RedisCache extends BaseCache {
|
|
|
275
280
|
await this.ensureConnected();
|
|
276
281
|
// Use sendCommand which works for both single and cluster
|
|
277
282
|
// `sendCommand` exists on both single and cluster clients in runtime; cast narrowly for the call
|
|
278
|
-
if (this.client &&
|
|
283
|
+
if (this.client &&
|
|
284
|
+
typeof this.client.sendCommand === 'function') {
|
|
279
285
|
await this.client.sendCommand(['PING']);
|
|
280
286
|
}
|
|
281
|
-
else if (this.client &&
|
|
287
|
+
else if (this.client &&
|
|
288
|
+
typeof this.client.ping === 'function') {
|
|
282
289
|
await this.client.ping();
|
|
283
290
|
}
|
|
284
291
|
return {
|
|
285
292
|
isAlive: true,
|
|
286
293
|
adapter: 'redis',
|
|
287
|
-
timestamp: new Date()
|
|
294
|
+
timestamp: new Date(),
|
|
288
295
|
};
|
|
289
296
|
}
|
|
290
297
|
catch (err) {
|
|
@@ -292,7 +299,7 @@ export class RedisCache extends BaseCache {
|
|
|
292
299
|
isAlive: false,
|
|
293
300
|
adapter: 'redis',
|
|
294
301
|
timestamp: new Date(),
|
|
295
|
-
error: err.message
|
|
302
|
+
error: err.message,
|
|
296
303
|
};
|
|
297
304
|
}
|
|
298
305
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { CacheConfig, CacheStats, HealthCheckResponse
|
|
1
|
+
import type { BatchResult, CacheConfig, CacheStats, HealthCheckResponse } from '../types';
|
|
2
2
|
import type { ICache } from './interfaces';
|
|
3
3
|
/**
|
|
4
4
|
* Abstract base class for all cache adapters
|
|
@@ -9,7 +9,7 @@ export class BaseCache {
|
|
|
9
9
|
hits: 0,
|
|
10
10
|
misses: 0,
|
|
11
11
|
sets: 0,
|
|
12
|
-
deletes: 0
|
|
12
|
+
deletes: 0,
|
|
13
13
|
};
|
|
14
14
|
this.namespace = config.namespace ? `${config.namespace}:` : '';
|
|
15
15
|
this.ttl = config.ttl ?? 3600; // 1 hour default
|
|
@@ -74,7 +74,7 @@ export class BaseCache {
|
|
|
74
74
|
hits: 0,
|
|
75
75
|
misses: 0,
|
|
76
76
|
sets: 0,
|
|
77
|
-
deletes: 0
|
|
77
|
+
deletes: 0,
|
|
78
78
|
};
|
|
79
79
|
}
|
|
80
80
|
/**
|
package/dist/esm/core/factory.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { RedisCache } from '../adapters/redis';
|
|
2
1
|
import { MemcacheCache } from '../adapters/memcache';
|
|
3
2
|
import { MemoryCache } from '../adapters/memory';
|
|
3
|
+
import { RedisCache } from '../adapters/redis';
|
|
4
4
|
import { CacheError } from '../errors';
|
|
5
5
|
/**
|
|
6
6
|
* Factory for creating cache instances
|
|
@@ -47,7 +47,7 @@ export class CacheFactory {
|
|
|
47
47
|
return new MemoryCache({
|
|
48
48
|
adapter: 'memory',
|
|
49
49
|
namespace: config.namespace,
|
|
50
|
-
ttl: config.ttl
|
|
50
|
+
ttl: config.ttl,
|
|
51
51
|
});
|
|
52
52
|
}
|
|
53
53
|
// No fallback, throw error
|
package/dist/esm/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type { CacheConfig, RedisCacheConfig, MemcacheCacheConfig, MemoryCacheConfig, SessionData, SessionOptions, CacheStats, HealthCheckResponse, BatchResult, CacheEntry } from './types';
|
|
1
|
+
export type { CacheConfig, RedisCacheConfig, MemcacheCacheConfig, MemoryCacheConfig, SessionData, SessionOptions, CacheStats, HealthCheckResponse, BatchResult, CacheEntry, } from './types';
|
|
2
2
|
export { CacheError } from './errors';
|
|
3
3
|
export type { ICache, ISession } from './core/interfaces';
|
|
4
4
|
export { BaseCache } from './core/BaseCache';
|
|
@@ -7,4 +7,4 @@ export { MemcacheCache } from './adapters/memcache';
|
|
|
7
7
|
export { MemoryCache } from './adapters/memory';
|
|
8
8
|
export { CacheFactory } from './core/factory';
|
|
9
9
|
export { SessionStore } from './session';
|
|
10
|
-
export { cacheSessionMiddleware, cacheHealthCheckMiddleware, cacheResponseMiddleware } from './middleware/express';
|
|
10
|
+
export { cacheSessionMiddleware, cacheHealthCheckMiddleware, cacheResponseMiddleware, } from './middleware/express';
|
package/dist/esm/index.js
CHANGED
|
@@ -11,4 +11,4 @@ export { CacheFactory } from './core/factory';
|
|
|
11
11
|
// Session
|
|
12
12
|
export { SessionStore } from './session';
|
|
13
13
|
// Middleware
|
|
14
|
-
export { cacheSessionMiddleware, cacheHealthCheckMiddleware, cacheResponseMiddleware } from './middleware/express';
|
|
14
|
+
export { cacheSessionMiddleware, cacheHealthCheckMiddleware, cacheResponseMiddleware, } from './middleware/express';
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import type { Request, Response
|
|
1
|
+
import type { NextFunction, Request, Response } from 'express';
|
|
2
2
|
import type { ICache } from '../../core/interfaces';
|
|
3
|
-
import { SessionStore } from '../../session/SessionStore';
|
|
3
|
+
import type { SessionStore } from '../../session/SessionStore';
|
|
4
4
|
/**
|
|
5
5
|
* Express middleware for session management using cache
|
|
6
6
|
*/
|
|
7
7
|
export declare function cacheSessionMiddleware(sessionStore: SessionStore, options?: {
|
|
8
8
|
sessionIdHeader?: string;
|
|
9
9
|
sessionDataKey?: string;
|
|
10
|
-
}): (req: Request,
|
|
10
|
+
}): (req: Request, _res: Response, next: NextFunction) => Promise<void>;
|
|
11
11
|
/**
|
|
12
12
|
* Express middleware for cache health check
|
|
13
13
|
*/
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
export function cacheSessionMiddleware(sessionStore, options) {
|
|
5
5
|
const sessionIdHeader = options?.sessionIdHeader ?? 'x-session-id';
|
|
6
6
|
const sessionDataKey = options?.sessionDataKey ?? 'session';
|
|
7
|
-
return async (req,
|
|
7
|
+
return async (req, _res, next) => {
|
|
8
8
|
try {
|
|
9
9
|
// Get session ID from header or cookie
|
|
10
10
|
const sessionId = req.get(sessionIdHeader) || req.cookies?.[sessionIdHeader];
|
|
@@ -12,6 +12,7 @@ export function cacheSessionMiddleware(sessionStore, options) {
|
|
|
12
12
|
// Fetch session data and extend expiry
|
|
13
13
|
const sessionData = await sessionStore.getAndExtend(sessionId);
|
|
14
14
|
if (sessionData) {
|
|
15
|
+
;
|
|
15
16
|
req[sessionDataKey] = sessionData;
|
|
16
17
|
}
|
|
17
18
|
}
|
|
@@ -39,7 +40,7 @@ export function cacheHealthCheckMiddleware(cache, endpoint = '/.health/cache') {
|
|
|
39
40
|
isAlive: false,
|
|
40
41
|
adapter: 'unknown',
|
|
41
42
|
timestamp: new Date(),
|
|
42
|
-
error: err.message
|
|
43
|
+
error: err.message,
|
|
43
44
|
});
|
|
44
45
|
});
|
|
45
46
|
return;
|
|
@@ -53,7 +54,9 @@ export function cacheHealthCheckMiddleware(cache, endpoint = '/.health/cache') {
|
|
|
53
54
|
export function cacheResponseMiddleware(cache, options) {
|
|
54
55
|
const ttl = options?.ttl ?? 300; // 5 minutes default
|
|
55
56
|
const keyPrefix = options?.keyPrefix ?? 'response:';
|
|
56
|
-
const excludeStatusCodes = options?.excludeStatusCodes ?? [
|
|
57
|
+
const excludeStatusCodes = options?.excludeStatusCodes ?? [
|
|
58
|
+
300, 301, 302, 303, 304, 307, 308, 404, 500, 501, 502, 503,
|
|
59
|
+
];
|
|
57
60
|
return (req, res, next) => {
|
|
58
61
|
// Only cache GET requests
|
|
59
62
|
if (req.method !== 'GET') {
|
|
@@ -85,7 +88,7 @@ export function cacheResponseMiddleware(cache, options) {
|
|
|
85
88
|
try {
|
|
86
89
|
responseData = JSON.stringify(data);
|
|
87
90
|
}
|
|
88
|
-
catch (
|
|
91
|
+
catch (_e) {
|
|
89
92
|
responseData = null;
|
|
90
93
|
}
|
|
91
94
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { cacheSessionMiddleware, cacheHealthCheckMiddleware, cacheResponseMiddleware } from './cacheMiddleware';
|
|
1
|
+
export { cacheSessionMiddleware, cacheHealthCheckMiddleware, cacheResponseMiddleware, } from './cacheMiddleware';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { cacheSessionMiddleware, cacheHealthCheckMiddleware, cacheResponseMiddleware } from './cacheMiddleware';
|
|
1
|
+
export { cacheSessionMiddleware, cacheHealthCheckMiddleware, cacheResponseMiddleware, } from './cacheMiddleware';
|
|
@@ -9,7 +9,7 @@ export class SessionStore {
|
|
|
9
9
|
this.options = {
|
|
10
10
|
ttl: options.ttl ?? 3600, // 1 hour default
|
|
11
11
|
serialize: options.serialize ?? ((data) => JSON.stringify(data)),
|
|
12
|
-
deserialize: options.deserialize ?? ((data) => JSON.parse(data))
|
|
12
|
+
deserialize: options.deserialize ?? ((data) => JSON.parse(data)),
|
|
13
13
|
};
|
|
14
14
|
}
|
|
15
15
|
/**
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { MemoryCacheConfig, HealthCheckResponse } from '../../types';
|
|
2
1
|
import { BaseCache } from '../../core/BaseCache';
|
|
2
|
+
import type { HealthCheckResponse, MemoryCacheConfig } from '../../types';
|
|
3
3
|
/**
|
|
4
4
|
* In-memory cache adapter for development and testing
|
|
5
5
|
*/
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { CacheConfig, CacheStats, HealthCheckResponse
|
|
1
|
+
import type { BatchResult, CacheConfig, CacheStats, HealthCheckResponse } from '../types';
|
|
2
2
|
import type { ICache } from './interfaces';
|
|
3
3
|
/**
|
|
4
4
|
* Abstract base class for all cache adapters
|
package/dist/types/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type { CacheConfig, RedisCacheConfig, MemcacheCacheConfig, MemoryCacheConfig, SessionData, SessionOptions, CacheStats, HealthCheckResponse, BatchResult, CacheEntry } from './types';
|
|
1
|
+
export type { CacheConfig, RedisCacheConfig, MemcacheCacheConfig, MemoryCacheConfig, SessionData, SessionOptions, CacheStats, HealthCheckResponse, BatchResult, CacheEntry, } from './types';
|
|
2
2
|
export { CacheError } from './errors';
|
|
3
3
|
export type { ICache, ISession } from './core/interfaces';
|
|
4
4
|
export { BaseCache } from './core/BaseCache';
|
|
@@ -7,4 +7,4 @@ export { MemcacheCache } from './adapters/memcache';
|
|
|
7
7
|
export { MemoryCache } from './adapters/memory';
|
|
8
8
|
export { CacheFactory } from './core/factory';
|
|
9
9
|
export { SessionStore } from './session';
|
|
10
|
-
export { cacheSessionMiddleware, cacheHealthCheckMiddleware, cacheResponseMiddleware } from './middleware/express';
|
|
10
|
+
export { cacheSessionMiddleware, cacheHealthCheckMiddleware, cacheResponseMiddleware, } from './middleware/express';
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import type { Request, Response
|
|
1
|
+
import type { NextFunction, Request, Response } from 'express';
|
|
2
2
|
import type { ICache } from '../../core/interfaces';
|
|
3
|
-
import { SessionStore } from '../../session/SessionStore';
|
|
3
|
+
import type { SessionStore } from '../../session/SessionStore';
|
|
4
4
|
/**
|
|
5
5
|
* Express middleware for session management using cache
|
|
6
6
|
*/
|
|
7
7
|
export declare function cacheSessionMiddleware(sessionStore: SessionStore, options?: {
|
|
8
8
|
sessionIdHeader?: string;
|
|
9
9
|
sessionDataKey?: string;
|
|
10
|
-
}): (req: Request,
|
|
10
|
+
}): (req: Request, _res: Response, next: NextFunction) => Promise<void>;
|
|
11
11
|
/**
|
|
12
12
|
* Express middleware for cache health check
|
|
13
13
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { cacheSessionMiddleware, cacheHealthCheckMiddleware, cacheResponseMiddleware } from './cacheMiddleware';
|
|
1
|
+
export { cacheSessionMiddleware, cacheHealthCheckMiddleware, cacheResponseMiddleware, } from './cacheMiddleware';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@naman_deep_singh/cache",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.2",
|
|
4
4
|
"description": "Extensible caching layer supporting Redis, Memcache, and in-memory caches with automatic fallback, namespacing, session management, and Express middleware.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/cjs/index.js",
|