sonamu 0.9.5 → 0.9.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (159) hide show
  1. package/dist/api/config.d.ts +13 -2
  2. package/dist/api/config.d.ts.map +1 -1
  3. package/dist/api/config.js +1 -1
  4. package/dist/api/context.d.ts +17 -7
  5. package/dist/api/context.d.ts.map +1 -1
  6. package/dist/api/context.js +1 -1
  7. package/dist/api/decorators.d.ts +18 -0
  8. package/dist/api/decorators.d.ts.map +1 -1
  9. package/dist/api/decorators.js +55 -4
  10. package/dist/api/index.js +8 -3
  11. package/dist/api/sonamu.d.ts +24 -9
  12. package/dist/api/sonamu.d.ts.map +1 -1
  13. package/dist/api/sonamu.js +365 -79
  14. package/dist/api/websocket-helpers.d.ts +24 -0
  15. package/dist/api/websocket-helpers.d.ts.map +1 -0
  16. package/dist/api/websocket-helpers.js +77 -0
  17. package/dist/bin/cli.js +12 -4
  18. package/dist/dict/sonamu-dictionary.js +5 -5
  19. package/dist/entity/entity-manager.js +1 -1
  20. package/dist/entity/entity.js +3 -3
  21. package/dist/index.d.ts +6 -0
  22. package/dist/index.d.ts.map +1 -1
  23. package/dist/index.js +16 -4
  24. package/dist/migration/code-generation.js +7 -7
  25. package/dist/stream/index.d.ts +6 -0
  26. package/dist/stream/index.d.ts.map +1 -1
  27. package/dist/stream/index.js +13 -2
  28. package/dist/stream/ws-audience-resolver.d.ts +15 -0
  29. package/dist/stream/ws-audience-resolver.d.ts.map +1 -0
  30. package/dist/stream/ws-audience-resolver.js +31 -0
  31. package/dist/stream/ws-audience.d.ts +28 -0
  32. package/dist/stream/ws-audience.d.ts.map +1 -0
  33. package/dist/stream/ws-audience.js +46 -0
  34. package/dist/stream/ws-cluster-bus.d.ts +23 -0
  35. package/dist/stream/ws-cluster-bus.d.ts.map +1 -0
  36. package/dist/stream/ws-cluster-bus.js +18 -0
  37. package/dist/stream/ws-core.d.ts +15 -0
  38. package/dist/stream/ws-core.d.ts.map +1 -0
  39. package/dist/stream/ws-core.js +1 -0
  40. package/dist/stream/ws-delivery.d.ts +24 -0
  41. package/dist/stream/ws-delivery.d.ts.map +1 -0
  42. package/dist/stream/ws-delivery.js +103 -0
  43. package/dist/stream/ws-local-connection-store.d.ts +10 -0
  44. package/dist/stream/ws-local-connection-store.d.ts.map +1 -0
  45. package/dist/stream/ws-local-connection-store.js +44 -0
  46. package/dist/stream/ws-presence-store.d.ts +61 -0
  47. package/dist/stream/ws-presence-store.d.ts.map +1 -0
  48. package/dist/stream/ws-presence-store.js +236 -0
  49. package/dist/stream/ws-registry.d.ts +42 -0
  50. package/dist/stream/ws-registry.d.ts.map +1 -0
  51. package/dist/stream/ws-registry.js +108 -0
  52. package/dist/stream/ws.d.ts +52 -0
  53. package/dist/stream/ws.d.ts.map +1 -0
  54. package/dist/stream/ws.js +397 -0
  55. package/dist/syncer/api-parser.d.ts.map +1 -1
  56. package/dist/syncer/api-parser.js +72 -2
  57. package/dist/syncer/checksum.d.ts.map +1 -1
  58. package/dist/syncer/checksum.js +13 -12
  59. package/dist/syncer/code-generator.d.ts.map +1 -1
  60. package/dist/syncer/code-generator.js +7 -4
  61. package/dist/syncer/event-batcher.d.ts +27 -0
  62. package/dist/syncer/event-batcher.d.ts.map +1 -0
  63. package/dist/syncer/event-batcher.js +69 -0
  64. package/dist/syncer/file-patterns.d.ts +48 -26
  65. package/dist/syncer/file-patterns.d.ts.map +1 -1
  66. package/dist/syncer/file-patterns.js +71 -23
  67. package/dist/syncer/file-tracking.d.ts +13 -0
  68. package/dist/syncer/file-tracking.d.ts.map +1 -0
  69. package/dist/syncer/file-tracking.js +33 -0
  70. package/dist/syncer/index.js +2 -2
  71. package/dist/syncer/module-loader.d.ts +2 -11
  72. package/dist/syncer/module-loader.d.ts.map +1 -1
  73. package/dist/syncer/module-loader.js +3 -3
  74. package/dist/syncer/syncer-actions.d.ts +39 -6
  75. package/dist/syncer/syncer-actions.d.ts.map +1 -1
  76. package/dist/syncer/syncer-actions.js +125 -10
  77. package/dist/syncer/syncer.d.ts +33 -19
  78. package/dist/syncer/syncer.d.ts.map +1 -1
  79. package/dist/syncer/syncer.js +168 -168
  80. package/dist/syncer/watcher.d.ts +8 -0
  81. package/dist/syncer/watcher.d.ts.map +1 -0
  82. package/dist/syncer/watcher.js +105 -0
  83. package/dist/tasks/workflow-manager.d.ts.map +1 -1
  84. package/dist/tasks/workflow-manager.js +2 -1
  85. package/dist/template/implementations/services.template.d.ts.map +1 -1
  86. package/dist/template/implementations/services.template.js +36 -1
  87. package/dist/testing/bootstrap.d.ts.map +1 -1
  88. package/dist/testing/bootstrap.js +8 -1
  89. package/dist/testing/fixture-manager.js +1 -1
  90. package/dist/types/types.d.ts +2 -1
  91. package/dist/types/types.d.ts.map +1 -1
  92. package/dist/types/types.js +2 -2
  93. package/dist/ui/api.js +1 -1
  94. package/dist/ui/cdd-service.js +1 -1
  95. package/dist/ui-web/assets/{index-DzZ7vBk4.js → index-BmThfg-s.js} +37 -37
  96. package/dist/ui-web/index.html +1 -1
  97. package/dist/utils/async-utils.d.ts +27 -3
  98. package/dist/utils/async-utils.d.ts.map +1 -1
  99. package/dist/utils/async-utils.js +56 -6
  100. package/dist/utils/formatter.d.ts +7 -1
  101. package/dist/utils/formatter.d.ts.map +1 -1
  102. package/dist/utils/formatter.js +93 -59
  103. package/dist/utils/fs-utils.d.ts +2 -0
  104. package/dist/utils/fs-utils.d.ts.map +1 -1
  105. package/dist/utils/fs-utils.js +10 -2
  106. package/dist/utils/process-utils.d.ts +10 -4
  107. package/dist/utils/process-utils.d.ts.map +1 -1
  108. package/dist/utils/process-utils.js +20 -7
  109. package/dist/utils/utils.d.ts +1 -0
  110. package/dist/utils/utils.d.ts.map +1 -1
  111. package/dist/utils/utils.js +2 -2
  112. package/package.json +3 -1
  113. package/src/api/__tests__/sonamu.websocket.test.ts +64 -0
  114. package/src/api/__tests__/websocket-context.types.test.ts +58 -0
  115. package/src/api/config.ts +28 -2
  116. package/src/api/context.ts +21 -7
  117. package/src/api/decorators.ts +103 -3
  118. package/src/api/sonamu.ts +529 -127
  119. package/src/api/websocket-helpers.ts +122 -0
  120. package/src/bin/cli.ts +10 -2
  121. package/src/dict/sonamu-dictionary.ts +2 -2
  122. package/src/entity/entity.ts +1 -1
  123. package/src/index.ts +6 -0
  124. package/src/migration/code-generation.ts +5 -5
  125. package/src/shared/app.shared.ts.txt +254 -1
  126. package/src/shared/web.shared.ts.txt +282 -1
  127. package/src/stream/__tests__/ws-contracts.test.ts +381 -0
  128. package/src/stream/__tests__/ws.test.ts +449 -0
  129. package/src/stream/index.ts +6 -0
  130. package/src/stream/ws-audience-resolver.ts +35 -0
  131. package/src/stream/ws-audience.ts +62 -0
  132. package/src/stream/ws-cluster-bus.ts +32 -0
  133. package/src/stream/ws-core.ts +16 -0
  134. package/src/stream/ws-delivery.ts +138 -0
  135. package/src/stream/ws-local-connection-store.ts +44 -0
  136. package/src/stream/ws-presence-store.ts +326 -0
  137. package/src/stream/ws-registry.ts +138 -0
  138. package/src/stream/ws.ts +591 -0
  139. package/src/syncer/__tests__/api-parser.websocket-type-ref.test.ts +78 -0
  140. package/src/syncer/api-parser.ts +112 -1
  141. package/src/syncer/checksum.ts +23 -29
  142. package/src/syncer/code-generator.ts +4 -1
  143. package/src/syncer/event-batcher.ts +72 -0
  144. package/src/syncer/file-patterns.ts +98 -30
  145. package/src/syncer/file-tracking.ts +27 -0
  146. package/src/syncer/module-loader.ts +5 -12
  147. package/src/syncer/syncer-actions.ts +179 -17
  148. package/src/syncer/syncer.ts +250 -287
  149. package/src/syncer/watcher.ts +128 -0
  150. package/src/tasks/workflow-manager.ts +1 -0
  151. package/src/template/__tests__/services.template.websocket.test.ts +79 -0
  152. package/src/template/implementations/services.template.ts +69 -0
  153. package/src/testing/bootstrap.ts +8 -1
  154. package/src/types/types.ts +20 -2
  155. package/src/utils/async-utils.ts +71 -4
  156. package/src/utils/formatter.ts +111 -74
  157. package/src/utils/fs-utils.ts +9 -0
  158. package/src/utils/process-utils.ts +21 -4
  159. package/src/utils/utils.ts +1 -1
@@ -8,15 +8,18 @@ import { NotFoundException, init_so_exceptions } from "../exceptions/so-exceptio
8
8
  import { BufferedFile, init_buffered_file } from "../storage/buffered-file.js";
9
9
  import { UploadedFile, init_uploaded_file } from "../storage/uploaded-file.js";
10
10
  import { createMockSSEFactory, init_sse } from "../stream/sse.js";
11
+ import { WebSocketRuntime, init_ws } from "../stream/ws.js";
12
+ import { centerText, init_console_util } from "../utils/console-util.js";
11
13
  import { init_controller, isDaemonServer } from "../utils/controller.js";
12
14
  import { exists, fileExists, init_fs_utils } from "../utils/fs-utils.js";
13
15
  import { convertFastifyHeadersToStandard, init_utils, merge } from "../utils/utils.js";
14
16
  import { getSecrets, init_secret } from "./secret.js";
17
+ import { createWebSocketReplyStub, init_websocket_helpers, resolveIntegratedViteHmrOptions, resolveWebSocketCloseDescriptor, resolveWebSocketPluginOptions } from "./websocket-helpers.js";
15
18
  import { AsyncLocalStorage } from "async_hooks";
16
19
  import { dispose } from "@logtape/logtape";
17
- import assert from "assert";
18
20
  import fs from "fs/promises";
19
21
  import path from "path";
22
+ import chalk from "chalk";
20
23
  import os from "os";
21
24
  import mime, { lookup } from "mime-types";
22
25
 
@@ -37,6 +40,11 @@ function formatTime(ms) {
37
40
  function isLocalHost(host) {
38
41
  return LOCAL_HOSTS.has(host);
39
42
  }
43
+ function runGuards({ guards, config, request, api }) {
44
+ for (const guard of guards ?? []) {
45
+ config.guardHandler(guard, request, api);
46
+ }
47
+ }
40
48
  var SonamuClass, Sonamu, LOCAL_HOSTS;
41
49
  var init_sonamu = __esmMin((() => {
42
50
  init_better_auth_entities();
@@ -48,10 +56,13 @@ var init_sonamu = __esmMin((() => {
48
56
  init_buffered_file();
49
57
  init_uploaded_file();
50
58
  init_sse();
59
+ init_ws();
60
+ init_console_util();
51
61
  init_controller();
52
62
  init_fs_utils();
53
63
  init_utils();
54
64
  init_secret();
65
+ init_websocket_helpers();
55
66
  SonamuClass = class {
56
67
  isInitialized = false;
57
68
  forTesting = false;
@@ -63,10 +74,14 @@ var init_sonamu = __esmMin((() => {
63
74
  }
64
75
  if (process.env.NODE_ENV === "test") {
65
76
  return {
77
+ transport: "http",
66
78
  request: null,
67
79
  reply: null,
68
80
  headers: {},
69
81
  createSSE: (schema) => createMockSSEFactory(schema),
82
+ locale: "",
83
+ user: null,
84
+ session: null,
70
85
  naiteStore: new Map()
71
86
  };
72
87
  } else {
@@ -158,9 +173,18 @@ var init_sonamu = __esmMin((() => {
158
173
  set devVitestManager(manager) {
159
174
  this._devVitestManager = manager;
160
175
  }
176
+ _websocketRuntime = null;
177
+ websocketPluginServers = new WeakSet();
178
+ get websocketRuntime() {
179
+ if (!this._websocketRuntime) {
180
+ throw new Error("WebSocket runtime has not been initialized.");
181
+ }
182
+ return this._websocketRuntime;
183
+ }
184
+ set websocketRuntime(runtime) {
185
+ this._websocketRuntime = runtime;
186
+ }
161
187
  watcher = null;
162
- pendingFiles = [];
163
- hmrStartTime = 0;
164
188
  server = null;
165
189
  async initForTesting() {
166
190
  await this.init(true, false, undefined, true);
@@ -214,7 +238,7 @@ var init_sonamu = __esmMin((() => {
214
238
  await this.syncer.autoloadWorkflows();
215
239
  const { TemplateManager } = await import("../template/index.js");
216
240
  await TemplateManager.autoload();
217
- await this.syncer.autoloadSSRRoutes();
241
+ await this.syncer.autoloadSsrRoutes();
218
242
  const { isLocal, isTest, isHotReloadServer } = await import("../utils/controller.js");
219
243
  if (isLocal() && !isTest() && isHotReloadServer() && enableSync) {
220
244
  await this.syncer.sync();
@@ -238,6 +262,7 @@ var init_sonamu = __esmMin((() => {
238
262
  logger: this.config.logging !== false ? getLogTapeFastifyLogger({ category: this.config.logging?.fastifyCategory ?? ["fastify"] }) : undefined
239
263
  });
240
264
  this.server = server;
265
+ this.websocketRuntime = new WebSocketRuntime(options.websocket);
241
266
  if (options.storage) {
242
267
  const { StorageManager } = await import("../storage/storage-manager.js");
243
268
  this._storage = new StorageManager(options.storage);
@@ -263,6 +288,7 @@ var init_sonamu = __esmMin((() => {
263
288
  await this.init(options?.doSilent, options?.enableSync);
264
289
  }
265
290
  this.server = server;
291
+ this.websocketRuntime ??= new WebSocketRuntime(this.config.server.websocket);
266
292
  const timezone = this.config.api.timezone;
267
293
  if (timezone) {
268
294
  const { formatInTimeZone } = await import("date-fns-tz");
@@ -319,6 +345,15 @@ var init_sonamu = __esmMin((() => {
319
345
  if (this.syncer.models[api.modelName] === undefined) {
320
346
  throw new Error(`정의되지 않은 모델에 접근 ${api.modelName}`);
321
347
  }
348
+ if (api.websocketOptions) {
349
+ server.route({
350
+ method: "GET",
351
+ url: this.config.api.route.prefix + api.path,
352
+ handler: this.createWebSocketUpgradeRequiredHandler(),
353
+ wsHandler: this.createWebSocketHandler(api, config)
354
+ });
355
+ continue;
356
+ }
322
357
  server.route({
323
358
  method: api.options.httpMethod ?? "GET",
324
359
  url: this.config.api.route.prefix + api.path,
@@ -337,12 +372,22 @@ var init_sonamu = __esmMin((() => {
337
372
  * 요청이 /api(정확히는 this.config.api.route.prefix)로 시작하지 않는 경우라면 null을 반환하며 끝냅니다.
338
373
  */
339
374
  handleDevApiRequest(request, config) {
375
+ const matchedApi = this.findMatchedApi(request);
376
+ if (!matchedApi) {
377
+ throw new NotFoundException(SD("error.api.notFound"));
378
+ }
379
+ if (matchedApi.websocketOptions) {
380
+ return this.createWebSocketUpgradeRequiredHandler();
381
+ }
382
+ return this.createApiHandler(matchedApi, config);
383
+ }
384
+ findMatchedApi(request) {
340
385
  const url = this.getPathnameFromUrl(request.url);
341
386
  const method = request.method;
342
387
  if (!url.startsWith(this.config.api.route.prefix)) {
343
- return null;
388
+ return undefined;
344
389
  }
345
- const matchedApi = this.syncer.apis.find((api) => {
390
+ return this.syncer.apis.find((api) => {
346
391
  if (this.syncer.models[api.modelName] === undefined) {
347
392
  return false;
348
393
  }
@@ -351,19 +396,28 @@ var init_sonamu = __esmMin((() => {
351
396
  const fullPath = this.config.api.route.prefix + api.path;
352
397
  return this.isPathPatternMatch(fullPath, url);
353
398
  });
354
- if (!matchedApi) {
355
- throw new NotFoundException(SD("error.api.notFound"));
356
- }
357
- return this.createApiHandler(matchedApi, config);
358
399
  }
359
400
  /**
360
401
  * dev api 모드: Vite 없이 API 동적 라우팅만 제공합니다.
361
402
  * HMR을 위해 catch-all에서 매 요청마다 syncer.apis를 조회합니다.
362
403
  */
363
404
  setupDevServer(server, config) {
405
+ server.route({
406
+ method: "GET",
407
+ url: `${this.config.api.route.prefix}/*`,
408
+ handler: async (request, reply) => {
409
+ const handler = this.handleDevApiRequest(request, config);
410
+ if (handler) {
411
+ return handler(request, reply);
412
+ }
413
+ throw new NotFoundException(SD("error.api.notFound"));
414
+ },
415
+ wsHandler: async (connection, request) => {
416
+ await this.handleDevWebSocketRequest(connection.socket, request, config);
417
+ }
418
+ });
364
419
  server.route({
365
420
  method: [
366
- "GET",
367
421
  "HEAD",
368
422
  "POST",
369
423
  "PUT",
@@ -388,11 +442,16 @@ var init_sonamu = __esmMin((() => {
388
442
  async setupDevServerWithVite(server, webPath, config) {
389
443
  await server.register((await import("@fastify/middie")).default);
390
444
  const vite = await import("vite");
445
+ const requiresDedicatedHmrServer = Boolean(this.config.server.plugins?.ws);
446
+ const hmr = resolveIntegratedViteHmrOptions({
447
+ httpServer: server.server,
448
+ requiresDedicatedWebSocketServer: requiresDedicatedHmrServer
449
+ });
391
450
  this.viteServer = await vite.createServer({
392
451
  root: webPath,
393
452
  server: {
394
453
  middlewareMode: true,
395
- hmr: { server: server.server }
454
+ hmr
396
455
  },
397
456
  appType: "custom"
398
457
  });
@@ -402,21 +461,41 @@ var init_sonamu = __esmMin((() => {
402
461
  }
403
462
  return this.viteServer.middlewares(req, res, next);
404
463
  });
464
+ server.route({
465
+ method: "GET",
466
+ url: `${this.config.api.route.prefix}/*`,
467
+ handler: async (request, reply) => {
468
+ const result = this.handleDevApiRequest(request, config);
469
+ if (result) {
470
+ return result(request, reply);
471
+ }
472
+ throw new NotFoundException(SD("error.api.notFound"));
473
+ },
474
+ wsHandler: async (connection, request) => {
475
+ await this.handleDevWebSocketRequest(connection.socket, request, config);
476
+ }
477
+ });
405
478
  server.route({
406
479
  method: [
407
- "GET",
408
480
  "HEAD",
409
481
  "POST",
410
482
  "PUT",
411
483
  "DELETE",
412
484
  "PATCH"
413
485
  ],
414
- url: "/*",
486
+ url: `${this.config.api.route.prefix}/*`,
415
487
  handler: async (request, reply) => {
416
488
  const result = this.handleDevApiRequest(request, config);
417
489
  if (result) {
418
490
  return result(request, reply);
419
491
  }
492
+ throw new NotFoundException(SD("error.api.notFound"));
493
+ }
494
+ });
495
+ server.route({
496
+ method: ["GET", "HEAD"],
497
+ url: "/*",
498
+ handler: async (request, reply) => {
420
499
  const url = request.url;
421
500
  const { matchSSRRoute, renderSSR } = await import("../ssr/index.js");
422
501
  const ssrMatch = matchSSRRoute(url);
@@ -443,8 +522,11 @@ var init_sonamu = __esmMin((() => {
443
522
  server.addHook("onClose", async () => {
444
523
  await this.viteServer.close();
445
524
  });
446
- const chalk = (await import("chalk")).default;
447
- console.log(chalk.dim(" Vite dev server integrated"));
525
+ const chalk$1 = (await import("chalk")).default;
526
+ if ("port" in hmr) {
527
+ console.log(chalk$1.dim(`✓ Vite HMR using dedicated websocket port ${hmr.port} to avoid Fastify websocket conflicts`));
528
+ }
529
+ console.log(chalk$1.dim("✓ Vite dev server integrated"));
448
530
  }
449
531
  async setupStaticWebServer(server, config, globalCompressOptions) {
450
532
  const webDistPath = path.join(this.apiRootPath, "web-dist", "client");
@@ -575,7 +657,12 @@ var init_sonamu = __esmMin((() => {
575
657
  return async (request, reply) => {
576
658
  const context = await this.createContext(config, request, reply);
577
659
  return this.asyncLocalStorage.run({ context }, async () => {
578
- (api.options.guards ?? []).every((guard) => config.guardHandler(guard, request, api));
660
+ runGuards({
661
+ guards: api.options.guards,
662
+ config,
663
+ request,
664
+ api
665
+ });
579
666
  const { getZodObjectFromApi } = await import("./code-converters.js");
580
667
  const ReqType = getZodObjectFromApi(api, this.syncer.types);
581
668
  const which = api.options.httpMethod === "GET" ? "query" : "body";
@@ -667,6 +754,151 @@ var init_sonamu = __esmMin((() => {
667
754
  });
668
755
  };
669
756
  }
757
+ createWebSocketUpgradeRequiredHandler() {
758
+ return async (_request, reply) => {
759
+ reply.header("connection", "Upgrade").header("upgrade", "websocket").status(426).send({ message: "WebSocket upgrade required" });
760
+ };
761
+ }
762
+ async handleDevWebSocketRequest(socket, request, config) {
763
+ const matchedApi = this.findMatchedApi(request);
764
+ if (!matchedApi?.websocketOptions) {
765
+ socket.close(1008, "WebSocket route not found");
766
+ return;
767
+ }
768
+ const handler = this.createWebSocketHandler(matchedApi, config);
769
+ await handler({ socket }, request);
770
+ }
771
+ createWebSocketHandler(api, config) {
772
+ return async (connection, request) => {
773
+ const socket = connection.socket;
774
+ let wsContext = null;
775
+ let rawWs = null;
776
+ try {
777
+ runGuards({
778
+ guards: api.options.guards,
779
+ config,
780
+ request,
781
+ api
782
+ });
783
+ const reqBody = await this.parseWebSocketRequestParams(api, request);
784
+ rawWs = this.websocketRuntime.registerConnection(socket, {
785
+ outEvents: api.websocketOptions.outEvents,
786
+ inEvents: api.websocketOptions.inEvents,
787
+ namespace: api.websocketOptions.namespace,
788
+ heartbeat: api.websocketOptions.heartbeat,
789
+ maxPayload: api.websocketOptions.maxPayload,
790
+ active: false
791
+ });
792
+ const scopedWs = this.createScopedWebSocketConnection(rawWs, () => wsContext);
793
+ wsContext = await this.createWebSocketContext(config, request, scopedWs);
794
+ this.websocketRuntime.activateConnection(rawWs.id);
795
+ const { ApiParamType } = await import("../types/types.js");
796
+ const args = api.parameters.map((param) => {
797
+ if (ApiParamType.isContext(param.type)) {
798
+ return wsContext;
799
+ }
800
+ return reqBody[param.name];
801
+ });
802
+ await this.asyncLocalStorage.run({ context: wsContext }, async () => {
803
+ await this.invokeModelMethod(api, args);
804
+ });
805
+ } catch (error) {
806
+ const closeDescriptor = resolveWebSocketCloseDescriptor(error);
807
+ if (rawWs) {
808
+ rawWs.close(closeDescriptor.code, closeDescriptor.reason);
809
+ } else if (socket.readyState < 2) {
810
+ socket.close(closeDescriptor.code, closeDescriptor.reason);
811
+ }
812
+ if (this.server?.log) {
813
+ const payload = {
814
+ err: error,
815
+ modelName: api.modelName,
816
+ methodName: api.methodName,
817
+ path: api.path
818
+ };
819
+ if (closeDescriptor.logLevel === "warn") {
820
+ this.server.log.warn(payload, closeDescriptor.reason);
821
+ } else {
822
+ this.server.log.error(payload, closeDescriptor.reason);
823
+ }
824
+ } else {
825
+ if (closeDescriptor.logLevel === "warn") {
826
+ console.warn(closeDescriptor.reason, error);
827
+ } else {
828
+ console.error(closeDescriptor.reason, error);
829
+ }
830
+ }
831
+ }
832
+ };
833
+ }
834
+ createScopedWebSocketConnection(ws, getContext) {
835
+ const runInContext = (callback) => {
836
+ const context = getContext();
837
+ if (!context) {
838
+ return callback();
839
+ }
840
+ return this.asyncLocalStorage.run({ context }, callback);
841
+ };
842
+ return {
843
+ get id() {
844
+ return ws.id;
845
+ },
846
+ get namespace() {
847
+ return ws.namespace;
848
+ },
849
+ get closed() {
850
+ return ws.closed;
851
+ },
852
+ transport: "ws",
853
+ publishUntyped(event, data) {
854
+ ws.publishUntyped(event, data);
855
+ },
856
+ close(code, reason) {
857
+ ws.close(code, reason);
858
+ },
859
+ onClose(callback) {
860
+ ws.onClose(() => runInContext(callback));
861
+ },
862
+ onMessage(event, handler) {
863
+ ws.onMessage(event, (data) => runInContext(() => handler(data)));
864
+ },
865
+ publish(event, data) {
866
+ ws.publish(event, data);
867
+ },
868
+ waitForClose() {
869
+ return ws.waitForClose();
870
+ },
871
+ join(roomId) {
872
+ ws.join(roomId);
873
+ },
874
+ leave(roomId) {
875
+ ws.leave(roomId);
876
+ },
877
+ setUserId(userId) {
878
+ ws.setUserId(userId);
879
+ },
880
+ clearUserId() {
881
+ ws.clearUserId();
882
+ }
883
+ };
884
+ }
885
+ async parseWebSocketRequestParams(api, request) {
886
+ const { getZodObjectFromApi } = await import("./code-converters.js");
887
+ const ReqType = getZodObjectFromApi(api, this.syncer.types);
888
+ try {
889
+ const { fastifyCaster } = await import("./caster.js");
890
+ return fastifyCaster(ReqType).parse(request.query ?? {});
891
+ } catch (e) {
892
+ const { ZodError } = await import("zod");
893
+ if (e instanceof ZodError) {
894
+ const { humanizeZodError } = await import("../utils/zod-error.js");
895
+ const messages = humanizeZodError(e).map((issue) => issue.message).join(" ");
896
+ const { BadRequestException } = await import("../exceptions/so-exceptions.js");
897
+ throw new BadRequestException(messages, { zodError: e });
898
+ }
899
+ throw e;
900
+ }
901
+ }
670
902
  /**
671
903
  * URL에서 path params를 추출합니다.
672
904
  * 예: pattern="/admin/companies/:companyId", url="/admin/companies/123" → { companyId: "123" }
@@ -762,7 +994,7 @@ var init_sonamu = __esmMin((() => {
762
994
  async invokeModelMethod(api, args, reply) {
763
995
  const model = this.syncer.models[api.modelName];
764
996
  const result = await model[api.methodName].apply(model, args);
765
- reply.type(api.options.contentType ?? "application/json");
997
+ reply?.type(api.options.contentType ?? "application/json");
766
998
  return result;
767
999
  }
768
1000
  async createContext(config, request, reply) {
@@ -771,7 +1003,8 @@ var init_sonamu = __esmMin((() => {
771
1003
  const locale = this.detectLocale(request.headers["accept-language"], this.config.i18n.supportedLocales) ?? this.config.i18n.defaultLocale;
772
1004
  const headers = convertFastifyHeadersToStandard(request.headers);
773
1005
  const session = await this._auth?.api.getSession({ headers }) ?? null;
774
- const context = { ...await Promise.resolve(config.contextProvider({
1006
+ const context = await Promise.resolve(config.contextProvider({
1007
+ transport: "http",
775
1008
  request,
776
1009
  reply,
777
1010
  headers: request.headers,
@@ -780,9 +1013,50 @@ var init_sonamu = __esmMin((() => {
780
1013
  locale,
781
1014
  user: session?.user ?? null,
782
1015
  session: session?.session ?? null
783
- }, request, reply)) };
1016
+ }, request, reply));
784
1017
  return context;
785
1018
  }
1019
+ async createWebSocketContext(config, request, ws) {
1020
+ const locale = this.detectLocale(request.headers["accept-language"], this.config.i18n.supportedLocales) ?? this.config.i18n.defaultLocale;
1021
+ const headers = convertFastifyHeadersToStandard(request.headers);
1022
+ const session = await this._auth?.api.getSession({ headers }) ?? null;
1023
+ const defaultContext = {
1024
+ transport: "ws",
1025
+ request,
1026
+ headers: request.headers,
1027
+ ws,
1028
+ naiteStore: new Map(),
1029
+ locale,
1030
+ user: session?.user ?? null,
1031
+ session: session?.session ?? null
1032
+ };
1033
+ if (config.websocketContextProvider) {
1034
+ return { ...await Promise.resolve(config.websocketContextProvider(defaultContext, request)) };
1035
+ }
1036
+ const replyStub = createWebSocketReplyStub();
1037
+ const createSSE = (_events) => {
1038
+ throw new Error("createSSE is not available in websocket context. Define websocketContextProvider if your context setup depends on SSE helpers.");
1039
+ };
1040
+ const httpLikeContext = await Promise.resolve(config.contextProvider({
1041
+ transport: "http",
1042
+ request,
1043
+ reply: replyStub,
1044
+ headers: request.headers,
1045
+ createSSE,
1046
+ naiteStore: defaultContext.naiteStore,
1047
+ locale,
1048
+ user: defaultContext.user,
1049
+ session: defaultContext.session
1050
+ }, request, replyStub));
1051
+ const { transport: _transport, reply: _reply, createSSE: _createSSE, bufferedFiles: _bufferedFiles, uploadedFiles: _uploadedFiles, ...rest } = httpLikeContext;
1052
+ return {
1053
+ ...rest,
1054
+ transport: "ws",
1055
+ request,
1056
+ headers: request.headers,
1057
+ ws
1058
+ };
1059
+ }
786
1060
  /**
787
1061
  * Accept-Language 헤더에서 지원하는 locale을 찾습니다.
788
1062
  * @example "ko-KR,ko;q=0.9,en;q=0.8" → "ko"
@@ -796,33 +1070,24 @@ var init_sonamu = __esmMin((() => {
796
1070
  return langs.find((lang) => supported.includes(lang));
797
1071
  }
798
1072
  async startWatcher() {
799
- const watchPath = [path.join(this.apiRootPath, "src")];
800
- const chokidar = (await import("chokidar")).default;
801
- this.watcher = chokidar.watch(watchPath, {
802
- ignored: (path$1, stats) => !!stats?.isFile() && !path$1.endsWith(".ts") && !path$1.endsWith(".json"),
803
- persistent: true,
804
- ignoreInitial: true
805
- });
806
- this.watcher.on("all", async (event, filePath) => {
807
- const absolutePath = filePath;
808
- assert(absolutePath.startsWith(this.apiRootPath), "File path is not within the API root path");
809
- if (event !== "change" && event !== "add") {
810
- return;
811
- }
812
- try {
813
- const isConfigTs = filePath === path.join(this.apiRootPath, "src", "sonamu.config.ts");
814
- if (isConfigTs) {
815
- const relativePath = filePath.replace(this.apiRootPath, "api");
816
- const chalk = (await import("chalk")).default;
817
- console.log(chalk.bold(`Detected(${event}): ${chalk.blue(relativePath)} - Restarting...`));
818
- process.kill(process.pid, "SIGUSR2");
819
- return;
820
- }
821
- await this.handleFileChange(event, absolutePath);
822
- } catch (e) {
823
- console.error(e);
824
- }
825
- });
1073
+ const { setupWatcher } = await import("../syncer/watcher.js");
1074
+ this.watcher = await setupWatcher((fileEvents) => this.runHmrSyncCycle(fileEvents));
1075
+ }
1076
+ /**
1077
+ * Watcher가 100ms batch로 모은 fileEvents 하나에 대해 한 번의 HMR/sync 사이클을 돕니다.
1078
+ * batch 큐잉 덕에 한 시점에 하나만 실행됨이 보장됩니다 (event-batcher가 직렬화).
1079
+ */
1080
+ async runHmrSyncCycle(fileEvents) {
1081
+ const startedAt = Date.now();
1082
+ for (const [filePath, event] of fileEvents) {
1083
+ const relativePath = path.relative(this.appRootPath, filePath);
1084
+ console.log(chalk.bold(`Detected(${event}): ${chalk.blue(relativePath)}`));
1085
+ }
1086
+ await this.syncer.hmrAndSync(fileEvents);
1087
+ await this.syncer.renewChecksums();
1088
+ const totalTime = Date.now() - startedAt;
1089
+ const msg = `HMR Done! ${chalk.bold.white(`${totalTime}ms`)}`;
1090
+ console.log(chalk.black.bgGreen(centerText(msg)));
826
1091
  }
827
1092
  async runScript(fn) {
828
1093
  await this.init(true, false, undefined, false);
@@ -875,10 +1140,51 @@ var init_sonamu = __esmMin((() => {
875
1140
  for (const [key, pluginName] of Object.entries(pluginsModules)) {
876
1141
  await registerPlugin(key, pluginName);
877
1142
  }
1143
+ if (plugins.ws) {
1144
+ await this.ensureWebSocketPlugin(server);
1145
+ }
878
1146
  if (plugins.custom) {
879
1147
  plugins.custom(server);
880
1148
  }
881
1149
  }
1150
+ async ensureWebSocketPlugin(server) {
1151
+ if (this.websocketPluginServers.has(server)) {
1152
+ return;
1153
+ }
1154
+ const pluginOption = this.config.server.plugins?.ws;
1155
+ if (!pluginOption) {
1156
+ return;
1157
+ }
1158
+ const websocketPlugin = (await import("@fastify/websocket")).default;
1159
+ const resolvedPluginOptions = resolveWebSocketPluginOptions({
1160
+ rawPluginOption: pluginOption,
1161
+ apis: this.syncer.apis
1162
+ });
1163
+ if (resolvedPluginOptions) {
1164
+ await server.register(websocketPlugin, resolvedPluginOptions);
1165
+ } else {
1166
+ await server.register(websocketPlugin);
1167
+ }
1168
+ this.websocketPluginServers.add(server);
1169
+ this.warnOnPotentialWebSocketTimeoutConflicts(server);
1170
+ }
1171
+ warnOnPotentialWebSocketTimeoutConflicts(server) {
1172
+ const heartbeats = this.syncer.apis.map((api) => api.websocketOptions?.heartbeat ?? 3e4).filter((heartbeat) => heartbeat > 0);
1173
+ if (heartbeats.length === 0) {
1174
+ return;
1175
+ }
1176
+ const keepAliveTimeout = this.config.server.fastify?.keepAliveTimeout;
1177
+ if (!keepAliveTimeout || keepAliveTimeout <= 0) {
1178
+ return;
1179
+ }
1180
+ const largestHeartbeat = Math.max(...heartbeats);
1181
+ if (largestHeartbeat >= keepAliveTimeout) {
1182
+ server.log.warn({
1183
+ keepAliveTimeout,
1184
+ largestHeartbeat
1185
+ }, "WebSocket heartbeat is greater than or equal to keepAliveTimeout; align infrastructure idle timeouts to avoid unexpected disconnects.");
1186
+ }
1187
+ }
882
1188
  /**
883
1189
  * better-auth 라우트를 등록합니다.
884
1190
  * /api/auth/* 경로로 인증 API가 자동 등록됩니다.
@@ -916,11 +1222,11 @@ var init_sonamu = __esmMin((() => {
916
1222
  });
917
1223
  }
918
1224
  async printStartupSummary() {
919
- const chalk = (await import("chalk")).default;
1225
+ const chalk$1 = (await import("chalk")).default;
920
1226
  const env = process.env.NODE_ENV ?? "development";
921
1227
  const activePreset = env === "production" ? "production_master" : "development_master";
922
- const dim = (msg) => console.log(chalk.dim(`✓ ${msg}`));
923
- const green = (msg) => console.log(chalk.green(`✓ ${msg}`));
1228
+ const dim = (msg) => console.log(chalk$1.dim(`✓ ${msg}`));
1229
+ const green = (msg) => console.log(chalk$1.green(`✓ ${msg}`));
924
1230
  dim(`Config loaded${formatTime(this._configElapsed)}`);
925
1231
  green("DB");
926
1232
  const { isLocal } = await import("../utils/controller.js");
@@ -931,11 +1237,11 @@ var init_sonamu = __esmMin((() => {
931
1237
  const host = conn?.host ?? "localhost";
932
1238
  const addr = `@ ${host}:${conn?.port ?? 5432}/${conn?.database ?? this.config.database.name}`;
933
1239
  const padded = name.padEnd(maxLen);
934
- const remoteTag = isLocal() && !isLocalHost(host) ? chalk.yellow(` \u26a0 remote`) : "";
1240
+ const remoteTag = isLocal() && !isLocalHost(host) ? chalk$1.yellow(` \u26a0 remote`) : "";
935
1241
  if (name === activePreset) {
936
- console.log(chalk.green(` \u25b8 ${padded} ${addr}`) + remoteTag);
1242
+ console.log(chalk$1.green(` \u25b8 ${padded} ${addr}`) + remoteTag);
937
1243
  } else {
938
- console.log(chalk.dim(` ${padded} ${addr}`) + remoteTag);
1244
+ console.log(chalk$1.dim(` ${padded} ${addr}`) + remoteTag);
939
1245
  }
940
1246
  }
941
1247
  if (this.config.server.auth) {
@@ -1011,43 +1317,23 @@ var init_sonamu = __esmMin((() => {
1011
1317
  await this.workflows.startWorker();
1012
1318
  await options.lifecycle?.onStart?.(server);
1013
1319
  }).catch(async (err) => {
1014
- const chalk = (await import("chalk")).default;
1015
- console.error(chalk.red("Failed to start server:", err));
1320
+ const chalk$1 = (await import("chalk")).default;
1321
+ console.error(chalk$1.red("Failed to start server:", err));
1016
1322
  await shutdown();
1017
1323
  });
1018
1324
  }
1019
- async handleFileChange(event, filePath) {
1020
- if (this.pendingFiles.length === 0) {
1021
- this.hmrStartTime = Date.now();
1022
- }
1023
- this.pendingFiles.push(filePath);
1024
- const relativePath = path.relative(this.apiRootPath, filePath);
1025
- const chalk = (await import("chalk")).default;
1026
- console.log(chalk.bold(`Detected(${event}): ${chalk.blue(relativePath)}`));
1027
- await this.syncer.syncFromWatcher(event, filePath);
1028
- this.pendingFiles = this.pendingFiles.slice(1);
1029
- if (this.pendingFiles.length === 0) {
1030
- await this.finishHMR();
1031
- }
1032
- }
1033
- async finishHMR() {
1034
- await this.syncer.renewChecksums();
1035
- const endTime = Date.now();
1036
- const totalTime = endTime - this.hmrStartTime;
1037
- const [chalk, { centerText }] = await Promise.all([(await import("chalk")).default, import("../utils/console-util.js")]);
1038
- const msg = `HMR Done! ${chalk.bold.white(`${totalTime}ms`)}`;
1039
- console.log(chalk.black.bgGreen(centerText(msg)));
1040
- }
1041
1325
  async destroy() {
1042
1326
  const { BaseModel } = await import("../database/base-model.js");
1043
1327
  await BaseModel.destroy();
1044
1328
  await Promise.allSettled([
1329
+ this._websocketRuntime?.shutdown() ?? Promise.resolve(),
1045
1330
  this._workflows?.destroy() ?? Promise.resolve(),
1046
1331
  this._cache?.disconnect() ?? Promise.resolve(),
1047
1332
  this._devVitestManager?.shutdown() ?? Promise.resolve(),
1048
1333
  this.watcher?.close() ?? Promise.resolve(),
1049
1334
  dispose()
1050
1335
  ]);
1336
+ this._websocketRuntime = null;
1051
1337
  }
1052
1338
  };
1053
1339
  Sonamu = new SonamuClass();
@@ -1061,5 +1347,5 @@ var init_sonamu = __esmMin((() => {
1061
1347
 
1062
1348
  //#endregion
1063
1349
  init_sonamu();
1064
- export { Sonamu, init_sonamu };
1065
- //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic29uYW11LmpzIiwibmFtZXMiOlsiREIiLCJhdXRoT3B0aW9uczogQmV0dGVyQXV0aE9wdGlvbnMiLCJnbG9iYWxDb21wcmVzc09wdGlvbnM6IENvbXByZXNzT3B0aW9ucyB8IHVuZGVmaW5lZCIsImZzIiwiY2FjaGVSZXE6IENhY2hlQ29udHJvbFJlcXVlc3QiLCJmaWxlUGF0aCIsImNzckNhY2hlUmVxOiBDYWNoZUNvbnRyb2xSZXF1ZXN0IiwibWltZUxvb2t1cCIsImNvbnRleHQ6IENvbnRleHQiLCJyZXFCb2R5OiB7XG4gICAgICAgICAgW2tleTogc3RyaW5nXTogdW5rbm93bjtcbiAgICAgICAgfSIsImZpbGVzOiB7XG4gICAgICAgICAgYnVmZmVyZWRGaWxlczogQnVmZmVyZWRGaWxlW107XG4gICAgICAgICAgdXBsb2FkZWRGaWxlczogVXBsb2FkZWRGaWxlW107XG4gICAgICAgIH0iLCJmaWVsZHM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4iLCJrZXlHZW5lcmF0b3I6IEtleUdlbmVyYXRvciIsInBhcmFtczogUmVjb3JkPHN0cmluZywgc3RyaW5nPiIsInBhdGgiLCJsb2d0YXBlRGlzcG9zZSJdLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9hcGkvc29uYW11LnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBhc3NlcnQgZnJvbSBcImFzc2VydFwiO1xuaW1wb3J0IHsgQXN5bmNMb2NhbFN0b3JhZ2UgfSBmcm9tIFwiYXN5bmNfaG9va3NcIjtcbmltcG9ydCBmcyBmcm9tIFwiZnMvcHJvbWlzZXNcIjtcbmltcG9ydCB7IHR5cGUgSW5jb21pbmdNZXNzYWdlLCB0eXBlIFNlcnZlciwgdHlwZSBTZXJ2ZXJSZXNwb25zZSB9IGZyb20gXCJodHRwXCI7XG5pbXBvcnQgb3MgZnJvbSBcIm9zXCI7XG5pbXBvcnQgcGF0aCBmcm9tIFwicGF0aFwiO1xuXG5pbXBvcnQgeyBkaXNwb3NlIGFzIGxvZ3RhcGVEaXNwb3NlIH0gZnJvbSBcIkBsb2d0YXBlL2xvZ3RhcGVcIjtcbmltcG9ydCB7IHR5cGUgQXV0aCwgdHlwZSBCZXR0ZXJBdXRoT3B0aW9ucyB9IGZyb20gXCJiZXR0ZXItYXV0aFwiO1xuaW1wb3J0IHsgdHlwZSBGU1dhdGNoZXIgfSBmcm9tIFwiY2hva2lkYXJcIjtcbmltcG9ydCB7IHR5cGUgRmFzdGlmeUluc3RhbmNlLCB0eXBlIEZhc3RpZnlSZXBseSwgdHlwZSBGYXN0aWZ5UmVxdWVzdCB9IGZyb20gXCJmYXN0aWZ5XCI7XG5pbXBvcnQgbWltZSwgeyBsb29rdXAgYXMgbWltZUxvb2t1cCB9IGZyb20gXCJtaW1lLXR5cGVzXCI7XG5pbXBvcnQgeyB0eXBlIFpvZE9iamVjdCB9IGZyb20gXCJ6b2RcIjtcblxuaW1wb3J0IHsgQkFTRV9GSUVMRF9NQVBQSU5HUyB9IGZyb20gXCIuLi9hdXRoL2JldHRlci1hdXRoLWVudGl0aWVzXCI7XG5pbXBvcnQgeyBhcHBseUNhY2hlSGVhZGVycywgQ2FjaGVQcmVzZXRzIH0gZnJvbSBcIi4uL2NhY2hlLWNvbnRyb2wvY2FjaGUtY29udHJvbFwiO1xuaW1wb3J0IHsgdHlwZSBDYWNoZUNvbnRyb2xDb25maWcsIHR5cGUgQ2FjaGVDb250cm9sUmVxdWVzdCB9IGZyb20gXCIuLi9jYWNoZS1jb250cm9sL3R5cGVzXCI7XG5pbXBvcnQgeyB0eXBlIENhY2hlQ29uZmlnLCB0eXBlIENhY2hlTWFuYWdlciB9IGZyb20gXCIuLi9jYWNoZS90eXBlc1wiO1xuaW1wb3J0IHsgdG9GYXN0aWZ5Q29tcHJlc3NPcHRpb24gfSBmcm9tIFwiLi4vY29tcHJlc3MvY29tcHJlc3NcIjtcbmltcG9ydCB7IHR5cGUgQ29tcHJlc3NPcHRpb25zIH0gZnJvbSBcIi4uL2NvbXByZXNzL3R5cGVzXCI7XG5pbXBvcnQgeyBEQiB9IGZyb20gXCIuLi9kYXRhYmFzZS9kYlwiO1xuaW1wb3J0IHsgdHlwZSBTb25hbXVEQkNvbmZpZyB9IGZyb20gXCIuLi9kYXRhYmFzZS9kYlwiO1xuaW1wb3J0IHsgU0QsIHNldFNEQ29uZmlnIH0gZnJvbSBcIi4uL2RpY3Qvc2RcIjtcbmltcG9ydCB7IHR5cGUgTG9jYWxpemVkU3RyaW5nIH0gZnJvbSBcIi4uL2RpY3QvdHlwZXNcIjtcbmltcG9ydCB7IE5vdEZvdW5kRXhjZXB0aW9uIH0gZnJvbSBcIi4uL2V4Y2VwdGlvbnMvc28tZXhjZXB0aW9uc1wiO1xuaW1wb3J0IHsgQnVmZmVyZWRGaWxlIH0gZnJvbSBcIi4uL3N0b3JhZ2UvYnVmZmVyZWQtZmlsZVwiO1xuaW1wb3J0IHsgdHlwZSBTdG9yYWdlTWFuYWdlciB9IGZyb20gXCIuLi9zdG9yYWdlL3N0b3JhZ2UtbWFuYWdlclwiO1xuaW1wb3J0IHsgdHlwZSBLZXlHZW5lcmF0b3IgfSBmcm9tIFwiLi4vc3RvcmFnZS90eXBlc1wiO1xuaW1wb3J0IHsgVXBsb2FkZWRGaWxlIH0gZnJvbSBcIi4uL3N0b3JhZ2UvdXBsb2FkZWQtZmlsZVwiO1xuaW1wb3J0IHsgY3JlYXRlTW9ja1NTRUZhY3RvcnkgfSBmcm9tIFwiLi4vc3RyZWFtL3NzZVwiO1xuaW1wb3J0IHsgdHlwZSBTeW5jZXIgfSBmcm9tIFwiLi4vc3luY2VyL3N5bmNlclwiO1xuaW1wb3J0IHsgdHlwZSBXb3JrZmxvd01hbmFnZXIgfSBmcm9tIFwiLi4vdGFza3Mvd29ya2Zsb3ctbWFuYWdlclwiO1xuaW1wb3J0IHsgdHlwZSBEZXZWaXRlc3RNYW5hZ2VyIH0gZnJvbSBcIi4uL3Rlc3RpbmcvZGV2LXZpdGVzdC1tYW5hZ2VyXCI7XG5pbXBvcnQgeyB0eXBlIFNvbmFtdUZhc3RpZnlDb25maWcgfSBmcm9tIFwiLi4vdHlwZXMvdHlwZXNcIjtcbmltcG9ydCB7IGlzRGFlbW9uU2VydmVyIH0gZnJvbSBcIi4uL3V0aWxzL2NvbnRyb2xsZXJcIjtcbmltcG9ydCB7IGV4aXN0cywgZmlsZUV4aXN0cyB9IGZyb20gXCIuLi91dGlscy9mcy11dGlsc1wiO1xuaW1wb3J0IHsgdHlwZSBBYnNvbHV0ZVBhdGggfSBmcm9tIFwiLi4vdXRpbHMvcGF0aC11dGlsc1wiO1xuaW1wb3J0IHsgY29udmVydEZhc3RpZnlIZWFkZXJzVG9TdGFuZGFyZCwgbWVyZ2UgfSBmcm9tIFwiLi4vdXRpbHMvdXRpbHNcIjtcbmltcG9ydCB7IHR5cGUgU29uYW11Q29uZmlnLCB0eXBlIFNvbmFtdVNlcnZlck9wdGlvbnMsIHR5cGUgU29uYW11VGFza09wdGlvbnMgfSBmcm9tIFwiLi9jb25maWdcIjtcbmltcG9ydCB7IHR5cGUgQ29udGV4dCB9IGZyb20gXCIuL2NvbnRleHRcIjtcbmltcG9ydCB7IHR5cGUgRXh0ZW5kZWRBcGkgfSBmcm9tIFwiLi9kZWNvcmF0b3JzXCI7XG5pbXBvcnQgeyBnZXRTZWNyZXRzIH0gZnJvbSBcIi4vc2VjcmV0XCI7XG5pbXBvcnQgeyB0eXBlIFNvbmFtdVNlY3JldHMgfSBmcm9tIFwiLi9zZWNyZXRcIjtcblxuY2xhc3MgU29uYW11Q2xhc3Mge1xuICBwdWJsaWMgaXNJbml0aWFsaXplZDogYm9vbGVhbiA9IGZhbHNlO1xuICBwdWJsaWMgZm9yVGVzdGluZzogYm9vbGVhbiA9IGZhbHNlO1xuICBwdWJsaWMgYXN5bmNMb2NhbFN0b3JhZ2U6IEFzeW5jTG9jYWxTdG9yYWdlPHtcbiAgICBjb250ZXh0OiBDb250ZXh0O1xuICB9PiA9IG5ldyBBc3luY0xvY2FsU3RvcmFnZSgpO1xuXG4gIHB1YmxpYyBnZXRDb250ZXh0KCk6IENvbnRleHQge1xuICAgIGNvbnN0IHN0b3JlID0gdGhpcy5hc3luY0xvY2FsU3RvcmFnZS5nZXRTdG9yZSgpO1xuICAgIGlmIChzdG9yZT8uY29udGV4dCkge1xuICAgICAgcmV0dXJuIHN0b3JlLmNvbnRleHQ7XG4gICAgfVxuXG4gICAgaWYgKHByb2Nlc3MuZW52Lk5PREVfRU5WID09PSBcInRlc3RcIikge1xuICAgICAgLy8g7YWM7Iqk7YyFIO2ZmOqyveyXkOyEnCDsu6jthY3siqTtirjqsIAg7KO87J6F65CY7KeAIOyViuydgCDqsr3smrAg67mIIOy7qO2FjeyKpO2KuCDrpqzthLRcbiAgICAgIHJldHVybiB7XG4gICAgICAgIHJlcXVlc3Q6IG51bGwsXG4gICAgICAgIHJlcGx5OiBudWxsLFxuICAgICAgICBoZWFkZXJzOiB7fSxcbiAgICAgICAgY3JlYXRlU1NFOiAoc2NoZW1hOiBab2RPYmplY3QpID0+IGNyZWF0ZU1vY2tTU0VGYWN0b3J5KHNjaGVtYSksXG4gICAgICAgIC8vIG94bGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tZXhwbGljaXQtYW55IC0tIO2FjOyKpO2MhSDtmZjqsr3sl5DshJwg7Luo7YWN7Iqk7Yq46rCAIOyjvOyeheuQmOyngCDslYrsnYAg6rK97JqwIOu5iCDsu6jthY3siqTtirgg66as7YS0XG4gICAgICAgIG5haXRlU3RvcmU6IG5ldyBNYXA8c3RyaW5nLCBhbnk+KCksXG4gICAgICB9IGFzIHVua25vd24gYXMgQ29udGV4dDtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiU29uYW11IGNhbm5vdCBmaW5kIGNvbnRleHRcIik7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBfYXBpUm9vdFBhdGg6IEFic29sdXRlUGF0aCB8IG51bGwgPSBudWxsO1xuICBzZXQgYXBpUm9vdFBhdGgoYXBpUm9vdFBhdGg6IEFic29sdXRlUGF0aCkge1xuICAgIHRoaXMuX2FwaVJvb3RQYXRoID0gYXBpUm9vdFBhdGg7XG4gIH1cbiAgZ2V0IGFwaVJvb3RQYXRoKCk6IEFic29sdXRlUGF0aCB7XG4gICAgaWYgKHRoaXMuX2FwaVJvb3RQYXRoID09PSBudWxsKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJTb25hbXUgaGFzIG5vdCBiZWVuIGluaXRpYWxpemVkXCIpO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5fYXBpUm9vdFBhdGg7XG4gIH1cbiAgZ2V0IGFwcFJvb3RQYXRoKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMuYXBpUm9vdFBhdGguc3BsaXQocGF0aC5zZXApLnNsaWNlKDAsIC0xKS5qb2luKHBhdGguc2VwKTtcbiAgfVxuXG4gIHByaXZhdGUgX2RiQ29uZmlnOiBTb25hbXVEQkNvbmZpZyB8IG51bGwgPSBudWxsO1xuICBzZXQgZGJDb25maWcoZGJDb25maWc6IFNvbmFtdURCQ29uZmlnKSB7XG4gICAgdGhpcy5fZGJDb25maWcgPSBkYkNvbmZpZztcbiAgfVxuICBnZXQgZGJDb25maWcoKTogU29uYW11REJDb25maWcge1xuICAgIGlmICh0aGlzLl9kYkNvbmZpZyA9PT0gbnVsbCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiU29uYW11IGhhcyBub3QgYmVlbiBpbml0aWFsaXplZFwiKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuX2RiQ29uZmlnO1xuICB9XG5cbiAgcHJpdmF0ZSBfc3luY2VyOiBTeW5jZXIgfCBudWxsID0gbnVsbDtcbiAgc2V0IHN5bmNlcihzeW5jZXI6IFN5bmNlcikge1xuICAgIHRoaXMuX3N5bmNlciA9IHN5bmNlcjtcbiAgfVxuICBnZXQgc3luY2VyKCk6IFN5bmNlciB7XG4gICAgaWYgKHRoaXMuX3N5bmNlciA9PT0gbnVsbCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiU29uYW11IGhhcyBub3QgYmVlbiBpbml0aWFsaXplZFwiKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuX3N5bmNlcjtcbiAgfVxuXG4gIHByaXZhdGUgX2NvbmZpZzogU29uYW11Q29uZmlnIHwgbnVsbCA9IG51bGw7XG4gIHNldCBjb25maWcoY29uZmlnOiBTb25hbXVDb25maWcpIHtcbiAgICB0aGlzLl9jb25maWcgPSBjb25maWc7XG4gIH1cbiAgZ2V0IGNvbmZpZygpOiBTb25hbXVDb25maWcge1xuICAgIGlmICh0aGlzLl9jb25maWcgPT09IG51bGwpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIlNvbmFtdSBoYXMgbm90IGJlZW4gaW5pdGlhbGl6ZWRcIik7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLl9jb25maWc7XG4gIH1cblxuICBwdWJsaWMgcmVhZG9ubHkgc2VjcmV0czogU29uYW11U2VjcmV0cyA9IGdldFNlY3JldHMoKTtcblxuICBwcml2YXRlIF9zdG9yYWdlOiBTdG9yYWdlTWFuYWdlciB8IG51bGwgPSBudWxsO1xuICAvKipcbiAgICogU3RvcmFnZU1hbmFnZXIg7J247Iqk7YS07IqkXG4gICAqL1xuICBnZXQgc3RvcmFnZSgpOiBTdG9yYWdlTWFuYWdlciB7XG4gICAgaWYgKCF0aGlzLl9zdG9yYWdlKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJTdG9yYWdlIGhhcyBub3QgYmVlbiBpbml0aWFsaXplZC4gQ2hlY2sgc3RvcmFnZSBjb25maWcuXCIpO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5fc3RvcmFnZTtcbiAgfVxuXG4gIHByaXZhdGUgX2NhY2hlOiBDYWNoZU1hbmFnZXIgfCBudWxsID0gbnVsbDtcbiAgLyoqXG4gICAqIENhY2hlTWFuYWdlciDsnbjsiqTthLTsiqQgKEJlbnRvQ2FjaGUpXG4gICAqL1xuICBnZXQgY2FjaGUoKTogQ2FjaGVNYW5hZ2VyIHtcbiAgICBpZiAoIXRoaXMuX2NhY2hlKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJDYWNoZSBoYXMgbm90IGJlZW4gaW5pdGlhbGl6ZWQuIENoZWNrIGNhY2hlIGNvbmZpZyBpbiBzb25hbXUuY29uZmlnLnRzLlwiKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuX2NhY2hlO1xuICB9XG5cbiAgcHJpdmF0ZSBfd29ya2Zsb3dzOiBXb3JrZmxvd01hbmFnZXIgfCBudWxsID0gbnVsbDtcbiAgZ2V0IHdvcmtmbG93cygpOiBXb3JrZmxvd01hbmFnZXIge1xuICAgIGlmICh0aGlzLl93b3JrZmxvd3MgPT09IG51bGwpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIlNvbmFtdSBoYXMgbm90IGJlZW4gaW5pdGlhbGl6ZWRcIik7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMuX3dvcmtmbG93cztcbiAgfVxuXG4gIHByaXZhdGUgX2F1dGg6IEF1dGg8QmV0dGVyQXV0aE9wdGlvbnM+IHwgbnVsbCA9IG51bGw7XG4gIGdldCBhdXRoKCk6IEF1dGg8QmV0dGVyQXV0aE9wdGlvbnM+IHtcbiAgICBpZiAoIXRoaXMuX2F1dGgpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIkF1dGggaGFzIG5vdCBiZWVuIGluaXRpYWxpemVkLiBDaGVjayBhdXRoIGNvbmZpZyBpbiBzb25hbXUuY29uZmlnLnRzLlwiKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuX2F1dGg7XG4gIH1cblxuICBwcml2YXRlIF9kZXZWaXRlc3RNYW5hZ2VyOiBEZXZWaXRlc3RNYW5hZ2VyIHwgbnVsbCA9IG51bGw7XG4gIGdldCBkZXZWaXRlc3RNYW5hZ2VyKCk6IERldlZpdGVzdE1hbmFnZXIgfCBudWxsIHtcbiAgICByZXR1cm4gdGhpcy5fZGV2Vml0ZXN0TWFuYWdlcjtcbiAgfVxuICBzZXQgZGV2Vml0ZXN0TWFuYWdlcihtYW5hZ2VyOiBEZXZWaXRlc3RNYW5hZ2VyIHwgbnVsbCkge1xuICAgIHRoaXMuX2RldlZpdGVzdE1hbmFnZXIgPSBtYW5hZ2VyO1xuICB9XG5cbiAgLy8gSE1SIOyymOumrFxuICBwdWJsaWMgd2F0Y2hlcjogRlNXYXRjaGVyIHwgbnVsbCA9IG51bGw7XG4gIHByaXZhdGUgcGVuZGluZ0ZpbGVzOiBzdHJpbmdbXSA9IFtdO1xuICBwcml2YXRlIGhtclN0YXJ0VGltZTogbnVtYmVyID0gMDtcblxuICBwdWJsaWMgc2VydmVyOiBGYXN0aWZ5SW5zdGFuY2UgfCBudWxsID0gbnVsbDtcblxuICBhc3luYyBpbml0Rm9yVGVzdGluZygpIHtcbiAgICBhd2FpdCB0aGlzLmluaXQodHJ1ZSwgZmFsc2UsIHVuZGVmaW5lZCwgdHJ1ZSk7XG4gIH1cblxuICBhc3luYyBpbml0KFxuICAgIGRvU2lsZW50OiBib29sZWFuID0gZmFsc2UsXG4gICAgZW5hYmxlU3luYzogYm9vbGVhbiA9IHRydWUsXG4gICAgYXBpUm9vdFBhdGg/OiBBYnNvbHV0ZVBhdGgsXG4gICAgZm9yVGVzdGluZzogYm9vbGVhbiA9IGZhbHNlLFxuICApIHtcbiAgICB0aGlzLmZvclRlc3RpbmcgPSBmb3JUZXN0aW5nO1xuXG4gICAgaWYgKHRoaXMuaXNJbml0aWFsaXplZCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IGluaXRTdGFydCA9IHBlcmZvcm1hbmNlLm5vdygpO1xuXG4gICAgLy8gQVBJIOujqO2KuCDtjKjsiqRcbiAgICBjb25zdCB7IGZpbmRBcGlSb290UGF0aCB9ID0gYXdhaXQgaW1wb3J0KFwiLi4vdXRpbHMvdXRpbHNcIik7XG4gICAgdGhpcy5hcGlSb290UGF0aCA9IGFwaVJvb3RQYXRoID8/IGZpbmRBcGlSb290UGF0aCgpO1xuXG4gICAgLy8g7ISk7KCV7J2EIOuhnOuUqe2VmOuKlCDqsoPrtoDthLAg7Iuc7J6RXG4gICAgY29uc3QgY29uZmlnU3RhcnQgPSBwZXJmb3JtYW5jZS5ub3coKTtcbiAgICBjb25zdCB7IGxvYWRDb25maWcgfSA9IGF3YWl0IGltcG9ydChcIi4vY29uZmlnXCIpO1xuICAgIHRoaXMuY29uZmlnID0gYXdhaXQgbG9hZENvbmZpZyh0aGlzLmFwaVJvb3RQYXRoKTtcbiAgICBjb25zdCBjb25maWdUaW1lID0gcGVyZm9ybWFuY2Uubm93KCkgLSBjb25maWdTdGFydDtcbiAgICBzZXRTRENvbmZpZyh0aGlzLmNvbmZpZy5pMThuKTtcbiAgICAvLyBzb25hbXUuY29uZmlnLnRzIOq4sOuzuOqwkiDshKTsoJVcbiAgICB0aGlzLmNvbmZpZy5kYXRhYmFzZS5kYXRhYmFzZSA9IHRoaXMuY29uZmlnLmRhdGFiYXNlLmRhdGFiYXNlID8/IFwicGdcIjtcbiAgICB0aGlzLmNvbmZpZy5kYXRhYmFzZS5kZWZhdWx0T3B0aW9ucy5jbGllbnQgPSB0aGlzLmNvbmZpZy5kYXRhYmFzZS5kYXRhYmFzZSA/PyBcInBnXCI7XG5cbiAgICAvLyDroZzquYUg7ISk7KCVXG4gICAgY29uc3QgeyBjb25maWd1cmVMb2dUYXBlIH0gPSBhd2FpdCBpbXBvcnQoXCIuLi9sb2dnZXIvY29uZmlndXJlXCIpO1xuICAgIGlmICh0aGlzLmNvbmZpZy5sb2dnaW5nICE9PSBmYWxzZSkge1xuICAgICAgYXdhaXQgY29uZmlndXJlTG9nVGFwZSh7XG4gICAgICAgIC4uLnRoaXMuY29uZmlnLmxvZ2dpbmcsXG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvLyBEQiDroZzrk5xcbiAgICBjb25zdCB7IERCIH0gPSBhd2FpdCBpbXBvcnQoXCIuLi9kYXRhYmFzZS9kYlwiKTtcbiAgICB0aGlzLmRiQ29uZmlnID0gREIuZ2VuZXJhdGVEQkNvbmZpZyh0aGlzLmNvbmZpZy5kYXRhYmFzZSk7XG4gICAgREIuc2V0Q29uZmlnKHRoaXMuZGJDb25maWcpO1xuXG4gICAgLy8gRW50aXR5IOuhnOuTnFxuICAgIC8vIO2FjOyKpO2KuOyXkOyEnOuPhCBFbnRpdHkg7KCV67O064qUIO2VhOyalO2VqeuLiOuLpC5cbiAgICAvLyB1cHNlcnTqsIAg7KCc64yA66GcIOyekeuPme2VmOugpOuptCBlbnRpdHnsnZggdW5pcXVlIGluZGV4IOygleuztOqwgCDtlYTsmpTtlZjquLAg65WM66y47J6F64uI64ukLlxuICAgIGNvbnN0IHsgRW50aXR5TWFuYWdlciB9ID0gYXdhaXQgaW1wb3J0KFwiLi4vZW50aXR5L2VudGl0eS1tYW5hZ2VyXCIpO1xuICAgIGF3YWl0IEVudGl0eU1hbmFnZXIuYXV0b2xvYWQoZG9TaWxlbnQpO1xuXG4gICAgLy8gQ2FjaGUg7LSI6riw7ZmUXG4gICAgYXdhaXQgdGhpcy5pbml0aWFsaXplQ2FjaGUodGhpcy5jb25maWcuc2VydmVyLmNhY2hlLCBmb3JUZXN0aW5nKTtcblxuICAgIC8vIEJldHRlckF1dGgg7LSI6riw7ZmUXG4gICAgY29uc3QgYXV0aENvbmZpZyA9IHRoaXMuY29uZmlnLnNlcnZlci5hdXRoO1xuICAgIGlmIChhdXRoQ29uZmlnKSB7XG4gICAgICAvLyDsgqzsmqnsnpAg7ISk7KCV6rO8IOq4sOuzuOqwkuydhCBtZXJnZVxuICAgICAgY29uc3QgbWVyZ2VkRmllbGRNYXBwaW5ncyA9IG1lcmdlKEJBU0VfRklFTERfTUFQUElOR1MsIGF1dGhDb25maWcpO1xuXG4gICAgICAvLyBiZXR0ZXItYXV0aCDsnbjsiqTthLTsiqQg7IOd7ISxXG4gICAgICBjb25zdCB7IGJldHRlckF1dGggfSA9IGF3YWl0IGltcG9ydChcImJldHRlci1hdXRoXCIpO1xuICAgICAgY29uc3QgeyBzb25hbXVLbmV4QWRhcHRlciB9ID0gYXdhaXQgaW1wb3J0KFwiLi4vYXV0aC9rbmV4LWFkYXB0ZXJcIik7XG5cbiAgICAgIGNvbnN0IGF1dGhPcHRpb25zOiBCZXR0ZXJBdXRoT3B0aW9ucyA9IHtcbiAgICAgICAgZGF0YWJhc2U6IHNvbmFtdUtuZXhBZGFwdGVyKCksXG4gICAgICAgIC4uLm1lcmdlZEZpZWxkTWFwcGluZ3MsXG4gICAgICB9O1xuICAgICAgdGhpcy5fYXV0aCA9IGJldHRlckF1dGgoYXV0aE9wdGlvbnMpO1xuICAgIH1cblxuICAgIC8vIO2FjOyKpO2MheyduCDqsr3smrAg7Iux7YGsIOyXhuydtCDspJHri6hcbiAgICBpZiAoZm9yVGVzdGluZykge1xuICAgICAgdGhpcy5pc0luaXRpYWxpemVkID0gdHJ1ZTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBUYXNrIOuTseuhnVxuICAgIGF3YWl0IHRoaXMuaW5pdGlhbGl6ZVdvcmtmbG93cyh0aGlzLmNvbmZpZy50YXNrcyk7XG5cbiAgICAvLyBTeW5jZXJcbiAgICBjb25zdCB7IFN5bmNlciB9ID0gYXdhaXQgaW1wb3J0KFwiLi4vc3luY2VyL3N5bmNlclwiKTtcbiAgICB0aGlzLnN5bmNlciA9IG5ldyBTeW5jZXIoKTtcblxuICAgIC8vIEF1dG9sb2FkOiBNb2RlbHMgLyBUeXBlcyAvIEFQSXMgLyBXb3JrZmxvd3MgLyBUZW1wbGF0ZXMgLyBTU1IgUm91dGVzXG4gICAgYXdhaXQgdGhpcy5zeW5jZXIuYXV0b2xvYWRUeXBlcygpO1xuICAgIGF3YWl0IHRoaXMuc3luY2VyLmF1dG9sb2FkTW9kZWxzKCk7XG4gICAgYXdhaXQgdGhpcy5zeW5jZXIuYXV0b2xvYWRBcGlzKCk7XG4gICAgYXdhaXQgdGhpcy5zeW5jZXIuYXV0b2xvYWRXb3JrZmxvd3MoKTtcbiAgICBjb25zdCB7IFRlbXBsYXRlTWFuYWdlciB9ID0gYXdhaXQgaW1wb3J0KFwiLi4vdGVtcGxhdGVcIik7XG4gICAgYXdhaXQgVGVtcGxhdGVNYW5hZ2VyLmF1dG9sb2FkKCk7XG4gICAgYXdhaXQgdGhpcy5zeW5jZXIuYXV0b2xvYWRTU1JSb3V0ZXMoKTtcblxuICAgIGNvbnN0IHsgaXNMb2NhbCwgaXNUZXN0LCBpc0hvdFJlbG9hZFNlcnZlciB9ID0gYXdhaXQgaW1wb3J0KFwiLi4vdXRpbHMvY29udHJvbGxlclwiKTtcbiAgICBpZiAoaXNMb2NhbCgpICYmICFpc1Rlc3QoKSAmJiBpc0hvdFJlbG9hZFNlcnZlcigpICYmIGVuYWJsZVN5bmMpIHtcbiAgICAgIGF3YWl0IHRoaXMuc3luY2VyLnN5bmMoKTtcbiAgICAgIGF3YWl0IHRoaXMuc3RhcnRXYXRjaGVyKCk7XG4gICAgfVxuXG4gICAgdGhpcy5pc0luaXRpYWxpemVkID0gdHJ1ZTtcbiAgICB0aGlzLl9pbml0RWxhcHNlZCA9IHBlcmZvcm1hbmNlLm5vdygpIC0gaW5pdFN0YXJ0O1xuICAgIHRoaXMuX2NvbmZpZ0VsYXBzZWQgPSBjb25maWdUaW1lO1xuICB9XG5cbiAgcHJpdmF0ZSBfaW5pdEVsYXBzZWQgPSAwO1xuICBwcml2YXRlIF9jb25maWdFbGFwc2VkID0gMDtcblxuICBhc3luYyBjcmVhdGVTZXJ2ZXIoaW5pdE9wdGlvbnM/OiB7IGVuYWJsZVN5bmM/OiBib29sZWFuOyBkb1NpbGVudD86IGJvb2xlYW4gfSkge1xuICAgIGlmICghdGhpcy5pc0luaXRpYWxpemVkKSB7XG4gICAgICBhd2FpdCB0aGlzLmluaXQoaW5pdE9wdGlvbnM/LmRvU2lsZW50LCBpbml0T3B0aW9ucz8uZW5hYmxlU3luYyk7XG4gICAgfVxuXG4gICAgY29uc3Qgb3B0aW9ucyA9IHRoaXMuY29uZmlnLnNlcnZlcjtcbiAgICBjb25zdCB7IGRlZmF1bHQ6IGZhc3RpZnkgfSA9IGF3YWl0IGltcG9ydChcImZhc3RpZnlcIik7XG4gICAgY29uc3QgeyBnZXRMb2dUYXBlRmFzdGlmeUxvZ2dlciB9ID0gYXdhaXQgaW1wb3J0KFwiQGxvZ3RhcGUvZmFzdGlmeVwiKTtcbiAgICBjb25zdCBzZXJ2ZXIgPSBmYXN0aWZ5KHtcbiAgICAgIC4uLm9wdGlvbnMuZmFzdGlmeSxcbiAgICAgIGxvZ2dlcjpcbiAgICAgICAgdGhpcy5jb25maWcubG9nZ2luZyAhPT0gZmFsc2VcbiAgICAgICAgICA/IGdldExvZ1RhcGVGYXN0aWZ5TG9nZ2VyKHtcbiAgICAgICAgICAgICAgY2F0ZWdvcnk6IHRoaXMuY29uZmlnLmxvZ2dpbmc/LmZhc3RpZnlDYXRlZ29yeSA/PyBbXCJmYXN0aWZ5XCJdLFxuICAgICAgICAgICAgfSlcbiAgICAgICAgICA6IHVuZGVmaW5lZCxcbiAgICB9KTtcbiAgICB0aGlzLnNlcnZlciA9IHNlcnZlcjtcblxuICAgIC8vIFN0b3JhZ2Ug7ISk7KCVIOKGkiBTdG9yYWdlTWFuYWdlciDsg53shLFcbiAgICBpZiAob3B0aW9ucy5zdG9yYWdlKSB7XG4gICAgICBjb25zdCB7IFN0b3JhZ2VNYW5hZ2VyIH0gPSBhd2FpdCBpbXBvcnQoXCIuLi9zdG9yYWdlL3N0b3JhZ2UtbWFuYWdlclwiKTtcbiAgICAgIHRoaXMuX3N0b3JhZ2UgPSBuZXcgU3RvcmFnZU1hbmFnZXIob3B0aW9ucy5zdG9yYWdlKTtcbiAgICB9XG5cbiAgICAvLyDtlIzrn6zqt7jsnbgg65Ox66GdXG4gICAgaWYgKG9wdGlvbnMucGx1Z2lucykge1xuICAgICAgYXdhaXQgdGhpcy5yZWdpc3RlclBsdWdpbnMoc2VydmVyLCBvcHRpb25zLnBsdWdpbnMpO1xuICAgIH1cblxuICAgIGlmIChvcHRpb25zLmF1dGgpIHtcbiAgICAgIGF3YWl0IHRoaXMucmVnaXN0ZXJCZXR0ZXJBdXRoKHNlcnZlciwgb3B0aW9ucy5hdXRoKTtcbiAgICB9XG5cbiAgICAvLyBBUEkg65287Jqw7YyFIOyEpOyglVxuICAgIGF3YWl0IHRoaXMud2l0aEZhc3RpZnkoc2VydmVyLCBvcHRpb25zLmFwaUNvbmZpZywge1xuICAgICAgZW5hYmxlU3luYzogaW5pdE9wdGlvbnM/LmVuYWJsZVN5bmMsXG4gICAgICBkb1NpbGVudDogaW5pdE9wdGlvbnM/LmRvU2lsZW50LFxuICAgIH0pO1xuXG4gICAgLy8g7ISc67KEIOyLnOyekVxuICAgIGF3YWl0IHRoaXMuYm9vdChzZXJ2ZXIsIG9wdGlvbnMpO1xuXG4gICAgaWYgKCFpbml0T3B0aW9ucz8uZG9TaWxlbnQpIHtcbiAgICAgIHRoaXMucHJpbnRTdGFydHVwU3VtbWFyeSgpO1xuICAgIH1cblxuICAgIHJldHVybiBzZXJ2ZXI7XG4gIH1cblxuICBhc3luYyB3aXRoRmFzdGlmeShcbiAgICBzZXJ2ZXI6IEZhc3RpZnlJbnN0YW5jZTxTZXJ2ZXIsIEluY29taW5nTWVzc2FnZSwgU2VydmVyUmVzcG9uc2U+LFxuICAgIGNvbmZpZzogU29uYW11RmFzdGlmeUNvbmZpZyxcbiAgICBvcHRpb25zPzoge1xuICAgICAgZW5hYmxlU3luYz86IGJvb2xlYW47XG4gICAgICBkb1NpbGVudD86IGJvb2xlYW47XG4gICAgfSxcbiAgKSB7XG4gICAgaWYgKCF0aGlzLmlzSW5pdGlhbGl6ZWQpIHtcbiAgICAgIGF3YWl0IHRoaXMuaW5pdChvcHRpb25zPy5kb1NpbGVudCwgb3B0aW9ucz8uZW5hYmxlU3luYyk7XG4gICAgfVxuXG4gICAgdGhpcy5zZXJ2ZXIgPSBzZXJ2ZXI7XG5cbiAgICAvLyB0aW1lem9uZSDshKTsoJVcbiAgICBjb25zdCB0aW1lem9uZSA9IHRoaXMuY29uZmlnLmFwaS50aW1lem9uZTtcbiAgICBpZiAodGltZXpvbmUpIHtcbiAgICAgIC8vIO2DgOyehOyhtOyXkCDrp57qsowg7J2R64u1IOuCoOynnCDsiqTtirjrp4HsnYQg67OA7ZmY7ZW07KO87Ja07JW8IO2VqeuLiOuLpC5cbiAgICAgIC8vIOqwgOuguSB0aW1lem9uZeydtCBcIkFzaWEvU2VvdWxcIiDsnbTrqbRcbiAgICAgIC8vIFwiMjAyNS0xMS0yMVQwMDowMDowMC4wMDBaXCIg66W8IFwiMjAyNS0xMS0yMVQwOTowMDowMCswOTowMFwiIOycvOuhnCDrs4DtmZjtlbTso7zslrTslbwg7ZWp64uI64ukLlxuICAgICAgY29uc3QgeyBmb3JtYXRJblRpbWVab25lIH0gPSBhd2FpdCBpbXBvcnQoXCJkYXRlLWZucy10elwiKTtcblxuICAgICAgLy8gSVNPIDg2MDEg64Kg7KecIO2YleyLnSDsoJXqt5zsi50gKOyYiDogMjAyNC0wMS0xNVQwOTozMDowMC4wMDBaKVxuICAgICAgY29uc3QgSVNPX0RBVEVfUkVHRVggPSAvXlxcZHs0fS1cXGR7Mn0tXFxkezJ9VFxcZHsyfTpcXGR7Mn06XFxkezJ9KFxcLlxcZHszfSk/WiQvO1xuXG4gICAgICAvLyBU66W8IOuRmOufrOyLvCDsnpHsnYDrlLDsmLTtkZzqsIAg7JeG64uk66m0IFwiMjAyNS0xMS0xOTE3NjM1NDYxODkwMDAxODo1NjoyOSswOTowMFwi7JmAIOqwmeydgCDqsrDqs7zqsIAg64KY7Ji164uI64ukLlxuICAgICAgLy8g7J2064qUIGRhdGUtZm5zIO2KueyeheuLiOuLpC5cbiAgICAgIC8vIOydtOugh+qyjCDtlbTrj4Qg6rSc7LCu7Iq164uI64ukLiBcIjIwMjUtMTEtMTlUMTg6NTY6MjkrMDk6MDBcIiDrqqjslpHsnLzroZwg7J6YIOuCmOyYteuLiOuLpC5cbiAgICAgIGNvbnN0IERBVEVfRk9STUFUID0gXCJ5eXl5LU1NLWRkJ1QnSEg6bW06c3NYWFhcIjtcblxuICAgICAgc2VydmVyLnNldFJlcGx5U2VyaWFsaXplcigocGF5bG9hZCkgPT4ge1xuICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkocGF5bG9hZCwgKF9rZXksIHZhbHVlKSA9PiB7XG4gICAgICAgICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gXCJzdHJpbmdcIiAmJiBJU09fREFURV9SRUdFWC50ZXN0KHZhbHVlKSkge1xuICAgICAgICAgICAgcmV0dXJuIGZvcm1hdEluVGltZVpvbmUoXG4gICAgICAgICAgICAgIG5ldyBEYXRlKHZhbHVlKSxcbiAgICAgICAgICAgICAgdGltZXpvbmUgYXMgYCR7c3RyaW5nfS8ke3N0cmluZ31gLFxuICAgICAgICAgICAgICBEQVRFX0ZPUk1BVCxcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICAgICAgfSk7XG4gICAgICB9KTtcbiAgICAgIC8vIFRpbWV6b25lIOuhnOq3uOuKlCBwcmludFN0YXJ0dXBTdW1tYXJ57JeQ7IScIO2Gte2VqSDstpzroKVcbiAgICB9XG5cbiAgICAvLyDsoITssrQg65287Jqw7YyFIOumrOyKpO2KuFxuICAgIHNlcnZlci5nZXQoXG4gICAgICBgJHt0aGlzLmNvbmZpZy5hcGkucm91dGUucHJlZml4fS9yb3V0ZXNgLFxuICAgICAgYXN5bmMgKF9yZXF1ZXN0LCBfcmVwbHkpOiBQcm9taXNlPHR5cGVvZiB0aGlzLnN5bmNlci5hcGlzPiA9PiB7XG4gICAgICAgIHJldHVybiB0aGlzLnN5bmNlci5hcGlzO1xuICAgICAgfSxcbiAgICApO1xuXG4gICAgLy8gSGVhbHRoY2hlY2sgQVBJXG4gICAgc2VydmVyLmdldChcbiAgICAgIGAke3RoaXMuY29uZmlnLmFwaS5yb3V0ZS5wcmVmaXh9L2hlYWx0aGNoZWNrYCxcbiAgICAgIGFzeW5jIChfcmVxdWVzdCwgX3JlcGx5KTogUHJvbWlzZTxzdHJpbmc+ID0+IHtcbiAgICAgICAgcmV0dXJuIFwib2tcIjtcbiAgICAgIH0sXG4gICAgKTtcblxuICAgIC8vIFNvbmFtdSBVSSBBUEkgKOuhnOy7rCDtmZjqsr3sl5DshJzrp4wpXG4gICAgY29uc3QgeyBpc0xvY2FsIH0gPSBhd2FpdCBpbXBvcnQoXCIuLi91dGlscy9jb250cm9sbGVyXCIpO1xuICAgIGlmIChpc0xvY2FsKCkpIHtcbiAgICAgIGNvbnN0IHsgc29uYW11VUlBcGlQbHVnaW4gfSA9IGF3YWl0IGltcG9ydChcIi4uL3VpL2FwaVwiKTtcbiAgICAgIHNlcnZlci5yZWdpc3Rlcihzb25hbXVVSUFwaVBsdWdpbik7XG4gICAgfVxuXG4gICAgLy8gRGV2UnVubmVyIO2FjOyKpO2KuCDsl5Trk5ztj6zsnbjtirggKOuhnOy7rCDtmZjqsr0gKyBkZXZSdW5uZXIg7Zmc7ISx7ZmUIOyLnClcbiAgICBpZiAoaXNMb2NhbCgpICYmIHRoaXMuY29uZmlnLnRlc3Q/LmRldlJ1bm5lcj8uZW5hYmxlZCkge1xuICAgICAgY29uc3QgeyByZWdpc3RlckRldlRlc3RSb3V0ZXMgfSA9IGF3YWl0IGltcG9ydChcIi4uL3Rlc3RpbmcvZGV2LXRlc3Qtcm91dGVzXCIpO1xuICAgICAgYXdhaXQgcmVnaXN0ZXJEZXZUZXN0Um91dGVzKHNlcnZlciwgdGhpcy5jb25maWcudGVzdC5kZXZSdW5uZXIpO1xuICAgIH1cblxuICAgIGNvbnN0IHdlYlBhdGggPSBwYXRoLmpvaW4odGhpcy5hcHBSb290UGF0aCwgXCJ3ZWJcIik7XG4gICAgY29uc3QgaGFzV2ViID0gYXdhaXQgZXhpc3RzKHdlYlBhdGgpO1xuXG4gICAgLy8g7KCE7JetIGNvbXByZXNzIOyYteyFmCDqs4TsgrAgKHJvdXRlLmNvbXByZXNzOiB0cnVl7J28IOuVjCDsgqzsmqkpXG4gICAgY29uc3QgcGx1Z2luQ29tcHJlc3MgPSB0aGlzLmNvbmZpZy5zZXJ2ZXIucGx1Z2lucz8uY29tcHJlc3M7XG4gICAgY29uc3QgZ2xvYmFsQ29tcHJlc3NPcHRpb25zOiBDb21wcmVzc09wdGlvbnMgfCB1bmRlZmluZWQgPSBwbHVnaW5Db21wcmVzc1xuICAgICAgPyBwbHVnaW5Db21wcmVzcyA9PT0gdHJ1ZVxuICAgICAgICA/IHsgdGhyZXNob2xkOiAxMDI0LCBlbmNvZGluZ3M6IFtcImJyXCIsIFwiZ3ppcFwiLCBcImRlZmxhdGVcIl0gfVxuICAgICAgICA6IHtcbiAgICAgICAgICAgIHRocmVzaG9sZDogcGx1Z2luQ29tcHJlc3MudGhyZXNob2xkLFxuICAgICAgICAgICAgZW5jb2RpbmdzOiBwbHVnaW5Db21wcmVzcy5lbmNvZGluZ3MsXG4gICAgICAgICAgICBjdXN0b21UeXBlczogcGx1Z2luQ29tcHJlc3MuY3VzdG9tVHlwZXMsXG4gICAgICAgICAgfVxuICAgICAgOiB1bmRlZmluZWQ7XG5cbiAgICBpZiAoaXNMb2NhbCgpKSB7XG4gICAgICAvLyDroZzsu6wg6rCc67CcIO2ZmOqyvTogY2F0Y2gtYWxs66GcIEFQSeulvCDrj5nsoIEg66ek7Lmt7ZWY7JesIEhNUuydhCDsp4Dsm5Dtlanri4jri6QuXG4gICAgICAvLyBTT05BTVVfRElTQUJMRV9JTlRFR1JBVEVEX1dFQj15ZXProZwg7ISk7KCV7ZWY66m0IGRldl9hcGkg66qo65Oc7JeQ7IScIFZpdGUg7Ya17ZWp7J2EIOu5hO2ZnOyEse2ZlO2VoCDsiJgg7J6I7Iq164uI64ukLlxuICAgICAgY29uc3QgZGlzYWJsZUludGVncmF0ZWRXZWIgPSBwcm9jZXNzLmVudi5TT05BTVVfRElTQUJMRV9JTlRFR1JBVEVEX1dFQiA9PT0gXCJ5ZXNcIjtcbiAgICAgIGlmIChoYXNXZWIgJiYgIWRpc2FibGVJbnRlZ3JhdGVkV2ViKSB7XG4gICAgICAgIGF3YWl0IHRoaXMuc2V0dXBEZXZTZXJ2ZXJXaXRoVml0ZShzZXJ2ZXIsIHdlYlBhdGgsIGNvbmZpZyk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLnNldHVwRGV2U2VydmVyKHNlcnZlciwgY29uZmlnKTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgLy8g7ZSE66Gc642V7IWYIO2ZmOqyvTog6rCc67OEIEFQSSDrnbzsmrDtirggKyDsoJXsoIEg7YyM7J28IOyEnOu5mVxuICAgICAgZm9yIChjb25zdCBhcGkgb2YgdGhpcy5zeW5jZXIuYXBpcykge1xuICAgICAgICBpZiAodGhpcy5zeW5jZXIubW9kZWxzW2FwaS5tb2RlbE5hbWVdID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYOygleydmOuQmOyngCDslYrsnYAg66qo64247JeQIOygkeq3vCAke2FwaS5tb2RlbE5hbWV9YCk7XG4gICAgICAgIH1cblxuICAgICAgICBzZXJ2ZXIucm91dGUoe1xuICAgICAgICAgIG1ldGhvZDogYXBpLm9wdGlvbnMuaHR0cE1ldGhvZCA/PyBcIkdFVFwiLFxuICAgICAgICAgIHVybDogdGhpcy5jb25maWcuYXBpLnJvdXRlLnByZWZpeCArIGFwaS5wYXRoLFxuICAgICAgICAgIGhhbmRsZXI6IHRoaXMuY3JlYXRlQXBpSGFuZGxlcihhcGksIGNvbmZpZyksXG4gICAgICAgICAgY29tcHJlc3M6IHRvRmFzdGlmeUNvbXByZXNzT3B0aW9uKGFwaS5vcHRpb25zLmNvbXByZXNzLCBnbG9iYWxDb21wcmVzc09wdGlvbnMpLFxuICAgICAgICB9KTtcbiAgICAgIH1cblxuICAgICAgLy8g7ZSE66Gc642V7IWY7JeQ7ISc64qUIHdlYiDshozsiqQoYXBwUm9vdC93ZWIpIOycoOustOyZgCDrrLTqtIDtlZjqsowsXG4gICAgICAvLyBhcGkvd2ViLWRpc3Qg7KG07J6sIOyXrOu2gOulvCBzZXR1cFN0YXRpY1dlYlNlcnZlciDrgrTrtoDsl5DshJwg7YyQ64uo7ZWp64uI64ukLlxuICAgICAgYXdhaXQgdGhpcy5zZXR1cFN0YXRpY1dlYlNlcnZlcihzZXJ2ZXIsIGNvbmZpZywgZ2xvYmFsQ29tcHJlc3NPcHRpb25zKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogZGV2IOuqqOuTnCDqs7XthrU6IGNhdGNoLWFsbOyXkOyEnCBzeW5jZXIuYXBpc+ulvCDrj5nsoIHsnLzroZwg7YOQ7IOJ7ZWY7JesIEFQSSDsmpTssq3snYQg7LKY66as7ZWp64uI64ukLlxuICAgKiBzZXJ2ZXIucm91dGUoKeuhnCDqsJzrs4Qg65Ox66Gd7ZWY66m0IGhhbmRsZXLqsIAg6rOg7KCV65CY7Ja0IEhNUuydtCDrj5nsnpHtlZjsp4Ag7JWK7Jy866+A66GcLFxuICAgKiDrp6Qg7JqU7LKt66eI64ukIHN5bmNlci5hcGlz66W8IOyhsO2ajO2VmOuKlCDsnbQg67Cp7Iud7J2EIOyCrOyaqe2VqeuLiOuLpC5cbiAgICpcbiAgICog7JqU7LKt7J20IC9hcGko7KCV7ZmV7Z6I64qUIHRoaXMuY29uZmlnLmFwaS5yb3V0ZS5wcmVmaXgp66GcIOyLnOyeke2VmOyngCDslYrripQg6rK97Jqw652866m0IG51bGzsnYQg67CY7ZmY7ZWY66mwIOuBneuDheuLiOuLpC5cbiAgICovXG4gIHByaXZhdGUgaGFuZGxlRGV2QXBpUmVxdWVzdChcbiAgICByZXF1ZXN0OiBGYXN0aWZ5UmVxdWVzdCxcbiAgICBjb25maWc6IFNvbmFtdUZhc3RpZnlDb25maWcsXG4gICk6ICgocmVxdWVzdDogRmFzdGlmeVJlcXVlc3QsIHJlcGx5OiBGYXN0aWZ5UmVwbHkpID0+IFByb21pc2U8dW5rbm93bj4pIHwgbnVsbCB7XG4gICAgY29uc3QgdXJsID0gdGhpcy5nZXRQYXRobmFtZUZyb21VcmwocmVxdWVzdC51cmwpO1xuICAgIGNvbnN0IG1ldGhvZCA9IHJlcXVlc3QubWV0aG9kO1xuXG4gICAgaWYgKCF1cmwuc3RhcnRzV2l0aCh0aGlzLmNvbmZpZy5hcGkucm91dGUucHJlZml4KSkge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgLy8gc3luY2VyLmFwaXPsnZggcGF0aOuKlCA6cGFyYW0g7ZiV7YOc66W8IO2PrO2VqO2VoCDsiJgg7J6I7Jy866+A66GcIOyEuOq3uOuovO2KuCDri6jsnITroZwg66ek7Lmt7ZWp64uI64ukLlxuICAgIC8vIOygleq3nOyLnSDsg53shLEg67Cp7Iud7J2AIHBhdGgg66y47J6Q7Je0IOuCtCDtirnsiJjrrLjsnpAoLiwgKywgKCwgWyDrk7Ep66GcIOyYpOyekeuPme2VoCDsiJgg7J6I7Ja0IOyCrOyaqe2VmOyngCDslYrsirXri4jri6QuXG4gICAgY29uc3QgbWF0Y2hlZEFwaSA9IHRoaXMuc3luY2VyLmFwaXMuZmluZCgoYXBpKSA9PiB7XG4gICAgICBpZiAodGhpcy5zeW5jZXIubW9kZWxzW2FwaS5tb2RlbE5hbWVdID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgICAgY29uc3QgYXBpTWV0aG9kID0gYXBpLm9wdGlvbnMuaHR0cE1ldGhvZCA/PyBcIkdFVFwiO1xuICAgICAgaWYgKGFwaU1ldGhvZCAhPT0gbWV0aG9kKSByZXR1cm4gZmFsc2U7XG5cbiAgICAgIGNvbnN0IGZ1bGxQYXRoID0gdGhpcy5jb25maWcuYXBpLnJvdXRlLnByZWZpeCArIGFwaS5wYXRoO1xuICAgICAgcmV0dXJuIHRoaXMuaXNQYXRoUGF0dGVybk1hdGNoKGZ1bGxQYXRoLCB1cmwpO1xuICAgIH0pO1xuXG4gICAgaWYgKCFtYXRjaGVkQXBpKSB7XG4gICAgICB0aHJvdyBuZXcgTm90Rm91bmRFeGNlcHRpb24oU0QoXCJlcnJvci5hcGkubm90Rm91bmRcIikpO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzLmNyZWF0ZUFwaUhhbmRsZXIobWF0Y2hlZEFwaSwgY29uZmlnKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBkZXYgYXBpIOuqqOuTnDogVml0ZSDsl4bsnbQgQVBJIOuPmeyggSDrnbzsmrDtjIXrp4wg7KCc6rO17ZWp64uI64ukLlxuICAgKiBITVLsnYQg7JyE7ZW0IGNhdGNoLWFsbOyXkOyEnCDrp6Qg7JqU7LKt66eI64ukIHN5bmNlci5hcGlz66W8IOyhsO2ajO2VqeuLiOuLpC5cbiAgICovXG4gIHByaXZhdGUgc2V0dXBEZXZTZXJ2ZXIoXG4gICAgc2VydmVyOiBGYXN0aWZ5SW5zdGFuY2U8U2VydmVyLCBJbmNvbWluZ01lc3NhZ2UsIFNlcnZlclJlc3BvbnNlPixcbiAgICBjb25maWc6IFNvbmFtdUZhc3RpZnlDb25maWcsXG4gICk6IHZvaWQge1xuICAgIHNlcnZlci5yb3V0ZSh7XG4gICAgICBtZXRob2Q6IFtcIkdFVFwiLCBcIkhFQURcIiwgXCJQT1NUXCIsIFwiUFVUXCIsIFwiREVMRVRFXCIsIFwiUEFUQ0hcIl0sXG4gICAgICB1cmw6IGAke3RoaXMuY29uZmlnLmFwaS5yb3V0ZS5wcmVmaXh9LypgLFxuICAgICAgaGFuZGxlcjogYXN5bmMgKHJlcXVlc3QsIHJlcGx5KSA9PiB7XG4gICAgICAgIGNvbnN0IGhhbmRsZXIgPSB0aGlzLmhhbmRsZURldkFwaVJlcXVlc3QocmVxdWVzdCwgY29uZmlnKTtcbiAgICAgICAgaWYgKGhhbmRsZXIpIHtcbiAgICAgICAgICByZXR1cm4gaGFuZGxlcihyZXF1ZXN0LCByZXBseSk7XG4gICAgICAgIH1cbiAgICAgICAgLy8g65Ox66Gd65CcIEFQSeyZgCDsnbzsuZjtlZjsp4Ag7JWK64qUIOyalOyyreyXkCDrjIDtlZwgZmFsbGJhY2vsnoXri4jri6QuXG4gICAgICAgIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbihTRChcImVycm9yLmFwaS5ub3RGb3VuZFwiKSk7XG4gICAgICB9LFxuICAgIH0pO1xuICB9XG5cbiAgLy8gb3hsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1leHBsaWNpdC1hbnkgLS0gVml0ZURldlNlcnZlciDtg4DsnoXsnYQg64+Z7KCB7Jy866GcIOuhnOuTnO2VtOyVvCDtlahcbiAgcHJpdmF0ZSB2aXRlU2VydmVyOiBhbnkgPSBudWxsO1xuXG4gIC8qKlxuICAgKiBkZXYgYWxsIOuqqOuTnDogVml0ZSBEZXYgU2VydmVy66W8IO2Gte2Vqe2VmOyXrCBBUEkgKyBTU1IgKyBDU1LsnYQg66qo65GQIOygnOqzte2VqeuLiOuLpC5cbiAgICogQVBJIOuPmeyggSDrp6Tsua3snYAgaGFuZGxlRGV2QXBpUmVxdWVzdOulvCDqs7XsnKDtlanri4jri6QuXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIHNldHVwRGV2U2VydmVyV2l0aFZpdGUoXG4gICAgc2VydmVyOiBGYXN0aWZ5SW5zdGFuY2U8U2VydmVyLCBJbmNvbWluZ01lc3NhZ2UsIFNlcnZlclJlc3BvbnNlPixcbiAgICB3ZWJQYXRoOiBzdHJpbmcsXG4gICAgY29uZmlnOiBTb25hbXVGYXN0aWZ5Q29uZmlnLFxuICApOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAvLyBAZmFzdGlmeS9taWRkaWUg65Ox66GdIChDb25uZWN0LXN0eWxlIG1pZGRsZXdhcmUg7KeA7JuQKVxuICAgIGF3YWl0IHNlcnZlci5yZWdpc3RlcigoYXdhaXQgaW1wb3J0KFwiQGZhc3RpZnkvbWlkZGllXCIpKS5kZWZhdWx0KTtcblxuICAgIGNvbnN0IHZpdGUgPSBhd2FpdCBpbXBvcnQoXCJ2aXRlXCIpO1xuXG4gICAgdGhpcy52aXRlU2VydmVyID0gYXdhaXQgdml0ZS5jcmVhdGVTZXJ2ZXIoe1xuICAgICAgcm9vdDogd2ViUGF0aCxcbiAgICAgIHNlcnZlcjoge1xuICAgICAgICBtaWRkbGV3YXJlTW9kZTogdHJ1ZSxcbiAgICAgICAgaG1yOiB7XG4gICAgICAgICAgc2VydmVyOiBzZXJ2ZXIuc2VydmVyLFxuICAgICAgICB9LFxuICAgICAgfSxcbiAgICAgIGFwcFR5cGU6IFwiY3VzdG9tXCIsXG4gICAgfSk7XG5cbiAgICAvLyBWaXRlIG1pZGRsZXdhcmUg65Ox66GdIChWaXRlIOyXkOyFiyDsspjrpqwpXG4gICAgc2VydmVyLnVzZSgocmVxLCByZXMsIG5leHQpID0+IHtcbiAgICAgIC8vIEFQSeyZgCBTb25hbXUgVUnripQgRmFzdGlmeSDrnbzsmrDtirjqsIAg7LKY66as7ZWY64+E66GdIHNraXBcbiAgICAgIGlmIChyZXEudXJsPy5zdGFydHNXaXRoKHRoaXMuY29uZmlnLmFwaS5yb3V0ZS5wcmVmaXgpIHx8IHJlcS51cmw/LnN0YXJ0c1dpdGgoXCIvc29uYW11LXVpXCIpKSB7XG4gICAgICAgIHJldHVybiBuZXh0KCk7XG4gICAgICB9XG4gICAgICAvLyDrgpjrqLjsp4DripQgVml0ZSBtaWRkbGV3YXJl66GcIOyghOuLrFxuICAgICAgcmV0dXJuIHRoaXMudml0ZVNlcnZlci5taWRkbGV3YXJlcyhyZXEsIHJlcywgbmV4dCk7XG4gICAgfSk7XG5cbiAgICAvLyBjYXRjaC1hbGwg65287Jqw7Yq47JeQ7IScIOuPmeyggeycvOuhnCBBUEkvU1NSIOyymOumrFxuICAgIC8vIOqwnOuwnCDtmZjqsr3sl5DshJzripQg65287Jqw7Yq467OEIGNvbXByZXNzIOyYteyFmOydhCDtj6zquLDtlZjqs6AgSE1SIOydtOygkOydhCDst6jtlanri4jri6QuXG4gICAgc2VydmVyLnJvdXRlKHtcbiAgICAgIG1ldGhvZDogW1wiR0VUXCIsIFwiSEVBRFwiLCBcIlBPU1RcIiwgXCJQVVRcIiwgXCJERUxFVEVcIiwgXCJQQVRDSFwiXSxcbiAgICAgIHVybDogXCIvKlwiLFxuICAgICAgaGFuZGxlcjogYXN5bmMgKHJlcXVlc3QsIHJlcGx5KSA9PiB7XG4gICAgICAgIC8vIDEuIEFQSSDsmpTssq0g7LKY66asXG4gICAgICAgIGNvbnN0IHJlc3VsdCA9IHRoaXMuaGFuZGxlRGV2QXBpUmVxdWVzdChyZXF1ZXN0LCBjb25maWcpO1xuICAgICAgICBpZiAocmVzdWx0KSB7XG4gICAgICAgICAgcmV0dXJuIHJlc3VsdChyZXF1ZXN0LCByZXBseSk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCB1cmwgPSByZXF1ZXN0LnVybDtcblxuICAgICAgICAvLyAyLiBTU1Ig65287Jqw7Yq4IOyymOumrFxuICAgICAgICBjb25zdCB7IG1hdGNoU1NSUm91dGUsIHJlbmRlclNTUiB9ID0gYXdhaXQgaW1wb3J0KFwiLi4vc3NyXCIpO1xuICAgICAgICBjb25zdCBzc3JNYXRjaCA9IG1hdGNoU1NSUm91dGUodXJsKTtcbiAgICAgICAgaWYgKHNzck1hdGNoKSB7XG4gICAgICAgICAgY29uc29sZS5sb2coYFtTU1JdIE1hdGNoZWQgcm91dGU6ICR7c3NyTWF0Y2gucm91dGUucGF0aH1gKTtcbiAgICAgICAgICBjb25zdCBodG1sID0gYXdhaXQgcmVuZGVyU1NSKFxuICAgICAgICAgICAgdXJsLFxuICAgICAgICAgICAgc3NyTWF0Y2gucm91dGUsXG4gICAgICAgICAgICBzc3JNYXRjaC5wYXJhbXMsXG4gICAgICAgICAgICByZXF1ZXN0LFxuICAgICAgICAgICAgcmVwbHksXG4gICAgICAgICAgICBjb25maWcsXG4gICAgICAgICAgICB0aGlzLnZpdGVTZXJ2ZXIsXG4gICAgICAgICAgKTtcbiAgICAgICAgICByZXBseS50eXBlKFwidGV4dC9odG1sXCIpO1xuICAgICAgICAgIHJldHVybiBodG1sO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gMy4gQ1NSIGZhbGxiYWNrXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgY29uc3QgZnMgPSBhd2FpdCBpbXBvcnQoXCJub2RlOmZzL3Byb21pc2VzXCIpO1xuICAgICAgICAgIGxldCB0ZW1wbGF0ZSA9IGF3YWl0IGZzLnJlYWRGaWxlKFxuICAgICAgICAgICAgcGF0aC5qb2luKHRoaXMudml0ZVNlcnZlci5jb25maWcucm9vdCwgXCJpbmRleC5odG1sXCIpLFxuICAgICAgICAgICAgXCJ1dGYtOFwiLFxuICAgICAgICAgICk7XG4gICAgICAgICAgdGVtcGxhdGUgPSBhd2FpdCB0aGlzLnZpdGVTZXJ2ZXIudHJhbnNmb3JtSW5kZXhIdG1sKHVybCwgdGVtcGxhdGUpO1xuXG4gICAgICAgICAgcmVwbHkudHlwZShcInRleHQvaHRtbFwiKTtcbiAgICAgICAgICByZXR1cm4gdGVtcGxhdGU7XG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICB0aGlzLnZpdGVTZXJ2ZXIuc3NyRml4U3RhY2t0cmFjZShlIGFzIEVycm9yKTtcbiAgICAgICAgICBjb25zb2xlLmVycm9yKGUpO1xuICAgICAgICAgIHJlcGx5LnN0YXR1cyg1MDApO1xuICAgICAgICAgIHJldHVybiAoZSBhcyBFcnJvcikubWVzc2FnZTtcbiAgICAgICAgfVxuICAgICAgfSxcbiAgICB9KTtcblxuICAgIC8vIOyEnOuyhCDsooXro4wg7IucIFZpdGXrj4Qg7KKF66OMXG4gICAgc2VydmVyLmFkZEhvb2soXCJvbkNsb3NlXCIsIGFzeW5jICgpID0+IHtcbiAgICAgIGF3YWl0IHRoaXMudml0ZVNlcnZlci5jbG9zZSgpO1xuICAgIH0pO1xuXG4gICAgY29uc3QgY2hhbGsgPSAoYXdhaXQgaW1wb3J0KFwiY2hhbGtcIikpLmRlZmF1bHQ7XG4gICAgY29uc29sZS5sb2coY2hhbGsuZGltKFwi4pyTIFZpdGUgZGV2IHNlcnZlciBpbnRlZ3JhdGVkXCIpKTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgc2V0dXBTdGF0aWNXZWJTZXJ2ZXIoXG4gICAgc2VydmVyOiBGYXN0aWZ5SW5zdGFuY2U8U2VydmVyLCBJbmNvbWluZ01lc3NhZ2UsIFNlcnZlclJlc3BvbnNlPixcbiAgICBjb25maWc6IFNvbmFtdUZhc3RpZnlDb25maWcsXG4gICAgZ2xvYmFsQ29tcHJlc3NPcHRpb25zOiBDb21wcmVzc09wdGlvbnMgfCB1bmRlZmluZWQsXG4gICk6IFByb21pc2U8dm9pZD4ge1xuICAgIC8vIOqyveuhnCDrqoXtmZXtmZQ6IGFwaS93ZWItZGlzdC9jbGllbnQgKOygleyggSDtjIzsnbwpLCBhcGkvd2ViLWRpc3Qvc2VydmVyIChTU1IgZW50cnkpLCBhcGkvZGlzdC9zc3IgKFNTUiByb3V0ZXMgLSBBUEkg7IaM7JygKVxuICAgIGNvbnN0IHdlYkRpc3RQYXRoID0gcGF0aC5qb2luKHRoaXMuYXBpUm9vdFBhdGgsIFwid2ViLWRpc3RcIiwgXCJjbGllbnRcIik7XG4gICAgY29uc3Qgc3NyUGF0aCA9IHBhdGguam9pbih0aGlzLmFwaVJvb3RQYXRoLCBcIndlYi1kaXN0XCIsIFwic2VydmVyXCIpO1xuICAgIGNvbnN0IHNzckVudHJ5UGF0aCA9IHBhdGguam9pbihzc3JQYXRoLCBcImVudHJ5LXNlcnZlci5nZW5lcmF0ZWQuanNcIik7XG4gICAgY29uc3Qgc3NyUm91dGVzUGF0aCA9IHBhdGguam9pbih0aGlzLmFwaVJvb3RQYXRoLCBcImRpc3RcIiwgXCJzc3JcIiwgXCJyb3V0ZXMuanNcIik7XG5cbiAgICBpZiAoIShhd2FpdCBleGlzdHMod2ViRGlzdFBhdGgpKSkge1xuICAgICAgY29uc29sZS53YXJuKGDimqAgV2ViIGRpc3Qgbm90IGZvdW5kOiAke3dlYkRpc3RQYXRofWApO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIFNTUiBlbnRyeSDsobTsnqwg7Jes67aAIO2ZleyduFxuICAgIGNvbnN0IHNzckF2YWlsYWJsZSA9IGF3YWl0IGV4aXN0cyhzc3JFbnRyeVBhdGgpO1xuXG4gICAgaWYgKCFzc3JBdmFpbGFibGUpIHtcbiAgICAgIGNvbnNvbGUud2Fybihg4pqgIFNTUiBlbnRyeSBub3QgZm91bmQ6ICR7c3NyRW50cnlQYXRofWApO1xuICAgICAgY29uc29sZS53YXJuKFwiICBTU1Igd2lsbCBiZSBkaXNhYmxlZC4gT25seSBDU1Igd2lsbCB3b3JrLlwiKTtcbiAgICB9XG5cbiAgICAvLyBTU1Ig65287Jqw7Yq4IOuhnOuTnCAocHJvZHVjdGlvbuyXkOyEnOunjCwg7IKs7Jqp7J6QIO2UhOuhnOygne2KuOydmCBzc3Ivcm91dGVzLnRzKVxuICAgIGlmIChzc3JBdmFpbGFibGUpIHtcbiAgICAgIGlmIChhd2FpdCBleGlzdHMoc3NyUm91dGVzUGF0aCkpIHtcbiAgICAgICAgLy8gdHMtbG9hZGVy652866m0IFwiZmlsZTovL1wi66GcIOyLnOyeke2VmOuKlCBmdWxseS1yZXNvbHZlZCBwYXRo66eMIOuwm+q4sOyXkCDsnbTrpbwg7LKY66as7ZW07KO864qUIGltcG9ydE1lbWJlcnPrpbwg7IKs7Jqp7ZW07JW8IO2WiOqyoOyngOunjCxcbiAgICAgICAgLy8g7Jes6riw64qUIO2UhOuhnOuNleyFmCDtmZjqsr3sl5DshJwgbG9hZGVyIOyXhuydtCDrj4zslYTqsIDquLAg65WM66y47JeQIFwi7KeE7KecIGpzIO2MjOydvFwi7J2YIFwi6re464OlXCIg7KCI64yA6rK966Gc66W8IOuwlOuhnCBpbXBvcnTtlbTrj4Qg65Cp64uI64ukLlxuICAgICAgICAvLyDsnbQg64K07Jqp7J2AIOydtCDtlajsiJgg64K07JeQ7IScIOyVhOuemOyXkCDrgpjsmKwg64uk66W4IGltcG9ydCDtmLjstpzsl5Drj4Qg64+Z7J287ZWY6rKMIOyggeyaqeuQqeuLiOuLpC5cbiAgICAgICAgYXdhaXQgaW1wb3J0KHNzclJvdXRlc1BhdGgpO1xuICAgICAgICBjb25zb2xlLmxvZyhcIuKckyBTU1Igcm91dGVzIGxvYWRlZFwiKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnNvbGUud2Fybihg4pqgIFNTUiByb3V0ZXMgbm90IGZvdW5kOiAke3NzclJvdXRlc1BhdGh9YCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8g66Gk66eBIOyXheuNsOydtO2KuCDrjIDsnZE6IGFzc2V0IGhhc2gg67aI7J287LmYIOyLnCDtmITsnqwg67KE7KCEIOyngeygkSDshJzruZlcbiAgICBzZXJ2ZXIuZ2V0KFwiL2Fzc2V0cy86ZmlsZW5hbWVcIiwgYXN5bmMgKHJlcXVlc3QsIHJlcGx5KSA9PiB7XG4gICAgICBjb25zdCByZXF1ZXN0ZWRGaWxlID0gKHJlcXVlc3QucGFyYW1zIGFzIHsgZmlsZW5hbWU6IHN0cmluZyB9KS5maWxlbmFtZTtcbiAgICAgIGNvbnN0IGFzc2V0c0RpciA9IHBhdGguam9pbih3ZWJEaXN0UGF0aCwgXCJhc3NldHNcIik7XG4gICAgICBjb25zdCBzYWZlRmlsZVBhdGggPSB0aGlzLnJlc29sdmVQYXRoV2l0aGluQmFzZURpcihhc3NldHNEaXIsIHJlcXVlc3RlZEZpbGUpO1xuICAgICAgaWYgKHNhZmVGaWxlUGF0aCA9PT0gbnVsbCkge1xuICAgICAgICByZXBseS5zdGF0dXMoNDAzKS5zZW5kKCk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIGNvbnN0IG5vcm1hbGl6ZWRSZXF1ZXN0ZWRGaWxlID0gcGF0aC5yZWxhdGl2ZShhc3NldHNEaXIsIHNhZmVGaWxlUGF0aCkucmVwbGFjZSgvXFxcXC9nLCBcIi9cIik7XG5cbiAgICAgIGNvbnN0IGFzc2V0UGF0aCA9IGAvYXNzZXRzLyR7bm9ybWFsaXplZFJlcXVlc3RlZEZpbGV9YDtcblxuICAgICAgLy8gQ2FjaGUtQ29udHJvbCDtl6TrjZQg6rKw7KCVXG4gICAgICBjb25zdCBnZXRDYWNoZUNvbnRyb2xGb3JBc3NldCA9ICgpOiBDYWNoZUNvbnRyb2xDb25maWcgPT4ge1xuICAgICAgICBjb25zdCBjYWNoZVJlcTogQ2FjaGVDb250cm9sUmVxdWVzdCA9IHtcbiAgICAgICAgICB0eXBlOiBcImFzc2V0c1wiLFxuICAgICAgICAgIHVybDogcmVxdWVzdC51cmwsXG4gICAgICAgICAgcGF0aDogYXNzZXRQYXRoLFxuICAgICAgICAgIG1ldGhvZDogcmVxdWVzdC5tZXRob2QsXG4gICAgICAgIH07XG5cbiAgICAgICAgLy8g7IKs7Jqp7J6QIOygleydmCDtlbjrk6Trn6wg7Jqw7ISgXG4gICAgICAgIGlmIChjb25maWcuY2FjaGVDb250cm9sSGFuZGxlcikge1xuICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IGNvbmZpZy5jYWNoZUNvbnRyb2xIYW5kbGVyKGNhY2hlUmVxKTtcbiAgICAgICAgICBpZiAocmVzdWx0KSByZXR1cm4gcmVzdWx0O1xuICAgICAgICB9XG5cbiAgICAgICAgLy8g6riw67O46rCSOiBpbW11dGFibGVcbiAgICAgICAgcmV0dXJuIENhY2hlUHJlc2V0cy5pbW11dGFibGU7XG4gICAgICB9O1xuXG4gICAgICAvLyBpbmRleC0qLmpzIOuYkOuKlCBpbmRleC0qLmNzcyDsmpTssq3snbgg6rK97JqwXG4gICAgICBpZiAoL15pbmRleC1bYS1mMC05XStcXC4oanN8Y3NzKSQvLnRlc3Qobm9ybWFsaXplZFJlcXVlc3RlZEZpbGUpKSB7XG4gICAgICAgIGNvbnN0IGV4dCA9IG5vcm1hbGl6ZWRSZXF1ZXN0ZWRGaWxlLnNwbGl0KFwiLlwiKS5wb3AoKTtcbiAgICAgICAgY29uc3QgZmlsZXMgPSBhd2FpdCBmcy5yZWFkZGlyKGFzc2V0c0Rpcik7XG4gICAgICAgIGNvbnN0IGN1cnJlbnRGaWxlID0gZmlsZXMuZmluZCgoZikgPT4gZi5zdGFydHNXaXRoKFwiaW5kZXgtXCIpICYmIGYuZW5kc1dpdGgoYC4ke2V4dH1gKSk7XG5cbiAgICAgICAgaWYgKGN1cnJlbnRGaWxlKSB7XG4gICAgICAgICAgY29uc3QgZmlsZVBhdGggPSBwYXRoLmpvaW4oYXNzZXRzRGlyLCBjdXJyZW50RmlsZSk7XG4gICAgICAgICAgY29uc3QgY29udGVudCA9IGF3YWl0IGZzLnJlYWRGaWxlKGZpbGVQYXRoKTtcbiAgICAgICAgICByZXBseS50eXBlKGV4dCA9PT0gXCJqc1wiID8gXCJhcHBsaWNhdGlvbi9qYXZhc2NyaXB0XCIgOiBcInRleHQvY3NzXCIpO1xuICAgICAgICAgIGFwcGx5Q2FjaGVIZWFkZXJzKHJlcGx5LCBnZXRDYWNoZUNvbnRyb2xGb3JBc3NldCgpKTtcbiAgICAgICAgICByZXR1cm4gcmVwbHkuc2VuZChjb250ZW50KTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICAvLyDsnbzrsJgg7YyM7J28IOyEnOu5mVxuICAgICAgY29uc3QgZmlsZVBhdGggPSBzYWZlRmlsZVBhdGg7XG4gICAgICBpZiAoYXdhaXQgZXhpc3RzKGZpbGVQYXRoKSkge1xuICAgICAgICBjb25zdCBjb250ZW50ID0gYXdhaXQgZnMucmVhZEZpbGUoZmlsZVBhdGgpO1xuICAgICAgICBjb25zdCBleHQgPSBub3JtYWxpemVkUmVxdWVzdGVkRmlsZS5zcGxpdChcIi5cIikucG9wKCk7XG4gICAgICAgIHJlcGx5LnR5cGUoZXh0ID09PSBcImpzXCIgPyBcImFwcGxpY2F0aW9uL2phdmFzY3JpcHRcIiA6IGV4dCA9PT0gXCJjc3NcIiA/IFwidGV4dC9jc3NcIiA6IFwiXCIpO1xuICAgICAgICBpZiAobm9ybWFsaXplZFJlcXVlc3RlZEZpbGUuaW5jbHVkZXMoXCItXCIpKSB7XG4gICAgICAgICAgYXBwbHlDYWNoZUhlYWRlcnMocmVwbHksIGdldENhY2hlQ29udHJvbEZvckFzc2V0KCkpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXBseS5zZW5kKGNvbnRlbnQpO1xuICAgICAgfVxuXG4gICAgICByZXBseS5zdGF0dXMoNDA0KS5zZW5kKCk7XG4gICAgfSk7XG5cbiAgICAvLyBTU1Ig65287Jqw7Yq4IOqwnOuzhCDrk7HroZ0gKGNvbXByZXNzIOyYteyFmOydtCDrnbzsmrDtirjrs4TroZwg7KCB7Jqp65CY64+E66GdKVxuICAgIGlmIChzc3JBdmFpbGFibGUpIHtcbiAgICAgIGNvbnN0IHsgZ2V0U1NSUm91dGVzIH0gPSBhd2FpdCBpbXBvcnQoXCIuLi9zc3JcIik7XG4gICAgICBjb25zdCB7IHJlbmRlclNTUiB9ID0gYXdhaXQgaW1wb3J0KFwiLi4vc3NyL3JlbmRlcmVyXCIpO1xuICAgICAgY29uc3Qgc3NyUm91dGVzID0gZ2V0U1NSUm91dGVzKCk7XG5cbiAgICAgIGZvciAoY29uc3Qgcm91dGUgb2Ygc3NyUm91dGVzKSB7XG4gICAgICAgIHNlcnZlci5yb3V0ZSh7XG4gICAgICAgICAgbWV0aG9kOiBbXCJHRVRcIiwgXCJIRUFEXCJdLFxuICAgICAgICAgIHVybDogcm91dGUucGF0aCxcbiAgICAgICAgICBjb21wcmVzczogdG9GYXN0aWZ5Q29tcHJlc3NPcHRpb24ocm91dGUuY29tcHJlc3MgPz8gdHJ1ZSwgZ2xvYmFsQ29tcHJlc3NPcHRpb25zKSxcbiAgICAgICAgICBoYW5kbGVyOiBhc3luYyAocmVxdWVzdCwgcmVwbHkpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHVybCA9IHJlcXVlc3QudXJsO1xuICAgICAgICAgICAgY29uc29sZS5sb2coYFtTU1JdIE1hdGNoZWQgcm91dGU6ICR7cm91dGUucGF0aH1gKTtcblxuICAgICAgICAgICAgY29uc3QgcGFyYW1zID0gdGhpcy5leHRyYWN0UGF0aFBhcmFtcyhyb3V0ZS5wYXRoLCB1cmwpO1xuICAgICAgICAgICAgY29uc3QgaHRtbCA9IGF3YWl0IHJlbmRlclNTUih1cmwsIHJvdXRlLCBwYXJhbXMsIHJlcXVlc3QsIHJlcGx5LCBjb25maWcpO1xuXG4gICAgICAgICAgICByZXBseS50eXBlKFwidGV4dC9odG1sXCIpO1xuICAgICAgICAgICAgcmV0dXJuIGh0bWw7XG4gICAgICAgICAgfSxcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gQ1NSIG9yIFN0YXRpYyBGaWxlIEZhbGxiYWNrIChTU1Ig65287Jqw7Yq47JeQIOunpOy5reuQmOyngCDslYrripQg66qo65OgIOyalOyyrSlcbiAgICBzZXJ2ZXIucm91dGUoe1xuICAgICAgbWV0aG9kOiBbXCJHRVRcIiwgXCJIRUFEXCJdLFxuICAgICAgdXJsOiBcIipcIixcbiAgICAgIGhhbmRsZXI6IGFzeW5jIChyZXF1ZXN0LCByZXBseSkgPT4ge1xuICAgICAgICAvLyAvYXBpLCAvc29uYW11LXVp64qUIDQwNCDqt7jrjIDroZxcbiAgICAgICAgaWYgKHJlcXVlc3QudXJsLnN0YXJ0c1dpdGgoXCIvYXBpXCIpIHx8IHJlcXVlc3QudXJsLnN0YXJ0c1dpdGgoXCIvc29uYW11LXVpXCIpKSB7XG4gICAgICAgICAgcmVwbHkuc3RhdHVzKDQwNCkuc2VuZCgpO1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIENTUuyaqSBDYWNoZS1Db250cm9sIO2XpOuNlCDshKTsoJVcbiAgICAgICAgaWYgKGNvbmZpZy5jYWNoZUNvbnRyb2xIYW5kbGVyKSB7XG4gICAgICAgICAgY29uc3QgY3NyQ2FjaGVSZXE6IENhY2hlQ29udHJvbFJlcXVlc3QgPSB7XG4gICAgICAgICAgICB0eXBlOiBcImNzclwiLFxuICAgICAgICAgICAgdXJsOiByZXF1ZXN0LnVybCxcbiAgICAgICAgICAgIHBhdGg6IHJlcXVlc3QudXJsLnNwbGl0KFwiP1wiKVswXSxcbiAgICAgICAgICAgIG1ldGhvZDogcmVxdWVzdC5tZXRob2QsXG4gICAgICAgICAgfTtcbiAgICAgICAgICBjb25zdCBjc3JDYWNoZUNvbmZpZyA9IGNvbmZpZy5jYWNoZUNvbnRyb2xIYW5kbGVyKGNzckNhY2hlUmVxKTtcblxuICAgICAgICAgIGlmIChjc3JDYWNoZUNvbmZpZykge1xuICAgICAgICAgICAgYXBwbHlDYWNoZUhlYWRlcnMocmVwbHksIGNzckNhY2hlQ29uZmlnKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyDsoJXsoIEg7YyM7J287J20IOyhtOyerO2VoCDqsr3smrAsIOygleyggSDtjIzsnbzsnYQg66i87KCAIOyEnOu5me2VtOyVvO2VqFxuICAgICAgICBjb25zdCByZXF1ZXN0UGF0aCA9IHRoaXMuZ2V0UGF0aG5hbWVGcm9tVXJsKHJlcXVlc3QudXJsKTtcbiAgICAgICAgY29uc3Qgc2FmZUZpbGVQYXRoID0gdGhpcy5yZXNvbHZlUGF0aFdpdGhpbkJhc2VEaXIod2ViRGlzdFBhdGgsIHJlcXVlc3RQYXRoKTtcbiAgICAgICAgaWYgKHNhZmVGaWxlUGF0aCA9PT0gbnVsbCkge1xuICAgICAgICAgIHJlcGx5LnN0YXR1cyg0MDMpLnNlbmQoKTtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGF3YWl0IGZpbGVFeGlzdHMoc2FmZUZpbGVQYXRoKSkge1xuICAgICAgICAgIGNvbnN0IGNvbnRlbnQgPSBhd2FpdCBmcy5yZWFkRmlsZShzYWZlRmlsZVBhdGgpO1xuICAgICAgICAgIHJldHVybiByZXBseS50eXBlKG1pbWVMb29rdXAoc2FmZUZpbGVQYXRoKSB8fCBcImFwcGxpY2F0aW9uL29jdGV0LXN0cmVhbVwiKS5zZW5kKGNvbnRlbnQpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gQ1NSIGZhbGxiYWNrOiBpbmRleC5odG1sIOyEnOu5mVxuICAgICAgICBjb25zdCBpbmRleFBhdGggPSBwYXRoLmpvaW4od2ViRGlzdFBhdGgsIFwiaW5kZXguaHRtbFwiKTtcbiAgICAgICAgcmV0dXJuIHJlcGx5LnR5cGUoXCJ0ZXh0L2h0bWxcIikuc2VuZChhd2FpdCBmcy5yZWFkRmlsZShpbmRleFBhdGgsIFwidXRmLThcIikpO1xuICAgICAgfSxcbiAgICB9KTtcblxuICAgIGNvbnNvbGUubG9nKGDinJMgU3RhdGljIHdlYiBzZXJ2ZXIgY29uZmlndXJlZCB3aXRoICR7c3NyQXZhaWxhYmxlID8gXCJTU1JcIiA6IFwiQ1NSIG9ubHlcIn0gc3VwcG9ydGApO1xuICB9XG5cbiAgY3JlYXRlQXBpSGFuZGxlcihcbiAgICBhcGk6IEV4dGVuZGVkQXBpLFxuICAgIGNvbmZpZzogU29uYW11RmFzdGlmeUNvbmZpZyxcbiAgKTogKHJlcXVlc3Q6IEZhc3RpZnlSZXF1ZXN0LCByZXBseTogRmFzdGlmeVJlcGx5KSA9PiBQcm9taXNlPHVua25vd24+IHtcbiAgICByZXR1cm4gYXN5bmMgKHJlcXVlc3Q6IEZhc3RpZnlSZXF1ZXN0LCByZXBseTogRmFzdGlmeVJlcGx5KTogUHJvbWlzZTx1bmtub3duPiA9PiB7XG4gICAgICAvLyBDb250ZXh0IOyDneyEsVxuICAgICAgY29uc3QgY29udGV4dDogQ29udGV4dCA9IGF3YWl0IHRoaXMuY3JlYXRlQ29udGV4dChjb25maWcsIHJlcXVlc3QsIHJlcGx5KTtcblxuICAgICAgcmV0dXJuIHRoaXMuYXN5bmNMb2NhbFN0b3JhZ2UucnVuKHsgY29udGV4dCB9LCBhc3luYyAoKSA9PiB7XG4gICAgICAgIC8vIGd1YXJkcyDsspjrpqxcbiAgICAgICAgKGFwaS5vcHRpb25zLmd1YXJkcyA/PyBbXSkuZXZlcnkoKGd1YXJkKSA9PiBjb25maWcuZ3VhcmRIYW5kbGVyKGd1YXJkLCByZXF1ZXN0LCBhcGkpKTtcblxuICAgICAgICAvLyDtjIzrnbzrr7jthLAg7KCV67O066GcIHpvZCDsiqTtgqTrp4gg67mM65OcXG4gICAgICAgIGNvbnN0IHsgZ2V0Wm9kT2JqZWN0RnJvbUFwaSB9ID0gYXdhaXQgaW1wb3J0KFwiLi9jb2RlLWNvbnZlcnRlcnNcIik7XG4gICAgICAgIGNvbnN0IFJlcVR5cGUgPSBnZXRab2RPYmplY3RGcm9tQXBpKGFwaSwgdGhpcy5zeW5jZXIudHlwZXMpO1xuXG4gICAgICAgIC8vIHJlcXVlc3Qg7YyM7IuxXG4gICAgICAgIGNvbnN0IHdoaWNoID0gYXBpLm9wdGlvbnMuaHR0cE1ldGhvZCA9PT0gXCJHRVRcIiA/IFwicXVlcnlcIiA6IFwiYm9keVwiO1xuICAgICAgICBsZXQgcmVxQm9keToge1xuICAgICAgICAgIFtrZXk6IHN0cmluZ106IHVua25vd247XG4gICAgICAgIH07XG4gICAgICAgIC8vIO2MjOydvCDsl4XroZzrk5wg7J6I64qUIOqyveyasCDsnoTsi5wg642w7J207YSwXG4gICAgICAgIGNvbnN0IGZpbGVzOiB7XG4gICAgICAgICAgYnVmZmVyZWRGaWxlczogQnVmZmVyZWRGaWxlW107XG4gICAgICAgICAgdXBsb2FkZWRGaWxlczogVXBsb2FkZWRGaWxlW107XG4gICAgICAgIH0gPSB7XG4gICAgICAgICAgYnVmZmVyZWRGaWxlczogW10sXG4gICAgICAgICAgdXBsb2FkZWRGaWxlczogW10sXG4gICAgICAgIH07XG5cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBjb25zdCBib2R5ID0gKHJlcXVlc3Rbd2hpY2hdID8/IHt9KSBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcbiAgICAgICAgICBpZiAoYXBpLnVwbG9hZE9wdGlvbnMpIHtcbiAgICAgICAgICAgIGNvbnN0IHBhcnRzID0gcmVxdWVzdC5wYXJ0cyh7XG4gICAgICAgICAgICAgIGxpbWl0czogYXBpLnVwbG9hZE9wdGlvbnMubGltaXRzLFxuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIC8vIEZvcm1EYXRh7J2YIGZpZWxk65Ok7J2EIOyehOyLnOuhnCDsoIDsnqVcbiAgICAgICAgICAgIGNvbnN0IGZpZWxkczogUmVjb3JkPHN0cmluZywgc3RyaW5nPiA9IHt9O1xuXG4gICAgICAgICAgICBpZiAoYXBpLnVwbG9hZE9wdGlvbnMuY29uc3VtZSA9PT0gXCJidWZmZXJcIiB8fCAhYXBpLnVwbG9hZE9wdGlvbnMuY29uc3VtZSkge1xuICAgICAgICAgICAgICAvLyBCdWZmZXIg66qo65OcOiDrqZTrqqjrpqzsl5Ag66Gc65OcXG4gICAgICAgICAgICAgIGZvciBhd2FpdCAoY29uc3QgcGFydCBvZiBwYXJ0cykge1xuICAgICAgICAgICAgICAgIGlmIChwYXJ0LnR5cGUgPT09IFwiZmlsZVwiKSB7XG4gICAgICAgICAgICAgICAgICAvLyBDUklUSUNBTDog7YyM7J28IOyKpO2KuOumvOydhCDsponsi5wgY29uc3VtZe2VtOyVvCDri6TsnYwgcGFydOuhnCDrhJjslrTqsIgg7IiYIOyeiOydjFxuICAgICAgICAgICAgICAgICAgLy8g7J20IO2YuOy2nOydtCDsl4bsnLzrqbQg7KKF7KKFIG11bHRpcGFydCDtjIzsi7HsnbQgcGVuZGluZyDsg4Htg5zroZwg7YOA7J6E7JWE7JuDIOuwnOyDnVxuICAgICAgICAgICAgICAgICAgY29uc3QgYnVmZmVyID0gYXdhaXQgcGFydC50b0J1ZmZlcigpO1xuICAgICAgICAgICAgICAgICAgZmlsZXMuYnVmZmVyZWRGaWxlcy5wdXNoKG5ldyBCdWZmZXJlZEZpbGUocGFydCwgYnVmZmVyKSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChwYXJ0LnR5cGUgPT09IFwiZmllbGRcIikge1xuICAgICAgICAgICAgICAgICAgZmllbGRzW3BhcnQuZmllbGRuYW1lXSA9IFN0cmluZyhwYXJ0LnZhbHVlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSBpZiAoYXBpLnVwbG9hZE9wdGlvbnMuY29uc3VtZSA9PT0gXCJzdHJlYW1cIikge1xuICAgICAgICAgICAgICAvLyBTdHJlYW0g66qo65OcOiDsponsi5wg7KCA7J6l7IaM66GcIOyKpO2KuOumrOuwjVxuICAgICAgICAgICAgICBjb25zdCBkaXNrTmFtZSA9IGFwaS51cGxvYWRPcHRpb25zLmRlc3RpbmF0aW9uO1xuICAgICAgICAgICAgICBjb25zdCBkaXNrID0gdGhpcy5zdG9yYWdlLnVzZShkaXNrTmFtZSk7XG5cbiAgICAgICAgICAgICAgLy8g7Jqw7ISg7Iic7JyEOiDrjbDsvZTroIjsnbTthLAgPiDsoITsl60g7ISk7KCVID4g6riw67O46rCSXG4gICAgICAgICAgICAgIGNvbnN0IGtleUdlbmVyYXRvcjogS2V5R2VuZXJhdG9yID1cbiAgICAgICAgICAgICAgICBhcGkudXBsb2FkT3B0aW9ucy5rZXlHZW5lcmF0b3IgPz9cbiAgICAgICAgICAgICAgICB0aGlzLmNvbmZpZy5zZXJ2ZXIuc3RvcmFnZT8ua2V5R2VuZXJhdG9yID8/XG4gICAgICAgICAgICAgICAgZGVmYXVsdEtleUdlbmVyYXRvcjtcblxuICAgICAgICAgICAgICBmb3IgYXdhaXQgKGNvbnN0IHBhcnQgb2YgcGFydHMpIHtcbiAgICAgICAgICAgICAgICBpZiAocGFydC50eXBlID09PSBcImZpbGVcIikge1xuICAgICAgICAgICAgICAgICAgY29uc3Qga2V5ID0gYXdhaXQga2V5R2VuZXJhdG9yKHtcbiAgICAgICAgICAgICAgICAgICAgZmlsZW5hbWU6IHBhcnQuZmlsZW5hbWUsXG4gICAgICAgICAgICAgICAgICAgIG1pbWV0eXBlOiBwYXJ0Lm1pbWV0eXBlLFxuICAgICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICAgIGF3YWl0IGRpc2sucHV0U3RyZWFtKGtleSwgcGFydC5maWxlLCB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnRlbnRUeXBlOiBwYXJ0Lm1pbWV0eXBlLFxuICAgICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICAgIGNvbnN0IHVybCA9IGF3YWl0IGRpc2suZ2V0VXJsKGtleSk7XG4gICAgICAgICAgICAgICAgICBjb25zdCBzaWduZWRVcmwgPSBhd2FpdCBkaXNrLmdldFNpZ25lZFVybChrZXkpO1xuXG4gICAgICAgICAgICAgICAgICBmaWxlcy51cGxvYWRlZEZpbGVzLnB1c2goXG4gICAgICAgICAgICAgICAgICAgIG5ldyBVcGxvYWRlZEZpbGUoe1xuICAgICAgICAgICAgICAgICAgICAgIGZpbGVuYW1lOiBwYXJ0LmZpbGVuYW1lLFxuICAgICAgICAgICAgICAgICAgICAgIG1pbWV0eXBlOiBwYXJ0Lm1pbWV0eXBlLFxuICAgICAgICAgICAgICAgICAgICAgIHNpemU6IHBhcnQuZmlsZS5ieXRlc1JlYWQsXG4gICAgICAgICAgICAgICAgICAgICAgdXJsLFxuICAgICAgICAgICAgICAgICAgICAgIHNpZ25lZFVybCxcbiAgICAgICAgICAgICAgICAgICAgICBrZXksXG4gICAgICAgICAgICAgICAgICAgICAgZGlza05hbWUsXG4gICAgICAgICAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHBhcnQudHlwZSA9PT0gXCJmaWVsZFwiKSB7XG4gICAgICAgICAgICAgICAgICBmaWVsZHNbcGFydC5maWVsZG5hbWVdID0gU3RyaW5nKHBhcnQudmFsdWUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBxc+uhnCDspJHssqkg6rWs7KGwIO2MjOyLsTogcGFyYW1zW2NhdGVnb3J5XSDihpIgeyBwYXJhbXM6IHsgY2F0ZWdvcnk6IFwidGVzdFwiIH0gfVxuICAgICAgICAgICAgY29uc3QgcXMgPSBhd2FpdCBpbXBvcnQoXCJxc1wiKTtcbiAgICAgICAgICAgIGNvbnN0IHBhcnNlZCA9IHFzLmRlZmF1bHQucGFyc2UoZmllbGRzKTtcbiAgICAgICAgICAgIE9iamVjdC5hc3NpZ24oYm9keSwgcGFyc2VkKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBjb25zdCB7IGZhc3RpZnlDYXN0ZXIgfSA9IGF3YWl0IGltcG9ydChcIi4vY2FzdGVyXCIpO1xuICAgICAgICAgIHJlcUJvZHkgPSBmYXN0aWZ5Q2FzdGVyKFJlcVR5cGUpLnBhcnNlKGJvZHkpO1xuICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgY29uc3QgeyBab2RFcnJvciB9ID0gYXdhaXQgaW1wb3J0KFwiem9kXCIpO1xuICAgICAgICAgIGlmIChlIGluc3RhbmNlb2YgWm9kRXJyb3IpIHtcbiAgICAgICAgICAgIGNvbnN0IHsgaHVtYW5pemVab2RFcnJvciB9ID0gYXdhaXQgaW1wb3J0KFwiLi4vdXRpbHMvem9kLWVycm9yXCIpO1xuICAgICAgICAgICAgY29uc3QgbWVzc2FnZXMgPSBodW1hbml6ZVpvZEVycm9yKGUpXG4gICAgICAgICAgICAgIC5tYXAoKGlzc3VlKSA9PiBpc3N1ZS5tZXNzYWdlKVxuICAgICAgICAgICAgICAuam9pbihcIiBcIik7XG4gICAgICAgICAgICBjb25zdCB7IEJhZFJlcXVlc3RFeGNlcHRpb24gfSA9IGF3YWl0IGltcG9ydChcIi4uL2V4Y2VwdGlvbnMvc28tZXhjZXB0aW9uc1wiKTtcbiAgICAgICAgICAgIHRocm93IG5ldyBCYWRSZXF1ZXN0RXhjZXB0aW9uKG1lc3NhZ2VzIGFzIExvY2FsaXplZFN0cmluZywge1xuICAgICAgICAgICAgICB6b2RFcnJvcjogZSxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aHJvdyBlO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIENvbnRlbnQtVHlwZVxuICAgICAgICByZXBseS50eXBlKGFwaS5vcHRpb25zLmNvbnRlbnRUeXBlID8/IFwiYXBwbGljYXRpb24vanNvblwiKTtcblxuICAgICAgICAvLyBDYWNoZS1Db250cm9sIO2XpOuNlCDshKTsoJVcbiAgICAgICAgY29uc3QgYXBpQ2FjaGVDb25maWcgPSB0aGlzLmdldEFwaUNhY2hlQ29udHJvbChhcGksIHJlcXVlc3QsIGNvbmZpZyk7XG4gICAgICAgIGlmIChhcGlDYWNoZUNvbmZpZykge1xuICAgICAgICAgIGFwcGx5Q2FjaGVIZWFkZXJzKHJlcGx5LCBhcGlDYWNoZUNvbmZpZyk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyDsl4XroZzrk5wg7Ji17IWY7J20IOyeiOuKlCDqsr3smrAg7YyM7J28IOuNsOydtO2EsOulvCBDb250ZXh07JeQIOy2lOqwgFxuICAgICAgICBpZiAoYXBpLnVwbG9hZE9wdGlvbnMpIHtcbiAgICAgICAgICBjb25zdCBjb25zdW1lID0gYXBpLnVwbG9hZE9wdGlvbnMuY29uc3VtZSA/PyBcImJ1ZmZlclwiO1xuICAgICAgICAgIGlmIChjb25zdW1lID09PSBcImJ1ZmZlclwiKSB7XG4gICAgICAgICAgICBjb250ZXh0LmJ1ZmZlcmVkRmlsZXMgPSBmaWxlcy5idWZmZXJlZEZpbGVzO1xuICAgICAgICAgIH0gZWxzZSBpZiAoY29uc3VtZSA9PT0gXCJzdHJlYW1cIikge1xuICAgICAgICAgICAgY29udGV4dC51cGxvYWRlZEZpbGVzID0gZmlsZXMudXBsb2FkZWRGaWxlcztcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyDrqqjrjbgg66mU7IaM65OcIGFyZ3Mg7IOd7ISx7ZWY7JesIO2YuOy2nFxuICAgICAgICBjb25zdCB7IEFwaVBhcmFtVHlwZSB9ID0gYXdhaXQgaW1wb3J0KFwiLi4vdHlwZXMvdHlwZXNcIik7XG4gICAgICAgIGNvbnN0IGFyZ3MgPSBhcGkucGFyYW1ldGVycy5tYXAoKHBhcmFtKSA9PiB7XG4gICAgICAgICAgLy8gQ29udGV4dCDsnbjsoJ3shZhcbiAgICAgICAgICBpZiAoQXBpUGFyYW1UeXBlLmlzQ29udGV4dChwYXJhbS50eXBlKSkge1xuICAgICAgICAgICAgcmV0dXJuIGNvbnRleHQ7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiByZXFCb2R5W3BhcmFtLm5hbWVdO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG5cbiAgICAgICAgcmV0dXJuIHRoaXMuaW52b2tlTW9kZWxNZXRob2QoYXBpLCBhcmdzLCByZXBseSk7XG4gICAgICB9KTtcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIFVSTOyXkOyEnCBwYXRoIHBhcmFtc+ulvCDstpTstpztlanri4jri6QuXG4gICAqIOyYiDogcGF0dGVybj1cIi9hZG1pbi9jb21wYW5pZXMvOmNvbXBhbnlJZFwiLCB1cmw9XCIvYWRtaW4vY29tcGFuaWVzLzEyM1wiIOKGkiB7IGNvbXBhbnlJZDogXCIxMjNcIiB9XG4gICAqL1xuICBwcml2YXRlIGV4dHJhY3RQYXRoUGFyYW1zKHBhdHRlcm46IHN0cmluZywgdXJsOiBzdHJpbmcpOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+IHtcbiAgICBjb25zdCBwYXR0ZXJuUGFydHMgPSBwYXR0ZXJuLnNwbGl0KFwiL1wiKS5maWx0ZXIoQm9vbGVhbik7XG4gICAgY29uc3QgdXJsUGFydHMgPSB0aGlzLmdldFBhdGhuYW1lRnJvbVVybCh1cmwpLnNwbGl0KFwiL1wiKS5maWx0ZXIoQm9vbGVhbik7XG4gICAgY29uc3QgcGFyYW1zOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+ID0ge307XG5cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHBhdHRlcm5QYXJ0cy5sZW5ndGg7IGkrKykge1xuICAgICAgaWYgKHBhdHRlcm5QYXJ0c1tpXS5zdGFydHNXaXRoKFwiOlwiKSkge1xuICAgICAgICBwYXJhbXNbcGF0dGVyblBhcnRzW2ldLnNsaWNlKDEpXSA9IHVybFBhcnRzW2ldO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gcGFyYW1zO1xuICB9XG5cbiAgcHJpdmF0ZSBpc1BhdGhQYXR0ZXJuTWF0Y2gocGF0dGVybjogc3RyaW5nLCB1cmw6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIGNvbnN0IHBhdHRlcm5QYXJ0cyA9IHBhdHRlcm4uc3BsaXQoXCIvXCIpLmZpbHRlcihCb29sZWFuKTtcbiAgICBjb25zdCB1cmxQYXJ0cyA9IHRoaXMuZ2V0UGF0aG5hbWVGcm9tVXJsKHVybCkuc3BsaXQoXCIvXCIpLmZpbHRlcihCb29sZWFuKTtcblxuICAgIGlmIChwYXR0ZXJuUGFydHMubGVuZ3RoICE9PSB1cmxQYXJ0cy5sZW5ndGgpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHBhdHRlcm5QYXJ0cy5sZW5ndGg7IGkrKykge1xuICAgICAgY29uc3QgcGF0dGVyblBhcnQgPSBwYXR0ZXJuUGFydHNbaV07XG4gICAgICBjb25zdCB1cmxQYXJ0ID0gdXJsUGFydHNbaV07XG4gICAgICBpZiAocGF0dGVyblBhcnQuc3RhcnRzV2l0aChcIjpcIikpIHtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG4gICAgICBpZiAocGF0dGVyblBhcnQgIT09IHVybFBhcnQpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXRQYXRobmFtZUZyb21VcmwodXJsOiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIHJldHVybiB1cmwuc3BsaXQoXCI/XCIpWzBdO1xuICB9XG5cbiAgcHJpdmF0ZSByZXNvbHZlUGF0aFdpdGhpbkJhc2VEaXIoYmFzZURpcjogc3RyaW5nLCBpbnB1dFBhdGg6IHN0cmluZyk6IHN0cmluZyB8IG51bGwge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBkZWNvZGVkID0gZGVjb2RlVVJJQ29tcG9uZW50KGlucHV0UGF0aCkucmVwbGFjZSgvXFxcXC9nLCBcIi9cIik7XG4gICAgICBpZiAoZGVjb2RlZC5pbmNsdWRlcyhcIlxcMFwiKSkge1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgIH1cbiAgICAgIGNvbnN0IHJlbGF0aXZlUGF0aCA9IGRlY29kZWQucmVwbGFjZSgvXlxcLysvLCBcIlwiKTtcbiAgICAgIGNvbnN0IHJlc29sdmVkUGF0aCA9IHBhdGgucmVzb2x2ZShiYXNlRGlyLCByZWxhdGl2ZVBhdGgpO1xuICAgICAgY29uc3QgcmVsYXRpdmVGcm9tQmFzZSA9IHBhdGgucmVsYXRpdmUoYmFzZURpciwgcmVzb2x2ZWRQYXRoKTtcbiAgICAgIGlmIChyZWxhdGl2ZUZyb21CYXNlLnN0YXJ0c1dpdGgoXCIuLlwiKSB8fCBwYXRoLmlzQWJzb2x1dGUocmVsYXRpdmVGcm9tQmFzZSkpIHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICB9XG4gICAgICByZXR1cm4gcmVzb2x2ZWRQYXRoO1xuICAgIH0gY2F0Y2gge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEFQSSDsnZHri7Xsl5Ag7KCB7Jqp7ZWgIENhY2hlLUNvbnRyb2wg7ISk7KCV7J2EIOqysOygle2VqeuLiOuLpC5cbiAgICog7Jqw7ISg7Iic7JyEOiDqsJzrs4Qg7KeA7KCVID4gY2FjaGVDb250cm9sSGFuZGxlclxuICAgKi9cbiAgcHJpdmF0ZSBnZXRBcGlDYWNoZUNvbnRyb2woXG4gICAgYXBpOiBFeHRlbmRlZEFwaSxcbiAgICByZXF1ZXN0OiBGYXN0aWZ5UmVxdWVzdCxcbiAgICBjb25maWc6IFNvbmFtdUZhc3RpZnlDb25maWcsXG4gICkge1xuICAgIC8vIOuNsOy9lOugiOydtO2EsCDshKTsoJUg7Jqw7ISgXG4gICAgaWYgKGFwaS5vcHRpb25zLmNhY2hlQ29udHJvbCkge1xuICAgICAgcmV0dXJuIGFwaS5vcHRpb25zLmNhY2hlQ29udHJvbDtcbiAgICB9XG5cbiAgICAvLyDsoITsl60g7ZW465Ok65+sXG4gICAgaWYgKGNvbmZpZy5jYWNoZUNvbnRyb2xIYW5kbGVyKSB7XG4gICAgICBjb25zdCBjYWNoZVJlcTogQ2FjaGVDb250cm9sUmVxdWVzdCA9IHtcbiAgICAgICAgdHlwZTogXCJhcGlcIixcbiAgICAgICAgdXJsOiByZXF1ZXN0LnVybCxcbiAgICAgICAgcGF0aDogcmVxdWVzdC5yb3V0ZU9wdGlvbnM/LnVybCA/PyByZXF1ZXN0LnVybC5zcGxpdChcIj9cIilbMF0sXG4gICAgICAgIG1ldGhvZDogcmVxdWVzdC5tZXRob2QsXG4gICAgICAgIGFwaSxcbiAgICAgIH07XG4gICAgICBjb25zdCByZXN1bHQgPSBjb25maWcuY2FjaGVDb250cm9sSGFuZGxlcihjYWNoZVJlcSk7XG4gICAgICBpZiAocmVzdWx0KSByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgLyoqXG4gICAqIFNTUuyaqSBBUEkg7Zi47LacIChIVFRQIOyYpOuyhO2XpOuTnCDsl4bsnbQg7KeB7KCRIO2YuOy2nClcbiAgICogY3JlYXRlQXBpSGFuZGxlcuydmCDroZzsp4HsnYQg7J6s7IKs7Jqp7ZWY65CYLCByZXF1ZXN0IO2MjOyLsSDrjIDsi6AgcGFyYW1zIOyngeygkSDsgqzsmqlcbiAgICovXG4gIGFzeW5jIGludm9rZUFwaUZvclNTUihcbiAgICBhcGk6IEV4dGVuZGVkQXBpLFxuICAgIC8vIG94bGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tZXhwbGljaXQtYW55IC0tIFNTUuyXkOyEnCDri6TslpHtlZwg7YOA7J6F7J2YIHBhcmFtc+ulvCDrsJvslYTslbwg7ZWoXG4gICAgcGFyYW1zOiBhbnlbXSxcbiAgICBjb25maWc6IFNvbmFtdUZhc3RpZnlDb25maWcsXG4gICAgcmVxdWVzdDogRmFzdGlmeVJlcXVlc3QsXG4gICAgcmVwbHk6IEZhc3RpZnlSZXBseSxcbiAgKTogUHJvbWlzZTx1bmtub3duPiB7XG4gICAgLy8gQ29udGV4dCDsg53shLEgKOq4sOyhtCDrqZTshozrk5wg7J6s7IKs7JqpKVxuICAgIGNvbnN0IGNvbnRleHQgPSBhd2FpdCB0aGlzLmNyZWF0ZUNvbnRleHQoY29uZmlnLCByZXF1ZXN0LCByZXBseSk7XG5cbiAgICByZXR1cm4gdGhpcy5hc3luY0xvY2FsU3RvcmFnZS5ydW4oeyBjb250ZXh0IH0sIGFzeW5jICgpID0+IHtcbiAgICAgIC8vIGFyZ3Mg7IOd7ISxOiBDb250ZXh0IO2MjOudvOuvuO2EsOuKlCDso7zsnoUsIOuCmOuouOyngOuKlCBwYXJhbXPsl5DshJwg6rCA7KC47Jik6riwXG4gICAgICBjb25zdCB7IEFwaVBhcmFtVHlwZSB9ID0gYXdhaXQgaW1wb3J0KFwiLi4vdHlwZXMvdHlwZXNcIik7XG4gICAgICBsZXQgcGFyYW1zSW5kZXggPSAwO1xuICAgICAgY29uc3QgYXJncyA9IGFwaS5wYXJhbWV0ZXJzLm1hcCgocGFyYW0pID0+IHtcbiAgICAgICAgaWYgKEFwaVBhcmFtVHlwZS5pc0NvbnRleHQocGFyYW0udHlwZSkpIHtcbiAgICAgICAgICByZXR1cm4gY29udGV4dDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcGFyYW1zW3BhcmFtc0luZGV4KytdO1xuICAgICAgfSk7XG5cbiAgICAgIC8vIOuqqOuNuCDrqZTshJzrk5wg7Zi47LacICjquLDsobQg66mU7ISc65OcIOyerOyCrOyaqSlcbiAgICAgIHJldHVybiB0aGlzLmludm9rZU1vZGVsTWV0aG9kKGFwaSwgYXJncywgcmVwbHkpO1xuICAgIH0pO1xuICB9XG5cbiAgYXN5bmMgaW52b2tlTW9kZWxNZXRob2QoXG4gICAgYXBpOiBFeHRlbmRlZEFwaSxcbiAgICBhcmdzOiB1bmtub3duW10sXG4gICAgcmVwbHk6IEZhc3RpZnlSZXBseSxcbiAgKTogUHJvbWlzZTx1bmtub3duPiB7XG4gICAgY29uc3QgbW9kZWwgPSB0aGlzLnN5bmNlci5tb2RlbHNbYXBpLm1vZGVsTmFtZV07XG4gICAgLy8gb3hsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1leHBsaWNpdC1hbnkgLS0gbW9kZWzsnYAg66qo6424IOyduOyKpO2EtOyKpOydtOuvgOuhnCDrqZTshJzrk5wg7Zi47LacIOqwgOuKpVxuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IChtb2RlbCBhcyBhbnkpW2FwaS5tZXRob2ROYW1lXS5hcHBseShtb2RlbCwgYXJncyk7XG4gICAgcmVwbHkudHlwZShhcGkub3B0aW9ucy5jb250ZW50VHlwZSA/PyBcImFwcGxpY2F0aW9uL2pzb25cIik7XG5cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbiAgYXN5bmMgY3JlYXRlQ29udGV4dChcbiAgICBjb25maWc6IFNvbmFtdUZhc3RpZnlDb25maWcsXG4gICAgcmVxdWVzdDogRmFzdGlmeVJlcXVlc3QsXG4gICAgcmVwbHk6IEZhc3RpZnlSZXBseSxcbiAgKTogUHJvbWlzZTxDb250ZXh0PiB7XG4gICAgLy8gY3JlYXRlU1NFRmFjdG9yeSDtlajsiJjsl5Ag66+466asIHJlcXVlc3TsnZggc29ja2V06rO8IHJlcGx566W8IOuwlOyduOuUqS5cbiAgICBjb25zdCB7IGNyZWF0ZVNTRUZhY3RvcnkgfSA9IGF3YWl0IGltcG9ydChcIi4uL3N0cmVhbS9zc2VcIik7XG4gICAgY29uc3QgY3JlYXRlU1NFID0gKDxUIGV4dGVuZHMgWm9kT2JqZWN0PihcbiAgICAgIF9yZXF1ZXN0OiBGYXN0aWZ5UmVxdWVzdCxcbiAgICAgIF9yZXBseTogRmFzdGlmeVJlcGx5LFxuICAgICAgX2V2ZW50czogVCxcbiAgICApID0+IGNyZWF0ZVNTRUZhY3RvcnkoX3JlcXVlc3Quc29ja2V0LCBfcmVwbHksIF9ldmVudHMpKS5iaW5kKG51bGwsIHJlcXVlc3QsIHJlcGx5KTtcblxuICAgIC8vIGxvY2FsZSDqsJDsp4BcbiAgICBjb25zdCBsb2NhbGUgPVxuICAgICAgdGhpcy5kZXRlY3RMb2NhbGUocmVxdWVzdC5oZWFkZXJzW1wiYWNjZXB0LWxhbmd1YWdlXCJdLCB0aGlzLmNvbmZpZy5pMThuLnN1cHBvcnRlZExvY2FsZXMpID8/XG4gICAgICB0aGlzLmNvbmZpZy5pMThuLmRlZmF1bHRMb2NhbGU7XG5cbiAgICAvLyBhdXRoIGNvbnRleHQg7LaU6rCAXG4gICAgY29uc3QgaGVhZGVycyA9IGNvbnZlcnRGYXN0aWZ5SGVhZGVyc1RvU3RhbmRhcmQocmVxdWVzdC5oZWFkZXJzKTtcbiAgICBjb25zdCBzZXNzaW9uID0gKGF3YWl0IHRoaXMuX2F1dGg/LmFwaS5nZXRTZXNzaW9uKHsgaGVhZGVycyB9KSkgPz8gbnVsbDtcblxuICAgIGNvbnN0IGNvbnRleHQ6IENvbnRleHQgPSB7XG4gICAgICAuLi4oYXdhaXQgUHJvbWlzZS5yZXNvbHZlKFxuICAgICAgICBjb25maWcuY29udGV4dFByb3ZpZGVyKFxuICAgICAgICAgIHtcbiAgICAgICAgICAgIHJlcXVlc3QsXG4gICAgICAgICAgICByZXBseSxcbiAgICAgICAgICAgIGhlYWRlcnM6IHJlcXVlc3QuaGVhZGVycyxcbiAgICAgICAgICAgIGNyZWF0ZVNTRSxcbiAgICAgICAgICAgIG5haXRlU3RvcmU6IG5ldyBNYXAoKSxcbiAgICAgICAgICAgIGxvY2FsZSxcbiAgICAgICAgICAgIC8vIGF1dGhcbiAgICAgICAgICAgIHVzZXI6IHNlc3Npb24/LnVzZXIgPz8gbnVsbCxcbiAgICAgICAgICAgIHNlc3Npb246IHNlc3Npb24/LnNlc3Npb24gPz8gbnVsbCxcbiAgICAgICAgICB9LFxuICAgICAgICAgIHJlcXVlc3QsXG4gICAgICAgICAgcmVwbHksXG4gICAgICAgICksXG4gICAgICApKSxcbiAgICB9O1xuICAgIHJldHVybiBjb250ZXh0O1xuICB9XG5cbiAgLyoqXG4gICAqIEFjY2VwdC1MYW5ndWFnZSDtl6TrjZTsl5DshJwg7KeA7JuQ7ZWY64qUIGxvY2FsZeydhCDssL7sirXri4jri6QuXG4gICAqIEBleGFtcGxlIFwia28tS1Isa287cT0wLjksZW47cT0wLjhcIiDihpIgXCJrb1wiXG4gICAqL1xuICBwcml2YXRlIGRldGVjdExvY2FsZShcbiAgICBhY2NlcHRMYW5ndWFnZTogc3RyaW5nIHwgdW5kZWZpbmVkLFxuICAgIHN1cHBvcnRlZDogc3RyaW5nW10sXG4gICk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gICAgaWYgKCFhY2NlcHRMYW5ndWFnZSkgcmV0dXJuIHVuZGVmaW5lZDtcblxuICAgIC8vIEFjY2VwdC1MYW5ndWFnZToga28tS1Isa287cT0wLjksZW47cT0wLjhcbiAgICBjb25zdCBsYW5ncyA9IGFjY2VwdExhbmd1YWdlLnNwbGl0KFwiLFwiKS5tYXAoKGxhbmcpID0+IHtcbiAgICAgIGNvbnN0IFtjb2RlXSA9IGxhbmcuc3BsaXQoXCI7XCIpO1xuICAgICAgcmV0dXJuIGNvZGUudHJpbSgpLnNwbGl0KFwiLVwiKVswXTsgLy8ga28tS1Ig4oaSIGtvXG4gICAgfSk7XG5cbiAgICByZXR1cm4gbGFuZ3MuZmluZCgobGFuZykgPT4gc3VwcG9ydGVkLmluY2x1ZGVzKGxhbmcpKTtcbiAgfVxuXG4gIGFzeW5jIHN0YXJ0V2F0Y2hlcigpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCB3YXRjaFBhdGggPSBbcGF0aC5qb2luKHRoaXMuYXBpUm9vdFBhdGgsIFwic3JjXCIpXTtcblxuICAgIGNvbnN0IGNob2tpZGFyID0gKGF3YWl0IGltcG9ydChcImNob2tpZGFyXCIpKS5kZWZhdWx0O1xuICAgIHRoaXMud2F0Y2hlciA9IGNob2tpZGFyLndhdGNoKHdhdGNoUGF0aCwge1xuICAgICAgaWdub3JlZDogKHBhdGgsIHN0YXRzKSA9PlxuICAgICAgICAhIXN0YXRzPy5pc0ZpbGUoKSAmJiAhcGF0aC5lbmRzV2l0aChcIi50c1wiKSAmJiAhcGF0aC5lbmRzV2l0aChcIi5qc29uXCIpLFxuICAgICAgcGVyc2lzdGVudDogdHJ1ZSxcbiAgICAgIGlnbm9yZUluaXRpYWw6IHRydWUsXG4gICAgfSk7XG5cbiAgICB0aGlzLndhdGNoZXIub24oXCJhbGxcIiwgYXN5bmMgKGV2ZW50OiBzdHJpbmcsIGZpbGVQYXRoOiBzdHJpbmcpID0+IHtcbiAgICAgIGNvbnN0IGFic29sdXRlUGF0aCA9IGZpbGVQYXRoIGFzIEFic29sdXRlUGF0aDtcbiAgICAgIGFzc2VydChcbiAgICAgICAgYWJzb2x1dGVQYXRoLnN0YXJ0c1dpdGgodGhpcy5hcGlSb290UGF0aCksXG4gICAgICAgIFwiRmlsZSBwYXRoIGlzIG5vdCB3aXRoaW4gdGhlIEFQSSByb290IHBhdGhcIixcbiAgICAgICk7XG5cbiAgICAgIGlmIChldmVudCAhPT0gXCJjaGFuZ2VcIiAmJiBldmVudCAhPT0gXCJhZGRcIikge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIHRyeSB7XG4gICAgICAgIC8vIHNvbmFtdS5jb25maWcudHMg67OA6rK9IOyLnCDsnqzsi5zsnpFcbiAgICAgICAgY29uc3QgaXNDb25maWdUcyA9IGZpbGVQYXRoID09PSBwYXRoLmpvaW4odGhpcy5hcGlSb290UGF0aCwgXCJzcmNcIiwgXCJzb25hbXUuY29uZmlnLnRzXCIpO1xuXG4gICAgICAgIGlmIChpc0NvbmZpZ1RzKSB7XG4gICAgICAgICAgY29uc3QgcmVsYXRpdmVQYXRoID0gZmlsZVBhdGgucmVwbGFjZSh0aGlzLmFwaVJvb3RQYXRoLCBcImFwaVwiKTtcbiAgICAgICAgICBjb25zdCBjaGFsayA9IChhd2FpdCBpbXBvcnQoXCJjaGFsa1wiKSkuZGVmYXVsdDtcbiAgICAgICAgICBjb25zb2xlLmxvZyhcbiAgICAgICAgICAgIGNoYWxrLmJvbGQoYERldGVjdGVkKCR7ZXZlbnR9KTogJHtjaGFsay5ibHVlKHJlbGF0aXZlUGF0aCl9IC0gUmVzdGFydGluZy4uLmApLFxuICAgICAgICAgICk7XG4gICAgICAgICAgcHJvY2Vzcy5raWxsKHByb2Nlc3MucGlkLCBcIlNJR1VTUjJcIik7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgYXdhaXQgdGhpcy5oYW5kbGVGaWxlQ2hhbmdlKGV2ZW50LCBhYnNvbHV0ZVBhdGgpO1xuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICBjb25zb2xlLmVycm9yKGUpO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgLypcbiAgICAgQSBmdW5jdGlvbiB0aGF0IGF1dG9tYXRpY2FsbHkgaGFuZGxlcyBpbml0IGFuZCBkZXN0cm95IHdoZW4gdXNpbmcgU29uYW11IHZpYSBzY3JpcHRzLlxuICAqL1xuICBhc3luYyBydW5TY3JpcHQoZm46ICgpID0+IFByb21pc2U8dm9pZD4pIHtcbiAgICBhd2FpdCB0aGlzLmluaXQodHJ1ZSwgZmFsc2UsIHVuZGVmaW5lZCwgZmFsc2UpO1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCBmbigpO1xuICAgIH0gZmluYWxseSB7XG4gICAgICBhd2FpdCB0aGlzLmRlc3Ryb3koKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIHJlZ2lzdGVyUGx1Z2lucyhzZXJ2ZXI6IEZhc3RpZnlJbnN0YW5jZSwgcGx1Z2luczogU29uYW11U2VydmVyT3B0aW9uc1tcInBsdWdpbnNcIl0pIHtcbiAgICBpZiAoIXBsdWdpbnMpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBjb21wcmVzcyDtlIzrn6zqt7jsnbjsnYAg64uk66W4IO2UjOufrOq3uOyduOuztOuLpCDrqLzsoIAg65Ox66Gd65CY7Ja07JW8IO2VqeuLiOuLpC5cbiAgICBpZiAocGx1Z2lucy5jb21wcmVzcykge1xuICAgICAgY29uc3QgY29tcHJlc3NQbHVnaW4gPSAoYXdhaXQgaW1wb3J0KFwiQGZhc3RpZnkvY29tcHJlc3NcIikpLmRlZmF1bHQ7XG4gICAgICBjb25zdCBkZWZhdWx0T3B0aW9ucyA9IHtcbiAgICAgICAgdGhyZXNob2xkOiAxMDI0LFxuICAgICAgICBlbmNvZGluZ3M6IFtcImJyXCIsIFwiZ3ppcFwiLCBcImRlZmxhdGVcIl0gYXMgKFwiYnJcIiB8IFwiZ3ppcFwiIHwgXCJkZWZsYXRlXCIpW10sXG4gICAgICB9O1xuXG4gICAgICBpZiAocGx1Z2lucy5jb21wcmVzcyA9PT0gdHJ1ZSkge1xuICAgICAgICBzZXJ2ZXIucmVnaXN0ZXIoY29tcHJlc3NQbHVnaW4sIGRlZmF1bHRPcHRpb25zKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHNlcnZlci5yZWdpc3Rlcihjb21wcmVzc1BsdWdpbiwge1xuICAgICAgICAgIC4uLmRlZmF1bHRPcHRpb25zLFxuICAgICAgICAgIC4uLnBsdWdpbnMuY29tcHJlc3MsXG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIGNvbnN0IHBsdWdpbnNNb2R1bGVzID0ge1xuICAgICAgY29yczogXCJAZmFzdGlmeS9jb3JzXCIsXG4gICAgICBmb3JtYm9keTogXCJAZmFzdGlmeS9mb3JtYm9keVwiLFxuICAgICAgbXVsdGlwYXJ0OiBcIkBmYXN0aWZ5L211bHRpcGFydFwiLFxuICAgICAgcXM6IFwiZmFzdGlmeS1xc1wiLFxuICAgICAgc3NlOiBcImZhc3RpZnktc3NlLXYyXCIsXG4gICAgICBzdGF0aWM6IFwiQGZhc3RpZnkvc3RhdGljXCIsXG4gICAgfSBhcyBjb25zdDtcblxuICAgIGNvbnN0IHJlZ2lzdGVyUGx1Z2luID0gYXN5bmMgPEsgZXh0ZW5kcyBrZXlvZiBOb25OdWxsYWJsZTx0eXBlb2YgcGx1Z2lucz4+KFxuICAgICAga2V5OiBLLFxuICAgICAgcGx1Z2luTmFtZTogc3RyaW5nLFxuICAgICkgPT4ge1xuICAgICAgY29uc3Qgb3B0aW9uID0gcGx1Z2luc1trZXldO1xuICAgICAgaWYgKCFvcHRpb24pIHJldHVybjtcblxuICAgICAgaWYgKG9wdGlvbiA9PT0gdHJ1ZSkge1xuICAgICAgICBzZXJ2ZXIucmVnaXN0ZXIoKGF3YWl0IGltcG9ydChwbHVnaW5OYW1lKSkuZGVmYXVsdCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBzZXJ2ZXIucmVnaXN0ZXIoKGF3YWl0IGltcG9ydChwbHVnaW5OYW1lKSkuZGVmYXVsdCwgb3B0aW9uKTtcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgZm9yIChjb25zdCBba2V5LCBwbHVnaW5OYW1lXSBvZiBPYmplY3QuZW50cmllcyhwbHVnaW5zTW9kdWxlcykpIHtcbiAgICAgIGF3YWl0IHJlZ2lzdGVyUGx1Z2luKGtleSBhcyBrZXlvZiB0eXBlb2YgcGx1Z2lucywgcGx1Z2luTmFtZSk7XG4gICAgfVxuXG4gICAgaWYgKHBsdWdpbnMuY3VzdG9tKSB7XG4gICAgICBwbHVnaW5zLmN1c3RvbShzZXJ2ZXIpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBiZXR0ZXItYXV0aCDrnbzsmrDtirjrpbwg65Ox66Gd7ZWp64uI64ukLlxuICAgKiAvYXBpL2F1dGgvKiDqsr3roZzroZwg7J247KadIEFQSeqwgCDsnpDrj5kg65Ox66Gd65Cp64uI64ukLlxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyByZWdpc3RlckJldHRlckF1dGgoXG4gICAgc2VydmVyOiBGYXN0aWZ5SW5zdGFuY2UsXG4gICAgb3B0aW9uczogTm9uTnVsbGFibGU8U29uYW11U2VydmVyT3B0aW9uc1tcImF1dGhcIl0+LFxuICApIHtcbiAgICBpZiAoIW9wdGlvbnMpIHJldHVybjtcblxuICAgIGNvbnN0IGJhc2VQYXRoID0gb3B0aW9ucy5iYXNlUGF0aCA/PyBcIi9hcGkvYXV0aFwiO1xuXG4gICAgLy8gYmV0dGVyLWF1dGgg65287Jqw7Yq4IOuTseuhnVxuICAgIHNlcnZlci5yb3V0ZSh7XG4gICAgICBtZXRob2Q6IFtcIkdFVFwiLCBcIlBPU1RcIl0sXG4gICAgICB1cmw6IGAke2Jhc2VQYXRofS8qYCxcbiAgICAgIGhhbmRsZXI6IGFzeW5jIChyZXF1ZXN0LCByZXBseSkgPT4ge1xuICAgICAgICBjb25zdCB1cmwgPSBuZXcgVVJMKHJlcXVlc3QudXJsLCBgaHR0cDovLyR7cmVxdWVzdC5oZWFkZXJzLmhvc3R9YCk7XG4gICAgICAgIGNvbnN0IGhlYWRlcnMgPSBjb252ZXJ0RmFzdGlmeUhlYWRlcnNUb1N0YW5kYXJkKHJlcXVlc3QuaGVhZGVycyk7XG5cbiAgICAgICAgLy8gSVAg7Zek642UIGZhbGxiYWNrOiDtlITroZ3si5zqsIAg7ZGc7KSAIElQIO2XpOuNlOulvCDso7zsnoXtlZjsp4Ag7JWK64qUIO2ZmOqyveyXkOyEnOuPhFxuICAgICAgICAvLyBiZXR0ZXItYXV0aC9pbmZyYeydmCBnZXRDbGllbnRJcEZyb21SZXF1ZXN0KCnqsIAgSVDrpbwg7J247Iud7ZWgIOyImCDsnojrj4TroZ1cbiAgICAgICAgLy8gRmFzdGlmeeqwgCByZXNvbHZl7ZWcIHJlcXVlc3QuaXDrpbwgeC1yZWFsLWlw66GcIOyjvOyehe2VnOuLpC5cbiAgICAgICAgY29uc3QgSVBfSEVBREVSUyA9IFtcbiAgICAgICAgICBcImNmLWNvbm5lY3RpbmctaXBcIixcbiAgICAgICAgICBcIngtZm9yd2FyZGVkLWZvclwiLFxuICAgICAgICAgIFwieC1yZWFsLWlwXCIsXG4gICAgICAgICAgXCJ4LXZlcmNlbC1mb3J3YXJkZWQtZm9yXCIsXG4gICAgICAgIF07XG4gICAgICAgIGlmIChyZXF1ZXN0LmlwICYmICFJUF9IRUFERVJTLnNvbWUoKGgpID0+IGhlYWRlcnMuaGFzKGgpKSkge1xuICAgICAgICAgIGhlYWRlcnMuc2V0KFwieC1yZWFsLWlwXCIsIHJlcXVlc3QuaXApO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgcmVxID0gbmV3IFJlcXVlc3QodXJsLnRvU3RyaW5nKCksIHtcbiAgICAgICAgICBtZXRob2Q6IHJlcXVlc3QubWV0aG9kLFxuICAgICAgICAgIGhlYWRlcnMsXG4gICAgICAgICAgLi4uKHJlcXVlc3QuYm9keSA/IHsgYm9keTogSlNPTi5zdHJpbmdpZnkocmVxdWVzdC5ib2R5KSB9IDoge30pLFxuICAgICAgICB9KTtcblxuICAgICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMuYXV0aC5oYW5kbGVyKHJlcSk7XG5cbiAgICAgICAgcmVwbHkuc3RhdHVzKHJlc3BvbnNlLnN0YXR1cyk7XG4gICAgICAgIHJlc3BvbnNlLmhlYWRlcnMuZm9yRWFjaCgodmFsdWU6IHN0cmluZywga2V5OiBzdHJpbmcpID0+IHtcbiAgICAgICAgICByZXBseS5oZWFkZXIoa2V5LCB2YWx1ZSk7XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gcmVwbHkuc2VuZChyZXNwb25zZS5ib2R5ID8gYXdhaXQgcmVzcG9uc2UudGV4dCgpIDogbnVsbCk7XG4gICAgICB9LFxuICAgIH0pO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBwcmludFN0YXJ0dXBTdW1tYXJ5KCkge1xuICAgIGNvbnN0IGNoYWxrID0gKGF3YWl0IGltcG9ydChcImNoYWxrXCIpKS5kZWZhdWx0O1xuICAgIGNvbnN0IGVudiA9IHByb2Nlc3MuZW52Lk5PREVfRU5WID8/IFwiZGV2ZWxvcG1lbnRcIjtcbiAgICBjb25zdCBhY3RpdmVQcmVzZXQgPSBlbnYgPT09IFwicHJvZHVjdGlvblwiID8gXCJwcm9kdWN0aW9uX21hc3RlclwiIDogXCJkZXZlbG9wbWVudF9tYXN0ZXJcIjtcblxuICAgIGNvbnN0IGRpbSA9IChtc2c6IHN0cmluZykgPT4gY29uc29sZS5sb2coY2hhbGsuZGltKGDinJMgJHttc2d9YCkpO1xuICAgIGNvbnN0IGdyZWVuID0gKG1zZzogc3RyaW5nKSA9PiBjb25zb2xlLmxvZyhjaGFsay5ncmVlbihg4pyTICR7bXNnfWApKTtcblxuICAgIGRpbShgQ29uZmlnIGxvYWRlZCR7Zm9ybWF0VGltZSh0aGlzLl9jb25maWdFbGFwc2VkKX1gKTtcblxuICAgIC8vIERCIHByZXNldCDrqqnroZ1cbiAgICBncmVlbihcIkRCXCIpO1xuICAgIGNvbnN0IHsgaXNMb2NhbCB9ID0gYXdhaXQgaW1wb3J0KFwiLi4vdXRpbHMvY29udHJvbGxlclwiKTtcbiAgICBjb25zdCBwcmVzZXROYW1lcyA9IE9iamVjdC5rZXlzKHRoaXMuZGJDb25maWcpIGFzIChrZXlvZiBTb25hbXVEQkNvbmZpZylbXTtcbiAgICBjb25zdCBtYXhMZW4gPSBNYXRoLm1heCguLi5wcmVzZXROYW1lcy5tYXAoKG4pID0+IG4ubGVuZ3RoKSk7XG4gICAgZm9yIChjb25zdCBuYW1lIG9mIHByZXNldE5hbWVzKSB7XG4gICAgICBjb25zdCBjb25uID0gdGhpcy5kYkNvbmZpZ1tuYW1lXS5jb25uZWN0aW9uIGFzXG4gICAgICAgIHwgeyBob3N0Pzogc3RyaW5nOyBwb3J0PzogbnVtYmVyOyBkYXRhYmFzZT86IHN0cmluZyB9XG4gICAgICAgIHwgdW5kZWZpbmVkO1xuICAgICAgY29uc3QgaG9zdCA9IGNvbm4/Lmhvc3QgPz8gXCJsb2NhbGhvc3RcIjtcbiAgICAgIGNvbnN0IGFkZHIgPSBgQCAke2hvc3R9OiR7Y29ubj8ucG9ydCA/PyA1NDMyfS8ke2Nvbm4/LmRhdGFiYXNlID8/IHRoaXMuY29uZmlnLmRhdGFiYXNlLm5hbWV9YDtcbiAgICAgIGNvbnN0IHBhZGRlZCA9IG5hbWUucGFkRW5kKG1heExlbik7XG4gICAgICBjb25zdCByZW1vdGVUYWcgPSBpc0xvY2FsKCkgJiYgIWlzTG9jYWxIb3N0KGhvc3QpID8gY2hhbGsueWVsbG93KGAgXFx1MjZhMCByZW1vdGVgKSA6IFwiXCI7XG5cbiAgICAgIGlmIChuYW1lID09PSBhY3RpdmVQcmVzZXQpIHtcbiAgICAgICAgY29uc29sZS5sb2coY2hhbGsuZ3JlZW4oYCAgXFx1MjViOCAke3BhZGRlZH0gJHthZGRyfWApICsgcmVtb3RlVGFnKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnNvbGUubG9nKGNoYWxrLmRpbShgICAgICR7cGFkZGVkfSAke2FkZHJ9YCkgKyByZW1vdGVUYWcpO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmICh0aGlzLmNvbmZpZy5zZXJ2ZXIuYXV0aCkge1xuICAgICAgY29uc3QgYmFzZVBhdGggPSB0aGlzLmNvbmZpZy5zZXJ2ZXIuYXV0aC5iYXNlUGF0aCA/PyBcIi9hcGkvYXV0aFwiO1xuICAgICAgZGltKGBBdXRoOiBiZXR0ZXItYXV0aCBhdCAke2Jhc2VQYXRofS8qYCk7XG4gICAgfVxuICAgIGlmICh0aGlzLmNvbmZpZy5hcGkudGltZXpvbmUpIHtcbiAgICAgIGRpbShgVGltZXpvbmU6ICR7dGhpcy5jb25maWcuYXBpLnRpbWV6b25lfWApO1xuICAgIH1cbiAgICBncmVlbihgU29uYW11IHJlYWR5JHtmb3JtYXRUaW1lKHRoaXMuX2luaXRFbGFwc2VkKX1gKTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgaW5pdGlhbGl6ZUNhY2hlKGNvbmZpZzogQ2FjaGVDb25maWcgfCB1bmRlZmluZWQsIGZvclRlc3Rpbmc6IGJvb2xlYW4pIHtcbiAgICBjb25zdCB7IHNldENhY2hlTWFuYWdlclJlZiB9ID0gYXdhaXQgaW1wb3J0KFwiLi4vY2FjaGUvZGVjb3JhdG9yXCIpO1xuXG4gICAgLy8g7YWM7Iqk7Yq4IO2ZmOqyveyXkOyEnCDrqZTrqqjrpqwg65Oc65287J2067KEIOyekOuPmSDsgqzsmqlcbiAgICBpZiAoZm9yVGVzdGluZykge1xuICAgICAgY29uc3QgeyBjcmVhdGVUZXN0Q2FjaGVNYW5hZ2VyIH0gPSBhd2FpdCBpbXBvcnQoXCIuLi9jYWNoZS9jYWNoZS1tYW5hZ2VyXCIpO1xuICAgICAgdGhpcy5fY2FjaGUgPSBjcmVhdGVUZXN0Q2FjaGVNYW5hZ2VyKCk7XG4gICAgICBzZXRDYWNoZU1hbmFnZXJSZWYodGhpcy5fY2FjaGUpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIOyEpOygleydtCDsl4bsnLzrqbQg7LqQ7IucIOu5hO2ZnOyEse2ZlFxuICAgIGlmICghY29uZmlnKSB7XG4gICAgICBzZXRDYWNoZU1hbmFnZXJSZWYobnVsbCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8g7ISk7KCV7JeQIOuUsOudvCBDYWNoZU1hbmFnZXIg7IOd7ISxXG4gICAgY29uc3QgeyBjcmVhdGVDYWNoZU1hbmFnZXIgfSA9IGF3YWl0IGltcG9ydChcIi4uL2NhY2hlL2NhY2hlLW1hbmFnZXJcIik7XG4gICAgdGhpcy5fY2FjaGUgPSBjcmVhdGVDYWNoZU1hbmFnZXIoY29uZmlnKTtcbiAgICBzZXRDYWNoZU1hbmFnZXJSZWYodGhpcy5fY2FjaGUpO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBpbml0aWFsaXplV29ya2Zsb3dzKG9wdGlvbnM6IFNvbmFtdVRhc2tPcHRpb25zIHwgdW5kZWZpbmVkKSB7XG4gICAgY29uc3QgeyBXb3JrZmxvd01hbmFnZXIgfSA9IGF3YWl0IGltcG9ydChcIi4uL3Rhc2tzL3dvcmtmbG93LW1hbmFnZXJcIik7XG4gICAgLy8gTk9URTogQHNvbmFtdS1raXQvdGFza3Mg7JWI7JeQ7ISgIGtuZXggY29uZmln66W8IOyImOygle2VmOq4sCDrlYzrrLjsl5AgY29ubmVjdGlvbuydtCDslYTri4wgY29uZmlnIOynuOuhnCDrs7Trg4Xri4jri6QuXG4gICAgdGhpcy5fd29ya2Zsb3dzID0gbmV3IFdvcmtmbG93TWFuYWdlcihEQi5nZXREQkNvbmZpZyhcIndcIikpO1xuICAgIGlmICghb3B0aW9ucykge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IGVuYWJsZVdvcmtlciA9IG9wdGlvbnMuZW5hYmxlV29ya2VyID8/IGlzRGFlbW9uU2VydmVyKCk7XG4gICAgY29uc3QgZGVmYXVsdFdvcmtlck9wdGlvbnMgPSB7XG4gICAgICBjb25jdXJyZW5jeTogb3MuY3B1cygpLmxlbmd0aCAtIDEsXG4gICAgICB1c2VQdWJTdWI6IHRydWUsXG4gICAgICBsaXN0ZW5EZWxheTogNTAwLFxuICAgIH07XG5cbiAgICBpZiAoZW5hYmxlV29ya2VyKSB7XG4gICAgICB0aGlzLndvcmtmbG93cy5zZXR1cFdvcmtlcih7XG4gICAgICAgIC4uLmRlZmF1bHRXb3JrZXJPcHRpb25zLFxuICAgICAgICAuLi5vcHRpb25zLndvcmtlck9wdGlvbnMsXG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGJvb3Qoc2VydmVyOiBGYXN0aWZ5SW5zdGFuY2UsIG9wdGlvbnM6IFNvbmFtdVNlcnZlck9wdGlvbnMpIHtcbiAgICBjb25zdCBwb3J0ID0gb3B0aW9ucy5saXN0ZW4/LnBvcnQgPz8gMzAwMDtcbiAgICBjb25zdCBob3N0ID0gb3B0aW9ucy5saXN0ZW4/Lmhvc3QgPz8gXCJsb2NhbGhvc3RcIjtcblxuICAgIHNlcnZlci5hZGRIb29rKFwib25DbG9zZVwiLCBhc3luYyAoKSA9PiB7XG4gICAgICBhd2FpdCBvcHRpb25zLmxpZmVjeWNsZT8ub25TaHV0ZG93bj8uKHNlcnZlcik7XG4gICAgICBhd2FpdCB0aGlzLndvcmtmbG93cy5kZXN0cm95KCk7XG4gICAgICBhd2FpdCB0aGlzLmRlc3Ryb3koKTtcbiAgICB9KTtcblxuICAgIGNvbnN0IHNodXRkb3duID0gYXN5bmMgKCkgPT4ge1xuICAgICAgdHJ5IHtcbiAgICAgICAgYXdhaXQgc2VydmVyLmNsb3NlKCk7XG4gICAgICAgIHByb2Nlc3MuZXhpdCgwKTtcbiAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICBjb25zb2xlLmVycm9yKFwiRXJyb3IgZHVyaW5nIHNodXRkb3duOlwiLCBlcnIpO1xuICAgICAgICBwcm9jZXNzLmV4aXQoMSk7XG4gICAgICB9XG4gICAgfTtcblxuICAgIHByb2Nlc3Mub24oXCJTSUdJTlRcIiwgc2h1dGRvd24pO1xuICAgIHByb2Nlc3Mub24oXCJTSUdURVJNXCIsIHNodXRkb3duKTtcblxuICAgIGlmIChvcHRpb25zLmxpZmVjeWNsZT8ub25FcnJvcikge1xuICAgICAgc2VydmVyLnNldEVycm9ySGFuZGxlcihvcHRpb25zLmxpZmVjeWNsZT8ub25FcnJvcik7XG4gICAgfVxuXG4gICAgc2VydmVyXG4gICAgICAubGlzdGVuKHsgcG9ydCwgaG9zdCB9KVxuICAgICAgLnRoZW4oYXN5bmMgKCkgPT4ge1xuICAgICAgICBhd2FpdCB0aGlzLndvcmtmbG93cy5zdGFydFdvcmtlcigpO1xuICAgICAgICBhd2FpdCBvcHRpb25zLmxpZmVjeWNsZT8ub25TdGFydD8uKHNlcnZlcik7XG4gICAgICB9KVxuICAgICAgLmNhdGNoKGFzeW5jIChlcnIpID0+IHtcbiAgICAgICAgY29uc3QgY2hhbGsgPSAoYXdhaXQgaW1wb3J0KFwiY2hhbGtcIikpLmRlZmF1bHQ7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoY2hhbGsucmVkKFwiRmFpbGVkIHRvIHN0YXJ0IHNlcnZlcjpcIiwgZXJyKSk7XG4gICAgICAgIGF3YWl0IHNodXRkb3duKCk7XG4gICAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgaGFuZGxlRmlsZUNoYW5nZShldmVudDogc3RyaW5nLCBmaWxlUGF0aDogQWJzb2x1dGVQYXRoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgLy8g7LKrIOuyiOynuCDtjIzsnbzsnbTrqbQgSE1SIOyLnOyekSDsi5zqsIQg6riw66GdXG4gICAgaWYgKHRoaXMucGVuZGluZ0ZpbGVzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgdGhpcy5obXJTdGFydFRpbWUgPSBEYXRlLm5vdygpO1xuICAgIH1cbiAgICB0aGlzLnBlbmRpbmdGaWxlcy5wdXNoKGZpbGVQYXRoKTtcblxuICAgIGNvbnN0IHJlbGF0aXZlUGF0aCA9IHBhdGgucmVsYXRpdmUodGhpcy5hcGlSb290UGF0aCwgZmlsZVBhdGgpO1xuICAgIGNvbnN0IGNoYWxrID0gKGF3YWl0IGltcG9ydChcImNoYWxrXCIpKS5kZWZhdWx0O1xuICAgIGNvbnNvbGUubG9nKGNoYWxrLmJvbGQoYERldGVjdGVkKCR7ZXZlbnR9KTogJHtjaGFsay5ibHVlKHJlbGF0aXZlUGF0aCl9YCkpO1xuXG4gICAgYXdhaXQgdGhpcy5zeW5jZXIuc3luY0Zyb21XYXRjaGVyKGV2ZW50LCBmaWxlUGF0aCk7XG5cbiAgICAvLyDsspjrpqwg7JmE66OM65CcIO2MjOydvOydhCDrjIDquLAg66qp66Gd7JeQ7IScIOygnOqxsFxuICAgIHRoaXMucGVuZGluZ0ZpbGVzID0gdGhpcy5wZW5kaW5nRmlsZXMuc2xpY2UoMSk7XG5cbiAgICAvLyDrqqjrk6Ag7YyM7J28IOyymOumrOqwgCDsmYTro4zrkJjrqbQg7LWc7KKFIOuplOyLnOyngCDstpzroKVcbiAgICBpZiAodGhpcy5wZW5kaW5nRmlsZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICBhd2FpdCB0aGlzLmZpbmlzaEhNUigpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgZmluaXNoSE1SKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGF3YWl0IHRoaXMuc3luY2VyLnJlbmV3Q2hlY2tzdW1zKCk7XG5cbiAgICBjb25zdCBlbmRUaW1lID0gRGF0ZS5ub3coKTtcbiAgICBjb25zdCB0b3RhbFRpbWUgPSBlbmRUaW1lIC0gdGhpcy5obXJTdGFydFRpbWU7XG4gICAgY29uc3QgW2NoYWxrLCB7IGNlbnRlclRleHQgfV0gPSBhd2FpdCBQcm9taXNlLmFsbChbXG4gICAgICAoYXdhaXQgaW1wb3J0KFwiY2hhbGtcIikpLmRlZmF1bHQsXG4gICAgICBpbXBvcnQoXCIuLi91dGlscy9jb25zb2xlLXV0aWxcIiksXG4gICAgXSk7XG4gICAgY29uc3QgbXNnID0gYEhNUiBEb25lISAke2NoYWxrLmJvbGQud2hpdGUoYCR7dG90YWxUaW1lfW1zYCl9YDtcblxuICAgIGNvbnNvbGUubG9nKGNoYWxrLmJsYWNrLmJnR3JlZW4oY2VudGVyVGV4dChtc2cpKSk7XG4gIH1cblxuICBhc3luYyBkZXN0cm95KCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IHsgQmFzZU1vZGVsIH0gPSBhd2FpdCBpbXBvcnQoXCIuLi9kYXRhYmFzZS9iYXNlLW1vZGVsXCIpO1xuICAgIC8vIOuovOyggCDsspjrpqztlbTslbztlaguXG4gICAgYXdhaXQgQmFzZU1vZGVsLmRlc3Ryb3koKTtcbiAgICBhd2FpdCBQcm9taXNlLmFsbFNldHRsZWQoW1xuICAgICAgdGhpcy5fd29ya2Zsb3dzPy5kZXN0cm95KCkgPz8gUHJvbWlzZS5yZXNvbHZlKCksXG4gICAgICB0aGlzLl9jYWNoZT8uZGlzY29ubmVjdCgpID8/IFByb21pc2UucmVzb2x2ZSgpLFxuICAgICAgdGhpcy5fZGV2Vml0ZXN0TWFuYWdlcj8uc2h1dGRvd24oKSA/PyBQcm9taXNlLnJlc29sdmUoKSxcbiAgICAgIHRoaXMud2F0Y2hlcj8uY2xvc2UoKSA/PyBQcm9taXNlLnJlc29sdmUoKSxcbiAgICAgIGxvZ3RhcGVEaXNwb3NlKCksXG4gICAgXSk7XG4gIH1cbn1cblxuZXhwb3J0IGNvbnN0IFNvbmFtdSA9IG5ldyBTb25hbXVDbGFzcygpO1xuXG4vKipcbiAqIHN0cmVhbSDrqqjrk5zsl5DshJwg7YKkIOyDneyEsSDtlajsiJjqsIAg7KeA7KCV65CY7KeAIOyViuyVmOydhCDrlYwg7IKs7Jqp7ZWY64qUIOq4sOuzuCDtlajsiJjsnoXri4jri6QuXG4gKi9cbmZ1bmN0aW9uIGRlZmF1bHRLZXlHZW5lcmF0b3IoZmlsZTogeyBmaWxlbmFtZTogc3RyaW5nOyBtaW1ldHlwZTogc3RyaW5nIH0pOiBzdHJpbmcge1xuICBjb25zdCBleHQgPSBtaW1lLmV4dGVuc2lvbihmaWxlLm1pbWV0eXBlKSB8fCBcImJpblwiO1xuICBjb25zdCB0aW1lc3RhbXAgPSBEYXRlLm5vdygpO1xuICBjb25zdCByYW5kb20gPSBNYXRoLnJhbmRvbSgpLnRvU3RyaW5nKDM2KS5zbGljZSgyLCA4KTtcbiAgcmV0dXJuIGB1cGxvYWRzLyR7dGltZXN0YW1wfS0ke3JhbmRvbX0uJHtleHR9YDtcbn1cblxuZnVuY3Rpb24gZm9ybWF0VGltZShtczogbnVtYmVyKTogc3RyaW5nIHtcbiAgY29uc3QgZm9ybWF0dGVkID0gbXMgPj0gMTAwMCA/IGAkeyhtcyAvIDEwMDApLnRvRml4ZWQoMil9c2AgOiBgJHtNYXRoLnJvdW5kKG1zKX1tc2A7XG4gIHJldHVybiBgICgke2Zvcm1hdHRlZH0pYDtcbn1cblxuY29uc3QgTE9DQUxfSE9TVFMgPSBuZXcgU2V0KFtcImxvY2FsaG9zdFwiLCBcIjEyNy4wLjAuMVwiLCBcIjAuMC4wLjBcIiwgXCI6OjFcIl0pO1xuZnVuY3Rpb24gaXNMb2NhbEhvc3QoaG9zdDogc3RyaW5nKTogYm9vbGVhbiB7XG4gIHJldHVybiBMT0NBTF9IT1NUUy5oYXMoaG9zdCk7XG59XG4iXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBazhDQSxTQUFTLG9CQUFvQixNQUFzRDtDQUNqRixNQUFNLE1BQU0sS0FBSyxVQUFVLEtBQUssU0FBUyxJQUFJO0NBQzdDLE1BQU0sWUFBWSxLQUFLLEtBQUs7Q0FDNUIsTUFBTSxTQUFTLEtBQUssUUFBUSxDQUFDLFNBQVMsR0FBRyxDQUFDLE1BQU0sR0FBRyxFQUFFO0FBQ3JELFFBQU8sV0FBVyxVQUFVLEdBQUcsT0FBTyxHQUFHOztBQUczQyxTQUFTLFdBQVcsSUFBb0I7Q0FDdEMsTUFBTSxZQUFZLE1BQU0sTUFBTyxJQUFJLEtBQUssS0FBTSxRQUFRLEVBQUUsQ0FBQyxLQUFLLEdBQUcsS0FBSyxNQUFNLEdBQUcsQ0FBQztBQUNoRixRQUFPLEtBQUssVUFBVTs7QUFJeEIsU0FBUyxZQUFZLE1BQXVCO0FBQzFDLFFBQU8sWUFBWSxJQUFJLEtBQUs7Ozs7NEJBbDhDcUM7cUJBQ2M7Z0JBR2xCO1VBRTNCO1VBRVM7cUJBRW1CO3FCQUNSO3FCQUdBO1dBQ0g7a0JBS0E7Z0JBQ0U7YUFFaUI7Y0FJbEM7Q0FHaEMsY0FBTixNQUFrQjtFQUNoQixBQUFPLGdCQUF5QjtFQUNoQyxBQUFPLGFBQXNCO0VBQzdCLEFBQU8sb0JBRUYsSUFBSSxtQkFBbUI7RUFFNUIsQUFBTyxhQUFzQjtHQUMzQixNQUFNLFFBQVEsS0FBSyxrQkFBa0IsVUFBVTtBQUMvQyxPQUFJLE9BQU8sU0FBUztBQUNsQixXQUFPLE1BQU07O0FBR2YsT0FBSSxRQUFRLElB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
1350
+ export { Sonamu, createWebSocketReplyStub, init_sonamu, resolveWebSocketCloseDescriptor, resolveWebSocketPluginOptions };
1351
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic29uYW11LmpzIiwibmFtZXMiOlsiREIiLCJhdXRoT3B0aW9uczogQmV0dGVyQXV0aE9wdGlvbnMiLCJnbG9iYWxDb21wcmVzc09wdGlvbnM6IENvbXByZXNzT3B0aW9ucyB8IHVuZGVmaW5lZCIsImZzIiwiY2hhbGsiLCJjYWNoZVJlcTogQ2FjaGVDb250cm9sUmVxdWVzdCIsImZpbGVQYXRoIiwiY3NyQ2FjaGVSZXE6IENhY2hlQ29udHJvbFJlcXVlc3QiLCJtaW1lTG9va3VwIiwiY29udGV4dDogQ29udGV4dCIsInJlcUJvZHk6IHtcbiAgICAgICAgICBba2V5OiBzdHJpbmddOiB1bmtub3duO1xuICAgICAgICB9IiwiZmlsZXM6IHtcbiAgICAgICAgICBidWZmZXJlZEZpbGVzOiBCdWZmZXJlZEZpbGVbXTtcbiAgICAgICAgICB1cGxvYWRlZEZpbGVzOiBVcGxvYWRlZEZpbGVbXTtcbiAgICAgICAgfSIsImZpZWxkczogUmVjb3JkPHN0cmluZywgc3RyaW5nPiIsImtleUdlbmVyYXRvcjogS2V5R2VuZXJhdG9yIiwid3NDb250ZXh0OiBXZWJTb2NrZXRDb250ZXh0IHwgbnVsbCIsInJhd1dzOiBSZXR1cm5UeXBlPFdlYlNvY2tldFJ1bnRpbWVbXCJyZWdpc3RlckNvbm5lY3Rpb25cIl0+IHwgbnVsbCIsInBhcmFtczogUmVjb3JkPHN0cmluZywgc3RyaW5nPiIsImxvZ3RhcGVEaXNwb3NlIl0sInNvdXJjZXMiOlsiLi4vLi4vc3JjL2FwaS9zb25hbXUudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQXN5bmNMb2NhbFN0b3JhZ2UgfSBmcm9tIFwiYXN5bmNfaG9va3NcIjtcbmltcG9ydCBmcyBmcm9tIFwiZnMvcHJvbWlzZXNcIjtcbmltcG9ydCB7IHR5cGUgSW5jb21pbmdNZXNzYWdlLCB0eXBlIFNlcnZlciwgdHlwZSBTZXJ2ZXJSZXNwb25zZSB9IGZyb20gXCJodHRwXCI7XG5pbXBvcnQgb3MgZnJvbSBcIm9zXCI7XG5pbXBvcnQgcGF0aCBmcm9tIFwicGF0aFwiO1xuXG5pbXBvcnQgdHlwZSB7fSBmcm9tIFwiQGZhc3RpZnkvd2Vic29ja2V0XCI7XG5pbXBvcnQgeyBkaXNwb3NlIGFzIGxvZ3RhcGVEaXNwb3NlIH0gZnJvbSBcIkBsb2d0YXBlL2xvZ3RhcGVcIjtcbmltcG9ydCB7IHR5cGUgQXV0aCwgdHlwZSBCZXR0ZXJBdXRoT3B0aW9ucyB9IGZyb20gXCJiZXR0ZXItYXV0aFwiO1xuaW1wb3J0IGNoYWxrIGZyb20gXCJjaGFsa1wiO1xuaW1wb3J0IHsgdHlwZSBGU1dhdGNoZXIgfSBmcm9tIFwiY2hva2lkYXJcIjtcbmltcG9ydCB7IHR5cGUgRmFzdGlmeUluc3RhbmNlLCB0eXBlIEZhc3RpZnlSZXBseSwgdHlwZSBGYXN0aWZ5UmVxdWVzdCB9IGZyb20gXCJmYXN0aWZ5XCI7XG5pbXBvcnQgbWltZSwgeyBsb29rdXAgYXMgbWltZUxvb2t1cCB9IGZyb20gXCJtaW1lLXR5cGVzXCI7XG5pbXBvcnQgeyB0eXBlIFdlYlNvY2tldCB9IGZyb20gXCJ3c1wiO1xuaW1wb3J0IHsgdHlwZSBab2RPYmplY3QgfSBmcm9tIFwiem9kXCI7XG5cbmltcG9ydCB7IEJBU0VfRklFTERfTUFQUElOR1MgfSBmcm9tIFwiLi4vYXV0aC9iZXR0ZXItYXV0aC1lbnRpdGllc1wiO1xuaW1wb3J0IHsgYXBwbHlDYWNoZUhlYWRlcnMsIENhY2hlUHJlc2V0cyB9IGZyb20gXCIuLi9jYWNoZS1jb250cm9sL2NhY2hlLWNvbnRyb2xcIjtcbmltcG9ydCB7IHR5cGUgQ2FjaGVDb250cm9sQ29uZmlnLCB0eXBlIENhY2hlQ29udHJvbFJlcXVlc3QgfSBmcm9tIFwiLi4vY2FjaGUtY29udHJvbC90eXBlc1wiO1xuaW1wb3J0IHsgdHlwZSBDYWNoZUNvbmZpZywgdHlwZSBDYWNoZU1hbmFnZXIgfSBmcm9tIFwiLi4vY2FjaGUvdHlwZXNcIjtcbmltcG9ydCB7IHRvRmFzdGlmeUNvbXByZXNzT3B0aW9uIH0gZnJvbSBcIi4uL2NvbXByZXNzL2NvbXByZXNzXCI7XG5pbXBvcnQgeyB0eXBlIENvbXByZXNzT3B0aW9ucyB9IGZyb20gXCIuLi9jb21wcmVzcy90eXBlc1wiO1xuaW1wb3J0IHsgREIgfSBmcm9tIFwiLi4vZGF0YWJhc2UvZGJcIjtcbmltcG9ydCB7IHR5cGUgU29uYW11REJDb25maWcgfSBmcm9tIFwiLi4vZGF0YWJhc2UvZGJcIjtcbmltcG9ydCB7IFNELCBzZXRTRENvbmZpZyB9IGZyb20gXCIuLi9kaWN0L3NkXCI7XG5pbXBvcnQgeyB0eXBlIExvY2FsaXplZFN0cmluZyB9IGZyb20gXCIuLi9kaWN0L3R5cGVzXCI7XG5pbXBvcnQgeyBOb3RGb3VuZEV4Y2VwdGlvbiB9IGZyb20gXCIuLi9leGNlcHRpb25zL3NvLWV4Y2VwdGlvbnNcIjtcbmltcG9ydCB7IEJ1ZmZlcmVkRmlsZSB9IGZyb20gXCIuLi9zdG9yYWdlL2J1ZmZlcmVkLWZpbGVcIjtcbmltcG9ydCB7IHR5cGUgU3RvcmFnZU1hbmFnZXIgfSBmcm9tIFwiLi4vc3RvcmFnZS9zdG9yYWdlLW1hbmFnZXJcIjtcbmltcG9ydCB7IHR5cGUgS2V5R2VuZXJhdG9yIH0gZnJvbSBcIi4uL3N0b3JhZ2UvdHlwZXNcIjtcbmltcG9ydCB7IFVwbG9hZGVkRmlsZSB9IGZyb20gXCIuLi9zdG9yYWdlL3VwbG9hZGVkLWZpbGVcIjtcbmltcG9ydCB7IGNyZWF0ZU1vY2tTU0VGYWN0b3J5IH0gZnJvbSBcIi4uL3N0cmVhbS9zc2VcIjtcbmltcG9ydCB7IFdlYlNvY2tldFJ1bnRpbWUsIHR5cGUgV2ViU29ja2V0Q29ubmVjdGlvbiwgdHlwZSBXZWJTb2NrZXRFdmVudE1hcCB9IGZyb20gXCIuLi9zdHJlYW0vd3NcIjtcbmltcG9ydCB7IHR5cGUgU3luY2VyIH0gZnJvbSBcIi4uL3N5bmNlci9zeW5jZXJcIjtcbmltcG9ydCB7IHR5cGUgV29ya2Zsb3dNYW5hZ2VyIH0gZnJvbSBcIi4uL3Rhc2tzL3dvcmtmbG93LW1hbmFnZXJcIjtcbmltcG9ydCB7IHR5cGUgRGV2Vml0ZXN0TWFuYWdlciB9IGZyb20gXCIuLi90ZXN0aW5nL2Rldi12aXRlc3QtbWFuYWdlclwiO1xuaW1wb3J0IHsgdHlwZSBTb25hbXVGYXN0aWZ5Q29uZmlnIH0gZnJvbSBcIi4uL3R5cGVzL3R5cGVzXCI7XG5pbXBvcnQgeyBjZW50ZXJUZXh0IH0gZnJvbSBcIi4uL3V0aWxzL2NvbnNvbGUtdXRpbFwiO1xuaW1wb3J0IHsgaXNEYWVtb25TZXJ2ZXIgfSBmcm9tIFwiLi4vdXRpbHMvY29udHJvbGxlclwiO1xuaW1wb3J0IHsgZXhpc3RzLCBmaWxlRXhpc3RzIH0gZnJvbSBcIi4uL3V0aWxzL2ZzLXV0aWxzXCI7XG5pbXBvcnQgeyB0eXBlIEFic29sdXRlUGF0aCB9IGZyb20gXCIuLi91dGlscy9wYXRoLXV0aWxzXCI7XG5pbXBvcnQgeyBjb252ZXJ0RmFzdGlmeUhlYWRlcnNUb1N0YW5kYXJkLCBtZXJnZSB9IGZyb20gXCIuLi91dGlscy91dGlsc1wiO1xuaW1wb3J0IHsgdHlwZSBTb25hbXVDb25maWcsIHR5cGUgU29uYW11U2VydmVyT3B0aW9ucywgdHlwZSBTb25hbXVUYXNrT3B0aW9ucyB9IGZyb20gXCIuL2NvbmZpZ1wiO1xuaW1wb3J0IHsgdHlwZSBDb250ZXh0LCB0eXBlIFJ1bnRpbWVDb250ZXh0LCB0eXBlIFdlYlNvY2tldENvbnRleHQgfSBmcm9tIFwiLi9jb250ZXh0XCI7XG5pbXBvcnQgeyB0eXBlIEV4dGVuZGVkQXBpIH0gZnJvbSBcIi4vZGVjb3JhdG9yc1wiO1xuaW1wb3J0IHsgZ2V0U2VjcmV0cyB9IGZyb20gXCIuL3NlY3JldFwiO1xuaW1wb3J0IHsgdHlwZSBTb25hbXVTZWNyZXRzIH0gZnJvbSBcIi4vc2VjcmV0XCI7XG5pbXBvcnQge1xuICBjcmVhdGVXZWJTb2NrZXRSZXBseVN0dWIsXG4gIHJlc29sdmVXZWJTb2NrZXRDbG9zZURlc2NyaXB0b3IsXG4gIHJlc29sdmVXZWJTb2NrZXRQbHVnaW5PcHRpb25zLFxuICByZXNvbHZlSW50ZWdyYXRlZFZpdGVIbXJPcHRpb25zLFxufSBmcm9tIFwiLi93ZWJzb2NrZXQtaGVscGVyc1wiO1xuXG5leHBvcnQge1xuICBjcmVhdGVXZWJTb2NrZXRSZXBseVN0dWIsXG4gIHJlc29sdmVXZWJTb2NrZXRDbG9zZURlc2NyaXB0b3IsXG4gIHJlc29sdmVXZWJTb2NrZXRQbHVnaW5PcHRpb25zLFxufSBmcm9tIFwiLi93ZWJzb2NrZXQtaGVscGVyc1wiO1xuXG5jbGFzcyBTb25hbXVDbGFzcyB7XG4gIHB1YmxpYyBpc0luaXRpYWxpemVkOiBib29sZWFuID0gZmFsc2U7XG4gIHB1YmxpYyBmb3JUZXN0aW5nOiBib29sZWFuID0gZmFsc2U7XG4gIHB1YmxpYyBhc3luY0xvY2FsU3RvcmFnZTogQXN5bmNMb2NhbFN0b3JhZ2U8e1xuICAgIGNvbnRleHQ6IFJ1bnRpbWVDb250ZXh0O1xuICB9PiA9IG5ldyBBc3luY0xvY2FsU3RvcmFnZSgpO1xuXG4gIHB1YmxpYyBnZXRDb250ZXh0PFQgZXh0ZW5kcyBSdW50aW1lQ29udGV4dCA9IENvbnRleHQ+KCk6IFQge1xuICAgIGNvbnN0IHN0b3JlID0gdGhpcy5hc3luY0xvY2FsU3RvcmFnZS5nZXRTdG9yZSgpO1xuICAgIGlmIChzdG9yZT8uY29udGV4dCkge1xuICAgICAgcmV0dXJuIHN0b3JlLmNvbnRleHQgYXMgVDtcbiAgICB9XG5cbiAgICBpZiAocHJvY2Vzcy5lbnYuTk9ERV9FTlYgPT09IFwidGVzdFwiKSB7XG4gICAgICAvLyDthYzsiqTtjIUg7ZmY6rK97JeQ7IScIOy7qO2FjeyKpO2KuOqwgCDso7zsnoXrkJjsp4Ag7JWK7J2AIOqyveyasCDruYgg7Luo7YWN7Iqk7Yq4IOumrO2EtFxuICAgICAgcmV0dXJuIHtcbiAgICAgICAgdHJhbnNwb3J0OiBcImh0dHBcIixcbiAgICAgICAgcmVxdWVzdDogbnVsbCxcbiAgICAgICAgcmVwbHk6IG51bGwsXG4gICAgICAgIGhlYWRlcnM6IHt9LFxuICAgICAgICBjcmVhdGVTU0U6IChzY2hlbWE6IFpvZE9iamVjdCkgPT4gY3JlYXRlTW9ja1NTRUZhY3Rvcnkoc2NoZW1hKSxcbiAgICAgICAgbG9jYWxlOiBcIlwiLFxuICAgICAgICB1c2VyOiBudWxsLFxuICAgICAgICBzZXNzaW9uOiBudWxsLFxuICAgICAgICBuYWl0ZVN0b3JlOiBuZXcgTWFwPHN0cmluZywgYW55PigpLFxuICAgICAgfSBhcyB1bmtub3duIGFzIFQ7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIlNvbmFtdSBjYW5ub3QgZmluZCBjb250ZXh0XCIpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgX2FwaVJvb3RQYXRoOiBBYnNvbHV0ZVBhdGggfCBudWxsID0gbnVsbDtcbiAgc2V0IGFwaVJvb3RQYXRoKGFwaVJvb3RQYXRoOiBBYnNvbHV0ZVBhdGgpIHtcbiAgICB0aGlzLl9hcGlSb290UGF0aCA9IGFwaVJvb3RQYXRoO1xuICB9XG4gIGdldCBhcGlSb290UGF0aCgpOiBBYnNvbHV0ZVBhdGgge1xuICAgIGlmICh0aGlzLl9hcGlSb290UGF0aCA9PT0gbnVsbCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiU29uYW11IGhhcyBub3QgYmVlbiBpbml0aWFsaXplZFwiKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuX2FwaVJvb3RQYXRoO1xuICB9XG4gIGdldCBhcHBSb290UGF0aCgpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLmFwaVJvb3RQYXRoLnNwbGl0KHBhdGguc2VwKS5zbGljZSgwLCAtMSkuam9pbihwYXRoLnNlcCk7XG4gIH1cblxuICBwcml2YXRlIF9kYkNvbmZpZzogU29uYW11REJDb25maWcgfCBudWxsID0gbnVsbDtcbiAgc2V0IGRiQ29uZmlnKGRiQ29uZmlnOiBTb25hbXVEQkNvbmZpZykge1xuICAgIHRoaXMuX2RiQ29uZmlnID0gZGJDb25maWc7XG4gIH1cbiAgZ2V0IGRiQ29uZmlnKCk6IFNvbmFtdURCQ29uZmlnIHtcbiAgICBpZiAodGhpcy5fZGJDb25maWcgPT09IG51bGwpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIlNvbmFtdSBoYXMgbm90IGJlZW4gaW5pdGlhbGl6ZWRcIik7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLl9kYkNvbmZpZztcbiAgfVxuXG4gIHByaXZhdGUgX3N5bmNlcjogU3luY2VyIHwgbnVsbCA9IG51bGw7XG4gIHNldCBzeW5jZXIoc3luY2VyOiBTeW5jZXIpIHtcbiAgICB0aGlzLl9zeW5jZXIgPSBzeW5jZXI7XG4gIH1cbiAgZ2V0IHN5bmNlcigpOiBTeW5jZXIge1xuICAgIGlmICh0aGlzLl9zeW5jZXIgPT09IG51bGwpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIlNvbmFtdSBoYXMgbm90IGJlZW4gaW5pdGlhbGl6ZWRcIik7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLl9zeW5jZXI7XG4gIH1cblxuICBwcml2YXRlIF9jb25maWc6IFNvbmFtdUNvbmZpZyB8IG51bGwgPSBudWxsO1xuICBzZXQgY29uZmlnKGNvbmZpZzogU29uYW11Q29uZmlnKSB7XG4gICAgdGhpcy5fY29uZmlnID0gY29uZmlnO1xuICB9XG4gIGdldCBjb25maWcoKTogU29uYW11Q29uZmlnIHtcbiAgICBpZiAodGhpcy5fY29uZmlnID09PSBudWxsKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJTb25hbXUgaGFzIG5vdCBiZWVuIGluaXRpYWxpemVkXCIpO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5fY29uZmlnO1xuICB9XG5cbiAgcHVibGljIHJlYWRvbmx5IHNlY3JldHM6IFNvbmFtdVNlY3JldHMgPSBnZXRTZWNyZXRzKCk7XG5cbiAgcHJpdmF0ZSBfc3RvcmFnZTogU3RvcmFnZU1hbmFnZXIgfCBudWxsID0gbnVsbDtcbiAgLyoqXG4gICAqIFN0b3JhZ2VNYW5hZ2VyIOyduOyKpO2EtOyKpFxuICAgKi9cbiAgZ2V0IHN0b3JhZ2UoKTogU3RvcmFnZU1hbmFnZXIge1xuICAgIGlmICghdGhpcy5fc3RvcmFnZSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiU3RvcmFnZSBoYXMgbm90IGJlZW4gaW5pdGlhbGl6ZWQuIENoZWNrIHN0b3JhZ2UgY29uZmlnLlwiKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuX3N0b3JhZ2U7XG4gIH1cblxuICBwcml2YXRlIF9jYWNoZTogQ2FjaGVNYW5hZ2VyIHwgbnVsbCA9IG51bGw7XG4gIC8qKlxuICAgKiBDYWNoZU1hbmFnZXIg7J247Iqk7YS07IqkIChCZW50b0NhY2hlKVxuICAgKi9cbiAgZ2V0IGNhY2hlKCk6IENhY2hlTWFuYWdlciB7XG4gICAgaWYgKCF0aGlzLl9jYWNoZSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiQ2FjaGUgaGFzIG5vdCBiZWVuIGluaXRpYWxpemVkLiBDaGVjayBjYWNoZSBjb25maWcgaW4gc29uYW11LmNvbmZpZy50cy5cIik7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLl9jYWNoZTtcbiAgfVxuXG4gIHByaXZhdGUgX3dvcmtmbG93czogV29ya2Zsb3dNYW5hZ2VyIHwgbnVsbCA9IG51bGw7XG4gIGdldCB3b3JrZmxvd3MoKTogV29ya2Zsb3dNYW5hZ2VyIHtcbiAgICBpZiAodGhpcy5fd29ya2Zsb3dzID09PSBudWxsKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJTb25hbXUgaGFzIG5vdCBiZWVuIGluaXRpYWxpemVkXCIpO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzLl93b3JrZmxvd3M7XG4gIH1cblxuICBwcml2YXRlIF9hdXRoOiBBdXRoPEJldHRlckF1dGhPcHRpb25zPiB8IG51bGwgPSBudWxsO1xuICBnZXQgYXV0aCgpOiBBdXRoPEJldHRlckF1dGhPcHRpb25zPiB7XG4gICAgaWYgKCF0aGlzLl9hdXRoKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJBdXRoIGhhcyBub3QgYmVlbiBpbml0aWFsaXplZC4gQ2hlY2sgYXV0aCBjb25maWcgaW4gc29uYW11LmNvbmZpZy50cy5cIik7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLl9hdXRoO1xuICB9XG5cbiAgcHJpdmF0ZSBfZGV2Vml0ZXN0TWFuYWdlcjogRGV2Vml0ZXN0TWFuYWdlciB8IG51bGwgPSBudWxsO1xuICBnZXQgZGV2Vml0ZXN0TWFuYWdlcigpOiBEZXZWaXRlc3RNYW5hZ2VyIHwgbnVsbCB7XG4gICAgcmV0dXJuIHRoaXMuX2RldlZpdGVzdE1hbmFnZXI7XG4gIH1cbiAgc2V0IGRldlZpdGVzdE1hbmFnZXIobWFuYWdlcjogRGV2Vml0ZXN0TWFuYWdlciB8IG51bGwpIHtcbiAgICB0aGlzLl9kZXZWaXRlc3RNYW5hZ2VyID0gbWFuYWdlcjtcbiAgfVxuXG4gIC8vIFNvbmFtdeqwgCBydW50aW1l7J2EIOyngeygkSDshozsnKDtlbQgcmVnaXN0cnkvY29ubmVjdGlvbiBsaWZlY3ljbGXsnYQg7JWg7ZSM66as7LyA7J207IWYIOyImOuqheyjvOq4sOyZgCDrj5nquLDtmZTtlahcbiAgcHJpdmF0ZSBfd2Vic29ja2V0UnVudGltZTogV2ViU29ja2V0UnVudGltZSB8IG51bGwgPSBudWxsO1xuICAvLyDqsJnsnYAgRmFzdGlmeSDsnbjsiqTthLTsiqTsl5AgQGZhc3RpZnkvd2Vic29ja2V07J2EIOykkeuztSDrk7HroZ3tlZjripQg6rKD7J2EIFdlYWtTZXTsnLzroZwg7LCo64uo7ZWoXG4gIHByaXZhdGUgcmVhZG9ubHkgd2Vic29ja2V0UGx1Z2luU2VydmVycyA9IG5ldyBXZWFrU2V0PFxuICAgIEZhc3RpZnlJbnN0YW5jZTxTZXJ2ZXIsIEluY29taW5nTWVzc2FnZSwgU2VydmVyUmVzcG9uc2U+XG4gID4oKTtcbiAgZ2V0IHdlYnNvY2tldFJ1bnRpbWUoKTogV2ViU29ja2V0UnVudGltZSB7XG4gICAgaWYgKCF0aGlzLl93ZWJzb2NrZXRSdW50aW1lKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJXZWJTb2NrZXQgcnVudGltZSBoYXMgbm90IGJlZW4gaW5pdGlhbGl6ZWQuXCIpO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5fd2Vic29ja2V0UnVudGltZTtcbiAgfVxuICBzZXQgd2Vic29ja2V0UnVudGltZShydW50aW1lOiBXZWJTb2NrZXRSdW50aW1lIHwgbnVsbCkge1xuICAgIHRoaXMuX3dlYnNvY2tldFJ1bnRpbWUgPSBydW50aW1lO1xuICB9XG5cbiAgLy8gSE1SIOyymOumrDog7YyM7J28IOyLnOyKpO2FnCDqsJDsi5wgKyBITVIvc3luYyDsgqzsnbTtgbQg7Iuk7ZaJ7J2AIHdhdGNoZXIg66qo65OI66GcIOychOyehO2VqeuLiOuLpC5cbiAgcHVibGljIHdhdGNoZXI6IEZTV2F0Y2hlciB8IG51bGwgPSBudWxsO1xuXG4gIHB1YmxpYyBzZXJ2ZXI6IEZhc3RpZnlJbnN0YW5jZSB8IG51bGwgPSBudWxsO1xuXG4gIGFzeW5jIGluaXRGb3JUZXN0aW5nKCkge1xuICAgIGF3YWl0IHRoaXMuaW5pdCh0cnVlLCBmYWxzZSwgdW5kZWZpbmVkLCB0cnVlKTtcbiAgfVxuXG4gIGFzeW5jIGluaXQoXG4gICAgZG9TaWxlbnQ6IGJvb2xlYW4gPSBmYWxzZSxcbiAgICBlbmFibGVTeW5jOiBib29sZWFuID0gdHJ1ZSxcbiAgICBhcGlSb290UGF0aD86IEFic29sdXRlUGF0aCxcbiAgICBmb3JUZXN0aW5nOiBib29sZWFuID0gZmFsc2UsXG4gICkge1xuICAgIHRoaXMuZm9yVGVzdGluZyA9IGZvclRlc3Rpbmc7XG5cbiAgICBpZiAodGhpcy5pc0luaXRpYWxpemVkKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgaW5pdFN0YXJ0ID0gcGVyZm9ybWFuY2Uubm93KCk7XG5cbiAgICAvLyBBUEkg66Oo7Yq4IO2MqOyKpFxuICAgIGNvbnN0IHsgZmluZEFwaVJvb3RQYXRoIH0gPSBhd2FpdCBpbXBvcnQoXCIuLi91dGlscy91dGlsc1wiKTtcbiAgICB0aGlzLmFwaVJvb3RQYXRoID0gYXBpUm9vdFBhdGggPz8gZmluZEFwaVJvb3RQYXRoKCk7XG5cbiAgICAvLyDshKTsoJXsnYQg66Gc65Sp7ZWY64qUIOqyg+u2gO2EsCDsi5zsnpFcbiAgICBjb25zdCBjb25maWdTdGFydCA9IHBlcmZvcm1hbmNlLm5vdygpO1xuICAgIGNvbnN0IHsgbG9hZENvbmZpZyB9ID0gYXdhaXQgaW1wb3J0KFwiLi9jb25maWdcIik7XG4gICAgdGhpcy5jb25maWcgPSBhd2FpdCBsb2FkQ29uZmlnKHRoaXMuYXBpUm9vdFBhdGgpO1xuICAgIGNvbnN0IGNvbmZpZ1RpbWUgPSBwZXJmb3JtYW5jZS5ub3coKSAtIGNvbmZpZ1N0YXJ0O1xuICAgIHNldFNEQ29uZmlnKHRoaXMuY29uZmlnLmkxOG4pO1xuICAgIC8vIHNvbmFtdS5jb25maWcudHMg6riw67O46rCSIOyEpOyglVxuICAgIHRoaXMuY29uZmlnLmRhdGFiYXNlLmRhdGFiYXNlID0gdGhpcy5jb25maWcuZGF0YWJhc2UuZGF0YWJhc2UgPz8gXCJwZ1wiO1xuICAgIHRoaXMuY29uZmlnLmRhdGFiYXNlLmRlZmF1bHRPcHRpb25zLmNsaWVudCA9IHRoaXMuY29uZmlnLmRhdGFiYXNlLmRhdGFiYXNlID8/IFwicGdcIjtcblxuICAgIC8vIOuhnOq5hSDshKTsoJVcbiAgICBjb25zdCB7IGNvbmZpZ3VyZUxvZ1RhcGUgfSA9IGF3YWl0IGltcG9ydChcIi4uL2xvZ2dlci9jb25maWd1cmVcIik7XG4gICAgaWYgKHRoaXMuY29uZmlnLmxvZ2dpbmcgIT09IGZhbHNlKSB7XG4gICAgICBhd2FpdCBjb25maWd1cmVMb2dUYXBlKHtcbiAgICAgICAgLi4udGhpcy5jb25maWcubG9nZ2luZyxcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIC8vIERCIOuhnOuTnFxuICAgIGNvbnN0IHsgREIgfSA9IGF3YWl0IGltcG9ydChcIi4uL2RhdGFiYXNlL2RiXCIpO1xuICAgIHRoaXMuZGJDb25maWcgPSBEQi5nZW5lcmF0ZURCQ29uZmlnKHRoaXMuY29uZmlnLmRhdGFiYXNlKTtcbiAgICBEQi5zZXRDb25maWcodGhpcy5kYkNvbmZpZyk7XG5cbiAgICAvLyBFbnRpdHkg66Gc65OcXG4gICAgLy8g7YWM7Iqk7Yq47JeQ7ISc64+EIEVudGl0eSDsoJXrs7TripQg7ZWE7JqU7ZWp64uI64ukLlxuICAgIC8vIHVwc2VydOqwgCDsoJzrjIDroZwg7J6R64+Z7ZWY66Ck66m0IGVudGl0eeydmCB1bmlxdWUgaW5kZXgg7KCV67O06rCAIO2VhOyalO2VmOq4sCDrlYzrrLjsnoXri4jri6QuXG4gICAgY29uc3QgeyBFbnRpdHlNYW5hZ2VyIH0gPSBhd2FpdCBpbXBvcnQoXCIuLi9lbnRpdHkvZW50aXR5LW1hbmFnZXJcIik7XG4gICAgYXdhaXQgRW50aXR5TWFuYWdlci5hdXRvbG9hZChkb1NpbGVudCk7XG5cbiAgICAvLyBDYWNoZSDstIjquLDtmZRcbiAgICBhd2FpdCB0aGlzLmluaXRpYWxpemVDYWNoZSh0aGlzLmNvbmZpZy5zZXJ2ZXIuY2FjaGUsIGZvclRlc3RpbmcpO1xuXG4gICAgLy8gQmV0dGVyQXV0aCDstIjquLDtmZRcbiAgICBjb25zdCBhdXRoQ29uZmlnID0gdGhpcy5jb25maWcuc2VydmVyLmF1dGg7XG4gICAgaWYgKGF1dGhDb25maWcpIHtcbiAgICAgIC8vIOyCrOyaqeyekCDshKTsoJXqs7wg6riw67O46rCS7J2EIG1lcmdlXG4gICAgICBjb25zdCBtZXJnZWRGaWVsZE1hcHBpbmdzID0gbWVyZ2UoQkFTRV9GSUVMRF9NQVBQSU5HUywgYXV0aENvbmZpZyk7XG5cbiAgICAgIC8vIGJldHRlci1hdXRoIOyduOyKpO2EtOyKpCDsg53shLFcbiAgICAgIGNvbnN0IHsgYmV0dGVyQXV0aCB9ID0gYXdhaXQgaW1wb3J0KFwiYmV0dGVyLWF1dGhcIik7XG4gICAgICBjb25zdCB7IHNvbmFtdUtuZXhBZGFwdGVyIH0gPSBhd2FpdCBpbXBvcnQoXCIuLi9hdXRoL2tuZXgtYWRhcHRlclwiKTtcblxuICAgICAgY29uc3QgYXV0aE9wdGlvbnM6IEJldHRlckF1dGhPcHRpb25zID0ge1xuICAgICAgICBkYXRhYmFzZTogc29uYW11S25leEFkYXB0ZXIoKSxcbiAgICAgICAgLi4ubWVyZ2VkRmllbGRNYXBwaW5ncyxcbiAgICAgIH07XG4gICAgICB0aGlzLl9hdXRoID0gYmV0dGVyQXV0aChhdXRoT3B0aW9ucyk7XG4gICAgfVxuXG4gICAgLy8g7YWM7Iqk7YyF7J24IOqyveyasCDsi7Htgawg7JeG7J20IOykkeuLqFxuICAgIGlmIChmb3JUZXN0aW5nKSB7XG4gICAgICB0aGlzLmlzSW5pdGlhbGl6ZWQgPSB0cnVlO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIFRhc2sg65Ox66GdXG4gICAgYXdhaXQgdGhpcy5pbml0aWFsaXplV29ya2Zsb3dzKHRoaXMuY29uZmlnLnRhc2tzKTtcblxuICAgIC8vIFN5bmNlclxuICAgIGNvbnN0IHsgU3luY2VyIH0gPSBhd2FpdCBpbXBvcnQoXCIuLi9zeW5jZXIvc3luY2VyXCIpO1xuICAgIHRoaXMuc3luY2VyID0gbmV3IFN5bmNlcigpO1xuXG4gICAgLy8gQXV0b2xvYWQ6IE1vZGVscyAvIFR5cGVzIC8gQVBJcyAvIFdvcmtmbG93cyAvIFRlbXBsYXRlcyAvIFNTUiBSb3V0ZXNcbiAgICBhd2FpdCB0aGlzLnN5bmNlci5hdXRvbG9hZFR5cGVzKCk7XG4gICAgYXdhaXQgdGhpcy5zeW5jZXIuYXV0b2xvYWRNb2RlbHMoKTtcbiAgICBhd2FpdCB0aGlzLnN5bmNlci5hdXRvbG9hZEFwaXMoKTtcbiAgICBhd2FpdCB0aGlzLnN5bmNlci5hdXRvbG9hZFdvcmtmbG93cygpO1xuICAgIGNvbnN0IHsgVGVtcGxhdGVNYW5hZ2VyIH0gPSBhd2FpdCBpbXBvcnQoXCIuLi90ZW1wbGF0ZVwiKTtcbiAgICBhd2FpdCBUZW1wbGF0ZU1hbmFnZXIuYXV0b2xvYWQoKTtcbiAgICBhd2FpdCB0aGlzLnN5bmNlci5hdXRvbG9hZFNzclJvdXRlcygpO1xuXG4gICAgY29uc3QgeyBpc0xvY2FsLCBpc1Rlc3QsIGlzSG90UmVsb2FkU2VydmVyIH0gPSBhd2FpdCBpbXBvcnQoXCIuLi91dGlscy9jb250cm9sbGVyXCIpO1xuICAgIGlmIChpc0xvY2FsKCkgJiYgIWlzVGVzdCgpICYmIGlzSG90UmVsb2FkU2VydmVyKCkgJiYgZW5hYmxlU3luYykge1xuICAgICAgYXdhaXQgdGhpcy5zeW5jZXIuc3luYygpO1xuICAgICAgYXdhaXQgdGhpcy5zdGFydFdhdGNoZXIoKTtcbiAgICB9XG5cbiAgICB0aGlzLmlzSW5pdGlhbGl6ZWQgPSB0cnVlO1xuICAgIHRoaXMuX2luaXRFbGFwc2VkID0gcGVyZm9ybWFuY2Uubm93KCkgLSBpbml0U3RhcnQ7XG4gICAgdGhpcy5fY29uZmlnRWxhcHNlZCA9IGNvbmZpZ1RpbWU7XG4gIH1cblxuICBwcml2YXRlIF9pbml0RWxhcHNlZCA9IDA7XG4gIHByaXZhdGUgX2NvbmZpZ0VsYXBzZWQgPSAwO1xuXG4gIGFzeW5jIGNyZWF0ZVNlcnZlcihpbml0T3B0aW9ucz86IHsgZW5hYmxlU3luYz86IGJvb2xlYW47IGRvU2lsZW50PzogYm9vbGVhbiB9KSB7XG4gICAgaWYgKCF0aGlzLmlzSW5pdGlhbGl6ZWQpIHtcbiAgICAgIGF3YWl0IHRoaXMuaW5pdChpbml0T3B0aW9ucz8uZG9TaWxlbnQsIGluaXRPcHRpb25zPy5lbmFibGVTeW5jKTtcbiAgICB9XG5cbiAgICBjb25zdCBvcHRpb25zID0gdGhpcy5jb25maWcuc2VydmVyO1xuICAgIGNvbnN0IHsgZGVmYXVsdDogZmFzdGlmeSB9ID0gYXdhaXQgaW1wb3J0KFwiZmFzdGlmeVwiKTtcbiAgICBjb25zdCB7IGdldExvZ1RhcGVGYXN0aWZ5TG9nZ2VyIH0gPSBhd2FpdCBpbXBvcnQoXCJAbG9ndGFwZS9mYXN0aWZ5XCIpO1xuICAgIGNvbnN0IHNlcnZlciA9IGZhc3RpZnkoe1xuICAgICAgLi4ub3B0aW9ucy5mYXN0aWZ5LFxuICAgICAgbG9nZ2VyOlxuICAgICAgICB0aGlzLmNvbmZpZy5sb2dnaW5nICE9PSBmYWxzZVxuICAgICAgICAgID8gZ2V0TG9nVGFwZUZhc3RpZnlMb2dnZXIoe1xuICAgICAgICAgICAgICBjYXRlZ29yeTogdGhpcy5jb25maWcubG9nZ2luZz8uZmFzdGlmeUNhdGVnb3J5ID8/IFtcImZhc3RpZnlcIl0sXG4gICAgICAgICAgICB9KVxuICAgICAgICAgIDogdW5kZWZpbmVkLFxuICAgIH0pO1xuICAgIHRoaXMuc2VydmVyID0gc2VydmVyO1xuICAgIHRoaXMud2Vic29ja2V0UnVudGltZSA9IG5ldyBXZWJTb2NrZXRSdW50aW1lKG9wdGlvbnMud2Vic29ja2V0KTtcblxuICAgIC8vIFN0b3JhZ2Ug7ISk7KCVIOKGkiBTdG9yYWdlTWFuYWdlciDsg53shLFcbiAgICBpZiAob3B0aW9ucy5zdG9yYWdlKSB7XG4gICAgICBjb25zdCB7IFN0b3JhZ2VNYW5hZ2VyIH0gPSBhd2FpdCBpbXBvcnQoXCIuLi9zdG9yYWdlL3N0b3JhZ2UtbWFuYWdlclwiKTtcbiAgICAgIHRoaXMuX3N0b3JhZ2UgPSBuZXcgU3RvcmFnZU1hbmFnZXIob3B0aW9ucy5zdG9yYWdlKTtcbiAgICB9XG5cbiAgICAvLyDtlIzrn6zqt7jsnbgg65Ox66GdXG4gICAgaWYgKG9wdGlvbnMucGx1Z2lucykge1xuICAgICAgYXdhaXQgdGhpcy5yZWdpc3RlclBsdWdpbnMoc2VydmVyLCBvcHRpb25zLnBsdWdpbnMpO1xuICAgIH1cblxuICAgIGlmIChvcHRpb25zLmF1dGgpIHtcbiAgICAgIGF3YWl0IHRoaXMucmVnaXN0ZXJCZXR0ZXJBdXRoKHNlcnZlciwgb3B0aW9ucy5hdXRoKTtcbiAgICB9XG5cbiAgICAvLyBBUEkg65287Jqw7YyFIOyEpOyglVxuICAgIGF3YWl0IHRoaXMud2l0aEZhc3RpZnkoc2VydmVyLCBvcHRpb25zLmFwaUNvbmZpZywge1xuICAgICAgZW5hYmxlU3luYzogaW5pdE9wdGlvbnM/LmVuYWJsZVN5bmMsXG4gICAgICBkb1NpbGVudDogaW5pdE9wdGlvbnM/LmRvU2lsZW50LFxuICAgIH0pO1xuXG4gICAgLy8g7ISc67KEIOyLnOyekVxuICAgIGF3YWl0IHRoaXMuYm9vdChzZXJ2ZXIsIG9wdGlvbnMpO1xuXG4gICAgaWYgKCFpbml0T3B0aW9ucz8uZG9TaWxlbnQpIHtcbiAgICAgIHRoaXMucHJpbnRTdGFydHVwU3VtbWFyeSgpO1xuICAgIH1cblxuICAgIHJldHVybiBzZXJ2ZXI7XG4gIH1cblxuICBhc3luYyB3aXRoRmFzdGlmeShcbiAgICBzZXJ2ZXI6IEZhc3RpZnlJbnN0YW5jZTxTZXJ2ZXIsIEluY29taW5nTWVzc2FnZSwgU2VydmVyUmVzcG9uc2U+LFxuICAgIGNvbmZpZzogU29uYW11RmFzdGlmeUNvbmZpZyxcbiAgICBvcHRpb25zPzoge1xuICAgICAgZW5hYmxlU3luYz86IGJvb2xlYW47XG4gICAgICBkb1NpbGVudD86IGJvb2xlYW47XG4gICAgfSxcbiAgKSB7XG4gICAgaWYgKCF0aGlzLmlzSW5pdGlhbGl6ZWQpIHtcbiAgICAgIGF3YWl0IHRoaXMuaW5pdChvcHRpb25zPy5kb1NpbGVudCwgb3B0aW9ucz8uZW5hYmxlU3luYyk7XG4gICAgfVxuXG4gICAgdGhpcy5zZXJ2ZXIgPSBzZXJ2ZXI7XG4gICAgdGhpcy53ZWJzb2NrZXRSdW50aW1lID8/PSBuZXcgV2ViU29ja2V0UnVudGltZSh0aGlzLmNvbmZpZy5zZXJ2ZXIud2Vic29ja2V0KTtcblxuICAgIC8vIHRpbWV6b25lIOyEpOyglVxuICAgIGNvbnN0IHRpbWV6b25lID0gdGhpcy5jb25maWcuYXBpLnRpbWV6b25lO1xuICAgIGlmICh0aW1lem9uZSkge1xuICAgICAgLy8g7YOA7J6E7KG07JeQIOunnuqyjCDsnZHri7Ug64Kg7KecIOyKpO2KuOungeydhCDrs4DtmZjtlbTso7zslrTslbwg7ZWp64uI64ukLlxuICAgICAgLy8g6rCA66C5IHRpbWV6b25l7J20IFwiQXNpYS9TZW91bFwiIOydtOuptFxuICAgICAgLy8gXCIyMDI1LTExLTIxVDAwOjAwOjAwLjAwMFpcIiDrpbwgXCIyMDI1LTExLTIxVDA5OjAwOjAwKzA5OjAwXCIg7Jy866GcIOuzgO2ZmO2VtOyjvOyWtOyVvCDtlanri4jri6QuXG4gICAgICBjb25zdCB7IGZvcm1hdEluVGltZVpvbmUgfSA9IGF3YWl0IGltcG9ydChcImRhdGUtZm5zLXR6XCIpO1xuXG4gICAgICAvLyBJU08gODYwMSDrgqDsp5wg7ZiV7IudIOygleq3nOyLnSAo7JiIOiAyMDI0LTAxLTE1VDA5OjMwOjAwLjAwMFopXG4gICAgICBjb25zdCBJU09fREFURV9SRUdFWCA9IC9eXFxkezR9LVxcZHsyfS1cXGR7Mn1UXFxkezJ9OlxcZHsyfTpcXGR7Mn0oXFwuXFxkezN9KT9aJC87XG5cbiAgICAgIC8vIFTrpbwg65GY65+s7Iu8IOyekeydgOuUsOyYtO2RnOqwgCDsl4bri6TrqbQgXCIyMDI1LTExLTE5MTc2MzU0NjE4OTAwMDE4OjU2OjI5KzA5OjAwXCLsmYAg6rCZ7J2AIOqysOqzvOqwgCDrgpjsmLXri4jri6QuXG4gICAgICAvLyDsnbTripQgZGF0ZS1mbnMg7Yq57J6F64uI64ukLlxuICAgICAgLy8g7J2066CH6rKMIO2VtOuPhCDqtJzssK7sirXri4jri6QuIFwiMjAyNS0xMS0xOVQxODo1NjoyOSswOTowMFwiIOuqqOyWkeycvOuhnCDsnpgg64KY7Ji164uI64ukLlxuICAgICAgY29uc3QgREFURV9GT1JNQVQgPSBcInl5eXktTU0tZGQnVCdISDptbTpzc1hYWFwiO1xuXG4gICAgICBzZXJ2ZXIuc2V0UmVwbHlTZXJpYWxpemVyKChwYXlsb2FkKSA9PiB7XG4gICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeShwYXlsb2FkLCAoX2tleSwgdmFsdWUpID0+IHtcbiAgICAgICAgICBpZiAodHlwZW9mIHZhbHVlID09PSBcInN0cmluZ1wiICYmIElTT19EQVRFX1JFR0VYLnRlc3QodmFsdWUpKSB7XG4gICAgICAgICAgICByZXR1cm4gZm9ybWF0SW5UaW1lWm9uZShcbiAgICAgICAgICAgICAgbmV3IERhdGUodmFsdWUpLFxuICAgICAgICAgICAgICB0aW1lem9uZSBhcyBgJHtzdHJpbmd9LyR7c3RyaW5nfWAsXG4gICAgICAgICAgICAgIERBVEVfRk9STUFULFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgICAgICB9KTtcbiAgICAgIH0pO1xuICAgICAgLy8gVGltZXpvbmUg66Gc6re464qUIHByaW50U3RhcnR1cFN1bW1hcnnsl5DshJwg7Ya17ZWpIOy2nOugpVxuICAgIH1cblxuICAgIC8vIOyghOyytCDrnbzsmrDtjIUg66as7Iqk7Yq4XG4gICAgc2VydmVyLmdldChcbiAgICAgIGAke3RoaXMuY29uZmlnLmFwaS5yb3V0ZS5wcmVmaXh9L3JvdXRlc2AsXG4gICAgICBhc3luYyAoX3JlcXVlc3QsIF9yZXBseSk6IFByb21pc2U8dHlwZW9mIHRoaXMuc3luY2VyLmFwaXM+ID0+IHtcbiAgICAgICAgcmV0dXJuIHRoaXMuc3luY2VyLmFwaXM7XG4gICAgICB9LFxuICAgICk7XG5cbiAgICAvLyBIZWFsdGhjaGVjayBBUElcbiAgICBzZXJ2ZXIuZ2V0KFxuICAgICAgYCR7dGhpcy5jb25maWcuYXBpLnJvdXRlLnByZWZpeH0vaGVhbHRoY2hlY2tgLFxuICAgICAgYXN5bmMgKF9yZXF1ZXN0LCBfcmVwbHkpOiBQcm9taXNlPHN0cmluZz4gPT4ge1xuICAgICAgICByZXR1cm4gXCJva1wiO1xuICAgICAgfSxcbiAgICApO1xuXG4gICAgLy8gU29uYW11IFVJIEFQSSAo66Gc7LusIO2ZmOqyveyXkOyEnOunjClcbiAgICBjb25zdCB7IGlzTG9jYWwgfSA9IGF3YWl0IGltcG9ydChcIi4uL3V0aWxzL2NvbnRyb2xsZXJcIik7XG4gICAgaWYgKGlzTG9jYWwoKSkge1xuICAgICAgY29uc3QgeyBzb25hbXVVSUFwaVBsdWdpbiB9ID0gYXdhaXQgaW1wb3J0KFwiLi4vdWkvYXBpXCIpO1xuICAgICAgc2VydmVyLnJlZ2lzdGVyKHNvbmFtdVVJQXBpUGx1Z2luKTtcbiAgICB9XG5cbiAgICAvLyBEZXZSdW5uZXIg7YWM7Iqk7Yq4IOyXlOuTnO2PrOyduO2KuCAo66Gc7LusIO2ZmOqyvSArIGRldlJ1bm5lciDtmZzshLHtmZQg7IucKVxuICAgIGlmIChpc0xvY2FsKCkgJiYgdGhpcy5jb25maWcudGVzdD8uZGV2UnVubmVyPy5lbmFibGVkKSB7XG4gICAgICBjb25zdCB7IHJlZ2lzdGVyRGV2VGVzdFJvdXRlcyB9ID0gYXdhaXQgaW1wb3J0KFwiLi4vdGVzdGluZy9kZXYtdGVzdC1yb3V0ZXNcIik7XG4gICAgICBhd2FpdCByZWdpc3RlckRldlRlc3RSb3V0ZXMoc2VydmVyLCB0aGlzLmNvbmZpZy50ZXN0LmRldlJ1bm5lcik7XG4gICAgfVxuXG4gICAgY29uc3Qgd2ViUGF0aCA9IHBhdGguam9pbih0aGlzLmFwcFJvb3RQYXRoLCBcIndlYlwiKTtcbiAgICBjb25zdCBoYXNXZWIgPSBhd2FpdCBleGlzdHMod2ViUGF0aCk7XG5cbiAgICAvLyDsoITsl60gY29tcHJlc3Mg7Ji17IWYIOqzhOyCsCAocm91dGUuY29tcHJlc3M6IHRydWXsnbwg65WMIOyCrOyaqSlcbiAgICBjb25zdCBwbHVnaW5Db21wcmVzcyA9IHRoaXMuY29uZmlnLnNlcnZlci5wbHVnaW5zPy5jb21wcmVzcztcbiAgICBjb25zdCBnbG9iYWxDb21wcmVzc09wdGlvbnM6IENvbXByZXNzT3B0aW9ucyB8IHVuZGVmaW5lZCA9IHBsdWdpbkNvbXByZXNzXG4gICAgICA/IHBsdWdpbkNvbXByZXNzID09PSB0cnVlXG4gICAgICAgID8geyB0aHJlc2hvbGQ6IDEwMjQsIGVuY29kaW5nczogW1wiYnJcIiwgXCJnemlwXCIsIFwiZGVmbGF0ZVwiXSB9XG4gICAgICAgIDoge1xuICAgICAgICAgICAgdGhyZXNob2xkOiBwbHVnaW5Db21wcmVzcy50aHJlc2hvbGQsXG4gICAgICAgICAgICBlbmNvZGluZ3M6IHBsdWdpbkNvbXByZXNzLmVuY29kaW5ncyxcbiAgICAgICAgICAgIGN1c3RvbVR5cGVzOiBwbHVnaW5Db21wcmVzcy5jdXN0b21UeXBlcyxcbiAgICAgICAgICB9XG4gICAgICA6IHVuZGVmaW5lZDtcblxuICAgIGlmIChpc0xvY2FsKCkpIHtcbiAgICAgIC8vIOuhnOy7rCDqsJzrsJwg7ZmY6rK9OiBjYXRjaC1hbGzroZwgQVBJ66W8IOuPmeyggSDrp6Tsua3tlZjsl6wgSE1S7J2EIOyngOybkO2VqeuLiOuLpC5cbiAgICAgIC8vIFNPTkFNVV9ESVNBQkxFX0lOVEVHUkFURURfV0VCPXllc+uhnCDshKTsoJXtlZjrqbQgZGV2X2FwaSDrqqjrk5zsl5DshJwgVml0ZSDthrXtlansnYQg67mE7Zmc7ISx7ZmU7ZWgIOyImCDsnojsirXri4jri6QuXG4gICAgICBjb25zdCBkaXNhYmxlSW50ZWdyYXRlZFdlYiA9IHByb2Nlc3MuZW52LlNPTkFNVV9ESVNBQkxFX0lOVEVHUkFURURfV0VCID09PSBcInllc1wiO1xuICAgICAgaWYgKGhhc1dlYiAmJiAhZGlzYWJsZUludGVncmF0ZWRXZWIpIHtcbiAgICAgICAgYXdhaXQgdGhpcy5zZXR1cERldlNlcnZlcldpdGhWaXRlKHNlcnZlciwgd2ViUGF0aCwgY29uZmlnKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMuc2V0dXBEZXZTZXJ2ZXIoc2VydmVyLCBjb25maWcpO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAvLyDtlITroZzrjZXshZgg7ZmY6rK9OiDqsJzrs4QgQVBJIOudvOyasO2KuCArIOygleyggSDtjIzsnbwg7ISc67mZXG4gICAgICBmb3IgKGNvbnN0IGFwaSBvZiB0aGlzLnN5bmNlci5hcGlzKSB7XG4gICAgICAgIGlmICh0aGlzLnN5bmNlci5tb2RlbHNbYXBpLm1vZGVsTmFtZV0gPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihg7KCV7J2Y65CY7KeAIOyViuydgCDrqqjrjbjsl5Ag7KCR6re8ICR7YXBpLm1vZGVsTmFtZX1gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIEB3ZWJzb2NrZXQgcm91dGXripQgd3NIYW5kbGVy66GcIOuTseuhne2VmOqzoCwg6rCZ7J2AIHBhdGjsnZgg7J2867CYIEhUVFAgR0VU7J2AIDQyNiDsnZHri7XsnLzroZwgdXBncmFkZeulvCDqsJXsoJztlahcbiAgICAgICAgaWYgKGFwaS53ZWJzb2NrZXRPcHRpb25zKSB7XG4gICAgICAgICAgc2VydmVyLnJvdXRlKHtcbiAgICAgICAgICAgIG1ldGhvZDogXCJHRVRcIixcbiAgICAgICAgICAgIHVybDogdGhpcy5jb25maWcuYXBpLnJvdXRlLnByZWZpeCArIGFwaS5wYXRoLFxuICAgICAgICAgICAgaGFuZGxlcjogdGhpcy5jcmVhdGVXZWJTb2NrZXRVcGdyYWRlUmVxdWlyZWRIYW5kbGVyKCksXG4gICAgICAgICAgICB3c0hhbmRsZXI6IHRoaXMuY3JlYXRlV2ViU29ja2V0SGFuZGxlcihhcGksIGNvbmZpZyksXG4gICAgICAgICAgfSk7XG4gICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cblxuICAgICAgICBzZXJ2ZXIucm91dGUoe1xuICAgICAgICAgIG1ldGhvZDogYXBpLm9wdGlvbnMuaHR0cE1ldGhvZCA/PyBcIkdFVFwiLFxuICAgICAgICAgIHVybDogdGhpcy5jb25maWcuYXBpLnJvdXRlLnByZWZpeCArIGFwaS5wYXRoLFxuICAgICAgICAgIGhhbmRsZXI6IHRoaXMuY3JlYXRlQXBpSGFuZGxlcihhcGksIGNvbmZpZyksXG4gICAgICAgICAgY29tcHJlc3M6IHRvRmFzdGlmeUNvbXByZXNzT3B0aW9uKGFwaS5vcHRpb25zLmNvbXByZXNzLCBnbG9iYWxDb21wcmVzc09wdGlvbnMpLFxuICAgICAgICB9KTtcbiAgICAgIH1cblxuICAgICAgLy8g7ZSE66Gc642V7IWY7JeQ7ISc64qUIHdlYiDshozsiqQoYXBwUm9vdC93ZWIpIOycoOustOyZgCDrrLTqtIDtlZjqsowsXG4gICAgICAvLyBhcGkvd2ViLWRpc3Qg7KG07J6sIOyXrOu2gOulvCBzZXR1cFN0YXRpY1dlYlNlcnZlciDrgrTrtoDsl5DshJwg7YyQ64uo7ZWp64uI64ukLlxuICAgICAgYXdhaXQgdGhpcy5zZXR1cFN0YXRpY1dlYlNlcnZlcihzZXJ2ZXIsIGNvbmZpZywgZ2xvYmFsQ29tcHJlc3NPcHRpb25zKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogZGV2IOuqqOuTnCDqs7XthrU6IGNhdGNoLWFsbOyXkOyEnCBzeW5jZXIuYXBpc+ulvCDrj5nsoIHsnLzroZwg7YOQ7IOJ7ZWY7JesIEFQSSDsmpTssq3snYQg7LKY66as7ZWp64uI64ukLlxuICAgKiBzZXJ2ZXIucm91dGUoKeuhnCDqsJzrs4Qg65Ox66Gd7ZWY66m0IGhhbmRsZXLqsIAg6rOg7KCV65CY7Ja0IEhNUuydtCDrj5nsnpHtlZjsp4Ag7JWK7Jy866+A66GcLFxuICAgKiDrp6Qg7JqU7LKt66eI64ukIHN5bmNlci5hcGlz66W8IOyhsO2ajO2VmOuKlCDsnbQg67Cp7Iud7J2EIOyCrOyaqe2VqeuLiOuLpC5cbiAgICpcbiAgICog7JqU7LKt7J20IC9hcGko7KCV7ZmV7Z6I64qUIHRoaXMuY29uZmlnLmFwaS5yb3V0ZS5wcmVmaXgp66GcIOyLnOyeke2VmOyngCDslYrripQg6rK97Jqw652866m0IG51bGzsnYQg67CY7ZmY7ZWY66mwIOuBneuDheuLiOuLpC5cbiAgICovXG4gIHByaXZhdGUgaGFuZGxlRGV2QXBpUmVxdWVzdChcbiAgICByZXF1ZXN0OiBGYXN0aWZ5UmVxdWVzdCxcbiAgICBjb25maWc6IFNvbmFtdUZhc3RpZnlDb25maWcsXG4gICk6ICgocmVxdWVzdDogRmFzdGlmeVJlcXVlc3QsIHJlcGx5OiBGYXN0aWZ5UmVwbHkpID0+IFByb21pc2U8dW5rbm93bj4pIHwgbnVsbCB7XG4gICAgY29uc3QgbWF0Y2hlZEFwaSA9IHRoaXMuZmluZE1hdGNoZWRBcGkocmVxdWVzdCk7XG5cbiAgICBpZiAoIW1hdGNoZWRBcGkpIHtcbiAgICAgIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbihTRChcImVycm9yLmFwaS5ub3RGb3VuZFwiKSk7XG4gICAgfVxuXG4gICAgLy8gd2Vic29ja2V0IHJvdXRl66W8IOydvOuwmCBIVFRQ66GcIOyngeygkSDtmLjstpztlZwg6rK97JqwIDQyNuydhCDrj4zroKTspJggdXBncmFkZSDsl4bsnbQg7KCR6re87ZWY64qUIOqyg+ydhCDssKjri6jtlahcbiAgICBpZiAobWF0Y2hlZEFwaS53ZWJzb2NrZXRPcHRpb25zKSB7XG4gICAgICByZXR1cm4gdGhpcy5jcmVhdGVXZWJTb2NrZXRVcGdyYWRlUmVxdWlyZWRIYW5kbGVyKCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMuY3JlYXRlQXBpSGFuZGxlcihtYXRjaGVkQXBpLCBjb25maWcpO1xuICB9XG5cbiAgcHJpdmF0ZSBmaW5kTWF0Y2hlZEFwaShyZXF1ZXN0OiBGYXN0aWZ5UmVxdWVzdCk6IEV4dGVuZGVkQXBpIHwgdW5kZWZpbmVkIHtcbiAgICBjb25zdCB1cmwgPSB0aGlzLmdldFBhdGhuYW1lRnJvbVVybChyZXF1ZXN0LnVybCk7XG4gICAgY29uc3QgbWV0aG9kID0gcmVxdWVzdC5tZXRob2Q7XG5cbiAgICBpZiAoIXVybC5zdGFydHNXaXRoKHRoaXMuY29uZmlnLmFwaS5yb3V0ZS5wcmVmaXgpKSB7XG4gICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzLnN5bmNlci5hcGlzLmZpbmQoKGFwaSkgPT4ge1xuICAgICAgaWYgKHRoaXMuc3luY2VyLm1vZGVsc1thcGkubW9kZWxOYW1lXSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IGFwaU1ldGhvZCA9IGFwaS5vcHRpb25zLmh0dHBNZXRob2QgPz8gXCJHRVRcIjtcbiAgICAgIGlmIChhcGlNZXRob2QgIT09IG1ldGhvZCkgcmV0dXJuIGZhbHNlO1xuXG4gICAgICBjb25zdCBmdWxsUGF0aCA9IHRoaXMuY29uZmlnLmFwaS5yb3V0ZS5wcmVmaXggKyBhcGkucGF0aDtcbiAgICAgIHJldHVybiB0aGlzLmlzUGF0aFBhdHRlcm5NYXRjaChmdWxsUGF0aCwgdXJsKTtcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBkZXYgYXBpIOuqqOuTnDogVml0ZSDsl4bsnbQgQVBJIOuPmeyggSDrnbzsmrDtjIXrp4wg7KCc6rO17ZWp64uI64ukLlxuICAgKiBITVLsnYQg7JyE7ZW0IGNhdGNoLWFsbOyXkOyEnCDrp6Qg7JqU7LKt66eI64ukIHN5bmNlci5hcGlz66W8IOyhsO2ajO2VqeuLiOuLpC5cbiAgICovXG4gIHByaXZhdGUgc2V0dXBEZXZTZXJ2ZXIoXG4gICAgc2VydmVyOiBGYXN0aWZ5SW5zdGFuY2U8U2VydmVyLCBJbmNvbWluZ01lc3NhZ2UsIFNlcnZlclJlc3BvbnNlPixcbiAgICBjb25maWc6IFNvbmFtdUZhc3RpZnlDb25maWcsXG4gICk6IHZvaWQge1xuICAgIC8vIHVwZ3JhZGXripQg7Iuk7KeI7KCB7Jy866GcIEdFVOyXkOyEnOunjCDshLHrpr3tlZjrr4DroZwgR0VUICsgd3NIYW5kbGVyIOyZgCDqt7gg7Jm4IG1ldGhvZOulvCDrs4Trj4Qgcm91dGXroZwg67aE66as7ZWoXG4gICAgc2VydmVyLnJvdXRlKHtcbiAgICAgIG1ldGhvZDogXCJHRVRcIixcbiAgICAgIHVybDogYCR7dGhpcy5jb25maWcuYXBpLnJvdXRlLnByZWZpeH0vKmAsXG4gICAgICBoYW5kbGVyOiBhc3luYyAocmVxdWVzdCwgcmVwbHkpID0+IHtcbiAgICAgICAgY29uc3QgaGFuZGxlciA9IHRoaXMuaGFuZGxlRGV2QXBpUmVxdWVzdChyZXF1ZXN0LCBjb25maWcpO1xuICAgICAgICBpZiAoaGFuZGxlcikge1xuICAgICAgICAgIHJldHVybiBoYW5kbGVyKHJlcXVlc3QsIHJlcGx5KTtcbiAgICAgICAgfVxuICAgICAgICAvLyDrk7HroZ3rkJwgQVBJ7JmAIOydvOy5mO2VmOyngCDslYrripQg7JqU7LKt7JeQIOuMgO2VnCBmYWxsYmFja+yeheuLiOuLpC5cbiAgICAgICAgdGhyb3cgbmV3IE5vdEZvdW5kRXhjZXB0aW9uKFNEKFwiZXJyb3IuYXBpLm5vdEZvdW5kXCIpKTtcbiAgICAgIH0sXG4gICAgICB3c0hhbmRsZXI6IGFzeW5jIChjb25uZWN0aW9uLCByZXF1ZXN0KSA9PiB7XG4gICAgICAgIGF3YWl0IHRoaXMuaGFuZGxlRGV2V2ViU29ja2V0UmVxdWVzdChjb25uZWN0aW9uLnNvY2tldCwgcmVxdWVzdCwgY29uZmlnKTtcbiAgICAgIH0sXG4gICAgfSk7XG5cbiAgICBzZXJ2ZXIucm91dGUoe1xuICAgICAgbWV0aG9kOiBbXCJIRUFEXCIsIFwiUE9TVFwiLCBcIlBVVFwiLCBcIkRFTEVURVwiLCBcIlBBVENIXCJdLFxuICAgICAgdXJsOiBgJHt0aGlzLmNvbmZpZy5hcGkucm91dGUucHJlZml4fS8qYCxcbiAgICAgIGhhbmRsZXI6IGFzeW5jIChyZXF1ZXN0LCByZXBseSkgPT4ge1xuICAgICAgICBjb25zdCBoYW5kbGVyID0gdGhpcy5oYW5kbGVEZXZBcGlSZXF1ZXN0KHJlcXVlc3QsIGNvbmZpZyk7XG4gICAgICAgIGlmIChoYW5kbGVyKSB7XG4gICAgICAgICAgcmV0dXJuIGhhbmRsZXIocmVxdWVzdCwgcmVwbHkpO1xuICAgICAgICB9XG4gICAgICAgIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbihTRChcImVycm9yLmFwaS5ub3RGb3VuZFwiKSk7XG4gICAgICB9LFxuICAgIH0pO1xuICB9XG5cbiAgcHJpdmF0ZSB2aXRlU2VydmVyOiBhbnkgPSBudWxsO1xuXG4gIC8qKlxuICAgKiBkZXYgYWxsIOuqqOuTnDogVml0ZSBEZXYgU2VydmVy66W8IO2Gte2Vqe2VmOyXrCBBUEkgKyBTU1IgKyBDU1LsnYQg66qo65GQIOygnOqzte2VqeuLiOuLpC5cbiAgICogQVBJIOuPmeyggSDrp6Tsua3snYAgaGFuZGxlRGV2QXBpUmVxdWVzdOulvCDqs7XsnKDtlanri4jri6QuXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIHNldHVwRGV2U2VydmVyV2l0aFZpdGUoXG4gICAgc2VydmVyOiBGYXN0aWZ5SW5zdGFuY2U8U2VydmVyLCBJbmNvbWluZ01lc3NhZ2UsIFNlcnZlclJlc3BvbnNlPixcbiAgICB3ZWJQYXRoOiBzdHJpbmcsXG4gICAgY29uZmlnOiBTb25hbXVGYXN0aWZ5Q29uZmlnLFxuICApOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAvLyBAZmFzdGlmeS9taWRkaWUg65Ox66GdIChDb25uZWN0LXN0eWxlIG1pZGRsZXdhcmUg7KeA7JuQKVxuICAgIGF3YWl0IHNlcnZlci5yZWdpc3RlcigoYXdhaXQgaW1wb3J0KFwiQGZhc3RpZnkvbWlkZGllXCIpKS5kZWZhdWx0KTtcblxuICAgIGNvbnN0IHZpdGUgPSBhd2FpdCBpbXBvcnQoXCJ2aXRlXCIpO1xuICAgIC8vIEBmYXN0aWZ5L3dlYnNvY2tldCDtlIzrn6zqt7jsnbjsnbQg7Zmc7ISx7ZmU65CY66m0IEhNUiB3ZWJzb2NrZXTqs7wgc2VydmVyIHNvY2tldOydtCDstqnrj4ztlZjrr4DroZwgZGVkaWNhdGVkIO2PrO2KuOuhnCDrtoTrpqztlahcbiAgICBjb25zdCByZXF1aXJlc0RlZGljYXRlZEhtclNlcnZlciA9IEJvb2xlYW4odGhpcy5jb25maWcuc2VydmVyLnBsdWdpbnM/LndzKTtcbiAgICBjb25zdCBobXIgPSByZXNvbHZlSW50ZWdyYXRlZFZpdGVIbXJPcHRpb25zKHtcbiAgICAgIGh0dHBTZXJ2ZXI6IHNlcnZlci5zZXJ2ZXIsXG4gICAgICByZXF1aXJlc0RlZGljYXRlZFdlYlNvY2tldFNlcnZlcjogcmVxdWlyZXNEZWRpY2F0ZWRIbXJTZXJ2ZXIsXG4gICAgfSk7XG5cbiAgICB0aGlzLnZpdGVTZXJ2ZXIgPSBhd2FpdCB2aXRlLmNyZWF0ZVNlcnZlcih7XG4gICAgICByb290OiB3ZWJQYXRoLFxuICAgICAgc2VydmVyOiB7XG4gICAgICAgIG1pZGRsZXdhcmVNb2RlOiB0cnVlLFxuICAgICAgICBobXIsXG4gICAgICB9LFxuICAgICAgYXBwVHlwZTogXCJjdXN0b21cIixcbiAgICB9KTtcblxuICAgIC8vIFZpdGUgbWlkZGxld2FyZSDrk7HroZ0gKFZpdGUg7JeQ7IWLIOyymOumrClcbiAgICBzZXJ2ZXIudXNlKChyZXEsIHJlcywgbmV4dCkgPT4ge1xuICAgICAgLy8gQVBJ7JmAIFNvbmFtdSBVSeuKlCBGYXN0aWZ5IOudvOyasO2KuOqwgCDsspjrpqztlZjrj4TroZ0gc2tpcFxuICAgICAgaWYgKHJlcS51cmw/LnN0YXJ0c1dpdGgodGhpcy5jb25maWcuYXBpLnJvdXRlLnByZWZpeCkgfHwgcmVxLnVybD8uc3RhcnRzV2l0aChcIi9zb25hbXUtdWlcIikpIHtcbiAgICAgICAgcmV0dXJuIG5leHQoKTtcbiAgICAgIH1cbiAgICAgIC8vIOuCmOuouOyngOuKlCBWaXRlIG1pZGRsZXdhcmXroZwg7KCE64usXG4gICAgICByZXR1cm4gdGhpcy52aXRlU2VydmVyLm1pZGRsZXdhcmVzKHJlcSwgcmVzLCBuZXh0KTtcbiAgICB9KTtcblxuICAgIC8vIFdTIHVwZ3JhZGUg6rK966GcKEdFVCnsmYAg7J2867CYIEhUVFAg66mU7ISc65Oc66W8IOuzhOuPhCByb3V0ZeuhnCDrtoTrpqztlbQgd2Vic29ja2V0IHJvdXRl6rCAIEhUTUwgZmFsbGJhY2vsl5Ag66i57Z6I7KeAIOyViuuPhOuhnSDtlahcbiAgICBzZXJ2ZXIucm91dGUoe1xuICAgICAgbWV0aG9kOiBcIkdFVFwiLFxuICAgICAgdXJsOiBgJHt0aGlzLmNvbmZpZy5hcGkucm91dGUucHJlZml4fS8qYCxcbiAgICAgIGhhbmRsZXI6IGFzeW5jIChyZXF1ZXN0LCByZXBseSkgPT4ge1xuICAgICAgICBjb25zdCByZXN1bHQgPSB0aGlzLmhhbmRsZURldkFwaVJlcXVlc3QocmVxdWVzdCwgY29uZmlnKTtcbiAgICAgICAgaWYgKHJlc3VsdCkge1xuICAgICAgICAgIHJldHVybiByZXN1bHQocmVxdWVzdCwgcmVwbHkpO1xuICAgICAgICB9XG4gICAgICAgIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbihTRChcImVycm9yLmFwaS5ub3RGb3VuZFwiKSk7XG4gICAgICB9LFxuICAgICAgd3NIYW5kbGVyOiBhc3luYyAoY29ubmVjdGlvbiwgcmVxdWVzdCkgPT4ge1xuICAgICAgICBhd2FpdCB0aGlzLmhhbmRsZURldldlYlNvY2tldFJlcXVlc3QoY29ubmVjdGlvbi5zb2NrZXQsIHJlcXVlc3QsIGNvbmZpZyk7XG4gICAgICB9LFxuICAgIH0pO1xuXG4gICAgc2VydmVyLnJvdXRlKHtcbiAgICAgIG1ldGhvZDogW1wiSEVBRFwiLCBcIlBPU1RcIiwgXCJQVVRcIiwgXCJERUxFVEVcIiwgXCJQQVRDSFwiXSxcbiAgICAgIHVybDogYCR7dGhpcy5jb25maWcuYXBpLnJvdXRlLnByZWZpeH0vKmAsXG4gICAgICBoYW5kbGVyOiBhc3luYyAocmVxdWVzdCwgcmVwbHkpID0+IHtcbiAgICAgICAgY29uc3QgcmVzdWx0ID0gdGhpcy5oYW5kbGVEZXZBcGlSZXF1ZXN0KHJlcXVlc3QsIGNvbmZpZyk7XG4gICAgICAgIGlmIChyZXN1bHQpIHtcbiAgICAgICAgICByZXR1cm4gcmVzdWx0KHJlcXVlc3QsIHJlcGx5KTtcbiAgICAgICAgfVxuICAgICAgICB0aHJvdyBuZXcgTm90Rm91bmRFeGNlcHRpb24oU0QoXCJlcnJvci5hcGkubm90Rm91bmRcIikpO1xuICAgICAgfSxcbiAgICB9KTtcblxuICAgIC8vIGNhdGNoLWFsbCDrnbzsmrDtirjsl5DshJwgU1NSL0NTUiDsspjrpqxcbiAgICAvLyDqsJzrsJwg7ZmY6rK97JeQ7ISc64qUIOudvOyasO2KuOuzhCBjb21wcmVzcyDsmLXshZjsnYQg7Y+s6riw7ZWY6rOgIEhNUiDsnbTsoJDsnYQg7Leo7ZWp64uI64ukLlxuICAgIHNlcnZlci5yb3V0ZSh7XG4gICAgICBtZXRob2Q6IFtcIkdFVFwiLCBcIkhFQURcIl0sXG4gICAgICB1cmw6IFwiLypcIixcbiAgICAgIGhhbmRsZXI6IGFzeW5jIChyZXF1ZXN0LCByZXBseSkgPT4ge1xuICAgICAgICBjb25zdCB1cmwgPSByZXF1ZXN0LnVybDtcblxuICAgICAgICAvLyAxLiBTU1Ig65287Jqw7Yq4IOyymOumrFxuICAgICAgICBjb25zdCB7IG1hdGNoU1NSUm91dGUsIHJlbmRlclNTUiB9ID0gYXdhaXQgaW1wb3J0KFwiLi4vc3NyXCIpO1xuICAgICAgICBjb25zdCBzc3JNYXRjaCA9IG1hdGNoU1NSUm91dGUodXJsKTtcbiAgICAgICAgaWYgKHNzck1hdGNoKSB7XG4gICAgICAgICAgY29uc29sZS5sb2coYFtTU1JdIE1hdGNoZWQgcm91dGU6ICR7c3NyTWF0Y2gucm91dGUucGF0aH1gKTtcbiAgICAgICAgICBjb25zdCBodG1sID0gYXdhaXQgcmVuZGVyU1NSKFxuICAgICAgICAgICAgdXJsLFxuICAgICAgICAgICAgc3NyTWF0Y2gucm91dGUsXG4gICAgICAgICAgICBzc3JNYXRjaC5wYXJhbXMsXG4gICAgICAgICAgICByZXF1ZXN0LFxuICAgICAgICAgICAgcmVwbHksXG4gICAgICAgICAgICBjb25maWcsXG4gICAgICAgICAgICB0aGlzLnZpdGVTZXJ2ZXIsXG4gICAgICAgICAgKTtcbiAgICAgICAgICByZXBseS50eXBlKFwidGV4dC9odG1sXCIpO1xuICAgICAgICAgIHJldHVybiBodG1sO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gMi4gQ1NSIGZhbGxiYWNrXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgY29uc3QgZnMgPSBhd2FpdCBpbXBvcnQoXCJub2RlOmZzL3Byb21pc2VzXCIpO1xuICAgICAgICAgIGxldCB0ZW1wbGF0ZSA9IGF3YWl0IGZzLnJlYWRGaWxlKFxuICAgICAgICAgICAgcGF0aC5qb2luKHRoaXMudml0ZVNlcnZlci5jb25maWcucm9vdCwgXCJpbmRleC5odG1sXCIpLFxuICAgICAgICAgICAgXCJ1dGYtOFwiLFxuICAgICAgICAgICk7XG4gICAgICAgICAgdGVtcGxhdGUgPSBhd2FpdCB0aGlzLnZpdGVTZXJ2ZXIudHJhbnNmb3JtSW5kZXhIdG1sKHVybCwgdGVtcGxhdGUpO1xuXG4gICAgICAgICAgcmVwbHkudHlwZShcInRleHQvaHRtbFwiKTtcbiAgICAgICAgICByZXR1cm4gdGVtcGxhdGU7XG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICB0aGlzLnZpdGVTZXJ2ZXIuc3NyRml4U3RhY2t0cmFjZShlIGFzIEVycm9yKTtcbiAgICAgICAgICBjb25zb2xlLmVycm9yKGUpO1xuICAgICAgICAgIHJlcGx5LnN0YXR1cyg1MDApO1xuICAgICAgICAgIHJldHVybiAoZSBhcyBFcnJvcikubWVzc2FnZTtcbiAgICAgICAgfVxuICAgICAgfSxcbiAgICB9KTtcblxuICAgIC8vIOyEnOuyhCDsooXro4wg7IucIFZpdGXrj4Qg7KKF66OMXG4gICAgc2VydmVyLmFkZEhvb2soXCJvbkNsb3NlXCIsIGFzeW5jICgpID0+IHtcbiAgICAgIGF3YWl0IHRoaXMudml0ZVNlcnZlci5jbG9zZSgpO1xuICAgIH0pO1xuXG4gICAgY29uc3QgY2hhbGsgPSAoYXdhaXQgaW1wb3J0KFwiY2hhbGtcIikpLmRlZmF1bHQ7XG4gICAgaWYgKFwicG9ydFwiIGluIGhtcikge1xuICAgICAgY29uc29sZS5sb2coXG4gICAgICAgIGNoYWxrLmRpbShcbiAgICAgICAgICBg4pyTIFZpdGUgSE1SIHVzaW5nIGRlZGljYXRlZCB3ZWJzb2NrZXQgcG9ydCAke2htci5wb3J0fSB0byBhdm9pZCBGYXN0aWZ5IHdlYnNvY2tldCBjb25mbGljdHNgLFxuICAgICAgICApLFxuICAgICAgKTtcbiAgICB9XG4gICAgY29uc29sZS5sb2coY2hhbGsuZGltKFwi4pyTIFZpdGUgZGV2IHNlcnZlciBpbnRlZ3JhdGVkXCIpKTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgc2V0dXBTdGF0aWNXZWJTZXJ2ZXIoXG4gICAgc2VydmVyOiBGYXN0aWZ5SW5zdGFuY2U8U2VydmVyLCBJbmNvbWluZ01lc3NhZ2UsIFNlcnZlclJlc3BvbnNlPixcbiAgICBjb25maWc6IFNvbmFtdUZhc3RpZnlDb25maWcsXG4gICAgZ2xvYmFsQ29tcHJlc3NPcHRpb25zOiBDb21wcmVzc09wdGlvbnMgfCB1bmRlZmluZWQsXG4gICk6IFByb21pc2U8dm9pZD4ge1xuICAgIC8vIOqyveuhnCDrqoXtmZXtmZQ6IGFwaS93ZWItZGlzdC9jbGllbnQgKOygleyggSDtjIzsnbwpLCBhcGkvd2ViLWRpc3Qvc2VydmVyIChTU1IgZW50cnkpLCBhcGkvZGlzdC9zc3IgKFNTUiByb3V0ZXMgLSBBUEkg7IaM7JygKVxuICAgIGNvbnN0IHdlYkRpc3RQYXRoID0gcGF0aC5qb2luKHRoaXMuYXBpUm9vdFBhdGgsIFwid2ViLWRpc3RcIiwgXCJjbGllbnRcIik7XG4gICAgY29uc3Qgc3NyUGF0aCA9IHBhdGguam9pbih0aGlzLmFwaVJvb3RQYXRoLCBcIndlYi1kaXN0XCIsIFwic2VydmVyXCIpO1xuICAgIGNvbnN0IHNzckVudHJ5UGF0aCA9IHBhdGguam9pbihzc3JQYXRoLCBcImVudHJ5LXNlcnZlci5nZW5lcmF0ZWQuanNcIik7XG4gICAgY29uc3Qgc3NyUm91dGVzUGF0aCA9IHBhdGguam9pbih0aGlzLmFwaVJvb3RQYXRoLCBcImRpc3RcIiwgXCJzc3JcIiwgXCJyb3V0ZXMuanNcIik7XG5cbiAgICBpZiAoIShhd2FpdCBleGlzdHMod2ViRGlzdFBhdGgpKSkge1xuICAgICAgY29uc29sZS53YXJuKGDimqAgV2ViIGRpc3Qgbm90IGZvdW5kOiAke3dlYkRpc3RQYXRofWApO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIFNTUiBlbnRyeSDsobTsnqwg7Jes67aAIO2ZleyduFxuICAgIGNvbnN0IHNzckF2YWlsYWJsZSA9IGF3YWl0IGV4aXN0cyhzc3JFbnRyeVBhdGgpO1xuXG4gICAgaWYgKCFzc3JBdmFpbGFibGUpIHtcbiAgICAgIGNvbnNvbGUud2Fybihg4pqgIFNTUiBlbnRyeSBub3QgZm91bmQ6ICR7c3NyRW50cnlQYXRofWApO1xuICAgICAgY29uc29sZS53YXJuKFwiICBTU1Igd2lsbCBiZSBkaXNhYmxlZC4gT25seSBDU1Igd2lsbCB3b3JrLlwiKTtcbiAgICB9XG5cbiAgICAvLyBTU1Ig65287Jqw7Yq4IOuhnOuTnCAocHJvZHVjdGlvbuyXkOyEnOunjCwg7IKs7Jqp7J6QIO2UhOuhnOygne2KuOydmCBzc3Ivcm91dGVzLnRzKVxuICAgIGlmIChzc3JBdmFpbGFibGUpIHtcbiAgICAgIGlmIChhd2FpdCBleGlzdHMoc3NyUm91dGVzUGF0aCkpIHtcbiAgICAgICAgLy8gdHMtbG9hZGVy652866m0IFwiZmlsZTovL1wi66GcIOyLnOyeke2VmOuKlCBmdWxseS1yZXNvbHZlZCBwYXRo66eMIOuwm+q4sOyXkCDsnbTrpbwg7LKY66as7ZW07KO864qUIGltcG9ydE1lbWJlcnPrpbwg7IKs7Jqp7ZW07JW8IO2WiOqyoOyngOunjCxcbiAgICAgICAgLy8g7Jes6riw64qUIO2UhOuhnOuNleyFmCDtmZjqsr3sl5DshJwgbG9hZGVyIOyXhuydtCDrj4zslYTqsIDquLAg65WM66y47JeQIFwi7KeE7KecIGpzIO2MjOydvFwi7J2YIFwi6re464OlXCIg7KCI64yA6rK966Gc66W8IOuwlOuhnCBpbXBvcnTtlbTrj4Qg65Cp64uI64ukLlxuICAgICAgICAvLyDsnbQg64K07Jqp7J2AIOydtCDtlajsiJgg64K07JeQ7IScIOyVhOuemOyXkCDrgpjsmKwg64uk66W4IGltcG9ydCDtmLjstpzsl5Drj4Qg64+Z7J287ZWY6rKMIOyggeyaqeuQqeuLiOuLpC5cbiAgICAgICAgYXdhaXQgaW1wb3J0KHNzclJvdXRlc1BhdGgpO1xuICAgICAgICBjb25zb2xlLmxvZyhcIuKckyBTU1Igcm91dGVzIGxvYWRlZFwiKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnNvbGUud2Fybihg4pqgIFNTUiByb3V0ZXMgbm90IGZvdW5kOiAke3NzclJvdXRlc1BhdGh9YCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8g66Gk66eBIOyXheuNsOydtO2KuCDrjIDsnZE6IGFzc2V0IGhhc2gg67aI7J287LmYIOyLnCDtmITsnqwg67KE7KCEIOyngeygkSDshJzruZlcbiAgICBzZXJ2ZXIuZ2V0KFwiL2Fzc2V0cy86ZmlsZW5hbWVcIiwgYXN5bmMgKHJlcXVlc3QsIHJlcGx5KSA9PiB7XG4gICAgICBjb25zdCByZXF1ZXN0ZWRGaWxlID0gKHJlcXVlc3QucGFyYW1zIGFzIHsgZmlsZW5hbWU6IHN0cmluZyB9KS5maWxlbmFtZTtcbiAgICAgIGNvbnN0IGFzc2V0c0RpciA9IHBhdGguam9pbih3ZWJEaXN0UGF0aCwgXCJhc3NldHNcIik7XG4gICAgICBjb25zdCBzYWZlRmlsZVBhdGggPSB0aGlzLnJlc29sdmVQYXRoV2l0aGluQmFzZURpcihhc3NldHNEaXIsIHJlcXVlc3RlZEZpbGUpO1xuICAgICAgaWYgKHNhZmVGaWxlUGF0aCA9PT0gbnVsbCkge1xuICAgICAgICByZXBseS5zdGF0dXMoNDAzKS5zZW5kKCk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIGNvbnN0IG5vcm1hbGl6ZWRSZXF1ZXN0ZWRGaWxlID0gcGF0aC5yZWxhdGl2ZShhc3NldHNEaXIsIHNhZmVGaWxlUGF0aCkucmVwbGFjZSgvXFxcXC9nLCBcIi9cIik7XG5cbiAgICAgIGNvbnN0IGFzc2V0UGF0aCA9IGAvYXNzZXRzLyR7bm9ybWFsaXplZFJlcXVlc3RlZEZpbGV9YDtcblxuICAgICAgLy8gQ2FjaGUtQ29udHJvbCDtl6TrjZQg6rKw7KCVXG4gICAgICBjb25zdCBnZXRDYWNoZUNvbnRyb2xGb3JBc3NldCA9ICgpOiBDYWNoZUNvbnRyb2xDb25maWcgPT4ge1xuICAgICAgICBjb25zdCBjYWNoZVJlcTogQ2FjaGVDb250cm9sUmVxdWVzdCA9IHtcbiAgICAgICAgICB0eXBlOiBcImFzc2V0c1wiLFxuICAgICAgICAgIHVybDogcmVxdWVzdC51cmwsXG4gICAgICAgICAgcGF0aDogYXNzZXRQYXRoLFxuICAgICAgICAgIG1ldGhvZDogcmVxdWVzdC5tZXRob2QsXG4gICAgICAgIH07XG5cbiAgICAgICAgLy8g7IKs7Jqp7J6QIOygleydmCDtlbjrk6Trn6wg7Jqw7ISgXG4gICAgICAgIGlmIChjb25maWcuY2FjaGVDb250cm9sSGFuZGxlcikge1xuICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IGNvbmZpZy5jYWNoZUNvbnRyb2xIYW5kbGVyKGNhY2hlUmVxKTtcbiAgICAgICAgICBpZiAocmVzdWx0KSByZXR1cm4gcmVzdWx0O1xuICAgICAgICB9XG5cbiAgICAgICAgLy8g6riw67O46rCSOiBpbW11dGFibGVcbiAgICAgICAgcmV0dXJuIENhY2hlUHJlc2V0cy5pbW11dGFibGU7XG4gICAgICB9O1xuXG4gICAgICAvLyBpbmRleC0qLmpzIOuYkOuKlCBpbmRleC0qLmNzcyDsmpTssq3snbgg6rK97JqwXG4gICAgICBpZiAoL15pbmRleC1bYS1mMC05XStcXC4oanN8Y3NzKSQvLnRlc3Qobm9ybWFsaXplZFJlcXVlc3RlZEZpbGUpKSB7XG4gICAgICAgIGNvbnN0IGV4dCA9IG5vcm1hbGl6ZWRSZXF1ZXN0ZWRGaWxlLnNwbGl0KFwiLlwiKS5wb3AoKTtcbiAgICAgICAgY29uc3QgZmlsZXMgPSBhd2FpdCBmcy5yZWFkZGlyKGFzc2V0c0Rpcik7XG4gICAgICAgIGNvbnN0IGN1cnJlbnRGaWxlID0gZmlsZXMuZmluZCgoZikgPT4gZi5zdGFydHNXaXRoKFwiaW5kZXgtXCIpICYmIGYuZW5kc1dpdGgoYC4ke2V4dH1gKSk7XG5cbiAgICAgICAgaWYgKGN1cnJlbnRGaWxlKSB7XG4gICAgICAgICAgY29uc3QgZmlsZVBhdGggPSBwYXRoLmpvaW4oYXNzZXRzRGlyLCBjdXJyZW50RmlsZSk7XG4gICAgICAgICAgY29uc3QgY29udGVudCA9IGF3YWl0IGZzLnJlYWRGaWxlKGZpbGVQYXRoKTtcbiAgICAgICAgICByZXBseS50eXBlKGV4dCA9PT0gXCJqc1wiID8gXCJhcHBsaWNhdGlvbi9qYXZhc2NyaXB0XCIgOiBcInRleHQvY3NzXCIpO1xuICAgICAgICAgIGFwcGx5Q2FjaGVIZWFkZXJzKHJlcGx5LCBnZXRDYWNoZUNvbnRyb2xGb3JBc3NldCgpKTtcbiAgICAgICAgICByZXR1cm4gcmVwbHkuc2VuZChjb250ZW50KTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICAvLyDsnbzrsJgg7YyM7J28IOyEnOu5mVxuICAgICAgY29uc3QgZmlsZVBhdGggPSBzYWZlRmlsZVBhdGg7XG4gICAgICBpZiAoYXdhaXQgZXhpc3RzKGZpbGVQYXRoKSkge1xuICAgICAgICBjb25zdCBjb250ZW50ID0gYXdhaXQgZnMucmVhZEZpbGUoZmlsZVBhdGgpO1xuICAgICAgICBjb25zdCBleHQgPSBub3JtYWxpemVkUmVxdWVzdGVkRmlsZS5zcGxpdChcIi5cIikucG9wKCk7XG4gICAgICAgIHJlcGx5LnR5cGUoZXh0ID09PSBcImpzXCIgPyBcImFwcGxpY2F0aW9uL2phdmFzY3JpcHRcIiA6IGV4dCA9PT0gXCJjc3NcIiA/IFwidGV4dC9jc3NcIiA6IFwiXCIpO1xuICAgICAgICBpZiAobm9ybWFsaXplZFJlcXVlc3RlZEZpbGUuaW5jbHVkZXMoXCItXCIpKSB7XG4gICAgICAgICAgYXBwbHlDYWNoZUhlYWRlcnMocmVwbHksIGdldENhY2hlQ29udHJvbEZvckFzc2V0KCkpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXBseS5zZW5kKGNvbnRlbnQpO1xuICAgICAgfVxuXG4gICAgICByZXBseS5zdGF0dXMoNDA0KS5zZW5kKCk7XG4gICAgfSk7XG5cbiAgICAvLyBTU1Ig65287Jqw7Yq4IOqwnOuzhCDrk7HroZ0gKGNvbXByZXNzIOyYteyFmOydtCDrnbzsmrDtirjrs4TroZwg7KCB7Jqp65CY64+E66GdKVxuICAgIGlmIChzc3JBdmFpbGFibGUpIHtcbiAgICAgIGNvbnN0IHsgZ2V0U1NSUm91dGVzIH0gPSBhd2FpdCBpbXBvcnQoXCIuLi9zc3JcIik7XG4gICAgICBjb25zdCB7IHJlbmRlclNTUiB9ID0gYXdhaXQgaW1wb3J0KFwiLi4vc3NyL3JlbmRlcmVyXCIpO1xuICAgICAgY29uc3Qgc3NyUm91dGVzID0gZ2V0U1NSUm91dGVzKCk7XG5cbiAgICAgIGZvciAoY29uc3Qgcm91dGUgb2Ygc3NyUm91dGVzKSB7XG4gICAgICAgIHNlcnZlci5yb3V0ZSh7XG4gICAgICAgICAgbWV0aG9kOiBbXCJHRVRcIiwgXCJIRUFEXCJdLFxuICAgICAgICAgIHVybDogcm91dGUucGF0aCxcbiAgICAgICAgICBjb21wcmVzczogdG9GYXN0aWZ5Q29tcHJlc3NPcHRpb24ocm91dGUuY29tcHJlc3MgPz8gdHJ1ZSwgZ2xvYmFsQ29tcHJlc3NPcHRpb25zKSxcbiAgICAgICAgICBoYW5kbGVyOiBhc3luYyAocmVxdWVzdCwgcmVwbHkpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHVybCA9IHJlcXVlc3QudXJsO1xuICAgICAgICAgICAgY29uc29sZS5sb2coYFtTU1JdIE1hdGNoZWQgcm91dGU6ICR7cm91dGUucGF0aH1gKTtcblxuICAgICAgICAgICAgY29uc3QgcGFyYW1zID0gdGhpcy5leHRyYWN0UGF0aFBhcmFtcyhyb3V0ZS5wYXRoLCB1cmwpO1xuICAgICAgICAgICAgY29uc3QgaHRtbCA9IGF3YWl0IHJlbmRlclNTUih1cmwsIHJvdXRlLCBwYXJhbXMsIHJlcXVlc3QsIHJlcGx5LCBjb25maWcpO1xuXG4gICAgICAgICAgICByZXBseS50eXBlKFwidGV4dC9odG1sXCIpO1xuICAgICAgICAgICAgcmV0dXJuIGh0bWw7XG4gICAgICAgICAgfSxcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gQ1NSIG9yIFN0YXRpYyBGaWxlIEZhbGxiYWNrIChTU1Ig65287Jqw7Yq47JeQIOunpOy5reuQmOyngCDslYrripQg66qo65OgIOyalOyyrSlcbiAgICBzZXJ2ZXIucm91dGUoe1xuICAgICAgbWV0aG9kOiBbXCJHRVRcIiwgXCJIRUFEXCJdLFxuICAgICAgdXJsOiBcIipcIixcbiAgICAgIGhhbmRsZXI6IGFzeW5jIChyZXF1ZXN0LCByZXBseSkgPT4ge1xuICAgICAgICAvLyAvYXBpLCAvc29uYW11LXVp64qUIDQwNCDqt7jrjIDroZxcbiAgICAgICAgaWYgKHJlcXVlc3QudXJsLnN0YXJ0c1dpdGgoXCIvYXBpXCIpIHx8IHJlcXVlc3QudXJsLnN0YXJ0c1dpdGgoXCIvc29uYW11LXVpXCIpKSB7XG4gICAgICAgICAgcmVwbHkuc3RhdHVzKDQwNCkuc2VuZCgpO1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIENTUuyaqSBDYWNoZS1Db250cm9sIO2XpOuNlCDshKTsoJVcbiAgICAgICAgaWYgKGNvbmZpZy5jYWNoZUNvbnRyb2xIYW5kbGVyKSB7XG4gICAgICAgICAgY29uc3QgY3NyQ2FjaGVSZXE6IENhY2hlQ29udHJvbFJlcXVlc3QgPSB7XG4gICAgICAgICAgICB0eXBlOiBcImNzclwiLFxuICAgICAgICAgICAgdXJsOiByZXF1ZXN0LnVybCxcbiAgICAgICAgICAgIHBhdGg6IHJlcXVlc3QudXJsLnNwbGl0KFwiP1wiKVswXSxcbiAgICAgICAgICAgIG1ldGhvZDogcmVxdWVzdC5tZXRob2QsXG4gICAgICAgICAgfTtcbiAgICAgICAgICBjb25zdCBjc3JDYWNoZUNvbmZpZyA9IGNvbmZpZy5jYWNoZUNvbnRyb2xIYW5kbGVyKGNzckNhY2hlUmVxKTtcblxuICAgICAgICAgIGlmIChjc3JDYWNoZUNvbmZpZykge1xuICAgICAgICAgICAgYXBwbHlDYWNoZUhlYWRlcnMocmVwbHksIGNzckNhY2hlQ29uZmlnKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyDsoJXsoIEg7YyM7J287J20IOyhtOyerO2VoCDqsr3smrAsIOygleyggSDtjIzsnbzsnYQg66i87KCAIOyEnOu5me2VtOyVvO2VqFxuICAgICAgICBjb25zdCByZXF1ZXN0UGF0aCA9IHRoaXMuZ2V0UGF0aG5hbWVGcm9tVXJsKHJlcXVlc3QudXJsKTtcbiAgICAgICAgY29uc3Qgc2FmZUZpbGVQYXRoID0gdGhpcy5yZXNvbHZlUGF0aFdpdGhpbkJhc2VEaXIod2ViRGlzdFBhdGgsIHJlcXVlc3RQYXRoKTtcbiAgICAgICAgaWYgKHNhZmVGaWxlUGF0aCA9PT0gbnVsbCkge1xuICAgICAgICAgIHJlcGx5LnN0YXR1cyg0MDMpLnNlbmQoKTtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGF3YWl0IGZpbGVFeGlzdHMoc2FmZUZpbGVQYXRoKSkge1xuICAgICAgICAgIGNvbnN0IGNvbnRlbnQgPSBhd2FpdCBmcy5yZWFkRmlsZShzYWZlRmlsZVBhdGgpO1xuICAgICAgICAgIHJldHVybiByZXBseS50eXBlKG1pbWVMb29rdXAoc2FmZUZpbGVQYXRoKSB8fCBcImFwcGxpY2F0aW9uL29jdGV0LXN0cmVhbVwiKS5zZW5kKGNvbnRlbnQpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gQ1NSIGZhbGxiYWNrOiBpbmRleC5odG1sIOyEnOu5mVxuICAgICAgICBjb25zdCBpbmRleFBhdGggPSBwYXRoLmpvaW4od2ViRGlzdFBhdGgsIFwiaW5kZXguaHRtbFwiKTtcbiAgICAgICAgcmV0dXJuIHJlcGx5LnR5cGUoXCJ0ZXh0L2h0bWxcIikuc2VuZChhd2FpdCBmcy5yZWFkRmlsZShpbmRleFBhdGgsIFwidXRmLThcIikpO1xuICAgICAgfSxcbiAgICB9KTtcblxuICAgIGNvbnNvbGUubG9nKGDinJMgU3RhdGljIHdlYiBzZXJ2ZXIgY29uZmlndXJlZCB3aXRoICR7c3NyQXZhaWxhYmxlID8gXCJTU1JcIiA6IFwiQ1NSIG9ubHlcIn0gc3VwcG9ydGApO1xuICB9XG5cbiAgY3JlYXRlQXBpSGFuZGxlcihcbiAgICBhcGk6IEV4dGVuZGVkQXBpLFxuICAgIGNvbmZpZzogU29uYW11RmFzdGlmeUNvbmZpZyxcbiAgKTogKHJlcXVlc3Q6IEZhc3RpZnlSZXF1ZXN0LCByZXBseTogRmFzdGlmeVJlcGx5KSA9PiBQcm9taXNlPHVua25vd24+IHtcbiAgICByZXR1cm4gYXN5bmMgKHJlcXVlc3Q6IEZhc3RpZnlSZXF1ZXN0LCByZXBseTogRmFzdGlmeVJlcGx5KTogUHJvbWlzZTx1bmtub3duPiA9PiB7XG4gICAgICAvLyBDb250ZXh0IOyDneyEsVxuICAgICAgY29uc3QgY29udGV4dDogQ29udGV4dCA9IGF3YWl0IHRoaXMuY3JlYXRlQ29udGV4dChjb25maWcsIHJlcXVlc3QsIHJlcGx5KTtcblxuICAgICAgcmV0dXJuIHRoaXMuYXN5bmNMb2NhbFN0b3JhZ2UucnVuKHsgY29udGV4dCB9LCBhc3luYyAoKSA9PiB7XG4gICAgICAgIC8vIGd1YXJkcyDsspjrpqxcbiAgICAgICAgcnVuR3VhcmRzKHtcbiAgICAgICAgICBndWFyZHM6IGFwaS5vcHRpb25zLmd1YXJkcyxcbiAgICAgICAgICBjb25maWcsXG4gICAgICAgICAgcmVxdWVzdCxcbiAgICAgICAgICBhcGksXG4gICAgICAgIH0pO1xuXG4gICAgICAgIC8vIO2MjOudvOuvuO2EsCDsoJXrs7TroZwgem9kIOyKpO2CpOuniCDruYzrk5xcbiAgICAgICAgY29uc3QgeyBnZXRab2RPYmplY3RGcm9tQXBpIH0gPSBhd2FpdCBpbXBvcnQoXCIuL2NvZGUtY29udmVydGVyc1wiKTtcbiAgICAgICAgY29uc3QgUmVxVHlwZSA9IGdldFpvZE9iamVjdEZyb21BcGkoYXBpLCB0aGlzLnN5bmNlci50eXBlcyk7XG5cbiAgICAgICAgLy8gcmVxdWVzdCDtjIzsi7FcbiAgICAgICAgY29uc3Qgd2hpY2ggPSBhcGkub3B0aW9ucy5odHRwTWV0aG9kID09PSBcIkdFVFwiID8gXCJxdWVyeVwiIDogXCJib2R5XCI7XG4gICAgICAgIGxldCByZXFCb2R5OiB7XG4gICAgICAgICAgW2tleTogc3RyaW5nXTogdW5rbm93bjtcbiAgICAgICAgfTtcbiAgICAgICAgLy8g7YyM7J28IOyXheuhnOuTnCDsnojripQg6rK97JqwIOyehOyLnCDrjbDsnbTthLBcbiAgICAgICAgY29uc3QgZmlsZXM6IHtcbiAgICAgICAgICBidWZmZXJlZEZpbGVzOiBCdWZmZXJlZEZpbGVbXTtcbiAgICAgICAgICB1cGxvYWRlZEZpbGVzOiBVcGxvYWRlZEZpbGVbXTtcbiAgICAgICAgfSA9IHtcbiAgICAgICAgICBidWZmZXJlZEZpbGVzOiBbXSxcbiAgICAgICAgICB1cGxvYWRlZEZpbGVzOiBbXSxcbiAgICAgICAgfTtcblxuICAgICAgICB0cnkge1xuICAgICAgICAgIGNvbnN0IGJvZHkgPSAocmVxdWVzdFt3aGljaF0gPz8ge30pIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xuICAgICAgICAgIGlmIChhcGkudXBsb2FkT3B0aW9ucykge1xuICAgICAgICAgICAgY29uc3QgcGFydHMgPSByZXF1ZXN0LnBhcnRzKHtcbiAgICAgICAgICAgICAgbGltaXRzOiBhcGkudXBsb2FkT3B0aW9ucy5saW1pdHMsXG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgLy8gRm9ybURhdGHsnZggZmllbGTrk6TsnYQg7J6E7Iuc66GcIOyggOyepVxuICAgICAgICAgICAgY29uc3QgZmllbGRzOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+ID0ge307XG5cbiAgICAgICAgICAgIGlmIChhcGkudXBsb2FkT3B0aW9ucy5jb25zdW1lID09PSBcImJ1ZmZlclwiIHx8ICFhcGkudXBsb2FkT3B0aW9ucy5jb25zdW1lKSB7XG4gICAgICAgICAgICAgIC8vIEJ1ZmZlciDrqqjrk5w6IOuplOuqqOumrOyXkCDroZzrk5xcbiAgICAgICAgICAgICAgZm9yIGF3YWl0IChjb25zdCBwYXJ0IG9mIHBhcnRzKSB7XG4gICAgICAgICAgICAgICAgaWYgKHBhcnQudHlwZSA9PT0gXCJmaWxlXCIpIHtcbiAgICAgICAgICAgICAgICAgIC8vIENSSVRJQ0FMOiDtjIzsnbwg7Iqk7Yq466a87J2EIOymieyLnCBjb25zdW1l7ZW07JW8IOuLpOydjCBwYXJ066GcIOuEmOyWtOqwiCDsiJgg7J6I7J2MXG4gICAgICAgICAgICAgICAgICAvLyDsnbQg7Zi47Lac7J20IOyXhuycvOuptCDsooXsooUgbXVsdGlwYXJ0IO2MjOyLseydtCBwZW5kaW5nIOyDge2DnOuhnCDtg4DsnoTslYTsm4Mg67Cc7IOdXG4gICAgICAgICAgICAgICAgICBjb25zdCBidWZmZXIgPSBhd2FpdCBwYXJ0LnRvQnVmZmVyKCk7XG4gICAgICAgICAgICAgICAgICBmaWxlcy5idWZmZXJlZEZpbGVzLnB1c2gobmV3IEJ1ZmZlcmVkRmlsZShwYXJ0LCBidWZmZXIpKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHBhcnQudHlwZSA9PT0gXCJmaWVsZFwiKSB7XG4gICAgICAgICAgICAgICAgICBmaWVsZHNbcGFydC5maWVsZG5hbWVdID0gU3RyaW5nKHBhcnQudmFsdWUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIGlmIChhcGkudXBsb2FkT3B0aW9ucy5jb25zdW1lID09PSBcInN0cmVhbVwiKSB7XG4gICAgICAgICAgICAgIC8vIFN0cmVhbSDrqqjrk5w6IOymieyLnCDsoIDsnqXshozroZwg7Iqk7Yq466as67CNXG4gICAgICAgICAgICAgIGNvbnN0IGRpc2tOYW1lID0gYXBpLnVwbG9hZE9wdGlvbnMuZGVzdGluYXRpb247XG4gICAgICAgICAgICAgIGNvbnN0IGRpc2sgPSB0aGlzLnN0b3JhZ2UudXNlKGRpc2tOYW1lKTtcblxuICAgICAgICAgICAgICAvLyDsmrDshKDsiJzsnIQ6IOuNsOy9lOugiOydtO2EsCA+IOyghOyXrSDshKTsoJUgPiDquLDrs7jqsJJcbiAgICAgICAgICAgICAgY29uc3Qga2V5R2VuZXJhdG9yOiBLZXlHZW5lcmF0b3IgPVxuICAgICAgICAgICAgICAgIGFwaS51cGxvYWRPcHRpb25zLmtleUdlbmVyYXRvciA/P1xuICAgICAgICAgICAgICAgIHRoaXMuY29uZmlnLnNlcnZlci5zdG9yYWdlPy5rZXlHZW5lcmF0b3IgPz9cbiAgICAgICAgICAgICAgICBkZWZhdWx0S2V5R2VuZXJhdG9yO1xuXG4gICAgICAgICAgICAgIGZvciBhd2FpdCAoY29uc3QgcGFydCBvZiBwYXJ0cykge1xuICAgICAgICAgICAgICAgIGlmIChwYXJ0LnR5cGUgPT09IFwiZmlsZVwiKSB7XG4gICAgICAgICAgICAgICAgICBjb25zdCBrZXkgPSBhd2FpdCBrZXlHZW5lcmF0b3Ioe1xuICAgICAgICAgICAgICAgICAgICBmaWxlbmFtZTogcGFydC5maWxlbmFtZSxcbiAgICAgICAgICAgICAgICAgICAgbWltZXR5cGU6IHBhcnQubWltZXR5cGUsXG4gICAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgICAgYXdhaXQgZGlzay5wdXRTdHJlYW0oa2V5LCBwYXJ0LmZpbGUsIHtcbiAgICAgICAgICAgICAgICAgICAgY29udGVudFR5cGU6IHBhcnQubWltZXR5cGUsXG4gICAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgICAgY29uc3QgdXJsID0gYXdhaXQgZGlzay5nZXRVcmwoa2V5KTtcbiAgICAgICAgICAgICAgICAgIGNvbnN0IHNpZ25lZFVybCA9IGF3YWl0IGRpc2suZ2V0U2lnbmVkVXJsKGtleSk7XG5cbiAgICAgICAgICAgICAgICAgIGZpbGVzLnVwbG9hZGVkRmlsZXMucHVzaChcbiAgICAgICAgICAgICAgICAgICAgbmV3IFVwbG9hZGVkRmlsZSh7XG4gICAgICAgICAgICAgICAgICAgICAgZmlsZW5hbWU6IHBhcnQuZmlsZW5hbWUsXG4gICAgICAgICAgICAgICAgICAgICAgbWltZXR5cGU6IHBhcnQubWltZXR5cGUsXG4gICAgICAgICAgICAgICAgICAgICAgc2l6ZTogcGFydC5maWxlLmJ5dGVzUmVhZCxcbiAgICAgICAgICAgICAgICAgICAgICB1cmwsXG4gICAgICAgICAgICAgICAgICAgICAgc2lnbmVkVXJsLFxuICAgICAgICAgICAgICAgICAgICAgIGtleSxcbiAgICAgICAgICAgICAgICAgICAgICBkaXNrTmFtZSxcbiAgICAgICAgICAgICAgICAgICAgfSksXG4gICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAocGFydC50eXBlID09PSBcImZpZWxkXCIpIHtcbiAgICAgICAgICAgICAgICAgIGZpZWxkc1twYXJ0LmZpZWxkbmFtZV0gPSBTdHJpbmcocGFydC52YWx1ZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIHFz66GcIOykkeyyqSDqtazsobAg7YyM7IuxOiBwYXJhbXNbY2F0ZWdvcnldIOKGkiB7IHBhcmFtczogeyBjYXRlZ29yeTogXCJ0ZXN0XCIgfSB9XG4gICAgICAgICAgICBjb25zdCBxcyA9IGF3YWl0IGltcG9ydChcInFzXCIpO1xuICAgICAgICAgICAgY29uc3QgcGFyc2VkID0gcXMuZGVmYXVsdC5wYXJzZShmaWVsZHMpO1xuICAgICAgICAgICAgT2JqZWN0LmFzc2lnbihib2R5LCBwYXJzZWQpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGNvbnN0IHsgZmFzdGlmeUNhc3RlciB9ID0gYXdhaXQgaW1wb3J0KFwiLi9jYXN0ZXJcIik7XG4gICAgICAgICAgcmVxQm9keSA9IGZhc3RpZnlDYXN0ZXIoUmVxVHlwZSkucGFyc2UoYm9keSk7XG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICBjb25zdCB7IFpvZEVycm9yIH0gPSBhd2FpdCBpbXBvcnQoXCJ6b2RcIik7XG4gICAgICAgICAgaWYgKGUgaW5zdGFuY2VvZiBab2RFcnJvcikge1xuICAgICAgICAgICAgY29uc3QgeyBodW1hbml6ZVpvZEVycm9yIH0gPSBhd2FpdCBpbXBvcnQoXCIuLi91dGlscy96b2QtZXJyb3JcIik7XG4gICAgICAgICAgICBjb25zdCBtZXNzYWdlcyA9IGh1bWFuaXplWm9kRXJyb3IoZSlcbiAgICAgICAgICAgICAgLm1hcCgoaXNzdWUpID0+IGlzc3VlLm1lc3NhZ2UpXG4gICAgICAgICAgICAgIC5qb2luKFwiIFwiKTtcbiAgICAgICAgICAgIGNvbnN0IHsgQmFkUmVxdWVzdEV4Y2VwdGlvbiB9ID0gYXdhaXQgaW1wb3J0KFwiLi4vZXhjZXB0aW9ucy9zby1leGNlcHRpb25zXCIpO1xuICAgICAgICAgICAgdGhyb3cgbmV3IEJhZFJlcXVlc3RFeGNlcHRpb24obWVzc2FnZXMgYXMgTG9jYWxpemVkU3RyaW5nLCB7XG4gICAgICAgICAgICAgIHpvZEVycm9yOiBlLFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRocm93IGU7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gQ29udGVudC1UeXBlXG4gICAgICAgIHJlcGx5LnR5cGUoYXBpLm9wdGlvbnMuY29udGVudFR5cGUgPz8gXCJhcHBsaWNhdGlvbi9qc29uXCIpO1xuXG4gICAgICAgIC8vIENhY2hlLUNvbnRyb2wg7Zek642UIOyEpOyglVxuICAgICAgICBjb25zdCBhcGlDYWNoZUNvbmZpZyA9IHRoaXMuZ2V0QXBpQ2FjaGVDb250cm9sKGFwaSwgcmVxdWVzdCwgY29uZmlnKTtcbiAgICAgICAgaWYgKGFwaUNhY2hlQ29uZmlnKSB7XG4gICAgICAgICAgYXBwbHlDYWNoZUhlYWRlcnMocmVwbHksIGFwaUNhY2hlQ29uZmlnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIOyXheuhnOuTnCDsmLXshZjsnbQg7J6I64qUIOqyveyasCDtjIzsnbwg642w7J207YSw66W8IENvbnRleHTsl5Ag7LaU6rCAXG4gICAgICAgIGlmIChhcGkudXBsb2FkT3B0aW9ucykge1xuICAgICAgICAgIGNvbnN0IGNvbnN1bWUgPSBhcGkudXBsb2FkT3B0aW9ucy5jb25zdW1lID8/IFwiYnVmZmVyXCI7XG4gICAgICAgICAgaWYgKGNvbnN1bWUgPT09IFwiYnVmZmVyXCIpIHtcbiAgICAgICAgICAgIGNvbnRleHQuYnVmZmVyZWRGaWxlcyA9IGZpbGVzLmJ1ZmZlcmVkRmlsZXM7XG4gICAgICAgICAgfSBlbHNlIGlmIChjb25zdW1lID09PSBcInN0cmVhbVwiKSB7XG4gICAgICAgICAgICBjb250ZXh0LnVwbG9hZGVkRmlsZXMgPSBmaWxlcy51cGxvYWRlZEZpbGVzO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIOuqqOuNuCDrqZTshozrk5wgYXJncyDsg53shLHtlZjsl6wg7Zi47LacXG4gICAgICAgIGNvbnN0IHsgQXBpUGFyYW1UeXBlIH0gPSBhd2FpdCBpbXBvcnQoXCIuLi90eXBlcy90eXBlc1wiKTtcbiAgICAgICAgY29uc3QgYXJncyA9IGFwaS5wYXJhbWV0ZXJzLm1hcCgocGFyYW0pID0+IHtcbiAgICAgICAgICAvLyBDb250ZXh0IOyduOygneyFmFxuICAgICAgICAgIGlmIChBcGlQYXJhbVR5cGUuaXNDb250ZXh0KHBhcmFtLnR5cGUpKSB7XG4gICAgICAgICAgICByZXR1cm4gY29udGV4dDtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIHJlcUJvZHlbcGFyYW0ubmFtZV07XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgICAgICByZXR1cm4gdGhpcy5pbnZva2VNb2RlbE1ldGhvZChhcGksIGFyZ3MsIHJlcGx5KTtcbiAgICAgIH0pO1xuICAgIH07XG4gIH1cblxuICAvLyBXUyBwYXRo66W8IOydvOuwmCBIVFRQIEdFVOycvOuhnCDtmLjstpztlZwg6rK97JqwIDQyNiArIFVwZ3JhZGUg7Zek642U66GcIOuqheyLnOyggeycvOuhnCB3ZWJzb2NrZXQg7KCR7IaN7J2EIOycoOuPhO2VqFxuICBwcml2YXRlIGNyZWF0ZVdlYlNvY2tldFVwZ3JhZGVSZXF1aXJlZEhhbmRsZXIoKSB7XG4gICAgcmV0dXJuIGFzeW5jIChfcmVxdWVzdDogRmFzdGlmeVJlcXVlc3QsIHJlcGx5OiBGYXN0aWZ5UmVwbHkpOiBQcm9taXNlPHZvaWQ+ID0+IHtcbiAgICAgIHJlcGx5LmhlYWRlcihcImNvbm5lY3Rpb25cIiwgXCJVcGdyYWRlXCIpLmhlYWRlcihcInVwZ3JhZGVcIiwgXCJ3ZWJzb2NrZXRcIikuc3RhdHVzKDQyNikuc2VuZCh7XG4gICAgICAgIG1lc3NhZ2U6IFwiV2ViU29ja2V0IHVwZ3JhZGUgcmVxdWlyZWRcIixcbiAgICAgIH0pO1xuICAgIH07XG4gIH1cblxuICAvLyBkZXYg66qo65Oc7J2YIGNhdGNoLWFsbCB3c0hhbmRsZXLsl5DshJwg7Iuk7KCcIFdTIEFQSeuhnCDrlJTsiqTtjKjsuZjtlaguIOunpOy5reuQmOuKlCByb3V0ZeqwgCDsl4bsnLzrqbQgMTAwOOuhnCDri6vsnYxcbiAgcHJpdmF0ZSBhc3luYyBoYW5kbGVEZXZXZWJTb2NrZXRSZXF1ZXN0KFxuICAgIHNvY2tldDogV2ViU29ja2V0LFxuICAgIHJlcXVlc3Q6IEZhc3RpZnlSZXF1ZXN0LFxuICAgIGNvbmZpZzogU29uYW11RmFzdGlmeUNvbmZpZyxcbiAgKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgbWF0Y2hlZEFwaSA9IHRoaXMuZmluZE1hdGNoZWRBcGkocmVxdWVzdCk7XG4gICAgaWYgKCFtYXRjaGVkQXBpPy53ZWJzb2NrZXRPcHRpb25zKSB7XG4gICAgICBzb2NrZXQuY2xvc2UoMTAwOCwgXCJXZWJTb2NrZXQgcm91dGUgbm90IGZvdW5kXCIpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IGhhbmRsZXIgPSB0aGlzLmNyZWF0ZVdlYlNvY2tldEhhbmRsZXIobWF0Y2hlZEFwaSwgY29uZmlnKTtcbiAgICBhd2FpdCBoYW5kbGVyKHsgc29ja2V0IH0sIHJlcXVlc3QpO1xuICB9XG5cbiAgLy8gV1Mgcm91dGUg7ZW465Ok65+s7J2YIOyLpO2WiSDsiJzshJzrpbwg6rOg7KCV7ZWoOlxuICAvLyAxKSBndWFyZOulvCBjb25uZWN0aW9uIOuTseuhnSDsnbTsoITsl5Ag64+M66CkIOyduOymnSDsi6TtjKgg7IucIOu2gOu2hCDrk7HroZ0g7IOB7YOc66W8IOuCqOq4sOyngCDslYrsnYxcbiAgLy8gMikgcXVlcnkgcGFyYW0g7YyM7Iux64+EIGFjdGl2YXRpb24g7KCE7JeQIOuBneuCtCBoYW5kc2hha2Ug7Iuk7Yyo6rCAIHJlZ2lzdHJ57JeQIOuFuOy2nOuQmOyngCDslYrqsowg7ZWoXG4gIC8vIDMpIGBhY3RpdmU6IGZhbHNlYOuhnCDrqLzsoIAg65Ox66Gd7ZWY6rOgLCBjb250ZXh0IOykgOu5hOqwgCDrgZ3rgpwg65KkIGBhY3RpdmF0ZSgpYO2VtCDruIzroZzrk5zsupDsiqTtirjqsIAg7LSI6riw7ZmUIOykkeqwhCDsg4Htg5zrpbwg67O07KeAIOuqu+2VmOqyjCDtlahcbiAgLy8g7JeQ65+sIOuwnOyDnSDsi5zsl5DripQgcmVzb2x2ZVdlYlNvY2tldENsb3NlRGVzY3JpcHRvciDsoJXssYXsl5Ag65Sw6528IGNsb3NlIGNvZGXrpbwg66ek7ZWR7ZWoXG4gIHByaXZhdGUgY3JlYXRlV2ViU29ja2V0SGFuZGxlcihhcGk6IEV4dGVuZGVkQXBpLCBjb25maWc6IFNvbmFtdUZhc3RpZnlDb25maWcpIHtcbiAgICByZXR1cm4gYXN5bmMgKFxuICAgICAgY29ubmVjdGlvbjoge1xuICAgICAgICBzb2NrZXQ6IFdlYlNvY2tldDtcbiAgICAgIH0sXG4gICAgICByZXF1ZXN0OiBGYXN0aWZ5UmVxdWVzdCxcbiAgICApOiBQcm9taXNlPHZvaWQ+ID0+IHtcbiAgICAgIGNvbnN0IHNvY2tldCA9IGNvbm5lY3Rpb24uc29ja2V0O1xuICAgICAgbGV0IHdzQ29udGV4dDogV2ViU29ja2V0Q29udGV4dCB8IG51bGwgPSBudWxsO1xuICAgICAgbGV0IHJhd1dzOiBSZXR1cm5UeXBlPFdlYlNvY2tldFJ1bnRpbWVbXCJyZWdpc3RlckNvbm5lY3Rpb25cIl0+IHwgbnVsbCA9IG51bGw7XG5cbiAgICAgIHRyeSB7XG4gICAgICAgIHJ1bkd1YXJkcyh7XG4gICAgICAgICAgZ3VhcmRzOiBhcGkub3B0aW9ucy5ndWFyZHMsXG4gICAgICAgICAgY29uZmlnLFxuICAgICAgICAgIHJlcXVlc3QsXG4gICAgICAgICAgYXBpLFxuICAgICAgICB9KTtcblxuICAgICAgICBjb25zdCByZXFCb2R5ID0gYXdhaXQgdGhpcy5wYXJzZVdlYlNvY2tldFJlcXVlc3RQYXJhbXMoYXBpLCByZXF1ZXN0KTtcbiAgICAgICAgcmF3V3MgPSB0aGlzLndlYnNvY2tldFJ1bnRpbWUucmVnaXN0ZXJDb25uZWN0aW9uKHNvY2tldCwge1xuICAgICAgICAgIG91dEV2ZW50czogYXBpLndlYnNvY2tldE9wdGlvbnMhLm91dEV2ZW50cyxcbiAgICAgICAgICBpbkV2ZW50czogYXBpLndlYnNvY2tldE9wdGlvbnMhLmluRXZlbnRzLFxuICAgICAgICAgIG5hbWVzcGFjZTogYXBpLndlYnNvY2tldE9wdGlvbnMhLm5hbWVzcGFjZSxcbiAgICAgICAgICBoZWFydGJlYXQ6IGFwaS53ZWJzb2NrZXRPcHRpb25zIS5oZWFydGJlYXQsXG4gICAgICAgICAgbWF4UGF5bG9hZDogYXBpLndlYnNvY2tldE9wdGlvbnMhLm1heFBheWxvYWQsXG4gICAgICAgICAgYWN0aXZlOiBmYWxzZSxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgY29uc3Qgc2NvcGVkV3MgPSB0aGlzLmNyZWF0ZVNjb3BlZFdlYlNvY2tldENvbm5lY3Rpb24ocmF3V3MsICgpID0+IHdzQ29udGV4dCk7XG4gICAgICAgIHdzQ29udGV4dCA9IGF3YWl0IHRoaXMuY3JlYXRlV2ViU29ja2V0Q29udGV4dChjb25maWcsIHJlcXVlc3QsIHNjb3BlZFdzKTtcbiAgICAgICAgdGhpcy53ZWJzb2NrZXRSdW50aW1lLmFjdGl2YXRlQ29ubmVjdGlvbihyYXdXcy5pZCk7XG5cbiAgICAgICAgY29uc3QgeyBBcGlQYXJhbVR5cGUgfSA9IGF3YWl0IGltcG9ydChcIi4uL3R5cGVzL3R5cGVzXCIpO1xuICAgICAgICBjb25zdCBhcmdzID0gYXBpLnBhcmFtZXRlcnMubWFwKChwYXJhbSkgPT4ge1xuICAgICAgICAgIGlmIChBcGlQYXJhbVR5cGUuaXNDb250ZXh0KHBhcmFtLnR5cGUpKSB7XG4gICAgICAgICAgICByZXR1cm4gd3NDb250ZXh0O1xuICAgICAgICAgIH1cblxuICAgICAgICAgIHJldHVybiByZXFCb2R5W3BhcmFtLm5hbWVdO1xuICAgICAgICB9KTtcblxuICAgICAgICBhd2FpdCB0aGlzLmFzeW5jTG9jYWxTdG9yYWdlLnJ1bih7IGNvbnRleHQ6IHdzQ29udGV4dCB9LCBhc3luYyAoKSA9PiB7XG4gICAgICAgICAgYXdhaXQgdGhpcy5pbnZva2VNb2RlbE1ldGhvZChhcGksIGFyZ3MpO1xuICAgICAgICB9KTtcbiAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgIGNvbnN0IGNsb3NlRGVzY3JpcHRvciA9IHJlc29sdmVXZWJTb2NrZXRDbG9zZURlc2NyaXB0b3IoZXJyb3IpO1xuICAgICAgICBpZiAocmF3V3MpIHtcbiAgICAgICAgICByYXdXcy5jbG9zZShjbG9zZURlc2NyaXB0b3IuY29kZSwgY2xvc2VEZXNjcmlwdG9yLnJlYXNvbik7XG4gICAgICAgIH0gZWxzZSBpZiAoc29ja2V0LnJlYWR5U3RhdGUgPCAyKSB7XG4gICAgICAgICAgc29ja2V0LmNsb3NlKGNsb3NlRGVzY3JpcHRvci5jb2RlLCBjbG9zZURlc2NyaXB0b3IucmVhc29uKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0aGlzLnNlcnZlcj8ubG9nKSB7XG4gICAgICAgICAgY29uc3QgcGF5bG9hZCA9IHtcbiAgICAgICAgICAgIGVycjogZXJyb3IsXG4gICAgICAgICAgICBtb2RlbE5hbWU6IGFwaS5tb2RlbE5hbWUsXG4gICAgICAgICAgICBtZXRob2ROYW1lOiBhcGkubWV0aG9kTmFtZSxcbiAgICAgICAgICAgIHBhdGg6IGFwaS5wYXRoLFxuICAgICAgICAgIH07XG4gICAgICAgICAgaWYgKGNsb3NlRGVzY3JpcHRvci5sb2dMZXZlbCA9PT0gXCJ3YXJuXCIpIHtcbiAgICAgICAgICAgIHRoaXMuc2VydmVyLmxvZy53YXJuKHBheWxvYWQsIGNsb3NlRGVzY3JpcHRvci5yZWFzb24pO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLnNlcnZlci5sb2cuZXJyb3IocGF5bG9hZCwgY2xvc2VEZXNjcmlwdG9yLnJlYXNvbik7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGlmIChjbG9zZURlc2NyaXB0b3IubG9nTGV2ZWwgPT09IFwid2FyblwiKSB7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oY2xvc2VEZXNjcmlwdG9yLnJlYXNvbiwgZXJyb3IpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKGNsb3NlRGVzY3JpcHRvci5yZWFzb24sIGVycm9yKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9O1xuICB9XG5cbiAgLy8gb25NZXNzYWdlL29uQ2xvc2Xsspjrn7wg64uk66W4IHRpY2vsl5DshJwg7Iuk7ZaJ65CY64qUIGNhbGxiYWNr7J2AIEFMUyBjb250ZXh06rCAIOuBiuq4sOuvgOuhnCB3cmFwcGVy7JeQ7IScIGBhc3luY0xvY2FsU3RvcmFnZS5ydW5g7Jy866GcIOuLpOyLnCDqsJDsi7gg67O17JuQ7ZWoXG4gIC8vIHB1Ymxpc2gvam9pbi9sZWF2ZS9zZXRVc2VySWQg6rCZ7J2AIOymieyLnCDsi6TtlokgQVBJ64qUIOuLqOyInCDsnITsnoTrp4wg7ZWY6rOgLCBkZWZlcnJlZCBjYWxsYmFja+yXkOunjCBjb250ZXh0IOuzteybkOydhCDsoIHsmqntlahcbiAgcHJpdmF0ZSBjcmVhdGVTY29wZWRXZWJTb2NrZXRDb25uZWN0aW9uPFxuICAgIFRPdXQgZXh0ZW5kcyBXZWJTb2NrZXRFdmVudE1hcCxcbiAgICBUSW4gZXh0ZW5kcyBXZWJTb2NrZXRFdmVudE1hcCxcbiAgPihcbiAgICB3czogV2ViU29ja2V0Q29ubmVjdGlvbjxUT3V0LCBUSW4+LFxuICAgIGdldENvbnRleHQ6ICgpID0+IFdlYlNvY2tldENvbnRleHQgfCBudWxsLFxuICApOiBXZWJTb2NrZXRDb25uZWN0aW9uPFRPdXQsIFRJbj4ge1xuICAgIGNvbnN0IHJ1bkluQ29udGV4dCA9IDxUPihjYWxsYmFjazogKCkgPT4gVCk6IFQgPT4ge1xuICAgICAgY29uc3QgY29udGV4dCA9IGdldENvbnRleHQoKTtcbiAgICAgIGlmICghY29udGV4dCkge1xuICAgICAgICByZXR1cm4gY2FsbGJhY2soKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXMuYXN5bmNMb2NhbFN0b3JhZ2UucnVuKHsgY29udGV4dCB9LCBjYWxsYmFjayk7XG4gICAgfTtcblxuICAgIHJldHVybiB7XG4gICAgICBnZXQgaWQoKSB7XG4gICAgICAgIHJldHVybiB3cy5pZDtcbiAgICAgIH0sXG4gICAgICBnZXQgbmFtZXNwYWNlKCkge1xuICAgICAgICByZXR1cm4gd3MubmFtZXNwYWNlO1xuICAgICAgfSxcbiAgICAgIGdldCBjbG9zZWQoKSB7XG4gICAgICAgIHJldHVybiB3cy5jbG9zZWQ7XG4gICAgICB9LFxuICAgICAgdHJhbnNwb3J0OiBcIndzXCIsXG4gICAgICBwdWJsaXNoVW50eXBlZChldmVudCwgZGF0YSkge1xuICAgICAgICB3cy5wdWJsaXNoVW50eXBlZChldmVudCwgZGF0YSk7XG4gICAgICB9LFxuICAgICAgY2xvc2UoY29kZSwgcmVhc29uKSB7XG4gICAgICAgIHdzLmNsb3NlKGNvZGUsIHJlYXNvbik7XG4gICAgICB9LFxuICAgICAgb25DbG9zZShjYWxsYmFjaykge1xuICAgICAgICB3cy5vbkNsb3NlKCgpID0+IHJ1bkluQ29udGV4dChjYWxsYmFjaykpO1xuICAgICAgfSxcbiAgICAgIG9uTWVzc2FnZShldmVudCwgaGFuZGxlcikge1xuICAgICAgICB3cy5vbk1lc3NhZ2UoZXZlbnQsIChkYXRhKSA9PiBydW5JbkNvbnRleHQoKCkgPT4gaGFuZGxlcihkYXRhKSkpO1xuICAgICAgfSxcbiAgICAgIHB1Ymxpc2goZXZlbnQsIGRhdGEpIHtcbiAgICAgICAgd3MucHVibGlzaChldmVudCwgZGF0YSk7XG4gICAgICB9LFxuICAgICAgd2FpdEZvckNsb3NlKCkge1xuICAgICAgICByZXR1cm4gd3Mud2FpdEZvckNsb3NlKCk7XG4gICAgICB9LFxuICAgICAgam9pbihyb29tSWQpIHtcbiAgICAgICAgd3Muam9pbihyb29tSWQpO1xuICAgICAgfSxcbiAgICAgIGxlYXZlKHJvb21JZCkge1xuICAgICAgICB3cy5sZWF2ZShyb29tSWQpO1xuICAgICAgfSxcbiAgICAgIHNldFVzZXJJZCh1c2VySWQpIHtcbiAgICAgICAgd3Muc2V0VXNlcklkKHVzZXJJZCk7XG4gICAgICB9LFxuICAgICAgY2xlYXJVc2VySWQoKSB7XG4gICAgICAgIHdzLmNsZWFyVXNlcklkKCk7XG4gICAgICB9LFxuICAgIH07XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIHBhcnNlV2ViU29ja2V0UmVxdWVzdFBhcmFtcyhcbiAgICBhcGk6IEV4dGVuZGVkQXBpLFxuICAgIHJlcXVlc3Q6IEZhc3RpZnlSZXF1ZXN0LFxuICApOiBQcm9taXNlPFJlY29yZDxzdHJpbmcsIHVua25vd24+PiB7XG4gICAgY29uc3QgeyBnZXRab2RPYmplY3RGcm9tQXBpIH0gPSBhd2FpdCBpbXBvcnQoXCIuL2NvZGUtY29udmVydGVyc1wiKTtcbiAgICBjb25zdCBSZXFUeXBlID0gZ2V0Wm9kT2JqZWN0RnJvbUFwaShhcGksIHRoaXMuc3luY2VyLnR5cGVzKTtcblxuICAgIHRyeSB7XG4gICAgICBjb25zdCB7IGZhc3RpZnlDYXN0ZXIgfSA9IGF3YWl0IGltcG9ydChcIi4vY2FzdGVyXCIpO1xuICAgICAgcmV0dXJuIGZhc3RpZnlDYXN0ZXIoUmVxVHlwZSkucGFyc2UoKHJlcXVlc3QucXVlcnkgPz8ge30pIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+KTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBjb25zdCB7IFpvZEVycm9yIH0gPSBhd2FpdCBpbXBvcnQoXCJ6b2RcIik7XG4gICAgICBpZiAoZSBpbnN0YW5jZW9mIFpvZEVycm9yKSB7XG4gICAgICAgIGNvbnN0IHsgaHVtYW5pemVab2RFcnJvciB9ID0gYXdhaXQgaW1wb3J0KFwiLi4vdXRpbHMvem9kLWVycm9yXCIpO1xuICAgICAgICBjb25zdCBtZXNzYWdlcyA9IGh1bWFuaXplWm9kRXJyb3IoZSlcbiAgICAgICAgICAubWFwKChpc3N1ZSkgPT4gaXNzdWUubWVzc2FnZSlcbiAgICAgICAgICAuam9pbihcIiBcIik7XG4gICAgICAgIGNvbnN0IHsgQmFkUmVxdWVzdEV4Y2VwdGlvbiB9ID0gYXdhaXQgaW1wb3J0KFwiLi4vZXhjZXB0aW9ucy9zby1leGNlcHRpb25zXCIpO1xuICAgICAgICB0aHJvdyBuZXcgQmFkUmVxdWVzdEV4Y2VwdGlvbihtZXNzYWdlcyBhcyBMb2NhbGl6ZWRTdHJpbmcsIHtcbiAgICAgICAgICB6b2RFcnJvcjogZSxcbiAgICAgICAgfSk7XG4gICAgICB9XG5cbiAgICAgIHRocm93IGU7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFVSTOyXkOyEnCBwYXRoIHBhcmFtc+ulvCDstpTstpztlanri4jri6QuXG4gICAqIOyYiDogcGF0dGVybj1cIi9hZG1pbi9jb21wYW5pZXMvOmNvbXBhbnlJZFwiLCB1cmw9XCIvYWRtaW4vY29tcGFuaWVzLzEyM1wiIOKGkiB7IGNvbXBhbnlJZDogXCIxMjNcIiB9XG4gICAqL1xuICBwcml2YXRlIGV4dHJhY3RQYXRoUGFyYW1zKHBhdHRlcm46IHN0cmluZywgdXJsOiBzdHJpbmcpOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+IHtcbiAgICBjb25zdCBwYXR0ZXJuUGFydHMgPSBwYXR0ZXJuLnNwbGl0KFwiL1wiKS5maWx0ZXIoQm9vbGVhbik7XG4gICAgY29uc3QgdXJsUGFydHMgPSB0aGlzLmdldFBhdGhuYW1lRnJvbVVybCh1cmwpLnNwbGl0KFwiL1wiKS5maWx0ZXIoQm9vbGVhbik7XG4gICAgY29uc3QgcGFyYW1zOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+ID0ge307XG5cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHBhdHRlcm5QYXJ0cy5sZW5ndGg7IGkrKykge1xuICAgICAgaWYgKHBhdHRlcm5QYXJ0c1tpXS5zdGFydHNXaXRoKFwiOlwiKSkge1xuICAgICAgICBwYXJhbXNbcGF0dGVyblBhcnRzW2ldLnNsaWNlKDEpXSA9IHVybFBhcnRzW2ldO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gcGFyYW1zO1xuICB9XG5cbiAgcHJpdmF0ZSBpc1BhdGhQYXR0ZXJuTWF0Y2gocGF0dGVybjogc3RyaW5nLCB1cmw6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIGNvbnN0IHBhdHRlcm5QYXJ0cyA9IHBhdHRlcm4uc3BsaXQoXCIvXCIpLmZpbHRlcihCb29sZWFuKTtcbiAgICBjb25zdCB1cmxQYXJ0cyA9IHRoaXMuZ2V0UGF0aG5hbWVGcm9tVXJsKHVybCkuc3BsaXQoXCIvXCIpLmZpbHRlcihCb29sZWFuKTtcblxuICAgIGlmIChwYXR0ZXJuUGFydHMubGVuZ3RoICE9PSB1cmxQYXJ0cy5sZW5ndGgpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHBhdHRlcm5QYXJ0cy5sZW5ndGg7IGkrKykge1xuICAgICAgY29uc3QgcGF0dGVyblBhcnQgPSBwYXR0ZXJuUGFydHNbaV07XG4gICAgICBjb25zdCB1cmxQYXJ0ID0gdXJsUGFydHNbaV07XG4gICAgICBpZiAocGF0dGVyblBhcnQuc3RhcnRzV2l0aChcIjpcIikpIHtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG4gICAgICBpZiAocGF0dGVyblBhcnQgIT09IHVybFBhcnQpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXRQYXRobmFtZUZyb21VcmwodXJsOiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIHJldHVybiB1cmwuc3BsaXQoXCI/XCIpWzBdO1xuICB9XG5cbiAgcHJpdmF0ZSByZXNvbHZlUGF0aFdpdGhpbkJhc2VEaXIoYmFzZURpcjogc3RyaW5nLCBpbnB1dFBhdGg6IHN0cmluZyk6IHN0cmluZyB8IG51bGwge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBkZWNvZGVkID0gZGVjb2RlVVJJQ29tcG9uZW50KGlucHV0UGF0aCkucmVwbGFjZSgvXFxcXC9nLCBcIi9cIik7XG4gICAgICBpZiAoZGVjb2RlZC5pbmNsdWRlcyhcIlxcMFwiKSkge1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgIH1cbiAgICAgIGNvbnN0IHJlbGF0aXZlUGF0aCA9IGRlY29kZWQucmVwbGFjZSgvXlxcLysvLCBcIlwiKTtcbiAgICAgIGNvbnN0IHJlc29sdmVkUGF0aCA9IHBhdGgucmVzb2x2ZShiYXNlRGlyLCByZWxhdGl2ZVBhdGgpO1xuICAgICAgY29uc3QgcmVsYXRpdmVGcm9tQmFzZSA9IHBhdGgucmVsYXRpdmUoYmFzZURpciwgcmVzb2x2ZWRQYXRoKTtcbiAgICAgIGlmIChyZWxhdGl2ZUZyb21CYXNlLnN0YXJ0c1dpdGgoXCIuLlwiKSB8fCBwYXRoLmlzQWJzb2x1dGUocmVsYXRpdmVGcm9tQmFzZSkpIHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICB9XG4gICAgICByZXR1cm4gcmVzb2x2ZWRQYXRoO1xuICAgIH0gY2F0Y2gge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEFQSSDsnZHri7Xsl5Ag7KCB7Jqp7ZWgIENhY2hlLUNvbnRyb2wg7ISk7KCV7J2EIOqysOygle2VqeuLiOuLpC5cbiAgICog7Jqw7ISg7Iic7JyEOiDqsJzrs4Qg7KeA7KCVID4gY2FjaGVDb250cm9sSGFuZGxlclxuICAgKi9cbiAgcHJpdmF0ZSBnZXRBcGlDYWNoZUNvbnRyb2woXG4gICAgYXBpOiBFeHRlbmRlZEFwaSxcbiAgICByZXF1ZXN0OiBGYXN0aWZ5UmVxdWVzdCxcbiAgICBjb25maWc6IFNvbmFtdUZhc3RpZnlDb25maWcsXG4gICkge1xuICAgIC8vIOuNsOy9lOugiOydtO2EsCDshKTsoJUg7Jqw7ISgXG4gICAgaWYgKGFwaS5vcHRpb25zLmNhY2hlQ29udHJvbCkge1xuICAgICAgcmV0dXJuIGFwaS5vcHRpb25zLmNhY2hlQ29udHJvbDtcbiAgICB9XG5cbiAgICAvLyDsoITsl60g7ZW465Ok65+sXG4gICAgaWYgKGNvbmZpZy5jYWNoZUNvbnRyb2xIYW5kbGVyKSB7XG4gICAgICBjb25zdCBjYWNoZVJlcTogQ2FjaGVDb250cm9sUmVxdWVzdCA9IHtcbiAgICAgICAgdHlwZTogXCJhcGlcIixcbiAgICAgICAgdXJsOiByZXF1ZXN0LnVybCxcbiAgICAgICAgcGF0aDogcmVxdWVzdC5yb3V0ZU9wdGlvbnM/LnVybCA/PyByZXF1ZXN0LnVybC5zcGxpdChcIj9cIilbMF0sXG4gICAgICAgIG1ldGhvZDogcmVxdWVzdC5tZXRob2QsXG4gICAgICAgIGFwaSxcbiAgICAgIH07XG4gICAgICBjb25zdCByZXN1bHQgPSBjb25maWcuY2FjaGVDb250cm9sSGFuZGxlcihjYWNoZVJlcSk7XG4gICAgICBpZiAocmVzdWx0KSByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgLyoqXG4gICAqIFNTUuyaqSBBUEkg7Zi47LacIChIVFRQIOyYpOuyhO2XpOuTnCDsl4bsnbQg7KeB7KCRIO2YuOy2nClcbiAgICogY3JlYXRlQXBpSGFuZGxlcuydmCDroZzsp4HsnYQg7J6s7IKs7Jqp7ZWY65CYLCByZXF1ZXN0IO2MjOyLsSDrjIDsi6AgcGFyYW1zIOyngeygkSDsgqzsmqlcbiAgICovXG4gIGFzeW5jIGludm9rZUFwaUZvclNTUihcbiAgICBhcGk6IEV4dGVuZGVkQXBpLFxuICAgIHBhcmFtczogYW55W10sXG4gICAgY29uZmlnOiBTb25hbXVGYXN0aWZ5Q29uZmlnLFxuICAgIHJlcXVlc3Q6IEZhc3RpZnlSZXF1ZXN0LFxuICAgIHJlcGx5OiBGYXN0aWZ5UmVwbHksXG4gICk6IFByb21pc2U8dW5rbm93bj4ge1xuICAgIC8vIENvbnRleHQg7IOd7ISxICjquLDsobQg66mU7IaM65OcIOyerOyCrOyaqSlcbiAgICBjb25zdCBjb250ZXh0ID0gYXdhaXQgdGhpcy5jcmVhdGVDb250ZXh0KGNvbmZpZywgcmVxdWVzdCwgcmVwbHkpO1xuXG4gICAgcmV0dXJuIHRoaXMuYXN5bmNMb2NhbFN0b3JhZ2UucnVuKHsgY29udGV4dCB9LCBhc3luYyAoKSA9PiB7XG4gICAgICAvLyBhcmdzIOyDneyEsTogQ29udGV4dCDtjIzrnbzrr7jthLDripQg7KO87J6FLCDrgpjrqLjsp4DripQgcGFyYW1z7JeQ7IScIOqwgOyguOyYpOq4sFxuICAgICAgY29uc3QgeyBBcGlQYXJhbVR5cGUgfSA9IGF3YWl0IGltcG9ydChcIi4uL3R5cGVzL3R5cGVzXCIpO1xuICAgICAgbGV0IHBhcmFtc0luZGV4ID0gMDtcbiAgICAgIGNvbnN0IGFyZ3MgPSBhcGkucGFyYW1ldGVycy5tYXAoKHBhcmFtKSA9PiB7XG4gICAgICAgIGlmIChBcGlQYXJhbVR5cGUuaXNDb250ZXh0KHBhcmFtLnR5cGUpKSB7XG4gICAgICAgICAgcmV0dXJuIGNvbnRleHQ7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHBhcmFtc1twYXJhbXNJbmRleCsrXTtcbiAgICAgIH0pO1xuXG4gICAgICAvLyDrqqjrjbgg66mU7ISc65OcIO2YuOy2nCAo6riw7KG0IOuplOyEnOuTnCDsnqzsgqzsmqkpXG4gICAgICByZXR1cm4gdGhpcy5pbnZva2VNb2RlbE1ldGhvZChhcGksIGFyZ3MsIHJlcGx5KTtcbiAgICB9KTtcbiAgfVxuXG4gIC8vIFdTIOqyveuhnOyXkOyEnOuKlCBIVFRQIHJlcGx56rCAIOyXhuycvOuvgOuhnCByZXBseeulvCBvcHRpb25hbOuhnCDrsJvslYQg6rO17Ya1IO2YuOy2nCDqsr3roZzrpbwg7Jyg7KeA7ZWoXG4gIGFzeW5jIGludm9rZU1vZGVsTWV0aG9kKFxuICAgIGFwaTogRXh0ZW5kZWRBcGksXG4gICAgYXJnczogdW5rbm93bltdLFxuICAgIHJlcGx5PzogRmFzdGlmeVJlcGx5LFxuICApOiBQcm9taXNlPHVua25vd24+IHtcbiAgICBjb25zdCBtb2RlbCA9IHRoaXMuc3luY2VyLm1vZGVsc1thcGkubW9kZWxOYW1lXTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCAobW9kZWwgYXMgYW55KVthcGkubWV0aG9kTmFtZV0uYXBwbHkobW9kZWwsIGFyZ3MpO1xuICAgIHJlcGx5Py50eXBlKGFwaS5vcHRpb25zLmNvbnRlbnRUeXBlID8/IFwiYXBwbGljYXRpb24vanNvblwiKTtcblxuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICBhc3luYyBjcmVhdGVDb250ZXh0KFxuICAgIGNvbmZpZzogU29uYW11RmFzdGlmeUNvbmZpZyxcbiAgICByZXF1ZXN0OiBGYXN0aWZ5UmVxdWVzdCxcbiAgICByZXBseTogRmFzdGlmeVJlcGx5LFxuICApOiBQcm9taXNlPENvbnRleHQ+IHtcbiAgICAvLyBjcmVhdGVTU0VGYWN0b3J5IO2VqOyImOyXkCDrr7jrpqwgcmVxdWVzdOydmCBzb2NrZXTqs7wgcmVwbHnrpbwg67CU7J2465SpLlxuICAgIGNvbnN0IHsgY3JlYXRlU1NFRmFjdG9yeSB9ID0gYXdhaXQgaW1wb3J0KFwiLi4vc3RyZWFtL3NzZVwiKTtcbiAgICBjb25zdCBjcmVhdGVTU0UgPSAoPFQgZXh0ZW5kcyBab2RPYmplY3Q+KFxuICAgICAgX3JlcXVlc3Q6IEZhc3RpZnlSZXF1ZXN0LFxuICAgICAgX3JlcGx5OiBGYXN0aWZ5UmVwbHksXG4gICAgICBfZXZlbnRzOiBULFxuICAgICkgPT4gY3JlYXRlU1NFRmFjdG9yeShfcmVxdWVzdC5zb2NrZXQsIF9yZXBseSwgX2V2ZW50cykpLmJpbmQobnVsbCwgcmVxdWVzdCwgcmVwbHkpO1xuXG4gICAgLy8gbG9jYWxlIOqwkOyngFxuICAgIGNvbnN0IGxvY2FsZSA9XG4gICAgICB0aGlzLmRldGVjdExvY2FsZShyZXF1ZXN0LmhlYWRlcnNbXCJhY2NlcHQtbGFuZ3VhZ2VcIl0sIHRoaXMuY29uZmlnLmkxOG4uc3VwcG9ydGVkTG9jYWxlcykgPz9cbiAgICAgIHRoaXMuY29uZmlnLmkxOG4uZGVmYXVsdExvY2FsZTtcblxuICAgIC8vIGF1dGggY29udGV4dCDstpTqsIBcbiAgICBjb25zdCBoZWFkZXJzID0gY29udmVydEZhc3RpZnlIZWFkZXJzVG9TdGFuZGFyZChyZXF1ZXN0LmhlYWRlcnMpO1xuICAgIGNvbnN0IHNlc3Npb24gPSAoYXdhaXQgdGhpcy5fYXV0aD8uYXBpLmdldFNlc3Npb24oeyBoZWFkZXJzIH0pKSA/PyBudWxsO1xuXG4gICAgY29uc3QgY29udGV4dDogQ29udGV4dCA9IGF3YWl0IFByb21pc2UucmVzb2x2ZShcbiAgICAgIGNvbmZpZy5jb250ZXh0UHJvdmlkZXIoXG4gICAgICAgIHtcbiAgICAgICAgICB0cmFuc3BvcnQ6IFwiaHR0cFwiLFxuICAgICAgICAgIHJlcXVlc3QsXG4gICAgICAgICAgcmVwbHksXG4gICAgICAgICAgaGVhZGVyczogcmVxdWVzdC5oZWFkZXJzLFxuICAgICAgICAgIGNyZWF0ZVNTRSxcbiAgICAgICAgICBuYWl0ZVN0b3JlOiBuZXcgTWFwKCksXG4gICAgICAgICAgbG9jYWxlLFxuICAgICAgICAgIC8vIGF1dGhcbiAgICAgICAgICB1c2VyOiBzZXNzaW9uPy51c2VyID8/IG51bGwsXG4gICAgICAgICAgc2Vzc2lvbjogc2Vzc2lvbj8uc2Vzc2lvbiA/PyBudWxsLFxuICAgICAgICB9LFxuICAgICAgICByZXF1ZXN0LFxuICAgICAgICByZXBseSxcbiAgICAgICksXG4gICAgKTtcbiAgICByZXR1cm4gY29udGV4dDtcbiAgfVxuXG4gIC8vIHNlc3Npb24vbG9jYWxlL3N0b3JlIOqwmeydgCDqs7XthrUgc3RhdGXripQgSFRUUCBjb250ZXh07JmAIOqzteycoO2VmOuQmCwgcmVwbHkvY3JlYXRlU1NFIOqwmeydgCBIVFRQIOyghOyaqSBoZWxwZXLripQg64W47Lac7ZWY7KeAIOyViuydjFxuICAvLyDsgqzsmqnsnpDqsIAgd2Vic29ja2V0Q29udGV4dFByb3ZpZGVy66W8IOyjvOuptCDqt7jrjIDroZwg7JyE7J6E7ZWY6rOgLCDsl4bsnLzrqbQg6riw7KG0IGNvbnRleHRQcm92aWRlcuulvCByZXBseS9TU0Ugc3R1YuqzvCDtlajqu5gg7J6s7Zmc7Jqp7ZWoXG4gIGFzeW5jIGNyZWF0ZVdlYlNvY2tldENvbnRleHQoXG4gICAgY29uZmlnOiBTb25hbXVGYXN0aWZ5Q29uZmlnLFxuICAgIHJlcXVlc3Q6IEZhc3RpZnlSZXF1ZXN0LFxuICAgIHdzOiBXZWJTb2NrZXRDb250ZXh0W1wid3NcIl0sXG4gICk6IFByb21pc2U8V2ViU29ja2V0Q29udGV4dD4ge1xuICAgIGNvbnN0IGxvY2FsZSA9XG4gICAgICB0aGlzLmRldGVjdExvY2FsZShyZXF1ZXN0LmhlYWRlcnNbXCJhY2NlcHQtbGFuZ3VhZ2VcIl0sIHRoaXMuY29uZmlnLmkxOG4uc3VwcG9ydGVkTG9jYWxlcykgPz9cbiAgICAgIHRoaXMuY29uZmlnLmkxOG4uZGVmYXVsdExvY2FsZTtcblxuICAgIGNvbnN0IGhlYWRlcnMgPSBjb252ZXJ0RmFzdGlmeUhlYWRlcnNUb1N0YW5kYXJkKHJlcXVlc3QuaGVhZGVycyk7XG4gICAgY29uc3Qgc2Vzc2lvbiA9IChhd2FpdCB0aGlzLl9hdXRoPy5hcGkuZ2V0U2Vzc2lvbih7IGhlYWRlcnMgfSkpID8/IG51bGw7XG5cbiAgICBjb25zdCBkZWZhdWx0Q29udGV4dCA9IHtcbiAgICAgIHRyYW5zcG9ydDogXCJ3c1wiIGFzIGNvbnN0LFxuICAgICAgcmVxdWVzdCxcbiAgICAgIGhlYWRlcnM6IHJlcXVlc3QuaGVhZGVycyxcbiAgICAgIHdzLFxuICAgICAgbmFpdGVTdG9yZTogbmV3IE1hcCgpLFxuICAgICAgbG9jYWxlLFxuICAgICAgdXNlcjogc2Vzc2lvbj8udXNlciA/PyBudWxsLFxuICAgICAgc2Vzc2lvbjogc2Vzc2lvbj8uc2Vzc2lvbiA/PyBudWxsLFxuICAgIH07XG5cbiAgICBpZiAoY29uZmlnLndlYnNvY2tldENvbnRleHRQcm92aWRlcikge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgLi4uKGF3YWl0IFByb21pc2UucmVzb2x2ZShjb25maWcud2Vic29ja2V0Q29udGV4dFByb3ZpZGVyKGRlZmF1bHRDb250ZXh0LCByZXF1ZXN0KSkpLFxuICAgICAgfTtcbiAgICB9XG5cbiAgICAvLyByZXBseS9jcmVhdGVTU0Xsl5Ag7J2Y7KG07ZWY64qUIGNvbnRleHRQcm92aWRlcuqwgCDsnojsnLzrqbQg7KaJ7IucIOyXkOufrOulvCDrjZjsoLggdHJhbnNwb3J0IG1pc3VzZeulvCDruajrpqwg65Oc65+s64OEXG4gICAgY29uc3QgcmVwbHlTdHViID0gY3JlYXRlV2ViU29ja2V0UmVwbHlTdHViKCk7XG4gICAgY29uc3QgY3JlYXRlU1NFID0gPFQgZXh0ZW5kcyBab2RPYmplY3Q+KF9ldmVudHM6IFQpID0+IHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgXCJjcmVhdGVTU0UgaXMgbm90IGF2YWlsYWJsZSBpbiB3ZWJzb2NrZXQgY29udGV4dC4gRGVmaW5lIHdlYnNvY2tldENvbnRleHRQcm92aWRlciBpZiB5b3VyIGNvbnRleHQgc2V0dXAgZGVwZW5kcyBvbiBTU0UgaGVscGVycy5cIixcbiAgICAgICk7XG4gICAgfTtcbiAgICBjb25zdCBodHRwTGlrZUNvbnRleHQgPSBhd2FpdCBQcm9taXNlLnJlc29sdmUoXG4gICAgICBjb25maWcuY29udGV4dFByb3ZpZGVyKFxuICAgICAgICB7XG4gICAgICAgICAgdHJhbnNwb3J0OiBcImh0dHBcIixcbiAgICAgICAgICByZXF1ZXN0LFxuICAgICAgICAgIHJlcGx5OiByZXBseVN0dWIsXG4gICAgICAgICAgaGVhZGVyczogcmVxdWVzdC5oZWFkZXJzLFxuICAgICAgICAgIGNyZWF0ZVNTRSxcbiAgICAgICAgICBuYWl0ZVN0b3JlOiBkZWZhdWx0Q29udGV4dC5uYWl0ZVN0b3JlLFxuICAgICAgICAgIGxvY2FsZSxcbiAgICAgICAgICB1c2VyOiBkZWZhdWx0Q29udGV4dC51c2VyLFxuICAgICAgICAgIHNlc3Npb246IGRlZmF1bHRDb250ZXh0LnNlc3Npb24sXG4gICAgICAgIH0sXG4gICAgICAgIHJlcXVlc3QsXG4gICAgICAgIHJlcGx5U3R1YixcbiAgICAgICksXG4gICAgKTtcblxuICAgIGNvbnN0IHtcbiAgICAgIHRyYW5zcG9ydDogX3RyYW5zcG9ydCxcbiAgICAgIHJlcGx5OiBfcmVwbHksXG4gICAgICBjcmVhdGVTU0U6IF9jcmVhdGVTU0UsXG4gICAgICBidWZmZXJlZEZpbGVzOiBfYnVmZmVyZWRGaWxlcyxcbiAgICAgIHVwbG9hZGVkRmlsZXM6IF91cGxvYWRlZEZpbGVzLFxuICAgICAgLi4ucmVzdFxuICAgIH0gPSBodHRwTGlrZUNvbnRleHQ7XG5cbiAgICByZXR1cm4ge1xuICAgICAgLi4ucmVzdCxcbiAgICAgIHRyYW5zcG9ydDogXCJ3c1wiLFxuICAgICAgcmVxdWVzdCxcbiAgICAgIGhlYWRlcnM6IHJlcXVlc3QuaGVhZGVycyxcbiAgICAgIHdzLFxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogQWNjZXB0LUxhbmd1YWdlIO2XpOuNlOyXkOyEnCDsp4Dsm5DtlZjripQgbG9jYWxl7J2EIOywvuyKteuLiOuLpC5cbiAgICogQGV4YW1wbGUgXCJrby1LUixrbztxPTAuOSxlbjtxPTAuOFwiIOKGkiBcImtvXCJcbiAgICovXG4gIHByaXZhdGUgZGV0ZWN0TG9jYWxlKFxuICAgIGFjY2VwdExhbmd1YWdlOiBzdHJpbmcgfCB1bmRlZmluZWQsXG4gICAgc3VwcG9ydGVkOiBzdHJpbmdbXSxcbiAgKTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgICBpZiAoIWFjY2VwdExhbmd1YWdlKSByZXR1cm4gdW5kZWZpbmVkO1xuXG4gICAgLy8gQWNjZXB0LUxhbmd1YWdlOiBrby1LUixrbztxPTAuOSxlbjtxPTAuOFxuICAgIGNvbnN0IGxhbmdzID0gYWNjZXB0TGFuZ3VhZ2Uuc3BsaXQoXCIsXCIpLm1hcCgobGFuZykgPT4ge1xuICAgICAgY29uc3QgW2NvZGVdID0gbGFuZy5zcGxpdChcIjtcIik7XG4gICAgICByZXR1cm4gY29kZS50cmltKCkuc3BsaXQoXCItXCIpWzBdOyAvLyBrby1LUiDihpIga29cbiAgICB9KTtcblxuICAgIHJldHVybiBsYW5ncy5maW5kKChsYW5nKSA9PiBzdXBwb3J0ZWQuaW5jbHVkZXMobGFuZykpO1xuICB9XG5cbiAgYXN5bmMgc3RhcnRXYXRjaGVyKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIC8vIHdhdGNoZXIg66qo65OI7J2AIGZpbGUtcGF0dGVybnMg4oaSIFNvbmFtdSDsiJztmZjsnYQg7ZS87ZWY6riwIOychO2VtCBkeW5hbWljIGltcG9ydCDtlanri4jri6QuXG4gICAgY29uc3QgeyBzZXR1cFdhdGNoZXIgfSA9IGF3YWl0IGltcG9ydChcIi4uL3N5bmNlci93YXRjaGVyXCIpO1xuICAgIHRoaXMud2F0Y2hlciA9IGF3YWl0IHNldHVwV2F0Y2hlcigoZmlsZUV2ZW50cykgPT4gdGhpcy5ydW5IbXJTeW5jQ3ljbGUoZmlsZUV2ZW50cykpO1xuICB9XG5cbiAgLyoqXG4gICAqIFdhdGNoZXLqsIAgMTAwbXMgYmF0Y2jroZwg66qo7J2AIGZpbGVFdmVudHMg7ZWY64KY7JeQIOuMgO2VtCDtlZwg67KI7J2YIEhNUi9zeW5jIOyCrOydtO2BtOydhCDrj5Xri4jri6QuXG4gICAqIGJhdGNoIO2BkOyeiSDrjZXsl5Ag7ZWcIOyLnOygkOyXkCDtlZjrgpjrp4wg7Iuk7ZaJ65Co7J20IOuztOyepeuQqeuLiOuLpCAoZXZlbnQtYmF0Y2hlcuqwgCDsp4HroKztmZQpLlxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyBydW5IbXJTeW5jQ3ljbGUoZmlsZUV2ZW50czogTWFwPEFic29sdXRlUGF0aCwgXCJjaGFuZ2VcIiB8IFwiYWRkXCI+KTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3Qgc3RhcnRlZEF0ID0gRGF0ZS5ub3coKTtcblxuICAgIGZvciAoY29uc3QgW2ZpbGVQYXRoLCBldmVudF0gb2YgZmlsZUV2ZW50cykge1xuICAgICAgY29uc3QgcmVsYXRpdmVQYXRoID0gcGF0aC5yZWxhdGl2ZSh0aGlzLmFwcFJvb3RQYXRoLCBmaWxlUGF0aCk7XG4gICAgICBjb25zb2xlLmxvZyhjaGFsay5ib2xkKGBEZXRlY3RlZCgke2V2ZW50fSk6ICR7Y2hhbGsuYmx1ZShyZWxhdGl2ZVBhdGgpfWApKTtcbiAgICB9XG5cbiAgICAvLyDrs7jssrQ6IOuzgOqyvSDtnaHsiJggKyDssrTtgazshKwg6rCx7IugLlxuICAgIGF3YWl0IHRoaXMuc3luY2VyLmhtckFuZFN5bmMoZmlsZUV2ZW50cyk7XG4gICAgYXdhaXQgdGhpcy5zeW5jZXIucmVuZXdDaGVja3N1bXMoKTtcblxuICAgIGNvbnN0IHRvdGFsVGltZSA9IERhdGUubm93KCkgLSBzdGFydGVkQXQ7XG4gICAgY29uc3QgbXNnID0gYEhNUiBEb25lISAke2NoYWxrLmJvbGQud2hpdGUoYCR7dG90YWxUaW1lfW1zYCl9YDtcbiAgICBjb25zb2xlLmxvZyhjaGFsay5ibGFjay5iZ0dyZWVuKGNlbnRlclRleHQobXNnKSkpO1xuICB9XG5cbiAgLypcbiAgICAgQSBmdW5jdGlvbiB0aGF0IGF1dG9tYXRpY2FsbHkgaGFuZGxlcyBpbml0IGFuZCBkZXN0cm95IHdoZW4gdXNpbmcgU29uYW11IHZpYSBzY3JpcHRzLlxuICAqL1xuICBhc3luYyBydW5TY3JpcHQoZm46ICgpID0+IFByb21pc2U8dm9pZD4pIHtcbiAgICBhd2FpdCB0aGlzLmluaXQodHJ1ZSwgZmFsc2UsIHVuZGVmaW5lZCwgZmFsc2UpO1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCBmbigpO1xuICAgIH0gZmluYWxseSB7XG4gICAgICBhd2FpdCB0aGlzLmRlc3Ryb3koKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIHJlZ2lzdGVyUGx1Z2lucyhzZXJ2ZXI6IEZhc3RpZnlJbnN0YW5jZSwgcGx1Z2luczogU29uYW11U2VydmVyT3B0aW9uc1tcInBsdWdpbnNcIl0pIHtcbiAgICBpZiAoIXBsdWdpbnMpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBjb21wcmVzcyDtlIzrn6zqt7jsnbjsnYAg64uk66W4IO2UjOufrOq3uOyduOuztOuLpCDrqLzsoIAg65Ox66Gd65CY7Ja07JW8IO2VqeuLiOuLpC5cbiAgICBpZiAocGx1Z2lucy5jb21wcmVzcykge1xuICAgICAgY29uc3QgY29tcHJlc3NQbHVnaW4gPSAoYXdhaXQgaW1wb3J0KFwiQGZhc3RpZnkvY29tcHJlc3NcIikpLmRlZmF1bHQ7XG4gICAgICBjb25zdCBkZWZhdWx0T3B0aW9ucyA9IHtcbiAgICAgICAgdGhyZXNob2xkOiAxMDI0LFxuICAgICAgICBlbmNvZGluZ3M6IFtcImJyXCIsIFwiZ3ppcFwiLCBcImRlZmxhdGVcIl0gYXMgKFwiYnJcIiB8IFwiZ3ppcFwiIHwgXCJkZWZsYXRlXCIpW10sXG4gICAgICB9O1xuXG4gICAgICBpZiAocGx1Z2lucy5jb21wcmVzcyA9PT0gdHJ1ZSkge1xuICAgICAgICBzZXJ2ZXIucmVnaXN0ZXIoY29tcHJlc3NQbHVnaW4sIGRlZmF1bHRPcHRpb25zKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHNlcnZlci5yZWdpc3Rlcihjb21wcmVzc1BsdWdpbiwge1xuICAgICAgICAgIC4uLmRlZmF1bHRPcHRpb25zLFxuICAgICAgICAgIC4uLnBsdWdpbnMuY29tcHJlc3MsXG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIGNvbnN0IHBsdWdpbnNNb2R1bGVzID0ge1xuICAgICAgY29yczogXCJAZmFzdGlmeS9jb3JzXCIsXG4gICAgICBmb3JtYm9keTogXCJAZmFzdGlmeS9mb3JtYm9keVwiLFxuICAgICAgbXVsdGlwYXJ0OiBcIkBmYXN0aWZ5L211bHRpcGFydFwiLFxuICAgICAgcXM6IFwiZmFzdGlmeS1xc1wiLFxuICAgICAgc3NlOiBcImZhc3RpZnktc3NlLXYyXCIsXG4gICAgICBzdGF0aWM6IFwiQGZhc3RpZnkvc3RhdGljXCIsXG4gICAgfSBhcyBjb25zdDtcblxuICAgIGNvbnN0IHJlZ2lzdGVyUGx1Z2luID0gYXN5bmMgPEsgZXh0ZW5kcyBrZXlvZiBOb25OdWxsYWJsZTx0eXBlb2YgcGx1Z2lucz4+KFxuICAgICAga2V5OiBLLFxuICAgICAgcGx1Z2luTmFtZTogc3RyaW5nLFxuICAgICkgPT4ge1xuICAgICAgY29uc3Qgb3B0aW9uID0gcGx1Z2luc1trZXldO1xuICAgICAgaWYgKCFvcHRpb24pIHJldHVybjtcblxuICAgICAgaWYgKG9wdGlvbiA9PT0gdHJ1ZSkge1xuICAgICAgICBzZXJ2ZXIucmVnaXN0ZXIoKGF3YWl0IGltcG9ydChwbHVnaW5OYW1lKSkuZGVmYXVsdCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBzZXJ2ZXIucmVnaXN0ZXIoKGF3YWl0IGltcG9ydChwbHVnaW5OYW1lKSkuZGVmYXVsdCwgb3B0aW9uKTtcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgZm9yIChjb25zdCBba2V5LCBwbHVnaW5OYW1lXSBvZiBPYmplY3QuZW50cmllcyhwbHVnaW5zTW9kdWxlcykpIHtcbiAgICAgIGF3YWl0IHJlZ2lzdGVyUGx1Z2luKGtleSBhcyBrZXlvZiB0eXBlb2YgcGx1Z2lucywgcGx1Z2luTmFtZSk7XG4gICAgfVxuXG4gICAgaWYgKHBsdWdpbnMud3MpIHtcbiAgICAgIGF3YWl0IHRoaXMuZW5zdXJlV2ViU29ja2V0UGx1Z2luKHNlcnZlcik7XG4gICAgfVxuXG4gICAgaWYgKHBsdWdpbnMuY3VzdG9tKSB7XG4gICAgICBwbHVnaW5zLmN1c3RvbShzZXJ2ZXIpO1xuICAgIH1cbiAgfVxuXG4gIC8vIEBmYXN0aWZ5L3dlYnNvY2tldOydgCBwbHVnaW5zLndz6rCAIOyEpOygleuQnCDqsr3smrDsl5Drp4wg65Ox66Gd7ZWY6rOgLCDqsJnsnYAgc2VydmVy7JeQIOykkeuztSDrk7HroZ3rkJjsp4Ag7JWK64+E66GdIFdlYWtTZXTsnLzroZwg6riw66Gd7ZWoXG4gIHByaXZhdGUgYXN5bmMgZW5zdXJlV2ViU29ja2V0UGx1Z2luKFxuICAgIHNlcnZlcjogRmFzdGlmeUluc3RhbmNlPFNlcnZlciwgSW5jb21pbmdNZXNzYWdlLCBTZXJ2ZXJSZXNwb25zZT4sXG4gICk6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmICh0aGlzLndlYnNvY2tldFBsdWdpblNlcnZlcnMuaGFzKHNlcnZlcikpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCBwbHVnaW5PcHRpb24gPSB0aGlzLmNvbmZpZy5zZXJ2ZXIucGx1Z2lucz8ud3M7XG4gICAgaWYgKCFwbHVnaW5PcHRpb24pIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCB3ZWJzb2NrZXRQbHVnaW4gPSAoYXdhaXQgaW1wb3J0KFwiQGZhc3RpZnkvd2Vic29ja2V0XCIpKS5kZWZhdWx0O1xuICAgIGNvbnN0IHJlc29sdmVkUGx1Z2luT3B0aW9ucyA9IHJlc29sdmVXZWJTb2NrZXRQbHVnaW5PcHRpb25zKHtcbiAgICAgIHJhd1BsdWdpbk9wdGlvbjogcGx1Z2luT3B0aW9uLFxuICAgICAgYXBpczogdGhpcy5zeW5jZXIuYXBpcyxcbiAgICB9KTtcbiAgICBpZiAocmVzb2x2ZWRQbHVnaW5PcHRpb25zKSB7XG4gICAgICBhd2FpdCBzZXJ2ZXIucmVnaXN0ZXIod2Vic29ja2V0UGx1Z2luLCByZXNvbHZlZFBsdWdpbk9wdGlvbnMpO1xuICAgIH0gZWxzZSB7XG4gICAgICBhd2FpdCBzZXJ2ZXIucmVnaXN0ZXIod2Vic29ja2V0UGx1Z2luKTtcbiAgICB9XG5cbiAgICB0aGlzLndlYnNvY2tldFBsdWdpblNlcnZlcnMuYWRkKHNlcnZlcik7XG4gICAgdGhpcy53YXJuT25Qb3RlbnRpYWxXZWJTb2NrZXRUaW1lb3V0Q29uZmxpY3RzKHNlcnZlcik7XG4gIH1cblxuICAvLyBoZWFydGJlYXQgaW50ZXJ2YWzsnbQgRmFzdGlmeSBrZWVwQWxpdmVUaW1lb3V0IOydtOyDgeydtOuptCDsnbjtlITrnbzqsIAg66i87KCAIGlkbGUg7Jew6rKw7J2EIOuBiuydhCDsiJgg7J6I7Ja0IOqyveqzoOunjCDrgqjquLDqs6Ag64SY7Ja06rCQXG4gIHByaXZhdGUgd2Fybk9uUG90ZW50aWFsV2ViU29ja2V0VGltZW91dENvbmZsaWN0cyhcbiAgICBzZXJ2ZXI6IEZhc3RpZnlJbnN0YW5jZTxTZXJ2ZXIsIEluY29taW5nTWVzc2FnZSwgU2VydmVyUmVzcG9uc2U+LFxuICApOiB2b2lkIHtcbiAgICBjb25zdCBoZWFydGJlYXRzID0gdGhpcy5zeW5jZXIuYXBpc1xuICAgICAgLm1hcCgoYXBpKSA9PiBhcGkud2Vic29ja2V0T3B0aW9ucz8uaGVhcnRiZWF0ID8/IDMwMDAwKVxuICAgICAgLmZpbHRlcigoaGVhcnRiZWF0KSA9PiBoZWFydGJlYXQgPiAwKTtcblxuICAgIGlmIChoZWFydGJlYXRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IGtlZXBBbGl2ZVRpbWVvdXQgPSB0aGlzLmNvbmZpZy5zZXJ2ZXIuZmFzdGlmeT8ua2VlcEFsaXZlVGltZW91dDtcbiAgICBpZiAoIWtlZXBBbGl2ZVRpbWVvdXQgfHwga2VlcEFsaXZlVGltZW91dCA8PSAwKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgbGFyZ2VzdEhlYXJ0YmVhdCA9IE1hdGgubWF4KC4uLmhlYXJ0YmVhdHMpO1xuICAgIGlmIChsYXJnZXN0SGVhcnRiZWF0ID49IGtlZXBBbGl2ZVRpbWVvdXQpIHtcbiAgICAgIHNlcnZlci5sb2cud2FybihcbiAgICAgICAge1xuICAgICAgICAgIGtlZXBBbGl2ZVRpbWVvdXQsXG4gICAgICAgICAgbGFyZ2VzdEhlYXJ0YmVhdCxcbiAgICAgICAgfSxcbiAgICAgICAgXCJXZWJTb2NrZXQgaGVhcnRiZWF0IGlzIGdyZWF0ZXIgdGhhbiBvciBlcXVhbCB0byBrZWVwQWxpdmVUaW1lb3V0OyBhbGlnbiBpbmZyYXN0cnVjdHVyZSBpZGxlIHRpbWVvdXRzIHRvIGF2b2lkIHVuZXhwZWN0ZWQgZGlzY29ubmVjdHMuXCIsXG4gICAgICApO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBiZXR0ZXItYXV0aCDrnbzsmrDtirjrpbwg65Ox66Gd7ZWp64uI64ukLlxuICAgKiAvYXBpL2F1dGgvKiDqsr3roZzroZwg7J247KadIEFQSeqwgCDsnpDrj5kg65Ox66Gd65Cp64uI64ukLlxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyByZWdpc3RlckJldHRlckF1dGgoXG4gICAgc2VydmVyOiBGYXN0aWZ5SW5zdGFuY2UsXG4gICAgb3B0aW9uczogTm9uTnVsbGFibGU8U29uYW11U2VydmVyT3B0aW9uc1tcImF1dGhcIl0+LFxuICApIHtcbiAgICBpZiAoIW9wdGlvbnMpIHJldHVybjtcblxuICAgIGNvbnN0IGJhc2VQYXRoID0gb3B0aW9ucy5iYXNlUGF0aCA/PyBcIi9hcGkvYXV0aFwiO1xuXG4gICAgLy8gYmV0dGVyLWF1dGgg65287Jqw7Yq4IOuTseuhnVxuICAgIHNlcnZlci5yb3V0ZSh7XG4gICAgICBtZXRob2Q6IFtcIkdFVFwiLCBcIlBPU1RcIl0sXG4gICAgICB1cmw6IGAke2Jhc2VQYXRofS8qYCxcbiAgICAgIGhhbmRsZXI6IGFzeW5jIChyZXF1ZXN0LCByZXBseSkgPT4ge1xuICAgICAgICBjb25zdCB1cmwgPSBuZXcgVVJMKHJlcXVlc3QudXJsLCBgaHR0cDovLyR7cmVxdWVzdC5oZWFkZXJzLmhvc3R9YCk7XG4gICAgICAgIGNvbnN0IGhlYWRlcnMgPSBjb252ZXJ0RmFzdGlmeUhlYWRlcnNUb1N0YW5kYXJkKHJlcXVlc3QuaGVhZGVycyk7XG5cbiAgICAgICAgLy8gSVAg7Zek642UIGZhbGxiYWNrOiDtlITroZ3si5zqsIAg7ZGc7KSAIElQIO2XpOuNlOulvCDso7zsnoXtlZjsp4Ag7JWK64qUIO2ZmOqyveyXkOyEnOuPhFxuICAgICAgICAvLyBiZXR0ZXItYXV0aC9pbmZyYeydmCBnZXRDbGllbnRJcEZyb21SZXF1ZXN0KCnqsIAgSVDrpbwg7J247Iud7ZWgIOyImCDsnojrj4TroZ1cbiAgICAgICAgLy8gRmFzdGlmeeqwgCByZXNvbHZl7ZWcIHJlcXVlc3QuaXDrpbwgeC1yZWFsLWlw66GcIOyjvOyehe2VnOuLpC5cbiAgICAgICAgY29uc3QgSVBfSEVBREVSUyA9IFtcbiAgICAgICAgICBcImNmLWNvbm5lY3RpbmctaXBcIixcbiAgICAgICAgICBcIngtZm9yd2FyZGVkLWZvclwiLFxuICAgICAgICAgIFwieC1yZWFsLWlwXCIsXG4gICAgICAgICAgXCJ4LXZlcmNlbC1mb3J3YXJkZWQtZm9yXCIsXG4gICAgICAgIF07XG4gICAgICAgIGlmIChyZXF1ZXN0LmlwICYmICFJUF9IRUFERVJTLnNvbWUoKGgpID0+IGhlYWRlcnMuaGFzKGgpKSkge1xuICAgICAgICAgIGhlYWRlcnMuc2V0KFwieC1yZWFsLWlwXCIsIHJlcXVlc3QuaXApO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgcmVxID0gbmV3IFJlcXVlc3QodXJsLnRvU3RyaW5nKCksIHtcbiAgICAgICAgICBtZXRob2Q6IHJlcXVlc3QubWV0aG9kLFxuICAgICAgICAgIGhlYWRlcnMsXG4gICAgICAgICAgLi4uKHJlcXVlc3QuYm9keSA/IHsgYm9keTogSlNPTi5zdHJpbmdpZnkocmVxdWVzdC5ib2R5KSB9IDoge30pLFxuICAgICAgICB9KTtcblxuICAgICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMuYXV0aC5oYW5kbGVyKHJlcSk7XG5cbiAgICAgICAgcmVwbHkuc3RhdHVzKHJlc3BvbnNlLnN0YXR1cyk7XG4gICAgICAgIHJlc3BvbnNlLmhlYWRlcnMuZm9yRWFjaCgodmFsdWU6IHN0cmluZywga2V5OiBzdHJpbmcpID0+IHtcbiAgICAgICAgICByZXBseS5oZWFkZXIoa2V5LCB2YWx1ZSk7XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gcmVwbHkuc2VuZChyZXNwb25zZS5ib2R5ID8gYXdhaXQgcmVzcG9uc2UudGV4dCgpIDogbnVsbCk7XG4gICAgICB9LFxuICAgIH0pO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBwcmludFN0YXJ0dXBTdW1tYXJ5KCkge1xuICAgIGNvbnN0IGNoYWxrID0gKGF3YWl0IGltcG9ydChcImNoYWxrXCIpKS5kZWZhdWx0O1xuICAgIGNvbnN0IGVudiA9IHByb2Nlc3MuZW52Lk5PREVfRU5WID8/IFwiZGV2ZWxvcG1lbnRcIjtcbiAgICBjb25zdCBhY3RpdmVQcmVzZXQgPSBlbnYgPT09IFwicHJvZHVjdGlvblwiID8gXCJwcm9kdWN0aW9uX21hc3RlclwiIDogXCJkZXZlbG9wbWVudF9tYXN0ZXJcIjtcblxuICAgIGNvbnN0IGRpbSA9IChtc2c6IHN0cmluZykgPT4gY29uc29sZS5sb2coY2hhbGsuZGltKGDinJMgJHttc2d9YCkpO1xuICAgIGNvbnN0IGdyZWVuID0gKG1zZzogc3RyaW5nKSA9PiBjb25zb2xlLmxvZyhjaGFsay5ncmVlbihg4pyTICR7bXNnfWApKTtcblxuICAgIGRpbShgQ29uZmlnIGxvYWRlZCR7Zm9ybWF0VGltZSh0aGlzLl9jb25maWdFbGFwc2VkKX1gKTtcblxuICAgIC8vIERCIHByZXNldCDrqqnroZ1cbiAgICBncmVlbihcIkRCXCIpO1xuICAgIGNvbnN0IHsgaXNMb2NhbCB9ID0gYXdhaXQgaW1wb3J0KFwiLi4vdXRpbHMvY29udHJvbGxlclwiKTtcbiAgICBjb25zdCBwcmVzZXROYW1lcyA9IE9iamVjdC5rZXlzKHRoaXMuZGJDb25maWcpIGFzIChrZXlvZiBTb25hbXVEQkNvbmZpZylbXTtcbiAgICBjb25zdCBtYXhMZW4gPSBNYXRoLm1heCguLi5wcmVzZXROYW1lcy5tYXAoKG4pID0+IG4ubGVuZ3RoKSk7XG4gICAgZm9yIChjb25zdCBuYW1lIG9mIHByZXNldE5hbWVzKSB7XG4gICAgICBjb25zdCBjb25uID0gdGhpcy5kYkNvbmZpZ1tuYW1lXS5jb25uZWN0aW9uIGFzXG4gICAgICAgIHwgeyBob3N0Pzogc3RyaW5nOyBwb3J0PzogbnVtYmVyOyBkYXRhYmFzZT86IHN0cmluZyB9XG4gICAgICAgIHwgdW5kZWZpbmVkO1xuICAgICAgY29uc3QgaG9zdCA9IGNvbm4/Lmhvc3QgPz8gXCJsb2NhbGhvc3RcIjtcbiAgICAgIGNvbnN0IGFkZHIgPSBgQCAke2hvc3R9OiR7Y29ubj8ucG9ydCA/PyA1NDMyfS8ke2Nvbm4/LmRhdGFiYXNlID8/IHRoaXMuY29uZmlnLmRhdGFiYXNlLm5hbWV9YDtcbiAgICAgIGNvbnN0IHBhZGRlZCA9IG5hbWUucGFkRW5kKG1heExlbik7XG4gICAgICBjb25zdCByZW1vdGVUYWcgPSBpc0xvY2FsKCkgJiYgIWlzTG9jYWxIb3N0KGhvc3QpID8gY2hhbGsueWVsbG93KGAgXFx1MjZhMCByZW1vdGVgKSA6IFwiXCI7XG5cbiAgICAgIGlmIChuYW1lID09PSBhY3RpdmVQcmVzZXQpIHtcbiAgICAgICAgY29uc29sZS5sb2coY2hhbGsuZ3JlZW4oYCAgXFx1MjViOCAke3BhZGRlZH0gJHthZGRyfWApICsgcmVtb3RlVGFnKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnNvbGUubG9nKGNoYWxrLmRpbShgICAgICR7cGFkZGVkfSAke2FkZHJ9YCkgKyByZW1vdGVUYWcpO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmICh0aGlzLmNvbmZpZy5zZXJ2ZXIuYXV0aCkge1xuICAgICAgY29uc3QgYmFzZVBhdGggPSB0aGlzLmNvbmZpZy5zZXJ2ZXIuYXV0aC5iYXNlUGF0aCA/PyBcIi9hcGkvYXV0aFwiO1xuICAgICAgZGltKGBBdXRoOiBiZXR0ZXItYXV0aCBhdCAke2Jhc2VQYXRofS8qYCk7XG4gICAgfVxuICAgIGlmICh0aGlzLmNvbmZpZy5hcGkudGltZXpvbmUpIHtcbiAgICAgIGRpbShgVGltZXpvbmU6ICR7dGhpcy5jb25maWcuYXBpLnRpbWV6b25lfWApO1xuICAgIH1cbiAgICBncmVlbihgU29uYW11IHJlYWR5JHtmb3JtYXRUaW1lKHRoaXMuX2luaXRFbGFwc2VkKX1gKTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgaW5pdGlhbGl6ZUNhY2hlKGNvbmZpZzogQ2FjaGVDb25maWcgfCB1bmRlZmluZWQsIGZvclRlc3Rpbmc6IGJvb2xlYW4pIHtcbiAgICBjb25zdCB7IHNldENhY2hlTWFuYWdlclJlZiB9ID0gYXdhaXQgaW1wb3J0KFwiLi4vY2FjaGUvZGVjb3JhdG9yXCIpO1xuXG4gICAgLy8g7YWM7Iqk7Yq4IO2ZmOqyveyXkOyEnCDrqZTrqqjrpqwg65Oc65287J2067KEIOyekOuPmSDsgqzsmqlcbiAgICBpZiAoZm9yVGVzdGluZykge1xuICAgICAgY29uc3QgeyBjcmVhdGVUZXN0Q2FjaGVNYW5hZ2VyIH0gPSBhd2FpdCBpbXBvcnQoXCIuLi9jYWNoZS9jYWNoZS1tYW5hZ2VyXCIpO1xuICAgICAgdGhpcy5fY2FjaGUgPSBjcmVhdGVUZXN0Q2FjaGVNYW5hZ2VyKCk7XG4gICAgICBzZXRDYWNoZU1hbmFnZXJSZWYodGhpcy5fY2FjaGUpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIOyEpOygleydtCDsl4bsnLzrqbQg7LqQ7IucIOu5hO2ZnOyEse2ZlFxuICAgIGlmICghY29uZmlnKSB7XG4gICAgICBzZXRDYWNoZU1hbmFnZXJSZWYobnVsbCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8g7ISk7KCV7JeQIOuUsOudvCBDYWNoZU1hbmFnZXIg7IOd7ISxXG4gICAgY29uc3QgeyBjcmVhdGVDYWNoZU1hbmFnZXIgfSA9IGF3YWl0IGltcG9ydChcIi4uL2NhY2hlL2NhY2hlLW1hbmFnZXJcIik7XG4gICAgdGhpcy5fY2FjaGUgPSBjcmVhdGVDYWNoZU1hbmFnZXIoY29uZmlnKTtcbiAgICBzZXRDYWNoZU1hbmFnZXJSZWYodGhpcy5fY2FjaGUpO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBpbml0aWFsaXplV29ya2Zsb3dzKG9wdGlvbnM6IFNvbmFtdVRhc2tPcHRpb25zIHwgdW5kZWZpbmVkKSB7XG4gICAgY29uc3QgeyBXb3JrZmxvd01hbmFnZXIgfSA9IGF3YWl0IGltcG9ydChcIi4uL3Rhc2tzL3dvcmtmbG93LW1hbmFnZXJcIik7XG4gICAgLy8gTk9URTogQHNvbmFtdS1raXQvdGFza3Mg7JWI7JeQ7ISgIGtuZXggY29uZmln66W8IOyImOygle2VmOq4sCDrlYzrrLjsl5AgY29ubmVjdGlvbuydtCDslYTri4wgY29uZmlnIOynuOuhnCDrs7Trg4Xri4jri6QuXG4gICAgdGhpcy5fd29ya2Zsb3dzID0gbmV3IFdvcmtmbG93TWFuYWdlcihEQi5nZXREQkNvbmZpZyhcIndcIikpO1xuICAgIGlmICghb3B0aW9ucykge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IGVuYWJsZVdvcmtlciA9IG9wdGlvbnMuZW5hYmxlV29ya2VyID8/IGlzRGFlbW9uU2VydmVyKCk7XG4gICAgY29uc3QgZGVmYXVsdFdvcmtlck9wdGlvbnMgPSB7XG4gICAgICBjb25jdXJyZW5jeTogb3MuY3B1cygpLmxlbmd0aCAtIDEsXG4gICAgICB1c2VQdWJTdWI6IHRydWUsXG4gICAgICBsaXN0ZW5EZWxheTogNTAwLFxuICAgIH07XG5cbiAgICBpZiAoZW5hYmxlV29ya2VyKSB7XG4gICAgICB0aGlzLndvcmtmbG93cy5zZXR1cFdvcmtlcih7XG4gICAgICAgIC4uLmRlZmF1bHRXb3JrZXJPcHRpb25zLFxuICAgICAgICAuLi5vcHRpb25zLndvcmtlck9wdGlvbnMsXG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGJvb3Qoc2VydmVyOiBGYXN0aWZ5SW5zdGFuY2UsIG9wdGlvbnM6IFNvbmFtdVNlcnZlck9wdGlvbnMpIHtcbiAgICBjb25zdCBwb3J0ID0gb3B0aW9ucy5saXN0ZW4/LnBvcnQgPz8gMzAwMDtcbiAgICBjb25zdCBob3N0ID0gb3B0aW9ucy5saXN0ZW4/Lmhvc3QgPz8gXCJsb2NhbGhvc3RcIjtcblxuICAgIHNlcnZlci5hZGRIb29rKFwib25DbG9zZVwiLCBhc3luYyAoKSA9PiB7XG4gICAgICBhd2FpdCBvcHRpb25zLmxpZmVjeWNsZT8ub25TaHV0ZG93bj8uKHNlcnZlcik7XG4gICAgICBhd2FpdCB0aGlzLndvcmtmbG93cy5kZXN0cm95KCk7XG4gICAgICBhd2FpdCB0aGlzLmRlc3Ryb3koKTtcbiAgICB9KTtcblxuICAgIGNvbnN0IHNodXRkb3duID0gYXN5bmMgKCkgPT4ge1xuICAgICAgdHJ5IHtcbiAgICAgICAgYXdhaXQgc2VydmVyLmNsb3NlKCk7XG4gICAgICAgIHByb2Nlc3MuZXhpdCgwKTtcbiAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICBjb25zb2xlLmVycm9yKFwiRXJyb3IgZHVyaW5nIHNodXRkb3duOlwiLCBlcnIpO1xuICAgICAgICBwcm9jZXNzLmV4aXQoMSk7XG4gICAgICB9XG4gICAgfTtcblxuICAgIHByb2Nlc3Mub24oXCJTSUdJTlRcIiwgc2h1dGRvd24pO1xuICAgIHByb2Nlc3Mub24oXCJTSUdURVJNXCIsIHNodXRkb3duKTtcblxuICAgIGlmIChvcHRpb25zLmxpZmVjeWNsZT8ub25FcnJvcikge1xuICAgICAgc2VydmVyLnNldEVycm9ySGFuZGxlcihvcHRpb25zLmxpZmVjeWNsZT8ub25FcnJvcik7XG4gICAgfVxuXG4gICAgc2VydmVyXG4gICAgICAubGlzdGVuKHsgcG9ydCwgaG9zdCB9KVxuICAgICAgLnRoZW4oYXN5bmMgKCkgPT4ge1xuICAgICAgICBhd2FpdCB0aGlzLndvcmtmbG93cy5zdGFydFdvcmtlcigpO1xuICAgICAgICBhd2FpdCBvcHRpb25zLmxpZmVjeWNsZT8ub25TdGFydD8uKHNlcnZlcik7XG4gICAgICB9KVxuICAgICAgLmNhdGNoKGFzeW5jIChlcnIpID0+IHtcbiAgICAgICAgY29uc3QgY2hhbGsgPSAoYXdhaXQgaW1wb3J0KFwiY2hhbGtcIikpLmRlZmF1bHQ7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoY2hhbGsucmVkKFwiRmFpbGVkIHRvIHN0YXJ0IHNlcnZlcjpcIiwgZXJyKSk7XG4gICAgICAgIGF3YWl0IHNodXRkb3duKCk7XG4gICAgICB9KTtcbiAgfVxuXG4gIGFzeW5jIGRlc3Ryb3koKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgeyBCYXNlTW9kZWwgfSA9IGF3YWl0IGltcG9ydChcIi4uL2RhdGFiYXNlL2Jhc2UtbW9kZWxcIik7XG4gICAgLy8g66i87KCAIOyymOumrO2VtOyVvO2VqC5cbiAgICBhd2FpdCBCYXNlTW9kZWwuZGVzdHJveSgpO1xuICAgIC8vIO2UhOuhnOyEuOyKpCDsooXro4wg7IucIOyCtOyVhOyeiOuKlCBXUyDsl7DqsrDsnYQg66i87KCAIOygleumrO2VtCDsnbTtm4Qg64uk66W4IOumrOyGjOyKpCDtlbTsoJwg6rO87KCV7JeQ7IScIOyelOyXrCBjYWxsYmFja+ydtCDtioDsp4Ag7JWK6rKMIO2VqFxuICAgIGF3YWl0IFByb21pc2UuYWxsU2V0dGxlZChbXG4gICAgICB0aGlzLl93ZWJzb2NrZXRSdW50aW1lPy5zaHV0ZG93bigpID8/IFByb21pc2UucmVzb2x2ZSgpLFxuICAgICAgdGhpcy5fd29ya2Zsb3dzPy5kZXN0cm95KCkgPz8gUHJvbWlzZS5yZXNvbHZlKCksXG4gICAgICB0aGlzLl9jYWNoZT8uZGlzY29ubmVjdCgpID8/IFByb21pc2UucmVzb2x2ZSgpLFxuICAgICAgdGhpcy5fZGV2Vml0ZXN0TWFuYWdlcj8uc2h1dGRvd24oKSA/PyBQcm9taXNlLnJlc29sdmUoKSxcbiAgICAgIHRoaXMud2F0Y2hlcj8uY2xvc2UoKSA/PyBQcm9taXNlLnJlc29sdmUoKSxcbiAgICAgIGxvZ3RhcGVEaXNwb3NlKCksXG4gICAgXSk7XG4gICAgdGhpcy5fd2Vic29ja2V0UnVudGltZSA9IG51bGw7XG4gIH1cbn1cblxuZXhwb3J0IGNvbnN0IFNvbmFtdSA9IG5ldyBTb25hbXVDbGFzcygpO1xuXG4vKipcbiAqIHN0cmVhbSDrqqjrk5zsl5DshJwg7YKkIOyDneyEsSDtlajsiJjqsIAg7KeA7KCV65CY7KeAIOyViuyVmOydhCDrlYwg7IKs7Jqp7ZWY64qUIOq4sOuzuCDtlajsiJjsnoXri4jri6QuXG4gKi9cbmZ1bmN0aW9uIGRlZmF1bHRLZXlHZW5lcmF0b3IoZmlsZTogeyBmaWxlbmFtZTogc3RyaW5nOyBtaW1ldHlwZTogc3RyaW5nIH0pOiBzdHJpbmcge1xuICBjb25zdCBleHQgPSBtaW1lLmV4dGVuc2lvbihmaWxlLm1pbWV0eXBlKSB8fCBcImJpblwiO1xuICBjb25zdCB0aW1lc3RhbXAgPSBEYXRlLm5vdygpO1xuICBjb25zdCByYW5kb20gPSBNYXRoLnJhbmRvbSgpLnRvU3RyaW5nKDM2KS5zbGljZSgyLCA4KTtcbiAgcmV0dXJuIGB1cGxvYWRzLyR7dGltZXN0YW1wfS0ke3JhbmRvbX0uJHtleHR9YDtcbn1cblxuZnVuY3Rpb24gZm9ybWF0VGltZShtczogbnVtYmVyKTogc3RyaW5nIHtcbiAgY29uc3QgZm9ybWF0dGVkID0gbXMgPj0gMTAwMCA/IGAkeyhtcyAvIDEwMDApLnRvRml4ZWQoMil9c2AgOiBgJHtNYXRoLnJvdW5kKG1zKX1tc2A7XG4gIHJldHVybiBgICgke2Zvcm1hdHRlZH0pYDtcbn1cblxuY29uc3QgTE9DQUxfSE9TVFMgPSBuZXcgU2V0KFtcImxvY2FsaG9zdFwiLCBcIjEyNy4wLjAuMVwiLCBcIjAuMC4wLjBcIiwgXCI6OjFcIl0pO1xuZnVuY3Rpb24gaXNMb2NhbEhvc3QoaG9zdDogc3RyaW5nKTogYm9vbGVhbiB7XG4gIHJldHVybiBMT0NBTF9IT1NUUy5oYXMoaG9zdCk7XG59XG5cbi8vIGAuZXZlcnkoKWDqsIAg7LKrIGd1YXJkIOydtO2bhCDsiJztmozrpbwg66mI7LaU64qUIOusuOygnOqwgCDsnojslrQgYGZvci4uLm9mYOuhnCDrqqjrk6AgZ3VhcmTrpbwg7Iic7ISc64yA66GcIOyLpO2Wie2VmOuPhOuhnSDqs6DsoJXtlahcbmZ1bmN0aW9uIHJ1bkd1YXJkcyh7XG4gIGd1YXJkcyxcbiAgY29uZmlnLFxuICByZXF1ZXN0LFxuICBhcGksXG59OiB7XG4gIGd1YXJkczogRXh0ZW5kZWRBcGlbXCJvcHRpb25zXCJdW1wiZ3VhcmRzXCJdIHwgdW5kZWZpbmVkO1xuICBjb25maWc6IFBpY2s8U29uYW11RmFzdGlmeUNvbmZpZywgXCJndWFyZEhhbmRsZXJcIj47XG4gIHJlcXVlc3Q6IEZhc3RpZnlSZXF1ZXN0O1xuICBhcGk6IEV4dGVuZGVkQXBpO1xufSk6IHZvaWQge1xuICBmb3IgKGNvbnN0IGd1YXJkIG9mIGd1YXJkcyA/PyBbXSkge1xuICAgIGNvbmZpZy5ndWFyZEhhbmRsZXIoZ3VhcmQsIHJlcXVlc3QsIGFwaSk7XG4gIH1cbn1cbiJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFtMERBLFNBQVMsb0JBQW9CLE1BQXNEO0NBQ2pGLE1BQU0sTUFBTSxLQUFLLFVBQVUsS0FBSyxTQUFTLElBQUk7Q0FDN0MsTUFBTSxZQUFZLEtBQUssS0FBSztDQUM1QixNQUFNLFNBQVMsS0FBSyxRQUFRLENBQUMsU0FBUyxHQUFHLENBQUMsTUFBTSxHQUFHLEVBQUU7QUFDckQsUUFBTyxXQUFXLFVBQVUsR0FBRyxPQUFPLEdBQUc7O0FBRzNDLFNBQVMsV0FBVyxJQUFvQjtDQUN0QyxNQUFNLFlBQVksTUFBTSxNQUFPLElBQUksS0FBSyxLQUFNLFFBQVEsRUFBRSxDQUFDLEtBQUssR0FBRyxLQUFLLE1BQU0sR0FBRyxDQUFDO0FBQ2hGLFFBQU8sS0FBSyxVQUFVOztBQUl4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