@kazekyo/nau-graphql-codegen-preset
Version:
A GraphQL Code Generator preset for Nau
359 lines (356 loc) • 50.8 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.transform = exports.exportedForTesting = void 0;
var _nau = require("@kazekyo/nau");
var _graphql = require("graphql");
var _graphqlAST = require("../utils/graphqlAST");
var _util = require("./util");
function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); }
function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }
function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return _typeof(key) === "symbol" ? key : String(key); }
function _toPrimitive(input, hint) { if (_typeof(input) !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (_typeof(res) !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
var transform = function transform(_ref) {
var documentFiles = _ref.documentFiles;
var fragmentDefinitions = (0, _graphqlAST.getFragmentDefinitionsByDocumentFiles)(documentFiles);
var operationInfoList = getOperationInfoList({
documentFiles: documentFiles
});
var files = documentFiles.map(function (file) {
if (!file.document) return file;
var result = copyFragments({
documentNode: file.document,
fragmentDefinitions: fragmentDefinitions,
operationInfoList: operationInfoList
});
file.document = result.documentNode;
return file;
});
operationInfoList = getOperationInfoList({
documentFiles: files
});
if (operationInfoList.length === 0) return {
documentFiles: files
};
files = documentFiles.map(function (file) {
if (!file.document) return file;
file.document = fixVariables({
documentNode: file.document,
operationInfoList: operationInfoList
});
return file;
});
return {
documentFiles: files
};
};
// Copy fragment definitions if both operations are with and without a argument in operation variables
exports.transform = transform;
var copyFragments = function copyFragments(params) {
var fragmentDefinitions = params.fragmentDefinitions,
operationInfoList = params.operationInfoList;
var documentNode = params.documentNode;
var operationDefinitions = (0, _graphqlAST.getOperationDefinitions)(documentNode);
if (!operationDefinitions) return {
documentNode: documentNode
};
var changedOperationDefinitions = [];
operationDefinitions.forEach(function (operationDefinition) {
var transformResult = transformFragmentSpreadFields({
targetDefinition: operationDefinition,
operationDefinition: operationDefinition,
documentNode: documentNode,
fragmentDefinitions: fragmentDefinitions,
operationInfoList: operationInfoList
});
changedOperationDefinitions.push(transformResult.newDefinition);
documentNode = transformResult.documentNode;
});
return {
documentNode: _objectSpread(_objectSpread({}, documentNode), {}, {
definitions: [].concat(changedOperationDefinitions, _toConsumableArray(documentNode.definitions.filter(function (definition) {
return definition.kind !== 'OperationDefinition';
})))
})
};
};
var transformFragmentSpreadFields = function transformFragmentSpreadFields(params) {
var targetDefinition = params.targetDefinition,
fragmentDefinitions = params.fragmentDefinitions,
operationInfoList = params.operationInfoList,
operationDefinition = params.operationDefinition;
var documentNode = params.documentNode;
var tokens = [];
var currentDefinition = (0, _graphql.visit)(targetDefinition, {
FragmentSpread: {
leave: function leave(originalNode) {
var originalFragmentName = originalNode.name.value;
var nextTargetFragmentDefinition = (0, _graphqlAST.getFragmentDefinitionByName)({
fragmentDefinitions: fragmentDefinitions,
fragmentName: originalFragmentName
});
if (!nextTargetFragmentDefinition) return;
var result = transformFragmentDefinition({
targetFragmentDefinition: nextTargetFragmentDefinition,
documentNode: documentNode,
operationDefinition: params.operationDefinition,
fragmentDefinitions: fragmentDefinitions,
operationInfoList: operationInfoList
});
documentNode = result.documentNode;
if (!result.changed) return;
var changedSpareadFragmentFieldNode = _objectSpread(_objectSpread({}, originalNode), {}, {
name: _objectSpread(_objectSpread({}, originalNode.name), {}, {
value: result.changed.fragmentName
})
});
if (targetDefinition.kind === _graphql.Kind.OPERATION_DEFINITION) {
return changedSpareadFragmentFieldNode;
}
var isFragmentInOtherOperation = operationInfoList.find(function (info) {
var _operationDefinition$;
return info.operationName !== ((_operationDefinition$ = operationDefinition.name) === null || _operationDefinition$ === void 0 ? void 0 : _operationDefinition$.value) && info.belongsFragmentNames.find(function (fragmentName) {
return fragmentName === targetDefinition.name.value;
});
});
if (isFragmentInOtherOperation) {
var splitName = result.changed.fragmentName.split('_');
tokens.push("child:".concat(splitName[splitName.length - 1]));
}
return changedSpareadFragmentFieldNode;
}
}
});
if (tokens.length !== 0 && currentDefinition.kind === _graphql.Kind.FRAGMENT_DEFINITION) {
var uniqueName = (0, _util.getUniqueFragmentName)(currentDefinition.name.value, tokens.join(','));
var newDefinition = _objectSpread(_objectSpread({}, currentDefinition), {}, {
name: _objectSpread(_objectSpread({}, currentDefinition.name), {}, {
value: uniqueName
})
});
var exists = !!documentNode.definitions.find(function (definition) {
return definition.kind === _graphql.Kind.FRAGMENT_DEFINITION && definition.name.value === uniqueName;
});
if (!exists) {
documentNode = _objectSpread(_objectSpread({}, documentNode), {}, {
definitions: [].concat(_toConsumableArray(documentNode.definitions), [newDefinition])
});
}
return {
documentNode: documentNode,
newDefinition: newDefinition,
changed: {
fragmentName: uniqueName
}
};
}
return {
documentNode: documentNode,
newDefinition: currentDefinition
};
};
var transformFragmentDefinition = function transformFragmentDefinition(params) {
var operationInfoList = params.operationInfoList,
operationDefinition = params.operationDefinition;
var documentNode = params.documentNode;
var currentFragmentDefinition = params.targetFragmentDefinition;
var transformResult = transformFragmentSpreadFields({
targetDefinition: currentFragmentDefinition,
operationDefinition: operationDefinition,
documentNode: documentNode,
fragmentDefinitions: params.fragmentDefinitions,
operationInfoList: operationInfoList
});
documentNode = transformResult.documentNode;
currentFragmentDefinition = transformResult.newDefinition;
var argumentDefinitionDataList = [];
(0, _graphql.visit)(currentFragmentDefinition, {
Directive: {
leave: function leave(node) {
if (node.name.value !== _nau.ARGUMENT_DEFINITIONS_DIRECTIVE_NAME) return;
argumentDefinitionDataList = (0, _util.getArgumentDefinitionDataList)(node);
return;
}
}
});
var variableNames = [];
(0, _graphql.visit)(currentFragmentDefinition, {
Variable: {
leave: function leave(node) {
var variableName = node.name.value;
var argumentDefinitionData = argumentDefinitionDataList.find(function (data) {
return data.name.value === variableName;
});
if (!argumentDefinitionData) return;
var variableDefinitions = operationDefinition.variableDefinitions;
if (!variableDefinitions) return;
var existsInOperationVariable = !!variableDefinitions.find(function (variableDefinition) {
return variableDefinition.variable.name.value === variableName;
});
if (!existsInOperationVariable) return;
// If there is a operation that uses the same fragment definition but variable does not exist,
// it is subject to copying because it is a different definition of fragment.
var compare = function compare(info, fragmentName) {
return info.belongsFragmentNames.find(function (name) {
return name === fragmentName;
}) && info.variableNames.find(function (name) {
return name === variableName;
});
};
var operationInfoListWithNotIncludingVariable = operationInfoList.filter(function (info) {
return !compare(info, currentFragmentDefinition.name.value);
});
if (operationInfoListWithNotIncludingVariable.length === 0) return;
variableNames.push(variableName);
return false;
}
}
});
if (variableNames.length === 0) return {
documentNode: documentNode,
changed: transformResult.changed
};
var uniqueFragmentName = (0, _util.getUniqueFragmentName)(currentFragmentDefinition.name.value, "".concat(_util.FRAGMENT_NAME_INFO_ID_3, ",").concat(variableNames.join(',')));
var copiedFragmentDefinition = _objectSpread(_objectSpread({}, currentFragmentDefinition), {}, {
name: _objectSpread(_objectSpread({}, currentFragmentDefinition.name), {}, {
value: uniqueFragmentName
})
});
documentNode = _objectSpread(_objectSpread({}, documentNode), {}, {
definitions: [].concat(_toConsumableArray(documentNode.definitions), [copiedFragmentDefinition])
});
return {
documentNode: documentNode,
changed: {
fragmentName: uniqueFragmentName
}
};
};
var fixVariables = function fixVariables(_ref2) {
var documentNode = _ref2.documentNode,
operationInfoList = _ref2.operationInfoList;
return (0, _graphql.visit)(documentNode, {
FragmentDefinition: {
leave: function leave(fragmentDefinition) {
var argumentDefinitionDataList = [];
(0, _graphql.visit)(fragmentDefinition, {
Directive: {
leave: function leave(node) {
if (node.name.value !== _nau.ARGUMENT_DEFINITIONS_DIRECTIVE_NAME) return;
argumentDefinitionDataList = (0, _util.getArgumentDefinitionDataList)(node);
return;
}
}
});
if (argumentDefinitionDataList.length === 0) return;
return (0, _graphql.visit)(fragmentDefinition, {
Variable: {
leave: function leave(variableNode) {
// Find with operationInfoList because there may be more than one operation definition in documentNode
var existsInVariable = existsVariable({
variableName: variableNode.name.value,
fragmentName: fragmentDefinition.name.value,
operationInfoList: operationInfoList
});
if (existsInVariable) return;
var argumentDefinitionData = argumentDefinitionDataList.find(function (data) {
return data.name.value === variableNode.name.value;
});
if (!argumentDefinitionData) return;
if (argumentDefinitionData.defaultValue) {
// Replace with default value
return _objectSpread({}, argumentDefinitionData.defaultValue);
}
if (argumentDefinitionData.type.kind !== 'NonNullType') {
// Replace with null value
var nullValueNode = {
kind: _graphql.Kind.NULL
};
return nullValueNode;
}
}
}
});
}
}
});
};
var getOperationInfoList = function getOperationInfoList(_ref3) {
var documentFiles = _ref3.documentFiles;
var fragmentDefinitions = (0, _graphqlAST.getFragmentDefinitionsByDocumentFiles)(documentFiles);
var namesPairs = [];
documentFiles.map(function (file) {
if (!file.document) return file;
var operationDefinitions = (0, _graphqlAST.getOperationDefinitions)(file.document);
operationDefinitions.forEach(function (operationDefinition) {
var _operationDefinition$2;
if (!operationDefinition.variableDefinitions) return;
var fragmentNames = getFragmentNames({
targetDefinition: operationDefinition,
fragmentDefinitions: fragmentDefinitions,
fragmentNames: []
});
var variableNames = operationDefinition.variableDefinitions.map(function (variableDefinition) {
return variableDefinition.variable.name.value;
});
namesPairs.push({
operationName: (_operationDefinition$2 = operationDefinition.name) === null || _operationDefinition$2 === void 0 ? void 0 : _operationDefinition$2.value,
variableNames: variableNames,
belongsFragmentNames: fragmentNames
});
});
});
return namesPairs;
};
var getFragmentNames = function getFragmentNames(_ref4) {
var targetDefinition = _ref4.targetDefinition,
fragmentDefinitions = _ref4.fragmentDefinitions,
fragmentNames = _ref4.fragmentNames;
(0, _graphql.visit)(targetDefinition, {
FragmentSpread: {
enter: function enter(node) {
var nextFragmentName = node.name.value;
var next = (0, _graphqlAST.getFragmentDefinitionByName)({
fragmentDefinitions: fragmentDefinitions,
fragmentName: node.name.value
});
if (!next) return;
fragmentNames.push(nextFragmentName);
getFragmentNames({
targetDefinition: next,
fragmentDefinitions: fragmentDefinitions,
fragmentNames: fragmentNames
});
}
}
});
return fragmentNames;
};
var existsVariable = function existsVariable(_ref5) {
var variableName = _ref5.variableName,
fragmentName = _ref5.fragmentName,
operationInfoList = _ref5.operationInfoList;
var operationInfo = operationInfoList.find(function (info) {
return info.belongsFragmentNames.find(function (name) {
return name === fragmentName;
});
});
if (!operationInfo) return false;
return !!operationInfo.variableNames.find(function (name) {
return variableName === name;
});
};
var exportedForTesting = {
getOperationInfoList: getOperationInfoList
};
exports.exportedForTesting = exportedForTesting;
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJ0cmFuc2Zvcm0iLCJkb2N1bWVudEZpbGVzIiwiZnJhZ21lbnREZWZpbml0aW9ucyIsImdldEZyYWdtZW50RGVmaW5pdGlvbnNCeURvY3VtZW50RmlsZXMiLCJvcGVyYXRpb25JbmZvTGlzdCIsImdldE9wZXJhdGlvbkluZm9MaXN0IiwiZmlsZXMiLCJtYXAiLCJmaWxlIiwiZG9jdW1lbnQiLCJyZXN1bHQiLCJjb3B5RnJhZ21lbnRzIiwiZG9jdW1lbnROb2RlIiwibGVuZ3RoIiwiZml4VmFyaWFibGVzIiwicGFyYW1zIiwib3BlcmF0aW9uRGVmaW5pdGlvbnMiLCJnZXRPcGVyYXRpb25EZWZpbml0aW9ucyIsImNoYW5nZWRPcGVyYXRpb25EZWZpbml0aW9ucyIsImZvckVhY2giLCJvcGVyYXRpb25EZWZpbml0aW9uIiwidHJhbnNmb3JtUmVzdWx0IiwidHJhbnNmb3JtRnJhZ21lbnRTcHJlYWRGaWVsZHMiLCJ0YXJnZXREZWZpbml0aW9uIiwicHVzaCIsIm5ld0RlZmluaXRpb24iLCJkZWZpbml0aW9ucyIsImZpbHRlciIsImRlZmluaXRpb24iLCJraW5kIiwidG9rZW5zIiwiY3VycmVudERlZmluaXRpb24iLCJ2aXNpdCIsIkZyYWdtZW50U3ByZWFkIiwibGVhdmUiLCJvcmlnaW5hbE5vZGUiLCJvcmlnaW5hbEZyYWdtZW50TmFtZSIsIm5hbWUiLCJ2YWx1ZSIsIm5leHRUYXJnZXRGcmFnbWVudERlZmluaXRpb24iLCJnZXRGcmFnbWVudERlZmluaXRpb25CeU5hbWUiLCJmcmFnbWVudE5hbWUiLCJ0cmFuc2Zvcm1GcmFnbWVudERlZmluaXRpb24iLCJ0YXJnZXRGcmFnbWVudERlZmluaXRpb24iLCJjaGFuZ2VkIiwiY2hhbmdlZFNwYXJlYWRGcmFnbWVudEZpZWxkTm9kZSIsIktpbmQiLCJPUEVSQVRJT05fREVGSU5JVElPTiIsImlzRnJhZ21lbnRJbk90aGVyT3BlcmF0aW9uIiwiZmluZCIsImluZm8iLCJvcGVyYXRpb25OYW1lIiwiYmVsb25nc0ZyYWdtZW50TmFtZXMiLCJzcGxpdE5hbWUiLCJzcGxpdCIsIkZSQUdNRU5UX0RFRklOSVRJT04iLCJ1bmlxdWVOYW1lIiwiZ2V0VW5pcXVlRnJhZ21lbnROYW1lIiwiam9pbiIsImV4aXN0cyIsImN1cnJlbnRGcmFnbWVudERlZmluaXRpb24iLCJhcmd1bWVudERlZmluaXRpb25EYXRhTGlzdCIsIkRpcmVjdGl2ZSIsIm5vZGUiLCJBUkdVTUVOVF9ERUZJTklUSU9OU19ESVJFQ1RJVkVfTkFNRSIsImdldEFyZ3VtZW50RGVmaW5pdGlvbkRhdGFMaXN0IiwidmFyaWFibGVOYW1lcyIsIlZhcmlhYmxlIiwidmFyaWFibGVOYW1lIiwiYXJndW1lbnREZWZpbml0aW9uRGF0YSIsImRhdGEiLCJ2YXJpYWJsZURlZmluaXRpb25zIiwiZXhpc3RzSW5PcGVyYXRpb25WYXJpYWJsZSIsInZhcmlhYmxlRGVmaW5pdGlvbiIsInZhcmlhYmxlIiwiY29tcGFyZSIsIm9wZXJhdGlvbkluZm9MaXN0V2l0aE5vdEluY2x1ZGluZ1ZhcmlhYmxlIiwidW5pcXVlRnJhZ21lbnROYW1lIiwiRlJBR01FTlRfTkFNRV9JTkZPX0lEXzMiLCJjb3BpZWRGcmFnbWVudERlZmluaXRpb24iLCJGcmFnbWVudERlZmluaXRpb24iLCJmcmFnbWVudERlZmluaXRpb24iLCJ2YXJpYWJsZU5vZGUiLCJleGlzdHNJblZhcmlhYmxlIiwiZXhpc3RzVmFyaWFibGUiLCJkZWZhdWx0VmFsdWUiLCJ0eXBlIiwibnVsbFZhbHVlTm9kZSIsIk5VTEwiLCJuYW1lc1BhaXJzIiwiZnJhZ21lbnROYW1lcyIsImdldEZyYWdtZW50TmFtZXMiLCJlbnRlciIsIm5leHRGcmFnbWVudE5hbWUiLCJuZXh0Iiwib3BlcmF0aW9uSW5mbyIsImV4cG9ydGVkRm9yVGVzdGluZyJdLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy90cmFuc2Zvcm1zL2ZpeFZhcmlhYmxlTm90RGVmaW5lZEluUm9vdC50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBUeXBlcyB9IGZyb20gJ0BncmFwaHFsLWNvZGVnZW4vcGx1Z2luLWhlbHBlcnMnO1xuaW1wb3J0IHsgQVJHVU1FTlRfREVGSU5JVElPTlNfRElSRUNUSVZFX05BTUUgfSBmcm9tICdAa2F6ZWt5by9uYXUnO1xuaW1wb3J0IHtcbiAgQVNUTm9kZSxcbiAgRG9jdW1lbnROb2RlLFxuICBGcmFnbWVudERlZmluaXRpb25Ob2RlLFxuICBLaW5kLFxuICBOdWxsVmFsdWVOb2RlLFxuICBPcGVyYXRpb25EZWZpbml0aW9uTm9kZSxcbiAgdmlzaXQsXG59IGZyb20gJ2dyYXBocWwnO1xuaW1wb3J0IHtcbiAgZ2V0RnJhZ21lbnREZWZpbml0aW9uQnlOYW1lLFxuICBnZXRGcmFnbWVudERlZmluaXRpb25zQnlEb2N1bWVudEZpbGVzLFxuICBnZXRPcGVyYXRpb25EZWZpbml0aW9ucyxcbn0gZnJvbSAnLi4vdXRpbHMvZ3JhcGhxbEFTVCc7XG5pbXBvcnQge1xuICBBcmd1bWVudERlZmluaXRpb25EYXRhLFxuICBGUkFHTUVOVF9OQU1FX0lORk9fSURfMyxcbiAgZ2V0QXJndW1lbnREZWZpbml0aW9uRGF0YUxpc3QsXG4gIGdldFVuaXF1ZUZyYWdtZW50TmFtZSxcbn0gZnJvbSAnLi91dGlsJztcblxudHlwZSBPcGVyYXRpb25JbmZvID0ge1xuICBvcGVyYXRpb25OYW1lPzogc3RyaW5nO1xuICB2YXJpYWJsZU5hbWVzOiBzdHJpbmdbXTtcbiAgYmVsb25nc0ZyYWdtZW50TmFtZXM6IHN0cmluZ1tdO1xufTtcblxuZXhwb3J0IGNvbnN0IHRyYW5zZm9ybSA9ICh7XG4gIGRvY3VtZW50RmlsZXMsXG59OiB7XG4gIGRvY3VtZW50RmlsZXM6IFR5cGVzLkRvY3VtZW50RmlsZVtdO1xufSk6IHsgZG9jdW1lbnRGaWxlczogVHlwZXMuRG9jdW1lbnRGaWxlW10gfSA9PiB7XG4gIGNvbnN0IGZyYWdtZW50RGVmaW5pdGlvbnMgPSBnZXRGcmFnbWVudERlZmluaXRpb25zQnlEb2N1bWVudEZpbGVzKGRvY3VtZW50RmlsZXMpO1xuXG4gIGxldCBvcGVyYXRpb25JbmZvTGlzdCA9IGdldE9wZXJhdGlvbkluZm9MaXN0KHsgZG9jdW1lbnRGaWxlcyB9KTtcblxuICBsZXQgZmlsZXMgPSBkb2N1bWVudEZpbGVzLm1hcCgoZmlsZSkgPT4ge1xuICAgIGlmICghZmlsZS5kb2N1bWVudCkgcmV0dXJuIGZpbGU7XG4gICAgY29uc3QgcmVzdWx0ID0gY29weUZyYWdtZW50cyh7XG4gICAgICBkb2N1bWVudE5vZGU6IGZpbGUuZG9jdW1lbnQsXG4gICAgICBmcmFnbWVudERlZmluaXRpb25zLFxuICAgICAgb3BlcmF0aW9uSW5mb0xpc3QsXG4gICAgfSk7XG4gICAgZmlsZS5kb2N1bWVudCA9IHJlc3VsdC5kb2N1bWVudE5vZGU7XG4gICAgcmV0dXJuIGZpbGU7XG4gIH0pO1xuXG4gIG9wZXJhdGlvbkluZm9MaXN0ID0gZ2V0T3BlcmF0aW9uSW5mb0xpc3QoeyBkb2N1bWVudEZpbGVzOiBmaWxlcyB9KTtcbiAgaWYgKG9wZXJhdGlvbkluZm9MaXN0Lmxlbmd0aCA9PT0gMCkgcmV0dXJuIHsgZG9jdW1lbnRGaWxlczogZmlsZXMgfTtcblxuICBmaWxlcyA9IGRvY3VtZW50RmlsZXMubWFwKChmaWxlKSA9PiB7XG4gICAgaWYgKCFmaWxlLmRvY3VtZW50KSByZXR1cm4gZmlsZTtcbiAgICBmaWxlLmRvY3VtZW50ID0gZml4VmFyaWFibGVzKHsgZG9jdW1lbnROb2RlOiBmaWxlLmRvY3VtZW50LCBvcGVyYXRpb25JbmZvTGlzdCB9KTtcbiAgICByZXR1cm4gZmlsZTtcbiAgfSk7XG4gIHJldHVybiB7IGRvY3VtZW50RmlsZXM6IGZpbGVzIH07XG59O1xuXG4vLyBDb3B5IGZyYWdtZW50IGRlZmluaXRpb25zIGlmIGJvdGggb3BlcmF0aW9ucyBhcmUgd2l0aCBhbmQgd2l0aG91dCBhIGFyZ3VtZW50IGluIG9wZXJhdGlvbiB2YXJpYWJsZXNcbmNvbnN0IGNvcHlGcmFnbWVudHMgPSAocGFyYW1zOiB7XG4gIGRvY3VtZW50Tm9kZTogRG9jdW1lbnROb2RlO1xuICBmcmFnbWVudERlZmluaXRpb25zOiBGcmFnbWVudERlZmluaXRpb25Ob2RlW107XG4gIG9wZXJhdGlvbkluZm9MaXN0OiBPcGVyYXRpb25JbmZvW107XG59KTogeyBkb2N1bWVudE5vZGU6IERvY3VtZW50Tm9kZSB9ID0+IHtcbiAgY29uc3QgeyBmcmFnbWVudERlZmluaXRpb25zLCBvcGVyYXRpb25JbmZvTGlzdCB9ID0gcGFyYW1zO1xuICBsZXQgZG9jdW1lbnROb2RlID0gcGFyYW1zLmRvY3VtZW50Tm9kZTtcbiAgY29uc3Qgb3BlcmF0aW9uRGVmaW5pdGlvbnMgPSBnZXRPcGVyYXRpb25EZWZpbml0aW9ucyhkb2N1bWVudE5vZGUpO1xuICBpZiAoIW9wZXJhdGlvbkRlZmluaXRpb25zKSByZXR1cm4geyBkb2N1bWVudE5vZGUgfTtcblxuICBjb25zdCBjaGFuZ2VkT3BlcmF0aW9uRGVmaW5pdGlvbnM6IE9wZXJhdGlvbkRlZmluaXRpb25Ob2RlW10gPSBbXTtcbiAgb3BlcmF0aW9uRGVmaW5pdGlvbnMuZm9yRWFjaCgob3BlcmF0aW9uRGVmaW5pdGlvbikgPT4ge1xuICAgIGNvbnN0IHRyYW5zZm9ybVJlc3VsdCA9IHRyYW5zZm9ybUZyYWdtZW50U3ByZWFkRmllbGRzKHtcbiAgICAgIHRhcmdldERlZmluaXRpb246IG9wZXJhdGlvbkRlZmluaXRpb24sXG4gICAgICBvcGVyYXRpb25EZWZpbml0aW9uLFxuICAgICAgZG9jdW1lbnROb2RlOiBkb2N1bWVudE5vZGUsXG4gICAgICBmcmFnbWVudERlZmluaXRpb25zLFxuICAgICAgb3BlcmF0aW9uSW5mb0xpc3QsXG4gICAgfSk7XG4gICAgY2hhbmdlZE9wZXJhdGlvbkRlZmluaXRpb25zLnB1c2godHJhbnNmb3JtUmVzdWx0Lm5ld0RlZmluaXRpb24pO1xuICAgIGRvY3VtZW50Tm9kZSA9IHRyYW5zZm9ybVJlc3VsdC5kb2N1bWVudE5vZGU7XG4gIH0pO1xuXG4gIHJldHVybiB7XG4gICAgZG9jdW1lbnROb2RlOiB7XG4gICAgICAuLi5kb2N1bWVudE5vZGUsXG4gICAgICBkZWZpbml0aW9uczogW1xuICAgICAgICAuLi5jaGFuZ2VkT3BlcmF0aW9uRGVmaW5pdGlvbnMsXG4gICAgICAgIC4uLmRvY3VtZW50Tm9kZS5kZWZpbml0aW9ucy5maWx0ZXIoKGRlZmluaXRpb24pID0+IGRlZmluaXRpb24ua2luZCAhPT0gJ09wZXJhdGlvbkRlZmluaXRpb24nKSxcbiAgICAgIF0sXG4gICAgfSxcbiAgfTtcbn07XG5cbmNvbnN0IHRyYW5zZm9ybUZyYWdtZW50U3ByZWFkRmllbGRzID0gPFxuICBURGVmaW5pdGlvbk5vZGUgZXh0ZW5kcyBPcGVyYXRpb25EZWZpbml0aW9uTm9kZSB8IEZyYWdtZW50RGVmaW5pdGlvbk5vZGUsXG4+KHBhcmFtczoge1xuICB0YXJnZXREZWZpbml0aW9uOiBURGVmaW5pdGlvbk5vZGU7XG4gIG9wZXJhdGlvbkRlZmluaXRpb246IE9wZXJhdGlvbkRlZmluaXRpb25Ob2RlO1xuICBkb2N1bWVudE5vZGU6IERvY3VtZW50Tm9kZTtcbiAgZnJhZ21lbnREZWZpbml0aW9uczogRnJhZ21lbnREZWZpbml0aW9uTm9kZVtdO1xuICBvcGVyYXRpb25JbmZvTGlzdDogT3BlcmF0aW9uSW5mb1tdO1xufSk6IHtcbiAgZG9jdW1lbnROb2RlOiBEb2N1bWVudE5vZGU7XG4gIG5ld0RlZmluaXRpb246IFREZWZpbml0aW9uTm9kZTtcbiAgY2hhbmdlZD86IHsgZnJhZ21lbnROYW1lOiBzdHJpbmcgfTtcbn0gPT4ge1xuICBjb25zdCB7IHRhcmdldERlZmluaXRpb24sIGZyYWdtZW50RGVmaW5pdGlvbnMsIG9wZXJhdGlvbkluZm9MaXN0LCBvcGVyYXRpb25EZWZpbml0aW9uIH0gPSBwYXJhbXM7XG4gIGxldCBkb2N1bWVudE5vZGUgPSBwYXJhbXMuZG9jdW1lbnROb2RlO1xuICBjb25zdCB0b2tlbnM6IHN0cmluZ1tdID0gW107XG4gIGNvbnN0IGN1cnJlbnREZWZpbml0aW9uID0gdmlzaXQodGFyZ2V0RGVmaW5pdGlvbiwge1xuICAgIEZyYWdtZW50U3ByZWFkOiB7XG4gICAgICBsZWF2ZShvcmlnaW5hbE5vZGUpIHtcbiAgICAgICAgY29uc3Qgb3JpZ2luYWxGcmFnbWVudE5hbWUgPSBvcmlnaW5hbE5vZGUubmFtZS52YWx1ZTtcbiAgICAgICAgY29uc3QgbmV4dFRhcmdldEZyYWdtZW50RGVmaW5pdGlvbiA9IGdldEZyYWdtZW50RGVmaW5pdGlvbkJ5TmFtZSh7XG4gICAgICAgICAgZnJhZ21lbnREZWZpbml0aW9ucyxcbiAgICAgICAgICBmcmFnbWVudE5hbWU6IG9yaWdpbmFsRnJhZ21lbnROYW1lLFxuICAgICAgICB9KTtcbiAgICAgICAgaWYgKCFuZXh0VGFyZ2V0RnJhZ21lbnREZWZpbml0aW9uKSByZXR1cm47XG5cbiAgICAgICAgY29uc3QgcmVzdWx0ID0gdHJhbnNmb3JtRnJhZ21lbnREZWZpbml0aW9uKHtcbiAgICAgICAgICB0YXJnZXRGcmFnbWVudERlZmluaXRpb246IG5leHRUYXJnZXRGcmFnbWVudERlZmluaXRpb24sXG4gICAgICAgICAgZG9jdW1lbnROb2RlOiBkb2N1bWVudE5vZGUsXG4gICAgICAgICAgb3BlcmF0aW9uRGVmaW5pdGlvbjogcGFyYW1zLm9wZXJhdGlvbkRlZmluaXRpb24sXG4gICAgICAgICAgZnJhZ21lbnREZWZpbml0aW9ucyxcbiAgICAgICAgICBvcGVyYXRpb25JbmZvTGlzdCxcbiAgICAgICAgfSk7XG4gICAgICAgIGRvY3VtZW50Tm9kZSA9IHJlc3VsdC5kb2N1bWVudE5vZGU7XG4gICAgICAgIGlmICghcmVzdWx0LmNoYW5nZWQpIHJldHVybjtcblxuICAgICAgICBjb25zdCBjaGFuZ2VkU3BhcmVhZEZyYWdtZW50RmllbGROb2RlID0ge1xuICAgICAgICAgIC4uLm9yaWdpbmFsTm9kZSxcbiAgICAgICAgICBuYW1lOiB7IC4uLm9yaWdpbmFsTm9kZS5uYW1lLCB2YWx1ZTogcmVzdWx0LmNoYW5nZWQuZnJhZ21lbnROYW1lIH0sXG4gICAgICAgIH07XG5cbiAgICAgICAgaWYgKHRhcmdldERlZmluaXRpb24ua2luZCA9PT0gS2luZC5PUEVSQVRJT05fREVGSU5JVElPTikge1xuICAgICAgICAgIHJldHVybiBjaGFuZ2VkU3BhcmVhZEZyYWdtZW50RmllbGROb2RlO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgaXNGcmFnbWVudEluT3RoZXJPcGVyYXRpb24gPSBvcGVyYXRpb25JbmZvTGlzdC5maW5kKFxuICAgICAgICAgIChpbmZvKSA9PlxuICAgICAgICAgICAgaW5mby5vcGVyYXRpb25OYW1lICE9PSBvcGVyYXRpb25EZWZpbml0aW9uLm5hbWU/LnZhbHVlICYmXG4gICAgICAgICAgICBpbmZvLmJlbG9uZ3NGcmFnbWVudE5hbWVzLmZpbmQoKGZyYWdtZW50TmFtZSkgPT4gZnJhZ21lbnROYW1lID09PSB0YXJnZXREZWZpbml0aW9uLm5hbWUudmFsdWUpLFxuICAgICAgICApO1xuICAgICAgICBpZiAoaXNGcmFnbWVudEluT3RoZXJPcGVyYXRpb24pIHtcbiAgICAgICAgICBjb25zdCBzcGxpdE5hbWUgPSByZXN1bHQuY2hhbmdlZC5mcmFnbWVudE5hbWUuc3BsaXQoJ18nKTtcbiAgICAgICAgICB0b2tlbnMucHVzaChgY2hpbGQ6JHtzcGxpdE5hbWVbc3BsaXROYW1lLmxlbmd0aCAtIDFdfWApO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGNoYW5nZWRTcGFyZWFkRnJhZ21lbnRGaWVsZE5vZGU7XG4gICAgICB9LFxuICAgIH0sXG4gIH0pO1xuXG4gIGlmICh0b2tlbnMubGVuZ3RoICE9PSAwICYmIGN1cnJlbnREZWZpbml0aW9uLmtpbmQgPT09IEtpbmQuRlJBR01FTlRfREVGSU5JVElPTikge1xuICAgIGNvbnN0IHVuaXF1ZU5hbWUgPSBnZXRVbmlxdWVGcmFnbWVudE5hbWUoY3VycmVudERlZmluaXRpb24ubmFtZS52YWx1ZSwgdG9rZW5zLmpvaW4oJywnKSk7XG4gICAgY29uc3QgbmV3RGVmaW5pdGlvbjogRnJhZ21lbnREZWZpbml0aW9uTm9kZSA9IHtcbiAgICAgIC4uLmN1cnJlbnREZWZpbml0aW9uLFxuICAgICAgbmFtZTogeyAuLi5jdXJyZW50RGVmaW5pdGlvbi5uYW1lLCB2YWx1ZTogdW5pcXVlTmFtZSB9LFxuICAgIH0gYXMgRnJhZ21lbnREZWZpbml0aW9uTm9kZTtcblxuICAgIGNvbnN0IGV4aXN0cyA9ICEhZG9jdW1lbnROb2RlLmRlZmluaXRpb25zLmZpbmQoXG4gICAgICAoZGVmaW5pdGlvbikgPT4gZGVmaW5pdGlvbi5raW5kID09PSBLaW5kLkZSQUdNRU5UX0RFRklOSVRJT04gJiYgZGVmaW5pdGlvbi5uYW1lLnZhbHVlID09PSB1bmlxdWVOYW1lLFxuICAgICk7XG4gICAgaWYgKCFleGlzdHMpIHtcbiAgICAgIGRvY3VtZW50Tm9kZSA9IHtcbiAgICAgICAgLi4uZG9jdW1lbnROb2RlLFxuICAgICAgICBkZWZpbml0aW9uczogWy4uLmRvY3VtZW50Tm9kZS5kZWZpbml0aW9ucywgbmV3RGVmaW5pdGlvbl0sXG4gICAgICB9O1xuICAgIH1cbiAgICByZXR1cm4ge1xuICAgICAgZG9jdW1lbnROb2RlLFxuICAgICAgbmV3RGVmaW5pdGlvbjogbmV3RGVmaW5pdGlvbiBhcyBURGVmaW5pdGlvbk5vZGUsXG4gICAgICBjaGFuZ2VkOiB7IGZyYWdtZW50TmFtZTogdW5pcXVlTmFtZSB9LFxuICAgIH07XG4gIH1cblxuICByZXR1cm4geyBkb2N1bWVudE5vZGUsIG5ld0RlZmluaXRpb246IGN1cnJlbnREZWZpbml0aW9uIH07XG59O1xuXG5jb25zdCB0cmFuc2Zvcm1GcmFnbWVudERlZmluaXRpb24gPSAocGFyYW1zOiB7XG4gIHRhcmdldEZyYWdtZW50RGVmaW5pdGlvbjogRnJhZ21lbnREZWZpbml0aW9uTm9kZTtcbiAgb3BlcmF0aW9uRGVmaW5pdGlvbjogT3BlcmF0aW9uRGVmaW5pdGlvbk5vZGU7XG4gIGRvY3VtZW50Tm9kZTogRG9jdW1lbnROb2RlO1xuICBmcmFnbWVudERlZmluaXRpb25zOiBGcmFnbWVudERlZmluaXRpb25Ob2RlW107XG4gIG9wZXJhdGlvbkluZm9MaXN0OiBPcGVyYXRpb25JbmZvW107XG59KToge1xuICBkb2N1bWVudE5vZGU6IERvY3VtZW50Tm9kZTtcbiAgY2hhbmdlZD86IHsgZnJhZ21lbnROYW1lOiBzdHJpbmcgfTtcbn0gPT4ge1xuICBjb25zdCB7IG9wZXJhdGlvbkluZm9MaXN0LCBvcGVyYXRpb25EZWZpbml0aW9uIH0gPSBwYXJhbXM7XG5cbiAgbGV0IGRvY3VtZW50Tm9kZSA9IHBhcmFtcy5kb2N1bWVudE5vZGU7XG4gIGxldCBjdXJyZW50RnJhZ21lbnREZWZpbml0aW9uID0gcGFyYW1zLnRhcmdldEZyYWdtZW50RGVmaW5pdGlvbjtcbiAgY29uc3QgdHJhbnNmb3JtUmVzdWx0ID0gdHJhbnNmb3JtRnJhZ21lbnRTcHJlYWRGaWVsZHMoe1xuICAgIHRhcmdldERlZmluaXRpb246IGN1cnJlbnRGcmFnbWVudERlZmluaXRpb24sXG4gICAgb3BlcmF0aW9uRGVmaW5pdGlvbixcbiAgICBkb2N1bWVudE5vZGU6IGRvY3VtZW50Tm9kZSxcbiAgICBmcmFnbWVudERlZmluaXRpb25zOiBwYXJhbXMuZnJhZ21lbnREZWZpbml0aW9ucyxcbiAgICBvcGVyYXRpb25JbmZvTGlzdCxcbiAgfSk7XG4gIGRvY3VtZW50Tm9kZSA9IHRyYW5zZm9ybVJlc3VsdC5kb2N1bWVudE5vZGU7XG4gIGN1cnJlbnRGcmFnbWVudERlZmluaXRpb24gPSB0cmFuc2Zvcm1SZXN1bHQubmV3RGVmaW5pdGlvbjtcblxuICBsZXQgYXJndW1lbnREZWZpbml0aW9uRGF0YUxpc3Q6IEFyZ3VtZW50RGVmaW5pdGlvbkRhdGFbXSA9IFtdO1xuICB2aXNpdChjdXJyZW50RnJhZ21lbnREZWZpbml0aW9uLCB7XG4gICAgRGlyZWN0aXZlOiB7XG4gICAgICBsZWF2ZShub2RlKSB7XG4gICAgICAgIGlmIChub2RlLm5hbWUudmFsdWUgIT09IEFSR1VNRU5UX0RFRklOSVRJT05TX0RJUkVDVElWRV9OQU1FKSByZXR1cm47XG4gICAgICAgIGFyZ3VtZW50RGVmaW5pdGlvbkRhdGFMaXN0ID0gZ2V0QXJndW1lbnREZWZpbml0aW9uRGF0YUxpc3Qobm9kZSk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH0sXG4gICAgfSxcbiAgfSk7XG5cbiAgY29uc3QgdmFyaWFibGVOYW1lczogc3RyaW5nW10gPSBbXTtcblxuICB2aXNpdChjdXJyZW50RnJhZ21lbnREZWZpbml0aW9uLCB7XG4gICAgVmFyaWFibGU6IHtcbiAgICAgIGxlYXZlKG5vZGUpIHtcbiAgICAgICAgY29uc3QgdmFyaWFibGVOYW1lID0gbm9kZS5uYW1lLnZhbHVlO1xuICAgICAgICBjb25zdCBhcmd1bWVudERlZmluaXRpb25EYXRhID0gYXJndW1lbnREZWZpbml0aW9uRGF0YUxpc3QuZmluZCgoZGF0YSkgPT4gZGF0YS5uYW1lLnZhbHVlID09PSB2YXJpYWJsZU5hbWUpO1xuICAgICAgICBpZiAoIWFyZ3VtZW50RGVmaW5pdGlvbkRhdGEpIHJldHVybjtcblxuICAgICAgICBjb25zdCB2YXJpYWJsZURlZmluaXRpb25zID0gb3BlcmF0aW9uRGVmaW5pdGlvbi52YXJpYWJsZURlZmluaXRpb25zO1xuICAgICAgICBpZiAoIXZhcmlhYmxlRGVmaW5pdGlvbnMpIHJldHVybjtcbiAgICAgICAgY29uc3QgZXhpc3RzSW5PcGVyYXRpb25WYXJpYWJsZSA9ICEhdmFyaWFibGVEZWZpbml0aW9ucy5maW5kKFxuICAgICAgICAgICh2YXJpYWJsZURlZmluaXRpb24pID0+IHZhcmlhYmxlRGVmaW5pdGlvbi52YXJpYWJsZS5uYW1lLnZhbHVlID09PSB2YXJpYWJsZU5hbWUsXG4gICAgICAgICk7XG4gICAgICAgIGlmICghZXhpc3RzSW5PcGVyYXRpb25WYXJpYWJsZSkgcmV0dXJuO1xuXG4gICAgICAgIC8vIElmIHRoZXJlIGlzIGEgb3BlcmF0aW9uIHRoYXQgdXNlcyB0aGUgc2FtZSBmcmFnbWVudCBkZWZpbml0aW9uIGJ1dCB2YXJpYWJsZSBkb2VzIG5vdCBleGlzdCxcbiAgICAgICAgLy8gICBpdCBpcyBzdWJqZWN0IHRvIGNvcHlpbmcgYmVjYXVzZSBpdCBpcyBhIGRpZmZlcmVudCBkZWZpbml0aW9uIG9mIGZyYWdtZW50LlxuICAgICAgICBjb25zdCBjb21wYXJlID0gKGluZm86IE9wZXJhdGlvbkluZm8sIGZyYWdtZW50TmFtZTogc3RyaW5nKSA9PlxuICAgICAgICAgIGluZm8uYmVsb25nc0ZyYWdtZW50TmFtZXMuZmluZCgobmFtZSkgPT4gbmFtZSA9PT0gZnJhZ21lbnROYW1lKSAmJlxuICAgICAgICAgIGluZm8udmFyaWFibGVOYW1lcy5maW5kKChuYW1lKSA9PiBuYW1lID09PSB2YXJpYWJsZU5hbWUpO1xuICAgICAgICBjb25zdCBvcGVyYXRpb25JbmZvTGlzdFdpdGhOb3RJbmNsdWRpbmdWYXJpYWJsZSA9IG9wZXJhdGlvbkluZm9MaXN0LmZpbHRlcihcbiAgICAgICAgICAoaW5mbykgPT4gIWNvbXBhcmUoaW5mbywgY3VycmVudEZyYWdtZW50RGVmaW5pdGlvbi5uYW1lLnZhbHVlKSxcbiAgICAgICAgKTtcbiAgICAgICAgaWYgKG9wZXJhdGlvbkluZm9MaXN0V2l0aE5vdEluY2x1ZGluZ1ZhcmlhYmxlLmxlbmd0aCA9PT0gMCkgcmV0dXJuO1xuXG4gICAgICAgIHZhcmlhYmxlTmFtZXMucHVzaCh2YXJpYWJsZU5hbWUpO1xuXG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH0sXG4gICAgfSxcbiAgfSk7XG5cbiAgaWYgKHZhcmlhYmxlTmFtZXMubGVuZ3RoID09PSAwKSByZXR1cm4geyBkb2N1bWVudE5vZGUsIGNoYW5nZWQ6IHRyYW5zZm9ybVJlc3VsdC5jaGFuZ2VkIH07XG5cbiAgY29uc3QgdW5pcXVlRnJhZ21lbnROYW1lID0gZ2V0VW5pcXVlRnJhZ21lbnROYW1lKFxuICAgIGN1cnJlbnRGcmFnbWVudERlZmluaXRpb24ubmFtZS52YWx1ZSxcbiAgICBgJHtGUkFHTUVOVF9OQU1FX0lORk9fSURfM30sJHt2YXJpYWJsZU5hbWVzLmpvaW4oJywnKX1gLFxuICApO1xuICBjb25zdCBjb3BpZWRGcmFnbWVudERlZmluaXRpb246IEZyYWdtZW50RGVmaW5pdGlvbk5vZGUgPSB7XG4gICAgLi4uY3VycmVudEZyYWdtZW50RGVmaW5pdGlvbixcbiAgICBuYW1lOiB7IC4uLmN1cnJlbnRGcmFnbWVudERlZmluaXRpb24ubmFtZSwgdmFsdWU6IHVuaXF1ZUZyYWdtZW50TmFtZSB9LFxuICB9O1xuICBkb2N1bWVudE5vZGUgPSB7XG4gICAgLi4uZG9jdW1lbnROb2RlLFxuICAgIGRlZmluaXRpb25zOiBbLi4uZG9jdW1lbnROb2RlLmRlZmluaXRpb25zLCBjb3BpZWRGcmFnbWVudERlZmluaXRpb25dLFxuICB9O1xuXG4gIHJldHVybiB7IGRvY3VtZW50Tm9kZSwgY2hhbmdlZDogeyBmcmFnbWVudE5hbWU6IHVuaXF1ZUZyYWdtZW50TmFtZSB9IH07XG59O1xuXG5jb25zdCBmaXhWYXJpYWJsZXMgPSAoe1xuICBkb2N1bWVudE5vZGUsXG4gIG9wZXJhdGlvbkluZm9MaXN0LFxufToge1xuICBkb2N1bWVudE5vZGU6IERvY3VtZW50Tm9kZTtcbiAgb3BlcmF0aW9uSW5mb0xpc3Q6IE9wZXJhdGlvbkluZm9bXTtcbn0pOiBEb2N1bWVudE5vZGUgPT4ge1xuICByZXR1cm4gdmlzaXQoZG9jdW1lbnROb2RlLCB7XG4gICAgRnJhZ21lbnREZWZpbml0aW9uOiB7XG4gICAgICBsZWF2ZShmcmFnbWVudERlZmluaXRpb24pIHtcbiAgICAgICAgbGV0IGFyZ3VtZW50RGVmaW5pdGlvbkRhdGFMaXN0OiBBcmd1bWVudERlZmluaXRpb25EYXRhW10gPSBbXTtcbiAgICAgICAgdmlzaXQoZnJhZ21lbnREZWZpbml0aW9uLCB7XG4gICAgICAgICAgRGlyZWN0aXZlOiB7XG4gICAgICAgICAgICBsZWF2ZShub2RlKSB7XG4gICAgICAgICAgICAgIGlmIChub2RlLm5hbWUudmFsdWUgIT09IEFSR1VNRU5UX0RFRklOSVRJT05TX0RJUkVDVElWRV9OQU1FKSByZXR1cm47XG4gICAgICAgICAgICAgIGFyZ3VtZW50RGVmaW5pdGlvbkRhdGFMaXN0ID0gZ2V0QXJndW1lbnREZWZpbml0aW9uRGF0YUxpc3Qobm9kZSk7XG4gICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgfSxcbiAgICAgICAgfSk7XG4gICAgICAgIGlmIChhcmd1bWVudERlZmluaXRpb25EYXRhTGlzdC5sZW5ndGggPT09IDApIHJldHVybjtcblxuICAgICAgICByZXR1cm4gdmlzaXQoZnJhZ21lbnREZWZpbml0aW9uLCB7XG4gICAgICAgICAgVmFyaWFibGU6IHtcbiAgICAgICAgICAgIGxlYXZlKHZhcmlhYmxlTm9kZSkge1xuICAgICAgICAgICAgICAvLyBGaW5kIHdpdGggb3BlcmF0aW9uSW5mb0xpc3QgYmVjYXVzZSB0aGVyZSBtYXkgYmUgbW9yZSB0aGFuIG9uZSBvcGVyYXRpb24gZGVmaW5pdGlvbiBpbiBkb2N1bWVudE5vZGVcbiAgICAgICAgICAgICAgY29uc3QgZXhpc3RzSW5WYXJpYWJsZSA9IGV4aXN0c1ZhcmlhYmxlKHtcbiAgICAgICAgICAgICAgICB2YXJpYWJsZU5hbWU6IHZhcmlhYmxlTm9kZS5uYW1lLnZhbHVlLFxuICAgICAgICAgICAgICAgIGZyYWdtZW50TmFtZTogZnJhZ21lbnREZWZpbml0aW9uLm5hbWUudmFsdWUsXG4gICAgICAgICAgICAgICAgb3BlcmF0aW9uSW5mb0xpc3QsXG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICBpZiAoZXhpc3RzSW5WYXJpYWJsZSkgcmV0dXJuO1xuXG4gICAgICAgICAgICAgIGNvbnN0IGFyZ3VtZW50RGVmaW5pdGlvbkRhdGEgPSBhcmd1bWVudERlZmluaXRpb25EYXRhTGlzdC5maW5kKFxuICAgICAgICAgICAgICAgIChkYXRhKSA9PiBkYXRhLm5hbWUudmFsdWUgPT09IHZhcmlhYmxlTm9kZS5uYW1lLnZhbHVlLFxuICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICBpZiAoIWFyZ3VtZW50RGVmaW5pdGlvbkRhdGEpIHJldHVybjtcblxuICAgICAgICAgICAgICBpZiAoYXJndW1lbnREZWZpbml0aW9uRGF0YS5kZWZhdWx0VmFsdWUpIHtcbiAgICAgICAgICAgICAgICAvLyBSZXBsYWNlIHdpdGggZGVmYXVsdCB2YWx1ZVxuICAgICAgICAgICAgICAgIHJldHVybiB7IC4uLmFyZ3VtZW50RGVmaW5pdGlvbkRhdGEuZGVmYXVsdFZhbHVlIH07XG4gICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICBpZiAoYXJndW1lbnREZWZpbml0aW9uRGF0YS50eXBlLmtpbmQgIT09ICdOb25OdWxsVHlwZScpIHtcbiAgICAgICAgICAgICAgICAvLyBSZXBsYWNlIHdpdGggbnVsbCB2YWx1ZVxuICAgICAgICAgICAgICAgIGNvbnN0IG51bGxWYWx1ZU5vZGU6IE51bGxWYWx1ZU5vZGUgPSB7IGtpbmQ6IEtpbmQuTlVMTCB9O1xuICAgICAgICAgICAgICAgIHJldHVybiBudWxsVmFsdWVOb2RlO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH0sXG4gICAgICAgIH0pO1xuICAgICAgfSxcbiAgICB9LFxuICB9KTtcbn07XG5cbmNvbnN0IGdldE9wZXJhdGlvbkluZm9MaXN0ID0gKHsgZG9jdW1lbnRGaWxlcyB9OiB7IGRvY3VtZW50RmlsZXM6IFR5cGVzLkRvY3VtZW50RmlsZVtdIH0pOiBPcGVyYXRpb25JbmZvW10gPT4ge1xuICBjb25zdCBmcmFnbWVudERlZmluaXRpb25zID0gZ2V0RnJhZ21lbnREZWZpbml0aW9uc0J5RG9jdW1lbnRGaWxlcyhkb2N1bWVudEZpbGVzKTtcbiAgY29uc3QgbmFtZXNQYWlyczogT3BlcmF0aW9uSW5mb1tdID0gW107XG4gIGRvY3VtZW50RmlsZXMubWFwKChmaWxlKSA9PiB7XG4gICAgaWYgKCFmaWxlLmRvY3VtZW50KSByZXR1cm4gZmlsZTtcbiAgICBjb25zdCBvcGVyYXRpb25EZWZpbml0aW9ucyA9IGdldE9wZXJhdGlvbkRlZmluaXRpb25zKGZpbGUuZG9jdW1lbnQpO1xuICAgIG9wZXJhdGlvbkRlZmluaXRpb25zLmZvckVhY2goKG9wZXJhdGlvbkRlZmluaXRpb24pID0+IHtcbiAgICAgIGlmICghb3BlcmF0aW9uRGVmaW5pdGlvbi52YXJpYWJsZURlZmluaXRpb25zKSByZXR1cm47XG5cbiAgICAgIGNvbnN0IGZyYWdtZW50TmFtZXMgPSBnZXRGcmFnbWVudE5hbWVzKHtcbiAgICAgICAgdGFyZ2V0RGVmaW5pdGlvbjogb3BlcmF0aW9uRGVmaW5pdGlvbixcbiAgICAgICAgZnJhZ21lbnREZWZpbml0aW9ucyxcbiAgICAgICAgZnJhZ21lbnROYW1lczogW10sXG4gICAgICB9KTtcblxuICAgICAgY29uc3QgdmFyaWFibGVOYW1lcyA9IG9wZXJhdGlvbkRlZmluaXRpb24udmFyaWFibGVEZWZpbml0aW9ucy5tYXAoXG4gICAgICAgICh2YXJpYWJsZURlZmluaXRpb24pID0+IHZhcmlhYmxlRGVmaW5pdGlvbi52YXJpYWJsZS5uYW1lLnZhbHVlLFxuICAgICAgKTtcblxuICAgICAgbmFtZXNQYWlycy5wdXNoKHtcbiAgICAgICAgb3BlcmF0aW9uTmFtZTogb3BlcmF0aW9uRGVmaW5pdGlvbi5uYW1lPy52YWx1ZSxcbiAgICAgICAgdmFyaWFibGVOYW1lcyxcbiAgICAgICAgYmVsb25nc0ZyYWdtZW50TmFtZXM6IGZyYWdtZW50TmFtZXMsXG4gICAgICB9KTtcbiAgICB9KTtcbiAgfSk7XG4gIHJldHVybiBuYW1lc1BhaXJzO1xufTtcblxuY29uc3QgZ2V0RnJhZ21lbnROYW1lcyA9IDxURGVmaW5pdGlvbk5vZGUgZXh0ZW5kcyBBU1ROb2RlPih7XG4gIHRhcmdldERlZmluaXRpb24sXG4gIGZyYWdtZW50RGVmaW5pdGlvbnMsXG4gIGZyYWdtZW50TmFtZXMsXG59OiB7XG4gIHRhcmdldERlZmluaXRpb246IFREZWZpbml0aW9uTm9kZTtcbiAgZnJhZ21lbnREZWZpbml0aW9uczogRnJhZ21lbnREZWZpbml0aW9uTm9kZVtdO1xuICBmcmFnbWVudE5hbWVzOiBzdHJpbmdbXTtcbn0pOiBzdHJpbmdbXSA9PiB7XG4gIHZpc2l0KHRhcmdldERlZmluaXRpb24sIHtcbiAgICBGcmFnbWVudFNwcmVhZDoge1xuICAgICAgZW50ZXIobm9kZSkge1xuICAgICAgICBjb25zdCBuZXh0RnJhZ21lbnROYW1lID0gbm9kZS5uYW1lLnZhbHVlO1xuICAgICAgICBjb25zdCBuZXh0ID0gZ2V0RnJhZ21lbnREZWZpbml0aW9uQnlOYW1lKHsgZnJhZ21lbnREZWZpbml0aW9ucywgZnJhZ21lbnROYW1lOiBub2RlLm5hbWUudmFsdWUgfSk7XG4gICAgICAgIGlmICghbmV4dCkgcmV0dXJuO1xuXG4gICAgICAgIGZyYWdtZW50TmFtZXMucHVzaChuZXh0RnJhZ21lbnROYW1lKTtcblxuICAgICAgICBnZXRGcmFnbWVudE5hbWVzKHtcbiAgICAgICAgICB0YXJnZXREZWZpbml0aW9uOiBuZXh0LFxuICAgICAgICAgIGZyYWdtZW50RGVmaW5pdGlvbnMsXG4gICAgICAgICAgZnJhZ21lbnROYW1lcyxcbiAgICAgICAgfSk7XG4gICAgICB9LFxuICAgIH0sXG4gIH0pO1xuICByZXR1cm4gZnJhZ21lbnROYW1lcztcbn07XG5cbmNvbnN0IGV4aXN0c1ZhcmlhYmxlID0gKHtcbiAgdmFyaWFibGVOYW1lLFxuICBmcmFnbWVudE5hbWUsXG4gIG9wZXJhdGlvbkluZm9MaXN0LFxufToge1xuICB2YXJpYWJsZU5hbWU6IHN0cmluZztcbiAgZnJhZ21lbnROYW1lOiBzdHJpbmc7XG4gIG9wZXJhdGlvbkluZm9MaXN0OiBPcGVyYXRpb25JbmZvW107XG59KSA9PiB7XG4gIGNvbnN0IG9wZXJhdGlvbkluZm8gPSBvcGVyYXRpb25JbmZvTGlzdC5maW5kKChpbmZvKSA9PlxuICAgIGluZm8uYmVsb25nc0ZyYWdtZW50TmFtZXMuZmluZCgobmFtZSkgPT4gbmFtZSA9PT0gZnJhZ21lbnROYW1lKSxcbiAgKTtcbiAgaWYgKCFvcGVyYXRpb25JbmZvKSByZXR1cm4gZmFsc2U7XG5cbiAgcmV0dXJuICEhb3BlcmF0aW9uSW5mby52YXJpYWJsZU5hbWVzLmZpbmQoKG5hbWUpID0+IHZhcmlhYmxlTmFtZSA9PT0gbmFtZSk7XG59O1xuXG5leHBvcnQgY29uc3QgZXhwb3J0ZWRGb3JUZXN0aW5nID0ge1xuICBnZXRPcGVyYXRpb25JbmZvTGlzdCxcbn07XG4iXSwibWFwcGluZ3MiOiI7Ozs7OztBQUNBO0FBQ0E7QUFTQTtBQUtBO0FBS2dCO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQVFULElBQU1BLFNBQVMsR0FBRyxTQUFaQSxTQUFTLE9BSXlCO0VBQUEsSUFIN0NDLGFBQWEsUUFBYkEsYUFBYTtFQUliLElBQU1DLG1CQUFtQixHQUFHLElBQUFDLGlEQUFxQyxFQUFDRixhQUFhLENBQUM7RUFFaEYsSUFBSUcsaUJBQWlCLEdBQUdDLG9CQUFvQixDQUFDO0lBQUVKLGFBQWEsRUFBYkE7RUFBYyxDQUFDLENBQUM7RUFFL0QsSUFBSUssS0FBSyxHQUFHTCxhQUFhLENBQUNNLEdBQUcsQ0FBQyxVQUFDQyxJQUFJLEVBQUs7SUFDdEMsSUFBSSxDQUFDQSxJQUFJLENBQUNDLFFBQVEsRUFBRSxPQUFPRCxJQUFJO0lBQy9CLElBQU1FLE1BQU0sR0FBR0MsYUFBYSxDQUFDO01BQzNCQyxZQUFZLEVBQUVKLElBQUksQ0FBQ0MsUUFBUTtNQUMzQlAsbUJBQW1CLEVBQW5CQSxtQkFBbUI7TUFDbkJFLGlCQUFpQixFQUFqQkE7SUFDRixDQUFDLENBQUM7SUFDRkksSUFBSSxDQUFDQyxRQUFRLEdBQUdDLE1BQU0sQ0FBQ0UsWUFBWTtJQUNuQyxPQUFPSixJQUFJO0VBQ2IsQ0FBQyxDQUFDO0VBRUZKLGlCQUFpQixHQUFHQyxvQkFBb0IsQ0FBQztJQUFFSixhQUFhLEVBQUVLO0VBQU0sQ0FBQyxDQUFDO0VBQ2xFLElBQUlGLGlCQUFpQixDQUFDUyxNQUFNLEtBQUssQ0FBQyxFQUFFLE9BQU87SUFBRVosYUFBYSxFQUFFSztFQUFNLENBQUM7RUFFbkVBLEtBQUssR0FBR0wsYUFBYSxDQUFDTSxHQUFHLENBQUMsVUFBQ0MsSUFBSSxFQUFLO0lBQ2xDLElBQUksQ0FBQ0EsSUFBSSxDQUFDQyxRQUFRLEVBQUUsT0FBT0QsSUFBSTtJQUMvQkEsSUFBSSxDQUFDQyxRQUFRLEdBQUdLLFlBQVksQ0FBQztNQUFFRixZQUFZLEVBQUVKLElBQUksQ0FBQ0MsUUFBUTtNQUFFTCxpQkFBaUIsRUFBakJBO0lBQWtCLENBQUMsQ0FBQztJQUNoRixPQUFPSSxJQUFJO0VBQ2IsQ0FBQyxDQUFDO0VBQ0YsT0FBTztJQUFFUCxhQUFhLEVBQUVLO0VBQU0sQ0FBQztBQUNqQyxDQUFDOztBQUVEO0FBQUE7QUFDQSxJQUFNSyxhQUFhLEdBQUcsU0FBaEJBLGFBQWEsQ0FBSUksTUFJdEIsRUFBcUM7RUFDcEMsSUFBUWIsbUJBQW1CLEdBQXdCYSxNQUFNLENBQWpEYixtQkFBbUI7SUFBRUUsaUJBQWlCLEdBQUtXLE1BQU0sQ0FBNUJYLGlCQUFpQjtFQUM5QyxJQUFJUSxZQUFZLEdBQUdHLE1BQU0sQ0FBQ0gsWUFBWTtFQUN0QyxJQUFNSSxvQkFBb0IsR0FBRyxJQUFBQyxtQ0FBdUIsRUFBQ0wsWUFBWSxDQUFDO0VBQ2xFLElBQUksQ0FBQ0ksb0JBQW9CLEVBQUUsT0FBTztJQUFFSixZQUFZLEVBQVpBO0VBQWEsQ0FBQztFQUVsRCxJQUFNTSwyQkFBc0QsR0FBRyxFQUFFO0VBQ2pFRixvQkFBb0IsQ0FBQ0csT0FBTyxDQUFDLFVBQUNDLG1CQUFtQixFQUFLO0lBQ3BELElBQU1DLGVBQWUsR0FBR0MsNkJBQTZCLENBQUM7TUFDcERDLGdCQUFnQixFQUFFSCxtQkFBbUI7TUFDckNBLG1CQUFtQixFQUFuQkEsbUJBQW1CO01BQ25CUixZQUFZLEVBQUVBLFlBQVk7TUFDMUJWLG1CQUFtQixFQUFuQkEsbUJBQW1CO01BQ25CRSxpQkFBaUIsRUFBakJBO0lBQ0YsQ0FBQyxDQUFDO0lBQ0ZjLDJCQUEyQixDQUFDTSxJQUFJLENBQUNILGVBQWUsQ0FBQ0ksYUFBYSxDQUFDO0lBQy9EYixZQUFZLEdBQUdTLGVBQWUsQ0FBQ1QsWUFBWTtFQUM3QyxDQUFDLENBQUM7RUFFRixPQUFPO0lBQ0xBLFlBQVksa0NBQ1BBLFlBQVk7TUFDZmMsV0FBVyxZQUNOUiwyQkFBMkIscUJBQzNCTixZQUFZLENBQUNjLFdBQVcsQ0FBQ0MsTUFBTSxDQUFDLFVBQUNDLFVBQVU7UUFBQSxPQUFLQSxVQUFVLENBQUNDLElBQUksS0FBSyxxQkFBcUI7TUFBQSxFQUFDO0lBQzlGO0VBRUwsQ0FBQztBQUNILENBQUM7QUFFRCxJQUFNUCw2QkFBNkIsR0FBRyxTQUFoQ0EsNkJBQTZCLENBRWpDUCxNQU1ELEVBSUk7RUFDSCxJQUFRUSxnQkFBZ0IsR0FBa0VSLE1BQU0sQ0FBeEZRLGdCQUFnQjtJQUFFckIsbUJBQW1CLEdBQTZDYSxNQUFNLENBQXRFYixtQkFBbUI7SUFBRUUsaUJBQWlCLEdBQTBCVyxNQUFNLENBQWpEWCxpQkFBaUI7SUFBRWdCLG1CQUFtQixHQUFLTCxNQUFNLENBQTlCSyxtQkFBbUI7RUFDckYsSUFBSVIsWUFBWSxHQUFHRyxNQUFNLENBQUNILFlBQVk7RUFDdEMsSUFBTWtCLE1BQWdCLEdBQUcsRUFBRTtFQUMzQixJQUFNQyxpQkFBaUIsR0FBRyxJQUFBQyxjQUFLLEVBQUNULGdCQUFnQixFQUFFO0lBQ2hEVSxjQUFjLEVBQUU7TUFDZEMsS0FBSyxpQkFBQ0MsWUFBWSxFQUFFO1FBQ2xCLElBQU1DLG9CQUFvQixHQUFHRCxZQUFZLENBQUNFLElBQUksQ0FBQ0MsS0FBSztRQUNwRCxJQUFNQyw0QkFBNEIsR0FBRyxJQUFBQyx1Q0FBMkIsRUFBQztVQUMvRHRDLG1CQUFtQixFQUFuQkEsbUJBQW1CO1VBQ25CdUMsWUFBWSxFQUFFTDtRQUNoQixDQUFDLENBQUM7UUFDRixJQUFJLENBQUNHLDRCQUE0QixFQUFFO1FBRW5DLElBQU03QixNQUFNLEdBQUdnQywyQkFBMkIsQ0FBQztVQUN6Q0Msd0JBQXdCLEVBQUVKLDRCQUE0QjtVQUN0RDNCLFlBQVksRUFBRUEsWUFBWTtVQUMxQlEsbUJBQW1CLEVBQUVMLE1BQU0sQ0FBQ0ssbUJBQW1CO1VBQy9DbEIsbUJBQW1CLEVBQW5CQSxtQkFBbUI7VUFDbkJFLGlCQUFpQixFQUFqQkE7UUFDRixDQUFDLENBQUM7UUFDRlEsWUFBWSxHQUFHRixNQUFNLENBQUNFLFlBQVk7UUFDbEMsSUFBSSxDQUFDRixNQUFNLENBQUNrQyxPQUFPLEVBQUU7UUFFckIsSUFBTUMsK0JBQStCLG1DQUNoQ1YsWUFBWTtVQUNmRSxJQUFJLGtDQUFPRixZQUFZLENBQUNFLElBQUk7WUFBRUMsS0FBSyxFQUFFNUIsTUFBTSxDQUFDa0MsT0FBTyxDQUFDSDtVQUFZO1FBQUUsRUFDbkU7UUFFRCxJQUFJbEIsZ0JBQWdCLENBQUNNLElBQUksS0FBS2lCLGFBQUksQ0FBQ0Msb0JBQW9CLEVBQUU7VUFDdkQsT0FBT0YsK0JBQStCO1FBQ3hDO1FBRUEsSUFBTUcsMEJBQTBCLEdBQUc1QyxpQkFBaUIsQ0FBQzZDLElBQUksQ0FDdkQsVUFBQ0MsSUFBSTtVQUFBO1VBQUEsT0FDSEEsSUFBSSxDQUFDQyxhQUFhLCtCQUFLL0IsbUJBQW1CLENBQUNpQixJQUFJLDBEQUF4QixzQkFBMEJDLEtBQUssS0FDdERZLElBQUksQ0FBQ0Usb0JBQW9CLENBQUNILElBQUksQ0FBQyxVQUFDUixZQUFZO1lBQUEsT0FBS0EsWUFBWSxLQUFLbEIsZ0JBQWdCLENBQUNjLElBQUksQ0FBQ0MsS0FBSztVQUFBLEVBQUM7UUFBQSxFQUNqRztRQUNELElBQUlVLDBCQUEwQixFQUFFO1VBQzlCLElBQU1LLFNBQVMsR0FBRzNDLE1BQU0sQ0FBQ2tDLE9BQU8sQ0FBQ0gsWUFBWSxDQUFDYSxLQUFLLENBQUMsR0FBRyxDQUFDO1VBQ3hEeEIsTUFBTSxDQUFDTixJQUFJLGlCQUFVNkIsU0FBUyxDQUFDQSxTQUFTLENBQUN4QyxNQUFNLEdBQUcsQ0FBQyxDQUFDLEVBQUc7UUFDekQ7UUFFQSxPQUFPZ0MsK0JBQStCO01BQ3hDO0lBQ0Y7RUFDRixDQUFDLENBQUM7RUFFRixJQUFJZixNQUFNLENBQUNqQixNQUFNLEtBQUssQ0FBQyxJQUFJa0IsaUJBQWlCLENBQUNGLElBQUksS0FBS2lCLGFBQUksQ0FBQ1MsbUJBQW1CLEVBQUU7SUFDOUUsSUFBTUMsVUFBVSxHQUFHLElBQUFDLDJCQUFxQixFQUFDMUIsaUJBQWlCLENBQUNNLElBQUksQ0FBQ0MsS0FBSyxFQUFFUixNQUFNLENBQUM0QixJQUFJLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDeEYsSUFBTWpDLGFBQXFDLG1DQUN0Q00saUJBQWlCO01BQ3BCTSxJQUFJLGtDQUFPTixpQkFBaUIsQ0FBQ00sSUFBSTtRQUFFQyxLQUFLLEVBQUVrQjtNQUFVO0lBQUUsRUFDN0I7SUFFM0IsSUFBTUcsTUFBTSxHQUFHLENBQUMsQ0FBQy9DLFlBQVksQ0FBQ2MsV0FBVyxDQUFDdUIsSUFBSSxDQUM1QyxVQUFDckIsVUFBVTtNQUFBLE9BQUtBLFVBQVUsQ0FBQ0MsSUFBSSxLQUFLaUIsYUFBSSxDQUFDUyxtQkFBbUIsSUFBSTNCLFVBQVUsQ0FBQ1MsSUFBSSxDQUFDQyxLQUFLLEtBQUtrQixVQUFVO0lBQUEsRUFDckc7SUFDRCxJQUFJLENBQUNHLE1BQU0sRUFBRTtNQUNYL0MsWUFBWSxtQ0FDUEEsWUFBWTtRQUNmYyxXQUFXLCtCQUFNZCxZQUFZLENBQUNjLFdBQVcsSUFBRUQsYUFBYTtNQUFDLEVBQzFEO0lBQ0g7SUFDQSxPQUFPO01BQ0xiLFlBQVksRUFBWkEsWUFBWTtNQUNaYSxhQUFhLEVBQUVBLGFBQWdDO01BQy9DbUIsT0FBTyxFQUFFO1FBQUVILFlBQVksRUFBRWU7TUFBVztJQUN0QyxDQUFDO0VBQ0g7RUFFQSxPQUFPO0lBQUU1QyxZQUFZLEVBQVpBLFlBQVk7SUFBRWEsYUFBYSxFQUFFTTtFQUFrQixDQUFDO0FBQzNELENBQUM7QUFFRCxJQUFNVywyQkFBMkIsR0FBRyxTQUE5QkEsMkJBQTJCLENBQUkzQixNQU1wQyxFQUdJO0VBQ0gsSUFBUVgsaUJBQWlCLEdBQTBCVyxNQUFNLENBQWpEWCxpQkFBaUI7SUFBRWdCLG1CQUFtQixHQUFLTCxNQUFNLENBQTlCSyxtQkFBbUI7RUFFOUMsSUFBSVIsWUFBWSxHQUFHRyxNQUFNLENBQUNILFlBQVk7RUFDdEMsSUFBSWdELHlCQUF5QixHQUFHN0MsTUFBTSxDQUFDNEIsd0JBQXdCO0VBQy9ELElBQU10QixlQUFlLEdBQUdDLDZCQUE2QixDQUFDO0lBQ3BEQyxnQkFBZ0IsRUFBRXFDLHlCQUF5QjtJQUMzQ3hDLG1CQUFtQixFQUFuQkEsbUJBQW1CO0lBQ25CUixZQUFZLEVBQUVBLFlBQVk7SUFDMUJWLG1CQUFtQixFQUFFYSxNQUFNLENBQUNiLG1CQUFtQjtJQUMvQ0UsaUJBQWlCLEVBQWpCQTtFQUNGLENBQUMsQ0FBQztFQUNGUSxZQUFZLEdBQUdTLGVBQWUsQ0FBQ1QsWUFBWTtFQUMzQ2dELHlCQUF5QixHQUFHdkMsZUFBZSxDQUFDSSxhQUFhO0VBRXpELElBQUlvQywwQkFBb0QsR0FBRyxFQUFFO0VBQzdELElBQUE3QixjQUFLLEVBQUM0Qix5QkFBeUIsRUFBRTtJQUMvQkUsU0FBUyxFQUFFO01BQ1Q1QixLQUFLLGlCQUFDNkIsSUFBSSxFQUFFO1FBQ1YsSUFBSUEsSUFBSSxDQUFDMUIsSUFBSSxDQUFDQyxLQUFLLEtBQUswQix3Q0FBbUMsRUFBRTtRQUM3REgsMEJBQTBCLEdBQUcsSUFBQUksbUNBQTZCLEVBQUNGLElBQUksQ0FBQztRQUNoRTtNQUNGO0lBQ0Y7RUFDRixDQUFDLENBQUM7RUFFRixJQUFNRyxhQUF1QixHQUFHLEVBQUU7RUFFbEMsSUFBQWxDLGNBQUssRUFBQzRCLHlCQUF5QixFQUFFO0lBQy9CTyxRQUFRLEVBQUU7TUFDUmpDLEtBQUssaUJBQUM2QixJQUFJLEVBQUU7UUFDVixJQUFNSyxZQUFZLEdBQUdMLElBQUksQ0FBQzFCLElBQUksQ0FBQ0MsS0FBSztRQUNwQyxJQUFNK0Isc0JBQXNCLEdBQUdSLDBCQUEwQixDQUFDWixJQUFJLENBQUMsVUFBQ3FCLElBQUk7VUFBQSxPQUFLQSxJQUFJLENBQUNqQyxJQUFJLENBQUNDLEtBQUssS0FBSzhCLFlBQVk7UUFBQSxFQUFDO1FBQzFHLElBQUksQ0FBQ0Msc0JBQXNCLEVBQUU7UUFFN0IsSUFBTUUsbUJBQW1CLEdBQUduRCxtQkFBbUIsQ0FBQ21ELG1CQUFtQjtRQUNuRSxJQUFJLENBQUNBLG1CQUFtQixFQUFFO1FBQzFCLElBQU1DLHlCQUF5QixHQUFHLENBQUMsQ0FBQ0QsbUJBQW1CLENBQUN0QixJQUFJLENBQzFELFVBQUN3QixrQkFBa0I7VUFBQSxPQUFLQSxrQkFBa0IsQ0FBQ0MsUUFBUSxDQUFDckMsSUFBSSxDQUFDQyxLQUFLLEtBQUs4QixZQUFZO1FBQUEsRUFDaEY7UUFDRCxJQUFJLENBQUNJLHlCQUF5QixFQUFFOztRQUVoQztRQUNBO1FBQ0EsSUFBTUcsT0FBTyxHQUFHLFNBQVZBLE9BQU8sQ0FBSXpCLElBQW1CLEVBQUVULFlBQW9CO1VBQUEsT0FDeERTLElBQUksQ0FBQ0Usb0JBQW9CLENBQUNILElBQUksQ0FBQyxVQUFDWixJQUFJO1lBQUEsT0FBS0EsSUFBSSxLQUFLSSxZQUFZO1VBQUEsRUFBQyxJQUMvRFMsSUFBSSxDQUFDZ0IsYUFBYSxDQUFDakIsSUFBSSxDQUFDLFVBQUNaLElBQUk7WUFBQSxPQUFLQSxJQUFJLEtBQUsrQixZQUFZO1VBQUEsRUFBQztRQUFBO1FBQzFELElBQU1RLHlDQUF5QyxHQUFHeEUsaUJBQWlCLENBQUN1QixNQUFNLENBQ3hFLFVBQUN1QixJQUFJO1VBQUEsT0FBSyxDQUFDeUIsT0FBTyxDQUFDekIsSUFBSSxFQUFFVSx5QkFBeUIsQ0FBQ3ZCLElBQUksQ0FBQ0MsS0FBSyxDQUFDO1FBQUEsRUFDL0Q7UUFDRCxJQUFJc0MseUNBQXlDLENBQUMvRCxNQUFNLEtBQUssQ0FBQyxFQUFFO1FBRTVEcUQsYUFBYSxDQUFDMUMsSUFBSSxDQUFDNEMsWUFBWSxDQUFDO1FBRWhDLE9BQU8sS0FBSztNQUNkO0lBQ0Y7RUFDRixDQUFDLENBQUM7RUFFRixJQUFJRixhQUFhLENBQUNyRCxNQUFNLEtBQUssQ0FBQyxFQUFFLE9BQU87SUFBRUQsWUFBWSxFQUFaQSxZQUFZO0lBQUVnQyxPQUFPLEVBQUV2QixlQUFlLENBQUN1QjtFQUFRLENBQUM7RUFFekYsSUFBTWlDLGtCQUFrQixHQUFHLElBQUFwQiwyQkFBcUIsRUFDOUNHLHlCQUF5QixDQUFDdkIsSUFBSSxDQUFDQyxLQUFLLFlBQ2pDd0MsNkJBQXVCLGNBQUlaLGFBQWEsQ0FBQ1IsSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUN0RDtFQUNELElBQU1xQix3QkFBZ0QsbUNBQ2pEbkIseUJBQXlCO0lBQzVCdkIsSUFBSSxrQ0FBT3VCLHlCQUF5QixDQUFDdkIsSUFBSTtNQUFFQyxLQUFLLEVBQUV1QztJQUFrQjtFQUFFLEVBQ3ZFO0VBQ0RqRSxZQUFZLG1DQUNQQSxZQUFZO0lBQ2ZjLFdBQVcsK0JBQU1kLFlBQVksQ0FBQ2MsV0FBVyxJQUFFcUQsd0JBQXdCO0VBQUMsRUFDckU7RUFFRCxPQUFPO0lBQUVuRSxZQUFZLEVBQVpBLFlBQVk7SUFBRWdDLE9BQU8sRUFBRTtNQUFFSCxZQUFZLEVBQUVvQztJQUFtQjtFQUFFLENBQUM7QUFDeEUsQ0FBQztBQUVELElBQU0vRCxZQUFZLEdBQUcsU0FBZkEsWUFBWSxRQU1FO0VBQUEsSUFMbEJGLFlBQVksU0FBWkEsWUFBWTtJQUNaUixpQkFBaUIsU0FBakJBLGlCQUFpQjtFQUtqQixPQUFPLElBQUE0QixjQUFLLEVBQUNwQixZQUFZLEVBQUU7SUFDekJvRSxrQkFBa0IsRUFBRTtNQUNsQjlDLEtBQUssaUJBQUMrQyxrQkFBa0IsRUFBRTtRQUN4QixJQUFJcEIsMEJBQW9ELEdBQUcsRUFBRTtRQUM3RCxJQUFBN0IsY0FBSyxFQUFDaUQsa0JBQWtCLEVBQUU7VUFDeEJuQixTQUFTLEVBQUU7WUFDVDVCLEtBQUssaUJBQUM2QixJQUFJLEVBQUU7Y0FDVixJQUFJQSxJQUFJLENBQUMxQixJQUFJLENBQUNDLEtBQUssS0FBSzBCLHdDQUFtQyxFQUFFO2NBQzdESCwwQkFBMEIsR0FBRyxJQUFBSSxtQ0FBNkIsRUFBQ0YsSUFBSSxDQUFDO2NBQ2hFO1lBQ0Y7VUFDRjtRQUNGLENBQUMsQ0FBQztRQUNGLElBQUlGLDBCQUEwQixDQUFDaEQsTUFBTSxLQUFLLENBQUMsRUFBRTtRQUU3QyxPQUFPLElBQUFtQixjQUFLLEVBQUNpRCxrQkFBa0IsRUFBRTtVQUMvQmQsUUFBUSxFQUFFO1lBQ1JqQyxLQUFLLGlCQUFDZ0QsWUFBWSxFQUFFO2NBQ2xCO2NBQ0EsSUFBTUMsZ0JBQWdCLEdBQUdDLGNBQWMsQ0FBQztnQkFDdENoQixZQUFZLEVBQUVjLFlBQVksQ0FBQzdDLElBQUksQ0FBQ0MsS0FBSztnQkFDckNHLFlBQVksRUFBRXdDLGtCQUFrQixDQUFDNUMsSUFBSSxDQUFDQyxLQUFLO2dCQUMzQ2xDLGlCQUFpQixFQUFqQkE7Y0FDRixDQUFDLENBQUM7Y0FDRixJQUFJK0UsZ0JBQWdCLEVBQUU7Y0FFdEIsSUFBTWQsc0JBQXNCLEdBQUdSLDBCQUEwQixDQUFDWixJQUFJLENBQzVELFVBQUNxQixJQUFJO2dCQUFBLE9BQUtBLElBQUksQ0FBQ2pDLElBQUksQ0FBQ0MsS0FBSyxLQUFLNEMsWUFBWSxDQUFDN0MsSUFBSSxDQUFDQyxLQUFLO2NBQUEsRUFDdEQ7Y0FDRCxJQUFJLENBQUMrQixzQkFBc0IsRUFBRTtjQUU3QixJQUFJQSxzQkFBc0IsQ0FBQ2dCLFlBQVksRUFBRTtnQkFDdkM7Z0JBQ0EseUJBQVloQixzQkFBc0IsQ0FBQ2dCLFlBQVk7Y0FDakQ7Y0FFQSxJQUFJaEIsc0JBQXNCLENBQUNpQixJQUFJLENBQUN6RCxJQUFJLEtBQUssYUFBYSxFQUFFO2dCQUN0RDtnQkFDQSxJQUFNMEQsYUFBNEIsR0FBRztrQkFBRTFELElBQUksRUFBRWlCLGFBQUksQ0FBQzBDO2dCQUFLLENBQUM7Z0JBQ3hELE9BQU9ELGFBQWE7Y0FDdEI7WUFDRjtVQUNGO1FBQ0YsQ0FBQyxDQUFDO01BQ0o7SUFDRjtFQUNGLENBQUMsQ0FBQztBQUNKLENBQUM7QUFFRCxJQUFNbEYsb0JBQW9CLEdBQUcsU0FBdkJBLG9CQUFvQixRQUFvRjtFQUFBLElBQTlFSixhQUFhLFNBQWJBLGFBQWE7RUFDM0MsSUFBTUMsbUJBQW1CLEdBQUcsSUFBQUMsaURBQXFDLEVBQUNGLGFBQWEsQ0FBQztFQUNoRixJQUFNd0YsVUFBMkIsR0FBRyxFQUFFO0VBQ3RDeEYsYUFBYSxDQUFDTSxHQUFHLENBQUMsVUFBQ0MsSUFBSSxFQUFLO0lBQzFCLElBQUksQ0FBQ0EsSUFBSSxDQUFDQyxRQUFRLEVBQUUsT0FBT0QsSUFBSTtJQUMvQixJQUFNUSxvQkFBb0IsR0FBRyxJQUFBQyxtQ0FBdUIsRUFBQ1QsSUFBSSxDQUFDQyxRQUFRLENBQUM7SUFDbkVPLG9CQUFvQixDQUFDRyxPQUFPLENBQUMsVUFBQ0MsbUJBQW1CLEVBQUs7TUFBQTtNQUNwRCxJQUFJLENBQUNBLG1CQUFtQixDQUFDbUQsbUJBQW1CLEVBQUU7TUFFOUMsSUFBTW1CLGFBQWEsR0FBR0MsZ0JBQWdCLENBQUM7UUFDckNwRSxnQkFBZ0IsRUFBRUgsbUJBQW1CO1FBQ3JDbEIsbUJBQW1CLEVBQW5CQSxtQkFBbUI7UUFDbkJ3RixhQUFhLEVBQUU7TUFDakIsQ0FBQyxDQUFDO01BRUYsSUFBTXhCLGFBQWEsR0FBRzlDLG1CQUFtQixDQUFDbUQsbUJBQW1CLENBQUNoRSxHQUFHLENBQy9ELFVBQUNrRSxrQkFBa0I7UUFBQSxPQUFLQSxrQkFBa0IsQ0FBQ0MsUUFBUSxDQUFDckMsSUFBSSxDQUFDQyxLQUFLO01BQUEsRUFDL0Q7TUFFRG1ELFVBQVUsQ0FBQ2pFLElBQUksQ0FBQztRQUNkMkIsYUFBYSw0QkFBRS9CLG1CQUFtQixDQUFDaUIsSUFBSSwyREFBeEIsdUJBQTBCQyxLQUFLO1FBQzlDNEIsYUFBYSxFQUFiQSxhQUFhO1FBQ2JkLG9CQUFvQixFQUFFc0M7TUFDeEIsQ0FBQyxDQUFDO0lBQ0osQ0FBQyxDQUFDO0VBQ0osQ0FBQyxDQUFDO0VBQ0YsT0FBT0QsVUFBVTtBQUNuQixDQUFDO0FBRUQsSUFBTUUsZ0JBQWdCLEdBQUcsU0FBbkJBLGdCQUFnQixRQVFOO0VBQUEsSUFQZHBFLGdCQUFnQixTQUFoQkEsZ0JBQWdCO0lBQ2hCckIsbUJBQW1CLFNBQW5CQSxtQkFBbUI7SUFDbkJ3RixhQUFhLFNBQWJBLGFBQWE7RUFNYixJQUFBMUQsY0FBSyxFQUFDVCxnQkFBZ0IsRUFBRTtJQUN0QlUsY0FBYyxFQUFFO01BQ2QyRCxLQUFLLGlCQUFDN0IsSUFBSSxFQUFFO1FBQ1YsSUFBTThCLGdCQUFnQixHQUFHOUIsSUFBSSxDQUFDMUIsSUFBSSxDQUFDQyxLQUFLO1FBQ3hDLElBQU13RCxJQUFJLEdBQUcsSUFBQXRELHVDQUEyQixFQUFDO1VBQUV0QyxtQkFBbUIsRUFBbkJBLG1CQUFtQjtVQUFFdUMsWUFBWSxFQUFFc0IsSUFBSSxDQUFDMUIsSUFBSSxDQUFDQztRQUFNLENBQUMsQ0FBQztRQUNoRyxJQUFJLENBQUN3RCxJQUFJLEVBQUU7UUFFWEosYUFBYSxDQUFDbEUsSUFBSSxDQUFDcUUsZ0JBQWdCLENBQUM7UUFFcENGLGdCQUFnQixDQUFDO1VBQ2ZwRS