@cacheable/node-cache 0.5.0 → 0.8.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/LICENSE +1 -1
- package/README.md +2 -2
- package/dist/index.cjs +353 -0
- package/dist/index.d.cts +64 -0
- package/dist/index.d.ts +8 -6
- package/dist/index.js +292 -318
- package/package.json +17 -8
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
package/LICENSE
CHANGED
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
> Simple and Maintained fast Node.js caching
|
|
6
6
|
|
|
7
|
-
[](https://codecov.io/gh/jaredwray/cacheable)
|
|
8
8
|
[](https://github.com/jaredwray/cacheable/actions/workflows/tests.yml)
|
|
9
9
|
[](https://www.npmjs.com/package/cacheable)
|
|
10
10
|
[](https://www.npmjs.com/package/cacheable)
|
|
@@ -259,4 +259,4 @@ cache.on('set', (key, value) => {
|
|
|
259
259
|
You can contribute by forking the repo and submitting a pull request. Please make sure to add tests and update the documentation. To learn more about how to contribute go to our main README [https://github.com/jaredwray/cacheable](https://github.com/jaredwray/cacheable). This will talk about how to `Open a Pull Request`, `Ask a Question`, or `Post an Issue`.
|
|
260
260
|
|
|
261
261
|
## License and Copyright
|
|
262
|
-
[MIT © Jared Wray](
|
|
262
|
+
[MIT © Jared Wray](./LICENSE)
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,353 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
|
|
30
|
+
// src/index.ts
|
|
31
|
+
var src_exports = {};
|
|
32
|
+
__export(src_exports, {
|
|
33
|
+
NodeCacheErrors: () => NodeCacheErrors,
|
|
34
|
+
default: () => NodeCache
|
|
35
|
+
});
|
|
36
|
+
module.exports = __toCommonJS(src_exports);
|
|
37
|
+
var import_eventemitter3 = __toESM(require("eventemitter3"), 1);
|
|
38
|
+
var NodeCacheErrors = /* @__PURE__ */ ((NodeCacheErrors2) => {
|
|
39
|
+
NodeCacheErrors2["ECACHEFULL"] = "Cache max keys amount exceeded";
|
|
40
|
+
NodeCacheErrors2["EKEYTYPE"] = "The key argument has to be of type `string` or `number`. Found: `__key`";
|
|
41
|
+
NodeCacheErrors2["EKEYSTYPE"] = "The keys argument has to be an array.";
|
|
42
|
+
NodeCacheErrors2["ETTLTYPE"] = "The ttl argument has to be a number.";
|
|
43
|
+
return NodeCacheErrors2;
|
|
44
|
+
})(NodeCacheErrors || {});
|
|
45
|
+
var NodeCache = class extends import_eventemitter3.default {
|
|
46
|
+
options = {
|
|
47
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
48
|
+
stdTTL: 0,
|
|
49
|
+
checkperiod: 600,
|
|
50
|
+
useClones: true,
|
|
51
|
+
deleteOnExpire: true,
|
|
52
|
+
maxKeys: -1
|
|
53
|
+
};
|
|
54
|
+
store = /* @__PURE__ */ new Map();
|
|
55
|
+
_stats = {
|
|
56
|
+
keys: 0,
|
|
57
|
+
hits: 0,
|
|
58
|
+
misses: 0,
|
|
59
|
+
ksize: 0,
|
|
60
|
+
vsize: 0
|
|
61
|
+
};
|
|
62
|
+
intervalId = 0;
|
|
63
|
+
constructor(options) {
|
|
64
|
+
super();
|
|
65
|
+
if (options) {
|
|
66
|
+
this.options = { ...this.options, ...options };
|
|
67
|
+
}
|
|
68
|
+
this.startInterval();
|
|
69
|
+
}
|
|
70
|
+
// Sets a key value pair. It is possible to define a ttl (in seconds). Returns true on success.
|
|
71
|
+
set(key, value, ttl) {
|
|
72
|
+
if (typeof key !== "string" && typeof key !== "number") {
|
|
73
|
+
throw this.createError("The key argument has to be of type `string` or `number`. Found: `__key`" /* EKEYTYPE */, key);
|
|
74
|
+
}
|
|
75
|
+
if (ttl && typeof ttl !== "number") {
|
|
76
|
+
throw this.createError("The ttl argument has to be a number." /* ETTLTYPE */, this.formatKey(key));
|
|
77
|
+
}
|
|
78
|
+
const keyValue = this.formatKey(key);
|
|
79
|
+
const ttlValue = ttl ?? this.options.stdTTL;
|
|
80
|
+
let expirationTimestamp = 0;
|
|
81
|
+
if (ttlValue && ttlValue > 0) {
|
|
82
|
+
expirationTimestamp = this.getExpirationTimestamp(ttlValue);
|
|
83
|
+
}
|
|
84
|
+
if (this.options.maxKeys) {
|
|
85
|
+
const maxKeys = this.options.maxKeys;
|
|
86
|
+
if (maxKeys > -1 && this.store.size >= maxKeys) {
|
|
87
|
+
throw this.createError("Cache max keys amount exceeded" /* ECACHEFULL */, this.formatKey(key));
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
this.store.set(keyValue, { key: keyValue, value, ttl: expirationTimestamp });
|
|
91
|
+
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;
|
|
95
|
+
return true;
|
|
96
|
+
}
|
|
97
|
+
// Sets multiple key val pairs. It is possible to define a ttl (seconds). Returns true on success.
|
|
98
|
+
mset(data) {
|
|
99
|
+
if (!Array.isArray(data)) {
|
|
100
|
+
throw this.createError("The keys argument has to be an array." /* EKEYSTYPE */);
|
|
101
|
+
}
|
|
102
|
+
for (const item of data) {
|
|
103
|
+
this.set(item.key, item.value, item.ttl);
|
|
104
|
+
}
|
|
105
|
+
return true;
|
|
106
|
+
}
|
|
107
|
+
// Gets a saved value from the cache. Returns a undefined if not found or expired. If the value was found it returns the value.
|
|
108
|
+
get(key) {
|
|
109
|
+
const result = this.store.get(this.formatKey(key));
|
|
110
|
+
if (result) {
|
|
111
|
+
if (result.ttl > 0) {
|
|
112
|
+
if (result.ttl < Date.now()) {
|
|
113
|
+
if (this.options.deleteOnExpire) {
|
|
114
|
+
this.del(key);
|
|
115
|
+
}
|
|
116
|
+
this.addMiss();
|
|
117
|
+
this.emit("expired", this.formatKey(key), result.value);
|
|
118
|
+
return void 0;
|
|
119
|
+
}
|
|
120
|
+
this.addHit();
|
|
121
|
+
if (this.options.useClones) {
|
|
122
|
+
return this.clone(result.value);
|
|
123
|
+
}
|
|
124
|
+
return result.value;
|
|
125
|
+
}
|
|
126
|
+
this.addHit();
|
|
127
|
+
if (this.options.useClones) {
|
|
128
|
+
return this.clone(result.value);
|
|
129
|
+
}
|
|
130
|
+
return result.value;
|
|
131
|
+
}
|
|
132
|
+
this.addMiss();
|
|
133
|
+
return void 0;
|
|
134
|
+
}
|
|
135
|
+
/*
|
|
136
|
+
Gets multiple saved values from the cache. Returns an empty object {} if not found or expired.
|
|
137
|
+
If the value was found it returns an object with the key value pair.
|
|
138
|
+
*/
|
|
139
|
+
mget(keys) {
|
|
140
|
+
const result = {};
|
|
141
|
+
for (const key of keys) {
|
|
142
|
+
const value = this.get(key);
|
|
143
|
+
if (value) {
|
|
144
|
+
result[this.formatKey(key)] = value;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
return result;
|
|
148
|
+
}
|
|
149
|
+
/*
|
|
150
|
+
Get the cached value and remove the key from the cache.
|
|
151
|
+
Equivalent to calling get(key) + del(key).
|
|
152
|
+
Useful for implementing single use mechanism such as OTP, where once a value is read it will become obsolete.
|
|
153
|
+
*/
|
|
154
|
+
take(key) {
|
|
155
|
+
const result = this.get(key);
|
|
156
|
+
if (result) {
|
|
157
|
+
this.del(key);
|
|
158
|
+
if (this.options.useClones) {
|
|
159
|
+
return this.clone(result);
|
|
160
|
+
}
|
|
161
|
+
return result;
|
|
162
|
+
}
|
|
163
|
+
return void 0;
|
|
164
|
+
}
|
|
165
|
+
// Delete a key. Returns the number of deleted entries. A delete will never fail.
|
|
166
|
+
del(key) {
|
|
167
|
+
if (Array.isArray(key)) {
|
|
168
|
+
return this.mdel(key);
|
|
169
|
+
}
|
|
170
|
+
const result = this.store.get(this.formatKey(key));
|
|
171
|
+
if (result) {
|
|
172
|
+
const keyValue = this.formatKey(key);
|
|
173
|
+
this.store.delete(keyValue);
|
|
174
|
+
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;
|
|
178
|
+
return 1;
|
|
179
|
+
}
|
|
180
|
+
return 0;
|
|
181
|
+
}
|
|
182
|
+
// Delete all keys in Array that exist. Returns the number of deleted entries.
|
|
183
|
+
mdel(keys) {
|
|
184
|
+
let result = 0;
|
|
185
|
+
for (const key of keys) {
|
|
186
|
+
result += this.del(key);
|
|
187
|
+
}
|
|
188
|
+
return result;
|
|
189
|
+
}
|
|
190
|
+
// Redefine the ttl of a key. Returns true if the key has been found and changed.
|
|
191
|
+
// Otherwise returns false. If the ttl-argument isn't passed the default-TTL will be used.
|
|
192
|
+
ttl(key, ttl) {
|
|
193
|
+
const result = this.store.get(this.formatKey(key));
|
|
194
|
+
if (result) {
|
|
195
|
+
const ttlValue = ttl ?? this.options.stdTTL;
|
|
196
|
+
result.ttl = this.getExpirationTimestamp(ttlValue);
|
|
197
|
+
this.store.set(this.formatKey(key), result);
|
|
198
|
+
return true;
|
|
199
|
+
}
|
|
200
|
+
return false;
|
|
201
|
+
}
|
|
202
|
+
/*
|
|
203
|
+
Receive the ttl of a key. You will get:
|
|
204
|
+
|
|
205
|
+
undefined if the key does not exist
|
|
206
|
+
0 if this key has no ttl
|
|
207
|
+
a timestamp in ms representing the time at which the key will expire
|
|
208
|
+
*/
|
|
209
|
+
getTtl(key) {
|
|
210
|
+
const result = this.store.get(this.formatKey(key));
|
|
211
|
+
if (result) {
|
|
212
|
+
if (result.ttl === 0) {
|
|
213
|
+
return 0;
|
|
214
|
+
}
|
|
215
|
+
return result.ttl;
|
|
216
|
+
}
|
|
217
|
+
return void 0;
|
|
218
|
+
}
|
|
219
|
+
/*
|
|
220
|
+
Returns an array of all existing keys.
|
|
221
|
+
[ "all", "my", "keys", "foo", "bar" ]
|
|
222
|
+
*/
|
|
223
|
+
keys() {
|
|
224
|
+
const result = [];
|
|
225
|
+
for (const key of this.store.keys()) {
|
|
226
|
+
result.push(key);
|
|
227
|
+
}
|
|
228
|
+
return result;
|
|
229
|
+
}
|
|
230
|
+
// Returns boolean indicating if the key is cached.
|
|
231
|
+
has(key) {
|
|
232
|
+
return this.store.has(this.formatKey(key));
|
|
233
|
+
}
|
|
234
|
+
// Gets the stats of the cache.
|
|
235
|
+
getStats() {
|
|
236
|
+
return this._stats;
|
|
237
|
+
}
|
|
238
|
+
// Flush the whole data.
|
|
239
|
+
flushAll() {
|
|
240
|
+
this.store.clear();
|
|
241
|
+
this.flushStats();
|
|
242
|
+
this.emit("flush");
|
|
243
|
+
}
|
|
244
|
+
// Flush the stats
|
|
245
|
+
flushStats() {
|
|
246
|
+
this._stats = {
|
|
247
|
+
keys: 0,
|
|
248
|
+
hits: 0,
|
|
249
|
+
misses: 0,
|
|
250
|
+
ksize: 0,
|
|
251
|
+
vsize: 0
|
|
252
|
+
};
|
|
253
|
+
this.emit("flush_stats");
|
|
254
|
+
}
|
|
255
|
+
// Close the cache. This will clear the interval timeout which is set on check period option.
|
|
256
|
+
close() {
|
|
257
|
+
this.stopInterval();
|
|
258
|
+
}
|
|
259
|
+
// Get the interval id
|
|
260
|
+
getIntervalId() {
|
|
261
|
+
return this.intervalId;
|
|
262
|
+
}
|
|
263
|
+
formatKey(key) {
|
|
264
|
+
return key.toString();
|
|
265
|
+
}
|
|
266
|
+
getExpirationTimestamp(ttlInSeconds) {
|
|
267
|
+
const currentTimestamp = Date.now();
|
|
268
|
+
const ttlInMilliseconds = ttlInSeconds * 1e3;
|
|
269
|
+
const expirationTimestamp = currentTimestamp + ttlInMilliseconds;
|
|
270
|
+
return expirationTimestamp;
|
|
271
|
+
}
|
|
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
|
+
startInterval() {
|
|
304
|
+
if (this.options.checkperiod && this.options.checkperiod > 0) {
|
|
305
|
+
const checkPeriodinSeconds = this.options.checkperiod * 1e3;
|
|
306
|
+
this.intervalId = setInterval(() => {
|
|
307
|
+
this.checkData();
|
|
308
|
+
}, checkPeriodinSeconds);
|
|
309
|
+
return;
|
|
310
|
+
}
|
|
311
|
+
this.intervalId = 0;
|
|
312
|
+
}
|
|
313
|
+
checkData() {
|
|
314
|
+
for (const [key, value] of this.store.entries()) {
|
|
315
|
+
if (value.ttl > 0 && value.ttl < Date.now()) {
|
|
316
|
+
this.del(key);
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
stopInterval() {
|
|
321
|
+
if (this.intervalId !== 0) {
|
|
322
|
+
clearInterval(this.intervalId);
|
|
323
|
+
this.intervalId = 0;
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
createError(errorCode, key) {
|
|
327
|
+
let error = errorCode;
|
|
328
|
+
if (key) {
|
|
329
|
+
error = error.replace("__key", key);
|
|
330
|
+
}
|
|
331
|
+
return new Error(error);
|
|
332
|
+
}
|
|
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
|
+
};
|
|
350
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
351
|
+
0 && (module.exports = {
|
|
352
|
+
NodeCacheErrors
|
|
353
|
+
});
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import eventemitter from 'eventemitter3';
|
|
2
|
+
|
|
3
|
+
type NodeCacheOptions = {
|
|
4
|
+
stdTTL?: number;
|
|
5
|
+
checkperiod?: number;
|
|
6
|
+
useClones?: boolean;
|
|
7
|
+
deleteOnExpire?: boolean;
|
|
8
|
+
maxKeys?: number;
|
|
9
|
+
};
|
|
10
|
+
type NodeCacheItem = {
|
|
11
|
+
key: string | number;
|
|
12
|
+
value: any;
|
|
13
|
+
ttl?: number;
|
|
14
|
+
};
|
|
15
|
+
declare enum NodeCacheErrors {
|
|
16
|
+
ECACHEFULL = "Cache max keys amount exceeded",
|
|
17
|
+
EKEYTYPE = "The key argument has to be of type `string` or `number`. Found: `__key`",
|
|
18
|
+
EKEYSTYPE = "The keys argument has to be an array.",
|
|
19
|
+
ETTLTYPE = "The ttl argument has to be a number."
|
|
20
|
+
}
|
|
21
|
+
type NodeCacheStats = {
|
|
22
|
+
keys: number;
|
|
23
|
+
hits: number;
|
|
24
|
+
misses: number;
|
|
25
|
+
ksize: number;
|
|
26
|
+
vsize: number;
|
|
27
|
+
};
|
|
28
|
+
declare class NodeCache extends eventemitter {
|
|
29
|
+
readonly options: NodeCacheOptions;
|
|
30
|
+
readonly store: Map<string, any>;
|
|
31
|
+
private _stats;
|
|
32
|
+
private intervalId;
|
|
33
|
+
constructor(options?: NodeCacheOptions);
|
|
34
|
+
set(key: string | number, value: any, ttl?: number): boolean;
|
|
35
|
+
mset(data: NodeCacheItem[]): boolean;
|
|
36
|
+
get(key: string | number): any;
|
|
37
|
+
mget(keys: Array<string | number>): Record<string, unknown>;
|
|
38
|
+
take(key: string | number): any;
|
|
39
|
+
del(key: string | number | Array<string | number>): number;
|
|
40
|
+
mdel(keys: Array<string | number>): number;
|
|
41
|
+
ttl(key: string | number, ttl?: number): boolean;
|
|
42
|
+
getTtl(key: string | number): number | undefined;
|
|
43
|
+
keys(): string[];
|
|
44
|
+
has(key: string | number): boolean;
|
|
45
|
+
getStats(): NodeCacheStats;
|
|
46
|
+
flushAll(): void;
|
|
47
|
+
flushStats(): void;
|
|
48
|
+
close(): void;
|
|
49
|
+
getIntervalId(): number | NodeJS.Timeout;
|
|
50
|
+
private formatKey;
|
|
51
|
+
private getExpirationTimestamp;
|
|
52
|
+
private addHit;
|
|
53
|
+
private addMiss;
|
|
54
|
+
private roughSizeOfKey;
|
|
55
|
+
private roughSizeOfObject;
|
|
56
|
+
private startInterval;
|
|
57
|
+
private checkData;
|
|
58
|
+
private stopInterval;
|
|
59
|
+
private createError;
|
|
60
|
+
private isPrimitive;
|
|
61
|
+
private clone;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export { NodeCacheErrors, type NodeCacheItem, type NodeCacheOptions, type NodeCacheStats, NodeCache as default };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,30 +1,31 @@
|
|
|
1
1
|
import eventemitter from 'eventemitter3';
|
|
2
|
-
|
|
2
|
+
|
|
3
|
+
type NodeCacheOptions = {
|
|
3
4
|
stdTTL?: number;
|
|
4
5
|
checkperiod?: number;
|
|
5
6
|
useClones?: boolean;
|
|
6
7
|
deleteOnExpire?: boolean;
|
|
7
8
|
maxKeys?: number;
|
|
8
9
|
};
|
|
9
|
-
|
|
10
|
+
type NodeCacheItem = {
|
|
10
11
|
key: string | number;
|
|
11
12
|
value: any;
|
|
12
13
|
ttl?: number;
|
|
13
14
|
};
|
|
14
|
-
|
|
15
|
+
declare enum NodeCacheErrors {
|
|
15
16
|
ECACHEFULL = "Cache max keys amount exceeded",
|
|
16
17
|
EKEYTYPE = "The key argument has to be of type `string` or `number`. Found: `__key`",
|
|
17
18
|
EKEYSTYPE = "The keys argument has to be an array.",
|
|
18
19
|
ETTLTYPE = "The ttl argument has to be a number."
|
|
19
20
|
}
|
|
20
|
-
|
|
21
|
+
type NodeCacheStats = {
|
|
21
22
|
keys: number;
|
|
22
23
|
hits: number;
|
|
23
24
|
misses: number;
|
|
24
25
|
ksize: number;
|
|
25
26
|
vsize: number;
|
|
26
27
|
};
|
|
27
|
-
|
|
28
|
+
declare class NodeCache extends eventemitter {
|
|
28
29
|
readonly options: NodeCacheOptions;
|
|
29
30
|
readonly store: Map<string, any>;
|
|
30
31
|
private _stats;
|
|
@@ -59,4 +60,5 @@ export default class NodeCache extends eventemitter {
|
|
|
59
60
|
private isPrimitive;
|
|
60
61
|
private clone;
|
|
61
62
|
}
|
|
62
|
-
|
|
63
|
+
|
|
64
|
+
export { NodeCacheErrors, type NodeCacheItem, type NodeCacheOptions, type NodeCacheStats, NodeCache as default };
|
package/dist/index.js
CHANGED
|
@@ -1,344 +1,318 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
ksize: 0,
|
|
33
|
-
vsize: 0,
|
|
34
|
-
};
|
|
35
|
-
this.intervalId = 0;
|
|
36
|
-
if (options) {
|
|
37
|
-
this.options = Object.assign(Object.assign({}, this.options), options);
|
|
38
|
-
}
|
|
39
|
-
this.startInterval();
|
|
1
|
+
// src/index.ts
|
|
2
|
+
import eventemitter from "eventemitter3";
|
|
3
|
+
var NodeCacheErrors = /* @__PURE__ */ ((NodeCacheErrors2) => {
|
|
4
|
+
NodeCacheErrors2["ECACHEFULL"] = "Cache max keys amount exceeded";
|
|
5
|
+
NodeCacheErrors2["EKEYTYPE"] = "The key argument has to be of type `string` or `number`. Found: `__key`";
|
|
6
|
+
NodeCacheErrors2["EKEYSTYPE"] = "The keys argument has to be an array.";
|
|
7
|
+
NodeCacheErrors2["ETTLTYPE"] = "The ttl argument has to be a number.";
|
|
8
|
+
return NodeCacheErrors2;
|
|
9
|
+
})(NodeCacheErrors || {});
|
|
10
|
+
var NodeCache = class extends eventemitter {
|
|
11
|
+
options = {
|
|
12
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
13
|
+
stdTTL: 0,
|
|
14
|
+
checkperiod: 600,
|
|
15
|
+
useClones: true,
|
|
16
|
+
deleteOnExpire: true,
|
|
17
|
+
maxKeys: -1
|
|
18
|
+
};
|
|
19
|
+
store = /* @__PURE__ */ new Map();
|
|
20
|
+
_stats = {
|
|
21
|
+
keys: 0,
|
|
22
|
+
hits: 0,
|
|
23
|
+
misses: 0,
|
|
24
|
+
ksize: 0,
|
|
25
|
+
vsize: 0
|
|
26
|
+
};
|
|
27
|
+
intervalId = 0;
|
|
28
|
+
constructor(options) {
|
|
29
|
+
super();
|
|
30
|
+
if (options) {
|
|
31
|
+
this.options = { ...this.options, ...options };
|
|
40
32
|
}
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
}
|
|
48
|
-
// Check on ttl type
|
|
49
|
-
/* c8 ignore next 3 */
|
|
50
|
-
if (ttl && typeof ttl !== 'number') {
|
|
51
|
-
throw this.createError(NodeCacheErrors.ETTLTYPE, this.formatKey(key));
|
|
52
|
-
}
|
|
53
|
-
const keyValue = this.formatKey(key);
|
|
54
|
-
const ttlValue = ttl !== null && ttl !== void 0 ? ttl : this.options.stdTTL;
|
|
55
|
-
let expirationTimestamp = 0; // Never delete
|
|
56
|
-
if (ttlValue && ttlValue > 0) {
|
|
57
|
-
expirationTimestamp = this.getExpirationTimestamp(ttlValue);
|
|
58
|
-
}
|
|
59
|
-
// Check on max key size
|
|
60
|
-
if (this.options.maxKeys) {
|
|
61
|
-
const maxKeys = this.options.maxKeys;
|
|
62
|
-
if (maxKeys > -1 && this.store.size >= maxKeys) {
|
|
63
|
-
throw this.createError(NodeCacheErrors.ECACHEFULL, this.formatKey(key));
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
this.store.set(keyValue, { key: keyValue, value, ttl: expirationTimestamp });
|
|
67
|
-
// Event
|
|
68
|
-
this.emit('set', keyValue, value, ttlValue);
|
|
69
|
-
// Add the bytes to the stats
|
|
70
|
-
this._stats.ksize += this.roughSizeOfKey(keyValue);
|
|
71
|
-
this._stats.vsize += this.roughSizeOfObject(value);
|
|
72
|
-
this._stats.keys = this.store.size;
|
|
73
|
-
return true;
|
|
74
|
-
}
|
|
75
|
-
// Sets multiple key val pairs. It is possible to define a ttl (seconds). Returns true on success.
|
|
76
|
-
mset(data) {
|
|
77
|
-
// Check on keys type
|
|
78
|
-
/* c8 ignore next 3 */
|
|
79
|
-
if (!Array.isArray(data)) {
|
|
80
|
-
throw this.createError(NodeCacheErrors.EKEYSTYPE);
|
|
81
|
-
}
|
|
82
|
-
for (const item of data) {
|
|
83
|
-
this.set(item.key, item.value, item.ttl);
|
|
84
|
-
}
|
|
85
|
-
return true;
|
|
33
|
+
this.startInterval();
|
|
34
|
+
}
|
|
35
|
+
// Sets a key value pair. It is possible to define a ttl (in seconds). Returns true on success.
|
|
36
|
+
set(key, value, ttl) {
|
|
37
|
+
if (typeof key !== "string" && typeof key !== "number") {
|
|
38
|
+
throw this.createError("The key argument has to be of type `string` or `number`. Found: `__key`" /* EKEYTYPE */, key);
|
|
86
39
|
}
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
const result = this.store.get(this.formatKey(key));
|
|
90
|
-
if (result) {
|
|
91
|
-
if (result.ttl > 0) {
|
|
92
|
-
if (result.ttl < Date.now()) {
|
|
93
|
-
if (this.options.deleteOnExpire) {
|
|
94
|
-
this.del(key);
|
|
95
|
-
}
|
|
96
|
-
this.addMiss();
|
|
97
|
-
// Event
|
|
98
|
-
this.emit('expired', this.formatKey(key), result.value);
|
|
99
|
-
return undefined;
|
|
100
|
-
}
|
|
101
|
-
this.addHit();
|
|
102
|
-
if (this.options.useClones) {
|
|
103
|
-
return this.clone(result.value);
|
|
104
|
-
}
|
|
105
|
-
return result.value;
|
|
106
|
-
}
|
|
107
|
-
this.addHit();
|
|
108
|
-
if (this.options.useClones) {
|
|
109
|
-
return this.clone(result.value);
|
|
110
|
-
}
|
|
111
|
-
return result.value;
|
|
112
|
-
}
|
|
113
|
-
this.addMiss();
|
|
114
|
-
return undefined;
|
|
40
|
+
if (ttl && typeof ttl !== "number") {
|
|
41
|
+
throw this.createError("The ttl argument has to be a number." /* ETTLTYPE */, this.formatKey(key));
|
|
115
42
|
}
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
const result = {};
|
|
122
|
-
for (const key of keys) {
|
|
123
|
-
const value = this.get(key);
|
|
124
|
-
if (value) {
|
|
125
|
-
result[this.formatKey(key)] = value;
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
return result;
|
|
43
|
+
const keyValue = this.formatKey(key);
|
|
44
|
+
const ttlValue = ttl ?? this.options.stdTTL;
|
|
45
|
+
let expirationTimestamp = 0;
|
|
46
|
+
if (ttlValue && ttlValue > 0) {
|
|
47
|
+
expirationTimestamp = this.getExpirationTimestamp(ttlValue);
|
|
129
48
|
}
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
take(key) {
|
|
136
|
-
const result = this.get(key);
|
|
137
|
-
if (result) {
|
|
138
|
-
this.del(key);
|
|
139
|
-
if (this.options.useClones) {
|
|
140
|
-
return this.clone(result);
|
|
141
|
-
}
|
|
142
|
-
return result;
|
|
143
|
-
}
|
|
144
|
-
return undefined;
|
|
49
|
+
if (this.options.maxKeys) {
|
|
50
|
+
const maxKeys = this.options.maxKeys;
|
|
51
|
+
if (maxKeys > -1 && this.store.size >= maxKeys) {
|
|
52
|
+
throw this.createError("Cache max keys amount exceeded" /* ECACHEFULL */, this.formatKey(key));
|
|
53
|
+
}
|
|
145
54
|
}
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
// Remove the bytes from the stats
|
|
158
|
-
this._stats.ksize -= this.roughSizeOfKey(keyValue);
|
|
159
|
-
this._stats.vsize -= this.roughSizeOfObject(result.value);
|
|
160
|
-
this._stats.keys = this.store.size;
|
|
161
|
-
return 1;
|
|
162
|
-
}
|
|
163
|
-
return 0;
|
|
55
|
+
this.store.set(keyValue, { key: keyValue, value, ttl: expirationTimestamp });
|
|
56
|
+
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;
|
|
60
|
+
return true;
|
|
61
|
+
}
|
|
62
|
+
// Sets multiple key val pairs. It is possible to define a ttl (seconds). Returns true on success.
|
|
63
|
+
mset(data) {
|
|
64
|
+
if (!Array.isArray(data)) {
|
|
65
|
+
throw this.createError("The keys argument has to be an array." /* EKEYSTYPE */);
|
|
164
66
|
}
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
let result = 0;
|
|
168
|
-
for (const key of keys) {
|
|
169
|
-
result += this.del(key);
|
|
170
|
-
}
|
|
171
|
-
return result;
|
|
67
|
+
for (const item of data) {
|
|
68
|
+
this.set(item.key, item.value, item.ttl);
|
|
172
69
|
}
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
undefined if the key does not exist
|
|
189
|
-
0 if this key has no ttl
|
|
190
|
-
a timestamp in ms representing the time at which the key will expire
|
|
191
|
-
*/
|
|
192
|
-
getTtl(key) {
|
|
193
|
-
const result = this.store.get(this.formatKey(key));
|
|
194
|
-
if (result) {
|
|
195
|
-
if (result.ttl === 0) {
|
|
196
|
-
return 0;
|
|
197
|
-
}
|
|
198
|
-
return result.ttl;
|
|
70
|
+
return true;
|
|
71
|
+
}
|
|
72
|
+
// Gets a saved value from the cache. Returns a undefined if not found or expired. If the value was found it returns the value.
|
|
73
|
+
get(key) {
|
|
74
|
+
const result = this.store.get(this.formatKey(key));
|
|
75
|
+
if (result) {
|
|
76
|
+
if (result.ttl > 0) {
|
|
77
|
+
if (result.ttl < Date.now()) {
|
|
78
|
+
if (this.options.deleteOnExpire) {
|
|
79
|
+
this.del(key);
|
|
80
|
+
}
|
|
81
|
+
this.addMiss();
|
|
82
|
+
this.emit("expired", this.formatKey(key), result.value);
|
|
83
|
+
return void 0;
|
|
199
84
|
}
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
Returns an array of all existing keys.
|
|
204
|
-
[ "all", "my", "keys", "foo", "bar" ]
|
|
205
|
-
*/
|
|
206
|
-
keys() {
|
|
207
|
-
const result = [];
|
|
208
|
-
for (const key of this.store.keys()) {
|
|
209
|
-
result.push(key);
|
|
85
|
+
this.addHit();
|
|
86
|
+
if (this.options.useClones) {
|
|
87
|
+
return this.clone(result.value);
|
|
210
88
|
}
|
|
211
|
-
return result;
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
return this.
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
getStats() {
|
|
219
|
-
return this._stats;
|
|
89
|
+
return result.value;
|
|
90
|
+
}
|
|
91
|
+
this.addHit();
|
|
92
|
+
if (this.options.useClones) {
|
|
93
|
+
return this.clone(result.value);
|
|
94
|
+
}
|
|
95
|
+
return result.value;
|
|
220
96
|
}
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
97
|
+
this.addMiss();
|
|
98
|
+
return void 0;
|
|
99
|
+
}
|
|
100
|
+
/*
|
|
101
|
+
Gets multiple saved values from the cache. Returns an empty object {} if not found or expired.
|
|
102
|
+
If the value was found it returns an object with the key value pair.
|
|
103
|
+
*/
|
|
104
|
+
mget(keys) {
|
|
105
|
+
const result = {};
|
|
106
|
+
for (const key of keys) {
|
|
107
|
+
const value = this.get(key);
|
|
108
|
+
if (value) {
|
|
109
|
+
result[this.formatKey(key)] = value;
|
|
110
|
+
}
|
|
227
111
|
}
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
112
|
+
return result;
|
|
113
|
+
}
|
|
114
|
+
/*
|
|
115
|
+
Get the cached value and remove the key from the cache.
|
|
116
|
+
Equivalent to calling get(key) + del(key).
|
|
117
|
+
Useful for implementing single use mechanism such as OTP, where once a value is read it will become obsolete.
|
|
118
|
+
*/
|
|
119
|
+
take(key) {
|
|
120
|
+
const result = this.get(key);
|
|
121
|
+
if (result) {
|
|
122
|
+
this.del(key);
|
|
123
|
+
if (this.options.useClones) {
|
|
124
|
+
return this.clone(result);
|
|
125
|
+
}
|
|
126
|
+
return result;
|
|
239
127
|
}
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
128
|
+
return void 0;
|
|
129
|
+
}
|
|
130
|
+
// Delete a key. Returns the number of deleted entries. A delete will never fail.
|
|
131
|
+
del(key) {
|
|
132
|
+
if (Array.isArray(key)) {
|
|
133
|
+
return this.mdel(key);
|
|
243
134
|
}
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
135
|
+
const result = this.store.get(this.formatKey(key));
|
|
136
|
+
if (result) {
|
|
137
|
+
const keyValue = this.formatKey(key);
|
|
138
|
+
this.store.delete(keyValue);
|
|
139
|
+
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;
|
|
143
|
+
return 1;
|
|
247
144
|
}
|
|
248
|
-
|
|
249
|
-
|
|
145
|
+
return 0;
|
|
146
|
+
}
|
|
147
|
+
// Delete all keys in Array that exist. Returns the number of deleted entries.
|
|
148
|
+
mdel(keys) {
|
|
149
|
+
let result = 0;
|
|
150
|
+
for (const key of keys) {
|
|
151
|
+
result += this.del(key);
|
|
250
152
|
}
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
153
|
+
return result;
|
|
154
|
+
}
|
|
155
|
+
// Redefine the ttl of a key. Returns true if the key has been found and changed.
|
|
156
|
+
// Otherwise returns false. If the ttl-argument isn't passed the default-TTL will be used.
|
|
157
|
+
ttl(key, ttl) {
|
|
158
|
+
const result = this.store.get(this.formatKey(key));
|
|
159
|
+
if (result) {
|
|
160
|
+
const ttlValue = ttl ?? this.options.stdTTL;
|
|
161
|
+
result.ttl = this.getExpirationTimestamp(ttlValue);
|
|
162
|
+
this.store.set(this.formatKey(key), result);
|
|
163
|
+
return true;
|
|
256
164
|
}
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
165
|
+
return false;
|
|
166
|
+
}
|
|
167
|
+
/*
|
|
168
|
+
Receive the ttl of a key. You will get:
|
|
169
|
+
|
|
170
|
+
undefined if the key does not exist
|
|
171
|
+
0 if this key has no ttl
|
|
172
|
+
a timestamp in ms representing the time at which the key will expire
|
|
173
|
+
*/
|
|
174
|
+
getTtl(key) {
|
|
175
|
+
const result = this.store.get(this.formatKey(key));
|
|
176
|
+
if (result) {
|
|
177
|
+
if (result.ttl === 0) {
|
|
178
|
+
return 0;
|
|
179
|
+
}
|
|
180
|
+
return result.ttl;
|
|
262
181
|
}
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
182
|
+
return void 0;
|
|
183
|
+
}
|
|
184
|
+
/*
|
|
185
|
+
Returns an array of all existing keys.
|
|
186
|
+
[ "all", "my", "keys", "foo", "bar" ]
|
|
187
|
+
*/
|
|
188
|
+
keys() {
|
|
189
|
+
const result = [];
|
|
190
|
+
for (const key of this.store.keys()) {
|
|
191
|
+
result.push(key);
|
|
266
192
|
}
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
193
|
+
return result;
|
|
194
|
+
}
|
|
195
|
+
// Returns boolean indicating if the key is cached.
|
|
196
|
+
has(key) {
|
|
197
|
+
return this.store.has(this.formatKey(key));
|
|
198
|
+
}
|
|
199
|
+
// Gets the stats of the cache.
|
|
200
|
+
getStats() {
|
|
201
|
+
return this._stats;
|
|
202
|
+
}
|
|
203
|
+
// Flush the whole data.
|
|
204
|
+
flushAll() {
|
|
205
|
+
this.store.clear();
|
|
206
|
+
this.flushStats();
|
|
207
|
+
this.emit("flush");
|
|
208
|
+
}
|
|
209
|
+
// Flush the stats
|
|
210
|
+
flushStats() {
|
|
211
|
+
this._stats = {
|
|
212
|
+
keys: 0,
|
|
213
|
+
hits: 0,
|
|
214
|
+
misses: 0,
|
|
215
|
+
ksize: 0,
|
|
216
|
+
vsize: 0
|
|
217
|
+
};
|
|
218
|
+
this.emit("flush_stats");
|
|
219
|
+
}
|
|
220
|
+
// Close the cache. This will clear the interval timeout which is set on check period option.
|
|
221
|
+
close() {
|
|
222
|
+
this.stopInterval();
|
|
223
|
+
}
|
|
224
|
+
// Get the interval id
|
|
225
|
+
getIntervalId() {
|
|
226
|
+
return this.intervalId;
|
|
227
|
+
}
|
|
228
|
+
formatKey(key) {
|
|
229
|
+
return key.toString();
|
|
230
|
+
}
|
|
231
|
+
getExpirationTimestamp(ttlInSeconds) {
|
|
232
|
+
const currentTimestamp = Date.now();
|
|
233
|
+
const ttlInMilliseconds = ttlInSeconds * 1e3;
|
|
234
|
+
const expirationTimestamp = currentTimestamp + ttlInMilliseconds;
|
|
235
|
+
return expirationTimestamp;
|
|
236
|
+
}
|
|
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]);
|
|
291
263
|
}
|
|
292
|
-
|
|
264
|
+
}
|
|
293
265
|
}
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
266
|
+
return bytes;
|
|
267
|
+
}
|
|
268
|
+
startInterval() {
|
|
269
|
+
if (this.options.checkperiod && this.options.checkperiod > 0) {
|
|
270
|
+
const checkPeriodinSeconds = this.options.checkperiod * 1e3;
|
|
271
|
+
this.intervalId = setInterval(() => {
|
|
272
|
+
this.checkData();
|
|
273
|
+
}, checkPeriodinSeconds);
|
|
274
|
+
return;
|
|
303
275
|
}
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
276
|
+
this.intervalId = 0;
|
|
277
|
+
}
|
|
278
|
+
checkData() {
|
|
279
|
+
for (const [key, value] of this.store.entries()) {
|
|
280
|
+
if (value.ttl > 0 && value.ttl < Date.now()) {
|
|
281
|
+
this.del(key);
|
|
282
|
+
}
|
|
310
283
|
}
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
284
|
+
}
|
|
285
|
+
stopInterval() {
|
|
286
|
+
if (this.intervalId !== 0) {
|
|
287
|
+
clearInterval(this.intervalId);
|
|
288
|
+
this.intervalId = 0;
|
|
316
289
|
}
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
}
|
|
323
|
-
return new Error(error);
|
|
290
|
+
}
|
|
291
|
+
createError(errorCode, key) {
|
|
292
|
+
let error = errorCode;
|
|
293
|
+
if (key) {
|
|
294
|
+
error = error.replace("__key", key);
|
|
324
295
|
}
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {
|
|
332
|
-
return true;
|
|
333
|
-
}
|
|
334
|
-
return result;
|
|
296
|
+
return new Error(error);
|
|
297
|
+
}
|
|
298
|
+
isPrimitive(value) {
|
|
299
|
+
const result = false;
|
|
300
|
+
if (value === null || value === void 0) {
|
|
301
|
+
return true;
|
|
335
302
|
}
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
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;
|
|
341
311
|
}
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
312
|
+
return structuredClone(value);
|
|
313
|
+
}
|
|
314
|
+
};
|
|
315
|
+
export {
|
|
316
|
+
NodeCacheErrors,
|
|
317
|
+
NodeCache as default
|
|
318
|
+
};
|
package/package.json
CHANGED
|
@@ -1,9 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cacheable/node-cache",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"description": "Simple and Maintained fast NodeJS internal caching",
|
|
5
|
-
"
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.cjs",
|
|
7
|
+
"module": "./dist/index.js",
|
|
6
8
|
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"require": "./dist/index.cjs",
|
|
12
|
+
"import": "./dist/index.js"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
7
15
|
"repository": "https://github.com/jaredwray/cacheable.git",
|
|
8
16
|
"author": "Jared Wray <me@jaredwray.com>",
|
|
9
17
|
"license": "MIT",
|
|
@@ -19,15 +27,16 @@
|
|
|
19
27
|
"cacheable-node"
|
|
20
28
|
],
|
|
21
29
|
"devDependencies": {
|
|
22
|
-
"@types/node": "^22.5.
|
|
23
|
-
"@vitest/coverage-v8": "^2.
|
|
30
|
+
"@types/node": "^22.5.5",
|
|
31
|
+
"@vitest/coverage-v8": "^2.1.1",
|
|
24
32
|
"rimraf": "^6.0.1",
|
|
25
|
-
"
|
|
26
|
-
"
|
|
33
|
+
"tsup": "^8.2.4",
|
|
34
|
+
"typescript": "^5.6.2",
|
|
35
|
+
"vitest": "^2.1.1",
|
|
27
36
|
"xo": "^0.59.3"
|
|
28
37
|
},
|
|
29
38
|
"dependencies": {
|
|
30
|
-
"cacheable": "^0.
|
|
39
|
+
"cacheable": "^0.8.0",
|
|
31
40
|
"eventemitter3": "^5.0.1"
|
|
32
41
|
},
|
|
33
42
|
"files": [
|
|
@@ -35,7 +44,7 @@
|
|
|
35
44
|
"license"
|
|
36
45
|
],
|
|
37
46
|
"scripts": {
|
|
38
|
-
"build": "rimraf ./dist &&
|
|
47
|
+
"build": "rimraf ./dist && tsup src/index.ts --format cjs,esm --dts --clean",
|
|
39
48
|
"test": "xo --fix && vitest run --coverage",
|
|
40
49
|
"test:ci": "xo && vitest run",
|
|
41
50
|
"clean": "rimraf ./dist ./coverage ./node_modules"
|
package/dist/index.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,YAAY,MAAM,eAAe,CAAC;AAEzC,MAAM,MAAM,gBAAgB,GAAG;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC3B,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC;IACrB,KAAK,EAAE,GAAG,CAAC;IACX,GAAG,CAAC,EAAE,MAAM,CAAC;CACb,CAAC;AAEF,oBAAY,eAAe;IAC1B,UAAU,mCAAmC;IAC7C,QAAQ,4EAA4E;IACpF,SAAS,0CAA0C;IACnD,QAAQ,yCAAyC;CACjD;AAED,MAAM,MAAM,cAAc,GAAG;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,CAAC,OAAO,OAAO,SAAU,SAAQ,YAAY;IAClD,SAAgB,OAAO,EAAE,gBAAgB,CAOvC;IAEF,SAAgB,KAAK,mBAA0B;IAE/C,OAAO,CAAC,MAAM,CAMZ;IAEF,OAAO,CAAC,UAAU,CAA8B;gBAEpC,OAAO,CAAC,EAAE,gBAAgB;IAW/B,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO;IAyC5D,IAAI,CAAC,IAAI,EAAE,aAAa,EAAE,GAAG,OAAO;IAepC,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,GAAG;IAuC9B,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAkB3D,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,GAAG;IAgB/B,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,GAAG,MAAM;IAwB1D,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,GAAG,MAAM;IAW1C,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO;IAoBhD,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,SAAS;IAiBhD,IAAI,IAAI,MAAM,EAAE;IAWhB,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO;IAKlC,QAAQ,IAAI,cAAc;IAK1B,QAAQ,IAAI,IAAI;IAQhB,UAAU,IAAI,IAAI;IAclB,KAAK,IAAI,IAAI;IAKb,aAAa,IAAI,MAAM,GAAG,MAAM,CAAC,OAAO;IAI/C,OAAO,CAAC,SAAS;IAIjB,OAAO,CAAC,sBAAsB;IAO9B,OAAO,CAAC,MAAM;IAId,OAAO,CAAC,OAAO;IAIf,OAAO,CAAC,cAAc;IAKtB,OAAO,CAAC,iBAAiB;IA6BzB,OAAO,CAAC,aAAa;IAarB,OAAO,CAAC,SAAS;IAQjB,OAAO,CAAC,YAAY;IAOpB,OAAO,CAAC,WAAW;IAUnB,OAAO,CAAC,WAAW;IAenB,OAAO,CAAC,KAAK;CAOb"}
|
package/dist/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable @typescript-eslint/no-unsafe-assignment */\nimport eventemitter from 'eventemitter3';\n\nexport type NodeCacheOptions = {\n\tstdTTL?: number; // The standard ttl as number in seconds for every generated cache element. 0 = unlimited\n\tcheckperiod?: number; // Default is 600\n\tuseClones?: boolean; // Default is true\n\tdeleteOnExpire?: boolean; // Default is true\n\tmaxKeys?: number; // Default is -1\n};\n\nexport type NodeCacheItem = {\n\tkey: string | number;\n\tvalue: any;\n\tttl?: number;\n};\n\nexport enum NodeCacheErrors {\n\tECACHEFULL = 'Cache max keys amount exceeded',\n\tEKEYTYPE = 'The key argument has to be of type `string` or `number`. Found: `__key`',\n\tEKEYSTYPE = 'The keys argument has to be an array.',\n\tETTLTYPE = 'The ttl argument has to be a number.',\n}\n\nexport type NodeCacheStats = {\n\tkeys: number; // global key count\n\thits: number; // global hit count\n\tmisses: number; // global miss count\n\tksize: number; // global key size count in approximately bytes\n\tvsize: number; // global value size count in approximately bytes\n};\n\nexport default class NodeCache extends eventemitter {\n\tpublic readonly options: NodeCacheOptions = {\n\t\t// eslint-disable-next-line @typescript-eslint/naming-convention\n\t\tstdTTL: 0,\n\t\tcheckperiod: 600,\n\t\tuseClones: true,\n\t\tdeleteOnExpire: true,\n\t\tmaxKeys: -1,\n\t};\n\n\tpublic readonly store = new Map<string, any>();\n\n\tprivate _stats: NodeCacheStats = {\n\t\tkeys: 0,\n\t\thits: 0,\n\t\tmisses: 0,\n\t\tksize: 0,\n\t\tvsize: 0,\n\t};\n\n\tprivate intervalId: number | NodeJS.Timeout = 0;\n\n\tconstructor(options?: NodeCacheOptions) {\n\t\tsuper();\n\n\t\tif (options) {\n\t\t\tthis.options = {...this.options, ...options};\n\t\t}\n\n\t\tthis.startInterval();\n\t}\n\n\t// Sets a key value pair. It is possible to define a ttl (in seconds). Returns true on success.\n\tpublic set(key: string | number, value: any, ttl?: number): boolean {\n\t\t// Check on key type\n\t\t/* c8 ignore next 3 */\n\t\tif (typeof key !== 'string' && typeof key !== 'number') {\n\t\t\tthrow this.createError(NodeCacheErrors.EKEYTYPE, key);\n\t\t}\n\n\t\t// Check on ttl type\n\t\t/* c8 ignore next 3 */\n\t\tif (ttl && typeof ttl !== 'number') {\n\t\t\tthrow this.createError(NodeCacheErrors.ETTLTYPE, this.formatKey(key));\n\t\t}\n\n\t\tconst keyValue = this.formatKey(key);\n\t\tconst ttlValue = ttl ?? this.options.stdTTL;\n\t\tlet expirationTimestamp = 0; // Never delete\n\t\tif (ttlValue && ttlValue > 0) {\n\t\t\texpirationTimestamp = this.getExpirationTimestamp(ttlValue);\n\t\t}\n\n\t\t// Check on max key size\n\t\tif (this.options.maxKeys) {\n\t\t\tconst maxKeys = this.options.maxKeys;\n\t\t\tif (maxKeys > -1 && this.store.size >= maxKeys) {\n\t\t\t\tthrow this.createError(NodeCacheErrors.ECACHEFULL, this.formatKey(key));\n\t\t\t}\n\t\t}\n\n\t\tthis.store.set(keyValue, {key: keyValue, value, ttl: expirationTimestamp});\n\n\t\t// Event\n\t\tthis.emit('set', keyValue, value, ttlValue);\n\n\t\t// Add the bytes to the stats\n\t\tthis._stats.ksize += this.roughSizeOfKey(keyValue);\n\t\tthis._stats.vsize += this.roughSizeOfObject(value);\n\t\tthis._stats.keys = this.store.size;\n\t\treturn true;\n\t}\n\n\t// Sets multiple key val pairs. It is possible to define a ttl (seconds). Returns true on success.\n\tpublic mset(data: NodeCacheItem[]): boolean {\n\t\t// Check on keys type\n\t\t/* c8 ignore next 3 */\n\t\tif (!Array.isArray(data)) {\n\t\t\tthrow this.createError(NodeCacheErrors.EKEYSTYPE);\n\t\t}\n\n\t\tfor (const item of data) {\n\t\t\tthis.set(item.key, item.value, item.ttl);\n\t\t}\n\n\t\treturn true;\n\t}\n\n\t// Gets a saved value from the cache. Returns a undefined if not found or expired. If the value was found it returns the value.\n\tpublic get(key: string | number): any {\n\t\tconst result = this.store.get(this.formatKey(key));\n\t\tif (result) {\n\t\t\tif (result.ttl > 0) {\n\t\t\t\tif (result.ttl < Date.now()) {\n\t\t\t\t\tif (this.options.deleteOnExpire) {\n\t\t\t\t\t\tthis.del(key);\n\t\t\t\t\t}\n\n\t\t\t\t\tthis.addMiss();\n\t\t\t\t\t// Event\n\t\t\t\t\tthis.emit('expired', this.formatKey(key), result.value);\n\t\t\t\t\treturn undefined;\n\t\t\t\t}\n\n\t\t\t\tthis.addHit();\n\t\t\t\tif (this.options.useClones) {\n\t\t\t\t\treturn this.clone(result.value);\n\t\t\t\t}\n\n\t\t\t\treturn result.value;\n\t\t\t}\n\n\t\t\tthis.addHit();\n\t\t\tif (this.options.useClones) {\n\t\t\t\treturn this.clone(result.value);\n\t\t\t}\n\n\t\t\treturn result.value;\n\t\t}\n\n\t\tthis.addMiss();\n\t\treturn undefined;\n\t}\n\n\t/*\n\t\tGets multiple saved values from the cache. Returns an empty object {} if not found or expired.\n\t\tIf the value was found it returns an object with the key value pair.\n\t*/\n\tpublic mget(keys: Array<string | number>): Record<string, unknown> {\n\t\tconst result: Record<string, unknown> = {};\n\n\t\tfor (const key of keys) {\n\t\t\tconst value = this.get(key);\n\t\t\tif (value) {\n\t\t\t\tresult[this.formatKey(key)] = value;\n\t\t\t}\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t/*\n\t\tGet the cached value and remove the key from the cache.\n\t\tEquivalent to calling get(key) + del(key).\n\t\tUseful for implementing single use mechanism such as OTP, where once a value is read it will become obsolete.\n\t*/\n\tpublic take(key: string | number): any {\n\t\tconst result = this.get(key);\n\n\t\tif (result) {\n\t\t\tthis.del(key);\n\t\t\tif (this.options.useClones) {\n\t\t\t\treturn this.clone(result);\n\t\t\t}\n\n\t\t\treturn result;\n\t\t}\n\n\t\treturn undefined;\n\t}\n\n\t// Delete a key. Returns the number of deleted entries. A delete will never fail.\n\tpublic del(key: string | number | Array<string | number>): number {\n\t\tif (Array.isArray(key)) {\n\t\t\treturn this.mdel(key);\n\t\t}\n\n\t\tconst result = this.store.get(this.formatKey(key));\n\t\tif (result) {\n\t\t\tconst keyValue = this.formatKey(key);\n\t\t\tthis.store.delete(keyValue);\n\n\t\t\t// Event\n\t\t\tthis.emit('del', keyValue, result.value);\n\n\t\t\t// Remove the bytes from the stats\n\t\t\tthis._stats.ksize -= this.roughSizeOfKey(keyValue);\n\t\t\tthis._stats.vsize -= this.roughSizeOfObject(result.value);\n\t\t\tthis._stats.keys = this.store.size;\n\t\t\treturn 1;\n\t\t}\n\n\t\treturn 0;\n\t}\n\n\t// Delete all keys in Array that exist. Returns the number of deleted entries.\n\tpublic mdel(keys: Array<string | number>): number {\n\t\tlet result = 0;\n\t\tfor (const key of keys) {\n\t\t\tresult += this.del(key);\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t// Redefine the ttl of a key. Returns true if the key has been found and changed.\n\t// Otherwise returns false. If the ttl-argument isn't passed the default-TTL will be used.\n\tpublic ttl(key: string | number, ttl?: number): boolean {\n\t\tconst result = this.store.get(this.formatKey(key));\n\t\tif (result) {\n\t\t\tconst ttlValue = ttl ?? this.options.stdTTL!;\n\t\t\tresult.ttl = this.getExpirationTimestamp(ttlValue);\n\t\t\tthis.store.set(this.formatKey(key), result);\n\t\t\treturn true;\n\t\t}\n\n\t\treturn false;\n\t}\n\n\t/*\n\t\tReceive the ttl of a key. You will get:\n\n\t\tundefined if the key does not exist\n\t\t0 if this key has no ttl\n\t\ta timestamp in ms representing the time at which the key will expire\n\t*/\n\n\tpublic getTtl(key: string | number): number | undefined {\n\t\tconst result = this.store.get(this.formatKey(key));\n\t\tif (result) {\n\t\t\tif (result.ttl === 0) {\n\t\t\t\treturn 0;\n\t\t\t}\n\n\t\t\treturn result.ttl as number;\n\t\t}\n\n\t\treturn undefined;\n\t}\n\n\t/*\n\t\tReturns an array of all existing keys.\n\t\t[ \"all\", \"my\", \"keys\", \"foo\", \"bar\" ]\n\t*/\n\tpublic keys(): string[] {\n\t\tconst result: string[] = [];\n\n\t\tfor (const key of this.store.keys()) {\n\t\t\tresult.push(key);\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t// Returns boolean indicating if the key is cached.\n\tpublic has(key: string | number): boolean {\n\t\treturn this.store.has(this.formatKey(key));\n\t}\n\n\t// Gets the stats of the cache.\n\tpublic getStats(): NodeCacheStats {\n\t\treturn this._stats;\n\t}\n\n\t// Flush the whole data.\n\tpublic flushAll(): void {\n\t\tthis.store.clear();\n\t\tthis.flushStats();\n\t\t// Event\n\t\tthis.emit('flush');\n\t}\n\n\t// Flush the stats\n\tpublic flushStats(): void {\n\t\tthis._stats = {\n\t\t\tkeys: 0,\n\t\t\thits: 0,\n\t\t\tmisses: 0,\n\t\t\tksize: 0,\n\t\t\tvsize: 0,\n\t\t};\n\n\t\t// Event\n\t\tthis.emit('flush_stats');\n\t}\n\n\t// Close the cache. This will clear the interval timeout which is set on check period option.\n\tpublic close(): void {\n\t\tthis.stopInterval();\n\t}\n\n\t// Get the interval id\n\tpublic getIntervalId(): number | NodeJS.Timeout {\n\t\treturn this.intervalId;\n\t}\n\n\tprivate formatKey(key: string | number): string {\n\t\treturn key.toString();\n\t}\n\n\tprivate getExpirationTimestamp(ttlInSeconds: number): number {\n\t\tconst currentTimestamp = Date.now(); // Current time in milliseconds\n\t\tconst ttlInMilliseconds = ttlInSeconds * 1000; // Convert TTL to milliseconds\n\t\tconst expirationTimestamp = currentTimestamp + ttlInMilliseconds;\n\t\treturn expirationTimestamp;\n\t}\n\n\tprivate addHit(): void {\n\t\tthis._stats.hits++;\n\t}\n\n\tprivate addMiss(): void {\n\t\tthis._stats.misses++;\n\t}\n\n\tprivate roughSizeOfKey(key: string): number {\n\t\t// Keys are strings (UTF-16)\n\t\treturn this.formatKey(key).toString().length * 2;\n\t}\n\n\tprivate roughSizeOfObject(object: any): number {\n\t\tconst objectList: any[] = [];\n\t\tconst stack: any[] = [object];\n\t\tlet bytes = 0;\n\n\t\twhile (stack.length > 0) {\n\t\t\tconst value = stack.pop();\n\n\t\t\tif (typeof value === 'boolean') {\n\t\t\t\tbytes += 4; // Booleans are 4 bytes\n\t\t\t} else if (typeof value === 'string') {\n\t\t\t\tbytes += value.length * 2; // Each character is 2 bytes (UTF-16 encoding)\n\t\t\t} else if (typeof value === 'number') {\n\t\t\t\tbytes += 8; // Numbers are 8 bytes (IEEE 754 format)\n\t\t\t} else if (typeof value === 'object' && value !== null && !objectList.includes(value)) {\n\t\t\t\tobjectList.push(value);\n\n\t\t\t\t// Estimate object overhead, and then recursively estimate the size of properties\n\t\t\t\t// eslint-disable-next-line guard-for-in\n\t\t\t\tfor (const key in value) {\n\t\t\t\t\tbytes += key.length * 2; // Keys are strings (UTF-16)\n\t\t\t\t\tstack.push(value[key]); // Add values to the stack to compute their size\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn bytes;\n\t}\n\n\tprivate startInterval(): void {\n\t\tif (this.options.checkperiod && this.options.checkperiod > 0) {\n\t\t\tconst checkPeriodinSeconds = this.options.checkperiod * 1000;\n\t\t\tthis.intervalId = setInterval(() => {\n\t\t\t\tthis.checkData();\n\t\t\t}, checkPeriodinSeconds);\n\n\t\t\treturn;\n\t\t}\n\n\t\tthis.intervalId = 0;\n\t}\n\n\tprivate checkData(): void {\n\t\tfor (const [key, value] of this.store.entries()) {\n\t\t\tif (value.ttl > 0 && value.ttl < Date.now()) {\n\t\t\t\tthis.del(key);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate stopInterval(): void {\n\t\tif (this.intervalId !== 0) {\n\t\t\tclearInterval(this.intervalId);\n\t\t\tthis.intervalId = 0;\n\t\t}\n\t}\n\n\tprivate createError(errorCode: string, key?: string): Error {\n\t\tlet error = errorCode;\n\t\t/* c8 ignore next 3 */\n\t\tif (key) {\n\t\t\terror = error.replace('__key', key);\n\t\t}\n\n\t\treturn new Error(error);\n\t}\n\n\tprivate isPrimitive(value: any): boolean {\n\t\tconst result = false;\n\n\t\t/* c8 ignore next 3 */\n\t\tif (value === null || value === undefined) {\n\t\t\treturn true;\n\t\t}\n\n\t\tif (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {\n\t\t\treturn true;\n\t\t}\n\n\t\treturn result;\n\t}\n\n\tprivate clone(value: any): any {\n\t\tif (this.isPrimitive(value)) {\n\t\t\treturn value;\n\t\t}\n\n\t\treturn structuredClone(value);\n\t}\n}\n\n"]}
|