UNPKG

@aikidosec/firewall

Version:

Zen by Aikido is an embedded Web Application Firewall that autonomously protects Node.js apps against common and critical attacks

131 lines (130 loc) 3.57 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.LRUMap = void 0; class LRUMap { constructor(max = 1000, ttlInMsecs = 0) { if (isNaN(max) || max < 0) { throw new Error("Invalid max value"); } if (isNaN(ttlInMsecs) || ttlInMsecs < 0) { throw new Error("Invalid ttl value"); } this.first = null; this.items = new Map(); this.last = null; this.max = max; this.ttl = ttlInMsecs; } get size() { return this.items.size; } bumpLru(item) { if (this.last === item) { return; // Item is already the last one, no need to bump } const last = this.last; const next = item.next; const prev = item.prev; if (this.first === item) { this.first = next; } item.next = null; item.prev = last; if (last) last.next = item; if (prev !== null) { prev.next = next; } if (next !== null) { next.prev = prev; } this.last = item; } clear() { this.items = new Map(); this.first = null; this.last = null; } delete(key) { if (this.items.has(key)) { const item = this.items.get(key); this.items.delete(key); if (item.prev !== null) { item.prev.next = item.next; } if (item.next !== null) { item.next.prev = item.prev; } if (this.first === item) { this.first = item.next; } if (this.last === item) { this.last = item.prev; } } } evict() { if (this.size > 0) { const item = this.first; this.items.delete(item.key); if (this.size === 0) { this.first = null; this.last = null; } else { this.first = item.next; if (this.first) this.first.prev = null; } } } get(key) { if (this.items.has(key)) { const item = this.items.get(key); // Item has already expired if (this.ttl > 0 && item.expiry <= performance.now()) { this.delete(key); return; } // Item is still fresh this.bumpLru(item); return item.value; } } keys() { return this.items.keys(); } set(key, value) { // Replace existing item if (this.items.has(key)) { const item = this.items.get(key); item.value = value; item.expiry = this.ttl > 0 ? performance.now() + this.ttl : this.ttl; if (this.last !== item) { this.bumpLru(item); } return; } // Add new item if (this.max > 0 && this.size === this.max) { this.evict(); } const item = { expiry: this.ttl > 0 ? performance.now() + this.ttl : this.ttl, key: key, prev: this.last, next: null, value, }; this.items.set(key, item); if (this.size === 1) { this.first = item; } else { if (this.last) this.last.next = item; } this.last = item; } } exports.LRUMap = LRUMap;