UNPKG

@aws/pdk

Version:

All documentation is located at: https://aws.github.io/aws-pdk

268 lines 35.1 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.buildDiagram = buildDiagram; /*! Copyright [Amazon.com](http://amazon.com/), Inc. or its affiliates. All Rights Reserved. SPDX-License-Identifier: Apache-2.0 */ const aws_arch_1 = require("../../../aws-arch"); const cdk_graph_1 = require("../../../cdk-graph"); const uniqBy = require("lodash.uniqby"); // eslint-disable-line @typescript-eslint/no-require-imports const Diagram = require("./entities"); const entities_1 = require("./entities"); const theme_1 = require("./theme"); const debug_1 = require("../debug"); /** * EdgeResolver class resolves edges within a diagram for rendering * @internal */ class EdgeResolver { constructor() { /** @internal */ this._edges = new Map(); } /** Adds diagram edge to the resolver to be resolved */ trackEdge(edge) { let fromId; let toId; if (edge instanceof Diagram.Edge) { fromId = edge.graphEdge.source.uuid; toId = edge.graphEdge.target.uuid; } else { fromId = edge.from.graphNode.uuid; toId = edge.to.graphNode.uuid; } const key = fromId < toId ? `${fromId}:${toId}` : `${toId}:${fromId}`; const edgeSet = this._edges.get(key) || []; this._edges.set(key, edgeSet.concat([edge])); } /** Resolve all edges based on diagram options */ resolveEdges(options) { const compact = options.preset === cdk_graph_1.FilterPreset.COMPACT; const resolvedEdges = []; for (let edges of this._edges.values()) { if (compact) { edges = edges.filter((edge) => !edge.isVerbose); } if (edges.length === 0) { continue; } edges.sort((a, b) => { const _a = getEdgeRank(a); const _b = getEdgeRank(b); if (_a === _b) return 0; if (_a < _b) return -1; return 1; }); edges = uniqBy(edges, getEdgeRank); // only return highest ranked edge unless verbose if (compact) { resolvedEdges.push(edges[0]); continue; } for (const _edge1 of edges) { for (const _edge2 of edges) { if (_edge1 === _edge2) continue; const _id1 = _edge1.attributes.get("id"); const _id2 = _edge2.attributes.get("id"); let _sameHead1 = _edge1.attributes.get("samehead"); _edge1.attributes.set("samehead", !_sameHead1 ? _id2 : `${_sameHead1},${_id2}`); let _sameTail1 = _edge1.attributes.get("sametail"); _edge1.attributes.set("sametail", !_sameTail1 ? _id2 : `${_sameTail1},${_id2}`); let _sameHead2 = _edge2.attributes.get("samehead"); _edge2.attributes.set("samehead", !_sameHead2 ? _id1 : `${_sameHead2},${_id1}`); let _sameTail2 = _edge2.attributes.get("sametail"); _edge2.attributes.set("sametail", !_sameTail2 ? _id1 : `${_sameTail2},${_id1}`); } } resolvedEdges.push(...edges); } return resolvedEdges; } } /** * Build a {@link Diagram.Diagram Diagram} for a given {@link Graph.Store} based on {@link DiagramOptions Options} * @internal */ function buildDiagram(store, options) { const { title, nodePositions } = options; const edgeResolve = new EdgeResolver(); theme_1.GraphTheme.init(options.theme); const entities = new Map(); const diagram = new Diagram.Diagram(title, aws_arch_1.AwsArchitecture.assetDirectory); function visit(gNode, parent) { if (gNode.isDestroyed) return; let entity; switch (gNode.nodeType) { case cdk_graph_1.NodeTypeEnum.RESOURCE: { entity = new Diagram.ResourceNode(gNode); break; } case cdk_graph_1.NodeTypeEnum.CFN_RESOURCE: { entity = new Diagram.CfnResourceNode(gNode); break; } case cdk_graph_1.NodeTypeEnum.NESTED_STACK: { entity = new Diagram.NestedStackCluster(gNode); break; } case cdk_graph_1.NodeTypeEnum.STACK: { if (theme_1.GraphTheme.instance.rendering.stack && new RegExp(theme_1.GraphTheme.instance.rendering.stack).test(gNode.id) === false) { // Ignore non-matching root stacks return; } entity = new Diagram.StackCluster(gNode); break; } default: { if (gNode.isLeaf) { if (gNode.hasFlag(cdk_graph_1.FlagEnum.CUSTOM_RESOURCE)) { entity = new Diagram.CustomResourceNode(gNode); } else { entity = new Diagram.Node(gNode); } } else { entity = new Diagram.Cluster(gNode); gNode.addFlag(cdk_graph_1.FlagEnum.CLUSTER); } break; } } if (nodePositions && entity instanceof Diagram.Node) { if (entity.graphNode.id in nodePositions) { entity.position = nodePositions[entity.graphNode.id]; } } if (entity instanceof entities_1.ImageNode && entity.image) { diagram.trackImage(entity.image); } if (parent instanceof Diagram.Container && parent.linkChildren) { edgeResolve.trackEdge(new entities_1.ChildLink(parent, entity)); } if (gNode.isLeaf) { entities.set(gNode.uuid, entity); parent.addNode(entity); } else { if (entity instanceof Diagram.Node) { entity = asContainer(entity); } parent.addSubgraph(entity); entities.set(gNode.uuid, entity); gNode.children.forEach((child) => visit(child, entity)); } } if (store.stages.length > 1) { const stageRendering = theme_1.GraphTheme.instance.rendering.stage || "last"; let stages; switch (stageRendering) { case "all": { stages = store.stages; break; } case "first": { stages = store.stages.slice(0, 1); break; } case "last": { stages = store.stages.slice(-1); break; } default: { stages = store.stages.filter((stage) => stage.id.match(stageRendering)); } } // traverse all stages stages.forEach((gStage) => { const dStage = new Diagram.StageCluster(gStage); diagram.addSubgraph(dStage); entities.set(gStage.uuid, dStage); gStage.children.forEach((child) => visit(child, dStage)); }); } else if (store.rootStacks.length) { // traverse all root stack store.rootStacks.forEach((gStack) => { const dStack = new Diagram.StackCluster(gStack); diagram.addSubgraph(dStack); entities.set(gStack.uuid, dStack); gStack.children.forEach((child) => visit(child, dStack)); }); } else { store.root.children.forEach((gChild) => { if (gChild.isGraphContainer) { gChild.children.forEach((_gChild) => { visit(_gChild, diagram); }); } else { visit(gChild, diagram); } }); } // apply all edges store.edges.forEach((gEdge) => { if (gEdge.isDestroyed) return; const dSource = entities.get(gEdge.source.uuid); const dTarget = entities.get(gEdge.target.uuid); if (!dSource || !dTarget) { debug_1.IS_DEBUG && console.warn("Diagram.Edge unresolved source and/or target:", `source(${gEdge.source} => ${dSource})`, `target(${gEdge.target} => ${dTarget})`); return; } let edge = undefined; switch (gEdge.edgeType) { case cdk_graph_1.EdgeTypeEnum.REFERENCE: { edge = new Diagram.ReferenceLink(gEdge, dSource, dTarget); break; } case cdk_graph_1.EdgeTypeEnum.DEPENDENCY: { edge = new Diagram.DependencyLink(gEdge, dSource, dTarget); break; } } if (edge) { entities.set(gEdge.uuid, edge); edgeResolve.trackEdge(edge); } }); edgeResolve.resolveEdges(options).forEach((edge) => { diagram.addEdge(edge); }); return diagram; } /** * Wrap a {@link Diagram.Node} with {@link Diagram.Container} to support adding child {@link Diagram.Node}s * @internal */ function asContainer(node) { const container = new Diagram.Container(node.graphNode); container.addNode(node); return container; } /** * Get the rank score of an {@link Diagram.BaseEdge Edge} used to sort and prioritize edges * @internal */ function getEdgeRank(edge) { if (edge instanceof Diagram.ChildLink) { return 0; } if (edge instanceof Diagram.ReferenceLink) { return 1; } if (edge instanceof Diagram.DependencyLink) { return 2; } return 3; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGlhZ3JhbS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImRpYWdyYW0udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFpSUEsb0NBeUxDO0FBMVREO3NDQUNzQztBQUN0Qyw0Q0FBZ0Q7QUFDaEQsOENBT3dCO0FBQ3hCLHdDQUF5QyxDQUFDLDREQUE0RDtBQUV0RyxzQ0FBc0M7QUFDdEMseUNBQWtEO0FBQ2xELG1DQUEyRDtBQUUzRCxvQ0FBb0M7QUFnQnBDOzs7R0FHRztBQUNILE1BQU0sWUFBWTtJQUFsQjtRQUNFLGdCQUFnQjtRQUNDLFdBQU0sR0FBb0MsSUFBSSxHQUFHLEVBQUUsQ0FBQztJQW9GdkUsQ0FBQztJQWxGQyx1REFBdUQ7SUFDdkQsU0FBUyxDQUFDLElBQXNCO1FBQzlCLElBQUksTUFBYyxDQUFDO1FBQ25CLElBQUksSUFBWSxDQUFDO1FBQ2pCLElBQUksSUFBSSxZQUFZLE9BQU8sQ0FBQyxJQUFJLEVBQUUsQ0FBQztZQUNqQyxNQUFNLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDO1lBQ3BDLElBQUksR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUM7UUFDcEMsQ0FBQzthQUFNLENBQUM7WUFDTixNQUFNLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDO1lBQ2xDLElBQUksR0FBRyxJQUFJLENBQUMsRUFBRSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUM7UUFDaEMsQ0FBQztRQUNELE1BQU0sR0FBRyxHQUFHLE1BQU0sR0FBRyxJQUFJLENBQUMsQ0FBQyxDQUFDLEdBQUcsTUFBTSxJQUFJLElBQUksRUFBRSxDQUFDLENBQUMsQ0FBQyxHQUFHLElBQUksSUFBSSxNQUFNLEVBQUUsQ0FBQztRQUN0RSxNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsSUFBSSxFQUFFLENBQUM7UUFD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IEluYy4gb3IgaXRzIGFmZmlsaWF0ZXMuIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG5TUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQXBhY2hlLTIuMCAqL1xuaW1wb3J0IHsgQXdzQXJjaGl0ZWN0dXJlIH0gZnJvbSBcIkBhd3MvYXdzLWFyY2hcIjtcbmltcG9ydCB7XG4gIEVkZ2VUeXBlRW51bSxcbiAgRmlsdGVyUHJlc2V0LFxuICBGbGFnRW51bSxcbiAgR3JhcGgsXG4gIE5vZGVUeXBlRW51bSxcbiAgVVVJRCxcbn0gZnJvbSBcIkBhd3MvY2RrLWdyYXBoXCI7XG5pbXBvcnQgdW5pcUJ5ID0gcmVxdWlyZShcImxvZGFzaC51bmlxYnlcIik7IC8vIGVzbGludC1kaXNhYmxlLWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXJlcXVpcmUtaW1wb3J0c1xuaW1wb3J0ICogYXMgRG90IGZyb20gXCJ0cy1ncmFwaHZpelwiO1xuaW1wb3J0ICogYXMgRGlhZ3JhbSBmcm9tIFwiLi9lbnRpdGllc1wiO1xuaW1wb3J0IHsgQ2hpbGRMaW5rLCBJbWFnZU5vZGUgfSBmcm9tIFwiLi9lbnRpdGllc1wiO1xuaW1wb3J0IHsgR3JhcGhUaGVtZSwgR3JhcGhUaGVtZUNvbmZpZ1Byb3AgfSBmcm9tIFwiLi90aGVtZVwiO1xuaW1wb3J0IHsgSU5vZGVQb3NpdGlvbiB9IGZyb20gXCIuLi8uLi9jb25maWdcIjtcbmltcG9ydCB7IElTX0RFQlVHIH0gZnJvbSBcIi4uL2RlYnVnXCI7XG5cbi8qKlxuICogVW5pb24gb2YgZW50aXRpZXMgc3VwcG9ydCBieSBkaWFncmFtXG4gKiBAaW50ZXJuYWxcbiAqL1xudHlwZSBURGlhZ3JhbUVudGl0eSA9IERpYWdyYW0uU3ViZ3JhcGggfCBEaWFncmFtLk5vZGUgfCBEaWFncmFtLkVkZ2U7XG5cbi8qKiBPcHRpb25zIGZvciBkaWFncmFtcyAqL1xuZXhwb3J0IGludGVyZmFjZSBEaWFncmFtT3B0aW9ucyB7XG4gIHJlYWRvbmx5IHRpdGxlOiBzdHJpbmc7XG4gIHJlYWRvbmx5IHByZXNldD86IEZpbHRlclByZXNldDtcbiAgcmVhZG9ubHkgdGhlbWU/OiBHcmFwaFRoZW1lQ29uZmlnUHJvcDtcbiAgcmVhZG9ubHkgbm9kZVBvc2l0aW9ucz86IHsgW2Nka0NvbnN0cnVjdElkOiBzdHJpbmddOiBJTm9kZVBvc2l0aW9uIH07XG59XG5cbi8qKlxuICogRWRnZVJlc29sdmVyIGNsYXNzIHJlc29sdmVzIGVkZ2VzIHdpdGhpbiBhIGRpYWdyYW0gZm9yIHJlbmRlcmluZ1xuICogQGludGVybmFsXG4gKi9cbmNsYXNzIEVkZ2VSZXNvbHZlciB7XG4gIC8qKiBAaW50ZXJuYWwgKi9cbiAgcHJpdmF0ZSByZWFkb25seSBfZWRnZXM6IE1hcDxzdHJpbmcsIERpYWdyYW0uQmFzZUVkZ2VbXT4gPSBuZXcgTWFwKCk7XG5cbiAgLyoqIEFkZHMgZGlhZ3JhbSBlZGdlIHRvIHRoZSByZXNvbHZlciB0byBiZSByZXNvbHZlZCAqL1xuICB0cmFja0VkZ2UoZWRnZTogRGlhZ3JhbS5CYXNlRWRnZSk6IHZvaWQge1xuICAgIGxldCBmcm9tSWQ6IHN0cmluZztcbiAgICBsZXQgdG9JZDogc3RyaW5nO1xuICAgIGlmIChlZGdlIGluc3RhbmNlb2YgRGlhZ3JhbS5FZGdlKSB7XG4gICAgICBmcm9tSWQgPSBlZGdlLmdyYXBoRWRnZS5zb3VyY2UudXVpZDtcbiAgICAgIHRvSWQgPSBlZGdlLmdyYXBoRWRnZS50YXJnZXQudXVpZDtcbiAgICB9IGVsc2Uge1xuICAgICAgZnJvbUlkID0gZWRnZS5mcm9tLmdyYXBoTm9kZS51dWlkO1xuICAgICAgdG9JZCA9IGVkZ2UudG8uZ3JhcGhOb2RlLnV1aWQ7XG4gICAgfVxuICAgIGNvbnN0IGtleSA9IGZyb21JZCA8IHRvSWQgPyBgJHtmcm9tSWR9OiR7dG9JZH1gIDogYCR7dG9JZH06JHtmcm9tSWR9YDtcbiAgICBjb25zdCBlZGdlU2V0ID0gdGhpcy5fZWRnZXMuZ2V0KGtleSkgfHwgW107XG4gICAgdGhpcy5fZWRnZXMuc2V0KGtleSwgZWRnZVNldC5jb25jYXQoW2VkZ2VdKSk7XG4gIH1cblxuICAvKiogUmVzb2x2ZSBhbGwgZWRnZXMgYmFzZWQgb24gZGlhZ3JhbSBvcHRpb25zICovXG4gIHJlc29sdmVFZGdlcyhvcHRpb25zOiBEaWFncmFtT3B0aW9ucyk6IERvdC5FZGdlW10ge1xuICAgIGNvbnN0IGNvbXBhY3QgPSBvcHRpb25zLnByZXNldCA9PT0gRmlsdGVyUHJlc2V0LkNPTVBBQ1Q7XG5cbiAgICBjb25zdCByZXNvbHZlZEVkZ2VzOiBEb3QuRWRnZVtdID0gW107XG4gICAgZm9yIChsZXQgZWRnZXMgb2YgdGhpcy5fZWRnZXMudmFsdWVzKCkpIHtcbiAgICAgIGlmIChjb21wYWN0KSB7XG4gICAgICAgIGVkZ2VzID0gZWRnZXMuZmlsdGVyKChlZGdlKSA9PiAhZWRnZS5pc1ZlcmJvc2UpO1xuICAgICAgfVxuXG4gICAgICBpZiAoZWRnZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuXG4gICAgICBlZGdlcy5zb3J0KChhLCBiKSA9PiB7XG4gICAgICAgIGNvbnN0IF9hID0gZ2V0RWRnZVJhbmsoYSk7XG4gICAgICAgIGNvbnN0IF9iID0gZ2V0RWRnZVJhbmsoYik7XG4gICAgICAgIGlmIChfYSA9PT0gX2IpIHJldHVybiAwO1xuICAgICAgICBpZiAoX2EgPCBfYikgcmV0dXJuIC0xO1xuICAgICAgICByZXR1cm4gMTtcbiAgICAgIH0pO1xuXG4gICAgICBlZGdlcyA9IHVuaXFCeShlZGdlcywgZ2V0RWRnZVJhbmspO1xuXG4gICAgICAvLyBvbmx5IHJldHVybiBoaWdoZXN0IHJhbmtlZCBlZGdlIHVubGVzcyB2ZXJib3NlXG4gICAgICBpZiAoY29tcGFjdCkge1xuICAgICAgICByZXNvbHZlZEVkZ2VzLnB1c2goZWRnZXNbMF0pO1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgZm9yIChjb25zdCBfZWRnZTEgb2YgZWRnZXMpIHtcbiAgICAgICAgZm9yIChjb25zdCBfZWRnZTIgb2YgZWRnZXMpIHtcbiAgICAgICAgICBpZiAoX2VkZ2UxID09PSBfZWRnZTIpIGNvbnRpbnVlO1xuXG4gICAgICAgICAgY29uc3QgX2lkMSA9IF9lZGdlMS5hdHRyaWJ1dGVzLmdldChcImlkXCIpITtcbiAgICAgICAgICBjb25zdCBfaWQyID0gX2VkZ2UyLmF0dHJpYnV0ZXMuZ2V0KFwiaWRcIikhO1xuXG4gICAgICAgICAgbGV0IF9zYW1lSGVhZDEgPSBfZWRnZTEuYXR0cmlidXRlcy5nZXQoXCJzYW1laGVhZFwiKSBhcyBzdHJpbmc7XG4gICAgICAgICAgX2VkZ2UxLmF0dHJpYnV0ZXMuc2V0KFxuICAgICAgICAgICAgXCJzYW1laGVhZFwiLFxuICAgICAgICAgICAgIV9zYW1lSGVhZDEgPyBfaWQyIDogYCR7X3NhbWVIZWFkMX0sJHtfaWQyfWBcbiAgICAgICAgICApO1xuICAgICAgICAgIGxldCBfc2FtZVRhaWwxID0gX2VkZ2UxLmF0dHJpYnV0ZXMuZ2V0KFwic2FtZXRhaWxcIikgYXMgc3RyaW5nO1xuICAgICAgICAgIF9lZGdlMS5hdHRyaWJ1dGVzLnNldChcbiAgICAgICAgICAgIFwic2FtZXRhaWxcIixcbiAgICAgICAgICAgICFfc2FtZVRhaWwxID8gX2lkMiA6IGAke19zYW1lVGFpbDF9LCR7X2lkMn1gXG4gICAgICAgICAgKTtcblxuICAgICAgICAgIGxldCBfc2FtZUhlYWQyID0gX2VkZ2UyLmF0dHJpYnV0ZXMuZ2V0KFwic2FtZWhlYWRcIikgYXMgc3RyaW5nO1xuICAgICAgICAgIF9lZGdlMi5hdHRyaWJ1dGVzLnNldChcbiAgICAgICAgICAgIFwic2FtZWhlYWRcIixcbiAgICAgICAgICAgICFfc2FtZUhlYWQyID8gX2lkMSA6IGAke19zYW1lSGVhZDJ9LCR7X2lkMX1gXG4gICAgICAgICAgKTtcbiAgICAgICAgICBsZXQgX3NhbWVUYWlsMiA9IF9lZGdlMi5hdHRyaWJ1dGVzLmdldChcInNhbWV0YWlsXCIpIGFzIHN0cmluZztcbiAgICAgICAgICBfZWRnZTIuYXR0cmlidXRlcy5zZXQoXG4gICAgICAgICAgICBcInNhbWV0YWlsXCIsXG4gICAgICAgICAgICAhX3NhbWVUYWlsMiA/IF9pZDEgOiBgJHtfc2FtZVRhaWwyfSwke19pZDF9YFxuICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgcmVzb2x2ZWRFZGdlcy5wdXNoKC4uLmVkZ2VzKTtcbiAgICB9XG5cbiAgICByZXR1cm4gcmVzb2x2ZWRFZGdlcztcbiAgfVxufVxuXG4vKipcbiAqIEJ1aWxkIGEge0BsaW5rIERpYWdyYW0uRGlhZ3JhbSBEaWFncmFtfSBmb3IgYSBnaXZlbiB7QGxpbmsgR3JhcGguU3RvcmV9IGJhc2VkIG9uIHtAbGluayBEaWFncmFtT3B0aW9ucyBPcHRpb25zfVxuICogQGludGVybmFsXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBidWlsZERpYWdyYW0oXG4gIHN0b3JlOiBHcmFwaC5TdG9yZSxcbiAgb3B0aW9uczogRGlhZ3JhbU9wdGlvbnNcbik6IERpYWdyYW0uRGlhZ3JhbSB7XG4gIGNvbnN0IHsgdGl0bGUsIG5vZGVQb3NpdGlvbnMgfSA9IG9wdGlvbnM7XG5cbiAgY29uc3QgZWRnZVJlc29sdmUgPSBuZXcgRWRnZVJlc29sdmVyKCk7XG5cbiAgR3JhcGhUaGVtZS5pbml0KG9wdGlvbnMudGhlbWUpO1xuXG4gIGNvbnN0IGVudGl0aWVzOiBNYXA8VVVJRCwgVERpYWdyYW1FbnRpdHk+ID0gbmV3IE1hcCgpO1xuICBjb25zdCBkaWFncmFtID0gbmV3IERpYWdyYW0uRGlhZ3JhbSh0aXRsZSwgQXdzQXJjaGl0ZWN0dXJlLmFzc2V0RGlyZWN0b3J5KTtcblxuICBmdW5jdGlvbiB2aXNpdChcbiAgICBnTm9kZTogR3JhcGguTm9kZSxcbiAgICBwYXJlbnQ6IERpYWdyYW0uU3ViZ3JhcGggfCBEaWFncmFtLkRpYWdyYW1cbiAgKSB7XG4gICAgaWYgKGdOb2RlLmlzRGVzdHJveWVkKSByZXR1cm47XG5cbiAgICBsZXQgZW50aXR5OiBEaWFncmFtLkNvbnRhaW5lciB8IERpYWdyYW0uTm9kZTtcblxuICAgIHN3aXRjaCAoZ05vZGUubm9kZVR5cGUpIHtcbiAgICAgIGNhc2UgTm9kZVR5cGVFbnVtLlJFU09VUkNFOiB7XG4gICAgICAgIGVudGl0eSA9IG5ldyBEaWFncmFtLlJlc291cmNlTm9kZShnTm9kZSBhcyBHcmFwaC5SZXNvdXJjZU5vZGUpO1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICAgIGNhc2UgTm9kZVR5cGVFbnVtLkNGTl9SRVNPVVJDRToge1xuICAgICAgICBlbnRpdHkgPSBuZXcgRGlhZ3JhbS5DZm5SZXNvdXJjZU5vZGUoZ05vZGUgYXMgR3JhcGguQ2ZuUmVzb3VyY2VOb2RlKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgICBjYXNlIE5vZGVUeXBlRW51bS5ORVNURURfU1RBQ0s6IHtcbiAgICAgICAgZW50aXR5ID0gbmV3IERpYWdyYW0uTmVzdGVkU3RhY2tDbHVzdGVyKGdOb2RlIGFzIEdyYXBoLk5lc3RlZFN0YWNrTm9kZSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgICAgY2FzZSBOb2RlVHlwZUVudW0uU1RBQ0s6IHtcbiAgICAgICAgaWYgKFxuICAgICAgICAgIEdyYXBoVGhlbWUuaW5zdGFuY2UucmVuZGVyaW5nLnN0YWNrICYmXG4gICAgICAgICAgbmV3IFJlZ0V4cChHcmFwaFRoZW1lLmluc3RhbmNlLnJlbmRlcmluZy5zdGFjaykudGVzdChnTm9kZS5pZCkgPT09XG4gICAgICAgICAgICBmYWxzZVxuICAgICAgICApIHtcbiAgICAgICAgICAvLyBJZ25vcmUgbm9uLW1hdGNoaW5nIHJvb3Qgc3RhY2tzXG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGVudGl0eSA9IG5ldyBEaWFncmFtLlN0YWNrQ2x1c3RlcihnTm9kZSBhcyBHcmFwaC5TdGFja05vZGUpO1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICAgIGRlZmF1bHQ6IHtcbiAgICAgICAgaWYgKGdOb2RlLmlzTGVhZikge1xuICAgICAgICAgIGlmIChnTm9kZS5oYXNGbGFnKEZsYWdFbnVtLkNVU1RPTV9SRVNPVVJDRSkpIHtcbiAgICAgICAgICAgIGVudGl0eSA9IG5ldyBEaWFncmFtLkN1c3RvbVJlc291cmNlTm9kZShnTm9kZSk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGVudGl0eSA9IG5ldyBEaWFncmFtLk5vZGUoZ05vZGUpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBlbnRpdHkgPSBuZXcgRGlhZ3JhbS5DbHVzdGVyKGdOb2RlKTtcbiAgICAgICAgICBnTm9kZS5hZGRGbGFnKEZsYWdFbnVtLkNMVVNURVIpO1xuICAgICAgICB9XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmIChub2RlUG9zaXRpb25zICYmIGVudGl0eSBpbnN0YW5jZW9mIERpYWdyYW0uTm9kZSkge1xuICAgICAgaWYgKGVudGl0eS5ncmFwaE5vZGUuaWQgaW4gbm9kZVBvc2l0aW9ucykge1xuICAgICAgICBlbnRpdHkucG9zaXRpb24gPSBub2RlUG9zaXRpb25zW2VudGl0eS5ncmFwaE5vZGUuaWRdITtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoZW50aXR5IGluc3RhbmNlb2YgSW1hZ2VOb2RlICYmIGVudGl0eS5pbWFnZSkge1xuICAgICAgZGlhZ3JhbS50cmFja0ltYWdlKGVudGl0eS5pbWFnZSk7XG4gICAgfVxuXG4gICAgaWYgKHBhcmVudCBpbnN0YW5jZW9mIERpYWdyYW0uQ29udGFpbmVyICYmIHBhcmVudC5saW5rQ2hpbGRyZW4pIHtcbiAgICAgIGVkZ2VSZXNvbHZlLnRyYWNrRWRnZShuZXcgQ2hpbGRMaW5rKHBhcmVudCwgZW50aXR5KSk7XG4gICAgfVxuXG4gICAgaWYgKGdOb2RlLmlzTGVhZikge1xuICAgICAgZW50aXRpZXMuc2V0KGdOb2RlLnV1aWQsIGVudGl0eSk7XG4gICAgICBwYXJlbnQuYWRkTm9kZShlbnRpdHkgYXMgRGlhZ3JhbS5Ob2RlKTtcbiAgICB9IGVsc2Uge1xuICAgICAgaWYgKGVudGl0eSBpbnN0YW5jZW9mIERpYWdyYW0uTm9kZSkge1xuICAgICAgICBlbnRpdHkgPSBhc0NvbnRhaW5lcihlbnRpdHkpO1xuICAgICAgfVxuXG4gICAgICBwYXJlbnQuYWRkU3ViZ3JhcGgoZW50aXR5IGFzIERpYWdyYW0uQ29udGFpbmVyKTtcblxuICAgICAgZW50aXRpZXMuc2V0KGdOb2RlLnV1aWQsIGVudGl0eSk7XG5cbiAgICAgIGdOb2RlLmNoaWxkcmVuLmZvckVhY2goKGNoaWxkKSA9PlxuICAgICAgICB2aXNpdChjaGlsZCwgZW50aXR5IGFzIERpYWdyYW0uQ29udGFpbmVyKVxuICAgICAgKTtcbiAgICB9XG4gIH1cblxuICBpZiAoc3RvcmUuc3RhZ2VzLmxlbmd0aCA+IDEpIHtcbiAgICBjb25zdCBzdGFnZVJlbmRlcmluZyA9IEdyYXBoVGhlbWUuaW5zdGFuY2UucmVuZGVyaW5nLnN0YWdlIHx8IFwibGFzdFwiO1xuICAgIGxldCBzdGFnZXM6IEdyYXBoLlN0YWdlTm9kZVtdO1xuICAgIHN3aXRjaCAoc3RhZ2VSZW5kZXJpbmcpIHtcbiAgICAgIGNhc2UgXCJhbGxcIjoge1xuICAgICAgICBzdGFnZXMgPSBzdG9yZS5zdGFnZXM7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgICAgY2FzZSBcImZpcnN0XCI6IHtcbiAgICAgICAgc3RhZ2VzID0gc3RvcmUuc3RhZ2VzLnNsaWNlKDAsIDEpO1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICAgIGNhc2UgXCJsYXN0XCI6IHtcbiAgICAgICAgc3RhZ2VzID0gc3RvcmUuc3RhZ2VzLnNsaWNlKC0xKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgICBkZWZhdWx0OiB7XG4gICAgICAgIHN0YWdlcyA9IHN0b3JlLnN0YWdlcy5maWx0ZXIoKHN0YWdlKSA9PiBzdGFnZS5pZC5tYXRjaChzdGFnZVJlbmRlcmluZykpO1xuICAgICAgfVxuICAgIH1cbiAgICAvLyB0cmF2ZXJzZSBhbGwgc3RhZ2VzXG4gICAgc3RhZ2VzLmZvckVhY2goKGdTdGFnZSkgPT4ge1xuICAgICAgY29uc3QgZFN0YWdlID0gbmV3IERpYWdyYW0uU3RhZ2VDbHVzdGVyKGdTdGFnZSk7XG4gICAgICBkaWFncmFtLmFkZFN1YmdyYXBoKGRTdGFnZSk7XG4gICAgICBlbnRpdGllcy5zZXQoZ1N0YWdlLnV1aWQsIGRTdGFnZSk7XG4gICAgICBnU3RhZ2UuY2hpbGRyZW4uZm9yRWFjaCgoY2hpbGQpID0+IHZpc2l0KGNoaWxkLCBkU3RhZ2UpKTtcbiAgICB9KTtcbiAgfSBlbHNlIGlmIChzdG9yZS5yb290U3RhY2tzLmxlbmd0aCkge1xuICAgIC8vIHRyYXZlcnNlIGFsbCByb290IHN0YWNrXG4gICAgc3RvcmUucm9vdFN0YWNrcy5mb3JFYWNoKChnU3RhY2spID0+IHtcbiAgICAgIGNvbnN0IGRTdGFjayA9IG5ldyBEaWFncmFtLlN0YWNrQ2x1c3RlcihnU3RhY2spO1xuICAgICAgZGlhZ3JhbS5hZGRTdWJncmFwaChkU3RhY2spO1xuICAgICAgZW50aXRpZXMuc2V0KGdTdGFjay51dWlkLCBkU3RhY2spO1xuICAgICAgZ1N0YWNrLmNoaWxkcmVuLmZvckVhY2goKGNoaWxkKSA9PiB2aXNpdChjaGlsZCwgZFN0YWNrKSk7XG4gICAgfSk7XG4gIH0gZWxzZSB7XG4gICAgc3RvcmUucm9vdC5jaGlsZHJlbi5mb3JFYWNoKChnQ2hpbGQpID0+IHtcbiAgICAgIGlmIChnQ2hpbGQuaXNHcmFwaENvbnRhaW5lcikge1xuICAgICAgICBnQ2hpbGQuY2hpbGRyZW4uZm9yRWFjaCgoX2dDaGlsZCkgPT4ge1xuICAgICAgICAgIHZpc2l0KF9nQ2hpbGQsIGRpYWdyYW0pO1xuICAgICAgICB9KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHZpc2l0KGdDaGlsZCwgZGlhZ3JhbSk7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICAvLyBhcHBseSBhbGwgZWRnZXNcbiAgc3RvcmUuZWRnZXMuZm9yRWFjaCgoZ0VkZ2UpID0+IHtcbiAgICBpZiAoZ0VkZ2UuaXNEZXN0cm95ZWQpIHJldHVybjtcblxuICAgIGNvbnN0IGRTb3VyY2UgPSBlbnRpdGllcy5nZXQoZ0VkZ2Uuc291cmNlLnV1aWQpIGFzXG4gICAgICB8IERpYWdyYW0uQ29udGFpbmVyXG4gICAgICB8IERpYWdyYW0uTm9kZTtcbiAgICBjb25zdCBkVGFyZ2V0ID0gZW50aXRpZXMuZ2V0KGdFZGdlLnRhcmdldC51dWlkKSBhc1xuICAgICAgfCBEaWFncmFtLkNvbnRhaW5lclxuICAgICAgfCBEaWFncmFtLk5vZGU7XG5cbiAgICBpZiAoIWRTb3VyY2UgfHwgIWRUYXJnZXQpIHtcbiAgICAgIElTX0RFQlVHICYmXG4gICAgICAgIGNvbnNvbGUud2FybihcbiAgICAgICAgICBcIkRpYWdyYW0uRWRnZSB1bnJlc29sdmVkIHNvdXJjZSBhbmQvb3IgdGFyZ2V0OlwiLFxuICAgICAgICAgIGBzb3VyY2UoJHtnRWRnZS5zb3VyY2V9ID0+ICR7ZFNvdXJjZX0pYCxcbiAgICAgICAgICBgdGFyZ2V0KCR7Z0VkZ2UudGFyZ2V0fSA9PiAke2RUYXJnZXR9KWBcbiAgICAgICAgKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBsZXQgZWRnZTogRGlhZ3JhbS5FZGdlIHwgdW5kZWZpbmVkID0gdW5kZWZpbmVkO1xuXG4gICAgc3dpdGNoIChnRWRnZS5lZGdlVHlwZSkge1xuICAgICAgY2FzZSBFZGdlVHlwZUVudW0uUkVGRVJFTkNFOiB7XG4gICAgICAgIGVkZ2UgPSBuZXcgRGlhZ3JhbS5SZWZlcmVuY2VMaW5rKGdFZGdlLCBkU291cmNlLCBkVGFyZ2V0KTtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgICBjYXNlIEVkZ2VUeXBlRW51bS5ERVBFTkRFTkNZOiB7XG4gICAgICAgIGVkZ2UgPSBuZXcgRGlhZ3JhbS5EZXBlbmRlbmN5TGluayhnRWRnZSwgZFNvdXJjZSwgZFRhcmdldCk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmIChlZGdlKSB7XG4gICAgICBlbnRpdGllcy5zZXQoZ0VkZ2UudXVpZCwgZWRnZSk7XG4gICAgICBlZGdlUmVzb2x2ZS50cmFja0VkZ2UoZWRnZSk7XG4gICAgfVxuICB9KTtcblxuICBlZGdlUmVzb2x2ZS5yZXNvbHZlRWRnZXMob3B0aW9ucykuZm9yRWFjaCgoZWRnZSkgPT4ge1xuICAgIGRpYWdyYW0uYWRkRWRnZShlZGdlKTtcbiAgfSk7XG5cbiAgcmV0dXJuIGRpYWdyYW07XG59XG5cbi8qKlxuICogV3JhcCBhIHtAbGluayBEaWFncmFtLk5vZGV9IHdpdGgge0BsaW5rIERpYWdyYW0uQ29udGFpbmVyfSB0byBzdXBwb3J0IGFkZGluZyBjaGlsZCB7QGxpbmsgRGlhZ3JhbS5Ob2RlfXNcbiAqIEBpbnRlcm5hbFxuICovXG5mdW5jdGlvbiBhc0NvbnRhaW5lcihub2RlOiBEaWFncmFtLk5vZGUpOiBEaWFncmFtLkNvbnRhaW5lciB7XG4gIGNvbnN0IGNvbnRhaW5lciA9IG5ldyBEaWFncmFtLkNvbnRhaW5lcihub2RlLmdyYXBoTm9kZSk7XG4gIGNvbnRhaW5lci5hZGROb2RlKG5vZGUpO1xuICByZXR1cm4gY29udGFpbmVyO1xufVxuXG4vKipcbiAqIEdldCB0aGUgcmFuayBzY29yZSBvZiBhbiB7QGxpbmsgRGlhZ3JhbS5CYXNlRWRnZSBFZGdlfSB1c2VkIHRvIHNvcnQgYW5kIHByaW9yaXRpemUgZWRnZXNcbiAqIEBpbnRlcm5hbFxuICovXG5mdW5jdGlvbiBnZXRFZGdlUmFuayhlZGdlOiBEaWFncmFtLkJhc2VFZGdlKTogbnVtYmVyIHtcbiAgaWYgKGVkZ2UgaW5zdGFuY2VvZiBEaWFncmFtLkNoaWxkTGluaykge1xuICAgIHJldHVybiAwO1xuICB9XG4gIGlmIChlZGdlIGluc3RhbmNlb2YgRGlhZ3JhbS5SZWZlcmVuY2VMaW5rKSB7XG4gICAgcmV0dXJuIDE7XG4gIH1cbiAgaWYgKGVkZ2UgaW5zdGFuY2VvZiBEaWFncmFtLkRlcGVuZGVuY3lMaW5rKSB7XG4gICAgcmV0dXJuIDI7XG4gIH1cbiAgcmV0dXJuIDM7XG59XG4iXX0=