@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
858 lines • 54.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';
var Uploader = /** @class */ (function () {
function Uploader(httpClient, options) {
if (options === void 0) { 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();
}
Object.defineProperty(Uploader.prototype, "itemsCount", {
get: /**
* @return {?}
*/
function () {
return this.queue.length;
},
enumerable: true,
configurable: true
});
Object.defineProperty(Uploader.prototype, "items", {
get: /**
* @return {?}
*/
function () {
return this.queue.map((/**
* @param {?} queueItem
* @return {?}
*/
function (queueItem) { return queueItem.item; }));
},
enumerable: true,
configurable: true
});
Object.defineProperty(Uploader.prototype, "readyItemsCount", {
get: /**
* @return {?}
*/
function () {
return this.queue
.map((/**
* @param {?} queueItem
* @return {?}
*/
function (queueItem) { return queueItem.item; }))
.filter((/**
* @param {?} item
* @return {?}
*/
function (item) { return item.isReady && !item.isUploading; })).length;
},
enumerable: true,
configurable: true
});
Object.defineProperty(Uploader.prototype, "readyItems", {
get: /**
* @private
* @return {?}
*/
function () {
return this.queue
.map((/**
* @param {?} queueItem
* @return {?}
*/
function (queueItem) { return queueItem.item; }))
.filter((/**
* @param {?} item
* @return {?}
*/
function (item) { return item.isReady && !item.isUploading; }));
},
enumerable: true,
configurable: true
});
Object.defineProperty(Uploader.prototype, "uploadingItemsCount", {
get: /**
* @return {?}
*/
function () {
return this.queue
.map((/**
* @param {?} queueItem
* @return {?}
*/
function (queueItem) { return queueItem.item; }))
.filter((/**
* @param {?} item
* @return {?}
*/
function (item) { return item.isUploading; })).length;
},
enumerable: true,
configurable: true
});
Object.defineProperty(Uploader.prototype, "uploadingItems", {
get: /**
* @private
* @return {?}
*/
function () {
return this.queue
.map((/**
* @param {?} queueItem
* @return {?}
*/
function (queueItem) { return queueItem.item; }))
.filter((/**
* @param {?} item
* @return {?}
*/
function (item) { return item.isUploading; }));
},
enumerable: true,
configurable: true
});
Object.defineProperty(Uploader.prototype, "uploadedItemsCount", {
get: /**
* @return {?}
*/
function () {
return this.queue
.map((/**
* @param {?} queueItem
* @return {?}
*/
function (queueItem) { return queueItem.item; }))
.filter((/**
* @param {?} item
* @return {?}
*/
function (item) { return item.isUploaded; })).length;
},
enumerable: true,
configurable: true
});
Object.defineProperty(Uploader.prototype, "uploadedItems", {
get: /**
* @private
* @return {?}
*/
function () {
return this.queue
.map((/**
* @param {?} queueItem
* @return {?}
*/
function (queueItem) { return queueItem.item; }))
.filter((/**
* @param {?} item
* @return {?}
*/
function (item) { return item.isUploaded; }));
},
enumerable: true,
configurable: true
});
Object.defineProperty(Uploader.prototype, "notUploadedItemsCount", {
get: /**
* @return {?}
*/
function () {
return this.queue
.map((/**
* @param {?} queueItem
* @return {?}
*/
function (queueItem) { return queueItem.item; }))
.filter((/**
* @param {?} item
* @return {?}
*/
function (item) { return !item.isUploaded; })).length;
},
enumerable: true,
configurable: true
});
Object.defineProperty(Uploader.prototype, "notUploadedItems", {
get: /**
* @private
* @return {?}
*/
function () {
return this.queue
.map((/**
* @param {?} queueItem
* @return {?}
*/
function (queueItem) { return queueItem.item; }))
.filter((/**
* @param {?} item
* @return {?}
*/
function (item) { return !item.isUploaded; }));
},
enumerable: true,
configurable: true
});
Object.defineProperty(Uploader.prototype, "cancelledItemsCount", {
get: /**
* @return {?}
*/
function () {
return this.queue
.map((/**
* @param {?} queueItem
* @return {?}
*/
function (queueItem) { return queueItem.item; }))
.filter((/**
* @param {?} item
* @return {?}
*/
function (item) { return item.isCancelled; })).length;
},
enumerable: true,
configurable: true
});
Object.defineProperty(Uploader.prototype, "cancelledItems", {
get: /**
* @private
* @return {?}
*/
function () {
return this.queue
.map((/**
* @param {?} queueItem
* @return {?}
*/
function (queueItem) { return queueItem.item; }))
.filter((/**
* @param {?} item
* @return {?}
*/
function (item) { return item.isCancelled; }));
},
enumerable: true,
configurable: true
});
Object.defineProperty(Uploader.prototype, "errorItemsCount", {
get: /**
* @return {?}
*/
function () {
return this.queue
.map((/**
* @param {?} queueItem
* @return {?}
*/
function (queueItem) { return queueItem.item; }))
.filter((/**
* @param {?} item
* @return {?}
*/
function (item) { return item.isError; })).length;
},
enumerable: true,
configurable: true
});
Object.defineProperty(Uploader.prototype, "errorItems", {
get: /**
* @private
* @return {?}
*/
function () {
return this.queue
.map((/**
* @param {?} queueItem
* @return {?}
*/
function (queueItem) { return queueItem.item; }))
.filter((/**
* @param {?} item
* @return {?}
*/
function (item) { return item.isError; }));
},
enumerable: true,
configurable: true
});
Object.defineProperty(Uploader.prototype, "totalProgress", {
get: /**
* @return {?}
*/
function () {
return this._totalProgress;
},
enumerable: true,
configurable: true
});
Object.defineProperty(Uploader.prototype, "isUploading", {
get: /**
* @return {?}
*/
function () {
return this.uploadingItemsCount > 0;
},
enumerable: true,
configurable: true
});
/**
* @private
* @param {?} __0
* @return {?}
*/
Uploader.prototype.onQueueItemSuccess = /**
* @private
* @param {?} __0
* @return {?}
*/
function (_a) {
var item = _a.item, res = _a.res;
item.onUploadSuccess(res);
this.onItemSuccessSubject.next({ item: item, res: res });
if (this.removeAfterUpload) {
item.remove();
}
};
/**
* @private
* @param {?} __0
* @return {?}
*/
Uploader.prototype.onQueueItemError = /**
* @private
* @param {?} __0
* @return {?}
*/
function (_a) {
var item = _a.item, err = _a.err;
item.onUploadError(err);
this.onItemErrorSubject.next({ item: item, err: err });
};
/**
* @private
* @param {?} req
* @return {?}
*/
Uploader.prototype.request = /**
* @private
* @param {?} req
* @return {?}
*/
function (req) {
return this.httpClient.request(req).pipe(filter((/**
* @param {?} event
* @return {?}
*/
function (event) {
return event.type === HttpEventType.Sent ||
event.type === HttpEventType.UploadProgress ||
event.type === HttpEventType.Response;
})), map((/**
* @param {?} event
* @return {?}
*/
function (event) {
switch (event.type) {
case HttpEventType.Sent:
return { type: 'start', value: null };
case HttpEventType.UploadProgress:
/** @type {?} */
var progress = Math.round((100 * event.loaded) / event.total);
return { type: 'progress', value: progress };
case HttpEventType.Response:
return { type: 'response', value: event.body };
}
})));
};
/**
* @private
* @return {?}
*/
Uploader.prototype.calculateTotalProgress = /**
* @private
* @return {?}
*/
function () {
/** @type {?} */
var value = this.uploadingItems.reduce((/**
* @param {?} acc
* @param {?} item
* @return {?}
*/
function (acc, item) { return item.progress + acc; }), 0) /
(this.uploadingItemsCount || 1);
if (this.removeAfterUpload) {
this._totalProgress = value;
}
else {
/** @type {?} */
var ratio = 100 / this.itemsCount;
/** @type {?} */
var current = (value * ratio) / 100;
this._totalProgress = Math.round(this.uploadedItemsCount * ratio + current);
}
};
/**
* @private
* @param {?} queueItem
* @return {?}
*/
Uploader.prototype.prepareQueueItem = /**
* @private
* @param {?} queueItem
* @return {?}
*/
function (queueItem) {
var _this = this;
return new Observable((/**
* @param {?} observer
* @return {?}
*/
function (observer) {
queueItem.subscription = _this.request(queueItem.item.req)
.pipe(finalize((/**
* @return {?}
*/
function () {
if (!observer.closed) {
observer.complete();
}
})), tap((/**
* @param {?} event
* @return {?}
*/
function (event) {
switch (event.type) {
case 'start':
queueItem.item.onUploadStart();
break;
case 'progress':
/** @type {?} */
var progress = event.value;
/** @type {?} */
var item = queueItem.item;
item.onUploadProgress(progress);
_this.onItemProgressSubject.next({ item: item, progress: progress });
_this.calculateTotalProgress();
break;
default:
break;
}
})), filter((/**
* @param {?} event
* @return {?}
*/
function (event) { return event.type === 'response'; })), map((/**
* @param {?} event
* @return {?}
*/
function (event) { return event.value; })))
.subscribe({
next: (/**
* @param {?} res
* @return {?}
*/
function (res) {
queueItem.subscription = null;
observer.next({ item: queueItem.item, res: res });
observer.complete();
}),
error: (/**
* @param {?} err
* @return {?}
*/
function (err) {
queueItem.subscription = null;
observer.error({ item: queueItem.item, err: err });
}),
complete: (/**
* @return {?}
*/
function () { return observer.complete(); })
});
}));
};
/**
* @private
* @return {?}
*/
Uploader.prototype.setupQueue = /**
* @private
* @return {?}
*/
function () {
var _this = this;
this.queue = [];
this.scheduler = new Subject();
this.scheduler
.pipe(mergeMap((/**
* @param {?} queueItem
* @return {?}
*/
function (queueItem) {
return _this.prepareQueueItem(queueItem).pipe(catchError((/**
* @param {?} uploadEvent
* @return {?}
*/
function (uploadEvent) {
_this.onQueueItemError(uploadEvent);
return of(null);
})));
}), this.concurrency), filter((/**
* @param {?} uploadEvent
* @return {?}
*/
function (uploadEvent) { return Boolean(uploadEvent); })))
.subscribe((/**
* @param {?} uploadEvent
* @return {?}
*/
function (uploadEvent) { return _this.onQueueItemSuccess(uploadEvent); }));
};
/**
* @private
* @param {?} __0
* @return {?}
*/
Uploader.prototype.isValidRequestParams = /**
* @private
* @param {?} __0
* @return {?}
*/
function (_a) {
var url = _a.url, method = _a.method;
return Boolean(url || this.url) && Boolean(method || this.method);
};
/**
* @private
* @param {?} file
* @return {?}
*/
Uploader.prototype.isValidFileType = /**
* @private
* @param {?} file
* @return {?}
*/
function (file) {
return this.allowedMimeTypes && this.allowedMimeTypes.length
? this.allowedMimeTypes.includes(file.type)
: true;
};
/**
* @private
* @param {?} file
* @return {?}
*/
Uploader.prototype.isValidFileSize = /**
* @private
* @param {?} file
* @return {?}
*/
function (file) {
return this.maxFileSize ? file.size <= this.maxFileSize : true;
};
/**
* @private
* @param {?} file
* @return {?}
*/
Uploader.prototype.isValidFile = /**
* @private
* @param {?} file
* @return {?}
*/
function (file) {
return this.isValidFileType(file) && this.isValidFileSize(file);
};
/**
* @private
* @return {?}
*/
Uploader.prototype.canAddToQueue = /**
* @private
* @return {?}
*/
function () {
return this.queueLimit ? this.itemsCount < this.queueLimit : true;
};
/**
* @private
* @param {?} options
* @return {?}
*/
Uploader.prototype.checkItem = /**
* @private
* @param {?} options
* @return {?}
*/
function (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 {?}
*/
Uploader.prototype.addItem = /**
* @param {?} options
* @return {?}
*/
function (options) {
this.checkItem(options);
Object.assign(options, {
url: options.url || this.url,
method: options.method || this.method
});
/** @type {?} */
var item = new UploadItem(this, options);
this.queue.push({ item: item, subscription: null });
this.calculateTotalProgress();
if (this.autoUpload) {
item.upload();
}
return item;
};
/**
* @param {?} item
* @return {?}
*/
Uploader.prototype.uploadItem = /**
* @param {?} item
* @return {?}
*/
function (item) {
/** @type {?} */
var queueItem = this.queue.find((/**
* @param {?} current
* @return {?}
*/
function (current) {
return current.item === item &&
!(current.item.isReady ||
current.item.isUploading ||
current.item.isUploaded);
}));
if (queueItem) {
item.onBeforeUpload();
this.scheduler.next(queueItem);
}
};
/**
* @return {?}
*/
Uploader.prototype.uploadAll = /**
* @return {?}
*/
function () {
this.items
.filter((/**
* @param {?} item
* @return {?}
*/
function (item) { return !(item.isReady || item.isUploading || item.isUploaded); }))
.forEach((/**
* @param {?} item
* @return {?}
*/
function (item) { return item.upload(); }));
};
/**
* @param {?} item
* @return {?}
*/
Uploader.prototype.cancelItem = /**
* @param {?} item
* @return {?}
*/
function (item) {
/** @type {?} */
var queueItem = this.queue.find((/**
* @param {?} current
* @return {?}
*/
function (current) { return current.item === item && item.isReady; }));
if (queueItem) {
if (queueItem.subscription) {
queueItem.subscription.unsubscribe();
queueItem.subscription = null;
}
queueItem.item.onUploadCancelled();
this.calculateTotalProgress();
}
};
/**
* @return {?}
*/
Uploader.prototype.cancelAll = /**
* @return {?}
*/
function () {
this.notUploadedItems.forEach((/**
* @param {?} item
* @return {?}
*/
function (item) { return item.cancel(); }));
};
/**
* @param {?} item
* @return {?}
*/
Uploader.prototype.removeItem = /**
* @param {?} item
* @return {?}
*/
function (item) {
if (item.isUploading) {
item.cancel();
}
item.cleanup();
this.queue = this.queue.filter((/**
* @param {?} current
* @return {?}
*/
function (current) { return current.item !== item; }));
this.calculateTotalProgress();
};
/**
* @return {?}
*/
Uploader.prototype.clearQueue = /**
* @return {?}
*/
function () {
while (this.itemsCount) {
this.queue[0].item.remove();
}
this._totalProgress = 0;
};
return Uploader;
}());
export { Uploader };
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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXBsb2FkZXIuY2xhc3MuanMiLCJzb3VyY2VSb290Ijoibmc6Ly9AdHJlbmRzdGVyLWlvL25nLXVwbG9hZGVyLyIsInNvdXJjZXMiOlsibGliL3VwbG9hZGVyLmNsYXNzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7QUFBQSxPQUFPLEVBSUwsYUFBYSxFQUNkLE1BQU0sc0JBQXNCLENBQUM7QUFFOUIsT0FBTyxFQUFFLE9BQU8sRUFBRSxVQUFVLEVBQUUsRUFBRSxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQy9DLE9BQU8sRUFDTCxRQUFRLEVBQ1IsR0FBRyxFQUNILE1BQU0sRUFDTixHQUFHLEVBQ0gsVUFBVSxFQUNWLFFBQVEsRUFDVCxNQUFNLGdCQUFnQixDQUFDO0FBRXhCLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQVVqRDtJQW1CRSxrQkFBb0IsVUFBc0IsRUFBRSxPQUE2QjtRQUE3Qix3QkFBQSxFQUFBLFlBQTZCO1FBQXJELGVBQVUsR0FBVixVQUFVLENBQVk7UUFDeEMsSUFBSSxDQUFDLG9CQUFvQixHQUFHLElBQUksT0FBTyxFQUFFLENBQUM7UUFDMUMsSUFBSSxDQUFDLHFCQUFxQixHQUFHLElBQUksT0FBTyxFQUFFLENBQUM7UUFDM0MsSUFBSSxDQUFDLGtCQUFrQixHQUFHLElBQUksT0FBTyxFQUFFLENBQUM7UUFDeEMsSUFBSSxDQUFDLGFBQWEsR0FBRyxJQUFJLENBQUMsb0JBQW9CLENBQUMsWUFBWSxFQUFFLENBQUM7UUFDOUQsSUFBSSxDQUFDLGNBQWMsR0FBRyxJQUFJLENBQUMscUJBQXFCLENBQUMsWUFBWSxFQUFFLENBQUM7UUFDaEUsSUFBSSxDQUFDLFdBQVcsR0FBRyxJQUFJLENBQUMsa0JBQWtCLENBQUMsWUFBWSxFQUFFLENBQUM7UUFDMUQsSUFBSSxDQUFDLGNBQWMsR0FBRyxDQUFDLENBQUM7UUFDeEIsSUFBSSxDQUFDLEdBQUcsR0FBRyxPQUFPLENBQUMsR0FBRyxDQUFDO1FBQ3ZCLElBQUks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QkFBNEI7Ozs7O0lBQzVCLCtCQUE0Qjs7Ozs7SUFDNUIsb0NBQW1DOzs7OztJQUNuQyx5QkFBaUM7Ozs7O0lBQ2pDLDZCQUE0Qzs7Ozs7SUFFaEMsOEJBQThCIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgSHR0cEVycm9yUmVzcG9uc2UsXG4gIEh0dHBDbGllbnQsXG4gIEh0dHBSZXF1ZXN0LFxuICBIdHRwRXZlbnRUeXBlXG59IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbi9odHRwJztcblxuaW1wb3J0IHsgU3ViamVjdCwgT2JzZXJ2YWJsZSwgb2YgfSBmcm9tICdyeGpzJztcbmltcG9ydCB7XG4gIG1lcmdlTWFwLFxuICB0YXAsXG4gIGZpbHRlcixcbiAgbWFwLFxuICBjYXRjaEVycm9yLFxuICBmaW5hbGl6ZVxufSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XG5cbmltcG9ydCB7IFVwbG9hZEl0ZW0gfSBmcm9tICcuL3VwbG9hZC1pdGVtLmNsYXNzJztcblxuaW1wb3J0IHtcbiAgVXBsb2FkTGlzdGVuZXIsXG4gIFVwbG9hZGVyT3B0aW9ucyxcbiAgVXBsb2FkSXRlbU9wdGlvbnMsXG4gIFVwbG9hZEl0ZW1FdmVudCxcbiAgVXBsb2FkUXVldWVJdGVtXG59IGZyb20gJy4vbW9kZWxzJztcblxuZXhwb3J0IGNsYXNzIFVwbG9hZGVyIGltcGxlbWVudHMgVXBsb2FkTGlzdGVuZXIge1xuICByZWFkb25seSBvbkl0ZW1TdWNjZXNzOiBPYnNlcnZhYmxlPFVwbG9hZEl0ZW1FdmVudD47XG4gIHJlYWRvbmx5IG9uSXRlbVByb2dyZXNzOiBPYnNlcnZhYmxlPFVwbG9hZEl0ZW1FdmVudD47XG4gIHJlYWRvbmx5IG9uSXRlbUVycm9yOiBPYnNlcnZhYmxlPFVwbG9hZEl0ZW1FdmVudD47XG4gIHByaXZhdGUgb25JdGVtU3VjY2Vzc1N1YmplY3Q6IFN1YmplY3Q8VXBsb2FkSXRlbUV2ZW50PjtcbiAgcHJpdmF0ZSBvbkl0ZW1Qcm9ncmVzc1N1YmplY3Q6IFN1YmplY3Q8VXBsb2FkSXRlbUV2ZW50PjtcbiAgcHJpdmF0ZSBvbkl0ZW1FcnJvclN1YmplY3Q6IFN1YmplY3Q8VXBsb2FkSXRlbUV2ZW50PjtcbiAgcHJpdmF0ZSBfdG90YWxQcm9ncmVzczogbnVtYmVyO1xuICBwcml2YXRlIHVybDogc3RyaW5nO1xuICBwcml2YXRlIG1ldGhvZDogJ1BPU1QnIHwgJ1BVVCcgfCAnUEFUQ0gnO1xuICBwcml2YXRlIGF1dG9VcGxvYWQ6IGJvb2xlYW47XG4gIHByaXZhdGUgcmVtb3ZlQWZ0ZXJVcGxvYWQ6IGJvb2xlYW47XG4gIHByaXZhdGUgcXVldWVMaW1pdDogbnVtYmVyO1xuICBwcml2YXRlIGNvbmN1cnJlbmN5OiBudW1iZXI7XG4gIHByaXZhdGUgbWF4RmlsZVNpemU6IG51bWJlcjtcbiAgcHJpdmF0ZSBhbGxvd2VkTWltZVR5cGVzOiBzdHJpbmdbXTtcbiAgcHJpdmF0ZSBxdWV1ZTogVXBsb2FkUXVldWVJdGVtW107XG4gIHByaXZhdGUgc2NoZWR1bGVyOiBTdWJqZWN0PFVwbG9hZFF1ZXVlSXRlbT47XG5cbiAgY29uc3RydWN0b3IocHJpdmF0ZSBodHRwQ2xpZW50OiBIdHRwQ2xpZW50LCBvcHRpb25zOiBVcGxvYWRlck9wdGlvbnMgPSB7fSkge1xuICAgIHRoaXMub25JdGVtU3VjY2Vzc1N1YmplY3QgPSBuZXcgU3ViamVjdCgpO1xuICAgIHRoaXMub25JdGVtUHJvZ3Jlc3NTdWJqZWN0ID0gbmV3IFN1YmplY3QoKTtcbiAgICB0aGlzLm9uSXRlbUVycm9yU3ViamVjdCA9IG5ldyBTdWJqZWN0KCk7XG4gICAgdGhpcy5vbkl0ZW1TdWNjZXNzID0gdGhpcy5vbkl0ZW1TdWNjZXNzU3ViamVjdC5hc09ic2VydmFibGUoKTtcbiAgICB0aGlzLm9uSXRlbVByb2dyZXNzID0gdGhpcy5vbkl0ZW1Qcm9ncmVzc1N1YmplY3QuYXNPYnNlcnZhYmxlKCk7XG4gICAgdGhpcy5vbkl0ZW1FcnJvciA9IHRoaXMub25JdGVtRXJyb3JTdWJqZWN0LmFzT2JzZXJ2YWJsZSgpO1xuICAgIHRoaXMuX3RvdGFsUHJvZ3Jlc3MgPSAwO1xuICAgIHRoaXMudXJsID0gb3B0aW9ucy51cmw7XG4gICAgdGhpcy5tZXRob2QgPSBvcHRpb25zLm1ldGhvZDtcbiAgICB0aGlzLmF1dG9VcGxvYWQgPSBvcHRpb25zLmF1dG9VcGxvYWQ7XG4gICAgdGhpcy5yZW1vdmVBZnRlclVwbG9hZCA9IG9wdGlvbnMucmVtb3ZlQWZ0ZXJVcGxvYWQ7XG4gICAgdGhpcy5xdWV1ZUxpbWl0ID0gb3B0aW9ucy5xdWV1ZUxpbWl0O1xuICAgIHRoaXMuY29uY3VycmVuY3kgPSBvcHRpb25zLmNvbmN1cnJlbmN5IHx8IDE7XG4gICAgdGhpcy5tYXhGaWxlU2l6ZSA9IG9wdGlvbnMubWF4RmlsZVNpemU7XG4gICAgdGhpcy5hbGxvd2VkTWltZVR5cGVzID0gb3B0aW9ucy5hbGxvd2VkTWltZVR5cGVzO1xuICAgIHRoaXMuc2V0dXBRdWV1ZSgpO1xuICB9XG5cbiAgZ2V0IGl0ZW1zQ291bnQoKTogbnVtYmVyIHtcbiAgICByZXR1cm4gdGhpcy5xdWV1ZS5sZW5ndGg7XG4gIH1cblxuICBnZXQgaXRlbXMoKTogVXBsb2FkSXRlbVtdIHtcbiAgICByZXR1cm4gdGhpcy5xdWV1ZS5tYXAocXVldWVJdGVtID0+IHF1ZXVlSXRlbS5pdGVtKTtcbiAgfVxuXG4gIGdldCByZWFkeUl0ZW1zQ291bnQoKTogbnVtYmVyIHtcbiAgICByZXR1cm4gdGhpcy5xdWV1ZVxuICAgICAgLm1hcChxdWV1ZUl0ZW0gPT4gcXVldWVJdGVtLml0ZW0pXG4gICAgICAuZmlsdGVyKGl0ZW0gPT4gaXRlbS5pc1JlYWR5ICYmICFpdGVtLmlzVXBsb2FkaW5nKS5sZW5ndGg7XG4gIH1cblxuICBwcml2YXRlIGdldCByZWFkeUl0ZW1zKCk6IFVwbG9hZEl0ZW1bXSB7XG4gICAgcmV0dXJuIHRoaXMucXVldWVcbiAgICAgIC5tYXAocXVldWVJdGVtID0+IHF1ZXVlSXRlbS5pdGVtKVxuICAgICAgLmZpbHRlcihpdGVtID0+IGl0ZW0uaXNSZWFkeSAmJiAhaXRlbS5pc1VwbG9hZGluZyk7XG4gIH1cblxuICBnZXQgdXBsb2FkaW5nSXRlbXNDb3VudCgpOiBudW1iZXIge1xuICAgIHJldHVybiB0aGlzLnF1ZXVlXG4gICAgICAubWFwKHF1ZXVlSXRlbSA9PiBxdWV1ZUl0ZW0uaXRlbSlcbiAgICAgIC5maWx0ZXIoaXRlbSA9PiBpdGVtLmlzVXBsb2FkaW5nKS5sZW5ndGg7XG4gIH1cblxuICBwcml2YXRlIGdldCB1cGxvYWRpbmdJdGVtcygpOiBVcGxvYWRJdGVtW10ge1xuICAgIHJldHVybiB0aGlzLnF1ZXVlXG4gICAgICAubWFwKHF1ZXVlSXRlbSA9PiBxdWV1ZUl0ZW0uaXRlbSlcbiAgICAgIC5maWx0ZXIoaXRlbSA9PiBpdGVtLmlzVXBsb2FkaW5nKTtcbiAgfVxuXG4gIGdldCB1cGxvYWRlZEl0ZW1zQ291bnQoKTogbnVtYmVyIHtcbiAgICByZXR1cm4gdGhpcy5xdWV1ZVxuICAgICAgLm1hcChxdWV1ZUl0ZW0gPT4gcXVldWVJdGVtLml0ZW0pXG4gICAgICAuZmlsdGVyKGl0ZW0gPT4gaXRlbS5pc1VwbG9hZGVkKS5sZW5ndGg7XG4gIH1cblxuICBwcml2YXRlIGdldCB1cGxvYWRlZEl0ZW1zKCk6IFVwbG9hZEl0ZW1bXSB7XG4gICAgcmV0dXJuIHRoaXMucXVldWVcbiAgICAgIC5tYXAocXVldWVJdGVtID0+IHF1ZXVlSXRlbS5pdGVtKVxuICAgICAgLmZpbHRlcihpdGVtID0+IGl0ZW0uaXNVcGxvYWRlZCk7XG4gIH1cblxuICBnZXQgbm90VXBsb2FkZWRJdGVtc0NvdW50KCk6IG51bWJlciB7XG4gICAgcmV0dXJuIHRoaXMucXVldWVcbiAgICAgIC5tYXAocXVldWVJdGVtID0+IHF1ZXVlSXRlbS5pdGVtKVxuICAgICAgLmZpbHRlcihpdGVtID0+ICFpdGVtLmlzVXBsb2FkZWQpLmxlbmd0aDtcbiAgfVxuXG4gIHByaXZhdGUgZ2V0IG5vdFVwbG9hZGVkSXRlbXMoKTogVXBsb2FkSXRlbVtdIHtcbiAgICByZXR1cm4gdGhpcy5xdWV1ZVxuICAgICAgLm1hcChxdWV1ZUl0ZW0gPT4gcXVldWVJdGVtLml0ZW0pXG4gICAgICAuZmlsdGVyKGl0ZW0gPT4gIWl0ZW0uaXNVcGxvYWRlZCk7XG4gIH1cblxuICBnZXQgY2FuY2VsbGVkSXRlbXNDb3VudCgpOiBudW1iZXIge1xuICAgIHJldHVybiB0aGlzLnF1ZXVlXG4gICAgICAubWFwKHF1ZXVlSXRlbSA9PiBxdWV1ZUl0ZW0uaXRlbSlcbiAgICAgIC5maWx0ZXIoaXRlbSA9PiBpdGVtLmlzQ2FuY2VsbGVkKS5sZW5ndGg7XG4gIH1cblxuICBwcml2YXRlIGdldCBjYW5jZWxsZWRJdGVtcygpOiBVcGxvYWRJdGVtW10ge1xuICAgIHJldHVybiB0aGlzLnF1ZXVlXG4gICAgICAubWFwKHF1ZXVlSXRlbSA9PiBxdWV1ZUl0ZW0uaXRlbSlcbiAgICAgIC5maWx0ZXIoaXRlbSA9PiBpdGVtLmlzQ2FuY2VsbGVkKTtcbiAgfVxuXG4gIGdldCBlcnJvckl0ZW1zQ291bnQoKTogbnVtYmVyIHtcbiAgICByZXR1cm4gdGhpcy5xdWV1ZVxuICAgICAgLm1hcChxdWV1ZUl0ZW0gPT4gcXVldWVJdGVtLml0ZW0pXG4gICAgICAuZmlsdGVyKGl0ZW0gPT4gaXRlbS5pc0Vycm9yKS5sZW5ndGg7XG4gIH1cblxuICBwcml2YXRlIGdldCBlcnJvckl0ZW1zKCk6IFVwbG9hZEl0ZW1bXSB7XG4gICAgcmV0dXJuIHRoaXMucXVldWVcbiAgICAgIC5tYXAocXVldWVJdGVtID0+IHF1ZXVlSXRlbS5pdGVtKVxuICAgICAgLmZpbHRlcihpdGVtID0+IGl0ZW0uaXNFcnJvcik7XG4gIH1cblxuICBnZXQgdG90YWxQcm9ncmVzcygpOiBudW1iZXIge1xuICAgIHJldHVybiB0aGlzLl90b3RhbFByb2dyZXNzO1xuICB9XG5cbiAgZ2V0IGlzVXBsb2FkaW5nKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLnVwbG9hZGluZ0l0ZW1zQ291bnQgPiAwO1xuICB9XG5cbiAgcHJpdmF0ZSBvblF1ZXVlSXRlbVN1Y2Nlc3MoeyBpdGVtLCByZXMgfTogVXBsb2FkSXRlbUV2ZW50KTogdm9pZCB7XG4gICAgaXRlbS5vblVwbG9hZFN1Y2Nlc3MocmVzKTtcbiAgICB0aGlzLm9uSXRlbVN1Y2Nlc3NTdWJqZWN0Lm5leHQoeyBpdGVtLCByZXMgfSk7XG4gICAgaWYgKHRoaXMucmVtb3ZlQWZ0ZXJVcGxvYWQpIHtcbiAgICAgIGl0ZW0ucmVtb3ZlKCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBvblF1ZXVlSXRlbUVycm9yKHsgaXRlbSwgZXJyIH06IFVwbG9hZEl0ZW1FdmVudCk6IHZvaWQge1xuICAgIGl0ZW0ub25VcGxvYWRFcnJvcihlcnIpO1xuICAgIHRoaXMub25JdGVtRXJyb3JTdWJqZWN0Lm5leHQoeyBpdGVtLCBlcnIgfSk7XG4gIH1cblxuICBwcml2YXRlIHJlcXVlc3QocmVxOiBIdHRwUmVxdWVzdDxGb3JtRGF0YT4pOiBPYnNlcnZhYmxlPGFueT4ge1xuICAgIHJldHVybiB0aGlzLmh0dHBDbGllbnQucmVxdWVzdChyZXEpLnBpcGUoXG4gICAgICBmaWx0ZXIoXG4gICAgICAgIGV2ZW50ID0+XG4gICAgICAgICAgZXZlbnQudHlwZSA9PT0gSHR0cEV2ZW50VHlwZS5TZW50IHx8XG4gICAgICAgICAgZXZlbnQudHlwZSA9PT0gSHR0cEV2ZW50VHlwZS5VcGxvYWRQcm9ncmVzcyB8fFxuICAgICAgICAgIGV2ZW50LnR5cGUgPT09IEh0dHBFdmVudFR5cGUuUmVzcG9uc2VcbiAgICAgICksXG4gICAgICBtYXAoZXZlbnQgPT4ge1xuICAgICAgICBzd2l0Y2ggKGV2ZW50LnR5cGUpIHtcbiAgICAgICAgICBjYXNlIEh0dHBFdmVudFR5cGUuU2VudDpcbiAgICAgICAgICAgIHJldHVybiB7IHR5cGU6ICdzdGFydCcsIHZhbHVlOiBudWxsIH07XG4gICAgICAgICAgY2FzZSBIdHRwRXZlbnRUeXBlLlVwbG9hZFByb2dyZXNzOlxuICAgICAgICAgICAgY29uc3QgcHJvZ3Jlc3MgPSBNYXRoLnJvdW5kKCgxMDAgKiBldmVudC5sb2FkZWQpIC8gZXZlbnQudG90YWwpO1xuICAgICAgICAgICAgcmV0dXJuIHsgdHlwZTogJ3Byb2dyZXNzJywgdmFsdWU6IHByb2dyZXNzIH07XG4gICAgICAgICAgY2FzZSBIdHRwRXZlbnRUeXBlLlJlc3BvbnNlOlxuICAgICAgICAgICAgcmV0dXJuIHsgdHlwZTogJ3Jlc3BvbnNlJywgdmFsdWU6IGV2ZW50LmJvZHkgfTtcbiAgICAgICAgfVxuICAgICAgfSlcbiAgICApO1xuICB9XG5cbiAgcHJpdmF0ZSBjYWxjdWxhdGVUb3RhbFByb2dyZXNzKCk6IHZvaWQge1xuICAgIGNvbnN0IHZhbHVlID1cbiAgICAgIHRoaXMudXBsb2FkaW5nSXRlbXMucmVkdWNlKChhY2MsIGl0ZW0pID0+IGl0ZW0ucHJvZ3Jlc3MgKyBhY2MsIDApIC9cbiAgICAgICh0aGlzLnVwbG9hZGluZ0l0ZW1zQ291bnQgfHwgMSk7XG4gICAgaWYgKHRoaXMucmVtb3ZlQWZ0ZXJVcGxvYWQpIHtcbiAgICAgIHRoaXMuX3RvdGFsUHJvZ3Jlc3MgPSB2YWx1ZTtcbiAgICB9IGVsc2Uge1xuICAgICAgY29uc3QgcmF0aW8gPSAxMDAgLyB0aGlzLml0ZW1zQ291bnQ7XG4gICAgICBjb25zdCBjdXJyZW50ID0gKHZhbHVlICogcmF0aW8pIC8gMTAwO1xuICAgICAgdGhpcy5fdG90YWxQcm9ncmVzcyA9IE1hdGgucm91bmQoXG4gICAgICAgIHRoaXMudXBsb2FkZWRJdGVtc0NvdW50ICogcmF0aW8gKyBjdXJyZW50XG4gICAgICApO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgcHJlcGFyZVF1ZXVlSXRlbShxdWV1ZUl0ZW06IFVwbG9hZFF1ZXVlSXRlbSk6IE9ic2VydmFibGU8YW55PiB7XG4gICAgcmV0dXJuIG5ldyBPYnNlcnZhYmxlKG9ic2VydmVyID0+IHtcbiAgICAgIHF1ZXVlSXRlbS5zdWJzY3JpcHRpb24gPSB0aGlzLnJlcXVlc3QocXVldWVJdGVtLml0ZW0ucmVxKVxuICAgICAgICAucGlwZShcbiAgICAgICAgICBmaW5hbGl6ZSgoKSA9PiB7XG4gICAgICAgICAgICBpZiAoIW9ic2VydmVyLmNsb3NlZCkge1xuICAgICAgICAgICAgICBvYnNlcnZlci5jb21wbGV0ZSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0pLFxuICAgICAgICAgIHRhcChldmVudCA9PiB7XG4gICAgICAgICAgICBzd2l0Y2ggKGV2ZW50LnR5cGUpIHtcbiAgICAgICAgICAgICAgY2FzZSAnc3RhcnQnOlxuICAgICAgICAgICAgICAgIHF1ZXVlSXRlbS5pdGVtLm9uVXBsb2FkU3RhcnQoKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgY2FzZSAncHJvZ3Jlc3MnOlxuICAgICAgICAgICAgICAgIGNvbnN0IHByb2dyZXNzID0gZXZlbnQudmFsdWU7XG4gICAgICAgICAgICAgICAgY29uc3QgaXRlbSA9IHF1ZXVlSXRlbS5pdGVtO1xuICAgICAgICAgICAgICAgIGl0ZW0ub25VcGxvYWRQcm9ncmVzcyhwcm9ncmVzcyk7XG4gICAgICAgICAgICAgICAgdGhpcy5vbkl0ZW1Qcm9ncmVzc1N1YmplY3QubmV4dCh7IGl0ZW0sIHByb2dyZXNzIH0pO1xuICAgICAgICAgICAgICAgIHRoaXMuY2FsY3VsYXRlVG90YWxQcm9ncmVzcygpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0pLFxuICAgICAgICAgIGZpbHRlcihldmVudCA9PiBldmVudC50eXBlID09PSAncmVzcG9uc2UnKSxcbiAgICAgICAgICBtYXAoZXZlbnQgPT4gZXZlbnQudmFsdWUpXG4gICAgICAgIClcbiAgICAgICAgLnN1YnNjcmliZSh7XG4gICAgICAgICAgbmV4dDogcmVzID0+IHtcbiAgICAgICAgICAgIHF1ZXVlSXRlbS5zdWJzY3JpcHRpb24gPSBudWxsO1xuICAgICAgICAgICAgb2JzZXJ2ZXIubmV4dCh7IGl0ZW06IHF1ZXVlSXRlbS5pdGVtLCByZXMgfSk7XG4gICAgICAgICAgICBvYnNlcnZlci5jb21wbGV0ZSgpO1xuICAgICAgICAgIH0sXG4gICAgICAgICAgZXJyb3I6IChlcnI6IEh0dHBFcnJvclJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICBxdWV1ZUl0ZW0uc3Vic2NyaXB0aW9uID0gbnVsbDtcbiAgICAgICAgICAgIG9ic2VydmVyLmVycm9yKHsgaXRlbTogcXVldWVJdGVtLml0ZW0sIGVyciB9KTtcbiAgICAgICAgICB9LFxuICAgICAgICAgIGNvbXBsZXRlOiAoKSA9PiBvYnNlcnZlci5jb21wbGV0ZSgpXG4gICAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cbiAgcHJpdmF0ZSBzZXR1cFF1ZXVlKCk6IHZvaWQge1xuICAgIHRoaXMucXVldWUgPSBbXTtcbiAgICB0aGlzLnNjaGVkdWxlciA9IG5ldyBTdWJqZWN0KCk7XG4gICAgdGhpcy5zY2hlZHVsZXJcbiAgICAgIC5waXBlKFxuICAgICAgICBtZXJnZU1hcChcbiAgICAgICAgICBxdWV1ZUl0ZW0gPT5cbiAgICAgICAgICAgIHRoaXMucHJlcGFyZVF1ZXVlSXRlbShxdWV1ZUl0ZW0pLnBpcGUoXG4gICAgICAgICAgICAgIGNhdGNoRXJyb3IoKHVwbG9hZEV2ZW50OiBVcGxvYWRJdGVtRXZlbnQpID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLm9uUXVldWVJdGVtRXJyb3IodXBsb2FkRXZlbnQpO1xuICAgICAgICAgICAgICAgIHJldHVybiBvZihudWxsKTtcbiAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICksXG4gICAgICAgICAgdGhpcy5jb25jdXJyZW5jeVxuICAgICAgICApLFxuICAgICAgICBmaWx0ZXIoKHVwbG9hZEV2ZW50OiBVcGxvYWRJdGVtRXZlbnQpID0+IEJvb2xlYW4odXBsb2FkRXZlbnQpKVxuICAgICAgKVxuICAgICAgLnN1YnNjcmliZSh1cGxvYWRFdmVudCA9PiB0aGlzLm9uU