projen
Version:
CDK for software projects
465 lines • 71.4 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.UpgradeDependenciesSchedule = exports.UpgradeDependencies = void 0;
const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
const component_1 = require("../component");
const dependencies_1 = require("../dependencies");
const github_1 = require("../github");
const util_1 = require("./util");
const constants_1 = require("../github/constants");
const util_2 = require("../github/private/util");
const workflow_actions_1 = require("../github/workflow-actions");
const workflows_model_1 = require("../github/workflows-model");
const javascript_1 = require("../javascript");
const release_1 = require("../release");
const name_1 = require("../util/name");
const CREATE_PATCH_STEP_ID = "create_patch";
const PATCH_CREATED_OUTPUT = "patch_created";
/**
* Upgrade node project dependencies.
*/
class UpgradeDependencies extends component_1.Component {
static [JSII_RTTI_SYMBOL_1] = { fqn: "projen.javascript.UpgradeDependencies", version: "0.103.12" };
/**
* The workflows that execute the upgrades. One workflow per branch.
*/
workflows = [];
project;
options;
pullRequestTitle;
/**
* Container definitions for the upgrade workflow.
*/
containerOptions;
/**
* The upgrade task.
*/
upgradeTask;
/**
* A task run after the upgrade task.
*/
postUpgradeTask;
gitIdentity;
postBuildSteps;
permissions;
depTypes;
upgradeTarget;
satisfyPeerDependencies;
includeDeprecatedVersions;
constructor(project, options = {}) {
super(project);
this.project = project;
this.options = options;
// Validate cooldown
if (options.cooldown !== undefined &&
(!Number.isInteger(options.cooldown) || options.cooldown < 0)) {
throw new Error("The 'cooldown' option must be a non-negative integer representing days");
}
// Yarn classic doesn't support cooldown
if (options.cooldown && (0, util_1.isYarnClassic)(project.package.packageManager)) {
throw new Error("The 'cooldown' option is not supported with yarn classic. " +
"Consider using npm, pnpm, bun, or yarn berry instead.");
}
this.depTypes = this.options.types ?? [
dependencies_1.DependencyType.BUILD,
dependencies_1.DependencyType.BUNDLED,
dependencies_1.DependencyType.DEVENV,
dependencies_1.DependencyType.PEER,
dependencies_1.DependencyType.RUNTIME,
dependencies_1.DependencyType.TEST,
dependencies_1.DependencyType.OPTIONAL,
];
this.upgradeTarget = this.options.target ?? "minor";
this.satisfyPeerDependencies = this.options.satisfyPeerDependencies ?? true;
this.includeDeprecatedVersions =
this.options.includeDeprecatedVersions ?? false;
this.pullRequestTitle = options.pullRequestTitle ?? "upgrade dependencies";
this.gitIdentity =
options.workflowOptions?.gitIdentity ?? constants_1.DEFAULT_GITHUB_ACTIONS_USER;
this.permissions = {
contents: workflows_model_1.JobPermission.READ,
...options.workflowOptions?.permissions,
};
this.postBuildSteps = [];
this.containerOptions = options.workflowOptions?.container;
this.postUpgradeTask =
project.tasks.tryFind("post-upgrade") ??
project.tasks.addTask("post-upgrade", {
description: "Runs after upgrading dependencies",
});
const taskEnv = { CI: "0" };
// Yarn berry treats any non-empty CI value as truthy and auto-enables
// immutable installs. Explicitly disable it so yarn dlx/up can modify
// the lockfile during upgrades.
if ((0, util_1.isYarnBerry)(project.package.packageManager)) {
taskEnv.YARN_ENABLE_IMMUTABLE_INSTALLS = "false";
}
// Set yarn berry cooldown via environment variable, expects minutes
if (options.cooldown && (0, util_1.isYarnBerry)(project.package.packageManager)) {
taskEnv.YARN_NPM_MINIMAL_AGE_GATE = String(daysToMinutes(options.cooldown));
}
// Set npm cooldown date via environment variable (calculated at runtime), expects a date in ISO format
if (options.cooldown && (0, util_1.isNpm)(project.package.packageManager)) {
taskEnv.NPM_CONFIG_BEFORE = `$(node -p "new Date(Date.now()-${daysToMilliseconds(options.cooldown)}).toISOString()")`;
}
this.upgradeTask = project.addTask(options.taskName ?? "upgrade", {
// this task should not run in CI mode because its designed to
// update package.json and lock files.
env: taskEnv,
description: this.pullRequestTitle,
steps: { toJSON: () => this.renderTaskSteps() },
});
this.upgradeTask.lock(); // this task is a lazy value, so make it readonly
// always use the GitHub of the root project - there can only be one
const github = github_1.GitHub.of(project.root);
if (this.upgradeTask && github && (options.workflow ?? true)) {
if (options.workflowOptions?.branches) {
for (const branch of options.workflowOptions.branches) {
this.workflows.push(this.createWorkflow(this.upgradeTask, github, branch));
}
}
else if (release_1.Release.of(project)) {
const release = release_1.Release.of(project);
release._forEachBranch((branch) => {
this.workflows.push(this.createWorkflow(this.upgradeTask, github, branch));
});
}
else {
// represents the default repository branch.
// just like not specifying anything.
const defaultBranch = undefined;
this.workflows.push(this.createWorkflow(this.upgradeTask, github, defaultBranch));
}
}
}
/**
* Add steps to execute a successful build.
* @param steps workflow steps
*/
addPostBuildSteps(...steps) {
this.postBuildSteps.push(...steps);
}
renderTaskSteps() {
const steps = new Array();
// Package Manager upgrade should always include all deps
const includeForPackageManagerUpgrade = this.buildDependencyList(true);
if (includeForPackageManagerUpgrade.length === 0) {
return [{ execArgs: ["echo", "No dependencies to upgrade."] }];
}
// Removing `npm-check-updates` from our dependency tree because it depends on a package
// that uses an npm-specific feature that causes an invalid dependency tree when using Yarn 1.
// See https://github.com/projen/projen/pull/3136 for more details.
const includeForNcu = this.buildDependencyList(false);
// bump versions in package.json
if (includeForNcu.length) {
const ncuCommand = this.buildNcuCommand(includeForNcu, {
upgrade: true,
target: this.upgradeTarget,
});
steps.push({ execArgs: ncuCommand });
}
// run "yarn/npm install" to update the lockfile and install any deps (such as projen)
steps.push({ exec: this.project.package.installAndUpdateLockfileCommand });
// run upgrade command to upgrade transitive deps as well
steps.push({
execArgs: this.renderUpgradePackagesCommand(includeForPackageManagerUpgrade),
});
// If we have a packages deduplication task, run it now.
if (this.project.package.dedupeTask) {
steps.push({ spawn: this.project.package.dedupeTask.name });
}
// run "projen" to give projen a chance to update dependencies (it will also run "yarn install")
steps.push({ exec: this.project.projenCommand });
steps.push({ spawn: this.postUpgradeTask.name });
return steps;
}
/**
* Build npm-check-updates command with common options.
*/
buildNcuCommand(includePackages, options = {}) {
const command = [
...(0, util_1.executeCommandPriorInstallation)(this.project.package.packageManager),
"npm-check-updates@20",
];
if (options.upgrade) {
command.push("--upgrade");
}
if (options.target) {
command.push(`--target=${options.target}`);
}
if (options.format) {
command.push(`--format=${options.format}`);
}
if (options.removeRange) {
command.push("--removeRange");
}
if (this.options.cooldown) {
command.push(`--cooldown=${this.options.cooldown}`);
}
command.push(`--${this.satisfyPeerDependencies ? "peer" : "no-peer"}`);
command.push(`--${this.includeDeprecatedVersions ? "deprecated" : "no-deprecated"}`);
command.push(`--dep=${this.renderNcuDependencyTypes(this.depTypes)}`);
command.push(`--filter=${includePackages.join(",")}`);
return command;
}
/**
* Render projen dependencies types to a list of ncu compatible types
*/
renderNcuDependencyTypes(types) {
return Array.from(new Set(types
.map((type) => {
switch (type) {
case dependencies_1.DependencyType.PEER:
return "peer";
case dependencies_1.DependencyType.RUNTIME:
return "prod";
case dependencies_1.DependencyType.OPTIONAL:
return "optional";
case dependencies_1.DependencyType.TEST:
case dependencies_1.DependencyType.DEVENV:
case dependencies_1.DependencyType.BUILD:
return "dev";
case dependencies_1.DependencyType.BUNDLED:
return "prod";
default:
return false;
}
})
.filter((type) => Boolean(type)))).join(",");
}
/**
* Render a package manager specific command to upgrade all requested dependencies.
*/
renderUpgradePackagesCommand(include) {
function upgradePackages(command, cooldownFlag) {
return () => {
const parts = [...command, ...include];
if (cooldownFlag) {
parts.push(cooldownFlag);
}
return parts;
};
}
const packageManager = this.project.package.packageManager;
const cooldown = this.options.cooldown;
let lazy = undefined;
switch (packageManager) {
case javascript_1.NodePackageManager.YARN:
case javascript_1.NodePackageManager.YARN_CLASSIC:
lazy = upgradePackages(["yarn", "upgrade"]);
break;
case javascript_1.NodePackageManager.YARN2:
case javascript_1.NodePackageManager.YARN_BERRY:
// Yarn Berry cooldown set via task env
lazy = upgradePackages(["yarn", "up", "-R"]);
break;
case javascript_1.NodePackageManager.NPM:
// npm cooldown set via NPM_CONFIG_BEFORE env
lazy = upgradePackages(["npm", "update"]);
break;
case javascript_1.NodePackageManager.PNPM:
// pnpm expects minutes
lazy = upgradePackages(["pnpm", "update"], cooldown !== undefined
? `--config.minimum-release-age=${daysToMinutes(cooldown)}`
: undefined);
break;
case javascript_1.NodePackageManager.BUN:
// bun expects seconds
lazy = upgradePackages(["bun", "update"], cooldown
? `--minimum-release-age=${daysToSeconds(cooldown)}`
: undefined);
break;
default:
throw new Error(`unexpected package manager ${packageManager}`);
}
// return a lazy function so that dependencies include ones that were
// added post project instantiation (i.e using project.addDeps)
return lazy;
}
buildDependencyList(includeDependenciesWithConstraint) {
return Array.from(new Set(this.options.include ??
this.filterDependencies(includeDependenciesWithConstraint)));
}
filterDependencies(includeConstraint) {
const dependencies = [];
const deps = this.project.deps.all
// remove those that have a constraint version (unless includeConstraint is true)
.filter((d) => includeConstraint ||
this.packageCanBeUpgradedInPackageJson(d.version))
// remove override dependencies
.filter((d) => d.type !== dependencies_1.DependencyType.OVERRIDE);
for (const type of this.depTypes) {
dependencies.push(...deps
.filter((d) => d.type === type)
.filter((d) => !(this.options.exclude ?? []).includes(d.name)));
}
return dependencies.map((d) => d.name);
}
/**
* Projen can alter a package's version in package.json when either the version is omitted, or set to "*".
* Otherwise, the exact version selected is placed in the package.json file and upgrading is handled through the package manager
* rather than npm-check-updates.
*
* @param version semver from DependencyCoordinates.version, may be undefined
* @returns whether the version is the default versioning behavior
*/
packageCanBeUpgradedInPackageJson(version) {
// No version means "latest"
return !version || version === "*";
}
createWorkflow(task, github, branch) {
const schedule = this.options.workflowOptions?.schedule ??
UpgradeDependenciesSchedule.DAILY;
const taskBranchName = `${task.name}${branch ? `-${branch.replace(/\//g, "-")}` : ""}`;
const workflowName = (0, name_1.workflowNameForProject)(taskBranchName, this.project);
const workflow = github.addWorkflow(workflowName);
const triggers = {
workflowDispatch: {},
schedule: schedule.cron.length > 0
? schedule.cron.map((e) => ({ cron: e }))
: undefined,
};
workflow.on(triggers);
const upgrade = this.createUpgrade(task, github, branch);
const pr = this.createPr(workflow, upgrade);
const jobs = {};
jobs[upgrade.jobId] = upgrade.job;
jobs[pr.jobId] = pr.job;
workflow.addJobs(jobs);
return workflow;
}
createUpgrade(task, github, branch) {
const with_ = {
...(branch ? { ref: branch } : {}),
...(github.downloadLfs ? { lfs: true } : {}),
...(github.checkoutSubmodules !== github_1.CheckoutSubmodules.DISABLED
? { submodules: github.checkoutSubmodules }
: {}),
};
const steps = [
github_1.WorkflowSteps.checkout({ with: with_ }),
...this.project.renderWorkflowSetup({ mutable: false }),
{
name: "Upgrade dependencies",
run: this.project.runTaskCommand(task),
workingDirectory: this.project.parent
? (0, util_2.projectPathRelativeToRepoRoot)(this.project)
: undefined,
},
];
steps.push(...this.postBuildSteps);
steps.push(...workflow_actions_1.WorkflowActions.uploadGitPatch({
stepId: CREATE_PATCH_STEP_ID,
outputName: PATCH_CREATED_OUTPUT,
}));
return {
job: {
name: "Upgrade",
container: this.containerOptions,
permissions: this.permissions,
env: this.options.workflowOptions?.env,
...github.runsOnConfig(this.options.workflowOptions),
steps: steps,
outputs: {
[PATCH_CREATED_OUTPUT]: {
stepId: CREATE_PATCH_STEP_ID,
outputName: PATCH_CREATED_OUTPUT,
},
},
},
jobId: "upgrade",
ref: branch,
};
}
createPr(workflow, upgrade) {
const credentials = this.options.workflowOptions?.projenCredentials ??
workflow.projenCredentials;
const semanticCommit = this.options.semanticCommit ?? "chore";
// createPr is only called from createWorkflow, which is only reachable
// once the constructor has already confirmed the root project has GitHub
// enabled - so this is always defined.
const github = github_1.GitHub.of(this.project.root);
return {
job: github_1.WorkflowJobs.pullRequestFromPatch({
patch: {
jobId: upgrade.jobId,
outputName: PATCH_CREATED_OUTPUT,
ref: upgrade.ref,
},
workflowName: workflow.name,
credentials,
...github.runsOnConfig(this.options.workflowOptions),
pullRequestTitle: `${semanticCommit}(deps): ${this.pullRequestTitle}`,
pullRequestDescription: "Upgrades project dependencies.",
gitIdentity: this.gitIdentity,
assignees: this.options.workflowOptions?.assignees,
labels: this.options.workflowOptions?.labels,
signoff: this.options.signoff,
}),
jobId: "pr",
};
}
}
exports.UpgradeDependencies = UpgradeDependencies;
/**
* How often to check for new versions and raise pull requests for version upgrades.
*/
class UpgradeDependenciesSchedule {
cron;
static [JSII_RTTI_SYMBOL_1] = { fqn: "projen.javascript.UpgradeDependenciesSchedule", version: "0.103.12" };
/**
* Disables automatic upgrades.
*/
static NEVER = new UpgradeDependenciesSchedule([]);
/**
* At 00:00.
*/
static DAILY = new UpgradeDependenciesSchedule(["0 0 * * *"]);
/**
* At 00:00 on every day-of-week from Monday through Friday.
*/
static WEEKDAY = new UpgradeDependenciesSchedule([
"0 0 * * 1-5",
]);
/**
* At 00:00 on Monday.
*/
static WEEKLY = new UpgradeDependenciesSchedule([
"0 0 * * 1",
]);
/**
* At 00:00 on day-of-month 1.
*/
static MONTHLY = new UpgradeDependenciesSchedule([
"0 0 1 * *",
]);
/**
* Create a schedule from a raw cron expression.
*/
static expressions(cron) {
return new UpgradeDependenciesSchedule(cron);
}
constructor(cron) {
this.cron = cron;
}
}
exports.UpgradeDependenciesSchedule = UpgradeDependenciesSchedule;
/**
* Convert days to minutes.
*/
function daysToMinutes(days) {
return days * 1440;
}
/**
* Convert days to seconds.
*/
function daysToSeconds(days) {
return days * 86400;
}
/**
* Convert days to milliseconds.
*/
function daysToMilliseconds(days) {
return days * 86400000;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXBncmFkZS1kZXBlbmRlbmNpZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvamF2YXNjcmlwdC91cGdyYWRlLWRlcGVuZGVuY2llcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7O0FBQUEsNENBQXlDO0FBQ3pDLGtEQUFpRDtBQU9qRCxzQ0FLbUI7QUFDbkIsaUNBS2dCO0FBQ2hCLG1EQUFrRTtBQUNsRSxpREFBdUU7QUFDdkUsaUVBQTZEO0FBTTdELCtEQUEwRDtBQUUxRCw4Q0FBbUQ7QUFDbkQsd0NBQXFDO0FBSXJDLHVDQUFzRDtBQUV0RCxNQUFNLG9CQUFvQixHQUFHLGNBQWMsQ0FBQztBQUM1QyxNQUFNLG9CQUFvQixHQUFHLGVBQWUsQ0FBQztBQWdJN0M7O0dBRUc7QUFDSCxNQUFhLG1CQUFvQixTQUFRLHFCQUFTOztJQUNoRDs7T0FFRztJQUNhLFNBQVMsR0FBcUIsRUFBRSxDQUFDO0lBRWpDLE9BQU8sQ0FBYztJQUVwQixPQUFPLENBQTZCO0lBQ3BDLGdCQUFnQixDQUFTO0lBRTFDOztPQUVHO0lBQ0ksZ0JBQWdCLENBQW9CO0lBRTNDOztPQUVHO0lBQ2EsV0FBVyxDQUFPO0lBRWxDOztPQUVHO0lBQ2EsZUFBZSxDQUFPO0lBRXJCLFdBQVcsQ0FBYztJQUN6QixjQUFjLENBQVk7SUFDMUIsV0FBVyxDQUFpQjtJQUM1QixRQUFRLENBQW1CO0lBQzNCLGFBQWEsQ0FBUztJQUN0Qix1QkFBdUIsQ0FBVTtJQUNqQyx5QkFBeUIsQ0FBVTtJQUVwRCxZQUFZLE9BQW9CLEVBQUUsVUFBc0MsRUFBRTtRQUN4RSxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUM7UUFFZixJQUFJLENBQUMsT0FBTyxHQUFHLE9BQU8sQ0FBQztRQUN2QixJQUFJLENBQUMsT0FBTyxHQUFHLE9BQU8sQ0FBQztRQUV2QixvQkFBb0I7UUFDcEIsSUFDRSxPQUFPLENBQUMsUUFBUSxLQUFLLFNBQVM7WUFDOUIsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxT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cEM7O09BRUc7SUFDSSxNQUFNLENBQVUsS0FBSyxHQUFHLElBQUksMkJBQTJCLENBQUMsRUFBRSxDQUFDLENBQUM7SUFFbkU7O09BRUc7SUFDSSxNQUFNLENBQVUsS0FBSyxHQUFHLElBQUksMkJBQTJCLENBQUMsQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDO0lBRTlFOztPQUVHO0lBQ0ksTUFBTSxDQUFVLE9BQU8sR0FBRyxJQUFJLDJCQUEyQixDQUFDO1FBQy9ELGFBQWE7S0FDZCxDQUFDLENBQUM7SUFFSDs7T0FFRztJQUNJLE1BQU0sQ0FBVSxNQUFNLEdBQUcsSUFBSSwyQkFBMkIsQ0FBQztRQUM5RCxXQUFXO0tBQ1osQ0FBQyxDQUFDO0lBRUg7O09BRUc7SUFDSSxNQUFNLENBQVUsT0FBTyxHQUFHLElBQUksMkJBQTJCLENBQUM7UUFDL0QsV0FBVztLQUNaLENBQUMsQ0FBQztJQUVIOztPQUVHO0lBQ0ksTUFBTSxDQUFDLFdBQVcsQ0FBQyxJQUFjO1FBQ3RDLE9BQU8sSUFBSSwyQkFBMkIsQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUMvQyxDQUFDO0lBRUQsWUFBb0MsSUFBYztRQUFkLFNBQUksR0FBSixJQUFJLENBQVU7SUFBRyxDQUFDOztBQXZDeEQsa0VBd0NDO0FBRUQ7O0dBRUc7QUFDSCxTQUFTLGFBQWEsQ0FBQyxJQUFZO0lBQ2pDLE9BQU8sSUFBSSxHQUFHLElBQUksQ0FBQztBQUNyQixDQUFDO0FBRUQ7O0dBRUc7QUFDSCxTQUFTLGFBQWEsQ0FBQyxJQUFZO0lBQ2pDLE9BQU8sSUFBSSxHQUFHLEtBQUssQ0FBQztBQUN0QixDQUFDO0FBRUQ7O0dBRUc7QUFDSCxTQUFTLGtCQUFrQixDQUFDLElBQVk7SUFDdEMsT0FBTyxJQUFJLEdBQUcsUUFBUSxDQUFDO0FBQ3pCLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb21wb25lbnQgfSBmcm9tIFwiLi4vY29tcG9uZW50XCI7XG5pbXBvcnQgeyBEZXBlbmRlbmN5VHlwZSB9IGZyb20gXCIuLi9kZXBlbmRlbmNpZXNcIjtcbmltcG9ydCB0eXBlIHtcbiAgR2l0aHViQ3JlZGVudGlhbHMsXG4gIEdpdGh1YldvcmtmbG93LFxuICBHaXRJZGVudGl0eSxcbiAgd29ya2Zsb3dzLFxufSBmcm9tIFwiLi4vZ2l0aHViXCI7XG5pbXBvcnQge1xuICBDaGVja291dFN1Ym1vZHVsZXMsXG4gIEdpdEh1YixcbiAgV29ya2Zsb3dKb2JzLFxuICBXb3JrZmxvd1N0ZXBzLFxufSBmcm9tIFwiLi4vZ2l0aHViXCI7XG5pbXBvcnQge1xuICBpc1lhcm5DbGFzc2ljLFxuICBpc1lhcm5CZXJyeSxcbiAgaXNOcG0sXG4gIGV4ZWN1dGVDb21tYW5kUHJpb3JJbnN0YWxsYXRpb24sXG59IGZyb20gXCIuL3V0aWxcIjtcbmltcG9ydCB7IERFRkFVTFRfR0lUSFVCX0FDVElPTlNfVVNFUiB9IGZyb20gXCIuLi9naXRodWIvY29uc3RhbnRzXCI7XG5pbXBvcnQgeyBwcm9qZWN0UGF0aFJlbGF0aXZlVG9SZXBvUm9vdCB9IGZyb20gXCIuLi9naXRodWIvcHJpdmF0ZS91dGlsXCI7XG5pbXBvcnQgeyBXb3JrZmxvd0FjdGlvbnMgfSBmcm9tIFwiLi4vZ2l0aHViL3dvcmtmbG93LWFjdGlvbnNcIjtcbmltcG9ydCB0eXBlIHtcbiAgQ29udGFpbmVyT3B0aW9ucyxcbiAgSm9iU3RlcCxcbiAgSm9iUGVybWlzc2lvbnMsXG59IGZyb20gXCIuLi9naXRodWIvd29ya2Zsb3dzLW1vZGVsXCI7XG5pbXBvcnQgeyBKb2JQZXJtaXNzaW9uIH0gZnJvbSBcIi4uL2dpdGh1Yi93b3JrZmxvd3MtbW9kZWxcIjtcbmltcG9ydCB0eXBlIHsgTm9kZVByb2plY3QgfSBmcm9tIFwiLi4vamF2YXNjcmlwdFwiO1xuaW1wb3J0IHsgTm9kZVBhY2thZ2VNYW5hZ2VyIH0gZnJvbSBcIi4uL2phdmFzY3JpcHRcIjtcbmltcG9ydCB7IFJlbGVhc2UgfSBmcm9tIFwiLi4vcmVsZWFzZVwiO1xuaW1wb3J0IHR5cGUgeyBHcm91cFJ1bm5lck9wdGlvbnMgfSBmcm9tIFwiLi4vcnVubmVyLW9wdGlvbnNcIjtcbmltcG9ydCB0eXBlIHsgVGFzayB9IGZyb20gXCIuLi90YXNrXCI7XG5pbXBvcnQgdHlwZSB7IFRhc2tTdGVwIH0gZnJvbSBcIi4uL3Rhc2stbW9kZWxcIjtcbmltcG9ydCB7IHdvcmtmbG93TmFtZUZvclByb2plY3QgfSBmcm9tIFwiLi4vdXRpbC9uYW1lXCI7XG5cbmNvbnN0IENSRUFURV9QQVRDSF9TVEVQX0lEID0gXCJjcmVhdGVfcGF0Y2hcIjtcbmNvbnN0IFBBVENIX0NSRUFURURfT1VUUFVUID0gXCJwYXRjaF9jcmVhdGVkXCI7XG5cbi8qKlxuICogT3B0aW9ucyBmb3IgYFVwZ3JhZGVEZXBlbmRlbmNpZXNgLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFVwZ3JhZGVEZXBlbmRlbmNpZXNPcHRpb25zIHtcbiAgLyoqXG4gICAqIExpc3Qgb2YgcGFja2FnZSBuYW1lcyB0byBleGNsdWRlIGR1cmluZyB0aGUgdXBncmFkZS5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBOb3RoaW5nIGlzIGV4Y2x1ZGVkLlxuICAgKi9cbiAgcmVhZG9ubHkgZXhjbHVkZT86IHN0cmluZ1tdO1xuXG4gIC8qKlxuICAgKiBMaXN0IG9mIHBhY2thZ2UgbmFtZXMgdG8gaW5jbHVkZSBkdXJpbmcgdGhlIHVwZ3JhZGUuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gRXZlcnl0aGluZyBpcyBpbmNsdWRlZC5cbiAgICovXG4gIHJlYWRvbmx5IGluY2x1ZGU/OiBzdHJpbmdbXTtcblxuICAvKipcbiAgICogRGV0ZXJtaW5lcyB0aGUgdGFyZ2V0IHZlcnNpb24gdG8gdXBncmFkZSBkZXBlbmRlbmNpZXMgdG8uXG4gICAqXG4gICAqIEBzZWUgaHR0cHM6Ly9naXRodWIuY29tL3JhaW5lb3JzaGluZS9ucG0tY2hlY2stdXBkYXRlcyN0YXJnZXRcbiAgICpcbiAgICogQGRlZmF1bHQgXCJtaW5vclwiXG4gICAqL1xuICByZWFkb25seSB0YXJnZXQ/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIENoZWNrIHBlZXIgZGVwZW5kZW5jaWVzIG9mIGluc3RhbGxlZCBwYWNrYWdlcyBhbmQgZmlsdGVyIHVwZGF0ZXMgdG8gY29tcGF0aWJsZSB2ZXJzaW9ucy5cbiAgICpcbiAgICogQnkgZGVmYXVsdCwgdGhlIHVwZ3JhZGUgd29ya2Zsb3cgd2lsbCBhZGhlcmUgdG8gdmVyc2lvbiBjb25zdHJhaW50cyBmcm9tIHBlZXIgZGVwZW5kZW5jaWVzLlxuICAgKiBTb21ldGltZXMgdGhpcyBpcyBub3QgZGVzaXJhYmxlIGFuZCBjYW4gYmUgZGlzYWJsZWQuXG4gICAqXG4gICAqIEBzZWUgaHR0cHM6Ly9naXRodWIuY29tL3JhaW5lb3JzaGluZS9ucG0tY2hlY2stdXBkYXRlcyNwZWVyXG4gICAqXG4gICAqIEBkZWZhdWx0IHRydWVcbiAgICovXG4gIHJlYWRvbmx5IHNhdGlzZnlQZWVyRGVwZW5kZW5jaWVzPzogYm9vbGVhbjtcblxuICAvKipcbiAgICogSW5jbHVkZSBkZXByZWNhdGVkIHBhY2thZ2VzLlxuICAgKlxuICAgKiBCeSBkZWZhdWx0LCBkZXByZWNhdGVkIHZlcnNpb25zIHdpbGwgYmUgZXhjbHVkZWQgZnJvbSB1cGdyYWRlcy5cbiAgICpcbiAgICogQHNlZSBodHRwczovL2dpdGh1Yi5jb20vcmFpbmVvcnNoaW5lL25wbS1jaGVjay11cGRhdGVzP3RhYj1yZWFkbWUtb3YtZmlsZSNvcHRpb25zXG4gICAqXG4gICAqIEBkZWZhdWx0IGZhbHNlXG4gICAqL1xuICByZWFkb25seSBpbmNsdWRlRGVwcmVjYXRlZFZlcnNpb25zPzogYm9vbGVhbjtcblxuICAvKipcbiAgICogSW5jbHVkZSBhIGdpdGh1YiB3b3JrZmxvdyBmb3IgY3JlYXRpbmcgUFIncyB0aGF0IHVwZ3JhZGVzIHRoZVxuICAgKiByZXF1aXJlZCBkZXBlbmRlbmNpZXMsIGVpdGhlciBieSBtYW51YWwgZGlzcGF0Y2gsIG9yIGJ5IGEgc2NoZWR1bGUuXG4gICAqXG4gICAqIElmIHRoaXMgaXMgYGZhbHNlYCwgb25seSBhIGxvY2FsIHByb2plbiB0YXNrIGlzIGNyZWF0ZWQsIHdoaWNoIGNhbiBiZSBleGVjdXRlZCBtYW51YWxseSB0b1xuICAgKiB1cGdyYWRlIHRoZSBkZXBlbmRlbmNpZXMuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gdHJ1ZSBmb3Igcm9vdCBwcm9qZWN0cywgZmFsc2UgZm9yIHN1YnByb2plY3RzLlxuICAgKi9cbiAgcmVhZG9ubHkgd29ya2Zsb3c/OiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBPcHRpb25zIGZvciB0aGUgZ2l0aHViIHdvcmtmbG93LiBPbmx5IGFwcGxpZXMgaWYgYHdvcmtmbG93YCBpcyB0cnVlLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIGRlZmF1bHQgb3B0aW9ucy5cbiAgICovXG4gIHJlYWRvbmx5IHdvcmtmbG93T3B0aW9ucz86IFVwZ3JhZGVEZXBlbmRlbmNpZXNXb3JrZmxvd09wdGlvbnM7XG5cbiAgLyoqXG4gICAqIFRoZSBuYW1lIG9mIHRoZSB0YXNrIHRoYXQgd2lsbCBiZSBjcmVhdGVkLlxuICAgKiBUaGlzIHdpbGwgYWxzbyBiZSB0aGUgd29ya2Zsb3cgbmFtZS5cbiAgICpcbiAgICogQGRlZmF1bHQgXCJ1cGdyYWRlXCIuXG4gICAqL1xuICByZWFkb25seSB0YXNrTmFtZT86IHN0cmluZztcblxuICAvKipcbiAgICogVGl0bGUgb2YgdGhlIHB1bGwgcmVxdWVzdCB0byB1c2UgKHNob3VsZCBiZSBhbGwgbG93ZXItY2FzZSkuXG4gICAqXG4gICAqIEBkZWZhdWx0IFwidXBncmFkZSBkZXBlbmRlbmNpZXNcIlxuICAgKi9cbiAgcmVhZG9ubHkgcHVsbFJlcXVlc3RUaXRsZT86IHN0cmluZztcblxuICAvKipcbiAgICogVGhlIHNlbWFudGljIGNvbW1pdCB0eXBlLlxuICAgKlxuICAgKiBAZGVmYXVsdCAnY2hvcmUnXG4gICAqL1xuICByZWFkb25seSBzZW1hbnRpY0NvbW1pdD86IHN0cmluZztcblxuICAvKipcbiAgICogQWRkIFNpZ25lZC1vZmYtYnkgbGluZSBieSB0aGUgY29tbWl0dGVyIGF0IHRoZSBlbmQgb2YgdGhlIGNvbW1pdCBsb2cgbWVzc2FnZS5cbiAgICpcbiAgICogQGRlZmF1bHQgdHJ1ZVxuICAgKi9cbiAgcmVhZG9ubHkgc2lnbm9mZj86IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIFNwZWNpZnkgd2hpY2ggZGVwZW5kZW5jeSB0eXBlcyB0aGUgdXBncmFkZSBzaG91bGQgb3BlcmF0ZSBvbi5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBBbGwgZGVwZW5kZW5jeSB0eXBlcy5cbiAgICovXG4gIHJlYWRvbmx5IHR5cGVzPzogRGVwZW5kZW5jeVR5cGVbXTtcblxuICAvKipcbiAgICogRXhjbHVkZSBwYWNrYWdlIHZlcnNpb25zIHB1Ymxpc2hlZCB3aXRoaW4gdGhlIHNwZWNpZmllZCBudW1iZXIgb2YgZGF5cy5cbiAgICpcbiAgICogVGhpcyBtYXkgcHJvdmlkZSBzb21lIHByb3RlY3Rpb24gYWdhaW5zdCBzdXBwbHkgY2hhaW4gYXR0YWNrcywgc2ltcGx5IGJ5IGF2b2lkaW5nXG4gICAqIG5ld2x5IHB1Ymxpc2hlZCBwYWNrYWdlcyB0aGF0IG1heSBiZSBtYWxpY2lvdXMuIEl0IGdpdmVzIHRoZSBlY29zeXN0ZW0gbW9yZSB0aW1lXG4gICAqIHRvIGRldGVjdCBtYWxpY2lvdXMgcGFja2FnZXMuIEhvd2V2ZXIgaXQgY29tZXMgYXQgdGhlIGNvc3Qgb2YgdXBkYXRpbmcgb3RoZXJcbiAgICogcGFja2FnZXMgc2xvd2VyLCB3aGljaCBtaWdodCBhbHNvIGNvbnRhaW4gdnVsbmVyYWJpbGl0aWVzIG9yIGJ1Z3MgaW4gbmVlZCBvZiBhIGZpeC5cbiAgICpcbiAgICogVGhlIGNvb2xkb3duIHBlcmlvZCBhcHBsaWVzIHRvIGJvdGggbnBtLWNoZWNrLXVwZGF0ZXMgZGlzY292ZXJ5XG4gICAqIGFuZCB0aGUgcGFja2FnZSBtYW5hZ2VyIHVwZGF0ZSBjb21tYW5kLlxuICAgKlxuICAgKiBAc2VlIGh0dHBzOi8vZ2l0aHViLmNvbS9yYWluZW9yc2hpbmUvbnBtLWNoZWNrLXVwZGF0ZXMjY29vbGRvd25cbiAgICogQHNlZSBodHRwczovL2RvY3MubnBtanMuY29tL2NsaS92MTEvY29tbWFuZHMvbnBtLXVwZGF0ZSNiZWZvcmVcbiAgICogQHNlZSBodHRwczovL3BucG0uaW8vc2V0dGluZ3MjbWluaW11bXJlbGVhc2VhZ2VcbiAgICogQHNlZSBodHRwczovL2J1bi5jb20vZG9jcy9wbS9jbGkvaW5zdGFsbCNtaW5pbXVtLXJlbGVhc2UtYWdlXG4gICAqIEBzZWUgaHR0cHM6Ly95YXJucGtnLmNvbS9jb25maWd1cmF0aW9uL3lhcm5yYyNucG1NaW5pbWFsQWdlR2F0ZVxuICAgKlxuICAgKiBAZGVmYXVsdCAtIE5vIGNvb2xkb3duIHBlcmlvZC5cbiAgICovXG4gIHJlYWRvbmx5IGNvb2xkb3duPzogbnVtYmVyO1xufVxuXG4vKipcbiAqIFVwZ3JhZGUgbm9kZSBwcm9qZWN0IGRlcGVuZGVuY2llcy5cbiAqL1xuZXhwb3J0IGNsYXNzIFVwZ3JhZGVEZXBlbmRlbmNpZXMgZXh0ZW5kcyBDb21wb25lbnQge1xuICAvKipcbiAgICogVGhlIHdvcmtmbG93cyB0aGF0IGV4ZWN1dGUgdGhlIHVwZ3JhZGVzLiBPbmUgd29ya2Zsb3cgcGVyIGJyYW5jaC5cbiAgICovXG4gIHB1YmxpYyByZWFkb25seSB3b3JrZmxvd3M6IEdpdGh1YldvcmtmbG93W10gPSBbXTtcblxuICBwdWJsaWMgcmVhZG9ubHkgcHJvamVjdDogTm9kZVByb2plY3Q7XG5cbiAgcHJpdmF0ZSByZWFkb25seSBvcHRpb25zOiBVcGdyYWRlRGVwZW5kZW5jaWVzT3B0aW9ucztcbiAgcHJpdmF0ZSByZWFkb25seSBwdWxsUmVxdWVzdFRpdGxlOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIENvbnRhaW5lciBkZWZpbml0aW9ucyBmb3IgdGhlIHVwZ3JhZGUgd29ya2Zsb3cuXG4gICAqL1xuICBwdWJsaWMgY29udGFpbmVyT3B0aW9ucz86IENvbnRhaW5lck9wdGlvbnM7XG5cbiAgLyoqXG4gICAqIFRoZSB1cGdyYWRlIHRhc2suXG4gICAqL1xuICBwdWJsaWMgcmVhZG9ubHkgdXBncmFkZVRhc2s6IFRhc2s7XG5cbiAgLyoqXG4gICAqIEEgdGFzayBydW4gYWZ0ZXIgdGhlIHVwZ3JhZGUgdGFzay5cbiAgICovXG4gIHB1YmxpYyByZWFkb25seSBwb3N0VXBncmFkZVRhc2s6IFRhc2s7XG5cbiAgcHJpdmF0ZSByZWFkb25seSBnaXRJZGVudGl0eTogR2l0SWRlbnRpdHk7XG4gIHByaXZhdGUgcmVhZG9ubHkgcG9zdEJ1aWxkU3RlcHM6IEpvYlN0ZXBbXTtcbiAgcHJpdmF0ZSByZWFkb25seSBwZXJtaXNzaW9uczogSm9iUGVybWlzc2lvbnM7XG4gIHByaXZhdGUgcmVhZG9ubHkgZGVwVHlwZXM6IERlcGVuZGVuY3lUeXBlW107XG4gIHByaXZhdGUgcmVhZG9ubHkgdXBncmFkZVRhcmdldDogc3RyaW5nO1xuICBwcml2YXRlIHJlYWRvbmx5IHNhdGlzZnlQZWVyRGVwZW5kZW5jaWVzOiBib29sZWFuO1xuICBwcml2YXRlIHJlYWRvbmx5IGluY2x1ZGVEZXByZWNhdGVkVmVyc2lvbnM6IGJvb2xlYW47XG5cbiAgY29uc3RydWN0b3IocHJvamVjdDogTm9kZVByb2plY3QsIG9wdGlvbnM6IFVwZ3JhZGVEZXBlbmRlbmNpZXNPcHRpb25zID0ge30pIHtcbiAgICBzdXBlcihwcm9qZWN0KTtcblxuICAgIHRoaXMucHJvamVjdCA9IHByb2plY3Q7XG4gICAgdGhpcy5vcHRpb25zID0gb3B0aW9ucztcblxuICAgIC8vIFZhbGlkYXRlIGNvb2xkb3duXG4gICAgaWYgKFxuICAgICAgb3B0aW9ucy5jb29sZG93biAhPT0gdW5kZWZpbmVkICYmXG4gICAgICAoIU51bWJlci5pc0ludGVnZXIob3B0aW9ucy5jb29sZG93bikgfHwgb3B0aW9ucy5jb29sZG93biA8IDApXG4gICAgKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIFwiVGhlICdjb29sZG93bicgb3B0aW9uIG11c3QgYmUgYSBub24tbmVnYXRpdmUgaW50ZWdlciByZXByZXNlbnRpbmcgZGF5c1wiLFxuICAgICAgKTtcbiAgICB9XG5cbiAgICAvLyBZYXJuIGNsYXNzaWMgZG9lc24ndCBzdXBwb3J0IGNvb2xkb3duXG4gICAgaWYgKG9wdGlvbnMuY29vbGRvd24gJiYgaXNZYXJuQ2xhc3NpYyhwcm9qZWN0LnBhY2thZ2UucGFja2FnZU1hbmFnZXIpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIFwiVGhlICdjb29sZG93bicgb3B0aW9uIGlzIG5vdCBzdXBwb3J0ZWQgd2l0aCB5YXJuIGNsYXNzaWMuIFwiICtcbiAgICAgICAgICBcIkNvbnNpZGVyIHVzaW5nIG5wbSwgcG5wbSwgYnVuLCBvciB5YXJuIGJlcnJ5IGluc3RlYWQuXCIsXG4gICAgICApO1xuICAgIH1cblxuICAgIHRoaXMuZGVwVHlwZXMgPSB0aGlzLm9wdGlvbnMudHlwZXMgPz8gW1xuICAgICAgRGVwZW5kZW5jeVR5cGUuQlVJTEQsXG4gICAgICBEZXBlbmRlbmN5VHlwZS5CVU5ETEVELFxuICAgICAgRGVwZW5kZW5jeVR5cGUuREVWRU5WLFxuICAgICAgRGVwZW5kZW5jeVR5cGUuUEVFUixcbiAgICAgIERlcGVuZGVuY3lUeXBlLlJVTlRJTUUsXG4gICAgICBEZXBlbmRlbmN5VHlwZS5URVNULFxuICAgICAgRGVwZW5kZW5jeVR5cGUuT1BUSU9OQUwsXG4gICAgXTtcbiAgICB0aGlzLnVwZ3JhZGVUYXJnZXQgPSB0aGlzLm9wdGlvbnMudGFyZ2V0ID8/IFwibWlub3JcIjtcbiAgICB0aGlzLnNhdGlzZnlQZWVyRGVwZW5kZW5jaWVzID0gdGhpcy5vcHRpb25zLnNhdGlzZnlQZWVyRGVwZW5kZW5jaWVzID8/IHRydWU7XG4gICAgdGhpcy5pbmNsdWRlRGVwcmVjYXRlZFZlcnNpb25zID1cbiAgICAgIHRoaXMub3B0aW9ucy5pbmNsdWRlRGVwcmVjYXRlZFZlcnNpb25zID8/IGZhbHNlO1xuICAgIHRoaXMucHVsbFJlcXVlc3RUaXRsZSA9IG9wdGlvbnMucHVsbFJlcXVlc3RUaXRsZSA/PyBcInVwZ3JhZGUgZGVwZW5kZW5jaWVzXCI7XG4gICAgdGhpcy5naXRJZGVudGl0eSA9XG4gICAgICBvcHRpb25zLndvcmtmbG93T3B0aW9ucz8uZ2l0SWRlbnRpdHkgPz8gREVGQVVMVF9HSVRIVUJfQUNUSU9OU19VU0VSO1xuICAgIHRoaXMucGVybWlzc2lvbnMgPSB7XG4gICAgICBjb250ZW50czogSm9iUGVybWlzc2lvbi5SRUFELFxuICAgICAgLi4ub3B0aW9ucy53b3JrZmxvd09wdGlvbnM/LnBlcm1pc3Npb25zLFxuICAgIH07XG4gICAgdGhpcy5wb3N0QnVpbGRTdGVwcyA9IFtdO1xuICAgIHRoaXMuY29udGFpbmVyT3B0aW9ucyA9IG9wdGlvbnMud29ya2Zsb3dPcHRpb25zPy5jb250YWluZXI7XG5cbiAgICB0aGlzLnBvc3RVcGdyYWRlVGFzayA9XG4gICAgICBwcm9qZWN0LnRhc2tzLnRyeUZpbmQoXCJwb3N0LXVwZ3JhZGVcIikgPz9cbiAgICAgIHByb2plY3QudGFza3MuYWRkVGFzayhcInBvc3QtdXBncmFkZVwiLCB7XG4gICAgICAgIGRlc2NyaXB0aW9uOiBcIlJ1bnMgYWZ0ZXIgdXBncmFkaW5nIGRlcGVuZGVuY2llc1wiLFxuICAgICAgfSk7XG5cbiAgICBjb25zdCB0YXNrRW52OiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+ID0geyBDSTogXCIwXCIgfTtcblxuICAgIC8vIFlhcm4gYmVycnkgdHJlYXRzIGFueSBub24tZW1wdHkgQ0kgdmFsdWUgYXMgdHJ1dGh5IGFuZCBhdXRvLWVuYWJsZXNcbiAgICAvLyBpbW11dGFibGUgaW5zdGFsbHMuIEV4cGxpY2l0bHkgZGlzYWJsZSBpdCBzbyB5YXJuIGRseC91cCBjYW4gbW9kaWZ5XG4gICAgLy8gdGhlIGxvY2tmaWxlIGR1cmluZyB1cGdyYWRlcy5cbiAgICBpZiAoaXNZYXJuQmVycnkocHJvamVjdC5wYWNrYWdlLnBhY2thZ2VNYW5hZ2VyKSkge1xuICAgICAgdGFza0Vudi5ZQVJOX0VOQUJMRV9JTU1VVEFCTEVfSU5TVEFMTFMgPSBcImZhbHNlXCI7XG4gICAgfVxuXG4gICAgLy8gU2V0IHlhcm4gYmVycnkgY29vbGRvd24gdmlhIGVudmlyb25tZW50IHZhcmlhYmxlLCBleHBlY3RzIG1pbnV0ZXNcbiAgICBpZiAob3B0aW9ucy5jb29sZG93biAmJiBpc1lhcm5CZXJyeShwcm9qZWN0LnBhY2thZ2UucGFja2FnZU1hbmFnZXIpKSB7XG4gICAgICB0YXNrRW52LllBUk5fTlBNX01JTklNQUxfQUdFX0dBVEUgPSBTdHJpbmcoXG4gICAgICAgIGRheXNUb01pbnV0ZXMob3B0aW9ucy5jb29sZG93biksXG4gICAgICApO1xuICAgIH1cblxuICAgIC8vIFNldCBucG0gY29vbGRvd24gZGF0ZSB2aWEgZW52aXJvbm1lbnQgdmFyaWFibGUgKGNhbGN1bGF0ZWQgYXQgcnVudGltZSksIGV4cGVjdHMgYSBkYXRlIGluIElTTyBmb3JtYXRcbiAgICBpZiAob3B0aW9ucy5jb29sZG93biAmJiBpc05wbShwcm9qZWN0LnBhY2thZ2UucGFja2FnZU1hbmFnZXIpKSB7XG4gICAgICB0YXNrRW52Lk5QTV9DT05GSUdfQkVGT1JFID0gYCQobm9kZSAtcCBcIm5ldyBEYXRlKERhdGUubm93KCktJHtkYXlzVG9NaWxsaXNlY29uZHMoXG4gICAgICAgIG9wdGlvbnMuY29vbGRvd24sXG4gICAgICApfSkudG9JU09TdHJpbmcoKVwiKWA7XG4gICAgfVxuXG4gICAgdGhpcy51cGdyYWRlVGFzayA9IHByb2plY3QuYWRkVGFzayhvcHRpb25zLnRhc2tOYW1lID8/IFwidXBncmFkZVwiLCB7XG4gICAgICAvLyB0aGlzIHRhc2sgc2hvdWxkIG5vdCBydW4gaW4gQ0kgbW9kZSBiZWNhdXNlIGl0cyBkZXNpZ25lZCB0b1xuICAgICAgLy8gdXBkYXRlIHBhY2thZ2UuanNvbiBhbmQgbG9jayBmaWxlcy5cbiAgICAgIGVudjogdGFza0VudixcbiAgICAgIGRlc2NyaXB0aW9uOiB0aGlzLnB1bGxSZXF1ZXN0VGl0bGUsXG4gICAgICBzdGVwczogeyB0b0pTT046ICgpID0+IHRoaXMucmVuZGVyVGFza1N0ZXBzKCkgfSBhcyBhbnksXG4gICAgfSk7XG4gICAgdGhpcy51cGdyYWRlVGFzay5sb2NrKCk7IC8vIHRoaXMgdGFzayBpcyBhIGxhenkgdmFsdWUsIHNvIG1ha2UgaXQgcmVhZG9ubHlcblxuICAgIC8vIGFsd2F5cyB1c2UgdGhlIEdpdEh1YiBvZiB0aGUgcm9vdCBwcm9qZWN0IC0gdGhlcmUgY2FuIG9ubHkgYmUgb25lXG4gICAgY29uc3QgZ2l0aHViID0gR2l0SHViLm9mKHByb2plY3Qucm9vdCk7XG5cbiAgICBpZiAodGhpcy51cGdyYWRlVGFzayAmJiBnaXRodWIgJiYgKG9wdGlvbnMud29ya2Zsb3cgPz8gdHJ1ZSkpIHtcbiAgICAgIGlmIChvcHRpb25zLndvcmtmbG93T3B0aW9ucz8uYnJhbmNoZXMpIHtcbiAgICAgICAgZm9yIChjb25zdCBicmFuY2ggb2Ygb3B0aW9ucy53b3JrZmxvd09wdGlvbnMuYnJhbmNoZXMpIHtcbiAgICAgICAgICB0aGlzLndvcmtmbG93cy5wdXNoKFxuICAgICAgICAgICAgdGhpcy5jcmVhdGVXb3JrZmxvdyh0aGlzLnVwZ3JhZGVUYXNrLCBnaXRodWIsIGJyYW5jaCksXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmIChSZWxlYXNlLm9mKHByb2plY3QpKSB7XG4gICAgICAgIGNvbnN0IHJlbGVhc2UgPSBSZWxlYXNlLm9mKHByb2plY3QpITtcbiAgICAgICAgcmVsZWFzZS5fZm9yRWFjaEJyYW5jaCgoYnJhbmNoOiBzdHJpbmcpID0+IHtcbiAgICAgICAgICB0aGlzLndvcmtmbG93cy5wdXNoKFxuICAgICAgICAgICAgdGhpcy5jcmVhdGVXb3JrZmxvdyh0aGlzLnVwZ3JhZGVUYXNrLCBnaXRodWIsIGJyYW5jaCksXG4gICAgICAgICAgKTtcbiAgICAgICAgfSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvLyByZXByZXNlbnRzIHRoZSBkZWZhdWx0IHJlcG9zaXRvcnkgYnJhbmNoLlxuICAgICAgICAvLyBqdXN0IGxpa2Ugbm90IHNwZWNpZnlpbmcgYW55dGhpbmcuXG4gICAgICAgIGNvbnN0IGRlZmF1bHRCcmFuY2ggPSB1bmRlZmluZWQ7XG4gICAgICAgIHRoaXMud29ya2Zsb3dzLnB1c2goXG4gICAgICAgICAgdGhpcy5jcmVhdGVXb3JrZmxvdyh0aGlzLnVwZ3JhZGVUYXNrLCBnaXRodWIsIGRlZmF1bHRCcmFuY2gpLFxuICAgICAgICApO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBBZGQgc3RlcHMgdG8gZXhlY3V0ZSBhIHN1Y2Nlc3NmdWwgYnVpbGQuXG4gICAqIEBwYXJhbSBzdGVwcyB3b3JrZmxvdyBzdGVwc1xuICAgKi9cbiAgcHVibGljIGFkZFBvc3RCdWlsZFN0ZXBzKC4uLnN0ZXBzOiBKb2JTdGVwW10pIHtcbiAgICB0aGlzLnBvc3RCdWlsZFN0ZXBzLnB1c2goLi4uc3RlcHMpO1xuICB9XG5cbiAgcHJpdmF0ZSByZW5kZXJUYXNrU3RlcHMoKTogVGFza1N0ZXBbXSB7XG4gICAgY29uc3Qgc3RlcHMgPSBuZXcgQXJyYXk8VGFza1N0ZXA+KCk7XG5cbiAgICAvLyBQYWNrYWdlIE1hbmFnZXIgdXBncmFkZSBzaG91bGQgYWx3YXlzIGluY2x1ZGUgYWxsIGRlcHNcbiAgICBjb25zdCBpbmNsdWRlRm9yUGFja2FnZU1hbmFnZXJVcGdyYWRlID0gdGhpcy5idWlsZERlcGVuZGVuY3lMaXN0KHRydWUpO1xuICAgIGlmIChpbmNsdWRlRm9yUGFja2FnZU1hbmFnZXJVcGdyYWRlLmxlbmd0aCA9PT0gMCkge1xuICAgICAgcmV0dXJuIFt7IGV4ZWNBcmdzOiBbXCJlY2hvXCIsIFwiTm8gZGVwZW5kZW5jaWVzIHRvIHVwZ3JhZGUuXCJdIH1dO1xuICAgIH1cblxuICAgIC8vIFJlbW92aW5nIGBucG0tY2hlY2stdXBkYXRlc2AgZnJvbSBvdXIgZGVwZW5kZW5jeSB0cmVlIGJlY2F1c2UgaXQgZGVwZW5kcyBvbiBhIHBhY2thZ2VcbiAgICAvLyB0aGF0IHVzZXMgYW4gbnBtLXNwZWNpZmljIGZlYXR1cmUgdGhhdCBjYXVzZXMgYW4gaW52YWxpZCBkZXBlbmRlbmN5IHRyZWUgd2hlbiB1c2luZyBZYXJuIDEuXG4gICAgLy8gU2VlIGh0dHBzOi8vZ2l0aHViLmNvbS9wcm9qZW4vcHJvamVuL3B1bGwvMzEzNiBmb3IgbW9yZSBkZXRhaWxzLlxuICAgIGNvbnN0IGluY2x1ZGVGb3JOY3UgPSB0aGlzLmJ1aWxkRGVwZW5kZW5jeUxpc3QoZmFsc2UpO1xuXG4gICAgLy8gYnVtcCB2ZXJzaW9ucyBpbiBwYWNrYWdlLmpzb25cbiAgICBpZiAoaW5jbHVkZUZvck5jdS5sZW5ndGgpIHtcbiAgICAgIGNvbnN0IG5jdUNvbW1hbmQgPSB0aGlzLmJ1aWxkTmN1Q29tbWFuZChpbmNsdWRlRm9yTmN1LCB7XG4gICAgICAgIHVwZ3JhZGU6IHRydWUsXG4gICAgICAgIHRhcmdldDogdGhpcy51cGdyYWRlVGFyZ2V0LFxuICAgICAgfSk7XG4gICAgICBzdGVwcy5wdXNoKHsgZXhlY0FyZ3M6IG5jdUNvbW1hbmQgfSk7XG4gICAgfVxuXG4gICAgLy8gcnVuIFwieWFybi9ucG0gaW5zdGFsbFwiIHRvIHVwZGF0ZSB0aGUgbG9ja2ZpbGUgYW5kIGluc3RhbGwgYW55IGRlcHMgKHN1Y2ggYXMgcHJvamVuKVxuICAgIHN0ZXBzLnB1c2goeyBleGVjOiB0aGlzLnByb2plY3QucGFja2FnZS5pbnN0YWxsQW5kVXBkYXRlTG9ja2ZpbGVDb21tYW5kIH0pO1xuXG4gICAgLy8gcnVuIHVwZ3JhZGUgY29tbWFuZCB0byB1cGdyYWRlIHRyYW5zaXRpdmUgZGVwcyBhcyB3ZWxsXG4gICAgc3RlcHMucHVzaCh7XG4gICAgICBleGVjQXJnczogdGhpcy5yZW5kZXJVcGdyYWRlUGFja2FnZXNDb21tYW5kKFxuICAgICAgICBpbmNsdWRlRm9yUGFja2FnZU1hbmFnZXJVcGdyYWRlLFxuICAgICAgKSxcbiAgICB9KTtcblxuICAgIC8vIElmIHdlIGhhdmUgYSBwYWNrYWdlcyBkZWR1cGxpY2F0aW9uIHRhc2ssIHJ1biBpdCBub3cuXG4gICAgaWYgKHRoaXMucHJvamVjdC5wYWNrYWdlLmRlZHVwZVRhc2spIHtcbiAgICAgIHN0ZXBzLnB1c2goeyBzcGF3bjogdGhpcy5wcm9qZWN0LnBhY2thZ2UuZGVkdXBlVGFzay5uYW1lIH0pO1xuICAgIH1cblxuICAgIC8vIHJ1biBcInByb2plblwiIHRvIGdpdmUgcHJvamVuIGEgY2hhbmNlIHRvIHVwZGF0ZSBkZXBlbmRlbmNpZXMgKGl0IHdpbGwgYWxzbyBydW4gXCJ5YXJuIGluc3RhbGxcIilcbiAgICBzdGVwcy5wdXNoKHsgZXhlYzogdGhpcy5wcm9qZWN0LnByb2plbkNvbW1hbmQgfSk7XG4gICAgc3RlcHMucHVzaCh7IHNwYXduOiB0aGlzLnBvc3RVcGdyYWRlVGFzay5uYW1lIH0pO1xuXG4gICAgcmV0dXJuIHN0ZXBzO1xuICB9XG5cbiAgLyoqXG4gICAqIEJ1aWxkIG5wbS1jaGVjay11cGRhdGVzIGNvbW1hbmQgd2l0aCBjb21tb24gb3B0aW9ucy5cbiAgICovXG4gIHByaXZhdGUgYnVpbGROY3VDb21tYW5kKFxuICAgIGluY2x1ZGVQYWNrYWdlczogc3RyaW5nW10sXG4gICAgb3B0aW9uczoge1xuICAgICAgdXBncmFkZT86IGJvb2xlYW47XG4gICAgICB0YXJnZXQ/OiBzdHJpbmc7XG4gICAgICBmb3JtYXQ/OiBzdHJpbmc7XG4gICAgICByZW1vdmVSYW5nZT86IGJvb2xlYW47XG4gICAgfSA9IHt9LFxuICApOiBzdHJpbmdbXSB7XG4gICAgY29uc3QgY29tbWFuZCA9IFtcbiAgICAgIC4uLmV4ZWN1dGVDb21tYW5kUHJpb3JJbnN0YWxsYXRpb24odGhpcy5wcm9qZWN0LnBhY2thZ2UucGFja2FnZU1hbmFnZXIpLFxuICAgICAgXCJucG0tY2hlY2stdXBkYXRlc0AyMFwiLFxuICAgIF07XG5cbiAgICBpZiAob3B0aW9ucy51cGdyYWRlKSB7XG4gICAgICBjb21tYW5kLnB1c2goXCItLXVwZ3JhZGVcIik7XG4gICAgfVxuICAgIGlmIChvcHRpb25zLnRhcmdldCkge1xuICAgICAgY29tbWFuZC5wdXNoKGAtLXRhcmdldD0ke29wdGlvbnMudGFyZ2V0fWApO1xuICAgIH1cbiAgICBpZiAob3B0aW9ucy5mb3JtYXQpIHtcbiAgICAgIGNvbW1hbmQucHVzaChgLS1mb3JtYXQ9JHtvcHRpb25zLmZvcm1hdH1gKTtcbiAgICB9XG4gICAgaWYgKG9wdGlvbnMucmVtb3ZlUmFuZ2UpIHtcbiAgICAgIGNvbW1hbmQucHVzaChcIi0tcmVtb3ZlUmFuZ2VcIik7XG4gICAgfVxuICAgIGlmICh0aGlzLm9wdGlvbnMuY29vbGRvd24pIHtcbiAgICAgIGNvbW1hbmQucHVzaChgLS1jb29sZG93bj0ke3RoaXMub3B0aW9ucy5jb29sZG93bn1gKTtcbiAgICB9XG5cbiAgICBjb21tYW5kLnB1c2goYC0tJHt0aGlzLnNhdGlzZnlQZWVyRGVwZW5kZW5jaWVzID8gXCJwZWVyXCIgOiBcIm5vLXBlZXJcIn1gKTtcbiAgICBjb21tYW5kLnB1c2goXG4gICAgICBgLS0ke3RoaXMuaW5jbHVkZURlcHJlY2F0ZWRWZXJzaW9ucyA/IFwiZGVwcmVjYXRlZFwiIDogXCJuby1kZXByZWNhdGVkXCJ9YCxcbiAgICApO1xuICAgIGNvbW1hbmQucHVzaChgLS1kZXA9JHt0aGlzLnJlbmRlck5jdURlcGVuZGVuY3lUeXBlcyh0aGlzLmRlcFR5cGVzKX1gKTtcbiAgICBjb21tYW5kLnB1c2goYC0tZmlsdGVyPSR7aW5jbHVkZVBhY2thZ2VzLmpvaW4oXCIsXCIpfWApO1xuXG4gICAgcmV0dXJuIGNvbW1hbmQ7XG4gIH1cblxuICAvKipcbiAgICogUmVuZGVyIHByb2plbiBkZXBlbmRlbmNpZXMgdHlwZXMgdG8gYSBsaXN0IG9mIG5jdSBjb21wYXRpYmxlIHR5cGVzXG4gICAqL1xuICBwcml2YXRlIHJlbmRlck5jdURlcGVuZGVuY3lUeXBlcyh0eXBlczogRGVwZW5kZW5jeVR5cGVbXSkge1xuICAgIHJldHVybiBBcnJheS5mcm9tKFxuICAgICAgbmV3IFNldChcbiAgICAgICAgdHlwZXNcbiAgICAgICAgICAubWFwKCh0eXBlKSA9PiB7XG4gICAgICAgICAgICBzd2l0Y2ggKHR5cGUpIHtcbiAgICAgICAgICAgICAgY2FzZSBEZXBlbmRlbmN5VHlwZS5QRUVSOlxuICAgICAgICAgICAgICAgIHJldHVybiBcInBlZXJcIjtcbiAgICAgICAgICAgICAgY2FzZSBEZXBlbmRlbmN5VHlwZS5SVU5USU1FOlxuICAgICAgICAgICAgICAgIHJldHVybiBcInByb2RcIjtcbiAgICAgICAgICAgICAgY2FzZSBEZXBlbmRlbmN5VHlwZS5PUFRJT05BTDpcbiAgICAgICAgICAgICAgICByZXR1cm4gXCJvcHRpb25hbFwiO1xuXG4gICAgICAgICAgICAgIGNhc2UgRGVwZW5kZW5jeVR5cGUuVEVTVDpcbiAgICAgICAgICAgICAgY2FzZSBEZXBlbmRlbmN5VHlwZS5ERVZFTlY6XG4gICAgICAgICAgICAgIGNhc2UgRGVwZW5kZW5jeVR5cGUuQlVJTEQ6XG4gICAgICAgICAgICAgICAgcmV0dXJuIFwiZGV2XCI7XG5cbiAgICAgICAgICAgICAgY2FzZSBEZXBlbmRlbmN5VHlwZS5CVU5ETEVEOlxuICAgICAgICAgICAgICAgIHJldHVybiBcInByb2RcIjtcbiAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSlcbiAgICAgICAgICAuZmlsdGVyKCh0eXBlKSA9PiBCb29sZWFuKHR5cGUpKSxcbiAgICAgICksXG4gICAgKS5qb2luKFwiLFwiKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZW5kZXIgYSBwYWNrYWdlIG1hbmFnZXIgc3BlY2lmaWMgY29tbWFuZCB0byB1cGdyYWRlIGFsbCByZXF1ZXN0ZWQgZGVwZW5kZW5jaWVzLlxuICAgKi9cbiAgcHJpdmF0ZSByZW5kZXJVcGdyYWRlUGFja2FnZXNDb21tYW5kKGluY2x1ZGU6IHN0cmluZ1tdKTogc3RyaW5nW10ge1xuICAgIGZ1bmN0aW9uIHVwZ3JhZGVQYWNrYWdlcyhjb21tYW5kOiBzdHJpbmdbXSwgY29vbGRvd25GbGFnPzogc3RyaW5nKSB7XG4gICAgICByZXR1cm4gKCkgPT4ge1xuICAgICAgICBjb25zdCBwYXJ0cyA9IFsuLi5jb21tYW5kLCAuLi5pbmNsdWRlXTtcbiAgICAgICAgaWYgKGNvb2xkb3duRmxhZykge1xuICAgICAgICAgIHBhcnRzLnB1c2goY29vbGRvd25GbGFnKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcGFydHM7XG4gICAgICB9O1xuICAgIH1cblxuICAgIGNvbnN0IHBhY2thZ2VNYW5hZ2VyID0gdGhpcy5wcm9qZWN0LnBhY2thZ2UucGFja2FnZU1hbmFnZXI7XG4gICAgY29uc3QgY29vbGRvd24gPSB0aGlzLm9wdGlvbnMuY29vbGRvd247XG5cbiAgICBsZXQgbGF6eSA9IHVuZGVmaW5lZDtcbiAgICBzd2l0Y2ggKHBhY2thZ2VNYW5hZ2VyKSB7XG4gICAgICBjYXNlIE5vZGVQYWNrYWdlTWFuYWdlci5ZQVJOOlxuICAgICAgY2FzZSBOb2RlUGFja2FnZU1hbmFnZXIuWUFSTl9DTEFTU0lDOlxuICAgICAgICBsYXp5ID0gdXBncmFkZVBhY2thZ2VzKFtcInlhcm5cIiwgXCJ1cGdyYWRlXCJdKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIE5vZGVQYWNrYWdlTWFuYWdlci5ZQVJOMjpcbiAgICAgIGNhc2UgTm9kZVBhY2thZ2VNYW5hZ2VyLllBUk5fQkVSUlk6XG4gICAgICAgIC8vIFlhcm4gQmVycnkgY29vbGRvd24gc2V0IHZpYSB0YXNrIGVudlxuICAgICAgICBsYXp5ID0gdXBncmFkZVBhY2thZ2VzKFtcInlhcm5cIiwgXCJ1cFwiLCBcIi1SXCJdKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIE5vZGVQYWNrYWdlTWFuYWdlci5OUE06XG4gICAgICAgIC8vIG5wbSBjb29sZG93biBzZXQgdmlhIE5QTV9DT05GSUdfQkVGT1JFIGVudlxuICAgICAgICBsYXp5ID0gdXBncmFkZVBhY2thZ2VzKFtcIm5wbVwiLCBcInVwZGF0ZVwiXSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBOb2RlUGFja2FnZU1hbmFnZXIuUE5QTTpcbiAgICAgICAgLy8gcG5wbSBleHBlY3RzIG1pbnV0ZXNcbiAgICAgICAgbGF6eSA9IHVwZ3JhZGVQYWNrYWdlcyhcbiAgICAgICAgICBbXCJwbnBtXCIsIFwidXBkYXRlXCJdLFxuICAgICAgICAgIGNvb2xkb3duICE9PSB1bmRlZmluZWRcbiAgICAgICAgICAgID8gYC0tY29uZmlnLm1pbmltdW0tcmVsZWFzZS1hZ2U9JHtkYXlzVG9NaW51dGVzKGNvb2xkb3duKX1gXG4gICAgICAgICAgICA6IHVuZGVmaW5lZCxcbiAgICAgICAgKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIE5vZGVQYWNrYWdlTWFuYWdlci5CVU46XG4gICAgICAgIC8vIGJ1biBleHBlY3RzIHNlY29uZHNcbiAgICAgICAgbGF6eSA9IHVwZ3JhZGVQYWNrYWdlcyhcbiAgICAgICAgICBbXCJidW5cIiwgXCJ1cGRhdGVcIl0sXG4gICAgICAgICAgY29vbGRvd25cbiAgICAgICAgICAgID8gYC0tbWluaW11bS1yZWxlYXNlLWFnZT0ke2RheXNUb1NlY29uZHMoY29vbGRvd24pfWBcbiAgICAgICAgICAgIDogdW5kZWZpbmVkLFxuICAgICAgICApO1xuICAgICAgICBicmVhaztcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgdW5leHBlY3RlZCBwYWNrYWdlIG1hbmFnZXIgJHtwYWNrYWdlTWFuYWdlcn1gKTtcbiAgICB9XG5cbiAgICAvLyByZXR1cm4gYSBsYXp5IGZ1bmN0aW9uIHNvIHRoYXQgZGVwZW5kZW5jaWVzIGluY2x1ZGUgb25lcyB0aGF0IHdlcmVcbiAgICAvLyBhZGRlZCBwb3N0IHByb2plY3QgaW5zdGFudGlhdGlvbiAoaS5lIHVzaW5nIHByb2plY3QuYWRkRGVwcylcbiAgICByZXR1cm4gbGF6eSBhcyB1bmtub3duIGFzIHN0cmluZ1tdO1xuICB9XG5cbiAgcHJpdmF0ZSBidWlsZERlcGVuZGVuY3lMaXN0KGluY2x1ZGVEZXBlbmRlbmNpZXNXaXRoQ29uc3RyYWludDogYm9vbGVhbikge1xuICAgIHJldHVybiBBcnJheS5mcm9tKFxuICAgICAgbmV3IFNldChcbiAgICAgICAgdGhpcy5vcHRpb25zLmluY2x1ZGUgPz9cbiAgICAgICAgICB0aGlzLmZpbHRlckRlcGVuZGVuY2llcyhpbmNsdWRlRGVwZW5kZW5jaWVzV2l0aENvbnN0cmFpbnQpLFxuICAgICAgKSxcbiAgICApO1xuICB9XG5cbiAgcHJpdmF0ZSBmaWx0ZXJEZXBlbmRlbmNpZXMoaW5jbHVkZUNvbnN0cmFpbnQ6IGJvb2xlYW4pOiBzdHJpbmdbXSB7XG4gICAgY29uc3QgZGVwZW5kZW5jaWVzID0gW107XG5cbiAgICBjb25zdCBkZXBzID0gdGhpcy5wcm9qZWN0LmRlcHMuYWxsXG4gICAgICAvLyByZW1vdmUgdGhvc2UgdGhhdCBoYXZlIGEgY29uc3RyYWludCB2ZXJzaW9uICh1bmxlc3MgaW5jbHVkZUNvbnN0cmFpbnQgaXMgdHJ1ZSlcbiAgICAgIC5maWx0ZXIoXG4gICAgICAgIChkKSA9PlxuICAgICAgICAgIGluY2x1ZGVDb25zdHJhaW50IHx8XG4gICAgICAgICAgdGhpcy5wYWNrYWdlQ2FuQmVVcGdyYWRlZEluUGFja2FnZUpzb24oZC52ZXJzaW9uKSxcbiAgICAgIClcbiAgICAgIC8vIHJlbW92ZSBvdmVycmlkZSBkZXBlbmRlbmNpZXNcbiAgICAgIC5maWx0ZXIoKGQpID0+IGQudHlwZSAhPT0gRGVwZW5kZW5jeVR5cGUuT1ZFUlJJREUpO1xuXG4gICAgZm9yIChjb25zdCB0eXBlIG9mIHRoaXMuZGVwVHlwZXMpIHtcbiAgICAgIGRlcGVuZGVuY2llcy5wdXNoKFxuICAgICAgICAuLi5kZXBzXG4gICAgICAgICAgLmZpbHRlcigoZCkgPT4gZC50eXBlID09PSB0eXBlKVxuICAgICAgICAgIC5maWx0ZXIoKGQpID0+ICEodGhpcy5vcHRpb25zLmV4Y2x1ZGUgPz8gW10pLmluY2x1ZGVzKGQubmFtZSkpLFxuICAgICAgKTtcbiAgICB9XG5cbiAgICByZXR1cm4gZGVwZW5kZW5jaWVzLm1hcCgoZCkgPT4gZC5uYW1lKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBQcm9qZW4gY2FuIGFsdGVyIGEgcGFja2FnZSdzIHZlcnNpb24gaW4gcGFja2FnZS5qc29uIHdoZW4gZWl0aGVyIHRoZSB2ZXJzaW9uIGlzIG9taXR0ZWQsIG9yIHNldCB0byBcIipcIi5cbiAgICogT3RoZXJ3aXNlLCB0aGUgZXhhY3QgdmVyc2lvbiBzZWxlY3RlZCBpcyBwbGFjZWQgaW4gdGhlIHBhY2thZ2UuanNvbiBmaWxlIGFuZCB1cGdyYWRpbmcgaXMgaGFuZGxlZCB0aHJvdWdoIHRoZSBwYWNrYWdlIG1hbmFnZXJcbiAgICogcmF0aGVyIHRoYW4gbnBtLWNoZWNrLXVwZGF0ZXMuXG4gICAqXG4gICAqIEBwYXJhbSB2ZXJzaW9uIHNlbXZlciBmcm9tIERlcGVuZGVuY3lDb29yZGluYXRlcy52ZXJzaW9uLCBtYXkgYmUgdW5kZWZpbmVkXG4gICAqIEByZXR1cm5zIHdoZXRoZXIgdGhlIHZlcnNpb24gaXMgdGhlIGRlZmF1bHQgdmVyc2lvbmluZyBiZWhhdmlvclxuICAgKi9cbiAgcHJpdmF0ZSBwYWNrYWdlQ2FuQmVVcGdyYWRlZEluUGFja2FnZUpzb24oXG4gICAgdmVyc2lvbjogc3RyaW5nIHwgdW5kZWZpbmVkLFxuICApOiBib29sZWFuIHtcbiAgICAvLyBObyB2ZXJzaW9uIG1lYW5zIFwibGF0ZXN0XCJcbiAgICByZXR1cm4gIXZlcnNpb24gfHwgdmVyc2lvbiA9PT0gXCIqXCI7XG4gIH1cblxuICBwcml2YXRlIGNyZWF0ZVdvcmtmbG93KFxuICAgIHRhc2s6IFRhc2ssXG4gICAgZ2l0aHViOiBHaXRIdWIsXG4gICAgYnJhbmNoPzogc3RyaW5nLFxuICApOiBHaXRodWJXb3JrZmxvdyB7XG4gICAgY29uc3Qgc2NoZWR1bGUgPVxuICAgICAgdGhpcy5vcHRpb25zLndvcmtmbG93T3B0aW9ucz8uc2NoZWR1bGUgPz9cbiAgICAgIFVwZ3JhZGVEZXBlbmRlbmNpZXNTY2hlZHVsZS5EQUlMWTtcblxuICAgIGNvbnN0IHRhc2tCcmFuY2hOYW1lID0gYCR7dGFzay5uYW1lfSR7XG4gICAgICBicmFuY2ggPyBgLSR7YnJhbmNoLnJlcGxhY2UoL1xcLy9nLCBcIi1cIil9YCA6IFwiXCJcbiAgICB9YDtcbiAgICBjb25zdCB3b3JrZmxvd05hbWUgPSB3b3JrZmxvd05hbWVGb3JQcm9qZWN0KHRhc2tCcmFuY2hOYW1lLCB0aGlzLnByb2plY3QpO1xuXG4gICAgY29uc3Qgd29ya2Zsb3cgPSBnaXRodWIuYWRkV29ya2Zsb3cod29ya2Zsb3dOYW1lKTtcbiAgICBjb25zdCB0cmlnZ2Vyczogd29ya2Zsb3dzLlRyaWdnZXJzID0ge1xuICAgICAgd29ya2Zsb3dEaXNwYXRjaDoge30sXG4gICAgICBzY2hlZHVsZTpcbiAgICAgICAgc2NoZWR1bGUuY3Jvbi5sZW5ndGggPiAwXG4gICAgICAgICAgPyBzY2hlZHVsZS5jcm9uLm1hcCgoZSkgPT4gKHsgY3JvbjogZSB9KSlcbiAgICAgICAgICA6IHVuZGVmaW5lZCxcbiAgICB9O1xuICAgIHdvcmtmbG93Lm9uKHRyaWdnZXJzKTtcblxuICAgIGNvbnN0IHVwZ3JhZGUgPSB0aGlzLmNyZWF0ZVVwZ3JhZGUodGFzaywgZ2l0aHViLCBicmFuY2gpO1xuICAgIGNvbnN0IHByID0gdGhpcy5jcmVhdGVQcih3b3JrZmxvdywgdXBncmFkZSk7XG5cbiAgICBjb25zdCBqb2JzOiBSZWNvcmQ8c3RyaW5nLCB3b3JrZmxvd3MuSm9iPiA9IHt9O1xuICAgIGpvYnNbdXBncmFkZS5qb2JJZF0gPSB1cGdyYWRlLmpvYjtcbiAgICBqb2JzW3ByLmpvYklkXSA9IHByLmpvYjtcblxuICAgIHdvcmtmbG93LmFkZEpvYnMoam9icyk7XG4gICAgcmV0dXJuIHdvcmtmbG93O1xuICB9XG5cbiAgcHJpdmF0ZSBjcmVhdGVVcGdyYWRlKHRhc2s6IFRhc2ssIGdpdGh1YjogR2l0SHViLCBicmFuY2g/OiBzdHJpbmcpOiBVcGdyYWRlIHtcbiAgICBjb25zdCB3aXRoXyA9IHtcbiAgICAgIC4uLihicmFuY2ggPyB7IHJlZjogYnJhbmNoIH0gOiB7fSksXG4gICAgICAuLi4oZ2l0aHViLmRvd25sb2FkTGZzID8geyBsZnM6IHRydWUgfSA6IHt9KSxcbiAgICAgIC4uLihnaXRodWIuY2hlY2tvdXRTdWJtb2R1bGVzICE9PSBDaGVja291dFN1Ym1vZHVsZXMuRElTQUJMRURcbiAgICAgICAgPyB7IHN1Ym1vZHVsZXM6IGdpdGh1Yi5jaGVja291dFN1Ym1vZHVsZXMgfVxuICAgICAgICA6IHt9KSxcbiAgICB9O1xuXG4gICAgY29uc3Qgc3RlcHM6IHdvcmtmbG93cy5Kb2JTdGVwW10gPSBbXG4gICAgICBXb3JrZmxvd1N0ZXBzLmNoZWNrb3V0KHsgd2l0aDogd2l0aF8gfSksXG4gICAgICAuLi50aGlzLnByb2plY3QucmVuZGVyV29ya2Zsb3dTZXR1cCh7IG11dGFibGU6IGZhbHNlIH0pLFxuICAgICAge1xuICAgICAgICBuYW1lOiBcIlVwZ3JhZGUgZGVwZW5kZW5jaWVzXCIsXG4gICAgICAgIHJ1bjogdGhpcy5wcm9qZWN0LnJ1blRhc2tDb21tYW5kKHRhc2spLFxuICAgICAgICB3b3JraW5nRGlyZWN0b3J5OiB0aGlzLnByb2plY3QucGFyZW50XG4gICAgICAgICAgPyBwcm9qZWN0UGF0aFJlbGF0aXZlVG9SZXBvUm9vdCh0aGlzLnByb2plY3QpXG4gICAgICAgICAgOiB1bmRlZmluZWQsXG4gICAgICB9LFxuICAgIF07XG5cbiAgICBzdGVwcy5wdXNoKC4uLnRoaXMucG9zdEJ1aWxkU3RlcHMpO1xuICAgIHN0ZXBzLnB1c2goXG4gICAgICAuLi5Xb3JrZmxvd0FjdGlvbnMudXBsb2FkR2l0UGF0Y2goe1xuICAgICAgICBzdGVwSWQ6IENSRUFURV9QQVRDSF9TVEVQX0lELFxuICAgICAgICBvdXRwdXROYW1lOiBQQVRDSF9DUkVBVEVEX09VVFBVVCxcbiAgICAgIH0pLFxuICAgICk7XG5cbiAgICByZXR1cm4ge1xuICAgICAgam9iOiB7XG4gICAgICAgIG5hbWU6IFwiVXBncmFkZVwiLFxuICAgICAgICBjb250YWluZXI6IHRoaXMuY29udGFpbmVyT3B0aW9ucyxcbiAgICAgICAgcGVybWlzc2lvbnM6IHRoaXMucGVybWlzc2lvbnMsXG4gICAgICAgIGVudjogdGhpcy5vcHRpb25zLndvcmtmbG93T3B0aW9ucz8uZW52LFxuICAgICAgICAuLi5naXRodWIucnVuc09uQ29uZmlnKHRoaXMub3B0aW9ucy53b3JrZmxvd09wdGlvbnMpLFxuICAgICAgICBzdGVwczogc3RlcHMsXG4gICAgICAgIG91dHB1dHM6IHtcbiAgICAgICAgICBbUEFUQ0hfQ1JFQVRFRF9PVVRQVVRdOiB7XG4gICAgICAgICAgICBzdGVwSWQ6IENSRUFURV9QQVRDSF9TVEVQX0lELFxuICAgICAgICAgICAgb3V0cHV0TmFtZTogUEFUQ0hfQ1JFQVRFRF9PVVRQVVQsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgIH0sXG4gICAgICBqb2JJZDogXCJ1cGdyYWRlXCIsXG4gICAgICByZWY6IGJyYW5jaCxcbiAgICB9O1xuICB9XG5cbiAgcHJpdmF0ZSBjcmVhdGVQcih3b3JrZmxvdzogR2l0aHViV29ya2Zsb3csIHVwZ3JhZGU6IFVwZ3JhZGUpOiBQUiB7XG4gICAgY29uc3QgY3JlZGVudGlhbHMgPVxuICAgICAgdGhpcy5vcHRpb25zLndvcmtmbG93T3B0aW9ucz8ucHJvamVuQ3JlZGVudGlhbHMgPz9cbiAgICAgIHdvcmtmbG93LnByb2plbkNyZWRlbnRpYWxzO1xuXG4gICAgY29uc3Qgc2VtYW50aWNDb21taXQgPSB0aGlzLm9wdGlvbnMuc2VtYW50aWNDb21taXQgPz8gXCJjaG9yZVwiO1xuXG4gICAgLy8gY3JlYXRlUHIgaXMgb25seSBjYWxsZWQgZnJvbSBjcmVhdGVXb3JrZmxvdywgd2hpY2ggaXMgb25seSByZWFjaGFibGVcbiAgICAvLyBvbmNlIHRoZSBjb25zdHJ1Y3RvciBoYXMgYWxyZWFkeSBjb25maXJtZWQgdGhlIHJvb3QgcHJvamVjdCBoYXMgR2l0SHViXG4gICAgLy8gZW5hYmxlZCAtIHNvIHRoaXMgaXMgYWx3YXlzIGRlZmluZWQuXG4gICAgY29uc3QgZ2l0aHViID0gR2l0SHViLm9mKHRoaXMucHJvamVjdC5yb290KSE7XG5cbiAgICByZXR1cm4ge1xuICAgICAgam9iOiBXb3JrZmxvd0pvYnMucHVsbFJlcXVlc3RGcm9tUGF0Y2goe1xuICAgICAgICBwYXRjaDoge1xuICAgICAgICAgIGpvYklkOiB1cGdyYWRlLmpvYklkLFxuICAgICAgICAgIG91dHB1dE5hbWU6IFBBVENIX0NSRUFURURfT1VUUFVULFxuICAgICAgICAgIHJlZjogdXBncmFkZS5yZWYsXG4gICAgICAgIH0sXG4gICAgICAgIHdvcmtmbG93TmFtZTogd29ya2Zsb3cubmFtZSxcbiAgICAgICAgY3JlZGVudGlhbHMsXG4gICAgICAgIC4uLmdpdGh1Yi5ydW5zT25Db25maWcodGhpcy5vcHRpb25zLndvcmtmbG93T3B0aW9ucyksXG4gICAgICAgIHB1bGxSZXF1ZXN0VGl0bGU6IGAke3NlbWFudGljQ29tbWl0fShkZXBzKTogJHt0aGlzLnB1bGxSZXF1ZXN0VGl0bGV9YCxcbiAgICAgICAgcHVsbFJlcXVlc3REZXNjcmlwdGlvbjogXCJVcGdyYWRlcyBwcm9qZWN0IGRlcGVuZGVuY2llcy5cIixcbiAgICAgICAgZ2l0SWRlbnRpdHk6IHRoaXMuZ2l0SWRlbnRpdHksXG4gICAgICAgIGFzc2lnbmVlczogdGhpcy5vcHRpb25zLndvcmtmbG93T3B0aW9ucz8uYXNzaWduZWVzLFxuICAgICAgICBsYWJlbHM6IHRoaXMub3B0aW9ucy53b3JrZmxvd09wdGlvbnM/LmxhYmVscyxcbiAgICAgICAgc2lnbm9mZjogdGhpcy5vcHRpb25zLnNpZ25vZmYsXG4gICAgICB9KSxcbiAgICAgIGpvYklkOiBcInByXCIsXG4gICAgfTtcbiAgfVxufVxuXG5pbnRlcmZhY2UgVXBncmFkZSB7XG4gIHJlYWRvbmx5IHJlZj86IHN0cmluZztcbiAgcmVhZG9ubHkgam9iOiB3b3JrZmxvd3MuSm9iO1xuICByZWFkb25seSBqb2JJZDogc3RyaW5nO1xufVxuXG5pbnRlcmZhY2UgUFIge1xuICByZWFkb25seSBqb2I6IHdvcmtmbG93cy5Kb2I7XG4gIHJlYWRvbmx5IGpvYklkOiBzdHJpbmc7XG59XG5cbi8qKlxuICogT3B0aW9ucyBmb3IgYFVwZ3JhZGVEZXBlbmRlbmNpZXMud29ya2Zsb3dPcHRpb25zYC5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBVcGdyYWRlRGVwZW5kZW5jaWVzV29ya2Zsb3dPcHRpb25zIHtcbiAgLyoqXG4gICAqIFNjaGVkdWxlIHRvIHJ1biBvbi5cbiAgICpcbiAgICogQGRlZmF1bHQgVXBncmFkZURlcGVuZGVuY2llc1NjaGVkdWxlLkRBSUxZXG4gICAqL1xuICByZWFkb25seSBzY2hlZHVsZT86IFVwZ3JhZGVEZXBlbmRlbmNpZXNTY2hlZHVsZTtcblxuICAvKipcbiAgICogQ2hvb3NlIGEgbWV0aG9kIGZvciBhdXRoZW50aWNhdGluZyB3aXRoIEdpdEh1YiBmb3IgY3JlYXRpbmcgdGhlIFBSLlxuICAgKlxuICAgKiBXaGVuIHVzaW5nIHRoZSBkZWZhdWx0IGdpdGh1YiB0b2tlbiwgUFIncyBjcmVhdGVkIGJ5IHRoaXMgd29ya2Zsb3dcbiAgICogd2lsbCBub3QgdHJpZ2dlciBhbnkgc3Vic2VxdWVudCB3b3JrZmxvd3MgKGkuZSB0aGUgYnVpbGQgd29ya2Zsb3cpLCBzb1xuICAgKiBwcm9qZW4gcmVxdWlyZXMgQVBJIGFjY2VzcyB0byBiZSBwcm92aWRlZCB0aHJvdWdoIGUuZy4gYSBwZXJzb25hbFxuICAgKiBhY2Nlc3MgdG9rZW4gb3Igb3RoZXIgbWV0aG9kLlxuICAgKlxuICAgKiBAc2VlIGh0dHBzOi8vZ2l0aHViLmNvbS9wZXRlci1ldmFucy9jcmVhdGUtcHVsbC1yZXF1ZXN0L2lzc3Vlcy80OFxuICAgKiBAZGVmYXVsdCAtIHBlcnNvbmFsIGFjY2VzcyB0b2tlbiBuYW1lZCBQUk9KRU5fR0lUSFVCX1RPS0VOXG4gICAqL1xuICByZWFkb25seSBwcm9qZW5DcmVkZW50aWFscz86IEdpdGh1YkNyZWRlbnRpYWxzO1xuXG4gIC8qKlxuICAgKiBMYWJlbHMgdG8gYXBwbHkgb24gdGhlIFBSLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIG5vIGxhYmVscy5cbiAgICovXG4gIHJlYWRvbmx5IGxhYmVscz86IHN0cmluZ1tdO1xuXG4gIC8qKlxuICAgKiBBc3NpZ25lZXMgdG8gYWRkIG9uIHRoZSBQUi5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBubyBhc3NpZ25lZXNcbiAgICovXG4gIHJlYWRvbmx5IGFzc2lnbmVlcz86IHN0cmluZ1tdO1xuXG4gIC8qKlxuICAgKiBKb2IgY29udGFpbmVyIG9wdGlvbnMuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gZGVmYXVsdHNcbiAgICovXG4gIHJlYWRvbmx5IGNvbnRhaW5lcj86IHdvcmtmbG93cy5Db250YWluZXJPcHRpb25zO1xuXG4gIC8qKlxuICAgKiBMaXN0IG9mIGJyYW5jaGVzIHRvIGNyZWF0ZSBQUidzIGZvci5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBBbGwgcmVsZWFzZSBicmFuY2hlcyBjb25maWd1cmVkIGZvciB0aGUgcHJvamVjdC5cbiAgICovXG4gIHJlYWRvbmx5IGJyYW5jaGVzPzogc3RyaW5nW107XG5cbiAgLyoqXG4gICAqIFRoZSBnaXQgaWRlbnRpdHkgdG8gdXNlIGZvciBjb21taXRzLlxuICAgKiBAZGVmYXVsdCAtIGRlZmF1bHQgR2l0SHViIEFjdGlvbnMgdXNlclxuICAgKi9cbiAgcmVhZG9ubHkgZ2l0SWRlbnRpdHk/OiBHaXRJZGVudGl0eTtcblxuICAvKipcbiAgICogR2l0aHViIFJ1bm5lciBzZWxlY3Rpb24gbGFiZWxzXG4gICAqIEBkZWZhdWx0IFtcInVidW50dS1sYXRlc3RcIl1cbiAgICogQGRlc2NyaXB0aW9uIERlZmluZXMgYSB0YXJnZXQgUnVubmVyIGJ5IGxhYmVsc1xuICAgKiBAdGhyb3dzIHtFcnJvcn0gaWYgYm90aCBgcnVuc09uYCBhbmQgYHJ1bnNPbkdyb3VwYCBhcmUgc3BlY2lmaWVkXG4gICAqL1xuICByZWFkb25seSBydW5zT24/OiBzdHJpbmdbXTtcblxuICAvKipcbiAgICogR2l0aHViIFJ1bm5lciBHcm91cCBzZWxlY3Rpb24gb3B0aW9uc1xuICAgKiBAZGVzY3JpcHRpb24gRGVmaW5lcyBhIHRhcmdldCBSdW5uZXIgR3JvdXAgYnkgbmFtZSBhbmQvb3IgbGFiZWxzXG4gICAqIEB0aHJvd3Mge0Vycm9yfSBpZiBib3RoIGBydW5zT25gIGFuZCBgcnVuc09uR3JvdXBgIGFyZSBzcGVjaWZpZWRcbiAgICovXG4gIHJlYWRvbmx5IHJ1bnNPbkdyb3VwPzogR3JvdXBSdW5uZXJPcHRpb25zO1xuXG4gIC8qKlxuICAgKiBQZXJtaXNzaW9ucyBncmFudGVkIHRvIHRoZSB1cGdyYWRlIGpvYlxuICAgKiBUbyBsaW1pdCBqb2IgcGVybWlzc2lvbnMgZm9yIGBjb250ZW50c2AsIHRoZSBkZXNpcmVkIHBlcm1pc3Npb25zIGhhdmUgdG8gYmUgZXhwbGljaXRseSBzZXQsIGUuZy46IGB7IGNvbnRlbnRzOiBKb2JQZXJtaXNzaW9uLk5PTkUgfWBcbiAgICogQGRlZmF1bHQgYHsgY29udGVudHM6IEpvYlBlcm1pc3Npb24uUkVBRCB9YFxuICAgKi9cbiAgcmVhZG9ubHkgcGVybWlzc2lvbnM/OiBKb2JQZXJtaXNzaW9ucztcblxuICAvKipcbiAgICogQnVpbGQgZW52aXJvbm1lbnQgdmFyaWFibGVzIGZvciB0aGUgdXBncmFkZSBqb2IuXG4gICAqXG4gICAqIEBkZWZhdWx0IHt9XG4gICAqL1xuICByZWFkb25seSBlbnY/OiB7IFtrZXk6IHN0cmluZ106IHN0cmluZyB9O1xufVxuXG4vKipcbiAqIEhvdyBvZnRlbiB0byBjaGVjayBmb3IgbmV3IHZlcnNpb25zIGFuZCByYWlzZSBwdWxsIHJlcXVlc3RzIGZvciB2ZXJzaW9uIHVwZ3JhZGVzLlxuICovXG5leHBvcnQgY2xhc3MgVXBncmFkZURlcGVuZGVuY2llc1NjaGVkdWxlIHtcbiAgLyoqXG4gICAqIERpc2FibGVzIGF1dG9tYXRpYyB1cGdyYWRlcy5cbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgcmVhZG9ubHkgTkVWRVIgPSBuZXcgVXBncmFkZURlcGVuZGVuY2llc1NjaGVkdWxlKFtdKTtcblxuICAvKipcbiAgICogQXQgMDA6MDAuXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIHJlYWRvbmx5IERBSUxZID0gbmV3IFVwZ3JhZGVEZXBlbmRlbmNpZXNTY2hlZHVsZShbXCIwIDAgKiAqICpcIl0pO1xuXG4gIC8qKlxuICAgKiBBdCAwMDowMCBvbiBldmVyeSBkYXktb2Ytd2VlayBmcm9tIE1vbmRheSB0aHJvdWdoIEZyaWRheS5cbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgcmVhZG9ubHkgV0VFS0RBWSA9IG5ldyBVcGdyYWRlRGVwZW5kZW5jaWVzU2NoZWR1bGUoW1xuICAgIFwiMCAwICogKiAxLTVcIixcbiAgXSk7XG5cbiAgLyoqXG4gICAqIEF0IDAwOjAwIG9uIE1vbmRheS5cbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgcmVhZG9ubHkgV0VFS0xZID0gbmV3IFVwZ3JhZGVEZXBlbmRlbmNpZXNTY2hlZHVsZShbXG4gICAgXCIwIDAgKiAqIDFcIixcbiAgXSk7XG5cbiAgLyoqXG4gICAqIEF0IDAwOjAwIG9uIGRheS1vZi1tb250aCAxLlxuICAgKi9cbiAgcHVibGljIHN0YXRpYyByZWFkb25seSBNT05USExZID0gbmV3IFVwZ3JhZGVEZXBlbmRlbmNpZXNTY2hlZHVsZShbXG4gICAgXCIwIDAgMSAqICpcIixcbiAgXSk7XG5cbiAgLyoqXG4gICAqIENyZWF0ZSBhIHNjaGVkdWxlIGZyb20gYSByYXcgY3JvbiBleHByZXNzaW9uLlxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBleHByZXNzaW9ucyhjcm9uOiBzdHJpbmdbXSkge1xuICAgIHJldHVybiBuZXcgVXBncmFkZURlcGVuZGVuY2llc1NjaGVkdWxlKGNyb24pO1xuICB9XG5cbiAgcHJpdmF0ZSBjb25zdHJ1Y3RvcihwdWJsaWMgcmVhZG9ubHkgY3Jvbjogc3RyaW5nW10pIHt9XG59XG5cbi8qKlxuICogQ29udmVydCBkYXlzIHRvIG1pbnV0ZXMuXG4gKi9cbmZ1bmN0aW9uIGRheXNUb01pbnV0ZXMoZGF5czogbnVtYmVyKTogbnVtYmVyIHtcbiAgcmV0dXJuIGRheXMgKiAxNDQwO1xufVxuXG4vKipcbiAqIENvbnZlcnQgZGF5cyB0byBzZWNvbmRzLlxuICovXG5mdW5jdGlvbiBkYXlzVG9TZWNvbmRzKGRheXM6IG51bWJlcik6IG51bWJlciB7XG4gIHJldHVybiBkYXlzICogODY0MDA7XG59XG5cbi8qKlxuICogQ29udmVydCBkYXlzIHRvIG1pbGxpc2Vjb25kcy5cbiAqL1xuZnVuY3Rpb24gZGF5c1RvTWlsbGlzZWNvbmRzKGRheXM6IG51bWJlcik6IG51bWJlciB7XG4gIHJldHVybiBkYXlzICogODY0MDAwMDA7XG59XG4iXX0=