394 lines
72 KiB
JavaScript
394 lines
72 KiB
JavaScript
import { AmplifyUserError, CallerDirectoryExtractor, TagName, } from '@aws-amplify/platform-core';
|
|
import { Duration, Size, Stack, Tags } from 'aws-cdk-lib';
|
|
import * as scheduler from 'aws-cdk-lib/aws-scheduler';
|
|
import * as targets from 'aws-cdk-lib/aws-scheduler-targets';
|
|
import { Architecture, LayerVersion, Runtime, } from 'aws-cdk-lib/aws-lambda';
|
|
import { LogLevel as EsBuildLogLevel, NodejsFunction, OutputFormat, } from 'aws-cdk-lib/aws-lambda-nodejs';
|
|
import { readFileSync } from 'fs';
|
|
import { createRequire } from 'module';
|
|
import { EOL } from 'os';
|
|
import * as path from 'path';
|
|
import { FunctionEnvironmentTranslator } from './function_env_translator.js';
|
|
import { FunctionEnvironmentTypeGenerator } from './function_env_type_generator.js';
|
|
import { FunctionLayerArnParser } from './layer_parser.js';
|
|
import { convertLoggingOptionsToCDK, createLogGroup, } from './logging_options_parser.js';
|
|
import { convertFunctionSchedulesToScheduleProps } from './schedule_parser.js';
|
|
import { ProvidedFunctionFactory, } from './provided_function_factory.js';
|
|
import { AmplifyFunctionBase } from './function_construct_base.js';
|
|
import { FunctionResourceAccessAcceptor } from './resource_access_acceptor.js';
|
|
/**
|
|
* Entry point for defining a function in the Amplify ecosystem
|
|
*/
|
|
// This is the "implementation overload", it's not visible in public api.
|
|
// We have to use function notation instead of arrow notation.
|
|
// Arrow notation does not support overloads.
|
|
// eslint-disable-next-line no-restricted-syntax
|
|
export function defineFunction(propsOrProvider = {}, providerProps) {
|
|
if (propsOrProvider && typeof propsOrProvider === 'function') {
|
|
return new ProvidedFunctionFactory(propsOrProvider, providerProps);
|
|
}
|
|
return new FunctionFactory(propsOrProvider, new Error().stack);
|
|
}
|
|
/**
|
|
* Create Lambda functions in the context of an Amplify backend definition
|
|
*/
|
|
class FunctionFactory {
|
|
props;
|
|
callerStack;
|
|
generator;
|
|
/**
|
|
* Create a new AmplifyFunctionFactory
|
|
*/
|
|
constructor(props, callerStack) {
|
|
this.props = props;
|
|
this.callerStack = callerStack;
|
|
}
|
|
/**
|
|
* Creates an instance of AmplifyFunction within the provided Amplify context
|
|
*/
|
|
getInstance = ({ constructContainer, outputStorageStrategy, resourceNameValidator, }) => {
|
|
if (!this.generator) {
|
|
this.generator = new FunctionGenerator(this.hydrateDefaults(resourceNameValidator), outputStorageStrategy);
|
|
}
|
|
return constructContainer.getOrCompute(this.generator);
|
|
};
|
|
hydrateDefaults = (resourceNameValidator) => {
|
|
const name = this.resolveName();
|
|
resourceNameValidator?.validate(name);
|
|
return {
|
|
name,
|
|
entry: this.resolveEntry(),
|
|
timeoutSeconds: this.resolveTimeout(),
|
|
memoryMB: this.resolveMemory(),
|
|
ephemeralStorageSizeMB: this.resolveEphemeralStorageSize(),
|
|
environment: this.resolveEnvironment(),
|
|
runtime: this.resolveRuntime(),
|
|
architecture: this.resolveArchitecture(),
|
|
schedule: this.resolveSchedule(),
|
|
bundling: this.resolveBundling(),
|
|
layers: this.props.layers ?? {},
|
|
resourceGroupName: this.props.resourceGroupName ?? 'function',
|
|
logging: this.props.logging ?? {},
|
|
durableConfig: this.resolveDurableConfig(),
|
|
};
|
|
};
|
|
resolveName = () => {
|
|
// If name is set explicitly, use that
|
|
if (this.props.name) {
|
|
return this.props.name;
|
|
}
|
|
// If entry is set, use the basename of the entry path
|
|
if (this.props.entry) {
|
|
return path.parse(this.props.entry).name;
|
|
}
|
|
// Otherwise, use the directory name where the function is defined
|
|
return path.basename(new CallerDirectoryExtractor(this.callerStack).extract());
|
|
};
|
|
resolveEntry = () => {
|
|
// if entry is not set, default to handler.ts
|
|
if (!this.props.entry) {
|
|
return path.join(new CallerDirectoryExtractor(this.callerStack).extract(), 'handler.ts');
|
|
}
|
|
// if entry is absolute use that
|
|
if (path.isAbsolute(this.props.entry)) {
|
|
return this.props.entry;
|
|
}
|
|
// if entry is relative, compute with respect to the caller directory
|
|
return path.join(new CallerDirectoryExtractor(this.callerStack).extract(), this.props.entry);
|
|
};
|
|
resolveTimeout = () => {
|
|
const timeoutMin = 1;
|
|
const timeoutMax = 60 * 15; // 15 minutes in seconds
|
|
const timeoutDefault = 3;
|
|
if (this.props.timeoutSeconds === undefined) {
|
|
return timeoutDefault;
|
|
}
|
|
if (!isWholeNumberBetweenInclusive(this.props.timeoutSeconds, timeoutMin, timeoutMax)) {
|
|
throw new AmplifyUserError('InvalidTimeoutError', {
|
|
message: `Invalid function timeout of ${this.props.timeoutSeconds}`,
|
|
resolution: `timeoutSeconds must be a whole number between ${timeoutMin} and ${timeoutMax} inclusive`,
|
|
});
|
|
}
|
|
return this.props.timeoutSeconds;
|
|
};
|
|
resolveMemory = () => {
|
|
const memoryMin = 128;
|
|
const memoryMax = 10240;
|
|
const memoryDefault = 512;
|
|
if (this.props.memoryMB === undefined) {
|
|
return memoryDefault;
|
|
}
|
|
if (!isWholeNumberBetweenInclusive(this.props.memoryMB, memoryMin, memoryMax)) {
|
|
throw new AmplifyUserError('InvalidMemoryMBError', {
|
|
message: `Invalid function memoryMB of ${this.props.memoryMB}`,
|
|
resolution: `memoryMB must be a whole number between ${memoryMin} and ${memoryMax} inclusive`,
|
|
});
|
|
}
|
|
return this.props.memoryMB;
|
|
};
|
|
resolveEphemeralStorageSize = () => {
|
|
const ephemeralStorageSizeMin = 512;
|
|
const ephemeralStorageSizeMax = 10240;
|
|
const ephemeralStorageSizeDefault = 512;
|
|
if (this.props.ephemeralStorageSizeMB === undefined) {
|
|
return ephemeralStorageSizeDefault;
|
|
}
|
|
if (!isWholeNumberBetweenInclusive(this.props.ephemeralStorageSizeMB, ephemeralStorageSizeMin, ephemeralStorageSizeMax)) {
|
|
throw new AmplifyUserError('InvalidEphemeralStorageSizeMBError', {
|
|
message: `Invalid function ephemeralStorageSizeMB of ${this.props.ephemeralStorageSizeMB}`,
|
|
resolution: `ephemeralStorageSizeMB must be a whole number between ${ephemeralStorageSizeMin} and ${ephemeralStorageSizeMax} inclusive`,
|
|
});
|
|
}
|
|
return this.props.ephemeralStorageSizeMB;
|
|
};
|
|
resolveEnvironment = () => {
|
|
if (this.props.environment === undefined) {
|
|
return {};
|
|
}
|
|
const invalidKeys = [];
|
|
Object.keys(this.props.environment).forEach((key) => {
|
|
// validate using key pattern from https://docs.aws.amazon.com/lambda/latest/api/API_Environment.html
|
|
if (!key.match(/^[a-zA-Z]([a-zA-Z0-9_])+$/)) {
|
|
invalidKeys.push(key);
|
|
}
|
|
});
|
|
if (invalidKeys.length > 0) {
|
|
throw new AmplifyUserError('InvalidEnvironmentKeyError', {
|
|
message: `Invalid function environment key(s): ${invalidKeys.join(', ')}`,
|
|
resolution: 'Environment keys must match [a-zA-Z]([a-zA-Z0-9_])+ and be at least 2 characters',
|
|
});
|
|
}
|
|
return this.props.environment;
|
|
};
|
|
resolveRuntime = () => {
|
|
const runtimeDefault = 22;
|
|
// if runtime is not set, default to the oldest LTS
|
|
if (!this.props.runtime) {
|
|
return runtimeDefault;
|
|
}
|
|
if (!(this.props.runtime in nodeVersionMap)) {
|
|
throw new AmplifyUserError('InvalidRuntimeError', {
|
|
message: `Invalid function runtime of ${this.props.runtime}`,
|
|
resolution: `runtime must be one of the following: ${Object.keys(nodeVersionMap).join(', ')}`,
|
|
});
|
|
}
|
|
return this.props.runtime;
|
|
};
|
|
resolveArchitecture = () => {
|
|
const architectureDefault = 'x86_64';
|
|
if (!this.props.architecture) {
|
|
return architectureDefault;
|
|
}
|
|
if (!(this.props.architecture in architectureMap)) {
|
|
throw new AmplifyUserError('InvalidArchitectureError', {
|
|
message: `Invalid function architecture of ${this.props.architecture}`,
|
|
resolution: `architecture must be one of the following: ${Object.keys(architectureMap).join(', ')}`,
|
|
});
|
|
}
|
|
return this.props.architecture;
|
|
};
|
|
resolveSchedule = () => {
|
|
if (!this.props.schedule) {
|
|
return [];
|
|
}
|
|
return this.props.schedule;
|
|
};
|
|
resolveBundling = () => {
|
|
const bundlingDefault = {
|
|
format: OutputFormat.ESM,
|
|
bundleAwsSDK: true,
|
|
loader: {
|
|
'.node': 'file',
|
|
},
|
|
minify: true,
|
|
sourceMap: true,
|
|
};
|
|
return {
|
|
...bundlingDefault,
|
|
minify: this.resolveMinify(this.props.bundling),
|
|
};
|
|
};
|
|
resolveMinify = (bundling) => {
|
|
return bundling?.minify === undefined ? true : bundling.minify;
|
|
};
|
|
resolveDurableConfig = () => {
|
|
if (!this.props.durableConfig) {
|
|
return undefined;
|
|
}
|
|
const { executionTimeoutSeconds, retentionPeriodDays } = this.props.durableConfig;
|
|
const executionTimeoutMin = 1;
|
|
const executionTimeoutMax = 31_622_400; // 366 days in seconds
|
|
if (!isWholeNumberBetweenInclusive(executionTimeoutSeconds, executionTimeoutMin, executionTimeoutMax)) {
|
|
throw new AmplifyUserError('InvalidDurableFunctionExecutionTimeoutError', {
|
|
message: `Invalid durable function execution timeout of ${this.props.durableConfig.executionTimeoutSeconds}`,
|
|
resolution: `durableConfig.executionTimeoutSeconds must be a whole number between ${executionTimeoutMin} and ${executionTimeoutMax} inclusive`,
|
|
});
|
|
}
|
|
if (retentionPeriodDays !== undefined) {
|
|
const retentionPeriodMin = 1;
|
|
const retentionPeriodMax = 90;
|
|
if (!isWholeNumberBetweenInclusive(retentionPeriodDays, retentionPeriodMin, retentionPeriodMax)) {
|
|
throw new AmplifyUserError('InvalidDurableFunctionRetentionPeriodError', {
|
|
message: `Invalid durable function retention period of ${this.props.durableConfig.retentionPeriodDays}`,
|
|
resolution: `durableConfig.retentionPeriodDays must be a whole number between ${retentionPeriodMin} and ${retentionPeriodMax} inclusive`,
|
|
});
|
|
}
|
|
}
|
|
const runtime = this.resolveRuntime();
|
|
if (runtime < 22) {
|
|
throw new AmplifyUserError('UnsupportedDurableFunctionRuntimeError', {
|
|
message: `Durable functions require runtime 22 or higher. Current runtime is ${runtime}.`,
|
|
resolution: `Set the function runtime to 22 or higher to use durable functions.`,
|
|
});
|
|
}
|
|
return {
|
|
executionTimeoutSeconds: this.props.durableConfig.executionTimeoutSeconds,
|
|
retentionPeriodDays: this.props.durableConfig.retentionPeriodDays ?? 14,
|
|
};
|
|
};
|
|
}
|
|
class FunctionGenerator {
|
|
props;
|
|
outputStorageStrategy;
|
|
resourceGroupName;
|
|
constructor(props, outputStorageStrategy) {
|
|
this.props = props;
|
|
this.outputStorageStrategy = outputStorageStrategy;
|
|
this.resourceGroupName = props.resourceGroupName;
|
|
}
|
|
generateContainerEntry = ({ scope, backendSecretResolver, }) => {
|
|
// Move layer resolution here where we have access to scope
|
|
const parser = new FunctionLayerArnParser(Stack.of(scope).region, Stack.of(scope).account);
|
|
const resolvedLayerArns = parser.parseLayers(this.props.layers ?? {}, this.props.name);
|
|
// resolve layers to LayerVersion objects for the NodejsFunction constructor
|
|
const resolvedLayers = Object.entries(resolvedLayerArns).map(([key, arn]) => LayerVersion.fromLayerVersionArn(scope, `${this.props.name}-${key}-layer`, arn));
|
|
return new AmplifyFunction(scope, this.props.name, { ...this.props, resolvedLayers }, backendSecretResolver, this.outputStorageStrategy);
|
|
};
|
|
}
|
|
class AmplifyFunction extends AmplifyFunctionBase {
|
|
resources;
|
|
functionEnvironmentTranslator;
|
|
constructor(scope, id, props, backendSecretResolver, outputStorageStrategy) {
|
|
super(scope, id, outputStorageStrategy);
|
|
const require = createRequire(import.meta.url);
|
|
const shims = [require.resolve('./lambda-shims/cjs_shim')];
|
|
const ssmResolverFile = require.resolve('./lambda-shims/resolve_ssm_params');
|
|
const invokeSsmResolverFile = require.resolve('./lambda-shims/invoke_ssm_shim');
|
|
/**
|
|
* This code concatenates the contents of the ssm resolver and invoker into a single line that can be used as the esbuild banner content
|
|
* This banner is responsible for resolving the customer's SSM parameters at runtime
|
|
*/
|
|
const bannerCode = readFileSync(ssmResolverFile, 'utf-8')
|
|
.concat(readFileSync(invokeSsmResolverFile, 'utf-8'))
|
|
.split(new RegExp(`${EOL}|\n|\r`, 'g'))
|
|
.map((line) => line.replace(/\/\/.*$/, '')) // strip out inline comments because the banner is going to be flattened into a single line
|
|
.join('');
|
|
const functionEnvironmentTypeGenerator = new FunctionEnvironmentTypeGenerator(id);
|
|
// esbuild runs as part of the NodejsFunction constructor, so we eagerly generate the process env shim without types so it can be included in the function bundle.
|
|
// This will be overwritten with the typed file at the end of synthesis
|
|
functionEnvironmentTypeGenerator.generateProcessEnvShim();
|
|
let functionLambda;
|
|
const cdkLoggingOptions = convertLoggingOptionsToCDK(props.logging);
|
|
// Create a log group if retention is specified (replacing deprecated logRetention property)
|
|
let logGroup = cdkLoggingOptions.logGroup;
|
|
if (props.logging.retention !== undefined && !logGroup) {
|
|
logGroup = createLogGroup(scope, id, props.logging);
|
|
}
|
|
try {
|
|
functionLambda = new NodejsFunction(scope, `${id}-lambda`, {
|
|
entry: props.entry,
|
|
timeout: Duration.seconds(props.timeoutSeconds),
|
|
memorySize: props.memoryMB,
|
|
architecture: architectureMap[props.architecture],
|
|
ephemeralStorageSize: Size.mebibytes(props.ephemeralStorageSizeMB),
|
|
runtime: nodeVersionMap[props.runtime],
|
|
layers: props.resolvedLayers,
|
|
bundling: {
|
|
...props.bundling,
|
|
banner: bannerCode,
|
|
inject: shims,
|
|
externalModules: Object.keys(props.layers),
|
|
logLevel: EsBuildLogLevel.ERROR,
|
|
},
|
|
logGroup: logGroup,
|
|
applicationLogLevelV2: cdkLoggingOptions.level,
|
|
loggingFormat: cdkLoggingOptions.format,
|
|
durableConfig: props.durableConfig
|
|
? {
|
|
executionTimeout: Duration.seconds(props.durableConfig.executionTimeoutSeconds),
|
|
retentionPeriod: Duration.days(props.durableConfig.retentionPeriodDays),
|
|
}
|
|
: undefined,
|
|
});
|
|
}
|
|
catch (error) {
|
|
// If the error is from ES Bundler which is executed as a child process by CDK,
|
|
// then the error from CDK contains the command that was executed along with the exit status.
|
|
// Wrapping it here would cause the cdk_deployer to re-throw this wrapped exception
|
|
// instead of scraping the stderr for actual ESBuild error.
|
|
if (error instanceof Error &&
|
|
error.message.match(/Failed to bundle asset.*exited with status/)) {
|
|
throw error;
|
|
}
|
|
throw new AmplifyUserError('NodeJSFunctionConstructInitializationError', {
|
|
message: 'Failed to instantiate nodejs function construct',
|
|
resolution: 'See the underlying error message for more details. Use `--debug` for additional debugging information.',
|
|
}, error);
|
|
}
|
|
let version;
|
|
if (props.durableConfig) {
|
|
try {
|
|
version = functionLambda.currentVersion;
|
|
}
|
|
catch (error) {
|
|
throw new AmplifyUserError('DurableFunctionVersionInitializationError', {
|
|
message: 'Failed to create version for durable function. Durable functions require a versioned Lambda function.',
|
|
resolution: 'See the underlying error message for more details.',
|
|
}, error);
|
|
}
|
|
}
|
|
try {
|
|
const scheduleProps = convertFunctionSchedulesToScheduleProps(functionLambda, props.schedule);
|
|
const lambdaTarget = new targets.LambdaInvoke(version ?? functionLambda);
|
|
scheduleProps.forEach(({ schedule, description }, index) => {
|
|
// Lambda name will be prepended to schedule id, so only using index here for uniqueness
|
|
new scheduler.Schedule(functionLambda, `schedule-${index}`, {
|
|
schedule,
|
|
description,
|
|
target: lambdaTarget,
|
|
});
|
|
});
|
|
}
|
|
catch (error) {
|
|
throw new AmplifyUserError('FunctionScheduleInitializationError', {
|
|
message: 'Failed to instantiate schedule for nodejs function',
|
|
resolution: 'See the underlying error message for more details.',
|
|
}, error);
|
|
}
|
|
Tags.of(functionLambda).add(TagName.FRIENDLY_NAME, id);
|
|
this.functionEnvironmentTranslator = new FunctionEnvironmentTranslator(functionLambda, props.environment, backendSecretResolver, functionEnvironmentTypeGenerator);
|
|
this.resources = {
|
|
lambda: functionLambda,
|
|
cfnResources: {
|
|
cfnFunction: functionLambda.node.findChild('Resource'),
|
|
},
|
|
};
|
|
this.storeOutput();
|
|
}
|
|
addEnvironment = (key, value) => {
|
|
this.functionEnvironmentTranslator.addEnvironmentEntry(key, value);
|
|
};
|
|
getResourceAccessAcceptor = () => new FunctionResourceAccessAcceptor(this, this.functionEnvironmentTranslator);
|
|
}
|
|
const isWholeNumberBetweenInclusive = (test, min, max) => min <= test && test <= max && test % 1 === 0;
|
|
const nodeVersionMap = {
|
|
18: Runtime.NODEJS_18_X,
|
|
20: Runtime.NODEJS_20_X,
|
|
22: Runtime.NODEJS_22_X,
|
|
24: Runtime.NODEJS_24_X,
|
|
};
|
|
const architectureMap = {
|
|
arm64: Architecture.ARM_64,
|
|
x86_64: Architecture.X86_64,
|
|
};
|
|
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmFjdG9yeS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9mYWN0b3J5LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUNBLE9BQU8sRUFDTCxnQkFBZ0IsRUFDaEIsd0JBQXdCLEVBQ3hCLE9BQU8sR0FDUixNQUFNLDRCQUE0QixDQUFDO0FBbUJwQyxPQUFPLEVBQUUsUUFBUSxFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsSUFBSSxFQUFFLE1BQU0sYUFBYSxDQUFDO0FBQzFELE9BQU8sS0FBSyxTQUFTLE1BQU0sMkJBQTJCLENBQUM7QUFDdkQsT0FBTyxLQUFLLE9BQU8sTUFBTSxtQ0FBbUMsQ0FBQztBQUM3RCxPQUFPLEVBQ0wsWUFBWSxFQUtaLFlBQVksRUFDWixPQUFPLEdBQ1IsTUFBTSx3QkFBd0IsQ0FBQztBQUNoQyxPQUFPLEVBQ0wsUUFBUSxJQUFJLGVBQWUsRUFDM0IsY0FBYyxFQUNkLFlBQVksR0FDYixNQUFNLCtCQUErQixDQUFDO0FBRXZDLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxJQUFJLENBQUM7QUFDbEMsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLFFBQVEsQ0FBQztBQUN2QyxPQUFPLEVBQUUsR0FBRyxFQUFFLE1BQU0sSUFBSSxDQUFDO0FBQ3pCLE9BQU8sS0FBSyxJQUFJLE1BQU0sTUFBTSxDQUFDO0FBQzdCLE9BQU8sRUFBRSw2QkFBNkIsRUFBRSxNQUFNLDhCQUE4QixDQUFDO0FBQzdFLE9BQU8sRUFBRSxnQ0FBZ0MsRUFBRSxNQUFNLGtDQUFrQyxDQUFDO0FBQ3BGLE9BQU8sRUFBRSxzQkFBc0IsRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBQzNELE9BQU8sRUFDTCwwQkFBMEIsRUFDMUIsY0FBYyxHQUNmLE1BQU0sNkJBQTZCLENBQUM7QUFDckMsT0FBTyxFQUFFLHVDQUF1QyxFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFDL0UsT0FBTyxFQUNMLHVCQUF1QixHQUV4QixNQUFNLGdDQUFnQyxDQUFDO0FB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QUFNO0NBQzVCLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBGdW5jdGlvbk91dHB1dCB9IGZyb20gJ0Bhd3MtYW1wbGlmeS9iYWNrZW5kLW91dHB1dC1zY2hlbWFzJztcbmltcG9ydCB7XG4gIEFtcGxpZnlVc2VyRXJyb3IsXG4gIENhbGxlckRpcmVjdG9yeUV4dHJhY3RvcixcbiAgVGFnTmFtZSxcbn0gZnJvbSAnQGF3cy1hbXBsaWZ5L3BsYXRmb3JtLWNvcmUnO1xuaW1wb3J0IHtcbiAgQW1wbGlmeVJlc291cmNlR3JvdXBOYW1lLFxuICBCYWNrZW5kT3V0cHV0U3RvcmFnZVN0cmF0ZWd5LFxuICBCYWNrZW5kU2VjcmV0LFxuICBCYWNrZW5kU2VjcmV0UmVzb2x2ZXIsXG4gIENvbnN0cnVjdENvbnRhaW5lckVudHJ5R2VuZXJhdG9yLFxuICBDb25zdHJ1Y3RGYWN0b3J5LFxuICBDb25zdHJ1Y3RGYWN0b3J5R2V0SW5zdGFuY2VQcm9wcyxcbiAgRnVuY3Rpb25SZXNvdXJjZXMsXG4gIEdlbmVyYXRlQ29udGFpbmVyRW50cnlQcm9wcyxcbiAgTG9nTGV2ZWwsXG4gIExvZ1JldGVudGlvbixcbiAgUmVzb3VyY2VBY2Nlc3NBY2NlcHRvcixcbiAgUmVzb3VyY2VBY2Nlc3NBY2NlcHRvckZhY3RvcnksXG4gIFJlc291cmNlTmFtZVZhbGlkYXRvcixcbiAgUmVzb3VyY2VQcm92aWRlcixcbiAgU3RhY2tQcm92aWRlcixcbn0gZnJvbSAnQGF3cy1hbXBsaWZ5L3BsdWdpbi10eXBlcyc7XG5pbXBvcnQgeyBEdXJhdGlvbiwgU2l6ZSwgU3RhY2ssIFRhZ3MgfSBmcm9tICdhd3MtY2RrLWxpYic7XG5pbXBvcnQgKiBhcyBzY2hlZHVsZXIgZnJvbSAnYXdzLWNkay1saWIvYXdzLXNjaGVkdWxlcic7XG5pbXBvcnQgKiBhcyB0YXJnZXRzIGZyb20gJ2F3cy1jZGstbGliL2F3cy1zY2hlZHVsZXItdGFyZ2V0cyc7XG5pbXBvcnQge1xuICBBcmNoaXRlY3R1cmUsXG4gIENmbkZ1bmN0aW9uLFxuICBJRnVuY3Rpb24sXG4gIElMYXllclZlcnNpb24sXG4gIElWZXJzaW9uLFxuICBMYXllclZlcnNpb24sXG4gIFJ1bnRpbWUsXG59IGZyb20gJ2F3cy1jZGstbGliL2F3cy1sYW1iZGEnO1xuaW1wb3J0IHtcbiAgTG9nTGV2ZWwgYXMgRXNCdWlsZExvZ0xldmVsLFxuICBOb2RlanNGdW5jdGlvbixcbiAgT3V0cHV0Rm9ybWF0LFxufSBmcm9tICdhd3MtY2RrLWxpYi9hd3MtbGFtYmRhLW5vZGVqcyc7XG5pbXBvcnQgeyBDb25zdHJ1Y3QgfSBmcm9tICdjb25zdHJ1Y3RzJztcbmltcG9ydCB7IHJlYWRGaWxlU3luYyB9IGZyb20gJ2ZzJztcbmltcG9ydCB7IGNyZWF0ZVJlcXVpcmUgfSBmcm9tICdtb2R1bGUnO1xuaW1wb3J0IHsgRU9MIH0gZnJvbSAnb3MnO1xuaW1wb3J0ICogYXMgcGF0aCBmcm9tICdwYXRoJztcbmltcG9ydCB7IEZ1bmN0aW9uRW52aXJvbm1lbnRUcmFuc2xhdG9yIH0gZnJvbSAnLi9mdW5jdGlvbl9lbnZfdHJhbnNsYXRvci5qcyc7XG5pbXBvcnQgeyBGdW5jdGlvbkVudmlyb25tZW50VHlwZUdlbmVyYXRvciB9IGZyb20gJy4vZnVuY3Rpb25fZW52X3R5cGVfZ2VuZXJhdG9yLmpzJztcbmltcG9ydCB7IEZ1bmN0aW9uTGF5ZXJBcm5QYXJzZXIgfSBmcm9tICcuL2xheWVyX3BhcnNlci5qcyc7XG5pbXBvcnQge1xuICBjb252ZXJ0TG9nZ2luZ09wdGlvbnNUb0NESyxcbiAgY3JlYXRlTG9nR3JvdXAsXG59IGZyb20gJy4vbG9nZ2luZ19vcHRpb25zX3BhcnNlci5qcyc7XG5pbXBvcnQgeyBjb252ZXJ0RnVuY3Rpb25TY2hlZHVsZXNUb1NjaGVkdWxlUHJvcHMgfSBmcm9tICcuL3NjaGVkdWxlX3BhcnNlci5qcyc7XG5pbXBvcnQge1xuICBQcm92aWRlZEZ1bmN0aW9uRmFjdG9yeSxcbiAgUHJvdmlkZWRGdW5jdGlvblByb3BzLFxufSBmcm9tICcuL3Byb3ZpZGVkX2Z1bmN0aW9uX2ZhY3RvcnkuanMnO1xuaW1wb3J0IHsgQW1wbGlmeUZ1bmN0aW9uQmFzZSB9IGZyb20gJy4vZnVuY3Rpb25fY29uc3RydWN0X2Jhc2UuanMnO1xuaW1wb3J0IHsgRnVuY3Rpb25SZXNvdXJjZUFjY2Vzc0FjY2VwdG9yIH0gZnJvbSAnLi9yZXNvdXJjZV9hY2Nlc3NfYWNjZXB0b3IuanMnO1xuXG5leHBvcnQgdHlwZSBBZGRFbnZpcm9ubWVudEZhY3RvcnkgPSB7XG4gIGFkZEVudmlyb25tZW50OiAoa2V5OiBzdHJpbmcsIHZhbHVlOiBzdHJpbmcgfCBCYWNrZW5kU2VjcmV0KSA9PiB2b2lkO1xufTtcblxuZXhwb3J0IHR5cGUgQ3JvblNjaGVkdWxlRXhwcmVzc2lvbiA9XG4gIHwgYCR7c3RyaW5nfSAke3N0cmluZ30gJHtzdHJpbmd9ICR7c3RyaW5nfSAke3N0cmluZ31gXG4gIHwgYCR7c3RyaW5nfSAke3N0cmluZ30gJHtzdHJpbmd9ICR7c3RyaW5nfSAke3N0cmluZ30gJHtzdHJpbmd9YDtcblxuZXhwb3J0IHR5cGUgWm9uZWRDcm9uU2NoZWR1bGUgPSB7XG4gIGNyb246IENyb25TY2hlZHVsZUV4cHJlc3Npb247XG4gIHRpbWV6b25lOiBzdHJpbmc7XG4gIGRlc2NyaXB0aW9uPzogc3RyaW5nO1xufTtcblxuZXhwb3J0IHR5cGUgQ3JvblNjaGVkdWxlID0gQ3JvblNjaGVkdWxlRXhwcmVzc2lvbiB8IFpvbmVkQ3JvblNjaGVkdWxlO1xuXG5leHBvcnQgdHlwZSBUaW1lSW50ZXJ2YWxFeHByZXNzaW9uID1cbiAgfCBgZXZlcnkgJHtudW1iZXJ9bWBcbiAgfCBgZXZlcnkgJHtudW1iZXJ9aGBcbiAgfCBgZXZlcnkgZGF5YFxuICB8IGBldmVyeSB3ZWVrYFxuICB8IGBldmVyeSBtb250aGBcbiAgfCBgZXZlcnkgeWVhcmA7XG5cbmV4cG9ydCB0eXBlIFpvbmVkVGltZUludGVydmFsID0ge1xuICByYXRlOiBUaW1lSW50ZXJ2YWxFeHByZXNzaW9uO1xuICB0aW1lem9uZTogc3RyaW5nO1xuICBkZXNjcmlwdGlvbj86IHN0cmluZztcbn07XG5cbmV4cG9ydCB0eXBlIFRpbWVJbnRlcnZhbCA9IFpvbmVkVGltZUludGVydmFsIHwgVGltZUludGVydmFsRXhwcmVzc2lvbjtcblxuZXhwb3J0IHR5cGUgRnVuY3Rpb25TY2hlZHVsZSA9IFRpbWVJbnRlcnZhbCB8IENyb25TY2hlZHVsZTtcblxuZXhwb3J0IHR5cGUgRnVuY3Rpb25Mb2dMZXZlbCA9IEV4dHJhY3Q8XG4gIExvZ0xldmVsLFxuICAnaW5mbycgfCAnZGVidWcnIHwgJ3dhcm4nIHwgJ2Vycm9yJyB8ICdmYXRhbCcgfCAndHJhY2UnXG4+O1xuZXhwb3J0IHR5cGUgRnVuY3Rpb25Mb2dSZXRlbnRpb24gPSBMb2dSZXRlbnRpb247XG5cbmV4cG9ydCBmdW5jdGlvbiBkZWZpbmVGdW5jdGlvbihcbiAgcHJvcHM/OiBGdW5jdGlvblByb3BzLFxuKTogQ29uc3RydWN0RmFjdG9yeTxcbiAgUmVzb3VyY2VQcm92aWRlcjxGdW5jdGlvblJlc291cmNlcz4gJlxuICAgIFJlc291cmNlQWNjZXNzQWNjZXB0b3JGYWN0b3J5ICZcbiAgICBBZGRFbnZpcm9ubWVudEZhY3RvcnkgJlxuICAgIFN0YWNrUHJvdmlkZXJcbj47XG5leHBvcnQgZnVuY3Rpb24gZGVmaW5lRnVuY3Rpb24oXG4gIHByb3ZpZGVyOiAoc2NvcGU6IENvbnN0cnVjdCkgPT4gSUZ1bmN0aW9uLFxuICBwcm92aWRlclByb3BzPzogUHJvdmlkZWRGdW5jdGlvblByb3BzLFxuKTogQ29uc3RydWN0RmFjdG9yeTxcbiAgUmVzb3VyY2VQcm92aWRlcjxGdW5jdGlvblJlc291cmNlcz4gJlxuICAgIFJlc291cmNlQWNjZXNzQWNjZXB0b3JGYWN0b3J5ICZcbiAgICBBZGRFbnZpcm9ubWVudEZhY3RvcnkgJlxuICAgIFN0YWNrUHJvdmlkZXJcbj47XG4vKipcbiAqIEVudHJ5IHBvaW50IGZvciBkZWZpbmluZyBhIGZ1bmN0aW9uIGluIHRoZSBBbXBsaWZ5IGVjb3N5c3RlbVxuICovXG4vLyBUaGlzIGlzIHRoZSBcImltcGxlbWVudGF0aW9uIG92ZXJsb2FkXCIsIGl0J3Mgbm90IHZpc2libGUgaW4gcHVibGljIGFwaS5cbi8vIFdlIGhhdmUgdG8gdXNlIGZ1bmN0aW9uIG5vdGF0aW9uIGluc3RlYWQgb2YgYXJyb3cgbm90YXRpb24uXG4vLyBBcnJvdyBub3RhdGlvbiBkb2VzIG5vdCBzdXBwb3J0IG92ZXJsb2Fkcy5cbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1yZXN0cmljdGVkLXN5bnRheFxuZXhwb3J0IGZ1bmN0aW9uIGRlZmluZUZ1bmN0aW9uKFxuICBwcm9wc09yUHJvdmlkZXI6IEZ1bmN0aW9uUHJvcHMgfCAoKHNjb3BlOiBDb25zdHJ1Y3QpID0+IElGdW5jdGlvbikgPSB7fSxcbiAgcHJvdmlkZXJQcm9wcz86IFByb3ZpZGVkRnVuY3Rpb25Qcm9wcyxcbik6IHVua25vd24ge1xuICBpZiAocHJvcHNPclByb3ZpZGVyICYmIHR5cGVvZiBwcm9wc09yUHJvdmlkZXIgPT09ICdmdW5jdGlvbicpIHtcbiAgICByZXR1cm4gbmV3IFByb3ZpZGVkRnVuY3Rpb25GYWN0b3J5KHByb3BzT3JQcm92aWRlciwgcHJvdmlkZXJQcm9wcyk7XG4gIH1cbiAgcmV0dXJuIG5ldyBGdW5jdGlvbkZhY3RvcnkocHJvcHNPclByb3ZpZGVyLCBuZXcgRXJyb3IoKS5zdGFjayk7XG59XG5cbmV4cG9ydCB0eXBlIEZ1bmN0aW9uUHJvcHMgPSB7XG4gIC8qKlxuICAgKiBBIG5hbWUgZm9yIHRoZSBmdW5jdGlvbi5cbiAgICogRGVmYXVsdHMgdG8gdGhlIGJhc2VuYW1lIG9mIHRoZSBlbnRyeSBwYXRoIGlmIHNwZWNpZmllZC5cbiAgICogSWYgbm8gZW50cnkgaXMgc3BlY2lmaWVkLCBkZWZhdWx0cyB0byB0aGUgZGlyZWN0b3J5IG5hbWUgaW4gd2hpY2ggdGhpcyBmdW5jdGlvbiBpcyBkZWZpbmVkLlxuICAgKlxuICAgKiBFeGFtcGxlOlxuICAgKiBJZiBlbnRyeSBpcyBgLi9zY2hlZHVsZWQtZGItYmFja3VwLnRzYCB0aGUgbmFtZSB3aWxsIGRlZmF1bHQgdG8gXCJzY2hlZHVsZWQtZGItYmFja3VwXCJcbiAgICogSWYgZW50cnkgaXMgbm90IHNldCBhbmQgdGhlIGZ1bmN0aW9uIGlzIGRlZmluZWQgaW4gYGFtcGxpZnkvZnVuY3Rpb25zL2RiLWJhY2t1cC9yZXNvdXJjZS50c2AgdGhlIG5hbWUgd2lsbCBkZWZhdWx0IHRvIFwiZGItYmFja3VwXCJcbiAgICovXG4gIG5hbWU/OiBzdHJpbmc7XG4gIC8qKlxuICAgKiBUaGUgcGF0aCB0byB0aGUgZmlsZSB0aGF0IGNvbnRhaW5zIHRoZSBmdW5jdGlvbiBlbnRyeSBwb2ludC5cbiAgICogSWYgdGhpcyBpcyBhIHJlbGF0aXZlIHBhdGgsIGl0IGlzIGNvbXB1dGVkIHJlbGF0aXZlIHRvIHRoZSBmaWxlIHdoZXJlIHRoaXMgZnVuY3Rpb24gaXMgZGVmaW5lZFxuICAgKlxuICAgKiBEZWZhdWx0cyB0byAnLi9oYW5kbGVyLnRzJ1xuICAgKi9cbiAgZW50cnk/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIEFuIGFtb3VudCBvZiB0aW1lIGluIHNlY29uZHMgYmV0d2VlbiAxIHNlY29uZCBhbmQgMTUgbWludXRlcy5cbiAgICogTXVzdCBiZSBhIHdob2xlIG51bWJlci5cbiAgICogRGVmYXVsdCBpcyAzIHNlY29uZHMuXG4gICAqL1xuICB0aW1lb3V0U2Vjb25kcz86IG51bWJlcjtcblxuICAvKipcbiAgICogQW4gYW1vdW50IG9mIG1lbW9yeSAoUkFNKSB0byBhbGxvY2F0ZSB0byB0aGUgZnVuY3Rpb24gYmV0d2VlbiAxMjggYW5kIDEwMjQwIE1CLlxuICAgKiBNdXN0IGJlIGEgd2hvbGUgbnVtYmVyLlxuICAgKiBEZWZhdWx0IGlzIDUxMk1CLlxuICAgKi9cbiAgbWVtb3J5TUI/OiBudW1iZXI7XG5cbiAgLyoqXG4gICAqIFRoZSBzaXplIG9mIHRoZSBmdW5jdGlvbidzIC90bXAgZGlyZWN0b3J5IGluIE1CLlxuICAgKiBNdXN0IGJlIGEgd2hvbGUgbnVtYmVyLlxuICAgKiBAZGVmYXVsdCA1MTJcbiAgICovXG4gIGVwaGVtZXJhbFN0b3JhZ2VTaXplTUI/OiBudW1iZXI7XG5cbiAgLyoqXG4gICAqIEVudmlyb25tZW50IHZhcmlhYmxlcyB0aGF0IHdpbGwgYmUgYXZhaWxhYmxlIGR1cmluZyBmdW5jdGlvbiBleGVjdXRpb25cbiAgICovXG4gIGVudmlyb25tZW50PzogUmVjb3JkPHN0cmluZywgc3RyaW5nIHwgQmFja2VuZFNlY3JldD47XG5cbiAgLyoqXG4gICAqIE5vZGUgcnVudGltZSB2ZXJzaW9uIGZvciB0aGUgbGFtYmRhIGVudmlyb25tZW50LlxuICAgKlxuICAgKiBEZWZhdWx0cyB0byB0aGUgb2xkZXN0IE5vZGVKUyBMVFMgdmVyc2lvbi4gU2VlIGh0dHBzOi8vbm9kZWpzLm9yZy9lbi9hYm91dC9wcmV2aW91cy1yZWxlYXNlc1xuICAgKi9cbiAgcnVudGltZT86IE5vZGVWZXJzaW9uO1xuXG4gIC8qKlxuICAgKiBUaGUgYXJjaGl0ZWN0dXJlIG9mIHRoZSB0YXJnZXQgcGxhdGZvcm0gZm9yIHRoZSBsYW1iZGEgZW52aXJvbm1lbnQuXG4gICAqIERlZmF1bHRzIHRvIFg4Nl82NC5cbiAgICovXG4gIGFyY2hpdGVjdHVyZT86IEZ1bmN0aW9uQXJjaGl0ZWN0dXJlO1xuXG4gIC8qKlxuICAgKiBBIHRpbWUgaW50ZXJ2YWwgc3RyaW5nIHRvIHBlcmlvZGljYWxseSBydW4gdGhlIGZ1bmN0aW9uLlxuICAgKiBUaGlzIGNhbiBiZSBlaXRoZXIgYSBzdHJpbmcgb2YgYFwiZXZlcnkgPHBvc2l0aXZlIHdob2xlIG51bWJlcj48bSAobWludXRlKSBvciBoIChob3VyKT5cImAsIGBcImV2ZXJ5IGRheXx3ZWVrfG1vbnRofHllYXJcImAgb3IgY3JvbiBleHByZXNzaW9uLlxuICAgKiBEZWZhdWx0cyB0byBubyBzY2hlZHVsaW5nIGZvciB0aGUgZnVuY3Rpb24uXG4gICAqIEBleGFtcGxlXG4gICAqIHNjaGVkdWxlOiBcImV2ZXJ5IDVtXCJcbiAgICogQGV4YW1wbGVcbiAgICogc2NoZWR1bGU6IFwiZXZlcnkgd2Vla1wiXG4gICAqIEBleGFtcGxlXG4gICAqIHNjaGVkdWxlOiBcIjAgOSA/ICogMiAqXCIgLy8gZXZlcnkgTW9uZGF5IGF0IDlhbVxuICAgKi9cbiAgc2NoZWR1bGU/OiBGdW5jdGlvblNjaGVkdWxlIHwgRnVuY3Rpb25TY2hlZHVsZVtdO1xuXG4gIC8qKlxuICAgKiBBdHRhY2ggTGFtYmRhIGxheWVycyB0byBhIGZ1bmN0aW9uXG4gICAqIC0gQSBMYW1iZGEgbGF5ZXIgaXMgcmVwcmVzZW50ZWQgYnkgYW4gb2JqZWN0IG9mIGtleS92YWx1ZSBwYWlyIHdoZXJlIHRoZSBrZXkgaXMgdGhlIG1vZHVsZSBuYW1lIHRoYXQgaXMgZXhwb3J0ZWQgZnJvbSB5b3VyIGxheWVyIGFuZCB0aGUgdmFsdWUgaXMgdGhlIEFSTiBvZiB0aGUgbGF5ZXIuIFRoZSBrZXkgKG1vZHVsZSBuYW1lKSBpcyB1c2VkIHRvIGV4dGVybmFsaXplIHRoZSBtb2R1bGUgZGVwZW5kZW5jeSBzbyBpdCBkb2Vzbid0IGdldCBidW5kbGVkIHdpdGggeW91ciBsYW1iZGEgZnVuY3Rpb25cbiAgICogLSBNYXhpbXVtIG9mIDUgbGF5ZXJzIGNhbiBiZSBhdHRhY2hlZCB0byBhIGZ1bmN0aW9uIGFuZCBtdXN0IGJlIGluIHRoZSBzYW1lIHJlZ2lvbiBhcyB0aGUgZnVuY3Rpb24uXG4gICAqIEBleGFtcGxlXG4gICAqIGxheWVyczoge1xuICAgKiAgICBcIkBhd3MtbGFtYmRhLXBvd2VydG9vbHMvbG9nZ2VyXCI6IFwiYXJuOmF3czpsYW1iZGE6PGN1cnJlbnQtcmVnaW9uPjowOTQyNzQxMDU5MTU6bGF5ZXI6QVdTTGFtYmRhUG93ZXJ0b29sc1R5cGVTY3JpcHRWMjoxMVwiXG4gICAqIH0sXG4gICAqIG9yXG4gICAqIEBleGFtcGxlXG4gICAqIGxheWVyczoge1xuICAgKiAgICBcIlNoYXJwXCI6IFwiU2hhcnBMYXllcjoxXCJcbiAgICogfSxcbiAgICogQHNlZSBbQW1wbGlmeSBkb2N1bWVudGF0aW9uIGZvciBMYW1iZGEgbGF5ZXJzXShodHRwczovL2RvY3MuYW1wbGlmeS5hd3MvcmVhY3QvYnVpbGQtYS1iYWNrZW5kL2Z1bmN0aW9ucy9hZGQtbGFtYmRhLWxheWVycylcbiAgICogQHNlZSBbQVdTIGRvY3VtZW50YXRpb24gZm9yIExhbWJkYSBsYXllcnNdKGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9sYW1iZGEvbGF0ZXN0L2RnL2NoYXB0ZXItbGF5ZXJzLmh0bWwpXG4gICAqL1xuICBsYXllcnM/OiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+O1xuXG4gIC8qXG4gICAqIE9wdGlvbnMgZm9yIGJ1bmRsaW5nIHRoZSBmdW5jdGlvbiBjb2RlLlxuICAgKi9cbiAgYnVuZGxpbmc/OiBGdW5jdGlvbkJ1bmRsaW5nT3B0aW9ucztcblxuICAvKipcbiAgICogR3JvdXAgdGhlIGZ1bmN0aW9uIHdpdGggZXhpc3RpbmcgQW1wbGlmeSByZXNvdXJjZXMgb3Igc2VwYXJhdGUgdGhlIGZ1bmN0aW9uIGludG8gaXRzIG93biBncm91cC5cbiAgICogQGRlZmF1bHQgJ2Z1bmN0aW9uJyAvLyBncm91cGluZyB3aXRoIG90aGVyIEFtcGxpZnkgZnVuY3Rpb25zXG4gICAqIEBleGFtcGxlXG4gICAqIHJlc291cmNlR3JvdXBOYW1lOiAnYXV0aCcgLy8gdG8gZ3JvdXAgYW4gYXV0aCB0cmlnZ2VyIHdpdGggYW4gYXV0aCByZXNvdXJjZVxuICAgKi9cbiAgcmVzb3VyY2VHcm91cE5hbWU/OiBBbXBsaWZ5UmVzb3VyY2VHcm91cE5hbWU7XG5cbiAgbG9nZ2luZz86IEZ1bmN0aW9uTG9nZ2luZ09wdGlvbnM7XG5cbiAgLyoqXG4gICAqIENvbmZpZ3VyYXRpb24gZm9yIGR1cmFibGUgZnVuY3Rpb25zLlxuICAgKlxuICAgKiBMYW1iZGEgZHVyYWJsZSBmdW5jdGlvbnMgYWxsb3cgZm9yIGxvbmctcnVubmluZyBleGVjdXRpb25zIHdpdGggcGVyc2lzdGVudCBzdGF0ZS5cbiAgICovXG4gIGR1cmFibGVDb25maWc/OiBGdW5jdGlvbkR1cmFibGVDb25maWdPcHRpb25zO1xufTtcblxuZXhwb3J0IHR5cGUgRnVuY3Rpb25CdW5kbGluZ09wdGlvbnMgPSB7XG4gIC8qKlxuICAgKiBXaGV0aGVyIHRvIG1pbmlmeSB0aGUgZnVuY3Rpb24gY29kZS5cbiAgICpcbiAgICogRGVmYXVsdHMgdG8gdHJ1ZS5cbiAgICovXG4gIG1pbmlmeT86IGJvb2xlYW47XG59O1xuXG5leHBvcnQgdHlwZSBGdW5jdGlvbkxvZ2dpbmdPcHRpb25zID0gKFxuICB8IHtcbiAgICAgIGZvcm1hdDogJ2pzb24nO1xuICAgICAgbGV2ZWw/OiBGdW5jdGlvbkxvZ0xldmVsO1xuICAgIH1cbiAgfCB7XG4gICAgICBmb3JtYXQ/OiAndGV4dCc7XG4gICAgfVxuKSAmIHtcbiAgcmV0ZW50aW9uPzogRnVuY3Rpb25Mb2dSZXRlbnRpb247XG59O1xuXG5leHBvcnQgdHlwZSBGdW5jdGlvbkR1cmFibGVDb25maWdPcHRpb25zID0ge1xuICAvKipcbiAgICogVGhlIGFtb3VudCBvZiB0aW1lIGluIHNlY29uZHMgdGhhdCBMYW1iZGEgYWxsb3dzIGEgZHVyYWJsZSBmdW5jdGlvbiB0byBydW4gYmVmb3JlIHN0b3BwaW5nIGl0LlxuICAgKlxuICAgKiBNdXN0IGJlIGJldHdlZW4gMSBhbmQgMzEsNjIyLDQwMCBzZWNvbmRzICgzNjYgZGF5cykuXG4gICAqL1xuICBleGVjdXRpb25UaW1lb3V0U2Vjb25kczogbnVtYmVyO1xuICAvKipcbiAgICogVGhlIG51bWJlciBvZiBkYXlzIGFmdGVyIGEgZHVyYWJsZSBleGVjdXRpb24gaXMgY2xvc2VkIHRoYXQgTGFtYmRhIHJldGFpbnMgaXRzIGhpc3RvcnkuXG4gICAqXG4gICAqIE11c3QgYmUgYmV0d2VlbiAxIGFuZCA5MCBkYXlzLlxuICAgKiBAZGVmYXVsdCAxNFxuICAgKi9cbiAgcmV0ZW50aW9uUGVyaW9kRGF5cz86IG51bWJlcjtcbn07XG5cbi8qKlxuICogQ3JlYXRlIExhbWJkYSBmdW5jdGlvbnMgaW4gdGhlIGNvbnRleHQgb2YgYW4gQW1wbGlmeSBiYWNrZW5kIGRlZmluaXRpb25cbiAqL1xuY2xhc3MgRnVuY3Rpb25GYWN0b3J5IGltcGxlbWVudHMgQ29uc3RydWN0RmFjdG9yeTxBbXBsaWZ5RnVuY3Rpb24+IHtcbiAgcHJpdmF0ZSBnZW5lcmF0b3I6IENvbnN0cnVjdENvbnRhaW5lckVudHJ5R2VuZXJhdG9yO1xuICAvKipcbiAgICogQ3JlYXRlIGEgbmV3IEFtcGxpZnlGdW5jdGlvbkZhY3RvcnlcbiAgICovXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgcmVhZG9ubHkgcHJvcHM6IEZ1bmN0aW9uUHJvcHMsXG4gICAgcHJpdmF0ZSByZWFkb25seSBjYWxsZXJTdGFjaz86IHN0cmluZyxcbiAgKSB7fVxuXG4gIC8qKlxuICAgKiBDcmVhdGVzIGFuIGluc3RhbmNlIG9mIEFtcGxpZnlGdW5jdGlvbiB3aXRoaW4gdGhlIHByb3ZpZGVkIEFtcGxpZnkgY29udGV4dFxuICAgKi9cbiAgZ2V0SW5zdGFuY2UgPSAoe1xuICAgIGNvbnN0cnVjdENvbnRhaW5lcixcbiAgICBvdXRwdXRTdG9yYWdlU3RyYXRlZ3ksXG4gICAgcmVzb3VyY2VOYW1lVmFsaWRhdG9yLFxuICB9OiBDb25zdHJ1Y3RGYWN0b3J5R2V0SW5zdGFuY2VQcm9wcyk6IEFtcGxpZnlGdW5jdGlvbiA9PiB7XG4gICAgaWYgKCF0aGlzLmdlbmVyYXRvcikge1xuICAgICAgdGhpcy5nZW5lcmF0b3IgPSBuZXcgRnVuY3Rpb25HZW5lcmF0b3IoXG4gICAgICAgIHRoaXMuaHlkcmF0ZURlZmF1bHRzKHJlc291cmNlTmFtZVZhbGlkYXRvciksXG4gICAgICAgIG91dHB1dFN0b3JhZ2VTdHJhdGVneSxcbiAgICAgICk7XG4gICAgfVxuICAgIHJldHVybiBjb25zdHJ1Y3RDb250YWluZXIuZ2V0T3JDb21wdXRlKHRoaXMuZ2VuZXJhdG9yKSBhcyBBbXBsaWZ5RnVuY3Rpb247XG4gIH07XG5cbiAgcHJpdmF0ZSBoeWRyYXRlRGVmYXVsdHMgPSAoXG4gICAgcmVzb3VyY2VOYW1lVmFsaWRhdG9yPzogUmVzb3VyY2VOYW1lVmFsaWRhdG9yLFxuICApOiBIeWRyYXRlZEZ1bmN0aW9uUHJvcHMgPT4ge1xuICAgIGNvbnN0IG5hbWUgPSB0aGlzLnJlc29sdmVOYW1lKCk7XG4gICAgcmVzb3VyY2VOYW1lVmFsaWRhdG9yPy52YWxpZGF0ZShuYW1lKTtcblxuICAgIHJldHVybiB7XG4gICAgICBuYW1lLFxuICAgICAgZW50cnk6IHRoaXMucmVzb2x2ZUVudHJ5KCksXG4gICAgICB0aW1lb3V0U2Vjb25kczogdGhpcy5yZXNvbHZlVGltZW91dCgpLFxuICAgICAgbWVtb3J5TUI6IHRoaXMucmVzb2x2ZU1lbW9yeSgpLFxuICAgICAgZXBoZW1lcmFsU3RvcmFnZVNpemVNQjogdGhpcy5yZXNvbHZlRXBoZW1lcmFsU3RvcmFnZVNpemUoKSxcbiAgICAgIGVudmlyb25tZW50OiB0aGlzLnJlc29sdmVFbnZpcm9ubWVudCgpLFxuICAgICAgcnVudGltZTogdGhpcy5yZXNvbHZlUnVudGltZSgpLFxuICAgICAgYXJjaGl0ZWN0dXJlOiB0aGlzLnJlc29sdmVBcmNoaXRlY3R1cmUoKSxcbiAgICAgIHNjaGVkdWxlOiB0aGlzLnJlc29sdmVTY2hlZHVsZSgpLFxuICAgICAgYnVuZGxpbmc6IHRoaXMucmVzb2x2ZUJ1bmRsaW5nKCksXG4gICAgICBsYXllcnM6IHRoaXMucHJvcHMubGF5ZXJzID8/IHt9LFxuICAgICAgcmVzb3VyY2VHcm91cE5hbWU6IHRoaXMucHJvcHMucmVzb3VyY2VHcm91cE5hbWUgPz8gJ2Z1bmN0aW9uJyxcbiAgICAgIGxvZ2dpbmc6IHRoaXMucHJvcHMubG9nZ2luZyA/PyB7fSxcbiAgICAgIGR1cmFibGVDb25maWc6IHRoaXMucmVzb2x2ZUR1cmFibGVDb25maWcoKSxcbiAgICB9O1xuICB9O1xuXG4gIHByaXZhdGUgcmVzb2x2ZU5hbWUgPSAoKSA9PiB7XG4gICAgLy8gSWYgbmFtZSBpcyBzZXQgZXhwbGljaXRseSwgdXNlIHRoYXRcbiAgICBpZiAodGhpcy5wcm9wcy5uYW1lKSB7XG4gICAgICByZXR1cm4gdGhpcy5wcm9wcy5uYW1lO1xuICAgIH1cbiAgICAvLyBJZiBlbnRyeSBpcyBzZXQsIHVzZSB0aGUgYmFzZW5hbWUgb2YgdGhlIGVudHJ5IHBhdGhcbiAgICBpZiAodGhpcy5wcm9wcy5lbnRyeSkge1xuICAgICAgcmV0dXJuIHBhdGgucGFyc2UodGhpcy5wcm9wcy5lbnRyeSkubmFtZTtcbiAgICB9XG5cbiAgICAvLyBPdGhlcndpc2UsIHVzZSB0aGUgZGlyZWN0b3J5IG5hbWUgd2hlcmUgdGhlIGZ1bmN0aW9uIGlzIGRlZmluZWRcbiAgICByZXR1cm4gcGF0aC5iYXNlbmFtZShcbiAgICAgIG5ldyBDYWxsZXJEaXJlY3RvcnlFeHRyYWN0b3IodGhpcy5jYWxsZXJTdGFjaykuZXh0cmFjdCgpLFxuICAgICk7XG4gIH07XG5cbiAgcHJpdmF0ZSByZXNvbHZlRW50cnkgPSAoKSA9PiB7XG4gICAgLy8gaWYgZW50cnkgaXMgbm90IHNldCwgZGVmYXVsdCB0byBoYW5kbGVyLnRzXG4gICAgaWYgKCF0aGlzLnByb3BzLmVudHJ5KSB7XG4gICAgICByZXR1cm4gcGF0aC5qb2luKFxuICAgICAgICBuZXcgQ2FsbGVyRGlyZWN0b3J5RXh0cmFjdG9yKHRoaXMuY2FsbGVyU3RhY2spLmV4dHJhY3QoKSxcbiAgICAgICAgJ2hhbmRsZXIudHMnLFxuICAgICAgKTtcbiAgICB9XG5cbiAgICAvLyBpZiBlbnRyeSBpcyBhYnNvbHV0ZSB1c2UgdGhhdFxuICAgIGlmIChwYXRoLmlzQWJzb2x1dGUodGhpcy5wcm9wcy5lbnRyeSkpIHtcbiAgICAgIHJldHVybiB0aGlzLnByb3BzLmVudHJ5O1xuICAgIH1cblxuICAgIC8vIGlmIGVudHJ5IGlzIHJlbGF0aXZlLCBjb21wdXRlIHdpdGggcmVzcGVjdCB0byB0aGUgY2FsbGVyIGRpcmVjdG9yeVxuICAgIHJldHVybiBwYXRoLmpvaW4oXG4gICAgICBuZXcgQ2FsbGVyRGlyZWN0b3J5RXh0cmFjdG9yKHRoaXMuY2FsbGVyU3RhY2spLmV4dHJhY3QoKSxcbiAgICAgIHRoaXMucHJvcHMuZW50cnksXG4gICAgKTtcbiAgfTtcblxuICBwcml2YXRlIHJlc29sdmVUaW1lb3V0ID0gKCkgPT4ge1xuICAgIGNvbnN0IHRpbWVvdXRNaW4gPSAxO1xuICAgIGNvbnN0IHRpbWVvdXRNYXggPSA2MCAqIDE1OyAvLyAxNSBtaW51dGVzIGluIHNlY29uZHNcbiAgICBjb25zdCB0aW1lb3V0RGVmYXVsdCA9IDM7XG4gICAgaWYgKHRoaXMucHJvcHMudGltZW91dFNlY29uZHMgPT09IHVuZGVmaW5lZCkge1xuICAgICAgcmV0dXJuIHRpbWVvdXREZWZhdWx0O1xuICAgIH1cblxuICAgIGlmIChcbiAgICAgICFpc1dob2xlTnVtYmVyQmV0d2VlbkluY2x1c2l2ZShcbiAgICAgICAgdGhpcy5wcm9wcy50aW1lb3V0U2Vjb25kcyxcbiAgICAgICAgdGltZW91dE1pbixcbiAgICAgICAgdGltZW91dE1heCxcbiAgICAgIClcbiAgICApIHtcbiAgICAgIHRocm93IG5ldyBBbXBsaWZ5VXNlckVycm9yKCdJbnZhbGlkVGltZW91dEVycm9yJywge1xuICAgICAgICBtZXNzYWdlOiBgSW52YWxpZCBmdW5jdGlvbiB0aW1lb3V0IG9mICR7dGhpcy5wcm9wcy50aW1lb3V0U2Vjb25kc31gLFxuICAgICAgICByZXNvbHV0aW9uOiBgdGltZW91dFNlY29uZHMgbXVzdCBiZSBhIHdob2xlIG51bWJlciBiZXR3ZWVuICR7dGltZW91dE1pbn0gYW5kICR7dGltZW91dE1heH0gaW5jbHVzaXZlYCxcbiAgICAgIH0pO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5wcm9wcy50aW1lb3V0U2Vjb25kcztcbiAgfTtcblxuICBwcml2YXRlIHJlc29sdmVNZW1vcnkgPSAoKSA9PiB7XG4gICAgY29uc3QgbWVtb3J5TWluID0gMTI4O1xuICAgIGNvbnN0IG1lbW9yeU1heCA9IDEwMjQwO1xuICAgIGNvbnN0IG1lbW9yeURlZmF1bHQgPSA1MTI7XG4gICAgaWYgKHRoaXMucHJvcHMubWVtb3J5TUIgPT09IHVuZGVmaW5lZCkge1xuICAgICAgcmV0dXJuIG1lbW9yeURlZmF1bHQ7XG4gICAgfVxuICAgIGlmIChcbiAgICAgICFpc1dob2xlTnVtYmVyQmV0d2VlbkluY2x1c2l2ZSh0aGlzLnByb3BzLm1lbW9yeU1CLCBtZW1vcnlNaW4sIG1lbW9yeU1heClcbiAgICApIHtcbiAgICAgIHRocm93IG5ldyBBbXBsaWZ5VXNlckVycm9yKCdJbnZhbGlkTWVtb3J5TUJFcnJvcicsIHtcbiAgICAgICAgbWVzc2FnZTogYEludmFsaWQgZnVuY3Rpb24gbWVtb3J5TUIgb2YgJHt0aGlzLnByb3BzLm1lbW9yeU1CfWAsXG4gICAgICAgIHJlc29sdXRpb246IGBtZW1vcnlNQiBtdXN0IGJlIGEgd2hvbGUgbnVtYmVyIGJldHdlZW4gJHttZW1vcnlNaW59IGFuZCAke21lbW9yeU1heH0gaW5jbHVzaXZlYCxcbiAgICAgIH0pO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5wcm9wcy5tZW1vcnlNQjtcbiAgfTtcblxuICBwcml2YXRlIHJlc29sdmVFcGhlbWVyYWxTdG9yYWdlU2l6ZSA9ICgpID0+IHtcbiAgICBjb25zdCBlcGhlbWVyYWxTdG9yYWdlU2l6ZU1pbiA9IDUxMjtcbiAgICBjb25zdCBlcGhlbWVyYWxTdG9yYWdlU2l6ZU1heCA9IDEwMjQwO1xuICAgIGNvbnN0IGVwaGVtZXJhbFN0b3JhZ2VTaXplRGVmYXVsdCA9IDUxMjtcbiAgICBpZiAodGhpcy5wcm9wcy5lcGhlbWVyYWxTdG9yYWdlU2l6ZU1CID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHJldHVybiBlcGhlbWVyYWxTdG9yYWdlU2l6ZURlZmF1bHQ7XG4gICAgfVxuICAgIGlmIChcbiAgICAgICFpc1dob2xlTnVtYmVyQmV0d2VlbkluY2x1c2l2ZShcbiAgICAgICAgdGhpcy5wcm9wcy5lcGhlbWVyYWxTdG9yYWdlU2l6ZU1CLFxuICAgICAgICBlcGhlbWVyYWxTdG9yYWdlU2l6ZU1pbixcbiAgICAgICAgZXBoZW1lcmFsU3RvcmFnZVNpemVNYXgsXG4gICAgICApXG4gICAgKSB7XG4gICAgICB0aHJvdyBuZXcgQW1wbGlmeVVzZXJFcnJvcignSW52YWxpZEVwaGVtZXJhbFN0b3JhZ2VTaXplTUJFcnJvcicsIHtcbiAgICAgICAgbWVzc2FnZTogYEludmFsaWQgZnVuY3Rpb24gZXBoZW1lcmFsU3RvcmFnZVNpemVNQiBvZiAke3RoaXMucHJvcHMuZXBoZW1lcmFsU3RvcmFnZVNpemVNQn1gLFxuICAgICAgICByZXNvbHV0aW9uOiBgZXBoZW1lcmFsU3RvcmFnZVNpemVNQiBtdXN0IGJlIGEgd2hvbGUgbnVtYmVyIGJldHdlZW4gJHtlcGhlbWVyYWxTdG9yYWdlU2l6ZU1pbn0gYW5kICR7ZXBoZW1lcmFsU3RvcmFnZVNpemVNYXh9IGluY2x1c2l2ZWAsXG4gICAgICB9KTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMucHJvcHMuZXBoZW1lcmFsU3RvcmFnZVNpemVNQjtcbiAgfTtcblxuICBwcml2YXRlIHJlc29sdmVFbnZpcm9ubWVudCA9ICgpID0+IHtcbiAgICBpZiAodGhpcy5wcm9wcy5lbnZpcm9ubWVudCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICByZXR1cm4ge307XG4gICAgfVxuXG4gICAgY29uc3QgaW52YWxpZEtleXM6IHN0cmluZ1tdID0gW107XG5cbiAgICBPYmplY3Qua2V5cyh0aGlzLnByb3BzLmVudmlyb25tZW50KS5mb3JFYWNoKChrZXkpID0+IHtcbiAgICAgIC8vIHZhbGlkYXRlIHVzaW5nIGtleSBwYXR0ZXJuIGZyb20gaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL2xhbWJkYS9sYXRlc3QvYXBpL0FQSV9FbnZpcm9ubWVudC5odG1sXG4gICAgICBpZiAoIWtleS5tYXRjaCgvXlthLXpBLVpdKFthLXpBLVowLTlfXSkrJC8pKSB7XG4gICAgICAgIGludmFsaWRLZXlzLnB1c2goa2V5KTtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIGlmIChpbnZhbGlkS2V5cy5sZW5ndGggPiAwKSB7XG4gICAgICB0aHJvdyBuZXcgQW1wbGlmeVVzZXJFcnJvcignSW52YWxpZEVudmlyb25tZW50S2V5RXJyb3InLCB7XG4gICAgICAgIG1lc3NhZ2U6IGBJbnZhbGlkIGZ1bmN0aW9uIGVudmlyb25tZW50IGtleShzKTogJHtpbnZhbGlkS2V5cy5qb2luKFxuICAgICAgICAgICcsICcsXG4gICAgICAgICl9YCxcbiAgICAgICAgcmVzb2x1dGlvbjpcbiAgICAgICAgICAnRW52aXJvbm1lbnQga2V5cyBtdXN0IG1hdGNoIFthLXpBLVpdKFthLXpBLVowLTlfXSkrIGFuZCBiZSBhdCBsZWFzdCAyIGNoYXJhY3RlcnMnLFxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMucHJvcHMuZW52aXJvbm1lbnQ7XG4gIH07XG5cbiAgcHJpdmF0ZSByZXNvbHZlUnVudGltZSA9ICgpID0+IHtcbiAgICBjb25zdCBydW50aW1lRGVmYXVsdCA9IDIyO1xuXG4gICAgLy8gaWYgcnVudGltZSBpcyBub3Qgc2V0LCBkZWZhdWx0IHRvIHRoZSBvbGRlc3QgTFRTXG4gICAgaWYgKCF0aGlzLnByb3BzLnJ1bnRpbWUpIHtcbiAgICAgIHJldHVybiBydW50aW1lRGVmYXVsdDtcbiAgICB9XG5cbiAgICBpZiAoISh0aGlzLnByb3BzLnJ1bnRpbWUgaW4gbm9kZVZlcnNpb25NYXApKSB7XG4gICAgICB0aHJvdyBuZXcgQW1wbGlmeVVzZXJFcnJvcignSW52YWxpZFJ1bnRpbWVFcnJvcicsIHtcbiAgICAgICAgbWVzc2FnZTogYEludmFsaWQgZnVuY3Rpb24gcnVudGltZSBvZiAke3RoaXMucHJvcHMucnVudGltZX1gLFxuICAgICAgICByZXNvbHV0aW9uOiBgcnVudGltZSBtdXN0IGJlIG9uZSBvZiB0aGUgZm9sbG93aW5nOiAke09iamVjdC5rZXlzKFxuICAgICAgICAgIG5vZGVWZXJzaW9uTWFwLFxuICAgICAgICApLmpvaW4oJywgJyl9YCxcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzLnByb3BzLnJ1bnRpbWU7XG4gIH07XG5cbiAgcHJpdmF0ZSByZXNvbHZlQXJjaGl0ZWN0dXJlID0gKCkgPT4ge1xuICAgIGNvbnN0IGFyY2hpdGVjdHVyZURlZmF1bHQgPSAneDg2XzY0JztcblxuICAgIGlmICghdGhpcy5wcm9wcy5hcmNoaXRlY3R1cmUpIHtcbiAgICAgIHJldHVybiBhcmNoaXRlY3R1cmVEZWZhdWx0O1xuICAgIH1cblxuICAgIGlmICghKHRoaXMucHJvcHMuYXJjaGl0ZWN0dXJlIGluIGFyY2hpdGVjdHVyZU1hcCkpIHtcbiAgICAgIHRocm93IG5ldyBBbXBsaWZ5VXNlckVycm9yKCdJbnZhbGlkQXJjaGl0ZWN0dXJlRXJyb3InLCB7XG4gICAgICAgIG1lc3NhZ2U6IGBJbnZhbGlkIGZ1bmN0aW9uIGFyY2hpdGVjdHVyZSBvZiAke3RoaXMucHJvcHMuYXJjaGl0ZWN0dXJlfWAsXG4gICAgICAgIHJlc29sdXRpb246IGBhcmNoaXRlY3R1cmUgbXVzdCBiZSBvbmUgb2YgdGhlIGZvbGxvd2luZzogJHtPYmplY3Qua2V5cyhcbiAgICAgICAgICBhcmNoaXRlY3R1cmVNYXAsXG4gICAgICAgICkuam9pbignLCAnKX1gLFxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMucHJvcHMuYXJjaGl0ZWN0dXJlO1xuICB9O1xuXG4gIHByaXZhdGUgcmVzb2x2ZVNjaGVkdWxlID0gKCkgPT4ge1xuICAgIGlmICghdGhpcy5wcm9wcy5zY2hlZHVsZSkge1xuICAgICAgcmV0dXJuIFtdO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzLnByb3BzLnNjaGVkdWxlO1xuICB9O1xuXG4gIHByaXZhdGUgcmVzb2x2ZUJ1bmRsaW5nID0gKCkgPT4ge1xuICAgIGNvbnN0IGJ1bmRsaW5nRGVmYXVsdCA9IHtcbiAgICAgIGZvcm1hdDogT3V0cHV0Rm9ybWF0LkVTTSxcbiAgICAgIGJ1bmRsZUF3c1NESzogdHJ1ZSxcbiAgICAgIGxvYWRlcjoge1xuICAgICAgICAnLm5vZGUnOiAnZmlsZScsXG4gICAgICB9LFxuICAgICAgbWluaWZ5OiB0cnVlLFxuICAgICAgc291cmNlTWFwOiB0cnVlLFxuICAgIH07XG5cbiAgICByZXR1cm4ge1xuICAgICAgLi4uYnVuZGxpbmdEZWZhdWx0LFxuICAgICAgbWluaWZ5OiB0aGlzLnJlc29sdmVNaW5pZnkodGhpcy5wcm9wcy5idW5kbGluZyksXG4gICAgfTtcbiAgfTtcblxuICBwcml2YXRlIHJlc29sdmVNaW5pZnkgPSAoYnVuZGxpbmc/OiBGdW5jdGlvbkJ1bmRsaW5nT3B0aW9ucykgPT4ge1xuICAgIHJldHVybiBidW5kbGluZz8ubWluaWZ5ID09PSB1bmRlZmluZWQgPyB0cnVlIDogYnVuZGxpbmcubWluaWZ5O1xuICB9O1xuXG4gIHByaXZhdGUgcmVzb2x2ZUR1cmFibGVDb25maWcgPSAoKSA9PiB7XG4gICAgaWYgKCF0aGlzLnByb3BzLmR1cmFibGVDb25maWcpIHtcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuICAgIGNvbnN0IHsgZXhlY3V0aW9uVGltZW91dFNlY29uZHMsIHJldGVudGlvblBlcmlvZERheXMgfSA9XG4gICAgICB0aGlzLnByb3BzLmR1cmFibGVDb25maWc7XG4gICAgY29uc3QgZXhlY3V0aW9uVGltZW91dE1pbiA9IDE7XG4gICAgY29uc3QgZXhlY3V0aW9uVGltZW91dE1heCA9IDMxXzYyMl80MDA7IC8vIDM2NiBkYXlzIGluIHNlY29uZHNcbiAgICBpZiAoXG4gICAgICAhaXNXaG9sZU51bWJlckJldHdlZW5JbmNsdXNpdmUoXG4gICAgICAgIGV4ZWN1dGlvblRpbWVvdXRTZWNvbmRzLFxuICAgICAgICBleGVjdXRpb25UaW1lb3V0TWluLFxuICAgICAgICBleGVjdXRpb25UaW1lb3V0TWF4LFxuICAgICAgKVxuICAgICkge1xuICAgICAgdGhyb3cgbmV3IEFtcGxpZnlVc2VyRXJyb3IoXG4gICAgICAgICdJbnZhbGlkRHVyYWJsZUZ1bmN0aW9uRXhlY3V0aW9uVGltZW91dEVycm9yJyxcbiAgICAgICAge1xuICAgICAgICAgIG1lc3NhZ2U6IGBJbnZhbGlkIGR1cmFibGUgZnVuY3Rpb24gZXhlY3V0aW9uIHRpbWVvdXQgb2YgJHt0aGlzLnByb3BzLmR1cmFibGVDb25maWcuZXhlY3V0aW9uVGltZW91dFNlY29uZHN9YCxcbiAgICAgICAgICByZXNvbHV0aW9uOiBgZHVyYWJsZUNvbmZpZy5leGVjdXRpb25UaW1lb3V0U2Vjb25kcyBtdXN0IGJlIGEgd2hvbGUgbnVtYmVyIGJldHdlZW4gJHtleGVjdXRpb25UaW1lb3V0TWlufSBhbmQgJHtleGVjdXRpb25UaW1lb3V0TWF4fSBpbmNsdXNpdmVgLFxuICAgICAgICB9LFxuICAgICAgKTtcbiAgICB9XG4gICAgaWYgKHJldGVudGlvblBlcmlvZERheXMgIT09IHVuZGVmaW5lZCkge1xuICAgICAgY29uc3QgcmV0ZW50aW9uUGVyaW9kTWluID0gMTtcbiAgICAgIGNvbnN0IHJldGVudGlvblBlcmlvZE1heCA9IDkwO1xuICAgICAgaWYgKFxuICAgICAgICAhaXNXaG9sZU51bWJlckJldHdlZW5JbmNsdXNpdmUoXG4gICAgICAgICAgcmV0ZW50aW9uUGVyaW9kRGF5cyxcbiAgICAgICAgICByZXRlbnRpb25QZXJpb2RNaW4sXG4gICAgICAgICAgcmV0ZW50aW9uUGVyaW9kTWF4LFxuICAgICAgICApXG4gICAgICApIHtcbiAgICAgICAgdGhyb3cgbmV3IEFtcGxpZnlVc2VyRXJyb3IoXG4gICAgICAgICAgJ0ludmFsaWREdXJhYmxlRnVuY3Rpb25SZXRlbnRpb25QZXJpb2RFcnJvcicsXG4gICAgICAgICAge1xuICAgICAgICAgICAgbWVzc2FnZTogYEludmFsaWQgZHVyYWJsZSBmdW5jdGlvbiByZXRlbnRpb24gcGVyaW9kIG9mICR7dGhpcy5wcm9wcy5kdXJhYmxlQ29uZmlnLnJldGVudGlvblBlcmlvZERheXN9YCxcbiAgICAgICAgICAgIHJlc29sdXRpb246IGBkdXJhYmxlQ29uZmlnLnJldGVudGlvblBlcmlvZERheXMgbXVzdCBiZSBhIHdob2xlIG51bWJlciBiZXR3ZWVuICR7cmV0ZW50aW9uUGVyaW9kTWlufSBhbmQgJHtyZXRlbnRpb25QZXJpb2RNYXh9IGluY2x1c2l2ZWAsXG4gICAgICAgICAgfSxcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBjb25zdCBydW50aW1lID0gdGhpcy5yZXNvbHZlUnVudGltZSgpO1xuICAgIGlmIChydW50aW1lIDwgMjIpIHtcbiAgICAgIHRocm93IG5ldyBBbXBsaWZ5VXNlckVycm9yKCdVbnN1cHBvcnRlZER1cmFibGVGdW5jdGlvblJ1bnRpbWVFcnJvcicsIHtcbiAgICAgICAgbWVzc2FnZTogYER1cmFibGUgZnVuY3Rpb25zIHJlcXVpcmUgcnVudGltZSAyMiBvciBoaWdoZXIuIEN1cnJlbnQgcnVudGltZSBpcyAke3J1bnRpbWV9LmAsXG4gICAgICAgIHJlc29sdXRpb246IGBTZXQgdGhlIGZ1bmN0aW9uIHJ1bnRpbWUgdG8gMjIgb3IgaGlnaGVyIHRvIHVzZSBkdXJhYmxlIGZ1bmN0aW9ucy5gLFxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIGV4ZWN1dGlvblRpbWVvdXRTZWNvbmRzOiB0aGlzLnByb3BzLmR1cmFibGVDb25maWcuZXhlY3V0aW9uVGltZW91dFNlY29uZHMsXG4gICAgICByZXRlbnRpb25QZXJpb2REYXlzOiB0aGlzLnByb3BzLmR1cmFibGVDb25maWcucmV0ZW50aW9uUGVyaW9kRGF5cyA/PyAxNCxcbiAgICB9O1xuICB9O1xufVxuXG50eXBlIEh5ZHJhdGVkRnVuY3Rpb25Qcm9wcyA9IHtcbiAgZHVyYWJsZUNvbmZpZz86IFJlcXVpcmVkPEZ1bmN0aW9uUHJvcHNbJ2R1cmFibGVDb25maWcnXT47XG59ICYgUmVxdWlyZWQ8T21pdDxGdW5jdGlvblByb3BzLCAnZHVyYWJsZUNvbmZpZyc+PjtcblxuY2xhc3MgRnVuY3Rpb25HZW5lcmF0b3IgaW1wbGVtZW50cyBDb25zdHJ1Y3RDb250YWluZXJFbnRyeUdlbmVyYXRvciB7XG4gIHJlYWRvbmx5IHJlc291cmNlR3JvdXBOYW1lOiBBbXBsaWZ5UmVzb3VyY2VHcm91cE5hbWU7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSByZWFkb25seSBwcm9wczogSHlkcmF0ZWRGdW5jdGlvblByb3BzLFxuICAgIHByaXZhdGUgcmVhZG9ubHkgb3V0cHV0U3RvcmFnZVN0cmF0ZWd5OiBCYWNrZW5kT3V0cHV0U3RvcmFnZVN0cmF0ZWd5PEZ1bmN0aW9uT3V0cHV0PixcbiAgKSB7XG4gICAgdGhpcy5yZXNvdXJjZUdyb3VwTmFtZSA9IHByb3BzLnJlc291cmNlR3JvdXBOYW1lO1xuICB9XG5cbiAgZ2VuZXJhdGVDb250YWluZXJFbnRyeSA9ICh7XG4gICAgc2NvcGUsXG4gICAgYmFja2VuZFNlY3JldFJlc29sdmVyLFxuICB9OiBHZW5lcmF0ZUNvbnRhaW5lckVudHJ5UHJvcHMpID0+IHtcbiAgICAvLyBNb3ZlIGxheWVyIHJlc29sdXRpb24gaGVyZSB3aGVyZSB3ZSBoYXZlIGFjY2VzcyB0byBzY29wZVxuICAgIGNvbnN0IHBhcnNlciA9IG5ldyBGdW5jdGlvbkxheWVyQXJuUGFyc2VyKFxuICAgICAgU3RhY2sub2Yoc2NvcGUpLnJlZ2lvbixcbiAgICAgIFN0YWNrLm9mKHNjb3BlKS5hY2NvdW50LFxuICAgICk7XG4gICAgY29uc3QgcmVzb2x2ZWRMYXllckFybnMgPSBwYXJzZXIucGFyc2VMYXllcnMoXG4gICAgICB0aGlzLnByb3BzLmxheWVycyA/PyB7fSxcbiAgICAgIHRoaXMucHJvcHMubmFtZSxcbiAgICApO1xuXG4gICAgLy8gcmVzb2x2ZSBsYXllcnMgdG8gTGF5ZXJWZXJzaW9uIG9iamVjdHMgZm9yIHRoZSBOb2RlanNGdW5jdGlvbiBjb25zdHJ1Y3RvclxuICAgIGNvbnN0IHJlc29sdmVkTGF5ZXJzID0gT2JqZWN0LmVudHJpZXMocmVzb2x2ZWRMYXllckFybnMpLm1hcCgoW2tleSwgYXJuXSkgPT5cbiAgICAgIExheWVyVmVyc2lvbi5mcm9tTGF5ZXJWZXJzaW9uQXJuKFxuICAgICAgICBzY29wZSxcbiAgICAgICAgYCR7dGhpcy5wcm9wcy5uYW1lfS0ke2tleX0tbGF5ZXJgLFxuICAgICAgICBhcm4sXG4gICAgICApLFxuICAgICk7XG5cbiAgICByZXR1cm4gbmV3IEFtcGxpZnlGdW5jdGlvbihcbiAgICAgIHNjb3BlLFxuICAgICAgdGhpcy5wcm9wcy5uYW1lLFxuICAgICAgeyAuLi50aGlzLnByb3BzLCByZXNvbHZlZExheWVycyB9LFxuICAgICAgYmFja2VuZFNlY3JldFJlc29sdmVyLFxuICAgICAgdGhpcy5vdXRwdXRTdG9yYWdlU3RyYXRlZ3ksXG4gICAgKTtcbiAgfTtcbn1cblxuY2xhc3MgQW1wbGlmeUZ1bmN0aW9uXG4gIGV4dGVuZHMgQW1wbGlmeUZ1bmN0aW9uQmFzZVxuICBpbXBsZW1lbnRzIEFkZEVudmlyb25tZW50RmFjdG9yeVxue1xuICByZWFkb25seSByZXNvdXJjZXM6IEZ1bmN0aW9uUmVzb3VyY2VzO1xuICBwcml2YXRlIHJlYWRvbmx5IGZ1bmN0aW9uRW52aXJvbm1lbnRUcmFuc2xhdG9yOiBGdW5jdGlvbkVudmlyb25tZW50VHJhbnNsYXRvcjtcbiAgY29uc3RydWN0b3IoXG4gICAgc2NvcGU6IENvbnN0cnVjdCxcbiAgICBpZDogc3RyaW5nLFxuICAgIHByb3BzOiBIeWRyYXRlZEZ1bmN0aW9uUHJvcHMgJiB7IHJlc29sdmVkTGF5ZXJzOiBJTGF5ZXJWZXJzaW9uW10gfSxcbiAgICBiYWNrZW5kU2VjcmV0UmVzb2x2ZXI6IEJhY2tlbmRTZWNyZXRSZXNvbHZlcixcbiAgICBvdXRwdXRTdG9yYWdlU3RyYXRlZ3k6IEJhY2tlbmRPdXRwdXRTdG9yYWdlU3RyYXRlZ3k8RnVuY3Rpb25PdXRwdXQ+LFxuICApIHtcbiAgICBzdXBlcihzY29wZSwgaWQsIG91dHB1dFN0b3JhZ2VTdHJhdGVneSk7XG5cbiAgICBjb25zdCByZXF1aXJlID0gY3JlYXRlUmVxdWlyZShpbXBvcnQubWV0YS51cmwpO1xuXG4gICAgY29uc3Qgc2hpbXMgPSBbcmVxdWlyZS5yZXNvbHZlKCcuL2xhbWJkYS1zaGltcy9janNfc2hpbScpXTtcblxuICAgIGNvbnN0IHNzbVJlc29sdmVyRmlsZSA9XG4gICAgICByZXF1aXJlLnJlc29sdmUoJy4vbGFtYmRhLXNoaW1zL3Jlc29sdmVfc3NtX3BhcmFtcycpO1xuXG4gICAgY29uc3QgaW52b2tlU3NtUmVzb2x2ZXJGaWxlID1cbiAgICAgIHJlcXVpcmUucmVzb2x2ZSgnLi9sYW1iZGEtc2hpbXMvaW52b2tlX3NzbV9zaGltJyk7XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIGNvZGUgY29uY2F0ZW5hdGVzIHRoZSBjb250ZW50cyBvZiB0aGUgc3NtIHJlc29sdmVyIGFuZCBpbnZva2VyIGludG8gYSBzaW5nbGUgbGluZSB0aGF0IGNhbiBiZSB1c2VkIGFzIHRoZSBlc2J1aWxkIGJhbm5lciBjb250ZW50XG4gICAgICogVGhpcyBiYW5uZXIgaXMgcmVzcG9uc2libGUgZm9yIHJlc29sdmluZyB0aGUgY3VzdG9tZXIncyBTU00gcGFyYW1ldGVycyBhdCBydW50aW1lXG4gICAgICovXG4gICAgY29uc3QgYmFubmVyQ29kZSA9IHJlYWRGaWxlU3luYyhzc21SZXNvbHZlckZpbGUsICd1dGYtOCcpXG4gICAgICAuY29uY2F0KHJlYWRGaWxlU3luYyhpbnZva2VTc21SZXNvbHZlckZpbGUsICd1dGYtOCcpKVxuICAgICAgLnNwbGl0KG5ldyBSZWdFeHAoYCR7RU9MfXxcXG58XFxyYCwgJ2cnKSlcbiAgICAgIC5tYXAoKGxpbmUpID0+IGxpbmUucmVwbGFjZSgvXFwvXFwvLiokLywgJycpKSAvLyBzdHJpcCBvdXQgaW5saW5lIGNvbW1lbnRzIGJlY2F1c2UgdGhlIGJhbm5lciBpcyBnb2luZyB0byBiZSBmbGF0dGVuZWQgaW50byBhIHNpbmdsZSBsaW5lXG4gICAgICAuam9pbignJyk7XG5cbiAgICBjb25zdCBmdW5jdGlvbkVudmlyb25tZW50VHlwZUdlbmVyYXRvciA9XG4gICAgICBuZXcgRnVuY3Rpb25FbnZpcm9ubWVudFR5cGVHZW5lcmF0b3IoaWQpO1xuXG4gICAgLy8gZXNidWlsZCBydW5zIGFzIHBhcnQgb2YgdGhlIE5vZGVqc0Z1bmN0aW9uIGNvbnN0cnVjdG9yLCBzbyB3ZSBlYWdlcmx5IGdlbmVyYXRlIHRoZSBwcm9jZXNzIGVudiBzaGltIHdpdGhvdXQgdHlwZXMgc28gaXQgY2FuIGJlIGluY2x1ZGVkIGluIHRoZSBmdW5jdGlvbiBidW5kbGUuXG4gICAgLy8gVGhpcyB3aWxsIGJlIG92ZXJ3cml0dGVuIHdpdGggdGhlIHR5cGVkIGZpbGUgYXQgdGhlIGVuZCBvZiBzeW50aGVzaXNcbiAgICBmdW5jdGlvbkVudmlyb25tZW50VHlwZUdlbmVyYXRvci5nZW5lcmF0ZVByb2Nlc3NFbnZTaGltKCk7XG5cbiAgICBsZXQgZnVuY3Rpb25MYW1iZGE6IE5vZGVqc0Z1bmN0aW9uO1xuICAgIGNvbnN0IGNka0xvZ2dpbmdPcHRpb25zID0gY29udmVydExvZ2dpbmdPcHRpb25zVG9DREsocHJvcHMubG9nZ2luZyk7XG5cbiAgICAvLyBDcmVhdGUgYSBsb2cgZ3JvdXAgaWYgcmV0ZW50aW9uIGlzIHNwZWNpZmllZCAocmVwbGFjaW5nIGRlcHJlY2F0ZWQgbG9nUmV0ZW50aW9uIHByb3BlcnR5KVxuICAgIGxldCBsb2dHcm91cCA9IGNka0xvZ2dpbmdPcHRpb25zLmxvZ0dyb3VwO1xuICAgIGlmIChwcm9wcy5sb2dnaW5nLnJldGVudGlvbiAhPT0gdW5kZWZpbmVkICYmICFsb2dHcm91cCkge1xuICAgICAgbG9nR3JvdXAgPSBjcmVhdGVMb2dHcm91cChzY29wZSwgaWQsIHByb3BzLmxvZ2dpbmcpO1xuICAgIH1cblxuICAgIHRyeSB7XG4gICAgICBmdW5jdGlvbkxhbWJkYSA9IG5ldyBOb2RlanNGdW5jdGlvbihzY29wZSwgYCR7aWR9LWxhbWJkYWAsIHtcbiAgICAgICAgZW50cnk6IHByb3BzLmVudHJ5LFxuICAgICAgICB0aW1lb3V0OiBEdXJhdGlvbi5zZWNvbmRzKHByb3BzLnRpbWVvdXRTZWNvbmRzKSxcbiAgICAgICAgbWVtb3J5U2l6ZTogcHJvcHMubWVtb3J5TUIsXG4gICAgICAgIGFyY2hpdGVjdHVyZTogYXJjaGl0ZWN0dXJlTWFwW3Byb3BzLmFyY2hpdGVjdHVyZV0sXG4gICAgICAgIGVwaGVtZXJhbFN0b3JhZ2VTaXplOiBTaXplLm1lYmlieXRlcyhwcm9wcy5lcGhlbWVyYWxTdG9yYWdlU2l6ZU1CKSxcbiAgICAgICAgcnVudGltZTogbm9kZVZlcnNpb25NYXBbcHJvcHMucnVudGltZV0sXG4gICAgICAgIGxheWVyczogcHJvcHMucmVzb2x2ZWRMYXllcnMsXG4gICAgICAgIGJ1bmRsaW5nOiB7XG4gICAgICAgICAgLi4ucHJvcHMuYnVuZGxpbmcsXG4gICAgICAgICAgYmFubmVyOiBiYW5uZXJDb2RlLFxuICAgICAgICAgIGluamVjdDogc2hpbXMsXG4gICAgICAgICAgZXh0ZXJuYWxNb2R1bGVzOiBPYmplY3Qua2V5cyhwcm9wcy5sYXllcnMpLFxuICAgICAgICAgIGxvZ0xldmVsOiBFc0J1aWxkTG9nTGV2ZWwuRVJST1IsXG4gICAgICAgIH0sXG4gICAgICAgIGxvZ0dyb3VwOiBsb2dHcm91cCxcbiAgICAgICAgYXBwbGljYXRpb25Mb2dMZXZlbFYyOiBjZGtMb2dnaW5nT3B0aW9ucy5sZXZlbCxcbiAgICAgICAgbG9nZ2luZ0Zvcm1hdDogY2RrTG9nZ2luZ09wdGlvbnMuZm9ybWF0LFxuICAgICAgICBkdXJhYmxlQ29uZmlnOiBwcm9wcy5kdXJhYmxlQ29uZmlnXG4gICAgICAgICAgPyB7XG4gICAgICAgICAgICAgIGV4ZWN1dGlvblRpbWVvdXQ6IER1cmF0aW9uLnNlY29uZHMoXG4gICAgICAgICAgICAgICAgcHJvcHMuZHVyYWJsZUNvbmZpZy5leGVjdXRpb25UaW1lb3V0U2Vjb25kcyxcbiAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgcmV0ZW50aW9uUGVyaW9kOiBEdXJhdGlvbi5kYXlzKFxuICAgICAgICAgICAgICAgIHByb3BzLmR1cmFibGVDb25maWcucmV0ZW50aW9uUGVyaW9kRGF5cyxcbiAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgIH1cbiAgICAgICAgICA6IHVuZGVmaW5lZCxcbiAgICAgIH0pO1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAvLyBJZiB0aGUgZXJyb3IgaXMgZnJvbSBFUyBCdW5kbGVyIHdoaWNoIGlzIGV4ZWN1dGVkIGFzIGEgY2hpbGQgcHJvY2VzcyBieSBDREssXG4gICAgICAvLyB0aGVuIHRoZSBlcnJvciBmcm9tIENESyBjb250YWlucyB0aGUgY29tbWFuZCB0aGF0IHdhcyBleGVjdXRlZCBhbG9uZyB3aXRoIHRoZSBleGl0IHN0YXR1cy5cbiAgICAgIC8vIFdyYXBwaW5nIGl0IGhlcmUgIHdvdWxkIGNhdXNlIHRoZSBjZGtfZGVwbG95ZXIgdG8gcmUtdGhyb3cgdGhpcyB3cmFwcGVkIGV4Y2VwdGlvblxuICAgICAgLy8gaW5zdGVhZCBvZiBzY3JhcGluZyB0aGUgc3RkZXJyIGZvciBhY3R1YWwgRVNCdWlsZCBlcnJvci5cbiAgICAgIGlmIChcbiAgICAgICAgZXJyb3IgaW5zdGFuY2VvZiBFcnJvciAmJlxuICAgICAgICBlcnJvci5tZXNzYWdlLm1hdGNoKC9GYWlsZWQgdG8gYnVuZGxlIGFzc2V0LipleGl0ZWQgd2l0aCBzdGF0dXMvKVxuICAgICAgKSB7XG4gICAgICAgIHRocm93IGVycm9yO1xuICAgICAgfVxuICAgICAgdGhyb3cgbmV3IEFtcGxpZnlVc2VyRXJyb3IoXG4gICAgICAgICdOb2RlSlNGdW5jdGlvbkNvbnN0cnVjdEluaXRpYWxpemF0aW9uRXJyb3InLFxuICAgICAgICB7XG4gICAgICAgICAgbWVzc2FnZTogJ0ZhaWxlZCB0byBpbnN0YW50aWF0ZSBub2RlanMgZnVuY3Rpb24gY29uc3RydWN0JyxcbiAgICAgICAgICByZXNvbHV0aW9uOlxuICAgICAgICAgICAgJ1NlZSB0aGUgdW5kZXJseWluZyBlcnJvciBtZXNzYWdlIGZvciBtb3JlIGRldGFpbHMuIFVzZSBgLS1kZWJ1Z2AgZm9yIGFkZGl0aW9uYWwgZGVidWdnaW5nIGluZm9ybWF0aW9uLicsXG4gICAgICAgIH0sXG4gICAgICAgIGVycm9yIGFzIEVycm9yLFxuICAgICAgKTtcbiAgICB9XG5cbiAgICBsZXQgdmVyc2lvbjogSVZlcnNpb24gfCB1bmRlZmluZWQ7XG4gICAgaWYgKHByb3BzLmR1cmFibGVDb25maWcpIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIHZlcnNpb24gPSBmdW5jdGlvbkxhbWJkYS5jdXJyZW50VmVyc2lvbjtcbiAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgIHRocm93IG5ldyBBbXBsaWZ5VXNlckVycm9yKFxuICAgICAgICAgICdEdXJhYmxlRnVuY3Rpb25WZXJzaW9uSW5pdGlhbGl6YXRpb25FcnJvcicsXG4gICAgICAgICAge1xuICAgICAgICAgICAgbWVzc2FnZTpcbiAgICAgICAgICAgICAgJ0ZhaWxlZCB0byBjcmVhdGUgdmVyc2lvbiBmb3IgZHVyYWJsZSBmdW5jdGlvbi4gRHVyYWJsZSBmdW5jdGlvbnMgcmVxdWlyZSBhIHZlcnNpb25lZCBMYW1iZGEgZnVuY3Rpb24uJyxcbiAgICAgICAgICAgIHJlc29sdXRpb246ICdTZWUgdGhlIHVuZGVybHlpbmcgZXJyb3IgbWVzc2FnZSBmb3IgbW9yZSBkZXRhaWxzLicsXG4gICAgICAgICAgfSxcbiAgICAgICAgICBlcnJvciBhcyBFcnJvcixcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0cnkge1xuICAgICAgY29uc3Qgc2NoZWR1bGVQcm9wcyA9IGNvbnZlcnRGdW5jdGlvblNjaGVkdWxlc1RvU2NoZWR1bGVQcm9wcyhcbiAgICAgICAgZnVuY3Rpb25MYW1iZGEsXG4gICAgICAgIHByb3BzLnNjaGVkdWxlLFxuICAgICAgKTtcblxuICAgICAgY29uc3QgbGFtYmRhVGFyZ2V0ID0gbmV3IHRhcmdldHMuTGFtYmRhSW52b2tlKHZlcnNpb24gPz8gZnVuY3Rpb25MYW1iZGEpO1xuXG4gICAgICBzY2hlZHVsZVByb3BzLmZvckVhY2goKHsgc2NoZWR1bGUsIGRlc2NyaXB0aW9uIH0sIGluZGV4KSA9PiB7XG4gICAgICAgIC8vIExhbWJkYSBuYW1lIHdpbGwgYmUgcHJlcGVuZGVkIHRvIHNjaGVkdWxlIGlkLCBzbyBvbmx5IHVzaW5nIGluZGV4IGhlcmUgZm9yIHVuaXF1ZW5lc3NcbiAgICAgICAgbmV3IHNjaGVkdWxlci5TY2hlZHVsZShmdW5jdGlvbkxhbWJkYSwgYHNjaGVkdWxlLSR7aW5kZXh9YCwge1xuICAgICAgICAgIHNjaGVkdWxlLFxuICAgICAgICAgIGRlc2NyaXB0aW9uLFxuICAgICAgICAgIHRhcmdldDogbGFtYmRhVGFyZ2V0LFxuICAgICAgICB9KTtcbiAgICAgIH0pO1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICB0aHJvdyBuZXcgQW1wbGlmeVVzZXJFcnJvcihcbiAgICAgICAgJ0Z1bmN0aW9uU2NoZWR1bGVJbml0aWFsaXphdGlvbkVycm9yJyxcbiAgICAgICAge1xuICAgICAgICAgIG1lc3NhZ2U6ICdGYWlsZWQgdG8gaW5zdGFudGlhdGUgc2NoZWR1bGUgZm9yIG5vZGVqcyBmdW5jdGlvbicsXG4gICAgICAgICAgcmVzb2x1dGlvbjogJ1NlZSB0aGUgdW5kZXJseWluZyBlcnJvciBtZXNzYWdlIGZvciBtb3JlIGRldGFpbHMuJyxcbiAgICAgICAgfSxcbiAgICAgICAgZXJyb3IgYXMgRXJyb3IsXG4gICAgICApO1xuICAgIH1cblxuICAgIFRhZ3Mub2YoZnVuY3Rpb25MYW1iZGEpLmFkZChUYWdOYW1lLkZSSUVORExZX05BTUUsIGlkKTtcblxuICAgIHRoaXMuZnVuY3Rpb25FbnZpcm9ubWVudFRyYW5zbGF0b3IgPSBuZXcgRnVuY3Rpb25FbnZpcm9ubWVudFRyYW5zbGF0b3IoXG4gICAgICBmdW5jdGlvbkxhbWJkYSxcbiAgICAgIHByb3BzLmVudmlyb25tZW50LFxuICAgICAgYmFja2VuZFNlY3JldFJlc29sdmVyLFxuICAgICAgZnVuY3Rpb25FbnZpcm9ubWVudFR5cGVHZW5lcmF0b3IsXG4gICAgKTtcblxuICAgIHRoaXMucmVzb3VyY2VzID0ge1xuICAgICAgbGFtYmRhOiBmdW5jdGlvbkxhbWJkYSxcbiAgICAgIGNmblJlc291cmNlczoge1xuICAgICAgICBjZm5GdW5jdGlvbjogZnVuY3Rpb25MYW1iZGEubm9kZS5maW5kQ2hpbGQoJ1Jlc291cmNlJykgYXMgQ2ZuRnVuY3Rpb24sXG4gICAgICB9LFxuICAgIH07XG5cbiAgICB0aGlzLnN0b3JlT3V0cHV0KCk7XG4gIH1cblxuICBhZGRFbnZpcm9ubWVudCA9IChrZXk6IHN0cmluZywgdmFsdWU6IHN0cmluZyB8IEJhY2tlbmRTZWNyZXQpID0+IHtcbiAgICB0aGlzLmZ1bmN0aW9uRW52aXJvbm1lbnRUcmFuc2xhdG9yLmFkZEVudmlyb25tZW50RW50cnkoa2V5LCB2YWx1ZSk7XG4gIH07XG5cbiAgZ2V0UmVzb3VyY2VBY2Nlc3NBY2NlcHRvciA9ICgpOiBSZXNvdXJjZUFjY2Vzc0FjY2VwdG9yID0+XG4gICAgbmV3IEZ1bmN0aW9uUmVzb3VyY2VBY2Nlc3NBY2NlcHRvcihcbiAgICAgIHRoaXMsXG4gICAgICB0aGlzLmZ1bmN0aW9uRW52aXJvbm1lbnRUcmFuc2xhdG9yLFxuICAgICk7XG59XG5cbmNvbnN0IGlzV2hvbGVOdW1iZXJCZXR3ZWVuSW5jbHVzaXZlID0gKFxuICB0ZXN0OiBudW1iZXIsXG4gIG1pbjogbnVtYmVyLFxuICBtYXg6IG51bWJlcixcbikgPT4gbWluIDw9IHRlc3QgJiYgdGVzdCA8PSBtYXggJiYgdGVzdCAlIDEgPT09IDA7XG5cbmV4cG9ydCB0eXBlIE5vZGVWZXJzaW9uID0gMTggfCAyMCB8IDIyIHwgMjQ7XG5cbmNvbnN0IG5vZGVWZXJzaW9uTWFwOiBSZWNvcmQ8Tm9kZVZlcnNpb24sIFJ1bnRpbWU+ID0ge1xuICAxODogUnVudGltZS5OT0RFSlNfMThfWCxcbiAgMjA6IFJ1bnRpbWUuTk9ERUpTXzIwX1gsXG4gIDIyOiBSdW50aW1lLk5PREVKU18yMl9YLFxuICAyNDogUnVudGltZS5OT0RFSlNfMjRfWCxcbn07XG5cbmV4cG9ydCB0eXBlIEZ1bmN0aW9uQXJjaGl0ZWN0dXJlID0gJ3g4Nl82NCcgfCAnYXJtNjQnO1xuXG5jb25zdCBhcmNoaXRlY3R1cmVNYXA6IFJlY29yZDxGdW5jdGlvbkFyY2hpdGVjdHVyZSwgQXJjaGl0ZWN0dXJlPiA9IHtcbiAgYXJtNjQ6IEFyY2hpdGVjdHVyZS5BUk1fNjQsXG4gIHg4Nl82NDogQXJjaGl0ZWN0dXJlLlg4Nl82NCxcbn07XG4iXX0=
|