evicting-cache 2.1.0 → 2.2.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.
@@ -77,6 +77,34 @@ declare class EvictingCache<K, V> {
77
77
  * @returns {number} The size of the cache.
78
78
  */
79
79
  get size(): number;
80
+ /**
81
+ * Returns an iterator over the keys in the cache.
82
+ * The keys are returned in the order of least recently used to most recently used.
83
+ *
84
+ * @returns {IterableIterator<K>} An iterator over the keys in the cache.
85
+ */
86
+ keys(): IterableIterator<K>;
87
+ /**
88
+ * Returns an iterator over the values in the cache.
89
+ * The values are returned in the order of least recently used to most recently used.
90
+ *
91
+ * @returns {IterableIterator<V>} An iterator over the values in the cache.
92
+ */
93
+ values(): IterableIterator<V>;
94
+ /**
95
+ * Returns an iterator over the entries in the cache.
96
+ * The entries are returned in the order of least recently used to most recently used.
97
+ *
98
+ * @returns {IterableIterator<[K, V]>} An iterator over the entries in the cache.
99
+ */
100
+ entries(): IterableIterator<[K, V]>;
101
+ /**
102
+ * Returns an iterator over the entries in the cache.
103
+ * The entries are returned in the order of least recently used to most recently used.
104
+ *
105
+ * @returns {IterableIterator<[K, V]>} An iterator over the entries in the cache.
106
+ */
107
+ [Symbol.iterator](): IterableIterator<[K, V]>;
80
108
  /**
81
109
  * Gets the description of the object.
82
110
  *
@@ -84,6 +112,14 @@ declare class EvictingCache<K, V> {
84
112
  * @returns {string} The description of the object.
85
113
  */
86
114
  get [Symbol.toStringTag](): string;
115
+ /**
116
+ * Puts a key-value pair into the cache and evicts the least recently used item if necessary.
117
+ * If the key already exists, the item is removed and re-added to update its position.
118
+ * If the cache is full, the least recently used item is evicted and the new item is added.
119
+ * @param {K} key The key to put.
120
+ * @param {V} value The value to put.
121
+ * @returns {V} The value that was put.
122
+ */
87
123
  private putAndEvict;
88
124
  }
89
125
 
@@ -1,2 +1,2 @@
1
- var c=class{_capacity;cache;constructor(e=100){if(e<1)throw new RangeError("capacity must be greater than 0");if(!Number.isInteger(e))throw new RangeError("capacity must be an integer");this._capacity=e,this.cache=new Map}get(e){let t=this.cache.get(e);return t===void 0?null:(this.cache.delete(e),this.cache.set(e,t),t)}has(e){return this.cache.has(e)}put(e,t){this.putAndEvict(e,t)}peek(e){return this.cache.get(e)??null}getOrPut(e,t){return this.get(e)??this.putAndEvict(e,t())}evict(){if(this.cache.size===0)return!1;let e=this.cache.keys().next().value;return this.cache.delete(e)}clear(){this.cache.clear()}get capacity(){return this._capacity}get size(){return this.cache.size}get[Symbol.toStringTag](){return"EvictingCache"}putAndEvict(e,t){return this.cache.has(e)&&this.cache.delete(e),this.cache.set(e,t),this.cache.size>this._capacity&&this.evict(),t}};export{c as EvictingCache};
1
+ var r=class{_capacity;cache;constructor(e=100){if(e<1)throw new RangeError("capacity must be greater than 0");if(!Number.isInteger(e))throw new RangeError("capacity must be an integer");this._capacity=e,this.cache=new Map}get(e){let t=this.cache.get(e);return t===void 0?null:(this.cache.delete(e),this.cache.set(e,t),t)}has(e){return this.cache.has(e)}put(e,t){this.putAndEvict(e,t)}peek(e){return this.cache.get(e)??null}getOrPut(e,t){return this.get(e)??this.putAndEvict(e,t())}evict(){if(this.cache.size===0)return!1;let e=this.cache.keys().next().value;return this.cache.delete(e)}clear(){this.cache.clear()}get capacity(){return this._capacity}get size(){return this.cache.size}keys(){return this.cache.keys()}values(){return this.cache.values()}entries(){return this.cache.entries()}[Symbol.iterator](){return this.entries()}get[Symbol.toStringTag](){return"EvictingCache"}putAndEvict(e,t){return this.cache.has(e)?this.cache.delete(e):this._capacity<=this.cache.size&&this.evict(),this.cache.set(e,t),t}};export{r as EvictingCache};
2
2
  //# sourceMappingURL=evicting-cache.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/evicting-cache.ts"],
