projen
Version:
CDK for software projects
384 lines • 53.9 kB
JavaScript
"use strict";
var _a;
Object.defineProperty(exports, "__esModule", { value: true });
exports.Eslint = void 0;
const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
const prettier_1 = require("./prettier");
const common_1 = require("../common");
const component_1 = require("../component");
const json_1 = require("../json");
const yaml_1 = require("../yaml");
/**
* Represents eslint configuration.
*/
class Eslint extends component_1.Component {
/**
* Returns the singleton Eslint component of a project or undefined if there is none.
*/
static of(project) {
const isEslint = (c) => c instanceof Eslint;
return project.components.find(isEslint);
}
constructor(project, options) {
super(project);
/**
* eslint overrides.
*/
this.overrides = [];
this._plugins = new Set();
this._extends = new Set();
this.nodeProject = project;
project.addDevDeps("eslint@^9", "@typescript-eslint/eslint-plugin@^8", "@typescript-eslint/parser@^8", "eslint-import-resolver-typescript", "eslint-plugin-import");
if (options.aliasMap) {
project.addDevDeps("eslint-import-resolver-alias");
}
const lintProjenRc = options.lintProjenRc ?? true;
const lintProjenRcFile = options.lintProjenRcFile ?? common_1.DEFAULT_PROJEN_RC_JS_FILENAME;
const devdirs = options.devdirs ?? [];
this._lintPatterns = new Set([
...options.dirs,
...devdirs,
...(lintProjenRc && lintProjenRcFile ? [lintProjenRcFile] : []),
]);
this._fileExtensions = new Set(options.fileExtensions ?? [".ts"]);
this._allowDevDeps = new Set((devdirs ?? []).map((dir) => `**/${dir}/**`));
const commandOptions = options.commandOptions ?? {};
const { fix = true, extraArgs: extraFlagArgs = [] } = commandOptions;
this._flagArgs = new Set(extraFlagArgs);
if (fix) {
this._flagArgs.add("--fix");
}
this._flagArgs.add("--no-error-on-unmatched-pattern");
this.sortExtends = options.sortExtends ?? new ExtendsDefaultOrder();
this.eslintTask = project.addTask("eslint", {
description: "Runs eslint against the codebase",
env: {
ESLINT_USE_FLAT_CONFIG: "false",
},
});
this.updateTask();
project.testTask.spawn(this.eslintTask);
// exclude some files
project.npmignore?.exclude("/.eslintrc.json");
this._formattingRules = {
// @see https://github.com/typescript-eslint/typescript-eslint/issues/8072
indent: ["off"],
"@stylistic/indent": ["error", 2],
// Style
quotes: ["error", "single", { avoidEscape: true }],
"comma-dangle": ["error", "always-multiline"], // ensures clean diffs, see https://medium.com/@nikgraf/why-you-should-enforce-dangling-commas-for-multiline-statements-d034c98e36f8
"comma-spacing": ["error", { before: false, after: true }], // space after, no space before
"no-multi-spaces": ["error", { ignoreEOLComments: false }], // no multi spaces
"array-bracket-spacing": ["error", "never"], // [1, 2, 3]
"array-bracket-newline": ["error", "consistent"], // enforce consistent line breaks between brackets
"object-curly-spacing": ["error", "always"], // { key: 'value' }
"object-curly-newline": ["error", { multiline: true, consistent: true }], // enforce consistent line breaks between braces
"object-property-newline": [
"error",
{ allowAllPropertiesOnSameLine: true },
], // enforce "same line" or "multiple line" on object properties
"keyword-spacing": ["error"], // require a space before & after keywords
"brace-style": ["error", "1tbs", { allowSingleLine: true }], // enforce one true brace style
"space-before-blocks": ["error"], // require space before blocks
curly: ["error", "multi-line", "consistent"], // require curly braces for multiline control statements
// @see https://github.com/typescript-eslint/typescript-eslint/issues/8072
"@stylistic/member-delimiter-style": ["error"],
// Require semicolons
semi: ["error", "always"],
// Max line lengths
"max-len": [
"error",
{
code: 150,
ignoreUrls: true, // Most common reason to disable it
ignoreStrings: true, // These are not fantastic but necessary for error messages
ignoreTemplateLiterals: true,
ignoreComments: true,
ignoreRegExpLiterals: true,
},
],
// Don't unnecessarily quote properties
"quote-props": ["error", "consistent-as-needed"],
};
this.rules = {
// Require use of the `import { foo } from 'bar';` form instead of `import foo = require('bar');`
"@typescript-eslint/no-require-imports": ["error"],
// Require all imported dependencies are actually declared in package.json
"import/no-extraneous-dependencies": [
"error",
{
// Only allow importing devDependencies from "devdirs".
devDependencies: () => this.renderDevDepsAllowList(),
optionalDependencies: false, // Disallow importing optional dependencies (those shouldn't be in use in the project)
peerDependencies: true, // Allow importing peer dependencies (that aren't also direct dependencies)
},
],
// Require all imported libraries actually resolve (!!required for import/no-extraneous-dependencies to work!!)
"import/no-unresolved": ["error"],
// Require an ordering on all imports
"import/order": [
"warn",
{
groups: ["builtin", "external"],
alphabetize: { order: "asc", caseInsensitive: true },
},
],
// Cannot import from the same module twice
"import/no-duplicates": ["error"],
// Cannot shadow names
"no-shadow": ["off"],
"@typescript-eslint/no-shadow": ["error"],
// Required spacing in property declarations (copied from TSLint, defaults are good)
"key-spacing": ["error"],
// No multiple empty lines
"no-multiple-empty-lines": ["error"],
// One of the easiest mistakes to make
"@typescript-eslint/no-floating-promises": ["error"],
// Make sure that inside try/catch blocks, promises are 'return await'ed
// (must disable the base rule as it can report incorrect errors)
"no-return-await": ["off"],
"@typescript-eslint/return-await": ["error"],
// Useless diff results
"no-trailing-spaces": ["error"],
// Must use foo.bar instead of foo['bar'] if possible
"dot-notation": ["error"],
// Are you sure | is not a typo for || ?
"no-bitwise": ["error"],
// Member ordering
"@typescript-eslint/member-ordering": [
"error",
{
default: [
"public-static-field",
"public-static-method",
"protected-static-field",
"protected-static-method",
"private-static-field",
"private-static-method",
"field",
// Constructors
"constructor", // = ["public-constructor", "protected-constructor", "private-constructor"]
// Methods
"method",
],
},
],
};
// Overrides for .projenrc.js
// @deprecated
if (lintProjenRc) {
this.overrides = [
{
files: [lintProjenRcFile || common_1.DEFAULT_PROJEN_RC_JS_FILENAME],
rules: {
"@typescript-eslint/no-require-imports": "off",
"import/no-extraneous-dependencies": "off",
},
},
];
}
this.ignorePatterns = options.ignorePatterns ?? [
"*.js",
// @deprecated
...(lintProjenRc
? [`!${lintProjenRcFile || common_1.DEFAULT_PROJEN_RC_JS_FILENAME}`]
: []),
"*.d.ts",
"node_modules/",
"*.generated.ts",
"coverage",
];
const tsconfig = options.tsconfigPath ?? "./tsconfig.json";
this.addPlugins("@typescript-eslint");
this.addPlugins("import");
this.addExtends("plugin:import/typescript");
this.config = {
env: {
jest: true,
node: true,
},
root: true,
plugins: this._plugins,
parser: "@typescript-eslint/parser",
parserOptions: {
ecmaVersion: 2018,
sourceType: "module",
project: tsconfig,
},
extends: () => Array.from(this._extends).sort((a, b) => this.sortExtends.compare(a, b)),
settings: {
"import/parsers": {
"@typescript-eslint/parser": [".ts", ".tsx"],
},
"import/resolver": {
...(options.aliasMap && {
alias: {
map: Object.entries(options.aliasMap).map(([k, v]) => [k, v]),
extensions: options.aliasExtensions,
},
}),
node: {},
typescript: {
project: tsconfig,
...(options.tsAlwaysTryTypes !== false && { alwaysTryTypes: true }),
},
},
},
ignorePatterns: this.ignorePatterns,
rules: () => ({ ...this._formattingRules, ...this.rules }),
overrides: this.overrides,
};
if (options.yaml) {
new yaml_1.YamlFile(project, ".eslintrc.yml", {
obj: this.config,
marker: true,
});
}
else {
new json_1.JsonFile(project, ".eslintrc.json", {
obj: this.config,
// https://eslint.org/docs/latest/user-guide/configuring/configuration-files#comments-in-configuration-files
marker: true,
allowComments: true,
});
}
// if the user enabled prettier explicitly _or_ if the project has a
// `Prettier` component, we shall tweak our configuration accordingly.
if (options.prettier || prettier_1.Prettier.of(project)) {
this.enablePrettier();
}
else {
this.nodeProject.addDevDeps("@stylistic/eslint-plugin@^2");
this.addPlugins("@stylistic");
}
}
/**
* Returns an immutable copy of the lintPatterns being used by this eslint configuration.
*/
get lintPatterns() {
if (this._lintPatterns && this._lintPatterns.size > 0) {
return [...this._lintPatterns];
}
return [];
}
/**
* Add a file, glob pattern or directory with source files to lint (e.g. [ "src" ])
*/
addLintPattern(pattern) {
this._lintPatterns.add(pattern);
this.updateTask();
}
/**
* Add an eslint rule.
*/
addRules(rules) {
for (const [k, v] of Object.entries(rules)) {
this.rules[k] = v;
}
}
/**
* Adds an eslint plugin
* @param plugins The names of plugins to add
*/
addPlugins(...plugins) {
for (const plugin of plugins) {
this._plugins.add(plugin);
}
}
/**
* Add an eslint override.
*/
addOverride(override) {
this.overrides.push(override);
}
/**
* Do not lint these files.
*/
addIgnorePattern(pattern) {
this.ignorePatterns.push(pattern);
}
/**
* Adds an `extends` item to the eslint configuration.
* @param extendList The list of "extends" to add.
*/
addExtends(...extendList) {
for (const extend of extendList) {
this._extends.add(extend);
}
}
/**
* Add a glob file pattern which allows importing dev dependencies.
* @param pattern glob pattern.
*/
allowDevDeps(pattern) {
this._allowDevDeps.add(pattern);
}
/**
* Enables prettier for code formatting.
*/
enablePrettier() {
this.nodeProject.addDevDeps("prettier", "eslint-plugin-prettier", "eslint-config-prettier");
this._formattingRules = {};
this.addExtends("plugin:prettier/recommended");
}
renderDevDepsAllowList() {
return Array.from(this._allowDevDeps);
}
/**
* Update the task with the current list of lint patterns and file extensions
*/
updateTask() {
const taskExecCommand = "eslint";
const argsSet = new Set();
if (this._fileExtensions.size > 0) {
argsSet.add(`--ext ${[...this._fileExtensions].join(",")}`);
}
argsSet.add(`${[...this._flagArgs].join(" ")}`);
argsSet.add("$@"); // External args go here
for (const pattern of this._lintPatterns) {
argsSet.add(pattern);
}
this.eslintTask.reset([taskExecCommand, ...argsSet].join(" "), this.buildTaskStepOptions(taskExecCommand));
}
/**
* In case of external editing of the eslint task step, we preserve those changes.
* Otherwise, we return the default task step options.
*
* @param taskExecCommand The command that the ESLint tasks executes
* @returns Either the externally edited, or the default task step options
*/
buildTaskStepOptions(taskExecCommand) {
const currentEslintTaskStep = this.eslintTask?.steps?.find((step) => step?.exec?.startsWith?.(taskExecCommand));
if (currentEslintTaskStep) {
const { args, condition, cwd, env, name, receiveArgs } = currentEslintTaskStep;
return {
args,
condition,
cwd,
env,
name,
receiveArgs,
};
}
return {
receiveArgs: true,
};
}
}
exports.Eslint = Eslint;
_a = JSII_RTTI_SYMBOL_1;
Eslint[_a] = { fqn: "projen.javascript.Eslint", version: "0.91.29" };
/**
* A compare protocol tp sort the extends array in eslint config using known ESLint best practices.
*
* Places "prettier" plugins at the end of the array
*/
class ExtendsDefaultOrder {
compare(a, b) {
return (ExtendsDefaultOrder.ORDER.indexOf(a) -
ExtendsDefaultOrder.ORDER.indexOf(b));
}
}
// This is the order that ESLint best practices suggest
ExtendsDefaultOrder.ORDER = ["plugin:prettier/recommended", "prettier"];
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXNsaW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2phdmFzY3JpcHQvZXNsaW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQ0EseUNBQXNDO0FBQ3RDLHNDQUEwRDtBQUUxRCw0Q0FBeUM7QUFFekMsa0NBQW1DO0FBRW5DLGtDQUFtQztBQWdKbkM7O0dBRUc7QUFDSCxNQUFhLE1BQU8sU0FBUSxxQkFBUztJQUNuQzs7T0FFRztJQUNJLE1BQU0sQ0FBQyxFQUFFLENBQUMsT0FBZ0I7UUFDL0IsTUFBTSxRQUFRLEdBQUcsQ0FBQyxDQUFZLEVBQWUsRUFBRSxDQUFDLENBQUMsWUFBWSxNQUFNLENBQUM7UUFDcEUsT0FBTyxPQUFPLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUMzQyxDQUFDO0lBcUNELFlBQVksT0FBb0IsRUFBRSxPQUFzQjtRQUN0RCxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUM7UUEvQmpCOztXQUVHO1FBQ2EsY0FBUyxHQUFxQixFQUFFLENBQUM7UUFtQmhDLGFBQVEsR0FBRyxJQUFJLEdBQUcsRUFBVSxDQUFDO1FBQzdCLGFBQVEsR0FBRyxJQUFJLEdBQUcsRUFBVSxDQUFDO1FBVTVDLElBQUksQ0FBQyxXQUFXLEdBQUcsT0FBTyxDQUFDO1FBRTNCLE9BQU8sQ0FBQyxVQUFVLENBQ2hCLFdBQVcsRUFDWCxxQ0FBcUMsRUFDckMsOEJBQThCLEVBQzlCLG1DQUFtQyxFQUNuQyxzQkFBc0IsQ0FDdkIsQ0FBQztRQUVGLElBQUksT0FBTyxDQUFDLFFBQVEsRUFBRSxDQUFDO1lBQ3JCLE9BQU8sQ0FBQyxVQUFVLENBQUMsOEJBQThCLENBQUMsQ0FBQztRQUNyRCxDQUFDO1FBRUQsTUFBTSxZQUFZLEdBQUcsT0FBTyxDQUFDLFlBQVksSUFBSSxJQUFJLENBQUM7UUFDbEQsTUFBTSxnQkFBZ0IsR0FDcEIsT0FBTyxDQUFDLGdCQUFnQixJQUFJLHNDQUE2QixDQUFDO1FB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UUFDbEQsTUFBTSxxQkFBcUIsR0FBRyxJQUFJLENBQUMsVUFBVSxFQUFFLEtBQUssRUFBRSxJQUFJLENBQUMsQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUNsRSxJQUFJLEVBQUUsSUFBSSxFQUFFLFVBQVUsRUFBRSxDQUFDLGVBQWUsQ0FBQyxDQUMxQyxDQUFDO1FBRUYsSUFBSSxxQkFBcUIsRUFBRSxDQUFDO1lBQzFCLE1BQU0sRUFBRSxJQUFJLEVBQUUsU0FBUyxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsSUFBSSxFQUFFLFdBQVcsRUFBRSxHQUNwRCxxQkFBcUIsQ0FBQztZQUN4QixPQUFPO2dCQUNMLElBQUk7Z0JBQ0osU0FBUztnQkFDVCxHQUFHO2dCQUNILEdBQUc7Z0JBQ0gsSUFBSTtnQkFDSixXQUFXO2FBQ1osQ0FBQztRQUNKLENBQUM7UUFFRCxPQUFPO1lBQ0wsV0FBVyxFQUFFLElBQUk7U0FDbEIsQ0FBQztJQUNKLENBQUM7O0FBNWNILHdCQTZjQzs7O0FBRUQ7Ozs7R0FJRztBQUNILE1BQU0sbUJBQW1CO0lBSWhCLE9BQU8sQ0FBQyxDQUFTLEVBQUUsQ0FBUztRQUNqQyxPQUFPLENBQ0wsbUJBQW1CLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUM7WUFDcEMsbUJBQW1CLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FDckMsQ0FBQztJQUNKLENBQUM7O0FBUkQsdURBQXVEO0FBQ3hDLHlCQUFLLEdBQUcsQ0FBQyw2QkFBNkIsRUFBRSxVQUFVLENBQUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IFByb2plY3QsIFRhc2tTdGVwT3B0aW9ucyB9IGZyb20gXCIuLlwiO1xuaW1wb3J0IHsgUHJldHRpZXIgfSBmcm9tIFwiLi9wcmV0dGllclwiO1xuaW1wb3J0IHsgREVGQVVMVF9QUk9KRU5fUkNfSlNfRklMRU5BTUUgfSBmcm9tIFwiLi4vY29tbW9uXCI7XG5pbXBvcnQgeyBJQ29tcGFyZVN0cmluZyB9IGZyb20gXCIuLi9jb21wYXJlXCI7XG5pbXBvcnQgeyBDb21wb25lbnQgfSBmcm9tIFwiLi4vY29tcG9uZW50XCI7XG5pbXBvcnQgeyBOb2RlUHJvamVjdCB9IGZyb20gXCIuLi9qYXZhc2NyaXB0XCI7XG5pbXBvcnQgeyBKc29uRmlsZSB9IGZyb20gXCIuLi9qc29uXCI7XG5pbXBvcnQgeyBUYXNrIH0gZnJvbSBcIi4uL3Rhc2tcIjtcbmltcG9ydCB7IFlhbWxGaWxlIH0gZnJvbSBcIi4uL3lhbWxcIjtcblxuZXhwb3J0IGludGVyZmFjZSBFc2xpbnRPcHRpb25zIHtcbiAgLyoqXG4gICAqIFBhdGggdG8gYHRzY29uZmlnLmpzb25gIHdoaWNoIHNob3VsZCBiZSB1c2VkIGJ5IGVzbGludC5cbiAgICogQGRlZmF1bHQgXCIuL3RzY29uZmlnLmpzb25cIlxuICAgKi9cbiAgcmVhZG9ubHkgdHNjb25maWdQYXRoPzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBGaWxlcyBvciBnbG9iIHBhdHRlcm5zIG9yIGRpcmVjdG9yaWVzIHdpdGggc291cmNlIGZpbGVzIHRvIGxpbnQgKGUuZy4gWyBcInNyY1wiIF0pXG4gICAqL1xuICByZWFkb25seSBkaXJzOiBzdHJpbmdbXTtcblxuICAvKipcbiAgICogRmlsZXMgb3IgZ2xvYiBwYXR0ZXJucyBvciBkaXJlY3RvcmllcyB3aXRoIHNvdXJjZSBmaWxlcyB0aGF0IGluY2x1ZGUgdGVzdHMgYW5kIGJ1aWxkIHRvb2xzXG4gICAqXG4gICAqIFRoZXNlIHNvdXJjZXMgYXJlIGxpbnRlZCBidXQgbWF5IGFsc28gaW1wb3J0IHBhY2thZ2VzIGZyb20gYGRldkRlcGVuZGVuY2llc2AuXG4gICAqIEBkZWZhdWx0IFtdXG4gICAqL1xuICByZWFkb25seSBkZXZkaXJzPzogc3RyaW5nW107XG4gIC8qKlxuICAgKiBGaWxlIHR5cGVzIHRoYXQgc2hvdWxkIGJlIGxpbnRlZCAoZS5nLiBbIFwiLmpzXCIsIFwiLnRzXCIgXSlcbiAgICogQGRlZmF1bHQgW1wiLnRzXCJdXG4gICAqL1xuICByZWFkb25seSBmaWxlRXh0ZW5zaW9ucz86IHN0cmluZ1tdO1xuXG4gIC8qKlxuICAgKiBPcHRpb25zIGZvciBlc2xpbnQgY29tbWFuZCBleGVjdXRlZCBieSBlc2xpbnQgdGFza1xuICAgKi9cbiAgcmVhZG9ubHkgY29tbWFuZE9wdGlvbnM/OiBFc2xpbnRDb21tYW5kT3B0aW9ucztcblxuICAvKipcbiAgICogTGlzdCBvZiBmaWxlIHBhdHRlcm5zIHRoYXQgc2hvdWxkIG5vdCBiZSBsaW50ZWQsIHVzaW5nIHRoZSBzYW1lIHN5bnRheFxuICAgKiBhcyAuZ2l0aWdub3JlIHBhdHRlcm5zLlxuICAgKlxuICAgKiBAZGVmYXVsdCBbICcqLmpzJywgJyouZC50cycsICdub2RlX21vZHVsZXMvJywgJyouZ2VuZXJhdGVkLnRzJywgJ2NvdmVyYWdlJyBdXG4gICAqL1xuICByZWFkb25seSBpZ25vcmVQYXR0ZXJucz86IHN0cmluZ1tdO1xuXG4gIC8qKlxuICAgKiBQcm9qZW5yYyBmaWxlIHRvIGxpbnQuIFVzZSBlbXB0eSBzdHJpbmcgdG8gZGlzYWJsZS5cbiAgICogQGRlZmF1bHQgXCJwcm9qZW5yYy5qc1wiXG4gICAqIEBkZXByZWNhdGVkIHByb3ZpZGUgYXMgYGRldmRpcnNgXG4gICAqL1xuICByZWFkb25seSBsaW50UHJvamVuUmNGaWxlPzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBTaG91bGQgd2UgbGludCAucHJvamVucmMuanNcbiAgICpcbiAgICogQGRlZmF1bHQgdHJ1ZVxuICAgKiBAZGVwcmVjYXRlZCBzZXQgdG8gYGZhbHNlYCB0byByZW1vdmUgYW55IGF1dG9tYXRpYyBydWxlcyBhbmQgYWRkIG1hbnVhbGx5XG4gICAqL1xuICByZWFkb25seSBsaW50UHJvamVuUmM/OiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBFbmFibGUgcHJldHRpZXIgZm9yIGNvZGUgZm9ybWF0dGluZ1xuICAgKiBAZGVmYXVsdCBmYWxzZVxuICAgKi9cbiAgcmVhZG9ubHkgcHJldHRpZXI/OiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBUaGUgZXh0ZW5kcyBhcnJheSBpbiBlc2xpbnQgaXMgb3JkZXIgZGVwZW5kZW50LlxuICAgKiBUaGlzIG9wdGlvbiBhbGxvd3MgdG8gc29ydCB0aGUgZXh0ZW5kcyBhcnJheSBpbiBhbnkgd2F5IHNlZW4gZml0LlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIFVzZSBrbm93biBFU0xpbnQgYmVzdCBwcmFjdGljZXMgdG8gcGxhY2UgXCJwcmV0dGllclwiIHBsdWdpbnMgYXQgdGhlIGVuZCBvZiB0aGUgYXJyYXlcbiAgICovXG4gIHJlYWRvbmx5IHNvcnRFeHRlbmRzPzogSUNvbXBhcmVTdHJpbmc7XG5cbiAgLyoqXG4gICAqIEVuYWJsZSBpbXBvcnQgYWxpYXMgZm9yIG1vZHVsZSBwYXRoc1xuICAgKiBAZGVmYXVsdCB1bmRlZmluZWRcbiAgICovXG4gIHJlYWRvbmx5IGFsaWFzTWFwPzogeyBba2V5OiBzdHJpbmddOiBzdHJpbmcgfTtcblxuICAvKipcbiAgICogRW5hYmxlIGltcG9ydCBhbGlhcyBmb3IgbW9kdWxlIHBhdGhzXG4gICAqIEBkZWZhdWx0IHVuZGVmaW5lZFxuICAgKi9cbiAgcmVhZG9ubHkgYWxpYXNFeHRlbnNpb25zPzogc3RyaW5nW107XG5cbiAgLyoqXG4gICAqIEFsd2F5cyB0cnkgdG8gcmVzb2x2ZSB0eXBlcyB1bmRlciBgPHJvb3Q+QHR5cGVzYCBkaXJlY3RvcnkgZXZlbiBpdCBkb2Vzbid0IGNvbnRhaW4gYW55IHNvdXJjZSBjb2RlLlxuICAgKiBUaGlzIHByZXZlbnRzIGBpbXBvcnQvbm8tdW5yZXNvbHZlZGAgZXNsaW50IGVycm9ycyB3aGVuIGltcG9ydGluZyBhIGBAdHlwZXMvKmAgbW9kdWxlIHRoYXQgd291bGQgb3RoZXJ3aXNlIHJlbWFpbiB1bnJlc29sdmVkLlxuICAgKiBAZGVmYXVsdCB0cnVlXG4gICAqL1xuICByZWFkb25seSB0c0Fsd2F5c1RyeVR5cGVzPzogYm9vbGVhbjtcblxuICAvKipcbiAgICogV3JpdGUgZXNsaW50IGNvbmZpZ3VyYXRpb24gYXMgWUFNTCBpbnN0ZWFkIG9mIEpTT05cbiAgICogQGRlZmF1bHQgZmFsc2VcbiAgICovXG4gIHJlYWRvbmx5IHlhbWw/OiBib29sZWFuO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEVzbGludENvbW1hbmRPcHRpb25zIHtcbiAgLyoqXG4gICAqIFdoZXRoZXIgdG8gZml4IGVzbGludCBpc3N1ZXMgd2hlbiBydW5uaW5nIHRoZSBlc2xpbnQgdGFza1xuICAgKiBAZGVmYXVsdCB0cnVlXG4gICAqL1xuICByZWFkb25seSBmaXg/OiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBFeHRyYSBmbGFnIGFyZ3VtZW50cyB0byBwYXNzIHRvIGVzbGludCBjb21tYW5kXG4gICAqL1xuICByZWFkb25seSBleHRyYUFyZ3M/OiBzdHJpbmdbXTtcbn1cblxuLyoqXG4gKiBlc2xpbnQgcnVsZXMgb3ZlcnJpZGVcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBFc2xpbnRPdmVycmlkZSB7XG4gIC8qKlxuICAgKiBGaWxlcyBvciBmaWxlIHBhdHRlcm5zIG9uIHdoaWNoIHRvIGFwcGx5IHRoZSBvdmVycmlkZVxuICAgKi9cbiAgcmVhZG9ubHkgZmlsZXM6IHN0cmluZ1tdO1xuXG4gIC8qKlxuICAgKiBQYXR0ZXJuKHMpIHRvIGV4Y2x1ZGUgZnJvbSB0aGlzIG92ZXJyaWRlLlxuICAgKiBJZiBhIGZpbGUgbWF0Y2hlcyBhbnkgb2YgdGhlIGV4Y2x1ZGVkIHBhdHRlcm5zLCB0aGUgY29uZmlndXJhdGlvbiB3b27igJl0IGFwcGx5LlxuICAgKi9cbiAgcmVhZG9ubHkgZXhjbHVkZWRGaWxlcz86IHN0cmluZ1tdO1xuXG4gIC8qKlxuICAgKiBUaGUgb3ZlcnJpZGRlbiBydWxlc1xuICAgKi9cbiAgcmVhZG9ubHkgcnVsZXM/OiB7IFtydWxlOiBzdHJpbmddOiBhbnkgfTtcblxuICAvKipcbiAgICogVGhlIG92ZXJyaWRkZW4gcGFyc2VyXG4gICAqL1xuICByZWFkb25seSBwYXJzZXI/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIENvbmZpZyhzKSB0byBleHRlbmQgaW4gdGhpcyBvdmVycmlkZVxuICAgKi9cbiAgcmVhZG9ubHkgZXh0ZW5kcz86IHN0cmluZ1tdO1xuXG4gIC8qKlxuICAgKiBgcGx1Z2luc2Agb3ZlcnJpZGVcbiAgICovXG4gIHJlYWRvbmx5IHBsdWdpbnM/OiBzdHJpbmdbXTtcbn1cblxuLyoqXG4gKiBSZXByZXNlbnRzIGVzbGludCBjb25maWd1cmF0aW9uLlxuICovXG5leHBvcnQgY2xhc3MgRXNsaW50IGV4dGVuZHMgQ29tcG9uZW50IHtcbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIHNpbmdsZXRvbiBFc2xpbnQgY29tcG9uZW50IG9mIGEgcHJvamVjdCBvciB1bmRlZmluZWQgaWYgdGhlcmUgaXMgbm9uZS5cbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgb2YocHJvamVjdDogUHJvamVjdCk6IEVzbGludCB8IHVuZGVmaW5lZCB7XG4gICAgY29uc3QgaXNFc2xpbnQgPSAoYzogQ29tcG9uZW50KTogYyBpcyBFc2xpbnQgPT4gYyBpbnN0YW5jZW9mIEVzbGludDtcbiAgICByZXR1cm4gcHJvamVjdC5jb21wb25lbnRzLmZpbmQoaXNFc2xpbnQpO1xuICB9XG5cbiAgLyoqXG4gICAqIGVzbGludCBydWxlcy5cbiAgICovXG4gIHB1YmxpYyByZWFkb25seSBydWxlczogeyBbcnVsZTogc3RyaW5nXTogYW55W10gfTtcblxuICAvKipcbiAgICogZXNsaW50IG92ZXJyaWRlcy5cbiAgICovXG4gIHB1YmxpYyByZWFkb25seSBvdmVycmlkZXM6IEVzbGludE92ZXJyaWRlW10gPSBbXTtcblxuICAvKipcbiAgICogZXNsaW50IHRhc2suXG4gICAqL1xuICBwdWJsaWMgcmVhZG9ubHkgZXNsaW50VGFzazogVGFzaztcblxuICAvKipcbiAgICogRGlyZWN0IGFjY2VzcyB0byB0aGUgZXNsaW50IGNvbmZpZ3VyYXRpb24gKGVzY2FwZSBoYXRjaClcbiAgICovXG4gIHB1YmxpYyByZWFkb25seSBjb25maWc6IGFueTtcblxuICAvKipcbiAgICogRmlsZSBwYXR0ZXJucyB0aGF0IHNob3VsZCBub3QgYmUgbGludGVkXG4gICAqL1xuICBwdWJsaWMgcmVhZG9ubHkgaWdub3JlUGF0dGVybnM6IHN0cmluZ1tdO1xuXG4gIHByaXZhdGUgX2Zvcm1hdHRpbmdSdWxlczogUmVjb3JkPHN0cmluZywgYW55PjtcbiAgcHJpdmF0ZSByZWFkb25seSBfYWxsb3dEZXZEZXBzOiBTZXQ8c3RyaW5nPjtcbiAgcHJpdmF0ZSByZWFkb25seSBfcGx1Z2lucyA9IG5ldyBTZXQ8c3RyaW5nPigpO1xuICBwcml2YXRlIHJlYWRvbmx5IF9leHRlbmRzID0gbmV3IFNldDxzdHJpbmc+KCk7XG4gIHByaXZhdGUgcmVhZG9ubHkgX2ZpbGVFeHRlbnNpb25zOiBTZXQ8c3RyaW5nPjtcbiAgcHJpdmF0ZSByZWFkb25seSBfZmxhZ0FyZ3M6IFNldDxzdHJpbmc+O1xuICBwcml2YXRlIHJlYWRvbmx5IF9saW50UGF0dGVybnM6IFNldDxzdHJpbmc+O1xuICBwcml2YXRlIHJlYWRvbmx5IG5vZGVQcm9qZWN0OiBOb2RlUHJvamVjdDtcbiAgcHJpdmF0ZSByZWFkb25seSBzb3J0RXh0ZW5kczogSUNvbXBhcmVTdHJpbmc7XG5cbiAgY29uc3RydWN0b3IocHJvamVjdDogTm9kZVByb2plY3QsIG9wdGlvbnM6IEVzbGludE9wdGlvbnMpIHtcbiAgICBzdXBlcihwcm9qZWN0KTtcblxuICAgIHRoaXMubm9kZVByb2plY3QgPSBwcm9qZWN0O1xuXG4gICAgcHJvamVjdC5hZGREZXZEZXBzKFxuICAgICAgXCJlc2xpbnRAXjlcIixcbiAgICAgIFwiQHR5cGVzY3JpcHQtZXNsaW50L2VzbGludC1wbHVnaW5AXjhcIixcbiAgICAgIFwiQHR5cGVzY3JpcHQtZXNsaW50L3BhcnNlckBeOFwiLFxuICAgICAgXCJlc2xpbnQtaW1wb3J0LXJlc29sdmVyLXR5cGVzY3JpcHRcIixcbiAgICAgIFwiZXNsaW50LXBsdWdpbi1pbXBvcnRcIlxuICAgICk7XG5cbiAgICBpZiAob3B0aW9ucy5hbGlhc01hcCkge1xuICAgICAgcHJvamVjdC5hZGREZXZEZXBzKFwiZXNsaW50LWltcG9ydC1yZXNvbHZlci1hbGlhc1wiKTtcbiAgICB9XG5cbiAgICBjb25zdCBsaW50UHJvamVuUmMgPSBvcHRpb25zLmxpbnRQcm9qZW5SYyA/PyB0cnVlO1xuICAgIGNvbnN0IGxpbnRQcm9qZW5SY0ZpbGUgPVxuICAgICAgb3B0aW9ucy5saW50UHJvamVuUmNGaWxlID8/IERFRkFVTFRfUFJPSkVOX1JDX0pTX0ZJTEVOQU1FO1xuXG4gICAgY29uc3QgZGV2ZGlycyA9IG9wdGlvbnMuZGV2ZGlycyA/PyBbXTtcblxuICAgIHRoaXMuX2xpbnRQYXR0ZXJucyA9IG5ldyBTZXQoW1xuICAgICAgLi4ub3B0aW9ucy5kaXJzLFxuICAgICAgLi4uZGV2ZGlycyxcbiAgICAgIC4uLihsaW50UHJvamVuUmMgJiYgbGludFByb2plblJjRmlsZSA/IFtsaW50UHJvamVuUmNGaWxlXSA6IFtdKSxcbiAgICBdKTtcbiAgICB0aGlzLl9maWxlRXh0ZW5zaW9ucyA9IG5ldyBTZXQob3B0aW9ucy5maWxlRXh0ZW5zaW9ucyA/PyBbXCIudHNcIl0pO1xuXG4gICAgdGhpcy5fYWxsb3dEZXZEZXBzID0gbmV3IFNldCgoZGV2ZGlycyA/PyBbXSkubWFwKChkaXIpID0+IGAqKi8ke2Rpcn0vKipgKSk7XG5cbiAgICBjb25zdCBjb21tYW5kT3B0aW9ucyA9IG9wdGlvbnMuY29tbWFuZE9wdGlvbnMgPz8ge307XG4gICAgY29uc3QgeyBmaXggPSB0cnVlLCBleHRyYUFyZ3M6IGV4dHJhRmxhZ0FyZ3MgPSBbXSB9ID0gY29tbWFuZE9wdGlvbnM7XG4gICAgdGhpcy5fZmxhZ0FyZ3MgPSBuZXcgU2V0KGV4dHJhRmxhZ0FyZ3MpO1xuICAgIGlmIChmaXgpIHtcbiAgICAgIHRoaXMuX2ZsYWdBcmdzLmFkZChcIi0tZml4XCIpO1xuICAgIH1cbiAgICB0aGlzLl9mbGFnQXJncy5hZGQoXCItLW5vLWVycm9yLW9uLXVubWF0Y2hlZC1wYXR0ZXJuXCIpO1xuXG4gICAgdGhpcy5zb3J0RXh0ZW5kcyA9IG9wdGlvbnMuc29ydEV4dGVuZHMgPz8gbmV3IEV4dGVuZHNEZWZhdWx0T3JkZXIoKTtcblxuICAgIHRoaXMuZXNsaW50VGFzayA9IHByb2plY3QuYWRkVGFzayhcImVzbGludFwiLCB7XG4gICAgICBkZXNjcmlwdGlvbjogXCJSdW5zIGVzbGludCBhZ2FpbnN0IHRoZSBjb2RlYmFzZVwiLFxuICAgICAgZW52OiB7XG4gICAgICAgIEVTTElOVF9VU0VfRkxBVF9DT05GSUc6IFwiZmFsc2VcIixcbiAgICAgIH0sXG4gICAgfSk7XG4gICAgdGhpcy51cGRhdGVUYXNrKCk7XG5cbiAgICBwcm9qZWN0LnRlc3RUYXNrLnNwYXduKHRoaXMuZXNsaW50VGFzayk7XG5cbiAgICAvLyBleGNsdWRlIHNvbWUgZmlsZXNcbiAgICBwcm9qZWN0Lm5wbWlnbm9yZT8uZXhjbHVkZShcIi8uZXNsaW50cmMuanNvblwiKTtcblxuICAgIHRoaXMuX2Zvcm1hdHRpbmdSdWxlcyA9IHtcbiAgICAgIC8vIEBzZWUgaHR0cHM6Ly9naXRodWIuY29tL3R5cGVzY3JpcHQtZXNsaW50L3R5cGVzY3JpcHQtZXNsaW50L2lzc3Vlcy84MDcyXG4gICAgICBpbmRlbnQ6IFtcIm9mZlwiXSxcbiAgICAgIFwiQHN0eWxpc3RpYy9pbmRlbnRcIjogW1wiZXJyb3JcIiwgMl0sXG5cbiAgICAgIC8vIFN0eWxlXG4gICAgICBxdW90ZXM6IFtcImVycm9yXCIsIFwic2luZ2xlXCIsIHsgYXZvaWRFc2NhcGU6IHRydWUgfV0sXG4gICAgICBcImNvbW1hLWRhbmdsZVwiOiBbXCJlcnJvclwiLCBcImFsd2F5cy1tdWx0aWxpbmVcIl0sIC8vIGVuc3VyZXMgY2xlYW4gZGlmZnMsIHNlZSBodHRwczovL21lZGl1bS5jb20vQG5pa2dyYWYvd2h5LXlvdS1zaG91bGQtZW5mb3JjZS1kYW5nbGluZy1jb21tYXMtZm9yLW11bHRpbGluZS1zdGF0ZW1lbnRzLWQwMzRjOThlMzZmOFxuICAgICAgXCJjb21tYS1zcGFjaW5nXCI6IFtcImVycm9yXCIsIHsgYmVmb3JlOiBmYWxzZSwgYWZ0ZXI6IHRydWUgfV0sIC8vIHNwYWNlIGFmdGVyLCBubyBzcGFjZSBiZWZvcmVcbiAgICAgIFwibm8tbXVsdGktc3BhY2VzXCI6IFtcImVycm9yXCIsIHsgaWdub3JlRU9MQ29tbWVudHM6IGZhbHNlIH1dLCAvLyBubyBtdWx0aSBzcGFjZXNcbiAgICAgIFwiYXJyYXktYnJhY2tldC1zcGFjaW5nXCI6IFtcImVycm9yXCIsIFwibmV2ZXJcIl0sIC8vIFsxLCAyLCAzXVxuICAgICAgXCJhcnJheS1icmFja2V0LW5ld2xpbmVcIjogW1wiZXJyb3JcIiwgXCJjb25zaXN0ZW50XCJdLCAvLyBlbmZvcmNlIGNvbnNpc3RlbnQgbGluZSBicmVha3MgYmV0d2VlbiBicmFja2V0c1xuICAgICAgXCJvYmplY3QtY3VybHktc3BhY2luZ1wiOiBbXCJlcnJvclwiLCBcImFsd2F5c1wiXSwgLy8geyBrZXk6ICd2YWx1ZScgfVxuICAgICAgXCJvYmplY3QtY3VybHktbmV3bGluZVwiOiBbXCJlcnJvclwiLCB7IG11bHRpbGluZTogdHJ1ZSwgY29uc2lzdGVudDogdHJ1ZSB9XSwgLy8gZW5mb3JjZSBjb25zaXN0ZW50IGxpbmUgYnJlYWtzIGJldHdlZW4gYnJhY2VzXG4gICAgICBcIm9iamVjdC1wcm9wZXJ0eS1uZXdsaW5lXCI6IFtcbiAgICAgICAgXCJlcnJvclwiLFxuICAgICAgICB7IGFsbG93QWxsUHJvcGVydGllc09uU2FtZUxpbmU6IHRydWUgfSxcbiAgICAgIF0sIC8vIGVuZm9yY2UgXCJzYW1lIGxpbmVcIiBvciBcIm11bHRpcGxlIGxpbmVcIiBvbiBvYmplY3QgcHJvcGVydGllc1xuICAgICAgXCJrZXl3b3JkLXNwYWNpbmdcIjogW1wiZXJyb3JcIl0sIC8vIHJlcXVpcmUgYSBzcGFjZSBiZWZvcmUgJiBhZnRlciBrZXl3b3Jkc1xuICAgICAgXCJicmFjZS1zdHlsZVwiOiBbXCJlcnJvclwiLCBcIjF0YnNcIiwgeyBhbGxvd1NpbmdsZUxpbmU6IHRydWUgfV0sIC8vIGVuZm9yY2Ugb25lIHRydWUgYnJhY2Ugc3R5bGVcbiAgICAgIFwic3BhY2UtYmVmb3JlLWJsb2Nrc1wiOiBbXCJlcnJvclwiXSwgLy8gcmVxdWlyZSBzcGFjZSBiZWZvcmUgYmxvY2tzXG4gICAgICBjdXJseTogW1wiZXJyb3JcIiwgXCJtdWx0aS1saW5lXCIsIFwiY29uc2lzdGVudFwiXSwgLy8gcmVxdWlyZSBjdXJseSBicmFjZXMgZm9yIG11bHRpbGluZSBjb250cm9sIHN0YXRlbWVudHNcbiAgICAgIC8vIEBzZWUgaHR0cHM6Ly9naXRodWIuY29tL3R5cGVzY3JpcHQtZXNsaW50L3R5cGVzY3JpcHQtZXNsaW50L2lzc3Vlcy84MDcyXG4gICAgICBcIkBzdHlsaXN0aWMvbWVtYmVyLWRlbGltaXRlci1zdHlsZVwiOiBbXCJlcnJvclwiXSxcblxuICAgICAgLy8gUmVxdWlyZSBzZW1pY29sb25zXG4gICAgICBzZW1pOiBbXCJlcnJvclwiLCBcImFsd2F5c1wiXSxcblxuICAgICAgLy8gTWF4IGxpbmUgbGVuZ3Roc1xuICAgICAgXCJtYXgtbGVuXCI6IFtcbiAgICAgICAgXCJlcnJvclwiLFxuICAgICAgICB7XG4gICAgICAgICAgY29kZTogMTUwLFxuICAgICAgICAgIGlnbm9yZVVybHM6IHRydWUsIC8vIE1vc3QgY29tbW9uIHJlYXNvbiB0byBkaXNhYmxlIGl0XG4gICAgICAgICAgaWdub3JlU3RyaW5nczogdHJ1ZSwgLy8gVGhlc2UgYXJlIG5vdCBmYW50YXN0aWMgYnV0IG5lY2Vzc2FyeSBmb3IgZXJyb3IgbWVzc2FnZXNcbiAgICAgICAgICBpZ25vcmVUZW1wbGF0ZUxpdGVyYWxzOiB0cnVlLFxuICAgICAgICAgIGlnbm9yZUNvbW1lbnRzOiB0cnVlLFxuICAgICAgICAgIGlnbm9yZVJlZ0V4cExpdGVyYWxzOiB0cnVlLFxuICAgICAgICB9LFxuICAgICAgXSxcblxuICAgICAgLy8gRG9uJ3QgdW5uZWNlc3NhcmlseSBxdW90ZSBwcm9wZXJ0aWVzXG4gICAgICBcInF1b3RlLXByb3BzXCI6IFtcImVycm9yXCIsIFwiY29uc2lzdGVudC1hcy1uZWVkZWRcIl0sXG4gICAgfTtcblxuICAgIHRoaXMucnVsZXMgPSB7XG4gICAgICAvLyBSZXF1aXJlIHVzZSBvZiB0aGUgYGltcG9ydCB7IGZvbyB9IGZyb20gJ2Jhcic7YCBmb3JtIGluc3RlYWQgb2YgYGltcG9ydCBmb28gPSByZXF1aXJlKCdiYXInKTtgXG4gICAgICBcIkB0eXBlc2NyaXB0LWVzbGludC9uby1yZXF1aXJlLWltcG9ydHNcIjogW1wiZXJyb3JcIl0sXG5cbiAgICAgIC8vIFJlcXVpcmUgYWxsIGltcG9ydGVkIGRlcGVuZGVuY2llcyBhcmUgYWN0dWFsbHkgZGVjbGFyZWQgaW4gcGFja2FnZS5qc29uXG4gICAgICBcImltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1wiOiBbXG4gICAgICAgIFwiZXJyb3JcIixcbiAgICAgICAge1xuICAgICAgICAgIC8vIE9ubHkgYWxsb3cgaW1wb3J0aW5nIGRldkRlcGVuZGVuY2llcyBmcm9tIFwiZGV2ZGlyc1wiLlxuICAgICAgICAgIGRldkRlcGVuZGVuY2llczogKCkgPT4gdGhpcy5yZW5kZXJEZXZEZXBzQWxsb3dMaXN0KCksXG4gICAgICAgICAgb3B0aW9uYWxEZXBlbmRlbmNpZXM6IGZhbHNlLCAvLyBEaXNhbGxvdyBpbXBvcnRpbmcgb3B0aW9uYWwgZGVwZW5kZW5jaWVzICh0aG9zZSBzaG91bGRuJ3QgYmUgaW4gdXNlIGluIHRoZSBwcm9qZWN0KVxuICAgICAgICAgIHBlZXJEZXBlbmRlbmNpZXM6IHRydWUsIC8vIEFsbG93IGltcG9ydGluZyBwZWVyIGRlcGVuZGVuY2llcyAodGhhdCBhcmVuJ3QgYWxzbyBkaXJlY3QgZGVwZW5kZW5jaWVzKVxuICAgICAgICB9LFxuICAgICAgXSxcblxuICAgICAgLy8gUmVxdWlyZSBhbGwgaW1wb3J0ZWQgbGlicmFyaWVzIGFjdHVhbGx5IHJlc29sdmUgKCEhcmVxdWlyZWQgZm9yIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llcyB0byB3b3JrISEpXG4gICAgICBcImltcG9ydC9uby11bnJlc29sdmVkXCI6IFtcImVycm9yXCJdLFxuXG4gICAgICAvLyBSZXF1aXJlIGFuIG9yZGVyaW5nIG9uIGFsbCBpbXBvcnRzXG4gICAgICBcImltcG9ydC9vcmRlclwiOiBbXG4gICAgICAgIFwid2FyblwiLFxuICAgICAgICB7XG4gICAgICAgICAgZ3JvdXBzOiBbXCJidWlsdGluXCIsIFwiZXh0ZXJuYWxcIl0sXG4gICAgICAgICAgYWxwaGFiZXRpemU6IHsgb3JkZXI6IFwiYXNjXCIsIGNhc2VJbnNlbnNpdGl2ZTogdHJ1ZSB9LFxuICAgICAgICB9LFxuICAgICAgXSxcblxuICAgICAgLy8gQ2Fubm90IGltcG9ydCBmcm9tIHRoZSBzYW1lIG1vZHVsZSB0d2ljZVxuICAgICAgXCJpbXBvcnQvbm8tZHVwbGljYXRlc1wiOiBbXCJlcnJvclwiXSxcblxuICAgICAgLy8gQ2Fubm90IHNoYWRvdyBuYW1lc1xuICAgICAgXCJuby1zaGFkb3dcIjogW1wib2ZmXCJdLFxuICAgICAgXCJAdHlwZXNjcmlwdC1lc2xpbnQvbm8tc2hhZG93XCI6IFtcImVycm9yXCJdLFxuXG4gICAgICAvLyBSZXF1aXJlZCBzcGFjaW5nIGluIHByb3BlcnR5IGRlY2xhcmF0aW9ucyAoY29waWVkIGZyb20gVFNMaW50LCBkZWZhdWx0cyBhcmUgZ29vZClcbiAgICAgIFwia2V5LXNwYWNpbmdcIjogW1wiZXJyb3JcIl0sXG5cbiAgICAgIC8vIE5vIG11bHRpcGxlIGVtcHR5IGxpbmVzXG4gICAgICBcIm5vLW11bHRpcGxlLWVtcHR5LWxpbmVzXCI6IFtcImVycm9yXCJdLFxuXG4gICAgICAvLyBPbmUgb2YgdGhlIGVhc2llc3QgbWlzdGFrZXMgdG8gbWFrZVxuICAgICAgXCJAdHlwZXNjcmlwdC1lc2xpbnQvbm8tZmxvYXRpbmctcHJvbWlzZXNcIjogW1wiZXJyb3JcIl0sXG5cbiAgICAgIC8vIE1ha2Ugc3VyZSB0aGF0IGluc2lkZSB0cnkvY2F0Y2ggYmxvY2tzLCBwcm9taXNlcyBhcmUgJ3JldHVybiBhd2FpdCdlZFxuICAgICAgLy8gKG11c3QgZGlzYWJsZSB0aGUgYmFzZSBydWxlIGFzIGl0IGNhbiByZXBvcnQgaW5jb3JyZWN0IGVycm9ycylcbiAgICAgIFwibm8tcmV0dXJuLWF3YWl0XCI6IFtcIm9mZlwiXSxcbiAgICAgIFwiQHR5cGVzY3JpcHQtZXNsaW50L3JldHVybi1hd2FpdFwiOiBbXCJlcnJvclwiXSxcblxuICAgICAgLy8gVXNlbGVzcyBkaWZmIHJlc3VsdHNcbiAgICAgIFwibm8tdHJhaWxpbmctc3BhY2VzXCI6IFtcImVycm9yXCJdLFxuXG4gICAgICAvLyBNdXN0IHVzZSBmb28uYmFyIGluc3RlYWQgb2YgZm9vWydiYXInXSBpZiBwb3NzaWJsZVxuICAgICAgXCJkb3Qtbm90YXRpb25cIjogW1wiZXJyb3JcIl0sXG5cbiAgICAgIC8vIEFyZSB5b3Ugc3VyZSB8IGlzIG5vdCBhIHR5cG8gZm9yIHx8ID9cbiAgICAgIFwibm8tYml0d2lzZVwiOiBbXCJlcnJvclwiXSxcblxuICAgICAgLy8gTWVtYmVyIG9yZGVyaW5nXG4gICAgICBcIkB0eXBlc2NyaXB0LWVzbGludC9tZW1iZXItb3JkZXJpbmdcIjogW1xuICAgICAgICBcImVycm9yXCIsXG4gICAgICAgIHtcbiAgICAgICAgICBkZWZhdWx0OiBbXG4gICAgICAgICAgICBcInB1YmxpYy1zdGF0aWMtZmllbGRcIixcbiAgICAgICAgICAgIFwicHVibGljLXN0YXRpYy1tZXRob2RcIixcbiAgICAgICAgICAgIFwicHJvdGVjdGVkLXN0YXRpYy1maWVsZFwiLFxuICAgICAgICAgICAgXCJwcm90ZWN0ZWQtc3RhdGljLW1ldGhvZFwiLFxuICAgICAgICAgICAgXCJwcml2YXRlLXN0YXRpYy1maWVsZFwiLFxuICAgICAgICAgICAgXCJwcml2YXRlLXN0YXRpYy1tZXRob2RcIixcblxuICAgICAgICAgICAgXCJmaWVsZFwiLFxuXG4gICAgICAgICAgICAvLyBDb25zdHJ1Y3RvcnNcbiAgICAgICAgICAgIFwiY29uc3RydWN0b3JcIiwgLy8gPSBbXCJwdWJsaWMtY29uc3RydWN0b3JcIiwgXCJwcm90ZWN0ZWQtY29uc3RydWN0b3JcIiwgXCJwcml2YXRlLWNvbnN0cnVjdG9yXCJdXG5cbiAgICAgICAgICAgIC8vIE1ldGhvZHNcbiAgICAgICAgICAgIFwibWV0aG9kXCIsXG4gICAgICAgICAgXSxcbiAgICAgICAgfSxcbiAgICAgIF0sXG4gICAgfTtcblxuICAgIC8vIE92ZXJyaWRlcyBmb3IgLnByb2plbnJjLmpzXG4gICAgLy8gQGRlcHJlY2F0ZWRcbiAgICBpZiAobGludFByb2plblJjKSB7XG4gICAgICB0aGlzLm92ZXJyaWRlcyA9IFtcbiAgICAgICAge1xuICAgICAgICAgIGZpbGVzOiBbbGludFByb2plblJjRmlsZSB8fCBERUZBVUxUX1BST0pFTl9SQ19KU19GSUxFTkFNRV0sXG4gICAgICAgICAgcnVsZXM6IHtcbiAgICAgICAgICAgIFwiQHR5cGVzY3JpcHQtZXNsaW50L25vLXJlcXVpcmUtaW1wb3J0c1wiOiBcIm9mZlwiLFxuICAgICAgICAgICAgXCJpbXBvcnQvbm8tZXh0cmFuZW91cy1kZXBlbmRlbmNpZXNcIjogXCJvZmZcIixcbiAgICAgICAgICB9LFxuICAgICAgICB9LFxuICAgICAgXTtcbiAgICB9XG5cbiAgICB0aGlzLmlnbm9yZVBhdHRlcm5zID0gb3B0aW9ucy5pZ25vcmVQYXR0ZXJucyA/PyBbXG4gICAgICBcIiouanNcIixcbiAgICAgIC8vIEBkZXByZWNhdGVkXG4gICAgICAuLi4obGludFByb2plblJjXG4gICAgICAgID8gW2AhJHtsaW50UHJvamVuUmNGaWxlIHx8IERFRkFVTFRfUFJPSkVOX1JDX0pTX0ZJTEVOQU1FfWBdXG4gICAgICAgIDogW10pLFxuICAgICAgXCIqLmQudHNcIixcbiAgICAgIFwibm9kZV9tb2R1bGVzL1wiLFxuICAgICAgXCIqLmdlbmVyYXRlZC50c1wiLFxuICAgICAgXCJjb3ZlcmFnZVwiLFxuICAgIF07XG5cbiAgICBjb25zdCB0c2NvbmZpZyA9IG9wdGlvbnMudHNjb25maWdQYXRoID8/IFwiLi90c2NvbmZpZy5qc29uXCI7XG5cbiAgICB0aGlzLmFkZFBsdWdpbnMoXCJAdHlwZXNjcmlwdC1lc2xpbnRcIik7XG4gICAgdGhpcy5hZGRQbHVnaW5zKFwiaW1wb3J0XCIpO1xuICAgIHRoaXMuYWRkRXh0ZW5kcyhcInBsdWdpbjppbXBvcnQvdHlwZXNjcmlwdFwiKTtcblxuICAgIHRoaXMuY29uZmlnID0ge1xuICAgICAgZW52OiB7XG4gICAgICAgIGplc3Q6IHRydWUsXG4gICAgICAgIG5vZGU6IHRydWUsXG4gICAgICB9LFxuICAgICAgcm9vdDogdHJ1ZSxcbiAgICAgIHBsdWdpbnM6IHRoaXMuX3BsdWdpbnMsXG4gICAgICBwYXJzZXI6IFwiQHR5cGVzY3JpcHQtZXNsaW50L3BhcnNlclwiLFxuICAgICAgcGFyc2VyT3B0aW9uczoge1xuICAgICAgICBlY21hVmVyc2lvbjogMjAxOCxcbiAgICAgICAgc291cmNlVHlwZTogXCJtb2R1bGVcIixcbiAgICAgICAgcHJvamVjdDogdHNjb25maWcsXG4gICAgICB9LFxuICAgICAgZXh0ZW5kczogKCkgPT5cbiAgICAgICAgQXJyYXkuZnJvbSh0aGlzLl9leHRlbmRzKS5zb3J0KChhLCBiKSA9PlxuICAgICAgICAgIHRoaXMuc29ydEV4dGVuZHMuY29tcGFyZShhLCBiKVxuICAgICAgICApLFxuICAgICAgc2V0dGluZ3M6IHtcbiAgICAgICAgXCJpbXBvcnQvcGFyc2Vyc1wiOiB7XG4gICAgICAgICAgXCJAdHlwZXNjcmlwdC1lc2xpbnQvcGFyc2VyXCI6IFtcIi50c1wiLCBcIi50c3hcIl0sXG4gICAgICAgIH0sXG4gICAgICAgIFwiaW1wb3J0L3Jlc29sdmVyXCI6IHtcbiAgICAgICAgICAuLi4ob3B0aW9ucy5hbGlhc01hcCAmJiB7XG4gICAgICAgICAgICBhbGlhczoge1xuICAgICAgICAgICAgICBtYXA6IE9iamVjdC5lbnRyaWVzKG9wdGlvbnMuYWxpYXNNYXApLm1hcCgoW2ssIHZdKSA9PiBbaywgdl0pLFxuICAgICAgICAgICAgICBleHRlbnNpb25zOiBvcHRpb25zLmFsaWFzRXh0ZW5zaW9ucyxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgfSksXG4gICAgICAgICAgbm9kZToge30sXG4gICAgICAgICAgdHlwZXNjcmlwdDoge1xuICAgICAgICAgICAgcHJvamVjdDogdHNjb25maWcsXG4gICAgICAgICAgICAuLi4ob3B0aW9ucy50c0Fsd2F5c1RyeVR5cGVzICE9PSBmYWxzZSAmJiB7IGFsd2F5c1RyeVR5cGVzOiB0cnVlIH0pLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICB9LFxuICAgICAgaWdub3JlUGF0dGVybnM6IHRoaXMuaWdub3JlUGF0dGVybnMsXG4gICAgICBydWxlczogKCkgPT4gKHsgLi4udGhpcy5fZm9ybWF0dGluZ1J1bGVzLCAuLi50aGlzLnJ1bGVzIH0pLFxuICAgICAgb3ZlcnJpZGVzOiB0aGlzLm92ZXJyaWRlcyxcbiAgICB9O1xuXG4gICAgaWYgKG9wdGlvbnMueWFtbCkge1xuICAgICAgbmV3IFlhbWxGaWxlKHByb2plY3QsIFwiLmVzbGludHJjLnltbFwiLCB7XG4gICAgICAgIG9iajogdGhpcy5jb25maWcsXG4gICAgICAgIG1hcmtlcjogdHJ1ZSxcbiAgICAgIH0pO1xuICAgIH0gZWxzZSB7XG4gICAgICBuZXcgSnNvbkZpbGUocHJvamVjdCwgXCIuZXNsaW50cmMuanNvblwiLCB7XG4gICAgICAgIG9iajogdGhpcy5jb25maWcsXG4gICAgICAgIC8vIGh0dHBzOi8vZXNsaW50Lm9yZy9kb2NzL2xhdGVzdC91c2VyLWd1aWRlL2NvbmZpZ3VyaW5nL2NvbmZpZ3VyYXRpb24tZmlsZXMjY29tbWVudHMtaW4tY29uZmlndXJhdGlvbi1maWxlc1xuICAgICAgICBtYXJrZXI6IHRydWUsXG4gICAgICAgIGFsbG93Q29tbWVudHM6IHRydWUsXG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvLyBpZiB0aGUgdXNlciBlbmFibGVkIHByZXR0aWVyIGV4cGxpY2l0bHkgX29yXyBpZiB0aGUgcHJvamVjdCBoYXMgYVxuICAgIC8vIGBQcmV0dGllcmAgY29tcG9uZW50LCB3ZSBzaGFsbCB0d2VhayBvdXIgY29uZmlndXJhdGlvbiBhY2NvcmRpbmdseS5cbiAgICBpZiAob3B0aW9ucy5wcmV0dGllciB8fCBQcmV0dGllci5vZihwcm9qZWN0KSkge1xuICAgICAgdGhpcy5lbmFibGVQcmV0dGllcigpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLm5vZGVQcm9qZWN0LmFkZERldkRlcHMoXCJAc3R5bGlzdGljL2VzbGludC1wbHVnaW5AXjJcIik7XG4gICAgICB0aGlzLmFkZFBsdWdpbnMoXCJAc3R5bGlzdGljXCIpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGFuIGltbXV0YWJsZSBjb3B5IG9mIHRoZSBsaW50UGF0dGVybnMgYmVpbmcgdXNlZCBieSB0aGlzIGVzbGludCBjb25maWd1cmF0aW9uLlxuICAgKi9cbiAgcHVibGljIGdldCBsaW50UGF0dGVybnMoKTogc3RyaW5nW10ge1xuICAgIGlmICh0aGlzLl9saW50UGF0dGVybnMgJiYgdGhpcy5fbGludFBhdHRlcm5zLnNpemUgPiAwKSB7XG4gICAgICByZXR1cm4gWy4uLnRoaXMuX2xpbnRQYXR0ZXJuc107XG4gICAgfVxuXG4gICAgcmV0dXJuIFtdO1xuICB9XG5cbiAgLyoqXG4gICAqIEFkZCBhIGZpbGUsIGdsb2IgcGF0dGVybiBvciBkaXJlY3Rvcnkgd2l0aCBzb3VyY2UgZmlsZXMgdG8gbGludCAoZS5nLiBbIFwic3JjXCIgXSlcbiAgICovXG4gIHB1YmxpYyBhZGRMaW50UGF0dGVybihwYXR0ZXJuOiBzdHJpbmcpIHtcbiAgICB0aGlzLl9saW50UGF0dGVybnMuYWRkKHBhdHRlcm4pO1xuICAgIHRoaXMudXBkYXRlVGFzaygpO1xuICB9XG5cbiAgLyoqXG4gICAqIEFkZCBhbiBlc2xpbnQgcnVsZS5cbiAgICovXG4gIHB1YmxpYyBhZGRSdWxlcyhydWxlczogeyBbcnVsZTogc3RyaW5nXTogYW55IH0pIHtcbiAgICBmb3IgKGNvbnN0IFtrLCB2XSBvZiBPYmplY3QuZW50cmllcyhydWxlcykpIHtcbiAgICAgIHRoaXMucnVsZXNba10gPSB2O1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBBZGRzIGFuIGVzbGludCBwbHVnaW5cbiAgICogQHBhcmFtIHBsdWdpbnMgVGhlIG5hbWVzIG9mIHBsdWdpbnMgdG8gYWRkXG4gICAqL1xuICBwdWJsaWMgYWRkUGx1Z2lucyguLi5wbHVnaW5zOiBzdHJpbmdbXSkge1xuICAgIGZvciAoY29uc3QgcGx1Z2luIG9mIHBsdWdpbnMpIHtcbiAgICAgIHRoaXMuX3BsdWdpbnMuYWRkKHBsdWdpbik7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEFkZCBhbiBlc2xpbnQgb3ZlcnJpZGUuXG4gICAqL1xuICBwdWJsaWMgYWRkT3ZlcnJpZGUob3ZlcnJpZGU6IEVzbGludE92ZXJyaWRlKSB7XG4gICAgdGhpcy5vdmVycmlkZXMucHVzaChvdmVycmlkZSk7XG4gIH1cblxuICAvKipcbiAgICogRG8gbm90IGxpbnQgdGhlc2UgZmlsZXMuXG4gICAqL1xuICBwdWJsaWMgYWRkSWdub3JlUGF0dGVybihwYXR0ZXJuOiBzdHJpbmcpIHtcbiAgICB0aGlzLmlnbm9yZVBhdHRlcm5zLnB1c2gocGF0dGVybik7XG4gIH1cblxuICAvKipc