UNPKG

jsii-docgen

Version:

generates api docs for jsii modules

343 lines 43.7 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 () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { if (kind === "m") throw new TypeError("Private method is not writable"); if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; }; var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); }; var _Npm_npmCommand; Object.defineProperty(exports, "__esModule", { value: true }); exports.OptionalPeerDepsFilter = exports.Npm = void 0; const child_process_1 = require("child_process"); const fs_1 = require("fs"); const os = __importStar(require("os")); const path_1 = require("path"); const semver_1 = require("semver"); const documentation_1 = require("./documentation"); const errors_1 = require("../../errors"); class Npm { constructor(workingDirectory, logger = console.log, npmCommand) { this.workingDirectory = workingDirectory; this.logger = logger; _Npm_npmCommand.set(this, void 0); __classPrivateFieldSet(this, _Npm_npmCommand, npmCommand, "f"); } /** * Installs the designated package into this repository's working directory. * * @param target the name or path to the package that needs to be installed. * @param force whether to pass `--force` to `npm install`. * * @returns the name of the package that was installed. */ async install(target, force = false) { const commonFlags = [ ...force ? [ // force install, ignoring recommended protections such as platform checks. This is okay // because we are not actually executing the code being installed in this context. '--force', ] : [], // this is critical from a security perspective to prevent // code execution as part of the install command using npm hooks. (e.g postInstall) '--ignore-scripts', // save time by not running audit '--no-audit', // ensures npm does not insert anything in $PATH '--no-bin-links', // don't write or update a package-lock.json file '--no-package-lock', // always produce JSON output '--json', ]; try { assertSuccess(await this.runCommand(await this.npmCommandPath(), [ 'install', JSON.stringify(target), ...commonFlags, // ensures we are installing devDependencies, too. '--include=dev', '--include=peer', '--include=optional', // Make sure we get a `package.json` so we can figure out the actual package name. '--save', ], chunksToObject, { cwd: this.workingDirectory, shell: true, })); const { dependencies } = JSON.parse(await fs_1.promises.readFile((0, path_1.join)(this.workingDirectory, 'package.json'), 'utf-8')); const names = Object.keys(dependencies !== null && dependencies !== void 0 ? dependencies : {}); const name = names.length === 1 ? names[0] : (0, documentation_1.extractPackageName)(target); const optionalPeerDeps = await this.listOptionalPeerDeps(name); if (optionalPeerDeps.length > 0) { assertSuccess(await this.runCommand(await this.npmCommandPath(), [ 'install', ...optionalPeerDeps, ...commonFlags, // Save as optional in the root package.json (courtesy) '--save-optional', ], chunksToObject, { cwd: this.workingDirectory, shell: true, })); } return name; } catch (e) { if (!force && (e instanceof errors_1.NpmError) && e.npmErrorCode === 'EBADPLATFORM') { console.warn('npm install failed with EBADPLATFORM, retrying with --force'); return this.install(target, true); } return Promise.reject(e); } } async listOptionalPeerDeps(target) { var _a; const result = new Array(); const packageJson = JSON.parse(await fs_1.promises.readFile((0, path_1.join)(this.workingDirectory, 'node_modules', target, 'package.json'), 'utf-8')); for (const [name, { optional }] of Object.entries((_a = packageJson.peerDependenciesMeta) !== null && _a !== void 0 ? _a : {})) { if (!optional) { continue; } const version = packageJson.peerDependencies[name]; if (version == null) { continue; } result.push(JSON.stringify(`${name}@${version}`)); } return result; } /** * Obtains the path to the npm command that should be run. This always returns * the path to an npm >= 7, which "correctly" handles peerDependencies. If the * npm version that's available in $PATH satisfies this predicate, this will * simply return `npm`. */ async npmCommandPath() { if (__classPrivateFieldGet(this, _Npm_npmCommand, "f")) { return __classPrivateFieldGet(this, _Npm_npmCommand, "f"); } // Get the platform specific npm command const npm = npmPlatformAwareCommand(); try { // If the npm in $PATH is >= v7, we can use that directly. The // `npm version --json` command returns a JSON object containing the // versions of several components (npm, node, v8, etc...). We are only // interested in the `npm` key here. const { exitCode, stdout } = await this.runCommand(npm, ['version', '--json'], chunksToObject); if (exitCode === 0 && (0, semver_1.major)(stdout.npm) >= 7) { return __classPrivateFieldSet(this, _Npm_npmCommand, npm, "f"); } } catch (e) { this.logger('Could not determine version of npm in $PATH:', e); } // npm@8 is needed so that we also install peerDependencies - they are needed to construct // the full type system. this.logger('The npm in $PATH is not >= v7. Installing npm@8 locally...'); const result = await this.runCommand(npm, ['install', 'npm@8', '--no-package-lock', '--no-save', '--json'], chunksToObject, { cwd: this.workingDirectory, shell: true, }); assertSuccess(result); __classPrivateFieldSet(this, _Npm_npmCommand, (0, path_1.join)(this.workingDirectory, 'node_modules', '.bin', npm), "f"); this.logger(`Done installing npm@8 at ${__classPrivateFieldGet(this, _Npm_npmCommand, "f")}`); return __classPrivateFieldGet(this, _Npm_npmCommand, "f"); } /** * Runs the supplied command with the provided arguments, captures the data * pushed to STDOUT, and "parses" it using `outputTransform` to produce a * result. * * You must consult the `exitCode` of the return value to determine whether * the command was successful or not. Use the `assertSuccess` function to * throw/reject in case the execution was not successful. * * @param command the command to invoke. * @param args arguments to provide to the command. * @param outputTransform the function that will parse STDOUT data. * @param options additional `spawn` options, if necessary. */ async runCommand(command, args, outputTransform, options) { return new Promise((ok, ko) => { // On Windows, spawning a program ending in .cmd or .bat needs to run in a shell // https://nodejs.org/en/blog/vulnerability/april-2024-security-releases-2 const shell = onWindows() && (command.endsWith('.cmd') || command.endsWith('.bat')); const child = (0, child_process_1.spawn)(command, args, { shell, ...options, stdio: ['inherit', 'pipe', 'pipe'] }); const stdout = new Array(); child.stdout.on('data', (chunk) => { stdout.push(Buffer.from(chunk)); }); child.stderr.on('data', (chunk) => { stdout.push(Buffer.from(chunk)); }); child.once('error', ko); child.once('close', (exitCode, signal) => { try { ok({ command: `${command} ${args.join(' ')}`, exitCode, signal, stdout: outputTransform(stdout), }); } catch (error) { ko(error); } }); }); } } exports.Npm = Npm; _Npm_npmCommand = new WeakMap(); /** * A filter to apply when selecting optional peer dependencies, based on how * their version target is specified. */ var OptionalPeerDepsFilter; (function (OptionalPeerDepsFilter) { /** * Ignore all optional peer dependencies when installing. */ OptionalPeerDepsFilter[OptionalPeerDepsFilter["None"] = 0] = "None"; /** * Install only optional peer dependencies specified as a version range, and * ignore those specified as a URL or local path. */ OptionalPeerDepsFilter[OptionalPeerDepsFilter["VersionRange"] = 1] = "VersionRange"; /** * Install all optional peer dependencies regardless of how they are * specified. This requires URL and local-path dependencies to be reachable. */ OptionalPeerDepsFilter[OptionalPeerDepsFilter["All"] = 2] = "All"; })(OptionalPeerDepsFilter || (exports.OptionalPeerDepsFilter = OptionalPeerDepsFilter = {})); /** * Asserts the provided CommandResult corresponds to a command that exited with * code `0`. If that is not the case, this will throw an appropriate error, * either `NpmError` or `NoSpaceLeftOnDevice`. */ function assertSuccess(result) { var _a; const { command, exitCode, signal, stdout } = result; if (exitCode === 0) { return; } if (signal != null) { throw new errors_1.NpmError(`Command "${command}" was killed by ${signal}`, stdout); } if (exitCode === 228 || ((_a = stdout.error) === null || _a === void 0 ? void 0 : _a.code) === 'ENOSPC') { throw new errors_1.NoSpaceLeftOnDevice(`Command "${command}" failed due to insufficient available disk space`); } const { code, detail, summary } = stdout.error; const message = [ `Command "${command}" exited with code ${exitCode}`, summary ? `: ${summary}` : '', detail ? `\n${detail}` : '', // If we have an error, but neither detail nor summary, then we probably // have an actual Error object, so we'll stringify that here... stdout.error && !detail && !summary ? `: ${stdout.error}` : '', ].join(''); if (typeof summary === 'string' && summary.includes('must provide string spec')) { // happens when package.json dependencies don't have a spec. // for example: https://github.com/markusl/cdk-codepipeline-bitbucket-build-result-reporter/blob/v0.0.7/package.json throw new errors_1.UnInstallablePackageError(summary); } // happens when a package has been deleted from npm // for example: sns-app-jsii-component if (!code && !detail && typeof summary === 'string' && summary.includes('Cannot convert undefined or null to object')) { throw new errors_1.UnInstallablePackageError(summary); } switch (code) { case 'E404': // package (or dependency) can't be found on NPM. This can happen if the package depends on a deprecated package (for example). case 'EOVERRIDE': // Package contains some version overrides that conflict. case 'ERESOLVE': // dependency resolution problem requires a manual intervention (most likely...) case 'ENOVERSIONS': // package has been removed from npm throw new errors_1.UnInstallablePackageError(message); default: throw new errors_1.NpmError(message, stdout, code); } } /** * Concatenates the provided chunks into a single Buffer, converts it to a * string using the designated encoding, then JSON-parses it. If any part of * this process results in an error, returns an object that contains the error * and the raw chunks. */ function chunksToObject(chunks, encoding = 'utf-8') { const raw = Buffer.concat(chunks).toString(encoding); try { // npm will sometimes print non json log lines even though --json was requested. // observed these log lines always start with 'npm', so we filter those out. // for example: "npm notice New patch version of npm available! 8.1.0 -> 8.1.3" // for example: "npm ERR! must provide string spec" const onlyJson = raw.split(/[\r\n]+/) // split on any newlines, because npm returns inconsistent newline characters on Windows .filter(l => !l.startsWith('npm')) // Suppress debugger messages, if present... .filter(l => l !== 'Debugger attached.') .filter(l => l !== 'Waiting for the debugger to disconnect...') // Re-join... .join(os.EOL); return JSON.parse(onlyJson); } catch (error) { return { error, raw }; } } /** * Helper to detect if we are running on Windows. */ function onWindows() { return process.platform === 'win32'; } /** * Get the npm binary path depending on the platform. * @returns "npm.cmd" on Windows, otherwise "npm" */ function npmPlatformAwareCommand() { if (onWindows()) { return 'npm.cmd'; } return 'npm'; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiX25wbS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9kb2NnZW4vdmlldy9fbnBtLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBLGlEQUFnRTtBQUNoRSwyQkFBb0M7QUFDcEMsdUNBQXlCO0FBQ3pCLCtCQUE0QjtBQUM1QixtQ0FBK0I7QUFDL0IsbURBQXFEO0FBQ3JELHlDQUF3RjtBQUV4RixNQUFhLEdBQUc7SUFHZCxZQUNtQixnQkFBd0IsRUFDeEIsU0FBUyxPQUFPLENBQUMsR0FBRyxFQUNyQyxVQUFtQjtRQUZGLHFCQUFnQixHQUFoQixnQkFBZ0IsQ0FBUTtRQUN4QixXQUFNLEdBQU4sTUFBTSxDQUFjO1FBSnZDLGtDQUFnQztRQU85Qix1QkFBQSxJQUFJLG1CQUFlLFVBQVUsTUFBQSxDQUFDO0lBQ2hDLENBQUM7SUFFRDs7Ozs7OztPQU9HO0lBQ0ksS0FBSyxDQUFDLE9BQU8sQ0FBQyxNQUFjLEVBQUUsS0FBSyxHQUFHLEtBQUs7UUFDaEQsTUFBTSxXQUFXLEdBQUc7WUFDbEIsR0FBRyxLQUFLO2dCQUNOLENBQUMsQ0FBQztvQkFDQSx3RkFBd0Y7b0JBQ3hGLGtGQUFrRjtvQkFDbEYsU0FBUztpQkFDVjtnQkFDRCxDQUFDLENBQUMsRUFBRTtZQUNOLDBEQUEwRDtZQUMxRCxtRkFBbUY7WUFDbkYsa0JBQWtCO1lBQ2xCLGlDQUFpQztZQUNqQyxZQUFZO1lBQ1osZ0RBQWdEO1lBQ2hELGdCQUFnQjtZQUNoQixpREFBaUQ7WUFDakQsbUJBQW1CO1lBQ25CLDZCQUE2QjtZQUM3QixRQUFRO1NBQ1QsQ0FBQztRQUVGLElBQUksQ0FBQztZQUNILGFBQWEsQ0FBQyxNQUFNLElBQUksQ0FBQyxVQUFVLENBQ2pDLE1BQU0sSUFBSSxDQUFDLGNBQWMsRUFBRSxFQUMzQjtnQkFDRSxTQUFTO2dCQUNULElBQUksQ0FBQyxTQUFTLENBQUMs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YUFDdkMsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxLQUFLLDJDQUEyQyxDQUFDO1lBQy9ELGFBQWE7YUFDWixJQUFJLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQ2hCLE9BQU8sSUFBSSxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUM5QixDQUFDO0lBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztRQUNmLE9BQU8sRUFBRSxLQUFLLEVBQUUsR0FBRyxFQUFFLENBQUM7SUFDeEIsQ0FBQztBQUNILENBQUM7QUFVRDs7R0FFRztBQUNILFNBQVMsU0FBUztJQUNoQixPQUFPLE9BQU8sQ0FBQyxRQUFRLEtBQUssT0FBTyxDQUFDO0FBQ3RDLENBQUM7QUFFRDs7O0dBR0c7QUFDSCxTQUFTLHVCQUF1QjtJQUM5QixJQUFJLFNBQVMsRUFBRSxFQUFFLENBQUM7UUFDaEIsT0FBTyxTQUFTLENBQUM7SUFDbkIsQ0FBQztJQUVELE9BQU8sS0FBSyxDQUFDO0FBQ2YsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IHNwYXduLCBTcGF3bk9wdGlvbnNXaXRob3V0U3RkaW8gfSBmcm9tICdjaGlsZF9wcm9jZXNzJztcbmltcG9ydCB7IHByb21pc2VzIGFzIGZzIH0gZnJvbSAnZnMnO1xuaW1wb3J0ICogYXMgb3MgZnJvbSAnb3MnO1xuaW1wb3J0IHsgam9pbiB9IGZyb20gJ3BhdGgnO1xuaW1wb3J0IHsgbWFqb3IgfSBmcm9tICdzZW12ZXInO1xuaW1wb3J0IHsgZXh0cmFjdFBhY2thZ2VOYW1lIH0gZnJvbSAnLi9kb2N1bWVudGF0aW9uJztcbmltcG9ydCB7IE5vU3BhY2VMZWZ0T25EZXZpY2UsIFVuSW5zdGFsbGFibGVQYWNrYWdlRXJyb3IsIE5wbUVycm9yIH0gZnJvbSAnLi4vLi4vZXJyb3JzJztcblxuZXhwb3J0IGNsYXNzIE5wbSB7XG4gICNucG1Db21tYW5kOiBzdHJpbmcgfCB1bmRlZmluZWQ7XG5cbiAgcHVibGljIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgcmVhZG9ubHkgd29ya2luZ0RpcmVjdG9yeTogc3RyaW5nLFxuICAgIHByaXZhdGUgcmVhZG9ubHkgbG9nZ2VyID0gY29uc29sZS5sb2csXG4gICAgbnBtQ29tbWFuZD86IHN0cmluZyxcbiAgKSB7XG4gICAgdGhpcy4jbnBtQ29tbWFuZCA9IG5wbUNvbW1hbmQ7XG4gIH1cblxuICAvKipcbiAgICogSW5zdGFsbHMgdGhlIGRlc2lnbmF0ZWQgcGFja2FnZSBpbnRvIHRoaXMgcmVwb3NpdG9yeSdzIHdvcmtpbmcgZGlyZWN0b3J5LlxuICAgKlxuICAgKiBAcGFyYW0gdGFyZ2V0IHRoZSBuYW1lIG9yIHBhdGggdG8gdGhlIHBhY2thZ2UgdGhhdCBuZWVkcyB0byBiZSBpbnN0YWxsZWQuXG4gICAqIEBwYXJhbSBmb3JjZSB3aGV0aGVyIHRvIHBhc3MgYC0tZm9yY2VgIHRvIGBucG0gaW5zdGFsbGAuXG4gICAqXG4gICAqIEByZXR1cm5zIHRoZSBuYW1lIG9mIHRoZSBwYWNrYWdlIHRoYXQgd2FzIGluc3RhbGxlZC5cbiAgICovXG4gIHB1YmxpYyBhc3luYyBpbnN0YWxsKHRhcmdldDogc3RyaW5nLCBmb3JjZSA9IGZhbHNlKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICBjb25zdCBjb21tb25GbGFncyA9IFtcbiAgICAgIC4uLmZvcmNlXG4gICAgICAgID8gW1xuICAgICAgICAgIC8vIGZvcmNlIGluc3RhbGwsIGlnbm9yaW5nIHJlY29tbWVuZGVkIHByb3RlY3Rpb25zIHN1Y2ggYXMgcGxhdGZvcm0gY2hlY2tzLiBUaGlzIGlzIG9rYXlcbiAgICAgICAgICAvLyBiZWNhdXNlIHdlIGFyZSBub3QgYWN0dWFsbHkgZXhlY3V0aW5nIHRoZSBjb2RlIGJlaW5nIGluc3RhbGxlZCBpbiB0aGlzIGNvbnRleHQuXG4gICAgICAgICAgJy0tZm9yY2UnLFxuICAgICAgICBdXG4gICAgICAgIDogW10sXG4gICAgICAvLyB0aGlzIGlzIGNyaXRpY2FsIGZyb20gYSBzZWN1cml0eSBwZXJzcGVjdGl2ZSB0byBwcmV2ZW50XG4gICAgICAvLyBjb2RlIGV4ZWN1dGlvbiBhcyBwYXJ0IG9mIHRoZSBpbnN0YWxsIGNvbW1hbmQgdXNpbmcgbnBtIGhvb2tzLiAoZS5nIHBvc3RJbnN0YWxsKVxuICAgICAgJy0taWdub3JlLXNjcmlwdHMnLFxuICAgICAgLy8gc2F2ZSB0aW1lIGJ5IG5vdCBydW5uaW5nIGF1ZGl0XG4gICAgICAnLS1uby1hdWRpdCcsXG4gICAgICAvLyBlbnN1cmVzIG5wbSBkb2VzIG5vdCBpbnNlcnQgYW55dGhpbmcgaW4gJFBBVEhcbiAgICAgICctLW5vLWJpbi1saW5rcycsXG4gICAgICAvLyBkb24ndCB3cml0ZSBvciB1cGRhdGUgYSBwYWNrYWdlLWxvY2suanNvbiBmaWxlXG4gICAgICAnLS1uby1wYWNrYWdlLWxvY2snLFxuICAgICAgLy8gYWx3YXlzIHByb2R1Y2UgSlNPTiBvdXRwdXRcbiAgICAgICctLWpzb24nLFxuICAgIF07XG5cbiAgICB0cnkge1xuICAgICAgYXNzZXJ0U3VjY2Vzcyhhd2FpdCB0aGlzLnJ1bkNvbW1hbmQoXG4gICAgICAgIGF3YWl0IHRoaXMubnBtQ29tbWFuZFBhdGgoKSxcbiAgICAgICAgW1xuICAgICAgICAgICdpbnN0YWxsJyxcbiAgICAgICAgICBKU09OLnN0cmluZ2lmeSh0YXJnZXQpLFxuICAgICAgICAgIC4uLmNvbW1vbkZsYWdzLFxuICAgICAgICAgIC8vIGVuc3VyZXMgd2UgYXJlIGluc3RhbGxpbmcgZGV2RGVwZW5kZW5jaWVzLCB0b28uXG4gICAgICAgICAgJy0taW5jbHVkZT1kZXYnLFxuICAgICAgICAgICctLWluY2x1ZGU9cGVlcicsXG4gICAgICAgICAgJy0taW5jbHVkZT1vcHRpb25hbCcsXG4gICAgICAgICAgLy8gTWFrZSBzdXJlIHdlIGdldCBhIGBwYWNrYWdlLmpzb25gIHNvIHdlIGNhbiBmaWd1cmUgb3V0IHRoZSBhY3R1YWwgcGFja2FnZSBuYW1lLlxuICAgICAgICAgICctLXNhdmUnLFxuICAgICAgICBdLFxuICAgICAgICBjaHVua3NUb09iamVjdCxcbiAgICAgICAge1xuICAgICAgICAgIGN3ZDogdGhpcy53b3JraW5nRGlyZWN0b3J5LFxuICAgICAgICAgIHNoZWxsOiB0cnVlLFxuICAgICAgICB9LFxuICAgICAgKSk7XG5cbiAgICAgIGNvbnN0IHsgZGVwZW5kZW5jaWVzIH0gPSBKU09OLnBhcnNlKGF3YWl0IGZzLnJlYWRGaWxlKGpvaW4odGhpcy53b3JraW5nRGlyZWN0b3J5LCAncGFja2FnZS5qc29uJyksICd1dGYtOCcpKTtcbiAgICAgIGNvbnN0IG5hbWVzID0gT2JqZWN0LmtleXMoZGVwZW5kZW5jaWVzID8/IHt9KTtcbiAgICAgIGNvbnN0IG5hbWUgPSBuYW1lcy5sZW5ndGggPT09IDFcbiAgICAgICAgPyBuYW1lc1swXVxuICAgICAgICA6IGV4dHJhY3RQYWNrYWdlTmFtZSh0YXJnZXQpO1xuXG4gICAgICBjb25zdCBvcHRpb25hbFBlZXJEZXBzID0gYXdhaXQgdGhpcy5saXN0T3B0aW9uYWxQZWVyRGVwcyhuYW1lKTtcbiAgICAgIGlmIChvcHRpb25hbFBlZXJEZXBzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgYXNzZXJ0U3VjY2Vzcyhhd2FpdCB0aGlzLnJ1bkNvbW1hbmQoXG4gICAgICAgICAgYXdhaXQgdGhpcy5ucG1Db21tYW5kUGF0aCgpLFxuICAgICAgICAgIFtcbiAgICAgICAgICAgICdpbnN0YWxsJyxcbiAgICAgICAgICAgIC4uLm9wdGlvbmFsUGVlckRlcHMsXG4gICAgICAgICAgICAuLi5jb21tb25GbGFncyxcbiAgICAgICAgICAgIC8vIFNhdmUgYXMgb3B0aW9uYWwgaW4gdGhlIHJvb3QgcGFja2FnZS5qc29uIChjb3VydGVzeSlcbiAgICAgICAgICAgICctLXNhdmUtb3B0aW9uYWwnLFxuICAgICAgICAgIF0sXG4gICAgICAgICAgY2h1bmtzVG9PYmplY3QsXG4gICAgICAgICAge1xuICAgICAgICAgICAgY3dkOiB0aGlzLndvcmtpbmdEaXJlY3RvcnksXG4gICAgICAgICAgICBzaGVsbDogdHJ1ZSxcbiAgICAgICAgICB9LFxuICAgICAgICApKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIG5hbWU7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgaWYgKCFmb3JjZSAmJiAoZSBpbnN0YW5jZW9mIE5wbUVycm9yKSAmJiBlLm5wbUVycm9yQ29kZSA9PT0gJ0VCQURQTEFURk9STScpIHtcbiAgICAgICAgY29uc29sZS53YXJuKCducG0gaW5zdGFsbCBmYWlsZWQgd2l0aCBFQkFEUExBVEZPUk0sIHJldHJ5aW5nIHdpdGggLS1mb3JjZScpO1xuICAgICAgICByZXR1cm4gdGhpcy5pbnN0YWxsKHRhcmdldCwgdHJ1ZSk7XG4gICAgICB9XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QoZSk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBsaXN0T3B0aW9uYWxQZWVyRGVwcyh0YXJnZXQ6IHN0cmluZyk6IFByb21pc2U8cmVhZG9ubHkgc3RyaW5nW10+IHtcbiAgICBjb25zdCByZXN1bHQgPSBuZXcgQXJyYXk8c3RyaW5nPigpO1xuXG4gICAgY29uc3QgcGFja2FnZUpzb24gPSBKU09OLnBhcnNlKGF3YWl0IGZzLnJlYWRGaWxlKGpvaW4odGhpcy53b3JraW5nRGlyZWN0b3J5LCAnbm9kZV9tb2R1bGVzJywgdGFyZ2V0LCAncGFja2FnZS5qc29uJyksICd1dGYtOCcpKTtcbiAgICBmb3IgKGNvbnN0IFtuYW1lLCB7IG9wdGlvbmFsIH1dIG9mIE9iamVjdC5lbnRyaWVzKHBhY2thZ2VKc29uLnBlZXJEZXBlbmRlbmNpZXNNZXRhID8/IHt9KSBhcyBbc3RyaW5nLCB7IG9wdGlvbmFsOiBib29sZWFuIH1dW10pIHtcbiAgICAgIGlmICghb3B0aW9uYWwpIHtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG4gICAgICBjb25zdCB2ZXJzaW9uID0gcGFja2FnZUpzb24ucGVlckRlcGVuZGVuY2llc1tuYW1lXTtcbiAgICAgIGlmICh2ZXJzaW9uID09IG51bGwpIHtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG4gICAgICByZXN1bHQucHVzaChKU09OLnN0cmluZ2lmeShgJHtuYW1lfUAke3ZlcnNpb259YCkpO1xuICAgIH1cblxuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICAvKipcbiAgICogT2J0YWlucyB0aGUgcGF0aCB0byB0aGUgbnBtIGNvbW1hbmQgdGhhdCBzaG91bGQgYmUgcnVuLiBUaGlzIGFsd2F5cyByZXR1cm5zXG4gICAqIHRoZSBwYXRoIHRvIGFuIG5wbSA+PSA3LCB3aGljaCBcImNvcnJlY3RseVwiIGhhbmRsZXMgcGVlckRlcGVuZGVuY2llcy4gSWYgdGhlXG4gICAqIG5wbSB2ZXJzaW9uIHRoYXQncyBhdmFpbGFibGUgaW4gJFBBVEggc2F0aXNmaWVzIHRoaXMgcHJlZGljYXRlLCB0aGlzIHdpbGxcbiAgICogc2ltcGx5IHJldHVybiBgbnBtYC5cbiAgICovXG4gIHByaXZhdGUgYXN5bmMgbnBtQ29tbWFuZFBhdGgoKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICBpZiAodGhpcy4jbnBtQ29tbWFuZCkge1xuICAgICAgcmV0dXJuIHRoaXMuI25wbUNvbW1hbmQ7XG4gICAgfVxuXG4gICAgLy8gR2V0IHRoZSBwbGF0Zm9ybSBzcGVjaWZpYyBucG0gY29tbWFuZFxuICAgIGNvbnN0IG5wbSA9IG5wbVBsYXRmb3JtQXdhcmVDb21tYW5kKCk7XG5cbiAgICB0cnkge1xuICAgICAgLy8gSWYgdGhlIG5wbSBpbiAkUEFUSCBpcyA+PSB2Nywgd2UgY2FuIHVzZSB0aGF0IGRpcmVjdGx5LiBUaGVcbiAgICAgIC8vIGBucG0gdmVyc2lvbiAtLWpzb25gIGNvbW1hbmQgcmV0dXJucyBhIEpTT04gb2JqZWN0IGNvbnRhaW5pbmcgdGhlXG4gICAgICAvLyB2ZXJzaW9ucyBvZiBzZXZlcmFsIGNvbXBvbmVudHMgKG5wbSwgbm9kZSwgdjgsIGV0Yy4uLikuIFdlIGFyZSBvbmx5XG4gICAgICAvLyBpbnRlcmVzdGVkIGluIHRoZSBgbnBtYCBrZXkgaGVyZS5cbiAgICAgIGNvbnN0IHsgZXhpdENvZGUsIHN0ZG91dCB9ID0gYXdhaXQgdGhpcy5ydW5Db21tYW5kKFxuICAgICAgICBucG0sIFsndmVyc2lvbicsICctLWpzb24nXSxcbiAgICAgICAgY2h1bmtzVG9PYmplY3QsXG4gICAgICApO1xuICAgICAgaWYgKGV4aXRDb2RlID09PSAwICYmIG1ham9yKChzdGRvdXQgYXMgYW55KS5ucG0pID49IDcpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuI25wbUNvbW1hbmQgPSBucG07XG4gICAgICB9XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgdGhpcy5sb2dnZXIoJ0NvdWxkIG5vdCBkZXRlcm1pbmUgdmVyc2lvbiBvZiBucG0gaW4gJFBBVEg6JywgZSk7XG4gICAgfVxuXG4gICAgLy8gbnBtQDggaXMgbmVlZGVkIHNvIHRoYXQgd2UgYWxzbyBpbnN0YWxsIHBlZXJEZXBlbmRlbmNpZXMgLSB0aGV5IGFyZSBuZWVkZWQgdG8gY29uc3RydWN0XG4gICAgLy8gdGhlIGZ1bGwgdHlwZSBzeXN0ZW0uXG4gICAgdGhpcy5sb2dnZXIoJ1RoZSBucG0gaW4gJFBBVEggaXMgbm90ID49IHY3LiBJbnN0YWxsaW5nIG5wbUA4IGxvY2FsbHkuLi4nKTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB0aGlzLnJ1bkNvbW1hbmQoXG4gICAgICBucG0sXG4gICAgICBbJ2luc3RhbGwnLCAnbnBtQDgnLCAnLS1uby1wYWNrYWdlLWxvY2snLCAnLS1uby1zYXZlJywgJy0tanNvbiddLFxuICAgICAgY2h1bmtzVG9PYmplY3QsXG4gICAgICB7XG4gICAgICAgIGN3ZDogdGhpcy53b3JraW5nRGlyZWN0b3J5LFxuICAgICAgICBzaGVsbDogdHJ1ZSxcbiAgICAgIH0sXG4gICAgKTtcbiAgICBhc3NlcnRTdWNjZXNzKHJlc3VsdCk7XG5cbiAgICB0aGlzLiNucG1Db21tYW5kID0gam9pbih0aGlzLndvcmtpbmdEaXJlY3RvcnksICdub2RlX21vZHVsZXMnLCAnLmJpbicsIG5wbSk7XG4gICAgdGhpcy5sb2dnZXIoYERvbmUgaW5zdGFsbGluZyBucG1AOCBhdCAke3RoaXMuI25wbUNvbW1hbmR9YCk7XG4gICAgcmV0dXJuIHRoaXMuI25wbUNvbW1hbmQ7XG4gIH1cblxuICAvKipcbiAgICogUnVucyB0aGUgc3VwcGxpZWQgY29tbWFuZCB3aXRoIHRoZSBwcm92aWRlZCBhcmd1bWVudHMsIGNhcHR1cmVzIHRoZSBkYXRhXG4gICAqIHB1c2hlZCB0byBTVERPVVQsIGFuZCBcInBhcnNlc1wiIGl0IHVzaW5nIGBvdXRwdXRUcmFuc2Zvcm1gIHRvIHByb2R1Y2UgYVxuICAgKiByZXN1bHQuXG4gICAqXG4gICAqIFlvdSBtdXN0IGNvbnN1bHQgdGhlIGBleGl0Q29kZWAgb2YgdGhlIHJldHVybiB2YWx1ZSB0byBkZXRlcm1pbmUgd2hldGhlclxuICAgKiB0aGUgY29tbWFuZCB3YXMgc3VjY2Vzc2Z1bCBvciBub3QuIFVzZSB0aGUgYGFzc2VydFN1Y2Nlc3NgIGZ1bmN0aW9uIHRvXG4gICAqIHRocm93L3JlamVjdCBpbiBjYXNlIHRoZSBleGVjdXRpb24gd2FzIG5vdCBzdWNjZXNzZnVsLlxuICAgKlxuICAgKiBAcGFyYW0gY29tbWFuZCAgICAgICAgIHRoZSBjb21tYW5kIHRvIGludm9rZS5cbiAgICogQHBhcmFtIGFyZ3MgICAgICAgICAgICBhcmd1bWVudHMgdG8gcHJvdmlkZSB0byB0aGUgY29tbWFuZC5cbiAgICogQHBhcmFtIG91dHB1dFRyYW5zZm9ybSB0aGUgZnVuY3Rpb24gdGhhdCB3aWxsIHBhcnNlIFNURE9VVCBkYXRhLlxuICAgKiBAcGFyYW0gb3B0aW9ucyAgICAgICAgIGFkZGl0aW9uYWwgYHNwYXduYCBvcHRpb25zLCBpZiBuZWNlc3NhcnkuXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIHJ1bkNvbW1hbmQ8VCA9IEJ1ZmZlcj4oXG4gICAgY29tbWFuZDogc3RyaW5nLFxuICAgIGFyZ3M6IHJlYWRvbmx5IHN0cmluZ1tdLFxuICAgIG91dHB1dFRyYW5zZm9ybTogKHN0ZGVycjogcmVhZG9ubHkgQnVmZmVyW10pID0+IFQsXG4gICAgb3B0aW9ucz86IFNwYXduT3B0aW9uc1dpdGhvdXRTdGRpbyxcbiAgKTogUHJvbWlzZTxDb21tYW5kUmVzdWx0PFQ+PiB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlPENvbW1hbmRSZXN1bHQ8VD4+KChvaywga28pID0+IHtcbiAgICAgIC8vIE9uIFdpbmRvd3MsIHNwYXduaW5nIGEgcHJvZ3JhbSBlbmRpbmcgaW4gLmNtZCBvciAuYmF0IG5lZWRzIHRvIHJ1biBpbiBhIHNoZWxsXG4gICAgICAvLyBodHRwczovL25vZGVqcy5vcmcvZW4vYmxvZy92dWxuZXJhYmlsaXR5L2FwcmlsLTIwMjQtc2VjdXJpdHktcmVsZWFzZXMtMlxuICAgICAgY29uc3Qgc2hlbGwgPSBvbldpbmRvd3MoKSAmJiAoY29tbWFuZC5lbmRzV2l0aCgnLmNtZCcpIHx8IGNvbW1hbmQuZW5kc1dpdGgoJy5iYXQnKSk7XG4gICAgICBjb25zdCBjaGlsZCA9IHNwYXduKGNvbW1hbmQsIGFyZ3MsIHsgc2hlbGwsIC4uLm9wdGlvbnMsIHN0ZGlvOiBbJ2luaGVyaXQnLCAncGlwZScsICdwaXBlJ10gfSk7XG4gICAgICBjb25zdCBzdGRvdXQgPSBuZXcgQXJyYXk8QnVmZmVyPigpO1xuICAgICAgY2hpbGQuc3Rkb3V0Lm9uKCdkYXRhJywgKGNodW5rKSA9PiB7XG4gICAgICAgIHN0ZG91dC5wdXNoKEJ1ZmZlci5mcm9tKGNodW5rKSk7XG4gICAgICB9KTtcbiAgICAgIGNoaWxkLnN0ZGVyci5vbignZGF0YScsIChjaHVuaykgPT4ge1xuICAgICAgICBzdGRvdXQucHVzaChCdWZmZXIuZnJvbShjaHVuaykpO1xuICAgICAgfSk7XG5cbiAgICAgIGNoaWxkLm9uY2UoJ2Vycm9yJywga28pO1xuICAgICAgY2hpbGQub25jZSgnY2xvc2UnLCAoZXhpdENvZGUsIHNpZ25hbCkgPT4ge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIG9rKHtcbiAgICAgICAgICAgIGNvbW1hbmQ6IGAke2NvbW1hbmR9ICR7YXJncy5qb2luKCcgJyl9YCxcbiAgICAgICAgICAgIGV4aXRDb2RlLFxuICAgICAgICAgICAgc2lnbmFsLFxuICAgICAgICAgICAgc3Rkb3V0OiBvdXRwdXRUcmFuc2Zvcm0oc3Rkb3V0KSxcbiAgICAgICAgICB9KTtcbiAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICBrbyhlcnJvcik7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG59XG5cbi8qKlxuICogQSBmaWx0ZXIgdG8gYXBwbHkgd2hlbiBzZWxlY3Rpbmcgb3B0aW9uYWwgcGVlciBkZXBlbmRlbmNpZXMsIGJhc2VkIG9uIGhvd1xuICogdGhlaXIgdmVyc2lvbiB0YXJnZXQgaXMgc3BlY2lmaWVkLlxuICovXG5leHBvcnQgZW51bSBPcHRpb25hbFBlZXJEZXBzRmlsdGVyIHtcbiAgLyoqXG4gICAqIElnbm9yZSBhbGwgb3B0aW9uYWwgcGVlciBkZXBlbmRlbmNpZXMgd2hlbiBpbnN0YWxsaW5nLlxuICAgKi9cbiAgTm9uZSxcblxuICAvKipcbiAgICogSW5zdGFsbCBvbmx5IG9wdGlvbmFsIHBlZXIgZGVwZW5kZW5jaWVzIHNwZWNpZmllZCBhcyBhIHZlcnNpb24gcmFuZ2UsIGFuZFxuICAgKiBpZ25vcmUgdGhvc2Ugc3BlY2lmaWVkIGFzIGEgVVJMIG9yIGxvY2FsIHBhdGguXG4gICAqL1xuICBWZXJzaW9uUmFuZ2UsXG5cbiAgLyoqXG4gICAqIEluc3RhbGwgYWxsIG9wdGlvbmFsIHBlZXIgZGVwZW5kZW5jaWVzIHJlZ2FyZGxlc3Mgb2YgaG93IHRoZXkgYXJlXG4gICAqIHNwZWNpZmllZC4gVGhpcyByZXF1aXJlcyBVUkwgYW5kIGxvY2FsLXBhdGggZGVwZW5kZW5jaWVzIHRvIGJlIHJlYWNoYWJsZS5cbiAgICovXG4gIEFsbCxcbn1cblxuaW50ZXJmYWNlIENvbW1hbmRSZXN1bHQ8VD4ge1xuICByZWFkb25seSBjb21tYW5kOiBzdHJpbmc7XG4gIHJlYWRvbmx5IGV4aXRDb2RlOiBudW1iZXIgfCBudWxsO1xuICByZWFkb25seSBzaWduYWw6IE5vZGVKUy5TaWduYWxzIHwgbnVsbDtcbiAgcmVhZG9ubHkgc3Rkb3V0OiBUO1xufVxuaW50ZXJmYWNlIFN1Y2Nlc3NmdWxDb21tYW5kUmVzdWx0PFQ+IGV4dGVuZHMgQ29tbWFuZFJlc3VsdDxUPiB7XG4gIHJlYWRvbmx5IGV4aXRDb2RlOiAwO1xuICByZWFkb25seSBzaWduYWw6IG51bGw7XG59XG5cbi8qKlxuICogQXNzZXJ0cyB0aGUgcHJvdmlkZWQgQ29tbWFuZFJlc3VsdCBjb3JyZXNwb25kcyB0byBhIGNvbW1hbmQgdGhhdCBleGl0ZWQgd2l0aFxuICogY29kZSBgMGAuIElmIHRoYXQgaXMgbm90IHRoZSBjYXNlLCB0aGlzIHdpbGwgdGhyb3cgYW4gYXBwcm9wcmlhdGUgZXJyb3IsXG4gKiBlaXRoZXIgYE5wbUVycm9yYCBvciBgTm9TcGFjZUxlZnRPbkRldmljZWAuXG4gKi9cbmZ1bmN0aW9uIGFzc2VydFN1Y2Nlc3MocmVzdWx0OiBDb21tYW5kUmVzdWx0PFJlc3BvbnNlT2JqZWN0Pik6IGFzc2VydHMgcmVzdWx0IGlzIFN1Y2Nlc3NmdWxDb21tYW5kUmVzdWx0PFJlc3BvbnNlT2JqZWN0PiB7XG4gIGNvbnN0IHsgY29tbWFuZCwgZXhpdENvZGUsIHNpZ25hbCwgc3Rkb3V0IH0gPSByZXN1bHQ7XG4gIGlmIChleGl0Q29kZSA9PT0gMCkge1xuICAgIHJldHVybjtcbiAgfVxuICBpZiAoc2lnbmFsICE9IG51bGwpIHtcbiAgICB0aHJvdyBuZXcgTnBtRXJyb3IoYENvbW1hbmQgXCIke2NvbW1hbmR9XCIgd2FzIGtpbGxlZCBieSAke3NpZ25hbH1gLCBzdGRvdXQpO1xuICB9XG4gIGlmIChleGl0Q29kZSA9PT0gMjI4IHx8IHN0ZG91dC5lcnJvcj8uY29kZSA9PT0gJ0VOT1NQQycpIHtcbiAgICB0aHJvdyBuZXcgTm9TcGFjZUxlZnRPbkRldmljZShgQ29tbWFuZCBcIiR7Y29tbWFuZH1cIiBmYWlsZWQgZHVlIHRvIGluc3VmZmljaWVudCBhdmFpbGFibGUgZGlzayBzcGFjZWApO1xuICB9XG4gIGNvbnN0IHsgY29kZSwgZGV0YWlsLCBzdW1tYXJ5IH0gPSBzdGRvdXQuZXJyb3I7XG4gIGNvbnN0IG1lc3NhZ2UgPSBbXG4gICAgYENvbW1hbmQgXCIke2NvbW1hbmR9XCIgZXhpdGVkIHdpdGggY29kZSAke2V4aXRDb2RlfWAsXG4gICAgc3VtbWFyeSA/IGA6ICR7c3VtbWFyeX1gIDogJycsXG4gICAgZGV0YWlsID8gYFxcbiR7ZGV0YWlsfWAgOiAnJyxcbiAgICAvLyBJZiB3ZSBoYXZlIGFuIGVycm9yLCBidXQgbmVpdGhlciBkZXRhaWwgbm9yIHN1bW1hcnksIHRoZW4gd2UgcHJvYmFibHlcbiAgICAvLyBoYXZlIGFuIGFjdHVhbCBFcnJvciBvYmplY3QsIHNvIHdlJ2xsIHN0cmluZ2lmeSB0aGF0IGhlcmUuLi5cbiAgICBzdGRvdXQuZXJyb3IgJiYgIWRldGFpbCAmJiAhc3VtbWFyeSA/IGA6ICR7c3Rkb3V0LmVycm9yfWAgOiAnJyxcbiAgXS5qb2luKCcnKTtcblxuICBpZiAodHlwZW9mIHN1bW1hcnkgPT09ICdzdHJpbmcnICYmIHN1bW1hcnkuaW5jbHVkZXMoJ211c3QgcHJvdmlkZSBzdHJpbmcgc3BlYycpKSB7XG4gICAgLy8gaGFwcGVucyB3aGVuIHBhY2thZ2UuanNvbiBkZXBlbmRlbmNpZXMgZG9uJ3QgaGF2ZSBhIHNwZWMuXG4gICAgLy8gZm9yIGV4YW1wbGU6IGh0dHBzOi8vZ2l0aHViLmNvbS9tYXJrdXNsL2Nkay1jb2RlcGlwZWxpbmUtYml0YnVja2V0LWJ1aWxkLXJlc3VsdC1yZXBvcnRlci9ibG9iL3YwLjAuNy9wYWNrYWdlLmpzb25cbiAgICB0aHJvdyBuZXcgVW5JbnN0YWxsYWJsZVBhY2thZ2VFcnJvcihzdW1tYXJ5KTtcbiAgfVxuXG4gIC8vIGhhcHBlbnMgd2hlbiBhIHBhY2thZ2UgaGFzIGJlZW4gZGVsZXRlZCBmcm9tIG5wbVxuICAvLyBmb3IgZXhhbXBsZTogc25zLWFwcC1qc2lpLWNvbXBvbmVudFxuICBpZiAoIWNvZGUgJiYgIWRldGFpbCAmJiB0eXBlb2Ygc3VtbWFyeSA9PT0gJ3N0cmluZycgJiYgc3VtbWFyeS5pbmNsdWRlcygnQ2Fubm90IGNvbnZlcnQgdW5kZWZpbmVkIG9yIG51bGwgdG8gb2JqZWN0JykpIHtcbiAgICB0aHJvdyBuZXcgVW5JbnN0YWxsYWJsZVBhY2thZ2VFcnJvcihzdW1tYXJ5KTtcbiAgfVxuXG4gIHN3aXRjaCAoY29kZSkge1xuICAgIGNhc2UgJ0U0MDQnOiAvLyBwYWNrYWdlIChvciBkZXBlbmRlbmN5KSBjYW4ndCBiZSBmb3VuZCBvbiBOUE0uIFRoaXMgY2FuIGhhcHBlbiBpZiB0aGUgcGFja2FnZSBkZXBlbmRzIG9uIGEgZGVwcmVjYXRlZCBwYWNrYWdlIChmb3IgZXhhbXBsZSkuXG4gICAgY2FzZSAnRU9WRVJSSURFJzogLy8gUGFja2FnZSBjb250YWlucyBzb21lIHZlcnNpb24gb3ZlcnJpZGVzIHRoYXQgY29uZmxpY3QuXG4gICAgY2FzZSAnRVJFU09MVkUnOiAvLyBkZXBlbmRlbmN5IHJlc29sdXRpb24gcHJvYmxlbSByZXF1aXJlcyBhIG1hbnVhbCBpbnRlcnZlbnRpb24gKG1vc3QgbGlrZWx5Li4uKVxuICAgIGNhc2UgJ0VOT1ZFUlNJT05TJzogLy8gcGFja2FnZSBoYXMgYmVlbiByZW1vdmVkIGZyb20gbnBtXG4gICAgICB0aHJvdyBuZXcgVW5JbnN0YWxsYWJsZVBhY2thZ2VFcnJvcihtZXNzYWdlKTtcbiAgICBkZWZhdWx0OlxuICAgICAgdGhyb3cgbmV3IE5wbUVycm9yKG1lc3NhZ2UsIHN0ZG91dCwgY29kZSk7XG4gIH1cbn1cblxuLyoqXG4gKiBDb25jYXRlbmF0ZXMgdGhlIHByb3ZpZGVkIGNodW5rcyBpbnRvIGEgc2luZ2xlIEJ1ZmZlciwgY29udmVydHMgaXQgdG8gYVxuICogc3RyaW5nIHVzaW5nIHRoZSBkZXNpZ25hdGVkIGVuY29kaW5nLCB0aGVuIEpTT04tcGFyc2VzIGl0LiBJZiBhbnkgcGFydCBvZlxuICogdGhpcyBwcm9jZXNzIHJlc3VsdHMgaW4gYW4gZXJyb3IsIHJldHVybnMgYW4gb2JqZWN0IHRoYXQgY29udGFpbnMgdGhlIGVycm9yXG4gKiBhbmQgdGhlIHJhdyBjaHVua3MuXG4gKi9cbmZ1bmN0aW9uIGNodW5rc1RvT2JqZWN0KGNodW5rczogcmVhZG9ubHkgQnVmZmVyW10sIGVuY29kaW5nOiBCdWZmZXJFbmNvZGluZyA9ICd1dGYtOCcpOiBSZXNwb25zZU9iamVjdCB7XG4gIGNvbnN0IHJhdyA9IEJ1ZmZlci5jb25jYXQoY2h1bmtzKS50b1N0cmluZyhlbmNvZGluZyk7XG4gIHRyeSB7XG4gICAgLy8gbnBtIHdpbGwgc29tZXRpbWVzIHByaW50IG5vbiBqc29uIGxvZyBsaW5lcyBldmVuIHRob3VnaCAtLWpzb24gd2FzIHJlcXVlc3RlZC5cbiAgICAvLyBvYnNlcnZlZCB0aGVzZSBsb2cgbGluZXMgYWx3YXlzIHN0YXJ0IHdpdGggJ25wbScsIHNvIHdlIGZpbHRlciB0aG9zZSBvdXQuXG4gICAgLy8gZm9yIGV4YW1wbGU6IFwibnBtIG5vdGljZSBOZXcgcGF0Y2ggdmVyc2lvbiBvZiBucG0gYXZhaWxhYmxlISA4LjEuMCAtPiA4LjEuM1wiXG4gICAgLy8gZm9yIGV4YW1wbGU6IFwibnBtIEVSUiEgbXVzdCBwcm92aWRlIHN0cmluZyBzcGVjXCJcbiAgICBjb25zdCBvbmx5SnNvbiA9IHJhdy5zcGxpdCgvW1xcclxcbl0rLykgLy8gc3BsaXQgb24gYW55IG5ld2xpbmVzLCBiZWNhdXNlIG5wbSByZXR1cm5zIGluY29uc2lzdGVudCBuZXdsaW5lIGNoYXJhY3RlcnMgb24gV2luZG93c1xuICAgICAgLmZpbHRlcihsID0+ICFsLnN0YXJ0c1dpdGgoJ25wbScpKVxuICAgICAgLy8gU3VwcHJlc3MgZGVidWdnZXIgbWVzc2FnZXMsIGlmIHByZXNlbnQuLi5cbiAgICAgIC5maWx0ZXIobCA9PiBsICE9PSAnRGVidWdnZXIgYXR0YWNoZWQuJylcbiAgICAgIC5maWx0ZXIobCA9PiBsICE9PSAnV2FpdGluZyBmb3IgdGhlIGRlYnVnZ2VyIHRvIGRpc2Nvbm5lY3QuLi4nKVxuICAgICAgLy8gUmUtam9pbi4uLlxuICAgICAgLmpvaW4ob3MuRU9MKTtcbiAgICByZXR1cm4gSlNPTi5wYXJzZShvbmx5SnNvbik7XG4gIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgcmV0dXJuIHsgZXJyb3IsIHJhdyB9O1xuICB9XG59XG5cbnR5cGUgUmVzcG9uc2VPYmplY3QgPVxuICAvLyBUaGUgZXJyb3Igd2hlbiB3ZSBmYWlsZWQgdG8gcGFyc2UgdGhlIG91dHB1dCBhcyBKU09OXG4gIHwgeyByZWFkb25seSBlcnJvcjogYW55OyByZWFkb25seSByYXc6IHN0cmluZyB9XG4gIC8vIFRoZSBlcnJvciBvYmplY3RzIG5wbSByZXR1cm5zIHdoZW4gb3BlcmF0aW5nIGluIC0tanNvbiBtb2RlXG4gIHwgeyByZWFkb25seSBlcnJvcjogeyByZWFkb25seSBjb2RlOiBzdHJpbmc7IHJlYWRvbmx5IHN1bW1hcnk6IHN0cmluZzsgcmVhZG9ubHkgZGV0YWlsOiBzdHJpbmcgfSB9XG4gIC8vIFRoZSBzdWNjZXNzZnVsIG9iamVjdHMgYXJlIHRyZWF0ZWQgYXMgb3BhcXVlIGJsb2JzIGhlcmVcbiAgfCB7IHJlYWRvbmx5IGVycm9yOiB1bmRlZmluZWQ7IHJlYWRvbmx5IFtrZXk6IHN0cmluZ106IHVua25vd24gfTtcblxuLyoqXG4gKiBIZWxwZXIgdG8gZGV0ZWN0IGlmIHdlIGFyZSBydW5uaW5nIG9uIFdpbmRvd3MuXG4gKi9cbmZ1bmN0aW9uIG9uV2luZG93cygpIHtcbiAgcmV0dXJuIHByb2Nlc3MucGxhdGZvcm0gPT09ICd3aW4zMic7XG59XG5cbi8qKlxuICogR2V0IHRoZSBucG0gYmluYXJ5IHBhdGggZGVwZW5kaW5nIG9uIHRoZSBwbGF0Zm9ybS5cbiAqIEByZXR1cm5zIFwibnBtLmNtZFwiIG9uIFdpbmRvd3MsIG90aGVyd2lzZSBcIm5wbVwiXG4gKi9cbmZ1bmN0aW9uIG5wbVBsYXRmb3JtQXdhcmVDb21tYW5kKCkge1xuICBpZiAob25XaW5kb3dzKCkpIHtcbiAgICByZXR1cm4gJ25wbS5jbWQnO1xuICB9XG5cbiAgcmV0dXJuICducG0nO1xufVxuIl19