@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 +44 -0
- package/dist/index.cjs +136 -76
- package/dist/index.d.cts +35 -7
- package/dist/index.d.ts +35 -7
- package/dist/index.js +134 -75
- package/package.json +5 -4
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
|
-
|
|
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.
|
|
93
|
-
this._stats.
|
|
94
|
-
this._stats.
|
|
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.
|
|
221
|
+
this._stats.incrementMisses();
|
|
117
222
|
this.emit("expired", this.formatKey(key), result.value);
|
|
118
223
|
return void 0;
|
|
119
224
|
}
|
|
120
|
-
this.
|
|
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.
|
|
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.
|
|
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.
|
|
176
|
-
this._stats.
|
|
177
|
-
this._stats.
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
58
|
-
this._stats.
|
|
59
|
-
this._stats.
|
|
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.
|
|
185
|
+
this._stats.incrementMisses();
|
|
82
186
|
this.emit("expired", this.formatKey(key), result.value);
|
|
83
187
|
return void 0;
|
|
84
188
|
}
|
|
85
|
-
this.
|
|
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.
|
|
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.
|
|
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.
|
|
141
|
-
this._stats.
|
|
142
|
-
this._stats.
|
|
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
|
-
|
|
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": "
|
|
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.
|
|
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": "^
|
|
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",
|