UNPKG

ngx-store

Version:

Angular decorators to automagically keep variables in HTML5 LocalStorage, SessionStorage, cookies; injectable services for managing and listening to data changes and a bit more.

203 lines 31.7 kB
import { Config, debug } from '../config/config'; const isEqual = require('lodash.isequal'); export class Cache { static getCacheFor(cacheCandidate) { let cacheItem = Cache.get(cacheCandidate.key); if (!cacheItem) { cacheItem = new CacheItem(cacheCandidate); debug.log(`Created new CacheItem for ${cacheCandidate.name} for ${cacheItem.utilities[0].utility.getStorageName()}`); Cache.set(cacheItem); return cacheItem; } debug.log(`Loaded prior CacheItem of ${cacheItem.name} for ${cacheCandidate.utilities[0].utility.getStorageName()}`); cacheItem.addTargets(cacheCandidate.targets); cacheItem.addServices(cacheCandidate.services); cacheItem.addUtilities(cacheCandidate.utilities); Cache.set(cacheItem); return cacheItem; } static remove(cacheItem) { return Cache.items.delete(cacheItem.key); } static get(key) { return Cache.items.get(key); } static set(cacheItem) { if (!Cache.get(cacheItem.key)) { debug.log('CacheItem for ' + cacheItem.key, cacheItem); } Cache.items.set(cacheItem.key, cacheItem); } } Cache.items = new Map(); // tslint:disable:only-arrow-functions export class CacheItem { constructor(cacheItem) { this.name = ''; this.targets = []; this.services = []; this.utilities = []; this.currentTarget = {}; this.proxy = null; this._key = ''; this.initializedTargets = new Set(); this._key = cacheItem.key; this.name = cacheItem.name; this.addTargets(cacheItem.targets); this.addServices(cacheItem.services); this.addUtilities(cacheItem.utilities); } get key() { return this._key; } saveValue(value, config = {}) { debug.groupCollapsed('CacheItem#saveValue for ' + this.key + ' in ' + this.currentTarget.constructor.name); debug.log('new value: ', value); // if (value === false && this.readValue() === true) debugger; debug.log('previous value: ', this.readValue()); debug.log('targets.length: ', this.targets.length); debug.log('currentTarget:', this.currentTarget); debug.groupEnd(); // prevent overwriting value by initializators if (!this.initializedTargets.has(this.currentTarget)) { this.initializedTargets.add(this.currentTarget); let readValue = this.readValue(); if (config.migrateKey) { this.migrate(config, this.utilities[0].utility); readValue = this.readValue(); } const savedValue = (readValue !== null && readValue !== undefined) ? readValue : value; let proxy = this.getProxy(savedValue, config); proxy = (proxy !== null) ? proxy : value; debug.log('initial value for ' + this.key + ' in ' + this.currentTarget.constructor.name, proxy); this.propagateChange(savedValue); return proxy; } this.propagateChange(value); return this.getProxy(value, config); } getProxy(value, config = {}) { if (value === undefined && this.proxy) { return this.proxy; } // return cached proxy if value hasn't changed value = (value === undefined) ? this.readValue() : value; if (typeof value !== 'object' || value === null) { this.proxy = value; return value; } if ((!Config.mutateObjects && !config.mutate) || config.mutate === false) { return value; } const _self = this; // alias to use in standard function expressions const prototype = Object.assign(new value.constructor(), value.__proto__); prototype.save = function () { _self.saveValue(value, config); }; // TODO set prototype for Array.prototype or something if (Array.isArray(value)) { // handle methods that could change value of array const methodsToOverwrite = [ 'pop', 'push', 'reverse', 'shift', 'unshift', 'splice', 'filter', 'forEach', 'map', 'fill', 'sort', 'copyWithin', ]; for (const method of methodsToOverwrite) { prototype[method] = function () { const readValue = _self.readValue(); // @ts-ignore const result = Array.prototype[method].apply(readValue, arguments); debug.log('Saving value for ' + _self.key + ' by method ' + prototype.constructor.name + '.' + method); _self.saveValue(readValue, config); return result; }; } } Object.setPrototypeOf(value, prototype); this.proxy = value; return value; } readValue(config = {}) { const entry = this.utilities[0]; const value = entry ? entry.utility.get(this.key, entry.config) : null; return (typeof value !== 'object') ? value : JSON.parse(JSON.stringify(this.getProxy(value, entry.config))); } addTargets(targets) { targets.forEach(target => { if (this.targets.indexOf(target) === -1) { if (typeof target === 'object') { // handle Angular Component destruction const originalFunction = target.ngOnDestroy; const _self = this; target.ngOnDestroy = function () { if (typeof originalFunction === 'function') { originalFunction.apply(this, arguments); } target.ngOnDestroy = originalFunction || function () { }; _self.initializedTargets.delete(target); _self.targets = _self.targets.filter(t => t !== target); if (!_self.targets.length) { _self.services.forEach(service => { service.keys = service.keys.filter(key => key !== _self._key); }); _self.resetProxy(); Cache.remove(_self); } debug.groupCollapsed(`${_self.key} OnDestroy handler:`); debug.log('removed target:', target.constructor.name); debug.log('remaining targets:', _self.targets); debug.log('cacheItem:', Cache.get(_self.key)); debug.groupEnd(); }; this.targets.push(target); } } }); } addServices(services) { services.forEach(service => { if (this.services.indexOf(service) === -1) { service.keys.push(this._key); this.services.push(service); } }); } addUtilities(utilityEntries) { utilityEntries.forEach(entry => { if (this.utilities.findIndex(e => e.utility === entry.utility) === -1) { this.utilities.push(entry); entry.utility.set(this.key, this.readValue()); } }); } resetProxy() { this.proxy = null; } propagateChange(value, source) { if (isEqual(value, this.readValue())) { return; } this.utilities.forEach(entry => { const utility = entry.utility; // updating service which the change came from would affect in a cycle if (utility === source) { return; } debug.log(`propagating change on ${this.key} to:`, utility); utility.set(this._key, value, entry.config); }); } migrate(config, utility) { const prefix = (config.prefix || Config.prefix) || ''; const keyExists = (key) => key in utility.getStorage(); const migrateKey = keyExists(prefix + config.migrateKey) ? prefix + config.migrateKey : config.migrateKey; if (!keyExists(migrateKey)) { return; } debug.log('Migrating', migrateKey, 'to', config.key, 'in', utility.getStorageName()); const value = utility.get(migrateKey, Object.assign(Object.assign({}, config), { prefix: '' })); utility.set(this._key, value); utility.remove(migrateKey, { prefix: '' }); } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2FjaGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9uZ3gtc3RvcmUvc3JjL2xpYi9kZWNvcmF0b3IvY2FjaGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQU1qRCxNQUFNLE9BQU8sR0FBRyxPQUFPLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztBQUUxQyxNQUFNLE9BQU8sS0FBSztJQUdULE1BQU0sQ0FBQyxXQUFXLENBQUMsY0FBa0M7UUFDMUQsSUFBSSxTQUFTLEdBQUcsS0FBSyxDQUFDLEdBQUcsQ0FBQyxjQUFjLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDOUMsSUFBSSxDQUFDLFNBQVMsRUFBRTtZQUNkLFNBQVMsR0FBRyxJQUFJLFNBQVMsQ0FBQyxjQUFjLENBQUMsQ0FBQztZQUMxQyxLQUFLLENBQUMsR0FBRyxDQUFDLDZCQUE2QixjQUFjLENBQUMsSUFBSSxRQUFRLFNBQVMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLGNBQWMsRUFBRSxFQUFFLENBQUMsQ0FBQztZQUNySCxLQUFLLENBQUMsR0FBRyxDQUFDLFNBQVMsQ0FBQyxDQUFDO1lBQ3JCLE9BQU8sU0FBUyxDQUFDO1NBQ2xCO1FBQ0QsS0FBSyxDQUFDLEdBQUcsQ0FBQyw2QkFBNkIsU0FBUyxDQUFDLElBQUk7V0FDOUMsY0FBYyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsY0FBYyxFQUFFLEVBQUUsQ0FBQyxDQUFDO1FBQy9ELFNBQVMsQ0FBQyxVQUFVLENBQUMsY0FBYyxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQzdDLFNBQVMsQ0FBQyxXQUFXLENBQUMsY0FBYyxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQy9DLFNBQVMsQ0FBQyxZQUFZLENBQUMsY0FBYyxDQUFDLFNBQVMsQ0FBQyxDQUFD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QU0sQ0FBQyxVQUFXO1lBQzdCLENBQUMsQ0FBQyxNQUFNLENBQUMsVUFBVyxDQUFDO1FBQ3ZCLElBQUksQ0FBQyxTQUFTLENBQUMsVUFBVSxDQUFDLEVBQUU7WUFDMUIsT0FBTztTQUNSO1FBQ0QsS0FBSyxDQUFDLEdBQUcsQ0FBQyxXQUFXLEVBQUUsVUFBVSxFQUFFLElBQUksRUFBRSxNQUFNLENBQUMsR0FBRyxFQUFFLElBQUksRUFBRSxPQUFPLENBQUMsY0FBYyxFQUFFLENBQUMsQ0FBQztRQUNyRixNQUFNLEtBQUssR0FBRyxPQUFPLENBQUMsR0FBRyxDQUFDLFVBQVUsa0NBQU0sTUFBTSxLQUFFLE1BQU0sRUFBRSxFQUFFLElBQUUsQ0FBQztRQUMvRCxPQUFPLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFDOUIsT0FBTyxDQUFDLE1BQU0sQ0FBQyxVQUFVLEVBQUUsRUFBQyxNQUFNLEVBQUUsRUFBRSxFQUFDLENBQUMsQ0FBQztJQUMzQyxDQUFDO0NBQ0YiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb25maWcsIGRlYnVnIH0gZnJvbSAnLi4vY29uZmlnL2NvbmZpZyc7XG5pbXBvcnQgeyBDYWNoZUl0ZW1JbnRlcmZhY2UsIFV0aWxpdHlFbnRyeSB9IGZyb20gJy4vY2FjaGUuaW50ZXJmYWNlJztcbmltcG9ydCB7IFdlYlN0b3JhZ2VTZXJ2aWNlSW50ZXJmYWNlIH0gZnJvbSAnLi4vc2VydmljZS93ZWJzdG9yYWdlLmludGVyZmFjZSc7XG5pbXBvcnQgeyBEZWNvcmF0b3JDb25maWcgfSBmcm9tICcuLi9uZ3gtc3RvcmUudHlwZXMnO1xuaW1wb3J0IHsgV2ViU3RvcmFnZVV0aWxpdHkgfSBmcm9tICcuLi91dGlsaXR5L3dlYnN0b3JhZ2UudXRpbGl0eSc7XG5cbmNvbnN0IGlzRXF1YWwgPSByZXF1aXJlKCdsb2Rhc2guaXNlcXVhbCcpO1xuXG5leHBvcnQgY2xhc3MgQ2FjaGUge1xuICBwdWJsaWMgc3RhdGljIGl0ZW1zOiBNYXA8c3RyaW5nLCBDYWNoZUl0ZW0+ID0gbmV3IE1hcCgpO1xuXG4gIHB1YmxpYyBzdGF0aWMgZ2V0Q2FjaGVGb3IoY2FjaGVDYW5kaWRhdGU6IENhY2hlSXRlbUludGVyZmFjZSk6IENhY2hlSXRlbSB7XG4gICAgbGV0IGNhY2hlSXRlbSA9IENhY2hlLmdldChjYWNoZUNhbmRpZGF0ZS5rZXkpO1xuICAgIGlmICghY2FjaGVJdGVtKSB7XG4gICAgICBjYWNoZUl0ZW0gPSBuZXcgQ2FjaGVJdGVtKGNhY2hlQ2FuZGlkYXRlKTtcbiAgICAgIGRlYnVnLmxvZyhgQ3JlYXRlZCBuZXcgQ2FjaGVJdGVtIGZvciAke2NhY2hlQ2FuZGlkYXRlLm5hbWV9IGZvciAke2NhY2hlSXRlbS51dGlsaXRpZXNbMF0udXRpbGl0eS5nZXRTdG9yYWdlTmFtZSgpfWApO1xuICAgICAgQ2FjaGUuc2V0KGNhY2hlSXRlbSk7XG4gICAgICByZXR1cm4gY2FjaGVJdGVtO1xuICAgIH1cbiAgICBkZWJ1Zy5sb2coYExvYWRlZCBwcmlvciBDYWNoZUl0ZW0gb2YgJHtjYWNoZUl0ZW0ubmFtZX1cbiAgICAgZm9yICR7Y2FjaGVDYW5kaWRhdGUudXRpbGl0aWVzWzBdLnV0aWxpdHkuZ2V0U3RvcmFnZU5hbWUoKX1gKTtcbiAgICBjYWNoZUl0ZW0uYWRkVGFyZ2V0cyhjYWNoZUNhbmRpZGF0ZS50YXJnZXRzKTtcbiAgICBjYWNoZUl0ZW0uYWRkU2VydmljZXMoY2FjaGVDYW5kaWRhdGUuc2VydmljZXMpO1xuICAgIGNhY2hlSXRlbS5hZGRVdGlsaXRpZXMoY2FjaGVDYW5kaWRhdGUudXRpbGl0aWVzKTtcbiAgICBDYWNoZS5zZXQoY2FjaGVJdGVtKTtcbiAgICByZXR1cm4gY2FjaGVJdGVtO1xuICB9XG5cbiAgcHVibGljIHN0YXRpYyByZW1vdmUoY2FjaGVJdGVtOiBDYWNoZUl0ZW0pOiBib29sZWFuIHtcbiAgICByZXR1cm4gQ2FjaGUuaXRlbXMuZGVsZXRlKGNhY2hlSXRlbS5rZXkpO1xuICB9XG5cbiAgcHVibGljIHN0YXRpYyBnZXQoa2V5OiBzdHJpbmcpOiBDYWNoZUl0ZW0ge1xuICAgIHJldHVybiBDYWNoZS5pdGVtcy5nZXQoa2V5KSBhcyBDYWNoZUl0ZW07XG4gIH1cblxuICBwcm90ZWN0ZWQgc3RhdGljIHNldChjYWNoZUl0ZW06IENhY2hlSXRlbSk6IHZvaWQge1xuICAgIGlmICghQ2FjaGUuZ2V0KGNhY2hlSXRlbS5rZXkpKSB7XG4gICAgICBkZWJ1Zy5sb2coJ0NhY2hlSXRlbSBmb3IgJyArIGNhY2hlSXRlbS5rZXksIGNhY2hlSXRlbSk7XG4gICAgfVxuICAgIENhY2hlLml0ZW1zLnNldChjYWNoZUl0ZW0ua2V5LCBjYWNoZUl0ZW0pO1xuICB9XG59XG5cbi8vIHRzbGludDpkaXNhYmxlOm9ubHktYXJyb3ctZnVuY3Rpb25zXG5leHBvcnQgY2xhc3MgQ2FjaGVJdGVtIGltcGxlbWVudHMgQ2FjaGVJdGVtSW50ZXJmYWNlIHtcbiAgcHVibGljIG5hbWU6IHN0cmluZyA9ICcnO1xuICBwdWJsaWMgdGFyZ2V0czogQXJyYXk8b2JqZWN0PiA9IFtdO1xuICBwdWJsaWMgc2VydmljZXM6IEFycmF5PFdlYlN0b3JhZ2VTZXJ2aWNlSW50ZXJmYWNlPiA9IFtdO1xuICBwdWJsaWMgdXRpbGl0aWVzOiBBcnJheTxVdGlsaXR5RW50cnk+ID0gW107XG4gIHB1YmxpYyBjdXJyZW50VGFyZ2V0OiBvYmplY3QgPSB7fTtcbiAgcHJvdGVjdGVkIHByb3h5OiBhbnkgPSBudWxsO1xuICBwcm90ZWN0ZWQgX2tleTogc3RyaW5nID0gJyc7XG4gIHByb3RlY3RlZCBpbml0aWFsaXplZFRhcmdldHM6IFNldDxvYmplY3Q+ID0gbmV3IFNldCgpO1xuXG4gIGNvbnN0cnVjdG9yKGNhY2hlSXRlbTogQ2FjaGVJdGVtSW50ZXJmYWNlKSB7XG4gICAgdGhpcy5fa2V5ID0gY2FjaGVJdGVtLmtleTtcbiAgICB0aGlzLm5hbWUgPSBjYWNoZUl0ZW0ubmFtZTtcbiAgICB0aGlzLmFkZFRhcmdldHMoY2FjaGVJdGVtLnRhcmdldHMpO1xuICAgIHRoaXMuYWRkU2VydmljZXMoY2FjaGVJdGVtLnNlcnZpY2VzKTtcbiAgICB0aGlzLmFkZFV0aWxpdGllcyhjYWNoZUl0ZW0udXRpbGl0aWVzKTtcbiAgfVxuXG4gIHB1YmxpYyBnZXQga2V5KCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMuX2tleTtcbiAgfVxuXG4gIHB1YmxpYyBzYXZlVmFsdWUodmFsdWU6IGFueSwgY29uZmlnOiBEZWNvcmF0b3JDb25maWcgPSB7fSk6IGFueSB7XG4gICAgZGVidWcuZ3JvdXBDb2xsYXBzZWQoJ0NhY2hlSXRlbSNzYXZlVmFsdWUgZm9yICcgKyB0aGlzLmtleSArICcgaW4gJyArIHRoaXMuY3VycmVudFRhcmdldC5jb25zdHJ1Y3Rvci5uYW1lKTtcbiAgICBkZWJ1Zy5sb2coJ25ldyB2YWx1ZTogJywgdmFsdWUpO1xuICAgIC8vIGlmICh2YWx1ZSA9PT0gZmFsc2UgJiYgdGhpcy5yZWFkVmFsdWUoKSA9PT0gdHJ1ZSkgZGVidWdnZXI7XG4gICAgZGVidWcubG9nKCdwcmV2aW91cyB2YWx1ZTogJywgdGhpcy5yZWFkVmFsdWUoKSk7XG4gICAgZGVidWcubG9nKCd0YXJnZXRzLmxlbmd0aDogJywgdGhpcy50YXJnZXRzLmxlbmd0aCk7XG4gICAgZGVidWcubG9nKCdjdXJyZW50VGFyZ2V0OicsIHRoaXMuY3VycmVudFRhcmdldCk7XG4gICAgZGVidWcuZ3JvdXBFbmQoKTtcblxuICAgIC8vIHByZXZlbnQgb3ZlcndyaXRpbmcgdmFsdWUgYnkgaW5pdGlhbGl6YXRvcnNcbiAgICBpZiAoIXRoaXMuaW5pdGlhbGl6ZWRUYXJnZXRzLmhhcyh0aGlzLmN1cnJlbnRUYXJnZXQpKSB7XG4gICAgICB0aGlzLmluaXRpYWxpemVkVGFyZ2V0cy5hZGQodGhpcy5jdXJyZW50VGFyZ2V0KTtcbiAgICAgIGxldCByZWFkVmFsdWUgPSB0aGlzLnJlYWRWYWx1ZSgpO1xuICAgICAgaWYgKGNvbmZpZy5taWdyYXRlS2V5KSB7XG4gICAgICAgIHRoaXMubWlncmF0ZShjb25maWcsIHRoaXMudXRpbGl0aWVzWzBdLnV0aWxpdHkpO1xuICAgICAgICByZWFkVmFsdWUgPSB0aGlzLnJlYWRWYWx1ZSgpO1xuICAgICAgfVxuICAgICAgY29uc3Qgc2F2ZWRWYWx1ZSA9IChyZWFkVmFsdWUgIT09IG51bGwgJiYgcmVhZFZhbHVlICE9PSB1bmRlZmluZWQpID8gcmVhZFZhbHVlIDogdmFsdWU7XG4gICAgICBsZXQgcHJveHkgPSB0aGlzLmdldFByb3h5KHNhdmVkVmFsdWUsIGNvbmZpZyk7XG4gICAgICBwcm94eSA9IChwcm94eSAhPT0gbnVsbCkgPyBwcm94eSA6IHZhbHVlO1xuICAgICAgZGVidWcubG9nKCdpbml0aWFsIHZhbHVlIGZvciAnICsgdGhpcy5rZXkgKyAnIGluICcgKyB0aGlzLmN1cnJlbnRUYXJnZXQuY29uc3RydWN0b3IubmFtZSwgcHJveHkpO1xuICAgICAgdGhpcy5wcm9wYWdhdGVDaGFuZ2Uoc2F2ZWRWYWx1ZSk7XG4gICAgICByZXR1cm4gcHJveHk7XG4gICAgfVxuICAgIHRoaXMucHJvcGFnYXRlQ2hhbmdlKHZhbHVlKTtcbiAgICByZXR1cm4gdGhpcy5nZXRQcm94eSh2YWx1ZSwgY29uZmlnKTtcbiAgfVxuXG4gIHB1YmxpYyBnZXRQcm94eSh2YWx1ZT86IGFueSwgY29uZmlnOiBEZWNvcmF0b3JDb25maWcgPSB7fSk6IGFueSB7XG4gICAgaWYgKHZhbHVlID09PSB1bmRlZmluZWQgJiYgdGhpcy5wcm94eSkge1xuICAgICAgcmV0dXJuIHRoaXMucHJveHk7XG4gICAgfSAvLyByZXR1cm4gY2FjaGVkIHByb3h5IGlmIHZhbHVlIGhhc24ndCBjaGFuZ2VkXG4gICAgdmFsdWUgPSAodmFsdWUgPT09IHVuZGVmaW5lZCkgPyB0aGlzLnJlYWRWYWx1ZSgpIDogdmFsdWU7XG4gICAgaWYgKHR5cGVvZiB2YWx1ZSAhPT0gJ29iamVjdCcgfHwgdmFsdWUgPT09IG51bGwpIHtcbiAgICAgIHRoaXMucHJveHkgPSB2YWx1ZTtcbiAgICAgIHJldHVybiB2YWx1ZTtcbiAgICB9XG4gICAgaWYgKCghQ29uZmlnLm11dGF0ZU9iamVjdHMgJiYgIWNvbmZpZy5tdXRhdGUpIHx8IGNvbmZpZy5tdXRhdGUgPT09IGZhbHNlKSB7XG4gICAgICByZXR1cm4gdmFsdWU7XG4gICAgfVxuXG4gICAgY29uc3QgX3NlbGYgPSB0aGlzOyAvLyBhbGlhcyB0byB1c2UgaW4gc3RhbmRhcmQgZnVuY3Rpb24gZXhwcmVzc2lvbnNcbiAgICBjb25zdCBwcm90b3R5cGU6IGFueSA9IE9iamVjdC5hc3NpZ24obmV3IHZhbHVlLmNvbnN0cnVjdG9yKCksIHZhbHVlLl9fcHJvdG9fXyk7XG5cbiAgICBwcm90b3R5cGUuc2F2ZSA9IGZ1bmN0aW9uKCk6IHZvaWQgeyAvLyBhZGQgbWV0aG9kIGZvciB0cmlnZ2VyaW5nIGZvcmNlIHNhdmVcbiAgICAgIF9zZWxmLnNhdmVWYWx1ZSh2YWx1ZSwgY29uZmlnKTtcbiAgICB9O1xuXG4gICAgLy8gVE9ETyBzZXQgcHJvdG90eXBlIGZvciBBcnJheS5wcm90b3R5cGUgb3Igc29tZXRoaW5nXG4gICAgaWYgKEFycmF5LmlzQXJyYXkodmFsdWUpKSB7IC8vIGhhbmRsZSBtZXRob2RzIHRoYXQgY291bGQgY2hhbmdlIHZhbHVlIG9mIGFycmF5XG4gICAgICBjb25zdCBtZXRob2RzVG9PdmVyd3JpdGUgPSBbXG4gICAgICAgICdwb3AnLCAncHVzaCcsICdyZXZlcnNlJywgJ3NoaWZ0JywgJ3Vuc2hpZnQnLCAnc3BsaWNlJyxcbiAgICAgICAgJ2ZpbHRlcicsICdmb3JFYWNoJywgJ21hcCcsICdmaWxsJywgJ3NvcnQnLCAnY29weVdpdGhpbicsXG4gICAgICBdO1xuICAgICAgZm9yIChjb25zdCBtZXRob2Qgb2YgbWV0aG9kc1RvT3ZlcndyaXRlKSB7XG4gICAgICAgIHByb3RvdHlwZVttZXRob2RdID0gZnVuY3Rpb24oKTogdm9pZCB7XG4gICAgICAgICAgY29uc3QgcmVhZFZhbHVlID0gX3NlbGYucmVhZFZhbHVlKCk7XG4gICAgICAgICAgLy8gQHRzLWlnbm9yZVxuICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IEFycmF5LnByb3RvdHlwZVttZXRob2RdLmFwcGx5KHJlYWRWYWx1ZSwgYXJndW1lbnRzKTtcbiAgICAgICAgICBkZWJ1Zy5sb2coJ1NhdmluZyB2YWx1ZSBmb3IgJyArIF9zZWxmLmtleSArICcgYnkgbWV0aG9kICdcbiAgICAgICAgICAgICsgcHJvdG90eXBlLmNvbnN0cnVjdG9yLm5hbWUgKyAnLicgKyBtZXRob2QpO1xuICAgICAgICAgIF9zZWxmLnNhdmVWYWx1ZShyZWFkVmFsdWUsIGNvbmZpZyk7XG4gICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgfTtcbiAgICAgIH1cbiAgICB9XG4gICAgT2JqZWN0LnNldFByb3RvdHlwZU9mKHZhbHVlLCBwcm90b3R5cGUpO1xuICAgIHRoaXMucHJveHkgPSB2YWx1ZTtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBwdWJsaWMgcmVhZFZhbHVlKGNvbmZpZzogRGVjb3JhdG9yQ29uZmlnID0ge30pOiBhbnkge1xuICAgIGNvbnN0IGVudHJ5ID0gdGhpcy51dGlsaXRpZXNbMF07XG4gICAgY29uc3QgdmFsdWUgPSBlbnRyeSA/IGVudHJ5LnV0aWxpdHkuZ2V0KHRoaXMua2V5LCBlbnRyeS5jb25maWcpIDogbnVsbDtcbiAgICByZXR1cm4gKHR5cGVvZiB2YWx1ZSAhPT0gJ29iamVjdCcpID8gdmFsdWUgOiBKU09OLnBhcnNlKEpTT04uc3RyaW5naWZ5KHRoaXMuZ2V0UHJveHkodmFsdWUsIGVudHJ5LmNvbmZpZykpKTtcbiAgfVxuXG4gIHB1YmxpYyBhZGRUYXJnZXRzKHRhcmdldHM6IEFycmF5PGFueT4pOiB2b2lkIHtcbiAgICB0YXJnZXRzLmZvckVhY2godGFyZ2V0ID0+IHtcbiAgICAgIGlmICh0aGlzLnRhcmdldHMuaW5kZXhPZih0YXJnZXQpID09PSAtMSkge1xuICAgICAgICBpZiAodHlwZW9mIHRhcmdldCA9PT0gJ29iamVjdCcpIHsgLy8gaGFuZGxlIEFuZ3VsYXIgQ29tcG9uZW50IGRlc3RydWN0aW9uXG4gICAgICAgICAgY29uc3Qgb3JpZ2luYWxGdW5jdGlvbiA9IHRhcmdldC5uZ09uRGVzdHJveTtcbiAgICAgICAgICBjb25zdCBfc2VsZiA9IHRoaXM7XG4gICAgICAgICAgdGFyZ2V0Lm5nT25EZXN0cm95ID0gZnVuY3Rpb24oKTogYW55IHtcbiAgICAgICAgICAgIGlmICh0eXBlb2Ygb3JpZ2luYWxGdW5jdGlvbiA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgICBvcmlnaW5hbEZ1bmN0aW9uLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0YXJnZXQubmdPbkRlc3Ryb3kgPSBvcmlnaW5hbEZ1bmN0aW9uIHx8IGZ1bmN0aW9uKCk6IGFueSB7fTtcblxuICAgICAgICAgICAgX3NlbGYuaW5pdGlhbGl6ZWRUYXJnZXRzLmRlbGV0ZSh0YXJnZXQpO1xuICAgICAgICAgICAgX3NlbGYudGFyZ2V0cyA9IF9zZWxmLnRhcmdldHMuZmlsdGVyKHQgPT4gdCAhPT0gdGFyZ2V0KTtcbiAgICAgICAgICAgIGlmICghX3NlbGYudGFyZ2V0cy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgX3NlbGYuc2VydmljZXMuZm9yRWFjaChzZXJ2aWNlID0+IHtcbiAgICAgICAgICAgICAgICBzZXJ2aWNlLmtleXMgPSBzZXJ2aWNlLmtleXMuZmlsdGVyKGtleSA9PiBrZXkgIT09IF9zZWxmLl9rZXkpO1xuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgX3NlbGYucmVzZXRQcm94eSgpO1xuICAgICAgICAgICAgICBDYWNoZS5yZW1vdmUoX3NlbGYpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZGVidWcuZ3JvdXBDb2xsYXBzZWQoYCR7X3NlbGYua2V5fSBPbkRlc3Ryb3kgaGFuZGxlcjpgKTtcbiAgICAgICAgICAgIGRlYnVnLmxvZygncmVtb3ZlZCB0YXJnZXQ6JywgdGFyZ2V0LmNvbnN0cnVjdG9yLm5hbWUpO1xuICAgICAgICAgICAgZGVidWcubG9nKCdyZW1haW5pbmcgdGFyZ2V0czonLCBfc2VsZi50YXJnZXRzKTtcbiAgICAgICAgICAgIGRlYnVnLmxvZygnY2FjaGVJdGVtOicsIENhY2hlLmdldChfc2VsZi5rZXkpKTtcbiAgICAgICAgICAgIGRlYnVnLmdyb3VwRW5kKCk7XG4gICAgICAgICAgfTtcbiAgICAgICAgICB0aGlzLnRhcmdldHMucHVzaCh0YXJnZXQpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICBwdWJsaWMgYWRkU2VydmljZXMoc2VydmljZXM6IEFycmF5PFdlYlN0b3JhZ2VTZXJ2aWNlSW50ZXJmYWNlPik6IHZvaWQge1xuICAgIHNlcnZpY2VzLmZvckVhY2goc2VydmljZSA9PiB7XG4gICAgICBpZiAodGhpcy5zZXJ2aWNlcy5pbmRleE9mKHNlcnZpY2UpID09PSAtMSkge1xuICAgICAgICBzZXJ2aWNlLmtleXMucHVzaCh0aGlzLl9rZXkpO1xuICAgICAgICB0aGlzLnNlcnZpY2VzLnB1c2goc2VydmljZSk7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICBwdWJsaWMgYWRkVXRpbGl0aWVzKHV0aWxpdHlFbnRyaWVzOiBBcnJheTxVdGlsaXR5RW50cnk+KTogdm9pZCB7XG4gICAgdXRpbGl0eUVudHJpZXMuZm9yRWFjaChlbnRyeSA9PiB7XG4gICAgICBpZiAodGhpcy51dGlsaXRpZXMuZmluZEluZGV4KGUgPT4gZS51dGlsaXR5ID09PSBlbnRyeS51dGlsaXR5KSA9PT0gLTEpIHtcbiAgICAgICAgdGhpcy51dGlsaXRpZXMucHVzaChlbnRyeSk7XG4gICAgICAgIGVudHJ5LnV0aWxpdHkuc2V0KHRoaXMua2V5LCB0aGlzLnJlYWRWYWx1ZSgpKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIHB1YmxpYyByZXNldFByb3h5KCk6IHZvaWQge1xuICAgIHRoaXMucHJveHkgPSBudWxsO1xuICB9XG5cbiAgcHVibGljIHByb3BhZ2F0ZUNoYW5nZSh2YWx1ZTogYW55LCBzb3VyY2U/OiBXZWJTdG9yYWdlVXRpbGl0eSk6IHZvaWQge1xuICAgIGlmIChpc0VxdWFsKHZhbHVlLCB0aGlzLnJlYWRWYWx1ZSgpKSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB0aGlzLnV0aWxpdGllcy5mb3JFYWNoKGVudHJ5ID0+IHtcbiAgICAgIGNvbnN0IHV0aWxpdHkgPSBlbnRyeS51dGlsaXR5O1xuICAgICAgLy8gdXBkYXRpbmcgc2VydmljZSB3aGljaCB0aGUgY2hhbmdlIGNhbWUgZnJvbSB3b3VsZCBhZmZlY3QgaW4gYSBjeWNsZVxuICAgICAgaWYgKHV0aWxpdHkgPT09IHNvdXJjZSkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICBkZWJ1Zy5sb2coYHByb3BhZ2F0aW5nIGNoYW5nZSBvbiAke3RoaXMua2V5fSB0bzpgLCB1dGlsaXR5KTtcbiAgICAgIHV0aWxpdHkuc2V0KHRoaXMuX2tleSwgdmFsdWUsIGVudHJ5LmNvbmZpZyk7XG4gICAgfSk7XG4gIH1cblxuICBwcm90ZWN0ZWQgbWlncmF0ZShjb25maWc6IERlY29yYXRvckNvbmZpZywgdXRpbGl0eTogV2ViU3RvcmFnZVV0aWxpdHkpOiB2b2lkIHtcbiAgICBjb25zdCBwcmVmaXggPSAoY29uZmlnLnByZWZpeCB8fCBDb25maWcucHJlZml4KSB8fCAnJztcbiAgICBjb25zdCBrZXlFeGlzdHMgPSAoa2V5OiBzdHJpbmcpOiBib29sZWFuID0+IGtleSBpbiB1dGlsaXR5LmdldFN0b3JhZ2UoKTtcbiAgICBjb25zdCBtaWdyYXRlS2V5ID0ga2V5RXhpc3RzKHByZWZpeCArIGNvbmZpZy5taWdyYXRlS2V5ISlcbiAgICAgID8gcHJlZml4ICsgY29uZmlnLm1pZ3JhdGVLZXkhXG4gICAgICA6IGNvbmZpZy5taWdyYXRlS2V5ITtcbiAgICBpZiAoIWtleUV4aXN0cyhtaWdyYXRlS2V5KSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBkZWJ1Zy5sb2coJ01pZ3JhdGluZycsIG1pZ3JhdGVLZXksICd0bycsIGNvbmZpZy5rZXksICdpbicsIHV0aWxpdHkuZ2V0U3RvcmFnZU5hbWUoKSk7XG4gICAgY29uc3QgdmFsdWUgPSB1dGlsaXR5LmdldChtaWdyYXRlS2V5LCB7Li4uY29uZmlnLCBwcmVmaXg6ICcnfSk7XG4gICAgdXRpbGl0eS5zZXQodGhpcy5fa2V5LCB2YWx1ZSk7XG4gICAgdXRpbGl0eS5yZW1vdmUobWlncmF0ZUtleSwge3ByZWZpeDogJyd9KTtcbiAgfVxufVxuIl19