projen
Version:
CDK for software projects
283 lines • 41 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.LambdaRuntime = exports.LambdaFunction = void 0;
const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
const path = __importStar(require("path"));
const case_1 = require("case");
const internal_1 = require("./internal");
const component_1 = require("../component");
const javascript_1 = require("../javascript");
const source_code_1 = require("../source-code");
const util_1 = require("../util");
/**
* Generates a pre-bundled AWS Lambda function construct from handler code.
*
* To use this, create an AWS Lambda handler file under your source tree with
* the `.lambda.ts` extension and add a `LambdaFunction` component to your
* typescript project pointing to this entrypoint.
*
* This will add a task to your "compile" step which will use `esbuild` to
* bundle the handler code into the build directory. It will also generate a
* file `src/foo-function.ts` with a custom AWS construct called `FooFunction`
* which extends `@aws-cdk/aws-lambda.Function` which is bound to the bundled
* handle through an asset.
*
* @example
*
* new LambdaFunction(myProject, {
* srcdir: myProject.srcdir,
* entrypoint: 'src/foo.lambda.ts',
* });
*/
class LambdaFunction extends component_1.Component {
static [JSII_RTTI_SYMBOL_1] = { fqn: "projen.awscdk.LambdaFunction", version: "0.103.12" };
/**
* Defines a pre-bundled AWS Lambda function construct from handler code.
*
* @param project The project to use
* @param options Options
*/
constructor(project, options) {
super(project);
const bundler = javascript_1.Bundler.of(project);
if (!bundler) {
throw new Error("No bundler found. Please add a Bundler component to your project.");
}
// Use NODEJS_REGIONAL_LATEST as default, which generates determineLatestNodeRuntime()
const runtime = options.runtime ?? LambdaRuntime.NODEJS_REGIONAL_LATEST;
const entrypoint = (0, util_1.normalizePersistedPath)(options.entrypoint);
// allow Lambda handler code to import dev-deps since they are only needed
// during bundling
const eslint = javascript_1.Eslint.of(project);
eslint?.allowDevDeps(entrypoint);
if (!entrypoint.endsWith(internal_1.TYPESCRIPT_LAMBDA_EXT) &&
!entrypoint.endsWith(internal_1.TYPESCRIPT_EDGE_LAMBDA_EXT) &&
!entrypoint.endsWith(internal_1.TYPESCRIPT_SINGLETON_LAMBDA_EXT)) {
throw new Error(`${entrypoint} must have a ${internal_1.TYPESCRIPT_LAMBDA_EXT}, ${internal_1.TYPESCRIPT_EDGE_LAMBDA_EXT}, or ${internal_1.TYPESCRIPT_SINGLETON_LAMBDA_EXT} extension`);
}
if (options.edgeLambda && options.singleton) {
throw new Error("singleton cannot be used with edgeLambda");
}
if (options.singletonUuid && !options.singleton) {
throw new Error("singletonUuid can only be used with singleton");
}
const sourceExtension = entrypoint.endsWith(internal_1.TYPESCRIPT_EDGE_LAMBDA_EXT)
? internal_1.TYPESCRIPT_EDGE_LAMBDA_EXT
: entrypoint.endsWith(internal_1.TYPESCRIPT_SINGLETON_LAMBDA_EXT)
? internal_1.TYPESCRIPT_SINGLETON_LAMBDA_EXT
: internal_1.TYPESCRIPT_LAMBDA_EXT;
const basePath = path.posix.join(path.dirname(entrypoint), path.basename(entrypoint, sourceExtension));
const constructFile = options.constructFile ?? `${basePath}-function.ts`;
if (path.extname(constructFile) !== ".ts") {
throw new Error(`Construct file name "${constructFile}" must have a .ts extension`);
}
// type names
const constructName = options.constructName ?? (0, case_1.pascal)(path.basename(basePath)) + "Function";
const propsType = `${constructName}Props`;
const bundle = bundler.addBundle(entrypoint, {
target: runtime.esbuildTarget,
platform: runtime.esbuildPlatform,
externals: runtime.defaultExternals,
...options.bundlingOptions,
tsconfigPath: project?.tsconfigDev?.fileName,
});
// calculate the relative path between the directory containing the
// generated construct source file to the directory containing the bundle
// index.js by resolving them as absolute paths first.
// e.g:
// - outfileAbs => `/project-outdir/assets/foo/bar/baz/foo-function/index.js`
// - constructAbs => `/project-outdir/src/foo/bar/baz/foo-function.ts`
const outfileAbs = path.join(project.outdir, bundle.outfile);
const constructAbs = path.join(project.outdir, constructFile);
const relativeOutfile = path.relative(path.dirname(constructAbs), path.dirname(outfileAbs));
const src = new source_code_1.SourceCode(project, constructFile);
if (src.marker) {
src.line(`// ${src.marker}`);
}
src.line("import * as path from 'path';");
if (options.edgeLambda) {
src.line("import * as cloudfront from 'aws-cdk-lib/aws-cloudfront';");
}
src.line("import * as lambda from 'aws-cdk-lib/aws-lambda';");
// Import determineLatestNodeRuntime if using NODEJS_REGIONAL_LATEST
if (runtime === LambdaRuntime.NODEJS_REGIONAL_LATEST) {
src.line("import { determineLatestNodeRuntime } from 'aws-cdk-lib/aws-lambda';");
}
src.line("import { Construct } from 'constructs';");
src.line();
src.line("/**");
src.line(` * Props for ${constructName}`);
src.line(" */");
if (options.edgeLambda) {
src.open(`export interface ${propsType} extends cloudfront.experimental.EdgeFunctionProps {`);
}
else if (options.singleton) {
src.open(`export interface ${propsType} extends lambda.SingletonFunctionProps {`);
}
else {
src.open(`export interface ${propsType} extends lambda.FunctionOptions {`);
}
// Add runtime prop to interface only when runtime is not explicitly set
// This allows consumers to override the default NODEJS_REGIONAL_LATEST
if (!options.runtime) {
src.line("/**");
src.line(" * The Lambda runtime to use.");
src.line(" * @default - Latest Node.js runtime available in the deployment region");
src.line(" */");
src.line("readonly runtime?: lambda.Runtime;");
}
src.close("}");
src.line();
src.line("/**");
src.line(` * An AWS Lambda function which executes ${(0, internal_1.convertToPosixPath)(basePath)}.`);
src.line(" */");
if (options.edgeLambda) {
src.open(`export class ${constructName} extends cloudfront.experimental.EdgeFunction {`);
}
else if (options.singleton) {
src.open(`export class ${constructName} extends lambda.SingletonFunction {`);
}
else {
src.open(`export class ${constructName} extends lambda.Function {`);
}
src.open(`constructor(scope: Construct, id: string, props?: ${propsType}) {`);
src.open("super(scope, id, {");
src.line(`description: '${(0, internal_1.convertToPosixPath)(entrypoint)}',`);
src.line("...props,");
if (options.singleton && options.singletonUuid) {
src.line(`uuid: ${JSON.stringify(options.singletonUuid)},`);
}
// Generate runtime code
if (runtime === LambdaRuntime.NODEJS_REGIONAL_LATEST) {
// Regional latest runtime
if (!options.runtime) {
// Default (not explicitly set) - allow consumer override
src.line("runtime: props?.runtime ?? determineLatestNodeRuntime(scope),");
}
else {
// Explicitly set - no override
src.line("runtime: determineLatestNodeRuntime(scope),");
}
}
else {
// Explicit runtime - hardcoded, no override
src.line(`runtime: new lambda.Runtime('${runtime.functionRuntime}', lambda.RuntimeFamily.NODEJS),`);
}
src.line("handler: 'index.handler',");
src.line(`code: lambda.Code.fromAsset(path.join(__dirname, '${(0, internal_1.convertToPosixPath)(relativeOutfile)}')),`);
src.close("});");
if ((options.awsSdkConnectionReuse ?? true) && !options.edgeLambda) {
src.line("this.addEnvironment('AWS_NODEJS_CONNECTION_REUSE_ENABLED', '1', { removeInEdge: true });");
}
src.close("}");
src.close("}");
this.project.logger.verbose(`${basePath}: construct "${constructName}" generated under "${constructFile}"`);
this.project.logger.verbose(`${basePath}: bundle task "${bundle.bundleTask.name}"`);
if (bundle.watchTask) {
this.project.logger.verbose(`${basePath}: bundle watch task "${bundle.watchTask.name}"`);
}
}
}
exports.LambdaFunction = LambdaFunction;
/**
* The runtime for the AWS Lambda function.
*/
class LambdaRuntime {
functionRuntime;
esbuildTarget;
static [JSII_RTTI_SYMBOL_1] = { fqn: "projen.awscdk.LambdaRuntime", version: "0.103.12" };
/**
* Node.js 14.x
* @deprecated Node.js 14 runtime has been deprecated on Dec 4, 2023
*/
static NODEJS_14_X = new LambdaRuntime("nodejs14.x", "node14", { defaultExternals: ["aws-sdk"] });
/**
* Node.js 16.x
* @deprecated Node.js 16 runtime has been deprecated on Jun 12, 2024
*/
static NODEJS_16_X = new LambdaRuntime("nodejs16.x", "node16", { defaultExternals: ["aws-sdk"] });
/**
* Node.js 18.x
*
* @deprecated: Node.js 18 runtime has been deprecated on Sep 1, 2025
*/
static NODEJS_18_X = new LambdaRuntime("nodejs18.x", "node18");
/**
* Node.js 20.x
*/
static NODEJS_20_X = new LambdaRuntime("nodejs20.x", "node20");
/**
* Node.js 22.x
*/
static NODEJS_22_X = new LambdaRuntime("nodejs22.x", "node22");
/**
* Node.js 24.x
*/
static NODEJS_24_X = new LambdaRuntime("nodejs24.x", "node24");
/**
* Use the latest Node.js runtime available in the deployment region.
*
* This generates code that uses `determineLatestNodeRuntime()` at CDK synthesis time,
* which dynamically selects the latest Node.js runtime available based on regional
* availability. This eliminates the need to manually update runtime versions and
* avoids EOL warnings.
*
* @default Uses determineLatestNodeRuntime() from aws-cdk-lib
*/
static NODEJS_REGIONAL_LATEST = new LambdaRuntime("NODEJS_REGIONAL_LATEST", // Marker value
"node22");
esbuildPlatform = "node";
defaultExternals;
constructor(
/**
* The Node.js runtime to use
*/
functionRuntime,
/**
* The esbuild setting to use.
*/
esbuildTarget,
/**
* Options for this runtime.
*/
options) {
this.functionRuntime = functionRuntime;
this.esbuildTarget = esbuildTarget;
this.defaultExternals = options?.defaultExternals ?? ["@aws-sdk/*"];
}
}
exports.LambdaRuntime = LambdaRuntime;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGFtYmRhLWZ1bmN0aW9uLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2F3c2Nkay9sYW1iZGEtZnVuY3Rpb24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBLDJDQUE2QjtBQUM3QiwrQkFBOEI7QUFFOUIseUNBS29CO0FBQ3BCLDRDQUF5QztBQUV6Qyw4Q0FBZ0Q7QUFFaEQsZ0RBQTRDO0FBRTVDLGtDQUFpRDtBQTRHakQ7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FtQkc7QUFDSCxNQUFhLGNBQWUsU0FBUSxxQkFBUzs7SUFDM0M7Ozs7O09BS0c7SUFDSCxZQUFZLE9BQWdCLEVBQUUsT0FBOEI7UUFDMUQsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBRWYsTUFBTSxPQUFPLEdBQUcsb0JBQU8sQ0FBQyxFQUFFLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDcEMsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDO1lBQ2IsTUFBTSxJQUFJLEtBQUssQ0FDYixtRUFBbUUsQ0FDcEUsQ0FBQztRQUNKLENBQUM7UUFFRCxzRkFBc0Y7UUFDdEYsTUFBTSxPQUFPLEdBQUcsT0FBTyxDQUFDLE9BQU8sSUFBSSxhQUFhLENBQUMsc0JBQXNCLENBQUM7UUFFeEUsTUFBTSxVQUFVLEdBQUcsSUFBQSw2QkFBc0IsRUFBQyxPQUFPLENBQUMsVUFBVSxDQUFDLENBQUM7UUFFOUQsMEVBQTBFO1FBQzFFLGtCQUFrQjtRQUNsQixNQUFNLE1BQU0sR0FBRyxtQkFBTSxDQUFDLEVBQUUsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUNsQyxNQUFNLEVBQUUsWUFBWSxDQUFDLFVBQVUsQ0FBQyxDQUFDO1FBRWpDLElBQ0UsQ0FBQyxVQUFVLENBQUMsUUFBUSxDQUFDLGdDQUFxQixDQUFDO1lBQzNDLENBQUMsVUFBVSxDQUFDLFFBQVEsQ0FBQyxxQ0FBMEIsQ0FBQztZQUNoRCxDQUFDLFVBQVUsQ0FB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LENBQ1QsQ0FBQztJQUVGOzs7Ozs7Ozs7T0FTRztJQUNJLE1BQU0sQ0FBVSxzQkFBc0IsR0FBRyxJQUFJLGFBQWEsQ0FDL0Qsd0JBQXdCLEVBQUUsZUFBZTtJQUN6QyxRQUFRLENBQ1QsQ0FBQztJQUVjLGVBQWUsR0FBRyxNQUFNLENBQUM7SUFFekIsZ0JBQWdCLENBQVc7SUFFM0M7SUFDRTs7T0FFRztJQUNhLGVBQXVCO0lBRXZDOztPQUVHO0lBQ2EsYUFBcUI7SUFFckM7O09BRUc7SUFDSCxPQUE4QjtRQVZkLG9CQUFlLEdBQWYsZUFBZSxDQUFRO1FBS3ZCLGtCQUFhLEdBQWIsYUFBYSxDQUFRO1FBT3JDLElBQUksQ0FBQyxnQkFBZ0IsR0FBRyxPQUFPLEVBQUUsZ0JBQWdCLElBQUksQ0FBQyxZQUFZLENBQUMsQ0FBQztJQUN0RSxDQUFDOztBQTNGSCxzQ0E0RkMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyBwYXRoIGZyb20gXCJwYXRoXCI7XG5pbXBvcnQgeyBwYXNjYWwgfSBmcm9tIFwiY2FzZVwiO1xuaW1wb3J0IHR5cGUgeyBBd3NDZGtEZXBzIH0gZnJvbSBcIi4vYXdzY2RrLWRlcHNcIjtcbmltcG9ydCB7XG4gIGNvbnZlcnRUb1Bvc2l4UGF0aCxcbiAgVFlQRVNDUklQVF9FREdFX0xBTUJEQV9FWFQsXG4gIFRZUEVTQ1JJUFRfTEFNQkRBX0VYVCxcbiAgVFlQRVNDUklQVF9TSU5HTEVUT05fTEFNQkRBX0VYVCxcbn0gZnJvbSBcIi4vaW50ZXJuYWxcIjtcbmltcG9ydCB7IENvbXBvbmVudCB9IGZyb20gXCIuLi9jb21wb25lbnRcIjtcbmltcG9ydCB0eXBlIHsgQnVuZGxpbmdPcHRpb25zIH0gZnJvbSBcIi4uL2phdmFzY3JpcHRcIjtcbmltcG9ydCB7IEJ1bmRsZXIsIEVzbGludCB9IGZyb20gXCIuLi9qYXZhc2NyaXB0XCI7XG5pbXBvcnQgdHlwZSB7IFByb2plY3QgfSBmcm9tIFwiLi4vcHJvamVjdFwiO1xuaW1wb3J0IHsgU291cmNlQ29kZSB9IGZyb20gXCIuLi9zb3VyY2UtY29kZVwiO1xuaW1wb3J0IHR5cGUgeyBUeXBlU2NyaXB0UHJvamVjdCB9IGZyb20gXCIuLi90eXBlc2NyaXB0XCI7XG5pbXBvcnQgeyBub3JtYWxpemVQZXJzaXN0ZWRQYXRoIH0gZnJvbSBcIi4uL3V0aWxcIjtcblxuLyoqXG4gKiBDb21tb24gb3B0aW9ucyBmb3IgYExhbWJkYUZ1bmN0aW9uYC4gQXBwbGllcyB0byBhbGwgZnVuY3Rpb25zIGluXG4gKiBhdXRvLWRpc2NvdmVyeS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBMYW1iZGFGdW5jdGlvbkNvbW1vbk9wdGlvbnMge1xuICAvKipcbiAgICogVGhlIG5vZGUuanMgdmVyc2lvbiB0byB0YXJnZXQuXG4gICAqXG4gICAqIEBkZWZhdWx0IExhbWJkYVJ1bnRpbWUuTk9ERUpTX1JFR0lPTkFMX0xBVEVTVCAtIFVzZXMgdGhlIGxhdGVzdCBOb2RlLmpzIHJ1bnRpbWVcbiAgICogYXZhaWxhYmxlIGluIHRoZSBkZXBsb3ltZW50IHJlZ2lvbiwgZGV0ZXJtaW5lZCBhdCBDREsgc3ludGhlc2lzIHRpbWUuXG4gICAqL1xuICByZWFkb25seSBydW50aW1lPzogTGFtYmRhUnVudGltZTtcblxuICAvKipcbiAgICogQnVuZGxpbmcgb3B0aW9ucyBmb3IgdGhpcyBBV1MgTGFtYmRhIGZ1bmN0aW9uLlxuICAgKlxuICAgKiBJZiBub3Qgc3BlY2lmaWVkIHRoZSBkZWZhdWx0IGJ1bmRsaW5nIG9wdGlvbnMgc3BlY2lmaWVkIGZvciB0aGUgcHJvamVjdFxuICAgKiBgQnVuZGxlcmAgaW5zdGFuY2Ugd2lsbCBiZSB1c2VkLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIGRlZmF1bHRzXG4gICAqL1xuICByZWFkb25seSBidW5kbGluZ09wdGlvbnM/OiBCdW5kbGluZ09wdGlvbnM7XG5cbiAgLyoqXG4gICAqIFdoZXRoZXIgdG8gYXV0b21hdGljYWxseSByZXVzZSBUQ1AgY29ubmVjdGlvbnMgd2hlbiB3b3JraW5nIHdpdGggdGhlIEFXU1xuICAgKiBTREsgZm9yIEphdmFTY3JpcHQuXG4gICAqXG4gICAqIFRoaXMgc2V0cyB0aGUgYEFXU19OT0RFSlNfQ09OTkVDVElPTl9SRVVTRV9FTkFCTEVEYCBlbnZpcm9ubWVudCB2YXJpYWJsZVxuICAgKiB0byBgMWAuXG4gICAqXG4gICAqIE5vdCBhcHBsaWNhYmxlIHdoZW4gYGVkZ2VMYW1iZGFgIGlzIHNldCB0byBgdHJ1ZWAgYmVjYXVzZSBlbnZpcm9ubWVudFxuICAgKiB2YXJpYWJsZXMgYXJlIG5vdCBzdXBwb3J0ZWQgaW4gTGFtYmRhQEVkZ2UuXG4gICAqXG4gICAqIEBzZWUgaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL3Nkay1mb3ItamF2YXNjcmlwdC92Mi9kZXZlbG9wZXItZ3VpZGUvbm9kZS1yZXVzaW5nLWNvbm5lY3Rpb25zLmh0bWxcbiAgICpcbiAgICogQGRlZmF1bHQgdHJ1ZVxuICAgKi9cbiAgcmVhZG9ubHkgYXdzU2RrQ29ubmVjdGlvblJldXNlPzogYm9vbGVhbjtcblxuICAvKipcbiAgICogV2hldGhlciB0byBjcmVhdGUgYSBgY2xvdWRmcm9udC5leHBlcmltZW50YWwuRWRnZUZ1bmN0aW9uYCBpbnN0ZWFkXG4gICAqIG9mIGEgYGxhbWJkYS5GdW5jdGlvbmAuXG4gICAqXG4gICAqIEBkZWZhdWx0IGZhbHNlXG4gICAqL1xuICByZWFkb25seSBlZGdlTGFtYmRhPzogYm9vbGVhbjtcblxuICAvKipcbiAgICogV2hldGhlciB0byBjcmVhdGUgYSBgbGFtYmRhLlNpbmdsZXRvbkZ1bmN0aW9uYCBpbnN0ZWFkIG9mIGFcbiAgICogYGxhbWJkYS5GdW5jdGlvbmAuXG4gICAqXG4gICAqIE5vdCBjb21wYXRpYmxlIHdpdGggYGVkZ2VMYW1iZGFgLlxuICAgKlxuICAgKiBAZGVmYXVsdCBmYWxzZVxuICAgKi9cbiAgcmVhZG9ubHkgc2luZ2xldG9uPzogYm9vbGVhbjtcblxuICAvKipcbiAgICogVVVJRCB0byB1c2UgZm9yIHNpbmdsZXRvbiBsYW1iZGEgdW5pcXVlbmVzcy5cbiAgICpcbiAgICogV2hlbiBzcGVjaWZpZWQsIHRoZSBnZW5lcmF0ZWQgc2luZ2xldG9uIGNvbnN0cnVjdCBoYXJkY29kZXMgdGhpcyBVVUlELlxuICAgKlxuICAgKiBPbmx5IHZhbGlkIHdoZW4gYHNpbmdsZXRvbmAgaXMgc2V0IHRvIGB0cnVlYC5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBubyBVVUlEIGlzIGhhcmRjb2RlZCBhbmQgY29uc3VtZXJzIG11c3QgcHJvdmlkZSBvbmVcbiAgICovXG4gIHJlYWRvbmx5IHNpbmdsZXRvblV1aWQ/OiBzdHJpbmc7XG59XG5cbi8qKlxuICogT3B0aW9ucyBmb3IgYEZ1bmN0aW9uYC5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBMYW1iZGFGdW5jdGlvbk9wdGlvbnMgZXh0ZW5kcyBMYW1iZGFGdW5jdGlvbkNvbW1vbk9wdGlvbnMge1xuICAvKipcbiAgICogQSBwYXRoIGZyb20gdGhlIHByb2plY3Qgcm9vdCBkaXJlY3RvcnkgdG8gYSBUeXBlU2NyaXB0IGZpbGUgd2hpY2ggY29udGFpbnNcbiAgICogdGhlIEFXUyBMYW1iZGEgaGFuZGxlciBlbnRyeXBvaW50IChleHBvcnRzIGEgYGhhbmRsZXJgIGZ1bmN0aW9uKS5cbiAgICpcbiAgICogVGhpcyBpcyByZWxhdGl2ZSB0byB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhlIHByb2plY3QuXG4gICAqXG4gICAqIEBleGFtcGxlIFwic3JjL3N1YmRpci9mb28ubGFtYmRhLnRzXCJcbiAgICovXG4gIHJlYWRvbmx5IGVudHJ5cG9pbnQ6IHN0cmluZztcblxuICAvKipcbiAgICogVGhlIG5hbWUgb2YgdGhlIGdlbmVyYXRlZCBUeXBlU2NyaXB0IHNvdXJjZSBmaWxlLiBUaGlzIGZpbGUgc2hvdWxkIGFsc28gYmVcbiAgICogdW5kZXIgdGhlIHNvdXJjZSB0cmVlLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIFRoZSBuYW1lIG9mIHRoZSBlbnRyeXBvaW50IGZpbGUsIHdpdGggdGhlIGAtZnVuY3Rpb24udHNgIHN1ZmZpeFxuICAgKiBpbnN0ZWFkIG9mIGAubGFtYmRhLnRzYC5cbiAgICovXG4gIHJlYWRvbmx5IGNvbnN0cnVjdEZpbGU/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSBuYW1lIG9mIHRoZSBnZW5lcmF0ZWQgYGxhbWJkYS5GdW5jdGlvbmAgc3ViY2xhc3MuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gQSBwYXNjYWwgY2FzZWQgdmVyc2lvbiBvZiB0aGUgbmFtZSBvZiB0aGUgZW50cnlwb2ludCBmaWxlLCB3aXRoXG4gICAqIHRoZSBleHRlbnNpb24gYEZ1bmN0aW9uYCAoZS5nLiBgUmVzaXplSW1hZ2VGdW5jdGlvbmApLlxuICAgKi9cbiAgcmVhZG9ubHkgY29uc3RydWN0TmFtZT86IHN0cmluZztcblxuICAvKipcbiAgICogQVdTIENESyBkZXBlbmRlbmN5IG1hbmFnZXIuXG4gICAqL1xuICByZWFkb25seSBjZGtEZXBzOiBBd3NDZGtEZXBzO1xufVxuXG4vKipcbiAqIEdlbmVyYXRlcyBhIHByZS1idW5kbGVkIEFXUyBMYW1iZGEgZnVuY3Rpb24gY29uc3RydWN0IGZyb20gaGFuZGxlciBjb2RlLlxuICpcbiAqIFRvIHVzZSB0aGlzLCBjcmVhdGUgYW4gQVdTIExhbWJkYSBoYW5kbGVyIGZpbGUgdW5kZXIgeW91ciBzb3VyY2UgdHJlZSB3aXRoXG4gKiB0aGUgYC5sYW1iZGEudHNgIGV4dGVuc2lvbiBhbmQgYWRkIGEgYExhbWJkYUZ1bmN0aW9uYCBjb21wb25lbnQgdG8geW91clxuICogdHlwZXNjcmlwdCBwcm9qZWN0IHBvaW50aW5nIHRvIHRoaXMgZW50cnlwb2ludC5cbiAqXG4gKiBUaGlzIHdpbGwgYWRkIGEgdGFzayB0byB5b3VyIFwiY29tcGlsZVwiIHN0ZXAgd2hpY2ggd2lsbCB1c2UgYGVzYnVpbGRgIHRvXG4gKiBidW5kbGUgdGhlIGhhbmRsZXIgY29kZSBpbnRvIHRoZSBidWlsZCBkaXJlY3RvcnkuIEl0IHdpbGwgYWxzbyBnZW5lcmF0ZSBhXG4gKiBmaWxlIGBzcmMvZm9vLWZ1bmN0aW9uLnRzYCB3aXRoIGEgY3VzdG9tIEFXUyBjb25zdHJ1Y3QgY2FsbGVkIGBGb29GdW5jdGlvbmBcbiAqIHdoaWNoIGV4dGVuZHMgYEBhd3MtY2RrL2F3cy1sYW1iZGEuRnVuY3Rpb25gIHdoaWNoIGlzIGJvdW5kIHRvIHRoZSBidW5kbGVkXG4gKiBoYW5kbGUgdGhyb3VnaCBhbiBhc3NldC5cbiAqXG4gKiBAZXhhbXBsZVxuICpcbiAqIG5ldyBMYW1iZGFGdW5jdGlvbihteVByb2plY3QsIHtcbiAqICAgc3JjZGlyOiBteVByb2plY3Quc3JjZGlyLFxuICogICBlbnRyeXBvaW50OiAnc3JjL2Zvby5sYW1iZGEudHMnLFxuICogfSk7XG4gKi9cbmV4cG9ydCBjbGFzcyBMYW1iZGFGdW5jdGlvbiBleHRlbmRzIENvbXBvbmVudCB7XG4gIC8qKlxuICAgKiBEZWZpbmVzIGEgcHJlLWJ1bmRsZWQgQVdTIExhbWJkYSBmdW5jdGlvbiBjb25zdHJ1Y3QgZnJvbSBoYW5kbGVyIGNvZGUuXG4gICAqXG4gICAqIEBwYXJhbSBwcm9qZWN0IFRoZSBwcm9qZWN0IHRvIHVzZVxuICAgKiBAcGFyYW0gb3B0aW9ucyBPcHRpb25zXG4gICAqL1xuICBjb25zdHJ1Y3Rvcihwcm9qZWN0OiBQcm9qZWN0LCBvcHRpb25zOiBMYW1iZGFGdW5jdGlvbk9wdGlvbnMpIHtcbiAgICBzdXBlcihwcm9qZWN0KTtcblxuICAgIGNvbnN0IGJ1bmRsZXIgPSBCdW5kbGVyLm9mKHByb2plY3QpO1xuICAgIGlmICghYnVuZGxlcikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBcIk5vIGJ1bmRsZXIgZm91bmQuIFBsZWFzZSBhZGQgYSBCdW5kbGVyIGNvbXBvbmVudCB0byB5b3VyIHByb2plY3QuXCIsXG4gICAgICApO1xuICAgIH1cblxuICAgIC8vIFVzZSBOT0RFSlNfUkVHSU9OQUxfTEFURVNUIGFzIGRlZmF1bHQsIHdoaWNoIGdlbmVyYXRlcyBkZXRlcm1pbmVMYXRlc3ROb2RlUnVudGltZSgpXG4gICAgY29uc3QgcnVudGltZSA9IG9wdGlvbnMucnVudGltZSA/PyBMYW1iZGFSdW50aW1lLk5PREVKU19SRUdJT05BTF9MQVRFU1Q7XG5cbiAgICBjb25zdCBlbnRyeXBvaW50ID0gbm9ybWFsaXplUGVyc2lzdGVkUGF0aChvcHRpb25zLmVudHJ5cG9pbnQpO1xuXG4gICAgLy8gYWxsb3cgTGFtYmRhIGhhbmRsZXIgY29kZSB0byBpbXBvcnQgZGV2LWRlcHMgc2luY2UgdGhleSBhcmUgb25seSBuZWVkZWRcbiAgICAvLyBkdXJpbmcgYnVuZGxpbmdcbiAgICBjb25zdCBlc2xpbnQgPSBFc2xpbnQub2YocHJvamVjdCk7XG4gICAgZXNsaW50Py5hbGxvd0RldkRlcHMoZW50cnlwb2ludCk7XG5cbiAgICBpZiAoXG4gICAgICAhZW50cnlwb2ludC5lbmRzV2l0aChUWVBFU0NSSVBUX0xBTUJEQV9FWFQpICYmXG4gICAgICAhZW50cnlwb2ludC5lbmRzV2l0aChUWVBFU0NSSVBUX0VER0VfTEFNQkRBX0VYVCkgJiZcbiAgICAgICFlbnRyeXBvaW50LmVuZHNXaXRoKFRZUEVTQ1JJUFRfU0lOR0xFVE9OX0xBTUJEQV9FWFQpXG4gICAgKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGAke2VudHJ5cG9pbnR9IG11c3QgaGF2ZSBhICR7VFlQRVNDUklQVF9MQU1CREFfRVhUfSwgJHtUWVBFU0NSSVBUX0VER0VfTEFNQkRBX0VYVH0sIG9yICR7VFlQRVNDUklQVF9TSU5HTEVUT05fTEFNQkRBX0VYVH0gZXh0ZW5zaW9uYCxcbiAgICAgICk7XG4gICAgfVxuXG4gICAgaWYgKG9wdGlvbnMuZWRnZUxhbWJkYSAmJiBvcHRpb25zLnNpbmdsZXRvbikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwic2luZ2xldG9uIGNhbm5vdCBiZSB1c2VkIHdpdGggZWRnZUxhbWJkYVwiKTtcbiAgICB9XG5cbiAgICBpZiAob3B0aW9ucy5zaW5nbGV0b25VdWlkICYmICFvcHRpb25zLnNpbmdsZXRvbikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwic2luZ2xldG9uVXVpZCBjYW4gb25seSBiZSB1c2VkIHdpdGggc2luZ2xldG9uXCIpO1xuICAgIH1cblxuICAgIGNvbnN0IHNvdXJjZUV4dGVuc2lvbiA9IGVudHJ5cG9pbnQuZW5kc1dpdGgoVFlQRVNDUklQVF9FREdFX0xBTUJEQV9FWFQpXG4gICAgICA/IFRZUEVTQ1JJUFRfRURHRV9MQU1CREFfRVhUXG4gICAgICA6IGVudHJ5cG9pbnQuZW5kc1dpdGgoVFlQRVNDUklQVF9TSU5HTEVUT05fTEFNQkRBX0VYVClcbiAgICAgICAgPyBUWVBFU0NSSVBUX1NJTkdMRVRPTl9MQU1CREFfRVhUXG4gICAgICAgIDogVFlQRVNDUklQVF9MQU1CREFfRVhUO1xuXG4gICAgY29uc3QgYmFzZVBhdGggPSBwYXRoLnBvc2l4LmpvaW4oXG4gICAgICBwYXRoLmRpcm5hbWUoZW50cnlwb2ludCksXG4gICAgICBwYXRoLmJhc2VuYW1lKGVudHJ5cG9pbnQsIHNvdXJjZUV4dGVuc2lvbiksXG4gICAgKTtcbiAgICBjb25zdCBjb25zdHJ1Y3RGaWxlID0gb3B0aW9ucy5jb25zdHJ1Y3RGaWxlID8/IGAke2Jhc2VQYXRofS1mdW5jdGlvbi50c2A7XG5cbiAgICBpZiAocGF0aC5leHRuYW1lKGNvbnN0cnVjdEZpbGUpICE9PSBcIi50c1wiKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGBDb25zdHJ1Y3QgZmlsZSBuYW1lIFwiJHtjb25zdHJ1Y3RGaWxlfVwiIG11c3QgaGF2ZSBhIC50cyBleHRlbnNpb25gLFxuICAgICAgKTtcbiAgICB9XG5cbiAgICAvLyB0eXBlIG5hbWVzXG4gICAgY29uc3QgY29uc3RydWN0TmFtZSA9XG4gICAgICBvcHRpb25zLmNvbnN0cnVjdE5hbWUgPz8gcGFzY2FsKHBhdGguYmFzZW5hbWUoYmFzZVBhdGgpKSArIFwiRnVuY3Rpb25cIjtcbiAgICBjb25zdCBwcm9wc1R5cGUgPSBgJHtjb25zdHJ1Y3ROYW1lfVByb3BzYDtcblxuICAgIGNvbnN0IGJ1bmRsZSA9IGJ1bmRsZXIuYWRkQnVuZGxlKGVudHJ5cG9pbnQsIHtcbiAgICAgIHRhcmdldDogcnVudGltZS5lc2J1aWxkVGFyZ2V0LFxuICAgICAgcGxhdGZvcm06IHJ1bnRpbWUuZXNidWlsZFBsYXRmb3JtLFxuICAgICAgZXh0ZXJuYWxzOiBydW50aW1lLmRlZmF1bHRFeHRlcm5hbHMsXG4gICAgICAuLi5vcHRpb25zLmJ1bmRsaW5nT3B0aW9ucyxcbiAgICAgIHRzY29uZmlnUGF0aDogKHByb2plY3QgYXMgVHlwZVNjcmlwdFByb2plY3QpPy50c2NvbmZpZ0Rldj8uZmlsZU5hbWUsXG4gICAgfSk7XG5cbiAgICAvLyBjYWxjdWxhdGUgdGhlIHJlbGF0aXZlIHBhdGggYmV0d2VlbiB0aGUgZGlyZWN0b3J5IGNvbnRhaW5pbmcgdGhlXG4gICAgLy8gZ2VuZXJhdGVkIGNvbnN0cnVjdCBzb3VyY2UgZmlsZSB0byB0aGUgZGlyZWN0b3J5IGNvbnRhaW5pbmcgdGhlIGJ1bmRsZVxuICAgIC8vIGluZGV4LmpzIGJ5IHJlc29sdmluZyB0aGVtIGFzIGFic29sdXRlIHBhdGhzIGZpcnN0LlxuICAgIC8vIGUuZzpcbiAgICAvLyAgLSBvdXRmaWxlQWJzID0+IGAvcHJvamVjdC1vdXRkaXIvYXNzZXRzL2Zvby9iYXIvYmF6L2Zvby1mdW5jdGlvbi9pbmRleC5qc2BcbiAgICAvLyAgLSBjb25zdHJ1Y3RBYnMgPT4gYC9wcm9qZWN0LW91dGRpci9zcmMvZm9vL2Jhci9iYXovZm9vLWZ1bmN0aW9uLnRzYFxuICAgIGNvbnN0IG91dGZpbGVBYnMgPSBwYXRoLmpvaW4ocHJvamVjdC5vdXRkaXIsIGJ1bmRsZS5vdXRmaWxlKTtcbiAgICBjb25zdCBjb25zdHJ1Y3RBYnMgPSBwYXRoLmpvaW4ocHJvamVjdC5vdXRkaXIsIGNvbnN0cnVjdEZpbGUpO1xuICAgIGNvbnN0IHJlbGF0aXZlT3V0ZmlsZSA9IHBhdGgucmVsYXRpdmUoXG4gICAgICBwYXRoLmRpcm5hbWUoY29uc3RydWN0QWJzKSxcbiAgICAgIHBhdGguZGlybmFtZShvdXRmaWxlQWJzKSxcbiAgICApO1xuXG4gICAgY29uc3Qgc3JjID0gbmV3IFNvdXJjZUNvZGUocHJvamVjdCwgY29uc3RydWN0RmlsZSk7XG4gICAgaWYgKHNyYy5tYXJrZXIpIHtcbiAgICAgIHNyYy5saW5lKGAvLyAke3NyYy5tYXJrZXJ9YCk7XG4gICAgfVxuICAgIHNyYy5saW5lKFwiaW1wb3J0ICogYXMgcGF0aCBmcm9tICdwYXRoJztcIik7XG5cbiAgICBpZiAob3B0aW9ucy5lZGdlTGFtYmRhKSB7XG4gICAgICBzcmMubGluZShcImltcG9ydCAqIGFzIGNsb3VkZnJvbnQgZnJvbSAnYXdzLWNkay1saWIvYXdzLWNsb3VkZnJvbnQnO1wiKTtcbiAgICB9XG4gICAgc3JjLmxpbmUoXCJpbXBvcnQgKiBhcyBsYW1iZGEgZnJvbSAnYXdzLWNkay1saWIvYXdzLWxhbWJkYSc7XCIpO1xuICAgIC8vIEltcG9ydCBkZXRlcm1pbmVMYXRlc3ROb2RlUnVudGltZSBpZiB1c2luZyBOT0RFSlNfUkVHSU9OQUxfTEFURVNUXG4gICAgaWYgKHJ1bnRpbWUgPT09IExhbWJkYVJ1bnRpbWUuTk9ERUpTX1JFR0lPTkFMX0xBVEVTVCkge1xuICAgICAgc3JjLmxpbmUoXG4gICAgICAgIFwiaW1wb3J0IHsgZGV0ZXJtaW5lTGF0ZXN0Tm9kZVJ1bnRpbWUgfSBmcm9tICdhd3MtY2RrLWxpYi9hd3MtbGFtYmRhJztcIixcbiAgICAgICk7XG4gICAgfVxuICAgIHNyYy5saW5lKFwiaW1wb3J0IHsgQ29uc3RydWN0IH0gZnJvbSAnY29uc3RydWN0cyc7XCIpO1xuXG4gICAgc3JjLmxpbmUoKTtcbiAgICBzcmMubGluZShcIi8qKlwiKTtcbiAgICBzcmMubGluZShgICogUHJvcHMgZm9yICR7Y29uc3RydWN0TmFtZX1gKTtcbiAgICBzcmMubGluZShcIiAqL1wiKTtcbiAgICBpZiAob3B0aW9ucy5lZGdlTGFtYmRhKSB7XG4gICAgICBzcmMub3BlbihcbiAgICAgICAgYGV4cG9ydCBpbnRlcmZhY2UgJHtwcm9wc1R5cGV9IGV4dGVuZHMgY2xvdWRmcm9udC5leHBlcmltZW50YWwuRWRnZUZ1bmN0aW9uUHJvcHMge2AsXG4gICAgICApO1xuICAgIH0gZWxzZSBpZiAob3B0aW9ucy5zaW5nbGV0b24pIHtcbiAgICAgIHNyYy5vcGVuKFxuICAgICAgICBgZXhwb3J0IGludGVyZmFjZSAke3Byb3BzVHlwZX0gZXh0ZW5kcyBsYW1iZGEuU2luZ2xldG9uRnVuY3Rpb25Qcm9wcyB7YCxcbiAgICAgICk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHNyYy5vcGVuKFxuICAgICAgICBgZXhwb3J0IGludGVyZmFjZSAke3Byb3BzVHlwZX0gZXh0ZW5kcyBsYW1iZGEuRnVuY3Rpb25PcHRpb25zIHtgLFxuICAgICAgKTtcbiAgICB9XG4gICAgLy8gQWRkIHJ1bnRpbWUgcHJvcCB0byBpbnRlcmZhY2Ugb25seSB3aGVuIHJ1bnRpbWUgaXMgbm90IGV4cGxpY2l0bHkgc2V0XG4gICAgLy8gVGhpcyBhbGxvd3MgY29uc3VtZXJzIHRvIG92ZXJyaWRlIHRoZSBkZWZhdWx0IE5PREVKU19SRUdJT05BTF9MQVRFU1RcbiAgICBpZiAoIW9wdGlvbnMucnVudGltZSkge1xuICAgICAgc3JjLmxpbmUoXCIvKipcIik7XG4gICAgICBzcmMubGluZShcIiAqIFRoZSBMYW1iZGEgcnVudGltZSB0byB1c2UuXCIpO1xuICAgICAgc3JjLmxpbmUoXG4gICAgICAgIFwiICogQGRlZmF1bHQgLSBMYXRlc3QgTm9kZS5qcyBydW50aW1lIGF2YWlsYWJsZSBpbiB0aGUgZGVwbG95bWVudCByZWdpb25cIixcbiAgICAgICk7XG4gICAgICBzcmMubGluZShcIiAqL1wiKTtcbiAgICAgIHNyYy5saW5lKFwicmVhZG9ubHkgcnVudGltZT86IGxhbWJkYS5SdW50aW1lO1wiKTtcbiAgICB9XG4gICAgc3JjLmNsb3NlKFwifVwiKTtcbiAgICBzcmMubGluZSgpO1xuICAgIHNyYy5saW5lKFwiLyoqXCIpO1xuICAgIHNyYy5saW5lKFxuICAgICAgYCAqIEFuIEFXUyBMYW1iZGEgZnVuY3Rpb24gd2hpY2ggZXhlY3V0ZXMgJHtjb252ZXJ0VG9Qb3NpeFBhdGgoXG4gICAgICAgIGJhc2VQYXRoLFxuICAgICAgKX0uYCxcbiAgICApO1xuICAgIHNyYy5saW5lKFwiICovXCIpO1xuICAgIGlmIChvcHRpb25zLmVkZ2VMYW1iZGEpIHtcbiAgICAgIHNyYy5vcGVuKFxuICAgICAgICBgZXhwb3J0IGNsYXNzICR7Y29uc3RydWN0TmFtZX0gZXh0ZW5kcyBjbG91ZGZyb250LmV4cGVyaW1lbnRhbC5FZGdlRnVuY3Rpb24ge2AsXG4gICAgICApO1xuICAgIH0gZWxzZSBpZiAob3B0aW9ucy5zaW5nbGV0b24pIHtcbiAgICAgIHNyYy5vcGVuKFxuICAgICAgICBgZXhwb3J0IGNsYXNzICR7Y29uc3RydWN0TmFtZX0gZXh0ZW5kcyBsYW1iZGEuU2luZ2xldG9uRnVuY3Rpb24ge2AsXG4gICAgICApO1xuICAgIH0gZWxzZSB7XG4gICAgICBzcmMub3BlbihgZXhwb3J0IGNsYXNzICR7Y29uc3RydWN0TmFtZX0gZXh0ZW5kcyBsYW1iZGEuRnVuY3Rpb24ge2ApO1xuICAgIH1cbiAgICBzcmMub3BlbihcbiAgICAgIGBjb25zdHJ1Y3RvcihzY29wZTogQ29uc3RydWN0LCBpZDogc3RyaW5nLCBwcm9wcz86ICR7cHJvcHNUeXBlfSkge2AsXG4gICAgKTtcbiAgICBzcmMub3BlbihcInN1cGVyKHNjb3BlLCBpZCwge1wiKTtcbiAgICBzcmMubGluZShgZGVzY3JpcHRpb246ICcke2NvbnZlcnRUb1Bvc2l4UGF0aChlbnRyeXBvaW50KX0nLGApO1xuICAgIHNyYy5saW5lKFwiLi4ucHJvcHMsXCIpO1xuICAgIGlmIChvcHRpb25zLnNpbmdsZXRvbiAmJiBvcHRpb25zLnNpbmdsZXRvblV1aWQpIHtcbiAgICAgIHNyYy5saW5lKGB1dWlkOiAke0pTT04uc3RyaW5naWZ5KG9wdGlvbnMuc2luZ2xldG9uVXVpZCl9LGApO1xuICAgIH1cblxuICAgIC8vIEdlbmVyYXRlIHJ1bnRpbWUgY29kZVxuICAgIGlmIChydW50aW1lID09PSBMYW1iZGFSdW50aW1lLk5PREVKU19SRUdJT05BTF9MQVRFU1QpIHtcbiAgICAgIC8vIFJlZ2lvbmFsIGxhdGVzdCBydW50aW1lXG4gICAgICBpZiAoIW9wdGlvbnMucnVudGltZSkge1xuICAgICAgICAvLyBEZWZhdWx0IChub3QgZXhwbGljaXRseSBzZXQpIC0gYWxsb3cgY29uc3VtZXIgb3ZlcnJpZGVcbiAgICAgICAgc3JjLmxpbmUoXG4gICAgICAgICAgXCJydW50aW1lOiBwcm9wcz8ucnVudGltZSA/PyBkZXRlcm1pbmVMYXRlc3ROb2RlUnVudGltZShzY29wZSksXCIsXG4gICAgICAgICk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvLyBFeHBsaWNpdGx5IHNldCAtIG5vIG92ZXJyaWRlXG4gICAgICAgIHNyYy5saW5lKFwicnVudGltZTogZGV0ZXJtaW5lTGF0ZXN0Tm9kZVJ1bnRpbWUoc2NvcGUpLFwiKTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgLy8gRXhwbGljaXQgcnVudGltZSAtIGhhcmRjb2RlZCwgbm8gb3ZlcnJpZGVcbiAgICAgIHNyYy5saW5lKFxuICAgICAgICBgcnVudGltZTogbmV3IGxhbWJkYS5SdW50aW1lKCcke3J1bnRpbWUuZnVuY3Rpb25SdW50aW1lfScsIGxhbWJkYS5SdW50aW1lRmFtaWx5Lk5PREVKUyksYCxcbiAgICAgICk7XG4gICAgfVxuXG4gICAgc3JjLmxpbmUoXCJoYW5kbGVyOiAnaW5kZXguaGFuZGxlcicsXCIpO1xuICAgIHNyYy5saW5lKFxuICAgICAgYGNvZGU6IGxhbWJkYS5Db2RlLmZyb21Bc3NldChwYXRoLmpvaW4oX19kaXJuYW1lLCAnJHtjb252ZXJ0VG9Qb3NpeFBhdGgoXG4gICAgICAgIHJlbGF0aXZlT3V0ZmlsZSxcbiAgICAgICl9JykpLGAsXG4gICAgKTtcbiAgICBzcmMuY2xvc2UoXCJ9KTtcIik7XG4gICAgaWYgKChvcHRpb25zLmF3c1Nka0Nvbm5lY3Rpb25SZXVzZSA/PyB0cnVlKSAmJiAhb3B0aW9ucy5lZGdlTGFtYmRhKSB7XG4gICAgICBzcmMubGluZShcbiAgICAgICAgXCJ0aGlzLmFkZEVudmlyb25tZW50KCdBV1NfTk9ERUpTX0NPTk5FQ1RJT05fUkVVU0VfRU5BQkxFRCcsICcxJywgeyByZW1vdmVJbkVkZ2U6IHRydWUgfSk7XCIsXG4gICAgICApO1xuICAgIH1cbiAgICBzcmMuY2xvc2UoXCJ9XCIpO1xuICAgIHNyYy5jbG9zZShcIn1cIik7XG5cbiAgICB0aGlzLnByb2plY3QubG9nZ2VyLnZlcmJvc2UoXG4gICAgICBgJHtiYXNlUGF0aH06IGNvbnN0cnVjdCBcIiR7Y29uc3RydWN0TmFtZX1cIiBnZW5lcmF0ZWQgdW5kZXIgXCIke2NvbnN0cnVjdEZpbGV9XCJgLFxuICAgICk7XG4gICAgdGhpcy5wcm9qZWN0LmxvZ2dlci52ZXJib3NlKFxuICAgICAgYCR7YmFzZVBhdGh9OiBidW5kbGUgdGFzayBcIiR7YnVuZGxlLmJ1bmRsZVRhc2submFtZX1cImAsXG4gICAgKTtcbiAgICBpZiAoYnVuZGxlLndhdGNoVGFzaykge1xuICAgICAgdGhpcy5wcm9qZWN0LmxvZ2dlci52ZXJib3NlKFxuICAgICAgICBgJHtiYXNlUGF0aH06IGJ1bmRsZSB3YXRjaCB0YXNrIFwiJHtidW5kbGUud2F0Y2hUYXNrLm5hbWV9XCJgLFxuICAgICAgKTtcbiAgICB9XG4gIH1cbn1cblxuLyoqXG4gKiBPcHRpb25zIGZvciB0aGUgQVdTIExhbWJkYSBmdW5jdGlvbiBydW50aW1lXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgTGFtYmRhUnVudGltZU9wdGlvbnMge1xuICAvKipcbiAgICogUGFja2FnZXMgdGhhdCBhcmUgY29uc2lkZXJlZCBleHRlcm5hbHMgYnkgZGVmYXVsdCB3aGVuIGJ1bmRsaW5nXG4gICAqXG4gICAqIEBkZWZhdWx0IFsnQGF3cy1zZGsvKiddXG4gICAqL1xuICByZWFkb25seSBkZWZhdWx0RXh0ZXJuYWxzPzogc3RyaW5nW107XG59XG5cbi8qKlxuICogVGhlIHJ1bnRpbWUgZm9yIHRoZSBBV1MgTGFtYmRhIGZ1bmN0aW9uLlxuICovXG5leHBvcnQgY2xhc3MgTGFtYmRhUnVudGltZSB7XG4gIC8qKlxuICAgKiBOb2RlLmpzIDE0LnhcbiAgICogQGRlcHJlY2F0ZWQgTm9kZS5qcyAxNCBydW50aW1lIGhhcyBiZWVuIGRlcHJlY2F0ZWQgb24gRGVjIDQsIDIwMjNcbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgcmVhZG9ubHkgTk9ERUpTXzE0X1ggPSBuZXcgTGFtYmRhUnVudGltZShcbiAgICBcIm5vZGVqczE0LnhcIixcbiAgICBcIm5vZGUxNFwiLFxuICAgIHsgZGVmYXVsdEV4dGVybmFsczogW1wiYXdzLXNka1wiXSB9LFxuICApO1xuXG4gIC8qKlxuICAgKiBOb2RlLmpzIDE2LnhcbiAgICogQGRlcHJlY2F0ZWQgTm9kZS5qcyAxNiBydW50aW1lIGhhcyBiZWVuIGRlcHJlY2F0ZWQgb24gSnVuIDEyLCAyMDI0XG4gICAqL1xuICBwdWJsaWMgc3RhdGljIHJlYWRvbmx5IE5PREVKU18xNl9YID0gbmV3IExhbWJkYVJ1bnRpbWUoXG4gICAgXCJub2RlanMxNi54XCIsXG4gICAgXCJub2RlMTZcIixcbiAgICB7IGRlZmF1bHRFeHRlcm5hbHM6IFtcImF3cy1zZGtcIl0gfSxcbiAgKTtcblxuICAvKipcbiAgICogTm9kZS5qcyAxOC54XG4gICAqXG4gICAqIEBkZXByZWNhdGVkOiBOb2RlLmpzIDE4IHJ1bnRpbWUgaGFzIGJlZW4gZGVwcmVjYXRlZCBvbiBTZXAgMSwgMjAyNVxuICAgKi9cbiAgcHVibGljIHN0YXRpYyByZWFkb25seSBOT0RFSlNfMThfWCA9IG5ldyBMYW1iZGFSdW50aW1lKFxuICAgIFwibm9kZWpzMTgueFwiLFxuICAgIFwibm9kZTE4XCIsXG4gICk7XG5cbiAgLyoqXG4gICAqIE5vZGUuanMgMjAueFxuICAgKi9cbiAgcHVibGljIHN0YXRpYyByZWFkb25seSBOT0RFSlNfMjBfWCA9IG5ldyBMYW1iZGFSdW50aW1lKFxuICAgIFwibm9kZWpzMjAueFwiLFxuICAgIFwibm9kZTIwXCIsXG4gICk7XG5cbiAgLyoqXG4gICAqIE5vZGUuanMgMjIueFxuICAgKi9cbiAgcHVibGljIHN0YXRpYyByZWFkb25seSBOT0RFSlNfMjJfWCA9IG5ldyBMYW1iZGFSdW50aW1lKFxuICAgIFwibm9kZWpzMjIueFwiLFxuICAgIFwibm9kZTIyXCIsXG4gICk7XG5cbiAgLyoqXG4gICAqIE5vZGUuanMgMjQueFxuICAgKi9cbiAgcHVibGljIHN0YXRpYyByZWFkb25seSBOT0RFSlNfMjRfWCA9IG5ldyBMYW1iZGFSdW50aW1lKFxuICAgIFwibm9kZWpzMjQueFwiLFxuICAgIFwibm9kZTI0XCIsXG4gICk7XG5cbiAgLyoqXG4gICAqIFVzZSB0aGUgbGF0ZXN0IE5vZGUuanMgcnVudGltZSBhdmFpbGFibGUgaW4gdGhlIGRlcGxveW1lbnQgcmVnaW9uLlxuICAgKlxuICAgKiBUaGlzIGdlbmVyYXRlcyBjb2RlIHRoYXQgdXNlcyBgZGV0ZXJtaW5lTGF0ZXN0Tm9kZVJ1bnRpbWUoKWAgYXQgQ0RLIHN5bnRoZXNpcyB0aW1lLFxuICAgKiB3aGljaCBkeW5hbWljYWxseSBzZWxlY3RzIHRoZSBsYXRlc3QgTm9kZS5qcyBydW50aW1lIGF2YWlsYWJsZSBiYXNlZCBvbiByZWdpb25hbFxuICAgKiBhdmFpbGFiaWxpdHkuIFRoaXMgZWxpbWluYXRlcyB0aGUgbmVlZCB0byBtYW51YWxseSB1cGRhdGUgcnVudGltZSB2ZXJzaW9ucyBhbmRcbiAgICogYXZvaWRzIEVPTCB3YXJuaW5ncy5cbiAgICpcbiAgICogQGRlZmF1bHQgVXNlcyBkZXRlcm1pbmVMYXRlc3ROb2RlUnVudGltZSgpIGZyb20gYXdzLWNkay1saWJcbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgcmVhZG9ubHkgTk9ERUpTX1JFR0lPTkFMX0xBVEVTVCA9IG5ldyBMYW1iZGFSdW50aW1lKFxuICAgIFwiTk9ERUpTX1JFR0lPTkFMX0xBVEVTVFwiLCAvLyBNYXJrZXIgdmFsdWVcbiAgICBcIm5vZGUyMlwiLCAvLyBlc2J1aWxkIHRhcmdldCAoY3VycmVudCBMVFMpXG4gICk7XG5cbiAgcHVibGljIHJlYWRvbmx5IGVzYnVpbGRQbGF0Zm9ybSA9IFwibm9kZVwiO1xuXG4gIHB1YmxpYyByZWFkb25seSBkZWZhdWx0RXh0ZXJuYWxzOiBzdHJpbmdbXTtcblxuICBwdWJsaWMgY29uc3RydWN0b3IoXG4gICAgLyoqXG4gICAgICogVGhlIE5vZGUuanMgcnVudGltZSB0byB1c2VcbiAgICAgKi9cbiAgICBwdWJsaWMgcmVhZG9ubHkgZnVuY3Rpb25SdW50aW1lOiBzdHJpbmcsXG5cbiAgICAvKipcbiAgICAgKiBUaGUgZXNidWlsZCBzZXR0aW5nIHRvIHVzZS5cbiAgICAgKi9cbiAgICBwdWJsaWMgcmVhZG9ubHkgZXNidWlsZFRhcmdldDogc3RyaW5nLFxuXG4gICAgLyoqXG4gICAgICogT3B0aW9ucyBmb3IgdGhpcyBydW50aW1lLlxuICAgICAqL1xuICAgIG9wdGlvbnM/OiBMYW1iZGFSdW50aW1lT3B0aW9ucyxcbiAgKSB7XG4gICAgdGhpcy5kZWZhdWx0RXh0ZXJuYWxzID0gb3B0aW9ucz8uZGVmYXVsdEV4dGVybmFscyA/PyBbXCJAYXdzLXNkay8qXCJdO1xuICB9XG59XG4iXX0=