sonamu 0.7.21 → 0.7.23

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 (200) hide show
  1. package/dist/ai/agents/agent.d.ts +6 -1
  2. package/dist/ai/agents/agent.d.ts.map +1 -1
  3. package/dist/ai/agents/agent.js +20 -5
  4. package/dist/api/base-frame.d.ts +4 -0
  5. package/dist/api/base-frame.d.ts.map +1 -1
  6. package/dist/api/base-frame.js +9 -1
  7. package/dist/api/caster.d.ts.map +1 -1
  8. package/dist/api/caster.js +2 -2
  9. package/dist/api/config.d.ts +35 -3
  10. package/dist/api/config.d.ts.map +1 -1
  11. package/dist/api/config.js +1 -1
  12. package/dist/api/decorators.d.ts +4 -4
  13. package/dist/api/decorators.d.ts.map +1 -1
  14. package/dist/api/decorators.js +80 -18
  15. package/dist/api/index.d.ts +1 -0
  16. package/dist/api/index.d.ts.map +1 -1
  17. package/dist/api/index.js +2 -1
  18. package/dist/api/secret.d.ts +7 -0
  19. package/dist/api/secret.d.ts.map +1 -0
  20. package/dist/api/secret.js +17 -0
  21. package/dist/api/sonamu.d.ts +17 -8
  22. package/dist/api/sonamu.d.ts.map +1 -1
  23. package/dist/api/sonamu.js +265 -47
  24. package/dist/cache/cache-manager.d.ts +11 -0
  25. package/dist/cache/cache-manager.d.ts.map +1 -0
  26. package/dist/cache/cache-manager.js +22 -0
  27. package/dist/cache/decorator.d.ts +31 -0
  28. package/dist/cache/decorator.d.ts.map +1 -0
  29. package/dist/cache/decorator.js +86 -0
  30. package/dist/cache/drivers.d.ts +33 -0
  31. package/dist/cache/drivers.d.ts.map +1 -0
  32. package/dist/cache/drivers.js +36 -0
  33. package/dist/cache/index.d.ts +4 -0
  34. package/dist/cache/index.d.ts.map +1 -0
  35. package/dist/cache/index.js +8 -0
  36. package/dist/cache/types.d.ts +28 -0
  37. package/dist/cache/types.d.ts.map +1 -0
  38. package/dist/cache/types.js +6 -0
  39. package/dist/database/base-model.d.ts +4 -2
  40. package/dist/database/base-model.d.ts.map +1 -1
  41. package/dist/database/base-model.js +9 -4
  42. package/dist/database/code-generator.d.ts +3 -1
  43. package/dist/database/code-generator.d.ts.map +1 -1
  44. package/dist/database/code-generator.js +3 -2
  45. package/dist/database/db.d.ts +1 -1
  46. package/dist/database/db.d.ts.map +1 -1
  47. package/dist/database/db.js +5 -5
  48. package/dist/database/knex.d.ts +3 -0
  49. package/dist/database/knex.d.ts.map +1 -0
  50. package/dist/database/knex.js +29 -0
  51. package/dist/database/puri.types.d.ts.map +1 -1
  52. package/dist/database/puri.types.js +1 -1
  53. package/dist/database/upsert-builder.d.ts.map +1 -1
  54. package/dist/database/upsert-builder.js +49 -5
  55. package/dist/index.d.ts +4 -0
  56. package/dist/index.d.ts.map +1 -1
  57. package/dist/index.js +4 -1
  58. package/dist/logger/category.d.ts +4 -0
  59. package/dist/logger/category.d.ts.map +1 -0
  60. package/dist/logger/category.js +34 -0
  61. package/dist/logger/configure.d.ts +9 -0
  62. package/dist/logger/configure.d.ts.map +1 -0
  63. package/dist/logger/configure.js +115 -0
  64. package/dist/migration/code-generation.d.ts +5 -1
  65. package/dist/migration/code-generation.d.ts.map +1 -1
  66. package/dist/migration/code-generation.js +13 -7
  67. package/dist/migration/migrator.d.ts +1 -1
  68. package/dist/migration/migrator.d.ts.map +1 -1
  69. package/dist/migration/migrator.js +7 -7
  70. package/dist/migration/postgresql-schema-reader.d.ts.map +1 -1
  71. package/dist/migration/postgresql-schema-reader.js +5 -3
  72. package/dist/naite/naite.d.ts +0 -4
  73. package/dist/naite/naite.d.ts.map +1 -1
  74. package/dist/naite/naite.js +11 -19
  75. package/dist/ssr/index.d.ts +4 -0
  76. package/dist/ssr/index.d.ts.map +1 -0
  77. package/dist/ssr/index.js +4 -0
  78. package/dist/ssr/registry.d.ts +10 -0
  79. package/dist/ssr/registry.d.ts.map +1 -0
  80. package/dist/ssr/registry.js +43 -0
  81. package/dist/ssr/renderer.d.ts +6 -0
  82. package/dist/ssr/renderer.d.ts.map +1 -0
  83. package/dist/ssr/renderer.js +70 -0
  84. package/dist/ssr/types.d.ts +19 -0
  85. package/dist/ssr/types.d.ts.map +1 -0
  86. package/dist/ssr/types.js +4 -0
  87. package/dist/syncer/syncer.d.ts +1 -0
  88. package/dist/syncer/syncer.d.ts.map +1 -1
  89. package/dist/syncer/syncer.js +58 -1
  90. package/dist/tasks/decorator.d.ts +1 -0
  91. package/dist/tasks/decorator.d.ts.map +1 -1
  92. package/dist/tasks/decorator.js +9 -7
  93. package/dist/tasks/step-wrapper.d.ts +5 -0
  94. package/dist/tasks/step-wrapper.d.ts.map +1 -1
  95. package/dist/tasks/step-wrapper.js +11 -6
  96. package/dist/tasks/workflow-manager.d.ts +2 -0
  97. package/dist/tasks/workflow-manager.d.ts.map +1 -1
  98. package/dist/tasks/workflow-manager.js +5 -2
  99. package/dist/template/implementations/entry-server.template.d.ts +17 -0
  100. package/dist/template/implementations/entry-server.template.d.ts.map +1 -0
  101. package/dist/template/implementations/entry-server.template.js +78 -0
  102. package/dist/template/implementations/model.template.d.ts.map +1 -1
  103. package/dist/template/implementations/model.template.js +5 -3
  104. package/dist/template/implementations/queries.template.d.ts +17 -0
  105. package/dist/template/implementations/queries.template.d.ts.map +1 -0
  106. package/dist/template/implementations/queries.template.js +83 -0
  107. package/dist/template/implementations/view_enums_select.template.d.ts.map +1 -1
  108. package/dist/template/implementations/view_enums_select.template.js +34 -20
  109. package/dist/template/implementations/view_form.template.d.ts +2 -1
  110. package/dist/template/implementations/view_form.template.d.ts.map +1 -1
  111. package/dist/template/implementations/view_form.template.js +301 -129
  112. package/dist/template/implementations/view_id_async_select.template.d.ts.map +1 -1
  113. package/dist/template/implementations/view_id_async_select.template.js +136 -57
  114. package/dist/template/implementations/view_list.template.d.ts +2 -0
  115. package/dist/template/implementations/view_list.template.d.ts.map +1 -1
  116. package/dist/template/implementations/view_list.template.js +392 -227
  117. package/dist/template/implementations/view_search_input.template.d.ts.map +1 -1
  118. package/dist/template/implementations/view_search_input.template.js +46 -30
  119. package/dist/template/zod-converter.d.ts.map +1 -1
  120. package/dist/template/zod-converter.js +2 -2
  121. package/dist/testing/bootstrap.d.ts +28 -0
  122. package/dist/testing/bootstrap.d.ts.map +1 -0
  123. package/dist/testing/bootstrap.js +120 -0
  124. package/dist/testing/fixture-loader.d.ts +21 -0
  125. package/dist/testing/fixture-loader.d.ts.map +1 -0
  126. package/dist/testing/fixture-loader.js +28 -0
  127. package/dist/testing/fixture-manager.d.ts +1 -1
  128. package/dist/testing/fixture-manager.d.ts.map +1 -1
  129. package/dist/testing/fixture-manager.js +7 -7
  130. package/dist/testing/index.d.ts +4 -0
  131. package/dist/testing/index.d.ts.map +1 -0
  132. package/dist/testing/index.js +5 -0
  133. package/dist/testing/naite-vitest-reporter.d.ts +12 -0
  134. package/dist/testing/naite-vitest-reporter.d.ts.map +1 -0
  135. package/dist/testing/naite-vitest-reporter.js +17 -0
  136. package/dist/types/types.d.ts +5 -6
  137. package/dist/types/types.d.ts.map +1 -1
  138. package/dist/types/types.js +7 -8
  139. package/dist/ui/ai-client.d.ts +3 -1
  140. package/dist/ui/ai-client.d.ts.map +1 -1
  141. package/dist/ui/ai-client.js +27 -8
  142. package/dist/ui-web/assets/index-CTYv3qL6.js +92 -0
  143. package/dist/ui-web/index.html +1 -1
  144. package/package.json +43 -20
  145. package/src/ai/agents/agent.ts +38 -19
  146. package/src/api/base-frame.ts +8 -0
  147. package/src/api/caster.ts +6 -1
  148. package/src/api/config.ts +38 -4
  149. package/src/api/decorators.ts +106 -20
  150. package/src/api/index.ts +1 -0
  151. package/src/api/secret.ts +23 -0
  152. package/src/api/sonamu.ts +334 -61
  153. package/src/cache/cache-manager.ts +23 -0
  154. package/src/cache/decorator.ts +116 -0
  155. package/src/cache/drivers.ts +42 -0
  156. package/src/cache/index.ts +16 -0
  157. package/src/cache/types.ts +32 -0
  158. package/src/database/base-model.ts +7 -3
  159. package/src/database/code-generator.ts +3 -1
  160. package/src/database/db.ts +5 -5
  161. package/src/database/knex.ts +34 -0
  162. package/src/database/puri.types.ts +2 -3
  163. package/src/database/upsert-builder.ts +58 -4
  164. package/src/index.ts +4 -0
  165. package/src/logger/category.ts +42 -0
  166. package/src/logger/configure.ts +132 -0
  167. package/src/migration/code-generation.ts +19 -6
  168. package/src/migration/migrator.ts +7 -6
  169. package/src/migration/postgresql-schema-reader.ts +7 -2
  170. package/src/naite/naite.ts +10 -18
  171. package/src/shared/web.shared.ts.txt +1 -1
  172. package/src/ssr/index.ts +13 -0
  173. package/src/ssr/registry.ts +52 -0
  174. package/src/ssr/renderer.ts +105 -0
  175. package/src/ssr/types.ts +20 -0
  176. package/src/syncer/syncer.ts +59 -0
  177. package/src/tasks/decorator.ts +20 -4
  178. package/src/tasks/step-wrapper.ts +14 -5
  179. package/src/tasks/workflow-manager.ts +9 -1
  180. package/src/template/implementations/entry-server.template.ts +81 -0
  181. package/src/template/implementations/model.template.ts +4 -2
  182. package/src/template/implementations/queries.template.ts +111 -0
  183. package/src/template/implementations/view_enums_select.template.ts +33 -19
  184. package/src/template/implementations/view_form.template.ts +324 -145
  185. package/src/template/implementations/view_id_async_select.template.ts +145 -56
  186. package/src/template/implementations/view_list.template.ts +446 -236
  187. package/src/template/implementations/view_search_input.template.ts +45 -29
  188. package/src/template/zod-converter.ts +4 -1
  189. package/src/testing/bootstrap.ts +176 -0
  190. package/src/testing/fixture-loader.ts +28 -0
  191. package/src/testing/fixture-manager.ts +7 -6
  192. package/src/testing/index.ts +3 -0
  193. package/src/testing/naite-vitest-reporter.ts +18 -0
  194. package/src/types/types.ts +4 -5
  195. package/src/ui/ai-client.ts +82 -50
  196. package/dist/template/implementations/view_enums_dropdown.template.d.ts +0 -17
  197. package/dist/template/implementations/view_enums_dropdown.template.d.ts.map +0 -1
  198. package/dist/template/implementations/view_enums_dropdown.template.js +0 -50
  199. package/dist/ui-web/assets/index-B87IyofX.js +0 -92
  200. package/src/template/implementations/view_enums_dropdown.template.ts +0 -53
@@ -1,9 +1,12 @@
1
+ import { dispose as logtapeDispose } from "@logtape/logtape";
1
2
  import assert from "assert";
2
3
  import { AsyncLocalStorage } from "async_hooks";
4
+ import fs from "fs";
3
5
  import os from "os";
4
6
  import path from "path";
5
7
  import { createMockSSEFactory, DB, isDaemonServer } from "../index.js";
6
8
  import { Naite } from "../naite/naite.js";
9
+ import { getSecrets } from "./secret.js";
7
10
  class SonamuClass {
8
11
  isInitialized = false;
9
12
  asyncLocalStorage = new AsyncLocalStorage();
@@ -77,13 +80,7 @@ class SonamuClass {
77
80
  }
78
81
  return this._config;
79
82
  }
80
- _secrets = null;
81
- set secrets(secrets) {
82
- this._secrets = secrets;
83
- }
84
- get secrets() {
85
- return this._secrets;
86
- }
83
+ secrets = getSecrets();
87
84
  _storage = null;
88
85
  /**
89
86
  * StorageManager 인스턴스
@@ -93,6 +90,15 @@ class SonamuClass {
93
90
  }
94
91
  return this._storage;
95
92
  }
93
+ _cache = null;
94
+ /**
95
+ * CacheManager 인스턴스 (BentoCache)
96
+ */ get cache() {
97
+ if (!this._cache) {
98
+ throw new Error("Cache has not been initialized. Check cache config in sonamu.config.ts.");
99
+ }
100
+ return this._cache;
101
+ }
96
102
  _workflows = null;
