UNPKG

@decaf-ts/fabric-weaver

Version:
117 lines 14.7 kB
import fs from "fs"; import yaml from "js-yaml"; import { Logging } from "@decaf-ts/logging"; const logger = 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 */ export 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) */ export 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"); } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoieWFtbC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy91dGlscy95YW1sLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxNQUFNLElBQUksQ0FBQztBQUNwQixPQUFPLElBQUksTUFBTSxTQUFTLENBQUM7QUFDM0IsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBRTVDLE1BQU0sTUFBTSxHQUFHLE9BQU8sQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUM7QUFFbkM7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQW1ERztBQUNILE1BQU0sVUFBVSxZQUFZLENBQzFCLFlBQW9CLEVBQ3BCLFFBQWlCO0lBRWpCLE1BQU0sR0FBRyxHQUFHLE1BQU0sQ0FBQyxHQUFHLENBQUMsWUFBWSxDQUFDLENBQUM7SUFFckMsR0FBRyxDQUFDLEtBQUssQ0FBQyxzQkFBc0IsWUFBWSxFQUFFLENBQUMsQ0FBQztJQUNoRCxNQUFNLE9BQU8sR0FBRyxFQUFFLENBQUMsWUFBWSxDQUFDLFlBQVksRUFBRSxNQUFNLENBQUMsQ0FBQztJQUV0RCxHQUFHLENBQUMsS0FBSyxDQUFDLHdCQUF3QixPQUFPLEVBQUUsQ0FBQyxDQUFDO0lBQzdDLE1BQU0sVUFBVSxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUF3QixDQUFDO0lBRTdELEdBQUcsQ0FBQyxLQUFLLENBQUMsdUJBQXVCLElBQUksQ0FBQyxTQUFTLENBQUMsVUFBVSxFQUFFLElBQUksRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUM7SUFFeEUsR0FBRyxDQUFDLElBQUksQ0FDTixhQUFhLFFBQVEsQ0FBQyxDQUFDLENBQUMsYUFBYSxRQUFRLEdBQUcsQ0FBQyxDQUFDLENBQUMsK0JBQStCLEVBQUUsQ0FDckYsQ0FBQztJQUNGLElBQUksQ0FBQyxRQUFRO1FBQUUsT0FBTyxVQUFVLENBQUM7SUFFakMsTUFBTSxZQUFZLEdBQUcsUUFBUSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUV6QyxPQUFPLFlBQVksQ0FBQyxNQUFNLENBQUMsQ0FBQyxHQUFHLEVBQUUsR0FBRyxFQUFFLEVBQUU7UUFDdEMsaURBQWlEO1FBQ2pELElBQUksQ0FBQyxHQUFHLENBQUMsY0FBYyxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUM7WUFDN0IsTUFBTSxJQUFJLEtBQUssQ0FDYixzQ0FBc0MsR0FBRyxnQkFBZ0IsUUFBUSxrQkFBa0IsWUFBWSxFQUFFLENBQ2xHLENBQUM7UUFDSixDQUFDO1FBQ0QsT0FBTyxPQUFPLEdBQUcsQ0FBQyxHQUFHLENBQUMsS0FBSyxRQUFRLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQ25FLENBQUMsRUFBRSxVQUFVLENBQUMsQ0FBQztBQUNqQixDQUFDO0FBRUQ7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBZ0NHO0FBQ0gsTUFBTSxVQUFVLGFBQWEsQ0FBSSxJQUFZLEVBQUUsSUFBTztJQUNwRCxNQUFNLEdBQUcsR0FBRyxNQUFNLENBQUMsR0FBRyxDQUFDLGFBQWEsQ0FBQyxDQUFDO0lBRXRDLEdBQUcsQ0FBQyxLQUFLLENBQUMsc0JBQXNCLElBQUksRUFBRSxDQUFDLENBQUM7SUFDeEMsR0FBRyxDQUFDLEtBQUssQ0FBQyx5QkFBeUIsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUNwRSxNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxFQUFFLE1BQU0sRUFBRSxDQUFDLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUU5RCxHQUFHLENBQUMsS0FBSyxDQUFDLGlDQUFpQyxPQUFPLEVBQUUsQ0FBQyxDQUFDO0lBQ3RELEVBQUUsQ0FBQyxhQUFhLENBQUMsSUFBSSxFQUFFLE9BQU8sQ0FBQyxPQUFPLENBQUMsVUFBVSxFQUFFLEVBQUUsQ0FBQyxFQUFFLE1BQU0sQ0FBQyxDQUFDO0FBQ2xFLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgZnMgZnJvbSBcImZzXCI7XG5pbXBvcnQgeWFtbCBmcm9tIFwianMteWFtbFwiO1xuaW1wb3J0IHsgTG9nZ2luZyB9IGZyb20gXCJAZGVjYWYtdHMvbG9nZ2luZ1wiO1xuXG5jb25zdCBsb2dnZXIgPSBMb2dnaW5nLmZvcihcInlhbWxcIik7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIFJlYWRzIGFuZCBwYXJzZXMgYSBZQU1MIGZpbGUsIG9wdGlvbmFsbHkgcmV0cmlldmluZyBhIHNwZWNpZmljIHByb3BlcnR5LlxuICogQHN1bW1hcnkgVGhpcyBmdW5jdGlvbiByZWFkcyBhIFlBTUwgZmlsZSBmcm9tIHRoZSBnaXZlbiBwYXRoLCBwYXJzZXMgaXRzIGNvbnRlbnQsIGFuZCByZXR1cm5zIGVpdGhlciB0aGUgZW50aXJlIHBhcnNlZCBZQU1MIG9iamVjdCBvciBhIHNwZWNpZmljIHByb3BlcnR5IHZhbHVlIGJhc2VkIG9uIHRoZSBwcm92aWRlZCBwYXRoLlxuICpcbiAqIEBmdW5jdGlvbiByZWFkRmlsZVlhbWxcbiAqIEB0ZW1wbGF0ZSBUIC0gVGhlIHR5cGUgb2YgdGhlIHJldHVybmVkIHZhbHVlIHdoZW4gYSBzcGVjaWZpYyBwcm9wZXJ0eSBpcyByZXF1ZXN0ZWQuXG4gKiBAcGFyYW0ge3N0cmluZ30geWFtbEZpbGVQYXRoIC0gVGhlIHBhdGggdG8gdGhlIFlBTUwgZmlsZSB0byBiZSByZWFkLlxuICogQHBhcmFtIHtzdHJpbmd9IFt2YXJpYWJsZV0gLSBPcHRpb25hbC4gQSBkb3Qtbm90YXRlZCBwYXRoIHN0cmluZyB0aGF0IHNwZWNpZmllcyB0aGUgcHJvcGVydHkgdG8gcmV0cmlldmUgZnJvbSB0aGUgcGFyc2VkIFlBTUwuXG4gKiBAcmV0dXJuIHtSZWNvcmQ8c3RyaW5nLCBhbnk+IHwgVH0gUmV0dXJucyB0aGUgZW50aXJlIHBhcnNlZCBZQU1MIG9iamVjdCBpZiBubyBgdmFyaWFibGVgIGlzIHByb3ZpZGVkLCBvciB0aGUgdmFsdWUgb2YgdGhlIHNwZWNpZmllZCBwcm9wZXJ0eSBpZiBgdmFyaWFibGVgIGlzIHByb3ZpZGVkLlxuICpcbiAqIEBtZW1iZXJPZiBtb2R1bGU6ZmFicmljLXdlYXZlci5VdGlsc1xuICpcbiAqIEBleGFtcGxlXG4gKiAvLyBFeGFtcGxlIDE6IFJlYWQgdGhlIGVudGlyZSBZQU1MIGZpbGVcbiAqIGNvbnN0IGNvbmZpZyA9IHJlYWRGaWxlWWFtbChcImNvbmZpZy9zZXR0aW5ncy55YW1sXCIpO1xuICogY29uc29sZS5sb2coY29uZmlnKTtcbiAqXG4gKiBAZXhhbXBsZVxuICogLy8gRXhhbXBsZSAyOiBSZXRyaWV2ZSBhIHNwZWNpZmljIHByb3BlcnR5IGZyb20gdGhlIFlBTUwgZmlsZVxuICogY29uc3QgZGJIb3N0ID0gcmVhZEZpbGVZYW1sKFwiY29uZmlnL3NldHRpbmdzLnlhbWxcIiwgXCJkYXRhYmFzZS5ob3N0XCIpO1xuICogY29uc29sZS5sb2coZGJIb3N0KTtcbiAqXG4gKiBAZXhhbXBsZVxuICogLy8gRXhhbXBsZSAzOiBIYW5kbGUgYW4gZXJyb3IgaWYgdGhlIHByb3BlcnR5IGRvZXMgbm90IGV4aXN0XG4gKiBjb25zdCBpbnZhbGlkUHJvcGVydHkgPSByZWFkRmlsZVlhbWwoXCJjb25maWcvc2V0dGluZ3MueWFtbFwiLCBcInNlcnZlci5wb3J0XCIpO1xuICpcbiAqIEBtZXJtYWlkXG4gKiBzZXF1ZW5jZURpYWdyYW1cbiAqICAgcGFydGljaXBhbnQgQ2FsbGVyXG4gKiAgIHBhcnRpY2lwYW50IHJlYWRGaWxlWWFtbFxuICogICBwYXJ0aWNpcGFudCBsb2dnZXJcbiAqICAgcGFydGljaXBhbnQgZnNcbiAqICAgcGFydGljaXBhbnQgeWFtbFxuICpcbiAqICAgQ2FsbGVyLT4+cmVhZEZpbGVZYW1sOiBDYWxsIHdpdGggeWFtbEZpbGVQYXRoIGFuZCBvcHRpb25hbCB2YXJpYWJsZVxuICogICByZWFkRmlsZVlhbWwtPj5sb2dnZXI6IExvZyB2ZXJib3NlIG1lc3NhZ2UgKFJlYWRpbmcgWUFNTCBmaWxlKVxuICogICByZWFkRmlsZVlhbWwtPj5mczogUmVhZCBmaWxlIGNvbnRlbnRcbiAqICAgcmVhZEZpbGVZYW1sLT4+bG9nZ2VyOiBMb2cgdmVyYm9zZSBtZXNzYWdlIChQYXJzZWQgWUFNTCBjb250ZW50KVxuICogICByZWFkRmlsZVlhbWwtPj55YW1sOiBQYXJzZSBZQU1MIGNvbnRlbnRcbiAqICAgcmVhZEZpbGVZYW1sLT4+bG9nZ2VyOiBMb2cgdmVyYm9zZSBtZXNzYWdlIChQYXJzZWQgWUFNTCBvYmplY3QpXG4gKiAgIGFsdCB2YXJpYWJsZSBpcyBwcm92aWRlZFxuICogICAgIHJlYWRGaWxlWWFtbC0+PnJlYWRGaWxlWWFtbDogTmF2aWdhdGUgdGhyb3VnaCBwYXJzZWQgWUFNTCB1c2luZyB2YXJpYWJsZSBwYXRoXG4gKiAgICAgYWx0IFByb3BlcnR5IGV4aXN0c1xuICogICAgICAgcmVhZEZpbGVZYW1sLS0+PkNhbGxlcjogUmV0dXJuIHNwZWNpZmljIHByb3BlcnR5IHZhbHVlXG4gKiAgICAgZWxzZSBQcm9wZXJ0eSBkb2Vzbid0IGV4aXN0XG4gKiAgICAgICByZWFkRmlsZVlhbWwtPj5sb2dnZXI6IExvZyBlcnJvciBtZXNzYWdlXG4gKiAgICAgICByZWFkRmlsZVlhbWwtLT4+Q2FsbGVyOiBSZXR1cm4gZXJyb3JcbiAqICAgICBlbmRcbiAqICAgZWxzZSB2YXJpYWJsZSBpcyBub3QgcHJvdmlkZWRcbiAqICAgICByZWFkRmlsZVlhbWwtLT4+Q2FsbGVyOiBSZXR1cm4gZW50aXJlIHBhcnNlZCBZQU1MIG9iamVjdFxuICogICBlbmRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlYWRGaWxlWWFtbDxUPihcbiAgeWFtbEZpbGVQYXRoOiBzdHJpbmcsXG4gIHZhcmlhYmxlPzogc3RyaW5nXG4pOiBSZWNvcmQ8c3RyaW5nLCBhbnk+IHwgVCB7XG4gIGNvbnN0IGxvZyA9IGxvZ2dlci5mb3IocmVhZEZpbGVZYW1sKTtcblxuICBsb2cuZGVidWcoYFJlYWRpbmcgWUFNTCBmaWxlOiAke3lhbWxGaWxlUGF0aH1gKTtcbiAgY29uc3QgY29udGVudCA9IGZzLnJlYWRGaWxlU3luYyh5YW1sRmlsZVBhdGgsIFwidXRmOFwiKTtcblxuICBsb2cuZGVidWcoYFBhcnNlZCBZQU1MIGNvbnRlbnQ6ICR7Y29udGVudH1gKTtcbiAgY29uc3QgcGFyc2VkWUFNTCA9IHlhbWwubG9hZChjb250ZW50KSBhcyBSZWNvcmQ8c3RyaW5nLCBhbnk+O1xuXG4gIGxvZy5kZWJ1ZyhgUGFyc2VkIFlBTUwgb2JqZWN0OiAke0pTT04uc3RyaW5naWZ5KHBhcnNlZFlBTUwsIG51bGwsIDIpfWApO1xuXG4gIGxvZy5pbmZvKFxuICAgIGBSZXR1cm5pbmcgJHt2YXJpYWJsZSA/IGBwcm9wZXJ0eSAnJHt2YXJpYWJsZX0nYCA6IFwidGhlIGVudGlyZSBwYXJzZWQgWUFNTCBvYmplY3RcIn1gXG4gICk7XG4gIGlmICghdmFyaWFibGUpIHJldHVybiBwYXJzZWRZQU1MO1xuXG4gIGNvbnN0IHZhcmlhYmxlUGF0aCA9IHZhcmlhYmxlLnNwbGl0KFwiLlwiKTtcblxuICByZXR1cm4gdmFyaWFibGVQYXRoLnJlZHVjZSgoYWNjLCBrZXkpID0+IHtcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tcHJvdG90eXBlLWJ1aWx0aW5zXG4gICAgaWYgKCFhY2MuaGFzT3duUHJvcGVydHkoa2V5KSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgVW5hYmxlIHRvIGxvY2F0ZSBhIHByb3BlcnR5IG5hbWVkICcke2tleX0nIGZyb20gcGF0aCAnJHt2YXJpYWJsZX0nIGluIGZpbGU6IFxcbj4gJHt5YW1sRmlsZVBhdGh9YFxuICAgICAgKTtcbiAgICB9XG4gICAgcmV0dXJuIHR5cGVvZiBhY2Nba2V5XSA9PT0gXCJzdHJpbmdcIiA/IGFjY1trZXldLnRyaW0oKSA6IGFjY1trZXldO1xuICB9LCBwYXJzZWRZQU1MKTtcbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gV3JpdGVzIGEgSlNPTiBvYmplY3QgdG8gYSBZQU1MIGZpbGUuXG4gKiBAc3VtbWFyeSBUaGlzIGZ1bmN0aW9uIHRha2VzIGEgSlNPTiBvYmplY3QgYW5kIHdyaXRlcyBpdCB0byBhIHNwZWNpZmllZCBmaWxlIHBhdGggaW4gWUFNTCBmb3JtYXQuXG4gKiBJdCB1c2VzIGpzLXlhbWwgdG8gY29udmVydCB0aGUgSlNPTiB0byBZQU1MLCBhbmQgdGhlbiB3cml0ZXMgdGhlIGNvbnRlbnQgdG8gdGhlIGZpbGUuXG4gKlxuICogQGZ1bmN0aW9uIHdyaXRlRmlsZVlhbWxcbiAqIEB0ZW1wbGF0ZSBUIC0gVGhlIHR5cGUgb2YgdGhlIEpTT04gb2JqZWN0IHRvIGJlIHdyaXR0ZW4uXG4gKiBAcGFyYW0ge3N0cmluZ30gcGF0aCAtIFRoZSBmaWxlIHBhdGggd2hlcmUgdGhlIFlBTUwgY29udGVudCB3aWxsIGJlIHdyaXR0ZW4uXG4gKiBAcGFyYW0ge1R9IGpzb24gLSBUaGUgSlNPTiBvYmplY3QgdG8gYmUgY29udmVydGVkIHRvIFlBTUwgYW5kIHdyaXR0ZW4gdG8gdGhlIGZpbGUuXG4gKiBAcmV0dXJuIHt2b2lkfVxuICpcbiAqIEBtZW1iZXJPZiBtb2R1bGU6ZmFicmljLXdlYXZlci5VdGlsc1xuICpcbiAqIEBleGFtcGxlXG4gKiBjb25zdCBjb25maWcgPSB7IGRhdGFiYXNlOiB7IGhvc3Q6ICdsb2NhbGhvc3QnLCBwb3J0OiA1NDMyIH0gfTtcbiAqIHdyaXRlRmlsZVlhbWwoJ2NvbmZpZy9zZXR0aW5ncy55YW1sJywgY29uZmlnKTtcbiAqXG4gKiBAbWVybWFpZFxuICogc2VxdWVuY2VEaWFncmFtXG4gKiAgIHBhcnRpY2lwYW50IENhbGxlclxuICogICBwYXJ0aWNpcGFudCB3cml0ZUZpbGVZYW1sXG4gKiAgIHBhcnRpY2lwYW50IGxvZ2dlclxuICogICBwYXJ0aWNpcGFudCB5YW1sXG4gKiAgIHBhcnRpY2lwYW50IGZzXG4gKlxuICogICBDYWxsZXItPj53cml0ZUZpbGVZYW1sOiBDYWxsIHdpdGggcGF0aCBhbmQgSlNPTlxuICogICB3cml0ZUZpbGVZYW1sLT4+bG9nZ2VyOiBMb2cgdmVyYm9zZSBtZXNzYWdlIChXcml0aW5nIFlBTUwgZmlsZSlcbiAqICAgd3JpdGVGaWxlWWFtbC0+PmxvZ2dlcjogTG9nIHZlcmJvc2UgbWVzc2FnZSAoV3JpdGluZyBZQU1MIGNvbnRlbnQpXG4gKiAgIHdyaXRlRmlsZVlhbWwtPj55YW1sOiBDb252ZXJ0IEpTT04gdG8gWUFNTFxuICogICB3cml0ZUZpbGVZYW1sLT4+bG9nZ2VyOiBMb2cgdmVyYm9zZSBtZXNzYWdlIChXcml0aW5nIFlBTUwgY29udGVudCB0byBmaWxlKVxuICogICB3cml0ZUZpbGVZYW1sLT4+ZnM6IFdyaXRlIFlBTUwgY29udGVudCB0byBmaWxlXG4gKiAgIHdyaXRlRmlsZVlhbWwtLT4+Q2FsbGVyOiBSZXR1cm4gKHZvaWQpXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB3cml0ZUZpbGVZYW1sPFQ+KHBhdGg6IHN0cmluZywganNvbjogVCkge1xuICBjb25zdCBsb2cgPSBsb2dnZXIuZm9yKHdyaXRlRmlsZVlhbWwpO1xuXG4gIGxvZy5kZWJ1ZyhgV3JpdGluZyBZQU1MIGZpbGU6ICR7cGF0aH1gKTtcbiAgbG9nLmRlYnVnKGBXcml0aW5nIFlBTUwgY29udGVudDogJHtKU09OLnN0cmluZ2lmeShqc29uLCBudWxsLCAyKX1gKTtcbiAgY29uc3QgY29udGVudCA9IHlhbWwuZHVtcChqc29uLCB7IGluZGVudDogMiwgbGluZVdpZHRoOiAtMSB9KTtcblxuICBsb2cuZGVidWcoYFdyaXRpbmcgWUFNTCBjb250ZW50IHRvIGZpbGU6ICR7Y29udGVudH1gKTtcbiAgZnMud3JpdGVGaWxlU3luYyhwYXRoLCBjb250ZW50LnJlcGxhY2UoLyBudWxsJC9nbSwgXCJcIiksIFwidXRmOFwiKTtcbn1cbiJdfQ==