UNPKG

jsii-docgen

Version:

generates api docs for jsii modules

450 lines • 65.1 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.LANGUAGE_SPECIFIC = exports.Documentation = exports.SUPPORTED_ASSEMBLY_FEATURES = void 0;
exports.extractPackageName = extractPackageName;
const os = __importStar(require("os"));
const path = __importStar(require("path"));
const spec_1 = require("@jsii/spec");
const fs = __importStar(require("fs-extra"));
const reflect = __importStar(require("jsii-reflect"));
const jsii_rosetta_1 = require("jsii-rosetta");
const _npm_1 = require("./_npm");
const api_reference_1 = require("./api-reference");
const readme_1 = require("./readme");
const __1 = require("../..");
const json_1 = require("../render/json");
const markdown_doc_1 = require("../render/markdown-doc");
const markdown_render_1 = require("../render/markdown-render");
const schema_1 = require("../schema");
const assembly_1 = require("./assembly");
const csharp_1 = require("../transpile/csharp");
const go_1 = require("../transpile/go");
const java_1 = require("../transpile/java");
const python_1 = require("../transpile/python");
const transpile_1 = require("../transpile/transpile");
const typescript_1 = require("../transpile/typescript");
// https://github.com/aws/jsii/blob/v1.122.0/packages/jsii-reflect/lib/assembly.ts#L233
const NOT_FOUND_IN_ASSEMBLY_REGEX = /Type '(.*)\..*' not found in assembly (.*)$/;
// https://github.com/aws/jsii/blob/v1.122.0/packages/jsii-reflect/lib/type-system.ts#L252
const ASSEMBLY_NOT_FOUND_REGEX = /Assembly "(.*)" not found/;
exports.SUPPORTED_ASSEMBLY_FEATURES = ['intersection-types', 'class-covariant-overrides'];
/**
 * Render documentation pages for a jsii library.
 */
class Documentation {
    /**
     * Create a `Documentation` object from a package installable by npm.
     *
     * Note that this method installs the target package to the local file-system. Make sure
     * to call `Documentation.cleanup` once you are done rendering.
     *
     * @param target - The target to install. This can either be a local path or a registry identifier (e.g <name>@<version>)
     * @param options - Additional options.
     *
     * @throws NoSpaceLeftOnDevice if the installation fails due to running out of disk space
     * @throws NpmError if some `npm` command fails when preparing the working set
     */
    static async forPackage(target, options = {}) {
        var _a;
        const workdir = await fs.mkdtemp(path.join(os.tmpdir(), path.sep));
        const npm = new _npm_1.Npm(workdir);
        if ((_a = options.verbose) !== null && _a !== void 0 ? _a : true) {
            console.log(`Installing package ${target}`);
        }
        const name = await npm.install(target);
        if (options._postInstall != null) {
            await options._postInstall(workdir);
        }
        const docs = await Documentation.forProject(path.join(workdir, 'node_modules', name), { ...options, assembliesDir: workdir });
        // we cannot delete this directory immediately since it is used during `render` calls.
        // instead we register it so that callers can clean it up by calling the `cleanup` method.
        docs.addCleanupDirectory(workdir);
        return docs;
    }
    /**
     * Create a `Documentation` object from a local directory containing a node project.
     *
     * @param root - The local directory path. Must contain a package.json file.
     * @param options - Additional options.
     */
    static async forProject(root, options = {}) {
        var _a;
        const manifestPath = path.join(root, 'package.json');
        if (!(await fs.pathExists(manifestPath))) {
            throw new Error(`Unable to locate ${manifestPath}`);
        }
        // normally the assemblies are located in subdirectories
        // of the root package dir (i.e ./node_modules)
        const assembliesDir = (_a = options === null || options === void 0 ? void 0 : options.assembliesDir) !== null && _a !== void 0 ? _a : root;
        const { name } = JSON.parse(await fs.readFile(manifestPath, 'utf-8'));
        return Documentation.forAssembly(name, assembliesDir);
    }
    /**
     * Create a `Documentation` object for a specific assembly from a directory of assemblies.
     *
     * @param assemblyName - The assembly name.
     * @param assembliesDir - The directory containing the assemblies that comprise the type-system.
     */
    static async forAssembly(assemblyName, assembliesDir) {
        return new Documentation(assemblyName, assembliesDir);
    }
    constructor(assemblyName, assembliesDir) {
        this.assemblyName = assemblyName;
        this.assembliesDir = assembliesDir;
        this.cleanupDirectories = new Set();
        this.assembliesCache = new Map();
    }
    /**
     * List all submodules in the assembly.
     */
    async listSubmodules() {
        const tsAssembly = await this.createAssembly(undefined, { loose: true, validate: false });
        return tsAssembly.allSubmodules;
    }
    async toIndexMarkdown(fileSuffix, options) {
        const assembly = await this.createAssembly(undefined, { loose: true, validate: false });
        const submodules = await this.listSubmodules();
        const schema = (await this.toJson({
            ...options,
            submodule: undefined,
            allSubmodules: false,
        })).content;
        const ref = new markdown_doc_1.MarkdownDocument({ header: { title: 'API Reference' }, id: 'api-reference' });
        if (schema.version !== schema_1.CURRENT_SCHEMA_VERSION) {
            throw new Error(`Unexpected schema version: ${schema.version}`);
        }
        const renderer = new markdown_render_1.MarkdownRenderer({
            language: options.language,
            packageName: assembly.name,
            packageVersion: assembly.version,
        });
        if (submodules.length) {
            ref.section(renderer.visitSubmodules(submodules, fileSuffix));
        }
        if (schema.apiReference) {
            ref.section(renderer.visitConstructs(schema.apiReference.constructs));
            ref.section(renderer.visitStructs(schema.apiReference.structs));
            ref.section(renderer.visitClasses(schema.apiReference.classes));
            ref.section(renderer.visitInterfaces(schema.apiReference.interfaces));
            ref.section(renderer.visitEnums(schema.apiReference.enums));
        }
        const documentation = new markdown_doc_1.MarkdownDocument();
        documentation.section(ref);
        return documentation;
    }
    /**
     * Generate markdown.
     */
    async toJson(options) {
        var _a, _b, _c, _d, _e, _f, _g, _h;
        const language = (_a = options.language) !== null && _a !== void 0 ? _a : transpile_1.Language.TYPESCRIPT;
        const loose = (_b = options.loose) !== null && _b !== void 0 ? _b : true;
        const validate = (_c = options.validate) !== null && _c !== void 0 ? _c : false;
        const allSubmodules = (_d = options.allSubmodules) !== null && _d !== void 0 ? _d : false;
        // Get the TS assembly first to check what languages are supported before calling rosetta
        const tsAssembly = await this.createAssembly(undefined, { loose, validate });
        const isSupported = language === transpile_1.Language.TYPESCRIPT || language.isValidConfiguration((_e = tsAssembly === null || tsAssembly === void 0 ? void 0 : tsAssembly.targets) === null || _e === void 0 ? void 0 : _e[language.targetName]);
        this.assemblyFqn = `${tsAssembly.name}@${tsAssembly.version}`;
        if (!isSupported) {
            throw new __1.LanguageNotSupportedError(`Language ${language} is not supported for package ${this.assemblyFqn}`);
        }
        let submoduleStr = options.submodule;
        if (allSubmodules && submoduleStr) {
            throw new Error('Cannot call toJson with allSubmodules and a specific submodule both selected.');
        }
        const { assembly, transpile } = await this.languageSpecific(language, { loose, validate });
        const targets = assembly.targets;
        if (!targets) {
            throw new Error(`Assembly ${this.assemblyFqn} does not have any targets defined`);
        }
        const submodule = submoduleStr ? this.findSubmodule(assembly, submoduleStr) : undefined;
        let readme;
        if ((_f = options === null || options === void 0 ? void 0 : options.readme) !== null && _f !== void 0 ? _f : false) {
            readme = new readme_1.Readme(transpile, assembly, submodule).render();
        }
        let apiReference;
        if ((_g = options === null || options === void 0 ? void 0 : options.apiReference) !== null && _g !== void 0 ? _g : true) {
            try {
                apiReference = new api_reference_1.ApiReference(transpile, assembly, submodule, allSubmodules);
            }
            catch (error) {
                if (!(error instanceof Error)) {
                    throw error;
                }
                throw (_h = maybeCorruptedAssemblyError(error)) !== null && _h !== void 0 ? _h : error;
            }
        }
        const contents = {
            version: schema_1.CURRENT_SCHEMA_VERSION,
            language: language.toString(),
            metadata: {
                packageName: assembly.name,
                packageVersion: assembly.version,
                submodule: (0, schema_1.submodulePath)(submodule),
            },
            readme: readme === null || readme === void 0 ? void 0 : readme.render(),
            apiReference: apiReference === null || apiReference === void 0 ? void 0 : apiReference.toJson(),
        };
        return new json_1.Json(contents, {
            spaces: options.spaces,
        });
    }
    async toMarkdown(options) {
        const json = (await this.toJson(options)).content;
        return markdown_render_1.MarkdownRenderer.fromSchema(json, {
            anchorFormatter: options.anchorFormatter,
            linkFormatter: options.linkFormatter,
            typeFormatter: options.typeFormatter,
            header: options.header,
        });
    }
    addCleanupDirectory(directory) {
        this.cleanupDirectories.add(directory);
    }
    /**
     * Removes any internal working directories.
     */
    async cleanup() {
        for (const dir of [...this.cleanupDirectories]) {
            await fs.remove(dir);
            this.cleanupDirectories.delete(dir);
        }
    }
    async languageSpecific(lang, options) {
        const { rosettaTarget, transpile } = exports.LANGUAGE_SPECIFIC[lang.toString()];
        return { assembly: await this.createAssembly(rosettaTarget, options), transpile };
    }
    /**
     * Lookup a submodule by a submodule name.
     *
     * The contract of this function is historically quite confused: the submodule
     * name can be either an FQN (`asm.sub1.sub2`) or just a submodule name
     * (`sub1` or `sub1.sub2`).
     *
     * This is sligthly complicated by ambiguity: `asm.asm.package` and
     * `asm.package` can both exist, and which one do you mean when you say
     * `asm.package`?
     *
     * We prefer an FQN match if possible (`asm.sub1.sub2`), but will accept a
     * root-relative submodule name as well (`sub1.sub2`).
     */
    findSubmodule(assembly, submodule) {
        const fqnSubs = assembly.allSubmodules.filter((s) => s.fqn === submodule);
        if (fqnSubs.length === 1) {
            return fqnSubs[0];
        }
        // Fallback: assembly-relative name
        const relSubs = assembly.allSubmodules.filter((s) => s.fqn === `${assembly.name}.${submodule}`);
        if (relSubs.length === 1) {
            console.error(`[WARNING] findSubmodule() is being called with a relative submodule name: '${submodule}'. Prefer the absolute name: '${assembly.name}.${submodule}'`);
            return relSubs[0];
        }
        if (fqnSubs.length + relSubs.length === 0) {
            throw new Error(`Submodule ${submodule} not found in assembly ${assembly.name}@${assembly.version} (neither as '${submodule}' nor as '${assembly.name}.${submodule})`);
        }
        // Almost impossible that this would be true
        if (fqnSubs.length > 1) {
            throw new Error(`Found multiple submodules with FQN: ${submodule} in assembly ${assembly.name}@${assembly.version}`);
        }
        throw new Error(`Found multiple submodules with relative name: ${submodule} in assembly ${assembly.name}@${assembly.version}`);
    }
    async createAssembly(language, options) {
        const cacheKey = `lang:${language !== null && language !== void 0 ? language : 'ts'}.loose:${options.loose}.validate:${options.validate}`;
        const cached = this.assembliesCache.get(cacheKey);
        if (cached) {
            return cached;
        }
        const created = await withTempDir(async (workdir) => {
            const ts = new reflect.TypeSystem();
            const assemblies = (0, assembly_1.discoverAssemblies)(this.assembliesDir);
            for (let { name: discoveredName, path: dotJsii } of Object.values(assemblies)) {
                // we only transliterate the top level assembly and not the entire type-system.
                // note that the only reason to translate dependant assemblies is to show code examples
                // for expanded python arguments - which we don't to right now anyway.
                // we don't want to make any assumption of the directory structure, so this is the most
                // robust way to detect the root assembly.
                if (discoveredName === this.assemblyName) {
                    // only transliterate if we have received a target lang request
                    if (language) {
                        const packageDir = path.dirname(dotJsii);
                        try {
                            await (0, jsii_rosetta_1.transliterateAssembly)([packageDir], [language], { loose: options.loose, unknownSnippets: jsii_rosetta_1.UnknownSnippetMode.FAIL, outdir: workdir });
                        }
                        catch (e) {
                            throw new __1.TransliterationError(`Could not transliterate snippets in '${this.assemblyFqn}' to ${language}: ${e.message}`);
                        }
                        const langDotJsii = path.join(workdir, `${spec_1.SPEC_FILE_NAME}.${language}`);
                        await loadAssembly(langDotJsii, ts, assemblies, options);
                    }
                    else {
                        await loadAssembly(dotJsii, ts, assemblies, options);
                    }
                }
            }
            return ts.findAssembly(this.assemblyName);
        });
        this.assembliesCache.set(cacheKey, created);
        return created;
    }
}
exports.Documentation = Documentation;
exports.LANGUAGE_SPECIFIC = {
    [transpile_1.Language.PYTHON.toString()]: {
        transpile: new python_1.PythonTranspile(),
        rosettaTarget: jsii_rosetta_1.TargetLanguage.PYTHON,
    },
    [transpile_1.Language.TYPESCRIPT.toString()]: {
        transpile: new typescript_1.TypeScriptTranspile(),
        rosettaTarget: undefined, // no transpilation needed
    },
    [transpile_1.Language.JAVA.toString()]: {
        transpile: new java_1.JavaTranspile(),
        rosettaTarget: jsii_rosetta_1.TargetLanguage.JAVA,
    },
    [transpile_1.Language.CSHARP.toString()]: {
        transpile: new csharp_1.CSharpTranspile(),
        rosettaTarget: jsii_rosetta_1.TargetLanguage.CSHARP,
    },
    [transpile_1.Language.GO.toString()]: {
        transpile: new go_1.GoTranspile(),
        rosettaTarget: jsii_rosetta_1.TargetLanguage.GO,
    },
};
/**
 * Loads the specified assembly document into the provided type system, and
 * recursively attempt to load the assembly's dependencies.
 *
 * @param dotJsii the assembly to be loaded.
 * @param ts the type system in which the assembly is to be loaded.
 * @param validate whether assemblies should be validated.
 */
