From 535ff968cfeb4a13285a6c49df8bff223e716ed7 Mon Sep 17 00:00:00 2001 From: Jason Mulligan Date: Wed, 20 Sep 2023 21:49:35 -0400 Subject: [PATCH] Moving `has()` into the class and into the README.md (want interop with common primitives), adding `entries()` & `values()`, & adding tests Updating README.md --- .eslintrc | 3 ++- README.md | 41 ++++++++++++++++++++++++++++++++++++ dist/tiny-lru.cjs | 26 +++++++++++++++-------- dist/tiny-lru.js | 26 ++++++++++++++++------- dist/tiny-lru.min.js | 4 ++-- dist/tiny-lru.min.js.map | 2 +- dist/tiny-lru.umd.js | 26 ++++++++++++++++------- dist/tiny-lru.umd.min.js | 4 ++-- dist/tiny-lru.umd.min.js.map | 2 +- package-lock.json | 4 ++-- package.json | 2 +- src/has.js | 3 --- src/lru.js | 22 +++++++++++++------ test/lru.js | 13 ++++++++++++ 14 files changed, 134 insertions(+), 44 deletions(-) delete mode 100644 src/has.js diff --git a/.eslintrc b/.eslintrc index f818ced..2d158eb 100644 --- a/.eslintrc +++ b/.eslintrc @@ -15,7 +15,8 @@ "after": true, "before": true, "beforeEach": true, - "expect": true + "expect": true, + "Iterator": true }, "rules": { "arrow-parens": [2, "as-needed"], diff --git a/README.md b/README.md index 7ceb948..943e27c 100644 --- a/README.md +++ b/README.md @@ -44,6 +44,20 @@ Removes item from cache cache.delete("myKey"); ``` +## entries(*["key1", "key2"]*) +### Method + +Returns an `Array` cache items + + param {Array} keys (Optional) Cache item keys to get + return {Object} LRU instance + +**Example** + +```javascript +cache.entries(['myKey1', 'myKey2']); +``` + ## evict ### Method @@ -98,6 +112,19 @@ Gets cached item and moves it to the front const item = cache.get("myKey"); ``` +## has +### Method + +Returns a `Boolean` indicating if `key` is in cache + + return {Object} LRU instance + +**Example** + +```javascript +cache.has('myKey'); +``` + ## keys ### Method @@ -191,6 +218,20 @@ const cache = lru(); cache.ttl = 3e4; ``` +## values(*["key1", "key2"]*) +### Method + +Returns an `Array` cache items + + param {Array} keys (Optional) Cache item keys to get + return {Array} Cache items + +**Example** + +```javascript +cache.values(['abc', 'def']); +``` + ## License Copyright (c) 2023 Jason Mulligan Licensed under the BSD-3 license. diff --git a/dist/tiny-lru.cjs b/dist/tiny-lru.cjs index c7c7643..2d5d41a 100644 --- a/dist/tiny-lru.cjs +++ b/dist/tiny-lru.cjs @@ -3,14 +3,10 @@ * * @copyright 2023 Jason Mulligan * @license BSD-3-Clause - * @version 11.0.1 + * @version 11.1.0 */ 'use strict'; -function has (items, key) { - return key in items; -} - class LRU { constructor (max = 0, ttl = 0, resetTtl = false) { this.first = null; @@ -32,7 +28,7 @@ class LRU { } delete (key) { - if (has(this.items, key)) { + if (this.has(key)) { const item = this.items[key]; delete this.items[key]; @@ -58,6 +54,10 @@ class LRU { return this; } + entries (keys = this.keys()) { + return keys.map(key => [key, this.get(key)]); + } + evict (bypass = false) { if (bypass || this.size > 0) { const item = this.first; @@ -79,7 +79,7 @@ class LRU { expiresAt (key) { let result; - if (has(this.items, key)) { + if (this.has(key)) { result = this.items[key].expiry; } @@ -89,7 +89,7 @@ class LRU { get (key) { let result; - if (has(this.items, key)) { + if (this.has(key)) { const item = this.items[key]; if (this.ttl > 0 && item.expiry <= Date.now()) { @@ -103,6 +103,10 @@ class LRU { return result; } + has (key) { + return key in this.items; + } + keys () { return Object.keys(this.items); } @@ -110,7 +114,7 @@ class LRU { set (key, value, bypass = false, resetTtl = this.resetTtl) { let item; - if (bypass || has(this.items, key)) { + if (bypass || this.has(key)) { item = this.items[key]; item.value = value; @@ -163,6 +167,10 @@ class LRU { return this; } + + values (keys = this.keys()) { + return keys.map(key => this.get(key)); + } } function lru (max = 1000, ttl = 0, resetTtl = false) { diff --git a/dist/tiny-lru.js b/dist/tiny-lru.js index 3bf0398..0e3c5a5 100644 --- a/dist/tiny-lru.js +++ b/dist/tiny-lru.js @@ -3,11 +3,9 @@ * * @copyright 2023 Jason Mulligan * @license BSD-3-Clause - * @version 11.0.1 + * @version 11.1.0 */ -function has (items, key) { - return key in items; -}class LRU { +class LRU { constructor (max = 0, ttl = 0, resetTtl = false) { this.first = null; this.items = Object.create(null); @@ -28,7 +26,7 @@ function has (items, key) { } delete (key) { - if (has(this.items, key)) { + if (this.has(key)) { const item = this.items[key]; delete this.items[key]; @@ -54,6 +52,10 @@ function has (items, key) { return this; } + entries (keys = this.keys()) { + return keys.map(key => [key, this.get(key)]); + } + evict (bypass = false) { if (bypass || this.size > 0) { const item = this.first; @@ -75,7 +77,7 @@ function has (items, key) { expiresAt (key) { let result; - if (has(this.items, key)) { + if (this.has(key)) { result = this.items[key].expiry; } @@ -85,7 +87,7 @@ function has (items, key) { get (key) { let result; - if (has(this.items, key)) { + if (this.has(key)) { const item = this.items[key]; if (this.ttl > 0 && item.expiry <= Date.now()) { @@ -99,6 +101,10 @@ function has (items, key) { return result; } + has (key) { + return key in this.items; + } + keys () { return Object.keys(this.items); } @@ -106,7 +112,7 @@ function has (items, key) { set (key, value, bypass = false, resetTtl = this.resetTtl) { let item; - if (bypass || has(this.items, key)) { + if (bypass || this.has(key)) { item = this.items[key]; item.value = value; @@ -159,6 +165,10 @@ function has (items, key) { return this; } + + values (keys = this.keys()) { + return keys.map(key => this.get(key)); + } } function lru (max = 1000, ttl = 0, resetTtl = false) { diff --git a/dist/tiny-lru.min.js b/dist/tiny-lru.min.js index bc9db4b..7c94986 100644 --- a/dist/tiny-lru.min.js +++ b/dist/tiny-lru.min.js @@ -1,5 +1,5 @@ /*! 2023 Jason Mulligan - @version 11.0.1 + @version 11.1.0 */ -function t(t,s){return s in t}class s{constructor(t=0,s=0,e=!1){this.first=null,this.items=Object.create(null),this.last=null,this.max=t,this.resetTtl=e,this.size=0,this.ttl=s}clear(){return this.first=null,this.items=Object.create(null),this.last=null,this.size=0,this}delete(s){if(t(this.items,s)){const t=this.items[s];delete this.items[s],this.size--,null!==t.prev&&(t.prev.next=t.next),null!==t.next&&(t.next.prev=t.prev),this.first===t&&(this.first=t.next),this.last===t&&(this.last=t.prev)}return this}evict(t=!1){if(t||this.size>0){const t=this.first;delete this.items[t.key],0==--this.size?(this.first=null,this.last=null):(this.first=t.next,this.first.prev=null)}return this}expiresAt(s){let e;return t(this.items,s)&&(e=this.items[s].expiry),e}get(s){let e;if(t(this.items,s)){const t=this.items[s];this.ttl>0&&t.expiry<=Date.now()?this.delete(s):(e=t.value,this.set(s,e,!0))}return e}keys(){return Object.keys(this.items)}set(s,e,i=!1,l=this.resetTtl){let h;if(i||t(this.items,s)){if(h=this.items[s],h.value=e,l&&(h.expiry=this.ttl>0?Date.now()+this.ttl:this.ttl),this.last!==h){const t=this.last,s=h.next,e=h.prev;this.first===h&&(this.first=h.next),h.next=null,h.prev=this.last,t.next=h,null!==e&&(e.next=s),null!==s&&(s.prev=e)}}else this.max>0&&this.size===this.max&&this.evict(!0),h=this.items[s]={expiry:this.ttl>0?Date.now()+this.ttl:this.ttl,key:s,prev:this.last,next:null,value:e},1==++this.size?this.first=h:this.last.next=h;return this.last=h,this}}function e(t=1e3,e=0,i=!1){if(isNaN(t)||t<0)throw new TypeError("Invalid max value");if(isNaN(e)||e<0)throw new TypeError("Invalid ttl value");if("boolean"!=typeof i)throw new TypeError("Invalid resetTtl value");return new s(t,e,i)}export{e as lru};//# sourceMappingURL=tiny-lru.min.js.map +class t{constructor(t=0,s=0,e=!1){this.first=null,this.items=Object.create(null),this.last=null,this.max=t,this.resetTtl=e,this.size=0,this.ttl=s}clear(){return this.first=null,this.items=Object.create(null),this.last=null,this.size=0,this}delete(t){if(this.has(t)){const s=this.items[t];delete this.items[t],this.size--,null!==s.prev&&(s.prev.next=s.next),null!==s.next&&(s.next.prev=s.prev),this.first===s&&(this.first=s.next),this.last===s&&(this.last=s.prev)}return this}entries(t=this.keys()){return t.map((t=>[t,this.get(t)]))}evict(t=!1){if(t||this.size>0){const t=this.first;delete this.items[t.key],0==--this.size?(this.first=null,this.last=null):(this.first=t.next,this.first.prev=null)}return this}expiresAt(t){let s;return this.has(t)&&(s=this.items[t].expiry),s}get(t){let s;if(this.has(t)){const e=this.items[t];this.ttl>0&&e.expiry<=Date.now()?this.delete(t):(s=e.value,this.set(t,s,!0))}return s}has(t){return t in this.items}keys(){return Object.keys(this.items)}set(t,s,e=!1,i=this.resetTtl){let h;if(e||this.has(t)){if(h=this.items[t],h.value=s,i&&(h.expiry=this.ttl>0?Date.now()+this.ttl:this.ttl),this.last!==h){const t=this.last,s=h.next,e=h.prev;this.first===h&&(this.first=h.next),h.next=null,h.prev=this.last,t.next=h,null!==e&&(e.next=s),null!==s&&(s.prev=e)}}else this.max>0&&this.size===this.max&&this.evict(!0),h=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=h:this.last.next=h;return this.last=h,this}values(t=this.keys()){return t.map((t=>this.get(t)))}}function s(s=1e3,e=0,i=!1){if(isNaN(s)||s<0)throw new TypeError("Invalid max value");if(isNaN(e)||e<0)throw new TypeError("Invalid ttl value");if("boolean"!=typeof i)throw new TypeError("Invalid resetTtl value");return new t(s,e,i)}export{s 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 7335512..59c2b7e 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/has.js","../src/lru.js"],"sourcesContent":["export function has (items, key) {\r\n\treturn key in items;\r\n}\r\n","import {has} from \"./has.js\";\r\n\r\nclass LRU {\r\n\tconstructor (max = 0, ttl = 0, resetTtl = false) {\r\n\t\tthis.first = null;\r\n\t\tthis.items = Object.create(null);\r\n\t\tthis.last = null;\r\n\t\tthis.max = max;\r\n\t\tthis.resetTtl = resetTtl;\r\n\t\tthis.size = 0;\r\n\t\tthis.ttl = ttl;\r\n\t}\r\n\r\n\tclear () {\r\n\t\tthis.first = null;\r\n\t\tthis.items = Object.create(null);\r\n\t\tthis.last = null;\r\n\t\tthis.size = 0;\r\n\r\n\t\treturn this;\r\n\t}\r\n\r\n\tdelete (key) {\r\n\t\tif (has(this.items, key)) {\r\n\t\t\tconst item = this.items[key];\r\n\r\n\t\t\tdelete this.items[key];\r\n\t\t\tthis.size--;\r\n\r\n\t\t\tif (item.prev !== null) {\r\n\t\t\t\titem.prev.next = item.next;\r\n\t\t\t}\r\n\r\n\t\t\tif (item.next !== null) {\r\n\t\t\t\titem.next.prev = item.prev;\r\n\t\t\t}\r\n\r\n\t\t\tif (this.first === item) {\r\n\t\t\t\tthis.first = item.next;\r\n\t\t\t}\r\n\r\n\t\t\tif (this.last === item) {\r\n\t\t\t\tthis.last = item.prev;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\treturn this;\r\n\t}\r\n\r\n\tevict (bypass = false) {\r\n\t\tif (bypass || this.size > 0) {\r\n\t\t\tconst item = this.first;\r\n\r\n\t\t\tdelete this.items[item.key];\r\n\r\n\t\t\tif (--this.size === 0) {\r\n\t\t\t\tthis.first = null;\r\n\t\t\t\tthis.last = null;\r\n\t\t\t} else {\r\n\t\t\t\tthis.first = item.next;\r\n\t\t\t\tthis.first.prev = null;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\treturn this;\r\n\t}\r\n\r\n\texpiresAt (key) {\r\n\t\tlet result;\r\n\r\n\t\tif (has(this.items, key)) {\r\n\t\t\tresult = this.items[key].expiry;\r\n\t\t}\r\n\r\n\t\treturn result;\r\n\t}\r\n\r\n\tget (key) {\r\n\t\tlet result;\r\n\r\n\t\tif (has(this.items, key)) {\r\n\t\t\tconst item = this.items[key];\r\n\r\n\t\t\tif (this.ttl > 0 && item.expiry <= Date.now()) {\r\n\t\t\t\tthis.delete(key);\r\n\t\t\t} else {\r\n\t\t\t\tresult = item.value;\r\n\t\t\t\tthis.set(key, result, true);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\treturn result;\r\n\t}\r\n\r\n\tkeys () {\r\n\t\treturn Object.keys(this.items);\r\n\t}\r\n\r\n\tset (key, value, bypass = false, resetTtl = this.resetTtl) {\r\n\t\tlet item;\r\n\r\n\t\tif (bypass || has(this.items, key)) {\r\n\t\t\titem = this.items[key];\r\n\t\t\titem.value = value;\r\n\r\n\t\t\tif (resetTtl) {\r\n\t\t\t\titem.expiry = this.ttl > 0 ? Date.now() + this.ttl : this.ttl;\r\n\t\t\t}\r\n\r\n\t\t\tif (this.last !== item) {\r\n\t\t\t\tconst last = this.last,\r\n\t\t\t\t\tnext = item.next,\r\n\t\t\t\t\tprev = item.prev;\r\n\r\n\t\t\t\tif (this.first === item) {\r\n\t\t\t\t\tthis.first = item.next;\r\n\t\t\t\t}\r\n\r\n\t\t\t\titem.next = null;\r\n\t\t\t\titem.prev = this.last;\r\n\t\t\t\tlast.next = item;\r\n\r\n\t\t\t\tif (prev !== null) {\r\n\t\t\t\t\tprev.next = next;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif (next !== null) {\r\n\t\t\t\t\tnext.prev = prev;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t} else {\r\n\t\t\tif (this.max > 0 && this.size === this.max) {\r\n\t\t\t\tthis.evict(true);\r\n\t\t\t}\r\n\r\n\t\t\titem = this.items[key] = {\r\n\t\t\t\texpiry: this.ttl > 0 ? Date.now() + this.ttl : this.ttl,\r\n\t\t\t\tkey: key,\r\n\t\t\t\tprev: this.last,\r\n\t\t\t\tnext: null,\r\n\t\t\t\tvalue\r\n\t\t\t};\r\n\r\n\t\t\tif (++this.size === 1) {\r\n\t\t\t\tthis.first = item;\r\n\t\t\t} else {\r\n\t\t\t\tthis.last.next = item;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tthis.last = item;\r\n\r\n\t\treturn this;\r\n\t}\r\n}\r\n\r\nexport function lru (max = 1000, ttl = 0, resetTtl = false) {\r\n\tif (isNaN(max) || max < 0) {\r\n\t\tthrow new TypeError(\"Invalid max value\");\r\n\t}\r\n\r\n\tif (isNaN(ttl) || ttl < 0) {\r\n\t\tthrow new TypeError(\"Invalid ttl value\");\r\n\t}\r\n\r\n\tif (typeof resetTtl !== \"boolean\") {\r\n\t\tthrow new TypeError(\"Invalid resetTtl value\");\r\n\t}\r\n\r\n\treturn new LRU(max, ttl, resetTtl);\r\n}\r\n"],"names":["has","items","key","LRU","constructor","max","ttl","resetTtl","this","first","Object","create","last","size","clear","delete","item","prev","next","evict","bypass","expiresAt","result","expiry","get","Date","now","value","set","keys","lru","isNaN","TypeError"],"mappings":";;;;AAAO,SAASA,EAAKC,EAAOC,GAC3B,OAAOA,KAAOD,CACf,CCAA,MAAME,EACLC,YAAaC,EAAM,EAAGC,EAAM,EAAGC,GAAW,GACzCC,KAAKC,MAAQ,KACbD,KAAKP,MAAQS,OAAOC,OAAO,MAC3BH,KAAKI,KAAO,KACZJ,KAAKH,IAAMA,EACXG,KAAKD,SAAWA,EAChBC,KAAKK,KAAO,EACZL,KAAKF,IAAMA,CACX,CAEDQ,QAMC,OALAN,KAAKC,MAAQ,KACbD,KAAKP,MAAQS,OAAOC,OAAO,MAC3BH,KAAKI,KAAO,KACZJ,KAAKK,KAAO,EAELL,IACP,CAEDO,OAAQb,GACP,GAAIF,EAAIQ,KAAKP,MAAOC,GAAM,CACzB,MAAMc,EAAOR,KAAKP,MAAMC,UAEjBM,KAAKP,MAAMC,GAClBM,KAAKK,OAEa,OAAdG,EAAKC,OACRD,EAAKC,KAAKC,KAAOF,EAAKE,MAGL,OAAdF,EAAKE,OACRF,EAAKE,KAAKD,KAAOD,EAAKC,MAGnBT,KAAKC,QAAUO,IAClBR,KAAKC,MAAQO,EAAKE,MAGfV,KAAKI,OAASI,IACjBR,KAAKI,KAAOI,EAAKC,KAElB,CAED,OAAOT,IACP,CAEDW,MAAOC,GAAS,GACf,GAAIA,GAAUZ,KAAKK,KAAO,EAAG,CAC5B,MAAMG,EAAOR,KAAKC,aAEXD,KAAKP,MAAMe,EAAKd,KAEH,KAAdM,KAAKK,MACVL,KAAKC,MAAQ,KACbD,KAAKI,KAAO,OAEZJ,KAAKC,MAAQO,EAAKE,KAClBV,KAAKC,MAAMQ,KAAO,KAEnB,CAED,OAAOT,IACP,CAEDa,UAAWnB,GACV,IAAIoB,EAMJ,OAJItB,EAAIQ,KAAKP,MAAOC,KACnBoB,EAASd,KAAKP,MAAMC,GAAKqB,QAGnBD,CACP,CAEDE,IAAKtB,GACJ,IAAIoB,EAEJ,GAAItB,EAAIQ,KAAKP,MAAOC,GAAM,CACzB,MAAMc,EAAOR,KAAKP,MAAMC,GAEpBM,KAAKF,IAAM,GAAKU,EAAKO,QAAUE,KAAKC,MACvClB,KAAKO,OAAOb,IAEZoB,EAASN,EAAKW,MACdnB,KAAKoB,IAAI1B,EAAKoB,GAAQ,GAEvB,CAED,OAAOA,CACP,CAEDO,OACC,OAAOnB,OAAOmB,KAAKrB,KAAKP,MACxB,CAED2B,IAAK1B,EAAKyB,EAAOP,GAAS,EAAOb,EAAWC,KAAKD,UAChD,IAAIS,EAEJ,GAAII,GAAUpB,EAAIQ,KAAKP,MAAOC,IAQ7B,GAPAc,EAAOR,KAAKP,MAAMC,GAClBc,EAAKW,MAAQA,EAETpB,IACHS,EAAKO,OAASf,KAAKF,IAAM,EAAImB,KAAKC,MAAQlB,KAAKF,IAAME,KAAKF,KAGvDE,KAAKI,OAASI,EAAM,CACvB,MAAMJ,EAAOJ,KAAKI,KACjBM,EAAOF,EAAKE,KACZD,EAAOD,EAAKC,KAETT,KAAKC,QAAUO,IAClBR,KAAKC,MAAQO,EAAKE,MAGnBF,EAAKE,KAAO,KACZF,EAAKC,KAAOT,KAAKI,KACjBA,EAAKM,KAAOF,EAEC,OAATC,IACHA,EAAKC,KAAOA,GAGA,OAATA,IACHA,EAAKD,KAAOA,EAEb,OAEGT,KAAKH,IAAM,GAAKG,KAAKK,OAASL,KAAKH,KACtCG,KAAKW,OAAM,GAGZH,EAAOR,KAAKP,MAAMC,GAAO,CACxBqB,OAAQf,KAAKF,IAAM,EAAImB,KAAKC,MAAQlB,KAAKF,IAAME,KAAKF,IACpDJ,IAAKA,EACLe,KAAMT,KAAKI,KACXM,KAAM,KACNS,SAGmB,KAAdnB,KAAKK,KACVL,KAAKC,MAAQO,EAEbR,KAAKI,KAAKM,KAAOF,EAMnB,OAFAR,KAAKI,KAAOI,EAELR,IACP,EAGK,SAASsB,EAAKzB,EAAM,IAAMC,EAAM,EAAGC,GAAW,GACpD,GAAIwB,MAAM1B,IAAQA,EAAM,EACvB,MAAM,IAAI2B,UAAU,qBAGrB,GAAID,MAAMzB,IAAQA,EAAM,EACvB,MAAM,IAAI0B,UAAU,qBAGrB,GAAwB,kBAAbzB,EACV,MAAM,IAAIyB,UAAU,0BAGrB,OAAO,IAAI7B,EAAIE,EAAKC,EAAKC,EAC1B,QAAAuB"} \ No newline at end of file +{"version":3,"file":"tiny-lru.min.js","sources":["../src/lru.js"],"sourcesContent":["class LRU {\r\n\tconstructor (max = 0, ttl = 0, resetTtl = false) {\r\n\t\tthis.first = null;\r\n\t\tthis.items = Object.create(null);\r\n\t\tthis.last = null;\r\n\t\tthis.max = max;\r\n\t\tthis.resetTtl = resetTtl;\r\n\t\tthis.size = 0;\r\n\t\tthis.ttl = ttl;\r\n\t}\r\n\r\n\tclear () {\r\n\t\tthis.first = null;\r\n\t\tthis.items = Object.create(null);\r\n\t\tthis.last = null;\r\n\t\tthis.size = 0;\r\n\r\n\t\treturn this;\r\n\t}\r\n\r\n\tdelete (key) {\r\n\t\tif (this.has(key)) {\r\n\t\t\tconst item = this.items[key];\r\n\r\n\t\t\tdelete this.items[key];\r\n\t\t\tthis.size--;\r\n\r\n\t\t\tif (item.prev !== null) {\r\n\t\t\t\titem.prev.next = item.next;\r\n\t\t\t}\r\n\r\n\t\t\tif (item.next !== null) {\r\n\t\t\t\titem.next.prev = item.prev;\r\n\t\t\t}\r\n\r\n\t\t\tif (this.first === item) {\r\n\t\t\t\tthis.first = item.next;\r\n\t\t\t}\r\n\r\n\t\t\tif (this.last === item) {\r\n\t\t\t\tthis.last = item.prev;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\treturn this;\r\n\t}\r\n\r\n\tentries (keys = this.keys()) {\r\n\t\treturn keys.map(key => [key, this.get(key)]);\r\n\t}\r\n\r\n\tevict (bypass = false) {\r\n\t\tif (bypass || this.size > 0) {\r\n\t\t\tconst item = this.first;\r\n\r\n\t\t\tdelete this.items[item.key];\r\n\r\n\t\t\tif (--this.size === 0) {\r\n\t\t\t\tthis.first = null;\r\n\t\t\t\tthis.last = null;\r\n\t\t\t} else {\r\n\t\t\t\tthis.first = item.next;\r\n\t\t\t\tthis.first.prev = null;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\treturn this;\r\n\t}\r\n\r\n\texpiresAt (key) {\r\n\t\tlet result;\r\n\r\n\t\tif (this.has(key)) {\r\n\t\t\tresult = this.items[key].expiry;\r\n\t\t}\r\n\r\n\t\treturn result;\r\n\t}\r\n\r\n\tget (key) {\r\n\t\tlet result;\r\n\r\n\t\tif (this.has(key)) {\r\n\t\t\tconst item = this.items[key];\r\n\r\n\t\t\tif (this.ttl > 0 && item.expiry <= Date.now()) {\r\n\t\t\t\tthis.delete(key);\r\n\t\t\t} else {\r\n\t\t\t\tresult = item.value;\r\n\t\t\t\tthis.set(key, result, true);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\treturn result;\r\n\t}\r\n\r\n\thas (key) {\r\n\t\treturn key in this.items;\r\n\t}\r\n\r\n\tkeys () {\r\n\t\treturn Object.keys(this.items);\r\n\t}\r\n\r\n\tset (key, value, bypass = false, resetTtl = this.resetTtl) {\r\n\t\tlet item;\r\n\r\n\t\tif (bypass || this.has(key)) {\r\n\t\t\titem = this.items[key];\r\n\t\t\titem.value = value;\r\n\r\n\t\t\tif (resetTtl) {\r\n\t\t\t\titem.expiry = this.ttl > 0 ? Date.now() + this.ttl : this.ttl;\r\n\t\t\t}\r\n\r\n\t\t\tif (this.last !== item) {\r\n\t\t\t\tconst last = this.last,\r\n\t\t\t\t\tnext = item.next,\r\n\t\t\t\t\tprev = item.prev;\r\n\r\n\t\t\t\tif (this.first === item) {\r\n\t\t\t\t\tthis.first = item.next;\r\n\t\t\t\t}\r\n\r\n\t\t\t\titem.next = null;\r\n\t\t\t\titem.prev = this.last;\r\n\t\t\t\tlast.next = item;\r\n\r\n\t\t\t\tif (prev !== null) {\r\n\t\t\t\t\tprev.next = next;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif (next !== null) {\r\n\t\t\t\t\tnext.prev = prev;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t} else {\r\n\t\t\tif (this.max > 0 && this.size === this.max) {\r\n\t\t\t\tthis.evict(true);\r\n\t\t\t}\r\n\r\n\t\t\titem = this.items[key] = {\r\n\t\t\t\texpiry: this.ttl > 0 ? Date.now() + this.ttl : this.ttl,\r\n\t\t\t\tkey: key,\r\n\t\t\t\tprev: this.last,\r\n\t\t\t\tnext: null,\r\n\t\t\t\tvalue\r\n\t\t\t};\r\n\r\n\t\t\tif (++this.size === 1) {\r\n\t\t\t\tthis.first = item;\r\n\t\t\t} else {\r\n\t\t\t\tthis.last.next = item;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tthis.last = item;\r\n\r\n\t\treturn this;\r\n\t}\r\n\r\n\tvalues (keys = this.keys()) {\r\n\t\treturn keys.map(key => this.get(key));\r\n\t}\r\n}\r\n\r\nexport function lru (max = 1000, ttl = 0, resetTtl = false) {\r\n\tif (isNaN(max) || max < 0) {\r\n\t\tthrow new TypeError(\"Invalid max value\");\r\n\t}\r\n\r\n\tif (isNaN(ttl) || ttl < 0) {\r\n\t\tthrow new TypeError(\"Invalid ttl value\");\r\n\t}\r\n\r\n\tif (typeof resetTtl !== \"boolean\") {\r\n\t\tthrow new TypeError(\"Invalid resetTtl value\");\r\n\t}\r\n\r\n\treturn new LRU(max, ttl, resetTtl);\r\n}\r\n"],"names":["LRU","constructor","max","ttl","resetTtl","this","first","items","Object","create","last","size","clear","delete","key","has","item","prev","next","entries","keys","map","get","evict","bypass","expiresAt","result","expiry","Date","now","value","set","values","lru","isNaN","TypeError"],"mappings":"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"} \ No newline at end of file diff --git a/dist/tiny-lru.umd.js b/dist/tiny-lru.umd.js index 5345b7d..47451ba 100644 --- a/dist/tiny-lru.umd.js +++ b/dist/tiny-lru.umd.js @@ -3,11 +3,9 @@ * * @copyright 2023 Jason Mulligan * @license BSD-3-Clause - * @version 11.0.1 + * @version 11.1.0 */ -(function(g,f){typeof exports==='object'&&typeof module!=='undefined'?f(exports):typeof define==='function'&&define.amd?define(['exports'],f):(g=typeof globalThis!=='undefined'?globalThis:g||self,f(g.lru={}));})(this,(function(exports){'use strict';function has (items, key) { - return key in items; -}class LRU { +(function(g,f){typeof exports==='object'&&typeof module!=='undefined'?f(exports):typeof define==='function'&&define.amd?define(['exports'],f):(g=typeof globalThis!=='undefined'?globalThis:g||self,f(g.lru={}));})(this,(function(exports){'use strict';class LRU { constructor (max = 0, ttl = 0, resetTtl = false) { this.first = null; this.items = Object.create(null); @@ -28,7 +26,7 @@ } delete (key) { - if (has(this.items, key)) { + if (this.has(key)) { const item = this.items[key]; delete this.items[key]; @@ -54,6 +52,10 @@ return this; } + entries (keys = this.keys()) { + return keys.map(key => [key, this.get(key)]); + } + evict (bypass = false) { if (bypass || this.size > 0) { const item = this.first; @@ -75,7 +77,7 @@ expiresAt (key) { let result; - if (has(this.items, key)) { + if (this.has(key)) { result = this.items[key].expiry; } @@ -85,7 +87,7 @@ get (key) { let result; - if (has(this.items, key)) { + if (this.has(key)) { const item = this.items[key]; if (this.ttl > 0 && item.expiry <= Date.now()) { @@ -99,6 +101,10 @@ return result; } + has (key) { + return key in this.items; + } + keys () { return Object.keys(this.items); } @@ -106,7 +112,7 @@ set (key, value, bypass = false, resetTtl = this.resetTtl) { let item; - if (bypass || has(this.items, key)) { + if (bypass || this.has(key)) { item = this.items[key]; item.value = value; @@ -159,6 +165,10 @@ return this; } + + values (keys = this.keys()) { + return keys.map(key => this.get(key)); + } } function lru (max = 1000, ttl = 0, resetTtl = false) { diff --git a/dist/tiny-lru.umd.min.js b/dist/tiny-lru.umd.min.js index cdee6da..163c284 100644 --- a/dist/tiny-lru.umd.min.js +++ b/dist/tiny-lru.umd.min.js @@ -1,5 +1,5 @@ /*! 2023 Jason Mulligan - @version 11.0.1 + @version 11.1.0 */ -!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).lru={})}(this,(function(t){"use strict";function e(t,e){return e in t}class s{constructor(t=0,e=0,s=!1){this.first=null,this.items=Object.create(null),this.last=null,this.max=t,this.resetTtl=s,this.size=0,this.ttl=e}clear(){return this.first=null,this.items=Object.create(null),this.last=null,this.size=0,this}delete(t){if(e(this.items,t)){const e=this.items[t];delete this.items[t],this.size--,null!==e.prev&&(e.prev.next=e.next),null!==e.next&&(e.next.prev=e.prev),this.first===e&&(this.first=e.next),this.last===e&&(this.last=e.prev)}return this}evict(t=!1){if(t||this.size>0){const t=this.first;delete this.items[t.key],0==--this.size?(this.first=null,this.last=null):(this.first=t.next,this.first.prev=null)}return this}expiresAt(t){let s;return e(this.items,t)&&(s=this.items[t].expiry),s}get(t){let s;if(e(this.items,t)){const e=this.items[t];this.ttl>0&&e.expiry<=Date.now()?this.delete(t):(s=e.value,this.set(t,s,!0))}return s}keys(){return Object.keys(this.items)}set(t,s,i=!1,l=this.resetTtl){let n;if(i||e(this.items,t)){if(n=this.items[t],n.value=s,l&&(n.expiry=this.ttl>0?Date.now()+this.ttl:this.ttl),this.last!==n){const t=this.last,e=n.next,s=n.prev;this.first===n&&(this.first=n.next),n.next=null,n.prev=this.last,t.next=n,null!==s&&(s.next=e),null!==e&&(e.prev=s)}}else this.max>0&&this.size===this.max&&this.evict(!0),n=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=n:this.last.next=n;return this.last=n,this}}t.lru=function(t=1e3,e=0,i=!1){if(isNaN(t)||t<0)throw new TypeError("Invalid max value");if(isNaN(e)||e<0)throw new TypeError("Invalid ttl value");if("boolean"!=typeof i)throw new TypeError("Invalid resetTtl value");return new s(t,e,i)}}));//# sourceMappingURL=tiny-lru.umd.min.js.map +!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).lru={})}(this,(function(t){"use strict";class e{constructor(t=0,e=0,s=!1){this.first=null,this.items=Object.create(null),this.last=null,this.max=t,this.resetTtl=s,this.size=0,this.ttl=e}clear(){return this.first=null,this.items=Object.create(null),this.last=null,this.size=0,this}delete(t){if(this.has(t)){const e=this.items[t];delete this.items[t],this.size--,null!==e.prev&&(e.prev.next=e.next),null!==e.next&&(e.next.prev=e.prev),this.first===e&&(this.first=e.next),this.last===e&&(this.last=e.prev)}return this}entries(t=this.keys()){return t.map((t=>[t,this.get(t)]))}evict(t=!1){if(t||this.size>0){const t=this.first;delete this.items[t.key],0==--this.size?(this.first=null,this.last=null):(this.first=t.next,this.first.prev=null)}return this}expiresAt(t){let e;return this.has(t)&&(e=this.items[t].expiry),e}get(t){let e;if(this.has(t)){const s=this.items[t];this.ttl>0&&s.expiry<=Date.now()?this.delete(t):(e=s.value,this.set(t,e,!0))}return e}has(t){return t in this.items}keys(){return Object.keys(this.items)}set(t,e,s=!1,i=this.resetTtl){let l;if(s||this.has(t)){if(l=this.items[t],l.value=e,i&&(l.expiry=this.ttl>0?Date.now()+this.ttl:this.ttl),this.last!==l){const t=this.last,e=l.next,s=l.prev;this.first===l&&(this.first=l.next),l.next=null,l.prev=this.last,t.next=l,null!==s&&(s.next=e),null!==e&&(e.prev=s)}}else this.max>0&&this.size===this.max&&this.evict(!0),l=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=l:this.last.next=l;return this.last=l,this}values(t=this.keys()){return t.map((t=>this.get(t)))}}t.lru=function(t=1e3,s=0,i=!1){if(isNaN(t)||t<0)throw new TypeError("Invalid max value");if(isNaN(s)||s<0)throw new TypeError("Invalid ttl value");if("boolean"!=typeof i)throw new TypeError("Invalid resetTtl value");return new e(t,s,i)}}));//# sourceMappingURL=tiny-lru.umd.min.js.map diff --git a/dist/tiny-lru.umd.min.js.map b/dist/tiny-lru.umd.min.js.map index 1272a54..1e6a971 100644 --- a/dist/tiny-lru.umd.min.js.map +++ b/dist/tiny-lru.umd.min.js.map @@ -1 +1 @@ -{"version":3,"file":"tiny-lru.umd.min.js","sources":["../src/has.js","../src/lru.js"],"sourcesContent":["export function has (items, key) {\r\n\treturn key in items;\r\n}\r\n","import {has} from \"./has.js\";\r\n\r\nclass LRU {\r\n\tconstructor (max = 0, ttl = 0, resetTtl = false) {\r\n\t\tthis.first = null;\r\n\t\tthis.items = Object.create(null);\r\n\t\tthis.last = null;\r\n\t\tthis.max = max;\r\n\t\tthis.resetTtl = resetTtl;\r\n\t\tthis.size = 0;\r\n\t\tthis.ttl = ttl;\r\n\t}\r\n\r\n\tclear () {\r\n\t\tthis.first = null;\r\n\t\tthis.items = Object.create(null);\r\n\t\tthis.last = null;\r\n\t\tthis.size = 0;\r\n\r\n\t\treturn this;\r\n\t}\r\n\r\n\tdelete (key) {\r\n\t\tif (has(this.items, key)) {\r\n\t\t\tconst item = this.items[key];\r\n\r\n\t\t\tdelete this.items[key];\r\n\t\t\tthis.size--;\r\n\r\n\t\t\tif (item.prev !== null) {\r\n\t\t\t\titem.prev.next = item.next;\r\n\t\t\t}\r\n\r\n\t\t\tif (item.next !== null) {\r\n\t\t\t\titem.next.prev = item.prev;\r\n\t\t\t}\r\n\r\n\t\t\tif (this.first === item) {\r\n\t\t\t\tthis.first = item.next;\r\n\t\t\t}\r\n\r\n\t\t\tif (this.last === item) {\r\n\t\t\t\tthis.last = item.prev;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\treturn this;\r\n\t}\r\n\r\n\tevict (bypass = false) {\r\n\t\tif (bypass || this.size > 0) {\r\n\t\t\tconst item = this.first;\r\n\r\n\t\t\tdelete this.items[item.key];\r\n\r\n\t\t\tif (--this.size === 0) {\r\n\t\t\t\tthis.first = null;\r\n\t\t\t\tthis.last = null;\r\n\t\t\t} else {\r\n\t\t\t\tthis.first = item.next;\r\n\t\t\t\tthis.first.prev = null;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\treturn this;\r\n\t}\r\n\r\n\texpiresAt (key) {\r\n\t\tlet result;\r\n\r\n\t\tif (has(this.items, key)) {\r\n\t\t\tresult = this.items[key].expiry;\r\n\t\t}\r\n\r\n\t\treturn result;\r\n\t}\r\n\r\n\tget (key) {\r\n\t\tlet result;\r\n\r\n\t\tif (has(this.items, key)) {\r\n\t\t\tconst item = this.items[key];\r\n\r\n\t\t\tif (this.ttl > 0 && item.expiry <= Date.now()) {\r\n\t\t\t\tthis.delete(key);\r\n\t\t\t} else {\r\n\t\t\t\tresult = item.value;\r\n\t\t\t\tthis.set(key, result, true);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\treturn result;\r\n\t}\r\n\r\n\tkeys () {\r\n\t\treturn Object.keys(this.items);\r\n\t}\r\n\r\n\tset (key, value, bypass = false, resetTtl = this.resetTtl) {\r\n\t\tlet item;\r\n\r\n\t\tif (bypass || has(this.items, key)) {\r\n\t\t\titem = this.items[key];\r\n\t\t\titem.value = value;\r\n\r\n\t\t\tif (resetTtl) {\r\n\t\t\t\titem.expiry = this.ttl > 0 ? Date.now() + this.ttl : this.ttl;\r\n\t\t\t}\r\n\r\n\t\t\tif (this.last !== item) {\r\n\t\t\t\tconst last = this.last,\r\n\t\t\t\t\tnext = item.next,\r\n\t\t\t\t\tprev = item.prev;\r\n\r\n\t\t\t\tif (this.first === item) {\r\n\t\t\t\t\tthis.first = item.next;\r\n\t\t\t\t}\r\n\r\n\t\t\t\titem.next = null;\r\n\t\t\t\titem.prev = this.last;\r\n\t\t\t\tlast.next = item;\r\n\r\n\t\t\t\tif (prev !== null) {\r\n\t\t\t\t\tprev.next = next;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif (next !== null) {\r\n\t\t\t\t\tnext.prev = prev;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t} else {\r\n\t\t\tif (this.max > 0 && this.size === this.max) {\r\n\t\t\t\tthis.evict(true);\r\n\t\t\t}\r\n\r\n\t\t\titem = this.items[key] = {\r\n\t\t\t\texpiry: this.ttl > 0 ? Date.now() + this.ttl : this.ttl,\r\n\t\t\t\tkey: key,\r\n\t\t\t\tprev: this.last,\r\n\t\t\t\tnext: null,\r\n\t\t\t\tvalue\r\n\t\t\t};\r\n\r\n\t\t\tif (++this.size === 1) {\r\n\t\t\t\tthis.first = item;\r\n\t\t\t} else {\r\n\t\t\t\tthis.last.next = item;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tthis.last = item;\r\n\r\n\t\treturn this;\r\n\t}\r\n}\r\n\r\nexport function lru (max = 1000, ttl = 0, resetTtl = false) {\r\n\tif (isNaN(max) || max < 0) {\r\n\t\tthrow new TypeError(\"Invalid max value\");\r\n\t}\r\n\r\n\tif (isNaN(ttl) || ttl < 0) {\r\n\t\tthrow new TypeError(\"Invalid ttl value\");\r\n\t}\r\n\r\n\tif (typeof resetTtl !== \"boolean\") {\r\n\t\tthrow new TypeError(\"Invalid resetTtl value\");\r\n\t}\r\n\r\n\treturn new LRU(max, ttl, resetTtl);\r\n}\r\n"],"names":["g","f","exports","module","define","amd","globalThis","self","lru","this","has","items","key","LRU","constructor","max","ttl","resetTtl","first","Object","create","last","size","clear","delete","item","prev","next","evict","bypass","expiresAt","result","expiry","get","Date","now","value","set","keys","isNaN","TypeError"],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"tiny-lru.umd.min.js","sources":["../src/lru.js"],"sourcesContent":["class LRU {\r\n\tconstructor (max = 0, ttl = 0, resetTtl = false) {\r\n\t\tthis.first = null;\r\n\t\tthis.items = Object.create(null);\r\n\t\tthis.last = null;\r\n\t\tthis.max = max;\r\n\t\tthis.resetTtl = resetTtl;\r\n\t\tthis.size = 0;\r\n\t\tthis.ttl = ttl;\r\n\t}\r\n\r\n\tclear () {\r\n\t\tthis.first = null;\r\n\t\tthis.items = Object.create(null);\r\n\t\tthis.last = null;\r\n\t\tthis.size = 0;\r\n\r\n\t\treturn this;\r\n\t}\r\n\r\n\tdelete (key) {\r\n\t\tif (this.has(key)) {\r\n\t\t\tconst item = this.items[key];\r\n\r\n\t\t\tdelete this.items[key];\r\n\t\t\tthis.size--;\r\n\r\n\t\t\tif (item.prev !== null) {\r\n\t\t\t\titem.prev.next = item.next;\r\n\t\t\t}\r\n\r\n\t\t\tif (item.next !== null) {\r\n\t\t\t\titem.next.prev = item.prev;\r\n\t\t\t}\r\n\r\n\t\t\tif (this.first === item) {\r\n\t\t\t\tthis.first = item.next;\r\n\t\t\t}\r\n\r\n\t\t\tif (this.last === item) {\r\n\t\t\t\tthis.last = item.prev;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\treturn this;\r\n\t}\r\n\r\n\tentries (keys = this.keys()) {\r\n\t\treturn keys.map(key => [key, this.get(key)]);\r\n\t}\r\n\r\n\tevict (bypass = false) {\r\n\t\tif (bypass || this.size > 0) {\r\n\t\t\tconst item = this.first;\r\n\r\n\t\t\tdelete this.items[item.key];\r\n\r\n\t\t\tif (--this.size === 0) {\r\n\t\t\t\tthis.first = null;\r\n\t\t\t\tthis.last = null;\r\n\t\t\t} else {\r\n\t\t\t\tthis.first = item.next;\r\n\t\t\t\tthis.first.prev = null;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\treturn this;\r\n\t}\r\n\r\n\texpiresAt (key) {\r\n\t\tlet result;\r\n\r\n\t\tif (this.has(key)) {\r\n\t\t\tresult = this.items[key].expiry;\r\n\t\t}\r\n\r\n\t\treturn result;\r\n\t}\r\n\r\n\tget (key) {\r\n\t\tlet result;\r\n\r\n\t\tif (this.has(key)) {\r\n\t\t\tconst item = this.items[key];\r\n\r\n\t\t\tif (this.ttl > 0 && item.expiry <= Date.now()) {\r\n\t\t\t\tthis.delete(key);\r\n\t\t\t} else {\r\n\t\t\t\tresult = item.value;\r\n\t\t\t\tthis.set(key, result, true);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\treturn result;\r\n\t}\r\n\r\n\thas (key) {\r\n\t\treturn key in this.items;\r\n\t}\r\n\r\n\tkeys () {\r\n\t\treturn Object.keys(this.items);\r\n\t}\r\n\r\n\tset (key, value, bypass = false, resetTtl = this.resetTtl) {\r\n\t\tlet item;\r\n\r\n\t\tif (bypass || this.has(key)) {\r\n\t\t\titem = this.items[key];\r\n\t\t\titem.value = value;\r\n\r\n\t\t\tif (resetTtl) {\r\n\t\t\t\titem.expiry = this.ttl > 0 ? Date.now() + this.ttl : this.ttl;\r\n\t\t\t}\r\n\r\n\t\t\tif (this.last !== item) {\r\n\t\t\t\tconst last = this.last,\r\n\t\t\t\t\tnext = item.next,\r\n\t\t\t\t\tprev = item.prev;\r\n\r\n\t\t\t\tif (this.first === item) {\r\n\t\t\t\t\tthis.first = item.next;\r\n\t\t\t\t}\r\n\r\n\t\t\t\titem.next = null;\r\n\t\t\t\titem.prev = this.last;\r\n\t\t\t\tlast.next = item;\r\n\r\n\t\t\t\tif (prev !== null) {\r\n\t\t\t\t\tprev.next = next;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif (next !== null) {\r\n\t\t\t\t\tnext.prev = prev;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t} else {\r\n\t\t\tif (this.max > 0 && this.size === this.max) {\r\n\t\t\t\tthis.evict(true);\r\n\t\t\t}\r\n\r\n\t\t\titem = this.items[key] = {\r\n\t\t\t\texpiry: this.ttl > 0 ? Date.now() + this.ttl : this.ttl,\r\n\t\t\t\tkey: key,\r\n\t\t\t\tprev: this.last,\r\n\t\t\t\tnext: null,\r\n\t\t\t\tvalue\r\n\t\t\t};\r\n\r\n\t\t\tif (++this.size === 1) {\r\n\t\t\t\tthis.first = item;\r\n\t\t\t} else {\r\n\t\t\t\tthis.last.next = item;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tthis.last = item;\r\n\r\n\t\treturn this;\r\n\t}\r\n\r\n\tvalues (keys = this.keys()) {\r\n\t\treturn keys.map(key => this.get(key));\r\n\t}\r\n}\r\n\r\nexport function lru (max = 1000, ttl = 0, resetTtl = false) {\r\n\tif (isNaN(max) || max < 0) {\r\n\t\tthrow new TypeError(\"Invalid max value\");\r\n\t}\r\n\r\n\tif (isNaN(ttl) || ttl < 0) {\r\n\t\tthrow new TypeError(\"Invalid ttl value\");\r\n\t}\r\n\r\n\tif (typeof resetTtl !== \"boolean\") {\r\n\t\tthrow new TypeError(\"Invalid resetTtl value\");\r\n\t}\r\n\r\n\treturn new LRU(max, ttl, resetTtl);\r\n}\r\n"],"names":["g","f","exports","module","define","amd","globalThis","self","lru","this","LRU","constructor","max","ttl","resetTtl","first","items","Object","create","last","size","clear","delete","key","has","item","prev","next","entries","keys","map","get","evict","bypass","expiresAt","result","expiry","Date","now","value","set","values","isNaN","TypeError"],"mappings":"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"} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 1c2b029..94538ac 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "tiny-lru", - "version": "11.0.1", + "version": "11.1.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "tiny-lru", - "version": "11.0.1", + "version": "11.1.0", "license": "BSD-3-Clause", "devDependencies": { "@rollup/plugin-terser": "^0.4.0", diff --git a/package.json b/package.json index 44df01f..a85fc6c 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "tiny-lru", "description": "Tiny LRU cache for Client or Server", - "version": "11.0.1", + "version": "11.1.0", "homepage": "https://github.com/avoidwork/tiny-lru", "author": "Jason Mulligan ", "repository": { diff --git a/src/has.js b/src/has.js deleted file mode 100644 index ca47e0c..0000000 --- a/src/has.js +++ /dev/null @@ -1,3 +0,0 @@ -export function has (items, key) { - return key in items; -} diff --git a/src/lru.js b/src/lru.js index b48dc2c..6b3c414 100644 --- a/src/lru.js +++ b/src/lru.js @@ -1,5 +1,3 @@ -import {has} from "./has.js"; - class LRU { constructor (max = 0, ttl = 0, resetTtl = false) { this.first = null; @@ -21,7 +19,7 @@ class LRU { } delete (key) { - if (has(this.items, key)) { + if (this.has(key)) { const item = this.items[key]; delete this.items[key]; @@ -47,6 +45,10 @@ class LRU { return this; } + entries (keys = this.keys()) { + return keys.map(key => [key, this.get(key)]); + } + evict (bypass = false) { if (bypass || this.size > 0) { const item = this.first; @@ -68,7 +70,7 @@ class LRU { expiresAt (key) { let result; - if (has(this.items, key)) { + if (this.has(key)) { result = this.items[key].expiry; } @@ -78,7 +80,7 @@ class LRU { get (key) { let result; - if (has(this.items, key)) { + if (this.has(key)) { const item = this.items[key]; if (this.ttl > 0 && item.expiry <= Date.now()) { @@ -92,6 +94,10 @@ class LRU { return result; } + has (key) { + return key in this.items; + } + keys () { return Object.keys(this.items); } @@ -99,7 +105,7 @@ class LRU { set (key, value, bypass = false, resetTtl = this.resetTtl) { let item; - if (bypass || has(this.items, key)) { + if (bypass || this.has(key)) { item = this.items[key]; item.value = value; @@ -152,6 +158,10 @@ class LRU { return this; } + + values (keys = this.keys()) { + return keys.map(key => this.get(key)); + } } export function lru (max = 1000, ttl = 0, resetTtl = false) { diff --git a/test/lru.js b/test/lru.js index d32f12c..7fb1152 100644 --- a/test/lru.js +++ b/test/lru.js @@ -18,6 +18,19 @@ describe("Testing functionality", function () { assert.strictEqual(this.cache.size, 0, "Should be '0'"); }); + it("It should have keys", function () { + this.items.forEach(i => this.cache.set(i, false)); + assert.strictEqual(this.cache.has(this.items[0]), false, "Should be 'false'"); + assert.strictEqual(this.cache.has(this.items[1]), true, "Should be 'true'"); + }); + + it("It should have entries", function () { + this.items.forEach(i => this.cache.set(i, false)); + const entries = this.cache.entries(); + assert.strictEqual(entries.length, this.cache.keys().length, "Should be equal"); + assert.strictEqual(entries[entries.length - 1][0], this.items[this.items.length - 1], "Should be equal"); + }); + it("It should evict", function () { this.items.forEach(i => this.cache.set(i, false)); assert.strictEqual(this.cache.first.key, "b", "Should be 'b'");