UNPKG

projen

Version:

CDK for software projects

260 lines • 29.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 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.debug(`${type}-dep ${spec}`); const dep = { ...Dependencies.parseDependency(spec), type, metadata, }; const existingDepIndex = this.tryGetDependencyIndex(dep.name, type); if (existingDepIndex !== -1) { this.project.logger.debug(`updating existing ${dep.type}-dep ${dep.name} with more specific version/metadata`); 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); } 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.95.2" }; /** * 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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVwZW5kZW5jaWVzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL2RlcGVuZGVuY2llcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUFBLDZCQUE2QjtBQUM3QixpQ0FBaUM7QUFDakMscUNBQXNDO0FBQ3RDLDJDQUF3QztBQUN4QyxpQ0FBa0M7QUFHbEM7Ozs7Ozs7O0dBUUc7QUFDSCxNQUFhLFlBQWEsU0FBUSxxQkFBUztJQVN6Qzs7Ozs7T0FLRztJQUNJLE1BQU0sQ0FBQyxlQUFlLENBQUMsSUFBWTtRQUN4QyxNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsVUFBVSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQ25DLElBQUksS0FBSyxFQUFFLENBQUM7WUFDVixJQUFJLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUN4QixDQUFDO1FBRUQsTUFBTSxDQUFDLE1BQU0sRUFBRSxHQUFHLE9BQU8sQ0FBQyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDN0MsTUFBTSxJQUFJLEdBQUcsS0FBSyxDQUFDLENBQUMsQ0FBQyxJQUFJLE1BQU0sRUFBRSxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUM7UUFDM0MsSUFBSSxPQUFPLENBQUMsTUFBTSxJQUFJLENBQUMsRUFBRSxDQUFDO1lBQ3hCLE9BQU8sRUFBRSxJQUFJLEVBQUUsQ0FBQztRQUNsQixDQUFDO2FBQU0sQ0FBQztZQUNOLE9BQU8sRUFBRSxJQUFJLEVBQUUsT0FBTyxFQUFFLE9BQU8sRUFBRSxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQztRQUMvQyxDQUFDO0lBQ0gsQ0FBQztJQUlEOzs7T0FHRztJQUNILFlBQVksT0FBZ0I7UUFDMUIsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBUEEsVUFBSyxHQUFHLElBQUksS0FBSyxFQUFjLENBQUM7UUFTL0MsNEVBQTRFO1FBQzVFLHNFQUFzRTtRQUN0RSx3Q0FB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RUFBYztJQUNqRCxPQUFPLE1BQU0sQ0FBQyxFQUFFLENBQUMsQ0FBQyxhQUFhLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFFNUMsU0FBUyxNQUFNLENBQUMsR0FBZTtRQUM3QixJQUFJLElBQUksR0FBRyxHQUFHLENBQUMsSUFBSSxHQUFHLEdBQUcsR0FBRyxHQUFHLENBQUMsSUFBSSxDQUFDO1FBQ3JDLElBQUksR0FBRyxDQUFDLE9BQU8sRUFBRSxDQUFDO1lBQ2hCLElBQUksSUFBSSxHQUFHLEdBQUcsR0FBRyxDQUFDLE9BQU8sQ0FBQztRQUM1QixDQUFDO1FBQ0QsT0FBTyxJQUFJLENBQUM7SUFDZCxDQUFDO0FBQ0gsQ0FBQztBQThDRDs7R0FFRztBQUNILElBQVksY0E2Q1g7QUE3Q0QsV0FBWSxjQUFjO0lBQ3hCOztPQUVHO0lBQ0gscUNBQW1CLENBQUE7SUFFbkI7OztPQUdHO0lBQ0gsK0JBQWEsQ0FBQTtJQUViOzs7T0FHRztJQUNILHFDQUFtQixDQUFBO0lBRW5COztPQUVHO0lBQ0gsaUNBQWUsQ0FBQTtJQUVmOztPQUVHO0lBQ0gsK0JBQWEsQ0FBQTtJQUViOztPQUVHO0lBQ0gsbUNBQWlCLENBQUE7SUFFakI7Ozs7T0FJRztJQUNILHVDQUFxQixDQUFBO0lBRXJCOzs7T0FHRztJQUNILHVDQUFxQixDQUFBO0FBQ3ZCLENBQUMsRUE3Q1csY0FBYyw4QkFBZCxjQUFjLFFBNkN6QiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAqIGFzIHBhdGggZnJvbSBcInBhdGhcIjtcbmltcG9ydCAqIGFzIHNlbXZlciBmcm9tIFwic2VtdmVyXCI7XG5pbXBvcnQgeyBQUk9KRU5fRElSIH0gZnJvbSBcIi4vY29tbW9uXCI7XG5pbXBvcnQgeyBDb21wb25lbnQgfSBmcm9tIFwiLi9jb21wb25lbnRcIjtcbmltcG9ydCB7IEpzb25GaWxlIH0gZnJvbSBcIi4vanNvblwiO1xuaW1wb3J0IHsgUHJvamVjdCB9IGZyb20gXCIuL3Byb2plY3RcIjtcblxuLyoqXG4gKiBUaGUgYERlcGVuZGVuY2llc2AgY29tcG9uZW50IGlzIHJlc3BvbnNpYmxlIHRvIHRyYWNrIHRoZSBsaXN0IG9mIGRlcGVuZGVuY2llc1xuICogYSBwcm9qZWN0IGhhcywgYW5kIHRoZW4gdXNlZCBieSBwcm9qZWN0IHR5cGVzIGFzIHRoZSBtb2RlbCBmb3IgcmVuZGVyaW5nXG4gKiBwcm9qZWN0LXNwZWNpZmljIGRlcGVuZGVuY3kgbWFuaWZlc3RzIHN1Y2ggYXMgdGhlIGRlcGVuZGVuY2llcyBzZWN0aW9uXG4gKiBgcGFja2FnZS5qc29uYCBmaWxlcy5cbiAqXG4gKiBUbyBhZGQgYSBkZXBlbmRlbmN5IHlvdSBjYW4gdXNlIGEgcHJvamVjdC10eXBlIHNwZWNpZmljIEFQSSBzdWNoIGFzXG4gKiBgbm9kZVByb2plY3QuYWRkRGVwcygpYCBvciB1c2UgdGhlIGdlbmVyaWMgQVBJIG9mIGBwcm9qZWN0LmRlcHNgOlxuICovXG5leHBvcnQgY2xhc3MgRGVwZW5kZW5jaWVzIGV4dGVuZHMgQ29tcG9uZW50IHtcbiAgLyoqXG4gICAqIFRoZSBwcm9qZWN0LXJlbGF0aXZlIHBhdGggb2YgdGhlIGRlcHMgbWFuaWZlc3QgZmlsZS5cbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgcmVhZG9ubHkgTUFOSUZFU1RfRklMRSA9IHBhdGgucG9zaXguam9pbihcbiAgICBQUk9KRU5fRElSLFxuICAgIFwiZGVwcy5qc29uXCJcbiAgKTtcblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgY29vcmRpbmF0ZXMgb2YgYSBkZXBlbmRlbmN5IHNwZWMuXG4gICAqXG4gICAqIEdpdmVuIGBmb29AXjMuNC4wYCByZXR1cm5zIGB7IG5hbWU6IFwiZm9vXCIsIHZlcnNpb246IFwiXjMuNC4wXCIgfWAuXG4gICAqIEdpdmVuIGBiYXJAbnBtOkBiYXIvbGVnYWN5YCByZXR1cm5zIGB7IG5hbWU6IFwiYmFyXCIsIHZlcnNpb246IFwibnBtOkBiYXIvbGVnYWN5XCIgfWAuXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIHBhcnNlRGVwZW5kZW5jeShzcGVjOiBzdHJpbmcpOiBEZXBlbmRlbmN5Q29vcmRpbmF0ZXMge1xuICAgIGNvbnN0IHNjb3BlID0gc3BlYy5zdGFydHNXaXRoKFwiQFwiKTtcbiAgICBpZiAoc2NvcGUpIHtcbiAgICAgIHNwZWMgPSBzcGVjLnN1YnN0cigxKTtcbiAgICB9XG5cbiAgICBjb25zdCBbbW9kdWxlLCAuLi52ZXJzaW9uXSA9IHNwZWMuc3BsaXQoXCJAXCIpO1xuICAgIGNvbnN0IG5hbWUgPSBzY29wZSA/IGBAJHttb2R1bGV9YCA6IG1vZHVsZTtcbiAgICBpZiAodmVyc2lvbi5sZW5ndGggPT0gMCkge1xuICAgICAgcmV0dXJuIHsgbmFtZSB9O1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4geyBuYW1lLCB2ZXJzaW9uOiB2ZXJzaW9uPy5qb2luKFwiQFwiKSB9O1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgcmVhZG9ubHkgX2RlcHMgPSBuZXcgQXJyYXk8RGVwZW5kZW5jeT4oKTtcblxuICAvKipcbiAgICogQWRkcyBhIGRlcGVuZGVuY2llcyBjb21wb25lbnQgdG8gdGhlIHByb2plY3QuXG4gICAqIEBwYXJhbSBwcm9qZWN0IFRoZSBwYXJlbnQgcHJvamVjdFxuICAgKi9cbiAgY29uc3RydWN0b3IocHJvamVjdDogUHJvamVjdCkge1xuICAgIHN1cGVyKHByb2plY3QpO1xuXG4gICAgLy8gdGhpcyBpcyBub3QgcmVhbGx5IHJlcXVpcmVkIGF0IHRoZSBtb21lbnQsIGJ1dCBhY3R1YWxseSBxdWl0ZSB1c2VmdWwgYXMgYVxuICAgIC8vIGNoZWNrZWQtaW4gc291cmNlIG9mIHRydXRoIGZvciBkZXBlbmRlbmNpZXMgYW5kIHdpbGwgcG90ZW50aWFsbHkgYmVcbiAgICAvLyB2YWx1YWJsZSBpbiB0aGUgZnV0dXJlIGZvciBDTEkgdG9vbHMuXG4gICAgaWYgKCFwcm9qZWN0LmVqZWN0ZWQpIHtcbiAgICAgIG5ldyBKc29uRmlsZShwcm9qZWN0LCBEZXBlbmRlbmNpZXMuTUFOSUZFU1RfRklMRSwge1xuICAgICAgICBvbWl0RW1wdHk6IHRydWUsXG4gICAgICAgIG9iajogKCkgPT4gdGhpcy50b0pzb24oKSxcbiAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBBIGNvcHkgb2YgYWxsIGRlcGVuZGVuY2llcyByZWNvcmRlZCBmb3IgdGhpcyBwcm9qZWN0LlxuICAgKlxuICAgKiBUaGUgbGlzdCBpcyBzb3J0ZWQgYnkgdHlwZS0+bmFtZS0+dmVyc2lvblxuICAgKi9cbiAgcHVibGljIGdldCBhbGwoKTogRGVwZW5kZW5jeVtdIHtcbiAgICByZXR1cm4gWy4uLnRoaXMuX2RlcHNdLnNvcnQoY29tcGFyZURlcHMpLm1hcChub3JtYWxpemVEZXApO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgYSBkZXBlbmRlbmN5IGJ5IG5hbWUuXG4gICAqXG4gICAqIEZhaWxzIGlmIHRoZXJlIGlzIG5vIGRlcGVuZGVuY3kgZGVmaW5lZCBieSB0aGF0IG5hbWUgb3IgaWYgYHR5cGVgIGlzIG5vdFxuICAgKiBwcm92aWRlZCBhbmQgdGhlcmUgaXMgbW9yZSB0aGVuIG9uZSBkZXBlbmRlbmN5IHR5cGUgZm9yIHRoaXMgZGVwZW5kZW5jeS5cbiAgICpcbiAgICogQHBhcmFtIG5hbWUgVGhlIG5hbWUgb2YgdGhlIGRlcGVuZGVuY3lcbiAgICogQHBhcmFtIHR5cGUgVGhlIGRlcGVuZGVuY3kgdHlwZS4gSWYgdGhpcyBkZXBlbmRlbmN5IGlzIGRlZmluZWQgb25seSBmb3IgYVxuICAgKiBzaW5nbGUgdHlwZSwgdGhpcyBhcmd1bWVudCBjYW4gYmUgb21pdHRlZC5cbiAgICpcbiAgICogQHJldHVybnMgYSBjb3B5IChjYW5ub3QgYmUgbW9kaWZpZWQpXG4gICAqL1xuICBwdWJsaWMgZ2V0RGVwZW5kZW5jeShuYW1lOiBzdHJpbmcsIHR5cGU/OiBEZXBlbmRlbmN5VHlwZSk6IERlcGVuZGVuY3kge1xuICAgIGNvbnN0IGRlcCA9IHRoaXMudHJ5R2V0RGVwZW5kZW5jeShuYW1lLCB0eXBlKTtcbiAgICBpZiAoIWRlcCkge1xuICAgICAgY29uc3QgbXNnID0gdHlwZVxuICAgICAgICA/IGB0aGVyZSBpcyBubyAke3R5cGV9IGRlcGVuZGVuY3kgZGVmaW5lZCBvbiBcIiR7bmFtZX1cImBcbiAgICAgICAgOiBgdGhlcmUgaXMgbm8gZGVwZW5kZW5jeSBkZWZpbmVkIG9uIFwiJHtuYW1lfVwiYDtcblxuICAgICAgdGhyb3cgbmV3IEVycm9yKG1zZyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGRlcDtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGEgZGVwZW5kZW5jeSBieSBuYW1lLlxuICAgKlxuICAgKiBSZXR1cm5zIGB1bmRlZmluZWRgIGlmIHRoZXJlIGlzIG5vIGRlcGVuZGVuY3kgZGVmaW5lZCBieSB0aGF0IG5hbWUgb3IgaWZcbiAgICogYHR5cGVgIGlzIG5vdCBwcm92aWRlZCBhbmQgdGhlcmUgaXMgbW9yZSB0aGVuIG9uZSBkZXBlbmRlbmN5IHR5cGUgZm9yIHRoaXNcbiAgICogZGVwZW5kZW5jeS5cbiAgICpcbiAgICogQHBhcmFtIG5hbWUgVGhlIG5hbWUgb2YgdGhlIGRlcGVuZGVuY3lcbiAgICogQHBhcmFtIHR5cGUgVGhlIGRlcGVuZGVuY3kgdHlwZS4gSWYgdGhpcyBkZXBlbmRlbmN5IGlzIGRlZmluZWQgb25seSBmb3IgYVxuICAgKiBzaW5nbGUgdHlwZSwgdGhpcyBhcmd1bWVudCBjYW4gYmUgb21pdHRlZC5cbiAgICpcbiAgICogQHJldHVybnMgYSBjb3B5IChjYW5ub3QgYmUgbW9kaWZpZWQpIG9yIHVuZGVmaW5lZCBpZiB0aGVyZSBpcyBubyBtYXRjaFxuICAgKi9cbiAgcHVibGljIHRyeUdldERlcGVuZGVuY3koXG4gICAgbmFtZTogc3RyaW5nLFxuICAgIHR5cGU/OiBEZXBlbmRlbmN5VHlwZVxuICApOiBEZXBlbmRlbmN5IHwgdW5kZWZpbmVkIHtcbiAgICBjb25zdCBpZHggPSB0aGlzLnRyeUdldERlcGVuZGVuY3lJbmRleChuYW1lLCB0eXBlKTtcbiAgICBpZiAoaWR4ID09PSAtMSkge1xuICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgLi4ubm9ybWFsaXplRGVwKHRoaXMuX2RlcHNbaWR4XSksXG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBZGRzIGEgZGVwZW5kZW5jeSB0byB0aGlzIHByb2plY3QuXG4gICAqIEBwYXJhbSBzcGVjIFRoZSBkZXBlbmRlbmN5IHNwZWMgaW4gdGhlIGZvcm1hdCBgTU9EVUxFW0BWRVJTSU9OXWAgd2hlcmVcbiAgICogYE1PRFVMRWAgaXMgdGhlIHBhY2thZ2UtbWFuYWdlci1zcGVjaWZpYyBtb2R1bGUgbmFtZSBhbmQgYFZFUlNJT05gIGlzIGFuXG4gICAqIG9wdGlvbmFsIHNlbWFudGljIHZlcnNpb24gcmVxdWlyZW1lbnQgKGUuZy4gYF4zLjQuMGApLlxuICAgKiBAcGFyYW0gdHlwZSBUaGUgdHlwZSBvZiB0aGUgZGVwZW5kZW5jeS5cbiAgICovXG4gIHB1YmxpYyBhZGREZXBlbmRlbmN5KFxuICAgIHNwZWM6IHN0cmluZyxcbiAgICB0eXBlOiBEZXBlbmRlbmN5VHlwZSxcbiAgICBtZXRhZGF0YTogeyBba2V5OiBzdHJpbmddOiBhbnkgfSA9IHt9XG4gICk6IERlcGVuZGVuY3kge1xuICAgIHRoaXMucHJvamVjdC5sb2dnZXIuZGVidWcoYCR7dHlwZX0tZGVwICR7c3BlY31gKTtcblxuICAgIGNvbnN0IGRlcDogRGVwZW5kZW5jeSA9IHtcbiAgICAgIC4uLkRlcGVuZGVuY2llcy5wYXJzZURlcGVuZGVuY3koc3BlYyksXG4gICAgICB0eXBlLFxuICAgICAgbWV0YWRhdGEsXG4gICAgfTtcblxuICAgIGNvbnN0IGV4aXN0aW5nRGVwSW5kZXggPSB0aGlzLnRyeUdldERlcGVuZGVuY3lJbmRleChkZXAubmFtZSwgdHlwZSk7XG5cbiAgICBpZiAoZXhpc3RpbmdEZXBJbmRleCAhPT0gLTEpIHtcbiAgICAgIHRoaXMucHJvamVjdC5sb2dnZXIuZGVidWcoXG4gICAgICAgIGB1cGRhdGluZyBleGlzdGluZyAke2RlcC50eXBlfS1kZXAgJHtkZXAubmFtZX0gd2l0aCBtb3JlIHNwZWNpZmljIHZlcnNpb24vbWV0YWRhdGFgXG4gICAgICApO1xuICAgICAgdGhpcy5fZGVwc1tleGlzdGluZ0RlcEluZGV4XSA9IGRlcDtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5fZGVwcy5wdXNoKGRlcCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGRlcDtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZW1vdmVzIGEgZGVwZW5kZW5jeS5cbiAgICogQHBhcmFtIG5hbWUgVGhlIG5hbWUgb2YgdGhlIG1vZHVsZSB0byByZW1vdmUgKHdpdGhvdXQgdGhlIHZlcnNpb24pXG4gICAqIEBwYXJhbSB0eXBlIFRoZSBkZXBlbmRlbmN5IHR5cGUuIFRoaXMgaXMgb25seSByZXF1aXJlZCBpZiB0aGVyZSB0aGVcbiAgICogZGVwZW5kZW5jeSBpcyBkZWZpbmVkIGZvciBtdWx0aXBsZSB0eXBlcy5cbiAgICovXG4gIHB1YmxpYyByZW1vdmVEZXBlbmRlbmN5KG5hbWU6IHN0cmluZywgdHlwZT86IERlcGVuZGVuY3lUeXBlKSB7XG4gICAgY29uc3QgcmVtb3ZlSW5kZXggPSB0aGlzLnRyeUdldERlcGVuZGVuY3lJbmRleChuYW1lLCB0eXBlKTtcbiAgICBpZiAocmVtb3ZlSW5kZXggPT09IC0xKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdGhpcy5fZGVwcy5zcGxpY2UocmVtb3ZlSW5kZXgsIDEpO1xuICB9XG5cbiAgLyoqXG4gICAqIENoZWNrcyBpZiBhbiBleGlzdGluZyBkZXBlbmRlbmN5IHNhdGlzZmllcyBhIGRlcGVuZGVuY3kgcmVxdWlyZW1lbnQuXG4gICAqIEBwYXJhbSBuYW1lIFRoZSBuYW1lIG9mIHRoZSBkZXBlbmRlbmN5IHRvIGNoZWNrICh3aXRob3V0IHRoZSB2ZXJzaW9uKS5cbiAgICogQHBhcmFtIHR5cGUgVGhlIGRlcGVuZGVuY3kgdHlwZS5cbiAgICogQHBhcmFtIGV4cGVjdGVkUmFuZ2UgVGhlIHZlcnNpb24gY29uc3RyYWludCB0byBjaGVjayAoZS5nLiBgXjMuNC4wYCkuXG4gICAqIFRoZSBjb25zdHJhaW50IG9mIHRoZSBkZXBlbmRlbmN5IG11c3QgYmUgYSBzdWJzZXQgb2YgdGhlIGV4cGVjdGVkIHJhbmdlIHRvIHNhdGlzZnkgdGhlIHJlcXVpcmVtZW50cy5cbiAgICogQHJldHVybnMgYHRydWVgIGlmIHRoZSBkZXBlbmRlbmN5IGV4aXN0cyBhbmQgaXRzIHZlcnNpb24gc2F0aXNmaWVzIHRoZSBwcm92aWRlZCBjb25zdHJhaW50LiBgZmFsc2VgIG90aGVyd2lzZS5cbiAgICogTm90YWJseSByZXR1cm5zIGBmYWxzZWAgaWYgYSBkZXBlbmRlbmN5IGV4aXN0cywgYnV0IGhhcyBubyB2ZXJzaW9uLlxuICAgKi9cbiAgcHVibGljIGlzRGVwZW5kZW5jeVNhdGlzZmllZChcbiAgICBuYW1lOiBzdHJpbmcsXG4gICAgdHlwZTogRGVwZW5kZW5jeVR5cGUsXG4gICAgZXhwZWN0ZWRSYW5nZTogc3RyaW5nXG4gICk6IGJvb2xlYW4ge1xuICAgIGNvbnN0IGRlcCA9IHRoaXMudHJ5R2V0RGVwZW5kZW5jeShuYW1lLCB0eXBlKTtcbiAgICByZXR1cm4gZGVwPy52ZXJzaW9uICE9IG51bGwgJiYgc2VtdmVyLnN1YnNldChkZXAudmVyc2lvbiwgZXhwZWN0ZWRSYW5nZSk7XG4gIH1cblxuICBwcml2YXRlIHRyeUdldERlcGVuZGVuY3lJbmRleChuYW1lOiBzdHJpbmcsIHR5cGU/OiBEZXBlbmRlbmN5VHlwZSk6IG51bWJlciB7XG4gICAgY29uc3QgZGVwcyA9IHRoaXMuX2RlcHMuZmlsdGVyKChkKSA9PiBkLm5hbWUgPT09IG5hbWUpO1xuICAgIGlmIChkZXBzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgcmV0dXJuIC0xOyAvLyBub3QgZm91bmRcbiAgICB9XG5cbiAgICBpZiAoIXR5cGUpIHtcbiAgICAgIGlmIChkZXBzLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgIGBcIiR7bmFtZX1cIiBpcyBkZWZpbmVkIGZvciBtdWx0aXBsZSBkZXBlbmRlbmN5IHR5cGVzOiAke2RlcHNcbiAgICAgICAgICAgIC5tYXAoKGQpID0+IGQudHlwZSlcbiAgICAgICAgICAgIC5qb2luKFwiLFwiKX0uIFBsZWFzZSBzcGVjaWZ5IGRlcGVuZGVuY3kgdHlwZWBcbiAgICAgICAgKTtcbiAgICAgIH1cblxuICAgICAgdHlwZSA9IGRlcHNbMF0udHlwZTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5fZGVwcy5maW5kSW5kZXgoXG4gICAgICAoZGVwKSA9PiBkZXAubmFtZSA9PT0gbmFtZSAmJiBkZXAudHlwZSA9PT0gdHlwZVxuICAgICk7XG4gIH1cblxuICBwcml2YXRlIHRvSnNvbigpOiBEZXBzTWFuaWZlc3QgfCB1bmRlZmluZWQge1xuICAgIGlmICh0aGlzLl9kZXBzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9XG4gICAgcmV0dXJuIHtcbiAgICAgIGRlcGVuZGVuY2llczogdGhpcy5fZGVwcy5zb3J0KGNvbXBhcmVEZXBzKS5tYXAobm9ybWFsaXplRGVwKSxcbiAgICB9O1xuICB9XG59XG5cbmZ1bmN0aW9uIG5vcm1hbGl6ZURlcChkOiBEZXBlbmRlbmN5KSB7XG4gIGNvbnN0IG9iajogYW55ID0ge307XG4gIGZvciAoY29uc3QgW2ssIHZdIG9mIE9iamVjdC5lbnRyaWVzKGQpKSB7XG4gICAgaWYgKHYgPT0gdW5kZWZpbmVkKSB7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG4gICAgaWYgKHR5cGVvZiB2ID09PSBcIm9iamVjdFwiICYmIE9iamVjdC5rZXlzKHYpLmxlbmd0aCA9PT0gMCkge1xuICAgICAgY29udGludWU7XG4gICAgfVxuICAgIGlmIChBcnJheS5pc0FycmF5KHYpICYmIHYubGVuZ3RoID09PSAwKSB7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG4gICAgb2JqW2tdID0gdjtcbiAgfVxuXG4gIHJldHVybiBvYmo7XG59XG5cbmZ1bmN0aW9uIGNvbXBhcmVEZXBzKGQxOiBEZXBlbmRlbmN5LCBkMjogRGVwZW5kZW5jeSkge1xuICByZXR1cm4gc3BlY09mKGQxKS5sb2NhbGVDb21wYXJlKHNwZWNPZihkMikpO1xuXG4gIGZ1bmN0aW9uIHNwZWNPZihkZXA6IERlcGVuZGVuY3kpIHtcbiAgICBsZXQgc3BlYyA9IGRlcC50eXBlICsgXCI6XCIgKyBkZXAubmFtZTtcbiAgICBpZiAoZGVwLnZlcnNpb24pIHtcbiAgICAgIHNwZWMgKz0gXCJAXCIgKyBkZXAudmVyc2lvbjtcbiAgICB9XG4gICAgcmV0dXJuIHNwZWM7XG4gIH1cbn1cblxuZXhwb3J0IGludGVyZmFjZSBEZXBzTWFuaWZlc3Qge1xuICAvKipcbiAgICogQWxsIGRlcGVuZGVuY2llcyBvZiB0aGlzIG1vZHVsZS5cbiAgICovXG4gIHJlYWRvbmx5IGRlcGVuZGVuY2llczogRGVwZW5kZW5jeVtdO1xufVxuXG4vKipcbiAqIENvb3JkaW5hdGVzIG9mIHRoZSBkZXBlbmRlbmN5IChuYW1lIGFuZCB2ZXJzaW9uKS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBEZXBlbmRlbmN5Q29vcmRpbmF0ZXMge1xuICAvKipcbiAgICogVGhlIHBhY2thZ2UgbWFuYWdlciBuYW1lIG9mIHRoZSBkZXBlbmRlbmN5IChlLmcuIGBsZWZ0cGFkYCBmb3IgbnBtKS5cbiAgICpcbiAgICogTk9URTogRm9yIHBhY2thZ2UgbWFuYWdlcnMgdGhhdCB1c2UgY29tcGxleCBjb29yZGluYXRlcyAobGlrZSBNYXZlbiksIHdlXG4gICAqIHdpbGwgY29kaWZ5IGl0IGludG8gYSBzdHJpbmcgc29tZWhvdy5cbiAgICovXG4gIHJlYWRvbmx5IG5hbWU6IHN0cmluZztcblxuICAvKipcbiAgICogU2VtYW50aWMgdmVyc2lvbiB2ZXJzaW9uIHJlcXVpcmVtZW50LlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIHJlcXVpcmVtZW50IGlzIG1hbmFnZWQgYnkgdGhlIHBhY2thZ2UgbWFuYWdlciAoZS5nLiBucG0veWFybikuXG4gICAqL1xuICByZWFkb25seSB2ZXJzaW9uPzogc3RyaW5nO1xufVxuXG4vKipcbiAqIFJlcHJlc2VudHMgYSBwcm9qZWN0IGRlcGVuZGVuY3kuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgRGVwZW5kZW5jeSBleHRlbmRzIERlcGVuZGVuY3lDb29yZGluYXRlcyB7XG4gIC8qKlxuICAgKiBXaGljaCB0eXBlIG9mIGRlcGVuZGVuY3kgdGhpcyBpcyAocnVudGltZSwgYnVpbGQtdGltZSwgZXRjKS5cbiAgICovXG4gIHJlYWRvbmx5IHR5cGU6IERlcGVuZGVuY3lUeXBlO1xuXG4gIC8qKlxuICAgKiBBZGRpdGlvbmFsIEpTT04gbWV0YWRhdGEgYXNzb2NpYXRlZCB3aXRoIHRoZSBkZXBlbmRlbmN5IChwYWNrYWdlIG1hbmFnZXJcbiAgICogc3BlY2lmaWMpLlxuICAgKiBAZGVmYXVsdCB7fVxuICAgKi9cbiAgcmVhZG9ubHkgbWV0YWRhdGE/OiB7IFtrZXk6IHN0cmluZ106IGFueSB9O1xufVxuXG4vKipcbiAqIFR5cGUgb2YgZGVwZW5kZW5jeS5cbiAqL1xuZXhwb3J0IGVudW0gRGVwZW5kZW5jeVR5cGUge1xuICAvKipcbiAgICogVGhlIGRlcGVuZGVuY3kgaXMgcmVxdWlyZWQgZm9yIHRoZSBwcm9ncmFtL2xpYnJhcnkgZHVyaW5nIHJ1bnRpbWUuXG4gICAqL1xuICBSVU5USU1FID0gXCJydW50aW1lXCIsXG5cbiAgLyoqXG4gICAqIFRoZSBkZXBlbmRlbmN5IGlzIHJlcXVpcmVkIGF0IHJ1bnRpbWUgYnV0IGV4cGVjdGVkIHRvIGJlIGluc3RhbGxlZCBieSB0aGVcbiAgICogY29uc3VtZXIuXG4gICAqL1xuICBQRUVSID0gXCJwZWVyXCIsXG5cbiAgLyoqXG4gICAqIFRoZSBkZXBlbmRlbmN5IGlzIGJ1bmRsZWQgYW5kIHNoaXBwZWQgd2l0aCB0aGUgbW9kdWxlLCBzbyBjb25zdW1lcnMgYXJlIG5vdFxuICAgKiByZXF1aXJlZCB0byBpbnN0YWxsIGl0LlxuICAgKi9cbiAgQlVORExFRCA9IFwiYnVuZGxlZFwiLFxuXG4gIC8qKlxuICAgKiBUaGUgZGVwZW5kZW5jeSBpcyByZXF1aXJlZCB0byBydW4gdGhlIGBidWlsZGAgdGFzay5cbiAgICovXG4gIEJVSUxEID0gXCJidWlsZFwiLFxuXG4gIC8qKlxuICAgKiBUaGUgZGVwZW5kZW5jeSBpcyByZXF1aXJlZCB0byBydW4gdGhlIGB0ZXN0YCB0YXNrLlxuICAgKi9cbiAgVEVTVCA9IFwidGVzdFwiLFxuXG4gIC8qKlxuICAgKiBUaGUgZGVwZW5kZW5jeSBpcyByZXF1aXJlZCBmb3IgZGV2ZWxvcG1lbnQgKGUuZy4gSURFIHBsdWdpbnMpLlxuICAgKi9cbiAgREVWRU5WID0gXCJkZXZlbnZcIixcblxuICAvKipcbiAgICogVHJhbnNpZW50IGRlcGVuZGVuY3kgdGhhdCBuZWVkcyB0byBiZSBvdmVyd3JpdHRlbi5cbiAgICpcbiAgICogQXZhaWxhYmxlIGZvciBOb2RlIHBhY2thZ2VzXG4gICAqL1xuICBPVkVSUklERSA9IFwib3ZlcnJpZGVcIixcblxuICAvKipcbiAgICogQW4gb3B0aW9uYWwgZGVwZW5kZW5jeSB0aGF0IG1heSBiZSB1c2VkIGF0IHJ1bnRpbWUgaWYgYXZhaWxhYmxlLCBidXQgaXMgbm90IHJlcXVpcmVkLlxuICAgKiBJdCBpcyBleHBlY3RlZCB0byBiZSBpbnN0YWxsZWQgYnkgdGhlIGNvbnN1bWVyLlxuICAgKi9cbiAgT1BUSU9OQUwgPSBcIm9wdGlvbmFsXCIsXG59XG4iXX0=