UNPKG

projen

Version:

CDK for software projects

283 lines • 41 kB
"use strict"; 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=