@cloudcamp/aws-runtime
Version:
CloudCamp - Launch faster by building scalable infrastructure in few lines of code.
322 lines • 32.5 kB
JavaScript
"use strict";
var _a;
Object.defineProperty(exports, "__esModule", { value: true });
exports.App = void 0;
const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
const cdk = require("aws-cdk-lib/core");
const _ = require("lodash");
const pipeline_1 = require("./pipeline");
const stage_1 = require("./stage");
const utils_1 = require("./utils");
const constants_1 = require("./constants");
const ssm = require("aws-cdk-lib/aws-ssm");
const pipelines = require("aws-cdk-lib/pipelines");
const stack_1 = require("./stack");
/**
* (experimental) App represents your application running in the cloud․ Every app contains one or more ``{@link Stack | Stacks}``, which you can use to add your own resources, like a ``{@link WebService | WebService}`` or a ``{@link Database | Database}``.
*
* An app can be as big or small as you like - from a single webserver to
* dozens of load-balanced instances serving different parts of your
* application.
*
* This example adds a ``{@link WebService | WebService}`` to the
* ``{@link App.production | production}`` stack:
*
* ```ts
* import { App, WebService } from "@cloudcamp/aws-runtime";
*
* let app = new App();
*
* new WebService(app.production, "prod-web", {
* dockerfile: "../Dockerfile"
* });
* ```
*
* @experimental
* @order 1
*/
class App extends cdk.App {
/**
* (experimental) Initialize your cloudcamp application.
*
* @experimental
* @remarks App is a singleton class - it is instantiated exactly once, before
* any other resources are created.
* @topic Initialization
*/
constructor() {
super({ autoSynth: true });
this.stages = new Map();
if (App.INSTANCE) {
throw new Error("App has already been instantiated.");
}
App.INSTANCE = this;
this.configuration = {
account: this.getContextOrThrow(constants_1.CONTEXT_KEY_ACCOUNT),
region: this.getContextOrThrow(constants_1.CONTEXT_KEY_REGION),
repository: this.getContextOrThrow(constants_1.CONTEXT_KEY_REPOSITORY),
name: this.getContextOrThrow(constants_1.CONTEXT_KEY_NAME),
branch: this.getContextOrThrow(constants_1.CONTEXT_KEY_BRANCH),
vpcId: this.getContextOrThrow(constants_1.CONTEXT_KEY_VPC),
repositoryTokenSecret: this.getContextOrThrow(constants_1.CONTEXT_REPOSITORY_TOKEN_SECRET),
};
cdk.Tags.of(this).add(constants_1.TAG_APP_NAME, this.configuration.name);
this.pipelineStack = this.setupCodePipeline();
//add pipelineStack to our global list of stacks
new ssm.StringParameter(this.pipelineStack, "ssm-stack", {
parameterName: `/cloudcamp/${App.instance.configuration.name}/_/stack/${_.kebabCase(this.pipelineStack.stackName)}`,
stringValue: this.pipelineStack.stackName,
});
// We need the name of the codepipeline for later use
new ssm.StringParameter(this.pipelineStack, "ssm-codepipeline", {
parameterName: `/cloudcamp/${this.configuration.name}/_/codepipeline`,
stringValue: this.pipelineStack.pipelineName,
});
// Also, we need to identify the pipeline stack
new ssm.StringParameter(this.pipelineStack, "ssm-pipeline-stack", {
parameterName: `/cloudcamp/${this.configuration.name}/_/pipeline-stack`,
stringValue: this.pipelineStack.stackName,
});
}
getContextOrThrow(key) {
let value = this.node.tryGetContext(key);
if (value == null) {
throw new Error("Missing config in cdk.json: " + key);
}
return value;
}
/**
* (experimental) Returns the global App singleton instance.
*
* Throws an exception if App has not been instantiated yet.
*
* @experimental
*/
static get instance() {
if (!App.INSTANCE) {
throw new Error("instance() called but App has not been instantiated yet.");
}
return App.INSTANCE;
}
/**
* (experimental) Use this stack for anything related to the network, for example DNS entries.
*
* @experimental
* @topic Stacks
* @remarks To deploy resources to the cloud, they are added to a ``Stack``.
* CloudCamp comes with three default stacks:
*/
get network() {
return this.getOrAddStage("network").stack;
}
/**
* (experimental) This stack can be used to create an environment for testing changes before deploying to production.
*
* @experimental
*/
get staging() {
return this.getOrAddStage("staging").stack;
}
/**
* (experimental) The production stack.
*
* @experimental
*/
get production() {
return this.getOrAddStage("production").stack;
}
/**
* (experimental) Get an existing stack by name.
*
* @param name The name of the stack.
* @experimental
* @topic Adding custom stacks
* @remarks In addition to the default stacks provided by cloudcamp, you can
* create your own stacks.
*/
getStack(name) {
try {
return this.getStage(name).stack;
}
catch (e) {
if (e.message.startsWith("Stage doesn't exist")) {
throw new Error("Stack doesn't exist: " + name);
}
else {
throw e;
}
}
}
/**
* (experimental) Add a new stack to your application.
*
* Pass a stack name to create a new, empty stack:
*
* ```ts
* void 0;
* import { App, WebService, Stack} from "@cloudcamp/aws-runtime";
* const app = new App();
* void 'show';
* const devStack = app.stack("development");
* ```
*
* @param name The name of the stack.
* @experimental
*/
stack(name) {
if (this.stages.get(name)) {
throw new Error("Stack already exists: " + name);
}
return this.getOrAddStage(name).stack;
}
getOrAddStage(id) {
let existingStage = this.stages.get(id);
if (existingStage) {
return existingStage;
}
let stage = new stage_1.Stage(this, _.upperFirst(_.camelCase(id)));
let stack = new stack_1.Stack(stage, id);
stage.stack = stack;
this.stages.set(id, stage);
return stage;
}
/**
* (experimental) Get an existing stage by name.
*
* Stages can be obtained by their name to modify their attributes. A common
* use case is to require manual approval to deploy to the production stage:
*
* ```ts
* const stage = app.getStage("production");
* stage.needsManualApproval = true;
* ```
*
* @param name The name of the stage.
* @experimental
* @topic Stages
* @remarks Stages are responsible for building your stacks. By default,
* CloudCamp creates a stage for each stack and gives it the same name. You
* can customize this behaviour by adding your own stages.
*/
getStage(name) {
if (name in ["network", "staging", "production"]) {
return this.getOrAddStage(name);
}
if (!this.stages.has(name)) {
throw new Error("Stage doesn't exist: " + name);
}
return this.stages.get(name);
}
/**
* (experimental) Add a new stage.
*
* This method can be used to add a stage with a custom ``Stack`` subclass.
* ```ts
* import { App, WebService, Stack } from "@cloudcamp/aws-runtime";
*
* class CustomStack extends Stack {
* constructor(scope: cdk.Construct, id: string, props: cdk.StackProps) {
* super(scope, id, props);
* new WebService(this, "web", {
* dockerfile: "../Dockerfile"
* });
* }
* }
*
* // later in the code...
* const app = new App();
* const stage = app.stage("dev");
* const stack = new CustomStack(stage, "dev");
*
* // stack is automatically set to the new stack we created
* if (stage.stack == stack) {
* // outputs "True!"
* console.log("True!");
* }
* ```
*
* @param name The name of the stage.
* @param stage An optional stage object.
* @experimental
*/
stage(name, stage) {
if (this.stages.has(name)) {
throw new Error("Stage already exists: " + name);
}
if (!stage) {
stage = new stage_1.Stage(this, _.upperFirst(_.camelCase(name)));
}
this.stages.set(name, stage);
return stage;
}
/**
* @experimental
* @ignore true
*/
get pipeline() {
return this.pipelineStack.pipeline;
}
setupCodePipeline() {
const repositoryUrl = this.configuration.repository;
const branch = this.configuration.branch;
let parsed = utils_1.parseRepositoryUrl(repositoryUrl);
let repositoryTokenSecretName = this.configuration.repositoryTokenSecret;
return new pipeline_1.PipelineStack(this, _.upperFirst(_.camelCase(this.configuration.name + "-pipeline")), {
appName: this.configuration.name,
repositoryTokenSecretName: repositoryTokenSecretName,
host: parsed.host,
owner: parsed.owner,
repo: parsed.repo,
branch: branch,
});
}
/**
* (experimental) Synthesize this stage into a cloud assembly.
*
* Once an assembly has been synthesized, it cannot be modified. Subsequent
* calls will return the same assembly.
*
* @experimental
* @ignore true
*/
synth(options) {
let names = Array.from(this.stages.keys());
names.sort((a, b) => {
switch (a) {
case "network":
if (b == "staging" || b == "production") {
return -1;
}
return 0;
case "staging":
if (b == "network") {
return 1;
}
if (b == "production") {
return -1;
}
return 0;
case "production":
if (b == "network" || b == "staging") {
return 1;
}
return 0;
default:
return 0;
}
});
for (let name of names) {
let stage = this.stages.get(name);
let pre = undefined;
if (stage.needsManualApproval) {
pre = [new pipelines.ManualApprovalStep("approve-" + name)];
}
this.pipeline.addStage(stage, { pre: pre });
}
return super.synth(options);
}
}
exports.App = App;
_a = JSII_RTTI_SYMBOL_1;
App[_a] = { fqn: "@cloudcamp/aws-runtime.App", version: "0.0.1" };
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXBwLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL2FwcC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUFBLHdDQUF3QztBQUN4Qyw0QkFBNEI7QUFDNUIseUNBQTJDO0FBQzNDLG1DQUFnQztBQUNoQyxtQ0FBNkM7QUFDN0MsMkNBU3FCO0FBQ3JCLDJDQUEyQztBQUUzQyxtREFBbUQ7QUFDbkQsbUNBQWdDOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFjaEMsTUFBYSxHQUFJLFNBQVEsR0FBRyxDQUFDLEdBQUc7Ozs7Ozs7OztJQUk5QjtRQUNFLEtBQUssQ0FBQyxFQUFFLFNBQVMsRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDO1FBa0dyQixXQUFNLEdBQXVCLElBQUksR0FBRyxFQUFFLENBQUM7UUFoRzdDLElBQUksR0FBRyxDQUFDLFFBQVEsRUFBRTtZQUNoQixNQUFNLElBQUksS0FBSyxDQUFDLG9DQUFvQyxDQUFDLENBQUM7U0FDdkQ7UUFFRCxHQUFHLENBQUMsUUFBUSxHQUFHLElBQUksQ0FBQztRQUVwQixJQUFJLENBQUMsYUFBYSxHQUFHO1lBQ25CLE9BQU8sRUFBRSxJQUFJLENBQUMsaUJBQWlCLENBQUMsK0JBQW1CLENBQUM7WUFDcEQsTUFBTSxFQUFFLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyw4QkFBa0IsQ0FBQztZQUNsRCxVQUFVLEVBQUUsSUFBSSxDQUFDLGlCQUFpQixDQUFDLGtDQUFzQixDQUFDO1lBQzFELElBQUksRUFBRSxJQUFJLENBQUMsaUJBQWlCLENBQUMsNEJBQWdCLENBQUM7WUFDOUMsTUFBTSxFQUFFLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyw4QkFBa0IsQ0FBQztZQUNsRCxLQUFLLEVBQUUsSUFBSSxDQUFDLGlCQUFpQixDQUFDLDJCQUFlLENBQUM7WUFDOUMscUJBQXFCLEVBQUUsSUFBSSxDQUFDLGlCQUFpQixDQUMzQywyQ0FBK0IsQ0FDaEM7U0FDRixDQUFDO1FBRUYsR0FBRyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUMsR0FBRyxDQUFDLHdCQUFZLEVBQUUsSUFBSSxDQUFDLGFBQWEsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUM3RCxJQUFJLENBQUMsYUFBYSxHQUFHLElBQUksQ0FBQyxpQkFBaUIsRUFBRSxDQUFDO1FBRTlDLGdEQUFnRDtRQUNoRCxJQUFJLEdBQUcsQ0FBQyxlQUFlLENBQUMsSUFBSSxDQUFDLGFBQWEsRUFBRSxXQUFXLEVBQUU7WUFDdkQsYUFBYSxFQUFFLGNBQ2IsR0FBRyxDQUFDLFFBQVEsQ0FBQyxhQUFhLENBQUMsSUFDN0IsWUFBWSxDQUFDLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsU0FBUyxDQUFDLEVBQUU7WUFDdkQsV0FBVyxFQUFFLElBQUksQ0FBQyxhQUFhLENBQUMsU0FBUztTQUMxQyxDQUFDLENBQUM7UUFFSCxxREFBcUQ7UUFDckQsSUFBSSxHQUFHLENBQUMsZUFBZSxDQUFDLElBQUksQ0FBQyxhQUFhLEVBQUUsa0JBQWtCLEVBQUU7WUFDOUQsYUFBYSxFQUFFLGNBQWMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxJQUFJLGlCQUFpQjtZQUNyRSxXQUFXLEVBQUUsSUFBSSxDQUFDLGFBQWEsQ0FBQyxZQUFZO1NBQzdDLENBQUMsQ0FBQztRQUVILCtDQUErQztRQUMvQyxJQUFJLEdBQUcsQ0FBQyxlQUFlLENBQUMsSUFBSSxDQUFDLGFBQWEsRUFBRSxvQkFBb0IsRUFBRTtZQUNoRSxhQUFhLEVBQUUsY0FBYyxJQUFJLENBQUMsYUFBYSxDQUFDLElBQUksbUJBQW1CO1lBQ3ZFLFdBQVcsRUFBRSxJQUFJLENBQUMsYUFBYSxDQUFDLFNBQVM7U0FDMUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVPLGlCQUFpQixDQUFDLEdBQVc7UUFDbkMsSUFBSSxLQUFLLEdBQVcsSUFBSSxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDakQsSUFBSSxLQUFLLElBQUksSUFBSSxFQUFFO1lBQ2pCLE1BQU0sSUFBSSxLQUFLLENBQUMsOEJBQThCLEdBQUcsR0FBRyxDQUFDLENBQUM7U0FDdkQ7UUFDRCxPQUFPLEtBQUssQ0FBQztJQUNmLENBQUM7Ozs7Ozs7O0lBR00sTUFBTSxLQUFLLFFBQVE7UUFDeEIsSUFBSSxDQUFDLEdBQUcsQ0FBQyxRQUFRLEVBQUU7WUFDakIsTUFBTSxJQUFJLEtBQUssQ0FDYiwwREFBMEQsQ0FDM0QsQ0FBQztTQUNIO1FBQ0QsT0FBTyxHQUFHLENBQUMsUUFBUSxDQUFDO0lBQ3RCLENBQUM7Ozs7Ozs7OztJQUdELElBQUksT0FBTztRQUNULE9BQU8sSUFBSSxDQUFDLGFBQWEsQ0FBQyxTQUFTLENBQUMsQ0FBQyxLQUFLLENBQUM7SUFDN0MsQ0FBQzs7Ozs7O0lBR0QsSUFBSSxPQUFPO1FBQ1QsT0FBTyxJQUFJLENBQUMsYUFBYSxDQUFDLFNBQVMsQ0FBQyxDQUFDLEtBQUssQ0FBQztJQUM3QyxDQUFDOzs7Ozs7SUFHRCxJQUFJLFVBQVU7UUFDWixPQUFPLElBQUksQ0FBQyxhQUFhLENBQUMsWUFBWSxDQUFDLENBQUMsS0FBSyxDQUFDO0lBQ2hELENBQUM7Ozs7Ozs7Ozs7SUFHTSxRQUFRLENBQUMsSUFBWTtRQUMxQixJQUFJO1lBQ0YsT0FBTyxJQUFJLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxDQUFDLEtBQUssQ0FBQztTQUNsQztRQUFDLE9BQU8sQ0FBQyxFQUFFO1lBQ1YsSUFBSyxDQUFXLENBQUMsT0FBTyxDQUFDLFVBQVUsQ0FBQyxxQkFBcUIsQ0FBQyxFQUFFO2dCQUMxRCxNQUFNLElBQUksS0FBSyxDQUFDLHVCQUF1QixHQUFHLElBQUksQ0FBQyxDQUFDO2FBQ2pEO2lCQUFNO2dCQUNMLE1BQU0sQ0FBQyxDQUFDO2FBQ1Q7U0FDRjtJQUNILENBQUM7Ozs7Ozs7Ozs7Ozs7Ozs7O0lBR00sS0FBSyxDQUFDLElBQVk7UUFDdkIsSUFBSSxJQUFJLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsRUFBRTtZQUN6QixNQUFNLElBQUksS0FBSyxDQUFDLHdCQUF3QixHQUFHLElBQUksQ0FBQyxDQUFDO1NBQ2xEO1FBQ0QsT0FBTyxJQUFJLENBQUMsYUFBYSxDQUFDLElBQUksQ0FBQyxDQUFDLEtBQUssQ0FBQztJQUN4QyxDQUFDO0lBSU8sYUFBYSxDQUFDLEVBQVU7UUFDOUIsSUFBSSxhQUFhLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDeEMsSUFBSSxhQUFhLEVBQUU7WUFDakIsT0FBTyxhQUFhLENBQUM7U0FDdEI7UUFDRCxJQUFJLEtBQUssR0FBRyxJQUFJLGFBQUssQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUMzRCxJQUFJLEtBQUssR0FBRyxJQUFJLGFBQUssQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFDakMsS0FBSyxDQUFDLEtBQUssR0FBRyxLQUFLLENBQUM7UUFDcEIsSUFBSSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsRUFBRSxFQUFFLEtBQUssQ0FBQyxDQUFDO1FBRTNCLE9BQU8sS0FBSyxDQUFDO0lBQ2YsQ0FBQzs7Ozs7Ozs7Ozs7Ozs7Ozs7OztJQUlNLFFBQVEsQ0FBQyxJQUFZO1FBQzFCLElBQUksSUFBSSxJQUFJLENBQUMsU0FBUyxFQUFFLFNBQVMsRUFBRSxZQUFZLENBQUMsRUFBRTtZQUNoRCxPQUFPLElBQUksQ0FBQyxhQUFhLENBQUMsSUFBSSxDQUFDLENBQUM7U0FDakM7UUFDRCxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLEVBQUU7WUFDMUIsTUFBTSxJQUFJLEtBQUssQ0FBQyx1QkFBdUIsR0FBRyxJQUFJLENBQUMsQ0FBQztTQUNqRDtRQUNELE9BQU8sSUFBSSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFFLENBQUM7SUFDaEMsQ0FBQzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0lBR00sS0FBSyxDQUFDLElBQVksRUFBRSxLQUFhO1FBQ3RDLElBQUksSUFBSSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLEVBQUU7WUFDekIsTUFBTSxJQUFJLEtBQUssQ0FBQyx3QkFBd0IsR0FBRyxJQUFJLENBQUMsQ0FBQztTQUNsRDtRQUNELElBQUksQ0FBQyxLQUFLLEVBQUU7WUFDVixLQUFLLEdBQUcsSUFBSSxhQUFLLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUM7U0FDMUQ7UUFDRCxJQUFJLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxJQUFJLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFDN0IsT0FBTyxLQUFLLENBQUM7SUFDZixDQUFDOzs7OztJQU9ELElBQVcsUUFBUTtRQUNqQixPQUFPLElBQUksQ0FBQyxhQUFhLENBQUMsUUFBUSxDQUFDO0lBQ3JDLENBQUM7SUFFTyxpQkFBaUI7UUFDdkIsTUFBTSxhQUFhLEdBQUcsSUFBSSxDQUFDLGFBQWEsQ0FBQyxVQUFVLENBQUM7UUFDcEQsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLGFBQWEsQ0FBQyxNQUFNLENBQUM7UUFDekMsSUFBSSxNQUFNLEdBQUcsMEJBQWtCLENBQUMsYUFBYSxDQUFDLENBQUM7UUFDL0MsSUFBSSx5QkFBeUIsR0FBRyxJQUFJLENBQUMsYUFBYSxDQUFDLHFCQUFxQixDQUFDO1FBQ3pFLE9BQU8sSUFBSSx3QkFBYSxDQUN0QixJQUFJLEVBQ0osQ0FBQyxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsSUFBSSxHQUFHLFdBQVcsQ0FBQyxDQUFDLEVBQ2hFO1lBQ0UsT0FBTyxFQUFFLElBQUksQ0FBQyxhQUFhLENBQUMsSUFBSTtZQUNoQyx5QkFBeUIsRUFBRSx5QkFBeUI7WUFDcEQsSUFBSSxFQUFFLE1BQU0sQ0FBQyxJQUFJO1lBQ2pCLEtBQUssRUFBRSxNQUFNLENBQUMsS0FBSztZQUNuQixJQUFJLEVBQUUsTUFBTSxDQUFDLElBQUk7WUFDakIsTUFBTSxFQUFFLE1BQU07U0FDZixDQUNGLENBQUM7SUFDSixDQUFDOzs7Ozs7Ozs7O0lBR0QsS0FBSyxDQUFDLE9BQW1DO1FBQ3ZDLElBQUksS0FBSyxHQUFHLEtBQUssQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDO1FBQzNDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUU7WUFDbEIsUUFBUSxDQUFDLEVBQUU7Z0JBQ1QsS0FBSyxTQUFTO29CQUNaLElBQUksQ0FBQyxJQUFJLFNBQVMsSUFBSSxDQUFDLElBQUksWUFBWSxFQUFFO3dCQUN2QyxPQUFPLENBQUMsQ0FBQyxDQUFDO3FCQUNYO29CQUNELE9BQU8sQ0FBQyxDQUFDO2dCQUNYLEtBQUssU0FBUztvQkFDWixJQUFJLENBQUMsSUFBSSxTQUFTLEVBQUU7d0JBQ2xCLE9BQU8sQ0FBQyxDQUFDO3FCQUNWO29CQUNELElBQUksQ0FBQyxJQUFJLFlBQVksRUFBRTt3QkFDckIsT0FBTyxDQUFDLENBQUMsQ0FBQztxQkFDWDtvQkFDRCxPQUFPLENBQUMsQ0FBQztnQkFDWCxLQUFLLFlBQVk7b0JBQ2YsSUFBSSxDQUFDLElBQUksU0FBUyxJQUFJLENBQUMsSUFBSSxTQUFTLEVBQUU7d0JBQ3BDLE9BQU8sQ0FBQyxDQUFDO3FCQUNWO29CQUNELE9BQU8sQ0FBQyxDQUFDO2dCQUNYO29CQUNFLE9BQU8sQ0FBQyxDQUFDO2FBQ1o7UUFDSCxDQUFDLENBQUMsQ0FBQztRQUNILEtBQUssSUFBSSxJQUFJLElBQUksS0FBSyxFQUFFO1lBQ3RCLElBQUksS0FBSyxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBRSxDQUFDO1lBQ25DLElBQUksR0FBRyxHQUFHLFNBQVMsQ0FBQztZQUNwQixJQUFJLEtBQUssQ0FBQyxtQkFBbUIsRUFBRTtnQkFDN0IsR0FBRyxHQUFHLENBQUMsSUFBSSxTQUFTLENBQUMsa0JBQWtCLENBQUMsVUFBVSxHQUFHLElBQUksQ0FBQyxDQUFDLENBQUM7YUFDN0Q7WUFDRCxJQUFJLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxLQUFLLEVBQUUsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLENBQUMsQ0FBQztTQUM3QztRQUNELE9BQU8sS0FBSyxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUM5QixDQUFDOztBQTlNSCxrQkErTUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyBjZGsgZnJvbSBcImF3cy1jZGstbGliL2NvcmVcIjtcbmltcG9ydCAqIGFzIF8gZnJvbSBcImxvZGFzaFwiO1xuaW1wb3J0IHsgUGlwZWxpbmVTdGFjayB9IGZyb20gXCIuL3BpcGVsaW5lXCI7XG5pbXBvcnQgeyBTdGFnZSB9IGZyb20gXCIuL3N0YWdlXCI7XG5pbXBvcnQgeyBwYXJzZVJlcG9zaXRvcnlVcmwgfSBmcm9tIFwiLi91dGlsc1wiO1xuaW1wb3J0IHtcbiAgQ09OVEVYVF9LRVlfQUNDT1VOVCxcbiAgQ09OVEVYVF9LRVlfQlJBTkNILFxuICBDT05URVhUX0tFWV9OQU1FLFxuICBDT05URVhUX0tFWV9SRUdJT04sXG4gIENPTlRFWFRfS0VZX1JFUE9TSVRPUlksXG4gIENPTlRFWFRfS0VZX1ZQQyxcbiAgQ09OVEVYVF9SRVBPU0lUT1JZX1RPS0VOX1NFQ1JFVCxcbiAgVEFHX0FQUF9OQU1FLFxufSBmcm9tIFwiLi9jb25zdGFudHNcIjtcbmltcG9ydCAqIGFzIHNzbSBmcm9tIFwiYXdzLWNkay1saWIvYXdzLXNzbVwiO1xuaW1wb3J0ICogYXMgY3hhcGkgZnJvbSBcImF3cy1jZGstbGliL2N4LWFwaVwiO1xuaW1wb3J0ICogYXMgcGlwZWxpbmVzIGZyb20gXCJhd3MtY2RrLWxpYi9waXBlbGluZXNcIjtcbmltcG9ydCB7IFN0YWNrIH0gZnJvbSBcIi4vc3RhY2tcIjtcblxuZXhwb3J0IGludGVyZmFjZSBDb25maWd1cmF0aW9uIHtcbiAgcmVhZG9ubHkgbmFtZTogc3RyaW5nO1xuICByZWFkb25seSByZXBvc2l0b3J5OiBzdHJpbmc7XG4gIHJlYWRvbmx5IGFjY291bnQ6IHN0cmluZztcbiAgcmVhZG9ubHkgcmVnaW9uOiBzdHJpbmc7XG4gIHJlYWRvbmx5IGJyYW5jaDogc3RyaW5nO1xuICByZWFkb25seSB2cGNJZDogc3RyaW5nO1xuICByZWFkb25seSByZXBvc2l0b3J5VG9rZW5TZWNyZXQ6IHN0cmluZztcbn1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuXG5leHBvcnQgY2xhc3MgQXBwIGV4dGVuZHMgY2RrLkFwcCB7XG4gIHByaXZhdGUgc3RhdGljIElOU1RBTkNFPzogQXBwO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcbiAgY29uc3RydWN0b3IoKSB7XG4gICAgc3VwZXIoeyBhdXRvU3ludGg6IHRydWUgfSk7XG5cbiAgICBpZiAoQXBwLklOU1RBTkNFKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJBcHAgaGFzIGFscmVhZHkgYmVlbiBpbnN0YW50aWF0ZWQuXCIpO1xuICAgIH1cblxuICAgIEFwcC5JTlNUQU5DRSA9IHRoaXM7XG5cbiAgICB0aGlzLmNvbmZpZ3VyYXRpb24gPSB7XG4gICAgICBhY2NvdW50OiB0aGlzLmdldENvbnRleHRPclRocm93KENPTlRFWFRfS0VZX0FDQ09VTlQpLFxuICAgICAgcmVnaW9uOiB0aGlzLmdldENvbnRleHRPclRocm93KENPTlRFWFRfS0VZX1JFR0lPTiksXG4gICAgICByZXBvc2l0b3J5OiB0aGlzLmdldENvbnRleHRPclRocm93KENPTlRFWFRfS0VZX1JFUE9TSVRPUlkpLFxuICAgICAgbmFtZTogdGhpcy5nZXRDb250ZXh0T3JUaHJvdyhDT05URVhUX0tFWV9OQU1FKSxcbiAgICAgIGJyYW5jaDogdGhpcy5nZXRDb250ZXh0T3JUaHJvdyhDT05URVhUX0tFWV9CUkFOQ0gpLFxuICAgICAgdnBjSWQ6IHRoaXMuZ2V0Q29udGV4dE9yVGhyb3coQ09OVEVYVF9LRVlfVlBDKSxcbiAgICAgIHJlcG9zaXRvcnlUb2tlblNlY3JldDogdGhpcy5nZXRDb250ZXh0T3JUaHJvdyhcbiAgICAgICAgQ09OVEVYVF9SRVBPU0lUT1JZX1RPS0VOX1NFQ1JFVFxuICAgICAgKSxcbiAgICB9O1xuXG4gICAgY2RrLlRhZ3Mub2YodGhpcykuYWRkKFRBR19BUFBfTkFNRSwgdGhpcy5jb25maWd1cmF0aW9uLm5hbWUpO1xuICAgIHRoaXMucGlwZWxpbmVTdGFjayA9IHRoaXMuc2V0dXBDb2RlUGlwZWxpbmUoKTtcblxuICAgIC8vYWRkIHBpcGVsaW5lU3RhY2sgdG8gb3VyIGdsb2JhbCBsaXN0IG9mIHN0YWNrc1xuICAgIG5ldyBzc20uU3RyaW5nUGFyYW1ldGVyKHRoaXMucGlwZWxpbmVTdGFjaywgXCJzc20tc3RhY2tcIiwge1xuICAgICAgcGFyYW1ldGVyTmFtZTogYC9jbG91ZGNhbXAvJHtcbiAgICAgICAgQXBwLmluc3RhbmNlLmNvbmZpZ3VyYXRpb24ubmFtZVxuICAgICAgfS9fL3N0YWNrLyR7Xy5rZWJhYkNhc2UodGhpcy5waXBlbGluZVN0YWNrLnN0YWNrTmFtZSl9YCxcbiAgICAgIHN0cmluZ1ZhbHVlOiB0aGlzLnBpcGVsaW5lU3RhY2suc3RhY2tOYW1lLFxuICAgIH0pO1xuXG4gICAgLy8gV2UgbmVlZCB0aGUgbmFtZSBvZiB0aGUgY29kZXBpcGVsaW5lIGZvciBsYXRlciB1c2VcbiAgICBuZXcgc3NtLlN0cmluZ1BhcmFtZXRlcih0aGlzLnBpcGVsaW5lU3RhY2ssIFwic3NtLWNvZGVwaXBlbGluZVwiLCB7XG4gICAgICBwYXJhbWV0ZXJOYW1lOiBgL2Nsb3VkY2FtcC8ke3RoaXMuY29uZmlndXJhdGlvbi5uYW1lfS9fL2NvZGVwaXBlbGluZWAsXG4gICAgICBzdHJpbmdWYWx1ZTogdGhpcy5waXBlbGluZVN0YWNrLnBpcGVsaW5lTmFtZSxcbiAgICB9KTtcblxuICAgIC8vIEFsc28sIHdlIG5lZWQgdG8gaWRlbnRpZnkgdGhlIHBpcGVsaW5lIHN0YWNrXG4gICAgbmV3IHNzbS5TdHJpbmdQYXJhbWV0ZXIodGhpcy5waXBlbGluZVN0YWNrLCBcInNzbS1waXBlbGluZS1zdGFja1wiLCB7XG4gICAgICBwYXJhbWV0ZXJOYW1lOiBgL2Nsb3VkY2FtcC8ke3RoaXMuY29uZmlndXJhdGlvbi5uYW1lfS9fL3BpcGVsaW5lLXN0YWNrYCxcbiAgICAgIHN0cmluZ1ZhbHVlOiB0aGlzLnBpcGVsaW5lU3RhY2suc3RhY2tOYW1lLFxuICAgIH0pO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXRDb250ZXh0T3JUaHJvdyhrZXk6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgbGV0IHZhbHVlOiBzdHJpbmcgPSB0aGlzLm5vZGUudHJ5R2V0Q29udGV4dChrZXkpO1xuICAgIGlmICh2YWx1ZSA9PSBudWxsKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJNaXNzaW5nIGNvbmZpZyBpbiBjZGsuanNvbjogXCIgKyBrZXkpO1xuICAgIH1cbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuICBwdWJsaWMgc3RhdGljIGdldCBpbnN0YW5jZSgpOiBBcHAge1xuICAgIGlmICghQXBwLklOU1RBTkNFKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIFwiaW5zdGFuY2UoKSBjYWxsZWQgYnV0IEFwcCBoYXMgbm90IGJlZW4gaW5zdGFudGlhdGVkIHlldC5cIlxuICAgICAgKTtcbiAgICB9XG4gICAgcmV0dXJuIEFwcC5JTlNUQU5DRTtcbiAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcbiAgZ2V0IG5ldHdvcmsoKTogU3RhY2sge1xuICAgIHJldHVybiB0aGlzLmdldE9yQWRkU3RhZ2UoXCJuZXR3b3JrXCIpLnN0YWNrO1xuICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcbiAgZ2V0IHN0YWdpbmcoKTogU3RhY2sge1xuICAgIHJldHVybiB0aGlzLmdldE9yQWRkU3RhZ2UoXCJzdGFnaW5nXCIpLnN0YWNrO1xuICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXG4gIGdldCBwcm9kdWN0aW9uKCk6IFN0YWNrIHtcbiAgICByZXR1cm4gdGhpcy5nZXRPckFkZFN0YWdlKFwicHJvZHVjdGlvblwiKS5zdGFjaztcbiAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcbiAgcHVibGljIGdldFN0YWNrKG5hbWU6IHN0cmluZyk6IFN0YWNrIHtcbiAgICB0cnkge1xuICAgICAgcmV0dXJuIHRoaXMuZ2V0U3RhZ2UobmFtZSkuc3RhY2s7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgaWYgKChlIGFzIEVycm9yKS5tZXNzYWdlLnN0YXJ0c1dpdGgoXCJTdGFnZSBkb2Vzbid0IGV4aXN0XCIpKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIlN0YWNrIGRvZXNuJ3QgZXhpc3Q6IFwiICsgbmFtZSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aHJvdyBlO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXG4gIHB1YmxpYyBzdGFjayhuYW1lOiBzdHJpbmcpOiBTdGFjayB7XG4gICAgaWYgKHRoaXMuc3RhZ2VzLmdldChuYW1lKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiU3RhY2sgYWxyZWFkeSBleGlzdHM6IFwiICsgbmFtZSk7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLmdldE9yQWRkU3RhZ2UobmFtZSkuc3RhY2s7XG4gIH1cblxuICBwcml2YXRlIHN0YWdlczogTWFwPHN0cmluZywgU3RhZ2U+ID0gbmV3IE1hcCgpO1xuXG4gIHByaXZhdGUgZ2V0T3JBZGRTdGFnZShpZDogc3RyaW5nKSB7XG4gICAgbGV0IGV4aXN0aW5nU3RhZ2UgPSB0aGlzLnN0YWdlcy5nZXQoaWQpO1xuICAgIGlmIChleGlzdGluZ1N0YWdlKSB7XG4gICAgICByZXR1cm4gZXhpc3RpbmdTdGFnZTtcbiAgICB9XG4gICAgbGV0IHN0YWdlID0gbmV3IFN0YWdlKHRoaXMsIF8udXBwZXJGaXJzdChfLmNhbWVsQ2FzZShpZCkpKTtcbiAgICBsZXQgc3RhY2sgPSBuZXcgU3RhY2soc3RhZ2UsIGlkKTtcbiAgICBzdGFnZS5zdGFjayA9IHN0YWNrO1xuICAgIHRoaXMuc3RhZ2VzLnNldChpZCwgc3RhZ2UpO1xuXG4gICAgcmV0dXJuIHN0YWdlO1xuICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuXG4gIHB1YmxpYyBnZXRTdGFnZShuYW1lOiBzdHJpbmcpOiBTdGFnZSB7XG4gICAgaWYgKG5hbWUgaW4gW1wibmV0d29ya1wiLCBcInN0YWdpbmdcIiwgXCJwcm9kdWN0aW9uXCJdKSB7XG4gICAgICByZXR1cm4gdGhpcy5nZXRPckFkZFN0YWdlKG5hbWUpO1xuICAgIH1cbiAgICBpZiAoIXRoaXMuc3RhZ2VzLmhhcyhuYW1lKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiU3RhZ2UgZG9lc24ndCBleGlzdDogXCIgKyBuYW1lKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuc3RhZ2VzLmdldChuYW1lKSE7XG4gIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcbiAgcHVibGljIHN0YWdlKG5hbWU6IHN0cmluZywgc3RhZ2U/OiBTdGFnZSk6IFN0YWdlIHtcbiAgICBpZiAodGhpcy5zdGFnZXMuaGFzKG5hbWUpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJTdGFnZSBhbHJlYWR5IGV4aXN0czogXCIgKyBuYW1lKTtcbiAgICB9XG4gICAgaWYgKCFzdGFnZSkge1xuICAgICAgc3RhZ2UgPSBuZXcgU3RhZ2UodGhpcywgXy51cHBlckZpcnN0KF8uY2FtZWxDYXNlKG5hbWUpKSk7XG4gICAgfVxuICAgIHRoaXMuc3RhZ2VzLnNldChuYW1lLCBzdGFnZSk7XG4gICAgcmV0dXJuIHN0YWdlO1xuICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIFxuICBjb25maWd1cmF0aW9uOiBDb25maWd1cmF0aW9uO1xuXG4gIHByaXZhdGUgcGlwZWxpbmVTdGFjazogUGlwZWxpbmVTdGFjaztcbiAgICAgICAgICAgICAgICAgICAgICAgIFxuICBwdWJsaWMgZ2V0IHBpcGVsaW5lKCkge1xuICAgIHJldHVybiB0aGlzLnBpcGVsaW5lU3RhY2sucGlwZWxpbmU7XG4gIH1cblxuICBwcml2YXRlIHNldHVwQ29kZVBpcGVsaW5lKCk6IFBpcGVsaW5lU3RhY2sge1xuICAgIGNvbnN0IHJlcG9zaXRvcnlVcmwgPSB0aGlzLmNvbmZpZ3VyYXRpb24ucmVwb3NpdG9yeTtcbiAgICBjb25zdCBicmFuY2ggPSB0aGlzLmNvbmZpZ3VyYXRpb24uYnJhbmNoO1xuICAgIGxldCBwYXJzZWQgPSBwYXJzZVJlcG9zaXRvcnlVcmwocmVwb3NpdG9yeVVybCk7XG4gICAgbGV0IHJlcG9zaXRvcnlUb2tlblNlY3JldE5hbWUgPSB0aGlzLmNvbmZpZ3VyYXRpb24ucmVwb3NpdG9yeVRva2VuU2VjcmV0O1xuICAgIHJldHVybiBuZXcgUGlwZWxpbmVTdGFjayhcbiAgICAgIHRoaXMsXG4gICAgICBfLnVwcGVyRmlyc3QoXy5jYW1lbENhc2UodGhpcy5jb25maWd1cmF0aW9uLm5hbWUgKyBcIi1waXBlbGluZVwiKSksXG4gICAgICB7XG4gICAgICAgIGFwcE5hbWU6IHRoaXMuY29uZmlndXJhdGlvbi5uYW1lLFxuICAgICAgICByZXBvc2l0b3J5VG9rZW5TZWNyZXROYW1lOiByZXBvc2l0b3J5VG9rZW5TZWNyZXROYW1lLFxuICAgICAgICBob3N0OiBwYXJzZWQuaG9zdCxcbiAgICAgICAgb3duZXI6IHBhcnNlZC5vd25lcixcbiAgICAgICAgcmVwbzogcGFyc2VkLnJlcG8sXG4gICAgICAgIGJyYW5jaDogYnJhbmNoLFxuICAgICAgfVxuICAgICk7XG4gIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgXG4gIHN5bnRoKG9wdGlvbnM/OiBjZGsuU3RhZ2VTeW50aGVzaXNPcHRpb25zKTogY3hhcGkuQ2xvdWRBc3NlbWJseSB7XG4gICAgbGV0IG5hbWVzID0gQXJyYXkuZnJvbSh0aGlzLnN0YWdlcy5rZXlzKCkpO1xuICAgIG5hbWVzLnNvcnQoKGEsIGIpID0+IHtcbiAgICAgIHN3aXRjaCAoYSkge1xuICAgICAgICBjYXNlIFwibmV0d29ya1wiOlxuICAgICAgICAgIGlmIChiID09IFwic3RhZ2luZ1wiIHx8IGIgPT0gXCJwcm9kdWN0aW9uXCIpIHtcbiAgICAgICAgICAgIHJldHVybiAtMTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIDA7XG4gICAgICAgIGNhc2UgXCJzdGFnaW5nXCI6XG4gICAgICAgICAgaWYgKGIgPT0gXCJuZXR3b3JrXCIpIHtcbiAgICAgICAgICAgIHJldHVybiAxO1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoYiA9PSBcInByb2R1Y3Rpb25cIikge1xuICAgICAgICAgICAgcmV0dXJuIC0xO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gMDtcbiAgICAgICAgY2FzZSBcInByb2R1Y3Rpb25cIjpcbiAgICAgICAgICBpZiAoYiA9PSBcIm5ldHdvcmtcIiB8fCBiID09IFwic3RhZ2luZ1wiKSB7XG4gICAgICAgICAgICByZXR1cm4gMTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIDA7XG4gICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgcmV0dXJuIDA7XG4gICAgICB9XG4gICAgfSk7XG4gICAgZm9yIChsZXQgbmFtZSBvZiBuYW1lcykge1xuICAgICAgbGV0IHN0YWdlID0gdGhpcy5zdGFnZXMuZ2V0KG5hbWUpITtcbiAgICAgIGxldCBwcmUgPSB1bmRlZmluZWQ7XG4gICAgICBpZiAoc3RhZ2UubmVlZHNNYW51YWxBcHByb3ZhbCkge1xuICAgICAgICBwcmUgPSBbbmV3IHBpcGVsaW5lcy5NYW51YWxBcHByb3ZhbFN0ZXAoXCJhcHByb3ZlLVwiICsgbmFtZSldO1xuICAgICAgfVxuICAgICAgdGhpcy5waXBlbGluZS5hZGRTdGFnZShzdGFnZSwgeyBwcmU6IHByZSB9KTtcbiAgICB9XG4gICAgcmV0dXJuIHN1cGVyLnN5bnRoKG9wdGlvbnMpO1xuICB9XG59XG4iXX0=