ParseGraphQLSchema.js 60 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. exports.ParseGraphQLSchema = void 0;
  6. var _node = _interopRequireDefault(require("parse/node"));
  7. var _graphql = require("graphql");
  8. var _schema = require("@graphql-tools/schema");
  9. var _merge = require("@graphql-tools/merge");
  10. var _util = require("util");
  11. var _requiredParameter = _interopRequireDefault(require("../requiredParameter"));
  12. var defaultGraphQLTypes = _interopRequireWildcard(require("./loaders/defaultGraphQLTypes"));
  13. var parseClassTypes = _interopRequireWildcard(require("./loaders/parseClassTypes"));
  14. var parseClassQueries = _interopRequireWildcard(require("./loaders/parseClassQueries"));
  15. var parseClassMutations = _interopRequireWildcard(require("./loaders/parseClassMutations"));
  16. var defaultGraphQLQueries = _interopRequireWildcard(require("./loaders/defaultGraphQLQueries"));
  17. var defaultGraphQLMutations = _interopRequireWildcard(require("./loaders/defaultGraphQLMutations"));
  18. var _ParseGraphQLController = _interopRequireWildcard(require("../Controllers/ParseGraphQLController"));
  19. var _DatabaseController = _interopRequireDefault(require("../Controllers/DatabaseController"));
  20. var _SchemaCache = _interopRequireDefault(require("../Adapters/Cache/SchemaCache"));
  21. var _parseGraphQLUtils = require("./parseGraphQLUtils");
  22. var schemaDirectives = _interopRequireWildcard(require("./loaders/schemaDirectives"));
  23. var schemaTypes = _interopRequireWildcard(require("./loaders/schemaTypes"));
  24. var _triggers = require("../triggers");
  25. var defaultRelaySchema = _interopRequireWildcard(require("./loaders/defaultRelaySchema"));
  26. function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
  27. function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
  28. function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
  29. const RESERVED_GRAPHQL_TYPE_NAMES = ['String', 'Boolean', 'Int', 'Float', 'ID', 'ArrayResult', 'Query', 'Mutation', 'Subscription', 'CreateFileInput', 'CreateFilePayload', 'Viewer', 'SignUpInput', 'SignUpPayload', 'LogInInput', 'LogInPayload', 'LogOutInput', 'LogOutPayload', 'CloudCodeFunction', 'CallCloudCodeInput', 'CallCloudCodePayload', 'CreateClassInput', 'CreateClassPayload', 'UpdateClassInput', 'UpdateClassPayload', 'DeleteClassInput', 'DeleteClassPayload', 'PageInfo'];
  30. const RESERVED_GRAPHQL_QUERY_NAMES = ['health', 'viewer', 'class', 'classes'];
  31. const RESERVED_GRAPHQL_MUTATION_NAMES = ['signUp', 'logIn', 'logOut', 'createFile', 'callCloudCode', 'createClass', 'updateClass', 'deleteClass'];
  32. class ParseGraphQLSchema {
  33. constructor(params = {}) {
  34. this.parseGraphQLController = params.parseGraphQLController || (0, _requiredParameter.default)('You must provide a parseGraphQLController instance!');
  35. this.databaseController = params.databaseController || (0, _requiredParameter.default)('You must provide a databaseController instance!');
  36. this.log = params.log || (0, _requiredParameter.default)('You must provide a log instance!');
  37. this.graphQLCustomTypeDefs = params.graphQLCustomTypeDefs;
  38. this.appId = params.appId || (0, _requiredParameter.default)('You must provide the appId!');
  39. this.schemaCache = _SchemaCache.default;
  40. this.logCache = {};
  41. }
  42. async load() {
  43. const {
  44. parseGraphQLConfig
  45. } = await this._initializeSchemaAndConfig();
  46. const parseClassesArray = await this._getClassesForSchema(parseGraphQLConfig);
  47. const functionNames = await this._getFunctionNames();
  48. const functionNamesString = functionNames.join();
  49. const parseClasses = parseClassesArray.reduce((acc, clazz) => {
  50. acc[clazz.className] = clazz;
  51. return acc;
  52. }, {});
  53. if (!this._hasSchemaInputChanged({
  54. parseClasses,
  55. parseGraphQLConfig,
  56. functionNamesString
  57. })) {
  58. return this.graphQLSchema;
  59. }
  60. this.parseClasses = parseClasses;
  61. this.parseGraphQLConfig = parseGraphQLConfig;
  62. this.functionNames = functionNames;
  63. this.functionNamesString = functionNamesString;
  64. this.parseClassTypes = {};
  65. this.viewerType = null;
  66. this.graphQLAutoSchema = null;
  67. this.graphQLSchema = null;
  68. this.graphQLTypes = [];
  69. this.graphQLQueries = {};
  70. this.graphQLMutations = {};
  71. this.graphQLSubscriptions = {};
  72. this.graphQLSchemaDirectivesDefinitions = null;
  73. this.graphQLSchemaDirectives = {};
  74. this.relayNodeInterface = null;
  75. defaultGraphQLTypes.load(this);
  76. defaultRelaySchema.load(this);
  77. schemaTypes.load(this);
  78. this._getParseClassesWithConfig(parseClassesArray, parseGraphQLConfig).forEach(([parseClass, parseClassConfig]) => {
  79. // Some times schema return the _auth_data_ field
  80. // it will lead to unstable graphql generation order
  81. if (parseClass.className === '_User') {
  82. Object.keys(parseClass.fields).forEach(fieldName => {
  83. if (fieldName.startsWith('_auth_data_')) {
  84. delete parseClass.fields[fieldName];
  85. }
  86. });
  87. }
  88. // Fields order inside the schema seems to not be consistent across
  89. // restart so we need to ensure an alphabetical order
  90. // also it's better for the playground documentation
  91. const orderedFields = {};
  92. Object.keys(parseClass.fields).sort().forEach(fieldName => {
  93. orderedFields[fieldName] = parseClass.fields[fieldName];
  94. });
  95. parseClass.fields = orderedFields;
  96. parseClassTypes.load(this, parseClass, parseClassConfig);
  97. parseClassQueries.load(this, parseClass, parseClassConfig);
  98. parseClassMutations.load(this, parseClass, parseClassConfig);
  99. });
  100. defaultGraphQLTypes.loadArrayResult(this, parseClassesArray);
  101. defaultGraphQLQueries.load(this);
  102. defaultGraphQLMutations.load(this);
  103. let graphQLQuery = undefined;
  104. if (Object.keys(this.graphQLQueries).length > 0) {
  105. graphQLQuery = new _graphql.GraphQLObjectType({
  106. name: 'Query',
  107. description: 'Query is the top level type for queries.',
  108. fields: this.graphQLQueries
  109. });
  110. this.addGraphQLType(graphQLQuery, true, true);
  111. }
  112. let graphQLMutation = undefined;
  113. if (Object.keys(this.graphQLMutations).length > 0) {
  114. graphQLMutation = new _graphql.GraphQLObjectType({
  115. name: 'Mutation',
  116. description: 'Mutation is the top level type for mutations.',
  117. fields: this.graphQLMutations
  118. });
  119. this.addGraphQLType(graphQLMutation, true, true);
  120. }
  121. let graphQLSubscription = undefined;
  122. if (Object.keys(this.graphQLSubscriptions).length > 0) {
  123. graphQLSubscription = new _graphql.GraphQLObjectType({
  124. name: 'Subscription',
  125. description: 'Subscription is the top level type for subscriptions.',
  126. fields: this.graphQLSubscriptions
  127. });
  128. this.addGraphQLType(graphQLSubscription, true, true);
  129. }
  130. this.graphQLAutoSchema = new _graphql.GraphQLSchema({
  131. types: this.graphQLTypes,
  132. query: graphQLQuery,
  133. mutation: graphQLMutation,
  134. subscription: graphQLSubscription
  135. });
  136. if (this.graphQLCustomTypeDefs) {
  137. schemaDirectives.load(this);
  138. if (typeof this.graphQLCustomTypeDefs.getTypeMap === 'function') {
  139. // In following code we use underscore attr to keep the direct variable reference
  140. const customGraphQLSchemaTypeMap = this.graphQLCustomTypeDefs._typeMap;
  141. const findAndReplaceLastType = (parent, key) => {
  142. if (parent[key].name) {
  143. if (this.graphQLAutoSchema._typeMap[parent[key].name] && this.graphQLAutoSchema._typeMap[parent[key].name] !== parent[key]) {
  144. // To avoid unresolved field on overloaded schema
  145. // replace the final type with the auto schema one
  146. parent[key] = this.graphQLAutoSchema._typeMap[parent[key].name];
  147. }
  148. } else {
  149. if (parent[key].ofType) {
  150. findAndReplaceLastType(parent[key], 'ofType');
  151. }
  152. }
  153. };
  154. // Add non shared types from custom schema to auto schema
  155. // note: some non shared types can use some shared types
  156. // so this code need to be ran before the shared types addition
  157. // we use sort to ensure schema consistency over restarts
  158. Object.keys(customGraphQLSchemaTypeMap).sort().forEach(customGraphQLSchemaTypeKey => {
  159. const customGraphQLSchemaType = customGraphQLSchemaTypeMap[customGraphQLSchemaTypeKey];
  160. if (!customGraphQLSchemaType || !customGraphQLSchemaType.name || customGraphQLSchemaType.name.startsWith('__')) {
  161. return;
  162. }
  163. const autoGraphQLSchemaType = this.graphQLAutoSchema._typeMap[customGraphQLSchemaType.name];
  164. if (!autoGraphQLSchemaType) {
  165. this.graphQLAutoSchema._typeMap[customGraphQLSchemaType.name] = customGraphQLSchemaType;
  166. }
  167. });
  168. // Handle shared types
  169. // We pass through each type and ensure that all sub field types are replaced
  170. // we use sort to ensure schema consistency over restarts
  171. Object.keys(customGraphQLSchemaTypeMap).sort().forEach(customGraphQLSchemaTypeKey => {
  172. const customGraphQLSchemaType = customGraphQLSchemaTypeMap[customGraphQLSchemaTypeKey];
  173. if (!customGraphQLSchemaType || !customGraphQLSchemaType.name || customGraphQLSchemaType.name.startsWith('__')) {
  174. return;
  175. }
  176. const autoGraphQLSchemaType = this.graphQLAutoSchema._typeMap[customGraphQLSchemaType.name];
  177. if (autoGraphQLSchemaType && typeof customGraphQLSchemaType.getFields === 'function') {
  178. Object.keys(customGraphQLSchemaType._fields).sort().forEach(fieldKey => {
  179. const field = customGraphQLSchemaType._fields[fieldKey];
  180. findAndReplaceLastType(field, 'type');
  181. autoGraphQLSchemaType._fields[field.name] = field;
  182. });
  183. }
  184. });
  185. this.graphQLSchema = this.graphQLAutoSchema;
  186. } else if (typeof this.graphQLCustomTypeDefs === 'function') {
  187. this.graphQLSchema = await this.graphQLCustomTypeDefs({
  188. directivesDefinitionsSchema: this.graphQLSchemaDirectivesDefinitions,
  189. autoSchema: this.graphQLAutoSchema,
  190. graphQLSchemaDirectives: this.graphQLSchemaDirectives
  191. });
  192. } else {
  193. this.graphQLSchema = (0, _schema.mergeSchemas)({
  194. schemas: [this.graphQLAutoSchema],
  195. typeDefs: (0, _merge.mergeTypeDefs)([this.graphQLCustomTypeDefs, this.graphQLSchemaDirectivesDefinitions])
  196. });
  197. this.graphQLSchema = this.graphQLSchemaDirectives(this.graphQLSchema);
  198. }
  199. } else {
  200. this.graphQLSchema = this.graphQLAutoSchema;
  201. }
  202. return this.graphQLSchema;
  203. }
  204. _logOnce(severity, message) {
  205. if (this.logCache[message]) {
  206. return;
  207. }
  208. this.log[severity](message);
  209. this.logCache[message] = true;
  210. }
  211. addGraphQLType(type, throwError = false, ignoreReserved = false, ignoreConnection = false) {
  212. if (!ignoreReserved && RESERVED_GRAPHQL_TYPE_NAMES.includes(type.name) || this.graphQLTypes.find(existingType => existingType.name === type.name) || !ignoreConnection && type.name.endsWith('Connection')) {
  213. const message = `Type ${type.name} could not be added to the auto schema because it collided with an existing type.`;
  214. if (throwError) {
  215. throw new Error(message);
  216. }
  217. this._logOnce('warn', message);
  218. return undefined;
  219. }
  220. this.graphQLTypes.push(type);
  221. return type;
  222. }
  223. addGraphQLQuery(fieldName, field, throwError = false, ignoreReserved = false) {
  224. if (!ignoreReserved && RESERVED_GRAPHQL_QUERY_NAMES.includes(fieldName) || this.graphQLQueries[fieldName]) {
  225. const message = `Query ${fieldName} could not be added to the auto schema because it collided with an existing field.`;
  226. if (throwError) {
  227. throw new Error(message);
  228. }
  229. this._logOnce('warn', message);
  230. return undefined;
  231. }
  232. this.graphQLQueries[fieldName] = field;
  233. return field;
  234. }
  235. addGraphQLMutation(fieldName, field, throwError = false, ignoreReserved = false) {
  236. if (!ignoreReserved && RESERVED_GRAPHQL_MUTATION_NAMES.includes(fieldName) || this.graphQLMutations[fieldName]) {
  237. const message = `Mutation ${fieldName} could not be added to the auto schema because it collided with an existing field.`;
  238. if (throwError) {
  239. throw new Error(message);
  240. }
  241. this._logOnce('warn', message);
  242. return undefined;
  243. }
  244. this.graphQLMutations[fieldName] = field;
  245. return field;
  246. }
  247. handleError(error) {
  248. if (error instanceof _node.default.Error) {
  249. this.log.error('Parse error: ', error);
  250. } else {
  251. this.log.error('Uncaught internal server error.', error, error.stack);
  252. }
  253. throw (0, _parseGraphQLUtils.toGraphQLError)(error);
  254. }
  255. async _initializeSchemaAndConfig() {
  256. const [schemaController, parseGraphQLConfig] = await Promise.all([this.databaseController.loadSchema(), this.parseGraphQLController.getGraphQLConfig()]);
  257. this.schemaController = schemaController;
  258. return {
  259. parseGraphQLConfig
  260. };
  261. }
  262. /**
  263. * Gets all classes found by the `schemaController`
  264. * minus those filtered out by the app's parseGraphQLConfig.
  265. */
  266. async _getClassesForSchema(parseGraphQLConfig) {
  267. const {
  268. enabledForClasses,
  269. disabledForClasses
  270. } = parseGraphQLConfig;
  271. const allClasses = await this.schemaController.getAllClasses();
  272. if (Array.isArray(enabledForClasses) || Array.isArray(disabledForClasses)) {
  273. let includedClasses = allClasses;
  274. if (enabledForClasses) {
  275. includedClasses = allClasses.filter(clazz => {
  276. return enabledForClasses.includes(clazz.className);
  277. });
  278. }
  279. if (disabledForClasses) {
  280. // Classes included in `enabledForClasses` that
  281. // are also present in `disabledForClasses` will
  282. // still be filtered out
  283. includedClasses = includedClasses.filter(clazz => {
  284. return !disabledForClasses.includes(clazz.className);
  285. });
  286. }
  287. this.isUsersClassDisabled = !includedClasses.some(clazz => {
  288. return clazz.className === '_User';
  289. });
  290. return includedClasses;
  291. } else {
  292. return allClasses;
  293. }
  294. }
  295. /**
  296. * This method returns a list of tuples
  297. * that provide the parseClass along with
  298. * its parseClassConfig where provided.
  299. */
  300. _getParseClassesWithConfig(parseClasses, parseGraphQLConfig) {
  301. const {
  302. classConfigs
  303. } = parseGraphQLConfig;
  304. // Make sures that the default classes and classes that
  305. // starts with capitalized letter will be generated first.
  306. const sortClasses = (a, b) => {
  307. a = a.className;
  308. b = b.className;
  309. if (a[0] === '_') {
  310. if (b[0] !== '_') {
  311. return -1;
  312. }
  313. }
  314. if (b[0] === '_') {
  315. if (a[0] !== '_') {
  316. return 1;
  317. }
  318. }
  319. if (a === b) {
  320. return 0;
  321. } else if (a < b) {
  322. return -1;
  323. } else {
  324. return 1;
  325. }
  326. };
  327. return parseClasses.sort(sortClasses).map(parseClass => {
  328. let parseClassConfig;
  329. if (classConfigs) {
  330. parseClassConfig = classConfigs.find(c => c.className === parseClass.className);
  331. }
  332. return [parseClass, parseClassConfig];
  333. });
  334. }
  335. async _getFunctionNames() {
  336. return await (0, _triggers.getFunctionNames)(this.appId).filter(functionName => {
  337. if (/^[_a-zA-Z][_a-zA-Z0-9]*$/.test(functionName)) {
  338. return true;
  339. } else {
  340. this._logOnce('warn', `Function ${functionName} could not be added to the auto schema because GraphQL names must match /^[_a-zA-Z][_a-zA-Z0-9]*$/.`);
  341. return false;
  342. }
  343. });
  344. }
  345. /**
  346. * Checks for changes to the parseClasses
  347. * objects (i.e. database schema) or to
  348. * the parseGraphQLConfig object. If no
  349. * changes are found, return true;
  350. */
  351. _hasSchemaInputChanged(params) {
  352. const {
  353. parseClasses,
  354. parseGraphQLConfig,
  355. functionNamesString
  356. } = params;
  357. // First init
  358. if (!this.graphQLSchema) {
  359. return true;
  360. }
  361. if ((0, _util.isDeepStrictEqual)(this.parseGraphQLConfig, parseGraphQLConfig) && this.functionNamesString === functionNamesString && (0, _util.isDeepStrictEqual)(this.parseClasses, parseClasses)) {
  362. return false;
  363. }
  364. return true;
  365. }
  366. }
  367. exports.ParseGraphQLSchema = ParseGraphQLSchema;
  368. //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfbm9kZSIsIl9pbnRlcm9wUmVxdWlyZURlZmF1bHQiLCJyZXF1aXJlIiwiX2dyYXBocWwiLCJfc2NoZW1hIiwiX21lcmdlIiwiX3V0aWwiLCJfcmVxdWlyZWRQYXJhbWV0ZXIiLCJkZWZhdWx0R3JhcGhRTFR5cGVzIiwiX2ludGVyb3BSZXF1aXJlV2lsZGNhcmQiLCJwYXJzZUNsYXNzVHlwZXMiLCJwYXJzZUNsYXNzUXVlcmllcyIsInBhcnNlQ2xhc3NNdXRhdGlvbnMiLCJkZWZhdWx0R3JhcGhRTFF1ZXJpZXMiLCJkZWZhdWx0R3JhcGhRTE11dGF0aW9ucyIsIl9QYXJzZUdyYXBoUUxDb250cm9sbGVyIiwiX0RhdGFiYXNlQ29udHJvbGxlciIsIl9TY2hlbWFDYWNoZSIsIl9wYXJzZUdyYXBoUUxVdGlscyIsInNjaGVtYURpcmVjdGl2ZXMiLCJzY2hlbWFUeXBlcyIsIl90cmlnZ2VycyIsImRlZmF1bHRSZWxheVNjaGVtYSIsIl9nZXRSZXF1aXJlV2lsZGNhcmRDYWNoZSIsImUiLCJXZWFrTWFwIiwiciIsInQiLCJfX2VzTW9kdWxlIiwiZGVmYXVsdCIsImhhcyIsImdldCIsIm4iLCJfX3Byb3RvX18iLCJhIiwiT2JqZWN0IiwiZGVmaW5lUHJvcGVydHkiLCJnZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IiLCJ1IiwiaGFzT3duUHJvcGVydHkiLCJjYWxsIiwiaSIsInNldCIsIlJFU0VSVkVEX0dSQVBIUUxfVFlQRV9OQU1FUyIsIlJFU0VSVkVEX0dSQVBIUUxfUVVFUllfTkFNRVMiLCJSRVNFUlZFRF9HUkFQSFFMX01VVEFUSU9OX05BTUVTIiwiUGFyc2VHcmFwaFFMU2NoZW1hIiwiY29uc3RydWN0b3IiLCJwYXJhbXMiLCJwYXJzZUdyYXBoUUxDb250cm9sbGVyIiwicmVxdWlyZWRQYXJhbWV0ZXIiLCJkYXRhYmFzZUNvbnRyb2xsZXIiLCJsb2ciLCJncmFwaFFMQ3VzdG9tVHlwZURlZnMiLCJhcHBJZCIsInNjaGVtYUNhY2hlIiwiU2NoZW1hQ2FjaGUiLCJsb2dDYWNoZSIsImxvYWQiLCJwYXJzZUdyYXBoUUxDb25maWciLCJfaW5pdGlhbGl6ZVNjaGVtYUFuZENvbmZpZyIsInBhcnNlQ2xhc3Nlc0FycmF5IiwiX2dldENsYXNzZXNGb3JTY2hlbWEiLCJmdW5jdGlvbk5hbWVzIiwiX2dldEZ1bmN0aW9uTmFtZXMiLCJmdW5jdGlvbk5hbWVzU3RyaW5nIiwiam9pbiIsInBhcnNlQ2xhc3NlcyIsInJlZHVjZSIsImFjYyIsImNsYXp6IiwiY2xhc3NOYW1lIiwiX2hhc1NjaGVtYUlucHV0Q2hhbmdlZCIsImdyYXBoUUxTY2hlbWEiLCJ2aWV3ZXJUeXBlIiwiZ3JhcGhRTEF1dG9TY2hlbWEiLCJncmFwaFFMVHlwZXMiLCJncmFwaFFMUXVlcmllcyIsImdyYXBoUUxNdXRhdGlvbnMiLCJncmFwaFFMU3Vic2NyaXB0aW9ucyIsImdyYXBoUUxTY2hlbWFEaXJlY3RpdmVzRGVmaW5pdGlvbnMiLCJncmFwaFFMU2NoZW1hRGlyZWN0aXZlcyIsInJlbGF5Tm9kZUludGVyZmFjZSIsIl9nZXRQYXJzZUNsYXNzZXNXaXRoQ29uZmlnIiwiZm9yRWFjaCIsInBhcnNlQ2xhc3MiLCJwYXJzZUNsYXNzQ29uZmlnIiwia2V5cyIsImZpZWxkcyIsImZpZWxkTmFtZSIsInN0YXJ0c1dpdGgiLCJvcmRlcmVkRmllbGRzIiwic29ydCIsImxvYWRBcnJheVJlc3VsdCIsImdyYXBoUUxRdWVyeSIsInVuZGVmaW5lZCIsImxlbmd0aCIsIkdyYXBoUUxPYmplY3RUeXBlIiwibmFtZSIsImRlc2NyaXB0aW9uIiwiYWRkR3JhcGhRTFR5cGUiLCJncmFwaFFMTXV0YXRpb24iLCJncmFwaFFMU3Vic2NyaXB0aW9uIiwiR3JhcGhRTFNjaGVtYSIsInR5cGVzIiwicXVlcnkiLCJtdXRhdGlvbiIsInN1YnNjcmlwdGlvbiIsImdldFR5cGVNYXAiLCJjdXN0b21HcmFwaFFMU2NoZW1hVHlwZU1hcCIsIl90eXBlTWFwIiwiZmluZEFuZFJlcGxhY2VMYXN0VHlwZSIsInBhcmVudCIsImtleSIsIm9mVHlwZSIsImN1c3RvbUdyYXBoUUxTY2hlbWFUeXBlS2V5IiwiY3VzdG9tR3JhcGhRTFNjaGVtYVR5cGUiLCJhdXRvR3JhcGhRTFNjaGVtYVR5cGUiLCJnZXRGaWVsZHMiLCJfZmllbGRzIiwiZmllbGRLZXkiLCJmaWVsZCIsImRpcmVjdGl2ZXNEZWZpbml0aW9uc1NjaGVtYSIsImF1dG9TY2hlbWEiLCJtZXJnZVNjaGVtYXMiLCJzY2hlbWFzIiwidHlwZURlZnMiLCJtZXJnZVR5cGVEZWZzIiwiX2xvZ09uY2UiLCJzZXZlcml0eSIsIm1lc3NhZ2UiLCJ0eXBlIiwidGhyb3dFcnJvciIsImlnbm9yZVJlc2VydmVkIiwiaWdub3JlQ29ubmVjdGlvbiIsImluY2x1ZGVzIiwiZmluZCIsImV4aXN0aW5nVHlwZSIsImVuZHNXaXRoIiwiRXJyb3IiLCJwdXNoIiwiYWRkR3JhcGhRTFF1ZXJ5IiwiYWRkR3JhcGhRTE11dGF0aW9uIiwiaGFuZGxlRXJyb3IiLCJlcnJvciIsIlBhcnNlIiwic3RhY2siLCJ0b0dyYXBoUUxFcnJvciIsInNjaGVtYUNvbnRyb2xsZXIiLCJQcm9taXNlIiwiYWxsIiwibG9hZFNjaGVtYSIsImdldEdyYXBoUUxDb25maWciLCJlbmFibGVkRm9yQ2xhc3NlcyIsImRpc2FibGVkRm9yQ2xhc3NlcyIsImFsbENsYXNzZXMiLCJnZXRBbGxDbGFzc2VzIiwiQXJyYXkiLCJpc0FycmF5IiwiaW5jbHVkZWRDbGFzc2VzIiwiZmlsdGVyIiwiaXNVc2Vyc0NsYXNzRGlzYWJsZWQiLCJzb21lIiwiY2xhc3NDb25maWdzIiwic29ydENsYXNzZXMiLCJiIiwibWFwIiwiYyIsImdldEZ1bmN0aW9uTmFtZXMiLCJmdW5jdGlvbk5hbWUiLCJ0ZXN0IiwiaXNEZWVwU3RyaWN0RXF1YWwiLCJleHBvcnRzIl0sInNvdXJjZXMiOlsiLi4vLi4vc3JjL0dyYXBoUUwvUGFyc2VHcmFwaFFMU2NoZW1hLmpzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBQYXJzZSBmcm9tICdwYXJzZS9ub2RlJztcbmltcG9ydCB7IEdyYXBoUUxTY2hlbWEsIEdyYXBoUUxPYmplY3RUeXBlLCBEb2N1bWVudE5vZGUsIEdyYXBoUUxOYW1lZFR5cGUgfSBmcm9tICdncmFwaHFsJztcbmltcG9ydCB7IG1lcmdlU2NoZW1hcyB9IGZyb20gJ0BncmFwaHFsLXRvb2xzL3NjaGVtYSc7XG5pbXBvcnQgeyBtZXJnZVR5cGVEZWZzIH0gZnJvbSAnQGdyYXBocWwtdG9vbHMvbWVyZ2UnO1xuaW1wb3J0IHsgaXNEZWVwU3RyaWN0RXF1YWwgfSBmcm9tICd1dGlsJztcbmltcG9ydCByZXF1aXJlZFBhcmFtZXRlciBmcm9tICcuLi9yZXF1aXJlZFBhcmFtZXRlcic7XG5pbXBvcnQgKiBhcyBkZWZhdWx0R3JhcGhRTFR5cGVzIGZyb20gJy4vbG9hZGVycy9kZWZhdWx0R3JhcGhRTFR5cGVzJztcbmltcG9ydCAqIGFzIHBhcnNlQ2xhc3NUeXBlcyBmcm9tICcuL2xvYWRlcnMvcGFyc2VDbGFzc1R5cGVzJztcbmltcG9ydCAqIGFzIHBhcnNlQ2xhc3NRdWVyaWVzIGZyb20gJy4vbG9hZGVycy9wYXJzZUNsYXNzUXVlcmllcyc7XG5pbXBvcnQgKiBhcyBwYXJzZUNsYXNzTXV0YXRpb25zIGZyb20gJy4vbG9hZGVycy9wYXJzZUNsYXNzTXV0YXRpb25zJztcbmltcG9ydCAqIGFzIGRlZmF1bHRHcmFwaFFMUXVlcmllcyBmcm9tICcuL2xvYWRlcnMvZGVmYXVsdEdyYXBoUUxRdWVyaWVzJztcbmltcG9ydCAqIGFzIGRlZmF1bHRHcmFwaFFMTXV0YXRpb25zIGZyb20gJy4vbG9hZGVycy9kZWZhdWx0R3JhcGhRTE11dGF0aW9ucyc7XG5pbXBvcnQgUGFyc2VHcmFwaFFMQ29udHJvbGxlciwgeyBQYXJzZUdyYXBoUUxDb25maWcgfSBmcm9tICcuLi9Db250cm9sbGVycy9QYXJzZUdyYXBoUUxDb250cm9sbGVyJztcbmltcG9ydCBEYXRhYmFzZUNvbnRyb2xsZXIgZnJvbSAnLi4vQ29udHJvbGxlcnMvRGF0YWJhc2VDb250cm9sbGVyJztcbmltcG9ydCBTY2hlbWFDYWNoZSBmcm9tICcuLi9BZGFwdGVycy9DYWNoZS9TY2hlbWFDYWNoZSc7XG5pbXBvcnQgeyB0b0dyYXBoUUxFcnJvciB9IGZyb20gJy4vcGFyc2VHcmFwaFFMVXRpbHMnO1xuaW1wb3J0ICogYXMgc2NoZW1hRGlyZWN0aXZlcyBmcm9tICcuL2xvYWRlcnMvc2NoZW1hRGlyZWN0aXZlcyc7XG5pbXBvcnQgKiBhcyBzY2hlbWFUeXBlcyBmcm9tICcuL2xvYWRlcnMvc2NoZW1hVHlwZXMnO1xuaW1wb3J0IHsgZ2V0RnVuY3Rpb25OYW1lcyB9IGZyb20gJy4uL3RyaWdnZXJzJztcbmltcG9ydCAqIGFzIGRlZmF1bHRSZWxheVNjaGVtYSBmcm9tICcuL2xvYWRlcnMvZGVmYXVsdFJlbGF5U2NoZW1hJztcblxuY29uc3QgUkVTRVJWRURfR1JBUEhRTF9UWVBFX05BTUVTID0gW1xuICAnU3RyaW5nJyxcbiAgJ0Jvb2xlYW4nLFxuICAnSW50JyxcbiAgJ0Zsb2F0JyxcbiAgJ0lEJyxcbiAgJ0FycmF5UmVzdWx0JyxcbiAgJ1F1ZXJ5JyxcbiAgJ011dGF0aW9uJyxcbiAgJ1N1YnNjcmlwdGlvbicsXG4gICdDcmVhdGVGaWxlSW5wdXQnLFxuICAnQ3JlYXRlRmlsZVBheWxvYWQnLFxuICAnVmlld2VyJyxcbiAgJ1NpZ25VcElucHV0JyxcbiAgJ1NpZ25VcFBheWxvYWQnLFxuICAnTG9nSW5JbnB1dCcsXG4gICdMb2dJblBheWxvYWQnLFxuICAnTG9nT3V0SW5wdXQnLFxuICAnTG9nT3V0UGF5bG9hZCcsXG4gICdDbG91ZENvZGVGdW5jdGlvbicsXG4gICdDYWxsQ2xvdWRDb2RlSW5wdXQnLFxuICAnQ2FsbENsb3VkQ29kZVBheWxvYWQnLFxuICAnQ3JlYXRlQ2xhc3NJbnB1dCcsXG4gICdDcmVhdGVDbGFzc1BheWxvYWQnLFxuICAnVXBkYXRlQ2xhc3NJbnB1dCcsXG4gICdVcGRhdGVDbGFzc1BheWxvYWQnLFxuICAnRGVsZXRlQ2xhc3NJbnB1dCcsXG4gICdEZWxldGVDbGFzc1BheWxvYWQnLFxuICAnUGFnZUluZm8nLFxuXTtcbmNvbnN0IFJFU0VSVkVEX0dSQVBIUUxfUVVFUllfTkFNRVMgPSBbJ2hlYWx0aCcsICd2aWV3ZXInLCAnY2xhc3MnLCAnY2xhc3NlcyddO1xuY29uc3QgUkVTRVJWRURfR1JBUEhRTF9NVVRBVElPTl9OQU1FUyA9IFtcbiAgJ3NpZ25VcCcsXG4gICdsb2dJbicsXG4gICdsb2dPdXQnLFxuICAnY3JlYXRlRmlsZScsXG4gICdjYWxsQ2xvdWRDb2RlJyxcbiAgJ2NyZWF0ZUNsYXNzJyxcbiAgJ3VwZGF0ZUNsYXNzJyxcbiAgJ2RlbGV0ZUNsYXNzJyxcbl07XG5cbmNsYXNzIFBhcnNlR3JhcGhRTFNjaGVtYSB7XG4gIGRhdGFiYXNlQ29udHJvbGxlcjogRGF0YWJhc2VDb250cm9sbGVyO1xuICBwYXJzZUdyYXBoUUxDb250cm9sbGVyOiBQYXJzZUdyYXBoUUxDb250cm9sbGVyO1xuICBwYXJzZUdyYXBoUUxDb25maWc6IFBhcnNlR3JhcGhRTENvbmZpZztcbiAgbG9nOiBhbnk7XG4gIGFwcElkOiBzdHJpbmc7XG4gIGdyYXBoUUxDdXN0b21UeXBlRGVmczogPyhzdHJpbmcgfCBHcmFwaFFMU2NoZW1hIHwgRG9jdW1lbnROb2RlIHwgR3JhcGhRTE5hbWVkVHlwZVtdKTtcbiAgc2NoZW1hQ2FjaGU6IGFueTtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwYXJhbXM6IHtcbiAgICAgIGRhdGFiYXNlQ29udHJvbGxlcjogRGF0YWJhc2VDb250cm9sbGVyLFxuICAgICAgcGFyc2VHcmFwaFFMQ29udHJvbGxlcjogUGFyc2VHcmFwaFFMQ29udHJvbGxlcixcbiAgICAgIGxvZzogYW55LFxuICAgICAgYXBwSWQ6IHN0cmluZyxcbiAgICAgIGdyYXBoUUxDdXN0b21UeXBlRGVmczogPyhzdHJpbmcgfCBHcmFwaFFMU2NoZW1hIHwgRG9jdW1lbnROb2RlIHwgR3JhcGhRTE5hbWVkVHlwZVtdKSxcbiAgICB9ID0ge31cbiAgKSB7XG4gICAgdGhpcy5wYXJzZUdyYXBoUUxDb250cm9sbGVyID1cbiAgICAgIHBhcmFtcy5wYXJzZUdyYXBoUUxDb250cm9sbGVyIHx8XG4gICAgICByZXF1aXJlZFBhcmFtZXRlcignWW91IG11c3QgcHJvdmlkZSBhIHBhcnNlR3JhcGhRTENvbnRyb2xsZXIgaW5zdGFuY2UhJyk7XG4gICAgdGhpcy5kYXRhYmFzZUNvbnRyb2xsZXIgPVxuICAgICAgcGFyYW1zLmRhdGFiYXNlQ29udHJvbGxlciB8fFxuICAgICAgcmVxdWlyZWRQYXJhbWV0ZXIoJ1lvdSBtdXN0IHByb3ZpZGUgYSBkYXRhYmFzZUNvbnRyb2xsZXIgaW5zdGFuY2UhJyk7XG4gICAgdGhpcy5sb2cgPSBwYXJhbXMubG9nIHx8IHJlcXVpcmVkUGFyYW1ldGVyKCdZb3UgbXVzdCBwcm92aWRlIGEgbG9nIGluc3RhbmNlIScpO1xuICAgIHRoaXMuZ3JhcGhRTEN1c3RvbVR5cGVEZWZzID0gcGFyYW1zLmdyYXBoUUxDdXN0b21UeXBlRGVmcztcbiAgICB0aGlzLmFwcElkID0gcGFyYW1zLmFwcElkIHx8IHJlcXVpcmVkUGFyYW1ldGVyKCdZb3UgbXVzdCBwcm92aWRlIHRoZSBhcHBJZCEnKTtcbiAgICB0aGlzLnNjaGVtYUNhY2hlID0gU2NoZW1hQ2FjaGU7XG4gICAgdGhpcy5sb2dDYWNoZSA9IHt9O1xuICB9XG5cbiAgYXN5bmMgbG9hZCgpIHtcbiAgICBjb25zdCB7IHBhcnNlR3JhcGhRTENvbmZpZyB9ID0gYXdhaXQgdGhpcy5faW5pdGlhbGl6ZVNjaGVtYUFuZENvbmZpZygpO1xuICAgIGNvbnN0IHBhcnNlQ2xhc3Nlc0FycmF5ID0gYXdhaXQgdGhpcy5fZ2V0Q2xhc3Nlc0ZvclNjaGVtYShwYXJzZUdyYXBoUUxDb25maWcpO1xuICAgIGNvbnN0IGZ1bmN0aW9uTmFtZXMgPSBhd2FpdCB0aGlzLl9nZXRGdW5jdGlvbk5hbWVzKCk7XG4gICAgY29uc3QgZnVuY3Rpb25OYW1lc1N0cmluZyA9IGZ1bmN0aW9uTmFtZXMuam9pbigpO1xuXG4gICAgY29uc3QgcGFyc2VDbGFzc2VzID0gcGFyc2VDbGFzc2VzQXJyYXkucmVkdWNlKChhY2MsIGNsYXp6KSA9PiB7XG4gICAgICBhY2NbY2xhenouY2xhc3NOYW1lXSA9IGNsYXp6O1xuICAgICAgcmV0dXJuIGFjYztcbiAgICB9LCB7fSk7XG4gICAgaWYgKFxuICAgICAgIXRoaXMuX2hhc1NjaGVtYUlucHV0Q2hhbmdlZCh7XG4gICAgICAgIHBhcnNlQ2xhc3NlcyxcbiAgICAgICAgcGFyc2VHcmFwaFFMQ29uZmlnLFxuICAgICAgICBmdW5jdGlvbk5hbWVzU3RyaW5nLFxuICAgICAgfSlcbiAgICApIHtcbiAgICAgIHJldHVybiB0aGlzLmdyYXBoUUxTY2hlbWE7XG4gICAgfVxuXG4gICAgdGhpcy5wYXJzZUNsYXNzZXMgPSBwYXJzZUNsYXNzZXM7XG4gICAgdGhpcy5wYXJzZUdyYXBoUUxDb25maWcgPSBwYXJzZUdyYXBoUUxDb25maWc7XG4gICAgdGhpcy5mdW5jdGlvbk5hbWVzID0gZnVuY3Rpb25OYW1lcztcbiAgICB0aGlzLmZ1bmN0aW9uTmFtZXNTdHJpbmcgPSBmdW5jdGlvbk5hbWVzU3RyaW5nO1xuICAgIHRoaXMucGFyc2VDbGFzc1R5cGVzID0ge307XG4gICAgdGhpcy52aWV3ZXJUeXBlID0gbnVsbDtcbiAgICB0aGlzLmdyYXBoUUxBdXRvU2NoZW1hID0gbnVsbDtcbiAgICB0aGlzLmdyYXBoUUxTY2hlbWEgPSBudWxsO1xuICAgIHRoaXMuZ3JhcGhRTFR5cGVzID0gW107XG4gICAgdGhpcy5ncmFwaFFMUXVlcmllcyA9IHt9O1xuICAgIHRoaXMuZ3JhcGhRTE11dGF0aW9ucyA9IHt9O1xuICAgIHRoaXMuZ3JhcGhRTFN1YnNjcmlwdGlvbnMgPSB7fTtcbiAgICB0aGlzLmdyYXBoUUxTY2hlbWFEaXJlY3RpdmVzRGVmaW5pdGlvbnMgPSBudWxsO1xuICAgIHRoaXMuZ3JhcGhRTFNjaGVtYURpcmVjdGl2ZXMgPSB7fTtcbiAgICB0aGlzLnJlbGF5Tm9kZUludGVyZmFjZSA9IG51bGw7XG5cbiAgICBkZWZhdWx0R3JhcGhRTFR5cGVzLmxvYWQodGhpcyk7XG4gICAgZGVmYXVsdFJlbGF5U2NoZW1hLmxvYWQodGhpcyk7XG4gICAgc2NoZW1hVHlwZXMubG9hZCh0aGlzKTtcblxuICAgIHRoaXMuX2dldFBhcnNlQ2xhc3Nlc1dpdGhDb25maWcocGFyc2VDbGFzc2VzQXJyYXksIHBhcnNlR3JhcGhRTENvbmZpZykuZm9yRWFjaChcbiAgICAgIChbcGFyc2VDbGFzcywgcGFyc2VDbGFzc0NvbmZpZ10pID0+IHtcbiAgICAgICAgLy8gU29tZSB0aW1lcyBzY2hlbWEgcmV0dXJuIHRoZSBfYXV0aF9kYXRhXyBmaWVsZFxuICAgICAgICAvLyBpdCB3aWxsIGxlYWQgdG8gdW5zdGFibGUgZ3JhcGhxbCBnZW5lcmF0aW9uIG9yZGVyXG4gICAgICAgIGlmIChwYXJzZUNsYXNzLmNsYXNzTmFtZSA9PT0gJ19Vc2VyJykge1xuICAgICAgICAgIE9iamVjdC5rZXlzKHBhcnNlQ2xhc3MuZmllbGRzKS5mb3JFYWNoKGZpZWxkTmFtZSA9PiB7XG4gICAgICAgICAgICBpZiAoZmllbGROYW1lLnN0YXJ0c1dpdGgoJ19hdXRoX2RhdGFfJykpIHtcbiAgICAgICAgICAgICAgZGVsZXRlIHBhcnNlQ2xhc3MuZmllbGRzW2ZpZWxkTmFtZV07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBGaWVsZHMgb3JkZXIgaW5zaWRlIHRoZSBzY2hlbWEgc2VlbXMgdG8gbm90IGJlIGNvbnNpc3RlbnQgYWNyb3NzXG4gICAgICAgIC8vIHJlc3RhcnQgc28gd2UgbmVlZCB0byBlbnN1cmUgYW4gYWxwaGFiZXRpY2FsIG9yZGVyXG4gICAgICAgIC8vIGFsc28gaXQncyBiZXR0ZXIgZm9yIHRoZSBwbGF5Z3JvdW5kIGRvY3VtZW50YXRpb25cbiAgICAgICAgY29uc3Qgb3JkZXJlZEZpZWxkcyA9IHt9O1xuICAgICAgICBPYmplY3Qua2V5cyhwYXJzZUNsYXNzLmZpZWxkcylcbiAgICAgICAgICAuc29ydCgpXG4gICAgICAgICAgLmZvckVhY2goZmllbGROYW1lID0+IHtcbiAgICAgICAgICAgIG9yZGVyZWRGaWVsZHNbZmllbGROYW1lXSA9IHBhcnNlQ2xhc3MuZmllbGRzW2ZpZWxkTmFtZV07XG4gICAgICAgICAgfSk7XG4gICAgICAgIHBhcnNlQ2xhc3MuZmllbGRzID0gb3JkZXJlZEZpZWxkcztcbiAgICAgICAgcGFyc2VDbGFzc1R5cGVzLmxvYWQodGhpcywgcGFyc2VDbGFzcywgcGFyc2VDbGFzc0NvbmZpZyk7XG4gICAgICAgIHBhcnNlQ2xhc3NRdWVyaWVzLmxvYWQodGhpcywgcGFyc2VDbGFzcywgcGFyc2VDbGFzc0NvbmZpZyk7XG4gICAgICAgIHBhcnNlQ2xhc3NNdXRhdGlvbnMubG9hZCh0aGlzLCBwYXJzZUNsYXNzLCBwYXJzZUNsYXNzQ29uZmlnKTtcbiAgICAgIH1cbiAgICApO1xuXG4gICAgZGVmYXVsdEdyYXBoUUxUeXBlcy5sb2FkQXJyYXlSZXN1bHQodGhpcywgcGFyc2VDbGFzc2VzQXJyYXkpO1xuICAgIGRlZmF1bHRHcmFwaFFMUXVlcmllcy5sb2FkKHRoaXMpO1xuICAgIGRlZmF1bHRHcmFwaFFMTXV0YXRpb25zLmxvYWQodGhpcyk7XG5cbiAgICBsZXQgZ3JhcGhRTFF1ZXJ5ID0gdW5kZWZpbmVkO1xuICAgIGlmIChPYmplY3Qua2V5cyh0aGlzLmdyYXBoUUxRdWVyaWVzKS5sZW5ndGggPiAwKSB7XG4gICAgICBncmFwaFFMUXVlcnkgPSBuZXcgR3JhcGhRTE9iamVjdFR5cGUoe1xuICAgICAgICBuYW1lOiAnUXVlcnknLFxuICAgICAgICBkZXNjcmlwdGlvbjogJ1F1ZXJ5IGlzIHRoZSB0b3AgbGV2ZWwgdHlwZSBmb3IgcXVlcmllcy4nLFxuICAgICAgICBmaWVsZHM6IHRoaXMuZ3JhcGhRTFF1ZXJpZXMsXG4gICAgICB9KTtcbiAgICAgIHRoaXMuYWRkR3JhcGhRTFR5cGUoZ3JhcGhRTFF1ZXJ5LCB0cnVlLCB0cnVlKTtcbiAgICB9XG5cbiAgICBsZXQgZ3JhcGhRTE11dGF0aW9uID0gdW5kZWZpbmVkO1xuICAgIGlmIChPYmplY3Qua2V5cyh0aGlzLmdyYXBoUUxNdXRhdGlvbnMpLmxlbmd0aCA+IDApIHtcbiAgICAgIGdyYXBoUUxNdXRhdGlvbiA9IG5ldyBHcmFwaFFMT2JqZWN0VHlwZSh7XG4gICAgICAgIG5hbWU6ICdNdXRhdGlvbicsXG4gICAgICAgIGRlc2NyaXB0aW9uOiAnTXV0YXRpb24gaXMgdGhlIHRvcCBsZXZlbCB0eXBlIGZvciBtdXRhdGlvbnMuJyxcbiAgICAgICAgZmllbGRzOiB0aGlzLmdyYXBoUUxNdXRhdGlvbnMsXG4gICAgICB9KTtcbiAgICAgIHRoaXMuYWRkR3JhcGhRTFR5cGUoZ3JhcGhRTE11dGF0aW9uLCB0cnVlLCB0cnVlKTtcbiAgICB9XG5cbiAgICBsZXQgZ3JhcGhRTFN1YnNjcmlwdGlvbiA9IHVuZGVmaW5lZDtcbiAgICBpZiAoT2JqZWN0LmtleXModGhpcy5ncmFwaFFMU3Vic2NyaXB0aW9ucykubGVuZ3RoID4gMCkge1xuICAgICAgZ3JhcGhRTFN1YnNjcmlwdGlvbiA9IG5ldyBHcmFwaFFMT2JqZWN0VHlwZSh7XG4gICAgICAgIG5hbWU6ICdTdWJzY3JpcHRpb24nLFxuICAgICAgICBkZXNjcmlwdGlvbjogJ1N1YnNjcmlwdGlvbiBpcyB0aGUgdG9wIGxldmVsIHR5cGUgZm9yIHN1YnNjcmlwdGlvbnMuJyxcbiAgICAgICAgZmllbGRzOiB0aGlzLmdyYXBoUUxTdWJzY3JpcHRpb25zLFxuICAgICAgfSk7XG4gICAgICB0aGlzLmFkZEdyYXBoUUxUeXBlKGdyYXBoUUxTdWJzY3JpcHRpb24sIHRydWUsIHRydWUpO1xuICAgIH1cblxuICAgIHRoaXMuZ3JhcGhRTEF1dG9TY2hlbWEgPSBuZXcgR3JhcGhRTFNjaGVtYSh7XG4gICAgICB0eXBlczogdGhpcy5ncmFwaFFMVHlwZXMsXG4gICAgICBxdWVyeTogZ3JhcGhRTFF1ZXJ5LFxuICAgICAgbXV0YXRpb246IGdyYXBoUUxNdXRhdGlvbixcbiAgICAgIHN1YnNjcmlwdGlvbjogZ3JhcGhRTFN1YnNjcmlwdGlvbixcbiAgICB9KTtcblxuICAgIGlmICh0aGlzLmdyYXBoUUxDdXN0b21UeXBlRGVmcykge1xuICAgICAgc2NoZW1hRGlyZWN0aXZlcy5sb2FkKHRoaXMpO1xuICAgICAgaWYgKHR5cGVvZiB0aGlzLmdyYXBoUUxDdXN0b21UeXBlRGVmcy5nZXRUeXBlTWFwID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIC8vIEluIGZvbGxvd2luZyBjb2RlIHdlIHVzZSB1bmRlcnNjb3JlIGF0dHIgdG8ga2VlcCB0aGUgZGlyZWN0IHZhcmlhYmxlIHJlZmVyZW5jZVxuICAgICAgICBjb25zdCBjdXN0b21HcmFwaFFMU2NoZW1hVHlwZU1hcCA9IHRoaXMuZ3JhcGhRTEN1c3RvbVR5cGVEZWZzLl90eXBlTWFwO1xuICAgICAgICBjb25zdCBmaW5kQW5kUmVwbGFjZUxhc3RUeXBlID0gKHBhcmVudCwga2V5KSA9PiB7XG4gICAgICAgICAgaWYgKHBhcmVudFtrZXldLm5hbWUpIHtcbiAgICAgICAgICAgIGlmIChcbiAgICAgICAgICAgICAgdGhpcy5ncmFwaFFMQXV0b1NjaGVtYS5fdHlwZU1hcFtwYXJlbnRba2V5XS5uYW1lXSAmJlxuICAgICAgICAgICAgICB0aGlzLmdyYXBoUUxBdXRvU2NoZW1hLl90eXBlTWFwW3BhcmVudFtrZXldLm5hbWVdICE9PSBwYXJlbnRba2V5XVxuICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgIC8vIFRvIGF2b2lkIHVucmVzb2x2ZWQgZmllbGQgb24gb3ZlcmxvYWRlZCBzY2hlbWFcbiAgICAgICAgICAgICAgLy8gcmVwbGFjZSB0aGUgZmluYWwgdHlwZSB3aXRoIHRoZSBhdXRvIHNjaGVtYSBvbmVcbiAgICAgICAgICAgICAgcGFyZW50W2tleV0gPSB0aGlzLmdyYXBoUUxBdXRvU2NoZW1hLl90eXBlTWFwW3BhcmVudFtrZXldLm5hbWVdO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBpZiAocGFyZW50W2tleV0ub2ZUeXBlKSB7XG4gICAgICAgICAgICAgIGZpbmRBbmRSZXBsYWNlTGFzdFR5cGUocGFyZW50W2tleV0sICdvZlR5cGUnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIC8vIEFkZCBub24gc2hhcmVkIHR5cGVzIGZyb20gY3VzdG9tIHNjaGVtYSB0byBhdXRvIHNjaGVtYVxuICAgICAgICAvLyBub3RlOiBzb21lIG5vbiBzaGFyZWQgdHlwZXMgY2FuIHVzZSBzb21lIHNoYXJlZCB0eXBlc1xuICAgICAgICAvLyBzbyB0aGlzIGNvZGUgbmVlZCB0byBiZSByYW4gYmVmb3JlIHRoZSBzaGFyZWQgdHlwZXMgYWRkaXRpb25cbiAgICAgICAgLy8gd2UgdXNlIHNvcnQgdG8gZW5zdXJlIHNjaGVtYSBjb25zaXN0ZW5jeSBvdmVyIHJlc3RhcnRzXG4gICAgICAgIE9iamVjdC5rZXlzKGN1c3RvbUdyYXBoUUxTY2hlbWFUeXBlTWFwKVxuICAgICAgICAgIC5zb3J0KClcbiAgICAgICAgICAuZm9yRWFjaChjdXN0b21HcmFwaFFMU2NoZW1hVHlwZUtleSA9PiB7XG4gICAgICAgICAgICBjb25zdCBjdXN0b21HcmFwaFFMU2NoZW1hVHlwZSA9IGN1c3RvbUdyYXBoUUxTY2hlbWFUeXBlTWFwW2N1c3RvbUdyYXBoUUxTY2hlbWFUeXBlS2V5XTtcbiAgICAgICAgICAgIGlmIChcbiAgICAgICAgICAgICAgIWN1c3RvbUdyYXBoUUxTY2hlbWFUeXBlIHx8XG4gICAgICAgICAgICAgICFjdXN0b21HcmFwaFFMU2NoZW1hVHlwZS5uYW1lIHx8XG4gICAgICAgICAgICAgIGN1c3RvbUdyYXBoUUxTY2hlbWFUeXBlLm5hbWUuc3RhcnRzV2l0aCgnX18nKVxuICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IGF1dG9HcmFwaFFMU2NoZW1hVHlwZSA9IHRoaXMuZ3JhcGhRTEF1dG9TY2hlbWEuX3R5cGVNYXBbXG4gICAgICAgICAgICAgIGN1c3RvbUdyYXBoUUxTY2hlbWFUeXBlLm5hbWVcbiAgICAgICAgICAgIF07XG4gICAgICAgICAgICBpZiAoIWF1dG9HcmFwaFFMU2NoZW1hVHlwZSkge1xuICAgICAgICAgICAgICB0aGlzLmdyYXBoUUxBdXRvU2NoZW1hLl90eXBlTWFwW1xuICAgICAgICAgICAgICAgIGN1c3RvbUdyYXBoUUxTY2hlbWFUeXBlLm5hbWVcbiAgICAgICAgICAgICAgXSA9IGN1c3RvbUdyYXBoUUxTY2hlbWFUeXBlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0pO1xuICAgICAgICAvLyBIYW5kbGUgc2hhcmVkIHR5cGVzXG4gICAgICAgIC8vIFdlIHBhc3MgdGhyb3VnaCBlYWNoIHR5cGUgYW5kIGVuc3VyZSB0aGF0IGFsbCBzdWIgZmllbGQgdHlwZXMgYXJlIHJlcGxhY2VkXG4gICAgICAgIC8vIHdlIHVzZSBzb3J0IHRvIGVuc3VyZSBzY2hlbWEgY29uc2lzdGVuY3kgb3ZlciByZXN0YXJ0c1xuICAgICAgICBPYmplY3Qua2V5cyhjdXN0b21HcmFwaFFMU2NoZW1hVHlwZU1hcClcbiAgICAgICAgICAuc29ydCgpXG4gICAgICAgICAgLmZvckVhY2goY3VzdG9tR3JhcGhRTFNjaGVtYVR5cGVLZXkgPT4ge1xuICAgICAgICAgICAgY29uc3QgY3VzdG9tR3JhcGhRTFNjaGVtYVR5cGUgPSBjdXN0b21HcmFwaFFMU2NoZW1hVHlwZU1hcFtjdXN0b21HcmFwaFFMU2NoZW1hVHlwZUtleV07XG4gICAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAgICFjdXN0b21HcmFwaFFMU2NoZW1hVHlwZSB8fFxuICAgICAgICAgICAgICAhY3VzdG9tR3JhcGhRTFNjaGVtYVR5cGUubmFtZSB8fFxuICAgICAgICAgICAgICBjdXN0b21HcmFwaFFMU2NoZW1hVHlwZS5uYW1lLnN0YXJ0c1dpdGgoJ19fJylcbiAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCBhdXRvR3JhcGhRTFNjaGVtYVR5cGUgPSB0aGlzLmdyYXBoUUxBdXRvU2NoZW1hLl90eXBlTWFwW1xuICAgICAgICAgICAgICBjdXN0b21HcmFwaFFMU2NoZW1hVHlwZS5uYW1lXG4gICAgICAgICAgICBdO1xuXG4gICAgICAgICAgICBpZiAoYXV0b0dyYXBoUUxTY2hlbWFUeXBlICYmIHR5cGVvZiBjdXN0b21HcmFwaFFMU2NoZW1hVHlwZS5nZXRGaWVsZHMgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgICAgT2JqZWN0LmtleXMoY3VzdG9tR3JhcGhRTFNjaGVtYVR5cGUuX2ZpZWxkcylcbiAgICAgICAgICAgICAgICAuc29ydCgpXG4gICAgICAgICAgICAgICAgLmZvckVhY2goZmllbGRLZXkgPT4ge1xuICAgICAgICAgICAgICAgICAgY29uc3QgZmllbGQgPSBjdXN0b21HcmFwaFFMU2NoZW1hVHlwZS5fZmllbGRzW2ZpZWxkS2V5XTtcbiAgICAgICAgICAgICAgICAgIGZpbmRBbmRSZXBsYWNlTGFzdFR5cGUoZmllbGQsICd0eXBlJyk7XG4gICAgICAgICAgICAgICAgICBhdXRvR3JhcGhRTFNjaGVtYVR5cGUuX2ZpZWxkc1tmaWVsZC5uYW1lXSA9IGZpZWxkO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0pO1xuICAgICAgICB0aGlzLmdyYXBoUUxTY2hlbWEgPSB0aGlzLmdyYXBoUUxBdXRvU2NoZW1hO1xuICAgICAgfSBlbHNlIGlmICh0eXBlb2YgdGhpcy5ncmFwaFFMQ3VzdG9tVHlwZURlZnMgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgdGhpcy5ncmFwaFFMU2NoZW1hID0gYXdhaXQgdGhpcy5ncmFwaFFMQ3VzdG9tVHlwZURlZnMoe1xuICAgICAgICAgIGRpcmVjdGl2ZXNEZWZpbml0aW9uc1NjaGVtYTogdGhpcy5ncmFwaFFMU2NoZW1hRGlyZWN0aXZlc0RlZmluaXRpb25zLFxuICAgICAgICAgIGF1dG9TY2hlbWE6IHRoaXMuZ3JhcGhRTEF1dG9TY2hlbWEsXG4gICAgICAgICAgZ3JhcGhRTFNjaGVtYURpcmVjdGl2ZXM6IHRoaXMuZ3JhcGhRTFNjaGVtYURpcmVjdGl2ZXMsXG4gICAgICAgIH0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5ncmFwaFFMU2NoZW1hID0gbWVyZ2VTY2hlbWFzKHtcbiAgICAgICAgICBzY2hlbWFzOiBbdGhpcy5ncmFwaFFMQXV0b1NjaGVtYV0sXG4gICAgICAgICAgdHlwZURlZnM6IG1lcmdlVHlwZURlZnMoW1xuICAgICAgICAgICAgdGhpcy5ncmFwaFFMQ3VzdG9tVHlwZURlZnMsXG4gICAgICAgICAgICB0aGlzLmdyYXBoUUxTY2hlbWFEaXJlY3RpdmVzRGVmaW5pdGlvbnMsXG4gICAgICAgICAgXSksXG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLmdyYXBoUUxTY2hlbWEgPSB0aGlzLmdyYXBoUUxTY2hlbWFEaXJlY3RpdmVzKHRoaXMuZ3JhcGhRTFNjaGVtYSk7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuZ3JhcGhRTFNjaGVtYSA9IHRoaXMuZ3JhcGhRTEF1dG9TY2hlbWE7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMuZ3JhcGhRTFNjaGVtYTtcbiAgfVxuXG4gIF9sb2dPbmNlKHNldmVyaXR5LCBtZXNzYWdlKSB7XG4gICAgaWYgKHRoaXMubG9nQ2FjaGVbbWVzc2FnZV0pIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdGhpcy5sb2dbc2V2ZXJpdHldKG1lc3NhZ2UpO1xuICAgIHRoaXMubG9nQ2FjaGVbbWVzc2FnZV0gPSB0cnVlO1xuICB9XG5cbiAgYWRkR3JhcGhRTFR5cGUodHlwZSwgdGhyb3dFcnJvciA9IGZhbHNlLCBpZ25vcmVSZXNlcnZlZCA9IGZhbHNlLCBpZ25vcmVDb25uZWN0aW9uID0gZmFsc2UpIHtcbiAgICBpZiAoXG4gICAgICAoIWlnbm9yZVJlc2VydmVkICYmIFJFU0VSVkVEX0dSQVBIUUxfVFlQRV9OQU1FUy5pbmNsdWRlcyh0eXBlLm5hbWUpKSB8fFxuICAgICAgdGhpcy5ncmFwaFFMVHlwZXMuZmluZChleGlzdGluZ1R5cGUgPT4gZXhpc3RpbmdUeXBlLm5hbWUgPT09IHR5cGUubmFtZSkgfHxcbiAgICAgICghaWdub3JlQ29ubmVjdGlvbiAmJiB0eXBlLm5hbWUuZW5kc1dpdGgoJ0Nvbm5lY3Rpb24nKSlcbiAgICApIHtcbiAgICAgIGNvbnN0IG1lc3NhZ2UgPSBgVHlwZSAke3R5cGUubmFtZX0gY291bGQgbm90IGJlIGFkZGVkIHRvIHRoZSBhdXRvIHNjaGVtYSBiZWNhdXNlIGl0IGNvbGxpZGVkIHdpdGggYW4gZXhpc3RpbmcgdHlwZS5gO1xuICAgICAgaWYgKHRocm93RXJyb3IpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKG1lc3NhZ2UpO1xuICAgICAgfVxuICAgICAgdGhpcy5fbG9nT25jZSgnd2FybicsIG1lc3NhZ2UpO1xuICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9XG4gICAgdGhpcy5ncmFwaFFMVHlwZXMucHVzaCh0eXBlKTtcbiAgICByZXR1cm4gdHlwZTtcbiAgfVxuXG4gIGFkZEdyYXBoUUxRdWVyeShmaWVsZE5hbWUsIGZpZWxkLCB0aHJvd0Vycm9yID0gZmFsc2UsIGlnbm9yZVJlc2VydmVkID0gZmFsc2UpIHtcbiAgICBpZiAoXG4gICAgICAoIWlnbm9yZVJlc2VydmVkICYmIFJFU0VSVkVEX0dSQVBIUUxfUVVFUllfTkFNRVMuaW5jbHVkZXMoZmllbGROYW1lKSkgfHxcbiAgICAgIHRoaXMuZ3JhcGhRTFF1ZXJpZXNbZmllbGROYW1lXVxuICAgICkge1xuICAgICAgY29uc3QgbWVzc2FnZSA9IGBRdWVyeSAke2ZpZWxkTmFtZX0gY291bGQgbm90IGJlIGFkZGVkIHRvIHRoZSBhdXRvIHNjaGVtYSBiZWNhdXNlIGl0IGNvbGxpZGVkIHdpdGggYW4gZXhpc3RpbmcgZmllbGQuYDtcbiAgICAgIGlmICh0aHJvd0Vycm9yKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihtZXNzYWdlKTtcbiAgICAgIH1cbiAgICAgIHRoaXMuX2xvZ09uY2UoJ3dhcm4nLCBtZXNzYWdlKTtcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuICAgIHRoaXMuZ3JhcGhRTFF1ZXJpZXNbZmllbGROYW1lXSA9IGZpZWxkO1xuICAgIHJldHVybiBmaWVsZDtcbiAgfVxuXG4gIGFkZEdyYXBoUUxNdXRhdGlvbihmaWVsZE5hbWUsIGZpZWxkLCB0aHJvd0Vycm9yID0gZmFsc2UsIGlnbm9yZVJlc2VydmVkID0gZmFsc2UpIHtcbiAgICBpZiAoXG4gICAgICAoIWlnbm9yZVJlc2VydmVkICYmIFJFU0VSVkVEX0dSQVBIUUxfTVVUQVRJT05fTkFNRVMuaW5jbHVkZXMoZmllbGROYW1lKSkgfHxcbiAgICAgIHRoaXMuZ3JhcGhRTE11dGF0aW9uc1tmaWVsZE5hbWVdXG4gICAgKSB7XG4gICAgICBjb25zdCBtZXNzYWdlID0gYE11dGF0aW9uICR7ZmllbGROYW1lfSBjb3VsZCBub3QgYmUgYWRkZWQgdG8gdGhlIGF1dG8gc2NoZW1hIGJlY2F1c2UgaXQgY29sbGlkZWQgd2l0aCBhbiBleGlzdGluZyBmaWVsZC5gO1xuICAgICAgaWYgKHRocm93RXJyb3IpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKG1lc3NhZ2UpO1xuICAgICAgfVxuICAgICAgdGhpcy5fbG9nT25jZSgnd2FybicsIG1lc3NhZ2UpO1xuICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9XG4gICAgdGhpcy5ncmFwaFFMTXV0YXRpb25zW2ZpZWxkTmFtZV0gPSBmaWVsZDtcbiAgICByZXR1cm4gZmllbGQ7XG4gIH1cblxuICBoYW5kbGVFcnJvcihlcnJvcikge1xuICAgIGlmIChlcnJvciBpbnN0YW5jZW9mIFBhcnNlLkVycm9yKSB7XG4gICAgICB0aGlzLmxvZy5lcnJvcignUGFyc2UgZXJyb3I6ICcsIGVycm9yKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5sb2cuZXJyb3IoJ1VuY2F1Z2h0IGludGVybmFsIHNlcnZlciBlcnJvci4nLCBlcnJvciwgZXJyb3Iuc3RhY2spO1xuICAgIH1cbiAgICB0aHJvdyB0b0dyYXBoUUxFcnJvcihlcnJvcik7XG4gIH1cblxuICBhc3luYyBfaW5pdGlhbGl6ZVNjaGVtYUFuZENvbmZpZygpIHtcbiAgICBjb25zdCBbc2NoZW1hQ29udHJvbGxlciwgcGFyc2VHcmFwaFFMQ29uZmlnXSA9IGF3YWl0IFByb21pc2UuYWxsKFtcbiAgICAgIHRoaXMuZGF0YWJhc2VDb250cm9sbGVyLmxvYWRTY2hlbWEoKSxcbiAgICAgIHRoaXMucGFyc2VHcmFwaFFMQ29udHJvbGxlci5nZXRHcmFwaFFMQ29uZmlnKCksXG4gICAgXSk7XG5cbiAgICB0aGlzLnNjaGVtYUNvbnRyb2xsZXIgPSBzY2hlbWFDb250cm9sbGVyO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgIHBhcnNlR3JhcGhRTENvbmZpZyxcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIEdldHMgYWxsIGNsYXNzZXMgZm91bmQgYnkgdGhlIGBzY2hlbWFDb250cm9sbGVyYFxuICAgKiBtaW51cyB0aG9zZSBmaWx0ZXJlZCBvdXQgYnkgdGhlIGFwcCdzIHBhcnNlR3JhcGhRTENvbmZpZy5cbiAgICovXG4gIGFzeW5jIF9nZXRDbGFzc2VzRm9yU2NoZW1hKHBhcnNlR3JhcGhRTENvbmZpZzogUGFyc2VHcmFwaFFMQ29uZmlnKSB7XG4gICAgY29uc3QgeyBlbmFibGVkRm9yQ2xhc3NlcywgZGlzYWJsZWRGb3JDbGFzc2VzIH0gPSBwYXJzZUdyYXBoUUxDb25maWc7XG4gICAgY29uc3QgYWxsQ2xhc3NlcyA9IGF3YWl0IHRoaXMuc2NoZW1hQ29udHJvbGxlci5nZXRBbGxDbGFzc2VzKCk7XG5cbiAgICBpZiAoQXJyYXkuaXNBcnJheShlbmFibGVkRm9yQ2xhc3NlcykgfHwgQXJyYXkuaXNBcnJheShkaXNhYmxlZEZvckNsYXNzZXMpKSB7XG4gICAgICBsZXQgaW5jbHVkZWRDbGFzc2VzID0gYWxsQ2xhc3NlcztcbiAgICAgIGlmIChlbmFibGVkRm9yQ2xhc3Nlcykge1xuICAgICAgICBpbmNsdWRlZENsYXNzZXMgPSBhbGxDbGFzc2VzLmZpbHRlcihjbGF6eiA9PiB7XG4gICAgICAgICAgcmV0dXJuIGVuYWJsZWRGb3JDbGFzc2VzLmluY2x1ZGVzKGNsYXp6LmNsYXNzTmFtZSk7XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgICAgaWYgKGRpc2FibGVkRm9yQ2xhc3Nlcykge1xuICAgICAgICAvLyBDbGFzc2VzIGluY2x1ZGVkIGluIGBlbmFibGVkRm9yQ2xhc3Nlc2AgdGhhdFxuICAgICAgICAvLyBhcmUgYWxzbyBwcmVzZW50IGluIGBkaXNhYmxlZEZvckNsYXNzZXNgIHdpbGxcbiAgICAgICAgLy8gc3RpbGwgYmUgZmlsdGVyZWQgb3V0XG4gICAgICAgIGluY2x1ZGVkQ2xhc3NlcyA9IGluY2x1ZGVkQ2xhc3Nlcy5maWx0ZXIoY2xhenogPT4ge1xuICAgICAgICAgIHJldHVybiAhZGlzYWJsZWRGb3JDbGFzc2VzLmluY2x1ZGVzKGNsYXp6LmNsYXNzTmFtZSk7XG4gICAgICAgIH0pO1xuICAgICAgfVxuXG4gICAgICB0aGlzLmlzVXNlcnNDbGFzc0Rpc2FibGVkID0gIWluY2x1ZGVkQ2xhc3Nlcy5zb21lKGNsYXp6ID0+IHtcbiAgICAgICAgcmV0dXJuIGNsYXp6LmNsYXNzTmFtZSA9PT0gJ19Vc2VyJztcbiAgICAgIH0pO1xuXG4gICAgICByZXR1cm4gaW5jbHVkZWRDbGFzc2VzO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gYWxsQ2xhc3NlcztcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogVGhpcyBtZXRob2QgcmV0dXJucyBhIGxpc3Qgb2YgdHVwbGVzXG4gICAqIHRoYXQgcHJvdmlkZSB0aGUgcGFyc2VDbGFzcyBhbG9uZyB3aXRoXG4gICAqIGl0cyBwYXJzZUNsYXNzQ29uZmlnIHdoZXJlIHByb3ZpZGVkLlxuICAgKi9cbiAgX2dldFBhcnNlQ2xhc3Nlc1dpdGhDb25maWcocGFyc2VDbGFzc2VzLCBwYXJzZUdyYXBoUUxDb25maWc6IFBhcnNlR3JhcGhRTENvbmZpZykge1xuICAgIGNvbnN0IHsgY2xhc3NDb25maWdzIH0gPSBwYXJzZUdyYXBoUUxDb25maWc7XG5cbiAgICAvLyBNYWtlIHN1cmVzIHRoYXQgdGhlIGRlZmF1bHQgY2xhc3NlcyBhbmQgY2xhc3NlcyB0aGF0XG4gICAgLy8gc3RhcnRzIHdpdGggY2FwaXRhbGl6ZWQgbGV0dGVyIHdpbGwgYmUgZ2VuZXJhdGVkIGZpcnN0LlxuICAgIGNvbnN0IHNvcnRDbGFzc2VzID0gKGEsIGIpID0+IHtcbiAgICAgIGEgPSBhLmNsYXNzTmFtZTtcbiAgICAgIGIgPSBiLmNsYXNzTmFtZTtcbiAgICAgIGlmIChhWzBdID09PSAnXycpIHtcbiAgICAgICAgaWYgKGJbMF0gIT09ICdfJykge1xuICAgICAgICAgIHJldHVybiAtMTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgaWYgKGJbMF0gPT09ICdfJykge1xuICAgICAgICBpZiAoYVswXSAhPT0gJ18nKSB7XG4gICAgICAgICAgcmV0dXJuIDE7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGlmIChhID09PSBiKSB7XG4gICAgICAgIHJldHVybiAwO1xuICAgICAgfSBlbHNlIGlmIChhIDwgYikge1xuICAgICAgICByZXR1cm4gLTE7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gMTtcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgcmV0dXJuIHBhcnNlQ2xhc3Nlcy5zb3J0KHNvcnRDbGFzc2VzKS5tYXAocGFyc2VDbGFzcyA9PiB7XG4gICAgICBsZXQgcGFyc2VDbGFzc0NvbmZpZztcbiAgICAgIGlmIChjbGFzc0NvbmZpZ3MpIHtcbiAgICAgICAgcGFyc2VDbGFzc0NvbmZpZyA9IGNsYXNzQ29uZmlncy5maW5kKGMgPT4gYy5jbGFzc05hbWUgPT09IHBhcnNlQ2xhc3MuY2xhc3NOYW1lKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBbcGFyc2VDbGFzcywgcGFyc2VDbGFzc0NvbmZpZ107XG4gICAgfSk7XG4gIH1cblxuICBhc3luYyBfZ2V0RnVuY3Rpb25OYW1lcygpIHtcbiAgICByZXR1cm4gYXdhaXQgZ2V0RnVuY3Rpb25OYW1lcyh0aGlzLmFwcElkKS5maWx0ZXIoZnVuY3Rpb25OYW1lID0+IHtcbiAgICAgIGlmICgvXltfYS16QS1aXVtfYS16QS1aMC05XSokLy50ZXN0KGZ1bmN0aW9uTmFtZSkpIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLl9sb2dPbmNlKFxuICAgICAgICAgICd3YXJuJyxcbiAgICAgICAgICBgRnVuY3Rpb24gJHtmdW5jdGlvbk5hbWV9IGNvdWxkIG5vdCBiZSBhZGRlZCB0byB0aGUgYXV0byBzY2hlbWEgYmVjYXVzZSBHcmFwaFFMIG5hbWVzIG11c3QgbWF0Y2ggL15bX2EtekEtWl1bX2EtekEtWjAtOV0qJC8uYFxuICAgICAgICApO1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogQ2hlY2tzIGZvciBjaGFuZ2VzIHRvIHRoZSBwYXJzZUNsYXNzZXNcbiAgICogb2JqZWN0cyAoaS5lLiBkYXRhYmFzZSBzY2hlbWEpIG9yIHRvXG4gICAqIHRoZSBwYXJzZUdyYXBoUUxDb25maWcgb2JqZWN0LiBJZiBub1xuICAgKiBjaGFuZ2VzIGFyZSBmb3VuZCwgcmV0dXJuIHRydWU7XG4gICAqL1xuICBfaGFzU2NoZW1hSW5wdXRDaGFuZ2VkKHBhcmFtczoge1xuICAgIHBhcnNlQ2xhc3NlczogYW55LFxuICAgIHBhcnNlR3JhcGhRTENvbmZpZzogP1BhcnNlR3JhcGhRTENvbmZpZyxcbiAgICBmdW5jdGlvbk5hbWVzU3RyaW5nOiBzdHJpbmcsXG4gIH0pOiBib29sZWFuIHtcbiAgICBjb25zdCB7IHBhcnNlQ2xhc3NlcywgcGFyc2VHcmFwaFFMQ29uZmlnLCBmdW5jdGlvbk5hbWVzU3RyaW5nIH0gPSBwYXJhbXM7XG5cbiAgICAvLyBGaXJzdCBpbml0XG4gICAgaWYgKCF0aGlzLmdyYXBoUUxTY2hlbWEpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIGlmIChcbiAgICAgIGlzRGVlcFN0cmljdEVxdWFsKHRoaXMucGFyc2VHcmFwaFFMQ29uZmlnLCBwYXJzZUdyYXBoUUxDb25maWcpICYmXG4gICAgICB0aGlzLmZ1bmN0aW9uTmFtZXNTdHJpbmcgPT09IGZ1bmN0aW9uTmFtZXNTdHJpbmcgJiZcbiAgICAgIGlzRGVlcFN0cmljdEVxdWFsKHRoaXMucGFyc2VDbGFzc2VzLCBwYXJzZUNsYXNzZXMpXG4gICAgKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIHJldHVybiB0cnVlO1xuICB9XG59XG5cbmV4cG9ydCB7IFBhcnNlR3JhcGhRTFNjaGVtYSB9O1xuIl0sIm1hcHBpbmdzIjoiOzs7Ozs7QUFBQSxJQUFBQSxLQUFBLEdBQUFDLHNCQUFBLENBQUFDLE9BQUE7QUFDQSxJQUFBQyxRQUFBLEdBQUFELE9BQUE7QUFDQSxJQUFBRSxPQUFBLEdBQUFGLE9BQUE7QUFDQSxJQUFBRyxNQUFBLEdBQUFILE9BQUE7QUFDQSxJQUFBSSxLQUFBLEdBQUFKLE9BQUE7QUFDQSxJQUFBSyxrQkFBQSxHQUFBTixzQkFBQSxDQUFBQyxPQUFBO0FBQ0EsSUFBQU0sbUJBQUEsR0FBQUMsdUJBQUEsQ0FBQVAsT0FBQTtBQUNBLElBQUFRLGVBQUEsR0FBQUQsdUJBQUEsQ0FBQVAsT0FBQTtBQUNBLElBQUFTLGlCQUFBLEdBQUFGLHVCQUFBLENBQUFQLE9BQUE7QUFDQSxJQUFBVSxtQkFBQSxHQUFBSCx1QkFBQSxDQUFBUCxPQUFBO0FBQ0EsSUFBQVcscUJBQUEsR0FBQUosdUJBQUEsQ0FBQVAsT0FBQTtBQUNBLElBQUFZLHVCQUFBLEdBQUFMLHVCQUFBLENBQUFQLE9BQUE7QUFDQSxJQUFBYSx1QkFBQSxHQUFBTix1QkFBQSxDQUFBUCxPQUFBO0FBQ0EsSUFBQWMsbUJBQUEsR0FBQWYsc0JBQUEsQ0FBQUMsT0FBQTtBQUNBLElBQUFlLFlBQUEs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