UNPKG

projen

Version:

CDK for software projects

273 lines • 42.7 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) && !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 (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 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; _a = JSII_RTTI_SYMBOL_1; LambdaFunction[_a] = { fqn: "projen.awscdk.LambdaFunction", version: "0.99.51" }; /** * 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.51" }; /** * 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"); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGFtYmRhLWZ1bmN0aW9uLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2F3c2Nkay9sYW1iZGEtZnVuY3Rpb24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFBQSw2QkFBNkI7QUFDN0IsK0JBQThCO0FBRTlCLHlDQUtvQjtBQUNwQiw0Q0FBeUM7QUFFekMsOENBQWdEO0FBRWhELGdEQUE0QztBQUU1QyxrQ0FBaUQ7QUE0R2pEOzs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBbUJHO0FBQ0gsTUFBYSxjQUFlLFNBQVEscUJBQVM7SUFDM0M7Ozs7O09BS0c7SUFDSCxZQUFZLE9BQWdCLEVBQUUsT0FBOEI7UUFDMUQsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBRWYsTUFBTSxPQUFPLEdBQUcsT0FBTyxDQUFDLE9BQU8sQ0FBQztRQUNoQyxNQUFNLE9BQU8sR0FBRyxvQkFBTyxDQUFDLEVBQUUsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUNwQyxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUM7WUFDYixNQUFNLElBQUksS0FBSyxDQUNiLG1FQUFtRSxDQUNwRSxDQUFDO1FBQ0osQ0FBQztRQUVELHNGQUFzRjtRQUN0RixNQUFNLE9BQU8sR0FBRyxPQUFPLENBQUMsT0FBTyxJQUFJLGFBQWEsQ0FBQyxzQkFBc0IsQ0FBQztRQUV4RSxNQUFNLFVBQVUsR0FBRyxJQUFBLDZCQUFzQixFQUFDLE9BQU8sQ0FBQyxVQUFVLENBQUMsQ0FBQztRQUU5RCwwRUFBMEU7UUFDMUUsa0JBQWtCO1FBQ2xCLE1BQU0sTUFBTSxHQUFHLG1CQUFNLENBQUMsRUFBRSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQ2xDLE1BQU0sRUFBRSxZQUFZLENBQUMsVUFBVSxDQUFDLENBQUM7UUFFakMsSUFDRSxDQUFDLFVBQVUsQ0FBQyxRQUFRLENBQUMsZ0NBQXFCLENBQUM7WUFDM0MsQ0FBQyxVQUFVLENBQUMsUUFBUSxDQUFDLHFDQUEwQixDQUFDO1lBQ2hELENBQUMs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O0FBQ29CLG9DQUFzQixHQUFHLElBQUksYUFBYSxDQUMvRCx3QkFBd0IsRUFBRSxlQUFlO0FBQ3pDLFFBQVEsQ0FDVCxBQUg0QyxDQUczQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAqIGFzIHBhdGggZnJvbSBcInBhdGhcIjtcbmltcG9ydCB7IHBhc2NhbCB9IGZyb20gXCJjYXNlXCI7XG5pbXBvcnQgdHlwZSB7IEF3c0Nka0RlcHMgfSBmcm9tIFwiLi9hd3NjZGstZGVwc1wiO1xuaW1wb3J0IHtcbiAgY29udmVydFRvUG9zaXhQYXRoLFxuICBUWVBFU0NSSVBUX0VER0VfTEFNQkRBX0VYVCxcbiAgVFlQRVNDUklQVF9MQU1CREFfRVhULFxuICBUWVBFU0NSSVBUX1NJTkdMRVRPTl9MQU1CREFfRVhULFxufSBmcm9tIFwiLi9pbnRlcm5hbFwiO1xuaW1wb3J0IHsgQ29tcG9uZW50IH0gZnJvbSBcIi4uL2NvbXBvbmVudFwiO1xuaW1wb3J0IHR5cGUgeyBCdW5kbGluZ09wdGlvbnMgfSBmcm9tIFwiLi4vamF2YXNjcmlwdFwiO1xuaW1wb3J0IHsgQnVuZGxlciwgRXNsaW50IH0gZnJvbSBcIi4uL2phdmFzY3JpcHRcIjtcbmltcG9ydCB0eXBlIHsgUHJvamVjdCB9IGZyb20gXCIuLi9wcm9qZWN0XCI7XG5pbXBvcnQgeyBTb3VyY2VDb2RlIH0gZnJvbSBcIi4uL3NvdXJjZS1jb2RlXCI7XG5pbXBvcnQgdHlwZSB7IFR5cGVTY3JpcHRQcm9qZWN0IH0gZnJvbSBcIi4uL3R5cGVzY3JpcHRcIjtcbmltcG9ydCB7IG5vcm1hbGl6ZVBlcnNpc3RlZFBhdGggfSBmcm9tIFwiLi4vdXRpbFwiO1xuXG4vKipcbiAqIENvbW1vbiBvcHRpb25zIGZvciBgTGFtYmRhRnVuY3Rpb25gLiBBcHBsaWVzIHRvIGFsbCBmdW5jdGlvbnMgaW5cbiAqIGF1dG8tZGlzY292ZXJ5LlxuICovXG5leHBvcnQgaW50ZXJmYWNlIExhbWJkYUZ1bmN0aW9uQ29tbW9uT3B0aW9ucyB7XG4gIC8qKlxuICAgKiBUaGUgbm9kZS5qcyB2ZXJzaW9uIHRvIHRhcmdldC5cbiAgICpcbiAgICogQGRlZmF1bHQgTGFtYmRhUnVudGltZS5OT0RFSlNfUkVHSU9OQUxfTEFURVNUIC0gVXNlcyB0aGUgbGF0ZXN0IE5vZGUuanMgcnVudGltZVxuICAgKiBhdmFpbGFibGUgaW4gdGhlIGRlcGxveW1lbnQgcmVnaW9uLCBkZXRlcm1pbmVkIGF0IENESyBzeW50aGVzaXMgdGltZS5cbiAgICovXG4gIHJlYWRvbmx5IHJ1bnRpbWU/OiBMYW1iZGFSdW50aW1lO1xuXG4gIC8qKlxuICAgKiBCdW5kbGluZyBvcHRpb25zIGZvciB0aGlzIEFXUyBMYW1iZGEgZnVuY3Rpb24uXG4gICAqXG4gICAqIElmIG5vdCBzcGVjaWZpZWQgdGhlIGRlZmF1bHQgYnVuZGxpbmcgb3B0aW9ucyBzcGVjaWZpZWQgZm9yIHRoZSBwcm9qZWN0XG4gICAqIGBCdW5kbGVyYCBpbnN0YW5jZSB3aWxsIGJlIHVzZWQuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gZGVmYXVsdHNcbiAgICovXG4gIHJlYWRvbmx5IGJ1bmRsaW5nT3B0aW9ucz86IEJ1bmRsaW5nT3B0aW9ucztcblxuICAvKipcbiAgICogV2hldGhlciB0byBhdXRvbWF0aWNhbGx5IHJldXNlIFRDUCBjb25uZWN0aW9ucyB3aGVuIHdvcmtpbmcgd2l0aCB0aGUgQVdTXG4gICAqIFNESyBmb3IgSmF2YVNjcmlwdC5cbiAgICpcbiAgICogVGhpcyBzZXRzIHRoZSBgQVdTX05PREVKU19DT05ORUNUSU9OX1JFVVNFX0VOQUJMRURgIGVudmlyb25tZW50IHZhcmlhYmxlXG4gICAqIHRvIGAxYC5cbiAgICpcbiAgICogTm90IGFwcGxpY2FibGUgd2hlbiBgZWRnZUxhbWJkYWAgaXMgc2V0IHRvIGB0cnVlYCBiZWNhdXNlIGVudmlyb25tZW50XG4gICAqIHZhcmlhYmxlcyBhcmUgbm90IHN1cHBvcnRlZCBpbiBMYW1iZGFARWRnZS5cbiAgICpcbiAgICogQHNlZSBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vc2RrLWZvci1qYXZhc2NyaXB0L3YyL2RldmVsb3Blci1ndWlkZS9ub2RlLXJldXNpbmctY29ubmVjdGlvbnMuaHRtbFxuICAgKlxuICAgKiBAZGVmYXVsdCB0cnVlXG4gICAqL1xuICByZWFkb25seSBhd3NTZGtDb25uZWN0aW9uUmV1c2U/OiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBXaGV0aGVyIHRvIGNyZWF0ZSBhIGBjbG91ZGZyb250LmV4cGVyaW1lbnRhbC5FZGdlRnVuY3Rpb25gIGluc3RlYWRcbiAgICogb2YgYSBgbGFtYmRhLkZ1bmN0aW9uYC5cbiAgICpcbiAgICogQGRlZmF1bHQgZmFsc2VcbiAgICovXG4gIHJlYWRvbmx5IGVkZ2VMYW1iZGE/OiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBXaGV0aGVyIHRvIGNyZWF0ZSBhIGBsYW1iZGEuU2luZ2xldG9uRnVuY3Rpb25gIGluc3RlYWQgb2YgYVxuICAgKiBgbGFtYmRhLkZ1bmN0aW9uYC5cbiAgICpcbiAgICogTm90IGNvbXBhdGlibGUgd2l0aCBgZWRnZUxhbWJkYWAuXG4gICAqXG4gICAqIEBkZWZhdWx0IGZhbHNlXG4gICAqL1xuICByZWFkb25seSBzaW5nbGV0b24/OiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBVVUlEIHRvIHVzZSBmb3Igc2luZ2xldG9uIGxhbWJkYSB1bmlxdWVuZXNzLlxuICAgKlxuICAgKiBXaGVuIHNwZWNpZmllZCwgdGhlIGdlbmVyYXRlZCBzaW5nbGV0b24gY29uc3RydWN0IGhhcmRjb2RlcyB0aGlzIFVVSUQuXG4gICAqXG4gICAqIE9ubHkgdmFsaWQgd2hlbiBgc2luZ2xldG9uYCBpcyBzZXQgdG8gYHRydWVgLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIG5vIFVVSUQgaXMgaGFyZGNvZGVkIGFuZCBjb25zdW1lcnMgbXVzdCBwcm92aWRlIG9uZVxuICAgKi9cbiAgcmVhZG9ubHkgc2luZ2xldG9uVXVpZD86IHN0cmluZztcbn1cblxuLyoqXG4gKiBPcHRpb25zIGZvciBgRnVuY3Rpb25gLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIExhbWJkYUZ1bmN0aW9uT3B0aW9ucyBleHRlbmRzIExhbWJkYUZ1bmN0aW9uQ29tbW9uT3B0aW9ucyB7XG4gIC8qKlxuICAgKiBBIHBhdGggZnJvbSB0aGUgcHJvamVjdCByb290IGRpcmVjdG9yeSB0byBhIFR5cGVTY3JpcHQgZmlsZSB3aGljaCBjb250YWluc1xuICAgKiB0aGUgQVdTIExhbWJkYSBoYW5kbGVyIGVudHJ5cG9pbnQgKGV4cG9ydHMgYSBgaGFuZGxlcmAgZnVuY3Rpb24pLlxuICAgKlxuICAgKiBUaGlzIGlzIHJlbGF0aXZlIHRvIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGUgcHJvamVjdC5cbiAgICpcbiAgICogQGV4YW1wbGUgXCJzcmMvc3ViZGlyL2Zvby5sYW1iZGEudHNcIlxuICAgKi9cbiAgcmVhZG9ubHkgZW50cnlwb2ludDogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBUaGUgbmFtZSBvZiB0aGUgZ2VuZXJhdGVkIFR5cGVTY3JpcHQgc291cmNlIGZpbGUuIFRoaXMgZmlsZSBzaG91bGQgYWxzbyBiZVxuICAgKiB1bmRlciB0aGUgc291cmNlIHRyZWUuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gVGhlIG5hbWUgb2YgdGhlIGVudHJ5cG9pbnQgZmlsZSwgd2l0aCB0aGUgYC1mdW5jdGlvbi50c2Agc3VmZml4XG4gICAqIGluc3RlYWQgb2YgYC5sYW1iZGEudHNgLlxuICAgKi9cbiAgcmVhZG9ubHkgY29uc3RydWN0RmlsZT86IHN0cmluZztcblxuICAvKipcbiAgICogVGhlIG5hbWUgb2YgdGhlIGdlbmVyYXRlZCBgbGFtYmRhLkZ1bmN0aW9uYCBzdWJjbGFzcy5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBBIHBhc2NhbCBjYXNlZCB2ZXJzaW9uIG9mIHRoZSBuYW1lIG9mIHRoZSBlbnRyeXBvaW50IGZpbGUsIHdpdGhcbiAgICogdGhlIGV4dGVuc2lvbiBgRnVuY3Rpb25gIChlLmcuIGBSZXNpemVJbWFnZUZ1bmN0aW9uYCkuXG4gICAqL1xuICByZWFkb25seSBjb25zdHJ1Y3ROYW1lPzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBBV1MgQ0RLIGRlcGVuZGVuY3kgbWFuYWdlci5cbiAgICovXG4gIHJlYWRvbmx5IGNka0RlcHM6IEF3c0Nka0RlcHM7XG59XG5cbi8qKlxuICogR2VuZXJhdGVzIGEgcHJlLWJ1bmRsZWQgQVdTIExhbWJkYSBmdW5jdGlvbiBjb25zdHJ1Y3QgZnJvbSBoYW5kbGVyIGNvZGUuXG4gKlxuICogVG8gdXNlIHRoaXMsIGNyZWF0ZSBhbiBBV1MgTGFtYmRhIGhhbmRsZXIgZmlsZSB1bmRlciB5b3VyIHNvdXJjZSB0cmVlIHdpdGhcbiAqIHRoZSBgLmxhbWJkYS50c2AgZXh0ZW5zaW9uIGFuZCBhZGQgYSBgTGFtYmRhRnVuY3Rpb25gIGNvbXBvbmVudCB0byB5b3VyXG4gKiB0eXBlc2NyaXB0IHByb2plY3QgcG9pbnRpbmcgdG8gdGhpcyBlbnRyeXBvaW50LlxuICpcbiAqIFRoaXMgd2lsbCBhZGQgYSB0YXNrIHRvIHlvdXIgXCJjb21waWxlXCIgc3RlcCB3aGljaCB3aWxsIHVzZSBgZXNidWlsZGAgdG9cbiAqIGJ1bmRsZSB0aGUgaGFuZGxlciBjb2RlIGludG8gdGhlIGJ1aWxkIGRpcmVjdG9yeS4gSXQgd2lsbCBhbHNvIGdlbmVyYXRlIGFcbiAqIGZpbGUgYHNyYy9mb28tZnVuY3Rpb24udHNgIHdpdGggYSBjdXN0b20gQVdTIGNvbnN0cnVjdCBjYWxsZWQgYEZvb0Z1bmN0aW9uYFxuICogd2hpY2ggZXh0ZW5kcyBgQGF3cy1jZGsvYXdzLWxhbWJkYS5GdW5jdGlvbmAgd2hpY2ggaXMgYm91bmQgdG8gdGhlIGJ1bmRsZWRcbiAqIGhhbmRsZSB0aHJvdWdoIGFuIGFzc2V0LlxuICpcbiAqIEBleGFtcGxlXG4gKlxuICogbmV3IExhbWJkYUZ1bmN0aW9uKG15UHJvamVjdCwge1xuICogICBzcmNkaXI6IG15UHJvamVjdC5zcmNkaXIsXG4gKiAgIGVudHJ5cG9pbnQ6ICdzcmMvZm9vLmxhbWJkYS50cycsXG4gKiB9KTtcbiAqL1xuZXhwb3J0IGNsYXNzIExhbWJkYUZ1bmN0aW9uIGV4dGVuZHMgQ29tcG9uZW50IHtcbiAgLyoqXG4gICAqIERlZmluZXMgYSBwcmUtYnVuZGxlZCBBV1MgTGFtYmRhIGZ1bmN0aW9uIGNvbnN0cnVjdCBmcm9tIGhhbmRsZXIgY29kZS5cbiAgICpcbiAgICogQHBhcmFtIHByb2plY3QgVGhlIHByb2plY3QgdG8gdXNlXG4gICAqIEBwYXJhbSBvcHRpb25zIE9wdGlvbnNcbiAgICovXG4gIGNvbnN0cnVjdG9yKHByb2plY3Q6IFByb2plY3QsIG9wdGlvbnM6IExhbWJkYUZ1bmN0aW9uT3B0aW9ucykge1xuICAgIHN1cGVyKHByb2plY3QpO1xuXG4gICAgY29uc3QgY2RrRGVwcyA9IG9wdGlvbnMuY2RrRGVwcztcbiAgICBjb25zdCBidW5kbGVyID0gQnVuZGxlci5vZihwcm9qZWN0KTtcbiAgICBpZiAoIWJ1bmRsZXIpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgXCJObyBidW5kbGVyIGZvdW5kLiBQbGVhc2UgYWRkIGEgQnVuZGxlciBjb21wb25lbnQgdG8geW91ciBwcm9qZWN0LlwiLFxuICAgICAgKTtcbiAgICB9XG5cbiAgICAvLyBVc2UgTk9ERUpTX1JFR0lPTkFMX0xBVEVTVCBhcyBkZWZhdWx0LCB3aGljaCBnZW5lcmF0ZXMgZGV0ZXJtaW5lTGF0ZXN0Tm9kZVJ1bnRpbWUoKVxuICAgIGNvbnN0IHJ1bnRpbWUgPSBvcHRpb25zLnJ1bnRpbWUgPz8gTGFtYmRhUnVudGltZS5OT0RFSlNfUkVHSU9OQUxfTEFURVNUO1xuXG4gICAgY29uc3QgZW50cnlwb2ludCA9IG5vcm1hbGl6ZVBlcnNpc3RlZFBhdGgob3B0aW9ucy5lbnRyeXBvaW50KTtcblxuICAgIC8vIGFsbG93IExhbWJkYSBoYW5kbGVyIGNvZGUgdG8gaW1wb3J0IGRldi1kZXBzIHNpbmNlIHRoZXkgYXJlIG9ubHkgbmVlZGVkXG4gICAgLy8gZHVyaW5nIGJ1bmRsaW5nXG4gICAgY29uc3QgZXNsaW50ID0gRXNsaW50Lm9mKHByb2plY3QpO1xuICAgIGVzbGludD8uYWxsb3dEZXZEZXBzKGVudHJ5cG9pbnQpO1xuXG4gICAgaWYgKFxuICAgICAgIWVudHJ5cG9pbnQuZW5kc1dpdGgoVFlQRVNDUklQVF9MQU1CREFfRVhUKSAmJlxuICAgICAgIWVudHJ5cG9pbnQuZW5kc1dpdGgoVFlQRVNDUklQVF9FREdFX0xBTUJEQV9FWFQpICYmXG4gICAgICAhZW50cnlwb2ludC5lbmRzV2l0aChUWVBFU0NSSVBUX1NJTkdMRVRPTl9MQU1CREFfRVhUKVxuICAgICkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgJHtlbnRyeXBvaW50fSBtdXN0IGhhdmUgYSAke1RZUEVTQ1JJUFRfTEFNQkRBX0VYVH0sICR7VFlQRVNDUklQVF9FREdFX0xBTUJEQV9FWFR9LCBvciAke1RZUEVTQ1JJUFRfU0lOR0xFVE9OX0xBTUJEQV9FWFR9IGV4dGVuc2lvbmAsXG4gICAgICApO1xuICAgIH1cblxuICAgIGlmIChvcHRpb25zLmVkZ2VMYW1iZGEgJiYgb3B0aW9ucy5zaW5nbGV0b24pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcInNpbmdsZXRvbiBjYW5ub3QgYmUgdXNlZCB3aXRoIGVkZ2VMYW1iZGFcIik7XG4gICAgfVxuXG4gICAgaWYgKG9wdGlvbnMuc2luZ2xldG9uVXVpZCAmJiAhb3B0aW9ucy5zaW5nbGV0b24pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcInNpbmdsZXRvblV1aWQgY2FuIG9ubHkgYmUgdXNlZCB3aXRoIHNpbmdsZXRvblwiKTtcbiAgICB9XG5cbiAgICBjb25zdCBzb3VyY2VFeHRlbnNpb24gPSBlbnRyeXBvaW50LmVuZHNXaXRoKFRZUEVTQ1JJUFRfRURHRV9MQU1CREFfRVhUKVxuICAgICAgPyBUWVBFU0NSSVBUX0VER0VfTEFNQkRBX0VYVFxuICAgICAgOiBlbnRyeXBvaW50LmVuZHNXaXRoKFRZUEVTQ1JJUFRfU0lOR0xFVE9OX0xBTUJEQV9FWFQpXG4gICAgICAgID8gVFlQRVNDUklQVF9TSU5HTEVUT05fTEFNQkRBX0VYVFxuICAgICAgICA6IFRZUEVTQ1JJUFRfTEFNQkRBX0VYVDtcblxuICAgIGNvbnN0IGJhc2VQYXRoID0gcGF0aC5wb3NpeC5qb2luKFxuICAgICAgcGF0aC5kaXJuYW1lKGVudHJ5cG9pbnQpLFxuICAgICAgcGF0aC5iYXNlbmFtZShlbnRyeXBvaW50LCBzb3VyY2VFeHRlbnNpb24pLFxuICAgICk7XG4gICAgY29uc3QgY29uc3RydWN0RmlsZSA9IG9wdGlvbnMuY29uc3RydWN0RmlsZSA/PyBgJHtiYXNlUGF0aH0tZnVuY3Rpb24udHNgO1xuXG4gICAgaWYgKHBhdGguZXh0bmFtZShjb25zdHJ1Y3RGaWxlKSAhPT0gXCIudHNcIikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgQ29uc3RydWN0IGZpbGUgbmFtZSBcIiR7Y29uc3RydWN0RmlsZX1cIiBtdXN0IGhhdmUgYSAudHMgZXh0ZW5zaW9uYCxcbiAgICAgICk7XG4gICAgfVxuXG4gICAgLy8gdHlwZSBuYW1lc1xuICAgIGNvbnN0IGNvbnN0cnVjdE5hbWUgPVxuICAgICAgb3B0aW9ucy5jb25zdHJ1Y3ROYW1lID8/IHBhc2NhbChwYXRoLmJhc2VuYW1lKGJhc2VQYXRoKSkgKyBcIkZ1bmN0aW9uXCI7XG4gICAgY29uc3QgcHJvcHNUeXBlID0gYCR7Y29uc3RydWN0TmFtZX1Qcm9wc2A7XG5cbiAgICBjb25zdCBidW5kbGUgPSBidW5kbGVyLmFkZEJ1bmRsZShlbnRyeXBvaW50LCB7XG4gICAgICB0YXJnZXQ6IHJ1bnRpbWUuZXNidWlsZFRhcmdldCxcbiAgICAgIHBsYXRmb3JtOiBydW50aW1lLmVzYnVpbGRQbGF0Zm9ybSxcbiAgICAgIGV4dGVybmFsczogcnVudGltZS5kZWZhdWx0RXh0ZXJuYWxzLFxuICAgICAgLi4ub3B0aW9ucy5idW5kbGluZ09wdGlvbnMsXG4gICAgICB0c2NvbmZpZ1BhdGg6IChwcm9qZWN0IGFzIFR5cGVTY3JpcHRQcm9qZWN0KT8udHNjb25maWdEZXY/LmZpbGVOYW1lLFxuICAgIH0pO1xuXG4gICAgLy8gY2FsY3VsYXRlIHRoZSByZWxhdGl2ZSBwYXRoIGJldHdlZW4gdGhlIGRpcmVjdG9yeSBjb250YWluaW5nIHRoZVxuICAgIC8vIGdlbmVyYXRlZCBjb25zdHJ1Y3Qgc291cmNlIGZpbGUgdG8gdGhlIGRpcmVjdG9yeSBjb250YWluaW5nIHRoZSBidW5kbGVcbiAgICAvLyBpbmRleC5qcyBieSByZXNvbHZpbmcgdGhlbSBhcyBhYnNvbHV0ZSBwYXRocyBmaXJzdC5cbiAgICAvLyBlLmc6XG4gICAgLy8gIC0gb3V0ZmlsZUFicyA9PiBgL3Byb2plY3Qtb3V0ZGlyL2Fzc2V0cy9mb28vYmFyL2Jhei9mb28tZnVuY3Rpb24vaW5kZXguanNgXG4gICAgLy8gIC0gY29uc3RydWN0QWJzID0+IGAvcHJvamVjdC1vdXRkaXIvc3JjL2Zvby9iYXIvYmF6L2Zvby1mdW5jdGlvbi50c2BcbiAgICBjb25zdCBvdXRmaWxlQWJzID0gcGF0aC5qb2luKHByb2plY3Qub3V0ZGlyLCBidW5kbGUub3V0ZmlsZSk7XG4gICAgY29uc3QgY29uc3RydWN0QWJzID0gcGF0aC5qb2luKHByb2plY3Qub3V0ZGlyLCBjb25zdHJ1Y3RGaWxlKTtcbiAgICBjb25zdCByZWxhdGl2ZU91dGZpbGUgPSBwYXRoLnJlbGF0aXZlKFxuICAgICAgcGF0aC5kaXJuYW1lKGNvbnN0cnVjdEFicyksXG4gICAgICBwYXRoLmRpcm5hbWUob3V0ZmlsZUFicyksXG4gICAgKTtcblxuICAgIGNvbnN0IHNyYyA9IG5ldyBTb3VyY2VDb2RlKHByb2plY3QsIGNvbnN0cnVjdEZpbGUpO1xuICAgIGlmIChzcmMubWFya2VyKSB7XG4gICAgICBzcmMubGluZShgLy8gJHtzcmMubWFya2VyfWApO1xuICAgIH1cbiAgICBzcmMubGluZShcImltcG9ydCAqIGFzIHBhdGggZnJvbSAncGF0aCc7XCIpO1xuXG4gICAgaWYgKGNka0RlcHMuY2RrTWFqb3JWZXJzaW9uID09PSAxKSB7XG4gICAgICBpZiAob3B0aW9ucy5lZGdlTGFtYmRhKSB7XG4gICAgICAgIHNyYy5saW5lKFwiaW1wb3J0ICogYXMgY2xvdWRmcm9udCBmcm9tICdAYXdzLWNkay9hd3MtY2xvdWRmcm9udCc7XCIpO1xuICAgICAgICBjZGtEZXBzLmFkZFYxRGVwZW5kZW5jaWVzKFwiQGF3cy1jZGsvYXdzLWNsb3VkZnJvbnRcIik7XG4gICAgICB9XG4gICAgICBzcmMubGluZShcImltcG9ydCAqIGFzIGxhbWJkYSBmcm9tICdAYXdzLWNkay9hd3MtbGFtYmRhJztcIik7XG4gICAgICBzcmMubGluZShcImltcG9ydCB7IENvbnN0cnVjdCB9IGZyb20gJ0Bhd3MtY2RrL2NvcmUnO1wiKTtcbiAgICAgIGNka0RlcHMuYWRkVjFEZXBlbmRlbmNpZXMoXCJAYXdzLWNkay9hd3MtbGFtYmRhXCIpO1xuICAgICAgY2RrRGVwcy5hZGRWMURlcGVuZGVuY2llcyhcIkBhd3MtY2RrL2NvcmVcIik7XG4gICAgfSBlbHNlIHtcbiAgICAgIGlmIChvcHRpb25zLmVkZ2VMYW1iZGEpIHtcbiAgICAgICAgc3JjLmxpbmUoXCJpbXBvcnQgKiBhcyBjbG91ZGZyb250IGZyb20gJ2F3cy1jZGstbGliL2F3cy1jbG91ZGZyb250JztcIik7XG4gICAgICB9XG4gICAgICBzcmMubGluZShcImltcG9ydCAqIGFzIGxhbWJkYSBmcm9tICdhd3MtY2RrLWxpYi9hd3MtbGFtYmRhJztcIik7XG4gICAgICAvLyBJbXBvcnQgZGV0ZXJtaW5lTGF0ZXN0Tm9kZVJ1bnRpbWUgaWYgdXNpbmcgTk9ERUpTX1JFR0lPTkFMX0xBVEVTVFxuICAgICAgaWYgKHJ1bnRpbWUgPT09IExhbWJkYVJ1bnRpbWUuTk9ERUpTX1JFR0lPTkFMX0xBVEVTVCkge1xuICAgICAgICBzcmMubGluZShcbiAgICAgICAgICBcImltcG9ydCB7IGRldGVybWluZUxhdGVzdE5vZGVSdW50aW1lIH0gZnJvbSAnYXdzLWNkay1saWIvYXdzLWxhbWJkYSc7XCIsXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgICBzcmMubGluZShcImltcG9ydCB7IENvbnN0cnVjdCB9IGZyb20gJ2NvbnN0cnVjdHMnO1wiKTtcbiAgICB9XG5cbiAgICBzcmMubGluZSgpO1xuICAgIHNyYy5saW5lKFwiLyoqXCIpO1xuICAgIHNyYy5saW5lKGAgKiBQcm9wcyBmb3IgJHtjb25zdHJ1Y3ROYW1lfWApO1xuICAgIHNyYy5saW5lKFwiICovXCIpO1xuICAgIGlmIChvcHRpb25zLmVkZ2VMYW1iZGEpIHtcbiAgICAgIHNyYy5vcGVuKFxuICAgICAgICBgZXhwb3J0IGludGVyZmFjZSAke3Byb3BzVHlwZX0gZXh0ZW5kcyBjbG91ZGZyb250LmV4cGVyaW1lbnRhbC5FZGdlRnVuY3Rpb25Qcm9wcyB7YCxcbiAgICAgICk7XG4gICAgfSBlbHNlIGlmIChvcHRpb25zLnNpbmdsZXRvbikge1xuICAgICAgc3JjLm9wZW4oXG4gICAgICAgIGBleHBvcnQgaW50ZXJmYWNlICR7cHJvcHNUeXBlfSBleHRlbmRzIGxhbWJkYS5TaW5nbGV0b25GdW5jdGlvblByb3BzIHtgLFxuICAgICAgKTtcbiAgICB9IGVsc2Uge1xuICAgICAgc3JjLm9wZW4oXG4gICAgICAgIGBleHBvcnQgaW50ZXJmYWNlICR7cHJvcHNUeXBlfSBleHRlbmRzIGxhbWJkYS5GdW5jdGlvbk9wdGlvbnMge2AsXG4gICAgICApO1xuICAgIH1cbiAgICAvLyBBZGQgcnVudGltZSBwcm9wIHRvIGludGVyZmFjZSBvbmx5IHdoZW4gcnVudGltZSBpcyBub3QgZXhwbGljaXRseSBzZXRcbiAgICAvLyBUaGlzIGFsbG93cyBjb25zdW1lcnMgdG8gb3ZlcnJpZGUgdGhlIGRlZmF1bHQgTk9ERUpTX1JFR0lPTkFMX0xBVEVTVFxuICAgIGlmICghb3B0aW9ucy5ydW50aW1lKSB7XG4gICAgICBzcmMubGluZShcIi8qKlwiKTtcbiAgICAgIHNyYy5saW5lKFwiICogVGhlIExhbWJkYSBydW50aW1lIHRvIHVzZS5cIik7XG4gICAgICBzcmMubGluZShcbiAgICAgICAgXCIgKiBAZGVmYXVsdCAtIExhdGVzdCBOb2RlLmpzIHJ1bnRpbWUgYXZhaWxhYmxlIGluIHRoZSBkZXBsb3ltZW50IHJlZ2lvblwiLFxuICAgICAgKTtcbiAgICAgIHNyYy5saW5lKFwiICovXCIpO1xuICAgICAgc3JjLmxpbmUoXCJyZWFkb25seSBydW50aW1lPzogbGFtYmRhLlJ1bnRpbWU7XCIpO1xuICAgIH1cbiAgICBzcmMuY2xvc2UoXCJ9XCIpO1xuICAgIHNyYy5saW5lKCk7XG4gICAgc3JjLmxpbmUoXCIvKipcIik7XG4gICAgc3JjLmxpbmUoXG4gICAgICBgICogQW4gQVdTIExhbWJkYSBmdW5jdGlvbiB3aGljaCBleGVjdXRlcyAke2NvbnZlcnRUb1Bvc2l4UGF0aChcbiAgICAgICAgYmFzZVBhdGgsXG4gICAgICApfS5gLFxuICAgICk7XG4gICAgc3JjLmxpbmUoXCIgKi9cIik7XG4gICAgaWYgKG9wdGlvbnMuZWRnZUxhbWJkYSkge1xuICAgICAgc3JjLm9wZW4oXG4gICAgICAgIGBleHBvcnQgY2xhc3MgJHtjb25zdHJ1Y3ROYW1lfSBleHRlbmRzIGNsb3VkZnJvbnQuZXhwZXJpbWVudGFsLkVkZ2VGdW5jdGlvbiB7YCxcbiAgICAgICk7XG4gICAgfSBlbHNlIGlmIChvcHRpb25zLnNpbmdsZXRvbikge1xuICAgICAgc3JjLm9wZW4oXG4gICAgICAgIGBleHBvcnQgY2xhc3MgJHtjb25zdHJ1Y3ROYW1lfSBleHRlbmRzIGxhbWJkYS5TaW5nbGV0b25GdW5jdGlvbiB7YCxcbiAgICAgICk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHNyYy5vcGVuKGBleHBvcnQgY2xhc3MgJHtjb25zdHJ1Y3ROYW1lfSBleHRlbmRzIGxhbWJkYS5GdW5jdGlvbiB7YCk7XG4gICAgfVxuICAgIHNyYy5vcGVuKFxuICAgICAgYGNvbnN0cnVjdG9yKHNjb3BlOiBDb25zdHJ1Y3QsIGlkOiBzdHJpbmcsIHByb3BzPzogJHtwcm9wc1R5cGV9KSB7YCxcbiAgICApO1xuICAgIHNyYy5vcGVuKFwic3VwZXIoc2NvcGUsIGlkLCB7XCIpO1xuICAgIHNyYy5saW5lKGBkZXNjcmlwdGlvbjogJyR7Y29udmVydFRvUG9zaXhQYXRoKGVudHJ5cG9pbnQpfScsYCk7XG4gICAgc3JjLmxpbmUoXCIuLi5wcm9wcyxcIik7XG4gICAgaWYgKG9wdGlvbnMuc2luZ2xldG9uICYmIG9wdGlvbnMuc2luZ2xldG9uVXVpZCkge1xuICAgICAgc3JjLmxpbmUoYHV1aWQ6ICR7SlNPTi5zdHJpbmdpZnkob3B0aW9ucy5zaW5nbGV0b25VdWlkKX0sYCk7XG4gICAgfVxuXG4gICAgLy8gR2VuZXJhdGUgcnVudGltZSBjb2RlXG4gICAgaWYgKHJ1bnRpbWUgPT09IExhbWJkYVJ1bnRpbWUuTk9ERUpTX1JFR0lPTkFMX0xBVEVTVCkge1xuICAgICAgLy8gUmVnaW9uYWwgbGF0ZXN0IHJ1bnRpbWVcbiAgICAgIGlmICghb3B0aW9ucy5ydW50aW1lKSB7XG4gICAgICAgIC8vIERlZmF1bHQgKG5vdCBleHBsaWNpdGx5IHNldCkgLSBhbGxvdyBjb25zdW1lciBvdmVycmlkZVxuICAgICAgICBzcmMubGluZShcbiAgICAgICAgICBcInJ1bnRpbWU6IHByb3BzPy5ydW50aW1lID8/IGRldGVybWluZUxhdGVzdE5vZGVSdW50aW1lKHNjb3BlKSxcIixcbiAgICAgICAgKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIEV4cGxpY2l0bHkgc2V0IC0gbm8gb3ZlcnJpZGVcbiAgICAgICAgc3JjLmxpbmUoXCJydW50aW1lOiBkZXRlcm1pbmVMYXRlc3ROb2RlUnVudGltZShzY29wZSksXCIpO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAvLyBFeHBsaWNpdCBydW50aW1lIC0gaGFyZGNvZGVkLCBubyBvdmVycmlkZVxuICAgICAgc3JjLmxpbmUoXG4gICAgICAgIGBydW50aW1lOiBuZXcgbGFtYmRhLlJ1bnRpbWUoJyR7cnVudGltZS5mdW5jdGlvblJ1bnRpbWV9JywgbGFtYmRhLlJ1bnRpbWVGYW1pbHkuTk9ERUpTKSxgLFxuICAgICAgKTtcbiAgICB9XG5cbiAgICBzcmMubGluZShcImhhbmRsZXI6ICdpbmRleC5oYW5kbGVyJyxcIik7XG4gICAgc3JjLmxpbmUoXG4gICAgICBgY29kZTogbGFtYmRhLkNvZGUuZnJvbUFzc2V0KHBhdGguam9pbihfX2Rpcm5hbWUsICcke2NvbnZlcnRUb1Bvc2l4UGF0aChcbiAgICAgICAgcmVsYXRpdmVPdXRmaWxlLFxuICAgICAgKX0nKSksYCxcbiAgICApO1xuICAgIHNyYy5jbG9zZShcIn0pO1wiKTtcbiAgICBpZiAoKG9wdGlvbnMuYXdzU2RrQ29ubmVjdGlvblJldXNlID8/IHRydWUpICYmICFvcHRpb25zLmVkZ2VMYW1iZGEpIHtcbiAgICAgIHNyYy5saW5lKFxuICAgICAgICBcInRoaXMuYWRkRW52aXJvbm1lbnQoJ0FXU19OT0RFSlNfQ09OTkVDVElPTl9SRVVTRV9FTkFCTEVEJywgJzEnLCB7IHJlbW92ZUluRWRnZTogdHJ1ZSB9KTtcIixcbiAgICAgICk7XG4gICAgfVxuICAgIHNyYy5jbG9zZShcIn1cIik7XG4gICAgc3JjLmNsb3NlKFwifVwiKTtcblxuICAgIHRoaXMucHJvamVjdC5sb2dnZXIudmVyYm9zZShcbiAgICAgIGAke2Jhc2VQYXRofTogY29uc3RydWN0IFwiJHtjb25zdHJ1Y3ROYW1lfVwiIGdlbmVyYXRlZCB1bmRlciBcIiR7Y29uc3RydWN0RmlsZX1cImAsXG4gICAgKTtcbiAgICB0aGlzLnByb2plY3QubG9nZ2VyLnZlcmJvc2UoXG4gICAgICBgJHtiYXNlUGF0aH06IGJ1bmRsZSB0YXNrIFwiJHtidW5kbGUuYnVuZGxlVGFzay5uYW1lfVwiYCxcbiAgICApO1xuICAgIGlmIChidW5kbGUud2F0Y2hUYXNrKSB7XG4gICAgICB0aGlzLnByb2plY3QubG9nZ2VyLnZlcmJvc2UoXG4gICAgICAgIGAke2Jhc2VQYXRofTogYnVuZGxlIHdhdGNoIHRhc2sgXCIke2J1bmRsZS53YXRjaFRhc2submFtZX1cImAsXG4gICAgICApO1xuICAgIH1cbiAgfVxufVxuXG4vKipcbiAqIE9wdGlvbnMgZm9yIHRoZSBBV1MgTGFtYmRhIGZ1bmN0aW9uIHJ1bnRpbWVcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBMYW1iZGFSdW50aW1lT3B0aW9ucyB7XG4gIC8qKlxuICAgKiBQYWNrYWdlcyB0aGF0IGFyZSBjb25zaWRlcmVkIGV4dGVybmFscyBieSBkZWZhdWx0IHdoZW4gYnVuZGxpbmdcbiAgICpcbiAgICogQGRlZmF1bHQgWydAYXdzLXNkay8qJ11cbiAgICovXG4gIHJlYWRvbmx5IGRlZmF1bHRFeHRlcm5hbHM/OiBzdHJpbmdbXTtcbn1cblxuLyoqXG4gKiBUaGUgcnVudGltZSBmb3IgdGhlIEFXUyBMYW1iZGEgZnVuY3Rpb24uXG4gKi9cbmV4cG9ydCBjbGFzcyBMYW1iZGFSdW50aW1lIHtcbiAgLyoqXG4gICAqIE5vZGUuanMgMTAueFxuICAgKiBAZGVwcmVjYXRlZCBOb2RlLmpzIDEwIHJ1bnRpbWUgaGFzIGJlZW4gZGVwcmVjYXRlZCBvbiBKdWwgMzAsIDIwMjFcbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgcmVhZG9ubHkgTk9ERUpTXzEwX1ggPSBuZXcgTGFtYmRhUnVudGltZShcbiAgICBcIm5vZGVqczEwLnhcIixcbiAgICBcIm5vZGUxMFwiLFxuICAgIHsgZGVmYXVsdEV4dGVybmFsczogW1wiYXdzLXNka1wiXSB9LFxuICApO1xuXG4gIC8qKlxuICAgKiBOb2RlLmpzIDEyLnhcbiAgICogQGRlcHJlY2F0ZWQgTm9kZS5qcyAxMiBydW50aW1lIGhhcyBiZWVuIGRlcHJlY2F0ZWQgb24gTWFyIDMxLCAyMDIzXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIHJlYWRvbmx5IE5PREVKU18xMl9YID0gbmV3IExhbWJkYVJ1bnRpbWUoXG4gICAgXCJub2RlanMxMi54XCIsXG4gICAgXCJub2RlMTJcIixcbiAgICB7IGRlZmF1bHRFeHRlcm5hbHM6IFtcImF3cy1zZGtcIl0gfSxcbiAgKTtcblxuICAvKipcbiAgICogTm9kZS5qcyAxNC54XG4gICAqIEBkZXByZWNhdGVkIE5vZGUuanMgMTQgcnVudGltZSBoYXMgYmVlbiBkZXByZWNhdGVkIG9uIERlYyA0LCAyMDIzXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIHJlYWRvbmx5IE5PREVKU18xNF9YID0gbmV3IExhbWJkYVJ1bnRpbWUoXG4gICAgXCJub2RlanMxNC54XCIsXG4gICAgXCJub2RlMTRcIixcbiAgICB7IGRlZmF1bHRFeHRlcm5hbHM6IFtcImF3cy1zZGtcIl0gfSxcbiAgKTtcblxuICAvKipcbiAgICogTm9kZS5qcyAxNi54XG4gICAqIEBkZXByZWNhdGVkIE5vZGUuanMgMTYgcnVudGltZSBoYXMgYmVlbiBkZXByZWNhdGVkIG9uIEp1biAxMiwgMjAyNFxuICAgKi9cbiAgcHVibGljIHN0YXRpYyByZWFkb25seSBOT0RFSlNfMTZfWCA9IG5ldyBMYW1iZGFSdW50aW1lKFxuICAgIFwibm9kZWpzMTYueFwiLFxuICAgIFwibm9kZTE2XCIsXG4gICAgeyBkZWZhdWx0RXh0ZXJuYWxzOiBbXCJhd3Mtc2RrXCJdIH0sXG4gICk7XG5cbiAgLyoqXG4gICAqIE5vZGUuanMgMTgueFxuICAgKlxuICAgKiBAZGVwcmVjYXRlZDogTm9kZS5qcyAxOCBydW50aW1lIGhhcyBiZWVuIGRlcHJlY2F0ZWQgb24gU2VwIDEsIDIwMjVcbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgcmVhZG9ubHkgTk9ERUpTXzE4X1ggPSBuZXcgTGFtYmRhUnVudGltZShcbiAgICBcIm5vZGVqczE4LnhcIixcbiAgICBcIm5vZGUxOFwiLFxuICApO1xuXG4gIC8qKlxuICAgKiBOb2RlLmpzIDIwLnhcbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgcmVhZG9ubHkgTk9ERUpTXzIwX1ggPSBuZXcgTGFtYmRhUnVudGltZShcbiAgICBcIm5vZGVqczIwLnhcIixcbiAgICBcIm5vZGUyMFwiLFxuICApO1xuXG4gIC8qKlxuICAgKiBOb2RlLmpzIDIyLnhcbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgcmVhZG9ubHkgTk9ERUpTXzIyX1ggPSBuZXcgTGFtYmRhUnVudGltZShcbiAgICBcIm5vZGVqczIyLnhcIixcbiAgICBcIm5vZGUyMlwiLFxuICApO1xuXG4gIC8qKlxuICAgKiBOb2RlLmpzIDI0LnhcbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgcmVhZG9ubHkgTk9ERUpTXzI0X1ggPSBuZXcgTGFtYmRhUnVudGltZShcbiAgICBcIm5vZGVqczI0LnhcIixcbiAgICBcIm5vZGUyNFwiLFxuICApO1xuXG4gIC8qKlxuICAgKiBVc2UgdGhlIGxhdGVzdCBOb2RlLmpzIHJ1bnRpbWUgYXZhaWxhYmxlIGluIHRoZSBkZXBsb3ltZW50IHJlZ2lvbi5cbiAgICpcbiAgICogVGhpcyBnZW5lcmF0ZXMgY29kZSB0aGF0IHVzZXMgYGRldGVybWluZUxhdGVzdE5vZGVSdW50aW1lKClgIGF0IENESyBzeW50aGVzaXMgdGltZSxcbiAgICogd2hpY2ggZHluYW1pY2FsbHkgc2VsZWN0cyB0aGUgbGF0ZXN0IE5vZGUuanMgcnVudGltZSBhdmFpbGFibGUgYmFzZWQgb24gcmVnaW9uYWxcbiAgICogYXZhaWxhYmlsaXR5LiBUaGlzIGVsaW1pbmF0ZXMgdGhlIG5lZWQgdG8gbWFudWFsbHkgdXBkYXRlIHJ1bnRpbWUgdmVyc2lvbnMgYW5kXG4gICAqIGF2b2lkcyBFT0wgd2FybmluZ3MuXG4gICAqXG4gICAqIEBkZWZhdWx0IFVzZXMgZGV0ZXJtaW5lTGF0ZXN0Tm9kZVJ1bnRpbWUoKSBmcm9tIGF3cy1jZGstbGliXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIHJlYWRvbmx5IE5PREVKU19SRUdJT05BTF9MQVRFU1QgPSBuZXcgTGFtYmRhUnVudGltZShcbiAgICBcIk5PREVKU19SRUdJT05BTF9MQVRFU1RcIiwgLy8gTWFya2VyIHZhbHVlXG4gICAgXCJub2RlMjJcIiwgLy8gZXNidWlsZCB0YXJnZXQgKGN1cnJlbnQgTFRTKVxuICApO1xuXG4gIHB1YmxpYyByZWFkb25seSBlc2J1aWxkUGxhdGZvcm0gPSBcIm5vZGVcIjtcblxuICBwdWJsaWMgcmVhZG9ubHkgZGVmYXVsdEV4dGVybmFsczogc3RyaW5nW107XG5cbiAgcHVibGljIGNvbnN0cnVjdG9yKFxuICAgIC8qKlxuICAgICAqIFRoZSBOb2RlLmpzIHJ1bnRpbWUgdG8gdXNlXG4gICAgICovXG4gICAgcHVibGljIHJlYWRvbmx5IGZ1bmN0aW9uUnVudGltZTogc3RyaW5nLFxuXG4gICAgLyoqXG4gICAgICogVGhlIGVzYnVpbGQgc2V0dGluZyB0byB1c2UuXG4gICAgICovXG4gICAgcHVibGljIHJlYWRvbmx5IGVzYnVpbGRUYXJnZXQ6IHN0cmluZyxcblxuICAgIC8qKlxuICAgICAqIE9wdGlvbnMgZm9yIHRoaXMgcnVudGltZS5cbiAgICAgKi9cbiAgICBvcHRpb25zPzogTGFtYmRhUnVudGltZU9wdGlvbnMsXG4gICkge1xuICAgIHRoaXMuZGVmYXVsdEV4dGVybmFscyA9IG9wdGlvbnM/LmRlZmF1bHRFeHRlcm5hbHMgPz8gW1wiQGF3cy1zZGsvKlwiXTtcbiAgfVxufVxuIl19