async function loadAssembly(dotJsii, ts, availableAssemblies, { validate } = {}) {
    var _a;
    const loaded = await ts.load(dotJsii, { validate, supportedFeatures: exports.SUPPORTED_ASSEMBLY_FEATURES });
    for (const [dep, version] of Object.entries((_a = loaded.spec.dependencies) !== null && _a !== void 0 ? _a : {})) {
        if (ts.tryFindAssembly(dep) != null) {
            // dependency already loaded... move on...
            continue;
        }
        const depPath = (0, assembly_1.bestAssemblyMatch)(availableAssemblies, `${dep}@${version}`).path;
        try {
            await loadAssembly(depPath, ts, availableAssemblies, { validate });
        }
        catch (error) {
            // Silently ignore any resolution errors... We'll fail later if the dependency is
            // ACTUALLY required, but it's okay to omit it if none of its types are actually exposed
            // by the translated assembly's own API.
        }
    }
    return loaded;
}
async function withTempDir(work) {
    const workdir = await fs.mkdtemp(path.join(os.tmpdir(), path.sep));
    const cwd = process.cwd();
    try {
        process.chdir(workdir);
        // wait for the work to be completed before
        // we cleanup the work environment.
        return await work(workdir);
    }
    finally {
        process.chdir(cwd);
        await fs.remove(workdir);
    }
}
function extractPackageName(spec) {
    const firstAt = spec.indexOf('@');
    if (firstAt === 0) {
        const lastAt = spec.indexOf('@', firstAt + 1);
        if (lastAt === -1) {
            // @aws-cdk/aws-ecr
            return spec;
        }
        else {
            // @aws-cdk/aws-ecr@2.0.0
            return spec.substring(0, lastAt);
        }
    }
    if (firstAt > 0) {
        // aws-cdk-lib@2.0.0
        return spec.substring(0, firstAt);
    }
    // aws-cdk-lib
    return spec;
}
/**
 * Return a `CorruptedAssemblyError` if the error matches, undefined otherwise.
 *
 * Note that an 'not found in assembly` can be thrown in two cases:
 *
 * 1. Direct usage of `assembly.findType(fqn)`
 *
 *    In this case the error could be caused by a wrong FQN being passed to the function. This is not considered
 *    a corrupted assembly since the caller might be passing an FQN from a different assembly.
 *
 * 2. Implicit usage of `assembly.findType(fqn)` by calling `.type` (e.g `parameter.type`)
 *
 *    In this case the assembly we look in is always the same assembly the type itself comes from, and if it doesn't exist,
 *    then the assembly is considered corrupt.
 */
