UNPKG

projen

Version:

CDK for software projects

138 lines • 20.6 kB
"use strict"; var _a; Object.defineProperty(exports, "__esModule", { value: true }); exports.Uv = void 0; const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti"); const component_1 = require("../component"); const uv_config_1 = require("./uv-config"); const dependencies_1 = require("../dependencies"); const task_runtime_1 = require("../task-runtime"); const util_1 = require("../util"); const pyproject_toml_file_1 = require("./pyproject-toml-file"); /** * Manage project dependencies, virtual environments, and packaging through uv. */ class Uv extends component_1.Component { constructor(scope, options) { super(scope); const requiresPython = options.project?.requiresPython ?? ">=3.12,<4.0"; this.venvPython = options.pythonExec ?? requiresPython; this.installTask = this.project.addTask("install", { description: "Install dependencies and update lockfile", exec: "uv sync && uv lock", }); this.installCiTask = this.project.addTask("install:ci", { description: "Install dependencies with frozen lockfile", exec: "uv sync", }); this.project.tasks.addEnvironment("VIRTUAL_ENV", ".venv"); this.project.tasks.addEnvironment("PATH", "$(echo .venv/bin:$PATH)"); this.project.packageTask.exec("uv build"); this.publishTestTask = this.project.addTask("publish:test", { description: "Uploads the package against a test PyPI endpoint.", exec: "uv publish --index testpypi", }); this.publishTask = this.project.addTask("publish", { description: "Uploads the package to PyPI.", exec: "uv publish", }); this.file = new pyproject_toml_file_1.PyprojectTomlFile(this.project, { project: { name: options.project?.name ?? this.project.name, requiresPython, ...options.project, dependencies: (() => [ ...(options?.project?.dependencies ?? []), ...this.synthDependencies(), ]), }, dependencyGroups: (() => this.synthDependencyGroups()), buildSystem: options.buildSystem, tool: { uv: (0, uv_config_1.toJson_UvConfiguration)(options.uv), }, }); } /** Formats dependencies in UV style. */ formatDependency(dep) { const name = dep.name; const version = dep.version; if (!version || version === "*") { return name; } // Translate caret (^) to Python compatible constraints if (version.startsWith("^")) { const cleanVersion = version.slice(1); const [major] = cleanVersion.split("."); const nextMajor = Number(major) + 1; return `${name}>=${cleanVersion},<${nextMajor}.0.0`; } // Translate tilde (~) to compatible release clause per PEP 440 if (version.startsWith("~")) { const cleanVersion = version.slice(1); // Only keep major.minor for tilde if possible const [major, minor = "0", patch = "0"] = cleanVersion.split("."); const nextMinor = Number(minor) + 1; return `${name}>=${major}.${minor}.${patch},<${major}.${nextMinor}.0`; } // Otherwise treat as an exact version return `${name}==${version}`; } getDependencies(dependencyTypes) { return (this.project.deps.all .filter((pkg) => dependencyTypes.includes(pkg.type) && pkg.name !== "python") // remove duplicate versions of the same dependency .filter((dep, index, self) => index === self.findIndex((d) => d.name === dep.name)) .map((pkg) => this.formatDependency(pkg))); } synthDependencies() { return this.getDependencies([dependencies_1.DependencyType.RUNTIME]); } synthDependencyGroups() { const devDeps = this.getDependencies([ dependencies_1.DependencyType.DEVENV, dependencies_1.DependencyType.TEST, ]); if (devDeps) { return { dev: devDeps }; } else { return undefined; } } addDependency(spec) { this.project.deps.addDependency(spec, dependencies_1.DependencyType.RUNTIME); } addDevDependency(spec) { this.project.deps.addDependency(spec, dependencies_1.DependencyType.DEVENV); } setupEnvironment() { const result = (0, util_1.execOrUndefined)("which uv", { cwd: this.project.outdir, }); if (!result) { this.project.logger.info("Unable to setup an environment since uv is not installed. Please install uv (https://github.com/astral-sh/uv) or use a different component for managing environments."); return; } // Create venv with the specific Python version // this will install the requested python version if needed (0, util_1.exec)(`uv venv --python "${this.venvPython}" --clear .venv`, { cwd: this.project.outdir, }); this.project.logger.info(`Environment successfully created in .venv directory with Python ${this.venvPython}.`); } installDependencies() { this.project.logger.info("Installing dependencies..."); const runtime = new task_runtime_1.TaskRuntime(this.project.outdir); if (this.file.changed) { runtime.runTask(this.installTask.name); } else { runtime.runTask(this.installCiTask.name); } } } exports.Uv = Uv; _a = JSII_RTTI_SYMBOL_1; Uv[_a] = { fqn: "projen.python.Uv", version: "0.99.19" }; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXYuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvcHl0aG9uL3V2LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBSUEsNENBQXlDO0FBQ3pDLDJDQUFzRTtBQUN0RSxrREFBNkQ7QUFFN0Qsa0RBQThDO0FBQzlDLGtDQUFnRDtBQUVoRCwrREFBMEQ7QUF5QjFEOztHQUVHO0FBQ0gsTUFBYSxFQUNYLFNBQVEscUJBQVM7SUFjakIsWUFBWSxLQUFpQixFQUFFLE9BQWtCO1FBQy9DLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUViLE1BQU0sY0FBYyxHQUFHLE9BQU8sQ0FBQyxPQUFPLEVBQUUsY0FBYyxJQUFJLGFBQWEsQ0FBQztRQUN4RSxJQUFJLENBQUMsVUFBVSxHQUFHLE9BQU8sQ0FBQyxVQUFVLElBQUksY0FBYyxDQUFDO1FBRXZELElBQUksQ0FBQyxXQUFXLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsU0FBUyxFQUFFO1lBQ2pELFdBQVcsRUFBRSwwQ0FBMEM7WUFDdkQsSUFBSSxFQUFFLG9CQUFvQjtTQUMzQixDQUFDLENBQUM7UUFFSCxJQUFJLENBQUMsYUFBYSxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLFlBQVksRUFBRTtZQUN0RCxXQUFXLEVBQUUsMkNBQTJDO1lBQ3hELElBQUksRUFBRSxTQUFTO1NBQ2hCLENBQUMsQ0FBQztRQUVILElBQUksQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLGNBQWMsQ0FBQyxhQUFhLEVBQUUsT0FBTyxDQUFDLENBQUM7UUFDMUQsSUFBSSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsY0FBYyxDQUFDLE1BQU0sRUFBRSx5QkFBeUIsQ0FBQyxDQUFDO1FBRXJFLElBQUksQ0FBQyxPQUFPLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQztRQUUxQyxJQUFJLENBQUMsZUFBZSxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLGNBQWMsRUFBRTtZQUMxRCxXQUFXLEVBQUUsbURBQW1EO1lBQ2hFLElBQUksRUFBRSw2QkFBNkI7U0FDcEMsQ0FBQyxDQUFDO1FBRUgsSUFBSSxDQUFDLFdBQVcsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxTQUFTLEVBQUU7WUFDakQsV0FBVyxFQUFFLDhCQUE4QjtZQUMzQyxJQUFJLEVBQUUsWUFBWTtTQUNuQixDQUFDLENBQUM7UUFFSCxJQUFJLENBQUMsSUFBSSxHQUFHLElBQUksdUNBQWlCLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRTtZQUM5QyxPQUFPLEVBQUU7Z0JBQ1AsSUFBSSxFQUFFLE9BQU8sQ0FBQyxPQUFPLEVBQUUsSUFBSSxJQUFJLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSTtnQkFDaEQsY0FBYztnQkFDZCxHQUFHLE9BQU8sQ0FBQyxPQUFPO2dCQUNsQixZQUFZLEVBQUUsQ0FBQyxHQUFHLEVBQUUsQ0FBQztvQkFDbkIsR0FBRyxDQUFDLE9BQU8sRUFBRSxPQUFPLEVBQUUsWUFBWSxJQUFJLEVBQUUsQ0FBQztvQkFDekMsR0FBRyxJQUFJLENBQUMsaUJBQWlCLEVBQUU7aUJBQzVCLENBQVE7YUFDVjtZQUNELGdCQUFnQixFQUFFLENBQUMsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLHFCQUFxQixFQUFFLENBQVE7WUFDN0QsV0FBVyxFQUFFLE9BQU8sQ0FBQyxXQUFXO1lBQ2hDLElBQUksRUFBRTtnQkFDSixFQUFFLEVBQUUsSUFBQSxrQ0FBc0IsRUFBQyxPQUFPLENBQUMsRUFBRSxDQUFDO2FBQ3ZDO1NBQ0YsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVELHdDQUF3QztJQUNoQyxnQkFBZ0IsQ0FBQyxHQUFlO1FBQ3RDLE1BQU0sSUFBSSxHQUFHLEdBQUcsQ0FBQyxJQUFJLENBQUM7UUFDdEIsTUFBTSxPQUFPLEdBQUcsR0FBRyxDQUFDLE9BQU8sQ0FBQztRQUU1QixJQUFJLENBQUMsT0FBTyxJQUFJLE9BQU8sS0FBSyxHQUFHLEVBQUUsQ0FBQztZQUNoQyxPQUFPLElBQUksQ0FBQztRQUNkLENBQUM7UUFFRCx1REFBdUQ7UUFDdkQsSUFBSSxPQUFPLENBQUMsVUFBVSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUM7WUFDNUIsTUFBTSxZQUFZLEdBQUcsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUN0QyxNQUFNLENBQUMsS0FBSyxDQUFDLEdBQUcsWUFBWSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQztZQUN4QyxNQUFNLFNBQVMsR0FBRyxNQUFNLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1lBQ3BDLE9BQU8sR0FBRyxJQUFJLEtBQUssWUFBWSxLQUFLLFNBQVMsTUFBTSxDQUFDO1FBQ3RELENBQUM7UUFFRCwrREFBK0Q7UUFDL0QsSUFBSSxPQUFPLENBQUMsVUFBVSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUM7WUFDNUIsTUFBTSxZQUFZLEdBQUcsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUV0Qyw4Q0FBOEM7WUFDOUMsTUFBTSxDQUFDLEtBQUssRUFBRSxLQUFLLEdBQUcsR0FBRyxFQUFFLEtBQUssR0FBRyxHQUFHLENBQUMsR0FBRyxZQUFZLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1lBQ2xFLE1BQU0sU0FBUyxHQUFHLE1BQU0sQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUM7WUFDcEMsT0FBTyxHQUFHLElBQUksS0FBSyxLQUFLLElBQUksS0FBSyxJQUFJLEtBQUssS0FBSyxLQUFLLElBQUksU0FBUyxJQUFJLENBQUM7UUFDeEUsQ0FBQztRQUVELHNDQUFzQztRQUN0QyxPQUFPLEdBQUcsSUFBSSxLQUFLLE9BQU8sRUFBRSxDQUFDO0lBQy9CLENBQUM7SUFFTyxlQUFlLENBQUMsZUFBaUM7UUFDdkQsT0FBTyxDQUNMLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLEdBQUc7YUFDbEIsTUFBTSxDQUNMLENBQUMsR0FBRyxFQUFFLEVBQUUsQ0FBQyxlQUFlLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsSUFBSSxHQUFHLENBQUMsSUFBSSxLQUFLLFFBQVEsQ0FDckU7WUFDRCxtREFBbUQ7YUFDbEQsTUFBTSxDQUNMLENBQUMsR0FBRyxFQUFFLEtBQUssRUFBRSxJQUFJLEVBQUUsRUFBRSxDQUNuQixLQUFLLEtBQUssSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLElBQUksS0FBSyxHQUFHLENBQUMsSUFBSSxDQUFDLENBQ3ZEO2FBQ0EsR0FBRyxDQUFDLENBQUMsR0FBRyxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FDNUMsQ0FBQztJQUNKLENBQUM7SUFFTyxpQkFBaUI7UUFDdkIsT0FBTyxJQUFJLENBQUMsZUFBZSxDQUFDLENBQUMsNkJBQWMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDO0lBQ3hELENBQUM7SUFFTyxxQkFBcUI7UUFDM0IsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLGVBQWUsQ0FBQztZQUNuQyw2QkFBYyxDQUFDLE1BQU07WUFDckIsNkJBQWMsQ0FBQyxJQUFJO1NBQ3BCLENBQUMsQ0FBQztRQUVILElBQUksT0FBTyxFQUFFLENBQUM7WUFDWixPQUFPLEVBQUUsR0FBRyxFQUFFLE9BQU8sRUFBRSxDQUFDO1FBQzFCLENBQUM7YUFBTSxDQUFDO1lBQ04sT0FBTyxTQUFTLENBQUM7UUFDbkIsQ0FBQztJQUNILENBQUM7SUFFTSxhQUFhLENBQUMsSUFBWTtRQUMvQixJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsSUFBSSxFQUFFLDZCQUFjLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDaEUsQ0FBQztJQUVNLGdCQUFnQixDQUFDLElBQVk7UUFDbEMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsYUFBYSxDQUFDLElBQUksRUFBRSw2QkFBYyxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQy9ELENBQUM7SUFFTSxnQkFBZ0I7UUFDckIsTUFBTSxNQUFNLEdBQUcsSUFBQSxzQkFBZSxFQUFDLFVBQVUsRUFBRTtZQUN6QyxHQUFHLEVBQUUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNO1NBQ3pCLENBQUMsQ0FBQztRQUNILElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztZQUNaLElBQUksQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLElBQUksQ0FDdEIsdUtBQXVLLENBQ3hLLENBQUM7WUFDRixPQUFPO1FBQ1QsQ0FBQztRQUVELCtDQUErQztRQUMvQywyREFBMkQ7UUFDM0QsSUFBQSxXQUFJLEVBQUMscUJBQXFCLElBQUksQ0FBQyxVQUFVLGlCQUFpQixFQUFFO1lBQzFELEdBQUcsRUFBRSxJQUFJLENBQUMsT0FBTyxDQUFDLE1BQU07U0FDekIsQ0FBQyxDQUFDO1FBQ0gsSUFBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUN0QixtRUFBbUUsSUFBSSxDQUFDLFVBQVUsR0FBRyxDQUN0RixDQUFDO0lBQ0osQ0FBQztJQUVNLG1CQUFtQjtRQUN4QixJQUFJLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsNEJBQTRCLENBQUMsQ0FBQztRQUN2RCxNQUFNLE9BQU8sR0FBRyxJQUFJLDBCQUFXLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUNyRCxJQUFJLElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUM7WUFDdEIsT0FBTyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ3pDLENBQUM7YUFBTSxDQUFDO1lBQ04sT0FBTyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsYUFBYSxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQzNDLENBQUM7SUFDSCxDQUFDOztBQXBLSCxnQkFxS0MiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBJQ29uc3RydWN0IH0gZnJvbSBcImNvbnN0cnVjdHNcIjtcbmltcG9ydCB7IElQeXRob25EZXBzIH0gZnJvbSBcIi4vcHl0aG9uLWRlcHNcIjtcbmltcG9ydCB7IElQeXRob25FbnYgfSBmcm9tIFwiLi9weXRob24tZW52XCI7XG5pbXBvcnQgeyBJUHl0aG9uUGFja2FnaW5nIH0gZnJvbSBcIi4vcHl0aG9uLXBhY2thZ2luZ1wiO1xuaW1wb3J0IHsgQ29tcG9uZW50IH0gZnJvbSBcIi4uL2NvbXBvbmVudFwiO1xuaW1wb3J0IHsgdG9Kc29uX1V2Q29uZmlndXJhdGlvbiwgVXZDb25maWd1cmF0aW9uIH0gZnJvbSBcIi4vdXYtY29uZmlnXCI7XG5pbXBvcnQgeyBEZXBlbmRlbmN5LCBEZXBlbmRlbmN5VHlwZSB9IGZyb20gXCIuLi9kZXBlbmRlbmNpZXNcIjtcbmltcG9ydCB7IFRhc2sgfSBmcm9tIFwiLi4vdGFza1wiO1xuaW1wb3J0IHsgVGFza1J1bnRpbWUgfSBmcm9tIFwiLi4vdGFzay1ydW50aW1lXCI7XG5pbXBvcnQgeyBleGVjLCBleGVjT3JVbmRlZmluZWQgfSBmcm9tIFwiLi4vdXRpbFwiO1xuaW1wb3J0IHsgQnVpbGRTeXN0ZW0sIFB5cHJvamVjdFRvbWxQcm9qZWN0IH0gZnJvbSBcIi4vcHlwcm9qZWN0LXRvbWxcIjtcbmltcG9ydCB7IFB5cHJvamVjdFRvbWxGaWxlIH0gZnJvbSBcIi4vcHlwcm9qZWN0LXRvbWwtZmlsZVwiO1xuaW1wb3J0IHsgUHl0aG9uRXhlY3V0YWJsZU9wdGlvbnMgfSBmcm9tIFwiLi9weXRob24tcHJvamVjdFwiO1xuXG4vKipcbiAqIE9wdGlvbnMgZm9yIFVWIHByb2plY3RcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBVdk9wdGlvbnMgZXh0ZW5kcyBQeXRob25FeGVjdXRhYmxlT3B0aW9ucyB7XG4gIC8qKlxuICAgKiBUaGUgcHJvamVjdCdzIGJhc2ljIG1ldGFkYXRhIGNvbmZpZ3VyYXRpb24uXG4gICAqL1xuICByZWFkb25seSBwcm9qZWN0PzogUHlwcm9qZWN0VG9tbFByb2plY3Q7XG5cbiAgLyoqXG4gICAqIERlY2xhcmVzIGFueSBQeXRob24gbGV2ZWwgZGVwZW5kZW5jaWVzIHRoYXQgbXVzdCBiZSBpbnN0YWxsZWQgaW4gb3JkZXIgdG8gcnVuIHRoZSBwcm9qZWN04oCZcyBidWlsZCBzeXN0ZW0gc3VjY2Vzc2Z1bGx5LlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIG5vIGJ1aWxkIHN5c3RlbVxuICAgKi9cbiAgcmVhZG9ubHkgYnVpbGRTeXN0ZW0/OiBCdWlsZFN5c3RlbTtcblxuICAvKipcbiAgICogVGhlIGNvbmZpZ3VyYXRpb24gYW5kIG1ldGFkYXRhIGZvciB1di5cbiAgICovXG4gIHJlYWRvbmx5IHV2PzogVXZDb25maWd1cmF0aW9uO1xufVxuXG4vKipcbiAqIE1hbmFnZSBwcm9qZWN0IGRlcGVuZGVuY2llcywgdmlydHVhbCBlbnZpcm9ubWVudHMsIGFuZCBwYWNrYWdpbmcgdGhyb3VnaCB1di5cbiAqL1xuZXhwb3J0IGNsYXNzIFV2XG4gIGV4dGVuZHMgQ29tcG9uZW50XG4gIGltcGxlbWVudHMgSVB5dGhvbkRlcHMsIElQeXRob25FbnYsIElQeXRob25QYWNrYWdpbmdcbntcbiAgLyoqXG4gICAqIFRoZSBgcHlwcm9qZWN0LnRvbWxgIGZpbGVcbiAgICovXG4gIHB1YmxpYyByZWFkb25seSBmaWxlOiBQeXByb2plY3RUb21sRmlsZTtcbiAgcHVibGljIHJlYWRvbmx5IGluc3RhbGxUYXNrOiBUYXNrO1xuICBwdWJsaWMgcmVhZG9ubHkgaW5zdGFsbENpVGFzazogVGFzaztcbiAgcHVibGljIHJlYWRvbmx5IHB1Ymxpc2hUYXNrOiBUYXNrO1xuICBwdWJsaWMgcmVhZG9ubHkgcHVibGlzaFRlc3RUYXNrOiBUYXNrO1xuXG4gIHByaXZhdGUgcmVhZG9ubHkgdmVudlB5dGhvbjogc3RyaW5nO1xuXG4gIGNvbnN0cnVjdG9yKHNjb3BlOiBJQ29uc3RydWN0LCBvcHRpb25zOiBVdk9wdGlvbnMpIHtcbiAgICBzdXBlcihzY29wZSk7XG5cbiAgICBjb25zdCByZXF1aXJlc1B5dGhvbiA9IG9wdGlvbnMucHJvamVjdD8ucmVxdWlyZXNQeXRob24gPz8gXCI+PTMuMTIsPDQuMFwiO1xuICAgIHRoaXMudmVudlB5dGhvbiA9IG9wdGlvbnMucHl0aG9uRXhlYyA/PyByZXF1aXJlc1B5dGhvbjtcblxuICAgIHRoaXMuaW5zdGFsbFRhc2sgPSB0aGlzLnByb2plY3QuYWRkVGFzayhcImluc3RhbGxcIiwge1xuICAgICAgZGVzY3JpcHRpb246IFwiSW5zdGFsbCBkZXBlbmRlbmNpZXMgYW5kIHVwZGF0ZSBsb2NrZmlsZVwiLFxuICAgICAgZXhlYzogXCJ1diBzeW5jICYmIHV2IGxvY2tcIixcbiAgICB9KTtcblxuICAgIHRoaXMuaW5zdGFsbENpVGFzayA9IHRoaXMucHJvamVjdC5hZGRUYXNrKFwiaW5zdGFsbDpjaVwiLCB7XG4gICAgICBkZXNjcmlwdGlvbjogXCJJbnN0YWxsIGRlcGVuZGVuY2llcyB3aXRoIGZyb3plbiBsb2NrZmlsZVwiLFxuICAgICAgZXhlYzogXCJ1diBzeW5jXCIsXG4gICAgfSk7XG5cbiAgICB0aGlzLnByb2plY3QudGFza3MuYWRkRW52aXJvbm1lbnQoXCJWSVJUVUFMX0VOVlwiLCBcIi52ZW52XCIpO1xuICAgIHRoaXMucHJvamVjdC50YXNrcy5hZGRFbnZpcm9ubWVudChcIlBBVEhcIiwgXCIkKGVjaG8gLnZlbnYvYmluOiRQQVRIKVwiKTtcblxuICAgIHRoaXMucHJvamVjdC5wYWNrYWdlVGFzay5leGVjKFwidXYgYnVpbGRcIik7XG5cbiAgICB0aGlzLnB1Ymxpc2hUZXN0VGFzayA9IHRoaXMucHJvamVjdC5hZGRUYXNrKFwicHVibGlzaDp0ZXN0XCIsIHtcbiAgICAgIGRlc2NyaXB0aW9uOiBcIlVwbG9hZHMgdGhlIHBhY2thZ2UgYWdhaW5zdCBhIHRlc3QgUHlQSSBlbmRwb2ludC5cIixcbiAgICAgIGV4ZWM6IFwidXYgcHVibGlzaCAtLWluZGV4IHRlc3RweXBpXCIsXG4gICAgfSk7XG5cbiAgICB0aGlzLnB1Ymxpc2hUYXNrID0gdGhpcy5wcm9qZWN0LmFkZFRhc2soXCJwdWJsaXNoXCIsIHtcbiAgICAgIGRlc2NyaXB0aW9uOiBcIlVwbG9hZHMgdGhlIHBhY2thZ2UgdG8gUHlQSS5cIixcbiAgICAgIGV4ZWM6IFwidXYgcHVibGlzaFwiLFxuICAgIH0pO1xuXG4gICAgdGhpcy5maWxlID0gbmV3IFB5cHJvamVjdFRvbWxGaWxlKHRoaXMucHJvamVjdCwge1xuICAgICAgcHJvamVjdDoge1xuICAgICAgICBuYW1lOiBvcHRpb25zLnByb2plY3Q/Lm5hbWUgPz8gdGhpcy5wcm9qZWN0Lm5hbWUsXG4gICAgICAgIHJlcXVpcmVzUHl0aG9uLFxuICAgICAgICAuLi5vcHRpb25zLnByb2plY3QsXG4gICAgICAgIGRlcGVuZGVuY2llczogKCgpID0+IFtcbiAgICAgICAgICAuLi4ob3B0aW9ucz8ucHJvamVjdD8uZGVwZW5kZW5jaWVzID8/IFtdKSxcbiAgICAgICAgICAuLi50aGlzLnN5bnRoRGVwZW5kZW5jaWVzKCksXG4gICAgICAgIF0pIGFzIGFueSxcbiAgICAgIH0sXG4gICAgICBkZXBlbmRlbmN5R3JvdXBzOiAoKCkgPT4gdGhpcy5zeW50aERlcGVuZGVuY3lHcm91cHMoKSkgYXMgYW55LFxuICAgICAgYnVpbGRTeXN0ZW06IG9wdGlvbnMuYnVpbGRTeXN0ZW0sXG4gICAgICB0b29sOiB7XG4gICAgICAgIHV2OiB0b0pzb25fVXZDb25maWd1cmF0aW9uKG9wdGlvbnMudXYpLFxuICAgICAgfSxcbiAgICB9KTtcbiAgfVxuXG4gIC8qKiBGb3JtYXRzIGRlcGVuZGVuY2llcyBpbiBVViBzdHlsZS4gKi9cbiAgcHJpdmF0ZSBmb3JtYXREZXBlbmRlbmN5KGRlcDogRGVwZW5kZW5jeSk6IHN0cmluZyB7XG4gICAgY29uc3QgbmFtZSA9IGRlcC5uYW1lO1xuICAgIGNvbnN0IHZlcnNpb24gPSBkZXAudmVyc2lvbjtcblxuICAgIGlmICghdmVyc2lvbiB8fCB2ZXJzaW9uID09PSBcIipcIikge1xuICAgICAgcmV0dXJuIG5hbWU7XG4gICAgfVxuXG4gICAgLy8gVHJhbnNsYXRlIGNhcmV0ICheKSB0byBQeXRob24gY29tcGF0aWJsZSBjb25zdHJhaW50c1xuICAgIGlmICh2ZXJzaW9uLnN0YXJ0c1dpdGgoXCJeXCIpKSB7XG4gICAgICBjb25zdCBjbGVhblZlcnNpb24gPSB2ZXJzaW9uLnNsaWNlKDEpO1xuICAgICAgY29uc3QgW21ham9yXSA9IGNsZWFuVmVyc2lvbi5zcGxpdChcIi5cIik7XG4gICAgICBjb25zdCBuZXh0TWFqb3IgPSBOdW1iZXIobWFqb3IpICsgMTtcbiAgICAgIHJldHVybiBgJHtuYW1lfT49JHtjbGVhblZlcnNpb259LDwke25leHRNYWpvcn0uMC4wYDtcbiAgICB9XG5cbiAgICAvLyBUcmFuc2xhdGUgdGlsZGUgKH4pIHRvIGNvbXBhdGlibGUgcmVsZWFzZSBjbGF1c2UgcGVyIFBFUCA0NDBcbiAgICBpZiAodmVyc2lvbi5zdGFydHNXaXRoKFwiflwiKSkge1xuICAgICAgY29uc3QgY2xlYW5WZXJzaW9uID0gdmVyc2lvbi5zbGljZSgxKTtcblxuICAgICAgLy8gT25seSBrZWVwIG1ham9yLm1pbm9yIGZvciB0aWxkZSBpZiBwb3NzaWJsZVxuICAgICAgY29uc3QgW21ham9yLCBtaW5vciA9IFwiMFwiLCBwYXRjaCA9IFwiMFwiXSA9IGNsZWFuVmVyc2lvbi5zcGxpdChcIi5cIik7XG4gICAgICBjb25zdCBuZXh0TWlub3IgPSBOdW1iZXIobWlub3IpICsgMTtcbiAgICAgIHJldHVybiBgJHtuYW1lfT49JHttYWpvcn0uJHttaW5vcn0uJHtwYXRjaH0sPCR7bWFqb3J9LiR7bmV4dE1pbm9yfS4wYDtcbiAgICB9XG5cbiAgICAvLyBPdGhlcndpc2UgdHJlYXQgYXMgYW4gZXhhY3QgdmVyc2lvblxuICAgIHJldHVybiBgJHtuYW1lfT09JHt2ZXJzaW9ufWA7XG4gIH1cblxuICBwcml2YXRlIGdldERlcGVuZGVuY2llcyhkZXBlbmRlbmN5VHlwZXM6IERlcGVuZGVuY3lUeXBlW10pOiBzdHJpbmdbXSB7XG4gICAgcmV0dXJuIChcbiAgICAgIHRoaXMucHJvamVjdC5kZXBzLmFsbFxuICAgICAgICAuZmlsdGVyKFxuICAgICAgICAgIChwa2cpID0+IGRlcGVuZGVuY3lUeXBlcy5pbmNsdWRlcyhwa2cudHlwZSkgJiYgcGtnLm5hbWUgIT09IFwicHl0aG9uXCIsXG4gICAgICAgIClcbiAgICAgICAgLy8gcmVtb3ZlIGR1cGxpY2F0ZSB2ZXJzaW9ucyBvZiB0aGUgc2FtZSBkZXBlbmRlbmN5XG4gICAgICAgIC5maWx0ZXIoXG4gICAgICAgICAgKGRlcCwgaW5kZXgsIHNlbGYpID0+XG4gICAgICAgICAgICBpbmRleCA9PT0gc2VsZi5maW5kSW5kZXgoKGQpID0+IGQubmFtZSA9PT0gZGVwLm5hbWUpLFxuICAgICAgICApXG4gICAgICAgIC5tYXAoKHBrZykgPT4gdGhpcy5mb3JtYXREZXBlbmRlbmN5KHBrZykpXG4gICAgKTtcbiAgfVxuXG4gIHByaXZhdGUgc3ludGhEZXBlbmRlbmNpZXMoKTogc3RyaW5nW10ge1xuICAgIHJldHVybiB0aGlzLmdldERlcGVuZGVuY2llcyhbRGVwZW5kZW5jeVR5cGUuUlVOVElNRV0pO1xuICB9XG5cbiAgcHJpdmF0ZSBzeW50aERlcGVuZGVuY3lHcm91cHMoKTogeyBba2V5OiBzdHJpbmddOiBzdHJpbmdbXSB9IHwgdW5kZWZpbmVkIHtcbiAgICBjb25zdCBkZXZEZXBzID0gdGhpcy5nZXREZXBlbmRlbmNpZXMoW1xuICAgICAgRGVwZW5kZW5jeVR5cGUuREVWRU5WLFxuICAgICAgRGVwZW5kZW5jeVR5cGUuVEVTVCxcbiAgICBdKTtcblxuICAgIGlmIChkZXZEZXBzKSB7XG4gICAgICByZXR1cm4geyBkZXY6IGRldkRlcHMgfTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9XG4gIH1cblxuICBwdWJsaWMgYWRkRGVwZW5kZW5jeShzcGVjOiBzdHJpbmcpOiB2b2lkIHtcbiAgICB0aGlzLnByb2plY3QuZGVwcy5hZGREZXBlbmRlbmN5KHNwZWMsIERlcGVuZGVuY3lUeXBlLlJVTlRJTUUpO1xuICB9XG5cbiAgcHVibGljIGFkZERldkRlcGVuZGVuY3koc3BlYzogc3RyaW5nKTogdm9pZCB7XG4gICAgdGhpcy5wcm9qZWN0LmRlcHMuYWRkRGVwZW5kZW5jeShzcGVjLCBEZXBlbmRlbmN5VHlwZS5ERVZFTlYpO1xuICB9XG5cbiAgcHVibGljIHNldHVwRW52aXJvbm1lbnQoKTogdm9pZCB7XG4gICAgY29uc3QgcmVzdWx0ID0gZXhlY09yVW5kZWZpbmVkKFwid2hpY2ggdXZcIiwge1xuICAgICAgY3dkOiB0aGlzLnByb2plY3Qub3V0ZGlyLFxuICAgIH0pO1xuICAgIGlmICghcmVzdWx0KSB7XG4gICAgICB0aGlzLnByb2plY3QubG9nZ2VyLmluZm8oXG4gICAgICAgIFwiVW5hYmxlIHRvIHNldHVwIGFuIGVudmlyb25tZW50IHNpbmNlIHV2IGlzIG5vdCBpbnN0YWxsZWQuIFBsZWFzZSBpbnN0YWxsIHV2IChodHRwczovL2dpdGh1Yi5jb20vYXN0cmFsLXNoL3V2KSBvciB1c2UgYSBkaWZmZXJlbnQgY29tcG9uZW50IGZvciBtYW5hZ2luZyBlbnZpcm9ubWVudHMuXCIsXG4gICAgICApO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIENyZWF0ZSB2ZW52IHdpdGggdGhlIHNwZWNpZmljIFB5dGhvbiB2ZXJzaW9uXG4gICAgLy8gdGhpcyB3aWxsIGluc3RhbGwgdGhlIHJlcXVlc3RlZCBweXRob24gdmVyc2lvbiBpZiBuZWVkZWRcbiAgICBleGVjKGB1diB2ZW52IC0tcHl0aG9uIFwiJHt0aGlzLnZlbnZQeXRob259XCIgLS1jbGVhciAudmVudmAsIHtcbiAgICAgIGN3ZDogdGhpcy5wcm9qZWN0Lm91dGRpcixcbiAgICB9KTtcbiAgICB0aGlzLnByb2plY3QubG9nZ2VyLmluZm8oXG4gICAgICBgRW52aXJvbm1lbnQgc3VjY2Vzc2Z1bGx5IGNyZWF0ZWQgaW4gLnZlbnYgZGlyZWN0b3J5IHdpdGggUHl0aG9uICR7dGhpcy52ZW52UHl0aG9ufS5gLFxuICAgICk7XG4gIH1cblxuICBwdWJsaWMgaW5zdGFsbERlcGVuZGVuY2llcygpOiB2b2lkIHtcbiAgICB0aGlzLnByb2plY3QubG9nZ2VyLmluZm8oXCJJbnN0YWxsaW5nIGRlcGVuZGVuY2llcy4uLlwiKTtcbiAgICBjb25zdCBydW50aW1lID0gbmV3IFRhc2tSdW50aW1lKHRoaXMucHJvamVjdC5vdXRkaXIpO1xuICAgIGlmICh0aGlzLmZpbGUuY2hhbmdlZCkge1xuICAgICAgcnVudGltZS5ydW5UYXNrKHRoaXMuaW5zdGFsbFRhc2submFtZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJ1bnRpbWUucnVuVGFzayh0aGlzLmluc3RhbGxDaVRhc2submFtZSk7XG4gICAgfVxuICB9XG59XG4iXX0=