97
103
  get workflows() {
98
104
  if (this._workflows === null) {
@@ -119,23 +125,18 @@ class SonamuClass {
119
125
  // API 루트 패스
120
126
  const { findApiRootPath } = await import("../utils/utils.js");
121
127
  this.apiRootPath = apiRootPath ?? findApiRootPath();
128
+ // 설정을 로딩하는 것부터 시작
122
129
  const { loadConfig } = await import("./config.js");
123
130
  this.config = await loadConfig(this.apiRootPath);
124
131
  // sonamu.config.ts 기본값 설정
125
- this.config.database.database = this.config.database.database ?? "postgresql";
126
- // API 환경변수 로드
127
- const secrets = {};
128
- if (process.env.ANTHROPIC_API_KEY) {
129
- secrets.anthropic_api_key = process.env.ANTHROPIC_API_KEY;
130
- }
131
- if (process.env.VOYAGE_API_KEY) {
132
- secrets.voyage_api_key = process.env.VOYAGE_API_KEY;
133
- }
134
- if (process.env.OPENAI_API_KEY) {
135
- secrets.openai_api_key = process.env.OPENAI_API_KEY;
136
- }
137
- if (Object.keys(secrets).length > 0) {
138
- this.secrets = secrets;
132
+ this.config.database.database = this.config.database.database ?? "pg";
133
+ this.config.database.defaultOptions.client = this.config.database.database ?? "pg";
134
+ // 로깅 설정
135
+ const { configureLogTape } = await import("../logger/configure.js");
136
+ if (this.config.logging !== false) {
137
+ await configureLogTape({
138
+ ...this.config.logging
139
+ });
139
140
  }
140
141
  // DB 로드
141
142
  const { DB } = await import("../database/db.js");
@@ -149,6 +150,8 @@ class SonamuClass {
149
150
  // upsert가 제대로 작동하려면 entity의 unique index 정보가 필요하기 때문입니다.
150
151
  const { EntityManager } = await import("../entity/entity-manager.js");
151
152
  await EntityManager.autoload(doSilent);
153
+ // Cache 초기화
154
+ await this.initializeCache(this.config.server.cache, forTesting);
152
155
  // 테스팅인 경우 싱크 없이 중단
153
156
  if (forTesting) {
154
157
  this.isInitialized = true;
@@ -159,13 +162,14 @@ class SonamuClass {
159
162
  // Syncer
160
163
  const { Syncer } = await import("../syncer/syncer.js");
161
164
  this.syncer = new Syncer();
162
- // Autoload: Models / Types / APIs
165
+ // Autoload: Models / Types / APIs / Workflows / Templates / SSR Routes
163
166
  await this.syncer.autoloadTypes();
164
167
  await this.syncer.autoloadModels();
165
168
  await this.syncer.autoloadApis();
166
169
  await this.syncer.autoloadWorkflows();
167
170
  const { TemplateManager } = await import("../template/index.js");
168
171
  await TemplateManager.autoload();
172
+ await this.syncer.autoloadSSRRoutes();
169
173
  const { isLocal, isTest } = await import("../utils/controller.js");
170
174
  if (isLocal()) {
171
175
  // 로컬에서는 코드 생성을 위해 Biome 셋업이 필요함 (현재 apiRootPath 전달하여 실행)
@@ -187,8 +191,16 @@ class SonamuClass {
187
191
  await this.init(initOptions?.doSilent, initOptions?.enableSync);
188
192
  }
189
193
  const options = this.config.server;
190
- const fastify = (await import("fastify")).default;
191
- const server = fastify(options.fastify);
194
+ const { default: fastify } = await import("fastify");
195
+ const { getLogTapeFastifyLogger } = await import("@logtape/fastify");
196
+ const server = fastify({
197
+ ...options.fastify,
198
+ logger: this.config.logging !== false ? getLogTapeFastifyLogger({
199
+ category: this.config.logging?.fastifyCategory ?? [
200
+ "fastify"
201
+ ]
202
+ }) : undefined
203
+ });
192
204
  this.server = server;
193
205
  // Storage 설정 → StorageManager 생성
194
206
  if (options.storage) {
@@ -256,39 +268,202 @@ class SonamuClass {
256
268
  // Sonamu UI API
257
269
  const { sonamuUIApiPlugin } = await import("../ui/api.js");
258
270
  server.register(sonamuUIApiPlugin);
259
- // API 라우팅 (로컬HMR 상태와 구분)
271
+ // 로컬/프로덕션 환경 분기
260
272
  const { isLocal } = await import("../utils/controller.js");
273
+ const webPath = path.join(this.appRootPath, "web");
274
+ const hasWeb = fs.existsSync(webPath);
261
275
  if (isLocal()) {
262
- server.all("*", async (request, reply)=>{
263
- // Sonamu UI
264
- if (request.url.startsWith("/sonamu-ui")) {
265
- return;
266
- }
267
- const found = this.syncer.apis.find((api)=>this.config.api.route.prefix + api.path === request.url.split("?")[0] && (api.options.httpMethod ?? "GET") === request.method.toUpperCase());
268
- if (found) {
269
- return this.createApiHandler(found, config)(request, reply);
270
- }
271
- if (request.url.startsWith("/api/")) {
272
- const { NotFoundException } = await import("../exceptions/so-exceptions.js");
273
- throw new NotFoundException(`존재하지 않는 API 접근입니다. ${request.url}`);
274
- }
275
- // 일반 파일 접근시 별도의 에러 출력하지 않음
276
- return;
277
- });
276
+ // 로컬 개발 환경: Vite Dev Server + 통합 핸들러
277
+ if (hasWeb) {
278
+ await this.setupViteDevServer(server, webPath, config);
279
+ }
278
280
  } else {
281
+ // 프로덕션 환경: 개별 API 라우트 + 정적 파일 서빙
279
282
  for (const api of this.syncer.apis){
280
- // model
281
283
  if (this.syncer.models[api.modelName] === undefined) {
282
284
  throw new Error(`정의되지 않은 모델에 접근 ${api.modelName}`);
283
285
  }
284
- // route
285
286
  server.route({
286
287
  method: api.options.httpMethod ?? "GET",
287
288
  url: this.config.api.route.prefix + api.path,
288
289
  handler: this.createApiHandler(api, config)
289
- }); // END server.route
290
+ });
291
+ }
292
+ if (hasWeb) {
293
+ await this.setupStaticWebServer(server, webPath, config);
294
+ }
295
+ }
296
+ }
297
+ // biome-ignore lint/suspicious/noExplicitAny: ViteDevServer 타입을 동적으로 로드해야 함
298
+ viteServer = null;
299
+ async setupViteDevServer(server, webPath, config) {
300
+ // @fastify/middie 등록 (Connect-style middleware 지원)
301
+ await server.register((await import("@fastify/middie")).default);
302
+ const vite = await import("vite");
303
+ this.viteServer = await vite.createServer({
304
+ root: webPath,
305
+ server: {
306
+ middlewareMode: true,
307
+ hmr: {
308
+ server: server.server
309
+ }
310
+ },
311
+ appType: "custom"
312
+ });
313
+ // Vite middleware 등록 (Vite 에셋 처리)
314
+ server.use((req, res, next)=>{
315
+ // API와 Sonamu UI는 Fastify 라우트가 처리하도록 skip
316
+ if (req.url?.startsWith(this.config.api.route.prefix) || req.url?.startsWith("/sonamu-ui")) {
317
+ return next();
318
+ }
319
+ // 나머지는 Vite middleware로 전달
320
+ return this.viteServer.middlewares(req, res, next);
321
+ });
322
+ // API 동적 라우팅 (catch-all 전에 등록)
323
+ for (const api of this.syncer.apis){
324
+ if (this.syncer.models[api.modelName] === undefined) {
325
+ throw new Error(`정의되지 않은 모델에 접근 ${api.modelName}`);
326
+ }
327
+ server.route({
328
+ method: api.options.httpMethod ?? "GET",
329
+ url: this.config.api.route.prefix + api.path,
330
+ handler: this.createApiHandler(api, config)
331
+ });
332
+ }
333
+ // Catch-all 핸들러: SSR + CSR fallback
334
+ server.setNotFoundHandler(async (request, reply)=>{
335
+ const url = request.url;
336
+ // SSR 라우트 체크
337
+ const { matchSSRRoute } = await import("../ssr/index.js");
338
+ const match = matchSSRRoute(url);
339
+ if (match) {
340
+ console.log(`[SSR] Matched route: ${match.route.path}`);
341
+ // SSR 렌더링
342
+ try {
343
+ const { renderSSR } = await import("../ssr/index.js");
344
+ const html = await renderSSR(url, match.route, match.params, request, reply, config, this.viteServer);
345
+ reply.type("text/html").send(html);
346
+ return;
347
+ } catch (e) {
348
+ console.error("SSR Error:", e);
349
+ console.log("Falling back to CSR...");
350
+ // fallback to CSR (아래 로직 실행)
351
+ }
352
+ }
353
+ // CSR fallback
354
+ try {
355
+ const fs = await import("node:fs/promises");
356
+ let template = await fs.readFile(path.join(this.viteServer.config.root, "index.html"), "utf-8");
357
+ template = await this.viteServer.transformIndexHtml(url, template);
358
+ reply.type("text/html").send(template);
359
+ return;
360
+ } catch (e) {
361
+ this.viteServer.ssrFixStacktrace(e);
362
+ console.error(e);
363
+ reply.status(500).send(e.message);
364
+ return;
290
365
  }
366
+ });
367
+ // 서버 종료 시 Vite도 종료
368
+ server.addHook("onClose", async ()=>{
369
+ await this.viteServer.close();
370
+ });
371
+ console.log("✓ Vite dev server integrated");
372
+ }
373
+ async setupStaticWebServer(server, _webPath, config) {
374
+ // 경로 명확화: api/public/web, api/dist/ssr
375
+ const webDistPath = path.join(this.apiRootPath, "public", "web");
376
+ const ssrPath = path.join(this.apiRootPath, "dist", "ssr");
377
+ if (!fs.existsSync(webDistPath)) {
378
+ console.warn(`⚠ Web dist not found: ${webDistPath}`);
379
+ return;
291
380
  }
381
+ // SSR entry 존재 여부 확인
382
+ const ssrEntryPath = path.join(ssrPath, "entry-server.generated.js");
383
+ const ssrAvailable = fs.existsSync(ssrEntryPath);
384
+ if (!ssrAvailable) {
385
+ console.warn(`⚠ SSR entry not found: ${ssrEntryPath}`);
386
+ console.warn(" SSR will be disabled. Only CSR will work.");
387
+ }
388
+ // SSR 라우트 로드 (production에서만, 사용자 프로젝트의 ssr/routes.ts)
389
+ if (ssrAvailable) {
390
+ const ssrRoutesPath = path.join(this.apiRootPath, "dist", "ssr", "routes.js");
391
+ if (fs.existsSync(ssrRoutesPath)) {
392
+ await import(ssrRoutesPath);
393
+ console.log("✓ SSR routes loaded");
394
+ } else {
395
+ console.warn(`⚠ SSR routes not found: ${ssrRoutesPath}`);
396
+ }
397
+ }
398
+ // 롤링 업데이트 대응: asset hash 불일치 시 현재 버전 직접 서빙
399
+ server.get("/assets/:filename", async (request, reply)=>{
400
+ const requestedFile = request.params.filename;
401
+ const assetsDir = path.join(webDistPath, "assets");
402
+ // index-*.js 또는 index-*.css 요청인 경우
403
+ if (/^index-[a-f0-9]+\.(js|css)$/.test(requestedFile)) {
404
+ const ext = requestedFile.split(".").pop();
405
+ const files = fs.readdirSync(assetsDir);
406
+ const currentFile = files.find((f)=>f.startsWith("index-") && f.endsWith(`.${ext}`));
407
+ if (currentFile) {
408
+ const filePath = path.join(assetsDir, currentFile);
409
+ const content = fs.readFileSync(filePath);
410
+ reply.type(ext === "js" ? "application/javascript" : "text/css");
411
+ reply.header("Cache-Control", "public, max-age=31536000, immutable");
412
+ return reply.send(content);
413
+ }
414
+ }
415
+ // 일반 파일 서빙
416
+ const filePath = path.join(assetsDir, requestedFile);
417
+ if (fs.existsSync(filePath)) {
418
+ const content = fs.readFileSync(filePath);
419
+ const ext = requestedFile.split(".").pop();
420
+ reply.type(ext === "js" ? "application/javascript" : ext === "css" ? "text/css" : "");
421
+ if (requestedFile.includes("-")) {
422
+ reply.header("Cache-Control", "public, max-age=31536000, immutable");
423
+ }
424
+ return reply.send(content);
425
+ }
426
+ reply.code(404).send("Not found");
427
+ });
428
+ // SPA/SSR 라우팅
429
+ server.setNotFoundHandler(async (request, reply)=>{
430
+ // /api, /sonamu-ui는 404 그대로
431
+ if (request.url.startsWith("/api") || request.url.startsWith("/sonamu-ui")) {
432
+ reply.code(404).send({
433
+ error: "Not Found"
434
+ });
435
+ return;
436
+ }
437
+ const url = request.url;
438
+ // SSR 라우트 체크
439
+ if (ssrAvailable) {
440
+ const { matchSSRRoute } = await import("../ssr/index.js");
441
+ const match = matchSSRRoute(url);
442
+ if (match) {
443
+ try {
444
+ // renderSSR 재사용 (vite 없이 호출 = production 모드)
445
+ const { renderSSR } = await import("../ssr/renderer.js");
446
+ const html = await renderSSR(url, match.route, match.params, request, reply, config);
447
+ reply.type("text/html").send(html);
448
+ console.log(`[SSR] Matched route: ${match.route.path}`);
449
+ return;
450
+ } catch (e) {
451
+ console.error("[SSR Error]", {
452
+ url: request.url,
453
+ route: match.route.path,
454
+ error: e instanceof Error ? e.message : String(e),
455
+ timestamp: new Date().toISOString()
456
+ });
457
+ // CSR로 fallback
458
+ }
459
+ }
460
+ }
461
+ // CSR fallback (SSR 실패 시 또는 SSR 라우트가 아닌 경우)
462
+ const indexPath = path.join(webDistPath, "index.html");
463
+ const html = fs.readFileSync(indexPath, "utf-8");
464
+ reply.type("text/html").send(html);
465
+ });
466
+ console.log(`✓ Static web server configured with ${ssrAvailable ? "SSR" : "CSR only"} support`);
292
467
  }
293
468
  createApiHandler(api, config) {
294
469
  return async (request, reply)=>{
@@ -332,6 +507,25 @@ class SonamuClass {
332
507
  return this.invokeModelMethod(api, args, context, reply);
333
508
  };
334
509
  }
510
+ /**
511
+ * SSR용 API 호출 (HTTP 오버헤드 없이 직접 호출)
512
+ * createApiHandler의 로직을 재사용하되, request 파싱 대신 params 직접 사용
513
+ */ async invokeApiForSSR(api, // biome-ignore lint/suspicious/noExplicitAny: SSR에서 다양한 타입의 params를 받아야 함
514
+ params, config, request, reply) {
515
+ // Context 생성 (기존 메소드 재사용)
516
+ const context = await this.createContext(config, request, reply);
517
+ // args 생성: Context 파라미터는 주입, 나머지는 params에서 가져오기
518
+ const { ApiParamType } = await import("../types/types.js");
519
+ let paramsIndex = 0;
520
+ const args = api.parameters.map((param)=>{
521
+ if (ApiParamType.isContext(param.type)) {
522
+ return context;
523
+ }
524
+ return params[paramsIndex++];
525
+ });
526
+ // 모델 메서드 호출 (기존 메서드 재사용)
527
+ return this.invokeModelMethod(api, args, context, reply);
528
+ }
335
529
  async invokeModelMethod(api, args, context, reply) {
336
530
  const model = this.syncer.models[api.modelName];
337
531
  return this.asyncLocalStorage.run({
@@ -448,6 +642,25 @@ class SonamuClass {
448
642
  fastifyPassport.registerUserDeserializer(options.userDeserializer);
449
643
  }
450
644
  }
645
+ async initializeCache(config, forTesting) {
646
+ const { setCacheManagerRef } = await import("../cache/decorator.js");
647
+ // 테스트 환경에서 메모리 드라이버 자동 사용
648
+ if (forTesting) {
649
+ const { createTestCacheManager } = await import("../cache/cache-manager.js");
650
+ this._cache = createTestCacheManager();
651
+ setCacheManagerRef(this._cache);
652
+ return;
653
+ }
654
+ // 설정이 없으면 캐시 비활성화
655
+ if (!config) {
656
+ setCacheManagerRef(null);
657
+ return;
658
+ }
659
+ // 설정에 따라 CacheManager 생성
660
+ const { createCacheManager } = await import("../cache/cache-manager.js");
661
+ this._cache = createCacheManager(config);
662
+ setCacheManagerRef(this._cache);
663
+ }
451
664
  async initializeWorkflows(options) {
452
665
  const { WorkflowManager } = await import("../tasks/workflow-manager.js");
453
666
  // NOTE: @sonamu-kit/tasks 안에선 knex config를 수정하기 때문에 connection이 아닌 config 째로 보냅니다.
@@ -532,11 +745,16 @@ class SonamuClass {
532
745
  }
533
746
  async destroy() {
534
747
  const { BaseModel } = await import("../database/base-model.js");
748
+ // 먼저 처리해야함.
535
749
  await BaseModel.destroy();
536
- await this._workflows?.destroy();
537
- await this.watcher?.close();
750
+ await Promise.allSettled([
751
+ this._workflows?.destroy() ?? Promise.resolve(),
752
+ this._cache?.disconnect() ?? Promise.resolve(),
753
+ this.watcher?.close() ?? Promise.resolve(),
754
+ logtapeDispose()
755
+ ]);
538
756
  }
539
757
  }
540
758
  export const Sonamu = new SonamuClass();
541
759
 
542
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9hcGkvc29uYW11LnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBhc3NlcnQgZnJvbSBcImFzc2VydFwiO1xuaW1wb3J0IHsgQXN5bmNMb2NhbFN0b3JhZ2UgfSBmcm9tIFwiYXN5bmNfaG9va3NcIjtcbmltcG9ydCB0eXBlIHsgRlNXYXRjaGVyIH0gZnJvbSBcImNob2tpZGFyXCI7XG5pbXBvcnQgdHlwZSB7IEZhc3RpZnlJbnN0YW5jZSwgRmFzdGlmeVJlcGx5LCBGYXN0aWZ5UmVxdWVzdCB9IGZyb20gXCJmYXN0aWZ5XCI7XG5pbXBvcnQgdHlwZSB7IEluY29taW5nTWVzc2FnZSwgU2VydmVyLCBTZXJ2ZXJSZXNwb25zZSB9IGZyb20gXCJodHRwXCI7XG5pbXBvcnQgb3MgZnJvbSBcIm9zXCI7XG5pbXBvcnQgcGF0aCBmcm9tIFwicGF0aFwiO1xuaW1wb3J0IHR5cGUgeyBab2RPYmplY3QgfSBmcm9tIFwiem9kXCI7XG5pbXBvcnQgeyBjcmVhdGVNb2NrU1NFRmFjdG9yeSwgREIsIGlzRGFlbW9uU2VydmVyIH0gZnJvbSBcIi4uXCI7XG5pbXBvcnQgdHlwZSB7IFNvbmFtdURCQ29uZmlnIH0gZnJvbSBcIi4uL2RhdGFiYXNlL2RiXCI7XG5pbXBvcnQgeyBOYWl0ZSB9IGZyb20gXCIuLi9uYWl0ZS9uYWl0ZVwiO1xuaW1wb3J0IHR5cGUgeyBTdG9yYWdlTWFuYWdlciB9IGZyb20gXCIuLi9zdG9yYWdlL3N0b3JhZ2UtbWFuYWdlclwiO1xuaW1wb3J0IHR5cGUgeyBTeW5jZXIgfSBmcm9tIFwiLi4vc3luY2VyL3N5bmNlclwiO1xuaW1wb3J0IHR5cGUgeyBXb3JrZmxvd01hbmFnZXIgfSBmcm9tIFwiLi4vdGFza3Mvd29ya2Zsb3ctbWFuYWdlclwiO1xuaW1wb3J0IHR5cGUgeyBTb25hbXVGYXN0aWZ5Q29uZmlnIH0gZnJvbSBcIi4uL3R5cGVzL3R5cGVzXCI7XG5pbXBvcnQgdHlwZSB7IEFic29sdXRlUGF0aCB9IGZyb20gXCIuLi91dGlscy9wYXRoLXV0aWxzXCI7XG5pbXBvcnQgdHlwZSB7IFNvbmFtdUNvbmZpZywgU29uYW11U2VydmVyT3B0aW9ucywgU29uYW11VGFza09wdGlvbnMgfSBmcm9tIFwiLi9jb25maWdcIjtcbmltcG9ydCB0eXBlIHsgQXV0aENvbnRleHQsIENvbnRleHQsIFVwbG9hZENvbnRleHQgfSBmcm9tIFwiLi9jb250ZXh0XCI7XG5pbXBvcnQgdHlwZSB7IEV4dGVuZGVkQXBpIH0gZnJvbSBcIi4vZGVjb3JhdG9yc1wiO1xuXG5leHBvcnQgdHlwZSBTb25hbXVTZWNyZXRzID0ge1xuICBhbnRocm9waWNfYXBpX2tleT86IHN0cmluZztcbiAgdm95YWdlX2FwaV9rZXk/OiBzdHJpbmc7XG4gIG9wZW5haV9hcGlfa2V5Pzogc3RyaW5nO1xufTtcbmNsYXNzIFNvbmFtdUNsYXNzIHtcbiAgcHVibGljIGlzSW5pdGlhbGl6ZWQ6IGJvb2xlYW4gPSBmYWxzZTtcbiAgcHVibGljIGFzeW5jTG9jYWxTdG9yYWdlOiBBc3luY0xvY2FsU3RvcmFnZTx7XG4gICAgY29udGV4dDogQ29udGV4dDtcbiAgfT4gPSBuZXcgQXN5bmNMb2NhbFN0b3JhZ2UoKTtcblxuICBwdWJsaWMgdXBsb2FkU3RvcmFnZTogQXN5bmNMb2NhbFN0b3JhZ2U8e1xuICAgIHVwbG9hZENvbnRleHQ6IFVwbG9hZENvbnRleHQ7XG4gIH0+ID0gbmV3IEFzeW5jTG9jYWxTdG9yYWdlKCk7XG5cbiAgcHVibGljIGdldENvbnRleHQoKTogQ29udGV4dCB7XG4gICAgY29uc3Qgc3RvcmUgPSB0aGlzLmFzeW5jTG9jYWxTdG9yYWdlLmdldFN0b3JlKCk7XG4gICAgaWYgKHN0b3JlPy5jb250ZXh0KSB7XG4gICAgICByZXR1cm4gc3RvcmUuY29udGV4dDtcbiAgICB9XG5cbiAgICBpZiAocHJvY2Vzcy5lbnYuTk9ERV9FTlYgPT09IFwidGVzdFwiKSB7XG4gICAgICAvLyDthYzsiqTtjIUg7ZmY6rK97JeQ7IScIOy7qO2FjeyKpO2KuOqwgCDso7zsnoXrkJjsp4Ag7JWK7J2AIOqyveyasCDruYgg7Luo7YWN7Iqk7Yq4IOumrO2EtFxuICAgICAgcmV0dXJuIHtcbiAgICAgICAgcmVxdWVzdDogbnVsbCxcbiAgICAgICAgcmVwbHk6IG51bGwsXG4gICAgICAgIGhlYWRlcnM6IHt9LFxuICAgICAgICBjcmVhdGVTU0U6IChzY2hlbWE6IFpvZE9iamVjdCkgPT4gY3JlYXRlTW9ja1NTRUZhY3Rvcnkoc2NoZW1hKSxcbiAgICAgICAgLy8gYmlvbWUtaWdub3JlIGxpbnQvc3VzcGljaW91cy9ub0V4cGxpY2l0QW55OiDthYzsiqTtjIUg7ZmY6rK97JeQ7IScIOy7qO2FjeyKpO2KuOqwgCDso7zsnoXrkJjsp4Ag7JWK7J2AIOqyveyasCDruYgg7Luo7YWN7Iqk7Yq4IOumrO2EtFxuICAgICAgICBuYWl0ZVN0b3JlOiBuZXcgTWFwPHN0cmluZywgYW55PigpLFxuICAgICAgfSBhcyB1bmtub3duIGFzIENvbnRleHQ7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIlNvbmFtdSBjYW5ub3QgZmluZCBjb250ZXh0XCIpO1xuICAgIH1cbiAgfVxuXG4gIHB1YmxpYyBnZXRVcGxvYWRDb250ZXh0KCk6IFVwbG9hZENvbnRleHQge1xuICAgIGNvbnN0IHN0b3JlID0gdGhpcy51cGxvYWRTdG9yYWdlLmdldFN0b3JlKCk7XG4gICAgaWYgKHN0b3JlPy51cGxvYWRDb250ZXh0KSB7XG4gICAgICByZXR1cm4gc3RvcmUudXBsb2FkQ29udGV4dDtcbiAgICB9XG4gICAgdGhyb3cgbmV3IEVycm9yKFwiU29uYW11IGNhbm5vdCBmaW5kIHVwbG9hZCBjb250ZXh0LiBEaWQgeW91IHVzZSBAdXBsb2FkIGRlY29yYXRvcj9cIik7XG4gIH1cblxuICBwcml2YXRlIF9hcGlSb290UGF0aDogQWJzb2x1dGVQYXRoIHwgbnVsbCA9IG51bGw7XG4gIHNldCBhcGlSb290UGF0aChhcGlSb290UGF0aDogQWJzb2x1dGVQYXRoKSB7XG4gICAgdGhpcy5fYXBpUm9vdFBhdGggPSBhcGlSb290UGF0aDtcbiAgfVxuICBnZXQgYXBpUm9vdFBhdGgoKTogQWJzb2x1dGVQYXRoIHtcbiAgICBpZiAodGhpcy5fYXBpUm9vdFBhdGggPT09IG51bGwpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIlNvbmFtdSBoYXMgbm90IGJlZW4gaW5pdGlhbGl6ZWRcIik7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLl9hcGlSb290UGF0aDtcbiAgfVxuICBnZXQgYXBwUm9vdFBhdGgoKTogc3RyaW5nIHtcbiAgICByZXR1cm4gdGhpcy5hcGlSb290UGF0aC5zcGxpdChwYXRoLnNlcCkuc2xpY2UoMCwgLTEpLmpvaW4ocGF0aC5zZXApO1xuICB9XG5cbiAgcHJpdmF0ZSBfZGJDb25maWc6IFNvbmFtdURCQ29uZmlnIHwgbnVsbCA9IG51bGw7XG4gIHNldCBkYkNvbmZpZyhkYkNvbmZpZzogU29uYW11REJDb25maWcpIHtcbiAgICB0aGlzLl9kYkNvbmZpZyA9IGRiQ29uZmlnO1xuICB9XG4gIGdldCBkYkNvbmZpZygpOiBTb25hbXVEQkNvbmZpZyB7XG4gICAgaWYgKHRoaXMuX2RiQ29uZmlnID09PSBudWxsKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJTb25hbXUgaGFzIG5vdCBiZWVuIGluaXRpYWxpemVkXCIpO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5fZGJDb25maWc7XG4gIH1cblxuICBwcml2YXRlIF9zeW5jZXI6IFN5bmNlciB8IG51bGwgPSBudWxsO1xuICBzZXQgc3luY2VyKHN5bmNlcjogU3luY2VyKSB7XG4gICAgdGhpcy5fc3luY2VyID0gc3luY2VyO1xuICB9XG4gIGdldCBzeW5jZXIoKTogU3luY2VyIHtcbiAgICBpZiAodGhpcy5fc3luY2VyID09PSBudWxsKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJTb25hbXUgaGFzIG5vdCBiZWVuIGluaXRpYWxpemVkXCIpO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5fc3luY2VyO1xuICB9XG5cbiAgcHJpdmF0ZSBfY29uZmlnOiBTb25hbXVDb25maWcgfCBudWxsID0gbnVsbDtcbiAgc2V0IGNvbmZpZyhjb25maWc6IFNvbmFtdUNvbmZpZykge1xuICAgIHRoaXMuX2NvbmZpZyA9IGNvbmZpZztcbiAgfVxuICBnZXQgY29uZmlnKCk6IFNvbmFtdUNvbmZpZyB7XG4gICAgaWYgKHRoaXMuX2NvbmZpZyA9PT0gbnVsbCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiU29uYW11IGhhcyBub3QgYmVlbiBpbml0aWFsaXplZFwiKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuX2NvbmZpZztcbiAgfVxuXG4gIHByaXZhdGUgX3NlY3JldHM6IFNvbmFtdVNlY3JldHMgfCBudWxsID0gbnVsbDtcbiAgc2V0IHNlY3JldHMoc2VjcmV0czogU29uYW11U2VjcmV0cykge1xuICAgIHRoaXMuX3NlY3JldHMgPSBzZWNyZXRzO1xuICB9XG4gIGdldCBzZWNyZXRzKCk6IFNvbmFtdVNlY3JldHMgfCBudWxsIHtcbiAgICByZXR1cm4gdGhpcy5fc2VjcmV0cztcbiAgfVxuXG4gIHByaXZhdGUgX3N0b3JhZ2U6IFN0b3JhZ2VNYW5hZ2VyIHwgbnVsbCA9IG51bGw7XG4gIC8qKlxuICAgKiBTdG9yYWdlTWFuYWdlciDsnbjsiqTthLTsiqRcbiAgICovXG4gIGdldCBzdG9yYWdlKCk6IFN0b3JhZ2VNYW5hZ2VyIHtcbiAgICBpZiAoIXRoaXMuX3N0b3JhZ2UpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIlN0b3JhZ2UgaGFzIG5vdCBiZWVuIGluaXRpYWxpemVkLiBDaGVjayBzdG9yYWdlIGNvbmZpZy5cIik7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLl9zdG9yYWdlO1xuICB9XG5cbiAgcHJpdmF0ZSBfd29ya2Zsb3dzOiBXb3JrZmxvd01hbmFnZXIgfCBudWxsID0gbnVsbDtcbiAgZ2V0IHdvcmtmbG93cygpOiBXb3JrZmxvd01hbmFnZXIge1xuICAgIGlmICh0aGlzLl93b3JrZmxvd3MgPT09IG51bGwpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIlNvbmFtdSBoYXMgbm90IGJlZW4gaW5pdGlhbGl6ZWRcIik7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMuX3dvcmtmbG93cztcbiAgfVxuXG4gIC8vIEhNUiDsspjrpqxcbiAgcHVibGljIHdhdGNoZXI6IEZTV2F0Y2hlciB8IG51bGwgPSBudWxsO1xuICBwcml2YXRlIHBlbmRpbmdGaWxlczogc3RyaW5nW10gPSBbXTtcbiAgcHJpdmF0ZSBobXJTdGFydFRpbWU6IG51bWJlciA9IDA7XG5cbiAgcHVibGljIHNlcnZlcjogRmFzdGlmeUluc3RhbmNlIHwgbnVsbCA9IG51bGw7XG5cbiAgYXN5bmMgaW5pdEZvclRlc3RpbmcoKSB7XG4gICAgYXdhaXQgdGhpcy5pbml0KHRydWUsIGZhbHNlLCB1bmRlZmluZWQsIHRydWUpO1xuICB9XG5cbiAgYXN5bmMgaW5pdChcbiAgICBkb1NpbGVudDogYm9vbGVhbiA9IGZhbHNlLFxuICAgIGVuYWJsZVN5bmM6IGJvb2xlYW4gPSB0cnVlLFxuICAgIGFwaVJvb3RQYXRoPzogQWJzb2x1dGVQYXRoLFxuICAgIGZvclRlc3Rpbmc6IGJvb2xlYW4gPSBmYWxzZSxcbiAgKSB7XG4gICAgaWYgKHRoaXMuaXNJbml0aWFsaXplZCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmICghZG9TaWxlbnQpIHtcbiAgICAgIGNvbnN0IGNoYWxrID0gKGF3YWl0IGltcG9ydChcImNoYWxrXCIpKS5kZWZhdWx0O1xuICAgICAgY29uc29sZS50aW1lKGNoYWxrLmN5YW4oYFNvbmFtdS5pbml0JHtmb3JUZXN0aW5nID8gXCIgZm9yIHRlc3RpbmdcIiA6IFwiXCJ9YCkpO1xuICAgIH1cblxuICAgIC8vIEFQSSDro6jtirgg7Yyo7IqkXG4gICAgY29uc3QgeyBmaW5kQXBpUm9vdFBhdGggfSA9IGF3YWl0IGltcG9ydChcIi4uL3V0aWxzL3V0aWxzXCIpO1xuICAgIHRoaXMuYXBpUm9vdFBhdGggPSBhcGlSb290UGF0aCA/PyBmaW5kQXBpUm9vdFBhdGgoKTtcblxuICAgIGNvbnN0IHsgbG9hZENvbmZpZyB9ID0gYXdhaXQgaW1wb3J0KFwiLi9jb25maWdcIik7XG4gICAgdGhpcy5jb25maWcgPSBhd2FpdCBsb2FkQ29uZmlnKHRoaXMuYXBpUm9vdFBhdGgpO1xuICAgIC8vIHNvbmFtdS5jb25maWcudHMg6riw67O46rCSIOyEpOyglVxuICAgIHRoaXMuY29uZmlnLmRhdGFiYXNlLmRhdGFiYXNlID0gdGhpcy5jb25maWcuZGF0YWJhc2UuZGF0YWJhc2UgPz8gXCJwb3N0Z3Jlc3FsXCI7XG5cbiAgICAvLyBBUEkg7YKkIO2ZmOqyveuzgOyImCDroZzrk5xcbiAgICBjb25zdCBzZWNyZXRzOiBTb25hbXVTZWNyZXRzID0ge307XG4gICAgaWYgKHByb2Nlc3MuZW52LkFOVEhST1BJQ19BUElfS0VZKSB7XG4gICAgICBzZWNyZXRzLmFudGhyb3BpY19hcGlfa2V5ID0gcHJvY2Vzcy5lbnYuQU5USFJPUElDX0FQSV9LRVk7XG4gICAgfVxuICAgIGlmIChwcm9jZXNzLmVudi5WT1lBR0VfQVBJX0tFWSkge1xuICAgICAgc2VjcmV0cy52b3lhZ2VfYXBpX2tleSA9IHByb2Nlc3MuZW52LlZPWUFHRV9BUElfS0VZO1xuICAgIH1cbiAgICBpZiAocHJvY2Vzcy5lbnYuT1BFTkFJX0FQSV9LRVkpIHtcbiAgICAgIHNlY3JldHMub3BlbmFpX2FwaV9rZXkgPSBwcm9jZXNzLmVudi5PUEVOQUlfQVBJX0tFWTtcbiAgICB9XG4gICAgaWYgKE9iamVjdC5rZXlzKHNlY3JldHMpLmxlbmd0aCA+IDApIHtcbiAgICAgIHRoaXMuc2VjcmV0cyA9IHNlY3JldHM7XG4gICAgfVxuXG4gICAgLy8gREIg66Gc65OcXG4gICAgY29uc3QgeyBEQiB9ID0gYXdhaXQgaW1wb3J0KFwiLi4vZGF0YWJhc2UvZGJcIik7XG4gICAgdGhpcy5kYkNvbmZpZyA9IERCLmdlbmVyYXRlREJDb25maWcodGhpcy5jb25maWcuZGF0YWJhc2UpO1xuICAgIGlmICghZG9TaWxlbnQpIHtcbiAgICAgIGNvbnN0IGNoYWxrID0gKGF3YWl0IGltcG9ydChcImNoYWxrXCIpKS5kZWZhdWx0O1xuICAgICAgY29uc29sZS5sb2coY2hhbGsuZ3JlZW4oXCJEQiBDb25maWcgTG9hZGVkIVwiKSk7XG4gICAgfVxuXG4gICAgLy8gRW50aXR5IOuhnOuTnFxuICAgIC8vIO2FjOyKpO2KuOyXkOyEnOuPhCBFbnRpdHkg7KCV67O064qUIO2VhOyalO2VqeuLiOuLpC5cbiAgICAvLyB1cHNlcnTqsIAg7KCc64yA66GcIOyekeuPme2VmOugpOuptCBlbnRpdHnsnZggdW5pcXVlIGluZGV4IOygleuztOqwgCDtlYTsmpTtlZjquLAg65WM66y47J6F64uI64ukLlxuICAgIGNvbnN0IHsgRW50aXR5TWFuYWdlciB9ID0gYXdhaXQgaW1wb3J0KFwiLi4vZW50aXR5L2VudGl0eS1tYW5hZ2VyXCIpO1xuICAgIGF3YWl0IEVudGl0eU1hbmFnZXIuYXV0b2xvYWQoZG9TaWxlbnQpO1xuXG4gICAgLy8g7YWM7Iqk7YyF7J24IOqyveyasCDsi7Htgawg7JeG7J20IOykkeuLqFxuICAgIGlmIChmb3JUZXN0aW5nKSB7XG4gICAgICB0aGlzLmlzSW5pdGlhbGl6ZWQgPSB0cnVlO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIFRhc2sg65Ox66GdXG4gICAgYXdhaXQgdGhpcy5pbml0aWFsaXplV29ya2Zsb3dzKHRoaXMuY29uZmlnLnRhc2tzKTtcblxuICAgIC8vIFN5bmNlclxuICAgIGNvbnN0IHsgU3luY2VyIH0gPSBhd2FpdCBpbXBvcnQoXCIuLi9zeW5jZXIvc3luY2VyXCIpO1xuICAgIHRoaXMuc3luY2VyID0gbmV3IFN5bmNlcigpO1xuXG4gICAgLy8gQXV0b2xvYWQ6IE1vZGVscyAvIFR5cGVzIC8gQVBJc1xuICAgIGF3YWl0IHRoaXMuc3luY2VyLmF1dG9sb2FkVHlwZXMoKTtcbiAgICBhd2FpdCB0aGlzLnN5bmNlci5hdXRvbG9hZE1vZGVscygpO1xuICAgIGF3YWl0IHRoaXMuc3luY2VyLmF1dG9sb2FkQXBpcygpO1xuICAgIGF3YWl0IHRoaXMuc3luY2VyLmF1dG9sb2FkV29ya2Zsb3dzKCk7XG5cbiAgICBjb25zdCB7IFRlbXBsYXRlTWFuYWdlciB9ID0gYXdhaXQgaW1wb3J0KFwiLi4vdGVtcGxhdGVcIik7XG4gICAgYXdhaXQgVGVtcGxhdGVNYW5hZ2VyLmF1dG9sb2FkKCk7XG5cbiAgICBjb25zdCB7IGlzTG9jYWwsIGlzVGVzdCB9ID0gYXdhaXQgaW1wb3J0KFwiLi4vdXRpbHMvY29udHJvbGxlclwiKTtcbiAgICBpZiAoaXNMb2NhbCgpKSB7XG4gICAgICAvLyDroZzsu6zsl5DshJzripQg7L2U65OcIOyDneyEseydhCDsnITtlbQgQmlvbWUg7IWL7JeF7J20IO2VhOyalO2VqCAo7ZiE7J6sIGFwaVJvb3RQYXRoIOyghOuLrO2VmOyXrCDsi6TtlokpXG4gICAgICAoYXdhaXQgaW1wb3J0KFwiLi4vdXRpbHMvZm9ybWF0dGVyXCIpKS5zZXR1cEJpb21lKHRoaXMuYXBpUm9vdFBhdGgpO1xuICAgIH1cblxuICAgIGNvbnN0IHsgaXNIb3RSZWxvYWRTZXJ2ZXIgfSA9IGF3YWl0IGltcG9ydChcIi4uL3V0aWxzL2NvbnRyb2xsZXJcIik7XG4gICAgaWYgKGlzTG9jYWwoKSAmJiAhaXNUZXN0KCkgJiYgaXNIb3RSZWxvYWRTZXJ2ZXIoKSAmJiBlbmFibGVTeW5jKSB7XG4gICAgICBhd2FpdCB0aGlzLnN5bmNlci5zeW5jKCk7XG5cbiAgICAgIGF3YWl0IHRoaXMuc3RhcnRXYXRjaGVyKCk7XG4gICAgfVxuXG4gICAgdGhpcy5pc0luaXRpYWxpemVkID0gdHJ1ZTtcbiAgICBpZiAoIWRvU2lsZW50KSB7XG4gICAgICBjb25zdCBjaGFsayA9IChhd2FpdCBpbXBvcnQoXCJjaGFsa1wiKSkuZGVmYXVsdDtcbiAgICAgIGNvbnNvbGUudGltZUVuZChjaGFsay5jeWFuKFwiU29uYW11LmluaXRcIikpO1xuICAgIH1cbiAgfVxuXG4gIGFzeW5jIGNyZWF0ZVNlcnZlcihpbml0T3B0aW9ucz86IHsgZW5hYmxlU3luYz86IGJvb2xlYW47IGRvU2lsZW50PzogYm9vbGVhbiB9KSB7XG4gICAgaWYgKHRoaXMuaXNJbml0aWFsaXplZCA9PT0gZmFsc2UpIHtcbiAgICAgIGF3YWl0IHRoaXMuaW5pdChpbml0T3B0aW9ucz8uZG9TaWxlbnQsIGluaXRPcHRpb25zPy5lbmFibGVTeW5jKTtcbiAgICB9XG5cbiAgICBjb25zdCBvcHRpb25zID0gdGhpcy5jb25maWcuc2VydmVyO1xuICAgIGNvbnN0IGZhc3RpZnkgPSAoYXdhaXQgaW1wb3J0KFwiZmFzdGlmeVwiKSkuZGVmYXVsdDtcbiAgICBjb25zdCBzZXJ2ZXIgPSBmYXN0aWZ5KG9wdGlvbnMuZmFzdGlmeSk7XG4gICAgdGhpcy5zZXJ2ZXIgPSBzZXJ2ZXI7XG5cbiAgICAvLyBTdG9yYWdlIOyEpOyglSDihpIgU3RvcmFnZU1hbmFnZXIg7IOd7ISxXG4gICAgaWYgKG9wdGlvbnMuc3RvcmFnZSkge1xuICAgICAgY29uc3QgeyBTdG9yYWdlTWFuYWdlciB9ID0gYXdhaXQgaW1wb3J0KFwiLi4vc3RvcmFnZS9zdG9yYWdlLW1hbmFnZXJcIik7XG4gICAgICB0aGlzLl9zdG9yYWdlID0gbmV3IFN0b3JhZ2VNYW5hZ2VyKG9wdGlvbnMuc3RvcmFnZSk7XG4gICAgfVxuXG4gICAgLy8g7ZSM65+s6re47J24IOuTseuhnVxuICAgIGlmIChvcHRpb25zLnBsdWdpbnMpIHtcbiAgICAgIGF3YWl0IHRoaXMucmVnaXN0ZXJQbHVnaW5zKHNlcnZlciwgb3B0aW9ucy5wbHVnaW5zKTtcbiAgICB9XG5cbiAgICBpZiAob3B0aW9ucy5hdXRoKSB7XG4gICAgICBpZiAoIW9wdGlvbnMucGx1Z2lucz8uc2Vzc2lvbikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJBdXRoIHJlcXVpcmVzIHNlc3Npb24gcGx1Z2luLiBQbGVhc2UgYWRkIHBsdWdpbnMuc2Vzc2lvbiBjb25maWd1cmF0aW9uLlwiKTtcbiAgICAgIH1cblxuICAgICAgYXdhaXQgdGhpcy5yZWdpc3RlckF1dGgoc2VydmVyLCBvcHRpb25zLmF1dGgpO1xuICAgIH1cblxuICAgIC8vIEFQSSDrnbzsmrDtjIUg7ISk7KCVXG4gICAgYXdhaXQgdGhpcy53aXRoRmFzdGlmeShzZXJ2ZXIsIG9wdGlvbnMuYXBpQ29uZmlnLCB7XG4gICAgICBlbmFibGVTeW5jOiBpbml0T3B0aW9ucz8uZW5hYmxlU3luYyxcbiAgICAgIGRvU2lsZW50OiBpbml0T3B0aW9ucz8uZG9TaWxlbnQsXG4gICAgfSk7XG5cbiAgICAvLyDshJzrsoQg7Iuc7J6RXG4gICAgYXdhaXQgdGhpcy5ib290KHNlcnZlciwgb3B0aW9ucyk7XG5cbiAgICByZXR1cm4gc2VydmVyO1xuICB9XG5cbiAgYXN5bmMgd2l0aEZhc3RpZnkoXG4gICAgc2VydmVyOiBGYXN0aWZ5SW5zdGFuY2U8U2VydmVyLCBJbmNvbWluZ01lc3NhZ2UsIFNlcnZlclJlc3BvbnNlPixcbiAgICBjb25maWc6IFNvbmFtdUZhc3RpZnlDb25maWcsXG4gICAgb3B0aW9ucz86IHtcbiAgICAgIGVuYWJsZVN5bmM/OiBib29sZWFuO1xuICAgICAgZG9TaWxlbnQ/OiBib29sZWFuO1xuICAgIH0sXG4gICkge1xuICAgIGlmICh0aGlzLmlzSW5pdGlhbGl6ZWQgPT09IGZhbHNlKSB7XG4gICAgICBhd2FpdCB0aGlzLmluaXQob3B0aW9ucz8uZG9TaWxlbnQsIG9wdGlvbnM/LmVuYWJsZVN5bmMpO1xuICAgIH1cblxuICAgIHRoaXMuc2VydmVyID0gc2VydmVyO1xuXG4gICAgLy8gdGltZXpvbmUg7ISk7KCVXG4gICAgY29uc3QgdGltZXpvbmUgPSB0aGlzLmNvbmZpZy5hcGkudGltZXpvbmU7XG4gICAgaWYgKHRpbWV6b25lKSB7XG4gICAgICAvLyDtg4DsnoTsobTsl5Ag66ee6rKMIOydkeuLtSDrgqDsp5wg7Iqk7Yq466eB7J2EIOuzgO2ZmO2VtOyjvOyWtOyVvCDtlanri4jri6QuXG4gICAgICAvLyDqsIDroLkgdGltZXpvbmXsnbQgXCJBc2lhL1Nlb3VsXCIg7J2066m0XG4gICAgICAvLyBcIjIwMjUtMTEtMjFUMDA6MDA6MDAuMDAwWlwiIOulvCBcIjIwMjUtMTEtMjFUMDk6MDA6MDArMDk6MDBcIiDsnLzroZwg67OA7ZmY7ZW07KO87Ja07JW8IO2VqeuLiOuLpC5cbiAgICAgIGNvbnN0IHsgZm9ybWF0SW5UaW1lWm9uZSB9ID0gYXdhaXQgaW1wb3J0KFwiZGF0ZS1mbnMtdHpcIik7XG5cbiAgICAgIC8vIElTTyA4NjAxIOuCoOynnCDtmJXsi50g7KCV6rec7IudICjsmIg6IDIwMjQtMDEtMTVUMDk6MzA6MDAuMDAwWilcbiAgICAgIGNvbnN0IElTT19EQVRFX1JFR0VYID0gL15cXGR7NH0tXFxkezJ9LVxcZHsyfVRcXGR7Mn06XFxkezJ9OlxcZHsyfShcXC5cXGR7M30pP1okLztcblxuICAgICAgLy8gVOulvCDrkZjrn6zsi7wg7J6R7J2A65Sw7Ji07ZGc6rCAIOyXhuuLpOuptCBcIjIwMjUtMTEtMTkxNzYzNTQ2MTg5MDAwMTg6NTY6MjkrMDk6MDBcIuyZgCDqsJnsnYAg6rKw6rO86rCAIOuCmOyYteuLiOuLpC5cbiAgICAgIC8vIOydtOuKlCBkYXRlLWZucyDtirnsnoXri4jri6QuXG4gICAgICAvLyDsnbTroIfqsowg7ZW064+EIOq0nOywruyKteuLiOuLpC4gXCIyMDI1LTExLTE5VDE4OjU2OjI5KzA5OjAwXCIg66qo7JaR7Jy866GcIOyemCDrgpjsmLXri4jri6QuXG4gICAgICBjb25zdCBEQVRFX0ZPUk1BVCA9IFwieXl5eS1NTS1kZCdUJ0hIOm1tOnNzWFhYXCI7XG5cbiAgICAgIHNlcnZlci5zZXRSZXBseVNlcmlhbGl6ZXIoKHBheWxvYWQpID0+IHtcbiAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHBheWxvYWQsIChfa2V5LCB2YWx1ZSkgPT4ge1xuICAgICAgICAgIGlmICh0eXBlb2YgdmFsdWUgPT09IFwic3RyaW5nXCIgJiYgSVNPX0RBVEVfUkVHRVgudGVzdCh2YWx1ZSkpIHtcbiAgICAgICAgICAgIHJldHVybiBmb3JtYXRJblRpbWVab25lKFxuICAgICAgICAgICAgICBuZXcgRGF0ZSh2YWx1ZSksXG4gICAgICAgICAgICAgIHRpbWV6b25lIGFzIGAke3N0cmluZ30vJHtzdHJpbmd9YCxcbiAgICAgICAgICAgICAgREFURV9GT1JNQVQsXG4gICAgICAgICAgICApO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gdmFsdWU7XG4gICAgICAgIH0pO1xuICAgICAgfSk7XG4gICAgICBpZiAoIW9wdGlvbnM/LmRvU2lsZW50KSB7XG4gICAgICAgIGNvbnN0IGNoYWxrID0gKGF3YWl0IGltcG9ydChcImNoYWxrXCIpKS5kZWZhdWx0O1xuICAgICAgICBjb25zb2xlLmxvZyhjaGFsay5ncmVlbihgVGltZXpvbmUgc2V0IHRvICR7dGltZXpvbmV9YCkpO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIOyghOyytCDrnbzsmrDtjIUg66as7Iqk7Yq4XG4gICAgc2VydmVyLmdldChcbiAgICAgIGAke3RoaXMuY29uZmlnLmFwaS5yb3V0ZS5wcmVmaXh9L3JvdXRlc2AsXG4gICAgICBhc3luYyAoX3JlcXVlc3QsIF9yZXBseSk6IFByb21pc2U8dHlwZW9mIHRoaXMuc3luY2VyLmFwaXM+ID0+IHtcbiAgICAgICAgcmV0dXJuIHRoaXMuc3luY2VyLmFwaXM7XG4gICAgICB9LFxuICAgICk7XG5cbiAgICAvLyBIZWFsdGhjaGVjayBBUElcbiAgICBzZXJ2ZXIuZ2V0KFxuICAgICAgYCR7dGhpcy5jb25maWcuYXBpLnJvdXRlLnByZWZpeH0vaGVhbHRoY2hlY2tgLFxuICAgICAgYXN5bmMgKF9yZXF1ZXN0LCBfcmVwbHkpOiBQcm9taXNlPHN0cmluZz4gPT4ge1xuICAgICAgICByZXR1cm4gXCJva1wiO1xuICAgICAgfSxcbiAgICApO1xuXG4gICAgLy8gU29uYW11IFVJIEFQSVxuICAgIGNvbnN0IHsgc29uYW11VUlBcGlQbHVnaW4gfSA9IGF3YWl0IGltcG9ydChcIi4uL3VpL2FwaVwiKTtcbiAgICBzZXJ2ZXIucmVnaXN0ZXIoc29uYW11VUlBcGlQbHVnaW4pO1xuXG4gICAgLy8gQVBJIOudvOyasO2MhSAo66Gc7LusSE1SIOyDge2DnOyZgCDqtazrtoQpXG4gICAgY29uc3QgeyBpc0xvY2FsIH0gPSBhd2FpdCBpbXBvcnQoXCIuLi91dGlscy9jb250cm9sbGVyXCIpO1xuICAgIGlmIChpc0xvY2FsKCkpIHtcbiAgICAgIHNlcnZlci5hbGwoXCIqXCIsIGFzeW5jIChyZXF1ZXN0LCByZXBseSkgPT4ge1xuICAgICAgICAvLyBTb25hbXUgVUlcbiAgICAgICAgaWYgKHJlcXVlc3QudXJsLnN0YXJ0c1dpdGgoXCIvc29uYW11LXVpXCIpKSB7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgZm91bmQgPSB0aGlzLnN5bmNlci5hcGlzLmZpbmQoXG4gICAgICAgICAgKGFwaSkgPT5cbiAgICAgICAgICAgIHRoaXMuY29uZmlnLmFwaS5yb3V0ZS5wcmVmaXggKyBhcGkucGF0aCA9PT0gcmVxdWVzdC51cmwuc3BsaXQoXCI/XCIpWzBdICYmXG4gICAgICAgICAgICAoYXBpLm9wdGlvbnMuaHR0cE1ldGhvZCA/PyBcIkdFVFwiKSA9PT0gcmVxdWVzdC5tZXRob2QudG9VcHBlckNhc2UoKSxcbiAgICAgICAgKTtcbiAgICAgICAgaWYgKGZvdW5kKSB7XG4gICAgICAgICAgcmV0dXJuIHRoaXMuY3JlYXRlQXBpSGFuZGxlcihmb3VuZCwgY29uZmlnKShyZXF1ZXN0LCByZXBseSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAocmVxdWVzdC51cmwuc3RhcnRzV2l0aChcIi9hcGkvXCIpKSB7XG4gICAgICAgICAgY29uc3QgeyBOb3RGb3VuZEV4Y2VwdGlvbiB9ID0gYXdhaXQgaW1wb3J0KFwiLi4vZXhjZXB0aW9ucy9zby1leGNlcHRpb25zXCIpO1xuICAgICAgICAgIHRocm93IG5ldyBOb3RGb3VuZEV4Y2VwdGlvbihg7KG07J6s7ZWY7KeAIOyViuuKlCBBUEkg7KCR6re87J6F64uI64ukLiAke3JlcXVlc3QudXJsfWApO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8g7J2867CYIO2MjOydvCDsoJHqt7zsi5wg67OE64+E7J2YIOyXkOufrCDstpzroKXtlZjsp4Ag7JWK7J2MXG4gICAgICAgIHJldHVybjtcbiAgICAgIH0pO1xuICAgIH0gZWxzZSB7XG4gICAgICBmb3IgKGNvbnN0IGFwaSBvZiB0aGlzLnN5bmNlci5hcGlzKSB7XG4gICAgICAgIC8vIG1vZGVsXG4gICAgICAgIGlmICh0aGlzLnN5bmNlci5tb2RlbHNbYXBpLm1vZGVsTmFtZV0gPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihg7KCV7J2Y65CY7KeAIOyViuydgCDrqqjrjbjsl5Ag7KCR6re8ICR7YXBpLm1vZGVsTmFtZX1gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIHJvdXRlXG4gICAgICAgIHNlcnZlci5yb3V0ZSh7XG4gICAgICAgICAgbWV0aG9kOiBhcGkub3B0aW9ucy5odHRwTWV0aG9kID8/IFwiR0VUXCIsXG4gICAgICAgICAgdXJsOiB0aGlzLmNvbmZpZy5hcGkucm91dGUucHJlZml4ICsgYXBpLnBhdGgsXG4gICAgICAgICAgaGFuZGxlcjogdGhpcy5jcmVhdGVBcGlIYW5kbGVyKGFwaSwgY29uZmlnKSxcbiAgICAgICAgfSk7IC8vIEVORCBzZXJ2ZXIucm91dGVcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBjcmVhdGVBcGlIYW5kbGVyKFxuICAgIGFwaTogRXh0ZW5kZWRBcGksXG4gICAgY29uZmlnOiBTb25hbXVGYXN0aWZ5Q29uZmlnLFxuICApOiAocmVxdWVzdDogRmFzdGlmeVJlcXVlc3QsIHJlcGx5OiBGYXN0aWZ5UmVwbHkpID0+IFByb21pc2U8dW5rbm93bj4ge1xuICAgIHJldHVybiBhc3luYyAocmVxdWVzdDogRmFzdGlmeVJlcXVlc3QsIHJlcGx5OiBGYXN0aWZ5UmVwbHkpOiBQcm9taXNlPHVua25vd24+ID0+IHtcbiAgICAgIChhcGkub3B0aW9ucy5ndWFyZHMgPz8gW10pLmV2ZXJ5KChndWFyZCkgPT4gY29uZmlnLmd1YXJkSGFuZGxlcihndWFyZCwgcmVxdWVzdCwgYXBpKSk7XG5cbiAgICAgIC8vIO2MjOudvOuvuO2EsCDsoJXrs7TroZwgem9kIOyKpO2CpOuniCDruYzrk5xcbiAgICAgIGNvbnN0IHsgZ2V0Wm9kT2JqZWN0RnJvbUFwaSB9ID0gYXdhaXQgaW1wb3J0KFwiLi9jb2RlLWNvbnZlcnRlcnNcIik7XG4gICAgICBjb25zdCBSZXFUeXBlID0gZ2V0Wm9kT2JqZWN0RnJvbUFwaShhcGksIHRoaXMuc3luY2VyLnR5cGVzKTtcblxuICAgICAgLy8gcmVxdWVzdCDtjIzsi7FcbiAgICAgIGNvbnN0IHdoaWNoID0gYXBpLm9wdGlvbnMuaHR0cE1ldGhvZCA9PT0gXCJHRVRcIiA/IFwicXVlcnlcIiA6IFwiYm9keVwiO1xuICAgICAgbGV0IHJlcUJvZHk6IHtcbiAgICAgICAgW2tleTogc3RyaW5nXTogdW5rbm93bjtcbiAgICAgIH07XG4gICAgICB0cnkge1xuICAgICAgICBjb25zdCB7IGZhc3RpZnlDYXN0ZXIgfSA9IGF3YWl0IGltcG9ydChcIi4vY2FzdGVyXCIpO1xuICAgICAgICByZXFCb2R5ID0gZmFzdGlmeUNhc3RlcihSZXFUeXBlKS5wYXJzZShyZXF1ZXN0W3doaWNoXSA/PyB7fSk7XG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIGNvbnN0IHsgWm9kRXJyb3IgfSA9IGF3YWl0IGltcG9ydChcInpvZFwiKTtcbiAgICAgICAgaWYgKGUgaW5zdGFuY2VvZiBab2RFcnJvcikge1xuICAgICAgICAgIGNvbnN0IHsgaHVtYW5pemVab2RFcnJvciB9ID0gYXdhaXQgaW1wb3J0KFwiLi4vdXRpbHMvem9kLWVycm9yXCIpO1xuICAgICAgICAgIGNvbnN0IG1lc3NhZ2VzID0gaHVtYW5pemVab2RFcnJvcihlKVxuICAgICAgICAgICAgLm1hcCgoaXNzdWUpID0+IGlzc3VlLm1lc3NhZ2UpXG4gICAgICAgICAgICAuam9pbihcIiBcIik7XG4gICAgICAgICAgY29uc3QgeyBCYWRSZXF1ZXN0RXhjZXB0aW9uIH0gPSBhd2FpdCBpbXBvcnQoXCIuLi9leGNlcHRpb25zL3NvLWV4Y2VwdGlvbnNcIik7XG4gICAgICAgICAgdGhyb3cgbmV3IEJhZFJlcXVlc3RFeGNlcHRpb24obWVzc2FnZXMsIHtcbiAgICAgICAgICAgIHpvZEVycm9yOiBlLFxuICAgICAgICAgIH0pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRocm93IGU7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgLy8gQ29udGVudC1UeXBlXG4gICAgICByZXBseS50eXBlKGFwaS5vcHRpb25zLmNvbnRlbnRUeXBlID8/IFwiYXBwbGljYXRpb24vanNvblwiKTtcblxuICAgICAgLy8gQ29udGV4dCDsg53shLFcbiAgICAgIGNvbnN0IGNvbnRleHQ6IENvbnRleHQgPSBhd2FpdCB0aGlzLmNyZWF0ZUNvbnRleHQoY29uZmlnLCByZXF1ZXN0LCByZXBseSk7XG5cbiAgICAgIC8vIOuqqOuNuCDrqZTshozrk5wgYXJncyDsg53shLHtlZjsl6wg7Zi47LacXG4gICAgICBjb25zdCB7IEFwaVBhcmFtVHlwZSB9ID0gYXdhaXQgaW1wb3J0KFwiLi4vdHlwZXMvdHlwZXNcIik7XG4gICAgICBjb25zdCBhcmdzID0gYXBpLnBhcmFtZXRlcnMubWFwKChwYXJhbSkgPT4ge1xuICAgICAgICAvLyBDb250ZXh0IOyduOygneyFmFxuICAgICAgICBpZiAoQXBpUGFyYW1UeXBlLmlzQ29udGV4dChwYXJhbS50eXBlKSkge1xuICAgICAgICAgIHJldHVybiBjb250ZXh0O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHJldHVybiByZXFCb2R5W3BhcmFtLm5hbWVdO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIHJldHVybiB0aGlzLmludm9rZU1vZGVsTWV0aG9kKGFwaSwgYXJncywgY29udGV4dCwgcmVwbHkpO1xuICAgIH07XG4gIH1cblxuICBhc3luYyBpbnZva2VNb2RlbE1ldGhvZChcbiAgICBhcGk6IEV4dGVuZGVkQXBpLFxuICAgIGFyZ3M6IHVua25vd25bXSxcbiAgICBjb250ZXh0OiBDb250ZXh0LFxuICAgIHJlcGx5OiBGYXN0aWZ5UmVwbHksXG4gICk6IFByb21pc2U8dW5rbm93bj4ge1xuICAgIGNvbnN0IG1vZGVsID0gdGhpcy5zeW5jZXIubW9kZWxzW2FwaS5tb2RlbE5hbWVdO1xuICAgIHJldHVybiB0aGlzLmFzeW5jTG9jYWxTdG9yYWdlLnJ1bih7IGNvbnRleHQgfSwgYXN5bmMgKCkgPT4ge1xuICAgICAgLy8gYmlvbWUtaWdub3JlIGxpbnQvc3VzcGljaW91cy9ub0V4cGxpY2l0QW55OiBtb2RlbOydgCDrqqjrjbgg7J247Iqk7YS07Iqk7J2066+A66GcIOuplOyEnOuTnCDtmLjstpwg6rCA64qlXG4gICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCAobW9kZWwgYXMgYW55KVthcGkubWV0aG9kTmFtZV0uYXBwbHkobW9kZWwsIGFyZ3MpO1xuICAgICAgcmVwbHkudHlwZShhcGkub3B0aW9ucy5jb250ZW50VHlwZSA/PyBcImFwcGxpY2F0aW9uL2pzb25cIik7XG5cbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfSk7XG4gIH1cblxuICBhc3luYyBjcmVhdGVDb250ZXh0KFxuICAgIGNvbmZpZzogU29uYW11RmFzdGlmeUNvbmZpZyxcbiAgICByZXF1ZXN0OiBGYXN0aWZ5UmVxdWVzdCxcbiAgICByZXBseTogRmFzdGlmeVJlcGx5LFxuICApOiBQcm9taXNlPENvbnRleHQ+IHtcbiAgICAvLyBjcmVhdGVTU0VGYWN0b3J5IO2VqOyImOyXkCDrr7jrpqwgcmVxdWVzdOydmCBzb2NrZXTqs7wgcmVwbHnrpbwg67CU7J2465SpLlxuICAgIGNvbnN0IHsgY3JlYXRlU1NFRmFjdG9yeSB9ID0gYXdhaXQgaW1wb3J0KFwiLi4vc3RyZWFtL3NzZVwiKTtcbiAgICBjb25zdCBjcmVhdGVTU0UgPSAoPFQgZXh0ZW5kcyBab2RPYmplY3Q+KFxuICAgICAgX3JlcXVlc3Q6IEZhc3RpZnlSZXF1ZXN0LFxuICAgICAgX3JlcGx5OiBGYXN0aWZ5UmVwbHksXG4gICAgICBfZXZlbnRzOiBULFxuICAgICkgPT4gY3JlYXRlU1NFRmFjdG9yeShfcmVxdWVzdC5zb2NrZXQsIF9yZXBseSwgX2V2ZW50cykpLmJpbmQobnVsbCwgcmVxdWVzdCwgcmVwbHkpO1xuXG4gICAgY29uc3QgY29udGV4dDogQ29udGV4dCA9IHtcbiAgICAgIC4uLihhd2FpdCBQcm9taXNlLnJlc29sdmUoXG4gICAgICAgIGNvbmZpZy5jb250ZXh0UHJvdmlkZXIoXG4gICAgICAgICAge1xuICAgICAgICAgICAgcmVxdWVzdCxcbiAgICAgICAgICAgIHJlcGx5LFxuICAgICAgICAgICAgaGVhZGVyczogcmVxdWVzdC5oZWFkZXJzLFxuICAgICAgICAgICAgY3JlYXRlU1NFLFxuICAgICAgICAgICAgbmFpdGVTdG9yZTogTmFpdGUuY3JlYXRlU3RvcmUoKSxcbiAgICAgICAgICAgIC8vIGF1dGhcbiAgICAgICAgICAgIHVzZXI6IHJlcXVlc3QudXNlciA/PyBudWxsLFxuICAgICAgICAgICAgcGFzc3BvcnQ6IHtcbiAgICAgICAgICAgICAgbG9naW46IHJlcXVlc3QubG9naW4uYmluZChyZXF1ZXN0KSBhcyBBdXRoQ29udGV4dFtcInBhc3Nwb3J0XCJdW1wibG9naW5cIl0sXG4gICAgICAgICAgICAgIGxvZ291dDogcmVxdWVzdC5sb2dvdXQuYmluZChyZXF1ZXN0KSBhcyBBdXRoQ29udGV4dFtcInBhc3Nwb3J0XCJdW1wibG9nb3V0XCJdLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICB9LFxuICAgICAgICAgIHJlcXVlc3QsXG4gICAgICAgICAgcmVwbHksXG4gICAgICAgICksXG4gICAgICApKSxcbiAgICB9O1xuICAgIHJldHVybiBjb250ZXh0O1xuICB9XG5cbiAgYXN5bmMgc3RhcnRXYXRjaGVyKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IHdhdGNoUGF0aCA9IFtwYXRoLmpvaW4odGhpcy5hcGlSb290UGF0aCwgXCJzcmNcIildO1xuXG4gICAgY29uc3QgY2hva2lkYXIgPSAoYXdhaXQgaW1wb3J0KFwiY2hva2lkYXJcIikpLmRlZmF1bHQ7XG4gICAgdGhpcy53YXRjaGVyID0gY2hva2lkYXIud2F0Y2god2F0Y2hQYXRoLCB7XG4gICAgICBpZ25vcmVkOiAocGF0aCwgc3RhdHMpID0+XG4gICAgICAgICEhc3RhdHM/LmlzRmlsZSgpICYmICFwYXRoLmVuZHNXaXRoKFwiLnRzXCIpICYmICFwYXRoLmVuZHNXaXRoKFwiLmpzb25cIiksXG4gICAgICBwZXJzaXN0ZW50OiB0cnVlLFxuICAgICAgaWdub3JlSW5pdGlhbDogdHJ1ZSxcbiAgICB9KTtcblxuICAgIHRoaXMud2F0Y2hlci5vbihcImFsbFwiLCBhc3luYyAoZXZlbnQ6IHN0cmluZywgZmlsZVBhdGg6IHN0cmluZykgPT4ge1xuICAgICAgY29uc3QgYWJzb2x1dGVQYXRoID0gZmlsZVBhdGggYXMgQWJzb2x1dGVQYXRoO1xuICAgICAgYXNzZXJ0KFxuICAgICAgICBhYnNvbHV0ZVBhdGguc3RhcnRzV2l0aCh0aGlzLmFwaVJvb3RQYXRoKSxcbiAgICAgICAgXCJGaWxlIHBhdGggaXMgbm90IHdpdGhpbiB0aGUgQVBJIHJvb3QgcGF0aFwiLFxuICAgICAgKTtcblxuICAgICAgaWYgKGV2ZW50ICE9PSBcImNoYW5nZVwiICYmIGV2ZW50ICE9PSBcImFkZFwiKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgdHJ5IHtcbiAgICAgICAgLy8gc29uYW11LmNvbmZpZy50cyDrs4Dqsr0g7IucIOyerOyLnOyekVxuICAgICAgICBjb25zdCBpc0NvbmZpZ1RzID0gZmlsZVBhdGggPT09IHBhdGguam9pbih0aGlzLmFwaVJvb3RQYXRoLCBcInNyY1wiLCBcInNvbmFtdS5jb25maWcudHNcIik7XG5cbiAgICAgICAgaWYgKGlzQ29uZmlnVHMpIHtcbiAgICAgICAgICBjb25zdCByZWxhdGl2ZVBhdGggPSBmaWxlUGF0aC5yZXBsYWNlKHRoaXMuYXBpUm9vdFBhdGgsIFwiYXBpXCIpO1xuICAgICAgICAgIGNvbnN0IGNoYWxrID0gKGF3YWl0IGltcG9ydChcImNoYWxrXCIpKS5kZWZhdWx0O1xuICAgICAgICAgIGNvbnNvbGUubG9nKFxuICAgICAgICAgICAgY2hhbGsuYm9sZChgRGV0ZWN0ZWQoJHtldmVudH0pOiAke2NoYWxrLmJsdWUocmVsYXRpdmVQYXRoKX0gLSBSZXN0YXJ0aW5nLi4uYCksXG4gICAgICAgICAgKTtcbiAgICAgICAgICBwcm9jZXNzLmtpbGwocHJvY2Vzcy5waWQsIFwiU0lHVVNSMlwiKTtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBhd2FpdCB0aGlzLmhhbmRsZUZpbGVDaGFuZ2UoZXZlbnQsIGFic29sdXRlUGF0aCk7XG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoZSk7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICAvKlxuICAgICBBIGZ1bmN0aW9uIHRoYXQgYXV0b21hdGljYWxseSBoYW5kbGVzIGluaXQgYW5kIGRlc3Ryb3kgd2hlbiB1c2luZyBTb25hbXUgdmlhIHNjcmlwdHMuICAgIFxuICAqL1xuICBhc3luYyBydW5TY3JpcHQoZm46ICgpID0+IFByb21pc2U8dm9pZD4pIHtcbiAgICBhd2FpdCB0aGlzLmluaXQodHJ1ZSwgZmFsc2UsIHVuZGVmaW5lZCwgZmFsc2UpO1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCBmbigpO1xuICAgIH0gZmluYWxseSB7XG4gICAgICBhd2FpdCB0aGlzLmRlc3Ryb3koKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIHJlZ2lzdGVyUGx1Z2lucyhzZXJ2ZXI6IEZhc3RpZnlJbnN0YW5jZSwgcGx1Z2luczogU29uYW11U2VydmVyT3B0aW9uc1tcInBsdWdpbnNcIl0pIHtcbiAgICBpZiAoIXBsdWdpbnMpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCBwbHVnaW5zTW9kdWxlcyA9IHtcbiAgICAgIGNvcnM6IFwiQGZhc3RpZnkvY29yc1wiLFxuICAgICAgZm9ybWJvZHk6IFwiQGZhc3RpZnkvZm9ybWJvZHlcIixcbiAgICAgIG11bHRpcGFydDogXCJAZmFzdGlmeS9tdWx0aXBhcnRcIixcbiAgICAgIHFzOiBcImZhc3RpZnktcXNcIixcbiAgICAgIHNzZTogXCJmYXN0aWZ5LXNzZS12MlwiLFxuICAgICAgc3RhdGljOiBcIkBmYXN0aWZ5L3N0YXRpY1wiLFxuICAgICAgc2Vzc2lvbjogXCJAZmFzdGlmeS9zZWN1cmUtc2Vzc2lvblwiLFxuICAgIH0gYXMgY29uc3Q7XG5cbiAgICBjb25zdCByZWdpc3RlclBsdWdpbiA9IGFzeW5jIDxLIGV4dGVuZHMga2V5b2YgTm9uTnVsbGFibGU8dHlwZW9mIHBsdWdpbnM+PihcbiAgICAgIGtleTogSyxcbiAgICAgIHBsdWdpbk5hbWU6IHN0cmluZyxcbiAgICApID0+IHtcbiAgICAgIGNvbnN0IG9wdGlvbiA9IHBsdWdpbnNba2V5XTtcbiAgICAgIGlmICghb3B0aW9uKSByZXR1cm47XG5cbiAgICAgIGlmIChvcHRpb24gPT09IHRydWUpIHtcbiAgICAgICAgc2VydmVyLnJlZ2lzdGVyKChhd2FpdCBpbXBvcnQocGx1Z2luTmFtZSkpLmRlZmF1bHQpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgc2VydmVyLnJlZ2lzdGVyKChhd2FpdCBpbXBvcnQocGx1Z2luTmFtZSkpLmRlZmF1bHQsIG9wdGlvbik7XG4gICAgICB9XG4gICAgfTtcblxuICAgIGZvciAoY29uc3QgW2tleSwgcGx1Z2luTmFtZV0gb2YgT2JqZWN0LmVudHJpZXMocGx1Z2luc01vZHVsZXMpKSB7XG4gICAgICBhd2FpdCByZWdpc3RlclBsdWdpbihrZXkgYXMga2V5b2YgdHlwZW9mIHBsdWdpbnMsIHBsdWdpbk5hbWUpO1xuICAgIH1cblxuICAgIGlmIChwbHVnaW5zLmN1c3RvbSkge1xuICAgICAgcGx1Z2lucy5jdXN0b20oc2VydmVyKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIHJlZ2lzdGVyQXV0aChcbiAgICBzZXJ2ZXI6IEZhc3RpZnlJbnN0YW5jZSxcbiAgICBvcHRpb25zOiBOb25OdWxsYWJsZTxTb25hbXVTZXJ2ZXJPcHRpb25zW1wiYXV0aFwiXT4sXG4gICkge1xuICAgIC8vIGF3YWl0IGltcG9ydChcImZhc3RpZnlcIik7XG4gICAgY29uc3QgZmFzdGlmeVBhc3Nwb3J0ID0gKGF3YWl0IGltcG9ydChcIkBmYXN0aWZ5L3Bhc3Nwb3J0XCIpKS5kZWZhdWx0O1xuICAgIHNlcnZlci5yZWdpc3RlcihmYXN0aWZ5UGFzc3BvcnQuaW5pdGlhbGl6ZSgpKTtcbiAgICBzZXJ2ZXIucmVnaXN0ZXIoZmFzdGlmeVBhc3Nwb3J0LnNlY3VyZVNlc3Npb24oKSk7XG5cbiAgICBpZiAodHlwZW9mIG9wdGlvbnMgPT09IFwiYm9vbGVhblwiKSB7XG4gICAgICBmYXN0aWZ5UGFzc3BvcnQucmVnaXN0ZXJVc2VyU2VyaWFsaXplcihhc3luYyAodXNlciwgX3JlcXVlc3QpID0+IHVzZXIpO1xuICAgICAgZmFzdGlmeVBhc3Nwb3J0LnJlZ2lzdGVyVXNlckRlc2VyaWFsaXplcihhc3luYyAoc2VyaWFsaXplZCwgX3JlcXVlc3QpID0+IHNlcmlhbGl6ZWQpO1xuICAgIH0gZWxzZSB7XG4gICAgICBmYXN0aWZ5UGFzc3BvcnQucmVnaXN0ZXJVc2VyU2VyaWFsaXplcihvcHRpb25zLnVzZXJTZXJpYWxpemVyKTtcbiAgICAgIGZhc3RpZnlQYXNzcG9ydC5yZWdpc3RlclVzZXJEZXNlcmlhbGl6ZXIob3B0aW9ucy51c2VyRGVzZXJpYWxpemVyKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGluaXRpYWxpemVXb3JrZmxvd3Mob3B0aW9uczogU29uYW11VGFza09wdGlvbnMgfCB1bmRlZmluZWQpIHtcbiAgICBjb25zdCB7IFdvcmtmbG93TWFuYWdlciB9ID0gYXdhaXQgaW1wb3J0KFwiLi4vdGFza3Mvd29ya2Zsb3ctbWFuYWdlclwiKTtcbiAgICAvLyBOT1RFOiBAc29uYW11LWtpdC90YXNrcyDslYjsl5DshKAga25leCBjb25maWfrpbwg7IiY7KCV7ZWY6riwIOuVjOusuOyXkCBjb25uZWN0aW9u7J20IOyVhOuLjCBjb25maWcg7Ke466GcIOuztOuDheuLiOuLpC5cbiAgICB0aGlzLl93b3JrZmxvd3MgPSBuZXcgV29ya2Zsb3dNYW5hZ2VyKERCLmdldERCQ29uZmlnKFwid1wiKSk7XG4gICAgaWYgKCFvcHRpb25zKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgZW5hYmxlV29ya2VyID0gb3B0aW9ucy5lbmFibGVXb3JrZXIgPz8gaXNEYWVtb25TZXJ2ZXIoKTtcbiAgICBjb25zdCBkZWZhdWx0V29ya2VyT3B0aW9ucyA9IHtcbiAgICAgIGNvbmN1cnJlbmN5OiBvcy5jcHVzKCkubGVuZ3RoIC0gMSxcbiAgICAgIHVzZVB1YlN1YjogdHJ1ZSxcbiAgICAgIGxpc3RlbkRlbGF5OiA1MDAsXG4gICAgfTtcblxuICAgIGlmIChlbmFibGVXb3JrZXIpIHtcbiAgICAgIHRoaXMud29ya2Zsb3dzLnNldHVwV29ya2VyKHtcbiAgICAgICAgLi4uZGVmYXVsdFdvcmtlck9wdGlvbnMsXG4gICAgICAgIC4uLm9wdGlvbnMud29ya2VyT3B0aW9ucyxcbiAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgYm9vdChzZXJ2ZXI6IEZhc3RpZnlJbnN0YW5jZSwgb3B0aW9uczogU29uYW11U2VydmVyT3B0aW9ucykge1xuICAgIGNvbnN0IHBvcnQgPSBvcHRpb25zLmxpc3Rlbj8ucG9ydCA/PyAzMDAwO1xuICAgIGNvbnN0IGhvc3QgPSBvcHRpb25zLmxpc3Rlbj8uaG9zdCA/PyBcImxvY2FsaG9zdFwiO1xuXG4gICAgc2VydmVyLmFkZEhvb2soXCJvbkNsb3NlXCIsIGFzeW5jICgpID0+IHtcbiAgICAgIGF3YWl0IG9wdGlvbnMubGlmZWN5Y2xlPy5vblNodXRkb3duPy4oc2VydmVyKTtcbiAgICAgIGF3YWl0IHRoaXMud29ya2Zsb3dzLmRlc3Ryb3koKTtcbiAgICAgIGF3YWl0IHRoaXMuZGVzdHJveSgpO1xuICAgIH0pO1xuXG4gICAgY29uc3Qgc2h1dGRvd24gPSBhc3luYyAoKSA9PiB7XG4gICAgICB0cnkge1xuICAgICAgICBhd2FpdCBzZXJ2ZXIuY2xvc2UoKTtcbiAgICAgICAgcHJvY2Vzcy5leGl0KDApO1xuICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoXCJFcnJvciBkdXJpbmcgc2h1dGRvd246XCIsIGVycik7XG4gICAgICAgIHByb2Nlc3MuZXhpdCgxKTtcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgcHJvY2Vzcy5vbihcIlNJR0lOVFwiLCBzaHV0ZG93bik7XG4gICAgcHJvY2Vzcy5vbihcIlNJR1RFUk1cIiwgc2h1dGRvd24pO1xuXG4gICAgaWYgKG9wdGlvbnMubGlmZWN5Y2xlPy5vbkVycm9yKSB7XG4gICAgICBzZXJ2ZXIuc2V0RXJyb3JIYW5kbGVyKG9wdGlvbnMubGlmZWN5Y2xlPy5vbkVycm9yKTtcbiAgICB9XG5cbiAgICBzZXJ2ZXJcbiAgICAgIC5saXN0ZW4oeyBwb3J0LCBob3N0IH0pXG4gICAgICAudGhlbihhc3luYyAoKSA9PiB7XG4gICAgICAgIGF3YWl0IHRoaXMud29ya2Zsb3dzLnN0YXJ0V29ya2VyKCk7XG4gICAgICAgIGF3YWl0IG9wdGlvbnMubGlmZWN5Y2xlPy5vblN0YXJ0Py4oc2VydmVyKTtcbiAgICAgIH0pXG4gICAgICAuY2F0Y2goYXN5bmMgKGVycikgPT4ge1xuICAgICAgICBjb25zdCBjaGFsayA9IChhd2FpdCBpbXBvcnQoXCJjaGFsa1wiKSkuZGVmYXVsdDtcbiAgICAgICAgY29uc29sZS5lcnJvcihjaGFsay5yZWQoXCJGYWlsZWQgdG8gc3RhcnQgc2VydmVyOlwiLCBlcnIpKTtcbiAgICAgICAgYXdhaXQgc2h1dGRvd24oKTtcbiAgICAgIH0pO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBoYW5kbGVGaWxlQ2hhbmdlKGV2ZW50OiBzdHJpbmcsIGZpbGVQYXRoOiBBYnNvbHV0ZVBhdGgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAvLyDssqsg67KI7Ke4IO2MjOydvOydtOuptCBITVIg7Iuc7J6RIOyLnOqwhCDquLDroZ1cbiAgICBpZiAodGhpcy5wZW5kaW5nRmlsZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICB0aGlzLmhtclN0YXJ0VGltZSA9IERhdGUubm93KCk7XG4gICAgfVxuICAgIHRoaXMucGVuZGluZ0ZpbGVzLnB1c2goZmlsZVBhdGgpO1xuXG4gICAgY29uc3QgcmVsYXRpdmVQYXRoID0gcGF0aC5yZWxhdGl2ZSh0aGlzLmFwaVJvb3RQYXRoLCBmaWxlUGF0aCk7XG4gICAgY29uc3QgY2hhbGsgPSAoYXdhaXQgaW1wb3J0KFwiY2hhbGtcIikpLmRlZmF1bHQ7XG4gICAgY29uc29sZS5sb2coY2hhbGsuYm9sZChgRGV0ZWN0ZWQoJHtldmVudH0pOiAke2NoYWxrLmJsdWUocmVsYXRpdmVQYXRoKX1gKSk7XG5cbiAgICBhd2FpdCB0aGlzLnN5bmNlci5zeW5jRnJvbVdhdGNoZXIoZXZlbnQsIGZpbGVQYXRoKTtcblxuICAgIC8vIOyymOumrCDsmYTro4zrkJwg7YyM7J287J2EIOuMgOq4sCDrqqnroZ3sl5DshJwg7KCc6rGwXG4gICAgdGhpcy5wZW5kaW5nRmlsZXMgPSB0aGlzLnBlbmRpbmdGaWxlcy5zbGljZSgxKTtcblxuICAgIC8vIOuqqOuToCDtjIzsnbwg7LKY66as6rCAIOyZhOujjOuQmOuptCDstZzsooUg66mU7Iuc7KeAIOy2nOugpVxuICAgIGlmICh0aGlzLnBlbmRpbmdGaWxlcy5sZW5ndGggPT09IDApIHtcbiAgICAgIGF3YWl0IHRoaXMuZmluaXNoSE1SKCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBmaW5pc2hITVIoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgYXdhaXQgdGhpcy5zeW5jZXIucmVuZXdDaGVja3N1bXMoKTtcblxuICAgIGNvbnN0IGVuZFRpbWUgPSBEYXRlLm5vdygpO1xuICAgIGNvbnN0IHRvdGFsVGltZSA9IGVuZFRpbWUgLSB0aGlzLmhtclN0YXJ0VGltZTtcbiAgICBjb25zdCBbY2hhbGssIHsgY2VudGVyVGV4dCB9XSA9IGF3YWl0IFByb21pc2UuYWxsKFtcbiAgICAgIChhd2FpdCBpbXBvcnQoXCJjaGFsa1wiKSkuZGVmYXVsdCxcbiAgICAgIGltcG9ydChcIi4uL3V0aWxzL2NvbnNvbGUtdXRpbFwiKSxcbiAgICBdKTtcbiAgICBjb25zdCBtc2cgPSBgSE1SIERvbmUhICR7Y2hhbGsuYm9sZC53aGl0ZShgJHt0b3RhbFRpbWV9bXNgKX1gO1xuXG4gICAgY29uc29sZS5sb2coY2hhbGsuYmxhY2suYmdHcmVlbihjZW50ZXJUZXh0KG1zZykpKTtcbiAgfVxuXG4gIGFzeW5jIGRlc3Ryb3koKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgeyBCYXNlTW9kZWwgfSA9IGF3YWl0IGltcG9ydChcIi4uL2RhdGFiYXNlL2Jhc2UtbW9kZWxcIik7XG4gICAgYXdhaXQgQmFzZU1vZGVsLmRlc3Ryb3koKTtcbiAgICBhd2FpdCB0aGlzLl93b3JrZmxvd3M/LmRlc3Ryb3koKTtcbiAgICBhd2FpdCB0aGlzLndhdGNoZXI/LmNsb3NlKCk7XG4gIH1cbn1cbmV4cG9ydCBjb25zdCBTb25hbXUgPSBuZXcgU29uYW11Q2xhc3MoKTtcbiJdLCJuYW1lcyI6WyJhc3NlcnQiLCJBc3luY0xvY2FsU3RvcmFnZSIsIm9zIiwicGF0aCIsImNyZWF0ZU1vY2tTU0VGYWN0b3J5IiwiREIiLCJpc0RhZW1vblNlcnZlciIsIk5haXRlIiwiU29uYW11Q2xhc3MiLCJpc0luaXRpYWxpemVkIiwiYXN5bmNMb2NhbFN0b3JhZ2UiLCJ1cGxvYWRTdG9yYWdlIiwiZ2V0Q29udGV4dCIsInN0b3JlIiwiZ2V0U3RvcmUiLCJjb250ZXh0IiwicHJvY2VzcyIsImVudiIsIk5PREVfRU5WIiwicmVxdWVzdCIsInJlcGx5IiwiaGVhZGVycyIsImNyZWF0ZVNTRSIsInNjaGVtYSIsIm5haXRlU3RvcmUiLCJNYXAiLCJFcnJvciIsImdldFVwbG9hZENvbnRleHQiLCJ1cGxvYWRDb250ZXh0IiwiX2FwaVJvb3RQYXRoIiwiYXBpUm9vdFBhdGgiLCJhcHBSb290UGF0aCIsInNwbGl0Iiwic2VwIiwic2xpY2UiLCJqb2luIiwiX2RiQ29uZmlnIiwiZGJDb25maWciLCJfc3luY2VyIiwic3luY2VyIiwiX2NvbmZpZyIsImNvbmZpZyIsIl9zZWNyZXRzIiwic2VjcmV0cyIsIl9zdG9yYWdlIiwic3RvcmFnZSIsIl93b3JrZmxvd3MiLCJ3b3JrZmxvd3MiLCJ3YXRjaGVyIiwicGVuZGluZ0ZpbGVzIiwiaG1yU3RhcnRUaW1lIiwic2VydmVyIiwiaW5pdEZvclRlc3RpbmciLCJpbml0IiwidW5kZWZpbmVkIiwiZG9TaWxlbnQiLCJlbmFibGVTeW5jIiwiZm9yVGVzdGluZyIsImNoYWxrIiwiZGVmYXVsdCIsImNvbnNvbGUiLCJ0aW1lIiwiY3lhbiIsImZpbmRBcGlSb290UGF0aCIsImxvYWRDb25maWciLCJkYXRhYmFzZSIsIkFOVEhST1BJQ19BUElfS0VZIiwiYW50aHJvcGljX2FwaV9rZXkiLCJWT1lBR0VfQVBJX0tFWSIsInZveWFnZV9hcGlfa2V5IiwiT1BFTkFJX0FQSV9LRVkiLCJvcGVuYWlfYXBpX2tleSIsIk9iamVjdCIsImtleXMiLCJsZW5ndGgiLCJnZW5lcmF0ZURCQ29uZmlnIiwibG9nIiwiZ3JlZW4iLCJFbnRpdHlNYW5hZ2VyIiwiYXV0b2xvYWQiLCJpbml0aWFsaXplV29ya2Zsb3dzIiwidGFza3MiLCJTeW5jZXIiLCJhdXRvbG9hZFR5cGVzIiwiYXV0b2xvYWRNb2RlbHMiLCJhdXRvbG9hZEFwaXMiLCJhdXRvbG9hZFdvcmtmbG93cyIsIlRlbXBsYXRlTWFuYWdlciIsImlzTG9jYWwiLCJpc1Rlc3QiLCJzZXR1cEJpb21lIiwiaXNIb3RSZWxvYWRTZXJ2ZXIiLCJzeW5jIiwic3RhcnRXYXRjaGVyIiwidGltZUVuZCIsImNyZWF0ZVNlcnZlciIsImluaXRPcHRpb25zIiwib3B0aW9ucyIsImZhc3RpZnkiLCJTdG9yYWdlTWFuYWdlciIsInBsdWdpbnMiLCJyZWdpc3RlclBsdWdpbnMiLCJhdXRoIiwic2Vzc2lvbiIsInJlZ2lzdGVyQXV0aCIsIndpdGhGYXN0aWZ5IiwiYXBpQ29uZmlnIiwiYm9vdCIsInRpbWV6b25lIiwiYXBpIiwiZm9ybWF0SW5UaW1lWm9uZSIsIklTT19EQVRFX1JFR0VYIiwiREFURV9GT1JNQVQiLCJzZXRSZXBseVNlcmlhbGl6ZXIiLCJwYXlsb2FkIiwiSlNPTiIsInN0cmluZ2lmeSIsIl9rZXkiLCJ2YWx1ZSIsInRlc3QiLCJEYXRlIiwiZ2V0Iiwicm91dGUiLCJwcmVmaXgiLCJfcmVxdWVzdCIsIl9yZXBseSIsImFwaXMiLCJzb25hbXVVSUFwaVBsdWdpbiIsInJlZ2lzdGVyIiwiYWxsIiwidXJsIiwic3RhcnRzV2l0aCIsImZvdW5kIiwiZmluZCIsImh0dHBNZXRob2QiLCJtZXRob2QiLCJ0b1VwcGVyQ2FzZSIsImNyZWF0ZUFwaUhhbmRsZXIiLCJOb3RGb3VuZEV4Y2VwdGlvbiIsIm1vZGVscyIsIm1vZGVsTmFtZSIsImhhbmRsZXIiLCJndWFyZHMiLCJldmVyeSIsImd1YXJkIiwiZ3VhcmRIYW5kbGVyIiwiZ2V0Wm9kT2JqZWN0RnJvbUFwaSIsIlJlcVR5cGUiLCJ0eXBlcyIsIndoaWNoIiwicmVxQm9keSIsImZhc3RpZnlDYXN0ZXIiLCJwYXJzZSIsImUiLCJab2RFcnJvciIsImh1bWFuaXplWm9kRXJyb3IiLCJtZXNzYWdlcyIsIm1hcCIsImlzc3VlIiwibWVzc2FnZSIsIkJhZFJlcXVlc3RFeGNlcHRpb24iLCJ6b2RFcnJvciIsInR5cGUiLCJjb250ZW50VHlwZSIsImNyZWF0ZUNvbnRleHQiLCJBcGlQYXJhbVR5cGUiLCJhcmdzIiwicGFyYW1ldGVycyIsInBhcmFtIiwiaXNDb250ZXh0IiwibmFtZSIsImludm9rZU1vZGVsTWV0aG9kIiwibW9kZWwiLCJydW4iLCJyZXN1bHQiLCJtZXRob2ROYW1lIiwiYXBwbHkiLCJjcmVhdGVTU0VGYWN0b3J5IiwiX2V2ZW50cyIsInNvY2tldCIsImJpbmQiLCJQcm9taXNlIiwicmVzb2x2ZSIsImNvbnRleHRQcm92aWRlciIsImNyZWF0ZVN0b3JlIiwidXNlciIsInBhc3Nwb3J0IiwibG9naW4iLCJsb2dvdXQiLCJ3YXRjaFBhdGgiLCJjaG9raWRhciIsIndhdGNoIiwiaWdub3JlZCIsInN0YXRzIiwiaXNGaWxlIiwiZW5kc1dpdGgiLCJwZXJzaXN0ZW50IiwiaWdub3JlSW5pdGlhbCIsIm9uIiwiZXZlbnQiLCJmaWxlUGF0aCIsImFic29sdXRlUGF0aCIsImlzQ29uZmlnVHMiLCJyZWxhdGl2ZVBhdGgiLCJyZXBsYWNlIiwiYm9sZCIsImJsdWUiLCJraWxsIiwicGlkIiwiaGFuZGxlRmlsZUNoYW5nZSIsImVycm9yIiwicnVuU2NyaXB0IiwiZm4iLCJkZXN0cm95IiwicGx1Z2luc01vZHVsZXMiLCJjb3JzIiwiZm9ybWJvZHkiLCJtdWx0aXBhcnQiLCJxcyIsInNzZSIsInN0YXRpYyIsInJlZ2lzdGVyUGx1Z2luIiwia2V5IiwicGx1Z2luTmFtZSIsIm9wdGlvbiIsImVudHJpZXMiLCJjdXN0b20iLCJmYXN0aWZ5UGFzc3BvcnQiLCJpbml0aWFsaXplIiwic2VjdXJlU2Vzc2lvbiIsInJlZ2lzdGVyVXNlclNlcmlhbGl6ZXIiLCJyZWdpc3RlclVzZXJEZXNlcmlhbGl6ZXIiLCJzZXJpYWxpemVkIiwidXNlclNlcmlhbGl6ZXIiLCJ1c2VyRGVzZXJpYWxpemVyIiwiV29ya2Zsb3dNYW5hZ2VyIiwiZ2V0REJDb25maWciLCJlbmFibGVXb3JrZXIiLCJkZWZhdWx0V29ya2VyT3B0aW9ucyIsImNvbmN1cnJlbmN5IiwiY3B1cyIsInVzZVB1YlN1YiIsImxpc3RlbkRlbGF5Iiwic2V0dXBXb3JrZXIiLCJ3b3JrZXJPcHRpb25zIiwicG9ydCIsImxpc3RlbiIsImhvc3QiLCJhZGRIb29rIiwibGlmZWN5Y2xlIiwib25TaHV0ZG93biIsInNodXRkb3duIiwiY2xvc2UiLCJleGl0IiwiZXJyIiwib25FcnJvciIsInNldEVycm9ySGFuZGxlciIsInRoZW4iLCJzdGFydFdvcmtlciIsIm9uU3RhcnQiLCJjYXRjaCIsInJlZCIsIm5vdyIsInB1c2giLCJyZWxhdGl2ZSIsInN5bmNGcm9tV2F0Y2hlciIsImZpbmlzaEhNUiIsInJlbmV3Q2hlY2tzdW1zIiwiZW5kVGltZSIsInRvdGFsVGltZSIsImNlbnRlclRleHQiLCJtc2ciLCJ3aGl0ZSIsImJsYWNrIiwiYmdHcmVlbiIsIkJhc2VNb2RlbCIsIlNvbmFtdSJdLCJtYXBwaW5ncyI6IkFBQUEsT0FBT0EsWUFBWSxTQUFTO0FBQzVCLFNBQVNDLGlCQUFpQixRQUFRLGNBQWM7QUFJaEQsT0FBT0MsUUFBUSxLQUFLO0FBQ3BCLE9BQU9DLFVBQVUsT0FBTztBQUV4QixTQUFTQyxvQkFBb0IsRUFBRUMsRUFBRSxFQUFFQyxjQUFjLFFBQVEsY0FBSztBQUU5RCxTQUFTQyxLQUFLLFFBQVEsb0JBQWlCO0FBZXZDLE1BQU1DO0lBQ0dDLGdCQUF5QixNQUFNO0lBQy9CQyxvQkFFRixJQUFJVCxvQkFBb0I7SUFFdEJVLGdCQUVGLElBQUlWLG9CQUFvQjtJQUV0QlcsYUFBc0I7UUFDM0IsTUFBTUMsUUFBUSxJQUFJLENBQUNILGlCQUFpQixDQUFDSSxRQUFRO1FBQzdDLElBQUlELE9BQU9FLFNBQVM7WUFDbEIsT0FBT0YsTUFBTUUsT0FBTztRQUN0QjtRQUVBLElBQUlDLFFBQVFDLEdBQUcsQ0FBQ0MsUUFBUSxLQUFLLFFBQVE7WUFDbkMsc0NBQXNDO1lBQ3RDLE9BQU87Z0JBQ0xDLFNBQVM7Z0JBQ1RDLE9BQU87Z0JBQ1BDLFNBQVMsQ0FBQztnQkFDVkMsV0FBVyxDQUFDQyxTQUFzQm5CLHFCQUFxQm1CO2dCQUN2RCxrRkFBa0Y7Z0JBQ2xGQyxZQUFZLElBQUlDO1lBQ2xCO1FBQ0YsT0FBTztZQUNMLE1BQU0sSUFBSUMsTUFBTTtRQUNsQjtJQUNGO0lBRU9DLG1CQUFrQztRQUN2QyxNQUFNZCxRQUFRLElBQUksQ0FBQ0YsYUFBYSxDQUFDRyxRQUFRO1FBQ3pDLElBQUlELE9BQU9lLGVBQWU7WUFDeEIsT0FBT2YsTUFBTWUsYUFB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
760
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9hcGkvc29uYW11LnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGRpc3Bvc2UgYXMgbG9ndGFwZURpc3Bvc2UgfSBmcm9tIFwiQGxvZ3RhcGUvbG9ndGFwZVwiO1xuaW1wb3J0IGFzc2VydCBmcm9tIFwiYXNzZXJ0XCI7XG5pbXBvcnQgeyBBc3luY0xvY2FsU3RvcmFnZSB9IGZyb20gXCJhc3luY19ob29rc1wiO1xuaW1wb3J0IHR5cGUgeyBGU1dhdGNoZXIgfSBmcm9tIFwiY2hva2lkYXJcIjtcbmltcG9ydCB0eXBlIHsgRmFzdGlmeUluc3RhbmNlLCBGYXN0aWZ5UmVwbHksIEZhc3RpZnlSZXF1ZXN0IH0gZnJvbSBcImZhc3RpZnlcIjtcbmltcG9ydCBmcyBmcm9tIFwiZnNcIjtcbmltcG9ydCB0eXBlIHsgSW5jb21pbmdNZXNzYWdlLCBTZXJ2ZXIsIFNlcnZlclJlc3BvbnNlIH0gZnJvbSBcImh0dHBcIjtcbmltcG9ydCBvcyBmcm9tIFwib3NcIjtcbmltcG9ydCBwYXRoIGZyb20gXCJwYXRoXCI7XG5pbXBvcnQgdHlwZSB7IFpvZE9iamVjdCB9IGZyb20gXCJ6b2RcIjtcbmltcG9ydCB7IGNyZWF0ZU1vY2tTU0VGYWN0b3J5LCBEQiwgaXNEYWVtb25TZXJ2ZXIgfSBmcm9tIFwiLi5cIjtcbmltcG9ydCB0eXBlIHsgQ2FjaGVDb25maWcsIENhY2hlTWFuYWdlciB9IGZyb20gXCIuLi9jYWNoZS90eXBlc1wiO1xuaW1wb3J0IHR5cGUgeyBTb25hbXVEQkNvbmZpZyB9IGZyb20gXCIuLi9kYXRhYmFzZS9kYlwiO1xuaW1wb3J0IHsgTmFpdGUgfSBmcm9tIFwiLi4vbmFpdGUvbmFpdGVcIjtcbmltcG9ydCB0eXBlIHsgU3RvcmFnZU1hbmFnZXIgfSBmcm9tIFwiLi4vc3RvcmFnZS9zdG9yYWdlLW1hbmFnZXJcIjtcbmltcG9ydCB0eXBlIHsgU3luY2VyIH0gZnJvbSBcIi4uL3N5bmNlci9zeW5jZXJcIjtcbmltcG9ydCB0eXBlIHsgV29ya2Zsb3dNYW5hZ2VyIH0gZnJvbSBcIi4uL3Rhc2tzL3dvcmtmbG93LW1hbmFnZXJcIjtcbmltcG9ydCB0eXBlIHsgU29uYW11RmFzdGlmeUNvbmZpZyB9IGZyb20gXCIuLi90eXBlcy90eXBlc1wiO1xuaW1wb3J0IHR5cGUgeyBBYnNvbHV0ZVBhdGggfSBmcm9tIFwiLi4vdXRpbHMvcGF0aC11dGlsc1wiO1xuaW1wb3J0IHR5cGUgeyBTb25hbXVDb25maWcsIFNvbmFtdVNlcnZlck9wdGlvbnMsIFNvbmFtdVRhc2tPcHRpb25zIH0gZnJvbSBcIi4vY29uZmlnXCI7XG5pbXBvcnQgdHlwZSB7IEF1dGhDb250ZXh0LCBDb250ZXh0LCBVcGxvYWRDb250ZXh0IH0gZnJvbSBcIi4vY29udGV4dFwiO1xuaW1wb3J0IHR5cGUgeyBFeHRlbmRlZEFwaSB9IGZyb20gXCIuL2RlY29yYXRvcnNcIjtcbmltcG9ydCB7IGdldFNlY3JldHMsIHR5cGUgU29uYW11U2VjcmV0cyB9IGZyb20gXCIuL3NlY3JldFwiO1xuXG5jbGFzcyBTb25hbXVDbGFzcyB7XG4gIHB1YmxpYyBpc0luaXRpYWxpemVkOiBib29sZWFuID0gZmFsc2U7XG4gIHB1YmxpYyBhc3luY0xvY2FsU3RvcmFnZTogQXN5bmNMb2NhbFN0b3JhZ2U8e1xuICAgIGNvbnRleHQ6IENvbnRleHQ7XG4gIH0+ID0gbmV3IEFzeW5jTG9jYWxTdG9yYWdlKCk7XG5cbiAgcHVibGljIHVwbG9hZFN0b3JhZ2U6IEFzeW5jTG9jYWxTdG9yYWdlPHtcbiAgICB1cGxvYWRDb250ZXh0OiBVcGxvYWRDb250ZXh0O1xuICB9PiA9IG5ldyBBc3luY0xvY2FsU3RvcmFnZSgpO1xuXG4gIHB1YmxpYyBnZXRDb250ZXh0KCk6IENvbnRleHQge1xuICAgIGNvbnN0IHN0b3JlID0gdGhpcy5hc3luY0xvY2FsU3RvcmFnZS5nZXRTdG9yZSgpO1xuICAgIGlmIChzdG9yZT8uY29udGV4dCkge1xuICAgICAgcmV0dXJuIHN0b3JlLmNvbnRleHQ7XG4gICAgfVxuXG4gICAgaWYgKHByb2Nlc3MuZW52Lk5PREVfRU5WID09PSBcInRlc3RcIikge1xuICAgICAgLy8g7YWM7Iqk7YyFIO2ZmOqyveyXkOyEnCDsu6jthY3siqTtirjqsIAg7KO87J6F65CY7KeAIOyViuydgCDqsr3smrAg67mIIOy7qO2FjeyKpO2KuCDrpqzthLRcbiAgICAgIHJldHVybiB7XG4gICAgICAgIHJlcXVlc3Q6IG51bGwsXG4gICAgICAgIHJlcGx5OiBudWxsLFxuICAgICAgICBoZWFkZXJzOiB7fSxcbiAgICAgICAgY3JlYXRlU1NFOiAoc2NoZW1hOiBab2RPYmplY3QpID0+IGNyZWF0ZU1vY2tTU0VGYWN0b3J5KHNjaGVtYSksXG4gICAgICAgIC8vIGJpb21lLWlnbm9yZSBsaW50L3N1c3BpY2lvdXMvbm9FeHBsaWNpdEFueTog7YWM7Iqk7YyFIO2ZmOqyveyXkOyEnCDsu6jthY3siqTtirjqsIAg7KO87J6F65CY7KeAIOyViuydgCDqsr3smrAg67mIIOy7qO2FjeyKpO2KuCDrpqzthLRcbiAgICAgICAgbmFpdGVTdG9yZTogbmV3IE1hcDxzdHJpbmcsIGFueT4oKSxcbiAgICAgIH0gYXMgdW5rbm93biBhcyBDb250ZXh0O1xuICAgIH0gZWxzZSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJTb25hbXUgY2Fubm90IGZpbmQgY29udGV4dFwiKTtcbiAgICB9XG4gIH1cblxuICBwdWJsaWMgZ2V0VXBsb2FkQ29udGV4dCgpOiBVcGxvYWRDb250ZXh0IHtcbiAgICBjb25zdCBzdG9yZSA9IHRoaXMudXBsb2FkU3RvcmFnZS5nZXRTdG9yZSgpO1xuICAgIGlmIChzdG9yZT8udXBsb2FkQ29udGV4dCkge1xuICAgICAgcmV0dXJuIHN0b3JlLnVwbG9hZENvbnRleHQ7XG4gICAgfVxuICAgIHRocm93IG5ldyBFcnJvcihcIlNvbmFtdSBjYW5ub3QgZmluZCB1cGxvYWQgY29udGV4dC4gRGlkIHlvdSB1c2UgQHVwbG9hZCBkZWNvcmF0b3I/XCIpO1xuICB9XG5cbiAgcHJpdmF0ZSBfYXBpUm9vdFBhdGg6IEFic29sdXRlUGF0aCB8IG51bGwgPSBudWxsO1xuICBzZXQgYXBpUm9vdFBhdGgoYXBpUm9vdFBhdGg6IEFic29sdXRlUGF0aCkge1xuICAgIHRoaXMuX2FwaVJvb3RQYXRoID0gYXBpUm9vdFBhdGg7XG4gIH1cbiAgZ2V0IGFwaVJvb3RQYXRoKCk6IEFic29sdXRlUGF0aCB7XG4gICAgaWYgKHRoaXMuX2FwaVJvb3RQYXRoID09PSBudWxsKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJTb25hbXUgaGFzIG5vdCBiZWVuIGluaXRpYWxpemVkXCIpO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5fYXBpUm9vdFBhdGg7XG4gIH1cbiAgZ2V0IGFwcFJvb3RQYXRoKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMuYXBpUm9vdFBhdGguc3BsaXQocGF0aC5zZXApLnNsaWNlKDAsIC0xKS5qb2luKHBhdGguc2VwKTtcbiAgfVxuXG4gIHByaXZhdGUgX2RiQ29uZmlnOiBTb25hbXVEQkNvbmZpZyB8IG51bGwgPSBudWxsO1xuICBzZXQgZGJDb25maWcoZGJDb25maWc6IFNvbmFtdURCQ29uZmlnKSB7XG4gICAgdGhpcy5fZGJDb25maWcgPSBkYkNvbmZpZztcbiAgfVxuICBnZXQgZGJDb25maWcoKTogU29uYW11REJDb25maWcge1xuICAgIGlmICh0aGlzLl9kYkNvbmZpZyA9PT0gbnVsbCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiU29uYW11IGhhcyBub3QgYmVlbiBpbml0aWFsaXplZFwiKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuX2RiQ29uZmlnO1xuICB9XG5cbiAgcHJpdmF0ZSBfc3luY2VyOiBTeW5jZXIgfCBudWxsID0gbnVsbDtcbiAgc2V0IHN5bmNlcihzeW5jZXI6IFN5bmNlcikge1xuICAgIHRoaXMuX3N5bmNlciA9IHN5bmNlcjtcbiAgfVxuICBnZXQgc3luY2VyKCk6IFN5bmNlciB7XG4gICAgaWYgKHRoaXMuX3N5bmNlciA9PT0gbnVsbCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiU29uYW11IGhhcyBub3QgYmVlbiBpbml0aWFsaXplZFwiKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuX3N5bmNlcjtcbiAgfVxuXG4gIHByaXZhdGUgX2NvbmZpZzogU29uYW11Q29uZmlnIHwgbnVsbCA9IG51bGw7XG4gIHNldCBjb25maWcoY29uZmlnOiBTb25hbXVDb25maWcpIHtcbiAgICB0aGlzLl9jb25maWcgPSBjb25maWc7XG4gIH1cbiAgZ2V0IGNvbmZpZygpOiBTb25hbXVDb25maWcge1xuICAgIGlmICh0aGlzLl9jb25maWcgPT09IG51bGwpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIlNvbmFtdSBoYXMgbm90IGJlZW4gaW5pdGlhbGl6ZWRcIik7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLl9jb25maWc7XG4gIH1cblxuICBwdWJsaWMgcmVhZG9ubHkgc2VjcmV0czogU29uYW11U2VjcmV0cyA9IGdldFNlY3JldHMoKTtcblxuICBwcml2YXRlIF9zdG9yYWdlOiBTdG9yYWdlTWFuYWdlciB8IG51bGwgPSBudWxsO1xuICAvKipcbiAgICogU3RvcmFnZU1hbmFnZXIg7J247Iqk7YS07IqkXG4gICAqL1xuICBnZXQgc3RvcmFnZSgpOiBTdG9yYWdlTWFuYWdlciB7XG4gICAgaWYgKCF0aGlzLl9zdG9yYWdlKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJTdG9yYWdlIGhhcyBub3QgYmVlbiBpbml0aWFsaXplZC4gQ2hlY2sgc3RvcmFnZSBjb25maWcuXCIpO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5fc3RvcmFnZTtcbiAgfVxuXG4gIHByaXZhdGUgX2NhY2hlOiBDYWNoZU1hbmFnZXIgfCBudWxsID0gbnVsbDtcbiAgLyoqXG4gICAqIENhY2hlTWFuYWdlciDsnbjsiqTthLTsiqQgKEJlbnRvQ2FjaGUpXG4gICAqL1xuICBnZXQgY2FjaGUoKTogQ2FjaGVNYW5hZ2VyIHtcbiAgICBpZiAoIXRoaXMuX2NhY2hlKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJDYWNoZSBoYXMgbm90IGJlZW4gaW5pdGlhbGl6ZWQuIENoZWNrIGNhY2hlIGNvbmZpZyBpbiBzb25hbXUuY29uZmlnLnRzLlwiKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuX2NhY2hlO1xuICB9XG5cbiAgcHJpdmF0ZSBfd29ya2Zsb3dzOiBXb3JrZmxvd01hbmFnZXIgfCBudWxsID0gbnVsbDtcbiAgZ2V0IHdvcmtmbG93cygpOiBXb3JrZmxvd01hbmFnZXIge1xuICAgIGlmICh0aGlzLl93b3JrZmxvd3MgPT09IG51bGwpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIlNvbmFtdSBoYXMgbm90IGJlZW4gaW5pdGlhbGl6ZWRcIik7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMuX3dvcmtmbG93cztcbiAgfVxuXG4gIC8vIEhNUiDsspjrpqxcbiAgcHVibGljIHdhdGNoZXI6IEZTV2F0Y2hlciB8IG51bGwgPSBudWxsO1xuICBwcml2YXRlIHBlbmRpbmdGaWxlczogc3RyaW5nW10gPSBbXTtcbiAgcHJpdmF0ZSBobXJTdGFydFRpbWU6IG51bWJlciA9IDA7XG5cbiAgcHVibGljIHNlcnZlcjogRmFzdGlmeUluc3RhbmNlIHwgbnVsbCA9IG51bGw7XG5cbiAgYXN5bmMgaW5pdEZvclRlc3RpbmcoKSB7XG4gICAgYXdhaXQgdGhpcy5pbml0KHRydWUsIGZhbHNlLCB1bmRlZmluZWQsIHRydWUpO1xuICB9XG5cbiAgYXN5bmMgaW5pdChcbiAgICBkb1NpbGVudDogYm9vbGVhbiA9IGZhbHNlLFxuICAgIGVuYWJsZVN5bmM6IGJvb2xlYW4gPSB0cnVlLFxuICAgIGFwaVJvb3RQYXRoPzogQWJzb2x1dGVQYXRoLFxuICAgIGZvclRlc3Rpbmc6IGJvb2xlYW4gPSBmYWxzZSxcbiAgKSB7XG4gICAgaWYgKHRoaXMuaXNJbml0aWFsaXplZCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmICghZG9TaWxlbnQpIHtcbiAgICAgIGNvbnN0IGNoYWxrID0gKGF3YWl0IGltcG9ydChcImNoYWxrXCIpKS5kZWZhdWx0O1xuICAgICAgY29uc29sZS50aW1lKGNoYWxrLmN5YW4oYFNvbmFtdS5pbml0JHtmb3JUZXN0aW5nID8gXCIgZm9yIHRlc3RpbmdcIiA6IFwiXCJ9YCkpO1xuICAgIH1cblxuICAgIC8vIEFQSSDro6jtirgg7Yyo7IqkXG4gICAgY29uc3QgeyBmaW5kQXBpUm9vdFBhdGggfSA9IGF3YWl0IGltcG9ydChcIi4uL3V0aWxzL3V0aWxzXCIpO1xuICAgIHRoaXMuYXBpUm9vdFBhdGggPSBhcGlSb290UGF0aCA/PyBmaW5kQXBpUm9vdFBhdGgoKTtcblxuICAgIC8vIOyEpOygleydhCDroZzrlKntlZjripQg6rKD67aA7YSwIOyLnOyekVxuICAgIGNvbnN0IHsgbG9hZENvbmZpZyB9ID0gYXdhaXQgaW1wb3J0KFwiLi9jb25maWdcIik7XG4gICAgdGhpcy5jb25maWcgPSBhd2FpdCBsb2FkQ29uZmlnKHRoaXMuYXBpUm9vdFBhdGgpO1xuICAgIC8vIHNvbmFtdS5jb25maWcudHMg6riw67O46rCSIOyEpOyglVxuICAgIHRoaXMuY29uZmlnLmRhdGFiYXNlLmRhdGFiYXNlID0gdGhpcy5jb25maWcuZGF0YWJhc2UuZGF0YWJhc2UgPz8gXCJwZ1wiO1xuICAgIHRoaXMuY29uZmlnLmRhdGFiYXNlLmRlZmF1bHRPcHRpb25zLmNsaWVudCA9IHRoaXMuY29uZmlnLmRhdGFiYXNlLmRhdGFiYXNlID8/IFwicGdcIjtcblxuICAgIC8vIOuhnOq5hSDshKTsoJVcbiAgICBjb25zdCB7IGNvbmZpZ3VyZUxvZ1RhcGUgfSA9IGF3YWl0IGltcG9ydChcIi4uL2xvZ2dlci9jb25maWd1cmVcIik7XG4gICAgaWYgKHRoaXMuY29uZmlnLmxvZ2dpbmcgIT09IGZhbHNlKSB7XG4gICAgICBhd2FpdCBjb25maWd1cmVMb2dUYXBlKHtcbiAgICAgICAgLi4udGhpcy5jb25maWcubG9nZ2luZyxcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIC8vIERCIOuhnOuTnFxuICAgIGNvbnN0IHsgREIgfSA9IGF3YWl0IGltcG9ydChcIi4uL2RhdGFiYXNlL2RiXCIpO1xuICAgIHRoaXMuZGJDb25maWcgPSBEQi5nZW5lcmF0ZURCQ29uZmlnKHRoaXMuY29uZmlnLmRhdGFiYXNlKTtcbiAgICBpZiAoIWRvU2lsZW50KSB7XG4gICAgICBjb25zdCBjaGFsayA9IChhd2FpdCBpbXBvcnQoXCJjaGFsa1wiKSkuZGVmYXVsdDtcbiAgICAgIGNvbnNvbGUubG9nKGNoYWxrLmdyZWVuKFwiREIgQ29uZmlnIExvYWRlZCFcIikpO1xuICAgIH1cblxuICAgIC8vIEVudGl0eSDroZzrk5xcbiAgICAvLyDthYzsiqTtirjsl5DshJzrj4QgRW50aXR5IOygleuztOuKlCDtlYTsmpTtlanri4jri6QuXG4gICAgLy8gdXBzZXJ06rCAIOygnOuMgOuhnCDsnpHrj5ntlZjroKTrqbQgZW50aXR57J2YIHVuaXF1ZSBpbmRleCDsoJXrs7TqsIAg7ZWE7JqU7ZWY6riwIOuVjOusuOyeheuLiOuLpC5cbiAgICBjb25zdCB7IEVudGl0eU1hbmFnZXIgfSA9IGF3YWl0IGltcG9ydChcIi4uL2VudGl0eS9lbnRpdHktbWFuYWdlclwiKTtcbiAgICBhd2FpdCBFbnRpdHlNYW5hZ2VyLmF1dG9sb2FkKGRvU2lsZW50KTtcblxuICAgIC8vIENhY2hlIOy0iOq4sO2ZlFxuICAgIGF3YWl0IHRoaXMuaW5pdGlhbGl6ZUNhY2hlKHRoaXMuY29uZmlnLnNlcnZlci5jYWNoZSwgZm9yVGVzdGluZyk7XG5cbiAgICAvLyDthYzsiqTtjIXsnbgg6rK97JqwIOyLse2BrCDsl4bsnbQg7KSR64uoXG4gICAgaWYgKGZvclRlc3RpbmcpIHtcbiAgICAgIHRoaXMuaXNJbml0aWFsaXplZCA9IHRydWU7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gVGFzayDrk7HroZ1cbiAgICBhd2FpdCB0aGlzLmluaXRpYWxpemVXb3JrZmxvd3ModGhpcy5jb25maWcudGFza3MpO1xuXG4gICAgLy8gU3luY2VyXG4gICAgY29uc3QgeyBTeW5jZXIgfSA9IGF3YWl0IGltcG9ydChcIi4uL3N5bmNlci9zeW5jZXJcIik7XG4gICAgdGhpcy5zeW5jZXIgPSBuZXcgU3luY2VyKCk7XG5cbiAgICAvLyBBdXRvbG9hZDogTW9kZWxzIC8gVHlwZXMgLyBBUElzIC8gV29ya2Zsb3dzIC8gVGVtcGxhdGVzIC8gU1NSIFJvdXRlc1xuICAgIGF3YWl0IHRoaXMuc3luY2VyLmF1dG9sb2FkVHlwZXMoKTtcbiAgICBhd2FpdCB0aGlzLnN5bmNlci5hdXRvbG9hZE1vZGVscygpO1xuICAgIGF3YWl0IHRoaXMuc3luY2VyLmF1dG9sb2FkQXBpcygpO1xuICAgIGF3YWl0IHRoaXMuc3luY2VyLmF1dG9sb2FkV29ya2Zsb3dzKCk7XG4gICAgY29uc3QgeyBUZW1wbGF0ZU1hbmFnZXIgfSA9IGF3YWl0IGltcG9ydChcIi4uL3RlbXBsYXRlXCIpO1xuICAgIGF3YWl0IFRlbXBsYXRlTWFuYWdlci5hdXRvbG9hZCgpO1xuICAgIGF3YWl0IHRoaXMuc3luY2VyLmF1dG9sb2FkU1NSUm91dGVzKCk7XG5cbiAgICBjb25zdCB7IGlzTG9jYWwsIGlzVGVzdCB9ID0gYXdhaXQgaW1wb3J0KFwiLi4vdXRpbHMvY29udHJvbGxlclwiKTtcbiAgICBpZiAoaXNMb2NhbCgpKSB7XG4gICAgICAvLyDroZzsu6zsl5DshJzripQg7L2U65OcIOyDneyEseydhCDsnITtlbQgQmlvbWUg7IWL7JeF7J20IO2VhOyalO2VqCAo7ZiE7J6sIGFwaVJvb3RQYXRoIOyghOuLrO2VmOyXrCDsi6TtlokpXG4gICAgICAoYXdhaXQgaW1wb3J0KFwiLi4vdXRpbHMvZm9ybWF0dGVyXCIpKS5zZXR1cEJpb21lKHRoaXMuYXBpUm9vdFBhdGgpO1xuICAgIH1cblxuICAgIGNvbnN0IHsgaXNIb3RSZWxvYWRTZXJ2ZXIgfSA9IGF3YWl0IGltcG9ydChcIi4uL3V0aWxzL2NvbnRyb2xsZXJcIik7XG4gICAgaWYgKGlzTG9jYWwoKSAmJiAhaXNUZXN0KCkgJiYgaXNIb3RSZWxvYWRTZXJ2ZXIoKSAmJiBlbmFibGVTeW5jKSB7XG4gICAgICBhd2FpdCB0aGlzLnN5bmNlci5zeW5jKCk7XG4gICAgICBhd2FpdCB0aGlzLnN0YXJ0V2F0Y2hlcigpO1xuICAgIH1cblxuICAgIHRoaXMuaXNJbml0aWFsaXplZCA9IHRydWU7XG4gICAgaWYgKCFkb1NpbGVudCkge1xuICAgICAgY29uc3QgY2hhbGsgPSAoYXdhaXQgaW1wb3J0KFwiY2hhbGtcIikpLmRlZmF1bHQ7XG4gICAgICBjb25zb2xlLnRpbWVFbmQoY2hhbGsuY3lhbihcIlNvbmFtdS5pbml0XCIpKTtcbiAgICB9XG4gIH1cblxuICBhc3luYyBjcmVhdGVTZXJ2ZXIoaW5pdE9wdGlvbnM/OiB7IGVuYWJsZVN5bmM/OiBib29sZWFuOyBkb1NpbGVudD86IGJvb2xlYW4gfSkge1xuICAgIGlmICh0aGlzLmlzSW5pdGlhbGl6ZWQgPT09IGZhbHNlKSB7XG4gICAgICBhd2FpdCB0aGlzLmluaXQoaW5pdE9wdGlvbnM/LmRvU2lsZW50LCBpbml0T3B0aW9ucz8uZW5hYmxlU3luYyk7XG4gICAgfVxuXG4gICAgY29uc3Qgb3B0aW9ucyA9IHRoaXMuY29uZmlnLnNlcnZlcjtcbiAgICBjb25zdCB7IGRlZmF1bHQ6IGZhc3RpZnkgfSA9IGF3YWl0IGltcG9ydChcImZhc3RpZnlcIik7XG4gICAgY29uc3QgeyBnZXRMb2dUYXBlRmFzdGlmeUxvZ2dlciB9ID0gYXdhaXQgaW1wb3J0KFwiQGxvZ3RhcGUvZmFzdGlmeVwiKTtcbiAgICBjb25zdCBzZXJ2ZXIgPSBmYXN0aWZ5KHtcbiAgICAgIC4uLm9wdGlvbnMuZmFzdGlmeSxcbiAgICAgIGxvZ2dlcjpcbiAgICAgICAgdGhpcy5jb25maWcubG9nZ2luZyAhPT0gZmFsc2VcbiAgICAgICAgICA/IGdldExvZ1RhcGVGYXN0aWZ5TG9nZ2VyKHtcbiAgICAgICAgICAgICAgY2F0ZWdvcnk6IHRoaXMuY29uZmlnLmxvZ2dpbmc/LmZhc3RpZnlDYXRlZ29yeSA/PyBbXCJmYXN0aWZ5XCJdLFxuICAgICAgICAgICAgfSlcbiAgICAgICAgICA6IHVuZGVmaW5lZCxcbiAgICB9KTtcbiAgICB0aGlzLnNlcnZlciA9IHNlcnZlcjtcblxuICAgIC8vIFN0b3JhZ2Ug7ISk7KCVIOKGkiBTdG9yYWdlTWFuYWdlciDsg53shLFcbiAgICBpZiAob3B0aW9ucy5zdG9yYWdlKSB7XG4gICAgICBjb25zdCB7IFN0b3JhZ2VNYW5hZ2VyIH0gPSBhd2FpdCBpbXBvcnQoXCIuLi9zdG9yYWdlL3N0b3JhZ2UtbWFuYWdlclwiKTtcbiAgICAgIHRoaXMuX3N0b3JhZ2UgPSBuZXcgU3RvcmFnZU1hbmFnZXIob3B0aW9ucy5zdG9yYWdlKTtcbiAgICB9XG5cbiAgICAvLyDtlIzrn6zqt7jsnbgg65Ox66GdXG4gICAgaWYgKG9wdGlvbnMucGx1Z2lucykge1xuICAgICAgYXdhaXQgdGhpcy5yZWdpc3RlclBsdWdpbnMoc2VydmVyLCBvcHRpb25zLnBsdWdpbnMpO1xuICAgIH1cblxuICAgIGlmIChvcHRpb25zLmF1dGgpIHtcbiAgICAgIGlmICghb3B0aW9ucy5wbHVnaW5zPy5zZXNzaW9uKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIkF1dGggcmVxdWlyZXMgc2Vzc2lvbiBwbHVnaW4uIFBsZWFzZSBhZGQgcGx1Z2lucy5zZXNzaW9uIGNvbmZpZ3VyYXRpb24uXCIpO1xuICAgICAgfVxuXG4gICAgICBhd2FpdCB0aGlzLnJlZ2lzdGVyQXV0aChzZXJ2ZXIsIG9wdGlvbnMuYXV0aCk7XG4gICAgfVxuXG4gICAgLy8gQVBJIOudvOyasO2MhSDshKTsoJVcbiAgICBhd2FpdCB0aGlzLndpdGhGYXN0aWZ5KHNlcnZlciwgb3B0aW9ucy5hcGlDb25maWcsIHtcbiAgICAgIGVuYWJsZVN5bmM6IGluaXRPcHRpb25zPy5lbmFibGVTeW5jLFxuICAgICAgZG9TaWxlbnQ6IGluaXRPcHRpb25zPy5kb1NpbGVudCxcbiAgICB9KTtcblxuICAgIC8vIOyEnOuyhCDsi5zsnpFcbiAgICBhd2FpdCB0aGlzLmJvb3Qoc2VydmVyLCBvcHRpb25zKTtcblxuICAgIHJldHVybiBzZXJ2ZXI7XG4gIH1cblxuICBhc3luYyB3aXRoRmFzdGlmeShcbiAgICBzZXJ2ZXI6IEZhc3RpZnlJbnN0YW5jZTxTZXJ2ZXIsIEluY29taW5nTWVzc2FnZSwgU2VydmVyUmVzcG9uc2U+LFxuICAgIGNvbmZpZzogU29uYW11RmFzdGlmeUNvbmZpZyxcbiAgICBvcHRpb25zPzoge1xuICAgICAgZW5hYmxlU3luYz86IGJvb2xlYW47XG4gICAgICBkb1NpbGVudD86IGJvb2xlYW47XG4gICAgfSxcbiAgKSB7XG4gICAgaWYgKHRoaXMuaXNJbml0aWFsaXplZCA9PT0gZmFsc2UpIHtcbiAgICAgIGF3YWl0IHRoaXMuaW5pdChvcHRpb25zPy5kb1NpbGVudCwgb3B0aW9ucz8uZW5hYmxlU3luYyk7XG4gICAgfVxuXG4gICAgdGhpcy5zZXJ2ZXIgPSBzZXJ2ZXI7XG5cbiAgICAvLyB0aW1lem9uZSDshKTsoJVcbiAgICBjb25zdCB0aW1lem9uZSA9IHRoaXMuY29uZmlnLmFwaS50aW1lem9uZTtcbiAgICBpZiAodGltZXpvbmUpIHtcbiAgICAgIC8vIO2DgOyehOyhtOyXkCDrp57qsowg7J2R64u1IOuCoOynnCDsiqTtirjrp4HsnYQg67OA7ZmY7ZW07KO87Ja07JW8IO2VqeuLiOuLpC5cbiAgICAgIC8vIOqwgOuguSB0aW1lem9uZeydtCBcIkFzaWEvU2VvdWxcIiDsnbTrqbRcbiAgICAgIC8vIFwiMjAyNS0xMS0yMVQwMDowMDowMC4wMDBaXCIg66W8IFwiMjAyNS0xMS0yMVQwOTowMDowMCswOTowMFwiIOycvOuhnCDrs4DtmZjtlbTso7zslrTslbwg7ZWp64uI64ukLlxuICAgICAgY29uc3QgeyBmb3JtYXRJblRpbWVab25lIH0gPSBhd2FpdCBpbXBvcnQoXCJkYXRlLWZucy10elwiKTtcblxuICAgICAgLy8gSVNPIDg2MDEg64Kg7KecIO2YleyLnSDsoJXqt5zsi50gKOyYiDogMjAyNC0wMS0xNVQwOTozMDowMC4wMDBaKVxuICAgICAgY29uc3QgSVNPX0RBVEVfUkVHRVggPSAvXlxcZHs0fS1cXGR7Mn0tXFxkezJ9VFxcZHsyfTpcXGR7Mn06XFxkezJ9KFxcLlxcZHszfSk/WiQvO1xuXG4gICAgICAvLyBU66W8IOuRmOufrOyLvCDsnpHsnYDrlLDsmLTtkZzqsIAg7JeG64uk66m0IFwiMjAyNS0xMS0xOTE3NjM1NDYxODkwMDAxODo1NjoyOSswOTowMFwi7JmAIOqwmeydgCDqsrDqs7zqsIAg64KY7Ji164uI64ukLlxuICAgICAgLy8g7J2064qUIGRhdGUtZm5zIO2KueyeheuLiOuLpC5cbiAgICAgIC8vIOydtOugh+qyjCDtlbTrj4Qg6rSc7LCu7Iq164uI64ukLiBcIjIwMjUtMTEtMTlUMTg6NTY6MjkrMDk6MDBcIiDrqqjslpHsnLzroZwg7J6YIOuCmOyYteuLiOuLpC5cbiAgICAgIGNvbnN0IERBVEVfRk9STUFUID0gXCJ5eXl5LU1NLWRkJ1QnSEg6bW06c3NYWFhcIjtcblxuICAgICAgc2VydmVyLnNldFJlcGx5U2VyaWFsaXplcigocGF5bG9hZCkgPT4ge1xuICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkocGF5bG9hZCwgKF9rZXksIHZhbHVlKSA9PiB7XG4gICAgICAgICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gXCJzdHJpbmdcIiAmJiBJU09fREFURV9SRUdFWC50ZXN0KHZhbHVlKSkge1xuICAgICAgICAgICAgcmV0dXJuIGZvcm1hdEluVGltZVpvbmUoXG4gICAgICAgICAgICAgIG5ldyBEYXRlKHZhbHVlKSxcbiAgICAgICAgICAgICAgdGltZXpvbmUgYXMgYCR7c3RyaW5nfS8ke3N0cmluZ31gLFxuICAgICAgICAgICAgICBEQVRFX0ZPUk1BVCxcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICAgICAgfSk7XG4gICAgICB9KTtcbiAgICAgIGlmICghb3B0aW9ucz8uZG9TaWxlbnQpIHtcbiAgICAgICAgY29uc3QgY2hhbGsgPSAoYXdhaXQgaW1wb3J0KFwiY2hhbGtcIikpLmRlZmF1bHQ7XG4gICAgICAgIGNvbnNvbGUubG9nKGNoYWxrLmdyZWVuKGBUaW1lem9uZSBzZXQgdG8gJHt0aW1lem9uZX1gKSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8g7KCE7LK0IOudvOyasO2MhSDrpqzsiqTtirhcbiAgICBzZXJ2ZXIuZ2V0KFxuICAgICAgYCR7dGhpcy5jb25maWcuYXBpLnJvdXRlLnByZWZpeH0vcm91dGVzYCxcbiAgICAgIGFzeW5jIChfcmVxdWVzdCwgX3JlcGx5KTogUHJvbWlzZTx0eXBlb2YgdGhpcy5zeW5jZXIuYXBpcz4gPT4ge1xuICAgICAgICByZXR1cm4gdGhpcy5zeW5jZXIuYXBpcztcbiAgICAgIH0sXG4gICAgKTtcblxuICAgIC8vIEhlYWx0aGNoZWNrIEFQSVxuICAgIHNlcnZlci5nZXQoXG4gICAgICBgJHt0aGlzLmNvbmZpZy5hcGkucm91dGUucHJlZml4fS9oZWFsdGhjaGVja2AsXG4gICAgICBhc3luYyAoX3JlcXVlc3QsIF9yZXBseSk6IFByb21pc2U8c3RyaW5nPiA9PiB7XG4gICAgICAgIHJldHVybiBcIm9rXCI7XG4gICAgICB9LFxuICAgICk7XG5cbiAgICAvLyBTb25hbXUgVUkgQVBJXG4gICAgY29uc3QgeyBzb25hbXVVSUFwaVBsdWdpbiB9ID0gYXdhaXQgaW1wb3J0KFwiLi4vdWkvYXBpXCIpO1xuICAgIHNlcnZlci5yZWdpc3Rlcihzb25hbXVVSUFwaVBsdWdpbik7XG5cbiAgICAvLyDroZzsu6wv7ZSE66Gc642V7IWYIO2ZmOqyvSDrtoTquLBcbiAgICBjb25zdCB7IGlzTG9jYWwgfSA9IGF3YWl0IGltcG9ydChcIi4uL3V0aWxzL2NvbnRyb2xsZXJcIik7XG4gICAgY29uc3Qgd2ViUGF0aCA9IHBhdGguam9pbih0aGlzLmFwcFJvb3RQYXRoLCBcIndlYlwiKTtcbiAgICBjb25zdCBoYXNXZWIgPSBmcy5leGlzdHNTeW5jKHdlYlBhdGgpO1xuXG4gICAgaWYgKGlzTG9jYWwoKSkge1xuICAgICAgLy8g66Gc7LusIOqwnOuwnCDtmZjqsr06IFZpdGUgRGV2IFNlcnZlciArIO2Gte2VqSDtlbjrk6Trn6xcbiAgICAgIGlmIChoYXNXZWIpIHtcbiAgICAgICAgYXdhaXQgdGhpcy5zZXR1cFZpdGVEZXZTZXJ2ZXIoc2VydmVyLCB3ZWJQYXRoLCBjb25maWcpO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAvLyDtlITroZzrjZXshZgg7ZmY6rK9OiDqsJzrs4QgQVBJIOudvOyasO2KuCArIOygleyggSDtjIzsnbwg7ISc67mZXG4gICAgICBmb3IgKGNvbnN0IGFwaSBvZiB0aGlzLnN5bmNlci5hcGlzKSB7XG4gICAgICAgIGlmICh0aGlzLnN5bmNlci5tb2RlbHNbYXBpLm1vZGVsTmFtZV0gPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihg7KCV7J2Y65CY7KeAIOyViuydgCDrqqjrjbjsl5Ag7KCR6re8ICR7YXBpLm1vZGVsTmFtZX1gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHNlcnZlci5yb3V0ZSh7XG4gICAgICAgICAgbWV0aG9kOiBhcGkub3B0aW9ucy5odHRwTWV0aG9kID8/IFwiR0VUXCIsXG4gICAgICAgICAgdXJsOiB0aGlzLmNvbmZpZy5hcGkucm91dGUucHJlZml4ICsgYXBpLnBhdGgsXG4gICAgICAgICAgaGFuZGxlcjogdGhpcy5jcmVhdGVBcGlIYW5kbGVyKGFwaSwgY29uZmlnKSxcbiAgICAgICAgfSk7XG4gICAgICB9XG5cbiAgICAgIGlmIChoYXNXZWIpIHtcbiAgICAgICAgYXdhaXQgdGhpcy5zZXR1cFN0YXRpY1dlYlNlcnZlcihzZXJ2ZXIsIHdlYlBhdGgsIGNvbmZpZyk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLy8gYmlvbWUtaWdub3JlIGxpbnQvc3VzcGljaW91cy9ub0V4cGxpY2l0QW55OiBWaXRlRGV2U2VydmVyIO2DgOyeheydhCDrj5nsoIHsnLzroZwg66Gc65Oc7ZW07JW8IO2VqFxuICBwcml2YXRlIHZpdGVTZXJ2ZXI6IGFueSA9IG51bGw7XG5cbiAgcHJpdmF0ZSBhc3luYyBzZXR1cFZpdGVEZXZTZXJ2ZXIoXG4gICAgc2VydmVyOiBGYXN0aWZ5SW5zdGFuY2U8U2VydmVyLCBJbmNvbWluZ01lc3NhZ2UsIFNlcnZlclJlc3BvbnNlPixcbiAgICB3ZWJQYXRoOiBzdHJpbmcsXG4gICAgY29uZmlnOiBTb25hbXVGYXN0aWZ5Q29uZmlnLFxuICApOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAvLyBAZmFzdGlmeS9taWRkaWUg65Ox66GdIChDb25uZWN0LXN0eWxlIG1pZGRsZXdhcmUg7KeA7JuQKVxuICAgIGF3YWl0IHNlcnZlci5yZWdpc3RlcigoYXdhaXQgaW1wb3J0KFwiQGZhc3RpZnkvbWlkZGllXCIpKS5kZWZhdWx0KTtcblxuICAgIGNvbnN0IHZpdGUgPSBhd2FpdCBpbXBvcnQoXCJ2aXRlXCIpO1xuXG4gICAgdGhpcy52aXRlU2VydmVyID0gYXdhaXQgdml0ZS5jcmVhdGVTZXJ2ZXIoe1xuICAgICAgcm9vdDogd2ViUGF0aCxcbiAgICAgIHNlcnZlcjoge1xuICAgICAgICBtaWRkbGV3YXJlTW9kZTogdHJ1ZSxcbiAgICAgICAgaG1yOiB7XG4gICAgICAgICAgc2VydmVyOiBzZXJ2ZXIuc2VydmVyLFxuICAgICAgICB9LFxuICAgICAgfSxcbiAgICAgIGFwcFR5cGU6IFwiY3VzdG9tXCIsXG4gICAgfSk7XG5cbiAgICAvLyBWaXRlIG1pZGRsZXdhcmUg65Ox66GdIChWaXRlIOyXkOyFiyDsspjrpqwpXG4gICAgc2VydmVyLnVzZSgocmVxLCByZXMsIG5leHQpID0+IHtcbiAgICAgIC8vIEFQSeyZgCBTb25hbXUgVUnripQgRmFzdGlmeSDrnbzsmrDtirjqsIAg7LKY66as7ZWY64+E66GdIHNraXBcbiAgICAgIGlmIChyZXEudXJsPy5zdGFydHNXaXRoKHRoaXMuY29uZmlnLmFwaS5yb3V0ZS5wcmVmaXgpIHx8IHJlcS51cmw/LnN0YXJ0c1dpdGgoXCIvc29uYW11LXVpXCIpKSB7XG4gICAgICAgIHJldHVybiBuZXh0KCk7XG4gICAgICB9XG4gICAgICAvLyDrgpjrqLjsp4DripQgVml0ZSBtaWRkbGV3YXJl66GcIOyghOuLrFxuICAgICAgcmV0dXJuIHRoaXMudml0ZVNlcnZlci5taWRkbGV3YXJlcyhyZXEsIHJlcywgbmV4dCk7XG4gICAgfSk7XG5cbiAgICAvLyBBUEkg64+Z7KCBIOudvOyasO2MhSAoY2F0Y2gtYWxsIOyghOyXkCDrk7HroZ0pXG4gICAgZm9yIChjb25zdCBhcGkgb2YgdGhpcy5zeW5jZXIuYXBpcykge1xuICAgICAgaWYgKHRoaXMuc3luY2VyLm1vZGVsc1thcGkubW9kZWxOYW1lXSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihg7KCV7J2Y65CY7KeAIOyViuydgCDrqqjrjbjsl5Ag7KCR6re8ICR7YXBpLm1vZGVsTmFtZX1gKTtcbiAgICAgIH1cblxuICAgICAgc2VydmVyLnJvdXRlKHtcbiAgICAgICAgbWV0aG9kOiBhcGkub3B0aW9ucy5odHRwTWV0aG9kID8/IFwiR0VUXCIsXG4gICAgICAgIHVybDogdGhpcy5jb25maWcuYXBpLnJvdXRlLnByZWZpeCArIGFwaS5wYXRoLFxuICAgICAgICBoYW5kbGVyOiB0aGlzLmNyZWF0ZUFwaUhhbmRsZXIoYXBpLCBjb25maWcpLFxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgLy8gQ2F0Y2gtYWxsIO2VuOuTpOufrDogU1NSICsgQ1NSIGZhbGxiYWNrXG4gICAgc2VydmVyLnNldE5vdEZvdW5kSGFuZGxlcihhc3luYyAocmVxdWVzdCwgcmVwbHkpID0+IHtcbiAgICAgIGNvbnN0IHVybCA9IHJlcXVlc3QudXJsO1xuXG4gICAgICAvLyBTU1Ig65287Jqw7Yq4IOyytO2BrFxuICAgICAgY29uc3QgeyBtYXRjaFNTUlJvdXRlIH0gPSBhd2FpdCBpbXBvcnQoXCIuLi9zc3JcIik7XG4gICAgICBjb25zdCBtYXRjaCA9IG1hdGNoU1NSUm91dGUodXJsKTtcblxuICAgICAgaWYgKG1hdGNoKSB7XG4gICAgICAgIGNvbnNvbGUubG9nKGBbU1NSXSBNYXRjaGVkIHJvdXRlOiAke21hdGNoLnJvdXRlLnBhdGh9YCk7XG4gICAgICAgIC8vIFNTUiDroIzrjZTrp4FcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBjb25zdCB7IHJlbmRlclNTUiB9ID0gYXdhaXQgaW1wb3J0KFwiLi4vc3NyXCIpO1xuICAgICAgICAgIGNvbnN0IGh0bWwgPSBhd2FpdCByZW5kZXJTU1IoXG4gICAgICAgICAgICB1cmwsXG4gICAgICAgICAgICBtYXRjaC5yb3V0ZSxcbiAgICAgICAgICAgIG1hdGNoLnBhcmFtcyxcbiAgICAgICAgICAgIHJlcXVlc3QsXG4gICAgICAgICAgICByZXBseSxcbiAgICAgICAgICAgIGNvbmZpZyxcbiAgICAgICAgICAgIHRoaXMudml0ZVNlcnZlcixcbiAgICAgICAgICApO1xuICAgICAgICAgIHJlcGx5LnR5cGUoXCJ0ZXh0L2h0bWxcIikuc2VuZChodG1sKTtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICBjb25zb2xlLmVycm9yKFwiU1NSIEVycm9yOlwiLCBlKTtcbiAgICAgICAgICBjb25zb2xlLmxvZyhcIkZhbGxpbmcgYmFjayB0byBDU1IuLi5cIik7XG4gICAgICAgICAgLy8gZmFsbGJhY2sgdG8gQ1NSICjslYTrnpgg66Gc7KeBIOyLpO2WiSlcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICAvLyBDU1IgZmFsbGJhY2tcbiAgICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IGZzID0gYXdhaXQgaW1wb3J0KFwibm9kZTpmcy9wcm9taXNlc1wiKTtcbiAgICAgICAgbGV0IHRlbXBsYXRlID0gYXdhaXQgZnMucmVhZEZpbGUoXG4gICAgICAgICAgcGF0aC5qb2luKHRoaXMudml0ZVNlcnZlci5jb25maWcucm9vdCwgXCJpbmRleC5odG1sXCIpLFxuICAgICAgICAgIFwidXRmLThcIixcbiAgICAgICAgKTtcbiAgICAgICAgdGVtcGxhdGUgPSBhd2FpdCB0aGlzLnZpdGVTZXJ2ZXIudHJhbnNmb3JtSW5kZXhIdG1sKHVybCwgdGVtcGxhdGUpO1xuXG4gICAgICAgIHJlcGx5LnR5cGUoXCJ0ZXh0L2h0bWxcIikuc2VuZCh0ZW1wbGF0ZSk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgdGhpcy52aXRlU2VydmVyLnNzckZpeFN0YWNrdHJhY2UoZSBhcyBFcnJvcik7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoZSk7XG4gICAgICAgIHJlcGx5LnN0YXR1cyg1MDApLnNlbmQoKGUgYXMgRXJyb3IpLm1lc3NhZ2UpO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICAvLyDshJzrsoQg7KKF66OMIOyLnCBWaXRl64+EIOyiheujjFxuICAgIHNlcnZlci5hZGRIb29rKFwib25DbG9zZVwiLCBhc3luYyAoKSA9PiB7XG4gICAgICBhd2FpdCB0aGlzLnZpdGVTZXJ2ZXIuY2xvc2UoKTtcbiAgICB9KTtcblxuICAgIGNvbnNvbGUubG9nKFwi4pyTIFZpdGUgZGV2IHNlcnZlciBpbnRlZ3JhdGVkXCIpO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBzZXR1cFN0YXRpY1dlYlNlcnZlcihcbiAgICBzZXJ2ZXI6IEZhc3RpZnlJbnN0YW5jZTxTZXJ2ZXIsIEluY29taW5nTWVzc2FnZSwgU2VydmVyUmVzcG9uc2U+LFxuICAgIF93ZWJQYXRoOiBzdHJpbmcsXG4gICAgY29uZmlnOiBTb25hbXVGYXN0aWZ5Q29uZmlnLFxuICApOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAvLyDqsr3roZwg66qF7ZmV7ZmUOiBhcGkvcHVibGljL3dlYiwgYXBpL2Rpc3Qvc3NyXG4gICAgY29uc3Qgd2ViRGlzdFBhdGggPSBwYXRoLmpvaW4odGhpcy5hcGlSb290UGF0aCwgXCJwdWJsaWNcIiwgXCJ3ZWJcIik7XG4gICAgY29uc3Qgc3NyUGF0aCA9IHBhdGguam9pbih0aGlzLmFwaVJvb3RQYXRoLCBcImRpc3RcIiwgXCJzc3JcIik7XG5cbiAgICBpZiAoIWZzLmV4aXN0c1N5bmMod2ViRGlzdFBhdGgpKSB7XG4gICAgICBjb25zb2xlLndhcm4oYOKaoCBXZWIgZGlzdCBub3QgZm91bmQ6ICR7d2ViRGlzdFBhdGh9YCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gU1NSIGVudHJ5IOyhtOyerCDsl6zrtoAg7ZmV7J24XG4gICAgY29uc3Qgc3NyRW50cnlQYXRoID0gcGF0aC5qb2luKHNzclBhdGgsIFwiZW50cnktc2VydmVyLmdlbmVyYXRlZC5qc1wiKTtcbiAgICBjb25zdCBzc3JBdmFpbGFibGUgPSBmcy5leGlzdHNTeW5jKHNzckVudHJ5UGF0aCk7XG5cbiAgICBpZiAoIXNzckF2YWlsYWJsZSkge1xuICAgICAgY29uc29sZS53YXJuKGDimqAgU1NSIGVudHJ5IG5vdCBmb3VuZDogJHtzc3JFbnRyeVBhdGh9YCk7XG4gICAgICBjb25zb2xlLndhcm4oXCIgIFNTUiB3aWxsIGJlIGRpc2FibGVkLiBPbmx5IENTUiB3aWxsIHdvcmsuXCIpO1xuICAgIH1cblxuICAgIC8vIFNTUiDrnbzsmrDtirgg66Gc65OcIChwcm9kdWN0aW9u7JeQ7ISc66eMLCDsgqzsmqnsnpAg7ZSE66Gc7KCd7Yq47J2YIHNzci9yb3V0ZXMudHMpXG4gICAgaWYgKHNzckF2YWlsYWJsZSkge1xuICAgICAgY29uc3Qgc3NyUm91dGVzUGF0aCA9IHBhdGguam9pbih0aGlzLmFwaVJvb3RQYXRoLCBcImRpc3RcIiwgXCJzc3JcIiwgXCJyb3V0ZXMuanNcIik7XG4gICAgICBpZiAoZnMuZXhpc3RzU3luYyhzc3JSb3V0ZXNQYXRoKSkge1xuICAgICAgICBhd2FpdCBpbXBvcnQoc3NyUm91dGVzUGF0aCk7XG4gICAgICAgIGNvbnNvbGUubG9nKFwi4pyTIFNTUiByb3V0ZXMgbG9hZGVkXCIpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY29uc29sZS53YXJuKGDimqAgU1NSIHJvdXRlcyBub3QgZm91bmQ6ICR7c3NyUm91dGVzUGF0aH1gKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyDroaTrp4Eg7JeF642w7J207Yq4IOuMgOydkTogYXNzZXQgaGFzaCDrtojsnbzsuZgg7IucIO2YhOyerCDrsoTsoIQg7KeB7KCRIOyEnOu5mVxuICAgIHNlcnZlci5nZXQoXCIvYXNzZXRzLzpmaWxlbmFtZVwiLCBhc3luYyAocmVxdWVzdCwgcmVwbHkpID0+IHtcbiAgICAgIGNvbnN0IHJlcXVlc3RlZEZpbGUgPSAocmVxdWVzdC5wYXJhbXMgYXMgeyBmaWxlbmFtZTogc3RyaW5nIH0pLmZpbGVuYW1lO1xuICAgICAgY29uc3QgYXNzZXRzRGlyID0gcGF0aC5qb2luKHdlYkRpc3RQYXRoLCBcImFzc2V0c1wiKTtcblxuICAgICAgLy8gaW5kZXgtKi5qcyDrmJDripQgaW5kZXgtKi5jc3Mg7JqU7LKt7J24IOqyveyasFxuICAgICAgaWYgKC9eaW5kZXgtW2EtZjAtOV0rXFwuKGpzfGNzcykkLy50ZXN0KHJlcXVlc3RlZEZpbGUpKSB7XG4gICAgICAgIGNvbnN0IGV4dCA9IHJlcXVlc3RlZEZpbGUuc3BsaXQoXCIuXCIpLnBvcCgpO1xuICAgICAgICBjb25zdCBmaWxlcyA9IGZzLnJlYWRkaXJTeW5jKGFzc2V0c0Rpcik7XG4gICAgICAgIGNvbnN0IGN1cnJlbnRGaWxlID0gZmlsZXMuZmluZCgoZikgPT4gZi5zdGFydHNXaXRoKFwiaW5kZXgtXCIpICYmIGYuZW5kc1dpdGgoYC4ke2V4dH1gKSk7XG5cbiAgICAgICAgaWYgKGN1cnJlbnRGaWxlKSB7XG4gICAgICAgICAgY29uc3QgZmlsZVBhdGggPSBwYXRoLmpvaW4oYXNzZXRzRGlyLCBjdXJyZW50RmlsZSk7XG4gICAgICAgICAgY29uc3QgY29udGVudCA9IGZzLnJlYWRGaWxlU3luYyhmaWxlUGF0aCk7XG4gICAgICAgICAgcmVwbHkudHlwZShleHQgPT09IFwianNcIiA/IFwiYXBwbGljYXRpb24vamF2YXNjcmlwdFwiIDogXCJ0ZXh0L2Nzc1wiKTtcbiAgICAgICAgICByZXBseS5oZWFkZXIoXCJDYWNoZS1Db250cm9sXCIsIFwicHVibGljLCBtYXgtYWdlPTMxNTM2MDAwLCBpbW11dGFibGVcIik7XG4gICAgICAgICAgcmV0dXJuIHJlcGx5LnNlbmQoY29udGVudCk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgLy8g7J2867CYIO2MjOydvCDshJzruZlcbiAgICAgIGNvbnN0IGZpbGVQYXRoID0gcGF0aC5qb2luKGFzc2V0c0RpciwgcmVxdWVzdGVkRmlsZSk7XG4gICAgICBpZiAoZnMuZXhpc3RzU3luYyhmaWxlUGF0aCkpIHtcbiAgICAgICAgY29uc3QgY29udGVudCA9IGZzLnJlYWRGaWxlU3luYyhmaWxlUGF0aCk7XG4gICAgICAgIGNvbnN0IGV4dCA9IHJlcXVlc3RlZEZpbGUuc3BsaXQoXCIuXCIpLnBvcCgpO1xuICAgICAgICByZXBseS50eXBlKGV4dCA9PT0gXCJqc1wiID8gXCJhcHBsaWNhdGlvbi9qYXZhc2NyaXB0XCIgOiBleHQgPT09IFwiY3NzXCIgPyBcInRleHQvY3NzXCIgOiBcIlwiKTtcbiAgICAgICAgaWYgKHJlcXVlc3RlZEZpbGUuaW5jbHVkZXMoXCItXCIpKSB7XG4gICAgICAgICAgcmVwbHkuaGVhZGVyKFwiQ2FjaGUtQ29udHJvbFwiLCBcInB1YmxpYywgbWF4LWFnZT0zMTUzNjAwMCwgaW1tdXRhYmxlXCIpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXBseS5zZW5kKGNvbnRlbnQpO1xuICAgICAgfVxuXG4gICAgICByZXBseS5jb2RlKDQwNCkuc2VuZChcIk5vdCBmb3VuZFwiKTtcbiAgICB9KTtcblxuICAgIC8vIFNQQS9TU1Ig65287Jqw7YyFXG4gICAgc2VydmVyLnNldE5vdEZvdW5kSGFuZGxlcihhc3luYyAocmVxdWVzdCwgcmVwbHkpID0+IHtcbiAgICAgIC8vIC9hcGksIC9zb25hbXUtdWnripQgNDA0IOq3uOuMgOuhnFxuICAgICAgaWYgKHJlcXVlc3QudXJsLnN0YXJ0c1dpdGgoXCIvYXBpXCIpIHx8IHJlcXVlc3QudXJsLnN0YXJ0c1dpdGgoXCIvc29uYW11LXVpXCIpKSB7XG4gICAgICAgIHJlcGx5LmNvZGUoNDA0KS5zZW5kKHsgZXJyb3I6IFwiTm90IEZvdW5kXCIgfSk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgY29uc3QgdXJsID0gcmVxdWVzdC51cmw7XG5cbiAgICAgIC8vIFNTUiDrnbzsmrDtirgg7LK07YGsXG4gICAgICBpZiAoc3NyQXZhaWxhYmxlKSB7XG4gICAgICAgIGNvbnN0IHsgbWF0Y2hTU1JSb3V0ZSB9ID0gYXdhaXQgaW1wb3J0KFwiLi4vc3NyXCIpO1xuICAgICAgICBjb25zdCBtYXRjaCA9IG1hdGNoU1NSUm91dGUodXJsKTtcblxuICAgICAgICBpZiAobWF0Y2gpIHtcbiAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgLy8gcmVuZGVyU1NSIOyerOyCrOyaqSAodml0ZSDsl4bsnbQg7Zi47LacID0gcHJvZHVjdGlvbiDrqqjrk5wpXG4gICAgICAgICAgICBjb25zdCB7IHJlbmRlclNTUiB9ID0gYXdhaXQgaW1wb3J0KFwiLi4vc3NyL3JlbmRlcmVyXCIpO1xuICAgICAgICAgICAgY29uc3QgaHRtbCA9IGF3YWl0IHJlbmRlclNTUih1cmwsIG1hdGNoLnJvdXRlLCBtYXRjaC5wYXJhbXMsIHJlcXVlc3QsIHJlcGx5LCBjb25maWcpO1xuICAgICAgICAgICAgcmVwbHkudHlwZShcInRleHQvaHRtbFwiKS5zZW5kKGh0bWwpO1xuICAgICAgICAgICAgY29uc29sZS5sb2coYFtTU1JdIE1hdGNoZWQgcm91dGU6ICR7bWF0Y2gucm91dGUucGF0aH1gKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKFwiW1NTUiBFcnJvcl1cIiwge1xuICAgICAgICAgICAgICB1cmw6IHJlcXVlc3QudXJsLFxuICAgICAgICAgICAgICByb3V0ZTogbWF0Y2gucm91dGUucGF0aCxcbiAgICAgICAgICAgICAgZXJyb3I6IGUgaW5zdGFuY2VvZiBFcnJvciA/IGUubWVzc2FnZSA6IFN0cmluZyhlKSxcbiAgICAgICAgICAgICAgdGltZXN0YW1wOiBuZXcgRGF0ZSgpLnRvSVNPU3RyaW5nKCksXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIC8vIENTUuuhnCBmYWxsYmFja1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICAvLyBDU1IgZmFsbGJhY2sgKFNTUiDsi6TtjKgg7IucIOuYkOuKlCBTU1Ig65287Jqw7Yq46rCAIOyVhOuLjCDqsr3smrApXG4gICAgICBjb25zdCBpbmRleFBhdGggPSBwYXRoLmpvaW4od2ViRGlzdFBhdGgsIFwiaW5kZXguaHRtbFwiKTtcbiAgICAgIGNvbnN0IGh0bWwgPSBmcy5yZWFkRmlsZVN5bmMoaW5kZXhQYXRoLCBcInV0Zi04XCIpO1xuICAgICAgcmVwbHkudHlwZShcInRleHQvaHRtbFwiKS5zZW5kKGh0bWwpO1xuICAgIH0pO1xuXG4gICAgY29uc29sZS5sb2coYOKckyBTdGF0aWMgd2ViIHNlcnZlciBjb25maWd1cmVkIHdpdGggJHtzc3JBdmFpbGFibGUgPyBcIlNTUlwiIDogXCJDU1Igb25seVwifSBzdXBwb3J0YCk7XG4gIH1cblxuICBjcmVhdGVBcGlIYW5kbGVyKFxuICAgIGFwaTogRXh0ZW5kZWRBcGksXG4gICAgY29uZmlnOiBTb25hbXVGYXN0aWZ5Q29uZmlnLFxuICApOiAocmVxdWVzdDogRmFzdGlmeVJlcXVlc3QsIHJlcGx5OiBGYXN0aWZ5UmVwbHkpID0+IFByb21pc2U8dW5rbm93bj4ge1xuICAgIHJldHVybiBhc3luYyAocmVxdWVzdDogRmFzdGlmeVJlcXVlc3QsIHJlcGx5OiBGYXN0aWZ5UmVwbHkpOiBQcm9taXNlPHVua25vd24+ID0+IHtcbiAgICAgIChhcGkub3B0aW9ucy5ndWFyZHMgPz8gW10pLmV2ZXJ5KChndWFyZCkgPT4gY29uZmlnLmd1YXJkSGFuZGxlcihndWFyZCwgcmVxdWVzdCwgYXBpKSk7XG5cbiAgICAgIC8vIO2MjOudvOuvuO2EsCDsoJXrs7TroZwgem9kIOyKpO2CpOuniCDruYzrk5xcbiAgICAgIGNvbnN0IHsgZ2V0Wm9kT2JqZWN0RnJvbUFwaSB9ID0gYXdhaXQgaW1wb3J0KFwiLi9jb2RlLWNvbnZlcnRlcnNcIik7XG4gICAgICBjb25zdCBSZXFUeXBlID0gZ2V0Wm9kT2JqZWN0RnJvbUFwaShhcGksIHRoaXMuc3luY2VyLnR5cGVzKTtcblxuICAgICAgLy8gcmVxdWVzdCDtjIzsi7FcbiAgICAgIGNvbnN0IHdoaWNoID0gYXBpLm9wdGlvbnMuaHR0cE1ldGhvZCA9PT0gXCJHRVRcIiA/IFwicXVlcnlcIiA6IFwiYm9keVwiO1xuICAgICAgbGV0IHJlcUJvZHk6IHtcbiAgICAgICAgW2tleTogc3RyaW5nXTogdW5rbm93bjtcbiAgICAgIH07XG4gICAgICB0cnkge1xuICAgICAgICBjb25zdCB7IGZhc3RpZnlDYXN0ZXIgfSA9IGF3YWl0IGltcG9ydChcIi4vY2FzdGVyXCIpO1xuICAgICAgICByZXFCb2R5ID0gZmFzdGlmeUNhc3RlcihSZXFUeXBlKS5wYXJzZShyZXF1ZXN0W3doaWNoXSA/PyB7fSk7XG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIGNvbnN0IHsgWm9kRXJyb3IgfSA9IGF3YWl0IGltcG9ydChcInpvZFwiKTtcbiAgICAgICAgaWYgKGUgaW5zdGFuY2VvZiBab2RFcnJvcikge1xuICAgICAgICAgIGNvbnN0IHsgaHVtYW5pemVab2RFcnJvciB9ID0gYXdhaXQgaW1wb3J0KFwiLi4vdXRpbHMvem9kLWVycm9yXCIpO1xuICAgICAgICAgIGNvbnN0IG1lc3NhZ2VzID0gaHVtYW5pemVab2RFcnJvcihlKVxuICAgICAgICAgICAgLm1hcCgoaXNzdWUpID0+IGlzc3VlLm1lc3NhZ2UpXG4gICAgICAgICAgICAuam9pbihcIiBcIik7XG4gICAgICAgICAgY29uc3QgeyBCYWRSZXF1ZXN0RXhjZXB0aW9uIH0gPSBhd2FpdCBpbXBvcnQoXCIuLi9leGNlcHRpb25zL3NvLWV4Y2VwdGlvbnNcIik7XG4gICAgICAgICAgdGhyb3cgbmV3IEJhZFJlcXVlc3RFeGNlcHRpb24obWVzc2FnZXMsIHtcbiAgICAgICAgICAgIHpvZEVycm9yOiBlLFxuICAgICAgICAgIH0pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRocm93IGU7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgLy8gQ29udGVudC1UeXBlXG4gICAgICByZXBseS50eXBlKGFwaS5vcHRpb25zLmNvbnRlbnRUeXBlID8/IFwiYXBwbGljYXRpb24vanNvblwiKTtcblxuICAgICAgLy8gQ29udGV4dCDsg53shLFcbiAgICAgIGNvbnN0IGNvbnRleHQ6IENvbnRleHQgPSBhd2FpdCB0aGlzLmNyZWF0ZUNvbnRleHQoY29uZmlnLCByZXF1ZXN0LCByZXBseSk7XG5cbiAgICAgIC8vIOuqqOuNuCDrqZTshozrk5wgYXJncyDsg53shLHtlZjsl6wg7Zi47LacXG4gICAgICBjb25zdCB7IEFwaVBhcmFtVHlwZSB9ID0gYXdhaXQgaW1wb3J0KFwiLi4vdHlwZXMvdHlwZXNcIik7XG4gICAgICBjb25zdCBhcmdzID0gYXBpLnBhcmFtZXRlcnMubWFwKChwYXJhbSkgPT4ge1xuICAgICAgICAvLyBDb250ZXh0IOyduOygneyFmFxuICAgICAgICBpZiAoQXBpUGFyYW1UeXBlLmlzQ29udGV4dChwYXJhbS50eXBlKSkge1xuICAgICAgICAgIHJldHVybiBjb250ZXh0O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHJldHVybiByZXFCb2R5W3BhcmFtLm5hbWVdO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIHJldHVybiB0aGlzLmludm9rZU1vZGVsTWV0aG9kKGFwaSwgYXJncywgY29udGV4dCwgcmVwbHkpO1xuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogU1NS7JqpIEFQSSDtmLjstpwgKEhUVFAg7Jik67KE7Zek65OcIOyXhuydtCDsp4HsoJEg7Zi47LacKVxuICAgKiBjcmVhdGVBcGlIYW5kbGVy7J2YIOuhnOyngeydhCDsnqzsgqzsmqntlZjrkJgsIHJlcXVlc3Qg7YyM7IuxIOuMgOyLoCBwYXJhbXMg7KeB7KCRIOyCrOyaqVxuICAgKi9cbiAgYXN5bmMgaW52b2tlQXBpRm9yU1NSKFxuICAgIGFwaTogRXh0ZW5kZWRBcGksXG4gICAgLy8gYmlvbWUtaWdub3JlIGxpbnQvc3VzcGljaW91cy9ub0V4cGxpY2l0QW55OiBTU1Lsl5DshJwg64uk7JaR7ZWcIO2DgOyeheydmCBwYXJhbXPrpbwg67Cb7JWE7JW8IO2VqFxuICAgIHBhcmFtczogYW55W10sXG4gICAgY29uZmlnOiBTb25hbXVGYXN0aWZ5Q29uZmlnLFxuICAgIHJlcXVlc3Q6IEZhc3RpZnlSZXF1ZXN0LFxuICAgIHJlcGx5OiBGYXN0aWZ5UmVwbHksXG4gICk6IFByb21pc2U8dW5rbm93bj4ge1xuICAgIC8vIENvbnRleHQg7IOd7ISxICjquLDsobQg66mU7IaM65OcIOyerOyCrOyaqSlcbiAgICBjb25zdCBjb250ZXh0ID0gYXdhaXQgdGhpcy5jcmVhdGVDb250ZXh0KGNvbmZpZywgcmVxdWVzdCwgcmVwbHkpO1xuXG4gICAgLy8gYXJncyDsg53shLE6IENvbnRleHQg7YyM652866+47YSw64qUIOyjvOyehSwg64KY66i47KeA64qUIHBhcmFtc+yXkOyEnCDqsIDsoLjsmKTquLBcbiAgICBjb25zdCB7IEFwaVBhcmFtVHlwZSB9ID0gYXdhaXQgaW1wb3J0KFwiLi4vdHlwZXMvdHlwZXNcIik7XG4gICAgbGV0IHBhcmFtc0luZGV4ID0gMDtcbiAgICBjb25zdCBhcmdzID0gYXBpLnBhcmFtZXRlcnMubWFwKChwYXJhbSkgPT4ge1xuICAgICAgaWYgKEFwaVBhcmFtVHlwZS5pc0NvbnRleHQocGFyYW0udHlwZSkpIHtcbiAgICAgICAgcmV0dXJuIGNvbnRleHQ7XG4gICAgICB9XG4gICAgICByZXR1cm4gcGFyYW1zW3BhcmFtc0luZGV4KytdO1xuICAgIH0pO1xuXG4gICAgLy8g66qo6424IOuplOyEnOuTnCDtmLjstpwgKOq4sOyhtCDrqZTshJzrk5wg7J6s7IKs7JqpKVxuICAgIHJldHVybiB0aGlzLmludm9rZU1vZGVsTWV0aG9kKGFwaSwgYXJncywgY29udGV4dCwgcmVwbHkpO1xuICB9XG5cbiAgYXN5bmMgaW52b2tlTW9kZWxNZXRob2QoXG4gICAgYXBpOiBFeHRlbmRlZEFwaSxcbiAgICBhcmdzOiB1bmtub3duW10sXG4gICAgY29udGV4dDogQ29udGV4dCxcbiAgICByZXBseTogRmFzdGlmeVJlcGx5LFxuICApOiBQcm9taXNlPHVua25vd24+IHtcbiAgICBjb25zdCBtb2RlbCA9IHRoaXMuc3luY2VyLm1vZGVsc1thcGkubW9kZWxOYW1lXTtcbiAgICByZXR1cm4gdGhpcy5hc3luY0xvY2FsU3RvcmFnZS5ydW4oeyBjb250ZXh0IH0sIGFzeW5jICgpID0+IHtcbiAgICAgIC8vIGJpb21lLWlnbm9yZSBsaW50L3N1c3BpY2lvdXMvbm9FeHBsaWNpdEFueTogbW9kZWzsnYAg66qo6424IOyduOyKpO2EtOyKpOydtOuvgOuhnCDrqZTshJzrk5wg7Zi47LacIOqwgOuKpVxuICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgKG1vZGVsIGFzIGFueSlbYXBpLm1ldGhvZE5hbWVdLmFwcGx5KG1vZGVsLCBhcmdzKTtcbiAgICAgIHJlcGx5LnR5cGUoYXBpLm9wdGlvbnMuY29udGVudFR5cGUgPz8gXCJhcHBsaWNhdGlvbi9qc29uXCIpO1xuXG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH0pO1xuICB9XG5cbiAgYXN5bmMgY3JlYXRlQ29udGV4dChcbiAgICBjb25maWc6IFNvbmFtdUZhc3RpZnlDb25maWcsXG4gICAgcmVxdWVzdDogRmFzdGlmeVJlcXVlc3QsXG4gICAgcmVwbHk6IEZhc3RpZnlSZXBseSxcbiAgKTogUHJvbWlzZTxDb250ZXh0PiB7XG4gICAgLy8gY3JlYXRlU1NFRmFjdG9yeSDtlajsiJjsl5Ag66+466asIHJlcXVlc3TsnZggc29ja2V06rO8IHJlcGx566W8IOuwlOyduOuUqS5cbiAgICBjb25zdCB7IGNyZWF0ZVNTRUZhY3RvcnkgfSA9IGF3YWl0IGltcG9ydChcIi4uL3N0cmVhbS9zc2VcIik7XG4gICAgY29uc3QgY3JlYXRlU1NFID0gKDxUIGV4dGVuZHMgWm9kT2JqZWN0PihcbiAgICAgIF9yZXF1ZXN0OiBGYXN0aWZ5UmVxdWVzdCxcbiAgICAgIF9yZXBseTogRmFzdGlmeVJlcGx5LFxuICAgICAgX2V2ZW50czogVCxcbiAgICApID0+IGNyZWF0ZVNTRUZhY3RvcnkoX3JlcXVlc3Quc29ja2V0LCBfcmVwbHksIF9ldmVudHMpKS5iaW5kKG51bGwsIHJlcXVlc3QsIHJlcGx5KTtcblxuICAgIGNvbnN0IGNvbnRleHQ6IENvbnRleHQgPSB7XG4gICAgICAuLi4oYXdhaXQgUHJvbWlzZS5yZXNvbHZlKFxuICAgICAgICBjb25maWcuY29udGV4dFByb3ZpZGVyKFxuICAgICAgICAgIHtcbiAgICAgICAgICAgIHJlcXVlc3QsXG4gICAgICAgICAgICByZXBseSxcbiAgICAgICAgICAgIGhlYWRlcnM6IHJlcXVlc3QuaGVhZGVycyxcbiAgICAgICAgICAgIGNyZWF0ZVNTRSxcbiAgICAgICAgICAgIG5haXRlU3RvcmU6IE5haXRlLmNyZWF0ZVN0b3JlKCksXG4gICAgICAgICAgICAvLyBhdXRoXG4gICAgICAgICAgICB1c2VyOiByZXF1ZXN0LnVzZXIgPz8gbnVsbCxcbiAgICAgICAgICAgIHBhc3Nwb3J0OiB7XG4gICAgICAgICAgICAgIGxvZ2luOiByZXF1ZXN0LmxvZ2luLmJpbmQocmVxdWVzdCkgYXMgQXV0aENvbnRleHRbXCJwYXNzcG9ydFwiXVtcImxvZ2luXCJdLFxuICAgICAgICAgICAgICBsb2dvdXQ6IHJlcXVlc3QubG9nb3V0LmJpbmQocmVxdWVzdCkgYXMgQXV0aENvbnRleHRbXCJwYXNzcG9ydFwiXVtcImxvZ291dFwiXSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgfSxcbiAgICAgICAgICByZXF1ZXN0LFxuICAgICAgICAgIHJlcGx5LFxuICAgICAgICApLFxuICAgICAgKSksXG4gICAgfTtcbiAgICByZXR1cm4gY29udGV4dDtcbiAgfVxuXG4gIGFzeW5jIHN0YXJ0V2F0Y2hlcigpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCB3YXRjaFBhdGggPSBbcGF0aC5qb2luKHRoaXMuYXBpUm9vdFBhdGgsIFwic3JjXCIpXTtcblxuICAgIGNvbnN0IGNob2tpZGFyID0gKGF3YWl0IGltcG9ydChcImNob2tpZGFyXCIpKS5kZWZhdWx0O1xuICAgIHRoaXMud2F0Y2hlciA9IGNob2tpZGFyLndhdGNoKHdhdGNoUGF0aCwge1xuICAgICAgaWdub3JlZDogKHBhdGgsIHN0YXRzKSA9PlxuICAgICAgICAhIXN0YXRzPy5pc0ZpbGUoKSAmJiAhcGF0aC5lbmRzV2l0aChcIi50c1wiKSAmJiAhcGF0aC5lbmRzV2l0aChcIi5qc29uXCIpLFxuICAgICAgcGVyc2lzdGVudDogdHJ1ZSxcbiAgICAgIGlnbm9yZUluaXRpYWw6IHRydWUsXG4gICAgfSk7XG5cbiAgICB0aGlzLndhdGNoZXIub24oXCJhbGxcIiwgYXN5bmMgKGV2ZW50OiBzdHJpbmcsIGZpbGVQYXRoOiBzdHJpbmcpID0+IHtcbiAgICAgIGNvbnN0IGFic29sdXRlUGF0aCA9IGZpbGVQYXRoIGFzIEFic29sdXRlUGF0aDtcbiAgICAgIGFzc2VydChcbiAgICAgICAgYWJzb2x1dGVQYXRoLnN0YXJ0c1dpdGgodGhpcy5hcGlSb290UGF0aCksXG4gICAgICAgIFwiRmlsZSBwYXRoIGlzIG5vdCB3aXRoaW4gdGhlIEFQSSByb290IHBhdGhcIixcbiAgICAgICk7XG5cbiAgICAgIGlmIChldmVudCAhPT0gXCJjaGFuZ2VcIiAmJiBldmVudCAhPT0gXCJhZGRcIikge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIHRyeSB7XG4gICAgICAgIC8vIHNvbmFtdS5jb25maWcudHMg67OA6rK9IOyLnCDsnqzsi5zsnpFcbiAgICAgICAgY29uc3QgaXNDb25maWdUcyA9IGZpbGVQYXRoID09PSBwYXRoLmpvaW4odGhpcy5hcGlSb290UGF0aCwgXCJzcmNcIiwgXCJzb25hbXUuY29uZmlnLnRzXCIpO1xuXG4gICAgICAgIGlmIChpc0NvbmZpZ1RzKSB7XG4gICAgICAgICAgY29uc3QgcmVsYXRpdmVQYXRoID0gZmlsZVBhdGgucmVwbGFjZSh0aGlzLmFwaVJvb3RQYXRoLCBcImFwaVwiKTtcbiAgICAgICAgICBjb25zdCBjaGFsayA9IChhd2FpdCBpbXBvcnQoXCJjaGFsa1wiKSkuZGVmYXVsdDtcbiAgICAgICAgICBjb25zb2xlLmxvZyhcbiAgICAgICAgICAgIGNoYWxrLmJvbGQoYERldGVjdGVkKCR7ZXZlbnR9KTogJHtjaGFsay5ibHVlKHJlbGF0aXZlUGF0aCl9IC0gUmVzdGFydGluZy4uLmApLFxuICAgICAgICAgICk7XG4gICAgICAgICAgcHJvY2Vzcy5raWxsKHByb2Nlc3MucGlkLCBcIlNJR1VTUjJcIik7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgYXdhaXQgdGhpcy5oYW5kbGVGaWxlQ2hhbmdlKGV2ZW50LCBhYnNvbHV0ZVBhdGgpO1xuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICBjb25zb2xlLmVycm9yKGUpO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgLypcbiAgICAgQSBmdW5jdGlvbiB0aGF0IGF1dG9tYXRpY2FsbHkgaGFuZGxlcyBpbml0IGFuZCBkZXN0cm95IHdoZW4gdXNpbmcgU29uYW11IHZpYSBzY3JpcHRzLiAgICBcbiAgKi9cbiAgYXN5bmMgcnVuU2NyaXB0KGZuOiAoKSA9PiBQcm9taXNlPHZvaWQ+KSB7XG4gICAgYXdhaXQgdGhpcy5pbml0KHRydWUsIGZhbHNlLCB1bmRlZmluZWQsIGZhbHNlKTtcbiAgICB0cnkge1xuICAgICAgYXdhaXQgZm4oKTtcbiAgICB9IGZpbmFsbHkge1xuICAgICAgYXdhaXQgdGhpcy5kZXN0cm95KCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyByZWdpc3RlclBsdWdpbnMoc2VydmVyOiBGYXN0aWZ5SW5zdGFuY2UsIHBsdWdpbnM6IFNvbmFtdVNlcnZlck9wdGlvbnNbXCJwbHVnaW5zXCJdKSB7XG4gICAgaWYgKCFwbHVnaW5zKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgcGx1Z2luc01vZHVsZXMgPSB7XG4gICAgICBjb3JzOiBcIkBmYXN0aWZ5L2NvcnNcIixcbiAgICAgIGZvcm1ib2R5OiBcIkBmYXN0aWZ5L2Zvcm1ib2R5XCIsXG4gICAgICBtdWx0aXBhcnQ6IFwiQGZhc3RpZnkvbXVsdGlwYXJ0XCIsXG4gICAgICBxczogXCJmYXN0aWZ5LXFzXCIsXG4gICAgICBzc2U6IFwiZmFzdGlmeS1zc2UtdjJcIixcbiAgICAgIHN0YXRpYzogXCJAZmFzdGlmeS9zdGF0aWNcIixcbiAgICAgIHNlc3Npb246IFwiQGZhc3RpZnkvc2VjdXJlLXNlc3Npb25cIixcbiAgICB9IGFzIGNvbnN0O1xuXG4gICAgY29uc3QgcmVnaXN0ZXJQbHVnaW4gPSBhc3luYyA8SyBleHRlbmRzIGtleW9mIE5vbk51bGxhYmxlPHR5cGVvZiBwbHVnaW5zPj4oXG4gICAgICBrZXk6IEssXG4gICAgICBwbHVnaW5OYW1lOiBzdHJpbmcsXG4gICAgKSA9PiB7XG4gICAgICBjb25zdCBvcHRpb24gPSBwbHVnaW5zW2tleV07XG4gICAgICBpZiAoIW9wdGlvbikgcmV0dXJuO1xuXG4gICAgICBpZiAob3B0aW9uID09PSB0cnVlKSB7XG4gICAgICAgIHNlcnZlci5yZWdpc3RlcigoYXdhaXQgaW1wb3J0KHBsdWdpbk5hbWUpKS5kZWZhdWx0KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHNlcnZlci5yZWdpc3RlcigoYXdhaXQgaW1wb3J0KHBsdWdpbk5hbWUpKS5kZWZhdWx0LCBvcHRpb24pO1xuICAgICAgfVxuICAgIH07XG5cbiAgICBmb3IgKGNvbnN0IFtrZXksIHBsdWdpbk5hbWVdIG9mIE9iamVjdC5lbnRyaWVzKHBsdWdpbnNNb2R1bGVzKSkge1xuICAgICAgYXdhaXQgcmVnaXN0ZXJQbHVnaW4oa2V5IGFzIGtleW9mIHR5cGVvZiBwbHVnaW5zLCBwbHVnaW5OYW1lKTtcbiAgICB9XG5cbiAgICBpZiAocGx1Z2lucy5jdXN0b20pIHtcbiAgICAgIHBsdWdpbnMuY3VzdG9tKHNlcnZlcik7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyByZWdpc3RlckF1dGgoXG4gICAgc2VydmVyOiBGYXN0aWZ5SW5zdGFuY2UsXG4gICAgb3B0aW9uczogTm9uTnVsbGFibGU8U29uYW11U2VydmVyT3B0aW9uc1tcImF1dGhcIl0+LFxuICApIHtcbiAgICAvLyBhd2FpdCBpbXBvcnQoXCJmYXN0aWZ5XCIpO1xuICAgIGNvbnN0IGZhc3RpZnlQYXNzcG9ydCA9IChhd2FpdCBpbXBvcnQoXCJAZmFzdGlmeS9wYXNzcG9ydFwiKSkuZGVmYXVsdDtcbiAgICBzZXJ2ZXIucmVnaXN0ZXIoZmFzdGlmeVBhc3Nwb3J0LmluaXRpYWxpemUoKSk7XG4gICAgc2VydmVyLnJlZ2lzdGVyKGZhc3RpZnlQYXNzcG9ydC5zZWN1cmVTZXNzaW9uKCkpO1xuXG4gICAgaWYgKHR5cGVvZiBvcHRpb25zID09PSBcImJvb2xlYW5cIikge1xuICAgICAgZmFzdGlmeVBhc3Nwb3J0LnJlZ2lzdGVyVXNlclNlcmlhbGl6ZXIoYXN5bmMgKHVzZXIsIF9yZXF1ZXN0KSA9PiB1c2VyKTtcbiAgICAgIGZhc3RpZnlQYXNzcG9ydC5yZWdpc3RlclVzZXJEZXNlcmlhbGl6ZXIoYXN5bmMgKHNlcmlhbGl6ZWQsIF9yZXF1ZXN0KSA9PiBzZXJpYWxpemVkKTtcbiAgICB9IGVsc2Uge1xuICAgICAgZmFzdGlmeVBhc3Nwb3J0LnJlZ2lzdGVyVXNlclNlcmlhbGl6ZXIob3B0aW9ucy51c2VyU2VyaWFsaXplcik7XG4gICAgICBmYXN0aWZ5UGFzc3BvcnQucmVnaXN0ZXJVc2VyRGVzZXJpYWxpemVyKG9wdGlvbnMudXNlckRlc2VyaWFsaXplcik7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBpbml0aWFsaXplQ2FjaGUoY29uZmlnOiBDYWNoZUNvbmZpZyB8IHVuZGVmaW5lZCwgZm9yVGVzdGluZzogYm9vbGVhbikge1xuICAgIGNvbnN0IHsgc2V0Q2FjaGVNYW5hZ2VyUmVmIH0gPSBhd2FpdCBpbXBvcnQoXCIuLi9jYWNoZS9kZWNvcmF0b3JcIik7XG5cbiAgICAvLyDthYzsiqTtirgg7ZmY6rK97JeQ7IScIOuplOuqqOumrCDrk5zrnbzsnbTrsoQg7J6Q64+ZIOyCrOyaqVxuICAgIGlmIChmb3JUZXN0aW5nKSB7XG4gICAgICBjb25zdCB7IGNyZWF0ZVRlc3RDYWNoZU1hbmFnZXIgfSA9IGF3YWl0IGltcG9ydChcIi4uL2NhY2hlL2NhY2hlLW1hbmFnZXJcIik7XG4gICAgICB0aGlzLl9jYWNoZSA9IGNyZWF0ZVRlc3RDYWNoZU1hbmFnZXIoKTtcbiAgICAgIHNldENhY2hlTWFuYWdlclJlZih0aGlzLl9jYWNoZSk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8g7ISk7KCV7J20IOyXhuycvOuptCDsupDsi5wg67mE7Zmc7ISx7ZmUXG4gICAgaWYgKCFjb25maWcpIHtcbiAgICAgIHNldENhY2hlTWFuYWdlclJlZihudWxsKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyDshKTsoJXsl5Ag65Sw6528IENhY2hlTWFuYWdlciDsg53shLFcbiAgICBjb25zdCB7IGNyZWF0ZUNhY2hlTWFuYWdlciB9ID0gYXdhaXQgaW1wb3J0KFwiLi4vY2FjaGUvY2FjaGUtbWFuYWdlclwiKTtcbiAgICB0aGlzLl9jYWNoZSA9IGNyZWF0ZUNhY2hlTWFuYWdlcihjb25maWcpO1xuICAgIHNldENhY2hlTWFuYWdlclJlZih0aGlzLl9jYWNoZSk7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGluaXRpYWxpemVXb3JrZmxvd3Mob3B0aW9uczogU29uYW11VGFza09wdGlvbnMgfCB1bmRlZmluZWQpIHtcbiAgICBjb25zdCB7IFdvcmtmbG93TWFuYWdlciB9ID0gYXdhaXQgaW1wb3J0KFwiLi4vdGFza3Mvd29ya2Zsb3ctbWFuYWdlclwiKTtcbiAgICAvLyBOT1RFOiBAc29uYW11LWtpdC90YXNrcyDslYjsl5DshKAga25leCBjb25maWfrpbwg7IiY7KCV7ZWY6riwIOuVjOusuOyXkCBjb25uZWN0aW9u7J20IOyVhOuLjCBjb25maWcg7Ke466GcIOuztOuDheuLiOuLpC5cbiAgICB0aGlzLl93b3JrZmxvd3MgPSBuZXcgV29ya2Zsb3dNYW5hZ2VyKERCLmdldERCQ29uZmlnKFwid1wiKSk7XG4gICAgaWYgKCFvcHRpb25zKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgZW5hYmxlV29ya2VyID0gb3B0aW9ucy5lbmFibGVXb3JrZXIgPz8gaXNEYWVtb25TZXJ2ZXIoKTtcbiAgICBjb25zdCBkZWZhdWx0V29ya2VyT3B0aW9ucyA9IHtcbiAgICAgIGNvbmN1cnJlbmN5OiBvcy5jcHVzKCkubGVuZ3RoIC0gMSxcbiAgICAgIHVzZVB1YlN1YjogdHJ1ZSxcbiAgICAgIGxpc3RlbkRlbGF5OiA1MDAsXG4gICAgfTtcblxuICAgIGlmIChlbmFibGVXb3JrZXIpIHtcbiAgICAgIHRoaXMud29ya2Zsb3dzLnNldHVwV29ya2VyKHtcbiAgICAgICAgLi4uZGVmYXVsdFdvcmtlck9wdGlvbnMsXG4gICAgICAgIC4uLm9wdGlvbnMud29ya2VyT3B0aW9ucyxcbiAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgYm9vdChzZXJ2ZXI6IEZhc3RpZnlJbnN0YW5jZSwgb3B0aW9uczogU29uYW11U2VydmVyT3B0aW9ucykge1xuICAgIGNvbnN0IHBvcnQgPSBvcHRpb25zLmxpc3Rlbj8ucG9ydCA/PyAzMDAwO1xuICAgIGNvbnN0IGhvc3QgPSBvcHRpb25zLmxpc3Rlbj8uaG9zdCA/PyBcImxvY2FsaG9zdFwiO1xuXG4gICAgc2VydmVyLmFkZEhvb2soXCJvbkNsb3NlXCIsIGFzeW5jICgpID0+IHtcbiAgICAgIGF3YWl0IG9wdGlvbnMubGlmZWN5Y2xlPy5vblNodXRkb3duPy4oc2VydmVyKTtcbiAgICAgIGF3YWl0IHRoaXMud29ya2Zsb3dzLmRlc3Ryb3koKTtcbiAgICAgIGF3YWl0IHRoaXMuZGVzdHJveSgpO1xuICAgIH0pO1xuXG4gICAgY29uc3Qgc2h1dGRvd24gPSBhc3luYyAoKSA9PiB7XG4gICAgICB0cnkge1xuICAgICAgICBhd2FpdCBzZXJ2ZXIuY2xvc2UoKTtcbiAgICAgICAgcHJvY2Vzcy5leGl0KDApO1xuICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoXCJFcnJvciBkdXJpbmcgc2h1dGRvd246XCIsIGVycik7XG4gICAgICAgIHByb2Nlc3MuZXhpdCgxKTtcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgcHJvY2Vzcy5vbihcIlNJR0lOVFwiLCBzaHV0ZG93bik7XG4gICAgcHJvY2Vzcy5vbihcIlNJR1RFUk1cIiwgc2h1dGRvd24pO1xuXG4gICAgaWYgKG9wdGlvbnMubGlmZWN5Y2xlPy5vbkVycm9yKSB7XG4gICAgICBzZXJ2ZXIuc2V0RXJyb3JIYW5kbGVyKG9wdGlvbnMubGlmZWN5Y2xlPy5vbkVycm9yKTtcbiAgICB9XG5cbiAgICBzZXJ2ZXJcbiAgICAgIC5saXN0ZW4oeyBwb3J0LCBob3N0IH0pXG4gICAgICAudGhlbihhc3luYyAoKSA9PiB7XG4gICAgICAgIGF3YWl0IHRoaXMud29ya2Zsb3dzLnN0YXJ0V29ya2VyKCk7XG4gICAgICAgIGF3YWl0IG9wdGlvbnMubGlmZWN5Y2xlPy5vblN0YXJ0Py4oc2VydmVyKTtcbiAgICAgIH0pXG4gICAgICAuY2F0Y2goYXN5bmMgKGVycikgPT4ge1xuICAgICAgICBjb25zdCBjaGFsayA9IChhd2FpdCBpbXBvcnQoXCJjaGFsa1wiKSkuZGVmYXVsdDtcbiAgICAgICAgY29uc29sZS5lcnJvcihjaGFsay5yZWQoXCJGYWlsZWQgdG8gc3RhcnQgc2VydmVyOlwiLCBlcnIpKTtcbiAgICAgICAgYXdhaXQgc2h1dGRvd24oKTtcbiAgICAgIH0pO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBoYW5kbGVGaWxlQ2hhbmdlKGV2ZW50OiBzdHJpbmcsIGZpbGVQYXRoOiBBYnNvbHV0ZVBhdGgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAvLyDssqsg67KI7Ke4IO2MjOydvOydtOuptCBITVIg7Iuc7J6RIOyLnOqwhCDquLDroZ1cbiAgICBpZiAodGhpcy5wZW5kaW5nRmlsZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICB0aGlzLmhtclN0YXJ0VGltZSA9IERhdGUubm93KCk7XG4gICAgfVxuICAgIHRoaXMucGVuZGluZ0ZpbGVzLnB1c2goZmlsZVBhdGgpO1xuXG4gICAgY29uc3QgcmVsYXRpdmVQYXRoID0gcGF0aC5yZWxhdGl2ZSh0aGlzLmFwaVJvb3RQYXRoLCBmaWxlUGF0aCk7XG4gICAgY29uc3QgY2hhbGsgPSAoYXdhaXQgaW1wb3J0KFwiY2hhbGtcIikpLmRlZmF1bHQ7XG4gICAgY29uc29sZS5sb2coY2hhbGsuYm9sZChgRGV0ZWN0ZWQoJHtldmVudH0pOiAke2NoYWxrLmJsdWUocmVsYXRpdmVQYXRoKX1gKSk7XG5cbiAgICBhd2FpdCB0aGlzLnN5bmNlci5zeW5jRnJvbVdhdGNoZXIoZXZlbnQsIGZpbGVQYXRoKTtcblxuICAgIC8vIOyymOumrCDsmYTro4zrkJwg7YyM7J287J2EIOuMgOq4sCDrqqnroZ3sl5DshJwg7KCc6rGwXG4gICAgdGhpcy5wZW5kaW5nRmlsZXMgPSB0aGlzLnBlbmRpbmdGaWxlcy5zbGljZSgxKTtcblxuICAgIC8vIOuqqOuToCDtjIzsnbwg7LKY66as6rCAIOyZhOujjOuQmOuptCDstZzsooUg66mU7Iuc7KeAIOy2nOugpVxuICAgIGlmICh0aGlzLnBlbmRpbmdGaWxlcy5sZW5ndGggPT09IDApIHtcbiAgICAgIGF3YWl0IHRoaXMuZmluaXNoSE1SKCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBmaW5pc2hITVIoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgYXdhaXQgdGhpcy5zeW5jZXIucmVuZXdDaGVja3N1bXMoKTtcblxuICAgIGNvbnN0IGVuZFRpbWUgPSBEYXRlLm5vdygpO1xuICAgIGNvbnN0IHRvdGFsVGltZSA9IGVuZFRpbWUgLSB0aGlzLmhtclN0YXJ0VGltZTtcbiAgICBjb25zdCBbY2hhbGssIHsgY2VudGVyVGV4dCB9XSA9IGF3YWl0IFByb21pc2UuYWxsKFtcbiAgICAgIChhd2FpdCBpbXBvcnQoXCJjaGFsa1wiKSkuZGVmYXVsdCxcbiAgICAgIGltcG9ydChcIi4uL3V0aWxzL2NvbnNvbGUtdXRpbFwiKSxcbiAgICBdKTtcbiAgICBjb25zdCBtc2cgPSBgSE1SIERvbmUhICR7Y2hhbGsuYm9sZC53aGl0ZShgJHt0b3RhbFRpbWV9bXNgKX1gO1xuXG4gICAgY29uc29sZS5sb2coY2hhbGsuYmxhY2suYmdHcmVlbihjZW50ZXJUZXh0KG1zZykpKTtcbiAgfVxuXG4gIGFzeW5jIGRlc3Ryb3koKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgeyBCYXNlTW9kZWwgfSA9IGF3YWl0IGltcG9ydChcIi4uL2RhdGFiYXNlL2Jhc2UtbW9kZWxcIik7XG4gICAgLy8g66i87KCAIOyymOumrO2VtOyVvO2VqC5cbiAgICBhd2FpdCBCYXNlTW9kZWwuZGVzdHJveSgpO1xuICAgIGF3YWl0IFByb21pc2UuYWxsU2V0dGxlZChbXG4gICAgICB0aGlzLl93b3JrZmxvd3M/LmRlc3Ryb3koKSA/PyBQcm9taXNlLnJlc29sdmUoKSxcbiAgICAgIHRoaXMuX2NhY2hlPy5kaXNjb25uZWN0KCkgPz8gUHJvbWlzZS5yZXNvbHZlKCksXG4gICAgICB0aGlzLndhdGNoZXI/LmNsb3NlKCkgPz8gUHJvbWlzZS5yZXNvbHZlKCksXG4gICAgICBsb2d0YXBlRGlzcG9zZSgpLFxuICAgIF0pO1xuICB9XG59XG5cbmV4cG9ydCBjb25zdCBTb25hbXUgPSBuZXcgU29uYW11Q2xhc3MoKTtcbiJdLCJuYW1lcyI6WyJkaXNwb3NlIiwibG9ndGFwZURpc3Bvc2UiLCJhc3NlcnQiLCJBc3luY0xvY2FsU3RvcmFnZSIsImZzIiwib3MiLCJwYXRoIiwiY3JlYXRlTW9ja1NTRUZhY3RvcnkiLCJEQiIsImlzRGFlbW9uU2VydmVyIiwiTmFpdGUiLCJnZXRTZWNyZXRzIiwiU29uYW11Q2xhc3MiLCJpc0luaXRpYWxpemVkIiwiYXN5bmNMb2NhbFN0b3JhZ2UiLCJ1cGxvYWRTdG9yYWdlIiwiZ2V0Q29udGV4dCIsInN0b3JlIiwiZ2V0U3RvcmUiLCJjb250ZXh0IiwicHJvY2VzcyIsImVudiIsIk5PREVfRU5WIiwicmVxdWVzdCIsInJlcGx5IiwiaGVhZGVycyIsImNyZWF0ZVNTRSIsInNjaGVtYSIsIm5haXRlU3RvcmUiLCJNYXAiLCJFcnJvciIsImdldFVwbG9hZENvbnRleHQiLCJ1cGxvYWRDb250ZXh0IiwiX2FwaVJvb3RQYXRoIiwiYXBpUm9vdFBhdGgiLCJhcHBSb290UGF0aCIsInNwbGl0Iiwic2VwIiwic2xpY2UiLCJqb2luIiwiX2RiQ29uZmlnIiwiZGJDb25maWciLCJfc3luY2VyIiwic3luY2VyIiwiX2NvbmZpZyIsImNvbmZpZyIsInNlY3JldHMiLCJfc3RvcmFnZSIsInN0b3JhZ2UiLCJfY2FjaGUiLCJjYWNoZSIsIl93b3JrZmxvd3MiLCJ3b3JrZmxvd3MiLCJ3YXRjaGVyIiwicGVuZGluZ0ZpbGVzIiwiaG1yU3RhcnRUaW1lIiwic2VydmVyIiwiaW5pdEZvclRlc3RpbmciLCJpbml0IiwidW5kZWZpbmVkIiwiZG9TaWxlbnQiLCJlbmFibGVTeW5jIiwiZm9yVGVzdGluZyIsImNoYWxrIiwiZGVmYXVsdCIsImNvbnNvbGUiLCJ0aW1lIiwiY3lhbiIsImZpbmRBcGlSb290UGF0aCIsImxvYWRDb25maWciLCJkYXRhYmFzZSIsImRlZmF1bHRPcHRpb25zIiwiY2xpZW50IiwiY29uZmlndXJlTG9nVGFwZSIsImxvZ2dpbmciLCJnZW5lcmF0ZURCQ29uZmlnIiwibG9nIiwiZ3JlZW4iLCJFbnRpdHlNYW5hZ2VyIiwiYXV0b2xvYWQiLCJpbml0aWFsaXplQ2FjaGUiLCJpbml0aWFsaXplV29ya2Zsb3dzIiwidGFza3MiLCJTeW5jZXIiLCJhdXRvbG9hZFR5cGVzIiwiYXV0b2xvYWRNb2RlbHMiLCJhdXRvbG9hZEFwaXMiLCJhdXRvbG9hZFdvcmtmbG93cyIsIlRlbXBsYXRlTWFuYWdlciIsImF1dG9sb2FkU1NSUm91dGVzIiwiaXNMb2NhbCIsImlzVGVzdCIsInNldHVwQmlvbWUiLCJpc0hvdFJlbG9hZFNlcnZlciIsInN5bmMiLCJzdGFydFdhdGNoZXIiLCJ0aW1lRW5kIiwiY3JlYXRlU2VydmVyIiwiaW5pdE9wdGlvbnMiLCJvcHRpb25zIiwiZmFzdGlmeSIsImdldExvZ1RhcGVGYXN0aWZ5TG9nZ2VyIiwibG9nZ2VyIiwiY2F0ZWdvcnkiLCJmYXN0aWZ5Q2F0ZWdvcnkiLCJTdG9yYWdlTWFuYWdlciIsInBsdWdpbnMiLCJyZWdpc3RlclBsdWdpbnMiLCJhdXRoIiwic2Vzc2lvbiIsInJlZ2lzdGVyQXV0aCIsIndpdGhGYXN0aWZ5IiwiYXBpQ29uZmlnIiwiYm9vdCIsInRpbWV6b25lIiwiYXBpIiwiZm9ybWF0SW5UaW1lWm9uZSIsIklTT19EQVRFX1JFR0VYIiwiREFURV9GT1JNQVQiLCJzZXRSZXBseVNlcmlhbGl6ZXIiLCJwYXlsb2FkIiwiSlNPTiIsInN0cmluZ2lmeSIsIl9rZXkiLCJ2YWx1ZSIsInRlc3QiLCJEYXRlIiwiZ2V0Iiwicm91dGUiLCJwcmVmaXgiLCJfcmVxdWVzdCIsIl9yZXBseSIsImFwaXMiLCJzb25hbXVVSUFwaVBsdWdpbiIsInJlZ2lzdGVyIiwid2ViUGF0aCIsImhhc1dlYiIsImV4aXN0c1N5bmMiLCJzZXR1cFZpdGVEZXZTZXJ2ZXIiLCJtb2RlbHMiLCJtb2RlbE5hbWUiLCJtZXRob2QiLCJodHRwTWV0aG9kIiwidXJsIiwiaGFuZGxlciIsImNyZWF0ZUFwaUhhbmRsZXIiLCJzZXR1cFN0YXRpY1dlYlNlcnZlciIsInZpdGVTZXJ2ZXIiLCJ2aXRlIiwicm9vdCIsIm1pZGRsZXdhcmVNb2RlIiwiaG1yIiwiYXBwVHlwZSIsInVzZSIsInJlcSIsInJlcyIsIm5leHQiLCJzdGFydHNXaXRoIiwibWlkZGxld2FyZXMiLCJzZXROb3RGb3VuZEhhbmRsZXIiLCJtYXRjaFNTUlJvdXRlIiwibWF0Y2giLCJyZW5kZXJTU1IiLCJodG1sIiwicGFyYW1zIiwidHlwZSIsInNlbmQiLCJlIiwiZXJyb3IiLCJ0ZW1wbGF0ZSIsInJlYWRGaWxlIiwidHJhbnNmb3JtSW5kZXhIdG1sIiwic3NyRml4U3RhY2t0cmFjZSIsInN0YXR1cyIsIm1lc3NhZ2UiLCJhZGRIb29rIiwiY2xvc2UiLCJfd2ViUGF0aCIsIndlYkRpc3RQYXRoIiwic3NyUGF0aCIsIndhcm4iLCJzc3JFbnRyeVBhdGgiLCJzc3JBdmFpbGFibGUiLCJzc3JSb3V0ZXNQYXRoIiwicmVxdWVzdGVkRmlsZSIsImZpbGVuYW1lIiwiYXNzZXRzRGlyIiwiZXh0IiwicG9wIiwiZmlsZXMiLCJyZWFkZGlyU3luYyIsImN1cnJlbnRGaWxlIiwiZmluZCIsImYiLCJlbmRzV2l0aCIsImZpbGVQYXRoIiwiY29udGVudCIsInJlYWRGaWxlU3luYyIsImhlYWRlciIsImluY2x1ZGVzIiwiY29kZSIsIlN0cmluZyIsInRpbWVzdGFtcCIsInRvSVNPU3RyaW5nIiwiaW5kZXhQYXRoIiwiZ3VhcmRzIiwiZXZlcnkiLCJndWFyZCIsImd1YXJkSGFuZGxlciIsImdldFpvZE9iamVjdEZyb21BcGkiLCJSZXFUeXBlIiwidHlwZXMiLCJ3aGljaCIsInJlcUJvZHkiLCJmYXN0aWZ5Q2FzdGVyIiwicGFyc2UiLCJab2RFcnJvciIsImh1bWFuaXplWm9kRXJyb3IiLCJtZXNzYWdlcyIsIm1hcCIsImlzc3VlIiwiQmFkUmVxdWVzdEV4Y2VwdGlvbiIsInpvZEVycm9yIiwiY29udGVudFR5cGUiLCJjcmVhdGVDb250ZXh0IiwiQXBpUGFyYW1UeXBlIiwiYXJncyIsInBhcmFtZXRlcnMiLCJwYXJhbSIsImlzQ29udGV4dCIsIm5hbWUiLCJpbnZva2VNb2RlbE1ldGhvZCIsImludm9rZUFwaUZvclNTUiIsInBhcmFtc0luZGV4IiwibW9kZWwiLCJydW4iLCJyZXN1bHQiLCJtZXRob2ROYW1lIiwiYXBwbHkiLCJjcmVhdGVTU0VGYWN0b3J5IiwiX2V2ZW50cyIsInNvY2tldCIsImJpbmQiLCJQcm9taXNlIiwicmVzb2x2ZSIsImNvbnRleHRQcm92aWRlciIsImNyZWF0ZVN0b3JlIiwidXNlciIsInBhc3Nwb3J0IiwibG9naW4iLCJsb2dvdXQiLCJ3YXRjaFBhdGgiLCJjaG9raWRhciIsIndhdGNoIiwiaWdub3JlZCIsInN0YXRzIiwiaXNGaWxlIiwicGVyc2lzdGVudCIsImlnbm9yZUluaXRpYWwiLCJvbiIsImV2ZW50IiwiYWJzb2x1dGVQYXRoIiwiaXNDb25maWdUcyIsInJlbGF0aXZlUGF0aCIsInJlcGxhY2UiLCJib2xkIiwiYmx1ZSIsImtpbGwiLCJwaWQiLCJoYW5kbGVGaWxlQ2hhbmdlIiwicnVuU2NyaXB0IiwiZm4iLCJkZXN0cm95IiwicGx1Z2luc01vZHVsZXMiLCJjb3JzIiwiZm9ybWJvZHkiLCJtdWx0aXBhcnQiLCJxcyIsInNzZSIsInN0YXRpYyIsInJlZ2lzdGVyUGx1Z2luIiwia2V5IiwicGx1Z2luTmFtZSIsIm9wdGlvbiIsIk9iamVjdCIsImVudHJpZXMiLCJjdXN0b20iLCJmYXN0aWZ5UGFzc3BvcnQiLCJpbml0aWFsaXplIiwic2VjdXJlU2Vzc2lvbiIsInJlZ2lzdGVyVXNlclNlcmlhbGl6ZXIiLCJyZWdpc3RlclVzZXJEZXNlcmlhbGl6ZXIiLCJzZXJpYWxpemVkIiwidXNlclNlcmlhbGl6ZXIiLCJ1c2VyRGVzZXJpYWxpemVyIiwic2V0Q2FjaGVNYW5hZ2VyUmVmIiwiY3JlYXRlVGVzdENhY2hlTWFuYWdlciIsImNyZWF0ZUNhY2hlTWFuYWdlciIsIldvcmtmbG93TWFuYWdlciIsImdldERCQ29uZmlnIiwiZW5hYmxlV29ya2VyIiwiZGVmYXVsdFdvcmtlck9wdGlvbnMiLCJjb25jdXJyZW5jeSIsImNwdXMiLCJsZW5ndGgiLCJ1c2VQdWJTdWIiLCJsaXN0ZW5EZWxheSIsInNldHVwV29ya2VyIiwid29ya2VyT3B0aW9ucyIsInBvcnQiLCJsaXN0ZW4iLCJob3N0IiwibGlmZWN5Y2xlIiwib25TaHV0ZG93biIsInNodXRkb3duIiwiZXhpdCIsImVyciIsIm9uRXJyb3IiLCJzZXRFcnJvckhhbmRsZXIiLCJ0aGVuIiwic3RhcnRXb3JrZXIiLCJvblN0YXJ0IiwiY2F0Y2giLCJyZWQiLCJub3ciLCJwdXNoIiwicmVsYXRpdmUiLCJzeW5jRnJvbVdhdGNoZXIiLCJmaW5pc2hITVIiLCJyZW5ld0NoZWNrc3VtcyIsImVuZFRpbWUiLCJ0b3RhbFRpbWUiLCJjZW50ZXJUZXh0IiwiYWxsIiwibXNnIiwid2hpdGUiLCJibGFjayIsImJnR3JlZW4iLCJCYXNlTW9kZWwiLCJhbGxTZXR0bGVkIiwiZGlzY29ubmVjdCIsIlNvbmFtdSJdLCJtYXBwaW5ncyI6IkFBQUEsU0FBU0EsV0FBV0MsY0FBYyxRQUFRLG1CQUFtQjtBQUM3RCxPQUFPQyxZQUFZLFNBQVM7QUFDNUIsU0FBU0MsaUJBQWlCLFFBQVEsY0FBYztBQUdoRCxPQUFPQyxRQUFRLEtBQUs7QUFFcEIsT0FBT0MsUUFBUSxLQUFLO0FBQ3BCLE9BQU9DLFVBQVUsT0FBTztBQUV4QixTQUFTQyxvQkFBb0IsRUFBRUMsRUFBRSxFQUFFQyxjQUFjLFFBQVEsY0FBSztBQUc5RCxTQUFTQyxLQUFLLFFBQVEsb0JBQWlCO0FBU3ZDLFNBQVNDLFVBQVUsUUFBNEIsY0FBVztBQUUxRCxNQUFNQztJQUNHQyxnQkFBeUIsTUFBTTtJQUMvQkMsb0JBRUYsSUFBSVgsb0JBQW9CO0lBRXRCWSxnQkFFRixJQUFJWixvQkFBb0I7SUFFdEJhLGFBQXNCO1FBQzNCLE1BQU1DLFFBQVEsSUFBSSxDQUFDSCxpQkFBaUIsQ0FBQ0ksUUFBUTtRQUM3QyxJQUFJRCxPQUFPRSxTQUFTO1lBQ2xCLE9BQU9GLE1BQU1FLE9BQU87UUFDdEI7UUFFQSxJQUFJQyxRQUFRQyxHQUFHLENBQUNDLFFBQVEsS0FBSyxRQUFRO1lBQ25DLHNDQUFzQztZQUN0QyxPQUFPO2dCQUNMQyxTQUFTO2dCQUNUQyxPQUFPO2dCQUNQQyxTQUFTLENBQUM7Z0JBQ1ZDLFdBQVcsQ0FBQ0MsU0FBc0JwQixxQkFBcUJvQjtnQkFDdkQsa0ZBQWtGO2dCQUNsRkMsWUFBWSxJQUFJQztZQUNsQjtRQUNGLE9BQU87WUFDTCxNQUFNLElBQUlD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