UNPKG

27.6 kBJavaScriptView Raw
1"use strict";
2
3Object.defineProperty(exports, "__esModule", {
4 value: true
5});
6exports.default = void 0;
7
8var _awsSdk = _interopRequireDefault(require("aws-sdk"));
9
10var _System = _interopRequireDefault(require("./System"));
11
12var _Module = _interopRequireDefault(require("./Module"));
13
14var _errorUtils = require("./errorUtils");
15
16function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
17
18function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; }
19
20function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
21
22const {
23 MODULE_NAME,
24 debug,
25 log,
26 warn,
27 error,
28 noteGauge,
29 noteCount,
30 noteTimer,
31 trackOp
32} = new _Module.default(__filename); // eslint-disable-line no-unused-vars
33
34class AWSError extends Error {
35 constructor(err, opName, data) {
36 // $FlowIgnore
37 const message = `AWS Op '${opName}' threw '${err.code}': ${err.message}`;
38 super(message);
39
40 _defineProperty(this, "message", void 0);
41
42 _defineProperty(this, "code", void 0);
43
44 _defineProperty(this, "time", void 0);
45
46 _defineProperty(this, "statusCode", void 0);
47
48 _defineProperty(this, "retryable", void 0);
49
50 _defineProperty(this, "data", void 0);
51
52 this.message = message; // $FlowIgnore
53
54 this.code = err.code; // $FlowIgnore
55
56 this.time = err.time; // $FlowIgnore
57
58 this.statusCode = err.statusCode; // $FlowIgnore
59
60 this.retryable = err.retryable;
61 this.data = data;
62 }
63
64}
65
66class AWSClient {
67 constructor() {
68 const awsConfig = _System.default.getConfig().aws;
69
70 if (!awsConfig) throw new Error('aws system config is unset');
71 _awsSdk.default.config.region = awsConfig.defaultRegion; // support local execution
72
73 if (awsConfig.profile) {
74 log('Using profile', {
75 profile: awsConfig.profile
76 });
77 _awsSdk.default.config.credentials = new _awsSdk.default.SharedIniFileCredentials({
78 profile: awsConfig.profile
79 });
80 }
81 }
82
83 async runSES(func, options) {
84 return await this._runOp('SES', clientConfig => new _awsSdk.default.SES(clientConfig), func, options);
85 }
86
87 async runS3(func, options) {
88 return await this._runOp('S3', clientConfig => new _awsSdk.default.S3(clientConfig), func, options);
89 }
90
91 async runDocumentClient(func, options) {
92 return await this._runOp('DocumentClient', clientConfig => new _awsSdk.default.DynamoDB.DocumentClient(_objectSpread({
93 convertEmptyValues: true
94 }, clientConfig)), func, options);
95 }
96
97 async runDynamoDB(func, options) {
98 return await this._runOp('DynamoDB', clientConfig => new _awsSdk.default.DynamoDB(clientConfig), func, options);
99 }
100
101 async runApplicationAutoScaling(func, options) {
102 return await this._runOp('ApplicationAutoScaling', clientConfig => new _awsSdk.default.ApplicationAutoScaling(clientConfig), func, options);
103 }
104
105 async runCloudFront(func, options) {
106 return await this._runOp('CloudFront', clientConfig => new _awsSdk.default.CloudFront(clientConfig), func, options);
107 }
108
109 async runAthena(func, options) {
110 return await this._runOp('Athena', clientConfig => new _awsSdk.default.Athena(clientConfig), func, options);
111 }
112
113 async runSQS(func, options) {
114 return await this._runOp('SQS', clientConfig => new _awsSdk.default.SQS(clientConfig), func, options);
115 }
116
117 async runCloudWatch(func, options) {
118 return await this._runOp('CloudWatch', clientConfig => new _awsSdk.default.CloudWatch(clientConfig), func, options);
119 }
120
121 async runFirehose(func, options) {
122 return await this._runOp('Firehose', clientConfig => new _awsSdk.default.Firehose(clientConfig), func, options);
123 }
124
125 async runES(func, options) {
126 return await this._runOp('Firehose', clientConfig => new _awsSdk.default.ES(clientConfig), func, options);
127 }
128
129 async _runOp(serviceName, serviceGenerator, func, options) {
130 const awsConfig = _System.default.getConfig().aws;
131
132 if (!awsConfig) throw new Error('aws config not set in system config');
133 const region = awsConfig.defaultRegion || (options || {}).region || (0, _errorUtils.throwUnsetArg)('aws region');
134 options = options || {};
135 options.errorHandlers = options.errorHandlers || {};
136 const credentials = _awsSdk.default.config.credentials;
137 let start = 0;
138 let opName = 'unknown-operation';
139
140 try {
141 // TODO: recreate only when creds expire?
142 const service = serviceGenerator({
143 credentials: credentials,
144 region: region
145 });
146 const req = func(service);
147 if (req === undefined) throw new Error(`AWS runXXX method call on service '${serviceName}' is missing, did you user 'return'?`); // $FlowIgnore
148
149 opName = options.opName || req['operation'];
150 if (!options.noLog) debug(`AWS operation started...`, {
151 serviceName,
152 opName
153 });
154 let result;
155 let success = false;
156 let code;
157
158 do {
159 try {
160 start = Date.now();
161 result = await req.promise();
162 success = true;
163 } catch (err) {
164 // $FlowIgnore
165 const errorHandler = options.errorHandlers[err.code];
166 if (!errorHandler) throw err;
167
168 switch (errorHandler.type) {
169 case 'retry':
170 try {
171 errorHandler.tries = errorHandler.tries || 1;
172
173 if (errorHandler.tries-- > 0 && errorHandler.action) {
174 await errorHandler.action(err);
175 }
176 } catch (err2) {
177 err2.leadingError = err;
178 throw err2;
179 }
180
181 break;
182
183 case 'ignore':
184 code = err.code;
185 success = true;
186 log(`${serviceName} op '${opName}' completed with an ignorable error code`, {
187 code: code,
188 ms: Date.now() - start
189 });
190 break;
191
192 default:
193 throw new Error(`Unexpected errorHandler type: '${errorHandler.type}'`);
194 }
195 }
196 } while (!success);
197
198 if (!options.noLog) debug(`AWS operation completed`, {
199 serviceName,
200 opName,
201 ms: Date.now() - start
202 });
203 noteCount(`${MODULE_NAME}.${serviceName}.${opName}.success`, 1); // $FlowIgnore
204
205 return {
206 result: result,
207 code: code
208 };
209 } catch (err) {
210 log(`${serviceName} op '${opName}' failed`, {
211 err,
212 args: options.args
213 });
214 noteCount(`${MODULE_NAME}.${serviceName}.${opName}.fail`, 1);
215 throw new AWSError(err, `${serviceName}.${opName}`, {
216 args: options.args
217 });
218 } finally {
219 noteTimer(`${MODULE_NAME}.${serviceName}.${opName}`, Date.now() - start);
220 }
221 }
222
223}
224
225exports.default = AWSClient;
226//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9BV1NDbGllbnQuanMiXSwibmFtZXMiOlsiTU9EVUxFX05BTUUiLCJkZWJ1ZyIsImxvZyIsIndhcm4iLCJlcnJvciIsIm5vdGVHYXVnZSIsIm5vdGVDb3VudCIsIm5vdGVUaW1lciIsInRyYWNrT3AiLCJNb2R1bGUiLCJfX2ZpbGVuYW1lIiwiQVdTRXJyb3IiLCJFcnJvciIsImNvbnN0cnVjdG9yIiwiZXJyIiwib3BOYW1lIiwiZGF0YSIsIm1lc3NhZ2UiLCJjb2RlIiwidGltZSIsInN0YXR1c0NvZGUiLCJyZXRyeWFibGUiLCJBV1NDbGllbnQiLCJhd3NDb25maWciLCJTeXN0ZW0iLCJnZXRDb25maWciLCJhd3MiLCJBV1MiLCJjb25maWciLCJyZWdpb24iLCJkZWZhdWx0UmVnaW9uIiwicHJvZmlsZSIsImNyZWRlbnRpYWxzIiwiU2hhcmVkSW5pRmlsZUNyZWRlbnRpYWxzIiwicnVuU0VTIiwiZnVuYyIsIm9wdGlvbnMiLCJfcnVuT3AiLCJjbGllbnRDb25maWciLCJTRVMiLCJydW5TMyIsIlMzIiwicnVuRG9jdW1lbnRDbGllbnQiLCJEeW5hbW9EQiIsIkRvY3VtZW50Q2xpZW50IiwiY29udmVydEVtcHR5VmFsdWVzIiwicnVuRHluYW1vREIiLCJydW5BcHBsaWNhdGlvbkF1dG9TY2FsaW5nIiwiQXBwbGljYXRpb25BdXRvU2NhbGluZyIsInJ1bkNsb3VkRnJvbnQiLCJDbG91ZEZyb250IiwicnVuQXRoZW5hIiwiQXRoZW5hIiwicnVuU1FTIiwiU1FTIiwicnVuQ2xvdWRXYXRjaCIsIkNsb3VkV2F0Y2giLCJydW5GaXJlaG9zZSIsIkZpcmVob3NlIiwicnVuRVMiLCJFUyIsInNlcnZpY2VOYW1lIiwic2VydmljZUdlbmVyYXRvciIsImVycm9ySGFuZGxlcnMiLCJzdGFydCIsInNlcnZpY2UiLCJyZXEiLCJ1bmRlZmluZWQiLCJub0xvZyIsInJlc3VsdCIsInN1Y2Nlc3MiLCJEYXRlIiwibm93IiwicHJvbWlzZSIsImVycm9ySGFuZGxlciIsInR5cGUiLCJ0cmllcyIsImFjdGlvbiIsImVycjIiLCJsZWFkaW5nRXJyb3IiLCJtcyIsImFyZ3MiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFFQTs7QUFFQTs7QUFDQTs7QUFDQTs7Ozs7Ozs7QUFFQSxNQUFNO0FBQUVBLEVBQUFBLFdBQUY7QUFBZUMsRUFBQUEsS0FBZjtBQUFzQkMsRUFBQUEsR0FBdEI7QUFBMkJDLEVBQUFBLElBQTNCO0FBQWlDQyxFQUFBQSxLQUFqQztBQUF3Q0MsRUFBQUEsU0FBeEM7QUFBbURDLEVBQUFBLFNBQW5EO0FBQThEQyxFQUFBQSxTQUE5RDtBQUF5RUMsRUFBQUE7QUFBekUsSUFBcUYsSUFBSUMsZUFBSixDQUFXQyxVQUFYLENBQTNGLEMsQ0FBa0g7O0FBRWxILE1BQU1DLFFBQU4sU0FBdUJDLEtBQXZCLENBQTZCO0FBVTNCQyxFQUFBQSxXQUFXLENBQUNDLEdBQUQsRUFBYUMsTUFBYixFQUE2QkMsSUFBN0IsRUFBeUM7QUFDbEQ7QUFDQSxVQUFNQyxPQUFPLEdBQUksV0FBVUYsTUFBTyxZQUFXRCxHQUFHLENBQUNJLElBQUssTUFBS0osR0FBRyxDQUFDRyxPQUFRLEVBQXZFO0FBRUEsVUFBTUEsT0FBTjs7QUFKa0Q7O0FBQUE7O0FBQUE7O0FBQUE7O0FBQUE7O0FBQUE7O0FBTWxELFNBQUtBLE9BQUwsR0FBZUEsT0FBZixDQU5rRCxDQU9sRDs7QUFDQSxTQUFLQyxJQUFMLEdBQVlKLEdBQUcsQ0FBQ0ksSUFBaEIsQ0FSa0QsQ0FTbEQ7O0FBQ0EsU0FBS0MsSUFBTCxHQUFZTCxHQUFHLENBQUNLLElBQWhCLENBVmtELENBV2xEOztBQUNBLFNBQUtDLFVBQUwsR0FBa0JOLEdBQUcsQ0FBQ00sVUFBdEIsQ0Faa0QsQ0FhbEQ7O0FBQ0EsU0FBS0MsU0FBTCxHQUFpQlAsR0FBRyxDQUFDTyxTQUFyQjtBQUVBLFNBQUtMLElBQUwsR0FBWUEsSUFBWjtBQUNEOztBQTNCMEI7O0FBZ0RkLE1BQU1NLFNBQU4sQ0FBZ0I7QUFFN0JULEVBQUFBLFdBQVcsR0FBRztBQUNaLFVBQU1VLFNBQVMsR0FBR0MsZ0JBQU9DLFNBQVAsR0FBbUJDLEdBQXJDOztBQUNBLFFBQUksQ0FBQ0gsU0FBTCxFQUNFLE1BQU0sSUFBSVgsS0FBSixDQUFVLDRCQUFWLENBQU47QUFFRmUsb0JBQUlDLE1BQUosQ0FBV0MsTUFBWCxHQUFvQk4sU0FBUyxDQUFDTyxhQUE5QixDQUxZLENBT1o7O0FBQ0EsUUFBSVAsU0FBUyxDQUFDUSxPQUFkLEVBQXVCO0FBQ3JCN0IsTUFBQUEsR0FBRyxDQUFDLGVBQUQsRUFBa0I7QUFBRTZCLFFBQUFBLE9BQU8sRUFBRVIsU0FBUyxDQUFDUTtBQUFyQixPQUFsQixDQUFIO0FBQ0FKLHNCQUFJQyxNQUFKLENBQVdJLFdBQVgsR0FBeUIsSUFBSUwsZ0JBQUlNLHdCQUFSLENBQWlDO0FBQUVGLFFBQUFBLE9BQU8sRUFBRVIsU0FBUyxDQUFDUTtBQUFyQixPQUFqQyxDQUF6QjtBQUNEO0FBQ0Y7O0FBRUQsUUFBTUcsTUFBTixDQUNFQyxJQURGLEVBRUVDLE9BRkYsRUFHMEM7QUFDeEMsV0FBTyxNQUFNLEtBQUtDLE1BQUwsQ0FDWCxLQURXLEVBRVZDLFlBQUQsSUFBZ0MsSUFBSVgsZ0JBQUlZLEdBQVIsQ0FBWUQsWUFBWixDQUZyQixFQUdYSCxJQUhXLEVBSVhDLE9BSlcsQ0FBYjtBQUtEOztBQUVELFFBQU1JLEtBQU4sQ0FDRUwsSUFERixFQUVFQyxPQUZGLEVBRzBDO0FBQ3hDLFdBQU8sTUFBTSxLQUFLQyxNQUFMLENBQ1gsSUFEVyxFQUVWQyxZQUFELElBQWdDLElBQUlYLGdCQUFJYyxFQUFSLENBQVdILFlBQVgsQ0FGckIsRUFHWEgsSUFIVyxFQUlYQyxPQUpXLENBQWI7QUFLRDs7QUFFRCxRQUFNTSxpQkFBTixDQUNFUCxJQURGLEVBRUVDLE9BRkYsRUFHMEM7QUFDeEMsV0FBTyxNQUFNLEtBQUtDLE1BQUwsQ0FDWCxnQkFEVyxFQUVWQyxZQUFELElBQWdDLElBQUlYLGdCQUFJZ0IsUUFBSixDQUFhQyxjQUFqQjtBQUFrQ0MsTUFBQUEsa0JBQWtCLEVBQUU7QUFBdEQsT0FBK0RQLFlBQS9ELEVBRnJCLEVBR1hILElBSFcsRUFJWEMsT0FKVyxDQUFiO0FBS0Q7O0FBRUQsUUFBTVUsV0FBTixDQUNFWCxJQURGLEVBRUVDLE9BRkYsRUFHMEM7QUFDeEMsV0FBTyxNQUFNLEtBQUtDLE1BQUwsQ0FDWCxVQURXLEVBRVZDLFlBQUQsSUFBZ0MsSUFBSVgsZ0JBQUlnQixRQUFSLENBQWlCTCxZQUFqQixDQUZyQixFQUdYSCxJQUhXLEVBSVhDLE9BSlcsQ0FBYjtBQUtEOztBQUVELFFBQU1XLHlCQUFOLENBQ0VaLElBREYsRUFFRUMsT0FGRixFQUcwQztBQUN4QyxXQUFPLE1BQU0sS0FBS0MsTUFBTCxDQUNYLHdCQURXLEVBRVZDLFlBQUQsSUFBZ0MsSUFBSVgsZ0JBQUlxQixzQkFBUixDQUErQlYsWUFBL0IsQ0FGckIsRUFHWEgsSUFIVyxFQUlYQyxPQUpXLENBQWI7QUFLRDs7QUFFRCxRQUFNYSxhQUFOLENBQ0VkLElBREYsRUFFRUMsT0FGRixFQUcwQztBQUN4QyxXQUFPLE1BQU0sS0FBS0MsTUFBTCxDQUNYLFlBRFcsRUFFVkMsWUFBRCxJQUFnQyxJQUFJWCxnQkFBSXVCLFVBQVIsQ0FBbUJaLFlBQW5CLENBRnJCLEVBR1hILElBSFcsRUFJWEMsT0FKVyxDQUFiO0FBS0Q7O0FBRUQsUUFBTWUsU0FBTixDQUNFaEIsSUFERixFQUVFQyxPQUZGLEVBRzBDO0FBQ3hDLFdBQU8sTUFBTSxLQUFLQyxNQUFMLENBQ1gsUUFEVyxFQUVWQyxZQUFELElBQWdDLElBQUlYLGdCQUFJeUIsTUFBUixDQUFlZCxZQUFmLENBRnJCLEVBR1hILElBSFcsRUFJWEMsT0FKVyxDQUFiO0FBS0Q7O0FBRUQsUUFBTWlCLE1BQU4sQ0FDRWxCLElBREYsRUFFRUMsT0FGRixFQUcwQztBQUN4QyxXQUFPLE1BQU0sS0FBS0MsTUFBTCxDQUNYLEtBRFcsRUFFVkMsWUFBRCxJQUFnQyxJQUFJWCxnQkFBSTJCLEdBQVIsQ0FBWWhCLFlBQVosQ0FGckIsRUFHWEgsSUFIVyxFQUlYQyxPQUpXLENBQWI7QUFLRDs7QUFFRCxRQUFNbUIsYUFBTixDQUNFcEIsSUFERixFQUVFQyxPQUZGLEVBRzBDO0FBQ3hDLFdBQU8sTUFBTSxLQUFLQyxNQUFMLENBQ1gsWUFEVyxFQUVWQyxZQUFELElBQWdDLElBQUlYLGdCQUFJNkIsVUFBUixDQUFtQmxCLFlBQW5CLENBRnJCLEVBR1hILElBSFcsRUFJWEMsT0FKVyxDQUFiO0FBS0Q7O0FBRUQsUUFBTXFCLFdBQU4sQ0FDRXRCLElBREYsRUFFRUMsT0FGRixFQUcwQztBQUN4QyxXQUFPLE1BQU0sS0FBS0MsTUFBTCxDQUNYLFVBRFcsRUFFVkMsWUFBRCxJQUFnQyxJQUFJWCxnQkFBSStCLFFBQVIsQ0FBaUJwQixZQUFqQixDQUZyQixFQUdYSCxJQUhXLEVBSVhDLE9BSlcsQ0FBYjtBQUtEOztBQUVELFFBQU11QixLQUFOLENBQ0V4QixJQURGLEVBRUVDLE9BRkYsRUFHMEM7QUFDeEMsV0FBTyxNQUFNLEtBQUtDLE1BQUwsQ0FDWCxVQURXLEVBRVZDLFlBQUQsSUFBZ0MsSUFBSVgsZ0JBQUlpQyxFQUFSLENBQVd0QixZQUFYLENBRnJCLEVBR1hILElBSFcsRUFJWEMsT0FKVyxDQUFiO0FBS0Q7O0FBRUQsUUFBTUMsTUFBTixDQUNFd0IsV0FERixFQUVFQyxnQkFGRixFQUdFM0IsSUFIRixFQUlFQyxPQUpGLEVBSzBDO0FBQ3hDLFVBQU1iLFNBQVMsR0FBR0MsZ0JBQU9DLFNBQVAsR0FBbUJDLEdBQXJDOztBQUNBLFFBQUksQ0FBQ0gsU0FBTCxFQUNFLE1BQU0sSUFBSVgsS0FBSixDQUFVLHFDQUFWLENBQU47QUFDRixVQUFNaUIsTUFBTSxHQUFHTixTQUFTLENBQUNPLGFBQVYsSUFBMkIsQ0FBQ00sT0FBTyxJQUFJLEVBQVosRUFBZ0JQLE1BQTNDLElBQXFELCtCQUFjLFlBQWQsQ0FBcEU7QUFFQU8sSUFBQUEsT0FBTyxHQUFHQSxPQUFPLElBQUksRUFBckI7QUFDQUEsSUFBQUEsT0FBTyxDQUFDMkIsYUFBUixHQUF3QjNCLE9BQU8sQ0FBQzJCLGFBQVIsSUFBeUIsRUFBakQ7QUFFQSxVQUFNL0IsV0FBVyxHQUFHTCxnQkFBSUMsTUFBSixDQUFXSSxXQUEvQjtBQUNBLFFBQUlnQyxLQUFLLEdBQUcsQ0FBWjtBQUNBLFFBQUlqRCxNQUFNLEdBQUcsbUJBQWI7O0FBQ0EsUUFBSTtBQUNGO0FBQ0EsWUFBTWtELE9BQU8sR0FBR0gsZ0JBQWdCLENBQUM7QUFBRTlCLFFBQUFBLFdBQVcsRUFBRUEsV0FBZjtBQUE0QkgsUUFBQUEsTUFBTSxFQUFFQTtBQUFwQyxPQUFELENBQWhDO0FBQ0EsWUFBTXFDLEdBQUcsR0FBRy9CLElBQUksQ0FBQzhCLE9BQUQsQ0FBaEI7QUFDQSxVQUFJQyxHQUFHLEtBQUtDLFNBQVosRUFDRSxNQUFNLElBQUl2RCxLQUFKLENBQVcsc0NBQXFDaUQsV0FBWSxzQ0FBNUQsQ0FBTixDQUxBLENBTUY7O0FBQ0E5QyxNQUFBQSxNQUFNLEdBQUdxQixPQUFPLENBQUNyQixNQUFSLElBQWtCbUQsR0FBRyxDQUFDLFdBQUQsQ0FBOUI7QUFFQSxVQUFJLENBQUM5QixPQUFPLENBQUNnQyxLQUFiLEVBQ0VuRSxLQUFLLENBQUUsMEJBQUYsRUFBNkI7QUFBQzRELFFBQUFBLFdBQUQ7QUFBYzlDLFFBQUFBO0FBQWQsT0FBN0IsQ0FBTDtBQUVGLFVBQUlzRCxNQUFKO0FBQ0EsVUFBSUMsT0FBTyxHQUFHLEtBQWQ7QUFDQSxVQUFJcEQsSUFBSjs7QUFDQSxTQUFHO0FBQ0QsWUFBSTtBQUNGOEMsVUFBQUEsS0FBSyxHQUFHTyxJQUFJLENBQUNDLEdBQUwsRUFBUjtBQUNBSCxVQUFBQSxNQUFNLEdBQUcsTUFBTUgsR0FBRyxDQUFDTyxPQUFKLEVBQWY7QUFDQUgsVUFBQUEsT0FBTyxHQUFHLElBQVY7QUFDRCxTQUpELENBSUUsT0FBT3hELEdBQVAsRUFBWTtBQUNaO0FBQ0EsZ0JBQU00RCxZQUFZLEdBQUd0QyxPQUFPLENBQUMyQixhQUFSLENBQXNCakQsR0FBRyxDQUFDSSxJQUExQixDQUFyQjtBQUNBLGNBQUksQ0FBQ3dELFlBQUwsRUFDRSxNQUFNNUQsR0FBTjs7QUFDRixrQkFBUTRELFlBQVksQ0FBQ0MsSUFBckI7QUFDQSxpQkFBSyxPQUFMO0FBQ0Usa0JBQUk7QUFDRkQsZ0JBQUFBLFlBQVksQ0FBQ0UsS0FBYixHQUFxQkYsWUFBWSxDQUFDRSxLQUFiLElBQXNCLENBQTNDOztBQUNBLG9CQUFJRixZQUFZLENBQUNFLEtBQWIsS0FBdUIsQ0FBdkIsSUFBNEJGLFlBQVksQ0FBQ0csTUFBN0MsRUFBcUQ7QUFDbkQsd0JBQU1ILFlBQVksQ0FBQ0csTUFBYixDQUFvQi9ELEdBQXBCLENBQU47QUFDRDtBQUNGLGVBTEQsQ0FLRSxPQUFPZ0UsSUFBUCxFQUFhO0FBQ2JBLGdCQUFBQSxJQUFJLENBQUNDLFlBQUwsR0FBb0JqRSxHQUFwQjtBQUNBLHNCQUFNZ0UsSUFBTjtBQUNEOztBQUNEOztBQUNGLGlCQUFLLFFBQUw7QUFDRTVELGNBQUFBLElBQUksR0FBR0osR0FBRyxDQUFDSSxJQUFYO0FBQ0FvRCxjQUFBQSxPQUFPLEdBQUcsSUFBVjtBQUNBcEUsY0FBQUEsR0FBRyxDQUFFLEdBQUUyRCxXQUFZLFFBQU85QyxNQUFPLDBDQUE5QixFQUF5RTtBQUFFRyxnQkFBQUEsSUFBSSxFQUFFQSxJQUFSO0FBQWM4RCxnQkFBQUEsRUFBRSxFQUFFVCxJQUFJLENBQUNDLEdBQUwsS0FBYVI7QUFBL0IsZUFBekUsQ0FBSDtBQUNBOztBQUNGO0FBQ0Usb0JBQU0sSUFBSXBELEtBQUosQ0FBVyxrQ0FBaUM4RCxZQUFZLENBQUNDLElBQUssR0FBOUQsQ0FBTjtBQWxCRjtBQW9CRDtBQUNGLE9BL0JELFFBK0JTLENBQUNMLE9BL0JWOztBQWlDQSxVQUFJLENBQUNsQyxPQUFPLENBQUNnQyxLQUFiLEVBQ0VuRSxLQUFLLENBQUUseUJBQUYsRUFBNEI7QUFBRTRELFFBQUFBLFdBQUY7QUFBZTlDLFFBQUFBLE1BQWY7QUFBdUJpRSxRQUFBQSxFQUFFLEVBQUVULElBQUksQ0FBQ0MsR0FBTCxLQUFhUjtBQUF4QyxPQUE1QixDQUFMO0FBQ0YxRCxNQUFBQSxTQUFTLENBQUUsR0FBRU4sV0FBWSxJQUFHNkQsV0FBWSxJQUFHOUMsTUFBTyxVQUF6QyxFQUFvRCxDQUFwRCxDQUFULENBbERFLENBbURGOztBQUNBLGFBQU87QUFDTHNELFFBQUFBLE1BQU0sRUFBRUEsTUFESDtBQUVMbkQsUUFBQUEsSUFBSSxFQUFFQTtBQUZELE9BQVA7QUFJRCxLQXhERCxDQXdERSxPQUFPSixHQUFQLEVBQVk7QUFDWlosTUFBQUEsR0FBRyxDQUFFLEdBQUUyRCxXQUFZLFFBQU85QyxNQUFPLFVBQTlCLEVBQXlDO0FBQUVELFFBQUFBLEdBQUY7QUFBT21FLFFBQUFBLElBQUksRUFBRTdDLE9BQU8sQ0FBQzZDO0FBQXJCLE9BQXpDLENBQUg7QUFDQTNFLE1BQUFBLFNBQVMsQ0FBRSxHQUFFTixXQUFZLElBQUc2RCxXQUFZLElBQUc5QyxNQUFPLE9BQXpDLEVBQWlELENBQWpELENBQVQ7QUFDQSxZQUFNLElBQUlKLFFBQUosQ0FBYUcsR0FBYixFQUFtQixHQUFFK0MsV0FBWSxJQUFHOUMsTUFBTyxFQUEzQyxFQUE4QztBQUFFa0UsUUFBQUEsSUFBSSxFQUFFN0MsT0FBTyxDQUFDNkM7QUFBaEIsT0FBOUMsQ0FBTjtBQUNELEtBNURELFNBNERVO0FBQ1IxRSxNQUFBQSxTQUFTLENBQUUsR0FBRVAsV0FBWSxJQUFHNkQsV0FBWSxJQUFHOUMsTUFBTyxFQUF6QyxFQUE0Q3dELElBQUksQ0FBQ0MsR0FBTCxLQUFhUixLQUF6RCxDQUFUO0FBQ0Q7QUFDRjs7QUF6TjRCIiwic291cmNlc0NvbnRlbnQiOlsiLy9AZmxvd1xuXG5pbXBvcnQgQVdTIGZyb20gJ2F3cy1zZGsnXG5cbmltcG9ydCBTeXN0ZW0gZnJvbSAnLi9TeXN0ZW0nXG5pbXBvcnQgTW9kdWxlIGZyb20gJy4vTW9kdWxlJ1xuaW1wb3J0IHsgdGhyb3dVbnNldEFyZyB9IGZyb20gJy4vZXJyb3JVdGlscydcblxuY29uc3QgeyBNT0RVTEVfTkFNRSwgZGVidWcsIGxvZywgd2FybiwgZXJyb3IsIG5vdGVHYXVnZSwgbm90ZUNvdW50LCBub3RlVGltZXIsIHRyYWNrT3AgfSA9IG5ldyBNb2R1bGUoX19maWxlbmFtZSkgLy8gZXNsaW50LWRpc2FibGUtbGluZSBuby11bnVzZWQtdmFyc1xuXG5jbGFzcyBBV1NFcnJvciBleHRlbmRzIEVycm9yIHtcblxuICBtZXNzYWdlOiBzdHJpbmdcbiAgY29kZTogc3RyaW5nXG4gIHRpbWU6IHN0cmluZ1xuICBzdGF0dXNDb2RlOiBudW1iZXJcbiAgcmV0cnlhYmxlOiBib29sZWFuXG4gIGRhdGE6ID9hbnlcblxuICBcbiAgY29uc3RydWN0b3IoZXJyOiBFcnJvciwgb3BOYW1lOiBzdHJpbmcsIGRhdGE6ID9hbnkpIHtcbiAgICAvLyAkRmxvd0lnbm9yZSAgICBcbiAgICBjb25zdCBtZXNzYWdlID0gYEFXUyBPcCAnJHtvcE5hbWV9JyB0aHJldyAnJHtlcnIuY29kZX0nOiAke2Vyci5tZXNzYWdlfWBcblxuICAgIHN1cGVyKG1lc3NhZ2UpXG5cbiAgICB0aGlzLm1lc3NhZ2UgPSBtZXNzYWdlXG4gICAgLy8gJEZsb3dJZ25vcmVcbiAgICB0aGlzLmNvZGUgPSBlcnIuY29kZVxuICAgIC8vICRGbG93SWdub3JlXG4gICAgdGhpcy50aW1lID0gZXJyLnRpbWVcbiAgICAvLyAkRmxvd0lnbm9yZVxuICAgIHRoaXMuc3RhdHVzQ29kZSA9IGVyci5zdGF0dXNDb2RlXG4gICAgLy8gJEZsb3dJZ25vcmVcbiAgICB0aGlzLnJldHJ5YWJsZSA9IGVyci5yZXRyeWFibGVcblxuICAgIHRoaXMuZGF0YSA9IGRhdGFcbiAgfVxufVxuXG50eXBlIENsaWVudENvbmZpZyA9IHtcbiAgcmVnaW9uOiBzdHJpbmcsXG59XG5cbnR5cGUgQVdTT3BPcHRpb25zID0ge1xuICBhcmdzPzogP0FycmF5PGFueT4sXG4gIG9wTmFtZT86ID9zdHJpbmcsXG4gIHJlZ2lvbj86ID9zdHJpbmcsXG4gIGVycm9ySGFuZGxlcnM/OiA/eyBcbiAgICBbY29kZTogc3RyaW5nXToge1xuICAgICAgdHlwZTogJ2lnbm9yZScgfCAncmV0cnknLFxuICAgICAgdHJpZXM/OiA/bnVtYmVyLFxuICAgICAgYWN0aW9uPzogPyhlcnI6IEFXU0Vycm9yKSA9PiBQcm9taXNlPHZvaWQ+LFxuICAgIH1cbiAgfSxcbiAgbm9Mb2c/OiA/Ym9vbGVhbixcbn1cblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgQVdTQ2xpZW50IHtcblxuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBjb25zdCBhd3NDb25maWcgPSBTeXN0ZW0uZ2V0Q29uZmlnKCkuYXdzXG4gICAgaWYgKCFhd3NDb25maWcpXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ2F3cyBzeXN0ZW0gY29uZmlnIGlzIHVuc2V0JylcblxuICAgIEFXUy5jb25maWcucmVnaW9uID0gYXdzQ29uZmlnLmRlZmF1bHRSZWdpb25cbiAgICBcbiAgICAvLyBzdXBwb3J0IGxvY2FsIGV4ZWN1dGlvblxuICAgIGlmIChhd3NDb25maWcucHJvZmlsZSkge1xuICAgICAgbG9nKCdVc2luZyBwcm9maWxlJywgeyBwcm9maWxlOiBhd3NDb25maWcucHJvZmlsZSB9KVxuICAgICAgQVdTLmNvbmZpZy5jcmVkZW50aWFscyA9IG5ldyBBV1MuU2hhcmVkSW5pRmlsZUNyZWRlbnRpYWxzKHsgcHJvZmlsZTogYXdzQ29uZmlnLnByb2ZpbGUgfSlcbiAgICB9XG4gIH1cblxuICBhc3luYyBydW5TRVM8RCwgRT4gKFxuICAgIGZ1bmM6IChzZXJ2aWNlOiBBV1MuU0VTKSA9PiBBV1MuUmVxdWVzdDxELCBFPixcbiAgICBvcHRpb25zOiA/QVdTT3BPcHRpb25zLFxuICApOiBQcm9taXNlPHsgcmVzdWx0OiBELCBjb2RlPzogP3N0cmluZyB9PiB7XG4gICAgcmV0dXJuIGF3YWl0IHRoaXMuX3J1bk9wKFxuICAgICAgJ1NFUycsXG4gICAgICAoY2xpZW50Q29uZmlnOiBDbGllbnRDb25maWcpID0+IG5ldyBBV1MuU0VTKGNsaWVudENvbmZpZyksXG4gICAgICBmdW5jLFxuICAgICAgb3B0aW9ucylcbiAgfVxuXG4gIGFzeW5jIHJ1blMzPEQsIEU+IChcbiAgICBmdW5jOiAoc2VydmljZTogQVdTLlMzKSA9PiBBV1MuUmVxdWVzdDxELCBFPixcbiAgICBvcHRpb25zOiA/QVdTT3BPcHRpb25zLFxuICApOiBQcm9taXNlPHsgcmVzdWx0OiBELCBjb2RlPzogP3N0cmluZyB9PiB7XG4gICAgcmV0dXJuIGF3YWl0IHRoaXMuX3J1bk9wKFxuICAgICAgJ1MzJyxcbiAgICAgIChjbGllbnRDb25maWc6IENsaWVudENvbmZpZykgPT4gbmV3IEFXUy5TMyhjbGllbnRDb25maWcpLFxuICAgICAgZnVuYyxcbiAgICAgIG9wdGlvbnMpXG4gIH1cblxuICBhc3luYyBydW5Eb2N1bWVudENsaWVudDxELCBFPiAoXG4gICAgZnVuYzogKHNlcnZpY2U6IEFXUy5EeW5hbW9EQi5Eb2N1bWVudENsaWVudCkgPT4gQVdTLlJlcXVlc3Q8RCwgRT4sXG4gICAgb3B0aW9uczogP0FXU09wT3B0aW9ucyxcbiAgKTogUHJvbWlzZTx7IHJlc3VsdDogRCwgY29kZT86ID9zdHJpbmcgfT4ge1xuICAgIHJldHVybiBhd2FpdCB0aGlzLl9ydW5PcChcbiAgICAgICdEb2N1bWVudENsaWVudCcsXG4gICAgICAoY2xpZW50Q29uZmlnOiBDbGllbnRDb25maWcpID0+IG5ldyBBV1MuRHluYW1vREIuRG9jdW1lbnRDbGllbnQoeyBjb252ZXJ0RW1wdHlWYWx1ZXM6IHRydWUsIC4uLmNsaWVudENvbmZpZyB9KSxcbiAgICAgIGZ1bmMsXG4gICAgICBvcHRpb25zKVxuICB9XG5cbiAgYXN5bmMgcnVuRHluYW1vREI8RCwgRT4gKFxuICAgIGZ1bmM6IChzZXJ2aWNlOiBBV1MuRHluYW1vREIpID0+IEFXUy5SZXF1ZXN0PEQsIEU+LFxuICAgIG9wdGlvbnM6ID9BV1NPcE9wdGlvbnMsXG4gICk6IFByb21pc2U8eyByZXN1bHQ6IEQsIGNvZGU/OiA/c3RyaW5nIH0+IHtcbiAgICByZXR1cm4gYXdhaXQgdGhpcy5fcnVuT3AoXG4gICAgICAnRHluYW1vREInLFxuICAgICAgKGNsaWVudENvbmZpZzogQ2xpZW50Q29uZmlnKSA9PiBuZXcgQVdTLkR5bmFtb0RCKGNsaWVudENvbmZpZyksXG4gICAgICBmdW5jLFxuICAgICAgb3B0aW9ucylcbiAgfVxuXG4gIGFzeW5jIHJ1bkFwcGxpY2F0aW9uQXV0b1NjYWxpbmc8RCwgRT4gKFxuICAgIGZ1bmM6IChzZXJ2aWNlOiBBV1MuQXBwbGljYXRpb25BdXRvU2NhbGluZykgPT4gQVdTLlJlcXVlc3Q8RCwgRT4sXG4gICAgb3B0aW9uczogP0FXU09wT3B0aW9ucyxcbiAgKTogUHJvbWlzZTx7IHJlc3VsdDogRCwgY29kZT86ID9zdHJpbmcgfT4ge1xuICAgIHJldHVybiBhd2FpdCB0aGlzLl9ydW5PcChcbiAgICAgICdBcHBsaWNhdGlvbkF1dG9TY2FsaW5nJyxcbiAgICAgIChjbGllbnRDb25maWc6IENsaWVudENvbmZpZykgPT4gbmV3IEFXUy5BcHBsaWNhdGlvbkF1dG9TY2FsaW5nKGNsaWVudENvbmZpZyksXG4gICAgICBmdW5jLFxuICAgICAgb3B0aW9ucylcbiAgfVxuXG4gIGFzeW5jIHJ1bkNsb3VkRnJvbnQ8RCwgRT4gKFxuICAgIGZ1bmM6IChzZXJ2aWNlOiBBV1MuQ2xvdWRGcm9udCkgPT4gQVdTLlJlcXVlc3Q8RCwgRT4sXG4gICAgb3B0aW9uczogP0FXU09wT3B0aW9ucyxcbiAgKTogUHJvbWlzZTx7IHJlc3VsdDogRCwgY29kZT86ID9zdHJpbmcgfT4ge1xuICAgIHJldHVybiBhd2FpdCB0aGlzLl9ydW5PcChcbiAgICAgICdDbG91ZEZyb250JyxcbiAgICAgIChjbGllbnRDb25maWc6IENsaWVudENvbmZpZykgPT4gbmV3IEFXUy5DbG91ZEZyb250KGNsaWVudENvbmZpZyksXG4gICAgICBmdW5jLFxuICAgICAgb3B0aW9ucylcbiAgfVxuXG4gIGFzeW5jIHJ1bkF0aGVuYTxELCBFPiAoXG4gICAgZnVuYzogKHNlcnZpY2U6IEFXUy5BdGhlbmEpID0+IEFXUy5SZXF1ZXN0PEQsIEU+LFxuICAgIG9wdGlvbnM6ID9BV1NPcE9wdGlvbnMsXG4gICk6IFByb21pc2U8eyByZXN1bHQ6IEQsIGNvZGU/OiA/c3RyaW5nIH0+IHtcbiAgICByZXR1cm4gYXdhaXQgdGhpcy5fcnVuT3AoXG4gICAgICAnQXRoZW5hJyxcbiAgICAgIChjbGllbnRDb25maWc6IENsaWVudENvbmZpZykgPT4gbmV3IEFXUy5BdGhlbmEoY2xpZW50Q29uZmlnKSxcbiAgICAgIGZ1bmMsXG4gICAgICBvcHRpb25zKVxuICB9XG5cbiAgYXN5bmMgcnVuU1FTPEQsIEU+IChcbiAgICBmdW5jOiAoc2VydmljZTogQVdTLlNRUykgPT4gQVdTLlJlcXVlc3Q8RCwgRT4sXG4gICAgb3B0aW9uczogP0FXU09wT3B0aW9ucyxcbiAgKTogUHJvbWlzZTx7IHJlc3VsdDogRCwgY29kZT86ID9zdHJpbmcgfT4ge1xuICAgIHJldHVybiBhd2FpdCB0aGlzLl9ydW5PcChcbiAgICAgICdTUVMnLFxuICAgICAgKGNsaWVudENvbmZpZzogQ2xpZW50Q29uZmlnKSA9PiBuZXcgQVdTLlNRUyhjbGllbnRDb25maWcpLFxuICAgICAgZnVuYyxcbiAgICAgIG9wdGlvbnMpXG4gIH1cblxuICBhc3luYyBydW5DbG91ZFdhdGNoPEQsIEU+IChcbiAgICBmdW5jOiAoc2VydmljZTogQVdTLlNRUykgPT4gQVdTLlJlcXVlc3Q8RCwgRT4sXG4gICAgb3B0aW9uczogP0FXU09wT3B0aW9ucyxcbiAgKTogUHJvbWlzZTx7IHJlc3VsdDogRCwgY29kZT86ID9zdHJpbmcgfT4ge1xuICAgIHJldHVybiBhd2FpdCB0aGlzLl9ydW5PcChcbiAgICAgICdDbG91ZFdhdGNoJyxcbiAgICAgIChjbGllbnRDb25maWc6IENsaWVudENvbmZpZykgPT4gbmV3IEFXUy5DbG91ZFdhdGNoKGNsaWVudENvbmZpZyksXG4gICAgICBmdW5jLFxuICAgICAgb3B0aW9ucylcbiAgfVxuXG4gIGFzeW5jIHJ1bkZpcmVob3NlPEQsIEU+IChcbiAgICBmdW5jOiAoc2VydmljZTogQVdTLlNRUykgPT4gQVdTLlJlcXVlc3Q8RCwgRT4sXG4gICAgb3B0aW9uczogP0FXU09wT3B0aW9ucyxcbiAgKTogUHJvbWlzZTx7IHJlc3VsdDogRCwgY29kZT86ID9zdHJpbmcgfT4ge1xuICAgIHJldHVybiBhd2FpdCB0aGlzLl9ydW5PcChcbiAgICAgICdGaXJlaG9zZScsXG4gICAgICAoY2xpZW50Q29uZmlnOiBDbGllbnRDb25maWcpID0+IG5ldyBBV1MuRmlyZWhvc2UoY2xpZW50Q29uZmlnKSxcbiAgICAgIGZ1bmMsXG4gICAgICBvcHRpb25zKVxuICB9XG5cbiAgYXN5bmMgcnVuRVM8RCwgRT4oXG4gICAgZnVuYzogKHNlcnZpY2U6IEFXUy5FUykgPT4gQVdTLlJlcXVlc3Q8RCwgRT4sXG4gICAgb3B0aW9uczogP0FXU09wT3B0aW9ucyxcbiAgKTogUHJvbWlzZTx7IHJlc3VsdDogRCwgY29kZT86ID9zdHJpbmcgfT4ge1xuICAgIHJldHVybiBhd2FpdCB0aGlzLl9ydW5PcChcbiAgICAgICdGaXJlaG9zZScsXG4gICAgICAoY2xpZW50Q29uZmlnOiBDbGllbnRDb25maWcpID0+IG5ldyBBV1MuRVMoY2xpZW50Q29uZmlnKSxcbiAgICAgIGZ1bmMsXG4gICAgICBvcHRpb25zKVxuICB9XG5cbiAgYXN5bmMgX3J1bk9wPEQsIEU+IChcbiAgICBzZXJ2aWNlTmFtZTogc3RyaW5nLFxuICAgIHNlcnZpY2VHZW5lcmF0b3I6IChjbGllbnRDb25maWc6IENsaWVudENvbmZpZykgPT4gT2JqZWN0LFxuICAgIGZ1bmM6IChzZXJ2aWNlOiBPYmplY3QpID0+IEFXUy5SZXF1ZXN0PEQsIEU+LFxuICAgIG9wdGlvbnM6ID9BV1NPcE9wdGlvbnMsXG4gICk6IFByb21pc2U8eyByZXN1bHQ6IEQsIGNvZGU/OiA/c3RyaW5nIH0+IHtcbiAgICBjb25zdCBhd3NDb25maWcgPSBTeXN0ZW0uZ2V0Q29uZmlnKCkuYXdzXG4gICAgaWYgKCFhd3NDb25maWcpXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ2F3cyBjb25maWcgbm90IHNldCBpbiBzeXN0ZW0gY29uZmlnJylcbiAgICBjb25zdCByZWdpb24gPSBhd3NDb25maWcuZGVmYXVsdFJlZ2lvbiB8fCAob3B0aW9ucyB8fCB7fSkucmVnaW9uIHx8IHRocm93VW5zZXRBcmcoJ2F3cyByZWdpb24nKVxuXG4gICAgb3B0aW9ucyA9IG9wdGlvbnMgfHwge31cbiAgICBvcHRpb25zLmVycm9ySGFuZGxlcnMgPSBvcHRpb25zLmVycm9ySGFuZGxlcnMgfHwge31cblxuICAgIGNvbnN0IGNyZWRlbnRpYWxzID0gQVdTLmNvbmZpZy5jcmVkZW50aWFsc1xuICAgIGxldCBzdGFydCA9IDBcbiAgICBsZXQgb3BOYW1lID0gJ3Vua25vd24tb3BlcmF0aW9uJ1xuICAgIHRyeSB7XG4gICAgICAvLyBUT0RPOiByZWNyZWF0ZSBvbmx5IHdoZW4gY3JlZHMgZXhwaXJlP1xuICAgICAgY29uc3Qgc2VydmljZSA9IHNlcnZpY2VHZW5lcmF0b3IoeyBjcmVkZW50aWFsczogY3JlZGVudGlhbHMsIHJlZ2lvbjogcmVnaW9uIH0pXG4gICAgICBjb25zdCByZXEgPSBmdW5jKHNlcnZpY2UpXG4gICAgICBpZiAocmVxID09PSB1bmRlZmluZWQpXG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgQVdTIHJ1blhYWCBtZXRob2QgY2FsbCBvbiBzZXJ2aWNlICcke3NlcnZpY2VOYW1lfScgaXMgbWlzc2luZywgZGlkIHlvdSB1c2VyICdyZXR1cm4nP2ApXG4gICAgICAvLyAkRmxvd0lnbm9yZVxuICAgICAgb3BOYW1lID0gb3B0aW9ucy5vcE5hbWUgfHwgcmVxWydvcGVyYXRpb24nXVxuXG4gICAgICBpZiAoIW9wdGlvbnMubm9Mb2cpXG4gICAgICAgIGRlYnVnKGBBV1Mgb3BlcmF0aW9uIHN0YXJ0ZWQuLi5gLCB7c2VydmljZU5hbWUsIG9wTmFtZX0gKVxuXG4gICAgICBsZXQgcmVzdWx0OiBEXG4gICAgICBsZXQgc3VjY2VzcyA9IGZhbHNlXG4gICAgICBsZXQgY29kZTogP3N0cmluZ1xuICAgICAgZG8ge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIHN0YXJ0ID0gRGF0ZS5ub3coKVxuICAgICAgICAgIHJlc3VsdCA9IGF3YWl0IHJlcS5wcm9taXNlKClcbiAgICAgICAgICBzdWNjZXNzID0gdHJ1ZVxuICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAvLyAkRmxvd0lnbm9yZVxuICAgICAgICAgIGNvbnN0IGVycm9ySGFuZGxlciA9IG9wdGlvbnMuZXJyb3JIYW5kbGVyc1tlcnIuY29kZV1cbiAgICAgICAgICBpZiAoIWVycm9ySGFuZGxlcikgXG4gICAgICAgICAgICB0aHJvdyBlcnJcbiAgICAgICAgICBzd2l0Y2ggKGVycm9ySGFuZGxlci50eXBlKSB7XG4gICAgICAgICAgY2FzZSAncmV0cnknOlxuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgZXJyb3JIYW5kbGVyLnRyaWVzID0gZXJyb3JIYW5kbGVyLnRyaWVzIHx8IDFcbiAgICAgICAgICAgICAgaWYgKGVycm9ySGFuZGxlci50cmllcy0tID4gMCAmJiBlcnJvckhhbmRsZXIuYWN0aW9uKSB7XG4gICAgICAgICAgICAgICAgYXdhaXQgZXJyb3JIYW5kbGVyLmFjdGlvbihlcnIpXG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gY2F0Y2ggKGVycjIpIHtcbiAgICAgICAgICAgICAgZXJyMi5sZWFkaW5nRXJyb3IgPSBlcnJcbiAgICAgICAgICAgICAgdGhyb3cgZXJyMlxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYnJlYWtcbiAgICAgICAgICBjYXNlICdpZ25vcmUnOlxuICAgICAgICAgICAgY29kZSA9IGVyci5jb2RlXG4gICAgICAgICAgICBzdWNjZXNzID0gdHJ1ZVxuICAgICAgICAgICAgbG9nKGAke3NlcnZpY2VOYW1lfSBvcCAnJHtvcE5hbWV9JyBjb21wbGV0ZWQgd2l0aCBhbiBpZ25vcmFibGUgZXJyb3IgY29kZWAsIHsgY29kZTogY29kZSwgbXM6IERhdGUubm93KCkgLSBzdGFydCB9KVxuICAgICAgICAgICAgYnJlYWtcbiAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBVbmV4cGVjdGVkIGVycm9ySGFuZGxlciB0eXBlOiAnJHtlcnJvckhhbmRsZXIudHlwZX0nYClcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0gd2hpbGUgKCFzdWNjZXNzKVxuXG4gICAgICBpZiAoIW9wdGlvbnMubm9Mb2cpXG4gICAgICAgIGRlYnVnKGBBV1Mgb3BlcmF0aW9uIGNvbXBsZXRlZGAsIHsgc2VydmljZU5hbWUsIG9wTmFtZSwgbXM6IERhdGUubm93KCkgLSBzdGFydCB9KVxuICAgICAgbm90ZUNvdW50KGAke01PRFVMRV9OQU1FfS4ke3NlcnZpY2VOYW1lfS4ke29wTmFtZX0uc3VjY2Vzc2AsIDEpXG4gICAgICAvLyAkRmxvd0lnbm9yZSAgIFxuICAgICAgcmV0dXJuIHtcbiAgICAgICAgcmVzdWx0OiByZXN1bHQsXG4gICAgICAgIGNvZGU6IGNvZGUsXG4gICAgICB9XG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICBsb2coYCR7c2VydmljZU5hbWV9IG9wICcke29wTmFtZX0nIGZhaWxlZGAsIHsgZXJyLCBhcmdzOiBvcHRpb25zLmFyZ3MgfSlcbiAgICAgIG5vdGVDb3VudChgJHtNT0RVTEVfTkFNRX0uJHtzZXJ2aWNlTmFtZX0uJHtvcE5hbWV9LmZhaWxgLCAxKVxuICAgICAgdGhyb3cgbmV3IEFXU0Vycm9yKGVyciwgYCR7c2VydmljZU5hbWV9LiR7b3BOYW1lfWAsIHsgYXJnczogb3B0aW9ucy5hcmdzIH0pXG4gICAgfSBmaW5hbGx5IHtcbiAgICAgIG5vdGVUaW1lcihgJHtNT0RVTEVfTkFNRX0uJHtzZXJ2aWNlTmFtZX0uJHtvcE5hbWV9YCwgRGF0ZS5ub3coKSAtIHN0YXJ0KVxuICAgIH1cbiAgfVxufSJdfQ==
\No newline at end of file