4
- "sourcesContent": ["/** JavaScript implementation of a Least Recently Used(LRU) Cache using a Map. */\nexport class EvictingCache<K, V> {\n\tprivate readonly _capacity: number;\n\tprivate readonly cache: Map<K, V>;\n\n\t/**\n\t * Creates a new Evicting Cache with the given capacity.\n\t *\n\t * @param {number} [capacity=100] The maximum number of key-value pairs the cache can hold.\n\t */\n\tconstructor(capacity: number = 100) {\n\t\tif (capacity < 1) { throw new RangeError('capacity must be greater than 0') }\n\t\tif (!Number.isInteger(capacity)) { throw new RangeError('capacity must be an integer') }\n\n\t\tthis._capacity = capacity;\n\t\tthis.cache = new Map();\n\t}\n\n\t/**\n\t * Returns the value associated with the given key from the cache and updates the LRU order.\n\t *\n\t * @param {K} key The key to get the value for.\n\t * @returns {V | null} The associated value if the key is in the cache, or null otherwise.\n\t */\n\tget(key: K): V | null {\n\t\tconst value = this.cache.get(key);\n\t\tif (value === undefined) { return null }\n\n\t\tthis.cache.delete(key);\n\t\t// Move the accessed item to the end (most recently used)\n\t\tthis.cache.set(key, value);\n\n\t\treturn value;\n\t}\n\n\t/**\n\t * Returns true if the given key is in the cache, false otherwise.\n\t *\n\t * @param {K} key The key to check.\n\t * @returns {boolean} True if the key is in the cache, false otherwise.\n\t */\n\thas(key: K): boolean {\n\t\treturn this.cache.has(key);\n\t}\n\n\t/**\n\t * Adds a new key-value pair to the cache and updates the LRU order.\n\t * If adding the new pair will exceed the capacity, removes the least recently used pair from the cache.\n\t *\n\t * @param {K} key The key to add.\n\t * @param {V} value The value to add.\n\t * @returns {void}\n\t */\n\tput(key: K, value: V): void {\n\t\tthis.putAndEvict(key, value);\n\t}\n\n\t/**\n\t * Returns the value associated with the given key from the cache without updating the LRU order.\n\t *\n\t * @param {K} key The key to get the value for.\n\t * @returns {V | null} The associated value if the key is in the cache, or null otherwise.\n\t */\n\tpeek(key: K): V | null {\n\t\treturn this.cache.get(key) ?? null;\n\t}\n\n\t/**\n\t * Returns the value for the key if it exists in the cache. If not, put the key-value pair into the cache and return the value.\n\t * @param {K} key The key.\n\t * @param {function(): V} producer The value to put if the key does not exist in the cache.\n\t * @returns {V} The value corresponding to the key.\n\t */\n\tgetOrPut(key: K, producer: () => V): V {\n\t\treturn this.get(key) ?? this.putAndEvict(key, producer());\n\t}\n\n\t/**\n\t * Removes the least recently used key-value pair from the cache.\n\t *\n\t * @returns {boolean} True if an item was removed, false otherwise.\n\t */\n\tevict(): boolean {\n\t\tif (this.cache.size === 0) { return false }\n\t\tconst key = this.cache.keys().next().value as K;\n\n\t\treturn this.cache.delete(key);\n\t}\n\n\t/**\n\t * Clears the cache and the LRU list.\n\t *\n\t * @returns {void}\n\t */\n\tclear(): void {\n\t\tthis.cache.clear();\n\t}\n\n\t/**\n\t * Gets the capacity of the cache.\n\t * This is the maximum number of key-value pairs the cache can hold.\n\t * This is not the number of key-value pairs in the cache.\n\t *\n\t * @readonly\n\t * @returns {number} The capacity of the cache.\n\t */\n\tget capacity(): number {\n\t\treturn this._capacity;\n\t}\n\n\t/**\n\t * Gets the size of the cache.\n\t * This is the number of key-value pairs in the cache.\n\t * This is not the capacity of the cache.\n\t * The capacity is the maximum number of key-value pairs the cache can hold.\n\t * The size is the number of key-value pairs currently in the cache.\n\t * The size will be less than or equal to the capacity.\n\t *\n\t * @returns {number} The size of the cache.\n\t */\n\tget size(): number {\n\t\treturn this.cache.size;\n\t}\n\n\t/**\n\t * Gets the description of the object.\n\t *\n\t * @override\n\t * @returns {string} The description of the object.\n\t */\n\tget [Symbol.toStringTag](): string {\n\t\treturn 'EvictingCache';\n\t}\n\n\tprivate putAndEvict(key: K, value: V): V {\n\t\t// If the key already exists, remove it to update the LRU order and then set the new value.\n\t\t// This ensures that the most recently used item is at the end of the Map.\n\t\tif (this.cache.has(key)) { this.cache.delete(key) }\n\t\tthis.cache.set(key, value);\n\t\tif (this.cache.size > this._capacity) { this.evict() }\n\n\t\treturn value;\n\t}\n}"],
5
- "mappings": "AACO,IAAMA,EAAN,KAA0B,CACf,UACA,MAOjB,YAAYC,EAAmB,IAAK,CACnC,GAAIA,EAAW,EAAK,MAAM,IAAI,WAAW,iCAAiC,EAC1E,GAAI,CAAC,OAAO,UAAUA,CAAQ,EAAK,MAAM,IAAI,WAAW,6BAA6B,EAErF,KAAK,UAAYA,EACjB,KAAK,MAAQ,IAAI,GAClB,CAQA,IAAIC,EAAkB,CACrB,IAAMC,EAAQ,KAAK,MAAM,IAAID,CAAG,EAChC,OAAIC,IAAU,OAAoB,MAElC,KAAK,MAAM,OAAOD,CAAG,EAErB,KAAK,MAAM,IAAIA,EAAKC,CAAK,EAElBA,EACR,CAQA,IAAID,EAAiB,CACpB,OAAO,KAAK,MAAM,IAAIA,CAAG,CAC1B,CAUA,IAAIA,EAAQC,EAAgB,CAC3B,KAAK,YAAYD,EAAKC,CAAK,CAC5B,CAQA,KAAKD,EAAkB,CACtB,OAAO,KAAK,MAAM,IAAIA,CAAG,GAAK,IAC/B,CAQA,SAASA,EAAQE,EAAsB,CACtC,OAAO,KAAK,IAAIF,CAAG,GAAK,KAAK,YAAYA,EAAKE,EAAS,CAAC,CACzD,CAOA,OAAiB,CAChB,GAAI,KAAK,MAAM,OAAS,EAAK,MAAO,GACpC,IAAMF,EAAM,KAAK,MAAM,KAAK,EAAE,KAAK,EAAE,MAErC,OAAO,KAAK,MAAM,OAAOA,CAAG,CAC7B,CAOA,OAAc,CACb,KAAK,MAAM,MAAM,CAClB,CAUA,IAAI,UAAmB,CACtB,OAAO,KAAK,SACb,CAYA,IAAI,MAAe,CAClB,OAAO,KAAK,MAAM,IACnB,CAQA,IAAK,OAAO,WAAW,GAAY,CAClC,MAAO,eACR,CAEQ,YAAYA,EAAQC,EAAa,CAGxC,OAAI,KAAK,MAAM,IAAID,CAAG,GAAK,KAAK,MAAM,OAAOA,CAAG,EAChD,KAAK,MAAM,IAAIA,EAAKC,CAAK,EACrB,KAAK,MAAM,KAAO,KAAK,WAAa,KAAK,MAAM,EAE5CA,CACR,CACD",
4
+ "sourcesContent": ["/** JavaScript implementation of a Least Recently Used(LRU) Cache using a Map. */\nexport class EvictingCache<K, V> {\n\tprivate readonly _capacity: number;\n\tprivate readonly cache: Map<K, V>;\n\n\t/**\n\t * Creates a new Evicting Cache with the given capacity.\n\t *\n\t * @param {number} [capacity=100] The maximum number of key-value pairs the cache can hold.\n\t */\n\tconstructor(capacity: number = 100) {\n\t\tif (capacity < 1) { throw new RangeError('capacity must be greater than 0') }\n\t\tif (!Number.isInteger(capacity)) { throw new RangeError('capacity must be an integer') }\n\n\t\tthis._capacity = capacity;\n\t\tthis.cache = new Map();\n\t}\n\n\t/**\n\t * Returns the value associated with the given key from the cache and updates the LRU order.\n\t *\n\t * @param {K} key The key to get the value for.\n\t * @returns {V | null} The associated value if the key is in the cache, or null otherwise.\n\t */\n\tget(key: K): V | null {\n\t\tconst value = this.cache.get(key);\n\t\tif (value === undefined) { return null }\n\n\t\tthis.cache.delete(key);\n\t\t// Move the accessed item to the end (most recently used)\n\t\tthis.cache.set(key, value);\n\n\t\treturn value;\n\t}\n\n\t/**\n\t * Returns true if the given key is in the cache, false otherwise.\n\t *\n\t * @param {K} key The key to check.\n\t * @returns {boolean} True if the key is in the cache, false otherwise.\n\t */\n\thas(key: K): boolean {\n\t\treturn this.cache.has(key);\n\t}\n\n\t/**\n\t * Adds a new key-value pair to the cache and updates the LRU order.\n\t * If adding the new pair will exceed the capacity, removes the least recently used pair from the cache.\n\t *\n\t * @param {K} key The key to add.\n\t * @param {V} value The value to add.\n\t * @returns {void}\n\t */\n\tput(key: K, value: V): void {\n\t\tthis.putAndEvict(key, value);\n\t}\n\n\t/**\n\t * Returns the value associated with the given key from the cache without updating the LRU order.\n\t *\n\t * @param {K} key The key to get the value for.\n\t * @returns {V | null} The associated value if the key is in the cache, or null otherwise.\n\t */\n\tpeek(key: K): V | null {\n\t\treturn this.cache.get(key) ?? null;\n\t}\n\n\t/**\n\t * Returns the value for the key if it exists in the cache. If not, put the key-value pair into the cache and return the value.\n\t * @param {K} key The key.\n\t * @param {function(): V} producer The value to put if the key does not exist in the cache.\n\t * @returns {V} The value corresponding to the key.\n\t */\n\tgetOrPut(key: K, producer: () => V): V {\n\t\treturn this.get(key) ?? this.putAndEvict(key, producer());\n\t}\n\n\t/**\n\t * Removes the least recently used key-value pair from the cache.\n\t *\n\t * @returns {boolean} True if an item was removed, false otherwise.\n\t */\n\tevict(): boolean {\n\t\tif (this.cache.size === 0) { return false }\n\t\tconst key = this.cache.keys().next().value as K;\n\n\t\treturn this.cache.delete(key);\n\t}\n\n\t/**\n\t * Clears the cache and the LRU list.\n\t *\n\t * @returns {void}\n\t */\n\tclear(): void {\n\t\tthis.cache.clear();\n\t}\n\n\t/**\n\t * Gets the capacity of the cache.\n\t * This is the maximum number of key-value pairs the cache can hold.\n\t * This is not the number of key-value pairs in the cache.\n\t *\n\t * @readonly\n\t * @returns {number} The capacity of the cache.\n\t */\n\tget capacity(): number {\n\t\treturn this._capacity;\n\t}\n\n\t/**\n\t * Gets the size of the cache.\n\t * This is the number of key-value pairs in the cache.\n\t * This is not the capacity of the cache.\n\t * The capacity is the maximum number of key-value pairs the cache can hold.\n\t * The size is the number of key-value pairs currently in the cache.\n\t * The size will be less than or equal to the capacity.\n\t *\n\t * @returns {number} The size of the cache.\n\t */\n\tget size(): number {\n\t\treturn this.cache.size;\n\t}\n\n\t/**\n\t * Returns an iterator over the keys in the cache.\n\t * The keys are returned in the order of least recently used to most recently used.\n\t *\n\t * @returns {IterableIterator<K>} An iterator over the keys in the cache.\n\t */\n\tkeys(): IterableIterator<K> {\n\t\treturn this.cache.keys();\n\t}\n\n\t/**\n\t * Returns an iterator over the values in the cache.\n\t * The values are returned in the order of least recently used to most recently used.\n\t *\n\t * @returns {IterableIterator<V>} An iterator over the values in the cache.\n\t */\n\tvalues(): IterableIterator<V> {\n\t\treturn this.cache.values();\n\t}\n\n\t/**\n\t * Returns an iterator over the entries in the cache.\n\t * The entries are returned in the order of least recently used to most recently used.\n\t *\n\t * @returns {IterableIterator<[K, V]>} An iterator over the entries in the cache.\n\t */\n\tentries(): IterableIterator<[K, V]> {\n\t\treturn this.cache.entries();\n\t}\n\n\t/**\n\t * Returns an iterator over the entries in the cache.\n\t * The entries are returned in the order of least recently used to most recently used.\n\t *\n\t * @returns {IterableIterator<[K, V]>} An iterator over the entries in the cache.\n\t */\n\t[Symbol.iterator](): IterableIterator<[K, V]> {\n\t\treturn this.entries();\n\t}\n\n\t/**\n\t * Gets the description of the object.\n\t *\n\t * @override\n\t * @returns {string} The description of the object.\n\t */\n\tget [Symbol.toStringTag](): string {\n\t\treturn 'EvictingCache';\n\t}\n\n\t/**\n\t * Puts a key-value pair into the cache and evicts the least recently used item if necessary.\n\t * If the key already exists, the item is removed and re-added to update its position.\n\t * If the cache is full, the least recently used item is evicted and the new item is added.\n\t * @param {K} key The key to put.\n\t * @param {V} value The value to put.\n\t * @returns {V} The value that was put.\n\t */\n\tprivate putAndEvict(key: K, value: V): V {\n\t\tif (this.cache.has(key)) {\n\t\t\tthis.cache.delete(key);\n\t\t} else if (this._capacity <= this.cache.size) {\n\t\t\tthis.evict();\n\t\t}\n\n\t\tthis.cache.set(key, value);\n\n\t\treturn value;\n\t}\n}"],
5
+ "mappings": "AACO,IAAMA,EAAN,KAA0B,CACf,UACA,MAOjB,YAAYC,EAAmB,IAAK,CACnC,GAAIA,EAAW,EAAK,MAAM,IAAI,WAAW,iCAAiC,EAC1E,GAAI,CAAC,OAAO,UAAUA,CAAQ,EAAK,MAAM,IAAI,WAAW,6BAA6B,EAErF,KAAK,UAAYA,EACjB,KAAK,MAAQ,IAAI,GAClB,CAQA,IAAIC,EAAkB,CACrB,IAAMC,EAAQ,KAAK,MAAM,IAAID,CAAG,EAChC,OAAIC,IAAU,OAAoB,MAElC,KAAK,MAAM,OAAOD,CAAG,EAErB,KAAK,MAAM,IAAIA,EAAKC,CAAK,EAElBA,EACR,CAQA,IAAID,EAAiB,CACpB,OAAO,KAAK,MAAM,IAAIA,CAAG,CAC1B,CAUA,IAAIA,EAAQC,EAAgB,CAC3B,KAAK,YAAYD,EAAKC,CAAK,CAC5B,CAQA,KAAKD,EAAkB,CACtB,OAAO,KAAK,MAAM,IAAIA,CAAG,GAAK,IAC/B,CAQA,SAASA,EAAQE,EAAsB,CACtC,OAAO,KAAK,IAAIF,CAAG,GAAK,KAAK,YAAYA,EAAKE,EAAS,CAAC,CACzD,CAOA,OAAiB,CAChB,GAAI,KAAK,MAAM,OAAS,EAAK,MAAO,GACpC,IAAMF,EAAM,KAAK,MAAM,KAAK,EAAE,KAAK,EAAE,MAErC,OAAO,KAAK,MAAM,OAAOA,CAAG,CAC7B,CAOA,OAAc,CACb,KAAK,MAAM,MAAM,CAClB,CAUA,IAAI,UAAmB,CACtB,OAAO,KAAK,SACb,CAYA,IAAI,MAAe,CAClB,OAAO,KAAK,MAAM,IACnB,CAQA,MAA4B,CAC3B,OAAO,KAAK,MAAM,KAAK,CACxB,CAQA,QAA8B,CAC7B,OAAO,KAAK,MAAM,OAAO,CAC1B,CAQA,SAAoC,CACnC,OAAO,KAAK,MAAM,QAAQ,CAC3B,CAQA,CAAC,OAAO,QAAQ,GAA8B,CAC7C,OAAO,KAAK,QAAQ,CACrB,CAQA,IAAK,OAAO,WAAW,GAAY,CAClC,MAAO,eACR,CAUQ,YAAYA,EAAQC,EAAa,CACxC,OAAI,KAAK,MAAM,IAAID,CAAG,EACrB,KAAK,MAAM,OAAOA,CAAG,EACX,KAAK,WAAa,KAAK,MAAM,MACvC,KAAK,MAAM,EAGZ,KAAK,MAAM,IAAIA,EAAKC,CAAK,EAElBA,CACR,CACD",
6
6
  "names": ["EvictingCache", "capacity", "key", "value", "producer"]
