UNPKG

@grnsft/if-core

Version:

If core utilities.

298 lines 42.5 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.validateArithmeticExpression = exports.evaluateSimpleArithmeticExpression = exports.isValidArithmeticExpression = exports.evaluateConfig = exports.evaluateInput = exports.evaluateArithmeticOutput = exports.getParameterFromArithmeticExpression = void 0; const errors_1 = require("./errors"); const { InputValidationError, WrongArithmeticExpressionError, ZeroDivisionArithmeticOperationError, } = errors_1.ERRORS; /** * Parses an arithmetic parameter string by identifying and extracting * operands and variables from the input string. This function handles * arithmetic symbols, numeric values, and string literals, and returns * a list of trimmed and sanitized operands for further processing. */ const parseArithmeticParameter = (arithmeticParameter) => { const stringWithArithmeticSymbols = /(\s*[\+\-\*/&]\s*)|(\b\d+\b)|("[^"]+"|'[^']+')|(\b\w[\w-]*\b)/; const operands = arithmeticParameter .replace('=', '') .trim() .split(stringWithArithmeticSymbols) .filter(Boolean) .map(s => s.trim().replace(/^['"](.*)['"]$/, '$1')); return [...operands]; }; /** * Extracts a parameter from an arithmetic expression. */ const getParameterFromArithmeticExpression = (arithmeticParameter) => { const regex = /["']?([a-zA-Z]+(?:[-_/][a-zA-Z]+)*)["']?/; const regexForNumbers = /^=?[0-9+\-*/\s]+$/; const match = regex.exec(arithmeticParameter) || regexForNumbers.exec(arithmeticParameter); if (regexForNumbers.exec(arithmeticParameter)) { const evaluatedValue = eval(arithmeticParameter.toString().replace('=', '')); if (!isNaN(evaluatedValue) && isFinite(evaluatedValue)) { return evaluatedValue; } } if (typeof arithmeticParameter === 'string' && match !== null) { return match[1]; } return arithmeticParameter; }; exports.getParameterFromArithmeticExpression = getParameterFromArithmeticExpression; /** * Evaluates an arithmetic expression provided as a string and returns the result. * The function first checks if the `outputParameter` contains an assignment ('=') and extracts the parameter * from the expression. If found, the expression is transformed by replacing the assignment and the parameter * with the `calculatedResult`, and then evaluated using `eval`. The result is returned as an object. * If no assignment is found, the function returns the original `outputParameter` with the `calculatedResult`. */ const evaluateArithmeticOutput = (outputParameter, output) => { const checkedOutputParameter = (0, exports.getParameterFromArithmeticExpression)(outputParameter); const isValidExpression = (0, exports.isValidArithmeticExpression)(outputParameter); const valueFromOutput = output[outputParameter]; if (typeof outputParameter === 'string' && outputParameter.includes('=') && checkedOutputParameter && isValidExpression) { const transformedOutputParameter = outputParameter .replace('=', '') .replace(`${checkedOutputParameter}`, valueFromOutput.toString()) .replace(/['"]/g, ''); const result = evaluateExpression(transformedOutputParameter); delete output[outputParameter]; return { ...output, [checkedOutputParameter]: result, }; } else if (outputParameter !== checkedOutputParameter) { throw new WrongArithmeticExpressionError(`The output parameter \`${outputParameter}\` contains an invalid arithmetic expression. It should start with \`=\` and include the symbols \`*\`, \`+\`, \`-\` and \`/\`.`); } return output; }; exports.evaluateArithmeticOutput = evaluateArithmeticOutput; /** * Evaluates and updates the input by replacing its properties * with the results of arithmetic expressions. */ const evaluateInput = (input) => { const evaluatedInput = Object.assign({}, input); Object.entries(input).forEach(([parameter, value]) => { evaluatedInput[parameter] = evaluateArithmeticExpression(value, parameter, [], evaluatedInput); }); return evaluatedInput; }; exports.evaluateInput = evaluateInput; /** * Evaluates and updates the config by replacing its properties * with the results of arithmetic expressions. */ const evaluateConfig = (options) => { const { config, input, parametersToEvaluate } = options; const evaluatedConfig = Object.assign({}, config); Object.keys(evaluatedConfig).forEach(parameter => { if (parametersToEvaluate.includes(parameter)) { (0, exports.validateArithmeticExpression)(parameter, evaluatedConfig[parameter]); evaluatedConfig[parameter] = evaluateArithmeticExpression(evaluatedConfig[parameter], parameter, parametersToEvaluate, input); } }); return evaluatedConfig; }; exports.evaluateConfig = evaluateConfig; /** * Checks if the provided parameter is a valid arithmetic expression. * The function uses a regular expression to validate arithmetic expressions * that consist of numbers, alphanumeric strings, or quoted strings, * separated by arithmetic operators (+, -, *, /). The expression can contain * whitespace and support basic arithmetic operations. */ const isValidArithmeticExpression = (parameter) => { const arithmeticExpression = /^\s*(\d+(\.\d+)?|["']?[a-zA-Z0-9-_]+["']?)(\s*[-+*/]\s*(\d+(\.\d+)?|["']?[a-zA-Z0-9-_]+["']?))*\s*$/; const checkedParameter = (0, exports.getParameterFromArithmeticExpression)(parameter); return !!(parameter !== checkedParameter && parameter.replace('=', '').match(arithmeticExpression)); }; exports.isValidArithmeticExpression = isValidArithmeticExpression; /** * Evaluates an arithmetic expression by validating it first, * then either returning the original expression or evaluating its value. * * The function performs the following: * 1. Checks if the paramenter is `timestamp`, returns the value. * 2. Checks if the expression is valid based on the provided parameters. * 3. If valid, it returns the original expression. * 4. If the expression is a basic arithmetic operation, it evaluates the expression. * 5. If not, it proceeds to evaluate more complex expressions. */ const evaluateArithmeticExpression = (expression, parameter, parametersToEvaluate, input) => { if (parameter === 'timestamp') { return input[parameter]; } if (isNotArithmeticExpression(expression)) { return expression; } const strippedEqualExpression = expression.replace('=', ''); if (isBasicArithmetic(strippedEqualExpression)) { return evaluateExpression(strippedEqualExpression); } return evaluateComplexExpression(expression, parameter, parametersToEvaluate, input); }; /** * Checks if the given expression is not an arithmetic expression. */ const isNotArithmeticExpression = (expression) => typeof expression !== 'string' || (!expression.includes('=') && !containsOnlyNumbersAndOperators(expression)); /** * Utility function to check if a string contains only numbers and basic math operators. */ const containsOnlyNumbersAndOperators = (expression) => { const numberAndMathSymbolsRegex = /^\s*\d+(\.\d+)?(\s*[-+*/]\s*\d+(\.\d+)?)*\s*$/; return numberAndMathSymbolsRegex.test(expression); }; /** * Checks if the provided expression is a basic arithmetic expression. */ const isBasicArithmetic = (expression) => typeof expression === 'string' && containsOnlyNumbersAndOperators(expression); /** * Evaluates a complex arithmetic expression by parsing it into operands, * validating whether each operand is a number or an operator, and evaluating * any parameters within the expression. The resulting valid operands are * joined together and evaluated using `eval`. */ const evaluateComplexExpression = (expression, parameterValue, parametersToEvaluate, input) => { const operands = parseArithmeticParameter(expression); const params = []; operands.forEach(operand => { // Check if the operand is a number if (operand && !isNaN(Number(operand))) { params.push(operand); } else if (isOperandOperator(operand, expression)) { params.push(operand); } else { const evaluatedOperand = evaluateOperand({ parameter: operand, expression, parameterValue, parametersToEvaluate, input, }); params.push(evaluatedOperand); } }); return evaluateExpression(params.join('')); }; /** * Checks if a given operand is a valid arithmetic operator within an expression. * Throws an error if the operand is not one of the allowed arithmetic operators: *, +, -, or /. */ const isOperandOperator = (operand, expression) => { if (operand.length === 1 && !/[\+\-\*/]/.test(operand)) { throw new WrongArithmeticExpressionError(`The operator in \`${expression}\` should be one of these arithmetic operators: *, +, - or /.`); } else if (operand.length === 1) { return true; } return false; }; /** * Evaluates the value of a given parameter from the input. * If the parameter's value is an arithmetic expression, it evaluates the expression. * Otherwise, it returns the parameter's value directly. */ const evaluateOperand = (operandOptions) => { const { parameter, expression, parametersToEvaluate, input } = operandOptions; if (!(parameter in input)) { throw new InputValidationError(`${parameter} is missing from the input array or has nullish value.`); } // Checks if the parameter in the input array has number value. if (isNaN(Number(input[parameter]))) { throw new InputValidationError(`The value of the \`${parameter}\` parameter in the input array is not a number.`); } const isExpression = (0, exports.isValidArithmeticExpression)(expression); if (isExpression) { return evaluateArithmeticExpression(input[parameter], parameter, [...parametersToEvaluate, parameter], input); } return input[parameter]; }; /** * Evaluates a simple arithmetic expression if the input is a valid expression. * It checks if the input string follows a pattern for simple arithmetic * operations (numbers with operators like *, /, +, -) between them. */ const evaluateSimpleArithmeticExpression = (parameter) => { const simpleExpressionRegex = /^\d+(\.\d+)?([+\-*/]\d+(\.\d+)?)*$/; return typeof parameter === 'string' && parameter.replace('=', '').match(simpleExpressionRegex) ? evaluateExpression(parameter.replace('=', '')) : parameter; }; exports.evaluateSimpleArithmeticExpression = evaluateSimpleArithmeticExpression; /** * Validates whether a given value is a valid arithmetic expression. * * If the value is a string, it first removes any equal signs and checks if it * is a valid arithmetic expression using the `isValidArithmeticExpression` helper. * If valid, it attempts to evaluate the expression and ensures the result is numeric. * In case of an invalid format, it calls `validateExpressionFormat`. * The function returns true if the value is valid or numeric. */ const validateArithmeticExpression = (parameterName, value, type) => { if (typeof value === 'string') { const sanitizedValue = value.replace('=', ''); if ((0, exports.isValidArithmeticExpression)(sanitizedValue)) { const evaluatedParam = evaluateExpression(sanitizedValue) || value; if (!isNaN(Number(evaluatedParam))) { return evaluatedParam; } } validateExpressionFormat(parameterName, value); if (type === 'number') { const numberMatch = sanitizedValue.match(/[-+]?[0-9]*\.?[0-9]+/g); return numberMatch ? parseFloat(numberMatch[0]) : value; } } return value; }; exports.validateArithmeticExpression = validateArithmeticExpression; /** * Helper function to evaluate the arithmetic expression. */ const evaluateExpression = (expression) => { try { const evaluatedValue = eval(expression); if (evaluatedValue === Infinity) { throw new ZeroDivisionArithmeticOperationError(`The input expression contains a division by zero: \`${expression}\`.`); } if (isNaN(evaluatedValue)) { return undefined; } return evaluatedValue; } catch (error) { if (error instanceof ZeroDivisionArithmeticOperationError) { throw error; } return undefined; } }; /** * Validates whether the provided string value is a valid arithmetic expression based on its format. * * Checks if the expression contains an `=` sign and ensures that * the part of the string following the equal sign is a valid arithmetic expression. * * - If the string starts with `=`, the remaining part should be a valid arithmetic expression. * - If it doesn't start with `=`, the entire string should not resemble a valid arithmetic expression. * * Throws an `InputValidationError` error if the format or content of the arithmetic expression is invalid. */ const validateExpressionFormat = (parameterName, value) => { const hasEqualSign = value.includes('='); const isValid = (0, exports.isValidArithmeticExpression)(value.replace('=', '')); if ((hasEqualSign && !isValid) || (!hasEqualSign && isValid)) { throw new InputValidationError(`The \`${parameterName}\` contains an invalid arithmetic expression. It should start with \`=\` and include the symbols \`*\`, \`+\`, \`-\` and \`/\`.`); } }; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXJpdGhtZXRpYy1oZWxwZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvdXRpbHMvYXJpdGhtZXRpYy1oZWxwZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBRUEscUNBQWdDO0FBRWhDLE1BQU0sRUFDSixvQkFBb0IsRUFDcEIsOEJBQThCLEVBQzlCLG9DQUFvQyxHQUNyQyxHQUFHLGVBQU0sQ0FBQztBQUVYOzs7OztHQUtHO0FBQ0gsTUFBTSx3QkFBd0IsR0FBRyxDQUFDLG1CQUEyQixFQUFFLEVBQUU7SUFDL0QsTUFBTSwyQkFBMkIsR0FDL0IsK0RBQStELENBQUM7SUFFbEUsTUFBTSxRQUFRLEdBQUcsbUJBQW1CO1NBQ2pDLE9BQU8sQ0FBQyxHQUFHLEVBQUUsRUFBRSxDQUFDO1NBQ2hCLElBQUksRUFBRTtTQUNOLEtBQUssQ0FBQywyQkFBMkIsQ0FBQztTQUNsQyxNQUFNLENBQUMsT0FBTyxDQUFDO1NBQ2YsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLElBQUksRUFBRSxDQUFDLE9BQU8sQ0FBQyxnQkFBZ0IsRUFBRSxJQUFJLENBQUMsQ0FBQyxDQUFDO0lBRXRELE9BQU8sQ0FBQyxHQUFHLFFBQVEsQ0FBQyxDQUFDO0FBQ3ZCLENBQUMsQ0FBQztBQUVGOztHQUVHO0FBQ0ksTUFBTSxvQ0FBb0MsR0FBRyxDQUNsRCxtQkFBMkIsRUFDM0IsRUFBRTtJQUNGLE1BQU0sS0FBSyxHQUFHLDBDQUEwQyxDQUFDO0lBQ3pELE1BQU0sZUFBZSxHQUFHLG1CQUFtQixDQUFDO0lBRTVDLE1BQU0sS0FBSyxHQUNULEtBQUssQ0FBQyxJQUFJLENBQUMsbUJBQW1CLENBQUM7UUFDL0IsZUFBZSxDQUFDLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxDQUFDO0lBRTVDLElBQUksZUFBZSxDQUFDLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxFQUFFLENBQUM7UUFDOUMsTUFBTSxjQUFjLEdBQUcsSUFBSSxDQUN6Qixt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b0NBQW9DLENBQzVDLHVEQUF1RCxVQUFVLEtBQUssQ0FDdkUsQ0FBQztRQUNKLENBQUM7UUFDRCxJQUFJLEtBQUssQ0FBQyxjQUFjLENBQUMsRUFBRSxDQUFDO1lBQzFCLE9BQU8sU0FBUyxDQUFDO1FBQ25CLENBQUM7UUFFRCxPQUFPLGNBQWMsQ0FBQztJQUN4QixDQUFDO0lBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztRQUNmLElBQUksS0FBSyxZQUFZLG9DQUFvQyxFQUFFLENBQUM7WUFDMUQsTUFBTSxLQUFLLENBQUM7UUFDZCxDQUFDO1FBRUQsT0FBTyxTQUFTLENBQUM7SUFDbkIsQ0FBQztBQUNILENBQUMsQ0FBQztBQUVGOzs7Ozs7Ozs7O0dBVUc7QUFDSCxNQUFNLHdCQUF3QixHQUFHLENBQUMsYUFBcUIsRUFBRSxLQUFhLEVBQUUsRUFBRTtJQUN4RSxNQUFNLFlBQVksR0FBRyxLQUFLLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQ3pDLE1BQU0sT0FBTyxHQUFHLElBQUEsbUNBQTJCLEVBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxHQUFHLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUVwRSxJQUFJLENBQUMsWUFBWSxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDLFlBQVksSUFBSSxPQUFPLENBQUMsRUFBRSxDQUFDO1FBQzdELE1BQU0sSUFBSSxvQkFBb0IsQ0FDNUIsU0FBUyxhQUFhLGlJQUFpSSxDQUN4SixDQUFDO0lBQ0osQ0FBQztBQUNILENBQUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7UGx1Z2luUGFyYW1zLCBBcml0aG1ldGljUGFyYW1ldGVyc30gZnJvbSAnLi4vdHlwZXMnO1xuXG5pbXBvcnQge0VSUk9SU30gZnJvbSAnLi9lcnJvcnMnO1xuXG5jb25zdCB7XG4gIElucHV0VmFsaWRhdGlvbkVycm9yLFxuICBXcm9uZ0FyaXRobWV0aWNFeHByZXNzaW9uRXJyb3IsXG4gIFplcm9EaXZpc2lvbkFyaXRobWV0aWNPcGVyYXRpb25FcnJvcixcbn0gPSBFUlJPUlM7XG5cbi8qKlxuICogUGFyc2VzIGFuIGFyaXRobWV0aWMgcGFyYW1ldGVyIHN0cmluZyBieSBpZGVudGlmeWluZyBhbmQgZXh0cmFjdGluZ1xuICogb3BlcmFuZHMgYW5kIHZhcmlhYmxlcyBmcm9tIHRoZSBpbnB1dCBzdHJpbmcuIFRoaXMgZnVuY3Rpb24gaGFuZGxlc1xuICogYXJpdGhtZXRpYyBzeW1ib2xzLCBudW1lcmljIHZhbHVlcywgYW5kIHN0cmluZyBsaXRlcmFscywgYW5kIHJldHVybnNcbiAqIGEgbGlzdCBvZiB0cmltbWVkIGFuZCBzYW5pdGl6ZWQgb3BlcmFuZHMgZm9yIGZ1cnRoZXIgcHJvY2Vzc2luZy5cbiAqL1xuY29uc3QgcGFyc2VBcml0aG1ldGljUGFyYW1ldGVyID0gKGFyaXRobWV0aWNQYXJhbWV0ZXI6IHN0cmluZykgPT4ge1xuICBjb25zdCBzdHJpbmdXaXRoQXJpdGhtZXRpY1N5bWJvbHMgPVxuICAgIC8oXFxzKltcXCtcXC1cXCovJl1cXHMqKXwoXFxiXFxkK1xcYil8KFwiW15cIl0rXCJ8J1teJ10rJyl8KFxcYlxcd1tcXHctXSpcXGIpLztcblxuICBjb25zdCBvcGVyYW5kcyA9IGFyaXRobWV0aWNQYXJhbWV0ZXJcbiAgICAucmVwbGFjZSgnPScsICcnKVxuICAgIC50cmltKClcbiAgICAuc3BsaXQoc3RyaW5nV2l0aEFyaXRobWV0aWNTeW1ib2xzKVxuICAgIC5maWx0ZXIoQm9vbGVhbilcbiAgICAubWFwKHMgPT4gcy50cmltKCkucmVwbGFjZSgvXlsnXCJdKC4qKVsnXCJdJC8sICckMScpKTtcblxuICByZXR1cm4gWy4uLm9wZXJhbmRzXTtcbn07XG5cbi8qKlxuICogRXh0cmFjdHMgYSBwYXJhbWV0ZXIgZnJvbSBhbiBhcml0aG1ldGljIGV4cHJlc3Npb24uXG4gKi9cbmV4cG9ydCBjb25zdCBnZXRQYXJhbWV0ZXJGcm9tQXJpdGhtZXRpY0V4cHJlc3Npb24gPSAoXG4gIGFyaXRobWV0aWNQYXJhbWV0ZXI6IHN0cmluZ1xuKSA9PiB7XG4gIGNvbnN0IHJlZ2V4ID0gL1tcIiddPyhbYS16QS1aXSsoPzpbLV8vXVthLXpBLVpdKykqKVtcIiddPy87XG4gIGNvbnN0IHJlZ2V4Rm9yTnVtYmVycyA9IC9ePT9bMC05K1xcLSovXFxzXSskLztcblxuICBjb25zdCBtYXRjaCA9XG4gICAgcmVnZXguZXhlYyhhcml0aG1ldGljUGFyYW1ldGVyKSB8fFxuICAgIHJlZ2V4Rm9yTnVtYmVycy5leGVjKGFyaXRobWV0aWNQYXJhbWV0ZXIpO1xuXG4gIGlmIChyZWdleEZvck51bWJlcnMuZXhlYyhhcml0aG1ldGljUGFyYW1ldGVyKSkge1xuICAgIGNvbnN0IGV2YWx1YXRlZFZhbHVlID0gZXZhbChcbiAgICAgIGFyaXRobWV0aWNQYXJhbWV0ZXIudG9TdHJpbmcoKS5yZXBsYWNlKCc9JywgJycpXG4gICAgKTtcblxuICAgIGlmICghaXNOYU4oZXZhbHVhdGVkVmFsdWUpICYmIGlzRmluaXRlKGV2YWx1YXRlZFZhbHVlKSkge1xuICAgICAgcmV0dXJuIGV2YWx1YXRlZFZhbHVlO1xuICAgIH1cbiAgfVxuXG4gIGlmICh0eXBlb2YgYXJpdGhtZXRpY1BhcmFtZXRlciA9PT0gJ3N0cmluZycgJiYgbWF0Y2ggIT09IG51bGwpIHtcbiAgICByZXR1cm4gbWF0Y2hbMV07XG4gIH1cblxuICByZXR1cm4gYXJpdGhtZXRpY1BhcmFtZXRlcjtcbn07XG5cbi8qKlxuICogRXZhbHVhdGVzIGFuIGFyaXRobWV0aWMgZXhwcmVzc2lvbiBwcm92aWRlZCBhcyBhIHN0cmluZyBhbmQgcmV0dXJucyB0aGUgcmVzdWx0LlxuICogVGhlIGZ1bmN0aW9uIGZpcnN0IGNoZWNrcyBpZiB0aGUgYG91dHB1dFBhcmFtZXRlcmAgY29udGFpbnMgYW4gYXNzaWdubWVudCAoJz0nKSBhbmQgZXh0cmFjdHMgdGhlIHBhcmFtZXRlclxuICogZnJvbSB0aGUgZXhwcmVzc2lvbi4gSWYgZm91bmQsIHRoZSBleHByZXNzaW9uIGlzIHRyYW5zZm9ybWVkIGJ5IHJlcGxhY2luZyB0aGUgYXNzaWdubWVudCBhbmQgdGhlIHBhcmFtZXRlclxuICogd2l0aCB0aGUgYGNhbGN1bGF0ZWRSZXN1bHRgLCBhbmQgdGhlbiBldmFsdWF0ZWQgdXNpbmcgYGV2YWxgLiBUaGUgcmVzdWx0IGlzIHJldHVybmVkIGFzIGFuIG9iamVjdC5cbiAqIElmIG5vIGFzc2lnbm1lbnQgaXMgZm91bmQsIHRoZSBmdW5jdGlvbiByZXR1cm5zIHRoZSBvcmlnaW5hbCBgb3V0cHV0UGFyYW1ldGVyYCB3aXRoIHRoZSBgY2FsY3VsYXRlZFJlc3VsdGAuXG4gKi9cbmV4cG9ydCBjb25zdCBldmFsdWF0ZUFyaXRobWV0aWNPdXRwdXQgPSAoXG4gIG91dHB1dFBhcmFtZXRlcjogc3RyaW5nLFxuICBvdXRwdXQ6IFBsdWdpblBhcmFtc1xuKSA9PiB7XG4gIGNvbnN0IGNoZWNrZWRPdXRwdXRQYXJhbWV0ZXIgPVxuICAgIGdldFBhcmFtZXRlckZyb21Bcml0aG1ldGljRXhwcmVzc2lvbihvdXRwdXRQYXJhbWV0ZXIpO1xuICBjb25zdCBpc1ZhbGlkRXhwcmVzc2lvbiA9IGlzVmFsaWRBcml0aG1ldGljRXhwcmVzc2lvbihvdXRwdXRQYXJhbWV0ZXIpO1xuICBjb25zdCB2YWx1ZUZyb21PdXRwdXQgPSBvdXRwdXRbb3V0cHV0UGFyYW1ldGVyXTtcblxuICBpZiAoXG4gICAgdHlwZW9mIG91dHB1dFBhcmFtZXRlciA9PT0gJ3N0cmluZycgJiZcbiAgICBvdXRwdXRQYXJhbWV0ZXIuaW5jbHVkZXMoJz0nKSAmJlxuICAgIGNoZWNrZWRPdXRwdXRQYXJhbWV0ZXIgJiZcbiAgICBpc1ZhbGlkRXhwcmVzc2lvblxuICApIHtcbiAgICBjb25zdCB0cmFuc2Zvcm1lZE91dHB1dFBhcmFtZXRlciA9IG91dHB1dFBhcmFtZXRlclxuICAgICAgLnJlcGxhY2UoJz0nLCAnJylcbiAgICAgIC5yZXBsYWNlKGAke2NoZWNrZWRPdXRwdXRQYXJhbWV0ZXJ9YCwgdmFsdWVGcm9tT3V0cHV0LnRvU3RyaW5nKCkpXG4gICAgICAucmVwbGFjZSgvWydcIl0vZywgJycpO1xuXG4gICAgY29uc3QgcmVzdWx0ID0gZXZhbHVhdGVFeHByZXNzaW9uKHRyYW5zZm9ybWVkT3V0cHV0UGFyYW1ldGVyKTtcbiAgICBkZWxldGUgb3V0cHV0W291dHB1dFBhcmFtZXRlcl07XG5cbiAgICByZXR1cm4ge1xuICAgICAgLi4ub3V0cHV0LFxuICAgICAgW2NoZWNrZWRPdXRwdXRQYXJhbWV0ZXJdOiByZXN1bHQsXG4gICAgfTtcbiAgfSBlbHNlIGlmIChvdXRwdXRQYXJhbWV0ZXIgIT09IGNoZWNrZWRPdXRwdXRQYXJhbWV0ZXIpIHtcbiAgICB0aHJvdyBuZXcgV3JvbmdBcml0aG1ldGljRXhwcmVzc2lvbkVycm9yKFxuICAgICAgYFRoZSBvdXRwdXQgcGFyYW1ldGVyIFxcYCR7b3V0cHV0UGFyYW1ldGVyfVxcYCBjb250YWlucyBhbiBpbnZhbGlkIGFyaXRobWV0aWMgZXhwcmVzc2lvbi4gSXQgc2hvdWxkIHN0YXJ0IHdpdGggXFxgPVxcYCBhbmQgaW5jbHVkZSB0aGUgc3ltYm9scyBcXGAqXFxgLCBcXGArXFxgLCBcXGAtXFxgIGFuZCBcXGAvXFxgLmBcbiAgICApO1xuICB9XG5cbiAgcmV0dXJuIG91dHB1dDtcbn07XG5cbi8qKlxuICogRXZhbHVhdGVzIGFuZCB1cGRhdGVzIHRoZSBpbnB1dCBieSByZXBsYWNpbmcgaXRzIHByb3BlcnRpZXNcbiAqIHdpdGggdGhlIHJlc3VsdHMgb2YgYXJpdGhtZXRpYyBleHByZXNzaW9ucy5cbiAqL1xuZXhwb3J0IGNvbnN0IGV2YWx1YXRlSW5wdXQgPSAoaW5wdXQ6IFBsdWdpblBhcmFtcykgPT4ge1xuICBjb25zdCBldmFsdWF0ZWRJbnB1dCA9IE9iamVjdC5hc3NpZ24oe30sIGlucHV0KTtcblxuICBPYmplY3QuZW50cmllcyhpbnB1dCkuZm9yRWFjaCgoW3BhcmFtZXRlciwgdmFsdWVdKSA9PiB7XG4gICAgZXZhbHVhdGVkSW5wdXRbcGFyYW1ldGVyXSA9IGV2YWx1YXRlQXJpdGhtZXRpY0V4cHJlc3Npb24oXG4gICAgICB2YWx1ZSxcbiAgICAgIHBhcmFtZXRlcixcbiAgICAgIFtdLFxuICAgICAgZXZhbHVhdGVkSW5wdXRcbiAgICApO1xuICB9KTtcblxuICByZXR1cm4gZXZhbHVhdGVkSW5wdXQ7XG59O1xuXG4vKipcbiAqIEV2YWx1YXRlcyBhbmQgdXBkYXRlcyB0aGUgY29uZmlnIGJ5IHJlcGxhY2luZyBpdHMgcHJvcGVydGllc1xuICogd2l0aCB0aGUgcmVzdWx0cyBvZiBhcml0aG1ldGljIGV4cHJlc3Npb25zLlxuICovXG5leHBvcnQgY29uc3QgZXZhbHVhdGVDb25maWcgPSAob3B0aW9uczogQXJpdGhtZXRpY1BhcmFtZXRlcnMpID0+IHtcbiAgY29uc3Qge2NvbmZpZywgaW5wdXQsIHBhcmFtZXRlcnNUb0V2YWx1YXRlfSA9IG9wdGlvbnM7XG4gIGNvbnN0IGV2YWx1YXRlZENvbmZpZyA9IE9iamVjdC5hc3NpZ24oe30sIGNvbmZpZyk7XG5cbiAgT2JqZWN0LmtleXMoZXZhbHVhdGVkQ29uZmlnKS5mb3JFYWNoKHBhcmFtZXRlciA9PiB7XG4gICAgaWYgKHBhcmFtZXRlcnNUb0V2YWx1YXRlLmluY2x1ZGVzKHBhcmFtZXRlcikpIHtcbiAgICAgIHZhbGlkYXRlQXJpdGhtZXRpY0V4cHJlc3Npb24ocGFyYW1ldGVyLCBldmFsdWF0ZWRDb25maWdbcGFyYW1ldGVyXSk7XG5cbiAgICAgIGV2YWx1YXRlZENvbmZpZ1twYXJhbWV0ZXJdID0gZXZhbHVhdGVBcml0aG1ldGljRXhwcmVzc2lvbihcbiAgICAgICAgZXZhbHVhdGVkQ29uZmlnW3BhcmFtZXRlcl0sXG4gICAgICAgIHBhcmFtZXRlcixcbiAgICAgICAgcGFyYW1ldGVyc1RvRXZhbHVhdGUsXG4gICAgICAgIGlucHV0XG4gICAgICApO1xuICAgIH1cbiAgfSk7XG5cbiAgcmV0dXJuIGV2YWx1YXRlZENvbmZpZztcbn07XG5cbi8qKlxuICogQ2hlY2tzIGlmIHRoZSBwcm92aWRlZCBwYXJhbWV0ZXIgaXMgYSB2YWxpZCBhcml0aG1ldGljIGV4cHJlc3Npb24uXG4gKiBUaGUgZnVuY3Rpb24gdXNlcyBhIHJlZ3VsYXIgZXhwcmVzc2lvbiB0byB2YWxpZGF0ZSBhcml0aG1ldGljIGV4cHJlc3Npb25zXG4gKiB0aGF0IGNvbnNpc3Qgb2YgbnVtYmVycywgYWxwaGFudW1lcmljIHN0cmluZ3MsIG9yIHF1b3RlZCBzdHJpbmdzLFxuICogc2VwYXJhdGVkIGJ5IGFyaXRobWV0aWMgb3BlcmF0b3JzICgrLCAtLCAqLCAvKS4gVGhlIGV4cHJlc3Npb24gY2FuIGNvbnRhaW5cbiAqIHdoaXRlc3BhY2UgYW5kIHN1cHBvcnQgYmFzaWMgYXJpdGhtZXRpYyBvcGVyYXRpb25zLlxuICovXG5leHBvcnQgY29uc3QgaXNWYWxpZEFyaXRobWV0aWNFeHByZXNzaW9uID0gKHBhcmFtZXRlcjogc3RyaW5nKSA9PiB7XG4gIGNvbnN0IGFyaXRobWV0aWNFeHByZXNzaW9uID1cbiAgICAvXlxccyooXFxkKyhcXC5cXGQrKT98W1wiJ10/W2EtekEtWjAtOS1fXStbXCInXT8pKFxccypbLSsqL11cXHMqKFxcZCsoXFwuXFxkKyk/fFtcIiddP1thLXpBLVowLTktX10rW1wiJ10/KSkqXFxzKiQvO1xuICBjb25zdCBjaGVja2VkUGFyYW1ldGVyID0gZ2V0UGFyYW1ldGVyRnJvbUFyaXRobWV0aWNFeHByZXNzaW9uKHBhcmFtZXRlcik7XG5cbiAgcmV0dXJuICEhKFxuICAgIHBhcmFtZXRlciAhPT0gY2hlY2tlZFBhcmFtZXRlciAmJlxuICAgIHBhcmFtZXRlci5yZXBsYWNlKCc9JywgJycpLm1hdGNoKGFyaXRobWV0aWNFeHByZXNzaW9uKVxuICApO1xufTtcblxuLyoqXG4gKiBFdmFsdWF0ZXMgYW4gYXJpdGhtZXRpYyBleHByZXNzaW9uIGJ5IHZhbGlkYXRpbmcgaXQgZmlyc3QsXG4gKiB0aGVuIGVpdGhlciByZXR1cm5pbmcgdGhlIG9yaWdpbmFsIGV4cHJlc3Npb24gb3IgZXZhbHVhdGluZyBpdHMgdmFsdWUuXG4gKlxuICogVGhlIGZ1bmN0aW9uIHBlcmZvcm1zIHRoZSBmb2xsb3dpbmc6XG4gKiAxLiBDaGVja3MgaWYgdGhlIHBhcmFtZW50ZXIgaXMgYHRpbWVzdGFtcGAsIHJldHVybnMgdGhlIHZhbHVlLlxuICogMi4gQ2hlY2tzIGlmIHRoZSBleHByZXNzaW9uIGlzIHZhbGlkIGJhc2VkIG9uIHRoZSBwcm92aWRlZCBwYXJhbWV0ZXJzLlxuICogMy4gSWYgdmFsaWQsIGl0IHJldHVybnMgdGhlIG9yaWdpbmFsIGV4cHJlc3Npb24uXG4gKiA0LiBJZiB0aGUgZXhwcmVzc2lvbiBpcyBhIGJhc2ljIGFyaXRobWV0aWMgb3BlcmF0aW9uLCBpdCBldmFsdWF0ZXMgdGhlIGV4cHJlc3Npb24uXG4gKiA1LiBJZiBub3QsIGl0IHByb2NlZWRzIHRvIGV2YWx1YXRlIG1vcmUgY29tcGxleCBleHByZXNzaW9ucy5cbiAqL1xuY29uc3QgZXZhbHVhdGVBcml0aG1ldGljRXhwcmVzc2lvbiA9IChcbiAgZXhwcmVzc2lvbjogc3RyaW5nLFxuICBwYXJhbWV0ZXI6IHN0cmluZyxcbiAgcGFyYW1ldGVyc1RvRXZhbHVhdGU6IHN0cmluZ1tdLFxuICBpbnB1dDogUGx1Z2luUGFyYW1zXG4pID0+IHtcbiAgaWYgKHBhcmFtZXRlciA9PT0gJ3RpbWVzdGFtcCcpIHtcbiAgICByZXR1cm4gaW5wdXRbcGFyYW1ldGVyXTtcbiAgfVxuXG4gIGlmIChpc05vdEFyaXRobWV0aWNFeHByZXNzaW9uKGV4cHJlc3Npb24pKSB7XG4gICAgcmV0dXJuIGV4cHJlc3Npb247XG4gIH1cblxuICBjb25zdCBzdHJpcHBlZEVxdWFsRXhwcmVzc2lvbiA9IGV4cHJlc3Npb24ucmVwbGFjZSgnPScsICcnKTtcblxuICBpZiAoaXNCYXNpY0FyaXRobWV0aWMoc3RyaXBwZWRFcXVhbEV4cHJlc3Npb24pKSB7XG4gICAgcmV0dXJuIGV2YWx1YXRlRXhwcmVzc2lvbihzdHJpcHBlZEVxdWFsRXhwcmVzc2lvbik7XG4gIH1cblxuICByZXR1cm4gZXZhbHVhdGVDb21wbGV4RXhwcmVzc2lvbihcbiAgICBleHByZXNzaW9uLFxuICAgIHBhcmFtZXRlcixcbiAgICBwYXJhbWV0ZXJzVG9FdmFsdWF0ZSxcbiAgICBpbnB1dFxuICApO1xufTtcblxuLyoqXG4gKiBDaGVja3MgaWYgdGhlIGdpdmVuIGV4cHJlc3Npb24gaXMgbm90IGFuIGFyaXRobWV0aWMgZXhwcmVzc2lvbi5cbiAqL1xuY29uc3QgaXNOb3RBcml0aG1ldGljRXhwcmVzc2lvbiA9IChleHByZXNzaW9uOiBzdHJpbmcpID0+XG4gIHR5cGVvZiBleHByZXNzaW9uICE9PSAnc3RyaW5nJyB8fFxuICAoIWV4cHJlc3Npb24uaW5jbHVkZXMoJz0nKSAmJiAhY29udGFpbnNPbmx5TnVtYmVyc0FuZE9wZXJhdG9ycyhleHByZXNzaW9uKSk7XG5cbi8qKlxuICogVXRpbGl0eSBmdW5jdGlvbiB0byBjaGVjayBpZiBhIHN0cmluZyBjb250YWlucyBvbmx5IG51bWJlcnMgYW5kIGJhc2ljIG1hdGggb3BlcmF0b3JzLlxuICovXG5jb25zdCBjb250YWluc09ubHlOdW1iZXJzQW5kT3BlcmF0b3JzID0gKGV4cHJlc3Npb246IHN0cmluZyk6IGJvb2xlYW4gPT4ge1xuICBjb25zdCBudW1iZXJBbmRNYXRoU3ltYm9sc1JlZ2V4ID1cbiAgICAvXlxccypcXGQrKFxcLlxcZCspPyhcXHMqWy0rKi9dXFxzKlxcZCsoXFwuXFxkKyk/KSpcXHMqJC87XG5cbiAgcmV0dXJuIG51bWJlckFuZE1hdGhTeW1ib2xzUmVnZXgudGVzdChleHByZXNzaW9uKTtcbn07XG5cbi8qKlxuICogQ2hlY2tzIGlmIHRoZSBwcm92aWRlZCBleHByZXNzaW9uIGlzIGEgYmFzaWMgYXJpdGhtZXRpYyBleHByZXNzaW9uLlxuICovXG5jb25zdCBpc0Jhc2ljQXJpdGhtZXRpYyA9IChleHByZXNzaW9uOiBzdHJpbmcpOiBib29sZWFuID0+XG4gIHR5cGVvZiBleHByZXNzaW9uID09PSAnc3RyaW5nJyAmJiBjb250YWluc09ubHlOdW1iZXJzQW5kT3BlcmF0b3JzKGV4cHJlc3Npb24pO1xuXG4vKipcbiAqIEV2YWx1YXRlcyBhIGNvbXBsZXggYXJpdGhtZXRpYyBleHByZXNzaW9uIGJ5IHBhcnNpbmcgaXQgaW50byBvcGVyYW5kcyxcbiAqIHZhbGlkYXRpbmcgd2hldGhlciBlYWNoIG9wZXJhbmQgaXMgYSBudW1iZXIgb3IgYW4gb3BlcmF0b3IsIGFuZCBldmFsdWF0aW5nXG4gKiBhbnkgcGFyYW1ldGVycyB3aXRoaW4gdGhlIGV4cHJlc3Npb24uIFRoZSByZXN1bHRpbmcgdmFsaWQgb3BlcmFuZHMgYXJlXG4gKiBqb2luZWQgdG9nZXRoZXIgYW5kIGV2YWx1YXRlZCB1c2luZyBgZXZhbGAuXG4gKi9cbmNvbnN0IGV2YWx1YXRlQ29tcGxleEV4cHJlc3Npb24gPSAoXG4gIGV4cHJlc3Npb246IHN0cmluZyxcbiAgcGFyYW1ldGVyVmFsdWU6IHN0cmluZyxcbiAgcGFyYW1ldGVyc1RvRXZhbHVhdGU6IHN0cmluZ1tdLFxuICBpbnB1dDogUGx1Z2luUGFyYW1zXG4pID0+IHtcbiAgY29uc3Qgb3BlcmFuZHMgPSBwYXJzZUFyaXRobWV0aWNQYXJhbWV0ZXIoZXhwcmVzc2lvbik7XG4gIGNvbnN0IHBhcmFtczogc3RyaW5nW10gPSBbXTtcblxuICBvcGVyYW5kcy5mb3JFYWNoKG9wZXJhbmQgPT4ge1xuICAgIC8vIENoZWNrIGlmIHRoZSBvcGVyYW5kIGlzIGEgbnVtYmVyXG4gICAgaWYgKG9wZXJhbmQgJiYgIWlzTmFOKE51bWJlcihvcGVyYW5kKSkpIHtcbiAgICAgIHBhcmFtcy5wdXNoKG9wZXJhbmQpO1xuICAgIH0gZWxzZSBpZiAoaXNPcGVyYW5kT3BlcmF0b3Iob3BlcmFuZCwgZXhwcmVzc2lvbikpIHtcbiAgICAgIHBhcmFtcy5wdXNoKG9wZXJhbmQpO1xuICAgIH0gZWxzZSB7XG4gICAgICBjb25zdCBldmFsdWF0ZWRPcGVyYW5kID0gZXZhbHVhdGVPcGVyYW5kKHtcbiAgICAgICAgcGFyYW1ldGVyOiBvcGVyYW5kLFxuICAgICAgICBleHByZXNzaW9uLFxuICAgICAgICBwYXJhbWV0ZXJWYWx1ZSxcbiAgICAgICAgcGFyYW1ldGVyc1RvRXZhbHVhdGUsXG4gICAgICAgIGlucHV0LFxuICAgICAgfSk7XG5cbiAgICAgIHBhcmFtcy5wdXNoKGV2YWx1YXRlZE9wZXJhbmQpO1xuICAgIH1cbiAgfSk7XG5cbiAgcmV0dXJuIGV2YWx1YXRlRXhwcmVzc2lvbihwYXJhbXMuam9pbignJykpO1xufTtcblxuLyoqXG4gKiBDaGVja3MgaWYgYSBnaXZlbiBvcGVyYW5kIGlzIGEgdmFsaWQgYXJpdGhtZXRpYyBvcGVyYXRvciB3aXRoaW4gYW4gZXhwcmVzc2lvbi5cbiAqIFRocm93cyBhbiBlcnJvciBpZiB0aGUgb3BlcmFuZCBpcyBub3Qgb25lIG9mIHRoZSBhbGxvd2VkIGFyaXRobWV0aWMgb3BlcmF0b3JzOiAqLCArLCAtLCBvciAvLlxuICovXG5jb25zdCBpc09wZXJhbmRPcGVyYXRvciA9IChvcGVyYW5kOiBzdHJpbmcsIGV4cHJlc3Npb246IHN0cmluZykgPT4ge1xuICBpZiAob3BlcmFuZC5sZW5ndGggPT09IDEgJiYgIS9bXFwrXFwtXFwqL10vLnRlc3Qob3BlcmFuZCkpIHtcbiAgICB0aHJvdyBuZXcgV3JvbmdBcml0aG1ldGljRXhwcmVzc2lvbkVycm9yKFxuICAgICAgYFRoZSBvcGVyYXRvciBpbiBcXGAke2V4cHJlc3Npb259XFxgIHNob3VsZCBiZSBvbmUgb2YgdGhlc2UgYXJpdGhtZXRpYyBvcGVyYXRvcnM6ICosICssIC0gb3IgLy5gXG4gICAgKTtcbiAgfSBlbHNlIGlmIChvcGVyYW5kLmxlbmd0aCA9PT0gMSkge1xuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgcmV0dXJuIGZhbHNlO1xufTtcblxuLyoqXG4gKiBFdmFsdWF0ZXMgdGhlIHZhbHVlIG9mIGEgZ2l2ZW4gcGFyYW1ldGVyIGZyb20gdGhlIGlucHV0LlxuICogSWYgdGhlIHBhcmFtZXRlcidzIHZhbHVlIGlzIGFuIGFyaXRobWV0aWMgZXhwcmVzc2lvbiwgaXQgZXZhbHVhdGVzIHRoZSBleHByZXNzaW9uLlxuICogT3RoZXJ3aXNlLCBpdCByZXR1cm5zIHRoZSBwYXJhbWV0ZXIncyB2YWx1ZSBkaXJlY3RseS5cbiAqL1xuY29uc3QgZXZhbHVhdGVPcGVyYW5kID0gKG9wZXJhbmRPcHRpb25zOiB7XG4gIHBhcmFtZXRlcjogc3RyaW5nO1xuICBleHByZXNzaW9uOiBzdHJpbmc7XG4gIHBhcmFtZXRlclZhbHVlOiBzdHJpbmc7XG4gIHBhcmFtZXRlcnNUb0V2YWx1YXRlOiBzdHJpbmdbXTtcbiAgaW5wdXQ6IFBsdWdpblBhcmFtcztcbn0pID0+IHtcbiAgY29uc3Qge3BhcmFtZXRlciwgZXhwcmVzc2lvbiwgcGFyYW1ldGVyc1RvRXZhbHVhdGUsIGlucHV0fSA9IG9wZXJhbmRPcHRpb25zO1xuXG4gIGlmICghKHBhcmFtZXRlciBpbiBpbnB1dCkpIHtcbiAgICB0aHJvdyBuZXcgSW5wdXRWYWxpZGF0aW9uRXJyb3IoXG4gICAgICBgJHtwYXJhbWV0ZXJ9IGlzIG1pc3NpbmcgZnJvbSB0aGUgaW5wdXQgYXJyYXkgb3IgaGFzIG51bGxpc2ggdmFsdWUuYFxuICAgICk7XG4gIH1cblxuICAvLyBDaGVja3MgaWYgdGhlIHBhcmFtZXRlciBpbiB0aGUgaW5wdXQgYXJyYXkgaGFzIG51bWJlciB2YWx1ZS5cbiAgaWYgKGlzTmFOKE51bWJlcihpbnB1dFtwYXJhbWV0ZXJdKSkpIHtcbiAgICB0aHJvdyBuZXcgSW5wdXRWYWxpZGF0aW9uRXJyb3IoXG4gICAgICBgVGhlIHZhbHVlIG9mIHRoZSBcXGAke3BhcmFtZXRlcn1cXGAgcGFyYW1ldGVyIGluIHRoZSBpbnB1dCBhcnJheSBpcyBub3QgYSBudW1iZXIuYFxuICAgICk7XG4gIH1cblxuICBjb25zdCBpc0V4cHJlc3Npb24gPSBpc1ZhbGlkQXJpdGhtZXRpY0V4cHJlc3Npb24oZXhwcmVzc2lvbik7XG5cbiAgaWYgKGlzRXhwcmVzc2lvbikge1xuICAgIHJldHVybiBldmFsdWF0ZUFyaXRobWV0aWNFeHByZXNzaW9uKFxuICAgICAgaW5wdXRbcGFyYW1ldGVyXSxcbiAgICAgIHBhcmFtZXRlcixcbiAgICAgIFsuLi5wYXJhbWV0ZXJzVG9FdmFsdWF0ZSwgcGFyYW1ldGVyXSxcbiAgICAgIGlucHV0XG4gICAgKTtcbiAgfVxuXG4gIHJldHVybiBpbnB1dFtwYXJhbWV0ZXJdO1xufTtcblxuLyoqXG4gKiBFdmFsdWF0ZXMgYSBzaW1wbGUgYXJpdGhtZXRpYyBleHByZXNzaW9uIGlmIHRoZSBpbnB1dCBpcyBhIHZhbGlkIGV4cHJlc3Npb24uXG4gKiBJdCBjaGVja3MgaWYgdGhlIGlucHV0IHN0cmluZyBmb2xsb3dzIGEgcGF0dGVybiBmb3Igc2ltcGxlIGFyaXRobWV0aWNcbiAqIG9wZXJhdGlvbnMgKG51bWJlcnMgd2l0aCBvcGVyYXRvcnMgbGlrZSAqLCAvLCArLCAtKSBiZXR3ZWVuIHRoZW0uXG4gKi9cbmV4cG9ydCBjb25zdCBldmFsdWF0ZVNpbXBsZUFyaXRobWV0aWNFeHByZXNzaW9uID0gKHBhcmFtZXRlcjogc3RyaW5nKSA9PiB7XG4gIGNvbnN0IHNpbXBsZUV4cHJlc3Npb25SZWdleCA9IC9eXFxkKyhcXC5cXGQrKT8oWytcXC0qL11cXGQrKFxcLlxcZCspPykqJC87XG5cbiAgcmV0dXJuIHR5cGVvZiBwYXJhbWV0ZXIgPT09ICdzdHJpbmcnICYmXG4gICAgcGFyYW1ldGVyLnJlcGxhY2UoJz0nLCAnJykubWF0Y2goc2ltcGxlRXhwcmVzc2lvblJlZ2V4KVxuICAgID8gZXZhbHVhdGVFeHByZXNzaW9uKHBhcmFtZXRlci5yZXBsYWNlKCc9JywgJycpKVxuICAgIDogcGFyYW1ldGVyO1xufTtcblxuLyoqXG4gKiBWYWxpZGF0ZXMgd2hldGhlciBhIGdpdmVuIHZhbHVlIGlzIGEgdmFsaWQgYXJpdGhtZXRpYyBleHByZXNzaW9uLlxuICpcbiAqIElmIHRoZSB2YWx1ZSBpcyBhIHN0cmluZywgaXQgZmlyc3QgcmVtb3ZlcyBhbnkgZXF1YWwgc2lnbnMgYW5kIGNoZWNrcyBpZiBpdFxuICogaXMgYSB2YWxpZCBhcml0aG1ldGljIGV4cHJlc3Npb24gdXNpbmcgdGhlIGBpc1ZhbGlkQXJpdGhtZXRpY0V4cHJlc3Npb25gIGhlbHBlci5cbiAqIElmIHZhbGlkLCBpdCBhdHRlbXB0cyB0byBldmFsdWF0ZSB0aGUgZXhwcmVzc2lvbiBhbmQgZW5zdXJlcyB0aGUgcmVzdWx0IGlzIG51bWVyaWMuXG4gKiBJbiBjYXNlIG9mIGFuIGludmFsaWQgZm9ybWF0LCBpdCBjYWxscyBgdmFsaWRhdGVFeHByZXNzaW9uRm9ybWF0YC5cbiAqIFRoZSBmdW5jdGlvbiByZXR1cm5zIHRydWUgaWYgdGhlIHZhbHVlIGlzIHZhbGlkIG9yIG51bWVyaWMuXG4gKi9cbmV4cG9ydCBjb25zdCB2YWxpZGF0ZUFyaXRobWV0aWNFeHByZXNzaW9uID0gKFxuICBwYXJhbWV0ZXJOYW1lOiBzdHJpbmcsXG4gIHZhbHVlOiBhbnksXG4gIHR5cGU/OiBhbnlcbikgPT4ge1xuICBpZiAodHlwZW9mIHZhbHVlID09PSAnc3RyaW5nJykge1xuICAgIGNvbnN0IHNhbml0aXplZFZhbHVlID0gdmFsdWUucmVwbGFjZSgnPScsICcnKTtcblxuICAgIGlmIChpc1ZhbGlkQXJpdGhtZXRpY0V4cHJlc3Npb24oc2FuaXRpemVkVmFsdWUpKSB7XG4gICAgICBjb25zdCBldmFsdWF0ZWRQYXJhbSA9IGV2YWx1YXRlRXhwcmVzc2lvbihzYW5pdGl6ZWRWYWx1ZSkgfHwgdmFsdWU7XG5cbiAgICAgIGlmICghaXNOYU4oTnVtYmVyKGV2YWx1YXRlZFBhcmFtKSkpIHtcbiAgICAgICAgcmV0dXJuIGV2YWx1YXRlZFBhcmFtO1xuICAgICAgfVxuICAgIH1cblxuICAgIHZhbGlkYXRlRXhwcmVzc2lvbkZvcm1hdChwYXJhbWV0ZXJOYW1lLCB2YWx1ZSk7XG5cbiAgICBpZiAodHlwZSA9PT0gJ251bWJlcicpIHtcbiAgICAgIGNvbnN0IG51bWJlck1hdGNoID0gc2FuaXRpemVkVmFsdWUubWF0Y2goL1stK10/WzAtOV0qXFwuP1swLTldKy9nKTtcblxuICAgICAgcmV0dXJuIG51bWJlck1hdGNoID8gcGFyc2VGbG9hdChudW1iZXJNYXRjaFswXSkgOiB2YWx1ZTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gdmFsdWU7XG59O1xuXG4vKipcbiAqIEhlbHBlciBmdW5jdGlvbiB0byBldmFsdWF0ZSB0aGUgYXJpdGhtZXRpYyBleHByZXNzaW9uLlxuICovXG5jb25zdCBldmFsdWF0ZUV4cHJlc3Npb24gPSAoZXhwcmVzc2lvbjogc3RyaW5nKSA9PiB7XG4gIHRyeSB7XG4gICAgY29uc3QgZXZhbHVhdGVkVmFsdWUgPSBldmFsKGV4cHJlc3Npb24pO1xuICAgIGlmIChldmFsdWF0ZWRWYWx1ZSA9PT0gSW5maW5pdHkpIHtcbiAgICAgIHRocm93IG5ldyBaZXJvRGl2aXNpb25Bcml0aG1ldGljT3BlcmF0aW9uRXJyb3IoXG4gICAgICAgIGBUaGUgaW5wdXQgZXhwcmVzc2lvbiBjb250YWlucyBhIGRpdmlzaW9uIGJ5IHplcm86IFxcYCR7ZXhwcmVzc2lvbn1cXGAuYFxuICAgICAgKTtcbiAgICB9XG4gICAgaWYgKGlzTmFOKGV2YWx1YXRlZFZhbHVlKSkge1xuICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9XG5cbiAgICByZXR1cm4gZXZhbHVhdGVkVmFsdWU7XG4gIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgaWYgKGVycm9yIGluc3RhbmNlb2YgWmVyb0RpdmlzaW9uQXJpdGhtZXRpY09wZXJhdGlvbkVycm9yKSB7XG4gICAgICB0aHJvdyBlcnJvcjtcbiAgICB9XG5cbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG59O1xuXG4vKipcbiAqIFZhbGlkYXRlcyB3aGV0aGVyIHRoZSBwcm92aWRlZCBzdHJpbmcgdmFsdWUgaXMgYSB2YWxpZCBhcml0aG1ldGljIGV4cHJlc3Npb24gYmFzZWQgb24gaXRzIGZvcm1hdC5cbiAqXG4gKiBDaGVja3MgaWYgdGhlIGV4cHJlc3Npb24gY29udGFpbnMgYW4gYD1gIHNpZ24gYW5kIGVuc3VyZXMgdGhhdFxuICogdGhlIHBhcnQgb2YgdGhlIHN0cmluZyBmb2xsb3dpbmcgdGhlIGVxdWFsIHNpZ24gaXMgYSB2YWxpZCBhcml0aG1ldGljIGV4cHJlc3Npb24uXG4gKlxuICogLSBJZiB0aGUgc3RyaW5nIHN0YXJ0cyB3aXRoIGA9YCwgdGhlIHJlbWFpbmluZyBwYXJ0IHNob3VsZCBiZSBhIHZhbGlkIGFyaXRobWV0aWMgZXhwcmVzc2lvbi5cbiAqIC0gSWYgaXQgZG9lc24ndCBzdGFydCB3aXRoIGA9YCwgdGhlIGVudGlyZSBzdHJpbmcgc2hvdWxkIG5vdCByZXNlbWJsZSBhIHZhbGlkIGFyaXRobWV0aWMgZXhwcmVzc2lvbi5cbiAqXG4gKiBUaHJvd3MgYW4gYElucHV0VmFsaWRhdGlvbkVycm9yYCBlcnJvciBpZiB0aGUgZm9ybWF0IG9yIGNvbnRlbnQgb2YgdGhlIGFyaXRobWV0aWMgZXhwcmVzc2lvbiBpcyBpbnZhbGlkLlxuICovXG5jb25zdCB2YWxpZGF0ZUV4cHJlc3Npb25Gb3JtYXQgPSAocGFyYW1ldGVyTmFtZTogc3RyaW5nLCB2YWx1ZTogc3RyaW5nKSA9PiB7XG4gIGNvbnN0IGhhc0VxdWFsU2lnbiA9IHZhbHVlLmluY2x1ZGVzKCc9Jyk7XG4gIGNvbnN0IGlzVmFsaWQgPSBpc1ZhbGlkQXJpdGhtZXRpY0V4cHJlc3Npb24odmFsdWUucmVwbGFjZSgnPScsICcnKSk7XG5cbiAgaWYgKChoYXNFcXVhbFNpZ24gJiYgIWlzVmFsaWQpIHx8ICghaGFzRXF1YWxTaWduICYmIGlzVmFsaWQpKSB7XG4gICAgdGhyb3cgbmV3IElucHV0VmFsaWRhdGlvbkVycm9yKFxuICAgICAgYFRoZSBcXGAke3BhcmFtZXRlck5hbWV9XFxgIGNvbnRhaW5zIGFuIGludmFsaWQgYXJpdGhtZXRpYyBleHByZXNzaW9uLiBJdCBzaG91bGQgc3RhcnQgd2l0aCBcXGA9XFxgIGFuZCBpbmNsdWRlIHRoZSBzeW1ib2xzIFxcYCpcXGAsIFxcYCtcXGAsIFxcYC1cXGAgYW5kIFxcYC9cXGAuYFxuICAgICk7XG4gIH1cbn07XG4iXX0=