@synerty/vortexjs
Version:
Custom observable data serialisation and routing based on Angular 2+
176 lines • 23.2 kB
JavaScript
import { bind, dateStr, getFiltStr } from "./UtilMisc";
import { VortexClientABC } from "./VortexClientABC";
import { PayloadEnvelope } from "./PayloadEnvelope";
export class VortexClientHttp extends VortexClientABC {
/**
* RapUI VortexService, This class is responsible for sending and receiving payloads to/from
* the server.
*/
lastConn = null;
constructor(vortexStatusService, url, vortexClientName, headers) {
super(vortexStatusService, url, vortexClientName, headers);
}
shutdown() {
this.setShutdown();
if (this.lastConn) {
this.lastConn.shutdown();
this.lastConn = null;
}
return Promise.resolve();
}
setClosedByConnection() {
this.setClosed();
}
sendVortexMsg(vortexMsgs) {
this.lastConn = new _VortexClientHttpConnection(this, this.vortexStatusService, (payload) => this.receive(payload), () => this.beat());
this.lastConn.send(vortexMsgs);
// console.log(dateStr() + "Sent payload with filt : " + JSON.stringify(payload.filt));
}
}
// ############################################################################
class _VortexClientHttpConnection {
vortex;
vortexStatusService;
receiveCallback;
vortexBeatCallback;
static RECONNECT_SIZE_LIMIT = 20 * 1024 * 1024; // 20 megabytes
_vortex;
_http;
_updateTimer;
_responseParseIndex;
_closing;
_aborting;
constructor(vortex, vortexStatusService, receiveCallback, vortexBeatCallback) {
this.vortex = vortex;
this.vortexStatusService = vortexStatusService;
this.receiveCallback = receiveCallback;
this.vortexBeatCallback = vortexBeatCallback;
let self = this;
let randArg = Math.random() + "." + new Date().getTime();
let args = {
vortexUuid: vortex.uuid,
vortexName: vortex.name,
__randArg__: randArg,
};
self._http = new XMLHttpRequest();
self._http.open("POST", self.vortex.url + getFiltStr(args), true);
// Set the headers
for (const headerKey of vortex.headers.keys()) {
self._http.setRequestHeader(headerKey, vortex.headers.get(headerKey));
}
self._updateTimer = null;
// Good events
self._http.onloadstart = function (e) {
self._received();
// Force a 50-millisecond timer, as some browsers don't call "onprogress"
// very often.
self._updateTimer = setInterval(function () {
self._received();
}, 50);
};
self._http.onprogress = function (e) {
self._received();
};
self._http.onload = function (e) {
if (self._updateTimer)
clearInterval(self._updateTimer);
self._received();
};
// Bad events
self._http.onabort = bind(self, self._error);
self._http.onerror = bind(self, self._error);
self._http.ontimeout = bind(self, self._error);
self._responseParseIndex = 0;
self._closing = false;
self._aborting = false;
}
shutdown() {
this._closing = true;
if (this._http)
this._http.abort();
}
send(vortexMsgs) {
let data = "";
for (let vortexMsg of vortexMsgs) {
// Serialise the payload
data += vortexMsg + ".";
}
// console.log("sending payload");
// console.log(xmlStr);
this._http.send(data);
}
_received() {
let self = this;
/*
* Received
*
* Called when progress is made on receiving data from the vortex server.
*
* This means that it needs to be able to handle : * partial payloads (in
* which case it does nothing) * multiple payloads (in which case, it breaks
* them up, parses them and sends them to vortex individually)
*/
if (self._aborting)
return;
// If we receive something that is not valid vortex data, then reload the page
// This typically occurs when we're receving HTML because we're not logged in.
if (/^</.test(self._http.responseText)) {
self.vortex.setClosedByConnection();
self._closing = true;
self._aborting = true;
self._http.abort();
location.reload();
return;
}
// Split out the payloads of data, they are delimited by a '.'
let data = self._http.responseText.substr(self._responseParseIndex);
let payloadSeparatorIndex = data.indexOf(".");
while (payloadSeparatorIndex !== -1) {
self._responseParseIndex += payloadSeparatorIndex + 1;
// Get the b64encoded string
let vortexStr = data.substr(0, payloadSeparatorIndex);
if (vortexStr.length === 0) {
self.vortexBeatCallback();
}
else {
// Create payload object from it
// Send to vortex
PayloadEnvelope.fromVortexMsg(vortexStr)
.then((pe) => self.receiveCallback(pe))
.catch((e) => console.log(`${dateStr()} An error occured deserialising ${e}`));
}
data = self._http.responseText.substr(self._responseParseIndex);
payloadSeparatorIndex = data.indexOf(".");
}
// In the event that the browser is buffering all this data, we should
// reconnect to allow the browser to cleanup.
if (self._http.responseText.length >=
_VortexClientHttpConnection.RECONNECT_SIZE_LIMIT &&
!self._closing) {
self._closing = true;
self.vortex.reconnect();
}
}
_error(e) {
let self = this;
if (self._updateTimer)
clearInterval(self._updateTimer);
if (self._aborting || this._closing)
return;
let msg = "";
if (e.type === "abort") {
msg = "Request was aborted and not by VortexJS";
}
else {
try {
msg = e.toString();
}
catch (e) {
}
}
this._vortex["setConnecting"]();
this.vortexStatusService.logError(msg);
// console.log("VortexConnection, connection errored out: " + msg);
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiVm9ydGV4Q2xpZW50SHR0cC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy92b3J0ZXgvVm9ydGV4Q2xpZW50SHR0cC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsSUFBSSxFQUFFLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxZQUFZLENBQUM7QUFDdkQsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBRXBELE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQztBQVdwRCxNQUFNLE9BQU8sZ0JBQWlCLFNBQVEsZUFBZTtJQUNqRDs7O09BR0c7SUFDSyxRQUFRLEdBQXVDLElBQUksQ0FBQztJQUU1RCxZQUNJLG1CQUF3QyxFQUN4QyxHQUFXLEVBQ1gsZ0JBQXdCLEVBQ3hCLE9BQW9CO1FBRXBCLEtBQUssQ0FBQyxtQkFBbUIsRUFBRSxHQUFHLEVBQUUsZ0JBQWdCLEVBQUUsT0FBTyxDQUFDLENBQUM7SUFDL0QsQ0FBQztJQUVTLFFBQVE7UUFDZCxJQUFJLENBQUMsV0FBVyxFQUFFLENBQUM7UUFDbkIsSUFBSSxJQUFJLENBQUMsUUFBUSxFQUFFO1lBQ2YsSUFBSSxDQUFDLFFBQVEsQ0FBQyxRQUFRLEVBQUUsQ0FBQztZQUN6QixJQUFJLENBQUMsUUFBUSxHQUFHLElBQUksQ0FBQztTQUN4QjtRQUNELE9BQU8sT0FBTyxDQUFDLE9BQU8sRUFBRSxDQUFDO0lBQzdCLENBQUM7SUFFRCxxQkFBcUI7UUFDakIsSUFBSSxDQUFDLFNBQVMsRUFBRSxDQUFDO0lBQ3JCLENBQUM7SUFFUyxhQUFhLENBQUMsVUFBb0I7UUFDeEMsSUFBSSxDQUFDLFFBQVEsR0FBRyxJQUFJLDJCQUEyQixDQUMzQyxJQUFJLEVBQ0osSUFBSSxDQUFDLG1CQUFtQixFQUN4QixDQUFDLE9BQU8sRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsRUFDbEMsR0FB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LDJCQUEyQixDQUFDLG9CQUFvQjtZQUNoRCxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQ2hCO1lBQ0UsSUFBSSxDQUFDLFFBQVEsR0FBRyxJQUFJLENBQUM7WUFDckIsSUFBSSxDQUFDLE1BQU0sQ0FBQyxTQUFTLEVBQUUsQ0FBQztTQUMzQjtJQUNMLENBQUM7SUFFTyxNQUFNLENBQUMsQ0FBQztRQUNaLElBQUksSUFBSSxHQUFHLElBQUksQ0FBQztRQUNoQixJQUFJLElBQUksQ0FBQyxZQUFZO1lBQUUsYUFBYSxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsQ0FBQztRQUV4RCxJQUFJLElBQUksQ0FBQyxTQUFTLElBQUksSUFBSSxDQUFDLFFBQVE7WUFBRSxPQUFPO1FBRTVDLElBQUksR0FBRyxHQUFHLEVBQUUsQ0FBQztRQUViLElBQUksQ0FBQyxDQUFDLElBQUksS0FBSyxPQUFPLEVBQUU7WUFDcEIsR0FBRyxHQUFHLHlDQUF5QyxDQUFDO1NBQ25EO2FBQU07WUFDSCxJQUFJO2dCQUNBLEdBQUcsR0FBRyxDQUFDLENBQUMsUUFBUSxFQUFFLENBQUM7YUFDdEI7WUFBQyxPQUFPLENBQUMsRUFBRTthQUNYO1NBQ0o7UUFFRCxJQUFJLENBQUMsT0FBTyxDQUFDLGVBQWUsQ0FBQyxFQUFFLENBQUM7UUFDaEMsSUFBSSxDQUFDLG1CQUFtQixDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUN2QyxtRUFBbUU7SUFDdkUsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGJpbmQsIGRhdGVTdHIsIGdldEZpbHRTdHIgfSBmcm9tIFwiLi9VdGlsTWlzY1wiO1xuaW1wb3J0IHsgVm9ydGV4Q2xpZW50QUJDIH0gZnJvbSBcIi4vVm9ydGV4Q2xpZW50QUJDXCI7XG5pbXBvcnQgeyBWb3J0ZXhTdGF0dXNTZXJ2aWNlIH0gZnJvbSBcIi4vVm9ydGV4U3RhdHVzU2VydmljZVwiO1xuaW1wb3J0IHsgUGF5bG9hZEVudmVsb3BlIH0gZnJvbSBcIi4vUGF5bG9hZEVudmVsb3BlXCI7XG5pbXBvcnQgeyBIdHRwSGVhZGVycyB9IGZyb20gXCJAYW5ndWxhci9jb21tb24vaHR0cFwiO1xuXG5pbnRlcmZhY2UgUmVjZWl2ZVBheWxvYWRDYWxsYWJsZSB7XG4gICAgKFBheWxvYWQpOiB2b2lkO1xufVxuXG5pbnRlcmZhY2UgVm9ydGV4QmVhdENhbGxhYmxlIHtcbiAgICAoKTogdm9pZDtcbn1cblxuZXhwb3J0IGNsYXNzIFZvcnRleENsaWVudEh0dHAgZXh0ZW5kcyBWb3J0ZXhDbGllbnRBQkMge1xuICAgIC8qKlxuICAgICAqIFJhcFVJIFZvcnRleFNlcnZpY2UsIFRoaXMgY2xhc3MgaXMgcmVzcG9uc2libGUgZm9yIHNlbmRpbmcgYW5kIHJlY2VpdmluZyBwYXlsb2FkcyB0by9mcm9tXG4gICAgICogdGhlIHNlcnZlci5cbiAgICAgKi9cbiAgICBwcml2YXRlIGxhc3RDb25uOiBfVm9ydGV4Q2xpZW50SHR0cENvbm5lY3Rpb24gfCBudWxsID0gbnVsbDtcblxuICAgIGNvbnN0cnVjdG9yKFxuICAgICAgICB2b3J0ZXhTdGF0dXNTZXJ2aWNlOiBWb3J0ZXhTdGF0dXNTZXJ2aWNlLFxuICAgICAgICB1cmw6IHN0cmluZyxcbiAgICAgICAgdm9ydGV4Q2xpZW50TmFtZTogc3RyaW5nLFxuICAgICAgICBoZWFkZXJzOiBIdHRwSGVhZGVycyxcbiAgICApIHtcbiAgICAgICAgc3VwZXIodm9ydGV4U3RhdHVzU2VydmljZSwgdXJsLCB2b3J0ZXhDbGllbnROYW1lLCBoZWFkZXJzKTtcbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgc2h1dGRvd24oKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIHRoaXMuc2V0U2h1dGRvd24oKTtcbiAgICAgICAgaWYgKHRoaXMubGFzdENvbm4pIHtcbiAgICAgICAgICAgIHRoaXMubGFzdENvbm4uc2h1dGRvd24oKTtcbiAgICAgICAgICAgIHRoaXMubGFzdENvbm4gPSBudWxsO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgICB9XG5cbiAgICBzZXRDbG9zZWRCeUNvbm5lY3Rpb24oKSB7XG4gICAgICAgIHRoaXMuc2V0Q2xvc2VkKCk7XG4gICAgfVxuXG4gICAgcHJvdGVjdGVkIHNlbmRWb3J0ZXhNc2codm9ydGV4TXNnczogc3RyaW5nW10pOiB2b2lkIHtcbiAgICAgICAgdGhpcy5sYXN0Q29ubiA9IG5ldyBfVm9ydGV4Q2xpZW50SHR0cENvbm5lY3Rpb24oXG4gICAgICAgICAgICB0aGlzLFxuICAgICAgICAgICAgdGhpcy52b3J0ZXhTdGF0dXNTZXJ2aWNlLFxuICAgICAgICAgICAgKHBheWxvYWQpID0+IHRoaXMucmVjZWl2ZShwYXlsb2FkKSxcbiAgICAgICAgICAgICgpID0+IHRoaXMuYmVhdCgpLFxuICAgICAgICApO1xuICAgICAgICB0aGlzLmxhc3RDb25uLnNlbmQodm9ydGV4TXNncyk7XG4gICAgICAgIC8vIGNvbnNvbGUubG9nKGRhdGVTdHIoKSArIFwiU2VudCBwYXlsb2FkIHdpdGggZmlsdCA6IFwiICsgSlNPTi5zdHJpbmdpZnkocGF5bG9hZC5maWx0KSk7XG4gICAgfVxufVxuXG4vLyAjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjXG5jbGFzcyBfVm9ydGV4Q2xpZW50SHR0cENvbm5lY3Rpb24ge1xuICAgIHByaXZhdGUgc3RhdGljIHJlYWRvbmx5IFJFQ09OTkVDVF9TSVpFX0xJTUlUID0gMjAgKiAxMDI0ICogMTAyNDsgLy8gMjAgbWVnYWJ5dGVzXG5cbiAgICBwcml2YXRlIF92b3J0ZXg6IFZvcnRleENsaWVudEh0dHA7XG4gICAgcHJpdmF0ZSBfaHR0cDogWE1MSHR0cFJlcXVlc3Q7XG4gICAgcHJpdmF0ZSBfdXBkYXRlVGltZXI6IGFueTtcbiAgICBwcml2YXRlIF9yZXNwb25zZVBhcnNlSW5kZXg6IG51bWJlcjtcbiAgICBwcml2YXRlIF9jbG9zaW5nOiBib29sZWFuO1xuICAgIHByaXZhdGUgX2Fib3J0aW5nOiBib29sZWFuO1xuXG4gICAgY29uc3RydWN0b3IoXG4gICAgICAgIHByaXZhdGUgdm9ydGV4OiBWb3J0ZXhDbGllbnRIdHRwLFxuICAgICAgICBwcml2YXRlIHZvcnRleFN0YXR1c1NlcnZpY2U6IFZvcnRleFN0YXR1c1NlcnZpY2UsXG4gICAgICAgIHByaXZhdGUgcmVjZWl2ZUNhbGxiYWNrOiBSZWNlaXZlUGF5bG9hZENhbGxhYmxlLFxuICAgICAgICBwcml2YXRlIHZvcnRleEJlYXRDYWxsYmFjazogVm9ydGV4QmVhdENhbGxhYmxlLFxuICAgICkge1xuICAgICAgICBsZXQgc2VsZiA9IHRoaXM7XG5cbiAgICAgICAgbGV0IHJhbmRBcmcgPSBNYXRoLnJhbmRvbSgpICsgXCIuXCIgKyBuZXcgRGF0ZSgpLmdldFRpbWUoKTtcbiAgICAgICAgbGV0IGFyZ3MgPSB7XG4gICAgICAgICAgICB2b3J0ZXhVdWlkOiB2b3J0ZXgudXVpZCxcbiAgICAgICAgICAgIHZvcnRleE5hbWU6IHZvcnRleC5uYW1lLFxuICAgICAgICAgICAgX19yYW5kQXJnX186IHJhbmRBcmcsXG4gICAgICAgIH07XG5cbiAgICAgICAgc2VsZi5faHR0cCA9IG5ldyBYTUxIdHRwUmVxdWVzdCgpO1xuICAgICAgICBzZWxmLl9odHRwLm9wZW4oXCJQT1NUXCIsIHNlbGYudm9ydGV4LnVybCArIGdldEZpbHRTdHIoYXJncyksIHRydWUpO1xuICAgICAgICAvLyBTZXQgdGhlIGhlYWRlcnNcbiAgICAgICAgZm9yIChjb25zdCBoZWFkZXJLZXkgb2Ygdm9ydGV4LmhlYWRlcnMua2V5cygpKSB7XG4gICAgICAgICAgICBzZWxmLl9odHRwLnNldFJlcXVlc3RIZWFkZXIoXG4gICAgICAgICAgICAgICAgaGVhZGVyS2V5LFxuICAgICAgICAgICAgICAgIHZvcnRleC5oZWFkZXJzLmdldChoZWFkZXJLZXkpLFxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHNlbGYuX3VwZGF0ZVRpbWVyID0gbnVsbDtcblxuICAgICAgICAvLyBHb29kIGV2ZW50c1xuICAgICAgICBzZWxmLl9odHRwLm9ubG9hZHN0YXJ0ID0gZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgICAgIHNlbGYuX3JlY2VpdmVkKCk7XG5cbiAgICAgICAgICAgIC8vIEZvcmNlIGEgNTAtbWlsbGlzZWNvbmQgdGltZXIsIGFzIHNvbWUgYnJvd3NlcnMgZG9uJ3QgY2FsbCBcIm9ucHJvZ3Jlc3NcIlxuICAgICAgICAgICAgLy8gdmVyeSBvZnRlbi5cbiAgICAgICAgICAgIHNlbGYuX3VwZGF0ZVRpbWVyID0gc2V0SW50ZXJ2YWwoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHNlbGYuX3JlY2VpdmVkKCk7XG4gICAgICAgICAgICB9LCA1MCk7XG4gICAgICAgIH07XG5cbiAgICAgICAgc2VsZi5faHR0cC5vbnByb2dyZXNzID0gZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgICAgIHNlbGYuX3JlY2VpdmVkKCk7XG4gICAgICAgIH07XG5cbiAgICAgICAgc2VsZi5faHR0cC5vbmxvYWQgPSBmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgaWYgKHNlbGYuX3VwZGF0ZVRpbWVyKSBjbGVhckludGVydmFsKHNlbGYuX3VwZGF0ZVRpbWVyKTtcbiAgICAgICAgICAgIHNlbGYuX3JlY2VpdmVkKCk7XG4gICAgICAgIH07XG5cbiAgICAgICAgLy8gQmFkIGV2ZW50c1xuICAgICAgICBzZWxmLl9odHRwLm9uYWJvcnQgPSBiaW5kKHNlbGYsIHNlbGYuX2Vycm9yKTtcbiAgICAgICAgc2VsZi5faHR0cC5vbmVycm9yID0gYmluZChzZWxmLCBzZWxmLl9lcnJvcik7XG4gICAgICAgIHNlbGYuX2h0dHAub250aW1lb3V0ID0gYmluZChzZWxmLCBzZWxmLl9lcnJvcik7XG5cbiAgICAgICAgc2VsZi5fcmVzcG9uc2VQYXJzZUluZGV4ID0gMDtcbiAgICAgICAgc2VsZi5fY2xvc2luZyA9IGZhbHNlO1xuICAgICAgICBzZWxmLl9hYm9ydGluZyA9IGZhbHNlO1xuICAgIH1cblxuICAgIHNodXRkb3duKCk6IHZvaWQge1xuICAgICAgICB0aGlzLl9jbG9zaW5nID0gdHJ1ZTtcbiAgICAgICAgaWYgKHRoaXMuX2h0dHApIHRoaXMuX2h0dHAuYWJvcnQoKTtcbiAgICB9XG5cbiAgICBzZW5kKHZvcnRleE1zZ3M6IHN0cmluZ1tdKSB7XG4gICAgICAgIGxldCBkYXRhID0gXCJcIjtcblxuICAgICAgICBmb3IgKGxldCB2b3J0ZXhNc2cgb2Ygdm9ydGV4TXNncykge1xuICAgICAgICAgICAgLy8gU2VyaWFsaXNlIHRoZSBwYXlsb2FkXG4gICAgICAgICAgICBkYXRhICs9IHZvcnRleE1zZyArIFwiLlwiO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gY29uc29sZS5sb2coXCJzZW5kaW5nIHBheWxvYWRcIik7XG4gICAgICAgIC8vIGNvbnNvbGUubG9nKHhtbFN0cik7XG4gICAgICAgIHRoaXMuX2h0dHAuc2VuZChkYXRhKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIF9yZWNlaXZlZCgpIHtcbiAgICAgICAgbGV0IHNlbGYgPSB0aGlzO1xuICAgICAgICAvKlxuICAgICAgICAgKiBSZWNlaXZlZFxuICAgICAgICAgKlxuICAgICAgICAgKiBDYWxsZWQgd2hlbiBwcm9ncmVzcyBpcyBtYWRlIG9uIHJlY2VpdmluZyBkYXRhIGZyb20gdGhlIHZvcnRleCBzZXJ2ZXIuXG4gICAgICAgICAqXG4gICAgICAgICAqIFRoaXMgbWVhbnMgdGhhdCBpdCBuZWVkcyB0byBiZSBhYmxlIHRvIGhhbmRsZSA6ICogcGFydGlhbCBwYXlsb2FkcyAoaW5cbiAgICAgICAgICogd2hpY2ggY2FzZSBpdCBkb2VzIG5vdGhpbmcpICogbXVsdGlwbGUgcGF5bG9hZHMgKGluIHdoaWNoIGNhc2UsIGl0IGJyZWFrc1xuICAgICAgICAgKiB0aGVtIHVwLCBwYXJzZXMgdGhlbSBhbmQgc2VuZHMgdGhlbSB0byB2b3J0ZXggaW5kaXZpZHVhbGx5KVxuICAgICAgICAgKi9cblxuICAgICAgICBpZiAoc2VsZi5fYWJvcnRpbmcpIHJldHVybjtcblxuICAgICAgICAvLyBJZiB3ZSByZWNlaXZlIHNvbWV0aGluZyB0aGF0IGlzIG5vdCB2YWxpZCB2b3J0ZXggZGF0YSwgdGhlbiByZWxvYWQgdGhlIHBhZ2VcbiAgICAgICAgLy8gVGhpcyB0eXBpY2FsbHkgb2NjdXJzIHdoZW4gd2UncmUgcmVjZXZpbmcgSFRNTCBiZWNhdXNlIHdlJ3JlIG5vdCBsb2dnZWQgaW4uXG4gICAgICAgIGlmICgvXjwvLnRlc3Qoc2VsZi5faHR0cC5yZXNwb25zZVRleHQpKSB7XG4gICAgICAgICAgICBzZWxmLnZvcnRleC5zZXRDbG9zZWRCeUNvbm5lY3Rpb24oKTtcbiAgICAgICAgICAgIHNlbGYuX2Nsb3NpbmcgPSB0cnVlO1xuICAgICAgICAgICAgc2VsZi5fYWJvcnRpbmcgPSB0cnVlO1xuICAgICAgICAgICAgc2VsZi5faHR0cC5hYm9ydCgpO1xuXG4gICAgICAgICAgICBsb2NhdGlvbi5yZWxvYWQoKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFNwbGl0IG91dCB0aGUgcGF5bG9hZHMgb2YgZGF0YSwgdGhleSBhcmUgZGVsaW1pdGVkIGJ5IGEgJy4nXG4gICAgICAgIGxldCBkYXRhID0gc2VsZi5faHR0cC5yZXNwb25zZVRleHQuc3Vic3RyKHNlbGYuX3Jlc3BvbnNlUGFyc2VJbmRleCk7XG4gICAgICAgIGxldCBwYXlsb2FkU2VwYXJhdG9ySW5kZXggPSBkYXRhLmluZGV4T2YoXCIuXCIpO1xuXG4gICAgICAgIHdoaWxlIChwYXlsb2FkU2VwYXJhdG9ySW5kZXggIT09IC0xKSB7XG4gICAgICAgICAgICBzZWxmLl9yZXNwb25zZVBhcnNlSW5kZXggKz0gcGF5bG9hZFNlcGFyYXRvckluZGV4ICsgMTtcblxuICAgICAgICAgICAgLy8gR2V0IHRoZSBiNjRlbmNvZGVkIHN0cmluZ1xuICAgICAgICAgICAgbGV0IHZvcnRleFN0ciA9IGRhdGEuc3Vic3RyKDAsIHBheWxvYWRTZXBhcmF0b3JJbmRleCk7XG5cbiAgICAgICAgICAgIGlmICh2b3J0ZXhTdHIubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgc2VsZi52b3J0ZXhCZWF0Q2FsbGJhY2soKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gQ3JlYXRlIHBheWxvYWQgb2JqZWN0IGZyb20gaXRcbiAgICAgICAgICAgICAgICAvLyBTZW5kIHRvIHZvcnRleFxuICAgICAgICAgICAgICAgIFBheWxvYWRFbnZlbG9wZS5mcm9tVm9ydGV4TXNnKHZvcnRleFN0cilcbiAgICAgICAgICAgICAgICAgICAgLnRoZW4oKHBlOiBQYXlsb2FkRW52ZWxvcGUpID0+IHNlbGYucmVjZWl2ZUNhbGxiYWNrKHBlKSlcbiAgICAgICAgICAgICAgICAgICAgLmNhdGNoKChlKSA9PlxuICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5sb2coXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYCR7ZGF0ZVN0cigpfSBBbiBlcnJvciBvY2N1cmVkIGRlc2VyaWFsaXNpbmcgJHtlfWAsXG4gICAgICAgICAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBkYXRhID0gc2VsZi5faHR0cC5yZXNwb25zZVRleHQuc3Vic3RyKHNlbGYuX3Jlc3BvbnNlUGFyc2VJbmRleCk7XG4gICAgICAgICAgICBwYXlsb2FkU2VwYXJhdG9ySW5kZXggPSBkYXRhLmluZGV4T2YoXCIuXCIpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gSW4gdGhlIGV2ZW50IHRoYXQgdGhlIGJyb3dzZXIgaXMgYnVmZmVyaW5nIGFsbCB0aGlzIGRhdGEsIHdlIHNob3VsZFxuICAgICAgICAvLyByZWNvbm5lY3QgdG8gYWxsb3cgdGhlIGJyb3dzZXIgdG8gY2xlYW51cC5cbiAgICAgICAgaWYgKFxuICAgICAgICAgICAgc2VsZi5faHR0cC5yZXNwb25zZVRleHQubGVuZ3RoID49XG4gICAgICAgICAgICBfVm9ydGV4Q2xpZW50SHR0cENvbm5lY3Rpb24uUkVDT05ORUNUX1NJWkVfTElNSVQgJiZcbiAgICAgICAgICAgICFzZWxmLl9jbG9zaW5nXG4gICAgICAgICkge1xuICAgICAgICAgICAgc2VsZi5fY2xvc2luZyA9IHRydWU7XG4gICAgICAgICAgICBzZWxmLnZvcnRleC5yZWNvbm5lY3QoKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgX2Vycm9yKGUpIHtcbiAgICAgICAgbGV0IHNlbGYgPSB0aGlzO1xuICAgICAgICBpZiAoc2VsZi5fdXBkYXRlVGltZXIpIGNsZWFySW50ZXJ2YWwoc2VsZi5fdXBkYXRlVGltZXIpO1xuXG4gICAgICAgIGlmIChzZWxmLl9hYm9ydGluZyB8fCB0aGlzLl9jbG9zaW5nKSByZXR1cm47XG5cbiAgICAgICAgbGV0IG1zZyA9IFwiXCI7XG5cbiAgICAgICAgaWYgKGUudHlwZSA9PT0gXCJhYm9ydFwiKSB7XG4gICAgICAgICAgICBtc2cgPSBcIlJlcXVlc3Qgd2FzIGFib3J0ZWQgYW5kIG5vdCBieSBWb3J0ZXhKU1wiO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBtc2cgPSBlLnRvU3RyaW5nKCk7XG4gICAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLl92b3J0ZXhbXCJzZXRDb25uZWN0aW5nXCJdKCk7XG4gICAgICAgIHRoaXMudm9ydGV4U3RhdHVzU2VydmljZS5sb2dFcnJvcihtc2cpO1xuICAgICAgICAvLyBjb25zb2xlLmxvZyhcIlZvcnRleENvbm5lY3Rpb24sIGNvbm5lY3Rpb24gZXJyb3JlZCBvdXQ6IFwiICsgbXNnKTtcbiAgICB9XG59XG4iXX0=