ehandler
Version:
Exception handler for Angular Applications
424 lines (416 loc) • 34.7 kB
JavaScript
import { Inject, Injectable, Injector, ErrorHandler, NgModule, defineInjectable, inject, INJECTOR } from '@angular/core';
import { HttpClient, HttpHeaders, HttpErrorResponse, HttpResponse, HTTP_INTERCEPTORS, HttpClientModule } from '@angular/common/http';
import { catchError, finalize, map } from 'rxjs/operators';
import { error } from 'toastr';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
var HookService = /** @class */ (function () {
function HookService(http, config) {
this.http = http;
this.config = config;
}
/**
* Send Message
*/
/**
* Send Message
* @param {?} payload
* @return {?}
*/
HookService.prototype.sendMessage = /**
* Send Message
* @param {?} payload
* @return {?}
*/
function (payload) {
this.http.post(this.config.hook, payload, { observe: 'response', responseType: 'text' }).subscribe(function (response) {
console.info('Message sent');
});
};
/**
* Send Exception to hook
*/
/**
* Send Exception to hook
* @param {?} error
* @param {?=} couse
* @return {?}
*/
HookService.prototype.exceptionNotify = /**
* Send Exception to hook
* @param {?} error
* @param {?=} couse
* @return {?}
*/
function (error$$1, couse) {
var _this = this;
if (couse === void 0) { couse = ''; }
/** @type {?} */
var status = error$$1.status ? error$$1.status : 'Application Error';
/** *
* Error Payload
@type {?} */
var payload = {
text: '--------------------------[ ' + status + ' ]--------------------------',
attachments: [
{
author_name: 'Cause: ' + couse + '\nURL: ' + window.location.href,
title: 'Message: ' + error$$1.message,
text: 'Date: ' + new Date() + '\nUserAgent: ' + navigator.userAgent +
'\n---------------------------------------------------------'
}
]
};
if (!this.bugged) {
/** @type {?} */
var headers = new HttpHeaders({
'Content-Type': 'text/plain'
});
this.http.post(this.config.hook, JSON.stringify(payload), { observe: 'response', responseType: 'text', headers: headers })
.pipe(catchError(function (e) {
_this.bugged = true;
console.log('Hook stopped working');
throw e;
}))
.subscribe(function (response) {
console.log('Exception Sent');
});
}
};
HookService.decorators = [
{ type: Injectable },
];
/** @nocollapse */
HookService.ctorParameters = function () { return [
{ type: HttpClient },
{ type: undefined, decorators: [{ type: Inject, args: ['configurations',] }] }
]; };
return HookService;
}());
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
var EHandlerService = /** @class */ (function () {
function EHandlerService(injector, config, hook) {
this.injector = injector;
this.config = config;
this.hook = hook;
}
/**
* Global Error Handler
*/
/**
* Global Error Handler
* @param {?} error
* @return {?}
*/
EHandlerService.prototype.handleError = /**
* Global Error Handler
* @param {?} error
* @return {?}
*/
function (error$$1) {
/** *
* Error Message for view
@type {?} */
var message;
/** *
* Error TimeStamp
@type {?} */
var date = new Date();
/**
* Handle errors occured while making server call
*/
if (error$$1 instanceof HttpErrorResponse) {
message = this.config.message.statusException;
/**
* If UnAuthorized
* Else If Server Error
*/
switch (error$$1.status) {
case 400:
case 401:
this.logout();
break;
case 500:
message = this.config.message.serverException;
}
// Backend returns unsuccessful response codes such as 404, 500 etc.
this.statusMessage(error$$1, date);
}
else {
// A client-side or network error occurred.
this.commonMessage(error$$1, date);
message = this.config.message.appException;
}
this.errorMSG(message);
};
/**
* Logout of system
*/
/**
* Logout of system
* @param {?=} message
* @return {?}
*/
EHandlerService.prototype.logout = /**
* Logout of system
* @param {?=} message
* @return {?}
*/
function (message) {
var _this = this;
error(this.config.message.unAuthenticated);
if (message) {
error(message);
}
setTimeout(function () {
window.location.replace(_this.config.logout);
}, 5000);
};
/**
* Show Error Message
*/
/**
* Show Error Message
* @param {?} message
* @param {?=} code
* @return {?}
*/
EHandlerService.prototype.errorMSG = /**
* Show Error Message
* @param {?} message
* @param {?=} code
* @return {?}
*/
function (message, code) {
if (code === void 0) { code = null; }
error(message, code);
};
/**
* Log Error Message
*/
/**
* Log Error Message
* @param {?} error
* @param {?=} date
* @return {?}
*/
EHandlerService.prototype.statusMessage = /**
* Log Error Message
* @param {?} error
* @param {?=} date
* @return {?}
*/
function (error$$1, date) {
if (date === void 0) { date = new Date(); }
console.error('--------------------------------------------\n', 'Backend returned status code: ' + error$$1.status + '\n', 'Response body ehandler:' + error$$1.message + '\n', date + '\n', '--------------------------------------------');
this.hook.exceptionNotify(error$$1.message, '----HTTP Error----');
};
/**
* Log Common Error
*/
/**
* Log Common Error
* @param {?} error
* @param {?=} date
* @return {?}
*/
EHandlerService.prototype.commonMessage = /**
* Log Common Error
* @param {?} error
* @param {?=} date
* @return {?}
*/
function (error$$1, date) {
if (date === void 0) { date = new Date(); }
console.error('--------------------------------------------\n', 'An error occurred ehandler:' + error$$1.message + '\n', date + '\n', '--------------------------------------------');
this.hook.exceptionNotify(error$$1.message, '----Common Error----');
};
EHandlerService.decorators = [
{ type: Injectable, args: [{
providedIn: 'root'
},] },
];
/** @nocollapse */
EHandlerService.ctorParameters = function () { return [
{ type: Injector },
{ type: undefined, decorators: [{ type: Inject, args: ['configurations',] }] },
{ type: HookService }
]; };
/** @nocollapse */ EHandlerService.ngInjectableDef = defineInjectable({ factory: function EHandlerService_Factory() { return new EHandlerService(inject(INJECTOR), inject("configurations"), inject(HookService)); }, token: EHandlerService, providedIn: "root" });
return EHandlerService;
}());
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
var EIntercepterService = /** @class */ (function () {
function EIntercepterService(config, eh) {
this.config = config;
this.eh = eh;
}
/**
* @param {?} req
* @param {?} next
* @return {?}
*/
EIntercepterService.prototype.intercept = /**
* @param {?} req
* @param {?} next
* @return {?}
*/
function (req, next) {
var _this = this;
return next.handle(req).pipe(map(function (event) {
if (event instanceof HttpResponse) {
/** @type {?} */
var requestData = event.body;
if (requestData) {
if (requestData.exception && requestData.exception.code) {
try {
if (_this.config && _this.config.logoutCodes && _this.config.logoutCodes.indexOf(requestData.exception.code) !== -1) {
_this.eh.logout();
}
else {
/** @type {?} */
var error$$1 = {
code: requestData.exception.code,
message: requestData.exception.message
};
_this.eh.errorMSG(error$$1.message, error$$1.code);
_this.eh.statusMessage(error$$1);
}
}
catch (e) {
console.log('There was an error while trying to send message');
}
}
else if (requestData.error && requestData.error.code) {
try {
if (_this.config && _this.config.logoutCodes && _this.config.logoutCodes.indexOf(requestData.error.code) !== -1) {
_this.eh.logout();
}
else {
/** @type {?} */
var error$$1 = {
code: requestData.error.code,
message: requestData.error.message
};
_this.eh.errorMSG(error$$1.message, error$$1.code);
_this.eh.statusMessage(error$$1);
}
}
catch (e) {
console.log('There was an error while trying to send message');
}
}
}
}
return event;
}), catchError(function (error$$1) {
_this.eh.handleError(error$$1);
throw error$$1;
}), finalize(function () { }));
};
EIntercepterService.decorators = [
{ type: Injectable },
];
/** @nocollapse */
EIntercepterService.ctorParameters = function () { return [
{ type: undefined, decorators: [{ type: Inject, args: ['configurations',] }] },
{ type: EHandlerService }
]; };
return EIntercepterService;
}());
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
/** @type {?} */
var InitialConfig = {
message: {
unAuthenticated: 'Xahiş olunur sistemə daxil olun!',
statusException: 'Status xətası',
serverException: 'Server xətası',
appException: 'Sistem xətası'
},
logout: '/logout',
logoutCodes: [
401,
1005,
1006,
1014,
1015,
1016,
1017,
1401,
],
hook: 'https://hooks.slack.com/services/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',
};
var EHandlerModule = /** @class */ (function () {
function EHandlerModule() {
}
/**
* @param {?=} configurations
* @return {?}
*/
EHandlerModule.forRoot = /**
* @param {?=} configurations
* @return {?}
*/
function (configurations) {
if (configurations === void 0) { configurations = InitialConfig; }
return {
ngModule: EHandlerModule,
providers: [
{ provide: 'configurations', useValue: configurations },
],
};
};
/**
* @return {?}
*/
EHandlerModule.forChild = /**
* @return {?}
*/
function () {
return {
ngModule: EHandlerModule,
};
};
EHandlerModule.decorators = [
{ type: NgModule, args: [{
imports: [
HttpClientModule,
BrowserAnimationsModule
],
providers: [
{ provide: ErrorHandler, useClass: EHandlerService },
{
provide: HTTP_INTERCEPTORS,
useClass: EIntercepterService,
multi: true
},
HookService
],
declarations: [],
exports: []
},] },
];
return EHandlerModule;
}());
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
export { EHandlerService, EIntercepterService, InitialConfig, EHandlerModule, HookService as ɵb };
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZWhhbmRsZXIuanMubWFwIiwic291cmNlcyI6WyJuZzovL2VoYW5kbGVyL2xpYi9ob29rLnNlcnZpY2UudHMiLCJuZzovL2VoYW5kbGVyL2xpYi9laGFuZGxlci5zZXJ2aWNlLnRzIiwibmc6Ly9laGFuZGxlci9saWIvZWludGVyY2VwdGVyLnNlcnZpY2UudHMiLCJuZzovL2VoYW5kbGVyL2xpYi9laGFuZGxlci5tb2R1bGUudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtJbmplY3QsIEluamVjdGFibGV9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5pbXBvcnQge0h0dHBDbGllbnQsIEh0dHBIZWFkZXJzfSBmcm9tICdAYW5ndWxhci9jb21tb24vaHR0cCc7XHJcbmltcG9ydCB7Q29uZmlnfSBmcm9tICcuL2NvbnN0L2NvbmZpZyc7XHJcbmltcG9ydCB7Y2F0Y2hFcnJvciwgbWFwfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XHJcblxyXG5ASW5qZWN0YWJsZSgpXHJcblxyXG5leHBvcnQgY2xhc3MgSG9va1NlcnZpY2Uge1xyXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgaHR0cDogSHR0cENsaWVudCwgQEluamVjdCgnY29uZmlndXJhdGlvbnMnKSBwcml2YXRlIGNvbmZpZzogQ29uZmlnKSB7fVxyXG4gIHByaXZhdGUgYnVnZ2VkOiBib29sZWFuO1xyXG4gIC8qKlxyXG4gICAqIFNlbmQgTWVzc2FnZVxyXG4gICAqL1xyXG4gIHNlbmRNZXNzYWdlKHBheWxvYWQ6IGFueSkge1xyXG4gICAgdGhpcy5odHRwLnBvc3QodGhpcy5jb25maWcuaG9vaywgcGF5bG9hZCwge29ic2VydmU6ICdyZXNwb25zZScsIHJlc3BvbnNlVHlwZTogJ3RleHQnfSkuc3Vic2NyaWJlKCByZXNwb25zZSA9PiB7XHJcbiAgICAgIGNvbnNvbGUuaW5mbygnTWVzc2FnZSBzZW50Jyk7XHJcbiAgICB9KTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqICBTZW5kIEV4Y2VwdGlvbiB0byBob29rXHJcbiAgICovXHJcbiAgZXhjZXB0aW9uTm90aWZ5KGVycm9yLCBjb3VzZSA9ICcnKSB7XHJcbiAgICBjb25zdCBzdGF0dXMgPSBlcnJvci5zdGF0dXMgPyBlcnJvci5zdGF0dXMgOiAnQXBwbGljYXRpb24gRXJyb3InO1xyXG4gICAgLyoqXHJcbiAgICAgKiBFcnJvciBQYXlsb2FkXHJcbiAgICAgKi9cclxuICAgIGNvbnN0IHBheWxvYWQgPSB7XHJcbiAgICAgIHRleHQ6ICctLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVsgJyArIHN0YXR1cyArICcgXS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tJyxcclxuICAgICAgYXR0YWNobWVudHM6IFtcclxuICAgICAgICB7XHJcbiAgICAgICAgICBhdXRob3JfbmFtZTogJ0NhdXNlOiAnICsgY291c2UgKyAnXFxuVVJMOiAnICsgd2luZG93LmxvY2F0aW9uLmhyZWYsXHJcbiAgICAgICAgICB0aXRsZTogJ01lc3NhZ2U6ICcgKyBlcnJvci5tZXNzYWdlLFxyXG4gICAgICAgICAgdGV4dDogJ0RhdGU6ICcgKyBuZXcgRGF0ZSgpICsgJ1xcblVzZXJBZ2VudDogJyArIG5hdmlnYXRvci51c2VyQWdlbnQgK1xyXG4gICAgICAgICAgJ1xcbi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSdcclxuICAgICAgICB9XHJcbiAgICAgIF1cclxuICAgIH07XHJcbiAgICBpZiAoIXRoaXMuYnVnZ2VkKSB7XHJcbiAgICAgIGNvbnN0IGhlYWRlcnMgPSBuZXcgSHR0cEhlYWRlcnMoe1xyXG4gICAgICAgICdDb250ZW50LVR5cGUnOiAndGV4dC9wbGFpbidcclxuICAgICAgfSlcclxuICAgICAgdGhpcy5odHRwLnBvc3QodGhpcy5jb25maWcuaG9vaywgSlNPTi5zdHJpbmdpZnkocGF5bG9hZCksIHtvYnNlcnZlOiAncmVzcG9uc2UnLCByZXNwb25zZVR5cGU6ICd0ZXh0JywgaGVhZGVyc30pXHJcbiAgICAgICAgLnBpcGUoXHJcbiAgICAgICAgICBjYXRjaEVycm9yKGUgPT4ge1xyXG4gICAgICAgICAgICB0aGlzLmJ1Z2dlZCA9IHRydWU7XHJcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKCdIb29rIHN0b3BwZWQgd29ya2luZycpO1xyXG4gICAgICAgICAgICB0aHJvdyBlO1xyXG4gICAgICAgICAgfSlcclxuICAgICAgICApXHJcbiAgICAgICAgLnN1YnNjcmliZSggcmVzcG9uc2UgPT4ge1xyXG4gICAgICAgICAgY29uc29sZS5sb2coJ0V4Y2VwdGlvbiBTZW50Jyk7XHJcbiAgICAgICAgfSk7XHJcbiAgICB9XHJcblxyXG4gIH1cclxufVxyXG4iLCJpbXBvcnQge0Vycm9ySGFuZGxlciwgSW5qZWN0LCBJbmplY3RhYmxlLCBJbmplY3Rvcn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XHJcbmltcG9ydCB7SHR0cEVycm9yUmVzcG9uc2V9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbi9odHRwJztcclxuaW1wb3J0IHtDb25maWd9IGZyb20gJy4vY29uc3QvY29uZmlnJztcclxuaW1wb3J0IHtIb29rU2VydmljZX0gZnJvbSAnLi9ob29rLnNlcnZpY2UnO1xyXG5pbXBvcnQgKiBhcyB0b2FzdHIgZnJvbSAndG9hc3RyJztcclxuQEluamVjdGFibGUoe1xyXG4gIHByb3ZpZGVkSW46ICdyb290J1xyXG59KVxyXG5leHBvcnQgY2xhc3MgRUhhbmRsZXJTZXJ2aWNlIGltcGxlbWVudHMgRXJyb3JIYW5kbGVyIHtcclxuICBjb25zdHJ1Y3RvcihcclxuICAgIHByaXZhdGUgaW5qZWN0b3I6IEluamVjdG9yLFxyXG4gICAgQEluamVjdCgnY29uZmlndXJhdGlvbnMnKSBwcml2YXRlIGNvbmZpZzogQ29uZmlnLFxyXG4gICAgcHJpdmF0ZSBob29rOiBIb29rU2VydmljZSxcclxuICApIHtcclxuICB9XHJcbiAgLyoqXHJcbiAgICogR2xvYmFsIEVycm9yIEhhbmRsZXJcclxuICAgKi9cclxuICBoYW5kbGVFcnJvcihlcnJvcjogYW55KSB7XHJcbiAgICAvKipcclxuICAgICAqIEVycm9yIE1lc3NhZ2UgZm9yIHZpZXdcclxuICAgICAqL1xyXG4gICAgbGV0IG1lc3NhZ2U6IHN0cmluZztcclxuICAgIC8qKlxyXG4gICAgICogRXJyb3IgVGltZVN0YW1wXHJcbiAgICAgKi9cclxuICAgIGNvbnN0IGRhdGU6IERhdGUgPSBuZXcgRGF0ZSgpO1xyXG4gICAgLyoqXHJcbiAgICAgKiBIYW5kbGUgZXJyb3JzIG9jY3VyZWQgd2hpbGUgbWFraW5nIHNlcnZlciBjYWxsXHJcbiAgICAgKi9cclxuICAgIGlmIChlcnJvciBpbnN0YW5jZW9mIEh0dHBFcnJvclJlc3BvbnNlKSB7XHJcbiAgICAgIG1lc3NhZ2UgPSB0aGlzLmNvbmZpZy5tZXNzYWdlLnN0YXR1c0V4Y2VwdGlvbjtcclxuICAgICAgLyoqXHJcbiAgICAgICAqIElmIFVuQXV0aG9yaXplZFxyXG4gICAgICAgKiBFbHNlIElmIFNlcnZlciBFcnJvclxyXG4gICAgICAgKi9cclxuICAgICAgc3dpdGNoIChlcnJvci5zdGF0dXMpIHtcclxuICAgICAgICBjYXNlIDQwMDpcclxuICAgICAgICBjYXNlIDQwMTpcclxuICAgICAgICAgIHRoaXMubG9nb3V0KCk7XHJcbiAgICAgICAgICBicmVhaztcclxuICAgICAgICBjYXNlIDUwMDpcclxuICAgICAgICAgIG1lc3NhZ2UgPSB0aGlzLmNvbmZpZy5tZXNzYWdlLnNlcnZlckV4Y2VwdGlvbjtcclxuICAgICAgfVxyXG4gICAgICAvLyBCYWNrZW5kIHJldHVybnMgdW5zdWNjZXNzZnVsIHJlc3BvbnNlIGNvZGVzIHN1Y2ggYXMgNDA0LCA1MDAgZXRjLlxyXG4gICAgICB0aGlzLnN0YXR1c01lc3NhZ2UoZXJyb3IsIGRhdGUpO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgLy8gQSBjbGllbnQtc2lkZSBvciBuZXR3b3JrIGVycm9yIG9jY3VycmVkLlxyXG4gICAgICB0aGlzLmNvbW1vbk1lc3NhZ2UoZXJyb3IsIGRhdGUpO1xyXG4gICAgICBtZXNzYWdlID0gdGhpcy5jb25maWcubWVzc2FnZS5hcHBFeGNlcHRpb247XHJcbiAgICB9XHJcbiAgICB0aGlzLmVycm9yTVNHKG1lc3NhZ2UpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogTG9nb3V0IG9mIHN5c3RlbVxyXG4gICAqL1xyXG4gIGxvZ291dChtZXNzYWdlPzogc3RyaW5nKSB7XHJcbiAgICB0b2FzdHIuZXJyb3IodGhpcy5jb25maWcubWVzc2FnZS51bkF1dGhlbnRpY2F0ZWQpO1xyXG4gICAgaWYgKG1lc3NhZ2UpIHtcclxuICAgICAgdG9hc3RyLmVycm9yKG1lc3NhZ2UpO1xyXG4gICAgfVxyXG4gICAgc2V0VGltZW91dCgoKSA9PiB7XHJcbiAgICAgIHdpbmRvdy5sb2NhdGlvbi5yZXBsYWNlKHRoaXMuY29uZmlnLmxvZ291dCk7XHJcbiAgICB9LCA1MDAwKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFNob3cgRXJyb3IgTWVzc2FnZVxyXG4gICAqL1xyXG4gIGVycm9yTVNHKG1lc3NhZ2UsIGNvZGUgPSBudWxsKSB7XHJcbiAgICB0b2FzdHIuZXJyb3IobWVzc2FnZSwgY29kZSk7XHJcbiAgfVxyXG4gIC8qKlxyXG4gICAqIExvZyBFcnJvciBNZXNzYWdlXHJcbiAgICovXHJcbiAgc3RhdHVzTWVzc2FnZShlcnJvciwgZGF0ZSA9IG5ldyBEYXRlKCkpIHtcclxuICAgIGNvbnNvbGUuZXJyb3IoXHJcbiAgICAgICctLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxcbicsXHJcbiAgICAgICdCYWNrZW5kIHJldHVybmVkIHN0YXR1cyBjb2RlOiAnICsgZXJyb3Iuc3RhdHVzICsgJ1xcbicsXHJcbiAgICAgICdSZXNwb25zZSBib2R5IGVoYW5kbGVyOicgKyBlcnJvci5tZXNzYWdlICsgJ1xcbicsXHJcbiAgICAgIGRhdGUgKyAnXFxuJyxcclxuICAgICAgJy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tJ1xyXG4gICAgKTtcclxuICAgICAgdGhpcy5ob29rLmV4Y2VwdGlvbk5vdGlmeShlcnJvci5tZXNzYWdlLCAnLS0tLUhUVFAgRXJyb3ItLS0tJyk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBMb2cgQ29tbW9uIEVycm9yXHJcbiAgICovXHJcbiAgY29tbW9uTWVzc2FnZShlcnJvciwgZGF0ZSA9IG5ldyBEYXRlKCkpIHtcclxuICAgIGNvbnNvbGUuZXJyb3IoXHJcbiAgICAgICctLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxcbicsXHJcbiAgICAgICdBbiBlcnJvciBvY2N1cnJlZCBlaGFuZGxlcjonICsgZXJyb3IubWVzc2FnZSArICdcXG4nLFxyXG4gICAgICBkYXRlICsgJ1xcbicsXHJcbiAgICAgICctLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSdcclxuICAgICk7XHJcbiAgICB0aGlzLmhvb2suZXhjZXB0aW9uTm90aWZ5KGVycm9yLm1lc3NhZ2UsICctLS0tQ29tbW9uIEVycm9yLS0tLScpO1xyXG4gIH1cclxufVxyXG4iLCJpbXBvcnQge0luamVjdCwgSW5qZWN0YWJsZX0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQge0h0dHBFdmVudCwgSHR0cEhhbmRsZXIsIEh0dHBJbnRlcmNlcHRvciwgSHR0cFJlcXVlc3QsIEh0dHBSZXNwb25zZX0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uL2h0dHAnO1xuaW1wb3J0IHtPYnNlcnZhYmxlfSBmcm9tICdyeGpzJztcbmltcG9ydCB7Y2F0Y2hFcnJvciwgZmluYWxpemUsIG1hcH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuaW1wb3J0IHtDb25maWd9IGZyb20gJy4vY29uc3QvY29uZmlnJztcbmltcG9ydCB7RUhhbmRsZXJTZXJ2aWNlfSBmcm9tICcuL2VoYW5kbGVyLnNlcnZpY2UnO1xuXG5ASW5qZWN0YWJsZSgpXG5leHBvcnQgY2xhc3MgRUludGVyY2VwdGVyU2VydmljZSBpbXBsZW1lbnRzIEh0dHBJbnRlcmNlcHRvciB7XG4gIGNvbnN0cnVjdG9yKEBJbmplY3QoJ2NvbmZpZ3VyYXRpb25zJykgcHJpdmF0ZSBjb25maWc6IENvbmZpZywgcHJpdmF0ZSBlaDogRUhhbmRsZXJTZXJ2aWNlKSB7IH1cbiAgaW50ZXJjZXB0KFxuICAgIHJlcTogSHR0cFJlcXVlc3Q8YW55PixcbiAgICBuZXh0OiBIdHRwSGFuZGxlclxuICApOiBPYnNlcnZhYmxlPEh0dHBFdmVudDxhbnk+PiB7XG4gICAgcmV0dXJuIG5leHQuaGFuZGxlKHJlcSkucGlwZShcbiAgICAgIG1hcChldmVudCA9PiB7XG4gICAgICAgIGlmIChldmVudCBpbnN0YW5jZW9mIEh0dHBSZXNwb25zZSkge1xuICAgICAgICAgIGNvbnN0IHJlcXVlc3REYXRhID0gZXZlbnQuYm9keTtcbiAgICAgICAgICBpZiAocmVxdWVzdERhdGEpIHtcbiAgICAgICAgICAgIGlmIChyZXF1ZXN0RGF0YS5leGNlcHRpb24gJiYgcmVxdWVzdERhdGEuZXhjZXB0aW9uLmNvZGUpIHtcbiAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5jb25maWcgJiYgdGhpcy5jb25maWcubG9nb3V0Q29kZXMgJiYgdGhpcy5jb25maWcubG9nb3V0Q29kZXMuaW5kZXhPZihyZXF1ZXN0RGF0YS5leGNlcHRpb24uY29kZSkgIT09IC0xICkge1xuICAgICAgICAgICAgICAgICAgdGhpcy5laC5sb2dvdXQoKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgY29uc3QgZXJyb3IgPSB7XG4gICAgICAgICAgICAgICAgICAgIGNvZGU6IHJlcXVlc3REYXRhLmV4Y2VwdGlvbi5jb2RlLFxuICAgICAgICAgICAgICAgICAgICBtZXNzYWdlOiByZXF1ZXN0RGF0YS5leGNlcHRpb24ubWVzc2FnZVxuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgdGhpcy5laC5lcnJvck1TRyhlcnJvci5tZXNzYWdlLCBlcnJvci5jb2RlKTtcbiAgICAgICAgICAgICAgICAgIHRoaXMuZWguc3RhdHVzTWVzc2FnZShlcnJvcik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5sb2coJ1RoZXJlIHdhcyBhbiBlcnJvciB3aGlsZSB0cnlpbmcgdG8gc2VuZCBtZXNzYWdlJyk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSBpZiAocmVxdWVzdERhdGEuZXJyb3IgJiYgcmVxdWVzdERhdGEuZXJyb3IuY29kZSkge1xuICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLmNvbmZpZyAmJiB0aGlzLmNvbmZpZy5sb2dvdXRDb2RlcyAmJiB0aGlzLmNvbmZpZy5sb2dvdXRDb2Rlcy5pbmRleE9mKHJlcXVlc3REYXRhLmVycm9yLmNvZGUpICE9PSAtMSApIHtcbiAgICAgICAgICAgICAgICAgIHRoaXMuZWgubG9nb3V0KCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgIGNvbnN0IGVycm9yID0ge1xuICAgICAgICAgICAgICAgICAgICBjb2RlOiByZXF1ZXN0RGF0YS5lcnJvci5jb2RlLFxuICAgICAgICAgICAgICAgICAgICBtZXNzYWdlOiByZXF1ZXN0RGF0YS5lcnJvci5tZXNzYWdlXG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICB0aGlzLmVoLmVycm9yTVNHKGVycm9yLm1lc3NhZ2UsIGVycm9yLmNvZGUpO1xuICAgICAgICAgICAgICAgICAgdGhpcy5laC5zdGF0dXNNZXNzYWdlKGVycm9yKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmxvZygnVGhlcmUgd2FzIGFuIGVycm9yIHdoaWxlIHRyeWluZyB0byBzZW5kIG1lc3NhZ2UnKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZXZlbnQ7XG4gICAgICB9KSxcbiAgICAgIGNhdGNoRXJyb3IoZXJyb3IgPT4ge1xuICAgICAgICB0aGlzLmVoLmhhbmRsZUVycm9yKGVycm9yKTtcbiAgICAgICAgdGhyb3cgZXJyb3I7XG4gICAgICB9KSxcbiAgICAgIGZpbmFsaXplKCgpID0+IHt9KVxuICAgICk7XG4gIH1cbn1cbiIsImltcG9ydCB7RXJyb3JIYW5kbGVyLCBNb2R1bGVXaXRoUHJvdmlkZXJzLCBOZ01vZHVsZX0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQge0NvbmZpZ30gZnJvbSAnLi9jb25zdC9jb25maWcnO1xuaW1wb3J0IHtFSW50ZXJjZXB0ZXJTZXJ2aWNlfSBmcm9tICcuL2VpbnRlcmNlcHRlci5zZXJ2aWNlJztcbmltcG9ydCB7RUhhbmRsZXJTZXJ2aWNlfSBmcm9tICcuL2VoYW5kbGVyLnNlcnZpY2UnO1xuaW1wb3J0IHtIVFRQX0lOVEVSQ0VQVE9SUywgSHR0cENsaWVudE1vZHVsZX0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uL2h0dHAnO1xuaW1wb3J0IHtCcm93c2VyQW5pbWF0aW9uc01vZHVsZX0gZnJvbSAnQGFuZ3VsYXIvcGxhdGZvcm0tYnJvd3Nlci9hbmltYXRpb25zJztcbmltcG9ydCB7SG9va1NlcnZpY2V9IGZyb20gJy4vaG9vay5zZXJ2aWNlJztcblxuZXhwb3J0IGNvbnN0IEluaXRpYWxDb25maWc6IENvbmZpZyA9IHtcbiAgbWVzc2FnZToge1xuICAgIHVuQXV0aGVudGljYXRlZDogJ1hhaGnDhcKfIG9sdW51ciBzaXN0ZW3DicKZIGRheGlsIG9sdW4hJyxcbiAgICBzdGF0dXNFeGNlcHRpb246ICdTdGF0dXMgeMOJwpl0YXPDhMKxJyxcbiAgICBzZXJ2ZXJFeGNlcHRpb246ICdTZXJ2ZXIgeMOJwpl0YXPDhMKxJyxcbiAgICBhcHBFeGNlcHRpb246ICdTaXN0ZW0geMOJwpl0YXPDhMKxJ1xuICB9LFxuICBsb2dvdXQ6ICcvbG9nb3V0JyxcbiAgbG9nb3V0Q29kZXM6IFtcbiAgICA0MDEsICAvLyBCdSDDg8K8bnZhbmEgaWNhesOJwpluaXogeW94ZHVyXG4gICAgMTAwNSwgLy8gWW91IGFyZSBub3QgYWxsb3dlZCB0byByZXF1ZXN0IHRoaXMgcmVzb3VyY2VcbiAgICAxMDA2LCAvLyBUb2tlbiB0YXDDhMKxbG1hZMOEwrFcbiAgICAxMDE0LCAvLyBUb2tlbiB0YXDDhMKxbG1hZMOEwrEsIHrDicKZaG3DicKZdCBvbG1hc2Egc2lzdGVtw4nCmSB5ZW5pZMOJwpluIGRheGlsIG9sdW5cbiAgICAxMDE1LCAvLyBTaXppbiBzaXN0ZW1sw4nCmXJkw4nCmW4gaXN0aWbDicKZZMOJwpkgaMODwrxxdXF1bnV6IHlveGR1clxuICAgIDEwMTYsIC8vIFNpemluIGJ1IHNpc3RlbcOJwpkgaXN0aWbDicKZZMOJwpkgaMODwrxxdXF1bnV6IHlveGR1clxuICAgIDEwMTcsIC8vIFNlc3NpeWEgYmHDhMKfbGFubcOEwrHDhcKfZMOEwrFyLCB6w4nCmWhtw4nCmXQgb2xtYXNhIHNpc3RlbcOJwpkgeWVuaWTDicKZbiBkYXhpbCBvbHVuLlxuICAgIDE0MDEsIC8vIFNlc3NpeWEgbcODwrxkZMOJwpl0aSBiaXRtacOFwp9kaXIsIHrDicKZaG3DicKZdCBvbG1henNhIHNpc3RlbcOJwpkgeWVuaWTDicKZbiBkYXhpbCBvbHVuXG4gICAgLy8gMTQwMiAgLy8gU2l6aW4gYnUgc2Vydmlzw4nCmSBpY2F6w4nCmW5peiB5b3hkdXJcbiAgXSxcbiAgaG9vazogJ2h0dHBzOi8vaG9va3Muc2xhY2suY29tL3NlcnZpY2VzL1RDMTBHSDQ4Wi9CQzJBMjlZMlovdHB4VjBpSUhoajJmVFM2Rk8wUEExQ3pjJyxcbn1cblxuQE5nTW9kdWxlKHtcbiAgaW1wb3J0czogW1xuICAgIEh0dHBDbGllbnRNb2R1bGUsXG4gICAgQnJvd3NlckFuaW1hdGlvbnNNb2R1bGVcbiAgXSxcbiAgcHJvdmlkZXJzOiBbXG4gICAgeyBwcm92aWRlOiBFcnJvckhhbmRsZXIsIHVzZUNsYXNzOiBFSGFuZGxlclNlcnZpY2UgfSxcbiAgICB7XG4gICAgICBwcm92aWRlOiBIVFRQX0lOVEVSQ0VQVE9SUyxcbiAgICAgIHVzZUNsYXNzOiBFSW50ZXJjZXB0ZXJTZXJ2aWNlLFxuICAgICAgbXVsdGk6IHRydWVcbiAgICB9LFxuICAgIEhvb2tTZXJ2aWNlXG4gIF0sXG4gIGRlY2xhcmF0aW9uczogW10sXG4gIGV4cG9ydHM6IFtdXG59KVxuZXhwb3J0IGNsYXNzIEVIYW5kbGVyTW9kdWxlIHtcbiAgc3RhdGljIGZvclJvb3QoY29uZmlndXJhdGlvbnMgPSBJbml0aWFsQ29uZmlnKTogTW9kdWxlV2l0aFByb3ZpZGVycyB7XG4gICAgcmV0dXJuIHtcbiAgICAgIG5nTW9kdWxlOiBFSGFuZGxlck1vZHVsZSxcbiAgICAgIHByb3ZpZGVyczogW1xuICAgICAgICB7cHJvdmlkZTogJ2NvbmZpZ3VyYXRpb25zJywgdXNlVmFsdWU6IGNvbmZpZ3VyYXRpb25zfSxcbiAgICAgIF0sXG4gICAgfTtcbiAgfVxuICBzdGF0aWMgZm9yQ2hpbGQoKTogTW9kdWxlV2l0aFByb3ZpZGVycyB7XG5cbiAgICByZXR1cm57XG4gICAgICBuZ01vZHVsZTogRUhhbmRsZXJNb2R1bGUsXG4gICAgfTtcblxuICB9XG5cbn1cbiJdLCJuYW1lcyI6WyJlcnJvciIsInRvYXN0ci5lcnJvciJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7OztBQUFBO0lBUUUscUJBQW9CLElBQWdCLEVBQW9DLE1BQWM7UUFBbEUsU0FBSSxHQUFKLElBQUksQ0FBWTtRQUFvQyxXQUFNLEdBQU4sTUFBTSxDQUFRO0tBQUk7Ozs7Ozs7OztJQUsxRixpQ0FBVzs7Ozs7SUFBWCxVQUFZLE9BQVk7UUFDdEIsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLEVBQUUsT0FBTyxFQUFFLEVBQUMsT0FB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