filestack-js
Version:
Official JavaScript library for Filestack
764 lines • 100 kB
JavaScript
import { __assign, __awaiter, __extends, __generator } from "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.
*/
import Debug from 'debug';
import PQueue from 'p-queue';
import { FilestackError, FilestackErrorType } from './../../../../filestack_error';
import { FsCancelToken, FsRequest, FsRequestError, FsRequestErrorCode } from './../../../request';
import { shouldRetry } from './../../../request/helpers';
import { filterObject, uniqueId, uniqueTime } from './../../../utils';
import { DEFAULT_STORE_LOCATION, INTELLIGENT_CHUNK_SIZE, MIN_CHUNK_SIZE, UploaderAbstract } from './abstract';
var debug = Debug('fs:upload:s3');
var COMPLETE_TIMEOUT = 1000 * 1;
var S3Uploader = /** @class */ (function (_super) {
__extends(S3Uploader, _super);
function S3Uploader(storeOptions, concurrency) {
var _this = _super.call(this, storeOptions, concurrency) || this;
_this.payloads = {};
_this.partsQueue = new PQueue({
autoStart: false,
concurrency: _this.concurrency,
});
_this.cancelToken = new 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 __awaiter(this, void 0, void 0, function () {
var tasks;
var _this = this;
return __generator(this, function (_a) {
tasks = Object.keys(this.payloads).map(function (id) {
return new Promise(function (resolve) { return __awaiter(_this, void 0, void 0, function () {
var e_1, file;
return __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(uniqueId(15), "_").concat(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 = __assign({ location: 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 = __assign(__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 __assign(__assign({}, 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 = 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] = __assign(__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 FilestackError("Invalid file \"".concat(payload.file.name, "\" size - 0"), {}, FilestackErrorType.VALIDATION));
}
debug("[".concat(id, "] Make start request"));
return FsRequest.post("".concat(this.getUrl(), "/multipart/start"), __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 FilestackError('Incorrect start response', data, 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 __awaiter(this, void 0, void 0, function () {
var payload, parts, waitingLength;
var _this = this;
return __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 __awaiter(_this, void 0, void 0, function () {
var _a;
var _this = this;
return __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 = __assign(__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 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 __awaiter(this, void 0, void 0, function () {
var payload, partMetadata, part, _a, data, headers;
var _this = this;
return __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*/, 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 FilestackError('Cannot upload file, check S3 bucket settings', 'Etag header is not exposed in CORS settings', 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 FilestackError('Cannot upload file', resp.data.Error, FilestackErrorType.REQUEST));
}
}
}
// release memory
part = null;
if (err instanceof 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 __awaiter(this, void 0, void 0, function () {
var _this = this;
return __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 __awaiter(this, void 0, void 0, function () {
var payload, part, chunk, data;
var _this = this;
return __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*/, 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 FilestackError('Cannot upload file', resp.data.Error, FilestackErrorType.REQUEST));
}
}
}
// reset progress on failed upload
_this.onProgressUpdate(id, partNumber, part.offset);
var nextChunkSize = Math.ceil(chunkSize / 2);
if (nextChunkSize < MIN_CHUNK_SIZE) {
debug("[".concat(id, "] Minimal chunk size limit. Upload file failed!"));
return Promise.reject(new FilestackError('Min chunk size reached', err.data, FilestackErrorType.REQUEST));
}
if (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 FsRequest.post("".concat(this.getUploadUrl(id), "/multipart/commit"), __assign(__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 FsRequest.post("".concat(this.getUploadUrl(id), "/multipart/complete"), __assign(__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] = __assign(__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 FsRequestError && err.code === FsRequestErrorCode.ABORTED) {
return Promise.reject(new FilestackError(message, { reason: err.message }, FilestackErrorType.ABORTED));
}
return Promise.reject(new FilestackError(message, this.parseError(err), FilestackErrorType.REQUEST));
};
return S3Uploader;
}(UploaderAbstract));
export { S3Uploader };
//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9saWIvYXBpL3VwbG9hZC91cGxvYWRlcnMvczMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7Ozs7Ozs7Ozs7Ozs7R0FlRztBQUNILE9BQU8sS0FBSyxNQUFNLE9BQU8sQ0FBQztBQUMxQixPQUFPLE1BQU0sTUFBTSxTQUFTLENBQUM7QUFFN0IsT0FBTyxFQUFFLGNBQWMsRUFBRSxrQkFBa0IsRUFBRSxNQUFNLCtCQUErQixDQUFDO0FBQ25GLE9BQU8sRUFBRSxhQUFhLEVBQUUsU0FBUyxFQUFFLGNBQWMsRUFBRSxrQkFBa0IsRUFBYyxNQUFNLG9CQUFvQixDQUFDO0FBQzlHLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUN6RCxPQUFPLEVBQUUsWUFBWSxFQUFFLFFBQVEsRUFBRSxVQUFVLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUd0RSxPQUFPLEVBQUUsc0JBQXNCLEVBQUUsc0JBQXNCLEVBQUUsY0FBYyxFQUFFLGdCQUFnQixFQUFjLE1BQU0sWUFBWSxDQUFDO0FBRTFILElBQU0sS0FBSyxHQUFHLEtBQUssQ0FBQyxjQUFjLENBQUMsQ0FBQztBQUVwQyxJQUFNLGdCQUFnQixHQUFHLElBQUksR0FBRyxDQUFDLENBQUM7QUFtQmxDO0lBQWdDLDhCQUFnQjtJQU05QyxvQkFBWSxZQUFnQyxFQUFFLFdBQVk7UUFBMUQsWUFDRSxrQkFBTSxZQUFZLEVBQUUsV0FBVyxDQUFDLFNBUWpDO1FBWE8sY0FBUSxHQUFxQyxFQUFFLENBQUM7UUFLdEQsS0FBSSxDQUFDLFVBQVUsR0FBRyxJQUFJLE1BQU0sQ0FBQztZQUMzQixTQUFTLEVBQUUsS0FBSztZQUNoQixXQUFXLEVBQUUsS0FBSSxDQUFDLFdBQVc7U0FDOUIsQ0FBQyxDQUFDO1FBRUgsS0FBSSxDQUFDLFdBQVcsR0FBRyxJQUFJLGFBQWEsRUFBRSxDQUFDOztJQUN6QyxDQUFDO0lBRUQ7Ozs7T0FJRztJQUNJLDBCQUFLLEdBQVo7UUFDRSxJQUFJ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QUMsUUFBUSxDQUFDLEVBQUUsQ0FBQyxDQUFDLElBQUksQ0FBQyxNQUFNLEdBQUcsTUFBTSxDQUFDO0lBQ3pDLENBQUM7SUFFRDs7OztPQUlHO0lBQ0ssK0JBQVUsR0FBbEIsVUFBbUIsR0FBbUI7UUFDcEMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxRQUFRLEVBQUU7WUFDakIsT0FBTyxFQUFFLENBQUM7U0FDWDtRQUVELE9BQU87WUFDTCxJQUFJLEVBQUUsR0FBRyxDQUFDLFFBQVEsQ0FBQyxNQUFNO1lBQ3pCLElBQUksRUFBRSxHQUFHLENBQUMsUUFBUSxDQUFDLElBQUk7WUFDdkIsT0FBTyxFQUFFLEdBQUcsQ0FBQyxRQUFRLENBQUMsT0FBTztTQUM5QixDQUFDO0lBQ0osQ0FBQztJQUVPLGlDQUFZLEdBQXBCLFVBQXFCLE9BQWUsRUFBRSxHQUFtQjtRQUN2RCxJQUFJLEdBQUcsWUFBWSxjQUFjLElBQUksR0FBRyxDQUFDLElBQUksS0FBSyxrQkFBa0IsQ0FBQyxPQUFPLEVBQUU7WUFDNUUsT0FBTyxPQUFPLENBQUMsTUFBTSxDQUFDLElBQUksY0FBYyxDQUFDLE9BQU8sRUFBRSxFQUFFLE1BQU0sRUFBRSxHQUFHLENBQUMsT0FBTyxFQUFFLEVBQUUsa0JBQWtCLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQztTQUN6RztRQUNELE9BQU8sT0FBTyxDQUFDLE1BQU0sQ0FBQyxJQUFJLGNBQWMsQ0FBQyxPQUFPLEVBQUUsSUFBSSxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsRUFBRSxrQkFBa0IsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDO0lBQ3ZHLENBQUM7SUFDSCxpQkFBQztBQUFELENBcDBCQSxBQW8wQkMsQ0FwMEIrQixnQkFBZ0IsR0FvMEIvQyIsImZpbGUiOiJsaWIvYXBpL3VwbG9hZC91cGxvYWRlcnMvczMuanMiLCJzb3VyY2VzQ29udGVudCI6WyIvKlxuICogQ29weXJpZ2h0IChjKSAyMDE5IGJ5IEZpbGVzdGFjay5cbiAqIFNvbWUgcmlnaHRzIHJlc2VydmVkLlxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuaW1wb3J0IERlYnVnIGZyb20gJ2RlYnVnJztcbmltcG9ydCBQUXVldWUgZnJvbSAncC1xdWV1ZSc7XG5cbmltcG9ydCB7IEZpbGVzdGFja0Vycm9yLCBGaWxlc3RhY2tFcnJvclR5cGUgfSBmcm9tICcuLy4uLy4uLy4uLy4uL2ZpbGVzdGFja19lcnJvcic7XG5pbXBvcnQgeyBGc0NhbmNlbFRva2VuLCBGc1JlcXVlc3QsIEZzUmVxdWVzdEVycm9yLCBGc1JlcXVlc3RFcnJvckNvZGUsIEZzUmVzcG9uc2UgfSBmcm9tICcuLy4uLy4uLy4uL3JlcXVlc3QnO1xuaW1wb3J0IHsgc2hvdWxkUmV0cnkgfSBmcm9tICcuLy4uLy4uLy4uL3JlcXVlc3QvaGVscGVycyc7XG5pbXBvcnQgeyBmaWx0ZXJPYmplY3QsIHVuaXF1ZUlkLCB1bmlxdWVUaW1lIH0gZnJvbSAnLi8uLi8uLi8uLi91dGlscyc7XG5pbXBvcnQgeyBGaWxlLCBGaWxlUGFydCwgRmlsZVBhcnRNZXRhZGF0YSwgRmlsZVN0YXRlIH0gZnJvbSAnLi8uLi9maWxlJztcbmltcG9ydCB7IFN0b3JlVXBsb2FkT3B0aW9ucyB9IGZyb20gJy4vLi4vdHlwZXMnO1xuaW1wb3J0IHsgREVGQVVMVF9TVE9SRV9MT0NBVElPTiwgSU5URUxMSUdFTlRfQ0hVTktfU0laRSwgTUlOX0NIVU5LX1NJWkUsIFVwbG9hZGVyQWJzdHJhY3QsIFVwbG9hZE1vZGUgfSBmcm9tICcuL2Fic3RyYWN0JztcblxuY29uc3QgZGVidWcgPSBEZWJ1ZygnZnM6dXBsb2FkOnMzJyk7XG5cbmNvbnN0IENPTVBMRVRFX1RJTUVPVVQgPSAxMDAwICogMTtcblxuZXhwb3J0IGludGVyZmFjZSBVcGxvYWRQYXJ0IGV4dGVuZHMgRmlsZVBhcnRNZXRhZGF0YSB7XG4gIGV0YWc/OiBzdHJpbmc7XG4gIG9mZnNldD86IG51bWJlcjtcbiAgcHJvZ3Jlc3M/OiBudW1iZXI7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgVXBsb2FkUGF5bG9hZCB7XG4gIGZpbGU6IEZpbGU7XG4gIHBhcnRzOiBVcGxvYWRQYXJ0W107XG4gIGhhbmRsZT86IHN0cmluZztcbiAgdXJpPzogc3RyaW5nO1xuICByZWdpb24/OiBzdHJpbmc7XG4gIHVwbG9hZF9pZD86IG51bWJlcjtcbiAgbG9jYXRpb25fdXJsPzogc3RyaW5nO1xuICBsb2NhdGlvbl9yZWdpb24/OiBzdHJpbmc7XG59XG5cbmV4cG9ydCBjbGFzcyBTM1VwbG9hZGVyIGV4dGVuZHMgVXBsb2FkZXJBYnN0cmFjdCB7XG4gIHByaXZhdGUgcGFydHNRdWV1ZTtcbiAgcHJpdmF0ZSBjYW5jZWxUb2tlbjogRnNDYW5jZWxUb2tlbjsgLy8gZ2xvYmFsIGNhbmNlbCB0b2tlbiBmb3IgYWxsIHJlcXVlc3RzXG5cbiAgcHJpdmF0ZSBwYXlsb2FkczogeyBba2V5OiBzdHJpbmddOiBVcGxvYWRQYXlsb2FkIH0gPSB7fTtcblxuICBjb25zdHJ1Y3RvcihzdG9yZU9wdGlvbnM6IFN0b3JlVXBsb2FkT3B0aW9ucywgY29uY3VycmVuY3k/KSB7XG4gICAgc3VwZXIoc3RvcmVPcHRpb25zLCBjb25jdXJyZW5jeSk7XG5cbiAgICB0aGlzLnBhcnRzUXVldWUgPSBuZXcgUFF1ZXVlKHtcbiAgICAgIGF1dG9TdGFydDogZmFsc2UsXG4gICAgICBjb25jdXJyZW5jeTogdGhpcy5jb25jdXJyZW5jeSxcbiAgICB9KTtcblxuICAgIHRoaXMuY2FuY2VsVG9rZW4gPSBuZXcgRnNDYW5jZWxUb2tlbigpO1xuICB9XG5cbiAgLyoqXG4gICAqIFBhdXNlIHVwbG9hZCBxdWV1ZVxuICAgKlxuICAgKiBAbWVtYmVyb2YgUzNVcGxvYWRlclxuICAgKi9cbiAgcHVibGljIHBhdXNlKCk6IHZvaWQge1xuICAgIHRoaXMucGFydHNRdWV1ZS5wYXVzZSgpO1xuICB9XG5cbiAgLyoqXG4gICAqIHJlc3VtZSB1cGxvYWQgcXVldWUgaWYgaXRzIHBhdXNlZFxuICAgKlxuICAgKiBAbWVtYmVyb2YgUzNVcGxvYWRlclxuICAgKi9cbiAgcHVibGljIHJlc3VtZSgpOiB2b2lkIHtcbiAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dCAqL1xuICAgIGlmICh0aGlzLnBhcnRzUXVldWUuaXNQYXVzZWQpIHtcbiAgICAgIHRoaXMucGFydHNRdWV1ZS5zdGFydCgpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBBYm9ydHMgcXVldWUgKGFsbCBwZW5kaW5nIHJlcXVlc3RzIHdpdGggd2lsbCBiZSBhYm9ydGVkKVxuICAgKlxuICAgKiBAbWVtYmVyb2YgUzNVcGxvYWRlclxuICAgKi9cbiAgcHVibGljIGFib3J0KG1zZz86IHN0cmluZyk6IHZvaWQge1xuICAgIHRoaXMucGFydHNRdWV1ZS5wYXVzZSgpO1xuICAgIHRoaXMucGFydHNRdWV1ZS5jbGVhcigpO1xuXG4gICAgdGhpcy5jYW5jZWxUb2tlbi5jYW5jZWwobXNnIHx8ICdBYm9ydGVkIGJ5IHVzZXInKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBFeGVjdXRlIGFsbCBxdWV1ZWQgZmlsZXNcbiAgICpcbiAgICogQHJldHVybnMge1Byb21pc2U8YW55Pn1cbiAgICogQG1lbWJlcm9mIFMzVXBsb2FkZXJcbiAgICovXG4gIHB1YmxpYyBhc3luYyBleGVjdXRlKCk6IFByb21pc2U8YW55PiB7XG4gICAgY29uc3QgdGFza3MgPSBPYmplY3Qua2V5cyh0aGlzLnBheWxvYWRzKS5tYXAoXG4gICAgICBpZCA9PlxuICAgICAgICBuZXcgUHJvbWlzZShhc3luYyByZXNvbHZlID0+IHtcbiAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgYXdhaXQgdGhpcy5zdGFydFJlcXVlc3QoaWQpO1xuICAgICAgICAgICAgYXdhaXQgdGhpcy5wcmVwYXJlUGFydHMoaWQpO1xuICAgICAgICAgICAgYXdhaXQgdGhpcy5zdGFydFBhcnRzUXVldWUoaWQpO1xuICAgICAgICAgICAgYXdhaXQgdGhpcy5jb21wbGV0ZVJlcXVlc3QoaWQpO1xuICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXG4gICAgICAgICAgICB0aGlzLmVtaXQoJ2Vycm9yJywgZSk7XG4gICAgICAgICAgICBkZWJ1ZyhgWyR7aWR9XSBGaWxlIHVwbG9hZCBmYWlsZWQuICVPLCBcXG5EZXRhaWxzOiAlTyBgLCBlLm1lc3NhZ2UsIGUuZGV0YWlscyk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgY29uc3QgZmlsZSA9IHRoaXMuZ2V0UGF5bG9hZEJ5SWQoaWQpLmZpbGU7XG5cbiAgICAgICAgICAvLyByZWxlYXNlIGZpbGUgYnVmZmVyXG4gICAgICAgICAgZmlsZS5yZWxlYXNlKCk7XG5cbiAgICAgICAgICAvLyBjbGVhbnVwIHBheWxvYWRzXG4gICAgICAgICAgZGVsZXRlIHRoaXMucGF5bG9hZHNbaWRdO1xuXG4gICAgICAgICAgcmVzb2x2ZShmaWxlKTtcbiAgICAgICAgfSlcbiAgICApO1xuXG4gICAgcmV0dXJuIFByb21pc2UuYWxsKHRhc2tzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBZGQgZmlsZSB0byB1cGxvYWQgcXVldWVcbiAgICpcbiAgICogQHBhcmFtIHtGaWxlfSBmaWxlXG4gICAqIEByZXR1cm5zXG4gICAqIEBtZW1iZXJvZiBTM1VwbG9hZGVyXG4gICAqL1xuICBwdWJsaWMgYWRkRmlsZShmaWxlOiBGaWxlKTogc3RyaW5nIHtcbiAgICBkZWJ1ZygnQWRkIGZpbGUgdG8gcXVldWU6IFxcbiAlbycsIGZpbGUpO1xuXG4gICAgY29uc3QgaWQgPSBgJHt1bmlxdWVJZCgxNSl9XyR7dW5pcXVlVGltZSgpfWA7XG5cbiAgICBmaWxlLnN0YXR1cyA9IEZpbGVTdGF0ZS5JTklUO1xuXG4gICAgLy8gc3BsaXQgZmlsZSBpbnRvIHBhcnRzIGFuZCBzZXQgaXQgYXMgd2FpdGluZ1xuICAgIHRoaXMucGF5bG9hZHNbaWRdID0ge1xuICAgICAgZmlsZSxcbiAgICAgIHBhcnRzOiBbXSxcbiAgICB9O1xuXG4gICAgcmV0dXJuIGlkO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgaG9zdCBmb3IgdXBsb2FkIChyZWdpb24gYmFzZWQpXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEByZXR1cm5zXG4gICAqIEBtZW1iZXJvZiBTM1VwbG9hZGVyXG4gICAqL1xuICBwcml2YXRlIGdldFVwbG9hZFVybChpZDogc3RyaW5nKTogc3RyaW5nIHtcbiAgICBjb25zdCB7IGxvY2F0aW9uX3VybCB9ID0gdGhpcy5nZXREZWZhdWx0RmllbGRzKGlkLCBbJ2xvY2F0aW9uX3VybCddKTtcbiAgICByZXR1cm4gbG9jYXRpb25fdXJsLmluZGV4T2YoJ2h0dHAnKSA9PT0gMCA/IGxvY2F0aW9uX3VybCA6IGBodHRwczovLyR7bG9jYXRpb25fdXJsfWA7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyBmb3JtYXR0ZWQgc3RvcmUgb3B0aW9uc1xuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcmV0dXJuc1xuICAgKiBAbWVtYmVyb2YgUzNVcGxvYWRlclxuICAgKi9cbiAgcHJpdmF0ZSBnZXRTdG9yZU9wdGlvbnMoaWQ6IHN0cmluZyk6IFN0b3JlVXBsb2FkT3B0aW9ucyB7XG4gICAgbGV0IG9wdGlvbnMgPSB7XG4gICAgICBsb2NhdGlvbjogREVGQVVMVF9TVE9SRV9MT0NBVElPTiwgLy8gdGhpcyBwYXJhbWV0ZXIgaXMgcmVxdWlyZWQsIGlmIG5vdCBzZXQgdXNlIGRlZmF1bHQgb25lXG4gICAgICAuLi50aGlzLnN0b3JlT3B0aW9ucyxcbiAgICB9O1xuXG4gICAgaWYgKHRoaXMuc3RvcmVPcHRpb25zLmRpc2FibGVTdG9yYWdlS2V5KSB7XG4gICAgICBjb25zdCBwYXlsb2FkID0gdGhpcy5nZXRQYXlsb2FkQnlJZChpZCk7XG5cbiAgICAgIGlmIChvcHRpb25zLnBhdGggJiYgb3B0aW9ucy5wYXRoLnN1YnN0cigtMSkgIT09ICcvJykge1xuICAgICAgICBvcHRpb25zLnBhdGggPSBgJHtvcHRpb25zLnBhdGh9L2A7XG4gICAgICB9XG5cbiAgICAgIG9wdGlvbnMucGF0aCA9IGAke29wdGlvbnMucGF0aCA/IG9wdGlvbnMucGF0aCA6ICcvJ30ke3BheWxvYWQuZmlsZS5uYW1lfWA7XG5cbiAgICAgIGRlbGV0ZSBvcHRpb25zLmRpc2FibGVTdG9yYWdlS2V5O1xuICAgIH1cblxuICAgIHJldHVybiBvcHRpb25zO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgYWxsIGRlZmF1bHQgZmllbGRzIGZvciBmaWxlc3RhY2sgcmVxdWVzdHNcbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHJldHVybnNcbiAgICogQG1lbWJlcm9mIFMzVXBsb2FkZXJcbiAgICovXG4gIHByaXZhdGUgZ2V0RGVmYXVsdEZpZWxkcyhpZDogc3RyaW5nLCByZXF1aXJlZEZpZWxkczogc3RyaW5nW10sIGZpaUZhbGxiYWNrOiBib29sZWFuID0gZmFsc2UpIHtcbiAgICBjb25zdCBwYXlsb2FkID0gdGhpcy5nZXRQYXlsb2FkQnlJZChpZCk7XG5cbiAgICBsZXQgZmllbGRzID0ge1xuICAgICAgLi4udGhpcy5zZWN1cml0eSxcbiAgICAgIGFwaWtleTogdGhpcy5hcGlrZXksXG4gICAgICB1cmk6IHBheWxvYWQudXJpLFxuICAgICAgbG9jYXRpb25fdXJsOiBwYXlsb2FkLmxvY2F0aW9uX3VybCxcbiAgICAgIHVwbG9hZF9pZDogcGF5bG9hZC51cGxvYWRfaWQsXG4gICAgICByZWdpb246IHBheWxvYWQucmVnaW9uLFxuICAgICAgYWx0OiBwYXlsb2FkLmZpbGUuYWx0LFxuICAgIH07XG5cbiAgICBpZiAodGhpcy51cGxvYWRNb2RlID09PSBVcGxvYWRNb2RlLklOVEVMTElHRU5UIHx8ICh0aGlzLnVwbG9hZE1vZGUgPT09IFVwbG9hZE1vZGUuRkFMTEJBQ0sgJiYgZmlpRmFsbGJhY2spKSB7XG4gICAgICBmaWVsZHNbJ2ZpaSddID0gdHJ1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgLi4uZmlsdGVyT2JqZWN0KGZpZWxkcywgcmVxdWlyZWRGaWVsZHMpLFxuICAgICAgc3RvcmU6IHRoaXMuZ2V0U3RvcmVPcHRpb25zKGlkKSxcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgZGVmYXVsdCBoZWFkZXJzIG5lZWRlZCBmb3IgZmlsZXN0YWNrIHJlcXVlc3RcbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHJldHVybnNcbiAgICogQG1lbWJlcm9mIFMzVXBsb2FkZXJcbiAgICovXG4gIHByaXZhdGUgZ2V0RGVmYXVsdEhlYWRlcnMoaWQ6IHN0cmluZykge1xuICAgIGxldCBoZWFkZXJzID0ge307XG4gICAgY29uc3QgZmlsZSA9IHRoaXMuZ2V0UGF5bG9hZEJ5SWQoaWQpO1xuXG4gICAgaWYgKGZpbGUubG9jYXRpb25fcmVnaW9uKSB7XG4gICAgICBoZWFkZXJzWydGaWxlc3RhY2stVXBsb2FkLVJlZ2lvbiddID0gZmlsZS5sb2NhdGlvbl9yZWdpb247XG4gICAgfVxuXG4gICAgcmV0dXJuIGhlYWRlcnM7XG4gIH1cblxuICBwcml2YXRlIGdldFBheWxvYWRCeUlkKGlkOiBzdHJpbmcpOiBVcGxvYWRQYXlsb2FkIHtcbiAgICByZXR1cm4gdGhpcy5wYXlsb2Fkc1tpZF07XG4gIH1cblxuICAvKipcbiAgICogU3BsaXQgZmlsZSBvbnRvIHBhcnRzIGZvciB1cGxvYWRpbmcgd2l0aCBtdWx0aXBhcnQgbWVjaGFuaXNtIGFuZCBzZXR1cCBzdGFydFxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAbWVtYmVyb2YgUzNVcGxvYWRlclxuICAgKi9cbiAgcHJpdmF0ZSBwcmVwYXJlUGFydHMoaWQ6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IGZpbGUgPSB0aGlzLmdldFBheWxvYWRCeUlkKGlkKS5maWxlO1xuICAgIGxldCBpbnRlbGxpZ2VudENodW5rID0gZmFsc2U7XG5cbiAgICAvLyBmb3IgaW50ZWxsaWdlbnQgb3IgZmFsbGJhY2sgbW9kZSB3ZSBjYW50IG92ZXJ3cml0ZSBwYXJ0IHNpemUgLSByZXF1aXJlcyA4TUJcbiAgICBpZiAoW1VwbG9hZE1vZGUuSU5URUxMSUdFTlQsIFVwbG9hZE1vZGUuRkFMTEJBQ0tdLmluZGV4T2YodGhpcy51cGxvYWRNb2RlKSA+IC0xKSB7XG4gICAgICB0aGlzLnBhcnRTaXplID0gSU5URUxMSUdFTlRfQ0hVTktfU0laRTtcbiAgICAgIGludGVsbGlnZW50Q2h1bmsgPSB0cnVlO1xuICAgIH1cblxuICAgIGNvbnN0IHsgcGFydHNDb3VudCwgY2h1bmtTaXplIH0gPSBmaWxlLmdldFBhcnRzQ291bnQodGhpcy5wYXJ0U2l6ZSwgaW50ZWxsaWdlbnRDaHVuayk7XG5cbiAgICBjb25zdCBwYXJ0cyA9IFtdO1xuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBwYXJ0c0NvdW50OyBpKyspIHtcbiAgICAgIHBhcnRzW2ldID0ge1xuICAgICAgICAuLi5maWxlLmdldFBhcnRNZXRhZGF0YShpLCBjaHVua1NpemUpLFxuICAgICAgICBvZmZzZXQ6IDAsXG4gICAgICB9O1xuICAgIH1cblxuICAgIC8vIHNwbGl0IGZpbGUgaW50byBwYXJ0cyBhbmQgc2V0IGl0IGFzIHdhaXRpbmdcbiAgICB0aGlzLnBheWxvYWRzW2lkXS5wYXJ0cyA9IHBhcnRzO1xuXG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuICB9XG5cbiAgLyoqXG4gICAqIE1ha2Ugc3RhcnQgcmVxdWVzdCBmb3IgZ2V0dGluZyBuZWVkZWQgdXBsb2FkIGZpZWxkc1xuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTxhbnk+fVxuICAgKiBAbWVtYmVyb2YgUzNVcGxvYWRlclxuICAgKi9cbiAgcHJpdmF0ZSBzdGFydFJlcXVlc3QoaWQ6IHN0cmluZyk6IFByb21pc2U8YW55PiB7XG4gICAgY29uc3QgcGF5bG9hZCA9IHRoaXMuZ2V0UGF5bG9hZEJ5SWQoaWQpO1xuXG4gICAgaWYgKHBheWxvYWQuZmlsZS5zaXplID09PSAwKSB7XG4gICAgICB0aGlzLnNldFBheWxvYWRTdGF0dXMoaWQsIEZpbGVTdGF0ZS5GQUlMRUQpO1xuICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KG5ldyBGaWxlc3RhY2tFcnJvcihgSW52YWxpZCBmaWxlIFwiJHtwYXlsb2FkLmZpbGUubmFtZX1cIiBzaXplIC0gMGAsIHt9LCBGaWxlc3RhY2tFcnJvclR5cGUuVkFMSURBVElPTikpO1xuICAgIH1cblxuICAgIGRlYnVnKGBbJHtpZH1dIE1ha2Ugc3RhcnQgcmVxdWVzdGApO1xuICAgIHJldHVybiBGc1JlcXVlc3QucG9zdChcbiAgICAgIGAke3RoaXMuZ2V0VXJsKCl9L211bHRpcGFydC9zdGFydGAsXG4gICAgICB7XG4gICAgICAgIGZpbGVuYW1lOiBwYXlsb2FkLmZpbGUubmFtZSxcbiAgICAgICAgbWltZXR5cGU6IHBheWxvYWQuZmlsZS50eXBlLFxuICAgICAgICBzaXplOiBwYXlsb2FkLmZpbGUuc2l6ZSxcbiAgICAgICAgLi4udGhpcy5nZXREZWZhdWx0RmllbGRzKGlkLCBbJ2FwaWtleScsICdwb2xpY3knLCAnc2lnbmF0dXJlJywgJ2ZpaSddLCB0cnVlKSxcbiAgICAgIH0sXG4gICAgICB7XG4gICAgICAgIHRpbWVvdXQ6IHRoaXMudGltZW91dCxcbiAgICAgICAgY2FuY2VsVG9rZW46IHRoaXMuY2FuY2VsVG9rZW4sXG4gICAgICAgIGhlYWRlcnM6IHRoaXMuZ2V0RGVmYXVsdEhlYWRlcnMoaWQpLFxuICAgICAgICByZXRyeTogdGhpcy5yZXRyeUNvbmZpZyxcbiAgICAgIH1cbiAgICApXG4gICAgICAudGhlbigoeyBkYXRhIH0pID0+IHtcbiAgICAgICAgaWYgKCFkYXRhIHx8ICFkYXRhLmxvY2F0aW9uX3VybCB8fCAhZGF0YS5yZWdpb24gfHwgIWRhdGEudXBsb2FkX2lkIHx8ICFkYXRhLnVyaSkge1xuICAgICAgICAgIGRlYnVnKGBbJHtpZH1dIEluY29ycmVjdCBzdGFydCByZXNwb25zZTogXFxuJU9cXG5gLCBkYXRhKTtcbiAgICAgICAgICB0aGlzLnNldFBheWxvYWRTdGF0dXMoaWQsIEZpbGVTdGF0ZS5GQUlMRUQpO1xuICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdChuZXcgRmlsZXN0YWNrRXJyb3IoJ0luY29ycmVjdCBzdGFydCByZXNwb25zZScsIGRhdGEsIEZpbGVzdGFja0Vycm9yVHlwZS5SRVFVRVNUKSk7XG4gICAgICAgIH1cblxuICAgICAgICBkZWJ1ZyhgWyR7aWR9XSBBc3NpZ24gcGF5bG9hZCBkYXRhOiBcXG4lT1xcbmAsIGRhdGEpO1xuXG4gICAgICAgIHRoaXMudXBkYXRlUGF5bG9hZChpZCwgZGF0YSk7XG5cbiAgICAgICAgLy8gaWkgaXMgbm90IGVuYWJsZWQgaW4gYmFja2VuZCBzd2l0Y2ggYmFjayB0byBkZWZhdWx0IHVwbG9hZCBtb2RlXG4gICAgICAgIGlmIChbVXBsb2FkTW9kZS5JTlRFTExJR0VOVCwgVXBsb2FkTW9kZS5GQUxMQkFDS10uaW5kZXhPZih0aGlzLnVwbG9hZE1vZGUpID4gLTEgJiYgKCFkYXRhLnVwbG9hZF90eXBlIHx8IGRhdGEudXBsb2FkX3R5cGUgIT09ICdpbnRlbGxpZ2VudF9pbmdlc3Rpb24nKSkge1xuICAgICAgICAgIGRlYnVnKGBbJHtpZH1dIEludGVsbGlnZW50IEluZ2VzdGlvbiBpcyBub3QgZW5hYmxlZCBvbiBhY2NvdW50LCBzd2l0Y2ggYmFjayB0byByZWd1bGFyIHVwbG9hZCBhbmQgbG9jayBtb2RlIGNoYW5nZWApO1xuICAgICAgICAgIHRoaXMuc2V0VXBsb2FkTW9kZShVcGxvYWRNb2RlLkRFRkFVTFQsIHRydWUpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGRhdGE7XG4gICAgICB9KVxuICAgICAgLmNhdGNoKGVyciA9PiB7XG4gICAgICAgIGRlYnVnKGBbJHtpZH1dIFN0YXJ0IHJlcXVlc3QgZXJyb3IgJU9gLCBlcnIpO1xuICAgICAgICB0aGlzLnNldFBheWxvYWRTdGF0dXMoaWQsIEZpbGVTdGF0ZS5GQUlMRUQpO1xuXG4gICAgICAgIHJldHVybiB0aGlzLnJlamVjdFVwbG9hZCgnQ2Fubm90IHVwbG9hZCBmaWxlLiBTdGFydCByZXF1ZXN0IGZhaWxlZCcsIGVycik7XG4gICAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBFbnF1ZXVlIGZpbGUgcGFydHMgdG8gdXBsb2FkXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEByZXR1cm5zXG4gICAqIEBtZW1iZXJvZiBTM1VwbG9hZGVyXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIHN0YXJ0UGFydHNRdWV1ZShpZDogc3RyaW5nKTogUHJvbWlzZTxhbnk+IHtcbiAgICBjb25zdCBwYXlsb2FkID0gdGhpcy5nZXRQYXlsb2FkQnlJZChpZCk7XG4gICAgY29uc3QgcGFydHMgPSBwYXlsb2FkLnBhcnRzO1xuICAgIGNvbnN0IHdhaXRpbmdMZW5ndGggPSBwYXJ0cy5sZW5ndGg7XG5cbiAgICBkZWJ1ZyhgWyR7aWR9XSBDcmVhdGUgdXBsb2FkaW5nIHF1ZXVlIGZyb20gZmlsZS4gcGFydHMgY291bnQgLSAlZGAsIHdhaXRpbmdMZW5ndGgpO1xuXG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKGFzeW5jIChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIHBhcnRzLmZvckVhY2gocGFydCA9PlxuICAgICAgICB0aGlzLnBhcnRzUXVldWVcbiAgICAgICAgICAuYWRkKCgpID0+IHRoaXMuc3RhcnRQYXJ0KGlkLCBwYXJ0LnBhcnROdW1iZXIpKVxuICAgICAgICAgIC5jYXRjaChlID0+IHtcbiAgICAgICAgICAgIHRoaXMuc2V0UGF5bG9hZFN0YXR1cyhpZCwgRmlsZVN0YXRlLkZBSUxFRCk7XG4gICAgICAgICAgICBkZWJ1ZyhgWyR7aWR9XSBGYWlsZWQgdG8gdXBsb2FkIHBhcnQgJXNgLCBlLm1lc3NhZ2UpO1xuXG4gICAgICAgICAgICB0aGlzLnBhcnRzUXVldWUucGF1c2UoKTtcbiAgICAgICAgICAgIHRoaXMucGFydHNRdWV1ZS5jbGVhcigpO1xuICAgICAgICAgICAgcmV0dXJuIHJlamVjdChlKTtcbiAgICAgICAgICB9KVxuICAgICAgKTtcblxuICAgICAgZGVidWcoYFske2lkfV0gQWxsIHRhc2tzIGZvciAlcyBlbnF1ZXVlZC4gU3RhcnQgcHJvY2Vzc2luZyBtYWluIHVwbG9hZCBxdWV1ZWAsIGlkKTtcbiAgICAgIHRoaXMuZW1pdCgnc3RhcnQnKTtcbiAgICAgIHRoaXMucGFydHNRdWV1ZS5zdGFydCgpO1xuXG4gICAgICByZXNvbHZlKGF3YWl0IHRoaXMucGFydHNRdWV1ZS5vbklkbGUoKSk7XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogRGVjaWRlIGlmIHVwbG9hZCBzaG91bGQgYmUgbWFkZSB1c2luZyBpaSBvciByZWd1bGFyIHVwbG9hZFxuICAgKiBJdCBhbGxvd3MgY2hhbmdlIHVwbG9hZCBtb2RlIGR1cmluZyB1cGxvYWQgcXVldWVcbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtudW1iZXJ9IHBhcnROdW1iZXJcbiAgICogQHJldHVybnMge1Byb21pc2U8YW55Pn1cbiAgICogQG1lbWJlcm9mIFMzVXBsb2FkZXJcbiAgICovXG4gIHByaXZhdGUgc3RhcnRQYXJ0KGlkOiBzdHJpbmcsIHBhcnROdW1iZXI6IG51bWJlcik6IFByb21pc2U8YW55PiB7XG4gICAgZGVidWcoYFske2lkfV0gU3RhcnQgcHJvY2Vzc2luZyBwYXJ0ICR7cGFydE51bWJlcn0gd2l0aCBtb2RlICR7dGhpcy51cGxvYWRNb2RlfWApO1xuXG4gICAgbGV0IHBheWxvYWQgPSB0aGlzLmdldFBheWxvYWRCeUlkKGlkKTtcblxuICAgIHBheWxvYWQuZmlsZS5zdGF0dXMgPSBGaWxlU3RhdGUuUFJPR1JFU1M7XG4gICAgcmV0dXJuICh0aGlzLnVwbG9hZE1vZGUgIT09IFVwbG9hZE1vZGUuSU5URUxMSUdFTlQgPyB0aGlzLnVwbG9hZFJlZ3VsYXIgOiB0aGlzLnVwbG9hZEludGVsbGlnZW50KS5hcHBseSh0aGlzLCBbaWQsIHBhcnROdW1iZXJdKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHBhcnQgZGF0YSBuZWVkZWQgZm9yIHVwbG9hZFxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gaWQgLSBpZCBvZiBhIGN1cnJlbnRseSB1cGxvYWRpbmcgZmlsZVxuICAgKiBAcGFyYW0ge0ZpbGVQYXJ0fSBwYXJ0XG4gICAqIEByZXR1cm5zXG4gICAqIEBtZW1iZXJvZiBTM1VwbG9hZGVyXG4gICAqL1xuICBwcml2YXRlIGdldFMzUGFydE1ldGFkYXRhKGlkOiBzdHJpbmcsIHBhcnQ6IEZpbGVQYXJ0LCBvZmZzZXQ/OiBudW1iZXIpOiBQcm9taXNlPGFueT4ge1xuICAgIGNvbnN0IHVybCA9IHRoaXMuZ2V0VXBsb2FkVXJsKGlkKTtcblxuICAgIGRlYnVnKGBbJHtpZH1dIEdldCBkYXRhIGZvciBwYXJ0ICR7cGFydC5wYXJ0TnVtYmVyfSwgdXJsICR7dXJsfSwgTWQ1OiAke3BhcnQubWQ1fSwgU2l6ZTogJHtwYXJ0LnNpemV9YCk7XG5cbiAgICBjb25zdCBkYXRhID0ge1xuICAgICAgLi4udGhpcy5nZXREZWZhdWx0RmllbGRzKGlkLCBbJ2FwaWtleScsICd1cmknLCAncmVnaW9uJywgJ3NpZ25hdHVyZScsICdwb2xpY3knLCAndXBsb2FkX2lkJywgJ2ZpaSddKSxcbiAgICAgIC8vIG1ldGhvZCBzcGVjaWZpYyBrZXlzXG4gICAgICBwYXJ0OiBwYXJ0LnBhcnROdW1iZXIgKyAxLFxuICAgICAgc2l6ZTogcGFydC5zaXplLFxuICAgICAgb2Zmc2V0LFxuICAgIH07XG5cbiAgICBpZiAodGhpcy5pbnRlZ3JpdHlDaGVjayAmJiBwYXJ0Lm1kNSkge1xuICAgICAgZGF0YS5tZDUgPSBwYXJ0Lm1kNTtcbiAgICB9XG5cbiAgICByZXR1cm4gRnNSZXF1ZXN0LnBvc3QoYCR7dXJsfS9tdWx0aXBhcnQvdXBsb2FkYCwgZGF0YSwge1xuICAgICAgaGVhZGVyczogdGhpcy5nZXREZWZhdWx0SGVhZGVycyhpZCksXG4gICAgICBjYW5jZWxUb2tlbjogdGhpcy5jYW5jZWxUb2tlbixcbiAgICAgIHRpbWVvdXQ6IHRoaXMudGltZW91dCxcbiAgICAgIHJldHJ5OiB0aGlzLnJldHJ5Q29uZmlnLFxuICAgIH0pLmNhdGNoKGVyciA9PiB7XG4gICAgICB0aGlzLnNldFBheWxvYWRTdGF0dXMoaWQsIEZpbGVTdGF0ZS5GQUlMRUQpO1xuXG4gICAgICByZXR1cm4gdGhpcy5yZWplY3RVcGxvYWQoJ0Nhbm5vdCBnZXQgcGFydCBtZXRhZGF0YScsIGVycik7XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogUmVndWxhciBtdWx0aXBhcnQgcmVxdWVzdCB0byBhbWF6b25cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtudW1iZXJ9IHBhcnROdW1iZXJcbiAgICogQHJldHVybnMge1Byb21pc2U8YW55Pn1cbiAgICogQG1lbWJlcm9mIFMzVXBsb2FkZXJcbiAgICovXG4gIHByaXZhdGUgYXN5bmMgdXBsb2FkUmVndWxhcihpZDogc3RyaW5nLCBwYXJ0TnVtYmVyOiBudW1iZXIpOiBQcm9taXNlPGFueT4ge1xuICAgIGxldCBwYXlsb2FkID0gdGhpcy5nZXRQYXlsb2FkQnlJZChpZCk7XG4gICAgY29uc3QgcGFydE1ldGFkYXRhID0gcGF5bG9hZC5wYXJ0c1twYXJ0TnVtYmVyXTtcbiAgICBsZXQgcGFydCA9IGF3YWl0IHBheWxvYWQuZmlsZS5nZXRQYXJ0QnlNZXRhZGF0YShwYXJ0TWV0YWRhdGEsIHRoaXMuaW50ZWdyaXR5Q2hlY2spO1xuXG4gICAgY29uc3QgeyBkYXRhLCBoZWFkZXJzIH0gPSBhd2FpdCB0aGlzLmdldFMzUGFydE1ldGFkYXRhKGlkLCBwYXJ0KTtcbiAgICBkZWJ1ZyhgWyR7aWR9XSBSZWNlaXZlZCBwYXJ0ICR7cGFydE51bWJlcn0gaW5mbyBib2R5OiBcXG4lT1xcbiBoZWFkZXJzOiBcXG4lT1xcbmAsIGRhdGEsIGhlYWRlcnMpO1xuICAgIHJldHVybiBGc1JlcXVlc3QucHV0KGRhdGEudXJsLCBwYXJ0LmJ1ZmZlciwge1xuICAgICAgY2FuY2VsVG9rZW46IHRoaXMuY2FuY2VsVG9rZW4sXG4gICAgICB0aW1lb3V0OiB0aGlzLnRpbWVvdXQsXG4gICAgICBoZWFkZXJzOiBkYXRhLmhlYWRlcnMsXG4gICAgICBmaWxlc3RhY2tIZWFkZXJzOiBmYWxzZSxcbiAgICAgIC8vIGZvciBub3cgd2UgY2FudCB0ZXN0IHByb2dyZXNzIGNhbGxiYWNrIGZyb20gdXBsb2FkXG4gICAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dCAqL1xuICAgICAgb25Qcm9ncmVzczogKHByOiBQcm9ncmVzc0V2ZW50KSA9PiB0aGlzLm9uUHJvZ3Jlc3NVcGRhdGUoaWQsIHBhcnROdW1iZXIsIHByLmxvYWRlZCksXG4gICAgICByZXRyeTogdGhpcy5yZXRyeUNvbmZpZyAmJiB0aGlzLnVwbG9hZE1vZGUgIT09IFVwbG9hZE1vZGUuRkFMTEJBQ0sgPyB0aGlzLnJldHJ5Q29uZmlnIDogdW5kZWZpbmVkLFxuICAgIH0pXG4gICAgLnRoZW4ocmVzID0+IHtcbiAgICAgIGlmIChyZXMuaGVhZGVycy5ldGFnKSB7XG4gICAgICAgIHRoaXMuc2V0UGFydEVUYWcoaWQsIHBhcnROdW1iZXIsIHJlcy5oZWFkZXJzLmV0YWcpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gcmVsZWFzZSBtZW1vcnlcbiAgICAgICAgcGFydCA9IG51bGw7XG4gICAgICAgIHRocm93IG5ldyBGaWxlc3RhY2tFcnJvcignQ2Fubm90IHVwbG9hZCBmaWxlLCBjaGVjayBTMyBidWNrZXQgc2V0dGluZ3MnLCAnRXRhZyBoZWFkZXIgaXMgbm90IGV4cG9zZWQgaW4gQ09SUyBzZXR0aW5ncycsIEZpbGVzdGFja0Vycm9yVHlwZS5SRVFVRVNUKTtcbiAgICAgIH1cblxuICAgICAgZGVidWcoYFske2lkfV0gUzMgVXBsb2FkIHJlc3BvbnNlIGhlYWRlcnMgZm9yICR7cGFydE51bWJlcn06IFxcbiVPXFxuYCwgcmVzLmhlYWRlcnMpO1xuXG4gICAgICB0aGlzLm9uUHJvZ3Jlc3NVcGRhdGUoaWQsIHBhcnROdW1iZXIsIHBhcnQuc2l6ZSk7XG5cbiAgICAgIC8vIHJlbGVhc2UgbWVtb3J5XG4gICAgICBwYXJ0ID0gbnVsbDtcblxuICAgICAgcmV0dXJuIHJlcztcbiAgICB9KVxuICAgIC5jYXRjaChlcnIgPT4ge1xuICAgICAgY29uc3QgcmVzcCA9IGVyciAmJiBlcnIucmVzcG9uc2UgPyBlcnIucmVzcG9uc2UgOiBudWxsO1xuXG4gICAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dCAqL1xuICAgICAgaWYgKHJlc3AgJiYgcmVzcC5zdGF0dXMgPT09IDQwMykge1xuICAgICAgICBpZiAocmVzcC5kYXRhICYmIHJlc3AuZGF0YS5FcnJvciAmJiByZXNwLmRhdGEuRXJyb3IuY29kZSkge1xuICAgICAgICAgIGxldCBjb2RlID0gcmVzcC5kYXRhLkVycm9yLmNvZGU7XG5cbiAgICAgICAgICBpZiAoQXJyYXkuaXNBcnJheShjb2RlKSkge1xuICAgICAgICAgICAgY29kZSA9IGNvZGUucG9wKCk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgc3dpdGNoIChjb2RlKSB7XG4gICAgICAgICAgICBjYXNlICdSZXF1ZXN0VGltZVRvb1NrZXdlZCc6XG4gICAgICAgICAgICAgIHJldHVybiB0aGlzLnN0YXJ0UGFydChpZCwgcGFydE51bWJlcik7XG4gICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QobmV3IEZpbGVzdGFja0Vycm9yKCdDYW5ub3QgdXBsb2FkIGZpbGUnLCByZXNwLmRhdGEuRXJyb3IsIEZpbGVzdGFja0Vycm9yVHlwZS5SRVFVRVNUKSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIC8vIHJlbGVhc2UgbWVtb3J5XG4gICAgICBwYXJ0ID0gbnVsbDtcblxuICAgICAgaWYgKGVyciBpbnN0YW5jZW9mIEZpbGVzdGFja0Vycm9yKSB7XG4gICAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdChlcnIpO1xuICAgICAgfVxuICAgICAgLy8gcmVzZXQgdXBsb2FkIHByb2dyZXNzIG9uIGZhaWxlZCBwYXJ0XG4gICAgICB0aGlzLm9uUHJvZ3Jlc3NVcGRhdGUoaWQsIHBhcnROdW1iZXIsIDApO1xuXG4gICAgICAvLyBpZiBmYWxsYmFjaywgc2V0IHVwbG9hZCBtb2RlIHRvIGludGVsbGlnZW50IGFuZCByZXN0YXJ0IGN1cnJlbnQgcGFydFxuICAgICAgaWYgKCh0aGlzLnVwbG9hZE1vZGUgPT09IFVwbG9hZE1vZGUuRkFMTEJBQ0sgJiYgIXRoaXMuaXNNb2RlTG9ja2VkKSB8fCB0aGlzLnVwbG9hZE1vZGUgPT09IFVwbG9hZE1vZGUuSU5URUxMSUdFTlQpIHtcbiAgICAgICAgZGVidWcoYFske2lkfV0gUmVndWxhciB1cGxvYWQgZmFpbGVkLiBTd2l0Y2hpbmcgdG8gaW50ZWxsaWdlbnQgaW5nZXN0aW9uIG1vZGVgKTtcbiAgICAgICAgdGhpcy5zZXRVcGxvYWRNb2RlKFVwbG9hZE1vZGUuSU5URUxMSUdFTlQpO1xuICAgICAgICAvLyByZXN0YXJ0IHBhcnRcbiAgICAgICAgcmV0dXJuIHRoaXMuc3RhcnRQYXJ0KGlkLCBwYXJ0TnVtYmVyKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXMucmVqZWN0VXBsb2FkKCdDYW5ub3QgdXBsb2FkIGZpbGUgcGFydCcsIGVycik7XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogVXBsb2FkIGZpbGUgdXNpbmcgaW50ZWxsaWdlbnQgbWVjaGFuaXNtXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBpZFxuICAgKiBAcGFyYW0ge251bWJlcn0gcGFydE51bWJlclxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTxhbnk+fVxuICAgKiBAbWVtYmVyb2YgUzNVcGxvYWRlclxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyB1cGxvYWRJbnRlbGxpZ2VudChpZDogc3RyaW5nLCBwYXJ0TnVtYmVyOiBudW1iZXIpOiBQcm9taXNlPGFueT4ge1xuICAgIHJldHVybiB0aGlzLnVwbG9hZE5leHRDaHVuayhpZCwgcGFydE51bWJlcikudGhlbigoKSA9PiB0aGlzLmNvbW1pdFBhcnQoaWQsIHBhcnROdW1iZXIpKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZWN1cnNpdmVseSB1cGxvYWQgZmlsZSBpbiBjaHVuayBtb2RlIChpbnRlbGxpZ2VudCBpbmdlc3Npb24pXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBpZFxuICAgKiBAcGFyYW0ge251bWJlcn0gcGFydE51bWJlclxuICAgKiBAcGFyYW0ge251bWJlcn0gY2h1bmtTaXplXG4gICAqIEByZXR1cm5zXG4gICAqIEBtZW1iZXJvZiBTM1VwbG9hZGVyXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIHVwbG9hZE5leHRDaHVuayhpZDogc3RyaW5nLCBwYXJ0TnVtYmVyOiBudW1iZXIsIGNodW5rU2l6ZTogbnVtYmVyID0gdGhpcy5pbnRlbGxpZ2VudENodW5rU2l6ZSkge1xuICAgIGNvbnN0IHBheWxvYWQgPSB0aGlzLmdldFBheWxvYWRCeUlkKGlkKTtcbiAgICBsZXQgcGFydCA9IHBheWxvYWQucGFydHNbcGFydE51bWJlcl07XG4gICAgY2h1bmtTaXplID0gcGFydC5zaXplIC0gcGFydC5vZmZzZXQ7XG5cbiAgICBsZXQgY2h1bmsgPSBhd2FpdCBwYXlsb2FkLmZpbGUuZ2V0Q2h1bmtCeU1ldGFkYXRhKHBhcnQsIHBhcnQub2Zmc2V0LCBjaHVua1NpemUsIHRoaXMuaW50ZWdyaXR5Q2hlY2spO1xuXG4gICAgZGVidWcoXG4gICAgICBgWyR7aWR9XSBQYXJ0TnVtOiAke3BhcnROdW1iZXJ9LCBQYXJ0U2l6ZTogJHtwYXJ0LnNpemV9LCBTdGFydEJ5dGU6ICR7cGFydC5zdGFydEJ5dGV9LCBPZmZzZXQ6ICR7cGFydC5vZmZzZXR9LCBDaHVua1NpemU6ICR7Y2h1bmsuc2l6ZX0sXG4gICAgICAgTGVmdDogJHtwYXJ0LnNpemUgLSBwYXJ0Lm9mZnNldCAtIGNodW5rLnNpemV9YFxuICAgICk7XG5cbiAgICAvLyBjYXRjaCBlcnJvciBmb3IgZGVidWcgcHVycG9zZXNcbiAgICBjb25zdCB7IGRhdGEgfSA9IGF3YWl0IHRoaXMuZ2V0UzNQYXJ0TWV0YWRhdGEoaWQsIGNodW5rLCBwYXJ0Lm9mZnNldCkuY2F0Y2goZXJyID0+IHtcbiAgICAgIGRlYnVnKGBbJHtpZH1dIEdldHRpbmcgY2h1bmsgZGF0YSBmb3IgaWkgZmFpbGVkICVPLCBDaHVuayBzaXplOiAke2NodW5rU2l6ZX0sIG9mZnNldCAke3BhcnQub2Zmc2V0fSwgcGFydCAke3BhcnROdW1iZXJ9YCwgZXJyKTtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdChlcnIpO1xuICAgIH0pO1xuXG4gICAgcmV0dXJuIEZzUmVxdWVzdC5wdXQoZGF0YS51cmwsIGNodW5rLmJ1ZmZlciwge1xuICAgICAgY2FuY2VsVG9rZW46IHRoaXMuY2FuY2VsVG9rZW4sXG4gICAgICB0aW1lb3V0OiB0aGlzLnRpbWVvdXQsXG4gICAgICBoZWFkZXJzOiBkYXRhLmhlYWRlcnMsXG4gICAgICBmaWxlc3RhY2tIZWFkZXJzOiBmYWxzZSxcbiAgICAgIC8vIGZvciBub3cgd2UgY2FudCB0ZXN0IHByb2dyZXNzIGNhbGxiYWNrIGZyb20gdXBsb2FkXG4gICAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dCAqL1xuICAgICAgb25Qcm9ncmVzczogKHByOiBQcm9ncmVzc0V2ZW50KSA9PiBwYXJ0ID8gdGhpcy5vblByb2dyZXNzVXBkYXRlKGlkLCBwYXJ0TnVtYmVyLCBwYXJ0Lm9mZnNldCArIHByLmxvYWRlZCkgOiBudWxsLFxuICAgIH0pXG4gICAgICAudGhlbihyZXMgPT4ge1xuICAgICAgICB0aGlzLm9uUHJvZ3Jlc3NVcGRhdGUoaWQsIHBhcnROdW1iZXIsIHBhcnQub2Zmc2V0ICsgY2h1bmsuc2l6ZSk7XG4gICAgICAgIGNvbnN0IG5ld09mZnNldCA9IE1hdGgubWluKHBhcnQub2Zmc2V0ICsgY2h1bmtTaXplLCBwYXJ0LnNpemUpO1xuICAgICAgICBkZWJ1ZyhgWyR7aWR9XSBTMyBDaHVuayB1cGxvYWRlZCEgb2Zmc2V0OiAke3BhcnQub2Zmc2V0fSwgcGFydCAke3BhcnROdW1iZXJ9ISByZXNwb25zZSBoZWFkZXJzIGZvciAke3BhcnROdW1iZXJ9OiBcXG4lT1xcbmAsIHJlcy5oZWFkZXJzKTtcbiAgICAgICAgdGhpcy5zZXRQYXJ0RGF0YShpZCwgcGFydE51bWJlciwgJ29mZnNldCcsIG5ld09mZnNldCk7XG5cbiAgICAgICAgLy8gaWYgYWxsIGNodW5rcyB3YXMgdXBsb2FkZWQgdGhlbiByZXR1cm4gcmVzb2x2ZVxuICAgICAgICBpZiAobmV3T2Zmc2V0ID09PSBwYXJ0LnNpemUpIHtcbiAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHJlcyk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyByZWxlYXNlIG1lbW9yeVxuICAgICAgICBwYXJ0ID0gbnVsbDtcbiAgICAgICAgY2h1bmsgPSBudWxsO1xuXG4gICAgICAgIHJldHVybiB0aGlzLnVwbG9hZE5leHRDaHVuayhpZCwgcGFydE51bWJlciwgY2h1bmtTaXplKTtcbiAgICAgIH0pXG4gICAgICAuY2F0Y2goZXJyID0+IHtcbiAgICAgICAgY29uc3QgcmVzcCA9IGVyciAmJiBlcnIucmVzcG9uc2UgPyBlcnIucmVzcG9uc2UgOiBudWxsO1xuICAgICAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dCAqL1xuICAgICAgICBpZiAocmVzcCAmJiByZXNwLnN0YXR1cyA9PT0gNDAzKSB7XG4gICAgICAgICAgaWYgKHJlc3AuZGF0YSAmJiByZXNwLmRhdGEuRXJyb3IgJiYgcmVzcC5kYXRhLkVycm9yLmNvZGUpIHtcbiAgICAgICAgICAgIGxldCBjb2RlID0gcmVzcC5kYXRhLkVycm9yLmNvZGU7XG5cbiAgICAgICAgICAgIGlmIChBcnJheS5pc0FycmF5KGNvZGUpKSB7XG4gICAgICAgICAgICAgIGNvZGUgPSBjb2RlLnBvcCgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBzd2l0Y2ggKGNvZGUpIHtcbiAgICAgICAgICAgICAgY2FzZSAnUmVxdWVzdFRpbWVUb29Ta2V3ZWQnOlxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLnN0YXJ0UGFydChpZCwgcGFydE51bWJlcik7XG4gICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KG5ldyBGaWxlc3RhY2tFcnJvcignQ2Fubm90IHVwbG9hZCBmaWxlJywgcmVzcC5kYXRhLkVycm9yLCBGaWxlc3RhY2tFcnJvclR5cGUuUkVRVUVTVCkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIHJlc2V0IHByb2dyZXNzIG9uIGZhaWxlZCB1cGxvYWRcbiAgICAgICAgdGhpcy5vblByb2dyZXNzVXBkYXRlKGlkLCBwYXJ0TnVtYmVyLCBwYXJ0Lm9mZnNldCk7XG4gICAgICAgIGNvbnN0IG5leHRDaHVua1NpemUgPSBNYXRoLmNlaWwoY2h1bmtTaXplIC8gMik7XG5cbiAgICAgICAgaWYgKG5leHRDaHVua1NpemUgPCBNSU5fQ0hVTktfU0laRSkge1xuICAgICAgICAgIGRlYnVnKGBbJHtpZH1dIE1pbmltYWwgY2h1bmsgc2l6ZSBsaW1pdC4gVXBsb2FkIGZpbGUgZmFpbGVkIWApO1xuICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdChuZXcgRmlsZXN0YWNrRXJyb3IoJ01pbiBjaHVuayBzaXplIHJlYWNoZWQnLCBlcnIuZGF0YSwgRmlsZXN0YWNrRXJyb3JUeXBlLlJFUVVFU1QpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChzaG91bGRSZXRyeShlcnIpKSB7XG4gICAgICAgICAgZGVidWcoYFske2lkfV0gUmVxdWVzdCBuZXR3b3JrIGVycm9yLiBSZXRyeSB3aXRoIG5ldyBjaHVuayBzaXplOiAke25leHRDaHVua1NpemV9YCk7XG4gICAgICAgICAgcmV0dXJuIHRoaXMudXBsb2FkTmV4dENodW5rKGlkLCBwYXJ0TnVtYmVyLCBuZXh0Q2h1bmtTaXplKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIHJlbGVhc2UgbWVtb3J5XG4gICAgICAgIHBhcnQgPSBudWxsO1xuICAgICAgICBjaHVuayA9IG51bGw7XG5cbiAgICAgICAgcmV0dXJuIHRoaXMucmVqZWN0VXBsb2FkKCdDYW5ub3QgdXBsb2FkIGZpbGUgcGFydCAoRklJKScsIGVycik7XG4gICAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDb21taXQgYWZ0ZXIgdXBsb2FkIGFsbCBjaHVua3Mgb2YgdGhlIHBhcnQgaW4gaWkgbW9kZVxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gaWRcbiAgICogQHBhcmFtIHtGaWxlUGFydH0gcGFydFxuICAgKiBAcmV0dXJuc1xuICAgKiBAbWVtYmVyb2YgUzNVcGxvYWRlclxuICAgKi9cbiAgcHJpdmF0ZSBjb21taXRQYXJ0KGlkOiBzdHJpbmcsIHBhcnROdW1iZXI6IG51bWJlcikge1xuICAgIGNvbnN0IHBheWxvYWQgPSB0aGlzLmdldFBheWxvYWRCeUlkKGlkKTtcbiAgICBjb25zdCBwYXJ0ID0gcGF5bG9hZC5wYXJ0c1twYXJ0TnVtYmVyXTtcblxuICAgIHJldHVybiBGc1JlcXVlc3QucG9zdChcbiAgICAgIGAke3RoaXMuZ2V0VXBsb2FkVXJsKGlkKX0vbXVsdGlwYXJ0L2NvbW1pdGAsXG4gICAgICB7XG4gICAgICAgIC4uLnRoaXMuZ2V0RGVmYXVsdEZpZWxkcyhpZCwgWydhcGlrZXknLCAncmVnaW9uJywgJ3VwbG9hZF9pZCcsICdwb2xpY3knLCAnc2lnbmF0dXJlJywgJ3VyaSddKSxcbiAgICAgICAgc2l6ZTogcGF5bG9hZC5maWxlLnNpemUsXG4gICAgICAgIHBhcnQ6IHBhcnQucGFydE51bWJlciArIDEsXG4gICAgICB9LFxuICAgICAge1xuICAgICAgICBjYW5jZWxUb2tlbjogdGhpcy5jYW5jZWxUb2tlbixcbiAgICAgICAgdGltZW91dDogdGhpcy50aW1lb3V0LFxuICAgICAgICBoZWFkZXJzOiB0aGlzLmdldERlZmF1bHRIZWFkZXJzKGlkKSxcbiAgICAgICAgcmV0cnk6IHRoaXMucmV0cnlDb25maWcsXG4gICAgICB9XG4gICAgKVxuICAgICAgLnRoZW4oKHJlczogRnNSZXNwb25zZSkgPT4ge1xuICAgICAgICBkZWJ1ZyhgWyR7aWR9XSBDb21taXQgUGFydCBudW1iZXIgJHtwYXJ0LnBhcnROdW1iZXJ9LiBSZXNwb25zZTogJU9gLCByZXMuZGF0YSk7XG5cbiAgICAgICAgcmV0dXJuIHJlcztcbiAgICAgIH0pXG4gICAgICAuY2F0Y2goZXJyID0+IHtcbiAgICAgICAgcmV0dXJuIHRoaXMucmVqZWN0VXBsb2FkKCdDYW5ub3QgY29tbWl0IGZpbGUgcGFydCBtZXRhZGF0YScsIGVycik7XG4gICAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDb21wbGV0ZSByZXF1ZXN0IHRvIG1lcmdlIGFsbCBwYXJ0cyBhbmQgZ2V0IGZpbGUgaGFuZGxlIGV0Y1xuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcmV0dXJuc1xuICAgKiBAbWVtYmVyb2YgUzNVcGxvYWRlclxuICAgKi9cbiAgcHJpdmF0ZSBjb21wbGV0ZVJlcXVlc3QoaWQ6IHN0cmluZyk6IFByb21pc2U8YW55PiB7XG4gICAgY29uc3QgcGF5bG9hZCA9IHRoaXMuZ2V0UGF5bG9hZEJ5SWQoaWQpO1xuICAgIGxldCBwYXJ0cyA9IFtdO1xuXG4gICAgZGVidWcoYFske2lkfV0gUnVuIGNvbXBsZXRlIHJlcXVlc3RgKTtcblxuICAgIGNvbnN0IHBhcnRzSGFuZGxlID0gcGF5bG9hZC5wYXJ0cztcbiAgICBjb25zdCBwYXJ0TGVuID0gcGFydHNIYW5kbGUubGVuZ3RoO1xuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBwYXJ0TGVuOyBpKyspIHtcbiAgICAgIGlmIChwYXJ0c0hhbmRsZVtpXS5ldGFnKSB7XG4gICAgICAgIHBhcnRzLnB1c2goeyBwYXJ0X251bWJlcjogaSArIDEsIGV0YWc6IHBhcnRzSGFuZGxlW2ldLmV0YWcgfSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgZGVidWcoYFske2lkfV0gRXRhZ3MgJU9gLCBwYXJ0cyk7XG5cbiAgICByZXR1cm4gRnNSZXF1ZXN0LnBvc3QoXG4gICAgICBgJHt0aGlzLmdldFVwbG9hZFVybChpZCl9L211bHRpcGFydC9jb21wbGV0ZWAsXG4gICAgICB7XG4gICAgICAgIC4uLnRoaXMuZ2V0RGVmYXVsdEZpZWxkcyhpZCwgWydhcGlrZXknLCAncG9saWN5JywgJ3NpZ25hdHVyZScsICd1cmknLCAncmVnaW9uJywgJ3VwbG9hZF9pZCcsICdmaWknLCAnYWx0J10sIHRydWUpLFxuICAgICAgICAvLyBtZXRob2Qgc3BlY2lmaWMga2V5c1xuICAgICAgICBmaWxlbmFtZTogcGF5bG9hZC5maWxlLm5hbWUsXG4gICAgICAgIG1pbWV0eXBlOiBwYXlsb2FkLmZpbGUudHlwZSxcbiAgICAgICAgc2l6ZTogcGF5bG9hZC5maWxlLnNpemUsXG4gICAgICAgIHVwbG9hZF90YWdzOiB0aGlzLnVwbG9hZFRhZ3MgJiYgT2JqZWN0LmtleXModGhpcy51cGxvYWRUYWdzKS5sZW5ndGggPyB0aGlzLnVwbG9hZFRhZ3MgOiB1bmRlZmluZWQsXG4gICAgICAgIHBhcnRzOiBwYXJ0cy5sZW5ndGggPyBwYXJ0cyA6IHVuZGVmaW5lZCxcbiAgICAgIH0sXG4gICAgICB7XG4gICAgICAgIHRpbWVvdXQ6IHRoaXMudGltZW91dCxcbiAgICAgICAgY2FuY2VsVG9rZW46IHRoaXMuY2FuY2VsVG9rZW4sXG4gICAgICAgIGhlYWRlcnM6IHRoaXMuZ2V0RGVmYXVsdEhlYWRlcnMoaWQpLFxuICAgICAgICByZXRyeTogdGhpcy5yZXRyeUNvbmZpZyxcbiAgICAgIH1cbiAgICApXG4gICAgICAudGhlbihyZXMgPT4ge1xuICAgICAgICAvLyBpZiBwYXJ0cyBoYXNudCBiZWVuIG1lcmdlZCwgcmV0cnkgY29tcGxldGUgcmVxdWVzdCBhZ2FpblxuICAgICAgICBpZiAocmVzLnN0YXR1cyA9PT0gMjAyKSB7XG4gICAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIHNldFRpbWVvdXQoXG4gICAgICAgICAgICAgICgpID0+XG4gICAgICAgICAgICAgICAgdGhpcy5jb21wbGV0ZVJlcXVlc3QoaWQpXG4gICAgICAgICAgICAgICAgICAudGhlbihyZXNvbHZlKVxuICAgICAgICAgICAgICAgICAgLmNhdGNoKHJlamVjdCksXG4gICAgICAgICAgICAgIENPTVBMRVRFX1RJTUVPVVRcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyB1cGRhdGUgZmlsZSBvYmplY3RcbiAgICAgICAgbGV0IGZpbGUgPSB0aGlzLmdldFBheWxvYWRCeUlkKGlkKS5maWxlO1xuXG4gICAgICAgIGZpbGUuaGFuZGxlID0gcmVzLmRhdGEuaGFuZGxlO1xuICAgICAgICBmaWxlLnVybCA9IHJlcy5kYXRhLnVybDtcbiAgICAgICAgZmlsZS5jb250YWluZXIgPSByZXMuZGF0YS5jb250YWluZXI7XG4gICAgICAgIGZpbGUua2V5ID0gcmVzLmRhdGEua2V5O1xuICAgICAgICBmaWxlLnVwbG9hZFRhZ3MgPSByZXMuZGF0YS51cGxvYWRfdGFncztcbiAgICAgICAgZmlsZS53b3JrZmxvd3MgPSByZXMuZGF0YS53b3JrZmxvd3M7XG4gICAgICAgIGZpbGUuc3RhdHVzID0gcmVzLmRhdGEuc3RhdHVzO1xuXG4gICAgICAgIHJldHVybiBmaWxlO1xuICAgICAgfSlcbiAgICAgIC5jYXRjaChlcnIgPT4ge1xuICAgICAgICB0aGlzLnNldFBheWxvYWRTdGF0dXMoaWQsIEZpbGVTdGF0ZS5GQUlMRUQpO1xuXG4gICAgICAgIHJldHVybiB0aGlzLnJlamVjdFVwbG9hZCgnQ2Fubm90IGNvbXBsZXRlIGZpbGUnLCBlcnIpO1xuICAgICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogVVVwZ3JhZGUgdXBsb2FkIHByb2dyZXNzIGFuZCBydW4gcHJvZ3Jlc3MgZXZlbnRcbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtzdHJpbmd9IGlkXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBwYXJ0TnVtYmVyXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBsb2FkZWRcbiAgICogQG1lbWJlcm9mIFMzVXBsb2FkZXJcbiAgICovXG4gIHByaXZhdGUgb25Qcm9ncmVzc1VwZGF0ZShpZDogc3RyaW5nLCBwYXJ0TnVtYmVyOiBudW1iZXIsIGxvYWRlZDogbnVtYmVyKSB7XG4gICAgdGhpcy5zZXRQYXJ0RGF0YShpZCwgcGFydE51bWJlciwgJ3Byb2dyZXNzJywgbG9hZGVkKTtcbiAgICB0aGlzLmVtaXRQcm9ncmVzcygpO1xuICB9XG5cbiAgLyoqXG4gICAqIEVtaXRzIG5vcm1hbGl6ZWQgcHJvZ3Jlc3MgZXZlbnRcbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQG1lbWJlcm9mIFMzVXBsb2FkZXJcbiAgICovXG4gIHByaXZhdGUgZW1pdFByb2dyZXNzKCkge1xuICAgIGxldCB0b3RhbFNpemUgPSAwO1xuICAgIGxldCB0b3RhbEJ5dGVzID0gMDtcblxuICAgIGxldCBmaWxlc1Byb2dyZXNzID0ge307XG4gICAgZm9yIChsZXQgaSBpbiB0aGlzLnBheWxvYWRzKSB7XG4gICAgICBjb25zdCBwYXlsb2FkID0gdGhpcy5wYXlsb2Fkc1tpXTtcbiAgICAgIC8vIG9taXQgYWxsIGZhaWxlZCBmaWxlcyBpbiBwcm9ncmVzcyBldmVudFxuICAgICAgLy8gdGhpcyBzaG91bGRuJ3QgaGFwcGVuZCBiZWNhdXNlIG9mIHByb21pc2VzIHJlamVjdGlvbiBpbiBleGVjdXRlLiBMZWZ0IHRvIGJlIHN1cmVcbiAgICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXG4gICAgICBpZiAocGF5bG9hZC5maWxlLnN0YXR1cyA9PT0gRmlsZVN0YXRlLkZBSUxFRCkge1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgdG90YWxQYXJ0cyA9IHBheWxvYWQucGFydHMubWFwKHAgPT4gcC5wcm9ncmVzcyB8fCAwKS5yZWR1Y2UoKGEsIGIpID0+IGEgKyBiLCAwKTtcblxuICAgICAgdG90YWxCeXRlcyA9IHRvdGFsQnl0ZXMgKyB0b3RhbFBhcnRzO1xuXG4gICAgICBmaWxlc1Byb2dyZXNzW2ldID0ge1xuICAgICAgICB0b3RhbEJ5dGVzOiB0b3RhbFBhcnRzLFxuICAgICAgICB0b3RhbFBlcmNlbnQ6IE1hdGgucm91bmQoKHRvdGFsUGFydHMgKiAxMDApIC8gcGF5bG9hZC5maWxlLnNpemUpIHx8IDAsXG4gICAgICB9O1xuXG4gICAgICB0b3RhbFNpemUgPSB0b3RhbFNpemUgKyBwYXlsb2FkLmZpbGUuc2l6ZTtcbiAgICB9XG5cbiAgICBjb25zdCByZXMgPSB7XG4gICAgICB0b3RhbEJ5dGVzOiB0b3RhbEJ5dGVzIHx8IDAsXG4gICAgICB0b3RhbFBlcmNlbnQ6IE1hdGgucm91bmQoKHRvdGFsQnl0ZXMgKiAxMDApIC8gdG90YWxTaXplKSB8fCAwLFxuICAgICAgZmlsZXM6IGZpbGVzUHJvZ3Jlc3MsXG4gICAgfTtcblxuICAgIGRlYnVnKGBVcGxvYWQgcHJvZ3Jlc3MgJU9gLCByZXMpO1xuICAgIHRoaXMuZW1pdCgncHJvZ3Jlc3MnLCByZXMpO1xuICB9XG5cbiAgLyoqXG4gICAqIEFwcGx5IHByb3ZpZGVkIGRhdGEgdG8gZ2l2ZW4gcGF5bG9hZFxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gaWRcbiAgICogQHBhcmFtIHsqfSBkYXRhXG4gICAqIEBtZW1iZXJvZiBTM1VwbG9hZGVyXG4gICAqL1xuICBwcml2YXRlIHVwZGF0ZVBheWxvYWQoaWQ6IHN0cmluZywgZGF0YTogYW55KSB7XG4gICAgdGhpcy5wYXlsb2Fkc1tpZF0gPSB7XG4gICAgICAuLi50aGlzLnBheWxvYWRzW2lkXSxcbiAgICAgIC4uLmRhdGEsXG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTZXRzIGV0YWcgZm9yIHBhcnRcbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtudW1iZXJ9IHBhcnROdW1iZXJcbiAgICogQHBhcmFtIHtzdHJpbmd9IGV0YWdcbiAgICogQG1lbWJlcm9mIFMzVXBsb2FkZXJcbiAgICovXG4gIHByaXZhdGUgc2V0UGFydEVUYWcoaWQ6IHN0cmluZywgcGFydE51bWJlcjogbnVtYmVyLCBldGFnOiBzdHJpbmcpIHtcbiAgICBkZWJ1ZyhgWyR7aWR9XSBTZXQgJHtldGFnfSBldGFnIGZvciBwYXJ0ICR7cGFydE51bWJlcn1gKTtcbiAgICB0aGlzLmdldFBheWxvYWRCeUlkKGlkKS5wYXJ0c1twYXJ0TnVtYmVyXS5ldGFnID0gZXRhZztcbiAgfVxuXG4gIC8qKlxuICAgKiBTZXRzIHBhcnQgdmFsdWUgZm9yIGEga2V5XG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBwYXJ0TnVtYmVyXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBldGFnXG4gICAqIEBtZW1iZXJvZiBTM1VwbG9hZGVyXG4gICAqL1xuICBwcml2YXRlIHNldFBhcnREYXRhKGlkOiBzdHJpbmcsIHBhcnROdW1iZXI6IG51bWJlciwga2V5OiBzdHJpbmcsIHZhbHVlOiBhbnkpIHtcbiAgICBkZWJ1ZyhgWyR7aWR9XSBTZXQgJHtrZXl9ID0gJHt2YWx1ZX0gZm9yIHBhcnQgJHtwYXJ0TnVtYmVyfWApO1xuXG4gICAgY29uc3QgcGF5bG9hZCA9IHRoaXMuZ2V0UGF5bG9hZEJ5SWQoaWQpO1xuXG4gICAgLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cbiAgICBpZiAoIXBheWxvYWQpIHtcbiAgICAgIGRlYnVnKGBbJHtpZH1dIENhbm5vdCBzZXQgJHtrZXl9ID0gJHt2YWx1ZX0gZm9yIHBhcnQgJHtwYXJ0TnVtYmVyfWApO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHBheWxvYWQucGFydHNbcGFydE51bWJlcl1ba2V5XSA9IHZhbHVlO1xuICB9XG5cbiAgLyoqXG4gICAqIFNldCBwYXlsb2FkIGZpbGUgc3RhdGVcbiAgICpcbiAgICogQHBhcmFtIGlkXG4gICAqIEBwYXJhbSBzdGF0dXNcbiAgICovXG4gIHByaXZhdGUgc2V0UGF5bG9hZFN0YXR1cyhpZDogc3RyaW5nLCBzdGF0dXM6IEZpbGVTdGF0ZSkge1xuICAgIGRlYnVnKGBbJHtpZH1dIFNldCBwYXlsb2FkIHN0YXR1cyB0byAke3N0YXR1c31gKTtcbiAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dDogYWRkaXRpb25hbCBjaGVjayBpbiBjYXNlIGlmIGZpbGUgd2lsbCBiZSBkZWxldGVkIGJlZm9yZSBzZXR0aW5nIHN0YXR1cyAqL1xuICAgIGlmICghdGhpcy5wYXlsb2Fkc1tpZF0pIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLnBheWxvYWRzW2lkXS5maWxlLnN0YXR1cyA9IHN0YXR1cztcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGVycm9yIGRldGFpbHMgaWYgcmVzcG9uc2UgZXhpc3RzXG4gICAqXG4gICAqIEBwYXJhbSBlcnJcbiAgICovXG4gIHByaXZhdGUgcGFyc2VFcnJvcihlcnI6IEZzUmVxdWVzdEVycm9yKSB7XG4gICAgaWYgKCFlcnIucmVzcG9uc2UpIHtcbiAgICAgIHJldHVybiB7fTtcbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgY29kZTogZXJyLnJlc3BvbnNlLnN0YXR1cyxcbiAgICAgIGRhdGE6IGVyci5yZXNwb25zZS5kYXRhLFxuICAgICAgaGVhZGVyczogZXJyLnJlc3BvbnNlLmhlYWRlcnMsXG4gICAgfTtcbiAgfVxuXG4gIHByaXZhdGUgcmVqZWN0VXBsb2FkKG1lc3NhZ2U6IHN0cmluZywgZXJyOiBGc1JlcXVlc3RFcnJvcikge1xuICAgIGlmIChlcnIgaW5zdGFuY2VvZiBGc1JlcXVlc3RFcnJvciAmJiBlcnIuY29kZSA9PT0gRnNSZXF1ZXN0RXJyb3JDb2RlLkFCT1JURUQpIHtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdChuZXcgRmlsZXN0YWNrRXJyb3IobWVzc2FnZSwgeyByZWFzb246IGVyci5tZXNzYWdlIH0sIEZpbGVzdGFja0Vycm9yVHlwZS5BQk9SVEVEKSk7XG4gICAgfVxuICAgIHJldHVybiBQcm9taXNlLnJlamVjdChuZXcgRmlsZXN0YWNrRXJyb3IobWVzc2FnZSwgdGhpcy5wYXJzZUVycm9yKGVyciksIEZpbGVzdGFja0Vycm9yVHlwZS5SRVFVRVNUKSk7XG4gIH1cbn1cbiJdfQ==