@cartanova/qgrid-cli 2.10.9 → 2.11.0

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 (318) hide show
  1. package/bundle/dist/_virtual/_rolldown/runtime.js +1 -10
  2. package/bundle/dist/application/monit/log-buffer.js +12 -6
  3. package/bundle/dist/application/monit/monit.frame.js +11 -3
  4. package/bundle/dist/application/monit/monit.types.js +1 -1
  5. package/bundle/dist/application/qgrid/conv-routing.js +9 -6
  6. package/bundle/dist/application/qgrid/expired-token-reminder.js +2 -2
  7. package/bundle/dist/application/qgrid/oauth.js +31 -4
  8. package/bundle/dist/application/qgrid/qgrid-image-generation.js +1 -1
  9. package/bundle/dist/application/qgrid/qgrid-response-format.js +22 -20
  10. package/bundle/dist/application/qgrid/qgrid-run-lifecycle.js +43 -34
  11. package/bundle/dist/application/qgrid/qgrid.dispatcher.js +128 -93
  12. package/bundle/dist/application/qgrid/qgrid.frame.js +930 -49
  13. package/bundle/dist/application/qgrid/qgrid.types.js +212 -5
  14. package/bundle/dist/application/qgrid/schema-prompt.js +75 -48
  15. package/bundle/dist/application/qgrid/slack-user-map.js +1 -1
  16. package/bundle/dist/application/qgrid/token-death.js +1 -1
  17. package/bundle/dist/application/qgrid/token-subscriber.js +83 -30
  18. package/bundle/dist/application/qgrid/token-trigger-setup.js +1 -1
  19. package/bundle/dist/application/qgrid/token-window-keepalive.js +8 -6
  20. package/bundle/dist/application/qgrid/tool-emulation-schema.js +13 -13
  21. package/bundle/dist/application/qgrid/tool-emulation.js +19 -15
  22. package/bundle/dist/application/request-log/json-schema-type-text.js +29 -12
  23. package/bundle/dist/application/request-log/request-log.model.js +83 -69
  24. package/bundle/dist/application/request-log/request-log.types.js +8 -2
  25. package/bundle/dist/application/request-log/zod-code-format.js +1 -1
  26. package/bundle/dist/application/request-log-step/request-log-step.model.js +1 -1
  27. package/bundle/dist/application/request-log-step/request-log-step.types.js +1 -1
  28. package/bundle/dist/application/setting/setting.constant.js +1 -1
  29. package/bundle/dist/application/setting/setting.model.js +2 -2
  30. package/bundle/dist/application/setting/setting.store.js +2 -2
  31. package/bundle/dist/application/setting/setting.types.js +1 -1
  32. package/bundle/dist/application/sonamu.generated.js +40 -16
  33. package/bundle/dist/application/sonamu.generated.sso.js +2 -1
  34. package/bundle/dist/application/token/token.model.js +26 -9
  35. package/bundle/dist/application/token/token.types.js +20 -3
  36. package/bundle/dist/i18n/en.js +15 -1
  37. package/bundle/dist/i18n/ko.js +15 -1
  38. package/bundle/dist/i18n/sd.generated.js +2 -1
  39. package/bundle/dist/migrations/20260807133553_manual__backfill_request_log_cost.js +8 -6
  40. package/bundle/dist/migrations/20261018215031_alter_request_logs_add1_alter1.js +15 -0
  41. package/bundle/dist/server-bootstrap.js +4 -2
  42. package/bundle/dist/server-error-handler.js +1 -1
  43. package/bundle/dist/sonamu.config.js +37 -8
  44. package/bundle/dist/startup-migrations.js +17 -7
  45. package/bundle/dist/testing/global.js +1 -1
  46. package/bundle/dist/testing/schema-bench.js +0 -0
  47. package/bundle/dist/testing/test-database-name.js +1 -1
  48. package/bundle/dist/utils/providers/anthropic/anthropic-constants.js +1 -1
  49. package/bundle/dist/utils/providers/anthropic/anthropic-dispatcher.js +11 -5
  50. package/bundle/dist/utils/providers/anthropic/anthropic-quota.js +4 -4
  51. package/bundle/dist/utils/providers/anthropic/anthropic-thinking.js +1 -1
  52. package/bundle/dist/utils/providers/anthropic/claude-session.js +20 -19
  53. package/bundle/dist/utils/providers/anthropic/fence-strip.js +1 -1
  54. package/bundle/dist/utils/providers/anthropic/stream-json-adapter.js +49 -23
  55. package/bundle/dist/utils/providers/common/credentials.js +5 -1
  56. package/bundle/dist/utils/providers/common/effort.js +3 -3
  57. package/bundle/dist/utils/providers/common/model-cost.js +69 -14
  58. package/bundle/dist/utils/providers/common/provider-types.js +29 -1
  59. package/bundle/dist/utils/providers/common/schema-validation.js +78 -40
  60. package/bundle/dist/utils/providers/common/smooth-weighted-round-robin.js +1 -1
  61. package/bundle/dist/utils/providers/common/strictifier.js +62 -43
  62. package/bundle/dist/utils/providers/common/thinking.js +3 -2
  63. package/bundle/dist/utils/providers/common/ttft.js +1 -1
  64. package/bundle/dist/utils/providers/grok/grok-backend-protocol.js +427 -0
  65. package/bundle/dist/utils/providers/grok/grok-constants.js +55 -0
  66. package/bundle/dist/utils/providers/grok/grok-direct-client.js +196 -0
  67. package/bundle/dist/utils/providers/grok/grok-dispatcher.js +1313 -0
  68. package/bundle/dist/utils/providers/grok/grok-headers.js +118 -0
  69. package/bundle/dist/utils/providers/grok/grok-media-client.js +420 -0
  70. package/bundle/dist/utils/providers/grok/grok-models.js +114 -0
  71. package/bundle/dist/utils/providers/grok/grok-oauth.js +455 -0
  72. package/bundle/dist/utils/providers/grok/grok-quota.js +119 -0
  73. package/bundle/dist/utils/providers/grok/grok-refresh.js +192 -0
  74. package/bundle/dist/utils/providers/grok/grok-types.js +186 -0
  75. package/bundle/dist/utils/providers/grok/grok-voice-client.js +199 -0
  76. package/bundle/dist/utils/providers/grok/index.js +11 -0
  77. package/bundle/dist/utils/providers/openai/openai-backend-protocol.js +111 -83
  78. package/bundle/dist/utils/providers/openai/openai-callback-relay.js +3 -2
  79. package/bundle/dist/utils/providers/openai/openai-constants.js +1 -1
  80. package/bundle/dist/utils/providers/openai/openai-direct-client.js +23 -7
  81. package/bundle/dist/utils/providers/openai/openai-dispatcher.js +143 -106
  82. package/bundle/dist/utils/providers/openai/openai-image-generation.js +48 -33
  83. package/bundle/dist/utils/providers/openai/openai-oauth.js +28 -13
  84. package/bundle/dist/utils/providers/openai/openai-quota.js +38 -27
  85. package/bundle/dist/utils/providers/openai/openai-refresh.js +17 -9
  86. package/bundle/dist/utils/providers/openai/openai-sse.js +1 -1
  87. package/bundle/dist/utils/providers/openai/openai-transport-config.js +1 -1
  88. package/bundle/dist/utils/quiet-hours.js +1 -1
  89. package/bundle/dist/utils/slack-notify.js +14 -8
  90. package/bundle/dist/utils/subset-loaders.js +4 -5
  91. package/bundle/src/application/monit/log-buffer.ts +23 -9
  92. package/bundle/src/application/monit/monit.frame.ts +22 -5
  93. package/bundle/src/application/monit/monit.types.ts +6 -0
  94. package/bundle/src/application/qgrid/conv-routing.test.ts +76 -4
  95. package/bundle/src/application/qgrid/conv-routing.ts +35 -9
  96. package/bundle/src/application/qgrid/expired-token-reminder.ts +9 -1
  97. package/bundle/src/application/qgrid/oauth.ts +51 -15
  98. package/bundle/src/application/qgrid/qgrid-image-generation.ts +9 -0
  99. package/bundle/src/application/qgrid/qgrid-response-format.ts +50 -25
  100. package/bundle/src/application/qgrid/qgrid-run-lifecycle.test.ts +33 -0
  101. package/bundle/src/application/qgrid/qgrid-run-lifecycle.ts +87 -40
  102. package/bundle/src/application/qgrid/qgrid.dispatcher.test.ts +97 -0
  103. package/bundle/src/application/qgrid/qgrid.dispatcher.ts +274 -126
  104. package/bundle/src/application/qgrid/qgrid.frame.test.ts +1013 -3
  105. package/bundle/src/application/qgrid/qgrid.frame.ts +1415 -60
  106. package/bundle/src/application/qgrid/qgrid.types.ts +335 -0
  107. package/bundle/src/application/qgrid/schema-prompt.ts +105 -41
  108. package/bundle/src/application/qgrid/slack-user-map.ts +5 -0
  109. package/bundle/src/application/qgrid/token-death.ts +4 -0
  110. package/bundle/src/application/qgrid/token-subscriber.test.ts +21 -19
  111. package/bundle/src/application/qgrid/token-subscriber.ts +186 -53
  112. package/bundle/src/application/qgrid/token-trigger-setup.ts +2 -0
  113. package/bundle/src/application/qgrid/token-window-keepalive.ts +49 -6
  114. package/bundle/src/application/qgrid/tool-emulation-schema.ts +33 -29
  115. package/bundle/src/application/qgrid/tool-emulation.ts +52 -27
  116. package/bundle/src/application/request-log/json-schema-type-text.test.ts +5 -5
  117. package/bundle/src/application/request-log/json-schema-type-text.ts +81 -26
  118. package/bundle/src/application/request-log/request-log.entity.json +8 -0
  119. package/bundle/src/application/request-log/request-log.model.test.ts +111 -4
  120. package/bundle/src/application/request-log/request-log.model.ts +279 -145
  121. package/bundle/src/application/request-log/request-log.types.ts +17 -0
  122. package/bundle/src/application/request-log/zod-code-format.ts +11 -0
  123. package/bundle/src/application/request-log-step/request-log-step.model.ts +1 -0
  124. package/bundle/src/application/request-log-step/request-log-step.types.ts +2 -0
  125. package/bundle/src/application/setting/setting.constant.ts +9 -0
  126. package/bundle/src/application/setting/setting.model.ts +12 -2
  127. package/bundle/src/application/setting/setting.store.ts +5 -1
  128. package/bundle/src/application/setting/setting.types.ts +8 -0
  129. package/bundle/src/application/sonamu.generated.http +135 -0
  130. package/bundle/src/application/sonamu.generated.sso.ts +3 -0
  131. package/bundle/src/application/sonamu.generated.ts +29 -0
  132. package/bundle/src/application/token/token.identity.test.ts +20 -0
  133. package/bundle/src/application/token/token.model.ts +66 -7
  134. package/bundle/src/application/token/token.types.ts +24 -1
  135. package/bundle/src/i18n/en.ts +19 -0
  136. package/bundle/src/i18n/ko.ts +21 -0
  137. package/bundle/src/i18n/sd.generated.ts +24 -2
  138. package/bundle/src/migrations/20260807133553_manual__backfill_request_log_cost.ts +16 -8
  139. package/bundle/src/migrations/20261018215031_alter_request_logs_add1_alter1.ts +15 -0
  140. package/bundle/src/server-bootstrap.ts +4 -2
  141. package/bundle/src/server-error-handler.ts +1 -0
  142. package/bundle/src/sonamu.config.ts +69 -7
  143. package/bundle/src/startup-migrations.ts +27 -9
  144. package/bundle/src/testing/global.ts +20 -0
  145. package/bundle/src/testing/schema-bench.ts +105 -30
  146. package/bundle/src/testing/test-database-name.ts +2 -0
  147. package/bundle/src/utils/providers/anthropic/anthropic-constants.ts +8 -0
  148. package/bundle/src/utils/providers/anthropic/anthropic-dispatcher.ts +41 -6
  149. package/bundle/src/utils/providers/anthropic/anthropic-quota.ts +7 -3
  150. package/bundle/src/utils/providers/anthropic/anthropic-thinking.ts +6 -0
  151. package/bundle/src/utils/providers/anthropic/claude-session.ts +58 -24
  152. package/bundle/src/utils/providers/anthropic/fence-strip.ts +11 -0
  153. package/bundle/src/utils/providers/anthropic/stream-json-adapter.ts +110 -45
  154. package/bundle/src/utils/providers/common/credentials.ts +8 -0
  155. package/bundle/src/utils/providers/common/effort.ts +9 -2
  156. package/bundle/src/utils/providers/common/model-cost.test.ts +48 -1
  157. package/bundle/src/utils/providers/common/model-cost.ts +259 -158
  158. package/bundle/src/utils/providers/common/provider-dispatcher.ts +98 -2
  159. package/bundle/src/utils/providers/common/provider-types.ts +46 -3
  160. package/bundle/src/utils/providers/common/schema-validation.test.ts +5 -1
  161. package/bundle/src/utils/providers/common/schema-validation.ts +124 -56
  162. package/bundle/src/utils/providers/common/smooth-weighted-round-robin.ts +4 -0
  163. package/bundle/src/utils/providers/common/strictifier.ts +185 -59
  164. package/bundle/src/utils/providers/common/thinking.ts +2 -2
  165. package/bundle/src/utils/providers/common/ttft.ts +4 -2
  166. package/bundle/src/utils/providers/grok/__fixtures__/golden-responses-1.0.60.json +164 -0
  167. package/bundle/src/utils/providers/grok/grok-backend-protocol.test.ts +325 -0
  168. package/bundle/src/utils/providers/grok/grok-backend-protocol.ts +721 -0
  169. package/bundle/src/utils/providers/grok/grok-constants.ts +105 -0
  170. package/bundle/src/utils/providers/grok/grok-direct-client.test.ts +179 -0
  171. package/bundle/src/utils/providers/grok/grok-direct-client.ts +313 -0
  172. package/bundle/src/utils/providers/grok/grok-dispatcher.test.ts +1395 -0
  173. package/bundle/src/utils/providers/grok/grok-dispatcher.ts +2105 -0
  174. package/bundle/src/utils/providers/grok/grok-headers.test.ts +149 -0
  175. package/bundle/src/utils/providers/grok/grok-headers.ts +199 -0
  176. package/bundle/src/utils/providers/grok/grok-media-client.test.ts +446 -0
  177. package/bundle/src/utils/providers/grok/grok-media-client.ts +703 -0
  178. package/bundle/src/utils/providers/grok/grok-models.test.ts +96 -0
  179. package/bundle/src/utils/providers/grok/grok-models.ts +161 -0
  180. package/bundle/src/utils/providers/grok/grok-oauth.test.ts +406 -0
  181. package/bundle/src/utils/providers/grok/grok-oauth.ts +771 -0
  182. package/bundle/src/utils/providers/grok/grok-quota.test.ts +142 -0
  183. package/bundle/src/utils/providers/grok/grok-quota.ts +198 -0
  184. package/bundle/src/utils/providers/grok/grok-refresh.test.ts +239 -0
  185. package/bundle/src/utils/providers/grok/grok-refresh.ts +325 -0
  186. package/bundle/src/utils/providers/grok/grok-types.test.ts +252 -0
  187. package/bundle/src/utils/providers/grok/grok-types.ts +374 -0
  188. package/bundle/src/utils/providers/grok/grok-voice-client.test.ts +321 -0
  189. package/bundle/src/utils/providers/grok/grok-voice-client.ts +284 -0
  190. package/bundle/src/utils/providers/grok/index.ts +20 -0
  191. package/bundle/src/utils/providers/openai/openai-backend-protocol.ts +221 -137
  192. package/bundle/src/utils/providers/openai/openai-callback-relay.ts +12 -1
  193. package/bundle/src/utils/providers/openai/openai-constants.ts +2 -0
  194. package/bundle/src/utils/providers/openai/openai-direct-client.ts +111 -21
  195. package/bundle/src/utils/providers/openai/openai-dispatcher.ts +322 -169
  196. package/bundle/src/utils/providers/openai/openai-image-generation.ts +116 -36
  197. package/bundle/src/utils/providers/openai/openai-oauth.ts +48 -20
  198. package/bundle/src/utils/providers/openai/openai-quota.ts +77 -46
  199. package/bundle/src/utils/providers/openai/openai-refresh.ts +42 -18
  200. package/bundle/src/utils/providers/openai/openai-sse.ts +27 -3
  201. package/bundle/src/utils/providers/openai/openai-transport-config.ts +2 -0
  202. package/bundle/src/utils/quiet-hours.ts +12 -1
  203. package/bundle/src/utils/slack-notify.ts +44 -13
  204. package/bundle/src/utils/subset-loaders.ts +7 -7
  205. package/bundle/web-dist/client/assets/clsx-5XM_pHvN.js +1 -0
  206. package/bundle/web-dist/client/assets/index-BA7uQ-6c.js +31 -0
  207. package/bundle/web-dist/client/assets/index-Be2qCZmI.css +1 -0
  208. package/bundle/web-dist/client/assets/logs-C47OJGEI.js +1 -0
  209. package/bundle/web-dist/client/assets/monit-BS9no0dU.js +4 -0
  210. package/bundle/web-dist/client/assets/plus-sdACTfH0.js +1 -0
  211. package/bundle/web-dist/client/assets/refresh-cw-CY8o_1cT.js +1 -0
  212. package/bundle/web-dist/client/assets/request-model-BRtFuZvj.js +1 -0
  213. package/bundle/web-dist/client/assets/routes-kqgkUxE8.js +5 -0
  214. package/bundle/web-dist/client/assets/{services.generated-BsieU37H.js → services.generated-CefiDXEv.js} +5 -5
  215. package/bundle/web-dist/client/assets/settings-DNDvFGSw.js +1 -0
  216. package/bundle/web-dist/client/assets/show-u8Np69q3.js +2 -0
  217. package/bundle/web-dist/client/assets/tokens-QvP410NW.js +1 -0
  218. package/bundle/web-dist/client/assets/total-cost-MnfKU8IN.js +1 -0
  219. package/bundle/web-dist/client/assets/use-oauth-login-flow-Bzdh28Ws.js +1 -0
  220. package/bundle/web-dist/client/assets/use-update-token-mutation-CfJKaxmR.js +1 -0
  221. package/bundle/web-dist/client/assets/vendor-react-CUFFrVN9.js +244 -0
  222. package/bundle/web-dist/client/assets/vendor-tanstack-Bf_jag9G.js +1 -0
  223. package/bundle/web-dist/client/index.html +6 -6
  224. package/bundle/web-dist/server/assets/clsx-D_N5PN_2.js +16 -0
  225. package/bundle/web-dist/server/assets/{lazyRouteComponent-Dtd0NR4r.js → lazyRouteComponent-D8iTIHyn.js} +129 -2
  226. package/bundle/web-dist/server/assets/logs-B3OTd9hy.js +825 -0
  227. package/bundle/web-dist/server/assets/{monit-DvzribSE.js → monit-B2hqorPe.js} +385 -126
  228. package/bundle/web-dist/server/assets/plus-DwG7h9kq.js +28 -0
  229. package/bundle/web-dist/server/assets/{react-dom-B4a6-uuR.js → react-dom-BIYQzBqG.js} +2 -129
  230. package/bundle/web-dist/server/assets/refresh-cw-mMBkwOq0.js +44 -0
  231. package/bundle/web-dist/server/assets/{request-model-CbqfnQOJ.js → request-model-I6OdODSH.js} +15 -6
  232. package/bundle/web-dist/server/assets/{routes-BAPWTizT.js → routes-B95YlUv2.js} +760 -213
  233. package/bundle/web-dist/server/assets/{services.generated-CEbGjsI0.js → services.generated-DQATJ6qf.js} +12821 -12194
  234. package/bundle/web-dist/server/assets/settings-C3gbGk0m.js +830 -0
  235. package/bundle/web-dist/server/assets/{show-CxVZTAdv.js → show-Bxaj3rhH.js} +1355 -419
  236. package/bundle/web-dist/server/assets/tokens-CZjH3cB7.js +1038 -0
  237. package/bundle/web-dist/server/assets/total-cost-fTE9Xy82.js +18 -0
  238. package/bundle/web-dist/server/assets/use-oauth-login-flow-CKDHgc3U.js +2379 -0
  239. package/bundle/web-dist/server/assets/{use-update-token-mutation-CfYmk_4_.js → use-update-token-mutation-BEbgOzaa.js} +1 -1
  240. package/bundle/web-dist/server/entry-server.generated.js +4303 -22810
  241. package/dist/cli.js +9 -9
  242. package/package.json +4 -11
  243. package/postinstall.mjs +12 -0
  244. package/skills/qgrid/SKILL.md +1 -0
  245. package/skills/qgrid/references/cli-env-and-server-boot.md +4 -1
  246. package/skills/qgrid/references/decision-rationale.md +24 -1
  247. package/skills/qgrid/references/grok-runtime.md +89 -0
  248. package/skills/qgrid/references/provider-runtime-differences.md +30 -29
  249. package/skills/qgrid/references/repo-map.md +10 -0
  250. package/skills/qgrid/references/request-log-run-lifecycle.md +1 -1
  251. package/skills/qgrid/references/sonamu-api-web-flow.md +1 -1
  252. package/skills/qgrid/references/token-auth-quota-lifecycle.md +56 -3
  253. package/bundle/dist/node_modules/.pnpm/@jridgewell_sourcemap-codec@1.5.5/node_modules/@jridgewell/sourcemap-codec/dist/sourcemap-codec.js +0 -406
  254. package/bundle/dist/node_modules/.pnpm/@vitest_expect@4.1.10/node_modules/@vitest/expect/dist/index.js +0 -1507
  255. package/bundle/dist/node_modules/.pnpm/@vitest_pretty-format@4.1.10/node_modules/@vitest/pretty-format/dist/index.js +0 -887
  256. package/bundle/dist/node_modules/.pnpm/@vitest_runner@4.1.10/node_modules/@vitest/runner/dist/chunk-artifact.js +0 -2756
  257. package/bundle/dist/node_modules/.pnpm/@vitest_runner@4.1.10/node_modules/@vitest/runner/dist/index.js +0 -8
  258. package/bundle/dist/node_modules/.pnpm/@vitest_runner@4.1.10/node_modules/@vitest/runner/dist/utils.js +0 -8
  259. package/bundle/dist/node_modules/.pnpm/@vitest_snapshot@4.1.10/node_modules/@vitest/snapshot/dist/index.js +0 -922
  260. package/bundle/dist/node_modules/.pnpm/@vitest_spy@4.1.10/node_modules/@vitest/spy/dist/index.js +0 -386
  261. package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/chunk-pathe.M-eThtNZ.js +0 -121
  262. package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/constants.js +0 -51
  263. package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/diff.js +0 -1317
  264. package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/display.js +0 -561
  265. package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/error.js +0 -40
  266. package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/helpers.js +0 -272
  267. package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/offset.js +0 -27
  268. package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/serialize.js +0 -77
  269. package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/source-map.js +0 -381
  270. package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/timers.js +0 -51
  271. package/bundle/dist/node_modules/.pnpm/chai@6.2.2/node_modules/chai/index.js +0 -2986
  272. package/bundle/dist/node_modules/.pnpm/expect-type@1.3.0/node_modules/expect-type/dist/branding.js +0 -10
  273. package/bundle/dist/node_modules/.pnpm/expect-type@1.3.0/node_modules/expect-type/dist/index.js +0 -109
  274. package/bundle/dist/node_modules/.pnpm/expect-type@1.3.0/node_modules/expect-type/dist/messages.js +0 -10
  275. package/bundle/dist/node_modules/.pnpm/expect-type@1.3.0/node_modules/expect-type/dist/overloads.js +0 -10
  276. package/bundle/dist/node_modules/.pnpm/expect-type@1.3.0/node_modules/expect-type/dist/utils.js +0 -10
  277. package/bundle/dist/node_modules/.pnpm/magic-string@0.30.21/node_modules/magic-string/dist/magic-string.es.js +0 -1126
  278. package/bundle/dist/node_modules/.pnpm/pathe@2.0.3/node_modules/pathe/dist/index.js +0 -21
  279. package/bundle/dist/node_modules/.pnpm/pathe@2.0.3/node_modules/pathe/dist/shared/pathe.M-eThtNZ.js +0 -432
  280. package/bundle/dist/node_modules/.pnpm/tinybench@2.9.0/node_modules/tinybench/dist/index.js +0 -517
  281. package/bundle/dist/node_modules/.pnpm/tinyrainbow@3.1.0/node_modules/tinyrainbow/dist/index.js +0 -101
  282. package/bundle/dist/node_modules/.pnpm/vite@8.0.3_@emnapi_core@1.11.2_@emnapi_runtime@1.11.2_@types_node@25.0.7_esbuild@0.27.4_5b35fc1fb85d2af4d105e0d74f940f50/node_modules/vite/dist/node/module-runner.js +0 -1265
  283. package/bundle/dist/node_modules/.pnpm/vitest@4.1.10_@opentelemetry_api@1.9.0_@types_node@25.0.7_@vitest_coverage-v8@4.1.10_vi_a1977b93af7bb69308bcb1dbab39b618/node_modules/vitest/dist/chunks/_commonjsHelpers.D26ty3Ew.js +0 -9
  284. package/bundle/dist/node_modules/.pnpm/vitest@4.1.10_@opentelemetry_api@1.9.0_@types_node@25.0.7_@vitest_coverage-v8@4.1.10_vi_a1977b93af7bb69308bcb1dbab39b618/node_modules/vitest/dist/chunks/benchmark.CX_oY03V.js +0 -41
  285. package/bundle/dist/node_modules/.pnpm/vitest@4.1.10_@opentelemetry_api@1.9.0_@types_node@25.0.7_@vitest_coverage-v8@4.1.10_vi_a1977b93af7bb69308bcb1dbab39b618/node_modules/vitest/dist/chunks/evaluatedModules.Dg1zASAC.js +0 -19
  286. package/bundle/dist/node_modules/.pnpm/vitest@4.1.10_@opentelemetry_api@1.9.0_@types_node@25.0.7_@vitest_coverage-v8@4.1.10_vi_a1977b93af7bb69308bcb1dbab39b618/node_modules/vitest/dist/chunks/index.Chj8NDwU.js +0 -202
  287. package/bundle/dist/node_modules/.pnpm/vitest@4.1.10_@opentelemetry_api@1.9.0_@types_node@25.0.7_@vitest_coverage-v8@4.1.10_vi_a1977b93af7bb69308bcb1dbab39b618/node_modules/vitest/dist/chunks/index.DdgEv5B1.js +0 -46
  288. package/bundle/dist/node_modules/.pnpm/vitest@4.1.10_@opentelemetry_api@1.9.0_@types_node@25.0.7_@vitest_coverage-v8@4.1.10_vi_a1977b93af7bb69308bcb1dbab39b618/node_modules/vitest/dist/chunks/rpc.MzXet3jl.js +0 -119
  289. package/bundle/dist/node_modules/.pnpm/vitest@4.1.10_@opentelemetry_api@1.9.0_@types_node@25.0.7_@vitest_coverage-v8@4.1.10_vi_a1977b93af7bb69308bcb1dbab39b618/node_modules/vitest/dist/chunks/test.DNmyFkvJ.js +0 -3044
  290. package/bundle/dist/node_modules/.pnpm/vitest@4.1.10_@opentelemetry_api@1.9.0_@types_node@25.0.7_@vitest_coverage-v8@4.1.10_vi_a1977b93af7bb69308bcb1dbab39b618/node_modules/vitest/dist/chunks/utils.BX5Fg8C4.js +0 -59
  291. package/bundle/dist/node_modules/.pnpm/vitest@4.1.10_@opentelemetry_api@1.9.0_@types_node@25.0.7_@vitest_coverage-v8@4.1.10_vi_a1977b93af7bb69308bcb1dbab39b618/node_modules/vitest/dist/index.js +0 -28
  292. package/bundle/dist/testing/setup-mocks.js +0 -16
  293. package/bundle/src/testing/setup-mocks.ts +0 -44
  294. package/bundle/web-dist/client/assets/index-Bw2s88Ot.css +0 -1
  295. package/bundle/web-dist/client/assets/index-CrXKu_J8.js +0 -106
  296. package/bundle/web-dist/client/assets/logs-B2SmWJXA.js +0 -1
  297. package/bundle/web-dist/client/assets/monit-D-JwXXoA.js +0 -1
  298. package/bundle/web-dist/client/assets/plus-B62CuqT8.js +0 -1
  299. package/bundle/web-dist/client/assets/refresh-cw-NNcU0Cmq.js +0 -1
  300. package/bundle/web-dist/client/assets/request-model-CojtinqK.js +0 -1
  301. package/bundle/web-dist/client/assets/routes-C5r4gTvY.js +0 -5
  302. package/bundle/web-dist/client/assets/settings-D3tDSAck.js +0 -1
  303. package/bundle/web-dist/client/assets/show-Cah_kUKC.js +0 -2
  304. package/bundle/web-dist/client/assets/tokens-DU2Iyxxd.js +0 -1
  305. package/bundle/web-dist/client/assets/use-oauth-login-flow-D0UaR9_e.js +0 -1
  306. package/bundle/web-dist/client/assets/use-update-token-mutation-DAq0F8p-.js +0 -1
  307. package/bundle/web-dist/client/assets/vendor-react-DH4kUfK2.js +0 -9
  308. package/bundle/web-dist/client/assets/vendor-tanstack-DJRQAbrY.js +0 -1
  309. package/bundle/web-dist/server/assets/logs-l91avYif.js +0 -509
  310. package/bundle/web-dist/server/assets/plus-KZrECewT.js +0 -19
  311. package/bundle/web-dist/server/assets/refresh-cw-BND93JrF.js +0 -23
  312. package/bundle/web-dist/server/assets/settings-BZR5HSAL.js +0 -461
  313. package/bundle/web-dist/server/assets/tokens-D1hb4eKk.js +0 -448
  314. package/bundle/web-dist/server/assets/use-oauth-login-flow-Cvdy0zF8.js +0 -178
  315. package/dist/cli.d.ts +0 -10
  316. /package/bundle/web-dist/client/assets/{cost-DH2jZbrw.js → cost-DB3HbU7T.js} +0 -0
  317. /package/bundle/web-dist/client/assets/{preload-helper-ca-nBW7U.js → preload-helper-DWTEM3RW.js} +0 -0
  318. /package/bundle/web-dist/server/assets/{cost-eEHeTRT5.js → cost-BC9yzyA9.js} +0 -0