7
7
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "evicting-cache",
3
3
  "author": "D1g1talEntr0py",
4
- "version": "2.1.0",
4
+ "version": "2.2.0",
5
5
  "license": "ISC",
6
6
  "description": "Cache implementation with an LRU evicting policy",
7
7
  "type": "module",
@@ -24,15 +24,15 @@
24
24
  ],
25
25
  "devDependencies": {
26
26
  "@eslint/compat": "^1.3.1",
27
- "@eslint/js": "^9.31.0",
27
+ "@eslint/js": "^9.32.0",
28
28
  "@types/eslint": "^9.6.1",
29
29
  "@types/node": "^24.1.0",
30
30
  "@typescript-eslint/eslint-plugin": "^8.38.0",
31
31
  "@typescript-eslint/parser": "^8.38.0",
32
32
  "@vitest/coverage-v8": "^3.2.4",
33
- "eslint": "^9.31.0",
33
+ "eslint": "^9.32.0",
34
34
  "eslint-plugin-compat": "^6.0.2",
35
- "eslint-plugin-jsdoc": "^51.4.1",
35
+ "eslint-plugin-jsdoc": "^52.0.1",
36
36
  "globals": "^16.3.0",
37
37
  "typescript": "^5.8.3",
38
38
  "typescript-eslint": "^8.38.0",
@@ -122,6 +122,46 @@ export class EvictingCache<K, V> {
122
122
  return this.cache.size;
123
123
  }
124
124
 
125
+ /**
126
+ * Returns an iterator over the keys in the cache.
127
+ * The keys are returned in the order of least recently used to most recently used.
128
+ *
129
+ * @returns {IterableIterator<K>} An iterator over the keys in the cache.
130
+ */
131
+ keys(): IterableIterator<K> {
132
+ return this.cache.keys();
133
+ }
134
+
135
+ /**
136
+ * Returns an iterator over the values in the cache.
137
+ * The values are returned in the order of least recently used to most recently used.
138
+ *
139
+ * @returns {IterableIterator<V>} An iterator over the values in the cache.
140
+ */
141
+ values(): IterableIterator<V> {
142
+ return this.cache.values();
143
+ }
144
+
145
+ /**
146
+ * Returns an iterator over the entries in the cache.
147
+ * The entries are returned in the order of least recently used to most recently used.
148
+ *
149
+ * @returns {IterableIterator<[K, V]>} An iterator over the entries in the cache.
150
+ */
151
+ entries(): IterableIterator<[K, V]> {
152
+ return this.cache.entries();
153
+ }
154
+
155
+ /**
156
+ * Returns an iterator over the entries in the cache.
157
+ * The entries are returned in the order of least recently used to most recently used.
158
+ *
159
+ * @returns {IterableIterator<[K, V]>} An iterator over the entries in the cache.
160
+ */
161
+ [Symbol.iterator](): IterableIterator<[K, V]> {
162
+ return this.entries();
163
+ }
164
+
125
165
  /**
126
166
  * Gets the description of the object.
127
167
  *
@@ -132,12 +172,22 @@ export class EvictingCache<K, V> {
132
172
  return 'EvictingCache';
133
173
  }
134
174
 
175
+ /**
176
+ * Puts a key-value pair into the cache and evicts the least recently used item if necessary.
177
+ * If the key already exists, the item is removed and re-added to update its position.
178
+ * If the cache is full, the least recently used item is evicted and the new item is added.
179
+ * @param {K} key The key to put.
180
+ * @param {V} value The value to put.
181
+ * @returns {V} The value that was put.
182
+ */
135
183
  private putAndEvict(key: K, value: V): V {
136
- // If the key already exists, remove it to update the LRU order and then set the new value.
137
- // This ensures that the most recently used item is at the end of the Map.
138
- if (this.cache.has(key)) { this.cache.delete(key) }
184
+ if (this.cache.has(key)) {
185
+ this.cache.delete(key);
186
+ } else if (this._capacity <= this.cache.size) {
187
+ this.evict();
188
+ }
189
+
139
190
  this.cache.set(key, value);
140
- if (this.cache.size > this._capacity) { this.evict() }
141
191
 
142
192
  return value;
143
193
  }