ts-cache-mongoose 2.0.0 → 2.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 +14 -15
- package/dist/index.cjs +84 -118
- package/dist/index.d.cts +48 -10
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +48 -10
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +84 -118
- package/dist/nest/index.cjs +3 -1
- package/dist/nest/index.mjs +3 -1
- package/package.json +2 -2
- package/src/cache/Cache.ts +4 -4
- package/src/cache/engine/MemoryCacheEngine.ts +3 -3
- package/src/cache/engine/RedisCacheEngine.ts +3 -3
- package/src/extend/aggregate.ts +5 -6
- package/src/extend/query.ts +5 -6
- package/src/index.ts +7 -7
- package/src/ms.ts +46 -35
- package/src/types.ts +4 -3
- package/tests/ms.test.ts +69 -49
- package/tsconfig.json +2 -3
package/dist/index.mjs
CHANGED
|
@@ -9,65 +9,62 @@ const h = m * 60;
|
|
|
9
9
|
const d = h * 24;
|
|
10
10
|
const w = d * 7;
|
|
11
11
|
const y = d * 365.25;
|
|
12
|
-
const
|
|
12
|
+
const mo = y / 12;
|
|
13
13
|
const UNITS = {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
weeks: w,
|
|
20
|
-
week: w,
|
|
21
|
-
w,
|
|
22
|
-
days: d,
|
|
23
|
-
day: d,
|
|
24
|
-
d,
|
|
25
|
-
hours: h,
|
|
26
|
-
hour: h,
|
|
27
|
-
hrs: h,
|
|
28
|
-
hr: h,
|
|
29
|
-
h,
|
|
30
|
-
minutes: m,
|
|
31
|
-
minute: m,
|
|
32
|
-
mins: m,
|
|
33
|
-
min: m,
|
|
34
|
-
m,
|
|
14
|
+
milliseconds: 1,
|
|
15
|
+
millisecond: 1,
|
|
16
|
+
msecs: 1,
|
|
17
|
+
msec: 1,
|
|
18
|
+
ms: 1,
|
|
35
19
|
seconds: s,
|
|
36
20
|
second: s,
|
|
37
21
|
secs: s,
|
|
38
22
|
sec: s,
|
|
39
23
|
s,
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
24
|
+
minutes: m,
|
|
25
|
+
minute: m,
|
|
26
|
+
mins: m,
|
|
27
|
+
min: m,
|
|
28
|
+
m,
|
|
29
|
+
hours: h,
|
|
30
|
+
hour: h,
|
|
31
|
+
hrs: h,
|
|
32
|
+
hr: h,
|
|
33
|
+
h,
|
|
34
|
+
days: d,
|
|
35
|
+
day: d,
|
|
36
|
+
d,
|
|
37
|
+
weeks: w,
|
|
38
|
+
week: w,
|
|
39
|
+
w,
|
|
40
|
+
months: mo,
|
|
41
|
+
month: mo,
|
|
42
|
+
mo,
|
|
43
|
+
years: y,
|
|
44
|
+
year: y,
|
|
45
|
+
yrs: y,
|
|
46
|
+
yr: y,
|
|
47
|
+
y
|
|
45
48
|
};
|
|
49
|
+
const unitPattern = Object.keys(UNITS).sort((a, b) => b.length - a.length).join("|");
|
|
50
|
+
const RE = new RegExp(String.raw`^(-?(?:\d+)?\.?\d+)\s*(${unitPattern})?$`, "i");
|
|
46
51
|
const ms = (val) => {
|
|
47
52
|
const str = String(val);
|
|
48
|
-
if (str.length > 100) return
|
|
53
|
+
if (str.length > 100) return Number.NaN;
|
|
49
54
|
const match = RE.exec(str);
|
|
50
|
-
if (!match) return
|
|
55
|
+
if (!match) return Number.NaN;
|
|
51
56
|
const n = Number.parseFloat(match[1] ?? "");
|
|
52
57
|
const type = (match[2] ?? "ms").toLowerCase();
|
|
53
58
|
return n * (UNITS[type] ?? 0);
|
|
54
59
|
};
|
|
55
60
|
|
|
56
|
-
var __typeError$3 = (msg) => {
|
|
57
|
-
throw TypeError(msg);
|
|
58
|
-
};
|
|
59
|
-
var __accessCheck$3 = (obj, member, msg) => member.has(obj) || __typeError$3("Cannot " + msg);
|
|
60
|
-
var __privateGet$3 = (obj, member, getter) => (__accessCheck$3(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
|
|
61
|
-
var __privateAdd$3 = (obj, member, value) => member.has(obj) ? __typeError$3("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
|
|
62
|
-
var __privateSet$3 = (obj, member, value, setter) => (__accessCheck$3(obj, member, "write to private field"), member.set(obj, value), value);
|
|
63
|
-
var _cache;
|
|
64
61
|
class MemoryCacheEngine {
|
|
62
|
+
#cache;
|
|
65
63
|
constructor() {
|
|
66
|
-
|
|
67
|
-
__privateSet$3(this, _cache, /* @__PURE__ */ new Map());
|
|
64
|
+
this.#cache = /* @__PURE__ */ new Map();
|
|
68
65
|
}
|
|
69
66
|
get(key) {
|
|
70
|
-
const item =
|
|
67
|
+
const item = this.#cache.get(key);
|
|
71
68
|
if (!item || item.expiresAt < Date.now()) {
|
|
72
69
|
this.del(key);
|
|
73
70
|
return void 0;
|
|
@@ -75,23 +72,22 @@ class MemoryCacheEngine {
|
|
|
75
72
|
return item.value;
|
|
76
73
|
}
|
|
77
74
|
set(key, value, ttl) {
|
|
78
|
-
const givenTTL =
|
|
75
|
+
const givenTTL = ttl == null ? void 0 : ms(ttl);
|
|
79
76
|
const actualTTL = givenTTL ?? Number.POSITIVE_INFINITY;
|
|
80
|
-
|
|
77
|
+
this.#cache.set(key, {
|
|
81
78
|
value,
|
|
82
79
|
expiresAt: Date.now() + actualTTL
|
|
83
80
|
});
|
|
84
81
|
}
|
|
85
82
|
del(key) {
|
|
86
|
-
|
|
83
|
+
this.#cache.delete(key);
|
|
87
84
|
}
|
|
88
85
|
clear() {
|
|
89
|
-
|
|
86
|
+
this.#cache.clear();
|
|
90
87
|
}
|
|
91
88
|
close() {
|
|
92
89
|
}
|
|
93
90
|
}
|
|
94
|
-
_cache = new WeakMap();
|
|
95
91
|
|
|
96
92
|
const isMongooseLessThan7 = Number.parseInt(mongoose.version, 10) < 7;
|
|
97
93
|
const convertToObject = (value) => {
|
|
@@ -106,23 +102,15 @@ const convertToObject = (value) => {
|
|
|
106
102
|
return value;
|
|
107
103
|
};
|
|
108
104
|
|
|
109
|
-
var __typeError$2 = (msg) => {
|
|
110
|
-
throw TypeError(msg);
|
|
111
|
-
};
|
|
112
|
-
var __accessCheck$2 = (obj, member, msg) => member.has(obj) || __typeError$2("Cannot " + msg);
|
|
113
|
-
var __privateGet$2 = (obj, member, getter) => (__accessCheck$2(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
|
|
114
|
-
var __privateAdd$2 = (obj, member, value) => member.has(obj) ? __typeError$2("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
|
|
115
|
-
var __privateSet$2 = (obj, member, value, setter) => (__accessCheck$2(obj, member, "write to private field"), member.set(obj, value), value);
|
|
116
|
-
var _client;
|
|
117
105
|
class RedisCacheEngine {
|
|
106
|
+
#client;
|
|
118
107
|
constructor(options) {
|
|
119
|
-
__privateAdd$2(this, _client);
|
|
120
108
|
options.keyPrefix ??= "cache-mongoose:";
|
|
121
|
-
|
|
109
|
+
this.#client = new IORedis(options);
|
|
122
110
|
}
|
|
123
111
|
async get(key) {
|
|
124
112
|
try {
|
|
125
|
-
const value = await
|
|
113
|
+
const value = await this.#client.get(key);
|
|
126
114
|
if (value === null) {
|
|
127
115
|
return void 0;
|
|
128
116
|
}
|
|
@@ -134,92 +122,79 @@ class RedisCacheEngine {
|
|
|
134
122
|
}
|
|
135
123
|
async set(key, value, ttl) {
|
|
136
124
|
try {
|
|
137
|
-
const givenTTL =
|
|
125
|
+
const givenTTL = ttl == null ? void 0 : ms(ttl);
|
|
138
126
|
const actualTTL = givenTTL ?? Number.POSITIVE_INFINITY;
|
|
139
127
|
const serializedValue = EJSON.stringify(convertToObject(value));
|
|
140
|
-
await
|
|
128
|
+
await this.#client.setex(key, Math.ceil(actualTTL / 1e3), serializedValue);
|
|
141
129
|
} catch (err) {
|
|
142
130
|
console.error(err);
|
|
143
131
|
}
|
|
144
132
|
}
|
|
145
133
|
async del(key) {
|
|
146
|
-
await
|
|
134
|
+
await this.#client.del(key);
|
|
147
135
|
}
|
|
148
136
|
async clear() {
|
|
149
|
-
await
|
|
137
|
+
await this.#client.flushdb();
|
|
150
138
|
}
|
|
151
139
|
async close() {
|
|
152
|
-
await
|
|
140
|
+
await this.#client.quit();
|
|
153
141
|
}
|
|
154
142
|
}
|
|
155
|
-
_client = new WeakMap();
|
|
156
143
|
|
|
157
|
-
var __typeError$1 = (msg) => {
|
|
158
|
-
throw TypeError(msg);
|
|
159
|
-
};
|
|
160
|
-
var __accessCheck$1 = (obj, member, msg) => member.has(obj) || __typeError$1("Cannot " + msg);
|
|
161
|
-
var __privateGet$1 = (obj, member, getter) => (__accessCheck$1(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
|
|
162
|
-
var __privateAdd$1 = (obj, member, value) => member.has(obj) ? __typeError$1("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
|
|
163
|
-
var __privateSet$1 = (obj, member, value, setter) => (__accessCheck$1(obj, member, "write to private field"), member.set(obj, value), value);
|
|
164
|
-
var _engine, _defaultTTL, _debug, _engines;
|
|
165
144
|
class Cache {
|
|
145
|
+
#engine;
|
|
146
|
+
#defaultTTL;
|
|
147
|
+
#debug;
|
|
148
|
+
#engines = ["memory", "redis"];
|
|
166
149
|
constructor(cacheOptions) {
|
|
167
|
-
|
|
168
|
-
__privateAdd$1(this, _defaultTTL);
|
|
169
|
-
__privateAdd$1(this, _debug);
|
|
170
|
-
__privateAdd$1(this, _engines, ["memory", "redis"]);
|
|
171
|
-
if (!__privateGet$1(this, _engines).includes(cacheOptions.engine)) {
|
|
150
|
+
if (!this.#engines.includes(cacheOptions.engine)) {
|
|
172
151
|
throw new Error(`Invalid engine name: ${cacheOptions.engine}`);
|
|
173
152
|
}
|
|
174
153
|
if (cacheOptions.engine === "redis" && !cacheOptions.engineOptions) {
|
|
175
154
|
throw new Error(`Engine options are required for ${cacheOptions.engine} engine`);
|
|
176
155
|
}
|
|
177
156
|
cacheOptions.defaultTTL ??= "1 minute";
|
|
178
|
-
|
|
157
|
+
this.#defaultTTL = ms(cacheOptions.defaultTTL);
|
|
179
158
|
if (cacheOptions.engine === "redis" && cacheOptions.engineOptions) {
|
|
180
|
-
|
|
159
|
+
this.#engine = new RedisCacheEngine(cacheOptions.engineOptions);
|
|
181
160
|
}
|
|
182
161
|
if (cacheOptions.engine === "memory") {
|
|
183
|
-
|
|
162
|
+
this.#engine = new MemoryCacheEngine();
|
|
184
163
|
}
|
|
185
|
-
|
|
164
|
+
this.#debug = cacheOptions.debug === true;
|
|
186
165
|
}
|
|
187
166
|
async get(key) {
|
|
188
|
-
const cacheEntry = await
|
|
189
|
-
if (
|
|
167
|
+
const cacheEntry = await this.#engine.get(key);
|
|
168
|
+
if (this.#debug) {
|
|
190
169
|
const cacheHit = cacheEntry == null ? "MISS" : "HIT";
|
|
191
170
|
console.log(`[ts-cache-mongoose] GET '${key}' - ${cacheHit}`);
|
|
192
171
|
}
|
|
193
172
|
return cacheEntry;
|
|
194
173
|
}
|
|
195
174
|
async set(key, value, ttl) {
|
|
196
|
-
const givenTTL =
|
|
197
|
-
const actualTTL = givenTTL ??
|
|
198
|
-
await
|
|
199
|
-
if (
|
|
175
|
+
const givenTTL = ttl == null ? null : ms(ttl);
|
|
176
|
+
const actualTTL = givenTTL ?? this.#defaultTTL;
|
|
177
|
+
await this.#engine.set(key, value, actualTTL);
|
|
178
|
+
if (this.#debug) {
|
|
200
179
|
console.log(`[ts-cache-mongoose] SET '${key}' - ttl: ${actualTTL.toFixed(0)} ms`);
|
|
201
180
|
}
|
|
202
181
|
}
|
|
203
182
|
async del(key) {
|
|
204
|
-
await
|
|
205
|
-
if (
|
|
183
|
+
await this.#engine.del(key);
|
|
184
|
+
if (this.#debug) {
|
|
206
185
|
console.log(`[ts-cache-mongoose] DEL '${key}'`);
|
|
207
186
|
}
|
|
208
187
|
}
|
|
209
188
|
async clear() {
|
|
210
|
-
await
|
|
211
|
-
if (
|
|
189
|
+
await this.#engine.clear();
|
|
190
|
+
if (this.#debug) {
|
|
212
191
|
console.log("[ts-cache-mongoose] CLEAR");
|
|
213
192
|
}
|
|
214
193
|
}
|
|
215
194
|
async close() {
|
|
216
|
-
return
|
|
195
|
+
return this.#engine.close();
|
|
217
196
|
}
|
|
218
197
|
}
|
|
219
|
-
_engine = new WeakMap();
|
|
220
|
-
_defaultTTL = new WeakMap();
|
|
221
|
-
_debug = new WeakMap();
|
|
222
|
-
_engines = new WeakMap();
|
|
223
198
|
|
|
224
199
|
const isPlainObject = (value) => {
|
|
225
200
|
if (typeof value !== "object" || value === null) return false;
|
|
@@ -271,7 +246,7 @@ function extendAggregate(mongoose, cache) {
|
|
|
271
246
|
pipeline: this.pipeline()
|
|
272
247
|
});
|
|
273
248
|
};
|
|
274
|
-
mongoose.Aggregate.prototype.
|
|
249
|
+
mongoose.Aggregate.prototype.getDuration = function() {
|
|
275
250
|
return this._ttl;
|
|
276
251
|
};
|
|
277
252
|
mongoose.Aggregate.prototype.cache = function(ttl, customKey) {
|
|
@@ -280,11 +255,11 @@ function extendAggregate(mongoose, cache) {
|
|
|
280
255
|
return this;
|
|
281
256
|
};
|
|
282
257
|
mongoose.Aggregate.prototype.exec = async function(...args) {
|
|
283
|
-
if (!Object.
|
|
258
|
+
if (!Object.hasOwn(this, "_ttl")) {
|
|
284
259
|
return mongooseExec.apply(this, args);
|
|
285
260
|
}
|
|
286
261
|
const key = this.getCacheKey();
|
|
287
|
-
const ttl = this.
|
|
262
|
+
const ttl = this.getDuration();
|
|
288
263
|
const resultCache = await cache.get(key).catch((err) => {
|
|
289
264
|
console.error(err);
|
|
290
265
|
});
|
|
@@ -320,7 +295,7 @@ function extendQuery(mongoose, cache) {
|
|
|
320
295
|
_conditions: this._conditions
|
|
321
296
|
});
|
|
322
297
|
};
|
|
323
|
-
mongoose.Query.prototype.
|
|
298
|
+
mongoose.Query.prototype.getDuration = function() {
|
|
324
299
|
return this._ttl;
|
|
325
300
|
};
|
|
326
301
|
mongoose.Query.prototype.cache = function(ttl, customKey) {
|
|
@@ -329,11 +304,11 @@ function extendQuery(mongoose, cache) {
|
|
|
329
304
|
return this;
|
|
330
305
|
};
|
|
331
306
|
mongoose.Query.prototype.exec = async function(...args) {
|
|
332
|
-
if (!Object.
|
|
307
|
+
if (!Object.hasOwn(this, "_ttl")) {
|
|
333
308
|
return mongooseExec.apply(this, args);
|
|
334
309
|
}
|
|
335
310
|
const key = this.getCacheKey();
|
|
336
|
-
const ttl = this.
|
|
311
|
+
const ttl = this.getDuration();
|
|
337
312
|
const mongooseOptions = this.mongooseOptions();
|
|
338
313
|
const isCount = this.op?.includes("count") ?? false;
|
|
339
314
|
const isDistinct = this.op === "distinct";
|
|
@@ -361,26 +336,20 @@ function extendQuery(mongoose, cache) {
|
|
|
361
336
|
};
|
|
362
337
|
}
|
|
363
338
|
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
|
|
368
|
-
var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
|
|
369
|
-
var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
|
|
370
|
-
var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), member.set(obj, value), value);
|
|
371
|
-
var _instance;
|
|
372
|
-
const _CacheMongoose = class _CacheMongoose {
|
|
339
|
+
class CacheMongoose {
|
|
340
|
+
static #instance;
|
|
341
|
+
cache;
|
|
373
342
|
constructor() {
|
|
374
343
|
}
|
|
375
344
|
static init(mongoose, cacheOptions) {
|
|
376
|
-
if (!
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
const cache =
|
|
345
|
+
if (!CacheMongoose.#instance) {
|
|
346
|
+
CacheMongoose.#instance = new CacheMongoose();
|
|
347
|
+
CacheMongoose.#instance.cache = new Cache(cacheOptions);
|
|
348
|
+
const cache = CacheMongoose.#instance.cache;
|
|
380
349
|
extendQuery(mongoose, cache);
|
|
381
350
|
extendAggregate(mongoose, cache);
|
|
382
351
|
}
|
|
383
|
-
return
|
|
352
|
+
return CacheMongoose.#instance;
|
|
384
353
|
}
|
|
385
354
|
async clear(customKey) {
|
|
386
355
|
if (customKey == null) {
|
|
@@ -392,9 +361,6 @@ const _CacheMongoose = class _CacheMongoose {
|
|
|
392
361
|
async close() {
|
|
393
362
|
await this.cache.close();
|
|
394
363
|
}
|
|
395
|
-
}
|
|
396
|
-
_instance = new WeakMap();
|
|
397
|
-
__privateAdd(_CacheMongoose, _instance);
|
|
398
|
-
let CacheMongoose = _CacheMongoose;
|
|
364
|
+
}
|
|
399
365
|
|
|
400
366
|
export { CacheMongoose as default };
|
package/dist/nest/index.cjs
CHANGED
|
@@ -9,8 +9,10 @@ require('node:crypto');
|
|
|
9
9
|
|
|
10
10
|
const CACHE_OPTIONS = Symbol("CACHE_OPTIONS");
|
|
11
11
|
class CacheService {
|
|
12
|
+
logger = new common.Logger(CacheService.name);
|
|
13
|
+
options;
|
|
14
|
+
cacheMongoose;
|
|
12
15
|
constructor(options) {
|
|
13
|
-
this.logger = new common.Logger(CacheService.name);
|
|
14
16
|
this.options = options;
|
|
15
17
|
}
|
|
16
18
|
get instance() {
|
package/dist/nest/index.mjs
CHANGED
|
@@ -7,8 +7,10 @@ import 'node:crypto';
|
|
|
7
7
|
|
|
8
8
|
const CACHE_OPTIONS = Symbol("CACHE_OPTIONS");
|
|
9
9
|
class CacheService {
|
|
10
|
+
logger = new Logger(CacheService.name);
|
|
11
|
+
options;
|
|
12
|
+
cacheMongoose;
|
|
10
13
|
constructor(options) {
|
|
11
|
-
this.logger = new Logger(CacheService.name);
|
|
12
14
|
this.options = options;
|
|
13
15
|
}
|
|
14
16
|
get instance() {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ts-cache-mongoose",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.1.0",
|
|
4
4
|
"description": "Cache plugin for mongoose Queries and Aggregate (in-memory, redis)",
|
|
5
5
|
"author": "ilovepixelart",
|
|
6
6
|
"license": "MIT",
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"aggregate"
|
|
36
36
|
],
|
|
37
37
|
"engines": {
|
|
38
|
-
"node": ">=
|
|
38
|
+
"node": ">=18"
|
|
39
39
|
},
|
|
40
40
|
"files": [
|
|
41
41
|
"dist",
|
package/src/cache/Cache.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { ms } from '../ms'
|
|
|
2
2
|
import { MemoryCacheEngine } from './engine/MemoryCacheEngine'
|
|
3
3
|
import { RedisCacheEngine } from './engine/RedisCacheEngine'
|
|
4
4
|
|
|
5
|
-
import type { CacheData, CacheEngine, CacheOptions,
|
|
5
|
+
import type { CacheData, CacheEngine, CacheOptions, Duration } from '../types'
|
|
6
6
|
|
|
7
7
|
export class Cache {
|
|
8
8
|
readonly #engine!: CacheEngine
|
|
@@ -21,7 +21,7 @@ export class Cache {
|
|
|
21
21
|
|
|
22
22
|
cacheOptions.defaultTTL ??= '1 minute'
|
|
23
23
|
|
|
24
|
-
this.#defaultTTL =
|
|
24
|
+
this.#defaultTTL = ms(cacheOptions.defaultTTL)
|
|
25
25
|
|
|
26
26
|
if (cacheOptions.engine === 'redis' && cacheOptions.engineOptions) {
|
|
27
27
|
this.#engine = new RedisCacheEngine(cacheOptions.engineOptions)
|
|
@@ -43,8 +43,8 @@ export class Cache {
|
|
|
43
43
|
return cacheEntry
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
async set(key: string, value: CacheData, ttl:
|
|
47
|
-
const givenTTL =
|
|
46
|
+
async set(key: string, value: CacheData, ttl: Duration | null): Promise<void> {
|
|
47
|
+
const givenTTL = ttl == null ? null : ms(ttl)
|
|
48
48
|
const actualTTL = givenTTL ?? this.#defaultTTL
|
|
49
49
|
await this.#engine.set(key, value, actualTTL)
|
|
50
50
|
if (this.#debug) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ms } from '../../ms'
|
|
2
2
|
|
|
3
|
-
import type { CacheData, CacheEngine,
|
|
3
|
+
import type { CacheData, CacheEngine, Duration } from '../../types'
|
|
4
4
|
|
|
5
5
|
export class MemoryCacheEngine implements CacheEngine {
|
|
6
6
|
readonly #cache: Map<string, { value: CacheData; expiresAt: number } | undefined>
|
|
@@ -18,8 +18,8 @@ export class MemoryCacheEngine implements CacheEngine {
|
|
|
18
18
|
return item.value
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
set(key: string, value: CacheData, ttl?:
|
|
22
|
-
const givenTTL =
|
|
21
|
+
set(key: string, value: CacheData, ttl?: Duration): void {
|
|
22
|
+
const givenTTL = ttl == null ? undefined : ms(ttl)
|
|
23
23
|
const actualTTL = givenTTL ?? Number.POSITIVE_INFINITY
|
|
24
24
|
this.#cache.set(key, {
|
|
25
25
|
value,
|
|
@@ -4,7 +4,7 @@ import { ms } from '../../ms'
|
|
|
4
4
|
import { convertToObject } from '../../version'
|
|
5
5
|
|
|
6
6
|
import type { Redis, RedisOptions } from 'ioredis'
|
|
7
|
-
import type { CacheData, CacheEngine,
|
|
7
|
+
import type { CacheData, CacheEngine, Duration } from '../../types'
|
|
8
8
|
|
|
9
9
|
export class RedisCacheEngine implements CacheEngine {
|
|
10
10
|
readonly #client: Redis
|
|
@@ -27,9 +27,9 @@ export class RedisCacheEngine implements CacheEngine {
|
|
|
27
27
|
}
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
async set(key: string, value: CacheData, ttl?:
|
|
30
|
+
async set(key: string, value: CacheData, ttl?: Duration): Promise<void> {
|
|
31
31
|
try {
|
|
32
|
-
const givenTTL =
|
|
32
|
+
const givenTTL = ttl == null ? undefined : ms(ttl)
|
|
33
33
|
const actualTTL = givenTTL ?? Number.POSITIVE_INFINITY
|
|
34
34
|
const serializedValue = EJSON.stringify(convertToObject(value))
|
|
35
35
|
await this.#client.setex(key, Math.ceil(actualTTL / 1000), serializedValue)
|
package/src/extend/aggregate.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { getKey } from '../key'
|
|
|
2
2
|
|
|
3
3
|
import type { Mongoose } from 'mongoose'
|
|
4
4
|
import type { Cache } from '../cache/Cache'
|
|
5
|
-
import type {
|
|
5
|
+
import type { Duration } from '../types'
|
|
6
6
|
|
|
7
7
|
export function extendAggregate(mongoose: Mongoose, cache: Cache): void {
|
|
8
8
|
const mongooseExec = mongoose.Aggregate.prototype.exec
|
|
@@ -15,24 +15,23 @@ export function extendAggregate(mongoose: Mongoose, cache: Cache): void {
|
|
|
15
15
|
})
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
-
mongoose.Aggregate.prototype.
|
|
18
|
+
mongoose.Aggregate.prototype.getDuration = function (): Duration | null {
|
|
19
19
|
return this._ttl
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
mongoose.Aggregate.prototype.cache = function (ttl?:
|
|
22
|
+
mongoose.Aggregate.prototype.cache = function (ttl?: Duration, customKey?: string) {
|
|
23
23
|
this._ttl = ttl ?? null
|
|
24
24
|
this._key = customKey ?? null
|
|
25
25
|
return this
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
mongoose.Aggregate.prototype.exec = async function (...args: []) {
|
|
29
|
-
|
|
30
|
-
if (!Object.prototype.hasOwnProperty.call(this, '_ttl')) {
|
|
29
|
+
if (!Object.hasOwn(this, '_ttl')) {
|
|
31
30
|
return mongooseExec.apply(this, args)
|
|
32
31
|
}
|
|
33
32
|
|
|
34
33
|
const key = this.getCacheKey()
|
|
35
|
-
const ttl = this.
|
|
34
|
+
const ttl = this.getDuration()
|
|
36
35
|
|
|
37
36
|
const resultCache = await cache.get(key).catch((err: unknown) => {
|
|
38
37
|
console.error(err)
|
package/src/extend/query.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { getKey } from '../key'
|
|
|
2
2
|
|
|
3
3
|
import type { Mongoose } from 'mongoose'
|
|
4
4
|
import type { Cache } from '../cache/Cache'
|
|
5
|
-
import type {
|
|
5
|
+
import type { Duration } from '../types'
|
|
6
6
|
|
|
7
7
|
export function extendQuery(mongoose: Mongoose, cache: Cache): void {
|
|
8
8
|
const mongooseExec = mongoose.Query.prototype.exec
|
|
@@ -29,24 +29,23 @@ export function extendQuery(mongoose: Mongoose, cache: Cache): void {
|
|
|
29
29
|
})
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
mongoose.Query.prototype.
|
|
32
|
+
mongoose.Query.prototype.getDuration = function (): Duration | null {
|
|
33
33
|
return this._ttl
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
-
mongoose.Query.prototype.cache = function (ttl?:
|
|
36
|
+
mongoose.Query.prototype.cache = function (ttl?: Duration, customKey?: string) {
|
|
37
37
|
this._ttl = ttl ?? null
|
|
38
38
|
this._key = customKey ?? null
|
|
39
39
|
return this
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
mongoose.Query.prototype.exec = async function (...args: []) {
|
|
43
|
-
|
|
44
|
-
if (!Object.prototype.hasOwnProperty.call(this, '_ttl')) {
|
|
43
|
+
if (!Object.hasOwn(this, '_ttl')) {
|
|
45
44
|
return mongooseExec.apply(this, args)
|
|
46
45
|
}
|
|
47
46
|
|
|
48
47
|
const key = this.getCacheKey()
|
|
49
|
-
const ttl = this.
|
|
48
|
+
const ttl = this.getDuration()
|
|
50
49
|
const mongooseOptions = this.mongooseOptions()
|
|
51
50
|
|
|
52
51
|
const isCount = this.op?.includes('count') ?? false
|
package/src/index.ts
CHANGED
|
@@ -3,17 +3,17 @@ import { extendAggregate } from './extend/aggregate'
|
|
|
3
3
|
import { extendQuery } from './extend/query'
|
|
4
4
|
|
|
5
5
|
import type { Mongoose } from 'mongoose'
|
|
6
|
-
import type { CacheOptions,
|
|
6
|
+
import type { CacheOptions, Duration } from './types'
|
|
7
7
|
|
|
8
8
|
export * from './types'
|
|
9
9
|
|
|
10
10
|
declare module 'mongoose' {
|
|
11
11
|
interface Query<ResultType, DocType, THelpers, RawDocType> {
|
|
12
|
-
cache: (this: Query<ResultType, DocType, THelpers, RawDocType>, ttl?:
|
|
12
|
+
cache: (this: Query<ResultType, DocType, THelpers, RawDocType>, ttl?: Duration, customKey?: string) => this
|
|
13
13
|
_key: string | null
|
|
14
14
|
getCacheKey: (this: Query<ResultType, DocType, THelpers, RawDocType>) => string
|
|
15
|
-
_ttl:
|
|
16
|
-
|
|
15
|
+
_ttl: Duration | null
|
|
16
|
+
getDuration: (this: Query<ResultType, DocType, THelpers, RawDocType>) => Duration | null
|
|
17
17
|
op?: string
|
|
18
18
|
_path?: unknown
|
|
19
19
|
_fields?: unknown
|
|
@@ -22,11 +22,11 @@ declare module 'mongoose' {
|
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
interface Aggregate<ResultType> {
|
|
25
|
-
cache: (this: Aggregate<ResultType>, ttl?:
|
|
25
|
+
cache: (this: Aggregate<ResultType>, ttl?: Duration, customKey?: string) => this
|
|
26
26
|
_key: string | null
|
|
27
27
|
getCacheKey: (this: Aggregate<ResultType>) => string
|
|
28
|
-
_ttl:
|
|
29
|
-
|
|
28
|
+
_ttl: Duration | null
|
|
29
|
+
getDuration: (this: Aggregate<ResultType>) => Duration | null
|
|
30
30
|
}
|
|
31
31
|
}
|
|
32
32
|
|