@synerty/vortexjs
Version:
Custom observable data serialisation and routing based on Angular 2+
281 lines • 36.2 kB
JavaScript
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=