export class MemoryCacheItem { item; expiresAt; // Timestamp in ms constructor(item, expiresAt) { this.item = item; this.expiresAt = expiresAt; } isExpired(now) { return now > this.expiresAt; } setAccess(now, ttl) { this.expiresAt = now + ttl; } getItem() { return this.item; } done(now) { if (this.isExpired(now)) { return true; } return false; } } export class MemoryCache { isGathered = new Map(); references = new Map(); cache = new Map(); options; logger; disposed = false; currentSize = 0; timer; constructor(options, logger) { this.options = options; this.logger = logger; this.resetGlobalTimer(); } add(item, requestItem, testNow) { if (this.disposed) throw new Error('MemoryCache is disposed'); this.currentSize += item.size || 0; this.cache.set(item.baseId, new MemoryCacheItem(item, (testNow || this.now()) + this.options.ttlms)); if (!this.isGathered.has(item.baseId)) { this.isGathered.set(item.baseId, true); this.scanForReferences(item.base, requestItem); } } get(id) { if (this.disposed) throw new Error('MemoryCache is disposed'); const item = this.cache.get(id); if (item) { item.setAccess(this.now(), this.options.ttlms); return item.getItem(); } return undefined; } scanForReferences(data, requestItem) { const scan = (item) => { // Stop if the item is null or not an object (i.e., primitive) if (item === null || typeof item !== 'object') { return; } // If it's an array, scan each element if (Array.isArray(item)) { for (const element of item) { scan(element); } return; } // If it's an object, scan its properties for (const key in item) { if (Object.prototype.hasOwnProperty.call(item, key)) { // We found the target property! if (key === 'referencedId') { const value = item.referencedId; // Ensure the value is a string before adding it if (typeof value === 'string') { this.references.set(value, (this.references.get(value) || 0) + 1); if (!this.cache.has(value)) { requestItem(value); } } } // Continue scanning deeper into the object's properties scan(item[key]); } } }; scan(data); } resetGlobalTimer() { const run = () => { this.cleanCache(); this.timer = setTimeout(run, this.options.ttlms); }; this.timer = setTimeout(run, this.options.ttlms); } now() { return Date.now(); } cleanCache(testNow) { const maxSizeBytes = this.options.maxSizeInMb * 1024 * 1024; if (this.currentSize < maxSizeBytes) { this.logger(`cache size (${this.currentSize} < ${maxSizeBytes}) is ok, no need to clean`); return; } const now = testNow || this.now(); let cleaned = 0; const start = performance.now(); for (const deferredBase of Array.from(this.cache.values()) .filter((x) => x.isExpired(now)) .sort((a, b) => this.compareMaybeBasesByReferences(a.getItem().baseId, b.getItem().baseId))) { if (deferredBase.done(now)) { const id = deferredBase.getItem().baseId; const referenceCount = this.references.get(id) || 0; if (referenceCount > 0) { // Skip eviction for items with reference counts greater than 0, // as they are still in use and should not be removed from the cache. continue; } this.currentSize -= deferredBase.getItem().size || 0; this.cache.delete(id); cleaned++; if (this.currentSize < maxSizeBytes) { break; } } } this.logger(`cleaned cache: cleaned ${cleaned}, cached ${this.cache.size}, time ${performance.now() - start}`); return; } compareMaybeBasesByReferences(id1, id2) { const a = this.references.get(id1); const b = this.references.get(id2); if (a === undefined && b === undefined) return 0; if (a === undefined) return -1; if (b === undefined) return 1; return a - b; } dispose() { if (this.disposed) return; this.disposed = true; if (this.timer) { clearTimeout(this.timer); this.timer = undefined; } this.cache.clear(); this.isGathered.clear(); this.references.clear(); } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiTWVtb3J5Q2FjaGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvZGVmZXJtZW50L01lbW9yeUNhY2hlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQVFBLE1BQU0sT0FBTyxlQUFlO0lBQ2xCLElBQUksQ0FBTTtJQUNWLFNBQVMsQ0FBUSxDQUFDLGtCQUFrQjtJQUU1QyxZQUFZLElBQVUsRUFBRSxTQUFpQjtRQUN2QyxJQUFJLENBQUMsSUFBSSxHQUFHLElBQUksQ0FBQTtRQUNoQixJQUFJLENBQUMsU0FBUyxHQUFHLFNBQVMsQ0FBQTtJQUM1QixDQUFDO0lBRUQsU0FBUyxDQUFDLEdBQVc7UUFDbkIsT0FBTyxHQUFHLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQTtJQUM3QixDQUFDO0lBQ0QsU0FBUyxDQUFDLEdBQVcsRUFBRSxHQUFXO1FBQ2hDLElBQUksQ0FBQyxTQUFTLEdBQUcsR0FBRyxHQUFHLEdBQUcsQ0FBQTtJQUM1QixDQUFDO0lBRUQsT0FBTztRQUNMLE9BQU8sSUFBSSxDQUFDLElBQUksQ0FBQTtJQUNsQixDQUFDO0lBRUQsSUFBSSxDQUFDLEdBQVc7UUFDZCxJQUFJLElBQUksQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQztZQUN4QixPQUFPLElBQUksQ0FBQTtRQUNiLENBQUM7UUFDRCxPQUFPLEtBQUssQ0FBQTtJQUNkLENBQUM7Q0FDRjtBQUVELE1BQU0sT0FBTyxXQUFXO0lBQ2QsVUFBVSxHQUF5QixJQUFJLEdBQUcsRUFBRSxDQUFBO0lBQzVDLFVBQVUsR0FBd0IsSUFBSSxHQUFHLEVBQUUsQ0FBQTtJQUMzQyxLQUFLLEdBQWlDLElBQUksR0FBRyxFQUFFLENBQUE7SUFFL0MsT0FBTyxDQUFvQjtJQUMzQixNQUFNLENBQWM7SUFDcEIsUUFBUSxHQUFHLEtBQUssQ0FBQTtJQUNoQixXQUFXLEdBQUcsQ0FBQyxDQUFBO0lBQ2YsS0FBSyxDQUFnQztJQUU3QyxZQUFZLE9BQTJCLEVBQUUs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QUFDLEtBQUssQ0FBQyxJQUFJLFVBQzFELFdBQVcsQ0FBQyxHQUFHLEVBQUUsR0FBRyxLQUN0QixFQUFFLENBQ0gsQ0FBQTtRQUNELE9BQU07SUFDUixDQUFDO0lBRUQsNkJBQTZCLENBQUMsR0FBVyxFQUFFLEdBQVc7UUFDcEQsTUFBTSxDQUFDLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUE7UUFDbEMsTUFBTSxDQUFDLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUE7UUFDbEMsSUFBSSxDQUFDLEtBQUssU0FBUyxJQUFJLENBQUMsS0FBSyxTQUFTO1lBQUUsT0FBTyxDQUFDLENBQUE7UUFDaEQsSUFBSSxDQUFDLEtBQUssU0FBUztZQUFFLE9BQU8sQ0FBQyxDQUFDLENBQUE7UUFDOUIsSUFBSSxDQUFDLEtBQUssU0FBUztZQUFFLE9BQU8sQ0FBQyxDQUFBO1FBQzdCLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQTtJQUNkLENBQUM7SUFFRCxPQUFPO1FBQ0wsSUFBSSxJQUFJLENBQUMsUUFBUTtZQUFFLE9BQU07UUFDekIsSUFBSSxDQUFDLFFBQVEsR0FBRyxJQUFJLENBQUE7UUFDcEIsSUFBSSxJQUFJLENBQUMsS0FBSyxFQUFFLENBQUM7WUFDZixZQUFZLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFBO1lBQ3hCLElBQUksQ0FBQyxLQUFLLEdBQUcsU0FBUyxDQUFBO1FBQ3hCLENBQUM7UUFDRCxJQUFJLENBQUMsS0FBSyxDQUFDLEtBQUssRUFBRSxDQUFBO1FBQ2xCLElBQUksQ0FBQyxVQUFVLENBQUMsS0FBSyxFQUFFLENBQUE7UUFDdkIsSUFBSSxDQUFDLFVBQVUsQ0FBQyxLQUFLLEVBQUUsQ0FBQTtJQUN6QixDQUFDO0NBQ0YiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDdXN0b21Mb2dnZXIgfSBmcm9tICcuLi90eXBlcy9mdW5jdGlvbnMuanMnXHJcbmltcG9ydCB7IEl0ZW0gfSBmcm9tICcuLi90eXBlcy90eXBlcy5qcydcclxuXHJcbmV4cG9ydCBpbnRlcmZhY2UgTWVtb3J5Q2FjaGVPcHRpb25zIHtcclxuICBtYXhTaXplSW5NYjogbnVtYmVyXHJcbiAgdHRsbXM6IG51bWJlclxyXG59XHJcblxyXG5leHBvcnQgY2xhc3MgTWVtb3J5Q2FjaGVJdGVtIHtcclxuICBwcml2YXRlIGl0ZW06IEl0ZW1cclxuICBwcml2YXRlIGV4cGlyZXNBdDogbnVtYmVyIC8vIFRpbWVzdGFtcCBpbiBtc1xyXG5cclxuICBjb25zdHJ1Y3RvcihpdGVtOiBJdGVtLCBleHBpcmVzQXQ6IG51bWJlcikge1xyXG4gICAgdGhpcy5pdGVtID0gaXRlbVxyXG4gICAgdGhpcy5leHBpcmVzQXQgPSBleHBpcmVzQXRcclxuICB9XHJcblxyXG4gIGlzRXhwaXJlZChub3c6IG51bWJlcik6IGJvb2xlYW4ge1xyXG4gICAgcmV0dXJuIG5vdyA+IHRoaXMuZXhwaXJlc0F0XHJcbiAgfVxyXG4gIHNldEFjY2Vzcyhub3c6IG51bWJlciwgdHRsOiBudW1iZXIpOiB2b2lkIHtcclxuICAgIHRoaXMuZXhwaXJlc0F0ID0gbm93ICsgdHRsXHJcbiAgfVxyXG5cclxuICBnZXRJdGVtKCk6IEl0ZW0ge1xyXG4gICAgcmV0dXJuIHRoaXMuaXRlbVxyXG4gIH1cclxuXHJcbiAgZG9uZShub3c6IG51bWJlcik6IGJvb2xlYW4ge1xyXG4gICAgaWYgKHRoaXMuaXNFeHBpcmVkKG5vdykpIHtcclxuICAgICAgcmV0dXJuIHRydWVcclxuICAgIH1cclxuICAgIHJldHVybiBmYWxzZVxyXG4gIH1cclxufVxyXG5cclxuZXhwb3J0IGNsYXNzIE1lbW9yeUNhY2hlIHtcclxuICBwcml2YXRlIGlzR2F0aGVyZWQ6IE1hcDxzdHJpbmcsIGJvb2xlYW4+ID0gbmV3IE1hcCgpXHJcbiAgcHJpdmF0ZSByZWZlcmVuY2VzOiBNYXA8c3RyaW5nLCBudW1iZXI+ID0gbmV3IE1hcCgpXHJcbiAgcHJpdmF0ZSBjYWNoZTogTWFwPHN0cmluZywgTWVtb3J5Q2FjaGVJdGVtPiA9IG5ldyBNYXAoKVxyXG5cclxuICBwcml2YXRlIG9wdGlvbnM6IE1lbW9yeUNhY2hlT3B0aW9uc1xyXG4gIHByaXZhdGUgbG9nZ2VyOiBDdXN0b21Mb2dnZXJcclxuICBwcml2YXRlIGRpc3Bvc2VkID0gZmFsc2VcclxuICBwcml2YXRlIGN1cnJlbnRTaXplID0gMFxyXG4gIHByaXZhdGUgdGltZXI/OiBSZXR1cm5UeXBlPHR5cGVvZiBzZXRUaW1lb3V0PlxyXG5cclxuICBjb25zdHJ1Y3RvcihvcHRpb25zOiBNZW1vcnlDYWNoZU9wdGlvbnMsIGxvZ2dlcjogQ3VzdG9tTG9nZ2VyKSB7XHJcbiAgICB0aGlzLm9wdGlvbnMgPSBvcHRpb25zXHJcbiAgICB0aGlzLmxvZ2dlciA9IGxvZ2dlclxyXG4gICAgdGhpcy5yZXNldEdsb2JhbFRpbWVyKClcclxuICB9XHJcblxyXG4gIGFkZChpdGVtOiBJdGVtLCByZXF1ZXN0SXRlbTogKGlkOiBzdHJpbmcpID0+IHZvaWQsIHRlc3ROb3c/OiBudW1iZXIpOiB2b2lkIHtcclxuICAgIGlmICh0aGlzLmRpc3Bvc2VkKSB0aHJvdyBuZXcgRXJyb3IoJ01lbW9yeUNhY2hlIGlzIGRpc3Bvc2VkJylcclxuICAgIHRoaXMuY3VycmVudFNpemUgKz0gaXRlbS5zaXplIHx8IDBcclxuICAgIHRoaXMuY2FjaGUuc2V0KFxyXG4gICAgICBpdGVtLmJhc2VJZCxcclxuICAgICAgbmV3IE1lbW9yeUNhY2hlSXRlbShpdGVtLCAodGVzdE5vdyB8fCB0aGlzLm5vdygpKSArIHRoaXMub3B0aW9ucy50dGxtcylcclxuICAgIClcclxuXHJcbiAgICBpZiAoIXRoaXMuaXNHYXRoZXJlZC5oYXMoaXRlbS5iYXNlSWQpKSB7XHJcbiAgICAgIHRoaXMuaXNHYXRoZXJlZC5zZXQoaXRlbS5iYXNlSWQsIHRydWUpXHJcbiAgICAgIHRoaXMuc2NhbkZvclJlZmVyZW5jZXMoaXRlbS5iYXNlISwgcmVxdWVzdEl0ZW0pXHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBnZXQoaWQ6IHN0cmluZyk6IEl0ZW0gfCB1bmRlZmluZWQge1xyXG4gICAgaWYgKHRoaXMuZGlzcG9zZWQpIHRocm93IG5ldyBFcnJvcignTWVtb3J5Q2FjaGUgaXMgZGlzcG9zZWQnKVxyXG4gICAgY29uc3QgaXRlbSA9IHRoaXMuY2FjaGUuZ2V0KGlkKVxyXG4gICAgaWYgKGl0ZW0pIHtcclxuICAgICAgaXRlbS5zZXRBY2Nlc3ModGhpcy5ub3coKSwgdGhpcy5vcHRpb25zLnR0bG1zKVxyXG4gICAgICByZXR1cm4gaXRlbS5nZXRJdGVtKClcclxuICAgIH1cclxuICAgIHJldHVybiB1bmRlZmluZWRcclxuICB9XHJcblxyXG4gIHNjYW5Gb3JSZWZlcmVuY2VzKGRhdGE6IHVua25vd24sIHJlcXVlc3RJdGVtOiAoaWQ6IHN0cmluZykgPT4gdm9pZCk6IHZvaWQge1xyXG4gICAgY29uc3Qgc2NhbiA9IChpdGVtOiB1bmtub3duKTogdm9pZCA9PiB7XHJcbiAgICAgIC8vIFN0b3AgaWYgdGhlIGl0ZW0gaXMgbnVsbCBvciBub3QgYW4gb2JqZWN0IChpLmUuLCBwcmltaXRpdmUpXHJcbiAgICAgIGlmIChpdGVtID09PSBudWxsIHx8IHR5cGVvZiBpdGVtICE9PSAnb2JqZWN0Jykge1xyXG4gICAgICAgIHJldHVyblxyXG4gICAgICB9XHJcblxyXG4gICAgICAvLyBJZiBpdCdzIGFuIGFycmF5LCBzY2FuIGVhY2ggZWxlbWVudFxyXG4gICAgICBpZiAoQXJyYXkuaXNBcnJheShpdGVtKSkge1xyXG4gICAgICAgIGZvciAoY29uc3QgZWxlbWVudCBvZiBpdGVtKSB7XHJcbiAgICAgICAgICBzY2FuKGVsZW1lbnQpXHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVyblxyXG4gICAgICB9XHJcblxyXG4gICAgICAvLyBJZiBpdCdzIGFuIG9iamVjdCwgc2NhbiBpdHMgcHJvcGVydGllc1xyXG4gICAgICBmb3IgKGNvbnN0IGtleSBpbiBpdGVtKSB7XHJcbiAgICAgICAgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChpdGVtLCBrZXkpKSB7XHJcbiAgICAgICAgICAvLyBXZSBmb3VuZCB0aGUgdGFyZ2V0IHByb3BlcnR5IVxyXG4gICAgICAgICAgaWYgKGtleSA9PT0gJ3JlZmVyZW5jZWRJZCcpIHtcclxuICAgICAgICAgICAgY29uc3QgdmFsdWUgPSAoaXRlbSBhcyB7IHJlZmVyZW5jZWRJZDogdW5rbm93biB9KS5yZWZlcmVuY2VkSWRcclxuICAgICAgICAgICAgLy8gRW5zdXJlIHRoZSB2YWx1ZSBpcyBhIHN0cmluZyBiZWZvcmUgYWRkaW5nIGl0XHJcbiAgICAgICAgICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICdzdHJpbmcnKSB7XHJcbiAgICAgICAgICAgICAgdGhpcy5yZWZlcmVuY2VzLnNldCh2YWx1ZSwgKHRoaXMucmVmZXJlbmNlcy5nZXQodmFsdWUpIHx8IDApICsgMSlcclxuICAgICAgICAgICAgICBpZiAoIXRoaXMuY2FjaGUuaGFzKHZhbHVlKSkge1xyXG4gICAgICAgICAgICAgICAgcmVxdWVzdEl0ZW0odmFsdWUpXHJcbiAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgLy8gQ29udGludWUgc2Nhbm5pbmcgZGVlcGVyIGludG8gdGhlIG9iamVjdCdzIHByb3BlcnRpZXNcclxuICAgICAgICAgIHNjYW4oKGl0ZW0gYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj4pW2tleV0pXHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgc2NhbihkYXRhKVxyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSByZXNldEdsb2JhbFRpbWVyKCk6IHZvaWQge1xyXG4gICAgY29uc3QgcnVuID0gKCk6IHZvaWQgPT4ge1xyXG4gICAgICB0aGlzLmNsZWFuQ2FjaGUoKVxyXG4gICAgICB0aGlzLnRpbWVyID0gc2V0VGltZW91dChydW4sIHRoaXMub3B0aW9ucy50dGxtcylcclxuICAgIH1cclxuICAgIHRoaXMudGltZXIgPSBzZXRUaW1lb3V0KHJ1biwgdGhpcy5vcHRpb25zLnR0bG1zKVxyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBub3coKTogbnVtYmVyIHtcclxuICAgIHJldHVybiBEYXRlLm5vdygpXHJcbiAgfVxyXG5cclxuICBjbGVhbkNhY2hlKHRlc3ROb3c/OiBudW1iZXIpOiB2b2lkIHtcclxuICAgIGNvbnN0IG1heFNpemVCeXRlcyA9IHRoaXMub3B0aW9ucy5tYXhTaXplSW5NYiAqIDEwMjQgKiAxMDI0XHJcbiAgICBpZiAodGhpcy5jdXJyZW50U2l6ZSA8IG1heFNpemVCeXRlcykge1xyXG4gICAgICB0aGlzLmxvZ2dlcihcclxuICAgICAgICBgY2FjaGUgc2l6ZSAoJHt0aGlzLmN1cnJlbnRTaXplfSA8ICR7bWF4U2l6ZUJ5dGVzfSkgaXMgb2ssIG5vIG5lZWQgdG8gY2xlYW5gXHJcbiAgICAgIClcclxuICAgICAgcmV0dXJuXHJcbiAgICB9XHJcbiAgICBjb25zdCBub3cgPSB0ZXN0Tm93IHx8IHRoaXMubm93KClcclxuICAgIGxldCBjbGVhbmVkID0gMFxyXG4gICAgY29uc3Qgc3RhcnQgPSBwZXJmb3JtYW5jZS5ub3coKVxyXG4gICAgZm9yIChjb25zdCBkZWZlcnJlZEJhc2Ugb2YgQXJyYXkuZnJvbSh0aGlzLmNhY2hlLnZhbHVlcygpKVxyXG4gICAgICAuZmlsdGVyKCh4KSA9PiB4LmlzRXhwaXJlZChub3cpKVxyXG4gICAgICAuc29ydCgoYSwgYikgPT5cclxuICAgICAgICB0aGlzLmNvbXBhcmVNYXliZUJhc2VzQnlSZWZlcmVuY2VzKGEuZ2V0SXRlbSgpLmJhc2VJZCwgYi5nZXRJdGVtKCkuYmFzZUlkKVxyXG4gICAgICApKSB7XHJcbiAgICAgIGlmIChkZWZlcnJlZEJhc2UuZG9uZShub3cpKSB7XHJcbiAgICAgICAgY29uc3QgaWQgPSBkZWZlcnJlZEJhc2UuZ2V0SXRlbSgpLmJhc2VJZFxyXG4gICAgICAgIGNvbnN0IHJlZmVyZW5jZUNvdW50ID0gdGhpcy5yZWZlcmVuY2VzLmdldChpZCkgfHwgMFxyXG4gICAgICAgIGlmIChyZWZlcmVuY2VDb3VudCA+IDApIHtcclxuICAgICAgICAgIC8vIFNraXAgZXZpY3Rpb24gZm9yIGl0ZW1zIHdpdGggcmVmZXJlbmNlIGNvdW50cyBncmVhdGVyIHRoYW4gMCxcclxuICAgICAgICAgIC8vIGFzIHRoZXkgYXJlIHN0aWxsIGluIHVzZSBhbmQgc2hvdWxkIG5vdCBiZSByZW1vdmVkIGZyb20gdGhlIGNhY2hlLlxyXG4gICAgICAgICAgY29udGludWVcclxuICAgICAgICB9XHJcbiAgICAgICAgdGhpcy5jdXJyZW50U2l6ZSAtPSBkZWZlcnJlZEJhc2UuZ2V0SXRlbSgpLnNpemUgfHwgMFxyXG4gICAgICAgIHRoaXMuY2FjaGUuZGVsZXRlKGlkKVxyXG4gICAgICAgIGNsZWFuZWQrK1xyXG4gICAgICAgIGlmICh0aGlzLmN1cnJlbnRTaXplIDwgbWF4U2l6ZUJ5dGVzKSB7XHJcbiAgICAgICAgICBicmVha1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfVxyXG4gICAgdGhpcy5sb2dnZXIoXHJcbiAgICAgIGBjbGVhbmVkIGNhY2hlOiBjbGVhbmVkICR7Y2xlYW5lZH0sIGNhY2hlZCAke3RoaXMuY2FjaGUuc2l6ZX0sIHRpbWUgJHtcclxuICAgICAgICBwZXJmb3JtYW5jZS5ub3coKSAtIHN0YXJ0XHJcbiAgICAgIH1gXHJcbiAgICApXHJcbiAgICByZXR1cm5cclxuICB9XHJcblxyXG4gIGNvbXBhcmVNYXliZUJhc2VzQnlSZWZlcmVuY2VzKGlkMTogc3RyaW5nLCBpZDI6IHN0cmluZyk6IG51bWJlciB7XHJcbiAgICBjb25zdCBhID0gdGhpcy5yZWZlcmVuY2VzLmdldChpZDEpXHJcbiAgICBjb25zdCBiID0gdGhpcy5yZWZlcmVuY2VzLmdldChpZDIpXHJcbiAgICBpZiAoYSA9PT0gdW5kZWZpbmVkICYmIGIgPT09IHVuZGVmaW5lZCkgcmV0dXJuIDBcclxuICAgIGlmIChhID09PSB1bmRlZmluZWQpIHJldHVybiAtMVxyXG4gICAgaWYgKGIgPT09IHVuZGVmaW5lZCkgcmV0dXJuIDFcclxuICAgIHJldHVybiBhIC0gYlxyXG4gIH1cclxuXHJcbiAgZGlzcG9zZSgpOiB2b2lkIHtcclxuICAgIGlmICh0aGlzLmRpc3Bvc2VkKSByZXR1cm5cclxuICAgIHRoaXMuZGlzcG9zZWQgPSB0cnVlXHJcbiAgICBpZiAodGhpcy50aW1lcikge1xyXG4gICAgICBjbGVhclRpbWVvdXQodGhpcy50aW1lcilcclxuICAgICAgdGhpcy50aW1lciA9IHVuZGVmaW5lZFxyXG4gICAgfVxyXG4gICAgdGhpcy5jYWNoZS5jbGVhcigpXHJcbiAgICB0aGlzLmlzR2F0aGVyZWQuY2xlYXIoKVxyXG4gICAgdGhpcy5yZWZlcmVuY2VzLmNsZWFyKClcclxuICB9XHJcbn1cclxuIl19