UNPKG

projen

Version:

CDK for software projects

253 lines • 38.5 kB
"use strict"; var _a, _b; Object.defineProperty(exports, "__esModule", { value: true }); exports.LambdaRuntime = exports.LambdaFunction = void 0; const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti"); const path = 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 { /** * 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 cdkDeps = options.cdkDeps; 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)) { throw new Error(`${entrypoint} must have a ${internal_1.TYPESCRIPT_LAMBDA_EXT} or ${internal_1.TYPESCRIPT_EDGE_LAMBDA_EXT} extension`); } const basePath = path.posix.join(path.dirname(entrypoint), path.basename(entrypoint, options.edgeLambda ? internal_1.TYPESCRIPT_EDGE_LAMBDA_EXT : internal_1.TYPESCRIPT_LAMBDA_EXT)); 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 (cdkDeps.cdkMajorVersion === 1) { if (options.edgeLambda) { src.line("import * as cloudfront from '@aws-cdk/aws-cloudfront';"); cdkDeps.addV1Dependencies("@aws-cdk/aws-cloudfront"); } src.line("import * as lambda from '@aws-cdk/aws-lambda';"); src.line("import { Construct } from '@aws-cdk/core';"); cdkDeps.addV1Dependencies("@aws-cdk/aws-lambda"); cdkDeps.addV1Dependencies("@aws-cdk/core"); } else { 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 { 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 { 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,"); // 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; _a = JSII_RTTI_SYMBOL_1; LambdaFunction[_a] = { fqn: "projen.awscdk.LambdaFunction", version: "0.99.3" }; /** * The runtime for the AWS Lambda function. */ class LambdaRuntime { 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.esbuildPlatform = "node"; this.defaultExternals = options?.defaultExternals ?? ["@aws-sdk/*"]; } } exports.LambdaRuntime = LambdaRuntime; _b = JSII_RTTI_SYMBOL_1; LambdaRuntime[_b] = { fqn: "projen.awscdk.LambdaRuntime", version: "0.99.3" }; /** * Node.js 10.x * @deprecated Node.js 10 runtime has been deprecated on Jul 30, 2021 */ LambdaRuntime.NODEJS_10_X = new LambdaRuntime("nodejs10.x", "node10", { defaultExternals: ["aws-sdk"] }); /** * Node.js 12.x * @deprecated Node.js 12 runtime has been deprecated on Mar 31, 2023 */ LambdaRuntime.NODEJS_12_X = new LambdaRuntime("nodejs12.x", "node12", { defaultExternals: ["aws-sdk"] }); /** * Node.js 14.x * @deprecated Node.js 14 runtime has been deprecated on Dec 4, 2023 */ LambdaRuntime.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 */ LambdaRuntime.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 */ LambdaRuntime.NODEJS_18_X = new LambdaRuntime("nodejs18.x", "node18"); /** * Node.js 20.x */ LambdaRuntime.NODEJS_20_X = new LambdaRuntime("nodejs20.x", "node20"); /** * Node.js 22.x */ LambdaRuntime.NODEJS_22_X = new LambdaRuntime("nodejs22.x", "node22"); /** * Node.js 24.x */ LambdaRuntime.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 */ LambdaRuntime.NODEJS_REGIONAL_LATEST = new LambdaRuntime("NODEJS_REGIONAL_LATEST", // Marker value "node22" // esbuild target (current LTS) ); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGFtYmRhLWZ1bmN0aW9uLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2F3c2Nkay9sYW1iZGEtZnVuY3Rpb24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFBQSw2QkFBNkI7QUFDN0IsK0JBQThCO0FBRTlCLHlDQUlvQjtBQUNwQiw0Q0FBeUM7QUFDekMsOENBQWlFO0FBRWpFLGdEQUE0QztBQUU1QyxrQ0FBaUQ7QUF1RmpEOzs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBbUJHO0FBQ0gsTUFBYSxjQUFlLFNBQVEscUJBQVM7SUFDM0M7Ozs7O09BS0c7SUFDSCxZQUFZLE9BQWdCLEVBQUUsT0FBOEI7UUFDMUQsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBRWYsTUFBTSxPQUFPLEdBQUcsT0FBTyxDQUFDLE9BQU8sQ0FBQztRQUNoQyxNQUFNLE9BQU8sR0FBRyxvQkFBTyxDQUFDLEVBQUUsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUNwQyxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUM7WUFDYixNQUFNLElBQUksS0FBSyxDQUNiLG1FQUFtRSxDQUNwRSxDQUFDO1FBQ0osQ0FBQztRQUVELHNGQUFzRjtRQUN0RixNQUFNLE9BQU8sR0FBRyxPQUFPLENBQUMsT0FBTyxJQUFJLGFBQWEsQ0FBQyxzQkFBc0IsQ0FBQztRQUV4RSxNQUFNLFVBQVUsR0FBRyxJQUFBLDZCQUFzQixFQUFDLE9BQU8sQ0FBQyxVQUFVLENBQUMsQ0FBQztRQUU5RCwwRUFBMEU7UUFDMUUsa0JBQWtCO1FBQ2xCLE1BQU0sTUFBTSxHQUFHLG1CQUFNLENBQUMsRUFBRSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQ2xDLE1BQU0sRUFBRSxZQUFZLENBQUMsVUFBVSxDQUFDLENBQUM7UUFFakMsSUFDRSxDQUFDLFVBQVUsQ0FBQyxRQUFRLENBQUMsZ0NBQXFCLENBQUM7WUFDM0MsQ0FBQyxVQUFVLENBQUMsUUFBUSxDQUFDLHFDQUEwQixDQUFDLEVBQ2hELENBQUM7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QUFHLElBQUksYUFBYSxDQUNwRCxZQUFZLEVBQ1osUUFBUSxDQUNULEFBSGlDLENBR2hDO0FBRUY7O0dBRUc7QUFDb0IseUJBQVcsR0FBRyxJQUFJLGFBQWEsQ0FDcEQsWUFBWSxFQUNaLFFBQVEsQ0FDVCxBQUhpQyxDQUdoQztBQUVGOzs7Ozs7Ozs7R0FTRztBQUNvQixvQ0FBc0IsR0FBRyxJQUFJLGFBQWEsQ0FDL0Qsd0JBQXdCLEVBQUUsZUFBZTtBQUN6QyxRQUFRLENBQUMsK0JBQStCO0NBQ3pDLEFBSDRDLENBRzNDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICogYXMgcGF0aCBmcm9tIFwicGF0aFwiO1xuaW1wb3J0IHsgcGFzY2FsIH0gZnJvbSBcImNhc2VcIjtcbmltcG9ydCB7IEF3c0Nka0RlcHMgfSBmcm9tIFwiLi9hd3NjZGstZGVwc1wiO1xuaW1wb3J0IHtcbiAgY29udmVydFRvUG9zaXhQYXRoLFxuICBUWVBFU0NSSVBUX0VER0VfTEFNQkRBX0VYVCxcbiAgVFlQRVNDUklQVF9MQU1CREFfRVhULFxufSBmcm9tIFwiLi9pbnRlcm5hbFwiO1xuaW1wb3J0IHsgQ29tcG9uZW50IH0gZnJvbSBcIi4uL2NvbXBvbmVudFwiO1xuaW1wb3J0IHsgQnVuZGxlciwgQnVuZGxpbmdPcHRpb25zLCBFc2xpbnQgfSBmcm9tIFwiLi4vamF2YXNjcmlwdFwiO1xuaW1wb3J0IHsgUHJvamVjdCB9IGZyb20gXCIuLi9wcm9qZWN0XCI7XG5pbXBvcnQgeyBTb3VyY2VDb2RlIH0gZnJvbSBcIi4uL3NvdXJjZS1jb2RlXCI7XG5pbXBvcnQgeyBUeXBlU2NyaXB0UHJvamVjdCB9IGZyb20gXCIuLi90eXBlc2NyaXB0XCI7XG5pbXBvcnQgeyBub3JtYWxpemVQZXJzaXN0ZWRQYXRoIH0gZnJvbSBcIi4uL3V0aWxcIjtcblxuLyoqXG4gKiBDb21tb24gb3B0aW9ucyBmb3IgYExhbWJkYUZ1bmN0aW9uYC4gQXBwbGllcyB0byBhbGwgZnVuY3Rpb25zIGluXG4gKiBhdXRvLWRpc2NvdmVyeS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBMYW1iZGFGdW5jdGlvbkNvbW1vbk9wdGlvbnMge1xuICAvKipcbiAgICogVGhlIG5vZGUuanMgdmVyc2lvbiB0byB0YXJnZXQuXG4gICAqXG4gICAqIEBkZWZhdWx0IExhbWJkYVJ1bnRpbWUuTk9ERUpTX1JFR0lPTkFMX0xBVEVTVCAtIFVzZXMgdGhlIGxhdGVzdCBOb2RlLmpzIHJ1bnRpbWVcbiAgICogYXZhaWxhYmxlIGluIHRoZSBkZXBsb3ltZW50IHJlZ2lvbiwgZGV0ZXJtaW5lZCBhdCBDREsgc3ludGhlc2lzIHRpbWUuXG4gICAqL1xuICByZWFkb25seSBydW50aW1lPzogTGFtYmRhUnVudGltZTtcblxuICAvKipcbiAgICogQnVuZGxpbmcgb3B0aW9ucyBmb3IgdGhpcyBBV1MgTGFtYmRhIGZ1bmN0aW9uLlxuICAgKlxuICAgKiBJZiBub3Qgc3BlY2lmaWVkIHRoZSBkZWZhdWx0IGJ1bmRsaW5nIG9wdGlvbnMgc3BlY2lmaWVkIGZvciB0aGUgcHJvamVjdFxuICAgKiBgQnVuZGxlcmAgaW5zdGFuY2Ugd2lsbCBiZSB1c2VkLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIGRlZmF1bHRzXG4gICAqL1xuICByZWFkb25seSBidW5kbGluZ09wdGlvbnM/OiBCdW5kbGluZ09wdGlvbnM7XG5cbiAgLyoqXG4gICAqIFdoZXRoZXIgdG8gYXV0b21hdGljYWxseSByZXVzZSBUQ1AgY29ubmVjdGlvbnMgd2hlbiB3b3JraW5nIHdpdGggdGhlIEFXU1xuICAgKiBTREsgZm9yIEphdmFTY3JpcHQuXG4gICAqXG4gICAqIFRoaXMgc2V0cyB0aGUgYEFXU19OT0RFSlNfQ09OTkVDVElPTl9SRVVTRV9FTkFCTEVEYCBlbnZpcm9ubWVudCB2YXJpYWJsZVxuICAgKiB0byBgMWAuXG4gICAqXG4gICAqIE5vdCBhcHBsaWNhYmxlIHdoZW4gYGVkZ2VMYW1iZGFgIGlzIHNldCB0byBgdHJ1ZWAgYmVjYXVzZSBlbnZpcm9ubWVudFxuICAgKiB2YXJpYWJsZXMgYXJlIG5vdCBzdXBwb3J0ZWQgaW4gTGFtYmRhQEVkZ2UuXG4gICAqXG4gICAqIEBzZWUgaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL3Nkay1mb3ItamF2YXNjcmlwdC92Mi9kZXZlbG9wZXItZ3VpZGUvbm9kZS1yZXVzaW5nLWNvbm5lY3Rpb25zLmh0bWxcbiAgICpcbiAgICogQGRlZmF1bHQgdHJ1ZVxuICAgKi9cbiAgcmVhZG9ubHkgYXdzU2RrQ29ubmVjdGlvblJldXNlPzogYm9vbGVhbjtcblxuICAvKipcbiAgICogV2hldGhlciB0byBjcmVhdGUgYSBgY2xvdWRmcm9udC5leHBlcmltZW50YWwuRWRnZUZ1bmN0aW9uYCBpbnN0ZWFkXG4gICAqIG9mIGEgYGxhbWJkYS5GdW5jdGlvbmAuXG4gICAqXG4gICAqIEBkZWZhdWx0IGZhbHNlXG4gICAqL1xuICByZWFkb25seSBlZGdlTGFtYmRhPzogYm9vbGVhbjtcbn1cblxuLyoqXG4gKiBPcHRpb25zIGZvciBgRnVuY3Rpb25gLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIExhbWJkYUZ1bmN0aW9uT3B0aW9ucyBleHRlbmRzIExhbWJkYUZ1bmN0aW9uQ29tbW9uT3B0aW9ucyB7XG4gIC8qKlxuICAgKiBBIHBhdGggZnJvbSB0aGUgcHJvamVjdCByb290IGRpcmVjdG9yeSB0byBhIFR5cGVTY3JpcHQgZmlsZSB3aGljaCBjb250YWluc1xuICAgKiB0aGUgQVdTIExhbWJkYSBoYW5kbGVyIGVudHJ5cG9pbnQgKGV4cG9ydHMgYSBgaGFuZGxlcmAgZnVuY3Rpb24pLlxuICAgKlxuICAgKiBUaGlzIGlzIHJlbGF0aXZlIHRvIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGUgcHJvamVjdC5cbiAgICpcbiAgICogQGV4YW1wbGUgXCJzcmMvc3ViZGlyL2Zvby5sYW1iZGEudHNcIlxuICAgKi9cbiAgcmVhZG9ubHkgZW50cnlwb2ludDogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBUaGUgbmFtZSBvZiB0aGUgZ2VuZXJhdGVkIFR5cGVTY3JpcHQgc291cmNlIGZpbGUuIFRoaXMgZmlsZSBzaG91bGQgYWxzbyBiZVxuICAgKiB1bmRlciB0aGUgc291cmNlIHRyZWUuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gVGhlIG5hbWUgb2YgdGhlIGVudHJ5cG9pbnQgZmlsZSwgd2l0aCB0aGUgYC1mdW5jdGlvbi50c2Agc3VmZml4XG4gICAqIGluc3RlYWQgb2YgYC5sYW1iZGEudHNgLlxuICAgKi9cbiAgcmVhZG9ubHkgY29uc3RydWN0RmlsZT86IHN0cmluZztcblxuICAvKipcbiAgICogVGhlIG5hbWUgb2YgdGhlIGdlbmVyYXRlZCBgbGFtYmRhLkZ1bmN0aW9uYCBzdWJjbGFzcy5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBBIHBhc2NhbCBjYXNlZCB2ZXJzaW9uIG9mIHRoZSBuYW1lIG9mIHRoZSBlbnRyeXBvaW50IGZpbGUsIHdpdGhcbiAgICogdGhlIGV4dGVuc2lvbiBgRnVuY3Rpb25gIChlLmcuIGBSZXNpemVJbWFnZUZ1bmN0aW9uYCkuXG4gICAqL1xuICByZWFkb25seSBjb25zdHJ1Y3ROYW1lPzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBBV1MgQ0RLIGRlcGVuZGVuY3kgbWFuYWdlci5cbiAgICovXG4gIHJlYWRvbmx5IGNka0RlcHM6IEF3c0Nka0RlcHM7XG59XG5cbi8qKlxuICogR2VuZXJhdGVzIGEgcHJlLWJ1bmRsZWQgQVdTIExhbWJkYSBmdW5jdGlvbiBjb25zdHJ1Y3QgZnJvbSBoYW5kbGVyIGNvZGUuXG4gKlxuICogVG8gdXNlIHRoaXMsIGNyZWF0ZSBhbiBBV1MgTGFtYmRhIGhhbmRsZXIgZmlsZSB1bmRlciB5b3VyIHNvdXJjZSB0cmVlIHdpdGhcbiAqIHRoZSBgLmxhbWJkYS50c2AgZXh0ZW5zaW9uIGFuZCBhZGQgYSBgTGFtYmRhRnVuY3Rpb25gIGNvbXBvbmVudCB0byB5b3VyXG4gKiB0eXBlc2NyaXB0IHByb2plY3QgcG9pbnRpbmcgdG8gdGhpcyBlbnRyeXBvaW50LlxuICpcbiAqIFRoaXMgd2lsbCBhZGQgYSB0YXNrIHRvIHlvdXIgXCJjb21waWxlXCIgc3RlcCB3aGljaCB3aWxsIHVzZSBgZXNidWlsZGAgdG9cbiAqIGJ1bmRsZSB0aGUgaGFuZGxlciBjb2RlIGludG8gdGhlIGJ1aWxkIGRpcmVjdG9yeS4gSXQgd2lsbCBhbHNvIGdlbmVyYXRlIGFcbiAqIGZpbGUgYHNyYy9mb28tZnVuY3Rpb24udHNgIHdpdGggYSBjdXN0b20gQVdTIGNvbnN0cnVjdCBjYWxsZWQgYEZvb0Z1bmN0aW9uYFxuICogd2hpY2ggZXh0ZW5kcyBgQGF3cy1jZGsvYXdzLWxhbWJkYS5GdW5jdGlvbmAgd2hpY2ggaXMgYm91bmQgdG8gdGhlIGJ1bmRsZWRcbiAqIGhhbmRsZSB0aHJvdWdoIGFuIGFzc2V0LlxuICpcbiAqIEBleGFtcGxlXG4gKlxuICogbmV3IExhbWJkYUZ1bmN0aW9uKG15UHJvamVjdCwge1xuICogICBzcmNkaXI6IG15UHJvamVjdC5zcmNkaXIsXG4gKiAgIGVudHJ5cG9pbnQ6ICdzcmMvZm9vLmxhbWJkYS50cycsXG4gKiB9KTtcbiAqL1xuZXhwb3J0IGNsYXNzIExhbWJkYUZ1bmN0aW9uIGV4dGVuZHMgQ29tcG9uZW50IHtcbiAgLyoqXG4gICAqIERlZmluZXMgYSBwcmUtYnVuZGxlZCBBV1MgTGFtYmRhIGZ1bmN0aW9uIGNvbnN0cnVjdCBmcm9tIGhhbmRsZXIgY29kZS5cbiAgICpcbiAgICogQHBhcmFtIHByb2plY3QgVGhlIHByb2plY3QgdG8gdXNlXG4gICAqIEBwYXJhbSBvcHRpb25zIE9wdGlvbnNcbiAgICovXG4gIGNvbnN0cnVjdG9yKHByb2plY3Q6IFByb2plY3QsIG9wdGlvbnM6IExhbWJkYUZ1bmN0aW9uT3B0aW9ucykge1xuICAgIHN1cGVyKHByb2plY3QpO1xuXG4gICAgY29uc3QgY2RrRGVwcyA9IG9wdGlvbnMuY2RrRGVwcztcbiAgICBjb25zdCBidW5kbGVyID0gQnVuZGxlci5vZihwcm9qZWN0KTtcbiAgICBpZiAoIWJ1bmRsZXIpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgXCJObyBidW5kbGVyIGZvdW5kLiBQbGVhc2UgYWRkIGEgQnVuZGxlciBjb21wb25lbnQgdG8geW91ciBwcm9qZWN0LlwiXG4gICAgICApO1xuICAgIH1cblxuICAgIC8vIFVzZSBOT0RFSlNfUkVHSU9OQUxfTEFURVNUIGFzIGRlZmF1bHQsIHdoaWNoIGdlbmVyYXRlcyBkZXRlcm1pbmVMYXRlc3ROb2RlUnVudGltZSgpXG4gICAgY29uc3QgcnVudGltZSA9IG9wdGlvbnMucnVudGltZSA/PyBMYW1iZGFSdW50aW1lLk5PREVKU19SRUdJT05BTF9MQVRFU1Q7XG5cbiAgICBjb25zdCBlbnRyeXBvaW50ID0gbm9ybWFsaXplUGVyc2lzdGVkUGF0aChvcHRpb25zLmVudHJ5cG9pbnQpO1xuXG4gICAgLy8gYWxsb3cgTGFtYmRhIGhhbmRsZXIgY29kZSB0byBpbXBvcnQgZGV2LWRlcHMgc2luY2UgdGhleSBhcmUgb25seSBuZWVkZWRcbiAgICAvLyBkdXJpbmcgYnVuZGxpbmdcbiAgICBjb25zdCBlc2xpbnQgPSBFc2xpbnQub2YocHJvamVjdCk7XG4gICAgZXNsaW50Py5hbGxvd0RldkRlcHMoZW50cnlwb2ludCk7XG5cbiAgICBpZiAoXG4gICAgICAhZW50cnlwb2ludC5lbmRzV2l0aChUWVBFU0NSSVBUX0xBTUJEQV9FWFQpICYmXG4gICAgICAhZW50cnlwb2ludC5lbmRzV2l0aChUWVBFU0NSSVBUX0VER0VfTEFNQkRBX0VYVClcbiAgICApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgYCR7ZW50cnlwb2ludH0gbXVzdCBoYXZlIGEgJHtUWVBFU0NSSVBUX0xBTUJEQV9FWFR9IG9yICR7VFlQRVNDUklQVF9FREdFX0xBTUJEQV9FWFR9IGV4dGVuc2lvbmBcbiAgICAgICk7XG4gICAgfVxuXG4gICAgY29uc3QgYmFzZVBhdGggPSBwYXRoLnBvc2l4LmpvaW4oXG4gICAgICBwYXRoLmRpcm5hbWUoZW50cnlwb2ludCksXG4gICAgICBwYXRoLmJhc2VuYW1lKFxuICAgICAgICBlbnRyeXBvaW50LFxuICAgICAgICBvcHRpb25zLmVkZ2VMYW1iZGEgPyBUWVBFU0NSSVBUX0VER0VfTEFNQkRBX0VYVCA6IFRZUEVTQ1JJUFRfTEFNQkRBX0VYVFxuICAgICAgKVxuICAgICk7XG4gICAgY29uc3QgY29uc3RydWN0RmlsZSA9IG9wdGlvbnMuY29uc3RydWN0RmlsZSA/PyBgJHtiYXNlUGF0aH0tZnVuY3Rpb24udHNgO1xuXG4gICAgaWYgKHBhdGguZXh0bmFtZShjb25zdHJ1Y3RGaWxlKSAhPT0gXCIudHNcIikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgQ29uc3RydWN0IGZpbGUgbmFtZSBcIiR7Y29uc3RydWN0RmlsZX1cIiBtdXN0IGhhdmUgYSAudHMgZXh0ZW5zaW9uYFxuICAgICAgKTtcbiAgICB9XG5cbiAgICAvLyB0eXBlIG5hbWVzXG4gICAgY29uc3QgY29uc3RydWN0TmFtZSA9XG4gICAgICBvcHRpb25zLmNvbnN0cnVjdE5hbWUgPz8gcGFzY2FsKHBhdGguYmFzZW5hbWUoYmFzZVBhdGgpKSArIFwiRnVuY3Rpb25cIjtcbiAgICBjb25zdCBwcm9wc1R5cGUgPSBgJHtjb25zdHJ1Y3ROYW1lfVByb3BzYDtcblxuICAgIGNvbnN0IGJ1bmRsZSA9IGJ1bmRsZXIuYWRkQnVuZGxlKGVudHJ5cG9pbnQsIHtcbiAgICAgIHRhcmdldDogcnVudGltZS5lc2J1aWxkVGFyZ2V0LFxuICAgICAgcGxhdGZvcm06IHJ1bnRpbWUuZXNidWlsZFBsYXRmb3JtLFxuICAgICAgZXh0ZXJuYWxzOiBydW50aW1lLmRlZmF1bHRFeHRlcm5hbHMsXG4gICAgICAuLi5vcHRpb25zLmJ1bmRsaW5nT3B0aW9ucyxcbiAgICAgIHRzY29uZmlnUGF0aDogKHByb2plY3QgYXMgVHlwZVNjcmlwdFByb2plY3QpPy50c2NvbmZpZ0Rldj8uZmlsZU5hbWUsXG4gICAgfSk7XG5cbiAgICAvLyBjYWxjdWxhdGUgdGhlIHJlbGF0aXZlIHBhdGggYmV0d2VlbiB0aGUgZGlyZWN0b3J5IGNvbnRhaW5pbmcgdGhlXG4gICAgLy8gZ2VuZXJhdGVkIGNvbnN0cnVjdCBzb3VyY2UgZmlsZSB0byB0aGUgZGlyZWN0b3J5IGNvbnRhaW5pbmcgdGhlIGJ1bmRsZVxuICAgIC8vIGluZGV4LmpzIGJ5IHJlc29sdmluZyB0aGVtIGFzIGFic29sdXRlIHBhdGhzIGZpcnN0LlxuICAgIC8vIGUuZzpcbiAgICAvLyAgLSBvdXRmaWxlQWJzID0+IGAvcHJvamVjdC1vdXRkaXIvYXNzZXRzL2Zvby9iYXIvYmF6L2Zvby1mdW5jdGlvbi9pbmRleC5qc2BcbiAgICAvLyAgLSBjb25zdHJ1Y3RBYnMgPT4gYC9wcm9qZWN0LW91dGRpci9zcmMvZm9vL2Jhci9iYXovZm9vLWZ1bmN0aW9uLnRzYFxuICAgIGNvbnN0IG91dGZpbGVBYnMgPSBwYXRoLmpvaW4ocHJvamVjdC5vdXRkaXIsIGJ1bmRsZS5vdXRmaWxlKTtcbiAgICBjb25zdCBjb25zdHJ1Y3RBYnMgPSBwYXRoLmpvaW4ocHJvamVjdC5vdXRkaXIsIGNvbnN0cnVjdEZpbGUpO1xuICAgIGNvbnN0IHJlbGF0aXZlT3V0ZmlsZSA9IHBhdGgucmVsYXRpdmUoXG4gICAgICBwYXRoLmRpcm5hbWUoY29uc3RydWN0QWJzKSxcbiAgICAgIHBhdGguZGlybmFtZShvdXRmaWxlQWJzKVxuICAgICk7XG5cbiAgICBjb25zdCBzcmMgPSBuZXcgU291cmNlQ29kZShwcm9qZWN0LCBjb25zdHJ1Y3RGaWxlKTtcbiAgICBpZiAoc3JjLm1hcmtlcikge1xuICAgICAgc3JjLmxpbmUoYC8vICR7c3JjLm1hcmtlcn1gKTtcbiAgICB9XG4gICAgc3JjLmxpbmUoXCJpbXBvcnQgKiBhcyBwYXRoIGZyb20gJ3BhdGgnO1wiKTtcblxuICAgIGlmIChjZGtEZXBzLmNka01ham9yVmVyc2lvbiA9PT0gMSkge1xuICAgICAgaWYgKG9wdGlvbnMuZWRnZUxhbWJkYSkge1xuICAgICAgICBzcmMubGluZShcImltcG9ydCAqIGFzIGNsb3VkZnJvbnQgZnJvbSAnQGF3cy1jZGsvYXdzLWNsb3VkZnJvbnQnO1wiKTtcbiAgICAgICAgY2RrRGVwcy5hZGRWMURlcGVuZGVuY2llcyhcIkBhd3MtY2RrL2F3cy1jbG91ZGZyb250XCIpO1xuICAgICAgfVxuICAgICAgc3JjLmxpbmUoXCJpbXBvcnQgKiBhcyBsYW1iZGEgZnJvbSAnQGF3cy1jZGsvYXdzLWxhbWJkYSc7XCIpO1xuICAgICAgc3JjLmxpbmUoXCJpbXBvcnQgeyBDb25zdHJ1Y3QgfSBmcm9tICdAYXdzLWNkay9jb3JlJztcIik7XG4gICAgICBjZGtEZXBzLmFkZFYxRGVwZW5kZW5jaWVzKFwiQGF3cy1jZGsvYXdzLWxhbWJkYVwiKTtcbiAgICAgIGNka0RlcHMuYWRkVjFEZXBlbmRlbmNpZXMoXCJAYXdzLWNkay9jb3JlXCIpO1xuICAgIH0gZWxzZSB7XG4gICAgICBpZiAob3B0aW9ucy5lZGdlTGFtYmRhKSB7XG4gICAgICAgIHNyYy5saW5lKFwiaW1wb3J0ICogYXMgY2xvdWRmcm9udCBmcm9tICdhd3MtY2RrLWxpYi9hd3MtY2xvdWRmcm9udCc7XCIpO1xuICAgICAgfVxuICAgICAgc3JjLmxpbmUoXCJpbXBvcnQgKiBhcyBsYW1iZGEgZnJvbSAnYXdzLWNkay1saWIvYXdzLWxhbWJkYSc7XCIpO1xuICAgICAgLy8gSW1wb3J0IGRldGVybWluZUxhdGVzdE5vZGVSdW50aW1lIGlmIHVzaW5nIE5PREVKU19SRUdJT05BTF9MQVRFU1RcbiAgICAgIGlmIChydW50aW1lID09PSBMYW1iZGFSdW50aW1lLk5PREVKU19SRUdJT05BTF9MQVRFU1QpIHtcbiAgICAgICAgc3JjLmxpbmUoXG4gICAgICAgICAgXCJpbXBvcnQgeyBkZXRlcm1pbmVMYXRlc3ROb2RlUnVudGltZSB9IGZyb20gJ2F3cy1jZGstbGliL2F3cy1sYW1iZGEnO1wiXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgICBzcmMubGluZShcImltcG9ydCB7IENvbnN0cnVjdCB9IGZyb20gJ2NvbnN0cnVjdHMnO1wiKTtcbiAgICB9XG5cbiAgICBzcmMubGluZSgpO1xuICAgIHNyYy5saW5lKFwiLyoqXCIpO1xuICAgIHNyYy5saW5lKGAgKiBQcm9wcyBmb3IgJHtjb25zdHJ1Y3ROYW1lfWApO1xuICAgIHNyYy5saW5lKFwiICovXCIpO1xuICAgIGlmIChvcHRpb25zLmVkZ2VMYW1iZGEpIHtcbiAgICAgIHNyYy5vcGVuKFxuICAgICAgICBgZXhwb3J0IGludGVyZmFjZSAke3Byb3BzVHlwZX0gZXh0ZW5kcyBjbG91ZGZyb250LmV4cGVyaW1lbnRhbC5FZGdlRnVuY3Rpb25Qcm9wcyB7YFxuICAgICAgKTtcbiAgICB9IGVsc2Uge1xuICAgICAgc3JjLm9wZW4oXG4gICAgICAgIGBleHBvcnQgaW50ZXJmYWNlICR7cHJvcHNUeXBlfSBleHRlbmRzIGxhbWJkYS5GdW5jdGlvbk9wdGlvbnMge2BcbiAgICAgICk7XG4gICAgfVxuICAgIC8vIEFkZCBydW50aW1lIHByb3AgdG8gaW50ZXJmYWNlIG9ubHkgd2hlbiBydW50aW1lIGlzIG5vdCBleHBsaWNpdGx5IHNldFxuICAgIC8vIFRoaXMgYWxsb3dzIGNvbnN1bWVycyB0byBvdmVycmlkZSB0aGUgZGVmYXVsdCBOT0RFSlNfUkVHSU9OQUxfTEFURVNUXG4gICAgaWYgKCFvcHRpb25zLnJ1bnRpbWUpIHtcbiAgICAgIHNyYy5saW5lKFwiLyoqXCIpO1xuICAgICAgc3JjLmxpbmUoXCIgKiBUaGUgTGFtYmRhIHJ1bnRpbWUgdG8gdXNlLlwiKTtcbiAgICAgIHNyYy5saW5lKFxuICAgICAgICBcIiAqIEBkZWZhdWx0IC0gTGF0ZXN0IE5vZGUuanMgcnVudGltZSBhdmFpbGFibGUgaW4gdGhlIGRlcGxveW1lbnQgcmVnaW9uXCJcbiAgICAgICk7XG4gICAgICBzcmMubGluZShcIiAqL1wiKTtcbiAgICAgIHNyYy5saW5lKFwicmVhZG9ubHkgcnVudGltZT86IGxhbWJkYS5SdW50aW1lO1wiKTtcbiAgICB9XG4gICAgc3JjLmNsb3NlKFwifVwiKTtcbiAgICBzcmMubGluZSgpO1xuICAgIHNyYy5saW5lKFwiLyoqXCIpO1xuICAgIHNyYy5saW5lKFxuICAgICAgYCAqIEFuIEFXUyBMYW1iZGEgZnVuY3Rpb24gd2hpY2ggZXhlY3V0ZXMgJHtjb252ZXJ0VG9Qb3NpeFBhdGgoXG4gICAgICAgIGJhc2VQYXRoXG4gICAgICApfS5gXG4gICAgKTtcbiAgICBzcmMubGluZShcIiAqL1wiKTtcbiAgICBpZiAob3B0aW9ucy5lZGdlTGFtYmRhKSB7XG4gICAgICBzcmMub3BlbihcbiAgICAgICAgYGV4cG9ydCBjbGFzcyAke2NvbnN0cnVjdE5hbWV9IGV4dGVuZHMgY2xvdWRmcm9udC5leHBlcmltZW50YWwuRWRnZUZ1bmN0aW9uIHtgXG4gICAgICApO1xuICAgIH0gZWxzZSB7XG4gICAgICBzcmMub3BlbihgZXhwb3J0IGNsYXNzICR7Y29uc3RydWN0TmFtZX0gZXh0ZW5kcyBsYW1iZGEuRnVuY3Rpb24ge2ApO1xuICAgIH1cbiAgICBzcmMub3BlbihcbiAgICAgIGBjb25zdHJ1Y3RvcihzY29wZTogQ29uc3RydWN0LCBpZDogc3RyaW5nLCBwcm9wcz86ICR7cHJvcHNUeXBlfSkge2BcbiAgICApO1xuICAgIHNyYy5vcGVuKFwic3VwZXIoc2NvcGUsIGlkLCB7XCIpO1xuICAgIHNyYy5saW5lKGBkZXNjcmlwdGlvbjogJyR7Y29udmVydFRvUG9zaXhQYXRoKGVudHJ5cG9pbnQpfScsYCk7XG4gICAgc3JjLmxpbmUoXCIuLi5wcm9wcyxcIik7XG5cbiAgICAvLyBHZW5lcmF0ZSBydW50aW1lIGNvZGVcbiAgICBpZiAocnVudGltZSA9PT0gTGFtYmRhUnVudGltZS5OT0RFSlNfUkVHSU9OQUxfTEFURVNUKSB7XG4gICAgICAvLyBSZWdpb25hbCBsYXRlc3QgcnVudGltZVxuICAgICAgaWYgKCFvcHRpb25zLnJ1bnRpbWUpIHtcbiAgICAgICAgLy8gRGVmYXVsdCAobm90IGV4cGxpY2l0bHkgc2V0KSAtIGFsbG93IGNvbnN1bWVyIG92ZXJyaWRlXG4gICAgICAgIHNyYy5saW5lKFxuICAgICAgICAgIFwicnVudGltZTogcHJvcHM/LnJ1bnRpbWUgPz8gZGV0ZXJtaW5lTGF0ZXN0Tm9kZVJ1bnRpbWUoc2NvcGUpLFwiXG4gICAgICAgICk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvLyBFeHBsaWNpdGx5IHNldCAtIG5vIG92ZXJyaWRlXG4gICAgICAgIHNyYy5saW5lKFwicnVudGltZTogZGV0ZXJtaW5lTGF0ZXN0Tm9kZVJ1bnRpbWUoc2NvcGUpLFwiKTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgLy8gRXhwbGljaXQgcnVudGltZSAtIGhhcmRjb2RlZCwgbm8gb3ZlcnJpZGVcbiAgICAgIHNyYy5saW5lKFxuICAgICAgICBgcnVudGltZTogbmV3IGxhbWJkYS5SdW50aW1lKCcke3J1bnRpbWUuZnVuY3Rpb25SdW50aW1lfScsIGxhbWJkYS5SdW50aW1lRmFtaWx5Lk5PREVKUyksYFxuICAgICAgKTtcbiAgICB9XG5cbiAgICBzcmMubGluZShcImhhbmRsZXI6ICdpbmRleC5oYW5kbGVyJyxcIik7XG4gICAgc3JjLmxpbmUoXG4gICAgICBgY29kZTogbGFtYmRhLkNvZGUuZnJvbUFzc2V0KHBhdGguam9pbihfX2Rpcm5hbWUsICcke2NvbnZlcnRUb1Bvc2l4UGF0aChcbiAgICAgICAgcmVsYXRpdmVPdXRmaWxlXG4gICAgICApfScpKSxgXG4gICAgKTtcbiAgICBzcmMuY2xvc2UoXCJ9KTtcIik7XG4gICAgaWYgKChvcHRpb25zLmF3c1Nka0Nvbm5lY3Rpb25SZXVzZSA/PyB0cnVlKSAmJiAhb3B0aW9ucy5lZGdlTGFtYmRhKSB7XG4gICAgICBzcmMubGluZShcbiAgICAgICAgXCJ0aGlzLmFkZEVudmlyb25tZW50KCdBV1NfTk9ERUpTX0NPTk5FQ1RJT05fUkVVU0VfRU5BQkxFRCcsICcxJywgeyByZW1vdmVJbkVkZ2U6IHRydWUgfSk7XCJcbiAgICAgICk7XG4gICAgfVxuICAgIHNyYy5jbG9zZShcIn1cIik7XG4gICAgc3JjLmNsb3NlKFwifVwiKTtcblxuICAgIHRoaXMucHJvamVjdC5sb2dnZXIudmVyYm9zZShcbiAgICAgIGAke2Jhc2VQYXRofTogY29uc3RydWN0IFwiJHtjb25zdHJ1Y3ROYW1lfVwiIGdlbmVyYXRlZCB1bmRlciBcIiR7Y29uc3RydWN0RmlsZX1cImBcbiAgICApO1xuICAgIHRoaXMucHJvamVjdC5sb2dnZXIudmVyYm9zZShcbiAgICAgIGAke2Jhc2VQYXRofTogYnVuZGxlIHRhc2sgXCIke2J1bmRsZS5idW5kbGVUYXNrLm5hbWV9XCJgXG4gICAgKTtcbiAgICBpZiAoYnVuZGxlLndhdGNoVGFzaykge1xuICAgICAgdGhpcy5wcm9qZWN0LmxvZ2dlci52ZXJib3NlKFxuICAgICAgICBgJHtiYXNlUGF0aH06IGJ1bmRsZSB3YXRjaCB0YXNrIFwiJHtidW5kbGUud2F0Y2hUYXNrLm5hbWV9XCJgXG4gICAgICApO1xuICAgIH1cbiAgfVxufVxuXG4vKipcbiAqIE9wdGlvbnMgZm9yIHRoZSBBV1MgTGFtYmRhIGZ1bmN0aW9uIHJ1bnRpbWVcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBMYW1iZGFSdW50aW1lT3B0aW9ucyB7XG4gIC8qKlxuICAgKiBQYWNrYWdlcyB0aGF0IGFyZSBjb25zaWRlcmVkIGV4dGVybmFscyBieSBkZWZhdWx0IHdoZW4gYnVuZGxpbmdcbiAgICpcbiAgICogQGRlZmF1bHQgWydAYXdzLXNkay8qJ11cbiAgICovXG4gIHJlYWRvbmx5IGRlZmF1bHRFeHRlcm5hbHM/OiBzdHJpbmdbXTtcbn1cblxuLyoqXG4gKiBUaGUgcnVudGltZSBmb3IgdGhlIEFXUyBMYW1iZGEgZnVuY3Rpb24uXG4gKi9cbmV4cG9ydCBjbGFzcyBMYW1iZGFSdW50aW1lIHtcbiAgLyoqXG4gICAqIE5vZGUuanMgMTAueFxuICAgKiBAZGVwcmVjYXRlZCBOb2RlLmpzIDEwIHJ1bnRpbWUgaGFzIGJlZW4gZGVwcmVjYXRlZCBvbiBKdWwgMzAsIDIwMjFcbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgcmVhZG9ubHkgTk9ERUpTXzEwX1ggPSBuZXcgTGFtYmRhUnVudGltZShcbiAgICBcIm5vZGVqczEwLnhcIixcbiAgICBcIm5vZGUxMFwiLFxuICAgIHsgZGVmYXVsdEV4dGVybmFsczogW1wiYXdzLXNka1wiXSB9XG4gICk7XG5cbiAgLyoqXG4gICAqIE5vZGUuanMgMTIueFxuICAgKiBAZGVwcmVjYXRlZCBOb2RlLmpzIDEyIHJ1bnRpbWUgaGFzIGJlZW4gZGVwcmVjYXRlZCBvbiBNYXIgMzEsIDIwMjNcbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgcmVhZG9ubHkgTk9ERUpTXzEyX1ggPSBuZXcgTGFtYmRhUnVudGltZShcbiAgICBcIm5vZGVqczEyLnhcIixcbiAgICBcIm5vZGUxMlwiLFxuICAgIHsgZGVmYXVsdEV4dGVybmFsczogW1wiYXdzLXNka1wiXSB9XG4gICk7XG5cbiAgLyoqXG4gICAqIE5vZGUuanMgMTQueFxuICAgKiBAZGVwcmVjYXRlZCBOb2RlLmpzIDE0IHJ1bnRpbWUgaGFzIGJlZW4gZGVwcmVjYXRlZCBvbiBEZWMgNCwgMjAyM1xuICAgKi9cbiAgcHVibGljIHN0YXRpYyByZWFkb25seSBOT0RFSlNfMTRfWCA9IG5ldyBMYW1iZGFSdW50aW1lKFxuICAgIFwibm9kZWpzMTQueFwiLFxuICAgIFwibm9kZTE0XCIsXG4gICAgeyBkZWZhdWx0RXh0ZXJuYWxzOiBbXCJhd3Mtc2RrXCJdIH1cbiAgKTtcblxuICAvKipcbiAgICogTm9kZS5qcyAxNi54XG4gICAqIEBkZXByZWNhdGVkIE5vZGUuanMgMTYgcnVudGltZSBoYXMgYmVlbiBkZXByZWNhdGVkIG9uIEp1biAxMiwgMjAyNFxuICAgKi9cbiAgcHVibGljIHN0YXRpYyByZWFkb25seSBOT0RFSlNfMTZfWCA9IG5ldyBMYW1iZGFSdW50aW1lKFxuICAgIFwibm9kZWpzMTYueFwiLFxuICAgIFwibm9kZTE2XCIsXG4gICAgeyBkZWZhdWx0RXh0ZXJuYWxzOiBbXCJhd3Mtc2RrXCJdIH1cbiAgKTtcblxuICAvKipcbiAgICogTm9kZS5qcyAxOC54XG4gICAqXG4gICAqIEBkZXByZWNhdGVkOiBOb2RlLmpzIDE4IHJ1bnRpbWUgaGFzIGJlZW4gZGVwcmVjYXRlZCBvbiBTZXAgMSwgMjAyNVxuICAgKi9cbiAgcHVibGljIHN0YXRpYyByZWFkb25seSBOT0RFSlNfMThfWCA9IG5ldyBMYW1iZGFSdW50aW1lKFxuICAgIFwibm9kZWpzMTgueFwiLFxuICAgIFwibm9kZTE4XCJcbiAgKTtcblxuICAvKipcbiAgICogTm9kZS5qcyAyMC54XG4gICAqL1xuICBwdWJsaWMgc3RhdGljIHJlYWRvbmx5IE5PREVKU18yMF9YID0gbmV3IExhbWJkYVJ1bnRpbWUoXG4gICAgXCJub2RlanMyMC54XCIsXG4gICAgXCJub2RlMjBcIlxuICApO1xuXG4gIC8qKlxuICAgKiBOb2RlLmpzIDIyLnhcbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgcmVhZG9ubHkgTk9ERUpTXzIyX1ggPSBuZXcgTGFtYmRhUnVudGltZShcbiAgICBcIm5vZGVqczIyLnhcIixcbiAgICBcIm5vZGUyMlwiXG4gICk7XG5cbiAgLyoqXG4gICAqIE5vZGUuanMgMjQueFxuICAgKi9cbiAgcHVibGljIHN0YXRpYyByZWFkb25seSBOT0RFSlNfMjRfWCA9IG5ldyBMYW1iZGFSdW50aW1lKFxuICAgIFwibm9kZWpzMjQueFwiLFxuICAgIFwibm9kZTI0XCJcbiAgKTtcblxuICAvKipcbiAgICogVXNlIHRoZSBsYXRlc3QgTm9kZS5qcyBydW50aW1lIGF2YWlsYWJsZSBpbiB0aGUgZGVwbG95bWVudCByZWdpb24uXG4gICAqXG4gICAqIFRoaXMgZ2VuZXJhdGVzIGNvZGUgdGhhdCB1c2VzIGBkZXRlcm1pbmVMYXRlc3ROb2RlUnVudGltZSgpYCBhdCBDREsgc3ludGhlc2lzIHRpbWUsXG4gICAqIHdoaWNoIGR5bmFtaWNhbGx5IHNlbGVjdHMgdGhlIGxhdGVzdCBOb2RlLmpzIHJ1bnRpbWUgYXZhaWxhYmxlIGJhc2VkIG9uIHJlZ2lvbmFsXG4gICAqIGF2YWlsYWJpbGl0eS4gVGhpcyBlbGltaW5hdGVzIHRoZSBuZWVkIHRvIG1hbnVhbGx5IHVwZGF0ZSBydW50aW1lIHZlcnNpb25zIGFuZFxuICAgKiBhdm9pZHMgRU9MIHdhcm5pbmdzLlxuICAgKlxuICAgKiBAZGVmYXVsdCBVc2VzIGRldGVybWluZUxhdGVzdE5vZGVSdW50aW1lKCkgZnJvbSBhd3MtY2RrLWxpYlxuICAgKi9cbiAgcHVibGljIHN0YXRpYyByZWFkb25seSBOT0RFSlNfUkVHSU9OQUxfTEFURVNUID0gbmV3IExhbWJkYVJ1bnRpbWUoXG4gICAgXCJOT0RFSlNfUkVHSU9OQUxfTEFURVNUXCIsIC8vIE1hcmtlciB2YWx1ZVxuICAgIFwibm9kZTIyXCIgLy8gZXNidWlsZCB0YXJnZXQgKGN1cnJlbnQgTFRTKVxuICApO1xuXG4gIHB1YmxpYyByZWFkb25seSBlc2J1aWxkUGxhdGZvcm0gPSBcIm5vZGVcIjtcblxuICBwdWJsaWMgcmVhZG9ubHkgZGVmYXVsdEV4dGVybmFsczogc3RyaW5nW107XG5cbiAgcHVibGljIGNvbnN0cnVjdG9yKFxuICAgIC8qKlxuICAgICAqIFRoZSBOb2RlLmpzIHJ1bnRpbWUgdG8gdXNlXG4gICAgICovXG4gICAgcHVibGljIHJlYWRvbmx5IGZ1bmN0aW9uUnVudGltZTogc3RyaW5nLFxuXG4gICAgLyoqXG4gICAgICogVGhlIGVzYnVpbGQgc2V0dGluZyB0byB1c2UuXG4gICAgICovXG4gICAgcHVibGljIHJlYWRvbmx5IGVzYnVpbGRUYXJnZXQ6IHN0cmluZyxcblxuICAgIC8qKlxuICAgICAqIE9wdGlvbnMgZm9yIHRoaXMgcnVudGltZS5cbiAgICAgKi9cbiAgICBvcHRpb25zPzogTGFtYmRhUnVudGltZU9wdGlvbnNcbiAgKSB7XG4gICAgdGhpcy5kZWZhdWx0RXh0ZXJuYWxzID0gb3B0aW9ucz8uZGVmYXVsdEV4dGVybmFscyA/PyBbXCJAYXdzLXNkay8qXCJdO1xuICB9XG59XG4iXX0=