UNPKG

aws-ddk-core

Version:

The AWS DataOps Development Kit is an open source development framework for customers that build data workflows and modern data architecture on AWS.

285 lines 39.3 kB
"use strict"; var _a; Object.defineProperty(exports, "__esModule", { value: true }); exports.Configurator = exports.getStackSynthesizer = exports.getEnvironment = exports.getConfig = void 0; const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti"); const fs_1 = require("fs"); const cdk = require("aws-cdk-lib"); const yaml_1 = require("yaml"); const ddkBootstrapConfigKey = "bootstrap"; const bootstrapPrefix = "ddk"; const bootstrapQualifier = "hnb659fds"; const defaultAccountId = process.env.CDK_DEFAULT_ACCOUNT; const defaultRegion = process.env.CDK_DEFAULT_REGION; function readJson(path) { try { const rawdata = fs_1.readFileSync(path, "utf-8"); return JSON.parse(rawdata); } catch (err) { return { environments: {} }; } } function readYaml(path) { try { const rawdata = fs_1.readFileSync(path, "utf-8"); return yaml_1.parse(rawdata); } catch (err) { return { environments: {} }; } } function readConfigFile(path) { if (path.includes(".json")) { return readJson(path); } else if (path.includes(".yaml") || path.includes(".yml")) { return readYaml(path); } else { throw TypeError("Config file must be in YAML or JSON format"); } } function setRemovalPolicy(value, node) { if (value.toLowerCase() == "destroy") { node.applyRemovalPolicy(cdk.RemovalPolicy.DESTROY); } else if (value.toLowerCase() == "retain") { node.applyRemovalPolicy(cdk.RemovalPolicy.RETAIN); } else if (value.toLowerCase() == "snapshot") { node.applyRemovalPolicy(cdk.RemovalPolicy.SNAPSHOT); } else { throw new Error(`${value} is not a valid removal policy type. Must be one of ['DESTROY', 'RETAIN', & 'SNAPSHOT']`); } } function getConfig(props) { if (props.config) { if (typeof props.config == "string") { return readConfigFile(props.config); } else { return props.config; } } else { const path = "./ddk.json"; if (fs_1.existsSync(path)) { return readConfigFile(path); } return null; } } exports.getConfig = getConfig; function getEnvironment(config, environmentId) { const configData = getConfig({ config: config }); if (!configData) { throw TypeError("Config not defined."); } if (configData?.environments && environmentId) { return { account: configData.environments[environmentId].account, region: configData.environments[environmentId].region, }; } return { account: configData.account, region: configData.region, }; } exports.getEnvironment = getEnvironment; function getStackSynthesizer(props) { const configData = getConfig({ config: props.config }); let accountId; let region; try { accountId = configData && props.environmentId ? configData.environments[props.environmentId].account : defaultAccountId; region = configData && props.environmentId ? configData.environments[props.environmentId].region : defaultRegion; } catch (err) { throw TypeError("Invalid JSON/YAML supplied as Config"); } const bootstrapConfig = configData ? configData.ddkBootstrapConfigKey ? configData.ddkBootstrapConfigKey : props.environmentId in configData.environments && ddkBootstrapConfigKey in configData.environments[props.environmentId] ? configData.environments[props.environmentId][ddkBootstrapConfigKey] : undefined : undefined; if (bootstrapConfig) { const qualifier = bootstrapConfig.qualifier ? bootstrapConfig.qualifier : bootstrapQualifier; const prefix = bootstrapConfig.prefix ? bootstrapConfig.prefix : bootstrapPrefix; return new cdk.DefaultStackSynthesizer({ qualifier: qualifier, fileAssetsBucketName: bootstrapConfig.file_assets_bucket_name ? bootstrapConfig.file_assets_bucket_name : `${prefix}-${props.environmentId}-${qualifier}-assets-${accountId}-${region}`, bootstrapStackVersionSsmParameter: bootstrapConfig.stack_version_ssm_parameter ? bootstrapConfig.stack_version_ssm_parameter : `/${prefix}/${props.environmentId}/${qualifier}/bootstrap-version`, deployRoleArn: bootstrapConfig.deploy_role ? bootstrapConfig.deploy_role : `arn:aws:iam::${accountId}:role/${prefix}-${props.environmentId}-${qualifier}-deploy-${accountId}-${region}`, fileAssetPublishingRoleArn: bootstrapConfig.file_publish_role ? bootstrapConfig.file_publish_role : `arn:aws:iam::${accountId}:role/${prefix}-${props.environmentId}-${qualifier}-file-publish-${accountId}-${region}`, cloudFormationExecutionRole: bootstrapConfig.cfn_execution_role ? bootstrapConfig.cfn_execution_role : `arn:aws:iam::${accountId}:role/${prefix}-${props.environmentId}-${qualifier}-cfn-exec-${accountId}-${region}`, lookupRoleArn: bootstrapConfig.lookup_role ? bootstrapConfig.lookup_role : `arn:aws:iam::${accountId}:role/${prefix}-${props.environmentId}-${qualifier}-lookup-${accountId}-${region}`, }); } else { return new cdk.DefaultStackSynthesizer(); } } exports.getStackSynthesizer = getStackSynthesizer; class ConfiguratorAspect { constructor(props) { this.resourceType = props.resourceType; this.propertyName = props.propertyName; this.propertyValue = props.propertyValue; this.resourceId = props.resourceId; } visit(node) { if (this.resourceType && cdk.CfnResource.isCfnResource(node) && node.cfnResourceType == this.resourceType) { if (this.propertyName == "RemovalPolicy") { setRemovalPolicy(this.propertyValue, node); } else { node.addPropertyOverride(this.propertyName, this.propertyValue); } } const nodePathItemRegex = new RegExp(`^(.*\/)?(${this.resourceId}\/Resource)(\/.*)?$`); if (this.resourceId && cdk.CfnResource.isCfnResource(node) && nodePathItemRegex.test(node.node.path)) { if (this.propertyName == "RemovalPolicy") { setRemovalPolicy(this.propertyValue, node); } else { node.addPropertyOverride(this.propertyName, this.propertyValue); } } } } class Configurator { constructor(scope, config, environmentId) { this.config = getConfig({ config: config }) ?? { environments: {} }; this.environmentId = environmentId; if (environmentId && this.config.environments) { // Tags const tags = { ...this.config.tags, ...(this.config.environments[environmentId]?.tags ?? {}), }; this.tagConstruct(scope, tags); // Environment Based const environment = this.config.environments[environmentId]; for (const attribute in environment) { if (attribute == "resources") { for (const resourceIdentifier in environment.resources) { const regexp = new RegExp("^AWS::.*::.*$"); var resourceIdentifierArgument; if (regexp.test(resourceIdentifier)) { resourceIdentifierArgument = { resourceType: resourceIdentifier, }; } else { resourceIdentifierArgument = { resourceId: resourceIdentifier, }; } for (const property in environment.resources[resourceIdentifier]) { cdk.Aspects.of(scope).add(new ConfiguratorAspect({ propertyName: property, propertyValue: environment.resources[resourceIdentifier][property], ...resourceIdentifierArgument, })); } } } } } } static getEnvConfig(props) { const config = getConfig({ config: props.configPath }); if (!config || !config.environments) { throw TypeError("Config not defined."); } return config.environments[props.environmentId]; } static getTags(props) { const configPath = props.configPath ?? "./ddk.json"; const config = getConfig({ config: configPath }); if (!config || !config.environments) { throw TypeError("Config not defined."); } if (props.environmentId && config.environments) { return config.environments[props.environmentId].tags ?? {}; } if (config.tags) { return config.tags; } return {}; } static getEnvironment(props) { const configPath = props.configPath ?? "./ddk.json"; const config = getConfig({ config: configPath }); if (!config) { throw TypeError("Config not defined."); } if (config.environments && props.environmentId) { return { account: config.environments[props.environmentId].account, region: config.environments[props.environmentId].region, }; } return { account: config.account, region: config.region, }; } static getConfig(props) { if (props.config) { if (typeof props.config == "string") { return readConfigFile(props.config); } else { return props.config; } } else { const path = "./ddk.json"; if (fs_1.existsSync(path)) { return readConfigFile(path); } return undefined; } } tagConstruct(scope, tags) { if (tags) { Object.entries(tags).forEach(([key, value]) => cdk.Tags.of(scope).add(key, value)); } } getConfigAttribute(attribute) { if (!this.environmentId) return null; if (!this.config.environments) return null; const stageConfig = this.config.environments[this.environmentId]; if (!stageConfig) return null; if (!(attribute in stageConfig)) return null; return stageConfig[attribute]; } } exports.Configurator = Configurator; _a = JSII_RTTI_SYMBOL_1; Configurator[_a] = { fqn: "aws-ddk-core.Configurator", version: "1.4.1" }; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29uZmlndXJhdG9yLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2NvbmZpZy9jb25maWd1cmF0b3IudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFBQSwyQkFBOEM7QUFDOUMsbUNBQW1DO0FBRW5DLCtCQUE2QjtBQUU3QixNQUFNLHFCQUFxQixHQUFHLFdBQVcsQ0FBQztBQUMxQyxNQUFNLGVBQWUsR0FBRyxLQUFLLENBQUM7QUFDOUIsTUFBTSxrQkFBa0IsR0FBRyxXQUFXLENBQUM7QUFDdkMsTUFBTSxnQkFBZ0IsR0FBRyxPQUFPLENBQUMsR0FBRyxDQUFDLG1CQUFtQixDQUFDO0FBQ3pELE1BQU0sYUFBYSxHQUFHLE9BQU8sQ0FBQyxHQUFHLENBQUMsa0JBQWtCLENBQUM7QUFxQnJELFNBQVMsUUFBUSxDQUFDLElBQVk7SUFDNUIsSUFBSTtRQUNGLE1BQU0sT0FBTyxHQUFHLGlCQUFZLENBQUMsSUFBSSxFQUFFLE9BQU8sQ0FBQyxDQUFDO1FBQzVDLE9BQU8sSUFBSSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQztLQUM1QjtJQUFDLE9BQU8sR0FBRyxFQUFFO1FBQ1osT0FBTyxFQUFFLFlBQVksRUFBRSxFQUFFLEVBQUUsQ0FBQztLQUM3QjtBQUNILENBQUM7QUFDRCxTQUFTLFFBQVEsQ0FBQyxJQUFZO0lBQzVCLElBQUk7UUFDRixNQUFNLE9BQU8sR0FBRyxpQkFBWSxDQUFDLElBQUksRUFBRSxPQUFPLENBQUMsQ0FBQztRQUM1QyxPQUFPLFlBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQztLQUN2QjtJQUFDLE9BQU8sR0FBRyxFQUFFO1FBQ1osT0FBTyxFQUFFLFlBQVksRUFBRSxFQUFFLEVBQUUsQ0FBQztLQUM3QjtBQUNILENBQUM7QUFDRCxTQUFTLGNBQWMsQ0FBQyxJQUFZO0lBQ2xDLElBQUksSUFBSSxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsRUFBRTtRQUMxQixPQUFPLFFBQVEsQ0FBQyxJQUFJ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O2FBQ3JCO1NBQ0Y7YUFBTTtZQUNMLE1BQU0sSUFBSSxHQUFHLFlBQVksQ0FBQztZQUMxQixJQUFJLGVBQVUsQ0FBQyxJQUFJLENBQUMsRUFBRTtnQkFDcEIsT0FBTyxjQUFjLENBQUMsSUFBSSxDQUFDLENBQUM7YUFDN0I7WUFDRCxPQUFPLFNBQVMsQ0FBQztTQUNsQjtJQUNILENBQUM7SUErQ0QsWUFBWSxDQUFDLEtBQTJCLEVBQUUsSUFBK0I7UUFDdkUsSUFBSSxJQUFJLEVBQUU7WUFDUixNQUFNLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsR0FBRyxFQUFFLEtBQUssQ0FBQyxFQUFFLEVBQUUsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxLQUFLLENBQUMsQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLEtBQUssQ0FBQyxDQUFDLENBQUM7U0FDcEY7SUFDSCxDQUFDO0lBQ0Qsa0JBQWtCLENBQUMsU0FBaUI7UUFDbEMsSUFBSSxDQUFDLElBQUksQ0FBQyxhQUFhO1lBQUUsT0FBTyxJQUFJLENBQUM7UUFDckMsSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsWUFBWTtZQUFFLE9BQU8sSUFBSSxDQUFDO1FBRTNDLE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxhQUFhLENBQTJCLENBQUM7UUFFM0YsSUFBSSxDQUFDLFdBQVc7WUFBRSxPQUFPLElBQUksQ0FBQztRQUM5QixJQUFJLENBQUMsQ0FBQyxTQUFTLElBQUksV0FBVyxDQUFDO1lBQUUsT0FBTyxJQUFJLENBQUM7UUFFN0MsT0FBTyxXQUFXLENBQUMsU0FBUyxDQUFDLENBQUM7SUFDaEMsQ0FBQzs7QUEvSEgsb0NBZ0lDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgcmVhZEZpbGVTeW5jLCBleGlzdHNTeW5jIH0gZnJvbSBcImZzXCI7XG5pbXBvcnQgKiBhcyBjZGsgZnJvbSBcImF3cy1jZGstbGliXCI7XG5pbXBvcnQgKiBhcyBjb25zdHJ1Y3RzIGZyb20gXCJjb25zdHJ1Y3RzXCI7XG5pbXBvcnQgeyBwYXJzZSB9IGZyb20gXCJ5YW1sXCI7XG5cbmNvbnN0IGRka0Jvb3RzdHJhcENvbmZpZ0tleSA9IFwiYm9vdHN0cmFwXCI7XG5jb25zdCBib290c3RyYXBQcmVmaXggPSBcImRka1wiO1xuY29uc3QgYm9vdHN0cmFwUXVhbGlmaWVyID0gXCJobmI2NTlmZHNcIjtcbmNvbnN0IGRlZmF1bHRBY2NvdW50SWQgPSBwcm9jZXNzLmVudi5DREtfREVGQVVMVF9BQ0NPVU5UO1xuY29uc3QgZGVmYXVsdFJlZ2lvbiA9IHByb2Nlc3MuZW52LkNES19ERUZBVUxUX1JFR0lPTjtcblxuZXhwb3J0IGludGVyZmFjZSBFbnZpcm9ubWVudENvbmZpZ3VyYXRpb24ge1xuICByZWFkb25seSBhY2NvdW50Pzogc3RyaW5nO1xuICByZWFkb25seSByZWdpb24/OiBzdHJpbmc7XG4gIHJlYWRvbmx5IHJlc291cmNlcz86IHsgW2tleTogc3RyaW5nXTogYW55IH07XG4gIHJlYWRvbmx5IHRhZ3M/OiB7IFtrZXk6IHN0cmluZ106IHN0cmluZyB9O1xuICByZWFkb25seSBib290c3RyYXA/OiB7IFtrZXk6IHN0cmluZ106IHN0cmluZyB9O1xuICByZWFkb25seSBwcm9wcz86IHsgW2tleTogc3RyaW5nXTogYW55IH07XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgQ29uZmlndXJhdGlvbiB7XG4gIHJlYWRvbmx5IGVudmlyb25tZW50czogeyBbaWQ6IHN0cmluZ106IEVudmlyb25tZW50Q29uZmlndXJhdGlvbiB9O1xuICByZWFkb25seSBhY2NvdW50Pzogc3RyaW5nO1xuICByZWFkb25seSByZWdpb24/OiBzdHJpbmc7XG4gIHJlYWRvbmx5IHRhZ3M/OiB7IFtrZXk6IHN0cmluZ106IHN0cmluZyB9O1xuICByZWFkb25seSBib290c3RyYXA/OiB7IFtrZXk6IHN0cmluZ106IHN0cmluZyB9O1xuICByZWFkb25seSBkZGtCb290c3RyYXBDb25maWdLZXk/OiBzdHJpbmc7XG4gIHJlYWRvbmx5IHByb3BzPzogeyBba2V5OiBzdHJpbmddOiBhbnkgfTtcbn1cblxuZnVuY3Rpb24gcmVhZEpzb24ocGF0aDogc3RyaW5nKTogQ29uZmlndXJhdGlvbiB7XG4gIHRyeSB7XG4gICAgY29uc3QgcmF3ZGF0YSA9IHJlYWRGaWxlU3luYyhwYXRoLCBcInV0Zi04XCIpO1xuICAgIHJldHVybiBKU09OLnBhcnNlKHJhd2RhdGEpO1xuICB9IGNhdGNoIChlcnIpIHtcbiAgICByZXR1cm4geyBlbnZpcm9ubWVudHM6IHt9IH07XG4gIH1cbn1cbmZ1bmN0aW9uIHJlYWRZYW1sKHBhdGg6IHN0cmluZyk6IENvbmZpZ3VyYXRpb24ge1xuICB0cnkge1xuICAgIGNvbnN0IHJhd2RhdGEgPSByZWFkRmlsZVN5bmMocGF0aCwgXCJ1dGYtOFwiKTtcbiAgICByZXR1cm4gcGFyc2UocmF3ZGF0YSk7XG4gIH0gY2F0Y2ggKGVycikge1xuICAgIHJldHVybiB7IGVudmlyb25tZW50czoge30gfTtcbiAgfVxufVxuZnVuY3Rpb24gcmVhZENvbmZpZ0ZpbGUocGF0aDogc3RyaW5nKTogQ29uZmlndXJhdGlvbiB7XG4gIGlmIChwYXRoLmluY2x1ZGVzKFwiLmpzb25cIikpIHtcbiAgICByZXR1cm4gcmVhZEpzb24ocGF0aCk7XG4gIH0gZWxzZSBpZiAocGF0aC5pbmNsdWRlcyhcIi55YW1sXCIpIHx8IHBhdGguaW5jbHVkZXMoXCIueW1sXCIpKSB7XG4gICAgcmV0dXJuIHJlYWRZYW1sKHBhdGgpO1xuICB9IGVsc2Uge1xuICAgIHRocm93IFR5cGVFcnJvcihcIkNvbmZpZyBmaWxlIG11c3QgYmUgaW4gWUFNTCBvciBKU09OIGZvcm1hdFwiKTtcbiAgfVxufVxuZnVuY3Rpb24gc2V0UmVtb3ZhbFBvbGljeSh2YWx1ZTogc3RyaW5nLCBub2RlOiBjZGsuQ2ZuUmVzb3VyY2UpOiB2b2lkIHtcbiAgaWYgKHZhbHVlLnRvTG93ZXJDYXNlKCkgPT0gXCJkZXN0cm95XCIpIHtcbiAgICBub2RlLmFwcGx5UmVtb3ZhbFBvbGljeShjZGsuUmVtb3ZhbFBvbGljeS5ERVNUUk9ZKTtcbiAgfSBlbHNlIGlmICh2YWx1ZS50b0xvd2VyQ2FzZSgpID09IFwicmV0YWluXCIpIHtcbiAgICBub2RlLmFwcGx5UmVtb3ZhbFBvbGljeShjZGsuUmVtb3ZhbFBvbGljeS5SRVRBSU4pO1xuICB9IGVsc2UgaWYgKHZhbHVlLnRvTG93ZXJDYXNlKCkgPT0gXCJzbmFwc2hvdFwiKSB7XG4gICAgbm9kZS5hcHBseVJlbW92YWxQb2xpY3koY2RrLlJlbW92YWxQb2xpY3kuU05BUFNIT1QpO1xuICB9IGVsc2Uge1xuICAgIHRocm93IG5ldyBFcnJvcihgJHt2YWx1ZX0gaXMgbm90IGEgdmFsaWQgcmVtb3ZhbCBwb2xpY3kgdHlwZS4gTXVzdCBiZSBvbmUgb2YgWydERVNUUk9ZJywgJ1JFVEFJTicsICYgJ1NOQVBTSE9UJ11gKTtcbiAgfVxufVxuZXhwb3J0IGludGVyZmFjZSBHZXRDb25maWdQcm9wcyB7XG4gIHJlYWRvbmx5IGNvbmZpZz86IHN0cmluZyB8IENvbmZpZ3VyYXRpb247XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRDb25maWcocHJvcHM6IEdldENvbmZpZ1Byb3BzKTogQ29uZmlndXJhdGlvbiB8IG51bGwge1xuICBpZiAocHJvcHMuY29uZmlnKSB7XG4gICAgaWYgKHR5cGVvZiBwcm9wcy5jb25maWcgPT0gXCJzdHJpbmdcIikge1xuICAgICAgcmV0dXJuIHJlYWRDb25maWdGaWxlKHByb3BzLmNvbmZpZyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBwcm9wcy5jb25maWc7XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIGNvbnN0IHBhdGggPSBcIi4vZGRrLmpzb25cIjtcbiAgICBpZiAoZXhpc3RzU3luYyhwYXRoKSkge1xuICAgICAgcmV0dXJuIHJlYWRDb25maWdGaWxlKHBhdGgpO1xuICAgIH1cbiAgICByZXR1cm4gbnVsbDtcbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0RW52aXJvbm1lbnQoY29uZmlnOiBDb25maWd1cmF0aW9uIHwgc3RyaW5nLCBlbnZpcm9ubWVudElkPzogc3RyaW5nKTogY2RrLkVudmlyb25tZW50IHtcbiAgY29uc3QgY29uZmlnRGF0YSA9IGdldENvbmZpZyh7IGNvbmZpZzogY29uZmlnIH0pO1xuXG4gIGlmICghY29uZmlnRGF0YSkge1xuICAgIHRocm93IFR5cGVFcnJvcihcIkNvbmZpZyBub3QgZGVmaW5lZC5cIik7XG4gIH1cblxuICBpZiAoY29uZmlnRGF0YT8uZW52aXJvbm1lbnRzICYmIGVudmlyb25tZW50SWQpIHtcbiAgICByZXR1cm4ge1xuICAgICAgYWNjb3VudDogY29uZmlnRGF0YS5lbnZpcm9ubWVudHNbZW52aXJvbm1lbnRJZF0uYWNjb3VudCxcbiAgICAgIHJlZ2lvbjogY29uZmlnRGF0YS5lbnZpcm9ubWVudHNbZW52aXJvbm1lbnRJZF0ucmVnaW9uLFxuICAgIH07XG4gIH1cblxuICByZXR1cm4ge1xuICAgIGFjY291bnQ6IGNvbmZpZ0RhdGEuYWNjb3VudCxcbiAgICByZWdpb246IGNvbmZpZ0RhdGEucmVnaW9uLFxuICB9O1xufVxuXG5pbnRlcmZhY2UgZ2V0U3RhY2tTeW50aGVzaXplclByb3BzIHtcbiAgcmVhZG9ubHkgY29uZmlnPzogc3RyaW5nIHwgQ29uZmlndXJhdGlvbjtcbiAgcmVhZG9ubHkgZW52aXJvbm1lbnRJZDogc3RyaW5nO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0U3RhY2tTeW50aGVzaXplcihwcm9wczogZ2V0U3RhY2tTeW50aGVzaXplclByb3BzKTogY2RrLklTdGFja1N5bnRoZXNpemVyIHtcbiAgY29uc3QgY29uZmlnRGF0YSA9IGdldENvbmZpZyh7IGNvbmZpZzogcHJvcHMuY29uZmlnIH0pO1xuXG4gIGxldCBhY2NvdW50SWQ7XG4gIGxldCByZWdpb247XG4gIHRyeSB7XG4gICAgYWNjb3VudElkID1cbiAgICAgIGNvbmZpZ0RhdGEgJiYgcHJvcHMuZW52aXJvbm1lbnRJZCA/IGNvbmZpZ0RhdGEuZW52aXJvbm1lbnRzW3Byb3BzLmVudmlyb25tZW50SWRdLmFjY291bnQgOiBkZWZhdWx0QWNjb3VudElkO1xuICAgIHJlZ2lvbiA9IGNvbmZpZ0RhdGEgJiYgcHJvcHMuZW52aXJvbm1lbnRJZCA/IGNvbmZpZ0RhdGEuZW52aXJvbm1lbnRzW3Byb3BzLmVudmlyb25tZW50SWRdLnJlZ2lvbiA6IGRlZmF1bHRSZWdpb247XG4gIH0gY2F0Y2ggKGVycikge1xuICAgIHRocm93IFR5cGVFcnJvcihcIkludmFsaWQgSlNPTi9ZQU1MIHN1cHBsaWVkIGFzIENvbmZpZ1wiKTtcbiAgfVxuICBjb25zdCBib290c3RyYXBDb25maWc6IGFueSA9IGNvbmZpZ0RhdGFcbiAgICA/IGNvbmZpZ0RhdGEuZGRrQm9vdHN0cmFwQ29uZmlnS2V5XG4gICAgICA/IGNvbmZpZ0RhdGEuZGRrQm9vdHN0cmFwQ29uZmlnS2V5XG4gICAgICA6IHByb3BzLmVudmlyb25tZW50SWQgaW4gY29uZmlnRGF0YS5lbnZpcm9ubWVudHMgJiZcbiAgICAgICAgZGRrQm9vdHN0cmFwQ29uZmlnS2V5IGluIGNvbmZpZ0RhdGEuZW52aXJvbm1lbnRzW3Byb3BzLmVudmlyb25tZW50SWRdXG4gICAgICA/IGNvbmZpZ0RhdGEuZW52aXJvbm1lbnRzW3Byb3BzLmVudmlyb25tZW50SWRdW2Rka0Jvb3RzdHJhcENvbmZpZ0tleV1cbiAgICAgIDogdW5kZWZpbmVkXG4gICAgOiB1bmRlZmluZWQ7XG4gIGlmIChib290c3RyYXBDb25maWcpIHtcbiAgICBjb25zdCBxdWFsaWZpZXIgPSBib290c3RyYXBDb25maWcucXVhbGlmaWVyID8gYm9vdHN0cmFwQ29uZmlnLnF1YWxpZmllciA6IGJvb3RzdHJhcFF1YWxpZmllcjtcbiAgICBjb25zdCBwcmVmaXggPSBib290c3RyYXBDb25maWcucHJlZml4ID8gYm9vdHN0cmFwQ29uZmlnLnByZWZpeCA6IGJvb3RzdHJhcFByZWZpeDtcbiAgICByZXR1cm4gbmV3IGNkay5EZWZhdWx0U3RhY2tTeW50aGVzaXplcih7XG4gICAgICBxdWFsaWZpZXI6IHF1YWxpZmllcixcbiAgICAgIGZpbGVBc3NldHNCdWNrZXROYW1lOiBib290c3RyYXBDb25maWcuZmlsZV9hc3NldHNfYnVja2V0X25hbWVcbiAgICAgICAgPyBib290c3RyYXBDb25maWcuZmlsZV9hc3NldHNfYnVja2V0X25hbWVcbiAgICAgICAgOiBgJHtwcmVmaXh9LSR7cHJvcHMuZW52aXJvbm1lbnRJZH0tJHtxdWFsaWZpZXJ9LWFzc2V0cy0ke2FjY291bnRJZH0tJHtyZWdpb259YCxcbiAgICAgIGJvb3RzdHJhcFN0YWNrVmVyc2lvblNzbVBhcmFtZXRlcjogYm9vdHN0cmFwQ29uZmlnLnN0YWNrX3ZlcnNpb25fc3NtX3BhcmFtZXRlclxuICAgICAgICA/IGJvb3RzdHJhcENvbmZpZy5zdGFja192ZXJzaW9uX3NzbV9wYXJhbWV0ZXJcbiAgICAgICAgOiBgLyR7cHJlZml4fS8ke3Byb3BzLmVudmlyb25tZW50SWR9LyR7cXVhbGlmaWVyfS9ib290c3RyYXAtdmVyc2lvbmAsXG4gICAgICBkZXBsb3lSb2xlQXJuOiBib290c3RyYXBDb25maWcuZGVwbG95X3JvbGVcbiAgICAgICAgPyBib290c3RyYXBDb25maWcuZGVwbG95X3JvbGVcbiAgICAgICAgOiBgYXJuOmF3czppYW06OiR7YWNjb3VudElkfTpyb2xlLyR7cHJlZml4fS0ke3Byb3BzLmVudmlyb25tZW50SWR9LSR7cXVhbGlmaWVyfS1kZXBsb3ktJHthY2NvdW50SWR9LSR7cmVnaW9ufWAsXG4gICAgICBmaWxlQXNzZXRQdWJsaXNoaW5nUm9sZUFybjogYm9vdHN0cmFwQ29uZmlnLmZpbGVfcHVibGlzaF9yb2xlXG4gICAgICAgID8gYm9vdHN0cmFwQ29uZmlnLmZpbGVfcHVibGlzaF9yb2xlXG4gICAgICAgIDogYGFybjphd3M6aWFtOjoke2FjY291bnRJZH06cm9sZS8ke3ByZWZpeH0tJHtwcm9wcy5lbnZpcm9ubWVudElkfS0ke3F1YWxpZmllcn0tZmlsZS1wdWJsaXNoLSR7YWNjb3VudElkfS0ke3JlZ2lvbn1gLFxuICAgICAgY2xvdWRGb3JtYXRpb25FeGVjdXRpb25Sb2xlOiBib290c3RyYXBDb25maWcuY2ZuX2V4ZWN1dGlvbl9yb2xlXG4gICAgICAgID8gYm9vdHN0cmFwQ29uZmlnLmNmbl9leGVjdXRpb25fcm9sZVxuICAgICAgICA6IGBhcm46YXdzOmlhbTo6JHthY2NvdW50SWR9OnJvbGUvJHtwcmVmaXh9LSR7cHJvcHMuZW52aXJvbm1lbnRJZH0tJHtxdWFsaWZpZXJ9LWNmbi1leGVjLSR7YWNjb3VudElkfS0ke3JlZ2lvbn1gLFxuICAgICAgbG9va3VwUm9sZUFybjogYm9vdHN0cmFwQ29uZmlnLmxvb2t1cF9yb2xlXG4gICAgICAgID8gYm9vdHN0cmFwQ29uZmlnLmxvb2t1cF9yb2xlXG4gICAgICAgIDogYGFybjphd3M6aWFtOjoke2FjY291bnRJZH06cm9sZS8ke3ByZWZpeH0tJHtwcm9wcy5lbnZpcm9ubWVudElkfS0ke3F1YWxpZmllcn0tbG9va3VwLSR7YWNjb3VudElkfS0ke3JlZ2lvbn1gLFxuICAgIH0pO1xuICB9IGVsc2Uge1xuICAgIHJldHVybiBuZXcgY2RrLkRlZmF1bHRTdGFja1N5bnRoZXNpemVyKCk7XG4gIH1cbn1cblxuaW50ZXJmYWNlIENvbmZpZ3VyYXRvckFzcGVjdFByb3BzIHtcbiAgcmVhZG9ubHkgcHJvcGVydHlOYW1lOiBzdHJpbmc7XG4gIHJlYWRvbmx5IHByb3BlcnR5VmFsdWU6IGFueTtcbiAgcmVhZG9ubHkgcmVzb3VyY2VUeXBlPzogc3RyaW5nO1xuICByZWFkb25seSByZXNvdXJjZUlkPzogc3RyaW5nO1xufVxuXG5jbGFzcyBDb25maWd1cmF0b3JBc3BlY3QgaW1wbGVtZW50cyBjZGsuSUFzcGVjdCB7XG4gIHByaXZhdGUgcmVhZG9ubHkgcHJvcGVydHlOYW1lOiBzdHJpbmc7XG4gIHByaXZhdGUgcmVhZG9ubHkgcHJvcGVydHlWYWx1ZTogYW55O1xuICBwcml2YXRlIHJlYWRvbmx5IHJlc291cmNlVHlwZTogYW55O1xuICBwcml2YXRlIHJlYWRvbmx5IHJlc291cmNlSWQ6IGFueTtcblxuICBjb25zdHJ1Y3Rvcihwcm9wczogQ29uZmlndXJhdG9yQXNwZWN0UHJvcHMpIHtcbiAgICB0aGlzLnJlc291cmNlVHlwZSA9IHByb3BzLnJlc291cmNlVHlwZTtcbiAgICB0aGlzLnByb3BlcnR5TmFtZSA9IHByb3BzLnByb3BlcnR5TmFtZTtcbiAgICB0aGlzLnByb3BlcnR5VmFsdWUgPSBwcm9wcy5wcm9wZXJ0eVZhbHVlO1xuICAgIHRoaXMucmVzb3VyY2VJZCA9IHByb3BzLnJlc291cmNlSWQ7XG4gIH1cbiAgcHVibGljIHZpc2l0KG5vZGU6IGNvbnN0cnVjdHMuSUNvbnN0cnVjdCk6IHZvaWQge1xuICAgIGlmICh0aGlzLnJlc291cmNlVHlwZSAmJiBjZGsuQ2ZuUmVzb3VyY2UuaXNDZm5SZXNvdXJjZShub2RlKSAmJiBub2RlLmNmblJlc291cmNlVHlwZSA9PSB0aGlzLnJlc291cmNlVHlwZSkge1xuICAgICAgaWYgKHRoaXMucHJvcGVydHlOYW1lID09IFwiUmVtb3ZhbFBvbGljeVwiKSB7XG4gICAgICAgIHNldFJlbW92YWxQb2xpY3kodGhpcy5wcm9wZXJ0eVZhbHVlLCBub2RlKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIG5vZGUuYWRkUHJvcGVydHlPdmVycmlkZSh0aGlzLnByb3BlcnR5TmFtZSwgdGhpcy5wcm9wZXJ0eVZhbHVlKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBjb25zdCBub2RlUGF0aEl0ZW1SZWdleCA9IG5ldyBSZWdFeHAoYF4oLipcXC8pPygke3RoaXMucmVzb3VyY2VJZH1cXC9SZXNvdXJjZSkoXFwvLiopPyRgKTtcbiAgICBpZiAodGhpcy5yZXNvdXJjZUlkICYmIGNkay5DZm5SZXNvdXJjZS5pc0NmblJlc291cmNlKG5vZGUpICYmIG5vZGVQYXRoSXRlbVJlZ2V4LnRlc3Qobm9kZS5ub2RlLnBhdGgpKSB7XG4gICAgICBpZiAodGhpcy5wcm9wZXJ0eU5hbWUgPT0gXCJSZW1vdmFsUG9saWN5XCIpIHtcbiAgICAgICAgc2V0UmVtb3ZhbFBvbGljeSh0aGlzLnByb3BlcnR5VmFsdWUsIG5vZGUpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbm9kZS5hZGRQcm9wZXJ0eU92ZXJyaWRlKHRoaXMucHJvcGVydHlOYW1lLCB0aGlzLnByb3BlcnR5VmFsdWUpO1xuICAgICAgfVxuICAgIH1cbiAgfVxufVxuXG5leHBvcnQgaW50ZXJmYWNlIEdldEVudkNvbmZpZ1Byb3BzIHtcbiAgLyoqXG4gICAqIFJlbGF0aXZlIHBhdGggdG8gY29uZmlnIGZpbGUuIERlZmF1bHRzIHRvICcuL2Rkay5qc29uJ1xuICAgKi9cbiAgcmVhZG9ubHkgY29uZmlnUGF0aD86IHN0cmluZztcbiAgLyoqXG4gICAqIEVudmlyb25tZW50IGlkZW50aWZpZXJcbiAgICovXG4gIHJlYWRvbmx5IGVudmlyb25tZW50SWQ6IHN0cmluZztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBHZXRUYWdzUHJvcHMge1xuICAvKipcbiAgICogUmVsYXRpdmUgcGF0aCB0byBjb25maWcgZmlsZS4gRGVmYXVsdHMgdG8gJy4vZGRrLmpzb24nXG4gICAqL1xuICByZWFkb25seSBjb25maWdQYXRoPzogc3RyaW5nO1xuICAvKipcbiAgICogRW52aXJvbm1lbnQgaWRlbnRpZmllclxuICAgKi9cbiAgcmVhZG9ubHkgZW52aXJvbm1lbnRJZD86IHN0cmluZztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBHZXRFbnZpcm9ubWVudFByb3BzIHtcbiAgLyoqXG4gICAqIFJlbGF0aXZlIHBhdGggdG8gY29uZmlnIGZpbGUuIERlZmF1bHRzIHRvICcuL2Rkay5qc29uJ1xuICAgKi9cbiAgcmVhZG9ubHkgY29uZmlnUGF0aD86IHN0cmluZztcbiAgLyoqXG4gICAqIEVudmlyb25tZW50IGlkZW50aWZpZXIuXG4gICAqL1xuICByZWFkb25seSBlbnZpcm9ubWVudElkPzogc3RyaW5nO1xufVxuXG5leHBvcnQgY2xhc3MgQ29uZmlndXJhdG9yIHtcbiAgcHVibGljIHN0YXRpYyBnZXRFbnZDb25maWcocHJvcHM6IEdldEVudkNvbmZpZ1Byb3BzKTogRW52aXJvbm1lbnRDb25maWd1cmF0aW9uIHtcbiAgICBjb25zdCBjb25maWcgPSBnZXRDb25maWcoeyBjb25maWc6IHByb3BzLmNvbmZpZ1BhdGggfSk7XG5cbiAgICBpZiAoIWNvbmZpZyB8fCAhY29uZmlnLmVudmlyb25tZW50cykge1xuICAgICAgdGhyb3cgVHlwZUVycm9yKFwiQ29uZmlnIG5vdCBkZWZpbmVkLlwiKTtcbiAgICB9XG5cbiAgICByZXR1cm4gY29uZmlnLmVudmlyb25tZW50c1twcm9wcy5lbnZpcm9ubWVudElkXTtcbiAgfVxuXG4gIHB1YmxpYyBzdGF0aWMgZ2V0VGFncyhwcm9wczogR2V0VGFnc1Byb3BzKTogeyBba2V5OiBzdHJpbmddOiBzdHJpbmcgfSB7XG4gICAgY29uc3QgY29uZmlnUGF0aCA9IHByb3BzLmNvbmZpZ1BhdGggPz8gXCIuL2Rkay5qc29uXCI7XG4gICAgY29uc3QgY29uZmlnID0gZ2V0Q29uZmlnKHsgY29uZmlnOiBjb25maWdQYXRoIH0pO1xuXG4gICAgaWYgKCFjb25maWcgfHwgIWNvbmZpZy5lbnZpcm9ubWVudHMpIHtcbiAgICAgIHRocm93IFR5cGVFcnJvcihcIkNvbmZpZyBub3QgZGVmaW5lZC5cIik7XG4gICAgfVxuXG4gICAgaWYgKHByb3BzLmVudmlyb25tZW50SWQgJiYgY29uZmlnLmVudmlyb25tZW50cykge1xuICAgICAgcmV0dXJuIGNvbmZpZy5lbnZpcm9ubWVudHNbcHJvcHMuZW52aXJvbm1lbnRJZF0udGFncyA/PyB7fTtcbiAgICB9XG5cbiAgICBpZiAoY29uZmlnLnRhZ3MpIHtcbiAgICAgIHJldHVybiBjb25maWcudGFncztcbiAgICB9XG5cbiAgICByZXR1cm4ge307XG4gIH1cblxuICBwdWJsaWMgc3RhdGljIGdldEVudmlyb25tZW50KHByb3BzOiBHZXRFbnZpcm9ubWVudFByb3BzKTogY2RrLkVudmlyb25tZW50IHtcbiAgICBjb25zdCBjb25maWdQYXRoID0gcHJvcHMuY29uZmlnUGF0aCA/PyBcIi4vZGRrLmpzb25cIjtcbiAgICBjb25zdCBjb25maWcgPSBnZXRDb25maWcoeyBjb25maWc6IGNvbmZpZ1BhdGggfSk7XG5cbiAgICBpZiAoIWNvbmZpZykge1xuICAgICAgdGhyb3cgVHlwZUVycm9yKFwiQ29uZmlnIG5vdCBkZWZpbmVkLlwiKTtcbiAgICB9XG5cbiAgICBpZiAoY29uZmlnLmVudmlyb25tZW50cyAmJiBwcm9wcy5lbnZpcm9ubWVudElkKSB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBhY2NvdW50OiBjb25maWcuZW52aXJvbm1lbnRzW3Byb3BzLmVudmlyb25tZW50SWRdLmFjY291bnQsXG4gICAgICAgIHJlZ2lvbjogY29uZmlnLmVudmlyb25tZW50c1twcm9wcy5lbnZpcm9ubWVudElkXS5yZWdpb24sXG4gICAgICB9O1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBhY2NvdW50OiBjb25maWcuYWNjb3VudCxcbiAgICAgIHJlZ2lvbjogY29uZmlnLnJlZ2lvbixcbiAgICB9O1xuICB9XG5cbiAgcHVibGljIHN0YXRpYyBnZXRDb25maWcocHJvcHM6IEdldENvbmZpZ1Byb3BzKTogQ29uZmlndXJhdGlvbiB8IHVuZGVmaW5lZCB7XG4gICAgaWYgKHByb3BzLmNvbmZpZykge1xuICAgICAgaWYgKHR5cGVvZiBwcm9wcy5jb25maWcgPT0gXCJzdHJpbmdcIikge1xuICAgICAgICByZXR1cm4gcmVhZENvbmZpZ0ZpbGUocHJvcHMuY29uZmlnKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBwcm9wcy5jb25maWc7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnN0IHBhdGggPSBcIi4vZGRrLmpzb25cIjtcbiAgICAgIGlmIChleGlzdHNTeW5jKHBhdGgpKSB7XG4gICAgICAgIHJldHVybiByZWFkQ29uZmlnRmlsZShwYXRoKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuICB9XG5cbiAgcHVibGljIHJlYWRvbmx5IGNvbmZpZzogQ29uZmlndXJhdGlvbjtcbiAgcHVibGljIHJlYWRvbmx5IGVudmlyb25tZW50SWQ/OiBzdHJpbmc7XG5cbiAgY29uc3RydWN0b3Ioc2NvcGU6IGNvbnN0cnVjdHMuQ29uc3RydWN0LCBjb25maWc6IHN0cmluZyB8IENvbmZpZ3VyYXRpb24sIGVudmlyb25tZW50SWQ/OiBzdHJpbmcpIHtcbiAgICB0aGlzLmNvbmZpZyA9IGdldENvbmZpZyh7IGNvbmZpZzogY29uZmlnIH0pID8/IHsgZW52aXJvbm1lbnRzOiB7fSB9O1xuICAgIHRoaXMuZW52aXJvbm1lbnRJZCA9IGVudmlyb25tZW50SWQ7XG5cbiAgICBpZiAoZW52aXJvbm1lbnRJZCAmJiB0aGlzLmNvbmZpZy5lbnZpcm9ubWVudHMpIHtcbiAgICAgIC8vIFRhZ3NcbiAgICAgIGNvbnN0IHRhZ3MgPSB7XG4gICAgICAgIC4uLnRoaXMuY29uZmlnLnRhZ3MsXG4gICAgICAgIC4uLih0aGlzLmNvbmZpZy5lbnZpcm9ubWVudHNbZW52aXJvbm1lbnRJZF0/LnRhZ3MgPz8ge30pLFxuICAgICAgfTtcbiAgICAgIHRoaXMudGFnQ29uc3RydWN0KHNjb3BlLCB0YWdzKTtcblxuICAgICAgLy8gRW52aXJvbm1lbnQgQmFzZWRcbiAgICAgIGNvbnN0IGVudmlyb25tZW50ID0gdGhpcy5jb25maWcuZW52aXJvbm1lbnRzW2Vudmlyb25tZW50SWRdO1xuICAgICAgZm9yIChjb25zdCBhdHRyaWJ1dGUgaW4gZW52aXJvbm1lbnQpIHtcbiAgICAgICAgaWYgKGF0dHJpYnV0ZSA9PSBcInJlc291cmNlc1wiKSB7XG4gICAgICAgICAgZm9yIChjb25zdCByZXNvdXJjZUlkZW50aWZpZXIgaW4gZW52aXJvbm1lbnQucmVzb3VyY2VzKSB7XG4gICAgICAgICAgICBjb25zdCByZWdleHAgPSBuZXcgUmVnRXhwKFwiXkFXUzo6Lio6Oi4qJFwiKTtcbiAgICAgICAgICAgIHZhciByZXNvdXJjZUlkZW50aWZpZXJBcmd1bWVudDtcbiAgICAgICAgICAgIGlmIChyZWdleHAudGVzdChyZXNvdXJjZUlkZW50aWZpZXIpKSB7XG4gICAgICAgICAgICAgIHJlc291cmNlSWRlbnRpZmllckFyZ3VtZW50ID0ge1xuICAgICAgICAgICAgICAgIHJlc291cmNlVHlwZTogcmVzb3VyY2VJZGVudGlmaWVyLFxuICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgcmVzb3VyY2VJZGVudGlmaWVyQXJndW1lbnQgPSB7XG4gICAgICAgICAgICAgICAgcmVzb3VyY2VJZDogcmVzb3VyY2VJZGVudGlmaWVyLFxuICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZm9yIChjb25zdCBwcm9wZXJ0eSBpbiBlbnZpcm9ubWVudC5yZXNvdXJjZXNbcmVzb3VyY2VJZGVudGlmaWVyXSkge1xuICAgICAgICAgICAgICBjZGsuQXNwZWN0cy5vZihzY29wZSkuYWRkKFxuICAgICAgICAgICAgICAgIG5ldyBDb25maWd1cmF0b3JBc3BlY3Qoe1xuICAgICAgICAgICAgICAgICAgcHJvcGVydHlOYW1lOiBwcm9wZXJ0eSxcbiAgICAgICAgICAgICAgICAgIHByb3BlcnR5VmFsdWU6IGVudmlyb25tZW50LnJlc291cmNlc1tyZXNvdXJjZUlkZW50aWZpZXJdW3Byb3BlcnR5XSxcbiAgICAgICAgICAgICAgICAgIC4uLnJlc291cmNlSWRlbnRpZmllckFyZ3VtZW50LFxuICAgICAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxuICB0YWdDb25zdHJ1Y3Qoc2NvcGU6IGNvbnN0cnVjdHMuQ29uc3RydWN0LCB0YWdzOiB7IFtrZXk6IHN0cmluZ106IHN0cmluZyB9KTogdm9pZCB7XG4gICAgaWYgKHRhZ3MpIHtcbiAgICAgIE9iamVjdC5lbnRyaWVzKHRhZ3MpLmZvckVhY2goKFtrZXksIHZhbHVlXSkgPT4gY2RrLlRhZ3Mub2Yoc2NvcGUpLmFkZChrZXksIHZhbHVlKSk7XG4gICAgfVxuICB9XG4gIGdldENvbmZpZ0F0dHJpYnV0ZShhdHRyaWJ1dGU6IHN0cmluZyk6IGFueSB7XG4gICAgaWYgKCF0aGlzLmVudmlyb25tZW50SWQpIHJldHVybiBudWxsO1xuICAgIGlmICghdGhpcy5jb25maWcuZW52aXJvbm1lbnRzKSByZXR1cm4gbnVsbDtcblxuICAgIGNvbnN0IHN0YWdlQ29uZmlnID0gdGhpcy5jb25maWcuZW52aXJvbm1lbnRzW3RoaXMuZW52aXJvbm1lbnRJZF0gYXMgeyBba2V5OiBzdHJpbmddOiBhbnkgfTtcblxuICAgIGlmICghc3RhZ2VDb25maWcpIHJldHVybiBudWxsO1xuICAgIGlmICghKGF0dHJpYnV0ZSBpbiBzdGFnZUNvbmZpZykpIHJldHVybiBudWxsO1xuXG4gICAgcmV0dXJuIHN0YWdlQ29uZmlnW2F0dHJpYnV0ZV07XG4gIH1cbn1cbiJdfQ==