UNPKG

@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
/** * @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