cachimbo 0.0.3 → 0.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -4,7 +4,10 @@
4
4
 
5
5
  <h1 align="center">Cachimbo</h1>
6
6
 
7
- Cachimbo is an advanced caching library that allows you to layer different strategies in order to maximize the performance.
7
+ Cachimbo is a composable caching library that allows layering different strategies in order to maximize the performance.
8
+
9
+ [![NPM](https://img.shields.io/npm/v/cachimbo)](https://www.npmjs.com/package/cachimbo)
10
+ [![Coverage](https://img.shields.io/codecov/c/github/Guichaguri/cachimbo)](https://app.codecov.io/gh/Guichaguri/cachimbo)
8
11
 
9
12
  ## Features
10
13
 
@@ -18,7 +21,8 @@ Cachimbo is an advanced caching library that allows you to layer different strat
18
21
  - Least Recently Used (LRU) eviction
19
22
  - Time-based (TTL) eviction
20
23
  - FIFO eviction
21
- - Supports intermediary cache strategies
24
+ - Weak References (garbage collectable cached items)
25
+ - Supports composable cache strategies
22
26
  - Request coalescing (deduplication)
23
27
  - Multi-layer caching (tiered cache)
24
28
  - Stale-While-Revalidate
@@ -78,7 +82,9 @@ External caches (like Redis, Memcached, etc) provide fast, scalable, shared stor
78
82
 
79
83
  ## Cache Layers
80
84
 
81
- These layers work just like "middlewares" but for caches, they customize how a cache is handled.
85
+ Cache layers are composable components that sit between your code and the cache store. While cache stores define *where* data is stored, cache layers define *how* the cache is accessed.
86
+
87
+ Each layer intercepts cache operations to add behavior. Layers can be stacked to form a pipeline, allowing advanced caching strategies to be reused across different cache backends.
82
88
 
83
89
  - [Request Coalescing](/docs/layers/request-coalescing.md) (deduplication)
84
90
  - [Tiered Caching](/docs/layers/tiered.md) (multi-layer caching)
@@ -89,6 +95,9 @@ These layers work just like "middlewares" but for caches, they customize how a c
89
95
  - [Metrics Collection](/docs/layers/metrics-collection.md)
90
96
 
91
97
  ## Guides
98
+ - [Getting Started](/docs/guides/getting-started.md)
92
99
  - [Choosing the right combination of layers](/docs/guides/choosing-layers.md)
93
100
  - [Disabling cache](/docs/guides/disabling.md)
101
+ - [Testing](/docs/guides/testing.md)
94
102
  - [Extending](/docs/guides/extending.md)
103
+ - [Samples](/samples)
package/dist/index.cjs CHANGED
@@ -46,21 +46,18 @@ var BaseLocalCache = class extends BaseCache {
46
46
  disposeListeners = [];
47
47
  /**
48
48
  * Reads cached resources by their keys. (synchronous version)
49
- * @protected
50
49
  */
51
50
  _getMany(keys) {
52
51
  return Object.fromEntries(keys.map((key) => [key, this._get(key)]));
53
52
  }
54
53
  /**
55
54
  * Writes resources into cache. (synchronous version)
56
- * @protected
57
55
  */
58
56
  _setMany(data, options) {
59
57
  for (const [key, value] of Object.entries(data)) this._set(key, value, options);
60
58
  }
61
59
  /**
62
60
  * Deletes many cached resources by their keys. (synchronous version)
63
- * @protected
64
61
  */
65
62
  _deleteMany(keys) {
66
63
  for (const key of keys) this._delete(key);
@@ -69,29 +66,41 @@ var BaseLocalCache = class extends BaseCache {
69
66
  * Adds a listener that will be called when a cached item is disposed.
70
67
  *
71
68
  * @param listener The listener function to add.
72
- * @protected
73
69
  */
74
70
  _addDisposeListener(listener) {
75
71
  this.disposeListeners.push(listener);
76
72
  }
73
+ /**
74
+ * Gets access to the internal synchronous methods.
75
+ * @experimental
76
+ */
77
+ get internal() {
78
+ return this;
79
+ }
80
+ /** @sealed **/
77
81
  get(key) {
78
82
  return Promise.resolve(this._get(key));
79
83
  }
84
+ /** @sealed **/
80
85
  set(key, value, options) {
81
86
  this._set(key, value, options);
82
87
  return Promise.resolve();
83
88
  }
89
+ /** @sealed **/
84
90
  delete(key) {
85
91
  this._delete(key);
86
92
  return Promise.resolve();
87
93
  }
94
+ /** @sealed **/
88
95
  getMany(keys) {
89
96
  return Promise.resolve(this._getMany(keys));
90
97
  }
98
+ /** @sealed **/
91
99
  setMany(data, options) {
92
100
  this._setMany(data, options);
93
101
  return Promise.resolve();
94
102
  }
103
+ /** @sealed **/
95
104
  deleteMany(keys) {
96
105
  this._deleteMany(keys);
97
106
  return Promise.resolve();
@@ -205,66 +214,229 @@ var LocalTTLCache = class extends BaseLocalCache {
205
214
  * Once the limit of items is reached, the first inserted keys will be purged.
206
215
  */
207
216
  var LocalMapCache = class extends BaseLocalCache {
208
- cache;
217
+ map;
209
218
  max;
210
219
  constructor(options = {}) {
211
220
  super(options);
212
- this.cache = options.cache ?? /* @__PURE__ */ new Map();
221
+ this.map = options.map ?? /* @__PURE__ */ new Map();
213
222
  this.max = options.max ?? Infinity;
214
223
  }
215
224
  /** @internal */
216
225
  _get(key) {
217
226
  this.logger?.debug(this.name, "[get]", "key =", key);
218
- const data = this.cache.get(key);
227
+ const data = this.map.get(key);
219
228
  return data === void 0 ? null : data;
220
229
  }
221
230
  /** @internal */
222
231
  _set(key, value, options) {
223
232
  this.logger?.debug(this.name, "[set]", "key =", key);
224
- const previousValue = this.cache.get(key);
225
- if (this.cache.size >= this.max && previousValue === void 0) this.evict(1);
226
- this.cache.set(key, value);
233
+ const previousValue = this.map.get(key);
234
+ if (this.map.size >= this.max && previousValue === void 0) this.evict(1);
235
+ this.map.set(key, value);
227
236
  this.onDispose(key, previousValue, "set");
228
237
  }
229
238
  /** @internal */
230
239
  _delete(key) {
231
240
  this.logger?.debug(this.name, "[delete]", "key =", key);
232
- const previousValue = this.cache.get(key);
233
- this.cache.delete(key);
241
+ const previousValue = this.map.get(key);
242
+ this.map.delete(key);
234
243
  this.onDispose(key, previousValue, "delete");
235
244
  }
236
245
  async setMany(data, options) {
237
246
  this.logger?.debug(this.name, "[setMany]", "data =", data);
238
247
  const entries = Object.entries(data);
239
- const newEntries = entries.filter(([key]) => !this.cache.has(key)).length;
240
- if (this.cache.size + newEntries > this.max) this.evict(this.cache.size + newEntries - this.max);
248
+ const newEntries = entries.filter(([key]) => !this.map.has(key)).length;
249
+ if (this.map.size + newEntries > this.max) this.evict(this.map.size + newEntries - this.max);
241
250
  for (const [key, value] of entries) {
242
- const previousValue = this.cache.get(key);
243
- this.cache.set(key, value);
251
+ const previousValue = this.map.get(key);
252
+ this.map.set(key, value);
244
253
  this.onDispose(key, previousValue, "set");
245
254
  }
246
255
  }
247
256
  clear() {
248
257
  this.logger?.debug(this.name, "[clear]");
249
- for (const key of this.cache.keys()) this.onDispose(key, this.cache.get(key), "delete");
250
- this.cache.clear();
258
+ for (const key of this.map.keys()) this.onDispose(key, this.map.get(key), "delete");
259
+ this.map.clear();
251
260
  }
252
261
  onDispose(key, value, reason) {
253
262
  if (value !== void 0) super.onDispose(key, value, reason);
254
263
  }
255
264
  evict(length) {
256
- const keys = this.cache.keys();
265
+ const keys = this.map.keys();
257
266
  for (let i = 0; i < length; i++) {
258
267
  const key = keys.next();
259
268
  if (key.done) break;
260
269
  this.logger?.debug(this.name, "[evict]", "key = ", key);
261
- const previousValue = this.cache.get(key.value);
262
- this.cache.delete(key.value);
270
+ const previousValue = this.map.get(key.value);
271
+ this.map.delete(key.value);
263
272
  this.onDispose(key.value, previousValue, "evict");
264
273
  }
265
274
  }
266
275
  };
267
276
 
277
+ //#endregion
278
+ //#region src/local/weak/index.ts
279
+ /**
280
+ * A cache layer that stores objects as weak references.
281
+ *
282
+ * When an object is garbage collected, its entry is automatically removed from the underlying cache.
283
+ *
284
+ * This implementation requires support for both `WeakRef` and `FinalizationRegistry`.
285
+ *
286
+ * @see https://caniuse.com/mdn-javascript_builtins_finalizationregistry
287
+ * @see https://caniuse.com/mdn-javascript_builtins_weakref
288
+ */
289
+ var WeakCache = class extends BaseLocalCache {
290
+ cache;
291
+ cacheInternal;
292
+ registry;
293
+ constructor(options) {
294
+ super(options);
295
+ this.cache = options.cache;
296
+ this.cacheInternal = options.cache.internal;
297
+ this.cacheInternal._addDisposeListener(this.onCacheDispose);
298
+ this.registry = new FinalizationRegistry(this.onGarbageCollect);
299
+ }
300
+ onGarbageCollect = (key) => this.cacheInternal._delete(key);
301
+ onCacheDispose = (key, value, reason) => {
302
+ this.unregister(value);
303
+ this.onDispose(key, this.unwrap(value), reason);
304
+ };
305
+ /** @internal */
306
+ _get(key) {
307
+ return this.unwrap(this.cacheInternal._get(key));
308
+ }
309
+ /** @internal */
310
+ _set(key, value, options) {
311
+ this.cacheInternal._set(key, this.wrapAndRegister(key, value), options);
312
+ }
313
+ /** @internal */
314
+ _delete(key) {
315
+ this.unregisterByKey(key);
316
+ this.cacheInternal._delete(key);
317
+ }
318
+ /** @internal */
319
+ _getMany(keys) {
320
+ const data = this.cacheInternal._getMany(keys);
321
+ for (const key of keys) data[key] = this.unwrap(data[key]);
322
+ return data;
323
+ }
324
+ /** @internal */
325
+ _setMany(data, options) {
326
+ Object.keys(data).forEach((key) => this.unregisterByKey(key));
327
+ const wrappedData = {};
328
+ for (const [key, value] of Object.entries(data)) wrappedData[key] = this.wrapAndRegister(key, value);
329
+ this.cacheInternal._setMany(wrappedData, options);
330
+ }
331
+ /** @internal */
332
+ _deleteMany(keys) {
333
+ keys.forEach((key) => this.unregisterByKey(key));
334
+ this.cacheInternal._deleteMany(keys);
335
+ }
336
+ async getOrLoad(key, load, options) {
337
+ const wrappedLoad = async () => this.wrapAndRegister(key, await load());
338
+ return this.unwrap(await this.cache.getOrLoad(key, wrappedLoad, options));
339
+ }
340
+ /**
341
+ * Wraps the value in a WeakRef and registers it in the FinalizationRegistry if it's an object.
342
+ *
343
+ * @param key The key to reference the value in the FinalizationRegistry
344
+ * @param value The value to wrap
345
+ * @returns The wrapped value
346
+ */
347
+ wrapAndRegister(key, value) {
348
+ this.unregisterByKey(key);
349
+ if (value !== null && typeof value === "object") {
350
+ this.registry.register(value, key);
351
+ return {
352
+ v: new WeakRef(value),
353
+ w: true
354
+ };
355
+ }
356
+ return {
357
+ v: value,
358
+ w: false
359
+ };
360
+ }
361
+ /**
362
+ * Unwraps the value from a WeakRef if it's an object.
363
+ *
364
+ * @param data The data to unwrap
365
+ * @returns The unwrapped value
366
+ */
367
+ unwrap(data) {
368
+ if (data === null) return null;
369
+ if (data.w) return data.v.deref() ?? null;
370
+ return data.v;
371
+ }
372
+ /**
373
+ * Unregisters the value from the FinalizationRegistry if it's an object.
374
+ *
375
+ * @param value The value to unregister
376
+ */
377
+ unregister(value) {
378
+ if (value && value.w) this.registry.unregister(value.v);
379
+ }
380
+ /**
381
+ * Unregisters the value associated with the given key from the FinalizationRegistry.
382
+ *
383
+ * @param key The key
384
+ */
385
+ unregisterByKey(key) {
386
+ this.unregister(this.cacheInternal._get(key));
387
+ }
388
+ };
389
+
390
+ //#endregion
391
+ //#region src/local/cloning/index.ts
392
+ /**
393
+ * A cache layer that deep clones data when reading and writing.
394
+ *
395
+ * This is useful when you mutate the objects retrieved from cache,
396
+ * and you don't want them to also change in cache.
397
+ *
398
+ * Do not use this layer if you do not intend to mutate cached objects,
399
+ * as the cloning process adds unnecessary overhead.
400
+ */
401
+ var DeepCloningCache = class extends BaseLocalCache {
402
+ cache;
403
+ cacheInternal;
404
+ deepClone;
405
+ constructor(options) {
406
+ super(options);
407
+ this.cache = options.cache;
408
+ this.cacheInternal = options.cache.internal;
409
+ if (options.deepClone) this.deepClone = options.deepClone;
410
+ else if (typeof structuredClone === "function") this.deepClone = structuredClone;
411
+ else this.deepClone = (data) => JSON.parse(JSON.stringify(data));
412
+ }
413
+ _get(key) {
414
+ return this.deepClone(this.cacheInternal._get(key));
415
+ }
416
+ _set(key, value, options) {
417
+ this.cacheInternal._set(key, this.deepClone(value), options);
418
+ }
419
+ _delete(key) {
420
+ this.cacheInternal._delete(key);
421
+ }
422
+ _getMany(keys) {
423
+ return this.deepClone(this.cacheInternal._getMany(keys));
424
+ }
425
+ _setMany(data, options) {
426
+ this.cacheInternal._setMany(this.deepClone(data), options);
427
+ }
428
+ _deleteMany(keys) {
429
+ this.cacheInternal._deleteMany(keys);
430
+ }
431
+ _addDisposeListener(listener) {
432
+ this.cacheInternal._addDisposeListener(listener);
433
+ }
434
+ async getOrLoad(key, load, options) {
435
+ const loadWrapped = async () => this.deepClone(await load());
436
+ return this.deepClone(await this.cache.getOrLoad(key, loadWrapped, options));
437
+ }
438
+ };
439
+
268
440
  //#endregion
269
441
  //#region src/local/noop/index.ts
270
442
  /**
@@ -568,7 +740,10 @@ var WorkersKVCache = class extends BaseCache {
568
740
  return this.kv.delete(key);
569
741
  }
570
742
  async getMany(keys) {
571
- const data = await this.kv.get(keys, { type: "json" });
743
+ const data = await this.kv.get(keys, {
744
+ type: "json",
745
+ cacheTtl: this.edgeCacheTTL
746
+ });
572
747
  return Object.fromEntries(data);
573
748
  }
574
749
  };
@@ -862,7 +1037,7 @@ var KeyTransformingCache = class {
862
1037
  transform;
863
1038
  constructor(options) {
864
1039
  this.cache = options.cache;
865
- if ("transform" in options) this.transform = options.transform;
1040
+ if ("transform" in options && typeof options.transform === "function") this.transform = options.transform;
866
1041
  else {
867
1042
  const prefix = options.prefix || "";
868
1043
  const suffix = options.suffix || "";
@@ -1217,7 +1392,9 @@ var MetricsCollectingCache = class {
1217
1392
  //#endregion
1218
1393
  exports.AsyncLazyCache = AsyncLazyCache;
1219
1394
  exports.BaseCache = BaseCache;
1395
+ exports.BaseLocalCache = BaseLocalCache;
1220
1396
  exports.CoalescingCache = CoalescingCache;
1397
+ exports.DeepCloningCache = DeepCloningCache;
1221
1398
  exports.IORedisCache = IORedisCache;
1222
1399
  exports.JitteringCache = JitteringCache;
1223
1400
  exports.KeyTransformingCache = KeyTransformingCache;
@@ -1233,4 +1410,5 @@ exports.RedisCache = RedisCache;
1233
1410
  exports.SWRCache = SWRCache;
1234
1411
  exports.TieredCache = TieredCache;
1235
1412
  exports.ValkeyGlideCache = ValkeyGlideCache;
1413
+ exports.WeakCache = WeakCache;
1236
1414
  exports.WorkersKVCache = WorkersKVCache;
package/dist/index.d.cts CHANGED
@@ -121,50 +121,67 @@ declare abstract class BaseCache implements ICache {
121
121
  //#endregion
122
122
  //#region src/base/local.d.ts
123
123
  type LocalCacheDisposeListener<T = any> = (key: string, value: T, reason?: string) => void;
124
+ /**
125
+ * Internal methods for synchronous cache operations.
126
+ * @experimental
127
+ */
128
+ interface LocalCacheInternal {
129
+ _get<T>(key: string): T | null;
130
+ _set<T>(key: string, value: T, options?: SetCacheOptions): void;
131
+ _delete(key: string): void;
132
+ _getMany<T>(keys: string[]): Record<string, T | null>;
133
+ _setMany<T>(data: Record<string, T>, options?: SetCacheOptions): void;
134
+ _deleteMany(keys: string[]): void;
135
+ _addDisposeListener(listener: LocalCacheDisposeListener): void;
136
+ }
124
137
  declare abstract class BaseLocalCache extends BaseCache {
125
138
  protected disposeListeners: LocalCacheDisposeListener[];
126
139
  /**
127
140
  * Reads the cached resource from a key (synchronous version)
128
- * @protected
129
141
  */
130
- abstract _get<T>(key: string): T | null;
142
+ protected abstract _get<T>(key: string): T | null;
131
143
  /**
132
144
  * Writes a resource into cache (synchronous version)
133
- * @protected
134
145
  */
135
- abstract _set<T>(key: string, value: T, options?: SetCacheOptions): void;
146
+ protected abstract _set<T>(key: string, value: T, options?: SetCacheOptions): void;
136
147
  /**
137
148
  * Deletes a cached resource by a key. (synchronous version)
138
- * @protected
139
149
  */
140
- abstract _delete(key: string): void;
150
+ protected abstract _delete(key: string): void;
141
151
  /**
142
152
  * Reads cached resources by their keys. (synchronous version)
143
- * @protected
144
153
  */
145
- _getMany<T>(keys: string[]): Record<string, T | null>;
154
+ protected _getMany<T>(keys: string[]): Record<string, T | null>;
146
155
  /**
147
156
  * Writes resources into cache. (synchronous version)
148
- * @protected
149
157
  */
150
- _setMany<T>(data: Record<string, T>, options?: SetCacheOptions): void;
158
+ protected _setMany<T>(data: Record<string, T>, options?: SetCacheOptions): void;
151
159
  /**
152
160
  * Deletes many cached resources by their keys. (synchronous version)
153
- * @protected
154
161
  */
155
- _deleteMany(keys: string[]): void;
162
+ protected _deleteMany(keys: string[]): void;
156
163
  /**
157
164
  * Adds a listener that will be called when a cached item is disposed.
158
165
  *
159
166
  * @param listener The listener function to add.
160
- * @protected
161
167
  */
162
- _addDisposeListener(listener: LocalCacheDisposeListener): void;
168
+ protected _addDisposeListener(listener: LocalCacheDisposeListener): void;
169
+ /**
170
+ * Gets access to the internal synchronous methods.
171
+ * @experimental
172
+ */
173
+ get internal(): LocalCacheInternal;
174
+ /** @sealed **/
163
175
  get<T>(key: string): Promise<T | null>;
176
+ /** @sealed **/
164
177
  set<T>(key: string, value: T, options?: SetCacheOptions): Promise<void>;
178
+ /** @sealed **/
165
179
  delete(key: string): Promise<void>;
180
+ /** @sealed **/
166
181
  getMany<T>(keys: string[]): Promise<Record<string, T | null>>;
182
+ /** @sealed **/
167
183
  setMany<T>(data: Record<string, T>, options?: SetCacheOptions): Promise<void>;
184
+ /** @sealed **/
168
185
  deleteMany(keys: string[]): Promise<void>;
169
186
  protected onDispose(key: string, value: any, reason?: string): void;
170
187
  }
@@ -243,7 +260,7 @@ interface LocalMapCacheOptions extends BaseCacheOptions {
243
260
  /**
244
261
  * The underlying map.
245
262
  */
246
- cache?: MapLike<string, any>;
263
+ map?: MapLike<string, any>;
247
264
  /**
248
265
  * The maximum size of the cache.
249
266
  * When not set, the cache can grow indefinitely.
@@ -268,7 +285,7 @@ interface MapLike<K, V> {
268
285
  * Once the limit of items is reached, the first inserted keys will be purged.
269
286
  */
270
287
  declare class LocalMapCache extends BaseLocalCache {
271
- protected readonly cache: MapLike<string, any>;
288
+ protected readonly map: MapLike<string, any>;
272
289
  protected max: number;
273
290
  constructor(options?: LocalMapCacheOptions);
274
291
  setMany(data: Record<string, any>, options?: SetCacheOptions): Promise<void>;
@@ -277,6 +294,108 @@ declare class LocalMapCache extends BaseLocalCache {
277
294
  protected evict(length: number): void;
278
295
  }
279
296
  //#endregion
297
+ //#region src/local/weak/index.d.ts
298
+ interface WeakCacheOptions extends BaseCacheOptions {
299
+ /**
300
+ * The underlying cache. This must be an in-memory cache.
301
+ */
302
+ cache: BaseLocalCache;
303
+ }
304
+ type WeakValue = {
305
+ v: WeakRef<any>;
306
+ w: true;
307
+ } | {
308
+ v: any;
309
+ w: false;
310
+ };
311
+ /**
312
+ * A cache layer that stores objects as weak references.
313
+ *
314
+ * When an object is garbage collected, its entry is automatically removed from the underlying cache.
315
+ *
316
+ * This implementation requires support for both `WeakRef` and `FinalizationRegistry`.
317
+ *
318
+ * @see https://caniuse.com/mdn-javascript_builtins_finalizationregistry
319
+ * @see https://caniuse.com/mdn-javascript_builtins_weakref
320
+ */
321
+ declare class WeakCache extends BaseLocalCache {
322
+ protected readonly cache: BaseLocalCache;
323
+ protected readonly cacheInternal: LocalCacheInternal;
324
+ protected readonly registry: FinalizationRegistry<string>;
325
+ constructor(options: WeakCacheOptions);
326
+ protected onGarbageCollect: (key: string) => void;
327
+ protected onCacheDispose: (key: string, value: any, reason?: string) => void;
328
+ getOrLoad<T>(key: string, load: () => Promise<T>, options?: SetCacheOptions): Promise<T>;
329
+ /**
330
+ * Wraps the value in a WeakRef and registers it in the FinalizationRegistry if it's an object.
331
+ *
332
+ * @param key The key to reference the value in the FinalizationRegistry
333
+ * @param value The value to wrap
334
+ * @returns The wrapped value
335
+ */
336
+ protected wrapAndRegister(key: string, value: any): WeakValue;
337
+ /**
338
+ * Unwraps the value from a WeakRef if it's an object.
339
+ *
340
+ * @param data The data to unwrap
341
+ * @returns The unwrapped value
342
+ */
343
+ protected unwrap<T>(data: WeakValue | null): T | null;
344
+ /**
345
+ * Unregisters the value from the FinalizationRegistry if it's an object.
346
+ *
347
+ * @param value The value to unregister
348
+ */
349
+ protected unregister(value: WeakValue | null): void;
350
+ /**
351
+ * Unregisters the value associated with the given key from the FinalizationRegistry.
352
+ *
353
+ * @param key The key
354
+ */
355
+ protected unregisterByKey(key: string): void;
356
+ }
357
+ //#endregion
358
+ //#region src/local/cloning/index.d.ts
359
+ interface DeepCloningCacheOptions extends BaseCacheOptions {
360
+ /**
361
+ * The underlying cache. This must be an in-memory cache.
362
+ */
363
+ cache: BaseLocalCache;
364
+ /**
365
+ * The deep clone function to use.
366
+ *
367
+ * By default, it will try to use `structuredClone()` if available,
368
+ * otherwise it will use a JSON.parse/stringify-based implementation.
369
+ *
370
+ * @param data The data to deep clone
371
+ * @returns The cloned data
372
+ */
373
+ deepClone?: <T>(data: T) => T;
374
+ }
375
+ /**
376
+ * A cache layer that deep clones data when reading and writing.
377
+ *
378
+ * This is useful when you mutate the objects retrieved from cache,
379
+ * and you don't want them to also change in cache.
380
+ *
381
+ * Do not use this layer if you do not intend to mutate cached objects,
382
+ * as the cloning process adds unnecessary overhead.
383
+ */
384
+ declare class DeepCloningCache extends BaseLocalCache {
385
+ protected readonly cache: BaseLocalCache;
386
+ protected readonly cacheInternal: LocalCacheInternal;
387
+ protected deepClone: <T>(data: T) => T;
388
+ constructor(options: DeepCloningCacheOptions);
389
+ protected _get<T>(key: string): T | null;
390
+ protected _set<T>(key: string, value: T, options?: SetCacheOptions): void;
391
+ protected _delete(key: string): void;
392
+ protected _getMany<T>(keys: string[]): Record<string, T | null>;
393
+ protected _setMany<T>(data: Record<string, T>, options?: SetCacheOptions): void;
394
+ protected _deleteMany(keys: string[]): void;
395
+ protected _addDisposeListener(listener: any): void;
396
+ getOrLoad<T>(key: string, load: () => Promise<T>, options?: SetCacheOptions): Promise<T>;
397
+ }
398
+ //#endregion
280
399
  //#region src/local/noop/index.d.ts
281
400
  /**
282
401
  * A cache implementation that does nothing.
@@ -830,5 +949,5 @@ declare class MetricsCollectingCache implements ICache {
830
949
  resetMetrics(): void;
831
950
  }
832
951
  //#endregion
833
- export { AsyncLazyCache, AsyncLazyCacheOptions, BaseCache, BaseCacheOptions, CacheMetrics, CacheTier, CoalescingCache, CoalescingCacheOptions, ExistingLRUCacheOptions, ExistingTTLCacheOptions, ICache, IORedisCache, IORedisCacheOptions, JitteringCache, JitteringCacheOptions, KeyTransformingCache, KeyTransformingCacheOptions, KeyvCache, KeyvCacheOptions, LocalLRUCache, LocalLRUCacheOptions, LocalMapCache, LocalMapCacheOptions, LocalTTLCache, LocalTTLCacheOptions, Logger, MapLike, MemJSCache, MemJSCacheOptions, MemcacheCache, MemcacheCacheOptions, MetricsCollectingCache, MetricsCollectingCacheOptions, NoOpCache, RedisCache, RedisCacheOptions, SWRCache, SWRCacheOptions, SetCacheOptions, TieredCache, TieredCacheOptions, ValkeyGlideCache, ValkeyGlideCacheOptions, WorkersKVCache, WorkersKVCacheOptions };
952
+ export { AsyncLazyCache, AsyncLazyCacheOptions, BaseCache, BaseCacheOptions, BaseLocalCache, CacheMetrics, CacheTier, CoalescingCache, CoalescingCacheOptions, DeepCloningCache, DeepCloningCacheOptions, ExistingLRUCacheOptions, ExistingTTLCacheOptions, ICache, IORedisCache, IORedisCacheOptions, JitteringCache, JitteringCacheOptions, KeyTransformingCache, KeyTransformingCacheOptions, KeyvCache, KeyvCacheOptions, LocalCacheInternal, LocalLRUCache, LocalLRUCacheOptions, LocalMapCache, LocalMapCacheOptions, LocalTTLCache, LocalTTLCacheOptions, Logger, MapLike, MemJSCache, MemJSCacheOptions, MemcacheCache, MemcacheCacheOptions, MetricsCollectingCache, MetricsCollectingCacheOptions, NoOpCache, RedisCache, RedisCacheOptions, SWRCache, SWRCacheOptions, SetCacheOptions, TieredCache, TieredCacheOptions, ValkeyGlideCache, ValkeyGlideCacheOptions, WeakCache, WeakCacheOptions, WorkersKVCache, WorkersKVCacheOptions };
834
953
  //# sourceMappingURL=index.d.cts.map