UNPKG

@synerty/vortexjs

Version:

Custom observable data serialisation and routing based on Angular 2+

281 lines 36.2 kB
import { Subject } from "rxjs"; import { Payload } from "./Payload"; import { PayloadEndpoint } from "./PayloadEndpoint"; import { EventEmitter } from "@angular/core"; import { SERVER_RESPONSE_TIMEOUT_SECONDS, } from "./VortexClientABC"; import { plDeleteKey } from "./PayloadFilterKeys"; import { bind, dateStr } from "./UtilMisc"; import deepEqual from "deep-equal"; import { PayloadEnvelope } from "./PayloadEnvelope"; import { first, takeUntil } from "rxjs/operators"; // ------------------ // Some private structures export var TupleLoaderEventEnum; (function (TupleLoaderEventEnum) { TupleLoaderEventEnum[TupleLoaderEventEnum["Load"] = 0] = "Load"; TupleLoaderEventEnum[TupleLoaderEventEnum["Save"] = 1] = "Save"; TupleLoaderEventEnum[TupleLoaderEventEnum["Delete"] = 2] = "Delete"; })(TupleLoaderEventEnum || (TupleLoaderEventEnum = {})); /** * TupleLoader for Angular2 + Synerty Vortex * * @param: vortex The vortex instance to send via. * * @param: component The component to register our events on. * * @param: filterUpdateCallable A IFilterUpdateCallable callable that returns null * or an IPayloadFilter * * Manual changes can be triggerd as follows. * * "load()" * * "save()" * * "del()" */ export class TupleLoader { vortex; vortexStatusService; component; event = new EventEmitter(); filterUpdateCallable; lastPayloadFilt = null; lastTuples = null; timer = null; lastPromise = null; endpoint = null; constructor(vortex, vortexStatusService, component, filterUpdateCallable) { this.vortex = vortex; this.vortexStatusService = vortexStatusService; this.component = component; if (filterUpdateCallable instanceof Function) { this.filterUpdateCallable = filterUpdateCallable; } else { this.filterUpdateCallable = () => { return filterUpdateCallable; }; } // Regiseter for the angular docheck this.component.doCheckEvent .pipe(takeUntil(this.component.onDestroyEvent)) .subscribe(() => this.filterChangeCheck()); // Create the observable object this._observable = new Subject(); // Remove all observers when the component is destroyed. this.component.onDestroyEvent .pipe(first()) .subscribe(() => this._observable.complete()); } _observable; /** * @property: The tuple observable to subscribe to. */ get observable() { return this._observable; } filterChangeCheck() { if (!this.vortexStatusService.snapshot.isOnline) { return; } // Create a copy let newFilter = Object.assign({}, this.filterUpdateCallable()); if (newFilter == null) { if (this.endpoint != null) { this.endpoint.shutdown(); this.endpoint = null; } this.lastTuples = null; this.lastPayloadFilt = null; return; } if (this.lastPayloadFilt != null && deepEqual(newFilter, this.lastPayloadFilt, { strict: true })) { return; } this.lastPayloadFilt = newFilter; this.endpoint = new PayloadEndpoint(this.component, this.lastPayloadFilt, true); this.endpoint.observable.subscribe((payloadEnvelope) => { this.processPayloadEnvelope(payloadEnvelope); }); this.vortex.send(new PayloadEnvelope(this.lastPayloadFilt)); } /** * Load Loads the data from a server * * @returns: Promise<Payload>, which is called when the load succeeds or fails. * */ load() { return this.saveOrLoad(TupleLoaderEventEnum.Load); } /** * Save * * Collects the data from the form, into the tuple and sends it through the * vortex. * * @param: tuples The tuples to save, if tuples is null, the last loaded tuples will * be used. * * @returns: Promise, which is called when the save succeeds or fails. * */ save(tuples = null) { return this.saveOrLoad(TupleLoaderEventEnum.Save, tuples); } /** * Delete * * Sends the tuples to the server for it to delete them. * * @returns :Promise, which is called when the save succeeds or fails. * */ del(tuples = null) { let promise = this.saveOrLoad(TupleLoaderEventEnum.Delete, tuples); return promise; } saveOrLoad(type, tuples = null) { // I'm not sure if the promise is set straight away, so at least null out // the last one. this.lastPromise = null; // Initialise the promise let promise = new Promise((resolve, reject) => (this.lastPromise = { type: type, resolve: resolve, reject: reject, })); // Check if there is already a load or save in progress if (this.setupTimer() !== true) { setTimeout(() => { this.lastPromise.reject("Another save or load is still in progress."); this.lastPromise = null; }, 0); return promise; } if (type === TupleLoaderEventEnum.Load) { // Force a filter update and reload this.lastPayloadFilt = null; this.filterChangeCheck(); // If there was no filter update, fail if (this.lastPayloadFilt == null) { this.lastPromise.reject("There is no payload filter provided, load failed"); this.lastPromise = null; return promise; } } else if (type === TupleLoaderEventEnum.Save) { if (tuples != null) { this.lastTuples = tuples; } // Check if we have tuples to save. if (this.lastTuples == null) { this.lastPromise.reject("No tuples to save. " + " Provide one to with the save(tuples) call or load some first " + " with the filterUpdateCallable"); this.lastPromise = null; return promise; } // Save the tuples new Payload(this.lastPayloadFilt, this.lastTuples) .makePayloadEnvelope() .then((pe) => this.vortex.send(pe)) .catch((e) => `TupleLoader, failed to save tuples ${e}`); } else if (type === TupleLoaderEventEnum.Delete) { // Check if we have tuples to save. if (tuples == null || tuples.length == null) { this.lastPromise.reject("No tuples to delete. " + " Provide one or more with the del(tuples) call"); this.lastPromise = null; return promise; } // Set the delete key. The server will delete objects with this set. let filt = Object.assign({}, this.lastPayloadFilt); filt[plDeleteKey] = true; // Save the tuples new Payload(filt, tuples) .makePayloadEnvelope() .then((pe) => this.vortex.send(pe)) .catch((e) => `TupleLoader, failed to delete tuples ${e}`); } else { throw new Error(`Type ${type} is not implemented.`); } // Return the promise return promise; } processPayloadEnvelope(payloadEnvelope) { if (this.timer) { clearTimeout(this.timer); this.timer = null; } // No result, means this was a load if (payloadEnvelope.result == null) { try { this.event.emit(TupleLoaderEventEnum.Load); } catch (e) { console.log(`${dateStr()} TupleLoader - Load event emit error`); console.error(e); } // Result, means this was a save } else if (payloadEnvelope.result === true) { try { if (payloadEnvelope.filt.hasOwnProperty(plDeleteKey)) { this.event.emit(TupleLoaderEventEnum.Delete); } else { this.event.emit(TupleLoaderEventEnum.Save); } } catch (e) { console.log(`${dateStr()} TupleLoader - Save/Delete event emit error`); console.error(e); } // Else, treat this as a failure } else { if (this.lastPromise) { this.lastPromise.reject(payloadEnvelope.result.toString()); this.lastPromise = null; } this.vortexStatusService.logError(payloadEnvelope.result.toString()); return; } if (this.lastPromise) { this.lastPromise.resolve(payloadEnvelope); this.lastPromise = null; } payloadEnvelope .decodePayload() .then((payload) => { this.lastTuples = payload.tuples; this._observable.next(payload.tuples); }) .catch((e) => console.log(`${dateStr()} TupleLoader failed to decode payload ${e}`)); } resetTimer() { this.operationTimeout(false); } setupTimer() { let self = this; if (self.timer != null) { this.vortexStatusService.logWarning("We're already processing a request, Action failed"); return false; } self.timer = setTimeout(bind(self, self.operationTimeout), SERVER_RESPONSE_TIMEOUT_SECONDS * 1000); return true; } operationTimeout(showBaloon = true) { this.timer = null; let msg = "The server failed to respond, operaton timed out"; if (this.lastPromise) { msg = `${this.lastPromise.type} Failed, Response Timed out`; this.lastPromise.reject(msg); this.lastPromise = null; } showBaloon && this.vortexStatusService.logError(msg); } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiVHVwbGVMb2FkZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvdm9ydGV4L1R1cGxlTG9hZGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBYyxPQUFPLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDM0MsT0FBTyxFQUFnQixPQUFPLEVBQUUsTUFBTSxXQUFXLENBQUM7QUFDbEQsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBQ3BELE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFFN0MsT0FBTyxFQUNILCtCQUErQixHQUVsQyxNQUFNLG1CQUFtQixDQUFDO0FBRTNCLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUNsRCxPQUFPLEVBQUUsSUFBSSxFQUFFLE9BQU8sRUFBRSxNQUFNLFlBQVksQ0FBQztBQUMzQyxPQUFPLFNBQVMsTUFBTSxZQUFZLENBQUM7QUFDbkMsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBRXBELE9BQU8sRUFBRSxLQUFLLEVBQUUsU0FBUyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFFbEQscUJBQXFCO0FBQ3JCLDBCQUEwQjtBQUUxQixNQUFNLENBQU4sSUFBWSxvQkFJWDtBQUpELFdBQVksb0JBQW9CO0lBQzVCLCtEQUFJLENBQUE7SUFDSiwrREFBSSxDQUFBO0lBQ0osbUVBQU0sQ0FBQTtBQUNWLENBQUMsRUFKVyxvQkFBb0IsS0FBcEIsb0JBQW9CLFFBSS9CO0FBdUJEOzs7Ozs7Ozs7Ozs7OztHQWNHO0FBQ0gsTUFBTSxPQUFPLFdBQVc7SUFXUjtJQUNBO0lBQ0E7SUFaWixLQUFLLEdBQ0QsSUFBSSxZQUFZLEVBQXdCLENBQUM7SUFDckMsb0JBQW9CLENBQXdCO0lBQzVDLGVBQWUsR0FBd0IsSUFBSSxDQUFDO0lBQzVDLFVBQVUsR0FBMkIsSUFBSSxDQUFDO0lBQzFDLEtBQUss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QUksQ0FBQyxXQUFXLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1lBQzdCLElBQUksQ0FBQyxXQUFXLEdBQUcsSUFBSSxDQUFDO1NBQzNCO1FBRUQsVUFBVSxJQUFJLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDekQsQ0FBQztDQUNKIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgT2JzZXJ2YWJsZSwgU3ViamVjdCB9IGZyb20gXCJyeGpzXCI7XG5pbXBvcnQgeyBJUGF5bG9hZEZpbHQsIFBheWxvYWQgfSBmcm9tIFwiLi9QYXlsb2FkXCI7XG5pbXBvcnQgeyBQYXlsb2FkRW5kcG9pbnQgfSBmcm9tIFwiLi9QYXlsb2FkRW5kcG9pbnRcIjtcbmltcG9ydCB7IEV2ZW50RW1pdHRlciB9IGZyb20gXCJAYW5ndWxhci9jb3JlXCI7XG5pbXBvcnQgeyBOZ0xpZmVDeWNsZUV2ZW50cyB9IGZyb20gXCIuLi91dGlsL05nTGlmZUN5Y2xlRXZlbnRzXCI7XG5pbXBvcnQge1xuICAgIFNFUlZFUl9SRVNQT05TRV9USU1FT1VUX1NFQ09ORFMsXG4gICAgVm9ydGV4Q2xpZW50QUJDLFxufSBmcm9tIFwiLi9Wb3J0ZXhDbGllbnRBQkNcIjtcbmltcG9ydCB7IFR1cGxlIH0gZnJvbSBcIi4vZXhwb3J0c1wiO1xuaW1wb3J0IHsgcGxEZWxldGVLZXkgfSBmcm9tIFwiLi9QYXlsb2FkRmlsdGVyS2V5c1wiO1xuaW1wb3J0IHsgYmluZCwgZGF0ZVN0ciB9IGZyb20gXCIuL1V0aWxNaXNjXCI7XG5pbXBvcnQgZGVlcEVxdWFsIGZyb20gXCJkZWVwLWVxdWFsXCI7XG5pbXBvcnQgeyBQYXlsb2FkRW52ZWxvcGUgfSBmcm9tIFwiLi9QYXlsb2FkRW52ZWxvcGVcIjtcbmltcG9ydCB7IFZvcnRleFN0YXR1c1NlcnZpY2UgfSBmcm9tIFwiLi9Wb3J0ZXhTdGF0dXNTZXJ2aWNlXCI7XG5pbXBvcnQgeyBmaXJzdCwgdGFrZVVudGlsIH0gZnJvbSBcInJ4anMvb3BlcmF0b3JzXCI7XG5cbi8vIC0tLS0tLS0tLS0tLS0tLS0tLVxuLy8gU29tZSBwcml2YXRlIHN0cnVjdHVyZXNcblxuZXhwb3J0IGVudW0gVHVwbGVMb2FkZXJFdmVudEVudW0ge1xuICAgIExvYWQsXG4gICAgU2F2ZSxcbiAgICBEZWxldGUsXG59XG5cbmludGVyZmFjZSBJUHJvbWlzZUNhbGxiYWNrcyB7XG4gICAgdHlwZTogVHVwbGVMb2FkZXJFdmVudEVudW07XG4gICAgcmVzb2x2ZTogYW55O1xuICAgIHJlamVjdDogYW55O1xufVxuXG4vKipcbiAqIEZpbHRlciBVcGRhdGUgY2FsbGFibGUuXG4gKlxuICogVGhpcyB3aWxsIGJlIGNhbGxlZCB0byByZXR1cm4gYSBwYXlsb2FkIGZpbHRlci5cbiAqIElmIHRoZSBwYXlsb2FkIGZpbHRlciBpcyBudWxsLCBUdXBsZUxvYWRlciB3aWxsIHJlbW92ZSBpdCdzIHJlZmVyZW5jZSB0byBvbGQgZGF0YVxuICogYW5kIHdhaXQuXG4gKlxuICogSWYgdGhlIHBheWxvYWQgZmlsdGVyIGlzIG5vdCBudWxsIGFuZCBkaWZmZXJzIGZyb20gdGhlIGxhc3QgcGF5bG9hZCBmaWx0ZXIsIHRoZVxuICogVHVwbGVMb2FkZXIgd2lsbCBzZW5kIGEgcmVxdWVzdCB0byB0aGUgc2VydmVyLi5cbiAqXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgSUZpbHRlclVwZGF0ZUNhbGxhYmxlIHtcbiAgICAoKTogSVBheWxvYWRGaWx0IHwgbnVsbDtcbn1cblxuLyoqXG4gKiBUdXBsZUxvYWRlciBmb3IgQW5ndWxhcjIgKyBTeW5lcnR5IFZvcnRleFxuICpcbiAqIEBwYXJhbTogdm9ydGV4IFRoZSB2b3J0ZXggaW5zdGFuY2UgdG8gc2VuZCB2aWEuXG4gKlxuICogQHBhcmFtOiBjb21wb25lbnQgVGhlIGNvbXBvbmVudCB0byByZWdpc3RlciBvdXIgZXZlbnRzIG9uLlxuICpcbiAqIEBwYXJhbTogZmlsdGVyVXBkYXRlQ2FsbGFibGUgQSBJRmlsdGVyVXBkYXRlQ2FsbGFibGUgY2FsbGFibGUgdGhhdCByZXR1cm5zIG51bGxcbiAqIG9yIGFuIElQYXlsb2FkRmlsdGVyXG4gKlxuICogTWFudWFsIGNoYW5nZXMgY2FuIGJlIHRyaWdnZXJkIGFzIGZvbGxvd3MuXG4gKiAqIFwibG9hZCgpXCJcbiAqICogXCJzYXZlKClcIlxuICogKiBcImRlbCgpXCJcbiAqL1xuZXhwb3J0IGNsYXNzIFR1cGxlTG9hZGVyIHtcbiAgICBldmVudDogRXZlbnRFbWl0dGVyPFR1cGxlTG9hZGVyRXZlbnRFbnVtPiA9XG4gICAgICAgIG5ldyBFdmVudEVtaXR0ZXI8VHVwbGVMb2FkZXJFdmVudEVudW0+KCk7XG4gICAgcHJpdmF0ZSBmaWx0ZXJVcGRhdGVDYWxsYWJsZTogSUZpbHRlclVwZGF0ZUNhbGxhYmxlO1xuICAgIHByaXZhdGUgbGFzdFBheWxvYWRGaWx0OiBJUGF5bG9hZEZpbHQgfCBudWxsID0gbnVsbDtcbiAgICBwcml2YXRlIGxhc3RUdXBsZXM6IGFueVtdIHwgVHVwbGVbXSB8IG51bGwgPSBudWxsO1xuICAgIHByaXZhdGUgdGltZXI6IGFueSB8IG51bWJlciB8IG51bGwgPSBudWxsO1xuICAgIHByaXZhdGUgbGFzdFByb21pc2U6IElQcm9taXNlQ2FsbGJhY2tzIHwgbnVsbCA9IG51bGw7XG4gICAgcHJpdmF0ZSBlbmRwb2ludDogUGF5bG9hZEVuZHBvaW50IHwgbnVsbCA9IG51bGw7XG5cbiAgICBjb25zdHJ1Y3RvcihcbiAgICAgICAgcHJpdmF0ZSB2b3J0ZXg6IFZvcnRleENsaWVudEFCQyxcbiAgICAgICAgcHJpdmF0ZSB2b3J0ZXhTdGF0dXNTZXJ2aWNlOiBWb3J0ZXhTdGF0dXNTZXJ2aWNlLFxuICAgICAgICBwcml2YXRlIGNvbXBvbmVudDogTmdMaWZlQ3ljbGVFdmVudHMsXG4gICAgICAgIGZpbHRlclVwZGF0ZUNhbGxhYmxlOiBJRmlsdGVyVXBkYXRlQ2FsbGFibGUgfCBJUGF5bG9hZEZpbHRcbiAgICApIHtcbiAgICAgICAgaWYgKGZpbHRlclVwZGF0ZUNhbGxhYmxlIGluc3RhbmNlb2YgRnVuY3Rpb24pIHtcbiAgICAgICAgICAgIHRoaXMuZmlsdGVyVXBkYXRlQ2FsbGFibGUgPSBmaWx0ZXJVcGRhdGVDYWxsYWJsZTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuZmlsdGVyVXBkYXRlQ2FsbGFibGUgPSAoKSA9PiB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZpbHRlclVwZGF0ZUNhbGxhYmxlO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFJlZ2lzZXRlciBmb3IgdGhlIGFuZ3VsYXIgZG9jaGVja1xuICAgICAgICB0aGlzLmNvbXBvbmVudC5kb0NoZWNrRXZlbnRcbiAgICAgICAgICAgIC5waXBlKHRha2VVbnRpbCh0aGlzLmNvbXBvbmVudC5vbkRlc3Ryb3lFdmVudCkpXG4gICAgICAgICAgICAuc3Vic2NyaWJlKCgpID0+IHRoaXMuZmlsdGVyQ2hhbmdlQ2hlY2soKSk7XG5cbiAgICAgICAgLy8gQ3JlYXRlIHRoZSBvYnNlcnZhYmxlIG9iamVjdFxuICAgICAgICB0aGlzLl9vYnNlcnZhYmxlID0gbmV3IFN1YmplY3QoKTtcblxuICAgICAgICAvLyBSZW1vdmUgYWxsIG9ic2VydmVycyB3aGVuIHRoZSBjb21wb25lbnQgaXMgZGVzdHJveWVkLlxuICAgICAgICB0aGlzLmNvbXBvbmVudC5vbkRlc3Ryb3lFdmVudFxuICAgICAgICAgICAgLnBpcGUoZmlyc3QoKSlcbiAgICAgICAgICAgIC5zdWJzY3JpYmUoKCkgPT4gdGhpcy5fb2JzZXJ2YWJsZS5jb21wbGV0ZSgpKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIF9vYnNlcnZhYmxlOiBTdWJqZWN0PFR1cGxlW10gfCBhbnlbXT47XG5cbiAgICAvKipcbiAgICAgKiBAcHJvcGVydHk6IFRoZSB0dXBsZSBvYnNlcnZhYmxlIHRvIHN1YnNjcmliZSB0by5cbiAgICAgKi9cbiAgICBnZXQgb2JzZXJ2YWJsZSgpOiBPYnNlcnZhYmxlPFR1cGxlW10gfCBhbnlbXT4ge1xuICAgICAgICByZXR1cm4gdGhpcy5fb2JzZXJ2YWJsZTtcbiAgICB9XG5cbiAgICBmaWx0ZXJDaGFuZ2VDaGVjaygpOiB2b2lkIHtcbiAgICAgICAgaWYgKCF0aGlzLnZvcnRleFN0YXR1c1NlcnZpY2Uuc25hcHNob3QuaXNPbmxpbmUpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIENyZWF0ZSBhIGNvcHlcbiAgICAgICAgbGV0IG5ld0ZpbHRlciA9IE9iamVjdC5hc3NpZ24oe30sIHRoaXMuZmlsdGVyVXBkYXRlQ2FsbGFibGUoKSk7XG5cbiAgICAgICAgaWYgKG5ld0ZpbHRlciA9PSBudWxsKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5lbmRwb2ludCAhPSBudWxsKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5lbmRwb2ludC5zaHV0ZG93bigpO1xuICAgICAgICAgICAgICAgIHRoaXMuZW5kcG9pbnQgPSBudWxsO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLmxhc3RUdXBsZXMgPSBudWxsO1xuICAgICAgICAgICAgdGhpcy5sYXN0UGF5bG9hZEZpbHQgPSBudWxsO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKFxuICAgICAgICAgICAgdGhpcy5sYXN0UGF5bG9hZEZpbHQgIT0gbnVsbCAmJlxuICAgICAgICAgICAgZGVlcEVxdWFsKG5ld0ZpbHRlciwgdGhpcy5sYXN0UGF5bG9hZEZpbHQsIHsgc3RyaWN0OiB0cnVlIH0pXG4gICAgICAgICkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5sYXN0UGF5bG9hZEZpbHQgPSBuZXdGaWx0ZXI7XG4gICAgICAgIHRoaXMuZW5kcG9pbnQgPSBuZXcgUGF5bG9hZEVuZHBvaW50KFxuICAgICAgICAgICAgdGhpcy5jb21wb25lbnQsXG4gICAgICAgICAgICB0aGlzLmxhc3RQYXlsb2FkRmlsdCxcbiAgICAgICAgICAgIHRydWVcbiAgICAgICAgKTtcbiAgICAgICAgdGhpcy5lbmRwb2ludC5vYnNlcnZhYmxlLnN1YnNjcmliZShcbiAgICAgICAgICAgIChwYXlsb2FkRW52ZWxvcGU6IFBheWxvYWRFbnZlbG9wZSkgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMucHJvY2Vzc1BheWxvYWRFbnZlbG9wZShwYXlsb2FkRW52ZWxvcGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICApO1xuXG4gICAgICAgIHRoaXMudm9ydGV4LnNlbmQobmV3IFBheWxvYWRFbnZlbG9wZSh0aGlzLmxhc3RQYXlsb2FkRmlsdCkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIExvYWQgTG9hZHMgdGhlIGRhdGEgZnJvbSBhIHNlcnZlclxuICAgICAqXG4gICAgICogQHJldHVybnM6IFByb21pc2U8UGF5bG9hZD4sIHdoaWNoIGlzIGNhbGxlZCB3aGVuIHRoZSBsb2FkIHN1Y2NlZWRzIG9yIGZhaWxzLlxuICAgICAqXG4gICAgICovXG4gICAgbG9hZCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuc2F2ZU9yTG9hZChUdXBsZUxvYWRlckV2ZW50RW51bS5Mb2FkKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTYXZlXG4gICAgICpcbiAgICAgKiBDb2xsZWN0cyB0aGUgZGF0YSBmcm9tIHRoZSBmb3JtLCBpbnRvIHRoZSB0dXBsZSBhbmQgc2VuZHMgaXQgdGhyb3VnaCB0aGVcbiAgICAgKiB2b3J0ZXguXG4gICAgICpcbiAgICAgKiBAcGFyYW06IHR1cGxlcyBUaGUgdHVwbGVzIHRvIHNhdmUsIGlmIHR1cGxlcyBpcyBudWxsLCB0aGUgbGFzdCBsb2FkZWQgdHVwbGVzIHdpbGxcbiAgICAgKiBiZSB1c2VkLlxuICAgICAqXG4gICAgICogQHJldHVybnM6IFByb21pc2UsIHdoaWNoIGlzIGNhbGxlZCB3aGVuIHRoZSBzYXZlIHN1Y2NlZWRzIG9yIGZhaWxzLlxuICAgICAqXG4gICAgICovXG4gICAgc2F2ZSh0dXBsZXM6IFR1cGxlW10gfCBhbnlbXSB8IG51bGwgPSBudWxsKTogUHJvbWlzZTxQYXlsb2FkPiB7XG4gICAgICAgIHJldHVybiB0aGlzLnNhdmVPckxvYWQoVHVwbGVMb2FkZXJFdmVudEVudW0uU2F2ZSwgdHVwbGVzKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBEZWxldGVcbiAgICAgKlxuICAgICAqIFNlbmRzIHRoZSB0dXBsZXMgdG8gdGhlIHNlcnZlciBmb3IgaXQgdG8gZGVsZXRlIHRoZW0uXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyA6UHJvbWlzZSwgd2hpY2ggaXMgY2FsbGVkIHdoZW4gdGhlIHNhdmUgc3VjY2VlZHMgb3IgZmFpbHMuXG4gICAgICpcbiAgICAgKi9cbiAgICBkZWwodHVwbGVzOiBhbnlbXSB8IFR1cGxlW10gfCBudWxsID0gbnVsbCk6IFByb21pc2U8UGF5bG9hZD4ge1xuICAgICAgICBsZXQgcHJvbWlzZSA9IHRoaXMuc2F2ZU9yTG9hZChUdXBsZUxvYWRlckV2ZW50RW51bS5EZWxldGUsIHR1cGxlcyk7XG5cbiAgICAgICAgcmV0dXJuIHByb21pc2U7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBzYXZlT3JMb2FkKFxuICAgICAgICB0eXBlOiBUdXBsZUxvYWRlckV2ZW50RW51bSxcbiAgICAgICAgdHVwbGVzOiBhbnlbXSB8IFR1cGxlW10gfCBudWxsID0gbnVsbFxuICAgICk6IFByb21pc2U8UGF5bG9hZD4ge1xuICAgICAgICAvLyBJJ20gbm90IHN1cmUgaWYgdGhlIHByb21pc2UgaXMgc2V0IHN0cmFpZ2h0IGF3YXksIHNvIGF0IGxlYXN0IG51bGwgb3V0XG4gICAgICAgIC8vIHRoZSBsYXN0IG9uZS5cbiAgICAgICAgdGhpcy5sYXN0UHJvbWlzZSA9IG51bGw7XG5cbiAgICAgICAgLy8gSW5pdGlhbGlzZSB0aGUgcHJvbWlzZVxuICAgICAgICBsZXQgcHJvbWlzZSA9IG5ldyBQcm9taXNlPFBheWxvYWQ+KFxuICAgICAgICAgICAgKHJlc29sdmUsIHJlamVjdCkgPT5cbiAgICAgICAgICAgICAgICAodGhpcy5sYXN0UHJvbWlzZSA9IHtcbiAgICAgICAgICAgICAgICAgICAgdHlwZTogdHlwZSxcbiAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZTogcmVzb2x2ZSxcbiAgICAgICAgICAgICAgICAgICAgcmVqZWN0OiByZWplY3QsXG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgKTtcblxuICAgICAgICAvLyBDaGVjayBpZiB0aGVyZSBpcyBhbHJlYWR5IGEgbG9hZCBvciBzYXZlIGluIHByb2dyZXNzXG4gICAgICAgIGlmICh0aGlzLnNldHVwVGltZXIoKSAhPT0gdHJ1ZSkge1xuICAgICAgICAgICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5sYXN0UHJvbWlzZS5yZWplY3QoXG4gICAgICAgICAgICAgICAgICAgIFwiQW5vdGhlciBzYXZlIG9yIGxvYWQgaXMgc3RpbGwgaW4gcHJvZ3Jlc3MuXCJcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIHRoaXMubGFzdFByb21pc2UgPSBudWxsO1xuICAgICAgICAgICAgfSwgMCk7XG4gICAgICAgICAgICByZXR1cm4gcHJvbWlzZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0eXBlID09PSBUdXBsZUxvYWRlckV2ZW50RW51bS5Mb2FkKSB7XG4gICAgICAgICAgICAvLyBGb3JjZSBhIGZpbHRlciB1cGRhdGUgYW5kIHJlbG9hZFxuICAgICAgICAgICAgdGhpcy5sYXN0UGF5bG9hZEZpbHQgPSBudWxsO1xuICAgICAgICAgICAgdGhpcy5maWx0ZXJDaGFuZ2VDaGVjaygpO1xuXG4gICAgICAgICAgICAvLyBJZiB0aGVyZSB3YXMgbm8gZmlsdGVyIHVwZGF0ZSwgZmFpbFxuICAgICAgICAgICAgaWYgKHRoaXMubGFzdFBheWxvYWRGaWx0ID09IG51bGwpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmxhc3RQcm9taXNlLnJlamVjdChcbiAgICAgICAgICAgICAgICAgICAgXCJUaGVyZSBpcyBubyBwYXlsb2FkIGZpbHRlciBwcm92aWRlZCwgbG9hZCBmYWlsZWRcIlxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgdGhpcy5sYXN0UHJvbWlzZSA9IG51bGw7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHByb21pc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gVHVwbGVMb2FkZXJFdmVudEVudW0uU2F2ZSkge1xuICAgICAgICAgICAgaWYgKHR1cGxlcyAhPSBudWxsKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5sYXN0VHVwbGVzID0gdHVwbGVzO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBDaGVjayBpZiB3ZSBoYXZlIHR1cGxlcyB0byBzYXZlLlxuICAgICAgICAgICAgaWYgKHRoaXMubGFzdFR1cGxlcyA9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5sYXN0UHJvbWlzZS5yZWplY3QoXG4gICAgICAgICAgICAgICAgICAgIFwiTm8gdHVwbGVzIHRvIHNhdmUuIFwiICtcbiAgICAgICAgICAgICAgICAgICAgICAgIFwiIFByb3ZpZGUgb25lIHRvIHdpdGggdGhlIHNhdmUodHVwbGVzKSBjYWxsIG9yIGxvYWQgc29tZSBmaXJzdCBcIiArXG4gICAgICAgICAgICAgICAgICAgICAgICBcIiB3aXRoIHRoZSBmaWx0ZXJVcGRhdGVDYWxsYWJsZVwiXG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICB0aGlzLmxhc3RQcm9taXNlID0gbnVsbDtcbiAgICAgICAgICAgICAgICByZXR1cm4gcHJvbWlzZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gU2F2ZSB0aGUgdHVwbGVzXG4gICAgICAgICAgICBuZXcgUGF5bG9hZCh0aGlzLmxhc3RQYXlsb2FkRmlsdCwgdGhpcy5sYXN0VHVwbGVzKVxuICAgICAgICAgICAgICAgIC5tYWtlUGF5bG9hZEVudmVsb3BlKClcbiAgICAgICAgICAgICAgICAudGhlbigocGU6IFBheWxvYWRFbnZlbG9wZSkgPT4gdGhpcy52b3J0ZXguc2VuZChwZSkpXG4gICAgICAgICAgICAgICAgLmNhdGNoKChlKSA9PiBgVHVwbGVMb2FkZXIsIGZhaWxlZCB0byBzYXZlIHR1cGxlcyAke2V9YCk7XG4gICAgICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gVHVwbGVMb2FkZXJFdmVudEVudW0uRGVsZXRlKSB7XG4gICAgICAgICAgICAvLyBDaGVjayBpZiB3ZSBoYXZlIHR1cGxlcyB0byBzYXZlLlxuICAgICAgICAgICAgaWYgKHR1cGxlcyA9PSBudWxsIHx8IHR1cGxlcy5sZW5ndGggPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHRoaXMubGFzdFByb21pc2UucmVqZWN0KFxuICAgICAgICAgICAgICAgICAgICBcIk5vIHR1cGxlcyB0byBkZWxldGUuIFwiICtcbiAgICAgICAgICAgICAgICAgICAgICAgIFwiIFByb3ZpZGUgb25lIG9yIG1vcmUgd2l0aCB0aGUgZGVsKHR1cGxlcykgY2FsbFwiXG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICB0aGlzLmxhc3RQcm9taXNlID0gbnVsbDtcbiAgICAgICAgICAgICAgICByZXR1cm4gcHJvbWlzZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gU2V0IHRoZSBkZWxldGUga2V5LiBUaGUgc2VydmVyIHdpbGwgZGVsZXRlIG9iamVjdHMgd2l0aCB0aGlzIHNldC5cbiAgICAgICAgICAgIGxldCBmaWx0ID0gT2JqZWN0LmFzc2lnbih7fSwgdGhpcy5sYXN0UGF5bG9hZEZpbHQpO1xuICAgICAgICAgICAgZmlsdFtwbERlbGV0ZUtleV0gPSB0cnVlO1xuXG4gICAgICAgICAgICAvLyBTYXZlIHRoZSB0dXBsZXNcbiAgICAgICAgICAgIG5ldyBQYXlsb2FkKGZpbHQsIHR1cGxlcylcbiAgICAgICAgICAgICAgICAubWFrZVBheWxvYWRFbnZlbG9wZSgpXG4gICAgICAgICAgICAgICAgLnRoZW4oKHBlOiBQYXlsb2FkRW52ZWxvcGUpID0+IHRoaXMudm9ydGV4LnNlbmQocGUpKVxuICAgICAgICAgICAgICAgIC5jYXRjaCgoZSkgPT4gYFR1cGxlTG9hZGVyLCBmYWlsZWQgdG8gZGVsZXRlIHR1cGxlcyAke2V9YCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFR5cGUgJHt0eXBlfSBpcyBub3QgaW1wbGVtZW50ZWQuYCk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBSZXR1cm4gdGhlIHByb21pc2VcbiAgICAgICAgcmV0dXJuIHByb21pc2U7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBwcm9jZXNzUGF5bG9hZEVudmVsb3BlKHBheWxvYWRFbnZlbG9wZTogUGF5bG9hZEVudmVsb3BlKSB7XG4gICAgICAgIGlmICh0aGlzLnRpbWVyKSB7XG4gICAgICAgICAgICBjbGVhclRpbWVvdXQodGhpcy50aW1lcik7XG4gICAgICAgICAgICB0aGlzLnRpbWVyID0gbnVsbDtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIE5vIHJlc3VsdCwgbWVhbnMgdGhpcyB3YXMgYSBsb2FkXG4gICAgICAgIGlmIChwYXlsb2FkRW52ZWxvcGUucmVzdWx0ID09IG51bGwpIHtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgdGhpcy5ldmVudC5lbWl0KFR1cGxlTG9hZGVyRXZlbnRFbnVtLkxvYWQpO1xuICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKGAke2RhdGVTdHIoKX0gVHVwbGVMb2FkZXIgLSBMb2FkIGV2ZW50IGVtaXQgZXJyb3JgKTtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGUpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBSZXN1bHQsIG1lYW5zIHRoaXMgd2FzIGEgc2F2ZVxuICAgICAgICB9IGVsc2UgaWYgKHBheWxvYWRFbnZlbG9wZS5yZXN1bHQgPT09IHRydWUpIHtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgaWYgKHBheWxvYWRFbnZlbG9wZS5maWx0Lmhhc093blByb3BlcnR5KHBsRGVsZXRlS2V5KSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmV2ZW50LmVtaXQoVHVwbGVMb2FkZXJFdmVudEVudW0uRGVsZXRlKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmV2ZW50LmVtaXQoVHVwbGVMb2FkZXJFdmVudEVudW0uU2F2ZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKFxuICAgICAgICAgICAgICAgICAgICBgJHtkYXRlU3RyKCl9IFR1cGxlTG9hZGVyIC0gU2F2ZS9EZWxldGUgZXZlbnQgZW1pdCBlcnJvcmBcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIEVsc2UsIHRyZWF0IHRoaXMgYXMgYSBmYWlsdXJlXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBpZiAodGhpcy5sYXN0UHJvbWlzZSkge1xuICAgICAgICAgICAgICAgIHRoaXMubGFzdFByb21pc2UucmVqZWN0KHBheWxvYWRFbnZlbG9wZS5yZXN1bHQudG9TdHJpbmcoKSk7XG4gICAgICAgICAgICAgICAgdGhpcy5sYXN0UHJvbWlzZSA9IG51bGw7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMudm9ydGV4U3RhdHVzU2VydmljZS5sb2dFcnJvcihcbiAgICAgICAgICAgICAgICBwYXlsb2FkRW52ZWxvcGUucmVzdWx0LnRvU3RyaW5nKClcbiAgICAgICAgICAgICk7XG5cbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0aGlzLmxhc3RQcm9taXNlKSB7XG4gICAgICAgICAgICB0aGlzLmxhc3RQcm9taXNlLnJlc29sdmUocGF5bG9hZEVudmVsb3BlKTtcbiAgICAgICAgICAgIHRoaXMubGFzdFByb21pc2UgPSBudWxsO1xuICAgICAgICB9XG5cbiAgICAgICAgcGF5bG9hZEVudmVsb3BlXG4gICAgICAgICAgICAuZGVjb2RlUGF5bG9hZCgpXG4gICAgICAgICAgICAudGhlbigocGF5bG9hZDogUGF5bG9hZCkgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMubGFzdFR1cGxlcyA9IHBheWxvYWQudHVwbGVzO1xuICAgICAgICAgICAgICAgIHRoaXMuX29ic2VydmFibGUubmV4dChwYXlsb2FkLnR1cGxlcyk7XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLmNhdGNoKChlKSA9PlxuICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKFxuICAgICAgICAgICAgICAgICAgICBgJHtkYXRlU3RyKCl9IFR1cGxlTG9hZGVyIGZhaWxlZCB0byBkZWNvZGUgcGF5bG9hZCAke2V9YFxuICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSByZXNldFRpbWVyKCk6IHZvaWQge1xuICAgICAgICB0aGlzLm9wZXJhdGlvblRpbWVvdXQoZmFsc2UpO1xuICAgIH1cblxuICAgIHByaXZhdGUgc2V0dXBUaW1lcigpOiBib29sZWFuIHtcbiAgICAgICAgbGV0IHNlbGYgPSB0aGlzO1xuICAgICAgICBpZiAoc2VsZi50aW1lciAhPSBudWxsKSB7XG4gICAgICAgICAgICB0aGlzLnZvcnRleFN0YXR1c1NlcnZpY2UubG9nV2FybmluZyhcbiAgICAgICAgICAgICAgICBcIldlJ3JlIGFscmVhZHkgcHJvY2Vzc2luZyBhIHJlcXVlc3QsIEFjdGlvbiBmYWlsZWRcIlxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHNlbGYudGltZXIgPSBzZXRUaW1lb3V0KFxuICAgICAgICAgICAgYmluZChzZWxmLCBzZWxmLm9wZXJhdGlvblRpbWVvdXQpLFxuICAgICAgICAgICAgU0VSVkVSX1JFU1BPTlNFX1RJTUVPVVRfU0VDT05EUyAqIDEwMDBcbiAgICAgICAgKTtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBvcGVyYXRpb25UaW1lb3V0KHNob3dCYWxvb246IGJvb2xlYW4gPSB0cnVlKTogdm9pZCB7XG4gICAgICAgIHRoaXMudGltZXIgPSBudWxsO1xuXG4gICAgICAgIGxldCBtc2c6IHN0cmluZyA9IFwiVGhlIHNlcnZlciBmYWlsZWQgdG8gcmVzcG9uZCwgb3BlcmF0b24gdGltZWQgb3V0XCI7XG5cbiAgICAgICAgaWYgKHRoaXMubGFzdFByb21pc2UpIHtcbiAgICAgICAgICAgIG1zZyA9IGAke3RoaXMubGFzdFByb21pc2UudHlwZX0gRmFpbGVkLCBSZXNwb25zZSBUaW1lZCBvdXRgO1xuICAgICAgICAgICAgdGhpcy5sYXN0UHJvbWlzZS5yZWplY3QobXNnKTtcbiAgICAgICAgICAgIHRoaXMubGFzdFByb21pc2UgPSBudWxsO1xuICAgICAgICB9XG5cbiAgICAgICAgc2hvd0JhbG9vbiAmJiB0aGlzLnZvcnRleFN0YXR1c1NlcnZpY2UubG9nRXJyb3IobXNnKTtcbiAgICB9XG59XG4iXX0=