@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,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,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,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,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CacheError = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Custom error class for cache operations
|
|
6
|
+
*/
|
|
7
|
+
class CacheError extends Error {
|
|
8
|
+
constructor(message, code = 'CACHE_ERROR', adapter, originalError) {
|
|
9
|
+
super(message);
|
|
10
|
+
this.name = 'CacheError';
|
|
11
|
+
this.code = code;
|
|
12
|
+
this.adapter = adapter;
|
|
13
|
+
this.originalError = originalError;
|
|
14
|
+
Object.setPrototypeOf(this, CacheError.prototype);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
exports.CacheError = CacheError;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { CacheError } from './CacheError';
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CacheError = void 0;
|
|
4
|
+
var CacheError_1 = require("./CacheError");
|
|
5
|
+
Object.defineProperty(exports, "CacheError", { enumerable: true, get: function () { return CacheError_1.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,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.cacheResponseMiddleware = exports.cacheHealthCheckMiddleware = exports.cacheSessionMiddleware = exports.SessionStore = exports.CacheFactory = exports.MemoryCache = exports.MemcacheCache = exports.RedisCache = exports.BaseCache = exports.CacheError = void 0;
|
|
4
|
+
// Errors
|
|
5
|
+
var errors_1 = require("./errors");
|
|
6
|
+
Object.defineProperty(exports, "CacheError", { enumerable: true, get: function () { return errors_1.CacheError; } });
|
|
7
|
+
// Base Cache
|
|
8
|
+
var BaseCache_1 = require("./core/BaseCache");
|
|
9
|
+
Object.defineProperty(exports, "BaseCache", { enumerable: true, get: function () { return BaseCache_1.BaseCache; } });
|
|
10
|
+
// Adapters
|
|
11
|
+
var redis_1 = require("./adapters/redis");
|
|
12
|
+
Object.defineProperty(exports, "RedisCache", { enumerable: true, get: function () { return redis_1.RedisCache; } });
|
|
13
|
+
var memcache_1 = require("./adapters/memcache");
|
|
14
|
+
Object.defineProperty(exports, "MemcacheCache", { enumerable: true, get: function () { return memcache_1.MemcacheCache; } });
|
|
15
|
+
var memory_1 = require("./adapters/memory");
|
|
16
|
+
Object.defineProperty(exports, "MemoryCache", { enumerable: true, get: function () { return memory_1.MemoryCache; } });
|
|
17
|
+
// Factory
|
|
18
|
+
var factory_1 = require("./core/factory");
|
|
19
|
+
Object.defineProperty(exports, "CacheFactory", { enumerable: true, get: function () { return factory_1.CacheFactory; } });
|
|
20
|
+
// Session
|
|
21
|
+
var session_1 = require("./session");
|
|
22
|
+
Object.defineProperty(exports, "SessionStore", { enumerable: true, get: function () { return session_1.SessionStore; } });
|
|
23
|
+
// Middleware
|
|
24
|
+
var express_1 = require("./middleware/express");
|
|
25
|
+
Object.defineProperty(exports, "cacheSessionMiddleware", { enumerable: true, get: function () { return express_1.cacheSessionMiddleware; } });
|
|
26
|
+
Object.defineProperty(exports, "cacheHealthCheckMiddleware", { enumerable: true, get: function () { return express_1.cacheHealthCheckMiddleware; } });
|
|
27
|
+
Object.defineProperty(exports, "cacheResponseMiddleware", { enumerable: true, get: function () { return express_1.cacheResponseMiddleware; } });
|
|
@@ -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,100 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.cacheSessionMiddleware = cacheSessionMiddleware;
|
|
4
|
+
exports.cacheHealthCheckMiddleware = cacheHealthCheckMiddleware;
|
|
5
|
+
exports.cacheResponseMiddleware = cacheResponseMiddleware;
|
|
6
|
+
/**
|
|
7
|
+
* Express middleware for session management using cache
|
|
8
|
+
*/
|
|
9
|
+
function cacheSessionMiddleware(sessionStore, options) {
|
|
10
|
+
const sessionIdHeader = options?.sessionIdHeader ?? 'x-session-id';
|
|
11
|
+
const sessionDataKey = options?.sessionDataKey ?? 'session';
|
|
12
|
+
return async (req, res, next) => {
|
|
13
|
+
try {
|
|
14
|
+
// Get session ID from header or cookie
|
|
15
|
+
const sessionId = req.get(sessionIdHeader) || req.cookies?.[sessionIdHeader];
|
|
16
|
+
if (sessionId) {
|
|
17
|
+
// Fetch session data and extend expiry
|
|
18
|
+
const sessionData = await sessionStore.getAndExtend(sessionId);
|
|
19
|
+
if (sessionData) {
|
|
20
|
+
req[sessionDataKey] = sessionData;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
next();
|
|
24
|
+
}
|
|
25
|
+
catch (err) {
|
|
26
|
+
console.error('Session middleware error:', err);
|
|
27
|
+
next();
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Express middleware for cache health check
|
|
33
|
+
*/
|
|
34
|
+
function cacheHealthCheckMiddleware(cache, endpoint = '/.health/cache') {
|
|
35
|
+
return (req, res, next) => {
|
|
36
|
+
if (req.path === endpoint && req.method === 'GET') {
|
|
37
|
+
cache
|
|
38
|
+
.isAlive()
|
|
39
|
+
.then((health) => {
|
|
40
|
+
res.status(health.isAlive ? 200 : 503).json(health);
|
|
41
|
+
})
|
|
42
|
+
.catch((err) => {
|
|
43
|
+
res.status(503).json({
|
|
44
|
+
isAlive: false,
|
|
45
|
+
adapter: 'unknown',
|
|
46
|
+
timestamp: new Date(),
|
|
47
|
+
error: err.message
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
next();
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Express middleware for cache request/response caching
|
|
57
|
+
*/
|
|
58
|
+
function cacheResponseMiddleware(cache, options) {
|
|
59
|
+
const ttl = options?.ttl ?? 300; // 5 minutes default
|
|
60
|
+
const keyPrefix = options?.keyPrefix ?? 'response:';
|
|
61
|
+
const excludeStatusCodes = options?.excludeStatusCodes ?? [300, 301, 302, 303, 304, 307, 308, 404, 500, 501, 502, 503];
|
|
62
|
+
return (req, res, next) => {
|
|
63
|
+
// Only cache GET requests
|
|
64
|
+
if (req.method !== 'GET') {
|
|
65
|
+
next();
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
const cacheKey = `${keyPrefix}${req.originalUrl || req.url}`;
|
|
69
|
+
// Try to get cached response
|
|
70
|
+
cache
|
|
71
|
+
.get(cacheKey)
|
|
72
|
+
.then((cached) => {
|
|
73
|
+
if (cached) {
|
|
74
|
+
res.set('X-Cache', 'HIT');
|
|
75
|
+
return res.send(cached);
|
|
76
|
+
}
|
|
77
|
+
// Store original send method
|
|
78
|
+
const originalSend = res.send;
|
|
79
|
+
// Override send method to cache response
|
|
80
|
+
res.send = function (data) {
|
|
81
|
+
// Check if response should be cached
|
|
82
|
+
if (res.statusCode >= 200 &&
|
|
83
|
+
res.statusCode < 300 &&
|
|
84
|
+
!excludeStatusCodes.includes(res.statusCode)) {
|
|
85
|
+
const responseData = typeof data === 'string' ? data : JSON.stringify(data);
|
|
86
|
+
cache.set(cacheKey, responseData, ttl).catch((err) => {
|
|
87
|
+
console.error('Failed to cache response:', err);
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
res.set('X-Cache', 'MISS');
|
|
91
|
+
return originalSend.call(this, data);
|
|
92
|
+
};
|
|
93
|
+
next();
|
|
94
|
+
})
|
|
95
|
+
.catch((err) => {
|
|
96
|
+
console.error('Cache middleware error:', err);
|
|
97
|
+
next();
|
|
98
|
+
});
|
|
99
|
+
};
|
|
100
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { cacheSessionMiddleware, cacheHealthCheckMiddleware, cacheResponseMiddleware } from './cacheMiddleware';
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.cacheResponseMiddleware = exports.cacheHealthCheckMiddleware = exports.cacheSessionMiddleware = void 0;
|
|
4
|
+
var cacheMiddleware_1 = require("./cacheMiddleware");
|
|
5
|
+
Object.defineProperty(exports, "cacheSessionMiddleware", { enumerable: true, get: function () { return cacheMiddleware_1.cacheSessionMiddleware; } });
|
|
6
|
+
Object.defineProperty(exports, "cacheHealthCheckMiddleware", { enumerable: true, get: function () { return cacheMiddleware_1.cacheHealthCheckMiddleware; } });
|
|
7
|
+
Object.defineProperty(exports, "cacheResponseMiddleware", { enumerable: true, get: function () { return cacheMiddleware_1.cacheResponseMiddleware; } });
|
|
@@ -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
|
+
}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SessionStore = void 0;
|
|
4
|
+
const errors_1 = require("../errors");
|
|
5
|
+
/**
|
|
6
|
+
* Session store wrapper around cache adapters
|
|
7
|
+
* Provides session management functionality
|
|
8
|
+
*/
|
|
9
|
+
class SessionStore {
|
|
10
|
+
constructor(cache, options = {}) {
|
|
11
|
+
this.cache = cache;
|
|
12
|
+
this.options = {
|
|
13
|
+
ttl: options.ttl ?? 3600, // 1 hour default
|
|
14
|
+
serialize: options.serialize ?? ((data) => JSON.stringify(data)),
|
|
15
|
+
deserialize: options.deserialize ?? ((data) => JSON.parse(data))
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Create a new session
|
|
20
|
+
*/
|
|
21
|
+
async create(sessionId, data, ttl) {
|
|
22
|
+
try {
|
|
23
|
+
const ttlValue = ttl ?? this.options.ttl;
|
|
24
|
+
await this.cache.set(sessionId, data, ttlValue);
|
|
25
|
+
}
|
|
26
|
+
catch (err) {
|
|
27
|
+
throw new errors_1.CacheError(`Failed to create session "${sessionId}"`, 'SESSION_CREATE_ERROR', 'session', err);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Get session data
|
|
32
|
+
*/
|
|
33
|
+
async get(sessionId) {
|
|
34
|
+
try {
|
|
35
|
+
return await this.cache.get(sessionId);
|
|
36
|
+
}
|
|
37
|
+
catch (err) {
|
|
38
|
+
throw new errors_1.CacheError(`Failed to get session "${sessionId}"`, 'SESSION_GET_ERROR', 'session', err);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Update/merge session data
|
|
43
|
+
*/
|
|
44
|
+
async update(sessionId, data) {
|
|
45
|
+
try {
|
|
46
|
+
const current = await this.cache.get(sessionId);
|
|
47
|
+
if (!current) {
|
|
48
|
+
throw new errors_1.CacheError(`Session "${sessionId}" not found`, 'SESSION_NOT_FOUND');
|
|
49
|
+
}
|
|
50
|
+
const merged = { ...current, ...data };
|
|
51
|
+
await this.cache.set(sessionId, merged, this.options.ttl);
|
|
52
|
+
}
|
|
53
|
+
catch (err) {
|
|
54
|
+
if (err instanceof errors_1.CacheError) {
|
|
55
|
+
throw err;
|
|
56
|
+
}
|
|
57
|
+
throw new errors_1.CacheError(`Failed to update session "${sessionId}"`, 'SESSION_UPDATE_ERROR', 'session', err);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Delete session
|
|
62
|
+
*/
|
|
63
|
+
async delete(sessionId) {
|
|
64
|
+
try {
|
|
65
|
+
return await this.cache.delete(sessionId);
|
|
66
|
+
}
|
|
67
|
+
catch (err) {
|
|
68
|
+
throw new errors_1.CacheError(`Failed to delete session "${sessionId}"`, 'SESSION_DELETE_ERROR', 'session', err);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Check if session exists
|
|
73
|
+
*/
|
|
74
|
+
async exists(sessionId) {
|
|
75
|
+
try {
|
|
76
|
+
return await this.cache.exists(sessionId);
|
|
77
|
+
}
|
|
78
|
+
catch (err) {
|
|
79
|
+
throw new errors_1.CacheError(`Failed to check session "${sessionId}" existence`, 'SESSION_EXISTS_ERROR', 'session', err);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Clear all sessions
|
|
84
|
+
*/
|
|
85
|
+
async clear() {
|
|
86
|
+
try {
|
|
87
|
+
await this.cache.clear();
|
|
88
|
+
}
|
|
89
|
+
catch (err) {
|
|
90
|
+
throw new errors_1.CacheError('Failed to clear sessions', 'SESSION_CLEAR_ERROR', 'session', err);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Get all session keys (limited use - may be slow with large datasets)
|
|
95
|
+
*/
|
|
96
|
+
async getMultiple(sessionIds) {
|
|
97
|
+
try {
|
|
98
|
+
return await this.cache.getMultiple(sessionIds);
|
|
99
|
+
}
|
|
100
|
+
catch (err) {
|
|
101
|
+
throw new errors_1.CacheError('Failed to get multiple sessions', 'SESSION_GET_MULTIPLE_ERROR', 'session', err);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Delete multiple sessions
|
|
106
|
+
*/
|
|
107
|
+
async deleteMultiple(sessionIds) {
|
|
108
|
+
try {
|
|
109
|
+
return await this.cache.deleteMultiple(sessionIds);
|
|
110
|
+
}
|
|
111
|
+
catch (err) {
|
|
112
|
+
throw new errors_1.CacheError('Failed to delete multiple sessions', 'SESSION_DELETE_MULTIPLE_ERROR', 'session', err);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Extend session expiry
|
|
117
|
+
*/
|
|
118
|
+
async extend(sessionId, ttl) {
|
|
119
|
+
try {
|
|
120
|
+
const current = await this.cache.get(sessionId);
|
|
121
|
+
if (!current) {
|
|
122
|
+
throw new errors_1.CacheError(`Session "${sessionId}" not found`, 'SESSION_NOT_FOUND');
|
|
123
|
+
}
|
|
124
|
+
const ttlValue = ttl ?? this.options.ttl;
|
|
125
|
+
await this.cache.set(sessionId, current, ttlValue);
|
|
126
|
+
}
|
|
127
|
+
catch (err) {
|
|
128
|
+
if (err instanceof errors_1.CacheError) {
|
|
129
|
+
throw err;
|
|
130
|
+
}
|
|
131
|
+
throw new errors_1.CacheError(`Failed to extend session "${sessionId}"`, 'SESSION_EXTEND_ERROR', 'session', err);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Get session data and extend expiry in one operation
|
|
136
|
+
*/
|
|
137
|
+
async getAndExtend(sessionId, ttl) {
|
|
138
|
+
try {
|
|
139
|
+
const data = await this.get(sessionId);
|
|
140
|
+
if (data) {
|
|
141
|
+
await this.extend(sessionId, ttl);
|
|
142
|
+
}
|
|
143
|
+
return data;
|
|
144
|
+
}
|
|
145
|
+
catch (err) {
|
|
146
|
+
if (err instanceof errors_1.CacheError) {
|
|
147
|
+
throw err;
|
|
148
|
+
}
|
|
149
|
+
throw new errors_1.CacheError(`Failed to get and extend session "${sessionId}"`, 'SESSION_GET_EXTEND_ERROR', 'session', err);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
exports.SessionStore = SessionStore;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SessionStore = void 0;
|
|
4
|
+
var SessionStore_1 = require("./SessionStore");
|
|
5
|
+
Object.defineProperty(exports, "SessionStore", { enumerable: true, get: function () { return SessionStore_1.SessionStore; } });
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cache configuration options
|
|
3
|
+
*/
|
|
4
|
+
export interface CacheConfig {
|
|
5
|
+
adapter: 'redis' | 'memcache' | 'memory';
|
|
6
|
+
namespace?: string;
|
|
7
|
+
ttl?: number;
|
|
8
|
+
fallback?: boolean;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Redis-specific configuration
|
|
12
|
+
*/
|
|
13
|
+
export interface RedisCacheConfig extends CacheConfig {
|
|
14
|
+
adapter: 'redis';
|
|
15
|
+
host?: string;
|
|
16
|
+
port?: number;
|
|
17
|
+
username?: string;
|
|
18
|
+
password?: string;
|
|
19
|
+
db?: number;
|
|
20
|
+
tls?: boolean;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Memcache-specific configuration
|
|
24
|
+
*/
|
|
25
|
+
export interface MemcacheCacheConfig extends CacheConfig {
|
|
26
|
+
adapter: 'memcache';
|
|
27
|
+
servers: string | string[];
|
|
28
|
+
username?: string;
|
|
29
|
+
password?: string;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Memory cache configuration
|
|
33
|
+
*/
|
|
34
|
+
export interface MemoryCacheConfig extends CacheConfig {
|
|
35
|
+
adapter: 'memory';
|
|
36
|
+
maxSize?: number;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Session data structure
|
|
40
|
+
*/
|
|
41
|
+
export interface SessionData {
|
|
42
|
+
[key: string]: unknown;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Session store options
|
|
46
|
+
*/
|
|
47
|
+
export interface SessionOptions {
|
|
48
|
+
ttl?: number;
|
|
49
|
+
serialize?: (data: SessionData) => string;
|
|
50
|
+
deserialize?: (data: string) => SessionData;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Cache statistics
|
|
54
|
+
*/
|
|
55
|
+
export interface CacheStats {
|
|
56
|
+
hits: number;
|
|
57
|
+
misses: number;
|
|
58
|
+
sets: number;
|
|
59
|
+
deletes: number;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Health check response
|
|
63
|
+
*/
|
|
64
|
+
export interface HealthCheckResponse {
|
|
65
|
+
isAlive: boolean;
|
|
66
|
+
adapter: string;
|
|
67
|
+
timestamp: Date;
|
|
68
|
+
error?: string;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Batch operation result
|
|
72
|
+
*/
|
|
73
|
+
export interface BatchResult<T> {
|
|
74
|
+
[key: string]: T | null;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Cache key with optional metadata
|
|
78
|
+
*/
|
|
79
|
+
export interface CacheEntry<T = unknown> {
|
|
80
|
+
value: T;
|
|
81
|
+
expiresAt?: number;
|
|
82
|
+
createdAt: number;
|
|
83
|
+
}
|