@cdktf/hcl2json
Version:
Transform HCL into JSON
177 lines • 21.7 kB
JavaScript
;
// Copyright (c) HashiCorp, Inc
// SPDX-License-Identifier: MPL-2.0
// eslint-disable-next-line @typescript-eslint/triple-slash-reference
/// <reference lib="dom" />
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 (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.getExpressionAst = exports.getReferencesInExpression = exports.convertFiles = exports.parse = void 0;
// Inspired by
// https://github.com/ts-terraform/ts-terraform
// https://github.com/aaronpowell/webpack-golang-wasm-async-loader
const fs = __importStar(require("fs-extra"));
const path_1 = require("path");
const deepmerge_1 = require("./deepmerge");
const zlib_1 = require("zlib");
const references_1 = require("./references");
const util_1 = require("./util");
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
const jsRoot = {};
function sleep() {
return new Promise((resolve) => {
setTimeout(resolve, 0);
});
}
function goBridge(getBytes) {
let ready = false;
async function init() {
// After: https://github.com/golang/go/commit/680caf15355057ca84857a2a291b6f5c44e73329
// Go 1.19+ has a different entrypoint
await Promise.resolve().then(() => __importStar(require(`../wasm/bridge_wasm_exec.js`)));
const go = new global.Go();
const bytes = await getBytes;
const result = await WebAssembly.instantiate(bytes, go.importObject);
global.__parse_terraform_config_wasm__ = jsRoot;
void go.run(result.instance);
ready = true;
}
init().catch((error) => {
throw error;
});
const proxy = new Proxy({}, {
get: (_, key) => {
return async (...args) => {
while (!ready) {
await sleep();
}
if (!(key in jsRoot)) {
throw new Error(`There is nothing defined with the name "${key.toString()}"`);
}
if (typeof jsRoot[key] !== "function") {
return jsRoot[key];
}
return new Promise((resolve, reject) => {
const cb = (err, ...msg) =>
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
err ? reject(new Error(err)) : resolve(...msg);
const run = () => {
jsRoot[key].apply(undefined, [...args, cb]);
};
run();
});
};
},
});
return proxy;
}
const loadWasm = async () => {
return (0, zlib_1.gunzipSync)(await fs.readFile((0, path_1.join)(__dirname, "..", "main.wasm.gz")));
};
const wasm = goBridge(loadWasm());
async function parse(filename, contents) {
const res = await wasm.parse(filename, contents);
return JSON.parse(res);
}
exports.parse = parse;
async function convertFiles(workingDirectory) {
let tfFileContents = "";
const tfJSONFileContents = [];
for (const file of fs.readdirSync(workingDirectory)) {
const filePath = (0, path_1.resolve)(workingDirectory, file);
if (!fs.lstatSync(filePath).isDirectory()) {
if (file.match(/\.tf$/)) {
tfFileContents += fs.readFileSync(filePath, "utf-8");
tfFileContents += "\n";
}
else if (file.match(/\.tf\.json$/)) {
tfJSONFileContents.push(JSON.parse(fs.readFileSync(filePath, "utf-8")));
}
}
}
if (tfFileContents === "" && tfJSONFileContents.length === 0) {
console.error(`No '.tf' or '.tf.json' files found in ${workingDirectory}`);
return {};
}
return (0, deepmerge_1.deepMerge)(await parse("hcl2json.tf", tfFileContents), ...tfJSONFileContents);
}
exports.convertFiles = convertFiles;
/**
* Parse a Terraform expression and return the AST. This function expects a string input, and will wrap the expression in quotes if it is not already quoted.
* @param filename The filename to use for the expression. This is used for error reporting.
* @param expression The expression to parse.
* @returns An array of References found in the expression.
*/
async function getReferencesInExpression(filename, expression) {
// We have to do this twice because of the problem with HEREDOCS
// Our current hcl2json implementation removes HEREDOCS and replaces them
// with a multi-line string, which is causing all kinds of problems
let offset = 0;
let quoteWrappedExpression = expression;
if (!expression.startsWith('"')) {
quoteWrappedExpression = `"${expression}"`;
offset = 1;
}
const { wrap: wrappedExpression, wrapOffset: startOffset } = (0, util_1.wrapTerraformExpression)(`${quoteWrappedExpression}`);
offset += startOffset;
const ast = await getExpressionAst(filename, wrappedExpression);
if (!ast) {
return [];
}
const refs = (0, references_1.findAllReferencesInAst)(expression, ast);
if (wrappedExpression === expression) {
return refs;
}
return refs.map((ref) => {
return {
...ref,
startPosition: ref.startPosition - offset,
endPosition: ref.endPosition - offset,
};
});
}
exports.getReferencesInExpression = getReferencesInExpression;
/**
* Parse a Terraform expression and return the AST. The expression does not need to be a Terraform string.
* @param filename The filename to use for the expression. This is used for error reporting.
* @param expression The expression to parse.
* @returns The AST for the expression.
*
* The returned AST has the following structure:
* - type: The type of the node. This is a string.
* - range: This contains the start and end of the node in the expression.
* - children: This contains the children of the node. This is an array of nodes.
* - meta: This contains metadata about the node. This is an object, and varies depending on the type of the node.
*/
async function getExpressionAst(filename, expression) {
const res = await wasm.getExpressionAst(filename, expression);
const ast = JSON.parse(res);
if (!ast) {
return null;
}
return ast;
}
exports.getExpressionAst = getExpressionAst;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYnJpZGdlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiYnJpZGdlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQSwrQkFBK0I7QUFDL0IsbUNBQW1DO0FBQ25DLHFFQUFxRTtBQUNyRSwyQkFBMkI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBRTNCLGNBQWM7QUFDZCwrQ0FBK0M7QUFDL0Msa0VBQWtFO0FBRWxFLDZDQUErQjtBQUMvQiwrQkFBcUM7QUFDckMsMkNBQXdDO0FBQ3hDLCtCQUFrQztBQUNsQyw2Q0FBaUU7QUFFakUsaUNBQWlEO0FBUWpELHNFQUFzRTtBQUN0RSxNQUFNLE1BQU0sR0FBNkIsRUFBRSxDQUFDO0FBRTVDLFNBQVMsS0FBSztJQUNaLE9BQU8sSUFBSSxPQUFPLENBQUMsQ0FBQyxPQUFPLEVBQUUsRUFBRTtRQUM3QixVQUFVLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQ3pCLENBQUMsQ0FBQyxDQUFDO0FBQ0wsQ0FBQztBQUVELFNBQVMsUUFBUSxDQUFDLFFBQXlCO0lBQ3pDLElBQUksS0FBSyxHQUFHLEtBQUssQ0FBQztJQUVsQixLQUFLLFVBQVUsSUFBSTtRQUNqQixzRkFBc0Y7UUFDdEYsc0NBQXNDO1FBQ3RDLHdEQUFhLDZCQUE2QixHQUFDLENBQUM7UUFDNUMsTUFBTSxFQUFFLEdBQUcsSUFBSyxNQUFjLENBQUMsRUFBRSxFQUFFLENBQUM7UUFDcEMsTUFBTSxLQUFLLEdBQUcsTUFBTSxRQUFRLENBQUM7UUFDN0IsTUFBTSxNQUFNLEdBQUcsTUFBTSxXQUFXLENBQUMsV0FBVyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsWUFBWSxDQUFDLENBQUM7UUFDcEUsTUFBYyxDQUFDLCtCQUErQixHQUFHLE1BQU0sQ0FBQztRQUN6RCxLQUFLLEVBQUUsQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQzdCLEtBQUssR0FBRyxJQUFJLENBQUM7SUFDZixDQUFDO0lBRUQs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QUFHLHNCQUFzQixFQUFFLENBQUMsQ0FBQztJQUV2RCxNQUFNLElBQUksV0FBVyxDQUFDO0lBRXRCLE1BQU0sR0FBRyxHQUFHLE1BQU0sZ0JBQWdCLENBQUMsUUFBUSxFQUFFLGlCQUFpQixDQUFDLENBQUM7SUFDaEUsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDO1FBQ1QsT0FBTyxFQUFFLENBQUM7SUFDWixDQUFDO0lBRUQsTUFBTSxJQUFJLEdBQUcsSUFBQSxtQ0FBc0IsRUFBQyxVQUFVLEVBQUUsR0FBRyxDQUFDLENBQUM7SUFDckQsSUFBSSxpQkFBaUIsS0FBSyxVQUFVLEVBQUUsQ0FBQztRQUNyQyxPQUFPLElBQUksQ0FBQztJQUNkLENBQUM7SUFFRCxPQUFPLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxHQUFHLEVBQUUsRUFBRTtRQUN0QixPQUFPO1lBQ0wsR0FBRyxHQUFHO1lBQ04sYUFBYSxFQUFFLEdBQUcsQ0FBQyxhQUFhLEdBQUcsTUFBTTtZQUN6QyxXQUFXLEVBQUUsR0FBRyxDQUFDLFdBQVcsR0FBRyxNQUFNO1NBQ3RDLENBQUM7SUFDSixDQUFDLENBQUMsQ0FBQztBQUNMLENBQUM7QUFwQ0QsOERBb0NDO0FBRUQ7Ozs7Ozs7Ozs7O0dBV0c7QUFDSSxLQUFLLFVBQVUsZ0JBQWdCLENBQ3BDLFFBQWdCLEVBQ2hCLFVBQWtCO0lBRWxCLE1BQU0sR0FBRyxHQUFHLE1BQU0sSUFBSSxDQUFDLGdCQUFnQixDQUFDLFFBQVEsRUFBRSxVQUFVLENBQUMsQ0FBQztJQUM5RCxNQUFNLEdBQUcsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBbUIsQ0FBQztJQUU5QyxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUM7UUFDVCxPQUFPLElBQUksQ0FBQztJQUNkLENBQUM7SUFFRCxPQUFPLEdBQUcsQ0FBQztBQUNiLENBQUM7QUFaRCw0Q0FZQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIENvcHlyaWdodCAoYykgSGFzaGlDb3JwLCBJbmNcbi8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBNUEwtMi4wXG4vLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L3RyaXBsZS1zbGFzaC1yZWZlcmVuY2Vcbi8vLyA8cmVmZXJlbmNlIGxpYj1cImRvbVwiIC8+XG5cbi8vIEluc3BpcmVkIGJ5XG4vLyBodHRwczovL2dpdGh1Yi5jb20vdHMtdGVycmFmb3JtL3RzLXRlcnJhZm9ybVxuLy8gaHR0cHM6Ly9naXRodWIuY29tL2Fhcm9ucG93ZWxsL3dlYnBhY2stZ29sYW5nLXdhc20tYXN5bmMtbG9hZGVyXG5cbmltcG9ydCAqIGFzIGZzIGZyb20gXCJmcy1leHRyYVwiO1xuaW1wb3J0IHsgam9pbiwgcmVzb2x2ZSB9IGZyb20gXCJwYXRoXCI7XG5pbXBvcnQgeyBkZWVwTWVyZ2UgfSBmcm9tIFwiLi9kZWVwbWVyZ2VcIjtcbmltcG9ydCB7IGd1bnppcFN5bmMgfSBmcm9tIFwiemxpYlwiO1xuaW1wb3J0IHsgUmVmZXJlbmNlLCBmaW5kQWxsUmVmZXJlbmNlc0luQXN0IH0gZnJvbSBcIi4vcmVmZXJlbmNlc1wiO1xuaW1wb3J0IHsgRXhwcmVzc2lvblR5cGUgfSBmcm9tIFwiLi9zeW50YXgtdHJlZVwiO1xuaW1wb3J0IHsgd3JhcFRlcnJhZm9ybUV4cHJlc3Npb24gfSBmcm9tIFwiLi91dGlsXCI7XG5cbmludGVyZmFjZSBHb0JyaWRnZSB7XG4gIHBhcnNlOiAoZmlsZW5hbWU6IHN0cmluZywgaGNsOiBzdHJpbmcpID0+IFByb21pc2U8c3RyaW5nPjtcbiAgcGFyc2VFeHByZXNzaW9uOiAoZmlsZW5hbWU6IHN0cmluZywgaGNsOiBzdHJpbmcpID0+IFByb21pc2U8c3RyaW5nPjtcbiAgZ2V0RXhwcmVzc2lvbkFzdDogKGZpbGVuYW1lOiBzdHJpbmcsIGhjbDogc3RyaW5nKSA9PiBQcm9taXNlPHN0cmluZz47XG59XG5cbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW5zYWZlLWZ1bmN0aW9uLXR5cGVcbmNvbnN0IGpzUm9vdDogUmVjb3JkPHN0cmluZywgRnVuY3Rpb24+ID0ge307XG5cbmZ1bmN0aW9uIHNsZWVwKCkge1xuICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUpID0+IHtcbiAgICBzZXRUaW1lb3V0KHJlc29sdmUsIDApO1xuICB9KTtcbn1cblxuZnVuY3Rpb24gZ29CcmlkZ2UoZ2V0Qnl0ZXM6IFByb21pc2U8QnVmZmVyPikge1xuICBsZXQgcmVhZHkgPSBmYWxzZTtcblxuICBhc3luYyBmdW5jdGlvbiBpbml0KCkge1xuICAgIC8vIEFmdGVyOiBodHRwczovL2dpdGh1Yi5jb20vZ29sYW5nL2dvL2NvbW1pdC82ODBjYWYxNTM1NTA1N2NhODQ4NTdhMmEyOTFiNmY1YzQ0ZTczMzI5XG4gICAgLy8gR28gMS4xOSsgaGFzIGEgZGlmZmVyZW50IGVudHJ5cG9pbnRcbiAgICBhd2FpdCBpbXBvcnQoYC4uL3dhc20vYnJpZGdlX3dhc21fZXhlYy5qc2ApO1xuICAgIGNvbnN0IGdvID0gbmV3IChnbG9iYWwgYXMgYW55KS5HbygpO1xuICAgIGNvbnN0IGJ5dGVzID0gYXdhaXQgZ2V0Qnl0ZXM7XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgV2ViQXNzZW1ibHkuaW5zdGFudGlhdGUoYnl0ZXMsIGdvLmltcG9ydE9iamVjdCk7XG4gICAgKGdsb2JhbCBhcyBhbnkpLl9fcGFyc2VfdGVycmFmb3JtX2NvbmZpZ193YXNtX18gPSBqc1Jvb3Q7XG4gICAgdm9pZCBnby5ydW4ocmVzdWx0Lmluc3RhbmNlKTtcbiAgICByZWFkeSA9IHRydWU7XG4gIH1cblxuICBpbml0KCkuY2F0Y2goKGVycm9yKSA9PiB7XG4gICAgdGhyb3cgZXJyb3I7XG4gIH0pO1xuXG4gIGNvbnN0IHByb3h5ID0gbmV3IFByb3h5KHt9IGFzIEdvQnJpZGdlLCB7XG4gICAgZ2V0OiAoXywga2V5OiBzdHJpbmcpID0+IHtcbiAgICAgIHJldHVybiBhc3luYyAoLi4uYXJnczogdW5rbm93bltdKSA9PiB7XG4gICAgICAgIHdoaWxlICghcmVhZHkpIHtcbiAgICAgICAgICBhd2FpdCBzbGVlcCgpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCEoa2V5IGluIGpzUm9vdCkpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgICBgVGhlcmUgaXMgbm90aGluZyBkZWZpbmVkIHdpdGggdGhlIG5hbWUgXCIke2tleS50b1N0cmluZygpfVwiYCxcbiAgICAgICAgICApO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHR5cGVvZiBqc1Jvb3Rba2V5XSAhPT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgICAgcmV0dXJuIGpzUm9vdFtrZXldO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICBjb25zdCBjYiA9IChlcnI6IHN0cmluZywgLi4ubXNnOiBzdHJpbmdbXSkgPT5cbiAgICAgICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvYmFuLXRzLWNvbW1lbnRcbiAgICAgICAgICAgIC8vIEB0cy1pZ25vcmVcbiAgICAgICAgICAgIGVyciA/IHJlamVjdChuZXcgRXJyb3IoZXJyKSkgOiByZXNvbHZlKC4uLm1zZyk7XG5cbiAgICAgICAgICBjb25zdCBydW4gPSAoKSA9PiB7XG4gICAgICAgICAgICBqc1Jvb3Rba2V5XS5hcHBseSh1bmRlZmluZWQsIFsuLi5hcmdzLCBjYl0pO1xuICAgICAgICAgIH07XG5cbiAgICAgICAgICBydW4oKTtcbiAgICAgICAgfSk7XG4gICAgICB9O1xuICAgIH0sXG4gIH0pO1xuXG4gIHJldHVybiBwcm94eTtcbn1cblxuY29uc3QgbG9hZFdhc20gPSBhc3luYyAoKSA9PiB7XG4gIHJldHVybiBndW56aXBTeW5jKGF3YWl0IGZzLnJlYWRGaWxlKGpvaW4oX19kaXJuYW1lLCBcIi4uXCIsIFwibWFpbi53YXNtLmd6XCIpKSk7XG59O1xuXG5jb25zdCB3YXNtID0gZ29CcmlkZ2UobG9hZFdhc20oKSk7XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBwYXJzZShcbiAgZmlsZW5hbWU6IHN0cmluZyxcbiAgY29udGVudHM6IHN0cmluZyxcbik6IFByb21pc2U8UmVjb3JkPHN0cmluZywgYW55Pj4ge1xuICBjb25zdCByZXMgPSBhd2FpdCB3YXNtLnBhcnNlKGZpbGVuYW1lLCBjb250ZW50cyk7XG4gIHJldHVybiBKU09OLnBhcnNlKHJlcyk7XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBjb252ZXJ0RmlsZXMoXG4gIHdvcmtpbmdEaXJlY3Rvcnk6IHN0cmluZyxcbik6IFByb21pc2U8UmVjb3JkPHN0cmluZywgYW55Pj4ge1xuICBsZXQgdGZGaWxlQ29udGVudHMgPSBcIlwiO1xuICBjb25zdCB0ZkpTT05GaWxlQ29udGVudHM6IFJlY29yZDxzdHJpbmcsIGFueT5bXSA9IFtdO1xuXG4gIGZvciAoY29uc3QgZmlsZSBvZiBmcy5yZWFkZGlyU3luYyh3b3JraW5nRGlyZWN0b3J5KSkge1xuICAgIGNvbnN0IGZpbGVQYXRoID0gcmVzb2x2ZSh3b3JraW5nRGlyZWN0b3J5LCBmaWxlKTtcbiAgICBpZiAoIWZzLmxzdGF0U3luYyhmaWxlUGF0aCkuaXNEaXJlY3RvcnkoKSkge1xuICAgICAgaWYgKGZpbGUubWF0Y2goL1xcLnRmJC8pKSB7XG4gICAgICAgIHRmRmlsZUNvbnRlbnRzICs9IGZzLnJlYWRGaWxlU3luYyhmaWxlUGF0aCwgXCJ1dGYtOFwiKTtcbiAgICAgICAgdGZGaWxlQ29udGVudHMgKz0gXCJcXG5cIjtcbiAgICAgIH0gZWxzZSBpZiAoZmlsZS5tYXRjaCgvXFwudGZcXC5qc29uJC8pKSB7XG4gICAgICAgIHRmSlNPTkZpbGVDb250ZW50cy5wdXNoKEpTT04ucGFyc2UoZnMucmVhZEZpbGVTeW5jKGZpbGVQYXRoLCBcInV0Zi04XCIpKSk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgaWYgKHRmRmlsZUNvbnRlbnRzID09PSBcIlwiICYmIHRmSlNPTkZpbGVDb250ZW50cy5sZW5ndGggPT09IDApIHtcbiAgICBjb25zb2xlLmVycm9yKGBObyAnLnRmJyBvciAnLnRmLmpzb24nIGZpbGVzIGZvdW5kIGluICR7d29ya2luZ0RpcmVjdG9yeX1gKTtcbiAgICByZXR1cm4ge307XG4gIH1cblxuICByZXR1cm4gZGVlcE1lcmdlKFxuICAgIGF3YWl0IHBhcnNlKFwiaGNsMmpzb24udGZcIiwgdGZGaWxlQ29udGVudHMpLFxuICAgIC4uLnRmSlNPTkZpbGVDb250ZW50cyxcbiAgKTtcbn1cblxuLyoqXG4gKiBQYXJzZSBhIFRlcnJhZm9ybSBleHByZXNzaW9uIGFuZCByZXR1cm4gdGhlIEFTVC4gVGhpcyBmdW5jdGlvbiBleHBlY3RzIGEgc3RyaW5nIGlucHV0LCBhbmQgd2lsbCB3cmFwIHRoZSBleHByZXNzaW9uIGluIHF1b3RlcyBpZiBpdCBpcyBub3QgYWxyZWFkeSBxdW90ZWQuXG4gKiBAcGFyYW0gZmlsZW5hbWUgVGhlIGZpbGVuYW1lIHRvIHVzZSBmb3IgdGhlIGV4cHJlc3Npb24uIFRoaXMgaXMgdXNlZCBmb3IgZXJyb3IgcmVwb3J0aW5nLlxuICogQHBhcmFtIGV4cHJlc3Npb24gVGhlIGV4cHJlc3Npb24gdG8gcGFyc2UuXG4gKiBAcmV0dXJucyBBbiBhcnJheSBvZiBSZWZlcmVuY2VzIGZvdW5kIGluIHRoZSBleHByZXNzaW9uLlxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZ2V0UmVmZXJlbmNlc0luRXhwcmVzc2lvbihcbiAgZmlsZW5hbWU6IHN0cmluZyxcbiAgZXhwcmVzc2lvbjogc3RyaW5nLFxuKTogUHJvbWlzZTxSZWZlcmVuY2VbXT4ge1xuICAvLyBXZSBoYXZlIHRvIGRvIHRoaXMgdHdpY2UgYmVjYXVzZSBvZiB0aGUgcHJvYmxlbSB3aXRoIEhFUkVET0NTXG4gIC8vIE91ciBjdXJyZW50IGhjbDJqc29uIGltcGxlbWVudGF0aW9uIHJlbW92ZXMgSEVSRURPQ1MgYW5kIHJlcGxhY2VzIHRoZW1cbiAgLy8gd2l0aCBhIG11bHRpLWxpbmUgc3RyaW5nLCB3aGljaCBpcyBjYXVzaW5nIGFsbCBraW5kcyBvZiBwcm9ibGVtc1xuICBsZXQgb2Zmc2V0ID0gMDtcbiAgbGV0IHF1b3RlV3JhcHBlZEV4cHJlc3Npb24gPSBleHByZXNzaW9uO1xuICBpZiAoIWV4cHJlc3Npb24uc3RhcnRzV2l0aCgnXCInKSkge1xuICAgIHF1b3RlV3JhcHBlZEV4cHJlc3Npb24gPSBgXCIke2V4cHJlc3Npb259XCJgO1xuICAgIG9mZnNldCA9IDE7XG4gIH1cblxuICBjb25zdCB7IHdyYXA6IHdyYXBwZWRFeHByZXNzaW9uLCB3cmFwT2Zmc2V0OiBzdGFydE9mZnNldCB9ID1cbiAgICB3cmFwVGVycmFmb3JtRXhwcmVzc2lvbihgJHtxdW90ZVdyYXBwZWRFeHByZXNzaW9ufWApO1xuXG4gIG9mZnNldCArPSBzdGFydE9mZnNldDtcblxuICBjb25zdCBhc3QgPSBhd2FpdCBnZXRFeHByZXNzaW9uQXN0KGZpbGVuYW1lLCB3cmFwcGVkRXhwcmVzc2lvbik7XG4gIGlmICghYXN0KSB7XG4gICAgcmV0dXJuIFtdO1xuICB9XG5cbiAgY29uc3QgcmVmcyA9IGZpbmRBbGxSZWZlcmVuY2VzSW5Bc3QoZXhwcmVzc2lvbiwgYXN0KTtcbiAgaWYgKHdyYXBwZWRFeHByZXNzaW9uID09PSBleHByZXNzaW9uKSB7XG4gICAgcmV0dXJuIHJlZnM7XG4gIH1cblxuICByZXR1cm4gcmVmcy5tYXAoKHJlZikgPT4ge1xuICAgIHJldHVybiB7XG4gICAgICAuLi5yZWYsXG4gICAgICBzdGFydFBvc2l0aW9uOiByZWYuc3RhcnRQb3NpdGlvbiAtIG9mZnNldCxcbiAgICAgIGVuZFBvc2l0aW9uOiByZWYuZW5kUG9zaXRpb24gLSBvZmZzZXQsXG4gICAgfTtcbiAgfSk7XG59XG5cbi8qKlxuICogUGFyc2UgYSBUZXJyYWZvcm0gZXhwcmVzc2lvbiBhbmQgcmV0dXJuIHRoZSBBU1QuIFRoZSBleHByZXNzaW9uIGRvZXMgbm90IG5lZWQgdG8gYmUgYSBUZXJyYWZvcm0gc3RyaW5nLlxuICogQHBhcmFtIGZpbGVuYW1lIFRoZSBmaWxlbmFtZSB0byB1c2UgZm9yIHRoZSBleHByZXNzaW9uLiBUaGlzIGlzIHVzZWQgZm9yIGVycm9yIHJlcG9ydGluZy5cbiAqIEBwYXJhbSBleHByZXNzaW9uIFRoZSBleHByZXNzaW9uIHRvIHBhcnNlLlxuICogQHJldHVybnMgVGhlIEFTVCBmb3IgdGhlIGV4cHJlc3Npb24uXG4gKlxuICogICBUaGUgcmV0dXJuZWQgQVNUIGhhcyB0aGUgZm9sbG93aW5nIHN0cnVjdHVyZTpcbiAqICAgLSB0eXBlOiBUaGUgdHlwZSBvZiB0aGUgbm9kZS4gVGhpcyBpcyBhIHN0cmluZy5cbiAqICAgLSByYW5nZTogVGhpcyBjb250YWlucyB0aGUgc3RhcnQgYW5kIGVuZCBvZiB0aGUgbm9kZSBpbiB0aGUgZXhwcmVzc2lvbi5cbiAqICAgLSBjaGlsZHJlbjogVGhpcyBjb250YWlucyB0aGUgY2hpbGRyZW4gb2YgdGhlIG5vZGUuIFRoaXMgaXMgYW4gYXJyYXkgb2Ygbm9kZXMuXG4gKiAgIC0gbWV0YTogVGhpcyBjb250YWlucyBtZXRhZGF0YSBhYm91dCB0aGUgbm9kZS4gVGhpcyBpcyBhbiBvYmplY3QsIGFuZCB2YXJpZXMgZGVwZW5kaW5nIG9uIHRoZSB0eXBlIG9mIHRoZSBub2RlLlxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZ2V0RXhwcmVzc2lvbkFzdChcbiAgZmlsZW5hbWU6IHN0cmluZyxcbiAgZXhwcmVzc2lvbjogc3RyaW5nLFxuKTogUHJvbWlzZTxFeHByZXNzaW9uVHlwZSB8IG51bGw+IHtcbiAgY29uc3QgcmVzID0gYXdhaXQgd2FzbS5nZXRFeHByZXNzaW9uQXN0KGZpbGVuYW1lLCBleHByZXNzaW9uKTtcbiAgY29uc3QgYXN0ID0gSlNPTi5wYXJzZShyZXMpIGFzIEV4cHJlc3Npb25UeXBlO1xuXG4gIGlmICghYXN0KSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICByZXR1cm4gYXN0O1xufVxuIl19