projen
Version:
CDK for software projects
442 lines • 69.6 kB
JavaScript
"use strict";
var _a, _b;
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 runner_options_1 = require("../runner-options");
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 {
constructor(project, options = {}) {
super(project);
/**
* The workflows that execute the upgrades. One workflow per branch.
*/
this.workflows = [];
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" };
// 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 [{ exec: "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({ exec: 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({
exec: this.renderUpgradePackagesCommand(includeForPackageManagerUpgrade),
});
// 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 = {}) {
function executeCommand(packageManager) {
switch (packageManager) {
case javascript_1.NodePackageManager.NPM:
case javascript_1.NodePackageManager.YARN:
case javascript_1.NodePackageManager.YARN_CLASSIC:
return "npx";
case javascript_1.NodePackageManager.PNPM:
return "pnpm dlx";
case javascript_1.NodePackageManager.YARN2:
case javascript_1.NodePackageManager.YARN_BERRY:
return "yarn dlx";
case javascript_1.NodePackageManager.BUN:
return "bunx";
}
}
const command = [
`${executeCommand(this.project.package.packageManager)} npm-check-updates@18`,
];
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.join(" ");
}
/**
* 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:
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.join(" ");
};
}
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");
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 } : {}),
};
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,
...(0, runner_options_1.filteredRunsOnOptions)(this.options.workflowOptions?.runsOn, this.options.workflowOptions?.runsOnGroup),
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";
return {
job: github_1.WorkflowJobs.pullRequestFromPatch({
patch: {
jobId: upgrade.jobId,
outputName: PATCH_CREATED_OUTPUT,
ref: upgrade.ref,
},
workflowName: workflow.name,
credentials,
...(0, runner_options_1.filteredRunsOnOptions)(this.options.workflowOptions?.runsOn, this.options.workflowOptions?.runsOnGroup),
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;
_a = JSII_RTTI_SYMBOL_1;
UpgradeDependencies[_a] = { fqn: "projen.javascript.UpgradeDependencies", version: "0.99.16" };
/**
* How often to check for new versions and raise pull requests for version upgrades.
*/
class UpgradeDependenciesSchedule {
/**
* Create a schedule from a raw cron expression.
*/
static expressions(cron) {
return new UpgradeDependenciesSchedule(cron);
}
constructor(cron) {
this.cron = cron;
}
}
exports.UpgradeDependenciesSchedule = UpgradeDependenciesSchedule;
_b = JSII_RTTI_SYMBOL_1;
UpgradeDependenciesSchedule[_b] = { fqn: "projen.javascript.UpgradeDependenciesSchedule", version: "0.99.16" };
/**
* Disables automatic upgrades.
*/
UpgradeDependenciesSchedule.NEVER = new UpgradeDependenciesSchedule([]);
/**
* At 00:00.
*/
UpgradeDependenciesSchedule.DAILY = new UpgradeDependenciesSchedule(["0 0 * * *"]);
/**
* At 00:00 on every day-of-week from Monday through Friday.
*/
UpgradeDependenciesSchedule.WEEKDAY = new UpgradeDependenciesSchedule([
"0 0 * * 1-5",
]);
/**
* At 00:00 on Monday.
*/
UpgradeDependenciesSchedule.WEEKLY = new UpgradeDependenciesSchedule([
"0 0 * * 1",
]);
/**
* At 00:00 on day-of-month 1.
*/
UpgradeDependenciesSchedule.MONTHLY = new UpgradeDependenciesSchedule([
"0 0 1 * *",
]);
/**
* 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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXBncmFkZS1kZXBlbmRlbmNpZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvamF2YXNjcmlwdC91cGdyYWRlLWRlcGVuZGVuY2llcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUFBLDRDQUF5QztBQUN6QyxrREFBaUQ7QUFDakQsc0NBUW1CO0FBQ25CLGlDQUEyRDtBQUMzRCxtREFBa0U7QUFDbEUsaURBQXVFO0FBQ3ZFLGlFQUE2RDtBQUM3RCwrREFLbUM7QUFDbkMsOENBQWdFO0FBQ2hFLHdDQUFxQztBQUNyQyxzREFBOEU7QUFHOUUsdUNBQXNEO0FBRXRELE1BQU0sb0JBQW9CLEdBQUcsY0FBYyxDQUFDO0FBQzVDLE1BQU0sb0JBQW9CLEdBQUcsZUFBZSxDQUFDO0FBZ0k3Qzs7R0FFRztBQUNILE1BQWEsbUJBQW9CLFNBQVEscUJBQVM7SUFrQ2hELFlBQVksT0FBb0IsRUFBRSxVQUFzQyxFQUFFO1FBQ3hFLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQztRQWxDakI7O1dBRUc7UUFDYSxjQUFTLEdBQXFCLEVBQUUsQ0FBQztRQWlDL0MsSUFBSSxDQUFDLE9BQU8sR0FBRyxPQUFPLENBQUM7UUFDdkIsSUFBSSxDQUFDLE9BQU8sR0FBRyxPQUFPLENBQUM7UUFFdkIsb0JBQW9CO1FBQ3BCLElBQ0UsT0FBTyxDQUFDLFFBQVEsS0FBSyxTQUFTO1lBQzlCLENBQUMsQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsSUFBSSxPQUFPLENBQUMsUUFBUSxHQUFHLENBQUMsQ0FBQyxFQUM3RCxDQUFDO1lBQ0QsTUFBTSxJQUFJLEtBQUssQ0FDYix3RUFBd0UsQ0FDekUsQ0FBQztRQUNKLENBQUM7UUFFRCx3Q0FBd0M7UUFDeEMsSUFBSSxPQUFPLENBQUMsUUFBUSxJQUFJLElBQUEsb0JBQWEsRUFBQyxPQUFPLENBQUMsT0FBTyxDQUFDLGNBQWMsQ0FBQyxFQUFFLENBQUM7WUFDdEUsTUFB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QUksMkJBQTJCLENBQUM7SUFDL0QsV0FBVztDQUNaLENBQUMsQ0FBQztBQVlMOztHQUVHO0FBQ0gsU0FBUyxhQUFhLENBQUMsSUFBWTtJQUNqQyxPQUFPLElBQUksR0FBRyxJQUFJLENBQUM7QUFDckIsQ0FBQztBQUVEOztHQUVHO0FBQ0gsU0FBUyxhQUFhLENBQUMsSUFBWTtJQUNqQyxPQUFPLElBQUksR0FBRyxLQUFLLENBQUM7QUFDdEIsQ0FBQztBQUVEOztHQUVHO0FBQ0gsU0FBUyxrQkFBa0IsQ0FBQyxJQUFZO0lBQ3RDLE9BQU8sSUFBSSxHQUFHLFFBQVEsQ0FBQztBQUN6QixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ29tcG9uZW50IH0gZnJvbSBcIi4uL2NvbXBvbmVudFwiO1xuaW1wb3J0IHsgRGVwZW5kZW5jeVR5cGUgfSBmcm9tIFwiLi4vZGVwZW5kZW5jaWVzXCI7XG5pbXBvcnQge1xuICBHaXRodWJDcmVkZW50aWFscyxcbiAgR2l0SHViLFxuICBHaXRodWJXb3JrZmxvdyxcbiAgR2l0SWRlbnRpdHksXG4gIHdvcmtmbG93cyxcbiAgV29ya2Zsb3dKb2JzLFxuICBXb3JrZmxvd1N0ZXBzLFxufSBmcm9tIFwiLi4vZ2l0aHViXCI7XG5pbXBvcnQgeyBpc1lhcm5DbGFzc2ljLCBpc1lhcm5CZXJyeSwgaXNOcG0gfSBmcm9tIFwiLi91dGlsXCI7XG5pbXBvcnQgeyBERUZBVUxUX0dJVEhVQl9BQ1RJT05TX1VTRVIgfSBmcm9tIFwiLi4vZ2l0aHViL2NvbnN0YW50c1wiO1xuaW1wb3J0IHsgcHJvamVjdFBhdGhSZWxhdGl2ZVRvUmVwb1Jvb3QgfSBmcm9tIFwiLi4vZ2l0aHViL3ByaXZhdGUvdXRpbFwiO1xuaW1wb3J0IHsgV29ya2Zsb3dBY3Rpb25zIH0gZnJvbSBcIi4uL2dpdGh1Yi93b3JrZmxvdy1hY3Rpb25zXCI7XG5pbXBvcnQge1xuICBDb250YWluZXJPcHRpb25zLFxuICBKb2JTdGVwLFxuICBKb2JQZXJtaXNzaW9uLFxuICBKb2JQZXJtaXNzaW9ucyxcbn0gZnJvbSBcIi4uL2dpdGh1Yi93b3JrZmxvd3MtbW9kZWxcIjtcbmltcG9ydCB7IE5vZGVQYWNrYWdlTWFuYWdlciwgTm9kZVByb2plY3QgfSBmcm9tIFwiLi4vamF2YXNjcmlwdFwiO1xuaW1wb3J0IHsgUmVsZWFzZSB9IGZyb20gXCIuLi9yZWxlYXNlXCI7XG5pbXBvcnQgeyBHcm91cFJ1bm5lck9wdGlvbnMsIGZpbHRlcmVkUnVuc09uT3B0aW9ucyB9IGZyb20gXCIuLi9ydW5uZXItb3B0aW9uc1wiO1xuaW1wb3J0IHsgVGFzayB9IGZyb20gXCIuLi90YXNrXCI7XG5pbXBvcnQgeyBUYXNrU3RlcCB9IGZyb20gXCIuLi90YXNrLW1vZGVsXCI7XG5pbXBvcnQgeyB3b3JrZmxvd05hbWVGb3JQcm9qZWN0IH0gZnJvbSBcIi4uL3V0aWwvbmFtZVwiO1xuXG5jb25zdCBDUkVBVEVfUEFUQ0hfU1RFUF9JRCA9IFwiY3JlYXRlX3BhdGNoXCI7XG5jb25zdCBQQVRDSF9DUkVBVEVEX09VVFBVVCA9IFwicGF0Y2hfY3JlYXRlZFwiO1xuXG4vKipcbiAqIE9wdGlvbnMgZm9yIGBVcGdyYWRlRGVwZW5kZW5jaWVzYC5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBVcGdyYWRlRGVwZW5kZW5jaWVzT3B0aW9ucyB7XG4gIC8qKlxuICAgKiBMaXN0IG9mIHBhY2thZ2UgbmFtZXMgdG8gZXhjbHVkZSBkdXJpbmcgdGhlIHVwZ3JhZGUuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gTm90aGluZyBpcyBleGNsdWRlZC5cbiAgICovXG4gIHJlYWRvbmx5IGV4Y2x1ZGU/OiBzdHJpbmdbXTtcblxuICAvKipcbiAgICogTGlzdCBvZiBwYWNrYWdlIG5hbWVzIHRvIGluY2x1ZGUgZHVyaW5nIHRoZSB1cGdyYWRlLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIEV2ZXJ5dGhpbmcgaXMgaW5jbHVkZWQuXG4gICAqL1xuICByZWFkb25seSBpbmNsdWRlPzogc3RyaW5nW107XG5cbiAgLyoqXG4gICAqIERldGVybWluZXMgdGhlIHRhcmdldCB2ZXJzaW9uIHRvIHVwZ3JhZGUgZGVwZW5kZW5jaWVzIHRvLlxuICAgKlxuICAgKiBAc2VlIGh0dHBzOi8vZ2l0aHViLmNvbS9yYWluZW9yc2hpbmUvbnBtLWNoZWNrLXVwZGF0ZXMjdGFyZ2V0XG4gICAqXG4gICAqIEBkZWZhdWx0IFwibWlub3JcIlxuICAgKi9cbiAgcmVhZG9ubHkgdGFyZ2V0Pzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBDaGVjayBwZWVyIGRlcGVuZGVuY2llcyBvZiBpbnN0YWxsZWQgcGFja2FnZXMgYW5kIGZpbHRlciB1cGRhdGVzIHRvIGNvbXBhdGlibGUgdmVyc2lvbnMuXG4gICAqXG4gICAqIEJ5IGRlZmF1bHQsIHRoZSB1cGdyYWRlIHdvcmtmbG93IHdpbGwgYWRoZXJlIHRvIHZlcnNpb24gY29uc3RyYWludHMgZnJvbSBwZWVyIGRlcGVuZGVuY2llcy5cbiAgICogU29tZXRpbWVzIHRoaXMgaXMgbm90IGRlc2lyYWJsZSBhbmQgY2FuIGJlIGRpc2FibGVkLlxuICAgKlxuICAgKiBAc2VlIGh0dHBzOi8vZ2l0aHViLmNvbS9yYWluZW9yc2hpbmUvbnBtLWNoZWNrLXVwZGF0ZXMjcGVlclxuICAgKlxuICAgKiBAZGVmYXVsdCB0cnVlXG4gICAqL1xuICByZWFkb25seSBzYXRpc2Z5UGVlckRlcGVuZGVuY2llcz86IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIEluY2x1ZGUgZGVwcmVjYXRlZCBwYWNrYWdlcy5cbiAgICpcbiAgICogQnkgZGVmYXVsdCwgZGVwcmVjYXRlZCB2ZXJzaW9ucyB3aWxsIGJlIGV4Y2x1ZGVkIGZyb20gdXBncmFkZXMuXG4gICAqXG4gICAqIEBzZWUgaHR0cHM6Ly9naXRodWIuY29tL3JhaW5lb3JzaGluZS9ucG0tY2hlY2stdXBkYXRlcz90YWI9cmVhZG1lLW92LWZpbGUjb3B0aW9uc1xuICAgKlxuICAgKiBAZGVmYXVsdCBmYWxzZVxuICAgKi9cbiAgcmVhZG9ubHkgaW5jbHVkZURlcHJlY2F0ZWRWZXJzaW9ucz86IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIEluY2x1ZGUgYSBnaXRodWIgd29ya2Zsb3cgZm9yIGNyZWF0aW5nIFBSJ3MgdGhhdCB1cGdyYWRlcyB0aGVcbiAgICogcmVxdWlyZWQgZGVwZW5kZW5jaWVzLCBlaXRoZXIgYnkgbWFudWFsIGRpc3BhdGNoLCBvciBieSBhIHNjaGVkdWxlLlxuICAgKlxuICAgKiBJZiB0aGlzIGlzIGBmYWxzZWAsIG9ubHkgYSBsb2NhbCBwcm9qZW4gdGFzayBpcyBjcmVhdGVkLCB3aGljaCBjYW4gYmUgZXhlY3V0ZWQgbWFudWFsbHkgdG9cbiAgICogdXBncmFkZSB0aGUgZGVwZW5kZW5jaWVzLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIHRydWUgZm9yIHJvb3QgcHJvamVjdHMsIGZhbHNlIGZvciBzdWJwcm9qZWN0cy5cbiAgICovXG4gIHJlYWRvbmx5IHdvcmtmbG93PzogYm9vbGVhbjtcblxuICAvKipcbiAgICogT3B0aW9ucyBmb3IgdGhlIGdpdGh1YiB3b3JrZmxvdy4gT25seSBhcHBsaWVzIGlmIGB3b3JrZmxvd2AgaXMgdHJ1ZS5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBkZWZhdWx0IG9wdGlvbnMuXG4gICAqL1xuICByZWFkb25seSB3b3JrZmxvd09wdGlvbnM/OiBVcGdyYWRlRGVwZW5kZW5jaWVzV29ya2Zsb3dPcHRpb25zO1xuXG4gIC8qKlxuICAgKiBUaGUgbmFtZSBvZiB0aGUgdGFzayB0aGF0IHdpbGwgYmUgY3JlYXRlZC5cbiAgICogVGhpcyB3aWxsIGFsc28gYmUgdGhlIHdvcmtmbG93IG5hbWUuXG4gICAqXG4gICAqIEBkZWZhdWx0IFwidXBncmFkZVwiLlxuICAgKi9cbiAgcmVhZG9ubHkgdGFza05hbWU/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRpdGxlIG9mIHRoZSBwdWxsIHJlcXVlc3QgdG8gdXNlIChzaG91bGQgYmUgYWxsIGxvd2VyLWNhc2UpLlxuICAgKlxuICAgKiBAZGVmYXVsdCBcInVwZ3JhZGUgZGVwZW5kZW5jaWVzXCJcbiAgICovXG4gIHJlYWRvbmx5IHB1bGxSZXF1ZXN0VGl0bGU/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSBzZW1hbnRpYyBjb21taXQgdHlwZS5cbiAgICpcbiAgICogQGRlZmF1bHQgJ2Nob3JlJ1xuICAgKi9cbiAgcmVhZG9ubHkgc2VtYW50aWNDb21taXQ/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIEFkZCBTaWduZWQtb2ZmLWJ5IGxpbmUgYnkgdGhlIGNvbW1pdHRlciBhdCB0aGUgZW5kIG9mIHRoZSBjb21taXQgbG9nIG1lc3NhZ2UuXG4gICAqXG4gICAqIEBkZWZhdWx0IHRydWVcbiAgICovXG4gIHJlYWRvbmx5IHNpZ25vZmY/OiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBTcGVjaWZ5IHdoaWNoIGRlcGVuZGVuY3kgdHlwZXMgdGhlIHVwZ3JhZGUgc2hvdWxkIG9wZXJhdGUgb24uXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gQWxsIGRlcGVuZGVuY3kgdHlwZXMuXG4gICAqL1xuICByZWFkb25seSB0eXBlcz86IERlcGVuZGVuY3lUeXBlW107XG5cbiAgLyoqXG4gICAqIEV4Y2x1ZGUgcGFja2FnZSB2ZXJzaW9ucyBwdWJsaXNoZWQgd2l0aGluIHRoZSBzcGVjaWZpZWQgbnVtYmVyIG9mIGRheXMuXG4gICAqXG4gICAqIFRoaXMgbWF5IHByb3ZpZGUgc29tZSBwcm90ZWN0aW9uIGFnYWluc3Qgc3VwcGx5IGNoYWluIGF0dGFja3MsIHNpbXBseSBieSBhdm9pZGluZ1xuICAgKiBuZXdseSBwdWJsaXNoZWQgcGFja2FnZXMgdGhhdCBtYXkgYmUgbWFsaWNpb3VzLiBJdCBnaXZlcyB0aGUgZWNvc3lzdGVtIG1vcmUgdGltZVxuICAgKiB0byBkZXRlY3QgbWFsaWNpb3VzIHBhY2thZ2VzLiBIb3dldmVyIGl0IGNvbWVzIGF0IHRoZSBjb3N0IG9mIHVwZGF0aW5nIG90aGVyXG4gICAqIHBhY2thZ2VzIHNsb3dlciwgd2hpY2ggbWlnaHQgYWxzbyBjb250YWluIHZ1bG5lcmFiaWxpdGllcyBvciBidWdzIGluIG5lZWQgb2YgYSBmaXguXG4gICAqXG4gICAqIFRoZSBjb29sZG93biBwZXJpb2QgYXBwbGllcyB0byBib3RoIG5wbS1jaGVjay11cGRhdGVzIGRpc2NvdmVyeVxuICAgKiBhbmQgdGhlIHBhY2thZ2UgbWFuYWdlciB1cGRhdGUgY29tbWFuZC5cbiAgICpcbiAgICogQHNlZSBodHRwczovL2dpdGh1Yi5jb20vcmFpbmVvcnNoaW5lL25wbS1jaGVjay11cGRhdGVzI2Nvb2xkb3duXG4gICAqIEBzZWUgaHR0cHM6Ly9kb2NzLm5wbWpzLmNvbS9jbGkvdjExL2NvbW1hbmRzL25wbS11cGRhdGUjYmVmb3JlXG4gICAqIEBzZWUgaHR0cHM6Ly9wbnBtLmlvL3NldHRpbmdzI21pbmltdW1yZWxlYXNlYWdlXG4gICAqIEBzZWUgaHR0cHM6Ly9idW4uY29tL2RvY3MvcG0vY2xpL2luc3RhbGwjbWluaW11bS1yZWxlYXNlLWFnZVxuICAgKiBAc2VlIGh0dHBzOi8veWFybnBrZy5jb20vY29uZmlndXJhdGlvbi95YXJucmMjbnBtTWluaW1hbEFnZUdhdGVcbiAgICpcbiAgICogQGRlZmF1bHQgLSBObyBjb29sZG93biBwZXJpb2QuXG4gICAqL1xuICByZWFkb25seSBjb29sZG93bj86IG51bWJlcjtcbn1cblxuLyoqXG4gKiBVcGdyYWRlIG5vZGUgcHJvamVjdCBkZXBlbmRlbmNpZXMuXG4gKi9cbmV4cG9ydCBjbGFzcyBVcGdyYWRlRGVwZW5kZW5jaWVzIGV4dGVuZHMgQ29tcG9uZW50IHtcbiAgLyoqXG4gICAqIFRoZSB3b3JrZmxvd3MgdGhhdCBleGVjdXRlIHRoZSB1cGdyYWRlcy4gT25lIHdvcmtmbG93IHBlciBicmFuY2guXG4gICAqL1xuICBwdWJsaWMgcmVhZG9ubHkgd29ya2Zsb3dzOiBHaXRodWJXb3JrZmxvd1tdID0gW107XG5cbiAgcHVibGljIHJlYWRvbmx5IHByb2plY3Q6IE5vZGVQcm9qZWN0O1xuXG4gIHByaXZhdGUgcmVhZG9ubHkgb3B0aW9uczogVXBncmFkZURlcGVuZGVuY2llc09wdGlvbnM7XG4gIHByaXZhdGUgcmVhZG9ubHkgcHVsbFJlcXVlc3RUaXRsZTogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBDb250YWluZXIgZGVmaW5pdGlvbnMgZm9yIHRoZSB1cGdyYWRlIHdvcmtmbG93LlxuICAgKi9cbiAgcHVibGljIGNvbnRhaW5lck9wdGlvbnM/OiBDb250YWluZXJPcHRpb25zO1xuXG4gIC8qKlxuICAgKiBUaGUgdXBncmFkZSB0YXNrLlxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IHVwZ3JhZGVUYXNrOiBUYXNrO1xuXG4gIC8qKlxuICAgKiBBIHRhc2sgcnVuIGFmdGVyIHRoZSB1cGdyYWRlIHRhc2suXG4gICAqL1xuICBwdWJsaWMgcmVhZG9ubHkgcG9zdFVwZ3JhZGVUYXNrOiBUYXNrO1xuXG4gIHByaXZhdGUgcmVhZG9ubHkgZ2l0SWRlbnRpdHk6IEdpdElkZW50aXR5O1xuICBwcml2YXRlIHJlYWRvbmx5IHBvc3RCdWlsZFN0ZXBzOiBKb2JTdGVwW107XG4gIHByaXZhdGUgcmVhZG9ubHkgcGVybWlzc2lvbnM6IEpvYlBlcm1pc3Npb25zO1xuICBwcml2YXRlIHJlYWRvbmx5IGRlcFR5cGVzOiBEZXBlbmRlbmN5VHlwZVtdO1xuICBwcml2YXRlIHJlYWRvbmx5IHVwZ3JhZGVUYXJnZXQ6IHN0cmluZztcbiAgcHJpdmF0ZSByZWFkb25seSBzYXRpc2Z5UGVlckRlcGVuZGVuY2llczogYm9vbGVhbjtcbiAgcHJpdmF0ZSByZWFkb25seSBpbmNsdWRlRGVwcmVjYXRlZFZlcnNpb25zOiBib29sZWFuO1xuXG4gIGNvbnN0cnVjdG9yKHByb2plY3Q6IE5vZGVQcm9qZWN0LCBvcHRpb25zOiBVcGdyYWRlRGVwZW5kZW5jaWVzT3B0aW9ucyA9IHt9KSB7XG4gICAgc3VwZXIocHJvamVjdCk7XG5cbiAgICB0aGlzLnByb2plY3QgPSBwcm9qZWN0O1xuICAgIHRoaXMub3B0aW9ucyA9IG9wdGlvbnM7XG5cbiAgICAvLyBWYWxpZGF0ZSBjb29sZG93blxuICAgIGlmIChcbiAgICAgIG9wdGlvbnMuY29vbGRvd24gIT09IHVuZGVmaW5lZCAmJlxuICAgICAgKCFOdW1iZXIuaXNJbnRlZ2VyKG9wdGlvbnMuY29vbGRvd24pIHx8IG9wdGlvbnMuY29vbGRvd24gPCAwKVxuICAgICkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBcIlRoZSAnY29vbGRvd24nIG9wdGlvbiBtdXN0IGJlIGEgbm9uLW5lZ2F0aXZlIGludGVnZXIgcmVwcmVzZW50aW5nIGRheXNcIixcbiAgICAgICk7XG4gICAgfVxuXG4gICAgLy8gWWFybiBjbGFzc2ljIGRvZXNuJ3Qgc3VwcG9ydCBjb29sZG93blxuICAgIGlmIChvcHRpb25zLmNvb2xkb3duICYmIGlzWWFybkNsYXNzaWMocHJvamVjdC5wYWNrYWdlLnBhY2thZ2VNYW5hZ2VyKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBcIlRoZSAnY29vbGRvd24nIG9wdGlvbiBpcyBub3Qgc3VwcG9ydGVkIHdpdGggeWFybiBjbGFzc2ljLiBcIiArXG4gICAgICAgICAgXCJDb25zaWRlciB1c2luZyBucG0sIHBucG0sIGJ1biwgb3IgeWFybiBiZXJyeSBpbnN0ZWFkLlwiLFxuICAgICAgKTtcbiAgICB9XG5cbiAgICB0aGlzLmRlcFR5cGVzID0gdGhpcy5vcHRpb25zLnR5cGVzID8/IFtcbiAgICAgIERlcGVuZGVuY3lUeXBlLkJVSUxELFxuICAgICAgRGVwZW5kZW5jeVR5cGUuQlVORExFRCxcbiAgICAgIERlcGVuZGVuY3lUeXBlLkRFVkVOVixcbiAgICAgIERlcGVuZGVuY3lUeXBlLlBFRVIsXG4gICAgICBEZXBlbmRlbmN5VHlwZS5SVU5USU1FLFxuICAgICAgRGVwZW5kZW5jeVR5cGUuVEVTVCxcbiAgICAgIERlcGVuZGVuY3lUeXBlLk9QVElPTkFMLFxuICAgIF07XG4gICAgdGhpcy51cGdyYWRlVGFyZ2V0ID0gdGhpcy5vcHRpb25zLnRhcmdldCA/PyBcIm1pbm9yXCI7XG4gICAgdGhpcy5zYXRpc2Z5UGVlckRlcGVuZGVuY2llcyA9IHRoaXMub3B0aW9ucy5zYXRpc2Z5UGVlckRlcGVuZGVuY2llcyA/PyB0cnVlO1xuICAgIHRoaXMuaW5jbHVkZURlcHJlY2F0ZWRWZXJzaW9ucyA9XG4gICAgICB0aGlzLm9wdGlvbnMuaW5jbHVkZURlcHJlY2F0ZWRWZXJzaW9ucyA/PyBmYWxzZTtcbiAgICB0aGlzLnB1bGxSZXF1ZXN0VGl0bGUgPSBvcHRpb25zLnB1bGxSZXF1ZXN0VGl0bGUgPz8gXCJ1cGdyYWRlIGRlcGVuZGVuY2llc1wiO1xuICAgIHRoaXMuZ2l0SWRlbnRpdHkgPVxuICAgICAgb3B0aW9ucy53b3JrZmxvd09wdGlvbnM/LmdpdElkZW50aXR5ID8/IERFRkFVTFRfR0lUSFVCX0FDVElPTlNfVVNFUjtcbiAgICB0aGlzLnBlcm1pc3Npb25zID0ge1xuICAgICAgY29udGVudHM6IEpvYlBlcm1pc3Npb24uUkVBRCxcbiAgICAgIC4uLm9wdGlvbnMud29ya2Zsb3dPcHRpb25zPy5wZXJtaXNzaW9ucyxcbiAgICB9O1xuICAgIHRoaXMucG9zdEJ1aWxkU3RlcHMgPSBbXTtcbiAgICB0aGlzLmNvbnRhaW5lck9wdGlvbnMgPSBvcHRpb25zLndvcmtmbG93T3B0aW9ucz8uY29udGFpbmVyO1xuXG4gICAgdGhpcy5wb3N0VXBncmFkZVRhc2sgPVxuICAgICAgcHJvamVjdC50YXNrcy50cnlGaW5kKFwicG9zdC11cGdyYWRlXCIpID8/XG4gICAgICBwcm9qZWN0LnRhc2tzLmFkZFRhc2soXCJwb3N0LXVwZ3JhZGVcIiwge1xuICAgICAgICBkZXNjcmlwdGlvbjogXCJSdW5zIGFmdGVyIHVwZ3JhZGluZyBkZXBlbmRlbmNpZXNcIixcbiAgICAgIH0pO1xuXG4gICAgY29uc3QgdGFza0VudjogUmVjb3JkPHN0cmluZywgc3RyaW5nPiA9IHsgQ0k6IFwiMFwiIH07XG5cbiAgICAvLyBTZXQgeWFybiBiZXJyeSBjb29sZG93biB2aWEgZW52aXJvbm1lbnQgdmFyaWFibGUsIGV4cGVjdHMgbWludXRlc1xuICAgIGlmIChvcHRpb25zLmNvb2xkb3duICYmIGlzWWFybkJlcnJ5KHByb2plY3QucGFja2FnZS5wYWNrYWdlTWFuYWdlcikpIHtcbiAgICAgIHRhc2tFbnYuWUFSTl9OUE1fTUlOSU1BTF9BR0VfR0FURSA9IFN0cmluZyhcbiAgICAgICAgZGF5c1RvTWludXRlcyhvcHRpb25zLmNvb2xkb3duKSxcbiAgICAgICk7XG4gICAgfVxuXG4gICAgLy8gU2V0IG5wbSBjb29sZG93biBkYXRlIHZpYSBlbnZpcm9ubWVudCB2YXJpYWJsZSAoY2FsY3VsYXRlZCBhdCBydW50aW1lKSwgZXhwZWN0cyBhIGRhdGUgaW4gSVNPIGZvcm1hdFxuICAgIGlmIChvcHRpb25zLmNvb2xkb3duICYmIGlzTnBtKHByb2plY3QucGFja2FnZS5wYWNrYWdlTWFuYWdlcikpIHtcbiAgICAgIHRhc2tFbnYuTlBNX0NPTkZJR19CRUZPUkUgPSBgJChub2RlIC1wIFwibmV3IERhdGUoRGF0ZS5ub3coKS0ke2RheXNUb01pbGxpc2Vjb25kcyhcbiAgICAgICAgb3B0aW9ucy5jb29sZG93bixcbiAgICAgICl9KS50b0lTT1N0cmluZygpXCIpYDtcbiAgICB9XG5cbiAgICB0aGlzLnVwZ3JhZGVUYXNrID0gcHJvamVjdC5hZGRUYXNrKG9wdGlvbnMudGFza05hbWUgPz8gXCJ1cGdyYWRlXCIsIHtcbiAgICAgIC8vIHRoaXMgdGFzayBzaG91bGQgbm90IHJ1biBpbiBDSSBtb2RlIGJlY2F1c2UgaXRzIGRlc2lnbmVkIHRvXG4gICAgICAvLyB1cGRhdGUgcGFja2FnZS5qc29uIGFuZCBsb2NrIGZpbGVzLlxuICAgICAgZW52OiB0YXNrRW52LFxuICAgICAgZGVzY3JpcHRpb246IHRoaXMucHVsbFJlcXVlc3RUaXRsZSxcbiAgICAgIHN0ZXBzOiB7IHRvSlNPTjogKCkgPT4gdGhpcy5yZW5kZXJUYXNrU3RlcHMoKSB9IGFzIGFueSxcbiAgICB9KTtcbiAgICB0aGlzLnVwZ3JhZGVUYXNrLmxvY2soKTsgLy8gdGhpcyB0YXNrIGlzIGEgbGF6eSB2YWx1ZSwgc28gbWFrZSBpdCByZWFkb25seVxuXG4gICAgLy8gYWx3YXlzIHVzZSB0aGUgR2l0SHViIG9mIHRoZSByb290IHByb2plY3QgLSB0aGVyZSBjYW4gb25seSBiZSBvbmVcbiAgICBjb25zdCBnaXRodWIgPSBHaXRIdWIub2YocHJvamVjdC5yb290KTtcblxuICAgIGlmICh0aGlzLnVwZ3JhZGVUYXNrICYmIGdpdGh1YiAmJiAob3B0aW9ucy53b3JrZmxvdyA/PyB0cnVlKSkge1xuICAgICAgaWYgKG9wdGlvbnMud29ya2Zsb3dPcHRpb25zPy5icmFuY2hlcykge1xuICAgICAgICBmb3IgKGNvbnN0IGJyYW5jaCBvZiBvcHRpb25zLndvcmtmbG93T3B0aW9ucy5icmFuY2hlcykge1xuICAgICAgICAgIHRoaXMud29ya2Zsb3dzLnB1c2goXG4gICAgICAgICAgICB0aGlzLmNyZWF0ZVdvcmtmbG93KHRoaXMudXBncmFkZVRhc2ssIGdpdGh1YiwgYnJhbmNoKSxcbiAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICB9IGVsc2UgaWYgKFJlbGVhc2Uub2YocHJvamVjdCkpIHtcbiAgICAgICAgY29uc3QgcmVsZWFzZSA9IFJlbGVhc2Uub2YocHJvamVjdCkhO1xuICAgICAgICByZWxlYXNlLl9mb3JFYWNoQnJhbmNoKChicmFuY2g6IHN0cmluZykgPT4ge1xuICAgICAgICAgIHRoaXMud29ya2Zsb3dzLnB1c2goXG4gICAgICAgICAgICB0aGlzLmNyZWF0ZVdvcmtmbG93KHRoaXMudXBncmFkZVRhc2ssIGdpdGh1YiwgYnJhbmNoKSxcbiAgICAgICAgICApO1xuICAgICAgICB9KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIHJlcHJlc2VudHMgdGhlIGRlZmF1bHQgcmVwb3NpdG9yeSBicmFuY2guXG4gICAgICAgIC8vIGp1c3QgbGlrZSBub3Qgc3BlY2lmeWluZyBhbnl0aGluZy5cbiAgICAgICAgY29uc3QgZGVmYXVsdEJyYW5jaCA9IHVuZGVmaW5lZDtcbiAgICAgICAgdGhpcy53b3JrZmxvd3MucHVzaChcbiAgICAgICAgICB0aGlzLmNyZWF0ZVdvcmtmbG93KHRoaXMudXBncmFkZVRhc2ssIGdpdGh1YiwgZGVmYXVsdEJyYW5jaCksXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEFkZCBzdGVwcyB0byBleGVjdXRlIGEgc3VjY2Vzc2Z1bCBidWlsZC5cbiAgICogQHBhcmFtIHN0ZXBzIHdvcmtmbG93IHN0ZXBzXG4gICAqL1xuICBwdWJsaWMgYWRkUG9zdEJ1aWxkU3RlcHMoLi4uc3RlcHM6IEpvYlN0ZXBbXSkge1xuICAgIHRoaXMucG9zdEJ1aWxkU3RlcHMucHVzaCguLi5zdGVwcyk7XG4gIH1cblxuICBwcml2YXRlIHJlbmRlclRhc2tTdGVwcygpOiBUYXNrU3RlcFtdIHtcbiAgICBjb25zdCBzdGVwcyA9IG5ldyBBcnJheTxUYXNrU3RlcD4oKTtcblxuICAgIC8vIFBhY2thZ2UgTWFuYWdlciB1cGdyYWRlIHNob3VsZCBhbHdheXMgaW5jbHVkZSBhbGwgZGVwc1xuICAgIGNvbnN0IGluY2x1ZGVGb3JQYWNrYWdlTWFuYWdlclVwZ3JhZGUgPSB0aGlzLmJ1aWxkRGVwZW5kZW5jeUxpc3QodHJ1ZSk7XG4gICAgaWYgKGluY2x1ZGVGb3JQYWNrYWdlTWFuYWdlclVwZ3JhZGUubGVuZ3RoID09PSAwKSB7XG4gICAgICByZXR1cm4gW3sgZXhlYzogXCJlY2hvIE5vIGRlcGVuZGVuY2llcyB0byB1cGdyYWRlLlwiIH1dO1xuICAgIH1cblxuICAgIC8vIFJlbW92aW5nIGBucG0tY2hlY2stdXBkYXRlc2AgZnJvbSBvdXIgZGVwZW5kZW5jeSB0cmVlIGJlY2F1c2UgaXQgZGVwZW5kcyBvbiBhIHBhY2thZ2VcbiAgICAvLyB0aGF0IHVzZXMgYW4gbnBtLXNwZWNpZmljIGZlYXR1cmUgdGhhdCBjYXVzZXMgYW4gaW52YWxpZCBkZXBlbmRlbmN5IHRyZWUgd2hlbiB1c2luZyBZYXJuIDEuXG4gICAgLy8gU2VlIGh0dHBzOi8vZ2l0aHViLmNvbS9wcm9qZW4vcHJvam