@cacheable/node-cache 0.8.0 → 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 CHANGED
@@ -22,6 +22,7 @@ Note: `NodeCache` is ready and available for use. `NodeCacheStore` is in progres
22
22
  * [Getting Started](#getting-started)
23
23
  * [Basic Usage](#basic-usage)
24
24
  * [Advanced Usage](#advanced-usage)
25
+ * [NodeCacheStore](#nodecachestore)
25
26
  * [API](#api)
26
27
  * [How to Contribute](#how-to-contribute)
27
28
  * [License and Copyright](#license-and-copyright)
@@ -60,6 +61,49 @@ await cache.get('foo'); // 'bar'
60
61
  cache.getStats(); // {hits: 1, misses: 1, keys: 1, ksize: 2, vsize: 3}
61
62
  ```
62
63
 
64
+ ## NodeCacheStore
65
+
66
+ The `NodeCacheStore` is a class that extends the `NodeCache` and adds the ability to use storage adapters. This is based on the `cacheable` engine and allows you to do layer 1 and layer 2 caching. The storage adapters are based on the [Keyv](https://keyv.org) package. This allows you to use any of the storage adapters that are available.
67
+
68
+ ```javascript
69
+ import {NodeCacheStore} from '@cacheable/node-cache';
70
+
71
+ const cache = new NodeCacheStore();
72
+ cache.set('foo', 'bar');
73
+ cache.get('foo'); // 'bar'
74
+ ```
75
+
76
+ ### NodeCacheStoreOptions
77
+
78
+ When initializing the cache you can pass in the options below:
79
+
80
+ ```javascript
81
+ export type NodeCacheStoreOptions = {
82
+ ttl?: number; // The standard ttl as number in seconds for every generated cache element. 0 = unlimited
83
+ primary?: Keyv; // The primary storage adapter
84
+ secondary?: Keyv; // The secondary storage adapter
85
+ maxKeys?: number; // Default is 0 (unlimited). If this is set it will throw and error if you try to set more keys than the max.
86
+ };
87
+ ```
88
+
89
+ ### Node Cache Store API
90
+
91
+ * `set(key: string | number, value: any, ttl?: number): Promise<boolean>` - Set a key value pair with an optional ttl (in milliseconds). Will return true on success. If the ttl is not set it will default to 0 (no ttl)
92
+ * `mset(data: Array<NodeCacheItem>): Promise<boolean>` - Set multiple key value pairs at once
93
+ * `get<T>(key: string | number): Promise<T>` - Get a value from the cache by key
94
+ * `mget(keys: Array<string | number>): Promise<Record<string, unknown>>` - Get multiple values from the cache by keys
95
+ * `take<T>(key: string | number): Promise<T>` - Get a value from the cache by key and delete it
96
+ * `del(key: string | number): Promise<boolean>` - Delete a key
97
+ * `mdel(keys: Array<string | number>): Promise<boolean>` - Delete multiple keys
98
+ * `clear(): Promise<void>` - Clear the cache
99
+ * `setTtl(key: string | number, ttl: number): Promise<boolean>` - Set the ttl of a key
100
+ * `disconnect(): Promise<void>` - Disconnect the storage adapters
101
+ * `stats`: `NodeCacheStats` - Get the stats of the cache
102
+ * `ttl`: `number` - The standard ttl as number in seconds for every generated cache element. 0 = unlimited
103
+ * `primary`: `Keyv` - The primary storage adapter
104
+ * `secondary`: `Keyv` - The secondary storage adapter
105
+ * `maxKeys`: `number` - If this is set it will throw and error if you try to set more keys than the max
106
+
63
107
  ## API
64
108
 
65
109
  ### `constructor(options?: NodeCacheOptions)`
package/dist/index.cjs CHANGED
@@ -31,10 +31,120 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
31
31
  var src_exports = {};
32
32
  __export(src_exports, {
33
33
  NodeCacheErrors: () => NodeCacheErrors,
34
+ NodeCacheStore: () => NodeCacheStore,
34
35
  default: () => NodeCache
35
36
  });
36
37
  module.exports = __toCommonJS(src_exports);
37
38
  var import_eventemitter3 = __toESM(require("eventemitter3"), 1);
39
+ var import_cacheable2 = require("cacheable");
40
+
41
+ // src/store.ts
42
+ var import_cacheable = require("cacheable");
43
+ var import_keyv = require("keyv");
44
+ var NodeCacheStore = class {
45
+ _maxKeys = 0;
46
+ _cache = new import_cacheable.Cacheable({ primary: new import_keyv.Keyv({ store: new import_cacheable.CacheableMemory() }) });
47
+ constructor(options) {
48
+ if (options) {
49
+ const cacheOptions = {
50
+ ttl: options.ttl,
51
+ primary: options.primary,
52
+ secondary: options.secondary
53
+ };
54
+ this._cache = new import_cacheable.Cacheable(cacheOptions);
55
+ if (options.maxKeys) {
56
+ this._maxKeys = options.maxKeys;
57
+ if (this._maxKeys > 0) {
58
+ this._cache.stats.enabled = true;
59
+ }
60
+ }
61
+ }
62
+ }
63
+ get cache() {
64
+ return this._cache;
65
+ }
66
+ get ttl() {
67
+ return this._cache.ttl;
68
+ }
69
+ set ttl(ttl) {
70
+ this._cache.ttl = ttl;
71
+ }
72
+ get primary() {
73
+ return this._cache.primary;
74
+ }
75
+ set primary(primary) {
76
+ this._cache.primary = primary;
77
+ }
78
+ get secondary() {
79
+ return this._cache.secondary;
80
+ }
81
+ set secondary(secondary) {
82
+ this._cache.secondary = secondary;
83
+ }
84
+ get maxKeys() {
85
+ return this._maxKeys;
86
+ }
87
+ set maxKeys(maxKeys) {
88
+ this._maxKeys = maxKeys;
89
+ if (this._maxKeys > 0) {
90
+ this._cache.stats.enabled = true;
91
+ }
92
+ }
93
+ async set(key, value, ttl) {
94
+ if (this._maxKeys > 0) {
95
+ console.log(this._cache.stats.count, this._maxKeys);
96
+ if (this._cache.stats.count >= this._maxKeys) {
97
+ return false;
98
+ }
99
+ }
100
+ const finalTtl = ttl ?? this._cache.ttl;
101
+ await this._cache.set(key.toString(), value, finalTtl);
102
+ return true;
103
+ }
104
+ async mset(list) {
105
+ const items = new Array();
106
+ for (const item of list) {
107
+ items.push({ key: item.key.toString(), value: item.value, ttl: item.ttl });
108
+ }
109
+ await this._cache.setMany(items);
110
+ }
111
+ async get(key) {
112
+ return this._cache.get(key.toString());
113
+ }
114
+ async mget(keys) {
115
+ const result = {};
116
+ for (const key of keys) {
117
+ result[key.toString()] = await this._cache.get(key.toString());
118
+ }
119
+ return result;
120
+ }
121
+ async del(key) {
122
+ return this._cache.delete(key.toString());
123
+ }
124
+ async mdel(keys) {
125
+ return this._cache.deleteMany(keys.map((key) => key.toString()));
126
+ }
127
+ async clear() {
128
+ return this._cache.clear();
129
+ }
130
+ async setTtl(key, ttl) {
131
+ const finalTtl = ttl ?? this._cache.ttl;
132
+ const item = await this._cache.get(key.toString());
133
+ if (item) {
134
+ await this._cache.set(key.toString(), item, finalTtl);
135
+ return true;
136
+ }
137
+ return false;
138
+ }
139
+ async take(key) {
140
+ return this._cache.take(key.toString());
141
+ }
142
+ async disconnect() {
143
+ await this._cache.disconnect();
144
+ }
145
+ };
146
+
147
+ // src/index.ts
38
148
  var NodeCacheErrors = /* @__PURE__ */ ((NodeCacheErrors2) => {
39
149
  NodeCacheErrors2["ECACHEFULL"] = "Cache max keys amount exceeded";
40
150
  NodeCacheErrors2["EKEYTYPE"] = "The key argument has to be of type `string` or `number`. Found: `__key`";
@@ -52,13 +162,8 @@ var NodeCache = class extends import_eventemitter3.default {
52
162
  maxKeys: -1
53
163
  };
54
164
  store = /* @__PURE__ */ new Map();
55
- _stats = {
56
- keys: 0,
57
- hits: 0,
58
- misses: 0,
59
- ksize: 0,
60
- vsize: 0
61
- };
165
+ _stats = new import_cacheable2.CacheableStats({ enabled: true });
166
+ _cacheable = new import_cacheable2.CacheableMemory();
62
167
  intervalId = 0;
63
168
  constructor(options) {
64
169
  super();
@@ -89,9 +194,9 @@ var NodeCache = class extends import_eventemitter3.default {
89
194
  }
90
195
  this.store.set(keyValue, { key: keyValue, value, ttl: expirationTimestamp });
91
196
  this.emit("set", keyValue, value, ttlValue);
92
- this._stats.ksize += this.roughSizeOfKey(keyValue);
93
- this._stats.vsize += this.roughSizeOfObject(value);
94
- this._stats.keys = this.store.size;
197
+ this._stats.incrementKSize(keyValue);
198
+ this._stats.incrementVSize(value);
199
+ this._stats.setCount(this.store.size);
95
200
  return true;
96
201
  }
97
202
  // Sets multiple key val pairs. It is possible to define a ttl (seconds). Returns true on success.
@@ -113,23 +218,23 @@ var NodeCache = class extends import_eventemitter3.default {
113
218
  if (this.options.deleteOnExpire) {
114
219
  this.del(key);
115
220
  }
116
- this.addMiss();
221
+ this._stats.incrementMisses();
117
222
  this.emit("expired", this.formatKey(key), result.value);
118
223
  return void 0;
119
224
  }
120
- this.addHit();
225
+ this._stats.incrementHits();
121
226
  if (this.options.useClones) {
122
- return this.clone(result.value);
227
+ return this._cacheable.clone(result.value);
123
228
  }
124
229
  return result.value;
125
230
  }
126
- this.addHit();
231
+ this._stats.incrementHits();
127
232
  if (this.options.useClones) {
128
- return this.clone(result.value);
233
+ return this._cacheable.clone(result.value);
129
234
  }
130
235
  return result.value;
131
236
  }
132
- this.addMiss();
237
+ this._stats.incrementMisses();
133
238
  return void 0;
134
239
  }
135
240
  /*
@@ -156,7 +261,7 @@ var NodeCache = class extends import_eventemitter3.default {
156
261
  if (result) {
157
262
  this.del(key);
158
263
  if (this.options.useClones) {
159
- return this.clone(result);
264
+ return this._cacheable.clone(result);
160
265
  }
161
266
  return result;
162
267
  }
@@ -172,9 +277,9 @@ var NodeCache = class extends import_eventemitter3.default {
172
277
  const keyValue = this.formatKey(key);
173
278
  this.store.delete(keyValue);
174
279
  this.emit("del", keyValue, result.value);
175
- this._stats.ksize -= this.roughSizeOfKey(keyValue);
176
- this._stats.vsize -= this.roughSizeOfObject(result.value);
177
- this._stats.keys = this.store.size;
280
+ this._stats.decreaseKSize(keyValue);
281
+ this._stats.decreaseVSize(result.value);
282
+ this._stats.setCount(this.store.size);
178
283
  return 1;
179
284
  }
180
285
  return 0;
@@ -233,7 +338,14 @@ var NodeCache = class extends import_eventemitter3.default {
233
338
  }
234
339
  // Gets the stats of the cache.
235
340
  getStats() {
236
- return this._stats;
341
+ const stats = {
342
+ keys: this._stats.count,
343
+ hits: this._stats.hits,
344
+ misses: this._stats.misses,
345
+ ksize: this._stats.ksize,
346
+ vsize: this._stats.vsize
347
+ };
348
+ return stats;
237
349
  }
238
350
  // Flush the whole data.
239
351
  flushAll() {
@@ -243,13 +355,7 @@ var NodeCache = class extends import_eventemitter3.default {
243
355
  }
244
356
  // Flush the stats
245
357
  flushStats() {
246
- this._stats = {
247
- keys: 0,
248
- hits: 0,
249
- misses: 0,
250
- ksize: 0,
251
- vsize: 0
252
- };
358
+ this._stats = new import_cacheable2.CacheableStats({ enabled: true });
253
359
  this.emit("flush_stats");
254
360
  }
255
361
  // Close the cache. This will clear the interval timeout which is set on check period option.
@@ -269,37 +375,6 @@ var NodeCache = class extends import_eventemitter3.default {
269
375
  const expirationTimestamp = currentTimestamp + ttlInMilliseconds;
270
376
  return expirationTimestamp;
271
377
  }
272
- addHit() {
273
- this._stats.hits++;
274
- }
275
- addMiss() {
276
- this._stats.misses++;
277
- }
278
- roughSizeOfKey(key) {
279
- return this.formatKey(key).toString().length * 2;
280
- }
281
- roughSizeOfObject(object) {
282
- const objectList = [];
283
- const stack = [object];
284
- let bytes = 0;
285
- while (stack.length > 0) {
286
- const value = stack.pop();
287
- if (typeof value === "boolean") {
288
- bytes += 4;
289
- } else if (typeof value === "string") {
290
- bytes += value.length * 2;
291
- } else if (typeof value === "number") {
292
- bytes += 8;
293
- } else if (typeof value === "object" && value !== null && !objectList.includes(value)) {
294
- objectList.push(value);
295
- for (const key in value) {
296
- bytes += key.length * 2;
297
- stack.push(value[key]);
298
- }
299
- }
300
- }
301
- return bytes;
302
- }
303
378
  startInterval() {
304
379
  if (this.options.checkperiod && this.options.checkperiod > 0) {
305
380
  const checkPeriodinSeconds = this.options.checkperiod * 1e3;
@@ -330,24 +405,9 @@ var NodeCache = class extends import_eventemitter3.default {
330
405
  }
331
406
  return new Error(error);
332
407
  }
333
- isPrimitive(value) {
334
- const result = false;
335
- if (value === null || value === void 0) {
336
- return true;
337
- }
338
- if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
339
- return true;
340
- }
341
- return result;
342
- }
343
- clone(value) {
344
- if (this.isPrimitive(value)) {
345
- return value;
346
- }
347
- return structuredClone(value);
348
- }
349
408
  };
350
409
  // Annotate the CommonJS export names for ESM import in node:
351
410
  0 && (module.exports = {
352
- NodeCacheErrors
411
+ NodeCacheErrors,
412
+ NodeCacheStore
353
413
  });
package/dist/index.d.cts CHANGED
@@ -1,4 +1,37 @@
1
1
  import eventemitter from 'eventemitter3';
2
+ import { Cacheable } from 'cacheable';
3
+ import { Keyv } from 'keyv';
4
+
5
+ type NodeCacheStoreOptions = {
6
+ ttl?: number;
7
+ maxKeys?: number;
8
+ primary?: Keyv;
9
+ secondary?: Keyv;
10
+ };
11
+ declare class NodeCacheStore {
12
+ private _maxKeys;
13
+ private readonly _cache;
14
+ constructor(options?: NodeCacheStoreOptions);
15
+ get cache(): Cacheable;
16
+ get ttl(): number | undefined;
17
+ set ttl(ttl: number | undefined);
18
+ get primary(): Keyv;
19
+ set primary(primary: Keyv);
20
+ get secondary(): Keyv | undefined;
21
+ set secondary(secondary: Keyv | undefined);
22
+ get maxKeys(): number;
23
+ set maxKeys(maxKeys: number);
24
+ set(key: string | number, value: any, ttl?: number): Promise<boolean>;
25
+ mset(list: NodeCacheItem[]): Promise<void>;
26
+ get<T>(key: string | number): Promise<T | undefined>;
27
+ mget<T>(keys: Array<string | number>): Promise<Record<string, T | undefined>>;
28
+ del(key: string | number): Promise<boolean>;
29
+ mdel(keys: Array<string | number>): Promise<boolean>;
30
+ clear(): Promise<void>;
31
+ setTtl(key: string | number, ttl?: number): Promise<boolean>;
32
+ take<T>(key: string | number): Promise<T | undefined>;
33
+ disconnect(): Promise<void>;
34
+ }
2
35
 
3
36
  type NodeCacheOptions = {
4
37
  stdTTL?: number;
@@ -29,6 +62,7 @@ declare class NodeCache extends eventemitter {
29
62
  readonly options: NodeCacheOptions;
30
63
  readonly store: Map<string, any>;
31
64
  private _stats;
65
+ private readonly _cacheable;
32
66
  private intervalId;
33
67
  constructor(options?: NodeCacheOptions);
34
68
  set(key: string | number, value: any, ttl?: number): boolean;
@@ -49,16 +83,10 @@ declare class NodeCache extends eventemitter {
49
83
  getIntervalId(): number | NodeJS.Timeout;
50
84
  private formatKey;
51
85
  private getExpirationTimestamp;
52
- private addHit;
53
- private addMiss;
54
- private roughSizeOfKey;
55
- private roughSizeOfObject;
56
86
  private startInterval;
57
87
  private checkData;
58
88
  private stopInterval;
59
89
  private createError;
60
- private isPrimitive;
61
- private clone;
62
90
  }
63
91
 
64
- export { NodeCacheErrors, type NodeCacheItem, type NodeCacheOptions, type NodeCacheStats, NodeCache as default };
92
+ export { NodeCacheErrors, type NodeCacheItem, type NodeCacheOptions, type NodeCacheStats, NodeCacheStore, type NodeCacheStoreOptions, NodeCache as default };
package/dist/index.d.ts CHANGED
@@ -1,4 +1,37 @@
1
1
  import eventemitter from 'eventemitter3';
2
+ import { Cacheable } from 'cacheable';
3
+ import { Keyv } from 'keyv';
4
+
5
+ type NodeCacheStoreOptions = {
6
+ ttl?: number;
7
+ maxKeys?: number;
8
+ primary?: Keyv;
9
+ secondary?: Keyv;
10
+ };
11
+ declare class NodeCacheStore {
12
+ private _maxKeys;
13
+ private readonly _cache;
14
+ constructor(options?: NodeCacheStoreOptions);
15
+ get cache(): Cacheable;
16
+ get ttl(): number | undefined;
17
+ set ttl(ttl: number | undefined);
18
+ get primary(): Keyv;
19
+ set primary(primary: Keyv);
20
+ get secondary(): Keyv | undefined;
21
+ set secondary(secondary: Keyv | undefined);
22
+ get maxKeys(): number;
23
+ set maxKeys(maxKeys: number);
24
+ set(key: string | number, value: any, ttl?: number): Promise<boolean>;
25
+ mset(list: NodeCacheItem[]): Promise<void>;
26
+ get<T>(key: string | number): Promise<T | undefined>;
27
+ mget<T>(keys: Array<string | number>): Promise<Record<string, T | undefined>>;
28
+ del(key: string | number): Promise<boolean>;
29
+ mdel(keys: Array<string | number>): Promise<boolean>;
30
+ clear(): Promise<void>;
31
+ setTtl(key: string | number, ttl?: number): Promise<boolean>;
32
+ take<T>(key: string | number): Promise<T | undefined>;
33
+ disconnect(): Promise<void>;
34
+ }
2
35
 
3
36
  type NodeCacheOptions = {
4
37
  stdTTL?: number;
@@ -29,6 +62,7 @@ declare class NodeCache extends eventemitter {
29
62
  readonly options: NodeCacheOptions;
30
63
  readonly store: Map<string, any>;
31
64
  private _stats;
65
+ private readonly _cacheable;
32
66
  private intervalId;
33
67
  constructor(options?: NodeCacheOptions);
34
68
  set(key: string | number, value: any, ttl?: number): boolean;
@@ -49,16 +83,10 @@ declare class NodeCache extends eventemitter {
49
83
  getIntervalId(): number | NodeJS.Timeout;
50
84
  private formatKey;
51
85
  private getExpirationTimestamp;
52
- private addHit;
53
- private addMiss;
54
- private roughSizeOfKey;
55
- private roughSizeOfObject;
56
86
  private startInterval;
57
87
  private checkData;
58
88
  private stopInterval;
59
89
  private createError;
60
- private isPrimitive;
61
- private clone;
62
90
  }
63
91
 
64
- export { NodeCacheErrors, type NodeCacheItem, type NodeCacheOptions, type NodeCacheStats, NodeCache as default };
92
+ export { NodeCacheErrors, type NodeCacheItem, type NodeCacheOptions, type NodeCacheStats, NodeCacheStore, type NodeCacheStoreOptions, NodeCache as default };
package/dist/index.js CHANGED
@@ -1,5 +1,114 @@
1
1
  // src/index.ts
2
2
  import eventemitter from "eventemitter3";
3
+ import { CacheableMemory as CacheableMemory2, CacheableStats } from "cacheable";
4
+
5
+ // src/store.ts
6
+ import { Cacheable, CacheableMemory } from "cacheable";
7
+ import { Keyv } from "keyv";
8
+ var NodeCacheStore = class {
9
+ _maxKeys = 0;
10
+ _cache = new Cacheable({ primary: new Keyv({ store: new CacheableMemory() }) });
11
+ constructor(options) {
12
+ if (options) {
13
+ const cacheOptions = {
14
+ ttl: options.ttl,
15
+ primary: options.primary,
16
+ secondary: options.secondary
17
+ };
18
+ this._cache = new Cacheable(cacheOptions);
19
+ if (options.maxKeys) {
20
+ this._maxKeys = options.maxKeys;
21
+ if (this._maxKeys > 0) {
22
+ this._cache.stats.enabled = true;
23
+ }
24
+ }
25
+ }
26
+ }
27
+ get cache() {
28
+ return this._cache;
29
+ }
30
+ get ttl() {
31
+ return this._cache.ttl;
32
+ }
33
+ set ttl(ttl) {
34
+ this._cache.ttl = ttl;
35
+ }
36
+ get primary() {
37
+ return this._cache.primary;
38
+ }
39
+ set primary(primary) {
40
+ this._cache.primary = primary;
41
+ }
42
+ get secondary() {
43
+ return this._cache.secondary;
44
+ }
45
+ set secondary(secondary) {
46
+ this._cache.secondary = secondary;
47
+ }
48
+ get maxKeys() {
49
+ return this._maxKeys;
50
+ }
51
+ set maxKeys(maxKeys) {
52
+ this._maxKeys = maxKeys;
53
+ if (this._maxKeys > 0) {
54
+ this._cache.stats.enabled = true;
55
+ }
56
+ }
57
+ async set(key, value, ttl) {
58
+ if (this._maxKeys > 0) {
59
+ console.log(this._cache.stats.count, this._maxKeys);
60
+ if (this._cache.stats.count >= this._maxKeys) {
61
+ return false;
62
+ }
63
+ }
64
+ const finalTtl = ttl ?? this._cache.ttl;
65
+ await this._cache.set(key.toString(), value, finalTtl);
66
+ return true;
67
+ }
68
+ async mset(list) {
69
+ const items = new Array();
70
+ for (const item of list) {
71
+ items.push({ key: item.key.toString(), value: item.value, ttl: item.ttl });
72
+ }
73
+ await this._cache.setMany(items);
74
+ }
75
+ async get(key) {
76
+ return this._cache.get(key.toString());
77
+ }
78
+ async mget(keys) {
79
+ const result = {};
80
+ for (const key of keys) {
81
+ result[key.toString()] = await this._cache.get(key.toString());
82
+ }
83
+ return result;
84
+ }
85
+ async del(key) {
86
+ return this._cache.delete(key.toString());
87
+ }
88
+ async mdel(keys) {
89
+ return this._cache.deleteMany(keys.map((key) => key.toString()));
90
+ }
91
+ async clear() {
92
+ return this._cache.clear();
93
+ }
94
+ async setTtl(key, ttl) {
95
+ const finalTtl = ttl ?? this._cache.ttl;
96
+ const item = await this._cache.get(key.toString());
97
+ if (item) {
98
+ await this._cache.set(key.toString(), item, finalTtl);
99
+ return true;
100
+ }
101
+ return false;
102
+ }
103
+ async take(key) {
104
+ return this._cache.take(key.toString());
105
+ }
106
+ async disconnect() {
107
+ await this._cache.disconnect();
108
+ }
109
+ };
110
+
111
+ // src/index.ts
3
112
  var NodeCacheErrors = /* @__PURE__ */ ((NodeCacheErrors2) => {
4
113
  NodeCacheErrors2["ECACHEFULL"] = "Cache max keys amount exceeded";
5
114
  NodeCacheErrors2["EKEYTYPE"] = "The key argument has to be of type `string` or `number`. Found: `__key`";
@@ -17,13 +126,8 @@ var NodeCache = class extends eventemitter {
17
126
  maxKeys: -1
18
127
  };
19
128
  store = /* @__PURE__ */ new Map();
20
- _stats = {
21
- keys: 0,
22
- hits: 0,
23
- misses: 0,
24
- ksize: 0,
25
- vsize: 0
26
- };
129
+ _stats = new CacheableStats({ enabled: true });
130
+ _cacheable = new CacheableMemory2();
27
131
  intervalId = 0;
28
132
  constructor(options) {
29
133
  super();
@@ -54,9 +158,9 @@ var NodeCache = class extends eventemitter {
54
158
  }
55
159
  this.store.set(keyValue, { key: keyValue, value, ttl: expirationTimestamp });
56
160
  this.emit("set", keyValue, value, ttlValue);
57
- this._stats.ksize += this.roughSizeOfKey(keyValue);
58
- this._stats.vsize += this.roughSizeOfObject(value);
59
- this._stats.keys = this.store.size;
161
+ this._stats.incrementKSize(keyValue);
162
+ this._stats.incrementVSize(value);
163
+ this._stats.setCount(this.store.size);
60
164
  return true;
61
165
  }
62
166
  // Sets multiple key val pairs. It is possible to define a ttl (seconds). Returns true on success.
@@ -78,23 +182,23 @@ var NodeCache = class extends eventemitter {
78
182
  if (this.options.deleteOnExpire) {
79
183
  this.del(key);
80
184
  }
81
- this.addMiss();
185
+ this._stats.incrementMisses();
82
186
  this.emit("expired", this.formatKey(key), result.value);
83
187
  return void 0;
84
188
  }
85
- this.addHit();
189
+ this._stats.incrementHits();
86
190
  if (this.options.useClones) {
87
- return this.clone(result.value);
191
+ return this._cacheable.clone(result.value);
88
192
  }
89
193
  return result.value;
90
194
  }
91
- this.addHit();
195
+ this._stats.incrementHits();
92
196
  if (this.options.useClones) {
93
- return this.clone(result.value);
197
+ return this._cacheable.clone(result.value);
94
198
  }
95
199
  return result.value;
96
200
  }
97
- this.addMiss();
201
+ this._stats.incrementMisses();
98
202
  return void 0;
99
203
  }
100
204
  /*
@@ -121,7 +225,7 @@ var NodeCache = class extends eventemitter {
121
225
  if (result) {
122
226
  this.del(key);
123
227
  if (this.options.useClones) {
124
- return this.clone(result);
228
+ return this._cacheable.clone(result);
125
229
  }
126
230
  return result;
127
231
  }
@@ -137,9 +241,9 @@ var NodeCache = class extends eventemitter {
137
241
  const keyValue = this.formatKey(key);
138
242
  this.store.delete(keyValue);
139
243
  this.emit("del", keyValue, result.value);
140
- this._stats.ksize -= this.roughSizeOfKey(keyValue);
141
- this._stats.vsize -= this.roughSizeOfObject(result.value);
142
- this._stats.keys = this.store.size;
244
+ this._stats.decreaseKSize(keyValue);
245
+ this._stats.decreaseVSize(result.value);
246
+ this._stats.setCount(this.store.size);
143
247
  return 1;
144
248
  }
145
249
  return 0;
@@ -198,7 +302,14 @@ var NodeCache = class extends eventemitter {
198
302
  }
199
303
  // Gets the stats of the cache.
200
304
  getStats() {
201
- return this._stats;
305
+ const stats = {
306
+ keys: this._stats.count,
307
+ hits: this._stats.hits,
308
+ misses: this._stats.misses,
309
+ ksize: this._stats.ksize,
310
+ vsize: this._stats.vsize
311
+ };
312
+ return stats;
202
313
  }
203
314
  // Flush the whole data.
204
315
  flushAll() {
@@ -208,13 +319,7 @@ var NodeCache = class extends eventemitter {
208
319
  }
209
320
  // Flush the stats
210
321
  flushStats() {
211
- this._stats = {
212
- keys: 0,
213
- hits: 0,
214
- misses: 0,
215
- ksize: 0,
216
- vsize: 0
217
- };
322
+ this._stats = new CacheableStats({ enabled: true });
218
323
  this.emit("flush_stats");
219
324
  }
220
325
  // Close the cache. This will clear the interval timeout which is set on check period option.
@@ -234,37 +339,6 @@ var NodeCache = class extends eventemitter {
234
339
  const expirationTimestamp = currentTimestamp + ttlInMilliseconds;
235
340
  return expirationTimestamp;
236
341
  }
237
- addHit() {
238
- this._stats.hits++;
239
- }
240
- addMiss() {
241
- this._stats.misses++;
242
- }
243
- roughSizeOfKey(key) {
244
- return this.formatKey(key).toString().length * 2;
245
- }
246
- roughSizeOfObject(object) {
247
- const objectList = [];
248
- const stack = [object];
249
- let bytes = 0;
250
- while (stack.length > 0) {
251
- const value = stack.pop();
252
- if (typeof value === "boolean") {
253
- bytes += 4;
254
- } else if (typeof value === "string") {
255
- bytes += value.length * 2;
256
- } else if (typeof value === "number") {
257
- bytes += 8;
258
- } else if (typeof value === "object" && value !== null && !objectList.includes(value)) {
259
- objectList.push(value);
260
- for (const key in value) {
261
- bytes += key.length * 2;
262
- stack.push(value[key]);
263
- }
264
- }
265
- }
266
- return bytes;
267
- }
268
342
  startInterval() {
269
343
  if (this.options.checkperiod && this.options.checkperiod > 0) {
270
344
  const checkPeriodinSeconds = this.options.checkperiod * 1e3;
@@ -295,24 +369,9 @@ var NodeCache = class extends eventemitter {
295
369
  }
296
370
  return new Error(error);
297
371
  }
298
- isPrimitive(value) {
299
- const result = false;
300
- if (value === null || value === void 0) {
301
- return true;
302
- }
303
- if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
304
- return true;
305
- }
306
- return result;
307
- }
308
- clone(value) {
309
- if (this.isPrimitive(value)) {
310
- return value;
311
- }
312
- return structuredClone(value);
313
- }
314
372
  };
315
373
  export {
316
374
  NodeCacheErrors,
375
+ NodeCacheStore,
317
376
  NodeCache as default
318
377
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cacheable/node-cache",
3
- "version": "0.8.0",
3
+ "version": "1.1.0",
4
4
  "description": "Simple and Maintained fast NodeJS internal caching",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -30,14 +30,15 @@
30
30
  "@types/node": "^22.5.5",
31
31
  "@vitest/coverage-v8": "^2.1.1",
32
32
  "rimraf": "^6.0.1",
33
- "tsup": "^8.2.4",
33
+ "tsup": "^8.3.0",
34
34
  "typescript": "^5.6.2",
35
35
  "vitest": "^2.1.1",
36
36
  "xo": "^0.59.3"
37
37
  },
38
38
  "dependencies": {
39
- "cacheable": "^0.8.0",
40
- "eventemitter3": "^5.0.1"
39
+ "cacheable": "^1.2.0",
40
+ "eventemitter3": "^5.0.1",
41
+ "keyv": "^5.0.1"
41
42
  },
42
43
  "files": [
43
44
  "dist",