UNPKG

@decaf-ts/fabric-weaver

Version:
306 lines (297 loc) 38.3 kB
(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@decaf-ts/utils'), require('fs'), require('path'), require('js-yaml'), require('@decaf-ts/logging'), require('child_process')) : typeof define === 'function' && define.amd ? define(['exports', '@decaf-ts/utils', 'fs', 'path', 'js-yaml', '@decaf-ts/logging', 'child_process'], factory) : (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global["fabric-weaver"] = {}, global.utils, global.fs, global.path, global.yaml, global.logging, global.child_process)); })(this, (function (exports, utils, fs, path, yaml, logging, child_process) { 'use strict'; /** * @module build-scripts * @description Custom build scripts for the fabric-weaver project. * @summary This module extends the BuildScripts class from @decaf-ts/utils to provide custom build functionality for the fabric-weaver project. It includes utilities for building command-line interfaces and handling different module formats (CommonJS and ES Modules). */ /** * @description Enumeration of module modes. * @summary Defines the different module formats supported in the build process. * @enum {string} * @readonly * @memberOf module:build-scripts */ var Modes; (function (Modes) { /** CommonJS module format */ Modes["CJS"] = "commonjs"; /** ECMAScript module format (ES2022) */ Modes["ESM"] = "es2022"; })(Modes || (Modes = {})); /** * @description Custom build scripts for the fabric-weaver project. * @summary Extends the BuildScripts class to provide project-specific build functionality, including command bundling and file manipulation. * @class BuildScriptsCustom * @extends BuildScripts */ class BuildScriptsCustom extends utils.BuildScripts { /** * @description Builds command-line interfaces for the project. * @summary Processes each command in the Commands array, bundling the TypeScript files, adding a shebang line, and setting appropriate permissions. * @return {Promise<void>} * @mermaid * sequenceDiagram * participant BuildScriptsCustom * participant FileSystem * loop For each command * BuildScriptsCustom->>BuildScriptsCustom: bundle(Modes.CJS, true, true, `src/bin/${cmd}.ts`, cmd) * BuildScriptsCustom->>FileSystem: readFile(`bin/${cmd}.cjs`) * FileSystem-->>BuildScriptsCustom: file content * BuildScriptsCustom->>BuildScriptsCustom: Add shebang to file content * BuildScriptsCustom->>FileSystem: writeFile(`bin/${cmd}.cjs`, modified content) * BuildScriptsCustom->>FileSystem: chmodSync(`bin/${cmd}.cjs`, "755") * end */ async buildCommands() { const commands = fs.readdirSync(path.join(process.cwd() + "/src/bin")); for (const cmd of commands) { if (!cmd.endsWith(".ts")) continue; await this.bundle(Modes.CJS, true, true, `src/bin/${cmd}`, cmd); let data = utils.readFile(`bin/${cmd}.cjs`); data = "#!/usr/bin/env node\n" + data; utils.writeFile(`bin/${cmd}.cjs`, data); fs.chmodSync(`bin/${cmd}.cjs`, "755"); } } } const COMMA_SEPARATOR = ","; const SLASH_SEPARATOR = "/"; function safeParseJSON(v) { try { return JSON.parse(v); } catch (e) { throw new Error(`Invalid JSON: ${e.message}`); } } function safeParseInt(v) { if (typeof v === "number") return Math.floor(v); const value = Number(v); if (!Number.isInteger(value)) { throw new Error(`Invalid integer value: ${v}`); } return value; } function safeParseCSV(csv) { if (!csv.trim()) return []; return csv.split(COMMA_SEPARATOR).map((item) => item.trim()); } function safeParseSSV(csv) { console.log(csv); if (!csv.trim()) return []; return csv.split(SLASH_SEPARATOR).map((item) => `"${item.trim()}"`); } function mapParser(map) { const argz = Array.from(map, ([key, value]) => { if (typeof value === "boolean") { return value ? [`--${key}`] : []; } if (Array.isArray(value)) { return [`--${key}`, value.join(",")]; } return [`--${key}`, value.toString()]; }); return argz.map((el) => el.join(" ")); } const logger = logging.Logging.for("yaml"); /** * @description Reads and parses a YAML file, optionally retrieving a specific property. * @summary This function reads a YAML file from the given path, parses its content, and returns either the entire parsed YAML object or a specific property value based on the provided path. * * @function readFileYaml * @template T - The type of the returned value when a specific property is requested. * @param {string} yamlFilePath - The path to the YAML file to be read. * @param {string} [variable] - Optional. A dot-notated path string that specifies the property to retrieve from the parsed YAML. * @return {Record<string, any> | T} Returns the entire parsed YAML object if no `variable` is provided, or the value of the specified property if `variable` is provided. * * @memberOf module:fabric-weaver.Utils * * @example * // Example 1: Read the entire YAML file * const config = readFileYaml("config/settings.yaml"); * console.log(config); * * @example * // Example 2: Retrieve a specific property from the YAML file * const dbHost = readFileYaml("config/settings.yaml", "database.host"); * console.log(dbHost); * * @example * // Example 3: Handle an error if the property does not exist * const invalidProperty = readFileYaml("config/settings.yaml", "server.port"); * * @mermaid * sequenceDiagram * participant Caller * participant readFileYaml * participant logger * participant fs * participant yaml * * Caller->>readFileYaml: Call with yamlFilePath and optional variable * readFileYaml->>logger: Log verbose message (Reading YAML file) * readFileYaml->>fs: Read file content * readFileYaml->>logger: Log verbose message (Parsed YAML content) * readFileYaml->>yaml: Parse YAML content * readFileYaml->>logger: Log verbose message (Parsed YAML object) * alt variable is provided * readFileYaml->>readFileYaml: Navigate through parsed YAML using variable path * alt Property exists * readFileYaml-->>Caller: Return specific property value * else Property doesn't exist * readFileYaml->>logger: Log error message * readFileYaml-->>Caller: Return error * end * else variable is not provided * readFileYaml-->>Caller: Return entire parsed YAML object * end */ function readFileYaml(yamlFilePath, variable) { const log = logger.for(readFileYaml); log.debug(`Reading YAML file: ${yamlFilePath}`); const content = fs.readFileSync(yamlFilePath, "utf8"); log.debug(`Parsed YAML content: ${content}`); const parsedYAML = yaml.load(content); log.debug(`Parsed YAML object: ${JSON.stringify(parsedYAML, null, 2)}`); log.info(`Returning ${variable ? `property '${variable}'` : "the entire parsed YAML object"}`); if (!variable) return parsedYAML; const variablePath = variable.split("."); return variablePath.reduce((acc, key) => { // eslint-disable-next-line no-prototype-builtins if (!acc.hasOwnProperty(key)) { throw new Error(`Unable to locate a property named '${key}' from path '${variable}' in file: \n> ${yamlFilePath}`); } return typeof acc[key] === "string" ? acc[key].trim() : acc[key]; }, parsedYAML); } /** * @description Writes a JSON object to a YAML file. * @summary This function takes a JSON object and writes it to a specified file path in YAML format. * It uses js-yaml to convert the JSON to YAML, and then writes the content to the file. * * @function writeFileYaml * @template T - The type of the JSON object to be written. * @param {string} path - The file path where the YAML content will be written. * @param {T} json - The JSON object to be converted to YAML and written to the file. * @return {void} * * @memberOf module:fabric-weaver.Utils * * @example * const config = { database: { host: 'localhost', port: 5432 } }; * writeFileYaml('config/settings.yaml', config); * * @mermaid * sequenceDiagram * participant Caller * participant writeFileYaml * participant logger * participant yaml * participant fs * * Caller->>writeFileYaml: Call with path and JSON * writeFileYaml->>logger: Log verbose message (Writing YAML file) * writeFileYaml->>logger: Log verbose message (Writing YAML content) * writeFileYaml->>yaml: Convert JSON to YAML * writeFileYaml->>logger: Log verbose message (Writing YAML content to file) * writeFileYaml->>fs: Write YAML content to file * writeFileYaml-->>Caller: Return (void) */ function writeFileYaml(path, json) { const log = logger.for(writeFileYaml); log.debug(`Writing YAML file: ${path}`); log.debug(`Writing YAML content: ${JSON.stringify(json, null, 2)}`); const content = yaml.dump(json, { indent: 2, lineWidth: -1 }); log.debug(`Writing YAML content to file: ${content}`); fs.writeFileSync(path, content.replace(/ null$/gm, ""), "utf8"); } async function runCommand(command, args = [], options = { stdio: "inherit" }, logMatch) { const log = logging.Logging.for(runCommand); log.info(`Running command: ${command} ${args.join(" ")}`); if (!logMatch) return child_process.execSync([command, ...args].join(" "), options); return new Promise((resolve, reject) => { const child = child_process.spawn(command, args, options); let stdoutData = ""; let stderrData = ""; const checkMatch = (data) => { if (logMatch && logMatch.test(data)) { resolve(child); } }; child.stdout.on("data", (data) => { const strData = data.toString(); console.log(strData); stdoutData += strData; checkMatch(strData); }); child.stderr.on("data", (data) => { const strData = data.toString(); console.error(strData); stderrData += strData; checkMatch(strData); }); child.on("error", (err) => { reject(err); }); child.on("close", (code) => { if (code === 0) { resolve(child); } else { reject(new Error(`Process exited with code ${code}\nStdout: ${stdoutData}\nStderr: ${stderrData}`)); } }); }); } /** * @module fabric-weaver * @description This module serves as the main entry point for the fabric-weaver library, providing TypeScript integration with Hyperledger Fabric. * @summary Aggregates and exports functionality for managing Hyperledger Fabric infrastructures. * * The module includes: * 1. Utility functions and types from the "./utils" directory: * - Helper functions for interacting with Fabric binaries. * - Utilities for generating and managing Docker Compose files. * - Functions to assist in creating, maintaining, and updating Hyperledger Fabric networks. * * 2. Core functionality from the "./core" directory: * - TypeScript interfaces and classes representing Fabric concepts. * - Implementation of Fabric operations and interactions. * * 3. A VERSION constant: * - Represents the current version of the fabric-weaver module. * - Useful for version checking and compatibility purposes. * * This structure provides a comprehensive toolkit for working with Hyperledger Fabric in TypeScript, * allowing developers to easily set up, manage, and interact with Fabric networks and components. */ /** * @const VERSION * @name VERSION * @description Represents the current version of the fabric-weaver module. * @summary The actual version number is replaced during the build process. * @type {string} */ const VERSION = "0.0.14"; exports.BuildScriptsCustom = BuildScriptsCustom; exports.VERSION = VERSION; exports.mapParser = mapParser; exports.readFileYaml = readFileYaml; exports.runCommand = runCommand; exports.safeParseCSV = safeParseCSV; exports.safeParseInt = safeParseInt; exports.safeParseJSON = safeParseJSON; exports.safeParseSSV = safeParseSSV; exports.writeFileYaml = writeFileYaml; })); //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmFicmljLXdlYXZlci5janMiLCJzb3VyY2VzIjpbIi4uL3NyYy91dGlscy1vbGQvYnVpbGQtc2NyaXB0cy50cyIsIi4uL3NyYy9jb3JlL2NvbnN0YW50cy9jb25zdGFudHMudHMiLCIuLi9zcmMvdXRpbHMvcGFyc2Vycy50cyIsIi4uL3NyYy91dGlscy95YW1sLnRzIiwiLi4vc3JjL3V0aWxzL2NoaWxkLXByb2Nlc3MudHMiLCIuLi9zcmMvaW5kZXgudHMiXSwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBAbW9kdWxlIGJ1aWxkLXNjcmlwdHNcbiAqIEBkZXNjcmlwdGlvbiBDdXN0b20gYnVpbGQgc2NyaXB0cyBmb3IgdGhlIGZhYnJpYy13ZWF2ZXIgcHJvamVjdC5cbiAqIEBzdW1tYXJ5IFRoaXMgbW9kdWxlIGV4dGVuZHMgdGhlIEJ1aWxkU2NyaXB0cyBjbGFzcyBmcm9tIEBkZWNhZi10cy91dGlscyB0byBwcm92aWRlIGN1c3RvbSBidWlsZCBmdW5jdGlvbmFsaXR5IGZvciB0aGUgZmFicmljLXdlYXZlciBwcm9qZWN0LiBJdCBpbmNsdWRlcyB1dGlsaXRpZXMgZm9yIGJ1aWxkaW5nIGNvbW1hbmQtbGluZSBpbnRlcmZhY2VzIGFuZCBoYW5kbGluZyBkaWZmZXJlbnQgbW9kdWxlIGZvcm1hdHMgKENvbW1vbkpTIGFuZCBFUyBNb2R1bGVzKS5cbiAqL1xuXG5pbXBvcnQgeyBCdWlsZFNjcmlwdHMsIHJlYWRGaWxlLCB3cml0ZUZpbGUgfSBmcm9tIFwiQGRlY2FmLXRzL3V0aWxzXCI7XG5pbXBvcnQgZnMgZnJvbSBcImZzXCI7XG5pbXBvcnQgcGF0aCBmcm9tIFwicGF0aFwiO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBFbnVtZXJhdGlvbiBvZiBtb2R1bGUgbW9kZXMuXG4gKiBAc3VtbWFyeSBEZWZpbmVzIHRoZSBkaWZmZXJlbnQgbW9kdWxlIGZvcm1hdHMgc3VwcG9ydGVkIGluIHRoZSBidWlsZCBwcm9jZXNzLlxuICogQGVudW0ge3N0cmluZ31cbiAqIEByZWFkb25seVxuICogQG1lbWJlck9mIG1vZHVsZTpidWlsZC1zY3JpcHRzXG4gKi9cbmVudW0gTW9kZXMge1xuICAvKiogQ29tbW9uSlMgbW9kdWxlIGZvcm1hdCAqL1xuICBDSlMgPSBcImNvbW1vbmpzXCIsXG4gIC8qKiBFQ01BU2NyaXB0IG1vZHVsZSBmb3JtYXQgKEVTMjAyMikgKi9cbiAgRVNNID0gXCJlczIwMjJcIixcbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gQ3VzdG9tIGJ1aWxkIHNjcmlwdHMgZm9yIHRoZSBmYWJyaWMtd2VhdmVyIHByb2plY3QuXG4gKiBAc3VtbWFyeSBFeHRlbmRzIHRoZSBCdWlsZFNjcmlwdHMgY2xhc3MgdG8gcHJvdmlkZSBwcm9qZWN0LXNwZWNpZmljIGJ1aWxkIGZ1bmN0aW9uYWxpdHksIGluY2x1ZGluZyBjb21tYW5kIGJ1bmRsaW5nIGFuZCBmaWxlIG1hbmlwdWxhdGlvbi5cbiAqIEBjbGFzcyBCdWlsZFNjcmlwdHNDdXN0b21cbiAqIEBleHRlbmRzIEJ1aWxkU2NyaXB0c1xuICovXG5leHBvcnQgY2xhc3MgQnVpbGRTY3JpcHRzQ3VzdG9tIGV4dGVuZHMgQnVpbGRTY3JpcHRzIHtcbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBCdWlsZHMgY29tbWFuZC1saW5lIGludGVyZmFjZXMgZm9yIHRoZSBwcm9qZWN0LlxuICAgKiBAc3VtbWFyeSBQcm9jZXNzZXMgZWFjaCBjb21tYW5kIGluIHRoZSBDb21tYW5kcyBhcnJheSwgYnVuZGxpbmcgdGhlIFR5cGVTY3JpcHQgZmlsZXMsIGFkZGluZyBhIHNoZWJhbmcgbGluZSwgYW5kIHNldHRpbmcgYXBwcm9wcmlhdGUgcGVybWlzc2lvbnMuXG4gICAqIEByZXR1cm4ge1Byb21pc2U8dm9pZD59XG4gICAqIEBtZXJtYWlkXG4gICAqIHNlcXVlbmNlRGlhZ3JhbVxuICAgKiAgIHBhcnRpY2lwYW50IEJ1aWxkU2NyaXB0c0N1c3RvbVxuICAgKiAgIHBhcnRpY2lwYW50IEZpbGVTeXN0ZW1cbiAgICogICBsb29wIEZvciBlYWNoIGNvbW1hbmRcbiAgICogICAgIEJ1aWxkU2NyaXB0c0N1c3RvbS0+PkJ1aWxkU2NyaXB0c0N1c3RvbTogYnVuZGxlKE1vZGVzLkNKUywgdHJ1ZSwgdHJ1ZSwgYHNyYy9iaW4vJHtjbWR9LnRzYCwgY21kKVxuICAgKiAgICAgQnVpbGRTY3JpcHRzQ3VzdG9tLT4+RmlsZVN5c3RlbTogcmVhZEZpbGUoYGJpbi8ke2NtZH0uY2pzYClcbiAgICogICAgIEZpbGVTeXN0ZW0tLT4+QnVpbGRTY3JpcHRzQ3VzdG9tOiBmaWxlIGNvbnRlbnRcbiAgICogICAgIEJ1aWxkU2NyaXB0c0N1c3RvbS0+PkJ1aWxkU2NyaXB0c0N1c3RvbTogQWRkIHNoZWJhbmcgdG8gZmlsZSBjb250ZW50XG4gICAqICAgICBCdWlsZFNjcmlwdHNDdXN0b20tPj5GaWxlU3lzdGVtOiB3cml0ZUZpbGUoYGJpbi8ke2NtZH0uY2pzYCwgbW9kaWZpZWQgY29udGVudClcbiAgICogICAgIEJ1aWxkU2NyaXB0c0N1c3RvbS0+PkZpbGVTeXN0ZW06IGNobW9kU3luYyhgYmluLyR7Y21kfS5janNgLCBcIjc1NVwiKVxuICAgKiAgIGVuZFxuICAgKi9cbiAgYXN5bmMgYnVpbGRDb21tYW5kcygpIHtcbiAgICBjb25zdCBjb21tYW5kcyA9IGZzLnJlYWRkaXJTeW5jKHBhdGguam9pbihwcm9jZXNzLmN3ZCgpICsgXCIvc3JjL2JpblwiKSk7XG4gICAgZm9yIChjb25zdCBjbWQgb2YgY29tbWFuZHMpIHtcbiAgICAgIGlmICghY21kLmVuZHNXaXRoKFwiLnRzXCIpKSBjb250aW51ZTtcblxuICAgICAgYXdhaXQgdGhpcy5idW5kbGUoTW9kZXMuQ0pTLCB0cnVlLCB0cnVlLCBgc3JjL2Jpbi8ke2NtZH1gLCBjbWQpO1xuICAgICAgbGV0IGRhdGEgPSByZWFkRmlsZShgYmluLyR7Y21kfS5janNgKTtcbiAgICAgIGRhdGEgPSBcIiMhL3Vzci9iaW4vZW52IG5vZGVcXG5cIiArIGRhdGE7XG4gICAgICB3cml0ZUZpbGUoYGJpbi8ke2NtZH0uY2pzYCwgZGF0YSk7XG4gICAgICBmcy5jaG1vZFN5bmMoYGJpbi8ke2NtZH0uY2pzYCwgXCI3NTVcIik7XG4gICAgfVxuICB9XG59XG4iLCJleHBvcnQgY29uc3QgQ09NTUFfU0VQQVJBVE9SID0gXCIsXCI7XG5leHBvcnQgY29uc3QgQ09MT05fU0VQQVJBVE9SID0gXCI6XCI7XG5leHBvcnQgY29uc3QgUElQRV9TRVBBUkFUT1IgPSBcInxcIjtcbmV4cG9ydCBjb25zdCBTTEFTSF9TRVBBUkFUT1IgPSBcIi9cIjtcblxuZXhwb3J0IGNvbnN0IE5BTUVfUExBQ0VIT0xERVIgPSBcIiMjTkFNRSMjXCI7XG5leHBvcnQgY29uc3QgVkVSU0lPTl9QTEFDRUhPTERFUiA9IFwiIyNWRVIjI1wiO1xuZXhwb3J0IGNvbnN0IEVOVFJZX1BMQUNFSE9MREVSID0gXCIjI0VOVFJZIyNcIjtcbiIsImltcG9ydCB7IENPTU1BX1NFUEFSQVRPUiwgU0xBU0hfU0VQQVJBVE9SIH0gZnJvbSBcIi4uL2NvcmUvY29uc3RhbnRzL2NvbnN0YW50c1wiO1xuXG5leHBvcnQgZnVuY3Rpb24gc2FmZVBhcnNlSlNPTih2OiBzdHJpbmcpOiB1bmtub3duIHtcbiAgdHJ5IHtcbiAgICByZXR1cm4gSlNPTi5wYXJzZSh2KTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIHRocm93IG5ldyBFcnJvcihgSW52YWxpZCBKU09OOiAkeyhlIGFzIEVycm9yKS5tZXNzYWdlfWApO1xuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBzYWZlUGFyc2VJbnQodjogc3RyaW5nIHwgbnVtYmVyKTogbnVtYmVyIHtcbiAgaWYgKHR5cGVvZiB2ID09PSBcIm51bWJlclwiKSByZXR1cm4gTWF0aC5mbG9vcih2KTtcblxuICBjb25zdCB2YWx1ZSA9IE51bWJlcih2KTtcblxuICBpZiAoIU51bWJlci5pc0ludGVnZXIodmFsdWUpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBJbnZhbGlkIGludGVnZXIgdmFsdWU6ICR7dn1gKTtcbiAgfVxuXG4gIHJldHVybiB2YWx1ZTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHNhZmVQYXJzZUNTVihjc3Y6IHN0cmluZyk6IHN0cmluZ1tdIHtcbiAgaWYgKCFjc3YudHJpbSgpKSByZXR1cm4gW107XG5cbiAgcmV0dXJuIGNzdi5zcGxpdChDT01NQV9TRVBBUkFUT1IpLm1hcCgoaXRlbSkgPT4gaXRlbS50cmltKCkpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gc2FmZVBhcnNlU1NWKGNzdjogc3RyaW5nKTogc3RyaW5nW10ge1xuICBjb25zb2xlLmxvZyhjc3YpO1xuICBpZiAoIWNzdi50cmltKCkpIHJldHVybiBbXTtcblxuICByZXR1cm4gY3N2LnNwbGl0KFNMQVNIX1NFUEFSQVRPUikubWFwKChpdGVtKSA9PiBgXCIke2l0ZW0udHJpbSgpfVwiYCk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBtYXBQYXJzZXIoXG4gIG1hcDogTWFwPHN0cmluZywgc3RyaW5nIHwgbnVtYmVyIHwgYm9vbGVhbiB8IHN0cmluZ1tdPlxuKTogc3RyaW5nW10ge1xuICBjb25zdCBhcmd6ID0gQXJyYXkuZnJvbShtYXAsIChba2V5LCB2YWx1ZV0pID0+IHtcbiAgICBpZiAodHlwZW9mIHZhbHVlID09PSBcImJvb2xlYW5cIikge1xuICAgICAgcmV0dXJuIHZhbHVlID8gW2AtLSR7a2V5fWBdIDogW107XG4gICAgfVxuICAgIGlmIChBcnJheS5pc0FycmF5KHZhbHVlKSkge1xuICAgICAgcmV0dXJuIFtgLS0ke2tleX1gLCB2YWx1ZS5qb2luKFwiLFwiKV07XG4gICAgfVxuICAgIHJldHVybiBbYC0tJHtrZXl9YCwgdmFsdWUudG9TdHJpbmcoKV07XG4gIH0pO1xuXG4gIHJldHVybiBhcmd6Lm1hcCgoZWwpID0+IGVsLmpvaW4oXCIgXCIpKTtcbn1cbiIsImltcG9ydCBmcyBmcm9tIFwiZnNcIjtcbmltcG9ydCB5YW1sIGZyb20gXCJqcy15YW1sXCI7XG5pbXBvcnQgeyBMb2dnaW5nIH0gZnJvbSBcIkBkZWNhZi10cy9sb2dnaW5nXCI7XG5cbmNvbnN0IGxvZ2dlciA9IExvZ2dpbmcuZm9yKFwieWFtbFwiKTtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gUmVhZHMgYW5kIHBhcnNlcyBhIFlBTUwgZmlsZSwgb3B0aW9uYWxseSByZXRyaWV2aW5nIGEgc3BlY2lmaWMgcHJvcGVydHkuXG4gKiBAc3VtbWFyeSBUaGlzIGZ1bmN0aW9uIHJlYWRzIGEgWUFNTCBmaWxlIGZyb20gdGhlIGdpdmVuIHBhdGgsIHBhcnNlcyBpdHMgY29udGVudCwgYW5kIHJldHVybnMgZWl0aGVyIHRoZSBlbnRpcmUgcGFyc2VkIFlBTUwgb2JqZWN0IG9yIGEgc3BlY2lmaWMgcHJvcGVydHkgdmFsdWUgYmFzZWQgb24gdGhlIHByb3ZpZGVkIHBhdGguXG4gKlxuICogQGZ1bmN0aW9uIHJlYWRGaWxlWWFtbFxuICogQHRlbXBsYXRlIFQgLSBUaGUgdHlwZSBvZiB0aGUgcmV0dXJuZWQgdmFsdWUgd2hlbiBhIHNwZWNpZmljIHByb3BlcnR5IGlzIHJlcXVlc3RlZC5cbiAqIEBwYXJhbSB7c3RyaW5nfSB5YW1sRmlsZVBhdGggLSBUaGUgcGF0aCB0byB0aGUgWUFNTCBmaWxlIHRvIGJlIHJlYWQuXG4gKiBAcGFyYW0ge3N0cmluZ30gW3ZhcmlhYmxlXSAtIE9wdGlvbmFsLiBBIGRvdC1ub3RhdGVkIHBhdGggc3RyaW5nIHRoYXQgc3BlY2lmaWVzIHRoZSBwcm9wZXJ0eSB0byByZXRyaWV2ZSBmcm9tIHRoZSBwYXJzZWQgWUFNTC5cbiAqIEByZXR1cm4ge1JlY29yZDxzdHJpbmcsIGFueT4gfCBUfSBSZXR1cm5zIHRoZSBlbnRpcmUgcGFyc2VkIFlBTUwgb2JqZWN0IGlmIG5vIGB2YXJpYWJsZWAgaXMgcHJvdmlkZWQsIG9yIHRoZSB2YWx1ZSBvZiB0aGUgc3BlY2lmaWVkIHByb3BlcnR5IGlmIGB2YXJpYWJsZWAgaXMgcHJvdmlkZWQuXG4gKlxuICogQG1lbWJlck9mIG1vZHVsZTpmYWJyaWMtd2VhdmVyLlV0aWxzXG4gKlxuICogQGV4YW1wbGVcbiAqIC8vIEV4YW1wbGUgMTogUmVhZCB0aGUgZW50aXJlIFlBTUwgZmlsZVxuICogY29uc3QgY29uZmlnID0gcmVhZEZpbGVZYW1sKFwiY29uZmlnL3NldHRpbmdzLnlhbWxcIik7XG4gKiBjb25zb2xlLmxvZyhjb25maWcpO1xuICpcbiAqIEBleGFtcGxlXG4gKiAvLyBFeGFtcGxlIDI6IFJldHJpZXZlIGEgc3BlY2lmaWMgcHJvcGVydHkgZnJvbSB0aGUgWUFNTCBmaWxlXG4gKiBjb25zdCBkYkhvc3QgPSByZWFkRmlsZVlhbWwoXCJjb25maWcvc2V0dGluZ3MueWFtbFwiLCBcImRhdGFiYXNlLmhvc3RcIik7XG4gKiBjb25zb2xlLmxvZyhkYkhvc3QpO1xuICpcbiAqIEBleGFtcGxlXG4gKiAvLyBFeGFtcGxlIDM6IEhhbmRsZSBhbiBlcnJvciBpZiB0aGUgcHJvcGVydHkgZG9lcyBub3QgZXhpc3RcbiAqIGNvbnN0IGludmFsaWRQcm9wZXJ0eSA9IHJlYWRGaWxlWWFtbChcImNvbmZpZy9zZXR0aW5ncy55YW1sXCIsIFwic2VydmVyLnBvcnRcIik7XG4gKlxuICogQG1lcm1haWRcbiAqIHNlcXVlbmNlRGlhZ3JhbVxuICogICBwYXJ0aWNpcGFudCBDYWxsZXJcbiAqICAgcGFydGljaXBhbnQgcmVhZEZpbGVZYW1sXG4gKiAgIHBhcnRpY2lwYW50IGxvZ2dlclxuICogICBwYXJ0aWNpcGFudCBmc1xuICogICBwYXJ0aWNpcGFudCB5YW1sXG4gKlxuICogICBDYWxsZXItPj5yZWFkRmlsZVlhbWw6IENhbGwgd2l0aCB5YW1sRmlsZVBhdGggYW5kIG9wdGlvbmFsIHZhcmlhYmxlXG4gKiAgIHJlYWRGaWxlWWFtbC0+PmxvZ2dlcjogTG9nIHZlcmJvc2UgbWVzc2FnZSAoUmVhZGluZyBZQU1MIGZpbGUpXG4gKiAgIHJlYWRGaWxlWWFtbC0+PmZzOiBSZWFkIGZpbGUgY29udGVudFxuICogICByZWFkRmlsZVlhbWwtPj5sb2dnZXI6IExvZyB2ZXJib3NlIG1lc3NhZ2UgKFBhcnNlZCBZQU1MIGNvbnRlbnQpXG4gKiAgIHJlYWRGaWxlWWFtbC0+PnlhbWw6IFBhcnNlIFlBTUwgY29udGVudFxuICogICByZWFkRmlsZVlhbWwtPj5sb2dnZXI6IExvZyB2ZXJib3NlIG1lc3NhZ2UgKFBhcnNlZCBZQU1MIG9iamVjdClcbiAqICAgYWx0IHZhcmlhYmxlIGlzIHByb3ZpZGVkXG4gKiAgICAgcmVhZEZpbGVZYW1sLT4+cmVhZEZpbGVZYW1sOiBOYXZpZ2F0ZSB0aHJvdWdoIHBhcnNlZCBZQU1MIHVzaW5nIHZhcmlhYmxlIHBhdGhcbiAqICAgICBhbHQgUHJvcGVydHkgZXhpc3RzXG4gKiAgICAgICByZWFkRmlsZVlhbWwtLT4+Q2FsbGVyOiBSZXR1cm4gc3BlY2lmaWMgcHJvcGVydHkgdmFsdWVcbiAqICAgICBlbHNlIFByb3BlcnR5IGRvZXNuJ3QgZXhpc3RcbiAqICAgICAgIHJlYWRGaWxlWWFtbC0+PmxvZ2dlcjogTG9nIGVycm9yIG1lc3NhZ2VcbiAqICAgICAgIHJlYWRGaWxlWWFtbC0tPj5DYWxsZXI6IFJldHVybiBlcnJvclxuICogICAgIGVuZFxuICogICBlbHNlIHZhcmlhYmxlIGlzIG5vdCBwcm92aWRlZFxuICogICAgIHJlYWRGaWxlWWFtbC0tPj5DYWxsZXI6IFJldHVybiBlbnRpcmUgcGFyc2VkIFlBTUwgb2JqZWN0XG4gKiAgIGVuZFxuICovXG5leHBvcnQgZnVuY3Rpb24gcmVhZEZpbGVZYW1sPFQ+KFxuICB5YW1sRmlsZVBhdGg6IHN0cmluZyxcbiAgdmFyaWFibGU/OiBzdHJpbmdcbik6IFJlY29yZDxzdHJpbmcsIGFueT4gfCBUIHtcbiAgY29uc3QgbG9nID0gbG9nZ2VyLmZvcihyZWFkRmlsZVlhbWwpO1xuXG4gIGxvZy5kZWJ1ZyhgUmVhZGluZyBZQU1MIGZpbGU6ICR7eWFtbEZpbGVQYXRofWApO1xuICBjb25zdCBjb250ZW50ID0gZnMucmVhZEZpbGVTeW5jKHlhbWxGaWxlUGF0aCwgXCJ1dGY4XCIpO1xuXG4gIGxvZy5kZWJ1ZyhgUGFyc2VkIFlBTUwgY29udGVudDogJHtjb250ZW50fWApO1xuICBjb25zdCBwYXJzZWRZQU1MID0geWFtbC5sb2FkKGNvbnRlbnQpIGFzIFJlY29yZDxzdHJpbmcsIGFueT47XG5cbiAgbG9nLmRlYnVnKGBQYXJzZWQgWUFNTCBvYmplY3Q6ICR7SlNPTi5zdHJpbmdpZnkocGFyc2VkWUFNTCwgbnVsbCwgMil9YCk7XG5cbiAgbG9nLmluZm8oXG4gICAgYFJldHVybmluZyAke3ZhcmlhYmxlID8gYHByb3BlcnR5ICcke3ZhcmlhYmxlfSdgIDogXCJ0aGUgZW50aXJlIHBhcnNlZCBZQU1MIG9iamVjdFwifWBcbiAgKTtcbiAgaWYgKCF2YXJpYWJsZSkgcmV0dXJuIHBhcnNlZFlBTUw7XG5cbiAgY29uc3QgdmFyaWFibGVQYXRoID0gdmFyaWFibGUuc3BsaXQoXCIuXCIpO1xuXG4gIHJldHVybiB2YXJpYWJsZVBhdGgucmVkdWNlKChhY2MsIGtleSkgPT4ge1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1wcm90b3R5cGUtYnVpbHRpbnNcbiAgICBpZiAoIWFjYy5oYXNPd25Qcm9wZXJ0eShrZXkpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGBVbmFibGUgdG8gbG9jYXRlIGEgcHJvcGVydHkgbmFtZWQgJyR7a2V5fScgZnJvbSBwYXRoICcke3ZhcmlhYmxlfScgaW4gZmlsZTogXFxuPiAke3lhbWxGaWxlUGF0aH1gXG4gICAgICApO1xuICAgIH1cbiAgICByZXR1cm4gdHlwZW9mIGFjY1trZXldID09PSBcInN0cmluZ1wiID8gYWNjW2tleV0udHJpbSgpIDogYWNjW2tleV07XG4gIH0sIHBhcnNlZFlBTUwpO1xufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBXcml0ZXMgYSBKU09OIG9iamVjdCB0byBhIFlBTUwgZmlsZS5cbiAqIEBzdW1tYXJ5IFRoaXMgZnVuY3Rpb24gdGFrZXMgYSBKU09OIG9iamVjdCBhbmQgd3JpdGVzIGl0IHRvIGEgc3BlY2lmaWVkIGZpbGUgcGF0aCBpbiBZQU1MIGZvcm1hdC5cbiAqIEl0IHVzZXMganMteWFtbCB0byBjb252ZXJ0IHRoZSBKU09OIHRvIFlBTUwsIGFuZCB0aGVuIHdyaXRlcyB0aGUgY29udGVudCB0byB0aGUgZmlsZS5cbiAqXG4gKiBAZnVuY3Rpb24gd3JpdGVGaWxlWWFtbFxuICogQHRlbXBsYXRlIFQgLSBUaGUgdHlwZSBvZiB0aGUgSlNPTiBvYmplY3QgdG8gYmUgd3JpdHRlbi5cbiAqIEBwYXJhbSB7c3RyaW5nfSBwYXRoIC0gVGhlIGZpbGUgcGF0aCB3aGVyZSB0aGUgWUFNTCBjb250ZW50IHdpbGwgYmUgd3JpdHRlbi5cbiAqIEBwYXJhbSB7VH0ganNvbiAtIFRoZSBKU09OIG9iamVjdCB0byBiZSBjb252ZXJ0ZWQgdG8gWUFNTCBhbmQgd3JpdHRlbiB0byB0aGUgZmlsZS5cbiAqIEByZXR1cm4ge3ZvaWR9XG4gKlxuICogQG1lbWJlck9mIG1vZHVsZTpmYWJyaWMtd2VhdmVyLlV0aWxzXG4gKlxuICogQGV4YW1wbGVcbiAqIGNvbnN0IGNvbmZpZyA9IHsgZGF0YWJhc2U6IHsgaG9zdDogJ2xvY2FsaG9zdCcsIHBvcnQ6IDU0MzIgfSB9O1xuICogd3JpdGVGaWxlWWFtbCgnY29uZmlnL3NldHRpbmdzLnlhbWwnLCBjb25maWcpO1xuICpcbiAqIEBtZXJtYWlkXG4gKiBzZXF1ZW5jZURpYWdyYW1cbiAqICAgcGFydGljaXBhbnQgQ2FsbGVyXG4gKiAgIHBhcnRpY2lwYW50IHdyaXRlRmlsZVlhbWxcbiAqICAgcGFydGljaXBhbnQgbG9nZ2VyXG4gKiAgIHBhcnRpY2lwYW50IHlhbWxcbiAqICAgcGFydGljaXBhbnQgZnNcbiAqXG4gKiAgIENhbGxlci0+PndyaXRlRmlsZVlhbWw6IENhbGwgd2l0aCBwYXRoIGFuZCBKU09OXG4gKiAgIHdyaXRlRmlsZVlhbWwtPj5sb2dnZXI6IExvZyB2ZXJib3NlIG1lc3NhZ2UgKFdyaXRpbmcgWUFNTCBmaWxlKVxuICogICB3cml0ZUZpbGVZYW1sLT4+bG9nZ2VyOiBMb2cgdmVyYm9zZSBtZXNzYWdlIChXcml0aW5nIFlBTUwgY29udGVudClcbiAqICAgd3JpdGVGaWxlWWFtbC0+PnlhbWw6IENvbnZlcnQgSlNPTiB0byBZQU1MXG4gKiAgIHdyaXRlRmlsZVlhbWwtPj5sb2dnZXI6IExvZyB2ZXJib3NlIG1lc3NhZ2UgKFdyaXRpbmcgWUFNTCBjb250ZW50IHRvIGZpbGUpXG4gKiAgIHdyaXRlRmlsZVlhbWwtPj5mczogV3JpdGUgWUFNTCBjb250ZW50IHRvIGZpbGVcbiAqICAgd3JpdGVGaWxlWWFtbC0tPj5DYWxsZXI6IFJldHVybiAodm9pZClcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHdyaXRlRmlsZVlhbWw8VD4ocGF0aDogc3RyaW5nLCBqc29uOiBUKSB7XG4gIGNvbnN0IGxvZyA9IGxvZ2dlci5mb3Iod3JpdGVGaWxlWWFtbCk7XG5cbiAgbG9nLmRlYnVnKGBXcml0aW5nIFlBTUwgZmlsZTogJHtwYXRofWApO1xuICBsb2cuZGVidWcoYFdyaXRpbmcgWUFNTCBjb250ZW50OiAke0pTT04uc3RyaW5naWZ5KGpzb24sIG51bGwsIDIpfWApO1xuICBjb25zdCBjb250ZW50ID0geWFtbC5kdW1wKGpzb24sIHsgaW5kZW50OiAyLCBsaW5lV2lkdGg6IC0xIH0pO1xuXG4gIGxvZy5kZWJ1ZyhgV3JpdGluZyBZQU1MIGNvbnRlbnQgdG8gZmlsZTogJHtjb250ZW50fWApO1xuICBmcy53cml0ZUZpbGVTeW5jKHBhdGgsIGNvbnRlbnQucmVwbGFjZSgvIG51bGwkL2dtLCBcIlwiKSwgXCJ1dGY4XCIpO1xufVxuIiwiaW1wb3J0IHsgc3Bhd24sIENoaWxkUHJvY2VzcywgZXhlY1N5bmMgfSBmcm9tIFwiY2hpbGRfcHJvY2Vzc1wiO1xuaW1wb3J0IHsgTG9nZ2VyLCBMb2dnaW5nIH0gZnJvbSBcIkBkZWNhZi10cy9sb2dnaW5nXCI7XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBydW5Db21tYW5kKFxuICBjb21tYW5kOiBzdHJpbmcsXG4gIGFyZ3M6IHN0cmluZ1tdID0gW10sXG4gIG9wdGlvbnM6IHsgW2luZGV4ZXI6IHN0cmluZ106IHN0cmluZyB9ID0geyBzdGRpbzogXCJpbmhlcml0XCIgfSxcbiAgbG9nTWF0Y2g/OiBSZWdFeHBcbik6IFByb21pc2U8Q2hpbGRQcm9jZXNzIHwgdm9pZCB8IEJ1ZmZlcj4ge1xuICBjb25zdCBsb2c6IExvZ2dlciA9IExvZ2dpbmcuZm9yKHJ1bkNvbW1hbmQpO1xuICBsb2cuaW5mbyhgUnVubmluZyBjb21tYW5kOiAke2NvbW1hbmR9ICR7YXJncy5qb2luKFwiIFwiKX1gKTtcblxuICBpZiAoIWxvZ01hdGNoKSByZXR1cm4gZXhlY1N5bmMoW2NvbW1hbmQsIC4uLmFyZ3NdLmpvaW4oXCIgXCIpLCBvcHRpb25zKTtcblxuICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgIGNvbnN0IGNoaWxkID0gc3Bhd24oY29tbWFuZCwgYXJncywgb3B0aW9ucyk7XG4gICAgbGV0IHN0ZG91dERhdGEgPSBcIlwiO1xuICAgIGxldCBzdGRlcnJEYXRhID0gXCJcIjtcblxuICAgIGNvbnN0IGNoZWNrTWF0Y2ggPSAoZGF0YTogc3RyaW5nKSA9PiB7XG4gICAgICBpZiAobG9nTWF0Y2ggJiYgbG9nTWF0Y2gudGVzdChkYXRhKSkge1xuICAgICAgICByZXNvbHZlKGNoaWxkKTtcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgY2hpbGQuc3Rkb3V0Lm9uKFwiZGF0YVwiLCAoZGF0YTogQnVmZmVyKSA9PiB7XG4gICAgICBjb25zdCBzdHJEYXRhID0gZGF0YS50b1N0cmluZygpO1xuICAgICAgY29uc29sZS5sb2coc3RyRGF0YSk7XG4gICAgICBzdGRvdXREYXRhICs9IHN0ckRhdGE7XG4gICAgICBjaGVja01hdGNoKHN0ckRhdGEpO1xuICAgIH0pO1xuXG4gICAgY2hpbGQuc3RkZXJyLm9uKFwiZGF0YVwiLCAoZGF0YTogQnVmZmVyKSA9PiB7XG4gICAgICBjb25zdCBzdHJEYXRhID0gZGF0YS50b1N0cmluZygpO1xuICAgICAgY29uc29sZS5lcnJvcihzdHJEYXRhKTtcbiAgICAgIHN0ZGVyckRhdGEgKz0gc3RyRGF0YTtcbiAgICAgIGNoZWNrTWF0Y2goc3RyRGF0YSk7XG4gICAgfSk7XG5cbiAgICBjaGlsZC5vbihcImVycm9yXCIsIChlcnI6IEVycm9yKSA9PiB7XG4gICAgICByZWplY3QoZXJyKTtcbiAgICB9KTtcblxuICAgIGNoaWxkLm9uKFwiY2xvc2VcIiwgKGNvZGU6IG51bWJlcikgPT4ge1xuICAgICAgaWYgKGNvZGUgPT09IDApIHtcbiAgICAgICAgcmVzb2x2ZShjaGlsZCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZWplY3QoXG4gICAgICAgICAgbmV3IEVycm9yKFxuICAgICAgICAgICAgYFByb2Nlc3MgZXhpdGVkIHdpdGggY29kZSAke2NvZGV9XFxuU3Rkb3V0OiAke3N0ZG91dERhdGF9XFxuU3RkZXJyOiAke3N0ZGVyckRhdGF9YFxuICAgICAgICAgIClcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfSk7XG59XG4iLCIvKipcbiAqIEBtb2R1bGUgZmFicmljLXdlYXZlclxuICogQGRlc2NyaXB0aW9uIFRoaXMgbW9kdWxlIHNlcnZlcyBhcyB0aGUgbWFpbiBlbnRyeSBwb2ludCBmb3IgdGhlIGZhYnJpYy13ZWF2ZXIgbGlicmFyeSwgcHJvdmlkaW5nIFR5cGVTY3JpcHQgaW50ZWdyYXRpb24gd2l0aCBIeXBlcmxlZGdlciBGYWJyaWMuXG4gKiBAc3VtbWFyeSBBZ2dyZWdhdGVzIGFuZCBleHBvcnRzIGZ1bmN0aW9uYWxpdHkgZm9yIG1hbmFnaW5nIEh5cGVybGVkZ2VyIEZhYnJpYyBpbmZyYXN0cnVjdHVyZXMuXG4gKlxuICogVGhlIG1vZHVsZSBpbmNsdWRlczpcbiAqIDEuIFV0aWxpdHkgZnVuY3Rpb25zIGFuZCB0eXBlcyBmcm9tIHRoZSBcIi4vdXRpbHNcIiBkaXJlY3Rvcnk6XG4gKiAgICAtIEhlbHBlciBmdW5jdGlvbnMgZm9yIGludGVyYWN0aW5nIHdpdGggRmFicmljIGJpbmFyaWVzLlxuICogICAgLSBVdGlsaXRpZXMgZm9yIGdlbmVyYXRpbmcgYW5kIG1hbmFnaW5nIERvY2tlciBDb21wb3NlIGZpbGVzLlxuICogICAgLSBGdW5jdGlvbnMgdG8gYXNzaXN0IGluIGNyZWF0aW5nLCBtYWludGFpbmluZywgYW5kIHVwZGF0aW5nIEh5cGVybGVkZ2VyIEZhYnJpYyBuZXR3b3Jrcy5cbiAqXG4gKiAyLiBDb3JlIGZ1bmN0aW9uYWxpdHkgZnJvbSB0aGUgXCIuL2NvcmVcIiBkaXJlY3Rvcnk6XG4gKiAgICAtIFR5cGVTY3JpcHQgaW50ZXJmYWNlcyBhbmQgY2xhc3NlcyByZXByZXNlbnRpbmcgRmFicmljIGNvbmNlcHRzLlxuICogICAgLSBJbXBsZW1lbnRhdGlvbiBvZiBGYWJyaWMgb3BlcmF0aW9ucyBhbmQgaW50ZXJhY3Rpb25zLlxuICpcbiAqIDMuIEEgVkVSU0lPTiBjb25zdGFudDpcbiAqICAgIC0gUmVwcmVzZW50cyB0aGUgY3VycmVudCB2ZXJzaW9uIG9mIHRoZSBmYWJyaWMtd2VhdmVyIG1vZHVsZS5cbiAqICAgIC0gVXNlZnVsIGZvciB2ZXJzaW9uIGNoZWNraW5nIGFuZCBjb21wYXRpYmlsaXR5IHB1cnBvc2VzLlxuICpcbiAqIFRoaXMgc3RydWN0dXJlIHByb3ZpZGVzIGEgY29tcHJlaGVuc2l2ZSB0b29sa2l0IGZvciB3b3JraW5nIHdpdGggSHlwZXJsZWRnZXIgRmFicmljIGluIFR5cGVTY3JpcHQsXG4gKiBhbGxvd2luZyBkZXZlbG9wZXJzIHRvIGVhc2lseSBzZXQgdXAsIG1hbmFnZSwgYW5kIGludGVyYWN0IHdpdGggRmFicmljIG5ldHdvcmtzIGFuZCBjb21wb25lbnRzLlxuICovXG5cbmV4cG9ydCAqIGZyb20gXCIuL3V0aWxzLW9sZFwiO1xuZXhwb3J0ICogZnJvbSBcIi4vdXRpbHNcIjtcblxuLyoqXG4gKiBAY29uc3QgVkVSU0lPTlxuICogQG5hbWUgVkVSU0lPTlxuICogQGRlc2NyaXB0aW9uIFJlcHJlc2VudHMgdGhlIGN1cnJlbnQgdmVyc2lvbiBvZiB0aGUgZmFicmljLXdlYXZlciBtb2R1bGUuXG4gKiBAc3VtbWFyeSBUaGUgYWN0dWFsIHZlcnNpb24gbnVtYmVyIGlzIHJlcGxhY2VkIGR1cmluZyB0aGUgYnVpbGQgcHJvY2Vzcy5cbiAqIEB0eXBlIHtzdHJpbmd9XG4gKi9cbmV4cG9ydCBjb25zdCBWRVJTSU9OID0gXCIjI1ZFUlNJT04jI1wiO1xuIl0sIm5hbWVzIjpbIkJ1aWxkU2NyaXB0cyIsInJlYWRGaWxlIiwid3JpdGVGaWxlIiwiTG9nZ2luZyIsImV4ZWNTeW5jIiwic3Bhd24iXSwibWFwcGluZ3MiOiI7Ozs7OztJQUFBOzs7O0lBSUc7SUFNSDs7Ozs7O0lBTUc7SUFDSCxJQUFLLEtBS0o7SUFMRCxDQUFBLFVBQUssS0FBSyxFQUFBOztJQUVSLElBQUEsS0FBQSxDQUFBLEtBQUEsQ0FBQSxHQUFBLFVBQWdCOztJQUVoQixJQUFBLEtBQUEsQ0FBQSxLQUFBLENBQUEsR0FBQSxRQUFjO0lBQ2hCLENBQUMsRUFMSSxLQUFLLEtBQUwsS0FBSyxHQUtULEVBQUEsQ0FBQSxDQUFBO0lBRUQ7Ozs7O0lBS0c7SUFDRyxNQUFPLGtCQUFtQixTQUFRQSxrQkFBWSxDQUFBO0lBQ2xEOzs7Ozs7Ozs7Ozs7Ozs7O0lBZ0JHO0lBQ0gsSUFBQSxNQUFNLGFBQWEsR0FBQTtJQUNqQixRQUFBLE1BQU0sUUFBUSxHQUFHLEVBQUUsQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsR0FBRyxFQUFFLEdBQUcsVUFBVSxDQUFDLENBQUM7SUFDdEUsUUFBQSxLQUFLLE1BQU0sR0FBRyxJQUFJLFFBQVEsRUFBRTtJQUMxQixZQUFBLElBQUksQ0FBQyxHQUFHLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQztvQkFBRTtJQUUxQixZQUFBLE1BQU0sSUFBSSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsR0FBRyxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsQ0FBVyxRQUFBLEVBQUEsR0FBRyxFQUFFLEVBQUUsR0FBRyxDQUFDO2dCQUMvRCxJQUFJLElBQUksR0FBR0MsY0FBUSxDQUFDLE9BQU8sR0FBRyxDQUFBLElBQUEs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