UNPKG

47.6 kBJavaScriptView Raw
1'use strict';
2
3Object.defineProperty(exports, "__esModule", {
4 value: true
5});
6exports.Plugin = undefined;
7
8var _keys = require('babel-runtime/core-js/object/keys');
9
10var _keys2 = _interopRequireDefault(_keys);
11
12var _regenerator = require('babel-runtime/regenerator');
13
14var _regenerator2 = _interopRequireDefault(_regenerator);
15
16var _stringify = require('babel-runtime/core-js/json/stringify');
17
18var _stringify2 = _interopRequireDefault(_stringify);
19
20var _asyncToGenerator2 = require('babel-runtime/helpers/asyncToGenerator');
21
22var _asyncToGenerator3 = _interopRequireDefault(_asyncToGenerator2);
23
24var _getIterator2 = require('babel-runtime/core-js/get-iterator');
25
26var _getIterator3 = _interopRequireDefault(_getIterator2);
27
28var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of');
29
30var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf);
31
32var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');
33
34var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
35
36var _createClass2 = require('babel-runtime/helpers/createClass');
37
38var _createClass3 = _interopRequireDefault(_createClass2);
39
40var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn');
41
42var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2);
43
44var _inherits2 = require('babel-runtime/helpers/inherits');
45
46var _inherits3 = _interopRequireDefault(_inherits2);
47
48var _cliEngineCommand = require('cli-engine-command');
49
50var _cliEngineCommand2 = _interopRequireDefault(_cliEngineCommand);
51
52var _path = require('path');
53
54var _path2 = _interopRequireDefault(_path);
55
56var _yarn = require('./yarn');
57
58var _yarn2 = _interopRequireDefault(_yarn);
59
60function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
61
62var Cache = function (_Base) {
63 (0, _inherits3.default)(Cache, _Base);
64
65 function Cache() {
66 (0, _classCallCheck3.default)(this, Cache);
67 return (0, _possibleConstructorReturn3.default)(this, (Cache.__proto__ || (0, _getPrototypeOf2.default)(Cache)).apply(this, arguments));
68 }
69
70 (0, _createClass3.default)(Cache, [{
71 key: 'plugin',
72 value: function plugin(path) {
73 return this.cache.plugins[path];
74 }
75 }, {
76 key: 'updatePlugin',
77 value: function updatePlugin(path, plugin) {
78 this.constructor.updated = true;
79 this.cache.plugins[path] = plugin;
80 }
81 }, {
82 key: 'save',
83 value: function save() {
84 if (!this.constructor.updated) return;
85 try {
86 this.fs.writeJSONSync(this.file, this.cache);
87 } catch (err) {
88 this.warn(err);
89 }
90 }
91 }, {
92 key: 'file',
93 get: function get() {
94 return _path2.default.join(this.config.dirs.cache, 'plugins.json');
95 }
96 }, {
97 key: 'cache',
98 get: function get() {
99 if (this._cache) return this._cache;
100 var initial = { version: this.config.version, plugins: {} };
101 try {
102 this._cache = this.fs.readJSONSync(this.file);
103 } catch (err) {
104 if (err.code !== 'ENOENT') throw err;
105 this._cache = initial;
106 }
107 if (this._cache.version !== this.config.version) this._cache = initial;
108 return this._cache;
109 }
110 }]);
111 return Cache;
112}(_cliEngineCommand.Base);
113/* globals
114 Class
115*/
116
117Cache.updated = false;
118
119
120function undefaultTopic(t) {
121 if (t.default) return t.default;
122 return t;
123}
124
125function undefaultCommand(c) {
126 if (c.default && typeof c.default !== 'boolean') return c.default;
127 return c;
128}
129
130var Plugin = exports.Plugin = function (_Base2) {
131 (0, _inherits3.default)(Plugin, _Base2);
132
133 function Plugin(type, path, config, cache) {
134 (0, _classCallCheck3.default)(this, Plugin);
135
136 var _this2 = (0, _possibleConstructorReturn3.default)(this, (Plugin.__proto__ || (0, _getPrototypeOf2.default)(Plugin)).call(this, config));
137
138 _this2.cache = cache;
139 _this2.type = type;
140 _this2.path = path;
141 var p = _this2.fetch();
142 _this2.name = p.name;
143 _this2.version = p.version;
144 _this2.commands = p.commands;
145 _this2.topics = p.topics;
146 return _this2;
147 }
148
149 (0, _createClass3.default)(Plugin, [{
150 key: 'findCommand',
151 value: function findCommand(cmd) {
152 var c = this.commands.find(function (c) {
153 return c.id === cmd || (c.aliases || []).includes(cmd);
154 });
155 if (!c) return;
156 var topic = c.topic,
157 command = c.command;
158
159 var p = this.require();
160 var Command = (p.commands || []).map(undefaultCommand).find(function (d) {
161 return topic === d.topic && command === d.command;
162 });
163 return typeof Command === 'function' ? Command : this.buildCommand(Command);
164 }
165 }, {
166 key: 'findTopic',
167 value: function findTopic(name) {
168 var t = this.topics.find(function (t) {
169 return t.topic === name;
170 });
171 if (!t) return;
172 var Topic = (this.require().topics || []).find(function (t) {
173 return [t.topic, t.name].includes(name);
174 });
175 return typeof Topic === 'function' ? Topic : this.buildTopic(t);
176 }
177 }, {
178 key: 'buildTopic',
179 value: function buildTopic(t) {
180 var _class, _temp;
181
182 return _temp = _class = function (_Topic) {
183 (0, _inherits3.default)(_class, _Topic);
184
185 function _class() {
186 (0, _classCallCheck3.default)(this, _class);
187 return (0, _possibleConstructorReturn3.default)(this, (_class.__proto__ || (0, _getPrototypeOf2.default)(_class)).apply(this, arguments));
188 }
189
190 return _class;
191 }(_cliEngineCommand.Topic), _class.topic = t.topic, _class.description = t.description, _class.hidden = t.hidden, _temp;
192 }
193 }, {
194 key: 'buildCommand',
195 value: function buildCommand(c) {
196 var _class2, _temp2;
197
198 if (!c.topic) throw new Error('command has no topic');
199 var Base = c.needsApp || c.wantsApp ? _cliEngineCommand.mixins.app(_cliEngineCommand2.default, { required: !!c.needsApp }) : _cliEngineCommand2.default;
200 return _temp2 = _class2 = function (_Base3) {
201 (0, _inherits3.default)(_class2, _Base3);
202
203 function _class2() {
204 (0, _classCallCheck3.default)(this, _class2);
205 return (0, _possibleConstructorReturn3.default)(this, (_class2.__proto__ || (0, _getPrototypeOf2.default)(_class2)).apply(this, arguments));
206 }
207
208 (0, _createClass3.default)(_class2, [{
209 key: 'run',
210 value: function run() {
211 var ctx = {
212 supportsColor: this.color.enabled,
213 auth: {},
214 debug: this.config.debug,
215 flags: this.flags,
216 args: this.args,
217 // flow$ignore
218 app: this.app
219 };
220 if (c.needsAuth) {
221 ctx.auth.password = process.env.HEROKU_API_KEY;
222 if (!ctx.auth.password) {
223 var netrc = require('netrc')();
224 var host = netrc['api.heroku.com'];
225 if (host) ctx.auth.password = host.password;
226 }
227 if (!ctx.auth.password) throw new Error('Not logged in');
228 }
229 return c.run(ctx);
230 }
231 }]);
232 return _class2;
233 }(Base), _class2.topic = c.topic, _class2.command = c.command, _class2.description = c.description, _class2.hidden = c.hidden, _class2.args = c.args || [], _class2.flags = c.flags || [], _temp2;
234 }
235 }, {
236 key: 'fetch',
237 value: function fetch() {
238 var c = this.cache.plugin(this.path);
239 if (c) return c;
240 try {
241 return this.updatePlugin(this.require());
242 } catch (err) {
243 if (this.type === 'builtin') throw err;
244 this.warn(err);
245 return {
246 name: this.path,
247 version: '',
248 commands: [],
249 topics: []
250 };
251 }
252 }
253 }, {
254 key: 'updatePlugin',
255 value: function updatePlugin(plugin) {
256 var name = this.type === 'builtin' ? 'builtin' : this.pjson().name;
257 var version = this.type === 'builtin' ? this.config.version : this.pjson().version;
258 if (!plugin.commands) throw new Error('no commands found');
259 var commands = plugin.commands.map(undefaultCommand).map(function (c) {
260 return {
261 id: c.command ? c.topic + ':' + c.command : c.topic,
262 topic: c.topic,
263 command: c.command,
264 description: c.description,
265 args: c.args,
266 flags: c.flags,
267 help: c.help,
268 usage: c.usage,
269 hidden: !!c.hidden,
270 aliases: c.aliases
271 };
272 });
273 var topics = (plugin.topics || (plugin.topic ? [plugin.topic] : [])).map(undefaultTopic).map(function (t) {
274 return {
275 topic: t.topic || t.name || '',
276 description: t.description,
277 hidden: !!t.hidden
278 };
279 });
280
281 var _iteratorNormalCompletion = true;
282 var _didIteratorError = false;
283 var _iteratorError = undefined;
284
285 try {
286 var _loop = function _loop() {
287 var command = _step.value;
288
289 if (topics.find(function (t) {
290 return t.topic === command.topic;
291 })) return 'continue';
292 topics.push({
293 topic: command.topic,
294 hidden: true
295 });
296 };
297
298 for (var _iterator = (0, _getIterator3.default)(commands), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
299 var _ret = _loop();
300
301 if (_ret === 'continue') continue;
302 }
303 } catch (err) {
304 _didIteratorError = true;
305 _iteratorError = err;
306 } finally {
307 try {
308 if (!_iteratorNormalCompletion && _iterator.return) {
309 _iterator.return();
310 }
311 } finally {
312 if (_didIteratorError) {
313 throw _iteratorError;
314 }
315 }
316 }
317
318 var cachedPlugin = { name: name, version: version, commands: commands, topics: topics };
319 this.cache.updatePlugin(this.path, cachedPlugin);
320 return cachedPlugin;
321 }
322
323 // flow$ignore
324
325 }, {
326 key: 'require',
327 value: function (_require) {
328 function require() {
329 return _require.apply(this, arguments);
330 }
331
332 require.toString = function () {
333 return _require.toString();
334 };
335
336 return require;
337 }(function () {
338 return require(this.path);
339 })
340 // flow$ignore
341
342 }, {
343 key: 'pjson',
344 value: function pjson() {
345 return require(_path2.default.join(this.path, 'package.json'));
346 }
347 }]);
348 return Plugin;
349}(_cliEngineCommand.Base);
350
351var Plugins = function (_Base4) {
352 (0, _inherits3.default)(Plugins, _Base4);
353
354 function Plugins(config) {
355 (0, _classCallCheck3.default)(this, Plugins);
356
357 var _this5 = (0, _possibleConstructorReturn3.default)(this, (Plugins.__proto__ || (0, _getPrototypeOf2.default)(Plugins)).call(this, config));
358
359 _this5.config = config;
360 _this5.cache = new Cache(config);
361 _this5.plugins = [new Plugin('builtin', './commands', config, _this5.cache)].concat(_this5.corePlugins).concat(_this5.userPlugins);
362 _this5.cache.save();
363 _this5.yarn = new _yarn2.default(_this5.config);
364 return _this5;
365 }
366
367 (0, _createClass3.default)(Plugins, [{
368 key: 'list',
369 value: function list() {
370 return this.plugins;
371 }
372 }, {
373 key: 'findCommand',
374 value: function findCommand(cmd) {
375 var _iteratorNormalCompletion2 = true;
376 var _didIteratorError2 = false;
377 var _iteratorError2 = undefined;
378
379 try {
380 for (var _iterator2 = (0, _getIterator3.default)(this.plugins), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
381 var plugin = _step2.value;
382
383 var c = plugin.findCommand(cmd);
384 if (c) return c;
385 }
386 } catch (err) {
387 _didIteratorError2 = true;
388 _iteratorError2 = err;
389 } finally {
390 try {
391 if (!_iteratorNormalCompletion2 && _iterator2.return) {
392 _iterator2.return();
393 }
394 } finally {
395 if (_didIteratorError2) {
396 throw _iteratorError2;
397 }
398 }
399 }
400 }
401 }, {
402 key: 'commandsForTopic',
403 value: function commandsForTopic(topic) {
404 return this.plugins.reduce(function (t, p) {
405 return t.concat(p.commands.filter(function (c) {
406 return c.topic === topic;
407 }).map(function (c) {
408 return p.findCommand(c.id);
409 }));
410 }, []);
411 }
412 }, {
413 key: 'findTopic',
414 value: function findTopic(cmd) {
415 var name = cmd.split(':')[0];
416 var _iteratorNormalCompletion3 = true;
417 var _didIteratorError3 = false;
418 var _iteratorError3 = undefined;
419
420 try {
421 for (var _iterator3 = (0, _getIterator3.default)(this.plugins), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) {
422 var plugin = _step3.value;
423
424 var t = plugin.findTopic(name);
425 if (t) return t;
426 }
427 } catch (err) {
428 _didIteratorError3 = true;
429 _iteratorError3 = err;
430 } finally {
431 try {
432 if (!_iteratorNormalCompletion3 && _iterator3.return) {
433 _iterator3.return();
434 }
435 } finally {
436 if (_didIteratorError3) {
437 throw _iteratorError3;
438 }
439 }
440 }
441 }
442 }, {
443 key: 'setupUserPlugins',
444 value: function () {
445 var _ref = (0, _asyncToGenerator3.default)(_regenerator2.default.mark(function _callee() {
446 var pjson;
447 return _regenerator2.default.wrap(function _callee$(_context) {
448 while (1) {
449 switch (_context.prev = _context.next) {
450 case 0:
451 pjson = _path2.default.join(this.userPluginsDir, 'package.json');
452
453 this.fs.mkdirpSync(this.userPluginsDir);
454 if (!this.fs.existsSync(pjson)) this.fs.writeFileSync(pjson, (0, _stringify2.default)({ private: true }));
455 _context.next = 5;
456 return this.yarn.exec();
457
458 case 5:
459 case 'end':
460 return _context.stop();
461 }
462 }
463 }, _callee, this);
464 }));
465
466 function setupUserPlugins() {
467 return _ref.apply(this, arguments);
468 }
469
470 return setupUserPlugins;
471 }()
472 }, {
473 key: 'install',
474 value: function () {
475 var _ref2 = (0, _asyncToGenerator3.default)(_regenerator2.default.mark(function _callee2(name) {
476 var plugin;
477 return _regenerator2.default.wrap(function _callee2$(_context2) {
478 while (1) {
479 switch (_context2.prev = _context2.next) {
480 case 0:
481 _context2.next = 2;
482 return this.setupUserPlugins();
483
484 case 2:
485 if (!this.config.debug) this.action.start('Installing plugin ' + name);
486 _context2.next = 5;
487 return this.yarn.exec('add', name);
488
489 case 5:
490 this.clearCache(name);
491 _context2.prev = 6;
492
493 // flow$ignore
494 plugin = require(this.userPluginPath(name));
495
496 if (plugin.commands) {
497 _context2.next = 10;
498 break;
499 }
500
501 throw new Error(name + ' does not appear to be a Heroku CLI plugin');
502
503 case 10:
504 _context2.next = 18;
505 break;
506
507 case 12:
508 _context2.prev = 12;
509 _context2.t0 = _context2['catch'](6);
510
511 this.error(_context2.t0, false);
512 _context2.next = 17;
513 return this.uninstall(name);
514
515 case 17:
516 this.exit(1);
517
518 case 18:
519 this.action.stop();
520
521 case 19:
522 case 'end':
523 return _context2.stop();
524 }
525 }
526 }, _callee2, this, [[6, 12]]);
527 }));
528
529 function install(_x) {
530 return _ref2.apply(this, arguments);
531 }
532
533 return install;
534 }()
535 }, {
536 key: 'uninstall',
537 value: function () {
538 var _ref3 = (0, _asyncToGenerator3.default)(_regenerator2.default.mark(function _callee3(name) {
539 return _regenerator2.default.wrap(function _callee3$(_context3) {
540 while (1) {
541 switch (_context3.prev = _context3.next) {
542 case 0:
543 if (!this.config.debug) this.action.start('Uninstalling plugin ' + name);
544 _context3.next = 3;
545 return this.yarn.exec('remove', name);
546
547 case 3:
548 case 'end':
549 return _context3.stop();
550 }
551 }
552 }, _callee3, this);
553 }));
554
555 function uninstall(_x2) {
556 return _ref3.apply(this, arguments);
557 }
558
559 return uninstall;
560 }()
561 }, {
562 key: 'clearCache',
563 value: function clearCache(name) {
564 var _iteratorNormalCompletion4 = true;
565 var _didIteratorError4 = false;
566 var _iteratorError4 = undefined;
567
568 try {
569 for (var _iterator4 = (0, _getIterator3.default)((0, _keys2.default)(this.cache.cache.plugins)), _step4; !(_iteratorNormalCompletion4 = (_step4 = _iterator4.next()).done); _iteratorNormalCompletion4 = true) {
570 var k = _step4.value;
571
572 if (this.cache.cache.plugins[k].name === name) delete this.cache.cache[k];
573 }
574 } catch (err) {
575 _didIteratorError4 = true;
576 _iteratorError4 = err;
577 } finally {
578 try {
579 if (!_iteratorNormalCompletion4 && _iterator4.return) {
580 _iterator4.return();
581 }
582 } finally {
583 if (_didIteratorError4) {
584 throw _iteratorError4;
585 }
586 }
587 }
588
589 this.cache.save();
590 }
591 }, {
592 key: 'userPluginPath',
593 value: function userPluginPath(name) {
594 return _path2.default.join(this.userPluginsDir, 'node_modules', name);
595 }
596 }, {
597 key: 'corePlugins',
598 get: function get() {
599 var _this6 = this;
600
601 return (this.config._cli.plugins || []).map(function (name) {
602 return new Plugin('core', _path2.default.join(_this6.config.root, 'node_modules', name), _this6.config, _this6.cache);
603 });
604 }
605 }, {
606 key: 'userPlugins',
607 get: function get() {
608 var _this7 = this;
609
610 var pjson = this.userPluginsPJSON;
611 return (0, _keys2.default)(pjson.dependencies || {}).map(function (name) {
612 return new Plugin('user', _this7.userPluginPath(name), _this7.config, _this7.cache);
613 });
614 }
615 }, {
616 key: 'userPluginsPJSON',
617 get: function get() {
618 try {
619 return this.fs.readJSONSync(_path2.default.join(this.userPluginsDir, 'package.json'));
620 } catch (err) {
621 return { dependencies: {} };
622 }
623 }
624 }, {
625 key: 'userPluginsDir',
626 get: function get() {
627 return _path2.default.join(this.config.dirs.data, 'plugins');
628 }
629 }, {
630 key: 'topics',
631 get: function get() {
632 return this.plugins.reduce(function (t, p) {
633 return t.concat(p.topics);
634 }, []);
635 }
636 }]);
637 return Plugins;
638}(_cliEngineCommand.Base);
639
640exports.default = Plugins;
641//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9wbHVnaW5zLmpzIl0sIm5hbWVzIjpbIkNhY2hlIiwicGF0aCIsImNhY2hlIiwicGx1Z2lucyIsInBsdWdpbiIsImNvbnN0cnVjdG9yIiwidXBkYXRlZCIsImZzIiwid3JpdGVKU09OU3luYyIsImZpbGUiLCJlcnIiLCJ3YXJuIiwiam9pbiIsImNvbmZpZyIsImRpcnMiLCJfY2FjaGUiLCJpbml0aWFsIiwidmVyc2lvbiIsInJlYWRKU09OU3luYyIsImNvZGUiLCJ1bmRlZmF1bHRUb3BpYyIsInQiLCJkZWZhdWx0IiwidW5kZWZhdWx0Q29tbWFuZCIsImMiLCJQbHVnaW4iLCJ0eXBlIiwicCIsImZldGNoIiwibmFtZSIsImNvbW1hbmRzIiwidG9waWNzIiwiY21kIiwiZmluZCIsImlkIiwiYWxpYXNlcyIsImluY2x1ZGVzIiwidG9waWMiLCJjb21tYW5kIiwicmVxdWlyZSIsIkNvbW1hbmQiLCJtYXAiLCJkIiwiYnVpbGRDb21tYW5kIiwiVG9waWMiLCJidWlsZFRvcGljIiwiZGVzY3JpcHRpb24iLCJoaWRkZW4iLCJFcnJvciIsIkJhc2UiLCJuZWVkc0FwcCIsIndhbnRzQXBwIiwiYXBwIiwicmVxdWlyZWQiLCJjdHgiLCJzdXBwb3J0c0NvbG9yIiwiY29sb3IiLCJlbmFibGVkIiwiYXV0aCIsImRlYnVnIiwiZmxhZ3MiLCJhcmdzIiwibmVlZHNBdXRoIiwicGFzc3dvcmQiLCJwcm9jZXNzIiwiZW52IiwiSEVST0tVX0FQSV9LRVkiLCJuZXRyYyIsImhvc3QiLCJydW4iLCJ1cGRhdGVQbHVnaW4iLCJwanNvbiIsImhlbHAiLCJ1c2FnZSIsInB1c2giLCJjYWNoZWRQbHVnaW4iLCJQbHVnaW5zIiwiY29uY2F0IiwiY29yZVBsdWdpbnMiLCJ1c2VyUGx1Z2lucyIsInNhdmUiLCJ5YXJuIiwiZmluZENvbW1hbmQiLCJyZWR1Y2UiLCJmaWx0ZXIiLCJzcGxpdCIsImZpbmRUb3BpYyIsInVzZXJQbHVnaW5zRGlyIiwibWtkaXJwU3luYyIsImV4aXN0c1N5bmMiLCJ3cml0ZUZpbGVTeW5jIiwicHJpdmF0ZSIsImV4ZWMiLCJzZXR1cFVzZXJQbHVnaW5zIiwiYWN0aW9uIiwic3RhcnQiLCJjbGVhckNhY2hlIiwidXNlclBsdWdpblBhdGgiLCJlcnJvciIsInVuaW5zdGFsbCIsImV4aXQiLCJzdG9wIiwiayIsIl9jbGkiLCJyb290IiwidXNlclBsdWdpbnNQSlNPTiIsImRlcGVuZGVuY2llcyIsImRhdGEiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBS0E7Ozs7QUFDQTs7OztBQUNBOzs7Ozs7SUEwRU1BLEs7Ozs7Ozs7Ozs7MkJBa0JJQyxJLEVBQTZCO0FBQUUsYUFBTyxLQUFLQyxLQUFMLENBQVdDLE9BQVgsQ0FBbUJGLElBQW5CLENBQVA7QUFBaUM7OztpQ0FDMURBLEksRUFBY0csTSxFQUFzQjtBQUNoRCxXQUFLQyxXQUFMLENBQWlCQyxPQUFqQixHQUEyQixJQUEzQjtBQUNBLFdBQUtKLEtBQUwsQ0FBV0MsT0FBWCxDQUFtQkYsSUFBbkIsSUFBMkJHLE1BQTNCO0FBQ0Q7OzsyQkFFTztBQUNOLFVBQUksQ0FBQyxLQUFLQyxXQUFMLENBQWlCQyxPQUF0QixFQUErQjtBQUMvQixVQUFJO0FBQ0YsYUFBS0MsRUFBTCxDQUFRQyxhQUFSLENBQXNCLEtBQUtDLElBQTNCLEVBQWlDLEtBQUtQLEtBQXRDO0FBQ0QsT0FGRCxDQUVFLE9BQU9RLEdBQVAsRUFBWTtBQUNaLGFBQUtDLElBQUwsQ0FBVUQsR0FBVjtBQUNEO0FBQ0Y7Ozt3QkEzQm1CO0FBQUUsYUFBTyxlQUFLRSxJQUFMLENBQVUsS0FBS0MsTUFBTCxDQUFZQyxJQUFaLENBQWlCWixLQUEzQixFQUFrQyxjQUFsQyxDQUFQO0FBQTBEOzs7d0JBQ3hEO0FBQ3RCLFVBQUksS0FBS2EsTUFBVCxFQUFpQixPQUFPLEtBQUtBLE1BQVo7QUFDakIsVUFBSUMsVUFBVSxFQUFDQyxTQUFTLEtBQUtKLE1BQUwsQ0FBWUksT0FBdEIsRUFBK0Jk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c1xuICAgQ2xhc3NcbiovXG5cbmltcG9ydCBDb21tYW5kLCB7Q29uZmlnLCBCYXNlLCBUb3BpYywgbWl4aW5zLCB0eXBlIEZsYWcsIHR5cGUgQXJnfSBmcm9tICdjbGktZW5naW5lLWNvbW1hbmQnXG5pbXBvcnQgcGF0aCBmcm9tICdwYXRoJ1xuaW1wb3J0IFlhcm4gZnJvbSAnLi95YXJuJ1xuXG50eXBlIFBsdWdpblR5cGUgPSB8IFwiYnVpbHRpblwiIHwgXCJjb3JlXCIgfCBcInVzZXJcIlxuXG50eXBlIExlZ2FjeUNvbW1hbmQgPSB7XG4gIHRvcGljOiBzdHJpbmcsXG4gIGNvbW1hbmQ/OiBzdHJpbmcsXG4gIGFsaWFzZXM/OiBzdHJpbmdbXSxcbiAgYXJnczogQXJnW10sXG4gIGZsYWdzOiBGbGFnW10sXG4gIGRlc2NyaXB0aW9uPzogP3N0cmluZyxcbiAgaGVscD86ID9zdHJpbmcsXG4gIHVzYWdlPzogP3N0cmluZyxcbiAgbmVlZHNBcHA/OiA/Ym9vbGVhbixcbiAgbmVlZHNBdXRoPzogP2Jvb2xlYW4sXG4gIGhpZGRlbj86ID9ib29sZWFuLFxuICBkZWZhdWx0PzogP2Jvb2xlYW4sXG4gIHJ1bjogKGN0eDogTGVnYWN5Q29udGV4dCkgPT4gUHJvbWlzZTxhbnk+XG59XG5cbnR5cGUgTGVnYWN5Q29udGV4dCA9IHtcbiAgc3VwcG9ydHNDb2xvcjogYm9vbGVhblxufVxuXG50eXBlIFBhcnNlZFRvcGljID0gfCB7XG4gIG5hbWU/OiA/c3RyaW5nLFxuICB0b3BpYz86ID9zdHJpbmcsXG4gIGRlc2NyaXB0aW9uPzogP3N0cmluZyxcbiAgaGlkZGVuPzogP2Jvb2xlYW5cbn0gfCBDbGFzczxUb3BpYz5cblxudHlwZSBQYXJzZWRDb21tYW5kID0gfCBMZWdhY3lDb21tYW5kIHwgQ2xhc3M8Q29tbWFuZD5cblxudHlwZSBQYXJzZWRQbHVnaW4gPSB7XG4gIHRvcGljPzogUGFyc2VkVG9waWMsXG4gIHRvcGljcz86IFBhcnNlZFRvcGljW10sXG4gIGNvbW1hbmRzPzogKFBhcnNlZENvbW1hbmQgfCB7ZGVmYXVsdDogUGFyc2VkQ29tbWFuZH0pW11cbn1cblxudHlwZSBDYWNoZWRDb21tYW5kID0ge1xuICBpZDogc3RyaW5nLFxuICB0b3BpYzogc3RyaW5nLFxuICBjb21tYW5kPzogP3N0cmluZyxcbiAgYWxpYXNlcz86IHN0cmluZ1tdLFxuICBhcmdzOiBBcmdbXSxcbiAgZmxhZ3M6IEZsYWdbXSxcbiAgZGVzY3JpcHRpb246ID9zdHJpbmcsXG4gIGhlbHA/OiA/c3RyaW5nLFxuICB1c2FnZT86ID9zdHJpbmcsXG4gIGhpZGRlbjogYm9vbGVhblxufVxuXG50eXBlIENhY2hlZFRvcGljID0ge1xuICB0b3BpYzogc3RyaW5nLFxuICBkZXNjcmlwdGlvbj86ID9zdHJpbmcsXG4gIGhpZGRlbjogYm9vbGVhblxufVxuXG50eXBlIENhY2hlZFBsdWdpbiA9IHtcbiAgbmFtZTogc3RyaW5nLFxuICB2ZXJzaW9uOiBzdHJpbmcsXG4gIGNvbW1hbmRzOiBDYWNoZWRDb21tYW5kW10sXG4gIHRvcGljczogQ2FjaGVkVG9waWNbXVxufVxuXG50eXBlIENhY2hlRGF0YSA9IHtcbiAgdmVyc2lvbjogc3RyaW5nLFxuICBwbHVnaW5zOiB7W3BhdGg6IHN0cmluZ106IENhY2hlZFBsdWdpbn1cbn1cblxudHlwZSBQSlNPTiA9IHtcbiAgZGVwZW5kZW5jaWVzPzogeyBbbmFtZTogc3RyaW5nXTogc3RyaW5nIH1cbn1cblxuY2xhc3MgQ2FjaGUgZXh0ZW5kcyBCYXNlIHtcbiAgc3RhdGljIHVwZGF0ZWQgPSBmYWxzZVxuICBfY2FjaGU6IENhY2hlRGF0YVxuXG4gIGdldCBmaWxlICgpOiBzdHJpbmcgeyByZXR1cm4gcGF0aC5qb2luKHRoaXMuY29uZmlnLmRpcnMuY2FjaGUsICdwbHVnaW5zLmpzb24nKSB9XG4gIGdldCBjYWNoZSAoKTogQ2FjaGVEYXRhIHtcbiAgICBpZiAodGhpcy5fY2FjaGUpIHJldHVybiB0aGlzLl9jYWNoZVxuICAgIGxldCBpbml0aWFsID0ge3ZlcnNpb246IHRoaXMuY29uZmlnLnZlcnNpb24sIHBsdWdpbnM6IHt9fVxuICAgIHRyeSB7XG4gICAgICB0aGlzLl9jYWNoZSA9IHRoaXMuZnMucmVhZEpTT05TeW5jKHRoaXMuZmlsZSlcbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIGlmIChlcnIuY29kZSAhPT0gJ0VOT0VOVCcpIHRocm93IGVyclxuICAgICAgdGhpcy5fY2FjaGUgPSBpbml0aWFsXG4gICAgfVxuICAgIGlmICh0aGlzLl9jYWNoZS52ZXJzaW9uICE9PSB0aGlzLmNvbmZpZy52ZXJzaW9uKSB0aGlzLl9jYWNoZSA9IGluaXRpYWxcbiAgICByZXR1cm4gdGhpcy5fY2FjaGVcbiAgfVxuXG4gIHBsdWdpbiAocGF0aDogc3RyaW5nKTogP0NhY2hlZFBsdWdpbiB7IHJldHVybiB0aGlzLmNhY2hlLnBsdWdpbnNbcGF0aF0gfVxuICB1cGRhdGVQbHVnaW4gKHBhdGg6IHN0cmluZywgcGx1Z2luOiBDYWNoZWRQbHVnaW4pIHtcbiAgICB0aGlzLmNvbnN0cnVjdG9yLnVwZGF0ZWQgPSB0cnVlXG4gICAgdGhpcy5jYWNoZS5wbHVnaW5zW3BhdGhdID0gcGx1Z2luXG4gIH1cblxuICBzYXZlICgpIHtcbiAgICBpZiAoIXRoaXMuY29uc3RydWN0b3IudXBkYXRlZCkgcmV0dXJuXG4gICAgdHJ5IHtcbiAgICAgIHRoaXMuZnMud3JpdGVKU09OU3luYyh0aGlzLmZpbGUsIHRoaXMuY2FjaGUpXG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICB0aGlzLndhcm4oZXJyKVxuICAgIH1cbiAgfVxufVxuXG5mdW5jdGlvbiB1bmRlZmF1bHRUb3BpYyAodDogKFBhcnNlZFRvcGljIHwge2RlZmF1bHQ6IFBhcnNlZFRvcGljfSkpOiBQYXJzZWRUb3BpYyB7XG4gIGlmICh0LmRlZmF1bHQpIHJldHVybiAodC5kZWZhdWx0OiBhbnkpXG4gIHJldHVybiB0XG59XG5cbmZ1bmN0aW9uIHVuZGVmYXVsdENvbW1hbmQgKGM6IChQYXJzZWRDb21tYW5kIHwge2RlZmF1bHQ6IFBhcnNlZENvbW1hbmR9KSk6IFBhcnNlZENvbW1hbmQge1xuICBpZiAoYy5kZWZhdWx0ICYmIHR5cGVvZiBjLmRlZmF1bHQgIT09ICdib29sZWFuJykgcmV0dXJuIChjLmRlZmF1bHQ6IGFueSlcbiAgcmV0dXJuIChjOiBhbnkpXG59XG5cbmV4cG9ydCBjbGFzcyBQbHVnaW4gZXh0ZW5kcyBCYXNlIHtcbiAgY29uc3RydWN0b3IgKHR5cGU6IFBsdWdpblR5cGUsIHBhdGg6IHN0cmluZywgY29uZmlnOiBDb25maWcsIGNhY2hlOiBDYWNoZSkge1xuICAgIHN1cGVyKGNvbmZpZylcbiAgICB0aGlzLmNhY2hlID0gY2FjaGVcbiAgICB0aGlzLnR5cGUgPSB0eXBlXG4gICAgdGhpcy5wYXRoID0gcGF0aFxuICAgIGxldCBwID0gdGhpcy5mZXRjaCgpXG4gICAgdGhpcy5uYW1lID0gcC5uYW1lXG4gICAgdGhpcy52ZXJzaW9uID0gcC52ZXJzaW9uXG4gICAgdGhpcy5jb21tYW5kcyA9IHAuY29tbWFuZHNcbiAgICB0aGlzLnRvcGljcyA9IHAudG9waWNzXG4gIH1cblxuICB0eXBlOiBQbHVnaW5UeXBlXG4gIHBhdGg6IHN0cmluZ1xuICBjYWNoZTogQ2FjaGVcbiAgbmFtZTogc3RyaW5nXG4gIHZlcnNpb246IHN0cmluZ1xuICBjb21tYW5kczogQ2FjaGVkQ29tbWFuZFtdXG4gIHRvcGljczogQ2FjaGVkVG9waWNbXVxuXG4gIGZpbmRDb21tYW5kIChjbWQ6IHN0cmluZyk6ID9DbGFzczxDb21tYW5kPiB7XG4gICAgbGV0IGMgPSB0aGlzLmNvbW1hbmRzLmZpbmQoYyA9PiBjLmlkID09PSBjbWQgfHwgKGMuYWxpYXNlcyB8fCBbXSkuaW5jbHVkZXMoY21kKSlcbiAgICBpZiAoIWMpIHJldHVyblxuICAgIGxldCB7dG9waWMsIGNvbW1hbmR9ID0gY1xuICAgIGxldCBwID0gdGhpcy5yZXF1aXJlKClcbiAgICBsZXQgQ29tbWFuZCA9IChwLmNvbW1hbmRzIHx8IFtdKVxuICAgICAgLm1hcCh1bmRlZmF1bHRDb21tYW5kKVxuICAgICAgLmZpbmQoZCA9PiB0b3BpYyA9PT0gZC50b3BpYyAmJiBjb21tYW5kID09PSBkLmNvbW1hbmQpXG4gICAgcmV0dXJuIHR5cGVvZiBDb21tYW5kID09PSAnZnVuY3Rpb24nID8gQ29tbWFuZCA6IHRoaXMuYnVpbGRDb21tYW5kKChDb21tYW5kOiBhbnkpKVxuICB9XG5cbiAgZmluZFRvcGljIChuYW1lOiBzdHJpbmcpOiA/Q2xhc3M8VG9waWM+IHtcbiAgICBsZXQgdCA9IHRoaXMudG9waWNzLmZpbmQodCA9PiB0LnRvcGljID09PSBuYW1lKVxuICAgIGlmICghdCkgcmV0dXJuXG4gICAgbGV0IFRvcGljID0gKHRoaXMucmVxdWlyZSgpLnRvcGljcyB8fCBbXSlcbiAgICAgIC5maW5kKHQgPT4gW3QudG9waWMsIHQubmFtZV0uaW5jbHVkZXMobmFtZSkpXG4gICAgcmV0dXJuIHR5cGVvZiBUb3BpYyA9PT0gJ2Z1bmN0aW9uJyA/IFRvcGljIDogdGhpcy5idWlsZFRvcGljKHQpXG4gIH1cblxuICBidWlsZFRvcGljICh0OiBDYWNoZWRUb3BpYyk6IENsYXNzPFRvcGljPiB7XG4gICAgcmV0dXJuIGNsYXNzIGV4dGVuZHMgVG9waWMge1xuICAgICAgc3RhdGljIHRvcGljID0gdC50b3BpY1xuICAgICAgc3RhdGljIGRlc2NyaXB0aW9uID0gdC5kZXNjcmlwdGlvblxuICAgICAgc3RhdGljIGhpZGRlbiA9IHQuaGlkZGVuXG4gICAgfVxuICB9XG5cbiAgYnVpbGRDb21tYW5kIChjOiBMZWdhY3lDb21tYW5kKTogQ2xhc3M8Q29tbWFuZD4ge1xuICAgIGlmICghYy50b3BpYykgdGhyb3cgbmV3IEVycm9yKCdjb21tYW5kIGhhcyBubyB0b3BpYycpXG4gICAgbGV0IEJhc2UgPSAoYy5uZWVkc0FwcCB8fCBjLndhbnRzQXBwKVxuICAgID8gbWl4aW5zLmFwcChDb21tYW5kLCB7cmVxdWlyZWQ6ICEhYy5uZWVkc0FwcH0pXG4gICAgOiBDb21tYW5kXG4gICAgcmV0dXJuIGNsYXNzIGV4dGVuZHMgQmFzZSB7XG4gICAgICBzdGF0aWMgdG9waWMgPSBjLnRvcGljXG4gICAgICBzdGF0aWMgY29tbWFuZCA9IGMuY29tbWFuZFxuICAgICAgc3RhdGljIGRlc2NyaXB0aW9uID0gYy5kZXNjcmlwdGlvblxuICAgICAgc3RhdGljIGhpZGRlbiA9IGMuaGlkZGVuXG4gICAgICBzdGF0aWMgYXJncyA9IGMuYXJncyB8fCBbXVxuICAgICAgc3RhdGljIGZsYWdzID0gYy5mbGFncyB8fCBbXVxuXG4gICAgICBydW4gKCkge1xuICAgICAgICBjb25zdCBjdHggPSB7XG4gICAgICAgICAgc3VwcG9ydHNDb2xvcjogdGhpcy5jb2xvci5lbmFibGVkLFxuICAgICAgICAgIGF1dGg6IHt9LFxuICAgICAgICAgIGRlYnVnOiB0aGlzLmNvbmZpZy5kZWJ1ZyxcbiAgICAgICAgICBmbGFnczogdGhpcy5mbGFncyxcbiAgICAgICAgICBhcmdzOiB0aGlzLmFyZ3MsXG4gICAgICAgICAgLy8gZmxvdyRpZ25vcmVcbiAgICAgICAgICBhcHA6IHRoaXMuYXBwXG4gICAgICAgIH1cbiAgICAgICAgaWYgKGMubmVlZHNBdXRoKSB7XG4gICAgICAgICAgY3R4LmF1dGgucGFzc3dvcmQgPSBwcm9jZXNzLmVudi5IRVJPS1VfQVBJX0tFWVxuICAgICAgICAgIGlmICghY3R4LmF1dGgucGFzc3dvcmQpIHtcbiAgICAgICAgICAgIGNvbnN0IG5ldHJjID0gcmVxdWlyZSgnbmV0cmMnKSgpXG4gICAgICAgICAgICBjb25zdCBob3N0ID0gbmV0cmNbJ2FwaS5oZXJva3UuY29tJ11cbiAgICAgICAgICAgIGlmIChob3N0KSBjdHguYXV0aC5wYXNzd29yZCA9IGhvc3QucGFzc3dvcmRcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKCFjdHguYXV0aC5wYXNzd29yZCkgdGhyb3cgbmV3IEVycm9yKCdOb3QgbG9nZ2VkIGluJylcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gYy5ydW4oY3R4KVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIGZldGNoICgpOiBDYWNoZWRQbHVnaW4ge1xuICAgIGxldCBjID0gdGhpcy5jYWNoZS5wbHVnaW4odGhpcy5wYXRoKVxuICAgIGlmIChjKSByZXR1cm4gY1xuICAgIHRyeSB7XG4gICAgICByZXR1cm4gdGhpcy51cGRhdGVQbHVnaW4odGhpcy5yZXF1aXJlKCkpXG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICBpZiAodGhpcy50eXBlID09PSAnYnVpbHRpbicpIHRocm93IGVyclxuICAgICAgdGhpcy53YXJuKGVycilcbiAgICAgIHJldHVybiB7XG4gICAgICAgIG5hbWU6IHRoaXMucGF0aCxcbiAgICAgICAgdmVyc2lvbjogJycsXG4gICAgICAgIGNvbW1hbmRzOiBbXSxcbiAgICAgICAgdG9waWNzOiBbXVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHVwZGF0ZVBsdWdpbiAocGx1Z2luOiBQYXJzZWRQbHVnaW4pOiBDYWNoZWRQbHVnaW4ge1xuICAgIGNvbnN0IG5hbWUgPSB0aGlzLnR5cGUgPT09ICdidWlsdGluJyA/ICdidWlsdGluJyA6IHRoaXMucGpzb24oKS5uYW1lXG4gICAgY29uc3QgdmVyc2lvbiA9IHRoaXMudHlwZSA9PT0gJ2J1aWx0aW4nID8gdGhpcy5jb25maWcudmVyc2lvbiA6IHRoaXMucGpzb24oKS52ZXJzaW9uXG4gICAgaWYgKCFwbHVnaW4uY29tbWFuZHMpIHRocm93IG5ldyBFcnJvcignbm8gY29tbWFuZHMgZm91bmQnKVxuICAgIGNvbnN0IGNvbW1hbmRzOiBDYWNoZWRDb21tYW5kW10gPSBwbHVnaW4uY29tbWFuZHNcbiAgICAubWFwKHVuZGVmYXVsdENvbW1hbmQpXG4gICAgLm1hcChjID0+ICh7XG4gICAgICBpZDogYy5jb21tYW5kID8gYCR7Yy50b3BpY306JHtjLmNvbW1hbmR9YCA6IGMudG9waWMsXG4gICAgICB0b3BpYzogYy50b3BpYyxcbiAgICAgIGNvbW1hbmQ6IGMuY29tbWFuZCxcbiAgICAgIGRlc2NyaXB0aW9uOiBjLmRlc2NyaXB0aW9uLFxuICAgICAgYXJnczogYy5hcmdzLFxuICAgICAgZmxhZ3M6IGMuZmxhZ3MsXG4gICAgICBoZWxwOiBjLmhlbHAsXG4gICAgICB1c2FnZTogYy51c2FnZSxcbiAgICAgIGhpZGRlbjogISFjLmhpZGRlbixcbiAgICAgIGFsaWFzZXM6IGMuYWxpYXNlc1xuICAgIH0pKVxuICAgIGNvbnN0IHRvcGljczogQ2FjaGVkVG9waWNbXSA9IChwbHVnaW4udG9waWNzIHx8IChwbHVnaW4udG9waWMgPyBbcGx1Z2luLnRvcGljXSA6IFtdKSlcbiAgICAubWFwKHVuZGVmYXVsdFRvcGljKVxuICAgIC5tYXAodCA9PiAoe1xuICAgICAgdG9waWM6IHQudG9waWMgfHwgdC5uYW1lIHx8ICcnLFxuICAgICAgZGVzY3JpcHRpb246IHQuZGVzY3JpcHRpb24sXG4gICAgICBoaWRkZW46ICEhdC5oaWRkZW5cbiAgICB9KSlcblxuICAgIGZvciAobGV0IGNvbW1hbmQgb2YgY29tbWFuZHMpIHtcbiAgICAgIGlmICh0b3BpY3MuZmluZCh0ID0+IHQudG9waWMgPT09IGNvbW1hbmQudG9waWMpKSBjb250aW51ZVxuICAgICAgdG9waWNzLnB1c2goe1xuICAgICAgICB0b3BpYzogY29tbWFuZC50b3BpYyxcbiAgICAgICAgaGlkZGVuOiB0cnVlXG4gICAgICB9KVxuICAgIH1cblxuICAgIGNvbnN0IGNhY2hlZFBsdWdpbjogQ2FjaGVkUGx1Z2luID0ge25hbWUsIHZlcnNpb24sIGNvbW1hbmRzLCB0b3BpY3N9XG4gICAgdGhpcy5jYWNoZS51cGRhdGVQbHVnaW4odGhpcy5wYXRoLCBjYWNoZWRQbHVnaW4pXG4gICAgcmV0dXJuIGNhY2hlZFBsdWdpblxuICB9XG5cbiAgLy8gZmxvdyRpZ25vcmVcbiAgcmVxdWlyZSAoKTogUGFyc2VkUGx1Z2luIHsgcmV0dXJuIHJlcXVpcmUodGhpcy5wYXRoKSB9XG4gIC8vIGZsb3ckaWdub3JlXG4gIHBqc29uICgpOiB7bmFtZTogc3RyaW5nLCB2ZXJzaW9uOiBzdHJpbmd9IHsgcmV0dXJuIHJlcXVpcmUocGF0aC5qb2luKHRoaXMucGF0aCwgJ3BhY2thZ2UuanNvbicpKSB9XG59XG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFBsdWdpbnMgZXh0ZW5kcyBCYXNlIHtcbiAgY29uc3RydWN0b3IgKGNvbmZpZzogQ29uZmlnKSB7XG4gICAgc3VwZXIoY29uZmlnKVxuICAgIHRoaXMuY29uZmlnID0gY29uZmlnXG4gICAgdGhpcy5jYWNoZSA9IG5ldyBDYWNoZShjb25maWcpXG4gICAgdGhpcy5wbHVnaW5zID0gW25ldyBQbHVnaW4oJ2J1aWx0aW4nLCAnLi9jb21tYW5kcycsIGNvbmZpZywgdGhpcy5jYWNoZSldXG4gICAgLmNvbmNhdCh0aGlzLmNvcmVQbHVnaW5zKVxuICAgIC5jb25jYXQodGhpcy51c2VyUGx1Z2lucylcbiAgICB0aGlzLmNhY2hlLnNhdmUoKVxuICAgIHRoaXMueWFybiA9IG5ldyBZYXJuKHRoaXMuY29uZmlnKVxuICB9XG5cbiAgcGx1Z2luczogUGx1Z2luW11cbiAgY2FjaGU6IENhY2hlXG4gIHlhcm46IFlhcm5cblxuICBnZXQgY29yZVBsdWdpbnMgKCk6IFBsdWdpbltdIHtcbiAgICByZXR1cm4gKHRoaXMuY29uZmlnLl9jbGkucGx1Z2lucyB8fCBbXSkubWFwKG5hbWUgPT4ge1xuICAgICAgcmV0dXJuIG5ldyBQbHVnaW4oJ2NvcmUnLCBwYXRoLmpvaW4odGhpcy5jb25maWcucm9vdCwgJ25vZGVfbW9kdWxlcycsIG5hbWUpLCB0aGlzLmNvbmZpZywgdGhpcy5jYWNoZSlcbiAgICB9KVxuICB9XG5cbiAgZ2V0IHVzZXJQbHVnaW5zICgpOiBQbHVnaW5bXSB7XG4gICAgY29uc3QgcGpzb24gPSB0aGlzLnVzZXJQbHVnaW5zUEpTT05cbiAgICByZXR1cm4gT2JqZWN0LmtleXMocGpzb24uZGVwZW5kZW5jaWVzIHx8IHt9KS5tYXAobmFtZSA9PiB7XG4gICAgICByZXR1cm4gbmV3IFBsdWdpbigndXNlcicsIHRoaXMudXNlclBsdWdpblBhdGgobmFtZSksIHRoaXMuY29uZmlnLCB0aGlzLmNhY2hlKVxuICAgIH0pXG4gIH1cblxuICBnZXQgdXNlclBsdWdpbnNQSlNPTiAoKTogUEpTT04ge1xuICAgIHRyeSB7XG4gICAgICByZXR1cm4gdGhpcy5mcy5yZWFkSlNPTlN5bmMocGF0aC5qb2luKHRoaXMudXNlclBsdWdpbnNEaXIsICdwYWNrYWdlLmpzb24nKSlcbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIHJldHVybiB7IGRlcGVuZGVuY2llczoge30gfVxuICAgIH1cbiAgfVxuXG4gIGxpc3QgKCkge1xuICAgIHJldHVybiB0aGlzLnBsdWdpbnNcbiAgfVxuXG4gIGZpbmRDb21tYW5kIChjbWQ6IHN0cmluZyk6ID9DbGFzczxDb21tYW5kPiB7XG4gICAgZm9yIChsZXQgcGx1Z2luIG9mIHRoaXMucGx1Z2lucykge1xuICAgICAgbGV0IGMgPSBwbHVnaW4uZmluZENvbW1hbmQoY21kKVxuICAgICAgaWYgKGMpIHJldHVybiBjXG4gICAgfVxuICB9XG5cbiAgY29tbWFuZHNGb3JUb3BpYyAodG9waWM6IHN0cmluZyk6IENsYXNzPENvbW1hbmQ+W10ge1xuICAgIHJldHVybiB0aGlzLnBsdWdpbnMucmVkdWNlKCh0LCBwKSA9PiB7XG4gICAgICByZXR1cm4gdC5jb25jYXQocC5jb21tYW5kc1xuICAgICAgICAuZmlsdGVyKGMgPT4gYy50b3BpYyA9PT0gdG9waWMpXG4gICAgICAgIC5tYXAoYyA9PiAocC5maW5kQ29tbWFuZChjLmlkKTogYW55KSkpXG4gICAgfSwgW10pXG4gIH1cblxuICBmaW5kVG9waWMgKGNtZDogc3RyaW5nKTogP0NsYXNzPFRvcGljPiB7XG4gICAgbGV0IG5hbWUgPSBjbWQuc3BsaXQoJzonKVswXVxuICAgIGZvciAobGV0IHBsdWdpbiBvZiB0aGlzLnBsdWdpbnMpIHtcbiAgICAgIGxldCB0ID0gcGx1Z2luLmZpbmRUb3BpYyhuYW1lKVxuICAgICAgaWYgKHQpIHJldHVybiB0XG4gICAgfVxuICB9XG5cbiAgYXN5bmMgc2V0dXBVc2VyUGx1Z2lucyAoKSB7XG4gICAgY29uc3QgcGpzb24gPSBwYXRoLmpvaW4odGhpcy51c2VyUGx1Z2luc0RpciwgJ3BhY2thZ2UuanNvbicpXG4gICAgdGhpcy5mcy5ta2RpcnBTeW5jKHRoaXMudXNlclBsdWdpbnNEaXIpXG4gICAgaWYgKCF0aGlzLmZzLmV4aXN0c1N5bmMocGpzb24pKSB0aGlzLmZzLndyaXRlRmlsZVN5bmMocGpzb24sIEpTT04uc3RyaW5naWZ5KHtwcml2YXRlOiB0cnVlfSkpXG4gICAgYXdhaXQgdGhpcy55YXJuLmV4ZWMoKVxuICB9XG5cbiAgYXN5bmMgaW5zdGFsbCAobmFtZTogc3RyaW5nKSB7XG4gICAgYXdhaXQgdGhpcy5zZXR1cFVzZXJQbHVnaW5zKClcbiAgICBpZiAoIXRoaXMuY29uZmlnLmRlYnVnKSB0aGlzLmFjdGlvbi5zdGFydChgSW5zdGFsbGluZyBwbHVnaW4gJHtuYW1lfWApXG4gICAgYXdhaXQgdGhpcy55YXJuLmV4ZWMoJ2FkZCcsIG5hbWUpXG4gICAgdGhpcy5jbGVhckNhY2hlKG5hbWUpXG4gICAgdHJ5IHtcbiAgICAgIC8vIGZsb3ckaWdub3JlXG4gICAgICBsZXQgcGx1Z2luID0gKHJlcXVpcmUodGhpcy51c2VyUGx1Z2luUGF0aChuYW1lKSk6IFBhcnNlZFBsdWdpbilcbiAgICAgIGlmICghcGx1Z2luLmNvbW1hbmRzKSB0aHJvdyBuZXcgRXJyb3IoYCR7bmFtZX0gZG9lcyBub3QgYXBwZWFyIHRvIGJlIGEgSGVyb2t1IENMSSBwbHVnaW5gKVxuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgdGhpcy5lcnJvcihlcnIsIGZhbHNlKVxuICAgICAgYXdhaXQgdGhpcy51bmluc3RhbGwobmFtZSlcbiAgICAgIHRoaXMuZXhpdCgxKVxuICAgIH1cbiAgICB0aGlzLmFjdGlvbi5zdG9wKClcbiAgfVxuXG4gIGFzeW5jIHVuaW5zdGFsbCAobmFtZTogc3RyaW5nKSB7XG4gICAgaWYgKCF0aGlzLmNvbmZpZy5kZWJ1ZykgdGhpcy5hY3Rpb24uc3RhcnQoYFVuaW5zdGFsbGluZyBwbHVnaW4gJHtuYW1lfWApXG4gICAgYXdhaXQgdGhpcy55YXJuLmV4ZWMoJ3JlbW92ZScsIG5hbWUpXG4gIH1cblxuICBjbGVhckNhY2hlIChuYW1lOiBzdHJpbmcpIHtcbiAgICBmb3IgKGxldCBrIG9mIE9iamVjdC5rZXlzKHRoaXMuY2FjaGUuY2FjaGUucGx1Z2lucykpIHtcbiAgICAgIGlmICh0aGlzLmNhY2hlLmNhY2hlLnBsdWdpbnNba10ubmFtZSA9PT0gbmFtZSkgZGVsZXRlIHRoaXMuY2FjaGUuY2FjaGVba11cbiAgICB9XG4gICAgdGhpcy5jYWNoZS5zYXZlKClcbiAgfVxuXG4gIGdldCB1c2VyUGx1Z2luc0RpciAoKTogc3RyaW5nIHsgcmV0dXJuIHBhdGguam9pbih0aGlzLmNvbmZpZy5kaXJzLmRhdGEsICdwbHVnaW5zJykgfVxuICB1c2VyUGx1Z2luUGF0aCAobmFtZTogc3RyaW5nKTogc3RyaW5nIHsgcmV0dXJuIHBhdGguam9pbih0aGlzLnVzZXJQbHVnaW5zRGlyLCAnbm9kZV9tb2R1bGVzJywgbmFtZSkgfVxuXG4gIGdldCB0b3BpY3MgKCk6IENhY2hlZFRvcGljW10ge1xuICAgIHJldHVybiB0aGlzLnBsdWdpbnMucmVkdWNlKCh0LCBwKSA9PiB0LmNvbmNhdChwLnRvcGljcyksIFtdKVxuICB9XG5cbiAgY29uZmlnOiBDb25maWdcbn1cbiJdfQ==
\No newline at end of file