@cdklabs/cdk-appflow
Version:
*Note:* this library is currently in technical preview.
261 lines • 36.7 kB
JavaScript
"use strict";
var _a;
Object.defineProperty(exports, "__esModule", { value: true });
exports.FlowBase = exports.DataPullMode = exports.FlowStatus = exports.FlowType = void 0;
const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
/*
Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/
const aws_cdk_lib_1 = require("aws-cdk-lib");
const aws_appflow_1 = require("aws-cdk-lib/aws-appflow");
const aws_cloudwatch_1 = require("aws-cdk-lib/aws-cloudwatch");
const aws_events_1 = require("aws-cdk-lib/aws-events");
const flow_time_updater_1 = require("./flow-time-updater");
var FlowType;
(function (FlowType) {
FlowType["EVENT"] = "Event";
FlowType["ON_DEMAND"] = "OnDemand";
FlowType["SCHEDULED"] = "Scheduled";
})(FlowType || (exports.FlowType = FlowType = {}));
var FlowStatus;
(function (FlowStatus) {
FlowStatus["ACTIVE"] = "Active";
FlowStatus["SUSPENDED"] = "Suspended";
})(FlowStatus || (exports.FlowStatus = FlowStatus = {}));
var DataPullMode;
(function (DataPullMode) {
DataPullMode["COMPLETE"] = "Complete";
DataPullMode["INCREMENTAL"] = "Incremental";
})(DataPullMode || (exports.DataPullMode = DataPullMode = {}));
class FlowBase extends aws_cdk_lib_1.Resource {
constructor(scope, id, props) {
super(scope, id, {
physicalName: props.name ||
aws_cdk_lib_1.Lazy.string({
produce: () => aws_cdk_lib_1.Names.uniqueResourceName(this, {
maxLength: 256,
allowedSpecialCharacters: "-_",
}),
}),
});
this.mappings = [];
this.validations = [];
this.transforms = [];
this.filters = [];
this.type = props.type;
this._projectionFilter = this.initProjectionFilter(props.source.connectorType);
const resource = new aws_appflow_1.CfnFlow(this, "Resource", {
flowName: this.physicalName,
flowStatus: props.status,
triggerConfig: {
triggerType: props.type,
triggerProperties: props.triggerConfig &&
props.triggerConfig.properties &&
this.buildTriggerProperties(scope, id, props.triggerConfig.properties),
},
kmsArn: props.key?.keyArn,
metadataCatalogConfig: aws_cdk_lib_1.Lazy.any({ produce: () => this._catalogMetadata }),
description: props.description,
sourceFlowConfig: {
...props.source.bind(this),
incrementalPullConfig: this.buildIncrementalPullConfig(props.triggerConfig),
},
// NOTE: currently only a single destination is allowed with AppFlow
// it might require a change of approach in the future.
destinationFlowConfigList: [props.destination.bind(this)],
tasks: aws_cdk_lib_1.Lazy.any({
produce: () => {
const tasks = [
...this.mappings,
...this.transforms,
...this.filters,
...this.validations,
];
// TODO: make sure that this.filters doesn't already have a projection definition
if (this._projectionFilter.sourceFields.length > 0) {
tasks.unshift(this._projectionFilter);
}
return tasks;
},
}),
});
this.arn = resource.attrFlowArn;
this.name = this.physicalName;
this.source = props.source;
props.mappings.forEach((m) => this._addMapping(m));
if (props.validations) {
props.validations.forEach((v) => this._addValidation(v));
}
if (props.transforms) {
props.transforms.forEach((t) => this._addTransform(t));
}
if (props.filters) {
props.filters.forEach((f) => this._addFilter(f));
}
this.node.addValidation({
validate: () => this.mappings.length === 0
? ["A Flow must have at least one mapping"]
: [],
});
}
metric(metricName, options) {
return new aws_cloudwatch_1.Metric({
namespace: "AWS/AppFlow",
metricName,
dimensionsMap: {
FlowName: this.name,
},
...options,
});
}
metricFlowExecutionsStarted(options) {
return this.metric("FlowExecutionsStarted", options);
}
metricFlowExecutionsFailed(options) {
return this.metric("FlowExecutionsFailed", options);
}
metricFlowExecutionsSucceeded(options) {
return this.metric("FlowExecutionsSucceeded", options);
}
metricFlowExecutionTime(options) {
return this.metric("FlowExecutionTime", options);
}
metricFlowExecutionRecordsProcessed(options) {
return this.metric("FlowExecutionRecordsProcessed", options);
}
buildTriggerProperties(scope, id, props) {
const updater = new flow_time_updater_1.FlowTimeUpdater(scope, `${id}Updater`, {
schedule: props.schedule,
startTime: props.properties?.startTime,
endTime: props.properties?.endTime,
});
this.node.addDependency(updater);
return {
dataPullMode: props.dataPullConfig.mode,
flowErrorDeactivationThreshold: props.flowErrorDeactivationThreshold,
scheduleExpression: updater.scheduleExpression,
firstExecutionFrom: props.properties?.firstExecutionFrom &&
Math.floor(props.properties.firstExecutionFrom.getTime() / 1000),
scheduleStartTime: props.properties?.startTime && updater.startTime,
scheduleEndTime: props.properties?.endTime && updater.endTime,
scheduleOffset: props.properties?.offset && props.properties.offset.toSeconds(),
};
}
initProjectionFilter(sourceType) {
const filterConnectorOperator = {};
filterConnectorOperator[sourceType.asTaskConnectorOperatorOrigin] =
"PROJECTION";
return {
taskType: "Filter",
connectorOperator: filterConnectorOperator,
sourceFields: [],
};
}
/**
* Set the catalog definitionfor the flow
*
* @internal
*/
_addCatalog(metadata) {
this._catalogMetadata = metadata;
}
/**
*
* @param validation
* @returns the flow to which the validation was added
*
* @internal
*/
_addValidation(validation) {
this.validations.push(...validation.bind(this, this.source));
return this;
}
/**
*
* @param mapping
* @returns the flow to which the validation was added
*
* @internal
*/
_addMapping(mapping) {
const boundMappingTasks = mapping.bind(this, this.source);
this.addProjectionField(boundMappingTasks);
this.mappings.push(...boundMappingTasks);
return this;
}
/**
*
* @param filter
* @returns the flow to which the validation was added
*
* @internal
*/
_addFilter(filter) {
const boundFilterTasks = filter.bind(this, this.source);
this.addProjectionField(boundFilterTasks);
this.filters.push(...boundFilterTasks);
return this;
}
/**
*
* @param transform
* @returns the flow to which the validation was added
*
* @internal
*/
_addTransform(transform) {
this.transforms.push(...transform.bind(this, this.source));
return this;
}
addProjectionField(boundMappingTasks) {
// TODO: test if this satisfies all the requirements.
boundMappingTasks.forEach((boundMapping) => {
if (["Map", "Filter"].includes(boundMapping.taskType)) {
boundMapping.sourceFields.forEach((field) => {
if (!this._projectionFilter.sourceFields.includes(field)) {
this._projectionFilter.sourceFields.push(field);
}
});
}
});
}
// see: https://docs.aws.amazon.com/appflow/latest/userguide/flow-notifications.html
onEvent(id, options = {}) {
const rule = new aws_events_1.Rule(this, id, options);
rule.addEventPattern({
source: ["aws.appflow"],
resources: [this.arn],
});
rule.addTarget(options.target);
return rule;
}
onRunStarted(id, options = {}) {
const rule = this.onEvent(id, options);
rule.addEventPattern({
detailType: ["AppFlow Start Flow Run Report"],
});
return rule;
}
onRunCompleted(id, options = {}) {
const rule = this.onEvent(id, options);
rule.addEventPattern({
detailType: ["AppFlow End Flow Run Report"],
});
return rule;
}
buildIncrementalPullConfig(triggerConfig) {
return triggerConfig &&
triggerConfig.properties &&
triggerConfig.properties.dataPullConfig &&
triggerConfig.properties.dataPullConfig.timestampField
? {
datetimeTypeFieldName: triggerConfig.properties.dataPullConfig.timestampField,
}
: undefined;
}
}
exports.FlowBase = FlowBase;
_a = JSII_RTTI_SYMBOL_1;
FlowBase[_a] = { fqn: "@cdklabs/cdk-appflow.FlowBase", version: "0.2.3" };
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmxvdy1iYXNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2NvcmUvZmxvd3MvZmxvdy1iYXNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUE7OztFQUdFO0FBQ0YsNkNBQXlFO0FBQ3pFLHlEQUFrRDtBQUVsRCwrREFBbUU7QUFDbkUsdURBQXdFO0FBR3hFLDJEQUFzRDtBQW1GdEQsSUFBWSxRQUlYO0FBSkQsV0FBWSxRQUFRO0lBQ2xCLDJCQUFlLENBQUE7SUFDZixrQ0FBc0IsQ0FBQTtJQUN0QixtQ0FBdUIsQ0FBQTtBQUN6QixDQUFDLEVBSlcsUUFBUSx3QkFBUixRQUFRLFFBSW5CO0FBRUQsSUFBWSxVQUdYO0FBSEQsV0FBWSxVQUFVO0lBQ3BCLCtCQUFpQixDQUFBO0lBQ2pCLHFDQUF1QixDQUFBO0FBQ3pCLENBQUMsRUFIVyxVQUFVLDBCQUFWLFVBQVUsUUFHckI7QUFFRCxJQUFZLFlBR1g7QUFIRCxXQUFZLFlBQVk7SUFDdEIscUNBQXFCLENBQUE7SUFDckIsMkNBQTJCLENBQUE7QUFDN0IsQ0FBQyxFQUhXLFlBQVksNEJBQVosWUFBWSxRQUd2QjtBQW1ERCxNQUFzQixRQUFTLFNBQVEsc0JBQVE7SUEyQjdDLFlBQVksS0FBZ0IsRUFBRSxFQUFVLEVBQUUsS0FBb0I7UUFDNUQsS0FBSyxDQUFDLEtBQUssRUFBRSxFQUFFLEVBQUU7WUFDZixZQUFZLEVBQ1YsS0FBSyxDQUFDLElBQUk7Z0JBQ1Ysa0JBQUksQ0FBQyxNQUFNLENBQUM7b0JBQ1YsT0FBTyxFQUFFLEdBQUcsRUFBRSxDQUNaLG1CQUFLLENBQUMsa0JBQWtCLENBQUMsSUFBSSxFQUFFO3dCQUM3QixTQUFTLEVBQUUsR0FBRzt3QkFDZCx3QkFBd0IsRUFBRSxJQUFJO3FCQUMvQixDQUFDO2lCQUNMLENBQUM7U0FDTCxDQUFDLENBQUM7UUF0QlksYUFBUSxHQUEyQixFQUFFLENBQUM7UUFDdEMsZ0JBQVcsR0FBMkIsRUFBRSxDQUFDO1FB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LFNBQVMsQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDL0IsT0FBTyxJQUFJLENBQUM7SUFDZCxDQUFDO0lBRU0sWUFBWSxDQUFDLEVBQVUsRUFBRSxVQUEwQixFQUFFO1FBQzFELE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsRUFBRSxFQUFFLE9BQU8sQ0FBQyxDQUFDO1FBQ3ZDLElBQUksQ0FBQyxlQUFlLENBQUM7WUFDbkIsVUFBVSxFQUFFLENBQUMsK0JBQStCLENBQUM7U0FDOUMsQ0FBQyxDQUFDO1FBQ0gsT0FBTyxJQUFJLENBQUM7SUFDZCxDQUFDO0lBRU0sY0FBYyxDQUFDLEVBQVUsRUFBRSxVQUEwQixFQUFFO1FBQzVELE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsRUFBRSxFQUFFLE9BQU8sQ0FBQyxDQUFDO1FBQ3ZDLElBQUksQ0FBQyxlQUFlLENBQUM7WUFDbkIsVUFBVSxFQUFFLENBQUMsNkJBQTZCLENBQUM7U0FDNUMsQ0FBQyxDQUFDO1FBQ0gsT0FBTyxJQUFJLENBQUM7SUFDZCxDQUFDO0lBRU8sMEJBQTBCLENBQ2hDLGFBQTZCO1FBRTdCLE9BQU8sYUFBYTtZQUNsQixhQUFhLENBQUMsVUFBVTtZQUN4QixhQUFhLENBQUMsVUFBVSxDQUFDLGNBQWM7WUFDdkMsYUFBYSxDQUFDLFVBQVUsQ0FBQyxjQUFjLENBQUMsY0FBYztZQUN0RCxDQUFDLENBQUM7Z0JBQ0UscUJBQXFCLEVBQ25CLGFBQWEsQ0FBQyxVQUFVLENBQUMsY0FBYyxDQUFDLGNBQWM7YUFDekQ7WUFDSCxDQUFDLENBQUMsU0FBUyxDQUFDO0lBQ2hCLENBQUM7O0FBL1NILDRCQWdUQyIsInNvdXJjZXNDb250ZW50IjpbIi8qXG5Db3B5cmlnaHQgQW1hem9uLmNvbSwgSW5jLiBvciBpdHMgYWZmaWxpYXRlcy4gQWxsIFJpZ2h0cyBSZXNlcnZlZC5cblNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBcGFjaGUtMi4wXG4qL1xuaW1wb3J0IHsgRHVyYXRpb24sIElSZXNvdXJjZSwgTGF6eSwgTmFtZXMsIFJlc291cmNlIH0gZnJvbSBcImF3cy1jZGstbGliXCI7XG5pbXBvcnQgeyBDZm5GbG93IH0gZnJvbSBcImF3cy1jZGstbGliL2F3cy1hcHBmbG93XCI7XG5cbmltcG9ydCB7IE1ldHJpYywgTWV0cmljT3B0aW9ucyB9IGZyb20gXCJhd3MtY2RrLWxpYi9hd3MtY2xvdWR3YXRjaFwiO1xuaW1wb3J0IHsgT25FdmVudE9wdGlvbnMsIFJ1bGUsIFNjaGVkdWxlIH0gZnJvbSBcImF3cy1jZGstbGliL2F3cy1ldmVudHNcIjtcbmltcG9ydCB7IElLZXkgfSBmcm9tIFwiYXdzLWNkay1saWIvYXdzLWttc1wiO1xuaW1wb3J0IHsgQ29uc3RydWN0LCBJQ29uc3RydWN0IH0gZnJvbSBcImNvbnN0cnVjdHNcIjtcbmltcG9ydCB7IEZsb3dUaW1lVXBkYXRlciB9IGZyb20gXCIuL2Zsb3ctdGltZS11cGRhdGVyXCI7XG5pbXBvcnQgeyBDb25uZWN0b3JUeXBlIH0gZnJvbSBcIi4uL2Nvbm5lY3RvcnMvY29ubmVjdG9yLXR5cGVcIjtcblxuaW1wb3J0IHsgSU1hcHBpbmcsIElUcmFuc2Zvcm0sIElGaWx0ZXIsIElWYWxpZGF0aW9uIH0gZnJvbSBcIi4uL3Rhc2tzXCI7XG5pbXBvcnQgeyBJRGVzdGluYXRpb24gfSBmcm9tIFwiLi4vdmVydGljZXMvZGVzdGluYXRpb25cIjtcbmltcG9ydCB7IElTb3VyY2UgfSBmcm9tIFwiLi4vdmVydGljZXMvc291cmNlXCI7XG5cbmV4cG9ydCBpbnRlcmZhY2UgSUZsb3cgZXh0ZW5kcyBJUmVzb3VyY2Uge1xuICAvKipcbiAgICogVGhlIEFSTiBvZiB0aGUgZmxvdy5cbiAgICovXG4gIHJlYWRvbmx5IGFybjogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBUaGUgbmFtZSBvZiB0aGUgZmxvd1xuICAgKi9cbiAgcmVhZG9ubHkgbmFtZTogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBUaGUgdHlwZSBvZiB0aGUgZmxvdy5cbiAgICovXG4gIHJlYWRvbmx5IHR5cGU6IEZsb3dUeXBlO1xuXG4gIG9uUnVuU3RhcnRlZChpZDogc3RyaW5nLCBvcHRpb25zPzogT25FdmVudE9wdGlvbnMpOiBSdWxlO1xuXG4gIG9uUnVuQ29tcGxldGVkKGlkOiBzdHJpbmcsIG9wdGlvbnM/OiBPbkV2ZW50T3B0aW9ucyk6IFJ1bGU7XG5cbiAgLyoqXG4gICAqIENyZWF0ZXMgYSBtZXRyaWMgdG8gcmVwb3J0IHRoZSBudW1iZXIgb2YgZmxvdyBydW5zIHN0YXJ0ZWQuXG4gICAqIEBwYXJhbSBvcHRpb25zXG4gICAqL1xuICBtZXRyaWNGbG93RXhlY3V0aW9uc1N0YXJ0ZWQob3B0aW9ucz86IE1ldHJpY09wdGlvbnMpOiBNZXRyaWM7XG5cbiAgLyoqXG4gICAqIENyZWF0ZXMgYSBtZXRyaWMgdG8gcmVwb3J0IHRoZSBudW1iZXIgb2YgZmFpbGVkIGZsb3cgcnVucy5cbiAgICogQHBhcmFtIG9wdGlvbnNcbiAgICovXG4gIG1ldHJpY0Zsb3dFeGVjdXRpb25zRmFpbGVkKG9wdGlvbnM/OiBNZXRyaWNPcHRpb25zKTogTWV0cmljO1xuXG4gIC8qKlxuICAgKiBDcmVhdGVzIGEgbWV0cmljIHRvIHJlcG9ydCB0aGUgbnVtYmVyIG9mIHN1Y2Nlc3NmdWwgZmxvdyBydW5zLlxuICAgKiBAcGFyYW0gb3B0aW9uc1xuICAgKi9cbiAgbWV0cmljRmxvd0V4ZWN1dGlvbnNTdWNjZWVkZWQob3B0aW9ucz86IE1ldHJpY09wdGlvbnMpOiBNZXRyaWM7XG5cbiAgLyoqXG4gICAqIENyZWF0ZXMgYSBtZXRyaWMgdG8gcmVwb3J0IHRoZSAgaW50ZXJ2YWwsIGluIG1pbGxpc2Vjb25kcywgYmV0d2VlbiB0aGUgdGltZSB0aGUgZmxvdyBzdGFydHMgYW5kIHRoZSB0aW1lIGl0IGZpbmlzaGVzLlxuICAgKiBAcGFyYW0gb3B0aW9uc1xuICAgKi9cbiAgbWV0cmljRmxvd0V4ZWN1dGlvblRpbWUob3B0aW9ucz86IE1ldHJpY09wdGlvbnMpOiBNZXRyaWM7XG5cbiAgLyoqXG4gICAqIENyZWF0ZXMgYSBtZXRyaWMgdG8gcmVwb3J0IHRoZSBudW1iZXIgb2YgcmVjb3JkcyB0aGF0IEFtYXpvbiBBcHBGbG93IGF0dGVtcHRlZCB0byB0cmFuc2ZlciBmb3IgdGhlIGZsb3cgcnVuLlxuICAgKiBAcGFyYW0gb3B0aW9uc1xuICAgKi9cbiAgbWV0cmljRmxvd0V4ZWN1dGlvblJlY29yZHNQcm9jZXNzZWQob3B0aW9ucz86IE1ldHJpY09wdGlvbnMpOiBNZXRyaWM7XG5cbiAgLyoqXG4gICAqIEBpbnRlcm5hbFxuICAgKi9cbiAgX2FkZE1hcHBpbmcobWFwcGluZzogSU1hcHBpbmcpOiBJRmxvdztcblxuICAvKipcbiAgICogQGludGVybmFsXG4gICAqL1xuICBfYWRkVmFsaWRhdGlvbih2YWxpZGF0b3I6IElWYWxpZGF0aW9uKTogSUZsb3c7XG5cbiAgLyoqXG4gICAqIEBpbnRlcm5hbFxuICAgKi9cbiAgX2FkZFRyYW5zZm9ybSh0cmFuc2Zvcm06IElUcmFuc2Zvcm0pOiBJRmxvdztcblxuICAvKipcbiAgICogQGludGVybmFsXG4gICAqL1xuICBfYWRkRmlsdGVyKGZpbHRlcjogSUZpbHRlcik6IElGbG93O1xuXG4gIC8qKlxuICAgKiBAaW50ZXJuYWxcbiAgICovXG4gIF9hZGRDYXRhbG9nKG1ldGFkYXRhOiBDZm5GbG93Lk1ldGFkYXRhQ2F0YWxvZ0NvbmZpZ1Byb3BlcnR5KTogdm9pZDtcbn1cblxuZXhwb3J0IGVudW0gRmxvd1R5cGUge1xuICBFVkVOVCA9IFwiRXZlbnRcIixcbiAgT05fREVNQU5EID0gXCJPbkRlbWFuZFwiLFxuICBTQ0hFRFVMRUQgPSBcIlNjaGVkdWxlZFwiLFxufVxuXG5leHBvcnQgZW51bSBGbG93U3RhdHVzIHtcbiAgQUNUSVZFID0gXCJBY3RpdmVcIixcbiAgU1VTUEVOREVEID0gXCJTdXNwZW5kZWRcIixcbn1cblxuZXhwb3J0IGVudW0gRGF0YVB1bGxNb2RlIHtcbiAgQ09NUExFVEUgPSBcIkNvbXBsZXRlXCIsXG4gIElOQ1JFTUVOVEFMID0gXCJJbmNyZW1lbnRhbFwiLFxufVxuXG5leHBvcnQgaW50ZXJmYWNlIERhdGFQdWxsQ29uZmlnIHtcbiAgcmVhZG9ubHkgbW9kZTogRGF0YVB1bGxNb2RlO1xuICAvKipcbiAgICogVGhlIG5hbWUgb2YgdGhlIGZpZWxkIHRvIHVzZSBhcyBhIHRpbWVzdGFtcCBmb3IgcmVjdXJyaW5nIGluY3JlbWVudGFsIGZsb3dzLlxuICAgKiBUaGUgZGVmYXVsdCBmaWVsZCBpcyBzZXQgcGVyIHBhcnRpY3VsYXIgQHNlZSBJU291cmNlLlxuICAgKi9cbiAgcmVhZG9ubHkgdGltZXN0YW1wRmllbGQ/OiBzdHJpbmc7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgU2NoZWR1bGVQcm9wZXJ0aWVzIHtcbiAgcmVhZG9ubHkgc3RhcnRUaW1lPzogRGF0ZTtcbiAgcmVhZG9ubHkgZW5kVGltZT86IERhdGU7XG4gIHJlYWRvbmx5IG9mZnNldD86IER1cmF0aW9uO1xuICAvKipcbiAgICogVGltZXN0YW1wIGZvciB0aGUgcmVjb3JkcyB0byBpbXBvcnQgZnJvbSB0aGUgY29ubmVjdG9yIGluIHRoZSBmaXJzdCBmbG93IHJ1blxuICAgKiBAZGVmYXVsdCAzMCBkYXlzIGJhY2sgZnJvbSB0aGUgaW5pdGlhbCBmcm93IHJ1blxuICAgKi9cbiAgcmVhZG9ubHkgZmlyc3RFeGVjdXRpb25Gcm9tPzogRGF0ZTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBUcmlnZ2VyUHJvcGVydGllcyB7XG4gIHJlYWRvbmx5IGRhdGFQdWxsQ29uZmlnOiBEYXRhUHVsbENvbmZpZztcbiAgcmVhZG9ubHkgc2NoZWR1bGU6IFNjaGVkdWxlO1xuICByZWFkb25seSBwcm9wZXJ0aWVzPzogU2NoZWR1bGVQcm9wZXJ0aWVzO1xuICByZWFkb25seSBmbG93RXJyb3JEZWFjdGl2YXRpb25UaHJlc2hvbGQ/OiBudW1iZXI7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgVHJpZ2dlckNvbmZpZyB7XG4gIHJlYWRvbmx5IHByb3BlcnRpZXM/OiBUcmlnZ2VyUHJvcGVydGllcztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBGbG93UHJvcHMge1xuICByZWFkb25seSBuYW1lPzogc3RyaW5nO1xuICByZWFkb25seSBkZXNjcmlwdGlvbj86IHN0cmluZztcbiAgcmVhZG9ubHkgc291cmNlOiBJU291cmNlO1xuICByZWFkb25seSBkZXN0aW5hdGlvbjogSURlc3RpbmF0aW9uO1xuICByZWFkb25seSBtYXBwaW5nczogSU1hcHBpbmdbXTtcbiAgcmVhZG9ubHkgdmFsaWRhdGlvbnM/OiBJVmFsaWRhdGlvbltdO1xuICByZWFkb25seSB0cmFuc2Zvcm1zPzogSVRyYW5zZm9ybVtdO1xuICByZWFkb25seSBmaWx0ZXJzPzogSUZpbHRlcltdO1xuICByZWFkb25seSBrZXk/OiBJS2V5O1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEZsb3dCYXNlUHJvcHMgZXh0ZW5kcyBGbG93UHJvcHMge1xuICByZWFkb25seSB0eXBlOiBGbG93VHlwZTtcbiAgcmVhZG9ubHkgdHJpZ2dlckNvbmZpZz86IFRyaWdnZXJDb25maWc7XG4gIHJlYWRvbmx5IHN0YXR1cz86IEZsb3dTdGF0dXM7XG59XG5cbmV4cG9ydCBhYnN0cmFjdCBjbGFzcyBGbG93QmFzZSBleHRlbmRzIFJlc291cmNlIGltcGxlbWVudHMgSUZsb3cge1xuICAvKipcbiAgICogVGhlIEFSTiBvZiB0aGUgZmxvdy5cbiAgICovXG4gIHB1YmxpYyByZWFkb25seSBhcm46IHN0cmluZztcblxuICAvKipcbiAgICogVGhlIHR5cGUgb2YgdGhlIGZsb3cuXG4gICAqL1xuICBwdWJsaWMgcmVhZG9ubHkgdHlwZTogRmxvd1R5cGU7XG5cbiAgLyoqXG4gICAqIFRoZSBuYW1lIG9mIHRoZSBmbG93LlxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IG5hbWU6IHN0cmluZztcblxuICBwcml2YXRlIHJlYWRvbmx5IG1hcHBpbmdzOiBDZm5GbG93LlRhc2tQcm9wZXJ0eVtdID0gW107XG4gIHByaXZhdGUgcmVhZG9ubHkgdmFsaWRhdGlvbnM6IENmbkZsb3cuVGFza1Byb3BlcnR5W10gPSBbXTtcbiAgcHJpdmF0ZSByZWFkb25seSB0cmFuc2Zvcm1zOiBDZm5GbG93LlRhc2tQcm9wZXJ0eVtdID0gW107XG4gIHByaXZhdGUgcmVhZG9ubHkgZmlsdGVyczogQ2ZuRmxvdy5UYXNrUHJvcGVydHlbXSA9IFtdO1xuICBwcml2YXRlIHJlYWRvbmx5IHNvdXJjZTogSVNvdXJjZTtcbiAgcHJpdmF0ZSBfY2F0YWxvZ01ldGFkYXRhPzogQ2ZuRmxvdy5NZXRhZGF0YUNhdGFsb2dDb25maWdQcm9wZXJ0eTtcbiAgLy8gVE9ETzogbWFrZSBpdCBvcHRpb25hbC5cbiAgLy8gVGhhdCBpczogaWYgc29tZWJvZHkgcGFzc2VzcyBwcm9qZWN0aW9uIGFzIGEgZmlsdGVyXG4gIC8vICAgICAgICAgIHRoaXMgc2hvdWxkIG5vdCBiZSB1c2VkLlxuICBwcml2YXRlIF9wcm9qZWN0aW9uRmlsdGVyOiBDZm5GbG93LlRhc2tQcm9wZXJ0eTtcblxuICBjb25zdHJ1Y3RvcihzY29wZTogQ29uc3RydWN0LCBpZDogc3RyaW5nLCBwcm9wczogRmxvd0Jhc2VQcm9wcykge1xuICAgIHN1cGVyKHNjb3BlLCBpZCwge1xuICAgICAgcGh5c2ljYWxOYW1lOlxuICAgICAgICBwcm9wcy5uYW1lIHx8XG4gICAgICAgIExhenkuc3RyaW5nKHtcbiAgICAgICAgICBwcm9kdWNlOiAoKSA9PlxuICAgICAgICAgICAgTmFtZXMudW5pcXVlUmVzb3VyY2VOYW1lKHRoaXMsIHtcbiAgICAgICAgICAgICAgbWF4TGVuZ3RoOiAyNTYsXG4gICAgICAgICAgICAgIGFsbG93ZWRTcGVjaWFsQ2hhcmFjdGVyczogXCItX1wiLFxuICAgICAgICAgICAgfSksXG4gICAgICAgIH0pLFxuICAgIH0pO1xuXG4gICAgdGhpcy50eXBlID0gcHJvcHMudHlwZTtcblxuICAgIHRoaXMuX3Byb2plY3Rpb25GaWx0ZXIgPSB0aGlzLmluaXRQcm9qZWN0aW9uRmlsdGVyKFxuICAgICAgcHJvcHMuc291cmNlLmNvbm5lY3RvclR5cGUsXG4gICAgKTtcblxuICAgIGNvbnN0IHJlc291cmNlID0gbmV3IENmbkZsb3codGhpcywgXCJSZXNvdXJjZVwiLCB7XG4gICAgICBmbG93TmFtZTogdGhpcy5waHlzaWNhbE5hbWUsXG4gICAgICBmbG93U3RhdHVzOiBwcm9wcy5zdGF0dXMsXG4gICAgICB0cmlnZ2VyQ29uZmlnOiB7XG4gICAgICAgIHRyaWdnZXJUeXBlOiBwcm9wcy50eXBlLFxuICAgICAgICB0cmlnZ2VyUHJvcGVydGllczpcbiAgICAgICAgICBwcm9wcy50cmlnZ2VyQ29uZmlnICYmXG4gICAgICAgICAgcHJvcHMudHJpZ2dlckNvbmZpZy5wcm9wZXJ0aWVzICYmXG4gICAgICAgICAgdGhpcy5idWlsZFRyaWdnZXJQcm9wZXJ0aWVzKFxuICAgICAgICAgICAgc2NvcGUsXG4gICAgICAgICAgICBpZCxcbiAgICAgICAgICAgIHByb3BzLnRyaWdnZXJDb25maWcucHJvcGVydGllcyxcbiAgICAgICAgICApLFxuICAgICAgfSxcbiAgICAgIGttc0FybjogcHJvcHMua2V5Py5rZXlBcm4sXG4gICAgICBtZXRhZGF0YUNhdGFsb2dDb25maWc6IExhenkuYW55KHsgcHJvZHVjZTogKCkgPT4gdGhpcy5fY2F0YWxvZ01ldGFkYXRhIH0pLFxuICAgICAgZGVzY3JpcHRpb246IHByb3BzLmRlc2NyaXB0aW9uLFxuICAgICAgc291cmNlRmxvd0NvbmZpZzoge1xuICAgICAgICAuLi5wcm9wcy5zb3VyY2UuYmluZCh0aGlzKSxcbiAgICAgICAgaW5jcmVtZW50YWxQdWxsQ29uZmlnOiB0aGlzLmJ1aWxkSW5jcmVtZW50YWxQdWxsQ29uZmlnKFxuICAgICAgICAgIHByb3BzLnRyaWdnZXJDb25maWcsXG4gICAgICAgICksXG4gICAgICB9LFxuICAgICAgLy8gTk9URTogY3VycmVudGx5IG9ubHkgYSBzaW5nbGUgZGVzdGluYXRpb24gaXMgYWxsb3dlZCB3aXRoIEFwcEZsb3dcbiAgICAgIC8vICAgICAgIGl0IG1pZ2h0IHJlcXVpcmUgYSBjaGFuZ2Ugb2YgYXBwcm9hY2ggaW4gdGhlIGZ1dHVyZS5cbiAgICAgIGRlc3RpbmF0aW9uRmxvd0NvbmZpZ0xpc3Q6IFtwcm9wcy5kZXN0aW5hdGlvbi5iaW5kKHRoaXMpXSxcbiAgICAgIHRhc2tzOiBMYXp5LmFueSh7XG4gICAgICAgIHByb2R1Y2U6ICgpID0+IHtcbiAgICAgICAgICBjb25zdCB0YXNrcyA9IFtcbiAgICAgICAgICAgIC4uLnRoaXMubWFwcGluZ3MsXG4gICAgICAgICAgICAuLi50aGlzLnRyYW5zZm9ybXMsXG4gICAgICAgICAgICAuLi50aGlzLmZpbHRlcnMsXG4gICAgICAgICAgICAuLi50aGlzLnZhbGlkYXRpb25zLFxuICAgICAgICAgIF07XG5cbiAgICAgICAgICAvLyBUT0RPOiBtYWtlIHN1cmUgdGhhdCB0aGlzLmZpbHRlcnMgZG9lc24ndCBhbHJlYWR5IGhhdmUgYSBwcm9qZWN0aW9uIGRlZmluaXRpb25cbiAgICAgICAgICBpZiAodGhpcy5fcHJvamVjdGlvbkZpbHRlci5zb3VyY2VGaWVsZHMubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgdGFza3MudW5zaGlmdCh0aGlzLl9wcm9qZWN0aW9uRmlsdGVyKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICByZXR1cm4gdGFza3M7XG4gICAgICAgIH0sXG4gICAgICB9KSxcbiAgICB9KTtcblxuICAgIHRoaXMuYXJuID0gcmVzb3VyY2UuYXR0ckZsb3dBcm47XG4gICAgdGhpcy5uYW1lID0gdGhpcy5waHlzaWNhbE5hbWU7XG4gICAgdGhpcy5zb3VyY2UgPSBwcm9wcy5zb3VyY2U7XG5cbiAgICBwcm9wcy5tYXBwaW5ncy5mb3JFYWNoKChtKSA9PiB0aGlzLl9hZGRNYXBwaW5nKG0pKTtcblxuICAgIGlmIChwcm9wcy52YWxpZGF0aW9ucykge1xuICAgICAgcHJvcHMudmFsaWRhdGlvbnMuZm9yRWFjaCgodikgPT4gdGhpcy5fYWRkVmFsaWRhdGlvbih2KSk7XG4gICAgfVxuXG4gICAgaWYgKHByb3BzLnRyYW5zZm9ybXMpIHtcbiAgICAgIHByb3BzLnRyYW5zZm9ybXMuZm9yRWFjaCgodCkgPT4gdGhpcy5fYWRkVHJhbnNmb3JtKHQpKTtcbiAgICB9XG5cbiAgICBpZiAocHJvcHMuZmlsdGVycykge1xuICAgICAgcHJvcHMuZmlsdGVycy5mb3JFYWNoKChmKSA9PiB0aGlzLl9hZGRGaWx0ZXIoZikpO1xuICAgIH1cblxuICAgIHRoaXMubm9kZS5hZGRWYWxpZGF0aW9uKHtcbiAgICAgIHZhbGlkYXRlOiAoKSA9PlxuICAgICAgICB0aGlzLm1hcHBpbmdzLmxlbmd0aCA9PT0gMFxuICAgICAgICAgID8gW1wiQSBGbG93IG11c3QgaGF2ZSBhdCBsZWFzdCBvbmUgbWFwcGluZ1wiXVxuICAgICAgICAgIDogW10sXG4gICAgfSk7XG4gIH1cblxuICBwdWJsaWMgbWV0cmljKG1ldHJpY05hbWU6IHN0cmluZywgb3B0aW9ucz86IE1ldHJpY09wdGlvbnMpOiBNZXRyaWMge1xuICAgIHJldHVybiBuZXcgTWV0cmljKHtcbiAgICAgIG5hbWVzcGFjZTogXCJBV1MvQXBwRmxvd1wiLFxuICAgICAgbWV0cmljTmFtZSxcbiAgICAgIGRpbWVuc2lvbnNNYXA6IHtcbiAgICAgICAgRmxvd05hbWU6IHRoaXMubmFtZSxcbiAgICAgIH0sXG4gICAgICAuLi5vcHRpb25zLFxuICAgIH0pO1xuICB9XG5cbiAgcHVibGljIG1ldHJpY0Zsb3dFeGVjdXRpb25zU3RhcnRlZChvcHRpb25zPzogTWV0cmljT3B0aW9ucyk6IE1ldHJpYyB7XG4gICAgcmV0dXJuIHRoaXMubWV0cmljKFwiRmxvd0V4ZWN1dGlvbnNTdGFydGVkXCIsIG9wdGlvbnMpO1xuICB9XG5cbiAgcHVibGljIG1ldHJpY0Zsb3dFeGVjdXRpb25zRmFpbGVkKG9wdGlvbnM/OiBNZXRyaWNPcHRpb25zKTogTWV0cmljIHtcbiAgICByZXR1cm4gdGhpcy5tZXRyaWMoXCJGbG93RXhlY3V0aW9uc0ZhaWxlZFwiLCBvcHRpb25zKTtcbiAgfVxuXG4gIHB1YmxpYyBtZXRyaWNGbG93RXhlY3V0aW9uc1N1Y2NlZWRlZChvcHRpb25zPzogTWV0cmljT3B0aW9ucyk6IE1ldHJpYyB7XG4gICAgcmV0dXJuIHRoaXMubWV0cmljKFwiRmxvd0V4ZWN1dGlvbnNTdWNjZWVkZWRcIiwgb3B0aW9ucyk7XG4gIH1cblxuICBwdWJsaWMgbWV0cmljRmxvd0V4ZWN1dGlvblRpbWUob3B0aW9ucz86IE1ldHJpY09wdGlvbnMpOiBNZXRyaWMge1xuICAgIHJldHVybiB0aGlzLm1ldHJpYyhcIkZsb3dFeGVjdXRpb25UaW1lXCIsIG9wdGlvbnMpO1xuICB9XG5cbiAgcHVibGljIG1ldHJpY0Zsb3dFeGVjdXRpb25SZWNvcmRzUHJvY2Vzc2VkKG9wdGlvbnM/OiBNZXRyaWNPcHRpb25zKTogTWV0cmljIHtcbiAgICByZXR1cm4gdGhpcy5tZXRyaWMoXCJGbG93RXhlY3V0aW9uUmVjb3Jkc1Byb2Nlc3NlZFwiLCBvcHRpb25zKTtcbiAgfVxuXG4gIHByaXZhdGUgYnVpbGRUcmlnZ2VyUHJvcGVydGllcyhcbiAgICBzY29wZTogSUNvbnN0cnVjdCxcbiAgICBpZDogc3RyaW5nLFxuICAgIHByb3BzOiBUcmlnZ2VyUHJvcGVydGllcyxcbiAgKTogQ2ZuRmxvdy5TY2hlZHVsZWRUcmlnZ2VyUHJvcGVydGllc1Byb3BlcnR5IHtcbiAgICBjb25zdCB1cGRhdGVyID0gbmV3IEZsb3dUaW1lVXBkYXRlcihzY29wZSwgYCR7aWR9VXBkYXRlcmAsIHtcbiAgICAgIHNjaGVkdWxlOiBwcm9wcy5zY2hlZHVsZSxcbiAgICAgIHN0YXJ0VGltZTogcHJvcHMucHJvcGVydGllcz8uc3RhcnRUaW1lLFxuICAgICAgZW5kVGltZTogcHJvcHMucHJvcGVydGllcz8uZW5kVGltZSxcbiAgICB9KTtcblxuICAgIHRoaXMubm9kZS5hZGREZXBlbmRlbmN5KHVwZGF0ZXIpO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgIGRhdGFQdWxsTW9kZTogcHJvcHMuZGF0YVB1bGxDb25maWcubW9kZSxcbiAgICAgIGZsb3dFcnJvckRlYWN0aXZhdGlvblRocmVzaG9sZDogcHJvcHMuZmxvd0Vycm9yRGVhY3RpdmF0aW9uVGhyZXNob2xkLFxuICAgICAgc2NoZWR1bGVFeHByZXNzaW9uOiB1cGRhdGVyLnNjaGVkdWxlRXhwcmVzc2lvbixcbiAgICAgIGZpcnN0RXhlY3V0aW9uRnJvbTpcbiAgICAgICAgcHJvcHMucHJvcGVydGllcz8uZmlyc3RFeGVjdXRpb25Gcm9tICYmXG4gICAgICAgIE1hdGguZmxvb3IocHJvcHMucHJvcGVydGllcy5maXJzdEV4ZWN1dGlvbkZyb20uZ2V0VGltZSgpIC8gMTAwMCksXG4gICAgICBzY2hlZHVsZVN0YXJ0VGltZTogcHJvcHMucHJvcGVydGllcz8uc3RhcnRUaW1lICYmIHVwZGF0ZXIuc3RhcnRUaW1lLFxuICAgICAgc2NoZWR1bGVFbmRUaW1lOiBwcm9wcy5wcm9wZXJ0aWVzPy5lbmRUaW1lICYmIHVwZGF0ZXIuZW5kVGltZSxcbiAgICAgIHNjaGVkdWxlT2Zmc2V0OlxuICAgICAgICBwcm9wcy5wcm9wZXJ0aWVzPy5vZmZzZXQgJiYgcHJvcHMucHJvcGVydGllcy5vZmZzZXQudG9TZWNvbmRzKCksXG4gICAgfTtcbiAgfVxuXG4gIHByaXZhdGUgaW5pdFByb2plY3Rpb25GaWx0ZXIoXG4gICAgc291cmNlVHlwZTogQ29ubmVjdG9yVHlwZSxcbiAgKTogQ2ZuRmxvdy5UYXNrUHJvcGVydHkge1xuICAgIGNvbnN0IGZpbHRlckNvbm5lY3Rvck9wZXJhdG9yOiB7IFtrZXk6IHN0cmluZ106IHN0cmluZyB9ID0ge307XG4gICAgZmlsdGVyQ29ubmVjdG9yT3BlcmF0b3Jbc291cmNlVHlwZS5hc1Rhc2tDb25uZWN0b3JPcGVyYXRvck9yaWdpbl0gPVxuICAgICAgXCJQUk9KRUNUSU9OXCI7XG5cbiAgICByZXR1cm4ge1xuICAgICAgdGFza1R5cGU6IFwiRmlsdGVyXCIsXG4gICAgICBjb25uZWN0b3JPcGVyYXRvcjogZmlsdGVyQ29ubmVjdG9yT3BlcmF0b3IsXG4gICAgICBzb3VyY2VGaWVsZHM6IFtdLFxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogU2V0IHRoZSBjYXRhbG9nIGRlZmluaXRpb25mb3IgdGhlIGZsb3dcbiAgICpcbiAgICogQGludGVybmFsXG4gICAqL1xuICBwdWJsaWMgX2FkZENhdGFsb2cobWV0YWRhdGE6IENmbkZsb3cuTWV0YWRhdGFDYXRhbG9nQ29uZmlnUHJvcGVydHkpIHtcbiAgICB0aGlzLl9jYXRhbG9nTWV0YWRhdGEgPSBtZXRhZGF0YTtcbiAgfVxuXG4gIC8qKlxuICAgKlxuICAgKiBAcGFyYW0gdmFsaWRhdGlvblxuICAgKiBAcmV0dXJucyB0aGUgZmxvdyB0byB3aGljaCB0aGUgdmFsaWRhdGlvbiB3YXMgYWRkZWRcbiAgICpcbiAgICogQGludGVybmFsXG4gICAqL1xuICBwdWJsaWMgX2FkZFZhbGlkYXRpb24odmFsaWRhdGlvbjogSVZhbGlkYXRpb24pOiBJRmxvdyB7XG4gICAgdGhpcy52YWxpZGF0aW9ucy5wdXNoKC4uLnZhbGlkYXRpb24uYmluZCh0aGlzLCB0aGlzLnNvdXJjZSkpO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLyoqXG4gICAqXG4gICAqIEBwYXJhbSBtYXBwaW5nXG4gICAqIEByZXR1cm5zIHRoZSBmbG93IHRvIHdoaWNoIHRoZSB2YWxpZGF0aW9uIHdhcyBhZGRlZFxuICAgKlxuICAgKiBAaW50ZXJuYWxcbiAgICovXG4gIHB1YmxpYyBfYWRkTWFwcGluZyhtYXBwaW5nOiBJTWFwcGluZyk6IElGbG93IHtcbiAgICBjb25zdCBib3VuZE1hcHBpbmdUYXNrcyA9IG1hcHBpbmcuYmluZCh0aGlzLCB0aGlzLnNvdXJjZSk7XG4gICAgdGhpcy5hZGRQcm9qZWN0aW9uRmllbGQoYm91bmRNYXBwaW5nVGFza3MpO1xuICAgIHRoaXMubWFwcGluZ3MucHVzaCguLi5ib3VuZE1hcHBpbmdUYXNrcyk7XG5cbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIC8qKlxuICAgKlxuICAgKiBAcGFyYW0gZmlsdGVyXG4gICAqIEByZXR1cm5zIHRoZSBmbG93IHRvIHdoaWNoIHRoZSB2YWxpZGF0aW9uIHdhcyBhZGRlZFxuICAgKlxuICAgKiBAaW50ZXJuYWxcbiAgICovXG4gIHB1YmxpYyBfYWRkRmlsdGVyKGZpbHRlcjogSUZpbHRlcik6IElGbG93IHtcbiAgICBjb25zdCBib3VuZEZpbHRlclRhc2tzID0gZmlsdGVyLmJpbmQodGhpcywgdGhpcy5zb3VyY2UpO1xuICAgIHRoaXMuYWRkUHJvamVjdGlvbkZpZWxkKGJvdW5kRmlsdGVyVGFza3MpO1xuICAgIHRoaXMuZmlsdGVycy5wdXNoKC4uLmJvdW5kRmlsdGVyVGFza3MpO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLyoqXG4gICAqXG4gICAqIEBwYXJhbSB0cmFuc2Zvcm1cbiAgICogQHJldHVybnMgdGhlIGZsb3cgdG8gd2hpY2ggdGhlIHZhbGlkYXRpb24gd2FzIGFkZGVkXG4gICAqXG4gICAqIEBpbnRlcm5hbFxuICAgKi9cbiAgcHVibGljIF9hZGRUcmFuc2Zvcm0odHJhbnNmb3JtOiBJVHJhbnNmb3JtKTogSUZsb3cge1xuICAgIHRoaXMudHJhbnNmb3Jtcy5wdXNoKC4uLnRyYW5zZm9ybS5iaW5kKHRoaXMsIHRoaXMuc291cmNlKSk7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICBwcml2YXRlIGFkZFByb2plY3Rpb25GaWVsZChib3VuZE1hcHBpbmdUYXNrczogQ2ZuRmxvdy5UYXNrUHJvcGVydHlbXSkge1xuICAgIC8vIFRPRE86IHRlc3QgaWYgdGhpcyBzYXRpc2ZpZXMgYWxsIHRoZSByZXF1aXJlbWVudHMuXG4gICAgYm91bmRNYXBwaW5nVGFza3MuZm9yRWFjaCgoYm91bmRNYXBwaW5nKSA9PiB7XG4gICAgICBpZiAoW1wiTWFwXCIsIFwiRmlsdGVyXCJdLmluY2x1ZGVzKGJvdW5kTWFwcGluZy50YXNrVHlwZSkpIHtcbiAgICAgICAgYm91bmRNYXBwaW5nLnNvdXJjZUZpZWxkcy5mb3JFYWNoKChmaWVsZCkgPT4ge1xuICAgICAgICAgIGlmICghdGhpcy5fcHJvamVjdGlvbkZpbHRlci5zb3VyY2VGaWVsZHMuaW5jbHVkZXMoZmllbGQpKSB7XG4gICAgICAgICAgICB0aGlzLl9wcm9qZWN0aW9uRmlsdGVyLnNvdXJjZUZpZWxkcy5wdXNoKGZpZWxkKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgLy8gc2VlOiBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vYXBwZmxvdy9sYXRlc3QvdXNlcmd1aWRlL2Zsb3ctbm90aWZpY2F0aW9ucy5odG1sXG4gIHB1YmxpYyBvbkV2ZW50KGlkOiBzdHJpbmcsIG9wdGlvbnM6IE9uRXZlbnRPcHRpb25zID0ge30pIHtcbiAgICBjb25zdCBydWxlID0gbmV3IFJ1bGUodGhpcywgaWQsIG9wdGlvbnMpO1xuICAgIHJ1bGUuYWRkRXZlbnRQYXR0ZXJuKHtcbiAgICAgIHNvdXJjZTogW1wiYXdzLmFwcGZsb3dcIl0sXG4gICAgICByZXNvdXJjZXM6IFt0aGlzLmFybl0sXG4gICAgfSk7XG4gICAgcnVsZS5hZGRUYXJnZXQob3B0aW9ucy50YXJnZXQpO1xuICAgIHJldHVybiBydWxlO1xuICB9XG5cbiAgcHVibGljIG9uUnVuU3RhcnRlZChpZDogc3RyaW5nLCBvcHRpb25zOiBPbkV2ZW50T3B0aW9ucyA9IHt9KSB7XG4gICAgY29uc3QgcnVsZSA9IHRoaXMub25FdmVudChpZCwgb3B0aW9ucyk7XG4gICAgcnVsZS5hZGRFdmVudFBhdHRlcm4oe1xuICAgICAgZGV0YWlsVHlwZTogW1wiQXBwRmxvdyBTdGFydCBGbG93IFJ1biBSZXBvcnRcIl0sXG4gICAgfSk7XG4gICAgcmV0dXJuIHJ1bGU7XG4gIH1cblxuICBwdWJsaWMgb25SdW5Db21wbGV0ZWQoaWQ6IHN0cmluZywgb3B0aW9uczogT25FdmVudE9wdGlvbnMgPSB7fSkge1xuICAgIGNvbnN0IHJ1bGUgPSB0aGlzLm9uRXZlbnQoaWQsIG9wdGlvbnMpO1xuICAgIHJ1bGUuYWRkRXZlbnRQYXR0ZXJuKHtcbiAgICAgIGRldGFpbFR5cGU6IFtcIkFwcEZsb3cgRW5kIEZsb3cgUnVuIFJlcG9ydFwiXSxcbiAgICB9KTtcbiAgICByZXR1cm4gcnVsZTtcbiAgfVxuXG4gIHByaXZhdGUgYnVpbGRJbmNyZW1lbnRhbFB1bGxDb25maWcoXG4gICAgdHJpZ2dlckNvbmZpZz86IFRyaWdnZXJDb25maWcsXG4gICk6IENmbkZsb3cuSW5jcmVtZW50YWxQdWxsQ29uZmlnUHJvcGVydHkgfCB1bmRlZmluZWQge1xuICAgIHJldHVybiB0cmlnZ2VyQ29uZmlnICYmXG4gICAgICB0cmlnZ2VyQ29uZmlnLnByb3BlcnRpZXMgJiZcbiAgICAgIHRyaWdnZXJDb25maWcucHJvcGVydGllcy5kYXRhUHVsbENvbmZpZyAmJlxuICAgICAgdHJpZ2dlckNvbmZpZy5wcm9wZXJ0aWVzLmRhdGFQdWxsQ29uZmlnLnRpbWVzdGFtcEZpZWxkXG4gICAgICA/IHtcbiAgICAgICAgICBkYXRldGltZVR5cGVGaWVsZE5hbWU6XG4gICAgICAgICAgICB0cmlnZ2VyQ29uZmlnLnByb3BlcnRpZXMuZGF0YVB1bGxDb25maWcudGltZXN0YW1wRmllbGQsXG4gICAgICAgIH1cbiAgICAgIDogdW5kZWZpbmVkO1xuICB9XG59XG4iXX0=