ts-cache-mongoose 2.0.0 → 2.2.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 CHANGED
@@ -12,22 +12,28 @@ Cache query and aggregate in mongoose using in-memory or redis
12
12
  [![Reliability Rating](https://sonarcloud.io/api/project_badges/measure?project=ilovepixelart_ts-cache-mongoose&metric=reliability_rating)](https://sonarcloud.io/summary/new_code?id=ilovepixelart_ts-cache-mongoose)
13
13
  [![Maintainability Rating](https://sonarcloud.io/api/project_badges/measure?project=ilovepixelart_ts-cache-mongoose&metric=sqale_rating)](https://sonarcloud.io/summary/new_code?id=ilovepixelart_ts-cache-mongoose)
14
14
  [![Security Rating](https://sonarcloud.io/api/project_badges/measure?project=ilovepixelart_ts-cache-mongoose&metric=security_rating)](https://sonarcloud.io/summary/new_code?id=ilovepixelart_ts-cache-mongoose)
15
+ \
16
+ [![Socket Badge](https://badge.socket.dev/npm/package/ts-cache-mongoose)](https://socket.dev/npm/package/ts-cache-mongoose)
17
+ [![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/ilovepixelart/ts-cache-mongoose/badge)](https://securityscorecards.dev/viewer/?uri=github.com/ilovepixelart/ts-cache-mongoose)
18
+ [![OpenSSF Best Practices](https://www.bestpractices.dev/projects/12484/badge?v=1)](https://www.bestpractices.dev/en/projects/12484)
15
19
 
16
20
  ## Motivation
17
21
 
18
22
  ts-cache-mongoose is a plugin for mongoose
19
23
  \
20
- Caching queries is a good way to improve performance of your application
24
+ I need a way to cache mongoose queries and aggregations to improve application performance. It should support both in-memory and Redis cache engines, work with all major Node.js frameworks, and be easy to use with a simple `.cache()` method on queries and aggregations.
21
25
 
22
26
  ## Supports and tested with
23
27
 
24
28
  ```json
25
29
  {
26
30
  "node": "20.x || 22.x || 24.x",
27
- "mongoose": ">=6.6.x || 7.x || 8.x || 9.x",
31
+ "mongoose": ">=6.6.0 <10"
28
32
  }
29
33
  ```
30
34
 
35
+ CI tests against mongoose `6.12.2`, `7.6.4`, `8.23.0`, and `9.4.1`.
36
+
31
37
  ## Features
32
38
 
33
39
  - In-memory caching
@@ -42,22 +48,13 @@ Caching queries is a good way to improve performance of your application
42
48
 
43
49
  ## Installation
44
50
 
45
- - Locally inside your project
46
-
47
- ```bash
48
- npm install ts-cache-mongoose
49
- pnpm add ts-cache-mongoose
50
- yarn add ts-cache-mongoose
51
- bun add ts-cache-mongoose
52
- ```
53
-
54
- - This plugin requires `mongoose` to be installed as a peer dependency
51
+ `mongoose` is a peer dependency — install it alongside `ts-cache-mongoose`.
55
52
 
56
53
  ```bash
57
- npm install mongoose
58
- pnpm add mongoose
59
- yarn add mongoose
60
- bun add mongoose
54
+ npm install ts-cache-mongoose mongoose
55
+ pnpm add ts-cache-mongoose mongoose
56
+ yarn add ts-cache-mongoose mongoose
57
+ bun add ts-cache-mongoose mongoose
61
58
  ```
62
59
 
63
60
  ## Example
@@ -105,6 +102,53 @@ const books = await Book.aggregate([
105
102
  ]).cache('1 minute').exec()
106
103
  ```
107
104
 
105
+ ### Bounded in-memory cache
106
+
107
+ The in-memory engine is unbounded by default. For workloads where query keys are driven by user input (search, filters, pagination), cap the cache so a caller generating unique cache keys cannot grow the map without limit. Two bounds are available and can be combined — eviction is LRU, and whichever bound is hit first triggers it:
108
+
109
+ ```typescript
110
+ cache.init(mongoose, {
111
+ engine: 'memory',
112
+ defaultTTL: '60 seconds',
113
+ maxEntries: 10_000, // cap by entry count
114
+ maxBytes: 50 * 1024 * 1024, // cap by serialized bytes (50 MB)
115
+ })
116
+ ```
117
+
118
+ `maxBytes` measures entry size via `node:v8.serialize(value).byteLength` by default — handles circular references (mongoose `populate` parent-refs), single C++ call per `set`, works on Node / Bun / Deno. Provide your own `sizeCalculation` callback if you want an O(1) estimate instead:
119
+
120
+ ```typescript
121
+ cache.init(mongoose, {
122
+ engine: 'memory',
123
+ maxBytes: 50 * 1024 * 1024,
124
+ sizeCalculation: (value) => {
125
+ if (Array.isArray(value)) return value.length * 512
126
+ return 512
127
+ },
128
+ })
129
+ ```
130
+
131
+ Eviction is soft: the just-written entry is never dropped, even if its own size exceeds `maxBytes`. Everything older gets evicted until both bounds are satisfied (or only the new entry remains).
132
+
133
+ Both options are ignored for the Redis engine — use Redis's own `maxmemory` + `maxmemory-policy` instead.
134
+
135
+ ### Custom error handling
136
+
137
+ By default, cache engine failures (Redis disconnects, serialization errors, etc.) are logged via `console.error` and the query falls through to the database. Pass an `onError` callback to route them somewhere else — e.g. a structured logger, Sentry, or a metric counter:
138
+
139
+ ```typescript
140
+ cache.init(mongoose, {
141
+ engine: 'redis',
142
+ defaultTTL: '60 seconds',
143
+ engineOptions: { host: 'localhost', port: 6379 },
144
+ onError: (error) => {
145
+ logger.warn({ err: error }, 'cache engine failure')
146
+ },
147
+ })
148
+ ```
149
+
150
+ The callback receives the raw `Error`. Cache reads and writes never throw — a failing engine degrades to a cache miss.
151
+
108
152
  ### Cache invalidation
109
153
 
110
154
  ```typescript
@@ -164,6 +208,14 @@ export class SomeService {
164
208
  }
165
209
  ```
166
210
 
211
+ ## Contributing
212
+
213
+ Check [CONTRIBUTING.md](CONTRIBUTING.md)
214
+
215
+ ## License
216
+
217
+ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details
218
+
167
219
  ## Check my other projects
168
220
 
169
221
  - [ts-migrate-mongoose](https://github.com/ilovepixelart/ts-migrate-mongoose) - Migration framework for mongoose
package/dist/index.cjs CHANGED
@@ -1,5 +1,6 @@
1
1
  'use strict';
2
2
 
3
+ var node_v8 = require('node:v8');
3
4
  var bson = require('bson');
4
5
  var IORedis = require('ioredis');
5
6
  var mongoose = require('mongoose');
@@ -11,89 +12,119 @@ const h = m * 60;
11
12
  const d = h * 24;
12
13
  const w = d * 7;
13
14
  const y = d * 365.25;
14
- const RE = /^(-?(?:\d+)?\.?\d+)\s*(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)?$/i;
15
+ const mo = y / 12;
15
16
  const UNITS = {
16
- years: y,
17
- year: y,
18
- yrs: y,
19
- yr: y,
20
- y,
21
- weeks: w,
22
- week: w,
23
- w,
24
- days: d,
25
- day: d,
26
- d,
27
- hours: h,
28
- hour: h,
29
- hrs: h,
30
- hr: h,
31
- h,
32
- minutes: m,
33
- minute: m,
34
- mins: m,
35
- min: m,
36
- m,
17
+ milliseconds: 1,
18
+ millisecond: 1,
19
+ msecs: 1,
20
+ msec: 1,
21
+ ms: 1,
37
22
  seconds: s,
38
23
  second: s,
39
24
  secs: s,
40
25
  sec: s,
41
26
  s,
42
- milliseconds: 1,
43
- millisecond: 1,
44
- msecs: 1,
45
- msec: 1,
46
- ms: 1
27
+ minutes: m,
28
+ minute: m,
29
+ mins: m,
30
+ min: m,
31
+ m,
32
+ hours: h,
33
+ hour: h,
34
+ hrs: h,
35
+ hr: h,
36
+ h,
37
+ days: d,
38
+ day: d,
39
+ d,
40
+ weeks: w,
41
+ week: w,
42
+ w,
43
+ months: mo,
44
+ month: mo,
45
+ mo,
46
+ years: y,
47
+ year: y,
48
+ yrs: y,
49
+ yr: y,
50
+ y
47
51
  };
52
+ const unitPattern = Object.keys(UNITS).sort((a, b) => b.length - a.length).join("|");
53
+ const RE = new RegExp(String.raw`^(-?(?:\d+)?\.?\d+)\s*(${unitPattern})?$`, "i");
48
54
  const ms = (val) => {
49
55
  const str = String(val);
50
- if (str.length > 100) return 0;
56
+ if (str.length > 100) return Number.NaN;
51
57
  const match = RE.exec(str);
52
- if (!match) return 0;
58
+ if (!match) return Number.NaN;
53
59
  const n = Number.parseFloat(match[1] ?? "");
54
60
  const type = (match[2] ?? "ms").toLowerCase();
55
61
  return n * (UNITS[type] ?? 0);
56
62
  };
57
63
 
58
- var __typeError$3 = (msg) => {
59
- throw TypeError(msg);
60
- };
61
- var __accessCheck$3 = (obj, member, msg) => member.has(obj) || __typeError$3("Cannot " + msg);
62
- var __privateGet$3 = (obj, member, getter) => (__accessCheck$3(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
63
- 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);
64
- var __privateSet$3 = (obj, member, value, setter) => (__accessCheck$3(obj, member, "write to private field"), member.set(obj, value), value);
65
- var _cache;
64
+ const defaultSizer = (value) => node_v8.serialize(value).byteLength;
66
65
  class MemoryCacheEngine {
67
- constructor() {
68
- __privateAdd$3(this, _cache);
69
- __privateSet$3(this, _cache, /* @__PURE__ */ new Map());
66
+ #cache;
67
+ #maxEntries;
68
+ #maxBytes;
69
+ #sizeOf;
70
+ #totalBytes;
71
+ constructor(options) {
72
+ this.#cache = /* @__PURE__ */ new Map();
73
+ this.#maxEntries = options?.maxEntries != null && options.maxEntries > 0 ? options.maxEntries : Number.POSITIVE_INFINITY;
74
+ this.#maxBytes = options?.maxBytes != null && options.maxBytes > 0 ? options.maxBytes : Number.POSITIVE_INFINITY;
75
+ this.#sizeOf = options?.sizeCalculation ?? defaultSizer;
76
+ this.#totalBytes = 0;
77
+ }
78
+ get totalBytes() {
79
+ return this.#totalBytes;
80
+ }
81
+ get size() {
82
+ return this.#cache.size;
70
83
  }
71
84
  get(key) {
72
- const item = __privateGet$3(this, _cache).get(key);
73
- if (!item || item.expiresAt < Date.now()) {
74
- this.del(key);
85
+ const item = this.#cache.get(key);
86
+ if (!item) return void 0;
87
+ if (item.expiresAt < Date.now()) {
88
+ this.#cache.delete(key);
89
+ this.#totalBytes -= item.bytes;
75
90
  return void 0;
76
91
  }
92
+ this.#cache.delete(key);
93
+ this.#cache.set(key, item);
77
94
  return item.value;
78
95
  }
79
96
  set(key, value, ttl) {
80
- const givenTTL = typeof ttl === "string" ? ms(ttl) : ttl;
97
+ const givenTTL = ttl == null ? void 0 : ms(ttl);
81
98
  const actualTTL = givenTTL ?? Number.POSITIVE_INFINITY;
82
- __privateGet$3(this, _cache).set(key, {
83
- value,
84
- expiresAt: Date.now() + actualTTL
85
- });
99
+ const existing = this.#cache.get(key);
100
+ if (existing) {
101
+ this.#cache.delete(key);
102
+ this.#totalBytes -= existing.bytes;
103
+ }
104
+ const bytes = this.#sizeOf(value);
105
+ this.#cache.set(key, { value, expiresAt: Date.now() + actualTTL, bytes });
106
+ this.#totalBytes += bytes;
107
+ while ((this.#cache.size > this.#maxEntries || this.#totalBytes > this.#maxBytes) && this.#cache.size > 1) {
108
+ const oldestKey = this.#cache.keys().next().value;
109
+ if (oldestKey === void 0 || oldestKey === key) break;
110
+ const oldest = this.#cache.get(oldestKey);
111
+ this.#cache.delete(oldestKey);
112
+ if (oldest) this.#totalBytes -= oldest.bytes;
113
+ }
86
114
  }
87
115
  del(key) {
88
- __privateGet$3(this, _cache).delete(key);
116
+ const item = this.#cache.get(key);
117
+ if (!item) return;
118
+ this.#cache.delete(key);
119
+ this.#totalBytes -= item.bytes;
89
120
  }
90
121
  clear() {
91
- __privateGet$3(this, _cache).clear();
122
+ this.#cache.clear();
123
+ this.#totalBytes = 0;
92
124
  }
93
125
  close() {
94
126
  }
95
127
  }
96
- _cache = new WeakMap();
97
128
 
98
129
  const isMongooseLessThan7 = Number.parseInt(mongoose.version, 10) < 7;
99
130
  const convertToObject = (value) => {
@@ -108,120 +139,120 @@ const convertToObject = (value) => {
108
139
  return value;
109
140
  };
110
141
 
111
- var __typeError$2 = (msg) => {
112
- throw TypeError(msg);
113
- };
114
- var __accessCheck$2 = (obj, member, msg) => member.has(obj) || __typeError$2("Cannot " + msg);
115
- var __privateGet$2 = (obj, member, getter) => (__accessCheck$2(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
116
- 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);
117
- var __privateSet$2 = (obj, member, value, setter) => (__accessCheck$2(obj, member, "write to private field"), member.set(obj, value), value);
118
- var _client;
119
142
  class RedisCacheEngine {
120
- constructor(options) {
121
- __privateAdd$2(this, _client);
143
+ #client;
144
+ #onError;
145
+ constructor(options, onError) {
122
146
  options.keyPrefix ??= "cache-mongoose:";
123
- __privateSet$2(this, _client, new IORedis(options));
147
+ this.#client = new IORedis(options);
148
+ this.#onError = onError;
124
149
  }
125
150
  async get(key) {
126
151
  try {
127
- const value = await __privateGet$2(this, _client).get(key);
152
+ const value = await this.#client.get(key);
128
153
  if (value === null) {
129
154
  return void 0;
130
155
  }
131
156
  return bson.EJSON.parse(value);
132
157
  } catch (err) {
133
- console.error(err);
158
+ this.#onError(err);
134
159
  return void 0;
135
160
  }
136
161
  }
137
162
  async set(key, value, ttl) {
138
163
  try {
139
- const givenTTL = typeof ttl === "string" ? ms(ttl) : ttl;
164
+ const converted = convertToObject(value);
165
+ if (converted === void 0) {
166
+ return;
167
+ }
168
+ const givenTTL = ttl == null ? void 0 : ms(ttl);
140
169
  const actualTTL = givenTTL ?? Number.POSITIVE_INFINITY;
141
- const serializedValue = bson.EJSON.stringify(convertToObject(value));
142
- await __privateGet$2(this, _client).setex(key, Math.ceil(actualTTL / 1e3), serializedValue);
170
+ const serializedValue = bson.EJSON.stringify(converted);
171
+ await this.#client.setex(key, Math.ceil(actualTTL / 1e3), serializedValue);
143
172
  } catch (err) {
144
- console.error(err);
173
+ this.#onError(err);
145
174
  }
146
175
  }
147
176
  async del(key) {
148
- await __privateGet$2(this, _client).del(key);
177
+ await this.#client.del(key);
149
178
  }
150
179
  async clear() {
151
- await __privateGet$2(this, _client).flushdb();
180
+ await this.#client.flushdb();
152
181
  }
153
182
  async close() {
154
- await __privateGet$2(this, _client).quit();
183
+ await this.#client.quit();
155
184
  }
156
185
  }
157
- _client = new WeakMap();
158
186
 
159
- var __typeError$1 = (msg) => {
160
- throw TypeError(msg);
161
- };
162
- var __accessCheck$1 = (obj, member, msg) => member.has(obj) || __typeError$1("Cannot " + msg);
163
- var __privateGet$1 = (obj, member, getter) => (__accessCheck$1(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
164
- 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);
165
- var __privateSet$1 = (obj, member, value, setter) => (__accessCheck$1(obj, member, "write to private field"), member.set(obj, value), value);
166
- var _engine, _defaultTTL, _debug, _engines;
167
187
  class Cache {
188
+ #engine;
189
+ #defaultTTL;
190
+ #debug;
191
+ #onError;
192
+ #engines = ["memory", "redis"];
168
193
  constructor(cacheOptions) {
169
- __privateAdd$1(this, _engine);
170
- __privateAdd$1(this, _defaultTTL);
171
- __privateAdd$1(this, _debug);
172
- __privateAdd$1(this, _engines, ["memory", "redis"]);
173
- if (!__privateGet$1(this, _engines).includes(cacheOptions.engine)) {
194
+ if (!this.#engines.includes(cacheOptions.engine)) {
174
195
  throw new Error(`Invalid engine name: ${cacheOptions.engine}`);
175
196
  }
176
197
  if (cacheOptions.engine === "redis" && !cacheOptions.engineOptions) {
177
198
  throw new Error(`Engine options are required for ${cacheOptions.engine} engine`);
178
199
  }
179
200
  cacheOptions.defaultTTL ??= "1 minute";
180
- __privateSet$1(this, _defaultTTL, typeof cacheOptions.defaultTTL === "string" ? ms(cacheOptions.defaultTTL) : cacheOptions.defaultTTL);
201
+ this.#defaultTTL = ms(cacheOptions.defaultTTL);
202
+ this.#onError = cacheOptions.onError ?? console.error;
181
203
  if (cacheOptions.engine === "redis" && cacheOptions.engineOptions) {
182
- __privateSet$1(this, _engine, new RedisCacheEngine(cacheOptions.engineOptions));
204
+ this.#engine = new RedisCacheEngine(cacheOptions.engineOptions, this.#onError);
183
205
  }
184
206
  if (cacheOptions.engine === "memory") {
185
- __privateSet$1(this, _engine, new MemoryCacheEngine());
207
+ this.#engine = new MemoryCacheEngine({
208
+ maxEntries: cacheOptions.maxEntries,
209
+ maxBytes: cacheOptions.maxBytes,
210
+ sizeCalculation: cacheOptions.sizeCalculation
211
+ });
186
212
  }
187
- __privateSet$1(this, _debug, cacheOptions.debug === true);
213
+ this.#debug = cacheOptions.debug === true;
214
+ }
215
+ get onError() {
216
+ return this.#onError;
188
217
  }
189
218
  async get(key) {
190
- const cacheEntry = await __privateGet$1(this, _engine).get(key);
191
- if (__privateGet$1(this, _debug)) {
219
+ const cacheEntry = await this.#engine.get(key);
220
+ if (this.#debug) {
192
221
  const cacheHit = cacheEntry == null ? "MISS" : "HIT";
193
222
  console.log(`[ts-cache-mongoose] GET '${key}' - ${cacheHit}`);
194
223
  }
195
224
  return cacheEntry;
196
225
  }
197
226
  async set(key, value, ttl) {
198
- const givenTTL = typeof ttl === "string" ? ms(ttl) : ttl;
199
- const actualTTL = givenTTL ?? __privateGet$1(this, _defaultTTL);
200
- await __privateGet$1(this, _engine).set(key, value, actualTTL);
201
- if (__privateGet$1(this, _debug)) {
227
+ const givenTTL = ttl == null ? null : ms(ttl);
228
+ const actualTTL = givenTTL ?? this.#defaultTTL;
229
+ if (Number.isNaN(actualTTL) || actualTTL <= 0) {
230
+ if (this.#debug) {
231
+ console.log(`[ts-cache-mongoose] SET '${key}' - skipped (non-positive ttl: ${String(actualTTL)} ms)`);
232
+ }
233
+ return;
234
+ }
235
+ await this.#engine.set(key, value, actualTTL);
236
+ if (this.#debug) {
202
237
  console.log(`[ts-cache-mongoose] SET '${key}' - ttl: ${actualTTL.toFixed(0)} ms`);
203
238
  }
204
239
  }
205
240
  async del(key) {
206
- await __privateGet$1(this, _engine).del(key);
207
- if (__privateGet$1(this, _debug)) {
241
+ await this.#engine.del(key);
242
+ if (this.#debug) {
208
243
  console.log(`[ts-cache-mongoose] DEL '${key}'`);
209
244
  }
210
245
  }
211
246
  async clear() {
212
- await __privateGet$1(this, _engine).clear();
213
- if (__privateGet$1(this, _debug)) {
247
+ await this.#engine.clear();
248
+ if (this.#debug) {
214
249
  console.log("[ts-cache-mongoose] CLEAR");
215
250
  }
216
251
  }
217
252
  async close() {
218
- return __privateGet$1(this, _engine).close();
253
+ return this.#engine.close();
219
254
  }
220
255
  }
221
- _engine = new WeakMap();
222
- _defaultTTL = new WeakMap();
223
- _debug = new WeakMap();
224
- _engines = new WeakMap();
225
256
 
226
257
  const isPlainObject = (value) => {
227
258
  if (typeof value !== "object" || value === null) return false;
@@ -273,7 +304,7 @@ function extendAggregate(mongoose, cache) {
273
304
  pipeline: this.pipeline()
274
305
  });
275
306
  };
276
- mongoose.Aggregate.prototype.getCacheTTL = function() {
307
+ mongoose.Aggregate.prototype.getDuration = function() {
277
308
  return this._ttl;
278
309
  };
279
310
  mongoose.Aggregate.prototype.cache = function(ttl, customKey) {
@@ -282,20 +313,20 @@ function extendAggregate(mongoose, cache) {
282
313
  return this;
283
314
  };
284
315
  mongoose.Aggregate.prototype.exec = async function(...args) {
285
- if (!Object.prototype.hasOwnProperty.call(this, "_ttl")) {
316
+ if (!Object.hasOwn(this, "_ttl")) {
286
317
  return mongooseExec.apply(this, args);
287
318
  }
288
319
  const key = this.getCacheKey();
289
- const ttl = this.getCacheTTL();
320
+ const ttl = this.getDuration();
290
321
  const resultCache = await cache.get(key).catch((err) => {
291
- console.error(err);
322
+ cache.onError(err);
292
323
  });
293
324
  if (resultCache) {
294
325
  return resultCache;
295
326
  }
296
327
  const result = await mongooseExec.call(this);
297
328
  await cache.set(key, result, ttl).catch((err) => {
298
- console.error(err);
329
+ cache.onError(err);
299
330
  });
300
331
  return result;
301
332
  };
@@ -322,7 +353,7 @@ function extendQuery(mongoose, cache) {
322
353
  _conditions: this._conditions
323
354
  });
324
355
  };
325
- mongoose.Query.prototype.getCacheTTL = function() {
356
+ mongoose.Query.prototype.getDuration = function() {
326
357
  return this._ttl;
327
358
  };
328
359
  mongoose.Query.prototype.cache = function(ttl, customKey) {
@@ -331,17 +362,17 @@ function extendQuery(mongoose, cache) {
331
362
  return this;
332
363
  };
333
364
  mongoose.Query.prototype.exec = async function(...args) {
334
- if (!Object.prototype.hasOwnProperty.call(this, "_ttl")) {
365
+ if (!Object.hasOwn(this, "_ttl")) {
335
366
  return mongooseExec.apply(this, args);
336
367
  }
337
368
  const key = this.getCacheKey();
338
- const ttl = this.getCacheTTL();
369
+ const ttl = this.getDuration();
339
370
  const mongooseOptions = this.mongooseOptions();
340
371
  const isCount = this.op?.includes("count") ?? false;
341
372
  const isDistinct = this.op === "distinct";
342
373
  const model = this.model.modelName;
343
374
  const resultCache = await cache.get(key).catch((err) => {
344
- console.error(err);
375
+ cache.onError(err);
345
376
  });
346
377
  if (resultCache) {
347
378
  if (isCount || isDistinct || mongooseOptions.lean) {
@@ -357,32 +388,26 @@ function extendQuery(mongoose, cache) {
357
388
  }
358
389
  const result = await mongooseExec.call(this);
359
390
  await cache.set(key, result, ttl).catch((err) => {
360
- console.error(err);
391
+ cache.onError(err);
361
392
  });
362
393
  return result;
363
394
  };
364
395
  }
365
396
 
366
- var __typeError = (msg) => {
367
- throw TypeError(msg);
368
- };
369
- var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
370
- var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
371
- 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);
372
- var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), member.set(obj, value), value);
373
- var _instance;
374
- const _CacheMongoose = class _CacheMongoose {
397
+ class CacheMongoose {
398
+ static #instance;
399
+ cache;
375
400
  constructor() {
376
401
  }
377
402
  static init(mongoose, cacheOptions) {
378
- if (!__privateGet(_CacheMongoose, _instance)) {
379
- __privateSet(_CacheMongoose, _instance, new _CacheMongoose());
380
- __privateGet(_CacheMongoose, _instance).cache = new Cache(cacheOptions);
381
- const cache = __privateGet(_CacheMongoose, _instance).cache;
403
+ if (!CacheMongoose.#instance) {
404
+ CacheMongoose.#instance = new CacheMongoose();
405
+ CacheMongoose.#instance.cache = new Cache(cacheOptions);
406
+ const cache = CacheMongoose.#instance.cache;
382
407
  extendQuery(mongoose, cache);
383
408
  extendAggregate(mongoose, cache);
384
409
  }
385
- return __privateGet(_CacheMongoose, _instance);
410
+ return CacheMongoose.#instance;
386
411
  }
387
412
  async clear(customKey) {
388
413
  if (customKey == null) {
@@ -394,9 +419,6 @@ const _CacheMongoose = class _CacheMongoose {
394
419
  async close() {
395
420
  await this.cache.close();
396
421
  }
397
- };
398
- _instance = new WeakMap();
399
- __privateAdd(_CacheMongoose, _instance);
400
- let CacheMongoose = _CacheMongoose;
422
+ }
401
423
 
402
424
  module.exports = CacheMongoose;