projen
Version:
CDK for software projects
659 lines • 89.2 kB
JavaScript
"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.TypeScriptAppProject = exports.TypeScriptProject = exports.TsJestTsconfig = exports.TsJestDiagnostics = exports.TsJestBabelConfig = void 0;
exports.mergeTsconfigOptions = mergeTsconfigOptions;
const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
const path = __importStar(require("path"));
const semver = __importStar(require("semver"));
const common_1 = require("../common");
const component_1 = require("../component");
const dependencies_1 = require("../dependencies");
const javascript_1 = require("../javascript");
const util_1 = require("../javascript/util");
const sample_file_1 = require("../sample-file");
const textfile_1 = require("../textfile");
const typescript_1 = require("../typescript");
const util_2 = require("../util");
/**
* @see https://kulshekhar.github.io/ts-jest/docs/getting-started/options/babelConfig/
*/
class TsJestBabelConfig {
config;
static [JSII_RTTI_SYMBOL_1] = { fqn: "projen.typescript.TsJestBabelConfig", version: "0.104.8" };
/**
* Disables the use of Babel
*/
static disabled() {
return new TsJestBabelConfig(false);
}
/**
* Enables Babel processing
*
* `ts-jest` will try to find an existing Babel configuration and pass it to the `babel-jest` processor.
*/
static autoDetectConfig() {
return new TsJestBabelConfig(true);
}
/**
* Path to a babelrc file
*
* The path should be relative to the current working directory where you start Jest from. You can also use `<rootDir>` in the path.
*/
static fromFile(filePath) {
return new TsJestBabelConfig(filePath);
}
/**
* Inline compiler options
* @see https://babeljs.io/docs/options
*/
static custom(config) {
return new TsJestBabelConfig(config);
}
constructor(config) {
this.config = config;
}
/**
* @jsii ignore
* @internal
*/
toJSON() {
return this.config;
}
}
exports.TsJestBabelConfig = TsJestBabelConfig;
/**
* @see https://kulshekhar.github.io/ts-jest/docs/getting-started/options/diagnostics/
*/
class TsJestDiagnostics {
config;
static [JSII_RTTI_SYMBOL_1] = { fqn: "projen.typescript.TsJestDiagnostics", version: "0.104.8" };
/**
* Enable all diagnostics.
*/
static all() {
return new TsJestDiagnostics(true);
}
/**
* Disable all diagnostics.
*/
static none() {
return new TsJestDiagnostics(false);
}
/**
* Provide a custom diagnostics configuration.
*
* @see https://kulshekhar.github.io/ts-jest/docs/getting-started/options/diagnostics/
*/
static custom(config) {
return new TsJestDiagnostics(config);
}
constructor(config) {
this.config = config;
}
/**
* @jsii ignore
* @internal
*/
toJSON() {
return this.config;
}
}
exports.TsJestDiagnostics = TsJestDiagnostics;
/**
* @see https://kulshekhar.github.io/ts-jest/docs/getting-started/options/tsconfig/
*/
class TsJestTsconfig {
config;
static [JSII_RTTI_SYMBOL_1] = { fqn: "projen.typescript.TsJestTsconfig", version: "0.104.8" };
/**
* Uses `tsconfig.json` if found, or the built-in default TypeScript compiler options.
*/
static auto() {
return new TsJestTsconfig(true);
}
/**
* Force` ts-jest` to use its built-in defaults even if there is a `tsconfig.json` in your project.
*/
static builtInDefaults() {
return new TsJestTsconfig(false);
}
/**
* Path to a `tsconfig` file
*
* The path should be relative to the current working directory where you start Jest from. You can also use `<rootDir>` in the path to start from the project root dir.
*/
static fromFile(filePath) {
return new TsJestTsconfig(filePath);
}
/**
* Inline compiler options
*
* @see TypeScriptCompilerOptions
*/
static custom(config) {
return new TsJestTsconfig(config);
}
constructor(config) {
this.config = config;
}
/**
* @jsii ignore
* @internal
*/
toJSON() {
return this.config;
}
}
exports.TsJestTsconfig = TsJestTsconfig;
/**
* TypeScript project
* @pjid typescript
*/
class TypeScriptProject extends javascript_1.NodeProject {
static [JSII_RTTI_SYMBOL_1] = { fqn: "projen.typescript.TypeScriptProject", version: "0.104.8" };
static DEFAULT_TS_JEST_TRANFORM_PATTERN = "^.+\\.[t]sx?$";
docgen;
docsDirectory;
eslint;
tsconfigEslint;
tsconfig;
/**
* A typescript configuration file which covers all files (sources, tests, projen).
*/
tsconfigDev;
/**
* The directory in which the .ts sources reside.
*/
srcdir;
/**
* The directory in which compiled .js files reside.
*/
libdir;
/**
* The directory in which tests reside.
*/
testdir;
/**
* The TypeScript runner used for executing TypeScript files.
*/
runner;
/**
* The "watch" task.
*/
watchTask;
constructor(options) {
super({
...options,
// disable .projenrc.js if typescript is enabled
projenrcJs: options.projenrcTs ? false : options.projenrcJs,
jestOptions: {
...options.jestOptions,
jestConfig: {
...options.jestOptions?.jestConfig,
testMatch: options.jestOptions?.jestConfig?.testMatch ?? [],
},
},
});
this.srcdir = options.srcdir ?? "src";
this.libdir = options.libdir ?? "lib";
this.runner = options.runner ?? typescript_1.TypeScriptRunner.tsNode();
this.runner.tryAttach(this);
this.docgen = options.docgen;
this.docsDirectory = options.docsDirectory ?? "docs/";
const tsconfigFilename = options.tsconfig?.fileName;
this.compileTask.execArgs(["tsc", "--build", tsconfigFilename].filter((a) => a !== undefined));
this.watchTask = this.addTask("watch", {
description: "Watch & compile in the background",
execArgs: ["tsc", "--build", "-w", tsconfigFilename].filter((a) => a !== undefined),
});
this.testdir = options.testdir ?? "test";
this.gitignore.include(`/${this.testdir}/`);
this.npmignore?.exclude(`/${this.testdir}/`);
// if the test directory is under `src/`, then we will run our tests against
// the javascript files and not let jest compile it for us.
const compiledTests = this.testdir.startsWith(this.srcdir + path.posix.sep);
if (options.entrypointTypes || this.package.entrypoint !== "") {
const entrypointPath = path.join(path.dirname(this.package.entrypoint), path.basename(this.package.entrypoint, ".js"));
const normalizedPath = (0, util_2.normalizePersistedPath)(entrypointPath);
const entrypointTypes = options.entrypointTypes ?? `${normalizedPath}.d.ts`;
this.package.addField("types", entrypointTypes);
}
if (options.disableTsconfigDev && options.disableTsconfig) {
throw new Error("Cannot specify both 'disableTsconfigDev' and 'disableTsconfig' fields.");
}
const shouldHaveTsconfig = !options.disableTsconfig;
const shouldHaveDevTsconfig = !options.disableTsconfigDev;
if (shouldHaveTsconfig) {
this.tsconfig = this.makeTsconfig(options);
}
if (shouldHaveDevTsconfig) {
// When a root tsconfig exists, the dev/test config lives inside the test
// directory and extends it; otherwise it is a self-contained config at
// the repository root.
this.tsconfigDev = this.tsconfig
? this.makeDevTsconfig(options, this.tsconfig)
: this.makeStandaloneDevTsconfig(options);
}
else {
// `disableTsconfigDev`: reuse the main tsconfig as the dev config.
this.tsconfigDev = this.tsconfig;
}
this.gitignore.include(`/${this.srcdir}/`);
this.npmignore?.exclude(`/${this.srcdir}/`);
if (this.srcdir !== this.libdir) {
// separated, can ignore the entire libdir
this.gitignore.exclude(`/${this.libdir}`);
}
else {
// collocated, can only ignore the compiled output
this.gitignore.exclude(`/${this.libdir}/**/*.js`);
this.gitignore.exclude(`/${this.libdir}/**/*.d.ts`);
this.gitignore.exclude(`/${this.libdir}/**/*.d.ts.map`);
}
this.npmignore?.include(`/${this.libdir}/`);
this.npmignore?.include(`/${this.libdir}/**/*.js`);
this.npmignore?.include(`/${this.libdir}/**/*.d.ts`);
this.gitignore.exclude("/dist/");
this.npmignore?.exclude("dist"); // jsii-pacmak expects this to be "dist" and not "/dist". otherwise it will tamper with it
this.npmignore?.exclude("/tsconfig.json");
this.npmignore?.exclude("/.github/");
this.npmignore?.exclude("/.vscode/");
this.npmignore?.exclude("/.idea/");
this.npmignore?.exclude("/.projenrc.js");
this.npmignore?.exclude("tsconfig.tsbuildinfo");
if (this.jest) {
if (compiledTests) {
this.addJestCompiled(this.jest);
}
else {
this.addJestNoCompile(this.jest, options?.tsJestOptions);
}
}
if (options.typecheckTests ?? false) {
this.testTask.prependSteps({
name: "Type-check the test suite",
execArgs: ["tsc", "--noEmit", "-p", this.tsconfigDev.fileName],
});
}
// Linter tool selection
// eslint is the default, but if biome has been enabled in the parent class and eslint unset, we default to biome
const biomeEnabled = this.biome != null;
const eslintEnabled = options.eslint ?? !biomeEnabled; // eslint defaults to the opposite of biome
if ((0, util_2.multipleSelected)([biomeEnabled, eslintEnabled])) {
throw new Error("Only one of biome and eslint can be enabled.");
}
if (eslintEnabled) {
this.eslint = new javascript_1.Eslint(this, {
tsconfigPath: `./${(this.tsconfig ?? this.tsconfigDev).fileName}`,
projectService: true,
dirs: [this.srcdir],
devdirs: [this.testdir, "build-tools"],
fileExtensions: [".ts", ".tsx"],
...options.eslintOptions,
});
this.tsconfigEslint = this.tsconfigDev;
}
// Add the src and test directories
// no need to exclude build artifacts: biome ignores files in .gitignore
this.biome?.addFilePattern(`${this.srcdir}/**`);
this.biome?.addFilePattern(`${this.testdir}/**`);
// when this is a root project
if (!this.parent) {
if (options.projenrcTs) {
new typescript_1.Projenrc(this, options.projenrcTsOptions);
}
else {
// projenrc.js created in NodeProject needs to be added in tsconfigDev.
// Only relevant when the dev config lives at the repository root
// (i.e. it was not relocated into the test directory or aliased to the
// root tsconfig); otherwise the include path would not resolve.
const projenrcJs = javascript_1.Projenrc.of(this);
if (projenrcJs && shouldHaveDevTsconfig && !shouldHaveTsconfig) {
this.tsconfigDev.addInclude(projenrcJs.filePath);
}
}
}
const tsDep = options.typescriptVersion
? `typescript@${options.typescriptVersion}`
: "typescript";
this.addDevDeps(tsDep);
this.addNodeTypesVersion(options.typescriptVersion, options.minNodeVersion);
// generate sample code in `src` and `lib` if these directories are empty or non-existent.
if (options.sampleCode ?? true) {
new SampleCode(this);
}
if (this.docgen) {
new typescript_1.TypedocDocgen(this);
}
}
/**
* The main `tsconfig.json` used to compile the project (src -> lib).
*/
makeTsconfig(options) {
return new javascript_1.TypescriptConfig(this, mergeTsconfigOptions({
include: [`${this.srcdir}/**/*.ts`],
exclude: ["node_modules"],
compilerOptions: {
rootDir: this.srcdir,
outDir: this.libdir,
...this.defaultTypeScriptCompilerOptions(),
},
}, options.tsconfig));
}
/**
* The development/test tsconfig, placed inside the test directory so that the
* TypeScript language service picks it up for test files. `tsserver` (and
* editors like VS Code >= 1.114, which bundle TypeScript 6) resolve the
* nearest `tsconfig.json` starting from the source file and no longer
* discover a differently-named config (e.g. `tsconfig.dev.json`) at the root.
*
* It extends the root tsconfig and is type-check only (`noEmit`), so it never
* participates in the build.
*/
makeDevTsconfig(options, tsconfig) {
const tsconfigDevFile = options.tsconfigDevFile ?? `${this.testdir}/tsconfig.json`;
// The root tsconfig sets `rootDir` to the source directory. Since this
// config also type-checks files outside `src` (the tests, and `src` files
// pulled in via imports), point `rootDir` at the project root relative to
// the config's own location to avoid TS6059 ("not under rootDir"). This
// only affects the (suppressed) emit layout.
const rootDir = path.posix.relative(path.posix.dirname(tsconfigDevFile), ".") || ".";
const devTsconfig = new javascript_1.TypescriptConfig(this, mergeTsconfigOptions({
fileName: tsconfigDevFile,
// include is relative to the config's directory (the test dir)
include: ["**/*.ts"],
exclude: ["node_modules"],
compilerOptions: {
// type-check only; the root tsconfig owns compilation
noEmit: true,
rootDir,
},
}, options.tsconfigDev));
// inherit all compiler options (including the dynamically resolved `types`)
// from the root tsconfig.
devTsconfig.addExtends(tsconfig);
return devTsconfig;
}
/**
* A self-contained development tsconfig at the repository root, used when
* there is no root tsconfig to extend (e.g. `disableTsconfig`).
*/
makeStandaloneDevTsconfig(options) {
const tsconfigDevFile = options.tsconfigDevFile ?? "tsconfig.dev.json";
return new javascript_1.TypescriptConfig(this, mergeTsconfigOptions({
fileName: tsconfigDevFile,
include: [`${this.srcdir}/**/*.ts`, `${this.testdir}/**/*.ts`],
exclude: ["node_modules"],
compilerOptions: this.defaultTypeScriptCompilerOptions(),
}, options.tsconfig, options.tsconfigDev));
}
/**
* Projen default Typescript compiler options.
*/
defaultTypeScriptCompilerOptions() {
return {
alwaysStrict: true,
declaration: true,
esModuleInterop: true,
experimentalDecorators: true,
inlineSourceMap: true,
inlineSources: true,
lib: ["es2020"],
module: "CommonJS",
noEmitOnError: false,
noFallthroughCasesInSwitch: true,
noImplicitAny: true,
noImplicitReturns: true,
noImplicitThis: true,
noUnusedLocals: true,
noUnusedParameters: true,
resolveJsonModule: true,
strict: true,
strictNullChecks: true,
strictPropertyInitialization: true,
stripInternal: true,
target: "ES2020",
types: (() => this.resolveInstalledTypes()), // TS6.0 compat, @see https://devblogs.microsoft.com/typescript/announcing-typescript-6-0/#up-front-adjustments
};
}
/**
* Add `@types/node` to this project.
*
* If the user has already added this dependency, do nothing.
* Otherwise use the major version of `minNodeVersion`.
* If that's not available, match the version to the used typescript version.
* And if that is also not available, we use latest and let the user manage the version.
*/
addNodeTypesVersion(tsVersion, minNodeVersion) {
const name = "@types/node";
if (this.deps.tryGetDependency(name, dependencies_1.DependencyType.BUILD)) {
return;
}
if (minNodeVersion) {
const minNodeParsed = semver.minVersion(minNodeVersion);
if (minNodeParsed) {
return this.addDevDeps(`${name}@^${minNodeParsed.major}`);
}
}
// coerce version, since the ts version likely something like ~5.3.0
const tsParsed = semver.coerce(tsVersion);
if (tsParsed) {
return this.addDevDeps(`${name}@ts${tsParsed.major}.${tsParsed.minor}`);
}
this.addDevDeps(name);
}
/**
* Resolve the `types` compiler option from all installed `@types` dependencies.
* Called lazily at synth time so all deps are available.
*/
resolveInstalledTypes() {
return this.deps.all
.filter((d) => d.name.startsWith("@types/") && d.type !== dependencies_1.DependencyType.OVERRIDE)
.map((d) => d.name.replace("@types/", ""));
}
/**
* Tests are compiled to `lib/TESTDIR`, so we don't need jest to compile them
* for us. just run them directly from javascript.
*/
addJestCompiled(jest) {
this.addDevDeps(`@types/jest${jest.jestVersion}`);
const testout = path.posix.relative(this.srcdir, this.testdir);
const libtest = path.posix.join(this.libdir, testout);
const srctest = this.testdir;
this.npmignore?.exclude(`/${libtest}/`);
jest.discoverTestMatchPatternsForDirs([libtest], {
fileExtensionPattern: this.tsconfig?.compilerOptions?.allowJs
? undefined
: "js?(x)",
});
jest.addWatchIgnorePattern(`/${this.srcdir}/`);
const resolveSnapshotPath = (test, ext) => {
const fullpath = test.replace(libtest, srctest);
return path.join(path.dirname(fullpath), "__snapshots__", path.basename(fullpath, ".js") + ".ts" + ext);
};
const resolveTestPath = (snap, ext) => {
const filename = path.basename(snap, ".ts" + ext) + ".js";
const dir = path.dirname(path.dirname(snap)).replace(srctest, libtest);
return path.join(dir, filename);
};
const resolver = new textfile_1.TextFile(this, path.posix.join(common_1.PROJEN_DIR, "jest-snapshot-resolver.js"));
if (!resolver.marker) {
resolver.addLine(`// ${resolver.marker}`);
}
resolver.addLine('const path = require("path");');
resolver.addLine(`const libtest = "${libtest}";`);
resolver.addLine(`const srctest= "${srctest}";`);
resolver.addLine("module.exports = {");
resolver.addLine(` resolveSnapshotPath: ${resolveSnapshotPath.toString()},`);
resolver.addLine(` resolveTestPath: ${resolveTestPath.toString()},`);
resolver.addLine(" testPathForConsistencyCheck: path.join('some', '__tests__', 'example.test.js')");
resolver.addLine("};");
jest.addSnapshotResolver(`./${resolver.path}`);
}
addJestNoCompile(jest, tsJestOptions) {
// Ts-jest doesn't follow semver, but major should match to Jest's major.
// For some reason this is not the case with Jest 30 anymore.
const jestMajor = semver.coerce(jest.jestVersion)?.major ?? 0;
const tsJestVersion = jestMajor > 29 ? "@^29" : jest.jestVersion;
this.addDevDeps(`@types/jest${jest.jestVersion}`, `ts-jest${tsJestVersion}`);
jest.discoverTestMatchPatternsForDirs([this.srcdir, this.testdir], {
fileExtensionPattern: this.tsconfig?.compilerOptions?.allowJs
? undefined
: "ts?(x)",
});
// Test for the ts-jest version that was requested;
//
// - First, check the `jest` version that is requested via projen properties. This
// should be the same as the `ts-jest` version anyway.
// - If none found, fall back to inspecting the actual `ts-jest` version
// that happens to be installed.
let hasTsJest29;
if (jest.jestVersion) {
// We could maybe replace this will full "actual version" checking, but
// the tests depend on this and the reading of 'package.json' is very
// awkward to test.
// Note that we use the requested version of `jest` as a proxy for the
// version of `ts-jest`, which is what we're actually interested in.
const major = semver.coerce(jest.jestVersion)?.major;
hasTsJest29 = major ? major >= 29 : undefined;
}
if (hasTsJest29 === undefined) {
hasTsJest29 = (0, util_1.hasDependencyVersion)(this, "ts-jest", ">= 29");
}
// add relevant deps (we treat "unknown" as having a modern ts-jest)
if (hasTsJest29 !== false) {
return this.addJestNoCompileModern(jest, tsJestOptions);
}
this.addJestNoCompileLegacy(jest, tsJestOptions);
}
addJestNoCompileModern(jest, tsJestOptions) {
jest.config.transform = (0, util_2.deepMerge)([
{
[tsJestOptions?.transformPattern ??
TypeScriptProject.DEFAULT_TS_JEST_TRANFORM_PATTERN]: new javascript_1.Transform("ts-jest", {
tsconfig: TsJestTsconfig.fromFile(this.tsconfigDev.fileName),
...(tsJestOptions?.transformOptions ?? {}),
}),
},
jest.config.transform,
]);
}
addJestNoCompileLegacy(jest, tsJestOptions) {
if (tsJestOptions) {
this.logger.warn("You are using a legacy version (<29) of jest and ts-jest that does not support tsJestOptions, they will be ignored.");
}
if (!jest.config.preset) {
jest.config.preset = "ts-jest";
}
jest.config.globals = (0, util_2.deepMerge)([
{
"ts-jest": {
tsconfig: this.tsconfigDev.fileName,
},
},
jest.config.globals,
]);
}
}
exports.TypeScriptProject = TypeScriptProject;
class SampleCode extends component_1.Component {
constructor(project) {
super(project);
const srcCode = [
"export class Hello {",
" public sayHello() {",
" return 'hello, world!';",
" }",
"}",
].join("\n");
const testCode = [
"import { Hello } from '../src';",
"",
"test('hello', () => {",
" expect(new Hello().sayHello()).toBe('hello, world!');",
"});",
].join("\n");
new sample_file_1.SampleDir(project, project.srcdir, {
files: {
"index.ts": srcCode,
},
});
if (project.jest) {
new sample_file_1.SampleDir(project, project.testdir, {
files: {
"hello.test.ts": testCode,
},
});
}
}
}
/**
* TypeScript app.
*
* @pjid typescript-app
*/
class TypeScriptAppProject extends TypeScriptProject {
static [JSII_RTTI_SYMBOL_1] = { fqn: "projen.typescript.TypeScriptAppProject", version: "0.104.8" };
constructor(options) {
// Releasing and packaging are coupled. If one is disabled, disable the other by default.
const shouldRelease = options.release ?? false;
super({
release: shouldRelease,
package: shouldRelease,
allowLibraryDependencies: false,
entrypoint: "", // "main" is not needed in typescript apps
...options,
});
}
}
exports.TypeScriptAppProject = TypeScriptAppProject;
/**
* @internal
*/
function mergeTsconfigOptions(...options) {
const definedOptions = options.filter(Boolean);
return definedOptions.reduce((previous, current) => ({
...previous,
...current,
include: [...(previous.include ?? []), ...(current.include ?? [])],
exclude: [...(previous.exclude ?? []), ...(current.exclude ?? [])],
compilerOptions: {
...previous.compilerOptions,
...current.compilerOptions,
},
}), { compilerOptions: {} });
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHlwZXNjcmlwdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy90eXBlc2NyaXB0L3R5cGVzY3JpcHQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBKzlCQSxvREFpQkM7O0FBaC9CRCwyQ0FBNkI7QUFDN0IsK0NBQWlDO0FBQ2pDLHNDQUF1QztBQUN2Qyw0Q0FBeUM7QUFDekMsa0RBQWlEO0FBUWpELDhDQU11QjtBQUN2Qiw2Q0FBMEQ7QUFDMUQsZ0RBQTJDO0FBRTNDLDBDQUF1QztBQUV2Qyw4Q0FJdUI7QUFDdkIsa0NBQThFO0FBRTlFOztHQUVHO0FBQ0gsTUFBYSxpQkFBaUI7SUFtQ1Q7O0lBbENuQjs7T0FFRztJQUNJLE1BQU0sQ0FBQyxRQUFRO1FBQ3BCLE9BQU8sSUFBSSxpQkFBaUIsQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUN0QyxDQUFDO0lBRUQ7Ozs7T0FJRztJQUNJLE1BQU0sQ0FBQyxnQkFBZ0I7UUFDNUIsT0FBTyxJQUFJLGlCQUFpQixDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ3JDLENBQUM7SUFFRDs7OztPQUlHO0lBQ0ksTUFBTSxDQUFDLFFBQVEsQ0FBQyxRQUFnQjtRQUNyQyxPQUFPLElBQUksaUJBQWlCLENBQUMsUUFBUSxDQUFDLENBQUM7SUFDekMsQ0FBQztJQUVEOzs7T0FHRztJQUNJLE1BQU0sQ0FBQyxNQUFNLENBQUMsTUFBMkI7UUFDOUMsT0FBTyxJQUFJLGlCQUFpQixDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQ3ZDLENBQUM7SUFFRCxZQUNtQixNQUE4QztRQUE5QyxXQUFNLEdBQU4sTUFBTSxDQUF3QztJQUM5RCxDQUFDO0lBRUo7OztPQUdHO0lBQ0ksTUFBTTtRQUNYLE9BQU8sSUFBSSxDQUFDLE1BQU0sQ0FBQztJQUNyQixDQUFDOztBQTVDSCw4Q0E2Q0M7QUFFRDs7R0FFRztBQUNILE1BQWEsaUJBQWlCO0lBd0JTOztJQXZCckM7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YXMgcGF0aCBmcm9tIFwicGF0aFwiO1xuaW1wb3J0ICogYXMgc2VtdmVyIGZyb20gXCJzZW12ZXJcIjtcbmltcG9ydCB7IFBST0pFTl9ESVIgfSBmcm9tIFwiLi4vY29tbW9uXCI7XG5pbXBvcnQgeyBDb21wb25lbnQgfSBmcm9tIFwiLi4vY29tcG9uZW50XCI7XG5pbXBvcnQgeyBEZXBlbmRlbmN5VHlwZSB9IGZyb20gXCIuLi9kZXBlbmRlbmNpZXNcIjtcbmltcG9ydCB0eXBlIHtcbiAgRXNsaW50T3B0aW9ucyxcbiAgSmVzdCxcbiAgTm9kZVByb2plY3RPcHRpb25zLFxuICBUeXBlU2NyaXB0Q29tcGlsZXJPcHRpb25zLFxuICBUeXBlc2NyaXB0Q29uZmlnT3B0aW9ucyxcbn0gZnJvbSBcIi4uL2phdmFzY3JpcHRcIjtcbmltcG9ydCB7XG4gIEVzbGludCxcbiAgTm9kZVByb2plY3QsXG4gIFByb2plbnJjIGFzIE5vZGVQcm9qZWN0UHJvamVucmMsXG4gIFRyYW5zZm9ybSxcbiAgVHlwZXNjcmlwdENvbmZpZyxcbn0gZnJvbSBcIi4uL2phdmFzY3JpcHRcIjtcbmltcG9ydCB7IGhhc0RlcGVuZGVuY3lWZXJzaW9uIH0gZnJvbSBcIi4uL2phdmFzY3JpcHQvdXRpbFwiO1xuaW1wb3J0IHsgU2FtcGxlRGlyIH0gZnJvbSBcIi4uL3NhbXBsZS1maWxlXCI7XG5pbXBvcnQgdHlwZSB7IFRhc2sgfSBmcm9tIFwiLi4vdGFza1wiO1xuaW1wb3J0IHsgVGV4dEZpbGUgfSBmcm9tIFwiLi4vdGV4dGZpbGVcIjtcbmltcG9ydCB0eXBlIHsgUHJvamVucmNPcHRpb25zIGFzIFByb2plbnJjVHNPcHRpb25zIH0gZnJvbSBcIi4uL3R5cGVzY3JpcHRcIjtcbmltcG9ydCB7XG4gIFByb2plbnJjIGFzIFByb2plbnJjVHMsXG4gIFR5cGVkb2NEb2NnZW4sXG4gIFR5cGVTY3JpcHRSdW5uZXIsXG59IGZyb20gXCIuLi90eXBlc2NyaXB0XCI7XG5pbXBvcnQgeyBkZWVwTWVyZ2UsIG11bHRpcGxlU2VsZWN0ZWQsIG5vcm1hbGl6ZVBlcnNpc3RlZFBhdGggfSBmcm9tIFwiLi4vdXRpbFwiO1xuXG4vKipcbiAqIEBzZWUgaHR0cHM6Ly9rdWxzaGVraGFyLmdpdGh1Yi5pby90cy1qZXN0L2RvY3MvZ2V0dGluZy1zdGFydGVkL29wdGlvbnMvYmFiZWxDb25maWcvXG4gKi9cbmV4cG9ydCBjbGFzcyBUc0plc3RCYWJlbENvbmZpZyB7XG4gIC8qKlxuICAgKiBEaXNhYmxlcyB0aGUgdXNlIG9mIEJhYmVsXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIGRpc2FibGVkKCkge1xuICAgIHJldHVybiBuZXcgVHNKZXN0QmFiZWxDb25maWcoZmFsc2UpO1xuICB9XG5cbiAgLyoqXG4gICAqIEVuYWJsZXMgQmFiZWwgcHJvY2Vzc2luZ1xuICAgKlxuICAgKiBgdHMtamVzdGAgd2lsbCB0cnkgdG8gZmluZCBhbiBleGlzdGluZyBCYWJlbCBjb25maWd1cmF0aW9uIGFuZCBwYXNzIGl0IHRvIHRoZSBgYmFiZWwtamVzdGAgcHJvY2Vzc29yLlxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBhdXRvRGV0ZWN0Q29uZmlnKCkge1xuICAgIHJldHVybiBuZXcgVHNKZXN0QmFiZWxDb25maWcodHJ1ZSk7XG4gIH1cblxuICAvKipcbiAgICogUGF0aCB0byBhIGJhYmVscmMgZmlsZVxuICAgKlxuICAgKiBUaGUgcGF0aCBzaG91bGQgYmUgcmVsYXRpdmUgdG8gdGhlIGN1cnJlbnQgd29ya2luZyBkaXJlY3Rvcnkgd2hlcmUgeW91IHN0YXJ0IEplc3QgZnJvbS4gWW91IGNhbiBhbHNvIHVzZSBgPHJvb3REaXI+YCBpbiB0aGUgcGF0aC5cbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgZnJvbUZpbGUoZmlsZVBhdGg6IHN0cmluZykge1xuICAgIHJldHVybiBuZXcgVHNKZXN0QmFiZWxDb25maWcoZmlsZVBhdGgpO1xuICB9XG5cbiAgLyoqXG4gICAqIElubGluZSBjb21waWxlciBvcHRpb25zXG4gICAqIEBzZWUgaHR0cHM6Ly9iYWJlbGpzLmlvL2RvY3Mvb3B0aW9uc1xuICAgKi9cbiAgcHVibGljIHN0YXRpYyBjdXN0b20oY29uZmlnOiBSZWNvcmQ8c3RyaW5nLCBhbnk+KSB7XG4gICAgcmV0dXJuIG5ldyBUc0plc3RCYWJlbENvbmZpZyhjb25maWcpO1xuICB9XG5cbiAgcHJpdmF0ZSBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIHJlYWRvbmx5IGNvbmZpZzogYm9vbGVhbiB8IHN0cmluZyB8IFJlY29yZDxzdHJpbmcsIGFueT4sXG4gICkge31cblxuICAvKipcbiAgICogQGpzaWkgaWdub3JlXG4gICAqIEBpbnRlcm5hbFxuICAgKi9cbiAgcHVibGljIHRvSlNPTigpOiBib29sZWFuIHwgc3RyaW5nIHwgUmVjb3JkPHN0cmluZywgYW55PiB7XG4gICAgcmV0dXJuIHRoaXMuY29uZmlnO1xuICB9XG59XG5cbi8qKlxuICogQHNlZSBodHRwczovL2t1bHNoZWtoYXIuZ2l0aHViLmlvL3RzLWplc3QvZG9jcy9nZXR0aW5nLXN0YXJ0ZWQvb3B0aW9ucy9kaWFnbm9zdGljcy9cbiAqL1xuZXhwb3J0IGNsYXNzIFRzSmVzdERpYWdub3N0aWNzIHtcbiAgLyoqXG4gICAqIEVuYWJsZSBhbGwgZGlhZ25vc3RpY3MuXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIGFsbCgpIHtcbiAgICByZXR1cm4gbmV3IFRzSmVzdERpYWdub3N0aWNzKHRydWUpO1xuICB9XG5cbiAgLyoqXG4gICAqIERpc2FibGUgYWxsIGRpYWdub3N0aWNzLlxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBub25lKCkge1xuICAgIHJldHVybiBuZXcgVHNKZXN0RGlhZ25vc3RpY3MoZmFsc2UpO1xuICB9XG5cbiAgLyoqXG4gICAqIFByb3ZpZGUgYSBjdXN0b20gZGlhZ25vc3RpY3MgY29uZmlndXJhdGlvbi5cbiAgICpcbiAgICogQHNlZSBodHRwczovL2t1bHNoZWtoYXIuZ2l0aHViLmlvL3RzLWplc3QvZG9jcy9nZXR0aW5nLXN0YXJ0ZWQvb3B0aW9ucy9kaWFnbm9zdGljcy9cbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgY3VzdG9tKGNvbmZpZzogUmVjb3JkPHN0cmluZywgYW55Pikge1xuICAgIHJldHVybiBuZXcgVHNKZXN0RGlhZ25vc3RpY3MoY29uZmlnKTtcbiAgfVxuXG4gIHByaXZhdGUgY29uc3RydWN0b3IocHJpdmF0ZSByZWFkb25seSBjb25maWc6IGJvb2xlYW4gfCBSZWNvcmQ8c3RyaW5nLCBhbnk+KSB7fVxuXG4gIC8qKlxuICAgKiBAanNpaSBpZ25vcmVcbiAgICogQGludGVybmFsXG4gICAqL1xuICBwdWJsaWMgdG9KU09OKCk6IGJvb2xlYW4gfCBSZWNvcmQ8c3RyaW5nLCBhbnk+IHtcbiAgICByZXR1cm4gdGhpcy5jb25maWc7XG4gIH1cbn1cblxuLyoqXG4gKiBAc2VlIGh0dHBzOi8va3Vsc2hla2hhci5naXRodWIuaW8vdHMtamVzdC9kb2NzL2dldHRpbmctc3RhcnRlZC9vcHRpb25zL3RzY29uZmlnL1xuICovXG5leHBvcnQgY2xhc3MgVHNKZXN0VHNjb25maWcge1xuICAvKipcbiAgICogVXNlcyBgdHNjb25maWcuanNvbmAgaWYgZm91bmQsIG9yIHRoZSBidWlsdC1pbiBkZWZhdWx0IFR5cGVTY3JpcHQgY29tcGlsZXIgb3B0aW9ucy5cbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgYXV0bygpIHtcbiAgICByZXR1cm4gbmV3IFRzSmVzdFRzY29uZmlnKHRydWUpO1xuICB9XG5cbiAgLyoqXG4gICAqIEZvcmNlYCB0cy1qZXN0YCB0byB1c2UgaXRzIGJ1aWx0LWluIGRlZmF1bHRzIGV2ZW4gaWYgdGhlcmUgaXMgYSBgdHNjb25maWcuanNvbmAgaW4geW91ciBwcm9qZWN0LlxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBidWlsdEluRGVmYXVsdHMoKSB7XG4gICAgcmV0dXJuIG5ldyBUc0plc3RUc2NvbmZpZyhmYWxzZSk7XG4gIH1cblxuICAvKipcbiAgICogUGF0aCB0byBhIGB0c2NvbmZpZ2AgZmlsZVxuICAgKlxuICAgKiBUaGUgcGF0aCBzaG91bGQgYmUgcmVsYXRpdmUgdG8gdGhlIGN1cnJlbnQgd29ya2luZyBkaXJlY3Rvcnkgd2hlcmUgeW91IHN0YXJ0IEplc3QgZnJvbS4gWW91IGNhbiBhbHNvIHVzZSBgPHJvb3REaXI+YCBpbiB0aGUgcGF0aCB0byBzdGFydCBmcm9tIHRoZSBwcm9qZWN0IHJvb3QgZGlyLlxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBmcm9tRmlsZShmaWxlUGF0aDogc3RyaW5nKSB7XG4gICAgcmV0dXJuIG5ldyBUc0plc3RUc2NvbmZpZyhmaWxlUGF0aCk7XG4gIH1cblxuICAvKipcbiAgICogSW5saW5lIGNvbXBpbGVyIG9wdGlvbnNcbiAgICpcbiAgICogQHNlZSBUeXBlU2NyaXB0Q29tcGlsZXJPcHRpb25zXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIGN1c3RvbShjb25maWc6IFR5cGVTY3JpcHRDb21waWxlck9wdGlvbnMpIHtcbiAgICByZXR1cm4gbmV3IFRzSmVzdFRzY29uZmlnKGNvbmZpZyk7XG4gIH1cblxuICBwcml2YXRlIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgcmVhZG9ubHkgY29uZmlnOiBib29sZWFuIHwgc3RyaW5nIHwgVHlwZVNjcmlwdENvbXBpbGVyT3B0aW9ucyxcbiAgKSB7fVxuXG4gIC8qKlxuICAgKiBAanNpaSBpZ25vcmVcbiAgICogQGludGVybmFsXG4gICAqL1xuICBwdWJsaWMgdG9KU09OKCk6IGJvb2xlYW4gfCBzdHJpbmcgfCBUeXBlU2NyaXB0Q29tcGlsZXJPcHRpb25zIHtcbiAgICByZXR1cm4gdGhpcy5jb25maWc7XG4gIH1cbn1cblxuLyoqXG4gKiBAc2VlIGh0dHBzOi8va3Vsc2hla2hhci5naXRodWIuaW8vdHMtamVzdC9kb2NzL2dldHRpbmctc3RhcnRlZC9vcHRpb25zXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgVHNKZXN0VHJhbnNmb3JtT3B0aW9ucyB7XG4gIC8qKlxuICAgKiBDdXN0b20gVHlwZVNjcmlwdCBBU1QgdHJhbnNmb3JtZXJzXG4gICAqXG4gICAqIEBkZWZhdWx0IGF1dG9cbiAgICovXG4gIHJlYWRvbmx5IGFzdFRyYW5zZm9ybWVycz86IFJlY29yZDxzdHJpbmcsIGFueT47XG4gIC8qKlxuICAgKiBCYWJlbChKZXN0KSByZWxhdGVkIGNvbmZpZ3VyYXRpb24uXG4gICAqXG4gICAqIEBkZWZhdWx0IFRzSmVzdEJhYmVsQ29uZmlnLmRpc2FibGVkKClcbiAgICovXG4gIHJlYWRvbmx5IGJhYmVsQ29uZmlnPzogVHNKZXN0QmFiZWxDb25maWc7XG4gIC8qKlxuICAgKiBUeXBlU2NyaXB0IG1vZHVsZSB0byB1c2UgYXMgY29tcGlsZXIuXG4gICAqXG4gICAqIEBkZWZhdWx0IFwidHlwZXNjcmlwdFwiXG4gICAqL1xuICByZWFkb25seSBjb21waWxlcj86IHN0cmluZztcbiAgLyoqXG4gICAqIERpYWdub3N0aWNzIHJlbGF0ZWQgY29uZmlndXJhdGlvbi5cbiAgICpcbiAgICogQGRlZmF1bHQgVHNKZXN0RGlhZ25vc3RpY3MuYWxsKClcbiAgICovXG4gIHJlYWRvbmx5IGRpYWdub3N0aWNzPzogVHNKZXN0RGlhZ25vc3RpY3M7XG4gIC8qKlxuICAgKiBSdW4gdHMtamVzdCB0ZXN0cyB3aXRoIHRoaXMgVFNDb25maWcgaXNvbGF0ZWRNb2R1bGVzIHNldHRpbmcuXG4gICAqXG4gICAqIFlvdSdsbCBsb3NlIHR5cGUtY2hlY2tpbmcgYWJpbGl0eSBhbmQgc29tZSBmZWF0dXJlcyBzdWNoIGFzIGNvbnN0IGVudW0sIGJ1dCBpbiB0aGUgY2FzZSB5b3UgcGxhbiBvbiB1c2luZyBKZXN0IHdpdGggdGhlIGNhY2hlIGRpc2FibGVkIChqZXN0IC0tbm8tY2FjaGUpLCB5b3VyIHRlc3RzIHdpbGwgdGhlbiBydW4gbXVjaCBmYXN0ZXIuXG4gICAqIEBzZWUgaHR0cHM6Ly9rdWxzaGVraGFyLmdpdGh1Yi5pby90cy1qZXN0L2RvY3MvZ2V0dGluZy1zdGFydGVkL29wdGlvbnMvaXNvbGF0ZWRNb2R1bGVzXG4gICAqXG4gICAqIEBkZWZhdWx0IGZhbHNlXG4gICAqL1xuICByZWFkb25seSBpc29sYXRlZE1vZHVsZXM/OiBib29sZWFuO1xuICAvKipcbiAgICogRmlsZXMgd2hpY2ggd2lsbCBiZWNvbWUgbW9kdWxlcyByZXR1cm5pbmcgc2VsZiBjb250ZW50LlxuICAgKlxuICAgKiBAZGVmYXVsdCBkaXNhYmxlZFxuICAgKi9cbiAgcmVhZG9ubHkgc3RyaW5naWZ5Q29udGVudFBhdGhSZWdleD86IHN0cmluZztcbiAgLyoqXG4gICAqIFR5cGVTY3JpcHQgY29tcGlsZXIgcmVsYXRlZCBjb25maWd1cmF0aW9uLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIFlvdXIgcHJvamVjdCdzIGB0c2NvbmZpZ0RldmAgZmlsZS5cbiAgICovXG4gIHJlYWRvbmx5IHRzY29uZmlnPzogVHNKZXN0VHNjb25maWc7XG4gIC8qKlxuICAgKiBFbmFibGUgRVNNIHN1cHBvcnRcbiAgICpcbiAgICogQGRlZmF1bHQgYXV0b1xuICAgKi9cbiAgcmVhZG9ubHkgdXNlRVNNPzogYm9vbGVhbjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBUc0plc3RPcHRpb25zIHtcbiAgLyoqXG4gICAqIFdoaWNoIGZpbGVzIHNob3VsZCB0cy1qZXN0IGFjdCB1cG9uLlxuICAgKlxuICAgKiBAc2VlIGh0dHBzOi8vamVzdGpzLmlvL2RvY3MvY29uZmlndXJhdGlvbiN0cmFuc2Zvcm0tb2JqZWN0c3RyaW5nLXBhdGh0b3RyYW5zZm9ybWVyLS1wYXRodG90cmFuc2Zvcm1lci1vYmplY3RcbiAgICpcbiAgICogQGRlZmF1bHQgXCJeLitcXFxcLlt0XXN4PyRcIlxuICAgKi9cbiAgcmVhZG9ubHkgdHJhbnNmb3JtUGF0dGVybj86IHN0cmluZztcbiAgLyoqXG4gICAqIE92ZXJyaWRlIHRoZSBkZWZhdWx0IHRzLWplc3QgdHJhbnNmb3JtZXIgY29uZmlndXJhdGlvbi5cbiAgICovXG4gIHJlYWRvbmx5IHRyYW5zZm9ybU9wdGlvbnM/OiBUc0plc3RUcmFuc2Zvcm1PcHRpb25zO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFR5cGVTY3JpcHRQcm9qZWN0T3B0aW9ucyBleHRlbmRzIE5vZGVQcm9qZWN0T3B0aW9ucyB7XG4gIC8qKlxuICAgKiBUeXBlc2NyaXB0ICBhcnRpZmFjdHMgb3V0cHV0IGRpcmVjdG9yeVxuICAgKlxuICAgKiBXaGVuIGBsaWJkaXJgIGlzIGNoYW5nZWQsIHNldCBgZW50cnlwb2ludGAgdG8gbWF0Y2ggaXQgKGZvciBleGFtcGxlXG4gICAqIGBsaWJkaXI6IFwiZGlzdFwiYCB3aXRoIGBlbnRyeXBvaW50OiBcImRpc3QvaW5kZXguanNcImApLiBgdHlwZXNgIGZvbGxvd3MgdGhlXG4gICAqIGVudHJ5cG9pbnQgcmF0aGVyIHRoYW4gYGxpYmRpcmAsIGFuZCBgbWFpbmAgc3RpbGwgZGVmYXVsdHMgdG9cbiAgICogYGxpYi9pbmRleC5qc2AuXG4gICAqXG4gICAqIEBkZWZhdWx0IFwibGliXCJcbiAgICovXG4gIHJlYWRvbmx5IGxpYmRpcj86IHN0cmluZztcblxuICAvKipcbiAgICogVHlwZXNjcmlwdCBzb3VyY2VzIGRpcmVjdG9yeS5cbiAgICpcbiAgICogQGRlZmF1bHQgXCJzcmNcIlxuICAgKi9cbiAgcmVhZG9ubHkgc3JjZGlyPzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBKZXN0IHRlc3RzIGRpcmVjdG9yeS4gVGVzdHMgZmlsZXMgc2hvdWxkIGJlIG5hbWVkIGB4eHgudGVzdC50c2AuXG4gICAqXG4gICAqIElmIHRoaXMgZGlyZWN0b3J5IGlzIHVuZGVyIGBzcmNkaXJgIChlLmcuIGBzcmMvdGVzdGAsIGBzcmMvX190ZXN0c19fYCksXG4gICAqIHRoZW4gdGVzdHMgYXJlIGdvaW5nIHRvIGJlIGNvbXBpbGVkIGludG8gYGxpYi9gIGFuZCBleGVjdXRlZCBhcyBqYXZhc2NyaXB0LlxuICAgKiBJZiB0aGUgdGVzdCBkaXJlY3RvcnkgaXMgb3V0c2lkZSBvZiBgc3JjYCwgdGhlbiB3ZSBjb25maWd1cmUgamVzdCB0b1xuICAgKiBjb21waWxlIHRoZSBjb2RlIGluLW1lbW9yeS5cbiAgICpcbiAgICogQGRlZmF1bHQgXCJ0ZXN0XCJcbiAgICovXG4gIHJlYWRvbmx5IHRlc3RkaXI/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFNldHVwIGVzbGludC5cbiAgICpcbiAgICogQGRlZmF1bHQgLSB0cnVlLCB1bmxlc3MgYmlvbWUgaXMgZW5hYmxlZFxuICAgKi9cbiAgcmVhZG9ubHkgZXNsaW50PzogYm9vbGVhbjtcblxuICAvKipcbiAgICogRXNsaW50IG9wdGlvbnNcbiAgICogQGRlZmF1bHQgLSBvcGluaW9uYXRlZCBkZWZhdWx0IG9wdGlvbnNcbiAgICovXG4gIHJlYWRvbmx5IGVzbGludE9wdGlvbnM/OiBFc2xpbnRPcHRpb25zO1xuXG4gIC8qKlxuICAgKiBUeXBlU2NyaXB0IHZlcnNpb24gdG8gdXNlLlxuICAgKlxuICAgKiBOT1RFOiBUeXBlc2NyaXB0IGlzIG5vdCBzZW1hbnRpY2FsbHkgdmVyc2lvbmVkIGFuZCBzaG91bGQgcmVtYWluIG9uIHRoZVxuICAgKiBzYW1lIG1pbm9yLCBzbyB3ZSByZWNvbW1lbmQgdXNpbmcgYSBgfmAgZGVwZW5kZW5jeSAoZS5nLiBgfjEuMi4zYCkuXG4gICAqXG4gICAqIEBkZWZhdWx0IFwibGF0ZXN0XCJcbiAgICovXG4gIHJlYWRvbmx5IHR5cGVzY3JpcHRWZXJzaW9uPzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBEb2NnZW4gYnkgVHlwZWRvY1xuICAgKlxuICAgKiBAZGVmYXVsdCBmYWxzZVxuICAgKi9cbiAgcmVhZG9ubHkgZG9jZ2VuPzogYm9vbGVhbjtcblxuICAvKipcbiAgICogRG9jcyBkaXJlY3RvcnlcbiAgICpcbiAgICogQGRlZmF1bHQgXCJkb2NzXCJcbiAgICovXG4gIHJlYWRvbmx5IGRvY3NEaXJlY3Rvcnk/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIEN1c3RvbSBUU0NvbmZpZ1xuICAgKiBAZGVmYXVsdCAtIGRlZmF1bHQgb3B0aW9uc1xuICAgKi9cbiAgcmVhZG9ubHkgdHNjb25maWc/OiBUeXBlc2NyaXB0Q29uZmlnT3B0aW9ucztcblxuICAvKipcbiAgICogQ3VzdG9tIHRzY29uZmlnIG9wdGlvbnMgZm9yIHRoZSBkZXZlbG9wbWVudCB0c2NvbmZpZy5qc29uIGZpbGUgKHVzZWQgZm9yIHRlc3RpbmcpLlxuICAgKiBAZGVmYXVsdCAtIHVzZSB0aGUgcHJvZHVjdGlvbiB0c2NvbmZpZyBvcHRpb25zXG4gICAqL1xuICByZWFkb25seSB0c2NvbmZpZ0Rldj86IFR5cGVzY3JpcHRDb25maWdPcHRpb25zO1xuXG4gIC8qKlxuICAgKiBUaGUgbmFtZSAoYW5kIHBhdGgpIG9mIHRoZSBkZXZlbG9wbWVudCB0c2NvbmZpZyBmaWxlLlxuICAgKlxuICAgKiBCeSBkZWZhdWx0IHRoaXMgbGl2ZXMgaW5zaWRlIHRoZSB0ZXN0IGRpcmVjdG9yeSAoZS5nLiBgdGVzdC90c2NvbmZpZy5qc29uYClcbiAgICogc28gdGhhdCB0aGUgVHlwZVNjcmlwdCBsYW5ndWFnZSBzZXJ2aWNlIHJlc29sdmVzIGl0IGFzIHRoZSBuZWFyZXN0IGNvbmZpZ1xuICAgKiBmb3IgdGVzdCBmaWxlcy5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBcInt0ZXN0ZGlyfS90c2NvbmZpZy5qc29uXCJcbiAgICovXG4gIHJlYWRvbmx5IHRzY29uZmlnRGV2RmlsZT86IHN0cmluZztcblxuICAvKipcbiAgICogRG8gbm90IGdlbmVyYXRlIGEgYHRzY29uZmlnLmpzb25gIGZpbGUgKHVzZWQgYnkganNpaSBwcm9qZWN0cyBzaW5jZVxuICAgKiB0c2NvbmZpZy5qc29uIGlzIGdlbmVyYXRlZCBieSB0aGUganNpaSBjb21waWxlcikuXG4gICAqXG4gICAqIEBkZWZhdWx0IGZhbHNlXG4gICAqL1xuICByZWFkb25seSBkaXNhYmxlVHNjb25maWc/OiBib29sZWFuO1xuICAvKipcbiAgICogRG8gbm90IGdlbmVyYXRlIGEgZGV2ZWxvcG1lbnQgdHNjb25maWcgZmlsZS5cbiAgICpcbiAgICogQGRlZmF1bHQgZmFsc2VcbiAgICovXG4gIHJlYWRvbmx5IGRpc2FibGVUc2NvbmZpZ0Rldj86IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIEdlbmVyYXRlIG9uZS10aW1lIHNhbXBsZSBpbiBgc3JjL2AgYW5kIGB0ZXN0L2AgaWYgdGhlcmUgYXJlIG5vIGZpbGVzIHRoZXJlLlxuICAgKiBAZGVmYXVsdCB0cnVlXG4gICAqL1xuICByZWFkb25seSBzYW1wbGVDb2RlPzogYm9vbGVhbjtcblxuICAvKipcbiAgICogVGhlIC5kLnRzIGZpbGUgdGhhdCBpbmNsdWRlcyB0aGUgdHlwZSBkZWNsYXJhdGlvbnMgZm9yIHRoaXMgbW9kdWxlLlxuICAgKiBAZGVmYXVsdCAtIC5kLnRzIGZpbGUgZGVyaXZlZCBmcm9tIHRoZSBwcm9qZWN0J3MgZW50cnlwb2ludCAodXN1YWxseSBsaWIvaW5kZXguZC50cylcbiAgICovXG4gIHJlYWRvbmx5IGVudHJ5cG9pbnRUeXBlcz86IHN0cmluZztcblxuICAvKipcbiAgICogVXNlIFR5cGVTY3JpcHQgZm9yIHlvdXIgcHJvamVucmMgZmlsZSAoYC5wcm9qZW5yYy50c2ApLlxuICAgKlxuICAgKiBAZGVmYXVsdCBmYWxzZVxuICAgKiBAcGpuZXcgdHJ1ZVxuICAgKi9cbiAgcmVhZG9ubHkgcHJvamVucmNUcz86IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIE9wdGlvbnMgZm9yIC5wcm9qZW5yYy50c1xuICAgKi9cbiAgcmVhZG9ubHkgcHJvamVucmNUc09wdGlvbnM/OiBQcm9qZW5yY1RzT3B0aW9ucztcblxuICAvKipcbiAgICogVGhlIFR5cGVTY3JpcHQgcnVubmVyIHRvIHVzZSBmb3IgZXhlY3V0aW5nIFR5cGVTY3JpcHQgZmlsZXMuXG4gICAqXG4gICAqIFRoaXMgaXMgYSBwcm9qZWN0LWxldmVsIHNldHRpbmcgdGhhdCBjb21wb25lbnRzIChlLmcuIHByb2plbnJjKSB3aWxsXG4gICAqIHVzZSBhcyB0aGVpciBkZWZhdWx0IHJ1bm5lci5cbiAgICpcbiAgICogQGRlZmF1bHQgVHlwZVNjcmlwdFJ1bm5lci50c05vZGUoKVxuICAgKi9cbiAgcmVhZG9ubHkgcnVubmVyPzogVHlwZVNjcmlwdFJ1bm5lcjtcblxuICAvKipcbiAgICogT3B0aW9ucyBmb3IgdHMtamVzdFxuICAgKi9cbiAgcmVhZG9ubHkgdHNKZXN0T3B0aW9ucz86IFRzSmVzdE9wdGlvbnM7XG5cbiAgLyoqXG4gICAqIFR5cGUtY2hlY2sgdGhlIHRlc3Qgc3VpdGUgYXMgcGFydCBvZiB0aGUgYHRlc3RgIHRhc2suXG4gICAqXG4gICAqIEFkZHMgYSBgdHNjIC0tbm9FbWl0YCBzdGVwIGFnYWluc3QgdGhlIGRldmVsb3BtZW50IHRzY29uZmlnLlxuICAgKlxuICAgKiBAZGVmYXVsdCBmYWxzZVxuICAgKi9cbiAgcmVhZG9ubHkgdHlwZWNoZWNrVGVzdHM/OiBib29sZWFuO1xufVxuXG4vKipcbiAqIFR5cGVTY3JpcHQgcHJvamVjdFxuICogQHBqaWQgdHlwZXNjcmlwdFxuICovXG5leHBvcnQgY2xhc3MgVHlwZVNjcmlwdFByb2plY3QgZXh0ZW5kcyBOb2RlUHJvamVjdCB7XG4gIHB1YmxpYyBzdGF0aWMgcmVhZG9ubHkgREVGQVVMVF9UU19KRVNUX1RSQU5GT1JNX1BBVFRFUk4gPSBcIl4uK1xcXFwuW3Rdc3g/JFwiO1xuXG4gIHB1YmxpYyByZWFkb25seSBkb2NnZW4/OiBib29sZWFuO1xuICBwdWJsaWMgcmVhZG9ubHkgZG9jc0RpcmVjdG9yeTogc3RyaW5nO1xuICBwdWJsaWMgcmVhZG9ubHkgZXNsaW50PzogRXNsaW50O1xuICBwdWJsaWMgcmVhZG9ubHkgdHNjb25maWdFc2xpbnQ/OiBUeXBlc2NyaXB0Q29uZmlnO1xuICBwdWJsaWMgcmVhZG9ubHkgdHNjb25maWc/OiBUeXBlc2NyaXB0Q29uZmlnO1xuXG4gIC8qKlxuICAgKiBBIHR5cGVzY3JpcHQgY29uZmlndXJhdGlvbiBmaWxlIHdoaWNoIGNvdmVycyBhbGwgZmlsZXMgKHNvdXJjZXMsIHRlc3RzLCBwcm9qZW4pLlxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IHRzY29uZmlnRGV2OiBUeXBlc2NyaXB0Q29uZmlnO1xuXG4gIC8qKlxuICAgKiBUaGUgZGlyZWN0b3J5IGluIHdoaWNoIHRoZSAudHMgc291cmNlcyByZXNpZGUuXG4gICAqL1xuICBwdWJsaWMgcmVhZG9ubHkgc3JjZGlyOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSBkaXJlY3RvcnkgaW4gd2hpY2ggY29tcGlsZWQgLmpzIGZpbGVzIHJlc2lkZS5cbiAgICovXG4gIHB1YmxpYyByZWFkb25seSBsaWJkaXI6IHN0cmluZztcblxuICAvKipcbiAgICogVGhlIGRpcmVjdG9yeSBpbiB3aGljaCB0ZXN0cyByZXNpZGUuXG4gICAqL1xuICBwdWJsaWMgcmVhZG9ubHkgdGVzdGRpcjogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBUaGUgVHlwZVNjcmlwdCBydW5uZXIgdXNlZCBmb3IgZXhlY3V0aW5nIFR5cGVTY3JpcHQgZmlsZXMuXG4gICAqL1xuICBwdWJsaWMgcmVhZG9ubHkgcnVubmVyOiBUeXBlU2NyaXB0UnVubmVyO1xuXG4gIC8qKlxuICAgKiBUaGUgXCJ3YXRjaFwiIHRhc2suXG4gICAqL1xuICBwdWJsaWMgcmVhZG9ubHkgd2F0Y2hUYXNrOiBUYXNrO1xuXG4gIGNvbnN0cnVjdG9yKG9wdGlvbnM6IFR5cGVTY3JpcHRQcm9qZWN0T3B0aW9ucykge1xuICAgIHN1cGVyKHtcbiAgICAgIC4uLm9wdGlvbnMsXG5cbiAgICAgIC8vIGRpc2FibGUgLnByb2plbnJjLmpzIGlmIHR5cGVzY3JpcHQgaXMgZW5hYmxlZFxuICAgICAgcHJvamVucmNKczogb3B0aW9ucy5wcm9qZW5yY1RzID8gZmFsc2UgOiBvcHRpb25zLnByb2plbnJjSnMsXG5cbiAgICAgIGplc3RPcHRpb25zOiB7XG4gICAgICAgIC4uLm9wdGlvbnMuamVzdE9wdGlvbnMsXG4gICAgICAgIGplc3RDb25maWc6IHtcbiAgICAgICAgICAuLi5vcHRpb25zLmplc3RPcHRpb25zPy5qZXN0Q29uZmlnLFxuICAgICAgICAgIHRlc3RNYXRjaDogb3B0aW9ucy5qZXN0T3B0aW9ucz8uamVzdENvbmZpZz8udGVzdE1hdGNoID8/IFtdLFxuICAgICAgICB9LFxuICAgICAgfSxcbiAgICB9KTtcblxuICAgIHRoaXMuc3JjZGlyID0gb3B0aW9ucy5zcmNkaXIgPz8gXCJzcmNcIjtcbiAgICB0aGlzLmxpYmRpciA9IG9wdGlvbnMubGliZGlyID8/IFwibGliXCI7XG4gICAgdGhpcy5ydW5uZXIgPSBvcHRpb25zLnJ1bm5lciA/PyBUeXBlU2NyaXB0UnVubmVyLnRzTm9kZSgpO1xuICAgIHRoaXMucnVubmVyLnRyeUF0dGFjaCh0aGlzKTtcblxuICAgIHRoaXMuZG9jZ2VuID0gb3B0aW9ucy5kb2NnZW47XG4gICAgdGhpcy5kb2NzRGlyZWN0b3J5ID0gb3B0aW9ucy5kb2NzRGlyZWN0b3J5ID8/IFwiZG9jcy9cIjtcblxuICAgIGNvbnN0IHRzY29uZmlnRmlsZW5hbWUgPSBvcHRpb25zLnRzY29uZmlnPy5maWxlTmFtZTtcbiAgICB0aGlzLmNvbXBpbGVUYXNrLmV4ZWNBcmdzKFxuICAgICAgW1widHNjXCIsIFwiLS1idWlsZFwiLCB0c2NvbmZpZ0ZpbGVuYW1lXS5maWx0ZXIoXG4gICAgICAgIChhKTogYSBpcyBzdHJpbmcgPT4gYSAhPT0gdW5kZWZpbmVkLFxuICAgICAgKSxcbiAgICApO1xuXG4gICAgdGhpcy53YXRjaFRhc2sgPSB0aGlzLmFkZFRhc2soXCJ3YXRjaFwiLCB7XG4gICAgICBkZXNjcmlwdGlvbjogXCJXYXRjaCAmIGNvbXBpbGUgaW4gdGhlIGJhY2tncm91bmRcIixcbiAgICAgIGV4ZWNBcmdzOiBbXCJ0c2NcIiwgXCItLWJ1aWxkXCIsIFwiLXdcIiwgdHNjb25maWdGaWxlbmFtZV0uZmlsdGVyKFxuICAgICAgICAoYSk6IGEgaXMgc3RyaW5nID0+IGEgIT09IHVuZGVmaW5lZCxcbiAgICAgICksXG4gICAgfSk7XG5cbiAgICB0aGlzLnRlc3RkaXIgPSBvcHRpb25zLnRlc3RkaXIgPz8gXCJ0ZXN0XCI7XG4gICAgdGhpcy5naXRpZ25vcmUuaW5jbHVkZShgLyR7dGhpcy50ZXN0ZGlyfS9gKTtcbiAgICB0aGlzLm5wbWlnbm9yZT8uZXhjbHVkZShgLyR7dGhpcy50ZXN0ZGlyfS9gKTtcblxuICAgIC8vIGlmIHRoZSB0ZXN0IGRpcmVjdG9yeSBpcyB1bmRlciBgc3JjL2AsIHRoZW4gd2Ugd2lsbCBydW4gb3VyIHRlc3RzIGFnYWluc3RcbiAgICAvLyB0aGUgamF2YXNjcmlwdCBmaWxlcyBhbmQgbm90IGxldCBqZXN0IGNvbXBpbGUgaXQgZm9yIHVzLlxuICAgIGNvbnN0IGNvbXBpbGVkVGVzdHMgPSB0aGlzLnRlc3RkaXIuc3RhcnRzV2l0aCh0aGlzLnNyY2RpciArIHBhdGgucG9zaXguc2VwKTtcblxuICAgIGlmIChvcHRpb25zLmVudHJ5cG9pbnRUeXBlcyB8fCB0aGlzLnBhY2thZ2UuZW50cnlwb2ludCAhPT0gXCJcIikge1xuICAgICAgY29uc3QgZW50cnlwb2ludFBhdGggPSBwYXRoLmpvaW4oXG4gICAgICAgIHBhdGguZGlybmFtZSh0aGlzLnBhY2thZ2UuZW50cnlwb2ludCksXG4gICAgICAgIHBhdGguYmFzZW5hbWUodGhpcy5wYWNrYWdlLmVudHJ5cG9pbnQsIFwiLmpzXCIpLFxuICAgICAgKTtcbiAgICAgIGNvbnN0IG5vcm1hbGl6ZWRQYXRoID0gbm9ybWFsaXplUGVyc2lzdGVkUGF0aChlbnRyeXBvaW50UGF0aCk7XG4gICAgICBjb25zdCBlbnRyeXBvaW50VHlwZXMgPVxuICAgICAgICBvcHRpb25zLmVudHJ5cG9pbnRUeXBlcyA/PyBgJHtub3JtYWxpemVkUGF0aH0uZC50c2A7XG4gICAgICB0aGlzLnBhY2thZ2UuYWRkRmllbGQoXCJ0eXBlc1wiLCBlbnRyeXBvaW50VHlwZXMpO1xuICAgIH1cblxuICAgIGlmIChvcHRpb25zLmRpc2FibGVUc2NvbmZpZ0RldiAmJiBvcHRpb25zLmRpc2FibGVUc2NvbmZpZykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBcIkNhbm5vdCBzcGVjaWZ5IGJvdGggJ2Rpc2FibGVUc2NvbmZpZ0RldicgYW5kICdkaXNhYmxlVHNjb25maWcnIGZpZWxkcy5cIixcbiAgICAgICk7XG4gICAgfVxuXG4gICAgY29uc3Qgc2hvdWxkSGF2ZVRzY29uZmlnID0gIW9wdGlvbnMuZGlzYWJsZVRzY29uZmlnO1xuICAgIGNvbnN0IHNob3VsZEhhdmVEZXZUc2NvbmZpZyA9ICFvcHRpb25zLmRpc2FibGVUc2NvbmZpZ0RldjtcblxuICAgIGlmIChzaG91bGRIYXZlVHNjb25maWcpIHtcbiAgICAgIHRoaXMudHNjb25maWcgPSB0aGlzLm1ha2VUc2NvbmZpZyhvcHRpb25zKTtcbiAgICB9XG5cbiAgICBpZiAoc2hvdWxkSGF2ZURldlRzY29uZmlnKSB7XG4gICAgICAvLyBXaGVuIGEgcm9vdCB0c2NvbmZpZyBleGlzdHMsIHRoZSBkZXYvdGVzdCBjb25maWcgbGl2ZXMgaW5zaWRlIHRoZSB0ZXN0XG4gICAgICAvLyBkaXJlY3RvcnkgYW5kIGV4dGVuZHMgaXQ7IG90aGVyd2lzZSBpdCBpcyBhIHNlbGYtY29udGFpbmVkIGNvbmZpZyBhdFxuICAgICAgLy8gdGhlIHJlcG9zaXRvcnkgcm9vdC5cbiAgICAgIHRoaXMudHNjb25maWdEZXYgPSB0aGlzLnRzY29uZmlnXG4gICAgICAgID8gdGhpcy5tYWtlRGV2VHNjb25maWcob3B0aW9ucywgdGhpcy50c2NvbmZpZylcbiAgICAgICAgOiB0aGlzLm1ha2VTdGFuZGFsb25lRGV2VHNjb25maWcob3B0aW9ucyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIGBkaXNhYmxlVHNjb25maWdEZXZgOiByZXVzZSB0aGUgbWFpbiB0c2NvbmZpZyBhcyB0aGUgZGV2IGNvbmZpZy5cbiAgICAgIHRoaXMudHNjb25maWdEZXYgPSB0aGlzLnRzY29uZmlnITtcbiAgICB9XG5cbiAgICB0aGlzLmdpdGlnbm9yZS5pbmNsdWRlKGAvJHt0aGlzLnNyY2Rpcn0vYCk7XG4gICAgdGhpcy5ucG1pZ25vcmU/LmV4Y2x1ZGUoYC8ke3RoaXMuc3JjZGlyfS9gKTtcblxuICAgIGlmICh0aGlzLnNyY2RpciAhPT0gdGhpcy5saWJkaXIpIHtcbiAgICAgIC8vIHNlcGFyYXRlZCwgY2FuIGlnbm9yZSB0aGUgZW50aXJlIGxpYmRpclxuICAgICAgdGhpcy5naXRpZ25vcmUuZXhjbHVkZShgLyR7dGhpcy5saWJkaXJ9YCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIGNvbGxvY2F0ZWQsIGNhbiBvbmx5IGlnbm9yZSB0aGUgY29tcGlsZWQgb3V0cHV0XG4gICAgICB0aGlzLmdpdGlnbm9yZS5leGNsdWRlKGAvJHt0aGlzLmxpYmRpcn0vKiovKi5qc2ApO1xuICAgICAgdGhpcy5naXRpZ25vcmUuZXhjbHVkZShgLyR7dGhpcy5saWJkaXJ9LyoqLyouZC50c2ApO1xuICAgICAgdGhpcy5naXRpZ25vcmUuZXhjbHVkZShgLyR7dGhpcy5saWJkaXJ9LyoqLyouZC50cy5tYXBgKTtcbiAgICB9XG5cbiAgICB0aGlzLm5wbWlnbm9yZT8uaW5jbHVkZShgLyR7dGhpcy5saWJkaXJ9L2ApO1xuXG4gICAgdGhpcy5ucG1pZ25vcmU/LmluY2x1ZGUoYC8ke3RoaXMubGliZGlyfS8qKi8qLmpzYCk7XG4gICAgdGhpcy5ucG1pZ25vcmU/LmluY2x1ZGUoYC8ke3RoaXMubGliZGlyfS8qKi8qLmQudHNgKTtcblxuICAgIHRoaXMuZ2l0aWdub3JlLmV4Y2x1ZGUoXCIvZGlzdC9cIik7XG4gICAgdGhpcy5ucG1pZ25vcmU/LmV4Y2x1ZGUoXCJkaXN0XCIpOyAvLyBqc2lpLXBhY21hayBleHBlY3RzIHRoaXMgdG8gYmUgXCJkaXN0XCIgYW5kIG5vdCBcIi9kaXN0XCIuIG90aGVyd2lzZSBpdCB3aWxsIHRhbXBlciB3aXRoIGl0XG5cbiAgICB0aGlzLm5wbWlnbm9yZT8uZXhjbHVkZShcIi90c2NvbmZpZy5qc29uXCIpO1xuICAgIHRoaXMubnBtaWdub3JlPy5leGNsdWRlKFwiLy5naXRodWIvXCIpO1xuICAgIHRoaXMubnBtaWdub3JlPy5leGNsdWRlKFwiLy52c2NvZGUvXCIpO1xuICAgIHRoaXMubnBtaWdub3JlPy5leGNsdWRlKFwiLy5pZGVhL1wiKTtcbiAgICB0aGlzLm5wbWlnbm9yZT8uZXhjbHVkZShcIi8ucHJvamVucmMuanNcIik7XG4gICAgdGhpcy5ucG1pZ25vcmU/LmV4Y2x1ZGUoXCJ0c2NvbmZpZy50c2J1aWxkaW5mb1wiKTtcblxuICAgIGlmICh0aGlzLmplc3QpIHtcbiAgICAgIGlmIChjb21waWxlZFRlc3RzKSB7XG4gICAgICAgIHRoaXMuYWRkSmVzdENvbXBpbGVkKHRoaXMuamVzdCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLmFkZEplc3ROb0NvbXBpbGUodGhpcy5qZXN0LCBvcHRpb25zPy50c0plc3RPcHRpb25zKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAob3B0aW9ucy50eXBlY2hlY2tUZXN0cyA/PyBmYWxzZSkge1xuICAgICAgdGhpcy50ZXN0VGFzay5wcmVwZW5kU3RlcHMoe1xuICAgICAgICBuYW1lOiBcIlR5cGUtY2hlY2sgdGhlIHRlc3Qgc3VpdGVcIixcbiAgICAgICAgZXhlY0FyZ3M6IFtcInRzY1wiLCBcIi0tbm9FbWl0XCIsIFwiLXBcIiwgdGhpcy50c2NvbmZpZ0Rldi5maWxlTmFtZV0sXG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvLyBMaW50ZXIgdG9vbCBzZWxlY3Rpb25cbiAgICAvLyBlc2xpbnQgaXMgdGhlIGRlZmF1bHQsIGJ1dCBpZiBiaW9tZSBoYXMgYmVlbiBlbmFibGVkIGluIHRoZSBwYXJlbnQgY2xhc3MgYW5kIGVzbGludCB1bnNldCwgd2UgZGVmYXVsdCB0byBiaW9tZVxuICAgIGNvbnN0IGJpb21lRW5hYmxlZCA9IHRoaXMuYmlvbWUgIT0gbnVsbDtcbiAgICBjb25zdCBlc2xpbnRFbmFibGVkID0gb3B0aW9ucy5lc2xpbnQgPz8gIWJpb21lRW5hYmxlZDsgLy8gZXNsaW50IGRlZmF1bHRzIHRvIHRoZSBvcHBvc2l0ZSBvZiBiaW9tZVxuXG4gICAgaWYgKG11bHRpcGxlU2VsZWN0ZWQoW2Jpb21lRW5hYmxlZCwgZXNsaW50RW5hYmxlZF0pKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJPbmx5IG9uZSBvZiBiaW9tZSBhbmQgZXNsaW50IGNhbiBiZSBlbmFibGVkLlwiKTtcbiAgICB9XG5cbiAgICBpZiAoZXNsaW50RW5hYmxlZCkge1xuICAgICAgdGhpcy5lc2xpbnQgPSBuZXcgRXNsaW50KHRoaXMsIHtcbiAgICAgICAgdHNjb25maWdQYXRoOiBgLi8keyh0aGlzLnRzY29uZmlnID8/IHRoaXMudHNjb25maWdEZXYpLmZpbGVOYW1lfWAsXG4gICAgICAgIHByb2plY3RTZXJ2aWNlOiB0cnVlLFxuICAgICAgICBkaXJzOiBbdGhpcy5zcmNkaXJdLFxuICAgICAgICBkZXZkaXJzOiBbdGhpcy50ZXN0ZGlyLCBcImJ1aWxkLXRvb2xzXCJdLFxuICAgICAgICBmaWxlRXh0ZW5zaW9uczogW1wiLnRzXCIsIFwiLnRzeFwiXSxcbiAgICAgICAgLi4ub3B0aW9ucy5lc2xpbnRPcHRpb25zLFxuICAgICAgfSk7XG5cbiAgICAgIHRoaXMudHNjb25maWdFc2xpbnQgPSB0aGlzLnRzY29uZmlnRGV2O1xuICAgIH1cblxuICAgIC8vIEFkZCB0aGUgc3JjIGFuZCB0ZXN0IGRpcmVjdG9yaWVzXG4gICAgLy8gbm8gbmVlZCB0byBleGNsdWRlIGJ1aWxkIGFydGlmYWN0czogYmlvbWUgaWdub3JlcyBmaWxlcyBpbiAuZ2l0aWdub3JlXG4gICAgdGhpcy5iaW9tZT8uYWRkRmlsZVBhdHRlcm4oYCR7dGhpcy5zcmNkaXJ9LyoqYCk7XG4gICAgdGhpcy5iaW9tZT8uYWRkRmlsZVBhdHRlcm4oYCR7dGhpcy50ZXN0ZGlyfS8qKmApO1xuXG4gICAgLy8gd2hlbiB0aGlzIGlzIGEgcm9vdCBwcm9qZWN0XG4gICAgaWYgKCF0aGlzLnBhcmVudCkge1xuICAgICAgaWYgKG9wdGlvbnMucHJvamVucmNUcykge1xuICAgICAgICBuZXcgUHJvamVucmNUcyh0aGlzLCBvcHRpb25zLnByb2plbnJjVHNPcHRpb25zKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIHByb2plbnJjLmpzIGNyZWF0ZWQgaW4gTm9kZVByb2plY3QgbmVlZHMgdG8gYmUgYWRkZWQgaW4gdHNjb25maWdEZXYuXG4gICAgICAgIC8vIE9ubHkgcmVsZXZhbnQgd2hlbiB0aGUgZGV2IGNvbmZpZyBsaXZlcyBhdCB0aGUgcmVwb3NpdG9yeSByb290XG4gICAgICAgIC8vIChpLmUuIGl0IHdhcyBub3QgcmVsb2NhdGVkIGludG8gdGhlIHRlc3QgZGlyZWN0b3J5IG9yIGFsaWFzZWQgdG8gdGhlXG4gICAgICAgIC8vIHJvb3QgdHNjb25maWcpOyBvdGhlcndpc2UgdGhlIGluY2x1ZGUgcGF0aCB3b3VsZCBub3QgcmVzb2x2ZS5cbiAgICAgICAgY29uc3QgcHJvamVucmNKcyA9IE5vZGVQcm9qZWN0UHJvamVucmMub2YodGhpcyk7XG4gICAgICAgIGlmIChwcm9qZW5yY0pzICYmIHNob3VsZEhhdmVEZXZUc2NvbmZpZyAmJiAhc2hvdWxkSGF2ZVRzY29uZmlnKSB7XG4gICAgICAgICAgdGhpcy50c2NvbmZpZ0Rldi5hZGRJbmNsdWRlKHByb2plbnJjSnMuZmlsZVBhdGgpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgY29uc3QgdHNEZXAgPSBvcHRpb25zLnR5cGVzY3JpcHRWZXJzaW9uXG4gICAgICA/IGB0eXBlc2NyaXB0QCR7b3B0aW9ucy50eXBlc2NyaXB0VmVyc2lvbn1gXG4gICAgICA6IFwidHlwZXNjcmlwdFwiO1xuICAgIHRoaXMuYWRkRGV2RGVwcyh0c0RlcCk7XG5cbiAgICB0aGlzLmFkZE5vZGVUeXBlc1ZlcnNpb24ob3B0aW9ucy50eXBlc2NyaXB0VmVyc2lvbiwgb3B0aW9ucy5taW5Ob2RlVmVyc2lvbik7XG5cbiAgICAvLyBnZW5lcmF0ZSBzYW1wbGUgY29kZSBpbiBgc3JjYCBhbmQgYGxpYmAgaWYgdGhlc2UgZGlyZWN0b3JpZXMgYXJlIGVtcHR5IG9yIG5vbi1leGlzdGVudC5cbiAgICBpZiAob3B0aW9ucy5zYW1wbGVDb2RlID8/IHRydWUpIHtcbiAgICAgIG5ldyBTYW1wbGVDb2RlKHRoaXMpO1xuICAgIH1cblxuICAgIGlmICh0aGlzLmRvY2dlbikge1xuICAgICAgbmV3IFR5cGVkb2NEb2NnZW4odGhpcyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFRoZSBtYWluIGB0c2NvbmZpZy5qc29uYCB1c2VkIHRvIGNvbXBpbGUgdGhlIHByb2plY3QgKHNyYyAtPiBsaWIpLlxuICAgKi9cbiAgcHJpdmF0ZSBtYWtlVHNjb25maWcob3B0aW9uczogVHlwZVNjcmlwdFByb2plY3RPcHRpb25zKTogVHlwZXNjcmlwdENvbmZpZyB7XG4gICAgcmV0dXJuIG5ldyBUeXBlc2NyaXB0Q29uZmlnKFxuICAgICAgdGhpcyxcbiAgICAgIG1lcmdlVHNjb25maWdPcHRpb25zKFxuICAgICAgICB7XG4gICAgICAgICAgaW5jbHVkZTogW2Ake3RoaXMuc3JjZGlyfS8qKi8qLnRzYF0sXG4gICAgICAgICAgZXhjbHVkZTogW1wibm9kZV9tb2R1bGVzXCJdLFxuICAgICAgICAgIGNvbXBpbGVyT3B0aW9uczoge1xuICAgICAgICAgICAgcm9vdERpcjogdGhpcy5zcmNkaXIsXG4gICAgICAgICAgICBvdXREaXI6IHRoaXMubGliZGlyLFxuICAgICAgICAgICAgLi4udGhpcy5kZWZhdWx0VHlwZVNjcmlwdENvbXBpbGVyT3B0aW9ucygpLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICAgIG9wdGlvbnMudHNjb25maWcsXG4gICAgICApLFxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogVGhlIGRldmVsb3BtZW50L3Rlc3QgdHNjb25maWcsIHBsYWNlZCBpbnNpZGUgdGhlIHRlc3QgZGlyZWN0b3J5IHNvIHRoYXQgdGhlXG4gICAqIFR5cGVTY3JpcHQgbGFuZ3VhZ2Ugc2VydmljZSBwaWNrcyBpdCB1cCBmb3IgdGVzdCBmaWxlcy4gYHRzc2VydmVyYCAoYW5kXG4gICAqIGVkaXRvcnMgbGlrZSBWUyBDb2RlID49IDEuMTE0LCB3aGljaCBidW5kbGUgVHlwZVNjcmlwdCA2KSByZXNvbHZlIHRoZVxuICAgKiBuZWFyZXN0IGB0c2NvbmZpZy5qc29uYCBzdGFydGluZyBmcm9tIHRoZSBzb3VyY2UgZmlsZSBhbmQgbm8gbG9uZ2VyXG4gICAqIGRpc2NvdmVyIGEgZGlmZmVyZW50bHktbmFtZWQgY29uZmlnIChlLmcuIGB0c2NvbmZpZy5kZXYuanNvbmApIGF0IHRoZSByb290LlxuICAgKlxuICAgKiBJdCBleHRlbmRzIHRoZSByb290IHRzY29uZmlnIGFuZCBpcyB0eXBlLWNoZWNrIG9ubHkgKGBub0VtaXRgKSwgc28gaXQgbmV2ZXJcbiAgICogcGFydGljaXBhdGVzIGluIHRoZSBidWlsZC5cbiAgICovXG4gIHByaXZhdGUgbWFrZURldlRzY29uZmlnKFxuICAgIG9wdGlvbnM6IFR5cGVTY3JpcHRQcm9qZWN0T3B0aW9ucyxcbiAgICB0c2NvbmZpZzogVHlwZXNjcmlwdENvbmZpZyxcbiAgKTogVHlwZXNjcmlwdENvbmZpZyB7XG4gICAgY29uc3QgdHNjb25maWdEZXZGaWxlID1cbiAgICAgIG9wdGlvbnMudHNjb25maWdEZXZGaWxlID8/IGAke3RoaXMudGVzdGRpcn0vdHNjb25maWcuanNvbmA7XG4gICAgLy8gVGhlIHJvb3QgdHNjb25maWcgc2V0cyBgcm9vdERpcmAgdG8gdGhlIHNvdXJjZSBkaXJlY3RvcnkuIFNpbmNlIHRoaXNcbiAgICAvLyBjb25maWcgYWxzbyB0eXBlLWNoZWNrcyBmaWxlcyBvdXRzaWRlIGBzcmNgICh0aGUgdGVzdHMsIGFuZCBgc3JjYCBmaWxlc1xuICAgIC8vIHB1bGxlZCBpbiB2aWEgaW1wb3J0cyksIHBvaW50IGByb290RGlyYCBhdCB0aGUgcHJvamVjdCByb290IHJlbGF0aXZlIHRvXG4gICAgLy8gdGhlIGNvbmZpZydzIG93biBsb2NhdGlvbiB0byBhdm9pZCBUUzYwNTkgKFwibm90IHVuZGVyIHJvb3REaXJcIikuIFRoaXNcbiAgICAvLyBvbmx5IGFmZmVjdHMgdGhlIChzdXBwcmVzc2VkKSBlbWl0IGxheW91dC5cbiAgICBjb25zdCByb290RGlyID1cbiAgICAgIHBhdGgucG9zaXgucmVsYXRpdmUocGF0aC5wb3NpeC5kaXJuYW1lKHRzY29uZmlnRGV2RmlsZSksIFwiLlwiKSB8fCBcIi5cIjtcbiAgICBjb25zdCBkZXZUc2NvbmZpZyA9IG5ldyBUeXBlc2NyaXB0Q29uZmlnKFxuICAgICAgdGhpcyxcbiAgICAgIG1lcmdlVHNjb25maWdPcHRpb25zKFxuICAgICAgICB7XG4gICAgICAgICAgZmlsZU5hbWU6IHRzY29uZmlnRGV2RmlsZSxcbiAgICAgICAgICAvLyBpbmNsdWRlIGlzIHJlbGF0aXZlIHRvIHRoZSBjb25maWcncyBkaXJlY3RvcnkgKHRoZSB0ZXN0IGRpcilcbiAgICAgICAgICBpbmNsdWRlOiBbXCIqKi8qLnRzXCJdLFxuICAgICAgICAgIGV4Y2x1ZGU6IFtcIm5vZGVfbW9kdWxlc1wiXSxcbiAgICAgICAgICBjb21waWxlck9wdGlvbnM6IHtcbiAgICAgICAgICAgIC8vIHR5cGUtY2hlY2sgb25seTsgdGhlIHJvb3QgdHNjb25maWcgb3ducyBjb21waWxhdGlvblxuICAgICAgICAgICAgbm9FbWl0OiB0cnVlLFxuICAgICAgICAgICAgcm9vdERpcixcbiAgICAgICAgICB9LFxuICAgICAgICB9LFxuICAgICAgICBvcHRpb25zLnRzY29uZmlnRGV2LFxuICAgICAgKSxcbiAgICApO1xuICAgIC8vIGluaGVyaXQgYWxsIGNvbXBpbGVyIG9wdGlvbnMgKGluY2x1ZGluZyB0aGUgZHluYW1pY2FsbHkgcmVzb2x2ZWQgYHR5cGVzYClcbiAgICAvLyBmcm9tIHRoZSByb290IHRzY29uZmlnLlxuICAgIGRldlRzY29uZmlnLmFkZEV4dGVuZHModHNjb25maWcpO1xuICAgIHJldHVybiBkZXZUc2NvbmZpZztcbiAgfVxuXG4gIC8qKlxuICAgKiBBIHNlbGYtY29udGFpbmVkIGRldmVsb3BtZW50IHRzY29uZmlnIGF0IHRoZSByZXBvc2l0b3J5IHJvb3QsIHVzZWQgd2hlblxuICAgKiB0aGVyZSBpcyBubyByb290IHRzY29uZmlnIHRvIGV4dGVuZCAoZS5nLiBgZGlzYWJsZVRzY29uZmlnYCkuXG4gICAqL1xuICBwcml2YXRlIG1ha2VTdGFuZGFsb25lRGV2VHNjb25maWcoXG4gICAgb3B0aW9uczogVHlwZVNjcmlwdFByb2plY3RPcHRpb25zLFxuICApOiBUeXBlc2NyaXB0Q29uZmlnIHtcbiAgICBjb25zdCB0c2NvbmZpZ0RldkZpbGUgPSBvcHRpb25zLnRzY29uZmlnRGV2RmlsZSA/PyBcInRzY29uZmlnLmRldi5qc29uXCI7XG4gICAgcmV0dXJuIG5ldyBUeXBlc2NyaXB0Q29uZmlnKFxuICAgICAgdGhpcyxcbiAgICAgIG1lcmdlVHNjb25maWdPcHRpb25zKFxuICAgICAgICB7XG4gICAgICAgICAgZmlsZU5hbWU6IHRzY29uZmlnRGV2RmlsZSxcbiAgICAgICAgICBpbmNsdWRlOiBbYCR7dGhpcy5zcmNkaXJ9LyoqLyoudHNgLCBgJHt0aGlzLnRlc3RkaXJ9LyoqLyoudHNgXSxcbiAgICAgICAgICBleGNsdWRlOiBbXCJub2RlX21vZHVsZXNcIl0sXG4gICAgICAgICAgY29tcGlsZXJPcHRpb25zOiB0aGlzLmRlZmF1bHRUeXBlU2NyaXB0Q29tcGlsZXJPcHRpb25zKCksXG4gICAgICAgIH0sXG4gICAgICAgIG9wdGlvbnMudHNjb25maWcsXG4gICAgICAgIG9wdGlvbnMudHNjb25maWdEZXYsXG4gICAgICApLFxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogUHJvamVuIGRlZmF1bHQgVHlwZXNjcmlwdCBjb21waWxlciBvcHRpb25zLlxuICAgKi9cbiAgcHJvdGVjdGVkIGRlZmF1bHRUeXBlU2NyaXB0Q29tcGlsZXJPcHRpb25zKCk6IFR5cGVTY3JpcHRDb21waWxlck9wdGlvbnMge1xuICAgIHJldHVybiB7XG4gICAgICBhbHdheXNTdHJpY3Q6IHRydWUsXG4gICAgICBkZWNsYXJhdGlvbjogdHJ1ZSxcbiAgICAgIGVzTW9kdWxlSW50ZXJvcDogdHJ1ZSxcbiAgICAgIGV4cGVyaW1lbnRhbERlY29yYXRvcnM6IHRydWUsXG4gICAgICBpbmxpbmVTb3VyY2VNYXA6IHRydWUsXG4gICAgICBpbmxpbmVTb3VyY2VzOiB0cnVlLFxuICAgICAgbGliOiBbXCJlczIwMjBcIl0sXG4gICAgICBtb2R1bGU6IFwiQ29tbW9uSlNcIixcbiAgICAgIG5vRW1pdE9uRXJyb3I6IGZhbHNlLFxuICAgICAgbm9GYWxsdGhyb3VnaENhc2VzSW5Td2l0Y2g6IHRydWUsXG4gICAgICBub0ltcGxpY2l0QW55OiB0cnVlLFxuICAgICAgbm9JbXBsaWNpdFJldHVybnM6IHRydWUsXG4gICAgICBub0ltcGxpY2l0VGhpczogdHJ1ZSxcbiAgICAgIG5vVW51c2VkTG9jYWxzOiB0cnVlLFxuICAgICAgbm9VbnVzZWRQYXJhbWV0ZXJzOiB0cnVlLFxuICAgICAgcmVzb2x2ZUpzb25Nb2R1bGU6IHRydWUsXG4gICAgICBzdHJpY3Q6IHRydWUsXG4gICAgICBzdHJpY3ROdWxsQ2hlY2tzOiB0cnVlLFxuICAgICAgc3RyaWN0UHJvcGVydHlJbml0aWFsaXphdGlvbjogdHJ1ZSxcbiAgICAgIHN0cmlwSW50ZXJuYWw6IHRydWUsXG4gICAgICB0YXJnZXQ6IFwiRVMyMDIwXCIsXG4gICAgICB0eXBlczogKCgpID0+IHRoaXMucmVzb2x2ZUluc3RhbGxlZFR5cGVzKCkpIGFzIGFueSwgLy8gVFM2LjAgY29tcGF0LCBAc2VlIGh0dHBzOi8vZGV2YmxvZ3MubWljcm9zb2Z0LmNvbS90eXBlc2NyaXB0L2Fubm91bmNpbmctdHlwZXNjcmlwdC02LTAvI3VwLWZyb250LWFkanVzdG1lbnRzXG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBZGQgYEB0eXBlcy9ub2RlYCB0byB0aGlzIHByb2plY3QuXG4gICAqXG4gICAqIElmIHRoZSB1c2VyIGhhcyBhbHJlYWR5IGFkZGVkIHRoaXMgZGVwZW5kZW5jeSwgZG8gbm90aGluZy5cbiAgICogT3RoZXJ3aXNlIHVzZSB0aGUgbWFqb3IgdmVyc2lvbiBvZiBgbWluTm9kZVZlcnNpb25gLlxuICAgKiBJZiB0aGF0J3Mgbm90IGF2YWlsYWJsZSwgbWF0Y2ggdGhlIHZlcnNpb24gdG8gdGhlIHVzZWQgdHlwZXNjcmlwdCB2ZXJzaW9uLlxuICAgKiBBbmQgaWYgdGhhdCBpcyBhbHNvIG5vdCBhdmFpbGFibGUsIHdlIHVzZSBsYXRlc3QgYW5kIGxldCB0aGUgdXNlciBtYW5hZ2UgdGhlIHZlcnNpb24uXG4gICAqL1xuICBwcml2YXRlIGFkZE5vZGVUeXBlc1ZlcnNpb24odHNWZXJzaW9uPzogc3RyaW5nLCBtaW5Ob2RlVmVyc2lvbj86IHN0cmluZykge1xuICAgIGNvbnN0IG5hbWUgPSBcIkB0eXBlcy9ub2RlXCI7XG5cbiAgICBpZiAodGhpcy5kZXBzLnRyeUdldERlcGVuZGVuY3kobmFtZSwgRGVwZW5kZW5jeVR5cGUuQlVJTEQpKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKG1pbk5vZGVWZXJzaW9uKSB7XG4gICAgICBjb25zdCBtaW5Ob2RlUGFyc2VkID0gc2VtdmVyLm1pblZlcnNpb24obWluTm9kZVZlcnNpb24pO1xuICAgICAgaWYgKG1pbk5vZGVQYXJzZWQpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuYWRkRGV2RGVwcyhgJHtuYW1lfUBeJHttaW5Ob2RlUGFyc2VkLm1ham9yfWApO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIGNvZXJjZSB2ZXJzaW9uLCBzaW5jZSB0aGUgdHMgdmVyc2lvbiBsaWtlbHkgc29tZXRoaW5nIGxpa2UgfjUuMy4wXG4gICAgY29uc3QgdHNQYXJzZWQgPSBzZW12ZXIuY29lcmNlKHRzVmVyc2lvbik7XG4gICAgaWYgKHRzUGFyc2VkKSB7XG4gICAgICByZXR1cm4gdGhpcy5hZGREZXZEZXBzKGAke25hbWV9QHRzJHt0c1BhcnNlZC5tYWpvcn0uJHt0c1BhcnNlZC5taW5vcn1gKTtcbiAgICB9XG5cbiAgICB0aGlzLmFkZERldkRlcHMobmFtZSk7XG4gIH1cblxuICAvKipcbiAgICogUmVzb2x2ZSB0aGUgYHR5cGVzYCBjb21waWxlciBvcHRpb24gZnJvbSBhbGwgaW5zdGFsbGVkIGBAdHlwZXNgIGRlcGVuZGVuY2llcy5cbiAgICogQ2FsbGVkIGxhemlseSBhdCBzeW50aCB0aW1lIHNvIGFsbCBkZXBzIGFyZSBhdmFpbGFibGUuXG4gICAqL1xuICBwcml2YXRlIHJlc29sdmVJbnN0YWxsZWRUeXBlcygpOiBzdHJpbmdbXSB7XG4gICAgcmV0dXJuIHRoaXMuZGVwcy5hbGxcbiAgICAgIC5maWx0ZXIoXG4gICAgICAgIChkKSA9PlxuICAgICAgICAgIGQubmFtZS5zdGFydHNXaXRoKFwiQHR5cGVzL1wiKSAmJiBkLnR5cGUgIT09IERlcGVuZGVuY3lUeXBlLk9WRVJSSURFLFxuICAgICAgKVxuICAgICAgLm1hcCgoZCkgPT4gZC5uYW1lLnJlcGxhY2UoXCJAdHlwZXMvXCIsIFwiXCIpKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBUZXN0cyBhcmUgY29tcGlsZWQgdG8gYGxpYi9URVNURElSYCwgc28gd2UgZG9uJ3QgbmVlZCBqZXN0IHRvIGNvbXBpbGUgdGhlbVxuICAgKiBmb3IgdXMuIGp1c3QgcnVuIHRoZW0gZGlyZWN0bHkgZnJvbSBqYXZhc2NyaXB0LlxuICAgKi9cbiAgcHJpdmF0ZSBhZGRKZXN0Q29tcGlsZWQoamVzdDogSmVzdCkge1xuICAgIHRoaXMuYWRkRGV2RGVwcyhgQHR5cGVzL2plc3Qke2plc3QuamVzdFZlcnNpb259YCk7XG5cbiAgICBjb25zdCB0ZXN0b3V0ID0gcGF0aC5wb3NpeC5yZWxhdGl2ZSh0aGlzLnNyY2RpciwgdGhpcy50ZXN0ZGlyKTtcbiAgICBjb25zdCBsaWJ0ZXN0ID0gcGF0aC5wb3NpeC5qb2luKHRoaXMubGliZGlyLCB0ZXN0b3V0KTtcbiAgICBjb25zdCBzcmN0ZXN0ID0gdGhpcy50ZXN0ZGlyO1xuXG4gICAgdGhpcy5ucG1pZ25vcmU/LmV4Y2x1ZGUoYC8ke2xpYnRlc3R9L2ApO1xuICAgIGplc3QuZGlzY292ZXJUZXN0TWF0Y2hQYXR0ZXJuc0ZvckRpcnMoW2xpYnRlc3RdLCB7XG4gICAgICBmaWxlRXh0ZW5zaW9uUGF0dGVybjogdGhpcy50c2NvbmZpZz8uY29tcGlsZXJPcHRpb25zPy5hbGxvd0pzXG4gICAgICAgID8gdW5kZWZpbmVkXG4gICAgICAgIDogXCJqcz8oeClcIixcbiAgICB9KTtcbiAgICBqZXN0LmFkZFdhdGNoSWdub3JlUGF0dGVybihgLyR7dGhpcy5zcmNkaXJ9L2ApO1xuXG4gICAgY29uc3QgcmVzb2x2ZVNuYXBzaG90UGF0aCA9ICh0ZXN0OiBzdHJpbmcsIGV4dDogc3RyaW5nKSA9PiB7XG4gICAgICBjb25zdCBmdWxscGF0aCA9IHRlc3QucmVwbGFjZShsaWJ0ZXN0LCBzcmN0ZXN0KTtcbiAgICAgIHJldHVybiBwYXRoLmpvaW4oXG4gICAgICAgIHBhdGguZGlybmFtZShmdWxscGF0aCksXG4gICAgICAgIFwiX19zbmFwc2hvdHNfX1wiLFxuICAgICAgICBwYXRoLmJhc2VuYW1lKGZ1bGxwYXRoLCBcIi5qc1wiKSArIFwiLnRzXCIgKyBleHQsXG4gICAgICApO1xuICAgIH07XG5cbiAgICBjb25zdCByZXNvbHZlVGVzdFBhdGggPSAoc25hcDogc3RyaW5nLCBleHQ6IHN0cmluZykgPT4ge1xuICAgICAgY29uc3QgZmlsZW5hbWUgPSBwYXRoLmJhc2VuYW1lKHNuYXAsIFwiLnRzXCIgKyBleHQpICsgXCIuanNcIjtcbiAgICAgIGNvbnN0IGRpciA9IHBhdGguZGlybmFtZShwYXRoLmRpcm5hbWUoc25hcCkpLnJlcGxhY2Uoc3JjdGVzdCwgbGlidGVzdCk7XG4gICAgICByZXR1cm4gcGF0aC5qb2luKGRpciwgZmlsZW5hbWUpO1xuICAgIH07XG5cbiAgICBjb25zdCByZXNvbHZlciA9IG5ldyBUZXh0RmlsZShcbiAgICAgIHRoaXMsXG4gICAgICBwYXRoLnBvc2l4LmpvaW4oUFJPSkVOX0RJUiwgXCJqZXN0LXNuYXBzaG90LXJlc29sdmVyLmpzXCIpLFxuICAgICk7XG4gICAgaWYgKCFyZXNvbHZlci5tYXJrZXIpIHtcbiAgICAgIHJlc29sdmVyLmFkZExpbmUoYC8vICR7cmVzb2x2ZXIubWFya2VyfWApO1xuICAgIH1cbiAgICByZXNvbHZlci5hZGRMaW5lKCdjb25zdCBwYXRoID0gcmVxdWlyZShcInBhdGhcIik7Jyk7XG4gICAgcmVzb2x2ZXIuYWRkTGluZShgY29uc3QgbGlidGVzdCA9IFwiJHtsaWJ0ZXN0fVwiO2ApO1xuICAgIHJlc29sdmVyLmFkZExpbmUoYGNvbnN0IHNyY3Rlc3Q9IFwiJHtzcmN0ZXN0fVwiO2ApO1xuICAgIHJlc29sdmVyLmFkZExpbmUoXCJtb2R1bGUuZXhwb3J0cyA9IHtcIik7XG4gICAgcmVzb2x2ZXIuYWRkTGluZShcbiAgICAgIGAgIHJlc29sdmVTbmFwc2hvdFBhdGg6ICR7cmVzb2x2ZVNuYXBzaG90UGF0aC50b1N0cmluZygpfSxgLFxuICAgICk7XG4gICAgcmVzb2x2ZXIuYWRkTGluZShgICByZXNvbHZlVGVzdFBhdGg6ICR7cmVzb2x2ZVRlc3RQYXRoLnRvU3RyaW5nKCl9LGApO1xuICAgIHJlc29sdmVyLmFkZExpbmUoXG4gICAgICBcIiAgdGVzdFBhdGhGb3JDb25zaXN0ZW5jeUNoZWNrOiBwYXRoLmpvaW4oJ3NvbWUnLCAnX190ZXN0c19fJywgJ2V4YW1wbGUudGVzdC5qcycpXCIsXG4gICAgKTtcbiAgICByZXNvbHZlci5hZGRMaW5lKFwifTtcIik7XG5cbiAgICBqZXN0LmFkZFNuYXBzaG90UmVzb2x2ZXIoYC4vJHtyZXNvbHZlci5wYXRofWApO1xuICB9XG5cbiAgcHJpdmF0ZSBhZGRKZXN0Tm9Db21waWxlKFxuICAgIGplc3Q6IEplc3QsXG4gICAgdHNKZXN0T3B0aW9uczogVHNKZXN0T3B0aW9ucyB8IHVuZGVmaW5lZCxcbiAgKSB7XG4gICAgLy8gVHMtamVzdCBkb2Vzbid0IGZvbGxvdyBzZW12ZXIsIGJ1dCBtYWpvciBzaG91bGQgbWF0Y2ggdG8gSmVzdCdzIG1ham9yLlxuICAgIC8vIEZvciBzb21lIHJlYXNvbiB0aGlzIGlzIG5vdCB0aGUgY2FzZSB3aXRoIEplc3QgMzAgYW55bW9yZS5cbiAgICBjb25zdCBqZXN0TWFqb3IgPSBzZW12ZXIuY29lcmNlKGplc3QuamVzdFZlcnNpb24pPy5tYWpvciA/PyAwO1xuICAgIGNvbnN0IHRzSmVzdFZlcnNpb24gPSBqZXN0TWFqb3IgPiAyOSA/IFwiQF4yOVwiIDogamVzdC5qZXN0VmVyc2lvbjtcbiAgICB0aGlzLmFkZERldkRlcHMoXG4gICAgICBgQHR5cGVzL2plc3Qke2plc3QuamVzdFZlcnNpb259YCxcbiAgICAgIGB0cy1qZXN0JHt0c0plc3RWZXJzaW9ufWAsXG4gICAgKTtcblxuICAgIGplc3QuZGlzY292ZXJUZXN0TWF0Y2hQYXR0ZXJuc0ZvckRpcnMoW3RoaXMuc3JjZGlyLCB0aGlzLnRlc3RkaXJdLCB7XG4gICAgICBmaWxlRXh0ZW5zaW9uUGF0dGVybjogdGhpcy50c2NvbmZpZz8uY29tcGlsZXJPcHRpb25zPy5hbGxvd0pzXG4gICAgICAgID8gdW5kZWZpbmVkXG4gICAgICAgIDogXCJ0cz8oeClcIixcbiAgICB9KTtcblxuICAgIC8vIFRlc3QgZm9yIHRoZSB0cy1qZXN0IHZlcnNpb24gdGhhdCB3YXMgcmVxdWVzdGVkO1xuICAgIC8vXG4gICAgLy8gLSBGaXJzdCwgY2hlY2sgdGhlIGBqZXN0YCB2ZXJzaW9uIHRoYXQgaXMgcmVxdWVzdGVkIHZpYSBwcm9qZW4gcHJvcGVydGllcy4gVGhpc1xuICAgIC8vICAgc2hvdWxkIGJlIHRoZSBzYW1lIGFzIHRoZSBgdHMtamVzdGAgdmVyc2lvbiBhbnl3YXkuXG4gICAgLy8gLSBJZiBub25lIGZvdW5kLCBmYWxsIGJhY2sgdG8gaW5zcGVjdGluZyB0aGUgYWN0dWFsIGB0cy1qZXN0YCB2ZXJzaW9uXG4gICAgLy8gICB0aGF0IGhhcHBlbnMgdG8gYmUgaW5zdGFsbGVkLlxuICAgIGxldCBoYXNUc0plc3QyOTogYm9vbGVhbiB8IHVuZGVmaW5lZDtcbiAgICBpZiAoamVzdC5qZXN0VmVyc2lvbikge1xuICAgICAgLy8gV2UgY291bGQgbWF5YmUgcmVwbGFjZSB0aGlzIHdpbGwgZnVsbCBcImFjdHVhbCB2ZXJzaW9uXCIgY2hlY2tpbmcsIGJ1dFxuICAgICAgLy8gdGhlIHRlc3RzIGRlcGVuZCBvbiB0aGlzIGFuZCB0aGUgcmVhZGluZyBvZiAncGFja2FnZS5qc29uJyBpcyB2ZXJ5XG4gICAgICAvLyBhd2t3YXJkIHRvIHRlc3QuXG4gICAgICAvLyBOb3RlIHRoYXQgd2UgdXNlIHRoZSByZXF1ZXN0ZWQgdmVyc2lvbiBvZiBgamVzdGAgYXMgYSBwcm94eSBmb3IgdGhlXG4gICAgICAvLyB2ZXJzaW9uIG9mIGB0cy1qZXN0YCwgd2hpY2ggaXMgd2hhdCB3ZSdyZSBhY3R1YWxseSBpbnRlcmVzdGVkIGluLlxuICAgICAgY29uc3QgbWFqb3IgPSBzZW12ZXIuY29lcmNlKGplc3QuamVzdFZlcnNpb24pPy5tYWpvcjtcbiAgICAgIGhhc1RzSmVzdDI5ID0gbWFqb3IgPyBtYWpvciA+PSAyOSA6IHVuZGVmaW5lZDtcbiAgICB9XG4gICAgaWYgKGhhc1RzSmVzdDI5ID09PSB1bmRlZmluZWQpIHtcbiAgICAgIGhhc1RzSmVzdDI5ID0gaGFzRGVwZW5kZW5jeVZlcnNpb24odGhpcywgXCJ0cy1qZXN0XCIsIFwiPj0gMjlcIik7XG4gICAgfVxuXG4gICAgLy8gYWRkIHJlbGV2YW50IGRlcHMgKHdlIHRyZWF0IFwidW5rbm93blwiIGFzIGhhdmluZyBhIG1vZGVybiB0cy1qZXN0KVxuICAgIGlmIChoYXNUc0plc3QyOSAhPT0gZmFsc2UpIHtcbiAgICAgIHJldHVybiB0aGlzLmFkZEplc3ROb0NvbXBpbGVNb2Rlcm4oamVzdCwgdHNKZXN0T3B0aW9ucyk7XG4gICAgfVxuICAgIHRoaXMuYWRkSmVzdE5vQ29tcGlsZUxlZ2FjeShqZXN0LCB0c0plc3RPcHRpb25zKTtcbiAgfVxuXG4gIHByaXZhdGUgYWRkSmVzdE5vQ29tcGlsZU1vZGVybihcbiAgICBqZXN0OiBKZXN0LFxuICAgIHRzSmVzdE9wdGlvbnM6IFRzSmVzdE9wdGlvbnMgfCB1bmRlZmluZWQsXG4gICkge1xuICAgIGplc3QuY29uZmlnLnRyYW5zZm9ybSA9IGRlZXBNZXJnZShbXG4gICAgICB7XG4gICAgICAgIFt0c0plc3RPcHRpb25zPy50cmFuc2Zvcm1QYXR0ZXJuID8/XG4gICAgICAgIFR5cGVTY3JpcHRQcm9qZWN0LkRFRkFVTFRfVFNfSkVTVF9UUkFORk9STV9QQVRURVJOXTogbmV3IFRyYW5zZm9ybShcbiAgICAgICAgICBcInRzLWplc3RcIixcbiAgICAgICAgICB7XG4gICAgICAgICAgICB0c2NvbmZpZzogVHNKZXN0VHNjb25maWcuZnJvbUZpbGUodGhpcy50c2NvbmZpZ0Rldi5maWxlTmFtZSksXG4gICAgICAgICAgICAuLi4odHNKZXN0T3B0aW9ucz8udHJhbnNmb3JtT3B0aW9ucyA/PyB7fSksXG4gICAgICAgICAgfSxcbiAgICAgICAgKSxcbiAgICAgIH0sXG4gICAgICBqZXN0LmNvbmZpZy50cmFuc2Zvcm0sXG4gICAgXSk7XG4gIH1cblxuICBwcml2YXRlIGFkZEplc3ROb0NvbXBpbGVMZWdhY3koXG4gICAgamVzdDogSmVzdCxcbiAgICB0c0plc3RPcHRpb25zOiBUc0plc3RPcHRpb25zIHwgdW5kZWZpbmVkLFxuICApIHtcbiAgICBpZiAodHNKZXN0T3B0aW9ucykge1xuICAgICAgdGhpcy5sb2dnZXIud2FybihcbiAgICAgICAgXCJZb3UgYXJlIHVzaW5nIGEgbGVnYWN5IHZlcnNpb24gKDwyOSkgb2YgamVzdCBhbmQgdHMtamVzdCB0aGF0IGRvZXMgbm90IHN1cHBvcnQgdHNKZXN0T3B0aW9ucywgdGhleSB3aWxsIGJlIGlnbm9yZWQuXCIsXG4gICAgICApO1xuICAgIH1cbiAgICBpZiAoIWplc3QuY29uZmlnLnByZXNldCkge1xuICAgICAgamVzdC5jb25maWcucHJlc2V0ID0gXCJ0cy1qZXN0XCI7XG4gICAgfVxuICAgIGplc3QuY29uZmlnLmdsb2JhbHMgPSBkZWVwTWVyZ2UoW1xuICAgICAge1xuICAgICAgICBcInRzLWplc3RcIjoge1xuICAgICAgICAgIHRzY29uZmlnOiB0aGlzLnRzY29uZmlnRGV2LmZpbGVOYW1lLFxuICAgICAgICB9LFxuICAgICAgfSxcbiAgICAgIGplc3QuY29uZmlnLmdsb2JhbHMsXG4gICAgXSk7XG4gIH1cbn1cblxuY2xhc3MgU2FtcGxlQ29kZSBleHRlbmRzIENvbXBvbmVudCB7XG4gIGNvbnN0cnVjdG9yKHByb2plY3Q6IFR5cGVTY3JpcHRQcm9qZWN0KSB7XG4gICAgc3VwZXIocHJvamVjdCk7XG4gICAgY29uc3Qgc3JjQ29kZSA9IFtcbiAgICAgIFwiZXhwb3J0IGNsYXNzIEhlbGxvIHtcIixcbiAgICAgIFwiICBwdWJsaWMgc2F5SGVsbG8oKSB7XCIsXG4gICAgICBcIiAgICByZXR1cm4gJ2hlbGxvLCB3b3JsZCEnO1wiLFxuICAgICAgXCIgIH1cIixcbiAgICAgIFwifVwiLFxuICAgIF0uam9pbihcIlxcblwiKTtcblxuICAgIGNvbnN0IHRlc3RDb2RlID0gW1xuICAgICAgXCJpbXBvcnQgeyBIZWxsbyB9IGZyb20gJy4uL3NyYyc7XCIsXG4gICAgICBcIlwiLFxuICAgICAgXCJ0ZXN0KCdoZWxsbycsICgpID0+IHtcIixcbiAgICAgIFwiICBleHBlY3QobmV3IEhlbGxvKCkuc2F5SGVsbG8oKSkudG9CZSgnaGVsbG8sIHdvcmxkIScpO1wiLFxuICAgICAgXCJ9KTtcIixcbiAgICBdLmpvaW4oXCJcXG5cIik7XG5cbiAgICBuZXcgU2FtcGxlRGlyKHByb2plY3QsIHByb2plY3Quc3JjZGlyLCB7XG4gICAgICBmaWxlczoge1xuICAgICAgICBcImluZGV4LnRzXCI6IHNyY0NvZGUsXG4gICAgICB9LFxuICAgIH0pO1xuXG4gICAgaWYgKHByb2plY3QuamVzdCkge1xuICAgICAgbmV3IFNhbXBsZURpcihwcm9qZWN0LCBwcm9qZWN0LnRlc3RkaXIsIHtcbiAgICAgICAgZmlsZXM6IHtcbiAgICAgICAgICBcImhlbGxvLnRlc3QudHNcIjogdGVzdENvZGUsXG4gICAgICAgIH0sXG4gICAgICB9KTtcbiAgICB9XG4gIH1cbn1cblxuLyoqXG4gKiBUeXBlU2NyaXB0IGFwcC5cbiAqXG4gKiBAcGppZCB0eXBlc2NyaXB0LWFwcFxuICovXG5leHBvcnQgY2xhc3MgVHlwZVNjcmlwdEFwcFByb2plY3QgZXh0ZW5kcyBUeXBlU2NyaXB0UHJvamVjdCB7XG4gIGNvbnN0cnVjdG9yKG9wdGlvbnM6IFR5cGVTY3JpcHRQcm9qZWN0T3B0aW9ucykge1xuICAgIC8vIFJlbGVhc2luZyBhbmQgcGFja2FnaW5nIGFyZSBjb3VwbGVkLiBJZiBvbmUgaXMgZGlzYWJsZWQsIGRpc2FibGUgdGhlIG90aGVyIGJ5IGRlZmF1bHQuXG4gICAgY29uc3Qgc2hvdWxkUmVsZWFzZSA9IG9wdGlvbnMucmVsZWFzZSA/PyBmYWxzZTtcblxuICAgIHN1cGVyKHtcbiAgICAgIHJlbGVhc2U6IHNob3VsZFJlbGVhc2UsXG4gICAgICBwYWNrYWdlOiBzaG91bGRSZWxlYXNlLFxuICAgICAgYWxsb3dMaWJyYXJ5RGVwZW5kZW5jaWVzOiBmYWxzZSxcbiAgICAgIGVudHJ5cG9pbnQ6IFwiXCIsIC8vIFwibWFpblwiIGlzIG5vdCBuZWVkZWQgaW4gdHlwZXNjcmlwdCBhcHBzXG4gICAgICAuLi5vcHRpb25zLFxuICAgIH0pO1xuICB9XG59XG5cbi8qKlxuICogQGludGVybmFsXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBtZXJnZVRzY29uZmlnT3B0aW9ucyhcbiAgLi4ub3B0aW9uczogKFR5cGVzY3JpcHRDb25maWdPcHRpb25zIHwgdW5kZWZpbmVkKVtdXG4pOiBUeXBlc2NyaXB0Q29uZmlnT3B0aW9ucyB7XG4gIGNvbnN0IGRlZmluZWRPcHRpb25zID0gb3B0aW9ucy5maWx0ZXIoQm9vbGVhbikgYXMgVHlwZXNjcmlwdENvbmZpZ09wdGlvbnNbXTtcbiAgcmV0dXJuIGRlZmluZWRPcHRpb25zLnJlZHVjZTxUeXBlc2NyaXB0Q29uZmlnT3B0aW9ucz4oXG4gICAgKHByZXZpb3VzLCBjdXJyZW50KSA9PiAoe1xuICAgICAgLi4ucHJldmlvdXMsXG4gICAgICAuLi5jdXJyZW50LFxuICAgICAgaW5jbHVkZTogWy4uLihwcmV2aW91cy5pbmNsdWRlID8/IFtdKSwgLi4uKGN1cnJlbnQuaW5jbHVkZSA/PyBbXSldLFxuICAgICAgZXhjbHVkZTogWy4uLihwcmV2aW91cy5leGNsdWRlID8/IFtdKSwgLi4uKGN1cnJlbnQuZXhjbHVkZSA/PyBbXSldLFxuICAgICAgY29tcGlsZXJPcHRpb25zOiB7XG4gICAgICAgIC4uLnByZXZpb3VzLmNvbXBpbGVyT3B0aW9ucyxcbiAgICAgICAgLi4uY3VycmVudC5jb21waWxlck9wdGlvbnMsXG4gICAgICB9LFxuICAgIH0pLFxuICAgIHsgY29tcGlsZXJPcHRpb25zOiB7fSB9LFxuICApO1xufVxuIl19