construct.js
1 "use strict"; 2 var _a, _b; 3 Object.defineProperty(exports, "__esModule", { value: true }); 4 exports.ConstructOrder = exports.Construct = exports.Node = void 0; 5 const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti"); 6 const metadata_1 = require("./metadata"); 7 const dependency_1 = require("./private/dependency"); 8 const stack_trace_1 = require("./private/stack-trace"); 9 const uniqueid_1 = require("./private/uniqueid"); 10 const CONSTRUCT_NODE_PROPERTY_SYMBOL = Symbol.for('constructs.Construct.node'); 11 /** 12 * Represents the construct node in the scope tree. 13 * 14 * @stability stable 15 */ 16 class Node { 17 /** 18 * @stability stable 19 */ 20 constructor(host, scope, id) { 21 this.host = host; 22 this._locked = false; // if this is "true", addChild will fail 23 this._aspects = []; 24 this._children = {}; 25 this._context = {}; 26 this._metadata = new Array(); 27 this._dependencies = new Set(); 28 this.invokedAspects = []; 29 this._validations = new Array(); 30 id = id || ''; // if undefined, convert to empty string 31 this.id = sanitizeId(id); 32 this.scope = scope; 33 // We say that scope is required, but root scopes will bypass the type 34 // checks and actually pass in 'undefined'. 35 if (scope != null) { 36 if (id === '') { 37 throw new Error('Only root constructs may have an empty name'); 38 } 39 // Has side effect so must be very last thing in constructor 40 Node.of(scope).addChild(host, this.id); 41 } 42 else { 43 // This is a root construct. 44 this.id = id; 45 } 46 } 47 /** 48 * Returns the node associated with a construct. 49 * 50 * @param construct the construct. 51 * @stability stable 52 */ 53 static of(construct) { 54 const node = construct[CONSTRUCT_NODE_PROPERTY_SYMBOL]; 55 if (!node) { 56 throw new Error('construct does not have an associated node. All constructs must extend the "Construct" base class'); 57 } 58 return node; 59 } 60 /** 61 * The full, absolute path of this construct in the tree. 62 * 63 * Components are separated by '/'. 64 * 65 * @stability stable 66 */ 67 get path() { 68 const components = this.scopes.slice(1).map(c => Node.of(c).id); 69 return components.join(Node.PATH_SEP); 70 } 71 /** 72 * Returns an opaque tree-unique address for this construct. 73 * 74 * Addresses are 42 characters hexadecimal strings. They begin with "c8" 75 * followed by 40 lowercase hexadecimal characters (0-9a-f). 76 * 77 * Addresses are calculated using a SHA-1 of the components of the construct 78 * path. 79 * 80 * To enable refactorings of construct trees, constructs with the ID `Default` 81 * will be excluded from the calculation. In those cases constructs in the 82 * same tree may have the same addreess. 83 * 84 * @stability stable 85 * @example 86 * 87 * c83a2846e506bcc5f10682b564084bca2d275709ee 88 */ 89 get addr() { 90 if (!this._addr) { 91 this._addr = uniqueid_1.addressOf(this.scopes.map(c => Node.of(c).id)); 92 } 93 return this._addr; 94 } 95 /** 96 * (deprecated) A tree-global unique alphanumeric identifier for this construct. 97 * 98 * Includes 99 * all components of the tree. 100 * 101 * @deprecated please avoid using this property and use `addr` to form unique names. 102 * This algorithm uses MD5, which is not FIPS-complient and also excludes the 103 * identity of the root construct from the calculation. 104 */ 105 get uniqueId() { 106 const components = this.scopes.slice(1).map(c => Node.of(c).id); 107 return components.length > 0 ? uniqueid_1.makeLegacyUniqueId(components) : ''; 108 } 109 /** 110 * Return a direct child by id, or undefined. 111 * 112 * @param id Identifier of direct child. 113 * @returns the child if found, or undefined 114 * @stability stable 115 */ 116 tryFindChild(id) { 117 return this._children[sanitizeId(id)]; 118 } 119 /** 120 * Return a direct child by id. 121 * 122 * Throws an error if the child is not found. 123 * 124 * @param id Identifier of direct child. 125 * @returns Child with the given id. 126 * @stability stable 127 */ 128 findChild(id) { 129 const ret = this.tryFindChild(id); 130 if (!ret) { 131 throw new Error(`No child with id: '${id}'`); 132 } 133 return ret; 134 } 135 /** 136 * Returns the child construct that has the id `Default` or `Resource"`. 137 * 138 * This is usually the construct that provides the bulk of the underlying functionality. 139 * Useful for modifications of the underlying construct that are not available at the higher levels. 140 * Override the defaultChild property. 141 * 142 * This should only be used in the cases where the correct 143 * default child is not named 'Resource' or 'Default' as it 144 * should be. 145 * 146 * If you set this to undefined, the default behavior of finding 147 * the child named 'Resource' or 'Default' will be used. 148 * 149 * @returns a construct or undefined if there is no default child 150 * @stability stable 151 * @throws if there is more than one child 152 */ 153 get defaultChild() { 154 if (this._defaultChild !== undefined) { 155 return this._defaultChild; 156 } 157 const resourceChild = this.tryFindChild('Resource'); 158 const defaultChild = this.tryFindChild('Default'); 159 if (resourceChild && defaultChild) { 160 throw new Error(`Cannot determine default child for ${this.path}. There is both a child with id "Resource" and id "Default"`); 161 } 162 return defaultChild || resourceChild; 163 } 164 /** 165 * Returns the child construct that has the id `Default` or `Resource"`. 166 * 167 * This is usually the construct that provides the bulk of the underlying functionality. 168 * Useful for modifications of the underlying construct that are not available at the higher levels. 169 * Override the defaultChild property. 170 * 171 * This should only be used in the cases where the correct 172 * default child is not named 'Resource' or 'Default' as it 173 * should be. 174 * 175 * If you set this to undefined, the default behavior of finding 176 * the child named 'Resource' or 'Default' will be used. 177 * 178 * @returns a construct or undefined if there is no default child 179 * @stability stable 180 * @throws if there is more than one child 181 */ 182 set defaultChild(value) { 183 this._defaultChild = value; 184 } 185 /** 186 * All direct children of this construct. 187 * 188 * @stability stable 189 */ 190 get children() { 191 return Object.values(this._children); 192 } 193 /** 194 * Return this construct and all of its children in the given order. 195 * 196 * @stability stable 197 */ 198 findAll(order = ConstructOrder.PREORDER) { 199 const ret = new Array(); 200 visit(this.host); 201 return ret; 202 function visit(c) { 203 if (order === ConstructOrder.PREORDER) { 204 ret.push(c); 205 } 206 for (const child of Node.of(c).children) { 207 visit(child); 208 } 209 if (order === ConstructOrder.POSTORDER) { 210 ret.push(c); 211 } 212 } 213 } 214 /** 215 * This can be used to set contextual values. 216 * 217 * Context must be set before any children are added, since children may consult context info during construction. 218 * If the key already exists, it will be overridden. 219 * 220 * @param key The context key. 221 * @param value The context value. 222 * @stability stable 223 */ 224 setContext(key, value) { 225 if (this.children.length > 0) { 226 const names = this.children.map(c => Node.of(c).id); 227 throw new Error('Cannot set context after children have been added: ' + names.join(',')); 228 } 229 this._context[key] = value; 230 } 231 /** 232 * Retrieves a value from tree context. 233 * 234 * Context is usually initialized at the root, but can be overridden at any point in the tree. 235 * 236 * @param key The context key. 237 * @returns The context value or `undefined` if there is no context value for thie key. 238 * @stability stable 239 */ 240 tryGetContext(key) { 241 const value = this._context[key]; 242 if (value !== undefined) { 243 return value; 244 } 245 return this.scope && Node.of(this.scope).tryGetContext(key); 246 } 247 /** 248 * An immutable array of metadata objects associated with this construct. 249 * 250 * This can be used, for example, to implement support for deprecation notices, source mapping, etc. 251 * 252 * @stability stable 253 */ 254 get metadata() { 255 return [...this._metadata]; 256 } 257 /** 258 * Adds a metadata entry to this construct. 259 * 260 * Entries are arbitrary values and will also include a stack trace to allow tracing back to 261 * the code location for when the entry was added. It can be used, for example, to include source 262 * mapping in CloudFormation templates to improve diagnostics. 263 * 264 * @param type a string denoting the type of metadata. 265 * @param data the value of the metadata (can be a Token). 266 * @param fromFunction a function under which to restrict the metadata entry's stack trace (defaults to this.addMetadata). 267 * @stability stable 268 */ 269 addMetadata(type, data, fromFunction) { 270 if (data == null) { 271 return; 272 } 273 const trace = this.tryGetContext(metadata_1.ConstructMetadata.DISABLE_STACK_TRACE_IN_METADATA) 274 ? undefined 275 : stack_trace_1.captureStackTrace(fromFunction || this.addMetadata); 276 this._metadata.push({ type, data, trace }); 277 } 278 /** 279 * Adds a { "info": <message> } metadata entry to this construct. 280 * 281 * The toolkit will display the info message when apps are synthesized. 282 * 283 * @param message The info message. 284 * @stability stable 285 */ 286 addInfo(message) { 287 this.addMetadata(metadata_1.ConstructMetadata.INFO_METADATA_KEY, message); 288 } 289 /** 290 * Adds a { "warning": <message> } metadata entry to this construct. 291 * 292 * The toolkit will display the warning when an app is synthesized, or fail 293 * if run in --strict mode. 294 * 295 * @param message The warning message. 296 * @stability stable 297 */ 298 addWarning(message) { 299 this.addMetadata(metadata_1.ConstructMetadata.WARNING_METADATA_KEY, message); 300 } 301 /** 302 * Adds an { "error": <message> } metadata entry to this construct. 303 * 304 * The toolkit will fail synthesis when errors are reported. 305 * 306 * @param message The error message. 307 * @stability stable 308 */ 309 addError(message) { 310 this.addMetadata(metadata_1.ConstructMetadata.ERROR_METADATA_KEY, message); 311 } 312 /** 313 * Applies the aspect to this Constructs node. 314 * 315 * @stability stable 316 */ 317 applyAspect(aspect) { 318 this._aspects.push(aspect); 319 return; 320 } 321 /** 322 * All parent scopes of this construct. 323 * 324 * @returns a list of parent scopes. The last element in the list will always 325 * be the current construct and the first element will be the root of the 326 * tree. 327 * @stability stable 328 */ 329 get scopes() { 330 const ret = new Array(); 331 let curr = this.host; 332 while (curr) { 333 ret.unshift(curr); 334 curr = Node.of(curr).scope; 335 } 336 return ret; 337 } 338 /** 339 * Returns the root of the construct tree. 340 * 341 * @returns The root of the construct tree. 342 * @stability stable 343 */ 344 get root() { 345 return this.scopes[0]; 346 } 347 /** 348 * Returns true if this construct or the scopes in which it is defined are locked. 349 * 350 * @stability stable 351 */ 352 get locked() { 353 if (this._locked) { 354 return true; 355 } 356 if (this.scope && Node.of(this.scope).locked) { 357 return true; 358 } 359 return false; 360 } 361 /** 362 * Add an ordering dependency on another Construct. 363 * 364 * All constructs in the dependency's scope will be deployed before any 365 * construct in this construct's scope. 366 * 367 * @stability stable 368 */ 369 addDependency(...dependencies) { 370 for (const dependency of dependencies) { 371 this._dependencies.add(dependency); 372 } 373 } 374 /** 375 * Return all dependencies registered on this node or any of its children. 376 * 377 * @stability stable 378 */ 379 get dependencies() { 380 const found = new Map(); // Deduplication map 381 const ret = new Array(); 382 for (const source of this.findAll()) { 383 for (const dependable of Node.of(source)._dependencies) { 384 for (const target of dependency_1.DependableTrait.get(dependable).dependencyRoots) { 385 let foundTargets = found.get(source); 386 if (!foundTargets) { 387 found.set(source, foundTargets = new Set()); 388 } 389 if (!foundTargets.has(target)) { 390 ret.push({ source, target }); 391 foundTargets.add(target); 392 } 393 } 394 } 395 } 396 return ret; 397 } 398 /** 399 * (experimental) Remove the child with the given name, if present. 400 * 401 * @returns Whether a child with the given name was deleted. 402 * @experimental 403 */ 404 tryRemoveChild(childName) { 405 if (!(childName in this._children)) { 406 return false; 407 } 408 delete this._children[childName]; 409 return true; 410 } 411 /** 412 * Adds a validation to this construct. 413 * 414 * When `node.validate()` is called, the `validate()` method will be called on 415 * all validations and all errors will be returned. 416 * 417 * @stability stable 418 */ 419 addValidation(validation) { 420 this._validations.push(validation); 421 } 422 /** 423 * Synthesizes a CloudAssembly from a construct tree. 424 * 425 * @param options Synthesis options. 426 * @stability stable 427 */ 428 synthesize(options) { 429 // the three holy phases of synthesis: prepare, validate and synthesize 430 // prepare 431 this.prepare(); 432 // validate 433 const validate = options.skipValidation === undefined ? true : !options.skipValidation; 434 if (validate) { 435 const errors = this.validate(); 436 if (errors.length > 0) { 437 const errorList = errors.map(e => `[${Node.of(e.source).path}] ${e.message}`).join('\n '); 438 throw new Error(`Validation failed with the following errors:\n ${errorList}`); 439 } 440 } 441 // synthesize (leaves first) 442 for (const construct of this.findAll(ConstructOrder.POSTORDER)) { 443 const node = Node.of(construct); 444 try { 445 node._lock(); 446 const ctx = { 447 ...options.sessionContext, 448 outdir: options.outdir, 449 }; 450 construct.onSynthesize(ctx); // "as any" is needed because we want to keep "synthesize" protected 451 } 452 finally { 453 node._unlock(); 454 } 455 } 456 } 457 /** 458 * Invokes "prepare" on all constructs (depth-first, post-order) in the tree under `node`. 459 * 460 * @stability stable 461 */ 462 prepare() { 463 // Aspects are applied root to leaf 464 for (const construct of this.findAll(ConstructOrder.PREORDER)) { 465 Node.of(construct).invokeAspects(); 466 } 467 // since constructs can be added to the tree during invokeAspects, call findAll() to recreate the list. 468 // use PREORDER.reverse() for backward compatability 469 for (const construct of this.findAll(ConstructOrder.PREORDER).reverse()) { 470 const cn = construct; 471 if ('onPrepare' in cn) { 472 if (typeof (cn.onPrepare) !== 'function') { 473 throw new Error('expecting "onPrepare" to be a function'); 474 } 475 cn.onPrepare(); 476 } 477 } 478 } 479 /** 480 * Validates tree (depth-first, pre-order) and returns the list of all errors. 481 * 482 * An empty list indicates that there are no errors. 483 * 484 * @stability stable 485 */ 486 validate() { 487 let errors = new Array(); 488 for (const child of this.children) { 489 errors = errors.concat(Node.of(child).validate()); 490 } 491 const localErrors = this.host.onValidate(); // "as any" is needed because we want to keep "validate" protected 492 // invoke validations 493 for (const v of this._validations) { 494 localErrors.push(...v.validate()); 495 } 496 return errors.concat(localErrors.map(msg => ({ source: this.host, message: msg }))); 497 } 498 /** 499 * Locks this construct from allowing more children to be added. After this 500 * call, no more children can be added to this construct or to any children. 501 * @internal 502 */ 503 _lock() { 504 this._locked = true; 505 } 506 /** 507 * Unlocks this costruct and allows mutations (adding children). 508 * @internal 509 */ 510 _unlock() { 511 this._locked = false; 512 } 513 /** 514 * Adds a child construct to this node. 515 * 516 * @param child The child construct 517 * @param childName The type name of the child construct. 518 * @returns The resolved path part name of the child 519 */ 520 addChild(child, childName) { 521 if (this.locked) { 522 // special error if root is locked 523 if (!this.path) { 524 throw new Error('Cannot add children during synthesis'); 525 } 526 throw new Error(`Cannot add children to "${this.path}" during synthesis`); 527 } 528 if (childName in this._children) { 529 const name = this.id || ''; 530 const typeName = this.host.constructor.name; 531 throw new Error(`There is already a Construct with name '${childName}' in ${typeName}${name.length > 0 ? ' [' + name + ']' : ''}`); 532 } 533 this._children[childName] = child; 534 } 535 /** 536 * Triggers each aspect to invoke visit 537 */ 538 invokeAspects() { 539 const descendants = this.findAll(); 540 for (const aspect of this._aspects) { 541 if (this.invokedAspects.includes(aspect)) { 542 continue; 543 } 544 descendants.forEach(member => aspect.visit(member)); 545 this.invokedAspects.push(aspect); 546 } 547 } 548 } 549 exports.Node = Node; 550 _a = JSII_RTTI_SYMBOL_1; 551 Node[_a] = { fqn: "constructs.Node", version: "3.3.161" }; 552 /** 553 * Separator used to delimit construct path components. 554 * 555 * @stability stable 556 */ 557 Node.PATH_SEP = '/'; 558 /** 559 * Represents the building block of the construct graph. 560 * 561 * All constructs besides the root construct must be created within the scope of 562 * another construct. 563 * 564 * @stability stable 565 */ 566 class Construct { 567 /** 568 * Creates a new construct node. 569 * 570 * @param scope The scope in which to define this construct. 571 * @param id The scoped construct ID. 572 * @param options Options. 573 * @stability stable 574 */ 575 constructor(scope, id, options = {}) { 576 var _c; 577 // attach the construct to the construct tree by creating a node 578 const nodeFactory = (_c = options.nodeFactory) !== null && _c !== void 0 ? _c : { createNode: (host, nodeScope, nodeId) => new Node(host, nodeScope, nodeId) }; 579 Object.defineProperty(this, CONSTRUCT_NODE_PROPERTY_SYMBOL, { 580 value: nodeFactory.createNode(this, scope, id), 581 enumerable: false, 582 configurable: false, 583 }); 584 // implement IDependable privately 585 dependency_1.DependableTrait.implement(this, { 586 dependencyRoots: [this], 587 }); 588 } 589 /** 590 * Returns a string representation of this construct. 591 * 592 * @stability stable 593 */ 594 toString() { 595 return Node.of(this).path || '<root>'; 596 } 597 /** 598 * (deprecated) Validate the current construct. 599 * 600 * This method can be implemented by derived constructs in order to perform 601 * validation logic. It is called on all constructs before synthesis. 602 * 603 * @returns An array of validation error messages, or an empty array if there the construct is valid. 604 * @deprecated use `Node.addValidation()` to subscribe validation functions on this construct 605 * instead of overriding this method. 606 */ 607 onValidate() { 608 return []; 609 } 610 /** 611 * Perform final modifications before synthesis. 612 * 613 * This method can be implemented by derived constructs in order to perform 614 * final changes before synthesis. prepare() will be called after child 615 * constructs have been prepared. 616 * 617 * This is an advanced framework feature. Only use this if you 618 * understand the implications. 619 * 620 * @stability stable 621 */ 622 onPrepare() { 623 return; 624 } 625 /** 626 * Allows this construct to emit artifacts into the cloud assembly during synthesis. 627 * 628 * This method is usually implemented by framework-level constructs such as `Stack` and `Asset` 629 * as they participate in synthesizing the cloud assembly. 630 * 631 * @param session The synthesis session. 632 * @stability stable 633 */ 634 onSynthesize(session) { 635 ignore(session); 636 } 637 } 638 exports.Construct = Construct; 639 _b = JSII_RTTI_SYMBOL_1; 640 Construct[_b] = { fqn: "constructs.Construct", version: "3.3.161" }; 641 /** 642 * In what order to return constructs. 643 * 644 * @stability stable 645 */ 646 var ConstructOrder; 647 (function (ConstructOrder) { 648 ConstructOrder[ConstructOrder["PREORDER"] = 0] = "PREORDER"; 649 ConstructOrder[ConstructOrder["POSTORDER"] = 1] = "POSTORDER"; 650 })(ConstructOrder = exports.ConstructOrder || (exports.ConstructOrder = {})); 651 function ignore(_x) { 652 return; 653 } 654 // Import this _after_ everything else to help node work the classes out in the correct order... 655 const PATH_SEP_REGEX = new RegExp(`${Node.PATH_SEP}`, 'g'); 656 /** 657 * Return a sanitized version of an arbitrary string, so it can be used as an ID 658 */ 659 function sanitizeId(id) { 660 // Escape path seps as double dashes 661 return id.replace(PATH_SEP_REGEX, '--'); 662 } 663 //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29uc3RydWN0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL2NvbnN0cnVjdC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUNBLHlDQUE4RDtBQUM5RCxxREFBdUQ7QUFDdkQsdURBQTBEO0FBQzFELGlEQUFtRTtBQUVuRSxNQUFNLDhCQUE4QixHQUFHLE1BQU0sQ0FBQyxHQUFHLENBQUMsMkJBQTJCLENBQUMsQ0FBQzs7Ozs7O0FBTS9FLE1BQWEsSUFBSTs7OztJQStCZixZQUE2QixJQUFlLEVBQUUsS0FBaUIsRUFBRSxFQUFVO1FBQTlDLFNBQUksR0FBSixJQUFJLENBQVc7UUFYcEMsWUFBTyxHQUFHLEtBQUssQ0FBQyxDQUFDLHdDQUF3QztRQUNoRCxhQUFRLEdBQWMsRUFBRSxDQUFDO1FBQ3pCLGNBQVMsR0FBaUMsRUFBRyxDQUFDO1FBQzlDLGFBQVEsR0FBMkIsRUFBRyxDQUFDO1FBQ3ZDLGNBQVMsR0FBRyxJQUFJLEtBQUssRUFBaUIsQ0FBQztRQUN2QyxrQkFBYSxHQUFHLElBQUksR0FBRyxFQUFjLENBQUM7UUFDdEMsbUJBQWMsR0FBYyxFQUFFLENBQUM7UUFFL0IsaUJBQVksR0FBRyxJQUFJLEtBQUssRUFBZSxDQUFDO1FBSXZELEVBQUUsR0FBRyxFQUFFLElBQUksRUFBRSxDQUFDLENBQUMsd0NBQXdDO1FBRXZELElBQUksQ0FBQyxFQUFFLEdBQUcsVUFBVSxDQUFDLEVBQUUsQ0FBQyxDQUFDO1FBQ3pCLElBQUksQ0FBQyxLQUFLLEdBQUcsS0FBSyxDQUFDO1FBRW5CLHNFQUFzRTtRQUN0RSwyQ0FBMkM7UUFDM0MsSUFBSSxLQUFLLElBQUksSUFBSSxFQUFFO1lBQ2pCLElBQUksRUFBRSxLQUFLLEVBQUUsRUFBRTtnQkFDYixNQUFNLElBQUksS0FBSyxDQUFDLDZDQUE2QyxDQUFDLENBQUM7YUFDaEU7WUFFRCw0REFBNEQ7WUFDNUQsSUFBSSxDQUFDLEVBQUUsQ0FBQyxLQUFLLENBQUMsQ0FBQyxRQUFRLENB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U0FDcEIsQ0FBQyxDQUFDO1FBRUgsa0NBQWtDO1FBQ2xDLDRCQUFlLENBQUMsU0FBUyxDQUFDLElBQUksRUFBRTtZQUM5QixlQUFlLEVBQUUsQ0FBQyxJQUFJLENBQUM7U0FDeEIsQ0FBQyxDQUFDO0lBQ0wsQ0FBQzs7Ozs7O0lBR00sUUFBUTtRQUNiLE9BQU8sSUFBSSxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxJQUFJLElBQUksUUFBUSxDQUFDO0lBQ3hDLENBQUM7Ozs7Ozs7Ozs7O0lBR1MsVUFBVTtRQUNsQixPQUFPLEVBQUUsQ0FBQztJQUNaLENBQUM7Ozs7Ozs7Ozs7Ozs7SUFHUyxTQUFTO1FBQ2pCLE9BQU87SUFDVCxDQUFDOzs7Ozs7Ozs7O0lBR1MsWUFBWSxDQUFDLE9BQTBCO1FBQy9DLE1BQU0sQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUNsQixDQUFDOztBQW5DSCw4QkFvQ0M7Ozs7Ozs7O0FBa0JELElBQVksY0FNWDtBQU5ELFdBQVksY0FBYztJQUV4QiwyREFBUSxDQUFBO0lBR1IsNkRBQVMsQ0FBQTtBQUNYLENBQUMsRUFOVyxjQUFjLEdBQWQsc0JBQWMsS0FBZCxzQkFBYyxRQU16QjtBQWtDRCxTQUFTLE1BQU0sQ0FBQyxFQUFPO0lBQ3JCLE9BQU87QUFDVCxDQUFDO0FBRUQsZ0dBQWdHO0FBQ2hHLE1BQU0sY0FBYyxHQUFHLElBQUksTUFBTSxDQUFDLEdBQUcsSUFBSSxDQUFDLFFBQVEsRUFBRSxFQUFFLEdBQUcsQ0FBQyxDQUFDO0FBRTNEOztHQUVHO0FBQ0gsU0FBUyxVQUFVLENBQUMsRUFBVTtJQUM1QixvQ0FBb0M7SUFDcEMsT0FBTyxFQUFFLENBQUMsT0FBTyxDQUFDLGNBQWMsRUFBRSxJQUFJLENBQUMsQ0FBQztBQUMxQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSUFzcGVjdCB9IGZyb20gJy4vYXNwZWN0JztcbmltcG9ydCB7IENvbnN0cnVjdE1ldGFkYXRhLCBNZXRhZGF0YUVudHJ5IH0gZnJvbSAnLi9tZXRhZGF0YSc7XG5pbXBvcnQgeyBEZXBlbmRhYmxlVHJhaXQgfSBmcm9tICcuL3ByaXZhdGUvZGVwZW5kZW5jeSc7XG5pbXBvcnQgeyBjYXB0dXJlU3RhY2tUcmFjZSB9IGZyb20gJy4vcHJpdmF0ZS9zdGFjay10cmFjZSc7XG5pbXBvcnQgeyBtYWtlTGVnYWN5VW5pcXVlSWQsIGFkZHJlc3NPZiB9IGZyb20gJy4vcHJpdmF0ZS91bmlxdWVpZCc7XG5cbmNvbnN0IENPTlNUUlVDVF9OT0RFX1BST1BFUlRZX1NZTUJPTCA9IFN5bWJvbC5mb3IoJ2NvbnN0cnVjdHMuQ29uc3RydWN0Lm5vZGUnKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuZXhwb3J0IGludGVyZmFjZSBJQ29uc3RydWN0IHsgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuZXhwb3J0IGNsYXNzIE5vZGUge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXG4gIHB1YmxpYyBzdGF0aWMgcmVhZG9ubHkgUEFUSF9TRVAgPSAnLyc7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXG4gIHB1YmxpYyBzdGF0aWMgb2YoY29uc3RydWN0OiBJQ29uc3RydWN0KTogTm9kZSB7XG4gICAgY29uc3Qgbm9kZSA9IChjb25zdHJ1Y3QgYXMgYW55KVtDT05TVFJVQ1RfTk9ERV9QUk9QRVJUWV9TWU1CT0xdIGFzIE5vZGU7XG4gICAgaWYgKCFub2RlKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ2NvbnN0cnVjdCBkb2VzIG5vdCBoYXZlIGFuIGFzc29jaWF0ZWQgbm9kZS4gQWxsIGNvbnN0cnVjdHMgbXVzdCBleHRlbmQgdGhlIFwiQ29uc3RydWN0XCIgYmFzZSBjbGFzcycpO1xuICAgIH1cblxuICAgIHJldHVybiBub2RlO1xuICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXG4gIHB1YmxpYyByZWFkb25seSBzY29wZT86IElDb25zdHJ1Y3Q7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcbiAgcHVibGljIHJlYWRvbmx5IGlkOiBzdHJpbmc7XG5cbiAgcHJpdmF0ZSBfbG9ja2VkID0gZmFsc2U7IC8vIGlmIHRoaXMgaXMgXCJ0cnVlXCIsIGFkZENoaWxkIHdpbGwgZmFpbFxuICBwcml2YXRlIHJlYWRvbmx5IF9hc3BlY3RzOiBJQXNwZWN0W10gPSBbXTtcbiAgcHJpdmF0ZSByZWFkb25seSBfY2hpbGRyZW46IHsgW2lkOiBzdHJpbmddOiBJQ29uc3RydWN0IH0gPSB7IH07XG4gIHByaXZhdGUgcmVhZG9ubHkgX2NvbnRleHQ6IHsgW2tleTogc3RyaW5nXTogYW55IH0gPSB7IH07XG4gIHByaXZhdGUgcmVhZG9ubHkgX21ldGFkYXRhID0gbmV3IEFycmF5PE1ldGFkYXRhRW50cnk+KCk7XG4gIHByaXZhdGUgcmVhZG9ubHkgX2RlcGVuZGVuY2llcyA9IG5ldyBTZXQ8SUNvbnN0cnVjdD4oKTtcbiAgcHJpdmF0ZSByZWFkb25seSBpbnZva2VkQXNwZWN0czogSUFzcGVjdFtdID0gW107XG4gIHByaXZhdGUgX2RlZmF1bHRDaGlsZDogSUNvbnN0cnVjdCB8IHVuZGVmaW5lZDtcbiAgcHJpdmF0ZSByZWFkb25seSBfdmFsaWRhdGlvbnMgPSBuZXcgQXJyYXk8SVZhbGlkYXRpb24+KCk7XG4gIHByaXZhdGUgX2FkZHI/OiBzdHJpbmc7IC8vIGNhY2hlXG5cbiAgY29uc3RydWN0b3IocHJpdmF0ZSByZWFkb25seSBob3N0OiBDb25zdHJ1Y3QsIHNjb3BlOiBJQ29uc3RydWN0LCBpZDogc3RyaW5nKSB7XG4gICAgaWQgPSBpZCB8fCAnJzsgLy8gaWYgdW5kZWZpbmVkLCBjb252ZXJ0IHRvIGVtcHR5IHN0cmluZ1xuXG4gICAgdGhpcy5pZCA9IHNhbml0aXplSWQoaWQpO1xuICAgIHRoaXMuc2NvcGUgPSBzY29wZTtcblxuICAgIC8vIFdlIHNheSB0aGF0IHNjb3BlIGlzIHJlcXVpcmVkLCBidXQgcm9vdCBzY29wZXMgd2lsbCBieXBhc3MgdGhlIHR5cGVcbiAgICAvLyBjaGVja3MgYW5kIGFjdHVhbGx5IHBhc3MgaW4gJ3VuZGVmaW5lZCcuXG4gICAgaWYgKHNjb3BlICE9IG51bGwpIHtcbiAgICAgIGlmIChpZCA9PT0gJycpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdPbmx5IHJvb3QgY29uc3RydWN0cyBtYXkgaGF2ZSBhbiBlbXB0eSBuYW1lJyk7XG4gICAgICB9XG5cbiAgICAgIC8vIEhhcyBzaWRlIGVmZmVjdCBzbyBtdXN0IGJlIHZlcnkgbGFzdCB0aGluZyBpbiBjb25zdHJ1Y3RvclxuICAgICAgTm9kZS5vZihzY29wZSkuYWRkQ2hpbGQoaG9zdCwgdGhpcy5pZCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIFRoaXMgaXMgYSByb290IGNvbnN0cnVjdC5cbiAgICAgIHRoaXMuaWQgPSBpZDtcbiAgICB9XG4gIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXG4gIHB1YmxpYyBnZXQgcGF0aCgpOiBzdHJpbmcge1xuICAgIGNvbnN0IGNvbXBvbmVudHMgPSB0aGlzLnNjb3Blcy5zbGljZSgxKS5tYXAoYyA9PiBOb2RlLm9mKGMpLmlkKTtcbiAgICByZXR1cm4gY29tcG9uZW50cy5qb2luKE5vZGUuUEFUSF9TRVApO1xuICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcbiAgcHVibGljIGdldCBhZGRyKCk6IHN0cmluZyB7XG4gICAgaWYgKCF0aGlzLl9hZGRyKSB7XG4gICAgICB0aGlzLl9hZGRyID0gYWRkcmVzc09mKHRoaXMuc2NvcGVzLm1hcChjID0+IE5vZGUub2YoYykuaWQpKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5fYWRkcjtcbiAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuICBwdWJsaWMgZ2V0IHVuaXF1ZUlkKCk6IHN0cmluZyB7XG4gICAgY29uc3QgY29tcG9uZW50cyA9IHRoaXMuc2NvcGVzLnNsaWNlKDEpLm1hcChjID0+IE5vZGUub2YoYykuaWQpO1xuICAgIHJldHVybiBjb21wb25lbnRzLmxlbmd0aCA+IDAgPyBtYWtlTGVnYWN5VW5pcXVlSWQoY29tcG9uZW50cykgOiAnJztcbiAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuICBwdWJsaWMgdHJ5RmluZENoaWxkKGlkOiBzdHJpbmcpOiBJQ29uc3RydWN0IHwgdW5kZWZpbmVkIHtcbiAgICByZXR1cm4gdGhpcy5fY2hpbGRyZW5bc2FuaXRpemVJZChpZCldO1xuICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuICBwdWJsaWMgZmluZENoaWxkKGlkOiBzdHJpbmcpOiBJQ29uc3RydWN0IHtcbiAgICBjb25zdCByZXQgPSB0aGlzLnRyeUZpbmRDaGlsZChpZCk7XG4gICAgaWYgKCFyZXQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgTm8gY2hpbGQgd2l0aCBpZDogJyR7aWR9J2ApO1xuICAgIH1cbiAgICByZXR1cm4gcmV0O1xuICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXG4gIHB1YmxpYyBnZXQgZGVmYXVsdENoaWxkKCk6IElDb25zdHJ1Y3QgfCB1bmRlZmluZWQge1xuICAgIGlmICh0aGlzLl9kZWZhdWx0Q2hpbGQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgcmV0dXJuIHRoaXMuX2RlZmF1bHRDaGlsZDtcbiAgICB9XG5cbiAgICBjb25zdCByZXNvdXJjZUNoaWxkID0gdGhpcy50cnlGaW5kQ2hpbGQoJ1Jlc291cmNlJyk7XG4gICAgY29uc3QgZGVmYXVsdENoaWxkID0gdGhpcy50cnlGaW5kQ2hpbGQoJ0RlZmF1bHQnKTtcbiAgICBpZiAocmVzb3VyY2VDaGlsZCAmJiBkZWZhdWx0Q2hpbGQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgQ2Fubm90IGRldGVybWluZSBkZWZhdWx0IGNoaWxkIGZvciAke3RoaXMucGF0aH0uIFRoZXJlIGlzIGJvdGggYSBjaGlsZCB3aXRoIGlkIFwiUmVzb3VyY2VcIiBhbmQgaWQgXCJEZWZhdWx0XCJgKTtcbiAgICB9XG5cbiAgICByZXR1cm4gZGVmYXVsdENoaWxkIHx8IHJlc291cmNlQ2hpbGQ7XG4gIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXG4gIHB1YmxpYyBzZXQgZGVmYXVsdENoaWxkKHZhbHVlOiBJQ29uc3RydWN0IHwgdW5kZWZpbmVkKSB7XG4gICAgdGhpcy5fZGVmYXVsdENoaWxkID0gdmFsdWU7XG4gIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuICBwdWJsaWMgZ2V0IGNoaWxkcmVuKCkge1xuICAgIHJldHVybiBPYmplY3QudmFsdWVzKHRoaXMuX2NoaWxkcmVuKTtcbiAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcbiAgcHVibGljIGZpbmRBbGwob3JkZXI6IENvbnN0cnVjdE9yZGVyID0gQ29uc3RydWN0T3JkZXIuUFJFT1JERVIpOiBJQ29uc3RydWN0W10ge1xuICAgIGNvbnN0IHJldCA9IG5ldyBBcnJheTxJQ29uc3RydWN0PigpO1xuICAgIHZpc2l0KHRoaXMuaG9zdCk7XG4gICAgcmV0dXJuIHJldDtcblxuICAgIGZ1bmN0aW9uIHZpc2l0KGM6IElDb25zdHJ1Y3QpIHtcbiAgICAgIGlmIChvcmRlciA9PT0gQ29uc3RydWN0T3JkZXIuUFJFT1JERVIpIHtcbiAgICAgICAgcmV0LnB1c2goYyk7XG4gICAgICB9XG5cbiAgICAgIGZvciAoY29uc3QgY2hpbGQgb2YgTm9kZS5vZihjKS5jaGlsZHJlbikge1xuICAgICAgICB2aXNpdChjaGlsZCk7XG4gICAgICB9XG5cbiAgICAgIGlmIChvcmRlciA9PT0gQ29uc3RydWN0T3JkZXIuUE9TVE9SREVSKSB7XG4gICAgICAgIHJldC5wdXNoKGMpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuICBwdWJsaWMgc2V0Q29udGV4dChrZXk6IHN0cmluZywgdmFsdWU6IGFueSkge1xuICAgIGlmICh0aGlzLmNoaWxkcmVuLmxlbmd0aCA+IDApIHtcbiAgICAgIGNvbnN0IG5hbWVzID0gdGhpcy5jaGlsZHJlbi5tYXAoYyA9PiBOb2RlLm9mKGMpLmlkKTtcbiAgICAgIHRocm93IG5ldyBFcnJvcignQ2Fubm90IHNldCBjb250ZXh0IGFmdGVyIGNoaWxkcmVuIGhhdmUgYmVlbiBhZGRlZDogJyArIG5hbWVzLmpvaW4oJywnKSk7XG4gICAgfVxuICAgIHRoaXMuX2NvbnRleHRba2V5XSA9IHZhbHVlO1xuICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuICBwdWJsaWMgdHJ5R2V0Q29udGV4dChrZXk6IHN0cmluZyk6IGFueSB7XG4gICAgY29uc3QgdmFsdWUgPSB0aGlzLl9jb250ZXh0W2tleV07XG4gICAgaWYgKHZhbHVlICE9PSB1bmRlZmluZWQpIHsgcmV0dXJuIHZhbHVlOyB9XG5cbiAgICByZXR1cm4gdGhpcy5zY29wZSAmJiBOb2RlLm9mKHRoaXMuc2NvcGUpLnRyeUdldENvbnRleHQoa2V5KTtcbiAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXG4gIHB1YmxpYyBnZXQgbWV0YWRhdGEoKSB7XG4gICAgcmV0dXJuIFsuLi50aGlzLl9tZXRhZGF0YV07XG4gIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuICBwdWJsaWMgYWRkTWV0YWRhdGEodHlwZTogc3RyaW5nLCBkYXRhOiBhbnksIGZyb21GdW5jdGlvbj86IGFueSk6IHZvaWQge1xuICAgIGlmIChkYXRhID09IG51bGwpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCB0cmFjZSA9IHRoaXMudHJ5R2V0Q29udGV4dChDb25zdHJ1Y3RNZXRhZGF0YS5ESVNBQkxFX1NUQUNLX1RSQUNFX0lOX01FVEFEQVRBKVxuICAgICAgPyB1bmRlZmluZWRcbiAgICAgIDogY2FwdHVyZVN0YWNrVHJhY2UoZnJvbUZ1bmN0aW9uIHx8IHRoaXMuYWRkTWV0YWRhdGEpO1xuXG4gICAgdGhpcy5fbWV0YWRhdGEucHVzaCh7IHR5cGUsIGRhdGEsIHRyYWNlIH0pO1xuICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXG4gIHB1YmxpYyBhZGRJbmZvKG1lc3NhZ2U6IHN0cmluZyk6IHZvaWQge1xuICAgIHRoaXMuYWRkTWV0YWRhdGEoQ29uc3RydWN0TWV0YWRhdGEuSU5GT19NRVRBREFUQV9LRVksIG1lc3NhZ2UpO1xuICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuICBwdWJsaWMgYWRkV2FybmluZyhtZXNzYWdlOiBzdHJpbmcpOiB2b2lkIHtcbiAgICB0aGlzLmFkZE1ldGFkYXRhKENvbnN0cnVjdE1ldGFkYXRhLldBUk5JTkdfTUVUQURBVEFfS0VZLCBtZXNzYWdlKTtcbiAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcbiAgcHVibGljIGFkZEVycm9yKG1lc3NhZ2U6IHN0cmluZykge1xuICAgIHRoaXMuYWRkTWV0YWRhdGEoQ29uc3RydWN0TWV0YWRhdGEuRVJST1JfTUVUQURBVEFfS0VZLCBtZXNzYWdlKTtcbiAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuICBwdWJsaWMgYXBwbHlBc3BlY3QoYXNwZWN0OiBJQXNwZWN0KTogdm9pZCB7XG4gICAgdGhpcy5fYXNwZWN0cy5wdXNoKGFzcGVjdCk7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuICBwdWJsaWMgZ2V0IHNjb3BlcygpOiBJQ29uc3RydWN0W10ge1xuICAgIGNvbnN0IHJldCA9IG5ldyBBcnJheTxJQ29uc3RydWN0PigpO1xuXG4gICAgbGV0IGN1cnI6IElDb25zdHJ1Y3QgfCB1bmRlZmluZWQgPSB0aGlzLmhvc3Q7XG4gICAgd2hpbGUgKGN1cnIpIHtcbiAgICAgIHJldC51bnNoaWZ0KGN1cnIpO1xuICAgICAgY3VyciA9IE5vZGUub2YoY3Vycikuc2NvcGU7XG4gICAgfVxuXG4gICAgcmV0dXJuIHJldDtcbiAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcbiAgcHVibGljIGdldCByb290KCkge1xuICAgIHJldHVybiB0aGlzLnNjb3Blc1swXTtcbiAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuICBwdWJsaWMgZ2V0IGxvY2tlZCgpIHtcbiAgICBpZiAodGhpcy5fbG9ja2VkKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5zY29wZSAmJiBOb2RlLm9mKHRoaXMuc2NvcGUpLmxvY2tlZCkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuICBwdWJsaWMgYWRkRGVwZW5kZW5jeSguLi5kZXBlbmRlbmNpZXM6IElDb25zdHJ1Y3RbXSkge1xuICAgIGZvciAoY29uc3QgZGVwZW5kZW5jeSBvZiBkZXBlbmRlbmNpZXMpIHtcbiAgICAgIHRoaXMuX2RlcGVuZGVuY2llcy5hZGQoZGVwZW5kZW5jeSk7XG4gICAgfVxuICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuICBwdWJsaWMgZ2V0IGRlcGVuZGVuY2llcygpOiBEZXBlbmRlbmN5W10ge1xuICAgIGNvbnN0IGZvdW5kID0gbmV3IE1hcDxJQ29uc3RydWN0LCBTZXQ8SUNvbnN0cnVjdD4+KCk7IC8vIERlZHVwbGljYXRpb24gbWFwXG4gICAgY29uc3QgcmV0ID0gbmV3IEFycmF5PERlcGVuZGVuY3k+KCk7XG5cbiAgICBmb3IgKGNvbnN0IHNvdXJjZSBvZiB0aGlzLmZpbmRBbGwoKSkge1xuICAgICAgZm9yIChjb25zdCBkZXBlbmRhYmxlIG9mIE5vZGUub2Yoc291cmNlKS5fZGVwZW5kZW5jaWVzKSB7XG4gICAgICAgIGZvciAoY29uc3QgdGFyZ2V0IG9mIERlcGVuZGFibGVUcmFpdC5nZXQoZGVwZW5kYWJsZSkuZGVwZW5kZW5jeVJvb3RzKSB7XG4gICAgICAgICAgbGV0IGZvdW5kVGFyZ2V0cyA9IGZvdW5kLmdldChzb3VyY2UpO1xuICAgICAgICAgIGlmICghZm91bmRUYXJnZXRzKSB7IGZvdW5kLnNldChzb3VyY2UsIGZvdW5kVGFyZ2V0cyA9IG5ldyBTZXQoKSk7IH1cblxuICAgICAgICAgIGlmICghZm91bmRUYXJnZXRzLmhhcyh0YXJnZXQpKSB7XG4gICAgICAgICAgICByZXQucHVzaCh7IHNvdXJjZSwgdGFyZ2V0IH0pO1xuICAgICAgICAgICAgZm91bmRUYXJnZXRzLmFkZCh0YXJnZXQpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiByZXQ7XG4gIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXG4gIHB1YmxpYyB0cnlSZW1vdmVDaGlsZChjaGlsZE5hbWU6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIGlmICghKGNoaWxkTmFtZSBpbiB0aGlzLl9jaGlsZHJlbikpIHsgcmV0dXJuIGZhbHNlOyB9XG4gICAgZGVsZXRlIHRoaXMuX2NoaWxkcmVuW2NoaWxkTmFtZV07XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcbiAgcHVibGljIGFkZFZhbGlkYXRpb24odmFsaWRhdGlvbjogSVZhbGlkYXRpb24pIHtcbiAgICB0aGlzLl92YWxpZGF0aW9ucy5wdXNoKHZhbGlkYXRpb24pO1xuICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcbiAgcHVibGljIHN5bnRoZXNpemUob3B0aW9uczogU3ludGhlc2lzT3B0aW9ucyk6IHZvaWQge1xuICAgIC8vIHRoZSB0aHJlZSBob2x5IHBoYXNlcyBvZiBzeW50aGVzaXM6IHByZXBhcmUsIHZhbGlkYXRlIGFuZCBzeW50aGVzaXplXG5cbiAgICAvLyBwcmVwYXJlXG4gICAgdGhpcy5wcmVwYXJlKCk7XG5cbiAgICAvLyB2YWxpZGF0ZVxuICAgIGNvbnN0IHZhbGlkYXRlID0gb3B0aW9ucy5za2lwVmFsaWRhdGlvbiA9PT0gdW5kZWZpbmVkID8gdHJ1ZSA6ICFvcHRpb25zLnNraXBWYWxpZGF0aW9uO1xuICAgIGlmICh2YWxpZGF0ZSkge1xuICAgICAgY29uc3QgZXJyb3JzID0gdGhpcy52YWxpZGF0ZSgpO1xuICAgICAgaWYgKGVycm9ycy5sZW5ndGggPiAwKSB7XG4gICAgICAgIGNvbnN0IGVycm9yTGlzdCA9IGVycm9ycy5tYXAoZSA9PiBgWyR7Tm9kZS5vZihlLnNvdXJjZSkucGF0aH1dICR7ZS5tZXNzYWdlfWApLmpvaW4oJ1xcbiAgJyk7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgVmFsaWRhdGlvbiBmYWlsZWQgd2l0aCB0aGUgZm9sbG93aW5nIGVycm9yczpcXG4gICR7ZXJyb3JMaXN0fWApO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIHN5bnRoZXNpemUgKGxlYXZlcyBmaXJzdClcbiAgICBmb3IgKGNvbnN0IGNvbnN0cnVjdCBvZiB0aGlzLmZpbmRBbGwoQ29uc3RydWN0T3JkZXIuUE9TVE9SREVSKSkge1xuICAgICAgY29uc3Qgbm9kZSA9IE5vZGUub2YoY29uc3RydWN0KTtcbiAgICAgIHRyeSB7XG4gICAgICAgIG5vZGUuX2xvY2soKTtcbiAgICAgICAgY29uc3QgY3R4ID0ge1xuICAgICAgICAgIC4uLm9wdGlvbnMuc2Vzc2lvbkNvbnRleHQsXG4gICAgICAgICAgb3V0ZGlyOiBvcHRpb25zLm91dGRpcixcbiAgICAgICAgfTtcbiAgICAgICAgKGNvbnN0cnVjdCBhcyBhbnkpLm9uU3ludGhlc2l6ZShjdHgpOyAvLyBcImFzIGFueVwiIGlzIG5lZWRlZCBiZWNhdXNlIHdlIHdhbnQgdG8ga2VlcCBcInN5bnRoZXNpemVcIiBwcm90ZWN0ZWRcbiAgICAgIH0gZmluYWxseSB7XG4gICAgICAgIG5vZGUuX3VubG9jaygpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuICBwdWJsaWMgcHJlcGFyZSgpIHtcbiAgICAvLyBBc3BlY3RzIGFyZSBhcHBsaWVkIHJvb3QgdG8gbGVhZlxuICAgIGZvciAoY29uc3QgY29uc3RydWN0IG9mIHRoaXMuZmluZEFsbChDb25zdHJ1Y3RPcmRlci5QUkVPUkRFUikpIHtcbiAgICAgIE5vZGUub2YoY29uc3RydWN0KS5pbnZva2VBc3BlY3RzKCk7XG4gICAgfVxuXG4gICAgLy8gc2luY2UgY29uc3RydWN0cyBjYW4gYmUgYWRkZWQgdG8gdGhlIHRyZWUgZHVyaW5nIGludm9rZUFzcGVjdHMsIGNhbGwgZmluZEFsbCgpIHRvIHJlY3JlYXRlIHRoZSBsaXN0LlxuICAgIC8vIHVzZSBQUkVPUkRFUi5yZXZlcnNlKCkgZm9yIGJhY2t3YXJkIGNvbXBhdGFiaWxpdHlcbiAgICBmb3IgKGNvbnN0IGNvbnN0cnVjdCBvZiB0aGlzLmZpbmRBbGwoQ29uc3RydWN0T3JkZXIuUFJFT1JERVIpLnJldmVyc2UoKSkge1xuICAgICAgY29uc3QgY24gPSBjb25zdHJ1Y3QgYXMgYW55O1xuICAgICAgaWYgKCdvblByZXBhcmUnIGluIGNuKSB7XG4gICAgICAgIGlmICh0eXBlb2YoY24ub25QcmVwYXJlKSAhPT0gJ2Z1bmN0aW9uJykgeyB0aHJvdyBuZXcgRXJyb3IoJ2V4cGVjdGluZyBcIm9uUHJlcGFyZVwiIHRvIGJlIGEgZnVuY3Rpb24nKTsgfVxuICAgICAgICBjbi5vblByZXBhcmUoKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXG4gIHB1YmxpYyB2YWxpZGF0ZSgpIHtcbiAgICBsZXQgZXJyb3JzID0gbmV3IEFycmF5PFZhbGlkYXRpb25FcnJvcj4oKTtcblxuICAgIGZvciAoY29uc3QgY2hpbGQgb2YgdGhpcy5jaGlsZHJlbikge1xuICAgICAgZXJyb3JzID0gZXJyb3JzLmNvbmNhdChOb2RlLm9mKGNoaWxkKS52YWxpZGF0ZSgpKTtcbiAgICB9XG5cbiAgICBjb25zdCBsb2NhbEVycm9yczogc3RyaW5nW10gPSAodGhpcy5ob3N0IGFzIGFueSkub25WYWxpZGF0ZSgpOyAvLyBcImFzIGFueVwiIGlzIG5lZWRlZCBiZWNhdXNlIHdlIHdhbnQgdG8ga2VlcCBcInZhbGlkYXRlXCIgcHJvdGVjdGVkXG5cbiAgICAvLyBpbnZva2UgdmFsaWRhdGlvbnNcbiAgICBmb3IgKGNvbnN0IHYgb2YgdGhpcy5fdmFsaWRhdGlvbnMpIHtcbiAgICAgIGxvY2FsRXJyb3JzLnB1c2goLi4udi52YWxpZGF0ZSgpKTtcbiAgICB9XG5cbiAgICByZXR1cm4gZXJyb3JzLmNvbmNhdChsb2NhbEVycm9ycy5tYXAobXNnID0+ICh7IHNvdXJjZTogdGhpcy5ob3N0LCBtZXNzYWdlOiBtc2cgfSkpKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBMb2NrcyB0aGlzIGNvbnN0cnVjdCBmcm9tIGFsbG93aW5nIG1vcmUgY2hpbGRyZW4gdG8gYmUgYWRkZWQuIEFmdGVyIHRoaXNcbiAgICogY2FsbCwgbm8gbW9yZSBjaGlsZHJlbiBjYW4gYmUgYWRkZWQgdG8gdGhpcyBjb25zdHJ1Y3Qgb3IgdG8gYW55IGNoaWxkcmVuLlxuICAgKiBAaW50ZXJuYWxcbiAgICovXG4gIHByaXZhdGUgX2xvY2soKSB7XG4gICAgdGhpcy5fbG9ja2VkID0gdHJ1ZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBVbmxvY2tzIHRoaXMgY29zdHJ1Y3QgYW5kIGFsbG93cyBtdXRhdGlvbnMgKGFkZGluZyBjaGlsZHJlbikuXG4gICAqIEBpbnRlcm5hbFxuICAgKi9cbiAgcHJpdmF0ZSBfdW5sb2NrKCkge1xuICAgIHRoaXMuX2xvY2tlZCA9IGZhbHNlO1xuICB9XG5cbiAgLyoqXG4gICAqIEFkZHMgYSBjaGlsZCBjb25zdHJ1Y3QgdG8gdGhpcyBub2RlLlxuICAgKlxuICAgKiBAcGFyYW0gY2hpbGQgVGhlIGNoaWxkIGNvbnN0cnVjdFxuICAgKiBAcGFyYW0gY2hpbGROYW1lIFRoZSB0eXBlIG5hbWUgb2YgdGhlIGNoaWxkIGNvbnN0cnVjdC5cbiAgICogQHJldHVybnMgVGhlIHJlc29sdmVkIHBhdGggcGFydCBuYW1lIG9mIHRoZSBjaGlsZFxuICAgKi9cbiAgcHJpdmF0ZSBhZGRDaGlsZChjaGlsZDogQ29uc3RydWN0LCBjaGlsZE5hbWU6IHN0cmluZykge1xuICAgIGlmICh0aGlzLmxvY2tlZCkge1xuXG4gICAgICAvLyBzcGVjaWFsIGVycm9yIGlmIHJvb3QgaXMgbG9ja2VkXG4gICAgICBpZiAoIXRoaXMucGF0aCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Nhbm5vdCBhZGQgY2hpbGRyZW4gZHVyaW5nIHN5bnRoZXNpcycpO1xuICAgICAgfVxuXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYENhbm5vdCBhZGQgY2hpbGRyZW4gdG8gXCIke3RoaXMucGF0aH1cIiBkdXJpbmcgc3ludGhlc2lzYCk7XG4gICAgfVxuXG4gICAgaWYgKGNoaWxkTmFtZSBpbiB0aGlzLl9jaGlsZHJlbikge1xuICAgICAgY29uc3QgbmFtZSA9IHRoaXMuaWQgfHwgJyc7XG4gICAgICBjb25zdCB0eXBlTmFtZSA9IHRoaXMuaG9zdC5jb25zdHJ1Y3Rvci5uYW1lO1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBUaGVyZSBpcyBhbHJlYWR5IGEgQ29uc3RydWN0IHdpdGggbmFtZSAnJHtjaGlsZE5hbWV9JyBpbiAke3R5cGVOYW1lfSR7bmFtZS5sZW5ndGggPiAwID8gJyBbJyArIG5hbWUgKyAnXScgOiAnJ31gKTtcbiAgICB9XG5cbiAgICB0aGlzLl9jaGlsZHJlbltjaGlsZE5hbWVdID0gY2hpbGQ7XG4gIH1cblxuICAvKipcbiAgICogVHJpZ2dlcnMgZWFjaCBhc3BlY3QgdG8gaW52b2tlIHZpc2l0XG4gICAqL1xuICBwcml2YXRlIGludm9rZUFzcGVjdHMoKTogdm9pZCB7XG4gICAgY29uc3QgZGVzY2VuZGFudHMgPSB0aGlzLmZpbmRBbGwoKTtcbiAgICBmb3IgKGNvbnN0IGFzcGVjdCBvZiB0aGlzLl9hc3BlY3RzKSB7XG4gICAgICBpZiAodGhpcy5pbnZva2VkQXNwZWN0cy5pbmNsdWRlcyhhc3BlY3QpKSB7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuICAgICAgZGVzY2VuZGFudHMuZm9yRWFjaChtZW1iZXIgPT4gYXNwZWN0LnZpc2l0KG1lbWJlcikpO1xuICAgICAgdGhpcy5pbnZva2VkQXNwZWN0cy5wdXNoKGFzcGVjdCk7XG4gICAgfVxuICB9XG59XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXG5leHBvcnQgY2xhc3MgQ29uc3RydWN0IGltcGxlbWVudHMgSUNvbnN0cnVjdCB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXG4gIGNvbnN0cnVjdG9yKHNjb3BlOiBDb25zdHJ1Y3QsIGlkOiBzdHJpbmcsIG9wdGlvbnM6IENvbnN0cnVjdE9wdGlvbnMgPSB7IH0pIHtcbiAgICAvLyBhdHRhY2ggdGhlIGNvbnN0cnVjdCB0byB0aGUgY29uc3RydWN0IHRyZWUgYnkgY3JlYXRpbmcgYSBub2RlXG4gICAgY29uc3Qgbm9kZUZhY3RvcnkgPSBvcHRpb25zLm5vZGVGYWN0b3J5ID8/IHsgY3JlYXRlTm9kZTogKGhvc3QsIG5vZGVTY29wZSwgbm9kZUlkKSA9PiBuZXcgTm9kZShob3N0LCBub2RlU2NvcGUsIG5vZGVJZCkgfTtcbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkodGhpcywgQ09OU1RSVUNUX05PREVfUFJPUEVSVFlfU1lNQk9MLCB7XG4gICAgICB2YWx1ZTogbm9kZUZhY3RvcnkuY3JlYXRlTm9kZSh0aGlzLCBzY29wZSwgaWQpLFxuICAgICAgZW51bWVyYWJsZTogZmFsc2UsXG4gICAgICBjb25maWd1cmFibGU6IGZhbHNlLFxuICAgIH0pO1xuXG4gICAgLy8gaW1wbGVtZW50IElEZXBlbmRhYmxlIHByaXZhdGVseVxuICAgIERlcGVuZGFibGVUcmFpdC5pbXBsZW1lbnQodGhpcywge1xuICAgICAgZGVwZW5kZW5jeVJvb3RzOiBbdGhpc10sXG4gICAgfSk7XG4gIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuICBwdWJsaWMgdG9TdHJpbmcoKSB7XG4gICAgcmV0dXJuIE5vZGUub2YodGhpcykucGF0aCB8fCAnPHJvb3Q+JztcbiAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXG4gIHByb3RlY3RlZCBvblZhbGlkYXRlKCk6IHN0cmluZ1tdIHtcbiAgICByZXR1cm4gW107XG4gIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuICBwcm90ZWN0ZWQgb25QcmVwYXJlKCk6IHZvaWQge1xuICAgIHJldHVybjtcbiAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXG4gIHByb3RlY3RlZCBvblN5bnRoZXNpemUoc2Vzc2lvbjogSVN5bnRoZXNpc1Nlc3Npb24pOiB2b2lkIHtcbiAgICBpZ25vcmUoc2Vzc2lvbik7XG4gIH1cbn1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXG5leHBvcnQgaW50ZXJmYWNlIFZhbGlkYXRpb25FcnJvciB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXG4gIHJlYWRvbmx5IHNvdXJjZTogQ29uc3RydWN0O1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuICByZWFkb25seSBtZXNzYWdlOiBzdHJpbmc7XG59XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuZXhwb3J0IGludGVyZmFjZSBJVmFsaWRhdGlvbiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcbiAgdmFsaWRhdGUoKTogc3RyaW5nW107XG59XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuZXhwb3J0IGVudW0gQ29uc3RydWN0T3JkZXIge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXG4gIFBSRU9SREVSLFxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuICBQT1NUT1JERVJcbn1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXG5leHBvcnQgaW50ZXJmYWNlIERlcGVuZGVuY3kge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcbiAgcmVhZG9ubHkgc291cmNlOiBJQ29uc3RydWN0O1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuICByZWFkb25seSB0YXJnZXQ6IElDb25zdHJ1Y3Q7XG59XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcbmV4cG9ydCBpbnRlcmZhY2UgSVN5bnRoZXNpc1Nlc3Npb24ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcbiAgcmVhZG9ubHkgb3V0ZGlyOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIEFkZGl0aW9uYWwgY29udGV4dCBwYXNzZWQgdG8gc3ludGhlc2l6ZU5vZGUgdGhyb3VnaCBgc2Vzc2lvbkNvbnRleHRgLlxuICAgKi9cbiAgW2tleTogc3RyaW5nXTogYW55O1xufVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcbmV4cG9ydCBpbnRlcmZhY2UgU3ludGhlc2lzT3B0aW9ucyB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuICByZWFkb25seSBvdXRkaXI6IHN0cmluZztcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuICByZWFkb25seSBza2lwVmFsaWRhdGlvbj86IGJvb2xlYW47XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXG4gIHJlYWRvbmx5IHNlc3Npb25Db250ZXh0PzogeyBba2V5OiBzdHJpbmddOiBhbnkgfTtcbn1cblxuZnVuY3Rpb24gaWdub3JlKF94OiBhbnkpIHtcbiAgcmV0dXJuO1xufVxuXG4vLyBJbXBvcnQgdGhpcyBfYWZ0ZXJfIGV2ZXJ5dGhpbmcgZWxzZSB0byBoZWxwIG5vZGUgd29yayB0aGUgY2xhc3NlcyBvdXQgaW4gdGhlIGNvcnJlY3Qgb3JkZXIuLi5cbmNvbnN0IFBBVEhfU0VQX1JFR0VYID0gbmV3IFJlZ0V4cChgJHtOb2RlLlBBVEhfU0VQfWAsICdnJyk7XG5cbi8qKlxuICogUmV0dXJuIGEgc2FuaXRpemVkIHZlcnNpb24gb2YgYW4gYXJiaXRyYXJ5IHN0cmluZywgc28gaXQgY2FuIGJlIHVzZWQgYXMgYW4gSURcbiAqL1xuZnVuY3Rpb24gc2FuaXRpemVJZChpZDogc3RyaW5nKSB7XG4gIC8vIEVzY2FwZSBwYXRoIHNlcHMgYXMgZG91YmxlIGRhc2hlc1xuICByZXR1cm4gaWQucmVwbGFjZShQQVRIX1NFUF9SRUdFWCwgJy0tJyk7XG59XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcbmV4cG9ydCBpbnRlcmZhY2UgQ29uc3RydWN0T3B0aW9ucyB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXG4gIHJlYWRvbmx5IG5vZGVGYWN0b3J5PzogSU5vZGVGYWN0b3J5O1xufVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcbmV4cG9ydCBpbnRlcmZhY2UgSU5vZGVGYWN0b3J5IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcbiAgY3JlYXRlTm9kZShob3N0OiBDb25zdHJ1Y3QsIHNjb3BlOiBJQ29uc3RydWN0LCBpZDogc3RyaW5nKTogTm9kZTtcbn1cbiJdfQ==