summaryrefslogtreecommitdiff
path: root/node_modules/@alloc/quick-lru/index.js
diff options
context:
space:
mode:
authorPhilipp Tanlak <philipp.tanlak@gmail.com>2025-11-24 20:54:57 +0100
committerPhilipp Tanlak <philipp.tanlak@gmail.com>2025-11-24 20:57:48 +0100
commitb1e2c8fd5cb5dfa46bc440a12eafaf56cd844b1c (patch)
tree49d360fd6cbc6a2754efe93524ac47ff0fbe0f7d /node_modules/@alloc/quick-lru/index.js
Docs
Diffstat (limited to 'node_modules/@alloc/quick-lru/index.js')
-rw-r--r--node_modules/@alloc/quick-lru/index.js263
1 files changed, 263 insertions, 0 deletions
diff --git a/node_modules/@alloc/quick-lru/index.js b/node_modules/@alloc/quick-lru/index.js
new file mode 100644
index 0000000..7eeced2
--- /dev/null
+++ b/node_modules/@alloc/quick-lru/index.js
@@ -0,0 +1,263 @@
+'use strict';
+
+class QuickLRU {
+ constructor(options = {}) {
+ if (!(options.maxSize && options.maxSize > 0)) {
+ throw new TypeError('`maxSize` must be a number greater than 0');
+ }
+
+ if (typeof options.maxAge === 'number' && options.maxAge === 0) {
+ throw new TypeError('`maxAge` must be a number greater than 0');
+ }
+
+ this.maxSize = options.maxSize;
+ this.maxAge = options.maxAge || Infinity;
+ this.onEviction = options.onEviction;
+ this.cache = new Map();
+ this.oldCache = new Map();
+ this._size = 0;
+ }
+
+ _emitEvictions(cache) {
+ if (typeof this.onEviction !== 'function') {
+ return;
+ }
+
+ for (const [key, item] of cache) {
+ this.onEviction(key, item.value);
+ }
+ }
+
+ _deleteIfExpired(key, item) {
+ if (typeof item.expiry === 'number' && item.expiry <= Date.now()) {
+ if (typeof this.onEviction === 'function') {
+ this.onEviction(key, item.value);
+ }
+
+ return this.delete(key);
+ }
+
+ return false;
+ }
+
+ _getOrDeleteIfExpired(key, item) {
+ const deleted = this._deleteIfExpired(key, item);
+ if (deleted === false) {
+ return item.value;
+ }
+ }
+
+ _getItemValue(key, item) {
+ return item.expiry ? this._getOrDeleteIfExpired(key, item) : item.value;
+ }
+
+ _peek(key, cache) {
+ const item = cache.get(key);
+
+ return this._getItemValue(key, item);
+ }
+
+ _set(key, value) {
+ this.cache.set(key, value);
+ this._size++;
+
+ if (this._size >= this.maxSize) {
+ this._size = 0;
+ this._emitEvictions(this.oldCache);
+ this.oldCache = this.cache;
+ this.cache = new Map();
+ }
+ }
+
+ _moveToRecent(key, item) {
+ this.oldCache.delete(key);
+ this._set(key, item);
+ }
+
+ * _entriesAscending() {
+ for (const item of this.oldCache) {
+ const [key, value] = item;
+ if (!this.cache.has(key)) {
+ const deleted = this._deleteIfExpired(key, value);
+ if (deleted === false) {
+ yield item;
+ }
+ }
+ }
+
+ for (const item of this.cache) {
+ const [key, value] = item;
+ const deleted = this._deleteIfExpired(key, value);
+ if (deleted === false) {
+ yield item;
+ }
+ }
+ }
+
+ get(key) {
+ if (this.cache.has(key)) {
+ const item = this.cache.get(key);
+
+ return this._getItemValue(key, item);
+ }
+
+ if (this.oldCache.has(key)) {
+ const item = this.oldCache.get(key);
+ if (this._deleteIfExpired(key, item) === false) {
+ this._moveToRecent(key, item);
+ return item.value;
+ }
+ }
+ }
+
+ set(key, value, {maxAge = this.maxAge === Infinity ? undefined : Date.now() + this.maxAge} = {}) {
+ if (this.cache.has(key)) {
+ this.cache.set(key, {
+ value,
+ maxAge
+ });
+ } else {
+ this._set(key, {value, expiry: maxAge});
+ }
+ }
+
+ has(key) {
+ if (this.cache.has(key)) {
+ return !this._deleteIfExpired(key, this.cache.get(key));
+ }
+
+ if (this.oldCache.has(key)) {
+ return !this._deleteIfExpired(key, this.oldCache.get(key));
+ }
+
+ return false;
+ }
+
+ peek(key) {
+ if (this.cache.has(key)) {
+ return this._peek(key, this.cache);
+ }
+
+ if (this.oldCache.has(key)) {
+ return this._peek(key, this.oldCache);
+ }
+ }
+
+ delete(key) {
+ const deleted = this.cache.delete(key);
+ if (deleted) {
+ this._size--;
+ }
+
+ return this.oldCache.delete(key) || deleted;
+ }
+
+ clear() {
+ this.cache.clear();
+ this.oldCache.clear();
+ this._size = 0;
+ }
+
+ resize(newSize) {
+ if (!(newSize && newSize > 0)) {
+ throw new TypeError('`maxSize` must be a number greater than 0');
+ }
+
+ const items = [...this._entriesAscending()];
+ const removeCount = items.length - newSize;
+ if (removeCount < 0) {
+ this.cache = new Map(items);
+ this.oldCache = new Map();
+ this._size = items.length;
+ } else {
+ if (removeCount > 0) {
+ this._emitEvictions(items.slice(0, removeCount));
+ }
+
+ this.oldCache = new Map(items.slice(removeCount));
+ this.cache = new Map();
+ this._size = 0;
+ }
+
+ this.maxSize = newSize;
+ }
+
+ * keys() {
+ for (const [key] of this) {
+ yield key;
+ }
+ }
+
+ * values() {
+ for (const [, value] of this) {
+ yield value;
+ }
+ }
+
+ * [Symbol.iterator]() {
+ for (const item of this.cache) {
+ const [key, value] = item;
+ const deleted = this._deleteIfExpired(key, value);
+ if (deleted === false) {
+ yield [key, value.value];
+ }
+ }
+
+ for (const item of this.oldCache) {
+ const [key, value] = item;
+ if (!this.cache.has(key)) {
+ const deleted = this._deleteIfExpired(key, value);
+ if (deleted === false) {
+ yield [key, value.value];
+ }
+ }
+ }
+ }
+
+ * entriesDescending() {
+ let items = [...this.cache];
+ for (let i = items.length - 1; i >= 0; --i) {
+ const item = items[i];
+ const [key, value] = item;
+ const deleted = this._deleteIfExpired(key, value);
+ if (deleted === false) {
+ yield [key, value.value];
+ }
+ }
+
+ items = [...this.oldCache];
+ for (let i = items.length - 1; i >= 0; --i) {
+ const item = items[i];
+ const [key, value] = item;
+ if (!this.cache.has(key)) {
+ const deleted = this._deleteIfExpired(key, value);
+ if (deleted === false) {
+ yield [key, value.value];
+ }
+ }
+ }
+ }
+
+ * entriesAscending() {
+ for (const [key, value] of this._entriesAscending()) {
+ yield [key, value.value];
+ }
+ }
+
+ get size() {
+ if (!this._size) {
+ return this.oldCache.size;
+ }
+
+ let oldCacheSize = 0;
+ for (const key of this.oldCache.keys()) {
+ if (!this.cache.has(key)) {
+ oldCacheSize++;
+ }
+ }
+
+ return Math.min(this._size + oldCacheSize, this.maxSize);
+ }
+}
+
+module.exports = QuickLRU;