UNPKG

projen

Version:

CDK for software projects

371 lines • 47.9 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; }; })(); Object.defineProperty(exports, "__esModule", { value: true }); exports.discover = discover; exports.readManifest = readManifest; exports.resolveProjectType = resolveProjectType; exports.toProjectType = toProjectType; exports.readJsiiManifest = readJsiiManifest; const fs = __importStar(require("fs")); const path = __importStar(require("path")); const zlib_1 = require("zlib"); const case_1 = require("case"); const PROJEN_MODULE_ROOT = path.join(__dirname, ".."); const PROJECT_BASE_FQN = "projen.Project"; /** * Returns a list of project types exported the modules defined in `moduleDirs`. * This list will always also include the built-in projen project types. * Modules without a .jsii manifest are skipped. * * @param moduleDirs A list of npm module directories */ function discover(...moduleDirs) { const jsii = discoverJsiiTypes(...moduleDirs); const result = new Array(); for (const fqn of Object.keys(jsii)) { if (isProjectType(jsii, fqn)) { const p = toProjectType(jsii, fqn); result.push(p); } } return result.sort((r1, r2) => r1.pjid.localeCompare(r2.pjid)); } function readManifest(dir) { const jsiiFile = path.join(dir, ".jsii"); if (!fs.existsSync(jsiiFile)) { return undefined; } // no jsii manifest let manifest = JSON.parse(fs.readFileSync(jsiiFile, "utf-8")); if (manifest.schema === "jsii/file-redirect") { const compressedFile = path.join(dir, manifest.filename); if (!fs.existsSync(compressedFile)) { throw new Error(`${compressedFile} does not exist.`); } switch (manifest.compression) { case "gzip": manifest = JSON.parse((0, zlib_1.unzipSync)(fs.readFileSync(compressedFile)).toString()); break; default: throw new Error(`Unsupported compression format: ${manifest.compression}`); } } return manifest; } /** * Resolve all jsii types from @modulesDirs. * When a jsii module is found it will recusively list the types from the dependant module as well * * @param moduleDirs * @returns */ function discoverJsiiTypes(...moduleDirs) { const jsii = {}; const discoveredManifests = []; const discoverJsii = (dir) => { const manifest = readManifest(dir); if (!manifest) { return; } if (discoveredManifests.includes(manifest.fingerprint)) { return; } discoveredManifests.push(manifest.fingerprint); for (const [fqn, type] of Object.entries(manifest.types)) { jsii[fqn] = { ...type, }; } // Also search recursively in nested project dependencies. If the requested module is an external module // this will also end-up in the projen module and add the projen types if (manifest.dependencies) { for (const dependency of Object.keys(manifest.dependencies)) { const nestedDependencyFolder = path.dirname(require.resolve(`${dependency}/package.json`, { paths: [dir], })); if (fs.existsSync(nestedDependencyFolder)) { discoverJsii(nestedDependencyFolder); } } } }; // read all .jsii manifests from all requested modules and merge // them all into a single map of fqn->type. for (const dir of [...moduleDirs, PROJEN_MODULE_ROOT]) { discoverJsii(dir); // Read from scoped packages if (dir.includes("@") && fs.lstatSync(dir).isDirectory()) { const childDirs = fs.readdirSync(dir).map((file) => path.join(dir, file)); for (const child of childDirs) { discoverJsii(child); } } } return jsii; } function resolveProjectType(projectFqn) { let [moduleName] = projectFqn.split("."); if (moduleName === "projen") { moduleName = PROJEN_MODULE_ROOT; } // try picking the manifest. We only need the base folder but this is directly a nice check if we request from a valid jsii package const jsiiManifestFile = require.resolve(`${moduleName}/.jsii`, { paths: [process.cwd()], }); const moduleFolder = path.dirname(jsiiManifestFile); // Read all jsii types that can be loaded from this project type const jsii = discoverJsiiTypes(moduleFolder); return toProjectType(jsii, projectFqn); } function toProjectType(jsii, fqn) { if (!isProjectType(jsii, fqn)) { throw new Error(`Fully qualified name "${fqn}" is not a valid project type.`); } const typeinfo = jsii[fqn]; // projen.web.ReactProject -> web.ReactProject const typename = fqn.substring(fqn.indexOf(".") + 1); // projen.web.ReactProject -> web // projen.Project -> projen const readmeFileName = typename.includes(".") ? typename.split(".", 1)[0] : typeinfo.assembly; // * [java](https://projen.io/docs/api/java#javaproject-) - Java project. const docsurl = `https://projen.io/docs/api/${readmeFileName}#${typename .substring(typename.indexOf(".") + 1) .toLowerCase()}-`; let pjid = typeinfo.docs?.custom?.pjid ?? (0, case_1.snake)(typename).replace(/_project$/, ""); return { moduleName: typeinfo.assembly, typename, pjid, fqn, options: discoverOptions(jsii, fqn), docs: typeinfo.docs?.summary, docsurl, }; } function readJsiiManifest(jsiiFqn) { let [moduleName] = jsiiFqn.split("."); if (moduleName === "projen") { moduleName = PROJEN_MODULE_ROOT; } const jsiiManifestFile = require.resolve(`${moduleName}/.jsii`); return JSON.parse(fs.readFileSync(jsiiManifestFile, "utf-8")); } function discoverOptions(jsii, fqn) { const options = {}; const params = jsii[fqn]?.initializer?.parameters ?? []; const optionsParam = params[0]; const optionsTypeFqn = optionsParam?.type?.fqn; if (params.length > 1 || (params.length === 1 && optionsParam?.name !== "options")) { throw new Error(`constructor for project ${fqn} must have a single "options" argument of a struct type. got ${JSON.stringify(params)}`); } addOptions(optionsTypeFqn); const opts = Object.values(options); return opts.sort((a, b) => a.name.localeCompare(b.name)); function addOptions(ofqn, basePath = [], optional = false) { if (!ofqn) { return; } const struct = jsii[ofqn]; if (!struct) { throw new Error(`unable to find options type ${ofqn} for project ${fqn}`); } for (const prop of struct.properties ?? []) { const propPath = [...basePath, prop.name]; // protect against double-booking if (prop.name in options) { throw new Error(`duplicate option "${prop.name}" in ${fqn} (already declared in ${options[prop.name].parent})`); } let jsiiKind; if (prop.type?.fqn) { jsiiKind = jsii[prop.type?.fqn].kind; // e.g. 'class', 'interface', 'enum' } const isOptional = optional || prop.optional; const defaultValue = sanitizeValue(prop.docs?.default); const pjnew = sanitizeValue(prop.docs?.custom?.pjnew); // if this is a mandatory option and we have a default value, // or the option is tagged to be rendered with an initial value, // the value has to be JSON-parsable to the correct type const initialValue = getInitialValue(defaultValue, pjnew, isOptional); if (initialValue) { checkDefaultIsParsable(prop.name, initialValue, prop.type); } options[prop.name] = filterUndefined({ path: propPath, parent: struct.name, name: prop.name, fqn: prop.type?.fqn, docs: prop.docs.summary, simpleType: prop.type ? getSimpleTypeName(prop.type) : "unknown", type: prop.type, kind: jsiiKind, jsonLike: prop.type ? isJsonLike(jsii, prop.type) : undefined, switch: propPath.map((p) => (0, case_1.snake)(p).replace(/_/g, "-")).join("-"), default: defaultValue, initialValue: initialValue, optional: isOptional, featured: prop.docs?.custom?.featured === "true", deprecated: prop.docs.stability === "deprecated" ? true : undefined, }); } for (const ifc of struct.interfaces ?? []) { addOptions(ifc); } } } function getInitialValue(defaultValue, pjnew, isOptional = false) { if (pjnew) { return pjnew; } if (!isOptional) { return defaultValue; } return undefined; } function sanitizeValue(val) { if (val === "undefined") { return undefined; } return val; } function getSimpleTypeName(type) { if (type?.primitive) { return type.primitive; // e.g. 'string', 'boolean', 'number' } else if (type?.fqn) { return type.fqn.split(".").pop(); // projen.NodeProjectOptions -> NodeProjectOptions } else { // any other types such as collection types return "unknown"; } } /** * Whether a value of this type is serializable into JSON. */ function isJsonLike(jsii, type) { if (type.primitive) { // string, boolean, number, any return true; } else if (type.fqn) { const kind = jsii[type.fqn].kind; if (["interface", "enum"].includes(kind)) { // not 'class' return true; } } else if (type.collection) { return isJsonLike(jsii, type.collection.elementtype); } return false; } function filterUndefined(obj) { const ret = {}; for (const [k, v] of Object.entries(obj)) { if (v !== undefined) { ret[k] = v; } } return ret; } function isProjectType(jsii, fqn) { const type = jsii[fqn]; if (!type) { throw new Error(`Could not find project type with fqn "${fqn}" in .jsii file.`); } if (type.kind !== "class") { return false; } if (type.abstract) { return false; } if (type.docs?.deprecated) { return false; } let curr = type; while (true) { if (curr.fqn === PROJECT_BASE_FQN) { return true; } if (!curr.base) { return false; } curr = jsii[curr.base]; if (!curr) { return false; } } } function isPrimitiveArray({ collection }) { return Boolean(collection?.kind === "array" && collection?.elementtype.primitive); } function isPrimitiveOrPrimitiveArray(type) { return Boolean(type?.primitive || isPrimitiveArray(type)); } function checkDefaultIsParsable(prop, value, type) { // macros are pass-through if (value.startsWith("$")) { return; } if (!(type && isPrimitiveOrPrimitiveArray(type))) { throw new Error(`required option "${prop}" with a @default must use primitive types (string, number and boolean) or a primitive array. type found is: ${JSON.stringify(type)}`); } try { const parsed = JSON.parse(value); // Primitive type if (typeof parsed === type.primitive) { return; } // Primitive array if (Array.isArray(parsed) && isPrimitiveArray(type)) { // but empty (which is okay) if (parsed.length === 0) { return; } // if first element matches the type, assume it's correct if (typeof parsed[0] === type?.collection?.elementtype.primitive) { return; } } // Parsed value does not match type throw new Error(`cannot parse @default value for mandatory option ${prop} as a ${type}: ${parsed}`); } catch (e) { throw new Error(`unable to JSON.parse() value "${value}" specified as @default for mandatory option "${prop}": ${e.message}`); } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW52ZW50b3J5LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL2ludmVudG9yeS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQTBHQSw0QkFhQztBQUVELG9DQTRCQztBQWlFRCxnREFlQztBQUVELHNDQXFDQztBQUVELDRDQVFDO0FBdFJELHVDQUF5QjtBQUN6QiwyQ0FBNkI7QUFDN0IsK0JBQWlDO0FBQ2pDLCtCQUE2QjtBQUU3QixNQUFNLGtCQUFrQixHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFLElBQUksQ0FBQyxDQUFDO0FBQ3RELE1BQU0sZ0JBQWdCLEdBQUcsZ0JBQWdCLENBQUM7QUE2RjFDOzs7Ozs7R0FNRztBQUNILFNBQWdCLFFBQVEsQ0FBQyxHQUFHLFVBQW9CO0lBQzlDLE1BQU0sSUFBSSxHQUFHLGlCQUFpQixDQUFDLEdBQUcsVUFBVSxDQUFDLENBQUM7SUFFOUMsTUFBTSxNQUFNLEdBQUcsSUFBSSxLQUFLLEVBQXdCLENBQUM7SUFFakQsS0FBSyxNQUFNLEdBQUcsSUFBSSxNQUFNLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUM7UUFDcEMsSUFBSSxhQUFhLENBQUMsSUFBSSxFQUFFLEdBQUcsQ0FBQyxFQUFFLENBQUM7WUFDN0IsTUFBTSxDQUFDLEdBQUcsYUFBYSxDQUFDLElBQUksRUFBRSxHQUFHLENBQUMsQ0FBQztZQUNuQyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ2pCLENBQUM7SUFDSCxDQUFDO0lBRUQsT0FBTyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7QUFDakUsQ0FBQztBQUVELFNBQWdCLFlBQVksQ0FBQyxHQUFXO0lB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QUssSUFBSSxFQUFFLFVBQVUsRUFBRSxXQUFXLENBQUMsU0FBUyxFQUFFLENBQUM7Z0JBQ2pFLE9BQU87WUFDVCxDQUFDO1FBQ0gsQ0FBQztRQUVELG1DQUFtQztRQUNuQyxNQUFNLElBQUksS0FBSyxDQUNiLG9EQUFvRCxJQUFJLFNBQVMsSUFBSSxLQUFLLE1BQU0sRUFBRSxDQUNuRixDQUFDO0lBQ0osQ0FBQztJQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7UUFDWCxNQUFNLElBQUksS0FBSyxDQUNiLGlDQUFpQyxLQUFLLGlEQUFpRCxJQUFJLE1BQ3hGLENBQVMsQ0FBQyxPQUNiLEVBQUUsQ0FDSCxDQUFDO0lBQ0osQ0FBQztBQUNILENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyBmcyBmcm9tIFwiZnNcIjtcbmltcG9ydCAqIGFzIHBhdGggZnJvbSBcInBhdGhcIjtcbmltcG9ydCB7IHVuemlwU3luYyB9IGZyb20gXCJ6bGliXCI7XG5pbXBvcnQgeyBzbmFrZSB9IGZyb20gXCJjYXNlXCI7XG5cbmNvbnN0IFBST0pFTl9NT0RVTEVfUk9PVCA9IHBhdGguam9pbihfX2Rpcm5hbWUsIFwiLi5cIik7XG5jb25zdCBQUk9KRUNUX0JBU0VfRlFOID0gXCJwcm9qZW4uUHJvamVjdFwiO1xuXG50eXBlIEpzaWlUeXBlcyA9IHsgW25hbWU6IHN0cmluZ106IEpzaWlUeXBlIH07XG5cbmV4cG9ydCBpbnRlcmZhY2UgUHJvamVjdE9wdGlvbiB7XG4gIHJlYWRvbmx5IG5hbWU6IHN0cmluZztcbiAgcmVhZG9ubHkgZnFuPzogc3RyaW5nO1xuICByZWFkb25seSBkb2NzPzogc3RyaW5nO1xuICByZWFkb25seSBkZWZhdWx0Pzogc3RyaW5nO1xuICByZWFkb25seSBvcHRpb25hbD86IGJvb2xlYW47XG4gIHJlYWRvbmx5IGRlcHJlY2F0ZWQ/OiBib29sZWFuO1xuICByZWFkb25seSBmZWF0dXJlZD86IGJvb2xlYW47XG4gIHJlYWRvbmx5IGluaXRpYWxWYWx1ZT86IHN0cmluZztcbiAgcmVhZG9ubHkgdHlwZTogYW55O1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFByb2plY3RUeXBlIHtcbiAgcmVhZG9ubHkgbW9kdWxlTmFtZTogc3RyaW5nO1xuICByZWFkb25seSBwamlkOiBzdHJpbmc7XG4gIHJlYWRvbmx5IGZxbjogc3RyaW5nO1xuICByZWFkb25seSB0eXBlbmFtZTogc3RyaW5nO1xuICByZWFkb25seSBvcHRpb25zOiBQcm9qZWN0T3B0aW9uW107XG4gIHJlYWRvbmx5IGRvY3M/OiBzdHJpbmc7XG4gIHJlYWRvbmx5IGRvY3N1cmw6IHN0cmluZztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBJbnZlbnRvcnlQcm9qZWN0T3B0aW9uIGV4dGVuZHMgUHJvamVjdE9wdGlvbiB7XG4gIHJlYWRvbmx5IHBhdGg6IHN0cmluZ1tdO1xuICByZWFkb25seSBwYXJlbnQ6IHN0cmluZztcbiAgcmVhZG9ubHkgc3dpdGNoOiBzdHJpbmc7XG4gIHJlYWRvbmx5IGpzb25MaWtlPzogYm9vbGVhbjtcbiAgLyoqIFNpbXBsZSB0eXBlIG5hbWUsIGUuZy4gXCJzdHJpbmdcIiwgXCJib29sZWFuXCIsIFwibnVtYmVyXCIsIFwiRXNsaW50T3B0aW9uc1wiLCBcIk15RW51bVwiLiBDb2xsZWN0aW9ucyBhcmUgXCJ1bmtub3duXCIgKi9cbiAgcmVhZG9ubHkgc2ltcGxlVHlwZTogc3RyaW5nO1xuICAvKiogRnVsbCBKU0lJIHR5cGUsIGUuZy4geyBwcmltaXRpdmU6IFwic3RyaW5nXCIgfSBvciB7IGNvbGxlY3Rpb246IHsgZWxlbWVudHR5cGU6IHsgcHJpbWl0aXZlOiAnc3RyaW5nJyB9LCBraW5kOiAnbWFwJyB9IH0gKi9cbiAgcmVhZG9ubHkgdHlwZTogSnNpaVByb3BlcnR5VHlwZTtcbiAgcmVhZG9ubHkga2luZD86IFwiY2xhc3NcIiB8IFwiZW51bVwiIHwgXCJpbnRlcmZhY2VcIjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBJbnZlbnRvcnlQcm9qZWN0VHlwZSBleHRlbmRzIFByb2plY3RUeXBlIHtcbiAgbW9kdWxlTmFtZTogc3RyaW5nO1xuICBwamlkOiBzdHJpbmc7XG4gIGZxbjogc3RyaW5nO1xuICB0eXBlbmFtZTogc3RyaW5nO1xuICBvcHRpb25zOiBJbnZlbnRvcnlQcm9qZWN0T3B0aW9uW107XG4gIGRvY3M/OiBzdHJpbmc7XG4gIGRvY3N1cmw6IHN0cmluZztcbn1cblxuaW50ZXJmYWNlIEpzaWlUeXBlIHtcbiAgbmFtZTogc3RyaW5nO1xuICBhc3NlbWJseTogc3RyaW5nO1xuICBraW5kOiBzdHJpbmc7XG4gIGFic3RyYWN0PzogYm9vbGVhbjtcbiAgYmFzZT86IHN0cmluZztcbiAgZnFuOiBzdHJpbmc7XG4gIGludGVyZmFjZXM/OiBzdHJpbmdbXTtcbiAgaW5pdGlhbGl6ZXI/OiB7XG4gICAgcGFyYW1ldGVycz86IEFycmF5PHtcbiAgICAgIG5hbWU6IHN0cmluZztcbiAgICAgIHR5cGU/OiB7IGZxbj86IHN0cmluZyB9O1xuICAgIH0+O1xuICB9O1xuICBwcm9wZXJ0aWVzPzogQXJyYXk8e1xuICAgIG5hbWU6IHN0cmluZztcbiAgICBkb2NzOiB7XG4gICAgICBzdW1tYXJ5Pzogc3RyaW5nO1xuICAgICAgZGVmYXVsdD86IHN0cmluZztcbiAgICAgIGRlcHJlY2F0ZWQ/OiBzdHJpbmc7XG4gICAgICBzdGFiaWxpdHk/OiBzdHJpbmc7XG4gICAgICBjdXN0b20/OiB7IFtuYW1lOiBzdHJpbmddOiBzdHJpbmcgfTtcbiAgICB9O1xuICAgIG9wdGlvbmFsPzogYm9vbGVhbjtcbiAgICB0eXBlPzogSnNpaVByb3BlcnR5VHlwZTtcbiAgfT47XG4gIGRvY3M/OiB7XG4gICAgc3VtbWFyeT86IHN0cmluZztcbiAgICBkZXByZWNhdGVkPzogc3RyaW5nO1xuICAgIGN1c3RvbT86IHtcbiAgICAgIHBqaWQ/OiBzdHJpbmc7XG4gICAgICBwam5ldz86IHN0cmluZztcbiAgICB9O1xuICB9O1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEpzaWlQcm9wZXJ0eVR5cGUge1xuICBwcmltaXRpdmU/OiBzdHJpbmc7XG4gIGZxbj86IHN0cmluZztcbiAgY29sbGVjdGlvbj86IHtcbiAgICBlbGVtZW50dHlwZTogSnNpaVByb3BlcnR5VHlwZTtcbiAgICBraW5kOiBzdHJpbmc7XG4gIH07XG59XG5cbi8qKlxuICogUmV0dXJucyBhIGxpc3Qgb2YgcHJvamVjdCB0eXBlcyBleHBvcnRlZCB0aGUgbW9kdWxlcyBkZWZpbmVkIGluIGBtb2R1bGVEaXJzYC5cbiAqIFRoaXMgbGlzdCB3aWxsIGFsd2F5cyBhbHNvIGluY2x1ZGUgdGhlIGJ1aWx0LWluIHByb2plbiBwcm9qZWN0IHR5cGVzLlxuICogTW9kdWxlcyB3aXRob3V0IGEgLmpzaWkgbWFuaWZlc3QgYXJlIHNraXBwZWQuXG4gKlxuICogQHBhcmFtIG1vZHVsZURpcnMgQSBsaXN0IG9mIG5wbSBtb2R1bGUgZGlyZWN0b3JpZXNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGRpc2NvdmVyKC4uLm1vZHVsZURpcnM6IHN0cmluZ1tdKTogSW52ZW50b3J5UHJvamVjdFR5cGVbXSB7XG4gIGNvbnN0IGpzaWkgPSBkaXNjb3ZlckpzaWlUeXBlcyguLi5tb2R1bGVEaXJzKTtcblxuICBjb25zdCByZXN1bHQgPSBuZXcgQXJyYXk8SW52ZW50b3J5UHJvamVjdFR5cGU+KCk7XG5cbiAgZm9yIChjb25zdCBmcW4gb2YgT2JqZWN0LmtleXMoanNpaSkpIHtcbiAgICBpZiAoaXNQcm9qZWN0VHlwZShqc2lpLCBmcW4pKSB7XG4gICAgICBjb25zdCBwID0gdG9Qcm9qZWN0VHlwZShqc2lpLCBmcW4pO1xuICAgICAgcmVzdWx0LnB1c2gocCk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHJlc3VsdC5zb3J0KChyMSwgcjIpID0+IHIxLnBqaWQubG9jYWxlQ29tcGFyZShyMi5wamlkKSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiByZWFkTWFuaWZlc3QoZGlyOiBzdHJpbmcpIHtcbiAgY29uc3QganNpaUZpbGUgPSBwYXRoLmpvaW4oZGlyLCBcIi5qc2lpXCIpO1xuICBpZiAoIWZzLmV4aXN0c1N5bmMoanNpaUZpbGUpKSB7XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfSAvLyBubyBqc2lpIG1hbmlmZXN0XG4gIGxldCBtYW5pZmVzdCA9IEpTT04ucGFyc2UoZnMucmVhZEZpbGVTeW5jKGpzaWlGaWxlLCBcInV0Zi04XCIpKTtcblxuICBpZiAobWFuaWZlc3Quc2NoZW1hID09PSBcImpzaWkvZmlsZS1yZWRpcmVjdFwiKSB7XG4gICAgY29uc3QgY29tcHJlc3NlZEZpbGUgPSBwYXRoLmpvaW4oZGlyLCBtYW5pZmVzdC5maWxlbmFtZSk7XG5cbiAgICBpZiAoIWZzLmV4aXN0c1N5bmMoY29tcHJlc3NlZEZpbGUpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYCR7Y29tcHJlc3NlZEZpbGV9IGRvZXMgbm90IGV4aXN0LmApO1xuICAgIH1cblxuICAgIHN3aXRjaCAobWFuaWZlc3QuY29tcHJlc3Npb24pIHtcbiAgICAgIGNhc2UgXCJnemlwXCI6XG4gICAgICAgIG1hbmlmZXN0ID0gSlNPTi5wYXJzZShcbiAgICAgICAgICB1bnppcFN5bmMoZnMucmVhZEZpbGVTeW5jKGNvbXByZXNzZWRGaWxlKSkudG9TdHJpbmcoKSxcbiAgICAgICAgKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgYFVuc3VwcG9ydGVkIGNvbXByZXNzaW9uIGZvcm1hdDogJHttYW5pZmVzdC5jb21wcmVzc2lvbn1gLFxuICAgICAgICApO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBtYW5pZmVzdDtcbn1cblxuLyoqXG4gKiBSZXNvbHZlIGFsbCBqc2lpIHR5cGVzIGZyb20gQG1vZHVsZXNEaXJzLlxuICogV2hlbiBhIGpzaWkgbW9kdWxlIGlzIGZvdW5kIGl0IHdpbGwgcmVjdXNpdmVseSBsaXN0IHRoZSB0eXBlcyBmcm9tIHRoZSBkZXBlbmRhbnQgbW9kdWxlIGFzIHdlbGxcbiAqXG4gKiBAcGFyYW0gbW9kdWxlRGlyc1xuICogQHJldHVybnNcbiAqL1xuZnVuY3Rpb24gZGlzY292ZXJKc2lpVHlwZXMoLi4ubW9kdWxlRGlyczogc3RyaW5nW10pIHtcbiAgY29uc3QganNpaTogSnNpaVR5cGVzID0ge307XG4gIGNvbnN0IGRpc2NvdmVyZWRNYW5pZmVzdHM6IEFycmF5PHN0cmluZz4gPSBbXTtcblxuICBjb25zdCBkaXNjb3ZlckpzaWkgPSAoZGlyOiBzdHJpbmcpID0+IHtcbiAgICBjb25zdCBtYW5pZmVzdCA9IHJlYWRNYW5pZmVzdChkaXIpO1xuXG4gICAgaWYgKCFtYW5pZmVzdCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmIChkaXNjb3ZlcmVkTWFuaWZlc3RzLmluY2x1ZGVzKG1hbmlmZXN0LmZpbmdlcnByaW50KSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBkaXNjb3ZlcmVkTWFuaWZlc3RzLnB1c2gobWFuaWZlc3QuZmluZ2VycHJpbnQpO1xuXG4gICAgZm9yIChjb25zdCBbZnFuLCB0eXBlXSBvZiBPYmplY3QuZW50cmllcyhtYW5pZmVzdC50eXBlcyBhcyBKc2lpVHlwZXMpKSB7XG4gICAgICBqc2lpW2Zxbl0gPSB7XG4gICAgICAgIC4uLnR5cGUsXG4gICAgICB9O1xuICAgIH1cblxuICAgIC8vIEFsc28gc2VhcmNoIHJlY3Vyc2l2ZWx5IGluIG5lc3RlZCBwcm9qZWN0IGRlcGVuZGVuY2llcy4gSWYgdGhlIHJlcXVlc3RlZCBtb2R1bGUgaXMgYW4gZXh0ZXJuYWwgbW9kdWxlXG4gICAgLy8gdGhpcyB3aWxsIGFsc28gZW5kLXVwIGluIHRoZSBwcm9qZW4gbW9kdWxlIGFuZCBhZGQgdGhlIHByb2plbiB0eXBlc1xuICAgIGlmIChtYW5pZmVzdC5kZXBlbmRlbmNpZXMpIHtcbiAgICAgIGZvciAoY29uc3QgZGVwZW5kZW5jeSBvZiBPYmplY3Qua2V5cyhtYW5pZmVzdC5kZXBlbmRlbmNpZXMpKSB7XG4gICAgICAgIGNvbnN0IG5lc3RlZERlcGVuZGVuY3lGb2xkZXIgPSBwYXRoLmRpcm5hbWUoXG4gICAgICAgICAgcmVxdWlyZS5yZXNvbHZlKGAke2RlcGVuZGVuY3l9L3BhY2thZ2UuanNvbmAsIHtcbiAgICAgICAgICAgIHBhdGhzOiBbZGlyXSxcbiAgICAgICAgICB9KSxcbiAgICAgICAgKTtcblxuICAgICAgICBpZiAoZnMuZXhpc3RzU3luYyhuZXN0ZWREZXBlbmRlbmN5Rm9sZGVyKSkge1xuICAgICAgICAgIGRpc2NvdmVySnNpaShuZXN0ZWREZXBlbmRlbmN5Rm9sZGVyKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfTtcblxuICAvLyByZWFkIGFsbCAuanNpaSBtYW5pZmVzdHMgZnJvbSBhbGwgcmVxdWVzdGVkIG1vZHVsZXMgYW5kIG1lcmdlXG4gIC8vIHRoZW0gYWxsIGludG8gYSBzaW5nbGUgbWFwIG9mIGZxbi0+dHlwZS5cbiAgZm9yIChjb25zdCBkaXIgb2YgWy4uLm1vZHVsZURpcnMsIFBST0pFTl9NT0RVTEVfUk9PVF0pIHtcbiAgICBkaXNjb3ZlckpzaWkoZGlyKTtcblxuICAgIC8vIFJlYWQgZnJvbSBzY29wZWQgcGFja2FnZXNcbiAgICBpZiAoZGlyLmluY2x1ZGVzKFwiQFwiKSAmJiBmcy5sc3RhdFN5bmMoZGlyKS5pc0RpcmVjdG9yeSgpKSB7XG4gICAgICBjb25zdCBjaGlsZERpcnMgPSBmcy5yZWFkZGlyU3luYyhkaXIpLm1hcCgoZmlsZSkgPT4gcGF0aC5qb2luKGRpciwgZmlsZSkpO1xuICAgICAgZm9yIChjb25zdCBjaGlsZCBvZiBjaGlsZERpcnMpIHtcbiAgICAgICAgZGlzY292ZXJKc2lpKGNoaWxkKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICByZXR1cm4ganNpaTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHJlc29sdmVQcm9qZWN0VHlwZShwcm9qZWN0RnFuOiBzdHJpbmcpOiBJbnZlbnRvcnlQcm9qZWN0VHlwZSB7XG4gIGxldCBbbW9kdWxlTmFtZV0gPSBwcm9qZWN0RnFuLnNwbGl0KFwiLlwiKTtcbiAgaWYgKG1vZHVsZU5hbWUgPT09IFwicHJvamVuXCIpIHtcbiAgICBtb2R1bGVOYW1lID0gUFJPSkVOX01PRFVMRV9ST09UO1xuICB9XG5cbiAgLy8gdHJ5IHBpY2tpbmcgdGhlIG1hbmlmZXN0LiBXZSBvbmx5IG5lZWQgdGhlIGJhc2UgZm9sZGVyIGJ1dCB0aGlzIGlzIGRpcmVjdGx5IGEgbmljZSBjaGVjayBpZiB3ZSByZXF1ZXN0IGZyb20gYSB2YWxpZCBqc2lpIHBhY2thZ2VcbiAgY29uc3QganNpaU1hbmlmZXN0RmlsZSA9IHJlcXVpcmUucmVzb2x2ZShgJHttb2R1bGVOYW1lfS8uanNpaWAsIHtcbiAgICBwYXRoczogW3Byb2Nlc3MuY3dkKCldLFxuICB9KTtcbiAgY29uc3QgbW9kdWxlRm9sZGVyID0gcGF0aC5kaXJuYW1lKGpzaWlNYW5pZmVzdEZpbGUpO1xuXG4gIC8vIFJlYWQgYWxsIGpzaWkgdHlwZXMgdGhhdCBjYW4gYmUgbG9hZGVkIGZyb20gdGhpcyBwcm9qZWN0IHR5cGVcbiAgY29uc3QganNpaSA9IGRpc2NvdmVySnNpaVR5cGVzKG1vZHVsZUZvbGRlcik7XG4gIHJldHVybiB0b1Byb2plY3RUeXBlKGpzaWksIHByb2plY3RGcW4pO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gdG9Qcm9qZWN0VHlwZShcbiAganNpaTogSnNpaVR5cGVzLFxuICBmcW46IHN0cmluZyxcbik6IEludmVudG9yeVByb2plY3RUeXBlIHtcbiAgaWYgKCFpc1Byb2plY3RUeXBlKGpzaWksIGZxbikpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICBgRnVsbHkgcXVhbGlmaWVkIG5hbWUgXCIke2Zxbn1cIiBpcyBub3QgYSB2YWxpZCBwcm9qZWN0IHR5cGUuYCxcbiAgICApO1xuICB9XG5cbiAgY29uc3QgdHlwZWluZm8gPSBqc2lpW2Zxbl07XG5cbiAgLy8gcHJvamVuLndlYi5SZWFjdFByb2plY3QgLT4gd2ViLlJlYWN0UHJvamVjdFxuICBjb25zdCB0eXBlbmFtZSA9IGZxbi5zdWJzdHJpbmcoZnFuLmluZGV4T2YoXCIuXCIpICsgMSk7XG5cbiAgLy8gcHJvamVuLndlYi5SZWFjdFByb2plY3QgLT4gd2ViXG4gIC8vIHByb2plbi5Qcm9qZWN0IC0+IHByb2plblxuICBjb25zdCByZWFkbWVGaWxlTmFtZSA9IHR5cGVuYW1lLmluY2x1ZGVzKFwiLlwiKVxuICAgID8gdHlwZW5hbWUuc3BsaXQoXCIuXCIsIDEpWzBdXG4gICAgOiB0eXBlaW5mby5hc3NlbWJseTtcblxuICAvLyAqIFtqYXZhXShodHRwczovL3Byb2plbi5pby9kb2NzL2FwaS9qYXZhI2phdmFwcm9qZWN0LSkgLSBKYXZhIHByb2plY3QuXG5cbiAgY29uc3QgZG9jc3VybCA9IGBodHRwczovL3Byb2plbi5pby9kb2NzL2FwaS8ke3JlYWRtZUZpbGVOYW1lfSMke3R5cGVuYW1lXG4gICAgLnN1YnN0cmluZyh0eXBlbmFtZS5pbmRleE9mKFwiLlwiKSArIDEpXG4gICAgLnRvTG93ZXJDYXNlKCl9LWA7XG4gIGxldCBwamlkID1cbiAgICB0eXBlaW5mby5kb2NzPy5jdXN0b20/LnBqaWQgPz8gc25ha2UodHlwZW5hbWUpLnJlcGxhY2UoL19wcm9qZWN0JC8sIFwiXCIpO1xuICByZXR1cm4ge1xuICAgIG1vZHVsZU5hbWU6IHR5cGVpbmZvLmFzc2VtYmx5LFxuICAgIHR5cGVuYW1lLFxuICAgIHBqaWQsXG4gICAgZnFuLFxuICAgIG9wdGlvbnM6IGRpc2NvdmVyT3B0aW9ucyhqc2lpLCBmcW4pLFxuICAgIGRvY3M6IHR5cGVpbmZvLmRvY3M/LnN1bW1hcnksXG4gICAgZG9jc3VybCxcbiAgfSBhcyBJbnZlbnRvcnlQcm9qZWN0VHlwZTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHJlYWRKc2lpTWFuaWZlc3QoanNpaUZxbjogc3RyaW5nKTogYW55IHtcbiAgbGV0IFttb2R1bGVOYW1lXSA9IGpzaWlGcW4uc3BsaXQoXCIuXCIpO1xuICBpZiAobW9kdWxlTmFtZSA9PT0gXCJwcm9qZW5cIikge1xuICAgIG1vZHVsZU5hbWUgPSBQUk9KRU5fTU9EVUxFX1JPT1Q7XG4gIH1cblxuICBjb25zdCBqc2lpTWFuaWZlc3RGaWxlID0gcmVxdWlyZS5yZXNvbHZlKGAke21vZHVsZU5hbWV9Ly5qc2lpYCk7XG4gIHJldHVybiBKU09OLnBhcnNlKGZzLnJlYWRGaWxlU3luYyhqc2lpTWFuaWZlc3RGaWxlLCBcInV0Zi04XCIpKTtcbn1cblxuZnVuY3Rpb24gZGlzY292ZXJPcHRpb25zKFxuICBqc2lpOiBKc2lpVHlwZXMsXG4gIGZxbjogc3RyaW5nLFxuKTogSW52ZW50b3J5UHJvamVjdE9wdGlvbltdIHtcbiAgY29uc3Qgb3B0aW9uczogeyBbbmFtZTogc3RyaW5nXTogSW52ZW50b3J5UHJvamVjdE9wdGlvbiB9ID0ge307XG4gIGNvbnN0IHBhcmFtcyA9IGpzaWlbZnFuXT8uaW5pdGlhbGl6ZXI/LnBhcmFtZXRlcnMgPz8gW107XG4gIGNvbnN0IG9wdGlvbnNQYXJhbSA9IHBhcmFtc1swXTtcbiAgY29uc3Qgb3B0aW9uc1R5cGVGcW4gPSBvcHRpb25zUGFyYW0/LnR5cGU/LmZxbjtcblxuICBpZiAoXG4gICAgcGFyYW1zLmxlbmd0aCA+IDEgfHxcbiAgICAocGFyYW1zLmxlbmd0aCA9PT0gMSAmJiBvcHRpb25zUGFyYW0/Lm5hbWUgIT09IFwib3B0aW9uc1wiKVxuICApIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICBgY29uc3RydWN0b3IgZm9yIHByb2plY3QgJHtmcW59IG11c3QgaGF2ZSBhIHNpbmdsZSBcIm9wdGlvbnNcIiBhcmd1bWVudCBvZiBhIHN0cnVjdCB0eXBlLiBnb3QgJHtKU09OLnN0cmluZ2lmeShcbiAgICAgICAgcGFyYW1zLFxuICAgICAgKX1gLFxuICAgICk7XG4gIH1cblxuICBhZGRPcHRpb25zKG9wdGlvbnNUeXBlRnFuKTtcblxuICBjb25zdCBvcHRzID0gT2JqZWN0LnZhbHVlcyhvcHRpb25zKTtcblxuICByZXR1cm4gb3B0cy5zb3J0KChhLCBiKSA9PiBhLm5hbWUubG9jYWxlQ29tcGFyZShiLm5hbWUpKTtcblxuICBmdW5jdGlvbiBhZGRPcHRpb25zKFxuICAgIG9mcW4/OiBzdHJpbmcsXG4gICAgYmFzZVBhdGg6IHN0cmluZ1tdID0gW10sXG4gICAgb3B0aW9uYWwgPSBmYWxzZSxcbiAgKSB7XG4gICAgaWYgKCFvZnFuKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3Qgc3RydWN0ID0ganNpaVtvZnFuXTtcbiAgICBpZiAoIXN0cnVjdCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGB1bmFibGUgdG8gZmluZCBvcHRpb25zIHR5cGUgJHtvZnFufSBmb3IgcHJvamVjdCAke2Zxbn1gKTtcbiAgICB9XG5cbiAgICBmb3IgKGNvbnN0IHByb3Agb2Ygc3RydWN0LnByb3BlcnRpZXMgPz8gW10pIHtcbiAgICAgIGNvbnN0IHByb3BQYXRoID0gWy4uLmJhc2VQYXRoLCBwcm9wLm5hbWVdO1xuXG4gICAgICAvLyBwcm90ZWN0IGFnYWluc3QgZG91YmxlLWJvb2tpbmdcbiAgICAgIGlmIChwcm9wLm5hbWUgaW4gb3B0aW9ucykge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgYGR1cGxpY2F0ZSBvcHRpb24gXCIke3Byb3AubmFtZX1cIiBpbiAke2Zxbn0gKGFscmVhZHkgZGVjbGFyZWQgaW4gJHtcbiAgICAgICAgICAgIG9wdGlvbnNbcHJvcC5uYW1lXS5wYXJlbnRcbiAgICAgICAgICB9KWAsXG4gICAgICAgICk7XG4gICAgICB9XG5cbiAgICAgIGxldCBqc2lpS2luZDtcbiAgICAgIGlmIChwcm9wLnR5cGU/LmZxbikge1xuICAgICAgICBqc2lpS2luZCA9IGpzaWlbcHJvcC50eXBlPy5mcW5dLmtpbmQ7IC8vIGUuZy4gJ2NsYXNzJywgJ2ludGVyZmFjZScsICdlbnVtJ1xuICAgICAgfVxuXG4gICAgICBjb25zdCBpc09wdGlvbmFsID0gb3B0aW9uYWwgfHwgcHJvcC5vcHRpb25hbDtcbiAgICAgIGNvbnN0IGRlZmF1bHRWYWx1ZSA9IHNhbml0aXplVmFsdWUocHJvcC5kb2NzPy5kZWZhdWx0KTtcbiAgICAgIGNvbnN0IHBqbmV3ID0gc2FuaXRpemVWYWx1ZShwcm9wLmRvY3M/LmN1c3RvbT8ucGpuZXcpO1xuXG4gICAgICAvLyBpZiB0aGlzIGlzIGEgbWFuZGF0b3J5IG9wdGlvbiBhbmQgd2UgaGF2ZSBhIGRlZmF1bHQgdmFsdWUsXG4gICAgICAvLyBvciB0aGUgb3B0aW9uIGlzIHRhZ2dlZCB0byBiZSByZW5kZXJlZCB3aXRoIGFuIGluaXRpYWwgdmFsdWUsXG4gICAgICAvLyB0aGUgdmFsdWUgaGFzIHRvIGJlIEpTT04tcGFyc2FibGUgdG8gdGhlIGNvcnJlY3QgdHlwZVxuICAgICAgY29uc3QgaW5pdGlhbFZhbHVlID0gZ2V0SW5pdGlhbFZhbHVlKGRlZmF1bHRWYWx1ZSwgcGpuZXcsIGlzT3B0aW9uYWwpO1xuICAgICAgaWYgKGluaXRpYWxWYWx1ZSkge1xuICAgICAgICBjaGVja0RlZmF1bHRJc1BhcnNhYmxlKHByb3AubmFtZSwgaW5pdGlhbFZhbHVlLCBwcm9wLnR5cGUpO1xuICAgICAgfVxuXG4gICAgICBvcHRpb25zW3Byb3AubmFtZV0gPSBmaWx0ZXJVbmRlZmluZWQoe1xuICAgICAgICBwYXRoOiBwcm9wUGF0aCxcbiAgICAgICAgcGFyZW50OiBzdHJ1Y3QubmFtZSxcbiAgICAgICAgbmFtZTogcHJvcC5uYW1lLFxuICAgICAgICBmcW46IHByb3AudHlwZT8uZnFuLFxuICAgICAgICBkb2NzOiBwcm9wLmRvY3Muc3VtbWFyeSxcbiAgICAgICAgc2ltcGxlVHlwZTogcHJvcC50eXBlID8gZ2V0U2ltcGxlVHlwZU5hbWUocHJvcC50eXBlKSA6IFwidW5rbm93blwiLFxuICAgICAgICB0eXBlOiBwcm9wLnR5cGUsXG4gICAgICAgIGtpbmQ6IGpzaWlLaW5kLFxuICAgICAgICBqc29uTGlrZTogcHJvcC50eXBlID8gaXNKc29uTGlrZShqc2lpLCBwcm9wLnR5cGUpIDogdW5kZWZpbmVkLFxuICAgICAgICBzd2l0Y2g6IHByb3BQYXRoLm1hcCgocCkgPT4gc25ha2UocCkucmVwbGFjZSgvXy9nLCBcIi1cIikpLmpvaW4oXCItXCIpLFxuICAgICAgICBkZWZhdWx0OiBkZWZhdWx0VmFsdWUsXG4gICAgICAgIGluaXRpYWxWYWx1ZTogaW5pdGlhbFZhbHVlLFxuICAgICAgICBvcHRpb25hbDogaXNPcHRpb25hbCxcbiAgICAgICAgZmVhdHVyZWQ6IHByb3AuZG9jcz8uY3VzdG9tPy5mZWF0dXJlZCA9PT0gXCJ0cnVlXCIsXG4gICAgICAgIGRlcHJlY2F0ZWQ6IHByb3AuZG9jcy5zdGFiaWxpdHkgPT09IFwiZGVwcmVjYXRlZFwiID8gdHJ1ZSA6IHVuZGVmaW5lZCxcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIGZvciAoY29uc3QgaWZjIG9mIHN0cnVjdC5pbnRlcmZhY2VzID8/IFtdKSB7XG4gICAgICBhZGRPcHRpb25zKGlmYyk7XG4gICAgfVxuICB9XG59XG5cbmZ1bmN0aW9uIGdldEluaXRpYWxWYWx1ZShcbiAgZGVmYXVsdFZhbHVlPzogc3RyaW5nLFxuICBwam5ldz86IHN0cmluZyxcbiAgaXNPcHRpb25hbDogYm9vbGVhbiA9IGZhbHNlLFxuKSB7XG4gIGlmIChwam5ldykge1xuICAgIHJldHVybiBwam5ldztcbiAgfVxuXG4gIGlmICghaXNPcHRpb25hbCkge1xuICAgIHJldHVybiBkZWZhdWx0VmFsdWU7XG4gIH1cblxuICByZXR1cm4gdW5kZWZpbmVkO1xufVxuXG5mdW5jdGlvbiBzYW5pdGl6ZVZhbHVlKHZhbD86IHN0cmluZykge1xuICBpZiAodmFsID09PSBcInVuZGVmaW5lZFwiKSB7XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxuXG4gIHJldHVybiB2YWw7XG59XG5cbmZ1bmN0aW9uIGdldFNpbXBsZVR5cGVOYW1lKHR5cGU6IEpzaWlQcm9wZXJ0eVR5cGUpOiBzdHJpbmcge1xuICBpZiAodHlwZT8ucHJpbWl0aXZlKSB7XG4gICAgcmV0dXJuIHR5cGUucHJpbWl0aXZlOyAvLyBlLmcuICdzdHJpbmcnLCAnYm9vbGVhbicsICdudW1iZXInXG4gIH0gZWxzZSBpZiAodHlwZT8uZnFuKSB7XG4gICAgcmV0dXJuIHR5cGUuZnFuLnNwbGl0KFwiLlwiKS5wb3AoKSE7IC8vIHByb2plbi5Ob2RlUHJvamVjdE9wdGlvbnMgLT4gTm9kZVByb2plY3RPcHRpb25zXG4gIH0gZWxzZSB7XG4gICAgLy8gYW55IG90aGVyIHR5cGVzIHN1Y2ggYXMgY29sbGVjdGlvbiB0eXBlc1xuICAgIHJldHVybiBcInVua25vd25cIjtcbiAgfVxufVxuXG4vKipcbiAqIFdoZXRoZXIgYSB2YWx1ZSBvZiB0aGlzIHR5cGUgaXMgc2VyaWFsaXphYmxlIGludG8gSlNPTi5cbiAqL1xuZnVuY3Rpb24gaXNKc29uTGlrZShqc2lpOiBKc2lpVHlwZXMsIHR5cGU6IEpzaWlQcm9wZXJ0eVR5cGUpOiBib29sZWFuIHtcbiAgaWYgKHR5cGUucHJpbWl0aXZlKSB7XG4gICAgLy8gc3RyaW5nLCBib29sZWFuLCBudW1iZXIsIGFueVxuICAgIHJldHVybiB0cnVlO1xuICB9IGVsc2UgaWYgKHR5cGUuZnFuKSB7XG4gICAgY29uc3Qga2luZCA9IGpzaWlbdHlwZS5mcW5dLmtpbmQ7XG4gICAgaWYgKFtcImludGVyZmFjZVwiLCBcImVudW1cIl0uaW5jbHVkZXMoa2luZCkpIHtcbiAgICAgIC8vIG5vdCAnY2xhc3MnXG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gIH0gZWxzZSBpZiAodHlwZS5jb2xsZWN0aW9uKSB7XG4gICAgcmV0dXJuIGlzSnNvbkxpa2UoanNpaSwgdHlwZS5jb2xsZWN0aW9uLmVsZW1lbnR0eXBlKTtcbiAgfVxuICByZXR1cm4gZmFsc2U7XG59XG5cbmZ1bmN0aW9uIGZpbHRlclVuZGVmaW5lZChvYmo6IGFueSkge1xuICBjb25zdCByZXQ6IGFueSA9IHt9O1xuICBmb3IgKGNvbnN0IFtrLCB2XSBvZiBPYmplY3QuZW50cmllcyhvYmopKSB7XG4gICAgaWYgKHYgIT09IHVuZGVmaW5lZCkge1xuICAgICAgcmV0W2tdID0gdjtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIHJldDtcbn1cblxuZnVuY3Rpb24gaXNQcm9qZWN0VHlwZShqc2lpOiBKc2lpVHlwZXMsIGZxbjogc3RyaW5nKSB7XG4gIGNvbnN0IHR5cGUgPSBqc2lpW2Zxbl07XG5cbiAgaWYgKCF0eXBlKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgYENvdWxkIG5vdCBmaW5kIHByb2plY3QgdHlwZSB3aXRoIGZxbiBcIiR7ZnFufVwiIGluICAuanNpaSBmaWxlLmAsXG4gICAgKTtcbiAgfVxuXG4gIGlmICh0eXBlLmtpbmQgIT09IFwiY2xhc3NcIikge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuICBpZiAodHlwZS5hYnN0cmFjdCkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIGlmICh0eXBlLmRvY3M/LmRlcHJlY2F0ZWQpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICBsZXQgY3VyciA9IHR5cGU7XG4gIHdoaWxlICh0cnVlKSB7XG4gICAgaWYgKGN1cnIuZnFuID09PSBQUk9KRUNUX0JBU0VfRlFOKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICBpZiAoIWN1cnIuYmFzZSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIGN1cnIgPSBqc2lpW2N1cnIuYmFzZV07XG4gICAgaWYgKCFjdXJyKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9XG59XG5cbmZ1bmN0aW9uIGlzUHJpbWl0aXZlQXJyYXkoeyBjb2xsZWN0aW9uIH06IEpzaWlQcm9wZXJ0eVR5cGUpIHtcbiAgcmV0dXJuIEJvb2xlYW4oXG4gICAgY29sbGVjdGlvbj8ua2luZCA9PT0gXCJhcnJheVwiICYmIGNvbGxlY3Rpb24/LmVsZW1lbnR0eXBlLnByaW1pdGl2ZSxcbiAgKTtcbn1cblxuZnVuY3Rpb24gaXNQcmltaXRpdmVPclByaW1pdGl2ZUFycmF5KHR5cGU6IEpzaWlQcm9wZXJ0eVR5cGUpIHtcbiAgcmV0dXJuIEJvb2xlYW4odHlwZT8ucHJpbWl0aXZlIHx8IGlzUHJpbWl0aXZlQXJyYXkodHlwZSkpO1xufVxuXG5mdW5jdGlvbiBjaGVja0RlZmF1bHRJc1BhcnNhYmxlKFxuICBwcm9wOiBzdHJpbmcsXG4gIHZhbHVlOiBzdHJpbmcsXG4gIHR5cGU/OiBKc2lpUHJvcGVydHlUeXBlLFxuKSB7XG4gIC8vIG1hY3JvcyBhcmUgcGFzcy10aHJvdWdoXG4gIGlmICh2YWx1ZS5zdGFydHNXaXRoKFwiJFwiKSkge1xuICAgIHJldHVybjtcbiAgfVxuXG4gIGlmICghKHR5cGUgJiYgaXNQcmltaXRpdmVPclByaW1pdGl2ZUFycmF5KHR5cGUpKSkge1xuICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgIGByZXF1aXJlZCBvcHRpb24gXCIke3Byb3B9XCIgd2l0aCBhIEBkZWZhdWx0IG11c3QgdXNlIHByaW1pdGl2ZSB0eXBlcyAoc3RyaW5nLCBudW1iZXIgYW5kIGJvb2xlYW4pIG9yIGEgcHJpbWl0aXZlIGFycmF5LiB0eXBlIGZvdW5kIGlzOiAke0pTT04uc3RyaW5naWZ5KFxuICAgICAgICB0eXBlLFxuICAgICAgKX1gLFxuICAgICk7XG4gIH1cblxuICB0cnkge1xuICAgIGNvbnN0IHBhcnNlZCA9IEpTT04ucGFyc2UodmFsdWUpO1xuXG4gICAgLy8gUHJpbWl0aXZlIHR5cGVcbiAgICBpZiAodHlwZW9mIHBhcnNlZCA9PT0gdHlwZS5wcmltaXRpdmUpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBQcmltaXRpdmUgYXJyYXlcbiAgICBpZiAoQXJyYXkuaXNBcnJheShwYXJzZWQpICYmIGlzUHJpbWl0aXZlQXJyYXkodHlwZSkpIHtcbiAgICAgIC8vIGJ1dCBlbXB0eSAod2hpY2ggaXMgb2theSlcbiAgICAgIGlmIChwYXJzZWQubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgLy8gaWYgZmlyc3QgZWxlbWVudCBtYXRjaGVzIHRoZSB0eXBlLCBhc3N1bWUgaXQncyBjb3JyZWN0XG4gICAgICBpZiAodHlwZW9mIHBhcnNlZFswXSA9PT0gdHlwZT8uY29sbGVjdGlvbj8uZWxlbWVudHR5cGUucHJpbWl0aXZlKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBQYXJzZWQgdmFsdWUgZG9lcyBub3QgbWF0Y2ggdHlwZVxuICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgIGBjYW5ub3QgcGFyc2UgQGRlZmF1bHQgdmFsdWUgZm9yIG1hbmRhdG9yeSBvcHRpb24gJHtwcm9wfSBhcyBhICR7dHlwZX06ICR7cGFyc2VkfWAsXG4gICAgKTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgIGB1bmFibGUgdG8gSlNPTi5wYXJzZSgpIHZhbHVlIFwiJHt2YWx1ZX1cIiBzcGVjaWZpZWQgYXMgQGRlZmF1bHQgZm9yIG1hbmRhdG9yeSBvcHRpb24gXCIke3Byb3B9XCI6ICR7XG4gICAgICAgIChlIGFzIGFueSkubWVzc2FnZVxuICAgICAgfWAsXG4gICAgKTtcbiAgfVxufVxuIl19