@cacheable/node-cache 0.8.0 → 1.0.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 +41 -0
- package/dist/index.cjs +121 -76
- package/dist/index.d.cts +32 -7
- package/dist/index.d.ts +32 -7
- package/dist/index.js +119 -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,46 @@ 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(key: string | number): Promise<any>` - 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
|
+
* `del(key: string | number): Promise<boolean>` - Delete a key
|
|
96
|
+
* `mdel(keys: Array<string | number>): Promise<boolean>` - Delete multiple keys
|
|
97
|
+
* `clear(): Promise<void>` - Clear the cache
|
|
98
|
+
* `stats`: `NodeCacheStats` - Get the stats of the cache
|
|
99
|
+
* `ttl`: `number` - The standard ttl as number in seconds for every generated cache element. 0 = unlimited
|
|
100
|
+
* `primary`: `Keyv` - The primary storage adapter
|
|
101
|
+
* `secondary`: `Keyv` - The secondary storage adapter
|
|
102
|
+
* `maxKeys`: `number` - If this is set it will throw and error if you try to set more keys than the max
|
|
103
|
+
|
|
63
104
|
## API
|
|
64
105
|
|
|
65
106
|
### `constructor(options?: NodeCacheOptions)`
|
package/dist/index.cjs
CHANGED
|
@@ -31,10 +31,105 @@ 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
|
+
};
|
|
131
|
+
|
|
132
|
+
// src/index.ts
|
|
38
133
|
var NodeCacheErrors = /* @__PURE__ */ ((NodeCacheErrors2) => {
|
|
39
134
|
NodeCacheErrors2["ECACHEFULL"] = "Cache max keys amount exceeded";
|
|
40
135
|
NodeCacheErrors2["EKEYTYPE"] = "The key argument has to be of type `string` or `number`. Found: `__key`";
|
|
@@ -52,13 +147,8 @@ var NodeCache = class extends import_eventemitter3.default {
|
|
|
52
147
|
maxKeys: -1
|
|
53
148
|
};
|
|
54
149
|
store = /* @__PURE__ */ new Map();
|
|
55
|
-
_stats = {
|
|
56
|
-
|
|
57
|
-
hits: 0,
|
|
58
|
-
misses: 0,
|
|
59
|
-
ksize: 0,
|
|
60
|
-
vsize: 0
|
|
61
|
-
};
|
|
150
|
+
_stats = new import_cacheable2.CacheableStats({ enabled: true });
|
|
151
|
+
_cacheable = new import_cacheable2.CacheableMemory();
|
|
62
152
|
intervalId = 0;
|
|
63
153
|
constructor(options) {
|
|
64
154
|
super();
|
|
@@ -89,9 +179,9 @@ var NodeCache = class extends import_eventemitter3.default {
|
|
|
89
179
|
}
|
|
90
180
|
this.store.set(keyValue, { key: keyValue, value, ttl: expirationTimestamp });
|
|
91
181
|
this.emit("set", keyValue, value, ttlValue);
|
|
92
|
-
this._stats.
|
|
93
|
-
this._stats.
|
|
94
|
-
this._stats.
|
|
182
|
+
this._stats.incrementKSize(keyValue);
|
|
183
|
+
this._stats.incrementVSize(value);
|
|
184
|
+
this._stats.setCount(this.store.size);
|
|
95
185
|
return true;
|
|
96
186
|
}
|
|
97
187
|
// Sets multiple key val pairs. It is possible to define a ttl (seconds). Returns true on success.
|
|
@@ -113,23 +203,23 @@ var NodeCache = class extends import_eventemitter3.default {
|
|
|
113
203
|
if (this.options.deleteOnExpire) {
|
|
114
204
|
this.del(key);
|
|
115
205
|
}
|
|
116
|
-
this.
|
|
206
|
+
this._stats.incrementMisses();
|
|
117
207
|
this.emit("expired", this.formatKey(key), result.value);
|
|
118
208
|
return void 0;
|
|
119
209
|
}
|
|
120
|
-
this.
|
|
210
|
+
this._stats.incrementHits();
|
|
121
211
|
if (this.options.useClones) {
|
|
122
|
-
return this.clone(result.value);
|
|
212
|
+
return this._cacheable.clone(result.value);
|
|
123
213
|
}
|
|
124
214
|
return result.value;
|
|
125
215
|
}
|
|
126
|
-
this.
|
|
216
|
+
this._stats.incrementHits();
|
|
127
217
|
if (this.options.useClones) {
|
|
128
|
-
return this.clone(result.value);
|
|
218
|
+
return this._cacheable.clone(result.value);
|
|
129
219
|
}
|
|
130
220
|
return result.value;
|
|
131
221
|
}
|
|
132
|
-
this.
|
|
222
|
+
this._stats.incrementMisses();
|
|
133
223
|
return void 0;
|
|
134
224
|
}
|
|
135
225
|
/*
|
|
@@ -156,7 +246,7 @@ var NodeCache = class extends import_eventemitter3.default {
|
|
|
156
246
|
if (result) {
|
|
157
247
|
this.del(key);
|
|
158
248
|
if (this.options.useClones) {
|
|
159
|
-
return this.clone(result);
|
|
249
|
+
return this._cacheable.clone(result);
|
|
160
250
|
}
|
|
161
251
|
return result;
|
|
162
252
|
}
|
|
@@ -172,9 +262,9 @@ var NodeCache = class extends import_eventemitter3.default {
|
|
|
172
262
|
const keyValue = this.formatKey(key);
|
|
173
263
|
this.store.delete(keyValue);
|
|
174
264
|
this.emit("del", keyValue, result.value);
|
|
175
|
-
this._stats.
|
|
176
|
-
this._stats.
|
|
177
|
-
this._stats.
|
|
265
|
+
this._stats.decreaseKSize(keyValue);
|
|
266
|
+
this._stats.decreaseVSize(result.value);
|
|
267
|
+
this._stats.setCount(this.store.size);
|
|
178
268
|
return 1;
|
|
179
269
|
}
|
|
180
270
|
return 0;
|
|
@@ -233,7 +323,14 @@ var NodeCache = class extends import_eventemitter3.default {
|
|
|
233
323
|
}
|
|
234
324
|
// Gets the stats of the cache.
|
|
235
325
|
getStats() {
|
|
236
|
-
|
|
326
|
+
const stats = {
|
|
327
|
+
keys: this._stats.count,
|
|
328
|
+
hits: this._stats.hits,
|
|
329
|
+
misses: this._stats.misses,
|
|
330
|
+
ksize: this._stats.ksize,
|
|
331
|
+
vsize: this._stats.vsize
|
|
332
|
+
};
|
|
333
|
+
return stats;
|
|
237
334
|
}
|
|
238
335
|
// Flush the whole data.
|
|
239
336
|
flushAll() {
|
|
@@ -243,13 +340,7 @@ var NodeCache = class extends import_eventemitter3.default {
|
|
|
243
340
|
}
|
|
244
341
|
// Flush the stats
|
|
245
342
|
flushStats() {
|
|
246
|
-
this._stats = {
|
|
247
|
-
keys: 0,
|
|
248
|
-
hits: 0,
|
|
249
|
-
misses: 0,
|
|
250
|
-
ksize: 0,
|
|
251
|
-
vsize: 0
|
|
252
|
-
};
|
|
343
|
+
this._stats = new import_cacheable2.CacheableStats({ enabled: true });
|
|
253
344
|
this.emit("flush_stats");
|
|
254
345
|
}
|
|
255
346
|
// Close the cache. This will clear the interval timeout which is set on check period option.
|
|
@@ -269,37 +360,6 @@ var NodeCache = class extends import_eventemitter3.default {
|
|
|
269
360
|
const expirationTimestamp = currentTimestamp + ttlInMilliseconds;
|
|
270
361
|
return expirationTimestamp;
|
|
271
362
|
}
|
|
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
363
|
startInterval() {
|
|
304
364
|
if (this.options.checkperiod && this.options.checkperiod > 0) {
|
|
305
365
|
const checkPeriodinSeconds = this.options.checkperiod * 1e3;
|
|
@@ -330,24 +390,9 @@ var NodeCache = class extends import_eventemitter3.default {
|
|
|
330
390
|
}
|
|
331
391
|
return new Error(error);
|
|
332
392
|
}
|
|
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
393
|
};
|
|
350
394
|
// Annotate the CommonJS export names for ESM import in node:
|
|
351
395
|
0 && (module.exports = {
|
|
352
|
-
NodeCacheErrors
|
|
396
|
+
NodeCacheErrors,
|
|
397
|
+
NodeCacheStore
|
|
353
398
|
});
|
package/dist/index.d.cts
CHANGED
|
@@ -1,4 +1,34 @@
|
|
|
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
|
+
}
|
|
2
32
|
|
|
3
33
|
type NodeCacheOptions = {
|
|
4
34
|
stdTTL?: number;
|
|
@@ -29,6 +59,7 @@ declare class NodeCache extends eventemitter {
|
|
|
29
59
|
readonly options: NodeCacheOptions;
|
|
30
60
|
readonly store: Map<string, any>;
|
|
31
61
|
private _stats;
|
|
62
|
+
private readonly _cacheable;
|
|
32
63
|
private intervalId;
|
|
33
64
|
constructor(options?: NodeCacheOptions);
|
|
34
65
|
set(key: string | number, value: any, ttl?: number): boolean;
|
|
@@ -49,16 +80,10 @@ declare class NodeCache extends eventemitter {
|
|
|
49
80
|
getIntervalId(): number | NodeJS.Timeout;
|
|
50
81
|
private formatKey;
|
|
51
82
|
private getExpirationTimestamp;
|
|
52
|
-
private addHit;
|
|
53
|
-
private addMiss;
|
|
54
|
-
private roughSizeOfKey;
|
|
55
|
-
private roughSizeOfObject;
|
|
56
83
|
private startInterval;
|
|
57
84
|
private checkData;
|
|
58
85
|
private stopInterval;
|
|
59
86
|
private createError;
|
|
60
|
-
private isPrimitive;
|
|
61
|
-
private clone;
|
|
62
87
|
}
|
|
63
88
|
|
|
64
|
-
export { NodeCacheErrors, type NodeCacheItem, type NodeCacheOptions, type NodeCacheStats, NodeCache as default };
|
|
89
|
+
export { NodeCacheErrors, type NodeCacheItem, type NodeCacheOptions, type NodeCacheStats, NodeCacheStore, type NodeCacheStoreOptions, NodeCache as default };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,34 @@
|
|
|
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
|
+
}
|
|
2
32
|
|
|
3
33
|
type NodeCacheOptions = {
|
|
4
34
|
stdTTL?: number;
|
|
@@ -29,6 +59,7 @@ declare class NodeCache extends eventemitter {
|
|
|
29
59
|
readonly options: NodeCacheOptions;
|
|
30
60
|
readonly store: Map<string, any>;
|
|
31
61
|
private _stats;
|
|
62
|
+
private readonly _cacheable;
|
|
32
63
|
private intervalId;
|
|
33
64
|
constructor(options?: NodeCacheOptions);
|
|
34
65
|
set(key: string | number, value: any, ttl?: number): boolean;
|
|
@@ -49,16 +80,10 @@ declare class NodeCache extends eventemitter {
|
|
|
49
80
|
getIntervalId(): number | NodeJS.Timeout;
|
|
50
81
|
private formatKey;
|
|
51
82
|
private getExpirationTimestamp;
|
|
52
|
-
private addHit;
|
|
53
|
-
private addMiss;
|
|
54
|
-
private roughSizeOfKey;
|
|
55
|
-
private roughSizeOfObject;
|
|
56
83
|
private startInterval;
|
|
57
84
|
private checkData;
|
|
58
85
|
private stopInterval;
|
|
59
86
|
private createError;
|
|
60
|
-
private isPrimitive;
|
|
61
|
-
private clone;
|
|
62
87
|
}
|
|
63
88
|
|
|
64
|
-
export { NodeCacheErrors, type NodeCacheItem, type NodeCacheOptions, type NodeCacheStats, NodeCache as default };
|
|
89
|
+
export { NodeCacheErrors, type NodeCacheItem, type NodeCacheOptions, type NodeCacheStats, NodeCacheStore, type NodeCacheStoreOptions, NodeCache as default };
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,99 @@
|
|
|
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
|
+
};
|
|
95
|
+
|
|
96
|
+
// src/index.ts
|
|
3
97
|
var NodeCacheErrors = /* @__PURE__ */ ((NodeCacheErrors2) => {
|
|
4
98
|
NodeCacheErrors2["ECACHEFULL"] = "Cache max keys amount exceeded";
|
|
5
99
|
NodeCacheErrors2["EKEYTYPE"] = "The key argument has to be of type `string` or `number`. Found: `__key`";
|
|
@@ -17,13 +111,8 @@ var NodeCache = class extends eventemitter {
|
|
|
17
111
|
maxKeys: -1
|
|
18
112
|
};
|
|
19
113
|
store = /* @__PURE__ */ new Map();
|
|
20
|
-
_stats = {
|
|
21
|
-
|
|
22
|
-
hits: 0,
|
|
23
|
-
misses: 0,
|
|
24
|
-
ksize: 0,
|
|
25
|
-
vsize: 0
|
|
26
|
-
};
|
|
114
|
+
_stats = new CacheableStats({ enabled: true });
|
|
115
|
+
_cacheable = new CacheableMemory2();
|
|
27
116
|
intervalId = 0;
|
|
28
117
|
constructor(options) {
|
|
29
118
|
super();
|
|
@@ -54,9 +143,9 @@ var NodeCache = class extends eventemitter {
|
|
|
54
143
|
}
|
|
55
144
|
this.store.set(keyValue, { key: keyValue, value, ttl: expirationTimestamp });
|
|
56
145
|
this.emit("set", keyValue, value, ttlValue);
|
|
57
|
-
this._stats.
|
|
58
|
-
this._stats.
|
|
59
|
-
this._stats.
|
|
146
|
+
this._stats.incrementKSize(keyValue);
|
|
147
|
+
this._stats.incrementVSize(value);
|
|
148
|
+
this._stats.setCount(this.store.size);
|
|
60
149
|
return true;
|
|
61
150
|
}
|
|
62
151
|
// Sets multiple key val pairs. It is possible to define a ttl (seconds). Returns true on success.
|
|
@@ -78,23 +167,23 @@ var NodeCache = class extends eventemitter {
|
|
|
78
167
|
if (this.options.deleteOnExpire) {
|
|
79
168
|
this.del(key);
|
|
80
169
|
}
|
|
81
|
-
this.
|
|
170
|
+
this._stats.incrementMisses();
|
|
82
171
|
this.emit("expired", this.formatKey(key), result.value);
|
|
83
172
|
return void 0;
|
|
84
173
|
}
|
|
85
|
-
this.
|
|
174
|
+
this._stats.incrementHits();
|
|
86
175
|
if (this.options.useClones) {
|
|
87
|
-
return this.clone(result.value);
|
|
176
|
+
return this._cacheable.clone(result.value);
|
|
88
177
|
}
|
|
89
178
|
return result.value;
|
|
90
179
|
}
|
|
91
|
-
this.
|
|
180
|
+
this._stats.incrementHits();
|
|
92
181
|
if (this.options.useClones) {
|
|
93
|
-
return this.clone(result.value);
|
|
182
|
+
return this._cacheable.clone(result.value);
|
|
94
183
|
}
|
|
95
184
|
return result.value;
|
|
96
185
|
}
|
|
97
|
-
this.
|
|
186
|
+
this._stats.incrementMisses();
|
|
98
187
|
return void 0;
|
|
99
188
|
}
|
|
100
189
|
/*
|
|
@@ -121,7 +210,7 @@ var NodeCache = class extends eventemitter {
|
|
|
121
210
|
if (result) {
|
|
122
211
|
this.del(key);
|
|
123
212
|
if (this.options.useClones) {
|
|
124
|
-
return this.clone(result);
|
|
213
|
+
return this._cacheable.clone(result);
|
|
125
214
|
}
|
|
126
215
|
return result;
|
|
127
216
|
}
|
|
@@ -137,9 +226,9 @@ var NodeCache = class extends eventemitter {
|
|
|
137
226
|
const keyValue = this.formatKey(key);
|
|
138
227
|
this.store.delete(keyValue);
|
|
139
228
|
this.emit("del", keyValue, result.value);
|
|
140
|
-
this._stats.
|
|
141
|
-
this._stats.
|
|
142
|
-
this._stats.
|
|
229
|
+
this._stats.decreaseKSize(keyValue);
|
|
230
|
+
this._stats.decreaseVSize(result.value);
|
|
231
|
+
this._stats.setCount(this.store.size);
|
|
143
232
|
return 1;
|
|
144
233
|
}
|
|
145
234
|
return 0;
|
|
@@ -198,7 +287,14 @@ var NodeCache = class extends eventemitter {
|
|
|
198
287
|
}
|
|
199
288
|
// Gets the stats of the cache.
|
|
200
289
|
getStats() {
|
|
201
|
-
|
|
290
|
+
const stats = {
|
|
291
|
+
keys: this._stats.count,
|
|
292
|
+
hits: this._stats.hits,
|
|
293
|
+
misses: this._stats.misses,
|
|
294
|
+
ksize: this._stats.ksize,
|
|
295
|
+
vsize: this._stats.vsize
|
|
296
|
+
};
|
|
297
|
+
return stats;
|
|
202
298
|
}
|
|
203
299
|
// Flush the whole data.
|
|
204
300
|
flushAll() {
|
|
@@ -208,13 +304,7 @@ var NodeCache = class extends eventemitter {
|
|
|
208
304
|
}
|
|
209
305
|
// Flush the stats
|
|
210
306
|
flushStats() {
|
|
211
|
-
this._stats = {
|
|
212
|
-
keys: 0,
|
|
213
|
-
hits: 0,
|
|
214
|
-
misses: 0,
|
|
215
|
-
ksize: 0,
|
|
216
|
-
vsize: 0
|
|
217
|
-
};
|
|
307
|
+
this._stats = new CacheableStats({ enabled: true });
|
|
218
308
|
this.emit("flush_stats");
|
|
219
309
|
}
|
|
220
310
|
// Close the cache. This will clear the interval timeout which is set on check period option.
|
|
@@ -234,37 +324,6 @@ var NodeCache = class extends eventemitter {
|
|
|
234
324
|
const expirationTimestamp = currentTimestamp + ttlInMilliseconds;
|
|
235
325
|
return expirationTimestamp;
|
|
236
326
|
}
|
|
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
327
|
startInterval() {
|
|
269
328
|
if (this.options.checkperiod && this.options.checkperiod > 0) {
|
|
270
329
|
const checkPeriodinSeconds = this.options.checkperiod * 1e3;
|
|
@@ -295,24 +354,9 @@ var NodeCache = class extends eventemitter {
|
|
|
295
354
|
}
|
|
296
355
|
return new Error(error);
|
|
297
356
|
}
|
|
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
357
|
};
|
|
315
358
|
export {
|
|
316
359
|
NodeCacheErrors,
|
|
360
|
+
NodeCacheStore,
|
|
317
361
|
NodeCache as default
|
|
318
362
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cacheable/node-cache",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.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",
|