function maybeCorruptedAssemblyError(error) {
    if (isAssemblyNotFound(error) || isNotFoundInAssmebly(error)) {
        return new __1.CorruptedAssemblyError(error.message);
    }
    return;
}
function isNotFoundInAssmebly(error) {
    const match = error.message.match(NOT_FOUND_IN_ASSEMBLY_REGEX);
    if (!match) {
        return false;
    }
    const searchedAssembly = match[2];
    const typeAssembly = match[1];
    if (searchedAssembly === typeAssembly
        // take into account submodules (e.g aws-cdk-lib.aws_kms.IKeyRef)
        || typeAssembly.startsWith(searchedAssembly + '.')) {
        return true;
    }
    return false;
}
function isAssemblyNotFound(error) {
    const match = error.message.match(ASSEMBLY_NOT_FOUND_REGEX);
    if (!match) {
        return false;
    }
    return true;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZG9jdW1lbnRhdGlvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9kb2NnZW4vdmlldy9kb2N1bWVudGF0aW9uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQWtnQkEsZ0RBcUJDO0FBdmhCRCx1Q0FBeUI7QUFDekIsMkNBQTZCO0FBQzdCLHFDQUF5RDtBQUN6RCw2Q0FBK0I7QUFDL0Isc0RBQXdDO0FBQ3hDLCtDQUF5RjtBQUN6RixpQ0FBNkI7QUFDN0IsbURBQStDO0FBQy9DLHFDQUFrQztBQUNsQyw2QkFBZ0c7QUFDaEcseUNBQTZEO0FBQzdELHlEQUEwRDtBQUMxRCwrREFBd0Y7QUFDeEYsc0NBQTBFO0FBQzFFLHlDQUFtRjtBQUNuRixnREFBc0Q7QUFDdEQsd0NBQThDO0FBQzlDLDRDQUFrRDtBQUNsRCxnREFBc0Q7QUFDdEQsc0RBQTZEO0FBQzdELHdEQUE4RDtBQUU5RCx1RkFBdUY7QUFDdkYsTUFBTSwyQkFBMkIsR0FBRyw2Q0FBNkMsQ0FBQztBQUVsRiwwRkFBMEY7QUFDMUYsTUFBTSx3QkFBd0IsR0FBRywyQkFBMkIsQ0FBQztBQUVoRCxRQUFBLDJCQUEyQixHQUFrQixDQUFDLG9CQUFvQixFQUFFLDJCQUEyQixDQUFDLENBQUM7QUFpRzlHOztHQUVHO0FBQ0gsTUFBYSxhQUFhO0lBRXhCOzs7Ozs7Ozs7OztPQVdHO0lBQ0ksTUFBTSxDQUFDLEtBQUssQ0FBQyxVQUFVLENBQUMsTUFBYyxFQUFFLFVBQTBDLEVBQUU7O1FBQ3pGLE1BQU0sT0FBTyxHQUFHLE1BQU0sRUFBRSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxNQUFNLEVBQUUsRUFBRSxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztRQUVuRSxNQUFNLEdBQUcsR0FBRyxJQUFJLFVBQUcsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUU3QixJQUFJ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QUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsd0JBQXdCLENBQUMsQ0FBQztJQUM1RCxJQUFJLENBQUMsS0FBSyxFQUFFLENBQUM7UUFDWCxPQUFPLEtBQUssQ0FBQztJQUNmLENBQUM7SUFDRCxPQUFPLElBQUksQ0FBQztBQUVkLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyBvcyBmcm9tICdvcyc7XG5pbXBvcnQgKiBhcyBwYXRoIGZyb20gJ3BhdGgnO1xuaW1wb3J0IHsgSnNpaUZlYXR1cmUsIFNQRUNfRklMRV9OQU1FIH0gZnJvbSAnQGpzaWkvc3BlYyc7XG5pbXBvcnQgKiBhcyBmcyBmcm9tICdmcy1leHRyYSc7XG5pbXBvcnQgKiBhcyByZWZsZWN0IGZyb20gJ2pzaWktcmVmbGVjdCc7XG5pbXBvcnQgeyBUYXJnZXRMYW5ndWFnZSwgdHJhbnNsaXRlcmF0ZUFzc2VtYmx5LCBVbmtub3duU25pcHBldE1vZGUgfSBmcm9tICdqc2lpLXJvc2V0dGEnO1xuaW1wb3J0IHsgTnBtIH0gZnJvbSAnLi9fbnBtJztcbmltcG9ydCB7IEFwaVJlZmVyZW5jZSB9IGZyb20gJy4vYXBpLXJlZmVyZW5jZSc7XG5pbXBvcnQgeyBSZWFkbWUgfSBmcm9tICcuL3JlYWRtZSc7XG5pbXBvcnQgeyBDb3JydXB0ZWRBc3NlbWJseUVycm9yLCBMYW5ndWFnZU5vdFN1cHBvcnRlZEVycm9yLCBUcmFuc2xpdGVyYXRpb25FcnJvciB9IGZyb20gJy4uLy4uJztcbmltcG9ydCB7IEpzb24sIEpzb25Gb3JtYXR0aW5nT3B0aW9ucyB9IGZyb20gJy4uL3JlbmRlci9qc29uJztcbmltcG9ydCB7IE1hcmtkb3duRG9jdW1lbnQgfSBmcm9tICcuLi9yZW5kZXIvbWFya2Rvd24tZG9jJztcbmltcG9ydCB7IE1hcmtkb3duRm9ybWF0dGluZ09wdGlvbnMsIE1hcmtkb3duUmVuZGVyZXIgfSBmcm9tICcuLi9yZW5kZXIvbWFya2Rvd24tcmVuZGVyJztcbmltcG9ydCB7IFNjaGVtYSwgQ1VSUkVOVF9TQ0hFTUFfVkVSU0lPTiwgc3VibW9kdWxlUGF0aCB9IGZyb20gJy4uL3NjaGVtYSc7XG5pbXBvcnQgeyBBc3NlbWJseUxvb2t1cCwgYmVzdEFzc2VtYmx5TWF0Y2gsIGRpc2NvdmVyQXNzZW1ibGllcyB9IGZyb20gJy4vYXNzZW1ibHknO1xuaW1wb3J0IHsgQ1NoYXJwVHJhbnNwaWxlIH0gZnJvbSAnLi4vdHJhbnNwaWxlL2NzaGFycCc7XG5pbXBvcnQgeyBHb1RyYW5zcGlsZSB9IGZyb20gJy4uL3RyYW5zcGlsZS9nbyc7XG5pbXBvcnQgeyBKYXZhVHJhbnNwaWxlIH0gZnJvbSAnLi4vdHJhbnNwaWxlL2phdmEnO1xuaW1wb3J0IHsgUHl0aG9uVHJhbnNwaWxlIH0gZnJvbSAnLi4vdHJhbnNwaWxlL3B5dGhvbic7XG5pbXBvcnQgeyBUcmFuc3BpbGUsIExhbmd1YWdlIH0gZnJvbSAnLi4vdHJhbnNwaWxlL3RyYW5zcGlsZSc7XG5pbXBvcnQgeyBUeXBlU2NyaXB0VHJhbnNwaWxlIH0gZnJvbSAnLi4vdHJhbnNwaWxlL3R5cGVzY3JpcHQnO1xuXG4vLyBodHRwczovL2dpdGh1Yi5jb20vYXdzL2pzaWkvYmxvYi92MS4xMjIuMC9wYWNrYWdlcy9qc2lpLXJlZmxlY3QvbGliL2Fzc2VtYmx5LnRzI0wyMzNcbmNvbnN0IE5PVF9GT1VORF9JTl9BU1NFTUJMWV9SRUdFWCA9IC9UeXBlICcoLiopXFwuLionIG5vdCBmb3VuZCBpbiBhc3NlbWJseSAoLiopJC87XG5cbi8vIGh0dHBzOi8vZ2l0aHViLmNvbS9hd3MvanNpaS9ibG9iL3YxLjEyMi4wL3BhY2thZ2VzL2pzaWktcmVmbGVjdC9saWIvdHlwZS1zeXN0ZW0udHMjTDI1MlxuY29uc3QgQVNTRU1CTFlfTk9UX0ZPVU5EX1JFR0VYID0gL0Fzc2VtYmx5IFwiKC4qKVwiIG5vdCBmb3VuZC87XG5cbmV4cG9ydCBjb25zdCBTVVBQT1JURURfQVNTRU1CTFlfRkVBVFVSRVM6IEpzaWlGZWF0dXJlW10gPSBbJ2ludGVyc2VjdGlvbi10eXBlcycsICdjbGFzcy1jb3ZhcmlhbnQtb3ZlcnJpZGVzJ107XG5cbi8qKlxuICogT3B0aW9ucyBmb3IgcmVuZGVyaW5nIGEgYERvY3VtZW50YXRpb25gIG9iamVjdC5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBSZW5kZXJPcHRpb25zIGV4dGVuZHMgVHJhbnNsaXRlcmF0aW9uT3B0aW9ucyB7XG4gIC8qKlxuICAgKiBXaGljaCBsYW5ndWFnZSB0byBnZW5lcmF0ZSBkb2NzIGZvci5cbiAgICovXG4gIHJlYWRvbmx5IGxhbmd1YWdlOiBMYW5ndWFnZTtcblxuICAvKipcbiAgICogSW5jbHVkZSBhIGdlbmVyYXRlZCBhcGkgcmVmZXJlbmNlIGluIHRoZSBkb2N1bWVudGF0aW9uLlxuICAgKlxuICAgKiBAZGVmYXVsdCB0cnVlXG4gICAqL1xuICByZWFkb25seSBhcGlSZWZlcmVuY2U/OiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBJbmNsdWRlIHRoZSB1c2VyIGRlZmluZWQgUkVBRE1FLm1kIGluIHRoZSBkb2N1bWVudGF0aW9uLlxuICAgKlxuICAgKiBAZGVmYXVsdCBmYWxzZVxuICAgKi9cbiAgcmVhZG9ubHkgcmVhZG1lPzogYm9vbGVhbjtcblxuICAvKipcbiAgICogR2VuZXJhdGUgZG9jdW1lbnRhdGlvbiBvbmx5IGZvciBhIHNwZWNpZmljIHN1Ym1vZHVsZS5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBEb2N1bWVudGF0aW9uIGlzIGdlbmVyYXRlZCBmb3IgdGhlIHJvb3QgbW9kdWxlIG9ubHkuXG4gICAqL1xuICByZWFkb25seSBzdWJtb2R1bGU/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIEdlbmVyYXRlIGEgc2luZ2xlIGRvY3VtZW50IHdpdGggQVBJcyBmcm9tIGFsbCBhc3NlbWJseSBzdWJtb2R1bGVzXG4gICAqIChpbmNsdWRpbmcgdGhlIHJvb3QpLlxuICAgKlxuICAgKiBOb3RlOiBvbmx5IHRoZSByb290LWxldmVsIFJFQURNRSBpcyBpbmNsdWRlZC5cbiAgICpcbiAgICogQGRlZmF1bHQgZmFsc2VcbiAgICovXG4gIHJlYWRvbmx5IGFsbFN1Ym1vZHVsZXM/OiBib29sZWFuO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFRyYW5zbGl0ZXJhdGlvbk9wdGlvbnMge1xuICAvKipcbiAgICogV2hldGhlciB0byBpZ25vcmUgbWlzc2luZyBmaXh0dXJlIGZpbGVzIHRoYXQgd2lsbCBwcmV2ZW50IHRyYW5zbGl0ZXJhdGluZ1xuICAgKiBzb21lIGNvZGUgc25pcHBldCBleGFtcGxlcy5cbiAgICpcbiAgICogQGRlZmF1bHQgdHJ1ZVxuICAgKi9cbiAgcmVhZG9ubHkgbG9vc2U/OiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBXaGV0aGVyIHRvIHZhbGlkYXRlIGpzaWkgYXNzZW1ibGllcyBhZ2FpbnN0IHRoZSBqc2lpIHNjaGVtYSBiZWZvcmVcbiAgICogdXNpbmcgdGhlbS5cbiAgICpcbiAgICogQGRlZmF1bHQgZmFsc2VcbiAgICovXG4gIHJlYWRvbmx5IHZhbGlkYXRlPzogYm9vbGVhbjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBNYXJrZG93blJlbmRlck9wdGlvbnMgZXh0ZW5kcyBSZW5kZXJPcHRpb25zLCBNYXJrZG93bkZvcm1hdHRpbmdPcHRpb25zIHsgfVxuXG5leHBvcnQgaW50ZXJmYWNlIEpzb25SZW5kZXJPcHRpb25zIGV4dGVuZHMgUmVuZGVyT3B0aW9ucywgSnNvbkZvcm1hdHRpbmdPcHRpb25zIHsgfVxuXG4vKipcbiAqIE9wdGlvbnMgZm9yIGNyZWF0aW5nIGEgYERvY3VtZW50YXRpb25gIG9iamVjdCB1c2luZyB0aGUgYGZyb21Mb2NhbFBhY2thZ2VgIGZ1bmN0aW9uLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIEZvckxvY2FsUGFja2FnZURvY3VtZW50YXRpb25PcHRpb25zIHtcblxuICAvKipcbiAgICogQSBsb2NhbCBkaXJlY3RvcnkgY29udGFpbmluZyBqc2lpIGFzc2VtYmx5IGZpbGVzIHRoYXQgd2lsbFxuICAgKiBjb21wcmlzZSB0aGUgdHlwZS1zeXN0ZW0uXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gdGhlIHJvb3QgcGFja2FnZSBkaXJlY3Rvcnkgd2lsbCBiZSB1c2VkLlxuICAgKi9cbiAgcmVhZG9ubHkgYXNzZW1ibGllc0Rpcj86IHN0cmluZztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBGb3JQYWNrYWdlRG9jdW1lbnRhdGlvbk9wdGlvbnMge1xuICAvKipcbiAgICogV2hldGhlciB2ZXJib3NlIGxvZ2dpbmcgaXMgdG8gYmUgcGVyZm9ybWVkLlxuICAgKlxuICAgKiBAZGVmYXVsdCB0cnVlXG4gICAqL1xuICByZWFkb25seSB2ZXJib3NlPzogYm9vbGVhbjtcblxuICAvKipcbiAgICogQSBmdW5jdGlvbiB0byBydW4gYWZ0ZXIgcnVubmluZyBgbnBtIGluc3RhbGxgIGZvciB0aGUgdGFyZ2V0IHBhY2thZ2UuIFRoaXNcbiAgICogZXhpc3RzIG9ubHkgZm9yIHRlc3RpbmcgcHVycG9zZXMgYW5kIHNob3VsZCBub3QgYmUgdXNlZCBieSBjb25zdW1lcnMgb2ZcbiAgICogdGhpcyBtb2R1bGUuXG4gICAqXG4gICAqIEBpbnRlcm5hbFxuICAgKi9cbiAgcmVhZG9ubHkgX3Bvc3RJbnN0YWxsPzogKGRpcjogc3RyaW5nKSA9PiBQcm9taXNlPHZvaWQ+O1xufVxuXG4vKipcbiAqIFJlbmRlciBkb2N1bWVudGF0aW9uIHBhZ2VzIGZvciBhIGpzaWkgbGlicmFyeS5cbiAqL1xuZXhwb3J0IGNsYXNzIERvY3VtZW50YXRpb24ge1xuXG4gIC8qKlxuICAgKiBDcmVhdGUgYSBgRG9jdW1lbnRhdGlvbmAgb2JqZWN0IGZyb20gYSBwYWNrYWdlIGluc3RhbGxhYmxlIGJ5IG5wbS5cbiAgICpcbiAgICogTm90ZSB0aGF0IHRoaXMgbWV0aG9kIGluc3RhbGxzIHRoZSB0YXJnZXQgcGFja2FnZSB0byB0aGUgbG9jYWwgZmlsZS1zeXN0ZW0uIE1ha2Ugc3VyZVxuICAgKiB0byBjYWxsIGBEb2N1bWVudGF0aW9uLmNsZWFudXBgIG9uY2UgeW91IGFyZSBkb25lIHJlbmRlcmluZy5cbiAgICpcbiAgICogQHBhcmFtIHRhcmdldCAtIFRoZSB0YXJnZXQgdG8gaW5zdGFsbC4gVGhpcyBjYW4gZWl0aGVyIGJlIGEgbG9jYWwgcGF0aCBvciBhIHJlZ2lzdHJ5IGlkZW50aWZpZXIgKGUuZyA8bmFtZT5APHZlcnNpb24+KVxuICAgKiBAcGFyYW0gb3B0aW9ucyAtIEFkZGl0aW9uYWwgb3B0aW9ucy5cbiAgICpcbiAgICogQHRocm93cyBOb1NwYWNlTGVmdE9uRGV2aWNlIGlmIHRoZSBpbnN0YWxsYXRpb24gZmFpbHMgZHVlIHRvIHJ1bm5pbmcgb3V0IG9mIGRpc2sgc3BhY2VcbiAgICogQHRocm93cyBOcG1FcnJvciBpZiBzb21lIGBucG1gIGNvbW1hbmQgZmFpbHMgd2hlbiBwcmVwYXJpbmcgdGhlIHdvcmtpbmcgc2V0XG4gICAqL1xuICBwdWJsaWMgc3RhdGljIGFzeW5jIGZvclBhY2thZ2UodGFyZ2V0OiBzdHJpbmcsIG9wdGlvbnM6IEZvclBhY2thZ2VEb2N1bWVudGF0aW9uT3B0aW9ucyA9IHt9KTogUHJvbWlzZTxEb2N1bWVudGF0aW9uPiB7XG4gICAgY29uc3Qgd29ya2RpciA9IGF3YWl0IGZzLm1rZHRlbXAocGF0aC5qb2luKG9zLnRtcGRpcigpLCBwYXRoLnNlcCkpO1xuXG4gICAgY29uc3QgbnBtID0gbmV3IE5wbSh3b3JrZGlyKTtcblxuICAgIGlmIChvcHRpb25zLnZlcmJvc2UgPz8gdHJ1ZSkge1xuICAgICAgY29uc29sZS5sb2coYEluc3RhbGxpbmcgcGFja2FnZSAke3RhcmdldH1gKTtcbiAgICB9XG5cbiAgICBjb25zdCBuYW1lID0gYXdhaXQgbnBtLmluc3RhbGwodGFyZ2V0KTtcblxuICAgIGlmIChvcHRpb25zLl9wb3N0SW5zdGFsbCAhPSBudWxsKSB7XG4gICAgICBhd2FpdCBvcHRpb25zLl9wb3N0SW5zdGFsbCh3b3JrZGlyKTtcbiAgICB9XG5cbiAgICBjb25zdCBkb2NzID0gYXdhaXQgRG9jdW1lbnRhdGlvbi5mb3JQcm9qZWN0KHBhdGguam9pbih3b3JrZGlyLCAnbm9kZV9tb2R1bGVzJywgbmFtZSksIHsgLi4ub3B0aW9ucywgYXNzZW1ibGllc0Rpcjogd29ya2RpciB9KTtcblxuICAgIC8vIHdlIGNhbm5vdCBkZWxldGUgdGhpcyBkaXJlY3RvcnkgaW1tZWRpYXRlbHkgc2luY2UgaXQgaXMgdXNlZCBkdXJpbmcgYHJlbmRlcmAgY2FsbHMuXG4gICAgLy8gaW5zdGVhZCB3ZSByZWdpc3RlciBpdCBzbyB0aGF0IGNhbGxlcnMgY2FuIGNsZWFuIGl0IHVwIGJ5IGNhbGxpbmcgdGhlIGBjbGVhbnVwYCBtZXRob2QuXG4gICAgZG9jcy5hZGRDbGVhbnVwRGlyZWN0b3J5KHdvcmtkaXIpO1xuXG4gICAgcmV0dXJuIGRvY3M7XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlIGEgYERvY3VtZW50YXRpb25gIG9iamVjdCBmcm9tIGEgbG9jYWwgZGlyZWN0b3J5IGNvbnRhaW5pbmcgYSBub2RlIHByb2plY3QuXG4gICAqXG4gICAqIEBwYXJhbSByb290IC0gVGhlIGxvY2FsIGRpcmVjdG9yeSBwYXRoLiBNdXN0IGNvbnRhaW4gYSBwYWNrYWdlLmpzb24gZmlsZS5cbiAgICogQHBhcmFtIG9wdGlvbnMgLSBBZGRpdGlvbmFsIG9wdGlvbnMuXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIGFzeW5jIGZvclByb2plY3Qocm9vdDogc3RyaW5nLCBvcHRpb25zOiBGb3JMb2NhbFBhY2thZ2VEb2N1bWVudGF0aW9uT3B0aW9ucyA9IHt9KTogUHJvbWlzZTxEb2N1bWVudGF0aW9uPiB7XG4gICAgY29uc3QgbWFuaWZlc3RQYXRoID0gcGF0aC5qb2luKHJvb3QsICdwYWNrYWdlLmpzb24nKTtcbiAgICBpZiAoIShhd2FpdCBmcy5wYXRoRXhpc3RzKG1hbmlmZXN0UGF0aCkpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYFVuYWJsZSB0byBsb2NhdGUgJHttYW5pZmVzdFBhdGh9YCk7XG4gICAgfVxuXG4gICAgLy8gbm9ybWFsbHkgdGhlIGFzc2VtYmxpZXMgYXJlIGxvY2F0ZWQgaW4gc3ViZGlyZWN0b3JpZXNcbiAgICAvLyBvZiB0aGUgcm9vdCBwYWNrYWdlIGRpciAoaS5lIC4vbm9kZV9tb2R1bGVzKVxuICAgIGNvbnN0IGFzc2VtYmxpZXNEaXIgPSBvcHRpb25zPy5hc3NlbWJsaWVzRGlyID8/IHJvb3Q7XG5cbiAgICBjb25zdCB7IG5hbWUgfSA9IEpTT04ucGFyc2UoYXdhaXQgZnMucmVhZEZpbGUobWFuaWZlc3RQYXRoLCAndXRmLTgnKSk7XG4gICAgcmV0dXJuIERvY3VtZW50YXRpb24uZm9yQXNzZW1ibHkobmFtZSwgYXNzZW1ibGllc0Rpcik7XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlIGEgYERvY3VtZW50YXRpb25gIG9iamVjdCBmb3IgYSBzcGVjaWZpYyBhc3NlbWJseSBmcm9tIGEgZGlyZWN0b3J5IG9mIGFzc2VtYmxpZXMuXG4gICAqXG4gICAqIEBwYXJhbSBhc3NlbWJseU5hbWUgLSBUaGUgYXNzZW1ibHkgbmFtZS5cbiAgICogQHBhcmFtIGFzc2VtYmxpZXNEaXIgLSBUaGUgZGlyZWN0b3J5IGNvbnRhaW5pbmcgdGhlIGFzc2VtYmxpZXMgdGhhdCBjb21wcmlzZSB0aGUgdHlwZS1zeXN0ZW0uXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIGFzeW5jIGZvckFzc2VtYmx5KGFzc2VtYmx5TmFtZTogc3RyaW5nLCBhc3NlbWJsaWVzRGlyOiBzdHJpbmcpOiBQcm9taXNlPERvY3VtZW50YXRpb24+IHtcbiAgICByZXR1cm4gbmV3IERvY3VtZW50YXRpb24oYXNzZW1ibHlOYW1lLCBhc3NlbWJsaWVzRGlyKTtcbiAgfVxuXG4gIHByaXZhdGUgcmVhZG9ubHkgY2xlYW51cERpcmVjdG9yaWVzOiBTZXQ8c3RyaW5nPiA9IG5ldyBTZXQ8c3RyaW5nPigpO1xuICBwcml2YXRlIHJlYWRvbmx5IGFzc2VtYmxpZXNDYWNoZTogTWFwPHN0cmluZywgcmVmbGVjdC5Bc3NlbWJseT4gPSBuZXcgTWFwPHN0cmluZywgcmVmbGVjdC5Bc3NlbWJseT4oKTtcbiAgcHJpdmF0ZSBhc3NlbWJseUZxbjogc3RyaW5nIHwgdW5kZWZpbmVkO1xuXG4gIHByaXZhdGUgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSByZWFkb25seSBhc3NlbWJseU5hbWU6IHN0cmluZyxcbiAgICBwcml2YXRlIHJlYWRvbmx5IGFzc2VtYmxpZXNEaXI6IHN0cmluZyxcbiAgKSB7IH1cblxuICAvKipcbiAgICogTGlzdCBhbGwgc3VibW9kdWxlcyBpbiB0aGUgYXNzZW1ibHkuXG4gICAqL1xuICBwdWJsaWMgYXN5bmMgbGlzdFN1Ym1vZHVsZXMoKSB7XG4gICAgY29uc3QgdHNBc3NlbWJseSA9IGF3YWl0IHRoaXMuY3JlYXRlQXNzZW1ibHkodW5kZWZpbmVkLCB7IGxvb3NlOiB0cnVlLCB2YWxpZGF0ZTogZmFsc2UgfSk7XG4gICAgcmV0dXJuIHRzQXNzZW1ibHkuYWxsU3VibW9kdWxlcztcbiAgfVxuXG4gIHB1YmxpYyBhc3luYyB0b0luZGV4TWFya2Rvd24oZmlsZVN1ZmZpeDogc3RyaW5nLCBvcHRpb25zOiBSZW5kZXJPcHRpb25zKSB7XG4gICAgY29uc3QgYXNzZW1ibHkgPSBhd2FpdCB0aGlzLmNyZWF0ZUFzc2VtYmx5KHVuZGVmaW5lZCwgeyBsb29zZTogdHJ1ZSwgdmFsaWRhdGU6IGZhbHNlIH0pO1xuICAgIGNvbnN0IHN1Ym1vZHVsZXMgPSBhd2FpdCB0aGlzLmxpc3RTdWJtb2R1bGVzKCk7XG4gICAgY29uc3Qgc2NoZW1hID0gKGF3YWl0IHRoaXMudG9Kc29uKHtcbiAgICAgIC4uLm9wdGlvbnMsXG4gICAgICBzdWJtb2R1bGU6IHVuZGVmaW5lZCxcbiAgICAgIGFsbFN1Ym1vZHVsZXM6IGZhbHNlLFxuICAgIH0pKS5jb250ZW50O1xuXG4gICAgY29uc3QgcmVmID0gbmV3IE1hcmtkb3duRG9jdW1lbnQoeyBoZWFkZXI6IHsgdGl0bGU6ICdBUEkgUmVmZXJlbmNlJyB9LCBpZDogJ2FwaS1yZWZlcmVuY2UnIH0pO1xuXG4gICAgaWYgKHNjaGVtYS52ZXJzaW9uICE9PSBDVVJSRU5UX1NDSEVNQV9WRVJTSU9OKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYFVuZXhwZWN0ZWQgc2NoZW1hIHZlcnNpb246ICR7c2NoZW1hLnZlcnNpb259YCk7XG4gICAgfVxuXG4gICAgY29uc3QgcmVuZGVyZXIgPSBuZXcgTWFya2Rvd25SZW5kZXJlcih7XG4gICAgICBsYW5ndWFnZTogb3B0aW9ucy5sYW5ndWFnZSxcbiAgICAgIHBhY2thZ2VOYW1lOiBhc3NlbWJseS5uYW1lLFxuICAgICAgcGFja2FnZVZlcnNpb246IGFzc2VtYmx5LnZlcnNpb24sXG4gICAgfSk7XG5cbiAgICBpZiAoc3VibW9kdWxlcy5sZW5ndGgpIHtcbiAgICAgIHJlZi5zZWN0aW9uKHJlbmRlcmVyLnZpc2l0U3VibW9kdWxlcyhzdWJtb2R1bGVzLCBmaWxlU3VmZml4KSk7XG4gICAgfVxuXG4gICAgaWYgKHNjaGVtYS5hcGlSZWZlcmVuY2UpIHtcbiAgICAgIHJlZi5zZWN0aW9uKHJlbmRlcmVyLnZpc2l0Q29uc3RydWN0cyhzY2hlbWEuYXBpUmVmZXJlbmNlLmNvbnN0cnVjdHMpKTtcbiAgICAgIHJlZi5zZWN0aW9uKHJlbmRlcmVyLnZpc2l0U3RydWN0cyhzY2hlbWEuYXBpUmVmZXJlbmNlLnN0cnVjdHMpKTtcbiAgICAgIHJlZi5zZWN0aW9uKHJlbmRlcmVyLnZpc2l0Q2xhc3NlcyhzY2hlbWEuYXBpUmVmZXJlbmNlLmNsYXNzZXMpKTtcbiAgICAgIHJlZi5zZWN0aW9uKHJlbmRlcmVyLnZpc2l0SW50ZXJmYWNlcyhzY2hlbWEuYXBpUmVmZXJlbmNlLmludGVyZmFjZXMpKTtcbiAgICAgIHJlZi5zZWN0aW9uKHJlbmRlcmVyLnZpc2l0RW51bXMoc2NoZW1hLmFwaVJlZmVyZW5jZS5lbnVtcykpO1xuICAgIH1cblxuICAgIGNvbnN0IGRvY3VtZW50YXRpb24gPSBuZXcgTWFya2Rvd25Eb2N1bWVudCgpO1xuICAgIGRvY3VtZW50YXRpb24uc2VjdGlvbihyZWYpO1xuICAgIHJldHVybiBkb2N1bWVudGF0aW9uO1xuICB9XG5cbiAgLyoqXG4gICAqIEdlbmVyYXRlIG1hcmtkb3duLlxuICAgKi9cbiAgcHVibGljIGFzeW5jIHRvSnNvbihvcHRpb25zOiBKc29uUmVuZGVyT3B0aW9ucyk6IFByb21pc2U8SnNvbjxTY2hlbWE+PiB7XG5cbiAgICBjb25zdCBsYW5ndWFnZSA9IG9wdGlvbnMubGFuZ3VhZ2UgPz8gTGFuZ3VhZ2UuVFlQRVNDUklQVDtcbiAgICBjb25zdCBsb29zZSA9IG9wdGlvbnMubG9vc2UgPz8gdHJ1ZTtcbiAgICBjb25zdCB2YWxpZGF0ZSA9IG9wdGlvbnMudmFsaWRhdGUgPz8gZmFsc2U7XG4gICAgY29uc3QgYWxsU3VibW9kdWxlcyA9IG9wdGlvbnMuYWxsU3VibW9kdWxlcyA/PyBmYWxzZTtcblxuXG4gICAgLy8gR2V0IHRoZSBUUyBhc3NlbWJseSBmaXJzdCB0byBjaGVjayB3aGF0IGxhbmd1YWdlcyBhcmUgc3VwcG9ydGVkIGJlZm9yZSBjYWxsaW5nIHJvc2V0dGFcbiAgICBjb25zdCB0c0Fzc2VtYmx5ID0gYXdhaXQgdGhpcy5jcmVhdGVBc3NlbWJseSh1bmRlZmluZWQsIHsgbG9vc2UsIHZhbGlkYXRlIH0pO1xuICAgIGNvbnN0IGlzU3VwcG9ydGVkID0gbGFuZ3VhZ2UgPT09IExhbmd1YWdlLlRZUEVTQ1JJUFQgfHwgbGFuZ3VhZ2UuaXNWYWxpZENvbmZpZ3VyYXRpb24odHNBc3NlbWJseT8udGFyZ2V0cz8uW2xhbmd1YWdlLnRhcmdldE5hbWVdKTtcbiAgICB0aGlzLmFzc2VtYmx5RnFuID0gYCR7dHNBc3NlbWJseS5uYW1lfUAke3RzQXNzZW1ibHkudmVyc2lvbn1gO1xuXG4gICAgaWYgKCFpc1N1cHBvcnRlZCkge1xuICAgICAgdGhyb3cgbmV3IExhbmd1YWdlTm90U3VwcG9ydGVkRXJyb3IoYExhbmd1YWdlICR7bGFuZ3VhZ2V9IGlzIG5vdCBzdXBwb3J0ZWQgZm9yIHBhY2thZ2UgJHt0aGlzLmFzc2VtYmx5RnFufWApO1xuICAgIH1cblxuICAgIGxldCBzdWJtb2R1bGVTdHIgPSBvcHRpb25zLnN1Ym1vZHVsZTtcblxuICAgIGlmIChhbGxTdWJtb2R1bGVzICYmIHN1Ym1vZHVsZVN0cikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW5ub3QgY2FsbCB0b0pzb24gd2l0aCBhbGxTdWJtb2R1bGVzIGFuZCBhIHNwZWNpZmljIHN1Ym1vZHVsZSBib3RoIHNlbGVjdGVkLicpO1xuICAgIH1cblxuICAgIGNvbnN0IHsgYXNzZW1ibHksIHRyYW5zcGlsZSB9ID0gYXdhaXQgdGhpcy5sYW5ndWFnZVNwZWNpZmljKGxhbmd1YWdlLCB7IGxvb3NlLCB2YWxpZGF0ZSB9KTtcbiAgICBjb25zdCB0YXJnZXRzID0gYXNzZW1ibHkudGFyZ2V0cztcblxuICAgIGlmICghdGFyZ2V0cykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBBc3NlbWJseSAke3RoaXMuYXNzZW1ibHlGcW59IGRvZXMgbm90IGhhdmUgYW55IHRhcmdldHMgZGVmaW5lZGApO1xuICAgIH1cblxuICAgIGNvbnN0IHN1Ym1vZHVsZSA9IHN1Ym1vZHVsZVN0ciA/IHRoaXMuZmluZFN1Ym1vZHVsZShhc3NlbWJseSwgc3VibW9kdWxlU3RyKSA6IHVuZGVmaW5lZDtcblxuICAgIGxldCByZWFkbWU6IE1hcmtkb3duRG9jdW1lbnQgfCB1bmRlZmluZWQ7XG4gICAgaWYgKG9wdGlvbnM/LnJlYWRtZSA/PyBmYWxzZSkge1xuICAgICAgcmVhZG1lID0gbmV3IFJlYWRtZSh0cmFuc3BpbGUsIGFzc2VtYmx5LCBzdWJtb2R1bGUpLnJlbmRlcigpO1xuICAgIH1cblxuICAgIGxldCBhcGlSZWZlcmVuY2U6IEFwaVJlZmVyZW5jZSB8IHVuZGVmaW5lZDtcbiAgICBpZiAob3B0aW9ucz8uYXBpUmVmZXJlbmNlID8/IHRydWUpIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIGFwaVJlZmVyZW5jZSA9IG5ldyBBcGlSZWZlcmVuY2UodHJhbnNwaWxlLCBhc3NlbWJseSwgc3VibW9kdWxlLCBhbGxTdWJtb2R1bGVzKTtcbiAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgIGlmICghKGVycm9yIGluc3RhbmNlb2YgRXJyb3IpKSB7XG4gICAgICAgICAgdGhyb3cgZXJyb3I7XG4gICAgICAgIH1cbiAgICAgICAgdGhyb3cgbWF5YmVDb3JydXB0ZWRBc3NlbWJseUVycm9yKGVycm9yKSA/PyBlcnJvcjtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBjb25zdCBjb250ZW50czogU2NoZW1hID0ge1xuICAgICAgdmVyc2lvbjogQ1VSUkVOVF9TQ0hFTUFfVkVSU0lPTixcbiAgICAgIGxhbmd1YWdlOiBsYW5ndWFnZS50b1N0cmluZygpLFxuICAgICAgbWV0YWRhdGE6IHtcbiAgICAgICAgcGFja2FnZU5hbWU6IGFzc2VtYmx5Lm5hbWUsXG4gICAgICAgIHBhY2thZ2VWZXJzaW9uOiBhc3NlbWJseS52ZXJzaW9uLFxuICAgICAgICBzdWJtb2R1bGU6IHN1Ym1vZHVsZVBhdGgoc3VibW9kdWxlKSxcbiAgICAgIH0sXG4gICAgICByZWFkbWU6IHJlYWRtZT8ucmVuZGVyKCksXG4gICAgICBhcGlSZWZlcmVuY2U6IGFwaVJlZmVyZW5jZT8udG9Kc29uKCksXG4gICAgfTtcblxuICAgIHJldHVybiBuZXcgSnNvbihjb250ZW50cywge1xuICAgICAgc3BhY2VzOiBvcHRpb25zLnNwYWNlcyxcbiAgICB9KTtcbiAgfVxuXG4gIHB1YmxpYyBhc3luYyB0b01hcmtkb3duKG9wdGlvbnM6IE1hcmtkb3duUmVuZGVyT3B0aW9ucyk6IFByb21pc2U8TWFya2Rvd25Eb2N1bWVudD4ge1xuICAgIGNvbnN0IGpzb24gPSAoYXdhaXQgdGhpcy50b0pzb24ob3B0aW9ucykpLmNvbnRlbnQ7XG4gICAgcmV0dXJuIE1hcmtkb3duUmVuZGVyZXIuZnJvbVNjaGVtYShqc29uLCB7XG4gICAgICBhbmNob3JGb3JtYXR0ZXI6IG9wdGlvbnMuYW5jaG9yRm9ybWF0dGVyLFxuICAgICAgbGlua0Zvcm1hdHRlcjogb3B0aW9ucy5saW5rRm9ybWF0dGVyLFxuICAgICAgdHlwZUZvcm1hdHRlcjogb3B0aW9ucy50eXBlRm9ybWF0dGVyLFxuICAgICAgaGVhZGVyOiBvcHRpb25zLmhlYWRlcixcbiAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgYWRkQ2xlYW51cERpcmVjdG9yeShkaXJlY3Rvcnk6IHN0cmluZykge1xuICAgIHRoaXMuY2xlYW51cERpcmVjdG9yaWVzLmFkZChkaXJlY3RvcnkpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlbW92ZXMgYW55IGludGVybmFsIHdvcmtpbmcgZGlyZWN0b3JpZXMuXG4gICAqL1xuICBwdWJsaWMgYXN5bmMgY2xlYW51cCgpIHtcbiAgICBmb3IgKGNvbnN0IGRpciBvZiBbLi4udGhpcy5jbGVhbnVwRGlyZWN0b3JpZXNdKSB7XG4gICAgICBhd2FpdCBmcy5yZW1vdmUoZGlyKTtcbiAgICAgIHRoaXMuY2xlYW51cERpcmVjdG9yaWVzLmRlbGV0ZShkaXIpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgbGFuZ3VhZ2VTcGVjaWZpYyhcbiAgICBsYW5nOiBMYW5ndWFnZSxcbiAgICBvcHRpb25zOiBSZXF1aXJlZDxUcmFuc2xpdGVyYXRpb25PcHRpb25zPixcbiAgKTogUHJvbWlzZTx7IGFzc2VtYmx5OiByZWZsZWN0LkFzc2VtYmx5OyB0cmFuc3BpbGU6IFRyYW5zcGlsZSB9PiB7XG4gICAgY29uc3QgeyByb3NldHRhVGFyZ2V0LCB0cmFuc3BpbGUgfSA9IExBTkdVQUdFX1NQRUNJRklDW2xhbmcudG9TdHJpbmcoKV07XG4gICAgcmV0dXJuIHsgYXNzZW1ibHk6IGF3YWl0IHRoaXMuY3JlYXRlQXNzZW1ibHkocm9zZXR0YVRhcmdldCwgb3B0aW9ucyksIHRyYW5zcGlsZSB9O1xuICB9XG5cbiAgLyoqXG4gICAqIExvb2t1cCBhIHN1Ym1vZHVsZSBieSBhIHN1Ym1vZHVsZSBuYW1lLlxuICAgKlxuICAgKiBUaGUgY29udHJhY3Qgb2YgdGhpcyBmdW5jdGlvbiBpcyBoaXN0b3JpY2FsbHkgcXVpdGUgY29uZnVzZWQ6IHRoZSBzdWJtb2R1bGVcbiAgICogbmFtZSBjYW4gYmUgZWl0aGVyIGFuIEZRTiAoYGFzbS5zdWIxLnN1YjJgKSBvciBqdXN0IGEgc3VibW9kdWxlIG5hbWVcbiAgICogKGBzdWIxYCBvciBgc3ViMS5zdWIyYCkuXG4gICAqXG4gICAqIFRoaXMgaXMgc2xpZ3RobHkgY29tcGxpY2F0ZWQgYnkgYW1iaWd1aXR5OiBgYXNtLmFzbS5wYWNrYWdlYCBhbmRcbiAgICogYGFzbS5wYWNrYWdlYCBjYW4gYm90aCBleGlzdCwgYW5kIHdoaWNoIG9uZSBkbyB5b3UgbWVhbiB3aGVuIHlvdSBzYXlcbiAgICogYGFzbS5wYWNrYWdlYD9cbiAgICpcbiAgICogV2UgcHJlZmVyIGFuIEZRTiBtYXRjaCBpZiBwb3NzaWJsZSAoYGFzbS5zdWIxLnN1YjJgKSwgYnV0IHdpbGwgYWNjZXB0IGFcbiAgICogcm9vdC1yZWxhdGl2ZSBzdWJtb2R1bGUgbmFtZSBhcyB3ZWxsIChgc3ViMS5zdWIyYCkuXG4gICAqL1xuICBwcml2YXRlIGZpbmRTdWJtb2R1bGUoYXNzZW1ibHk6IHJlZmxlY3QuQXNzZW1ibHksIHN1Ym1vZHVsZTogc3RyaW5nKTogcmVmbGVjdC5TdWJtb2R1bGUge1xuICAgIGNvbnN0IGZxblN1YnMgPSBhc3NlbWJseS5hbGxTdWJtb2R1bGVzLmZpbHRlcihcbiAgICAgIChzKSA9PiBzLmZxbiA9PT0gc3VibW9kdWxlLFxuICAgICk7XG4gICAgaWYgKGZxblN1YnMubGVuZ3RoID09PSAxKSB7XG4gICAgICByZXR1cm4gZnFuU3Vic1swXTtcbiAgICB9XG5cbiAgICAvLyBGYWxsYmFjazogYXNzZW1ibHktcmVsYXRpdmUgbmFtZVxuICAgIGNvbnN0IHJlbFN1YnMgPSBhc3NlbWJseS5hbGxTdWJtb2R1bGVzLmZpbHRlcihcbiAgICAgIChzKSA9PiBzLmZxbiA9PT0gYCR7YXNzZW1ibHkubmFtZX0uJHtzdWJtb2R1bGV9YCxcbiAgICApO1xuICAgIGlmIChyZWxTdWJzLmxlbmd0aCA9PT0gMSkge1xuICAgICAgY29uc29sZS5lcnJvcihgW1dBUk5JTkddIGZpbmRTdWJtb2R1bGUoKSBpcyBiZWluZyBjYWxsZWQgd2l0aCBhIHJlbGF0aXZlIHN1Ym1vZHVsZSBuYW1lOiAnJHtzdWJtb2R1bGV9Jy4gUHJlZmVyIHRoZSBhYnNvbHV0ZSBuYW1lOiAnJHthc3NlbWJseS5uYW1lfS4ke3N1Ym1vZHVsZX0nYCk7XG4gICAgICByZXR1cm4gcmVsU3Vic1swXTtcbiAgICB9XG5cbiAgICBpZiAoZnFuU3Vicy5sZW5ndGggKyByZWxTdWJzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBTdWJtb2R1bGUgJHtzdWJtb2R1bGV9IG5vdCBmb3VuZCBpbiBhc3NlbWJseSAke2Fzc2VtYmx5Lm5hbWV9QCR7YXNzZW1ibHkudmVyc2lvbn0gKG5laXRoZXIgYXMgJyR7c3VibW9kdWxlfScgbm9yIGFzICcke2Fzc2VtYmx5Lm5hbWV9LiR7c3VibW9kdWxlfSlgKTtcbiAgICB9XG5cbiAgICAvLyBBbG1vc3QgaW1wb3NzaWJsZSB0aGF0IHRoaXMgd291bGQgYmUgdHJ1ZVxuICAgIGlmIChmcW5TdWJzLmxlbmd0aCA+IDEpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgRm91bmQgbXVsdGlwbGUgc3VibW9kdWxlcyB3aXRoIEZRTjogJHtzdWJtb2R1bGV9IGluIGFzc2VtYmx5ICR7YXNzZW1ibHkubmFtZX1AJHthc3NlbWJseS52ZXJzaW9ufWApO1xuICAgIH1cbiAgICB0aHJvdyBuZXcgRXJyb3IoYEZvdW5kIG11bHRpcGxlIHN1Ym1vZHVsZXMgd2l0aCByZWxhdGl2ZSBuYW1lOiAke3N1Ym1vZHVsZX0gaW4gYXNzZW1ibHkgJHthc3NlbWJseS5uYW1lfUAke2Fzc2VtYmx5LnZlcnNpb259YCk7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGNyZWF0ZUFzc2VtYmx5KFxuICAgIGxhbmd1YWdlOiBUYXJnZXRMYW5ndWFnZSB8IHVuZGVmaW5lZCxcbiAgICBvcHRpb25zOiBSZXF1aXJlZDxUcmFuc2xpdGVyYXRpb25PcHRpb25zPixcbiAgKTogUHJvbWlzZTxyZWZsZWN0LkFzc2VtYmx5PiB7XG5cbiAgICBjb25zdCBjYWNoZUtleSA9IGBsYW5nOiR7bGFuZ3VhZ2UgPz8gJ3RzJ30ubG9vc2U6JHtvcHRpb25zLmxvb3NlfS52YWxpZGF0ZToke29wdGlvbnMudmFsaWRhdGV9YDtcbiAgICBjb25zdCBjYWNoZWQgPSB0aGlzLmFzc2VtYmxpZXNDYWNoZS5nZXQoY2FjaGVLZXkpO1xuICAgIGlmIChjYWNoZWQpIHtcbiAgICAgIHJldHVybiBjYWNoZWQ7XG4gICAgfVxuXG4gICAgY29uc3QgY3JlYXRlZCA9IGF3YWl0IHdpdGhUZW1wRGlyKGFzeW5jICh3b3JrZGlyOiBzdHJpbmcpID0+IHtcblxuICAgICAgY29uc3QgdHMgPSBuZXcgcmVmbGVjdC5UeXBlU3lzdGVtKCk7XG5cbiAgICAgIGNvbnN0IGFzc2VtYmxpZXMgPSBkaXNjb3ZlckFzc2VtYmxpZXModGhpcy5hc3NlbWJsaWVzRGlyKTtcbiAgICAgIGZvciAobGV0IHsgbmFtZTogZGlzY292ZXJlZE5hbWUsIHBhdGg6IGRvdEpzaWkgfSBvZiBPYmplY3QudmFsdWVzKGFzc2VtYmxpZXMpKSB7XG4gICAgICAgIC8vIHdlIG9ubHkgdHJhbnNsaXRlcmF0ZSB0aGUgdG9wIGxldmVsIGFzc2VtYmx5IGFuZCBub3QgdGhlIGVudGlyZSB0eXBlLXN5c3RlbS5cbiAgICAgICAgLy8gbm90ZSB0aGF0IHRoZSBvbmx5IHJlYXNvbiB0byB0cmFuc2xhdGUgZGVwZW5kYW50IGFzc2VtYmxpZXMgaXMgdG8gc2hvdyBjb2RlIGV4YW1wbGVzXG4gICAgICAgIC8vIGZvciBleHBhbmRlZCBweXRob24gYXJndW1lbnRzIC0gd2hpY2ggd2UgZG9uJ3QgdG8gcmlnaHQgbm93IGFueXdheS5cbiAgICAgICAgLy8gd2UgZG9uJ3Qgd2FudCB0byBtYWtlIGFueSBhc3N1bXB0aW9uIG9mIHRoZSBkaXJlY3Rvcnkgc3RydWN0dXJlLCBzbyB0aGlzIGlzIHRoZSBtb3N0XG4gICAgICAgIC8vIHJvYnVzdCB3YXkgdG8gZGV0ZWN0IHRoZSByb290IGFzc2VtYmx5LlxuICAgICAgICBpZiAoZGlzY292ZXJlZE5hbWUgPT09IHRoaXMuYXNzZW1ibHlOYW1lKSB7XG4gICAgICAgICAgLy8gb25seSB0cmFuc2xpdGVyYXRlIGlmIHdlIGhhdmUgcmVjZWl2ZWQgYSB0YXJnZXQgbGFuZyByZXF1ZXN0XG4gICAgICAgICAgaWYgKGxhbmd1YWdlKSB7XG4gICAgICAgICAgICBjb25zdCBwYWNrYWdlRGlyID0gcGF0aC5kaXJuYW1lKGRvdEpzaWkpO1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgYXdhaXQgdHJhbnNsaXRlcmF0ZUFzc2VtYmx5KFtwYWNrYWdlRGlyXSwgW2xhbmd1YWdlXSxcbiAgICAgICAgICAgICAgICB7IGxvb3NlOiBvcHRpb25zLmxvb3NlLCB1bmtub3duU25pcHBldHM6IFVua25vd25TbmlwcGV0TW9kZS5GQUlMLCBvdXRkaXI6IHdvcmtkaXIgfSk7XG4gICAgICAgICAgICB9IGNhdGNoIChlOiBhbnkpIHtcbiAgICAgICAgICAgICAgdGhyb3cgbmV3IFRyYW5zbGl0ZXJhdGlvbkVycm9yKGBDb3VsZCBub3QgdHJhbnNsaXRlcmF0ZSBzbmlwcGV0cyBpbiAnJHt0aGlzLmFzc2VtYmx5RnFufScgdG8gJHtsYW5ndWFnZX06ICR7ZS5tZXNzYWdlfWApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgbGFuZ0RvdEpzaWkgPSBwYXRoLmpvaW4od29ya2RpciwgYCR7U1BFQ19GSUxFX05BTUV9LiR7bGFuZ3VhZ2V9YCk7XG4gICAgICAgICAgICBhd2FpdCBsb2FkQXNzZW1ibHkobGFuZ0RvdEpzaWksIHRzLCBhc3NlbWJsaWVzLCBvcHRpb25zKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgYXdhaXQgbG9hZEFzc2VtYmx5KGRvdEpzaWksIHRzLCBhc3NlbWJsaWVzLCBvcHRpb25zKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiB0cy5maW5kQXNzZW1ibHkodGhpcy5hc3NlbWJseU5hbWUpO1xuICAgIH0pO1xuXG4gICAgdGhpcy5hc3NlbWJsaWVzQ2FjaGUuc2V0KGNhY2hlS2V5LCBjcmVhdGVkKTtcbiAgICByZXR1cm4gY3JlYXRlZDtcbiAgfVxufVxuXG5cbmV4cG9ydCBjb25zdCBMQU5HVUFHRV9TUEVDSUZJQyA9IHtcbiAgW0xhbmd1YWdlLlBZVEhPTi50b1N0cmluZygpXToge1xuICAgIHRyYW5zcGlsZTogbmV3IFB5dGhvblRyYW5zcGlsZSgpLFxuICAgIHJvc2V0dGFUYXJnZXQ6IFRhcmdldExhbmd1YWdlLlBZVEhPTixcbiAgfSxcbiAgW0xhbmd1YWdlLlRZUEVTQ1JJUFQudG9TdHJpbmcoKV06IHtcbiAgICB0cmFuc3BpbGU6IG5ldyBUeXBlU2NyaXB0VHJhbnNwaWxlKCksXG4gICAgcm9zZXR0YVRhcmdldDogdW5kZWZpbmVkLCAvLyBubyB0cmFuc3BpbGF0aW9uIG5lZWRlZFxuICB9LFxuICBbTGFuZ3VhZ2UuSkFWQS50b1N0cmluZygpXToge1xuICAgIHRyYW5zcGlsZTogbmV3IEphdmFUcmFuc3BpbGUoKSxcbiAgICByb3NldHRhVGFyZ2V0OiBUYXJnZXRMYW5ndWFnZS5KQVZBLFxuICB9LFxuICBbTGFuZ3VhZ2UuQ1NIQVJQLnRvU3RyaW5nKCldOiB7XG4gICAgdHJhbnNwaWxlOiBuZXcgQ1NoYXJwVHJhbnNwaWxlKCksXG4gICAgcm9zZXR0YVRhcmdldDogVGFyZ2V0TGFuZ3VhZ2UuQ1NIQVJQLFxuICB9LFxuICBbTGFuZ3VhZ2UuR08udG9TdHJpbmcoKV06IHtcbiAgICB0cmFuc3BpbGU6IG5ldyBHb1RyYW5zcGlsZSgpLFxuICAgIHJvc2V0dGFUYXJnZXQ6IFRhcmdldExhbmd1YWdlLkdPLFxuICB9LFxufTtcblxuLyoqXG4gKiBMb2FkcyB0aGUgc3BlY2lmaWVkIGFzc2VtYmx5IGRvY3VtZW50IGludG8gdGhlIHByb3ZpZGVkIHR5cGUgc3lzdGVtLCBhbmRcbiAqIHJlY3Vyc2l2ZWx5IGF0dGVtcHQgdG8gbG9hZCB0aGUgYXNzZW1ibHkncyBkZXBlbmRlbmNpZXMuXG4gKlxuICogQHBhcmFtIGRvdEpzaWkgdGhlIGFzc2VtYmx5IHRvIGJlIGxvYWRlZC5cbiAqIEBwYXJhbSB0cyB0aGUgdHlwZSBzeXN0ZW0gaW4gd2hpY2ggdGhlIGFzc2VtYmx5IGlzIHRvIGJlIGxvYWRlZC5cbiAqIEBwYXJhbSB2YWxpZGF0ZSB3aGV0aGVyIGFzc2VtYmxpZXMgc2hvdWxkIGJlIHZhbGlkYXRlZC5cbiAqL1xuYXN5bmMgZnVuY3Rpb24gbG9hZEFzc2VtYmx5KFxuICBkb3RKc2lpOiBzdHJpbmcsXG4gIHRzOiByZWZsZWN0LlR5cGVTeXN0ZW0sXG4gIGF2YWlsYWJsZUFzc2VtYmxpZXM6IEFzc2VtYmx5TG9va3VwLFxuICB7IHZhbGlkYXRlIH06IHsgcmVhZG9ubHkgdmFsaWRhdGU/OiBib29sZWFuIH0gPSB7fSxcbik6IFByb21pc2U8cmVmbGVjdC5Bc3NlbWJseT4ge1xuICBjb25zdCBsb2FkZWQgPSBhd2FpdCB0cy5sb2FkKGRvdEpzaWksIHsgdmFsaWRhdGUsIHN1cHBvcnRlZEZlYXR1cmVzOiBTVVBQT1JURURfQVNTRU1CTFlfRkVBVFVSRVMgfSk7XG5cbiAgZm9yIChjb25zdCBbZGVwLCB2ZXJzaW9uXSBvZiBPYmplY3QuZW50cmllcyhsb2FkZWQuc3BlYy5kZXBlbmRlbmNpZXMgPz8ge30pKSB7XG4gICAgaWYgKHRzLnRyeUZpbmRBc3NlbWJseShkZXApICE9IG51bGwpIHtcbiAgICAgIC8vIGRlcGVuZGVuY3kgYWxyZWFkeSBsb2FkZWQuLi4gbW92ZSBvbi4uLlxuICAgICAgY29udGludWU7XG4gICAgfVxuXG4gICAgY29uc3QgZGVwUGF0aCA9IGJlc3RBc3NlbWJseU1hdGNoKGF2YWlsYWJsZUFzc2VtYmxpZXMsIGAke2RlcH1AJHt2ZXJzaW9ufWApLnBhdGg7XG5cbiAgICB0cnkge1xuICAgICAgYXdhaXQgbG9hZEFzc2VtYmx5KGRlcFBhdGgsIHRzLCBhdmFpbGFibGVBc3NlbWJsaWVzLCB7IHZhbGlkYXRlIH0pO1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAvLyBTaWxlbnRseSBpZ25vcmUgYW55IHJlc29sdXRpb24gZXJyb3JzLi4uIFdlJ2xsIGZhaWwgbGF0ZXIgaWYgdGhlIGRlcGVuZGVuY3kgaXNcbiAgICAgIC8vIEFDVFVBTExZIHJlcXVpcmVkLCBidXQgaXQncyBva2F5IHRvIG9taXQgaXQgaWYgbm9uZSBvZiBpdHMgdHlwZXMgYXJlIGFjdHVhbGx5IGV4cG9zZWRcbiAgICAgIC8vIGJ5IHRoZSB0cmFuc2xhdGVkIGFzc2VtYmx5J3Mgb3duIEFQSS5cbiAgICB9XG4gIH1cbiAgcmV0dXJuIGxvYWRlZDtcbn1cblxuYXN5bmMgZnVuY3Rpb24gd2l0aFRlbXBEaXI8VD4od29yazogKHdvcmtkaXI6IHN0cmluZykgPT4gUHJvbWlzZTxUPik6IFByb21pc2U8VD4ge1xuICBjb25zdCB3b3JrZGlyID0gYXdhaXQgZnMubWtkdGVtcChwYXRoLmpvaW4ob3MudG1wZGlyKCksIHBhdGguc2VwKSk7XG4gIGNvbnN0IGN3ZCA9IHByb2Nlc3MuY3dkKCk7XG4gIHRyeSB7XG4gICAgcHJvY2Vzcy5jaGRpcih3b3JrZGlyKTtcbiAgICAvLyB3YWl0IGZvciB0aGUgd29yayB0byBiZSBjb21wbGV0ZWQgYmVmb3JlXG4gICAgLy8gd2UgY2xlYW51cCB0aGUgd29yayBlbnZpcm9ubWVudC5cbiAgICByZXR1cm4gYXdhaXQgd29yayh3b3JrZGlyKTtcbiAgfSBmaW5hbGx5IHtcbiAgICBwcm9jZXNzLmNoZGlyKGN3ZCk7XG4gICAgYXdhaXQgZnMucmVtb3ZlKHdvcmtkaXIpO1xuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBleHRyYWN0UGFja2FnZU5hbWUoc3BlYzogc3RyaW5nKSB7XG4gIGNvbnN0IGZpcnN0QXQgPSBzcGVjLmluZGV4T2YoJ0AnKTtcblxuICBpZiAoZmlyc3RBdCA9PT0gMCkge1xuICAgIGNvbnN0IGxhc3RBdCA9IHNwZWMuaW5kZXhPZignQCcsIGZpcnN0QXQgKyAxKTtcbiAgICBpZiAobGFzdEF0ID09PSAtMSkge1xuICAgICAgLy8gQGF3cy1jZGsvYXdzLWVjclxuICAgICAgcmV0dXJuIHNwZWM7XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIEBhd3MtY2RrL2F3cy1lY3JAMi4wLjBcbiAgICAgIHJldHVybiBzcGVjLnN1YnN0cmluZygwLCBsYXN0QXQpO1xuICAgIH1cbiAgfVxuXG4gIGlmIChmaXJzdEF0ID4gMCkge1xuICAgIC8vIGF3cy1jZGstbGliQDIuMC4wXG4gICAgcmV0dXJuIHNwZWMuc3Vic3RyaW5nKDAsIGZpcnN0QXQpO1xuICB9XG5cbiAgLy8gYXdzLWNkay1saWJcbiAgcmV0dXJuIHNwZWM7XG59XG5cbi8qKlxuICogUmV0dXJuIGEgYENvcnJ1cHRlZEFzc2VtYmx5RXJyb3JgIGlmIHRoZSBlcnJvciBtYXRjaGVzLCB1bmRlZmluZWQgb3RoZXJ3aXNlLlxuICpcbiAqIE5vdGUgdGhhdCBhbiAnbm90IGZvdW5kIGluIGFzc2VtYmx5YCBjYW4gYmUgdGhyb3duIGluIHR3byBjYXNlczpcbiAqXG4gKiAxLiBEaXJlY3QgdXNhZ2Ugb2YgYGFzc2VtYmx5LmZpbmRUeXBlKGZxbilgXG4gKlxuICogICAgSW4gdGhpcyBjYXNlIHRoZSBlcnJvciBjb3VsZCBiZSBjYXVzZWQgYnkgYSB3cm9uZyBGUU4gYmVpbmcgcGFzc2VkIHRvIHRoZSBmdW5jdGlvbi4gVGhpcyBpcyBub3QgY29uc2lkZXJlZFxuICogICAgYSBjb3JydXB0ZWQgYXNzZW1ibHkgc2luY2UgdGhlIGNhbGxlciBtaWdodCBiZSBwYXNzaW5nIGFuIEZRTiBmcm9tIGEgZGlmZmVyZW50IGFzc2VtYmx5LlxuICpcbiAqIDIuIEltcGxpY2l0IHVzYWdlIG9mIGBhc3NlbWJseS5maW5kVHlwZShmcW4pYCBieSBjYWxsaW5nIGAudHlwZWAgKGUuZyBgcGFyYW1ldGVyLnR5cGVgKVxuICpcbiAqICAgIEluIHRoaXMgY2FzZSB0aGUgYXNzZW1ibHkgd2UgbG9vayBpbiBpcyBhbHdheXMgdGhlIHNhbWUgYXNzZW1ibHkgdGhlIHR5cGUgaXRzZWxmIGNvbWVzIGZyb20sIGFuZCBpZiBpdCBkb2Vzbid0IGV4aXN0LFxuICogICAgdGhlbiB0aGUgYXNzZW1ibHkgaXMgY29uc2lkZXJlZCBjb3JydXB0LlxuICovXG5mdW5jdGlvbiBtYXliZUNvcnJ1cHRlZEFzc2VtYmx5RXJyb3IoZXJyb3I6IEVycm9yKTogQ29ycnVwdGVkQXNzZW1ibHlFcnJvciB8IHVuZGVmaW5lZCB7XG4gIGlmIChpc0Fzc2VtYmx5Tm90Rm91bmQoZXJyb3IpIHx8IGlzTm90Rm91bmRJbkFzc21lYmx5KGVycm9yKSkge1xuICAgIHJldHVybiBuZXcgQ29ycnVwdGVkQXNzZW1ibHlFcnJvcihlcnJvci5tZXNzYWdlKTtcbiAgfVxuICByZXR1cm47XG59XG5cbmZ1bmN0aW9uIGlzTm90Rm91bmRJbkFzc21lYmx5KGVycm9yOiBFcnJvcikge1xuXG4gIGNvbnN0IG1hdGNoID0gZXJyb3IubWVzc2FnZS5tYXRjaChOT1RfRk9VTkRfSU5fQVNTRU1CTFlfUkVHRVgpO1xuICBpZiAoIW1hdGNoKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG4gIGNvbnN0IHNlYXJjaGVkQXNzZW1ibHkgPSBtYXRjaFsyXTtcbiAgY29uc3QgdHlwZUFzc2VtYmx5ID0gbWF0Y2hbMV07XG5cbiAgaWYgKHNlYXJjaGVkQXNzZW1ibHkgPT09IHR5cGVBc3NlbWJseVxuICAgIC8vIHRha2UgaW50byBhY2NvdW50IHN1Ym1vZHVsZXMgKGUuZyBhd3MtY2RrLWxpYi5hd3Nfa21zLklLZXlSZWYpXG4gICAgfHwgdHlwZUFzc2VtYmx5LnN0YXJ0c1dpdGgoc2VhcmNoZWRBc3NlbWJseSArICcuJykpIHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuICByZXR1cm4gZmFsc2U7XG5cbn1cblxuZnVuY3Rpb24gaXNBc3NlbWJseU5vdEZvdW5kKGVycm9yOiBFcnJvcikge1xuXG4gIGNvbnN0IG1hdGNoID0gZXJyb3IubWVzc2FnZS5tYXRjaChBU1NFTUJMWV9OT1RfRk9VTkRfUkVHRVgpO1xuICBpZiAoIW1hdGNoKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG4gIHJldHVybiB0cnVlO1xuXG59XG4iXX0=