@@ -1,922 +0,0 @@
1
- import { format, plugins } from "../../../../../@vitest_pretty-format@4.1.10/node_modules/@vitest/pretty-format/dist/index.js";
2
- import { getCallLastIndex, isObject } from "../../../../../@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/helpers.js";
3
- import { parseErrorStacktrace } from "../../../../../@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/source-map.js";
4
- import { lineSplitRE, offsetToLineNumber, positionToOffset } from "../../../../../@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/offset.js";
5
- //#region ../../node_modules/.pnpm/@vitest+snapshot@4.1.10/node_modules/@vitest/snapshot/dist/index.js
6
- function getDefaultExportFromCjs(x) {
7
- return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, "default") ? x["default"] : x;
8
- }
9
- var naturalCompare$1 = { exports: {} };
10
- var hasRequiredNaturalCompare;
11
- function requireNaturalCompare() {
12
- if (hasRequiredNaturalCompare) return naturalCompare$1.exports;
13
- hasRequiredNaturalCompare = 1;
14
- /*
15
- * @version 1.4.0
16
- * @date 2015-10-26
17
- * @stability 3 - Stable
18
- * @author Lauri Rooden (https://github.com/litejs/natural-compare-lite)
19
- * @license MIT License
20
- */
21
- var naturalCompare = function(a, b) {
22
- var i, codeA, codeB = 1, posA = 0, posB = 0, alphabet = String.alphabet;
23
- function getCode(str, pos, code) {
24
- if (code) {
25
- for (i = pos; code = getCode(str, i), code < 76 && code > 65;) ++i;
26
- return +str.slice(pos - 1, i);
27
- }
28
- code = alphabet && alphabet.indexOf(str.charAt(pos));
29
- return code > -1 ? code + 76 : (code = str.charCodeAt(pos) || 0, code < 45 || code > 127) ? code : code < 46 ? 65 : code < 48 ? code - 1 : code < 58 ? code + 18 : code < 65 ? code - 11 : code < 91 ? code + 11 : code < 97 ? code - 37 : code < 123 ? code + 5 : code - 63;
30
- }
31
- if ((a += "") != (b += "")) for (; codeB;) {
32
- codeA = getCode(a, posA++);
33
- codeB = getCode(b, posB++);
34
- if (codeA < 76 && codeB < 76 && codeA > 66 && codeB > 66) {
35
- codeA = getCode(a, posA, posA);
36
- codeB = getCode(b, posB, posA = i);
37
- posB = i;
38
- }
39
- if (codeA != codeB) return codeA < codeB ? -1 : 1;
40
- }
41
- return 0;
42
- };
43
- try {
44
- naturalCompare$1.exports = naturalCompare;
45
- } catch (e) {
46
- String.naturalCompare = naturalCompare;
47
- }
48
- return naturalCompare$1.exports;
49
- }
50
- var naturalCompare = /*@__PURE__*/ getDefaultExportFromCjs(requireNaturalCompare());
51
- const serialize$1 = (val, config, indentation, depth, refs, printer) => {
52
- const name = val.getMockName();
53
- const nameString = name === "vi.fn()" ? "" : ` ${name}`;
54
- let callsString = "";
55
- if (val.mock.calls.length !== 0) {
56
- const indentationNext = indentation + config.indent;
57
- callsString = ` {${config.spacingOuter}${indentationNext}"calls": ${printer(val.mock.calls, config, indentationNext, depth, refs)}${config.min ? ", " : ","}${config.spacingOuter}${indentationNext}"results": ${printer(val.mock.results, config, indentationNext, depth, refs)}${config.min ? "" : ","}${config.spacingOuter}${indentation}}`;
58
- }
59
- return `[MockFunction${nameString}]${callsString}`;
60
- };
61
- const test = (val) => val && !!val._isMockFunction;
62
- const plugin = {
63
- serialize: serialize$1,
64
- test
65
- };
66
- const { DOMCollection, DOMElement, Immutable, ReactElement, ReactTestComponent, AsymmetricMatcher } = plugins;
67
- let PLUGINS = [
68
- ReactTestComponent,
69
- ReactElement,
70
- DOMElement,
71
- DOMCollection,
72
- Immutable,
73
- AsymmetricMatcher,
74
- plugin
75
- ];
76
- function addSerializer(plugin) {
77
- PLUGINS = [plugin].concat(PLUGINS);
78
- }
79
- function getSerializers() {
80
- return PLUGINS;
81
- }
82
- function testNameToKey(testName, count) {
83
- return `${testName} ${count}`;
84
- }
85
- function keyToTestName(key) {
86
- if (!/ \d+$/.test(key)) throw new Error("Snapshot keys must end with a number.");
87
- return key.replace(/ \d+$/, "");
88
- }
89
- function getSnapshotData(content, options) {
90
- const update = options.updateSnapshot;
91
- const data = Object.create(null);
92
- let snapshotContents = "";
93
- let dirty = false;
94
- if (content != null) try {
95
- snapshotContents = content;
96
- new Function("exports", snapshotContents)(data);
97
- } catch {}
98
- if ((update === "all" || update === "new") && snapshotContents) dirty = true;
99
- return {
100
- data,
101
- dirty
102
- };
103
- }
104
- function addExtraLineBreaks(string) {
105
- return string.includes("\n") ? `\n${string}\n` : string;
106
- }
107
- function removeExtraLineBreaks(string) {
108
- return string.length > 2 && string[0] === "\n" && string.endsWith("\n") ? string.slice(1, -1) : string;
109
- }
110
- const escapeRegex = true;
111
- const printFunctionName = false;
112
- function serialize(val, indent = 2, formatOverrides = {}) {
113
- return normalizeNewlines(format(val, {
114
- escapeRegex,
115
- indent,
116
- plugins: getSerializers(),
117
- printFunctionName,
118
- ...formatOverrides
119
- }));
120
- }
121
- function escapeBacktickString(str) {
122
- return str.replace(/`|\\|\$\{/g, "\\$&");
123
- }
124
- function printBacktickString(str) {
125
- return `\`${escapeBacktickString(str)}\``;
126
- }
127
- function normalizeNewlines(string) {
128
- return string.replace(/\r\n|\r/g, "\n");
129
- }
130
- async function saveSnapshotFile(environment, snapshotData, snapshotPath) {
131
- const snapshots = Object.keys(snapshotData).sort(naturalCompare).map((key) => `exports[${printBacktickString(key)}] = ${printBacktickString(normalizeNewlines(snapshotData[key]))};`);
132
- const content = `${environment.getHeader()}\n\n${snapshots.join("\n\n")}\n`;
133
- const oldContent = await environment.readSnapshotFile(snapshotPath);
134
- if (oldContent != null && oldContent === content) return;
135
- await environment.saveSnapshotFile(snapshotPath, content);
136
- }
137
- function deepMergeArray(target = [], source = []) {
138
- const mergedOutput = Array.from(target);
139
- source.forEach((sourceElement, index) => {
140
- const targetElement = mergedOutput[index];
141
- if (Array.isArray(target[index])) mergedOutput[index] = deepMergeArray(target[index], sourceElement);
142
- else if (isObject(targetElement)) mergedOutput[index] = deepMergeSnapshot(target[index], sourceElement);
143
- else mergedOutput[index] = sourceElement;
144
- });
145
- return mergedOutput;
146
- }
147
- /**
148
- * Deep merge, but considers asymmetric matchers. Unlike base util's deep merge,
149
- * will merge any object-like instance.
150
- * Compatible with Jest's snapshot matcher. Should not be used outside of snapshot.
151
- *
152
- * @example
153
- * ```ts
154
- * toMatchSnapshot({
155
- * name: expect.stringContaining('text')
156
- * })
157
- * ```
158
- */
159
- function deepMergeSnapshot(target, source) {
160
- if (isObject(target) && isObject(source)) {
161
- const mergedOutput = { ...target };
162
- Object.keys(source).forEach((key) => {
163
- if (isObject(source[key]) && !source[key].$$typeof) if (!(key in target)) Object.assign(mergedOutput, { [key]: source[key] });
164
- else mergedOutput[key] = deepMergeSnapshot(target[key], source[key]);
165
- else if (Array.isArray(source[key])) mergedOutput[key] = deepMergeArray(target[key], source[key]);
166
- else Object.assign(mergedOutput, { [key]: source[key] });
167
- });
168
- return mergedOutput;
169
- } else if (Array.isArray(target) && Array.isArray(source)) return deepMergeArray(target, source);
170
- return target;
171
- }
172
- var DefaultMap = class extends Map {
173
- constructor(defaultFn, entries) {
174
- super(entries);
175
- this.defaultFn = defaultFn;
176
- }
177
- get(key) {
178
- if (!this.has(key)) this.set(key, this.defaultFn(key));
179
- return super.get(key);
180
- }
181
- };
182
- var CounterMap = class extends DefaultMap {
183
- constructor() {
184
- super(() => 0);
185
- }
186
- _total;
187
- valueOf() {
188
- return this._total = this.total();
189
- }
190
- increment(key) {
191
- if (typeof this._total !== "undefined") this._total++;
192
- this.set(key, this.get(key) + 1);
193
- }
194
- total() {
195
- if (typeof this._total !== "undefined") return this._total;
196
- let total = 0;
197
- for (const x of this.values()) total += x;
198
- return total;
199
- }
200
- };
201
- /* @__NO_SIDE_EFFECTS__ */
202
- function memo(fn) {
203
- const cache = /* @__PURE__ */ new Map();
204
- return (arg) => {
205
- if (!cache.has(arg)) cache.set(arg, fn(arg));
206
- return cache.get(arg);
207
- };
208
- }
209
- async function saveInlineSnapshots(environment, snapshots) {
210
- const MagicString = (await import("../../../../../magic-string@0.30.21/node_modules/magic-string/dist/magic-string.es.js")).default;
211
- const files = new Set(snapshots.map((i) => i.file));
212
- await Promise.all(Array.from(files).map(async (file) => {
213
- const snaps = snapshots.filter((i) => i.file === file);
214
- const code = await environment.readSnapshotFile(file);
215
- if (code == null) throw new Error(`cannot read ${file} when saving inline snapshot`);
216
- const s = new MagicString(code);
217
- for (const snap of snaps) replaceInlineSnap(code, s, positionToOffset(code, snap.line, snap.column), snap.snapshot, snap.assertionName);
218
- const transformed = s.toString();
219
- if (transformed !== code) await environment.saveSnapshotFile(file, transformed);
220
- }));
221
- }
222
- const defaultStartObjectRegex = /(?:toMatchInlineSnapshot|toThrowErrorMatchingInlineSnapshot)\s*\(\s*(?:\/\*[\s\S]*\*\/\s*|\/\/.*(?:[\n\r\u2028\u2029]\s*|[\t\v\f \xA0\u1680\u2000-\u200A\u202F\u205F\u3000\uFEFF]))*\{/;
223
- function escapeRegExp(s) {
224
- return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
225
- }
226
- const buildStartObjectRegex = /* @__PURE__ */ memo((assertionName) => {
227
- const replaced = defaultStartObjectRegex.source.replace("toMatchInlineSnapshot|toThrowErrorMatchingInlineSnapshot", escapeRegExp(assertionName));
228
- return new RegExp(replaced);
229
- });
230
- function replaceObjectSnap(code, s, index, newSnap, assertionName) {
231
- let _code = code.slice(index);
232
- const startMatch = (assertionName ? buildStartObjectRegex(assertionName) : defaultStartObjectRegex).exec(_code);
233
- if (!startMatch) return false;
234
- _code = _code.slice(startMatch.index);
235
- let callEnd = getCallLastIndex(_code);
236
- if (callEnd === null) return false;
237
- callEnd += index + startMatch.index;
238
- const shapeEnd = getObjectShapeEndIndex(code, index + startMatch.index + startMatch[0].length);
239
- const snap = `, ${prepareSnapString(newSnap, code, index)}`;
240
- if (shapeEnd === callEnd) s.appendLeft(callEnd, snap);
241
- else s.overwrite(shapeEnd, callEnd, snap);
242
- return true;
243
- }
244
- function getObjectShapeEndIndex(code, index) {
245
- let startBraces = 1;
246
- let endBraces = 0;
247
- while (startBraces !== endBraces && index < code.length) {
248
- const s = code[index++];
249
- if (s === "{") startBraces++;
250
- else if (s === "}") endBraces++;
251
- }
252
- return index;
253
- }
254
- function prepareSnapString(snap, source, index) {
255
- const lineNumber = offsetToLineNumber(source, index);
256
- const indent = source.split(lineSplitRE)[lineNumber - 1].match(/^\s*/)[0] || "";
257
- const indentNext = indent.includes(" ") ? `${indent}\t` : `${indent} `;
258
- const lines = snap.trim().replace(/\\/g, "\\\\").split(/\n/g);
259
- const isOneline = lines.length <= 1;
260
- const quote = "`";
261
- if (isOneline) return `${quote}${lines.join("\n").replace(/`/g, "\\`").replace(/\$\{/g, "\\${")}${quote}`;
262
- return `${quote}\n${lines.map((i) => i ? indentNext + i : "").join("\n").replace(/`/g, "\\`").replace(/\$\{/g, "\\${")}\n${indent}${quote}`;
263
- }
264
- const defaultMethodNames = ["toMatchInlineSnapshot", "toThrowErrorMatchingInlineSnapshot"];
265
- function getCodeStartingAtIndex(code, index, methodNames) {
266
- for (const name of methodNames) {
267
- const adjusted = index - name.length;
268
- if (adjusted >= 0 && code.slice(adjusted, index) === name) return {
269
- code: code.slice(adjusted),
270
- index: adjusted
271
- };
272
- }
273
- return {
274
- code: code.slice(index),
275
- index
276
- };
277
- }
278
- const defaultStartRegex = /(?:toMatchInlineSnapshot|toThrowErrorMatchingInlineSnapshot)\s*\(\s*(?:\/\*[\s\S]*\*\/\s*|\/\/.*(?:[\n\r\u2028\u2029]\s*|[\t\v\f \xA0\u1680\u2000-\u200A\u202F\u205F\u3000\uFEFF]))*[\w$]*(['"`)])/;
279
- const buildStartRegex = /* @__PURE__ */ memo((assertionName) => {
280
- const replaced = defaultStartRegex.source.replace("toMatchInlineSnapshot|toThrowErrorMatchingInlineSnapshot", escapeRegExp(assertionName));
281
- return new RegExp(replaced);
282
- });
283
- function replaceInlineSnap(code, s, currentIndex, newSnap, assertionName) {
284
- const { code: codeStartingAtIndex, index } = getCodeStartingAtIndex(code, currentIndex, assertionName ? [assertionName] : defaultMethodNames);
285
- const startMatch = (assertionName ? buildStartRegex(assertionName) : defaultStartRegex).exec(codeStartingAtIndex);
286
- const firstKeywordMatch = (assertionName ? new RegExp(escapeRegExp(assertionName)) : /toMatchInlineSnapshot|toThrowErrorMatchingInlineSnapshot/).exec(codeStartingAtIndex);
287
- if (!startMatch || startMatch.index !== firstKeywordMatch?.index) return replaceObjectSnap(code, s, index, newSnap, assertionName);
288
- const quote = startMatch[1];
289
- const startIndex = index + startMatch.index + startMatch[0].length;
290
- const snapString = prepareSnapString(newSnap, code, index);
291
- if (quote === ")") {
292
- s.appendRight(startIndex - 1, snapString);
293
- return true;
294
- }
295
- const endMatch = new RegExp(`(?:^|[^\\\\])${quote}`).exec(code.slice(startIndex));
296
- if (!endMatch) return false;
297
- const endIndex = startIndex + endMatch.index + endMatch[0].length;
298
- s.overwrite(startIndex - 1, endIndex, snapString);
299
- return true;
300
- }
301
- const INDENTATION_REGEX = /^([^\S\n]*)\S/m;
302
- function stripSnapshotIndentation(inlineSnapshot) {
303
- const match = inlineSnapshot.match(INDENTATION_REGEX);
304
- if (!match || !match[1]) return inlineSnapshot;
305
- const indentation = match[1];
306
- const lines = inlineSnapshot.split(/\n/g);
307
- if (lines.length <= 2) return inlineSnapshot;
308
- if (lines[0].trim() !== "" || lines.at(-1)?.trim() !== "") return inlineSnapshot;
309
- for (let i = 1; i < lines.length - 1; i++) if (lines[i] !== "") {
310
- if (lines[i].indexOf(indentation) !== 0) return inlineSnapshot;
311
- lines[i] = lines[i].substring(indentation.length);
312
- }
313
- lines[lines.length - 1] = "";
314
- inlineSnapshot = lines.join("\n");
315
- return inlineSnapshot;
316
- }
317
- async function saveRawSnapshots(environment, snapshots) {
318
- await Promise.all(snapshots.map(async (snap) => {
319
- if (!snap.readonly) await environment.saveSnapshotFile(snap.file, snap.snapshot);
320
- }));
321
- }
322
- function isSameStackPosition(x, y) {
323
- return x.file === y.file && x.column === y.column && x.line === y.line;
324
- }
325
- var SnapshotState = class SnapshotState {
326
- _counters = new CounterMap();
327
- _dirty;
328
- _updateSnapshot;
329
- _snapshotData;
330
- _initialData;
331
- _inlineSnapshots;
332
- _inlineSnapshotStacks;
333
- _testIdToKeys = new DefaultMap(() => []);
334
- _rawSnapshots;
335
- _uncheckedKeys;
336
- _snapshotFormat;
337
- _environment;
338
- _fileExists;
339
- expand;
340
- _added = new CounterMap();
341
- _matched = new CounterMap();
342
- _unmatched = new CounterMap();
343
- _updated = new CounterMap();
344
- get added() {
345
- return this._added;
346
- }
347
- set added(value) {
348
- this._added._total = value;
349
- }
350
- get matched() {
351
- return this._matched;
352
- }
353
- set matched(value) {
354
- this._matched._total = value;
355
- }
356
- get unmatched() {
357
- return this._unmatched;
358
- }
359
- set unmatched(value) {
360
- this._unmatched._total = value;
361
- }
362
- get updated() {
363
- return this._updated;
364
- }
365
- set updated(value) {
366
- this._updated._total = value;
367
- }
368
- constructor(testFilePath, snapshotPath, snapshotContent, options) {
369
- this.testFilePath = testFilePath;
370
- this.snapshotPath = snapshotPath;
371
- const { data, dirty } = getSnapshotData(snapshotContent, options);
372
- this._fileExists = snapshotContent != null;
373
- this._initialData = { ...data };
374
- this._snapshotData = { ...data };
375
- this._dirty = dirty;
376
- this._inlineSnapshots = [];
377
- this._inlineSnapshotStacks = [];
378
- this._rawSnapshots = [];
379
- this._uncheckedKeys = new Set(Object.keys(this._snapshotData));
380
- this.expand = options.expand || false;
381
- this._updateSnapshot = options.updateSnapshot;
382
- this._snapshotFormat = {
383
- printBasicPrototype: false,
384
- escapeString: false,
385
- maxOutputLength: 2 ** 27,
386
- ...options.snapshotFormat
387
- };
388
- this._environment = options.snapshotEnvironment;
389
- }
390
- static async create(testFilePath, options) {
391
- const snapshotPath = await options.snapshotEnvironment.resolvePath(testFilePath);
392
- const content = await options.snapshotEnvironment.readSnapshotFile(snapshotPath);
393
- return new SnapshotState(testFilePath, snapshotPath, content, options);
394
- }
395
- get snapshotUpdateState() {
396
- return this._updateSnapshot;
397
- }
398
- get environment() {
399
- return this._environment;
400
- }
401
- markSnapshotsAsCheckedForTest(testName) {
402
- this._uncheckedKeys.forEach((uncheckedKey) => {
403
- if (/ \d+$| > /.test(uncheckedKey.slice(testName.length))) this._uncheckedKeys.delete(uncheckedKey);
404
- });
405
- }
406
- clearTest(testId) {
407
- this._inlineSnapshots = this._inlineSnapshots.filter((s) => s.testId !== testId);
408
- this._inlineSnapshotStacks = this._inlineSnapshotStacks.filter((s) => s.testId !== testId);
409
- for (const key of this._testIdToKeys.get(testId)) {
410
- const name = keyToTestName(key);
411
- const count = this._counters.get(name);
412
- if (count > 0) {
413
- if (key in this._snapshotData || key in this._initialData) this._snapshotData[key] = this._initialData[key];
414
- this._counters.set(name, count - 1);
415
- }
416
- }
417
- this._testIdToKeys.delete(testId);
418
- this.added.delete(testId);
419
- this.updated.delete(testId);
420
- this.matched.delete(testId);
421
- this.unmatched.delete(testId);
422
- }
423
- _inferInlineSnapshotStack(stacks) {
424
- const promiseIndex = stacks.findIndex((i) => i.method.match(/__VITEST_(RESOLVES|REJECTS)__/));
425
- if (promiseIndex !== -1) return stacks[promiseIndex + 3];
426
- const pollChainIndex = stacks.findIndex((i) => i.method.match(/__VITEST_POLL_CHAIN__/));
427
- if (pollChainIndex !== -1) return stacks[pollChainIndex + 1];
428
- for (let i = 0; i < stacks.length; i++) {
429
- const match = stacks[i].method.match(/__INLINE_SNAPSHOT_OFFSET_(\d+)__/);
430
- if (match) return stacks[i + Number(match[1])] ?? null;
431
- }
432
- const customMatcherIndex = stacks.findIndex((i) => i.method.includes("__VITEST_EXTEND_ASSERTION__"));
433
- if (customMatcherIndex !== -1) return stacks[customMatcherIndex + 3] ?? null;
434
- const stackIndex = stacks.findIndex((i) => i.method.includes("__INLINE_SNAPSHOT__"));
435
- return stackIndex !== -1 ? stacks[stackIndex + 2] : null;
436
- }
437
- _addSnapshot(key, receivedSerialized, options) {
438
- this._dirty = true;
439
- if (options.stack) this._inlineSnapshots.push({
440
- ...options.stack,
441
- snapshot: receivedSerialized,
442
- testId: options.testId,
443
- assertionName: options.assertionName
444
- });
445
- else if (options.rawSnapshot) this._rawSnapshots.push({
446
- ...options.rawSnapshot,
447
- snapshot: receivedSerialized
448
- });
449
- else this._snapshotData[key] = receivedSerialized;
450
- }
451
- _resolveKey(testId, testName, key) {
452
- this._counters.increment(testName);
453
- const count = this._counters.get(testName);
454
- if (!key) key = testNameToKey(testName, count);
455
- this._testIdToKeys.get(testId).push(key);
456
- return {
457
- key,
458
- count
459
- };
460
- }
461
- _resolveInlineStack(options) {
462
- const { testId, snapshot, assertionName, error } = options;
463
- const stacks = parseErrorStacktrace(error, { ignoreStackEntries: [] });
464
- const _stack = this._inferInlineSnapshotStack(stacks);
465
- if (!_stack) {
466
- const message = stacks.map((s) => ` ${s.file}:${s.line}:${s.column}${s.method ? ` (${s.method})` : ""}`).join("\n");
467
- throw new Error(`@vitest/snapshot: Couldn't infer stack frame for inline snapshot.\n${message}`);
468
- }
469
- const stack = this.environment.processStackTrace?.(_stack) || _stack;
470
- stack.column--;
471
- const snapshotsWithSameStack = this._inlineSnapshotStacks.filter((s) => isSameStackPosition(s, stack));
472
- if (snapshotsWithSameStack.length > 0) {
473
- this._inlineSnapshots = this._inlineSnapshots.filter((s) => !isSameStackPosition(s, stack));
474
- const differentSnapshot = snapshotsWithSameStack.find((s) => s.snapshot !== snapshot);
475
- if (differentSnapshot) throw Object.assign(/* @__PURE__ */ new Error(`${assertionName} with different snapshots cannot be called at the same location`), {
476
- actual: snapshot,
477
- expected: differentSnapshot.snapshot
478
- });
479
- }
480
- this._inlineSnapshotStacks.push({
481
- ...stack,
482
- testId,
483
- snapshot
484
- });
485
- return stack;
486
- }
487
- _reconcile(opts) {
488
- if (opts.hasSnapshot && this._updateSnapshot === "all" || (!opts.hasSnapshot || !opts.snapshotIsPersisted) && (this._updateSnapshot === "new" || this._updateSnapshot === "all")) {
489
- if (this._updateSnapshot === "all") if (!opts.pass) {
490
- if (opts.hasSnapshot) this.updated.increment(opts.testId);
491
- else this.added.increment(opts.testId);
492
- this._addSnapshot(opts.key, opts.addValue, {
493
- stack: opts.stack,
494
- testId: opts.testId,
495
- rawSnapshot: opts.rawSnapshot,
496
- assertionName: opts.assertionName
497
- });
498
- } else this.matched.increment(opts.testId);
499
- else {
500
- this._addSnapshot(opts.key, opts.addValue, {
501
- stack: opts.stack,
502
- testId: opts.testId,
503
- rawSnapshot: opts.rawSnapshot,
504
- assertionName: opts.assertionName
505
- });
506
- this.added.increment(opts.testId);
507
- }
508
- return {
509
- actual: "",
510
- count: opts.count,
511
- expected: "",
512
- key: opts.key,
513
- pass: true
514
- };
515
- } else if (!opts.pass) {
516
- this.unmatched.increment(opts.testId);
517
- return {
518
- actual: opts.actualDisplay,
519
- count: opts.count,
520
- expected: opts.expectedDisplay,
521
- key: opts.key,
522
- pass: false
523
- };
524
- } else {
525
- this.matched.increment(opts.testId);
526
- return {
527
- actual: "",
528
- count: opts.count,
529
- expected: "",
530
- key: opts.key,
531
- pass: true
532
- };
533
- }
534
- }
535
- async save() {
536
- const hasExternalSnapshots = Object.keys(this._snapshotData).length;
537
- const hasInlineSnapshots = this._inlineSnapshots.length;
538
- const hasRawSnapshots = this._rawSnapshots.length;
539
- const isEmpty = !hasExternalSnapshots && !hasInlineSnapshots && !hasRawSnapshots;
540
- const status = {
541
- deleted: false,
542
- saved: false
543
- };
544
- if ((this._dirty || this._uncheckedKeys.size) && !isEmpty) {
545
- if (hasExternalSnapshots) {
546
- await saveSnapshotFile(this._environment, this._snapshotData, this.snapshotPath);
547
- this._fileExists = true;
548
- }
549
- if (hasInlineSnapshots) await saveInlineSnapshots(this._environment, this._inlineSnapshots);
550
- if (hasRawSnapshots) await saveRawSnapshots(this._environment, this._rawSnapshots);
551
- status.saved = true;
552
- } else if (!hasExternalSnapshots && this._fileExists) {
553
- if (this._updateSnapshot === "all") {
554
- await this._environment.removeSnapshotFile(this.snapshotPath);
555
- this._fileExists = false;
556
- }
557
- status.deleted = true;
558
- }
559
- return status;
560
- }
561
- getUncheckedCount() {
562
- return this._uncheckedKeys.size || 0;
563
- }
564
- getUncheckedKeys() {
565
- return Array.from(this._uncheckedKeys);
566
- }
567
- removeUncheckedKeys() {
568
- if (this._updateSnapshot === "all" && this._uncheckedKeys.size) {
569
- this._dirty = true;
570
- this._uncheckedKeys.forEach((key) => delete this._snapshotData[key]);
571
- this._uncheckedKeys.clear();
572
- }
573
- }
574
- probeExpectedSnapshot(options) {
575
- const count = this._counters.get(options.testName) + 1;
576
- const key = testNameToKey(options.testName, count);
577
- return {
578
- key,
579
- count,
580
- data: options?.isInline ? options.inlineSnapshot : this._snapshotData[key],
581
- markAsChecked: () => {
582
- this._counters.increment(options.testName);
583
- this._testIdToKeys.get(options.testId).push(key);
584
- this._uncheckedKeys.delete(key);
585
- }
586
- };
587
- }
588
- match({ testId, testName, received, key, inlineSnapshot, isInline, error, rawSnapshot, assertionName }) {
589
- const resolved = this._resolveKey(testId, testName, key);
590
- key = resolved.key;
591
- const count = resolved.count;
592
- if (!(isInline && this._snapshotData[key] !== void 0)) this._uncheckedKeys.delete(key);
593
- let receivedSerialized = rawSnapshot && typeof received === "string" ? received : serialize(received, void 0, this._snapshotFormat);
594
- if (!rawSnapshot) receivedSerialized = addExtraLineBreaks(receivedSerialized);
595
- if (rawSnapshot) {
596
- if (rawSnapshot.content && rawSnapshot.content.match(/\r\n/) && !receivedSerialized.match(/\r\n/)) rawSnapshot.content = normalizeNewlines(rawSnapshot.content);
597
- }
598
- const expected = isInline ? inlineSnapshot : rawSnapshot ? rawSnapshot.content : this._snapshotData[key];
599
- const expectedTrimmed = rawSnapshot ? expected : expected?.trim();
600
- const pass = expectedTrimmed === (rawSnapshot ? receivedSerialized : receivedSerialized.trim());
601
- const hasSnapshot = expected !== void 0;
602
- const snapshotIsPersisted = isInline || this._fileExists || rawSnapshot && rawSnapshot.content != null;
603
- if (pass && !isInline && !rawSnapshot) this._snapshotData[key] = receivedSerialized;
604
- const stack = isInline ? this._resolveInlineStack({
605
- testId,
606
- snapshot: receivedSerialized,
607
- assertionName: assertionName || "toMatchInlineSnapshot",
608
- error: error || /* @__PURE__ */ new Error("snapshot")
609
- }) : void 0;
610
- return this._reconcile({
611
- testId,
612
- key,
613
- count,
614
- pass,
615
- hasSnapshot,
616
- snapshotIsPersisted: !!snapshotIsPersisted,
617
- addValue: receivedSerialized,
618
- actualDisplay: rawSnapshot ? receivedSerialized : removeExtraLineBreaks(receivedSerialized),
619
- expectedDisplay: expectedTrimmed !== void 0 ? rawSnapshot ? expectedTrimmed : removeExtraLineBreaks(expectedTrimmed) : void 0,
620
- stack,
621
- rawSnapshot,
622
- assertionName
623
- });
624
- }
625
- processDomainSnapshot({ testId, received, expectedSnapshot, matchResult, isInline, error, assertionName }) {
626
- const stack = isInline ? this._resolveInlineStack({
627
- testId,
628
- snapshot: received,
629
- assertionName,
630
- error: error || /* @__PURE__ */ new Error("STACK_TRACE_ERROR")
631
- }) : void 0;
632
- const actualResolved = matchResult?.resolved ?? received;
633
- const expectedResolved = matchResult?.expected ?? expectedSnapshot.data;
634
- return this._reconcile({
635
- testId,
636
- key: expectedSnapshot.key,
637
- count: expectedSnapshot.count,
638
- pass: matchResult?.pass ?? false,
639
- hasSnapshot: !!expectedSnapshot.data,
640
- snapshotIsPersisted: isInline ? true : this._fileExists,
641
- addValue: actualResolved,
642
- actualDisplay: removeExtraLineBreaks(actualResolved),
643
- expectedDisplay: expectedResolved !== void 0 ? removeExtraLineBreaks(expectedResolved) : void 0,
644
- stack,
645
- assertionName
646
- });
647
- }
648
- async pack() {
649
- const snapshot = {
650
- filepath: this.testFilePath,
651
- added: 0,
652
- fileDeleted: false,
653
- matched: 0,
654
- unchecked: 0,
655
- uncheckedKeys: [],
656
- unmatched: 0,
657
- updated: 0
658
- };
659
- const uncheckedCount = this.getUncheckedCount();
660
- const uncheckedKeys = this.getUncheckedKeys();
661
- if (uncheckedCount) this.removeUncheckedKeys();
662
- const status = await this.save();
663
- snapshot.fileDeleted = status.deleted;
664
- snapshot.added = this.added.total();
665
- snapshot.matched = this.matched.total();
666
- snapshot.unmatched = this.unmatched.total();
667
- snapshot.updated = this.updated.total();
668
- snapshot.unchecked = !status.deleted ? uncheckedCount : 0;
669
- snapshot.uncheckedKeys = Array.from(uncheckedKeys);
670
- return snapshot;
671
- }
672
- };
673
- function createMismatchError(message, expand, actual, expected) {
674
- const error = new Error(message);
675
- Object.defineProperty(error, "actual", {
676
- value: actual,
677
- enumerable: true,
678
- configurable: true,
679
- writable: true
680
- });
681
- Object.defineProperty(error, "expected", {
682
- value: expected,
683
- enumerable: true,
684
- configurable: true,
685
- writable: true
686
- });
687
- Object.defineProperty(error, "diffOptions", { value: { expand } });
688
- return error;
689
- }
690
- var SnapshotClient = class {
691
- snapshotStateMap = /* @__PURE__ */ new Map();
692
- constructor(options = {}) {
693
- this.options = options;
694
- }
695
- async setup(filepath, options) {
696
- if (this.snapshotStateMap.has(filepath)) return;
697
- this.snapshotStateMap.set(filepath, await SnapshotState.create(filepath, options));
698
- }
699
- async finish(filepath) {
700
- const result = await this.getSnapshotState(filepath).pack();
701
- this.snapshotStateMap.delete(filepath);
702
- return result;
703
- }
704
- skipTest(filepath, testName) {
705
- this.getSnapshotState(filepath).markSnapshotsAsCheckedForTest(testName);
706
- }
707
- clearTest(filepath, testId) {
708
- this.getSnapshotState(filepath).clearTest(testId);
709
- }
710
- getSnapshotState(filepath) {
711
- const state = this.snapshotStateMap.get(filepath);
712
- if (!state) throw new Error(`The snapshot state for '${filepath}' is not found. Did you call 'SnapshotClient.setup()'?`);
713
- return state;
714
- }
715
- match(options) {
716
- const { filepath, name, testId = name, message, isInline = false, properties, inlineSnapshot, error, errorMessage, rawSnapshot, assertionName } = options;
717
- let { received } = options;
718
- if (!filepath) throw new Error("Snapshot cannot be used outside of test");
719
- const snapshotState = this.getSnapshotState(filepath);
720
- const testName = [name, ...message ? [message] : []].join(" > ");
721
- const expectedSnapshot = snapshotState.probeExpectedSnapshot({
722
- testName,
723
- testId,
724
- isInline,
725
- inlineSnapshot
726
- });
727
- if (typeof properties === "object") {
728
- if (typeof received !== "object" || !received) {
729
- expectedSnapshot.markAsChecked();
730
- throw new Error("Received value must be an object when the matcher has properties");
731
- }
732
- let propertiesPass;
733
- try {
734
- propertiesPass = this.options.isEqual?.(received, properties) ?? false;
735
- } catch (err) {
736
- expectedSnapshot.markAsChecked();
737
- throw err;
738
- }
739
- if (!propertiesPass) {
740
- expectedSnapshot.markAsChecked();
741
- return {
742
- pass: false,
743
- message: () => errorMessage || "Snapshot properties mismatched",
744
- actual: received,
745
- expected: properties
746
- };
747
- }
748
- received = deepMergeSnapshot(received, properties);
749
- }
750
- const { actual, expected, key, pass } = snapshotState.match({
751
- testId,
752
- testName,
753
- received,
754
- isInline,
755
- error,
756
- inlineSnapshot,
757
- rawSnapshot,
758
- assertionName
759
- });
760
- return {
761
- pass,
762
- message: () => `Snapshot \`${key || "unknown"}\` mismatched`,
763
- actual: rawSnapshot ? actual : actual?.trim(),
764
- expected: rawSnapshot ? expected : expected?.trim()
765
- };
766
- }
767
- assert(options) {
768
- const result = this.match(options);
769
- if (!result.pass) {
770
- const snapshotState = this.getSnapshotState(options.filepath);
771
- throw createMismatchError(result.message(), snapshotState.expand, result.actual, result.expected);
772
- }
773
- }
774
- matchDomain(options) {
775
- const { received, filepath, name, testId = name, message, adapter, isInline = false, inlineSnapshot, error } = options;
776
- if (!filepath) throw new Error("Snapshot cannot be used outside of test");
777
- const captured = adapter.capture(received);
778
- const rendered = adapter.render(captured);
779
- const snapshotState = this.getSnapshotState(filepath);
780
- const testName = [name, ...message ? [message] : []].join(" > ");
781
- const expectedSnapshot = snapshotState.probeExpectedSnapshot({
782
- testName,
783
- testId,
784
- isInline,
785
- inlineSnapshot
786
- });
787
- expectedSnapshot.markAsChecked();
788
- const matchResult = expectedSnapshot.data ? adapter.match(captured, adapter.parseExpected(expectedSnapshot.data)) : void 0;
789
- const { actual, expected, key, pass } = snapshotState.processDomainSnapshot({
790
- testId,
791
- received: rendered,
792
- expectedSnapshot,
793
- matchResult,
794
- isInline,
795
- error,
796
- assertionName: options.assertionName
797
- });
798
- return {
799
- pass,
800
- message: () => `Snapshot \`${key}\` mismatched`,
801
- actual: actual?.trim(),
802
- expected: expected?.trim()
803
- };
804
- }
805
- async pollMatchDomain(options) {
806
- const { poll, filepath, name, testId = name, message, adapter, isInline = false, inlineSnapshot, error, timeout = 1e3, interval = 50 } = options;
807
- if (!filepath) throw new Error("Snapshot cannot be used outside of test");
808
- const snapshotState = this.getSnapshotState(filepath);
809
- const testName = [name, ...message ? [message] : []].join(" > ");
810
- const expectedSnapshot = snapshotState.probeExpectedSnapshot({
811
- testName,
812
- testId,
813
- isInline,
814
- inlineSnapshot
815
- });
816
- const reference = expectedSnapshot.data && snapshotState.snapshotUpdateState !== "all" ? adapter.parseExpected(expectedSnapshot.data) : void 0;
817
- const stableResult = await getStableSnapshot({
818
- adapter,
819
- poll,
820
- interval,
821
- timedOut: timeout > 0 ? new Promise((r) => setTimeout(r, timeout)) : void 0,
822
- match: reference ? (captured) => adapter.match(captured, reference).pass : void 0
823
- });
824
- expectedSnapshot.markAsChecked();
825
- if (!stableResult?.rendered) {
826
- if (stableResult?.lastPollError) throw stableResult.lastPollError;
827
- return {
828
- pass: false,
829
- message: () => `poll() did not produce a stable snapshot within the timeout`
830
- };
831
- }
832
- const matchResult = expectedSnapshot.data ? adapter.match(stableResult.captured, adapter.parseExpected(expectedSnapshot.data)) : void 0;
833
- const { actual, expected, key, pass } = snapshotState.processDomainSnapshot({
834
- testId,
835
- received: stableResult.rendered,
836
- expectedSnapshot,
837
- matchResult,
838
- isInline,
839
- error,
840
- assertionName: options.assertionName
841
- });
842
- return {
843
- pass,
844
- message: () => `Snapshot \`${key}\` mismatched`,
845
- actual: actual?.trim(),
846
- expected: expected?.trim()
847
- };
848
- }
849
- async assertRaw(options) {
850
- if (!options.rawSnapshot) throw new Error("Raw snapshot is required");
851
- const { filepath, rawSnapshot } = options;
852
- if (rawSnapshot.content == null) {
853
- if (!filepath) throw new Error("Snapshot cannot be used outside of test");
854
- const snapshotState = this.getSnapshotState(filepath);
855
- options.filepath ||= filepath;
856
- rawSnapshot.file = await snapshotState.environment.resolveRawPath(filepath, rawSnapshot.file);
857
- rawSnapshot.content = await snapshotState.environment.readSnapshotFile(rawSnapshot.file) ?? void 0;
858
- }
859
- return this.assert(options);
860
- }
861
- clear() {
862
- this.snapshotStateMap.clear();
863
- }
864
- };
865
- /**
866
- * Polls repeatedly until the value reaches a stable state.
867
- *
868
- * Compares consecutive rendered outputs from the current session —
869
- * when two consecutive polls produce the same rendered string,
870
- * the value is considered stable.
871
- *
872
- * Every `await` (poll call, interval delay) races against `timedOut`
873
- * so that hanging polls and delays are interrupted.
874
- */
875
- async function getStableSnapshot({ adapter, poll, interval, timedOut, match }) {
876
- let lastRendered;
877
- let lastPollError;
878
- let lastStable;
879
- while (true) {
880
- try {
881
- const pollResult = await raceWith(Promise.resolve(poll()), timedOut);
882
- if (!pollResult.ok) break;
883
- const captured = adapter.capture(pollResult.value);
884
- const rendered = adapter.render(captured);
885
- if (lastRendered !== void 0 && rendered === lastRendered) {
886
- lastStable = {
887
- captured,
888
- rendered
889
- };
890
- if (!match || match(captured)) break;
891
- } else {
892
- lastRendered = rendered;
893
- lastStable = void 0;
894
- }
895
- } catch (pollError) {
896
- lastRendered = void 0;
897
- lastStable = void 0;
898
- lastPollError = pollError;
899
- }
900
- if (!(await raceWith(new Promise((r) => setTimeout(r, interval)), timedOut)).ok) break;
901
- }
902
- return {
903
- ...lastStable,
904
- lastPollError
905
- };
906
- }
907
- /** Type-safe `Promise.race` — tells you which promise won. */
908
- function raceWith(promise, other) {
909
- const left = promise.then((value) => ({
910
- ok: true,
911
- value
912
- }));
913
- if (!other) return left;
914
- return Promise.race([left, other.then((value) => ({
915
- ok: false,
916
- value
917
- }))]);
918
- }
919
- //#endregion
920
- export { SnapshotClient, SnapshotState, addSerializer, getSerializers, stripSnapshotIndentation };
921
-
922
- //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJuYW1lcyI6W10sInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vbm9kZV9tb2R1bGVzLy5wbnBtL0B2aXRlc3Qrc25hcHNob3RANC4xLjEwL25vZGVfbW9kdWxlcy9Adml0ZXN0L3NuYXBzaG90L2Rpc3QvaW5kZXguanMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgcGFyc2VFcnJvclN0YWNrdHJhY2UgfSBmcm9tICdAdml0ZXN0L3V0aWxzL3NvdXJjZS1tYXAnO1xuaW1wb3J0IHsgaXNPYmplY3QsIGdldENhbGxMYXN0SW5kZXggfSBmcm9tICdAdml0ZXN0L3V0aWxzL2hlbHBlcnMnO1xuaW1wb3J0IHsgcG9zaXRpb25Ub09mZnNldCwgb2Zmc2V0VG9MaW5lTnVtYmVyLCBsaW5lU3BsaXRSRSB9IGZyb20gJ0B2aXRlc3QvdXRpbHMvb2Zmc2V0JztcbmltcG9ydCB7IHBsdWdpbnMsIGZvcm1hdCB9IGZyb20gJ0B2aXRlc3QvcHJldHR5LWZvcm1hdCc7XG5cbmZ1bmN0aW9uIGdldERlZmF1bHRFeHBvcnRGcm9tQ2pzKHgpIHtcblx0cmV0dXJuIHggJiYgeC5fX2VzTW9kdWxlICYmIE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbCh4LCBcImRlZmF1bHRcIikgPyB4W1wiZGVmYXVsdFwiXSA6IHg7XG59XG5cbnZhciBuYXR1cmFsQ29tcGFyZSQxID0ge2V4cG9ydHM6IHt9fTtcblxudmFyIGhhc1JlcXVpcmVkTmF0dXJhbENvbXBhcmU7XG5cbmZ1bmN0aW9uIHJlcXVpcmVOYXR1cmFsQ29tcGFyZSAoKSB7XG5cdGlmIChoYXNSZXF1aXJlZE5hdHVyYWxDb21wYXJlKSByZXR1cm4gbmF0dXJhbENvbXBhcmUkMS5leHBvcnRzO1xuXHRoYXNSZXF1aXJlZE5hdHVyYWxDb21wYXJlID0gMTtcblx0Lypcblx0ICogQHZlcnNpb24gICAgMS40LjBcblx0ICogQGRhdGUgICAgICAgMjAxNS0xMC0yNlxuXHQgKiBAc3RhYmlsaXR5ICAzIC0gU3RhYmxlXG5cdCAqIEBhdXRob3IgICAgIExhdXJpIFJvb2RlbiAoaHR0cHM6Ly9naXRodWIuY29tL2xpdGVqcy9uYXR1cmFsLWNvbXBhcmUtbGl0ZSlcblx0ICogQGxpY2Vuc2UgICAgTUlUIExpY2Vuc2Vcblx0ICovXG5cblxuXHR2YXIgbmF0dXJhbENvbXBhcmUgPSBmdW5jdGlvbihhLCBiKSB7XG5cdFx0dmFyIGksIGNvZGVBXG5cdFx0LCBjb2RlQiA9IDFcblx0XHQsIHBvc0EgPSAwXG5cdFx0LCBwb3NCID0gMFxuXHRcdCwgYWxwaGFiZXQgPSBTdHJpbmcuYWxwaGFiZXQ7XG5cblx0XHRmdW5jdGlvbiBnZXRDb2RlKHN0ciwgcG9zLCBjb2RlKSB7XG5cdFx0XHRpZiAoY29kZSkge1xuXHRcdFx0XHRmb3IgKGkgPSBwb3M7IGNvZGUgPSBnZXRDb2RlKHN0ciwgaSksIGNvZGUgPCA3NiAmJiBjb2RlID4gNjU7KSArK2k7XG5cdFx0XHRcdHJldHVybiArc3RyLnNsaWNlKHBvcyAtIDEsIGkpXG5cdFx0XHR9XG5cdFx0XHRjb2RlID0gYWxwaGFiZXQgJiYgYWxwaGFiZXQuaW5kZXhPZihzdHIuY2hhckF0KHBvcykpO1xuXHRcdFx0cmV0dXJuIGNvZGUgPiAtMSA/IGNvZGUgKyA3NiA6ICgoY29kZSA9IHN0ci5jaGFyQ29kZUF0KHBvcykgfHwgMCksIGNvZGUgPCA0NSB8fCBjb2RlID4gMTI3KSA/IGNvZGVcblx0XHRcdFx0OiBjb2RlIDwgNDYgPyA2NSAgICAgICAgICAgICAgIC8vIC1cblx0XHRcdFx0OiBjb2RlIDwgNDggPyBjb2RlIC0gMVxuXHRcdFx0XHQ6IGNvZGUgPCA1OCA/IGNvZGUgKyAxOCAgICAgICAgLy8gMC05XG5cdFx0XHRcdDogY29kZSA8IDY1ID8gY29kZSAtIDExXG5cdFx0XHRcdDogY29kZSA8IDkxID8gY29kZSArIDExICAgICAgICAvLyBBLVpcblx0XHRcdFx0OiBjb2RlIDwgOTcgPyBjb2RlIC0gMzdcblx0XHRcdFx0OiBjb2RlIDwgMTIzID8gY29kZSArIDUgICAgICAgIC8vIGEtelxuXHRcdFx0XHQ6IGNvZGUgLSA2M1xuXHRcdH1cblxuXG5cdFx0aWYgKChhKz1cIlwiKSAhPSAoYis9XCJcIikpIGZvciAoO2NvZGVCOykge1xuXHRcdFx0Y29kZUEgPSBnZXRDb2RlKGEsIHBvc0ErKyk7XG5cdFx0XHRjb2RlQiA9IGdldENvZGUoYiwgcG9zQisrKTtcblxuXHRcdFx0aWYgKGNvZGVBIDwgNzYgJiYgY29kZUIgPCA3NiAmJiBjb2RlQSA+IDY2ICYmIGNvZGVCID4gNjYpIHtcblx0XHRcdFx0Y29kZUEgPSBnZXRDb2RlKGEsIHBvc0EsIHBvc0EpO1xuXHRcdFx0XHRjb2RlQiA9IGdldENvZGUoYiwgcG9zQiwgcG9zQSA9IGkpO1xuXHRcdFx0XHRwb3NCID0gaTtcblx0XHRcdH1cblxuXHRcdFx0aWYgKGNvZGVBICE9IGNvZGVCKSByZXR1cm4gKGNvZGVBIDwgY29kZUIpID8gLTEgOiAxXG5cdFx0fVxuXHRcdHJldHVybiAwXG5cdH07XG5cblx0dHJ5IHtcblx0XHRuYXR1cmFsQ29tcGFyZSQxLmV4cG9ydHMgPSBuYXR1cmFsQ29tcGFyZTtcblx0fSBjYXRjaCAoZSkge1xuXHRcdFN0cmluZy5uYXR1cmFsQ29tcGFyZSA9IG5hdHVyYWxDb21wYXJlO1xuXHR9XG5cdHJldHVybiBuYXR1cmFsQ29tcGFyZSQxLmV4cG9ydHM7XG59XG5cbnZhciBuYXR1cmFsQ29tcGFyZUV4cG9ydHMgPSByZXF1aXJlTmF0dXJhbENvbXBhcmUoKTtcbnZhciBuYXR1cmFsQ29tcGFyZSA9IC8qQF9fUFVSRV9fKi9nZXREZWZhdWx0RXhwb3J0RnJvbUNqcyhuYXR1cmFsQ29tcGFyZUV4cG9ydHMpO1xuXG5jb25zdCBzZXJpYWxpemUkMSA9ICh2YWwsIGNvbmZpZywgaW5kZW50YXRpb24sIGRlcHRoLCByZWZzLCBwcmludGVyKSA9PiB7XG5cdC8vIFNlcmlhbGl6ZSBhIG5vbi1kZWZhdWx0IG5hbWUsIGV2ZW4gaWYgY29uZmlnLnByaW50RnVuY3Rpb25OYW1lIGlzIGZhbHNlLlxuXHRjb25zdCBuYW1lID0gdmFsLmdldE1vY2tOYW1lKCk7XG5cdGNvbnN0IG5hbWVTdHJpbmcgPSBuYW1lID09PSBcInZpLmZuKClcIiA/IFwiXCIgOiBgICR7bmFtZX1gO1xuXHRsZXQgY2FsbHNTdHJpbmcgPSBcIlwiO1xuXHRpZiAodmFsLm1vY2suY2FsbHMubGVuZ3RoICE9PSAwKSB7XG5cdFx0Y29uc3QgaW5kZW50YXRpb25OZXh0ID0gaW5kZW50YXRpb24gKyBjb25maWcuaW5kZW50O1xuXHRcdGNhbGxzU3RyaW5nID0gYCB7JHtjb25maWcuc3BhY2luZ091dGVyfSR7aW5kZW50YXRpb25OZXh0fVwiY2FsbHNcIjogJHtwcmludGVyKHZhbC5tb2NrLmNhbGxzLCBjb25maWcsIGluZGVudGF0aW9uTmV4dCwgZGVwdGgsIHJlZnMpfSR7Y29uZmlnLm1pbiA/IFwiLCBcIiA6IFwiLFwifSR7Y29uZmlnLnNwYWNpbmdPdXRlcn0ke2luZGVudGF0aW9uTmV4dH1cInJlc3VsdHNcIjogJHtwcmludGVyKHZhbC5tb2NrLnJlc3VsdHMsIGNvbmZpZywgaW5kZW50YXRpb25OZXh0LCBkZXB0aCwgcmVmcyl9JHtjb25maWcubWluID8gXCJcIiA6IFwiLFwifSR7Y29uZmlnLnNwYWNpbmdPdXRlcn0ke2luZGVudGF0aW9ufX1gO1xuXHR9XG5cdHJldHVybiBgW01vY2tGdW5jdGlvbiR7bmFtZVN0cmluZ31dJHtjYWxsc1N0cmluZ31gO1xufTtcbmNvbnN0IHRlc3QgPSAodmFsKSA9PiB2YWwgJiYgISF2YWwuX2lzTW9ja0Z1bmN0aW9uO1xuY29uc3QgcGx1Z2luID0ge1xuXHRzZXJpYWxpemU6IHNlcmlhbGl6ZSQxLFxuXHR0ZXN0XG59O1xuXG5jb25zdCB7IERPTUNvbGxlY3Rpb24sIERPTUVsZW1lbnQsIEltbXV0YWJsZSwgUmVhY3RFbGVtZW50LCBSZWFjdFRlc3RDb21wb25lbnQsIEFzeW1tZXRyaWNNYXRjaGVyIH0gPSBwbHVnaW5zO1xubGV0IFBMVUdJTlMgPSBbXG5cdFJlYWN0VGVzdENvbXBvbmVudCxcblx0UmVhY3RFbGVtZW50LFxuXHRET01FbGVtZW50LFxuXHRET01Db2xsZWN0aW9uLFxuXHRJbW11dGFibGUsXG5cdEFzeW1tZXRyaWNNYXRjaGVyLFxuXHRwbHVnaW5cbl07XG5mdW5jdGlvbiBhZGRTZXJpYWxpemVyKHBsdWdpbikge1xuXHRQTFVHSU5TID0gW3BsdWdpbl0uY29uY2F0KFBMVUdJTlMpO1xufVxuZnVuY3Rpb24gZ2V0U2VyaWFsaXplcnMoKSB7XG5cdHJldHVybiBQTFVHSU5TO1xufVxuXG4vLyBUT0RPOiByZXdyaXRlIGFuZCBjbGVhbiB1cFxuZnVuY3Rpb24gdGVzdE5hbWVUb0tleSh0ZXN0TmFtZSwgY291bnQpIHtcblx0cmV0dXJuIGAke3Rlc3ROYW1lfSAke2NvdW50fWA7XG59XG5mdW5jdGlvbiBrZXlUb1Rlc3ROYW1lKGtleSkge1xuXHRpZiAoIS8gXFxkKyQvLnRlc3Qoa2V5KSkge1xuXHRcdHRocm93IG5ldyBFcnJvcihcIlNuYXBzaG90IGtleXMgbXVzdCBlbmQgd2l0aCBhIG51bWJlci5cIik7XG5cdH1cblx0cmV0dXJuIGtleS5yZXBsYWNlKC8gXFxkKyQvLCBcIlwiKTtcbn1cbmZ1bmN0aW9uIGdldFNuYXBzaG90RGF0YShjb250ZW50LCBvcHRpb25zKSB7XG5cdGNvbnN0IHVwZGF0ZSA9IG9wdGlvbnMudXBkYXRlU25hcHNob3Q7XG5cdGNvbnN0IGRhdGEgPSBPYmplY3QuY3JlYXRlKG51bGwpO1xuXHRsZXQgc25hcHNob3RDb250ZW50cyA9IFwiXCI7XG5cdGxldCBkaXJ0eSA9IGZhbHNlO1xuXHRpZiAoY29udGVudCAhPSBudWxsKSB7XG5cdFx0dHJ5IHtcblx0XHRcdHNuYXBzaG90Q29udGVudHMgPSBjb250ZW50O1xuXHRcdFx0Ly8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLW5ldy1mdW5jXG5cdFx0XHRjb25zdCBwb3B1bGF0ZSA9IG5ldyBGdW5jdGlvbihcImV4cG9ydHNcIiwgc25hcHNob3RDb250ZW50cyk7XG5cdFx0XHRwb3B1bGF0ZShkYXRhKTtcblx0XHR9IGNhdGNoIHt9XG5cdH1cblx0Ly8gY29uc3QgdmFsaWRhdGlvblJlc3VsdCA9IHZhbGlkYXRlU25hcHNob3RWZXJzaW9uKHNuYXBzaG90Q29udGVudHMpXG5cdGNvbnN0IGlzSW52YWxpZCA9IHNuYXBzaG90Q29udGVudHM7XG5cdC8vIGlmICh1cGRhdGUgPT09ICdub25lJyAmJiBpc0ludmFsaWQpXG5cdC8vICAgdGhyb3cgdmFsaWRhdGlvblJlc3VsdFxuXHRpZiAoKHVwZGF0ZSA9PT0gXCJhbGxcIiB8fCB1cGRhdGUgPT09IFwibmV3XCIpICYmIGlzSW52YWxpZCkge1xuXHRcdGRpcnR5ID0gdHJ1ZTtcblx0fVxuXHRyZXR1cm4ge1xuXHRcdGRhdGEsXG5cdFx0ZGlydHlcblx0fTtcbn1cbi8vIEFkZCBleHRyYSBsaW5lIGJyZWFrcyBhdCBiZWdpbm5pbmcgYW5kIGVuZCBvZiBtdWx0aWxpbmUgc25hcHNob3Rcbi8vIHRvIG1ha2UgdGhlIGNvbnRlbnQgZWFzaWVyIHRvIHJlYWQuXG5mdW5jdGlvbiBhZGRFeHRyYUxpbmVCcmVha3Moc3RyaW5nKSB7XG5cdHJldHVybiBzdHJpbmcuaW5jbHVkZXMoXCJcXG5cIikgPyBgXFxuJHtzdHJpbmd9XFxuYCA6IHN0cmluZztcbn1cbi8vIFJlbW92ZSBleHRyYSBsaW5lIGJyZWFrcyBhdCBiZWdpbm5pbmcgYW5kIGVuZCBvZiBtdWx0aWxpbmUgc25hcHNob3QuXG4vLyBJbnN0ZWFkIG9mIHRyaW0sIHdoaWNoIGNhbiByZW1vdmUgYWRkaXRpb25hbCBuZXdsaW5lcyBvciBzcGFjZXNcbi8vIGF0IGJlZ2lubmluZyBvciBlbmQgb2YgdGhlIGNvbnRlbnQgZnJvbSBhIGN1c3RvbSBzZXJpYWxpemVyLlxuZnVuY3Rpb24gcmVtb3ZlRXh0cmFMaW5lQnJlYWtzKHN0cmluZykge1xuXHRyZXR1cm4gc3RyaW5nLmxlbmd0aCA+IDIgJiYgc3RyaW5nWzBdID09PSBcIlxcblwiICYmIHN0cmluZy5lbmRzV2l0aChcIlxcblwiKSA/IHN0cmluZy5zbGljZSgxLCAtMSkgOiBzdHJpbmc7XG59XG4vLyBleHBvcnQgY29uc3QgcmVtb3ZlTGluZXNCZWZvcmVFeHRlcm5hbE1hdGNoZXJUcmFwID0gKHN0YWNrOiBzdHJpbmcpOiBzdHJpbmcgPT4ge1xuLy8gICBjb25zdCBsaW5lcyA9IHN0YWNrLnNwbGl0KCdcXG4nKVxuLy8gICBmb3IgKGxldCBpID0gMDsgaSA8IGxpbmVzLmxlbmd0aDsgaSArPSAxKSB7XG4vLyAgICAgLy8gSXQncyBhIGZ1bmN0aW9uIG5hbWUgc3BlY2lmaWVkIGluIGBwYWNrYWdlcy9leHBlY3Qvc3JjL2luZGV4LnRzYFxuLy8gICAgIC8vIGZvciBleHRlcm5hbCBjdXN0b20gbWF0Y2hlcnMuXG4vLyAgICAgaWYgKGxpbmVzW2ldLmluY2x1ZGVzKCdfX0VYVEVSTkFMX01BVENIRVJfVFJBUF9fJykpXG4vLyAgICAgICByZXR1cm4gbGluZXMuc2xpY2UoaSArIDEpLmpvaW4oJ1xcbicpXG4vLyAgIH1cbi8vICAgcmV0dXJuIHN0YWNrXG4vLyB9XG5jb25zdCBlc2NhcGVSZWdleCA9IHRydWU7XG5jb25zdCBwcmludEZ1bmN0aW9uTmFtZSA9IGZhbHNlO1xuZnVuY3Rpb24gc2VyaWFsaXplKHZhbCwgaW5kZW50ID0gMiwgZm9ybWF0T3ZlcnJpZGVzID0ge30pIHtcblx0cmV0dXJuIG5vcm1hbGl6ZU5ld2xpbmVzKGZvcm1hdCh2YWwsIHtcblx0XHRlc2NhcGVSZWdleCxcblx0XHRpbmRlbnQsXG5cdFx0cGx1Z2luczogZ2V0U2VyaWFsaXplcnMoKSxcblx0XHRwcmludEZ1bmN0aW9uTmFtZSxcblx0XHQuLi5mb3JtYXRPdmVycmlkZXNcblx0fSkpO1xufVxuZnVuY3Rpb24gZXNjYXBlQmFja3RpY2tTdHJpbmcoc3RyKSB7XG5cdHJldHVybiBzdHIucmVwbGFjZSgvYHxcXFxcfFxcJFxcey9nLCBcIlxcXFwkJlwiKTtcbn1cbmZ1bmN0aW9uIHByaW50QmFja3RpY2tTdHJpbmcoc3RyKSB7XG5cdHJldHVybiBgXFxgJHtlc2NhcGVCYWNrdGlja1N0cmluZyhzdHIpfVxcYGA7XG59XG5mdW5jdGlvbiBub3JtYWxpemVOZXdsaW5lcyhzdHJpbmcpIHtcblx0cmV0dXJuIHN0cmluZy5yZXBsYWNlKC9cXHJcXG58XFxyL2csIFwiXFxuXCIpO1xufVxuYXN5bmMgZnVuY3Rpb24gc2F2ZVNuYXBzaG90RmlsZShlbnZpcm9ubWVudCwgc25hcHNob3REYXRhLCBzbmFwc2hvdFBhdGgpIHtcblx0Y29uc3Qgc25hcHNob3RzID0gT2JqZWN0LmtleXMoc25hcHNob3REYXRhKS5zb3J0KG5hdHVyYWxDb21wYXJlKS5tYXAoKGtleSkgPT4gYGV4cG9ydHNbJHtwcmludEJhY2t0aWNrU3RyaW5nKGtleSl9XSA9ICR7cHJpbnRCYWNrdGlja1N0cmluZyhub3JtYWxpemVOZXdsaW5lcyhzbmFwc2hvdERhdGFba2V5XSkpfTtgKTtcblx0Y29uc3QgY29udGVudCA9IGAke2Vudmlyb25tZW50LmdldEhlYWRlcigpfVxcblxcbiR7c25hcHNob3RzLmpvaW4oXCJcXG5cXG5cIil9XFxuYDtcblx0Y29uc3Qgb2xkQ29udGVudCA9IGF3YWl0IGVudmlyb25tZW50LnJlYWRTbmFwc2hvdEZpbGUoc25hcHNob3RQYXRoKTtcblx0Y29uc3Qgc2tpcFdyaXRpbmcgPSBvbGRDb250ZW50ICE9IG51bGwgJiYgb2xkQ29udGVudCA9PT0gY29udGVudDtcblx0aWYgKHNraXBXcml0aW5nKSB7XG5cdFx0cmV0dXJuO1xuXHR9XG5cdGF3YWl0IGVudmlyb25tZW50LnNhdmVTbmFwc2hvdEZpbGUoc25hcHNob3RQYXRoLCBjb250ZW50KTtcbn1cbmZ1bmN0aW9uIGRlZXBNZXJnZUFycmF5KHRhcmdldCA9IFtdLCBzb3VyY2UgPSBbXSkge1xuXHRjb25zdCBtZXJnZWRPdXRwdXQgPSBBcnJheS5mcm9tKHRhcmdldCk7XG5cdHNvdXJjZS5mb3JFYWNoKChzb3VyY2VFbGVtZW50LCBpbmRleCkgPT4ge1xuXHRcdGNvbnN0IHRhcmdldEVsZW1lbnQgPSBtZXJnZWRPdXRwdXRbaW5kZXhdO1xuXHRcdGlmIChBcnJheS5pc0FycmF5KHRhcmdldFtpbmRleF0pKSB7XG5cdFx0XHRtZXJnZWRPdXRwdXRbaW5kZXhdID0gZGVlcE1lcmdlQXJyYXkodGFyZ2V0W2luZGV4XSwgc291cmNlRWxlbWVudCk7XG5cdFx0fSBlbHNlIGlmIChpc09iamVjdCh0YXJnZXRFbGVtZW50KSkge1xuXHRcdFx0bWVyZ2VkT3V0cHV0W2luZGV4XSA9IGRlZXBNZXJnZVNuYXBzaG90KHRhcmdldFtpbmRleF0sIHNvdXJjZUVsZW1lbnQpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHQvLyBTb3VyY2UgZG9lcyBub3QgZXhpc3QgaW4gdGFyZ2V0IG9yIHRhcmdldCBpcyBwcmltaXRpdmUgYW5kIGNhbm5vdCBiZSBkZWVwIG1lcmdlZFxuXHRcdFx0bWVyZ2VkT3V0cHV0W2luZGV4XSA9IHNvdXJjZUVsZW1lbnQ7XG5cdFx0fVxuXHR9KTtcblx0cmV0dXJuIG1lcmdlZE91dHB1dDtcbn1cbi8qKlxuKiBEZWVwIG1lcmdlLCBidXQgY29uc2lkZXJzIGFzeW1tZXRyaWMgbWF0Y2hlcnMuIFVubGlrZSBiYXNlIHV0aWwncyBkZWVwIG1lcmdlLFxuKiB3aWxsIG1lcmdlIGFueSBvYmplY3QtbGlrZSBpbnN0YW5jZS5cbiogQ29tcGF0aWJsZSB3aXRoIEplc3QncyBzbmFwc2hvdCBtYXRjaGVyLiBTaG91bGQgbm90IGJlIHVzZWQgb3V0c2lkZSBvZiBzbmFwc2hvdC5cbipcbiogQGV4YW1wbGVcbiogYGBgdHNcbiogdG9NYXRjaFNuYXBzaG90KHtcbiogICBuYW1lOiBleHBlY3Quc3RyaW5nQ29udGFpbmluZygndGV4dCcpXG4qIH0pXG4qIGBgYFxuKi9cbmZ1bmN0aW9uIGRlZXBNZXJnZVNuYXBzaG90KHRhcmdldCwgc291cmNlKSB7XG5cdGlmIChpc09iamVjdCh0YXJnZXQpICYmIGlzT2JqZWN0KHNvdXJjZSkpIHtcblx0XHRjb25zdCBtZXJnZWRPdXRwdXQgPSB7IC4uLnRhcmdldCB9O1xuXHRcdE9iamVjdC5rZXlzKHNvdXJjZSkuZm9yRWFjaCgoa2V5KSA9PiB7XG5cdFx0XHRpZiAoaXNPYmplY3Qoc291cmNlW2tleV0pICYmICFzb3VyY2Vba2V5XS4kJHR5cGVvZikge1xuXHRcdFx0XHRpZiAoIShrZXkgaW4gdGFyZ2V0KSkge1xuXHRcdFx0XHRcdE9iamVjdC5hc3NpZ24obWVyZ2VkT3V0cHV0LCB7IFtrZXldOiBzb3VyY2Vba2V5XSB9KTtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRtZXJnZWRPdXRwdXRba2V5XSA9IGRlZXBNZXJnZVNuYXBzaG90KHRhcmdldFtrZXldLCBzb3VyY2Vba2V5XSk7XG5cdFx0XHRcdH1cblx0XHRcdH0gZWxzZSBpZiAoQXJyYXkuaXNBcnJheShzb3VyY2Vba2V5XSkpIHtcblx0XHRcdFx0bWVyZ2VkT3V0cHV0W2tleV0gPSBkZWVwTWVyZ2VBcnJheSh0YXJnZXRba2V5XSwgc291cmNlW2tleV0pO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0T2JqZWN0LmFzc2lnbihtZXJnZWRPdXRwdXQsIHsgW2tleV06IHNvdXJjZVtrZXldIH0pO1xuXHRcdFx0fVxuXHRcdH0pO1xuXHRcdHJldHVybiBtZXJnZWRPdXRwdXQ7XG5cdH0gZWxzZSBpZiAoQXJyYXkuaXNBcnJheSh0YXJnZXQpICYmIEFycmF5LmlzQXJyYXkoc291cmNlKSkge1xuXHRcdHJldHVybiBkZWVwTWVyZ2VBcnJheSh0YXJnZXQsIHNvdXJjZSk7XG5cdH1cblx0cmV0dXJuIHRhcmdldDtcbn1cbmNsYXNzIERlZmF1bHRNYXAgZXh0ZW5kcyBNYXAge1xuXHRjb25zdHJ1Y3RvcihkZWZhdWx0Rm4sIGVudHJpZXMpIHtcblx0XHRzdXBlcihlbnRyaWVzKTtcblx0XHR0aGlzLmRlZmF1bHRGbiA9IGRlZmF1bHRGbjtcblx0fVxuXHRnZXQoa2V5KSB7XG5cdFx0aWYgKCF0aGlzLmhhcyhrZXkpKSB7XG5cdFx0XHR0aGlzLnNldChrZXksIHRoaXMuZGVmYXVsdEZuKGtleSkpO1xuXHRcdH1cblx0XHRyZXR1cm4gc3VwZXIuZ2V0KGtleSk7XG5cdH1cbn1cbmNsYXNzIENvdW50ZXJNYXAgZXh0ZW5kcyBEZWZhdWx0TWFwIHtcblx0Y29uc3RydWN0b3IoKSB7XG5cdFx0c3VwZXIoKCkgPT4gMCk7XG5cdH1cblx0Ly8gY29tcGF0IGZvciBqZXN0LWltYWdlLXNuYXBzaG90IGh0dHBzOi8vZ2l0aHViLmNvbS92aXRlc3QtZGV2L3ZpdGVzdC9pc3N1ZXMvNzMyMlxuXHQvLyBgdmFsdWVPZmAgYW5kIGBTbmFwc2hvdC5hZGRlZGAgc2V0dGVyIGFsbG93c1xuXHQvLyAgIHNuYXBzaG90U3RhdGUuYWRkZWQgPSBzbmFwc2hvdFN0YXRlLmFkZGVkICsgMVxuXHQvLyB0byBmdW5jdGlvbiBhc1xuXHQvLyAgIHNuYXBzaG90U3RhdGUuYWRkZWQudG90YWxfID0gc25hcHNob3RTdGF0ZS5hZGRlZC50b3RhbCgpICsgMVxuXHRfdG90YWw7XG5cdHZhbHVlT2YoKSB7XG5cdFx0cmV0dXJuIHRoaXMuX3RvdGFsID0gdGhpcy50b3RhbCgpO1xuXHR9XG5cdGluY3JlbWVudChrZXkpIHtcblx0XHRpZiAodHlwZW9mIHRoaXMuX3RvdGFsICE9PSBcInVuZGVmaW5lZFwiKSB7XG5cdFx0XHR0aGlzLl90b3RhbCsrO1xuXHRcdH1cblx0XHR0aGlzLnNldChrZXksIHRoaXMuZ2V0KGtleSkgKyAxKTtcblx0fVxuXHR0b3RhbCgpIHtcblx0XHRpZiAodHlwZW9mIHRoaXMuX3RvdGFsICE9PSBcInVuZGVmaW5lZFwiKSB7XG5cdFx0XHRyZXR1cm4gdGhpcy5fdG90YWw7XG5cdFx0fVxuXHRcdGxldCB0b3RhbCA9IDA7XG5cdFx0Zm9yIChjb25zdCB4IG9mIHRoaXMudmFsdWVzKCkpIHtcblx0XHRcdHRvdGFsICs9IHg7XG5cdFx0fVxuXHRcdHJldHVybiB0b3RhbDtcblx0fVxufVxuLyogQF9fTk9fU0lERV9FRkZFQ1RTX18gKi9cbmZ1bmN0aW9uIG1lbW8oZm4pIHtcblx0Y29uc3QgY2FjaGUgPSBuZXcgTWFwKCk7XG5cdHJldHVybiAoYXJnKSA9PiB7XG5cdFx0aWYgKCFjYWNoZS5oYXMoYXJnKSkge1xuXHRcdFx0Y2FjaGUuc2V0KGFyZywgZm4oYXJnKSk7XG5cdFx0fVxuXHRcdHJldHVybiBjYWNoZS5nZXQoYXJnKTtcblx0fTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gc2F2ZUlubGluZVNuYXBzaG90cyhlbnZpcm9ubWVudCwgc25hcHNob3RzKSB7XG5cdGNvbnN0IE1hZ2ljU3RyaW5nID0gKGF3YWl0IGltcG9ydCgnbWFnaWMtc3RyaW5nJykpLmRlZmF1bHQ7XG5cdGNvbnN0IGZpbGVzID0gbmV3IFNldChzbmFwc2hvdHMubWFwKChpKSA9PiBpLmZpbGUpKTtcblx0YXdhaXQgUHJvbWlzZS5hbGwoQXJyYXkuZnJvbShmaWxlcykubWFwKGFzeW5jIChmaWxlKSA9PiB7XG5cdFx0Y29uc3Qgc25hcHMgPSBzbmFwc2hvdHMuZmlsdGVyKChpKSA9PiBpLmZpbGUgPT09IGZpbGUpO1xuXHRcdGNvbnN0IGNvZGUgPSBhd2FpdCBlbnZpcm9ubWVudC5yZWFkU25hcHNob3RGaWxlKGZpbGUpO1xuXHRcdGlmIChjb2RlID09IG51bGwpIHtcblx0XHRcdHRocm93IG5ldyBFcnJvcihgY2Fubm90IHJlYWQgJHtmaWxlfSB3aGVuIHNhdmluZyBpbmxpbmUgc25hcHNob3RgKTtcblx0XHR9XG5cdFx0Y29uc3QgcyA9IG5ldyBNYWdpY1N0cmluZyhjb2RlKTtcblx0XHRmb3IgKGNvbnN0IHNuYXAgb2Ygc25hcHMpIHtcblx0XHRcdGNvbnN0IGluZGV4ID0gcG9zaXRpb25Ub09mZnNldChjb2RlLCBzbmFwLmxpbmUsIHNuYXAuY29sdW1uKTtcblx0XHRcdHJlcGxhY2VJbmxpbmVTbmFwKGNvZGUsIHMsIGluZGV4LCBzbmFwLnNuYXBzaG90LCBzbmFwLmFzc2VydGlvbk5hbWUpO1xuXHRcdH1cblx0XHRjb25zdCB0cmFuc2Zvcm1lZCA9IHMudG9TdHJpbmcoKTtcblx0XHRpZiAodHJhbnNmb3JtZWQgIT09IGNvZGUpIHtcblx0XHRcdGF3YWl0IGVudmlyb25tZW50LnNhdmVTbmFwc2hvdEZpbGUoZmlsZSwgdHJhbnNmb3JtZWQpO1xuXHRcdH1cblx0fSkpO1xufVxuY29uc3QgZGVmYXVsdFN0YXJ0T2JqZWN0UmVnZXggPSAvKD86dG9NYXRjaElubGluZVNuYXBzaG90fHRvVGhyb3dFcnJvck1hdGNoaW5nSW5saW5lU25hcHNob3QpXFxzKlxcKFxccyooPzpcXC9cXCpbXFxzXFxTXSpcXCpcXC9cXHMqfFxcL1xcLy4qKD86W1xcblxcclxcdTIwMjhcXHUyMDI5XVxccyp8W1xcdFxcdlxcZiBcXHhBMFxcdTE2ODBcXHUyMDAwLVxcdTIwMEFcXHUyMDJGXFx1MjA1RlxcdTMwMDBcXHVGRUZGXSkpKlxcey87XG5mdW5jdGlvbiBlc2NhcGVSZWdFeHAocykge1xuXHRyZXR1cm4gcy5yZXBsYWNlKC9bLiorP14ke30oKXxbXFxdXFxcXF0vZywgXCJcXFxcJCZcIik7XG59XG5jb25zdCBidWlsZFN0YXJ0T2JqZWN0UmVnZXggPSBtZW1vKChhc3NlcnRpb25OYW1lKSA9PiB7XG5cdGNvbnN0IHJlcGxhY2VkID0gZGVmYXVsdFN0YXJ0T2JqZWN0UmVnZXguc291cmNlLnJlcGxhY2UoXCJ0b01hdGNoSW5saW5lU25hcHNob3R8dG9UaHJvd0Vycm9yTWF0Y2hpbmdJbmxpbmVTbmFwc2hvdFwiLCBlc2NhcGVSZWdFeHAoYXNzZXJ0aW9uTmFtZSkpO1xuXHRyZXR1cm4gbmV3IFJlZ0V4cChyZXBsYWNlZCk7XG59KTtcbmZ1bmN0aW9uIHJlcGxhY2VPYmplY3RTbmFwKGNvZGUsIHMsIGluZGV4LCBuZXdTbmFwLCBhc3NlcnRpb25OYW1lKSB7XG5cdGxldCBfY29kZSA9IGNvZGUuc2xpY2UoaW5kZXgpO1xuXHRjb25zdCByZWdleCA9IGFzc2VydGlvbk5hbWUgPyBidWlsZFN0YXJ0T2JqZWN0UmVnZXgoYXNzZXJ0aW9uTmFtZSkgOiBkZWZhdWx0U3RhcnRPYmplY3RSZWdleDtcblx0Y29uc3Qgc3RhcnRNYXRjaCA9IHJlZ2V4LmV4ZWMoX2NvZGUpO1xuXHRpZiAoIXN0YXJ0TWF0Y2gpIHtcblx0XHRyZXR1cm4gZmFsc2U7XG5cdH1cblx0X2NvZGUgPSBfY29kZS5zbGljZShzdGFydE1hdGNoLmluZGV4KTtcblx0bGV0IGNhbGxFbmQgPSBnZXRDYWxsTGFzdEluZGV4KF9jb2RlKTtcblx0aWYgKGNhbGxFbmQgPT09IG51bGwpIHtcblx0XHRyZXR1cm4gZmFsc2U7XG5cdH1cblx0Y2FsbEVuZCArPSBpbmRleCArIHN0YXJ0TWF0Y2guaW5kZXg7XG5cdGNvbnN0IHNoYXBlU3RhcnQgPSBpbmRleCArIHN0YXJ0TWF0Y2guaW5kZXggKyBzdGFydE1hdGNoWzBdLmxlbmd0aDtcblx0Y29uc3Qgc2hhcGVFbmQgPSBnZXRPYmplY3RTaGFwZUVuZEluZGV4KGNvZGUsIHNoYXBlU3RhcnQpO1xuXHRjb25zdCBzbmFwID0gYCwgJHtwcmVwYXJlU25hcFN0cmluZyhuZXdTbmFwLCBjb2RlLCBpbmRleCl9YDtcblx0aWYgKHNoYXBlRW5kID09PSBjYWxsRW5kKSB7XG5cdFx0Ly8gdG9NYXRjaElubGluZVNuYXBzaG90KHsgZm9vOiBleHBlY3QuYW55KFN0cmluZykgfSlcblx0XHRzLmFwcGVuZExlZnQoY2FsbEVuZCwgc25hcCk7XG5cdH0gZWxzZSB7XG5cdFx0Ly8gdG9NYXRjaElubGluZVNuYXBzaG90KHsgZm9vOiBleHBlY3QuYW55KFN0cmluZykgfSwgYGApXG5cdFx0cy5vdmVyd3JpdGUoc2hhcGVFbmQsIGNhbGxFbmQsIHNuYXApO1xuXHR9XG5cdHJldHVybiB0cnVlO1xufVxuZnVuY3Rpb24gZ2V0T2JqZWN0U2hhcGVFbmRJbmRleChjb2RlLCBpbmRleCkge1xuXHRsZXQgc3RhcnRCcmFjZXMgPSAxO1xuXHRsZXQgZW5kQnJhY2VzID0gMDtcblx0d2hpbGUgKHN0YXJ0QnJhY2VzICE9PSBlbmRCcmFjZXMgJiYgaW5kZXggPCBjb2RlLmxlbmd0aCkge1xuXHRcdGNvbnN0IHMgPSBjb2RlW2luZGV4KytdO1xuXHRcdGlmIChzID09PSBcIntcIikge1xuXHRcdFx0c3RhcnRCcmFjZXMrKztcblx0XHR9IGVsc2UgaWYgKHMgPT09IFwifVwiKSB7XG5cdFx0XHRlbmRCcmFjZXMrKztcblx0XHR9XG5cdH1cblx0cmV0dXJuIGluZGV4O1xufVxuZnVuY3Rpb24gcHJlcGFyZVNuYXBTdHJpbmcoc25hcCwgc291cmNlLCBpbmRleCkge1xuXHRjb25zdCBsaW5lTnVtYmVyID0gb2Zmc2V0VG9MaW5lTnVtYmVyKHNvdXJjZSwgaW5kZXgpO1xuXHRjb25zdCBsaW5lID0gc291cmNlLnNwbGl0KGxpbmVTcGxpdFJFKVtsaW5lTnVtYmVyIC0gMV07XG5cdGNvbnN0IGluZGVudCA9IGxpbmUubWF0Y2goL15cXHMqLylbMF0gfHwgXCJcIjtcblx0Y29uc3QgaW5kZW50TmV4dCA9IGluZGVudC5pbmNsdWRlcyhcIlx0XCIpID8gYCR7aW5kZW50fVxcdGAgOiBgJHtpbmRlbnR9ICBgO1xuXHRjb25zdCBsaW5lcyA9IHNuYXAudHJpbSgpLnJlcGxhY2UoL1xcXFwvZywgXCJcXFxcXFxcXFwiKS5zcGxpdCgvXFxuL2cpO1xuXHRjb25zdCBpc09uZWxpbmUgPSBsaW5lcy5sZW5ndGggPD0gMTtcblx0Y29uc3QgcXVvdGUgPSBcImBcIjtcblx0aWYgKGlzT25lbGluZSkge1xuXHRcdHJldHVybiBgJHtxdW90ZX0ke2xpbmVzLmpvaW4oXCJcXG5cIikucmVwbGFjZSgvYC9nLCBcIlxcXFxgXCIpLnJlcGxhY2UoL1xcJFxcey9nLCBcIlxcXFwke1wiKX0ke3F1b3RlfWA7XG5cdH1cblx0cmV0dXJuIGAke3F1b3RlfVxcbiR7bGluZXMubWFwKChpKSA9PiBpID8gaW5kZW50TmV4dCArIGkgOiBcIlwiKS5qb2luKFwiXFxuXCIpLnJlcGxhY2UoL2AvZywgXCJcXFxcYFwiKS5yZXBsYWNlKC9cXCRcXHsvZywgXCJcXFxcJHtcIil9XFxuJHtpbmRlbnR9JHtxdW90ZX1gO1xufVxuY29uc3QgZGVmYXVsdE1ldGhvZE5hbWVzID0gW1widG9NYXRjaElubGluZVNuYXBzaG90XCIsIFwidG9UaHJvd0Vycm9yTWF0Y2hpbmdJbmxpbmVTbmFwc2hvdFwiXTtcbi8vIG9uIHdlYmtpdCwgdGhlIGxpbmUgbnVtYmVyIGlzIGF0IHRoZSBlbmQgb2YgdGhlIG1ldGhvZCwgbm90IGF0IHRoZSBzdGFydFxuZnVuY3Rpb24gZ2V0Q29kZVN0YXJ0aW5nQXRJbmRleChjb2RlLCBpbmRleCwgbWV0aG9kTmFtZXMpIHtcblx0Zm9yIChjb25zdCBuYW1lIG9mIG1ldGhvZE5hbWVzKSB7XG5cdFx0Y29uc3QgYWRqdXN0ZWQgPSBpbmRleCAtIG5hbWUubGVuZ3RoO1xuXHRcdGlmIChhZGp1c3RlZCA+PSAwICYmIGNvZGUuc2xpY2UoYWRqdXN0ZWQsIGluZGV4KSA9PT0gbmFtZSkge1xuXHRcdFx0cmV0dXJuIHtcblx0XHRcdFx0Y29kZTogY29kZS5zbGljZShhZGp1c3RlZCksXG5cdFx0XHRcdGluZGV4OiBhZGp1c3RlZFxuXHRcdFx0fTtcblx0XHR9XG5cdH1cblx0cmV0dXJuIHtcblx0XHRjb2RlOiBjb2RlLnNsaWNlKGluZGV4KSxcblx0XHRpbmRleFxuXHR9O1xufVxuY29uc3QgZGVmYXVsdFN0YXJ0UmVnZXggPSAvKD86dG9NYXRjaElubGluZVNuYXBzaG90fHRvVGhyb3dFcnJvck1hdGNoaW5nSW5saW5lU25hcHNob3QpXFxzKlxcKFxccyooPzpcXC9cXCpbXFxzXFxTXSpcXCpcXC9cXHMqfFxcL1xcLy4qKD86W1xcblxcclxcdTIwMjhcXHUyMDI5XVxccyp8W1xcdFxcdlxcZiBcXHhBMFxcdTE2ODBcXHUyMDAwLVxcdTIwMEFcXHUyMDJGXFx1MjA1RlxcdTMwMDBcXHVGRUZGXSkpKltcXHckXSooWydcImApXSkvO1xuY29uc3QgYnVpbGRTdGFydFJlZ2V4ID0gbWVtbygoYXNzZXJ0aW9uTmFtZSkgPT4ge1xuXHRjb25zdCByZXBsYWNlZCA9IGRlZmF1bHRTdGFydFJlZ2V4LnNvdXJjZS5yZXBsYWNlKFwidG9NYXRjaElubGluZVNuYXBzaG90fHRvVGhyb3dFcnJvck1hdGNoaW5nSW5saW5lU25hcHNob3RcIiwgZXNjYXBlUmVnRXhwKGFzc2VydGlvbk5hbWUpKTtcblx0cmV0dXJuIG5ldyBSZWdFeHAocmVwbGFjZWQpO1xufSk7XG5mdW5jdGlvbiByZXBsYWNlSW5saW5lU25hcChjb2RlLCBzLCBjdXJyZW50SW5kZXgsIG5ld1NuYXAsIGFzc2VydGlvbk5hbWUpIHtcblx0Y29uc3QgbWV0aG9kTmFtZXMgPSBhc3NlcnRpb25OYW1lID8gW2Fzc2VydGlvbk5hbWVdIDogZGVmYXVsdE1ldGhvZE5hbWVzO1xuXHRjb25zdCB7IGNvZGU6IGNvZGVTdGFydGluZ0F0SW5kZXgsIGluZGV4IH0gPSBnZXRDb2RlU3RhcnRpbmdBdEluZGV4KGNvZGUsIGN1cnJlbnRJbmRleCwgbWV0aG9kTmFtZXMpO1xuXHRjb25zdCBzdGFydFJlZ2V4ID0gYXNzZXJ0aW9uTmFtZSA/IGJ1aWxkU3RhcnRSZWdleChhc3NlcnRpb25OYW1lKSA6IGRlZmF1bHRTdGFydFJlZ2V4O1xuXHRjb25zdCBzdGFydE1hdGNoID0gc3RhcnRSZWdleC5leGVjKGNvZGVTdGFydGluZ0F0SW5kZXgpO1xuXHRjb25zdCBrZXl3b3JkUmVnZXggPSBhc3NlcnRpb25OYW1lID8gbmV3IFJlZ0V4cChlc2NhcGVSZWdFeHAoYXNzZXJ0aW9uTmFtZSkpIDogL3RvTWF0Y2hJbmxpbmVTbmFwc2hvdHx0b1Rocm93RXJyb3JNYXRjaGluZ0lubGluZVNuYXBzaG90Lztcblx0Y29uc3QgZmlyc3RLZXl3b3JkTWF0Y2ggPSBrZXl3b3JkUmVnZXguZXhlYyhjb2RlU3RhcnRpbmdBdEluZGV4KTtcblx0aWYgKCFzdGFydE1hdGNoIHx8IHN0YXJ0TWF0Y2guaW5kZXggIT09IGZpcnN0S2V5d29yZE1hdGNoPy5pbmRleCkge1xuXHRcdHJldHVybiByZXBsYWNlT2JqZWN0U25hcChjb2RlLCBzLCBpbmRleCwgbmV3U25hcCwgYXNzZXJ0aW9uTmFtZSk7XG5cdH1cblx0Y29uc3QgcXVvdGUgPSBzdGFydE1hdGNoWzFdO1xuXHRjb25zdCBzdGFydEluZGV4ID0gaW5kZXggKyBzdGFydE1hdGNoLmluZGV4ICsgc3RhcnRNYXRjaFswXS5sZW5ndGg7XG5cdGNvbnN0IHNuYXBTdHJpbmcgPSBwcmVwYXJlU25hcFN0cmluZyhuZXdTbmFwLCBjb2RlLCBpbmRleCk7XG5cdGlmIChxdW90ZSA9PT0gXCIpXCIpIHtcblx0XHRzLmFwcGVuZFJpZ2h0KHN0YXJ0SW5kZXggLSAxLCBzbmFwU3RyaW5nKTtcblx0XHRyZXR1cm4gdHJ1ZTtcblx0fVxuXHRjb25zdCBxdW90ZUVuZFJFID0gbmV3IFJlZ0V4cChgKD86XnxbXlxcXFxcXFxcXSkke3F1b3RlfWApO1xuXHRjb25zdCBlbmRNYXRjaCA9IHF1b3RlRW5kUkUuZXhlYyhjb2RlLnNsaWNlKHN0YXJ0SW5kZXgpKTtcblx0aWYgKCFlbmRNYXRjaCkge1xuXHRcdHJldHVybiBmYWxzZTtcblx0fVxuXHRjb25zdCBlbmRJbmRleCA9IHN0YXJ0SW5kZXggKyBlbmRNYXRjaC5pbmRleCArIGVuZE1hdGNoWzBdLmxlbmd0aDtcblx0cy5vdmVyd3JpdGUoc3RhcnRJbmRleCAtIDEsIGVuZEluZGV4LCBzbmFwU3RyaW5nKTtcblx0cmV0dXJuIHRydWU7XG59XG5jb25zdCBJTkRFTlRBVElPTl9SRUdFWCA9IC9eKFteXFxTXFxuXSopXFxTL207XG5mdW5jdGlvbiBzdHJpcFNuYXBzaG90SW5kZW50YXRpb24oaW5saW5lU25hcHNob3QpIHtcblx0Ly8gRmluZCBpbmRlbnRhdGlvbiBpZiBleGlzdHMuXG5cdGNvbnN0IG1hdGNoID0gaW5saW5lU25hcHNob3QubWF0Y2goSU5ERU5UQVRJT05fUkVHRVgpO1xuXHRpZiAoIW1hdGNoIHx8ICFtYXRjaFsxXSkge1xuXHRcdC8vIE5vIGluZGVudGF0aW9uLlxuXHRcdHJldHVybiBpbmxpbmVTbmFwc2hvdDtcblx0fVxuXHRjb25zdCBpbmRlbnRhdGlvbiA9IG1hdGNoWzFdO1xuXHRjb25zdCBsaW5lcyA9IGlubGluZVNuYXBzaG90LnNwbGl0KC9cXG4vZyk7XG5cdGlmIChsaW5lcy5sZW5ndGggPD0gMikge1xuXHRcdC8vIE11c3QgYmUgYXQgbGVhc3QgMyBsaW5lcy5cblx0XHRyZXR1cm4gaW5saW5lU25hcHNob3Q7XG5cdH1cblx0aWYgKGxpbmVzWzBdLnRyaW0oKSAhPT0gXCJcIiB8fCBsaW5lcy5hdCgtMSk/LnRyaW0oKSAhPT0gXCJcIikge1xuXHRcdC8vIElmIG5vdCBibGFuayBmaXJzdCBhbmQgbGFzdCBsaW5lcywgYWJvcnQuXG5cdFx0cmV0dXJuIGlubGluZVNuYXBzaG90O1xuXHR9XG5cdGZvciAobGV0IGkgPSAxOyBpIDwgbGluZXMubGVuZ3RoIC0gMTsgaSsrKSB7XG5cdFx0aWYgKGxpbmVzW2ldICE9PSBcIlwiKSB7XG5cdFx0XHRpZiAobGluZXNbaV0uaW5kZXhPZihpbmRlbnRhdGlvbikgIT09IDApIHtcblx0XHRcdFx0Ly8gQWxsIGxpbmVzIGV4Y2VwdCBmaXJzdCBhbmQgbGFzdCBzaG91bGQgZWl0aGVyIGJlIGJsYW5rIG9yIGhhdmUgdGhlIHNhbWVcblx0XHRcdFx0Ly8gaW5kZW50IGFzIHRoZSBmaXJzdCBsaW5lIChvciBtb3JlKS4gSWYgdGhpcyBpc24ndCB0aGUgY2FzZSB3ZSBkb24ndFxuXHRcdFx0XHQvLyB3YW50IHRvIHRvdWNoIHRoZSBzbmFwc2hvdCBhdCBhbGwuXG5cdFx0XHRcdHJldHVybiBpbmxpbmVTbmFwc2hvdDtcblx0XHRcdH1cblx0XHRcdGxpbmVzW2ldID0gbGluZXNbaV0uc3Vic3RyaW5nKGluZGVudGF0aW9uLmxlbmd0aCk7XG5cdFx0fVxuXHR9XG5cdC8vIExhc3QgbGluZSBpcyBhIHNwZWNpYWwgY2FzZSBiZWNhdXNlIGl0IHdvbid0IGhhdmUgdGhlIHNhbWUgaW5kZW50IGFzIG90aGVyc1xuXHQvLyBidXQgbWF5IHN0aWxsIGhhdmUgYmVlbiBnaXZlbiBzb21lIGluZGVudCB0byBsaW5lIHVwLlxuXHRsaW5lc1tsaW5lcy5sZW5ndGggLSAxXSA9IFwiXCI7XG5cdC8vIFJldHVybiBpbmxpbmUgc25hcHNob3QsIG5vdyBhdCBpbmRlbnQgMC5cblx0aW5saW5lU25hcHNob3QgPSBsaW5lcy5qb2luKFwiXFxuXCIpO1xuXHRyZXR1cm4gaW5saW5lU25hcHNob3Q7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHNhdmVSYXdTbmFwc2hvdHMoZW52aXJvbm1lbnQsIHNuYXBzaG90cykge1xuXHRhd2FpdCBQcm9taXNlLmFsbChzbmFwc2hvdHMubWFwKGFzeW5jIChzbmFwKSA9PiB7XG5cdFx0aWYgKCFzbmFwLnJlYWRvbmx5KSB7XG5cdFx0XHRhd2FpdCBlbnZpcm9ubWVudC5zYXZlU25hcHNob3RGaWxlKHNuYXAuZmlsZSwgc25hcC5zbmFwc2hvdCk7XG5cdFx0fVxuXHR9KSk7XG59XG5cbmZ1bmN0aW9uIGlzU2FtZVN0YWNrUG9zaXRpb24oeCwgeSkge1xuXHRyZXR1cm4geC5maWxlID09PSB5LmZpbGUgJiYgeC5jb2x1bW4gPT09IHkuY29sdW1uICYmIHgubGluZSA9PT0geS5saW5lO1xufVxuY2xhc3MgU25hcHNob3RTdGF0ZSB7XG5cdF9jb3VudGVycyA9IG5ldyBDb3VudGVyTWFwKCk7XG5cdF9kaXJ0eTtcblx0X3VwZGF0ZVNuYXBzaG90O1xuXHRfc25hcHNob3REYXRhO1xuXHRfaW5pdGlhbERhdGE7XG5cdF9pbmxpbmVTbmFwc2hvdHM7XG5cdF9pbmxpbmVTbmFwc2hvdFN0YWNrcztcblx0X3Rlc3RJZFRvS2V5cyA9IG5ldyBEZWZhdWx0TWFwKCgpID0+IFtdKTtcblx0X3Jhd1NuYXBzaG90cztcblx0X3VuY2hlY2tlZEtleXM7XG5cdF9zbmFwc2hvdEZvcm1hdDtcblx0X2Vudmlyb25tZW50O1xuXHRfZmlsZUV4aXN0cztcblx0ZXhwYW5kO1xuXHQvLyBnZXR0ZXIvc2V0dGVyIGZvciBqZXN0LWltYWdlLXNuYXBzaG90IGNvbXBhdFxuXHQvLyBodHRwczovL2dpdGh1Yi5jb20vdml0ZXN0LWRldi92aXRlc3QvaXNzdWVzLzczMjJcblx0X2FkZGVkID0gbmV3IENvdW50ZXJNYXAoKTtcblx0X21hdGNoZWQgPSBuZXcgQ291bnRlck1hcCgpO1xuXHRfdW5tYXRjaGVkID0gbmV3IENvdW50ZXJNYXAoKTtcblx0X3VwZGF0ZWQgPSBuZXcgQ291bnRlck1hcCgpO1xuXHRnZXQgYWRkZWQoKSB7XG5cdFx0cmV0dXJuIHRoaXMuX2FkZGVkO1xuXHR9XG5cdHNldCBhZGRlZCh2YWx1ZSkge1xuXHRcdHRoaXMuX2FkZGVkLl90b3RhbCA9IHZhbHVlO1xuXHR9XG5cdGdldCBtYXRjaGVkKCkge1xuXHRcdHJldHVybiB0aGlzLl9tYXRjaGVkO1xuXHR9XG5cdHNldCBtYXRjaGVkKHZhbHVlKSB7XG5cdFx0dGhpcy5fbWF0Y2hlZC5fdG90YWwgPSB2YWx1ZTtcblx0fVxuXHRnZXQgdW5tYXRjaGVkKCkge1xuXHRcdHJldHVybiB0aGlzLl91bm1hdGNoZWQ7XG5cdH1cblx0c2V0IHVubWF0Y2hlZCh2YWx1ZSkge1xuXHRcdHRoaXMuX3VubWF0Y2hlZC5fdG90YWwgPSB2YWx1ZTtcblx0fVxuXHRnZXQgdXBkYXRlZCgpIHtcblx0XHRyZXR1cm4gdGhpcy5fdXBkYXRlZDtcblx0fVxuXHRzZXQgdXBkYXRlZCh2YWx1ZSkge1xuXHRcdHRoaXMuX3VwZGF0ZWQuX3RvdGFsID0gdmFsdWU7XG5cdH1cblx0Y29uc3RydWN0b3IodGVzdEZpbGVQYXRoLCBzbmFwc2hvdFBhdGgsIHNuYXBzaG90Q29udGVudCwgb3B0aW9ucykge1xuXHRcdHRoaXMudGVzdEZpbGVQYXRoID0gdGVzdEZpbGVQYXRoO1xuXHRcdHRoaXMuc25hcHNob3RQYXRoID0gc25hcHNob3RQYXRoO1xuXHRcdGNvbnN0IHsgZGF0YSwgZGlydHkgfSA9IGdldFNuYXBzaG90RGF0YShzbmFwc2hvdENvbnRlbnQsIG9wdGlvbnMpO1xuXHRcdHRoaXMuX2ZpbGVFeGlzdHMgPSBzbmFwc2hvdENvbnRlbnQgIT0gbnVsbDtcblx0XHR0aGlzLl9pbml0aWFsRGF0YSA9IHsgLi4uZGF0YSB9O1xuXHRcdHRoaXMuX3NuYXBzaG90RGF0YSA9IHsgLi4uZGF0YSB9O1xuXHRcdHRoaXMuX2RpcnR5ID0gZGlydHk7XG5cdFx0dGhpcy5faW5saW5lU25hcHNob3RzID0gW107XG5cdFx0dGhpcy5faW5saW5lU25hcHNob3RTdGFja3MgPSBbXTtcblx0XHR0aGlzLl9yYXdTbmFwc2hvdHMgPSBbXTtcblx0XHR0aGlzLl91bmNoZWNrZWRLZXlzID0gbmV3IFNldChPYmplY3Qua2V5cyh0aGlzLl9zbmFwc2hvdERhdGEpKTtcblx0XHR0aGlzLmV4cGFuZCA9IG9wdGlvbnMuZXhwYW5kIHx8IGZhbHNlO1xuXHRcdHRoaXMuX3VwZGF0ZVNuYXBzaG90ID0gb3B0aW9ucy51cGRhdGVTbmFwc2hvdDtcblx0XHR0aGlzLl9zbmFwc2hvdEZvcm1hdCA9IHtcblx0XHRcdHByaW50QmFzaWNQcm90b3R5cGU6IGZhbHNlLFxuXHRcdFx0ZXNjYXBlU3RyaW5nOiBmYWxzZSxcblx0XHRcdG1heE91dHB1dExlbmd0aDogMiAqKiAyNyxcblx0XHRcdC4uLm9wdGlvbnMuc25hcHNob3RGb3JtYXRcblx0XHR9O1xuXHRcdHRoaXMuX2Vudmlyb25tZW50ID0gb3B0aW9ucy5zbmFwc2hvdEVudmlyb25tZW50O1xuXHR9XG5cdHN0YXRpYyBhc3luYyBjcmVhdGUodGVzdEZpbGVQYXRoLCBvcHRpb25zKSB7XG5cdFx0Y29uc3Qgc25hcHNob3RQYXRoID0gYXdhaXQgb3B0aW9ucy5zbmFwc2hvdEVudmlyb25tZW50LnJlc29sdmVQYXRoKHRlc3RGaWxlUGF0aCk7XG5cdFx0Y29uc3QgY29udGVudCA9IGF3YWl0IG9wdGlvbnMuc25hcHNob3RFbnZpcm9ubWVudC5yZWFkU25hcHNob3RGaWxlKHNuYXBzaG90UGF0aCk7XG5cdFx0cmV0dXJuIG5ldyBTbmFwc2hvdFN0YXRlKHRlc3RGaWxlUGF0aCwgc25hcHNob3RQYXRoLCBjb250ZW50LCBvcHRpb25zKTtcblx0fVxuXHRnZXQgc25hcHNob3RVcGRhdGVTdGF0ZSgpIHtcblx0XHRyZXR1cm4gdGhpcy5fdXBkYXRlU25hcHNob3Q7XG5cdH1cblx0Z2V0IGVudmlyb25tZW50KCkge1xuXHRcdHJldHVybiB0aGlzLl9lbnZpcm9ubWVudDtcblx0fVxuXHRtYXJrU25hcHNob3RzQXNDaGVja2VkRm9yVGVzdCh0ZXN0TmFtZSkge1xuXHRcdHRoaXMuX3VuY2hlY2tlZEtleXMuZm9yRWFjaCgodW5jaGVja2VkS2V5KSA9PiB7XG5cdFx0XHQvLyBza2lwIHNuYXBzaG90cyB3aXRoIGZvbGxvd2luZyBrZXlzXG5cdFx0XHQvLyAgIHRlc3ROYW1lIG5cblx0XHRcdC8vICAgdGVzdE5hbWUgPiB4eHggbiAodGhpcyBpcyBmb3IgdG9NYXRjaFNuYXBzaG90KFwieHh4XCIpIEFQSSlcblx0XHRcdGlmICgvIFxcZCskfCA+IC8udGVzdCh1bmNoZWNrZWRLZXkuc2xpY2UodGVzdE5hbWUubGVuZ3RoKSkpIHtcblx0XHRcdFx0dGhpcy5fdW5jaGVja2VkS2V5cy5kZWxldGUodW5jaGVja2VkS2V5KTtcblx0XHRcdH1cblx0XHR9KTtcblx0fVxuXHRjbGVhclRlc3QodGVzdElkKSB7XG5cdFx0Ly8gY2xlYXIgaW5saW5lXG5cdFx0dGhpcy5faW5saW5lU25hcHNob3RzID0gdGhpcy5faW5saW5lU25hcHNob3RzLmZpbHRlcigocykgPT4gcy50ZXN0SWQgIT09IHRlc3RJZCk7XG5cdFx0dGhpcy5faW5saW5lU25hcHNob3RTdGFja3MgPSB0aGlzLl9pbmxpbmVTbmFwc2hvdFN0YWNrcy5maWx0ZXIoKHMpID0+IHMudGVzdElkICE9PSB0ZXN0SWQpO1xuXHRcdC8vIGNsZWFyIGZpbGVcblx0XHRmb3IgKGNvbnN0IGtleSBvZiB0aGlzLl90ZXN0SWRUb0tleXMuZ2V0KHRlc3RJZCkpIHtcblx0XHRcdGNvbnN0IG5hbWUgPSBrZXlUb1Rlc3ROYW1lKGtleSk7XG5cdFx0XHRjb25zdCBjb3VudCA9IHRoaXMuX2NvdW50ZXJzLmdldChuYW1lKTtcblx0XHRcdGlmIChjb3VudCA+IDApIHtcblx0XHRcdFx0aWYgKGtleSBpbiB0aGlzLl9zbmFwc2hvdERhdGEgfHwga2V5IGluIHRoaXMuX2luaXRpYWxEYXRhKSB7XG5cdFx0XHRcdFx0dGhpcy5fc25hcHNob3REYXRhW2tleV0gPSB0aGlzLl9pbml0aWFsRGF0YVtrZXldO1xuXHRcdFx0XHR9XG5cdFx0XHRcdHRoaXMuX2NvdW50ZXJzLnNldChuYW1lLCBjb3VudCAtIDEpO1xuXHRcdFx0fVxuXHRcdH1cblx0XHR0aGlzLl90ZXN0SWRUb0tleXMuZGVsZXRlKHRlc3RJZCk7XG5cdFx0Ly8gY2xlYXIgc3RhdHNcblx0XHR0aGlzLmFkZGVkLmRlbGV0ZSh0ZXN0SWQpO1xuXHRcdHRoaXMudXBkYXRlZC5kZWxldGUodGVzdElkKTtcblx0XHR0aGlzLm1hdGNoZWQuZGVsZXRlKHRlc3RJZCk7XG5cdFx0dGhpcy51bm1hdGNoZWQuZGVsZXRlKHRlc3RJZCk7XG5cdH1cblx0X2luZmVySW5saW5lU25hcHNob3RTdGFjayhzdGFja3MpIHtcblx0XHQvLyBpZiBjYWxsZWQgaW5zaWRlIHJlc29sdmVzL3JlamVjdHMsIHN0YWNrdHJhY2UgaXMgZGlmZmVyZW50XG5cdFx0Y29uc3QgcHJvbWlzZUluZGV4ID0gc3RhY2tzLmZpbmRJbmRleCgoaSkgPT4gaS5tZXRob2QubWF0Y2goL19fVklURVNUXyhSRVNPTFZFU3xSRUpFQ1RTKV9fLykpO1xuXHRcdGlmIChwcm9taXNlSW5kZXggIT09IC0xKSB7XG5cdFx0XHRyZXR1cm4gc3RhY2tzW3Byb21pc2VJbmRleCArIDNdO1xuXHRcdH1cblx0XHQvLyBzdXBwb3J0IHBvbGwgKyBpbmxpbmUgc25hcHNob3Rcblx0XHRjb25zdCBwb2xsQ2hhaW5JbmRleCA9IHN0YWNrcy5maW5kSW5kZXgoKGkpID0+IGkubWV0aG9kLm1hdGNoKC9fX1ZJVEVTVF9QT0xMX0NIQUlOX18vKSk7XG5cdFx0aWYgKHBvbGxDaGFpbkluZGV4ICE9PSAtMSkge1xuXHRcdFx0cmV0dXJuIHN0YWNrc1twb2xsQ2hhaW5JbmRleCArIDFdO1xuXHRcdH1cblx0XHQvLyBpbmxpbmUgc25hcHNob3QgZnVuY3Rpb24gY2FuIGJlIG5hbWVkIF9fSU5MSU5FX1NOQVBTSE9UX09GRlNFVF88bj5fX1xuXHRcdC8vIHRvIHNwZWNpZnkgYSBjdXN0b20gc3RhY2sgb2Zmc2V0XG5cdFx0Zm9yIChsZXQgaSA9IDA7IGkgPCBzdGFja3MubGVuZ3RoOyBpKyspIHtcblx0XHRcdGNvbnN0IG1hdGNoID0gc3RhY2tzW2ldLm1ldGhvZC5tYXRjaCgvX19JTkxJTkVfU05BUFNIT1RfT0ZGU0VUXyhcXGQrKV9fLyk7XG5cdFx0XHRpZiAobWF0Y2gpIHtcblx0XHRcdFx0cmV0dXJuIHN0YWNrc1tpICsgTnVtYmVyKG1hdGNoWzFdKV0gPz8gbnVsbDtcblx0XHRcdH1cblx0XHR9XG5cdFx0Ly8gY3VzdG9tIG1hdGNoZXIgcmVnaXN0ZXJlZCB2aWEgZXhwZWN0LmV4dGVuZCgpIOKAlCB0aGUgd3JhcHBlciBmdW5jdGlvblxuXHRcdC8vIGluIGplc3QtZXh0ZW5kLnRzIGlzIG5hbWVkIF9fVklURVNUX0VYVEVORF9BU1NFUlRJT05fX1xuXHRcdGNvbnN0IGN1c3RvbU1hdGNoZXJJbmRleCA9IHN0YWNrcy5maW5kSW5kZXgoKGkpID0+IGkubWV0aG9kLmluY2x1ZGVzKFwiX19WSVRFU1RfRVhURU5EX0FTU0VSVElPTl9fXCIpKTtcblx0XHRpZiAoY3VzdG9tTWF0Y2hlckluZGV4ICE9PSAtMSkge1xuXHRcdFx0cmV0dXJuIHN0YWNrc1tjdXN0b21NYXRjaGVySW5kZXggKyAzXSA/PyBudWxsO1xuXHRcdH1cblx0XHQvLyBpbmxpbmUgc25hcHNob3QgZnVuY3Rpb24gaXMgY2FsbGVkIF9fSU5MSU5FX1NOQVBTSE9UX19cblx0XHQvLyBpbiBpbnRlZ3JhdGlvbnMvc25hcHNob3QvY2hhaS50c1xuXHRcdGNvbnN0IHN0YWNrSW5kZXggPSBzdGFja3MuZmluZEluZGV4KChpKSA9PiBpLm1ldGhvZC5pbmNsdWRlcyhcIl9fSU5MSU5FX1NOQVBTSE9UX19cIikpO1xuXHRcdHJldHVybiBzdGFja0luZGV4ICE9PSAtMSA/IHN0YWNrc1tzdGFja0luZGV4ICsgMl0gOiBudWxsO1xuXHR9XG5cdF9hZGRTbmFwc2hvdChrZXksIHJlY2VpdmVkU2VyaWFsaXplZCwgb3B0aW9ucykge1xuXHRcdHRoaXMuX2RpcnR5ID0gdHJ1ZTtcblx0XHRpZiAob3B0aW9ucy5zdGFjaykge1xuXHRcdFx0dGhpcy5faW5saW5lU25hcHNob3RzLnB1c2goe1xuXHRcdFx0XHQuLi5vcHRpb25zLnN0YWNrLFxuXHRcdFx0XHRzbmFwc2hvdDogcmVjZWl2ZWRTZXJpYWxpemVkLFxuXHRcdFx0XHR0ZXN0SWQ6IG9wdGlvbnMudGVzdElkLFxuXHRcdFx0XHRhc3NlcnRpb25OYW1lOiBvcHRpb25zLmFzc2VydGlvbk5hbWVcblx0XHRcdH0pO1xuXHRcdH0gZWxzZSBpZiAob3B0aW9ucy5yYXdTbmFwc2hvdCkge1xuXHRcdFx0dGhpcy5fcmF3U25hcHNob3RzLnB1c2goe1xuXHRcdFx0XHQuLi5vcHRpb25zLnJhd1NuYXBzaG90LFxuXHRcdFx0XHRzbmFwc2hvdDogcmVjZWl2ZWRTZXJpYWxpemVkXG5cdFx0XHR9KTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0dGhpcy5fc25hcHNob3REYXRhW2tleV0gPSByZWNlaXZlZFNlcmlhbGl6ZWQ7XG5cdFx0fVxuXHR9XG5cdF9yZXNvbHZlS2V5KHRlc3RJZCwgdGVzdE5hbWUsIGtleSkge1xuXHRcdHRoaXMuX2NvdW50ZXJzLmluY3JlbWVudCh0ZXN0TmFtZSk7XG5cdFx0Y29uc3QgY291bnQgPSB0aGlzLl9jb3VudGVycy5nZXQodGVzdE5hbWUpO1xuXHRcdGlmICgha2V5KSB7XG5cdFx0XHRrZXkgPSB0ZXN0TmFtZVRvS2V5KHRlc3ROYW1lLCBjb3VudCk7XG5cdFx0fVxuXHRcdHRoaXMuX3Rlc3RJZFRvS2V5cy5nZXQodGVzdElkKS5wdXNoKGtleSk7XG5cdFx0cmV0dXJuIHtcblx0XHRcdGtleSxcblx0XHRcdGNvdW50XG5cdFx0fTtcblx0fVxuXHRfcmVzb2x2ZUlubGluZVN0YWNrKG9wdGlvbnMpIHtcblx0XHRjb25zdCB7IHRlc3RJZCwgc25hcHNob3QsIGFzc2VydGlvbk5hbWUsIGVycm9yIH0gPSBvcHRpb25zO1xuXHRcdGNvbnN0IHN0YWNrcyA9IHBhcnNlRXJyb3JTdGFja3RyYWNlKGVycm9yLCB7IGlnbm9yZVN0YWNrRW50cmllczogW10gfSk7XG5cdFx0Y29uc3QgX3N0YWNrID0gdGhpcy5faW5mZXJJbmxpbmVTbmFwc2hvdFN0YWNrKHN0YWNrcyk7XG5cdFx0aWYgKCFfc3RhY2spIHtcblx0XHRcdGNvbnN0IG1lc3NhZ2UgPSBzdGFja3MubWFwKChzKSA9PiBgICAke3MuZmlsZX06JHtzLmxpbmV9OiR7cy5jb2x1bW59JHtzLm1ldGhvZCA/IGAgKCR7cy5tZXRob2R9KWAgOiBcIlwifWApLmpvaW4oXCJcXG5cIik7XG5cdFx0XHR0aHJvdyBuZXcgRXJyb3IoYEB2aXRlc3Qvc25hcHNob3Q6IENvdWxkbid0IGluZmVyIHN0YWNrIGZyYW1lIGZvciBpbmxpbmUgc25hcHNob3QuXFxuJHttZXNzYWdlfWApO1xuXHRcdH1cblx0XHRjb25zdCBzdGFjayA9IHRoaXMuZW52aXJvbm1lbnQucHJvY2Vzc1N0YWNrVHJhY2U/Lihfc3RhY2spIHx8IF9zdGFjaztcblx0XHQvLyByZW1vdmluZyAxIGNvbHVtbiwgYmVjYXVzZSBzb3VyY2UgbWFwIHBvaW50cyB0byB0aGUgd3Jvbmdcblx0XHQvLyBsb2NhdGlvbiBmb3IganMgZmlsZXMsIGJ1dCBgY29sdW1uLTFgIHBvaW50cyB0byB0aGUgc2FtZSBpbiBib3RoIGpzL3RzXG5cdFx0Ly8gaHR0cHM6Ly9naXRodWIuY29tL3ZpdGVqcy92aXRlL2lzc3Vlcy84NjU3XG5cdFx0c3RhY2suY29sdW1uLS07XG5cdFx0Ly8gcmVqZWN0IG11bHRpcGxlIGlubGluZSBzbmFwc2hvdHMgYXQgdGhlIHNhbWUgbG9jYXRpb24gaWYgc25hcHNob3QgaXMgZGlmZmVyZW50XG5cdFx0Y29uc3Qgc25hcHNob3RzV2l0aFNhbWVTdGFjayA9IHRoaXMuX2lubGluZVNuYXBzaG90U3RhY2tzLmZpbHRlcigocykgPT4gaXNTYW1lU3RhY2tQb3NpdGlvbihzLCBzdGFjaykpO1xuXHRcdGlmIChzbmFwc2hvdHNXaXRoU2FtZVN0YWNrLmxlbmd0aCA+IDApIHtcblx0XHRcdC8vIGVuc3VyZSBvbmx5IG9uZSBzbmFwc2hvdCB3aWxsIGJlIHdyaXR0ZW4gYXQgdGhlIHNhbWUgbG9jYXRpb25cblx0XHRcdHRoaXMuX2lubGluZVNuYXBzaG90cyA9IHRoaXMuX2lubGluZVNuYXBzaG90cy5maWx0ZXIoKHMpID0+ICFpc1NhbWVTdGFja1Bvc2l0aW9uKHMsIHN0YWNrKSk7XG5cdFx0XHRjb25zdCBkaWZmZXJlbnRTbmFwc2hvdCA9IHNuYXBzaG90c1dpdGhTYW1lU3RhY2suZmluZCgocykgPT4gcy5zbmFwc2hvdCAhPT0gc25hcHNob3QpO1xuXHRcdFx0aWYgKGRpZmZlcmVudFNuYXBzaG90KSB7XG5cdFx0XHRcdHRocm93IE9iamVjdC5hc3NpZ24obmV3IEVycm9yKGAke2Fzc2VydGlvbk5hbWV9IHdpdGggZGlmZmVyZW50IHNuYXBzaG90cyBjYW5ub3QgYmUgY2FsbGVkIGF0IHRoZSBzYW1lIGxvY2F0aW9uYCksIHtcblx0XHRcdFx0XHRhY3R1YWw6IHNuYXBzaG90LFxuXHRcdFx0XHRcdGV4cGVjdGVkOiBkaWZmZXJlbnRTbmFwc2hvdC5zbmFwc2hvdFxuXHRcdFx0XHR9KTtcblx0XHRcdH1cblx0XHR9XG5cdFx0dGhpcy5faW5saW5lU25hcHNob3RTdGFja3MucHVzaCh7XG5cdFx0XHQuLi5zdGFjayxcblx0XHRcdHRlc3RJZCxcblx0XHRcdHNuYXBzaG90XG5cdFx0fSk7XG5cdFx0cmV0dXJuIHN0YWNrO1xuXHR9XG5cdF9yZWNvbmNpbGUob3B0cykge1xuXHRcdC8vIFRoZXNlIGFyZSB0aGUgY29uZGl0aW9ucyBvbiB3aGVuIHRvIHdyaXRlIHNuYXBzaG90czpcblx0XHQvLyAgKiBUaGVyZSdzIG5vIHNuYXBzaG90IGZpbGUgaW4gYSBub24tQ0kgZW52aXJvbm1lbnQuXG5cdFx0Ly8gICogVGhlcmUgaXMgYSBzbmFwc2hvdCBmaWxlIGFuZCB3ZSBkZWNpZGVkIHRvIHVwZGF0ZSB0aGUgc25hcHNob3QuXG5cdFx0Ly8gICogVGhlcmUgaXMgYSBzbmFwc2hvdCBmaWxlLCBidXQgaXQgZG9lc24ndCBoYXZlIHRoaXMgc25hcHNob3QuXG5cdFx0Ly8gVGhlc2UgYXJlIHRoZSBjb25kaXRpb25zIG9uIHdoZW4gbm90IHRvIHdyaXRlIHNuYXBzaG90czpcblx0XHQvLyAgKiBUaGUgdXBkYXRlIGZsYWcgaXMgc2V0IHRvICdub25lJy5cblx0XHQvLyAgKiBUaGVyZSdzIG5vIHNuYXBzaG90IGZpbGUgb3IgYSBmaWxlIHdpdGhvdXQgdGhpcyBzbmFwc2hvdCBvbiBhIENJIGVudmlyb25tZW50LlxuXHRcdGlmIChvcHRzLmhhc1NuYXBzaG90ICYmIHRoaXMuX3VwZGF0ZVNuYXBzaG90ID09PSBcImFsbFwiIHx8ICghb3B0cy5oYXNTbmFwc2hvdCB8fCAhb3B0cy5zbmFwc2hvdElzUGVyc2lzdGVkKSAmJiAodGhpcy5fdXBkYXRlU25hcHNob3QgPT09IFwibmV3XCIgfHwgdGhpcy5fdXBkYXRlU25hcHNob3QgPT09IFwiYWxsXCIpKSB7XG5cdFx0XHRpZiAodGhpcy5fdXBkYXRlU25hcHNob3QgPT09IFwiYWxsXCIpIHtcblx0XHRcdFx0aWYgKCFvcHRzLnBhc3MpIHtcblx0XHRcdFx0XHRpZiAob3B0cy5oYXNTbmFwc2hvdCkge1xuXHRcdFx0XHRcdFx0dGhpcy51cGRhdGVkLmluY3JlbWVudChvcHRzLnRlc3RJZCk7XG5cdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdHRoaXMuYWRkZWQuaW5jcmVtZW50KG9wdHMudGVzdElkKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0dGhpcy5fYWRkU25hcHNob3Qob3B0cy5rZXksIG9wdHMuYWRkVmFsdWUsIHtcblx0XHRcdFx0XHRcdHN0YWNrOiBvcHRzLnN0YWNrLFxuXHRcdFx0XHRcdFx0dGVzdElkOiBvcHRzLnRlc3RJZCxcblx0XHRcdFx0XHRcdHJhd1NuYXBzaG90OiBvcHRzLnJhd1NuYXBzaG90LFxuXHRcdFx0XHRcdFx0YXNzZXJ0aW9uTmFtZTogb3B0cy5hc3NlcnRpb25OYW1lXG5cdFx0XHRcdFx0fSk7XG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0dGhpcy5tYXRjaGVkLmluY3JlbWVudChvcHRzLnRlc3RJZCk7XG5cdFx0XHRcdH1cblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdHRoaXMuX2FkZFNuYXBzaG90KG9wdHMua2V5LCBvcHRzLmFkZFZhbHVlLCB7XG5cdFx0XHRcdFx0c3RhY2s6IG9wdHMuc3RhY2ssXG5cdFx0XHRcdFx0dGVzdElkOiBvcHRzLnRlc3RJZCxcblx0XHRcdFx0XHRyYXdTbmFwc2hvdDogb3B0cy5yYXdTbmFwc2hvdCxcblx0XHRcdFx0XHRhc3NlcnRpb25OYW1lOiBvcHRzLmFzc2VydGlvbk5hbWVcblx0XHRcdFx0fSk7XG5cdFx0XHRcdHRoaXMuYWRkZWQuaW5jcmVtZW50KG9wdHMudGVzdElkKTtcblx0XHRcdH1cblx0XHRcdHJldHVybiB7XG5cdFx0XHRcdGFjdHVhbDogXCJcIixcblx0XHRcdFx0Y291bnQ6IG9wdHMuY291bnQsXG5cdFx0XHRcdGV4cGVjdGVkOiBcIlwiLFxuXHRcdFx0XHRrZXk6IG9wdHMua2V5LFxuXHRcdFx0XHRwYXNzOiB0cnVlXG5cdFx0XHR9O1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRpZiAoIW9wdHMucGFzcykge1xuXHRcdFx0XHR0aGlzLnVubWF0Y2hlZC5pbmNyZW1lbnQob3B0cy50ZXN0SWQpO1xuXHRcdFx0XHRyZXR1cm4ge1xuXHRcdFx0XHRcdGFjdHVhbDogb3B0cy5hY3R1YWxEaXNwbGF5LFxuXHRcdFx0XHRcdGNvdW50OiBvcHRzLmNvdW50LFxuXHRcdFx0XHRcdGV4cGVjdGVkOiBvcHRzLmV4cGVjdGVkRGlzcGxheSxcblx0XHRcdFx0XHRrZXk6IG9wdHMua2V5LFxuXHRcdFx0XHRcdHBhc3M6IGZhbHNlXG5cdFx0XHRcdH07XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHR0aGlzLm1hdGNoZWQuaW5jcmVtZW50KG9wdHMudGVzdElkKTtcblx0XHRcdFx0cmV0dXJuIHtcblx0XHRcdFx0XHRhY3R1YWw6IFwiXCIsXG5cdFx0XHRcdFx0Y291bnQ6IG9wdHMuY291bnQsXG5cdFx0XHRcdFx0ZXhwZWN0ZWQ6IFwiXCIsXG5cdFx0XHRcdFx0a2V5OiBvcHRzLmtleSxcblx0XHRcdFx0XHRwYXNzOiB0cnVlXG5cdFx0XHRcdH07XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cdGFzeW5jIHNhdmUoKSB7XG5cdFx0Y29uc3QgaGFzRXh0ZXJuYWxTbmFwc2hvdHMgPSBPYmplY3Qua2V5cyh0aGlzLl9zbmFwc2hvdERhdGEpLmxlbmd0aDtcblx0XHRjb25zdCBoYXNJbmxpbmVTbmFwc2hvdHMgPSB0aGlzLl9pbmxpbmVTbmFwc2hvdHMubGVuZ3RoO1xuXHRcdGNvbnN0IGhhc1Jhd1NuYXBzaG90cyA9IHRoaXMuX3Jhd1NuYXBzaG90cy5sZW5ndGg7XG5cdFx0Y29uc3QgaXNFbXB0eSA9ICFoYXNFeHRlcm5hbFNuYXBzaG90cyAmJiAhaGFzSW5saW5lU25hcHNob3RzICYmICFoYXNSYXdTbmFwc2hvdHM7XG5cdFx0Y29uc3Qgc3RhdHVzID0ge1xuXHRcdFx0ZGVsZXRlZDogZmFsc2UsXG5cdFx0XHRzYXZlZDogZmFsc2Vcblx0XHR9O1xuXHRcdGlmICgodGhpcy5fZGlydHkgfHwgdGhpcy5fdW5jaGVja2VkS2V5cy5zaXplKSAmJiAhaXNFbXB0eSkge1xuXHRcdFx0aWYgKGhhc0V4dGVybmFsU25hcHNob3RzKSB7XG5cdFx0XHRcdGF3YWl0IHNhdmVTbmFwc2hvdEZpbGUodGhpcy5fZW52aXJvbm1lbnQsIHRoaXMuX3NuYXBzaG90RGF0YSwgdGhpcy5zbmFwc2hvdFBhdGgpO1xuXHRcdFx0XHR0aGlzLl9maWxlRXhpc3RzID0gdHJ1ZTtcblx0XHRcdH1cblx0XHRcdGlmIChoYXNJbmxpbmVTbmFwc2hvdHMpIHtcblx0XHRcdFx0YXdhaXQgc2F2ZUlubGluZVNuYXBzaG90cyh0aGlzLl9lbnZpcm9ubWVudCwgdGhpcy5faW5saW5lU25hcHNob3RzKTtcblx0XHRcdH1cblx0XHRcdGlmIChoYXNSYXdTbmFwc2hvdHMpIHtcblx0XHRcdFx0YXdhaXQgc2F2ZVJhd1NuYXBzaG90cyh0aGlzLl9lbnZpcm9ubWVudCwgdGhpcy5fcmF3U25hcHNob3RzKTtcblx0XHRcdH1cblx0XHRcdHN0YXR1cy5zYXZlZCA9IHRydWU7XG5cdFx0fSBlbHNlIGlmICghaGFzRXh0ZXJuYWxTbmFwc2hvdHMgJiYgdGhpcy5fZmlsZUV4aXN0cykge1xuXHRcdFx0aWYgKHRoaXMuX3VwZGF0ZVNuYXBzaG90ID09PSBcImFsbFwiKSB7XG5cdFx0XHRcdGF3YWl0IHRoaXMuX2Vudmlyb25tZW50LnJlbW92ZVNuYXBzaG90RmlsZSh0aGlzLnNuYXBzaG90UGF0aCk7XG5cdFx0XHRcdHRoaXMuX2ZpbGVFeGlzdHMgPSBmYWxzZTtcblx0XHRcdH1cblx0XHRcdHN0YXR1cy5kZWxldGVkID0gdHJ1ZTtcblx0XHR9XG5cdFx0cmV0dXJuIHN0YXR1cztcblx0fVxuXHRnZXRVbmNoZWNrZWRDb3VudCgpIHtcblx0XHRyZXR1cm4gdGhpcy5fdW5jaGVja2VkS2V5cy5zaXplIHx8IDA7XG5cdH1cblx0Z2V0VW5jaGVja2VkS2V5cygpIHtcblx0XHRyZXR1cm4gQXJyYXkuZnJvbSh0aGlzLl91bmNoZWNrZWRLZXlzKTtcblx0fVxuXHRyZW1vdmVVbmNoZWNrZWRLZXlzKCkge1xuXHRcdGlmICh0aGlzLl91cGRhdGVTbmFwc2hvdCA9PT0gXCJhbGxcIiAmJiB0aGlzLl91bmNoZWNrZWRLZXlzLnNpemUpIHtcblx0XHRcdHRoaXMuX2RpcnR5ID0gdHJ1ZTtcblx0XHRcdHRoaXMuX3VuY2hlY2tlZEtleXMuZm9yRWFjaCgoa2V5KSA9PiBkZWxldGUgdGhpcy5fc25hcHNob3REYXRhW2tleV0pO1xuXHRcdFx0dGhpcy5fdW5jaGVja2VkS2V5cy5jbGVhcigpO1xuXHRcdH1cblx0fVxuXHRwcm9iZUV4cGVjdGVkU25hcHNob3Qob3B0aW9ucykge1xuXHRcdGNvbnN0IGNvdW50ID0gdGhpcy5fY291bnRlcnMuZ2V0KG9wdGlvbnMudGVzdE5hbWUpICsgMTtcblx0XHRjb25zdCBrZXkgPSB0ZXN0TmFtZVRvS2V5KG9wdGlvbnMudGVzdE5hbWUsIGNvdW50KTtcblx0XHRyZXR1cm4ge1xuXHRcdFx0a2V5LFxuXHRcdFx0Y291bnQsXG5cdFx0XHRkYXRhOiBvcHRpb25zPy5pc0lubGluZSA/IG9wdGlvbnMuaW5saW5lU25hcHNob3QgOiB0aGlzLl9zbmFwc2hvdERhdGFba2V5XSxcblx0XHRcdG1hcmtBc0NoZWNrZWQ6ICgpID0+IHtcblx0XHRcdFx0dGhpcy5fY291bnRlcnMuaW5jcmVtZW50KG9wdGlvbnMudGVzdE5hbWUpO1xuXHRcdFx0XHR0aGlzLl90ZXN0SWRUb0tleXMuZ2V0KG9wdGlvbnMudGVzdElkKS5wdXNoKGtleSk7XG5cdFx0XHRcdHRoaXMuX3VuY2hlY2tlZEtleXMuZGVsZXRlKGtleSk7XG5cdFx0XHR9XG5cdFx0fTtcblx0fVxuXHRtYXRjaCh7IHRlc3RJZCwgdGVzdE5hbWUsIHJlY2VpdmVkLCBrZXksIGlubGluZVNuYXBzaG90LCBpc0lubGluZSwgZXJyb3IsIHJhd1NuYXBzaG90LCBhc3NlcnRpb25OYW1lIH0pIHtcblx0XHRjb25zdCByZXNvbHZlZCA9IHRoaXMuX3Jlc29sdmVLZXkodGVzdElkLCB0ZXN0TmFtZSwga2V5KTtcblx0XHRrZXkgPSByZXNvbHZlZC5rZXk7XG5cdFx0Y29uc3QgY291bnQgPSByZXNvbHZlZC5jb3VudDtcblx0XHQvLyBEbyBub3QgbWFyayB0aGUgc25hcHNob3QgYXMgXCJjaGVja2VkXCIgaWYgdGhlIHNuYXBzaG90IGlzIGlubGluZSBhbmRcblx0XHQvLyB0aGVyZSdzIGFuIGV4dGVybmFsIHNuYXBzaG90LiBUaGlzIHdheSB0aGUgZXh0ZXJuYWwgc25hcHNob3QgY2FuIGJlXG5cdFx0Ly8gcmVtb3ZlZCB3aXRoIGAtLXVwZGF0ZVNuYXBzaG90YC5cblx0XHRpZiAoIShpc0lubGluZSAmJiB0aGlzLl9zbmFwc2hvdERhdGFba2V5XSAhPT0gdW5kZWZpbmVkKSkge1xuXHRcdFx0dGhpcy5fdW5jaGVja2VkS2V5cy5kZWxldGUoa2V5KTtcblx0XHR9XG5cdFx0bGV0IHJlY2VpdmVkU2VyaWFsaXplZCA9IHJhd1NuYXBzaG90ICYmIHR5cGVvZiByZWNlaXZlZCA9PT0gXCJzdHJpbmdcIiA/IHJlY2VpdmVkIDogc2VyaWFsaXplKHJlY2VpdmVkLCB1bmRlZmluZWQsIHRoaXMuX3NuYXBzaG90Rm9ybWF0KTtcblx0XHRpZiAoIXJhd1NuYXBzaG90KSB7XG5cdFx0XHRyZWNlaXZlZFNlcmlhbGl6ZWQgPSBhZGRFeHRyYUxpbmVCcmVha3MocmVjZWl2ZWRTZXJpYWxpemVkKTtcblx0XHR9XG5cdFx0aWYgKHJhd1NuYXBzaG90KSB7XG5cdFx0XHQvLyBub3JtYWxpemUgRU9MIHdoZW4gc25hcHNob3QgY29udGFpbnMgQ1JMRiBidXQgcmVjZWl2ZWQgaXMgTEZcblx0XHRcdGlmIChyYXdTbmFwc2hvdC5jb250ZW50ICYmIHJhd1NuYXBzaG90LmNvbnRlbnQubWF0Y2goL1xcclxcbi8pICYmICFyZWNlaXZlZFNlcmlhbGl6ZWQubWF0Y2goL1xcclxcbi8pKSB7XG5cdFx0XHRcdHJhd1NuYXBzaG90LmNvbnRlbnQgPSBub3JtYWxpemVOZXdsaW5lcyhyYXdTbmFwc2hvdC5jb250ZW50KTtcblx0XHRcdH1cblx0XHR9XG5cdFx0Y29uc3QgZXhwZWN0ZWQgPSBpc0lubGluZSA/IGlubGluZVNuYXBzaG90IDogcmF3U25hcHNob3QgPyByYXdTbmFwc2hvdC5jb250ZW50IDogdGhpcy5fc25hcHNob3REYXRhW2tleV07XG5cdFx0Y29uc3QgZXhwZWN0ZWRUcmltbWVkID0gcmF3U25hcHNob3QgPyBleHBlY3RlZCA6IGV4cGVjdGVkPy50cmltKCk7XG5cdFx0Y29uc3QgcGFzcyA9IGV4cGVjdGVkVHJpbW1lZCA9PT0gKHJhd1NuYXBzaG90ID8gcmVjZWl2ZWRTZXJpYWxpemVkIDogcmVjZWl2ZWRTZXJpYWxpemVkLnRyaW0oKSk7XG5cdFx0Y29uc3QgaGFzU25hcHNob3QgPSBleHBlY3RlZCAhPT0gdW5kZWZpbmVkO1xuXHRcdGNvbnN0IHNuYXBzaG90SXNQZXJzaXN0ZWQgPSBpc0lubGluZSB8fCB0aGlzLl9maWxlRXhpc3RzIHx8IHJhd1NuYXBzaG90ICYmIHJhd1NuYXBzaG90LmNvbnRlbnQgIT0gbnVsbDtcblx0XHRpZiAocGFzcyAmJiAhaXNJbmxpbmUgJiYgIXJhd1NuYXBzaG90KSB7XG5cdFx0XHQvLyBXaGVuIHRoZSBmaWxlIGlzIHJlLXNhdmVkIChiZWNhdXNlIG90aGVyIHNuYXBzaG90cyBjaGFuZ2VkKSwgdGhlIEpTXG5cdFx0XHQvLyByb3VuZC10cmlwIGNhbiBsb3NlIHByb3BlciBlc2NhcGluZy4gUmVmcmVzaCBpbi1tZW1vcnkgZGF0YSB3aXRoIHRoZVxuXHRcdFx0Ly8gZnJlc2hseSBzZXJpYWxpemVkIHN0cmluZyBzbyB0aGUgZmlsZSBpcyB3cml0dGVuIGNvcnJlY3RseS5cblx0XHRcdC8vIF9yZWNvbmNpbGUgZG9lcyBub3Qgd3JpdGUgX3NuYXBzaG90RGF0YSBvbiBwYXNzLCBzbyB0aGlzIGlzIHRoZSBvbmx5XG5cdFx0XHQvLyBwbGFjZSBpdCBnZXRzIHJlZnJlc2hlZC4gRG9tYWluIHNuYXBzaG90cyBza2lwIHRoaXMgYmVjYXVzZSB0aGUgc3RvcmVkXG5cdFx0XHQvLyB2YWx1ZSBtYXkgY29udGFpbiBtYXRjaCBwYXR0ZXJucyB0aGF0IGRpZmZlciBmcm9tIHRoZSByZWNlaXZlZCBvdXRwdXQuXG5cdFx0XHR0aGlzLl9zbmFwc2hvdERhdGFba2V5XSA9IHJlY2VpdmVkU2VyaWFsaXplZDtcblx0XHR9XG5cdFx0Y29uc3Qgc3RhY2sgPSBpc0lubGluZSA/IHRoaXMuX3Jlc29sdmVJbmxpbmVTdGFjayh7XG5cdFx0XHR0ZXN0SWQsXG5cdFx0XHRzbmFwc2hvdDogcmVjZWl2ZWRTZXJpYWxpemVkLFxuXHRcdFx0YXNzZXJ0aW9uTmFtZTogYXNzZXJ0aW9uTmFtZSB8fCBcInRvTWF0Y2hJbmxpbmVTbmFwc2hvdFwiLFxuXHRcdFx0ZXJyb3I6IGVycm9yIHx8IG5ldyBFcnJvcihcInNuYXBzaG90XCIpXG5cdFx0fSkgOiB1bmRlZmluZWQ7XG5cdFx0cmV0dXJuIHRoaXMuX3JlY29uY2lsZSh7XG5cdFx0XHR0ZXN0SWQsXG5cdFx0XHRrZXksXG5cdFx0XHRjb3VudCxcblx0XHRcdHBhc3MsXG5cdFx0XHRoYXNTbmFwc2hvdCxcblx0XHRcdHNuYXBzaG90SXNQZXJzaXN0ZWQ6ICEhc25hcHNob3RJc1BlcnNpc3RlZCxcblx0XHRcdGFkZFZhbHVlOiByZWNlaXZlZFNlcmlhbGl6ZWQsXG5cdFx0XHRhY3R1YWxEaXNwbGF5OiByYXdTbmFwc2hvdCA/IHJlY2VpdmVkU2VyaWFsaXplZCA6IHJlbW92ZUV4dHJhTGluZUJyZWFrcyhyZWNlaXZlZFNlcmlhbGl6ZWQpLFxuXHRcdFx0ZXhwZWN0ZWREaXNwbGF5OiBleHBlY3RlZFRyaW1tZWQgIT09IHVuZGVmaW5lZCA/IHJhd1NuYXBzaG90ID8gZXhwZWN0ZWRUcmltbWVkIDogcmVtb3ZlRXh0cmFMaW5lQnJlYWtzKGV4cGVjdGVkVHJpbW1lZCkgOiB1bmRlZmluZWQsXG5cdFx0XHRzdGFjayxcblx0XHRcdHJhd1NuYXBzaG90LFxuXHRcdFx0YXNzZXJ0aW9uTmFtZVxuXHRcdH0pO1xuXHR9XG5cdHByb2Nlc3NEb21haW5TbmFwc2hvdCh7IHRlc3RJZCwgcmVjZWl2ZWQsIGV4cGVjdGVkU25hcHNob3QsIG1hdGNoUmVzdWx0LCBpc0lubGluZSwgZXJyb3IsIGFzc2VydGlvbk5hbWUgfSkge1xuXHRcdGNvbnN0IHN0YWNrID0gaXNJbmxpbmUgPyB0aGlzLl9yZXNvbHZlSW5saW5lU3RhY2soe1xuXHRcdFx0dGVzdElkLFxuXHRcdFx0c25hcHNob3Q6IHJlY2VpdmVkLFxuXHRcdFx0YXNzZXJ0aW9uTmFtZSxcblx0XHRcdGVycm9yOiBlcnJvciB8fCBuZXcgRXJyb3IoXCJTVEFDS19UUkFDRV9FUlJPUlwiKVxuXHRcdH0pIDogdW5kZWZpbmVkO1xuXHRcdGNvbnN0IGFjdHVhbFJlc29sdmVkID0gbWF0Y2hSZXN1bHQ/LnJlc29sdmVkID8/IHJlY2VpdmVkO1xuXHRcdGNvbnN0IGV4cGVjdGVkUmVzb2x2ZWQgPSBtYXRjaFJlc3VsdD8uZXhwZWN0ZWQgPz8gZXhwZWN0ZWRTbmFwc2hvdC5kYXRhO1xuXHRcdHJldHVybiB0aGlzLl9yZWNvbmNpbGUoe1xuXHRcdFx0dGVzdElkLFxuXHRcdFx0a2V5OiBleHBlY3RlZFNuYXBzaG90LmtleSxcblx0XHRcdGNvdW50OiBleHBlY3RlZFNuYXBzaG90LmNvdW50LFxuXHRcdFx0cGFzczogbWF0Y2hSZXN1bHQ/LnBhc3MgPz8gZmFsc2UsXG5cdFx0XHRoYXNTbmFwc2hvdDogISFleHBlY3RlZFNuYXBzaG90LmRhdGEsXG5cdFx0XHRzbmFwc2hvdElzUGVyc2lzdGVkOiBpc0lubGluZSA/IHRydWUgOiB0aGlzLl9maWxlRXhpc3RzLFxuXHRcdFx0YWRkVmFsdWU6IGFjdHVhbFJlc29sdmVkLFxuXHRcdFx0YWN0dWFsRGlzcGxheTogcmVtb3ZlRXh0cmFMaW5lQnJlYWtzKGFjdHVhbFJlc29sdmVkKSxcblx0XHRcdGV4cGVjdGVkRGlzcGxheTogZXhwZWN0ZWRSZXNvbHZlZCAhPT0gdW5kZWZpbmVkID8gcmVtb3ZlRXh0cmFMaW5lQnJlYWtzKGV4cGVjdGVkUmVzb2x2ZWQpIDogdW5kZWZpbmVkLFxuXHRcdFx0c3RhY2ssXG5cdFx0XHRhc3NlcnRpb25OYW1lXG5cdFx0fSk7XG5cdH1cblx0YXN5bmMgcGFjaygpIHtcblx0XHRjb25zdCBzbmFwc2hvdCA9IHtcblx0XHRcdGZpbGVwYXRoOiB0aGlzLnRlc3RGaWxlUGF0aCxcblx0XHRcdGFkZGVkOiAwLFxuXHRcdFx0ZmlsZURlbGV0ZWQ6IGZhbHNlLFxuXHRcdFx0bWF0Y2hlZDogMCxcblx0XHRcdHVuY2hlY2tlZDogMCxcblx0XHRcdHVuY2hlY2tlZEtleXM6IFtdLFxuXHRcdFx0dW5tYXRjaGVkOiAwLFxuXHRcdFx0dXBkYXRlZDogMFxuXHRcdH07XG5cdFx0Y29uc3QgdW5jaGVja2VkQ291bnQgPSB0aGlzLmdldFVuY2hlY2tlZENvdW50KCk7XG5cdFx0Y29uc3QgdW5jaGVja2VkS2V5cyA9IHRoaXMuZ2V0VW5jaGVja2VkS2V5cygpO1xuXHRcdGlmICh1bmNoZWNrZWRDb3VudCkge1xuXHRcdFx0dGhpcy5yZW1vdmVVbmNoZWNrZWRLZXlzKCk7XG5cdFx0fVxuXHRcdGNvbnN0IHN0YXR1cyA9IGF3YWl0IHRoaXMuc2F2ZSgpO1xuXHRcdHNuYXBzaG90LmZpbGVEZWxldGVkID0gc3RhdHVzLmRlbGV0ZWQ7XG5cdFx0c25hcHNob3QuYWRkZWQgPSB0aGlzLmFkZGVkLnRvdGFsKCk7XG5cdFx0c25hcHNob3QubWF0Y2hlZCA9IHRoaXMubWF0Y2hlZC50b3RhbCgpO1xuXHRcdHNuYXBzaG90LnVubWF0Y2hlZCA9IHRoaXMudW5tYXRjaGVkLnRvdGFsKCk7XG5cdFx0c25hcHNob3QudXBkYXRlZCA9IHRoaXMudXBkYXRlZC50b3RhbCgpO1xuXHRcdHNuYXBzaG90LnVuY2hlY2tlZCA9ICFzdGF0dXMuZGVsZXRlZCA/IHVuY2hlY2tlZENvdW50IDogMDtcblx0XHRzbmFwc2hvdC51bmNoZWNrZWRLZXlzID0gQXJyYXkuZnJvbSh1bmNoZWNrZWRLZXlzKTtcblx0XHRyZXR1cm4gc25hcHNob3Q7XG5cdH1cbn1cblxuZnVuY3Rpb24gY3JlYXRlTWlzbWF0Y2hFcnJvcihtZXNzYWdlLCBleHBhbmQsIGFjdHVhbCwgZXhwZWN0ZWQpIHtcblx0Y29uc3QgZXJyb3IgPSBuZXcgRXJyb3IobWVzc2FnZSk7XG5cdE9iamVjdC5kZWZpbmVQcm9wZXJ0eShlcnJvciwgXCJhY3R1YWxcIiwge1xuXHRcdHZhbHVlOiBhY3R1YWwsXG5cdFx0ZW51bWVyYWJsZTogdHJ1ZSxcblx0XHRjb25maWd1cmFibGU6IHRydWUsXG5cdFx0d3JpdGFibGU6IHRydWVcblx0fSk7XG5cdE9iamVjdC5kZWZpbmVQcm9wZXJ0eShlcnJvciwgXCJleHBlY3RlZFwiLCB7XG5cdFx0dmFsdWU6IGV4cGVjdGVkLFxuXHRcdGVudW1lcmFibGU6IHRydWUsXG5cdFx0Y29uZmlndXJhYmxlOiB0cnVlLFxuXHRcdHdyaXRhYmxlOiB0cnVlXG5cdH0pO1xuXHRPYmplY3QuZGVmaW5lUHJvcGVydHkoZXJyb3IsIFwiZGlmZk9wdGlvbnNcIiwgeyB2YWx1ZTogeyBleHBhbmQgfSB9KTtcblx0cmV0dXJuIGVycm9yO1xufVxuY2xhc3MgU25hcHNob3RDbGllbnQge1xuXHRzbmFwc2hvdFN0YXRlTWFwID0gbmV3IE1hcCgpO1xuXHRjb25zdHJ1Y3RvcihvcHRpb25zID0ge30pIHtcblx0XHR0aGlzLm9wdGlvbnMgPSBvcHRpb25zO1xuXHR9XG5cdGFzeW5jIHNldHVwKGZpbGVwYXRoLCBvcHRpb25zKSB7XG5cdFx0aWYgKHRoaXMuc25hcHNob3RTdGF0ZU1hcC5oYXMoZmlsZXBhdGgpKSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXHRcdHRoaXMuc25hcHNob3RTdGF0ZU1hcC5zZXQoZmlsZXBhdGgsIGF3YWl0IFNuYXBzaG90U3RhdGUuY3JlYXRlKGZpbGVwYXRoLCBvcHRpb25zKSk7XG5cdH1cblx0YXN5bmMgZmluaXNoKGZpbGVwYXRoKSB7XG5cdFx0Y29uc3Qgc3RhdGUgPSB0aGlzLmdldFNuYXBzaG90U3RhdGUoZmlsZXBhdGgpO1xuXHRcdGNvbnN0IHJlc3VsdCA9IGF3YWl0IHN0YXRlLnBhY2soKTtcblx0XHR0aGlzLnNuYXBzaG90U3RhdGVNYXAuZGVsZXRlKGZpbGVwYXRoKTtcblx0XHRyZXR1cm4gcmVzdWx0O1xuXHR9XG5cdHNraXBUZXN0KGZpbGVwYXRoLCB0ZXN0TmFtZSkge1xuXHRcdGNvbnN0IHN0YXRlID0gdGhpcy5nZXRTbmFwc2hvdFN0YXRlKGZpbGVwYXRoKTtcblx0XHRzdGF0ZS5tYXJrU25hcHNob3RzQXNDaGVja2VkRm9yVGVzdCh0ZXN0TmFtZSk7XG5cdH1cblx0Y2xlYXJUZXN0KGZpbGVwYXRoLCB0ZXN0SWQpIHtcblx0XHRjb25zdCBzdGF0ZSA9IHRoaXMuZ2V0U25hcHNob3RTdGF0ZShmaWxlcGF0aCk7XG5cdFx0c3RhdGUuY2xlYXJUZXN0KHRlc3RJZCk7XG5cdH1cblx0Z2V0U25hcHNob3RTdGF0ZShmaWxlcGF0aCkge1xuXHRcdGNvbnN0IHN0YXRlID0gdGhpcy5zbmFwc2hvdFN0YXRlTWFwLmdldChmaWxlcGF0aCk7XG5cdFx0aWYgKCFzdGF0ZSkge1xuXHRcdFx0dGhyb3cgbmV3IEVycm9yKGBUaGUgc25hcHNob3Qgc3RhdGUgZm9yICcke2ZpbGVwYXRofScgaXMgbm90IGZvdW5kLiBEaWQgeW91IGNhbGwgJ1NuYXBzaG90Q2xpZW50LnNldHVwKCknP2ApO1xuXHRcdH1cblx0XHRyZXR1cm4gc3RhdGU7XG5cdH1cblx0bWF0Y2gob3B0aW9ucykge1xuXHRcdGNvbnN0IHsgZmlsZXBhdGgsIG5hbWUsIHRlc3RJZCA9IG5hbWUsIG1lc3NhZ2UsIGlzSW5saW5lID0gZmFsc2UsIHByb3BlcnRpZXMsIGlubGluZVNuYXBzaG90LCBlcnJvciwgZXJyb3JNZXNzYWdlLCByYXdTbmFwc2hvdCwgYXNzZXJ0aW9uTmFtZSB9ID0gb3B0aW9ucztcblx0XHRsZXQgeyByZWNlaXZlZCB9ID0gb3B0aW9ucztcblx0XHRpZiAoIWZpbGVwYXRoKSB7XG5cdFx0XHR0aHJvdyBuZXcgRXJyb3IoXCJTbmFwc2hvdCBjYW5ub3QgYmUgdXNlZCBvdXRzaWRlIG9mIHRlc3RcIik7XG5cdFx0fVxuXHRcdGNvbnN0IHNuYXBzaG90U3RhdGUgPSB0aGlzLmdldFNuYXBzaG90U3RhdGUoZmlsZXBhdGgpO1xuXHRcdGNvbnN0IHRlc3ROYW1lID0gW25hbWUsIC4uLm1lc3NhZ2UgPyBbbWVzc2FnZV0gOiBbXV0uam9pbihcIiA+IFwiKTtcblx0XHQvLyBQcm9iZSBmaXJzdCBzbyB3ZSBjYW4gbWFyayBhcyBjaGVja2VkIGV2ZW4gb24gZWFybHkgcmV0dXJuXG5cdFx0Y29uc3QgZXhwZWN0ZWRTbmFwc2hvdCA9IHNuYXBzaG90U3RhdGUucHJvYmVFeHBlY3RlZFNuYXBzaG90KHtcblx0XHRcdHRlc3ROYW1lLFxuXHRcdFx0dGVzdElkLFxuXHRcdFx0aXNJbmxpbmUsXG5cdFx0XHRpbmxpbmVTbmFwc2hvdFxuXHRcdH0pO1xuXHRcdGlmICh0eXBlb2YgcHJvcGVydGllcyA9PT0gXCJvYmplY3RcIikge1xuXHRcdFx0aWYgKHR5cGVvZiByZWNlaXZlZCAhPT0gXCJvYmplY3RcIiB8fCAhcmVjZWl2ZWQpIHtcblx0XHRcdFx0ZXhwZWN0ZWRTbmFwc2hvdC5tYXJrQXNDaGVja2VkKCk7XG5cdFx0XHRcdHRocm93IG5ldyBFcnJvcihcIlJlY2VpdmVkIHZhbHVlIG11c3QgYmUgYW4gb2JqZWN0IHdoZW4gdGhlIG1hdGNoZXIgaGFzIHByb3BlcnRpZXNcIik7XG5cdFx0XHR9XG5cdFx0XHRsZXQgcHJvcGVydGllc1Bhc3M7XG5cdFx0XHR0cnkge1xuXHRcdFx0XHRwcm9wZXJ0aWVzUGFzcyA9IHRoaXMub3B0aW9ucy5pc0VxdWFsPy4ocmVjZWl2ZWQsIHByb3BlcnRpZXMpID8/IGZhbHNlO1xuXHRcdFx0fSBjYXRjaCAoZXJyKSB7XG5cdFx0XHRcdGV4cGVjdGVkU25hcHNob3QubWFya0FzQ2hlY2tlZCgpO1xuXHRcdFx0XHR0aHJvdyBlcnI7XG5cdFx0XHR9XG5cdFx0XHRpZiAoIXByb3BlcnRpZXNQYXNzKSB7XG5cdFx0XHRcdGV4cGVjdGVkU25hcHNob3QubWFya0FzQ2hlY2tlZCgpO1xuXHRcdFx0XHRyZXR1cm4ge1xuXHRcdFx0XHRcdHBhc3M6IGZhbHNlLFxuXHRcdFx0XHRcdG1lc3NhZ2U6ICgpID0+IGVycm9yTWVzc2FnZSB8fCBcIlNuYXBzaG90IHByb3BlcnRpZXMgbWlzbWF0Y2hlZFwiLFxuXHRcdFx0XHRcdGFjdHVhbDogcmVjZWl2ZWQsXG5cdFx0XHRcdFx0ZXhwZWN0ZWQ6IHByb3BlcnRpZXNcblx0XHRcdFx0fTtcblx0XHRcdH1cblx0XHRcdHJlY2VpdmVkID0gZGVlcE1lcmdlU25hcHNob3QocmVjZWl2ZWQsIHByb3BlcnRpZXMpO1xuXHRcdH1cblx0XHRjb25zdCB7IGFjdHVhbCwgZXhwZWN0ZWQsIGtleSwgcGFzcyB9ID0gc25hcHNob3RTdGF0ZS5tYXRjaCh7XG5cdFx0XHR0ZXN0SWQsXG5cdFx0XHR0ZXN0TmFtZSxcblx0XHRcdHJlY2VpdmVkLFxuXHRcdFx0aXNJbmxpbmUsXG5cdFx0XHRlcnJvcixcblx0XHRcdGlubGluZVNuYXBzaG90LFxuXHRcdFx0cmF3U25hcHNob3QsXG5cdFx0XHRhc3NlcnRpb25OYW1lXG5cdFx0fSk7XG5cdFx0cmV0dXJuIHtcblx0XHRcdHBhc3MsXG5cdFx0XHRtZXNzYWdlOiAoKSA9PiBgU25hcHNob3QgXFxgJHtrZXkgfHwgXCJ1bmtub3duXCJ9XFxgIG1pc21hdGNoZWRgLFxuXHRcdFx0YWN0dWFsOiByYXdTbmFwc2hvdCA/IGFjdHVhbCA6IGFjdHVhbD8udHJpbSgpLFxuXHRcdFx0ZXhwZWN0ZWQ6IHJhd1NuYXBzaG90ID8gZXhwZWN0ZWQgOiBleHBlY3RlZD8udHJpbSgpXG5cdFx0fTtcblx0fVxuXHRhc3NlcnQob3B0aW9ucykge1xuXHRcdGNvbnN0IHJlc3VsdCA9IHRoaXMubWF0Y2gob3B0aW9ucyk7XG5cdFx0aWYgKCFyZXN1bHQucGFzcykge1xuXHRcdFx0Y29uc3Qgc25hcHNob3RTdGF0ZSA9IHRoaXMuZ2V0U25hcHNob3RTdGF0ZShvcHRpb25zLmZpbGVwYXRoKTtcblx0XHRcdHRocm93IGNyZWF0ZU1pc21hdGNoRXJyb3IocmVzdWx0Lm1lc3NhZ2UoKSwgc25hcHNob3RTdGF0ZS5leHBhbmQsIHJlc3VsdC5hY3R1YWwsIHJlc3VsdC5leHBlY3RlZCk7XG5cdFx0fVxuXHR9XG5cdG1hdGNoRG9tYWluKG9wdGlvbnMpIHtcblx0XHRjb25zdCB7IHJlY2VpdmVkLCBmaWxlcGF0aCwgbmFtZSwgdGVzdElkID0gbmFtZSwgbWVzc2FnZSwgYWRhcHRlciwgaXNJbmxpbmUgPSBmYWxzZSwgaW5saW5lU25hcHNob3QsIGVycm9yIH0gPSBvcHRpb25zO1xuXHRcdGlmICghZmlsZXBhdGgpIHtcblx0XHRcdHRocm93IG5ldyBFcnJvcihcIlNuYXBzaG90IGNhbm5vdCBiZSB1c2VkIG91dHNpZGUgb2YgdGVzdFwiKTtcblx0XHR9XG5cdFx0Y29uc3QgY2FwdHVyZWQgPSBhZGFwdGVyLmNhcHR1cmUocmVjZWl2ZWQpO1xuXHRcdGNvbnN0IHJlbmRlcmVkID0gYWRhcHRlci5yZW5kZXIoY2FwdHVyZWQpO1xuXHRcdGNvbnN0IHNuYXBzaG90U3RhdGUgPSB0aGlzLmdldFNuYXBzaG90U3RhdGUoZmlsZXBhdGgpO1xuXHRcdGNvbnN0IHRlc3ROYW1lID0gW25hbWUsIC4uLm1lc3NhZ2UgPyBbbWVzc2FnZV0gOiBbXV0uam9pbihcIiA+IFwiKTtcblx0XHRjb25zdCBleHBlY3RlZFNuYXBzaG90ID0gc25hcHNob3RTdGF0ZS5wcm9iZUV4cGVjdGVkU25hcHNob3Qoe1xuXHRcdFx0dGVzdE5hbWUsXG5cdFx0XHR0ZXN0SWQsXG5cdFx0XHRpc0lubGluZSxcblx0XHRcdGlubGluZVNuYXBzaG90XG5cdFx0fSk7XG5cdFx0ZXhwZWN0ZWRTbmFwc2hvdC5tYXJrQXNDaGVja2VkKCk7XG5cdFx0Y29uc3QgbWF0Y2hSZXN1bHQgPSBleHBlY3RlZFNuYXBzaG90LmRhdGEgPyBhZGFwdGVyLm1hdGNoKGNhcHR1cmVkLCBhZGFwdGVyLnBhcnNlRXhwZWN0ZWQoZXhwZWN0ZWRTbmFwc2hvdC5kYXRhKSkgOiB1bmRlZmluZWQ7XG5cdFx0Y29uc3QgeyBhY3R1YWwsIGV4cGVjdGVkLCBrZXksIHBhc3MgfSA9IHNuYXBzaG90U3RhdGUucHJvY2Vzc0RvbWFpblNuYXBzaG90KHtcblx0XHRcdHRlc3RJZCxcblx0XHRcdHJlY2VpdmVkOiByZW5kZXJlZCxcblx0XHRcdGV4cGVjdGVkU25hcHNob3QsXG5cdFx0XHRtYXRjaFJlc3VsdCxcblx0XHRcdGlzSW5saW5lLFxuXHRcdFx0ZXJyb3IsXG5cdFx0XHRhc3NlcnRpb25OYW1lOiBvcHRpb25zLmFzc2VydGlvbk5hbWVcblx0XHR9KTtcblx0XHRyZXR1cm4ge1xuXHRcdFx0cGFzcyxcblx0XHRcdG1lc3NhZ2U6ICgpID0+IGBTbmFwc2hvdCBcXGAke2tleX1cXGAgbWlzbWF0Y2hlZGAsXG5cdFx0XHRhY3R1YWw6IGFjdHVhbD8udHJpbSgpLFxuXHRcdFx0ZXhwZWN0ZWQ6IGV4cGVjdGVkPy50cmltKClcblx0XHR9O1xuXHR9XG5cdGFzeW5jIHBvbGxNYXRjaERvbWFpbihvcHRpb25zKSB7XG5cdFx0Y29uc3QgeyBwb2xsLCBmaWxlcGF0aCwgbmFtZSwgdGVzdElkID0gbmFtZSwgbWVzc2FnZSwgYWRhcHRlciwgaXNJbmxpbmUgPSBmYWxzZSwgaW5saW5lU25hcHNob3QsIGVycm9yLCB0aW1lb3V0ID0gMWUzLCBpbnRlcnZhbCA9IDUwIH0gPSBvcHRpb25zO1xuXHRcdGlmICghZmlsZXBhdGgpIHtcblx0XHRcdHRocm93IG5ldyBFcnJvcihcIlNuYXBzaG90IGNhbm5vdCBiZSB1c2VkIG91dHNpZGUgb2YgdGVzdFwiKTtcblx0XHR9XG5cdFx0Y29uc3Qgc25hcHNob3RTdGF0ZSA9IHRoaXMuZ2V0U25hcHNob3RTdGF0ZShmaWxlcGF0aCk7XG5cdFx0Y29uc3QgdGVzdE5hbWUgPSBbbmFtZSwgLi4ubWVzc2FnZSA/IFttZXNzYWdlXSA6IFtdXS5qb2luKFwiID4gXCIpO1xuXHRcdGNvbnN0IGV4cGVjdGVkU25hcHNob3QgPSBzbmFwc2hvdFN0YXRlLnByb2JlRXhwZWN0ZWRTbmFwc2hvdCh7XG5cdFx0XHR0ZXN0TmFtZSxcblx0XHRcdHRlc3RJZCxcblx0XHRcdGlzSW5saW5lLFxuXHRcdFx0aW5saW5lU25hcHNob3Rcblx0XHR9KTtcblx0XHRjb25zdCByZWZlcmVuY2UgPSBleHBlY3RlZFNuYXBzaG90LmRhdGEgJiYgc25hcHNob3RTdGF0ZS5zbmFwc2hvdFVwZGF0ZVN0YXRlICE9PSBcImFsbFwiID8gYWRhcHRlci5wYXJzZUV4cGVjdGVkKGV4cGVjdGVkU25hcHNob3QuZGF0YSkgOiB1bmRlZmluZWQ7XG5cdFx0Y29uc3QgdGltZWRPdXQgPSB0aW1lb3V0ID4gMCA/IG5ldyBQcm9taXNlKChyKSA9PiBzZXRUaW1lb3V0KHIsIHRpbWVvdXQpKSA6IHVuZGVmaW5lZDtcblx0XHRjb25zdCBzdGFibGVSZXN1bHQgPSBhd2FpdCBnZXRTdGFibGVTbmFwc2hvdCh7XG5cdFx0XHRhZGFwdGVyLFxuXHRcdFx0cG9sbCxcblx0XHRcdGludGVydmFsLFxuXHRcdFx0dGltZWRPdXQsXG5cdFx0XHRtYXRjaDogcmVmZXJlbmNlID8gKGNhcHR1cmVkKSA9PiBhZGFwdGVyLm1hdGNoKGNhcHR1cmVkLCByZWZlcmVuY2UpLnBhc3MgOiB1bmRlZmluZWRcblx0XHR9KTtcblx0XHRleHBlY3RlZFNuYXBzaG90Lm1hcmtBc0NoZWNrZWQoKTtcblx0XHRpZiAoIXN0YWJsZVJlc3VsdD8ucmVuZGVyZWQpIHtcblx0XHRcdC8vIHRoZSBvcmlnaW5hbCBjYWxsZXIgYGV4cGVjdC5wb2xsYCBsYXRlciBtYW5pcHVsYXRlcyBlcnJvciB2aWEgYHRocm93V2l0aENhdXNlYCxcblx0XHRcdC8vIHNvIGhlcmUgd2UgY2FuIGRpcmVjdGx5IHRocm93IGBsYXN0UG9sbEVycm9yYCBpZiBleGlzdHMuXG5cdFx0XHRpZiAoc3RhYmxlUmVzdWx0Py5sYXN0UG9sbEVycm9yKSB7XG5cdFx0XHRcdHRocm93IHN0YWJsZVJlc3VsdC5sYXN0UG9sbEVycm9yO1xuXHRcdFx0fVxuXHRcdFx0cmV0dXJuIHtcblx0XHRcdFx0cGFzczogZmFsc2UsXG5cdFx0XHRcdG1lc3NhZ2U6ICgpID0+IGBwb2xsKCkgZGlkIG5vdCBwcm9kdWNlIGEgc3RhYmxlIHNuYXBzaG90IHdpdGhpbiB0aGUgdGltZW91dGBcblx0XHRcdH07XG5cdFx0fVxuXHRcdC8vIFRPRE86IHNob3VsZCBgYWxsYCBtb2RlIGlnbm9yZSBwYXJzZSBlcnJvcj9cblx0XHQvLyBTaWVsZW50bHkgaGlkaW5nIHRoZSBlcnJvciBhbmQgY3JlYXRpbmcgc25hcGhzb3QgZnVsbCBzY3JhdGNoIGlzbid0IGdvb2QgZWl0aGVyLlxuXHRcdC8vIFVzZXJzIGNhbiBmaXggb3IgcHVyZ2UgdGhlIGJyb2tlbiBzbmFwc2hvdCBtYW51YWxseSBhbmQgdGhhdCBkZWNpc2lvbiBhZmZlY3RzIGhvdyBkb21haW4gc25hcHNob3QgZ2V0cyB1cGRhdGVkLlxuXHRcdGNvbnN0IG1hdGNoUmVzdWx0ID0gZXhwZWN0ZWRTbmFwc2hvdC5kYXRhID8gYWRhcHRlci5tYXRjaChzdGFibGVSZXN1bHQuY2FwdHVyZWQsIGFkYXB0ZXIucGFyc2VFeHBlY3RlZChleHBlY3RlZFNuYXBzaG90LmRhdGEpKSA6IHVuZGVmaW5lZDtcblx0XHRjb25zdCB7IGFjdHVhbCwgZXhwZWN0ZWQsIGtleSwgcGFzcyB9ID0gc25hcHNob3RTdGF0ZS5wcm9jZXNzRG9tYWluU25hcHNob3Qoe1xuXHRcdFx0dGVzdElkLFxuXHRcdFx0cmVjZWl2ZWQ6IHN0YWJsZVJlc3VsdC5yZW5kZXJlZCxcblx0XHRcdGV4cGVjdGVkU25hcHNob3QsXG5cdFx0XHRtYXRjaFJlc3VsdCxcblx0XHRcdGlzSW5saW5lLFxuXHRcdFx0ZXJyb3IsXG5cdFx0XHRhc3NlcnRpb25OYW1lOiBvcHRpb25zLmFzc2VydGlvbk5hbWVcblx0XHR9KTtcblx0XHRyZXR1cm4ge1xuXHRcdFx0cGFzcyxcblx0XHRcdG1lc3NhZ2U6ICgpID0+IGBTbmFwc2hvdCBcXGAke2tleX1cXGAgbWlzbWF0Y2hlZGAsXG5cdFx0XHRhY3R1YWw6IGFjdHVhbD8udHJpbSgpLFxuXHRcdFx0ZXhwZWN0ZWQ6IGV4cGVjdGVkPy50cmltKClcblx0XHR9O1xuXHR9XG5cdGFzeW5jIGFzc2VydFJhdyhvcHRpb25zKSB7XG5cdFx0aWYgKCFvcHRpb25zLnJhd1NuYXBzaG90KSB7XG5cdFx0XHR0aHJvdyBuZXcgRXJyb3IoXCJSYXcgc25hcHNob3QgaXMgcmVxdWlyZWRcIik7XG5cdFx0fVxuXHRcdGNvbnN0IHsgZmlsZXBhdGgsIHJhd1NuYXBzaG90IH0gPSBvcHRpb25zO1xuXHRcdGlmIChyYXdTbmFwc2hvdC5jb250ZW50ID09IG51bGwpIHtcblx0XHRcdGlmICghZmlsZXBhdGgpIHtcblx0XHRcdFx0dGhyb3cgbmV3IEVycm9yKFwiU25hcHNob3QgY2Fubm90IGJlIHVzZWQgb3V0c2lkZSBvZiB0ZXN0XCIpO1xuXHRcdFx0fVxuXHRcdFx0Y29uc3Qgc25hcHNob3RTdGF0ZSA9IHRoaXMuZ2V0U25hcHNob3RTdGF0ZShmaWxlcGF0aCk7XG5cdFx0XHQvLyBzYXZlIHRoZSBmaWxlcGF0aCwgc28gaXQgZG9uJ3QgbG9zZSBldmVuIGlmIHRoZSBhd2FpdCBtYWtlIGl0IG91dC1vZi1jb250ZXh0XG5cdFx0XHRvcHRpb25zLmZpbGVwYXRoIHx8PSBmaWxlcGF0aDtcblx0XHRcdC8vIHJlc29sdmUgYW5kIHJlYWQgdGhlIHJhdyBzbmFwc2hvdCBmaWxlXG5cdFx0XHRyYXdTbmFwc2hvdC5maWxlID0gYXdhaXQgc25hcHNob3RTdGF0ZS5lbnZpcm9ubWVudC5yZXNvbHZlUmF3UGF0aChmaWxlcGF0aCwgcmF3U25hcHNob3QuZmlsZSk7XG5cdFx0XHRyYXdTbmFwc2hvdC5jb250ZW50ID0gYXdhaXQgc25hcHNob3RTdGF0ZS5lbnZpcm9ubWVudC5yZWFkU25hcHNob3RGaWxlKHJhd1NuYXBzaG90LmZpbGUpID8/IHVuZGVmaW5lZDtcblx0XHR9XG5cdFx0cmV0dXJuIHRoaXMuYXNzZXJ0KG9wdGlvbnMpO1xuXHR9XG5cdGNsZWFyKCkge1xuXHRcdHRoaXMuc25hcHNob3RTdGF0ZU1hcC5jbGVhcigpO1xuXHR9XG59XG4vKipcbiogUG9sbHMgcmVwZWF0ZWRseSB1bnRpbCB0aGUgdmFsdWUgcmVhY2hlcyBhIHN0YWJsZSBzdGF0ZS5cbipcbiogQ29tcGFyZXMgY29uc2VjdXRpdmUgcmVuZGVyZWQgb3V0cHV0cyBmcm9tIHRoZSBjdXJyZW50IHNlc3Npb24g4oCUXG4qIHdoZW4gdHdvIGNvbnNlY3V0aXZlIHBvbGxzIHByb2R1Y2UgdGhlIHNhbWUgcmVuZGVyZWQgc3RyaW5nLFxuKiB0aGUgdmFsdWUgaXMgY29uc2lkZXJlZCBzdGFibGUuXG4qXG4qIEV2ZXJ5IGBhd2FpdGAgKHBvbGwgY2FsbCwgaW50ZXJ2YWwgZGVsYXkpIHJhY2VzIGFnYWluc3QgYHRpbWVkT3V0YFxuKiBzbyB0aGF0IGhhbmdpbmcgcG9sbHMgYW5kIGRlbGF5cyBhcmUgaW50ZXJydXB0ZWQuXG4qL1xuYXN5bmMgZnVuY3Rpb24gZ2V0U3RhYmxlU25hcHNob3QoeyBhZGFwdGVyLCBwb2xsLCBpbnRlcnZhbCwgdGltZWRPdXQsIG1hdGNoIH0pIHtcblx0bGV0IGxhc3RSZW5kZXJlZDtcblx0bGV0IGxhc3RQb2xsRXJyb3I7XG5cdGxldCBsYXN0U3RhYmxlO1xuXHR3aGlsZSAodHJ1ZSkge1xuXHRcdHRyeSB7XG5cdFx0XHRjb25zdCBwb2xsUmVzdWx0ID0gYXdhaXQgcmFjZVdpdGgoUHJvbWlzZS5yZXNvbHZlKHBvbGwoKSksIHRpbWVkT3V0KTtcblx0XHRcdGlmICghcG9sbFJlc3VsdC5vaykge1xuXHRcdFx0XHRicmVhaztcblx0XHRcdH1cblx0XHRcdGNvbnN0IGNhcHR1cmVkID0gYWRhcHRlci5jYXB0dXJlKHBvbGxSZXN1bHQudmFsdWUpO1xuXHRcdFx0Y29uc3QgcmVuZGVyZWQgPSBhZGFwdGVyLnJlbmRlcihjYXB0dXJlZCk7XG5cdFx0XHRpZiAobGFzdFJlbmRlcmVkICE9PSB1bmRlZmluZWQgJiYgcmVuZGVyZWQgPT09IGxhc3RSZW5kZXJlZCkge1xuXHRcdFx0XHRsYXN0U3RhYmxlID0ge1xuXHRcdFx0XHRcdGNhcHR1cmVkLFxuXHRcdFx0XHRcdHJlbmRlcmVkXG5cdFx0XHRcdH07XG5cdFx0XHRcdGlmICghbWF0Y2ggfHwgbWF0Y2goY2FwdHVyZWQpKSB7XG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdH1cblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdGxhc3RSZW5kZXJlZCA9IHJlbmRlcmVkO1xuXHRcdFx0XHRsYXN0U3RhYmxlID0gdW5kZWZpbmVkO1xuXHRcdFx0fVxuXHRcdH0gY2F0Y2ggKHBvbGxFcnJvcikge1xuXHRcdFx0Ly8gcG9sbCgpIHRocmV3IOKAlCByZXNldCBzdGFiaWxpdHkgYmFzZWxpbmUgYW5kIHJldHJ5XG5cdFx0XHRsYXN0UmVuZGVyZWQgPSB1bmRlZmluZWQ7XG5cdFx0XHRsYXN0U3RhYmxlID0gdW5kZWZpbmVkO1xuXHRcdFx0bGFzdFBvbGxFcnJvciA9IHBvbGxFcnJvcjtcblx0XHR9XG5cdFx0Y29uc3QgZGVsYXllZCA9IGF3YWl0IHJhY2VXaXRoKG5ldyBQcm9taXNlKChyKSA9PiBzZXRUaW1lb3V0KHIsIGludGVydmFsKSksIHRpbWVkT3V0KTtcblx0XHRpZiAoIWRlbGF5ZWQub2spIHtcblx0XHRcdGJyZWFrO1xuXHRcdH1cblx0fVxuXHRyZXR1cm4ge1xuXHRcdC4uLmxhc3RTdGFibGUsXG5cdFx0bGFzdFBvbGxFcnJvclxuXHR9O1xufVxuLyoqIFR5cGUtc2FmZSBgUHJvbWlzZS5yYWNlYCDigJQgdGVsbHMgeW91IHdoaWNoIHByb21pc2Ugd29uLiAqL1xuZnVuY3Rpb24gcmFjZVdpdGgocHJvbWlzZSwgb3RoZXIpIHtcblx0Y29uc3QgbGVmdCA9IHByb21pc2UudGhlbigodmFsdWUpID0+ICh7XG5cdFx0b2s6IHRydWUsXG5cdFx0dmFsdWVcblx0fSkpO1xuXHRpZiAoIW90aGVyKSB7XG5cdFx0cmV0dXJuIGxlZnQ7XG5cdH1cblx0cmV0dXJuIFByb21pc2UucmFjZShbbGVmdCwgb3RoZXIudGhlbigodmFsdWUpID0+ICh7XG5cdFx0b2s6IGZhbHNlLFxuXHRcdHZhbHVlXG5cdH0pKV0pO1xufVxuXG5leHBvcnQgeyBTbmFwc2hvdENsaWVudCwgU25hcHNob3RTdGF0ZSwgYWRkU2VyaWFsaXplciwgZ2V0U2VyaWFsaXplcnMsIHN0cmlwU25hcHNob3RJbmRlbnRhdGlvbiB9O1xuIl0sInhfZ29vZ2xlX2lnbm9yZUxpc3QiOlswXSwibWFwcGluZ3MiOiI7Ozs7O0FBS0EsU0FBUyx3QkFBd0IsR0FBRztDQUNuQyxPQUFPLEtBQUssRUFBRSxjQUFjLE9BQU8sVUFBVSxlQUFlLEtBQUssR0FBRyxTQUFTLElBQUksRUFBRSxhQUFhO0FBQ2pHO0FBRUEsSUFBSSxtQkFBbUIsRUFBQyxTQUFTLENBQUMsRUFBQztBQUVuQyxJQUFJO0FBRUosU0FBUyx3QkFBeUI7Q0FDakMsSUFBSSwyQkFBMkIsT0FBTyxpQkFBaUI7Q0FDdkQsNEJBQTRCOzs7Ozs7OztDQVU1QixJQUFJLGlCQUFp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