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==