@trendster-io/ng-uploader
Version:
A fully featured Angular file uploader that utilizes Angular's HttpClient internally, allows you to customize outgoing HTTP requests using the "Angular Way" (Interceptors), provides customizable concurrent queuing of uploads and a simple way to select fil
702 lines • 47.6 kB
JavaScript
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
import { HttpEventType } from '@angular/common/http';
import { Subject, Observable, of } from 'rxjs';
import { mergeMap, tap, filter, map, catchError, finalize } from 'rxjs/operators';
import { UploadItem } from './upload-item.class';
export class Uploader {
/**
* @param {?} httpClient
* @param {?=} options
*/
constructor(httpClient, options = {}) {
this.httpClient = httpClient;
this.onItemSuccessSubject = new Subject();
this.onItemProgressSubject = new Subject();
this.onItemErrorSubject = new Subject();
this.onItemSuccess = this.onItemSuccessSubject.asObservable();
this.onItemProgress = this.onItemProgressSubject.asObservable();
this.onItemError = this.onItemErrorSubject.asObservable();
this._totalProgress = 0;
this.url = options.url;
this.method = options.method;
this.autoUpload = options.autoUpload;
this.removeAfterUpload = options.removeAfterUpload;
this.queueLimit = options.queueLimit;
this.concurrency = options.concurrency || 1;
this.maxFileSize = options.maxFileSize;
this.allowedMimeTypes = options.allowedMimeTypes;
this.setupQueue();
}
/**
* @return {?}
*/
get itemsCount() {
return this.queue.length;
}
/**
* @return {?}
*/
get items() {
return this.queue.map((/**
* @param {?} queueItem
* @return {?}
*/
queueItem => queueItem.item));
}
/**
* @return {?}
*/
get readyItemsCount() {
return this.queue
.map((/**
* @param {?} queueItem
* @return {?}
*/
queueItem => queueItem.item))
.filter((/**
* @param {?} item
* @return {?}
*/
item => item.isReady && !item.isUploading)).length;
}
/**
* @private
* @return {?}
*/
get readyItems() {
return this.queue
.map((/**
* @param {?} queueItem
* @return {?}
*/
queueItem => queueItem.item))
.filter((/**
* @param {?} item
* @return {?}
*/
item => item.isReady && !item.isUploading));
}
/**
* @return {?}
*/
get uploadingItemsCount() {
return this.queue
.map((/**
* @param {?} queueItem
* @return {?}
*/
queueItem => queueItem.item))
.filter((/**
* @param {?} item
* @return {?}
*/
item => item.isUploading)).length;
}
/**
* @private
* @return {?}
*/
get uploadingItems() {
return this.queue
.map((/**
* @param {?} queueItem
* @return {?}
*/
queueItem => queueItem.item))
.filter((/**
* @param {?} item
* @return {?}
*/
item => item.isUploading));
}
/**
* @return {?}
*/
get uploadedItemsCount() {
return this.queue
.map((/**
* @param {?} queueItem
* @return {?}
*/
queueItem => queueItem.item))
.filter((/**
* @param {?} item
* @return {?}
*/
item => item.isUploaded)).length;
}
/**
* @private
* @return {?}
*/
get uploadedItems() {
return this.queue
.map((/**
* @param {?} queueItem
* @return {?}
*/
queueItem => queueItem.item))
.filter((/**
* @param {?} item
* @return {?}
*/
item => item.isUploaded));
}
/**
* @return {?}
*/
get notUploadedItemsCount() {
return this.queue
.map((/**
* @param {?} queueItem
* @return {?}
*/
queueItem => queueItem.item))
.filter((/**
* @param {?} item
* @return {?}
*/
item => !item.isUploaded)).length;
}
/**
* @private
* @return {?}
*/
get notUploadedItems() {
return this.queue
.map((/**
* @param {?} queueItem
* @return {?}
*/
queueItem => queueItem.item))
.filter((/**
* @param {?} item
* @return {?}
*/
item => !item.isUploaded));
}
/**
* @return {?}
*/
get cancelledItemsCount() {
return this.queue
.map((/**
* @param {?} queueItem
* @return {?}
*/
queueItem => queueItem.item))
.filter((/**
* @param {?} item
* @return {?}
*/
item => item.isCancelled)).length;
}
/**
* @private
* @return {?}
*/
get cancelledItems() {
return this.queue
.map((/**
* @param {?} queueItem
* @return {?}
*/
queueItem => queueItem.item))
.filter((/**
* @param {?} item
* @return {?}
*/
item => item.isCancelled));
}
/**
* @return {?}
*/
get errorItemsCount() {
return this.queue
.map((/**
* @param {?} queueItem
* @return {?}
*/
queueItem => queueItem.item))
.filter((/**
* @param {?} item
* @return {?}
*/
item => item.isError)).length;
}
/**
* @private
* @return {?}
*/
get errorItems() {
return this.queue
.map((/**
* @param {?} queueItem
* @return {?}
*/
queueItem => queueItem.item))
.filter((/**
* @param {?} item
* @return {?}
*/
item => item.isError));
}
/**
* @return {?}
*/
get totalProgress() {
return this._totalProgress;
}
/**
* @return {?}
*/
get isUploading() {
return this.uploadingItemsCount > 0;
}
/**
* @private
* @param {?} __0
* @return {?}
*/
onQueueItemSuccess({ item, res }) {
item.onUploadSuccess(res);
this.onItemSuccessSubject.next({ item, res });
if (this.removeAfterUpload) {
item.remove();
}
}
/**
* @private
* @param {?} __0
* @return {?}
*/
onQueueItemError({ item, err }) {
item.onUploadError(err);
this.onItemErrorSubject.next({ item, err });
}
/**
* @private
* @param {?} req
* @return {?}
*/
request(req) {
return this.httpClient.request(req).pipe(filter((/**
* @param {?} event
* @return {?}
*/
event => event.type === HttpEventType.Sent ||
event.type === HttpEventType.UploadProgress ||
event.type === HttpEventType.Response)), map((/**
* @param {?} event
* @return {?}
*/
event => {
switch (event.type) {
case HttpEventType.Sent:
return { type: 'start', value: null };
case HttpEventType.UploadProgress:
/** @type {?} */
const progress = Math.round((100 * event.loaded) / event.total);
return { type: 'progress', value: progress };
case HttpEventType.Response:
return { type: 'response', value: event.body };
}
})));
}
/**
* @private
* @return {?}
*/
calculateTotalProgress() {
/** @type {?} */
const value = this.uploadingItems.reduce((/**
* @param {?} acc
* @param {?} item
* @return {?}
*/
(acc, item) => item.progress + acc), 0) /
(this.uploadingItemsCount || 1);
if (this.removeAfterUpload) {
this._totalProgress = value;
}
else {
/** @type {?} */
const ratio = 100 / this.itemsCount;
/** @type {?} */
const current = (value * ratio) / 100;
this._totalProgress = Math.round(this.uploadedItemsCount * ratio + current);
}
}
/**
* @private
* @param {?} queueItem
* @return {?}
*/
prepareQueueItem(queueItem) {
return new Observable((/**
* @param {?} observer
* @return {?}
*/
observer => {
queueItem.subscription = this.request(queueItem.item.req)
.pipe(finalize((/**
* @return {?}
*/
() => {
if (!observer.closed) {
observer.complete();
}
})), tap((/**
* @param {?} event
* @return {?}
*/
event => {
switch (event.type) {
case 'start':
queueItem.item.onUploadStart();
break;
case 'progress':
/** @type {?} */
const progress = event.value;
/** @type {?} */
const item = queueItem.item;
item.onUploadProgress(progress);
this.onItemProgressSubject.next({ item, progress });
this.calculateTotalProgress();
break;
default:
break;
}
})), filter((/**
* @param {?} event
* @return {?}
*/
event => event.type === 'response')), map((/**
* @param {?} event
* @return {?}
*/
event => event.value)))
.subscribe({
next: (/**
* @param {?} res
* @return {?}
*/
res => {
queueItem.subscription = null;
observer.next({ item: queueItem.item, res });
observer.complete();
}),
error: (/**
* @param {?} err
* @return {?}
*/
(err) => {
queueItem.subscription = null;
observer.error({ item: queueItem.item, err });
}),
complete: (/**
* @return {?}
*/
() => observer.complete())
});
}));
}
/**
* @private
* @return {?}
*/
setupQueue() {
this.queue = [];
this.scheduler = new Subject();
this.scheduler
.pipe(mergeMap((/**
* @param {?} queueItem
* @return {?}
*/
queueItem => this.prepareQueueItem(queueItem).pipe(catchError((/**
* @param {?} uploadEvent
* @return {?}
*/
(uploadEvent) => {
this.onQueueItemError(uploadEvent);
return of(null);
})))), this.concurrency), filter((/**
* @param {?} uploadEvent
* @return {?}
*/
(uploadEvent) => Boolean(uploadEvent))))
.subscribe((/**
* @param {?} uploadEvent
* @return {?}
*/
uploadEvent => this.onQueueItemSuccess(uploadEvent)));
}
/**
* @private
* @param {?} __0
* @return {?}
*/
isValidRequestParams({ url, method }) {
return Boolean(url || this.url) && Boolean(method || this.method);
}
/**
* @private
* @param {?} file
* @return {?}
*/
isValidFileType(file) {
return this.allowedMimeTypes && this.allowedMimeTypes.length
? this.allowedMimeTypes.includes(file.type)
: true;
}
/**
* @private
* @param {?} file
* @return {?}
*/
isValidFileSize(file) {
return this.maxFileSize ? file.size <= this.maxFileSize : true;
}
/**
* @private
* @param {?} file
* @return {?}
*/
isValidFile(file) {
return this.isValidFileType(file) && this.isValidFileSize(file);
}
/**
* @private
* @return {?}
*/
canAddToQueue() {
return this.queueLimit ? this.itemsCount < this.queueLimit : true;
}
/**
* @private
* @param {?} options
* @return {?}
*/
checkItem(options) {
if (!this.isValidRequestParams(options)) {
throw {
name: 'RequestParamsMissing',
message: 'You have not supplied a general url or method to the uploader and also didn\'t provide them in your item.'
};
}
if (!this.isValidFileType(options.file)) {
throw {
name: 'NotAllowedFileType',
message: 'The file type is not included in the allowedMimeTypes.'
};
}
if (!this.isValidFileSize(options.file)) {
throw {
name: 'FileSizeExceeded',
message: 'The file size exceeded the maximumFileSize.'
};
}
if (!this.canAddToQueue()) {
throw {
name: 'QueueLimitReached',
message: 'The specified queueLimit was reached, cannot add more items at the moment.'
};
}
}
/**
* @param {?} options
* @return {?}
*/
addItem(options) {
this.checkItem(options);
Object.assign(options, {
url: options.url || this.url,
method: options.method || this.method
});
/** @type {?} */
const item = new UploadItem(this, options);
this.queue.push({ item, subscription: null });
this.calculateTotalProgress();
if (this.autoUpload) {
item.upload();
}
return item;
}
/**
* @param {?} item
* @return {?}
*/
uploadItem(item) {
/** @type {?} */
const queueItem = this.queue.find((/**
* @param {?} current
* @return {?}
*/
current => current.item === item &&
!(current.item.isReady ||
current.item.isUploading ||
current.item.isUploaded)));
if (queueItem) {
item.onBeforeUpload();
this.scheduler.next(queueItem);
}
}
/**
* @return {?}
*/
uploadAll() {
this.items
.filter((/**
* @param {?} item
* @return {?}
*/
item => !(item.isReady || item.isUploading || item.isUploaded)))
.forEach((/**
* @param {?} item
* @return {?}
*/
item => item.upload()));
}
/**
* @param {?} item
* @return {?}
*/
cancelItem(item) {
/** @type {?} */
const queueItem = this.queue.find((/**
* @param {?} current
* @return {?}
*/
current => current.item === item && item.isReady));
if (queueItem) {
if (queueItem.subscription) {
queueItem.subscription.unsubscribe();
queueItem.subscription = null;
}
queueItem.item.onUploadCancelled();
this.calculateTotalProgress();
}
}
/**
* @return {?}
*/
cancelAll() {
this.notUploadedItems.forEach((/**
* @param {?} item
* @return {?}
*/
item => item.cancel()));
}
/**
* @param {?} item
* @return {?}
*/
removeItem(item) {
if (item.isUploading) {
item.cancel();
}
item.cleanup();
this.queue = this.queue.filter((/**
* @param {?} current
* @return {?}
*/
current => current.item !== item));
this.calculateTotalProgress();
}
/**
* @return {?}
*/
clearQueue() {
while (this.itemsCount) {
this.queue[0].item.remove();
}
this._totalProgress = 0;
}
}
if (false) {
/** @type {?} */
Uploader.prototype.onItemSuccess;
/** @type {?} */
Uploader.prototype.onItemProgress;
/** @type {?} */
Uploader.prototype.onItemError;
/**
* @type {?}
* @private
*/
Uploader.prototype.onItemSuccessSubject;
/**
* @type {?}
* @private
*/
Uploader.prototype.onItemProgressSubject;
/**
* @type {?}
* @private
*/
Uploader.prototype.onItemErrorSubject;
/**
* @type {?}
* @private
*/
Uploader.prototype._totalProgress;
/**
* @type {?}
* @private
*/
Uploader.prototype.url;
/**
* @type {?}
* @private
*/
Uploader.prototype.method;
/**
* @type {?}
* @private
*/
Uploader.prototype.autoUpload;
/**
* @type {?}
* @private
*/
Uploader.prototype.removeAfterUpload;
/**
* @type {?}
* @private
*/
Uploader.prototype.queueLimit;
/**
* @type {?}
* @private
*/
Uploader.prototype.concurrency;
/**
* @type {?}
* @private
*/
Uploader.prototype.maxFileSize;
/**
* @type {?}
* @private
*/
Uploader.prototype.allowedMimeTypes;
/**
* @type {?}
* @private
*/
Uploader.prototype.queue;
/**
* @type {?}
* @private
*/
Uploader.prototype.scheduler;
/**
* @type {?}
* @private
*/
Uploader.prototype.httpClient;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXBsb2FkZXIuY2xhc3MuanMiLCJzb3VyY2VSb290Ijoibmc6Ly9AdHJlbmRzdGVyLWlvL25nLXVwbG9hZGVyLyIsInNvdXJjZXMiOlsibGliL3VwbG9hZGVyLmNsYXNzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7QUFBQSxPQUFPLEVBSUwsYUFBYSxFQUNkLE1BQU0sc0JBQXNCLENBQUM7QUFFOUIsT0FBTyxFQUFFLE9BQU8sRUFBRSxVQUFVLEVBQUUsRUFBRSxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQy9DLE9BQU8sRUFDTCxRQUFRLEVBQ1IsR0FBRyxFQUNILE1BQU0sRUFDTixHQUFHLEVBQ0gsVUFBVSxFQUNWLFFBQVEsRUFDVCxNQUFNLGdCQUFnQixDQUFDO0FBRXhCLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQVVqRCxNQUFNLE9BQU8sUUFBUTs7Ozs7SUFtQm5CLFlBQW9CLFVBQXNCLEVBQUUsVUFBMkIsRUFBRTtRQUFyRCxlQUFVLEdBQVYsVUFBVSxDQUFZO1FBQ3hDLElBQUksQ0FBQyxvQkFBb0IsR0FBRyxJQUFJLE9BQU8sRUFBRSxDQUFDO1FBQzFDLElBQUksQ0FBQyxxQkFBcUIsR0FBRyxJQUFJLE9BQU8sRUFBRSxDQUFDO1FBQzNDLElBQUksQ0FBQyxrQkFBa0IsR0FBRyxJQUFJLE9BQU8sRUFBRSxDQUFDO1FBQ3hDLElBQUksQ0FBQyxhQUFhLEdBQUcsSUFBSSxDQUFDLG9CQUFvQixDQUFDLFlBQVksRUFBRSxDQUFDO1FBQzlELElBQUksQ0FBQyxjQUFjLEdBQUcsSUFBSSxDQUFDLHFCQUFxQixDQUFDLFlBQVksRUFBRSxDQUFDO1FBQ2hFLElBQUksQ0FBQyxXQUFXLEdBQUcsSUFBSSxDQUFDLGtCQUFrQixDQUFDLFlBQVksRUFBRSxDQUFDO1FBQzFELElBQUksQ0FBQyxjQUFjLEdBQUcsQ0FBQyxDQUFDO1FBQ3hCLElBQUksQ0FBQyxHQUFHLEdBQUcsT0FBTyxDQUFDLEdBQUcsQ0FBQztRQUN2QixJQUFJ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K0JBQTRCOzs7OztJQUM1QiwrQkFBNEI7Ozs7O0lBQzVCLG9DQUFtQzs7Ozs7SUFDbkMseUJBQWlDOzs7OztJQUNqQyw2QkFBNEM7Ozs7O0lBRWhDLDhCQUE4QiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIEh0dHBFcnJvclJlc3BvbnNlLFxuICBIdHRwQ2xpZW50LFxuICBIdHRwUmVxdWVzdCxcbiAgSHR0cEV2ZW50VHlwZVxufSBmcm9tICdAYW5ndWxhci9jb21tb24vaHR0cCc7XG5cbmltcG9ydCB7IFN1YmplY3QsIE9ic2VydmFibGUsIG9mIH0gZnJvbSAncnhqcyc7XG5pbXBvcnQge1xuICBtZXJnZU1hcCxcbiAgdGFwLFxuICBmaWx0ZXIsXG4gIG1hcCxcbiAgY2F0Y2hFcnJvcixcbiAgZmluYWxpemVcbn0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuXG5pbXBvcnQgeyBVcGxvYWRJdGVtIH0gZnJvbSAnLi91cGxvYWQtaXRlbS5jbGFzcyc7XG5cbmltcG9ydCB7XG4gIFVwbG9hZExpc3RlbmVyLFxuICBVcGxvYWRlck9wdGlvbnMsXG4gIFVwbG9hZEl0ZW1PcHRpb25zLFxuICBVcGxvYWRJdGVtRXZlbnQsXG4gIFVwbG9hZFF1ZXVlSXRlbVxufSBmcm9tICcuL21vZGVscyc7XG5cbmV4cG9ydCBjbGFzcyBVcGxvYWRlciBpbXBsZW1lbnRzIFVwbG9hZExpc3RlbmVyIHtcbiAgcmVhZG9ubHkgb25JdGVtU3VjY2VzczogT2JzZXJ2YWJsZTxVcGxvYWRJdGVtRXZlbnQ+O1xuICByZWFkb25seSBvbkl0ZW1Qcm9ncmVzczogT2JzZXJ2YWJsZTxVcGxvYWRJdGVtRXZlbnQ+O1xuICByZWFkb25seSBvbkl0ZW1FcnJvcjogT2JzZXJ2YWJsZTxVcGxvYWRJdGVtRXZlbnQ+O1xuICBwcml2YXRlIG9uSXRlbVN1Y2Nlc3NTdWJqZWN0OiBTdWJqZWN0PFVwbG9hZEl0ZW1FdmVudD47XG4gIHByaXZhdGUgb25JdGVtUHJvZ3Jlc3NTdWJqZWN0OiBTdWJqZWN0PFVwbG9hZEl0ZW1FdmVudD47XG4gIHByaXZhdGUgb25JdGVtRXJyb3JTdWJqZWN0OiBTdWJqZWN0PFVwbG9hZEl0ZW1FdmVudD47XG4gIHByaXZhdGUgX3RvdGFsUHJvZ3Jlc3M6IG51bWJlcjtcbiAgcHJpdmF0ZSB1cmw6IHN0cmluZztcbiAgcHJpdmF0ZSBtZXRob2Q6ICdQT1NUJyB8ICdQVVQnIHwgJ1BBVENIJztcbiAgcHJpdmF0ZSBhdXRvVXBsb2FkOiBib29sZWFuO1xuICBwcml2YXRlIHJlbW92ZUFmdGVyVXBsb2FkOiBib29sZWFuO1xuICBwcml2YXRlIHF1ZXVlTGltaXQ6IG51bWJlcjtcbiAgcHJpdmF0ZSBjb25jdXJyZW5jeTogbnVtYmVyO1xuICBwcml2YXRlIG1heEZpbGVTaXplOiBudW1iZXI7XG4gIHByaXZhdGUgYWxsb3dlZE1pbWVUeXBlczogc3RyaW5nW107XG4gIHByaXZhdGUgcXVldWU6IFVwbG9hZFF1ZXVlSXRlbVtdO1xuICBwcml2YXRlIHNjaGVkdWxlcjogU3ViamVjdDxVcGxvYWRRdWV1ZUl0ZW0+O1xuXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgaHR0cENsaWVudDogSHR0cENsaWVudCwgb3B0aW9uczogVXBsb2FkZXJPcHRpb25zID0ge30pIHtcbiAgICB0aGlzLm9uSXRlbVN1Y2Nlc3NTdWJqZWN0ID0gbmV3IFN1YmplY3QoKTtcbiAgICB0aGlzLm9uSXRlbVByb2dyZXNzU3ViamVjdCA9IG5ldyBTdWJqZWN0KCk7XG4gICAgdGhpcy5vbkl0ZW1FcnJvclN1YmplY3QgPSBuZXcgU3ViamVjdCgpO1xuICAgIHRoaXMub25JdGVtU3VjY2VzcyA9IHRoaXMub25JdGVtU3VjY2Vzc1N1YmplY3QuYXNPYnNlcnZhYmxlKCk7XG4gICAgdGhpcy5vbkl0ZW1Qcm9ncmVzcyA9IHRoaXMub25JdGVtUHJvZ3Jlc3NTdWJqZWN0LmFzT2JzZXJ2YWJsZSgpO1xuICAgIHRoaXMub25JdGVtRXJyb3IgPSB0aGlzLm9uSXRlbUVycm9yU3ViamVjdC5hc09ic2VydmFibGUoKTtcbiAgICB0aGlzLl90b3RhbFByb2dyZXNzID0gMDtcbiAgICB0aGlzLnVybCA9IG9wdGlvbnMudXJsO1xuICAgIHRoaXMubWV0aG9kID0gb3B0aW9ucy5tZXRob2Q7XG4gICAgdGhpcy5hdXRvVXBsb2FkID0gb3B0aW9ucy5hdXRvVXBsb2FkO1xuICAgIHRoaXMucmVtb3ZlQWZ0ZXJVcGxvYWQgPSBvcHRpb25zLnJlbW92ZUFmdGVyVXBsb2FkO1xuICAgIHRoaXMucXVldWVMaW1pdCA9IG9wdGlvbnMucXVldWVMaW1pdDtcbiAgICB0aGlzLmNvbmN1cnJlbmN5ID0gb3B0aW9ucy5jb25jdXJyZW5jeSB8fCAxO1xuICAgIHRoaXMubWF4RmlsZVNpemUgPSBvcHRpb25zLm1heEZpbGVTaXplO1xuICAgIHRoaXMuYWxsb3dlZE1pbWVUeXBlcyA9IG9wdGlvbnMuYWxsb3dlZE1pbWVUeXBlcztcbiAgICB0aGlzLnNldHVwUXVldWUoKTtcbiAgfVxuXG4gIGdldCBpdGVtc0NvdW50KCk6IG51bWJlciB7XG4gICAgcmV0dXJuIHRoaXMucXVldWUubGVuZ3RoO1xuICB9XG5cbiAgZ2V0IGl0ZW1zKCk6IFVwbG9hZEl0ZW1bXSB7XG4gICAgcmV0dXJuIHRoaXMucXVldWUubWFwKHF1ZXVlSXRlbSA9PiBxdWV1ZUl0ZW0uaXRlbSk7XG4gIH1cblxuICBnZXQgcmVhZHlJdGVtc0NvdW50KCk6IG51bWJlciB7XG4gICAgcmV0dXJuIHRoaXMucXVldWVcbiAgICAgIC5tYXAocXVldWVJdGVtID0+IHF1ZXVlSXRlbS5pdGVtKVxuICAgICAgLmZpbHRlcihpdGVtID0+IGl0ZW0uaXNSZWFkeSAmJiAhaXRlbS5pc1VwbG9hZGluZykubGVuZ3RoO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXQgcmVhZHlJdGVtcygpOiBVcGxvYWRJdGVtW10ge1xuICAgIHJldHVybiB0aGlzLnF1ZXVlXG4gICAgICAubWFwKHF1ZXVlSXRlbSA9PiBxdWV1ZUl0ZW0uaXRlbSlcbiAgICAgIC5maWx0ZXIoaXRlbSA9PiBpdGVtLmlzUmVhZHkgJiYgIWl0ZW0uaXNVcGxvYWRpbmcpO1xuICB9XG5cbiAgZ2V0IHVwbG9hZGluZ0l0ZW1zQ291bnQoKTogbnVtYmVyIHtcbiAgICByZXR1cm4gdGhpcy5xdWV1ZVxuICAgICAgLm1hcChxdWV1ZUl0ZW0gPT4gcXVldWVJdGVtLml0ZW0pXG4gICAgICAuZmlsdGVyKGl0ZW0gPT4gaXRlbS5pc1VwbG9hZGluZykubGVuZ3RoO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXQgdXBsb2FkaW5nSXRlbXMoKTogVXBsb2FkSXRlbVtdIHtcbiAgICByZXR1cm4gdGhpcy5xdWV1ZVxuICAgICAgLm1hcChxdWV1ZUl0ZW0gPT4gcXVldWVJdGVtLml0ZW0pXG4gICAgICAuZmlsdGVyKGl0ZW0gPT4gaXRlbS5pc1VwbG9hZGluZyk7XG4gIH1cblxuICBnZXQgdXBsb2FkZWRJdGVtc0NvdW50KCk6IG51bWJlciB7XG4gICAgcmV0dXJuIHRoaXMucXVldWVcbiAgICAgIC5tYXAocXVldWVJdGVtID0+IHF1ZXVlSXRlbS5pdGVtKVxuICAgICAgLmZpbHRlcihpdGVtID0+IGl0ZW0uaXNVcGxvYWRlZCkubGVuZ3RoO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXQgdXBsb2FkZWRJdGVtcygpOiBVcGxvYWRJdGVtW10ge1xuICAgIHJldHVybiB0aGlzLnF1ZXVlXG4gICAgICAubWFwKHF1ZXVlSXRlbSA9PiBxdWV1ZUl0ZW0uaXRlbSlcbiAgICAgIC5maWx0ZXIoaXRlbSA9PiBpdGVtLmlzVXBsb2FkZWQpO1xuICB9XG5cbiAgZ2V0IG5vdFVwbG9hZGVkSXRlbXNDb3VudCgpOiBudW1iZXIge1xuICAgIHJldHVybiB0aGlzLnF1ZXVlXG4gICAgICAubWFwKHF1ZXVlSXRlbSA9PiBxdWV1ZUl0ZW0uaXRlbSlcbiAgICAgIC5maWx0ZXIoaXRlbSA9PiAhaXRlbS5pc1VwbG9hZGVkKS5sZW5ndGg7XG4gIH1cblxuICBwcml2YXRlIGdldCBub3RVcGxvYWRlZEl0ZW1zKCk6IFVwbG9hZEl0ZW1bXSB7XG4gICAgcmV0dXJuIHRoaXMucXVldWVcbiAgICAgIC5tYXAocXVldWVJdGVtID0+IHF1ZXVlSXRlbS5pdGVtKVxuICAgICAgLmZpbHRlcihpdGVtID0+ICFpdGVtLmlzVXBsb2FkZWQpO1xuICB9XG5cbiAgZ2V0IGNhbmNlbGxlZEl0ZW1zQ291bnQoKTogbnVtYmVyIHtcbiAgICByZXR1cm4gdGhpcy5xdWV1ZVxuICAgICAgLm1hcChxdWV1ZUl0ZW0gPT4gcXVldWVJdGVtLml0ZW0pXG4gICAgICAuZmlsdGVyKGl0ZW0gPT4gaXRlbS5pc0NhbmNlbGxlZCkubGVuZ3RoO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXQgY2FuY2VsbGVkSXRlbXMoKTogVXBsb2FkSXRlbVtdIHtcbiAgICByZXR1cm4gdGhpcy5xdWV1ZVxuICAgICAgLm1hcChxdWV1ZUl0ZW0gPT4gcXVldWVJdGVtLml0ZW0pXG4gICAgICAuZmlsdGVyKGl0ZW0gPT4gaXRlbS5pc0NhbmNlbGxlZCk7XG4gIH1cblxuICBnZXQgZXJyb3JJdGVtc0NvdW50KCk6IG51bWJlciB7XG4gICAgcmV0dXJuIHRoaXMucXVldWVcbiAgICAgIC5tYXAocXVldWVJdGVtID0+IHF1ZXVlSXRlbS5pdGVtKVxuICAgICAgLmZpbHRlcihpdGVtID0+IGl0ZW0uaXNFcnJvcikubGVuZ3RoO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXQgZXJyb3JJdGVtcygpOiBVcGxvYWRJdGVtW10ge1xuICAgIHJldHVybiB0aGlzLnF1ZXVlXG4gICAgICAubWFwKHF1ZXVlSXRlbSA9PiBxdWV1ZUl0ZW0uaXRlbSlcbiAgICAgIC5maWx0ZXIoaXRlbSA9PiBpdGVtLmlzRXJyb3IpO1xuICB9XG5cbiAgZ2V0IHRvdGFsUHJvZ3Jlc3MoKTogbnVtYmVyIHtcbiAgICByZXR1cm4gdGhpcy5fdG90YWxQcm9ncmVzcztcbiAgfVxuXG4gIGdldCBpc1VwbG9hZGluZygpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy51cGxvYWRpbmdJdGVtc0NvdW50ID4gMDtcbiAgfVxuXG4gIHByaXZhdGUgb25RdWV1ZUl0ZW1TdWNjZXNzKHsgaXRlbSwgcmVzIH06IFVwbG9hZEl0ZW1FdmVudCk6IHZvaWQge1xuICAgIGl0ZW0ub25VcGxvYWRTdWNjZXNzKHJlcyk7XG4gICAgdGhpcy5vbkl0ZW1TdWNjZXNzU3ViamVjdC5uZXh0KHsgaXRlbSwgcmVzIH0pO1xuICAgIGlmICh0aGlzLnJlbW92ZUFmdGVyVXBsb2FkKSB7XG4gICAgICBpdGVtLnJlbW92ZSgpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgb25RdWV1ZUl0ZW1FcnJvcih7IGl0ZW0sIGVyciB9OiBVcGxvYWRJdGVtRXZlbnQpOiB2b2lkIHtcbiAgICBpdGVtLm9uVXBsb2FkRXJyb3IoZXJyKTtcbiAgICB0aGlzLm9uSXRlbUVycm9yU3ViamVjdC5uZXh0KHsgaXRlbSwgZXJyIH0pO1xuICB9XG5cbiAgcHJpdmF0ZSByZXF1ZXN0KHJlcTogSHR0cFJlcXVlc3Q8Rm9ybURhdGE+KTogT2JzZXJ2YWJsZTxhbnk+IHtcbiAgICByZXR1cm4gdGhpcy5odHRwQ2xpZW50LnJlcXVlc3QocmVxKS5waXBlKFxuICAgICAgZmlsdGVyKFxuICAgICAgICBldmVudCA9PlxuICAgICAgICAgIGV2ZW50LnR5cGUgPT09IEh0dHBFdmVudFR5cGUuU2VudCB8fFxuICAgICAgICAgIGV2ZW50LnR5cGUgPT09IEh0dHBFdmVudFR5cGUuVXBsb2FkUHJvZ3Jlc3MgfHxcbiAgICAgICAgICBldmVudC50eXBlID09PSBIdHRwRXZlbnRUeXBlLlJlc3BvbnNlXG4gICAgICApLFxuICAgICAgbWFwKGV2ZW50ID0+IHtcbiAgICAgICAgc3dpdGNoIChldmVudC50eXBlKSB7XG4gICAgICAgICAgY2FzZSBIdHRwRXZlbnRUeXBlLlNlbnQ6XG4gICAgICAgICAgICByZXR1cm4geyB0eXBlOiAnc3RhcnQnLCB2YWx1ZTogbnVsbCB9O1xuICAgICAgICAgIGNhc2UgSHR0cEV2ZW50VHlwZS5VcGxvYWRQcm9ncmVzczpcbiAgICAgICAgICAgIGNvbnN0IHByb2dyZXNzID0gTWF0aC5yb3VuZCgoMTAwICogZXZlbnQubG9hZGVkKSAvIGV2ZW50LnRvdGFsKTtcbiAgICAgICAgICAgIHJldHVybiB7IHR5cGU6ICdwcm9ncmVzcycsIHZhbHVlOiBwcm9ncmVzcyB9O1xuICAgICAgICAgIGNhc2UgSHR0cEV2ZW50VHlwZS5SZXNwb25zZTpcbiAgICAgICAgICAgIHJldHVybiB7IHR5cGU6ICdyZXNwb25zZScsIHZhbHVlOiBldmVudC5ib2R5IH07XG4gICAgICAgIH1cbiAgICAgIH0pXG4gICAgKTtcbiAgfVxuXG4gIHByaXZhdGUgY2FsY3VsYXRlVG90YWxQcm9ncmVzcygpOiB2b2lkIHtcbiAgICBjb25zdCB2YWx1ZSA9XG4gICAgICB0aGlzLnVwbG9hZGluZ0l0ZW1zLnJlZHVjZSgoYWNjLCBpdGVtKSA9PiBpdGVtLnByb2dyZXNzICsgYWNjLCAwKSAvXG4gICAgICAodGhpcy51cGxvYWRpbmdJdGVtc0NvdW50IHx8IDEpO1xuICAgIGlmICh0aGlzLnJlbW92ZUFmdGVyVXBsb2FkKSB7XG4gICAgICB0aGlzLl90b3RhbFByb2dyZXNzID0gdmFsdWU7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnN0IHJhdGlvID0gMTAwIC8gdGhpcy5pdGVtc0NvdW50O1xuICAgICAgY29uc3QgY3VycmVudCA9ICh2YWx1ZSAqIHJhdGlvKSAvIDEwMDtcbiAgICAgIHRoaXMuX3RvdGFsUHJvZ3Jlc3MgPSBNYXRoLnJvdW5kKFxuICAgICAgICB0aGlzLnVwbG9hZGVkSXRlbXNDb3VudCAqIHJhdGlvICsgY3VycmVudFxuICAgICAgKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIHByZXBhcmVRdWV1ZUl0ZW0ocXVldWVJdGVtOiBVcGxvYWRRdWV1ZUl0ZW0pOiBPYnNlcnZhYmxlPGFueT4ge1xuICAgIHJldHVybiBuZXcgT2JzZXJ2YWJsZShvYnNlcnZlciA9PiB7XG4gICAgICBxdWV1ZUl0ZW0uc3Vic2NyaXB0aW9uID0gdGhpcy5yZXF1ZXN0KHF1ZXVlSXRlbS5pdGVtLnJlcSlcbiAgICAgICAgLnBpcGUoXG4gICAgICAgICAgZmluYWxpemUoKCkgPT4ge1xuICAgICAgICAgICAgaWYgKCFvYnNlcnZlci5jbG9zZWQpIHtcbiAgICAgICAgICAgICAgb2JzZXJ2ZXIuY29tcGxldGUoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9KSxcbiAgICAgICAgICB0YXAoZXZlbnQgPT4ge1xuICAgICAgICAgICAgc3dpdGNoIChldmVudC50eXBlKSB7XG4gICAgICAgICAgICAgIGNhc2UgJ3N0YXJ0JzpcbiAgICAgICAgICAgICAgICBxdWV1ZUl0ZW0uaXRlbS5vblVwbG9hZFN0YXJ0KCk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgIGNhc2UgJ3Byb2dyZXNzJzpcbiAgICAgICAgICAgICAgICBjb25zdCBwcm9ncmVzcyA9IGV2ZW50LnZhbHVlO1xuICAgICAgICAgICAgICAgIGNvbnN0IGl0ZW0gPSBxdWV1ZUl0ZW0uaXRlbTtcbiAgICAgICAgICAgICAgICBpdGVtLm9uVXBsb2FkUHJvZ3Jlc3MocHJvZ3Jlc3MpO1xuICAgICAgICAgICAgICAgIHRoaXMub25JdGVtUHJvZ3Jlc3NTdWJqZWN0Lm5leHQoeyBpdGVtLCBwcm9ncmVzcyB9KTtcbiAgICAgICAgICAgICAgICB0aGlzLmNhbGN1bGF0ZVRvdGFsUHJvZ3Jlc3MoKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9KSxcbiAgICAgICAgICBmaWx0ZXIoZXZlbnQgPT4gZXZlbnQudHlwZSA9PT0gJ3Jlc3BvbnNlJyksXG4gICAgICAgICAgbWFwKGV2ZW50ID0+IGV2ZW50LnZhbHVlKVxuICAgICAgICApXG4gICAgICAgIC5zdWJzY3JpYmUoe1xuICAgICAgICAgIG5leHQ6IHJlcyA9PiB7XG4gICAgICAgICAgICBxdWV1ZUl0ZW0uc3Vic2NyaXB0aW9uID0gbnVsbDtcbiAgICAgICAgICAgIG9ic2VydmVyLm5leHQoeyBpdGVtOiBxdWV1ZUl0ZW0uaXRlbSwgcmVzIH0pO1xuICAgICAgICAgICAgb2JzZXJ2ZXIuY29tcGxldGUoKTtcbiAgICAgICAgICB9LFxuICAgICAgICAgIGVycm9yOiAoZXJyOiBIdHRwRXJyb3JSZXNwb25zZSkgPT4ge1xuICAgICAgICAgICAgcXVldWVJdGVtLnN1YnNjcmlwdGlvbiA9IG51bGw7XG4gICAgICAgICAgICBvYnNlcnZlci5lcnJvcih7IGl0ZW06IHF1ZXVlSXRlbS5pdGVtLCBlcnIgfSk7XG4gICAgICAgICAgfSxcbiAgICAgICAgICBjb21wbGV0ZTogKCkgPT4gb2JzZXJ2ZXIuY29tcGxldGUoKVxuICAgICAgICB9KTtcbiAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgc2V0dXBRdWV1ZSgpOiB2b2lkIHtcbiAgICB0aGlzLnF1ZXVlID0gW107XG4gICAgdGhpcy5zY2hlZHVsZXIgPSBuZXcgU3ViamVjdCgpO1xuICAgIHRoaXMuc2NoZWR1bGVyXG4gICAgICAucGlwZShcbiAgICAgICAgbWVyZ2VNYXAoXG4gICAgICAgICAgcXVldWVJdGVtID0+XG4gICAgICAgICAgICB0aGlzLnByZXBhcmVRdWV1ZUl0ZW0ocXVldWVJdGVtKS5waXBlKFxuICAgICAgICAgICAgICBjYXRjaEVycm9yKCh1cGxvYWRFdmVudDogVXBsb2FkSXRlbUV2ZW50KSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5vblF1ZXVlSXRlbUVycm9yKHVwbG9hZEV2ZW50KTtcbiAgICAgICAgICAgICAgICByZXR1cm4gb2YobnVsbCk7XG4gICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICApLFxuICAgICAgICAgIHRoaXMuY29uY3VycmVuY3lcbiAgICAgICAgKSxcbiAgICAgICAgZmlsdGVyKCh1cGxvYWRFdmVudDogVXBsb2FkSXRlbUV2ZW50KSA9PiBCb29sZWFuKHVwbG9hZEV2ZW50KSlcbiAgICAgIClcbiAgICAgIC5zdWJzY3JpYmUodXBsb2FkRXZlbnQgPT4gdGhpcy5vblF1ZXVlSXRlbVN1Y2Nlc3ModXBsb2FkRXZlbnQpKTtcbiAgfVxuXG4gIHByaXZhdGUgaXNWYWxpZFJlcXVlc3RQYXJhbXMoeyB1cmwsIG1ldGhvZCB9OiBVcGxvYWRJdGVtT3B0aW9ucyk6IGJvb2xlYW4ge1xuICAgIHJldHVybiBCb29sZWFuKHVybCB8fCB0aGlzLnVybCkgJiYgQm9vbGVhbihtZXRob2QgfHwgdGhpcy5tZXRob2QpO1xuICB9XG5cbiAgcHJpdmF0ZSBpc1ZhbGlkRmlsZVR5cGUoZmlsZTogRmlsZSk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLmFsbG93ZWRNaW1lVHlwZXMgJiYgdGhpcy5hbGxvd2VkTWltZVR5cGVzLmxlbmd0aFxuICAgICAgPyB0aGlzLmFsbG93ZWRNaW1lVHlwZXMuaW5jbHVkZXMoZmlsZS50eXBlKVxuICAgICAgOiB0cnVlO1xuICB9XG5cbiAgcHJpdmF0ZSBpc1ZhbGlkRmlsZVNpemUoZmlsZTogRmlsZSk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLm1heEZpbGVTaXplID8gZmlsZS5zaXplIDw9IHRoaXMubWF4RmlsZVNpemUgOiB0cnVlO1xuICB9XG5cbiAgcHJpdmF0ZSBpc1ZhbGlkRmlsZShmaWxlOiBGaWxlKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMuaXNWYWxpZEZpbGVUeXBlKGZpbGUpICYmIHRoaXMuaXNWYWxpZEZpbGVTaXplKGZpbGUpO1xuICB9XG5cbiAgcHJpdmF0ZSBjYW5BZGRUb1F1ZXVlKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLnF1ZXVlTGltaXQgPyB0aGlzLml0ZW1zQ291bnQgPCB0aGlzLnF1ZXVlTGltaXQgOiB0cnVlO1xuICB9XG5cbiAgcHJpdmF0ZSBjaGVja0l0ZW0ob3B0aW9uczogVXBsb2FkSXRlbU9wdGlvbnMpOiB2b2lkIHtcbiAgICBpZiAoIXRoaXMuaXNWYWxpZFJlcXVlc3RQYXJhbXMob3B0aW9ucykpIHtcbiAgICAgIHRocm93IHtcbiAgICAgICAgbmFtZTogJ1JlcXVlc3RQYXJhbXNNaXNzaW5nJyxcbiAgICAgICAgbWVzc2FnZTpcbiAgICAgICAgICAnWW91IGhhdmUgbm90IHN1cHBsaWVkIGEgZ2VuZXJhbCB1cmwgb3IgbWV0aG9kIHRvIHRoZSB1cGxvYWRlciBhbmQgYWxzbyBkaWRuXFwndCBwcm92aWRlIHRoZW0gaW4geW91ciBpdGVtLidcbiAgICAgIH07XG4gICAgfVxuICAgIGlmICghdGhpcy5pc1ZhbGlkRmlsZVR5cGUob3B0aW9ucy5maWxlKSkge1xuICAgICAgdGhyb3cge1xuICAgICAgICBuYW1lOiAnTm90QWxsb3dlZEZpbGVUeXBlJyxcbiAgICAgICAgbWVzc2FnZTogJ1RoZSBmaWxlIHR5cGUgaXMgbm90IGluY2x1ZGVkIGluIHRoZSBhbGxvd2VkTWltZVR5cGVzLidcbiAgICAgIH07XG4gICAgfVxuICAgIGlmICghdGhpcy5pc1ZhbGlkRmlsZVNpemUob3B0aW9ucy5maWxlKSkge1xuICAgICAgdGhyb3cge1xuICAgICAgICBuYW1lOiAnRmlsZVNpemVFeGNlZWRlZCcsXG4gICAgICAgIG1lc3NhZ2U6ICdUaGUgZmlsZSBzaXplIGV4Y2VlZGVkIHRoZSBtYXhpbXVtRmlsZVNpemUuJ1xuICAgICAgfTtcbiAgICB9XG4gICAgaWYgKCF0aGlzLmNhbkFkZFRvUXVldWUoKSkge1xuICAgICAgdGhyb3cge1xuICAgICAgICBuYW1lOiAnUXVldWVMaW1pdFJlYWNoZWQnLFxuICAgICAgICBtZXNzYWdlOlxuICAgICAgICAgICdUaGUgc3BlY2lmaWVkIHF1ZXVlTGltaXQgd2FzIHJlYWNoZWQsIGNhbm5vdCBhZGQgbW9yZSBpdGVtcyBhdCB0aGUgbW9tZW50LidcbiAgICAgIH07XG4gICAgfVxuICB9XG5cbiAgYWRkSXRlbShvcHRpb25zOiBVcGxvYWRJdGVtT3B0aW9ucyk6IFVwbG9hZEl0ZW0ge1xuICAgIHRoaXMuY2hlY2tJdGVtKG9wdGlvbnMpO1xuICAgIE9iamVjdC5hc3NpZ24ob3B0aW9ucywge1xuICAgICAgdXJsOiBvcHRpb25zLnVybCB8fCB0aGlzLnVybCxcbiAgICAgIG1ldGhvZDogb3B0aW9ucy5tZXRob2QgfHwgdGhpcy5tZXRob2RcbiAgICB9KTtcbiAgICBjb25zdCBpdGVtID0gbmV3IFVwbG9hZEl0ZW0odGhpcywgb3B0aW9ucyk7XG4gICAgdGhpcy5xdWV1ZS5wdXNoKHsgaXRlbSwgc3Vic2NyaXB0aW9uOiBudWxsIH0pO1xuICAgIHRoaXMuY2FsY3VsYXRlVG90YWxQcm9ncmVzcygpO1xuICAgIGlmICh0aGlzLmF1dG9VcGxvYWQpIHtcbiAgICAgIGl0ZW0udXBsb2FkKCk7XG4gICAgfVxuICAgIHJldHVybiBpdGVtO1xuICB9XG5cbiAgdXBsb2FkSXRlbShpdGVtOiBVcGxvYWRJdGVtKTogdm9pZCB7XG4gICAgY29uc3QgcXVldWVJdGVtID0gdGhpcy5xdWV1ZS5maW5kKFxuICAgICAgY3VycmVudCA9PlxuICAgICAgICBjdXJyZW50Lml0ZW0gPT09IGl0ZW0gJiZcbiAgICAgICAgIShcbiAgICAgICAgICBjdXJyZW50Lml0ZW0uaXNSZWFkeSB8fFxuICAgICAgICAgIGN1cnJlbnQuaXRlbS5pc1VwbG9hZGluZyB8fFxuICAgICAgICAgIGN1cnJlbnQuaXRlbS5pc1VwbG9hZGVkXG4gICAgICAgIClcbiAgICApO1xuICAgIGlmIChxdWV1ZUl0ZW0pIHtcbiAgICAgIGl0ZW0ub25CZWZvcmVVcGxvYWQoKTtcbiAgICAgIHRoaXMuc2NoZWR1bGVyLm5leHQocXVldWVJdGVtKTtcbiAgICB9XG4gIH1cblxuICB1cGxvYWRBbGwoKTogdm9pZCB7XG4gICAgdGhpcy5pdGVtc1xuICAgICAgLmZpbHRlcihpdGVtID0+ICEoaXRlbS5pc1JlYWR5IHx8IGl0ZW0uaXNVcGxvYWRpbmcgfHwgaXRlbS5pc1VwbG9hZGVkKSlcbiAgICAgIC5mb3JFYWNoKGl0ZW0gPT4gaXRlbS51cGxvYWQoKSk7XG4gIH1cblxuICBjYW5jZWxJdGVtKGl0ZW06IFVwbG9hZEl0ZW0pOiB2b2lkIHtcbiAgICBjb25zdCBxdWV1ZUl0ZW0gPSB0aGlzLnF1ZXVlLmZpbmQoXG4gICAgICBjdXJyZW50ID0+IGN1cnJlbnQuaXRlbSA9PT0gaXRlbSAmJiBpdGVtLmlzUmVhZHlcbiAgICApO1xuICAgIGlmIChxdWV1ZUl0ZW0pIHtcbiAgICAgIGlmIChxdWV1ZUl0ZW0uc3Vic2NyaXB0aW9uKSB7XG4gICAgICAgIHF1ZXVlSXRlbS5zdWJzY3JpcHRpb24udW5zdWJzY3JpYmUoKTtcbiAgICAgICAgcXVldWVJdGVtLnN1YnNjcmlwdGlvbiA9IG51bGw7XG4gICAgICB9XG4gICAgICBxdWV1ZUl0ZW0uaXRlbS5vblVwbG9hZENhbmNlbGxlZCgpO1xuICAgICAgdGhpcy5jYWxjdWxhdGVUb3RhbFByb2dyZXNzKCk7XG4gICAgfVxuICB9XG5cbiAgY2FuY2VsQWxsKCk6IHZvaWQge1xuICAgIHRoaXMubm90VXBsb2FkZWRJdGVtcy5mb3JFYWNoKGl0ZW0gPT4gaXRlbS5jYW5jZWwoKSk7XG4gIH1cblxuICByZW1vdmVJdGVtKGl0ZW06IFVwbG9hZEl0ZW0pOiB2b2lkIHtcbiAgICBpZiAoaXRlbS5pc1VwbG9hZGluZykge1xuICAgICAgaXRlbS5jYW5jZWwoKTtcbiAgICB9XG4gICAgaXRlbS5jbGVhbnVwKCk7XG4gICAgdGhpcy5xdWV1ZSA9IHRoaXMucXVldWUuZmlsdGVyKGN1cnJlbnQgPT4gY3VycmVudC5pdGVtICE9PSBpdGVtKTtcbiAgICB0aGlzLmNhbGN1bGF0ZVRvdGFsUHJvZ3Jlc3MoKTtcbiAgfVxuXG4gIGNsZWFyUXVldWUoKTogdm9pZCB7XG4gICAgd2hpbGUgKHRoaXMuaXRlbXNDb3VudCkge1xuICAgICAgdGhpcy5xdWV1ZVswXS5pdGVtLnJlbW92ZSgpO1xuICAgIH1cbiAgICB0aGlzLl90b3RhbFByb2dyZXNzID0gMDtcbiAgfVxufVxuIl19