projen
Version:
CDK for software projects
324 lines • 39.2 kB
JavaScript
;
var _a;
Object.defineProperty(exports, "__esModule", { value: true });
exports.DependencyType = exports.Dependencies = void 0;
const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
const path = require("path");
const chalk_1 = require("chalk");
const semver = 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 {
/**
* 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.substr(1);
}
const [module, ...version] = spec.split("@");
const name = scope ? `@${module}` : module;
if (version.length == 0) {
return { name };
}
else {
return { name, version: version?.join("@") };
}
}
/**
* Adds a dependencies component to the project.
* @param project The parent project
*/
constructor(project) {
super(project);
this._deps = new Array();
// 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;
_a = JSII_RTTI_SYMBOL_1;
Dependencies[_a] = { fqn: "projen.Dependencies", version: "0.99.51" };
/**
* The project-relative path of the deps manifest file.
*/
Dependencies.MANIFEST_FILE = path.posix.join(common_1.PROJEN_DIR, "deps.json");
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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVwZW5kZW5jaWVzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL2RlcGVuZGVuY2llcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUFBLDZCQUE2QjtBQUM3QixpQ0FBa0M7QUFDbEMsaUNBQWlDO0FBQ2pDLHFDQUFzQztBQUN0QywyQ0FBd0M7QUFDeEMsaUNBQWtDO0FBR2xDOzs7Ozs7OztHQVFHO0FBQ0gsTUFBYSxZQUFhLFNBQVEscUJBQVM7SUFTekM7Ozs7O09BS0c7SUFDSSxNQUFNLENBQUMsZUFBZSxDQUFDLElBQVk7UUFDeEMsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUNuQyxJQUFJLEtBQUssRUFBRSxDQUFDO1lBQ1YsSUFBSSxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDeEIsQ0FBQztRQUVELE1BQU0sQ0FBQyxNQUFNLEVBQUUsR0FBRyxPQUFPLENBQUMsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQzdDLE1BQU0sSUFBSSxHQUFHLEtBQUssQ0FBQyxDQUFDLENBQUMsSUFBSSxNQUFNLEVBQUUsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDO1FBQzNDLElBQUksT0FBTyxDQUFDLE1BQU0sSUFBSSxDQUFDLEVBQUUsQ0FBQztZQUN4QixPQUFPLEVBQUUsSUFBSSxFQUFFLENBQUM7UUFDbEIsQ0FBQzthQUFNLENBQUM7WUFDTixPQUFPLEVBQUUsSUFBSSxFQUFFLE9BQU8sRUFBRSxPQUFPLEVBQUUsSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUM7UUFDL0MsQ0FBQztJQUNILENBQUM7SUFJRDs7O09BR0c7SUFDSCxZQUFZLE9BQWdCO1FBQzFCLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQztRQVBBLFVBQUssR0FBRyxJQUFJLEtBQUssRUFBYyxDQUFDO1FBUy9DLDRFQUE0RTtRQUM1RSxzRUFB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LENBQUMsQ0FBQztJQUU1QyxTQUFTLE1BQU0sQ0FBQyxHQUFlO1FBQzdCLElBQUksSUFBSSxHQUFHLEdBQUcsQ0FBQyxJQUFJLEdBQUcsR0FBRyxHQUFHLEdBQUcsQ0FBQyxJQUFJLENBQUM7UUFDckMsSUFBSSxHQUFHLENBQUMsT0FBTyxFQUFFLENBQUM7WUFDaEIsSUFBSSxJQUFJLEdBQUcsR0FBRyxHQUFHLENBQUMsT0FBTyxDQUFDO1FBQzVCLENBQUM7UUFDRCxPQUFPLElBQUksQ0FBQztJQUNkLENBQUM7QUFDSCxDQUFDO0FBOENEOztHQUVHO0FBQ0gsSUFBWSxjQTZDWDtBQTdDRCxXQUFZLGNBQWM7SUFDeEI7O09BRUc7SUFDSCxxQ0FBbUIsQ0FBQTtJQUVuQjs7O09BR0c7SUFDSCwrQkFBYSxDQUFBO0lBRWI7OztPQUdHO0lBQ0gscUNBQW1CLENBQUE7SUFFbkI7O09BRUc7SUFDSCxpQ0FBZSxDQUFBO0lBRWY7O09BRUc7SUFDSCwrQkFBYSxDQUFBO0lBRWI7O09BRUc7SUFDSCxtQ0FBaUIsQ0FBQTtJQUVqQjs7OztPQUlHO0lBQ0gsdUNBQXFCLENBQUE7SUFFckI7OztPQUdHO0lBQ0gsdUNBQXFCLENBQUE7QUFDdkIsQ0FBQyxFQTdDVyxjQUFjLDhCQUFkLGNBQWMsUUE2Q3pCIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICogYXMgcGF0aCBmcm9tIFwicGF0aFwiO1xuaW1wb3J0IHsgdW5kZXJsaW5lIH0gZnJvbSBcImNoYWxrXCI7XG5pbXBvcnQgKiBhcyBzZW12ZXIgZnJvbSBcInNlbXZlclwiO1xuaW1wb3J0IHsgUFJPSkVOX0RJUiB9IGZyb20gXCIuL2NvbW1vblwiO1xuaW1wb3J0IHsgQ29tcG9uZW50IH0gZnJvbSBcIi4vY29tcG9uZW50XCI7XG5pbXBvcnQgeyBKc29uRmlsZSB9IGZyb20gXCIuL2pzb25cIjtcbmltcG9ydCB0eXBlIHsgUHJvamVjdCB9IGZyb20gXCIuL3Byb2plY3RcIjtcblxuLyoqXG4gKiBUaGUgYERlcGVuZGVuY2llc2AgY29tcG9uZW50IGlzIHJlc3BvbnNpYmxlIHRvIHRyYWNrIHRoZSBsaXN0IG9mIGRlcGVuZGVuY2llc1xuICogYSBwcm9qZWN0IGhhcywgYW5kIHRoZW4gdXNlZCBieSBwcm9qZWN0IHR5cGVzIGFzIHRoZSBtb2RlbCBmb3IgcmVuZGVyaW5nXG4gKiBwcm9qZWN0LXNwZWNpZmljIGRlcGVuZGVuY3kgbWFuaWZlc3RzIHN1Y2ggYXMgdGhlIGRlcGVuZGVuY2llcyBzZWN0aW9uXG4gKiBgcGFja2FnZS5qc29uYCBmaWxlcy5cbiAqXG4gKiBUbyBhZGQgYSBkZXBlbmRlbmN5IHlvdSBjYW4gdXNlIGEgcHJvamVjdC10eXBlIHNwZWNpZmljIEFQSSBzdWNoIGFzXG4gKiBgbm9kZVByb2plY3QuYWRkRGVwcygpYCBvciB1c2UgdGhlIGdlbmVyaWMgQVBJIG9mIGBwcm9qZWN0LmRlcHNgOlxuICovXG5leHBvcnQgY2xhc3MgRGVwZW5kZW5jaWVzIGV4dGVuZHMgQ29tcG9uZW50IHtcbiAgLyoqXG4gICAqIFRoZSBwcm9qZWN0LXJlbGF0aXZlIHBhdGggb2YgdGhlIGRlcHMgbWFuaWZlc3QgZmlsZS5cbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgcmVhZG9ubHkgTUFOSUZFU1RfRklMRSA9IHBhdGgucG9zaXguam9pbihcbiAgICBQUk9KRU5fRElSLFxuICAgIFwiZGVwcy5qc29uXCIsXG4gICk7XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIGNvb3JkaW5hdGVzIG9mIGEgZGVwZW5kZW5jeSBzcGVjLlxuICAgKlxuICAgKiBHaXZlbiBgZm9vQF4zLjQuMGAgcmV0dXJucyBgeyBuYW1lOiBcImZvb1wiLCB2ZXJzaW9uOiBcIl4zLjQuMFwiIH1gLlxuICAgKiBHaXZlbiBgYmFyQG5wbTpAYmFyL2xlZ2FjeWAgcmV0dXJucyBgeyBuYW1lOiBcImJhclwiLCB2ZXJzaW9uOiBcIm5wbTpAYmFyL2xlZ2FjeVwiIH1gLlxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBwYXJzZURlcGVuZGVuY3koc3BlYzogc3RyaW5nKTogRGVwZW5kZW5jeUNvb3JkaW5hdGVzIHtcbiAgICBjb25zdCBzY29wZSA9IHNwZWMuc3RhcnRzV2l0aChcIkBcIik7XG4gICAgaWYgKHNjb3BlKSB7XG4gICAgICBzcGVjID0gc3BlYy5zdWJzdHIoMSk7XG4gICAgfVxuXG4gICAgY29uc3QgW21vZHVsZSwgLi4udmVyc2lvbl0gPSBzcGVjLnNwbGl0KFwiQFwiKTtcbiAgICBjb25zdCBuYW1lID0gc2NvcGUgPyBgQCR7bW9kdWxlfWAgOiBtb2R1bGU7XG4gICAgaWYgKHZlcnNpb24ubGVuZ3RoID09IDApIHtcbiAgICAgIHJldHVybiB7IG5hbWUgfTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHsgbmFtZSwgdmVyc2lvbjogdmVyc2lvbj8uam9pbihcIkBcIikgfTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIHJlYWRvbmx5IF9kZXBzID0gbmV3IEFycmF5PERlcGVuZGVuY3k+KCk7XG5cbiAgLyoqXG4gICAqIEFkZHMgYSBkZXBlbmRlbmNpZXMgY29tcG9uZW50IHRvIHRoZSBwcm9qZWN0LlxuICAgKiBAcGFyYW0gcHJvamVjdCBUaGUgcGFyZW50IHByb2plY3RcbiAgICovXG4gIGNvbnN0cnVjdG9yKHByb2plY3Q6IFByb2plY3QpIHtcbiAgICBzdXBlcihwcm9qZWN0KTtcblxuICAgIC8vIHRoaXMgaXMgbm90IHJlYWxseSByZXF1aXJlZCBhdCB0aGUgbW9tZW50LCBidXQgYWN0dWFsbHkgcXVpdGUgdXNlZnVsIGFzIGFcbiAgICAvLyBjaGVja2VkLWluIHNvdXJjZSBvZiB0cnV0aCBmb3IgZGVwZW5kZW5jaWVzIGFuZCB3aWxsIHBvdGVudGlhbGx5IGJlXG4gICAgLy8gdmFsdWFibGUgaW4gdGhlIGZ1dHVyZSBmb3IgQ0xJIHRvb2xzLlxuICAgIGlmICghcHJvamVjdC5lamVjdGVkKSB7XG4gICAgICBuZXcgSnNvbkZpbGUocHJvamVjdCwgRGVwZW5kZW5jaWVzLk1BTklGRVNUX0ZJTEUsIHtcbiAgICAgICAgb21pdEVtcHR5OiB0cnVlLFxuICAgICAgICBvYmo6ICgpID0+IHRoaXMudG9Kc29uKCksXG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQSBjb3B5IG9mIGFsbCBkZXBlbmRlbmNpZXMgcmVjb3JkZWQgZm9yIHRoaXMgcHJvamVjdC5cbiAgICpcbiAgICogVGhlIGxpc3QgaXMgc29ydGVkIGJ5IHR5cGUtPm5hbWUtPnZlcnNpb25cbiAgICovXG4gIHB1YmxpYyBnZXQgYWxsKCk6IERlcGVuZGVuY3lbXSB7XG4gICAgcmV0dXJuIFsuLi50aGlzLl9kZXBzXS5zb3J0KGNvbXBhcmVEZXBzKS5tYXAobm9ybWFsaXplRGVwKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGEgZGVwZW5kZW5jeSBieSBuYW1lLlxuICAgKlxuICAgKiBGYWlscyBpZiB0aGVyZSBpcyBubyBkZXBlbmRlbmN5IGRlZmluZWQgYnkgdGhhdCBuYW1lIG9yIGlmIGB0eXBlYCBpcyBub3RcbiAgICogcHJvdmlkZWQgYW5kIHRoZXJlIGlzIG1vcmUgdGhlbiBvbmUgZGVwZW5kZW5jeSB0eXBlIGZvciB0aGlzIGRlcGVuZGVuY3kuXG4gICAqXG4gICAqIEBwYXJhbSBuYW1lIFRoZSBuYW1lIG9mIHRoZSBkZXBlbmRlbmN5XG4gICAqIEBwYXJhbSB0eXBlIFRoZSBkZXBlbmRlbmN5IHR5cGUuIElmIHRoaXMgZGVwZW5kZW5jeSBpcyBkZWZpbmVkIG9ubHkgZm9yIGFcbiAgICogc2luZ2xlIHR5cGUsIHRoaXMgYXJndW1lbnQgY2FuIGJlIG9taXR0ZWQuXG4gICAqXG4gICAqIEByZXR1cm5zIGEgY29weSAoY2Fubm90IGJlIG1vZGlmaWVkKVxuICAgKi9cbiAgcHVibGljIGdldERlcGVuZGVuY3kobmFtZTogc3RyaW5nLCB0eXBlPzogRGVwZW5kZW5jeVR5cGUpOiBEZXBlbmRlbmN5IHtcbiAgICBjb25zdCBkZXAgPSB0aGlzLnRyeUdldERlcGVuZGVuY3kobmFtZSwgdHlwZSk7XG4gICAgaWYgKCFkZXApIHtcbiAgICAgIGNvbnN0IG1zZyA9IHR5cGVcbiAgICAgICAgPyBgdGhlcmUgaXMgbm8gJHt0eXBlfSBkZXBlbmRlbmN5IGRlZmluZWQgb24gXCIke25hbWV9XCJgXG4gICAgICAgIDogYHRoZXJlIGlzIG5vIGRlcGVuZGVuY3kgZGVmaW5lZCBvbiBcIiR7bmFtZX1cImA7XG5cbiAgICAgIHRocm93IG5ldyBFcnJvcihtc2cpO1xuICAgIH1cblxuICAgIHJldHVybiBkZXA7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyBhIGRlcGVuZGVuY3kgYnkgbmFtZS5cbiAgICpcbiAgICogUmV0dXJucyBgdW5kZWZpbmVkYCBpZiB0aGVyZSBpcyBubyBkZXBlbmRlbmN5IGRlZmluZWQgYnkgdGhhdCBuYW1lIG9yIGlmXG4gICAqIGB0eXBlYCBpcyBub3QgcHJvdmlkZWQgYW5kIHRoZXJlIGlzIG1vcmUgdGhlbiBvbmUgZGVwZW5kZW5jeSB0eXBlIGZvciB0aGlzXG4gICAqIGRlcGVuZGVuY3kuXG4gICAqXG4gICAqIEBwYXJhbSBuYW1lIFRoZSBuYW1lIG9mIHRoZSBkZXBlbmRlbmN5XG4gICAqIEBwYXJhbSB0eXBlIFRoZSBkZXBlbmRlbmN5IHR5cGUuIElmIHRoaXMgZGVwZW5kZW5jeSBpcyBkZWZpbmVkIG9ubHkgZm9yIGFcbiAgICogc2luZ2xlIHR5cGUsIHRoaXMgYXJndW1lbnQgY2FuIGJlIG9taXR0ZWQuXG4gICAqXG4gICAqIEByZXR1cm5zIGEgY29weSAoY2Fubm90IGJlIG1vZGlmaWVkKSBvciB1bmRlZmluZWQgaWYgdGhlcmUgaXMgbm8gbWF0Y2hcbiAgICovXG4gIHB1YmxpYyB0cnlHZXREZXBlbmRlbmN5KFxuICAgIG5hbWU6IHN0cmluZyxcbiAgICB0eXBlPzogRGVwZW5kZW5jeVR5cGUsXG4gICk6IERlcGVuZGVuY3kgfCB1bmRlZmluZWQge1xuICAgIGNvbnN0IGlkeCA9IHRoaXMudHJ5R2V0RGVwZW5kZW5jeUluZGV4KG5hbWUsIHR5cGUpO1xuICAgIGlmIChpZHggPT09IC0xKSB7XG4gICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICAuLi5ub3JtYWxpemVEZXAodGhpcy5fZGVwc1tpZHhdKSxcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIEFkZHMgYSBkZXBlbmRlbmN5IHRvIHRoaXMgcHJvamVjdC5cbiAgICogQHBhcmFtIHNwZWMgVGhlIGRlcGVuZGVuY3kgc3BlYyBpbiB0aGUgZm9ybWF0IGBNT0RVTEVbQFZFUlNJT05dYCB3aGVyZVxuICAgKiBgTU9EVUxFYCBpcyB0aGUgcGFja2FnZS1tYW5hZ2VyLXNwZWNpZmljIG1vZHVsZSBuYW1lIGFuZCBgVkVSU0lPTmAgaXMgYW5cbiAgICogb3B0aW9uYWwgc2VtYW50aWMgdmVyc2lvbiByZXF1aXJlbWVudCAoZS5nLiBgXjMuNC4wYCkuXG4gICAqIEBwYXJhbSB0eXBlIFRoZSB0eXBlIG9mIHRoZSBkZXBlbmRlbmN5LlxuICAgKi9cbiAgcHVibGljIGFkZERlcGVuZGVuY3koXG4gICAgc3BlYzogc3RyaW5nLFxuICAgIHR5cGU6IERlcGVuZGVuY3lUeXBlLFxuICAgIG1ldGFkYXRhOiB7IFtrZXk6IHN0cmluZ106IGFueSB9ID0ge30sXG4gICk6IERlcGVuZGVuY3kge1xuICAgIHRoaXMucHJvamVjdC5sb2dnZXIudmVyYm9zZShcbiAgICAgIGAke3VuZGVybGluZShcIkRlcGVuZGVuY3lcIil9IHwgQWRkaW5nICR7dHlwZX0tZGVwIFxcYCR7c3BlY31cXGBgLFxuICAgICk7XG5cbiAgICBjb25zdCBkZXA6IERlcGVuZGVuY3kgPSB7XG4gICAgICAuLi5EZXBlbmRlbmNpZXMucGFyc2VEZXBlbmRlbmN5KHNwZWMpLFxuICAgICAgdHlwZSxcbiAgICAgIG1ldGFkYXRhLFxuICAgIH07XG5cbiAgICBjb25zdCBleGlzdGluZ0RlcEluZGV4ID0gdGhpcy50cnlHZXREZXBlbmRlbmN5SW5kZXgoZGVwLm5hbWUsIHR5cGUpO1xuXG4gICAgaWYgKGV4aXN0aW5nRGVwSW5kZXggIT09IC0xKSB7XG4gICAgICB0aGlzLnByb2plY3QubG9nZ2VyLmRlYnVnKFxuICAgICAgICBgJHt1bmRlcmxpbmUoXCJEZXBlbmRlbmN5XCIpfSB8IFVwZGF0aW5nIGV4aXN0aW5nICR7ZGVwLnR5cGV9LWRlcCBcXGAke2RlcC5uYW1lfVxcYCB3aXRoIG1vcmUgc3BlY2lmaWMgcmVxdWVzdC5gLFxuICAgICAgKTtcbiAgICAgIHRoaXMuX2RlcHNbZXhpc3RpbmdEZXBJbmRleF0gPSBkZXA7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuX2RlcHMucHVzaChkZXApO1xuICAgIH1cblxuICAgIHJldHVybiBkZXA7XG4gIH1cblxuICAvKipcbiAgICogUmVtb3ZlcyBhIGRlcGVuZGVuY3kuXG4gICAqIEBwYXJhbSBuYW1lIFRoZSBuYW1lIG9mIHRoZSBtb2R1bGUgdG8gcmVtb3ZlICh3aXRob3V0IHRoZSB2ZXJzaW9uKVxuICAgKiBAcGFyYW0gdHlwZSBUaGUgZGVwZW5kZW5jeSB0eXBlLiBUaGlzIGlzIG9ubHkgcmVxdWlyZWQgaWYgdGhlcmUgdGhlXG4gICAqIGRlcGVuZGVuY3kgaXMgZGVmaW5lZCBmb3IgbXVsdGlwbGUgdHlwZXMuXG4gICAqL1xuICBwdWJsaWMgcmVtb3ZlRGVwZW5kZW5jeShuYW1lOiBzdHJpbmcsIHR5cGU/OiBEZXBlbmRlbmN5VHlwZSkge1xuICAgIGNvbnN0IHJlbW92ZUluZGV4ID0gdGhpcy50cnlHZXREZXBlbmRlbmN5SW5kZXgobmFtZSwgdHlwZSk7XG4gICAgaWYgKHJlbW92ZUluZGV4ID09PSAtMSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHRoaXMuX2RlcHMuc3BsaWNlKHJlbW92ZUluZGV4LCAxKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDaGVja3MgaWYgYW4gZXhpc3RpbmcgZGVwZW5kZW5jeSBzYXRpc2ZpZXMgYSBkZXBlbmRlbmN5IHJlcXVpcmVtZW50LlxuICAgKiBAcGFyYW0gbmFtZSBUaGUgbmFtZSBvZiB0aGUgZGVwZW5kZW5jeSB0byBjaGVjayAod2l0aG91dCB0aGUgdmVyc2lvbikuXG4gICAqIEBwYXJhbSB0eXBlIFRoZSBkZXBlbmRlbmN5IHR5cGUuXG4gICAqIEBwYXJhbSBleHBlY3RlZFJhbmdlIFRoZSB2ZXJzaW9uIGNvbnN0cmFpbnQgdG8gY2hlY2sgKGUuZy4gYF4zLjQuMGApLlxuICAgKiBUaGUgY29uc3RyYWludCBvZiB0aGUgZGVwZW5kZW5jeSBtdXN0IGJlIGEgc3Vic2V0IG9mIHRoZSBleHBlY3RlZCByYW5nZSB0byBzYXRpc2Z5IHRoZSByZXF1aXJlbWVudHMuXG4gICAqIEByZXR1cm5zIGB0cnVlYCBpZiB0aGUgZGVwZW5kZW5jeSBleGlzdHMgYW5kIGl0cyB2ZXJzaW9uIHNhdGlzZmllcyB0aGUgcHJvdmlkZWQgY29uc3RyYWludC4gYGZhbHNlYCBvdGhlcndpc2UuXG4gICAqIE5vdGFibHkgcmV0dXJucyBgZmFsc2VgIGlmIGEgZGVwZW5kZW5jeSBleGlzdHMsIGJ1dCBoYXMgbm8gdmVyc2lvbi5cbiAgICovXG4gIHB1YmxpYyBpc0RlcGVuZGVuY3lTYXRpc2ZpZWQoXG4gICAgbmFtZTogc3RyaW5nLFxuICAgIHR5cGU6IERlcGVuZGVuY3lUeXBlLFxuICAgIGV4cGVjdGVkUmFuZ2U6IHN0cmluZyxcbiAgKTogYm9vbGVhbiB7XG4gICAgY29uc3QgZGVwID0gdGhpcy50cnlHZXREZXBlbmRlbmN5KG5hbWUsIHR5cGUpO1xuICAgIHJldHVybiBkZXA/LnZlcnNpb24gIT0gbnVsbCAmJiBzZW12ZXIuc3Vic2V0KGRlcC52ZXJzaW9uLCBleHBlY3RlZFJhbmdlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXF1ZXN0IGEgZGVwZW5kZW5jeS4gVW5saWtlIGBhZGREZXBlbmRlbmN5YCwgdGhpcyBtZXJnZXMgaW50ZWxsaWdlbnRseVxuICAgKiB3aXRoIGV4aXN0aW5nIGRlcGVuZGVuY2llcyBvZiB0aGUgc2FtZSBuYW1lIGFuZCB0eXBlOlxuICAgKlxuICAgKiAtIElmIHRoZSBkZXAgZXhpc3RzIHdpdGggYSB2ZXJzaW9uIHRoYXQgYWxyZWFkeSBzYXRpc2ZpZXMgdGhlIHJlcXVlc3QsXG4gICAqICAgdGhlIHZlcnNpb24gaXMgbm90IGNoYW5nZWQuXG4gICAqIC0gSWYgdGhlIGRlcCBkb2Vzbid0IGV4aXN0LCBpdCBpcyBhZGRlZCB3aXRoIHRoZSByZXF1ZXN0ZWQgdHlwZS92ZXJzaW9uLlxuICAgKiAtIElmIHRoZSBkZXAgZXhpc3RzIGJ1dCB0aGUgdmVyc2lvbnMgZG9uJ3QgaW50ZXJzZWN0LCBhbiBlcnJvciBpcyB0aHJvd24uXG4gICAqIC0gSWYgbm8gdHlwZSBpcyBwcm92aWRlZCwgYW4gZXhpc3RpbmcgZGVwZW5kZW5jeSBvZiBhbnkgdHlwZSB3aWxsIHNhdGlzZnlcbiAgICogICB0aGUgcmVxdWVzdC4gSWYgbm9uZSBleGlzdHMsIGl0IGlzIGFkZGVkIGFzIEJVSUxELlxuICAgKlxuICAgKiBAcGFyYW0gcmVxdWVzdCBUaGUgZGVwZW5kZW5jeSByZXF1ZXN0LlxuICAgKiBAcmV0dXJucyBUaGUgcmVzdWx0aW5nIGRlcGVuZGVuY3kgYWZ0ZXIgbWVyZ2luZy5cbiAgICovXG4gIHB1YmxpYyByZXF1ZXN0RGVwZW5kZW5jeShyZXF1ZXN0OiBEZXBlbmRlbmN5UmVxdWVzdCk6IERlcGVuZGVuY3kge1xuICAgIC8vIFdoZW4gdHlwZSBpcyBub3Qgc3BlY2lmaWVkLCBmaW5kIGFueSBleGlzdGluZyBkZXAgd2l0aCB0aGlzIG5hbWVcbiAgICBjb25zdCByZXF1ZXN0ZWRUeXBlID1cbiAgICAgIHJlcXVlc3QudHlwZSA/P1xuICAgICAgdGhpcy5maW5kRXhpc3RpbmdJbnN0YWxsYWJsZVR5cGUocmVxdWVzdC5uYW1lKSA/P1xuICAgICAgRGVwZW5kZW5jeVR5cGUuQlVJTEQ7XG4gICAgY29uc3QgZXhpc3RpbmcgPSB0aGlzLnRyeUdldERlcGVuZGVuY3kocmVxdWVzdC5uYW1lLCByZXF1ZXN0ZWRUeXBlKTtcblxuICAgIGlmICghZXhpc3RpbmcpIHtcbiAgICAgIGNvbnN0IHNwZWMgPSByZXF1ZXN0LnZlcnNpb25cbiAgICAgICAgPyBgJHtyZXF1ZXN0Lm5hbWV9QCR7cmVxdWVzdC52ZXJzaW9ufWBcbiAgICAgICAgOiByZXF1ZXN0Lm5hbWU7XG4gICAgICByZXR1cm4gdGhpcy5hZGREZXBlbmRlbmN5KHNwZWMsIHJlcXVlc3RlZFR5cGUsIHJlcXVlc3QubWV0YWRhdGEgPz8ge30pO1xuICAgIH1cblxuICAgIC8vIFZlcnNpb24gbWVyZ2luZ1xuICAgIGxldCBlZmZlY3RpdmVWZXJzaW9uOiBzdHJpbmcgfCB1bmRlZmluZWQ7XG5cbiAgICBpZiAoIXJlcXVlc3QudmVyc2lvbikge1xuICAgICAgZWZmZWN0aXZlVmVyc2lvbiA9IGV4aXN0aW5nLnZlcnNpb247XG4gICAgfSBlbHNlIGlmIChcbiAgICAgIHRoaXMuaXNEZXBlbmRlbmN5U2F0aXNmaWVkKHJlcXVlc3QubmFtZSwgcmVxdWVzdGVkVHlwZSwgcmVxdWVzdC52ZXJzaW9uKVxuICAgICkge1xuICAgICAgZWZmZWN0aXZlVmVyc2lvbiA9IGV4aXN0aW5nLnZlcnNpb247XG4gICAgfSBlbHNlIGlmICghZXhpc3RpbmcudmVyc2lvbikge1xuICAgICAgZWZmZWN0aXZlVmVyc2lvbiA9IHJlcXVlc3QudmVyc2lvbjtcbiAgICB9IGVsc2UgaWYgKHNlbXZlci5pbnRlcnNlY3RzKGV4aXN0aW5nLnZlcnNpb24sIHJlcXVlc3QudmVyc2lvbikpIHtcbiAgICAgIGVmZmVjdGl2ZVZlcnNpb24gPSByZXF1ZXN0LnZlcnNpb247XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgYERlcGVuZGVuY3kgXCIke3JlcXVlc3QubmFtZX1cIiB2ZXJzaW9uIGNvbmZsaWN0OiBleGlzdGluZyBcIiR7ZXhpc3RpbmcudmVyc2lvbn1cIiBgICtcbiAgICAgICAgICBgZG9lcyBub3QgaW50ZXJzZWN0IHdpdGggcmVxdWVzdGVkIFwiJHtyZXF1ZXN0LnZlcnNpb259XCJgLFxuICAgICAgKTtcbiAgICB9XG5cbiAgICBjb25zdCBzcGVjID0gZWZmZWN0aXZlVmVyc2lvblxuICAgICAgPyBgJHtyZXF1ZXN0Lm5hbWV9QCR7ZWZmZWN0aXZlVmVyc2lvbn1gXG4gICAgICA6IHJlcXVlc3QubmFtZTtcbiAgICByZXR1cm4gdGhpcy5hZGREZXBlbmRlbmN5KHNwZWMsIHJlcXVlc3RlZFR5cGUsIHtcbiAgICAgIC4uLmV4aXN0aW5nLm1ldGFkYXRhLFxuICAgICAgLi4ucmVxdWVzdC5tZXRhZGF0YSxcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBGaW5kcyB0aGUgdHlwZSBvZiBhbiBleGlzdGluZyBpbnN0YWxsYWJsZSBkZXBlbmRlbmN5IGJ5IG5hbWUuXG4gICAqIEV4Y2x1ZGVzIFBFRVIsIE9WRVJSSURFLCBhbmQgT1BUSU9OQUwgdHlwZXMuXG4gICAqIFJldHVybnMgdW5kZWZpbmVkIGlmIG5vIGRlcGVuZGVuY3kgd2l0aCB0aGlzIG5hbWUgZXhpc3RzLlxuICAgKi9cbiAgcHJpdmF0ZSBmaW5kRXhpc3RpbmdJbnN0YWxsYWJsZVR5cGUoXG4gICAgbmFtZTogc3RyaW5nLFxuICApOiBEZXBlbmRlbmN5VHlwZSB8IHVuZGVmaW5lZCB7XG4gICAgcmV0dXJuIHRoaXMuX2RlcHMuZmluZChcbiAgICAgIChkKSA9PlxuICAgICAgICBkLm5hbWUgPT09IG5hbWUgJiZcbiAgICAgICAgZC50eXBlICE9PSBEZXBlbmRlbmN5VHlwZS5QRUVSICYmXG4gICAgICAgIGQudHlwZSAhPT0gRGVwZW5kZW5jeVR5cGUuT1ZFUlJJREUgJiZcbiAgICAgICAgZC50eXBlICE9PSBEZXBlbmRlbmN5VHlwZS5PUFRJT05BTCxcbiAgICApPy50eXBlO1xuICB9XG5cbiAgcHJpdmF0ZSB0cnlHZXREZXBlbmRlbmN5SW5kZXgobmFtZTogc3RyaW5nLCB0eXBlPzogRGVwZW5kZW5jeVR5cGUpOiBudW1iZXIge1xuICAgIGNvbnN0IGRlcHMgPSB0aGlzLl9kZXBzLmZpbHRlcigoZCkgPT4gZC5uYW1lID09PSBuYW1lKTtcbiAgICBpZiAoZGVwcy5sZW5ndGggPT09IDApIHtcbiAgICAgIHJldHVybiAtMTsgLy8gbm90IGZvdW5kXG4gICAgfVxuXG4gICAgaWYgKCF0eXBlKSB7XG4gICAgICBpZiAoZGVwcy5sZW5ndGggPiAxKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICBgXCIke25hbWV9XCIgaXMgZGVmaW5lZCBmb3IgbXVsdGlwbGUgZGVwZW5kZW5jeSB0eXBlczogJHtkZXBzXG4gICAgICAgICAgICAubWFwKChkKSA9PiBkLnR5cGUpXG4gICAgICAgICAgICAuam9pbihcIixcIil9LiBQbGVhc2Ugc3BlY2lmeSBkZXBlbmRlbmN5IHR5cGVgLFxuICAgICAgICApO1xuICAgICAgfVxuXG4gICAgICB0eXBlID0gZGVwc1swXS50eXBlO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzLl9kZXBzLmZpbmRJbmRleChcbiAgICAgIChkZXApID0+IGRlcC5uYW1lID09PSBuYW1lICYmIGRlcC50eXBlID09PSB0eXBlLFxuICAgICk7XG4gIH1cblxuICBwcml2YXRlIHRvSnNvbigpOiBEZXBzTWFuaWZlc3QgfCB1bmRlZmluZWQge1xuICAgIGlmICh0aGlzLl9kZXBzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9XG4gICAgcmV0dXJuIHtcbiAgICAgIGRlcGVuZGVuY2llczogdGhpcy5fZGVwcy5zb3J0KGNvbXBhcmVEZXBzKS5tYXAobm9ybWFsaXplRGVwKSxcbiAgICB9O1xuICB9XG59XG5cbmZ1bmN0aW9uIG5vcm1hbGl6ZURlcChkOiBEZXBlbmRlbmN5KSB7XG4gIGNvbnN0IG9iajogYW55ID0ge307XG4gIGZvciAoY29uc3QgW2ssIHZdIG9mIE9iamVjdC5lbnRyaWVzKGQpKSB7XG4gICAgaWYgKHYgPT0gdW5kZWZpbmVkKSB7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG4gICAgaWYgKHR5cGVvZiB2ID09PSBcIm9iamVjdFwiICYmIE9iamVjdC5rZXlzKHYpLmxlbmd0aCA9PT0gMCkge1xuICAgICAgY29udGludWU7XG4gICAgfVxuICAgIGlmIChBcnJheS5pc0FycmF5KHYpICYmIHYubGVuZ3RoID09PSAwKSB7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG4gICAgb2JqW2tdID0gdjtcbiAgfVxuXG4gIHJldHVybiBvYmo7XG59XG5cbmZ1bmN0aW9uIGNvbXBhcmVEZXBzKGQxOiBEZXBlbmRlbmN5LCBkMjogRGVwZW5kZW5jeSkge1xuICByZXR1cm4gc3BlY09mKGQxKS5sb2NhbGVDb21wYXJlKHNwZWNPZihkMikpO1xuXG4gIGZ1bmN0aW9uIHNwZWNPZihkZXA6IERlcGVuZGVuY3kpIHtcbiAgICBsZXQgc3BlYyA9IGRlcC50eXBlICsgXCI6XCIgKyBkZXAubmFtZTtcbiAgICBpZiAoZGVwLnZlcnNpb24pIHtcbiAgICAgIHNwZWMgKz0gXCJAXCIgKyBkZXAudmVyc2lvbjtcbiAgICB9XG4gICAgcmV0dXJuIHNwZWM7XG4gIH1cbn1cblxuZXhwb3J0IGludGVyZmFjZSBEZXBzTWFuaWZlc3Qge1xuICAvKipcbiAgICogQWxsIGRlcGVuZGVuY2llcyBvZiB0aGlzIG1vZHVsZS5cbiAgICovXG4gIHJlYWRvbmx5IGRlcGVuZGVuY2llczogRGVwZW5kZW5jeVtdO1xufVxuXG4vKipcbiAqIENvb3JkaW5hdGVzIG9mIHRoZSBkZXBlbmRlbmN5IChuYW1lIGFuZCB2ZXJzaW9uKS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBEZXBlbmRlbmN5Q29vcmRpbmF0ZXMge1xuICAvKipcbiAgICogVGhlIHBhY2thZ2UgbWFuYWdlciBuYW1lIG9mIHRoZSBkZXBlbmRlbmN5IChlLmcuIGBsZWZ0cGFkYCBmb3IgbnBtKS5cbiAgICpcbiAgICogTk9URTogRm9yIHBhY2thZ2UgbWFuYWdlcnMgdGhhdCB1c2UgY29tcGxleCBjb29yZGluYXRlcyAobGlrZSBNYXZlbiksIHdlXG4gICAqIHdpbGwgY29kaWZ5IGl0IGludG8gYSBzdHJpbmcgc29tZWhvdy5cbiAgICovXG4gIHJlYWRvbmx5IG5hbWU6IHN0cmluZztcblxuICAvKipcbiAgICogU2VtYW50aWMgdmVyc2lvbiB2ZXJzaW9uIHJlcXVpcmVtZW50LlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIHJlcXVpcmVtZW50IGlzIG1hbmFnZWQgYnkgdGhlIHBhY2thZ2UgbWFuYWdlciAoZS5nLiBucG0veWFybikuXG4gICAqL1xuICByZWFkb25seSB2ZXJzaW9uPzogc3RyaW5nO1xufVxuXG4vKipcbiAqIFJlcHJlc2VudHMgYSBwcm9qZWN0IGRlcGVuZGVuY3kuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgRGVwZW5kZW5jeSBleHRlbmRzIERlcGVuZGVuY3lDb29yZGluYXRlcyB7XG4gIC8qKlxuICAgKiBXaGljaCB0eXBlIG9mIGRlcGVuZGVuY3kgdGhpcyBpcyAocnVudGltZSwgYnVpbGQtdGltZSwgZXRjKS5cbiAgICovXG4gIHJlYWRvbmx5IHR5cGU6IERlcGVuZGVuY3lUeXBlO1xuXG4gIC8qKlxuICAgKiBBZGRpdGlvbmFsIEpTT04gbWV0YWRhdGEgYXNzb2NpYXRlZCB3aXRoIHRoZSBkZXBlbmRlbmN5IChwYWNrYWdlIG1hbmFnZXJcbiAgICogc3BlY2lmaWMpLlxuICAgKiBAZGVmYXVsdCB7fVxuICAgKi9cbiAgcmVhZG9ubHkgbWV0YWRhdGE/OiB7IFtrZXk6IHN0cmluZ106IGFueSB9O1xufVxuXG4vKipcbiAqIFR5cGUgb2YgZGVwZW5kZW5jeS5cbiAqL1xuZXhwb3J0IGVudW0gRGVwZW5kZW5jeVR5cGUge1xuICAvKipcbiAgICogVGhlIGRlcGVuZGVuY3kgaXMgcmVxdWlyZWQgZm9yIHRoZSBwcm9ncmFtL2xpYnJhcnkgZHVyaW5nIHJ1bnRpbWUuXG4gICAqL1xuICBSVU5USU1FID0gXCJydW50aW1lXCIsXG5cbiAgLyoqXG4gICAqIFRoZSBkZXBlbmRlbmN5IGlzIHJlcXVpcmVkIGF0IHJ1bnRpbWUgYnV0IGV4cGVjdGVkIHRvIGJlIGluc3RhbGxlZCBieSB0aGVcbiAgICogY29uc3VtZXIuXG4gICAqL1xuICBQRUVSID0gXCJwZWVyXCIsXG5cbiAgLyoqXG4gICAqIFRoZSBkZXBlbmRlbmN5IGlzIGJ1bmRsZWQgYW5kIHNoaXBwZWQgd2l0aCB0aGUgbW9kdWxlLCBzbyBjb25zdW1lcnMgYXJlIG5vdFxuICAgKiByZXF1aXJlZCB0byBpbnN0YWxsIGl0LlxuICAgKi9cbiAgQlVORExFRCA9IFwiYnVuZGxlZFwiLFxuXG4gIC8qKlxuICAgKiBUaGUgZGVwZW5kZW5jeSBpcyByZXF1aXJlZCB0byBydW4gdGhlIGBidWlsZGAgdGFzay5cbiAgICovXG4gIEJVSUxEID0gXCJidWlsZFwiLFxuXG4gIC8qKlxuICAgKiBUaGUgZGVwZW5kZW5jeSBpcyByZXF1aXJlZCB0byBydW4gdGhlIGB0ZXN0YCB0YXNrLlxuICAgKi9cbiAgVEVTVCA9IFwidGVzdFwiLFxuXG4gIC8qKlxuICAgKiBUaGUgZGVwZW5kZW5jeSBpcyByZXF1aXJlZCBmb3IgZGV2ZWxvcG1lbnQgKGUuZy4gSURFIHBsdWdpbnMpLlxuICAgKi9cbiAgREVWRU5WID0gXCJkZXZlbnZcIixcblxuICAvKipcbiAgICogVHJhbnNpZW50IGRlcGVuZGVuY3kgdGhhdCBuZWVkcyB0byBiZSBvdmVyd3JpdHRlbi5cbiAgICpcbiAgICogQXZhaWxhYmxlIGZvciBOb2RlIHBhY2thZ2VzXG4gICAqL1xuICBPVkVSUklERSA9IFwib3ZlcnJpZGVcIixcblxuICAvKipcbiAgICogQW4gb3B0aW9uYWwgZGVwZW5kZW5jeSB0aGF0IG1heSBiZSB1c2VkIGF0IHJ1bnRpbWUgaWYgYXZhaWxhYmxlLCBidXQgaXMgbm90IHJlcXVpcmVkLlxuICAgKiBJdCBpcyBleHBlY3RlZCB0byBiZSBpbnN0YWxsZWQgYnkgdGhlIGNvbnN1bWVyLlxuICAgKi9cbiAgT1BUSU9OQUwgPSBcIm9wdGlvbmFsXCIsXG59XG5cbi8qKlxuICogQSByZXF1ZXN0IGZvciBhIGRlcGVuZGVuY3kuIFVubGlrZSBhZGRpbmcgYSBkZXBlbmRlbmN5IGRpcmVjdGx5LFxuICogcmVxdWVzdGluZyBhIGRlcGVuZGVuY3kgd2lsbCBpbnRlbGxpZ2VudGx5IG1lcmdlIHdpdGggZXhpc3RpbmdcbiAqIGRlcGVuZGVuY2llcyBvZiB0aGUgc2FtZSBuYW1lIGFuZCB0eXBlLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIERlcGVuZGVuY3lSZXF1ZXN0IHtcbiAgLyoqXG4gICAqIFRoZSBwYWNrYWdlIG5hbWUuXG4gICAqL1xuICByZWFkb25seSBuYW1lOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFNlbWFudGljIHZlcnNpb24gY29uc3RyYWludC5cbiAgICogQGRlZmF1bHQgLSBhbnkgdmVyc2lvblxuICAgKi9cbiAgcmVhZG9ubHkgdmVyc2lvbj86IHN0cmluZztcblxuICAvKipcbiAgICogRGVwZW5kZW5jeSB0eXBlLiBJZiBub3QgcHJvdmlkZWQsIGFuIGV4aXN0aW5nIGRlcGVuZGVuY3kgb2YgYW55IHR5cGVcbiAgICogd2lsbCBzYXRpc2Z5IHRoZSByZXF1ZXN0LiBJZiBub25lIGV4aXN0cywgaXQgaXMgYWRkZWQgYXMgQlVJTEQuXG4gICAqIEBkZWZhdWx0IC0gYW55IGV4aXN0aW5nIHR5cGUsIG9yIERlcGVuZGVuY3lUeXBlLkJVSUxEXG4gICAqL1xuICByZWFkb25seSB0eXBlPzogRGVwZW5kZW5jeVR5cGU7XG5cbiAgLyoqXG4gICAqIEFkZGl0aW9uYWwgbWV0YWRhdGEuXG4gICAqIEBkZWZhdWx0IC0gbm9uZVxuICAgKi9cbiAgcmVhZG9ubHkgbWV0YWRhdGE/OiBSZWNvcmQ8c3RyaW5nLCBhbnk+O1xufVxuIl19