aws-cdk
Version:
CDK Toolkit, the command line tool for CDK apps
166 lines • 24.2 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.WorkGraphBuilder = void 0;
const cxapi = require("@aws-cdk/cx-api");
const cdk_assets_1 = require("cdk-assets");
const content_hash_1 = require("./content-hash");
const work_graph_1 = require("./work-graph");
const work_graph_types_1 = require("./work-graph-types");
class WorkGraphBuilder {
constructor(prebuildAssets, idPrefix = '') {
this.prebuildAssets = prebuildAssets;
this.idPrefix = idPrefix;
this.graph = new work_graph_1.WorkGraph();
}
addStack(artifact) {
this.graph.addNodes({
type: 'stack',
id: `${this.idPrefix}${artifact.id}`,
dependencies: new Set(this.stackArtifactIds(onlyStacks(artifact.dependencies))),
stack: artifact,
deploymentState: work_graph_types_1.DeploymentState.PENDING,
priority: WorkGraphBuilder.PRIORITIES.stack,
});
}
/**
* Oof, see this parameter list
*/
// eslint-disable-next-line max-len
addAsset(parentStack, assetManifestArtifact, assetManifest, asset) {
// Just the artifact identifier
const assetId = asset.id.assetId;
const buildId = `build-${assetId}-${(0, content_hash_1.contentHashAny)([assetId, asset.genericSource]).substring(0, 10)}`;
const publishId = `publish-${assetId}-${(0, content_hash_1.contentHashAny)([assetId, asset.genericDestination]).substring(0, 10)}`;
// Build node only gets added once because they are all the same
if (!this.graph.tryGetNode(buildId)) {
const node = {
type: 'asset-build',
id: buildId,
note: assetId,
dependencies: new Set([
...this.stackArtifactIds(assetManifestArtifact.dependencies),
// If we disable prebuild, then assets inherit (stack) dependencies from their parent stack
...!this.prebuildAssets ? this.stackArtifactIds(onlyStacks(parentStack.dependencies)) : [],
]),
parentStack: parentStack,
assetManifestArtifact,
assetManifest,
asset,
deploymentState: work_graph_types_1.DeploymentState.PENDING,
priority: WorkGraphBuilder.PRIORITIES['asset-build'],
};
this.graph.addNodes(node);
}
const publishNode = this.graph.tryGetNode(publishId);
if (!publishNode) {
this.graph.addNodes({
type: 'asset-publish',
id: publishId,
note: `${asset.id}`,
dependencies: new Set([
buildId,
]),
parentStack,
assetManifestArtifact,
assetManifest,
asset,
deploymentState: work_graph_types_1.DeploymentState.PENDING,
priority: WorkGraphBuilder.PRIORITIES['asset-publish'],
});
}
for (const inheritedDep of this.stackArtifactIds(onlyStacks(parentStack.dependencies))) {
// The asset publish step also depends on the stacks that the parent depends on.
// This is purely cosmetic: if we don't do this, the progress printing of asset publishing
// is going to interfere with the progress bar of the stack deployment. We could remove this
// for overall faster deployments if we ever have a better method of progress displaying.
// Note: this may introduce a cycle if one of the parent's dependencies is another stack that
// depends on this asset. To workaround this we remove these cycles once all nodes have
// been added to the graph.
this.graph.addDependency(publishId, inheritedDep);
}
// This will work whether the stack node has been added yet or not
this.graph.addDependency(`${this.idPrefix}${parentStack.id}`, publishId);
}
build(artifacts) {
const parentStacks = stacksFromAssets(artifacts);
for (const artifact of artifacts) {
if (cxapi.CloudFormationStackArtifact.isCloudFormationStackArtifact(artifact)) {
this.addStack(artifact);
}
else if (cxapi.AssetManifestArtifact.isAssetManifestArtifact(artifact)) {
const manifest = cdk_assets_1.AssetManifest.fromFile(artifact.file);
for (const entry of manifest.entries) {
const parentStack = parentStacks.get(artifact);
if (parentStack === undefined) {
throw new Error('Found an asset manifest that is not associated with a stack');
}
this.addAsset(parentStack, artifact, manifest, entry);
}
}
else if (cxapi.NestedCloudAssemblyArtifact.isNestedCloudAssemblyArtifact(artifact)) {
const assembly = new cxapi.CloudAssembly(artifact.fullPath, { topoSort: false });
const nestedGraph = new WorkGraphBuilder(this.prebuildAssets, `${this.idPrefix}${artifact.id}.`).build(assembly.artifacts);
this.graph.absorb(nestedGraph);
}
else {
// Ignore whatever else
}
}
this.graph.removeUnavailableDependencies();
// Remove any potentially introduced cycles between asset publishing and the stacks that depend on them.
this.removeStackPublishCycles();
return this.graph;
}
stackArtifactIds(deps) {
return deps.flatMap((d) => cxapi.CloudFormationStackArtifact.isCloudFormationStackArtifact(d) ? [this.stackArtifactId(d)] : []);
}
stackArtifactId(artifact) {
if (!cxapi.CloudFormationStackArtifact.isCloudFormationStackArtifact(artifact)) {
throw new Error(`Can only call this on CloudFormationStackArtifact, got: ${artifact.constructor.name}`);
}
return `${this.idPrefix}${artifact.id}`;
}
/**
* We may have accidentally introduced cycles in an attempt to make the messages printed to the
* console not interfere with each other too much. Remove them again.
*/
removeStackPublishCycles() {
const publishSteps = this.graph.nodesOfType('asset-publish');
for (const publishStep of publishSteps) {
for (const dep of publishStep.dependencies) {
if (this.graph.reachable(dep, publishStep.id)) {
publishStep.dependencies.delete(dep);
}
}
}
}
}
exports.WorkGraphBuilder = WorkGraphBuilder;
/**
* Default priorities for nodes
*
* Assets builds have higher priority than the other two operations, to make good on our promise that
* '--prebuild-assets' will actually do assets before stacks (if it can). Unfortunately it is the
* default :(
*
* But between stack dependencies and publish dependencies, stack dependencies go first
*/
WorkGraphBuilder.PRIORITIES = {
'asset-build': 10,
'asset-publish': 0,
'stack': 5,
};
function stacksFromAssets(artifacts) {
const ret = new Map();
for (const stack of artifacts.filter(cxapi.CloudFormationStackArtifact.isCloudFormationStackArtifact)) {
const assetArtifacts = stack.dependencies.filter(cxapi.AssetManifestArtifact.isAssetManifestArtifact);
for (const art of assetArtifacts) {
ret.set(art, stack);
}
}
return ret;
}
function onlyStacks(artifacts) {
return artifacts.filter(cxapi.CloudFormationStackArtifact.isCloudFormationStackArtifact);
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid29yay1ncmFwaC1idWlsZGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsid29yay1ncmFwaC1idWlsZGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLHlDQUF5QztBQUN6QywyQ0FBMkQ7QUFDM0QsaURBQWdEO0FBQ2hELDZDQUF5QztBQUN6Qyx5REFBK0U7QUFFL0UsTUFBYSxnQkFBZ0I7SUFpQjNCLFlBQTZCLGNBQXVCLEVBQW1CLFdBQVcsRUFBRTtRQUF2RCxtQkFBYyxHQUFkLGNBQWMsQ0FBUztRQUFtQixhQUFRLEdBQVIsUUFBUSxDQUFLO1FBRm5FLFVBQUssR0FBRyxJQUFJLHNCQUFTLEVBQUUsQ0FBQztJQUUrQyxDQUFDO0lBRWpGLFFBQVEsQ0FBQyxRQUEyQztRQUMxRCxJQUFJLENBQUMsS0FBSyxDQUFDLFFBQVEsQ0FBQztZQUNsQixJQUFJLEVBQUUsT0FBTztZQUNiLEVBQUUsRUFBRSxHQUFHLElBQUksQ0FBQyxRQUFRLEdBQUcsUUFBUSxDQUFDLEVBQUUsRUFBRTtZQUNwQyxZQUFZLEVBQUUsSUFBSSxHQUFHLENBQUMsSUFBSSxDQUFDLGdCQUFnQixDQUFDLFVBQVUsQ0FBQyxRQUFRLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQztZQUMvRSxLQUFLLEVBQUUsUUFBUTtZQUNmLGVBQWUsRUFBRSxrQ0FBZSxDQUFDLE9BQU87WUFDeEMsUUFBUSxFQUFFLGdCQUFnQixDQUFDLFVBQVUsQ0FBQyxLQUFLO1NBQzVDLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFRDs7T0FFRztJQUNILG1DQUFtQztJQUMzQixRQUFRLENBQUMsV0FBOEMsRUFBRSxxQkFBa0QsRUFBRSxhQUE0QixFQUFFLEtBQXFCO1FBQ3RLLCtCQUErQjtRQUMvQixNQUFNLE9BQU8sR0FBRyxLQUFLLENBQUMsRUFBRSxDQUFDLE9BQU8sQ0FBQztRQUVqQyxNQUFNLE9BQU8sR0FBRyxTQUFTLE9BQU8sSUFBSSxJQUFBLDZCQUFjLEVBQUMsQ0FBQyxPQUFPLEVB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ZUFBZSxFQUFFLENBQUM7SUFDbEIsT0FBTyxFQUFFLENBQUM7Q0FDWCxBQUp1QixDQUl0QjtBQTZJSixTQUFTLGdCQUFnQixDQUFDLFNBQWdDO0lBQ3hELE1BQU0sR0FBRyxHQUFHLElBQUksR0FBRyxFQUFrRSxDQUFDO0lBQ3RGLEtBQUssTUFBTSxLQUFLLElBQUksU0FBUyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsMkJBQTJCLENBQUMsNkJBQTZCLENBQUMsRUFBRTtRQUNyRyxNQUFNLGNBQWMsR0FBRyxLQUFLLENBQUMsWUFBWSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMscUJBQXFCLENBQUMsdUJBQXVCLENBQUMsQ0FBQztRQUN0RyxLQUFLLE1BQU0sR0FBRyxJQUFJLGNBQWMsRUFBRTtZQUNoQyxHQUFHLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRSxLQUFLLENBQUMsQ0FBQztTQUNyQjtLQUNGO0lBRUQsT0FBTyxHQUFHLENBQUM7QUFDYixDQUFDO0FBRUQsU0FBUyxVQUFVLENBQUMsU0FBZ0M7SUFDbEQsT0FBTyxTQUFTLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQywyQkFBMkIsQ0FBQyw2QkFBNkIsQ0FBQyxDQUFDO0FBQzNGLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyBjeGFwaSBmcm9tICdAYXdzLWNkay9jeC1hcGknO1xuaW1wb3J0IHsgQXNzZXRNYW5pZmVzdCwgSU1hbmlmZXN0RW50cnkgfSBmcm9tICdjZGstYXNzZXRzJztcbmltcG9ydCB7IGNvbnRlbnRIYXNoQW55IH0gZnJvbSAnLi9jb250ZW50LWhhc2gnO1xuaW1wb3J0IHsgV29ya0dyYXBoIH0gZnJvbSAnLi93b3JrLWdyYXBoJztcbmltcG9ydCB7IERlcGxveW1lbnRTdGF0ZSwgQXNzZXRCdWlsZE5vZGUsIFdvcmtOb2RlIH0gZnJvbSAnLi93b3JrLWdyYXBoLXR5cGVzJztcblxuZXhwb3J0IGNsYXNzIFdvcmtHcmFwaEJ1aWxkZXIge1xuICAvKipcbiAgICogRGVmYXVsdCBwcmlvcml0aWVzIGZvciBub2Rlc1xuICAgKlxuICAgKiBBc3NldHMgYnVpbGRzIGhhdmUgaGlnaGVyIHByaW9yaXR5IHRoYW4gdGhlIG90aGVyIHR3byBvcGVyYXRpb25zLCB0byBtYWtlIGdvb2Qgb24gb3VyIHByb21pc2UgdGhhdFxuICAgKiAnLS1wcmVidWlsZC1hc3NldHMnIHdpbGwgYWN0dWFsbHkgZG8gYXNzZXRzIGJlZm9yZSBzdGFja3MgKGlmIGl0IGNhbikuIFVuZm9ydHVuYXRlbHkgaXQgaXMgdGhlXG4gICAqIGRlZmF1bHQgOihcbiAgICpcbiAgICogQnV0IGJldHdlZW4gc3RhY2sgZGVwZW5kZW5jaWVzIGFuZCBwdWJsaXNoIGRlcGVuZGVuY2llcywgc3RhY2sgZGVwZW5kZW5jaWVzIGdvIGZpcnN0XG4gICAqL1xuICBwdWJsaWMgc3RhdGljIFBSSU9SSVRJRVM6IFJlY29yZDxXb3JrTm9kZVsndHlwZSddLCBudW1iZXI+ID0ge1xuICAgICdhc3NldC1idWlsZCc6IDEwLFxuICAgICdhc3NldC1wdWJsaXNoJzogMCxcbiAgICAnc3RhY2snOiA1LFxuICB9O1xuICBwcml2YXRlIHJlYWRvbmx5IGdyYXBoID0gbmV3IFdvcmtHcmFwaCgpO1xuXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgcmVhZG9ubHkgcHJlYnVpbGRBc3NldHM6IGJvb2xlYW4sIHByaXZhdGUgcmVhZG9ubHkgaWRQcmVmaXggPSAnJykgeyB9XG5cbiAgcHJpdmF0ZSBhZGRTdGFjayhhcnRpZmFjdDogY3hhcGkuQ2xvdWRGb3JtYXRpb25TdGFja0FydGlmYWN0KSB7XG4gICAgdGhpcy5ncmFwaC5hZGROb2Rlcyh7XG4gICAgICB0eXBlOiAnc3RhY2snLFxuICAgICAgaWQ6IGAke3RoaXMuaWRQcmVmaXh9JHthcnRpZmFjdC5pZH1gLFxuICAgICAgZGVwZW5kZW5jaWVzOiBuZXcgU2V0KHRoaXMuc3RhY2tBcnRpZmFjdElkcyhvbmx5U3RhY2tzKGFydGlmYWN0LmRlcGVuZGVuY2llcykpKSxcbiAgICAgIHN0YWNrOiBhcnRpZmFjdCxcbiAgICAgIGRlcGxveW1lbnRTdGF0ZTogRGVwbG95bWVudFN0YXRlLlBFTkRJTkcsXG4gICAgICBwcmlvcml0eTogV29ya0dyYXBoQnVpbGRlci5QUklPUklUSUVTLnN0YWNrLFxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIE9vZiwgc2VlIHRoaXMgcGFyYW1ldGVyIGxpc3RcbiAgICovXG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBtYXgtbGVuXG4gIHByaXZhdGUgYWRkQXNzZXQocGFyZW50U3RhY2s6IGN4YXBpLkNsb3VkRm9ybWF0aW9uU3RhY2tBcnRpZmFjdCwgYXNzZXRNYW5pZmVzdEFydGlmYWN0OiBjeGFwaS5Bc3NldE1hbmlmZXN0QXJ0aWZhY3QsIGFzc2V0TWFuaWZlc3Q6IEFzc2V0TWFuaWZlc3QsIGFzc2V0OiBJTWFuaWZlc3RFbnRyeSkge1xuICAgIC8vIEp1c3QgdGhlIGFydGlmYWN0IGlkZW50aWZpZXJcbiAgICBjb25zdCBhc3NldElkID0gYXNzZXQuaWQuYXNzZXRJZDtcblxuICAgIGNvbnN0IGJ1aWxkSWQgPSBgYnVpbGQtJHthc3NldElkfS0ke2NvbnRlbnRIYXNoQW55KFthc3NldElkLCBhc3NldC5nZW5lcmljU291cmNlXSkuc3Vic3RyaW5nKDAsIDEwKX1gO1xuICAgIGNvbnN0IHB1Ymxpc2hJZCA9IGBwdWJsaXNoLSR7YXNzZXRJZH0tJHtjb250ZW50SGFzaEFueShbYXNzZXRJZCwgYXNzZXQuZ2VuZXJpY0Rlc3RpbmF0aW9uXSkuc3Vic3RyaW5nKDAsIDEwKX1gO1xuXG4gICAgLy8gQnVpbGQgbm9kZSBvbmx5IGdldHMgYWRkZWQgb25jZSBiZWNhdXNlIHRoZXkgYXJlIGFsbCB0aGUgc2FtZVxuICAgIGlmICghdGhpcy5ncmFwaC50cnlHZXROb2RlKGJ1aWxkSWQpKSB7XG4gICAgICBjb25zdCBub2RlOiBBc3NldEJ1aWxkTm9kZSA9IHtcbiAgICAgICAgdHlwZTogJ2Fzc2V0LWJ1aWxkJyxcbiAgICAgICAgaWQ6IGJ1aWxkSWQsXG4gICAgICAgIG5vdGU6IGFzc2V0SWQsXG4gICAgICAgIGRlcGVuZGVuY2llczogbmV3IFNldChbXG4gICAgICAgICAgLi4udGhpcy5zdGFja0FydGlmYWN0SWRzKGFzc2V0TWFuaWZlc3RBcnRpZmFjdC5kZXBlbmRlbmNpZXMpLFxuICAgICAgICAgIC8vIElmIHdlIGRpc2FibGUgcHJlYnVpbGQsIHRoZW4gYXNzZXRzIGluaGVyaXQgKHN0YWNrKSBkZXBlbmRlbmNpZXMgZnJvbSB0aGVpciBwYXJlbnQgc3RhY2tcbiAgICAgICAgICAuLi4hdGhpcy5wcmVidWlsZEFzc2V0cyA/IHRoaXMuc3RhY2tBcnRpZmFjdElkcyhvbmx5U3RhY2tzKHBhcmVudFN0YWNrLmRlcGVuZGVuY2llcykpIDogW10sXG4gICAgICAgIF0pLFxuICAgICAgICBwYXJlbnRTdGFjazogcGFyZW50U3RhY2ssXG4gICAgICAgIGFzc2V0TWFuaWZlc3RBcnRpZmFjdCxcbiAgICAgICAgYXNzZXRNYW5pZmVzdCxcbiAgICAgICAgYXNzZXQsXG4gICAgICAgIGRlcGxveW1lbnRTdGF0ZTogRGVwbG95bWVudFN0YXRlLlBFTkRJTkcsXG4gICAgICAgIHByaW9yaXR5OiBXb3JrR3JhcGhCdWlsZGVyLlBSSU9SSVRJRVNbJ2Fzc2V0LWJ1aWxkJ10sXG4gICAgICB9O1xuICAgICAgdGhpcy5ncmFwaC5hZGROb2Rlcyhub2RlKTtcbiAgICB9XG5cbiAgICBjb25zdCBwdWJsaXNoTm9kZSA9IHRoaXMuZ3JhcGgudHJ5R2V0Tm9kZShwdWJsaXNoSWQpO1xuICAgIGlmICghcHVibGlzaE5vZGUpIHtcbiAgICAgIHRoaXMuZ3JhcGguYWRkTm9kZXMoe1xuICAgICAgICB0eXBlOiAnYXNzZXQtcHVibGlzaCcsXG4gICAgICAgIGlkOiBwdWJsaXNoSWQsXG4gICAgICAgIG5vdGU6IGAke2Fzc2V0LmlkfWAsXG4gICAgICAgIGRlcGVuZGVuY2llczogbmV3IFNldChbXG4gICAgICAgICAgYnVpbGRJZCxcbiAgICAgICAgXSksXG4gICAgICAgIHBhcmVudFN0YWNrLFxuICAgICAgICBhc3NldE1hbmlmZXN0QXJ0aWZhY3QsXG4gICAgICAgIGFzc2V0TWFuaWZlc3QsXG4gICAgICAgIGFzc2V0LFxuICAgICAgICBkZXBsb3ltZW50U3RhdGU6IERlcGxveW1lbnRTdGF0ZS5QRU5ESU5HLFxuICAgICAgICBwcmlvcml0eTogV29ya0dyYXBoQnVpbGRlci5QUklPUklUSUVTWydhc3NldC1wdWJsaXNoJ10sXG4gICAgICB9KTtcbiAgICB9XG5cbiAgICBmb3IgKGNvbnN0IGluaGVyaXRlZERlcCBvZiB0aGlzLnN0YWNrQXJ0aWZhY3RJZHMob25seVN0YWNrcyhwYXJlbnRTdGFjay5kZXBlbmRlbmNpZXMpKSkge1xuICAgICAgLy8gVGhlIGFzc2V0IHB1Ymxpc2ggc3RlcCBhbHNvIGRlcGVuZHMgb24gdGhlIHN0YWNrcyB0aGF0IHRoZSBwYXJlbnQgZGVwZW5kcyBvbi5cbiAgICAgIC8vIFRoaXMgaXMgcHVyZWx5IGNvc21ldGljOiBpZiB3ZSBkb24ndCBkbyB0aGlzLCB0aGUgcHJvZ3Jlc3MgcHJpbnRpbmcgb2YgYXNzZXQgcHVibGlzaGluZ1xuICAgICAgLy8gaXMgZ29pbmcgdG8gaW50ZXJmZXJlIHdpdGggdGhlIHByb2dyZXNzIGJhciBvZiB0aGUgc3RhY2sgZGVwbG95bWVudC4gV2UgY291bGQgcmVtb3ZlIHRoaXNcbiAgICAgIC8vIGZvciBvdmVyYWxsIGZhc3RlciBkZXBsb3ltZW50cyBpZiB3ZSBldmVyIGhhdmUgYSBiZXR0ZXIgbWV0aG9kIG9mIHByb2dyZXNzIGRpc3BsYXlpbmcuXG4gICAgICAvLyBOb3RlOiB0aGlzIG1heSBpbnRyb2R1Y2UgYSBjeWNsZSBpZiBvbmUgb2YgdGhlIHBhcmVudCdzIGRlcGVuZGVuY2llcyBpcyBhbm90aGVyIHN0YWNrIHRoYXRcbiAgICAgIC8vIGRlcGVuZHMgb24gdGhpcyBhc3NldC4gVG8gd29ya2Fyb3VuZCB0aGlzIHdlIHJlbW92ZSB0aGVzZSBjeWNsZXMgb25jZSBhbGwgbm9kZXMgaGF2ZVxuICAgICAgLy8gYmVlbiBhZGRlZCB0byB0aGUgZ3JhcGguXG4gICAgICB0aGlzLmdyYXBoLmFkZERlcGVuZGVuY3kocHVibGlzaElkLCBpbmhlcml0ZWREZXApO1xuICAgIH1cblxuICAgIC8vIFRoaXMgd2lsbCB3b3JrIHdoZXRoZXIgdGhlIHN0YWNrIG5vZGUgaGFzIGJlZW4gYWRkZWQgeWV0IG9yIG5vdFxuICAgIHRoaXMuZ3JhcGguYWRkRGVwZW5kZW5jeShgJHt0aGlzLmlkUHJlZml4fSR7cGFyZW50U3RhY2suaWR9YCwgcHVibGlzaElkKTtcbiAgfVxuXG4gIHB1YmxpYyBidWlsZChhcnRpZmFjdHM6IGN4YXBpLkNsb3VkQXJ0aWZhY3RbXSk6IFdvcmtHcmFwaCB7XG4gICAgY29uc3QgcGFyZW50U3RhY2tzID0gc3RhY2tzRnJvbUFzc2V0cyhhcnRpZmFjdHMpO1xuXG4gICAgZm9yIChjb25zdCBhcnRpZmFjdCBvZiBhcnRpZmFjdHMpIHtcbiAgICAgIGlmIChjeGFwaS5DbG91ZEZvcm1hdGlvblN0YWNrQXJ0aWZhY3QuaXNDbG91ZEZvcm1hdGlvblN0YWNrQXJ0aWZhY3QoYXJ0aWZhY3QpKSB7XG4gICAgICAgIHRoaXMuYWRkU3RhY2soYXJ0aWZhY3QpO1xuICAgICAgfSBlbHNlIGlmIChjeGFwaS5Bc3NldE1hbmlmZXN0QXJ0aWZhY3QuaXNBc3NldE1hbmlmZXN0QXJ0aWZhY3QoYXJ0aWZhY3QpKSB7XG4gICAgICAgIGNvbnN0IG1hbmlmZXN0ID0gQXNzZXRNYW5pZmVzdC5mcm9tRmlsZShhcnRpZmFjdC5maWxlKTtcblxuICAgICAgICBmb3IgKGNvbnN0IGVudHJ5IG9mIG1hbmlmZXN0LmVudHJpZXMpIHtcbiAgICAgICAgICBjb25zdCBwYXJlbnRTdGFjayA9IHBhcmVudFN0YWNrcy5nZXQoYXJ0aWZhY3QpO1xuICAgICAgICAgIGlmIChwYXJlbnRTdGFjayA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ZvdW5kIGFuIGFzc2V0IG1hbmlmZXN0IHRoYXQgaXMgbm90IGFzc29jaWF0ZWQgd2l0aCBhIHN0YWNrJyk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHRoaXMuYWRkQXNzZXQocGFyZW50U3RhY2ssIGFydGlmYWN0LCBtYW5pZmVzdCwgZW50cnkpO1xuICAgICAgICB9XG4gICAgICB9IGVsc2UgaWYgKGN4YXBpLk5lc3RlZENsb3VkQXNzZW1ibHlBcnRpZmFjdC5pc05lc3RlZENsb3VkQXNzZW1ibHlBcnRpZmFjdChhcnRpZmFjdCkpIHtcbiAgICAgICAgY29uc3QgYXNzZW1ibHkgPSBuZXcgY3hhcGkuQ2xvdWRBc3NlbWJseShhcnRpZmFjdC5mdWxsUGF0aCwgeyB0b3BvU29ydDogZmFsc2UgfSk7XG4gICAgICAgIGNvbnN0IG5lc3RlZEdyYXBoID0gbmV3IFdvcmtHcmFwaEJ1aWxkZXIodGhpcy5wcmVidWlsZEFzc2V0cywgYCR7dGhpcy5pZFByZWZpeH0ke2FydGlmYWN0LmlkfS5gKS5idWlsZChhc3NlbWJseS5hcnRpZmFjdHMpO1xuICAgICAgICB0aGlzLmdyYXBoLmFic29yYihuZXN0ZWRHcmFwaCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvLyBJZ25vcmUgd2hhdGV2ZXIgZWxzZVxuICAgICAgfVxuICAgIH1cblxuICAgIHRoaXMuZ3JhcGgucmVtb3ZlVW5hdmFpbGFibGVEZXBlbmRlbmNpZXMoKTtcblxuICAgIC8vIFJlbW92ZSBhbnkgcG90ZW50aWFsbHkgaW50cm9kdWNlZCBjeWNsZXMgYmV0d2VlbiBhc3NldCBwdWJsaXNoaW5nIGFuZCB0aGUgc3RhY2tzIHRoYXQgZGVwZW5kIG9uIHRoZW0uXG4gICAgdGhpcy5yZW1vdmVTdGFja1B1Ymxpc2hDeWNsZXMoKTtcblxuICAgIHJldHVybiB0aGlzLmdyYXBoO1xuICB9XG5cbiAgcHJpdmF0ZSBzdGFja0FydGlmYWN0SWRzKGRlcHM6IGN4YXBpLkNsb3VkQXJ0aWZhY3RbXSk6IHN0cmluZ1tdIHtcbiAgICByZXR1cm4gZGVwcy5mbGF0TWFwKChkKSA9PiBjeGFwaS5DbG91ZEZvcm1hdGlvblN0YWNrQXJ0aWZhY3QuaXNDbG91ZEZvcm1hdGlvblN0YWNrQXJ0aWZhY3QoZCkgPyBbdGhpcy5zdGFja0FydGlmYWN0SWQoZCldIDogW10pO1xuICB9XG5cbiAgcHJpdmF0ZSBzdGFja0FydGlmYWN0SWQoYXJ0aWZhY3Q6IGN4YXBpLkNsb3VkQXJ0aWZhY3QpOiBzdHJpbmcge1xuICAgIGlmICghY3hhcGkuQ2xvdWRGb3JtYXRpb25TdGFja0FydGlmYWN0LmlzQ2xvdWRGb3JtYXRpb25TdGFja0FydGlmYWN0KGFydGlmYWN0KSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBDYW4gb25seSBjYWxsIHRoaXMgb24gQ2xvdWRGb3JtYXRpb25TdGFja0FydGlmYWN0LCBnb3Q6ICR7YXJ0aWZhY3QuY29uc3RydWN0b3IubmFtZX1gKTtcbiAgICB9XG4gICAgcmV0dXJuIGAke3RoaXMuaWRQcmVmaXh9JHthcnRpZmFjdC5pZH1gO1xuICB9XG5cbiAgLyoqXG4gICAqIFdlIG1heSBoYXZlIGFjY2lkZW50YWxseSBpbnRyb2R1Y2VkIGN5Y2xlcyBpbiBhbiBhdHRlbXB0IHRvIG1ha2UgdGhlIG1lc3NhZ2VzIHByaW50ZWQgdG8gdGhlXG4gICAqIGNvbnNvbGUgbm90IGludGVyZmVyZSB3aXRoIGVhY2ggb3RoZXIgdG9vIG11Y2guIFJlbW92ZSB0aGVtIGFnYWluLlxuICAgKi9cbiAgcHJpdmF0ZSByZW1vdmVTdGFja1B1Ymxpc2hDeWNsZXMoKSB7XG4gICAgY29uc3QgcHVibGlzaFN0ZXBzID0gdGhpcy5ncmFwaC5ub2Rlc09mVHlwZSgnYXNzZXQtcHVibGlzaCcpO1xuICAgIGZvciAoY29uc3QgcHVibGlzaFN0ZXAgb2YgcHVibGlzaFN0ZXBzKSB7XG4gICAgICBmb3IgKGNvbnN0IGRlcCBvZiBwdWJsaXNoU3RlcC5kZXBlbmRlbmNpZXMpIHtcbiAgICAgICAgaWYgKHRoaXMuZ3JhcGgucmVhY2hhYmxlKGRlcCwgcHVibGlzaFN0ZXAuaWQpKSB7XG4gICAgICAgICAgcHVibGlzaFN0ZXAuZGVwZW5kZW5jaWVzLmRlbGV0ZShkZXApO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG59XG5cbmZ1bmN0aW9uIHN0YWNrc0Zyb21Bc3NldHMoYXJ0aWZhY3RzOiBjeGFwaS5DbG91ZEFydGlmYWN0W10pIHtcbiAgY29uc3QgcmV0ID0gbmV3IE1hcDxjeGFwaS5Bc3NldE1hbmlmZXN0QXJ0aWZhY3QsIGN4YXBpLkNsb3VkRm9ybWF0aW9uU3RhY2tBcnRpZmFjdD4oKTtcbiAgZm9yIChjb25zdCBzdGFjayBvZiBhcnRpZmFjdHMuZmlsdGVyKGN4YXBpLkNsb3VkRm9ybWF0aW9uU3RhY2tBcnRpZmFjdC5pc0Nsb3VkRm9ybWF0aW9uU3RhY2tBcnRpZmFjdCkpIHtcbiAgICBjb25zdCBhc3NldEFydGlmYWN0cyA9IHN0YWNrLmRlcGVuZGVuY2llcy5maWx0ZXIoY3hhcGkuQXNzZXRNYW5pZmVzdEFydGlmYWN0LmlzQXNzZXRNYW5pZmVzdEFydGlmYWN0KTtcbiAgICBmb3IgKGNvbnN0IGFydCBvZiBhc3NldEFydGlmYWN0cykge1xuICAgICAgcmV0LnNldChhcnQsIHN0YWNrKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gcmV0O1xufVxuXG5mdW5jdGlvbiBvbmx5U3RhY2tzKGFydGlmYWN0czogY3hhcGkuQ2xvdWRBcnRpZmFjdFtdKSB7XG4gIHJldHVybiBhcnRpZmFjdHMuZmlsdGVyKGN4YXBpLkNsb3VkRm9ybWF0aW9uU3RhY2tBcnRpZmFjdC5pc0Nsb3VkRm9ybWF0aW9uU3RhY2tBcnRpZmFjdCk7XG59XG4iXX0=