@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.
- package/README.md +637 -0
- package/dist/cjs/adapters/memcache/MemcacheCache.d.ts +71 -0
- package/dist/cjs/adapters/memcache/MemcacheCache.js +347 -0
- package/dist/cjs/adapters/memcache/index.d.ts +1 -0
- package/dist/cjs/adapters/memcache/index.js +5 -0
- package/dist/cjs/adapters/memory/MemoryCache.d.ts +63 -0
- package/dist/cjs/adapters/memory/MemoryCache.js +273 -0
- package/dist/cjs/adapters/memory/index.d.ts +1 -0
- package/dist/cjs/adapters/memory/index.js +5 -0
- package/dist/cjs/adapters/redis/RedisCache.d.ts +67 -0
- package/dist/cjs/adapters/redis/RedisCache.js +288 -0
- package/dist/cjs/adapters/redis/index.d.ts +1 -0
- package/dist/cjs/adapters/redis/index.js +5 -0
- package/dist/cjs/core/BaseCache.d.ts +78 -0
- package/dist/cjs/core/BaseCache.js +138 -0
- package/dist/cjs/core/factory.d.ts +16 -0
- package/dist/cjs/core/factory.js +51 -0
- package/dist/cjs/core/interfaces/ICache.d.ts +58 -0
- package/dist/cjs/core/interfaces/ICache.js +2 -0
- package/dist/cjs/core/interfaces/ISession.d.ts +30 -0
- package/dist/cjs/core/interfaces/ISession.js +2 -0
- package/dist/cjs/core/interfaces/index.d.ts +2 -0
- package/dist/cjs/core/interfaces/index.js +2 -0
- package/dist/cjs/errors/CacheError.d.ts +9 -0
- package/dist/cjs/errors/CacheError.js +17 -0
- package/dist/cjs/errors/index.d.ts +1 -0
- package/dist/cjs/errors/index.js +5 -0
- package/dist/cjs/index.d.ts +10 -0
- package/dist/cjs/index.js +27 -0
- package/dist/cjs/middleware/express/cacheMiddleware.d.ts +22 -0
- package/dist/cjs/middleware/express/cacheMiddleware.js +100 -0
- package/dist/cjs/middleware/express/index.d.ts +1 -0
- package/dist/cjs/middleware/express/index.js +7 -0
- package/dist/cjs/session/SessionStore.d.ts +51 -0
- package/dist/cjs/session/SessionStore.js +153 -0
- package/dist/cjs/session/index.d.ts +2 -0
- package/dist/cjs/session/index.js +5 -0
- package/dist/cjs/types.d.ts +83 -0
- package/dist/cjs/types.js +2 -0
- package/dist/esm/adapters/memcache/MemcacheCache.d.ts +71 -0
- package/dist/esm/adapters/memcache/MemcacheCache.js +340 -0
- package/dist/esm/adapters/memcache/index.d.ts +1 -0
- package/dist/esm/adapters/memcache/index.js +1 -0
- package/dist/esm/adapters/memory/MemoryCache.d.ts +63 -0
- package/dist/esm/adapters/memory/MemoryCache.js +269 -0
- package/dist/esm/adapters/memory/index.d.ts +1 -0
- package/dist/esm/adapters/memory/index.js +1 -0
- package/dist/esm/adapters/redis/RedisCache.d.ts +67 -0
- package/dist/esm/adapters/redis/RedisCache.js +284 -0
- package/dist/esm/adapters/redis/index.d.ts +1 -0
- package/dist/esm/adapters/redis/index.js +1 -0
- package/dist/esm/core/BaseCache.d.ts +78 -0
- package/dist/esm/core/BaseCache.js +134 -0
- package/dist/esm/core/factory.d.ts +16 -0
- package/dist/esm/core/factory.js +47 -0
- package/dist/esm/core/interfaces/ICache.d.ts +58 -0
- package/dist/esm/core/interfaces/ICache.js +1 -0
- package/dist/esm/core/interfaces/ISession.d.ts +30 -0
- package/dist/esm/core/interfaces/ISession.js +1 -0
- package/dist/esm/core/interfaces/index.d.ts +2 -0
- package/dist/esm/core/interfaces/index.js +1 -0
- package/dist/esm/errors/CacheError.d.ts +9 -0
- package/dist/esm/errors/CacheError.js +13 -0
- package/dist/esm/errors/index.d.ts +1 -0
- package/dist/esm/errors/index.js +1 -0
- package/dist/esm/index.d.ts +10 -0
- package/dist/esm/index.js +14 -0
- package/dist/esm/middleware/express/cacheMiddleware.d.ts +22 -0
- package/dist/esm/middleware/express/cacheMiddleware.js +95 -0
- package/dist/esm/middleware/express/index.d.ts +1 -0
- package/dist/esm/middleware/express/index.js +1 -0
- package/dist/esm/session/SessionStore.d.ts +51 -0
- package/dist/esm/session/SessionStore.js +149 -0
- package/dist/esm/session/index.d.ts +2 -0
- package/dist/esm/session/index.js +1 -0
- package/dist/esm/types.d.ts +83 -0
- package/dist/esm/types.js +1 -0
- package/dist/types/adapters/memcache/MemcacheCache.d.ts +71 -0
- package/dist/types/adapters/memcache/index.d.ts +1 -0
- package/dist/types/adapters/memory/MemoryCache.d.ts +63 -0
- package/dist/types/adapters/memory/index.d.ts +1 -0
- package/dist/types/adapters/redis/RedisCache.d.ts +67 -0
- package/dist/types/adapters/redis/index.d.ts +1 -0
- package/dist/types/core/BaseCache.d.ts +78 -0
- package/dist/types/core/factory.d.ts +16 -0
- package/dist/types/core/interfaces/ICache.d.ts +58 -0
- package/dist/types/core/interfaces/ISession.d.ts +30 -0
- package/dist/types/core/interfaces/index.d.ts +2 -0
- package/dist/types/errors/CacheError.d.ts +9 -0
- package/dist/types/errors/index.d.ts +1 -0
- package/dist/types/index.d.ts +10 -0
- package/dist/types/middleware/express/cacheMiddleware.d.ts +22 -0
- package/dist/types/middleware/express/index.d.ts +1 -0
- package/dist/types/session/SessionStore.d.ts +51 -0
- package/dist/types/session/index.d.ts +2 -0
- package/dist/types/types.d.ts +83 -0
- package/package.json +48 -0
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import type { CacheConfig, CacheStats, HealthCheckResponse, BatchResult } from '../types';
|
|
2
|
+
import type { ICache } from './interfaces';
|
|
3
|
+
/**
|
|
4
|
+
* Abstract base class for all cache adapters
|
|
5
|
+
*/
|
|
6
|
+
export declare abstract class BaseCache<T = unknown> implements ICache<T> {
|
|
7
|
+
protected config: CacheConfig;
|
|
8
|
+
protected readonly namespace: string;
|
|
9
|
+
protected readonly ttl: number;
|
|
10
|
+
protected stats: CacheStats;
|
|
11
|
+
constructor(config: CacheConfig);
|
|
12
|
+
/**
|
|
13
|
+
* Build full key with namespace prefix
|
|
14
|
+
*/
|
|
15
|
+
protected buildKey(key: string): string;
|
|
16
|
+
/**
|
|
17
|
+
* Deserialize string to object
|
|
18
|
+
*/
|
|
19
|
+
protected deserialize(data: string): T;
|
|
20
|
+
/**
|
|
21
|
+
* Serialize object to string
|
|
22
|
+
*/
|
|
23
|
+
protected serialize(value: T): string;
|
|
24
|
+
/**
|
|
25
|
+
* Track cache hit
|
|
26
|
+
*/
|
|
27
|
+
protected recordHit(): void;
|
|
28
|
+
/**
|
|
29
|
+
* Track cache miss
|
|
30
|
+
*/
|
|
31
|
+
protected recordMiss(): void;
|
|
32
|
+
/**
|
|
33
|
+
* Track cache set
|
|
34
|
+
*/
|
|
35
|
+
protected recordSet(): void;
|
|
36
|
+
/**
|
|
37
|
+
* Track cache delete
|
|
38
|
+
*/
|
|
39
|
+
protected recordDelete(): void;
|
|
40
|
+
/**
|
|
41
|
+
* Reset statistics
|
|
42
|
+
*/
|
|
43
|
+
protected resetStats(): void;
|
|
44
|
+
/**
|
|
45
|
+
* Get cache statistics
|
|
46
|
+
*/
|
|
47
|
+
getStats(): Promise<CacheStats>;
|
|
48
|
+
/**
|
|
49
|
+
* Abstract methods - must be implemented by subclasses
|
|
50
|
+
*/
|
|
51
|
+
abstract get(key: string): Promise<T | null>;
|
|
52
|
+
abstract set(key: string, value: T, ttl?: number): Promise<void>;
|
|
53
|
+
abstract delete(key: string): Promise<boolean>;
|
|
54
|
+
abstract exists(key: string): Promise<boolean>;
|
|
55
|
+
abstract clear(): Promise<void>;
|
|
56
|
+
abstract isAlive(): Promise<HealthCheckResponse>;
|
|
57
|
+
abstract close(): Promise<void>;
|
|
58
|
+
/**
|
|
59
|
+
* Default implementation for getMultiple
|
|
60
|
+
*/
|
|
61
|
+
getMultiple(keys: string[]): Promise<BatchResult<T>>;
|
|
62
|
+
/**
|
|
63
|
+
* Default implementation for setMultiple
|
|
64
|
+
*/
|
|
65
|
+
setMultiple(data: Record<string, T>, ttl?: number): Promise<void>;
|
|
66
|
+
/**
|
|
67
|
+
* Default implementation for deleteMultiple
|
|
68
|
+
*/
|
|
69
|
+
deleteMultiple(keys: string[]): Promise<number>;
|
|
70
|
+
/**
|
|
71
|
+
* Default implementation for increment
|
|
72
|
+
*/
|
|
73
|
+
increment(key: string, amount?: number): Promise<number>;
|
|
74
|
+
/**
|
|
75
|
+
* Default implementation for decrement
|
|
76
|
+
*/
|
|
77
|
+
decrement(key: string, amount?: number): Promise<number>;
|
|
78
|
+
}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { CacheError } from '../errors';
|
|
2
|
+
/**
|
|
3
|
+
* Abstract base class for all cache adapters
|
|
4
|
+
*/
|
|
5
|
+
export class BaseCache {
|
|
6
|
+
constructor(config) {
|
|
7
|
+
this.config = config;
|
|
8
|
+
this.stats = {
|
|
9
|
+
hits: 0,
|
|
10
|
+
misses: 0,
|
|
11
|
+
sets: 0,
|
|
12
|
+
deletes: 0
|
|
13
|
+
};
|
|
14
|
+
this.namespace = config.namespace ? `${config.namespace}:` : '';
|
|
15
|
+
this.ttl = config.ttl ?? 3600; // 1 hour default
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Build full key with namespace prefix
|
|
19
|
+
*/
|
|
20
|
+
buildKey(key) {
|
|
21
|
+
return `${this.namespace}${key}`;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Deserialize string to object
|
|
25
|
+
*/
|
|
26
|
+
deserialize(data) {
|
|
27
|
+
try {
|
|
28
|
+
return JSON.parse(data);
|
|
29
|
+
}
|
|
30
|
+
catch (err) {
|
|
31
|
+
throw new CacheError(`Failed to deserialize cache value for key`, 'DESERIALIZE_ERROR', this.config.adapter, err);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Serialize object to string
|
|
36
|
+
*/
|
|
37
|
+
serialize(value) {
|
|
38
|
+
try {
|
|
39
|
+
return JSON.stringify(value);
|
|
40
|
+
}
|
|
41
|
+
catch (err) {
|
|
42
|
+
throw new CacheError(`Failed to serialize cache value`, 'SERIALIZE_ERROR', this.config.adapter, err);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Track cache hit
|
|
47
|
+
*/
|
|
48
|
+
recordHit() {
|
|
49
|
+
this.stats.hits++;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Track cache miss
|
|
53
|
+
*/
|
|
54
|
+
recordMiss() {
|
|
55
|
+
this.stats.misses++;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Track cache set
|
|
59
|
+
*/
|
|
60
|
+
recordSet() {
|
|
61
|
+
this.stats.sets++;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Track cache delete
|
|
65
|
+
*/
|
|
66
|
+
recordDelete() {
|
|
67
|
+
this.stats.deletes++;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Reset statistics
|
|
71
|
+
*/
|
|
72
|
+
resetStats() {
|
|
73
|
+
this.stats = {
|
|
74
|
+
hits: 0,
|
|
75
|
+
misses: 0,
|
|
76
|
+
sets: 0,
|
|
77
|
+
deletes: 0
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Get cache statistics
|
|
82
|
+
*/
|
|
83
|
+
async getStats() {
|
|
84
|
+
return { ...this.stats };
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Default implementation for getMultiple
|
|
88
|
+
*/
|
|
89
|
+
async getMultiple(keys) {
|
|
90
|
+
const result = {};
|
|
91
|
+
for (const key of keys) {
|
|
92
|
+
result[key] = await this.get(key);
|
|
93
|
+
}
|
|
94
|
+
return result;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Default implementation for setMultiple
|
|
98
|
+
*/
|
|
99
|
+
async setMultiple(data, ttl) {
|
|
100
|
+
for (const [key, value] of Object.entries(data)) {
|
|
101
|
+
await this.set(key, value, ttl);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Default implementation for deleteMultiple
|
|
106
|
+
*/
|
|
107
|
+
async deleteMultiple(keys) {
|
|
108
|
+
let count = 0;
|
|
109
|
+
for (const key of keys) {
|
|
110
|
+
const deleted = await this.delete(key);
|
|
111
|
+
if (deleted)
|
|
112
|
+
count++;
|
|
113
|
+
}
|
|
114
|
+
return count;
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Default implementation for increment
|
|
118
|
+
*/
|
|
119
|
+
async increment(key, amount = 1) {
|
|
120
|
+
const current = await this.get(key);
|
|
121
|
+
const value = (typeof current === 'number' ? current : 0) + amount;
|
|
122
|
+
await this.set(key, value);
|
|
123
|
+
return value;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Default implementation for decrement
|
|
127
|
+
*/
|
|
128
|
+
async decrement(key, amount = 1) {
|
|
129
|
+
const current = await this.get(key);
|
|
130
|
+
const value = (typeof current === 'number' ? current : 0) - amount;
|
|
131
|
+
await this.set(key, value);
|
|
132
|
+
return value;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { CacheConfig } from '../types';
|
|
2
|
+
import type { ICache } from './interfaces';
|
|
3
|
+
/**
|
|
4
|
+
* Factory for creating cache instances
|
|
5
|
+
*/
|
|
6
|
+
export declare class CacheFactory {
|
|
7
|
+
/**
|
|
8
|
+
* Create a cache instance based on configuration
|
|
9
|
+
*/
|
|
10
|
+
static create<T = unknown>(config: CacheConfig): ICache<T>;
|
|
11
|
+
/**
|
|
12
|
+
* Create a cache with fallback support
|
|
13
|
+
* If primary adapter fails to connect, falls back to memory cache
|
|
14
|
+
*/
|
|
15
|
+
static createWithFallback<T = unknown>(config: CacheConfig): Promise<ICache<T>>;
|
|
16
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { RedisCache } from '../adapters/redis';
|
|
2
|
+
import { MemcacheCache } from '../adapters/memcache';
|
|
3
|
+
import { MemoryCache } from '../adapters/memory';
|
|
4
|
+
import { CacheError } from '../errors';
|
|
5
|
+
/**
|
|
6
|
+
* Factory for creating cache instances
|
|
7
|
+
*/
|
|
8
|
+
export class CacheFactory {
|
|
9
|
+
/**
|
|
10
|
+
* Create a cache instance based on configuration
|
|
11
|
+
*/
|
|
12
|
+
static create(config) {
|
|
13
|
+
switch (config.adapter) {
|
|
14
|
+
case 'redis':
|
|
15
|
+
return new RedisCache(config);
|
|
16
|
+
case 'memcache':
|
|
17
|
+
return new MemcacheCache(config);
|
|
18
|
+
case 'memory':
|
|
19
|
+
return new MemoryCache(config);
|
|
20
|
+
default:
|
|
21
|
+
throw new CacheError(`Unknown cache adapter: ${config.adapter}`, 'UNKNOWN_ADAPTER');
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Create a cache with fallback support
|
|
26
|
+
* If primary adapter fails to connect, falls back to memory cache
|
|
27
|
+
*/
|
|
28
|
+
static async createWithFallback(config) {
|
|
29
|
+
const cache = this.create(config);
|
|
30
|
+
// Check if primary cache is alive
|
|
31
|
+
const health = await cache.isAlive();
|
|
32
|
+
if (health.isAlive) {
|
|
33
|
+
return cache;
|
|
34
|
+
}
|
|
35
|
+
// If primary cache failed and fallback is enabled, use memory cache
|
|
36
|
+
if (config.fallback !== false) {
|
|
37
|
+
console.warn(`Failed to connect to ${config.adapter} cache, falling back to memory cache`);
|
|
38
|
+
return new MemoryCache({
|
|
39
|
+
adapter: 'memory',
|
|
40
|
+
namespace: config.namespace,
|
|
41
|
+
ttl: config.ttl
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
// No fallback, throw error
|
|
45
|
+
throw new CacheError(`Failed to initialize ${config.adapter} cache and fallback is disabled`, 'CACHE_INIT_ERROR');
|
|
46
|
+
}
|
|
47
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import type { CacheStats, HealthCheckResponse, BatchResult } from '../../types';
|
|
2
|
+
/**
|
|
3
|
+
* Main cache interface - defines all cache operations
|
|
4
|
+
*/
|
|
5
|
+
export interface ICache<T = unknown> {
|
|
6
|
+
/**
|
|
7
|
+
* Get a value from cache
|
|
8
|
+
*/
|
|
9
|
+
get(key: string): Promise<T | null>;
|
|
10
|
+
/**
|
|
11
|
+
* Set a value in cache
|
|
12
|
+
*/
|
|
13
|
+
set(key: string, value: T, ttl?: number): Promise<void>;
|
|
14
|
+
/**
|
|
15
|
+
* Delete a value from cache
|
|
16
|
+
*/
|
|
17
|
+
delete(key: string): Promise<boolean>;
|
|
18
|
+
/**
|
|
19
|
+
* Check if key exists
|
|
20
|
+
*/
|
|
21
|
+
exists(key: string): Promise<boolean>;
|
|
22
|
+
/**
|
|
23
|
+
* Clear all cache entries
|
|
24
|
+
*/
|
|
25
|
+
clear(): Promise<void>;
|
|
26
|
+
/**
|
|
27
|
+
* Get multiple values at once
|
|
28
|
+
*/
|
|
29
|
+
getMultiple(keys: string[]): Promise<BatchResult<T>>;
|
|
30
|
+
/**
|
|
31
|
+
* Set multiple values at once
|
|
32
|
+
*/
|
|
33
|
+
setMultiple(data: Record<string, T>, ttl?: number): Promise<void>;
|
|
34
|
+
/**
|
|
35
|
+
* Delete multiple keys at once
|
|
36
|
+
*/
|
|
37
|
+
deleteMultiple(keys: string[]): Promise<number>;
|
|
38
|
+
/**
|
|
39
|
+
* Increment a numeric value
|
|
40
|
+
*/
|
|
41
|
+
increment(key: string, amount?: number): Promise<number>;
|
|
42
|
+
/**
|
|
43
|
+
* Decrement a numeric value
|
|
44
|
+
*/
|
|
45
|
+
decrement(key: string, amount?: number): Promise<number>;
|
|
46
|
+
/**
|
|
47
|
+
* Get cache statistics
|
|
48
|
+
*/
|
|
49
|
+
getStats?(): Promise<CacheStats>;
|
|
50
|
+
/**
|
|
51
|
+
* Check cache health
|
|
52
|
+
*/
|
|
53
|
+
isAlive(): Promise<HealthCheckResponse>;
|
|
54
|
+
/**
|
|
55
|
+
* Close/disconnect cache connection
|
|
56
|
+
*/
|
|
57
|
+
close(): Promise<void>;
|
|
58
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { SessionData } from '../../types';
|
|
2
|
+
/**
|
|
3
|
+
* Session store interface
|
|
4
|
+
*/
|
|
5
|
+
export interface ISession {
|
|
6
|
+
/**
|
|
7
|
+
* Get session data
|
|
8
|
+
*/
|
|
9
|
+
get(sessionId: string): Promise<SessionData | null>;
|
|
10
|
+
/**
|
|
11
|
+
* Set session data
|
|
12
|
+
*/
|
|
13
|
+
set(sessionId: string, data: SessionData, ttl?: number): Promise<void>;
|
|
14
|
+
/**
|
|
15
|
+
* Delete session
|
|
16
|
+
*/
|
|
17
|
+
delete(sessionId: string): Promise<boolean>;
|
|
18
|
+
/**
|
|
19
|
+
* Check if session exists
|
|
20
|
+
*/
|
|
21
|
+
exists(sessionId: string): Promise<boolean>;
|
|
22
|
+
/**
|
|
23
|
+
* Clear all sessions
|
|
24
|
+
*/
|
|
25
|
+
clear(): Promise<void>;
|
|
26
|
+
/**
|
|
27
|
+
* Update/merge session data
|
|
28
|
+
*/
|
|
29
|
+
update(sessionId: string, data: Partial<SessionData>): Promise<void>;
|
|
30
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Custom error class for cache operations
|
|
3
|
+
*/
|
|
4
|
+
export declare class CacheError extends Error {
|
|
5
|
+
readonly code: string;
|
|
6
|
+
readonly adapter?: string;
|
|
7
|
+
readonly originalError?: Error;
|
|
8
|
+
constructor(message: string, code?: string, adapter?: string, originalError?: Error);
|
|
9
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Custom error class for cache operations
|
|
3
|
+
*/
|
|
4
|
+
export class CacheError extends Error {
|
|
5
|
+
constructor(message, code = 'CACHE_ERROR', adapter, originalError) {
|
|
6
|
+
super(message);
|
|
7
|
+
this.name = 'CacheError';
|
|
8
|
+
this.code = code;
|
|
9
|
+
this.adapter = adapter;
|
|
10
|
+
this.originalError = originalError;
|
|
11
|
+
Object.setPrototypeOf(this, CacheError.prototype);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { CacheError } from './CacheError';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { CacheError } from './CacheError';
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export type { CacheConfig, RedisCacheConfig, MemcacheCacheConfig, MemoryCacheConfig, SessionData, SessionOptions, CacheStats, HealthCheckResponse, BatchResult, CacheEntry } from './types';
|
|
2
|
+
export { CacheError } from './errors';
|
|
3
|
+
export type { ICache, ISession } from './core/interfaces';
|
|
4
|
+
export { BaseCache } from './core/BaseCache';
|
|
5
|
+
export { RedisCache } from './adapters/redis';
|
|
6
|
+
export { MemcacheCache } from './adapters/memcache';
|
|
7
|
+
export { MemoryCache } from './adapters/memory';
|
|
8
|
+
export { CacheFactory } from './core/factory';
|
|
9
|
+
export { SessionStore } from './session';
|
|
10
|
+
export { cacheSessionMiddleware, cacheHealthCheckMiddleware, cacheResponseMiddleware } from './middleware/express';
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// Errors
|
|
2
|
+
export { CacheError } from './errors';
|
|
3
|
+
// Base Cache
|
|
4
|
+
export { BaseCache } from './core/BaseCache';
|
|
5
|
+
// Adapters
|
|
6
|
+
export { RedisCache } from './adapters/redis';
|
|
7
|
+
export { MemcacheCache } from './adapters/memcache';
|
|
8
|
+
export { MemoryCache } from './adapters/memory';
|
|
9
|
+
// Factory
|
|
10
|
+
export { CacheFactory } from './core/factory';
|
|
11
|
+
// Session
|
|
12
|
+
export { SessionStore } from './session';
|
|
13
|
+
// Middleware
|
|
14
|
+
export { cacheSessionMiddleware, cacheHealthCheckMiddleware, cacheResponseMiddleware } from './middleware/express';
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { Request, Response, NextFunction } from 'express';
|
|
2
|
+
import type { ICache } from '../../core/interfaces';
|
|
3
|
+
import { SessionStore } from '../../session/SessionStore';
|
|
4
|
+
/**
|
|
5
|
+
* Express middleware for session management using cache
|
|
6
|
+
*/
|
|
7
|
+
export declare function cacheSessionMiddleware(sessionStore: SessionStore, options?: {
|
|
8
|
+
sessionIdHeader?: string;
|
|
9
|
+
sessionDataKey?: string;
|
|
10
|
+
}): (req: Request, res: Response, next: NextFunction) => Promise<void>;
|
|
11
|
+
/**
|
|
12
|
+
* Express middleware for cache health check
|
|
13
|
+
*/
|
|
14
|
+
export declare function cacheHealthCheckMiddleware(cache: ICache, endpoint?: string): (req: Request, res: Response, next: NextFunction) => void;
|
|
15
|
+
/**
|
|
16
|
+
* Express middleware for cache request/response caching
|
|
17
|
+
*/
|
|
18
|
+
export declare function cacheResponseMiddleware(cache: ICache<string>, options?: {
|
|
19
|
+
ttl?: number;
|
|
20
|
+
keyPrefix?: string;
|
|
21
|
+
excludeStatusCodes?: number[];
|
|
22
|
+
}): (req: Request, res: Response, next: NextFunction) => void;
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Express middleware for session management using cache
|
|
3
|
+
*/
|
|
4
|
+
export function cacheSessionMiddleware(sessionStore, options) {
|
|
5
|
+
const sessionIdHeader = options?.sessionIdHeader ?? 'x-session-id';
|
|
6
|
+
const sessionDataKey = options?.sessionDataKey ?? 'session';
|
|
7
|
+
return async (req, res, next) => {
|
|
8
|
+
try {
|
|
9
|
+
// Get session ID from header or cookie
|
|
10
|
+
const sessionId = req.get(sessionIdHeader) || req.cookies?.[sessionIdHeader];
|
|
11
|
+
if (sessionId) {
|
|
12
|
+
// Fetch session data and extend expiry
|
|
13
|
+
const sessionData = await sessionStore.getAndExtend(sessionId);
|
|
14
|
+
if (sessionData) {
|
|
15
|
+
req[sessionDataKey] = sessionData;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
next();
|
|
19
|
+
}
|
|
20
|
+
catch (err) {
|
|
21
|
+
console.error('Session middleware error:', err);
|
|
22
|
+
next();
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Express middleware for cache health check
|
|
28
|
+
*/
|
|
29
|
+
export function cacheHealthCheckMiddleware(cache, endpoint = '/.health/cache') {
|
|
30
|
+
return (req, res, next) => {
|
|
31
|
+
if (req.path === endpoint && req.method === 'GET') {
|
|
32
|
+
cache
|
|
33
|
+
.isAlive()
|
|
34
|
+
.then((health) => {
|
|
35
|
+
res.status(health.isAlive ? 200 : 503).json(health);
|
|
36
|
+
})
|
|
37
|
+
.catch((err) => {
|
|
38
|
+
res.status(503).json({
|
|
39
|
+
isAlive: false,
|
|
40
|
+
adapter: 'unknown',
|
|
41
|
+
timestamp: new Date(),
|
|
42
|
+
error: err.message
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
next();
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Express middleware for cache request/response caching
|
|
52
|
+
*/
|
|
53
|
+
export function cacheResponseMiddleware(cache, options) {
|
|
54
|
+
const ttl = options?.ttl ?? 300; // 5 minutes default
|
|
55
|
+
const keyPrefix = options?.keyPrefix ?? 'response:';
|
|
56
|
+
const excludeStatusCodes = options?.excludeStatusCodes ?? [300, 301, 302, 303, 304, 307, 308, 404, 500, 501, 502, 503];
|
|
57
|
+
return (req, res, next) => {
|
|
58
|
+
// Only cache GET requests
|
|
59
|
+
if (req.method !== 'GET') {
|
|
60
|
+
next();
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
const cacheKey = `${keyPrefix}${req.originalUrl || req.url}`;
|
|
64
|
+
// Try to get cached response
|
|
65
|
+
cache
|
|
66
|
+
.get(cacheKey)
|
|
67
|
+
.then((cached) => {
|
|
68
|
+
if (cached) {
|
|
69
|
+
res.set('X-Cache', 'HIT');
|
|
70
|
+
return res.send(cached);
|
|
71
|
+
}
|
|
72
|
+
// Store original send method
|
|
73
|
+
const originalSend = res.send;
|
|
74
|
+
// Override send method to cache response
|
|
75
|
+
res.send = function (data) {
|
|
76
|
+
// Check if response should be cached
|
|
77
|
+
if (res.statusCode >= 200 &&
|
|
78
|
+
res.statusCode < 300 &&
|
|
79
|
+
!excludeStatusCodes.includes(res.statusCode)) {
|
|
80
|
+
const responseData = typeof data === 'string' ? data : JSON.stringify(data);
|
|
81
|
+
cache.set(cacheKey, responseData, ttl).catch((err) => {
|
|
82
|
+
console.error('Failed to cache response:', err);
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
res.set('X-Cache', 'MISS');
|
|
86
|
+
return originalSend.call(this, data);
|
|
87
|
+
};
|
|
88
|
+
next();
|
|
89
|
+
})
|
|
90
|
+
.catch((err) => {
|
|
91
|
+
console.error('Cache middleware error:', err);
|
|
92
|
+
next();
|
|
93
|
+
});
|
|
94
|
+
};
|
|
95
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { cacheSessionMiddleware, cacheHealthCheckMiddleware, cacheResponseMiddleware } from './cacheMiddleware';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { cacheSessionMiddleware, cacheHealthCheckMiddleware, cacheResponseMiddleware } from './cacheMiddleware';
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { ICache } from '../core/interfaces';
|
|
2
|
+
import type { SessionData, SessionOptions } from '../types';
|
|
3
|
+
/**
|
|
4
|
+
* Session store wrapper around cache adapters
|
|
5
|
+
* Provides session management functionality
|
|
6
|
+
*/
|
|
7
|
+
export declare class SessionStore {
|
|
8
|
+
private cache;
|
|
9
|
+
private options;
|
|
10
|
+
constructor(cache: ICache<SessionData>, options?: SessionOptions);
|
|
11
|
+
/**
|
|
12
|
+
* Create a new session
|
|
13
|
+
*/
|
|
14
|
+
create(sessionId: string, data: SessionData, ttl?: number): Promise<void>;
|
|
15
|
+
/**
|
|
16
|
+
* Get session data
|
|
17
|
+
*/
|
|
18
|
+
get(sessionId: string): Promise<SessionData | null>;
|
|
19
|
+
/**
|
|
20
|
+
* Update/merge session data
|
|
21
|
+
*/
|
|
22
|
+
update(sessionId: string, data: Partial<SessionData>): Promise<void>;
|
|
23
|
+
/**
|
|
24
|
+
* Delete session
|
|
25
|
+
*/
|
|
26
|
+
delete(sessionId: string): Promise<boolean>;
|
|
27
|
+
/**
|
|
28
|
+
* Check if session exists
|
|
29
|
+
*/
|
|
30
|
+
exists(sessionId: string): Promise<boolean>;
|
|
31
|
+
/**
|
|
32
|
+
* Clear all sessions
|
|
33
|
+
*/
|
|
34
|
+
clear(): Promise<void>;
|
|
35
|
+
/**
|
|
36
|
+
* Get all session keys (limited use - may be slow with large datasets)
|
|
37
|
+
*/
|
|
38
|
+
getMultiple(sessionIds: string[]): Promise<Record<string, SessionData | null>>;
|
|
39
|
+
/**
|
|
40
|
+
* Delete multiple sessions
|
|
41
|
+
*/
|
|
42
|
+
deleteMultiple(sessionIds: string[]): Promise<number>;
|
|
43
|
+
/**
|
|
44
|
+
* Extend session expiry
|
|
45
|
+
*/
|
|
46
|
+
extend(sessionId: string, ttl?: number): Promise<void>;
|
|
47
|
+
/**
|
|
48
|
+
* Get session data and extend expiry in one operation
|
|
49
|
+
*/
|
|
50
|
+
getAndExtend(sessionId: string, ttl?: number): Promise<SessionData | null>;
|
|
51
|
+
}
|