UNPKG

webdriverio-automation

Version:

WebdriverIO-Automation android ios project

235 lines (184 loc) 26 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.uploadFile = uploadFile; exports.downloadFile = downloadFile; require("source-map-support/register"); var _lodash = _interopRequireDefault(require("lodash")); var _fs = _interopRequireDefault(require("./fs")); var _url = _interopRequireDefault(require("url")); var _bluebird = _interopRequireDefault(require("bluebird")); var _util = require("./util"); var _logger = _interopRequireDefault(require("./logger")); var _jsftp = _interopRequireDefault(require("jsftp")); var _timing = _interopRequireDefault(require("./timing")); var _axios = _interopRequireDefault(require("axios")); var _formData = _interopRequireDefault(require("form-data")); function toAxiosAuth(auth) { if (!_lodash.default.isPlainObject(auth)) { return null; } const axiosAuth = { username: auth.username || auth.user, password: auth.password || auth.pass }; return axiosAuth.username && axiosAuth.password ? axiosAuth : null; } async function uploadFileToHttp(localFileStream, parsedUri, uploadOptions = {}) { const { method = 'POST', timeout = 5000, headers, auth, fileFieldName = 'file', formFields } = uploadOptions; const { protocol, href } = parsedUri; const requestOpts = { url: href, method, timeout }; const axiosAuth = toAxiosAuth(auth); if (axiosAuth) { requestOpts.auth = axiosAuth; } const form = new _formData.default(); form.append(fileFieldName, localFileStream); if (formFields) { let pairs = []; if (_lodash.default.isArray(formFields)) { pairs = formFields; } else if (_lodash.default.isPlainObject(formFields)) { pairs = _lodash.default.toPairs(formFields); } for (const [key, value] of pairs) { if (_lodash.default.toLower(key) !== _lodash.default.toLower(fileFieldName)) { form.append(key, value); } } } requestOpts.headers = Object.assign({}, _lodash.default.isPlainObject(headers) ? headers : {}, form.getHeaders()); _logger.default.debug(`${protocol} upload options (ex. form data): ${JSON.stringify(requestOpts)}`); requestOpts.data = form; await (0, _axios.default)(requestOpts); } async function uploadFileToFtp(localFileStream, parsedUri, uploadOptions = {}) { const { auth, user, pass } = uploadOptions; const { hostname, port, protocol, pathname } = parsedUri; const ftpOpts = { host: hostname, port: port || 21 }; if ((auth === null || auth === void 0 ? void 0 : auth.user) && (auth === null || auth === void 0 ? void 0 : auth.pass) || user && pass) { ftpOpts.user = (auth === null || auth === void 0 ? void 0 : auth.user) || user; ftpOpts.pass = (auth === null || auth === void 0 ? void 0 : auth.pass) || pass; } _logger.default.debug(`${protocol} upload options: ${JSON.stringify(ftpOpts)}`); return await new _bluebird.default((resolve, reject) => { new _jsftp.default(ftpOpts).put(localFileStream, pathname, err => { if (err) { reject(err); } else { resolve(); } }); }); } async function uploadFile(localPath, remoteUri, uploadOptions = {}) { if (!(await _fs.default.exists(localPath))) { throw new Error(`'${localPath}' does not exists or is not accessible`); } const { isMetered = true } = uploadOptions; const parsedUri = _url.default.parse(remoteUri); const { size } = await _fs.default.stat(localPath); if (isMetered) { _logger.default.info(`Uploading '${localPath}' of ${(0, _util.toReadableSizeString)(size)} size to '${remoteUri}'...`); } const timer = new _timing.default().start(); if (['http:', 'https:'].includes(parsedUri.protocol)) { await uploadFileToHttp(_fs.default.createReadStream(localPath), parsedUri, uploadOptions); } else if (parsedUri.protocol === 'ftp:') { await uploadFileToFtp(_fs.default.createReadStream(localPath), parsedUri, uploadOptions); } else { throw new Error(`Cannot upload the file at '${localPath}' to '${remoteUri}'. ` + `Unsupported remote protocol '${parsedUri.protocol}'. ` + `Only http/https and ftp/ftps protocols are supported.`); } if (isMetered) { _logger.default.info(`Uploaded '${localPath}' of ${(0, _util.toReadableSizeString)(size)} size in ${timer.getDuration().asSeconds.toFixed(3)}s`); } } async function downloadFile(remoteUrl, dstPath, downloadOptions = {}) { const { isMetered = true, auth, timeout = 5000, headers } = downloadOptions; const requestOpts = { url: remoteUrl, responseType: 'stream', timeout }; const axiosAuth = toAxiosAuth(auth); if (axiosAuth) { requestOpts.auth = axiosAuth; } if (_lodash.default.isPlainObject(headers)) { requestOpts.headers = headers; } const timer = new _timing.default().start(); let responseLength; try { const writer = _fs.default.createWriteStream(dstPath); const { data: responseStream, headers: responseHeaders } = await (0, _axios.default)(requestOpts); responseLength = parseInt(responseHeaders['content-length'], 10); responseStream.pipe(writer); await new _bluebird.default((resolve, reject) => { responseStream.once('error', reject); writer.once('finish', resolve); writer.once('error', e => { responseStream.unpipe(writer); reject(e); }); }); } catch (err) { throw new Error(`Cannot download the file from ${remoteUrl}: ${err.message}`); } const { size } = await _fs.default.stat(dstPath); if (responseLength && size !== responseLength) { await _fs.default.rimraf(dstPath); throw new Error(`The size of the file downloaded from ${remoteUrl} (${size} bytes) ` + `differs from the one in Content-Length response header (${responseLength} bytes)`); } if (isMetered) { const secondsElapsed = timer.getDuration().asSeconds; _logger.default.debug(`${remoteUrl} (${(0, _util.toReadableSizeString)(size)}) ` + `has been downloaded to '${dstPath}' in ${secondsElapsed.toFixed(3)}s`); if (secondsElapsed >= 2) { const bytesPerSec = Math.floor(size / secondsElapsed); _logger.default.debug(`Approximate download speed: ${(0, _util.toReadableSizeString)(bytesPerSec)}/s`); } } }require('source-map-support').install(); //# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImxpYi9uZXQuanMiXSwibmFtZXMiOlsidG9BeGlvc0F1dGgiLCJhdXRoIiwiXyIsImlzUGxhaW5PYmplY3QiLCJheGlvc0F1dGgiLCJ1c2VybmFtZSIsInVzZXIiLCJwYXNzd29yZCIsInBhc3MiLCJ1cGxvYWRGaWxlVG9IdHRwIiwibG9jYWxGaWxlU3RyZWFtIiwicGFyc2VkVXJpIiwidXBsb2FkT3B0aW9ucyIsIm1ldGhvZCIsInRpbWVvdXQiLCJoZWFkZXJzIiwiZmlsZUZpZWxkTmFtZSIsImZvcm1GaWVsZHMiLCJwcm90b2NvbCIsImhyZWYiLCJyZXF1ZXN0T3B0cyIsInVybCIsImZvcm0iLCJGb3JtRGF0YSIsImFwcGVuZCIsInBhaXJzIiwiaXNBcnJheSIsInRvUGFpcnMiLCJrZXkiLCJ2YWx1ZSIsInRvTG93ZXIiLCJPYmplY3QiLCJhc3NpZ24iLCJnZXRIZWFkZXJzIiwibG9nIiwiZGVidWciLCJKU09OIiwic3RyaW5naWZ5IiwiZGF0YSIsInVwbG9hZEZpbGVUb0Z0cCIsImhvc3RuYW1lIiwicG9ydCIsInBhdGhuYW1lIiwiZnRwT3B0cyIsImhvc3QiLCJCIiwicmVzb2x2ZSIsInJlamVjdCIsIkZ0cCIsInB1dCIsImVyciIsInVwbG9hZEZpbGUiLCJsb2NhbFBhdGgiLCJyZW1vdGVVcmkiLCJmcyIsImV4aXN0cyIsIkVycm9yIiwiaXNNZXRlcmVkIiwicGFyc2UiLCJzaXplIiwic3RhdCIsImluZm8iLCJ0aW1lciIsIlRpbWVyIiwic3RhcnQiLCJpbmNsdWRlcyIsImNyZWF0ZVJlYWRTdHJlYW0iLCJnZXREdXJhdGlvbiIsImFzU2Vjb25kcyIsInRvRml4ZWQiLCJkb3dubG9hZEZpbGUiLCJyZW1vdGVVcmwiLCJkc3RQYXRoIiwiZG93bmxvYWRPcHRpb25zIiwicmVzcG9uc2VUeXBlIiwicmVzcG9uc2VMZW5ndGgiLCJ3cml0ZXIiLCJjcmVhdGVXcml0ZVN0cmVhbSIsInJlc3BvbnNlU3RyZWFtIiwicmVzcG9uc2VIZWFkZXJzIiwicGFyc2VJbnQiLCJwaXBlIiwib25jZSIsImUiLCJ1bnBpcGUiLCJtZXNzYWdlIiwicmltcmFmIiwic2Vjb25kc0VsYXBzZWQiLCJieXRlc1BlclNlYyIsIk1hdGgiLCJmbG9vciJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7O0FBQUE7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBR0EsU0FBU0EsV0FBVCxDQUFzQkMsSUFBdEIsRUFBNEI7QUFDMUIsTUFBSSxDQUFDQyxnQkFBRUMsYUFBRixDQUFnQkYsSUFBaEIsQ0FBTCxFQUE0QjtBQUMxQixXQUFPLElBQVA7QUFDRDs7QUFFRCxRQUFNRyxTQUFTLEdBQUc7QUFDaEJDLElBQUFBLFFBQVEsRUFBRUosSUFBSSxDQUFDSSxRQUFMLElBQWlCSixJQUFJLENBQUNLLElBRGhCO0FBRWhCQyxJQUFBQSxRQUFRLEVBQUVOLElBQUksQ0FBQ00sUUFBTCxJQUFpQk4sSUFBSSxDQUFDTztBQUZoQixHQUFsQjtBQUlBLFNBQVFKLFNBQVMsQ0FBQ0MsUUFBVixJQUFzQkQsU0FBUyxDQUFDRyxRQUFqQyxHQUE2Q0gsU0FBN0MsR0FBeUQsSUFBaEU7QUFDRDs7QUFFRCxlQUFlSyxnQkFBZixDQUFpQ0MsZUFBakMsRUFBa0RDLFNBQWxELEVBQTZEQyxhQUFhLEdBQUcsRUFBN0UsRUFBaUY7QUFDL0UsUUFBTTtBQUNKQyxJQUFBQSxNQUFNLEdBQUcsTUFETDtBQUVKQyxJQUFBQSxPQUFPLEdBQUcsSUFGTjtBQUdKQyxJQUFBQSxPQUhJO0FBSUpkLElBQUFBLElBSkk7QUFLSmUsSUFBQUEsYUFBYSxHQUFHLE1BTFo7QUFNSkMsSUFBQUE7QUFOSSxNQU9GTCxhQVBKO0FBUUEsUUFBTTtBQUNKTSxJQUFBQSxRQURJO0FBRUpDLElBQUFBO0FBRkksTUFHRlIsU0FISjtBQUtBLFFBQU1TLFdBQVcsR0FBRztBQUNsQkMsSUFBQUEsR0FBRyxFQUFFRixJQURhO0FBRWxCTixJQUFBQSxNQUZrQjtBQUdsQkMsSUFBQUE7QUFIa0IsR0FB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QUlHLGNBQWMsSUFBSWhCLElBQUksS0FBS2dCLGNBQS9CLEVBQStDO0FBQzdDLFVBQU1yQixZQUFHZ0MsTUFBSCxDQUFVZCxPQUFWLENBQU47QUFDQSxVQUFNLElBQUloQixLQUFKLENBQVcsd0NBQXVDZSxTQUFVLEtBQUlaLElBQUssVUFBM0QsR0FDYiwyREFBMERnQixjQUFlLFNBRHRFLENBQU47QUFFRDs7QUFDRCxNQUFJbEIsU0FBSixFQUFlO0FBQ2IsVUFBTThCLGNBQWMsR0FBR3pCLEtBQUssQ0FBQ0ssV0FBTixHQUFvQkMsU0FBM0M7O0FBQ0FsQyxvQkFBSUMsS0FBSixDQUFXLEdBQUVvQyxTQUFVLEtBQUksZ0NBQXFCWixJQUFyQixDQUEyQixJQUE1QyxHQUNQLDJCQUEwQmEsT0FBUSxRQUFPZSxjQUFjLENBQUNsQixPQUFmLENBQXVCLENBQXZCLENBQTBCLEdBRHRFOztBQUVBLFFBQUlrQixjQUFjLElBQUksQ0FBdEIsRUFBeUI7QUFDdkIsWUFBTUMsV0FBVyxHQUFHQyxJQUFJLENBQUNDLEtBQUwsQ0FBVy9CLElBQUksR0FBRzRCLGNBQWxCLENBQXBCOztBQUNBckQsc0JBQUlDLEtBQUosQ0FBVywrQkFBOEIsZ0NBQXFCcUQsV0FBckIsQ0FBa0MsSUFBM0U7QUFDRDtBQUNGO0FBQ0YiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgXyBmcm9tICdsb2Rhc2gnO1xuaW1wb3J0IGZzIGZyb20gJy4vZnMnO1xuaW1wb3J0IHVybCBmcm9tICd1cmwnO1xuaW1wb3J0IEIgZnJvbSAnYmx1ZWJpcmQnO1xuaW1wb3J0IHsgdG9SZWFkYWJsZVNpemVTdHJpbmcgfSBmcm9tICcuL3V0aWwnO1xuaW1wb3J0IGxvZyBmcm9tICcuL2xvZ2dlcic7XG5pbXBvcnQgRnRwIGZyb20gJ2pzZnRwJztcbmltcG9ydCBUaW1lciBmcm9tICcuL3RpbWluZyc7XG5pbXBvcnQgYXhpb3MgZnJvbSAnYXhpb3MnO1xuaW1wb3J0IEZvcm1EYXRhIGZyb20gJ2Zvcm0tZGF0YSc7XG5cblxuZnVuY3Rpb24gdG9BeGlvc0F1dGggKGF1dGgpIHtcbiAgaWYgKCFfLmlzUGxhaW5PYmplY3QoYXV0aCkpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIGNvbnN0IGF4aW9zQXV0aCA9IHtcbiAgICB1c2VybmFtZTogYXV0aC51c2VybmFtZSB8fCBhdXRoLnVzZXIsXG4gICAgcGFzc3dvcmQ6IGF1dGgucGFzc3dvcmQgfHwgYXV0aC5wYXNzLFxuICB9O1xuICByZXR1cm4gKGF4aW9zQXV0aC51c2VybmFtZSAmJiBheGlvc0F1dGgucGFzc3dvcmQpID8gYXhpb3NBdXRoIDogbnVsbDtcbn1cblxuYXN5bmMgZnVuY3Rpb24gdXBsb2FkRmlsZVRvSHR0cCAobG9jYWxGaWxlU3RyZWFtLCBwYXJzZWRVcmksIHVwbG9hZE9wdGlvbnMgPSB7fSkge1xuICBjb25zdCB7XG4gICAgbWV0aG9kID0gJ1BPU1QnLFxuICAgIHRpbWVvdXQgPSA1MDAwLFxuICAgIGhlYWRlcnMsXG4gICAgYXV0aCxcbiAgICBmaWxlRmllbGROYW1lID0gJ2ZpbGUnLFxuICAgIGZvcm1GaWVsZHMsXG4gIH0gPSB1cGxvYWRPcHRpb25zO1xuICBjb25zdCB7XG4gICAgcHJvdG9jb2wsXG4gICAgaHJlZixcbiAgfSA9IHBhcnNlZFVyaTtcblxuICBjb25zdCByZXF1ZXN0T3B0cyA9IHtcbiAgICB1cmw6IGhyZWYsXG4gICAgbWV0aG9kLFxuICAgIHRpbWVvdXQsXG4gIH07XG4gIGNvbnN0IGF4aW9zQXV0aCA9IHRvQXhpb3NBdXRoKGF1dGgpO1xuICBpZiAoYXhpb3NBdXRoKSB7XG4gICAgcmVxdWVzdE9wdHMuYXV0aCA9IGF4aW9zQXV0aDtcbiAgfVxuICBjb25zdCBmb3JtID0gbmV3IEZvcm1EYXRhKCk7XG4gIGZvcm0uYXBwZW5kKGZpbGVGaWVsZE5hbWUsIGxvY2FsRmlsZVN0cmVhbSk7XG4gIGlmIChmb3JtRmllbGRzKSB7XG4gICAgbGV0IHBhaXJzID0gW107XG4gICAgaWYgKF8uaXNBcnJheShmb3JtRmllbGRzKSkge1xuICAgICAgcGFpcnMgPSBmb3JtRmllbGRzO1xuICAgIH0gZWxzZSBpZiAoXy5pc1BsYWluT2JqZWN0KGZvcm1GaWVsZHMpKSB7XG4gICAgICBwYWlycyA9IF8udG9QYWlycyhmb3JtRmllbGRzKTtcbiAgICB9XG4gICAgZm9yIChjb25zdCBba2V5LCB2YWx1ZV0gb2YgcGFpcnMpIHtcbiAgICAgIGlmIChfLnRvTG93ZXIoa2V5KSAhPT0gXy50b0xvd2VyKGZpbGVGaWVsZE5hbWUpKSB7XG4gICAgICAgIGZvcm0uYXBwZW5kKGtleSwgdmFsdWUpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuICByZXF1ZXN0T3B0cy5oZWFkZXJzID0gT2JqZWN0LmFzc2lnbih7fSwgXy5pc1BsYWluT2JqZWN0KGhlYWRlcnMpID8gaGVhZGVycyA6IHt9LCBmb3JtLmdldEhlYWRlcnMoKSk7XG5cbiAgLy8gZXhjbHVkZSBmb3JtIGRhdGEgZnJvbSB0aGUgbG9nIHNpbmNlIGl0J2xsIGNvbnRhaW4gdGhlIGVudGlyZSByZWNvcmRlZCB2aWRlb1xuICBsb2cuZGVidWcoYCR7cHJvdG9jb2x9IHVwbG9hZCBvcHRpb25zIChleC4gZm9ybSBkYXRhKTogJHtKU09OLnN0cmluZ2lmeShyZXF1ZXN0T3B0cyl9YCk7XG4gIHJlcXVlc3RPcHRzLmRhdGEgPSBmb3JtO1xuXG4gIGF3YWl0IGF4aW9zKHJlcXVlc3RPcHRzKTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gdXBsb2FkRmlsZVRvRnRwIChsb2NhbEZpbGVTdHJlYW0sIHBhcnNlZFVyaSwgdXBsb2FkT3B0aW9ucyA9IHt9KSB7XG4gIGNvbnN0IHtcbiAgICBhdXRoLFxuICAgIHVzZXIsXG4gICAgcGFzcyxcbiAgfSA9IHVwbG9hZE9wdGlvbnM7XG4gIGNvbnN0IHtcbiAgICBob3N0bmFtZSxcbiAgICBwb3J0LFxuICAgIHByb3RvY29sLFxuICAgIHBhdGhuYW1lLFxuICB9ID0gcGFyc2VkVXJpO1xuXG4gIGNvbnN0IGZ0cE9wdHMgPSB7XG4gICAgaG9zdDogaG9zdG5hbWUsXG4gICAgcG9ydDogcG9ydCB8fCAyMSxcbiAgfTtcbiAgaWYgKChhdXRoPy51c2VyICYmIGF1dGg/LnBhc3MpIHx8ICh1c2VyICYmIHBhc3MpKSB7XG4gICAgZnRwT3B0cy51c2VyID0gYXV0aD8udXNlciB8fCB1c2VyO1xuICAgIGZ0cE9wdHMucGFzcyA9IGF1dGg/LnBhc3MgfHwgcGFzcztcbiAgfVxuICBsb2cuZGVidWcoYCR7cHJvdG9jb2x9IHVwbG9hZCBvcHRpb25zOiAke0pTT04uc3RyaW5naWZ5KGZ0cE9wdHMpfWApO1xuICByZXR1cm4gYXdhaXQgbmV3IEIoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgIG5ldyBGdHAoZnRwT3B0cykucHV0KGxvY2FsRmlsZVN0cmVhbSwgcGF0aG5hbWUsIChlcnIpID0+IHtcbiAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgcmVqZWN0KGVycik7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXNvbHZlKCk7XG4gICAgICB9XG4gICAgfSk7XG4gIH0pO1xufVxuXG4vKipcbiAqIEB0eXBlZGVmIHtPYmplY3R9IEF1dGhDcmVkZW50aWFsc1xuICogQHByb3BlcnR5IHtzdHJpbmd9IHVzZXIgLSBOb24tZW1wdHkgdXNlciBuYW1lXG4gKiBAcHJvcGVydHkge3N0cmluZ30gcGFzcyAtIE5vbi1lbXB0eSBwYXNzd29yZFxuICovXG5cbi8qKlxuICogQHR5cGVkZWYge09iamVjdH0gRnRwVXBsb2FkT3B0aW9uc1xuICogQHByb3BlcnR5IHtib29sZWFufSBpc01ldGVyZWQgW3RydWVdIC0gV2hldGhlciB0byBsb2cgdGhlIGFjdHVhbCB1cGxvYWQgcGVyZm9ybWFuY2VcbiAqIChlLmcuIHRpbWluZ3MgYW5kIHNwZWVkKVxuICogQHByb3BlcnR5IHtBdXRoQ3JlZGVudGlhbHN9IGF1dGhcbiAqL1xuXG4vKipcbiAqIEB0eXBlZGVmIHtPYmplY3R9IEh0dHBVcGxvYWRPcHRpb25zXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IGlzTWV0ZXJlZCBbdHJ1ZV0gLSBXaGV0aGVyIHRvIGxvZyB0aGUgYWN0dWFsIHVwbG9hZCBwZXJmb3JtYW5jZVxuICogKGUuZy4gdGltaW5ncyBhbmQgc3BlZWQpXG4gKiBAcHJvcGVydHkge3N0cmluZ30gbWV0aG9kIFtQT1NUXSAtIFRoZSBIVFRQIG1ldGhvZCB1c2VkIGZvciBmaWxlIHVwbG9hZFxuICogQHByb3BlcnR5IHtBdXRoQ3JlZGVudGlhbHN9IGF1dGhcbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSB0aW1lb3V0IFs1MDAwXSAtIFRoZSBhY3R1YWwgcmVxdWVzdCB0aW1lb3V0IGluIG1pbGxpc2Vjb25kc1xuICogQHByb3BlcnR5IHtPYmplY3R9IGhlYWRlcnMgLSBBZGRpdGlvbmFsIHJlcXVlc3QgaGVhZGVycyBtYXBwaW5nXG4gKiBAcHJvcGVydHkge3N0cmluZ30gZmlsZUZpZWxkTmFtZSBbZmlsZV0gLSBUaGUgbmFtZSBvZiB0aGUgZm9ybSBmaWVsZCBjb250YWluaW5nIHRoZSBmaWxlXG4gKiBjb250ZW50IHRvIGJlIHVwbG9hZGVkXG4gKiBAcHJvcGVydHkge0FycmF5PFBhaXI+fE9iamVjdH0gZm9ybUZpZWxkcyAtIFRoZSBhZGRpdGlvbmFsIGZvcm0gZmllbGRzXG4gKiB0byBiZSBpbmNsdWRlZCBpbnRvIHRoZSB1cGxvYWQgcmVxdWVzdC4gVGhpcyBwcm9wZXJ0eSBpcyBvbmx5IGNvbnNpZGVyZWQgaWZcbiAqIGBmaWxlRmllbGROYW1lYCBpcyBzZXRcbiAqL1xuXG4vKipcbiAqIFVwbG9hZHMgdGhlIGdpdmVuIGZpbGUgdG8gYSByZW1vdGUgbG9jYXRpb24uIEhUVFAoUykgYW5kIEZUUFxuICogcHJvdG9jb2xzIGFyZSBzdXBwb3J0ZWQuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IGxvY2FsUGF0aCAtIFRoZSBwYXRoIHRvIGEgZmlsZSBvbiB0aGUgbG9jYWwgc3RvcmFnZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSByZW1vdGVVcmkgLSBUaGUgcmVtb3RlIFVSSSB0byB1cGxvYWQgdGhlIGZpbGUgdG8uXG4gKiBAcGFyYW0gez9GdHBVcGxvYWRPcHRpb25zfEh0dHBVcGxvYWRPcHRpb25zfSB1cGxvYWRPcHRpb25zXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIHVwbG9hZEZpbGUgKGxvY2FsUGF0aCwgcmVtb3RlVXJpLCB1cGxvYWRPcHRpb25zID0ge30pIHtcbiAgaWYgKCFhd2FpdCBmcy5leGlzdHMobG9jYWxQYXRoKSkge1xuICAgIHRocm93IG5ldyBFcnJvciAoYCcke2xvY2FsUGF0aH0nIGRvZXMgbm90IGV4aXN0cyBvciBpcyBub3QgYWNjZXNzaWJsZWApO1xuICB9XG5cbiAgY29uc3Qge1xuICAgIGlzTWV0ZXJlZCA9IHRydWUsXG4gIH0gPSB1cGxvYWRPcHRpb25zO1xuXG4gIGNvbnN0IHBhcnNlZFVyaSA9IHVybC5wYXJzZShyZW1vdGVVcmkpO1xuICBjb25zdCB7c2l6ZX0gPSBhd2FpdCBmcy5zdGF0KGxvY2FsUGF0aCk7XG4gIGlmIChpc01ldGVyZWQpIHtcbiAgICBsb2cuaW5mbyhgVXBsb2FkaW5nICcke2xvY2FsUGF0aH0nIG9mICR7dG9SZWFkYWJsZVNpemVTdHJpbmcoc2l6ZSl9IHNpemUgdG8gJyR7cmVtb3RlVXJpfScuLi5gKTtcbiAgfVxuICBjb25zdCB0aW1lciA9IG5ldyBUaW1lcigpLnN0YXJ0KCk7XG4gIGlmIChbJ2h0dHA6JywgJ2h0dHBzOiddLmluY2x1ZGVzKHBhcnNlZFVyaS5wcm90b2NvbCkpIHtcbiAgICBhd2FpdCB1cGxvYWRGaWxlVG9IdHRwKGZzLmNyZWF0ZVJlYWRTdHJlYW0obG9jYWxQYXRoKSwgcGFyc2VkVXJpLCB1cGxvYWRPcHRpb25zKTtcbiAgfSBlbHNlIGlmIChwYXJzZWRVcmkucHJvdG9jb2wgPT09ICdmdHA6Jykge1xuICAgIGF3YWl0IHVwbG9hZEZpbGVUb0Z0cChmcy5jcmVhdGVSZWFkU3RyZWFtKGxvY2FsUGF0aCksIHBhcnNlZFVyaSwgdXBsb2FkT3B0aW9ucyk7XG4gIH0gZWxzZSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBDYW5ub3QgdXBsb2FkIHRoZSBmaWxlIGF0ICcke2xvY2FsUGF0aH0nIHRvICcke3JlbW90ZVVyaX0nLiBgICtcbiAgICAgIGBVbnN1cHBvcnRlZCByZW1vdGUgcHJvdG9jb2wgJyR7cGFyc2VkVXJpLnByb3RvY29sfScuIGAgK1xuICAgICAgYE9ubHkgaHR0cC9odHRwcyBhbmQgZnRwL2Z0cHMgcHJvdG9jb2xzIGFyZSBzdXBwb3J0ZWQuYCk7XG4gIH1cbiAgaWYgKGlzTWV0ZXJlZCkge1xuICAgIGxvZy5pbmZvKGBVcGxvYWRlZCAnJHtsb2NhbFBhdGh9JyBvZiAke3RvUmVhZGFibGVTaXplU3RyaW5nKHNpemUpfSBzaXplIGluICR7dGltZXIuZ2V0RHVyYXRpb24oKS5hc1NlY29uZHMudG9GaXhlZCgzKX1zYCk7XG4gIH1cbn1cblxuLyoqXG4gKiBAdHlwZWRlZiB7T2JqZWN0fSBEb3dubG9hZE9wdGlvbnNcbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gaXNNZXRlcmVkIFt0cnVlXSAtIFdoZXRoZXIgdG8gbG9nIHRoZSBhY3R1YWwgZG93bmxvYWQgcGVyZm9ybWFuY2VcbiAqIChlLmcuIHRpbWluZ3MgYW5kIHNwZWVkKVxuICogQHByb3BlcnR5IHtBdXRoQ3JlZGVudGlhbHN9IGF1dGhcbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSB0aW1lb3V0IFs1MDAwXSAtIFRoZSBhY3R1YWwgcmVxdWVzdCB0aW1lb3V0IGluIG1pbGxpc2Vjb25kc1xuICogQHByb3BlcnR5IHtPYmplY3R9IGhlYWRlcnMgLSBSZXF1ZXN0IGhlYWRlcnMgbWFwcGluZ1xuICovXG5cbi8qKlxuICogRG93bmxvYWRzIHRoZSBnaXZlbiBmaWxlIHZpYSBIVFRQKFMpXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IHJlbW90ZVVybCAtIFRoZSByZW1vdGUgdXJsXG4gKiBAcGFyYW0ge3N0cmluZ30gZHN0UGF0aCAtIFRoZSBsb2NhbCBwYXRoIHRvIGRvd25sb2FkIHRoZSBmaWxlIHRvXG4gKiBAcGFyYW0gez9Eb3dubG9hZE9wdGlvbnN9IGRvd25sb2FkT3B0aW9uc1xuICogQHRocm93cyB7RXJyb3J9IElmIGRvd25sb2FkIG9wZXJhdGlvbiBmYWlsc1xuICovXG5hc3luYyBmdW5jdGlvbiBkb3dubG9hZEZpbGUgKHJlbW90ZVVybCwgZHN0UGF0aCwgZG93bmxvYWRPcHRpb25zID0ge30pIHtcbiAgY29uc3Qge1xuICAgIGlzTWV0ZXJlZCA9IHRydWUsXG4gICAgYXV0aCxcbiAgICB0aW1lb3V0ID0gNTAwMCxcbiAgICBoZWFkZXJzLFxuICB9ID0gZG93bmxvYWRPcHRpb25zO1xuXG4gIGNvbnN0IHJlcXVlc3RPcHRzID0ge1xuICAgIHVybDogcmVtb3RlVXJsLFxuICAgIHJlc3BvbnNlVHlwZTogJ3N0cmVhbScsXG4gICAgdGltZW91dCxcbiAgfTtcbiAgY29uc3QgYXhpb3NBdXRoID0gdG9BeGlvc0F1dGgoYXV0aCk7XG4gIGlmIChheGlvc0F1dGgpIHtcbiAgICByZXF1ZXN0T3B0cy5hdXRoID0gYXhpb3NBdXRoO1xuICB9XG4gIGlmIChfLmlzUGxhaW5PYmplY3QoaGVhZGVycykpIHtcbiAgICByZXF1ZXN0T3B0cy5oZWFkZXJzID0gaGVhZGVycztcbiAgfVxuXG4gIGNvbnN0IHRpbWVyID0gbmV3IFRpbWVyKCkuc3RhcnQoKTtcbiAgbGV0IHJlc3BvbnNlTGVuZ3RoO1xuICB0cnkge1xuICAgIGNvbnN0IHdyaXRlciA9IGZzLmNyZWF0ZVdyaXRlU3RyZWFtKGRzdFBhdGgpO1xuICAgIGNvbnN0IHtcbiAgICAgIGRhdGE6IHJlc3BvbnNlU3RyZWFtLFxuICAgICAgaGVhZGVyczogcmVzcG9uc2VIZWFkZXJzLFxuICAgIH0gPSBhd2FpdCBheGlvcyhyZXF1ZXN0T3B0cyk7XG4gICAgcmVzcG9uc2VMZW5ndGggPSBwYXJzZUludChyZXNwb25zZUhlYWRlcnNbJ2NvbnRlbnQtbGVuZ3RoJ10sIDEwKTtcbiAgICByZXNwb25zZVN0cmVhbS5waXBlKHdyaXRlcik7XG5cbiAgICBhd2FpdCBuZXcgQigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICByZXNwb25zZVN0cmVhbS5vbmNlKCdlcnJvcicsIHJlamVjdCk7XG4gICAgICB3cml0ZXIub25jZSgnZmluaXNoJywgcmVzb2x2ZSk7XG4gICAgICB3cml0ZXIub25jZSgnZXJyb3InLCAoZSkgPT4ge1xuICAgICAgICByZXNwb25zZVN0cmVhbS51bnBpcGUod3JpdGVyKTtcbiAgICAgICAgcmVqZWN0KGUpO1xuICAgICAgfSk7XG4gICAgfSk7XG4gIH0gY2F0Y2ggKGVycikge1xuICAgIHRocm93IG5ldyBFcnJvcihgQ2Fubm90IGRvd25sb2FkIHRoZSBmaWxlIGZyb20gJHtyZW1vdGVVcmx9OiAke2Vyci5tZXNzYWdlfWApO1xuICB9XG5cbiAgY29uc3Qge3NpemV9ID0gYXdhaXQgZnMuc3RhdChkc3RQYXRoKTtcbiAgaWYgKHJlc3BvbnNlTGVuZ3RoICYmIHNpemUgIT09IHJlc3BvbnNlTGVuZ3RoKSB7XG4gICAgYXdhaXQgZnMucmltcmFmKGRzdFBhdGgpO1xuICAgIHRocm93IG5ldyBFcnJvcihgVGhlIHNpemUgb2YgdGhlIGZpbGUgZG93bmxvYWRlZCBmcm9tICR7cmVtb3RlVXJsfSAoJHtzaXplfSBieXRlcykgYCArXG4gICAgICBgZGlmZmVycyBmcm9tIHRoZSBvbmUgaW4gQ29udGVudC1MZW5ndGggcmVzcG9uc2UgaGVhZGVyICgke3Jlc3BvbnNlTGVuZ3RofSBieXRlcylgKTtcbiAgfVxuICBpZiAoaXNNZXRlcmVkKSB7XG4gICAgY29uc3Qgc2Vjb25kc0VsYXBzZWQgPSB0aW1lci5nZXREdXJhdGlvbigpLmFzU2Vjb25kcztcbiAgICBsb2cuZGVidWcoYCR7cmVtb3RlVXJsfSAoJHt0b1JlYWRhYmxlU2l6ZVN0cmluZyhzaXplKX0pIGAgK1xuICAgICAgYGhhcyBiZWVuIGRvd25sb2FkZWQgdG8gJyR7ZHN0UGF0aH0nIGluICR7c2Vjb25kc0VsYXBzZWQudG9GaXhlZCgzKX1zYCk7XG4gICAgaWYgKHNlY29uZHNFbGFwc2VkID49IDIpIHtcbiAgICAgIGNvbnN0IGJ5dGVzUGVyU2VjID0gTWF0aC5mbG9vcihzaXplIC8gc2Vjb25kc0VsYXBzZWQpO1xuICAgICAgbG9nLmRlYnVnKGBBcHByb3hpbWF0ZSBkb3dubG9hZCBzcGVlZDogJHt0b1JlYWRhYmxlU2l6ZVN0cmluZyhieXRlc1BlclNlYyl9L3NgKTtcbiAgICB9XG4gIH1cbn1cblxuZXhwb3J0IHsgdXBsb2FkRmlsZSwgZG93bmxvYWRGaWxlIH07XG4iXSwiZmlsZSI6ImxpYi9uZXQuanMiLCJzb3VyY2VSb290IjoiLi4vLi4ifQ==