UNPKG

@cdktf/hcl2cdk

Version:
141 lines 22.7 kB
"use strict"; /** * Copyright (c) HashiCorp, Inc. * SPDX-License-Identifier: MPL-2.0 */ Object.defineProperty(exports, "__esModule", { value: true }); exports.findUsedReferences = exports.extractReferencesFromExpression = exports.containsReference = exports.referenceToVariableName = void 0; const hcl2json_1 = require("@cdktf/hcl2json"); const utils_1 = require("./utils"); const variables_1 = require("./variables"); function referenceToVariableName(scope, ref) { const parts = ref.referencee.id.split("."); const resource = parts[0] === "data" ? `${parts[0]}.${parts[1]}` : parts[0]; const name = parts[0] === "data" ? parts[2] : parts[1]; return (0, variables_1.variableName)(scope, resource, name); } exports.referenceToVariableName = referenceToVariableName; function containsReference(expression) { if (!hcl2json_1.TFExpressionSyntaxTree.isScopeTraversalExpression(expression)) { return false; } const segments = expression.meta.traversal; const rootSegment = segments[0].segment; const fullAccessor = expression.meta.fullAccessor; if (rootSegment === "count" || // count variable rootSegment === "each" || // each variable // https://www.terraform.io/docs/language/expressions/references.html#filesystem-and-workspace-info fullAccessor.startsWith("path.module") || fullAccessor.startsWith("path.root") || fullAccessor.startsWith("path.cwd") || fullAccessor.startsWith("terraform.workspace") || fullAccessor.startsWith("self.") // block local value ) { utils_1.logger.debug(`skipping ${fullAccessor}`); return false; } return true; } exports.containsReference = containsReference; async function extractReferencesFromExpression(input, nodeIds, scopedIds = []) { utils_1.logger.debug(`extractReferencesFromExpression(${input})`); const possibleVariableSpots = await (0, hcl2json_1.getReferencesInExpression)("main.tf", input); utils_1.logger.debug(`found possible variable spots: ${JSON.stringify(possibleVariableSpots)}`); return possibleVariableSpots.reduce((carry, spot) => { const { value, startPosition, endPosition } = spot; // no reference if (!value.includes(".") || // just a literal value.startsWith(".") || // dangling property access value.endsWith("...") || // spread (likely in for loop) value.startsWith("count.") || // count variable value.startsWith("each.") || // each variable // https://www.terraform.io/docs/language/expressions/references.html#filesystem-and-workspace-info value.startsWith("path.module") || value.startsWith("path.root") || value.startsWith("path.cwd") || value.startsWith("terraform.workspace") || value.startsWith("self.") // block local value ) { utils_1.logger.debug(`skipping ${value}`); return carry; } const referenceParts = value.split("."); utils_1.logger.debug(`Searching for node id '${value}' in ${JSON.stringify(nodeIds)}`); const corespondingNodeId = [...nodeIds, ...scopedIds].find((id) => { const parts = id.split("."); const matchesFirst = parts[0] === referenceParts[0]; const matchesFirstTwo = matchesFirst && (parts[1] === referenceParts[1] || referenceParts.length === 1); return (matchesFirstTwo && (parts[0] === "data" ? parts[2] === referenceParts[2] : true)); }); if (!corespondingNodeId) { // This is most likely a false positive, so we just ignore it // We include the log below to help debugging utils_1.logger.error(`Found a reference that is unknown: ${input} has reference "${value}".The id was not found in ${JSON.stringify(nodeIds)} with temporary values ${JSON.stringify(scopedIds)}. ${utils_1.leaveCommentText}`); return carry; } if (scopedIds.includes(corespondingNodeId)) { utils_1.logger.debug(`skipping '${value}' since it's a scoped variable`); return carry; } utils_1.logger.debug(`Found node id '${corespondingNodeId}'`); const spotParts = value.split("."); let isThereANumericAccessor = false; const referenceSpotParts = spotParts.filter((part) => { if (!Number.isNaN(parseInt(part, 10))) { isThereANumericAccessor = true; return false; } return !isThereANumericAccessor; }); const fullReference = isThereANumericAccessor ? referenceSpotParts.slice(0, 2).join(".") : value; const isVariable = value.startsWith("var."); const useFqn = // Can not use FQN on vars !isVariable && // Can not use FQN on locals !value.startsWith("local.") && // If the following character is (input.substr(endPosition + 1, 1) === "*" || // a * (splat) we need to use the FQN input.substr(endPosition, 1) === "[" || // a property access isThereANumericAccessor); // a numeric access const ref = { start: startPosition, end: endPosition, referencee: { id: corespondingNodeId, full: fullReference, }, useFqn, isVariable, }; utils_1.logger.debug(`Found reference ${JSON.stringify(ref)}`); return [...carry, ref]; }, []); } exports.extractReferencesFromExpression = extractReferencesFromExpression; async function findUsedReferences(nodeIds, item) { utils_1.logger.debug(`findUsedReferences(${nodeIds}, ${item})`); if (typeof item === "string") { return await extractReferencesFromExpression(item, nodeIds, []); } if (typeof item !== "object" || item === null || item === undefined) { return []; } if (Array.isArray(item)) { return (await Promise.all(item.map((i) => findUsedReferences(nodeIds, i)))).flat(); } if (item && "dynamic" in item) { const dyn = item["dynamic"]; const { for_each, ...others } = dyn; const dynamicRef = Object.keys(others)[0]; return await findUsedReferences([...nodeIds, dynamicRef], dyn); } return (await Promise.all(Object.values(item).map((i) => findUsedReferences(nodeIds, i)))).flat(); } exports.findUsedReferences = findUsedReferences; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVmZXJlbmNlcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbInJlZmVyZW5jZXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7R0FHRzs7O0FBRUgsOENBR3lCO0FBQ3pCLG1DQUFtRDtBQUVuRCwyQ0FBMkM7QUFFM0MsU0FBZ0IsdUJBQXVCLENBQ3JDLEtBQW1CLEVBQ25CLEdBQWM7SUFFZCxNQUFNLEtBQUssR0FBRyxHQUFHLENBQUMsVUFBVSxDQUFDLEVBQUUsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDM0MsTUFBTSxRQUFRLEdBQUcsS0FBSyxDQUFDLENBQUMsQ0FBQyxLQUFLLE1BQU0sQ0FBQyxDQUFDLENBQUMsR0FBRyxLQUFLLENBQUMsQ0FBQyxDQUFDLElBQUksS0FBSyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUM1RSxNQUFNLElBQUksR0FBRyxLQUFLLENBQUMsQ0FBQyxDQUFDLEtBQUssTUFBTSxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUN2RCxPQUFPLElBQUEsd0JBQVksRUFBQyxLQUFLLEVBQUUsUUFBUSxFQUFFLElBQUksQ0FBQyxDQUFDO0FBQzdDLENBQUM7QUFSRCwwREFRQztBQUVELFNBQWdCLGlCQUFpQixDQUFDLFVBQThCO0lBQzlELElBQUksQ0FBQyxpQ0FBRyxDQUFDLDBCQUEwQixDQUFDLFVBQVUsQ0FBQyxFQUFFLENBQUM7UUFDaEQsT0FBTyxLQUFLLENBQUM7SUFDZixDQUFDO0lBRUQsTUFBTSxRQUFRLEdBQUcsVUFBVSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUM7SUFDM0MsTUFBTSxXQUFXLEdBQUcsUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQztJQUN4QyxNQUFNLFlBQVksR0FBRyxVQUFVLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQztJQUVsRCxJQUNFLFdBQVcsS0FBSyxPQUFPLElBQUksaUJBQWlCO1FBQzVDLFdBQVcsS0FBSyxNQUFNLElBQUksZ0JBQWdCO1FBQzFDLG1HQUFtRztRQUNuRyxZQUFZLENBQUMsVUFBVSxDQUFDLGFBQWEsQ0FBQztRQUN0QyxZQUFZLENBQUMsVUFBVSxDQUFDLFdBQVcsQ0FBQztRQUNwQyxZQUFZLENBQUMsVUFBVSxDQUFDLFVBQVUsQ0FBQztRQUNuQyxZQUFZLENBQUMsVUFBVSxDQUFDLHFCQUFxQixDQUFDO1FBQzlDLFlBQVksQ0FBQyxVQUFVLENBQUMsT0FBTyxDQUFDLENBQUMsb0JBQW9CO01BQ3JELENBQUM7UUFDRCxjQUFNLENBQUMsS0FBSyxDQUFDLFlBQVksWUFBWSxFQUFFLENBQUMsQ0FBQztRQUN6QyxPQUFPLEtBQUssQ0FBQztJQUNmLENBQUM7SUFFRCxPQUFPLElBQUksQ0FBQztBQUNkLENBQUM7QUF4QkQsOENBd0JDO0FBRU0sS0FBSyxVQUFVLCtCQUErQixDQUNuRCxLQUFhLEVBQ2IsT0FBMEIsRUFDMUIsWUFBK0IsRUFBRTtJQUVqQyxjQUFNLENBQUMsS0FBSyxDQUFDLG1DQUFtQyxLQUFLLEdBQUcsQ0FBQyxDQUFDO0lBQzFELE1BQU0scUJBQXFCLEdBQUcsTUFBTSxJQUFBLG9DQUF5QixFQUMzRCxTQUFTLEVBQ1QsS0FBSyxDQUNOLENBQUM7SUFFRixjQUFNLENBQUMsS0FBSyxDQUNWLGtDQUFrQyxJQUFJLENBQUMsU0FBUyxDQUFDLHFCQUFxQixDQUFDLEVBQUUsQ0FDMUUsQ0FBQztJQUVGLE9BQU8scUJBQXFCLENBQUMsTUFBTSxDQUFDLENBQUMsS0FBSyxFQUFFLElBQUksRUFBRSxFQUFFO1FBQ2xELE1BQU0sRUFBRSxLQUFLLEVBQUUsYUFBYSxFQUFFLFdBQVcsRUFBRSxHQUFHLElBQUksQ0FBQztRQUNuRCxlQUFlO1FBQ2YsSUFDRSxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLElBQUksaUJBQWlCO1lBQ3pDLEtBQUssQ0FBQyxVQUFVLENBQUMsR0FBRyxDQUFDLElBQUksMkJBQTJCO1lBQ3BELEtBQUssQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLElBQUksOEJBQThCO1lBQ3ZELEtBQUssQ0FBQyxVQUFVLENBQUMsUUFBUSxDQUFDLElBQUksaUJBQWlCO1lBQy9DLEtBQUssQ0FBQyxVQUFVLENBQUMsT0FBTyxDQUFDLElBQUksZ0JBQWdCO1lBQzdDLG1HQUFtRztZQUNuRyxLQUFLLENBQUMsVUFBVSxDQUFDLGFBQWEsQ0FBQztZQUMvQixLQUFLLENBQUMsVUFBVSxDQUFDLFdBQVcsQ0FBQztZQUM3QixLQUFLLENBQUMsVUFBVSxDQUFDLFVBQVUsQ0FBQztZQUM1QixLQUFLLENBQUMsVUFBVSxDQUFDLHFCQUFxQixDQUFDO1lBQ3ZDLEtBQUssQ0FBQyxVQUFVLENBQUMsT0FBTyxDQUFDLENBQUMsb0JBQW9CO1VBQzlDLENBQUM7WUFDRCxjQUFNLENBQUMsS0FBSyxDQUFDLFlBQVksS0FBSyxFQUFFLENBQUMsQ0FBQztZQUNsQyxPQUFPLEtBQUssQ0FBQztRQUNmLENBQUM7UUFFRCxNQUFNLGNBQWMsR0FBRyxLQUFLLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBRXhDLGNBQU0sQ0FBQyxLQUFLLENBQ1YsMEJBQTBCLEtBQUssUUFBUSxJQUFJLENBQUMsU0FBUyxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQ2pFLENBQUM7UUFDRixNQUFNLGtCQUFrQixHQUFHLENBQUMsR0FBRyxPQUFPLEVBQUUsR0FBRyxTQUFTLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxFQUFFLEVBQUUsRUFBRTtZQUNoRSxNQUFNLEtBQUssR0FBRyxFQUFFLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1lBQzVCLE1BQU0sWUFBWSxHQUFHLEtBQUssQ0FBQyxDQUFDLENBQUMsS0FBSyxjQUFjLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDcEQsTUFBTSxlQUFlLEdBQ25CLFlBQVk7Z0JBQ1osQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLEtBQUssY0FBYyxDQUFDLENBQUMsQ0FBQyxJQUFJLGNBQWMsQ0FBQyxNQUFNLEtBQUssQ0FBQyxDQUFDLENBQUM7WUFFbEUsT0FBTyxDQUNMLGVBQWU7Z0JBQ2YsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLEtBQUssTUFBTSxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLEtBQUssY0FBYyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FDOUQsQ0FBQztRQUNKLENBQUMsQ0FBQyxDQUFDO1FBRUgsSUFBSSxDQUFDLGtCQUFrQixFQUFFLENBQUM7WUFDeEIsNkRBQTZEO1lBQzdELDZDQUE2QztZQUM3QyxjQUFNLENBQUMsS0FBSyxDQUNWLHNDQUFzQyxLQUFLLG1CQUFtQixLQUFLLDZCQUE2QixJQUFJLENBQUMsU0FBUyxDQUM1RyxPQUFPLENBQ1IsMEJBQTBCLElBQUksQ0FBQyxTQUFTLENBQUMsU0FBUyxDQUFDO0VBQzFELHdCQUFnQixFQUFFLENBQ2IsQ0FBQztZQUNGLE9BQU8sS0FBSyxDQUFDO1FBQ2YsQ0FBQztRQUVELElBQUksU0FBUyxDQUFDLFFBQVEsQ0FBQyxrQkFBa0IsQ0FBQyxFQUFFLENBQUM7WUFDM0MsY0FBTSxDQUFDLEtBQUssQ0FBQyxhQUFhLEtBQUssZ0NBQWdDLENBQUMsQ0FBQztZQUNqRSxPQUFPLEtBQUssQ0FBQztRQUNmLENBQUM7UUFDRCxjQUFNLENBQUMsS0FBSyxDQUFDLGtCQUFrQixrQkFBa0IsR0FBRyxDQUFDLENBQUM7UUFFdEQsTUFBTSxTQUFTLEdBQUcsS0FBSyxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUNuQyxJQUFJLHVCQUF1QixHQUFHLEtBQUssQ0FBQztRQUNwQyxNQUFNLGtCQUFrQixHQUFHLFNBQVMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxJQUFJLEVBQUUsRUFBRTtZQUNuRCxJQUFJLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQztnQkFDdEMsdUJBQXVCLEdBQUcsSUFBSSxDQUFDO2dCQUMvQixPQUFPLEtBQUssQ0FBQztZQUNmLENBQUM7WUFFRCxPQUFPLENBQUMsdUJBQXVCLENBQUM7UUFDbEMsQ0FBQyxDQUFDLENBQUM7UUFDSCxNQUFNLGFBQWEsR0FBRyx1QkFBdUI7WUFDM0MsQ0FBQyxDQUFDLGtCQUFrQixDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQztZQUMxQyxDQUFDLENBQUMsS0FBSyxDQUFDO1FBRVYsTUFBTSxVQUFVLEdBQUcsS0FBSyxDQUFDLFVBQVUsQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUM1QyxNQUFNLE1BQU07UUFDViwwQkFBMEI7UUFDMUIsQ0FBQyxVQUFVO1lBQ1gsNEJBQTRCO1lBQzVCLENBQUMsS0FBSyxDQUFDLFVBQVUsQ0FBQyxRQUFRLENBQUM7WUFDM0IsZ0NBQWdDO1lBQ2hDLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxXQUFXLEdBQUcsQ0FBQyxFQUFFLENBQUMsQ0FBQyxLQUFLLEdBQUcsSUFBSSxxQ0FBcUM7Z0JBQ2hGLEtBQUssQ0FBQyxNQUFNLENBQUMsV0FBVyxFQUFFLENBQUMsQ0FBQyxLQUFLLEdBQUcsSUFBSSxvQkFBb0I7Z0JBQzVELHVCQUF1QixDQUFDLENBQUMsQ0FBQyxtQkFBbUI7UUFFakQsTUFBTSxHQUFHLEdBQWM7WUFDckIsS0FBSyxFQUFFLGFBQWE7WUFDcEIsR0FBRyxFQUFFLFdBQVc7WUFDaEIsVUFBVSxFQUFFO2dCQUNWLEVBQUUsRUFBRSxrQkFBa0I7Z0JBQ3RCLElBQUksRUFBRSxhQUFhO2FBQ3BCO1lBQ0QsTUFBTTtZQUNOLFVBQVU7U0FDWCxDQUFDO1FBQ0YsY0FBTSxDQUFDLEtBQUssQ0FBQyxtQkFBbUIsSUFBSSxDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDdkQsT0FBTyxDQUFDLEdBQUcsS0FBSyxFQUFFLEdBQUcsQ0FBQyxDQUFDO0lBQ3pCLENBQUMsRUFBRSxFQUFpQixDQUFDLENBQUM7QUFDeEIsQ0FBQztBQTdHRCwwRUE2R0M7QUFFTSxLQUFLLFVBQVUsa0JBQWtCLENBQ3RDLE9BQWlCLEVBQ2pCLElBQTRCO0lBRTVCLGNBQU0sQ0FBQyxLQUFLLENBQUMsc0JBQXNCLE9BQU8sS0FBSyxJQUFJLEdBQUcsQ0FBQyxDQUFDO0lBQ3hELElBQUksT0FBTyxJQUFJLEtBQUssUUFBUSxFQUFFLENBQUM7UUFDN0IsT0FBTyxNQUFNLCtCQUErQixDQUFDLElBQUksRUFBRSxPQUFPLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFDbEUsQ0FBQztJQUVELElBQUksT0FBTyxJQUFJLEtBQUssUUFBUSxJQUFJLElBQUksS0FBSyxJQUFJLElBQUksSUFBSSxLQUFLLFNBQVMsRUFBRSxDQUFDO1FBQ3BFLE9BQU8sRUFBRSxDQUFDO0lBQ1osQ0FBQztJQUVELElBQUksS0FBSyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDO1FBQ3hCLE9BQU8sQ0FDTCxNQUFNLE9BQU8sQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsa0JBQWtCLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FDbkUsQ0FBQyxJQUFJLEVBQUUsQ0FBQztJQUNYLENBQUM7SUFFRCxJQUFJLElBQUksSUFBSSxTQUFTLElBQUksSUFBSSxFQUFFLENBQUM7UUFDOUIsTUFBTSxHQUFHLEdBQUksSUFBWSxDQUFDLFNBQVMsQ0FBQyxDQUFDO1FBQ3JDLE1BQU0sRUFBRSxRQUFRLEVBQUUsR0FBRyxNQUFNLEVBQUUsR0FBRyxHQUFHLENBQUM7UUFDcEMsTUFBTSxVQUFVLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUMxQyxPQUFPLE1BQU0sa0JBQWtCLENBQUMsQ0FBQyxHQUFHLE9BQU8sRUFBRSxVQUFVLENBQUMsRUFBRSxHQUFHLENBQUMsQ0FBQztJQUNqRSxDQUFDO0lBRUQsT0FBTyxDQUNMLE1BQU0sT0FBTyxDQUFDLEdBQUcsQ0FDZixNQUFNLENBQUMsTUFBTSxDQUFDLElBQTJCLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUNuRCxrQkFBa0IsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDLENBQy9CLENBQ0YsQ0FDRixDQUFDLElBQUksRUFBRSxDQUFDO0FBQ1gsQ0FBQztBQWpDRCxnREFpQ0MiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIENvcHlyaWdodCAoYykgSGFzaGlDb3JwLCBJbmMuXG4gKiBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogTVBMLTIuMFxuICovXG5cbmltcG9ydCB7XG4gIGdldFJlZmVyZW5jZXNJbkV4cHJlc3Npb24sXG4gIFRGRXhwcmVzc2lvblN5bnRheFRyZWUgYXMgdGV4LFxufSBmcm9tIFwiQGNka3RmL2hjbDJqc29uXCI7XG5pbXBvcnQgeyBsZWF2ZUNvbW1lbnRUZXh0LCBsb2dnZXIgfSBmcm9tIFwiLi91dGlsc1wiO1xuaW1wb3J0IHsgUHJvZ3JhbVNjb3BlLCBSZWZlcmVuY2UsIFRlcnJhZm9ybVJlc291cmNlQmxvY2sgfSBmcm9tIFwiLi90eXBlc1wiO1xuaW1wb3J0IHsgdmFyaWFibGVOYW1lIH0gZnJvbSBcIi4vdmFyaWFibGVzXCI7XG5cbmV4cG9ydCBmdW5jdGlvbiByZWZlcmVuY2VUb1ZhcmlhYmxlTmFtZShcbiAgc2NvcGU6IFByb2dyYW1TY29wZSxcbiAgcmVmOiBSZWZlcmVuY2UsXG4pOiBzdHJpbmcge1xuICBjb25zdCBwYXJ0cyA9IHJlZi5yZWZlcmVuY2VlLmlkLnNwbGl0KFwiLlwiKTtcbiAgY29uc3QgcmVzb3VyY2UgPSBwYXJ0c1swXSA9PT0gXCJkYXRhXCIgPyBgJHtwYXJ0c1swXX0uJHtwYXJ0c1sxXX1gIDogcGFydHNbMF07XG4gIGNvbnN0IG5hbWUgPSBwYXJ0c1swXSA9PT0gXCJkYXRhXCIgPyBwYXJ0c1syXSA6IHBhcnRzWzFdO1xuICByZXR1cm4gdmFyaWFibGVOYW1lKHNjb3BlLCByZXNvdXJjZSwgbmFtZSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBjb250YWluc1JlZmVyZW5jZShleHByZXNzaW9uOiB0ZXguRXhwcmVzc2lvblR5cGUpIHtcbiAgaWYgKCF0ZXguaXNTY29wZVRyYXZlcnNhbEV4cHJlc3Npb24oZXhwcmVzc2lvbikpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICBjb25zdCBzZWdtZW50cyA9IGV4cHJlc3Npb24ubWV0YS50cmF2ZXJzYWw7XG4gIGNvbnN0IHJvb3RTZWdtZW50ID0gc2VnbWVudHNbMF0uc2VnbWVudDtcbiAgY29uc3QgZnVsbEFjY2Vzc29yID0gZXhwcmVzc2lvbi5tZXRhLmZ1bGxBY2Nlc3NvcjtcblxuICBpZiAoXG4gICAgcm9vdFNlZ21lbnQgPT09IFwiY291bnRcIiB8fCAvLyBjb3VudCB2YXJpYWJsZVxuICAgIHJvb3RTZWdtZW50ID09PSBcImVhY2hcIiB8fCAvLyBlYWNoIHZhcmlhYmxlXG4gICAgLy8gaHR0cHM6Ly93d3cudGVycmFmb3JtLmlvL2RvY3MvbGFuZ3VhZ2UvZXhwcmVzc2lvbnMvcmVmZXJlbmNlcy5odG1sI2ZpbGVzeXN0ZW0tYW5kLXdvcmtzcGFjZS1pbmZvXG4gICAgZnVsbEFjY2Vzc29yLnN0YXJ0c1dpdGgoXCJwYXRoLm1vZHVsZVwiKSB8fFxuICAgIGZ1bGxBY2Nlc3Nvci5zdGFydHNXaXRoKFwicGF0aC5yb290XCIpIHx8XG4gICAgZnVsbEFjY2Vzc29yLnN0YXJ0c1dpdGgoXCJwYXRoLmN3ZFwiKSB8fFxuICAgIGZ1bGxBY2Nlc3Nvci5zdGFydHNXaXRoKFwidGVycmFmb3JtLndvcmtzcGFjZVwiKSB8fFxuICAgIGZ1bGxBY2Nlc3Nvci5zdGFydHNXaXRoKFwic2VsZi5cIikgLy8gYmxvY2sgbG9jYWwgdmFsdWVcbiAgKSB7XG4gICAgbG9nZ2VyLmRlYnVnKGBza2lwcGluZyAke2Z1bGxBY2Nlc3Nvcn1gKTtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICByZXR1cm4gdHJ1ZTtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGV4dHJhY3RSZWZlcmVuY2VzRnJvbUV4cHJlc3Npb24oXG4gIGlucHV0OiBzdHJpbmcsXG4gIG5vZGVJZHM6IHJlYWRvbmx5IHN0cmluZ1tdLFxuICBzY29wZWRJZHM6IHJlYWRvbmx5IHN0cmluZ1tdID0gW10sIC8vIGR5bmFtaWNzIGludHJvZHVjZSBuZXcgc2NvcGVkIHZhcmlhYmxlcyB0aGF0IGFyZSBub3QgdGhlIGdsb2JhbGx5IGFjY2Vzc2libGUgaWRzXG4pOiBQcm9taXNlPFJlZmVyZW5jZVtdPiB7XG4gIGxvZ2dlci5kZWJ1ZyhgZXh0cmFjdFJlZmVyZW5jZXNGcm9tRXhwcmVzc2lvbigke2lucHV0fSlgKTtcbiAgY29uc3QgcG9zc2libGVWYXJpYWJsZVNwb3RzID0gYXdhaXQgZ2V0UmVmZXJlbmNlc0luRXhwcmVzc2lvbihcbiAgICBcIm1haW4udGZcIixcbiAgICBpbnB1dCxcbiAgKTtcblxuICBsb2dnZXIuZGVidWcoXG4gICAgYGZvdW5kIHBvc3NpYmxlIHZhcmlhYmxlIHNwb3RzOiAke0pTT04uc3RyaW5naWZ5KHBvc3NpYmxlVmFyaWFibGVTcG90cyl9YCxcbiAgKTtcblxuICByZXR1cm4gcG9zc2libGVWYXJpYWJsZVNwb3RzLnJlZHVjZSgoY2FycnksIHNwb3QpID0+IHtcbiAgICBjb25zdCB7IHZhbHVlLCBzdGFydFBvc2l0aW9uLCBlbmRQb3NpdGlvbiB9ID0gc3BvdDtcbiAgICAvLyBubyByZWZlcmVuY2VcbiAgICBpZiAoXG4gICAgICAhdmFsdWUuaW5jbHVkZXMoXCIuXCIpIHx8IC8vIGp1c3QgYSBsaXRlcmFsXG4gICAgICB2YWx1ZS5zdGFydHNXaXRoKFwiLlwiKSB8fCAvLyBkYW5nbGluZyBwcm9wZXJ0eSBhY2Nlc3NcbiAgICAgIHZhbHVlLmVuZHNXaXRoKFwiLi4uXCIpIHx8IC8vIHNwcmVhZCAobGlrZWx5IGluIGZvciBsb29wKVxuICAgICAgdmFsdWUuc3RhcnRzV2l0aChcImNvdW50LlwiKSB8fCAvLyBjb3VudCB2YXJpYWJsZVxuICAgICAgdmFsdWUuc3RhcnRzV2l0aChcImVhY2guXCIpIHx8IC8vIGVhY2ggdmFyaWFibGVcbiAgICAgIC8vIGh0dHBzOi8vd3d3LnRlcnJhZm9ybS5pby9kb2NzL2xhbmd1YWdlL2V4cHJlc3Npb25zL3JlZmVyZW5jZXMuaHRtbCNmaWxlc3lzdGVtLWFuZC13b3Jrc3BhY2UtaW5mb1xuICAgICAgdmFsdWUuc3RhcnRzV2l0aChcInBhdGgubW9kdWxlXCIpIHx8XG4gICAgICB2YWx1ZS5zdGFydHNXaXRoKFwicGF0aC5yb290XCIpIHx8XG4gICAgICB2YWx1ZS5zdGFydHNXaXRoKFwicGF0aC5jd2RcIikgfHxcbiAgICAgIHZhbHVlLnN0YXJ0c1dpdGgoXCJ0ZXJyYWZvcm0ud29ya3NwYWNlXCIpIHx8XG4gICAgICB2YWx1ZS5zdGFydHNXaXRoKFwic2VsZi5cIikgLy8gYmxvY2sgbG9jYWwgdmFsdWVcbiAgICApIHtcbiAgICAgIGxvZ2dlci5kZWJ1Zyhgc2tpcHBpbmcgJHt2YWx1ZX1gKTtcbiAgICAgIHJldHVybiBjYXJyeTtcbiAgICB9XG5cbiAgICBjb25zdCByZWZlcmVuY2VQYXJ0cyA9IHZhbHVlLnNwbGl0KFwiLlwiKTtcblxuICAgIGxvZ2dlci5kZWJ1ZyhcbiAgICAgIGBTZWFyY2hpbmcgZm9yIG5vZGUgaWQgJyR7dmFsdWV9JyBpbiAke0pTT04uc3RyaW5naWZ5KG5vZGVJZHMpfWAsXG4gICAgKTtcbiAgICBjb25zdCBjb3Jlc3BvbmRpbmdOb2RlSWQgPSBbLi4ubm9kZUlkcywgLi4uc2NvcGVkSWRzXS5maW5kKChpZCkgPT4ge1xuICAgICAgY29uc3QgcGFydHMgPSBpZC5zcGxpdChcIi5cIik7XG4gICAgICBjb25zdCBtYXRjaGVzRmlyc3QgPSBwYXJ0c1swXSA9PT0gcmVmZXJlbmNlUGFydHNbMF07XG4gICAgICBjb25zdCBtYXRjaGVzRmlyc3RUd28gPVxuICAgICAgICBtYXRjaGVzRmlyc3QgJiZcbiAgICAgICAgKHBhcnRzWzFdID09PSByZWZlcmVuY2VQYXJ0c1sxXSB8fCByZWZlcmVuY2VQYXJ0cy5sZW5ndGggPT09IDEpO1xuXG4gICAgICByZXR1cm4gKFxuICAgICAgICBtYXRjaGVzRmlyc3RUd28gJiZcbiAgICAgICAgKHBhcnRzWzBdID09PSBcImRhdGFcIiA/IHBhcnRzWzJdID09PSByZWZlcmVuY2VQYXJ0c1syXSA6IHRydWUpXG4gICAgICApO1xuICAgIH0pO1xuXG4gICAgaWYgKCFjb3Jlc3BvbmRpbmdOb2RlSWQpIHtcbiAgICAgIC8vIFRoaXMgaXMgbW9zdCBsaWtlbHkgYSBmYWxzZSBwb3NpdGl2ZSwgc28gd2UganVzdCBpZ25vcmUgaXRcbiAgICAgIC8vIFdlIGluY2x1ZGUgdGhlIGxvZyBiZWxvdyB0byBoZWxwIGRlYnVnZ2luZ1xuICAgICAgbG9nZ2VyLmVycm9yKFxuICAgICAgICBgRm91bmQgYSByZWZlcmVuY2UgdGhhdCBpcyB1bmtub3duOiAke2lucHV0fSBoYXMgcmVmZXJlbmNlIFwiJHt2YWx1ZX1cIi5UaGUgaWQgd2FzIG5vdCBmb3VuZCBpbiAke0pTT04uc3RyaW5naWZ5KFxuICAgICAgICAgIG5vZGVJZHMsXG4gICAgICAgICl9IHdpdGggdGVtcG9yYXJ5IHZhbHVlcyAke0pTT04uc3RyaW5naWZ5KHNjb3BlZElkcyl9LlxuJHtsZWF2ZUNvbW1lbnRUZXh0fWAsXG4gICAgICApO1xuICAgICAgcmV0dXJuIGNhcnJ5O1xuICAgIH1cblxuICAgIGlmIChzY29wZWRJZHMuaW5jbHVkZXMoY29yZXNwb25kaW5nTm9kZUlkKSkge1xuICAgICAgbG9nZ2VyLmRlYnVnKGBza2lwcGluZyAnJHt2YWx1ZX0nIHNpbmNlIGl0J3MgYSBzY29wZWQgdmFyaWFibGVgKTtcbiAgICAgIHJldHVybiBjYXJyeTtcbiAgICB9XG4gICAgbG9nZ2VyLmRlYnVnKGBGb3VuZCBub2RlIGlkICcke2NvcmVzcG9uZGluZ05vZGVJZH0nYCk7XG5cbiAgICBjb25zdCBzcG90UGFydHMgPSB2YWx1ZS5zcGxpdChcIi5cIik7XG4gICAgbGV0IGlzVGhlcmVBTnVtZXJpY0FjY2Vzc29yID0gZmFsc2U7XG4gICAgY29uc3QgcmVmZXJlbmNlU3BvdFBhcnRzID0gc3BvdFBhcnRzLmZpbHRlcigocGFydCkgPT4ge1xuICAgICAgaWYgKCFOdW1iZXIuaXNOYU4ocGFyc2VJbnQocGFydCwgMTApKSkge1xuICAgICAgICBpc1RoZXJlQU51bWVyaWNBY2Nlc3NvciA9IHRydWU7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuICFpc1RoZXJlQU51bWVyaWNBY2Nlc3NvcjtcbiAgICB9KTtcbiAgICBjb25zdCBmdWxsUmVmZXJlbmNlID0gaXNUaGVyZUFOdW1lcmljQWNjZXNzb3JcbiAgICAgID8gcmVmZXJlbmNlU3BvdFBhcnRzLnNsaWNlKDAsIDIpLmpvaW4oXCIuXCIpXG4gICAgICA6IHZhbHVlO1xuXG4gICAgY29uc3QgaXNWYXJpYWJsZSA9IHZhbHVlLnN0YXJ0c1dpdGgoXCJ2YXIuXCIpO1xuICAgIGNvbnN0IHVzZUZxbiA9XG4gICAgICAvLyBDYW4gbm90IHVzZSBGUU4gb24gdmFyc1xuICAgICAgIWlzVmFyaWFibGUgJiZcbiAgICAgIC8vIENhbiBub3QgdXNlIEZRTiBvbiBsb2NhbHNcbiAgICAgICF2YWx1ZS5zdGFydHNXaXRoKFwibG9jYWwuXCIpICYmXG4gICAgICAvLyBJZiB0aGUgZm9sbG93aW5nIGNoYXJhY3RlciBpc1xuICAgICAgKGlucHV0LnN1YnN0cihlbmRQb3NpdGlvbiArIDEsIDEpID09PSBcIipcIiB8fCAvLyBhICogKHNwbGF0KSB3ZSBuZWVkIHRvIHVzZSB0aGUgRlFOXG4gICAgICAgIGlucHV0LnN1YnN0cihlbmRQb3NpdGlvbiwgMSkgPT09IFwiW1wiIHx8IC8vIGEgcHJvcGVydHkgYWNjZXNzXG4gICAgICAgIGlzVGhlcmVBTnVtZXJpY0FjY2Vzc29yKTsgLy8gYSBudW1lcmljIGFjY2Vzc1xuXG4gICAgY29uc3QgcmVmOiBSZWZlcmVuY2UgPSB7XG4gICAgICBzdGFydDogc3RhcnRQb3NpdGlvbixcbiAgICAgIGVuZDogZW5kUG9zaXRpb24sXG4gICAgICByZWZlcmVuY2VlOiB7XG4gICAgICAgIGlkOiBjb3Jlc3BvbmRpbmdOb2RlSWQsXG4gICAgICAgIGZ1bGw6IGZ1bGxSZWZlcmVuY2UsXG4gICAgICB9LFxuICAgICAgdXNlRnFuLFxuICAgICAgaXNWYXJpYWJsZSxcbiAgICB9O1xuICAgIGxvZ2dlci5kZWJ1ZyhgRm91bmQgcmVmZXJlbmNlICR7SlNPTi5zdHJpbmdpZnkocmVmKX1gKTtcbiAgICByZXR1cm4gWy4uLmNhcnJ5LCByZWZdO1xuICB9LCBbXSBhcyBSZWZlcmVuY2VbXSk7XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBmaW5kVXNlZFJlZmVyZW5jZXMoXG4gIG5vZGVJZHM6IHN0cmluZ1tdLFxuICBpdGVtOiBUZXJyYWZvcm1SZXNvdXJjZUJsb2NrLFxuKTogUHJvbWlzZTxSZWZlcmVuY2VbXT4ge1xuICBsb2dnZXIuZGVidWcoYGZpbmRVc2VkUmVmZXJlbmNlcygke25vZGVJZHN9LCAke2l0ZW19KWApO1xuICBpZiAodHlwZW9mIGl0ZW0gPT09IFwic3RyaW5nXCIpIHtcbiAgICByZXR1cm4gYXdhaXQgZXh0cmFjdFJlZmVyZW5jZXNGcm9tRXhwcmVzc2lvbihpdGVtLCBub2RlSWRzLCBbXSk7XG4gIH1cblxuICBpZiAodHlwZW9mIGl0ZW0gIT09IFwib2JqZWN0XCIgfHwgaXRlbSA9PT0gbnVsbCB8fCBpdGVtID09PSB1bmRlZmluZWQpIHtcbiAgICByZXR1cm4gW107XG4gIH1cblxuICBpZiAoQXJyYXkuaXNBcnJheShpdGVtKSkge1xuICAgIHJldHVybiAoXG4gICAgICBhd2FpdCBQcm9taXNlLmFsbChpdGVtLm1hcCgoaSkgPT4gZmluZFVzZWRSZWZlcmVuY2VzKG5vZGVJZHMsIGkpKSlcbiAgICApLmZsYXQoKTtcbiAgfVxuXG4gIGlmIChpdGVtICYmIFwiZHluYW1pY1wiIGluIGl0ZW0pIHtcbiAgICBjb25zdCBkeW4gPSAoaXRlbSBhcyBhbnkpW1wiZHluYW1pY1wiXTtcbiAgICBjb25zdCB7IGZvcl9lYWNoLCAuLi5vdGhlcnMgfSA9IGR5bjtcbiAgICBjb25zdCBkeW5hbWljUmVmID0gT2JqZWN0LmtleXMob3RoZXJzKVswXTtcbiAgICByZXR1cm4gYXdhaXQgZmluZFVzZWRSZWZlcmVuY2VzKFsuLi5ub2RlSWRzLCBkeW5hbWljUmVmXSwgZHluKTtcbiAgfVxuXG4gIHJldHVybiAoXG4gICAgYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICBPYmplY3QudmFsdWVzKGl0ZW0gYXMgUmVjb3JkPHN0cmluZywgYW55PikubWFwKChpKSA9PlxuICAgICAgICBmaW5kVXNlZFJlZmVyZW5jZXMobm9kZUlkcywgaSksXG4gICAgICApLFxuICAgIClcbiAgKS5mbGF0KCk7XG59XG4iXX0=