@aws/pdk
Version:
All documentation is located at: https://aws.github.io/aws-pdk
268 lines • 35.1 kB
JavaScript
;
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=