filestack-js
Version:
Official JavaScript library for Filestack
767 lines • 101 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.S3Uploader = void 0;
var tslib_1 = require("tslib");
/*
* Copyright (c) 2019 by Filestack.
* Some rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
var debug_1 = tslib_1.__importDefault(require("debug"));
var p_queue_1 = tslib_1.__importDefault(require("p-queue"));
var filestack_error_1 = require("./../../../../filestack_error");
var request_1 = require("./../../../request");
var helpers_1 = require("./../../../request/helpers");
var utils_1 = require("./../../../utils");
var abstract_1 = require("./abstract");
var debug = (0, debug_1.default)('fs:upload:s3');
var COMPLETE_TIMEOUT = 1000 * 1;
var S3Uploader = /** @class */ (function (_super) {
tslib_1.__extends(S3Uploader, _super);
function S3Uploader(storeOptions, concurrency) {
var _this = _super.call(this, storeOptions, concurrency) || this;
_this.payloads = {};
_this.partsQueue = new p_queue_1.default({
autoStart: false,
concurrency: _this.concurrency,
});
_this.cancelToken = new request_1.FsCancelToken();
return _this;
}
/**
* Pause upload queue
*
* @memberof S3Uploader
*/
S3Uploader.prototype.pause = function () {
this.partsQueue.pause();
};
/**
* resume upload queue if its paused
*
* @memberof S3Uploader
*/
S3Uploader.prototype.resume = function () {
/* istanbul ignore next */
if (this.partsQueue.isPaused) {
this.partsQueue.start();
}
};
/**
* Aborts queue (all pending requests with will be aborted)
*
* @memberof S3Uploader
*/
S3Uploader.prototype.abort = function (msg) {
this.partsQueue.pause();
this.partsQueue.clear();
this.cancelToken.cancel(msg || 'Aborted by user');
};
/**
* Execute all queued files
*
* @returns {Promise<any>}
* @memberof S3Uploader
*/
S3Uploader.prototype.execute = function () {
return tslib_1.__awaiter(this, void 0, void 0, function () {
var tasks;
var _this = this;
return tslib_1.__generator(this, function (_a) {
tasks = Object.keys(this.payloads).map(function (id) {
return new Promise(function (resolve) { return tslib_1.__awaiter(_this, void 0, void 0, function () {
var e_1, file;
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0:
_a.trys.push([0, 5, , 6]);
return [4 /*yield*/, this.startRequest(id)];
case 1:
_a.sent();
return [4 /*yield*/, this.prepareParts(id)];
case 2:
_a.sent();
return [4 /*yield*/, this.startPartsQueue(id)];
case 3:
_a.sent();
return [4 /*yield*/, this.completeRequest(id)];
case 4:
_a.sent();
return [3 /*break*/, 6];
case 5:
e_1 = _a.sent();
/* istanbul ignore next */
this.emit('error', e_1);
debug("[".concat(id, "] File upload failed. %O, \nDetails: %O "), e_1.message, e_1.details);
return [3 /*break*/, 6];
case 6:
file = this.getPayloadById(id).file;
// release file buffer
file.release();
// cleanup payloads
delete this.payloads[id];
resolve(file);
return [2 /*return*/];
}
});
}); });
});
return [2 /*return*/, Promise.all(tasks)];
});
});
};
/**
* Add file to upload queue
*
* @param {File} file
* @returns
* @memberof S3Uploader
*/
S3Uploader.prototype.addFile = function (file) {
debug('Add file to queue: \n %o', file);
var id = "".concat((0, utils_1.uniqueId)(15), "_").concat((0, utils_1.uniqueTime)());
file.status = "Initialized" /* FileState.INIT */;
// split file into parts and set it as waiting
this.payloads[id] = {
file: file,
parts: [],
};
return id;
};
/**
* Returns host for upload (region based)
*
* @private
* @returns
* @memberof S3Uploader
*/
S3Uploader.prototype.getUploadUrl = function (id) {
var location_url = this.getDefaultFields(id, ['location_url']).location_url;
return location_url.indexOf('http') === 0 ? location_url : "https://".concat(location_url);
};
/**
* Returns formatted store options
*
* @private
* @returns
* @memberof S3Uploader
*/
S3Uploader.prototype.getStoreOptions = function (id) {
var options = tslib_1.__assign({ location: abstract_1.DEFAULT_STORE_LOCATION }, this.storeOptions);
if (this.storeOptions.disableStorageKey) {
var payload = this.getPayloadById(id);
if (options.path && options.path.substr(-1) !== '/') {
options.path = "".concat(options.path, "/");
}
options.path = "".concat(options.path ? options.path : '/').concat(payload.file.name);
delete options.disableStorageKey;
}
return options;
};
/**
* Returns all default fields for filestack requests
*
* @private
* @returns
* @memberof S3Uploader
*/
S3Uploader.prototype.getDefaultFields = function (id, requiredFields, fiiFallback) {
if (fiiFallback === void 0) { fiiFallback = false; }
var payload = this.getPayloadById(id);
var fields = tslib_1.__assign(tslib_1.__assign({}, this.security), { apikey: this.apikey, uri: payload.uri, location_url: payload.location_url, upload_id: payload.upload_id, region: payload.region, alt: payload.file.alt });
if (this.uploadMode === "intelligent" /* UploadMode.INTELLIGENT */ || (this.uploadMode === "fallback" /* UploadMode.FALLBACK */ && fiiFallback)) {
fields['fii'] = true;
}
return tslib_1.__assign(tslib_1.__assign({}, (0, utils_1.filterObject)(fields, requiredFields)), { store: this.getStoreOptions(id) });
};
/**
* Returns default headers needed for filestack request
*
* @private
* @returns
* @memberof S3Uploader
*/
S3Uploader.prototype.getDefaultHeaders = function (id) {
var headers = {};
var file = this.getPayloadById(id);
if (file.location_region) {
headers['Filestack-Upload-Region'] = file.location_region;
}
return headers;
};
S3Uploader.prototype.getPayloadById = function (id) {
return this.payloads[id];
};
/**
* Split file onto parts for uploading with multipart mechanism and setup start
*
* @private
* @memberof S3Uploader
*/
S3Uploader.prototype.prepareParts = function (id) {
var file = this.getPayloadById(id).file;
var intelligentChunk = false;
// for intelligent or fallback mode we cant overwrite part size - requires 8MB
if (["intelligent" /* UploadMode.INTELLIGENT */, "fallback" /* UploadMode.FALLBACK */].indexOf(this.uploadMode) > -1) {
this.partSize = abstract_1.INTELLIGENT_CHUNK_SIZE;
intelligentChunk = true;
}
var _a = file.getPartsCount(this.partSize, intelligentChunk), partsCount = _a.partsCount, chunkSize = _a.chunkSize;
var parts = [];
for (var i = 0; i < partsCount; i++) {
parts[i] = tslib_1.__assign(tslib_1.__assign({}, file.getPartMetadata(i, chunkSize)), { offset: 0 });
}
// split file into parts and set it as waiting
this.payloads[id].parts = parts;
return Promise.resolve();
};
/**
* Make start request for getting needed upload fields
*
* @private
* @returns {Promise<any>}
* @memberof S3Uploader
*/
S3Uploader.prototype.startRequest = function (id) {
var _this = this;
var payload = this.getPayloadById(id);
if (payload.file.size === 0) {
this.setPayloadStatus(id, "Failed" /* FileState.FAILED */);
return Promise.reject(new filestack_error_1.FilestackError("Invalid file \"".concat(payload.file.name, "\" size - 0"), {}, filestack_error_1.FilestackErrorType.VALIDATION));
}
debug("[".concat(id, "] Make start request"));
return request_1.FsRequest.post("".concat(this.getUrl(), "/multipart/start"), tslib_1.__assign({ filename: payload.file.name, mimetype: payload.file.type, size: payload.file.size }, this.getDefaultFields(id, ['apikey', 'policy', 'signature', 'fii'], true)), {
timeout: this.timeout,
cancelToken: this.cancelToken,
headers: this.getDefaultHeaders(id),
retry: this.retryConfig,
})
.then(function (_a) {
var data = _a.data;
if (!data || !data.location_url || !data.region || !data.upload_id || !data.uri) {
debug("[".concat(id, "] Incorrect start response: \n%O\n"), data);
_this.setPayloadStatus(id, "Failed" /* FileState.FAILED */);
return Promise.reject(new filestack_error_1.FilestackError('Incorrect start response', data, filestack_error_1.FilestackErrorType.REQUEST));
}
debug("[".concat(id, "] Assign payload data: \n%O\n"), data);
_this.updatePayload(id, data);
// ii is not enabled in backend switch back to default upload mode
if (["intelligent" /* UploadMode.INTELLIGENT */, "fallback" /* UploadMode.FALLBACK */].indexOf(_this.uploadMode) > -1 && (!data.upload_type || data.upload_type !== 'intelligent_ingestion')) {
debug("[".concat(id, "] Intelligent Ingestion is not enabled on account, switch back to regular upload and lock mode change"));
_this.setUploadMode("default" /* UploadMode.DEFAULT */, true);
}
return data;
})
.catch(function (err) {
debug("[".concat(id, "] Start request error %O"), err);
_this.setPayloadStatus(id, "Failed" /* FileState.FAILED */);
return _this.rejectUpload('Cannot upload file. Start request failed', err);
});
};
/**
* Enqueue file parts to upload
*
* @private
* @returns
* @memberof S3Uploader
*/
S3Uploader.prototype.startPartsQueue = function (id) {
return tslib_1.__awaiter(this, void 0, void 0, function () {
var payload, parts, waitingLength;
var _this = this;
return tslib_1.__generator(this, function (_a) {
payload = this.getPayloadById(id);
parts = payload.parts;
waitingLength = parts.length;
debug("[".concat(id, "] Create uploading queue from file. parts count - %d"), waitingLength);
return [2 /*return*/, new Promise(function (resolve, reject) { return tslib_1.__awaiter(_this, void 0, void 0, function () {
var _a;
var _this = this;
return tslib_1.__generator(this, function (_b) {
switch (_b.label) {
case 0:
parts.forEach(function (part) {
return _this.partsQueue
.add(function () { return _this.startPart(id, part.partNumber); })
.catch(function (e) {
_this.setPayloadStatus(id, "Failed" /* FileState.FAILED */);
debug("[".concat(id, "] Failed to upload part %s"), e.message);
_this.partsQueue.pause();
_this.partsQueue.clear();
return reject(e);
});
});
debug("[".concat(id, "] All tasks for %s enqueued. Start processing main upload queue"), id);
this.emit('start');
this.partsQueue.start();
_a = resolve;
return [4 /*yield*/, this.partsQueue.onIdle()];
case 1:
_a.apply(void 0, [_b.sent()]);
return [2 /*return*/];
}
});
}); })];
});
});
};
/**
* Decide if upload should be made using ii or regular upload
* It allows change upload mode during upload queue
*
* @private
* @param {number} partNumber
* @returns {Promise<any>}
* @memberof S3Uploader
*/
S3Uploader.prototype.startPart = function (id, partNumber) {
debug("[".concat(id, "] Start processing part ").concat(partNumber, " with mode ").concat(this.uploadMode));
var payload = this.getPayloadById(id);
payload.file.status = "Progress" /* FileState.PROGRESS */;
return (this.uploadMode !== "intelligent" /* UploadMode.INTELLIGENT */ ? this.uploadRegular : this.uploadIntelligent).apply(this, [id, partNumber]);
};
/**
* Returns part data needed for upload
*
* @private
* @param {string} id - id of a currently uploading file
* @param {FilePart} part
* @returns
* @memberof S3Uploader
*/
S3Uploader.prototype.getS3PartMetadata = function (id, part, offset) {
var _this = this;
var url = this.getUploadUrl(id);
debug("[".concat(id, "] Get data for part ").concat(part.partNumber, ", url ").concat(url, ", Md5: ").concat(part.md5, ", Size: ").concat(part.size));
var data = tslib_1.__assign(tslib_1.__assign({}, this.getDefaultFields(id, ['apikey', 'uri', 'region', 'signature', 'policy', 'upload_id', 'fii'])), {
// method specific keys
part: part.partNumber + 1, size: part.size, offset: offset });
if (this.integrityCheck && part.md5) {
data.md5 = part.md5;
}
return request_1.FsRequest.post("".concat(url, "/multipart/upload"), data, {
headers: this.getDefaultHeaders(id),
cancelToken: this.cancelToken,
timeout: this.timeout,
retry: this.retryConfig,
}).catch(function (err) {
_this.setPayloadStatus(id, "Failed" /* FileState.FAILED */);
return _this.rejectUpload('Cannot get part metadata', err);
});
};
/**
* Regular multipart request to amazon
*
* @private
* @param {number} partNumber
* @returns {Promise<any>}
* @memberof S3Uploader
*/
S3Uploader.prototype.uploadRegular = function (id, partNumber) {
return tslib_1.__awaiter(this, void 0, void 0, function () {
var payload, partMetadata, part, _a, data, headers;
var _this = this;
return tslib_1.__generator(this, function (_b) {
switch (_b.label) {
case 0:
payload = this.getPayloadById(id);
partMetadata = payload.parts[partNumber];
return [4 /*yield*/, payload.file.getPartByMetadata(partMetadata, this.integrityCheck)];
case 1:
part = _b.sent();
return [4 /*yield*/, this.getS3PartMetadata(id, part)];
case 2:
_a = _b.sent(), data = _a.data, headers = _a.headers;
debug("[".concat(id, "] Received part ").concat(partNumber, " info body: \n%O\n headers: \n%O\n"), data, headers);
return [2 /*return*/, request_1.FsRequest.put(data.url, part.buffer, {
cancelToken: this.cancelToken,
timeout: this.timeout,
headers: data.headers,
filestackHeaders: false,
// for now we cant test progress callback from upload
/* istanbul ignore next */
onProgress: function (pr) { return _this.onProgressUpdate(id, partNumber, pr.loaded); },
retry: this.retryConfig && this.uploadMode !== "fallback" /* UploadMode.FALLBACK */ ? this.retryConfig : undefined,
})
.then(function (res) {
if (res.headers.etag) {
_this.setPartETag(id, partNumber, res.headers.etag);
}
else {
// release memory
part = null;
throw new filestack_error_1.FilestackError('Cannot upload file, check S3 bucket settings', 'Etag header is not exposed in CORS settings', filestack_error_1.FilestackErrorType.REQUEST);
}
debug("[".concat(id, "] S3 Upload response headers for ").concat(partNumber, ": \n%O\n"), res.headers);
_this.onProgressUpdate(id, partNumber, part.size);
// release memory
part = null;
return res;
})
.catch(function (err) {
var resp = err && err.response ? err.response : null;
/* istanbul ignore next */
if (resp && resp.status === 403) {
if (resp.data && resp.data.Error && resp.data.Error.code) {
var code = resp.data.Error.code;
if (Array.isArray(code)) {
code = code.pop();
}
switch (code) {
case 'RequestTimeTooSkewed':
return _this.startPart(id, partNumber);
default:
return Promise.reject(new filestack_error_1.FilestackError('Cannot upload file', resp.data.Error, filestack_error_1.FilestackErrorType.REQUEST));
}
}
}
// release memory
part = null;
if (err instanceof filestack_error_1.FilestackError) {
return Promise.reject(err);
}
// reset upload progress on failed part
_this.onProgressUpdate(id, partNumber, 0);
// if fallback, set upload mode to intelligent and restart current part
if ((_this.uploadMode === "fallback" /* UploadMode.FALLBACK */ && !_this.isModeLocked) || _this.uploadMode === "intelligent" /* UploadMode.INTELLIGENT */) {
debug("[".concat(id, "] Regular upload failed. Switching to intelligent ingestion mode"));
_this.setUploadMode("intelligent" /* UploadMode.INTELLIGENT */);
// restart part
return _this.startPart(id, partNumber);
}
return _this.rejectUpload('Cannot upload file part', err);
})];
}
});
});
};
/**
* Upload file using intelligent mechanism
*
* @private
* @param {string} id
* @param {number} partNumber
* @returns {Promise<any>}
* @memberof S3Uploader
*/
S3Uploader.prototype.uploadIntelligent = function (id, partNumber) {
return tslib_1.__awaiter(this, void 0, void 0, function () {
var _this = this;
return tslib_1.__generator(this, function (_a) {
return [2 /*return*/, this.uploadNextChunk(id, partNumber).then(function () { return _this.commitPart(id, partNumber); })];
});
});
};
/**
* Recursively upload file in chunk mode (intelligent ingession)
*
* @private
* @param {string} id
* @param {number} partNumber
* @param {number} chunkSize
* @returns
* @memberof S3Uploader
*/
S3Uploader.prototype.uploadNextChunk = function (id, partNumber, chunkSize) {
if (chunkSize === void 0) { chunkSize = this.intelligentChunkSize; }
return tslib_1.__awaiter(this, void 0, void 0, function () {
var payload, part, chunk, data;
var _this = this;
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0:
payload = this.getPayloadById(id);
part = payload.parts[partNumber];
chunkSize = part.size - part.offset;
return [4 /*yield*/, payload.file.getChunkByMetadata(part, part.offset, chunkSize, this.integrityCheck)];
case 1:
chunk = _a.sent();
debug("[".concat(id, "] PartNum: ").concat(partNumber, ", PartSize: ").concat(part.size, ", StartByte: ").concat(part.startByte, ", Offset: ").concat(part.offset, ", ChunkSize: ").concat(chunk.size, ",\n Left: ").concat(part.size - part.offset - chunk.size));
return [4 /*yield*/, this.getS3PartMetadata(id, chunk, part.offset).catch(function (err) {
debug("[".concat(id, "] Getting chunk data for ii failed %O, Chunk size: ").concat(chunkSize, ", offset ").concat(part.offset, ", part ").concat(partNumber), err);
return Promise.reject(err);
})];
case 2:
data = (_a.sent()).data;
return [2 /*return*/, request_1.FsRequest.put(data.url, chunk.buffer, {
cancelToken: this.cancelToken,
timeout: this.timeout,
headers: data.headers,
filestackHeaders: false,
// for now we cant test progress callback from upload
/* istanbul ignore next */
onProgress: function (pr) { return part ? _this.onProgressUpdate(id, partNumber, part.offset + pr.loaded) : null; },
})
.then(function (res) {
_this.onProgressUpdate(id, partNumber, part.offset + chunk.size);
var newOffset = Math.min(part.offset + chunkSize, part.size);
debug("[".concat(id, "] S3 Chunk uploaded! offset: ").concat(part.offset, ", part ").concat(partNumber, "! response headers for ").concat(partNumber, ": \n%O\n"), res.headers);
_this.setPartData(id, partNumber, 'offset', newOffset);
// if all chunks was uploaded then return resolve
if (newOffset === part.size) {
return Promise.resolve(res);
}
// release memory
part = null;
chunk = null;
return _this.uploadNextChunk(id, partNumber, chunkSize);
})
.catch(function (err) {
var resp = err && err.response ? err.response : null;
/* istanbul ignore next */
if (resp && resp.status === 403) {
if (resp.data && resp.data.Error && resp.data.Error.code) {
var code = resp.data.Error.code;
if (Array.isArray(code)) {
code = code.pop();
}
switch (code) {
case 'RequestTimeTooSkewed':
return _this.startPart(id, partNumber);
default:
return Promise.reject(new filestack_error_1.FilestackError('Cannot upload file', resp.data.Error, filestack_error_1.FilestackErrorType.REQUEST));
}
}
}
// reset progress on failed upload
_this.onProgressUpdate(id, partNumber, part.offset);
var nextChunkSize = Math.ceil(chunkSize / 2);
if (nextChunkSize < abstract_1.MIN_CHUNK_SIZE) {
debug("[".concat(id, "] Minimal chunk size limit. Upload file failed!"));
return Promise.reject(new filestack_error_1.FilestackError('Min chunk size reached', err.data, filestack_error_1.FilestackErrorType.REQUEST));
}
if ((0, helpers_1.shouldRetry)(err)) {
debug("[".concat(id, "] Request network error. Retry with new chunk size: ").concat(nextChunkSize));
return _this.uploadNextChunk(id, partNumber, nextChunkSize);
}
// release memory
part = null;
chunk = null;
return _this.rejectUpload('Cannot upload file part (FII)', err);
})];
}
});
});
};
/**
* Commit after upload all chunks of the part in ii mode
*
* @private
* @param {string} id
* @param {FilePart} part
* @returns
* @memberof S3Uploader
*/
S3Uploader.prototype.commitPart = function (id, partNumber) {
var _this = this;
var payload = this.getPayloadById(id);
var part = payload.parts[partNumber];
return request_1.FsRequest.post("".concat(this.getUploadUrl(id), "/multipart/commit"), tslib_1.__assign(tslib_1.__assign({}, this.getDefaultFields(id, ['apikey', 'region', 'upload_id', 'policy', 'signature', 'uri'])), { size: payload.file.size, part: part.partNumber + 1 }), {
cancelToken: this.cancelToken,
timeout: this.timeout,
headers: this.getDefaultHeaders(id),
retry: this.retryConfig,
})
.then(function (res) {
debug("[".concat(id, "] Commit Part number ").concat(part.partNumber, ". Response: %O"), res.data);
return res;
})
.catch(function (err) {
return _this.rejectUpload('Cannot commit file part metadata', err);
});
};
/**
* Complete request to merge all parts and get file handle etc
*
* @private
* @returns
* @memberof S3Uploader
*/
S3Uploader.prototype.completeRequest = function (id) {
var _this = this;
var payload = this.getPayloadById(id);
var parts = [];
debug("[".concat(id, "] Run complete request"));
var partsHandle = payload.parts;
var partLen = partsHandle.length;
for (var i = 0; i < partLen; i++) {
if (partsHandle[i].etag) {
parts.push({ part_number: i + 1, etag: partsHandle[i].etag });
}
}
debug("[".concat(id, "] Etags %O"), parts);
return request_1.FsRequest.post("".concat(this.getUploadUrl(id), "/multipart/complete"), tslib_1.__assign(tslib_1.__assign({}, this.getDefaultFields(id, ['apikey', 'policy', 'signature', 'uri', 'region', 'upload_id', 'fii', 'alt'], true)), {
// method specific keys
filename: payload.file.name, mimetype: payload.file.type, size: payload.file.size, upload_tags: this.uploadTags && Object.keys(this.uploadTags).length ? this.uploadTags : undefined, parts: parts.length ? parts : undefined }), {
timeout: this.timeout,
cancelToken: this.cancelToken,
headers: this.getDefaultHeaders(id),
retry: this.retryConfig,
})
.then(function (res) {
// if parts hasnt been merged, retry complete request again
if (res.status === 202) {
return new Promise(function (resolve, reject) {
setTimeout(function () {
return _this.completeRequest(id)
.then(resolve)
.catch(reject);
}, COMPLETE_TIMEOUT);
});
}
// update file object
var file = _this.getPayloadById(id).file;
file.handle = res.data.handle;
file.url = res.data.url;
file.container = res.data.container;
file.key = res.data.key;
file.uploadTags = res.data.upload_tags;
file.workflows = res.data.workflows;
file.status = res.data.status;
return file;
})
.catch(function (err) {
_this.setPayloadStatus(id, "Failed" /* FileState.FAILED */);
return _this.rejectUpload('Cannot complete file', err);
});
};
/**
* UUpgrade upload progress and run progress event
*
* @private
* @param {string} id
* @param {number} partNumber
* @param {number} loaded
* @memberof S3Uploader
*/
S3Uploader.prototype.onProgressUpdate = function (id, partNumber, loaded) {
this.setPartData(id, partNumber, 'progress', loaded);
this.emitProgress();
};
/**
* Emits normalized progress event
*
* @private
* @memberof S3Uploader
*/
S3Uploader.prototype.emitProgress = function () {
var totalSize = 0;
var totalBytes = 0;
var filesProgress = {};
for (var i in this.payloads) {
var payload = this.payloads[i];
// omit all failed files in progress event
// this shouldn't happend because of promises rejection in execute. Left to be sure
/* istanbul ignore next */
if (payload.file.status === "Failed" /* FileState.FAILED */) {
continue;
}
var totalParts = payload.parts.map(function (p) { return p.progress || 0; }).reduce(function (a, b) { return a + b; }, 0);
totalBytes = totalBytes + totalParts;
filesProgress[i] = {
totalBytes: totalParts,
totalPercent: Math.round((totalParts * 100) / payload.file.size) || 0,
};
totalSize = totalSize + payload.file.size;
}
var res = {
totalBytes: totalBytes || 0,
totalPercent: Math.round((totalBytes * 100) / totalSize) || 0,
files: filesProgress,
};
debug("Upload progress %O", res);
this.emit('progress', res);
};
/**
* Apply provided data to given payload
*
* @private
* @param {string} id
* @param {*} data
* @memberof S3Uploader
*/
S3Uploader.prototype.updatePayload = function (id, data) {
this.payloads[id] = tslib_1.__assign(tslib_1.__assign({}, this.payloads[id]), data);
};
/**
* Sets etag for part
*
* @private
* @param {number} partNumber
* @param {string} etag
* @memberof S3Uploader
*/
S3Uploader.prototype.setPartETag = function (id, partNumber, etag) {
debug("[".concat(id, "] Set ").concat(etag, " etag for part ").concat(partNumber));
this.getPayloadById(id).parts[partNumber].etag = etag;
};
/**
* Sets part value for a key
*
* @private
* @param {number} partNumber
* @param {string} etag
* @memberof S3Uploader
*/
S3Uploader.prototype.setPartData = function (id, partNumber, key, value) {
debug("[".concat(id, "] Set ").concat(key, " = ").concat(value, " for part ").concat(partNumber));
var payload = this.getPayloadById(id);
/* istanbul ignore next */
if (!payload) {
debug("[".concat(id, "] Cannot set ").concat(key, " = ").concat(value, " for part ").concat(partNumber));
return;
}
payload.parts[partNumber][key] = value;
};
/**
* Set payload file state
*
* @param id
* @param status
*/
S3Uploader.prototype.setPayloadStatus = function (id, status) {
debug("[".concat(id, "] Set payload status to ").concat(status));
/* istanbul ignore next: additional check in case if file will be deleted before setting status */
if (!this.payloads[id]) {
return;
}
this.payloads[id].file.status = status;
};
/**
* Returns error details if response exists
*
* @param err
*/
S3Uploader.prototype.parseError = function (err) {
if (!err.response) {
return {};
}
return {
code: err.response.status,
data: err.response.data,
headers: err.response.headers,
};
};
S3Uploader.prototype.rejectUpload = function (message, err) {
if (err instanceof request_1.FsRequestError && err.code === request_1.FsRequestErrorCode.ABORTED) {
return Promise.reject(new filestack_error_1.FilestackError(message, { reason: err.message }, filestack_error_1.FilestackErrorType.ABORTED));
}
return Promise.reject(new filestack_error_1.FilestackError(message, this.parseError(err), filestack_error_1.FilestackErrorType.REQUEST));
};
return S3Uploader;
}(abstract_1.UploaderAbstract));
exports.S3Uploader = S3Uploader;
//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9saWIvYXBpL3VwbG9hZC91cGxvYWRlcnMvczMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7OztBQUFBOzs7Ozs7Ozs7Ozs7Ozs7R0FlRztBQUNILHdEQUEwQjtBQUMxQiw0REFBNkI7QUFFN0IsaUVBQW1GO0FBQ25GLDhDQUE4RztBQUM5RyxzREFBeUQ7QUFDekQsMENBQXNFO0FBR3RFLHVDQUEwSDtBQUUxSCxJQUFNLEtBQUssR0FBRyxJQUFBLGVBQUssRUFBQyxjQUFjLENBQUMsQ0FBQztBQUVwQyxJQUFNLGdCQUFnQixHQUFHLElBQUksR0FBRyxDQUFDLENBQUM7QUFtQmxDO0lBQWdDLHNDQUFnQjtJQU05QyxvQkFBWSxZQUFnQyxFQUFFLFdBQVk7UUFBMUQsWUFDRSxrQkFBTSxZQUFZLEVBQUUsV0FBVyxDQUFDLFNBUWpDO1FBWE8sY0FBUSxHQUFxQyxFQUFFLENBQUM7UUFLdEQsS0FBSSxDQUFDLFVBQVUsR0FBRyxJQUFJLGlCQUFNLENBQUM7WUFDM0IsU0FBUyxFQUFFLEtBQUs7WUFDaEIsV0FBVyxFQUFFLEtBQUksQ0FBQyxXQUFXO1NBQzlCLENBQUMsQ0FBQztRQUVILEtBQUksQ0FBQyxXQUFXLEdBQUcsSUFBSSx1QkFBYSxFQUFFLENBQUM7O0lBQ3pDLENBQUM7SUFFRDs7OztPQUlHO0lBQ0ksMEJBQUssR0FBWjtRQUNFLElBQUksQ0FBQyxVQUFVLENBQUMsS0FBSyxFQUFFLENBQUM7SUFDMUIsQ0FBQztJQUVEOzs7O09BSUc7SUFDSSwyQkFBTSxHQUFiO1FBQ0UsMEJBQTBCO1FBQzFCLElBQUksSUFBSSxDQUFDLFVBQVUsQ0FBQyxRQUFRLEVBQUU7WUFDNUIsSUFBSSxDQUFDLFVBQVUsQ0FBQyxLQUFLLEVBQUUsQ0FBQztTQUN6QjtJQUNILENBQUM7SUFFRDs7OztPQUlHO0lBQ0ksMEJBQUssR0FBWixVQUFhLEdBQVk7UUFDdkIsSUFBSSxDQUFDLFVBQVUsQ0FBQyxLQUFLLEVBQUUsQ0FBQztRQUN4QixJQUFJLENB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RUFBRSxHQUFHLENBQUMsUUFBUSxDQUFDLElBQUk7WUFDdkIsT0FBTyxFQUFFLEdBQUcsQ0FBQyxRQUFRLENBQUMsT0FBTztTQUM5QixDQUFDO0lBQ0osQ0FBQztJQUVPLGlDQUFZLEdBQXBCLFVBQXFCLE9BQWUsRUFBRSxHQUFtQjtRQUN2RCxJQUFJLEdBQUcsWUFBWSx3QkFBYyxJQUFJLEdBQUcsQ0FBQyxJQUFJLEtBQUssNEJBQWtCLENBQUMsT0FBTyxFQUFFO1lBQzVFLE9BQU8sT0FBTyxDQUFDLE1BQU0sQ0FBQyxJQUFJLGdDQUFjLENBQUMsT0FBTyxFQUFFLEVBQUUsTUFBTSxFQUFFLEdBQUcsQ0FBQyxPQUFPLEVBQUUsRUFBRSxvQ0FBa0IsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDO1NBQ3pHO1FBQ0QsT0FBTyxPQUFPLENBQUMsTUFBTSxDQUFDLElBQUksZ0NBQWMsQ0FBQyxPQUFPLEVBQUUsSUFBSSxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsRUFBRSxvQ0FBa0IsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDO0lBQ3ZHLENBQUM7SUFDSCxpQkFBQztBQUFELENBcDBCQSxBQW8wQkMsQ0FwMEIrQiwyQkFBZ0IsR0FvMEIvQztBQXAwQlksZ0NBQVUiLCJmaWxlIjoibGliL2FwaS91cGxvYWQvdXBsb2FkZXJzL3MzLmpzIiwic291cmNlc0NvbnRlbnQiOlsiLypcbiAqIENvcHlyaWdodCAoYykgMjAxOSBieSBGaWxlc3RhY2suXG4gKiBTb21lIHJpZ2h0cyByZXNlcnZlZC5cbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cbmltcG9ydCBEZWJ1ZyBmcm9tICdkZWJ1Zyc7XG5pbXBvcnQgUFF1ZXVlIGZyb20gJ3AtcXVldWUnO1xuXG5pbXBvcnQgeyBGaWxlc3RhY2tFcnJvciwgRmlsZXN0YWNrRXJyb3JUeXBlIH0gZnJvbSAnLi8uLi8uLi8uLi8uLi9maWxlc3RhY2tfZXJyb3InO1xuaW1wb3J0IHsgRnNDYW5jZWxUb2tlbiwgRnNSZXF1ZXN0LCBGc1JlcXVlc3RFcnJvciwgRnNSZXF1ZXN0RXJyb3JDb2RlLCBGc1Jlc3BvbnNlIH0gZnJvbSAnLi8uLi8uLi8uLi9yZXF1ZXN0JztcbmltcG9ydCB7IHNob3VsZFJldHJ5IH0gZnJvbSAnLi8uLi8uLi8uLi9yZXF1ZXN0L2hlbHBlcnMnO1xuaW1wb3J0IHsgZmlsdGVyT2JqZWN0LCB1bmlxdWVJZCwgdW5pcXVlVGltZSB9IGZyb20gJy4vLi4vLi4vLi4vdXRpbHMnO1xuaW1wb3J0IHsgRmlsZSwgRmlsZVBhcnQsIEZpbGVQYXJ0TWV0YWRhdGEsIEZpbGVTdGF0ZSB9IGZyb20gJy4vLi4vZmlsZSc7XG5pbXBvcnQgeyBTdG9yZVVwbG9hZE9wdGlvbnMgfSBmcm9tICcuLy4uL3R5cGVzJztcbmltcG9ydCB7IERFRkFVTFRfU1RPUkVfTE9DQVRJT04sIElOVEVMTElHRU5UX0NIVU5LX1NJWkUsIE1JTl9DSFVOS19TSVpFLCBVcGxvYWRlckFic3RyYWN0LCBVcGxvYWRNb2RlIH0gZnJvbSAnLi9hYnN0cmFjdCc7XG5cbmNvbnN0IGRlYnVnID0gRGVidWcoJ2ZzOnVwbG9hZDpzMycpO1xuXG5jb25zdCBDT01QTEVURV9USU1FT1VUID0gMTAwMCAqIDE7XG5cbmV4cG9ydCBpbnRlcmZhY2UgVXBsb2FkUGFydCBleHRlbmRzIEZpbGVQYXJ0TWV0YWRhdGEge1xuICBldGFnPzogc3RyaW5nO1xuICBvZmZzZXQ/OiBudW1iZXI7XG4gIHByb2dyZXNzPzogbnVtYmVyO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFVwbG9hZFBheWxvYWQge1xuICBmaWxlOiBGaWxlO1xuICBwYXJ0czogVXBsb2FkUGFydFtdO1xuICBoYW5kbGU/OiBzdHJpbmc7XG4gIHVyaT86IHN0cmluZztcbiAgcmVnaW9uPzogc3RyaW5nO1xuICB1cGxvYWRfaWQ/OiBudW1iZXI7XG4gIGxvY2F0aW9uX3VybD86IHN0cmluZztcbiAgbG9jYXRpb25fcmVnaW9uPzogc3RyaW5nO1xufVxuXG5leHBvcnQgY2xhc3MgUzNVcGxvYWRlciBleHRlbmRzIFVwbG9hZGVyQWJzdHJhY3Qge1xuICBwcml2YXRlIHBhcnRzUXVldWU7XG4gIHByaXZhdGUgY2FuY2VsVG9rZW46IEZzQ2FuY2VsVG9rZW47IC8vIGdsb2JhbCBjYW5jZWwgdG9rZW4gZm9yIGFsbCByZXF1ZXN0c1xuXG4gIHByaXZhdGUgcGF5bG9hZHM6IHsgW2tleTogc3RyaW5nXTogVXBsb2FkUGF5bG9hZCB9ID0ge307XG5cbiAgY29uc3RydWN0b3Ioc3RvcmVPcHRpb25zOiBTdG9yZVVwbG9hZE9wdGlvbnMsIGNvbmN1cnJlbmN5Pykge1xuICAgIHN1cGVyKHN0b3JlT3B0aW9ucywgY29uY3VycmVuY3kpO1xuXG4gICAgdGhpcy5wYXJ0c1F1ZXVlID0gbmV3IFBRdWV1ZSh7XG4gICAgICBhdXRvU3RhcnQ6IGZhbHNlLFxuICAgICAgY29uY3VycmVuY3k6IHRoaXMuY29uY3VycmVuY3ksXG4gICAgfSk7XG5cbiAgICB0aGlzLmNhbmNlbFRva2VuID0gbmV3IEZzQ2FuY2VsVG9rZW4oKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBQYXVzZSB1cGxvYWQgcXVldWVcbiAgICpcbiAgICogQG1lbWJlcm9mIFMzVXBsb2FkZXJcbiAgICovXG4gIHB1YmxpYyBwYXVzZSgpOiB2b2lkIHtcbiAgICB0aGlzLnBhcnRzUXVldWUucGF1c2UoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiByZXN1bWUgdXBsb2FkIHF1ZXVlIGlmIGl0cyBwYXVzZWRcbiAgICpcbiAgICogQG1lbWJlcm9mIFMzVXBsb2FkZXJcbiAgICovXG4gIHB1YmxpYyByZXN1bWUoKTogdm9pZCB7XG4gICAgLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cbiAgICBpZiAodGhpcy5wYXJ0c1F1ZXVlLmlzUGF1c2VkKSB7XG4gICAgICB0aGlzLnBhcnRzUXVldWUuc3RhcnQoKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQWJvcnRzIHF1ZXVlIChhbGwgcGVuZGluZyByZXF1ZXN0cyB3aXRoIHdpbGwgYmUgYWJvcnRlZClcbiAgICpcbiAgICogQG1lbWJlcm9mIFMzVXBsb2FkZXJcbiAgICovXG4gIHB1YmxpYyBhYm9ydChtc2c/OiBzdHJpbmcpOiB2b2lkIHtcbiAgICB0aGlzLnBhcnRzUXVldWUucGF1c2UoKTtcbiAgICB0aGlzLnBhcnRzUXVldWUuY2xlYXIoKTtcblxuICAgIHRoaXMuY2FuY2VsVG9rZW4uY2FuY2VsKG1zZyB8fCAnQWJvcnRlZCBieSB1c2VyJyk7XG4gIH1cblxuICAvKipcbiAgICogRXhlY3V0ZSBhbGwgcXVldWVkIGZpbGVzXG4gICAqXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPGFueT59XG4gICAqIEBtZW1iZXJvZiBTM1VwbG9hZGVyXG4gICAqL1xuICBwdWJsaWMgYXN5bmMgZXhlY3V0ZSgpOiBQcm9taXNlPGFueT4ge1xuICAgIGNvbnN0IHRhc2tzID0gT2JqZWN0LmtleXModGhpcy5wYXlsb2FkcykubWFwKFxuICAgICAgaWQgPT5cbiAgICAgICAgbmV3IFByb21pc2UoYXN5bmMgcmVzb2x2ZSA9PiB7XG4gICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGF3YWl0IHRoaXMuc3RhcnRSZXF1ZXN0KGlkKTtcbiAgICAgICAgICAgIGF3YWl0IHRoaXMucHJlcGFyZVBhcnRzKGlkKTtcbiAgICAgICAgICAgIGF3YWl0IHRoaXMuc3RhcnRQYXJ0c1F1ZXVlKGlkKTtcbiAgICAgICAgICAgIGF3YWl0IHRoaXMuY29tcGxldGVSZXF1ZXN0KGlkKTtcbiAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dCAqL1xuICAgICAgICAgICAgdGhpcy5lbWl0KCdlcnJvcicsIGUpO1xuICAgICAgICAgICAgZGVidWcoYFske2lkfV0gRmlsZSB1cGxvYWQgZmFpbGVkLiAlTywgXFxuRGV0YWlsczogJU8gYCwgZS5tZXNzYWdlLCBlLmRldGFpbHMpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGNvbnN0IGZpbGUgPSB0aGlzLmdldFBheWxvYWRCeUlkKGlkKS5maWxlO1xuXG4gICAgICAgICAgLy8gcmVsZWFzZSBmaWxlIGJ1ZmZlclxuICAgICAgICAgIGZpbGUucmVsZWFzZSgpO1xuXG4gICAgICAgICAgLy8gY2xlYW51cCBwYXlsb2Fkc1xuICAgICAgICAgIGRlbGV0ZSB0aGlzLnBheWxvYWRzW2lkXTtcblxuICAgICAgICAgIHJlc29sdmUoZmlsZSk7XG4gICAgICAgIH0pXG4gICAgKTtcblxuICAgIHJldHVybiBQcm9taXNlLmFsbCh0YXNrcyk7XG4gIH1cblxuICAvKipcbiAgICogQWRkIGZpbGUgdG8gdXBsb2FkIHF1ZXVlXG4gICAqXG4gICAqIEBwYXJhbSB7RmlsZX0gZmlsZVxuICAgKiBAcmV0dXJuc1xuICAgKiBAbWVtYmVyb2YgUzNVcGxvYWRlclxuICAgKi9cbiAgcHVibGljIGFkZEZpbGUoZmlsZTogRmlsZSk6IHN0cmluZyB7XG4gICAgZGVidWcoJ0FkZCBmaWxlIHRvIHF1ZXVlOiBcXG4gJW8nLCBmaWxlKTtcblxuICAgIGNvbnN0IGlkID0gYCR7dW5pcXVlSWQoMTUpfV8ke3VuaXF1ZVRpbWUoKX1gO1xuXG4gICAgZmlsZS5zdGF0dXMgPSBGaWxlU3RhdGUuSU5JVDtcblxuICAgIC8vIHNwbGl0IGZpbGUgaW50byBwYXJ0cyBhbmQgc2V0IGl0IGFzIHdhaXRpbmdcbiAgICB0aGlzLnBheWxvYWRzW2lkXSA9IHtcbiAgICAgIGZpbGUsXG4gICAgICBwYXJ0czogW10sXG4gICAgfTtcblxuICAgIHJldHVybiBpZDtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGhvc3QgZm9yIHVwbG9hZCAocmVnaW9uIGJhc2VkKVxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcmV0dXJuc1xuICAgKiBAbWVtYmVyb2YgUzNVcGxvYWRlclxuICAgKi9cbiAgcHJpdmF0ZSBnZXRVcGxvYWRVcmwoaWQ6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgY29uc3QgeyBsb2NhdGlvbl91cmwgfSA9IHRoaXMuZ2V0RGVmYXVsdEZpZWxkcyhpZCwgWydsb2NhdGlvbl91cmwnXSk7XG4gICAgcmV0dXJuIGxvY2F0aW9uX3VybC5pbmRleE9mKCdodHRwJykgPT09IDAgPyBsb2NhdGlvbl91cmwgOiBgaHR0cHM6Ly8ke2xvY2F0aW9uX3VybH1gO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgZm9ybWF0dGVkIHN0b3JlIG9wdGlvbnNcbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHJldHVybnNcbiAgICogQG1lbWJlcm9mIFMzVXBsb2FkZXJcbiAgICovXG4gIHByaXZhdGUgZ2V0U3RvcmVPcHRpb25zKGlkOiBzdHJpbmcpOiBTdG9yZVVwbG9hZE9wdGlvbnMge1xuICAgIGxldCBvcHRpb25zID0ge1xuICAgICAgbG9jYXRpb246IERFRkFVTFRfU1RPUkVfTE9DQVRJT04sIC8vIHRoaXMgcGFyYW1ldGVyIGlzIHJlcXVpcmVkLCBpZiBub3Qgc2V0IHVzZSBkZWZhdWx0IG9uZVxuICAgICAgLi4udGhpcy5zdG9yZU9wdGlvbnMsXG4gICAgfTtcblxuICAgIGlmICh0aGlzLnN0b3JlT3B0aW9ucy5kaXNhYmxlU3RvcmFnZUtleSkge1xuICAgICAgY29uc3QgcGF5bG9hZCA9IHRoaXMuZ2V0UGF5bG9hZEJ5SWQoaWQpO1xuXG4gICAgICBpZiAob3B0aW9ucy5wYXRoICYmIG9wdGlvbnMucGF0aC5zdWJzdHIoLTEpICE9PSAnLycpIHtcbiAgICAgICAgb3B0aW9ucy5wYXRoID0gYCR7b3B0aW9ucy5wYXRofS9gO1xuICAgICAgfVxuXG4gICAgICBvcHRpb25zLnBhdGggPSBgJHtvcHRpb25zLnBhdGggPyBvcHRpb25zLnBhdGggOiAnLyd9JHtwYXlsb2FkLmZpbGUubmFtZX1gO1xuXG4gICAgICBkZWxldGUgb3B0aW9ucy5kaXNhYmxlU3RvcmFnZUtleTtcbiAgICB9XG5cbiAgICByZXR1cm4gb3B0aW9ucztcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGFsbCBkZWZhdWx0IGZpZWxkcyBmb3IgZmlsZXN0YWNrIHJlcXVlc3RzXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEByZXR1cm5zXG4gICAqIEBtZW1iZXJvZiBTM1VwbG9hZGVyXG4gICAqL1xuICBwcml2YXRlIGdldERlZmF1bHRGaWVsZHMoaWQ6IHN0cmluZywgcmVxdWlyZWRGaWVsZHM6IHN0cmluZ1tdLCBmaWlGYWxsYmFjazogYm9vbGVhbiA9IGZhbHNlKSB7XG4gICAgY29uc3QgcGF5bG9hZCA9IHRoaXMuZ2V0UGF5bG9hZEJ5SWQoaWQpO1xuXG4gICAgbGV0IGZpZWxkcyA9IHtcbiAgICAgIC4uLnRoaXMuc2VjdXJpdHksXG4gICAgICBhcGlrZXk6IHRoaXMuYXBpa2V5LFxuICAgICAgdXJpOiBwYXlsb2FkLnVyaSxcbiAgICAgIGxvY2F0aW9uX3VybDogcGF5bG9hZC5sb2NhdGlvbl91cmwsXG4gICAgICB1cGxvYWRfaWQ6IHBheWxvYWQudXBsb2FkX2lkLFxuICAgICAgcmVnaW9uOiBwYXlsb2FkLnJlZ2lvbixcbiAgICAgIGFsdDogcGF5bG9hZC5maWxlLmFsdCxcbiAgICB9O1xuXG4gICAgaWYgKHRoaXMudXBsb2FkTW9kZSA9PT0gVXBsb2FkTW9kZS5JTlRFTExJR0VOVCB8fCAodGhpcy51cGxvYWRNb2RlID09PSBVcGxvYWRNb2RlLkZBTExCQUNLICYmIGZpaUZhbGxiYWNrKSkge1xuICAgICAgZmllbGRzWydmaWknXSA9IHRydWU7XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIC4uLmZpbHRlck9iamVjdChmaWVsZHMsIHJlcXVpcmVkRmllbGRzKSxcbiAgICAgIHN0b3JlOiB0aGlzLmdldFN0b3JlT3B0aW9ucyhpZCksXG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGRlZmF1bHQgaGVhZGVycyBuZWVkZWQgZm9yIGZpbGVzdGFjayByZXF1ZXN0XG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEByZXR1cm5zXG4gICAqIEBtZW1iZXJvZiBTM1VwbG9hZGVyXG4gICAqL1xuICBwcml2YXRlIGdldERlZmF1bHRIZWFkZXJzKGlkOiBzdHJpbmcpIHtcbiAgICBsZXQgaGVhZGVycyA9IHt9O1xuICAgIGNvbnN0IGZpbGUgPSB0aGlzLmdldFBheWxvYWRCeUlkKGlkKTtcblxuICAgIGlmIChmaWxlLmxvY2F0aW9uX3JlZ2lvbikge1xuICAgICAgaGVhZGVyc1snRmlsZXN0YWNrLVVwbG9hZC1SZWdpb24nXSA9IGZpbGUubG9jYXRpb25fcmVnaW9uO1xuICAgIH1cblxuICAgIHJldHVybiBoZWFkZXJzO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXRQYXlsb2FkQnlJZChpZDogc3RyaW5nKTogVXBsb2FkUGF5bG9hZCB7XG4gICAgcmV0dXJuIHRoaXMucGF5bG9hZHNbaWRdO1xuICB9XG5cbiAgLyoqXG4gICAqIFNwbGl0IGZpbGUgb250byBwYXJ0cyBmb3IgdXBsb2FkaW5nIHdpdGggbXVsdGlwYXJ0IG1lY2hhbmlzbSBhbmQgc2V0dXAgc3RhcnRcbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQG1lbWJlcm9mIFMzVXBsb2FkZXJcbiAgICovXG4gIHByaXZhdGUgcHJlcGFyZVBhcnRzKGlkOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCBmaWxlID0gdGhpcy5nZXRQYXlsb2FkQnlJZChpZCkuZmlsZTtcbiAgICBsZXQgaW50ZWxsaWdlbnRDaHVuayA9IGZhbHNlO1xuXG4gICAgLy8gZm9yIGludGVsbGlnZW50IG9yIGZhbGxiYWNrIG1vZGUgd2UgY2FudCBvdmVyd3JpdGUgcGFydCBzaXplIC0gcmVxdWlyZXMgOE1CXG4gICAgaWYgKFtVcGxvYWRNb2RlLklOVEVMTElHRU5ULCBVcGxvYWRNb2RlLkZBTExCQUNLXS5pbmRleE9mKHRoaXMudXBsb2FkTW9kZSkgPiAtMSkge1xuICAgICAgdGhpcy5wYXJ0U2l6ZSA9IElOVEVMTElHRU5UX0NIVU5LX1NJWkU7XG4gICAgICBpbnRlbGxpZ2VudENodW5rID0gdHJ1ZTtcbiAgICB9XG5cbiAgICBjb25zdCB7IHBhcnRzQ291bnQsIGNodW5rU2l6ZSB9ID0gZmlsZS5nZXRQYXJ0c0NvdW50KHRoaXMucGFydFNpemUsIGludGVsbGlnZW50Q2h1bmspO1xuXG4gICAgY29uc3QgcGFydHMgPSBbXTtcblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgcGFydHNDb3VudDsgaSsrKSB7XG4gICAgICBwYXJ0c1tpXSA9IHtcbiAgICAgICAgLi4uZmlsZS5nZXRQYXJ0TWV0YWRhdGEoaSwgY2h1bmtTaXplKSxcbiAgICAgICAgb2Zmc2V0OiAwLFxuICAgICAgfTtcbiAgICB9XG5cbiAgICAvLyBzcGxpdCBmaWxlIGludG8gcGFydHMgYW5kIHNldCBpdCBhcyB3YWl0aW5nXG4gICAgdGhpcy5wYXlsb2Fkc1tpZF0ucGFydHMgPSBwYXJ0cztcblxuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBNYWtlIHN0YXJ0IHJlcXVlc3QgZm9yIGdldHRpbmcgbmVlZGVkIHVwbG9hZCBmaWVsZHNcbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHJldHVybnMge1Byb21pc2U8YW55Pn1cbiAgICogQG1lbWJlcm9mIFMzVXBsb2FkZXJcbiAgICovXG4gIHByaXZhdGUgc3RhcnRSZXF1ZXN0KGlkOiBzdHJpbmcpOiBQcm9taXNlPGFueT4ge1xuICAgIGNvbnN0IHBheWxvYWQgPSB0aGlzLmdldFBheWxvYWRCeUlkKGlkKTtcblxuICAgIGlmIChwYXlsb2FkLmZpbGUuc2l6ZSA9PT0gMCkge1xuICAgICAgdGhpcy5zZXRQYXlsb2FkU3RhdHVzKGlkLCBGaWxlU3RhdGUuRkFJTEVEKTtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdChuZXcgRmlsZXN0YWNrRXJyb3IoYEludmFsaWQgZmlsZSBcIiR7cGF5bG9hZC5maWxlLm5hbWV9XCIgc2l6ZSAtIDBgLCB7fSwgRmlsZXN0YWNrRXJyb3JUeXBlLlZBTElEQVRJT04pKTtcbiAgICB9XG5cbiAgICBkZWJ1ZyhgWyR7aWR9XSBNYWtlIHN0YXJ0IHJlcXVlc3RgKTtcbiAgICByZXR1cm4gRnNSZXF1ZXN0LnBvc3QoXG4gICAgICBgJHt0aGlzLmdldFVybCgpfS9tdWx0aXBhcnQvc3RhcnRgLFxuICAgICAge1xuICAgICAgICBmaWxlbmFtZTogcGF5bG9hZC5maWxlLm5hbWUsXG4gICAgICAgIG1pbWV0eXBlOiBwYXlsb2FkLmZpbGUudHlwZSxcbiAgICAgICAgc2l6ZTogcGF5bG9hZC5maWxlLnNpemUsXG4gICAgICAgIC4uLnRoaXMuZ2V0RGVmYXVsdEZpZWxkcyhpZCwgWydhcGlrZXknLCAncG9saWN5JywgJ3NpZ25hdHVyZScsICdmaWknXSwgdHJ1ZSksXG4gICAgICB9LFxuICAgICAge1xuICAgICAgICB0aW1lb3V0OiB0aGlzLnRpbWVvdXQsXG4gICAgICAgIGNhbmNlbFRva2VuOiB0aGlzLmNhbmNlbFRva2VuLFxuICAgICAgICBoZWFkZXJzOiB0aGlzLmdldERlZmF1bHRIZWFkZXJzKGlkKSxcbiAgICAgICAgcmV0cnk6IHRoaXMucmV0cnlDb25maWcsXG4gICAgICB9XG4gICAgKVxuICAgICAgLnRoZW4oKHsgZGF0YSB9KSA9PiB7XG4gICAgICAgIGlmICghZGF0YSB8fCAhZGF0YS5sb2NhdGlvbl91cmwgfHwgIWRhdGEucmVnaW9uIHx8ICFkYXRhLnVwbG9hZF9pZCB8fCAhZGF0YS51cmkpIHtcbiAgICAgICAgICBkZWJ1ZyhgWyR7aWR9XSBJbmNvcnJlY3Qgc3RhcnQgcmVzcG9uc2U6IFxcbiVPXFxuYCwgZGF0YSk7XG4gICAgICAgICAgdGhpcy5zZXRQYXlsb2FkU3RhdHVzKGlkLCBGaWxlU3RhdGUuRkFJTEVEKTtcbiAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QobmV3IEZpbGVzdGFja0Vycm9yKCdJbmNvcnJlY3Qgc3RhcnQgcmVzcG9uc2UnLCBkYXRhLCBGaWxlc3RhY2tFcnJvclR5cGUuUkVRVUVTVCkpO1xuICAgICAgICB9XG5cbiAgICAgICAgZGVidWcoYFske2lkfV0gQXNzaWduIHBheWxvYWQgZGF0YTogXFxuJU9cXG5gLCBkYXRhKTtcblxuICAgICAgICB0aGlzLnVwZGF0ZVBheWxvYWQoaWQsIGRhdGEpO1xuXG4gICAgICAgIC8vIGlpIGlzIG5vdCBlbmFibGVkIGluIGJhY2tlbmQgc3dpdGNoIGJhY2sgdG8gZGVmYXVsdCB1cGxvYWQgbW9kZVxuICAgICAgICBpZiAoW1VwbG9hZE1vZGUuSU5URUxMSUdFTlQsIFVwbG9hZE1vZGUuRkFMTEJBQ0tdLmluZGV4T2YodGhpcy51cGxvYWRNb2RlKSA+IC0xICYmICghZGF0YS51cGxvYWRfdHlwZSB8fCBkYXRhLnVwbG9hZF90eXBlICE9PSAnaW50ZWxsaWdlbnRfaW5nZXN0aW9uJykpIHtcbiAgICAgICAgICBkZWJ1ZyhgWyR7aWR9XSBJbnRlbGxpZ2VudCBJbmdlc3Rpb24gaXMgbm90IGVuYWJsZWQgb24gYWNjb3VudCwgc3dpdGNoIGJhY2sgdG8gcmVndWxhciB1cGxvYWQgYW5kIGxvY2sgbW9kZSBjaGFuZ2VgKTtcbiAgICAgICAgICB0aGlzLnNldFVwbG9hZE1vZGUoVXBsb2FkTW9kZS5ERUZBVUxULCB0cnVlKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBkYXRhO1xuICAgICAgfSlcbiAgICAgIC5jYXRjaChlcnIgPT4ge1xuICAgICAgICBkZWJ1ZyhgWyR7aWR9XSBTdGFydCByZXF1ZXN0IGVycm9yICVPYCwgZXJyKTtcbiAgICAgICAgdGhpcy5zZXRQYXlsb2FkU3RhdHVzKGlkLCBGaWxlU3RhdGUuRkFJTEVEKTtcblxuICAgICAgICByZXR1cm4gdGhpcy5yZWplY3RVcGxvYWQoJ0Nhbm5vdCB1cGxvYWQgZmlsZS4gU3RhcnQgcmVxdWVzdCBmYWlsZWQnLCBlcnIpO1xuICAgICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogRW5xdWV1ZSBmaWxlIHBhcnRzIHRvIHVwbG9hZFxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcmV0dXJuc1xuICAgKiBAbWVtYmVyb2YgUzNVcGxvYWRlclxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyBzdGFydFBhcnRzUXVldWUoaWQ6IHN0cmluZyk6IFByb21pc2U8YW55PiB7XG4gICAgY29uc3QgcGF5bG9hZCA9IHRoaXMuZ2V0UGF5bG9hZEJ5SWQoaWQpO1xuICAgIGNvbnN0IHBhcnRzID0gcGF5bG9hZC5wYXJ0cztcbiAgICBjb25zdCB3YWl0aW5nTGVuZ3RoID0gcGFydHMubGVuZ3RoO1xuXG4gICAgZGVidWcoYFske2lkfV0gQ3JlYXRlIHVwbG9hZGluZyBxdWV1ZSBmcm9tIGZpbGUuIHBhcnRzIGNvdW50IC0gJWRgLCB3YWl0aW5nTGVuZ3RoKTtcblxuICAgIHJldHVybiBuZXcgUHJvbWlzZShhc3luYyAocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBwYXJ0cy5mb3JFYWNoKHBhcnQgPT5cbiAgICAgICAgdGhpcy5wYXJ0c1F1ZXVlXG4gICAgICAgICAgLmFkZCgoKSA9PiB0aGlzLnN0YXJ0UGFydChpZCwgcGFydC5wYXJ0TnVtYmVyKSlcbiAgICAgICAgICAuY2F0Y2goZSA9PiB7XG4gICAgICAgICAgICB0aGlzLnNldFBheWxvYWRTdGF0dXMoaWQsIEZpbGVTdGF0ZS5GQUlMRUQpO1xuICAgICAgICAgICAgZGVidWcoYFske2lkfV0gRmFpbGVkIHRvIHVwbG9hZCBwYXJ0ICVzYCwgZS5tZXNzYWdlKTtcblxuICAgICAgICAgICAgdGhpcy5wYXJ0c1F1ZXVlLnBhdXNlKCk7XG4gICAgICAgICAgICB0aGlzLnBhcnRzUXVldWUuY2xlYXIoKTtcbiAgICAgICAgICAgIHJldHVybiByZWplY3QoZSk7XG4gICAgICAgICAgfSlcbiAgICAgICk7XG5cbiAgICAgIGRlYnVnKGBbJHtpZH1dIEFsbCB0YXNrcyBmb3IgJXMgZW5xdWV1ZWQuIFN0YXJ0IHByb2Nlc3NpbmcgbWFpbiB1cGxvYWQgcXVldWVgLCBpZCk7XG4gICAgICB0aGlzLmVtaXQoJ3N0YXJ0Jyk7XG4gICAgICB0aGlzLnBhcnRzUXVldWUuc3RhcnQoKTtcblxuICAgICAgcmVzb2x2ZShhd2FpdCB0aGlzLnBhcnRzUXVldWUub25JZGxlKCkpO1xuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIERlY2lkZSBpZiB1cGxvYWQgc2hvdWxkIGJlIG1hZGUgdXNpbmcgaWkgb3IgcmVndWxhciB1cGxvYWRcbiAgICogSXQgYWxsb3dzIGNoYW5nZSB1cGxvYWQgbW9kZSBkdXJpbmcgdXBsb2FkIHF1ZXVlXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBwYXJ0TnVtYmVyXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPGFueT59XG4gICAqIEBtZW1iZXJvZiBTM1VwbG9hZGVyXG4gICAqL1xuICBwcml2YXRlIHN0YXJ0UGFydChpZDogc3RyaW5nLCBwYXJ0TnVtYmVyOiBudW1iZXIpOiBQcm9taXNlPGFueT4ge1xuICAgIGRlYnVnKGBbJHtpZH1dIFN0YXJ0IHByb2Nlc3NpbmcgcGFydCAke3BhcnROdW1iZXJ9IHdpdGggbW9kZSAke3RoaXMudXBsb2FkTW9kZX1gKTtcblxuICAgIGxldCBwYXlsb2FkID0gdGhpcy5nZXRQYXlsb2FkQnlJZChpZCk7XG5cbiAgICBwYXlsb2FkLmZpbGUuc3RhdHVzID0gRmlsZVN0YXRlLlBST0dSRVNTO1xuICAgIHJldHVybiAodGhpcy51cGxvYWRNb2RlICE9PSBVcGxvYWRNb2RlLklOVEVMTElHRU5UID8gdGhpcy51cGxvYWRSZWd1bGFyIDogdGhpcy51cGxvYWRJbnRlbGxpZ2VudCkuYXBwbHkodGhpcywgW2lkLCBwYXJ0TnVtYmVyXSk7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyBwYXJ0IGRhdGEgbmVlZGVkIGZvciB1cGxvYWRcbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtzdHJpbmd9IGlkIC0gaWQgb2YgYSBjdXJyZW50bHkgdXBsb2FkaW5nIGZpbGVcbiAgICogQHBhcmFtIHtGaWxlUGFydH0gcGFydFxuICAgKiBAcmV0dXJuc1xuICAgKiBAbWVtYmVyb2YgUzNVcGxvYWRlclxuICAgKi9cbiAgcHJpdmF0ZSBnZXRTM1BhcnRNZXRhZGF0YShpZDogc3RyaW5nLCBwYXJ0OiBGaWxlUGFydCwgb2Zmc2V0PzogbnVtYmVyKTogUHJvbWlzZTxhbnk+IHtcbiAgICBjb25zdCB1cmwgPSB0aGlzLmdldFVwbG9hZFVybChpZCk7XG5cbiAgICBkZWJ1ZyhgWyR7aWR9XSBHZXQgZGF0YSBmb3IgcGFydCAke3BhcnQucGFydE51bWJlcn0sIHVybCAke3VybH0sIE1kNTogJHtwYXJ0Lm1kNX0sIFNpemU6ICR7cGFydC5zaXplfWApO1xuXG4gICAgY29uc3QgZGF0YSA9IHtcbiAgICAgIC4uLnRoaXMuZ2V0RGVmYXVsdEZpZWxkcyhpZCwgWydhcGlrZXknLCAndXJpJywgJ3JlZ2lvbicsICdzaWduYXR1cmUnLCAncG9saWN5JywgJ3VwbG9hZF9pZCcsICdmaWknXSksXG4gICAgICAvLyBtZXRob2Qgc3BlY2lmaWMga2V5c1xuICAgICAgcGFydDogcGFydC5wYXJ0TnVtYmVyICsgMSxcbiAgICAgIHNpemU6IHBhcnQuc2l6ZSxcbiAgICAgIG9mZnNldCxcbiAgICB9O1xuXG4gICAgaWYgKHRoaXMuaW50ZWdyaXR5Q2hlY2sgJiYgcGFydC5tZDUpIHtcbiAgICAgIGRhdGEubWQ1ID0gcGFydC5tZDU7XG4gICAgfVxuXG4gICAgcmV0dXJuIEZzUmVxdWVzdC5wb3N0KGAke3VybH0vbXVsdGlwYXJ0L3VwbG9hZGAsIGRhdGEsIHtcbiAgICAgIGhlYWRlcnM6IHRoaXMuZ2V0RGVmYXVsdEhlYWRlcnMoaWQpLFxuICAgICAgY2FuY2VsVG9rZW46IHRoaXMuY2FuY2VsVG9rZW4sXG4gICAgICB0aW1lb3V0OiB0aGlzLnRpbWVvdXQsXG4gICAgICByZXRyeTogdGhpcy5yZXRyeUNvbmZpZyxcbiAgICB9KS5jYXRjaChlcnIgPT4ge1xuICAgICAgdGhpcy5zZXRQYXlsb2FkU3RhdHVzKGlkLCBGaWxlU3RhdGUuRkFJTEVEKTtcblxuICAgICAgcmV0dXJuIHRoaXMucmVqZWN0VXBsb2FkKCdDYW5ub3QgZ2V0IHBhcnQgbWV0YWRhdGEnLCBlcnIpO1xuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlZ3VsYXIgbXVsdGlwYXJ0IHJlcXVlc3QgdG8gYW1hem9uXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBwYXJ0TnVtYmVyXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPGFueT59XG4gICAqIEBtZW1iZXJvZiBTM1VwbG9hZGVyXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIHVwbG9hZFJlZ3VsYXIoaWQ6IHN0cmluZywgcGFydE51bWJlcjogbnVtYmVyKTogUHJvbWlzZTxhbnk+IHtcbiAgICBsZXQgcGF5bG9hZCA9IHRoaXMuZ2V0UGF5bG9hZEJ5SWQoaWQpO1xuICAgIGNvbnN0IHBhcnRNZXRhZGF0YSA9IHBheWxvYWQucGFydHNbcGFydE51bWJlcl07XG4gICAgbGV0IHBhcnQgPSBhd2FpdCBwYXlsb2FkLmZpbGUuZ2V0UGFydEJ5TWV0YWRhdGEocGFydE1ldGFkYXRhLCB0aGlzLmludGVncml0eUNoZWNrKTtcblxuICAgIGNvbnN0IHsgZGF0YSwgaGVhZGVycyB9ID0gYXdhaXQgdGhpcy5nZXRTM1BhcnRNZXRhZGF0YShpZCwgcGFydCk7XG4gICAgZGVidWcoYFske2lkfV0gUmVjZWl2ZWQgcGFydCAke3BhcnROdW1iZXJ9IGluZm8gYm9keTogXFxuJU9cXG4gaGVhZGVyczogXFxuJU9cXG5gLCBkYXRhLCBoZWFkZXJzKTtcbiAgICByZXR1cm4gRnNSZXF1ZXN0LnB1dChkYXRhLnVybCwgcGFydC5idWZmZXIsIHtcbiAgICAgIGNhbmNlbFRva2VuOiB0aGlzLmNhbmNlbFRva2VuLFxuICAgICAgdGltZW91dDogdGhpcy50aW1lb3V0LFxuICAgICAgaGVhZGVyczogZGF0YS5oZWFkZXJzLFxuICAgICAgZmlsZXN0YWNrSGVhZGVyczogZmFsc2UsXG4gICAgICAvLyBmb3Igbm93IHdlIGNhbnQgdGVzdCBwcm9ncmVzcyBjYWxsYmFjayBmcm9tIHVwbG9hZFxuICAgICAgLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cbiAgICAgIG9uUHJvZ3Jlc3M6IChwcjogUHJvZ3Jlc3NFdmVudCkgPT4gdGhpcy5vblByb2dyZXNzVXBkYXRlKGlkLCBwYXJ0TnVtYmVyLCBwci5sb2FkZWQpLFxuICAgICAgcmV0cnk6IHRoaXMucmV0cnlDb25maWcgJiYgdGhpcy51cGxvYWRNb2RlICE9PSBVcGxvYWRNb2RlLkZBTExCQUNLID8gdGhpcy5yZXRyeUNvbmZpZyA6IHVuZGVmaW5lZCxcbiAgICB9KVxuICAgIC50aGVuKHJlcyA9PiB7XG4gICAgICBpZiAocmVzLmhlYWRlcnMuZXRhZykge1xuICAgICAgICB0aGlzLnNldFBhcnRFVGFnKGlkLCBwYXJ0TnVtYmVyLCByZXMuaGVhZGVycy5ldGFnKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIHJlbGVhc2UgbWVtb3J5XG4gICAgICAgIHBhcnQgPSBudWxsO1xuICAgICAgICB0aHJvdyBuZXcgRmlsZXN0YWNrRXJyb3IoJ0Nhbm5vdCB1cGxvYWQgZmlsZSwgY2hlY2sgUzMgYnVja2V0IHNldHRpbmdzJywgJ0V0YWcgaGVhZGVyIGlzIG5vdCBleHBvc2VkIGluIENPUlMgc2V0dGluZ3MnLCBGaWxlc3RhY2tFcnJvclR5cGUuUkVRVUVTVCk7XG4gICAgICB9XG5cbiAgICAgIGRlYnVnKGBbJHtpZH1dIFMzIFVwbG9hZCByZXNwb25zZSBoZWFkZXJzIGZvciAke3BhcnROdW1iZXJ9OiBcXG4lT1xcbmAsIHJlcy5oZWFkZXJzKTtcblxuICAgICAgdGhpcy5vblByb2dyZXNzVXBkYXRlKGlkLCBwYXJ0TnVtYmVyLCBwYXJ0LnNpemUpO1xuXG4gICAgICAvLyByZWxlYXNlIG1lbW9yeVxuICAgICAgcGFydCA9IG51bGw7XG5cbiAgICAgIHJldHVybiByZXM7XG4gICAgfSlcbiAgICAuY2F0Y2goZXJyID0+IHtcbiAgICAgIGNvbnN0IHJlc3AgPSBlcnIgJiYgZXJyLnJlc3BvbnNlID8gZXJyLnJlc3BvbnNlIDogbnVsbDtcblxuICAgICAgLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cbiAgICAgIGlmIChyZXNwICYmIHJlc3Auc3RhdHVzID09PSA0MDMpIHtcbiAgICAgICAgaWYgKHJlc3AuZGF0YSAmJiByZXNwLmRhdGEuRXJyb3IgJiYgcmVzcC5kYXRhLkVycm9yLmNvZGUpIHtcbiAgICAgICAgICBsZXQgY29kZSA9IHJlc3AuZGF0YS5FcnJvci5jb2RlO1xuXG4gICAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkoY29kZSkpIHtcbiAgICAgICAgICAgIGNvZGUgPSBjb2RlLnBvcCgpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIHN3aXRjaCAoY29kZSkge1xuICAgICAgICAgICAgY2FzZSAnUmVxdWVzdFRpbWVUb29Ta2V3ZWQnOlxuICAgICAgICAgICAgICByZXR1cm4gdGhpcy5zdGFydFBhcnQoaWQsIHBhcnROdW1iZXIpO1xuICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KG5ldyBGaWxlc3RhY2tFcnJvcignQ2Fubm90IHVwbG9hZCBmaWxlJywgcmVzcC5kYXRhLkVycm9yLCBGaWxlc3RhY2tFcnJvclR5cGUuUkVRVUVTVCkpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICAvLyByZWxlYXNlIG1lbW9yeVxuICAgICAgcGFydCA9IG51bGw7XG5cbiAgICAgIGlmIChlcnIgaW5zdGFuY2VvZiBGaWxlc3RhY2tFcnJvcikge1xuICAgICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QoZXJyKTtcbiAgICAgIH1cbiAgICAgIC8vIHJlc2V0IHVwbG9hZCBwcm9ncmVzcyBvbiBmYWlsZWQgcGFydFxuICAgICAgdGhpcy5vblByb2dyZXNzVXBkYXRlKGlkLCBwYXJ0TnVtYmVyLCAwKTtcblxuICAgICAgLy8gaWYgZmFsbGJhY2ssIHNldCB1cGxvYWQgbW9kZSB0byBpbnRlbGxpZ2VudCBhbmQgcmVzdGFydCBjdXJyZW50IHBhcnRcbiAgICAgIGlmICgodGhpcy51cGxvYWRNb2RlID09PSBVcGxvYWRNb2RlLkZBTExCQUNLICYmICF0aGlzLmlzTW9kZUxvY2tlZCkgfHwgdGhpcy51cGxvYWRNb2RlID09PSBVcGxvYWRNb2RlLklOVEVMTElHRU5UKSB7XG4gICAgICAgIGRlYnVnKGBbJHtpZH1dIFJlZ3VsYXIgdXBsb2FkIGZhaWxlZC4gU3dpdGNoaW5nIHRvIGludGVsbGlnZW50IGluZ2VzdGlvbiBtb2RlYCk7XG4gICAgICAgIHRoaXMuc2V0VXBsb2FkTW9kZShVcGxvYWRNb2RlLklOVEVMTElHRU5UKTtcbiAgICAgICAgLy8gcmVzdGFydCBwYXJ0XG4gICAgICAgIHJldHVybiB0aGlzLnN0YXJ0UGFydChpZCwgcGFydE51bWJlcik7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiB0aGlzLnJlamVjdFVwbG9hZCgnQ2Fubm90IHVwbG9hZCBmaWxlIHBhcnQnLCBlcnIpO1xuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFVwbG9hZCBmaWxlIHVzaW5nIGludGVsbGlnZW50IG1lY2hhbmlzbVxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gaWRcbiAgICogQHBhcmFtIHtudW1iZXJ9IHBhcnROdW1iZXJcbiAgICogQHJldHVybnMge1Byb21pc2U8YW55Pn1cbiAgICogQG1lbWJlcm9mIFMzVXBsb2FkZXJcbiAgICovXG4gIHByaXZhdGUgYXN5bmMgdXBsb2FkSW50ZWxsaWdlbnQoaWQ6IHN0cmluZywgcGFydE51bWJlcjogbnVtYmVyKTogUHJvbWlzZTxhbnk+IHtcbiAgICByZXR1cm4gdGhpcy51cGxvYWROZXh0Q2h1bmsoaWQsIHBhcnROdW1iZXIpLnRoZW4oKCkgPT4gdGhpcy5jb21taXRQYXJ0KGlkLCBwYXJ0TnVtYmVyKSk7XG4gIH1cblxuICAvKipcbiAgICogUmVjdXJzaXZlbHkgdXBsb2FkIGZpbGUgaW4gY2h1bmsgbW9kZSAoaW50ZWxsaWdlbnQgaW5nZXNzaW9uKVxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gaWRcbiAgICogQHBhcmFtIHtudW1iZXJ9IHBhcnROdW1iZXJcbiAgICogQHBhcmFtIHtudW1iZXJ9IGNodW5rU2l6ZVxuICAgKiBAcmV0dXJuc1xuICAgKiBAbWVtYmVyb2YgUzNVcGxvYWRlclxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyB1cGxvYWROZXh0Q2h1bmsoaWQ6IHN0cmluZywgcGFydE51bWJlcjogbnVtYmVyLCBjaHVua1NpemU6IG51bWJlciA9IHRoaXMuaW50ZWxsaWdlbnRDaHVua1NpemUpIHtcbiAgICBjb25zdCBwYXlsb2FkID0gdGhpcy5nZXRQYXlsb2FkQnlJZChpZCk7XG4gICAgbGV0IHBhcnQgPSBwYXlsb2FkLnBhcnRzW3BhcnROdW1iZXJdO1xuICAgIGNodW5rU2l6ZSA9IHBhcnQuc2l6ZSAtIHBhcnQub2Zmc2V0O1xuXG4gICAgbGV0IGNodW5rID0gYXdhaXQgcGF5bG9hZC5maWxlLmdldENodW5rQnlNZXRhZGF0YShwYXJ0LCBwYXJ0Lm9mZnNldCwgY2h1bmtTaXplLCB0aGlzLmludGVncml0eUNoZWNrKTtcblxuICAgIGRlYnVnKFxuICAgICAgYFske2lkfV0gUGFydE51bTogJHtwYXJ0TnVtYmVyfSwgUGFydFNpemU6ICR7cGFydC5zaXplfSwgU3RhcnRCeXRlOiAke3BhcnQuc3RhcnRCeXRlfSwgT2Zmc2V0OiAke3BhcnQub2Zmc2V0fSwgQ2h1bmtTaXplOiAke2NodW5rLnNpemV9LFxuICAgICAgIExlZnQ6ICR7cGFydC5zaXplIC0gcGFydC5vZmZzZXQgLSBjaHVuay5zaXplfWBcbiAgICApO1xuXG4gICAgLy8gY2F0Y2ggZXJyb3IgZm9yIGRlYnVnIHB1cnBvc2VzXG4gICAgY29uc3QgeyBkYXRhIH0gPSBhd2FpdCB0aGlzLmdldFMzUGFydE1ldGFkYXRhKGlkLCBjaHVuaywgcGFydC5vZmZzZXQpLmNhdGNoKGVyciA9PiB7XG4gICAgICBkZWJ1ZyhgWyR7aWR9XSBHZXR0aW5nIGNodW5rIGRhdGEgZm9yIGlpIGZhaWxlZCAlTywgQ2h1bmsgc2l6ZTogJHtjaHVua1NpemV9LCBvZmZzZXQgJHtwYXJ0Lm9mZnNldH0sIHBhcnQgJHtwYXJ0TnVtYmVyfWAsIGVycik7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QoZXJyKTtcbiAgICB9KTtcblxuICAgIHJldHVybiBGc1JlcXVlc3QucHV0KGRhdGEudXJsLCBjaHVuay5idWZmZXIsIHtcbiAgICAgIGNhbmNlbFRva2VuOiB0aGlzLmNhbmNlbFRva2VuLFxuICAgICAgdGltZW91dDogdGhpcy50aW1lb3V0LFxuICAgICAgaGVhZGVyczogZGF0YS5oZWFkZXJzLFxuICAgICAgZmlsZXN0YWNrSGVhZGVyczogZmFsc2UsXG4gICAgICAvLyBmb3Igbm93IHdlIGNhbnQgdGVzdCBwcm9ncmVzcyBjYWxsYmFjayBmcm9tIHVwbG9hZFxuICAgICAgLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cbiAgICAgIG9uUHJvZ3Jlc3M6IChwcjogUHJvZ3Jlc3NFdmVudCkgPT4gcGFydCA/IHRoaXMub25Qcm9ncmVzc1VwZGF0ZShpZCwgcGFydE51bWJlciwgcGFydC5vZmZzZXQgKyBwci5sb2FkZWQpIDogbnVsbCxcbiAgICB9KVxuICAgICAgLnRoZW4ocmVzID0+IHtcbiAgICAgICAgdGhpcy5vblByb2dyZXNzVXBkYXRlKGlkLCBwYXJ0TnVtYmVyLCBwYXJ0Lm9mZnNldCArIGNodW5rLnNpemUpO1xuICAgICAgICBjb25zdCBuZXdPZmZzZXQgPSBNYXRoLm1pbihwYXJ0Lm9mZnNldCArIGNodW5rU2l6ZSwgcGFydC5zaXplKTtcbiAgICAgICAgZGVidWcoYFske2lkfV0gUzMgQ2h1bmsgdXBsb2FkZWQhIG9mZnNldDogJHtwYXJ0Lm9mZnNldH0sIHBhcnQgJHtwYXJ0TnVtYmVyfSEgcmVzcG9uc2UgaGVhZGVycyBmb3IgJHtwYXJ0TnVtYmVyfTogXFxuJU9cXG5gLCByZXMuaGVhZGVycyk7XG4gICAgICAgIHRoaXMuc2V0UGFydERhdGEoaWQsIHBhcnROdW1iZXIsICdvZmZzZXQnLCBuZXdPZmZzZXQpO1xuXG4gICAgICAgIC8vIGlmIGFsbCBjaHVua3Mgd2FzIHVwbG9hZGVkIHRoZW4gcmV0dXJuIHJlc29sdmVcbiAgICAgICAgaWYgKG5ld09mZnNldCA9PT0gcGFydC5zaXplKSB7XG4gICAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShyZXMpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gcmVsZWFzZSBtZW1vcnlcbiAgICAgICAgcGFydCA9IG51bGw7XG4gICAgICAgIGNodW5rID0gbnVsbDtcblxuICAgICAgICByZXR1cm4gdGhpcy51cGxvYWROZXh0Q2h1bmsoaWQsIHBhcnROdW1iZXIsIGNodW5rU2l6ZSk7XG4gICAgICB9KVxuICAgICAgLmNhdGNoKGVyciA9PiB7XG4gICAgICAgIGNvbnN0IHJlc3AgPSBlcnIgJiYgZXJyLnJlc3BvbnNlID8gZXJyLnJlc3BvbnNlIDogbnVsbDtcbiAgICAgICAgLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cbiAgICAgICAgaWYgKHJlc3AgJiYgcmVzcC5zdGF0dXMgPT09IDQwMykge1xuICAgICAgICAgIGlmIChyZXNwLmRhdGEgJiYgcmVzcC5kYXRhLkVycm9yICYmIHJlc3AuZGF0YS5FcnJvci5jb2RlKSB7XG4gICAgICAgICAgICBsZXQgY29kZSA9IHJlc3AuZGF0YS5FcnJvci5jb2RlO1xuXG4gICAgICAgICAgICBpZiAoQXJyYXkuaXNBcnJheShjb2RlKSkge1xuICAgICAgICAgICAgICBjb2RlID0gY29kZS5wb3AoKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgc3dpdGNoIChjb2RlKSB7XG4gICAgICAgICAgICAgIGNhc2UgJ1JlcXVlc3RUaW1lVG9vU2tld2VkJzpcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5zdGFydFBhcnQoaWQsIHBhcnROdW1iZXIpO1xuICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdChuZXcgRmlsZXN0YWNrRXJyb3IoJ0Nhbm5vdCB1cGxvYWQgZmlsZScsIHJlc3AuZGF0YS5FcnJvciwgRmlsZXN0YWNrRXJyb3JUeXBlLlJFUVVFU1QpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyByZXNldCBwcm9ncmVzcyBvbiBmYWlsZWQgdXBsb2FkXG4gICAgICAgIHRoaXMub25Qcm9ncmVzc1VwZGF0ZShpZCwgcGFydE51bWJlciwgcGFydC5vZmZzZXQpO1xuICAgICAgICBjb25zdCBuZXh0Q2h1bmtTaXplID0gTWF0aC5jZWlsKGNodW5rU2l6ZSAvIDIpO1xuXG4gICAgICAgIGlmIChuZXh0Q2h1bmtTaXplIDwgTUlOX0NIVU5LX1NJWkUpIHtcbiAgICAgICAgICBkZWJ1ZyhgWyR7aWR9XSBNaW5pbWFsIGNodW5rIHNpemUgbGltaXQuIFVwbG9hZCBmaWxlIGZhaWxlZCFgKTtcbiAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QobmV3IEZpbGVzdGFja0Vycm9yKCdNaW4gY2h1bmsgc2l6ZSByZWFjaGVkJywgZXJyLmRhdGEsIEZpbGVzdGFja0Vycm9yVHlwZS5SRVFVRVNUKSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoc2hvdWxkUmV0cnkoZXJyKSkge1xuICAgICAgICAgIGRlYnVnKGBbJHtpZH1dIFJlcXVlc3QgbmV0d29yayBlcnJvci4gUmV0cnkgd2l0aCBuZXcgY2h1bmsgc2l6ZTogJHtuZXh0Q2h1bmtTaXplfWApO1xuICAgICAgICAgIHJldHVybiB0aGlzLnVwbG9hZE5leHRDaHVuayhpZCwgcGFydE51bWJlciwgbmV4dENodW5rU2l6ZSk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyByZWxlYXNlIG1lbW9yeVxuICAgICAgICBwYXJ0ID0gbnVsbDtcbiAgICAgICAgY2h1bmsgPSBudWxsO1xuXG4gICAgICAgIHJldHVybiB0aGlzLnJlamVjdFVwbG9hZCgnQ2Fubm90IHVwbG9hZCBmaWxlIHBhcnQgKEZJSSknLCBlcnIpO1xuICAgICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogQ29tbWl0IGFmdGVyIHVwbG9hZCBhbGwgY2h1bmtzIG9mIHRoZSBwYXJ0IGluIGlpIG1vZGVcbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtzdHJpbmd9IGlkXG4gICAqIEBwYXJhbSB7RmlsZVBhcnR9IHBhcnRcbiAgICogQHJldHVybnNcbiAgICogQG1lbWJlcm9mIFMzVXBsb2FkZXJcbiAgICovXG4gIHByaXZhdGUgY29tbWl0UGFydChpZDogc3RyaW5nLCBwYXJ0TnVtYmVyOiBudW1iZXIpIHtcbiAgICBjb25zdCBwYXlsb2FkID0gdGhpcy5nZXRQYXlsb2FkQnlJZChpZCk7XG4gICAgY29uc3QgcGFydCA9IHBheWxvYWQucGFydHNbcGFydE51bWJlcl07XG5cbiAgICByZXR1cm4gRnNSZXF1ZXN0LnBvc3QoXG4gICAgICBgJHt0aGlzLmdldFVwbG9hZFVybChpZCl9L211bHRpcGFydC9jb21taXRgLFxuICAgICAge1xuICAgICAgICAuLi50aGlzLmdldERlZmF1bHRGaWVsZHMoaWQsIFsnYXBpa2V5JywgJ3JlZ2lvbicsICd1cGxvYWRfaWQnLCAncG9saWN5JywgJ3NpZ25hdHVyZScsICd1cmknXSksXG4gICAgICAgIHNpemU6IHBheWxvYWQuZmlsZS5zaXplLFxuICAgICAgICBwYXJ0OiBwYXJ0LnBhcnROdW1iZXIgKyAxLFxuICAgICAgfSxcbiAgICAgIHtcbiAgICAgICAgY2FuY2VsVG9rZW46IHRoaXMuY2FuY2VsVG9rZW4sXG4gICAgICAgIHRpbWVvdXQ6IHRoaXMudGltZW91dCxcbiAgICAgICAgaGVhZGVyczogdGhpcy5nZXREZWZhdWx0SGVhZGVycyhpZCksXG4gICAgICAgIHJldHJ5OiB0aGlzLnJldHJ5Q29uZmlnLFxuICAgICAgfVxuICAgIClcbiAgICAgIC50aGVuKChyZXM6IEZzUmVzcG9uc2UpID0+IHtcbiAgICAgICAgZGVidWcoYFske2lkfV0gQ29tbWl0IFBhcnQgbnVtYmVyICR7cGFydC5wYXJ0TnVtYmVyfS4gUmVzcG9uc2U6ICVPYCwgcmVzLmRhdGEpO1xuXG4gICAgICAgIHJldHVybiByZXM7XG4gICAgICB9KVxuICAgICAgLmNhdGNoKGVyciA9PiB7XG4gICAgICAgIHJldHVybiB0aGlzLnJlamVjdFVwbG9hZCgnQ2Fubm90IGNvbW1pdCBmaWxlIHBhcnQgbWV0YWRhdGEnLCBlcnIpO1xuICAgICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogQ29tcGxldGUgcmVxdWVzdCB0byBtZXJnZSBhbGwgcGFydHMgYW5kIGdldCBmaWxlIGhhbmRsZSBldGNcbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHJldHVybnNcbiAgICogQG1lbWJlcm9mIFMzVXBsb2FkZXJcbiAgICovXG4gIHByaXZhdGUgY29tcGxldGVSZXF1ZXN0KGlkOiBzdHJpbmcpOiBQcm9taXNlPGFueT4ge1xuICAgIGNvbnN0IHBheWxvYWQgPSB0aGlzLmdldFBheWxvYWRCeUlkKGlkKTtcbiAgICBsZXQgcGFydHMgPSBbXTtcblxuICAgIGRlYnVnKGBbJHtpZH1dIFJ1biBjb21wbGV0ZSByZXF1ZXN0YCk7XG5cbiAgICBjb25zdCBwYXJ0c0hhbmRsZSA9IHBheWxvYWQucGFydHM7XG4gICAgY29uc3QgcGFydExlbiA9IHBhcnRzSGFuZGxlLmxlbmd0aDtcblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgcGFydExlbjsgaSsrKSB7XG4gICAgICBpZiAocGFydHNIYW5kbGVbaV0uZXRhZykge1xuICAgICAgICBwYXJ0cy5wdXNoKHsgcGFydF9udW1iZXI6IGkgKyAxLCBldGFnOiBwYXJ0c0hhbmRsZVtpXS5ldGFnIH0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIGRlYnVnKGBbJHtpZH1dIEV0YWdzICVPYCwgcGFydHMpO1xuXG4gICAgcmV0dXJuIEZzUmVxdWVzdC5wb3N0KFxuICAgICAgYCR7dGhpcy5nZXRVcGxvYWRVcmwoaWQpfS9tdWx0aXBhcnQvY29tcGxldGVgLFxuICAgICAge1xuICAgICAgICAuLi50aGlzLmdldERlZmF1bHRGaWVsZHMoaWQsIFsnYXBpa2V5JywgJ3BvbGljeScsICdzaWduYXR1cmUnLCAndXJpJywgJ3JlZ2lvbicsICd1cGxvYWRfaWQnLCAnZmlpJywgJ2FsdCddLCB0cnVlKSxcbiAgICAgICAgLy8gbWV0aG9kIHNwZWNpZmljIGtleXNcbiAgICAgICAgZmlsZW5hbWU6IHBheWxvYWQuZmlsZS5uYW1lLFxuICAgICAgICBtaW1ldHlwZTogcGF5bG9hZC5maWxlLnR5cGUsXG4gICAgICAgIHNpemU6IHBheWxvYWQuZmlsZS5zaXplLFxuICAgICAgICB1cGxvYWRfdGFnczogdGhpcy51cGxvYWRUYWdzICYmIE9iamVjdC5rZXlzKHRoaXMudXBsb2FkVGFncykubGVuZ3RoID8gdGhpcy51cGxvYWRUYWdzIDogdW5kZWZpbmVkLFxuICAgICAgICBwYXJ0czogcGFydHMubGVuZ3RoID8gcGFydHMgOiB1bmRlZmluZWQsXG4gICAgICB9LFxuICAgICAge1xuICAgICAgICB0aW1lb3V0OiB0aGlzLnRpbWVvdXQsXG4gICAgICAgIGNhbmNlbFRva2VuOiB0aGlzLmNhbmNlbFRva2VuLFxuICAgICAgICBoZWFkZXJzOiB0aGlzLmdldERlZmF1bHRIZWFkZXJzKGlkKSxcbiAgICAgICAgcmV0cnk6IHRoaXMucmV0cnlDb25maWcsXG4gICAgICB9XG4gICAgKVxuICAgICAgLnRoZW4ocmVzID0+IHtcbiAgICAgICAgLy8gaWYgcGFydHMgaGFzbnQgYmVlbiBtZXJnZWQsIHJldHJ5IGNvbXBsZXRlIHJlcXVlc3QgYWdhaW5cbiAgICAgICAgaWYgKHJlcy5zdGF0dXMgPT09IDIwMikge1xuICAgICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBzZXRUaW1lb3V0KFxuICAgICAgICAgICAgICAoKSA9PlxuICAgICAgICAgICAgICAgIHRoaXMuY29tcGxldGVSZXF1ZXN0KGlkKVxuICAgICAgICAgICAgICAgICAgLnRoZW4ocmVzb2x2ZSlcbiAgICAgICAgICAgICAgICAgIC5jYXRjaChyZWplY3QpLFxuICAgICAgICAgICAgICBDT01QTEVURV9USU1FT1VUXG4gICAgICAgICAgICApO1xuICAgICAgICAgIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gdXBkYXRlIGZpbGUgb2JqZWN0XG4gICAgICAgIGxldCBmaWxlID0gdGhpcy5nZXRQYXlsb2FkQnlJZChpZCkuZmlsZTtcblxuICAgICAgICBmaWxlLmhhbmRsZSA9IHJlcy5kYXRhLmhhbmRsZTtcbiAgICAgICAgZmlsZS51cmwgPSByZXMuZGF0YS51cmw7XG4gICAgICAgIGZpbGUuY29udGFpbmVyID0gcmVzLmRhdGEuY29udGFpbmVyO1xuICAgICAgICBmaWxlLmtleSA9IHJlcy5kYXRhLmtleTtcbiAgICAgICAgZmlsZS51cGxvYWRUYWdzID0gcmVzLmRhdGEudXBsb2FkX3RhZ3M7XG4gICAgICAgIGZpbGUud29ya2Zsb3dzID0gcmVzLmRhdGEud29ya2Zsb3dzO1xuICAgICAgICBmaWxlLnN0YXR1cyA9IHJlcy5kYXRhLnN0YXR1cztcblxuICAgICAgICByZXR1cm4gZmlsZTtcbiAgICAgIH0pXG4gICAgICAuY2F0Y2goZXJyID0+IHtcbiAgICAgICAgdGhpcy5zZXRQYXlsb2FkU3RhdHVzKGlkLCBGaWxlU3RhdGUuRkFJTEVEKTtcblxuICAgICAgICByZXR1cm4gdGhpcy5yZWplY3RVcGxvYWQoJ0Nhbm5vdCBjb21wbGV0ZSBmaWxlJywgZXJyKTtcbiAgICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFVVcGdyYWRlIHVwbG9hZCBwcm9ncmVzcyBhbmQgcnVuIHByb2dyZXNzIGV2ZW50XG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBpZFxuICAgKiBAcGFyYW0ge251bWJlcn0gcGFydE51bWJlclxuICAgKiBAcGFyYW0ge251bWJlcn0gbG9hZGVkXG4gICAqIEBtZW1iZXJvZiBTM1VwbG9hZGVyXG4gICAqL1xuICBwcml2YXRlIG9uUHJvZ3Jlc3NVcGRhdGUoaWQ6IHN0cmluZywgcGFydE51bWJlcjogbnVtYmVyLCBsb2FkZWQ6IG51bWJlcikge1xuICAgIHRoaXMuc2V0UGFydERhdGEoaWQsIHBhcnROdW1iZXIsICdwcm9ncmVzcycsIGxvYWRlZCk7XG4gICAgdGhpcy5lbWl0UHJvZ3Jlc3MoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBFbWl0cyBub3JtYWxpemVkIHByb2dyZXNzIGV2ZW50XG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBtZW1iZXJvZiBTM1VwbG9hZGVyXG4gICAqL1xuICBwcml2YXRlIGVtaXRQcm9ncmVzcygpIHtcbiAgICBsZXQgdG90YWxTaXplID0gMDtcbiAgICBsZXQgdG90YWxCeXRlcyA9IDA7XG5cbiAgICBsZXQgZmlsZXNQcm9ncmVzcyA9IHt9O1xuICAgIGZvciAobGV0IGkgaW4gdGhpcy5wYXlsb2Fkcykge1xuICAgICAgY29uc3QgcGF5bG9hZCA9IHRoaXMucGF5bG9hZHNbaV07XG4gICAgICAvLyBvbWl0IGFsbCBmYWlsZWQgZmlsZXMgaW4gcHJvZ3Jlc3MgZXZlbnRcbiAgICAgIC8vIHRoaXMgc2hvdWxkbid0IGhhcHBlbmQgYmVjYXVzZSBvZiBwcm9taXNlcyByZWplY3Rpb24gaW4gZXhlY3V0ZS4gTGVmdCB0byBiZSBzdXJlXG4gICAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dCAqL1xuICAgICAgaWYgKHBheWxvYWQuZmlsZS5zdGF0dXMgPT09IEZpbGVTdGF0ZS5GQUlMRUQpIHtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHRvdGFsUGFydHMgPSBwYXlsb2FkLnBhcnRzLm1hcChwID0+IHAucHJvZ3Jlc3MgfHwgMCkucmVkdWNlKChhLCBiKSA9PiBhICsgYiwgMCk7XG5cbiAgICAgIHRvdGFsQnl0ZXMgPSB0b3RhbEJ5dGVzICsgdG90YWxQYXJ0cztcblxuICAgICAgZmlsZXNQcm9ncmVzc1tpXSA9IHtcbiAgICAgICAgdG90YWxCeXRlczogdG90YWxQYXJ0cyxcbiAgICAgICAgdG90YWxQZXJjZW50OiBNYXRoLnJvdW5kKCh0b3RhbFBhcnRzICogMTAwKSAvIHBheWxvYWQuZmlsZS5zaXplKSB8fCAwLFxuICAgICAgfTtcblxuICAgICAgdG90YWxTaXplID0gdG90YWxTaXplICsgcGF5bG9hZC5maWxlLnNpemU7XG4gICAgfVxuXG4gICAgY29uc3QgcmVzID0ge1xuICAgICAgdG90YWxCeXRlczogdG90YWxCeXRlcyB8fCAwLFxuICAgICAgdG90YWxQZXJjZW50OiBNYXRoLnJvdW5kKCh0b3RhbEJ5dGVzICogMTAwKSAvIHRvdGFsU2l6ZSkgfHwgMCxcbiAgICAgIGZpbGVzOiBmaWxlc1Byb2dyZXNzLFxuICAgIH07XG5cbiAgICBkZWJ1ZyhgVXBsb2FkIHByb2dyZXNzICVPYCwgcmVzKTtcbiAgICB0aGlzLmVtaXQoJ3Byb2dyZXNzJywgcmVzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBcHBseSBwcm92aWRlZCBkYXRhIHRvIGdpdmVuIHBheWxvYWRcbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtzdHJpbmd9IGlkXG4gICAqIEBwYXJhbSB7Kn0gZGF0YVxuICAgKiBAbWVtYmVyb2YgUzNVcGxvYWRlclxuICAgKi9cbiAgcHJpdmF0ZSB1cGRhdGVQYXlsb2FkKGlkOiBzdHJpbmcsIGRhdGE6IGFueSkge1xuICAgIHRoaXMucGF5bG9hZHNbaWRdID0ge1xuICAgICAgLi4udGhpcy5wYXlsb2Fkc1tpZF0sXG4gICAgICAuLi5kYXRhLFxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogU2V0cyBldGFnIGZvciBwYXJ0XG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBwYXJ0TnVtYmVyXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBldGFnXG4gICAqIEBtZW1iZXJvZiBTM1VwbG9hZGVyXG4gICAqL1xuICBwcml2YXRlIHNldFBhcnRFVGFnKGlkOiBzdHJpbmcsIHBhcnROdW1iZXI6IG51bWJlciwgZXRhZzogc3RyaW5nKSB7XG4gICAgZGVidWcoYFske2lkfV0gU2V0ICR7ZXRhZ30gZXRhZyBmb3IgcGFydCAke3BhcnROdW1iZXJ9YCk7XG4gICAgdGhpcy5nZXRQYXlsb2FkQnlJZChpZCkucGFydHNbcGFydE51bWJlcl0uZXRhZyA9IGV0YWc7XG4gIH1cblxuICAvKipcbiAgICogU2V0cyBwYXJ0IHZhbHVlIGZvciBhIGtleVxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge251bWJlcn0gcGFydE51bWJlclxuICAgKiBAcGFyYW0ge3N0cmluZ30gZXRhZ1xuICAgKiBAbWVtYmVyb2YgUzNVcGxvYWRlclxuICAgKi9cbiAgcHJpdmF0ZSBzZXRQYXJ0RGF0YShpZDogc3RyaW5nLCBwYXJ0TnVtYmVyOiBudW1iZXIsIGtleTogc3RyaW5nLCB2YWx1ZTogYW55KSB7XG4gICAgZGVidWcoYFske2lkfV0gU2V0ICR7a2V5fSA9ICR7dmFsdWV9IGZvciBwYXJ0ICR7cGFydE51bWJlcn1gKTtcblxuICAgIGNvbnN0IHBheWxvYWQgPSB0aGlzLmdldFBheWxvYWRCeUlkKGlkKTtcblxuICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXG4gICAgaWYgKCFwYXlsb2FkKSB7XG4gICAgICBkZWJ1ZyhgWyR7aWR9XSBDYW5ub3Qgc2V0ICR7a2V5fSA9ICR7dmFsdWV9IGZvciBwYXJ0ICR7cGFydE51bWJlcn1gKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBwYXlsb2FkLnBhcnRzW3BhcnROdW1iZXJdW2tleV0gPSB2YWx1ZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTZXQgcGF5bG9hZCBmaWxlIHN0YXRlXG4gICAqXG4gICAqIEBwYXJhbSBpZFxuICAgKiBAcGFyYW0gc3RhdHVzXG4gICAqL1xuICBwcml2YXRlIHNldFBheWxvYWRTdGF0dXMoaWQ6IHN0cmluZywgc3RhdHVzOiBGaWxlU3RhdGUpIHtcbiAgICBkZWJ1ZyhgWyR7aWR9XSBTZXQgcGF5bG9hZCBzdGF0dXMgdG8gJHtzdGF0dXN9YCk7XG4gICAgLyogaXN0YW5idWwgaWdub3JlIG5leHQ6IGFkZGl0aW9uYWwgY2hlY2sgaW4gY2FzZSBpZiBmaWxlIHdpbGwgYmUgZGVsZXRlZCBiZWZvcmUgc2V0dGluZyBzdGF0dXMgKi9cbiAgICBpZiAoIXRoaXMucGF5bG9hZHNbaWRdKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdGhpcy5wYXlsb2Fkc1tpZF0uZmlsZS5zdGF0dXMgPSBzdGF0dXM7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyBlcnJvciBkZXRhaWxzIGlmIHJlc3BvbnNlIGV4aXN0c1xuICAgKlxuICAgKiBAcGFyYW0gZXJyXG4gICAqL1xuICBwcml2YXRlIHBhcnNlRXJyb3IoZXJyOiBGc1JlcXVlc3RFcnJvcikge1xuICAgIGlmICghZXJyLnJlc3BvbnNlKSB7XG4gICAgICByZXR1cm4ge307XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIGNvZGU6IGVyci5yZXNwb25zZS5zdGF0dXMsXG4gICAgICBkYXRhOiBlcnIucmVzcG9uc2UuZGF0YSxcbiAgICAgIGhlYWRlcnM6IGVyci5yZXNwb25zZS5oZWFkZXJzLFxuICAgIH07XG4gIH1cblxuICBwcml2YXRlIHJlamVjdFVwbG9hZChtZXNzYWdlOiBzdHJpbmcsIGVycjogRnNSZXF1ZXN0RXJyb3IpIHtcbiAgICBpZiAoZXJyIGluc3RhbmNlb2YgRnNSZXF1ZXN0RXJyb3IgJiYgZXJyLmNvZGUgPT09IEZzUmVxdWVzdEVycm9yQ29kZS5BQk9SVEVEKSB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QobmV3IEZpbGVzdGFja0Vycm9yKG1lc3NhZ2UsIHsgcmVhc29uOiBlcnIubWVzc2FnZSB9LCBGaWxlc3RhY2tFcnJvclR5cGUuQUJPUlRFRCkpO1xuICAgIH1cbiAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QobmV3IEZpbGVzdGFja0Vycm9yKG1lc3NhZ2UsIHRoaXMucGFyc2VFcnJvcihlcnIpLCBGaWxlc3RhY2tFcnJvclR5cGUuUkVRVUVTVCkpO1xuICB9XG59XG4iXX0=