UNPKG

projen

Version:

CDK for software projects

442 lines • 69.6 kB
"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