UNPKG

@aws-cdk/aws-lambda

Version:

The CDK Construct Library for AWS::Lambda

491 lines 53 kB
"use strict"; var _a, _b, _c, _d, _e, _f, _g; Object.defineProperty(exports, "__esModule", { value: true }); exports.AssetImageCode = exports.EcrImageCode = exports.CfnParametersCode = exports.AssetCode = exports.InlineCode = exports.S3Code = exports.Code = void 0; const jsiiDeprecationWarnings = require("../.warnings.jsii.js"); const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti"); const ecr_assets = require("@aws-cdk/aws-ecr-assets"); const iam = require("@aws-cdk/aws-iam"); const s3_assets = require("@aws-cdk/aws-s3-assets"); const cdk = require("@aws-cdk/core"); /** * Represents the Lambda Handler Code. */ class Code { /** * Lambda handler code as an S3 object. * @param bucket The S3 bucket * @param key The object key * @param objectVersion Optional S3 object version */ static fromBucket(bucket, key, objectVersion) { return new S3Code(bucket, key, objectVersion); } /** * DEPRECATED * @deprecated use `fromBucket` */ static bucket(bucket, key, objectVersion) { try { jsiiDeprecationWarnings.print("@aws-cdk/aws-lambda.Code#bucket", "use `fromBucket`"); } catch (error) { if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") { Error.captureStackTrace(error, this.bucket); } throw error; } return this.fromBucket(bucket, key, objectVersion); } /** * Inline code for Lambda handler * @returns `LambdaInlineCode` with inline code. * @param code The actual handler code (limited to 4KiB) */ static fromInline(code) { return new InlineCode(code); } /** * DEPRECATED * @deprecated use `fromInline` */ static inline(code) { try { jsiiDeprecationWarnings.print("@aws-cdk/aws-lambda.Code#inline", "use `fromInline`"); } catch (error) { if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") { Error.captureStackTrace(error, this.inline); } throw error; } return this.fromInline(code); } /** * Loads the function code from a local disk path. * * @param path Either a directory with the Lambda code bundle or a .zip file */ static fromAsset(path, options) { return new AssetCode(path, options); } /** * Loads the function code from an asset created by a Docker build. * * By default, the asset is expected to be located at `/asset` in the * image. * * @param path The path to the directory containing the Docker file * @param options Docker build options */ static fromDockerBuild(path, options = {}) { try { jsiiDeprecationWarnings._aws_cdk_aws_lambda_DockerBuildAssetOptions(options); } catch (error) { if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") { Error.captureStackTrace(error, this.fromDockerBuild); } throw error; } let imagePath = options.imagePath ?? '/asset/.'; // ensure imagePath ends with /. to copy the **content** at this path if (imagePath.endsWith('/')) { imagePath = `${imagePath}.`; } else if (!imagePath.endsWith('/.')) { imagePath = `${imagePath}/.`; } const assetPath = cdk.DockerImage .fromBuild(path, options) .cp(imagePath, options.outputPath); return new AssetCode(assetPath); } /** * DEPRECATED * @deprecated use `fromAsset` */ static asset(path) { try { jsiiDeprecationWarnings.print("@aws-cdk/aws-lambda.Code#asset", "use `fromAsset`"); } catch (error) { if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") { Error.captureStackTrace(error, this.asset); } throw error; } return this.fromAsset(path); } /** * Creates a new Lambda source defined using CloudFormation parameters. * * @returns a new instance of `CfnParametersCode` * @param props optional construction properties of {@link CfnParametersCode} */ static fromCfnParameters(props) { try { jsiiDeprecationWarnings._aws_cdk_aws_lambda_CfnParametersCodeProps(props); } catch (error) { if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") { Error.captureStackTrace(error, this.fromCfnParameters); } throw error; } return new CfnParametersCode(props); } /** * DEPRECATED * @deprecated use `fromCfnParameters` */ static cfnParameters(props) { try { jsiiDeprecationWarnings.print("@aws-cdk/aws-lambda.Code#cfnParameters", "use `fromCfnParameters`"); jsiiDeprecationWarnings._aws_cdk_aws_lambda_CfnParametersCodeProps(props); } catch (error) { if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") { Error.captureStackTrace(error, this.cfnParameters); } throw error; } return this.fromCfnParameters(props); } /** * Use an existing ECR image as the Lambda code. * @param repository the ECR repository that the image is in * @param props properties to further configure the selected image */ static fromEcrImage(repository, props) { try { jsiiDeprecationWarnings._aws_cdk_aws_lambda_EcrImageCodeProps(props); } catch (error) { if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") { Error.captureStackTrace(error, this.fromEcrImage); } throw error; } return new EcrImageCode(repository, props); } /** * Create an ECR image from the specified asset and bind it as the Lambda code. * @param directory the directory from which the asset must be created * @param props properties to further configure the selected image */ static fromAssetImage(directory, props = {}) { try { jsiiDeprecationWarnings._aws_cdk_aws_lambda_AssetImageCodeProps(props); } catch (error) { if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") { Error.captureStackTrace(error, this.fromAssetImage); } throw error; } return new AssetImageCode(directory, props); } /** * Called after the CFN function resource has been created to allow the code * class to bind to it. Specifically it's required to allow assets to add * metadata for tooling like SAM CLI to be able to find their origins. */ bindToResource(_resource, _options) { try { jsiiDeprecationWarnings._aws_cdk_aws_lambda_ResourceBindOptions(_options); } catch (error) { if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") { Error.captureStackTrace(error, this.bindToResource); } throw error; } return; } } exports.Code = Code; _a = JSII_RTTI_SYMBOL_1; Code[_a] = { fqn: "@aws-cdk/aws-lambda.Code", version: "1.204.0" }; /** * Lambda code from an S3 archive. */ class S3Code extends Code { constructor(bucket, key, objectVersion) { super(); this.key = key; this.objectVersion = objectVersion; this.isInline = false; if (!bucket.bucketName) { throw new Error('bucketName is undefined for the provided bucket'); } this.bucketName = bucket.bucketName; } bind(_scope) { return { s3Location: { bucketName: this.bucketName, objectKey: this.key, objectVersion: this.objectVersion, }, }; } } exports.S3Code = S3Code; _b = JSII_RTTI_SYMBOL_1; S3Code[_b] = { fqn: "@aws-cdk/aws-lambda.S3Code", version: "1.204.0" }; /** * Lambda code from an inline string (limited to 4KiB). */ class InlineCode extends Code { constructor(code) { super(); this.code = code; this.isInline = true; if (code.length === 0) { throw new Error('Lambda inline code cannot be empty'); } if (code.length > 4096) { throw new Error('Lambda source is too large, must be <= 4096 but is ' + code.length); } } bind(_scope) { return { inlineCode: this.code, }; } } exports.InlineCode = InlineCode; _c = JSII_RTTI_SYMBOL_1; InlineCode[_c] = { fqn: "@aws-cdk/aws-lambda.InlineCode", version: "1.204.0" }; /** * Lambda code from a local directory. */ class AssetCode extends Code { /** * @param path The path to the asset file or directory. */ constructor(path, options = {}) { super(); this.path = path; this.options = options; this.isInline = false; } bind(scope) { // If the same AssetCode is used multiple times, retain only the first instantiation. if (!this.asset) { this.asset = new s3_assets.Asset(scope, 'Code', { path: this.path, ...this.options, }); } else if (cdk.Stack.of(this.asset) !== cdk.Stack.of(scope)) { throw new Error(`Asset is already associated with another stack '${cdk.Stack.of(this.asset).stackName}'. ` + 'Create a new Code instance for every stack.'); } if (!this.asset.isZipArchive) { throw new Error(`Asset must be a .zip file or a directory (${this.path})`); } return { s3Location: { bucketName: this.asset.s3BucketName, objectKey: this.asset.s3ObjectKey, }, }; } bindToResource(resource, options = {}) { try { jsiiDeprecationWarnings._aws_cdk_aws_lambda_ResourceBindOptions(options); } catch (error) { if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") { Error.captureStackTrace(error, this.bindToResource); } throw error; } if (!this.asset) { throw new Error('bindToResource() must be called after bind()'); } const resourceProperty = options.resourceProperty || 'Code'; // https://github.com/aws/aws-cdk/issues/1432 this.asset.addResourceMetadata(resource, resourceProperty); } } exports.AssetCode = AssetCode; _d = JSII_RTTI_SYMBOL_1; AssetCode[_d] = { fqn: "@aws-cdk/aws-lambda.AssetCode", version: "1.204.0" }; /** * Lambda code defined using 2 CloudFormation parameters. * Useful when you don't have access to the code of your Lambda from your CDK code, so you can't use Assets, * and you want to deploy the Lambda in a CodePipeline, using CloudFormation Actions - * you can fill the parameters using the {@link #assign} method. */ class CfnParametersCode extends Code { constructor(props = {}) { super(); this.isInline = false; try { jsiiDeprecationWarnings._aws_cdk_aws_lambda_CfnParametersCodeProps(props); } catch (error) { if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") { Error.captureStackTrace(error, CfnParametersCode); } throw error; } this._bucketNameParam = props.bucketNameParam; this._objectKeyParam = props.objectKeyParam; } bind(scope) { if (!this._bucketNameParam) { this._bucketNameParam = new cdk.CfnParameter(scope, 'LambdaSourceBucketNameParameter', { type: 'String', }); } if (!this._objectKeyParam) { this._objectKeyParam = new cdk.CfnParameter(scope, 'LambdaSourceObjectKeyParameter', { type: 'String', }); } return { s3Location: { bucketName: this._bucketNameParam.valueAsString, objectKey: this._objectKeyParam.valueAsString, }, }; } /** * Create a parameters map from this instance's CloudFormation parameters. * * It returns a map with 2 keys that correspond to the names of the parameters defined in this Lambda code, * and as values it contains the appropriate expressions pointing at the provided S3 location * (most likely, obtained from a CodePipeline Artifact by calling the `artifact.s3Location` method). * The result should be provided to the CloudFormation Action * that is deploying the Stack that the Lambda with this code is part of, * in the `parameterOverrides` property. * * @param location the location of the object in S3 that represents the Lambda code */ assign(location) { const ret = {}; ret[this.bucketNameParam] = location.bucketName; ret[this.objectKeyParam] = location.objectKey; return ret; } get bucketNameParam() { if (this._bucketNameParam) { return this._bucketNameParam.logicalId; } else { throw new Error('Pass CfnParametersCode to a Lambda Function before accessing the bucketNameParam property'); } } get objectKeyParam() { if (this._objectKeyParam) { return this._objectKeyParam.logicalId; } else { throw new Error('Pass CfnParametersCode to a Lambda Function before accessing the objectKeyParam property'); } } } exports.CfnParametersCode = CfnParametersCode; _e = JSII_RTTI_SYMBOL_1; CfnParametersCode[_e] = { fqn: "@aws-cdk/aws-lambda.CfnParametersCode", version: "1.204.0" }; /** * Represents a Docker image in ECR that can be bound as Lambda Code. */ class EcrImageCode extends Code { constructor(repository, props = {}) { super(); this.repository = repository; this.props = props; this.isInline = false; try { jsiiDeprecationWarnings._aws_cdk_aws_lambda_EcrImageCodeProps(props); } catch (error) { if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") { Error.captureStackTrace(error, EcrImageCode); } throw error; } } bind(_) { this.repository.grantPull(new iam.ServicePrincipal('lambda.amazonaws.com')); return { image: { imageUri: this.repository.repositoryUriForTagOrDigest(this.props?.tagOrDigest ?? this.props?.tag ?? 'latest'), cmd: this.props.cmd, entrypoint: this.props.entrypoint, workingDirectory: this.props.workingDirectory, }, }; } } exports.EcrImageCode = EcrImageCode; _f = JSII_RTTI_SYMBOL_1; EcrImageCode[_f] = { fqn: "@aws-cdk/aws-lambda.EcrImageCode", version: "1.204.0" }; /** * Represents an ECR image that will be constructed from the specified asset and can be bound as Lambda code. */ class AssetImageCode extends Code { constructor(directory, props) { super(); this.directory = directory; this.props = props; this.isInline = false; try { jsiiDeprecationWarnings._aws_cdk_aws_lambda_AssetImageCodeProps(props); } catch (error) { if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") { Error.captureStackTrace(error, AssetImageCode); } throw error; } } bind(scope) { // If the same AssetImageCode is used multiple times, retain only the first instantiation. if (!this.asset) { this.asset = new ecr_assets.DockerImageAsset(scope, 'AssetImage', { directory: this.directory, ...this.props, }); this.asset.repository.grantPull(new iam.ServicePrincipal('lambda.amazonaws.com')); } else if (cdk.Stack.of(this.asset) !== cdk.Stack.of(scope)) { throw new Error(`Asset is already associated with another stack '${cdk.Stack.of(this.asset).stackName}'. ` + 'Create a new Code instance for every stack.'); } return { image: { imageUri: this.asset.imageUri, entrypoint: this.props.entrypoint, cmd: this.props.cmd, workingDirectory: this.props.workingDirectory, }, }; } bindToResource(resource, options = {}) { try { jsiiDeprecationWarnings._aws_cdk_aws_lambda_ResourceBindOptions(options); } catch (error) { if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") { Error.captureStackTrace(error, this.bindToResource); } throw error; } if (!this.asset) { throw new Error('bindToResource() must be called after bind()'); } const resourceProperty = options.resourceProperty || 'Code.ImageUri'; // https://github.com/aws/aws-cdk/issues/14593 this.asset.addResourceMetadata(resource, resourceProperty); } } exports.AssetImageCode = AssetImageCode; _g = JSII_RTTI_SYMBOL_1; AssetImageCode[_g] = { fqn: "@aws-cdk/aws-lambda.AssetImageCode", version: "1.204.0" }; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29kZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImNvZGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7O0FBQ0Esc0RBQXNEO0FBQ3RELHdDQUF3QztBQUV4QyxvREFBb0Q7QUFDcEQscUNBQXFDO0FBTXJDOztHQUVHO0FBQ0gsTUFBc0IsSUFBSTtJQUN4Qjs7Ozs7T0FLRztJQUNJLE1BQU0sQ0FBQyxVQUFVLENBQUMsTUFBa0IsRUFBRSxHQUFXLEVBQUUsYUFBc0I7UUFDOUUsT0FBTyxJQUFJLE1BQU0sQ0FBQyxNQUFNLEVBQUUsR0FBRyxFQUFFLGFBQWEsQ0FBQyxDQUFDO0tBQy9DO0lBRUQ7OztPQUdHO0lBQ0ksTUFBTSxDQUFDLE1BQU0sQ0FBQyxNQUFrQixFQUFFLEdBQVcsRUFBRSxhQUFzQjs7Ozs7Ozs7OztRQUMxRSxPQUFPLElBQUksQ0FBQyxVQUFVLENBQUMsTUFBTSxFQUFFLEdBQUcsRUFBRSxhQUFhLENBQUMsQ0FBQztLQUNwRDtJQUVEOzs7O09BSUc7SUFDSSxNQUFNLENBQUMsVUFBVSxDQUFDLElBQVk7UUFDbkMsT0FBTyxJQUFJLFVBQVUsQ0FBQyxJQUFJLENBQUMsQ0FBQztLQUM3QjtJQUVEOzs7T0FHRztJQUNJLE1BQU0sQ0FBQyxNQUFNLENBQUMsSUFBWTs7Ozs7Ozs7OztRQUMvQixPQUFPLElBQUksQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLENBQUM7S0FDOUI7SUFFRDs7OztPQUlHO0lBQ0ksTUFBTSxDQUFDLFNBQVMsQ0FBQyxJQUFZLEVBQUUsT0FBZ0M7UUFDcEUsT0FBTyxJQUFJLFNBQVMsQ0FBQyxJQUFJLEVBQUUsT0FBTyxDQUFDLENBQUM7S0FDckM7SUFFRDs7Ozs7Ozs7T0FRRztJQUNJLE1BQU0sQ0FBQyxlQUFlLENBQUMsSUFBWSxFQUFFLFVBQW1DLEVBQUU7Ozs7Ozs7Ozs7UUFDL0UsSUFBSSxTQUFTLEdBQUcsT0FBTyxDQUFDLFNBQVMsSUFBSSxVQUFVLENBQUM7UUFFaEQscUVBQXFFO1FBQ3JF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QUFDLHNCQUFzQixDQUFDLENBQUMsQ0FBQztTQUNuRjthQUFNLElBQUksR0FBRyxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxLQUFLLEdBQUcsQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLEtBQUssQ0FBQyxFQUFFO1lBQzNELE1BQU0sSUFBSSxLQUFLLENBQUMsbURBQW1ELEdBQUcsQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxTQUFTLEtBQUs7Z0JBQ3hHLDZDQUE2QyxDQUFDLENBQUM7U0FDbEQ7UUFFRCxPQUFPO1lBQ0wsS0FBSyxFQUFFO2dCQUNMLFFBQVEsRUFBRSxJQUFJLENBQUMsS0FBSyxDQUFDLFFBQVE7Z0JBQzdCLFVBQVUsRUFBRSxJQUFJLENBQUMsS0FBSyxDQUFDLFVBQVU7Z0JBQ2pDLEdBQUcsRUFBRSxJQUFJLENBQUMsS0FBSyxDQUFDLEdBQUc7Z0JBQ25CLGdCQUFnQixFQUFFLElBQUksQ0FBQyxLQUFLLENBQUMsZ0JBQWdCO2FBQzlDO1NBQ0YsQ0FBQztLQUNIO0lBRU0sY0FBYyxDQUFDLFFBQXlCLEVBQUUsVUFBK0IsRUFBRzs7Ozs7Ozs7OztRQUNqRixJQUFJLENBQUMsSUFBSSxDQUFDLEtBQUssRUFBRTtZQUNmLE1BQU0sSUFBSSxLQUFLLENBQUMsOENBQThDLENBQUMsQ0FBQztTQUNqRTtRQUVELE1BQU0sZ0JBQWdCLEdBQUcsT0FBTyxDQUFDLGdCQUFnQixJQUFJLGVBQWUsQ0FBQztRQUVyRSw4Q0FBOEM7UUFDOUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxtQkFBbUIsQ0FBQyxRQUFRLEVBQUUsZ0JBQWdCLENBQUMsQ0FBQztLQUM1RDs7QUF4Q0gsd0NBeUNDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICogYXMgZWNyIGZyb20gJ0Bhd3MtY2RrL2F3cy1lY3InO1xuaW1wb3J0ICogYXMgZWNyX2Fzc2V0cyBmcm9tICdAYXdzLWNkay9hd3MtZWNyLWFzc2V0cyc7XG5pbXBvcnQgKiBhcyBpYW0gZnJvbSAnQGF3cy1jZGsvYXdzLWlhbSc7XG5pbXBvcnQgKiBhcyBzMyBmcm9tICdAYXdzLWNkay9hd3MtczMnO1xuaW1wb3J0ICogYXMgczNfYXNzZXRzIGZyb20gJ0Bhd3MtY2RrL2F3cy1zMy1hc3NldHMnO1xuaW1wb3J0ICogYXMgY2RrIGZyb20gJ0Bhd3MtY2RrL2NvcmUnO1xuXG4vLyBrZWVwIHRoaXMgaW1wb3J0IHNlcGFyYXRlIGZyb20gb3RoZXIgaW1wb3J0cyB0byByZWR1Y2UgY2hhbmNlIGZvciBtZXJnZSBjb25mbGljdHMgd2l0aCB2Mi1tYWluXG4vLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tZHVwbGljYXRlLWltcG9ydHMsIGltcG9ydC9vcmRlclxuaW1wb3J0IHsgQ29uc3RydWN0IH0gZnJvbSAnQGF3cy1jZGsvY29yZSc7XG5cbi8qKlxuICogUmVwcmVzZW50cyB0aGUgTGFtYmRhIEhhbmRsZXIgQ29kZS5cbiAqL1xuZXhwb3J0IGFic3RyYWN0IGNsYXNzIENvZGUge1xuICAvKipcbiAgICogTGFtYmRhIGhhbmRsZXIgY29kZSBhcyBhbiBTMyBvYmplY3QuXG4gICAqIEBwYXJhbSBidWNrZXQgVGhlIFMzIGJ1Y2tldFxuICAgKiBAcGFyYW0ga2V5IFRoZSBvYmplY3Qga2V5XG4gICAqIEBwYXJhbSBvYmplY3RWZXJzaW9uIE9wdGlvbmFsIFMzIG9iamVjdCB2ZXJzaW9uXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIGZyb21CdWNrZXQoYnVja2V0OiBzMy5JQnVja2V0LCBrZXk6IHN0cmluZywgb2JqZWN0VmVyc2lvbj86IHN0cmluZyk6IFMzQ29kZSB7XG4gICAgcmV0dXJuIG5ldyBTM0NvZGUoYnVja2V0LCBrZXksIG9iamVjdFZlcnNpb24pO1xuICB9XG5cbiAgLyoqXG4gICAqIERFUFJFQ0FURURcbiAgICogQGRlcHJlY2F0ZWQgdXNlIGBmcm9tQnVja2V0YFxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBidWNrZXQoYnVja2V0OiBzMy5JQnVja2V0LCBrZXk6IHN0cmluZywgb2JqZWN0VmVyc2lvbj86IHN0cmluZyk6IFMzQ29kZSB7XG4gICAgcmV0dXJuIHRoaXMuZnJvbUJ1Y2tldChidWNrZXQsIGtleSwgb2JqZWN0VmVyc2lvbik7XG4gIH1cblxuICAvKipcbiAgICogSW5saW5lIGNvZGUgZm9yIExhbWJkYSBoYW5kbGVyXG4gICAqIEByZXR1cm5zIGBMYW1iZGFJbmxpbmVDb2RlYCB3aXRoIGlubGluZSBjb2RlLlxuICAgKiBAcGFyYW0gY29kZSBUaGUgYWN0dWFsIGhhbmRsZXIgY29kZSAobGltaXRlZCB0byA0S2lCKVxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBmcm9tSW5saW5lKGNvZGU6IHN0cmluZyk6IElubGluZUNvZGUge1xuICAgIHJldHVybiBuZXcgSW5saW5lQ29kZShjb2RlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBERVBSRUNBVEVEXG4gICAqIEBkZXByZWNhdGVkIHVzZSBgZnJvbUlubGluZWBcbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgaW5saW5lKGNvZGU6IHN0cmluZyk6IElubGluZUNvZGUge1xuICAgIHJldHVybiB0aGlzLmZyb21JbmxpbmUoY29kZSk7XG4gIH1cblxuICAvKipcbiAgICogTG9hZHMgdGhlIGZ1bmN0aW9uIGNvZGUgZnJvbSBhIGxvY2FsIGRpc2sgcGF0aC5cbiAgICpcbiAgICogQHBhcmFtIHBhdGggRWl0aGVyIGEgZGlyZWN0b3J5IHdpdGggdGhlIExhbWJkYSBjb2RlIGJ1bmRsZSBvciBhIC56aXAgZmlsZVxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBmcm9tQXNzZXQocGF0aDogc3RyaW5nLCBvcHRpb25zPzogczNfYXNzZXRzLkFzc2V0T3B0aW9ucyk6IEFzc2V0Q29kZSB7XG4gICAgcmV0dXJuIG5ldyBBc3NldENvZGUocGF0aCwgb3B0aW9ucyk7XG4gIH1cblxuICAvKipcbiAgICogTG9hZHMgdGhlIGZ1bmN0aW9uIGNvZGUgZnJvbSBhbiBhc3NldCBjcmVhdGVkIGJ5IGEgRG9ja2VyIGJ1aWxkLlxuICAgKlxuICAgKiBCeSBkZWZhdWx0LCB0aGUgYXNzZXQgaXMgZXhwZWN0ZWQgdG8gYmUgbG9jYXRlZCBhdCBgL2Fzc2V0YCBpbiB0aGVcbiAgICogaW1hZ2UuXG4gICAqXG4gICAqIEBwYXJhbSBwYXRoIFRoZSBwYXRoIHRvIHRoZSBkaXJlY3RvcnkgY29udGFpbmluZyB0aGUgRG9ja2VyIGZpbGVcbiAgICogQHBhcmFtIG9wdGlvbnMgRG9ja2VyIGJ1aWxkIG9wdGlvbnNcbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgZnJvbURvY2tlckJ1aWxkKHBhdGg6IHN0cmluZywgb3B0aW9uczogRG9ja2VyQnVpbGRBc3NldE9wdGlvbnMgPSB7fSk6IEFzc2V0Q29kZSB7XG4gICAgbGV0IGltYWdlUGF0aCA9IG9wdGlvbnMuaW1hZ2VQYXRoID8/ICcvYXNzZXQvLic7XG5cbiAgICAvLyBlbnN1cmUgaW1hZ2VQYXRoIGVuZHMgd2l0aCAvLiB0byBjb3B5IHRoZSAqKmNvbnRlbnQqKiBhdCB0aGlzIHBhdGhcbiAgICBpZiAoaW1hZ2VQYXRoLmVuZHNXaXRoKCcvJykpIHtcbiAgICAgIGltYWdlUGF0aCA9IGAke2ltYWdlUGF0aH0uYDtcbiAgICB9IGVsc2UgaWYgKCFpbWFnZVBhdGguZW5kc1dpdGgoJy8uJykpIHtcbiAgICAgIGltYWdlUGF0aCA9IGAke2ltYWdlUGF0aH0vLmA7XG4gICAgfVxuXG4gICAgY29uc3QgYXNzZXRQYXRoID0gY2RrLkRvY2tlckltYWdlXG4gICAgICAuZnJvbUJ1aWxkKHBhdGgsIG9wdGlvbnMpXG4gICAgICAuY3AoaW1hZ2VQYXRoLCBvcHRpb25zLm91dHB1dFBhdGgpO1xuXG4gICAgcmV0dXJuIG5ldyBBc3NldENvZGUoYXNzZXRQYXRoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBERVBSRUNBVEVEXG4gICAqIEBkZXByZWNhdGVkIHVzZSBgZnJvbUFzc2V0YFxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBhc3NldChwYXRoOiBzdHJpbmcpOiBBc3NldENvZGUge1xuICAgIHJldHVybiB0aGlzLmZyb21Bc3NldChwYXRoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGVzIGEgbmV3IExhbWJkYSBzb3VyY2UgZGVmaW5lZCB1c2luZyBDbG91ZEZvcm1hdGlvbiBwYXJhbWV0ZXJzLlxuICAgKlxuICAgKiBAcmV0dXJucyBhIG5ldyBpbnN0YW5jZSBvZiBgQ2ZuUGFyYW1ldGVyc0NvZGVgXG4gICAqIEBwYXJhbSBwcm9wcyBvcHRpb25hbCBjb25zdHJ1Y3Rpb24gcHJvcGVydGllcyBvZiB7QGxpbmsgQ2ZuUGFyYW1ldGVyc0NvZGV9XG4gICAqL1xuICBwdWJsaWMgc3RhdGljIGZyb21DZm5QYXJhbWV0ZXJzKHByb3BzPzogQ2ZuUGFyYW1ldGVyc0NvZGVQcm9wcyk6IENmblBhcmFtZXRlcnNDb2RlIHtcbiAgICByZXR1cm4gbmV3IENmblBhcmFtZXRlcnNDb2RlKHByb3BzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBERVBSRUNBVEVEXG4gICAqIEBkZXByZWNhdGVkIHVzZSBgZnJvbUNmblBhcmFtZXRlcnNgXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIGNmblBhcmFtZXRlcnMocHJvcHM/OiBDZm5QYXJhbWV0ZXJzQ29kZVByb3BzKTogQ2ZuUGFyYW1ldGVyc0NvZGUge1xuICAgIHJldHVybiB0aGlzLmZyb21DZm5QYXJhbWV0ZXJzKHByb3BzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBVc2UgYW4gZXhpc3RpbmcgRUNSIGltYWdlIGFzIHRoZSBMYW1iZGEgY29kZS5cbiAgICogQHBhcmFtIHJlcG9zaXRvcnkgdGhlIEVDUiByZXBvc2l0b3J5IHRoYXQgdGhlIGltYWdlIGlzIGluXG4gICAqIEBwYXJhbSBwcm9wcyBwcm9wZXJ0aWVzIHRvIGZ1cnRoZXIgY29uZmlndXJlIHRoZSBzZWxlY3RlZCBpbWFnZVxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBmcm9tRWNySW1hZ2UocmVwb3NpdG9yeTogZWNyLklSZXBvc2l0b3J5LCBwcm9wcz86IEVjckltYWdlQ29kZVByb3BzKSB7XG4gICAgcmV0dXJuIG5ldyBFY3JJbWFnZUNvZGUocmVwb3NpdG9yeSwgcHJvcHMpO1xuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZSBhbiBFQ1IgaW1hZ2UgZnJvbSB0aGUgc3BlY2lmaWVkIGFzc2V0IGFuZCBiaW5kIGl0IGFzIHRoZSBMYW1iZGEgY29kZS5cbiAgICogQHBhcmFtIGRpcmVjdG9yeSB0aGUgZGlyZWN0b3J5IGZyb20gd2hpY2ggdGhlIGFzc2V0IG11c3QgYmUgY3JlYXRlZFxuICAgKiBAcGFyYW0gcHJvcHMgcHJvcGVydGllcyB0byBmdXJ0aGVyIGNvbmZpZ3VyZSB0aGUgc2VsZWN0ZWQgaW1hZ2VcbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgZnJvbUFzc2V0SW1hZ2UoZGlyZWN0b3J5OiBzdHJpbmcsIHByb3BzOiBBc3NldEltYWdlQ29kZVByb3BzID0ge30pIHtcbiAgICByZXR1cm4gbmV3IEFzc2V0SW1hZ2VDb2RlKGRpcmVjdG9yeSwgcHJvcHMpO1xuICB9XG5cbiAgLyoqXG4gICAqIERldGVybWluZXMgd2hldGhlciB0aGlzIENvZGUgaXMgaW5saW5lIGNvZGUgb3Igbm90LlxuICAgKlxuICAgKiBAZGVwcmVjYXRlZCB0aGlzIHZhbHVlIGlzIGlnbm9yZWQgc2luY2UgaW5saW5lIGlzIG5vdyBkZXRlcm1pbmVkIGJhc2VkIG9uIHRoZVxuICAgKiB0aGUgYGlubGluZUNvZGVgIGZpZWxkIG9mIGBDb2RlQ29uZmlnYCByZXR1cm5lZCBmcm9tIGBiaW5kKClgLlxuICAgKi9cbiAgcHVibGljIGFic3RyYWN0IHJlYWRvbmx5IGlzSW5saW5lOiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBDYWxsZWQgd2hlbiB0aGUgbGFtYmRhIG9yIGxheWVyIGlzIGluaXRpYWxpemVkIHRvIGFsbG93IHRoaXMgb2JqZWN0IHRvIGJpbmRcbiAgICogdG8gdGhlIHN0YWNrLCBhZGQgcmVzb3VyY2VzIGFuZCBoYXZlIGZ1bi5cbiAgICpcbiAgICogQHBhcmFtIHNjb3BlIFRoZSBiaW5kaW5nIHNjb3BlLiBEb24ndCBiZSBzbWFydCBhYm91dCB0cnlpbmcgdG8gZG93bi1jYXN0IG9yXG4gICAqIGFzc3VtZSBpdCdzIGluaXRpYWxpemVkLiBZb3UgbWF5IGp1c3QgdXNlIGl0IGFzIGEgY29uc3RydWN0IHNjb3BlLlxuICAgKi9cbiAgcHVibGljIGFic3RyYWN0IGJpbmQoc2NvcGU6IENvbnN0cnVjdCk6IENvZGVDb25maWc7XG5cbiAgLyoqXG4gICAqIENhbGxlZCBhZnRlciB0aGUgQ0ZOIGZ1bmN0aW9uIHJlc291cmNlIGhhcyBiZWVuIGNyZWF0ZWQgdG8gYWxsb3cgdGhlIGNvZGVcbiAgICogY2xhc3MgdG8gYmluZCB0byBpdC4gU3BlY2lmaWNhbGx5IGl0J3MgcmVxdWlyZWQgdG8gYWxsb3cgYXNzZXRzIHRvIGFkZFxuICAgKiBtZXRhZGF0YSBmb3IgdG9vbGluZyBsaWtlIFNBTSBDTEkgdG8gYmUgYWJsZSB0byBmaW5kIHRoZWlyIG9yaWdpbnMuXG4gICAqL1xuICBwdWJsaWMgYmluZFRvUmVzb3VyY2UoX3Jlc291cmNlOiBjZGsuQ2ZuUmVzb3VyY2UsIF9vcHRpb25zPzogUmVzb3VyY2VCaW5kT3B0aW9ucykge1xuICAgIHJldHVybjtcbiAgfVxufVxuXG4vKipcbiAqIFJlc3VsdCBvZiBiaW5kaW5nIGBDb2RlYCBpbnRvIGEgYEZ1bmN0aW9uYC5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBDb2RlQ29uZmlnIHtcbiAgLyoqXG4gICAqIFRoZSBsb2NhdGlvbiBvZiB0aGUgY29kZSBpbiBTMyAobXV0dWFsbHkgZXhjbHVzaXZlIHdpdGggYGlubGluZUNvZGVgIGFuZCBgaW1hZ2VgKS5cbiAgICogQGRlZmF1bHQgLSBjb2RlIGlzIG5vdCBhbiBzMyBsb2NhdGlvblxuICAgKi9cbiAgcmVhZG9ubHkgczNMb2NhdGlvbj86IHMzLkxvY2F0aW9uO1xuXG4gIC8qKlxuICAgKiBJbmxpbmUgY29kZSAobXV0dWFsbHkgZXhjbHVzaXZlIHdpdGggYHMzTG9jYXRpb25gIGFuZCBgaW1hZ2VgKS5cbiAgICogQGRlZmF1bHQgLSBjb2RlIGlzIG5vdCBpbmxpbmUgY29kZVxuICAgKi9cbiAgcmVhZG9ubHkgaW5saW5lQ29kZT86IHN0cmluZztcblxuICAvKipcbiAgICogRG9ja2VyIGltYWdlIGNvbmZpZ3VyYXRpb24gKG11dHVhbGx5IGV4Y2x1c2l2ZSB3aXRoIGBzM0xvY2F0aW9uYCBhbmQgYGlubGluZUNvZGVgKS5cbiAgICogQGRlZmF1bHQgLSBjb2RlIGlzIG5vdCBhbiBFQ1IgY29udGFpbmVyIGltYWdlXG4gICAqL1xuICByZWFkb25seSBpbWFnZT86IENvZGVJbWFnZUNvbmZpZztcbn1cblxuLyoqXG4gKiBSZXN1bHQgb2YgdGhlIGJpbmQgd2hlbiBhbiBFQ1IgaW1hZ2UgaXMgdXNlZC5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBDb2RlSW1hZ2VDb25maWcge1xuICAvKipcbiAgICogVVJJIHRvIHRoZSBEb2NrZXIgaW1hZ2UuXG4gICAqL1xuICByZWFkb25seSBpbWFnZVVyaTogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBTcGVjaWZ5IG9yIG92ZXJyaWRlIHRoZSBDTUQgb24gdGhlIHNwZWNpZmllZCBEb2NrZXIgaW1hZ2Ugb3IgRG9ja2VyZmlsZS5cbiAgICogVGhpcyBuZWVkcyB0byBiZSBpbiB0aGUgJ2V4ZWMgZm9ybScsIHZpei4sIGBbICdleGVjdXRhYmxlJywgJ3BhcmFtMScsICdwYXJhbTInIF1gLlxuICAgKiBAc2VlIGh0dHBzOi8vZG9jcy5kb2NrZXIuY29tL2VuZ2luZS9yZWZlcmVuY2UvYnVpbGRlci8jY21kXG4gICAqIEBkZWZhdWx0IC0gdXNlIHRoZSBDTUQgc3BlY2lmaWVkIGluIHRoZSBkb2NrZXIgaW1hZ2Ugb3IgRG9ja2VyZmlsZS5cbiAgICovXG4gIHJlYWRvbmx5IGNtZD86IHN0cmluZ1tdO1xuXG4gIC8qKlxuICAgKiBTcGVjaWZ5IG9yIG92ZXJyaWRlIHRoZSBFTlRSWVBPSU5UIG9uIHRoZSBzcGVjaWZpZWQgRG9ja2VyIGltYWdlIG9yIERvY2tlcmZpbGUuXG4gICAqIEFuIEVOVFJZUE9JTlQgYWxsb3dzIHlvdSB0byBjb25maWd1cmUgYSBjb250YWluZXIgdGhhdCB3aWxsIHJ1biBhcyBhbiBleGVjdXRhYmxlLlxuICAgKiBUaGlzIG5lZWRzIHRvIGJlIGluIHRoZSAnZXhlYyBmb3JtJywgdml6LiwgYFsgJ2V4ZWN1dGFibGUnLCAncGFyYW0xJywgJ3BhcmFtMicgXWAuXG4gICAqIEBzZWUgaHR0cHM6Ly9kb2NzLmRvY2tlci5jb20vZW5naW5lL3JlZmVyZW5jZS9idWlsZGVyLyNlbnRyeXBvaW50XG4gICAqIEBkZWZhdWx0IC0gdXNlIHRoZSBFTlRSWVBPSU5UIGluIHRoZSBkb2NrZXIgaW1hZ2Ugb3IgRG9ja2VyZmlsZS5cbiAgICovXG4gIHJlYWRvbmx5IGVudHJ5cG9pbnQ/OiBzdHJpbmdbXTtcblxuICAvKipcbiAgICogU3BlY2lmeSBvciBvdmVycmlkZSB0aGUgV09SS0RJUiBvbiB0aGUgc3BlY2lmaWVkIERvY2tlciBpbWFnZSBvciBEb2NrZXJmaWxlLlxuICAgKiBBIFdPUktESVIgYWxsb3dzIHlvdSB0byBjb25maWd1cmUgdGhlIHdvcmtpbmcgZGlyZWN0b3J5IHRoZSBjb250YWluZXIgd2lsbCB1c2UuXG4gICAqIEBzZWUgaHR0cHM6Ly9kb2NzLmRvY2tlci5jb20vZW5naW5lL3JlZmVyZW5jZS9idWlsZGVyLyN3b3JrZGlyXG4gICAqIEBkZWZhdWx0IC0gdXNlIHRoZSBXT1JLRElSIGluIHRoZSBkb2NrZXIgaW1hZ2Ugb3IgRG9ja2VyZmlsZS5cbiAgICovXG4gIHJlYWRvbmx5IHdvcmtpbmdEaXJlY3Rvcnk/OiBzdHJpbmc7XG59XG5cbi8qKlxuICogTGFtYmRhIGNvZGUgZnJvbSBhbiBTMyBhcmNoaXZlLlxuICovXG5leHBvcnQgY2xhc3MgUzNDb2RlIGV4dGVuZHMgQ29kZSB7XG4gIHB1YmxpYyByZWFkb25seSBpc0lubGluZSA9IGZhbHNlO1xuICBwcml2YXRlIGJ1Y2tldE5hbWU6IHN0cmluZztcblxuICBjb25zdHJ1Y3RvcihidWNrZXQ6IHMzLklCdWNrZXQsIHByaXZhdGUga2V5OiBzdHJpbmcsIHByaXZhdGUgb2JqZWN0VmVyc2lvbj86IHN0cmluZykge1xuICAgIHN1cGVyKCk7XG5cbiAgICBpZiAoIWJ1Y2tldC5idWNrZXROYW1lKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ2J1Y2tldE5hbWUgaXMgdW5kZWZpbmVkIGZvciB0aGUgcHJvdmlkZWQgYnVja2V0Jyk7XG4gICAgfVxuXG4gICAgdGhpcy5idWNrZXROYW1lID0gYnVja2V0LmJ1Y2tldE5hbWU7XG4gIH1cblxuICBwdWJsaWMgYmluZChfc2NvcGU6IENvbnN0cnVjdCk6IENvZGVDb25maWcge1xuICAgIHJldHVybiB7XG4gICAgICBzM0xvY2F0aW9uOiB7XG4gICAgICAgIGJ1Y2tldE5hbWU6IHRoaXMuYnVja2V0TmFtZSxcbiAgICAgICAgb2JqZWN0S2V5OiB0aGlzLmtleSxcbiAgICAgICAgb2JqZWN0VmVyc2lvbjogdGhpcy5vYmplY3RWZXJzaW9uLFxuICAgICAgfSxcbiAgICB9O1xuICB9XG59XG5cbi8qKlxuICogTGFtYmRhIGNvZGUgZnJvbSBhbiBpbmxpbmUgc3RyaW5nIChsaW1pdGVkIHRvIDRLaUIpLlxuICovXG5leHBvcnQgY2xhc3MgSW5saW5lQ29kZSBleHRlbmRzIENvZGUge1xuICBwdWJsaWMgcmVhZG9ubHkgaXNJbmxpbmUgPSB0cnVlO1xuXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgY29kZTogc3RyaW5nKSB7XG4gICAgc3VwZXIoKTtcblxuICAgIGlmIChjb2RlLmxlbmd0aCA9PT0gMCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdMYW1iZGEgaW5saW5lIGNvZGUgY2Fubm90IGJlIGVtcHR5Jyk7XG4gICAgfVxuXG4gICAgaWYgKGNvZGUubGVuZ3RoID4gNDA5Nikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdMYW1iZGEgc291cmNlIGlzIHRvbyBsYXJnZSwgbXVzdCBiZSA8PSA0MDk2IGJ1dCBpcyAnICsgY29kZS5sZW5ndGgpO1xuICAgIH1cbiAgfVxuXG4gIHB1YmxpYyBiaW5kKF9zY29wZTogQ29uc3RydWN0KTogQ29kZUNvbmZpZyB7XG4gICAgcmV0dXJuIHtcbiAgICAgIGlubGluZUNvZGU6IHRoaXMuY29kZSxcbiAgICB9O1xuICB9XG59XG5cbi8qKlxuICogTGFtYmRhIGNvZGUgZnJvbSBhIGxvY2FsIGRpcmVjdG9yeS5cbiAqL1xuZXhwb3J0IGNsYXNzIEFzc2V0Q29kZSBleHRlbmRzIENvZGUge1xuICBwdWJsaWMgcmVhZG9ubHkgaXNJbmxpbmUgPSBmYWxzZTtcbiAgcHJpdmF0ZSBhc3NldD86IHMzX2Fzc2V0cy5Bc3NldDtcblxuICAvKipcbiAgICogQHBhcmFtIHBhdGggVGhlIHBhdGggdG8gdGhlIGFzc2V0IGZpbGUgb3IgZGlyZWN0b3J5LlxuICAgKi9cbiAgY29uc3RydWN0b3IocHVibGljIHJlYWRvbmx5IHBhdGg6IHN0cmluZywgcHJpdmF0ZSByZWFkb25seSBvcHRpb25zOiBzM19hc3NldHMuQXNzZXRPcHRpb25zID0geyB9KSB7XG4gICAgc3VwZXIoKTtcbiAgfVxuXG4gIHB1YmxpYyBiaW5kKHNjb3BlOiBDb25zdHJ1Y3QpOiBDb2RlQ29uZmlnIHtcbiAgICAvLyBJZiB0aGUgc2FtZSBBc3NldENvZGUgaXMgdXNlZCBtdWx0aXBsZSB0aW1lcywgcmV0YWluIG9ubHkgdGhlIGZpcnN0IGluc3RhbnRpYXRpb24uXG4gICAgaWYgKCF0aGlzLmFzc2V0KSB7XG4gICAgICB0aGlzLmFzc2V0ID0gbmV3IHMzX2Fzc2V0cy5Bc3NldChzY29wZSwgJ0NvZGUnLCB7XG4gICAgICAgIHBhdGg6IHRoaXMucGF0aCxcbiAgICAgICAgLi4udGhpcy5vcHRpb25zLFxuICAgICAgfSk7XG4gICAgfSBlbHNlIGlmIChjZGsuU3RhY2sub2YodGhpcy5hc3NldCkgIT09IGNkay5TdGFjay5vZihzY29wZSkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgQXNzZXQgaXMgYWxyZWFkeSBhc3NvY2lhdGVkIHdpdGggYW5vdGhlciBzdGFjayAnJHtjZGsuU3RhY2sub2YodGhpcy5hc3NldCkuc3RhY2tOYW1lfScuIGAgK1xuICAgICAgICAnQ3JlYXRlIGEgbmV3IENvZGUgaW5zdGFuY2UgZm9yIGV2ZXJ5IHN0YWNrLicpO1xuICAgIH1cblxuICAgIGlmICghdGhpcy5hc3NldC5pc1ppcEFyY2hpdmUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgQXNzZXQgbXVzdCBiZSBhIC56aXAgZmlsZSBvciBhIGRpcmVjdG9yeSAoJHt0aGlzLnBhdGh9KWApO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBzM0xvY2F0aW9uOiB7XG4gICAgICAgIGJ1Y2tldE5hbWU6IHRoaXMuYXNzZXQuczNCdWNrZXROYW1lLFxuICAgICAgICBvYmplY3RLZXk6IHRoaXMuYXNzZXQuczNPYmplY3RLZXksXG4gICAgICB9LFxuICAgIH07XG4gIH1cblxuICBwdWJsaWMgYmluZFRvUmVzb3VyY2UocmVzb3VyY2U6IGNkay5DZm5SZXNvdXJjZSwgb3B0aW9uczogUmVzb3VyY2VCaW5kT3B0aW9ucyA9IHsgfSkge1xuICAgIGlmICghdGhpcy5hc3NldCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdiaW5kVG9SZXNvdXJjZSgpIG11c3QgYmUgY2FsbGVkIGFmdGVyIGJpbmQoKScpO1xuICAgIH1cblxuICAgIGNvbnN0IHJlc291cmNlUHJvcGVydHkgPSBvcHRpb25zLnJlc291cmNlUHJvcGVydHkgfHwgJ0NvZGUnO1xuXG4gICAgLy8gaHR0cHM6Ly9naXRodWIuY29tL2F3cy9hd3MtY2RrL2lzc3Vlcy8xNDMyXG4gICAgdGhpcy5hc3NldC5hZGRSZXNvdXJjZU1ldGFkYXRhKHJlc291cmNlLCByZXNvdXJjZVByb3BlcnR5KTtcbiAgfVxufVxuXG5leHBvcnQgaW50ZXJmYWNlIFJlc291cmNlQmluZE9wdGlvbnMge1xuICAvKipcbiAgICogVGhlIG5hbWUgb2YgdGhlIENsb3VkRm9ybWF0aW9uIHByb3BlcnR5IHRvIGFubm90YXRlIHdpdGggYXNzZXQgbWV0YWRhdGEuXG4gICAqIEBzZWUgaHR0cHM6Ly9naXRodWIuY29tL2F3cy9hd3MtY2RrL2lzc3Vlcy8xNDMyXG4gICAqIEBkZWZhdWx0IENvZGVcbiAgICovXG4gIHJlYWRvbmx5IHJlc291cmNlUHJvcGVydHk/OiBzdHJpbmc7XG59XG5cbi8qKlxuICogQ29uc3RydWN0aW9uIHByb3BlcnRpZXMgZm9yIHtAbGluayBDZm5QYXJhbWV0ZXJzQ29kZX0uXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQ2ZuUGFyYW1ldGVyc0NvZGVQcm9wcyB7XG4gIC8qKlxuICAgKiBUaGUgQ2xvdWRGb3JtYXRpb24gcGFyYW1ldGVyIHRoYXQgcmVwcmVzZW50cyB0aGUgbmFtZSBvZiB0aGUgUzMgQnVja2V0XG4gICAqIHdoZXJlIHRoZSBMYW1iZGEgY29kZSB3aWxsIGJlIGxvY2F0ZWQgaW4uXG4gICAqIE11c3QgYmUgb2YgdHlwZSAnU3RyaW5nJy5cbiAgICpcbiAgICogQGRlZmF1bHQgYSBuZXcgcGFyYW1ldGVyIHdpbGwgYmUgY3JlYXRlZFxuICAgKi9cbiAgcmVhZG9ubHkgYnVja2V0TmFtZVBhcmFtPzogY2RrLkNmblBhcmFtZXRlcjtcblxuICAvKipcbiAgICogVGhlIENsb3VkRm9ybWF0aW9uIHBhcmFtZXRlciB0aGF0IHJlcHJlc2VudHMgdGhlIHBhdGggaW5zaWRlIHRoZSBTMyBCdWNrZXRcbiAgICogd2hlcmUgdGhlIExhbWJkYSBjb2RlIHdpbGwgYmUgbG9jYXRlZCBhdC5cbiAgICogTXVzdCBiZSBvZiB0eXBlICdTdHJpbmcnLlxuICAgKlxuICAgKiBAZGVmYXVsdCBhIG5ldyBwYXJhbWV0ZXIgd2lsbCBiZSBjcmVhdGVkXG4gICAqL1xuICByZWFkb25seSBvYmplY3RLZXlQYXJhbT86IGNkay5DZm5QYXJhbWV0ZXI7XG59XG5cbi8qKlxuICogTGFtYmRhIGNvZGUgZGVmaW5lZCB1c2luZyAyIENsb3VkRm9ybWF0aW9uIHBhcmFtZXRlcnMuXG4gKiBVc2VmdWwgd2hlbiB5b3UgZG9uJ3QgaGF2ZSBhY2Nlc3MgdG8gdGhlIGNvZGUgb2YgeW91ciBMYW1iZGEgZnJvbSB5b3VyIENESyBjb2RlLCBzbyB5b3UgY2FuJ3QgdXNlIEFzc2V0cyxcbiAqIGFuZCB5b3Ugd2FudCB0byBkZXBsb3kgdGhlIExhbWJkYSBpbiBhIENvZGVQaXBlbGluZSwgdXNpbmcgQ2xvdWRGb3JtYXRpb24gQWN0aW9ucyAtXG4gKiB5b3UgY2FuIGZpbGwgdGhlIHBhcmFtZXRlcnMgdXNpbmcgdGhlIHtAbGluayAjYXNzaWdufSBtZXRob2QuXG4gKi9cbmV4cG9ydCBjbGFzcyBDZm5QYXJhbWV0ZXJzQ29kZSBleHRlbmRzIENvZGUge1xuICBwdWJsaWMgcmVhZG9ubHkgaXNJbmxpbmUgPSBmYWxzZTtcbiAgcHJpdmF0ZSBfYnVja2V0TmFtZVBhcmFtPzogY2RrLkNmblBhcmFtZXRlcjtcbiAgcHJpdmF0ZSBfb2JqZWN0S2V5UGFyYW0/OiBjZGsuQ2ZuUGFyYW1ldGVyO1xuXG4gIGNvbnN0cnVjdG9yKHByb3BzOiBDZm5QYXJhbWV0ZXJzQ29kZVByb3BzID0ge30pIHtcbiAgICBzdXBlcigpO1xuXG4gICAgdGhpcy5fYnVja2V0TmFtZVBhcmFtID0gcHJvcHMuYnVja2V0TmFtZVBhcmFtO1xuICAgIHRoaXMuX29iamVjdEtleVBhcmFtID0gcHJvcHMub2JqZWN0S2V5UGFyYW07XG4gIH1cblxuICBwdWJsaWMgYmluZChzY29wZTogQ29uc3RydWN0KTogQ29kZUNvbmZpZyB7XG4gICAgaWYgKCF0aGlzLl9idWNrZXROYW1lUGFyYW0pIHtcbiAgICAgIHRoaXMuX2J1Y2tldE5hbWVQYXJhbSA9IG5ldyBjZGsuQ2ZuUGFyYW1ldGVyKHNjb3BlLCAnTGFtYmRhU291cmNlQnVja2V0TmFtZVBhcmFtZXRlcicsIHtcbiAgICAgICAgdHlwZTogJ1N0cmluZycsXG4gICAgICB9KTtcbiAgICB9XG5cbiAgICBpZiAoIXRoaXMuX29iamVjdEtleVBhcmFtKSB7XG4gICAgICB0aGlzLl9vYmplY3RLZXlQYXJhbSA9IG5ldyBjZGsuQ2ZuUGFyYW1ldGVyKHNjb3BlLCAnTGFtYmRhU291cmNlT2JqZWN0S2V5UGFyYW1ldGVyJywge1xuICAgICAgICB0eXBlOiAnU3RyaW5nJyxcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBzM0xvY2F0aW9uOiB7XG4gICAgICAgIGJ1Y2tldE5hbWU6IHRoaXMuX2J1Y2tldE5hbWVQYXJhbS52YWx1ZUFzU3RyaW5nLFxuICAgICAgICBvYmplY3RLZXk6IHRoaXMuX29iamVjdEtleVBhcmFtLnZhbHVlQXNTdHJpbmcsXG4gICAgICB9LFxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlIGEgcGFyYW1ldGVycyBtYXAgZnJvbSB0aGlzIGluc3RhbmNlJ3MgQ2xvdWRGb3JtYXRpb24gcGFyYW1ldGVycy5cbiAgICpcbiAgICogSXQgcmV0dXJucyBhIG1hcCB3aXRoIDIga2V5cyB0aGF0IGNvcnJlc3BvbmQgdG8gdGhlIG5hbWVzIG9mIHRoZSBwYXJhbWV0ZXJzIGRlZmluZWQgaW4gdGhpcyBMYW1iZGEgY29kZSxcbiAgICogYW5kIGFzIHZhbHVlcyBpdCBjb250YWlucyB0aGUgYXBwcm9wcmlhdGUgZXhwcmVzc2lvbnMgcG9pbnRpbmcgYXQgdGhlIHByb3ZpZGVkIFMzIGxvY2F0aW9uXG4gICAqIChtb3N0IGxpa2VseSwgb2J0YWluZWQgZnJvbSBhIENvZGVQaXBlbGluZSBBcnRpZmFjdCBieSBjYWxsaW5nIHRoZSBgYXJ0aWZhY3QuczNMb2NhdGlvbmAgbWV0aG9kKS5cbiAgICogVGhlIHJlc3VsdCBzaG91bGQgYmUgcHJvdmlkZWQgdG8gdGhlIENsb3VkRm9ybWF0aW9uIEFjdGlvblxuICAgKiB0aGF0IGlzIGRlcGxveWluZyB0aGUgU3RhY2sgdGhhdCB0aGUgTGFtYmRhIHdpdGggdGhpcyBjb2RlIGlzIHBhcnQgb2YsXG4gICAqIGluIHRoZSBgcGFyYW1ldGVyT3ZlcnJpZGVzYCBwcm9wZXJ0eS5cbiAgICpcbiAgICogQHBhcmFtIGxvY2F0aW9uIHRoZSBsb2NhdGlvbiBvZiB0aGUgb2JqZWN0IGluIFMzIHRoYXQgcmVwcmVzZW50cyB0aGUgTGFtYmRhIGNvZGVcbiAgICovXG4gIHB1YmxpYyBhc3NpZ24obG9jYXRpb246IHMzLkxvY2F0aW9uKTogeyBbbmFtZTogc3RyaW5nXTogYW55IH0ge1xuICAgIGNvbnN0IHJldDogeyBbbmFtZTogc3RyaW5nXTogYW55IH0gPSB7fTtcbiAgICByZXRbdGhpcy5idWNrZXROYW1lUGFyYW1dID0gbG9jYXRpb24uYnVja2V0TmFtZTtcbiAgICByZXRbdGhpcy5vYmplY3RLZXlQYXJhbV0gPSBsb2NhdGlvbi5vYmplY3RLZXk7XG4gICAgcmV0dXJuIHJldDtcbiAgfVxuXG4gIHB1YmxpYyBnZXQgYnVja2V0TmFtZVBhcmFtKCk6IHN0cmluZyB7XG4gICAgaWYgKHRoaXMuX2J1Y2tldE5hbWVQYXJhbSkge1xuICAgICAgcmV0dXJuIHRoaXMuX2J1Y2tldE5hbWVQYXJhbS5sb2dpY2FsSWQ7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignUGFzcyBDZm5QYXJhbWV0ZXJzQ29kZSB0byBhIExhbWJkYSBGdW5jdGlvbiBiZWZvcmUgYWNjZXNzaW5nIHRoZSBidWNrZXROYW1lUGFyYW0gcHJvcGVydHknKTtcbiAgICB9XG4gIH1cblxuICBwdWJsaWMgZ2V0IG9iamVjdEtleVBhcmFtKCk6IHN0cmluZyB7XG4gICAgaWYgKHRoaXMuX29iamVjdEtleVBhcmFtKSB7XG4gICAgICByZXR1cm4gdGhpcy5fb2JqZWN0S2V5UGFyYW0ubG9naWNhbElkO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1Bhc3MgQ2ZuUGFyYW1ldGVyc0NvZGUgdG8gYSBMYW1iZGEgRnVuY3Rpb24gYmVmb3JlIGFjY2Vzc2luZyB0aGUgb2JqZWN0S2V5UGFyYW0gcHJvcGVydHknKTtcbiAgICB9XG4gIH1cbn1cblxuLyoqXG4gKiBQcm9wZXJ0aWVzIHRvIGluaXRpYWxpemUgYSBuZXcgRWNySW1hZ2VDb2RlXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgRWNySW1hZ2VDb2RlUHJvcHMge1xuICAvKipcbiAgICogU3BlY2lmeSBvciBvdmVycmlkZSB0aGUgQ01EIG9uIHRoZSBzcGVjaWZpZWQgRG9ja2VyIGltYWdlIG9yIERvY2tlcmZpbGUuXG4gICAqIFRoaXMgbmVlZHMgdG8gYmUgaW4gdGhlICdleGVjIGZvcm0nLCB2aXouLCBgWyAnZXhlY3V0YWJsZScsICdwYXJhbTEnLCAncGFyYW0yJyBdYC5cbiAgICogQHNlZSBodHRwczovL2RvY3MuZG9ja2VyLmNvbS9lbmdpbmUvcmVmZXJlbmNlL2J1aWxkZXIvI2NtZFxuICAgKiBAZGVmYXVsdCAtIHVzZSB0aGUgQ01EIHNwZWNpZmllZCBpbiB0aGUgZG9ja2VyIGltYWdlIG9yIERvY2tlcmZpbGUuXG4gICAqL1xuICByZWFkb25seSBjbWQ/OiBzdHJpbmdbXTtcblxuICAvKipcbiAgICogU3BlY2lmeSBvciBvdmVycmlkZSB0aGUgRU5UUllQT0lOVCBvbiB0aGUgc3BlY2lmaWVkIERvY2tlciBpbWFnZSBvciBEb2NrZXJmaWxlLlxuICAgKiBBbiBFTlRSWVBPSU5UIGFsbG93cyB5b3UgdG8gY29uZmlndXJlIGEgY29udGFpbmVyIHRoYXQgd2lsbCBydW4gYXMgYW4gZXhlY3V0YWJsZS5cbiAgICogVGhpcyBuZWVkcyB0byBiZSBpbiB0aGUgJ2V4ZWMgZm9ybScsIHZpei4sIGBbICdleGVjdXRhYmxlJywgJ3BhcmFtMScsICdwYXJhbTInIF1gLlxuICAgKiBAc2VlIGh0dHBzOi8vZG9jcy5kb2NrZXIuY29tL2VuZ2luZS9yZWZlcmVuY2UvYnVpbGRlci8jZW50cnlwb2ludFxuICAgKiBAZGVmYXVsdCAtIHVzZSB0aGUgRU5UUllQT0lOVCBpbiB0aGUgZG9ja2VyIGltYWdlIG9yIERvY2tlcmZpbGUuXG4gICAqL1xuICByZWFkb25seSBlbnRyeXBvaW50Pzogc3RyaW5nW107XG5cbiAgLyoqXG4gICAqIFNwZWNpZnkgb3Igb3ZlcnJpZGUgdGhlIFdPUktESVIgb24gdGhlIHNwZWNpZmllZCBEb2NrZXIgaW1hZ2Ugb3IgRG9ja2VyZmlsZS5cbiAgICogQSBXT1JLRElSIGFsbG93cyB5b3UgdG8gY29uZmlndXJlIHRoZSB3b3JraW5nIGRpcmVjdG9yeSB0aGUgY29udGFpbmVyIHdpbGwgdXNlLlxuICAgKiBAc2VlIGh0dHBzOi8vZG9jcy5kb2NrZXIuY29tL2VuZ2luZS9yZWZlcmVuY2UvYnVpbGRlci8jd29ya2RpclxuICAgKiBAZGVmYXVsdCAtIHVzZSB0aGUgV09SS0RJUiBpbiB0aGUgZG9ja2VyIGltYWdlIG9yIERvY2tlcmZpbGUuXG4gICAqL1xuICByZWFkb25seSB3b3JraW5nRGlyZWN0b3J5Pzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBUaGUgaW1hZ2UgdGFnIHRvIHVzZSB3aGVuIHB1bGxpbmcgdGhlIGltYWdlIGZyb20gRUNSLlxuICAgKiBAZGVmYXVsdCAnbGF0ZXN0J1xuICAgKiBAZGVwcmVjYXRlZCB1c2UgYHRhZ09yRGlnZXN0YFxuICAgKi9cbiAgcmVhZG9ubHkgdGFnPzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBUaGUgaW1hZ2UgdGFnIG9yIGRpZ2VzdCB0byB1c2Ugd2hlbiBwdWxsaW5nIHRoZSBpbWFnZSBmcm9tIEVDUiAoZGlnZXN0cyBtdXN0IHN0YXJ0IHdpdGggYHNoYTI1NjpgKS5cbiAgICogQGRlZmF1bHQgJ2xhdGVzdCdcbiAgICovXG4gIHJlYWRvbmx5IHRhZ09yRGlnZXN0Pzogc3RyaW5nO1xufVxuXG4vKipcbiAqIFJlcHJlc2VudHMgYSBEb2NrZXIgaW1hZ2UgaW4gRUNSIHRoYXQgY2FuIGJlIGJvdW5kIGFzIExhbWJkYSBDb2RlLlxuICovXG5leHBvcnQgY2xhc3MgRWNySW1hZ2VDb2RlIGV4dGVuZHMgQ29kZSB7XG4gIHB1YmxpYyByZWFkb25seSBpc0lubGluZTogYm9vbGVhbiA9IGZhbHNlO1xuXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgcmVhZG9ubHkgcmVwb3NpdG9yeTogZWNyLklSZXBvc2l0b3J5LCBwcml2YXRlIHJlYWRvbmx5IHByb3BzOiBFY3JJbWFnZUNvZGVQcm9wcyA9IHt9KSB7XG4gICAgc3VwZXIoKTtcbiAgfVxuXG4gIHB1YmxpYyBiaW5kKF86IENvbnN0cnVjdCk6IENvZGVDb25maWcge1xuICAgIHRoaXMucmVwb3NpdG9yeS5ncmFudFB1bGwobmV3IGlhbS5TZXJ2aWNlUHJpbmNpcGFsKCdsYW1iZGEuYW1hem9uYXdzLmNvbScpKTtcblxuICAgIHJldHVybiB7XG4gICAgICBpbWFnZToge1xuICAgICAgICBpbWFnZVVyaTogdGhpcy5yZXBvc2l0b3J5LnJlcG9zaXRvcnlVcmlGb3JUYWdPckRpZ2VzdCh0aGlzLnByb3BzPy50YWdPckRpZ2VzdCA/PyB0aGlzLnByb3BzPy50YWcgPz8gJ2xhdGVzdCcpLFxuICAgICAgICBjbWQ6IHRoaXMucHJvcHMuY21kLFxuICAgICAgICBlbnRyeXBvaW50OiB0aGlzLnByb3BzLmVudHJ5cG9pbnQsXG4gICAgICAgIHdvcmtpbmdEaXJlY3Rvcnk6IHRoaXMucHJvcHMud29ya2luZ0RpcmVjdG9yeSxcbiAgICAgIH0sXG4gICAgfTtcbiAgfVxufVxuXG4vKipcbiAqIFByb3BlcnRpZXMgdG8gaW5pdGlhbGl6ZSBhIG5ldyBBc3NldEltYWdlXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQXNzZXRJbWFnZUNvZGVQcm9wcyBleHRlbmRzIGVjcl9hc3NldHMuRG9ja2VySW1hZ2VBc3NldE9wdGlvbnMge1xuICAvKipcbiAgICogU3BlY2lmeSBvciBvdmVycmlkZSB0aGUgQ01EIG9uIHRoZSBzcGVjaWZpZWQgRG9ja2VyIGltYWdlIG9yIERvY2tlcmZpbGUuXG4gICAqIFRoaXMgbmVlZHMgdG8gYmUgaW4gdGhlICdleGVjIGZvcm0nLCB2aXouLCBgWyAnZXhlY3V0YWJsZScsICdwYXJhbTEnLCAncGFyYW0yJyBdYC5cbiAgICogQHNlZSBodHRwczovL2RvY3MuZG9ja2VyLmNvbS9lbmdpbmUvcmVmZXJlbmNlL2J1aWxkZXIvI2NtZFxuICAgKiBAZGVmYXVsdCAtIHVzZSB0aGUgQ01EIHNwZWNpZmllZCBpbiB0aGUgZG9ja2VyIGltYWdlIG9yIERvY2tlcmZpbGUuXG4gICAqL1xuICByZWFkb25seSBjbWQ/OiBzdHJpbmdbXTtcblxuICAvKipcbiAgICogU3BlY2lmeSBvciBvdmVycmlkZSB0aGUgRU5UUllQT0lOVCBvbiB0aGUgc3BlY2lmaWVkIERvY2tlciBpbWFnZSBvciBEb2NrZXJmaWxlLlxuICAgKiBBbiBFTlRSWVBPSU5UIGFsbG93cyB5b3UgdG8gY29uZmlndXJlIGEgY29udGFpbmVyIHRoYXQgd2lsbCBydW4gYXMgYW4gZXhlY3V0YWJsZS5cbiAgICogVGhpcyBuZWVkcyB0byBiZSBpbiB0aGUgJ2V4ZWMgZm9ybScsIHZpei4sIGBbICdleGVjdXRhYmxlJywgJ3BhcmFtMScsICdwYXJhbTInIF1gLlxuICAgKiBAc2VlIGh0dHBzOi8vZG9jcy5kb2NrZXIuY29tL2VuZ2luZS9yZWZlcmVuY2UvYnVpbGRlci8jZW50cnlwb2ludFxuICAgKiBAZGVmYXVsdCAtIHVzZSB0aGUgRU5UUllQT0lOVCBpbiB0aGUgZG9ja2VyIGltYWdlIG9yIERvY2tlcmZpbGUuXG4gICAqL1xuICByZWFkb25seSBlbnRyeXBvaW50Pzogc3RyaW5nW107XG5cbiAgLyoqXG4gICAqIFNwZWNpZnkgb3Igb3ZlcnJpZGUgdGhlIFdPUktESVIgb24gdGhlIHNwZWNpZmllZCBEb2NrZXIgaW1hZ2Ugb3IgRG9ja2VyZmlsZS5cbiAgICogQSBXT1JLRElSIGFsbG93cyB5b3UgdG8gY29uZmlndXJlIHRoZSB3b3JraW5nIGRpcmVjdG9yeSB0aGUgY29udGFpbmVyIHdpbGwgdXNlLlxuICAgKiBAc2VlIGh0dHBzOi8vZG9jcy5kb2NrZXIuY29tL2VuZ2luZS9yZWZlcmVuY2UvYnVpbGRlci8jd29ya2RpclxuICAgKiBAZGVmYXVsdCAtIHVzZSB0aGUgV09SS0RJUiBpbiB0aGUgZG9ja2VyIGltY