@aws-solutions-constructs/core
Version:
Core CDK Construct for patterns library
253 lines • 36 kB
JavaScript
"use strict";
/**
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance
* with the License. A copy of the License is located at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* or in the 'license' file accompanying this file. This file is distributed on an 'AS IS' BASIS, WITHOUT WARRANTIES
* OR CONDITIONS OF ANY KIND, express or implied. See the License for the specific language governing permissions
* and limitations under the License.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.PipesLogLevel = void 0;
exports.BuildPipe = BuildPipe;
exports.CreateSqsSource = CreateSqsSource;
exports.CreateDynamoDBStreamsSource = CreateDynamoDBStreamsSource;
exports.CreateStateMachineTarget = CreateStateMachineTarget;
exports.CheckPipesProps = CheckPipesProps;
const pipes = require("aws-cdk-lib/aws-pipes");
const iam = require("aws-cdk-lib/aws-iam");
const defaults = require("..");
const cdk = require("aws-cdk-lib");
var PipesLogLevel;
(function (PipesLogLevel) {
PipesLogLevel["OFF"] = "OFF";
PipesLogLevel["TRACE"] = "TRACE";
PipesLogLevel["INFO"] = "INFO";
PipesLogLevel["ERROR"] = "ERROR";
})(PipesLogLevel || (exports.PipesLogLevel = PipesLogLevel = {}));
function BuildPipe(scope, id, props) {
CheckBuildPipeProps(props);
const pipeRole = new iam.Role(scope, `PipeRole--${id}`, {
assumedBy: new iam.ServicePrincipal('pipes.amazonaws.com'),
inlinePolicies: {
sourcePolicy: props.source.sourcePolicy,
targetPolicy: props.target.targetPolicy,
},
});
// At this point we have the minimum values for CfnPipeProps - let's
// create it and fold in any additional values as we go along
let constructProps = {
roleArn: pipeRole.roleArn,
source: props.source.sourceArn,
target: props.target.targetArn,
sourceParameters: props.source.sourceParameters,
targetParameters: props.target.targetParameters,
};
// Do we have any enrichment functionality?
if (props.enrichmentFunction) {
const enrichmentSettings = createLambdaEnrichment(scope, id, props.enrichmentFunction);
pipeRole.attachInlinePolicy(enrichmentSettings.pipeRolePolicy);
constructProps = defaults.consolidateProps(constructProps, { enrichment: enrichmentSettings.enrichmentArn });
}
else if (props.enrichmentStateMachine) {
const enrichmentSettings = createStateMachineEnrichment(scope, id, props.enrichmentStateMachine);
pipeRole.attachInlinePolicy(enrichmentSettings.pipeRolePolicy);
constructProps = defaults.consolidateProps(constructProps, { enrichment: enrichmentSettings.enrichmentArn });
}
// Are we responsible to create the logging mechanism?
if (!props.clientProps?.logConfiguration) {
const logLevel = defaults.CheckStringWithDefault(props.logLevel, PipesLogLevel.INFO);
if (logLevel !== PipesLogLevel.OFF) {
const defaultLogGroupProps = {
logGroupName: createPipesLogGroupName(scope, id),
};
const consolidatedLogGroupProps = defaults.consolidateProps(defaultLogGroupProps, props.pipeLogProps);
const newLogGroup = defaults.buildLogGroup(scope, `LogGroup-${id}`, consolidatedLogGroupProps);
const logConfiguration = {
cloudwatchLogsLogDestination: {
logGroupArn: newLogGroup.logGroupArn
},
level: logLevel
};
constructProps = defaults.consolidateProps(constructProps, {
logConfiguration,
});
}
}
const consolidateProps = defaults.consolidateProps(defaults.defaultPipesProps(), props.clientProps, constructProps);
const newPipe = new pipes.CfnPipe(scope, `pipe-${id}`, consolidateProps);
return {
pipe: newPipe,
pipeRole
};
}
function createLambdaEnrichment(scope, id, lambdaFunction) {
return {
enrichmentArn: lambdaFunction.functionArn,
pipeRolePolicy: new iam.Policy(scope, `enrichmentpolicy${id}`, {
statements: [
new iam.PolicyStatement({
resources: [lambdaFunction.functionArn],
actions: ['lambda:InvokeFunction'],
effect: iam.Effect.ALLOW,
})
]
})
};
}
function createStateMachineEnrichment(scope, id, stateMachine) {
return {
enrichmentArn: stateMachine.stateMachineArn,
pipeRolePolicy: new iam.Policy(scope, `enrichmentpolicy${id}`, {
statements: [
new iam.PolicyStatement({
resources: [stateMachine.stateMachineArn],
actions: ['states:StartSyncExecution'],
effect: iam.Effect.ALLOW,
})
]
})
};
}
function createPipesLogGroupName(scope, id) {
const logGroupPrefix = '/aws/vendedlogs/pipes/constructs/';
const nameParts = [
cdk.Stack.of(scope).stackName,
id,
'PipesLog'
];
return defaults.generatePhysicalLogGroupName(logGroupPrefix, nameParts);
}
// ==========================
// Source and Target code - as new sources and targets are required, implement them
// here and test the new functions.
function CreateSqsSource(queue, clientProps) {
const sourceParameters = defaults.consolidateProps(defaults.defaultSqsSourceProps(), clientProps);
return {
sourceParameters,
sourceArn: queue.queueArn,
sourcePolicy: new iam.PolicyDocument({
statements: [
new iam.PolicyStatement({
resources: [queue.queueArn],
actions: [
"sqs:ReceiveMessage",
"sqs:DeleteMessage",
"sqs:GetQueueAttributes",
],
effect: iam.Effect.ALLOW,
})
]
})
};
}
function CreateDynamoDBStreamsSource(scope, props) {
if (!props.table.tableStreamArn) {
throw new Error("ERROR - DynamoDB Table must have an associated stream");
}
const deployDlq = defaults.CheckBooleanWithDefault(props.deploySqsDlqQueue, true);
let sourceParameters = defaults.consolidateProps(defaults.defaultDynamoDBStreamsSourceProps(deployDlq), props.clientProps);
const sourcePolicy = new iam.PolicyDocument({
statements: [
new iam.PolicyStatement({
resources: [props.table.tableStreamArn],
actions: [
"dynamodb:DescribeStream",
"dynamodb:GetRecords",
"dynamodb:GetShardIterator",
"dynamodb:ListStreams"
],
effect: iam.Effect.ALLOW,
})
]
});
let buildQueueResponse;
// Default to setting up DLQ for failed messages
if (deployDlq) {
buildQueueResponse = defaults.buildQueue(scope, 'dlq', {
deployDeadLetterQueue: false,
queueProps: props.sqsDlqQueueProps
});
sourceParameters = defaults.consolidateProps(sourceParameters, {
dynamoDbStreamParameters: {
deadLetterConfig: {
arn: buildQueueResponse.queue.queueArn
}
}
});
sourcePolicy.addStatements(new iam.PolicyStatement({
resources: [buildQueueResponse.queue.queueArn],
actions: [
"sqs:SendMessage"
],
effect: iam.Effect.ALLOW,
}));
}
else {
if ((sourceParameters.dynamoDbStreamParameters?.maximumRecordAgeInSeconds) ||
(sourceParameters.dynamoDbStreamParameters?.maximumRetryAttempts)) {
throw new Error('ERROR - retry and record age constraints cannot be specified with no DLQ\n');
}
}
return {
sourceParameters,
sourceArn: props.table.tableStreamArn,
sourcePolicy,
dlq: buildQueueResponse?.queue ?? undefined
};
}
function CreateStateMachineTarget(stateMachine, clientProps) {
const targetParameters = defaults.consolidateProps(defaults.defaultStateMachineTargetProps(), clientProps);
return {
targetParameters,
targetArn: stateMachine.stateMachineArn,
targetPolicy: new iam.PolicyDocument({
statements: [
new iam.PolicyStatement({
resources: [stateMachine.stateMachineArn],
actions: ['states:StartExecution'],
effect: iam.Effect.ALLOW,
}),
],
})
};
}
// This is called by BuildPipe to validate arguments sent to BuildPipe
function CheckBuildPipeProps(props) {
if (props.enrichmentFunction && props.enrichmentStateMachine) {
throw new Error("ERROR - Only one of enrichmentFunction or enrichmentStateMachine can be provided");
}
if (props.clientProps && (props.clientProps.source || props.clientProps.target || props.clientProps.roleArn || props.clientProps.enrichment)) {
throw new Error("ERROR - BuildPipeProps cannot specify source, target, roleArn, or enrichment");
}
if (props.logLevel && props.clientProps?.logConfiguration) {
throw new Error('ERROR - BuildPipeProps cannot specify logLevel and logConfiguration');
}
if (props.pipeLogProps && props.clientProps?.logConfiguration) {
throw new Error('ERROR - BuildPipeProps cannot specify pipeLogProps and logConfiguration');
}
if (props.pipeLogProps && (props.logLevel === PipesLogLevel.OFF)) {
throw new Error('ERROR - BuildPipeProps cannot specify pipeLogProps and log level OFF');
}
}
// This is called by constructs to validate inputs to the construct
function CheckPipesProps(propsObject) {
let errorMessages = '';
let errorFound = false;
if (propsObject.pipesProps?.source) {
errorMessages += 'Do not set source in pipesProps. It is set by the construct.\n';
errorFound = true;
}
if (propsObject.pipesProps?.target) {
errorMessages += 'Do not set target in pipesProps. It is set by the construct.\n';
errorFound = true;
}
if (errorFound) {
throw new Error(errorMessages);
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGlwZXMtaGVscGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsicGlwZXMtaGVscGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7Ozs7Ozs7Ozs7R0FXRzs7O0FBMkNILDhCQWdFQztBQW1ERCwwQ0FtQkM7QUFTRCxrRUEyREM7QUFRRCw0REFrQkM7QUE0QkQsMENBaUJDO0FBMVRELCtDQUErQztBQUUvQywyQ0FBMkM7QUFLM0MsK0JBQStCO0FBQy9CLG1DQUFtQztBQUduQyxJQUFZLGFBS1g7QUFMRCxXQUFZLGFBQWE7SUFDdkIsNEJBQVcsQ0FBQTtJQUNYLGdDQUFlLENBQUE7SUFDZiw4QkFBYSxDQUFBO0lBQ2IsZ0NBQWUsQ0FBQTtBQUNqQixDQUFDLEVBTFcsYUFBYSw2QkFBYixhQUFhLFFBS3hCO0FBeUJELFNBQWdCLFNBQVMsQ0FBQyxLQUFnQixFQUFFLEVBQVUsRUFBRSxLQUFzQjtJQUM1RSxtQkFBbUIsQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUUzQixNQUFNLFFBQVEsR0FBRyxJQUFJLEdBQUcsQ0FBQyxJQUFJLENBQUMsS0FBSyxFQUFFLGFBQWEsRUFBRSxFQUFFLEVBQUU7UUFDdEQsU0FBUyxFQUFFLElBQUksR0FBRyxDQUFDLGdCQUFnQixDQUFDLHFCQUFxQixDQUFDO1FBQzFELGNBQWMsRUFBRTtZQUNkLFlBQVksRUFBRSxLQUFLLENBQUMsTUFBTSxDQUFDLFlBQVk7WUFDdkMsWUFBWSxFQUFFLEtBQUssQ0FBQyxNQUFNLENBQUMsWUFBWTtTQUN4QztLQUNGLENBQUMsQ0FBQztJQUVILG9FQUFvRTtJQUNwRSw2REFBNkQ7SUFDN0QsSUFBSSxjQUFjLEdBQXVCO1FBQ3ZDLE9BQU8sRUFBRSxRQUFRLENBQUMsT0FBTztRQUN6QixNQUFNLEVBQUUsS0FBSyxDQUFDLE1BQU0sQ0FBQyxTQUFTO1FBQzlCLE1BQU0sRUFBRSxLQUFLLENBQUMsTUFBTSxDQUFDLFNBQVM7UUFDOUIsZ0JBQWdCLEVBQUUsS0FBSyxDQUFDLE1B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LFFBQVEsSUFBSSxLQUFLLENBQUMsV0FBVyxFQUFFLGdCQUFnQixFQUFFLENBQUM7UUFDMUQsTUFBTSxJQUFJLEtBQUssQ0FBQyxxRUFBcUUsQ0FBQyxDQUFDO0lBQ3pGLENBQUM7SUFDRCxJQUFJLEtBQUssQ0FBQyxZQUFZLElBQUksS0FBSyxDQUFDLFdBQVcsRUFBRSxnQkFBZ0IsRUFBRSxDQUFDO1FBQzlELE1BQU0sSUFBSSxLQUFLLENBQUMseUVBQXlFLENBQUMsQ0FBQztJQUM3RixDQUFDO0lBQ0QsSUFBSSxLQUFLLENBQUMsWUFBWSxJQUFJLENBQUMsS0FBSyxDQUFDLFFBQVEsS0FBSyxhQUFhLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQztRQUNqRSxNQUFNLElBQUksS0FBSyxDQUFDLHNFQUFzRSxDQUFDLENBQUM7SUFDMUYsQ0FBQztBQUNILENBQUM7QUFNRCxtRUFBbUU7QUFDbkUsU0FBZ0IsZUFBZSxDQUFDLFdBQTZCO0lBQzNELElBQUksYUFBYSxHQUFHLEVBQUUsQ0FBQztJQUN2QixJQUFJLFVBQVUsR0FBRyxLQUFLLENBQUM7SUFFdkIsSUFBSSxXQUFXLENBQUMsVUFBVSxFQUFFLE1BQU0sRUFBRSxDQUFDO1FBQ25DLGFBQWEsSUFBSSxnRUFBZ0UsQ0FBQztRQUNsRixVQUFVLEdBQUcsSUFBSSxDQUFDO0lBQ3BCLENBQUM7SUFFRCxJQUFJLFdBQVcsQ0FBQyxVQUFVLEVBQUUsTUFBTSxFQUFFLENBQUM7UUFDbkMsYUFBYSxJQUFJLGdFQUFnRSxDQUFDO1FBQ2xGLFVBQVUsR0FBRyxJQUFJLENBQUM7SUFDcEIsQ0FBQztJQUVELElBQUksVUFBVSxFQUFFLENBQUM7UUFDZixNQUFNLElBQUksS0FBSyxDQUFDLGFBQWEsQ0FBQyxDQUFDO0lBQ2pDLENBQUM7QUFDSCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiAgQ29weXJpZ2h0IEFtYXpvbi5jb20sIEluYy4gb3IgaXRzIGFmZmlsaWF0ZXMuIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG4gKlxuICogIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIikuIFlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2VcbiAqICB3aXRoIHRoZSBMaWNlbnNlLiBBIGNvcHkgb2YgdGhlIExpY2Vuc2UgaXMgbG9jYXRlZCBhdFxuICpcbiAqICAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogIG9yIGluIHRoZSAnbGljZW5zZScgZmlsZSBhY2NvbXBhbnlpbmcgdGhpcyBmaWxlLiBUaGlzIGZpbGUgaXMgZGlzdHJpYnV0ZWQgb24gYW4gJ0FTIElTJyBCQVNJUywgV0lUSE9VVCBXQVJSQU5USUVTXG4gKiAgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZXhwcmVzcyBvciBpbXBsaWVkLiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnNcbiAqICBhbmQgbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuaW1wb3J0ICogYXMgcGlwZXMgZnJvbSAnYXdzLWNkay1saWIvYXdzLXBpcGVzJztcbmltcG9ydCAqIGFzIHNxcyBmcm9tICdhd3MtY2RrLWxpYi9hd3Mtc3FzJztcbmltcG9ydCAqIGFzIGlhbSBmcm9tICdhd3MtY2RrLWxpYi9hd3MtaWFtJztcbmltcG9ydCAqIGFzIGxvZ3MgZnJvbSAnYXdzLWNkay1saWIvYXdzLWxvZ3MnO1xuaW1wb3J0ICogYXMgZHluYW1vZGIgZnJvbSAnYXdzLWNkay1saWIvYXdzLWR5bmFtb2RiJztcbmltcG9ydCAqIGFzIGxhbWJkYSBmcm9tICdhd3MtY2RrLWxpYi9hd3MtbGFtYmRhJztcbmltcG9ydCAqIGFzIHNmbiBmcm9tICdhd3MtY2RrLWxpYi9hd3Mtc3RlcGZ1bmN0aW9ucyc7XG5pbXBvcnQgKiBhcyBkZWZhdWx0cyBmcm9tIFwiLi5cIjtcbmltcG9ydCAqIGFzIGNkayBmcm9tICdhd3MtY2RrLWxpYic7XG5pbXBvcnQgeyBDb25zdHJ1Y3QgfSBmcm9tICdjb25zdHJ1Y3RzJztcblxuZXhwb3J0IGVudW0gUGlwZXNMb2dMZXZlbCB7XG4gIE9GRiA9IFwiT0ZGXCIsXG4gIFRSQUNFID0gXCJUUkFDRVwiLFxuICBJTkZPID0gXCJJTkZPXCIsXG4gIEVSUk9SID0gXCJFUlJPUlwiLFxufVxuXG5leHBvcnQgaW50ZXJmYWNlIENyZWF0ZVNvdXJjZVJlc3BvbnNlIHtcbiAgcmVhZG9ubHkgc291cmNlUGFyYW1ldGVyczogcGlwZXMuQ2ZuUGlwZS5QaXBlU291cmNlUGFyYW1ldGVyc1Byb3BlcnR5LFxuICByZWFkb25seSBzb3VyY2VBcm46IHN0cmluZyxcbiAgcmVhZG9ubHkgc291cmNlUG9saWN5OiBpYW0uUG9saWN5RG9jdW1lbnQsXG4gIC8vIE5vdCBwb3B1bGF0ZWQgZm9yIGV2ZXJ5IHNvdXJjZSwgbm90IHBvcHVsYXRlZCBpZiBleGlzdGluZyBxdWV1ZSBpcyBwYXNzZWQgaW4gc29tZWRheVxuICByZWFkb25seSBkbHE/OiBzcXMuUXVldWVcbn1cblxuZXhwb3J0IGludGVyZmFjZSBCdWlsZFBpcGVzUHJvcHMge1xuICByZWFkb25seSBzb3VyY2U6IENyZWF0ZVNvdXJjZVJlc3BvbnNlLFxuICByZWFkb25seSB0YXJnZXQ6IENyZWF0ZVRhcmdldFJlc3BvbnNlLFxuICByZWFkb25seSBlbnJpY2htZW50RnVuY3Rpb24/OiBsYW1iZGEuRnVuY3Rpb24sXG4gIHJlYWRvbmx5IGVucmljaG1lbnRTdGF0ZU1hY2hpbmU/OiBzZm4uU3RhdGVNYWNoaW5lLFxuICByZWFkb25seSBjbGllbnRQcm9wcz86IGFueSB8IHBpcGVzLkNmblBpcGVQcm9wc1xuICByZWFkb25seSBsb2dMZXZlbD86IFBpcGVzTG9nTGV2ZWwsXG4gIHJlYWRvbmx5IHBpcGVMb2dQcm9wcz86IGxvZ3MuTG9nR3JvdXBQcm9wc1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEJ1aWxkUGlwZXNSZXNwb25zZSB7XG4gIHJlYWRvbmx5IHBpcGU6IHBpcGVzLkNmblBpcGUsXG4gIHJlYWRvbmx5IHBpcGVSb2xlOiBpYW0uUm9sZVxufVxuXG5leHBvcnQgZnVuY3Rpb24gQnVpbGRQaXBlKHNjb3BlOiBDb25zdHJ1Y3QsIGlkOiBzdHJpbmcsIHByb3BzOiBCdWlsZFBpcGVzUHJvcHMpOiBCdWlsZFBpcGVzUmVzcG9uc2Uge1xuICBDaGVja0J1aWxkUGlwZVByb3BzKHByb3BzKTtcblxuICBjb25zdCBwaXBlUm9sZSA9IG5ldyBpYW0uUm9sZShzY29wZSwgYFBpcGVSb2xlLS0ke2lkfWAsIHtcbiAgICBhc3N1bWVkQnk6IG5ldyBpYW0uU2VydmljZVByaW5jaXBhbCgncGlwZXMuYW1hem9uYXdzLmNvbScpLFxuICAgIGlubGluZVBvbGljaWVzOiB7XG4gICAgICBzb3VyY2VQb2xpY3k6IHByb3BzLnNvdXJjZS5zb3VyY2VQb2xpY3ksXG4gICAgICB0YXJnZXRQb2xpY3k6IHByb3BzLnRhcmdldC50YXJnZXRQb2xpY3ksXG4gICAgfSxcbiAgfSk7XG5cbiAgLy8gQXQgdGhpcyBwb2ludCB3ZSBoYXZlIHRoZSBtaW5pbXVtIHZhbHVlcyBmb3IgQ2ZuUGlwZVByb3BzIC0gbGV0J3NcbiAgLy8gY3JlYXRlIGl0IGFuZCBmb2xkIGluIGFueSBhZGRpdGlvbmFsIHZhbHVlcyBhcyB3ZSBnbyBhbG9uZ1xuICBsZXQgY29uc3RydWN0UHJvcHM6IHBpcGVzLkNmblBpcGVQcm9wcyA9IHtcbiAgICByb2xlQXJuOiBwaXBlUm9sZS5yb2xlQXJuLFxuICAgIHNvdXJjZTogcHJvcHMuc291cmNlLnNvdXJjZUFybixcbiAgICB0YXJnZXQ6IHByb3BzLnRhcmdldC50YXJnZXRBcm4sXG4gICAgc291cmNlUGFyYW1ldGVyczogcHJvcHMuc291cmNlLnNvdXJjZVBhcmFtZXRlcnMsXG4gICAgdGFyZ2V0UGFyYW1ldGVyczogcHJvcHMudGFyZ2V0LnRhcmdldFBhcmFtZXRlcnMsXG4gIH07XG5cbiAgLy8gRG8gd2UgaGF2ZSBhbnkgZW5yaWNobWVudCBmdW5jdGlvbmFsaXR5P1xuICBpZiAocHJvcHMuZW5yaWNobWVudEZ1bmN0aW9uKSB7XG4gICAgY29uc3QgZW5yaWNobWVudFNldHRpbmdzID0gY3JlYXRlTGFtYmRhRW5yaWNobWVudChzY29wZSwgaWQsIHByb3BzLmVucmljaG1lbnRGdW5jdGlvbik7XG4gICAgcGlwZVJvbGUuYXR0YWNoSW5saW5lUG9saWN5KGVucmljaG1lbnRTZXR0aW5ncy5waXBlUm9sZVBvbGljeSk7XG4gICAgY29uc3RydWN0UHJvcHMgPSBkZWZhdWx0cy5jb25zb2xpZGF0ZVByb3BzKGNvbnN0cnVjdFByb3BzLCB7IGVucmljaG1lbnQ6IGVucmljaG1lbnRTZXR0aW5ncy5lbnJpY2htZW50QXJuIH0pO1xuICB9IGVsc2UgaWYgKHByb3BzLmVucmljaG1lbnRTdGF0ZU1hY2hpbmUpIHtcbiAgICBjb25zdCBlbnJpY2htZW50U2V0dGluZ3MgPSBjcmVhdGVTdGF0ZU1hY2hpbmVFbnJpY2htZW50KHNjb3BlLCBpZCwgcHJvcHMuZW5yaWNobWVudFN0YXRlTWFjaGluZSk7XG4gICAgcGlwZVJvbGUuYXR0YWNoSW5saW5lUG9saWN5KGVucmljaG1lbnRTZXR0aW5ncy5waXBlUm9sZVBvbGljeSk7XG4gICAgY29uc3RydWN0UHJvcHMgPSBkZWZhdWx0cy5jb25zb2xpZGF0ZVByb3BzKGNvbnN0cnVjdFByb3BzLCB7IGVucmljaG1lbnQ6IGVucmljaG1lbnRTZXR0aW5ncy5lbnJpY2htZW50QXJuIH0pO1xuICB9XG5cbiAgLy8gQXJlIHdlIHJlc3BvbnNpYmxlIHRvIGNyZWF0ZSB0aGUgbG9nZ2luZyBtZWNoYW5pc20/XG4gIGlmICghcHJvcHMuY2xpZW50UHJvcHM/LmxvZ0NvbmZpZ3VyYXRpb24pIHtcblxuICAgIGNvbnN0IGxvZ0xldmVsID0gZGVmYXVsdHMuQ2hlY2tTdHJpbmdXaXRoRGVmYXVsdChwcm9wcy5sb2dMZXZlbCwgUGlwZXNMb2dMZXZlbC5JTkZPKTtcbiAgICBpZiAobG9nTGV2ZWwgIT09IFBpcGVzTG9nTGV2ZWwuT0ZGKSB7XG5cbiAgICAgIGNvbnN0IGRlZmF1bHRMb2dHcm91cFByb3BzID0ge1xuICAgICAgICBsb2dHcm91cE5hbWU6IGNyZWF0ZVBpcGVzTG9nR3JvdXBOYW1lKHNjb3BlLCBpZCksXG4gICAgICB9O1xuICAgICAgY29uc3QgY29uc29saWRhdGVkTG9nR3JvdXBQcm9wcyA9IGRlZmF1bHRzLmNvbnNvbGlkYXRlUHJvcHMoZGVmYXVsdExvZ0dyb3VwUHJvcHMsIHByb3BzLnBpcGVMb2dQcm9wcyk7XG4gICAgICBjb25zdCBuZXdMb2dHcm91cCA9IGRlZmF1bHRzLmJ1aWxkTG9nR3JvdXAoc2NvcGUsIGBMb2dHcm91cC0ke2lkfWAsIGNvbnNvbGlkYXRlZExvZ0dyb3VwUHJvcHMpO1xuICAgICAgY29uc3QgbG9nQ29uZmlndXJhdGlvbiA9IHtcbiAgICAgICAgY2xvdWR3YXRjaExvZ3NMb2dEZXN0aW5hdGlvbjoge1xuICAgICAgICAgIGxvZ0dyb3VwQXJuOiBuZXdMb2dHcm91cC5sb2dHcm91cEFyblxuICAgICAgICB9LFxuICAgICAgICBsZXZlbDogbG9nTGV2ZWxcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0cnVjdFByb3BzID0gZGVmYXVsdHMuY29uc29saWRhdGVQcm9wcyhjb25zdHJ1Y3RQcm9wcywge1xuICAgICAgICBsb2dDb25maWd1cmF0aW9uLFxuICAgICAgfSk7XG4gICAgfVxuICB9XG5cbiAgY29uc3QgY29uc29saWRhdGVQcm9wcyA9IGRlZmF1bHRzLmNvbnNvbGlkYXRlUHJvcHMoZGVmYXVsdHMuZGVmYXVsdFBpcGVzUHJvcHMoKSwgcHJvcHMuY2xpZW50UHJvcHMsIGNvbnN0cnVjdFByb3BzKTtcblxuICBjb25zdCBuZXdQaXBlID0gbmV3IHBpcGVzLkNmblBpcGUoc2NvcGUsIGBwaXBlLSR7aWR9YCwgY29uc29saWRhdGVQcm9wcyk7XG5cbiAgcmV0dXJuIHtcbiAgICBwaXBlOiBuZXdQaXBlLFxuICAgIHBpcGVSb2xlXG4gIH07XG59XG5cbmludGVyZmFjZSBDcmVhdGVFbnJpY2htZW50UmVzcG9uc2Uge1xuICByZWFkb25seSBlbnJpY2htZW50QXJuOiBzdHJpbmcsXG4gIHJlYWRvbmx5IHBpcGVSb2xlUG9saWN5OiBpYW0uUG9saWN5XG59XG5cbmZ1bmN0aW9uIGNyZWF0ZUxhbWJkYUVucmljaG1lbnQoc2NvcGU6IENvbnN0cnVjdCwgaWQ6IHN0cmluZywgbGFtYmRhRnVuY3Rpb246IGxhbWJkYS5GdW5jdGlvbik6IENyZWF0ZUVucmljaG1lbnRSZXNwb25zZSB7XG4gIHJldHVybiB7XG4gICAgZW5yaWNobWVudEFybjogbGFtYmRhRnVuY3Rpb24uZnVuY3Rpb25Bcm4sXG4gICAgcGlwZVJvbGVQb2xpY3k6IG5ldyBpYW0uUG9saWN5KHNjb3BlLCBgZW5yaWNobWVudHBvbGljeSR7aWR9YCwge1xuICAgICAgc3RhdGVtZW50czogW1xuICAgICAgICBuZXcgaWFtLlBvbGljeVN0YXRlbWVudCh7XG4gICAgICAgICAgcmVzb3VyY2VzOiBbbGFtYmRhRnVuY3Rpb24uZnVuY3Rpb25Bcm5dLFxuICAgICAgICAgIGFjdGlvbnM6IFsnbGFtYmRhOkludm9rZUZ1bmN0aW9uJ10sXG4gICAgICAgICAgZWZmZWN0OiBpYW0uRWZmZWN0LkFMTE9XLFxuICAgICAgICB9KVxuICAgICAgXVxuICAgIH0pXG4gIH07XG59XG5cbmZ1bmN0aW9uIGNyZWF0ZVN0YXRlTWFjaGluZUVucmljaG1lbnQoc2NvcGU6IENvbnN0cnVjdCwgaWQ6IHN0cmluZywgc3RhdGVNYWNoaW5lOiBzZm4uU3RhdGVNYWNoaW5lKTogQ3JlYXRlRW5yaWNobWVudFJlc3BvbnNlIHtcbiAgcmV0dXJuIHtcbiAgICBlbnJpY2htZW50QXJuOiBzdGF0ZU1hY2hpbmUuc3RhdGVNYWNoaW5lQXJuLFxuICAgIHBpcGVSb2xlUG9saWN5OiBuZXcgaWFtLlBvbGljeShzY29wZSwgYGVucmljaG1lbnRwb2xpY3kke2lkfWAsIHtcbiAgICAgIHN0YXRlbWVudHM6IFtcbiAgICAgICAgbmV3IGlhbS5Qb2xpY3lTdGF0ZW1lbnQoe1xuICAgICAgICAgIHJlc291cmNlczogW3N0YXRlTWFjaGluZS5zdGF0ZU1hY2hpbmVBcm5dLFxuICAgICAgICAgIGFjdGlvbnM6IFsnc3RhdGVzOlN0YXJ0U3luY0V4ZWN1dGlvbiddLFxuICAgICAgICAgIGVmZmVjdDogaWFtLkVmZmVjdC5BTExPVyxcbiAgICAgICAgfSlcbiAgICAgIF1cbiAgICB9KVxuICB9O1xufVxuXG5mdW5jdGlvbiBjcmVhdGVQaXBlc0xvZ0dyb3VwTmFtZShzY29wZTogQ29uc3RydWN0LCBpZDogc3RyaW5nKTogc3RyaW5nIHtcbiAgY29uc3QgbG9nR3JvdXBQcmVmaXggPSAnL2F3cy92ZW5kZWRsb2dzL3BpcGVzL2NvbnN0cnVjdHMvJztcbiAgY29uc3QgbmFtZVBhcnRzOiBzdHJpbmdbXSA9IFtcbiAgICBjZGsuU3RhY2sub2Yoc2NvcGUpLnN0YWNrTmFtZSxcbiAgICBpZCxcbiAgICAnUGlwZXNMb2cnXG4gIF07XG4gIHJldHVybiBkZWZhdWx0cy5nZW5lcmF0ZVBoeXNpY2FsTG9nR3JvdXBOYW1lKGxvZ0dyb3VwUHJlZml4LCBuYW1lUGFydHMpO1xufVxuXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PVxuLy8gU291cmNlIGFuZCBUYXJnZXQgY29kZSAtIGFzIG5ldyBzb3VyY2VzIGFuZCB0YXJnZXRzIGFyZSByZXF1aXJlZCwgaW1wbGVtZW50IHRoZW1cbi8vIGhlcmUgYW5kIHRlc3QgdGhlIG5ldyBmdW5jdGlvbnMuXG5cbmV4cG9ydCBmdW5jdGlvbiBDcmVhdGVTcXNTb3VyY2UocXVldWU6IHNxcy5JUXVldWUsIGNsaWVudFByb3BzPzogcGlwZXMuQ2ZuUGlwZS5QaXBlU291cmNlUGFyYW1ldGVyc1Byb3BlcnR5IHwgY2RrLklSZXNvbHZhYmxlKTogQ3JlYXRlU291cmNlUmVzcG9uc2Uge1xuICBjb25zdCBzb3VyY2VQYXJhbWV0ZXJzOiBwaXBlcy5DZm5QaXBlLlBpcGVTb3VyY2VQYXJhbWV0ZXJzUHJvcGVydHkgPSBkZWZhdWx0cy5jb25zb2xpZGF0ZVByb3BzKGRlZmF1bHRzLmRlZmF1bHRTcXNTb3VyY2VQcm9wcygpLCBjbGllbnRQcm9wcyk7XG4gIHJldHVybiB7XG4gICAgc291cmNlUGFyYW1ldGVycyxcbiAgICBzb3VyY2VBcm46IHF1ZXVlLnF1ZXVlQXJuLFxuICAgIHNvdXJjZVBvbGljeTogbmV3IGlhbS5Qb2xpY3lEb2N1bWVudCh7XG4gICAgICBzdGF0ZW1lbnRzOiBbXG4gICAgICAgIG5ldyBpYW0uUG9saWN5U3RhdGVtZW50KHtcbiAgICAgICAgICByZXNvdXJjZXM6IFtxdWV1ZS5xdWV1ZUFybiFdLFxuICAgICAgICAgIGFjdGlvbnM6IFtcbiAgICAgICAgICAgIFwic3FzOlJlY2VpdmVNZXNzYWdlXCIsXG4gICAgICAgICAgICBcInNxczpEZWxldGVNZXNzYWdlXCIsXG4gICAgICAgICAgICBcInNxczpHZXRRdWV1ZUF0dHJpYnV0ZXNcIixcbiAgICAgICAgICBdLFxuICAgICAgICAgIGVmZmVjdDogaWFtLkVmZmVjdC5BTExPVyxcbiAgICAgICAgfSlcbiAgICAgIF1cbiAgICB9KVxuICB9O1xufVxuXG5pbnRlcmZhY2UgQ3JlYXRlRHluYW1vREJTdHJlYW1zU291cmNlUHJvcHMge1xuICB0YWJsZTogZHluYW1vZGIuSVRhYmxlLFxuICBkZXBsb3lTcXNEbHFRdWV1ZT86IGJvb2xlYW4sXG4gIHNxc0RscVF1ZXVlUHJvcHM/OiBzcXMuUXVldWVQcm9wcyxcbiAgY2xpZW50UHJvcHM/OiBwaXBlcy5DZm5QaXBlLlBpcGVTb3VyY2VQYXJhbWV0ZXJzUHJvcGVydHkgfCBjZGsuSVJlc29sdmFibGVcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIENyZWF0ZUR5bmFtb0RCU3RyZWFtc1NvdXJjZShcbiAgc2NvcGU6IENvbnN0cnVjdCwgcHJvcHM6IENyZWF0ZUR5bmFtb0RCU3RyZWFtc1NvdXJjZVByb3BzKTogQ3JlYXRlU291cmNlUmVzcG9uc2Uge1xuICBpZiAoIXByb3BzLnRhYmxlLnRhYmxlU3RyZWFtQXJuKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFwiRVJST1IgLSBEeW5hbW9EQiBUYWJsZSBtdXN0IGhhdmUgYW4gYXNzb2NpYXRlZCBzdHJlYW1cIik7XG4gIH1cbiAgY29uc3QgZGVwbG95RGxxID0gZGVmYXVsdHMuQ2hlY2tCb29sZWFuV2l0aERlZmF1bHQocHJvcHMuZGVwbG95U3FzRGxxUXVldWUsIHRydWUpO1xuICBsZXQgc291cmNlUGFyYW1ldGVyczogcGlwZXMuQ2ZuUGlwZS5QaXBlU291cmNlUGFyYW1ldGVyc1Byb3BlcnR5ID1cbiAgICBkZWZhdWx0cy5jb25zb2xpZGF0ZVByb3BzKGRlZmF1bHRzLmRlZmF1bHREeW5hbW9EQlN0cmVhbXNTb3VyY2VQcm9wcyhkZXBsb3lEbHEpLCBwcm9wcy5jbGllbnRQcm9wcyk7XG5cbiAgY29uc3Qgc291cmNlUG9saWN5OiBpYW0uUG9saWN5RG9jdW1lbnQgPSBuZXcgaWFtLlBvbGljeURvY3VtZW50KHtcbiAgICBzdGF0ZW1lbnRzOiBbXG4gICAgICBuZXcgaWFtLlBvbGljeVN0YXRlbWVudCh7XG4gICAgICAgIHJlc291cmNlczogW3Byb3BzLnRhYmxlLnRhYmxlU3RyZWFtQXJuXSxcbiAgICAgICAgYWN0aW9uczogW1xuICAgICAgICAgIFwiZHluYW1vZGI6RGVzY3JpYmVTdHJlYW1cIixcbiAgICAgICAgICBcImR5bmFtb2RiOkdldFJlY29yZHNcIixcbiAgICAgICAgICBcImR5bmFtb2RiOkdldFNoYXJkSXRlcmF0b3JcIixcbiAgICAgICAgICBcImR5bmFtb2RiOkxpc3RTdHJlYW1zXCJcbiAgICAgICAgXSxcbiAgICAgICAgZWZmZWN0OiBpYW0uRWZmZWN0LkFMTE9XLFxuICAgICAgfSlcbiAgICBdXG4gIH0pO1xuICBsZXQgYnVpbGRRdWV1ZVJlc3BvbnNlOiBkZWZhdWx0cy5CdWlsZFF1ZXVlUmVzcG9uc2UgfCB1bmRlZmluZWQ7XG4gIC8vIERlZmF1bHQgdG8gc2V0dGluZyB1cCBETFEgZm9yIGZhaWxlZCBtZXNzYWdlc1xuICBpZiAoZGVwbG95RGxxKSB7XG4gICAgYnVpbGRRdWV1ZVJlc3BvbnNlID0gZGVmYXVsdHMuYnVpbGRRdWV1ZShzY29wZSwgJ2RscScsIHtcbiAgICAgIGRlcGxveURlYWRMZXR0ZXJRdWV1ZTogZmFsc2UsXG4gICAgICBxdWV1ZVByb3BzOiBwcm9wcy5zcXNEbHFRdWV1ZVByb3BzXG4gICAgfSk7XG4gICAgc291cmNlUGFyYW1ldGVycyA9IGRlZmF1bHRzLmNvbnNvbGlkYXRlUHJvcHMoc291cmNlUGFyYW1ldGVycywge1xuICAgICAgZHluYW1vRGJTdHJlYW1QYXJhbWV0ZXJzOiB7XG4gICAgICAgIGRlYWRMZXR0ZXJDb25maWc6IHtcbiAgICAgICAgICBhcm46IGJ1aWxkUXVldWVSZXNwb25zZS5xdWV1ZS5xdWV1ZUFyblxuICAgICAgICB9XG4gICAgICB9XG4gICAgfSk7XG4gICAgc291cmNlUG9saWN5LmFkZFN0YXRlbWVudHMoXG4gICAgICBuZXcgaWFtLlBvbGljeVN0YXRlbWVudCh7XG4gICAgICAgIHJlc291cmNlczogW2J1aWxkUXVldWVSZXNwb25zZS5xdWV1ZS5xdWV1ZUFybl0sXG4gICAgICAgIGFjdGlvbnM6IFtcbiAgICAgICAgICBcInNxczpTZW5kTWVzc2FnZVwiXG4gICAgICAgIF0sXG4gICAgICAgIGVmZmVjdDogaWFtLkVmZmVjdC5BTExPVyxcbiAgICAgIH0pXG4gICAgKTtcbiAgfSBlbHNlIHtcbiAgICBpZiAoKChzb3VyY2VQYXJhbWV0ZXJzLmR5bmFtb0RiU3RyZWFtUGFyYW1ldGVycyBhcyBwaXBlcy5DZm5QaXBlLlBpcGVTb3VyY2VEeW5hbW9EQlN0cmVhbVBhcmFtZXRlcnNQcm9wZXJ0eSk/Lm1heGltdW1SZWNvcmRBZ2VJblNlY29uZHMpIHx8XG4gICAgICAoKHNvdXJjZVBhcmFtZXRlcnMuZHluYW1vRGJTdHJlYW1QYXJhbWV0ZXJzIGFzIHBpcGVzLkNmblBpcGUuUGlwZVNvdXJjZUR5bmFtb0RCU3RyZWFtUGFyYW1ldGVyc1Byb3BlcnR5KT8ubWF4aW11bVJldHJ5QXR0ZW1wdHMpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0VSUk9SIC0gcmV0cnkgYW5kIHJlY29yZCBhZ2UgY29uc3RyYWludHMgY2Fubm90IGJlIHNwZWNpZmllZCB3aXRoIG5vIERMUVxcbicpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiB7XG4gICAgc291cmNlUGFyYW1ldGVycyxcbiAgICBzb3VyY2VBcm46IHByb3BzLnRhYmxlLnRhYmxlU3RyZWFtQXJuISxcbiAgICBzb3VyY2VQb2xpY3ksXG4gICAgZGxxOiBidWlsZFF1ZXVlUmVzcG9uc2U/LnF1ZXVlID8/IHVuZGVmaW5lZFxuICB9O1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIENyZWF0ZVRhcmdldFJlc3BvbnNlIHtcbiAgcmVhZG9ubHkgdGFyZ2V0UGFyYW1ldGVyczogcGlwZXMuQ2ZuUGlwZS5QaXBlVGFyZ2V0UGFyYW1ldGVyc1Byb3BlcnR5LFxuICByZWFkb25seSB0YXJnZXRBcm46IHN0cmluZyxcbiAgcmVhZG9ubHkgdGFyZ2V0UG9saWN5OiBpYW0uUG9saWN5RG9jdW1lbnRcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIENyZWF0ZVN0YXRlTWFjaGluZVRhcmdldChzdGF0ZU1hY2hpbmU6IHNmbi5JU3RhdGVNYWNoaW5lLFxuICBjbGllbnRQcm9wcz86IHBpcGVzLkNmblBpcGUuUGlwZVRhcmdldFBhcmFtZXRlcnNQcm9wZXJ0eSB8IGNkay5JUmVzb2x2YWJsZSk6IENyZWF0ZVRhcmdldFJlc3BvbnNlIHtcblxuICBjb25zdCB0YXJnZXRQYXJhbWV0ZXJzOiBwaXBlcy5DZm5QaXBlLlBpcGVUYXJnZXRQYXJhbWV0ZXJzUHJvcGVydHkgPVxuICAgIGRlZmF1bHRzLmNvbnNvbGlkYXRlUHJvcHMoZGVmYXVsdHMuZGVmYXVsdFN0YXRlTWFjaGluZVRhcmdldFByb3BzKCksIGNsaWVudFByb3BzKTtcbiAgcmV0dXJuIHtcbiAgICB0YXJnZXRQYXJhbWV0ZXJzLFxuICAgIHRhcmdldEFybjogc3RhdGVNYWNoaW5lLnN0YXRlTWFjaGluZUFybixcbiAgICB0YXJnZXRQb2xpY3k6IG5ldyBpYW0uUG9saWN5RG9jdW1lbnQoe1xuICAgICAgc3RhdGVtZW50czogW1xuICAgICAgICBuZXcgaWFtLlBvbGljeVN0YXRlbWVudCh7XG4gICAgICAgICAgcmVzb3VyY2VzOiBbc3RhdGVNYWNoaW5lLnN0YXRlTWFjaGluZUFybl0sXG4gICAgICAgICAgYWN0aW9uczogWydzdGF0ZXM6U3RhcnRFeGVjdXRpb24nXSxcbiAgICAgICAgICBlZmZlY3Q6IGlhbS5FZmZlY3QuQUxMT1csXG4gICAgICAgIH0pLFxuICAgICAgXSxcbiAgICB9KVxuICB9O1xufVxuXG4vLyBUaGlzIGlzIGNhbGxlZCBieSBCdWlsZFBpcGUgdG8gdmFsaWRhdGUgYXJndW1lbnRzIHNlbnQgdG8gQnVpbGRQaXBlXG5mdW5jdGlvbiBDaGVja0J1aWxkUGlwZVByb3BzKHByb3BzOiBCdWlsZFBpcGVzUHJvcHMpIHtcbiAgaWYgKHByb3BzLmVucmljaG1lbnRGdW5jdGlvbiAmJiBwcm9wcy5lbnJpY2htZW50U3RhdGVNYWNoaW5lKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFwiRVJST1IgLSBPbmx5IG9uZSBvZiBlbnJpY2htZW50RnVuY3Rpb24gb3IgZW5yaWNobWVudFN0YXRlTWFjaGluZSBjYW4gYmUgcHJvdmlkZWRcIik7XG4gIH1cblxuICBpZiAocHJvcHMuY2xpZW50UHJvcHMgJiYgKHByb3BzLmNsaWVudFByb3BzLnNvdXJjZSB8fCBwcm9wcy5jbGllbnRQcm9wcy50YXJnZXQgfHwgcHJvcHMuY2xpZW50UHJvcHMucm9sZUFybiB8fCBwcm9wcy5jbGllbnRQcm9wcy5lbnJpY2htZW50KSkge1xuICAgIHRocm93IG5ldyBFcnJvcihcIkVSUk9SIC0gQnVpbGRQaXBlUHJvcHMgY2Fubm90IHNwZWNpZnkgc291cmNlLCB0YXJnZXQsIHJvbGVBcm4sIG9yIGVucmljaG1lbnRcIik7XG4gIH1cblxuICBpZiAocHJvcHMubG9nTGV2ZWwgJiYgcHJvcHMuY2xpZW50UHJvcHM/LmxvZ0NvbmZpZ3VyYXRpb24pIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0VSUk9SIC0gQnVpbGRQaXBlUHJvcHMgY2Fubm90IHNwZWNpZnkgbG9nTGV2ZWwgYW5kIGxvZ0NvbmZpZ3VyYXRpb24nKTtcbiAgfVxuICBpZiAocHJvcHMucGlwZUxvZ1Byb3BzICYmIHByb3BzLmNsaWVudFByb3BzPy5sb2dDb25maWd1cmF0aW9uKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdFUlJPUiAtIEJ1aWxkUGlwZVByb3BzIGNhbm5vdCBzcGVjaWZ5IHBpcGVMb2dQcm9wcyBhbmQgbG9nQ29uZmlndXJhdGlvbicpO1xuICB9XG4gIGlmIChwcm9wcy5waXBlTG9nUHJvcHMgJiYgKHByb3BzLmxvZ0xldmVsID09PSBQaXBlc0xvZ0xldmVsLk9GRikpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0VSUk9SIC0gQnVpbGRQaXBlUHJvcHMgY2Fubm90IHNwZWNpZnkgcGlwZUxvZ1Byb3BzIGFuZCBsb2cgbGV2ZWwgT0ZGJyk7XG4gIH1cbn1cblxuZXhwb3J0IGludGVyZmFjZSBQaXBlc1Byb3BzIHtcbiAgcmVhZG9ubHkgcGlwZXNQcm9wcz86IHBpcGVzLkNmblBpcGVQcm9wc1xufVxuXG4vLyBUaGlzIGlzIGNhbGxlZCBieSBjb25zdHJ1Y3RzIHRvIHZhbGlkYXRlIGlucHV0cyB0byB0aGUgY29uc3RydWN0XG5leHBvcnQgZnVuY3Rpb24gQ2hlY2tQaXBlc1Byb3BzKHByb3BzT2JqZWN0OiBQaXBlc1Byb3BzIHwgYW55KSB7XG4gIGxldCBlcnJvck1lc3NhZ2VzID0gJyc7XG4gIGxldCBlcnJvckZvdW5kID0gZmFsc2U7XG5cbiAgaWYgKHByb3BzT2JqZWN0LnBpcGVzUHJvcHM/LnNvdXJjZSkge1xuICAgIGVycm9yTWVzc2FnZXMgKz0gJ0RvIG5vdCBzZXQgc291cmNlIGluIHBpcGVzUHJvcHMuIEl0IGlzIHNldCBieSB0aGUgY29uc3RydWN0Llxcbic7XG4gICAgZXJyb3JGb3VuZCA9IHRydWU7XG4gIH1cblxuICBpZiAocHJvcHNPYmplY3QucGlwZXNQcm9wcz8udGFyZ2V0KSB7XG4gICAgZXJyb3JNZXNzYWdlcyArPSAnRG8gbm90IHNldCB0YXJnZXQgaW4gcGlwZXNQcm9wcy4gSXQgaXMgc2V0IGJ5IHRoZSBjb25zdHJ1Y3QuXFxuJztcbiAgICBlcnJvckZvdW5kID0gdHJ1ZTtcbiAgfVxuXG4gIGlmIChlcnJvckZvdW5kKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGVycm9yTWVzc2FnZXMpO1xuICB9XG59XG4iXX0=