UNPKG

jsii-docgen

Version:

generates api docs for jsii modules

443 lines 65.2 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/main/packages/jsii-reflect/lib/assembly.ts#L175 const NOT_FOUND_IN_ASSEMBLY_REGEX = /Type '(.*)\..*' not found in assembly (.*)$/; 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) => { // always better not to pollute an externally provided directory await fs.copy(this.assembliesDir, workdir, { // Ensure we don't try to copy socket files, as they can be found under .git when // core.fsmonitor is enabled. filter: async (src) => { const stat = await fs.stat(src); return stat.isFile() || stat.isDirectory(); }, }); 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, _b, _c; 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; } try { // Use path from look up or try to resolve the dependencies relative to the dependent's package root. const depPath = (_c = (_b = (0, assembly_1.bestAssemblyMatch)(availableAssemblies, `${dep}@${version}`)) === null || _b === void 0 ? void 0 : _b.path) !== null && _c !== void 0 ? _c : require.resolve(`${dep}/.jsii`, { paths: [path.dirname(dotJsii)] }); 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) { const match = error.message.match(NOT_FOUND_IN_ASSEMBLY_REGEX); if (!match) { return; } const searchedAssembly = match[2]; const typeAssembly = match[1]; if (searchedAssembly === typeAssembly) { return new __1.CorruptedAssemblyError(error.message); } return; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZG9jdW1lbnRhdGlvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9kb2NnZW4vdmlldy9kb2N1bWVudGF0aW9uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQXlnQkEsZ0RBcUJDO0FBOWhCRCx1Q0FBeUI7QUFDekIsMkNBQTZCO0FBQzdCLHFDQUF5RDtBQUN6RCw2Q0FBK0I7QUFDL0Isc0RBQXdDO0FBQ3hDLCtDQUF5RjtBQUN6RixpQ0FBNkI7QUFDN0IsbURBQStDO0FBQy9DLHFDQUFrQztBQUNsQyw2QkFBZ0c7QUFDaEcseUNBQTZEO0FBQzdELHlEQUEwRDtBQUMxRCwrREFBd0Y7QUFDeEYsc0NBQTBFO0FBQzFFLHlDQUFtRjtBQUNuRixnREFBc0Q7QUFDdEQsd0NBQThDO0FBQzlDLDRDQUFrRDtBQUNsRCxnREFBc0Q7QUFDdEQsc0RBQTZEO0FBQzdELHdEQUE4RDtBQUU5RCxtRkFBbUY7QUFDbkYsTUFBTSwyQkFBMkIsR0FBRyw2Q0FBNkMsQ0FBQztBQUVyRSxRQUFBLDJCQUEyQixHQUFrQixDQUFDLG9CQUFvQixFQUFFLDJCQUEyQixDQUFDLENBQUM7QUFpRzlHOztHQUVHO0FBQ0gsTUFBYSxhQUFhO0lBRXhCOzs7Ozs7Ozs7OztPQVdHO0lBQ0ksTUFBTSxDQUFDLEtBQUssQ0FBQyxVQUFVLENBQUMsTUFBYyxFQUFFLFVBQTBDLEVBQUU7O1FBQ3pGLE1BQU0sT0FBTyxHQUFHLE1BQU0sRUFBRSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxNQUFNLEVBQUUsRUFBRSxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztRQUVuRSxNQUFNLEdBQUcsR0FBRyxJQUFJLFVBQUcsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUU3QixJQUFJLE1BQUEsT0FBTyxDQUFDLE9BQU8sbUNBQUksSUFBSSxFQUFFLENBQUM7WUFDNUIs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WUFBWSxFQUFFLENBQUM7UUFDdEMsT0FBTyxJQUFJLDBCQUFzQixDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUNuRCxDQUFDO0lBQ0QsT0FBTztBQUNULENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyBvcyBmcm9tICdvcyc7XG5pbXBvcnQgKiBhcyBwYXRoIGZyb20gJ3BhdGgnO1xuaW1wb3J0IHsgSnNpaUZlYXR1cmUsIFNQRUNfRklMRV9OQU1FIH0gZnJvbSAnQGpzaWkvc3BlYyc7XG5pbXBvcnQgKiBhcyBmcyBmcm9tICdmcy1leHRyYSc7XG5pbXBvcnQgKiBhcyByZWZsZWN0IGZyb20gJ2pzaWktcmVmbGVjdCc7XG5pbXBvcnQgeyBUYXJnZXRMYW5ndWFnZSwgdHJhbnNsaXRlcmF0ZUFzc2VtYmx5LCBVbmtub3duU25pcHBldE1vZGUgfSBmcm9tICdqc2lpLXJvc2V0dGEnO1xuaW1wb3J0IHsgTnBtIH0gZnJvbSAnLi9fbnBtJztcbmltcG9ydCB7IEFwaVJlZmVyZW5jZSB9IGZyb20gJy4vYXBpLXJlZmVyZW5jZSc7XG5pbXBvcnQgeyBSZWFkbWUgfSBmcm9tICcuL3JlYWRtZSc7XG5pbXBvcnQgeyBDb3JydXB0ZWRBc3NlbWJseUVycm9yLCBMYW5ndWFnZU5vdFN1cHBvcnRlZEVycm9yLCBUcmFuc2xpdGVyYXRpb25FcnJvciB9IGZyb20gJy4uLy4uJztcbmltcG9ydCB7IEpzb24sIEpzb25Gb3JtYXR0aW5nT3B0aW9ucyB9IGZyb20gJy4uL3JlbmRlci9qc29uJztcbmltcG9ydCB7IE1hcmtkb3duRG9jdW1lbnQgfSBmcm9tICcuLi9yZW5kZXIvbWFya2Rvd24tZG9jJztcbmltcG9ydCB7IE1hcmtkb3duRm9ybWF0dGluZ09wdGlvbnMsIE1hcmtkb3duUmVuZGVyZXIgfSBmcm9tICcuLi9yZW5kZXIvbWFya2Rvd24tcmVuZGVyJztcbmltcG9ydCB7IFNjaGVtYSwgQ1VSUkVOVF9TQ0hFTUFfVkVSU0lPTiwgc3VibW9kdWxlUGF0aCB9IGZyb20gJy4uL3NjaGVtYSc7XG5pbXBvcnQgeyBBc3NlbWJseUxvb2t1cCwgYmVzdEFzc2VtYmx5TWF0Y2gsIGRpc2NvdmVyQXNzZW1ibGllcyB9IGZyb20gJy4vYXNzZW1ibHknO1xuaW1wb3J0IHsgQ1NoYXJwVHJhbnNwaWxlIH0gZnJvbSAnLi4vdHJhbnNwaWxlL2NzaGFycCc7XG5pbXBvcnQgeyBHb1RyYW5zcGlsZSB9IGZyb20gJy4uL3RyYW5zcGlsZS9nbyc7XG5pbXBvcnQgeyBKYXZhVHJhbnNwaWxlIH0gZnJvbSAnLi4vdHJhbnNwaWxlL2phdmEnO1xuaW1wb3J0IHsgUHl0aG9uVHJhbnNwaWxlIH0gZnJvbSAnLi4vdHJhbnNwaWxlL3B5dGhvbic7XG5pbXBvcnQgeyBUcmFuc3BpbGUsIExhbmd1YWdlIH0gZnJvbSAnLi4vdHJhbnNwaWxlL3RyYW5zcGlsZSc7XG5pbXBvcnQgeyBUeXBlU2NyaXB0VHJhbnNwaWxlIH0gZnJvbSAnLi4vdHJhbnNwaWxlL3R5cGVzY3JpcHQnO1xuXG4vLyBodHRwczovL2dpdGh1Yi5jb20vYXdzL2pzaWkvYmxvYi9tYWluL3BhY2thZ2VzL2pzaWktcmVmbGVjdC9saWIvYXNzZW1ibHkudHMjTDE3NVxuY29uc3QgTk9UX0ZPVU5EX0lOX0FTU0VNQkxZX1JFR0VYID0gL1R5cGUgJyguKilcXC4uKicgbm90IGZvdW5kIGluIGFzc2VtYmx5ICguKikkLztcblxuZXhwb3J0IGNvbnN0IFNVUFBPUlRFRF9BU1NFTUJMWV9GRUFUVVJFUzogSnNpaUZlYXR1cmVbXSA9IFsnaW50ZXJzZWN0aW9uLXR5cGVzJywgJ2NsYXNzLWNvdmFyaWFudC1vdmVycmlkZXMnXTtcblxuLyoqXG4gKiBPcHRpb25zIGZvciByZW5kZXJpbmcgYSBgRG9jdW1lbnRhdGlvbmAgb2JqZWN0LlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFJlbmRlck9wdGlvbnMgZXh0ZW5kcyBUcmFuc2xpdGVyYXRpb25PcHRpb25zIHtcbiAgLyoqXG4gICAqIFdoaWNoIGxhbmd1YWdlIHRvIGdlbmVyYXRlIGRvY3MgZm9yLlxuICAgKi9cbiAgcmVhZG9ubHkgbGFuZ3VhZ2U6IExhbmd1YWdlO1xuXG4gIC8qKlxuICAgKiBJbmNsdWRlIGEgZ2VuZXJhdGVkIGFwaSByZWZlcmVuY2UgaW4gdGhlIGRvY3VtZW50YXRpb24uXG4gICAqXG4gICAqIEBkZWZhdWx0IHRydWVcbiAgICovXG4gIHJlYWRvbmx5IGFwaVJlZmVyZW5jZT86IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIEluY2x1ZGUgdGhlIHVzZXIgZGVmaW5lZCBSRUFETUUubWQgaW4gdGhlIGRvY3VtZW50YXRpb24uXG4gICAqXG4gICAqIEBkZWZhdWx0IGZhbHNlXG4gICAqL1xuICByZWFkb25seSByZWFkbWU/OiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBHZW5lcmF0ZSBkb2N1bWVudGF0aW9uIG9ubHkgZm9yIGEgc3BlY2lmaWMgc3VibW9kdWxlLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIERvY3VtZW50YXRpb24gaXMgZ2VuZXJhdGVkIGZvciB0aGUgcm9vdCBtb2R1bGUgb25seS5cbiAgICovXG4gIHJlYWRvbmx5IHN1Ym1vZHVsZT86IHN0cmluZztcblxuICAvKipcbiAgICogR2VuZXJhdGUgYSBzaW5nbGUgZG9jdW1lbnQgd2l0aCBBUElzIGZyb20gYWxsIGFzc2VtYmx5IHN1Ym1vZHVsZXNcbiAgICogKGluY2x1ZGluZyB0aGUgcm9vdCkuXG4gICAqXG4gICAqIE5vdGU6IG9ubHkgdGhlIHJvb3QtbGV2ZWwgUkVBRE1FIGlzIGluY2x1ZGVkLlxuICAgKlxuICAgKiBAZGVmYXVsdCBmYWxzZVxuICAgKi9cbiAgcmVhZG9ubHkgYWxsU3VibW9kdWxlcz86IGJvb2xlYW47XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgVHJhbnNsaXRlcmF0aW9uT3B0aW9ucyB7XG4gIC8qKlxuICAgKiBXaGV0aGVyIHRvIGlnbm9yZSBtaXNzaW5nIGZpeHR1cmUgZmlsZXMgdGhhdCB3aWxsIHByZXZlbnQgdHJhbnNsaXRlcmF0aW5nXG4gICAqIHNvbWUgY29kZSBzbmlwcGV0IGV4YW1wbGVzLlxuICAgKlxuICAgKiBAZGVmYXVsdCB0cnVlXG4gICAqL1xuICByZWFkb25seSBsb29zZT86IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIFdoZXRoZXIgdG8gdmFsaWRhdGUganNpaSBhc3NlbWJsaWVzIGFnYWluc3QgdGhlIGpzaWkgc2NoZW1hIGJlZm9yZVxuICAgKiB1c2luZyB0aGVtLlxuICAgKlxuICAgKiBAZGVmYXVsdCBmYWxzZVxuICAgKi9cbiAgcmVhZG9ubHkgdmFsaWRhdGU/OiBib29sZWFuO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIE1hcmtkb3duUmVuZGVyT3B0aW9ucyBleHRlbmRzIFJlbmRlck9wdGlvbnMsIE1hcmtkb3duRm9ybWF0dGluZ09wdGlvbnMge31cblxuZXhwb3J0IGludGVyZmFjZSBKc29uUmVuZGVyT3B0aW9ucyBleHRlbmRzIFJlbmRlck9wdGlvbnMsIEpzb25Gb3JtYXR0aW5nT3B0aW9ucyB7fVxuXG4vKipcbiAqIE9wdGlvbnMgZm9yIGNyZWF0aW5nIGEgYERvY3VtZW50YXRpb25gIG9iamVjdCB1c2luZyB0aGUgYGZyb21Mb2NhbFBhY2thZ2VgIGZ1bmN0aW9uLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIEZvckxvY2FsUGFja2FnZURvY3VtZW50YXRpb25PcHRpb25zIHtcblxuICAvKipcbiAgICogQSBsb2NhbCBkaXJlY3RvcnkgY29udGFpbmluZyBqc2lpIGFzc2VtYmx5IGZpbGVzIHRoYXQgd2lsbFxuICAgKiBjb21wcmlzZSB0aGUgdHlwZS1zeXN0ZW0uXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gdGhlIHJvb3QgcGFja2FnZSBkaXJlY3Rvcnkgd2lsbCBiZSB1c2VkLlxuICAgKi9cbiAgcmVhZG9ubHkgYXNzZW1ibGllc0Rpcj86IHN0cmluZztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBGb3JQYWNrYWdlRG9jdW1lbnRhdGlvbk9wdGlvbnMge1xuICAvKipcbiAgICogV2hldGhlciB2ZXJib3NlIGxvZ2dpbmcgaXMgdG8gYmUgcGVyZm9ybWVkLlxuICAgKlxuICAgKiBAZGVmYXVsdCB0cnVlXG4gICAqL1xuICByZWFkb25seSB2ZXJib3NlPzogYm9vbGVhbjtcblxuICAvKipcbiAgICogQSBmdW5jdGlvbiB0byBydW4gYWZ0ZXIgcnVubmluZyBgbnBtIGluc3RhbGxgIGZvciB0aGUgdGFyZ2V0IHBhY2thZ2UuIFRoaXNcbiAgICogZXhpc3RzIG9ubHkgZm9yIHRlc3RpbmcgcHVycG9zZXMgYW5kIHNob3VsZCBub3QgYmUgdXNlZCBieSBjb25zdW1lcnMgb2ZcbiAgICogdGhpcyBtb2R1bGUuXG4gICAqXG4gICAqIEBpbnRlcm5hbFxuICAgKi9cbiAgcmVhZG9ubHkgX3Bvc3RJbnN0YWxsPzogKGRpcjogc3RyaW5nKSA9PiBQcm9taXNlPHZvaWQ+O1xufVxuXG4vKipcbiAqIFJlbmRlciBkb2N1bWVudGF0aW9uIHBhZ2VzIGZvciBhIGpzaWkgbGlicmFyeS5cbiAqL1xuZXhwb3J0IGNsYXNzIERvY3VtZW50YXRpb24ge1xuXG4gIC8qKlxuICAgKiBDcmVhdGUgYSBgRG9jdW1lbnRhdGlvbmAgb2JqZWN0IGZyb20gYSBwYWNrYWdlIGluc3RhbGxhYmxlIGJ5IG5wbS5cbiAgICpcbiAgICogTm90ZSB0aGF0IHRoaXMgbWV0aG9kIGluc3RhbGxzIHRoZSB0YXJnZXQgcGFja2FnZSB0byB0aGUgbG9jYWwgZmlsZS1zeXN0ZW0uIE1ha2Ugc3VyZVxuICAgKiB0byBjYWxsIGBEb2N1bWVudGF0aW9uLmNsZWFudXBgIG9uY2UgeW91IGFyZSBkb25lIHJlbmRlcmluZy5cbiAgICpcbiAgICogQHBhcmFtIHRhcmdldCAtIFRoZSB0YXJnZXQgdG8gaW5zdGFsbC4gVGhpcyBjYW4gZWl0aGVyIGJlIGEgbG9jYWwgcGF0aCBvciBhIHJlZ2lzdHJ5IGlkZW50aWZpZXIgKGUuZyA8bmFtZT5APHZlcnNpb24+KVxuICAgKiBAcGFyYW0gb3B0aW9ucyAtIEFkZGl0aW9uYWwgb3B0aW9ucy5cbiAgICpcbiAgICogQHRocm93cyBOb1NwYWNlTGVmdE9uRGV2aWNlIGlmIHRoZSBpbnN0YWxsYXRpb24gZmFpbHMgZHVlIHRvIHJ1bm5pbmcgb3V0IG9mIGRpc2sgc3BhY2VcbiAgICogQHRocm93cyBOcG1FcnJvciBpZiBzb21lIGBucG1gIGNvbW1hbmQgZmFpbHMgd2hlbiBwcmVwYXJpbmcgdGhlIHdvcmtpbmcgc2V0XG4gICAqL1xuICBwdWJsaWMgc3RhdGljIGFzeW5jIGZvclBhY2thZ2UodGFyZ2V0OiBzdHJpbmcsIG9wdGlvbnM6IEZvclBhY2thZ2VEb2N1bWVudGF0aW9uT3B0aW9ucyA9IHt9KTogUHJvbWlzZTxEb2N1bWVudGF0aW9uPiB7XG4gICAgY29uc3Qgd29ya2RpciA9IGF3YWl0IGZzLm1rZHRlbXAocGF0aC5qb2luKG9zLnRtcGRpcigpLCBwYXRoLnNlcCkpO1xuXG4gICAgY29uc3QgbnBtID0gbmV3IE5wbSh3b3JrZGlyKTtcblxuICAgIGlmIChvcHRpb25zLnZlcmJvc2UgPz8gdHJ1ZSkge1xuICAgICAgY29uc29sZS5sb2coYEluc3RhbGxpbmcgcGFja2FnZSAke3RhcmdldH1gKTtcbiAgICB9XG5cbiAgICBjb25zdCBuYW1lID0gYXdhaXQgbnBtLmluc3RhbGwodGFyZ2V0KTtcblxuICAgIGlmIChvcHRpb25zLl9wb3N0SW5zdGFsbCAhPSBudWxsKSB7XG4gICAgICBhd2FpdCBvcHRpb25zLl9wb3N0SW5zdGFsbCh3b3JrZGlyKTtcbiAgICB9XG5cbiAgICBjb25zdCBkb2NzID0gYXdhaXQgRG9jdW1lbnRhdGlvbi5mb3JQcm9qZWN0KHBhdGguam9pbih3b3JrZGlyLCAnbm9kZV9tb2R1bGVzJywgbmFtZSksIHsgLi4ub3B0aW9ucywgYXNzZW1ibGllc0Rpcjogd29ya2RpciB9KTtcblxuICAgIC8vIHdlIGNhbm5vdCBkZWxldGUgdGhpcyBkaXJlY3RvcnkgaW1tZWRpYXRlbHkgc2luY2UgaXQgaXMgdXNlZCBkdXJpbmcgYHJlbmRlcmAgY2FsbHMuXG4gICAgLy8gaW5zdGVhZCB3ZSByZWdpc3RlciBpdCBzbyB0aGF0IGNhbGxlcnMgY2FuIGNsZWFuIGl0IHVwIGJ5IGNhbGxpbmcgdGhlIGBjbGVhbnVwYCBtZXRob2QuXG4gICAgZG9jcy5hZGRDbGVhbnVwRGlyZWN0b3J5KHdvcmtkaXIpO1xuXG4gICAgcmV0dXJuIGRvY3M7XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlIGEgYERvY3VtZW50YXRpb25gIG9iamVjdCBmcm9tIGEgbG9jYWwgZGlyZWN0b3J5IGNvbnRhaW5pbmcgYSBub2RlIHByb2plY3QuXG4gICAqXG4gICAqIEBwYXJhbSByb290IC0gVGhlIGxvY2FsIGRpcmVjdG9yeSBwYXRoLiBNdXN0IGNvbnRhaW4gYSBwYWNrYWdlLmpzb24gZmlsZS5cbiAgICogQHBhcmFtIG9wdGlvbnMgLSBBZGRpdGlvbmFsIG9wdGlvbnMuXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIGFzeW5jIGZvclByb2plY3Qocm9vdDogc3RyaW5nLCBvcHRpb25zOiBGb3JMb2NhbFBhY2thZ2VEb2N1bWVudGF0aW9uT3B0aW9ucyA9IHt9KTogUHJvbWlzZTxEb2N1bWVudGF0aW9uPiB7XG4gICAgY29uc3QgbWFuaWZlc3RQYXRoID0gcGF0aC5qb2luKHJvb3QsICdwYWNrYWdlLmpzb24nKTtcbiAgICBpZiAoIShhd2FpdCBmcy5wYXRoRXhpc3RzKG1hbmlmZXN0UGF0aCkpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYFVuYWJsZSB0byBsb2NhdGUgJHttYW5pZmVzdFBhdGh9YCk7XG4gICAgfVxuXG4gICAgLy8gbm9ybWFsbHkgdGhlIGFzc2VtYmxpZXMgYXJlIGxvY2F0ZWQgaW4gc3ViZGlyZWN0b3JpZXNcbiAgICAvLyBvZiB0aGUgcm9vdCBwYWNrYWdlIGRpciAoaS5lIC4vbm9kZV9tb2R1bGVzKVxuICAgIGNvbnN0IGFzc2VtYmxpZXNEaXIgPSBvcHRpb25zPy5hc3NlbWJsaWVzRGlyID8/IHJvb3Q7XG5cbiAgICBjb25zdCB7IG5hbWUgfSA9IEpTT04ucGFyc2UoYXdhaXQgZnMucmVhZEZpbGUobWFuaWZlc3RQYXRoLCAndXRmLTgnKSk7XG4gICAgcmV0dXJuIERvY3VtZW50YXRpb24uZm9yQXNzZW1ibHkobmFtZSwgYXNzZW1ibGllc0Rpcik7XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlIGEgYERvY3VtZW50YXRpb25gIG9iamVjdCBmb3IgYSBzcGVjaWZpYyBhc3NlbWJseSBmcm9tIGEgZGlyZWN0b3J5IG9mIGFzc2VtYmxpZXMuXG4gICAqXG4gICAqIEBwYXJhbSBhc3NlbWJseU5hbWUgLSBUaGUgYXNzZW1ibHkgbmFtZS5cbiAgICogQHBhcmFtIGFzc2VtYmxpZXNEaXIgLSBUaGUgZGlyZWN0b3J5IGNvbnRhaW5pbmcgdGhlIGFzc2VtYmxpZXMgdGhhdCBjb21wcmlzZSB0aGUgdHlwZS1zeXN0ZW0uXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIGFzeW5jIGZvckFzc2VtYmx5KGFzc2VtYmx5TmFtZTogc3RyaW5nLCBhc3NlbWJsaWVzRGlyOiBzdHJpbmcpOiBQcm9taXNlPERvY3VtZW50YXRpb24+IHtcbiAgICByZXR1cm4gbmV3IERvY3VtZW50YXRpb24oYXNzZW1ibHlOYW1lLCBhc3NlbWJsaWVzRGlyKTtcbiAgfVxuXG4gIHByaXZhdGUgcmVhZG9ubHkgY2xlYW51cERpcmVjdG9yaWVzOiBTZXQ8c3RyaW5nPiA9IG5ldyBTZXQ8c3RyaW5nPigpO1xuICBwcml2YXRlIHJlYWRvbmx5IGFzc2VtYmxpZXNDYWNoZTogTWFwPHN0cmluZywgcmVmbGVjdC5Bc3NlbWJseT4gPSBuZXcgTWFwPHN0cmluZywgcmVmbGVjdC5Bc3NlbWJseT4oKTtcbiAgcHJpdmF0ZSBhc3NlbWJseUZxbjogc3RyaW5nIHwgdW5kZWZpbmVkO1xuXG4gIHByaXZhdGUgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSByZWFkb25seSBhc3NlbWJseU5hbWU6IHN0cmluZyxcbiAgICBwcml2YXRlIHJlYWRvbmx5IGFzc2VtYmxpZXNEaXI6IHN0cmluZyxcbiAgKSB7fVxuXG4gIC8qKlxuICAgKiBMaXN0IGFsbCBzdWJtb2R1bGVzIGluIHRoZSBhc3NlbWJseS5cbiAgICovXG4gIHB1YmxpYyBhc3luYyBsaXN0U3VibW9kdWxlcygpIHtcbiAgICBjb25zdCB0c0Fzc2VtYmx5ID0gYXdhaXQgdGhpcy5jcmVhdGVBc3NlbWJseSh1bmRlZmluZWQsIHsgbG9vc2U6IHRydWUsIHZhbGlkYXRlOiBmYWxzZSB9KTtcbiAgICByZXR1cm4gdHNBc3NlbWJseS5hbGxTdWJtb2R1bGVzO1xuICB9XG5cbiAgcHVibGljIGFzeW5jIHRvSW5kZXhNYXJrZG93bihmaWxlU3VmZml4OnN0cmluZywgb3B0aW9uczogUmVuZGVyT3B0aW9ucykge1xuICAgIGNvbnN0IGFzc2VtYmx5ID0gYXdhaXQgdGhpcy5jcmVhdGVBc3NlbWJseSh1bmRlZmluZWQsIHsgbG9vc2U6IHRydWUsIHZhbGlkYXRlOiBmYWxzZSB9KTtcbiAgICBjb25zdCBzdWJtb2R1bGVzID0gYXdhaXQgdGhpcy5saXN0U3VibW9kdWxlcygpO1xuICAgIGNvbnN0IHNjaGVtYSA9IChhd2FpdCB0aGlzLnRvSnNvbih7XG4gICAgICAuLi5vcHRpb25zLFxuICAgICAgc3VibW9kdWxlOiB1bmRlZmluZWQsXG4gICAgICBhbGxTdWJtb2R1bGVzOiBmYWxzZSxcbiAgICB9KSkuY29udGVudDtcblxuICAgIGNvbnN0IHJlZiA9IG5ldyBNYXJrZG93bkRvY3VtZW50KHsgaGVhZGVyOiB7IHRpdGxlOiAnQVBJIFJlZmVyZW5jZScgfSwgaWQ6ICdhcGktcmVmZXJlbmNlJyB9KTtcblxuICAgIGlmIChzY2hlbWEudmVyc2lvbiAhPT0gQ1VSUkVOVF9TQ0hFTUFfVkVSU0lPTikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBVbmV4cGVjdGVkIHNjaGVtYSB2ZXJzaW9uOiAke3NjaGVtYS52ZXJzaW9ufWApO1xuICAgIH1cblxuICAgIGNvbnN0IHJlbmRlcmVyID0gbmV3IE1hcmtkb3duUmVuZGVyZXIoe1xuICAgICAgbGFuZ3VhZ2U6IG9wdGlvbnMubGFuZ3VhZ2UsXG4gICAgICBwYWNrYWdlTmFtZTogYXNzZW1ibHkubmFtZSxcbiAgICAgIHBhY2thZ2VWZXJzaW9uOiBhc3NlbWJseS52ZXJzaW9uLFxuICAgIH0pO1xuXG4gICAgaWYgKHN1Ym1vZHVsZXMubGVuZ3RoKSB7XG4gICAgICByZWYuc2VjdGlvbihyZW5kZXJlci52aXNpdFN1Ym1vZHVsZXMoc3VibW9kdWxlcywgZmlsZVN1ZmZpeCkpO1xuICAgIH1cblxuICAgIGlmIChzY2hlbWEuYXBpUmVmZXJlbmNlKSB7XG4gICAgICByZWYuc2VjdGlvbihyZW5kZXJlci52aXNpdENvbnN0cnVjdHMoc2NoZW1hLmFwaVJlZmVyZW5jZS5jb25zdHJ1Y3RzKSk7XG4gICAgICByZWYuc2VjdGlvbihyZW5kZXJlci52aXNpdFN0cnVjdHMoc2NoZW1hLmFwaVJlZmVyZW5jZS5zdHJ1Y3RzKSk7XG4gICAgICByZWYuc2VjdGlvbihyZW5kZXJlci52aXNpdENsYXNzZXMoc2NoZW1hLmFwaVJlZmVyZW5jZS5jbGFzc2VzKSk7XG4gICAgICByZWYuc2VjdGlvbihyZW5kZXJlci52aXNpdEludGVyZmFjZXMoc2NoZW1hLmFwaVJlZmVyZW5jZS5pbnRlcmZhY2VzKSk7XG4gICAgICByZWYuc2VjdGlvbihyZW5kZXJlci52aXNpdEVudW1zKHNjaGVtYS5hcGlSZWZlcmVuY2UuZW51bXMpKTtcbiAgICB9XG5cbiAgICBjb25zdCBkb2N1bWVudGF0aW9uID0gbmV3IE1hcmtkb3duRG9jdW1lbnQoKTtcbiAgICBkb2N1bWVudGF0aW9uLnNlY3Rpb24ocmVmKTtcbiAgICByZXR1cm4gZG9jdW1lbnRhdGlvbjtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZW5lcmF0ZSBtYXJrZG93bi5cbiAgICovXG4gIHB1YmxpYyBhc3luYyB0b0pzb24ob3B0aW9uczogSnNvblJlbmRlck9wdGlvbnMpOiBQcm9taXNlPEpzb248U2NoZW1hPj4ge1xuXG4gICAgY29uc3QgbGFuZ3VhZ2UgPSBvcHRpb25zLmxhbmd1YWdlID8/IExhbmd1YWdlLlRZUEVTQ1JJUFQ7XG4gICAgY29uc3QgbG9vc2UgPSBvcHRpb25zLmxvb3NlID8/IHRydWU7XG4gICAgY29uc3QgdmFsaWRhdGUgPSBvcHRpb25zLnZhbGlkYXRlID8/IGZhbHNlO1xuICAgIGNvbnN0IGFsbFN1Ym1vZHVsZXMgPSBvcHRpb25zLmFsbFN1Ym1vZHVsZXMgPz8gZmFsc2U7XG5cblxuICAgIC8vIEdldCB0aGUgVFMgYXNzZW1ibHkgZmlyc3QgdG8gY2hlY2sgd2hhdCBsYW5ndWFnZXMgYXJlIHN1cHBvcnRlZCBiZWZvcmUgY2FsbGluZyByb3NldHRhXG4gICAgY29uc3QgdHNBc3NlbWJseSA9IGF3YWl0IHRoaXMuY3JlYXRlQXNzZW1ibHkodW5kZWZpbmVkLCB7IGxvb3NlLCB2YWxpZGF0ZSB9KTtc