projen
Version:
CDK for software projects
371 lines • 47.9 kB
JavaScript
;
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