cachimbo 0.0.1 → 0.0.3
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 +26 -21
- package/dist/index.cjs +149 -38
- package/dist/index.d.cts +88 -16
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.ts +88 -16
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +149 -38
- package/dist/index.js.map +1 -1
- package/package.json +24 -21
package/dist/index.js
CHANGED
|
@@ -40,6 +40,67 @@ var BaseCache = class {
|
|
|
40
40
|
}
|
|
41
41
|
};
|
|
42
42
|
|
|
43
|
+
//#endregion
|
|
44
|
+
//#region src/base/local.ts
|
|
45
|
+
var BaseLocalCache = class extends BaseCache {
|
|
46
|
+
disposeListeners = [];
|
|
47
|
+
/**
|
|
48
|
+
* Reads cached resources by their keys. (synchronous version)
|
|
49
|
+
* @protected
|
|
50
|
+
*/
|
|
51
|
+
_getMany(keys) {
|
|
52
|
+
return Object.fromEntries(keys.map((key) => [key, this._get(key)]));
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Writes resources into cache. (synchronous version)
|
|
56
|
+
* @protected
|
|
57
|
+
*/
|
|
58
|
+
_setMany(data, options) {
|
|
59
|
+
for (const [key, value] of Object.entries(data)) this._set(key, value, options);
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Deletes many cached resources by their keys. (synchronous version)
|
|
63
|
+
* @protected
|
|
64
|
+
*/
|
|
65
|
+
_deleteMany(keys) {
|
|
66
|
+
for (const key of keys) this._delete(key);
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Adds a listener that will be called when a cached item is disposed.
|
|
70
|
+
*
|
|
71
|
+
* @param listener The listener function to add.
|
|
72
|
+
* @protected
|
|
73
|
+
*/
|
|
74
|
+
_addDisposeListener(listener) {
|
|
75
|
+
this.disposeListeners.push(listener);
|
|
76
|
+
}
|
|
77
|
+
get(key) {
|
|
78
|
+
return Promise.resolve(this._get(key));
|
|
79
|
+
}
|
|
80
|
+
set(key, value, options) {
|
|
81
|
+
this._set(key, value, options);
|
|
82
|
+
return Promise.resolve();
|
|
83
|
+
}
|
|
84
|
+
delete(key) {
|
|
85
|
+
this._delete(key);
|
|
86
|
+
return Promise.resolve();
|
|
87
|
+
}
|
|
88
|
+
getMany(keys) {
|
|
89
|
+
return Promise.resolve(this._getMany(keys));
|
|
90
|
+
}
|
|
91
|
+
setMany(data, options) {
|
|
92
|
+
this._setMany(data, options);
|
|
93
|
+
return Promise.resolve();
|
|
94
|
+
}
|
|
95
|
+
deleteMany(keys) {
|
|
96
|
+
this._deleteMany(keys);
|
|
97
|
+
return Promise.resolve();
|
|
98
|
+
}
|
|
99
|
+
onDispose(key, value, reason) {
|
|
100
|
+
for (const listener of this.disposeListeners) listener(key, value, reason);
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
|
|
43
104
|
//#endregion
|
|
44
105
|
//#region src/local/lru/index.ts
|
|
45
106
|
/**
|
|
@@ -49,7 +110,7 @@ var BaseCache = class {
|
|
|
49
110
|
*
|
|
50
111
|
* Once the limit of items is reached, the least recently used items will be purged.
|
|
51
112
|
*/
|
|
52
|
-
var LocalLRUCache = class extends
|
|
113
|
+
var LocalLRUCache = class extends BaseLocalCache {
|
|
53
114
|
cache;
|
|
54
115
|
shouldUseFetch;
|
|
55
116
|
constructor(options = {}) {
|
|
@@ -62,16 +123,29 @@ var LocalLRUCache = class extends BaseCache {
|
|
|
62
123
|
ttl: options.ttl ? options.ttl * 1e3 : void 0,
|
|
63
124
|
max: options.max || 1e4,
|
|
64
125
|
ttlAutopurge: false,
|
|
65
|
-
fetchMethod: (_key, _staleValue, options$1) => options$1.context()
|
|
126
|
+
fetchMethod: (_key, _staleValue, options$1) => options$1.context(),
|
|
127
|
+
disposeAfter: (value, key, reason) => this.onDispose(key, value, reason)
|
|
66
128
|
});
|
|
67
129
|
this.shouldUseFetch = true;
|
|
68
130
|
}
|
|
69
131
|
}
|
|
70
|
-
|
|
132
|
+
/** @internal */
|
|
133
|
+
_get(key) {
|
|
71
134
|
this.logger?.debug(this.name, "[get]", "key =", key);
|
|
72
135
|
const data = this.cache.get(key);
|
|
73
136
|
return data === void 0 ? null : data;
|
|
74
137
|
}
|
|
138
|
+
/** @internal */
|
|
139
|
+
_set(key, value, options) {
|
|
140
|
+
this.logger?.debug(this.name, "[set]", "key =", key);
|
|
141
|
+
const ttl = options?.ttl;
|
|
142
|
+
this.cache.set(key, value, { ttl: ttl ? ttl * 1e3 : void 0 });
|
|
143
|
+
}
|
|
144
|
+
/** @internal */
|
|
145
|
+
_delete(key) {
|
|
146
|
+
this.logger?.debug(this.name, "[delete]", "key =", key);
|
|
147
|
+
this.cache.delete(key);
|
|
148
|
+
}
|
|
75
149
|
getOrLoad(key, load, options) {
|
|
76
150
|
if (!this.shouldUseFetch) return super.getOrLoad(key, load, options);
|
|
77
151
|
this.logger?.debug(this.name, "[getOrLoad] Running LRUCache's fetch...", "key =", key);
|
|
@@ -81,15 +155,6 @@ var LocalLRUCache = class extends BaseCache {
|
|
|
81
155
|
ttl: ttl ? ttl * 1e3 : void 0
|
|
82
156
|
});
|
|
83
157
|
}
|
|
84
|
-
async set(key, value, options) {
|
|
85
|
-
this.logger?.debug(this.name, "[set]", "key =", key);
|
|
86
|
-
const ttl = options?.ttl;
|
|
87
|
-
this.cache.set(key, value, { ttl: ttl ? ttl * 1e3 : void 0 });
|
|
88
|
-
}
|
|
89
|
-
async delete(key) {
|
|
90
|
-
this.logger?.debug(this.name, "[delete]", "key =", key);
|
|
91
|
-
this.cache.delete(key);
|
|
92
|
-
}
|
|
93
158
|
};
|
|
94
159
|
|
|
95
160
|
//#endregion
|
|
@@ -99,27 +164,31 @@ var LocalLRUCache = class extends BaseCache {
|
|
|
99
164
|
*
|
|
100
165
|
* Once the limit of items is reached, the soonest expiring items will be purged.
|
|
101
166
|
*/
|
|
102
|
-
var LocalTTLCache = class extends
|
|
167
|
+
var LocalTTLCache = class extends BaseLocalCache {
|
|
103
168
|
cache;
|
|
104
169
|
constructor(options = {}) {
|
|
105
170
|
super(options);
|
|
106
171
|
if ("cache" in options) this.cache = options.cache;
|
|
107
172
|
else this.cache = new TTLCache({
|
|
108
173
|
max: options.max,
|
|
109
|
-
ttl: options.ttl ? options.ttl * 1e3 : void 0
|
|
174
|
+
ttl: options.ttl ? options.ttl * 1e3 : void 0,
|
|
175
|
+
dispose: (value, key, reason) => this.onDispose(key, value, reason)
|
|
110
176
|
});
|
|
111
177
|
}
|
|
112
|
-
|
|
178
|
+
/** @internal */
|
|
179
|
+
_get(key) {
|
|
113
180
|
this.logger?.debug(this.name, "[get]", "key =", key);
|
|
114
181
|
const data = this.cache.get(key);
|
|
115
182
|
return data === void 0 ? null : data;
|
|
116
183
|
}
|
|
117
|
-
|
|
184
|
+
/** @internal */
|
|
185
|
+
_set(key, value, options) {
|
|
118
186
|
this.logger?.debug(this.name, "[set]", "key =", key);
|
|
119
187
|
const ttl = options?.ttl;
|
|
120
188
|
this.cache.set(key, value, { ttl: ttl ? ttl * 1e3 : void 0 });
|
|
121
189
|
}
|
|
122
|
-
|
|
190
|
+
/** @internal */
|
|
191
|
+
_delete(key) {
|
|
123
192
|
this.logger?.debug(this.name, "[delete]", "key =", key);
|
|
124
193
|
this.cache.delete(key);
|
|
125
194
|
}
|
|
@@ -132,9 +201,10 @@ var LocalTTLCache = class extends BaseCache {
|
|
|
132
201
|
*
|
|
133
202
|
* It ignores expiration times, but a limit of cached items can be set.
|
|
134
203
|
*
|
|
204
|
+
* It implements a simple FIFO eviction policy:
|
|
135
205
|
* Once the limit of items is reached, the first inserted keys will be purged.
|
|
136
206
|
*/
|
|
137
|
-
var LocalMapCache = class extends
|
|
207
|
+
var LocalMapCache = class extends BaseLocalCache {
|
|
138
208
|
cache;
|
|
139
209
|
max;
|
|
140
210
|
constructor(options = {}) {
|
|
@@ -142,38 +212,55 @@ var LocalMapCache = class extends BaseCache {
|
|
|
142
212
|
this.cache = options.cache ?? /* @__PURE__ */ new Map();
|
|
143
213
|
this.max = options.max ?? Infinity;
|
|
144
214
|
}
|
|
145
|
-
|
|
215
|
+
/** @internal */
|
|
216
|
+
_get(key) {
|
|
146
217
|
this.logger?.debug(this.name, "[get]", "key =", key);
|
|
147
218
|
const data = this.cache.get(key);
|
|
148
219
|
return data === void 0 ? null : data;
|
|
149
220
|
}
|
|
150
|
-
|
|
221
|
+
/** @internal */
|
|
222
|
+
_set(key, value, options) {
|
|
151
223
|
this.logger?.debug(this.name, "[set]", "key =", key);
|
|
152
|
-
|
|
224
|
+
const previousValue = this.cache.get(key);
|
|
225
|
+
if (this.cache.size >= this.max && previousValue === void 0) this.evict(1);
|
|
153
226
|
this.cache.set(key, value);
|
|
227
|
+
this.onDispose(key, previousValue, "set");
|
|
154
228
|
}
|
|
155
|
-
|
|
229
|
+
/** @internal */
|
|
230
|
+
_delete(key) {
|
|
156
231
|
this.logger?.debug(this.name, "[delete]", "key =", key);
|
|
232
|
+
const previousValue = this.cache.get(key);
|
|
157
233
|
this.cache.delete(key);
|
|
234
|
+
this.onDispose(key, previousValue, "delete");
|
|
158
235
|
}
|
|
159
236
|
async setMany(data, options) {
|
|
160
237
|
this.logger?.debug(this.name, "[setMany]", "data =", data);
|
|
161
238
|
const entries = Object.entries(data);
|
|
162
239
|
const newEntries = entries.filter(([key]) => !this.cache.has(key)).length;
|
|
163
240
|
if (this.cache.size + newEntries > this.max) this.evict(this.cache.size + newEntries - this.max);
|
|
164
|
-
for (const [key, value] of entries)
|
|
241
|
+
for (const [key, value] of entries) {
|
|
242
|
+
const previousValue = this.cache.get(key);
|
|
243
|
+
this.cache.set(key, value);
|
|
244
|
+
this.onDispose(key, previousValue, "set");
|
|
245
|
+
}
|
|
165
246
|
}
|
|
166
247
|
clear() {
|
|
167
248
|
this.logger?.debug(this.name, "[clear]");
|
|
249
|
+
for (const key of this.cache.keys()) this.onDispose(key, this.cache.get(key), "delete");
|
|
168
250
|
this.cache.clear();
|
|
169
251
|
}
|
|
252
|
+
onDispose(key, value, reason) {
|
|
253
|
+
if (value !== void 0) super.onDispose(key, value, reason);
|
|
254
|
+
}
|
|
170
255
|
evict(length) {
|
|
171
256
|
const keys = this.cache.keys();
|
|
172
257
|
for (let i = 0; i < length; i++) {
|
|
173
258
|
const key = keys.next();
|
|
174
259
|
if (key.done) break;
|
|
175
260
|
this.logger?.debug(this.name, "[evict]", "key = ", key);
|
|
261
|
+
const previousValue = this.cache.get(key.value);
|
|
176
262
|
this.cache.delete(key.value);
|
|
263
|
+
this.onDispose(key.value, previousValue, "evict");
|
|
177
264
|
}
|
|
178
265
|
}
|
|
179
266
|
};
|
|
@@ -182,7 +269,7 @@ var LocalMapCache = class extends BaseCache {
|
|
|
182
269
|
//#region src/local/noop/index.ts
|
|
183
270
|
/**
|
|
184
271
|
* A cache implementation that does nothing.
|
|
185
|
-
* It's useful for disabling cache.
|
|
272
|
+
* It's useful for disabling cache and unit testing.
|
|
186
273
|
*
|
|
187
274
|
* @example
|
|
188
275
|
* ```ts
|
|
@@ -214,12 +301,14 @@ var NoOpCache = class {
|
|
|
214
301
|
var IORedisCache = class extends BaseCache {
|
|
215
302
|
client;
|
|
216
303
|
defaultTTL;
|
|
304
|
+
isUNLINKSupported;
|
|
217
305
|
isMSETEXSupported;
|
|
218
306
|
constructor(options) {
|
|
219
307
|
super(options);
|
|
220
308
|
this.client = options.client;
|
|
221
309
|
this.defaultTTL = options.defaultTTL;
|
|
222
|
-
this.
|
|
310
|
+
this.isUNLINKSupported = options.isUNLINKSupported ?? true;
|
|
311
|
+
this.isMSETEXSupported = options.isMSETEXSupported ?? false;
|
|
223
312
|
}
|
|
224
313
|
async get(key) {
|
|
225
314
|
this.logger?.debug(this.name, "[get] Running \"GET\" command...", "key =", key);
|
|
@@ -234,8 +323,13 @@ var IORedisCache = class extends BaseCache {
|
|
|
234
323
|
else await this.client.set(key, raw);
|
|
235
324
|
}
|
|
236
325
|
async delete(key) {
|
|
237
|
-
|
|
238
|
-
|
|
326
|
+
if (this.isUNLINKSupported) {
|
|
327
|
+
this.logger?.debug(this.name, "[delete] Running \"UNLINK\" command...", "key =", key);
|
|
328
|
+
await this.client.unlink(key);
|
|
329
|
+
} else {
|
|
330
|
+
this.logger?.debug(this.name, "[delete] Running \"DEL\" command...", "key =", key);
|
|
331
|
+
await this.client.del(key);
|
|
332
|
+
}
|
|
239
333
|
}
|
|
240
334
|
async getMany(keys) {
|
|
241
335
|
this.logger?.debug(this.name, "[getMany] Running \"MGET\" command...", "keys =", keys);
|
|
@@ -256,8 +350,13 @@ var IORedisCache = class extends BaseCache {
|
|
|
256
350
|
await this.client.call("MSETEX", entries.length, ...raw, ...ttl ? ["EX", ttl] : []);
|
|
257
351
|
}
|
|
258
352
|
async deleteMany(keys) {
|
|
259
|
-
|
|
260
|
-
|
|
353
|
+
if (this.isUNLINKSupported) {
|
|
354
|
+
this.logger?.debug(this.name, "[deleteMany] Running \"UNLINK\" command...", "keys =", keys);
|
|
355
|
+
await this.client.unlink(keys);
|
|
356
|
+
} else {
|
|
357
|
+
this.logger?.debug(this.name, "[deleteMany] Running \"DEL\" command...", "keys =", keys);
|
|
358
|
+
await this.client.del(keys);
|
|
359
|
+
}
|
|
261
360
|
}
|
|
262
361
|
};
|
|
263
362
|
|
|
@@ -269,12 +368,14 @@ var IORedisCache = class extends BaseCache {
|
|
|
269
368
|
var RedisCache = class extends BaseCache {
|
|
270
369
|
client;
|
|
271
370
|
defaultTTL;
|
|
371
|
+
isUNLINKSupported;
|
|
272
372
|
isMSETEXSupported;
|
|
273
373
|
constructor(options) {
|
|
274
374
|
super(options);
|
|
275
375
|
this.client = options.client;
|
|
276
376
|
this.defaultTTL = options.defaultTTL;
|
|
277
|
-
this.
|
|
377
|
+
this.isUNLINKSupported = options.isUNLINKSupported ?? true;
|
|
378
|
+
this.isMSETEXSupported = options.isMSETEXSupported ?? false;
|
|
278
379
|
}
|
|
279
380
|
async get(key) {
|
|
280
381
|
this.logger?.debug(this.name, "[get] Running \"GET\" command...", "key =", key);
|
|
@@ -290,8 +391,13 @@ var RedisCache = class extends BaseCache {
|
|
|
290
391
|
} : void 0 });
|
|
291
392
|
}
|
|
292
393
|
async delete(key) {
|
|
293
|
-
|
|
294
|
-
|
|
394
|
+
if (this.isUNLINKSupported) {
|
|
395
|
+
this.logger?.debug(this.name, "[delete] Running \"UNLINK\" command...", "key =", key);
|
|
396
|
+
await this.client.unlink(key);
|
|
397
|
+
} else {
|
|
398
|
+
this.logger?.debug(this.name, "[delete] Running \"DEL\" command...", "key =", key);
|
|
399
|
+
await this.client.del(key);
|
|
400
|
+
}
|
|
295
401
|
}
|
|
296
402
|
async getMany(keys) {
|
|
297
403
|
this.logger?.debug(this.name, "[getMany] Running \"MGET\" command...", "keys =", keys);
|
|
@@ -315,8 +421,13 @@ var RedisCache = class extends BaseCache {
|
|
|
315
421
|
} : void 0 });
|
|
316
422
|
}
|
|
317
423
|
async deleteMany(keys) {
|
|
318
|
-
|
|
319
|
-
|
|
424
|
+
if (this.isUNLINKSupported) {
|
|
425
|
+
this.logger?.debug(this.name, "[deleteMany] Running \"UNLINK\" command...", "keys =", keys);
|
|
426
|
+
await this.client.unlink(keys);
|
|
427
|
+
} else {
|
|
428
|
+
this.logger?.debug(this.name, "[deleteMany] Running \"DEL\" command...", "keys =", keys);
|
|
429
|
+
await this.client.del(keys);
|
|
430
|
+
}
|
|
320
431
|
}
|
|
321
432
|
};
|
|
322
433
|
|
|
@@ -347,8 +458,8 @@ var ValkeyGlideCache = class extends BaseCache {
|
|
|
347
458
|
} : void 0 });
|
|
348
459
|
}
|
|
349
460
|
async delete(key) {
|
|
350
|
-
this.logger?.debug(this.name, "[delete] Running \"
|
|
351
|
-
await this.client.
|
|
461
|
+
this.logger?.debug(this.name, "[delete] Running \"UNLINK\" command...", "key =", key);
|
|
462
|
+
await this.client.unlink([key]);
|
|
352
463
|
}
|
|
353
464
|
async getMany(keys) {
|
|
354
465
|
this.logger?.debug(this.name, "[getMany] Running \"MGET\" command...", "keys =", keys);
|
|
@@ -361,8 +472,8 @@ var ValkeyGlideCache = class extends BaseCache {
|
|
|
361
472
|
return data;
|
|
362
473
|
}
|
|
363
474
|
async deleteMany(keys) {
|
|
364
|
-
this.logger?.debug(this.name, "[deleteMany] Running \"
|
|
365
|
-
await this.client.
|
|
475
|
+
this.logger?.debug(this.name, "[deleteMany] Running \"UNLINK\" command...", "keys =", keys);
|
|
476
|
+
await this.client.unlink(keys);
|
|
366
477
|
}
|
|
367
478
|
};
|
|
368
479
|
|