projen
Version:
CDK for software projects
355 lines • 40.6 kB
JavaScript
;
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.DependencyType = exports.Dependencies = void 0;
const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
const path = __importStar(require("path"));
const chalk_1 = require("chalk");
const semver = __importStar(require("semver"));
const common_1 = require("./common");
const component_1 = require("./component");
const json_1 = require("./json");
/**
* The `Dependencies` component is responsible to track the list of dependencies
* a project has, and then used by project types as the model for rendering
* project-specific dependency manifests such as the dependencies section
* `package.json` files.
*
* To add a dependency you can use a project-type specific API such as
* `nodeProject.addDeps()` or use the generic API of `project.deps`:
*/
class Dependencies extends component_1.Component {
static [JSII_RTTI_SYMBOL_1] = { fqn: "projen.Dependencies", version: "0.103.12" };
/**
* The project-relative path of the deps manifest file.
*/
static MANIFEST_FILE = path.posix.join(common_1.PROJEN_DIR, "deps.json");
/**
* Returns the coordinates of a dependency spec.
*
* Given `foo@^3.4.0` returns `{ name: "foo", version: "^3.4.0" }`.
* Given `bar@npm:@bar/legacy` returns `{ name: "bar", version: "npm:@bar/legacy" }`.
*/
static parseDependency(spec) {
const scope = spec.startsWith("@");
if (scope) {
spec = spec.substring(1);
}
const [module, ...version] = spec.split("@");
const name = scope ? `@${module}` : module;
if (version.length == 0) {
return { name };
}
else {
return { name, version: version?.join("@") };
}
}
_deps = new Array();
/**
* Adds a dependencies component to the project.
* @param project The parent project
*/
constructor(project) {
super(project);
// this is not really required at the moment, but actually quite useful as a
// checked-in source of truth for dependencies and will potentially be
// valuable in the future for CLI tools.
if (!project.ejected) {
new json_1.JsonFile(project, Dependencies.MANIFEST_FILE, {
omitEmpty: true,
obj: () => this.toJson(),
});
}
}
/**
* A copy of all dependencies recorded for this project.
*
* The list is sorted by type->name->version
*/
get all() {
return [...this._deps].sort(compareDeps).map(normalizeDep);
}
/**
* Returns a dependency by name.
*
* Fails if there is no dependency defined by that name or if `type` is not
* provided and there is more then one dependency type for this dependency.
*
* @param name The name of the dependency
* @param type The dependency type. If this dependency is defined only for a
* single type, this argument can be omitted.
*
* @returns a copy (cannot be modified)
*/
getDependency(name, type) {
const dep = this.tryGetDependency(name, type);
if (!dep) {
const msg = type
? `there is no ${type} dependency defined on "${name}"`
: `there is no dependency defined on "${name}"`;
throw new Error(msg);
}
return dep;
}
/**
* Returns a dependency by name.
*
* Returns `undefined` if there is no dependency defined by that name or if
* `type` is not provided and there is more then one dependency type for this
* dependency.
*
* @param name The name of the dependency
* @param type The dependency type. If this dependency is defined only for a
* single type, this argument can be omitted.
*
* @returns a copy (cannot be modified) or undefined if there is no match
*/
tryGetDependency(name, type) {
const idx = this.tryGetDependencyIndex(name, type);
if (idx === -1) {
return undefined;
}
return {
...normalizeDep(this._deps[idx]),
};
}
/**
* Adds a dependency to this project.
* @param spec The dependency spec in the format `MODULE[@VERSION]` where
* `MODULE` is the package-manager-specific module name and `VERSION` is an
* optional semantic version requirement (e.g. `^3.4.0`).
* @param type The type of the dependency.
*/
addDependency(spec, type, metadata = {}) {
this.project.logger.verbose(`${(0, chalk_1.underline)("Dependency")} | Adding ${type}-dep \`${spec}\``);
const dep = {
...Dependencies.parseDependency(spec),
type,
metadata,
};
const existingDepIndex = this.tryGetDependencyIndex(dep.name, type);
if (existingDepIndex !== -1) {
this.project.logger.debug(`${(0, chalk_1.underline)("Dependency")} | Updating existing ${dep.type}-dep \`${dep.name}\` with more specific request.`);
this._deps[existingDepIndex] = dep;
}
else {
this._deps.push(dep);
}
return dep;
}
/**
* Removes a dependency.
* @param name The name of the module to remove (without the version)
* @param type The dependency type. This is only required if there the
* dependency is defined for multiple types.
*/
removeDependency(name, type) {
const removeIndex = this.tryGetDependencyIndex(name, type);
if (removeIndex === -1) {
return;
}
this._deps.splice(removeIndex, 1);
}
/**
* Checks if an existing dependency satisfies a dependency requirement.
* @param name The name of the dependency to check (without the version).
* @param type The dependency type.
* @param expectedRange The version constraint to check (e.g. `^3.4.0`).
* The constraint of the dependency must be a subset of the expected range to satisfy the requirements.
* @returns `true` if the dependency exists and its version satisfies the provided constraint. `false` otherwise.
* Notably returns `false` if a dependency exists, but has no version.
*/
isDependencySatisfied(name, type, expectedRange) {
const dep = this.tryGetDependency(name, type);
return dep?.version != null && semver.subset(dep.version, expectedRange);
}
/**
* Request a dependency. Unlike `addDependency`, this merges intelligently
* with existing dependencies of the same name and type:
*
* - If the dep exists with a version that already satisfies the request,
* the version is not changed.
* - If the dep doesn't exist, it is added with the requested type/version.
* - If the dep exists but the versions don't intersect, an error is thrown.
* - If no type is provided, an existing dependency of any type will satisfy
* the request. If none exists, it is added as BUILD.
*
* @param request The dependency request.
* @returns The resulting dependency after merging.
*/
requestDependency(request) {
// When type is not specified, find any existing dep with this name
const requestedType = request.type ??
this.findExistingInstallableType(request.name) ??
DependencyType.BUILD;
const existing = this.tryGetDependency(request.name, requestedType);
if (!existing) {
const spec = request.version
? `${request.name}@${request.version}`
: request.name;
return this.addDependency(spec, requestedType, request.metadata ?? {});
}
// Version merging
let effectiveVersion;
if (!request.version) {
effectiveVersion = existing.version;
}
else if (this.isDependencySatisfied(request.name, requestedType, request.version)) {
effectiveVersion = existing.version;
}
else if (!existing.version) {
effectiveVersion = request.version;
}
else if (semver.intersects(existing.version, request.version)) {
effectiveVersion = request.version;
}
else {
throw new Error(`Dependency "${request.name}" version conflict: existing "${existing.version}" ` +
`does not intersect with requested "${request.version}"`);
}
const spec = effectiveVersion
? `${request.name}@${effectiveVersion}`
: request.name;
return this.addDependency(spec, requestedType, {
...existing.metadata,
...request.metadata,
});
}
/**
* Finds the type of an existing installable dependency by name.
* Excludes PEER, OVERRIDE, and OPTIONAL types.
* Returns undefined if no dependency with this name exists.
*/
findExistingInstallableType(name) {
return this._deps.find((d) => d.name === name &&
d.type !== DependencyType.PEER &&
d.type !== DependencyType.OVERRIDE &&
d.type !== DependencyType.OPTIONAL)?.type;
}
tryGetDependencyIndex(name, type) {
const deps = this._deps.filter((d) => d.name === name);
if (deps.length === 0) {
return -1; // not found
}
if (!type) {
if (deps.length > 1) {
throw new Error(`"${name}" is defined for multiple dependency types: ${deps
.map((d) => d.type)
.join(",")}. Please specify dependency type`);
}
type = deps[0].type;
}
return this._deps.findIndex((dep) => dep.name === name && dep.type === type);
}
toJson() {
if (this._deps.length === 0) {
return undefined;
}
return {
dependencies: this._deps.sort(compareDeps).map(normalizeDep),
};
}
}
exports.Dependencies = Dependencies;
function normalizeDep(d) {
const obj = {};
for (const [k, v] of Object.entries(d)) {
if (v == undefined) {
continue;
}
if (typeof v === "object" && Object.keys(v).length === 0) {
continue;
}
if (Array.isArray(v) && v.length === 0) {
continue;
}
obj[k] = v;
}
return obj;
}
function compareDeps(d1, d2) {
return specOf(d1).localeCompare(specOf(d2));
function specOf(dep) {
let spec = dep.type + ":" + dep.name;
if (dep.version) {
spec += "@" + dep.version;
}
return spec;
}
}
/**
* Type of dependency.
*/
var DependencyType;
(function (DependencyType) {
/**
* The dependency is required for the program/library during runtime.
*/
DependencyType["RUNTIME"] = "runtime";
/**
* The dependency is required at runtime but expected to be installed by the
* consumer.
*/
DependencyType["PEER"] = "peer";
/**
* The dependency is bundled and shipped with the module, so consumers are not
* required to install it.
*/
DependencyType["BUNDLED"] = "bundled";
/**
* The dependency is required to run the `build` task.
*/
DependencyType["BUILD"] = "build";
/**
* The dependency is required to run the `test` task.
*/
DependencyType["TEST"] = "test";
/**
* The dependency is required for development (e.g. IDE plugins).
*/
DependencyType["DEVENV"] = "devenv";
/**
* Transient dependency that needs to be overwritten.
*
* Available for Node packages
*/
DependencyType["OVERRIDE"] = "override";
/**
* An optional dependency that may be used at runtime if available, but is not required.
* It is expected to be installed by the consumer.
*/
DependencyType["OPTIONAL"] = "optional";
})(DependencyType || (exports.DependencyType = DependencyType = {}));
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVwZW5kZW5jaWVzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL2RlcGVuZGVuY2llcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUEsMkNBQTZCO0FBQzdCLGlDQUFrQztBQUNsQywrQ0FBaUM7QUFDakMscUNBQXNDO0FBQ3RDLDJDQUF3QztBQUN4QyxpQ0FBa0M7QUFHbEM7Ozs7Ozs7O0dBUUc7QUFDSCxNQUFhLFlBQWEsU0FBUSxxQkFBUzs7SUFDekM7O09BRUc7SUFDSSxNQUFNLENBQVUsYUFBYSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUNwRCxtQkFBVSxFQUNWLFdBQVcsQ0FDWixDQUFDO0lBRUY7Ozs7O09BS0c7SUFDSSxNQUFNLENBQUMsZUFBZSxDQUFDLElBQVk7UUFDeEMsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUNuQyxJQUFJLEtBQUssRUFBRSxDQUFDO1lBQ1YsSUFBSSxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDM0IsQ0FBQztRQUVELE1BQU0sQ0FBQyxNQUFNLEVBQUUsR0FBRyxPQUFPLENBQUMsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQzdDLE1BQU0sSUFBSSxHQUFHLEtBQUssQ0FBQyxDQUFDLENBQUMsSUFBSSxNQUFNLEVBQUUsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDO1FBQzNDLElBQUksT0FBTyxDQUFDLE1BQU0sSUFBSSxDQUFDLEVBQUUsQ0FBQztZQUN4QixPQUFPLEVBQUUsSUFBSSxFQUFFLENBQUM7UUFDbEIsQ0FBQzthQUFNLENBQUM7WUFDTixPQUFPLEVBQUUsSUFBSSxFQUFFLE9BQU8sRUFBRSxPQUFPLEVBQUUsSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUM7UUFDL0MsQ0FBQztJ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QyxhQUFhLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFFNUMsU0FBUyxNQUFNLENBQUMsR0FBZTtRQUM3QixJQUFJLElBQUksR0FBRyxHQUFHLENBQUMsSUFBSSxHQUFHLEdBQUcsR0FBRyxHQUFHLENBQUMsSUFBSSxDQUFDO1FBQ3JDLElBQUksR0FBRyxDQUFDLE9BQU8sRUFBRSxDQUFDO1lBQ2hCLElBQUksSUFBSSxHQUFHLEdBQUcsR0FBRyxDQUFDLE9BQU8sQ0FBQztRQUM1QixDQUFDO1FBQ0QsT0FBTyxJQUFJLENBQUM7SUFDZCxDQUFDO0FBQ0gsQ0FBQztBQThDRDs7R0FFRztBQUNILElBQVksY0E2Q1g7QUE3Q0QsV0FBWSxjQUFjO0lBQ3hCOztPQUVHO0lBQ0gscUNBQW1CLENBQUE7SUFFbkI7OztPQUdHO0lBQ0gsK0JBQWEsQ0FBQTtJQUViOzs7T0FHRztJQUNILHFDQUFtQixDQUFBO0lBRW5COztPQUVHO0lBQ0gsaUNBQWUsQ0FBQTtJQUVmOztPQUVHO0lBQ0gsK0JBQWEsQ0FBQTtJQUViOztPQUVHO0lBQ0gsbUNBQWlCLENBQUE7SUFFakI7Ozs7T0FJRztJQUNILHVDQUFxQixDQUFBO0lBRXJCOzs7T0FHRztJQUNILHVDQUFxQixDQUFBO0FBQ3ZCLENBQUMsRUE3Q1csY0FBYyw4QkFBZCxjQUFjLFFBNkN6QiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAqIGFzIHBhdGggZnJvbSBcInBhdGhcIjtcbmltcG9ydCB7IHVuZGVybGluZSB9IGZyb20gXCJjaGFsa1wiO1xuaW1wb3J0ICogYXMgc2VtdmVyIGZyb20gXCJzZW12ZXJcIjtcbmltcG9ydCB7IFBST0pFTl9ESVIgfSBmcm9tIFwiLi9jb21tb25cIjtcbmltcG9ydCB7IENvbXBvbmVudCB9IGZyb20gXCIuL2NvbXBvbmVudFwiO1xuaW1wb3J0IHsgSnNvbkZpbGUgfSBmcm9tIFwiLi9qc29uXCI7XG5pbXBvcnQgdHlwZSB7IFByb2plY3QgfSBmcm9tIFwiLi9wcm9qZWN0XCI7XG5cbi8qKlxuICogVGhlIGBEZXBlbmRlbmNpZXNgIGNvbXBvbmVudCBpcyByZXNwb25zaWJsZSB0byB0cmFjayB0aGUgbGlzdCBvZiBkZXBlbmRlbmNpZXNcbiAqIGEgcHJvamVjdCBoYXMsIGFuZCB0aGVuIHVzZWQgYnkgcHJvamVjdCB0eXBlcyBhcyB0aGUgbW9kZWwgZm9yIHJlbmRlcmluZ1xuICogcHJvamVjdC1zcGVjaWZpYyBkZXBlbmRlbmN5IG1hbmlmZXN0cyBzdWNoIGFzIHRoZSBkZXBlbmRlbmNpZXMgc2VjdGlvblxuICogYHBhY2thZ2UuanNvbmAgZmlsZXMuXG4gKlxuICogVG8gYWRkIGEgZGVwZW5kZW5jeSB5b3UgY2FuIHVzZSBhIHByb2plY3QtdHlwZSBzcGVjaWZpYyBBUEkgc3VjaCBhc1xuICogYG5vZGVQcm9qZWN0LmFkZERlcHMoKWAgb3IgdXNlIHRoZSBnZW5lcmljIEFQSSBvZiBgcHJvamVjdC5kZXBzYDpcbiAqL1xuZXhwb3J0IGNsYXNzIERlcGVuZGVuY2llcyBleHRlbmRzIENvbXBvbmVudCB7XG4gIC8qKlxuICAgKiBUaGUgcHJvamVjdC1yZWxhdGl2ZSBwYXRoIG9mIHRoZSBkZXBzIG1hbmlmZXN0IGZpbGUuXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIHJlYWRvbmx5IE1BTklGRVNUX0ZJTEUgPSBwYXRoLnBvc2l4LmpvaW4oXG4gICAgUFJPSkVOX0RJUixcbiAgICBcImRlcHMuanNvblwiLFxuICApO1xuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSBjb29yZGluYXRlcyBvZiBhIGRlcGVuZGVuY3kgc3BlYy5cbiAgICpcbiAgICogR2l2ZW4gYGZvb0BeMy40LjBgIHJldHVybnMgYHsgbmFtZTogXCJmb29cIiwgdmVyc2lvbjogXCJeMy40LjBcIiB9YC5cbiAgICogR2l2ZW4gYGJhckBucG06QGJhci9sZWdhY3lgIHJldHVybnMgYHsgbmFtZTogXCJiYXJcIiwgdmVyc2lvbjogXCJucG06QGJhci9sZWdhY3lcIiB9YC5cbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgcGFyc2VEZXBlbmRlbmN5KHNwZWM6IHN0cmluZyk6IERlcGVuZGVuY3lDb29yZGluYXRlcyB7XG4gICAgY29uc3Qgc2NvcGUgPSBzcGVjLnN0YXJ0c1dpdGgoXCJAXCIpO1xuICAgIGlmIChzY29wZSkge1xuICAgICAgc3BlYyA9IHNwZWMuc3Vic3RyaW5nKDEpO1xuICAgIH1cblxuICAgIGNvbnN0IFttb2R1bGUsIC4uLnZlcnNpb25dID0gc3BlYy5zcGxpdChcIkBcIik7XG4gICAgY29uc3QgbmFtZSA9IHNjb3BlID8gYEAke21vZHVsZX1gIDogbW9kdWxlO1xuICAgIGlmICh2ZXJzaW9uLmxlbmd0aCA9PSAwKSB7XG4gICAgICByZXR1cm4geyBuYW1lIH07XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiB7IG5hbWUsIHZlcnNpb246IHZlcnNpb24/LmpvaW4oXCJAXCIpIH07XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSByZWFkb25seSBfZGVwcyA9IG5ldyBBcnJheTxEZXBlbmRlbmN5PigpO1xuXG4gIC8qKlxuICAgKiBBZGRzIGEgZGVwZW5kZW5jaWVzIGNvbXBvbmVudCB0byB0aGUgcHJvamVjdC5cbiAgICogQHBhcmFtIHByb2plY3QgVGhlIHBhcmVudCBwcm9qZWN0XG4gICAqL1xuICBjb25zdHJ1Y3Rvcihwcm9qZWN0OiBQcm9qZWN0KSB7XG4gICAgc3VwZXIocHJvamVjdCk7XG5cbiAgICAvLyB0aGlzIGlzIG5vdCByZWFsbHkgcmVxdWlyZWQgYXQgdGhlIG1vbWVudCwgYnV0IGFjdHVhbGx5IHF1aXRlIHVzZWZ1bCBhcyBhXG4gICAgLy8gY2hlY2tlZC1pbiBzb3VyY2Ugb2YgdHJ1dGggZm9yIGRlcGVuZGVuY2llcyBhbmQgd2lsbCBwb3RlbnRpYWxseSBiZVxuICAgIC8vIHZhbHVhYmxlIGluIHRoZSBmdXR1cmUgZm9yIENMSSB0b29scy5cbiAgICBpZiAoIXByb2plY3QuZWplY3RlZCkge1xuICAgICAgbmV3IEpzb25GaWxlKHByb2plY3QsIERlcGVuZGVuY2llcy5NQU5JRkVTVF9GSUxFLCB7XG4gICAgICAgIG9taXRFbXB0eTogdHJ1ZSxcbiAgICAgICAgb2JqOiAoKSA9PiB0aGlzLnRvSnNvbigpLFxuICAgICAgfSk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEEgY29weSBvZiBhbGwgZGVwZW5kZW5jaWVzIHJlY29yZGVkIGZvciB0aGlzIHByb2plY3QuXG4gICAqXG4gICAqIFRoZSBsaXN0IGlzIHNvcnRlZCBieSB0eXBlLT5uYW1lLT52ZXJzaW9uXG4gICAqL1xuICBwdWJsaWMgZ2V0IGFsbCgpOiBEZXBlbmRlbmN5W10ge1xuICAgIHJldHVybiBbLi4udGhpcy5fZGVwc10uc29ydChjb21wYXJlRGVwcykubWFwKG5vcm1hbGl6ZURlcCk7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyBhIGRlcGVuZGVuY3kgYnkgbmFtZS5cbiAgICpcbiAgICogRmFpbHMgaWYgdGhlcmUgaXMgbm8gZGVwZW5kZW5jeSBkZWZpbmVkIGJ5IHRoYXQgbmFtZSBvciBpZiBgdHlwZWAgaXMgbm90XG4gICAqIHByb3ZpZGVkIGFuZCB0aGVyZSBpcyBtb3JlIHRoZW4gb25lIGRlcGVuZGVuY3kgdHlwZSBmb3IgdGhpcyBkZXBlbmRlbmN5LlxuICAgKlxuICAgKiBAcGFyYW0gbmFtZSBUaGUgbmFtZSBvZiB0aGUgZGVwZW5kZW5jeVxuICAgKiBAcGFyYW0gdHlwZSBUaGUgZGVwZW5kZW5jeSB0eXBlLiBJZiB0aGlzIGRlcGVuZGVuY3kgaXMgZGVmaW5lZCBvbmx5IGZvciBhXG4gICAqIHNpbmdsZSB0eXBlLCB0aGlzIGFyZ3VtZW50IGNhbiBiZSBvbWl0dGVkLlxuICAgKlxuICAgKiBAcmV0dXJucyBhIGNvcHkgKGNhbm5vdCBiZSBtb2RpZmllZClcbiAgICovXG4gIHB1YmxpYyBnZXREZXBlbmRlbmN5KG5hbWU6IHN0cmluZywgdHlwZT86IERlcGVuZGVuY3lUeXBlKTogRGVwZW5kZW5jeSB7XG4gICAgY29uc3QgZGVwID0gdGhpcy50cnlHZXREZXBlbmRlbmN5KG5hbWUsIHR5cGUpO1xuICAgIGlmICghZGVwKSB7XG4gICAgICBjb25zdCBtc2cgPSB0eXBlXG4gICAgICAgID8gYHRoZXJlIGlzIG5vICR7dHlwZX0gZGVwZW5kZW5jeSBkZWZpbmVkIG9uIFwiJHtuYW1lfVwiYFxuICAgICAgICA6IGB0aGVyZSBpcyBubyBkZXBlbmRlbmN5IGRlZmluZWQgb24gXCIke25hbWV9XCJgO1xuXG4gICAgICB0aHJvdyBuZXcgRXJyb3IobXNnKTtcbiAgICB9XG5cbiAgICByZXR1cm4gZGVwO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgYSBkZXBlbmRlbmN5IGJ5IG5hbWUuXG4gICAqXG4gICAqIFJldHVybnMgYHVuZGVmaW5lZGAgaWYgdGhlcmUgaXMgbm8gZGVwZW5kZW5jeSBkZWZpbmVkIGJ5IHRoYXQgbmFtZSBvciBpZlxuICAgKiBgdHlwZWAgaXMgbm90IHByb3ZpZGVkIGFuZCB0aGVyZSBpcyBtb3JlIHRoZW4gb25lIGRlcGVuZGVuY3kgdHlwZSBmb3IgdGhpc1xuICAgKiBkZXBlbmRlbmN5LlxuICAgKlxuICAgKiBAcGFyYW0gbmFtZSBUaGUgbmFtZSBvZiB0aGUgZGVwZW5kZW5jeVxuICAgKiBAcGFyYW0gdHlwZSBUaGUgZGVwZW5kZW5jeSB0eXBlLiBJZiB0aGlzIGRlcGVuZGVuY3kgaXMgZGVmaW5lZCBvbmx5IGZvciBhXG4gICAqIHNpbmdsZSB0eXBlLCB0aGlzIGFyZ3VtZW50IGNhbiBiZSBvbWl0dGVkLlxuICAgKlxuICAgKiBAcmV0dXJucyBhIGNvcHkgKGNhbm5vdCBiZSBtb2RpZmllZCkgb3IgdW5kZWZpbmVkIGlmIHRoZXJlIGlzIG5vIG1hdGNoXG4gICAqL1xuICBwdWJsaWMgdHJ5R2V0RGVwZW5kZW5jeShcbiAgICBuYW1lOiBzdHJpbmcsXG4gICAgdHlwZT86IERlcGVuZGVuY3lUeXBlLFxuICApOiBEZXBlbmRlbmN5IHwgdW5kZWZpbmVkIHtcbiAgICBjb25zdCBpZHggPSB0aGlzLnRyeUdldERlcGVuZGVuY3lJbmRleChuYW1lLCB0eXBlKTtcbiAgICBpZiAoaWR4ID09PSAtMSkge1xuICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgLi4ubm9ybWFsaXplRGVwKHRoaXMuX2RlcHNbaWR4XSksXG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBZGRzIGEgZGVwZW5kZW5jeSB0byB0aGlzIHByb2plY3QuXG4gICAqIEBwYXJhbSBzcGVjIFRoZSBkZXBlbmRlbmN5IHNwZWMgaW4gdGhlIGZvcm1hdCBgTU9EVUxFW0BWRVJTSU9OXWAgd2hlcmVcbiAgICogYE1PRFVMRWAgaXMgdGhlIHBhY2thZ2UtbWFuYWdlci1zcGVjaWZpYyBtb2R1bGUgbmFtZSBhbmQgYFZFUlNJT05gIGlzIGFuXG4gICAqIG9wdGlvbmFsIHNlbWFudGljIHZlcnNpb24gcmVxdWlyZW1lbnQgKGUuZy4gYF4zLjQuMGApLlxuICAgKiBAcGFyYW0gdHlwZSBUaGUgdHlwZSBvZiB0aGUgZGVwZW5kZW5jeS5cbiAgICovXG4gIHB1YmxpYyBhZGREZXBlbmRlbmN5KFxuICAgIHNwZWM6IHN0cmluZyxcbiAgICB0eXBlOiBEZXBlbmRlbmN5VHlwZSxcbiAgICBtZXRhZGF0YTogeyBba2V5OiBzdHJpbmddOiBhbnkgfSA9IHt9LFxuICApOiBEZXBlbmRlbmN5IHtcbiAgICB0aGlzLnByb2plY3QubG9nZ2VyLnZlcmJvc2UoXG4gICAgICBgJHt1bmRlcmxpbmUoXCJEZXBlbmRlbmN5XCIpfSB8IEFkZGluZyAke3R5cGV9LWRlcCBcXGAke3NwZWN9XFxgYCxcbiAgICApO1xuXG4gICAgY29uc3QgZGVwOiBEZXBlbmRlbmN5ID0ge1xuICAgICAgLi4uRGVwZW5kZW5jaWVzLnBhcnNlRGVwZW5kZW5jeShzcGVjKSxcbiAgICAgIHR5cGUsXG4gICAgICBtZXRhZGF0YSxcbiAgICB9O1xuXG4gICAgY29uc3QgZXhpc3RpbmdEZXBJbmRleCA9IHRoaXMudHJ5R2V0RGVwZW5kZW5jeUluZGV4KGRlcC5uYW1lLCB0eXBlKTtcblxuICAgIGlmIChleGlzdGluZ0RlcEluZGV4ICE9PSAtMSkge1xuICAgICAgdGhpcy5wcm9qZWN0LmxvZ2dlci5kZWJ1ZyhcbiAgICAgICAgYCR7dW5kZXJsaW5lKFwiRGVwZW5kZW5jeVwiKX0gfCBVcGRhdGluZyBleGlzdGluZyAke2RlcC50eXBlfS1kZXAgXFxgJHtkZXAubmFtZX1cXGAgd2l0aCBtb3JlIHNwZWNpZmljIHJlcXVlc3QuYCxcbiAgICAgICk7XG4gICAgICB0aGlzLl9kZXBzW2V4aXN0aW5nRGVwSW5kZXhdID0gZGVwO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLl9kZXBzLnB1c2goZGVwKTtcbiAgICB9XG5cbiAgICByZXR1cm4gZGVwO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlbW92ZXMgYSBkZXBlbmRlbmN5LlxuICAgKiBAcGFyYW0gbmFtZSBUaGUgbmFtZSBvZiB0aGUgbW9kdWxlIHRvIHJlbW92ZSAod2l0aG91dCB0aGUgdmVyc2lvbilcbiAgICogQHBhcmFtIHR5cGUgVGhlIGRlcGVuZGVuY3kgdHlwZS4gVGhpcyBpcyBvbmx5IHJlcXVpcmVkIGlmIHRoZXJlIHRoZVxuICAgKiBkZXBlbmRlbmN5IGlzIGRlZmluZWQgZm9yIG11bHRpcGxlIHR5cGVzLlxuICAgKi9cbiAgcHVibGljIHJlbW92ZURlcGVuZGVuY3kobmFtZTogc3RyaW5nLCB0eXBlPzogRGVwZW5kZW5jeVR5cGUpIHtcbiAgICBjb25zdCByZW1vdmVJbmRleCA9IHRoaXMudHJ5R2V0RGVwZW5kZW5jeUluZGV4KG5hbWUsIHR5cGUpO1xuICAgIGlmIChyZW1vdmVJbmRleCA9PT0gLTEpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLl9kZXBzLnNwbGljZShyZW1vdmVJbmRleCwgMSk7XG4gIH1cblxuICAvKipcbiAgICogQ2hlY2tzIGlmIGFuIGV4aXN0aW5nIGRlcGVuZGVuY3kgc2F0aXNmaWVzIGEgZGVwZW5kZW5jeSByZXF1aXJlbWVudC5cbiAgICogQHBhcmFtIG5hbWUgVGhlIG5hbWUgb2YgdGhlIGRlcGVuZGVuY3kgdG8gY2hlY2sgKHdpdGhvdXQgdGhlIHZlcnNpb24pLlxuICAgKiBAcGFyYW0gdHlwZSBUaGUgZGVwZW5kZW5jeSB0eXBlLlxuICAgKiBAcGFyYW0gZXhwZWN0ZWRSYW5nZSBUaGUgdmVyc2lvbiBjb25zdHJhaW50IHRvIGNoZWNrIChlLmcuIGBeMy40LjBgKS5cbiAgICogVGhlIGNvbnN0cmFpbnQgb2YgdGhlIGRlcGVuZGVuY3kgbXVzdCBiZSBhIHN1YnNldCBvZiB0aGUgZXhwZWN0ZWQgcmFuZ2UgdG8gc2F0aXNmeSB0aGUgcmVxdWlyZW1lbnRzLlxuICAgKiBAcmV0dXJucyBgdHJ1ZWAgaWYgdGhlIGRlcGVuZGVuY3kgZXhpc3RzIGFuZCBpdHMgdmVyc2lvbiBzYXRpc2ZpZXMgdGhlIHByb3ZpZGVkIGNvbnN0cmFpbnQuIGBmYWxzZWAgb3RoZXJ3aXNlLlxuICAgKiBOb3RhYmx5IHJldHVybnMgYGZhbHNlYCBpZiBhIGRlcGVuZGVuY3kgZXhpc3RzLCBidXQgaGFzIG5vIHZlcnNpb24uXG4gICAqL1xuICBwdWJsaWMgaXNEZXBlbmRlbmN5U2F0aXNmaWVkKFxuICAgIG5hbWU6IHN0cmluZyxcbiAgICB0eXBlOiBEZXBlbmRlbmN5VHlwZSxcbiAgICBleHBlY3RlZFJhbmdlOiBzdHJpbmcsXG4gICk6IGJvb2xlYW4ge1xuICAgIGNvbnN0IGRlcCA9IHRoaXMudHJ5R2V0RGVwZW5kZW5jeShuYW1lLCB0eXBlKTtcbiAgICByZXR1cm4gZGVwPy52ZXJzaW9uICE9IG51bGwgJiYgc2VtdmVyLnN1YnNldChkZXAudmVyc2lvbiwgZXhwZWN0ZWRSYW5nZSk7XG4gIH1cblxuICAvKipcbiAgICogUmVxdWVzdCBhIGRlcGVuZGVuY3kuIFVubGlrZSBgYWRkRGVwZW5kZW5jeWAsIHRoaXMgbWVyZ2VzIGludGVsbGlnZW50bHlcbiAgICogd2l0aCBleGlzdGluZyBkZXBlbmRlbmNpZXMgb2YgdGhlIHNhbWUgbmFtZSBhbmQgdHlwZTpcbiAgICpcbiAgICogLSBJZiB0aGUgZGVwIGV4aXN0cyB3aXRoIGEgdmVyc2lvbiB0aGF0IGFscmVhZHkgc2F0aXNmaWVzIHRoZSByZXF1ZXN0LFxuICAgKiAgIHRoZSB2ZXJzaW9uIGlzIG5vdCBjaGFuZ2VkLlxuICAgKiAtIElmIHRoZSBkZXAgZG9lc24ndCBleGlzdCwgaXQgaXMgYWRkZWQgd2l0aCB0aGUgcmVxdWVzdGVkIHR5cGUvdmVyc2lvbi5cbiAgICogLSBJZiB0aGUgZGVwIGV4aXN0cyBidXQgdGhlIHZlcnNpb25zIGRvbid0IGludGVyc2VjdCwgYW4gZXJyb3IgaXMgdGhyb3duLlxuICAgKiAtIElmIG5vIHR5cGUgaXMgcHJvdmlkZWQsIGFuIGV4aXN0aW5nIGRlcGVuZGVuY3kgb2YgYW55IHR5cGUgd2lsbCBzYXRpc2Z5XG4gICAqICAgdGhlIHJlcXVlc3QuIElmIG5vbmUgZXhpc3RzLCBpdCBpcyBhZGRlZCBhcyBCVUlMRC5cbiAgICpcbiAgICogQHBhcmFtIHJlcXVlc3QgVGhlIGRlcGVuZGVuY3kgcmVxdWVzdC5cbiAgICogQHJldHVybnMgVGhlIHJlc3VsdGluZyBkZXBlbmRlbmN5IGFmdGVyIG1lcmdpbmcuXG4gICAqL1xuICBwdWJsaWMgcmVxdWVzdERlcGVuZGVuY3kocmVxdWVzdDogRGVwZW5kZW5jeVJlcXVlc3QpOiBEZXBlbmRlbmN5IHtcbiAgICAvLyBXaGVuIHR5cGUgaXMgbm90IHNwZWNpZmllZCwgZmluZCBhbnkgZXhpc3RpbmcgZGVwIHdpdGggdGhpcyBuYW1lXG4gICAgY29uc3QgcmVxdWVzdGVkVHlwZSA9XG4gICAgICByZXF1ZXN0LnR5cGUgPz9cbiAgICAgIHRoaXMuZmluZEV4aXN0aW5nSW5zdGFsbGFibGVUeXBlKHJlcXVlc3QubmFtZSkgPz9cbiAgICAgIERlcGVuZGVuY3lUeXBlLkJVSUxEO1xuICAgIGNvbnN0IGV4aXN0aW5nID0gdGhpcy50cnlHZXREZXBlbmRlbmN5KHJlcXVlc3QubmFtZSwgcmVxdWVzdGVkVHlwZSk7XG5cbiAgICBpZiAoIWV4aXN0aW5nKSB7XG4gICAgICBjb25zdCBzcGVjID0gcmVxdWVzdC52ZXJzaW9uXG4gICAgICAgID8gYCR7cmVxdWVzdC5uYW1lfUAke3JlcXVlc3QudmVyc2lvbn1gXG4gICAgICAgIDogcmVxdWVzdC5uYW1lO1xuICAgICAgcmV0dXJuIHRoaXMuYWRkRGVwZW5kZW5jeShzcGVjLCByZXF1ZXN0ZWRUeXBlLCByZXF1ZXN0Lm1ldGFkYXRhID8/IHt9KTtcbiAgICB9XG5cbiAgICAvLyBWZXJzaW9uIG1lcmdpbmdcbiAgICBsZXQgZWZmZWN0aXZlVmVyc2lvbjogc3RyaW5nIHwgdW5kZWZpbmVkO1xuXG4gICAgaWYgKCFyZXF1ZXN0LnZlcnNpb24pIHtcbiAgICAgIGVmZmVjdGl2ZVZlcnNpb24gPSBleGlzdGluZy52ZXJzaW9uO1xuICAgIH0gZWxzZSBpZiAoXG4gICAgICB0aGlzLmlzRGVwZW5kZW5jeVNhdGlzZmllZChyZXF1ZXN0Lm5hbWUsIHJlcXVlc3RlZFR5cGUsIHJlcXVlc3QudmVyc2lvbilcbiAgICApIHtcbiAgICAgIGVmZmVjdGl2ZVZlcnNpb24gPSBleGlzdGluZy52ZXJzaW9uO1xuICAgIH0gZWxzZSBpZiAoIWV4aXN0aW5nLnZlcnNpb24pIHtcbiAgICAgIGVmZmVjdGl2ZVZlcnNpb24gPSByZXF1ZXN0LnZlcnNpb247XG4gICAgfSBlbHNlIGlmIChzZW12ZXIuaW50ZXJzZWN0cyhleGlzdGluZy52ZXJzaW9uLCByZXF1ZXN0LnZlcnNpb24pKSB7XG4gICAgICBlZmZlY3RpdmVWZXJzaW9uID0gcmVxdWVzdC52ZXJzaW9uO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGBEZXBlbmRlbmN5IFwiJHtyZXF1ZXN0Lm5hbWV9XCIgdmVyc2lvbiBjb25mbGljdDogZXhpc3RpbmcgXCIke2V4aXN0aW5nLnZlcnNpb259XCIgYCArXG4gICAgICAgICAgYGRvZXMgbm90IGludGVyc2VjdCB3aXRoIHJlcXVlc3RlZCBcIiR7cmVxdWVzdC52ZXJzaW9ufVwiYCxcbiAgICAgICk7XG4gICAgfVxuXG4gICAgY29uc3Qgc3BlYyA9IGVmZmVjdGl2ZVZlcnNpb25cbiAgICAgID8gYCR7cmVxdWVzdC5uYW1lfUAke2VmZmVjdGl2ZVZlcnNpb259YFxuICAgICAgOiByZXF1ZXN0Lm5hbWU7XG4gICAgcmV0dXJuIHRoaXMuYWRkRGVwZW5kZW5jeShzcGVjLCByZXF1ZXN0ZWRUeXBlLCB7XG4gICAgICAuLi5leGlzdGluZy5tZXRhZGF0YSxcbiAgICAgIC4uLnJlcXVlc3QubWV0YWRhdGEsXG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogRmluZHMgdGhlIHR5cGUgb2YgYW4gZXhpc3RpbmcgaW5zdGFsbGFibGUgZGVwZW5kZW5jeSBieSBuYW1lLlxuICAgKiBFeGNsdWRlcyBQRUVSLCBPVkVSUklERSwgYW5kIE9QVElPTkFMIHR5cGVzLlxuICAgKiBSZXR1cm5zIHVuZGVmaW5lZCBpZiBubyBkZXBlbmRlbmN5IHdpdGggdGhpcyBuYW1lIGV4aXN0cy5cbiAgICovXG4gIHByaXZhdGUgZmluZEV4aXN0aW5nSW5zdGFsbGFibGVUeXBlKFxuICAgIG5hbWU6IHN0cmluZyxcbiAgKTogRGVwZW5kZW5jeVR5cGUgfCB1bmRlZmluZWQge1xuICAgIHJldHVybiB0aGlzLl9kZXBzLmZpbmQoXG4gICAgICAoZCkgPT5cbiAgICAgICAgZC5uYW1lID09PSBuYW1lICYmXG4gICAgICAgIGQudHlwZSAhPT0gRGVwZW5kZW5jeVR5cGUuUEVFUiAmJlxuICAgICAgICBkLnR5cGUgIT09IERlcGVuZGVuY3lUeXBlLk9WRVJSSURFICYmXG4gICAgICAgIGQudHlwZSAhPT0gRGVwZW5kZW5jeVR5cGUuT1BUSU9OQUwsXG4gICAgKT8udHlwZTtcbiAgfVxuXG4gIHByaXZhdGUgdHJ5R2V0RGVwZW5kZW5jeUluZGV4KG5hbWU6IHN0cmluZywgdHlwZT86IERlcGVuZGVuY3lUeXBlKTogbnVtYmVyIHtcbiAgICBjb25zdCBkZXBzID0gdGhpcy5fZGVwcy5maWx0ZXIoKGQpID0+IGQubmFtZSA9PT0gbmFtZSk7XG4gICAgaWYgKGRlcHMubGVuZ3RoID09PSAwKSB7XG4gICAgICByZXR1cm4gLTE7IC8vIG5vdCBmb3VuZFxuICAgIH1cblxuICAgIGlmICghdHlwZSkge1xuICAgICAgaWYgKGRlcHMubGVuZ3RoID4gMSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgYFwiJHtuYW1lfVwiIGlzIGRlZmluZWQgZm9yIG11bHRpcGxlIGRlcGVuZGVuY3kgdHlwZXM6ICR7ZGVwc1xuICAgICAgICAgICAgLm1hcCgoZCkgPT4gZC50eXBlKVxuICAgICAgICAgICAgLmpvaW4oXCIsXCIpfS4gUGxlYXNlIHNwZWNpZnkgZGVwZW5kZW5jeSB0eXBlYCxcbiAgICAgICAgKTtcbiAgICAgIH1cblxuICAgICAgdHlwZSA9IGRlcHNbMF0udHlwZTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5fZGVwcy5maW5kSW5kZXgoXG4gICAgICAoZGVwKSA9PiBkZXAubmFtZSA9PT0gbmFtZSAmJiBkZXAudHlwZSA9PT0gdHlwZSxcbiAgICApO1xuICB9XG5cbiAgcHJpdmF0ZSB0b0pzb24oKTogRGVwc01hbmlmZXN0IHwgdW5kZWZpbmVkIHtcbiAgICBpZiAodGhpcy5fZGVwcy5sZW5ndGggPT09IDApIHtcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuICAgIHJldHVybiB7XG4gICAgICBkZXBlbmRlbmNpZXM6IHRoaXMuX2RlcHMuc29ydChjb21wYXJlRGVwcykubWFwKG5vcm1hbGl6ZURlcCksXG4gICAgfTtcbiAgfVxufVxuXG5mdW5jdGlvbiBub3JtYWxpemVEZXAoZDogRGVwZW5kZW5jeSkge1xuICBjb25zdCBvYmo6IGFueSA9IHt9O1xuICBmb3IgKGNvbnN0IFtrLCB2XSBvZiBPYmplY3QuZW50cmllcyhkKSkge1xuICAgIGlmICh2ID09IHVuZGVmaW5lZCkge1xuICAgICAgY29udGludWU7XG4gICAgfVxuICAgIGlmICh0eXBlb2YgdiA9PT0gXCJvYmplY3RcIiAmJiBPYmplY3Qua2V5cyh2KS5sZW5ndGggPT09IDApIHtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cbiAgICBpZiAoQXJyYXkuaXNBcnJheSh2KSAmJiB2Lmxlbmd0aCA9PT0gMCkge1xuICAgICAgY29udGludWU7XG4gICAgfVxuICAgIG9ialtrXSA9IHY7XG4gIH1cblxuICByZXR1cm4gb2JqO1xufVxuXG5mdW5jdGlvbiBjb21wYXJlRGVwcyhkMTogRGVwZW5kZW5jeSwgZDI6IERlcGVuZGVuY3kpIHtcbiAgcmV0dXJuIHNwZWNPZihkMSkubG9jYWxlQ29tcGFyZShzcGVjT2YoZDIpKTtcblxuICBmdW5jdGlvbiBzcGVjT2YoZGVwOiBEZXBlbmRlbmN5KSB7XG4gICAgbGV0IHNwZWMgPSBkZXAudHlwZSArIFwiOlwiICsgZGVwLm5hbWU7XG4gICAgaWYgKGRlcC52ZXJzaW9uKSB7XG4gICAgICBzcGVjICs9IFwiQFwiICsgZGVwLnZlcnNpb247XG4gICAgfVxuICAgIHJldHVybiBzcGVjO1xuICB9XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgRGVwc01hbmlmZXN0IHtcbiAgLyoqXG4gICAqIEFsbCBkZXBlbmRlbmNpZXMgb2YgdGhpcyBtb2R1bGUuXG4gICAqL1xuICByZWFkb25seSBkZXBlbmRlbmNpZXM6IERlcGVuZGVuY3lbXTtcbn1cblxuLyoqXG4gKiBDb29yZGluYXRlcyBvZiB0aGUgZGVwZW5kZW5jeSAobmFtZSBhbmQgdmVyc2lvbikuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgRGVwZW5kZW5jeUNvb3JkaW5hdGVzIHtcbiAgLyoqXG4gICAqIFRoZSBwYWNrYWdlIG1hbmFnZXIgbmFtZSBvZiB0aGUgZGVwZW5kZW5jeSAoZS5nLiBgbGVmdHBhZGAgZm9yIG5wbSkuXG4gICAqXG4gICAqIE5PVEU6IEZvciBwYWNrYWdlIG1hbmFnZXJzIHRoYXQgdXNlIGNvbXBsZXggY29vcmRpbmF0ZXMgKGxpa2UgTWF2ZW4pLCB3ZVxuICAgKiB3aWxsIGNvZGlmeSBpdCBpbnRvIGEgc3RyaW5nIHNvbWVob3cuXG4gICAqL1xuICByZWFkb25seSBuYW1lOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFNlbWFudGljIHZlcnNpb24gdmVyc2lvbiByZXF1aXJlbWVudC5cbiAgICpcbiAgICogQGRlZmF1bHQgLSByZXF1aXJlbWVudCBpcyBtYW5hZ2VkIGJ5IHRoZSBwYWNrYWdlIG1hbmFnZXIgKGUuZy4gbnBtL3lhcm4pLlxuICAgKi9cbiAgcmVhZG9ubHkgdmVyc2lvbj86IHN0cmluZztcbn1cblxuLyoqXG4gKiBSZXByZXNlbnRzIGEgcHJvamVjdCBkZXBlbmRlbmN5LlxuICovXG5leHBvcnQgaW50ZXJmYWNlIERlcGVuZGVuY3kgZXh0ZW5kcyBEZXBlbmRlbmN5Q29vcmRpbmF0ZXMge1xuICAvKipcbiAgICogV2hpY2ggdHlwZSBvZiBkZXBlbmRlbmN5IHRoaXMgaXMgKHJ1bnRpbWUsIGJ1aWxkLXRpbWUsIGV0YykuXG4gICAqL1xuICByZWFkb25seSB0eXBlOiBEZXBlbmRlbmN5VHlwZTtcblxuICAvKipcbiAgICogQWRkaXRpb25hbCBKU09OIG1ldGFkYXRhIGFzc29jaWF0ZWQgd2l0aCB0aGUgZGVwZW5kZW5jeSAocGFja2FnZSBtYW5hZ2VyXG4gICAqIHNwZWNpZmljKS5cbiAgICogQGRlZmF1bHQge31cbiAgICovXG4gIHJlYWRvbmx5IG1ldGFkYXRhPzogeyBba2V5OiBzdHJpbmddOiBhbnkgfTtcbn1cblxuLyoqXG4gKiBUeXBlIG9mIGRlcGVuZGVuY3kuXG4gKi9cbmV4cG9ydCBlbnVtIERlcGVuZGVuY3lUeXBlIHtcbiAgLyoqXG4gICAqIFRoZSBkZXBlbmRlbmN5IGlzIHJlcXVpcmVkIGZvciB0aGUgcHJvZ3JhbS9saWJyYXJ5IGR1cmluZyBydW50aW1lLlxuICAgKi9cbiAgUlVOVElNRSA9IFwicnVudGltZVwiLFxuXG4gIC8qKlxuICAgKiBUaGUgZGVwZW5kZW5jeSBpcyByZXF1aXJlZCBhdCBydW50aW1lIGJ1dCBleHBlY3RlZCB0byBiZSBpbnN0YWxsZWQgYnkgdGhlXG4gICAqIGNvbnN1bWVyLlxuICAgKi9cbiAgUEVFUiA9IFwicGVlclwiLFxuXG4gIC8qKlxuICAgKiBUaGUgZGVwZW5kZW5jeSBpcyBidW5kbGVkIGFuZCBzaGlwcGVkIHdpdGggdGhlIG1vZHVsZSwgc28gY29uc3VtZXJzIGFyZSBub3RcbiAgICogcmVxdWlyZWQgdG8gaW5zdGFsbCBpdC5cbiAgICovXG4gIEJVTkRMRUQgPSBcImJ1bmRsZWRcIixcblxuICAvKipcbiAgICogVGhlIGRlcGVuZGVuY3kgaXMgcmVxdWlyZWQgdG8gcnVuIHRoZSBgYnVpbGRgIHRhc2suXG4gICAqL1xuICBCVUlMRCA9IFwiYnVpbGRcIixcblxuICAvKipcbiAgICogVGhlIGRlcGVuZGVuY3kgaXMgcmVxdWlyZWQgdG8gcnVuIHRoZSBgdGVzdGAgdGFzay5cbiAgICovXG4gIFRFU1QgPSBcInRlc3RcIixcblxuICAvKipcbiAgICogVGhlIGRlcGVuZGVuY3kgaXMgcmVxdWlyZWQgZm9yIGRldmVsb3BtZW50IChlLmcuIElERSBwbHVnaW5zKS5cbiAgICovXG4gIERFVkVOViA9IFwiZGV2ZW52XCIsXG5cbiAgLyoqXG4gICAqIFRyYW5zaWVudCBkZXBlbmRlbmN5IHRoYXQgbmVlZHMgdG8gYmUgb3ZlcndyaXR0ZW4uXG4gICAqXG4gICAqIEF2YWlsYWJsZSBmb3IgTm9kZSBwYWNrYWdlc1xuICAgKi9cbiAgT1ZFUlJJREUgPSBcIm92ZXJyaWRlXCIsXG5cbiAgLyoqXG4gICAqIEFuIG9wdGlvbmFsIGRlcGVuZGVuY3kgdGhhdCBtYXkgYmUgdXNlZCBhdCBydW50aW1lIGlmIGF2YWlsYWJsZSwgYnV0IGlzIG5vdCByZXF1aXJlZC5cbiAgICogSXQgaXMgZXhwZWN0ZWQgdG8gYmUgaW5zdGFsbGVkIGJ5IHRoZSBjb25zdW1lci5cbiAgICovXG4gIE9QVElPTkFMID0gXCJvcHRpb25hbFwiLFxufVxuXG4vKipcbiAqIEEgcmVxdWVzdCBmb3IgYSBkZXBlbmRlbmN5LiBVbmxpa2UgYWRkaW5nIGEgZGVwZW5kZW5jeSBkaXJlY3RseSxcbiAqIHJlcXVlc3RpbmcgYSBkZXBlbmRlbmN5IHdpbGwgaW50ZWxsaWdlbnRseSBtZXJnZSB3aXRoIGV4aXN0aW5nXG4gKiBkZXBlbmRlbmNpZXMgb2YgdGhlIHNhbWUgbmFtZSBhbmQgdHlwZS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBEZXBlbmRlbmN5UmVxdWVzdCB7XG4gIC8qKlxuICAgKiBUaGUgcGFja2FnZSBuYW1lLlxuICAgKi9cbiAgcmVhZG9ubHkgbmFtZTogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBTZW1hbnRpYyB2ZXJzaW9uIGNvbnN0cmFpbnQuXG4gICAqIEBkZWZhdWx0IC0gYW55IHZlcnNpb25cbiAgICovXG4gIHJlYWRvbmx5IHZlcnNpb24/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIERlcGVuZGVuY3kgdHlwZS4gSWYgbm90IHByb3ZpZGVkLCBhbiBleGlzdGluZyBkZXBlbmRlbmN5IG9mIGFueSB0eXBlXG4gICAqIHdpbGwgc2F0aXNmeSB0aGUgcmVxdWVzdC4gSWYgbm9uZSBleGlzdHMsIGl0IGlzIGFkZGVkIGFzIEJVSUxELlxuICAgKiBAZGVmYXVsdCAtIGFueSBleGlzdGluZyB0eXBlLCBvciBEZXBlbmRlbmN5VHlwZS5CVUlMRFxuICAgKi9cbiAgcmVhZG9ubHkgdHlwZT86IERlcGVuZGVuY3lUeXBlO1xuXG4gIC8qKlxuICAgKiBBZGRpdGlvbmFsIG1ldGFkYXRhLlxuICAgKiBAZGVmYXVsdCAtIG5vbmVcbiAgICovXG4gIHJlYWRvbmx5IG1ldGFkYXRhPzogUmVjb3JkPHN0cmluZywgYW55Pjtcbn1cbiJdfQ==