UNPKG

@cloudbase/app

Version:
445 lines 63.4 kB
"use strict"; var __assign = (this && this.__assign) || function () { __assign = Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __generator = (this && this.__generator) || function (thisArg, body) { var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; function verb(n) { return function (v) { return step([n, v]); }; } function step(op) { if (f) throw new TypeError("Generator is already executing."); while (g && (g = 0, op[0] && (_ = 0)), _) try { if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; if (y = 0, t) op = [op[0] & 2, t.value]; switch (op[0]) { case 0: case 1: t = op; break; case 4: _.label++; return { value: op[1], done: false }; case 5: _.label++; y = op[1]; op = [0]; continue; case 7: op = _.ops.pop(); _.trys.pop(); continue; default: if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } if (t[2]) _.ops.pop(); _.trys.pop(); continue; } op = body.call(thisArg, _); } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; } }; Object.defineProperty(exports, "__esModule", { value: true }); exports.NodeRequest = void 0; var adapter_interface_1 = require("@cloudbase/adapter-interface"); var constants_1 = require("./constants"); var context_1 = require("./context"); var utils_1 = require("./utils"); var common_1 = require("../../constants/common"); var signFn = null; function getSign() { return __awaiter(this, void 0, void 0, function () { var mod, e_1; return __generator(this, function (_a) { switch (_a.label) { case 0: if (!!signFn) return [3, 4]; _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); return [4, import('@cloudbase/signature-nodejs')]; case 2: mod = _a.sent(); signFn = mod.sign; return [3, 4]; case 3: e_1 = _a.sent(); console.error('缺少依赖 @cloudbase/signature-nodejs,请执行以下命令安装:\n\n' + ' npm install @cloudbase/signature-nodejs\n\n' + '该依赖用于 Node 环境下的请求签名。'); return [3, 4]; case 4: return [2, signFn]; } }); }); } var NodeRequest = (function () { function NodeRequest(config) { var _this = this; this.getReqOptions = function (url, options) { return __awaiter(_this, void 0, void 0, function () { var urlObj, TCB_SOURCE, SOURCE, _a, _b, isAdminPath, UNSUPPORTED_V3_SIGN_PATH, token, _c, secretId, secretKey, sessionToken, secretType, method, body, headers, params, secretInfo, signedParams, sign, _d, authorization, timestamp; var _e, _f, _g, _h, _j, _k, _l, _m; return __generator(this, function (_o) { switch (_o.label) { case 0: urlObj = new URL(url); TCB_SOURCE = (0, context_1.getCloudbaseContext)().TCB_SOURCE; _b = (_a = "".concat(((_f = (_e = context_1.INIT_CONFIG.context) === null || _e === void 0 ? void 0 : _e.extendedContext) === null || _f === void 0 ? void 0 : _f.source) || TCB_SOURCE || '', ",")).concat; return [4, (0, utils_1.getCurrRunEnvTag)()]; case 1: SOURCE = _b.apply(_a, [_o.sent()]); options.headers = __assign(__assign({}, options.headers), { 'User-Agent': "adapter-node/".concat(((_g = options.headers) === null || _g === void 0 ? void 0 : _g['X-SDK-Version']) || "@cloudbase/js-sdk/".concat((0, common_1.getSdkVersion)())), 'X-TCB-Source': SOURCE, 'X-Client-Timestamp': new Date().valueOf(), 'X-TCB-Region': context_1.INIT_CONFIG.region || (0, utils_1.getEnv)('TENCENTCLOUD_REGION') || '', Host: urlObj.host }); if ((_j = (_h = options.headers.Authorization) === null || _h === void 0 ? void 0 : _h.replace('Bearer', '')) === null || _j === void 0 ? void 0 : _j.trim()) { return [2, options]; } if (urlObj.pathname.startsWith('/auth/') && urlObj.pathname !== constants_1.CLIENT_AUTH_PATH) { return [2, options]; } isAdminPath = urlObj.pathname === constants_1.ADMIN_PATH; UNSUPPORTED_V3_SIGN_PATH = ['/v1/model/', '/v1/rdb/', '/v1/ai/']; if (!UNSUPPORTED_V3_SIGN_PATH.some(function (v) { return urlObj.pathname.startsWith(v); })) return [3, 3]; return [4, this.getClientCredential({ origin: urlObj.origin })]; case 2: token = _o.sent(); options.headers.Authorization = "Bearer ".concat(token); return [2, options]; case 3: _c = ((_k = this.config) === null || _k === void 0 ? void 0 : _k.auth) || {}, secretId = _c.secretId, secretKey = _c.secretKey, sessionToken = _c.sessionToken; secretType = (((_l = this.config) === null || _l === void 0 ? void 0 : _l.auth) || {}).secretType; method = options.method, body = options.body; headers = JSON.parse(JSON.stringify(options.headers)); params = typeof body === 'object' ? body : (0, utils_1.safeParseJson)(body) || {}; params.envName = (params === null || params === void 0 ? void 0 : params.env) || this.config.env || ((_m = (0, context_1.getSecretInfo)()) === null || _m === void 0 ? void 0 : _m.env) || ''; if (params.access_token) { return [2, options]; } if (method.toLowerCase() === 'get') { params = undefined; } if (!secretId || !secretKey || secretType === 'SESSION_SECRET') { secretInfo = (0, context_1.getSecretInfo)(); secretId = secretInfo.secretId; secretKey = secretInfo.secretKey; sessionToken = secretInfo.sessionToken; } if (!secretId || !secretKey) { return [2, options]; } delete headers.Authorization; if (headers['content-type']) { headers['content-type'] = headers['content-type'].toLowerCase(); } else if (headers['Content-Type']) { headers['Content-Type'] = headers['Content-Type'].toLowerCase(); } if (isAdminPath && !!sessionToken) { params.sessionToken = sessionToken; } signedParams = { secretId: secretId, secretKey: secretKey, method: method, url: url, params: params, headers: headers, withSignedParams: isAdminPath, timestamp: Math.floor(new Date().getTime() / 1000) - 1, isCloudApi: !isAdminPath, }; if (!headers['content-type'] && !headers['Content-Type']) { return [2, options]; } return [4, getSign()]; case 4: sign = _o.sent(); if (!sign) return [2, options]; _d = sign(signedParams), authorization = _d.authorization, timestamp = _d.timestamp; if (typeof sessionToken === 'string' && sessionToken !== '') { if (isAdminPath) { headers.Authorization = "".concat(authorization); headers['X-Timestamp'] = timestamp; headers['X-Signature-Expires'] = 600; } else { headers.Authorization = "".concat(authorization, ", Timestamp=").concat(timestamp, ", Token=").concat(sessionToken); } } else { headers.Authorization = "".concat(authorization, ", Timestamp=").concat(timestamp); if (isAdminPath) { headers['X-Timestamp'] = timestamp; headers['X-Signature-Expires'] = 600; } } return [2, __assign(__assign({}, options), { headers: headers, body: typeof params === 'object' ? JSON.stringify(params) : params })]; } }); }); }; this.get = function (options) { return _this.request(__assign(__assign({}, options), { method: 'get' }), _this.restrictedMethods.includes('get')); }; this.post = function (options) { return _this.request(__assign(__assign({}, options), { method: 'post' }), _this.restrictedMethods.includes('post')); }; this.put = function (options) { return _this.request(__assign(__assign({}, options), { method: 'put' })); }; this.upload = function (options) { var _a; var _data = options.data, file = options.file, name = options.name, method = options.method, _b = options.headers, headers = _b === void 0 ? {} : _b; if (file === undefined || name == undefined) { throw new Error('file and name is required'); } var data = (0, utils_1.obj2StrRecord)(_data !== null && _data !== void 0 ? _data : {}); var loweredMethod = method === null || method === void 0 ? void 0 : method.toLowerCase(); var reqMethod = (_a = ['post', 'put'].find(function (m) { return m === loweredMethod; })) !== null && _a !== void 0 ? _a : 'put'; var formData = new FormData(); if (reqMethod === 'post') { Object.keys(data).forEach(function (key) { formData.append(key, data[key]); }); formData.append('key', name); formData.append('file', file); return _this.request(__assign(__assign({}, options), { data: formData, method: reqMethod }), _this.restrictedMethods.includes('upload')); } return _this.request(__assign(__assign({}, options), { method: 'put', headers: headers, body: file }), _this.restrictedMethods.includes('upload')); }; this.download = function (options) { return __awaiter(_this, void 0, void 0, function () { var data, url, fileName, link; var _a; return __generator(this, function (_b) { switch (_b.label) { case 0: return [4, this.get(__assign(__assign({}, options), { headers: {}, responseType: 'blob' }))]; case 1: data = (_b.sent()).data; url = window.URL.createObjectURL(new Blob([data])); fileName = decodeURIComponent(new URL((_a = options === null || options === void 0 ? void 0 : options.url) !== null && _a !== void 0 ? _a : '').pathname.split('/').pop() || ''); link = document.createElement('a'); link.href = url; link.setAttribute('download', fileName); link.style.display = 'none'; document.body.appendChild(link); link.click(); window.URL.revokeObjectURL(url); document.body.removeChild(link); return [2, new Promise(function (resolve) { resolve({ statusCode: 200, tempFilePath: options.url, }); })]; } }); }); }; this.fetch = function (options) { return __awaiter(_this, void 0, void 0, function () { var _a, enableAbort, _b, stream, signal, customReqOpts, url, abortController, timeout, timer, headers, fetchOptions, res, ret, _c, _d; var _e; return __generator(this, function (_f) { switch (_f.label) { case 0: _a = options.enableAbort, enableAbort = _a === void 0 ? false : _a, _b = options.stream, stream = _b === void 0 ? false : _b, signal = options.signal, customReqOpts = options.customReqOpts; url = this.getRealUrl(options.url, options.headers || {}, options.body); abortController = new AbortController(); timeout = (customReqOpts === null || customReqOpts === void 0 ? void 0 : customReqOpts.timeout) || this.timeout; if (signal) { if (signal.aborted) { abortController.abort(); } else { signal.addEventListener('abort', function () { return abortController.abort(); }); } } timer = undefined; if (enableAbort || timeout) { timer = setTimeout(function () { var timeoutMsg = "\u8BF7\u6C42\u5728".concat(timeout / 1000, "s\u5185\u672A\u5B8C\u6210\uFF0C\u5DF2\u4E2D\u65AD"); console.warn(timeoutMsg); abortController.abort(new Error(timeoutMsg)); }, timeout); } headers = options.headers ? (0, utils_1.headersInit2Indexable)(options.headers) : undefined; return [4, this.getReqOptions(url, __assign(__assign({}, options), { headers: headers, body: options.body, signal: abortController.signal }))]; case 1: fetchOptions = _f.sent(); return [4, fetch(url, fetchOptions) .then(function (x) { clearTimeout(timer); return x; }) .catch(function (x) { clearTimeout(timer); return Promise.reject(x); })]; case 2: res = _f.sent(); _e = {}; if (!(+res.status === 204)) return [3, 3]; _c = ''; return [3, 7]; case 3: if (!stream) return [3, 4]; _d = res.body; return [3, 6]; case 4: return [4, res.json()]; case 5: _d = _f.sent(); _f.label = 6; case 6: _c = _d; _f.label = 7; case 7: ret = (_e.data = _c, _e.statusCode = res.status, _e.header = res.headers, _e); return [2, ret]; } }); }); }; this.request = function (options, enableAbort) { if (enableAbort === void 0) { enableAbort = false; } return __awaiter(_this, void 0, void 0, function () { var url, _a, _headers, data, responseType, withCredentials, body, _method, customReqOpts, headers, method, abortController, signal, timeout, payload, realUrl, timer, requestOptions, response, result_1, _b, _c, _d, e_2, _e, _f, headers_1; return __generator(this, function (_g) { switch (_g.label) { case 0: url = options.url, _a = options.headers, _headers = _a === void 0 ? {} : _a, data = options.data, responseType = options.responseType, withCredentials = options.withCredentials, body = options.body, _method = options.method, customReqOpts = options.customReqOpts; headers = (0, utils_1.obj2StrRecord)(_headers); method = String(_method).toLowerCase() || 'get'; abortController = new AbortController(); signal = abortController.signal; timeout = (customReqOpts === null || customReqOpts === void 0 ? void 0 : customReqOpts.timeout) || this.timeout; if ((0, utils_1.isFormData)(data)) { payload = data; } else if (headers['content-type'] === 'application/x-www-form-urlencoded') { payload = (0, utils_1.toQueryString)(data !== null && data !== void 0 ? data : {}); } else if (body) { payload = body; } else { payload = data ? JSON.stringify(data) : undefined; } realUrl = this.getRealUrl((0, adapter_interface_1.formatUrl)('https', url !== null && url !== void 0 ? url : '', method === 'get' ? data : {}), options.headers || {}, payload); if (enableAbort || timeout) { timer = setTimeout(function () { var timeoutMsg = "\u8BF7\u6C42\u5728".concat(timeout / 1000, "s\u5185\u672A\u5B8C\u6210\uFF0C\u5DF2\u4E2D\u65AD"); console.warn(timeoutMsg); abortController.abort(new Error(timeoutMsg)); }, timeout); } return [4, this.getReqOptions(realUrl, { method: method, headers: headers, body: payload, credentials: withCredentials ? 'include' : 'same-origin', signal: signal, })]; case 1: requestOptions = _g.sent(); _g.label = 2; case 2: _g.trys.push([2, , 15, 16]); return [4, fetch(realUrl, requestOptions)]; case 3: response = _g.sent(); result_1 = { header: {}, statusCode: response.status, }; _g.label = 4; case 4: _g.trys.push([4, 9, , 14]); _b = result_1; if (!(responseType === 'blob')) return [3, 6]; return [4, response.blob()]; case 5: _c = _g.sent(); return [3, 8]; case 6: _d = utils_1.safeParseJson; return [4, response.text()]; case 7: _c = _d.apply(void 0, [_g.sent()]); _g.label = 8; case 8: _b.data = _c; return [3, 14]; case 9: e_2 = _g.sent(); console.log('catch an error', e_2); _e = result_1; if (!(responseType === 'blob')) return [3, 11]; return [4, response.blob()]; case 10: _f = _g.sent(); return [3, 13]; case 11: return [4, response.text()]; case 12: _f = _g.sent(); _g.label = 13; case 13: _e.data = _f; return [3, 14]; case 14: headers_1 = response.headers; headers_1.forEach(function (val, key) { return (result_1.header[key.toLowerCase()] = val); }); return [2, result_1]; case 15: clearTimeout(timer); return [7]; case 16: return [2]; } }); }); }; var timeout = config.timeout, restrictedMethods = config.restrictedMethods; this.timeout = timeout || 15000; this.restrictedMethods = restrictedMethods || ['get', 'post', 'upload', 'download']; this.config = config; } NodeRequest.prototype.getClientCredential = function (opts) { var _a; return __awaiter(this, void 0, void 0, function () { var res; return __generator(this, function (_b) { switch (_b.label) { case 0: return [4, this.fetch({ url: "".concat(opts.origin).concat(constants_1.CLIENT_AUTH_PATH), method: 'POST', headers: { 'content-type': 'application/json', }, body: JSON.stringify({ grant_type: 'client_credentials', }), })]; case 1: res = _b.sent(); return [2, (_a = res.data) === null || _a === void 0 ? void 0 : _a.access_token]; } }); }); }; NodeRequest.prototype.getRealUrl = function (url, headers, body) { var _a, _b, _c, _d; if ((_b = (_a = headers.Authorization) === null || _a === void 0 ? void 0 : _a.replace('Bearer', '')) === null || _b === void 0 ? void 0 : _b.trim()) { return url; } var params = typeof body === 'object' ? body : (0, utils_1.safeParseJson)(body) || ''; if (params.access_token) { return url; } var urlObj = new URL(url); if (urlObj.pathname === '/web' && ((_c = this.config.auth) === null || _c === void 0 ? void 0 : _c.secretId) && ((_d = this.config.auth) === null || _d === void 0 ? void 0 : _d.secretKey)) { urlObj.pathname = constants_1.ADMIN_PATH; } return urlObj.toString(); }; return NodeRequest; }()); exports.NodeRequest = NodeRequest; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVxdWVzdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9saWJzL2FkYXB0ZXItbm9kZS9yZXF1ZXN0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQ0Esa0VBUXFDO0FBQ3JDLHlDQUEwRDtBQUMxRCxxQ0FBMkU7QUFFM0UsaUNBUWdCO0FBRWhCLGlEQUFzRDtBQUd0RCxJQUFJLE1BQU0sR0FBcUMsSUFBSSxDQUFBO0FBQ25ELFNBQWUsT0FBTzs7Ozs7O3lCQUNoQixDQUFDLE1BQU0sRUFBUCxjQUFPOzs7O29CQUdLLFdBQU0sTUFBTSxDQUFDLDZCQUE2QixDQUFDLEVBQUE7O29CQUFqRCxHQUFHLEdBQUcsU0FBMkM7b0JBQ3ZELE1BQU0sR0FBRyxHQUFHLENBQUMsSUFBSSxDQUFBOzs7O29CQUVqQixPQUFPLENBQUMsS0FBSyxDQUFDLGlEQUFpRDswQkFDM0QsK0NBQStDOzBCQUMvQyxzQkFBc0IsQ0FBQyxDQUFBOzt3QkFHL0IsV0FBTyxNQUFPLEVBQUE7Ozs7Q0FDZjtBQU9EO0lBVUUscUJBQVksTUFBeUM7UUFBckQsaUJBS0M7UUF1RE0sa0JBQWEsR0FBRyxVQUNyQixHQUFXLEVBQ1gsT0FPQzs7Ozs7O3dCQUVLLE1BQU0sR0FBRyxJQUFJLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQTt3QkFFbkIsVUFBVSxHQUFLLElBQUEsNkJBQW1CLEdBQUUsV0FBMUIsQ0FBMEI7NkNBRTFCLENBQUEsTUFBQSxNQUFBLHFCQUFXLENBQUMsT0FBTywwQ0FBRSxlQUFlLDBDQUFFLE1BQU0sS0FBSSxVQUFVLElBQUksRUFBRTt3QkFBSSxXQUFNLElBQUEsd0JBQWdCLEdBQUUsRUFBQTs7d0JBQXhHLE1BQU0sR0FBRyxjQUF1RSxTQUF3QixFQUFFO3dCQUVoSCxPQUFPLENBQUMsT0FBTyx5QkFDVixPQUFPLENBQUMsT0FBTyxLQUNsQixZ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bm8tbmVzdGVkLXRlcm5hcnkgKi9cbmltcG9ydCB7XG4gIElGZXRjaE9wdGlvbnMsXG4gIElSZXF1ZXN0Q29uZmlnLFxuICBJUmVxdWVzdE1ldGhvZCxcbiAgSVJlcXVlc3RPcHRpb25zLFxuICBSZXNwb25zZU9iamVjdCxcbiAgU0RLUmVxdWVzdEludGVyZmFjZSxcbiAgZm9ybWF0VXJsLFxufSBmcm9tICdAY2xvdWRiYXNlL2FkYXB0ZXItaW50ZXJmYWNlJ1xuaW1wb3J0IHsgQURNSU5fUEFUSCwgQ0xJRU5UX0FVVEhfUEFUSCB9IGZyb20gJy4vY29uc3RhbnRzJ1xuaW1wb3J0IHsgZ2V0Q2xvdWRiYXNlQ29udGV4dCwgZ2V0U2VjcmV0SW5mbywgSU5JVF9DT05GSUcgfSBmcm9tICcuL2NvbnRleHQnXG5pbXBvcnQgdHlwZSB7IElDdXN0b21SZXFPcHRzIH0gZnJvbSAnLi90eXBlcydcbmltcG9ydCB7XG4gIGdldEVudixcbiAgaXNGb3JtRGF0YSxcbiAgdG9RdWVyeVN0cmluZyxcbiAgc2FmZVBhcnNlSnNvbixcbiAgb2JqMlN0clJlY29yZCxcbiAgaGVhZGVyc0luaXQySW5kZXhhYmxlLFxuICBnZXRDdXJyUnVuRW52VGFnLFxufSBmcm9tICcuL3V0aWxzJ1xuaW1wb3J0IHsgSUNsb3VkYmFzZUNvbmZpZyB9IGZyb20gJ0BjbG91ZGJhc2UvdHlwZXMnXG5pbXBvcnQgeyBnZXRTZGtWZXJzaW9uIH0gZnJvbSAnLi4vLi4vY29uc3RhbnRzL2NvbW1vbidcbi8vIOW7tui/n+WKoOi9ve+8jOmBv+WFjemdniBOb2RlIOeOr+Wig+aJk+WMheaXtuW8leWFpeatpOWMhVxuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1leHBsaWNpdC1hbnlcbmxldCBzaWduRm46ICgoLi4uYXJnczogYW55W10pID0+IGFueSkgfCBudWxsID0gbnVsbFxuYXN5bmMgZnVuY3Rpb24gZ2V0U2lnbigpIHtcbiAgaWYgKCFzaWduRm4pIHtcbiAgICB0cnkge1xuICAgICAgLy8gQHRzLWlnbm9yZSDigJQg6K+l5YyF5LuF5ZyoIE5vZGUg6L+Q6KGM5pe25a2Y5Zyo77yM5byA5Y+R546v5aKD5Y+v6IO95pyq5a6J6KOFXG4gICAgICBjb25zdCBtb2QgPSBhd2FpdCBpbXBvcnQoJ0BjbG91ZGJhc2Uvc2lnbmF0dXJlLW5vZGVqcycpXG4gICAgICBzaWduRm4gPSBtb2Quc2lnblxuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGNvbnNvbGUuZXJyb3IoJ+e8uuWwkeS+nei1liBAY2xvdWRiYXNlL3NpZ25hdHVyZS1ub2RlanPvvIzor7fmiafooYzku6XkuIvlkb3ku6Tlronoo4XvvJpcXG5cXG4nXG4gICAgICAgICsgJyAgbnBtIGluc3RhbGwgQGNsb3VkYmFzZS9zaWduYXR1cmUtbm9kZWpzXFxuXFxuJ1xuICAgICAgICArICfor6Xkvp3otZbnlKjkuo4gTm9kZSDnjq/looPkuIvnmoTor7fmsYLnrb7lkI3jgIInKVxuICAgIH1cbiAgfVxuICByZXR1cm4gc2lnbkZuIVxufVxuXG4vKipcbiAqIE5vZGUuanMg546v5aKD5LiL55qEIEhUVFAg6K+35rGC5a6e546wXG4gKiDln7rkuo7ljp/nlJ8gZmV0Y2jvvIzmlK/mjIEgR0VUL1BPU1QvUFVUL+S4iuS8oC/kuIvovb0v5rWB5byP6K+35rGCXG4gKiDoh6rliqjlpITnkIYgVjMg562+5ZCN5ZKMIEJlYXJlciBUb2tlbiDorqTor4FcbiAqL1xuZXhwb3J0IGNsYXNzIE5vZGVSZXF1ZXN0IGltcGxlbWVudHMgU0RLUmVxdWVzdEludGVyZmFjZSB7XG4gIC8qKiDor7fmsYLphY3nva7vvIzljIXlkKvorqTor4Hkv6Hmga8gKi9cbiAgY29uZmlnOiBJUmVxdWVzdENvbmZpZyAmIElDbG91ZGJhc2VDb25maWdcblxuICAvKiog6K+35rGC6LaF5pe25pe26Ze077yI5q+r56eS77yJ77yM6buY6K6kIDE1MDAwICovXG4gIHByaXZhdGUgcmVhZG9ubHkgdGltZW91dDogbnVtYmVyXG5cbiAgLyoqIOWPl+i2heaXtuaOp+WItueahOivt+axguexu+Wei+WIl+ihqCAqL1xuICBwcml2YXRlIHJlYWRvbmx5IHJlc3RyaWN0ZWRNZXRob2RzOiBBcnJheTxJUmVxdWVzdE1ldGhvZD5cblxuICBjb25zdHJ1Y3Rvcihjb25maWc6IElSZXF1ZXN0Q29uZmlnICYgSUNsb3VkYmFzZUNvbmZpZykge1xuICAgIGNvbnN0IHsgdGltZW91dCwgcmVzdHJpY3RlZE1ldGhvZHMgfSA9IGNvbmZpZ1xuICAgIHRoaXMudGltZW91dCA9IHRpbWVvdXQgfHwgMTUwMDBcbiAgICB0aGlzLnJlc3RyaWN0ZWRNZXRob2RzID0gcmVzdHJpY3RlZE1ldGhvZHMgfHwgWydnZXQnLCAncG9zdCcsICd1cGxvYWQnLCAnZG93bmxvYWQnXVxuICAgIHRoaXMuY29uZmlnID0gY29uZmlnXG4gIH1cblxuICAvKipcbiAgICog6I635Y+W5a6i5oi356uv5Yet6K+BIGFjY2Vzc190b2tlbu+8jOS4uueuoeeQhuWRmOadg+mZkFxuICAgKiDnlKjkuo7kuI3mlK/mjIEgVjMg562+5ZCN55qE5o6l5Y+j77yI5aaC5pWw5o2u5qih5Z6L44CB5YWz57O75Z6L5pWw5o2u5bqT44CBQUnvvIlcbiAgICovXG4gIGFzeW5jIGdldENsaWVudENyZWRlbnRpYWwob3B0czogeyBvcmlnaW46IHN0cmluZyB9KTogUHJvbWlzZTxhbnk+IHtcbiAgICBjb25zdCByZXMgPSBhd2FpdCB0aGlzLmZldGNoKHtcbiAgICAgIHVybDogYCR7b3B0cy5vcmlnaW59JHtDTElFTlRfQVVUSF9QQVRIfWAsXG4gICAgICBtZXRob2Q6ICdQT1NUJyxcbiAgICAgIGhlYWRlcnM6IHtcbiAgICAgICAgJ2NvbnRlbnQtdHlwZSc6ICdhcHBsaWNhdGlvbi9qc29uJyxcbiAgICAgIH0sXG4gICAgICBib2R5OiBKU09OLnN0cmluZ2lmeSh7XG4gICAgICAgIGdyYW50X3R5cGU6ICdjbGllbnRfY3JlZGVudGlhbHMnLFxuICAgICAgfSksXG4gICAgfSlcblxuICAgIHJldHVybiByZXMuZGF0YT8uYWNjZXNzX3Rva2VuXG4gIH1cblxuICAvKipcbiAgICog6I635Y+W5a6e6ZmF6K+35rGCIFVSTFxuICAgKiDlvZPor7fmsYLmnKrmkLrluKYgQXV0aG9yaXphdGlvbiDkuJTmnKroh6rluKYgYWNjZXNzX3Rva2VuIOaXtu+8jFxuICAgKiDlsIYgL3dlYiDot6/lvoTmm7/mjaLkuLogL2FkbWlu77yI566h55CG56uv562+5ZCN6Lev5b6E77yJXG4gICAqL1xuICBnZXRSZWFsVXJsKHVybDogc3RyaW5nLCBoZWFkZXJzOiBSZWNvcmQ8c3RyaW5nLCBhbnk+LCBib2R5OiBhbnkpIHtcbiAgICBpZiAoaGVhZGVycy5BdXRob3JpemF0aW9uPy5yZXBsYWNlKCdCZWFyZXInLCAnJyk/LnRyaW0oKSkge1xuICAgICAgcmV0dXJuIHVybFxuICAgIH1cblxuICAgIGNvbnN0IHBhcmFtcyA9IHR5cGVvZiBib2R5ID09PSAnb2JqZWN0JyA/IGJvZHkgOiBzYWZlUGFyc2VKc29uKGJvZHkpIHx8ICcnXG5cbiAgICBpZiAocGFyYW1zLmFjY2Vzc190b2tlbikge1xuICAgICAgcmV0dXJuIHVybFxuICAgIH1cblxuICAgIGNvbnN0IHVybE9iaiA9IG5ldyBVUkwodXJsKVxuXG4gICAgaWYgKHVybE9iai5wYXRobmFtZSA9PT0gJy93ZWInICYmIHRoaXMuY29uZmlnLmF1dGg/LnNlY3JldElkICYmIHRoaXMuY29uZmlnLmF1dGg/LnNlY3JldEtleSkge1xuICAgICAgdXJsT2JqLnBhdGhuYW1lID0gQURNSU5fUEFUSFxuICAgIH1cbiAgICByZXR1cm4gdXJsT2JqLnRvU3RyaW5nKClcbiAgfVxuXG4gIC8qKlxuICAgKiDkuLror7fmsYLmt7vliqDnrb7lkI3miJborqTor4Hkv6Hmga9cbiAgICpcbiAgICog5aSE55CG6YC76L6R5LyY5YWI57qn77yaXG4gICAqIDEuIOW3suaciSBBdXRob3JpemF0aW9uIGhlYWRlciDihpIg55u05o6l6L+U5ZueXG4gICAqIDIuIC9hdXRoLyDot6/lvoQg4oaSIFNESyDorqTor4HmjqXlj6PvvIzml6DpnIDnrb7lkI1cbiAgICogMy4g5LiN5pSv5oyBIFYzIOetvuWQjeeahOi3r+W+hO+8iC92MS9tb2RlbC8g562J77yJ4oaSIOeUqCBjbGllbnRDcmVkZW50aWFsIEJlYXJlciBUb2tlblxuICAgKiA0LiDlj4LmlbDlkKsgYWNjZXNzX3Rva2VuIOKGkiDml6DpnIDnrb7lkI1cbiAgICogNS4g5YW25LuWIOKGkiDkvb/nlKggVjMg562+5ZCN77yIVEMzLUhNQUMtU0hBMjU277yJXG4gICAqL1xuICBwdWJsaWMgZ2V0UmVxT3B0aW9ucyA9IGFzeW5jIChcbiAgICB1cmw6IHN0cmluZyxcbiAgICBvcHRpb25zOiB7XG4gICAgICBtZXRob2Q/OiBhbnlcbiAgICAgIGhlYWRlcnM6IGFueVxuICAgICAgYm9keT86IGFueVxuICAgICAgY3JlZGVudGlhbHM/OiBzdHJpbmdcbiAgICAgIHNpZ25hbD86IEFib3J0U2lnbmFsXG4gICAgICB1cmw/OiBhbnlcbiAgICB9LFxuICApID0+IHtcbiAgICBjb25zdCB1cmxPYmogPSBuZXcgVVJMKHVybClcblxuICAgIGNvbnN0IHsgVENCX1NPVVJDRSB9ID0gZ2V0Q2xvdWRiYXNlQ29udGV4dCgpXG4gICAgLy8gTm90ZTog5LqR5Ye95pWw6KKr6LCD55So5pe25Y+v6IO96LCD55So56uv5pyq5Lyg6YCSIFNPVVJDRe+8jFRDQl9TT1VSQ0Ug5Y+v6IO95Li656m6XG4gICAgY29uc3QgU09VUkNFID0gYCR7SU5JVF9DT05GSUcuY29udGV4dD8uZXh0ZW5kZWRDb250ZXh0Py5zb3VyY2UgfHwgVENCX1NPVVJDRSB8fCAnJ30sJHthd2FpdCBnZXRDdXJyUnVuRW52VGFnKCl9YFxuXG4gICAgb3B0aW9ucy5oZWFkZXJzID0ge1xuICAgICAgLi4ub3B0aW9ucy5oZWFkZXJzLFxuICAgICAgJ1VzZXItQWdlbnQnOiBgYWRhcHRlci1ub2RlLyR7b3B0aW9ucy5oZWFkZXJzPy5bJ1gtU0RLLVZlcnNpb24nXSB8fCBgQGNsb3VkYmFzZS9qcy1zZGsvJHtnZXRTZGtWZXJzaW9uKCl9YH1gLFxuICAgICAgJ1gtVENCLVNvdXJjZSc6IFNPVVJDRSxcbiAgICAgICdYLUNsaWVudC1UaW1lc3RhbXAnOiBuZXcgRGF0ZSgpLnZhbHVlT2YoKSxcbiAgICAgICdYLVRDQi1SZWdpb24nOiBJTklUX0NPTkZJRy5yZWdpb24gfHwgZ2V0RW52KCdURU5DRU5UQ0xPVURfUkVHSU9OJykgfHwgJycsXG4gICAgICBIb3N0OiB1cmxPYmouaG9zdCxcbiAgICB9XG5cbiAgICAvLyDlt7LmkLrluKbmnInmlYggQXV0aG9yaXphdGlvbu+8jOebtOaOpei/lOWbnlxuICAgIGlmIChvcHRpb25zLmhlYWRlcnMuQXV0aG9yaXphdGlvbj8ucmVwbGFjZSgnQmVhcmVyJywgJycpPy50cmltKCkpIHtcbiAgICAgIHJldHVybiBvcHRpb25zXG4gICAgfVxuXG4gICAgLy8gYXV0aCDnm7jlhbPmjqXlj6PkuI3pnIDopoHnrb7lkI1cbiAgICBpZiAodXJsT2JqLnBhdGhuYW1lLnN0YXJ0c1dpdGgoJy9hdXRoLycpICYmIHVybE9iai5wYXRobmFtZSAhPT0gQ0xJRU5UX0FVVEhfUEFUSCkge1xuICAgICAgcmV0dXJuIG9wdGlvbnNcbiAgICB9XG5cbiAgICBjb25zdCBpc0FkbWluUGF0aCA9IHVybE9iai5wYXRobmFtZSA9PT0gQURNSU5fUEFUSFxuXG4gICAgLy8g6L+Z5Lqb6Lev5b6E5LiN5pSv5oyBIFYzIOetvuWQje+8jOaUueeUqCBjbGllbnRDcmVkZW50aWFsIOiOt+WPliBCZWFyZXIgVG9rZW5cbiAgICBjb25zdCBVTlNVUFBPUlRFRF9WM19TSUdOX1BBVEggPSBbJy92MS9tb2RlbC8nLCAnL3YxL3JkYi8nLCAnL3YxL2FpLyddXG5cbiAgICBpZiAoVU5TVVBQT1JURURfVjNfU0lHTl9QQVRILnNvbWUodiA9PiB1cmxPYmoucGF0aG5hbWUuc3RhcnRzV2l0aCh2KSkpIHtcbiAgICAgIGNvbnN0IHRva2VuID0gYXdhaXQgdGhpcy5nZXRDbGllbnRDcmVkZW50aWFsKHsgb3JpZ2luOiB1cmxPYmoub3JpZ2luIH0pXG4gICAgICBvcHRpb25zLmhlYWRlcnMuQXV0aG9yaXphdGlvbiA9IGBCZWFyZXIgJHt0b2tlbn1gXG4gICAgICByZXR1cm4gb3B0aW9uc1xuICAgIH1cblxuICAgIGxldCB7IHNlY3JldElkLCBzZWNyZXRLZXksIHNlc3Npb25Ub2tlbiB9ID0gdGhpcy5jb2