UNPKG

projen

Version:

CDK for software projects

324 lines • 39.2 kB
"use strict"; 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