@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,347 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.MemcacheCache = void 0;
|
|
7
|
+
const memcached_1 = __importDefault(require("memcached"));
|
|
8
|
+
const BaseCache_1 = require("../../core/BaseCache");
|
|
9
|
+
const errors_1 = require("../../errors");
|
|
10
|
+
/**
|
|
11
|
+
* Memcache adapter
|
|
12
|
+
*/
|
|
13
|
+
class MemcacheCache extends BaseCache_1.BaseCache {
|
|
14
|
+
constructor(memcacheConfig) {
|
|
15
|
+
super(memcacheConfig);
|
|
16
|
+
this.memcacheConfig = memcacheConfig;
|
|
17
|
+
this.client = null;
|
|
18
|
+
this.isConnected = false;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Connect to Memcache
|
|
22
|
+
*/
|
|
23
|
+
async connect() {
|
|
24
|
+
try {
|
|
25
|
+
const servers = Array.isArray(this.memcacheConfig.servers)
|
|
26
|
+
? this.memcacheConfig.servers
|
|
27
|
+
: [this.memcacheConfig.servers];
|
|
28
|
+
const options = {
|
|
29
|
+
retries: 2,
|
|
30
|
+
retry: 30000,
|
|
31
|
+
remove: true,
|
|
32
|
+
failOverServers: [],
|
|
33
|
+
maxValue: 1048576, // 1MB default
|
|
34
|
+
idle: 30000
|
|
35
|
+
};
|
|
36
|
+
if (this.memcacheConfig.username) {
|
|
37
|
+
options.username = this.memcacheConfig.username;
|
|
38
|
+
}
|
|
39
|
+
if (this.memcacheConfig.password) {
|
|
40
|
+
options.password = this.memcacheConfig.password;
|
|
41
|
+
}
|
|
42
|
+
this.client = new memcached_1.default(servers, options);
|
|
43
|
+
this.isConnected = true;
|
|
44
|
+
// Test connection
|
|
45
|
+
await this.ping();
|
|
46
|
+
}
|
|
47
|
+
catch (err) {
|
|
48
|
+
throw new errors_1.CacheError('Failed to connect to Memcache', 'MEMCACHE_CONNECTION_ERROR', 'memcache', err);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Ensure client is connected
|
|
53
|
+
*/
|
|
54
|
+
async ensureConnected() {
|
|
55
|
+
if (!this.client) {
|
|
56
|
+
await this.connect();
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Ping memcache
|
|
61
|
+
*/
|
|
62
|
+
async ping() {
|
|
63
|
+
return new Promise((resolve, reject) => {
|
|
64
|
+
if (!this.client) {
|
|
65
|
+
reject(new Error('Memcache client not initialized'));
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
this.client.touch('__ping', 1, (err) => {
|
|
69
|
+
if (err)
|
|
70
|
+
reject(err);
|
|
71
|
+
else
|
|
72
|
+
resolve();
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Get a value from Memcache
|
|
78
|
+
*/
|
|
79
|
+
async get(key) {
|
|
80
|
+
try {
|
|
81
|
+
await this.ensureConnected();
|
|
82
|
+
const fullKey = this.buildKey(key);
|
|
83
|
+
return new Promise((resolve, reject) => {
|
|
84
|
+
this.client.get(fullKey, (err, data) => {
|
|
85
|
+
if (err) {
|
|
86
|
+
reject(err);
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
if (data === undefined) {
|
|
90
|
+
this.recordMiss();
|
|
91
|
+
resolve(null);
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
this.recordHit();
|
|
95
|
+
try {
|
|
96
|
+
resolve(this.deserialize(data));
|
|
97
|
+
}
|
|
98
|
+
catch (parseErr) {
|
|
99
|
+
reject(parseErr);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
catch (err) {
|
|
106
|
+
throw new errors_1.CacheError(`Failed to get key "${key}" from Memcache`, 'MEMCACHE_GET_ERROR', 'memcache', err);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Set a value in Memcache
|
|
111
|
+
*/
|
|
112
|
+
async set(key, value, ttl) {
|
|
113
|
+
try {
|
|
114
|
+
await this.ensureConnected();
|
|
115
|
+
const fullKey = this.buildKey(key);
|
|
116
|
+
const serialized = this.serialize(value);
|
|
117
|
+
const expiry = ttl ?? this.ttl;
|
|
118
|
+
return new Promise((resolve, reject) => {
|
|
119
|
+
this.client.set(fullKey, serialized, expiry, (err) => {
|
|
120
|
+
if (err) {
|
|
121
|
+
reject(err);
|
|
122
|
+
}
|
|
123
|
+
else {
|
|
124
|
+
this.recordSet();
|
|
125
|
+
resolve();
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
catch (err) {
|
|
131
|
+
throw new errors_1.CacheError(`Failed to set key "${key}" in Memcache`, 'MEMCACHE_SET_ERROR', 'memcache', err);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Delete a key from Memcache
|
|
136
|
+
*/
|
|
137
|
+
async delete(key) {
|
|
138
|
+
try {
|
|
139
|
+
await this.ensureConnected();
|
|
140
|
+
const fullKey = this.buildKey(key);
|
|
141
|
+
return new Promise((resolve, reject) => {
|
|
142
|
+
this.client.del(fullKey, (err) => {
|
|
143
|
+
if (err) {
|
|
144
|
+
reject(err);
|
|
145
|
+
}
|
|
146
|
+
else {
|
|
147
|
+
this.recordDelete();
|
|
148
|
+
resolve(true);
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
catch (err) {
|
|
154
|
+
throw new errors_1.CacheError(`Failed to delete key "${key}" from Memcache`, 'MEMCACHE_DELETE_ERROR', 'memcache', err);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Check if key exists
|
|
159
|
+
*/
|
|
160
|
+
async exists(key) {
|
|
161
|
+
try {
|
|
162
|
+
const value = await this.get(key);
|
|
163
|
+
return value !== null;
|
|
164
|
+
}
|
|
165
|
+
catch (err) {
|
|
166
|
+
throw new errors_1.CacheError(`Failed to check existence of key "${key}" in Memcache`, 'MEMCACHE_EXISTS_ERROR', 'memcache', err);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Clear all keys (Memcache limitation: flushes entire cache)
|
|
171
|
+
*/
|
|
172
|
+
async clear() {
|
|
173
|
+
try {
|
|
174
|
+
await this.ensureConnected();
|
|
175
|
+
return new Promise((resolve, reject) => {
|
|
176
|
+
this.client.flush((err) => {
|
|
177
|
+
if (err) {
|
|
178
|
+
reject(err);
|
|
179
|
+
}
|
|
180
|
+
else {
|
|
181
|
+
resolve();
|
|
182
|
+
}
|
|
183
|
+
});
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
catch (err) {
|
|
187
|
+
throw new errors_1.CacheError('Failed to clear Memcache', 'MEMCACHE_CLEAR_ERROR', 'memcache', err);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Get multiple values at once
|
|
192
|
+
*/
|
|
193
|
+
async getMultiple(keys) {
|
|
194
|
+
try {
|
|
195
|
+
await this.ensureConnected();
|
|
196
|
+
const fullKeys = keys.map(k => this.buildKey(k));
|
|
197
|
+
return new Promise((resolve, reject) => {
|
|
198
|
+
this.client.getMulti(fullKeys, (err, data) => {
|
|
199
|
+
if (err) {
|
|
200
|
+
reject(err);
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
const result = {};
|
|
204
|
+
keys.forEach((key) => {
|
|
205
|
+
const fullKey = this.buildKey(key);
|
|
206
|
+
if (fullKey in data) {
|
|
207
|
+
this.recordHit();
|
|
208
|
+
try {
|
|
209
|
+
result[key] = this.deserialize(data[fullKey]);
|
|
210
|
+
}
|
|
211
|
+
catch (parseErr) {
|
|
212
|
+
reject(parseErr);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
else {
|
|
216
|
+
this.recordMiss();
|
|
217
|
+
result[key] = null;
|
|
218
|
+
}
|
|
219
|
+
});
|
|
220
|
+
resolve(result);
|
|
221
|
+
});
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
catch (err) {
|
|
225
|
+
throw new errors_1.CacheError('Failed to get multiple keys from Memcache', 'MEMCACHE_GET_MULTIPLE_ERROR', 'memcache', err);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Set multiple values at once
|
|
230
|
+
*/
|
|
231
|
+
async setMultiple(data, ttl) {
|
|
232
|
+
try {
|
|
233
|
+
await this.ensureConnected();
|
|
234
|
+
const expiry = ttl ?? this.ttl;
|
|
235
|
+
const promises = [];
|
|
236
|
+
for (const [key, value] of Object.entries(data)) {
|
|
237
|
+
const fullKey = this.buildKey(key);
|
|
238
|
+
const serialized = this.serialize(value);
|
|
239
|
+
promises.push(new Promise((resolve, reject) => {
|
|
240
|
+
this.client.set(fullKey, serialized, expiry, (err) => {
|
|
241
|
+
if (err)
|
|
242
|
+
reject(err);
|
|
243
|
+
else
|
|
244
|
+
resolve();
|
|
245
|
+
});
|
|
246
|
+
}));
|
|
247
|
+
}
|
|
248
|
+
return Promise.all(promises).then(() => {
|
|
249
|
+
this.stats.sets += Object.keys(data).length;
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
catch (err) {
|
|
253
|
+
throw new errors_1.CacheError('Failed to set multiple keys in Memcache', 'MEMCACHE_SET_MULTIPLE_ERROR', 'memcache', err);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
/**
|
|
257
|
+
* Delete multiple keys at once
|
|
258
|
+
*/
|
|
259
|
+
async deleteMultiple(keys) {
|
|
260
|
+
try {
|
|
261
|
+
await this.ensureConnected();
|
|
262
|
+
const fullKeys = keys.map(k => this.buildKey(k));
|
|
263
|
+
let deletedCount = 0;
|
|
264
|
+
await Promise.all(fullKeys.map(key => new Promise((resolve, reject) => {
|
|
265
|
+
this.client.del(key, (err) => {
|
|
266
|
+
if (err) {
|
|
267
|
+
reject(err);
|
|
268
|
+
}
|
|
269
|
+
else {
|
|
270
|
+
deletedCount++;
|
|
271
|
+
resolve();
|
|
272
|
+
}
|
|
273
|
+
});
|
|
274
|
+
})));
|
|
275
|
+
this.stats.deletes += deletedCount;
|
|
276
|
+
return deletedCount;
|
|
277
|
+
}
|
|
278
|
+
catch (err) {
|
|
279
|
+
throw new errors_1.CacheError('Failed to delete multiple keys from Memcache', 'MEMCACHE_DELETE_MULTIPLE_ERROR', 'memcache', err);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* Increment a numeric value (not natively supported by Memcache in this library)
|
|
284
|
+
*/
|
|
285
|
+
async increment(key, amount = 1) {
|
|
286
|
+
try {
|
|
287
|
+
const current = await this.get(key);
|
|
288
|
+
const value = (typeof current === 'number' ? current : 0) + amount;
|
|
289
|
+
await this.set(key, value);
|
|
290
|
+
return value;
|
|
291
|
+
}
|
|
292
|
+
catch (err) {
|
|
293
|
+
throw new errors_1.CacheError(`Failed to increment key "${key}" in Memcache`, 'MEMCACHE_INCREMENT_ERROR', 'memcache', err);
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
/**
|
|
297
|
+
* Decrement a numeric value
|
|
298
|
+
*/
|
|
299
|
+
async decrement(key, amount = 1) {
|
|
300
|
+
try {
|
|
301
|
+
const current = await this.get(key);
|
|
302
|
+
const value = (typeof current === 'number' ? current : 0) - amount;
|
|
303
|
+
await this.set(key, value);
|
|
304
|
+
return value;
|
|
305
|
+
}
|
|
306
|
+
catch (err) {
|
|
307
|
+
throw new errors_1.CacheError(`Failed to decrement key "${key}" in Memcache`, 'MEMCACHE_DECREMENT_ERROR', 'memcache', err);
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
/**
|
|
311
|
+
* Check if Memcache is alive
|
|
312
|
+
*/
|
|
313
|
+
async isAlive() {
|
|
314
|
+
try {
|
|
315
|
+
await this.ping();
|
|
316
|
+
return {
|
|
317
|
+
isAlive: true,
|
|
318
|
+
adapter: 'memcache',
|
|
319
|
+
timestamp: new Date()
|
|
320
|
+
};
|
|
321
|
+
}
|
|
322
|
+
catch (err) {
|
|
323
|
+
return {
|
|
324
|
+
isAlive: false,
|
|
325
|
+
adapter: 'memcache',
|
|
326
|
+
timestamp: new Date(),
|
|
327
|
+
error: err.message
|
|
328
|
+
};
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
/**
|
|
332
|
+
* Close Memcache connection
|
|
333
|
+
*/
|
|
334
|
+
async close() {
|
|
335
|
+
try {
|
|
336
|
+
if (this.client && this.isConnected) {
|
|
337
|
+
this.client.end();
|
|
338
|
+
this.isConnected = false;
|
|
339
|
+
this.client = null;
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
catch (err) {
|
|
343
|
+
throw new errors_1.CacheError('Failed to close Memcache connection', 'MEMCACHE_CLOSE_ERROR', 'memcache', err);
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
exports.MemcacheCache = MemcacheCache;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { MemcacheCache } from './MemcacheCache';
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MemcacheCache = void 0;
|
|
4
|
+
var MemcacheCache_1 = require("./MemcacheCache");
|
|
5
|
+
Object.defineProperty(exports, "MemcacheCache", { enumerable: true, get: function () { return MemcacheCache_1.MemcacheCache; } });
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import type { MemoryCacheConfig, HealthCheckResponse } from '../../types';
|
|
2
|
+
import { BaseCache } from '../../core/BaseCache';
|
|
3
|
+
/**
|
|
4
|
+
* In-memory cache adapter for development and testing
|
|
5
|
+
*/
|
|
6
|
+
export declare class MemoryCache<T = unknown> extends BaseCache<T> {
|
|
7
|
+
private memoryCacheConfig;
|
|
8
|
+
private store;
|
|
9
|
+
private cleanupInterval;
|
|
10
|
+
constructor(memoryCacheConfig: MemoryCacheConfig);
|
|
11
|
+
/**
|
|
12
|
+
* Start periodic cleanup of expired items
|
|
13
|
+
*/
|
|
14
|
+
private startCleanup;
|
|
15
|
+
/**
|
|
16
|
+
* Get a value from memory
|
|
17
|
+
*/
|
|
18
|
+
get(key: string): Promise<T | null>;
|
|
19
|
+
/**
|
|
20
|
+
* Set a value in memory
|
|
21
|
+
*/
|
|
22
|
+
set(key: string, value: T, ttl?: number): Promise<void>;
|
|
23
|
+
/**
|
|
24
|
+
* Delete a key from memory
|
|
25
|
+
*/
|
|
26
|
+
delete(key: string): Promise<boolean>;
|
|
27
|
+
/**
|
|
28
|
+
* Check if key exists
|
|
29
|
+
*/
|
|
30
|
+
exists(key: string): Promise<boolean>;
|
|
31
|
+
/**
|
|
32
|
+
* Clear all keys with current namespace
|
|
33
|
+
*/
|
|
34
|
+
clear(): Promise<void>;
|
|
35
|
+
/**
|
|
36
|
+
* Get multiple values at once
|
|
37
|
+
*/
|
|
38
|
+
getMultiple(keys: string[]): Promise<Record<string, T | null>>;
|
|
39
|
+
/**
|
|
40
|
+
* Set multiple values at once
|
|
41
|
+
*/
|
|
42
|
+
setMultiple(data: Record<string, T>, ttl?: number): Promise<void>;
|
|
43
|
+
/**
|
|
44
|
+
* Delete multiple keys at once
|
|
45
|
+
*/
|
|
46
|
+
deleteMultiple(keys: string[]): Promise<number>;
|
|
47
|
+
/**
|
|
48
|
+
* Increment a numeric value
|
|
49
|
+
*/
|
|
50
|
+
increment(key: string, amount?: number): Promise<number>;
|
|
51
|
+
/**
|
|
52
|
+
* Decrement a numeric value
|
|
53
|
+
*/
|
|
54
|
+
decrement(key: string, amount?: number): Promise<number>;
|
|
55
|
+
/**
|
|
56
|
+
* Check if memory cache is alive
|
|
57
|
+
*/
|
|
58
|
+
isAlive(): Promise<HealthCheckResponse>;
|
|
59
|
+
/**
|
|
60
|
+
* Close memory cache
|
|
61
|
+
*/
|
|
62
|
+
close(): Promise<void>;
|
|
63
|
+
}
|
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MemoryCache = void 0;
|
|
4
|
+
const BaseCache_1 = require("../../core/BaseCache");
|
|
5
|
+
const errors_1 = require("../../errors");
|
|
6
|
+
/**
|
|
7
|
+
* In-memory cache adapter for development and testing
|
|
8
|
+
*/
|
|
9
|
+
class MemoryCache extends BaseCache_1.BaseCache {
|
|
10
|
+
constructor(memoryCacheConfig) {
|
|
11
|
+
super(memoryCacheConfig);
|
|
12
|
+
this.memoryCacheConfig = memoryCacheConfig;
|
|
13
|
+
this.store = new Map();
|
|
14
|
+
this.cleanupInterval = null;
|
|
15
|
+
this.startCleanup();
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Start periodic cleanup of expired items
|
|
19
|
+
*/
|
|
20
|
+
startCleanup() {
|
|
21
|
+
if (this.cleanupInterval)
|
|
22
|
+
return;
|
|
23
|
+
this.cleanupInterval = setInterval(() => {
|
|
24
|
+
const now = Date.now();
|
|
25
|
+
for (const [key, entry] of this.store.entries()) {
|
|
26
|
+
if (entry.expiresAt && entry.expiresAt < now) {
|
|
27
|
+
this.store.delete(key);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}, 30000); // Cleanup every 30 seconds
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Get a value from memory
|
|
34
|
+
*/
|
|
35
|
+
async get(key) {
|
|
36
|
+
try {
|
|
37
|
+
const fullKey = this.buildKey(key);
|
|
38
|
+
const entry = this.store.get(fullKey);
|
|
39
|
+
if (!entry) {
|
|
40
|
+
this.recordMiss();
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
// Check if expired
|
|
44
|
+
if (entry.expiresAt && entry.expiresAt < Date.now()) {
|
|
45
|
+
this.store.delete(fullKey);
|
|
46
|
+
this.recordMiss();
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
this.recordHit();
|
|
50
|
+
return entry.value;
|
|
51
|
+
}
|
|
52
|
+
catch (err) {
|
|
53
|
+
throw new errors_1.CacheError(`Failed to get key "${key}" from memory cache`, 'MEMORY_GET_ERROR', 'memory', err);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Set a value in memory
|
|
58
|
+
*/
|
|
59
|
+
async set(key, value, ttl) {
|
|
60
|
+
try {
|
|
61
|
+
const fullKey = this.buildKey(key);
|
|
62
|
+
const expiry = ttl ?? this.ttl;
|
|
63
|
+
const expiresAt = expiry > 0 ? Date.now() + expiry * 1000 : undefined;
|
|
64
|
+
// Check max size
|
|
65
|
+
const maxSize = this.memoryCacheConfig.maxSize;
|
|
66
|
+
if (maxSize && this.store.size >= maxSize && !this.store.has(fullKey)) {
|
|
67
|
+
// Remove oldest entry
|
|
68
|
+
const firstKey = this.store.keys().next().value;
|
|
69
|
+
if (firstKey) {
|
|
70
|
+
this.store.delete(firstKey);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
this.store.set(fullKey, { value, expiresAt });
|
|
74
|
+
this.recordSet();
|
|
75
|
+
}
|
|
76
|
+
catch (err) {
|
|
77
|
+
throw new errors_1.CacheError(`Failed to set key "${key}" in memory cache`, 'MEMORY_SET_ERROR', 'memory', err);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Delete a key from memory
|
|
82
|
+
*/
|
|
83
|
+
async delete(key) {
|
|
84
|
+
try {
|
|
85
|
+
const fullKey = this.buildKey(key);
|
|
86
|
+
const deleted = this.store.delete(fullKey);
|
|
87
|
+
if (deleted) {
|
|
88
|
+
this.recordDelete();
|
|
89
|
+
}
|
|
90
|
+
return deleted;
|
|
91
|
+
}
|
|
92
|
+
catch (err) {
|
|
93
|
+
throw new errors_1.CacheError(`Failed to delete key "${key}" from memory cache`, 'MEMORY_DELETE_ERROR', 'memory', err);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Check if key exists
|
|
98
|
+
*/
|
|
99
|
+
async exists(key) {
|
|
100
|
+
try {
|
|
101
|
+
const fullKey = this.buildKey(key);
|
|
102
|
+
const entry = this.store.get(fullKey);
|
|
103
|
+
if (!entry) {
|
|
104
|
+
return false;
|
|
105
|
+
}
|
|
106
|
+
// Check if expired
|
|
107
|
+
if (entry.expiresAt && entry.expiresAt < Date.now()) {
|
|
108
|
+
this.store.delete(fullKey);
|
|
109
|
+
return false;
|
|
110
|
+
}
|
|
111
|
+
return true;
|
|
112
|
+
}
|
|
113
|
+
catch (err) {
|
|
114
|
+
throw new errors_1.CacheError(`Failed to check existence of key "${key}" in memory cache`, 'MEMORY_EXISTS_ERROR', 'memory', err);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Clear all keys with current namespace
|
|
119
|
+
*/
|
|
120
|
+
async clear() {
|
|
121
|
+
try {
|
|
122
|
+
if (this.namespace) {
|
|
123
|
+
// Clear only keys with current namespace
|
|
124
|
+
for (const key of this.store.keys()) {
|
|
125
|
+
if (key.startsWith(this.namespace)) {
|
|
126
|
+
this.store.delete(key);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
// Clear all
|
|
132
|
+
this.store.clear();
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
catch (err) {
|
|
136
|
+
throw new errors_1.CacheError('Failed to clear memory cache', 'MEMORY_CLEAR_ERROR', 'memory', err);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Get multiple values at once
|
|
141
|
+
*/
|
|
142
|
+
async getMultiple(keys) {
|
|
143
|
+
try {
|
|
144
|
+
const result = {};
|
|
145
|
+
const now = Date.now();
|
|
146
|
+
for (const key of keys) {
|
|
147
|
+
const fullKey = this.buildKey(key);
|
|
148
|
+
const entry = this.store.get(fullKey);
|
|
149
|
+
if (!entry) {
|
|
150
|
+
this.recordMiss();
|
|
151
|
+
result[key] = null;
|
|
152
|
+
continue;
|
|
153
|
+
}
|
|
154
|
+
// Check if expired
|
|
155
|
+
if (entry.expiresAt && entry.expiresAt < now) {
|
|
156
|
+
this.store.delete(fullKey);
|
|
157
|
+
this.recordMiss();
|
|
158
|
+
result[key] = null;
|
|
159
|
+
}
|
|
160
|
+
else {
|
|
161
|
+
this.recordHit();
|
|
162
|
+
result[key] = entry.value;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
return result;
|
|
166
|
+
}
|
|
167
|
+
catch (err) {
|
|
168
|
+
throw new errors_1.CacheError('Failed to get multiple keys from memory cache', 'MEMORY_GET_MULTIPLE_ERROR', 'memory', err);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Set multiple values at once
|
|
173
|
+
*/
|
|
174
|
+
async setMultiple(data, ttl) {
|
|
175
|
+
try {
|
|
176
|
+
const expiry = ttl ?? this.ttl;
|
|
177
|
+
const expiresAt = expiry > 0 ? Date.now() + expiry * 1000 : undefined;
|
|
178
|
+
for (const [key, value] of Object.entries(data)) {
|
|
179
|
+
const fullKey = this.buildKey(key);
|
|
180
|
+
this.store.set(fullKey, { value, expiresAt });
|
|
181
|
+
}
|
|
182
|
+
this.stats.sets += Object.keys(data).length;
|
|
183
|
+
}
|
|
184
|
+
catch (err) {
|
|
185
|
+
throw new errors_1.CacheError('Failed to set multiple keys in memory cache', 'MEMORY_SET_MULTIPLE_ERROR', 'memory', err);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Delete multiple keys at once
|
|
190
|
+
*/
|
|
191
|
+
async deleteMultiple(keys) {
|
|
192
|
+
try {
|
|
193
|
+
let count = 0;
|
|
194
|
+
for (const key of keys) {
|
|
195
|
+
const fullKey = this.buildKey(key);
|
|
196
|
+
if (this.store.delete(fullKey)) {
|
|
197
|
+
count++;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
this.stats.deletes += count;
|
|
201
|
+
return count;
|
|
202
|
+
}
|
|
203
|
+
catch (err) {
|
|
204
|
+
throw new errors_1.CacheError('Failed to delete multiple keys from memory cache', 'MEMORY_DELETE_MULTIPLE_ERROR', 'memory', err);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Increment a numeric value
|
|
209
|
+
*/
|
|
210
|
+
async increment(key, amount = 1) {
|
|
211
|
+
try {
|
|
212
|
+
const fullKey = this.buildKey(key);
|
|
213
|
+
const entry = this.store.get(fullKey);
|
|
214
|
+
const current = entry && (!entry.expiresAt || entry.expiresAt >= Date.now())
|
|
215
|
+
? (typeof entry.value === 'number' ? entry.value : 0)
|
|
216
|
+
: 0;
|
|
217
|
+
const value = current + amount;
|
|
218
|
+
const expiry = this.ttl;
|
|
219
|
+
const expiresAt = expiry > 0 ? Date.now() + expiry * 1000 : undefined;
|
|
220
|
+
this.store.set(fullKey, { value: value, expiresAt });
|
|
221
|
+
return value;
|
|
222
|
+
}
|
|
223
|
+
catch (err) {
|
|
224
|
+
throw new errors_1.CacheError(`Failed to increment key "${key}" in memory cache`, 'MEMORY_INCREMENT_ERROR', 'memory', err);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Decrement a numeric value
|
|
229
|
+
*/
|
|
230
|
+
async decrement(key, amount = 1) {
|
|
231
|
+
try {
|
|
232
|
+
const fullKey = this.buildKey(key);
|
|
233
|
+
const entry = this.store.get(fullKey);
|
|
234
|
+
const current = entry && (!entry.expiresAt || entry.expiresAt >= Date.now())
|
|
235
|
+
? (typeof entry.value === 'number' ? entry.value : 0)
|
|
236
|
+
: 0;
|
|
237
|
+
const value = current - amount;
|
|
238
|
+
const expiry = this.ttl;
|
|
239
|
+
const expiresAt = expiry > 0 ? Date.now() + expiry * 1000 : undefined;
|
|
240
|
+
this.store.set(fullKey, { value: value, expiresAt });
|
|
241
|
+
return value;
|
|
242
|
+
}
|
|
243
|
+
catch (err) {
|
|
244
|
+
throw new errors_1.CacheError(`Failed to decrement key "${key}" in memory cache`, 'MEMORY_DECREMENT_ERROR', 'memory', err);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* Check if memory cache is alive
|
|
249
|
+
*/
|
|
250
|
+
async isAlive() {
|
|
251
|
+
return {
|
|
252
|
+
isAlive: true,
|
|
253
|
+
adapter: 'memory',
|
|
254
|
+
timestamp: new Date()
|
|
255
|
+
};
|
|
256
|
+
}
|
|
257
|
+
/**
|
|
258
|
+
* Close memory cache
|
|
259
|
+
*/
|
|
260
|
+
async close() {
|
|
261
|
+
try {
|
|
262
|
+
if (this.cleanupInterval) {
|
|
263
|
+
clearInterval(this.cleanupInterval);
|
|
264
|
+
this.cleanupInterval = null;
|
|
265
|
+
}
|
|
266
|
+
this.store.clear();
|
|
267
|
+
}
|
|
268
|
+
catch (err) {
|
|
269
|
+
throw new errors_1.CacheError('Failed to close memory cache', 'MEMORY_CLOSE_ERROR', 'memory', err);
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
exports.MemoryCache = MemoryCache;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { MemoryCache } from './MemoryCache';
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MemoryCache = void 0;
|
|
4
|
+
var MemoryCache_1 = require("./MemoryCache");
|
|
5
|
+
Object.defineProperty(exports, "MemoryCache", { enumerable: true, get: function () { return MemoryCache_1.MemoryCache; } });
|