UNPKG

aws-delivlib

Version:

A fabulous library for defining continuous pipelines for building, testing and releasing code libraries.

242 lines • 33 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.get = exports.download = exports.jsonGet = exports.PyPIArtifactIntegrity = exports.NpmArtifactIntegrity = exports.RepositoryIntegrity = exports.ArtifactIntegrity = void 0; const child_process_1 = require("child_process"); const os = __importStar(require("os")); const path = __importStar(require("path")); // eslint-disable-next-line import/no-extraneous-dependencies const adm_zip_1 = __importDefault(require("adm-zip")); // eslint-disable-next-line import/no-extraneous-dependencies const follow = __importStar(require("follow-redirects")); // eslint-disable-next-line import/no-extraneous-dependencies const fs = __importStar(require("fs-extra")); // eslint-disable-next-line import/no-extraneous-dependencies const jstream = __importStar(require("JSONStream")); // eslint-disable-next-line import/no-extraneous-dependencies const tar = __importStar(require("tar")); /** * Integrity class for validating a local artifact against its published counterpart. * * Implementations differ based on the package manager in question. */ class ArtifactIntegrity { /** * Validate a local artifact against its published counterpart. * * @param localArtifactDir The directory of the local artifact. Must contain exactly one file with the appropriate extenstion. */ async validate(localArtifactDir) { const artifactPath = this.findOne(localArtifactDir); const name = this.constructor.name; this.log(`Validating ${artifactPath}`); const workdir = fs.mkdtempSync(path.join(os.tmpdir(), 'integrity-check')); try { const downloaded = path.join(workdir, `${name}.downloaded`); const remote = path.join(workdir, `${name}.remote`); const local = path.join(workdir, `${name}.local`); // parse the artifact name into a package. const pkg = this.parseArtifactName(path.basename(artifactPath)); fs.mkdirSync(remote); fs.mkdirSync(local); // download the package this.log(`Downloading ${pkg.name}@${pkg.version} to ${downloaded}`); await this.download(pkg, downloaded); // extract the downlaoded package this.log(`Extracting remote artifact from ${downloaded} to ${remote}`); await this.extract(downloaded, remote); // extract the local artfiact this.log(`Extracting local artifact from ${artifactPath} to ${local}`); await this.extract(artifactPath, local); this.log(`Comparing ${local} <> ${remote}`); try { (0, child_process_1.execSync)(`diff ${local} ${remote}`, { stdio: ['ignore', 'inherit', 'inherit'] }); } catch (error) { throw new Error(`${name} validation failed`); } this.log('Success'); } finally { fs.removeSync(workdir); } } log(message) { console.log(`${this.constructor.name} | ${message} `); } findOne(dir) { const files = fs.readdirSync(dir).filter(f => f.endsWith(this.ext)); if (files.length === 0) { throw new Error(`No files found in ${dir} with extension ${this.ext}`); } const [first, ...rest] = files; if (rest.length > 0) { throw new Error(`Multiple files found in ${dir} with extension ${this.ext}: ${first}, ${rest.join(', ')}`); } return path.join(dir, first); } } exports.ArtifactIntegrity = ArtifactIntegrity; /** * Integrity class for validating the artifacts produced by this repository against their published counterparts. */ class RepositoryIntegrity { constructor(props) { this.props = props; } /** * Validate the artifacts of this repo against its published counterpart. */ async validate() { // note that run 'release' by default to preserve the version number. // this won't do a bump since the commit we are on is already tagged. const artifacts = this.props.repository.pack(this.props.packCommand ?? 'npx projen release'); let integrity = undefined; for (const artifact of artifacts) { switch (artifact.lang) { case 'js': integrity = new NpmArtifactIntegrity(); break; case 'python': integrity = new PyPIArtifactIntegrity(); break; case 'java': case 'dotnet': case 'go': // we don't have integrity checks for these // artifacts yet. break; default: throw new Error(`Unsupported artifact language: ${artifact.lang}`); } if (integrity) { await integrity.validate(artifact.directory); } } console.log('Validation done'); } } exports.RepositoryIntegrity = RepositoryIntegrity; /** * NpmIntegrity is able to perform integrity checks against packages stored on npmjs.com */ class NpmArtifactIntegrity extends ArtifactIntegrity { constructor() { super(...arguments); this.ext = 'tgz'; } async download(pkg, target) { const tarballUrl = await jsonGet(`https://registry.npmjs.org/${encodeURIComponent(pkg.name)}/${encodeURIComponent(pkg.version)}`, ['dist', 'tarball']); await download(tarballUrl, target); } async extract(file, targetDir) { return tar.x({ cwd: targetDir, file: file, strip: 1 }); } parseArtifactName(artifactName) { // cdk8s@1.0.0-beta.59.jsii.tgz const jsiiArtifact = /(.*)@(.*)\.jsii./; // npm artifact: cdk8s-cli-1.0.0-beta59.tgz // yarn artifact: cdk8s-cli-v1.0.0-beta59.tgz (add a 'v' before the version) const npmOrYarnArtifact = /(.*)-v?(\d.*).(tgz|tar.gz)/; const regex = artifactName.includes('.jsii.') ? jsiiArtifact : npmOrYarnArtifact; const match = artifactName.match(regex); if (!match) { throw new Error(`Unable to parse artifact: ${artifactName}`); } return { name: match[1], version: match[2] }; } } exports.NpmArtifactIntegrity = NpmArtifactIntegrity; /** * PyPIIntegiry is able to perform integiry checks against packages stored on pypi.org */ class PyPIArtifactIntegrity extends ArtifactIntegrity { constructor() { super(...arguments); this.ext = 'whl'; } async download(pkg, target) { const files = await jsonGet(`https://pypi.org/pypi/${encodeURIComponent(pkg.name)}/json`, ['releases', pkg.version]); const wheels = files.filter((f) => f.url.endsWith('whl')).map((f) => f.url); if (wheels.length === 0) { throw new Error(`No wheels found for package ${pkg.name}-${pkg.version}`); } if (wheels.length > 1) { throw new Error(`Multiple wheels found for package ${pkg.name}-${pkg.version}: ${wheels.join(',')}`); } await download(wheels[0], target); } async extract(artifact, target) { const zip = new adm_zip_1.default(artifact); return zip.extractAllTo(target); } parseArtifactName(artifactName) { // cdk8s-1.0.0b63-py3-none-any.whl const regex = /(.*)-v?(\d.*)-py.*.whl/; const match = artifactName.match(regex); if (!match) { throw new Error(`Unable to parse artifact: ${artifactName}`); } return { name: match[1], version: match[2] }; } } exports.PyPIArtifactIntegrity = PyPIArtifactIntegrity; function jsonGet(url, jsonPath) { return get(url, (res, ok, ko) => { const json = jstream.parse(jsonPath); json.once('data', ok); json.once('error', ko); res.pipe(json, { end: true }); }, { headers: { 'Accept': 'application/json', 'Accept-Encoding': 'identity' } }); } exports.jsonGet = jsonGet; async function download(url, targetFile) { return get(url, (res, ok, ko) => { const file = fs.createWriteStream(targetFile); file.on('finish', ok); file.on('error', ko); res.pipe(file, { end: true }); }); } exports.download = download; async function get(url, handler, options = {}) { return new Promise((ok, ko) => { const request = follow.https.get(url, options, (res) => { if (res.statusCode !== 200) { const error = new Error(`GET ${url} - HTTP ${res.statusCode} (${res.statusMessage})`); Error.captureStackTrace(error); return ko(error); } res.once('error', ko); handler(res, ok, ko); }); request.on('error', ko); }); } exports.get = get; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW50ZWdyaXR5LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiaW50ZWdyaXR5LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUEsaURBQXlDO0FBRXpDLHVDQUF5QjtBQUN6QiwyQ0FBNkI7QUFDN0IsNkRBQTZEO0FBQzdELHNEQUE2QjtBQUM3Qiw2REFBNkQ7QUFDN0QseURBQTJDO0FBQzNDLDZEQUE2RDtBQUM3RCw2Q0FBK0I7QUFDL0IsNkRBQTZEO0FBQzdELG9EQUFzQztBQUN0Qyw2REFBNkQ7QUFDN0QseUNBQTJCO0FBb0IzQjs7OztHQUlHO0FBQ0gsTUFBc0IsaUJBQWlCO0lBK0JyQzs7OztPQUlHO0lBQ0ksS0FBSyxDQUFDLFFBQVEsQ0FBQyxnQkFBd0I7UUFFNUMsTUFBTSxZQUFZLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDO1FBQ3BELE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDO1FBRW5DLElBQUksQ0FBQyxHQUFHLENBQUMsY0FBYyxZQUFZLEVBQUUsQ0FBQyxDQUFDO1FBQ3ZDLE1BQU0sT0FBTyxHQUFHLEVBQUUsQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsTUFBTSxFQUFFLEVBQUUsaUJBQWlCLENBQUMsQ0FBQyxDQUFDO1FBRTFFLElBQUk7WUFDRixNQUFNLFVBQVUsR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxHQUFHLElBQUksYUFBYSxDQUFDLENBQUM7WUFDNUQsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsR0FBRyxJQUFJLFNBQVMsQ0FBQyxDQUFDO1lBQ3BELE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTyxFQUFFLEdBQUcsSUFBSSxRQUFRLENBQUMsQ0FBQztZQUVsRCwwQ0FBMEM7WUFDMUMsTUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLGlCQUFpQixDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQztZQUVoRSxFQUFFLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1lBQ3JCLEVBQUUsQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLENBQUM7WUFFcEIsdUJBQXVCO1lBQ3ZCLElBQUksQ0FBQyxHQUFHLENBQUMsZUFBZSxHQUFHLENBQUMsSUFBSSxJQUFJLEdBQUcsQ0FBQyxPQUFPLE9BQU8sVUFBVSxFQUFFLENBQUMsQ0FBQztZQUNwRSxNQUFNLElBQUksQ0FBQyxRQUFRLENBQUMsR0FBRyxFQUFFLFVBQVUsQ0FBQyxDQUFDO1lBRXJDLGlDQUFpQztZQUNqQyxJQUFJLENBQUMsR0FBRyxDQUFDLG1DQUFtQyxVQUFVLE9BQU8sTUFBTSxFQUFFLENBQUMsQ0FBQztZQUN2RSxNQUFNLElBQUksQ0FBQyxPQUFPLENBQUMsVUFBVSxFQUFFLE1BQU0sQ0FBQyxDQUFDO1lBRXZDLDZCQUE2QjtZQUM3QixJQUFJLENBQUMsR0FBRyxDQUFDLGtDQUFrQyxZQUFZLE9BQU8sS0FBSyxFQUFFLENBQUMsQ0FBQztZQUN2RSxNQUFNLElBQUksQ0FBQyxPQUFPLENBQUMsWUFBWSxFQUFFLEtBQUssQ0FBQyxDQUFDO1lBRXhDLElBQUksQ0FBQyxHQUFHLENBQUMsYUFBYSxLQUFLLE9BQU8sTUFBTSxFQUFFLENBQUMsQ0FBQztZQUM1QyxJQUFJO2dCQUNGLElBQUEsd0JBQVEsRUFBQyxRQUFRLEtBQUssSUFBSSxNQUFNLEVBQUUsRUFBRSxFQUFFLEtBQUssRUFBRSxDQUFDLFFBQVEsRUFBRSxTQUFTLEVBQUUsU0FBUyxDQUFDLEVBQUUsQ0FBQyxDQUFDO2FBQ2xGO1lBQUMsT0FBTyxLQUFLLEVBQUU7Z0JBQ2QsTUFBTSxJQUFJLEtBQUssQ0FBQyxHQUFHLElBQUksb0JBQW9CLENBQUMsQ0FBQzthQUM5QztZQUNELElBQUksQ0FBQyxHQUFHLENBQUMsU0FBUyxDQUFDLENBQUM7U0FFckI7Z0JBQVM7WUFDUixFQUFFLENBQUMsVUFBVSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1NBQ3hCO0lBRUgsQ0FBQztJQUVTLEdBQUcsQ0FBQyxPQUFlO1FBQzNCLE9BQU8sQ0FBQyxHQUFHLENBQUMsR0FBRyxJQUFJLENBQUMsV0FBVyxDQUFDLElBQUksTUFBTSxPQUFPLEdBQUcsQ0FBQyxDQUFDO0lBQ3hELENBQUM7SUFFTyxPQUFPLENBQUMsR0FBVztRQUN6QixNQUFNLEtBQUssR0FBRyxFQUFFLENBQUMsV0FBVyxDQUFDLEdBQUcsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7UUFDcEUsSUFBSSxLQUFLLENBQUMsTUFBTSxLQUFLLENBQUMsRUFBRTtZQUN0QixNQUFNLElBQUksS0FBSyxDQUFDLHFCQUFxQixHQUFHLG1CQUFtQixJQUFJLENBQUMsR0FBRyxFQUFFLENBQUMsQ0FBQztTQUN4RTtRQUNELE1BQU0sQ0FBQyxLQUFLLEVBQUUsR0FBRyxJQUFJLENBQUMsR0FBRyxLQUFLLENBQUM7UUFDL0IsSUFBSSxJQUFJLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRTtZQUNuQixNQUFNLElBQUksS0FBSyxDQUFDLDJCQUEyQixHQUFHLG1CQUFtQixJQUFJLENBQUMsR0FBRyxLQUFLLEtBQUssS0FBSyxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQztTQUM1RztRQUNELE9BQU8sSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLEVBQUUsS0FBSyxDQUFDLENBQUM7SUFDL0IsQ0FBQztDQUVGO0FBakdELDhDQWlHQztBQW1CRDs7R0FFRztBQUNILE1BQWEsbUJBQW1CO0lBRTlCLFlBQW9DLEtBQStCO1FBQS9CLFVBQUssR0FBTCxLQUFLLENBQTBCO0lBQUcsQ0FBQztJQUV2RTs7T0FFRztJQUNJLEtBQUssQ0FBQyxRQUFRO1FBRW5CLHFFQUFxRTtRQUNyRSxxRUFBcUU7UUFDckUsTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsV0FBVyxJQUFJLG9CQUFvQixDQUFDLENBQUM7UUFFN0YsSUFBSSxTQUFTLEdBQUcsU0FBUyxDQUFDO1FBQzFCLEtBQUssTUFBTSxRQUFRLElBQUksU0FBUyxFQUFFO1lBQ2hDLFFBQVEsUUFBUSxDQUFDLElBQUksRUFBRTtnQkFDckIsS0FBSyxJQUFJO29CQUNQLFNBQVMsR0FBRyxJQUFJLG9CQUFvQixFQUFFLENBQUM7b0JBQ3ZDLE1BQU07Z0JBQ1IsS0FBSyxRQUFRO29CQUNYLFNBQVMsR0FBRyxJQUFJLHFCQUFxQixFQUFFLENBQUM7b0JBQ3hDLE1BQU07Z0JBQ1IsS0FBSyxNQUFNLENBQUM7Z0JBQ1osS0FBSyxRQUFRLENBQUM7Z0JBQ2QsS0FBSyxJQUFJO29CQUNQLDJDQUEyQztvQkFDM0MsaUJBQWlCO29CQUNqQixNQUFNO2dCQUNSO29CQUNFLE1BQU0sSUFBSSxLQUFLLENBQUMsa0NBQWtDLFFBQVEsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDO2FBQ3RFO1lBQ0QsSUFBSSxTQUFTLEVBQUU7Z0JBQ2IsTUFBTSxTQUFTLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxTQUFTLENBQUMsQ0FBQzthQUM5QztTQUNGO1FBQ0QsT0FBTyxDQUFDLEdBQUcsQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDO0lBQ2pDLENBQUM7Q0FFRjtBQXRDRCxrREFzQ0M7QUFFRDs7R0FFRztBQUNILE1BQWEsb0JBQXFCLFNBQVEsaUJBQWlCO0lBQTNEOztRQUVxQixRQUFHLEdBQUcsS0FBSyxDQUFDO0lBK0JqQyxDQUFDO0lBN0JXLEtBQUssQ0FBQyxRQUFRLENBQUMsR0FBcUIsRUFBRSxNQUFjO1FBQzVELE1BQU0sVUFBVSxHQUFHLE1BQU0sT0FBTyxDQUFDLDhCQUE4QixrQkFBa0IsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLElBQUksa0JBQWtCLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxFQUFFLEVBQUUsQ0FBQyxNQUFNLEVBQUUsU0FBUyxDQUFDLENBQUMsQ0FBQztRQUN2SixNQUFNLFFBQVEsQ0FBQyxVQUFVLEVBQUUsTUFBTSxDQUFDLENBQUM7SUFDckMsQ0FBQztJQUVNLEtBQUssQ0FBQyxPQUFPLENBQUMsSUFBWSxFQUFFLFNBQWlCO1FBQ2xELE9BQU8sR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLEdBQUcsRUFBRSxTQUFTLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUN6RCxDQUFDO0lBRVMsaUJBQWlCLENBQUMsWUFBb0I7UUFFOUMsK0JBQStCO1FBQy9CLE1BQU0sWUFBWSxHQUFHLGtCQUFrQixDQUFDO1FBRXhDLDJDQUEyQztRQUMzQyw0RUFBNEU7UUFDNUUsTUFBTSxpQkFBaUIsR0FBRyw0QkFBNEIsQ0FBQztRQUV2RCxNQUFNLEtBQUssR0FBRyxZQUFZLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQyxZQUFZLENBQUMsQ0FBQyxDQUFDLGlCQUFpQixDQUFDO1FBRWpGLE1BQU0sS0FBSyxHQUFHLFlBQVksQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDeEMsSUFBSSxDQUFDLEtBQUssRUFBRTtZQUNWLE1BQU0sSUFBSSxLQUFLLENBQUMsNkJBQTZCLFlBQVksRUFBRSxDQUFDLENBQUM7U0FDOUQ7UUFFRCxPQUFPLEVBQUUsSUFBSSxFQUFFLEtBQUssQ0FBQyxDQUFDLENBQUMsRUFBRSxPQUFPLEVBQUUsS0FBSyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7SUFFL0MsQ0FBQztDQUVGO0FBakNELG9EQWlDQztBQUVEOztHQUVHO0FBQ0gsTUFBYSxxQkFBc0IsU0FBUSxpQkFBaUI7SUFBNUQ7O1FBRXFCLFFBQUcsR0FBRyxLQUFLLENBQUM7SUFxQ2pDLENBQUM7SUFuQ1csS0FBSyxDQUFDLFFBQVEsQ0FBQyxHQUFxQixFQUFFLE1BQWM7UUFFNUQsTUFBTSxLQUFLLEdBQUcsTUFBTSxPQUFPLENBQUMseUJBQXlCLGtCQUFrQixDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUMsVUFBVSxFQUFFLEdBQUcsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDO1FBQ3JILE1BQU0sTUFBTSxHQUFhLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFNLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBTSxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUM7UUFFaEcsSUFBSSxNQUFNLENBQUMsTUFBTSxLQUFLLENBQUMsRUFBRTtZQUN2QixNQUFNLElBQUksS0FBSyxDQUFDLCtCQUErQixHQUFHLENBQUMsSUFBSSxJQUFJLEdBQUcsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDO1NBQzNFO1FBRUQsSUFBSSxNQUFNLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRTtZQUNyQixNQUFNLElBQUksS0FBSyxDQUFDLHFDQUFxQyxHQUFHLENBQUMsSUFBSSxJQUFJLEdBQUcsQ0FBQyxPQUFPLEtBQUssTUFBTSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUM7U0FDdEc7UUFFRCxNQUFNLFFBQVEsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUUsTUFBTSxDQUFDLENBQUM7SUFDcEMsQ0FBQztJQUVNLEtBQUssQ0FBQyxPQUFPLENBQUMsUUFBZ0IsRUFBRSxNQUFjO1FBQ25ELE1BQU0sR0FBRyxHQUFHLElBQUksaUJBQU0sQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUNqQyxPQUFPLEdBQUcsQ0FBQyxZQUFZLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDbEMsQ0FBQztJQUVTLGlCQUFpQixDQUFDLFlBQW9CO1FBRTlDLGtDQUFrQztRQUNsQyxNQUFNLEtBQUssR0FBRyx3QkFBd0IsQ0FBQztRQUV2QyxNQUFNLEtBQUssR0FBRyxZQUFZLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQ3hDLElBQUksQ0FBQyxLQUFLLEVBQUU7WUFDVixNQUFNLElBQUksS0FBSyxDQUFDLDZCQUE2QixZQUFZLEVBQUUsQ0FBQyxDQUFDO1NBQzlEO1FBRUQsT0FBTyxFQUFFLElBQUksRUFBRSxLQUFLLENBQUMsQ0FBQyxDQUFDLEVBQUUsT0FBTyxFQUFFLEtBQUssQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO0lBRS9DLENBQUM7Q0FFRjtBQXZDRCxzREF1Q0M7QUFFRCxTQUFnQixPQUFPLENBQUMsR0FBVyxFQUFFLFFBQW1CO0lBQ3RELE9BQU8sR0FBRyxDQUFDLEdBQUcsRUFBRSxDQUFDLEdBQUcsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUU7UUFDOUIsTUFBTSxJQUFJLEdBQUcsT0FBTyxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUNyQyxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxFQUFFLENBQUMsQ0FBQztRQUN0QixJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxFQUFFLENBQUMsQ0FBQztRQUV2QixHQUFHLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxFQUFFLEdBQUcsRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDO0lBQ2hDLENBQUMsRUFBRSxFQUFFLE9BQU8sRUFBRSxFQUFFLFFBQVEsRUFBRSxrQkFBa0IsRUFBRSxpQkFBaUIsRUFBRSxVQUFVLEVBQUUsRUFBRSxDQUFDLENBQUM7QUFDbkYsQ0FBQztBQVJELDBCQVFDO0FBRU0sS0FBSyxVQUFVLFFBQVEsQ0FBQyxHQUFXLEVBQUUsVUFBa0I7SUFDNUQsT0FBTyxHQUFHLENBQUMsR0FBRyxFQUFFLENBQUMsR0FBRyxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRTtRQUM5QixNQUFNLElBQUksR0FBRyxFQUFFLENBQUMsaUJBQWlCLENBQUMsVUFBVSxDQUFDLENBQUM7UUFDOUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxRQUFRLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFDdEIsSUFBSSxDQUFDLEVBQUUsQ0FBQyxPQUFPLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFDckIsR0FBRyxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsRUFBRSxHQUFHLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQztJQUNoQyxDQUFDLENBQUMsQ0FBQztBQUNMLENBQUM7QUFQRCw0QkFPQztBQUVNLEtBQUssVUFBVSxHQUFHLENBQ3ZCLEdBQVcsRUFDWCxPQUErRixFQUMvRixVQUEwQixFQUFFO0lBRTVCLE9BQU8sSUFBSSxPQUFPLENBQUMsQ0FBQyxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUU7UUFDNUIsTUFBTSxPQUFPLEdBQUcsTUFBTSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLE9BQU8sRUFBRSxDQUFDLEdBQW9CLEVBQUUsRUFBRTtZQUN0RSxJQUFJLEdBQUcsQ0FBQyxVQUFVLEtBQUssR0FBRyxFQUFFO2dCQUMxQixNQUFNLEtBQUssR0FBRyxJQUFJLEtBQUssQ0FBQyxPQUFPLEdBQUcsV0FBVyxHQUFHLENBQUMsVUFBVSxLQUFLLEdBQUcsQ0FBQyxhQUFhLEdBQUcsQ0FBQyxDQUFDO2dCQUN0RixLQUFLLENBQUMsaUJBQWlCLENBQUMsS0FBSyxDQUFDLENBQUM7Z0JBQy9CLE9BQU8sRUFBRSxDQUFDLEtBQUssQ0FBQyxDQUFDO2FBQ2xCO1lBQ0QsR0FBRyxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsRUFBRSxDQUFDLENBQUM7WUFDdEIsT0FBTyxDQUFDLEdBQUcsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFDdkIsQ0FBQyxDQUFDLENBQUM7UUFDSCxPQUFPLENBQUMsRUFBRSxDQUFDLE9BQU8sRUFBRSxFQUFFLENBQUMsQ0FBQztJQUMxQixDQUFDLENBQUMsQ0FBQztBQUVMLENBQUM7QUFsQkQsa0JBa0JDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgZXhlY1N5bmMgfSBmcm9tICdjaGlsZF9wcm9jZXNzJztcbmltcG9ydCB0eXBlIHsgUmVxdWVzdE9wdGlvbnMsIEluY29taW5nTWVzc2FnZSB9IGZyb20gJ2h0dHAnO1xuaW1wb3J0ICogYXMgb3MgZnJvbSAnb3MnO1xuaW1wb3J0ICogYXMgcGF0aCBmcm9tICdwYXRoJztcbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBpbXBvcnQvbm8tZXh0cmFuZW91cy1kZXBlbmRlbmNpZXNcbmltcG9ydCBBZG1aaXAgZnJvbSAnYWRtLXppcCc7XG4vLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgaW1wb3J0L25vLWV4dHJhbmVvdXMtZGVwZW5kZW5jaWVzXG5pbXBvcnQgKiBhcyBmb2xsb3cgZnJvbSAnZm9sbG93LXJlZGlyZWN0cyc7XG4vLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgaW1wb3J0L25vLWV4dHJhbmVvdXMtZGVwZW5kZW5jaWVzXG5pbXBvcnQgKiBhcyBmcyBmcm9tICdmcy1leHRyYSc7XG4vLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgaW1wb3J0L25vLWV4dHJhbmVvdXMtZGVwZW5kZW5jaWVzXG5pbXBvcnQgKiBhcyBqc3RyZWFtIGZyb20gJ0pTT05TdHJlYW0nO1xuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0ICogYXMgdGFyIGZyb20gJ3Rhcic7XG5pbXBvcnQgeyBSZXBvc2l0b3J5IH0gZnJvbSAnLi9yZXBvc2l0b3J5JztcblxuXG4vKipcbiAqIFB1Ymxpc2hlZCBwYWNrYWdlLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFB1Ymxpc2hlZFBhY2thZ2Uge1xuXG4gIC8qKlxuICAgKiBOYW1lIG9mIHRoZSBwYWNrYWdlIGFzIHN0b3JlZCBpbiB0aGUgcGFja2FnZSBtYW5hZ2VyLlxuICAgKi9cbiAgcmVhZG9ubHkgbmFtZTogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBWZXJzaW9uIG9mIHRoZSBwYWNrYWdlIGFzIHN0b3JlZCBpbiB0aGUgcGFja2FnZSBtYW5hZ2VyLlxuICAgKi9cbiAgcmVhZG9ubHkgdmVyc2lvbjogc3RyaW5nO1xufVxuXG4vKipcbiAqIEludGVncml0eSBjbGFzcyBmb3IgdmFsaWRhdGluZyBhIGxvY2FsIGFydGlmYWN0IGFnYWluc3QgaXRzIHB1Ymxpc2hlZCBjb3VudGVycGFydC5cbiAqXG4gKiBJbXBsZW1lbnRhdGlvbnMgZGlmZmVyIGJhc2VkIG9uIHRoZSBwYWNrYWdlIG1hbmFnZXIgaW4gcXVlc3Rpb24uXG4gKi9cbmV4cG9ydCBhYnN0cmFjdCBjbGFzcyBBcnRpZmFjdEludGVncml0eSB7XG5cbiAgLyoqXG4gICAqIFRoZSBmaWxlIGV4dGVuc3Rpb24gb2YgYXJ0aWZhY3RzIHByb2R1Y2VkIGZvciB0aGlzIGNoZWNrLiAoZS5nICd3aGwnKVxuICAgKi9cbiAgcHJvdGVjdGVkIGFic3RyYWN0IHJlYWRvbmx5IGV4dDogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBEb3dubG9hZCBhIHBhY2thZ2UgdG8gdGhlIHRhcmdldCBmaWxlLlxuICAgKlxuICAgKiBAcGFyYW0gcGtnIFRoZSBwYWNrYWdlIHRvIGRvd25sb2FkLlxuICAgKiBAcGFyYW0gdGFyZ2V0RmlsZSBUaGUgZmlsZSBwYXRoIHRvIGRvd25sb2FkIHRoZSBwYWNrYWdlIHRvLlxuICAgKi9cbiAgcHJvdGVjdGVkIGFic3RyYWN0IGRvd25sb2FkKHBrZzogUHVibGlzaGVkUGFja2FnZSwgdGFyZ2V0RmlsZTogc3RyaW5nKTogUHJvbWlzZTx2b2lkPjtcblxuICAvKipcbiAgICogRXh0cmFjdCB0aGUgYXJ0aWZhY3QgaW50byB0aGUgdGFyZ2V0IGRpcmVjdG9yeS5cbiAgICpcbiAgICogQHBhcmFtIGFydGlmYWN0IFBhdGggdG8gYW4gYXJ0aWZhY3QgZmlsZS5cbiAgICogQHBhcmFtIHRhcmdldERpciBUaGUgZGlyZWN0b3J5IHRvIGV4dHJhY3QgdG8uIEl0IHdpbGwgZXhpc3QgYnkgdGhlIHRpbWUgdGhpcyBtZXRob2QgaXMgaW52b2tlZC5cbiAgICovXG4gIHByb3RlY3RlZCBhYnN0cmFjdCBleHRyYWN0KGFydGlmYWN0OiBzdHJpbmcsIHRhcmdldERpcjogc3RyaW5nKTogUHJvbWlzZTx2b2lkPjtcblxuICAvKipcbiAgICogUGFyc2UgYSBsb2NhbCBhcnRpZmFjdCBmaWxlIG5hbWUgaW50byBhIHN0cnVjdHVyZWQgcGFja2FnZS5cbiAgICpcbiAgICogQHBhcmFtIGFydGlmYWN0TmFtZSBCYXNlIG5hbWUgb2YgdGhlIGxvY2FsIGFydGlmYWN0IGZpbGUuXG4gICAqIEByZXR1cm5zIFRoZSBwYWNrYWdlIHRoaXMgYXJ0aWZhY3QgY29ycmVsYXRlcyB0by5cbiAgICovXG4gIHByb3RlY3RlZCBhYnN0cmFjdCBwYXJzZUFydGlmYWN0TmFtZShhcnRpZmFjdE5hbWU6IHN0cmluZyk6IFB1Ymxpc2hlZFBhY2thZ2U7XG5cbiAgLyoqXG4gICAqIFZhbGlkYXRlIGEgbG9jYWwgYXJ0aWZhY3QgYWdhaW5zdCBpdHMgcHVibGlzaGVkIGNvdW50ZXJwYXJ0LlxuICAgKlxuICAgKiBAcGFyYW0gbG9jYWxBcnRpZmFjdERpciBUaGUgZGlyZWN0b3J5IG9mIHRoZSBsb2NhbCBhcnRpZmFjdC4gTXVzdCBjb250YWluIGV4YWN0bHkgb25lIGZpbGUgd2l0aCB0aGUgYXBwcm9wcmlhdGUgZXh0ZW5zdGlvbi5cbiAgICovXG4gIHB1YmxpYyBhc3luYyB2YWxpZGF0ZShsb2NhbEFydGlmYWN0RGlyOiBzdHJpbmcpIHtcblxuICAgIGNvbnN0IGFydGlmYWN0UGF0aCA9IHRoaXMuZmluZE9uZShsb2NhbEFydGlmYWN0RGlyKTtcbiAgICBjb25zdCBuYW1lID0gdGhpcy5jb25zdHJ1Y3Rvci5uYW1lO1xuXG4gICAgdGhpcy5sb2coYFZhbGlkYXRpbmcgJHthcnRpZmFjdFBhdGh9YCk7XG4gICAgY29uc3Qgd29ya2RpciA9IGZzLm1rZHRlbXBTeW5jKHBhdGguam9pbihvcy50bXBkaXIoKSwgJ2ludGVncml0eS1jaGVjaycpKTtcblxuICAgIHRyeSB7XG4gICAgICBjb25zdCBkb3dubG9hZGVkID0gcGF0aC5qb2luKHdvcmtkaXIsIGAke25hbWV9LmRvd25sb2FkZWRgKTtcbiAgICAgIGNvbnN0IHJlbW90ZSA9IHBhdGguam9pbih3b3JrZGlyLCBgJHtuYW1lfS5yZW1vdGVgKTtcbiAgICAgIGNvbnN0IGxvY2FsID0gcGF0aC5qb2luKHdvcmtkaXIsIGAke25hbWV9LmxvY2FsYCk7XG5cbiAgICAgIC8vIHBhcnNlIHRoZSBhcnRpZmFjdCBuYW1lIGludG8gYSBwYWNrYWdlLlxuICAgICAgY29uc3QgcGtnID0gdGhpcy5wYXJzZUFydGlmYWN0TmFtZShwYXRoLmJhc2VuYW1lKGFydGlmYWN0UGF0aCkpO1xuXG4gICAgICBmcy5ta2RpclN5bmMocmVtb3RlKTtcbiAgICAgIGZzLm1rZGlyU3luYyhsb2NhbCk7XG5cbiAgICAgIC8vIGRvd25sb2FkIHRoZSBwYWNrYWdlXG4gICAgICB0aGlzLmxvZyhgRG93bmxvYWRpbmcgJHtwa2cubmFtZX1AJHtwa2cudmVyc2lvbn0gdG8gJHtkb3dubG9hZGVkfWApO1xuICAgICAgYXdhaXQgdGhpcy5kb3dubG9hZChwa2csIGRvd25sb2FkZWQpO1xuXG4gICAgICAvLyBleHRyYWN0IHRoZSBkb3dubGFvZGVkIHBhY2thZ2VcbiAgICAgIHRoaXMubG9nKGBFeHRyYWN0aW5nIHJlbW90ZSBhcnRpZmFjdCBmcm9tICR7ZG93bmxvYWRlZH0gdG8gJHtyZW1vdGV9YCk7XG4gICAgICBhd2FpdCB0aGlzLmV4dHJhY3QoZG93bmxvYWRlZCwgcmVtb3RlKTtcblxuICAgICAgLy8gZXh0cmFjdCB0aGUgbG9jYWwgYXJ0ZmlhY3RcbiAgICAgIHRoaXMubG9nKGBFeHRyYWN0aW5nIGxvY2FsIGFydGlmYWN0IGZyb20gJHthcnRpZmFjdFBhdGh9IHRvICR7bG9jYWx9YCk7XG4gICAgICBhd2FpdCB0aGlzLmV4dHJhY3QoYXJ0aWZhY3RQYXRoLCBsb2NhbCk7XG5cbiAgICAgIHRoaXMubG9nKGBDb21wYXJpbmcgJHtsb2NhbH0gPD4gJHtyZW1vdGV9YCk7XG4gICAgICB0cnkge1xuICAgICAgICBleGVjU3luYyhgZGlmZiAke2xvY2FsfSAke3JlbW90ZX1gLCB7IHN0ZGlvOiBbJ2lnbm9yZScsICdpbmhlcml0JywgJ2luaGVyaXQnXSB9KTtcbiAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgJHtuYW1lfSB2YWxpZGF0aW9uIGZhaWxlZGApO1xuICAgICAgfVxuICAgICAgdGhpcy5sb2coJ1N1Y2Nlc3MnKTtcblxuICAgIH0gZmluYWxseSB7XG4gICAgICBmcy5yZW1vdmVTeW5jKHdvcmtkaXIpO1xuICAgIH1cblxuICB9XG5cbiAgcHJvdGVjdGVkIGxvZyhtZXNzYWdlOiBzdHJpbmcpIHtcbiAgICBjb25zb2xlLmxvZyhgJHt0aGlzLmNvbnN0cnVjdG9yLm5hbWV9IHwgJHttZXNzYWdlfSBgKTtcbiAgfVxuXG4gIHByaXZhdGUgZmluZE9uZShkaXI6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgY29uc3QgZmlsZXMgPSBmcy5yZWFkZGlyU3luYyhkaXIpLmZpbHRlcihmID0+IGYuZW5kc1dpdGgodGhpcy5leHQpKTtcbiAgICBpZiAoZmlsZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYE5vIGZpbGVzIGZvdW5kIGluICR7ZGlyfSB3aXRoIGV4dGVuc2lvbiAke3RoaXMuZXh0fWApO1xuICAgIH1cbiAgICBjb25zdCBbZmlyc3QsIC4uLnJlc3RdID0gZmlsZXM7XG4gICAgaWYgKHJlc3QubGVuZ3RoID4gMCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBNdWx0aXBsZSBmaWxlcyBmb3VuZCBpbiAke2Rpcn0gd2l0aCBleHRlbnNpb24gJHt0aGlzLmV4dH06ICR7Zmlyc3R9LCAke3Jlc3Quam9pbignLCAnKX1gKTtcbiAgICB9XG4gICAgcmV0dXJuIHBhdGguam9pbihkaXIsIGZpcnN0KTtcbiAgfVxuXG59XG5cbi8qKlxuICogUHJvcGVydGllcyBmb3IgYFJlcG9zaXRvcnlJbnRlZ3JpdHlgLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFJlcG9zaXRvcnlJbnRlZ3JpdHlQcm9wcyB7XG4gIC8qKlxuICAgKiBSZXBvc2l0b3J5IHRvIHZhbGlkYXRlLlxuICAgKi9cbiAgcmVhZG9ubHkgcmVwb3NpdG9yeTogUmVwb3NpdG9yeTtcblxuICAvKipcbiAgICogVGhlIGNvbW1hbmQgdGhhdCBwcm9kdWNlcyB0aGUgbG9jYWwgYXJ0aWZhY3RzLlxuICAgKlxuICAgKiBAZGVmYXVsdCAnbnB4IHByb2plbiByZWxlYXNlJ1xuICAgKi9cbiAgcmVhZG9ubHkgcGFja0NvbW1hbmQ/OiBzdHJpbmc7XG59XG5cbi8qKlxuICogSW50ZWdyaXR5IGNsYXNzIGZvciB2YWxpZGF0aW5nIHRoZSBhcnRpZmFjdHMgcHJvZHVjZWQgYnkgdGhpcyByZXBvc2l0b3J5IGFnYWluc3QgdGhlaXIgcHVibGlzaGVkIGNvdW50ZXJwYXJ0cy5cbiAqL1xuZXhwb3J0IGNsYXNzIFJlcG9zaXRvcnlJbnRlZ3JpdHkge1xuXG4gIHB1YmxpYyBjb25zdHJ1Y3Rvcihwcml2YXRlIHJlYWRvbmx5IHByb3BzOiBSZXBvc2l0b3J5SW50ZWdyaXR5UHJvcHMpIHt9XG5cbiAgLyoqXG4gICAqIFZhbGlkYXRlIHRoZSBhcnRpZmFjdHMgb2YgdGhpcyByZXBvIGFnYWluc3QgaXRzIHB1Ymxpc2hlZCBjb3VudGVycGFydC5cbiAgICovXG4gIHB1YmxpYyBhc3luYyB2YWxpZGF0ZSgpIHtcblxuICAgIC8vIG5vdGUgdGhhdCBydW4gJ3JlbGVhc2UnIGJ5IGRlZmF1bHQgdG8gcHJlc2VydmUgdGhlIHZlcnNpb24gbnVtYmVyLlxuICAgIC8vIHRoaXMgd29uJ3QgZG8gYSBidW1wIHNpbmNlIHRoZSBjb21taXQgd2UgYXJlIG9uIGlzIGFscmVhZHkgdGFnZ2VkLlxuICAgIGNvbnN0IGFydGlmYWN0cyA9IHRoaXMucHJvcHMucmVwb3NpdG9yeS5wYWNrKHRoaXMucHJvcHMucGFja0NvbW1hbmQgPz8gJ25weCBwcm9qZW4gcmVsZWFzZScpO1xuXG4gICAgbGV0IGludGVncml0eSA9IHVuZGVmaW5lZDtcbiAgICBmb3IgKGNvbnN0IGFydGlmYWN0IG9mIGFydGlmYWN0cykge1xuICAgICAgc3dpdGNoIChhcnRpZmFjdC5sYW5nKSB7XG4gICAgICAgIGNhc2UgJ2pzJzpcbiAgICAgICAgICBpbnRlZ3JpdHkgPSBuZXcgTnBtQXJ0aWZhY3RJbnRlZ3JpdHkoKTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAncHl0aG9uJzpcbiAgICAgICAgICBpbnRlZ3JpdHkgPSBuZXcgUHlQSUFydGlmYWN0SW50ZWdyaXR5KCk7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgJ2phdmEnOlxuICAgICAgICBjYXNlICdkb3RuZXQnOlxuICAgICAgICBjYXNlICdnbyc6XG4gICAgICAgICAgLy8gd2UgZG9uJ3QgaGF2ZSBpbnRlZ3JpdHkgY2hlY2tzIGZvciB0aGVzZVxuICAgICAgICAgIC8vIGFydGlmYWN0cyB5ZXQuXG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBVbnN1cHBvcnRlZCBhcnRpZmFjdCBsYW5ndWFnZTogJHthcnRpZmFjdC5sYW5nfWApO1xuICAgICAgfVxuICAgICAgaWYgKGludGVncml0eSkge1xuICAgICAgICBhd2FpdCBpbnRlZ3JpdHkudmFsaWRhdGUoYXJ0aWZhY3QuZGlyZWN0b3J5KTtcbiAgICAgIH1cbiAgICB9XG4gICAgY29uc29sZS5sb2coJ1ZhbGlkYXRpb24gZG9uZScpO1xuICB9XG5cbn1cblxuLyoqXG4gKiBOcG1JbnRlZ3JpdHkgaXMgYWJsZSB0byBwZXJmb3JtIGludGVncml0eSBjaGVja3MgYWdhaW5zdCBwYWNrYWdlcyBzdG9yZWQgb24gbnBtanMuY29tXG4gKi9cbmV4cG9ydCBjbGFzcyBOcG1BcnRpZmFjdEludGVncml0eSBleHRlbmRzIEFydGlmYWN0SW50ZWdyaXR5IHtcblxuICBwcm90ZWN0ZWQgcmVhZG9ubHkgZXh0ID0gJ3Rneic7XG5cbiAgcHJvdGVjdGVkIGFzeW5jIGRvd25sb2FkKHBrZzogUHVibGlzaGVkUGFja2FnZSwgdGFyZ2V0OiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCB0YXJiYWxsVXJsID0gYXdhaXQganNvbkdldChgaHR0cHM6Ly9yZWdpc3RyeS5ucG1qcy5vcmcvJHtlbmNvZGVVUklDb21wb25lbnQocGtnLm5hbWUpfS8ke2VuY29kZVVSSUNvbXBvbmVudChwa2cudmVyc2lvbil9YCwgWydkaXN0JywgJ3RhcmJhbGwnXSk7XG4gICAgYXdhaXQgZG93bmxvYWQodGFyYmFsbFVybCwgdGFyZ2V0KTtcbiAgfVxuXG4gIHB1YmxpYyBhc3luYyBleHRyYWN0KGZpbGU6IHN0cmluZywgdGFyZ2V0RGlyOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICByZXR1cm4gdGFyLngoeyBjd2Q6IHRhcmdldERpciwgZmlsZTogZmlsZSwgc3RyaXA6IDEgfSk7XG4gIH1cblxuICBwcm90ZWN0ZWQgcGFyc2VBcnRpZmFjdE5hbWUoYXJ0aWZhY3ROYW1lOiBzdHJpbmcpOiBQdWJsaXNoZWRQYWNrYWdlIHtcblxuICAgIC8vIGNkazhzQDEuMC4wLWJldGEuNTkuanNpaS50Z3pcbiAgICBjb25zdCBqc2lpQXJ0aWZhY3QgPSAvKC4qKUAoLiopXFwuanNpaS4vO1xuXG4gICAgLy8gbnBtIGFydGlmYWN0OiBjZGs4cy1jbGktMS4wLjAtYmV0YTU5LnRnelxuICAgIC8vIHlhcm4gYXJ0aWZhY3Q6IGNkazhzLWNsaS12MS4wLjAtYmV0YTU5LnRneiAoYWRkIGEgJ3YnIGJlZm9yZSB0aGUgdmVyc2lvbilcbiAgICBjb25zdCBucG1Pcllhcm5BcnRpZmFjdCA9IC8oLiopLXY/KFxcZC4qKS4odGd6fHRhci5neikvO1xuXG4gICAgY29uc3QgcmVnZXggPSBhcnRpZmFjdE5hbWUuaW5jbHVkZXMoJy5qc2lpLicpID8ganNpaUFydGlmYWN0IDogbnBtT3JZYXJuQXJ0aWZhY3Q7XG5cbiAgICBjb25zdCBtYXRjaCA9IGFydGlmYWN0TmFtZS5tYXRjaChyZWdleCk7XG4gICAgaWYgKCFtYXRjaCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBVbmFibGUgdG8gcGFyc2UgYXJ0aWZhY3Q6ICR7YXJ0aWZhY3ROYW1lfWApO1xuICAgIH1cblxuICAgIHJldHVybiB7IG5hbWU6IG1hdGNoWzFdLCB2ZXJzaW9uOiBtYXRjaFsyXSB9O1xuXG4gIH1cblxufVxuXG4vKipcbiAqIFB5UElJbnRlZ2lyeSBpcyBhYmxlIHRvIHBlcmZvcm0gaW50ZWdpcnkgY2hlY2tzIGFnYWluc3QgcGFja2FnZXMgc3RvcmVkIG9uIHB5cGkub3JnXG4gKi9cbmV4cG9ydCBjbGFzcyBQeVBJQXJ0aWZhY3RJbnRlZ3JpdHkgZXh0ZW5kcyBBcnRpZmFjdEludGVncml0eSB7XG5cbiAgcHJvdGVjdGVkIHJlYWRvbmx5IGV4dCA9ICd3aGwnO1xuXG4gIHByb3RlY3RlZCBhc3luYyBkb3dubG9hZChwa2c6IFB1Ymxpc2hlZFBhY2thZ2UsIHRhcmdldDogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG5cbiAgICBjb25zdCBmaWxlcyA9IGF3YWl0IGpzb25HZXQoYGh0dHBzOi8vcHlwaS5vcmcvcHlwaS8ke2VuY29kZVVSSUNvbXBvbmVudChwa2cubmFtZSl9L2pzb25gLCBbJ3JlbGVhc2VzJywgcGtnLnZlcnNpb25dKTtcbiAgICBjb25zdCB3aGVlbHM6IHN0cmluZ1tdID0gZmlsZXMuZmlsdGVyKChmOiBhbnkpID0+IGYudXJsLmVuZHNXaXRoKCd3aGwnKSkubWFwKChmOiBhbnkpID0+IGYudXJsKTtcblxuICAgIGlmICh3aGVlbHMubGVuZ3RoID09PSAwKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYE5vIHdoZWVscyBmb3VuZCBmb3IgcGFja2FnZSAke3BrZy5uYW1lfS0ke3BrZy52ZXJzaW9ufWApO1xuICAgIH1cblxuICAgIGlmICh3aGVlbHMubGVuZ3RoID4gMSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBNdWx0aXBsZSB3aGVlbHMgZm91bmQgZm9yIHBhY2thZ2UgJHtwa2cubmFtZX0tJHtwa2cudmVyc2lvbn06ICR7d2hlZWxzLmpvaW4oJywnKX1gKTtcbiAgICB9XG5cbiAgICBhd2FpdCBkb3dubG9hZCh3aGVlbHNbMF0sIHRhcmdldCk7XG4gIH1cblxuICBwdWJsaWMgYXN5bmMgZXh0cmFjdChhcnRpZmFjdDogc3RyaW5nLCB0YXJnZXQ6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IHppcCA9IG5ldyBBZG1aaXAoYXJ0aWZhY3QpO1xuICAgIHJldHVybiB6aXAuZXh0cmFjdEFsbFRvKHRhcmdldCk7XG4gIH1cblxuICBwcm90ZWN0ZWQgcGFyc2VBcnRpZmFjdE5hbWUoYXJ0aWZhY3ROYW1lOiBzdHJpbmcpOiBQdWJsaXNoZWRQYWNrYWdlIHtcblxuICAgIC8vIGNkazhzLTEuMC4wYjYzLXB5My1ub25lLWFueS53aGxcbiAgICBjb25zdCByZWdleCA9IC8oLiopLXY/KFxcZC4qKS1weS4qLndobC87XG5cbiAgICBjb25zdCBtYXRjaCA9IGFydGlmYWN0TmFtZS5tYXRjaChyZWdleCk7XG4gICAgaWYgKCFtYXRjaCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBVbmFibGUgdG8gcGFyc2UgYXJ0aWZhY3Q6ICR7YXJ0aWZhY3ROYW1lfWApO1xuICAgIH1cblxuICAgIHJldHVybiB7IG5hbWU6IG1hdGNoWzFdLCB2ZXJzaW9uOiBtYXRjaFsyXSB9O1xuXG4gIH1cblxufVxuXG5leHBvcnQgZnVuY3Rpb24ganNvbkdldCh1cmw6IHN0cmluZywganNvblBhdGg/OiBzdHJpbmdbXSk6IFByb21pc2U8YW55PiB7XG4gIHJldHVybiBnZXQodXJsLCAocmVzLCBvaywga28pID0+IHtcbiAgICBjb25zdCBqc29uID0ganN0cmVhbS5wYXJzZShqc29uUGF0aCk7XG4gICAganNvbi5vbmNlKCdkYXRhJywgb2spO1xuICAgIGpzb24ub25jZSgnZXJyb3InLCBrbyk7XG5cbiAgICByZXMucGlwZShqc29uLCB7IGVuZDogdHJ1ZSB9KTtcbiAgfSwgeyBoZWFkZXJzOiB7ICdBY2NlcHQnOiAnYXBwbGljYXRpb24vanNvbicsICdBY2NlcHQtRW5jb2RpbmcnOiAnaWRlbnRpdHknIH0gfSk7XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBkb3dubG9hZCh1cmw6IHN0cmluZywgdGFyZ2V0RmlsZTogc3RyaW5nKTogUHJvbWlzZTxhbnk+IHtcbiAgcmV0dXJuIGdldCh1cmwsIChyZXMsIG9rLCBrbykgPT4ge1xuICAgIGNvbnN0IGZpbGUgPSBmcy5jcmVhdGVXcml0ZVN0cmVhbSh0YXJnZXRGaWxlKTtcbiAgICBmaWxlLm9uKCdmaW5pc2gnLCBvayk7XG4gICAgZmlsZS5vbignZXJyb3InLCBrbyk7XG4gICAgcmVzLnBpcGUoZmlsZSwgeyBlbmQ6IHRydWUgfSk7XG4gIH0pO1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZ2V0KFxuICB1cmw6IHN0cmluZyxcbiAgaGFuZGxlcjogKHJlczogSW5jb21pbmdNZXNzYWdlLCBvazogKHZhbHVlOiB1bmtub3duKSA9PiB2b2lkLCBrbzogKGVycjogRXJyb3IpID0+IHZvaWQpID0+IHZvaWQsXG4gIG9wdGlvbnM6IFJlcXVlc3RPcHRpb25zID0ge30pIHtcblxuICByZXR1cm4gbmV3IFByb21pc2UoKG9rLCBrbykgPT4ge1xuICAgIGNvbnN0IHJlcXVlc3QgPSBmb2xsb3cuaHR0cHMuZ2V0KHVybCwgb3B0aW9ucywgKHJlczogSW5jb21pbmdNZXNzYWdlKSA9PiB7XG4gICAgICBpZiAocmVzLnN0YXR1c0NvZGUgIT09IDIwMCkge1xuICAgICAgICBjb25zdCBlcnJvciA9IG5ldyBFcnJvcihgR0VUICR7dXJsfSAtIEhUVFAgJHtyZXMuc3RhdHVzQ29kZX0gKCR7cmVzLnN0YXR1c01lc3NhZ2V9KWApO1xuICAgICAgICBFcnJvci5jYXB0dXJlU3RhY2tUcmFjZShlcnJvcik7XG4gICAgICAgIHJldHVybiBrbyhlcnJvcik7XG4gICAgICB9XG4gICAgICByZXMub25jZSgnZXJyb3InLCBrbyk7XG4gICAgICBoYW5kbGVyKHJlcywgb2ssIGtvKTtcbiAgICB9KTtcbiAgICByZXF1ZXN0Lm9uKCdlcnJvcicsIGtvKTtcbiAgfSk7XG5cbn1cbiJdfQ==