diff --git a/CHANGELOG.md b/CHANGELOG.md index ced1a4d..d550c7d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,8 +4,28 @@ All notable changes to this project will be documented in this file. Dates are d Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). +#### [13.1.1](https://github.com/avoidwork/tiny-lru/compare/13.1.0...13.1.1) + +- fix: preserve cleanup list links across TTL expiry [`#510`](https://github.com/avoidwork/tiny-lru/pull/510) +- build(deps-dev): bump rollup from 4.64.7 to 4.64.9 [`#514`](https://github.com/avoidwork/tiny-lru/pull/514) +- build(deps-dev): bump oxlint from 1.87.0 to 1.88.0 [`#513`](https://github.com/avoidwork/tiny-lru/pull/513) +- build(deps-dev): bump rollup from 4.64.5 to 4.64.7 [`#512`](https://github.com/avoidwork/tiny-lru/pull/512) +- build(deps-dev): bump oxfmt from 0.72.0 to 0.73.0 [`#511`](https://github.com/avoidwork/tiny-lru/pull/511) +- build(deps-dev): bump rollup from 4.64.3 to 4.64.5 [`#509`](https://github.com/avoidwork/tiny-lru/pull/509) +- build(deps-dev): bump tinybench from 6.2.1 to 6.2.2 [`#508`](https://github.com/avoidwork/tiny-lru/pull/508) +- build(deps-dev): bump rollup from 4.64.1 to 4.64.3 [`#507`](https://github.com/avoidwork/tiny-lru/pull/507) +- chore: update dev dependencies to latest versions [`#506`](https://github.com/avoidwork/tiny-lru/pull/506) +- build(deps-dev): bump rollup from 4.63.6 to 4.64.0 [`#505`](https://github.com/avoidwork/tiny-lru/pull/505) +- build(deps-dev): bump rollup from 4.63.5 to 4.63.6 [`#504`](https://github.com/avoidwork/tiny-lru/pull/504) +- build(deps-dev): bump oxlint from 1.85.0 to 1.86.0 [`#503`](https://github.com/avoidwork/tiny-lru/pull/503) +- build(deps-dev): bump rollup from 4.63.4 to 4.63.5 [`#501`](https://github.com/avoidwork/tiny-lru/pull/501) +- build(deps-dev): bump auto-changelog from 2.6.1 to 2.7.0 [`#500`](https://github.com/avoidwork/tiny-lru/pull/500) + #### [13.1.0](https://github.com/avoidwork/tiny-lru/compare/13.0.1...13.1.0) +> 26 September 2026 + +- chore: release v13.1.0 [`#499`](https://github.com/avoidwork/tiny-lru/pull/499) - feat: add fireOnEvict option to cleanup() [`#498`](https://github.com/avoidwork/tiny-lru/pull/498) - docs: correct README, API docs, and type definitions [`#497`](https://github.com/avoidwork/tiny-lru/pull/497) - build(deps-dev): bump oxlint from 1.83.0 to 1.85.0 [`#496`](https://github.com/avoidwork/tiny-lru/pull/496) diff --git a/dist/tiny-lru.cjs b/dist/tiny-lru.cjs index dddd421..1329c72 100644 --- a/dist/tiny-lru.cjs +++ b/dist/tiny-lru.cjs @@ -3,7 +3,7 @@ * * @copyright 2026 Jason Mulligan * @license BSD-3-Clause - * @version 13.1.0 + * @version 13.1.1 */ 'use strict'; @@ -57,7 +57,7 @@ class LRU { * @returns {LRU} The LRU instance for method chaining. */ clear() { - for (let x = this.first; x !== null; ) { + for (let x = this.first; x !== null;) { const next = x.next; x.prev = null; x.next = null; @@ -481,7 +481,7 @@ class LRU { * @returns {LRU} The LRU instance for method chaining. */ forEach(callback, thisArg) { - for (let x = this.first; x !== null; ) { + for (let x = this.first; x !== null;) { const next = x.next; if (!this.#isExpired(x)) { callback.call(thisArg, x.value, x.key, this); @@ -566,7 +566,7 @@ class LRU { let removed = 0; - for (let x = this.first; x !== null; ) { + for (let x = this.first; x !== null;) { const next = x.next; if (this.#isExpired(x)) { const key = x.key; @@ -589,10 +589,6 @@ class LRU { x = next; } - if (removed > 0) { - this.#rebuildList(); - } - return removed; } @@ -715,39 +711,6 @@ class LRU { return { valid, expired, noTTL: [] }; } - - /** - * Rebuild the doubly-linked list after cleanup by deleting expired items. - * This removes nodes that were deleted during cleanup. - * - * @private - */ - #rebuildList() { - if (this.size === 0) { - this.first = null; - this.last = null; - return; - } - - const keys = this.keys(); - this.first = null; - this.last = null; - - for (let i = 0; i < keys.length; i++) { - const item = this.items[keys[i]]; - if (item !== null && item !== undefined) { - if (this.first === null) { - this.first = item; - item.prev = null; - } else { - item.prev = this.last; - this.last.next = item; - } - item.next = null; - this.last = item; - } - } - } } /** diff --git a/dist/tiny-lru.js b/dist/tiny-lru.js index 0cd9aa6..69c9922 100644 --- a/dist/tiny-lru.js +++ b/dist/tiny-lru.js @@ -3,7 +3,7 @@ * * @copyright 2026 Jason Mulligan * @license BSD-3-Clause - * @version 13.1.0 + * @version 13.1.1 */ /** * A high-performance Least Recently Used (LRU) cache implementation with optional TTL support. @@ -55,7 +55,7 @@ class LRU { * @returns {LRU} The LRU instance for method chaining. */ clear() { - for (let x = this.first; x !== null; ) { + for (let x = this.first; x !== null;) { const next = x.next; x.prev = null; x.next = null; @@ -479,7 +479,7 @@ class LRU { * @returns {LRU} The LRU instance for method chaining. */ forEach(callback, thisArg) { - for (let x = this.first; x !== null; ) { + for (let x = this.first; x !== null;) { const next = x.next; if (!this.#isExpired(x)) { callback.call(thisArg, x.value, x.key, this); @@ -564,7 +564,7 @@ class LRU { let removed = 0; - for (let x = this.first; x !== null; ) { + for (let x = this.first; x !== null;) { const next = x.next; if (this.#isExpired(x)) { const key = x.key; @@ -587,10 +587,6 @@ class LRU { x = next; } - if (removed > 0) { - this.#rebuildList(); - } - return removed; } @@ -713,39 +709,6 @@ class LRU { return { valid, expired, noTTL: [] }; } - - /** - * Rebuild the doubly-linked list after cleanup by deleting expired items. - * This removes nodes that were deleted during cleanup. - * - * @private - */ - #rebuildList() { - if (this.size === 0) { - this.first = null; - this.last = null; - return; - } - - const keys = this.keys(); - this.first = null; - this.last = null; - - for (let i = 0; i < keys.length; i++) { - const item = this.items[keys[i]]; - if (item !== null && item !== undefined) { - if (this.first === null) { - this.first = item; - item.prev = null; - } else { - item.prev = this.last; - this.last.next = item; - } - item.next = null; - this.last = item; - } - } - } } /** diff --git a/dist/tiny-lru.min.js b/dist/tiny-lru.min.js index 9c87efa..948e563 100644 --- a/dist/tiny-lru.min.js +++ b/dist/tiny-lru.min.js @@ -1,5 +1,5 @@ /*! 2026 Jason Mulligan - @version 13.1.0 + @version 13.1.1 */ -class t{#t;#s;constructor(t=0,s=0,e=!1){if(!Number.isInteger(t)||t<0)throw new TypeError("Invalid max value");if(!Number.isInteger(s)||s<0)throw new TypeError("Invalid ttl value");if("boolean"!=typeof e)throw new TypeError("Invalid resetTTL value");this.first=null,this.items=Object.create(null),this.last=null,this.max=t,this.resetTTL=e,this.size=0,this.ttl=s,this.#t={hits:0,misses:0,sets:0,deletes:0,evictions:0},this.#s=null}clear(){for(let t=this.first;null!==t;){const s=t.next;t.prev=null,t.next=null,t=s}return this.first=null,this.items=Object.create(null),this.last=null,this.size=0,this.#t.hits=0,this.#t.misses=0,this.#t.sets=0,this.#t.deletes=0,this.#t.evictions=0,this}delete(t){const s=this.items[t];return void 0!==s&&(this.#e(s),this.#t.deletes++),this}entries(t){if(void 0===t){const t=[];for(let s=this.first;null!==s;s=s.next)this.#i(s)||t.push([s.key,s.value]);return t}if(!Array.isArray(t))throw new TypeError("keys must be an array");const s=Array.from({length:t.length});for(let e=0;e0&&this.size===this.max){const t=this.#r();e={key:t.key,value:t.value,expiry:t.expiry}}i=this.items[t]={expiry:this.ttl>0?Date.now()+this.ttl:this.ttl,key:t,prev:this.last,next:null,value:s},1==++this.size?this.first=i:this.last.next=i,this.last=i}else i.value=s,this.resetTTL&&(i.expiry=this.ttl>0?Date.now()+this.ttl:this.ttl),this.moveToEnd(i);return this.#t.sets++,e}set(t,s){let e=this.items[t];return void 0===e||this.#i(e)?(void 0!==e&&this.#e(e),this.max>0&&this.size===this.max&&this.evict(),e=this.items[t]={expiry:this.ttl>0?Date.now()+this.ttl:this.ttl,key:t,prev:this.last,next:null,value:s},1==++this.size?this.first=e:this.last.next=e,this.last=e):(e.value=s,this.resetTTL&&(e.expiry=this.ttl>0?Date.now()+this.ttl:this.ttl),this.moveToEnd(e)),this.#t.sets++,this}values(t){if(void 0===t){const t=[];for(let s=this.first;null!==s;s=s.next)this.#i(s)||t.push(s.value);return t}if(!Array.isArray(t))throw new TypeError("keys must be an array");const s=Array.from({length:t.length});for(let e=0;e0&&this.#n(),s}toJSON(){const t=[];for(let s=this.first;null!==s;s=s.next)this.#i(s)||t.push({key:s.key,value:s.value,expiry:s.expiry});return t}stats(){return{...this.#t}}onEvict(t){if("function"!=typeof t)throw new TypeError("onEvict callback must be a function");return this.#s=t,this}sizeByTTL(){if(0===this.ttl)return{valid:this.size,expired:0,noTTL:this.size};const t=Date.now();let s=0,e=0;for(let i=this.first;null!==i;i=i.next)i.expiry>t?s++:e++;return{valid:s,expired:e,noTTL:0}}keysByTTL(){if(0===this.ttl)return{valid:this.keys(),expired:[],noTTL:this.keys()};const t=Date.now(),s=[],e=[];for(let i=this.first;null!==i;i=i.next)i.expiry>t?s.push(i.key):e.push(i.key);return{valid:s,expired:e,noTTL:[]}}valuesByTTL(){if(0===this.ttl)return{valid:this.values(),expired:[],noTTL:this.values()};const t=Date.now(),s=[],e=[];for(let i=this.first;null!==i;i=i.next)i.expiry>t?s.push(i.value):e.push(i.value);return{valid:s,expired:e,noTTL:[]}}#n(){if(0===this.size)return this.first=null,void(this.last=null);const t=this.keys();this.first=null,this.last=null;for(let s=0;s0&&this.size===this.max){const t=this.#r();s={key:t.key,value:t.value,expiry:t.expiry}}i=this.items[t]={expiry:this.ttl>0?Date.now()+this.ttl:this.ttl,key:t,prev:this.last,next:null,value:e},1==++this.size?this.first=i:this.last.next=i,this.last=i}else i.value=e,this.resetTTL&&(i.expiry=this.ttl>0?Date.now()+this.ttl:this.ttl),this.moveToEnd(i);return this.#t.sets++,s}set(t,e){let s=this.items[t];return void 0===s||this.#i(s)?(void 0!==s&&this.#s(s),this.max>0&&this.size===this.max&&this.evict(),s=this.items[t]={expiry:this.ttl>0?Date.now()+this.ttl:this.ttl,key:t,prev:this.last,next:null,value:e},1==++this.size?this.first=s:this.last.next=s,this.last=s):(s.value=e,this.resetTTL&&(s.expiry=this.ttl>0?Date.now()+this.ttl:this.ttl),this.moveToEnd(s)),this.#t.sets++,this}values(t){if(void 0===t){const t=[];for(let e=this.first;null!==e;e=e.next)this.#i(e)||t.push(e.value);return t}if(!Array.isArray(t))throw new TypeError("keys must be an array");const e=Array.from({length:t.length});for(let s=0;st?e++:s++;return{valid:e,expired:s,noTTL:0}}keysByTTL(){if(0===this.ttl)return{valid:this.keys(),expired:[],noTTL:this.keys()};const t=Date.now(),e=[],s=[];for(let i=this.first;null!==i;i=i.next)i.expiry>t?e.push(i.key):s.push(i.key);return{valid:e,expired:s,noTTL:[]}}valuesByTTL(){if(0===this.ttl)return{valid:this.values(),expired:[],noTTL:this.values()};const t=Date.now(),e=[],s=[];for(let i=this.first;null!==i;i=i.next)i.expiry>t?e.push(i.value):s.push(i.value);return{valid:e,expired:s,noTTL:[]}}}function e(e=1e3,s=0,i=!1){return new t(e,s,i)}export{t as LRU,e as lru};//# sourceMappingURL=tiny-lru.min.js.map diff --git a/dist/tiny-lru.min.js.map b/dist/tiny-lru.min.js.map index 9ce59c6..067cb95 100644 --- a/dist/tiny-lru.min.js.map +++ b/dist/tiny-lru.min.js.map @@ -1 +1 @@ -{"version":3,"file":"tiny-lru.min.js","sources":["../src/lru.js"],"sourcesContent":["/**\n * A high-performance Least Recently Used (LRU) cache implementation with optional TTL support.\n * Items are automatically evicted when the cache reaches its maximum size,\n * removing the least recently used items first. All core operations (get, set, delete) are O(1).\n *\n * @class LRU\n */\nexport class LRU {\n\t#stats;\n\t#onEvict;\n\n\t/**\n\t * Creates a new LRU cache instance.\n\t *\n\t * @constructor\n\t * @param {number} [max=0] - Maximum number of items to store. 0 means unlimited.\n\t * @param {number} [ttl=0] - Time to live in milliseconds. 0 means no expiration.\n\t * @param {boolean} [resetTTL=false] - Whether to reset TTL when updating existing items via set().\n\t * @throws {TypeError} When parameters are invalid (negative numbers or wrong types).\n\t */\n\tconstructor(max = 0, ttl = 0, resetTTL = false) {\n\t\tif (!Number.isInteger(max) || max < 0) {\n\t\t\tthrow new TypeError(\"Invalid max value\");\n\t\t}\n\n\t\tif (!Number.isInteger(ttl) || ttl < 0) {\n\t\t\tthrow new TypeError(\"Invalid ttl value\");\n\t\t}\n\n\t\tif (typeof resetTTL !== \"boolean\") {\n\t\t\tthrow new TypeError(\"Invalid resetTTL value\");\n\t\t}\n\n\t\tthis.first = null;\n\t\tthis.items = Object.create(null);\n\t\tthis.last = null;\n\t\tthis.max = max;\n\t\tthis.resetTTL = resetTTL;\n\t\tthis.size = 0;\n\t\tthis.ttl = ttl;\n\t\tthis.#stats = { hits: 0, misses: 0, sets: 0, deletes: 0, evictions: 0 };\n\t\tthis.#onEvict = null;\n\t}\n\n\t/**\n\t * Removes all items from the cache.\n\t *\n\t * @returns {LRU} The LRU instance for method chaining.\n\t */\n\tclear() {\n\t\tfor (let x = this.first; x !== null; ) {\n\t\t\tconst next = x.next;\n\t\t\tx.prev = null;\n\t\t\tx.next = null;\n\t\t\tx = next;\n\t\t}\n\n\t\tthis.first = null;\n\t\tthis.items = Object.create(null);\n\t\tthis.last = null;\n\t\tthis.size = 0;\n\t\tthis.#stats.hits = 0;\n\t\tthis.#stats.misses = 0;\n\t\tthis.#stats.sets = 0;\n\t\tthis.#stats.deletes = 0;\n\t\tthis.#stats.evictions = 0;\n\n\t\treturn this;\n\t}\n\n\t/**\n\t * Removes an item from the cache by key.\n\t *\n\t * @param {string} key - The key of the item to delete.\n\t * @returns {LRU} The LRU instance for method chaining.\n\t */\n\tdelete(key) {\n\t\tconst item = this.items[key];\n\n\t\tif (item !== undefined) {\n\t\t\tthis.#removeItem(item);\n\t\t\tthis.#stats.deletes++;\n\t\t}\n\n\t\treturn this;\n\t}\n\n\t/**\n\t * Returns an array of [key, value] pairs for the specified keys.\n\t * When no keys provided, returns all entries in LRU order.\n\t * When keys provided, order matches the input array.\n\t *\n\t * @param {string[]} [keys=this.keys()] - Array of keys to get entries for. Defaults to all keys.\n\t * @returns {Array>} Array of [key, value] pairs.\n\t */\n\tentries(keys) {\n\t\tif (keys === undefined) {\n\t\t\tconst result = [];\n\t\t\tfor (let x = this.first; x !== null; x = x.next) {\n\t\t\t\tif (!this.#isExpired(x)) {\n\t\t\t\t\tresult.push([x.key, x.value]);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn result;\n\t\t}\n\n\t\tif (!Array.isArray(keys)) {\n\t\t\tthrow new TypeError(\"keys must be an array\");\n\t\t}\n\n\t\tconst result = Array.from({ length: keys.length });\n\t\tfor (let i = 0; i < keys.length; i++) {\n\t\t\tconst key = keys[i];\n\t\t\tconst item = this.items[key];\n\t\t\tresult[i] = [key, item !== undefined && !this.#isExpired(item) ? item.value : undefined];\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t/**\n\t * Removes the least recently used item from the cache.\n\t *\n\t * @returns {LRU} The LRU instance for method chaining.\n\t */\n\tevict() {\n\t\tif (this.size === 0) {\n\t\t\treturn this;\n\t\t}\n\n\t\tconst item = this.#evictItem();\n\n\t\tif (this.#onEvict !== null) {\n\t\t\tthis.#onEvict({\n\t\t\t\tkey: item.key,\n\t\t\t\tvalue: item.value,\n\t\t\t\texpiry: item.expiry,\n\t\t\t});\n\t\t}\n\n\t\treturn this;\n\t}\n\n\t/**\n\t * Returns the expiration timestamp for a given key.\n\t *\n\t * @param {string} key - The key to check expiration for.\n\t * @returns {number|undefined} The expiration timestamp in milliseconds, or undefined if key doesn't exist.\n\t */\n\texpiresAt(key) {\n\t\tconst item = this.items[key];\n\t\treturn item !== undefined ? item.expiry : undefined;\n\t}\n\n\t/**\n\t * Checks if an item has expired.\n\t *\n\t * @param {Object} item - The cache item to check.\n\t * @returns {boolean} True if the item has expired, false otherwise.\n\t * @private\n\t */\n\t#isExpired(item) {\n\t\tif (this.ttl === 0) {\n\t\t\treturn false;\n\t\t}\n\n\t\treturn item.expiry <= Date.now();\n\t}\n\n\t/**\n\t * Retrieves a value from the cache by key without updating LRU order.\n\t * Note: Does not perform TTL checks or remove expired items.\n\t *\n\t * @param {string} key - The key to retrieve.\n\t * @returns {*} The value associated with the key, or undefined if not found.\n\t */\n\tpeek(key) {\n\t\tconst item = this.items[key];\n\t\treturn item !== undefined ? item.value : undefined;\n\t}\n\n\t/**\n\t * Retrieves a value from the cache by key. Updates the item's position to most recently used.\n\t *\n\t * @param {string} key - The key to retrieve.\n\t * @returns {*} The value associated with the key, or undefined if not found or expired.\n\t */\n\tget(key) {\n\t\tconst item = this.items[key];\n\n\t\tif (item !== undefined) {\n\t\t\tif (!this.#isExpired(item)) {\n\t\t\t\tthis.moveToEnd(item);\n\t\t\t\tthis.#stats.hits++;\n\t\t\t\treturn item.value;\n\t\t\t}\n\n\t\t\tthis.#removeItem(item);\n\t\t\tthis.#stats.misses++;\n\t\t\treturn undefined;\n\t\t}\n\n\t\tthis.#stats.misses++;\n\t\treturn undefined;\n\t}\n\n\t/**\n\t * Checks if a key exists in the cache.\n\t * Expired items are removed before returning false.\n\t *\n\t * @param {string} key - The key to check for.\n\t * @returns {boolean} True if the key exists and is not expired, false otherwise.\n\t */\n\thas(key) {\n\t\tconst item = this.items[key];\n\n\t\tif (item !== undefined && this.#isExpired(item)) {\n\t\t\tthis.#removeItem(item);\n\t\t\treturn false;\n\t\t}\n\n\t\treturn item !== undefined;\n\t}\n\n\t/**\n\t * Unlinks an item from the doubly-linked list.\n\t * Updates first/last pointers if needed.\n\t * Does NOT clear the item's prev/next pointers or delete from items map.\n\t *\n\t * @private\n\t */\n\t#unlink(item) {\n\t\tif (item.prev !== null) {\n\t\t\titem.prev.next = item.next;\n\t\t}\n\n\t\tif (item.next !== null) {\n\t\t\titem.next.prev = item.prev;\n\t\t}\n\n\t\tif (this.first === item) {\n\t\t\tthis.first = item.next;\n\t\t}\n\n\t\tif (this.last === item) {\n\t\t\tthis.last = item.prev;\n\t\t}\n\t}\n\n\t/**\n\t * Removes an item from the cache without incrementing the deletes stat.\n\t * Used internally by get()/has() when removing expired items.\n\t *\n\t * @param {Object} item - The cache item to remove.\n\t * @private\n\t */\n\t#removeItem(item) {\n\t\tdelete this.items[item.key];\n\t\tthis.size--;\n\t\tthis.#unlink(item);\n\t\titem.prev = null;\n\t\titem.next = null;\n\t}\n\n\t/**\n\t * Evicts the least recently used item from the cache without firing onEvict.\n\t * Used internally by setWithEvicted() to avoid double-notification.\n\t *\n\t * @returns {Object} The evicted item.\n\t * @private\n\t */\n\t#evictItem() {\n\t\tconst item = this.first;\n\n\t\tdelete this.items[item.key];\n\t\tthis.#stats.evictions++;\n\n\t\tif (--this.size === 0) {\n\t\t\tthis.first = null;\n\t\t\tthis.last = null;\n\t\t} else {\n\t\t\tthis.#unlink(item);\n\t\t}\n\n\t\titem.prev = null;\n\t\titem.next = null;\n\n\t\treturn item;\n\t}\n\n\t/**\n\t * Efficiently moves an item to the end of the LRU list (most recently used position).\n\t * This is an internal optimization method that avoids the overhead of the full set() operation\n\t * when only LRU position needs to be updated.\n\t *\n\t * @param {Object} item - The cache item with prev/next pointers to reposition.\n\t * @private\n\t */\n\tmoveToEnd(item) {\n\t\tif (this.last === item) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.#unlink(item);\n\n\t\titem.prev = this.last;\n\t\titem.next = null;\n\t\tthis.last.next = item;\n\t\tthis.last = item;\n\t}\n\n\t/**\n\t * Returns an array of all keys in the cache, ordered from least to most recently used.\n\t * Expired items are skipped, consistent with entries(), values(), and toJSON().\n\t *\n\t * @returns {string[]} Array of keys in LRU order.\n\t */\n\tkeys() {\n\t\tconst result = [];\n\t\tfor (let x = this.first; x !== null; x = x.next) {\n\t\t\tif (!this.#isExpired(x)) {\n\t\t\t\tresult.push(x.key);\n\t\t\t}\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t/**\n\t * Sets a value in the cache and returns any evicted item.\n\t * Eviction is silent — onEvict is not fired for the returned item.\n\t *\n\t * @param {string} key - The key to set.\n\t * @param {*} value - The value to store.\n\t * @returns {Object|null} The evicted item (if any) with shape {key, value, expiry}, or null.\n\t */\n\tsetWithEvicted(key, value) {\n\t\tlet evicted = null;\n\t\tlet item = this.items[key];\n\n\t\tif (item !== undefined && !this.#isExpired(item)) {\n\t\t\titem.value = value;\n\t\t\tif (this.resetTTL) {\n\t\t\t\titem.expiry = this.ttl > 0 ? Date.now() + this.ttl : this.ttl;\n\t\t\t}\n\t\t\tthis.moveToEnd(item);\n\t\t} else {\n\t\t\tif (item !== undefined) {\n\t\t\t\tthis.#removeItem(item);\n\t\t\t}\n\n\t\t\tif (this.max > 0 && this.size === this.max) {\n\t\t\t\tconst evictedItem = this.#evictItem();\n\t\t\t\tevicted = {\n\t\t\t\t\tkey: evictedItem.key,\n\t\t\t\t\tvalue: evictedItem.value,\n\t\t\t\t\texpiry: evictedItem.expiry,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\titem = this.items[key] = {\n\t\t\t\texpiry: this.ttl > 0 ? Date.now() + this.ttl : this.ttl,\n\t\t\t\tkey: key,\n\t\t\t\tprev: this.last,\n\t\t\t\tnext: null,\n\t\t\t\tvalue,\n\t\t\t};\n\n\t\t\tif (++this.size === 1) {\n\t\t\t\tthis.first = item;\n\t\t\t} else {\n\t\t\t\tthis.last.next = item;\n\t\t\t}\n\n\t\t\tthis.last = item;\n\t\t}\n\n\t\tthis.#stats.sets++;\n\t\treturn evicted;\n\t}\n\n\t/**\n\t * Sets a value in the cache. Updates the item's position to most recently used.\n\t *\n\t * @param {string} key - The key to set.\n\t * @param {*} value - The value to store.\n\t * @returns {LRU} The LRU instance for method chaining.\n\t */\n\tset(key, value) {\n\t\tlet item = this.items[key];\n\n\t\tif (item !== undefined && !this.#isExpired(item)) {\n\t\t\titem.value = value;\n\n\t\t\tif (this.resetTTL) {\n\t\t\t\titem.expiry = this.ttl > 0 ? Date.now() + this.ttl : this.ttl;\n\t\t\t}\n\n\t\t\tthis.moveToEnd(item);\n\t\t} else {\n\t\t\tif (item !== undefined) {\n\t\t\t\tthis.#removeItem(item);\n\t\t\t}\n\n\t\t\tif (this.max > 0 && this.size === this.max) {\n\t\t\t\tthis.evict();\n\t\t\t}\n\n\t\t\titem = this.items[key] = {\n\t\t\t\texpiry: this.ttl > 0 ? Date.now() + this.ttl : this.ttl,\n\t\t\t\tkey: key,\n\t\t\t\tprev: this.last,\n\t\t\t\tnext: null,\n\t\t\t\tvalue,\n\t\t\t};\n\n\t\t\tif (++this.size === 1) {\n\t\t\t\tthis.first = item;\n\t\t\t} else {\n\t\t\t\tthis.last.next = item;\n\t\t\t}\n\n\t\t\tthis.last = item;\n\t\t}\n\n\t\tthis.#stats.sets++;\n\n\t\treturn this;\n\t}\n\n\t/**\n\t * Returns an array of all values in the cache for the specified keys.\n\t * When no keys provided, returns all values in LRU order.\n\t * When keys provided, order matches the input array.\n\t *\n\t * @param {string[]} [keys] - Array of keys to get values for. Defaults to all keys.\n\t * @returns {Array<*>} Array of values corresponding to the keys.\n\t */\n\tvalues(keys) {\n\t\tif (keys === undefined) {\n\t\t\tconst result = [];\n\t\t\tfor (let x = this.first; x !== null; x = x.next) {\n\t\t\t\tif (!this.#isExpired(x)) {\n\t\t\t\t\tresult.push(x.value);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn result;\n\t\t}\n\n\t\tif (!Array.isArray(keys)) {\n\t\t\tthrow new TypeError(\"keys must be an array\");\n\t\t}\n\n\t\tconst result = Array.from({ length: keys.length });\n\t\tfor (let i = 0; i < keys.length; i++) {\n\t\t\tconst item = this.items[keys[i]];\n\t\t\tresult[i] = item !== undefined && !this.#isExpired(item) ? item.value : undefined;\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t/**\n\t * Iterate over cache items in LRU order (least to most recent).\n\t * Note: This method directly accesses items from the linked list without calling\n\t * get() or peek(), so it does not update LRU order. Expired items are skipped.\n\t *\n\t * @param {function(*, any, LRU): void} callback - Function to call for each item. Signature: callback(value, key, cache)\n\t * @param {Object} [thisArg] - Value to use as `this` when executing callback.\n\t * @returns {LRU} The LRU instance for method chaining.\n\t */\n\tforEach(callback, thisArg) {\n\t\tfor (let x = this.first; x !== null; ) {\n\t\t\tconst next = x.next;\n\t\t\tif (!this.#isExpired(x)) {\n\t\t\t\tcallback.call(thisArg, x.value, x.key, this);\n\t\t\t}\n\t\t\tx = next;\n\t\t}\n\n\t\treturn this;\n\t}\n\n\t/**\n\t * Batch retrieve multiple items.\n\t *\n\t * @param {string[]} keys - Array of keys to retrieve.\n\t * @returns {Object} Object mapping keys to values (undefined for missing/expired keys).\n\t */\n\tgetMany(keys) {\n\t\tif (!Array.isArray(keys)) {\n\t\t\tthrow new TypeError(\"keys must be an array\");\n\t\t}\n\n\t\tconst result = Object.create(null);\n\t\tfor (let i = 0; i < keys.length; i++) {\n\t\t\tconst key = keys[i];\n\t\t\tresult[key] = this.get(key);\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t/**\n\t * Batch existence check - returns true if ALL keys exist.\n\t *\n\t * @param {string[]} keys - Array of keys to check.\n\t * @returns {boolean} True if all keys exist and are not expired.\n\t */\n\thasAll(keys) {\n\t\tif (!Array.isArray(keys)) {\n\t\t\tthrow new TypeError(\"keys must be an array\");\n\t\t}\n\n\t\tfor (let i = 0; i < keys.length; i++) {\n\t\t\tif (!this.has(keys[i])) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Batch existence check - returns true if ANY key exists.\n\t *\n\t * @param {string[]} keys - Array of keys to check.\n\t * @returns {boolean} True if any key exists and is not expired.\n\t */\n\thasAny(keys) {\n\t\tif (!Array.isArray(keys)) {\n\t\t\tthrow new TypeError(\"keys must be an array\");\n\t\t}\n\n\t\tfor (let i = 0; i < keys.length; i++) {\n\t\t\tif (this.has(keys[i])) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t}\n\n\t/**\n\t * Remove expired items without affecting LRU order.\n\t * Unlike get(), this does not move items to the end.\n\t *\n\t * @param {boolean} [fireOnEvict=false] - When true, invokes the onEvict callback for each removed item.\n\t * @returns {number} Number of expired items removed.\n\t */\n\tcleanup(fireOnEvict = false) {\n\t\tif (this.ttl === 0 || this.size === 0) {\n\t\t\treturn 0;\n\t\t}\n\n\t\tlet removed = 0;\n\n\t\tfor (let x = this.first; x !== null; ) {\n\t\t\tconst next = x.next;\n\t\t\tif (this.#isExpired(x)) {\n\t\t\t\tconst key = x.key;\n\t\t\t\tif (this.items[key] !== undefined) {\n\t\t\t\t\tdelete this.items[key];\n\t\t\t\t\tthis.size--;\n\t\t\t\t\tremoved++;\n\t\t\t\t\tthis.#unlink(x);\n\t\t\t\t\tx.prev = null;\n\t\t\t\t\tx.next = null;\n\t\t\t\t\tif (fireOnEvict && this.#onEvict !== null) {\n\t\t\t\t\t\tthis.#onEvict({\n\t\t\t\t\t\t\tkey: x.key,\n\t\t\t\t\t\t\tvalue: x.value,\n\t\t\t\t\t\t\texpiry: x.expiry,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tx = next;\n\t\t}\n\n\t\tif (removed > 0) {\n\t\t\tthis.#rebuildList();\n\t\t}\n\n\t\treturn removed;\n\t}\n\n\t/**\n\t * Serialize cache to JSON-compatible format.\n\t *\n\t * @returns {Array<{key: any, value: *, expiry: number}>} Array of cache items.\n\t */\n\ttoJSON() {\n\t\tconst result = [];\n\t\tfor (let x = this.first; x !== null; x = x.next) {\n\t\t\tif (!this.#isExpired(x)) {\n\t\t\t\tresult.push({\n\t\t\t\t\tkey: x.key,\n\t\t\t\t\tvalue: x.value,\n\t\t\t\t\texpiry: x.expiry,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t/**\n\t * Get cache statistics.\n\t *\n\t * @returns {Object} Statistics object with hits, misses, sets, deletes, evictions counts.\n\t */\n\tstats() {\n\t\treturn { ...this.#stats };\n\t}\n\n\t/**\n\t * Register callback for evicted items.\n\t *\n\t * @param {function(Object): void} callback - Function called when item is evicted. Receives {key, value, expiry}.\n\t * @returns {LRU} The LRU instance for method chaining.\n\t */\n\tonEvict(callback) {\n\t\tif (typeof callback !== \"function\") {\n\t\t\tthrow new TypeError(\"onEvict callback must be a function\");\n\t\t}\n\n\t\tthis.#onEvict = callback;\n\n\t\treturn this;\n\t}\n\n\t/**\n\t * Get counts of items by TTL status.\n\t *\n\t * @returns {Object} Object with valid, expired, and noTTL counts.\n\t */\n\tsizeByTTL() {\n\t\tif (this.ttl === 0) {\n\t\t\treturn { valid: this.size, expired: 0, noTTL: this.size };\n\t\t}\n\n\t\tconst now = Date.now();\n\t\tlet valid = 0;\n\t\tlet expired = 0;\n\n\t\tfor (let x = this.first; x !== null; x = x.next) {\n\t\t\tif (x.expiry > now) {\n\t\t\t\tvalid++;\n\t\t\t} else {\n\t\t\t\texpired++;\n\t\t\t}\n\t\t}\n\n\t\treturn { valid, expired, noTTL: 0 };\n\t}\n\n\t/**\n\t * Get keys filtered by TTL status.\n\t *\n\t * @returns {Object} Object with valid, expired, and noTTL arrays of keys.\n\t */\n\tkeysByTTL() {\n\t\tif (this.ttl === 0) {\n\t\t\treturn { valid: this.keys(), expired: [], noTTL: this.keys() };\n\t\t}\n\n\t\tconst now = Date.now();\n\t\tconst valid = [];\n\t\tconst expired = [];\n\n\t\tfor (let x = this.first; x !== null; x = x.next) {\n\t\t\tif (x.expiry > now) {\n\t\t\t\tvalid.push(x.key);\n\t\t\t} else {\n\t\t\t\texpired.push(x.key);\n\t\t\t}\n\t\t}\n\n\t\treturn { valid, expired, noTTL: [] };\n\t}\n\n\t/**\n\t * Get values filtered by TTL status.\n\t *\n\t * @returns {Object} Object with valid, expired, and noTTL arrays of values.\n\t */\n\tvaluesByTTL() {\n\t\tif (this.ttl === 0) {\n\t\t\treturn { valid: this.values(), expired: [], noTTL: this.values() };\n\t\t}\n\n\t\tconst now = Date.now();\n\t\tconst valid = [];\n\t\tconst expired = [];\n\n\t\tfor (let x = this.first; x !== null; x = x.next) {\n\t\t\tif (x.expiry > now) {\n\t\t\t\tvalid.push(x.value);\n\t\t\t} else {\n\t\t\t\texpired.push(x.value);\n\t\t\t}\n\t\t}\n\n\t\treturn { valid, expired, noTTL: [] };\n\t}\n\n\t/**\n\t * Rebuild the doubly-linked list after cleanup by deleting expired items.\n\t * This removes nodes that were deleted during cleanup.\n\t *\n\t * @private\n\t */\n\t#rebuildList() {\n\t\tif (this.size === 0) {\n\t\t\tthis.first = null;\n\t\t\tthis.last = null;\n\t\t\treturn;\n\t\t}\n\n\t\tconst keys = this.keys();\n\t\tthis.first = null;\n\t\tthis.last = null;\n\n\t\tfor (let i = 0; i < keys.length; i++) {\n\t\t\tconst item = this.items[keys[i]];\n\t\t\tif (item !== null && item !== undefined) {\n\t\t\t\tif (this.first === null) {\n\t\t\t\t\tthis.first = item;\n\t\t\t\t\titem.prev = null;\n\t\t\t\t} else {\n\t\t\t\t\titem.prev = this.last;\n\t\t\t\t\tthis.last.next = item;\n\t\t\t\t}\n\t\t\t\titem.next = null;\n\t\t\t\tthis.last = item;\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Factory function to create a new LRU cache instance with parameter validation.\n *\n * @function lru\n * @param {number} [max=1000] - Maximum number of items to store. Must be >= 0. Use 0 for unlimited size.\n * @param {number} [ttl=0] - Time to live in milliseconds. Must be >= 0. Use 0 for no expiration.\n * @param {boolean} [resetTTL=false] - Whether to reset TTL when updating existing items via set().\n * @returns {LRU} A new LRU cache instance.\n * @throws {TypeError} When parameters are invalid (negative numbers or wrong types).\n */\nexport function lru(max = 1000, ttl = 0, resetTTL = false) {\n\treturn new LRU(max, ttl, resetTTL);\n}\n"],"names":["LRU","stats","onEvict","constructor","max","ttl","resetTTL","Number","isInteger","TypeError","this","first","items","Object","create","last","size","hits","misses","sets","deletes","evictions","clear","x","next","prev","key","item","undefined","removeItem","entries","keys","result","isExpired","push","value","Array","isArray","from","length","i","evict","evictItem","expiry","expiresAt","Date","now","peek","get","moveToEnd","has","unlink","setWithEvicted","evicted","evictedItem","set","values","forEach","callback","thisArg","call","getMany","hasAll","hasAny","cleanup","fireOnEvict","removed","rebuildList","toJSON","sizeByTTL","valid","expired","noTTL","keysByTTL","valuesByTTL","lru"],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"tiny-lru.min.js","sources":["../src/lru.js"],"sourcesContent":["/**\n * A high-performance Least Recently Used (LRU) cache implementation with optional TTL support.\n * Items are automatically evicted when the cache reaches its maximum size,\n * removing the least recently used items first. All core operations (get, set, delete) are O(1).\n *\n * @class LRU\n */\nexport class LRU {\n\t#stats;\n\t#onEvict;\n\n\t/**\n\t * Creates a new LRU cache instance.\n\t *\n\t * @constructor\n\t * @param {number} [max=0] - Maximum number of items to store. 0 means unlimited.\n\t * @param {number} [ttl=0] - Time to live in milliseconds. 0 means no expiration.\n\t * @param {boolean} [resetTTL=false] - Whether to reset TTL when updating existing items via set().\n\t * @throws {TypeError} When parameters are invalid (negative numbers or wrong types).\n\t */\n\tconstructor(max = 0, ttl = 0, resetTTL = false) {\n\t\tif (!Number.isInteger(max) || max < 0) {\n\t\t\tthrow new TypeError(\"Invalid max value\");\n\t\t}\n\n\t\tif (!Number.isInteger(ttl) || ttl < 0) {\n\t\t\tthrow new TypeError(\"Invalid ttl value\");\n\t\t}\n\n\t\tif (typeof resetTTL !== \"boolean\") {\n\t\t\tthrow new TypeError(\"Invalid resetTTL value\");\n\t\t}\n\n\t\tthis.first = null;\n\t\tthis.items = Object.create(null);\n\t\tthis.last = null;\n\t\tthis.max = max;\n\t\tthis.resetTTL = resetTTL;\n\t\tthis.size = 0;\n\t\tthis.ttl = ttl;\n\t\tthis.#stats = { hits: 0, misses: 0, sets: 0, deletes: 0, evictions: 0 };\n\t\tthis.#onEvict = null;\n\t}\n\n\t/**\n\t * Removes all items from the cache.\n\t *\n\t * @returns {LRU} The LRU instance for method chaining.\n\t */\n\tclear() {\n\t\tfor (let x = this.first; x !== null;) {\n\t\t\tconst next = x.next;\n\t\t\tx.prev = null;\n\t\t\tx.next = null;\n\t\t\tx = next;\n\t\t}\n\n\t\tthis.first = null;\n\t\tthis.items = Object.create(null);\n\t\tthis.last = null;\n\t\tthis.size = 0;\n\t\tthis.#stats.hits = 0;\n\t\tthis.#stats.misses = 0;\n\t\tthis.#stats.sets = 0;\n\t\tthis.#stats.deletes = 0;\n\t\tthis.#stats.evictions = 0;\n\n\t\treturn this;\n\t}\n\n\t/**\n\t * Removes an item from the cache by key.\n\t *\n\t * @param {string} key - The key of the item to delete.\n\t * @returns {LRU} The LRU instance for method chaining.\n\t */\n\tdelete(key) {\n\t\tconst item = this.items[key];\n\n\t\tif (item !== undefined) {\n\t\t\tthis.#removeItem(item);\n\t\t\tthis.#stats.deletes++;\n\t\t}\n\n\t\treturn this;\n\t}\n\n\t/**\n\t * Returns an array of [key, value] pairs for the specified keys.\n\t * When no keys provided, returns all entries in LRU order.\n\t * When keys provided, order matches the input array.\n\t *\n\t * @param {string[]} [keys=this.keys()] - Array of keys to get entries for. Defaults to all keys.\n\t * @returns {Array>} Array of [key, value] pairs.\n\t */\n\tentries(keys) {\n\t\tif (keys === undefined) {\n\t\t\tconst result = [];\n\t\t\tfor (let x = this.first; x !== null; x = x.next) {\n\t\t\t\tif (!this.#isExpired(x)) {\n\t\t\t\t\tresult.push([x.key, x.value]);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn result;\n\t\t}\n\n\t\tif (!Array.isArray(keys)) {\n\t\t\tthrow new TypeError(\"keys must be an array\");\n\t\t}\n\n\t\tconst result = Array.from({ length: keys.length });\n\t\tfor (let i = 0; i < keys.length; i++) {\n\t\t\tconst key = keys[i];\n\t\t\tconst item = this.items[key];\n\t\t\tresult[i] = [key, item !== undefined && !this.#isExpired(item) ? item.value : undefined];\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t/**\n\t * Removes the least recently used item from the cache.\n\t *\n\t * @returns {LRU} The LRU instance for method chaining.\n\t */\n\tevict() {\n\t\tif (this.size === 0) {\n\t\t\treturn this;\n\t\t}\n\n\t\tconst item = this.#evictItem();\n\n\t\tif (this.#onEvict !== null) {\n\t\t\tthis.#onEvict({\n\t\t\t\tkey: item.key,\n\t\t\t\tvalue: item.value,\n\t\t\t\texpiry: item.expiry,\n\t\t\t});\n\t\t}\n\n\t\treturn this;\n\t}\n\n\t/**\n\t * Returns the expiration timestamp for a given key.\n\t *\n\t * @param {string} key - The key to check expiration for.\n\t * @returns {number|undefined} The expiration timestamp in milliseconds, or undefined if key doesn't exist.\n\t */\n\texpiresAt(key) {\n\t\tconst item = this.items[key];\n\t\treturn item !== undefined ? item.expiry : undefined;\n\t}\n\n\t/**\n\t * Checks if an item has expired.\n\t *\n\t * @param {Object} item - The cache item to check.\n\t * @returns {boolean} True if the item has expired, false otherwise.\n\t * @private\n\t */\n\t#isExpired(item) {\n\t\tif (this.ttl === 0) {\n\t\t\treturn false;\n\t\t}\n\n\t\treturn item.expiry <= Date.now();\n\t}\n\n\t/**\n\t * Retrieves a value from the cache by key without updating LRU order.\n\t * Note: Does not perform TTL checks or remove expired items.\n\t *\n\t * @param {string} key - The key to retrieve.\n\t * @returns {*} The value associated with the key, or undefined if not found.\n\t */\n\tpeek(key) {\n\t\tconst item = this.items[key];\n\t\treturn item !== undefined ? item.value : undefined;\n\t}\n\n\t/**\n\t * Retrieves a value from the cache by key. Updates the item's position to most recently used.\n\t *\n\t * @param {string} key - The key to retrieve.\n\t * @returns {*} The value associated with the key, or undefined if not found or expired.\n\t */\n\tget(key) {\n\t\tconst item = this.items[key];\n\n\t\tif (item !== undefined) {\n\t\t\tif (!this.#isExpired(item)) {\n\t\t\t\tthis.moveToEnd(item);\n\t\t\t\tthis.#stats.hits++;\n\t\t\t\treturn item.value;\n\t\t\t}\n\n\t\t\tthis.#removeItem(item);\n\t\t\tthis.#stats.misses++;\n\t\t\treturn undefined;\n\t\t}\n\n\t\tthis.#stats.misses++;\n\t\treturn undefined;\n\t}\n\n\t/**\n\t * Checks if a key exists in the cache.\n\t * Expired items are removed before returning false.\n\t *\n\t * @param {string} key - The key to check for.\n\t * @returns {boolean} True if the key exists and is not expired, false otherwise.\n\t */\n\thas(key) {\n\t\tconst item = this.items[key];\n\n\t\tif (item !== undefined && this.#isExpired(item)) {\n\t\t\tthis.#removeItem(item);\n\t\t\treturn false;\n\t\t}\n\n\t\treturn item !== undefined;\n\t}\n\n\t/**\n\t * Unlinks an item from the doubly-linked list.\n\t * Updates first/last pointers if needed.\n\t * Does NOT clear the item's prev/next pointers or delete from items map.\n\t *\n\t * @private\n\t */\n\t#unlink(item) {\n\t\tif (item.prev !== null) {\n\t\t\titem.prev.next = item.next;\n\t\t}\n\n\t\tif (item.next !== null) {\n\t\t\titem.next.prev = item.prev;\n\t\t}\n\n\t\tif (this.first === item) {\n\t\t\tthis.first = item.next;\n\t\t}\n\n\t\tif (this.last === item) {\n\t\t\tthis.last = item.prev;\n\t\t}\n\t}\n\n\t/**\n\t * Removes an item from the cache without incrementing the deletes stat.\n\t * Used internally by get()/has() when removing expired items.\n\t *\n\t * @param {Object} item - The cache item to remove.\n\t * @private\n\t */\n\t#removeItem(item) {\n\t\tdelete this.items[item.key];\n\t\tthis.size--;\n\t\tthis.#unlink(item);\n\t\titem.prev = null;\n\t\titem.next = null;\n\t}\n\n\t/**\n\t * Evicts the least recently used item from the cache without firing onEvict.\n\t * Used internally by setWithEvicted() to avoid double-notification.\n\t *\n\t * @returns {Object} The evicted item.\n\t * @private\n\t */\n\t#evictItem() {\n\t\tconst item = this.first;\n\n\t\tdelete this.items[item.key];\n\t\tthis.#stats.evictions++;\n\n\t\tif (--this.size === 0) {\n\t\t\tthis.first = null;\n\t\t\tthis.last = null;\n\t\t} else {\n\t\t\tthis.#unlink(item);\n\t\t}\n\n\t\titem.prev = null;\n\t\titem.next = null;\n\n\t\treturn item;\n\t}\n\n\t/**\n\t * Efficiently moves an item to the end of the LRU list (most recently used position).\n\t * This is an internal optimization method that avoids the overhead of the full set() operation\n\t * when only LRU position needs to be updated.\n\t *\n\t * @param {Object} item - The cache item with prev/next pointers to reposition.\n\t * @private\n\t */\n\tmoveToEnd(item) {\n\t\tif (this.last === item) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.#unlink(item);\n\n\t\titem.prev = this.last;\n\t\titem.next = null;\n\t\tthis.last.next = item;\n\t\tthis.last = item;\n\t}\n\n\t/**\n\t * Returns an array of all keys in the cache, ordered from least to most recently used.\n\t * Expired items are skipped, consistent with entries(), values(), and toJSON().\n\t *\n\t * @returns {string[]} Array of keys in LRU order.\n\t */\n\tkeys() {\n\t\tconst result = [];\n\t\tfor (let x = this.first; x !== null; x = x.next) {\n\t\t\tif (!this.#isExpired(x)) {\n\t\t\t\tresult.push(x.key);\n\t\t\t}\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t/**\n\t * Sets a value in the cache and returns any evicted item.\n\t * Eviction is silent — onEvict is not fired for the returned item.\n\t *\n\t * @param {string} key - The key to set.\n\t * @param {*} value - The value to store.\n\t * @returns {Object|null} The evicted item (if any) with shape {key, value, expiry}, or null.\n\t */\n\tsetWithEvicted(key, value) {\n\t\tlet evicted = null;\n\t\tlet item = this.items[key];\n\n\t\tif (item !== undefined && !this.#isExpired(item)) {\n\t\t\titem.value = value;\n\t\t\tif (this.resetTTL) {\n\t\t\t\titem.expiry = this.ttl > 0 ? Date.now() + this.ttl : this.ttl;\n\t\t\t}\n\t\t\tthis.moveToEnd(item);\n\t\t} else {\n\t\t\tif (item !== undefined) {\n\t\t\t\tthis.#removeItem(item);\n\t\t\t}\n\n\t\t\tif (this.max > 0 && this.size === this.max) {\n\t\t\t\tconst evictedItem = this.#evictItem();\n\t\t\t\tevicted = {\n\t\t\t\t\tkey: evictedItem.key,\n\t\t\t\t\tvalue: evictedItem.value,\n\t\t\t\t\texpiry: evictedItem.expiry,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\titem = this.items[key] = {\n\t\t\t\texpiry: this.ttl > 0 ? Date.now() + this.ttl : this.ttl,\n\t\t\t\tkey: key,\n\t\t\t\tprev: this.last,\n\t\t\t\tnext: null,\n\t\t\t\tvalue,\n\t\t\t};\n\n\t\t\tif (++this.size === 1) {\n\t\t\t\tthis.first = item;\n\t\t\t} else {\n\t\t\t\tthis.last.next = item;\n\t\t\t}\n\n\t\t\tthis.last = item;\n\t\t}\n\n\t\tthis.#stats.sets++;\n\t\treturn evicted;\n\t}\n\n\t/**\n\t * Sets a value in the cache. Updates the item's position to most recently used.\n\t *\n\t * @param {string} key - The key to set.\n\t * @param {*} value - The value to store.\n\t * @returns {LRU} The LRU instance for method chaining.\n\t */\n\tset(key, value) {\n\t\tlet item = this.items[key];\n\n\t\tif (item !== undefined && !this.#isExpired(item)) {\n\t\t\titem.value = value;\n\n\t\t\tif (this.resetTTL) {\n\t\t\t\titem.expiry = this.ttl > 0 ? Date.now() + this.ttl : this.ttl;\n\t\t\t}\n\n\t\t\tthis.moveToEnd(item);\n\t\t} else {\n\t\t\tif (item !== undefined) {\n\t\t\t\tthis.#removeItem(item);\n\t\t\t}\n\n\t\t\tif (this.max > 0 && this.size === this.max) {\n\t\t\t\tthis.evict();\n\t\t\t}\n\n\t\t\titem = this.items[key] = {\n\t\t\t\texpiry: this.ttl > 0 ? Date.now() + this.ttl : this.ttl,\n\t\t\t\tkey: key,\n\t\t\t\tprev: this.last,\n\t\t\t\tnext: null,\n\t\t\t\tvalue,\n\t\t\t};\n\n\t\t\tif (++this.size === 1) {\n\t\t\t\tthis.first = item;\n\t\t\t} else {\n\t\t\t\tthis.last.next = item;\n\t\t\t}\n\n\t\t\tthis.last = item;\n\t\t}\n\n\t\tthis.#stats.sets++;\n\n\t\treturn this;\n\t}\n\n\t/**\n\t * Returns an array of all values in the cache for the specified keys.\n\t * When no keys provided, returns all values in LRU order.\n\t * When keys provided, order matches the input array.\n\t *\n\t * @param {string[]} [keys] - Array of keys to get values for. Defaults to all keys.\n\t * @returns {Array<*>} Array of values corresponding to the keys.\n\t */\n\tvalues(keys) {\n\t\tif (keys === undefined) {\n\t\t\tconst result = [];\n\t\t\tfor (let x = this.first; x !== null; x = x.next) {\n\t\t\t\tif (!this.#isExpired(x)) {\n\t\t\t\t\tresult.push(x.value);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn result;\n\t\t}\n\n\t\tif (!Array.isArray(keys)) {\n\t\t\tthrow new TypeError(\"keys must be an array\");\n\t\t}\n\n\t\tconst result = Array.from({ length: keys.length });\n\t\tfor (let i = 0; i < keys.length; i++) {\n\t\t\tconst item = this.items[keys[i]];\n\t\t\tresult[i] = item !== undefined && !this.#isExpired(item) ? item.value : undefined;\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t/**\n\t * Iterate over cache items in LRU order (least to most recent).\n\t * Note: This method directly accesses items from the linked list without calling\n\t * get() or peek(), so it does not update LRU order. Expired items are skipped.\n\t *\n\t * @param {function(*, any, LRU): void} callback - Function to call for each item. Signature: callback(value, key, cache)\n\t * @param {Object} [thisArg] - Value to use as `this` when executing callback.\n\t * @returns {LRU} The LRU instance for method chaining.\n\t */\n\tforEach(callback, thisArg) {\n\t\tfor (let x = this.first; x !== null;) {\n\t\t\tconst next = x.next;\n\t\t\tif (!this.#isExpired(x)) {\n\t\t\t\tcallback.call(thisArg, x.value, x.key, this);\n\t\t\t}\n\t\t\tx = next;\n\t\t}\n\n\t\treturn this;\n\t}\n\n\t/**\n\t * Batch retrieve multiple items.\n\t *\n\t * @param {string[]} keys - Array of keys to retrieve.\n\t * @returns {Object} Object mapping keys to values (undefined for missing/expired keys).\n\t */\n\tgetMany(keys) {\n\t\tif (!Array.isArray(keys)) {\n\t\t\tthrow new TypeError(\"keys must be an array\");\n\t\t}\n\n\t\tconst result = Object.create(null);\n\t\tfor (let i = 0; i < keys.length; i++) {\n\t\t\tconst key = keys[i];\n\t\t\tresult[key] = this.get(key);\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t/**\n\t * Batch existence check - returns true if ALL keys exist.\n\t *\n\t * @param {string[]} keys - Array of keys to check.\n\t * @returns {boolean} True if all keys exist and are not expired.\n\t */\n\thasAll(keys) {\n\t\tif (!Array.isArray(keys)) {\n\t\t\tthrow new TypeError(\"keys must be an array\");\n\t\t}\n\n\t\tfor (let i = 0; i < keys.length; i++) {\n\t\t\tif (!this.has(keys[i])) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Batch existence check - returns true if ANY key exists.\n\t *\n\t * @param {string[]} keys - Array of keys to check.\n\t * @returns {boolean} True if any key exists and is not expired.\n\t */\n\thasAny(keys) {\n\t\tif (!Array.isArray(keys)) {\n\t\t\tthrow new TypeError(\"keys must be an array\");\n\t\t}\n\n\t\tfor (let i = 0; i < keys.length; i++) {\n\t\t\tif (this.has(keys[i])) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t}\n\n\t/**\n\t * Remove expired items without affecting LRU order.\n\t * Unlike get(), this does not move items to the end.\n\t *\n\t * @param {boolean} [fireOnEvict=false] - When true, invokes the onEvict callback for each removed item.\n\t * @returns {number} Number of expired items removed.\n\t */\n\tcleanup(fireOnEvict = false) {\n\t\tif (this.ttl === 0 || this.size === 0) {\n\t\t\treturn 0;\n\t\t}\n\n\t\tlet removed = 0;\n\n\t\tfor (let x = this.first; x !== null;) {\n\t\t\tconst next = x.next;\n\t\t\tif (this.#isExpired(x)) {\n\t\t\t\tconst key = x.key;\n\t\t\t\tif (this.items[key] !== undefined) {\n\t\t\t\t\tdelete this.items[key];\n\t\t\t\t\tthis.size--;\n\t\t\t\t\tremoved++;\n\t\t\t\t\tthis.#unlink(x);\n\t\t\t\t\tx.prev = null;\n\t\t\t\t\tx.next = null;\n\t\t\t\t\tif (fireOnEvict && this.#onEvict !== null) {\n\t\t\t\t\t\tthis.#onEvict({\n\t\t\t\t\t\t\tkey: x.key,\n\t\t\t\t\t\t\tvalue: x.value,\n\t\t\t\t\t\t\texpiry: x.expiry,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tx = next;\n\t\t}\n\n\t\treturn removed;\n\t}\n\n\t/**\n\t * Serialize cache to JSON-compatible format.\n\t *\n\t * @returns {Array<{key: any, value: *, expiry: number}>} Array of cache items.\n\t */\n\ttoJSON() {\n\t\tconst result = [];\n\t\tfor (let x = this.first; x !== null; x = x.next) {\n\t\t\tif (!this.#isExpired(x)) {\n\t\t\t\tresult.push({\n\t\t\t\t\tkey: x.key,\n\t\t\t\t\tvalue: x.value,\n\t\t\t\t\texpiry: x.expiry,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t/**\n\t * Get cache statistics.\n\t *\n\t * @returns {Object} Statistics object with hits, misses, sets, deletes, evictions counts.\n\t */\n\tstats() {\n\t\treturn { ...this.#stats };\n\t}\n\n\t/**\n\t * Register callback for evicted items.\n\t *\n\t * @param {function(Object): void} callback - Function called when item is evicted. Receives {key, value, expiry}.\n\t * @returns {LRU} The LRU instance for method chaining.\n\t */\n\tonEvict(callback) {\n\t\tif (typeof callback !== \"function\") {\n\t\t\tthrow new TypeError(\"onEvict callback must be a function\");\n\t\t}\n\n\t\tthis.#onEvict = callback;\n\n\t\treturn this;\n\t}\n\n\t/**\n\t * Get counts of items by TTL status.\n\t *\n\t * @returns {Object} Object with valid, expired, and noTTL counts.\n\t */\n\tsizeByTTL() {\n\t\tif (this.ttl === 0) {\n\t\t\treturn { valid: this.size, expired: 0, noTTL: this.size };\n\t\t}\n\n\t\tconst now = Date.now();\n\t\tlet valid = 0;\n\t\tlet expired = 0;\n\n\t\tfor (let x = this.first; x !== null; x = x.next) {\n\t\t\tif (x.expiry > now) {\n\t\t\t\tvalid++;\n\t\t\t} else {\n\t\t\t\texpired++;\n\t\t\t}\n\t\t}\n\n\t\treturn { valid, expired, noTTL: 0 };\n\t}\n\n\t/**\n\t * Get keys filtered by TTL status.\n\t *\n\t * @returns {Object} Object with valid, expired, and noTTL arrays of keys.\n\t */\n\tkeysByTTL() {\n\t\tif (this.ttl === 0) {\n\t\t\treturn { valid: this.keys(), expired: [], noTTL: this.keys() };\n\t\t}\n\n\t\tconst now = Date.now();\n\t\tconst valid = [];\n\t\tconst expired = [];\n\n\t\tfor (let x = this.first; x !== null; x = x.next) {\n\t\t\tif (x.expiry > now) {\n\t\t\t\tvalid.push(x.key);\n\t\t\t} else {\n\t\t\t\texpired.push(x.key);\n\t\t\t}\n\t\t}\n\n\t\treturn { valid, expired, noTTL: [] };\n\t}\n\n\t/**\n\t * Get values filtered by TTL status.\n\t *\n\t * @returns {Object} Object with valid, expired, and noTTL arrays of values.\n\t */\n\tvaluesByTTL() {\n\t\tif (this.ttl === 0) {\n\t\t\treturn { valid: this.values(), expired: [], noTTL: this.values() };\n\t\t}\n\n\t\tconst now = Date.now();\n\t\tconst valid = [];\n\t\tconst expired = [];\n\n\t\tfor (let x = this.first; x !== null; x = x.next) {\n\t\t\tif (x.expiry > now) {\n\t\t\t\tvalid.push(x.value);\n\t\t\t} else {\n\t\t\t\texpired.push(x.value);\n\t\t\t}\n\t\t}\n\n\t\treturn { valid, expired, noTTL: [] };\n\t}\n}\n\n/**\n * Factory function to create a new LRU cache instance with parameter validation.\n *\n * @function lru\n * @param {number} [max=1000] - Maximum number of items to store. Must be >= 0. Use 0 for unlimited size.\n * @param {number} [ttl=0] - Time to live in milliseconds. Must be >= 0. Use 0 for no expiration.\n * @param {boolean} [resetTTL=false] - Whether to reset TTL when updating existing items via set().\n * @returns {LRU} A new LRU cache instance.\n * @throws {TypeError} When parameters are invalid (negative numbers or wrong types).\n */\nexport function lru(max = 1000, ttl = 0, resetTTL = false) {\n\treturn new LRU(max, ttl, resetTTL);\n}\n"],"names":["LRU","stats","onEvict","constructor","max","ttl","resetTTL","Number","isInteger","TypeError","this","first","items","Object","create","last","size","hits","misses","sets","deletes","evictions","clear","x","next","prev","key","item","undefined","removeItem","entries","keys","result","isExpired","push","value","Array","isArray","from","length","i","evict","evictItem","expiry","expiresAt","Date","now","peek","get","moveToEnd","has","unlink","setWithEvicted","evicted","evictedItem","set","values","forEach","callback","thisArg","call","getMany","hasAll","hasAny","cleanup","fireOnEvict","removed","toJSON","sizeByTTL","valid","expired","noTTL","keysByTTL","valuesByTTL","lru"],"mappings":"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"} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index d3c5602..28d88c7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "tiny-lru", - "version": "13.1.0", + "version": "13.1.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "tiny-lru", - "version": "13.1.0", + "version": "13.1.1", "license": "BSD-3-Clause", "devDependencies": { "@rollup/plugin-terser": "^1.0.0", diff --git a/package.json b/package.json index e5717f8..96f9cef 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "tiny-lru", - "version": "13.1.0", + "version": "13.1.1", "description": "A fast, lightweight LRU (Least Recently Used) cache for JavaScript with O(1) operations and optional TTL support.", "keywords": [ "LRU",