@envive-ai/react-hooks 0.1.5 → 0.1.6

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 (491) hide show
  1. package/dist/amplitudeContext-CHzas7Cf.d.cts +52 -0
  2. package/dist/amplitudeContext-D-7fmVh1.cjs +356 -0
  3. package/dist/amplitudeContext-hY3caPC6.js +322 -0
  4. package/dist/amplitudeContext-tJ4y-SzX.d.ts +52 -0
  5. package/dist/api-DjeZXxl_.js +207 -0
  6. package/dist/api-_JaUnIUj.cjs +292 -0
  7. package/dist/app-CjsQ2_n-.js +132 -0
  8. package/dist/app-CnKRZ9RW.cjs +178 -0
  9. package/dist/application/models/graphql/index.cjs +3 -12
  10. package/dist/application/models/graphql/index.d.cts +1 -1
  11. package/dist/application/models/graphql/index.d.ts +1 -1
  12. package/dist/application/models/graphql/index.js +1 -10
  13. package/dist/application/models/guards/api/index.cjs +1 -2
  14. package/dist/application/models/guards/api/index.d.cts +2 -2
  15. package/dist/application/models/guards/api/index.d.ts +2 -2
  16. package/dist/application/models/guards/api/index.js +1 -2
  17. package/dist/application/models/index.cjs +48 -54
  18. package/dist/application/models/index.d.cts +7 -9
  19. package/dist/application/models/index.d.ts +7 -9
  20. package/dist/application/models/index.js +7 -11
  21. package/dist/application/models/utilityTypes/index.cjs +1 -1
  22. package/dist/application/models/utilityTypes/index.d.cts +1 -1
  23. package/dist/application/models/utilityTypes/index.d.ts +1 -1
  24. package/dist/application/models/utilityTypes/index.js +1 -1
  25. package/dist/application/models/variantInfo/index.cjs +1 -1
  26. package/dist/application/models/variantInfo/index.d.cts +1 -1
  27. package/dist/application/models/variantInfo/index.d.ts +1 -1
  28. package/dist/application/models/variantInfo/index.js +1 -1
  29. package/dist/application/utils/index.cjs +40 -37
  30. package/dist/application/utils/index.d.cts +18 -14
  31. package/dist/application/utils/index.d.ts +19 -15
  32. package/dist/application/utils/index.js +13 -10
  33. package/dist/{atomStore-JwGb7pcy.cjs → atomStore-B4jIaDPd.cjs} +1 -1
  34. package/dist/{atomStore-B1cgmbP0.js → atomStore-D8pjE1vL.js} +1 -1
  35. package/dist/atoms/app/index.cjs +14 -16
  36. package/dist/atoms/app/index.d.cts +20 -19
  37. package/dist/atoms/app/index.d.ts +20 -19
  38. package/dist/atoms/app/index.js +10 -11
  39. package/dist/atoms/atomStore/index.cjs +2 -1
  40. package/dist/atoms/atomStore/index.d.cts +24 -2
  41. package/dist/atoms/atomStore/index.d.ts +24 -2
  42. package/dist/atoms/atomStore/index.js +2 -1
  43. package/dist/atoms/chat/index.cjs +44 -40
  44. package/dist/atoms/chat/index.d.cts +35 -36
  45. package/dist/atoms/chat/index.d.ts +35 -36
  46. package/dist/atoms/chat/index.js +14 -10
  47. package/dist/atoms/globalSearch/index.cjs +1 -1
  48. package/dist/atoms/globalSearch/index.d.cts +5 -5
  49. package/dist/atoms/globalSearch/index.d.ts +6 -6
  50. package/dist/atoms/globalSearch/index.js +1 -1
  51. package/dist/atoms/org/index.cjs +26 -38
  52. package/dist/atoms/org/index.d.cts +35 -48
  53. package/dist/atoms/org/index.d.ts +35 -48
  54. package/dist/atoms/org/index.js +11 -11
  55. package/dist/atoms/search/index.cjs +47 -41
  56. package/dist/atoms/search/index.d.cts +7 -9
  57. package/dist/atoms/search/index.d.ts +7 -9
  58. package/dist/atoms/search/index.js +16 -10
  59. package/dist/bandolier-DYEz4-8C.js +1229 -0
  60. package/dist/bandolier-o_-xrbOV.cjs +1229 -0
  61. package/dist/carpe-CsG5jCcl.cjs +607 -0
  62. package/dist/carpe-DONk00bZ.js +605 -0
  63. package/dist/cdnUtils-32v8bDX9.cjs +16 -0
  64. package/dist/cdnUtils-E4tLBt2g.js +11 -0
  65. package/dist/{chat-_NzpO_Hn.cjs → chat-BubCW1as.cjs} +1 -1
  66. package/dist/chat-CO7cRkaq.cjs +506 -0
  67. package/dist/{chat-CHmD79E1.js → chat-CV6MXeID.js} +1 -1
  68. package/dist/chat-hcRc4RRd.js +285 -0
  69. package/dist/{components-Dl-TMD9k.js → components-B4T3Uzth.js} +1 -1
  70. package/dist/{components-D0XDRcaN.cjs → components-Cw9WjA6g.cjs} +1 -1
  71. package/dist/config/locators/components/chat/index.cjs +1 -1
  72. package/dist/config/locators/components/chat/index.d.cts +1 -1
  73. package/dist/config/locators/components/chat/index.d.ts +1 -1
  74. package/dist/config/locators/components/chat/index.js +1 -1
  75. package/dist/config/locators/components/chat/variants/index.d.cts +1 -1
  76. package/dist/config/locators/components/chat/variants/index.d.ts +1 -1
  77. package/dist/config/locators/components/index.cjs +1 -1
  78. package/dist/config/locators/components/index.d.cts +1 -1
  79. package/dist/config/locators/components/index.d.ts +1 -1
  80. package/dist/config/locators/components/index.js +1 -1
  81. package/dist/config/locators/components/search/index.d.ts +1 -1
  82. package/dist/config/locators/index.cjs +4 -4
  83. package/dist/config/locators/index.d.cts +2 -2
  84. package/dist/config/locators/index.d.ts +2 -2
  85. package/dist/config/locators/index.js +4 -4
  86. package/dist/contexts/index.cjs +45 -14
  87. package/dist/contexts/index.d.cts +10 -10
  88. package/dist/contexts/index.d.ts +10 -10
  89. package/dist/contexts/index.js +22 -11
  90. package/dist/contexts-B4ihTBsV.cjs +2980 -0
  91. package/dist/contexts-DGlr7M1o.js +2596 -0
  92. package/dist/coterie-CKB93qfz.cjs +239 -0
  93. package/dist/{coterie--MGvWeVh.cjs → coterie-DHcj2fRE.js} +64 -65
  94. package/dist/{custservice-types-C8-9vKWb.cjs → custservice-types-Dy0kc9TW.cjs} +1 -1
  95. package/dist/{custservice-types-CamCiXjq.js → custservice-types-mnIunabv.js} +1 -1
  96. package/dist/default-BnB4p0Se.cjs +234 -0
  97. package/dist/default-D6f5Dyt7.js +199 -0
  98. package/dist/default-ZKkE5zT4.cjs +4 -0
  99. package/dist/default-legGZJwI.js +4 -0
  100. package/dist/{divIds-CjceLRD9.cjs → divIds-2dJlU3z8.cjs} +1 -15
  101. package/dist/{divIds-0Vj9g-fM.js → divIds-BUrN2vY-.js} +2 -4
  102. package/dist/dreamlandBaby-BiRYYFav.js +346 -0
  103. package/dist/dreamlandBaby-zuvmfzfD.cjs +346 -0
  104. package/dist/{embedded-_cLpd6FK.js → embedded-BJLWIriJ.js} +1 -1
  105. package/dist/{embedded-B5Wi9g0T.cjs → embedded-Dl79TJLC.cjs} +1 -1
  106. package/dist/{entrypoints-CNUvSgnk.js → entrypoints-Bs3pn6EV.js} +1 -1
  107. package/dist/{entrypoints-DM9Sm18O.cjs → entrypoints-Dqi5pzWH.cjs} +1 -1
  108. package/dist/enviveConfig-BccuzS2a.cjs +240 -0
  109. package/dist/enviveConfig-CzhTz8Aa.js +152 -0
  110. package/dist/events/index.cjs +1 -1
  111. package/dist/events/index.js +1 -1
  112. package/dist/{events-ClCDFK7t.js → events-BrLpaNxh.js} +1 -1
  113. package/dist/{events-Da7gpmGv.cjs → events-DwT6cEwI.cjs} +1 -1
  114. package/dist/fiveCbd-DwTTwC2j.cjs +613 -0
  115. package/dist/fiveCbd-Dz2NouOF.js +613 -0
  116. package/dist/forLoveAndLemons-DqSdyD6S.js +665 -0
  117. package/dist/forLoveAndLemons-Ud6mPrV3.cjs +667 -0
  118. package/dist/{globalSearch-b0wC7ZEO.js → globalSearch-B6THR7Jx.js} +1 -1
  119. package/dist/{globalSearch-BTeZxvk1.cjs → globalSearch-BFvEg53C.cjs} +1 -1
  120. package/dist/graphql-BNW60InJ.cjs +128 -0
  121. package/dist/graphql-CjB8wHzm.js +74 -0
  122. package/dist/graphqlConfig-CYt6tWII.js +30 -0
  123. package/dist/graphqlConfig-DicykC-o.cjs +61 -0
  124. package/dist/greenpan-B_EbPkSP.js +397 -0
  125. package/dist/greenpan-kPE4fJgd.cjs +397 -0
  126. package/dist/grooveLife-Ckuir319.js +342 -0
  127. package/dist/grooveLife-DKSEQp1F.cjs +342 -0
  128. package/dist/homegrownCannabis-BVPa2pqe.js +410 -0
  129. package/dist/homegrownCannabis-BwIAkxuA.cjs +410 -0
  130. package/dist/hooks/index.cjs +39 -13
  131. package/dist/hooks/index.d.cts +127 -45
  132. package/dist/hooks/index.d.ts +124 -42
  133. package/dist/hooks/index.js +22 -11
  134. package/dist/{index-D46Rd0io.d.cts → index-B0NW9KTj.d.cts} +1 -1
  135. package/dist/{index-BdNKc2ix.d.cts → index-BDPWBU3h.d.cts} +1 -1
  136. package/dist/index-BMPtlgac.d.ts +191 -0
  137. package/dist/{index-BTK5uzs6.d.cts → index-Bmub8e38.d.cts} +1 -1
  138. package/dist/{index-BrXuc_Ck.d.cts → index-Byb45OPg.d.cts} +1 -1
  139. package/dist/{index-CSIOQD-A.d.ts → index-C6KdON7d.d.ts} +1 -1
  140. package/dist/index-C7pGDl1A.d.ts +1609 -0
  141. package/dist/{index-K2kNsOTw.d.cts → index-C9lgsCWp.d.cts} +32 -32
  142. package/dist/{index-BzgkfbNO.d.cts → index-CESxqFso.d.cts} +1 -1
  143. package/dist/{index-CbJZOEU4.d.ts → index-Cc-wBCn6.d.ts} +32 -32
  144. package/dist/{index-Cx9e-fRi.d.ts → index-CcIG01PJ.d.ts} +2 -2
  145. package/dist/{index-ClJ0nMsR.d.cts → index-CiWEYzXl.d.cts} +2 -2
  146. package/dist/{index-CKKkTsms.d.ts → index-Cqg6ltII.d.ts} +1 -1
  147. package/dist/{index-Cr2y08f1.d.ts → index-DOii3C6b.d.ts} +1 -1
  148. package/dist/index-DTu2X-YS.d.cts +1609 -0
  149. package/dist/index-OEifcBsm.d.cts +191 -0
  150. package/dist/{index-Dxpscrvz.d.ts → index-PGF8BvxQ.d.ts} +1 -1
  151. package/dist/{index-D2VaMPA3.d.ts → index-ylUiJvnr.d.ts} +1 -1
  152. package/dist/interceptors/index.cjs +2 -12
  153. package/dist/interceptors/index.d.cts +8 -13
  154. package/dist/interceptors/index.d.ts +8 -13
  155. package/dist/interceptors/index.js +2 -11
  156. package/dist/jackArcher-B39OEIj6.cjs +727 -0
  157. package/dist/{jackArcher-sO9EbgrZ.js → jackArcher-BwkWGybC.js} +24 -25
  158. package/dist/jordanCraig-CxRH_jLi.js +1786 -0
  159. package/dist/jordanCraig-RwmWw-jM.cjs +1786 -0
  160. package/dist/kindredBravely-D78VwL20.cjs +490 -0
  161. package/dist/kindredBravely-DQDpAzdl.js +490 -0
  162. package/dist/kutFromTheKloth-TcXQkIti.js +369 -0
  163. package/dist/kutFromTheKloth-dXRrNti0.cjs +369 -0
  164. package/dist/larryAndSerges-Bh5XEXsZ.js +262 -0
  165. package/dist/larryAndSerges-COdBzOzu.cjs +262 -0
  166. package/dist/leapsAndRebounds-BbXnqkl5.cjs +360 -0
  167. package/dist/leapsAndRebounds-mjCaH1k-.js +360 -0
  168. package/dist/longevityrx-DdV3v26F.cjs +320 -0
  169. package/dist/longevityrx-DfPDfvAt.js +320 -0
  170. package/dist/lookOptic-DgXFGBPP.cjs +282 -0
  171. package/dist/{lookOptic-Jwf7EAU8.js → lookOptic-FgVW1afF.js} +19 -20
  172. package/dist/mantraBrand-C5gVm3rk.cjs +750 -0
  173. package/dist/{mantraBrand-DoaVj837.js → mantraBrand-uV8HCDR8.js} +22 -23
  174. package/dist/medterra-BtDpr1Hw.cjs +583 -0
  175. package/dist/medterra-DgzE7-mj.js +583 -0
  176. package/dist/modells-CJjsxOIR.js +484 -0
  177. package/dist/modells-Ck5KbRFj.cjs +484 -0
  178. package/dist/models-BkXg5eIP.cjs +1534 -0
  179. package/dist/models-UZ6HszfZ.js +1281 -0
  180. package/dist/{nodeSelector-DybpVr-i.d.ts → nodeSelector-BxrS2S_k.d.ts} +1 -1
  181. package/dist/{nodeSelector-vKB44CDB.d.cts → nodeSelector-Dm4S-10n.d.cts} +1 -1
  182. package/dist/org-C2RrBVQR.cjs +81 -0
  183. package/dist/org-xMytX--e.js +38 -0
  184. package/dist/orgAnalyticsConfig-BJ2A1RZ-.cjs +39 -0
  185. package/dist/orgAnalyticsConfig-ClrFy2qH.js +14 -0
  186. package/dist/pressedFloral-Bteoboms.js +661 -0
  187. package/dist/pressedFloral-CexgV-xy.cjs +661 -0
  188. package/dist/search-BMOAmrmY.js +459 -0
  189. package/dist/search-Df0Ifneg.cjs +672 -0
  190. package/dist/{search-filter-types-9rTb3jMj.d.cts → search-filter-types-DosbseF3.d.cts} +1 -1
  191. package/dist/{search-filter-types-C-zZSpGo.d.ts → search-filter-types-fZf91Pdw.d.ts} +1 -1
  192. package/dist/skinPerfection-BGzq9lq-.cjs +334 -0
  193. package/dist/skinPerfection-BlvcEcUE.js +334 -0
  194. package/dist/snapSupplements-CbbGzAgO.cjs +285 -0
  195. package/dist/snapSupplements-kcsPAOm9.js +285 -0
  196. package/dist/{socialProofClasses-ky69yppk.cjs → socialProofClasses-Db8gzsfi.cjs} +1 -1
  197. package/dist/{socialProofClasses-DdzG1tZy.js → socialProofClasses-kwDvwLOZ.js} +1 -1
  198. package/dist/spanx-B4WFA_rI.js +661 -0
  199. package/dist/spanx-BWoE4F8b.cjs +663 -0
  200. package/dist/spanxStaging-BOrOjhXn.js +845 -0
  201. package/dist/spanxStaging-BfdfIug4.cjs +848 -0
  202. package/dist/{suggestionBarV2-types-Penx3Y67.js → suggestionBarV2-types-IMMOmCir.js} +1 -1
  203. package/dist/{suggestionBarV2-types-B3lwrENK.cjs → suggestionBarV2-types-nnGNgFvR.cjs} +1 -1
  204. package/dist/supergoop-22dd5_BS.js +323 -0
  205. package/dist/supergoop-B-a4cku2.cjs +323 -0
  206. package/dist/{test-types-CXVJxTeu.d.ts → test-types-C9b_OdfO.d.ts} +1 -1
  207. package/dist/{test-types-CuOq25VT.d.cts → test-types-CgVJtwUr.d.cts} +1 -1
  208. package/dist/types/index.cjs +2 -2
  209. package/dist/types/index.d.cts +2 -2
  210. package/dist/types/index.d.ts +2 -2
  211. package/dist/types/index.js +2 -2
  212. package/dist/types--pr1GQQx.js +154 -0
  213. package/dist/types-BVSyY3Hk.cjs +196 -0
  214. package/dist/{uniqueVintage-BWkDgt1z.js → uniqueVintage-CJXiNNe7.js} +19 -20
  215. package/dist/uniqueVintage-D0jzJWlo.cjs +1213 -0
  216. package/dist/useMessageInterceptor-B87e3yu3.cjs +33 -0
  217. package/dist/useMessageInterceptor-Bb7YRaWk.js +25 -0
  218. package/dist/userIdentityContext-BPqvVIg0.d.cts +20 -0
  219. package/dist/userIdentityContext-wbCRmlzp.d.ts +20 -0
  220. package/dist/utils-C9ZSCx12.js +888 -0
  221. package/dist/utils-D5HO61hG.cjs +1016 -0
  222. package/dist/variantInfo-DbVxA1yE.js +1 -0
  223. package/dist/variantInfo-orXoPBCU.cjs +0 -0
  224. package/dist/venaCbd-Bhhu_qUf.cjs +365 -0
  225. package/dist/venaCbd-CanovPS_.js +365 -0
  226. package/dist/westonJonBoucher-BC0x1ktI.cjs +422 -0
  227. package/dist/{westonJonBoucher-BAGXegsX.js → westonJonBoucher-BUu1_wP1.js} +19 -20
  228. package/dist/wineEnthusiast-BlCryfil.cjs +940 -0
  229. package/dist/{wineEnthusiast-EJbhMeKQ.js → wineEnthusiast-Ck1x5iJq.js} +19 -20
  230. package/dist/wolfMattress-D9Mjq-HP.js +372 -0
  231. package/dist/wolfMattress-JssghhC-.cjs +372 -0
  232. package/dist/wolfTactical-C6exYhL7.cjs +349 -0
  233. package/dist/wolfTactical-CnV3KQdI.js +349 -0
  234. package/package.json +100 -19
  235. package/src/{adapters/spiffy/commerce/api.ts → application/commerce-api.ts} +31 -23
  236. package/src/application/models/colorsConfig.ts +18 -18
  237. package/src/application/models/frontendConfig.ts +3 -3
  238. package/src/application/models/graphql/queries/getMerchantColorsQuery.ts +1 -1
  239. package/src/application/models/graphql/queries/getMerchantFrontendConfigQuery.ts +1 -1
  240. package/src/application/models/index.ts +0 -2
  241. package/src/application/models/localStorageEventListener.ts +2 -2
  242. package/src/application/models/utils/snakeToCamelTransformer.ts +8 -8
  243. package/src/application/models/validators/validateGraphQLColorsConfig.ts +0 -21
  244. package/src/application/models/validators/validateGraphQLFrontendConfig.ts +2 -2
  245. package/src/application/utils/analyticsUtils.ts +53 -22
  246. package/src/application/utils/cdnUtils.ts +11 -0
  247. package/src/atoms/amplitude/amplitudeTrackEventAtom.ts +15 -0
  248. package/src/atoms/app/index.ts +7 -17
  249. package/src/atoms/app/variant.ts +13 -4
  250. package/src/atoms/chat/chatState.ts +28 -18
  251. package/src/atoms/chat/messageQueue.ts +36 -5
  252. package/src/atoms/chat/replies.ts +45 -37
  253. package/src/atoms/envive/enviveConfig.ts +10 -6
  254. package/src/atoms/org/graphqlConfig.ts +7 -1
  255. package/src/atoms/org/index.ts +3 -3
  256. package/src/atoms/org/newOrgConfigAtom.ts +8 -0
  257. package/src/atoms/org/orgPageConfig.ts +6 -5
  258. package/src/atoms/search/chatSearch.ts +11 -5
  259. package/src/atoms/search/searchAPI.ts +22 -12
  260. package/src/atoms/search/searchServiceAdapter.ts +25 -0
  261. package/src/contexts/amplitudeContext.tsx +466 -0
  262. package/src/contexts/cdnContext.tsx +48 -0
  263. package/src/contexts/chatContext.tsx +15 -12
  264. package/src/contexts/enviveConfigContext.tsx +22 -17
  265. package/src/contexts/enviveCssContext.tsx +34 -5
  266. package/src/contexts/featureFlagContext.tsx +193 -0
  267. package/src/contexts/featureFlagServiceContext.tsx +87 -0
  268. package/src/contexts/graphqlContext.tsx +165 -0
  269. package/src/contexts/index.ts +13 -3
  270. package/src/contexts/localStorageContext.tsx +159 -0
  271. package/src/contexts/newOrgConfigContext.tsx +104 -0
  272. package/src/contexts/orgConfigContext.tsx +92 -92
  273. package/src/contexts/searchContext.tsx +187 -0
  274. package/src/contexts/sessionStorageContext.tsx +80 -0
  275. package/src/contexts/shopifyUrlContext.tsx +97 -0
  276. package/src/contexts/types.ts +12 -8
  277. package/src/contexts/userIdentityContext.tsx +197 -0
  278. package/src/events/registerAnalyticsListeners.ts +32 -38
  279. package/src/hooks/index.ts +10 -4
  280. package/src/hooks/useAmplitudeOperations.ts +35 -0
  281. package/src/hooks/useAppDetails.ts +49 -0
  282. package/src/hooks/useCdnOperations.ts +16 -0
  283. package/src/hooks/useChatToggle.ts +5 -4
  284. package/src/hooks/useChatToggleAnalytics.ts +15 -0
  285. package/src/hooks/useGraphQLConfig.ts +63 -0
  286. package/src/hooks/useIdentifyUser.ts +33 -0
  287. package/src/hooks/useImageResolver.ts +7 -7
  288. package/src/hooks/useLocalStorageOperations.ts +92 -0
  289. package/src/hooks/useNewOrgConfig.ts +3 -76
  290. package/src/hooks/useSearch.tsx +21 -18
  291. package/src/hooks/useSearchOperations.ts +97 -0
  292. package/src/hooks/useSessionStorageOperations.ts +28 -0
  293. package/src/hooks/useShopifyUrlOperations.ts +45 -0
  294. package/src/hooks/useTrackComponentVisibleEvent.ts +12 -8
  295. package/src/hooks/useUpdateAnalyticsProps.ts +28 -17
  296. package/src/interceptors/index.ts +0 -1
  297. package/src/interceptors/useMessageInterceptor.ts +5 -8
  298. package/src/merchants/bandolier/bandolier.ts +10 -28
  299. package/src/merchants/carpe/carpe.ts +5 -8
  300. package/src/merchants/coterie/coterie.ts +3 -6
  301. package/src/merchants/default.ts +73 -70
  302. package/src/merchants/domInsertion.ts +30 -0
  303. package/src/merchants/dreamlandBaby/dreamlandBaby.ts +12 -6
  304. package/src/merchants/fiveCbd/fiveCbd.ts +7 -13
  305. package/src/merchants/forLoveAndLemons/forLoveAndLemons.ts +44 -14
  306. package/src/merchants/greenpan/greenpan.ts +6 -12
  307. package/src/merchants/gridInsertion.ts +19 -0
  308. package/src/merchants/grooveLife/grooveLife.ts +13 -7
  309. package/src/merchants/homegrownCannabis/homegrownCannabis.ts +12 -6
  310. package/src/merchants/jackArcher/jackArcher.ts +26 -11
  311. package/src/merchants/jordanCraig/jordanCraig.ts +5 -5
  312. package/src/merchants/kindredBravely/kindredBravely.ts +16 -7
  313. package/src/merchants/kutFromTheKloth/kutFromTheKloth.ts +9 -6
  314. package/src/merchants/larryAndSerges/larryAndSerges.ts +6 -2
  315. package/src/merchants/leapsAndRebounds/leapsAndRebounds.ts +7 -7
  316. package/src/merchants/longevityrx/longevityrx.ts +14 -8
  317. package/src/merchants/lookOptic/lookOptic.ts +6 -6
  318. package/src/merchants/mantraBrand/mantraBrand.ts +14 -8
  319. package/src/merchants/medterra/medterra.ts +14 -11
  320. package/src/merchants/modells/modells.ts +6 -9
  321. package/src/merchants/pressedFloral/pressedFloral.ts +7 -13
  322. package/src/merchants/skinPerfection/skinPerfection.ts +13 -7
  323. package/src/merchants/snapSupplements/snapSupplements.ts +13 -10
  324. package/src/merchants/spanx/spanx.ts +6 -6
  325. package/src/merchants/spanx/spanxStaging.ts +6 -12
  326. package/src/merchants/supergoop/supergoop.ts +11 -12
  327. package/src/merchants/uniqueVintage/uniqueVintage.ts +6 -6
  328. package/src/merchants/venaCbd/venaCbd.ts +6 -9
  329. package/src/merchants/westonJonBoucher/westonJonBoucher.ts +6 -6
  330. package/src/merchants/wineEnthusiast/wineEnthusiast.ts +6 -6
  331. package/src/merchants/wolfMattress/wolfMattress.ts +3 -3
  332. package/src/merchants/wolfTactical/wolfTactical.ts +5 -11
  333. package/src/types/config-versions.ts +6 -0
  334. package/src/types.ts +0 -53
  335. package/dist/adapters/amplitude/index.cjs +0 -14
  336. package/dist/adapters/amplitude/index.d.cts +0 -6
  337. package/dist/adapters/amplitude/index.d.ts +0 -6
  338. package/dist/adapters/amplitude/index.js +0 -12
  339. package/dist/api-B2euFL-5.cjs +0 -269
  340. package/dist/api-XRr_lAG6.js +0 -190
  341. package/dist/application/config/index.cjs +0 -43
  342. package/dist/application/config/index.d.cts +0 -15
  343. package/dist/application/config/index.d.ts +0 -15
  344. package/dist/application/config/index.js +0 -41
  345. package/dist/application/service/customerService/index.cjs +0 -4
  346. package/dist/application/service/customerService/index.d.cts +0 -3
  347. package/dist/application/service/customerService/index.d.ts +0 -3
  348. package/dist/application/service/customerService/index.js +0 -4
  349. package/dist/application/service/index.cjs +0 -42
  350. package/dist/application/service/index.d.cts +0 -413
  351. package/dist/application/service/index.d.ts +0 -413
  352. package/dist/application/service/index.js +0 -12
  353. package/dist/atomStore-ONYy0XuA.d.cts +0 -24
  354. package/dist/atomStore-kOKiEcNl.d.ts +0 -24
  355. package/dist/bandolier-Da4wt6sm.cjs +0 -1230
  356. package/dist/bandolier-DzEmYWcz.js +0 -1230
  357. package/dist/carpe-AXipz0Xl.cjs +0 -608
  358. package/dist/carpe-CaUKwcEa.js +0 -606
  359. package/dist/contexts-CtRlNXaS.js +0 -7674
  360. package/dist/contexts-CtgmnYNn.cjs +0 -9088
  361. package/dist/coterie-oKHAT0lx.js +0 -240
  362. package/dist/customerService-BG1uNZZ1.cjs +0 -36
  363. package/dist/customerService-BHQRnLhC.js +0 -23
  364. package/dist/default-B4fINY5_.cjs +0 -4
  365. package/dist/default-BrTQxA0c.js +0 -4
  366. package/dist/default-C3LrcbZB.cjs +0 -199
  367. package/dist/default-CXkYrLEr.js +0 -176
  368. package/dist/dreamlandBaby-BEqt0eKF.js +0 -347
  369. package/dist/dreamlandBaby-DBDjEJCc.cjs +0 -347
  370. package/dist/featureFlagService-5wdmW02z.d.ts +0 -18
  371. package/dist/featureFlagService-DaelrXEk.d.cts +0 -18
  372. package/dist/fiveCbd-CdqNt16h.cjs +0 -614
  373. package/dist/fiveCbd-D6B-sgnX.js +0 -614
  374. package/dist/forLoveAndLemons-C7GsJG7f.cjs +0 -668
  375. package/dist/forLoveAndLemons-gNDlMtPR.js +0 -666
  376. package/dist/greenpan-B5AaW4M_.js +0 -398
  377. package/dist/greenpan-DrORpYms.cjs +0 -398
  378. package/dist/grooveLife-BJqsfH2H.cjs +0 -343
  379. package/dist/grooveLife-xIUmDM8s.js +0 -343
  380. package/dist/homegrownCannabis-8TZ21u6L.cjs +0 -411
  381. package/dist/homegrownCannabis-BtMuEvbZ.js +0 -411
  382. package/dist/index-CKUpnyJQ.d.ts +0 -72
  383. package/dist/index-DFL1dIT_.d.ts +0 -7
  384. package/dist/index-DXpgMVpp.d.ts +0 -749
  385. package/dist/index-MFbPQ8Ji.d.ts +0 -95
  386. package/dist/index-VHFMGkO-.d.cts +0 -72
  387. package/dist/index-VSFakgAI.d.cts +0 -95
  388. package/dist/index-aNW5V9fh.d.cts +0 -749
  389. package/dist/index-zZjcds15.d.cts +0 -7
  390. package/dist/jackArcher-WtkbLBZj.cjs +0 -728
  391. package/dist/jordanCraig-471FcgqF.cjs +0 -1787
  392. package/dist/jordanCraig-DNOncplU.js +0 -1787
  393. package/dist/kindredBravely-BlLyHGMX.cjs +0 -491
  394. package/dist/kindredBravely-cqZ4OvXp.js +0 -491
  395. package/dist/kutFromTheKloth-3mOIryvt.cjs +0 -370
  396. package/dist/kutFromTheKloth-DtVNCMKa.js +0 -370
  397. package/dist/larryAndSerges-88Bvq-Us.cjs +0 -262
  398. package/dist/larryAndSerges-cvak6May.js +0 -262
  399. package/dist/leapsAndRebounds-Dmf8eUPq.js +0 -361
  400. package/dist/leapsAndRebounds-iWKc923H.cjs +0 -361
  401. package/dist/logger-Dln20ans.cjs +0 -26
  402. package/dist/logger-pdEEY8T2.js +0 -20
  403. package/dist/longevityrx-BTMI9vn-.js +0 -321
  404. package/dist/longevityrx-CobPyigd.cjs +0 -321
  405. package/dist/lookOptic-C4H_c0JZ.cjs +0 -283
  406. package/dist/mantraBrand-CySGqbn6.cjs +0 -751
  407. package/dist/medterra-BnZ5p27n.cjs +0 -584
  408. package/dist/medterra-DaICcPPp.js +0 -584
  409. package/dist/modells-CZ1L6dD_.js +0 -485
  410. package/dist/modells-DF0SndHr.cjs +0 -485
  411. package/dist/orgConfigResults--dAwtw3W.d.ts +0 -881
  412. package/dist/orgConfigResults-BL0XBA6x.d.cts +0 -881
  413. package/dist/pressedFloral-B3t2cYzs.cjs +0 -662
  414. package/dist/pressedFloral-Dsws2Kfb.js +0 -662
  415. package/dist/skinPerfection-CILQM2bR.cjs +0 -335
  416. package/dist/skinPerfection-DmQCntRf.js +0 -335
  417. package/dist/snapSupplements--X_v0KRM.js +0 -286
  418. package/dist/snapSupplements-Djuzl0Ed.cjs +0 -286
  419. package/dist/spanx-Bo81yXSF.cjs +0 -664
  420. package/dist/spanx-DauxB8KE.js +0 -662
  421. package/dist/spanxStaging-BucYQvR1.cjs +0 -849
  422. package/dist/spanxStaging-CfXUukdP.js +0 -846
  423. package/dist/supergoop-8qa_NV3F.cjs +0 -338
  424. package/dist/supergoop-DOaui-A6.js +0 -336
  425. package/dist/types-CD4LFta-.d.cts +0 -33
  426. package/dist/types-CGC6Oozp.cjs +0 -231
  427. package/dist/types-CnTCkyvK.js +0 -177
  428. package/dist/types-DBdI0j89.d.ts +0 -33
  429. package/dist/uniqueVintage-DAne8XcL.cjs +0 -1214
  430. package/dist/variant-CC1nrywd.d.ts +0 -13
  431. package/dist/variant-CQTuQQSq.d.cts +0 -13
  432. package/dist/venaCbd-B1HO_Pkr.cjs +0 -366
  433. package/dist/venaCbd-CnByO-5R.js +0 -366
  434. package/dist/westonJonBoucher-BRfHWMbs.cjs +0 -423
  435. package/dist/wineEnthusiast-DW8JVwV8.cjs +0 -941
  436. package/dist/wolfMattress-B6INZNRJ.cjs +0 -373
  437. package/dist/wolfMattress-D9P7ErH_.js +0 -373
  438. package/dist/wolfTactical-C5Pupi3J.js +0 -350
  439. package/dist/wolfTactical-TMthZM93.cjs +0 -350
  440. package/src/adapters/amplitude/amplitudeAdapter.ts +0 -477
  441. package/src/adapters/amplitude/index.ts +0 -2
  442. package/src/adapters/amplitude/stubAmplitudeAdapter.ts +0 -34
  443. package/src/adapters/spiffy/commerce/graphql.ts +0 -219
  444. package/src/application/config/generalStaticConfig.ts +0 -40
  445. package/src/application/config/index.ts +0 -1
  446. package/src/application/models/domMutationContinuation.ts +0 -7
  447. package/src/application/models/domObservationStrategy.ts +0 -9
  448. package/src/application/service/cachingService.ts +0 -84
  449. package/src/application/service/cdnService.ts +0 -20
  450. package/src/application/service/customerService/index.ts +0 -8
  451. package/src/application/service/customerService/providers/UnsupportedCustomerService.ts +0 -15
  452. package/src/application/service/domMutationObserver.ts +0 -320
  453. package/src/application/service/domMutations/GridInsertionService.ts +0 -123
  454. package/src/application/service/domMutations/dataLayer/dataLayerEventsListener.ts +0 -99
  455. package/src/application/service/domMutations/domInsertionService.ts +0 -90
  456. package/src/application/service/domMutations/domMutationListener.ts +0 -15
  457. package/src/application/service/domMutations/domMutationListenerState.ts +0 -52
  458. package/src/application/service/domMutations/floatingChat/embeddedChatsPlacementsListener.ts +0 -41
  459. package/src/application/service/domMutations/gladly/gladlyListener.ts +0 -61
  460. package/src/application/service/domMutations/spiffy/orgs/common/kustomerVisibilityListener.ts +0 -41
  461. package/src/application/service/domMutations/spiffy/orgs/common/orgsCommonDataLayerListener.ts +0 -119
  462. package/src/application/service/featureFlagService.ts +0 -130
  463. package/src/application/service/graphqlConfigService.ts +0 -59
  464. package/src/application/service/index.ts +0 -32
  465. package/src/application/service/kustomerIntegrationService.ts +0 -111
  466. package/src/application/service/localStorageService.ts +0 -77
  467. package/src/application/service/pageVariantService.ts +0 -866
  468. package/src/application/service/searchService.ts +0 -147
  469. package/src/application/service/sessionStorageService.ts +0 -27
  470. package/src/application/service/shopifyUrlService.ts +0 -63
  471. package/src/application/service/userIdentityService.ts +0 -114
  472. package/src/application/service/windowChatToggleService.ts +0 -80
  473. package/src/application/service/windowDataLayerService.ts +0 -181
  474. package/src/application/service/windowFrontendConfigService.ts +0 -129
  475. package/src/atoms/org/merchantCss.ts +0 -161
  476. package/src/atoms/org/org.ts +0 -251
  477. package/src/atoms/org/orgUIConfig.ts +0 -142
  478. package/src/enabled-features.ts +0 -83
  479. package/src/hooks/useDynamicVariants.ts +0 -226
  480. package/src/hooks/useFileUpload.ts +0 -63
  481. package/src/hooks/useHideElements.ts +0 -85
  482. package/src/interceptors/useFormEscalation.ts +0 -57
  483. /package/dist/{locators-DnKpajbY.js → atomStore-CZnUUsrr.js} +0 -0
  484. /package/dist/{locators-CugndTUM.cjs → atomStore-KSoFS3Jj.cjs} +0 -0
  485. /package/dist/{utilityTypes-C4h2wgAK.cjs → locators-0YYZu9n4.cjs} +0 -0
  486. /package/dist/{utilityTypes-BVikejDo.js → locators-fBXS_pxP.js} +0 -0
  487. /package/dist/{variantInfo-CzhR5W6h.js → utilityTypes-8sETsYPk.js} +0 -0
  488. /package/dist/{variantInfo-CNRTY0gH.cjs → utilityTypes-COShxVir.cjs} +0 -0
  489. /package/src/{application/service/customerService/types.ts → types/customerService.ts} +0 -0
  490. /package/src/{adapters/spiffy/commerce → types}/exceptions/sessionExceptions.ts +0 -0
  491. /package/src/{adapters/spiffy/commerce → types}/exceptions/unsupportedProductExceptions.ts +0 -0
@@ -0,0 +1,2596 @@
1
+ import { FeatureGates, MessageRole, MessageType, ProductExperiment, SpiffyWidgets, getMerchantOrgIdQuery, transformSnakeToCamel, validateGraphQLOrgId, validateOrgConfigResults, validateResponse, validateSuggestion, validateUserEvent } from "./models-UZ6HszfZ.js";
2
+ import { OrgShortName, getOrgInfo } from "./types--pr1GQQx.js";
3
+ import { configVersion, parseHref } from "./graphql-CjB8wHzm.js";
4
+ import { logger_default } from "./api-DjeZXxl_.js";
5
+ import { LocalStorageKeys, baseUrlAtom, cdnUrlAtom, contextSourceAtom, envAtom, orgLevelApiKeyAtom, orgShortNameAtom, reactAppNameAtom, useLocalStorage } from "./enviveConfig-CzhTz8Aa.js";
6
+ import { getAtomStore } from "./atomStore-D8pjE1vL.js";
7
+ import { chatIdAtom, hasParsedVariantInfoAtom, supportedEventAtom, userIdAtom, variantInfoAtom } from "./app-CjsQ2_n-.js";
8
+ import { SpiffyMetricsEventName, useAmplitude, useEnviveConfig } from "./amplitudeContext-hY3caPC6.js";
9
+ import { DOMObserver, coreSupportedEventRequestToApiRequest, messageFromFormSubmittedEvent, messageFromQueryEvent, messageFromResponse, messageFromSuggestionEvent, messageRequestToCommerceMessageRequest } from "./utils-C9ZSCx12.js";
10
+ import { featureFlagServiceAtom, orgIdAtom } from "./graphqlConfig-CYt6tWII.js";
11
+ import { PerfMetricsEvents, chatAtom, chatOnToggleAtom, clearUserEventAtom, createResponsePayload, logPerfMetricAtom, messagesAtom, processUserEventAtom, requestFailureAtom, responseStreamingAtom, suggestionsAtom, suggestionsLoadingAtom, userEventQueueAtom, userEventsAtom, userHasRepliedAtom, userQueueEventCountAtom } from "./chat-hcRc4RRd.js";
12
+ import { newOrgConfigAtom } from "./org-xMytX--e.js";
13
+ import { ProductSorting, addSearchFilterAtom, chatSearchIsLoadingAtom, chatSearchProductSortingAtom, chatSearchProducts, chatSearchStateAtom, clearSearchFiltersAtom, clearSearchServiceFunction, createFilterOption, filteredSearchProductsAtom, formatFilterDisplayName, handleSearchResultsAtom, performSearchAtom, removeSearchFilterAtom, searchAtom, searchFiltersAtom, searchParamsAtom, searchProductSortingAtom, searchSelectedFiltersAtom, setSearchServiceFunction } from "./search-BMOAmrmY.js";
14
+ import { autocompleteStateAtom, isFilterOpenAtom } from "./globalSearch-B6THR7Jx.js";
15
+ import { useMessageInterceptor } from "./useMessageInterceptor-Bb7YRaWk.js";
16
+ import React, { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState } from "react";
17
+ import { useAtom, useAtomValue, useSetAtom } from "jotai";
18
+ import { Configuration, ContextEnvEnum, ContextSourceEnum, CustomerServiceApi, DefaultApi, FormType, InferenceApi, PLPAttributeCategory, ResponseCategory, ResponseError, SearchApi, UserEventCategory, V1OrgConfigGetSourceEnum } from "@spiffy-ai/commerce-api-client";
19
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
20
+ import { v4 } from "uuid";
21
+ import UAParser from "ua-parser-js";
22
+
23
+ //#region src/contexts/cdnContext.tsx
24
+ const CdnContext = createContext(null);
25
+ const CdnProvider = ({ children }) => {
26
+ const cdnUrl = useAtomValue(cdnUrlAtom) || "https://cdn.spiffy.ai/other";
27
+ const getCdnBasePath = useCallback(() => {
28
+ return cdnUrl;
29
+ }, [cdnUrl]);
30
+ const getAssetURL = useCallback((assetName, orgShortName) => {
31
+ return `${getCdnBasePath()}/assets/${orgShortName}/${assetName}`;
32
+ }, [getCdnBasePath]);
33
+ const value = useMemo(() => ({
34
+ cdnUrl,
35
+ getCdnBasePath,
36
+ getAssetURL
37
+ }), [
38
+ cdnUrl,
39
+ getCdnBasePath,
40
+ getAssetURL
41
+ ]);
42
+ return /* @__PURE__ */ jsx(CdnContext.Provider, {
43
+ value,
44
+ children
45
+ });
46
+ };
47
+ const useCdn = () => {
48
+ const context = useContext(CdnContext);
49
+ if (!context) throw new Error("useCdn must be used within a CdnProvider");
50
+ return context;
51
+ };
52
+
53
+ //#endregion
54
+ //#region src/types/exceptions/sessionExceptions.ts
55
+ var SessionRestartRequired = class extends Error {
56
+ constructor() {
57
+ super("Session restart required");
58
+ this.name = "SessionRestartRequired";
59
+ }
60
+ };
61
+
62
+ //#endregion
63
+ //#region src/types/exceptions/unsupportedProductExceptions.ts
64
+ var UnsupportedProductException = class extends Error {
65
+ constructor() {
66
+ super("Unsupported product");
67
+ this.name = "UnsupportedProduct";
68
+ }
69
+ };
70
+
71
+ //#endregion
72
+ //#region src/application/commerce-api.ts
73
+ async function errorResponseBody$1(error) {
74
+ try {
75
+ return await error.response.json();
76
+ } catch {
77
+ return {};
78
+ }
79
+ }
80
+ async function throwSessionRestartRequiredIf$1(errorMsg, error) {
81
+ if (!(error instanceof ResponseError)) {
82
+ logger_default.logInfo(errorMsg, error);
83
+ throw error;
84
+ }
85
+ const errorResponse = await errorResponseBody$1(error);
86
+ if (errorResponse?.message?.toLowerCase() === "unsupported product" || errorResponse?.app_code?.toUpperCase() === "PRODUCT_NOT_FOUND") throw new UnsupportedProductException();
87
+ else if (errorResponse?.app_code?.toUpperCase() === "RESTART_SESSION" || errorResponse?.sub_code?.toUpperCase() === "NOT_FOUND") {
88
+ logger_default.logInfo("Session does not exist. Re-start session", error, error.response, errorResponse);
89
+ throw new SessionRestartRequired();
90
+ }
91
+ logger_default.logInfo(errorMsg, error);
92
+ throw error;
93
+ }
94
+ var CommerceApiClient = class CommerceApiClient {
95
+ static {
96
+ this.getInstance = () => {
97
+ if (!CommerceApiClient.instance) CommerceApiClient.instance = new CommerceApiClient();
98
+ return CommerceApiClient.instance;
99
+ };
100
+ }
101
+ constructor(basePath) {
102
+ this.suggestionsAbortController = new AbortController();
103
+ this.responsesAbortController = new AbortController();
104
+ const baseUrl = getAtomStore().get(baseUrlAtom);
105
+ const config = new Configuration({
106
+ basePath: basePath || baseUrl,
107
+ headers: {
108
+ "Content-Type": "application/json",
109
+ Accept: "application/json"
110
+ }
111
+ });
112
+ this.defaultApi = new DefaultApi(config);
113
+ this.inferenceApi = new InferenceApi(config);
114
+ this.customerServiceApi = new CustomerServiceApi(config);
115
+ }
116
+ static {
117
+ this.resolveUrl = async (url) => {
118
+ const atomStore = getAtomStore();
119
+ const orgShortName = atomStore.get(orgShortNameAtom);
120
+ const orgId = atomStore.get(orgIdAtom);
121
+ const userId = atomStore.get(userIdAtom);
122
+ const chatId = atomStore.get(chatIdAtom);
123
+ const source = atomStore.get(contextSourceAtom);
124
+ const env = atomStore.get(envAtom);
125
+ const featureFlagService = atomStore.get(featureFlagServiceAtom);
126
+ const context = {
127
+ user_id: userId ?? "",
128
+ org_id: orgId ?? "",
129
+ org_short_name: orgShortName ?? "",
130
+ chat_id: chatId ?? "",
131
+ source: source ?? ContextSourceEnum.App,
132
+ env: env ?? ContextEnvEnum.Dev
133
+ };
134
+ const featureGates = featureFlagService?.featureFlagService?.getFeatureFlags() || {};
135
+ const urlResolvingRequest = {
136
+ url,
137
+ context,
138
+ feature_gates: featureGates
139
+ };
140
+ return await (await CommerceApiClient.getInstance().inferenceApi.v1UrlResolvingPostRaw({ UrlResolvingRequest: urlResolvingRequest })).raw.json();
141
+ };
142
+ }
143
+ static {
144
+ this.reportSession = async (reportRequest) => {
145
+ await CommerceApiClient.getInstance().defaultApi.v1ChatsReportSessionIdPost({ ReportSessionRequest: reportRequest });
146
+ };
147
+ }
148
+ static {
149
+ this.getNextResponses = async (payload) => {
150
+ try {
151
+ return (await CommerceApiClient.getInstance().inferenceApi.v1NextResponsesPost({ NextMessageRequest: messageRequestToCommerceMessageRequest(payload) })).map((resp) => validateResponse(resp)).map((resp) => messageFromResponse(resp)).filter((m) => m != null);
152
+ } catch (err) {
153
+ logger_default.logInfo("Failed to get next responses", err, {
154
+ payloadContext: payload?.context,
155
+ userEvents: payload?.userEvents
156
+ });
157
+ await throwSessionRestartRequiredIf$1("Failed to get next responses", err);
158
+ return [];
159
+ }
160
+ };
161
+ }
162
+ static {
163
+ this.getNextResponseStreaming = (payload) => {
164
+ async function* generate(inferenceApi, abortController) {
165
+ try {
166
+ const response = await inferenceApi.v1NextResponsesPostRaw({ NextMessageRequest: messageRequestToCommerceMessageRequest(payload) }, { signal: abortController.signal });
167
+ if (!response.raw.body) {
168
+ logger_default.logError("[spiffy-ai] No body in the streamed response", void 0, { response: response.raw });
169
+ return;
170
+ }
171
+ const reader = response.raw.body.getReader();
172
+ const decoder = new TextDecoder("utf-8");
173
+ let partial = "";
174
+ const safeParse = (line) => {
175
+ try {
176
+ return JSON.parse(line);
177
+ } catch (err) {
178
+ logger_default.logError("[spiffy-ai] Error parsing streamed line", err, {
179
+ line,
180
+ partial
181
+ });
182
+ partial = line;
183
+ return partial;
184
+ }
185
+ };
186
+ const processChunk = (chunk) => {
187
+ return `${partial}${chunk}`.split("\n").map((line) => line.replace(/^data: /, "").trim()).filter((line) => line !== "" && line !== "[DONE]").map(safeParse).filter((v) => v);
188
+ };
189
+ while (true) {
190
+ const { done, value } = await reader.read();
191
+ if (done) break;
192
+ const chunk = decoder.decode(value);
193
+ const parsedLines = processChunk(chunk);
194
+ for (const parsedLine of parsedLines) {
195
+ const validatedResponse = validateResponse(parsedLine);
196
+ if (validatedResponse) yield validatedResponse;
197
+ }
198
+ }
199
+ } catch (error) {
200
+ logger_default.logError("[spiffy-ai] Failed to get next streaming responses", error, {
201
+ payloadContext: payload?.context,
202
+ userEvents: payload?.userEvents
203
+ });
204
+ await throwSessionRestartRequiredIf$1("Failed to get next streaming responses", error);
205
+ }
206
+ }
207
+ CommerceApiClient.getInstance().responsesAbortController.abort();
208
+ CommerceApiClient.getInstance().responsesAbortController = new AbortController();
209
+ return generate(CommerceApiClient.getInstance().inferenceApi, CommerceApiClient.getInstance().responsesAbortController);
210
+ };
211
+ }
212
+ static {
213
+ this.getNextSuggestions = async (payload) => {
214
+ try {
215
+ CommerceApiClient.getInstance().suggestionsAbortController.abort();
216
+ CommerceApiClient.getInstance().suggestionsAbortController = new AbortController();
217
+ return (await CommerceApiClient.getInstance().inferenceApi.v1NextSuggestionsPost({ NextMessageRequest: messageRequestToCommerceMessageRequest(payload) }, { signal: CommerceApiClient.getInstance().suggestionsAbortController.signal })).map((resp) => validateSuggestion(resp)).filter((suggestion) => suggestion != null);
218
+ } catch (error) {
219
+ logger_default.logInfo("Failed to get suggestions", error, {
220
+ payloadContext: payload?.context,
221
+ userEvents: payload?.userEvents
222
+ });
223
+ await throwSessionRestartRequiredIf$1("Failed to get suggestions", error);
224
+ return [];
225
+ }
226
+ };
227
+ }
228
+ static {
229
+ this.getResponses = async (orgId, chatId, userId) => {
230
+ let data = {
231
+ responses: [],
232
+ suggestions: [],
233
+ user_events: []
234
+ };
235
+ const request = {
236
+ org_id: orgId,
237
+ chat_id: chatId,
238
+ user_id: userId
239
+ };
240
+ try {
241
+ data = await CommerceApiClient.getInstance().defaultApi.v1GetSessionMessages(request);
242
+ } catch (error) {
243
+ await throwSessionRestartRequiredIf$1("Failed to get chat responses", error);
244
+ }
245
+ const responses = data?.responses?.map((turn) => turn.map((response) => validateResponse(response)).filter((response) => response != null));
246
+ const suggestions = data?.suggestions.map((suggestion) => validateSuggestion(suggestion)).filter((suggestion) => suggestion != null);
247
+ const userEvents = data?.user_events.map((event) => validateUserEvent(event)).filter((event) => event != null);
248
+ const formSubmittedUserEventsFormIds = userEvents.filter((event) => event.category === UserEventCategory.FormSubmitted).map((event) => event.attributes.formResponseId);
249
+ const assistantMessages = responses.map((turn) => turn.filter((response) => !(response.category === ResponseCategory.Form && formSubmittedUserEventsFormIds.includes(response.id))).map((response) => messageFromResponse(response)).filter((message) => message != null)).filter((turn) => turn.length > 0);
250
+ const userMessages = userEvents.map((event) => {
251
+ if ([UserEventCategory.QueryTyped, UserEventCategory.Search].includes(event.category)) return [messageFromQueryEvent(event)];
252
+ if (event.category === UserEventCategory.SuggestionClicked) return [messageFromSuggestionEvent(event, suggestions)];
253
+ if (event.category === UserEventCategory.FormSubmitted) {
254
+ const formResponse = responses.flat().find((response) => response.id === event.attributes.formResponseId && event.attributes.formType !== FormType.Escalation);
255
+ if (formResponse && formResponse.category === ResponseCategory.Form) return [messageFromFormSubmittedEvent(event, formResponse.attributes)];
256
+ }
257
+ return [];
258
+ }).filter((message) => message.length > 0);
259
+ const sortedMessages = [...assistantMessages, ...userMessages].sort((a, b) => new Date(a[0].createdAt).getTime() - new Date(b[0].createdAt).getTime());
260
+ return {
261
+ responses,
262
+ userEvents,
263
+ suggestions,
264
+ messages: sortedMessages
265
+ };
266
+ };
267
+ }
268
+ static {
269
+ this.isSupportedEvent = async (payload) => {
270
+ try {
271
+ const httpResponseText = await (await CommerceApiClient.getInstance().inferenceApi.v1SupportedEventPostRaw({ SupportedEventRequest: coreSupportedEventRequestToApiRequest(payload) })).raw.text();
272
+ const httpResponseJson = JSON.parse(httpResponseText);
273
+ return {
274
+ ...httpResponseJson,
275
+ numberOfReviews: httpResponseJson.num_of_reviews,
276
+ merchant_tags: httpResponseJson.merchant_tags || []
277
+ };
278
+ } catch (err) {
279
+ logger_default.logError("Failed to get response for v1SupportedEventPost", { err });
280
+ return {
281
+ supported: false,
282
+ ready: false,
283
+ category: void 0,
284
+ collections: [],
285
+ numberOfReviews: void 0,
286
+ top_category: void 0,
287
+ merchant_tags: []
288
+ };
289
+ }
290
+ };
291
+ }
292
+ static {
293
+ this.identifyUser = async (spiffyUserId, merchantUserId, uaDetails) => {
294
+ try {
295
+ await CommerceApiClient.getInstance().defaultApi.v1AnalyticsIdentifyPost({ AnalyticsIdentifyRequest: {
296
+ user_id: spiffyUserId,
297
+ os_name: uaDetails.os,
298
+ os_version: uaDetails.osVersion,
299
+ platform: uaDetails.os,
300
+ device_id: uaDetails.deviceModel,
301
+ device_brand: uaDetails.deviceBrand,
302
+ device_manufacturer: uaDetails.deviceManufacturer,
303
+ device_model: uaDetails.deviceModel,
304
+ user_properties: {
305
+ cdp_user_id: merchantUserId,
306
+ browser: uaDetails.browser,
307
+ browser_version: uaDetails.browserVersion,
308
+ user_agent: uaDetails.userAgent
309
+ }
310
+ } });
311
+ } catch (err) {
312
+ logger_default.logError("Failed to identify user", err);
313
+ }
314
+ };
315
+ }
316
+ static {
317
+ this.mapContextSourceToV1OrgConfigGetSource = (source) => {
318
+ if (source === void 0) return void 0;
319
+ switch (source) {
320
+ case ContextSourceEnum.Fork: return V1OrgConfigGetSourceEnum.Fork;
321
+ case ContextSourceEnum.Playground: return V1OrgConfigGetSourceEnum.Playground;
322
+ case ContextSourceEnum.App: return V1OrgConfigGetSourceEnum.App;
323
+ case ContextSourceEnum.Test: return V1OrgConfigGetSourceEnum.Test;
324
+ default: return source;
325
+ }
326
+ };
327
+ }
328
+ static {
329
+ this.getOrgConfig = async (user_id) => {
330
+ try {
331
+ const atomStore = getAtomStore();
332
+ const reactAppName = atomStore.get(reactAppNameAtom);
333
+ const contextSource = atomStore.get(contextSourceAtom);
334
+ const featureFlagService = atomStore.get(featureFlagServiceAtom);
335
+ const request = {
336
+ namespace: reactAppName,
337
+ user_id,
338
+ source: this.mapContextSourceToV1OrgConfigGetSource(contextSource),
339
+ include_experiments: Object.values(ProductExperiment),
340
+ include_feature_gates: Object.entries(featureFlagService?.featureFlagService?.getFeatureFlags() || {}).filter(([, isEnabled]) => isEnabled).map(([featureGateName]) => featureGateName)
341
+ };
342
+ const response = await CommerceApiClient.getInstance().defaultApi.v1OrgConfigGet(request);
343
+ return validateOrgConfigResults(response);
344
+ } catch (err) {
345
+ logger_default.logError(`Failed to get org config`, err, { err });
346
+ return;
347
+ }
348
+ };
349
+ }
350
+ static {
351
+ this.addNoteToLatestConversation = async (spiffyUserId, email, customerServiceProvider) => {
352
+ logger_default.logInfo(`addNoteToLatestConversation - user_id=${spiffyUserId} email=${email} customer_service_provider=${customerServiceProvider}`);
353
+ try {
354
+ await CommerceApiClient.getInstance().customerServiceApi.v1CustserviceAddNoteToLatestConversationPost({ AddNoteToLatestConversationRequest: {
355
+ spiffy_user_id: spiffyUserId,
356
+ email,
357
+ customer_service_provider: customerServiceProvider
358
+ } });
359
+ } catch (err) {
360
+ logger_default.logError("Failed to add note to latest conversation", { err });
361
+ }
362
+ };
363
+ }
364
+ static {
365
+ this.getCustomerServiceApi = () => CommerceApiClient.getInstance().customerServiceApi;
366
+ }
367
+ };
368
+ var commerce_api_default = CommerceApiClient;
369
+
370
+ //#endregion
371
+ //#region src/hooks/useAmplitudeOperations.ts
372
+ const useAmplitudeTracking = () => {
373
+ const { trackEvent, isReady } = useAmplitude();
374
+ const [loading, setLoading] = useState(false);
375
+ const [error, setError] = useState(null);
376
+ return {
377
+ track: useCallback(async (eventName, eventProps) => {
378
+ if (!isReady) return;
379
+ setLoading(true);
380
+ setError(null);
381
+ try {
382
+ await trackEvent({
383
+ eventName,
384
+ eventProps
385
+ });
386
+ } catch (err) {
387
+ setError(err instanceof Error ? err : /* @__PURE__ */ new Error("Tracking failed"));
388
+ throw err;
389
+ } finally {
390
+ setLoading(false);
391
+ }
392
+ }, [trackEvent, isReady]),
393
+ loading,
394
+ error,
395
+ isReady
396
+ };
397
+ };
398
+
399
+ //#endregion
400
+ //#region src/hooks/useBlockBackButton.ts
401
+ const useBlockBackButton = (enabled, callback) => {
402
+ useEffect(() => {
403
+ if (enabled && window) {
404
+ if (window.history.scrollRestoration) window.history.scrollRestoration = "manual";
405
+ window.history.pushState(null, document.title, window.location.href);
406
+ window.onpopstate = (e) => {
407
+ e.preventDefault();
408
+ window.history.pushState(null, document.title, window.location.href);
409
+ callback?.();
410
+ };
411
+ }
412
+ return () => {
413
+ if (enabled && window) {
414
+ window.history.back();
415
+ window.onpopstate = null;
416
+ window.history.scrollRestoration = "auto";
417
+ }
418
+ };
419
+ }, [enabled]);
420
+ };
421
+
422
+ //#endregion
423
+ //#region src/hooks/useCdnOperations.ts
424
+ const useCdnUrl = () => {
425
+ const { cdnUrl } = useCdn();
426
+ return cdnUrl;
427
+ };
428
+ const useCdnBasePath = () => {
429
+ const { getCdnBasePath } = useCdn();
430
+ return getCdnBasePath();
431
+ };
432
+ const useAssetUrl = (assetName, orgShortName) => {
433
+ const { getAssetURL } = useCdn();
434
+ return getAssetURL(assetName, orgShortName);
435
+ };
436
+
437
+ //#endregion
438
+ //#region src/hooks/useChatToggle.ts
439
+ const useChatToggle = () => {
440
+ const onToggle = useSetAtom(chatOnToggleAtom);
441
+ const { isOpen } = useAtomValue(chatAtom);
442
+ const { trackEvent } = useAmplitude();
443
+ const toggle = (triggerLocation, triggerId) => {
444
+ if (!isOpen) trackEvent({
445
+ eventName: SpiffyMetricsEventName.ChatComponentExpanded,
446
+ eventProps: { message_metadata: {
447
+ trigger_location: triggerLocation,
448
+ trigger_id: triggerId
449
+ } }
450
+ });
451
+ else trackEvent({
452
+ eventName: SpiffyMetricsEventName.ChatComponentCollapsed,
453
+ eventProps: { message_metadata: {
454
+ trigger_location: triggerLocation,
455
+ trigger_id: triggerId
456
+ } }
457
+ });
458
+ onToggle();
459
+ };
460
+ const openChat = (triggerLocation, triggerId) => {
461
+ if (!isOpen) toggle(triggerLocation, triggerId);
462
+ };
463
+ const closeChat = (triggerLocation, triggerId) => {
464
+ if (isOpen) toggle(triggerLocation, triggerId);
465
+ };
466
+ return {
467
+ toggle,
468
+ isOpen,
469
+ openChat,
470
+ closeChat
471
+ };
472
+ };
473
+
474
+ //#endregion
475
+ //#region src/hooks/useChatToggleAnalytics.ts
476
+ const useChatToggleAnalytics = () => {
477
+ const setChatOnToggle = useSetAtom(chatOnToggleAtom);
478
+ const { track } = useAmplitudeTracking();
479
+ const toggleChat = (triggerLocation) => {
480
+ setChatOnToggle(triggerLocation, track);
481
+ };
482
+ return { toggleChat };
483
+ };
484
+
485
+ //#endregion
486
+ //#region src/hooks/useCustomerSupportHandoff.ts
487
+ /**
488
+ * Hook to call the `click` method of the merchant's customer support chat widget.
489
+ *
490
+ * @param onSwitchToAgent a function to override the function returned by the hook. This is mainly to
491
+ * preserve backward compatibility for merchants not using Kustomer and will be removed when all
492
+ * CS integrations are handled.
493
+ *
494
+ * @returns a function that searches for the customer support chat widget and calls the `click` method.
495
+ */
496
+ const useCustomerSupportHandoff = (onSwitchToAgent) => {
497
+ const onKustomerSwitch = useCallback(() => {
498
+ const kustomerElement = document.getElementById("kustomer-ui-sdk-iframe");
499
+ if (kustomerElement == null || !(kustomerElement instanceof HTMLIFrameElement)) {
500
+ logger_default.logError("[spiffy-ai] Kustomer iFrame element not found", void 0);
501
+ return;
502
+ }
503
+ const kustomerButton = kustomerElement.contentWindow?.document?.getElementById("rootChatIcon");
504
+ if (kustomerButton == null) {
505
+ logger_default.logError("[spiffy-ai] Kustomer button not found", void 0);
506
+ return;
507
+ }
508
+ kustomerButton.click();
509
+ }, []);
510
+ if (onSwitchToAgent != null) return { onSwitch: onSwitchToAgent };
511
+ return { onSwitch: onKustomerSwitch };
512
+ };
513
+
514
+ //#endregion
515
+ //#region src/hooks/useDebounce.ts
516
+ function useDebounce(value, delay) {
517
+ const [debouncedValue, setDebouncedValue] = useState(value);
518
+ useEffect(() => {
519
+ const handler = setTimeout(() => {
520
+ setDebouncedValue(value);
521
+ }, delay);
522
+ return () => {
523
+ clearTimeout(handler);
524
+ };
525
+ }, [value, delay]);
526
+ return debouncedValue;
527
+ }
528
+
529
+ //#endregion
530
+ //#region src/hooks/useElementObserver.ts
531
+ const useElementObserver = (selector) => {
532
+ const INITIAL_RENDER_STATE = true;
533
+ const eoRef = useRef(DOMObserver.add(selector));
534
+ const [renderBlocked, setRenderBlocked] = useState(INITIAL_RENDER_STATE);
535
+ /**
536
+ * Fired every time the HTML element changes.
537
+ *
538
+ * @param fn
539
+ */
540
+ const onChange = (fn) => {
541
+ eoRef.current?.registerOnChange(fn);
542
+ };
543
+ /**
544
+ * Fired when the HTML element is added to the DOM.
545
+ *
546
+ * @param fn
547
+ */
548
+ const onAdd = (fn) => {
549
+ eoRef.current?.registerOnAdd(fn);
550
+ };
551
+ /**
552
+ * Fired when the HTML element is removed from the DOM.
553
+ *
554
+ * @param fn
555
+ */
556
+ const onRemove = (fn) => {
557
+ eoRef.current?.registerOnRemove(fn);
558
+ };
559
+ /**
560
+ * Fired when the class of the HTML element changes.
561
+ *
562
+ * @param fn
563
+ */
564
+ const onClassChange = (fn) => {
565
+ eoRef.current?.registerOnclassChange(fn);
566
+ };
567
+ /**
568
+ * Fired when a class is added to the HTML element.
569
+ *
570
+ * @param className
571
+ * @param fn
572
+ */
573
+ const onClassAdded = (className, fn) => {
574
+ eoRef.current?.registerOnClassAdded(className, fn);
575
+ };
576
+ /**
577
+ * Fired when a class is removed from the HTML element.
578
+ *
579
+ * @param className
580
+ * @param fn
581
+ */
582
+ const onClassRemoved = (className, fn) => {
583
+ eoRef.current?.registerOnClassRemoved(className, fn);
584
+ };
585
+ /**
586
+ * Fired when a child element is added to the HTML element.
587
+ *
588
+ * @param fn
589
+ */
590
+ const onAddChild = (fn) => {
591
+ eoRef.current?.registerOnAddChild(fn);
592
+ };
593
+ /**
594
+ * Fired when a child element is removed from the HTML element.
595
+ *
596
+ * @param fn
597
+ */
598
+ const onRemoveChild = (fn) => {
599
+ eoRef.current?.registerOnRemoveChild(fn);
600
+ };
601
+ /**
602
+ * Allows hooking event listeners to the HTML element, such as `focus`, `blur`, etc.
603
+ *
604
+ * @param event
605
+ * @param fn
606
+ */
607
+ const onEvent = (event, fn) => {
608
+ eoRef.current.registerEvent(event, fn);
609
+ };
610
+ /**
611
+ * Useful when rendering a React.js component inside the HTML element.
612
+ *
613
+ * @param fn
614
+ * @returns
615
+ */
616
+ const render = (fn) => {
617
+ if (!renderBlocked) return eoRef.current.render(fn);
618
+ };
619
+ /**
620
+ * Checks if the element exists in the DOM.
621
+ *
622
+ * @returns
623
+ */
624
+ const exists = () => !!eoRef.current.getNode();
625
+ /**
626
+ * Checks if rendering is unblocked.
627
+ *
628
+ * @returns
629
+ */
630
+ const isRendered = () => !renderBlocked;
631
+ /**
632
+ * Triggers an event for the HTML element.
633
+ *
634
+ * @param event
635
+ */
636
+ const fire = (event) => {
637
+ eoRef.current.fire(event);
638
+ };
639
+ /**
640
+ * Shows the HTML element.
641
+ *
642
+ * @returns
643
+ */
644
+ const show = () => eoRef.current.show();
645
+ /**
646
+ * Hides the HTML element.
647
+ *
648
+ * @returns
649
+ */
650
+ const hide = () => eoRef.current.hide();
651
+ /**
652
+ * Blocks the rendering of elements.
653
+ *
654
+ * @returns
655
+ */
656
+ const blockRendering = () => setRenderBlocked(true);
657
+ /**
658
+ * Unblocks the rendering of elements.
659
+ *
660
+ * @returns
661
+ */
662
+ const unblockRendering = () => setRenderBlocked(false);
663
+ /**
664
+ * Applies CSS styles to the HTML element.
665
+ *
666
+ * @param styles
667
+ */
668
+ const applyStyle = (styles) => {
669
+ const node = eoRef?.current?.getNode();
670
+ node && Object.assign(node.style, styles);
671
+ };
672
+ useEffect(() => {
673
+ eoRef.current.init();
674
+ eoRef.current.registerOnReset(() => setRenderBlocked(INITIAL_RENDER_STATE));
675
+ DOMObserver.observe();
676
+ return () => DOMObserver.remove(selector);
677
+ }, [selector.getPattern()]);
678
+ return {
679
+ targetNode: eoRef.current.getNode(),
680
+ onChange,
681
+ onAdd,
682
+ onRemove,
683
+ onClassChange,
684
+ onClassAdded,
685
+ onClassRemoved,
686
+ onAddChild,
687
+ onRemoveChild,
688
+ onEvent,
689
+ blockRendering,
690
+ unblockRendering,
691
+ exists,
692
+ isRendered,
693
+ render,
694
+ fire,
695
+ show,
696
+ hide,
697
+ applyStyle
698
+ };
699
+ };
700
+
701
+ //#endregion
702
+ //#region src/hooks/useGrabAndScroll.ts
703
+ const animateHorizontalScroll = ({ element, duration, targetScroll, multiply = 1, direction, callback, offset = 0 }) => {
704
+ const start = element.scrollLeft;
705
+ const distance = (targetScroll - start) * multiply;
706
+ const startTime = performance.now();
707
+ function easeOutSine(x) {
708
+ return Math.sin(x * Math.PI / 2);
709
+ }
710
+ function scrollStep(currentTime) {
711
+ const timeElapsed = currentTime - startTime;
712
+ const progress = Math.min(timeElapsed / duration, 1);
713
+ const easing = easeOutSine(progress);
714
+ const step = start + distance * easing;
715
+ const canScroll = (direction === "rt" ? element.scrollLeft < step : element.scrollLeft > step) || !direction;
716
+ if (step > 0 && canScroll) element.scrollTo(step, 0);
717
+ if (timeElapsed < duration) requestAnimationFrame(scrollStep);
718
+ else if (element.scrollLeft + offset === element.scrollWidth) callback?.("rt");
719
+ else if (element.scrollLeft <= 1) callback?.("lt");
720
+ else callback?.("ct");
721
+ }
722
+ requestAnimationFrame(scrollStep);
723
+ };
724
+ const useGrabAndScroll = (enabled, chunkWidth, speed = 400, offset = 0) => {
725
+ const containerRef = useRef(null);
726
+ const [leftArrow, setLeftArrow] = useState(false);
727
+ const [rightArrow, setRightArrow] = useState(true);
728
+ const handleArrows = (position) => {
729
+ switch (position) {
730
+ case "lt":
731
+ setLeftArrow(false);
732
+ setRightArrow(true);
733
+ break;
734
+ case "rt":
735
+ setLeftArrow(true);
736
+ setRightArrow(false);
737
+ break;
738
+ default:
739
+ setLeftArrow(true);
740
+ setRightArrow(true);
741
+ }
742
+ };
743
+ const animationTrigger = () => {
744
+ if (enabled && containerRef.current) {
745
+ const dist = (containerRef?.current?.scrollLeft || 0) / chunkWidth;
746
+ const targetScroll = chunkWidth * (Math.floor(dist) + (dist % 1 > .5 ? 1 : 0));
747
+ animateHorizontalScroll({
748
+ element: containerRef.current,
749
+ targetScroll,
750
+ duration: speed,
751
+ offset,
752
+ callback: handleArrows
753
+ });
754
+ }
755
+ };
756
+ const onNext = (cardsToSlide) => {
757
+ if (containerRef.current) {
758
+ const targetScroll = containerRef.current.scrollLeft + chunkWidth;
759
+ animateHorizontalScroll({
760
+ element: containerRef.current,
761
+ targetScroll,
762
+ duration: speed,
763
+ direction: "rt",
764
+ multiply: cardsToSlide,
765
+ offset,
766
+ callback: handleArrows
767
+ });
768
+ }
769
+ };
770
+ const onPrevious = (cardsToSlide) => {
771
+ if (containerRef.current) {
772
+ const targetScroll = containerRef.current.scrollLeft - chunkWidth;
773
+ animateHorizontalScroll({
774
+ element: containerRef.current,
775
+ targetScroll,
776
+ duration: speed,
777
+ direction: "lt",
778
+ multiply: cardsToSlide,
779
+ offset,
780
+ callback: handleArrows
781
+ });
782
+ }
783
+ };
784
+ return {
785
+ containerRef,
786
+ leftArrow,
787
+ rightArrow,
788
+ animationTrigger,
789
+ onNext,
790
+ onPrevious
791
+ };
792
+ };
793
+
794
+ //#endregion
795
+ //#region src/contexts/graphqlContext.tsx
796
+ const GraphQLContext = createContext(null);
797
+ const colorsAndFrontendConfigQuery = () => `
798
+ query ($version: String = "${configVersion()}") {
799
+ me {
800
+ getProductsConfigByVersion(version: $version) {
801
+ frontend { values }
802
+ colors { values }
803
+ }
804
+ }
805
+ }
806
+ `;
807
+ const GraphQLProvider = ({ children }) => {
808
+ const apiKey = useAtomValue(orgLevelApiKeyAtom);
809
+ const baseUrl = useAtomValue(baseUrlAtom);
810
+ const isReady = Boolean(apiKey && baseUrl);
811
+ const executeQuery = useCallback(async (query, variables) => {
812
+ if (!isReady) throw new Error("GraphQL client not ready - missing apiKey or baseUrl");
813
+ const response = await fetch(`${baseUrl}/v1/graphql`, {
814
+ method: "POST",
815
+ headers: {
816
+ "Content-Type": "application/json",
817
+ Authorization: `Bearer ${apiKey}`
818
+ },
819
+ body: JSON.stringify({
820
+ query,
821
+ variables
822
+ })
823
+ });
824
+ if (!response.ok) throw new Error(`GraphQL request failed: ${response.statusText}`);
825
+ const result = await response.json();
826
+ if (result.errors) throw new Error(`GraphQL errors: ${JSON.stringify(result.errors)}`);
827
+ return result.data;
828
+ }, [
829
+ apiKey,
830
+ baseUrl,
831
+ isReady
832
+ ]);
833
+ const getOrgId = useCallback(async () => {
834
+ const response = await executeQuery(getMerchantOrgIdQuery);
835
+ return validateGraphQLOrgId(response.me.org?.id);
836
+ }, [executeQuery]);
837
+ const getColorsAndFrontendConfig = useCallback(async () => {
838
+ try {
839
+ const query = await colorsAndFrontendConfigQuery();
840
+ if (!query) throw new Error("Colors and frontend config query is not defined");
841
+ const response = await executeQuery(query);
842
+ const colorsConfig = response.me.getProductsConfigByVersion?.colors?.values;
843
+ const frontendConfig = response.me.getProductsConfigByVersion?.frontend?.values;
844
+ const transformedColorConfig = transformSnakeToCamel(colorsConfig);
845
+ const transformedFrontendConfig = transformSnakeToCamel(frontendConfig);
846
+ return {
847
+ colorsConfig: transformedColorConfig,
848
+ frontendConfig: transformedFrontendConfig
849
+ };
850
+ } catch (err) {
851
+ logger_default.logError("Error fetching graphql colors and frontend config", err);
852
+ return {
853
+ colorsConfig: void 0,
854
+ frontendConfig: void 0
855
+ };
856
+ }
857
+ }, [executeQuery]);
858
+ const value = useMemo(() => ({
859
+ executeQuery,
860
+ getOrgId,
861
+ getColorsAndFrontendConfig,
862
+ isReady
863
+ }), [
864
+ executeQuery,
865
+ getOrgId,
866
+ getColorsAndFrontendConfig,
867
+ isReady
868
+ ]);
869
+ return /* @__PURE__ */ jsx(GraphQLContext.Provider, {
870
+ value,
871
+ children
872
+ });
873
+ };
874
+ const useGraphQLClient = () => {
875
+ const context = useContext(GraphQLContext);
876
+ if (!context) throw new Error("useGraphQLClient must be used within a GraphQLProvider");
877
+ return context;
878
+ };
879
+
880
+ //#endregion
881
+ //#region src/hooks/useGraphQLConfig.ts
882
+ const useColorsAndFrontendConfig = () => {
883
+ const { getColorsAndFrontendConfig, isReady } = useGraphQLClient();
884
+ const [data, setData] = useState({});
885
+ const [loading, setLoading] = useState(false);
886
+ const [error, setError] = useState(null);
887
+ const fetchConfig = useCallback(async () => {
888
+ if (!isReady) return;
889
+ setLoading(true);
890
+ setError(null);
891
+ try {
892
+ const result = await getColorsAndFrontendConfig();
893
+ setData(result);
894
+ } catch (err) {
895
+ setError(err instanceof Error ? err : /* @__PURE__ */ new Error("Unknown error"));
896
+ } finally {
897
+ setLoading(false);
898
+ }
899
+ }, [getColorsAndFrontendConfig, isReady]);
900
+ useEffect(() => {
901
+ fetchConfig();
902
+ }, [fetchConfig]);
903
+ return {
904
+ data,
905
+ loading,
906
+ error,
907
+ refetch: fetchConfig
908
+ };
909
+ };
910
+ const useOrgId = () => {
911
+ const { getOrgId, isReady } = useGraphQLClient();
912
+ const [orgId, setOrgId] = useState();
913
+ const [loading, setLoading] = useState(false);
914
+ const [error, setError] = useState(null);
915
+ useEffect(() => {
916
+ if (!isReady) return;
917
+ const fetchOrgId = async () => {
918
+ setLoading(true);
919
+ setError(null);
920
+ try {
921
+ const id = await getOrgId();
922
+ setOrgId(id);
923
+ } catch (err) {
924
+ setError(err instanceof Error ? err : /* @__PURE__ */ new Error("Unknown error"));
925
+ } finally {
926
+ setLoading(false);
927
+ }
928
+ };
929
+ fetchOrgId();
930
+ }, [getOrgId, isReady]);
931
+ return {
932
+ orgId,
933
+ loading,
934
+ error
935
+ };
936
+ };
937
+
938
+ //#endregion
939
+ //#region src/contexts/userIdentityContext.tsx
940
+ const getUserAgentDetails = () => {
941
+ const result = new UAParser().getResult();
942
+ return {
943
+ os: result?.os?.name,
944
+ osVersion: result?.os?.version,
945
+ deviceBrand: result?.device?.vendor,
946
+ deviceManufacturer: result?.device?.vendor,
947
+ deviceModel: result?.device?.model,
948
+ browser: result?.browser?.name,
949
+ browserVersion: result?.browser?.version,
950
+ userAgent: result?.ua
951
+ };
952
+ };
953
+ const UserIdentityContext = createContext(void 0);
954
+ const UserIdentityProvider = ({ children }) => {
955
+ const { getItem, setItem, isAvailable: localStorageIsReady } = useLocalStorage();
956
+ const [isReady, setIsReady] = useState(false);
957
+ useEffect(() => {
958
+ setIsReady(localStorageIsReady);
959
+ }, [localStorageIsReady]);
960
+ const USER_ID_OVERRIDE_KEY = "v1-spiffy-user-id-override";
961
+ const USER_ID_DEFAULT_KEY = "v1-spiffy-user-id-default";
962
+ const getUserIdOverrideFromLocalStorage = useCallback(() => {
963
+ return getItem(USER_ID_OVERRIDE_KEY) ?? void 0;
964
+ }, [getItem]);
965
+ const getUserIdDefaultFromLocalStorage = useCallback(() => {
966
+ return getItem(USER_ID_DEFAULT_KEY) ?? void 0;
967
+ }, [getItem]);
968
+ const setUserIdDefaultInLocalStorage = useCallback((userId) => {
969
+ logger_default.logInfo(`setUserIdDefaultInLocalStorage - Setting user_id=${userId}`);
970
+ setItem(USER_ID_DEFAULT_KEY, userId);
971
+ return userId;
972
+ }, [setItem, USER_ID_DEFAULT_KEY]);
973
+ const setUserIdOverrideInLocalStorage = useCallback((userId) => {
974
+ logger_default.logInfo(`setUserIdOverrideInLocalStorage - Setting user_id=${userId}`);
975
+ setItem(USER_ID_OVERRIDE_KEY, userId);
976
+ return userId;
977
+ }, [setItem, USER_ID_OVERRIDE_KEY]);
978
+ const clearUserIdOverrideInLocalStorage = useCallback(() => {
979
+ logger_default.logInfo(`clearUserIdOverrideInLocalStorage - Clearing user_id`);
980
+ setItem(USER_ID_OVERRIDE_KEY, "");
981
+ }, [setItem, USER_ID_OVERRIDE_KEY]);
982
+ const getUserIdOrDefault = useCallback(() => {
983
+ const userIdOverride = getUserIdOverrideFromLocalStorage();
984
+ if (userIdOverride) return userIdOverride;
985
+ const defaultUserId = getUserIdDefaultFromLocalStorage();
986
+ if (defaultUserId) return defaultUserId;
987
+ return setUserIdDefaultInLocalStorage(`spiffy-user-id-${v4()}`);
988
+ }, [
989
+ getUserIdOverrideFromLocalStorage,
990
+ getUserIdDefaultFromLocalStorage,
991
+ setUserIdDefaultInLocalStorage
992
+ ]);
993
+ const identifyUser = useCallback(async () => {
994
+ if (!isReady) {
995
+ logger_default.logWarn("[UserIdentityContext] Context not ready, skipping identifyUser", void 0);
996
+ return;
997
+ }
998
+ try {
999
+ const cdpUserId = "UNKNOWN_CDP_USER_ID";
1000
+ const userId = getUserIdOrDefault();
1001
+ const userAgentDetails = getUserAgentDetails();
1002
+ await commerce_api_default.identifyUser(userId, cdpUserId, userAgentDetails);
1003
+ } catch (error) {
1004
+ logger_default.logError("[spiffy-ai] Error identifying user", error);
1005
+ }
1006
+ }, [isReady, getUserIdOrDefault]);
1007
+ const value = useMemo(() => ({
1008
+ identifyUser,
1009
+ getUserIdOrDefault,
1010
+ getUserIdOverrideFromLocalStorage,
1011
+ getUserIdDefaultFromLocalStorage,
1012
+ setUserIdDefaultInLocalStorage,
1013
+ setUserIdOverrideInLocalStorage,
1014
+ clearUserIdOverrideInLocalStorage,
1015
+ isReady
1016
+ }), [
1017
+ identifyUser,
1018
+ getUserIdOrDefault,
1019
+ getUserIdOverrideFromLocalStorage,
1020
+ getUserIdDefaultFromLocalStorage,
1021
+ setUserIdDefaultInLocalStorage,
1022
+ setUserIdOverrideInLocalStorage,
1023
+ clearUserIdOverrideInLocalStorage,
1024
+ isReady
1025
+ ]);
1026
+ return /* @__PURE__ */ jsx(UserIdentityContext.Provider, {
1027
+ value,
1028
+ children
1029
+ });
1030
+ };
1031
+ const useUserIdentity = () => {
1032
+ const context = useContext(UserIdentityContext);
1033
+ if (!context) throw new Error("useUserIdentity must be used within a UserIdentityProvider");
1034
+ return context;
1035
+ };
1036
+
1037
+ //#endregion
1038
+ //#region src/hooks/useIdentifyUser.ts
1039
+ const useIdentifyUser = () => {
1040
+ const { identifyUser, isReady } = useUserIdentity();
1041
+ const [loading, setLoading] = useState(false);
1042
+ const [error, setError] = useState(null);
1043
+ const executeIdentifyUser = useCallback(async () => {
1044
+ if (!isReady) {
1045
+ setError(/* @__PURE__ */ new Error("UserIdentityContext not ready."));
1046
+ return;
1047
+ }
1048
+ setLoading(true);
1049
+ setError(null);
1050
+ try {
1051
+ await identifyUser();
1052
+ } catch (err) {
1053
+ setError(err instanceof Error ? err : /* @__PURE__ */ new Error("Unknown error during user identification."));
1054
+ throw err;
1055
+ } finally {
1056
+ setLoading(false);
1057
+ }
1058
+ }, [identifyUser, isReady]);
1059
+ return {
1060
+ loading,
1061
+ error,
1062
+ executeIdentifyUser,
1063
+ isReady
1064
+ };
1065
+ };
1066
+
1067
+ //#endregion
1068
+ //#region src/hooks/useImageResolver.ts
1069
+ var ImageResolver = class {};
1070
+ var MerchantImageResolver = class {
1071
+ static {
1072
+ this.imageResolverMap = /* @__PURE__ */ new Map();
1073
+ }
1074
+ static loadMapping() {
1075
+ if (this.imageResolverMap.size === 0) {
1076
+ this.imageResolverMap.set(OrgShortName.Spanx, new ShopifyImageResolver());
1077
+ this.imageResolverMap.set(OrgShortName.SpanxStaging, new ShopifyImageResolver());
1078
+ this.imageResolverMap.set(OrgShortName.UniqueVintage, new ShopifyImageResolver());
1079
+ }
1080
+ return this.imageResolverMap;
1081
+ }
1082
+ static get(name) {
1083
+ return this.loadMapping().get(name);
1084
+ }
1085
+ };
1086
+ var ShopifyImageResolver = class extends ImageResolver {
1087
+ resolve(url, size) {
1088
+ const pattern = /_\d+x\.jpg/;
1089
+ const urlHasPrefix = pattern.test(url);
1090
+ const newSizePrefix = `_${size}x.jpg`;
1091
+ if (urlHasPrefix) return url.replace(pattern, newSizePrefix);
1092
+ return url.replace(".jpg", newSizePrefix);
1093
+ }
1094
+ };
1095
+ const useImageResolver = () => {
1096
+ const orgShortName = useAtomValue(orgShortNameAtom);
1097
+ const resolve = (image, size) => {
1098
+ if (image && size && orgShortName) return MerchantImageResolver.get(orgShortName)?.resolve(image, size) || image;
1099
+ return image;
1100
+ };
1101
+ return { resolve };
1102
+ };
1103
+
1104
+ //#endregion
1105
+ //#region src/hooks/useIntersection.ts
1106
+ const useIntersection = (element, rootMargin) => {
1107
+ const [isVisible, setIsVisible] = useState(false);
1108
+ useEffect(() => {
1109
+ const current = element?.current;
1110
+ const observer = new IntersectionObserver(([entry]) => {
1111
+ setIsVisible(entry.isIntersecting);
1112
+ }, { rootMargin });
1113
+ if (current) observer?.observe(current);
1114
+ return () => {
1115
+ if (current) observer.unobserve(current);
1116
+ };
1117
+ }, []);
1118
+ return isVisible;
1119
+ };
1120
+
1121
+ //#endregion
1122
+ //#region src/hooks/useIsSmallScreen.ts
1123
+ const useIsSmallScreen = () => {
1124
+ const [isSmall, setIsSmall] = useState(false);
1125
+ useEffect(() => {
1126
+ const mediaQuery = window.matchMedia("(max-width: 479px)");
1127
+ setIsSmall(mediaQuery.matches);
1128
+ const handleResize = (event) => {
1129
+ setIsSmall(event.matches);
1130
+ };
1131
+ mediaQuery.addEventListener("change", handleResize);
1132
+ return () => mediaQuery.removeEventListener("change", handleResize);
1133
+ }, []);
1134
+ return isSmall;
1135
+ };
1136
+
1137
+ //#endregion
1138
+ //#region src/hooks/useLocalStorageOperations.ts
1139
+ const useLocalStorageValue = (key) => {
1140
+ const { getItem, setItem, attachListener, detachListener } = useLocalStorage();
1141
+ const [value, setValue] = useState(() => getItem(key));
1142
+ useEffect(() => {
1143
+ const listener = {
1144
+ storageKey: key,
1145
+ listener: (event) => {
1146
+ setValue(event.newValue);
1147
+ }
1148
+ };
1149
+ attachListener(listener);
1150
+ return () => detachListener(listener);
1151
+ }, [
1152
+ key,
1153
+ attachListener,
1154
+ detachListener
1155
+ ]);
1156
+ const updateValue = useCallback((newValue) => {
1157
+ setItem(key, newValue);
1158
+ setValue(newValue);
1159
+ }, [key, setItem]);
1160
+ return {
1161
+ value,
1162
+ setValue: updateValue
1163
+ };
1164
+ };
1165
+ const useSpiffyFeatureFlag = () => {
1166
+ const { setSpiffyOnFeatureFlag } = useLocalStorage();
1167
+ const { value } = useLocalStorageValue(LocalStorageKeys.SpiffyOnOverride);
1168
+ const setFlag = useCallback((flag) => {
1169
+ setSpiffyOnFeatureFlag(flag);
1170
+ }, [setSpiffyOnFeatureFlag]);
1171
+ return {
1172
+ value: value === "true" ? true : value === "false" ? false : null,
1173
+ setFlag
1174
+ };
1175
+ };
1176
+ const useEnviveFeatureFlag = () => {
1177
+ const { setItem, getItem } = useLocalStorage();
1178
+ const { value } = useLocalStorageValue(LocalStorageKeys.EnviveOnOverride);
1179
+ const setFlag = useCallback((flag) => {
1180
+ if (flag === true) setItem(LocalStorageKeys.EnviveOnOverride, "true");
1181
+ else if (flag === false) setItem(LocalStorageKeys.EnviveOnOverride, "false");
1182
+ }, [setItem]);
1183
+ return {
1184
+ value: value === "true" ? true : value === "false" ? false : null,
1185
+ setFlag
1186
+ };
1187
+ };
1188
+ const useLocalStorageListener = (key, callback) => {
1189
+ const { attachListener, detachListener } = useLocalStorage();
1190
+ useEffect(() => {
1191
+ const listener = {
1192
+ storageKey: key,
1193
+ listener: callback
1194
+ };
1195
+ attachListener(listener);
1196
+ return () => detachListener(listener);
1197
+ }, [
1198
+ key,
1199
+ callback,
1200
+ attachListener,
1201
+ detachListener
1202
+ ]);
1203
+ };
1204
+
1205
+ //#endregion
1206
+ //#region src/hooks/useMessageFilter.ts
1207
+ const useMessageFilter = () => {
1208
+ const findMessageIndex = ({ msgs, type, role }) => {
1209
+ let lastIndex = -1;
1210
+ msgs.forEach((subArray, index) => {
1211
+ subArray.forEach((obj) => {
1212
+ if (obj.type === type || obj.role === role) lastIndex = index;
1213
+ });
1214
+ });
1215
+ return lastIndex;
1216
+ };
1217
+ const removePreviousDiscussions = (msgs, index) => {
1218
+ if (index > -1) {
1219
+ const lastMessages = msgs.slice(index);
1220
+ return lastMessages.length > 0 ? lastMessages : msgs;
1221
+ }
1222
+ return msgs;
1223
+ };
1224
+ const getFilteredMessages = (msgs, skipFilter) => {
1225
+ const messageMap = msgs.reduce((acc, msg) => {
1226
+ acc[msg[0].id] = msg;
1227
+ return acc;
1228
+ }, {});
1229
+ const deduplicatedMsgs = Object.values(messageMap);
1230
+ if (!skipFilter) {
1231
+ const idx = findMessageIndex({
1232
+ msgs: deduplicatedMsgs,
1233
+ type: MessageType.Separator
1234
+ });
1235
+ return removePreviousDiscussions(deduplicatedMsgs, idx);
1236
+ }
1237
+ return deduplicatedMsgs;
1238
+ };
1239
+ return {
1240
+ findMessageIndex,
1241
+ removePreviousDiscussions,
1242
+ getFilteredMessages
1243
+ };
1244
+ };
1245
+
1246
+ //#endregion
1247
+ //#region src/hooks/useMessageScrollObserver.ts
1248
+ const useMessageScrollObserver = (boxRef, scrollRef, onScrollChange) => {
1249
+ const calculateScrollHeight = () => {
1250
+ const boxHeight = boxRef?.current?.getBoundingClientRect().height || 0;
1251
+ const scrollHeight = scrollRef?.current?.getBoundingClientRect().height || 0;
1252
+ return boxHeight - scrollHeight;
1253
+ };
1254
+ const updateState = () => {
1255
+ const scrollHeight = calculateScrollHeight();
1256
+ if (scrollHeight > 0) onScrollChange(scrollHeight);
1257
+ };
1258
+ useEffect(() => {
1259
+ let boxRO = null;
1260
+ let scrollRO = null;
1261
+ if (scrollRef?.current) {
1262
+ boxRO = new ResizeObserver(updateState);
1263
+ boxRO.observe(scrollRef?.current);
1264
+ }
1265
+ if (boxRef?.current) {
1266
+ scrollRO = new ResizeObserver(updateState);
1267
+ scrollRO.observe(boxRef?.current);
1268
+ }
1269
+ return () => {
1270
+ if (scrollRef?.current && boxRO) boxRO.unobserve(scrollRef?.current);
1271
+ if (scrollRO && boxRef?.current) scrollRO?.unobserve(boxRef?.current);
1272
+ };
1273
+ }, []);
1274
+ };
1275
+
1276
+ //#endregion
1277
+ //#region src/contexts/featureFlagServiceContext.tsx
1278
+ var FeatureFlagService = class {
1279
+ constructor(featureGates) {
1280
+ this.isFeatureGateEnabled = (featureGate) => {
1281
+ const gateValue = this.featureGates.find((gate) => gate.name === featureGate);
1282
+ if (gateValue == null || gateValue.value == null) {
1283
+ logger_default.logDebug(`[spiffy-ai] isFeatureGateEnabled featureGate:${featureGate} value is undefined - returning false`);
1284
+ return false;
1285
+ }
1286
+ return gateValue.value;
1287
+ };
1288
+ this.isClientSessionEnabled = () => {
1289
+ return this.featureGates.filter((gate) => gate.name === FeatureGates.IsClientSessionEnabled && gate.value === true).length > 0;
1290
+ };
1291
+ this.getFeatureFlags = () => {
1292
+ return Object.fromEntries(Object.values(FeatureGates).map((featureGate) => [featureGate, this.isFeatureGateEnabled(featureGate)]));
1293
+ };
1294
+ this.featureGates = featureGates;
1295
+ }
1296
+ };
1297
+ const FeatureFlagServiceContext = createContext(void 0);
1298
+ const FeatureFlagServiceProvider = ({ featureGates, children }) => {
1299
+ const featureFlagService = useMemo(() => new FeatureFlagService(featureGates), [featureGates]);
1300
+ return /* @__PURE__ */ jsx(FeatureFlagServiceContext.Provider, {
1301
+ value: { featureFlagService },
1302
+ children
1303
+ });
1304
+ };
1305
+ const useFeatureFlagService = () => {
1306
+ const context = useContext(FeatureFlagServiceContext);
1307
+ if (context === void 0) throw new Error("useFeatureFlagService must be used within a FeatureFlagServiceProvider");
1308
+ return context;
1309
+ };
1310
+
1311
+ //#endregion
1312
+ //#region src/contexts/newOrgConfigContext.tsx
1313
+ const NewOrgConfigContext = createContext(void 0);
1314
+ const NewOrgConfigProvider = ({ children }) => {
1315
+ const [oldConfig, setOldConfig] = useState();
1316
+ const orgShortName = useAtomValue(orgShortNameAtom);
1317
+ const setNewOrgConfig = useSetAtom(newOrgConfigAtom);
1318
+ const { data: newConfig, loading, error } = useColorsAndFrontendConfig();
1319
+ useEffect(() => {
1320
+ if (orgShortName) getOrgInfo(orgShortName).then(setOldConfig);
1321
+ }, [orgShortName]);
1322
+ const combinedConfig = useMemo(() => {
1323
+ if (!oldConfig || !newConfig) return null;
1324
+ return {
1325
+ ...oldConfig,
1326
+ ...newConfig
1327
+ };
1328
+ }, [oldConfig, newConfig]);
1329
+ useEffect(() => {
1330
+ const atomStore = getAtomStore();
1331
+ if (combinedConfig) {
1332
+ atomStore.set(orgIdAtom, "mock-org-id");
1333
+ setNewOrgConfig(combinedConfig);
1334
+ }
1335
+ }, [combinedConfig, setNewOrgConfig]);
1336
+ const contextValue = useMemo(() => {
1337
+ if (!orgShortName || loading && !oldConfig) return {
1338
+ combinedConfig: null,
1339
+ loading: true,
1340
+ error: null
1341
+ };
1342
+ if (error) return {
1343
+ combinedConfig: null,
1344
+ loading: false,
1345
+ error
1346
+ };
1347
+ return {
1348
+ combinedConfig,
1349
+ loading: false,
1350
+ error: null
1351
+ };
1352
+ }, [
1353
+ orgShortName,
1354
+ loading,
1355
+ error,
1356
+ oldConfig,
1357
+ combinedConfig
1358
+ ]);
1359
+ return /* @__PURE__ */ jsx(NewOrgConfigContext.Provider, {
1360
+ value: contextValue,
1361
+ children: /* @__PURE__ */ jsx(FeatureFlagServiceProvider, {
1362
+ featureGates: [],
1363
+ children
1364
+ })
1365
+ });
1366
+ };
1367
+ const useNewOrgConfigContext = () => {
1368
+ const context = useContext(NewOrgConfigContext);
1369
+ if (context === void 0) throw new Error("useNewOrgConfigContext must be used within a NewOrgConfigProvider");
1370
+ return context;
1371
+ };
1372
+
1373
+ //#endregion
1374
+ //#region src/hooks/useNewOrgConfig.ts
1375
+ const useNewOrgConfig = () => {
1376
+ const { combinedConfig, loading, error } = useNewOrgConfigContext();
1377
+ return {
1378
+ ...combinedConfig,
1379
+ loading,
1380
+ error
1381
+ };
1382
+ };
1383
+
1384
+ //#endregion
1385
+ //#region src/hooks/utils.ts
1386
+ const isElementPartiallyVisible = (el) => {
1387
+ if (!el) return false;
1388
+ const rect = el.getBoundingClientRect();
1389
+ const windowHeight = window.innerHeight || document.documentElement.clientHeight;
1390
+ const windowWidth = window.innerWidth || document.documentElement.clientWidth;
1391
+ const verticallyVisible = Math.round(rect.top) < windowHeight && Math.round(rect.bottom) > 0;
1392
+ const horizontallyVisible = Math.round(rect.left) < windowWidth && Math.round(rect.right) > 0;
1393
+ return verticallyVisible && horizontallyVisible;
1394
+ };
1395
+ const createAppLoadedEvent = () => ({
1396
+ eventId: v4(),
1397
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
1398
+ category: UserEventCategory.AppLoaded
1399
+ });
1400
+ const createVisitUserEvent = ({ variantInfo }) => {
1401
+ if (variantInfo.variant === "pdp" && variantInfo.productId != null) return {
1402
+ eventId: v4(),
1403
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
1404
+ category: UserEventCategory.PdpVisit,
1405
+ attributes: {
1406
+ productId: variantInfo.productId,
1407
+ parentProductId: variantInfo.parentProductId ?? "",
1408
+ url: variantInfo.url ?? ""
1409
+ }
1410
+ };
1411
+ if (variantInfo.variant === "plp" && variantInfo.plpId != null) return {
1412
+ eventId: v4(),
1413
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
1414
+ category: UserEventCategory.PlpVisit,
1415
+ attributes: {
1416
+ category: PLPAttributeCategory.Id,
1417
+ attributes: { id: variantInfo.plpId }
1418
+ }
1419
+ };
1420
+ if (variantInfo.variant === "page_visit") return {
1421
+ eventId: v4(),
1422
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
1423
+ category: UserEventCategory.PageVisit,
1424
+ attributes: {
1425
+ url: variantInfo.url,
1426
+ pageVisitCategory: variantInfo.pageVisitCategory
1427
+ }
1428
+ };
1429
+ };
1430
+ const parseTime = (time, timeZone) => {
1431
+ const times = time.match(/^([0-1]?\d):([0-5]\d)(AM|PM)$/i);
1432
+ const hours = times?.[1];
1433
+ const minutes = times?.[2];
1434
+ const period = times?.[3];
1435
+ if (hours && minutes && period) {
1436
+ const date = /* @__PURE__ */ new Date();
1437
+ let adjustedHours = 0;
1438
+ if (period.toUpperCase() === "PM" && hours !== "12") adjustedHours = parseInt(hours) + 12;
1439
+ if (period.toUpperCase() === "AM" && hours !== "12") adjustedHours = parseInt(hours);
1440
+ const formattedDate = `${date.toISOString().split("T")[0]}T${String(adjustedHours).padStart(2, "0")}:${minutes}:00`;
1441
+ return /* @__PURE__ */ new Date(`${formattedDate}${timeZone}`);
1442
+ }
1443
+ };
1444
+ const isWithinBusinessHours = (startTime, endTime, timeZone) => {
1445
+ const start = parseTime(startTime, timeZone);
1446
+ let end = parseTime(endTime, timeZone);
1447
+ if (!start || !end) return false;
1448
+ let now = /* @__PURE__ */ new Date();
1449
+ if (end < start) {
1450
+ end = new Date(end.getTime() + 1440 * 60 * 1e3);
1451
+ now = new Date(now.getTime() + 1440 * 60 * 1e3);
1452
+ }
1453
+ if (end.getUTCDate() > start.getUTCDate()) {
1454
+ const crossingMidnight = new Date(now.getTime() + 1440 * 60 * 1e3);
1455
+ return start <= now || crossingMidnight <= end;
1456
+ }
1457
+ return now >= start && now <= end;
1458
+ };
1459
+ let SearchResultsState = /* @__PURE__ */ function(SearchResultsState$1) {
1460
+ SearchResultsState$1[SearchResultsState$1["Loading"] = 0] = "Loading";
1461
+ SearchResultsState$1[SearchResultsState$1["Results"] = 1] = "Results";
1462
+ SearchResultsState$1[SearchResultsState$1["NoResults"] = 2] = "NoResults";
1463
+ return SearchResultsState$1;
1464
+ }({});
1465
+ const getSearchResultsState = (isLoadingSearch, searchData) => {
1466
+ if (isLoadingSearch) return SearchResultsState.Loading;
1467
+ if (searchData) return SearchResultsState.Results;
1468
+ return SearchResultsState.NoResults;
1469
+ };
1470
+
1471
+ //#endregion
1472
+ //#region src/hooks/useSearch.tsx
1473
+ const useSearch = () => {
1474
+ const config = useNewOrgConfig();
1475
+ const orgShortName = useAtomValue(orgShortNameAtom);
1476
+ const { data: searchData, loading: isLoadingSearch } = useAtomValue(searchAtom);
1477
+ const productList = useAtomValue(filteredSearchProductsAtom);
1478
+ const performSearch = useSetAtom(performSearchAtom);
1479
+ const [{ results: autocompleteResults, isLoading: isLoadingAutocomplete }, setAutocompleteState] = useAtom(autocompleteStateAtom);
1480
+ const [{ query }] = useAtom(searchParamsAtom);
1481
+ const [isFilterOpen, setIsFilterOpen] = useAtom(isFilterOpenAtom);
1482
+ const [selectedFilterOptions] = useAtom(searchSelectedFiltersAtom);
1483
+ const addFilter = useSetAtom(addSearchFilterAtom);
1484
+ const removeFilter = useSetAtom(removeSearchFilterAtom);
1485
+ const [productSorting, setProductSorting] = useAtom(searchProductSortingAtom);
1486
+ const clearFilters = useSetAtom(clearSearchFiltersAtom);
1487
+ const searchFilters = useAtomValue(searchFiltersAtom);
1488
+ const [isDirty, setIsDirty] = useState(true);
1489
+ const [focusedIndex, setFocusedIndex] = useState(-1);
1490
+ const [focusedOptionId, setFocusedOptionId] = useState(void 0);
1491
+ const [searchText, setSearchText] = useState(query || "");
1492
+ const searchResultsRef = useRef(null);
1493
+ const debouncedSearchText = useDebounce(searchText, 200);
1494
+ const searchResultsState = getSearchResultsState(isLoadingSearch, searchData);
1495
+ const dynamicFilters = searchData?.filters || [];
1496
+ const safeProductCardConfig = config?.frontendConfig?.uiConfigs?.productCardConfig || {
1497
+ variant: "minimal",
1498
+ hoverVariant: "none",
1499
+ layoutVariant: "square"
1500
+ };
1501
+ const safeMerchantShortName = orgShortName || "";
1502
+ const availableDynamicFilters = useMemo(() => {
1503
+ return dynamicFilters.filter((dynamicFilterName) => !selectedFilterOptions.some((option) => option.id === `dynamic:${dynamicFilterName}`)).map((dynamicFilterName) => ({
1504
+ name: dynamicFilterName,
1505
+ displayName: formatFilterDisplayName(dynamicFilterName)
1506
+ }));
1507
+ }, [dynamicFilters, selectedFilterOptions]);
1508
+ const filters = useMemo(() => {
1509
+ return [{
1510
+ filterId: "sort",
1511
+ displayName: "SORT",
1512
+ items: [
1513
+ {
1514
+ filterItemId: String(ProductSorting.FEATURED),
1515
+ displayName: "Relevance",
1516
+ productCount: 0,
1517
+ isSelected: productSorting === ProductSorting.FEATURED
1518
+ },
1519
+ {
1520
+ filterItemId: String(ProductSorting.PRICE_ASC),
1521
+ displayName: "Price: Low to High",
1522
+ productCount: 0,
1523
+ isSelected: productSorting === ProductSorting.PRICE_ASC
1524
+ },
1525
+ {
1526
+ filterItemId: String(ProductSorting.PRICE_DESC),
1527
+ displayName: "Price: High to Low",
1528
+ productCount: 0,
1529
+ isSelected: productSorting === ProductSorting.PRICE_DESC
1530
+ }
1531
+ ]
1532
+ }, ...searchFilters];
1533
+ }, [productSorting, searchFilters]);
1534
+ const filterButtonText = useMemo(() => {
1535
+ const selectedCount = filters.reduce((acc, filter) => {
1536
+ if (filter.filterId === "sort") return acc;
1537
+ return acc + filter.items.filter((item) => item.isSelected).length;
1538
+ }, 0);
1539
+ if (selectedCount === 0) return "Filter & Sort";
1540
+ return `Filter & Sort (${selectedCount})`;
1541
+ }, [filters]);
1542
+ const { trackEvent } = useAmplitude();
1543
+ const handleToggleDynamicFilter = useCallback(({ filter, dynamicFilterDisplayName }) => {
1544
+ trackEvent({
1545
+ eventName: SpiffyMetricsEventName.SearchFilterClicked,
1546
+ eventProps: {
1547
+ filterType: "Dynamic",
1548
+ filterValue: filter,
1549
+ queryText: searchText
1550
+ }
1551
+ });
1552
+ addFilter(createFilterOption("dynamic", filter, dynamicFilterDisplayName));
1553
+ }, [
1554
+ addFilter,
1555
+ searchText,
1556
+ trackEvent
1557
+ ]);
1558
+ const handleRemoveFilter = useCallback((filter) => {
1559
+ removeFilter(filter.id);
1560
+ }, [removeFilter]);
1561
+ const handleSubmitSearch = useCallback(async () => {
1562
+ if (searchText.trim()) {
1563
+ trackEvent({
1564
+ eventName: SpiffyMetricsEventName.SearchQuerySubmitted,
1565
+ eventProps: {
1566
+ searchOrigin: SpiffyWidgets.SearchResults,
1567
+ queryText: searchText.trim()
1568
+ },
1569
+ alsoSendToGoogleAnalytics: true
1570
+ });
1571
+ const url = new URL(window.location.href);
1572
+ url.searchParams.set("esq", searchText.trim());
1573
+ window.history.pushState({}, "", url);
1574
+ performSearch({ query: searchText.trim() });
1575
+ }
1576
+ }, [
1577
+ performSearch,
1578
+ searchText,
1579
+ trackEvent
1580
+ ]);
1581
+ const handleAutocompleteSelect = useCallback((suggestion) => {
1582
+ setSearchText(suggestion);
1583
+ handleSubmitSearch();
1584
+ }, [handleSubmitSearch, setSearchText]);
1585
+ const handleKeyDown = useCallback((event) => {
1586
+ if (event.key === "ArrowDown") {
1587
+ event.preventDefault();
1588
+ const newIndex = (focusedIndex + 1) % autocompleteResults.length;
1589
+ setFocusedIndex(newIndex);
1590
+ setFocusedOptionId(`option-${newIndex}`);
1591
+ } else if (event.key === "ArrowUp") {
1592
+ event.preventDefault();
1593
+ const newIndex = (focusedIndex - 1 + autocompleteResults.length) % autocompleteResults.length;
1594
+ setFocusedIndex(newIndex);
1595
+ setFocusedOptionId(`option-${newIndex}`);
1596
+ } else if (event.key === "Enter") if (focusedIndex === -1) {
1597
+ event.preventDefault();
1598
+ handleSubmitSearch();
1599
+ } else {
1600
+ event.preventDefault();
1601
+ const suggestionText = autocompleteResults[focusedIndex];
1602
+ handleAutocompleteSelect(suggestionText);
1603
+ }
1604
+ else if (event.key === "Escape") {
1605
+ event.preventDefault();
1606
+ setFocusedIndex(-1);
1607
+ setFocusedOptionId(void 0);
1608
+ }
1609
+ }, [
1610
+ autocompleteResults,
1611
+ focusedIndex,
1612
+ handleAutocompleteSelect,
1613
+ handleSubmitSearch
1614
+ ]);
1615
+ const handleSearchInputChange = (newValue) => {
1616
+ if (newValue.length === 1) trackEvent({
1617
+ eventName: SpiffyMetricsEventName.SearchInputStarted,
1618
+ eventProps: { searchOrigin: SpiffyWidgets.SearchResults }
1619
+ });
1620
+ setSearchText(newValue);
1621
+ setIsDirty(true);
1622
+ };
1623
+ const handleSelectFilterItem = useCallback(({ filterId, filterItemId, isSelected, displayName }) => {
1624
+ if (filterId === "sort") {
1625
+ const newSort = filterItemId;
1626
+ trackEvent({
1627
+ eventName: SpiffyMetricsEventName.SearchSortClicked,
1628
+ eventProps: {
1629
+ sortType: newSort,
1630
+ queryText: searchText
1631
+ }
1632
+ });
1633
+ setProductSorting(newSort);
1634
+ } else if (!isSelected) removeFilter(`${filterId}:${filterItemId}`);
1635
+ else {
1636
+ trackEvent({
1637
+ eventName: SpiffyMetricsEventName.SearchFilterClicked,
1638
+ eventProps: {
1639
+ filterType: "Static",
1640
+ filterCategory: filterId,
1641
+ filterValue: filterItemId,
1642
+ queryText: searchText
1643
+ }
1644
+ });
1645
+ addFilter(createFilterOption(filterId, filterItemId, displayName));
1646
+ }
1647
+ }, [
1648
+ addFilter,
1649
+ removeFilter,
1650
+ setProductSorting,
1651
+ searchText,
1652
+ trackEvent
1653
+ ]);
1654
+ const handleClearAllFilters = useCallback(() => {
1655
+ setProductSorting(ProductSorting.FEATURED);
1656
+ clearFilters();
1657
+ }, [setProductSorting, clearFilters]);
1658
+ useTrackComponentVisibleEvent(SpiffyWidgets.SearchResults, searchResultsRef, {}, SpiffyMetricsEventName.SearchComponentVisible);
1659
+ useEffect(() => {
1660
+ if (productList.length > 0) trackEvent({
1661
+ eventName: SpiffyMetricsEventName.SearchResultsViewed,
1662
+ eventProps: {
1663
+ queryText: searchText,
1664
+ resultsCount: productList.length
1665
+ }
1666
+ });
1667
+ }, [
1668
+ productList.length,
1669
+ searchText,
1670
+ trackEvent
1671
+ ]);
1672
+ useEffect(() => {
1673
+ if (query && query !== searchText) setSearchText(query);
1674
+ }, [query]);
1675
+ useEffect(() => {
1676
+ const esq = new URLSearchParams(window.location.search).get("esq");
1677
+ if (esq) {
1678
+ setSearchText(esq);
1679
+ performSearch({ query: esq });
1680
+ }
1681
+ }, [performSearch]);
1682
+ const fetchAutocompleteSuggestions = (_query) => {
1683
+ return Promise.resolve([]);
1684
+ };
1685
+ useEffect(() => {
1686
+ if (fetchAutocompleteSuggestions === void 0) return;
1687
+ if (!isDirty || debouncedSearchText.length <= 2) {
1688
+ setAutocompleteState({
1689
+ results: [],
1690
+ isLoading: false
1691
+ });
1692
+ return;
1693
+ }
1694
+ setAutocompleteState((prev) => ({
1695
+ ...prev,
1696
+ isLoading: true
1697
+ }));
1698
+ const fetchData = async () => {
1699
+ try {
1700
+ const results = await fetchAutocompleteSuggestions?.(debouncedSearchText);
1701
+ setAutocompleteState({
1702
+ results: results ?? [],
1703
+ isLoading: false
1704
+ });
1705
+ } catch (error) {
1706
+ logger_default.logError("Failed to fetch autocomplete suggestions:", error);
1707
+ setAutocompleteState({
1708
+ results: [],
1709
+ isLoading: false
1710
+ });
1711
+ }
1712
+ };
1713
+ fetchData();
1714
+ }, [
1715
+ debouncedSearchText,
1716
+ isDirty,
1717
+ setAutocompleteState
1718
+ ]);
1719
+ return {
1720
+ searchData,
1721
+ searchResponseId: searchData?.searchResponseId ?? "",
1722
+ merchantShortName: safeMerchantShortName,
1723
+ productCardConfig: safeProductCardConfig,
1724
+ productList,
1725
+ autocompleteResults,
1726
+ searchFilters: filters,
1727
+ availableDynamicFilters,
1728
+ selectedFilterOptions,
1729
+ searchText,
1730
+ searchResultsState,
1731
+ isLoadingAutocomplete,
1732
+ isLoadingSearch,
1733
+ isFilterOpen,
1734
+ isDirty,
1735
+ focusedIndex,
1736
+ focusedOptionId,
1737
+ filterButtonText,
1738
+ onSearchInputChange: handleSearchInputChange,
1739
+ onSubmitSearch: handleSubmitSearch,
1740
+ onAutocompleteSelect: handleAutocompleteSelect,
1741
+ onKeyDown: handleKeyDown,
1742
+ onToggleDynamicFilter: handleToggleDynamicFilter,
1743
+ onSelectFilterItem: handleSelectFilterItem,
1744
+ onRemoveFilter: handleRemoveFilter,
1745
+ onClearAllFilters: handleClearAllFilters,
1746
+ setIsFilterOpen,
1747
+ searchResultsRef
1748
+ };
1749
+ };
1750
+
1751
+ //#endregion
1752
+ //#region src/hooks/useAppDetails.ts
1753
+ const useAppDetails = () => {
1754
+ const { orgId: fetchedOrgId } = useOrgId();
1755
+ const orgId = fetchedOrgId ?? "";
1756
+ const orgShortName = useAtomValue(orgShortNameAtom) ?? "spiffy-ai";
1757
+ const chatId = useAtomValue(chatIdAtom);
1758
+ const userId = useAtomValue(userIdAtom);
1759
+ const source = useAtomValue(contextSourceAtom) ?? ContextSourceEnum.App;
1760
+ const env = useAtomValue(envAtom) ?? ContextEnvEnum.Dev;
1761
+ const variantInfo = useAtomValue(variantInfoAtom);
1762
+ return {
1763
+ orgId,
1764
+ orgShortName,
1765
+ chatId,
1766
+ userId,
1767
+ source,
1768
+ env,
1769
+ variantInfo
1770
+ };
1771
+ };
1772
+
1773
+ //#endregion
1774
+ //#region src/contexts/searchContext.tsx
1775
+ const transformProductResponses = (products) => products.map((data) => ({
1776
+ id: data.id,
1777
+ responseId: data.response_id,
1778
+ category: ResponseCategory.Product,
1779
+ description: data.description,
1780
+ imageUrl: data.image_url,
1781
+ imageUrls: data.image_urls,
1782
+ title: data.title,
1783
+ url: data.url,
1784
+ originalPrice: data.original_price,
1785
+ salePrice: data.sale_price,
1786
+ averageRating: data.average_rating,
1787
+ numberReviews: data.number_reviews,
1788
+ metadata: data.metadata,
1789
+ isForGrid: data.is_for_grid,
1790
+ colors: data.colors,
1791
+ sizes: data.sizes,
1792
+ filters: data.filters
1793
+ }));
1794
+ async function errorResponseBody(error) {
1795
+ try {
1796
+ return await error.response.json();
1797
+ } catch {
1798
+ return {};
1799
+ }
1800
+ }
1801
+ async function throwSessionRestartRequiredIf(errorMsg, error) {
1802
+ if (!(error instanceof ResponseError)) {
1803
+ logger_default.logInfo(errorMsg, error);
1804
+ throw error;
1805
+ }
1806
+ const errorResponse = await errorResponseBody(error);
1807
+ if (errorResponse?.message?.toLowerCase() === "unsupported product" || errorResponse?.app_code?.toUpperCase() === "PRODUCT_NOT_FOUND") throw new UnsupportedProductException();
1808
+ else if (errorResponse?.app_code?.toUpperCase() === "RESTART_SESSION" || errorResponse?.sub_code?.toUpperCase() === "NOT_FOUND") {
1809
+ logger_default.logInfo("Session does not exist. Re-start session", error, error.response, errorResponse);
1810
+ throw new SessionRestartRequired();
1811
+ }
1812
+ logger_default.logInfo(errorMsg, error);
1813
+ throw error;
1814
+ }
1815
+ const SearchContext = createContext(void 0);
1816
+ const SearchProvider = ({ children }) => {
1817
+ const { orgLevelApiKey, publicKey } = useEnviveConfig();
1818
+ const apiKey = orgLevelApiKey || publicKey;
1819
+ const appDetails = useAppDetails();
1820
+ const baseUrl = useAtomValue(baseUrlAtom);
1821
+ const isReady = Boolean(apiKey && appDetails && baseUrl);
1822
+ const searchApi = useMemo(() => {
1823
+ if (!isReady) return null;
1824
+ const config = new Configuration({
1825
+ accessToken: apiKey,
1826
+ basePath: baseUrl,
1827
+ headers: {
1828
+ "Content-Type": "application/json",
1829
+ Accept: "application/json"
1830
+ }
1831
+ });
1832
+ return new SearchApi(config);
1833
+ }, [
1834
+ apiKey,
1835
+ baseUrl,
1836
+ isReady
1837
+ ]);
1838
+ const searchProducts = useCallback(async (params) => {
1839
+ if (!isReady || !searchApi) throw new Error("SearchService not ready - missing dependencies");
1840
+ try {
1841
+ const { products, filters, search_response_id: searchResponseId } = await searchApi.v1SearchQueryGet({
1842
+ query: params.query,
1843
+ limit: params.limit,
1844
+ org_id: appDetails.orgId,
1845
+ user_id: appDetails.userId
1846
+ });
1847
+ return {
1848
+ products: transformProductResponses(products) || [],
1849
+ filters: filters || [],
1850
+ totalProductCount: products?.length || 0,
1851
+ searchResponseId: searchResponseId || ""
1852
+ };
1853
+ } catch (error) {
1854
+ await throwSessionRestartRequiredIf("Failed to search products", error);
1855
+ return {
1856
+ products: [],
1857
+ filters: [],
1858
+ totalProductCount: 0,
1859
+ searchResponseId: ""
1860
+ };
1861
+ }
1862
+ }, [
1863
+ searchApi,
1864
+ isReady,
1865
+ appDetails
1866
+ ]);
1867
+ useEffect(() => {
1868
+ if (isReady) setSearchServiceFunction(searchProducts);
1869
+ else clearSearchServiceFunction();
1870
+ return () => {
1871
+ clearSearchServiceFunction();
1872
+ };
1873
+ }, [searchProducts, isReady]);
1874
+ const value = useMemo(() => ({
1875
+ searchProducts,
1876
+ isReady
1877
+ }), [searchProducts, isReady]);
1878
+ return /* @__PURE__ */ jsx(SearchContext.Provider, {
1879
+ value,
1880
+ children
1881
+ });
1882
+ };
1883
+ const useSearchService = () => {
1884
+ const context = useContext(SearchContext);
1885
+ if (!context) throw new Error("useSearchService must be used within a SearchProvider");
1886
+ return context;
1887
+ };
1888
+
1889
+ //#endregion
1890
+ //#region src/hooks/useSearchOperations.ts
1891
+ const useProductSearch = () => {
1892
+ const { searchProducts, isReady } = useSearchService();
1893
+ const [data, setData] = useState();
1894
+ const [loading, setLoading] = useState(false);
1895
+ const [error, setError] = useState(null);
1896
+ const search = useCallback(async (params) => {
1897
+ if (!isReady) {
1898
+ setError(/* @__PURE__ */ new Error("Search service not ready - missing dependencies"));
1899
+ return;
1900
+ }
1901
+ setLoading(true);
1902
+ setError(null);
1903
+ try {
1904
+ const result = await searchProducts(params);
1905
+ setData(result);
1906
+ } catch (err) {
1907
+ setError(err instanceof Error ? err : /* @__PURE__ */ new Error("Unknown search error"));
1908
+ } finally {
1909
+ setLoading(false);
1910
+ }
1911
+ }, [searchProducts, isReady]);
1912
+ const reset = useCallback(() => {
1913
+ setData(void 0);
1914
+ setError(null);
1915
+ setLoading(false);
1916
+ }, []);
1917
+ return {
1918
+ data,
1919
+ loading,
1920
+ error,
1921
+ search,
1922
+ reset,
1923
+ isReady
1924
+ };
1925
+ };
1926
+ const useSearchWithQuery = (params) => {
1927
+ const { searchProducts, isReady } = useSearchService();
1928
+ const [data, setData] = useState();
1929
+ const [loading, setLoading] = useState(false);
1930
+ const [error, setError] = useState(null);
1931
+ const executeSearch = useCallback(async (searchParams) => {
1932
+ if (!isReady) return;
1933
+ setLoading(true);
1934
+ setError(null);
1935
+ try {
1936
+ const result = await searchProducts(searchParams);
1937
+ setData(result);
1938
+ } catch (err) {
1939
+ setError(err instanceof Error ? err : /* @__PURE__ */ new Error("Unknown search error"));
1940
+ } finally {
1941
+ setLoading(false);
1942
+ }
1943
+ }, [searchProducts, isReady]);
1944
+ useEffect(() => {
1945
+ if (params && isReady) executeSearch(params);
1946
+ }, [
1947
+ params,
1948
+ isReady,
1949
+ executeSearch
1950
+ ]);
1951
+ const refetch = useCallback(() => {
1952
+ if (params) executeSearch(params);
1953
+ }, [params, executeSearch]);
1954
+ return {
1955
+ data,
1956
+ loading,
1957
+ error,
1958
+ refetch,
1959
+ isReady
1960
+ };
1961
+ };
1962
+
1963
+ //#endregion
1964
+ //#region src/contexts/sessionStorageContext.tsx
1965
+ const SessionStorageContext = createContext(null);
1966
+ const SessionStorageProvider = ({ children }) => {
1967
+ const isAvailable = useMemo(() => {
1968
+ try {
1969
+ return typeof window !== "undefined" && !!window.sessionStorage;
1970
+ } catch {
1971
+ return false;
1972
+ }
1973
+ }, []);
1974
+ useEffect(() => {
1975
+ if (!isAvailable) logger_default.logError("sessionStorage is not available", void 0);
1976
+ }, [isAvailable]);
1977
+ const setItem = useCallback((key, value$1) => {
1978
+ if (!isAvailable) return;
1979
+ sessionStorage.setItem(key, value$1);
1980
+ window.dispatchEvent(new StorageEvent("storage", {
1981
+ key,
1982
+ newValue: value$1
1983
+ }));
1984
+ }, [isAvailable]);
1985
+ const getItem = useCallback((key) => {
1986
+ if (!isAvailable) return null;
1987
+ return sessionStorage.getItem(key);
1988
+ }, [isAvailable]);
1989
+ const value = useMemo(() => ({
1990
+ setItem,
1991
+ getItem,
1992
+ isAvailable
1993
+ }), [
1994
+ setItem,
1995
+ getItem,
1996
+ isAvailable
1997
+ ]);
1998
+ return /* @__PURE__ */ jsx(SessionStorageContext.Provider, {
1999
+ value,
2000
+ children
2001
+ });
2002
+ };
2003
+ const useSessionStorage = () => {
2004
+ const context = useContext(SessionStorageContext);
2005
+ if (!context) throw new Error("useSessionStorage must be used within a SessionStorageProvider");
2006
+ return context;
2007
+ };
2008
+
2009
+ //#endregion
2010
+ //#region src/hooks/useSessionStorageOperations.ts
2011
+ const useSessionStorageValue = (key) => {
2012
+ const { getItem, setItem } = useSessionStorage();
2013
+ const [value, setValue] = useState(() => getItem(key));
2014
+ useEffect(() => {
2015
+ const handleStorageChange = (event) => {
2016
+ if (event.key === key) setValue(event.newValue);
2017
+ };
2018
+ window.addEventListener("storage", handleStorageChange);
2019
+ return () => window.removeEventListener("storage", handleStorageChange);
2020
+ }, [key, getItem]);
2021
+ const updateValue = useCallback((newValue) => {
2022
+ setItem(key, newValue);
2023
+ setValue(newValue);
2024
+ }, [key, setItem]);
2025
+ return {
2026
+ value,
2027
+ setValue: updateValue
2028
+ };
2029
+ };
2030
+
2031
+ //#endregion
2032
+ //#region src/contexts/shopifyUrlContext.tsx
2033
+ const ShopifyUrlContext = createContext(void 0);
2034
+ const ShopifyUrlProvider = ({ children }) => {
2035
+ const isReady = true;
2036
+ const getTrimmedPathName = useCallback(() => {
2037
+ let { pathname } = window.location;
2038
+ pathname = pathname.replace("/proxy", "");
2039
+ pathname = pathname.replace(/#.*$/, "");
2040
+ pathname = pathname.replace(/\/$/, "");
2041
+ if (pathname === void 0 || pathname === null || pathname.length === 0) return null;
2042
+ return pathname;
2043
+ }, []);
2044
+ const getPlpOrPdpId = useCallback((extractor) => {
2045
+ if (extractor === "shopify-product-variant-id") {
2046
+ const variantId = parseHref(window.location.href)?.urlSearchParams?.get("variant");
2047
+ if (!variantId) return getPlpOrPdpId("shopify-product-id");
2048
+ return variantId;
2049
+ }
2050
+ const pathSegment = extractor === "shopify-product-id" ? "products" : "collections";
2051
+ const tokens = getTrimmedPathName()?.split("/");
2052
+ const idIndex = tokens?.findIndex((token) => token === pathSegment);
2053
+ if (idIndex !== void 0 && idIndex >= 0 && tokens) return decodeURIComponent(tokens[idIndex + 1]);
2054
+ return null;
2055
+ }, [getTrimmedPathName]);
2056
+ const isOnPdpPage = useCallback(() => {
2057
+ return getTrimmedPathName()?.includes("/products") ?? false;
2058
+ }, [getTrimmedPathName]);
2059
+ const isOnPlpPage = useCallback(() => {
2060
+ return (getTrimmedPathName()?.includes("/collections") && !getTrimmedPathName()?.includes("/products")) ?? false;
2061
+ }, [getTrimmedPathName]);
2062
+ const value = useMemo(() => ({
2063
+ getTrimmedPathName,
2064
+ getPlpOrPdpId,
2065
+ isOnPdpPage,
2066
+ isOnPlpPage,
2067
+ isReady
2068
+ }), [
2069
+ getTrimmedPathName,
2070
+ getPlpOrPdpId,
2071
+ isOnPdpPage,
2072
+ isOnPlpPage,
2073
+ isReady
2074
+ ]);
2075
+ return /* @__PURE__ */ jsx(ShopifyUrlContext.Provider, {
2076
+ value,
2077
+ children
2078
+ });
2079
+ };
2080
+ const useShopifyUrl = () => {
2081
+ const context = useContext(ShopifyUrlContext);
2082
+ if (!context) throw new Error("useShopifyUrl must be used within a ShopifyUrlProvider");
2083
+ return context;
2084
+ };
2085
+
2086
+ //#endregion
2087
+ //#region src/hooks/useShopifyUrlOperations.ts
2088
+ const useShopifyUrlOperations = () => {
2089
+ const { getTrimmedPathName, getPlpOrPdpId, isOnPdpPage, isOnPlpPage, isReady } = useShopifyUrl();
2090
+ return {
2091
+ getTrimmedPathName,
2092
+ getPlpOrPdpId,
2093
+ isOnPdpPage,
2094
+ isOnPlpPage,
2095
+ isReady
2096
+ };
2097
+ };
2098
+ const useCurrentPageType = () => {
2099
+ const { isOnPdpPage, isOnPlpPage, isReady } = useShopifyUrl();
2100
+ return {
2101
+ getPageType: useCallback(() => {
2102
+ if (!isReady) return "unknown";
2103
+ if (isOnPdpPage()) return "pdp";
2104
+ if (isOnPlpPage()) return "plp";
2105
+ return "other";
2106
+ }, [
2107
+ isReady,
2108
+ isOnPdpPage,
2109
+ isOnPlpPage
2110
+ ]),
2111
+ isReady
2112
+ };
2113
+ };
2114
+ const useProductId = (extractor) => {
2115
+ const { getPlpOrPdpId, isReady } = useShopifyUrl();
2116
+ return {
2117
+ productId: useCallback(() => {
2118
+ if (!isReady) return null;
2119
+ return getPlpOrPdpId(extractor);
2120
+ }, [
2121
+ isReady,
2122
+ getPlpOrPdpId,
2123
+ extractor
2124
+ ]),
2125
+ isReady
2126
+ };
2127
+ };
2128
+
2129
+ //#endregion
2130
+ //#region src/hooks/useSnapCalculator.ts
2131
+ const useSnapCalculator = (snaps, maxHeight, unit) => {
2132
+ const viewportHeightPx = document.documentElement.clientHeight;
2133
+ const swipeviewHeightPx = unit === "percent" ? Math.floor(viewportHeightPx * (maxHeight / 100)) : maxHeight;
2134
+ const snapsToPixels = useMemo(() => snaps?.map((snap) => Math.abs((unit === "percent" ? Math.floor(swipeviewHeightPx * (snap / 100)) : snap) - swipeviewHeightPx)), [viewportHeightPx]);
2135
+ const getPixelToSnap = (pixels) => {
2136
+ const snapIdx = snapsToPixels?.indexOf(pixels) || 0;
2137
+ return snaps?.[snapIdx] || 0;
2138
+ };
2139
+ const getSnapToPixel = (snap) => {
2140
+ const snapIdx = snaps?.indexOf(snap) || 0;
2141
+ return snapsToPixels?.[snapIdx] || 0;
2142
+ };
2143
+ return {
2144
+ viewportHeightPx,
2145
+ snapsToPixels,
2146
+ swipeviewHeightPx,
2147
+ getPixelToSnap,
2148
+ getSnapToPixel
2149
+ };
2150
+ };
2151
+
2152
+ //#endregion
2153
+ //#region src/hooks/useSystemSettingsContext.ts
2154
+ const useSystemSettingsContext = () => {
2155
+ const context = useContext(SystemSettingsContext);
2156
+ if (!context) throw new Error("useSystemSettingsContext must be used within a SystemSettingsContextProvider");
2157
+ return { ...context };
2158
+ };
2159
+
2160
+ //#endregion
2161
+ //#region src/hooks/useTrackComponentVisibleEvent.ts
2162
+ /**
2163
+ * Tracks a component and logs an event to Amplitude when the component is visible.
2164
+ *
2165
+ * @param component - The component to track.
2166
+ * @param element - The element to track visibility of.
2167
+ * @param eventProps - Additional properties to include with the event.
2168
+ * @param eventName - The Amplitude event name to track (defaults to ChatComponentVisible).
2169
+ */
2170
+ const useTrackComponentVisibleEvent = (component, element, eventProps, eventName = SpiffyMetricsEventName.ChatComponentVisible) => {
2171
+ const isVisible = useIntersection(element, "0px");
2172
+ const hasTrackedEvent = useRef(false);
2173
+ const { trackEvent } = useAmplitude();
2174
+ const componentProps = (() => {
2175
+ if (eventName === SpiffyMetricsEventName.ChatComponentVisible) return {
2176
+ chat_component: component,
2177
+ ...eventProps
2178
+ };
2179
+ if (eventName === SpiffyMetricsEventName.SearchComponentVisible) return {
2180
+ search_component: component,
2181
+ ...eventProps
2182
+ };
2183
+ return {
2184
+ component,
2185
+ ...eventProps
2186
+ };
2187
+ })();
2188
+ useEffect(() => {
2189
+ if (isVisible && !hasTrackedEvent.current) {
2190
+ trackEvent({
2191
+ eventName,
2192
+ eventProps: componentProps
2193
+ });
2194
+ hasTrackedEvent.current = true;
2195
+ }
2196
+ }, [
2197
+ isVisible,
2198
+ component,
2199
+ eventProps,
2200
+ eventName,
2201
+ componentProps,
2202
+ trackEvent
2203
+ ]);
2204
+ };
2205
+
2206
+ //#endregion
2207
+ //#region src/hooks/useUpdateAnalyticsProps.ts
2208
+ /**
2209
+ * Updates the default analytics properties whenever the variant info changes. This hook also
2210
+ * triggers any events that should be sent once per page visit.
2211
+ */
2212
+ const useUpdateAnalyticsProps = () => {
2213
+ const variantInfo = useAtomValue(variantInfoAtom);
2214
+ const hasInitialized = useRef(false);
2215
+ const hasParsedVariantInfo = useAtomValue(hasParsedVariantInfoAtom);
2216
+ const { trackEvent, setSupplementalDefaultProps } = useAmplitude();
2217
+ useEffect(() => {
2218
+ const variantInfoWithPrefix = Object.fromEntries(Object.entries(variantInfo).map(([key, value]) => [`variantInfo.${key}`, value]));
2219
+ const defaultEventProperties = {
2220
+ page_variant: variantInfo.variant,
2221
+ ...variantInfoWithPrefix
2222
+ };
2223
+ if (variantInfo.variant === "pdp") defaultEventProperties.product_id = variantInfo.productId;
2224
+ if (variantInfo.variant === "plp") defaultEventProperties.plp_id = variantInfo.plpId;
2225
+ if (variantInfo.variant === "page_visit") {
2226
+ defaultEventProperties.page_visit_category = variantInfo.pageVisitCategory;
2227
+ defaultEventProperties.page_visit_url = variantInfo.url;
2228
+ }
2229
+ setSupplementalDefaultProps(defaultEventProperties);
2230
+ if (!hasInitialized.current && hasParsedVariantInfo) {
2231
+ trackEvent({ eventName: SpiffyMetricsEventName.BundleLoaded });
2232
+ hasInitialized.current = true;
2233
+ }
2234
+ }, [
2235
+ variantInfo,
2236
+ hasParsedVariantInfo,
2237
+ trackEvent,
2238
+ setSupplementalDefaultProps
2239
+ ]);
2240
+ };
2241
+
2242
+ //#endregion
2243
+ //#region src/contexts/chatContext.tsx
2244
+ /**
2245
+ * Record the chat assistant response in Amplitude
2246
+ *
2247
+ * @param startTimeMs The start time of the assistant response
2248
+ * @param payload The payload used to generate the response
2249
+ */
2250
+ const recordAssistantResponse = (startTimeMs, payload, track) => {
2251
+ const atomStore = getAtomStore();
2252
+ const chatState = atomStore.get(chatAtom);
2253
+ const chatSearchState = atomStore.get(chatSearchStateAtom);
2254
+ const searchProducts = atomStore.get(chatSearchProducts);
2255
+ const searchProductsSort = atomStore.get(chatSearchProductSortingAtom);
2256
+ const assistantResponseTimeMs = {
2257
+ start: startTimeMs,
2258
+ end: Date.now()
2259
+ };
2260
+ let userQueryProperty;
2261
+ if (chatState.replyEventCategory === UserEventCategory.SuggestionClicked && chatState.suggestion) userQueryProperty = chatState.suggestion.content;
2262
+ else if (chatState.userQuery && chatState.userQuery.length > 0) userQueryProperty = chatState.userQuery;
2263
+ const eventProps = {
2264
+ response_time_ms: assistantResponseTimeMs.end - assistantResponseTimeMs.start,
2265
+ user_event_type: chatState.replyEventCategory,
2266
+ user_query: userQueryProperty
2267
+ };
2268
+ if (chatState.replyEventCategory === UserEventCategory.FormSubmitted) {
2269
+ const lastAssistantTurn = chatState.messages.filter((turn) => turn.length > 0 && turn[0].role === MessageRole.Assistant).pop();
2270
+ const formType = payload.userEvents?.find((event) => event.category === UserEventCategory.FormSubmitted)?.attributes.formType;
2271
+ const formStatus = lastAssistantTurn?.some((response) => response.type === MessageType.Order);
2272
+ eventProps.form_submitted_attributes = {
2273
+ form_type: formType,
2274
+ status: formStatus ? "success" : "failed"
2275
+ };
2276
+ }
2277
+ if (chatSearchState === "product-page") {
2278
+ eventProps.search_products_returned = searchProducts.length;
2279
+ eventProps.search_products_sort_type = searchProductsSort;
2280
+ }
2281
+ track(SpiffyMetricsEventName.ChatAssistantResponse, { eventProps });
2282
+ };
2283
+ const ChatContext = createContext(void 0);
2284
+ const updateMessageState = (message, lastMessage, setMessages) => {
2285
+ if (lastMessage == null) {
2286
+ setMessages((prev) => [...prev, [message]]);
2287
+ return message;
2288
+ }
2289
+ if (lastMessage.type === MessageType.Text && message.type === MessageType.Text) {
2290
+ const newMessage = {
2291
+ ...lastMessage,
2292
+ metadata: {
2293
+ ...lastMessage.metadata,
2294
+ content: lastMessage.metadata.content + message.metadata.content
2295
+ }
2296
+ };
2297
+ setMessages((prev) => {
2298
+ const lastTurn = prev[prev.length - 1];
2299
+ return [...prev.slice(0, prev.length - 1), [...lastTurn.slice(0, lastTurn.length - 1), newMessage]];
2300
+ });
2301
+ return newMessage;
2302
+ }
2303
+ setMessages((prev) => [...prev.slice(0, prev.length - 1), [...prev[prev.length - 1], message]]);
2304
+ return message;
2305
+ };
2306
+ const handleStreamingError = (_error, setRequestFailure, setMessages) => {
2307
+ setRequestFailure(true);
2308
+ setMessages((prev) => [...prev, [{
2309
+ id: v4(),
2310
+ role: MessageRole.Assistant,
2311
+ type: MessageType.Text,
2312
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
2313
+ metadata: { content: "I'm sorry! I'm having trouble right now. Please refresh the page or try again in a moment." }
2314
+ }]]);
2315
+ };
2316
+ const processStreamingResponse = async (stream, messageInterceptor, handleSearchResults, setMessages, setSearchIsLoading, chatId) => {
2317
+ let lastMessage;
2318
+ let hasSearchResults = false;
2319
+ for await (const response of stream) try {
2320
+ if (messageInterceptor.intercept(response)) return { hasSearchResults };
2321
+ const message = messageFromResponse(response);
2322
+ if (!message) throw new Error("Failed to transform API response to client message");
2323
+ if (message.type === MessageType.ProductSearch) {
2324
+ handleSearchResults(message);
2325
+ hasSearchResults = true;
2326
+ setSearchIsLoading(false);
2327
+ }
2328
+ lastMessage = updateMessageState(message, lastMessage, setMessages);
2329
+ } catch (error) {
2330
+ logger_default.logWarn(`[spiffy-ai] Failed to generate responses from stream chat_id=${chatId}`, error, {
2331
+ lastResponse: lastMessage,
2332
+ response
2333
+ });
2334
+ }
2335
+ return { hasSearchResults };
2336
+ };
2337
+ const ChatContextProvider = ({ children }) => {
2338
+ const logPerfMetric = useSetAtom(logPerfMetricAtom);
2339
+ const [widgetInitialized, setWidgetInitialized] = useState(false);
2340
+ const setUserHasReplied = useSetAtom(userHasRepliedAtom);
2341
+ const [messages, setMessages] = useAtom(messagesAtom);
2342
+ const setUserEvents = useSetAtom(userEventsAtom);
2343
+ const setSuggestions = useSetAtom(suggestionsAtom);
2344
+ const [suggestionsLoading, setSuggestionsLoading] = useAtom(suggestionsLoadingAtom);
2345
+ const [responseStreaming, setResponseStreaming] = useAtom(responseStreamingAtom);
2346
+ const setRequestFailure = useSetAtom(requestFailureAtom);
2347
+ const userEvents = useAtomValue(userEventQueueAtom);
2348
+ const userQueueEventCount = useAtomValue(userQueueEventCountAtom);
2349
+ const markUserEventsProcessed = useSetAtom(processUserEventAtom);
2350
+ const clearUserEventQueue = useSetAtom(clearUserEventAtom);
2351
+ const userId = useAtomValue(userIdAtom);
2352
+ const chatId = useAtomValue(chatIdAtom);
2353
+ const supportedEvent = useAtomValue(supportedEventAtom);
2354
+ const orgId = "mock-org-id";
2355
+ const variantInfo = useAtomValue(variantInfoAtom);
2356
+ const settingsContext = useSystemSettingsContext();
2357
+ const messageInterceptor = useMessageInterceptor();
2358
+ const handleSearchResults = useSetAtom(handleSearchResultsAtom);
2359
+ const setSearchIsLoading = useSetAtom(chatSearchIsLoadingAtom);
2360
+ const { track } = useAmplitudeTracking();
2361
+ const getStreamingResponses = useCallback(async (payload) => {
2362
+ logPerfMetric(PerfMetricsEvents.FirstResponseStarted);
2363
+ const stream = commerce_api_default.getNextResponseStreaming(payload);
2364
+ try {
2365
+ setRequestFailure(false);
2366
+ const { hasSearchResults } = await processStreamingResponse(stream, messageInterceptor, handleSearchResults, setMessages, setSearchIsLoading, chatId);
2367
+ return { hasSearchResults };
2368
+ } catch (e) {
2369
+ handleStreamingError(e, setRequestFailure, setMessages);
2370
+ throw e;
2371
+ } finally {
2372
+ logPerfMetric(PerfMetricsEvents.FirstResponseCompleted);
2373
+ }
2374
+ }, [
2375
+ logPerfMetric,
2376
+ setRequestFailure,
2377
+ messageInterceptor,
2378
+ handleSearchResults,
2379
+ setMessages,
2380
+ setSearchIsLoading,
2381
+ chatId
2382
+ ]);
2383
+ const getSuggestions = useCallback(async () => {
2384
+ logPerfMetric(PerfMetricsEvents.FirstSuggestionsStarted);
2385
+ setSuggestionsLoading(true);
2386
+ setSuggestions([]);
2387
+ const payloadWithoutAppLoaded = createResponsePayload({
2388
+ userEvents: [],
2389
+ generationParams: settingsContext.generationParams
2390
+ });
2391
+ const response = await commerce_api_default.getNextSuggestions(payloadWithoutAppLoaded);
2392
+ setSuggestions(response.sort((a, b) => a.content.length - b.content.length));
2393
+ setSuggestionsLoading(false);
2394
+ logPerfMetric(PerfMetricsEvents.FirstSuggestionsCompleted);
2395
+ }, [
2396
+ logPerfMetric,
2397
+ setSuggestionsLoading,
2398
+ setSuggestions,
2399
+ settingsContext.generationParams
2400
+ ]);
2401
+ const getResponses = useCallback(async (payload) => {
2402
+ try {
2403
+ const requestPayload = payload ?? createResponsePayload({
2404
+ userEvents,
2405
+ generationParams: settingsContext.generationParams
2406
+ });
2407
+ setResponseStreaming(true);
2408
+ setSuggestions([]);
2409
+ const startTimeMs = Date.now();
2410
+ await getStreamingResponses(requestPayload);
2411
+ recordAssistantResponse(startTimeMs, requestPayload, track);
2412
+ await getSuggestions();
2413
+ } catch (error) {
2414
+ logger_default.logError("[spiffy-ai] getResponses error", error);
2415
+ } finally {
2416
+ markUserEventsProcessed(userEvents.map(({ eventId }) => eventId));
2417
+ setUserHasReplied(false);
2418
+ setResponseStreaming(false);
2419
+ }
2420
+ }, [
2421
+ userEvents,
2422
+ settingsContext.generationParams,
2423
+ setResponseStreaming,
2424
+ setSuggestions,
2425
+ getStreamingResponses,
2426
+ markUserEventsProcessed,
2427
+ getSuggestions,
2428
+ setUserHasReplied,
2429
+ track
2430
+ ]);
2431
+ useEffect(() => {
2432
+ const processUserEvents = async () => {
2433
+ if (responseStreaming || !widgetInitialized) return;
2434
+ if (variantInfo.variant === "pdp" && !variantInfo.productId || variantInfo.variant === "plp" && !variantInfo.plpId || variantInfo.variant === "page_visit" && !variantInfo.url) {
2435
+ logger_default.logDebug("[spiffy-ai] variantInfo has invalid values, skipping...", {
2436
+ variantInfo,
2437
+ supportedEvent
2438
+ });
2439
+ return;
2440
+ }
2441
+ logger_default.logDebug(`Assistants Turn is_currently_streaming=${responseStreaming} initialized=${widgetInitialized}`);
2442
+ try {
2443
+ await getResponses();
2444
+ logger_default.logInfo(`Assistants Turn [finished]`);
2445
+ } catch (error) {
2446
+ logger_default.logError("[spiffy-ai] Assistants Turn error", error);
2447
+ }
2448
+ };
2449
+ if (userQueueEventCount > 0) processUserEvents();
2450
+ }, [
2451
+ getResponses,
2452
+ responseStreaming,
2453
+ userQueueEventCount,
2454
+ widgetInitialized,
2455
+ variantInfo,
2456
+ supportedEvent
2457
+ ]);
2458
+ useEffect(() => {
2459
+ if (widgetInitialized || responseStreaming) {
2460
+ logger_default.logDebug(`[spiffy-ai] initializeWidget [skipped] is_currently_streaming=${responseStreaming} is_initialized=${widgetInitialized}`);
2461
+ return;
2462
+ }
2463
+ const hydrateChat = async () => {
2464
+ try {
2465
+ logger_default.logDebug(`[spiffy-ai] initializeWidget is_currently_streaming=${responseStreaming} is_initialized=${widgetInitialized}`);
2466
+ const { messages: existingMessages, userEvents: userEvents$1 } = await commerce_api_default.getResponses(orgId, chatId, userId);
2467
+ setMessages([...existingMessages]);
2468
+ setUserEvents([...userEvents$1]);
2469
+ getResponses();
2470
+ } catch (error) {
2471
+ logger_default.logInfo(`Init chat [exception] chat_id=${chatId} error=${error}`, error);
2472
+ if (error instanceof SessionRestartRequired) {
2473
+ const appLoadedEvent = createAppLoadedEvent();
2474
+ const visitEvent = createVisitUserEvent({ variantInfo });
2475
+ setMessages([]);
2476
+ clearUserEventQueue();
2477
+ if (visitEvent) {
2478
+ const payload = createResponsePayload({
2479
+ userEvents: [appLoadedEvent, visitEvent],
2480
+ generationParams: settingsContext.generationParams
2481
+ });
2482
+ getResponses(payload);
2483
+ }
2484
+ }
2485
+ } finally {
2486
+ setWidgetInitialized(true);
2487
+ }
2488
+ };
2489
+ hydrateChat();
2490
+ }, []);
2491
+ const onFocus = useCallback(async () => {
2492
+ try {
2493
+ if (!responseStreaming && !suggestionsLoading && orgId) {
2494
+ const { messages: existingMessages } = await commerce_api_default.getResponses(orgId, chatId, userId);
2495
+ if (existingMessages.length > messages.length) setMessages([...existingMessages]);
2496
+ }
2497
+ } catch (error) {
2498
+ logger_default.logError("[spiffy-ai] onFocus error", error);
2499
+ }
2500
+ }, [
2501
+ responseStreaming,
2502
+ suggestionsLoading,
2503
+ orgId,
2504
+ chatId,
2505
+ userId,
2506
+ messages.length,
2507
+ setMessages
2508
+ ]);
2509
+ useEffect(() => {
2510
+ window.addEventListener("focus", onFocus);
2511
+ return () => {
2512
+ window.removeEventListener("focus", onFocus);
2513
+ };
2514
+ }, [onFocus]);
2515
+ const chatContext = useMemo(() => ({}), []);
2516
+ return /* @__PURE__ */ jsx(ChatContext.Provider, {
2517
+ value: chatContext,
2518
+ children
2519
+ });
2520
+ };
2521
+
2522
+ //#endregion
2523
+ //#region src/contexts/enviveCssContext.tsx
2524
+ const EnviveCssProvider = ({ children }) => {
2525
+ const { colorsConfig, frontendConfig, loading } = useNewOrgConfig();
2526
+ let merchantThemeCss = `* {}`;
2527
+ if (colorsConfig && !loading) merchantThemeCss = `
2528
+ * {
2529
+ --spiffy-colors-text-primary: ${colorsConfig.textPrimary};
2530
+ --spiffy-colors-text-secondary: ${colorsConfig.textSecondary};
2531
+ --spiffy-colors-text-accent: ${colorsConfig.textAccent};
2532
+ --spiffy-colors-text-link: ${colorsConfig.textLink};
2533
+ --spiffy-colors-text-light: ${colorsConfig.textLight};
2534
+ --spiffy-colors-background-primary: ${colorsConfig.backgroundPrimary};
2535
+ --spiffy-colors-background-secondary: ${colorsConfig.backgroundSecondary};
2536
+ --spiffy-colors-background-secondary-dark: ${colorsConfig.backgroundSecondaryDark};
2537
+ --spiffy-colors-background-tertiary: ${colorsConfig.backgroundTertiary};
2538
+ --spiffy-colors-background-dark: ${colorsConfig.backgroundDark};
2539
+ --spiffy-colors-background-light: ${colorsConfig.backgroundLight};
2540
+ --spiffy-colors-background-saturated: ${colorsConfig.backgroundSaturated};
2541
+ --spiffy-colors-border-light: ${colorsConfig.borderLight};
2542
+ --spiffy-colors-border-medium: ${colorsConfig.borderMedium};
2543
+ --spiffy-colors-border-dark: ${colorsConfig.borderDark};
2544
+ --spiffy-colors-border-outline: ${colorsConfig.borderOutline};
2545
+ --spiffy-colors-accent-primary: ${colorsConfig.accentPrimary};
2546
+ --spiffy-colors-accent-secondary: ${colorsConfig.accentSecondary};
2547
+ }`;
2548
+ console.log(frontendConfig);
2549
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
2550
+ frontendConfig ? /* @__PURE__ */ jsx("style", {
2551
+ id: "merchant-css-overrides",
2552
+ children: `${frontendConfig.merchantOverrideCss}`
2553
+ }) : null,
2554
+ colorsConfig ? /* @__PURE__ */ jsx("style", {
2555
+ id: "merchant-css-colors",
2556
+ children: `${merchantThemeCss}`
2557
+ }) : null,
2558
+ children
2559
+ ] });
2560
+ };
2561
+
2562
+ //#endregion
2563
+ //#region src/contexts/systemSettingsContext.tsx
2564
+ const getChatModelName = () => {
2565
+ const urlObj = new URL(window.location.href);
2566
+ const params = new URLSearchParams(urlObj.search);
2567
+ return Object.fromEntries(params.entries()).llm_model_name;
2568
+ };
2569
+ const defaultGenerationParams = {
2570
+ stream: true,
2571
+ numSuggestions: 3,
2572
+ model: getChatModelName()
2573
+ };
2574
+ const SystemSettingsContext = createContext(void 0);
2575
+ const SystemSettingsContextProvider = ({ children, generationParams, showDebugBar }) => {
2576
+ const [params, setParams] = useState(() => generationParams ?? defaultGenerationParams);
2577
+ const endpointURL = useAtomValue(baseUrlAtom);
2578
+ const settingsContextValues = useMemo(() => ({
2579
+ generationParams: params,
2580
+ showDebugBar,
2581
+ setGenerationParams: setParams,
2582
+ endpointURL
2583
+ }), [
2584
+ generationParams,
2585
+ endpointURL,
2586
+ showDebugBar
2587
+ ]);
2588
+ return /* @__PURE__ */ jsx(SystemSettingsContext.Provider, {
2589
+ value: settingsContextValues,
2590
+ children
2591
+ });
2592
+ };
2593
+
2594
+ //#endregion
2595
+ export { CdnProvider, ChatContext, ChatContextProvider, EnviveCssProvider, FeatureFlagServiceProvider, GraphQLProvider, NewOrgConfigProvider, SearchProvider, SearchResultsState, SessionStorageProvider, ShopifyUrlProvider, SystemSettingsContext, SystemSettingsContextProvider, UserIdentityProvider, createAppLoadedEvent, createVisitUserEvent, defaultGenerationParams, getSearchResultsState, isElementPartiallyVisible, isWithinBusinessHours, useAmplitudeTracking, useAssetUrl, useBlockBackButton, useCdn, useCdnBasePath, useCdnUrl, useChatToggle, useChatToggleAnalytics, useColorsAndFrontendConfig, useCurrentPageType, useCustomerSupportHandoff, useDebounce, useElementObserver, useEnviveFeatureFlag, useFeatureFlagService, useGrabAndScroll, useGraphQLClient, useIdentifyUser, useImageResolver, useIntersection, useIsSmallScreen, useLocalStorageListener, useLocalStorageValue, useMessageFilter, useMessageScrollObserver, useNewOrgConfig, useNewOrgConfigContext, useOrgId, useProductId, useProductSearch, useSearch, useSearchService, useSearchWithQuery, useSessionStorage, useSessionStorageValue, useShopifyUrl, useShopifyUrlOperations, useSnapCalculator, useSpiffyFeatureFlag, useSystemSettingsContext, useTrackComponentVisibleEvent, useUpdateAnalyticsProps, useUserIdentity };
2596
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29udGV4dHMtREdscjdNMW8uanMiLCJuYW1lcyI6WyJDZG5Qcm92aWRlcjogUmVhY3QuRkM8eyBjaGlsZHJlbjogUmVhY3QuUmVhY3ROb2RlIH0+IiwiZXJyb3JSZXNwb25zZUJvZHkiLCJ0aHJvd1Nlc3Npb25SZXN0YXJ0UmVxdWlyZWRJZiIsImNvbmZpZzogQ29uZmlndXJhdGlvbiIsImNvbnRleHQ6IENvbnRleHQiLCJlcnI6IHVua25vd24iLCJlcnJvcjogdW5rbm93biIsImRhdGE6IFYxR2V0U2Vzc2lvbk1lc3NhZ2VzMjAwUmVzcG9uc2UiLCJyZXNwb25zZXM6IFJlc3BvbnNlW11bXSIsInN1Z2dlc3Rpb25zOiBTdWdnZXN0aW9uW10iLCJ1c2VyRXZlbnRzOiBVc2VyRXZlbnRbXSIsImFzc2lzdGFudE1lc3NhZ2VzOiBNZXNzYWdlW11bXSIsInVzZXJNZXNzYWdlczogTWVzc2FnZVtdW10iLCJyZXF1ZXN0OiBWMU9yZ0NvbmZpZ0dldFJlcXVlc3QiLCJVc2VySWRlbnRpdHlQcm92aWRlcjogUmVhY3QuRkM8eyBjaGlsZHJlbjogUmVhY3QuUmVhY3ROb2RlIH0+IiwidXVpZCIsIkNvbW1lcmNlQXBpQ2xpZW50IiwibGlzdGVuZXI6IExvY2FsU3RvcmFnZUV2ZW50TGlzdGVuZXIiLCJGZWF0dXJlRmxhZ1NlcnZpY2VQcm92aWRlcjogUmVhY3QuRkM8XG4gIEZlYXR1cmVGbGFnU2VydmljZVByb3ZpZGVyUHJvcHNcbj4iLCJOZXdPcmdDb25maWdQcm92aWRlcjogUmVhY3QuRkM8TmV3T3JnQ29uZmlnUHJvdmlkZXJQcm9wcz4iLCJ1dWlkIiwiaGFuZGxlU2VsZWN0RmlsdGVySXRlbTogU2VsZWN0RmlsdGVySXRlbSIsImVudml2ZU9yZ1Nob3J0TmFtZUF0b20iLCJlbnZpdmVFbnZBdG9tIiwiU2VhcmNoUHJvdmlkZXI6IFJlYWN0LkZDPHsgY2hpbGRyZW46IFJlYWN0LlJlYWN0Tm9kZSB9PiIsImNvbmZpZzogQ29uZmlndXJhdGlvbiIsIlNlc3Npb25TdG9yYWdlUHJvdmlkZXI6IFJlYWN0LkZDPHtcbiAgY2hpbGRyZW46IFJlYWN0LlJlYWN0Tm9kZTtcbn0+IiwidmFsdWUiLCJTaG9waWZ5VXJsUHJvdmlkZXI6IFJlYWN0LkZDPHsgY2hpbGRyZW46IFJlYWN0LlJlYWN0Tm9kZSB9PiIsImRlZmF1bHRFdmVudFByb3BlcnRpZXM6IFJlY29yZDxzdHJpbmcsIHVua25vd24+IiwidXNlclF1ZXJ5UHJvcGVydHk6IHN0cmluZyB8IHVuZGVmaW5lZCIsImV2ZW50UHJvcHM6IFJlY29yZDxzdHJpbmcsIHVua25vd24+IiwidXVpZCIsImxhc3RNZXNzYWdlOiBNZXNzYWdlIHwgdW5kZWZpbmVkIiwiZXJyb3I6IHVua25vd24iLCJDb21tZXJjZUFwaUNsaWVudCIsInVzZXJFdmVudHMiLCJFbnZpdmVDc3NQcm92aWRlcjogUmVhY3QuRkM8RW52aXZlQ3NzUHJvdmlkZXJQcm9wcz4iLCJkZWZhdWx0R2VuZXJhdGlvblBhcmFtczogR2VuZXJhdGlvblBhcmFtcyJdLCJzb3VyY2VzIjpbIi4uL3NyYy9jb250ZXh0cy9jZG5Db250ZXh0LnRzeCIsIi4uL3NyYy90eXBlcy9leGNlcHRpb25zL3Nlc3Npb25FeGNlcHRpb25zLnRzIiwiLi4vc3JjL3R5cGVzL2V4Y2VwdGlvbnMvdW5zdXBwb3J0ZWRQcm9kdWN0RXhjZXB0aW9ucy50cyIsIi4uL3NyYy9hcHBsaWNhdGlvbi9jb21tZXJjZS1hcGkudHMiLCIuLi9zcmMvaG9va3MvdXNlQW1wbGl0dWRlT3BlcmF0aW9ucy50cyIsIi4uL3NyYy9ob29rcy91c2VCbG9ja0JhY2tCdXR0b24udHMiLCIuLi9zcmMvaG9va3MvdXNlQ2RuT3BlcmF0aW9ucy50cyIsIi4uL3NyYy9ob29rcy91c2VDaGF0VG9nZ2xlLnRzIiwiLi4vc3JjL2hvb2tzL3VzZUNoYXRUb2dnbGVBbmFseXRpY3MudHMiLCIuLi9zcmMvaG9va3MvdXNlQ3VzdG9tZXJTdXBwb3J0SGFuZG9mZi50cyIsIi4uL3NyYy9ob29rcy91c2VEZWJvdW5jZS50cyIsIi4uL3NyYy9ob29rcy91c2VFbGVtZW50T2JzZXJ2ZXIudHMiLCIuLi9zcmMvaG9va3MvdXNlR3JhYkFuZFNjcm9sbC50cyIsIi4uL3NyYy9jb250ZXh0cy9ncmFwaHFsQ29udGV4dC50c3giLCIuLi9zcmMvaG9va3MvdXNlR3JhcGhRTENvbmZpZy50cyIsIi4uL3NyYy9jb250ZXh0cy91c2VySWRlbnRpdHlDb250ZXh0LnRzeCIsIi4uL3NyYy9ob29rcy91c2VJZGVudGlmeVVzZXIudHMiLCIuLi9zcmMvaG9va3MvdXNlSW1hZ2VSZXNvbHZlci50cyIsIi4uL3NyYy9ob29rcy91c2VJbnRlcnNlY3Rpb24udHMiLCIuLi9zcmMvaG9va3MvdXNlSXNTbWFsbFNjcmVlbi50cyIsIi4uL3NyYy9ob29rcy91c2VMb2NhbFN0b3JhZ2VPcGVyYXRpb25zLnRzIiwiLi4vc3JjL2hvb2tzL3VzZU1lc3NhZ2VGaWx0ZXIudHMiLCIuLi9zcmMvaG9va3MvdXNlTWVzc2FnZVNjcm9sbE9ic2VydmVyLnRzIiwiLi4vc3JjL2NvbnRleHRzL2ZlYXR1cmVGbGFnU2VydmljZUNvbnRleHQudHN4IiwiLi4vc3JjL2NvbnRleHRzL25ld09yZ0NvbmZpZ0NvbnRleHQudHN4IiwiLi4vc3JjL2hvb2tzL3VzZU5ld09yZ0NvbmZpZy50cyIsIi4uL3NyYy9ob29rcy91dGlscy50cyIsIi4uL3NyYy9ob29rcy91c2VTZWFyY2gudHN4IiwiLi4vc3JjL2hvb2tzL3VzZUFwcERldGFpbHMudHMiLCIuLi9zcmMvY29udGV4dHMvc2VhcmNoQ29udGV4dC50c3giLCIuLi9zcmMvaG9va3MvdXNlU2VhcmNoT3BlcmF0aW9ucy50cyIsIi4uL3NyYy9jb250ZXh0cy9zZXNzaW9uU3RvcmFnZUNvbnRleHQudHN4IiwiLi4vc3JjL2hvb2tzL3VzZVNlc3Npb25TdG9yYWdlT3BlcmF0aW9ucy50cyIsIi4uL3NyYy9jb250ZXh0cy9zaG9waWZ5VXJsQ29udGV4dC50c3giLCIuLi9zcmMvaG9va3MvdXNlU2hvcGlmeVVybE9wZXJhdGlvbnMudHMiLCIuLi9zcmMvaG9va3MvdXNlU25hcENhbGN1bGF0b3IudHMiLCIuLi9zcmMvaG9va3MvdXNlU3lzdGVtU2V0dGluZ3NDb250ZXh0LnRzIiwiLi4vc3JjL2hvb2tzL3VzZVRyYWNrQ29tcG9uZW50VmlzaWJsZUV2ZW50LnRzIiwiLi4vc3JjL2hvb2tzL3VzZVVwZGF0ZUFuYWx5dGljc1Byb3BzLnRzIiwiLi4vc3JjL2NvbnRleHRzL2NoYXRDb250ZXh0LnRzeCIsIi4uL3NyYy9jb250ZXh0cy9lbnZpdmVDc3NDb250ZXh0LnRzeCIsIi4uL3NyYy9jb250ZXh0cy9zeXN0ZW1TZXR0aW5nc0NvbnRleHQudHN4Il0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBSZWFjdCwgeyBjcmVhdGVDb250ZXh0LCB1c2VDb250ZXh0LCB1c2VDYWxsYmFjaywgdXNlTWVtbyB9IGZyb20gXCJyZWFjdFwiO1xuaW1wb3J0IHsgdXNlQXRvbVZhbHVlIH0gZnJvbSBcImpvdGFpXCI7XG5pbXBvcnQgeyBjZG5VcmxBdG9tIH0gZnJvbSBcIi4uL2F0b21zL2Vudml2ZS9lbnZpdmVDb25maWdcIjtcblxuaW50ZXJmYWNlIENkbkNvbnRleHRUeXBlIHtcbiAgY2RuVXJsOiBzdHJpbmc7XG4gIGdldENkbkJhc2VQYXRoOiAoKSA9PiBzdHJpbmc7XG4gIGdldEFzc2V0VVJMOiAoYXNzZXROYW1lOiBzdHJpbmcsIG9yZ1Nob3J0TmFtZTogc3RyaW5nKSA9PiBzdHJpbmc7XG59XG5cbmNvbnN0IENkbkNvbnRleHQgPSBjcmVhdGVDb250ZXh0PENkbkNvbnRleHRUeXBlIHwgbnVsbD4obnVsbCk7XG5cbmV4cG9ydCBjb25zdCBDZG5Qcm92aWRlcjogUmVhY3QuRkM8eyBjaGlsZHJlbjogUmVhY3QuUmVhY3ROb2RlIH0+ID0gKHtcbiAgY2hpbGRyZW4sXG59KSA9PiB7XG4gIGNvbnN0IGNkblVybEF0b21WYWx1ZSA9IHVzZUF0b21WYWx1ZShjZG5VcmxBdG9tKTtcbiAgY29uc3QgY2RuVXJsID0gY2RuVXJsQXRvbVZhbHVlIHx8IFwiaHR0cHM6Ly9jZG4uc3BpZmZ5LmFpL290aGVyXCI7XG5cbiAgY29uc3QgZ2V0Q2RuQmFzZVBhdGggPSB1c2VDYWxsYmFjaygoKSA9PiB7XG4gICAgcmV0dXJuIGNkblVybDtcbiAgfSwgW2NkblVybF0pO1xuXG4gIGNvbnN0IGdldEFzc2V0VVJMID0gdXNlQ2FsbGJhY2soXG4gICAgKGFzc2V0TmFtZTogc3RyaW5nLCBvcmdTaG9ydE5hbWU6IHN0cmluZykgPT4ge1xuICAgICAgcmV0dXJuIGAke2dldENkbkJhc2VQYXRoKCl9L2Fzc2V0cy8ke29yZ1Nob3J0TmFtZX0vJHthc3NldE5hbWV9YDtcbiAgICB9LFxuICAgIFtnZXRDZG5CYXNlUGF0aF1cbiAgKTtcblxuICBjb25zdCB2YWx1ZSA9IHVzZU1lbW8oXG4gICAgKCkgPT4gKHtcbiAgICAgIGNkblVybCxcbiAgICAgIGdldENkbkJhc2VQYXRoLFxuICAgICAgZ2V0QXNzZXRVUkwsXG4gICAgfSksXG4gICAgW2NkblVybCwgZ2V0Q2RuQmFzZVBhdGgsIGdldEFzc2V0VVJMXVxuICApO1xuXG4gIHJldHVybiA8Q2RuQ29udGV4dC5Qcm92aWRlciB2YWx1ZT17dmFsdWV9PntjaGlsZHJlbn08L0NkbkNvbnRleHQuUHJvdmlkZXI+O1xufTtcblxuZXhwb3J0IGNvbnN0IHVzZUNkbiA9ICgpID0+IHtcbiAgY29uc3QgY29udGV4dCA9IHVzZUNvbnRleHQoQ2RuQ29udGV4dCk7XG4gIGlmICghY29udGV4dCkge1xuICAgIHRocm93IG5ldyBFcnJvcihcInVzZUNkbiBtdXN0IGJlIHVzZWQgd2l0aGluIGEgQ2RuUHJvdmlkZXJcIik7XG4gIH1cbiAgcmV0dXJuIGNvbnRleHQ7XG59O1xuIiwiZXhwb3J0IGNsYXNzIFNlc3Npb25SZXN0YXJ0UmVxdWlyZWQgZXh0ZW5kcyBFcnJvciB7XG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHN1cGVyKCdTZXNzaW9uIHJlc3RhcnQgcmVxdWlyZWQnKTtcbiAgICB0aGlzLm5hbWUgPSAnU2Vzc2lvblJlc3RhcnRSZXF1aXJlZCc7XG4gIH1cbn1cbiIsImV4cG9ydCBjbGFzcyBVbnN1cHBvcnRlZFByb2R1Y3RFeGNlcHRpb24gZXh0ZW5kcyBFcnJvciB7XG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHN1cGVyKCdVbnN1cHBvcnRlZCBwcm9kdWN0Jyk7XG4gICAgdGhpcy5uYW1lID0gJ1Vuc3VwcG9ydGVkUHJvZHVjdCc7XG4gIH1cbn0iLCJpbXBvcnQgTG9nZ2VyIGZyb20gXCJzcmMvYXBwbGljYXRpb24vbG9nZ2luZy9sb2dnZXJcIjtcbmltcG9ydCB7XG4gIENvbmZpZ3VyYXRpb24sXG4gIEN1c3RvbWVyU2VydmljZUFwaSxcbiAgRGVmYXVsdEFwaSxcbiAgSW5mZXJlbmNlQXBpLFxuICBSZXBvcnRTZXNzaW9uUmVxdWVzdCxcbiAgUmVzcG9uc2VFcnJvcixcbiAgVXNlckV2ZW50Q2F0ZWdvcnksXG4gIFYxR2V0U2Vzc2lvbk1lc3NhZ2VzMjAwUmVzcG9uc2UsXG4gIFYxT3JnQ29uZmlnR2V0UmVxdWVzdCxcbiAgQ29udGV4dFNvdXJjZUVudW0sXG4gIFYxT3JnQ29uZmlnR2V0U291cmNlRW51bSxcbiAgQ3VzdG9tZXJTZXJ2aWNlUHJvdmlkZXIsXG4gIFJlc3BvbnNlQ2F0ZWdvcnksXG4gIEZvcm1UeXBlLFxufSBmcm9tIFwiQHNwaWZmeS1haS9jb21tZXJjZS1hcGktY2xpZW50XCI7XG5pbXBvcnQgeyB2YWxpZGF0ZVN1Z2dlc3Rpb24gfSBmcm9tIFwic3JjL2FwcGxpY2F0aW9uL21vZGVscy92YWxpZGF0b3JzL3ZhbGlkYXRlU3VnZ2VzdGlvblwiO1xuaW1wb3J0IHsgdmFsaWRhdGVVc2VyRXZlbnQgfSBmcm9tIFwic3JjL2FwcGxpY2F0aW9uL21vZGVscy92YWxpZGF0b3JzL3ZhbGlkYXRlVXNlckV2ZW50XCI7XG5pbXBvcnQge1xuICBtZXNzYWdlRnJvbVF1ZXJ5RXZlbnQsXG4gIG1lc3NhZ2VGcm9tUmVzcG9uc2UsXG4gIG1lc3NhZ2VGcm9tU3VnZ2VzdGlvbkV2ZW50LFxufSBmcm9tIFwic3JjL2FwcGxpY2F0aW9uL3V0aWxzXCI7XG5pbXBvcnQge1xuICBNZXNzYWdlLFxuICBOZXh0TWVzc2FnZVJlcXVlc3QsXG4gIFJlc3BvbnNlLFxuICBTdWdnZXN0aW9uLFxuICBTdXBwb3J0ZWRFdmVudFJlcXVlc3QsXG4gIFVzZXJFdmVudCxcbn0gZnJvbSBcInNyYy9hcHBsaWNhdGlvbi9tb2RlbHNcIjtcbmltcG9ydCB7IG1lc3NhZ2VSZXF1ZXN0VG9Db21tZXJjZU1lc3NhZ2VSZXF1ZXN0IH0gZnJvbSBcInNyYy9hcHBsaWNhdGlvbi91dGlscy9uZXh0TWVzc2FnZVJlcXVlc3RUb0FwaVJlcXVlc3RcIjtcbmltcG9ydCB7IHZhbGlkYXRlUmVzcG9uc2UgfSBmcm9tIFwic3JjL2FwcGxpY2F0aW9uL21vZGVscy92YWxpZGF0b3JzL3ZhbGlkYXRlUmVzcG9uc2VcIjtcbmltcG9ydCB7IGNvcmVTdXBwb3J0ZWRFdmVudFJlcXVlc3RUb0FwaVJlcXVlc3QgfSBmcm9tIFwic3JjL2FwcGxpY2F0aW9uL3V0aWxzL3N1cHBvcnRlZEV2ZW50UmVxdWVzdFRvQXBpUmVxdWVzdFwiO1xuaW1wb3J0IHsgU2Vzc2lvblJlc3RhcnRSZXF1aXJlZCB9IGZyb20gXCJzcmMvdHlwZXMvZXhjZXB0aW9ucy9zZXNzaW9uRXhjZXB0aW9uc1wiO1xuaW1wb3J0IHsgVW5zdXBwb3J0ZWRQcm9kdWN0RXhjZXB0aW9uIH0gZnJvbSBcInNyYy90eXBlcy9leGNlcHRpb25zL3Vuc3VwcG9ydGVkUHJvZHVjdEV4Y2VwdGlvbnNcIjtcbmltcG9ydCB7IENsaWVudERldGFpbHMgfSBmcm9tIFwic3JjL2FwcGxpY2F0aW9uL21vZGVscy9jbGllbnREZXRhaWxzXCI7XG5pbXBvcnQgeyBnZXRBdG9tU3RvcmUgfSBmcm9tIFwic3JjL2F0b21zL2F0b21TdG9yZS9hdG9tU3RvcmVcIjtcbmltcG9ydCB7IFByb2R1Y3RFeHBlcmltZW50IH0gZnJvbSBcInNyYy9hcHBsaWNhdGlvbi9tb2RlbHMvcHJvZHVjdEV4cGVyaW1lbnRcIjtcbmltcG9ydCB7IEZlYXR1cmVHYXRlcyB9IGZyb20gXCJzcmMvYXBwbGljYXRpb24vbW9kZWxzL2ZlYXR1cmVHYXRlc1wiO1xuaW1wb3J0IHsgdmFsaWRhdGVPcmdDb25maWdSZXN1bHRzIH0gZnJvbSBcInNyYy9hcHBsaWNhdGlvbi9tb2RlbHMvdmFsaWRhdG9ycy92YWxpZGF0ZU9yZ0NvbmZpZ1Jlc3VsdHNcIjtcbmltcG9ydCB7IE9yZ0NvbmZpZyB9IGZyb20gXCJzcmMvYXBwbGljYXRpb24vbW9kZWxzL2FwaS9vcmdDb25maWdSZXN1bHRzXCI7XG5pbXBvcnQgeyBTdXBwb3J0ZWRFdmVudCB9IGZyb20gXCJzcmMvYXRvbXMvYXBwL3ZhcmlhbnRcIjtcbmltcG9ydCB7IG1lc3NhZ2VGcm9tRm9ybVN1Ym1pdHRlZEV2ZW50IH0gZnJvbSBcInNyYy9hcHBsaWNhdGlvbi91dGlscy9tZXNzYWdlRnJvbUZvcm1TdWJtaXR0ZWRFdmVudFwiO1xuaW1wb3J0IHR5cGUgeyBDb250ZXh0IH0gZnJvbSBcIkBzcGlmZnktYWkvY29tbWVyY2UtYXBpLWNsaWVudC9kaXN0L21vZGVscy9Db250ZXh0XCI7XG5pbXBvcnQgeyBDb250ZXh0RW52RW51bSB9IGZyb20gXCJAc3BpZmZ5LWFpL2NvbW1lcmNlLWFwaS1jbGllbnRcIjsgLy8gSW1wb3J0IENvbnRleHRFbnZFbnVtXG5pbXBvcnQge1xuICBiYXNlVXJsQXRvbSxcbiAgcmVhY3RBcHBOYW1lQXRvbSxcbiAgY29udGV4dFNvdXJjZUF0b20sXG4gIG9yZ1Nob3J0TmFtZUF0b20sXG4gIGVudkF0b20sIC8vIEltcG9ydCBlbnZBdG9tXG59IGZyb20gXCJzcmMvYXRvbXMvZW52aXZlL2Vudml2ZUNvbmZpZ1wiO1xuaW1wb3J0IHsgdXNlcklkQXRvbSwgY2hhdElkQXRvbSB9IGZyb20gXCJzcmMvYXRvbXMvYXBwXCI7IC8vIEltcG9ydCB1c2VySWRBdG9tIGFuZCBjaGF0SWRBdG9tXG5pbXBvcnQgeyBvcmdJZEF0b20sIGZlYXR1cmVGbGFnU2VydmljZUF0b20gfSBmcm9tIFwic3JjL2F0b21zL29yZy9ncmFwaHFsQ29uZmlnXCI7IC8vIEltcG9ydCBuZXcgb3JnSWRBdG9tIGFuZCBmZWF0dXJlRmxhZ1NlcnZpY2VBdG9tXG5cbmFzeW5jIGZ1bmN0aW9uIGVycm9yUmVzcG9uc2VCb2R5KGVycm9yOiBSZXNwb25zZUVycm9yKSB7XG4gIHRyeSB7XG4gICAgcmV0dXJuIGF3YWl0IGVycm9yLnJlc3BvbnNlLmpzb24oKTtcbiAgfSBjYXRjaCB7XG4gICAgcmV0dXJuIHt9O1xuICB9XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHRocm93U2Vzc2lvblJlc3RhcnRSZXF1aXJlZElmKGVycm9yTXNnOiBzdHJpbmcsIGVycm9yOiB1bmtub3duKSB7XG4gIGlmICghKGVycm9yIGluc3RhbmNlb2YgUmVzcG9uc2VFcnJvcikpIHtcbiAgICBMb2dnZXIubG9nSW5mbyhlcnJvck1zZywgZXJyb3IpO1xuICAgIHRocm93IGVycm9yO1xuICB9XG5cbiAgY29uc3QgZXJyb3JSZXNwb25zZSA9IGF3YWl0IGVycm9yUmVzcG9uc2VCb2R5KGVycm9yKTtcbiAgaWYgKFxuICAgIGVycm9yUmVzcG9uc2U/Lm1lc3NhZ2U/LnRvTG93ZXJDYXNlKCkgPT09IFwidW5zdXBwb3J0ZWQgcHJvZHVjdFwiIHx8IC8vIGZvciBiYWNrd2FyZCBjb21wYXRpYmlsaXR5LiBuZXdlciB2ZXJzaW9ucyBvZiB0aGUgQVBJIHJldHVybiBzdWJfY29kZSBpbnN0ZWFkIG9mIG1lc3NhZ2VcbiAgICBlcnJvclJlc3BvbnNlPy5hcHBfY29kZT8udG9VcHBlckNhc2UoKSA9PT0gXCJQUk9EVUNUX05PVF9GT1VORFwiXG4gICkge1xuICAgIHRocm93IG5ldyBVbnN1cHBvcnRlZFByb2R1Y3RFeGNlcHRpb24oKTtcbiAgfSBlbHNlIGlmIChcbiAgICBlcnJvclJlc3BvbnNlPy5hcHBfY29kZT8udG9VcHBlckNhc2UoKSA9PT0gXCJSRVNUQVJUX1NFU1NJT05cIiB8fFxuICAgIGVycm9yUmVzcG9uc2U/LnN1Yl9jb2RlPy50b1VwcGVyQ2FzZSgpID09PSBcIk5PVF9GT1VORFwiIC8vIGZvciBiYWNrd2FyZCBjb21wYXRpYmlsaXR5LiBuZXcgQVBJIHJlc3BvbnNlcyB3aWxsIGNvbnRhaW4gXCJhcHBfY29kZVwiXG4gICkge1xuICAgIExvZ2dlci5sb2dJbmZvKFxuICAgICAgXCJTZXNzaW9uIGRvZXMgbm90IGV4aXN0LiBSZS1zdGFydCBzZXNzaW9uXCIsXG4gICAgICBlcnJvcixcbiAgICAgIGVycm9yLnJlc3BvbnNlLFxuICAgICAgZXJyb3JSZXNwb25zZVxuICAgICk7XG4gICAgdGhyb3cgbmV3IFNlc3Npb25SZXN0YXJ0UmVxdWlyZWQoKTtcbiAgfVxuXG4gIExvZ2dlci5sb2dJbmZvKGVycm9yTXNnLCBlcnJvcik7XG4gIHRocm93IGVycm9yO1xufVxuXG5jbGFzcyBDb21tZXJjZUFwaUNsaWVudCB7XG4gIHByaXZhdGUgcmVhZG9ubHkgZGVmYXVsdEFwaTogRGVmYXVsdEFwaTtcblxuICBwcml2YXRlIHJlYWRvbmx5IGN1c3RvbWVyU2VydmljZUFwaTogQ3VzdG9tZXJTZXJ2aWNlQXBpO1xuXG4gIHByaXZhdGUgcmVhZG9ubHkgaW5mZXJlbmNlQXBpOiBJbmZlcmVuY2VBcGk7XG5cbiAgcHJpdmF0ZSBzdGF0aWMgaW5zdGFuY2U6IENvbW1lcmNlQXBpQ2xpZW50IHwgdW5kZWZpbmVkO1xuXG4gIHByaXZhdGUgc3VnZ2VzdGlvbnNBYm9ydENvbnRyb2xsZXIgPSBuZXcgQWJvcnRDb250cm9sbGVyKCk7XG5cbiAgcHJpdmF0ZSByZXNwb25zZXNBYm9ydENvbnRyb2xsZXIgPSBuZXcgQWJvcnRDb250cm9sbGVyKCk7XG5cbiAgcHJpdmF0ZSBzdGF0aWMgZ2V0SW5zdGFuY2UgPSAoKTogQ29tbWVyY2VBcGlDbGllbnQgPT4ge1xuICAgIGlmICghQ29tbWVyY2VBcGlDbGllbnQuaW5zdGFuY2UpIHtcbiAgICAgIENvbW1lcmNlQXBpQ2xpZW50Lmluc3RhbmNlID0gbmV3IENvbW1lcmNlQXBpQ2xpZW50KCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIENvbW1lcmNlQXBpQ2xpZW50Lmluc3RhbmNlO1xuICB9O1xuXG4gIHByaXZhdGUgY29uc3RydWN0b3IoYmFzZVBhdGg/OiBzdHJpbmcpIHtcbiAgICBjb25zdCBhdG9tU3RvcmUgPSBnZXRBdG9tU3RvcmUoKTtcbiAgICBjb25zdCBiYXNlVXJsID0gYXRvbVN0b3JlLmdldChiYXNlVXJsQXRvbSk7XG4gICAgY29uc3QgcGF0aCA9IGJhc2VQYXRoIHx8IGJhc2VVcmw7XG4gICAgLy8gQVBJIEtleSBpcyBub3cgaGFuZGxlZCBhdCB0aGUgRW52aXZlQ29uZmlnUHJvdmlkZXIgbGV2ZWxcbiAgICBjb25zdCBjb25maWc6IENvbmZpZ3VyYXRpb24gPSBuZXcgQ29uZmlndXJhdGlvbih7XG4gICAgICBiYXNlUGF0aDogcGF0aCxcbiAgICAgIGhlYWRlcnM6IHtcbiAgICAgICAgXCJDb250ZW50LVR5cGVcIjogXCJhcHBsaWNhdGlvbi9qc29uXCIsXG4gICAgICAgIEFjY2VwdDogXCJhcHBsaWNhdGlvbi9qc29uXCIsXG4gICAgICB9LFxuICAgIH0pO1xuICAgIHRoaXMuZGVmYXVsdEFwaSA9IG5ldyBEZWZhdWx0QXBpKGNvbmZpZyk7XG4gICAgdGhpcy5pbmZlcmVuY2VBcGkgPSBuZXcgSW5mZXJlbmNlQXBpKGNvbmZpZyk7XG4gICAgdGhpcy5jdXN0b21lclNlcnZpY2VBcGkgPSBuZXcgQ3VzdG9tZXJTZXJ2aWNlQXBpKGNvbmZpZyk7XG4gIH1cblxuICBzdGF0aWMgcmVzb2x2ZVVybCA9IGFzeW5jICh1cmw6IHN0cmluZykgPT4ge1xuICAgIGNvbnN0IGF0b21TdG9yZSA9IGdldEF0b21TdG9yZSgpO1xuICAgIGNvbnN0IG9yZ1Nob3J0TmFtZSA9IGF0b21TdG9yZS5nZXQob3JnU2hvcnROYW1lQXRvbSk7XG4gICAgY29uc3Qgb3JnSWQgPSBhdG9tU3RvcmUuZ2V0KG9yZ0lkQXRvbSk7XG4gICAgY29uc3QgdXNlcklkID0gYXRvbVN0b3JlLmdldCh1c2VySWRBdG9tKTtcbiAgICBjb25zdCBjaGF0SWQgPSBhdG9tU3RvcmUuZ2V0KGNoYXRJZEF0b20pO1xuICAgIGNvbnN0IHNvdXJjZSA9IGF0b21TdG9yZS5nZXQoY29udGV4dFNvdXJjZUF0b20pO1xuICAgIGNvbnN0IGVudiA9IGF0b21TdG9yZS5nZXQoZW52QXRvbSk7XG5cbiAgICBjb25zdCBmZWF0dXJlRmxhZ1NlcnZpY2UgPSBhdG9tU3RvcmUuZ2V0KGZlYXR1cmVGbGFnU2VydmljZUF0b20pO1xuXG4gICAgY29uc3QgY29udGV4dDogQ29udGV4dCA9IHtcbiAgICAgIHVzZXJfaWQ6IHVzZXJJZCA/PyBcIlwiLFxuICAgICAgb3JnX2lkOiBvcmdJZCA/PyBcIlwiLFxuICAgICAgb3JnX3Nob3J0X25hbWU6IG9yZ1Nob3J0TmFtZSA/PyBcIlwiLFxuICAgICAgY2hhdF9pZDogY2hhdElkID8/IFwiXCIsXG4gICAgICBzb3VyY2U6IHNvdXJjZSA/PyBDb250ZXh0U291cmNlRW51bS5BcHAsXG4gICAgICBlbnY6IChlbnYgYXMgQ29udGV4dEVudkVudW0pID8/IENvbnRleHRFbnZFbnVtLkRldiwgLy8gQ2FzdCBlbnYgdG8gQ29udGV4dEVudkVudW1cbiAgICB9O1xuXG4gICAgY29uc3QgZmVhdHVyZUdhdGVzID1cbiAgICAgIGZlYXR1cmVGbGFnU2VydmljZT8uZmVhdHVyZUZsYWdTZXJ2aWNlPy5nZXRGZWF0dXJlRmxhZ3MoKSB8fCB7fTtcbiAgICBjb25zdCB1cmxSZXNvbHZpbmdSZXF1ZXN0ID0ge1xuICAgICAgdXJsLFxuICAgICAgY29udGV4dCxcbiAgICAgIGZlYXR1cmVfZ2F0ZXM6IGZlYXR1cmVHYXRlcyxcbiAgICB9O1xuXG4gICAgY29uc3QgcmF3UmVzcG9uc2UgPVxuICAgICAgYXdhaXQgQ29tbWVyY2VBcGlDbGllbnQuZ2V0SW5zdGFuY2UoKS5pbmZlcmVuY2VBcGkudjFVcmxSZXNvbHZpbmdQb3N0UmF3KHtcbiAgICAgICAgVXJsUmVzb2x2aW5nUmVxdWVzdDogdXJsUmVzb2x2aW5nUmVxdWVzdCxcbiAgICAgIH0pO1xuXG4gICAgY29uc3QgcmVzcG9uc2VCb2R5ID0gYXdhaXQgcmF3UmVzcG9uc2UucmF3Lmpzb24oKTtcblxuICAgIHJldHVybiByZXNwb25zZUJvZHk7XG4gIH07XG5cbiAgc3RhdGljIHJlcG9ydFNlc3Npb24gPSBhc3luYyAoXG4gICAgcmVwb3J0UmVxdWVzdDogUmVwb3J0U2Vzc2lvblJlcXVlc3RcbiAgKTogUHJvbWlzZTx2b2lkPiA9PiB7XG4gICAgYXdhaXQgQ29tbWVyY2VBcGlDbGllbnQuZ2V0SW5zdGFuY2UoKS5kZWZhdWx0QXBpLnYxQ2hhdHNSZXBvcnRTZXNzaW9uSWRQb3N0KFxuICAgICAge1xuICAgICAgICBSZXBvcnRTZXNzaW9uUmVxdWVzdDogcmVwb3J0UmVxdWVzdCxcbiAgICAgIH1cbiAgICApO1xuICB9O1xuXG4gIHN0YXRpYyBnZXROZXh0UmVzcG9uc2VzID0gYXN5bmMgKFxuICAgIHBheWxvYWQ6IE5leHRNZXNzYWdlUmVxdWVzdFxuICApOiBQcm9taXNlPE1lc3NhZ2VbXT4gPT4ge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCByZXNwb25zZSA9XG4gICAgICAgIGF3YWl0IENvbW1lcmNlQXBpQ2xpZW50LmdldEluc3RhbmNlKCkuaW5mZXJlbmNlQXBpLnYxTmV4dFJlc3BvbnNlc1Bvc3Qoe1xuICAgICAgICAgIE5leHRNZXNzYWdlUmVxdWVzdDogbWVzc2FnZVJlcXVlc3RUb0NvbW1lcmNlTWVzc2FnZVJlcXVlc3QocGF5bG9hZCksXG4gICAgICAgIH0pO1xuICAgICAgY29uc3QgbWVzc2FnZXMgPSByZXNwb25zZVxuICAgICAgICAubWFwKChyZXNwKSA9PiB2YWxpZGF0ZVJlc3BvbnNlKHJlc3ApKVxuICAgICAgICAubWFwKChyZXNwKSA9PiBtZXNzYWdlRnJvbVJlc3BvbnNlKHJlc3ApKTtcblxuICAgICAgcmV0dXJuIG1lc3NhZ2VzLmZpbHRlcigobSk6IG0gaXMgTWVzc2FnZSA9PiBtICE9IG51bGwpO1xuICAgIH0gY2F0Y2ggKGVycjogdW5rbm93bikge1xuICAgICAgTG9nZ2VyLmxvZ0luZm8oXCJGYWlsZWQgdG8gZ2V0IG5leHQgcmVzcG9uc2VzXCIsIGVyciwge1xuICAgICAgICBwYXlsb2FkQ29udGV4dDogcGF5bG9hZD8uY29udGV4dCxcbiAgICAgICAgdXNlckV2ZW50czogcGF5bG9hZD8udXNlckV2ZW50cyxcbiAgICAgIH0pO1xuICAgICAgYXdhaXQgdGhyb3dTZXNzaW9uUmVzdGFydFJlcXVpcmVkSWYoXCJGYWlsZWQgdG8gZ2V0IG5leHQgcmVzcG9uc2VzXCIsIGVycik7XG4gICAgICByZXR1cm4gW107XG4gICAgfVxuICB9O1xuXG4gIHN0YXRpYyBnZXROZXh0UmVzcG9uc2VTdHJlYW1pbmcgPSAoXG4gICAgcGF5bG9hZDogTmV4dE1lc3NhZ2VSZXF1ZXN0XG4gICk6IEFzeW5jR2VuZXJhdG9yPFJlc3BvbnNlLCB2b2lkLCB1bmtub3duPiA9PiB7XG4gICAgYXN5bmMgZnVuY3Rpb24qIGdlbmVyYXRlKFxuICAgICAgaW5mZXJlbmNlQXBpOiBJbmZlcmVuY2VBcGksXG4gICAgICBhYm9ydENvbnRyb2xsZXI6IEFib3J0Q29udHJvbGxlclxuICAgICkge1xuICAgICAgLy8gbWFrZSBzdXJlIHN0cmVhbWluZyBpcyBlbmFibGVkXG4gICAgICB0cnkge1xuICAgICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IGluZmVyZW5jZUFwaS52MU5leHRSZXNwb25zZXNQb3N0UmF3KFxuICAgICAgICAgIHtcbiAgICAgICAgICAgIE5leHRNZXNzYWdlUmVxdWVzdDogbWVzc2FnZVJlcXVlc3RUb0NvbW1lcmNlTWVzc2FnZVJlcXVlc3QocGF5bG9hZCksXG4gICAgICAgICAgfSxcbiAgICAgICAgICB7IHNpZ25hbDogYWJvcnRDb250cm9sbGVyLnNpZ25hbCB9XG4gICAgICAgICk7XG5cbiAgICAgICAgLy8gUmVhZCB0aGUgcmVzcG9uc2UgYXMgYSBzdHJlYW0gb2YgZGF0YVxuICAgICAgICBpZiAoIXJlc3BvbnNlLnJhdy5ib2R5KSB7XG4gICAgICAgICAgTG9nZ2VyLmxvZ0Vycm9yKFxuICAgICAgICAgICAgXCJbc3BpZmZ5LWFpXSBObyBib2R5IGluIHRoZSBzdHJlYW1lZCByZXNwb25zZVwiLFxuICAgICAgICAgICAgdW5kZWZpbmVkLFxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICByZXNwb25zZTogcmVzcG9uc2UucmF3LFxuICAgICAgICAgICAgfVxuICAgICAgICAgICk7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgcmVhZGVyID0gcmVzcG9uc2UucmF3LmJvZHkuZ2V0UmVhZGVyKCk7XG4gICAgICAgIGNvbnN0IGRlY29kZXIgPSBuZXcgVGV4dERlY29kZXIoXCJ1dGYtOFwiKTtcblxuICAgICAgICBsZXQgcGFydGlhbCA9IFwiXCI7XG4gICAgICAgIC8vIFRPRE8gdGhpcyBmdW5jdGlvbiBpcyByZWNyZWF0ZWQgZXZlcnkgdGltZSBuZXcgZGF0YSBjb21lcyBmcm9tIHRoZSBzdHJlYW0gLSBkZWZpbmUgaXQgb3V0c2lkZSBvZiB0aGUgZ2VuZXJhdG9yXG4gICAgICAgIGNvbnN0IHNhZmVQYXJzZSA9IChsaW5lOiBzdHJpbmcpOiB1bmtub3duID0+IHtcbiAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgcmV0dXJuIEpTT04ucGFyc2UobGluZSk7IC8vIFBhcnNlIHRoZSBKU09OIHN0cmluZ1xuICAgICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgTG9nZ2VyLmxvZ0Vycm9yKFwiW3NwaWZmeS1haV0gRXJyb3IgcGFyc2luZyBzdHJlYW1lZCBsaW5lXCIsIGVyciwge1xuICAgICAgICAgICAgICBsaW5lLFxuICAgICAgICAgICAgICBwYXJ0aWFsLFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAvLyBzd2FsbG93IHRoZSBlcnJvciBhbmQgc2V0IHRoZSBwYXJ0aWFsIHRvIG91ciBjdXJyZW50IGNodW5rXG4gICAgICAgICAgICBwYXJ0aWFsID0gbGluZTtcbiAgICAgICAgICAgIHJldHVybiBwYXJ0aWFsO1xuICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICAvLyBUT0RPIHRoaXMgZnVuY3Rpb24gaXMgcmVjcmVhdGVkIGV2ZXJ5IHRpbWUgbmV3IGRhdGEgY29tZXMgZnJvbSB0aGUgc3RyZWFtIC0gZGVmaW5lIGl0IG91dHNpZGUgb2YgdGhlIGdlbmVyYXRvclxuICAgICAgICBjb25zdCBwcm9jZXNzQ2h1bmsgPSAoY2h1bms6IHN0cmluZyk6IHVua25vd25bXSA9PiB7XG4gICAgICAgICAgLy8gbWVyZ2UgdGhlIHBhcnRpYWwgd2l0aCB0aGUgaW5jb21pbmcgY2h1bmtcbiAgICAgICAgICBjb25zdCBsaW5lcyA9IGAke3BhcnRpYWx9JHtjaHVua31gLnNwbGl0KFwiXFxuXCIpO1xuXG4gICAgICAgICAgY29uc3QgcGFyc2VkTGluZXMgPSBsaW5lc1xuICAgICAgICAgICAgLm1hcCgobGluZSkgPT4gbGluZS5yZXBsYWNlKC9eZGF0YTogLywgXCJcIikudHJpbSgpKSAvLyBSZW1vdmUgdGhlIFwiZGF0YTogXCIgcHJlZml4XG4gICAgICAgICAgICAuZmlsdGVyKChsaW5lKSA9PiBsaW5lICE9PSBcIlwiICYmIGxpbmUgIT09IFwiW0RPTkVdXCIpIC8vIFJlbW92ZSBlbXB0eSBsaW5lcyBhbmQgXCJbRE9ORV1cIlxuICAgICAgICAgICAgLm1hcChzYWZlUGFyc2UpXG4gICAgICAgICAgICAuZmlsdGVyKCh2KSA9PiB2KTsgLy8gYW5kIGZpbHRlciBvdXQgdGhlIHVuZGVmaW5lZCB2YWx1ZXNcbiAgICAgICAgICByZXR1cm4gcGFyc2VkTGluZXM7XG4gICAgICAgIH07XG5cbiAgICAgICAgd2hpbGUgKHRydWUpIHtcbiAgICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tYXdhaXQtaW4tbG9vcFxuICAgICAgICAgIGNvbnN0IHsgZG9uZSwgdmFsdWUgfSA9IGF3YWl0IHJlYWRlci5yZWFkKCk7XG5cbiAgICAgICAgICBpZiAoZG9uZSkge1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgLy8gTWFzc2FnZSBhbmQgcGFyc2UgdGhlIGNodW5rIG9mIGRhdGFcbiAgICAgICAgICBjb25zdCBjaHVuayA9IGRlY29kZXIuZGVjb2RlKHZhbHVlKTtcbiAgICAgICAgICBjb25zdCBwYXJzZWRMaW5lcyA9IHByb2Nlc3NDaHVuayhjaHVuayk7XG5cbiAgICAgICAgICBmb3IgKGNvbnN0IHBhcnNlZExpbmUgb2YgcGFyc2VkTGluZXMpIHtcbiAgICAgICAgICAgIGNvbnN0IHZhbGlkYXRlZFJlc3BvbnNlID0gdmFsaWRhdGVSZXNwb25zZShwYXJzZWRMaW5lKTtcblxuICAgICAgICAgICAgaWYgKHZhbGlkYXRlZFJlc3BvbnNlKSB7XG4gICAgICAgICAgICAgIHlpZWxkIHZhbGlkYXRlZFJlc3BvbnNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSBjYXRjaCAoZXJyb3I6IHVua25vd24pIHtcbiAgICAgICAgTG9nZ2VyLmxvZ0Vycm9yKFxuICAgICAgICAgIFwiW3NwaWZmeS1haV0gRmFpbGVkIHRvIGdldCBuZXh0IHN0cmVhbWluZyByZXNwb25zZXNcIixcbiAgICAgICAgICBlcnJvcixcbiAgICAgICAgICB7XG4gICAgICAgICAgICBwYXlsb2FkQ29udGV4dDogcGF5bG9hZD8uY29udGV4dCxcbiAgICAgICAgICAgIHVzZXJFdmVudHM6IHBheWxvYWQ/LnVzZXJFdmVudHMsXG4gICAgICAgICAgfVxuICAgICAgICApO1xuICAgICAgICBhd2FpdCB0aHJvd1Nlc3Npb25SZXN0YXJ0UmVxdWlyZWRJZihcbiAgICAgICAgICBcIkZhaWxlZCB0byBnZXQgbmV4dCBzdHJlYW1pbmcgcmVzcG9uc2VzXCIsXG4gICAgICAgICAgZXJyb3JcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBDb21tZXJjZUFwaUNsaWVudC5nZXRJbnN0YW5jZSgpLnJlc3BvbnNlc0Fib3J0Q29udHJvbGxlci5hYm9ydCgpO1xuICAgIENvbW1lcmNlQXBpQ2xpZW50LmdldEluc3RhbmNlKCkucmVzcG9uc2VzQWJvcnRDb250cm9sbGVyID1cbiAgICAgIG5ldyBBYm9ydENvbnRyb2xsZXIoKTtcblxuICAgIHJldHVybiBnZW5lcmF0ZShcbiAgICAgIENvbW1lcmNlQXBpQ2xpZW50LmdldEluc3RhbmNlKCkuaW5mZXJlbmNlQXBpLFxuICAgICAgQ29tbWVyY2VBcGlDbGllbnQuZ2V0SW5zdGFuY2UoKS5yZXNwb25zZXNBYm9ydENvbnRyb2xsZXJcbiAgICApO1xuICB9O1xuXG4gIHN0YXRpYyBnZXROZXh0U3VnZ2VzdGlvbnMgPSBhc3luYyAoXG4gICAgcGF5bG9hZDogTmV4dE1lc3NhZ2VSZXF1ZXN0XG4gICk6IFByb21pc2U8U3VnZ2VzdGlvbltdPiA9PiB7XG4gICAgdHJ5IHtcbiAgICAgIENvbW1lcmNlQXBpQ2xpZW50LmdldEluc3RhbmNlKCkuc3VnZ2VzdGlvbnNBYm9ydENvbnRyb2xsZXIuYWJvcnQoKTtcbiAgICAgIENvbW1lcmNlQXBpQ2xpZW50LmdldEluc3RhbmNlKCkuc3VnZ2VzdGlvbnNBYm9ydENvbnRyb2xsZXIgPVxuICAgICAgICBuZXcgQWJvcnRDb250cm9sbGVyKCk7XG5cbiAgICAgIGNvbnN0IHJlc3BvbnNlID1cbiAgICAgICAgYXdhaXQgQ29tbWVyY2VBcGlDbGllbnQuZ2V0SW5zdGFuY2UoKS5pbmZlcmVuY2VBcGkudjFOZXh0U3VnZ2VzdGlvbnNQb3N0KFxuICAgICAgICAgIHtcbiAgICAgICAgICAgIE5leHRNZXNzYWdlUmVxdWVzdDogbWVzc2FnZVJlcXVlc3RUb0NvbW1lcmNlTWVzc2FnZVJlcXVlc3QocGF5bG9hZCksXG4gICAgICAgICAgfSxcbiAgICAgICAgICB7XG4gICAgICAgICAgICBzaWduYWw6XG4gICAgICAgICAgICAgIENvbW1lcmNlQXBpQ2xpZW50LmdldEluc3RhbmNlKCkuc3VnZ2VzdGlvbnNBYm9ydENvbnRyb2xsZXIuc2lnbmFsLFxuICAgICAgICAgIH1cbiAgICAgICAgKTtcblxuICAgICAgY29uc3Qgc3VnZ2VzdGlvbnMgPSByZXNwb25zZVxuICAgICAgICAubWFwKChyZXNwKSA9PiB2YWxpZGF0ZVN1Z2dlc3Rpb24ocmVzcCkpXG4gICAgICAgIC5maWx0ZXIoKHN1Z2dlc3Rpb24pOiBzdWdnZXN0aW9uIGlzIFN1Z2dlc3Rpb24gPT4gc3VnZ2VzdGlvbiAhPSBudWxsKTtcblxuICAgICAgcmV0dXJuIHN1Z2dlc3Rpb25zO1xuICAgIH0gY2F0Y2ggKGVycm9yOiB1bmtub3duKSB7XG4gICAgICBMb2dnZXIubG9nSW5mbyhcIkZhaWxlZCB0byBnZXQgc3VnZ2VzdGlvbnNcIiwgZXJyb3IsIHtcbiAgICAgICAgcGF5bG9hZENvbnRleHQ6IHBheWxvYWQ/LmNvbnRleHQsXG4gICAgICAgIHVzZXJFdmVudHM6IHBheWxvYWQ/LnVzZXJFdmVudHMsXG4gICAgICB9KTtcblxuICAgICAgYXdhaXQgdGhyb3dTZXNzaW9uUmVzdGFydFJlcXVpcmVkSWYoXCJGYWlsZWQgdG8gZ2V0IHN1Z2dlc3Rpb25zXCIsIGVycm9yKTtcbiAgICAgIHJldHVybiBbXTtcbiAgICB9XG4gIH07XG5cbiAgLyoqXG4gICAqIEZldGNoZXMgdGhlIGV4aXN0aW5nIGNoYXQgZGF0YSBmb3IgYSBnaXZlbiBzZXNzaW9uIGFuZCB0cmFuc2Zvcm1zIHRoZW0gdG8gcmVjb25zdHJ1Y3QgdGhlIGNoYXQgaGlzdG9yeS5cbiAgICpcbiAgICogQHBhcmFtIG9yZ0lkIFRoZSBvcmdhbml6YXRpb24gSWRcbiAgICogQHBhcmFtIGNoYXRJZCBUaGUgZXhpc3RpbmcgY2hhdCBJZFxuICAgKiBAcGFyYW0gdXNlcklkIFRoZSB1c2VyIElkXG4gICAqXG4gICAqIEByZXR1cm5zIEEgbGlzdCBvZiBtZXNzYWdlcyB0aGF0IHdlcmUgZXhjaGFuZ2VkIGluIHRoZSBjaGF0LCB0aHJvd3MgYW4gZXJyb3IgaWYgdGhlIGNoYXQgc2Vzc2lvbiBoYXMgZXhwaXJlZC5cbiAgICovXG4gIHN0YXRpYyBnZXRSZXNwb25zZXMgPSBhc3luYyAoXG4gICAgb3JnSWQ6IHN0cmluZyxcbiAgICBjaGF0SWQ6IHN0cmluZyxcbiAgICB1c2VySWQ6IHN0cmluZ1xuICApOiBQcm9taXNlPHtcbiAgICByZXNwb25zZXM6IFJlc3BvbnNlW11bXTtcbiAgICB1c2VyRXZlbnRzOiBVc2VyRXZlbnRbXTtcbiAgICBzdWdnZXN0aW9uczogU3VnZ2VzdGlvbltdO1xuICAgIG1lc3NhZ2VzOiBNZXNzYWdlW11bXTtcbiAgfT4gPT4ge1xuICAgIGxldCBkYXRhOiBWMUdldFNlc3Npb25NZXNzYWdlczIwMFJlc3BvbnNlID0ge1xuICAgICAgcmVzcG9uc2VzOiBbXSxcbiAgICAgIHN1Z2dlc3Rpb25zOiBbXSxcbiAgICAgIHVzZXJfZXZlbnRzOiBbXSxcbiAgICB9O1xuICAgIGNvbnN0IHJlcXVlc3QgPSB7XG4gICAgICBvcmdfaWQ6IG9yZ0lkLFxuICAgICAgY2hhdF9pZDogY2hhdElkLFxuICAgICAgdXNlcl9pZDogdXNlcklkLFxuICAgIH07XG4gICAgdHJ5IHtcbiAgICAgIGRhdGEgPVxuICAgICAgICBhd2FpdCBDb21tZXJjZUFwaUNsaWVudC5nZXRJbnN0YW5jZSgpLmRlZmF1bHRBcGkudjFHZXRTZXNzaW9uTWVzc2FnZXMoXG4gICAgICAgICAgcmVxdWVzdFxuICAgICAgICApO1xuICAgIH0gY2F0Y2ggKGVycm9yOiB1bmtub3duKSB7XG4gICAgICBhd2FpdCB0aHJvd1Nlc3Npb25SZXN0YXJ0UmVxdWlyZWRJZihcbiAgICAgICAgXCJGYWlsZWQgdG8gZ2V0IGNoYXQgcmVzcG9uc2VzXCIsXG4gICAgICAgIGVycm9yXG4gICAgICApO1xuICAgIH1cblxuICAgIGNvbnN0IHJlc3BvbnNlczogUmVzcG9uc2VbXVtdID0gZGF0YT8ucmVzcG9uc2VzPy5tYXAoKHR1cm4pID0+XG4gICAgICB0dXJuXG4gICAgICAgIC5tYXAoKHJlc3BvbnNlKSA9PiB2YWxpZGF0ZVJlc3BvbnNlKHJlc3BvbnNlKSlcbiAgICAgICAgLmZpbHRlcigocmVzcG9uc2UpOiByZXNwb25zZSBpcyBSZXNwb25zZSA9PiByZXNwb25zZSAhPSBudWxsKVxuICAgICk7XG5cbiAgICBjb25zdCBzdWdnZXN0aW9uczogU3VnZ2VzdGlvbltdID0gZGF0YT8uc3VnZ2VzdGlvbnNcbiAgICAgIC5tYXAoKHN1Z2dlc3Rpb24pID0+IHZhbGlkYXRlU3VnZ2VzdGlvbihzdWdnZXN0aW9uKSlcbiAgICAgIC5maWx0ZXIoKHN1Z2dlc3Rpb24pOiBzdWdnZXN0aW9uIGlzIFN1Z2dlc3Rpb24gPT4gc3VnZ2VzdGlvbiAhPSBudWxsKTtcblxuICAgIGNvbnN0IHVzZXJFdmVudHM6IFVzZXJFdmVudFtdID0gZGF0YT8udXNlcl9ldmVudHNcbiAgICAgIC5tYXAoKGV2ZW50KSA9PiB2YWxpZGF0ZVVzZXJFdmVudChldmVudCkpXG4gICAgICAuZmlsdGVyKChldmVudCk6IGV2ZW50IGlzIFVzZXJFdmVudCA9PiBldmVudCAhPSBudWxsKTtcblxuICAgIC8vIGlmIGEgZm9ybSBoYXMgYWxyZWFkeSBiZWVuIHN1Ym1pdHRlZCwgZG9uJ3Qgc2hvdyBpdCBpbiB0aGUgY2hhdCBoaXN0b3J5XG4gICAgY29uc3QgZm9ybVN1Ym1pdHRlZFVzZXJFdmVudHNGb3JtSWRzID0gdXNlckV2ZW50c1xuICAgICAgLmZpbHRlcigoZXZlbnQpID0+IGV2ZW50LmNhdGVnb3J5ID09PSBVc2VyRXZlbnRDYXRlZ29yeS5Gb3JtU3VibWl0dGVkKVxuICAgICAgLm1hcCgoZXZlbnQpID0+IGV2ZW50LmF0dHJpYnV0ZXMuZm9ybVJlc3BvbnNlSWQpO1xuXG4gICAgY29uc3QgYXNzaXN0YW50TWVzc2FnZXM6IE1lc3NhZ2VbXVtdID0gcmVzcG9uc2VzXG4gICAgICAubWFwKCh0dXJuKSA9PlxuICAgICAgICB0dXJuXG4gICAgICAgICAgLmZpbHRlcihcbiAgICAgICAgICAgIChyZXNwb25zZSkgPT5cbiAgICAgICAgICAgICAgIShcbiAgICAgICAgICAgICAgICByZXNwb25zZS5jYXRlZ29yeSA9PT0gUmVzcG9uc2VDYXRlZ29yeS5Gb3JtICYmXG4gICAgICAgICAgICAgICAgZm9ybVN1Ym1pdHRlZFVzZXJFdmVudHNGb3JtSWRzLmluY2x1ZGVzKHJlc3BvbnNlLmlkKVxuICAgICAgICAgICAgICApXG4gICAgICAgICAgKVxuICAgICAgICAgIC5tYXAoKHJlc3BvbnNlKSA9PiBtZXNzYWdlRnJvbVJlc3BvbnNlKHJlc3BvbnNlKSlcbiAgICAgICAgICAuZmlsdGVyKChtZXNzYWdlKTogbWVzc2FnZSBpcyBNZXNzYWdlID0+IG1lc3NhZ2UgIT0gbnVsbClcbiAgICAgIClcbiAgICAgIC5maWx0ZXIoKHR1cm4pID0+IHR1cm4ubGVuZ3RoID4gMCk7XG5cbiAgICBjb25zdCB1c2VyTWVzc2FnZXM6IE1lc3NhZ2VbXVtdID0gdXNlckV2ZW50c1xuICAgICAgLm1hcCgoZXZlbnQpID0+IHtcbiAgICAgICAgaWYgKFxuICAgICAgICAgIFtVc2VyRXZlbnRDYXRlZ29yeS5RdWVyeVR5cGVkLCBVc2VyRXZlbnRDYXRlZ29yeS5TZWFyY2hdLmluY2x1ZGVzKFxuICAgICAgICAgICAgZXZlbnQuY2F0ZWdvcnlcbiAgICAgICAgICApXG4gICAgICAgICkge1xuICAgICAgICAgIHJldHVybiBbbWVzc2FnZUZyb21RdWVyeUV2ZW50KGV2ZW50KV07XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoZXZlbnQuY2F0ZWdvcnkgPT09IFVzZXJFdmVudENhdGVnb3J5LlN1Z2dlc3Rpb25DbGlja2VkKSB7XG4gICAgICAgICAgcmV0dXJuIFttZXNzYWdlRnJvbVN1Z2dlc3Rpb25FdmVudChldmVudCwgc3VnZ2VzdGlvbnMpXTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChldmVudC5jYXRlZ29yeSA9PT0gVXNlckV2ZW50Q2F0ZWdvcnkuRm9ybVN1Ym1pdHRlZCkge1xuICAgICAgICAgIGNvbnN0IGZvcm1SZXNwb25zZSA9IHJlc3BvbnNlc1xuICAgICAgICAgICAgLmZsYXQoKVxuICAgICAgICAgICAgLmZpbmQoXG4gICAgICAgICAgICAgIChyZXNwb25zZSkgPT5cbiAgICAgICAgICAgICAgICByZXNwb25zZS5pZCA9PT0gZXZlbnQuYXR0cmlidXRlcy5mb3JtUmVzcG9uc2VJZCAmJlxuICAgICAgICAgICAgICAgIGV2ZW50LmF0dHJpYnV0ZXMuZm9ybVR5cGUgIT09IEZvcm1UeXBlLkVzY2FsYXRpb25cbiAgICAgICAgICAgICk7XG5cbiAgICAgICAgICBpZiAoZm9ybVJlc3BvbnNlICYmIGZvcm1SZXNwb25zZS5jYXRlZ29yeSA9PT0gUmVzcG9uc2VDYXRlZ29yeS5Gb3JtKSB7XG4gICAgICAgICAgICByZXR1cm4gW1xuICAgICAgICAgICAgICBtZXNzYWdlRnJvbUZvcm1TdWJtaXR0ZWRFdmVudChldmVudCwgZm9ybVJlc3BvbnNlLmF0dHJpYnV0ZXMpLFxuICAgICAgICAgICAgXTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gW107XG4gICAgICB9KVxuICAgICAgLmZpbHRlcigobWVzc2FnZSk6IG1lc3NhZ2UgaXMgTWVzc2FnZVtdID0+IG1lc3NhZ2UubGVuZ3RoID4gMCk7XG5cbiAgICAvLyBTb3J0IHRoZSBtZXNzYWdlcyBjaHJvbm9sb2dpY2FsbHkgdG8gcmVjb25zdHJ1Y3QgdGhlIGNoYXQgaGlzdG9yeVxuICAgIGNvbnN0IHNvcnRlZE1lc3NhZ2VzID0gWy4uLmFzc2lzdGFudE1lc3NhZ2VzLCAuLi51c2VyTWVzc2FnZXNdLnNvcnQoXG4gICAgICAoYSwgYikgPT5cbiAgICAgICAgbmV3IERhdGUoYVswXS5jcmVhdGVkQXQpLmdldFRpbWUoKSAtIG5ldyBEYXRlKGJbMF0uY3JlYXRlZEF0KS5nZXRUaW1lKClcbiAgICApO1xuXG4gICAgcmV0dXJuIHsgcmVzcG9uc2VzLCB1c2VyRXZlbnRzLCBzdWdnZXN0aW9ucywgbWVzc2FnZXM6IHNvcnRlZE1lc3NhZ2VzIH07XG4gIH07XG5cbiAgLyoqXG4gICAqXG4gICAqIEBwYXJhbSBwYXlsb2FkXG4gICAqIEByZXR1cm5zXG4gICAqL1xuICBzdGF0aWMgaXNTdXBwb3J0ZWRFdmVudCA9IGFzeW5jIChcbiAgICBwYXlsb2FkOiBTdXBwb3J0ZWRFdmVudFJlcXVlc3RcbiAgKTogUHJvbWlzZTxTdXBwb3J0ZWRFdmVudD4gPT4ge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCByYXdSZXNwb25zZSA9XG4gICAgICAgIGF3YWl0IENvbW1lcmNlQXBpQ2xpZW50LmdldEluc3RhbmNlKCkuaW5mZXJlbmNlQXBpLnYxU3VwcG9ydGVkRXZlbnRQb3N0UmF3KFxuICAgICAgICAgIHtcbiAgICAgICAgICAgIFN1cHBvcnRlZEV2ZW50UmVxdWVzdDpcbiAgICAgICAgICAgICAgY29yZVN1cHBvcnRlZEV2ZW50UmVxdWVzdFRvQXBpUmVxdWVzdChwYXlsb2FkKSxcbiAgICAgICAgICB9XG4gICAgICAgICk7XG5cbiAgICAgIC8vIEdldCB0aGUgYWN0dWFsIEhUVFAgcmVzcG9uc2UgSlNPTlxuICAgICAgY29uc3QgaHR0cFJlc3BvbnNlVGV4dCA9IGF3YWl0IHJhd1Jlc3BvbnNlLnJhdy50ZXh0KCk7XG4gICAgICBjb25zdCBodHRwUmVzcG9uc2VKc29uID0gSlNPTi5wYXJzZShodHRwUmVzcG9uc2VUZXh0KTtcblxuICAgICAgcmV0dXJuIHtcbiAgICAgICAgLi4uaHR0cFJlc3BvbnNlSnNvbixcbiAgICAgICAgbnVtYmVyT2ZSZXZpZXdzOiBodHRwUmVzcG9uc2VKc29uLm51bV9vZl9yZXZpZXdzLFxuICAgICAgICBtZXJjaGFudF90YWdzOiBodHRwUmVzcG9uc2VKc29uLm1lcmNoYW50X3RhZ3MgfHwgW10sXG4gICAgICB9O1xuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgTG9nZ2VyLmxvZ0Vycm9yKFwiRmFpbGVkIHRvIGdldCByZXNwb25zZSBmb3IgdjFTdXBwb3J0ZWRFdmVudFBvc3RcIiwge1xuICAgICAgICBlcnIsXG4gICAgICB9KTtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIHN1cHBvcnRlZDogZmFsc2UsXG4gICAgICAgIHJlYWR5OiBmYWxzZSxcbiAgICAgICAgY2F0ZWdvcnk6IHVuZGVmaW5lZCxcbiAgICAgICAgY29sbGVjdGlvbnM6IFtdLFxuICAgICAgICBudW1iZXJPZlJldmlld3M6IHVuZGVmaW5lZCxcbiAgICAgICAgdG9wX2NhdGVnb3J5OiB1bmRlZmluZWQsXG4gICAgICAgIG1lcmNoYW50X3RhZ3M6IFtdLFxuICAgICAgfTtcbiAgICB9XG4gIH07XG5cbiAgc3RhdGljIGlkZW50aWZ5VXNlciA9IGFzeW5jIChcbiAgICBzcGlmZnlVc2VySWQ6IHN0cmluZyxcbiAgICBtZXJjaGFudFVzZXJJZDogc3RyaW5nLFxuICAgIHVhRGV0YWlsczogQ2xpZW50RGV0YWlsc1xuICApOiBQcm9taXNlPHZvaWQ+ID0+IHtcbiAgICB0cnkge1xuICAgICAgYXdhaXQgQ29tbWVyY2VBcGlDbGllbnQuZ2V0SW5zdGFuY2UoKS5kZWZhdWx0QXBpLnYxQW5hbHl0aWNzSWRlbnRpZnlQb3N0KHtcbiAgICAgICAgQW5hbHl0aWNzSWRlbnRpZnlSZXF1ZXN0OiB7XG4gICAgICAgICAgdXNlcl9pZDogc3BpZmZ5VXNlcklkLFxuICAgICAgICAgIG9zX25hbWU6IHVhRGV0YWlscy5vcyxcbiAgICAgICAgICBvc192ZXJzaW9uOiB1YURldGFpbHMub3NWZXJzaW9uLFxuICAgICAgICAgIHBsYXRmb3JtOiB1YURldGFpbHMub3MsXG4gICAgICAgICAgZGV2aWNlX2lkOiB1YURldGFpbHMuZGV2aWNlTW9kZWwsXG4gICAgICAgICAgZGV2aWNlX2JyYW5kOiB1YURldGFpbHMuZGV2aWNlQnJhbmQsXG4gICAgICAgICAgZGV2aWNlX21hbnVmYWN0dXJlcjogdWFEZXRhaWxzLmRldmljZU1hbnVmYWN0dXJlcixcbiAgICAgICAgICBkZXZpY2VfbW9kZWw6IHVhRGV0YWlscy5kZXZpY2VNb2RlbCxcbiAgICAgICAgICB1c2VyX3Byb3BlcnRpZXM6IHtcbiAgICAgICAgICAgIGNkcF91c2VyX2lkOiBtZXJjaGFudFVzZXJJZCxcbiAgICAgICAgICAgIGJyb3dzZXI6IHVhRGV0YWlscy5icm93c2VyLFxuICAgICAgICAgICAgYnJvd3Nlcl92ZXJzaW9uOiB1YURldGFpbHMuYnJvd3NlclZlcnNpb24sXG4gICAgICAgICAgICB1c2VyX2FnZW50OiB1YURldGFpbHMudXNlckFnZW50LFxuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICB9KTtcbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIExvZ2dlci5sb2dFcnJvcihcIkZhaWxlZCB0byBpZGVudGlmeSB1c2VyXCIsIGVycik7XG4gICAgfVxuICB9O1xuXG4gIHByaXZhdGUgc3RhdGljIG1hcENvbnRleHRTb3VyY2VUb1YxT3JnQ29uZmlnR2V0U291cmNlID0gKFxuICAgIHNvdXJjZTogQ29udGV4dFNvdXJjZUVudW0gfCB1bmRlZmluZWRcbiAgKTogVjFPcmdDb25maWdHZXRTb3VyY2VFbnVtIHwgdW5kZWZpbmVkID0+IHtcbiAgICBpZiAoc291cmNlID09PSB1bmRlZmluZWQpIHJldHVybiB1bmRlZmluZWQ7XG4gICAgc3dpdGNoIChzb3VyY2UpIHtcbiAgICAgIGNhc2UgQ29udGV4dFNvdXJjZUVudW0uRm9yazpcbiAgICAgICAgcmV0dXJuIFYxT3JnQ29uZmlnR2V0U291cmNlRW51bS5Gb3JrO1xuICAgICAgY2FzZSBDb250ZXh0U291cmNlRW51bS5QbGF5Z3JvdW5kOlxuICAgICAgICByZXR1cm4gVjFPcmdDb25maWdHZXRTb3VyY2VFbnVtLlBsYXlncm91bmQ7XG4gICAgICBjYXNlIENvbnRleHRTb3VyY2VFbnVtLkFwcDpcbiAgICAgICAgcmV0dXJuIFYxT3JnQ29uZmlnR2V0U291cmNlRW51bS5BcHA7XG4gICAgICBjYXNlIENvbnRleHRTb3VyY2VFbnVtLlRlc3Q6XG4gICAgICAgIHJldHVybiBWMU9yZ0NvbmZpZ0dldFNvdXJjZUVudW0uVGVzdDtcbiAgICAgIGRlZmF1bHQ6IHtcbiAgICAgICAgLy8gVGhpcyBlbnN1cmVzIHRoYXQgaWYgbmV3IHZhbHVlcyBhcmUgYWRkZWQgdG8gQ29udGV4dFNvdXJjZUVudW0sIHdlIGNhdGNoIGl0XG4gICAgICAgIGNvbnN0IGV4aGF1c3RpdmVDaGVjazogbmV2ZXIgPSBzb3VyY2U7XG4gICAgICAgIHJldHVybiBleGhhdXN0aXZlQ2hlY2s7XG4gICAgICB9XG4gICAgfVxuICB9O1xuXG4gIHN0YXRpYyBnZXRPcmdDb25maWcgPSBhc3luYyAoXG4gICAgdXNlcl9pZDogc3RyaW5nXG4gICk6IFByb21pc2U8T3JnQ29uZmlnIHwgdW5kZWZpbmVkPiA9PiB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IGF0b21TdG9yZSA9IGdldEF0b21TdG9yZSgpO1xuICAgICAgY29uc3QgcmVhY3RBcHBOYW1lID0gYXRvbVN0b3JlLmdldChyZWFjdEFwcE5hbWVBdG9tKTtcbiAgICAgIGNvbnN0IGNvbnRleHRTb3VyY2UgPSBhdG9tU3RvcmUuZ2V0KGNvbnRleHRTb3VyY2VBdG9tKTtcbiAgICAgIGNvbnN0IGZlYXR1cmVGbGFnU2VydmljZSA9IGF0b21TdG9yZS5nZXQoZmVhdHVyZUZsYWdTZXJ2aWNlQXRvbSk7IC8vIEdldCBmZWF0dXJlRmxhZ1NlcnZpY2VcbiAgICAgIGNvbnN0IHJlcXVlc3Q6IFYxT3JnQ29uZmlnR2V0UmVxdWVzdCA9IHtcbiAgICAgICAgbmFtZXNwYWNlOiByZWFjdEFwcE5hbWUsXG4gICAgICAgIHVzZXJfaWQsXG4gICAgICAgIHNvdXJjZTogdGhpcy5tYXBDb250ZXh0U291cmNlVG9WMU9yZ0NvbmZpZ0dldFNvdXJjZShjb250ZXh0U291cmNlKSxcbiAgICAgICAgaW5jbHVkZV9leHBlcmltZW50czogT2JqZWN0LnZhbHVlcyhQcm9kdWN0RXhwZXJpbWVudCksXG4gICAgICAgIGluY2x1ZGVfZmVhdHVyZV9nYXRlczogT2JqZWN0LmVudHJpZXMoXG4gICAgICAgICAgZmVhdHVyZUZsYWdTZXJ2aWNlPy5mZWF0dXJlRmxhZ1NlcnZpY2U/LmdldEZlYXR1cmVGbGFncygpIHx8IHt9XG4gICAgICAgIClcbiAgICAgICAgICAuZmlsdGVyKChbLCBpc0VuYWJsZWRdKSA9PiBpc0VuYWJsZWQpXG4gICAgICAgICAgLm1hcCgoW2ZlYXR1cmVHYXRlTmFtZV0pID0+IGZlYXR1cmVHYXRlTmFtZSksIC8vIFVzZSBmZWF0dXJlRmxhZ1NlcnZpY2VcbiAgICAgIH07XG4gICAgICBjb25zdCByZXNwb25zZSA9XG4gICAgICAgIGF3YWl0IENvbW1lcmNlQXBpQ2xpZW50LmdldEluc3RhbmNlKCkuZGVmYXVsdEFwaS52MU9yZ0NvbmZpZ0dldChcbiAgICAgICAgICByZXF1ZXN0XG4gICAgICAgICk7XG5cbiAgICAgIHJldHVybiB2YWxpZGF0ZU9yZ0NvbmZpZ1Jlc3VsdHMocmVzcG9uc2UpO1xuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgTG9nZ2VyLmxvZ0Vycm9yKGBGYWlsZWQgdG8gZ2V0IG9yZyBjb25maWdgLCBlcnIsIHsgZXJyIH0pO1xuICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9XG4gIH07XG5cbiAgc3RhdGljIGFkZE5vdGVUb0xhdGVzdENvbnZlcnNhdGlvbiA9IGFzeW5jIChcbiAgICBzcGlmZnlVc2VySWQ6IHN0cmluZyxcbiAgICBlbWFpbDogc3RyaW5nLFxuICAgIGN1c3RvbWVyU2VydmljZVByb3ZpZGVyOiBDdXN0b21lclNlcnZpY2VQcm92aWRlclxuICApID0+IHtcbiAgICBMb2dnZXIubG9nSW5mbyhcbiAgICAgIGBhZGROb3RlVG9MYXRlc3RDb252ZXJzYXRpb24gLSB1c2VyX2lkPSR7c3BpZmZ5VXNlcklkfSBlbWFpbD0ke2VtYWlsfSBjdXN0b21lcl9zZXJ2aWNlX3Byb3ZpZGVyPSR7Y3VzdG9tZXJTZXJ2aWNlUHJvdmlkZXJ9YFxuICAgICk7XG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IENvbW1lcmNlQXBpQ2xpZW50LmdldEluc3RhbmNlKCkuY3VzdG9tZXJTZXJ2aWNlQXBpLnYxQ3VzdHNlcnZpY2VBZGROb3RlVG9MYXRlc3RDb252ZXJzYXRpb25Qb3N0KFxuICAgICAgICB7XG4gICAgICAgICAgQWRkTm90ZVRvTGF0ZXN0Q29udmVyc2F0aW9uUmVxdWVzdDoge1xuICAgICAgICAgICAgc3BpZmZ5X3VzZXJfaWQ6IHNwaWZmeVVzZXJJZCxcbiAgICAgICAgICAgIGVtYWlsLFxuICAgICAgICAgICAgY3VzdG9tZXJfc2VydmljZV9wcm92aWRlcjogY3VzdG9tZXJTZXJ2aWNlUHJvdmlkZXIsXG4gICAgICAgICAgfSxcbiAgICAgICAgfVxuICAgICAgKTtcbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIExvZ2dlci5sb2dFcnJvcihcIkZhaWxlZCB0byBhZGQgbm90ZSB0byBsYXRlc3QgY29udmVyc2F0aW9uXCIsIHsgZXJyIH0pO1xuICAgIH1cbiAgfTtcblxuICBzdGF0aWMgZ2V0Q3VzdG9tZXJTZXJ2aWNlQXBpID0gKCkgPT5cbiAgICBDb21tZXJjZUFwaUNsaWVudC5nZXRJbnN0YW5jZSgpLmN1c3RvbWVyU2VydmljZUFwaTtcbn1cblxuZXhwb3J0IGRlZmF1bHQgQ29tbWVyY2VBcGlDbGllbnQ7XG4iLCJpbXBvcnQgeyB1c2VTdGF0ZSwgdXNlQ2FsbGJhY2sgfSBmcm9tIFwicmVhY3RcIjtcbmltcG9ydCB7XG4gIFNwaWZmeU1ldHJpY3NFdmVudE5hbWUsXG4gIHVzZUFtcGxpdHVkZSxcbn0gZnJvbSBcInNyYy9jb250ZXh0cy9hbXBsaXR1ZGVDb250ZXh0XCI7XG5cbmV4cG9ydCBjb25zdCB1c2VBbXBsaXR1ZGVUcmFja2luZyA9ICgpID0+IHtcbiAgY29uc3QgeyB0cmFja0V2ZW50LCBpc1JlYWR5IH0gPSB1c2VBbXBsaXR1ZGUoKTtcbiAgY29uc3QgW2xvYWRpbmcsIHNldExvYWRpbmddID0gdXNlU3RhdGUoZmFsc2UpO1xuICBjb25zdCBbZXJyb3IsIHNldEVycm9yXSA9IHVzZVN0YXRlPEVycm9yIHwgbnVsbD4obnVsbCk7XG5cbiAgY29uc3QgdHJhY2sgPSB1c2VDYWxsYmFjayhcbiAgICBhc3luYyAoXG4gICAgICBldmVudE5hbWU6IFNwaWZmeU1ldHJpY3NFdmVudE5hbWUsXG4gICAgICBldmVudFByb3BzPzogUmVjb3JkPHN0cmluZywgdW5rbm93bj5cbiAgICApID0+IHtcbiAgICAgIGlmICghaXNSZWFkeSkgcmV0dXJuO1xuXG4gICAgICBzZXRMb2FkaW5nKHRydWUpO1xuICAgICAgc2V0RXJyb3IobnVsbCk7XG5cbiAgICAgIHRyeSB7XG4gICAgICAgIGF3YWl0IHRyYWNrRXZlbnQoeyBldmVudE5hbWUsIGV2ZW50UHJvcHMgfSk7XG4gICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgc2V0RXJyb3IoZXJyIGluc3RhbmNlb2YgRXJyb3IgPyBlcnIgOiBuZXcgRXJyb3IoXCJUcmFja2luZyBmYWlsZWRcIikpO1xuICAgICAgICB0aHJvdyBlcnI7XG4gICAgICB9IGZpbmFsbHkge1xuICAgICAgICBzZXRMb2FkaW5nKGZhbHNlKTtcbiAgICAgIH1cbiAgICB9LFxuICAgIFt0cmFja0V2ZW50LCBpc1JlYWR5XVxuICApO1xuXG4gIHJldHVybiB7IHRyYWNrLCBsb2FkaW5nLCBlcnJvciwgaXNSZWFkeSB9O1xufTtcbiIsImltcG9ydCB7IHVzZUVmZmVjdCB9IGZyb20gXCJyZWFjdFwiO1xuXG5leHBvcnQgY29uc3QgdXNlQmxvY2tCYWNrQnV0dG9uID0gKGVuYWJsZWQ6IGJvb2xlYW4sIGNhbGxiYWNrOiAoKSA9PiB2b2lkKSA9PiB7XG5cbiAgdXNlRWZmZWN0KCgpID0+IHtcbiAgICBpZiAoZW5hYmxlZCAmJiB3aW5kb3cpIHtcblxuICAgICAgaWYgKHdpbmRvdy5oaXN0b3J5LnNjcm9sbFJlc3RvcmF0aW9uKSB7XG4gICAgICAgIHdpbmRvdy5oaXN0b3J5LnNjcm9sbFJlc3RvcmF0aW9uID0gXCJtYW51YWxcIlxuICAgICAgfVxuXG4gICAgICB3aW5kb3cuaGlzdG9yeS5wdXNoU3RhdGUobnVsbCwgZG9jdW1lbnQudGl0bGUsIHdpbmRvdy5sb2NhdGlvbi5ocmVmKTtcbiAgICAgIHdpbmRvdy5vbnBvcHN0YXRlID0gKGUpID0+IHtcbiAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICB3aW5kb3cuaGlzdG9yeS5wdXNoU3RhdGUobnVsbCwgZG9jdW1lbnQudGl0bGUsIHdpbmRvdy5sb2NhdGlvbi5ocmVmKTtcbiAgICAgICAgY2FsbGJhY2s/LigpXG4gICAgICB9O1xuICAgIH1cblxuICAgIHJldHVybiAoKSA9PiB7XG4gICAgICBpZiAoZW5hYmxlZCAmJiB3aW5kb3cpIHtcbiAgICAgICAgd2luZG93Lmhpc3RvcnkuYmFjaygpXG4gICAgICAgIHdpbmRvdy5vbnBvcHN0YXRlID0gbnVsbFxuICAgICAgICB3aW5kb3cuaGlzdG9yeS5zY3JvbGxSZXN0b3JhdGlvbiA9IFwiYXV0b1wiO1xuICAgICAgfVxuICAgIH1cbiAgfSwgW2VuYWJsZWRdKVxuXG59IiwiaW1wb3J0IHsgdXNlQ2RuIH0gZnJvbSBcIi4uL2NvbnRleHRzL2NkbkNvbnRleHRcIjtcblxuZXhwb3J0IGNvbnN0IHVzZUNkblVybCA9ICgpID0+IHtcbiAgY29uc3QgeyBjZG5VcmwgfSA9IHVzZUNkbigpO1xuICByZXR1cm4gY2RuVXJsO1xufTtcblxuZXhwb3J0IGNvbnN0IHVzZUNkbkJhc2VQYXRoID0gKCkgPT4ge1xuICBjb25zdCB7IGdldENkbkJhc2VQYXRoIH0gPSB1c2VDZG4oKTtcbiAgcmV0dXJuIGdldENkbkJhc2VQYXRoKCk7XG59O1xuXG5leHBvcnQgY29uc3QgdXNlQXNzZXRVcmwgPSAoYXNzZXROYW1lOiBzdHJpbmcsIG9yZ1Nob3J0TmFtZTogc3RyaW5nKSA9PiB7XG4gIGNvbnN0IHsgZ2V0QXNzZXRVUkwgfSA9IHVzZUNkbigpO1xuICByZXR1cm4gZ2V0QXNzZXRVUkwoYXNzZXROYW1lLCBvcmdTaG9ydE5hbWUpO1xufTtcbiIsImltcG9ydCB7IHVzZUF0b21WYWx1ZSwgdXNlU2V0QXRvbSB9IGZyb20gXCJqb3RhaVwiO1xuaW1wb3J0IHsgQ2hhdEVsZW1lbnREaXNwbGF5TG9jYXRpb24gfSBmcm9tIFwic3JjL2FwcGxpY2F0aW9uL21vZGVscy9jaGF0RWxlbWVudERpc3BsYXlMb2NhdGlvblwiO1xuaW1wb3J0IHsgY2hhdEF0b20sIGNoYXRPblRvZ2dsZUF0b20gfSBmcm9tIFwic3JjL2F0b21zL2NoYXRcIjtcbmltcG9ydCB7XG4gIFNwaWZmeU1ldHJpY3NFdmVudE5hbWUsXG4gIHVzZUFtcGxpdHVkZSxcbn0gZnJvbSBcInNyYy9jb250ZXh0cy9hbXBsaXR1ZGVDb250ZXh0XCI7XG5cbmV4cG9ydCBjb25zdCB1c2VDaGF0VG9nZ2xlID0gKCkgPT4ge1xuICBjb25zdCBvblRvZ2dsZSA9IHVzZVNldEF0b20oY2hhdE9uVG9nZ2xlQXRvbSk7XG4gIGNvbnN0IHsgaXNPcGVuIH0gPSB1c2VBdG9tVmFsdWUoY2hhdEF0b20pO1xuICBjb25zdCB7IHRyYWNrRXZlbnQgfSA9IHVzZUFtcGxpdHVkZSgpO1xuXG4gIGNvbnN0IHRvZ2dsZSA9IChcbiAgICB0cmlnZ2VyTG9jYXRpb246IENoYXRFbGVtZW50RGlzcGxheUxvY2F0aW9uLFxuICAgIHRyaWdnZXJJZD86IHN0cmluZ1xuICApID0+IHtcbiAgICBpZiAoIWlzT3Blbikge1xuICAgICAgdHJhY2tFdmVudCh7XG4gICAgICAgIGV2ZW50TmFtZTogU3BpZmZ5TWV0cmljc0V2ZW50TmFtZS5DaGF0Q29tcG9uZW50RXhwYW5kZWQsXG4gICAgICAgIGV2ZW50UHJvcHM6IHtcbiAgICAgICAgICBtZXNzYWdlX21ldGFkYXRhOiB7XG4gICAgICAgICAgICB0cmlnZ2VyX2xvY2F0aW9uOiB0cmlnZ2VyTG9jYXRpb24sXG4gICAgICAgICAgICB0cmlnZ2VyX2lkOiB0cmlnZ2VySWQsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgIH0pO1xuICAgIH0gZWxzZSB7XG4gICAgICB0cmFja0V2ZW50KHtcbiAgICAgICAgZXZlbnROYW1lOiBTcGlmZnlNZXRyaWNzRXZlbnROYW1lLkNoYXRDb21wb25lbnRDb2xsYXBzZWQsXG4gICAgICAgIGV2ZW50UHJvcHM6IHtcbiAgICAgICAgICBtZXNzYWdlX21ldGFkYXRhOiB7XG4gICAgICAgICAgICB0cmlnZ2VyX2xvY2F0aW9uOiB0cmlnZ2VyTG9jYXRpb24sXG4gICAgICAgICAgICB0cmlnZ2VyX2lkOiB0cmlnZ2VySWQsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIG9uVG9nZ2xlKCk7XG4gIH07XG5cbiAgY29uc3Qgb3BlbkNoYXQgPSAoXG4gICAgdHJpZ2dlckxvY2F0aW9uOiBDaGF0RWxlbWVudERpc3BsYXlMb2NhdGlvbixcbiAgICB0cmlnZ2VySWQ/OiBzdHJpbmdcbiAgKSA9PiB7XG4gICAgaWYgKCFpc09wZW4pIHtcbiAgICAgIHRvZ2dsZSh0cmlnZ2VyTG9jYXRpb24sIHRyaWdnZXJJZCk7XG4gICAgfVxuICB9O1xuXG4gIGNvbnN0IGNsb3NlQ2hhdCA9IChcbiAgICB0cmlnZ2VyTG9jYXRpb246IENoYXRFbGVtZW50RGlzcGxheUxvY2F0aW9uLFxuICAgIHRyaWdnZXJJZD86IHN0cmluZ1xuICApID0+IHtcbiAgICBpZiAoaXNPcGVuKSB7XG4gICAgICB0b2dnbGUodHJpZ2dlckxvY2F0aW9uLCB0cmlnZ2VySWQpO1xuICAgIH1cbiAgfTtcblxuICByZXR1cm4ge1xuICAgIHRvZ2dsZSxcbiAgICBpc09wZW4sXG4gICAgb3BlbkNoYXQsXG4gICAgY2xvc2VDaGF0LFxuICB9O1xufTtcbiIsImltcG9ydCB7IHVzZVNldEF0b20gfSBmcm9tIFwiam90YWlcIjtcbmltcG9ydCB7IGNoYXRPblRvZ2dsZUF0b20gfSBmcm9tIFwic3JjL2F0b21zL2NoYXQvY2hhdFN0YXRlXCI7XG5pbXBvcnQgeyBDaGF0RWxlbWVudERpc3BsYXlMb2NhdGlvbiB9IGZyb20gXCJzcmMvYXBwbGljYXRpb24vbW9kZWxzL2NoYXRFbGVtZW50RGlzcGxheUxvY2F0aW9uXCI7XG5pbXBvcnQgeyB1c2VBbXBsaXR1ZGVUcmFja2luZyB9IGZyb20gXCIuL3VzZUFtcGxpdHVkZU9wZXJhdGlvbnNcIjtcblxuZXhwb3J0IGNvbnN0IHVzZUNoYXRUb2dnbGVBbmFseXRpY3MgPSAoKSA9PiB7XG4gIGNvbnN0IHNldENoYXRPblRvZ2dsZSA9IHVzZVNldEF0b20oY2hhdE9uVG9nZ2xlQXRvbSk7XG4gIGNvbnN0IHsgdHJhY2sgfSA9IHVzZUFtcGxpdHVkZVRyYWNraW5nKCk7XG5cbiAgY29uc3QgdG9nZ2xlQ2hhdCA9ICh0cmlnZ2VyTG9jYXRpb24/OiBDaGF0RWxlbWVudERpc3BsYXlMb2NhdGlvbikgPT4ge1xuICAgIHNldENoYXRPblRvZ2dsZSh0cmlnZ2VyTG9jYXRpb24sIHRyYWNrKTtcbiAgfTtcblxuICByZXR1cm4geyB0b2dnbGVDaGF0IH07XG59O1xuIiwiaW1wb3J0IExvZ2dlciBmcm9tICdzcmMvYXBwbGljYXRpb24vbG9nZ2luZy9sb2dnZXInO1xuaW1wb3J0IHsgdXNlQ2FsbGJhY2sgfSBmcm9tICdyZWFjdCc7XG5cbi8qKlxuICogSG9vayB0byBjYWxsIHRoZSBgY2xpY2tgIG1ldGhvZCBvZiB0aGUgbWVyY2hhbnQncyBjdXN0b21lciBzdXBwb3J0IGNoYXQgd2lkZ2V0LlxuICpcbiAqIEBwYXJhbSBvblN3aXRjaFRvQWdlbnQgYSBmdW5jdGlvbiB0byBvdmVycmlkZSB0aGUgZnVuY3Rpb24gcmV0dXJuZWQgYnkgdGhlIGhvb2suIFRoaXMgaXMgbWFpbmx5IHRvXG4gKiBwcmVzZXJ2ZSBiYWNrd2FyZCBjb21wYXRpYmlsaXR5IGZvciBtZXJjaGFudHMgbm90IHVzaW5nIEt1c3RvbWVyIGFuZCB3aWxsIGJlIHJlbW92ZWQgd2hlbiBhbGxcbiAqIENTIGludGVncmF0aW9ucyBhcmUgaGFuZGxlZC5cbiAqXG4gKiBAcmV0dXJucyBhIGZ1bmN0aW9uIHRoYXQgc2VhcmNoZXMgZm9yIHRoZSBjdXN0b21lciBzdXBwb3J0IGNoYXQgd2lkZ2V0IGFuZCBjYWxscyB0aGUgYGNsaWNrYCBtZXRob2QuXG4gKi9cbmV4cG9ydCBjb25zdCB1c2VDdXN0b21lclN1cHBvcnRIYW5kb2ZmID0gKG9uU3dpdGNoVG9BZ2VudD86ICgpID0+IHZvaWQpID0+IHtcbiAgLy8gVE9ETyBoYW5kbGUgR29yZ2lhc1xuXG4gIGNvbnN0IG9uS3VzdG9tZXJTd2l0Y2ggPSB1c2VDYWxsYmFjaygoKSA9PiB7XG4gICAgY29uc3Qga3VzdG9tZXJFbGVtZW50ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2t1c3RvbWVyLXVpLXNkay1pZnJhbWUnKTtcblxuICAgIGlmIChrdXN0b21lckVsZW1lbnQgPT0gbnVsbCB8fCAhKGt1c3RvbWVyRWxlbWVudCBpbnN0YW5jZW9mIEhUTUxJRnJhbWVFbGVtZW50KSkge1xuICAgICAgTG9nZ2VyLmxvZ0Vycm9yKCdbc3BpZmZ5LWFpXSBLdXN0b21lciBpRnJhbWUgZWxlbWVudCBub3QgZm91bmQnLCB1bmRlZmluZWQpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IGt1c3RvbWVyQnV0dG9uID0ga3VzdG9tZXJFbGVtZW50LmNvbnRlbnRXaW5kb3c/LmRvY3VtZW50Py5nZXRFbGVtZW50QnlJZCgncm9vdENoYXRJY29uJyk7XG5cbiAgICBpZiAoa3VzdG9tZXJCdXR0b24gPT0gbnVsbCkge1xuICAgICAgTG9nZ2VyLmxvZ0Vycm9yKCdbc3BpZmZ5LWFpXSBLdXN0b21lciBidXR0b24gbm90IGZvdW5kJywgdW5kZWZpbmVkKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBrdXN0b21lckJ1dHRvbi5jbGljaygpO1xuICB9LCBbXSk7XG5cbiAgaWYgKG9uU3dpdGNoVG9BZ2VudCAhPSBudWxsKSB7XG4gICAgcmV0dXJuIHsgb25Td2l0Y2g6IG9uU3dpdGNoVG9BZ2VudCB9O1xuICB9XG5cbiAgcmV0dXJuIHsgb25Td2l0Y2g6IG9uS3VzdG9tZXJTd2l0Y2ggfTtcbn07XG4iLCJpbXBvcnQgeyB1c2VTdGF0ZSwgdXNlRWZmZWN0IH0gZnJvbSAncmVhY3QnO1xuXG5leHBvcnQgZnVuY3Rpb24gdXNlRGVib3VuY2U8VD4odmFsdWU6IFQsIGRlbGF5OiBudW1iZXIpOiBUIHtcbiAgY29uc3QgW2RlYm91bmNlZFZhbHVlLCBzZXREZWJvdW5jZWRWYWx1ZV0gPSB1c2VTdGF0ZTxUPih2YWx1ZSk7XG5cbiAgdXNlRWZmZWN0KCgpID0+IHtcbiAgICBjb25zdCBoYW5kbGVyID0gc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICBzZXREZWJvdW5jZWRWYWx1ZSh2YWx1ZSk7XG4gICAgfSwgZGVsYXkpO1xuXG4gICAgcmV0dXJuICgpID0+IHtcbiAgICAgIGNsZWFyVGltZW91dChoYW5kbGVyKTtcbiAgICB9O1xuICB9LCBbdmFsdWUsIGRlbGF5XSk7XG5cbiAgcmV0dXJuIGRlYm91bmNlZFZhbHVlO1xufVxuIiwiaW1wb3J0IHsgUmVhY3RFbGVtZW50LCB1c2VFZmZlY3QsIHVzZVJlZiwgdXNlU3RhdGUgfSBmcm9tICdyZWFjdCc7XG5pbXBvcnQgeyBET01PYnNlcnZlciB9IGZyb20gJ3NyYy9hcHBsaWNhdGlvbi91dGlscy9kb21PYnNlcnZlcic7XG5pbXBvcnQgeyBFbGVtZW50T2JzZXJ2ZXIgfSBmcm9tICdzcmMvYXBwbGljYXRpb24vdXRpbHMvZWxlbWVudE9ic2VydmVyJztcbmltcG9ydCB7IE1vdXNlRXZlbnRUeXBlcyB9IGZyb20gJ3NyYy9hcHBsaWNhdGlvbi91dGlscy9tb3VzZUV2ZW50VHlwZXMnO1xuaW1wb3J0IHsgTm9kZVNlbGVjdG9yIH0gZnJvbSAnc3JjL2FwcGxpY2F0aW9uL3V0aWxzL25vZGVTZWxlY3Rvcic7XG5cbmV4cG9ydCBpbnRlcmZhY2UgRWxlbWVudE9ic2VydmVyVXRpbGl0eSB7XG4gIG9uQ2hhbmdlOiAoZm46IChlbDogSFRNTEVsZW1lbnQgfCBudWxsKSA9PiB2b2lkKSA9PiB2b2lkO1xuICBvbkFkZDogKGZuOiAoZWw6IEhUTUxFbGVtZW50IHwgbnVsbCkgPT4gdm9pZCkgPT4gdm9pZDtcbiAgb25SZW1vdmU6IChmbjogKGVsOiBIVE1MRWxlbWVudCB8IG51bGwpID0+IHZvaWQpID0+IHZvaWQ7XG4gIG9uQ2xhc3NDaGFuZ2U6IChmbjogKGNsYXNzZXM/OiBET01Ub2tlbkxpc3QpID0+IHZvaWQpID0+IHZvaWQ7XG4gIG9uQ2xhc3NBZGRlZDogKGNsYXNzTmFtZTogc3RyaW5nLCBmbjogKCkgPT4gdm9pZCkgPT4gdm9pZDtcbiAgb25DbGFzc1JlbW92ZWQ6IChjbGFzc05hbWU6IHN0cmluZywgZm46ICgpID0+IHZvaWQpID0+IHZvaWQ7XG4gIG9uQWRkQ2hpbGQ6IChmbjogKG5vZGVzPzogRE9NVG9rZW5MaXN0KSA9PiB2b2lkKSA9PiB2b2lkO1xuICBvblJlbW92ZUNoaWxkOiAoZm46IChub2Rlcz86IERPTVRva2VuTGlzdCkgPT4gdm9pZCkgPT4gdm9pZDtcbiAgb25FdmVudDogPEsgZXh0ZW5kcyBrZXlvZiBIVE1MRWxlbWVudEV2ZW50TWFwPihcbiAgICBldmVudDogSyxcbiAgICBmbjogRXZlbnRMaXN0ZW5lck9yRXZlbnRMaXN0ZW5lck9iamVjdCxcbiAgKSA9PiB2b2lkO1xuICBibG9ja1JlbmRlcmluZzogKCkgPT4gdm9pZDtcbiAgdW5ibG9ja1JlbmRlcmluZzogKCkgPT4gdm9pZDtcbiAgZXhpc3RzOiAoKSA9PiBib29sZWFuO1xuICBpc1JlbmRlcmVkOiAoKSA9PiBib29sZWFuO1xuICByZW5kZXI6IChmbjogKCkgPT4gUmVhY3RFbGVtZW50KSA9PiBSZWFjdEVsZW1lbnQgfCB1bmRlZmluZWQ7XG4gIGZpcmU6IChldmVudDogTW91c2VFdmVudFR5cGVzKSA9PiB2b2lkO1xuICBzaG93OiAoKSA9PiB2b2lkO1xuICBoaWRlOiAoKSA9PiB2b2lkO1xuICBhcHBseVN0eWxlOiAoc3R5bGVzOiBSZWFjdC5DU1NQcm9wZXJ0aWVzKSA9PiB2b2lkO1xuICB0YXJnZXROb2RlOiBIVE1MRWxlbWVudCB8IG51bGw7XG59XG5cbi8qXG4gKiBUaGlzIGhvb2sgZW5hYmxlcyB0aGUgY29ubmVjdGlvbiBiZXR3ZWVuIGEgYE11dGF0aW9uT2JzZXJ2ZXJgIGFuZCBhIFJlYWN0LmpzIGNvbXBvbmVudC5cbiAqIEl0IGFic3RyYWN0cyBhbGwgdGhlIG5lY2Vzc2FyeSB2YWxpZGF0aW9ucyBhbmQgaW1wbGVtZW50YXRpb25zIHRvIG1vZGlmeSBIVE1MIGVsZW1lbnRzLFxuICogbW9uaXRvciB0aGVpciBjaGFuZ2VzLCBhbmQgaW50ZXJhY3Qgd2l0aCB0aGVtLiBUaGUgb25seSByZXF1aXJlZCBpbnB1dCBpcyB0aGUgZWxlbWVudCdzIHNlbGVjdG9yLlxuICpcbiAqIEhvdyB0byB1c2UgaXQ6XG4gKlxuICogTGV0J3MgYXNzdW1lIHdlIHdhbnQgdG8gaW50ZXJhY3Qgd2l0aCB0aGUgZm9sbG93aW5nIGVsZW1lbnQ6XG4gKiBgPGRpdiBpZD1cImF3ZXNvbWUtY29udGVudFwiPjxjb250ZW50IC8+PC9kaXY+YFxuICpcbiAqIFRvIGhvb2sgaW50byB0aGF0IGVsZW1lbnQsIHNpbXBseSBkbyB0aGUgZm9sbG93aW5nOlxuICogYGNvbnN0IGVsZW1lbnQgPSB1c2VFbGVtZW50T2JzZXJ2ZXIoU2VsZWN0b3JGYWN0b3J5LmlkKFwiYXdlc29tZS1jb250ZW50XCIpKWBcbiAqXG4gKiBXaXRoIHRoZSBgRWxlbWVudE9ic2VydmVyYCBpbnN0YW5jZSBpbiBoYW5kLCB3ZSBjYW4gaW50ZXJhY3Qgd2l0aCB0aGUgSFRNTCBlbGVtZW50IHdpdGhvdXQgaGF2aW5nXG4gKiB0byBtYW5hZ2UgaXRzIHByZXNlbmNlIGluIHRoZSBET00uIFRoZSBgb25BZGRgIGFuZCBgb25SZW1vdmVgIGZ1bmN0aW9ucyBjYW4gYmUgdXNlZCB0byBkZXRlcm1pbmVcbiAqIHdoZXRoZXIgdGhlIGVsZW1lbnQgaXMgcHJlc2VudCBpbiB0aGUgRE9NIG9yIG5vdCwgYW5kIHRvIGVuc3VyZSBpbnRlcmFjdGlvbiBvY2N1cnMgb25seSB3aGVuIG5lY2Vzc2FyeS5cbiAqXG4gKiBAcGFyYW0gc2VsZWN0b3JcbiAqIEByZXR1cm5zXG4gKi9cbmV4cG9ydCBjb25zdCB1c2VFbGVtZW50T2JzZXJ2ZXIgPSAoc2VsZWN0b3I6IE5vZGVTZWxlY3Rvcik6IEVsZW1lbnRPYnNlcnZlclV0aWxpdHkgPT4ge1xuICBjb25zdCBJTklUSUFMX1JFTkRFUl9TVEFURSA9IHRydWU7XG4gIGNvbnN0IGVvUmVmID0gdXNlUmVmPEVsZW1lbnRPYnNlcnZlcj4oRE9NT2JzZXJ2ZXIuYWRkKHNlbGVjdG9yKSk7XG4gIGNvbnN0IFtyZW5kZXJCbG9ja2VkLCBzZXRSZW5kZXJCbG9ja2VkXSA9IHVzZVN0YXRlKElOSVRJQUxfUkVOREVSX1NUQVRFKTtcblxuICAvKipcbiAgICogRmlyZWQgZXZlcnkgdGltZSB0aGUgSFRNTCBlbGVtZW50IGNoYW5nZXMuXG4gICAqXG4gICAqIEBwYXJhbSBmblxuICAgKi9cbiAgY29uc3Qgb25DaGFuZ2UgPSAoZm46IChlbDogSFRNTEVsZW1lbnQgfCBudWxsKSA9PiB2b2lkKSA9PiB7XG4gICAgZW9SZWYuY3VycmVudD8ucmVnaXN0ZXJPbkNoYW5nZShmbik7XG4gIH07XG5cbiAgLyoqXG4gICAqIEZpcmVkIHdoZW4gdGhlIEhUTUwgZWxlbWVudCBpcyBhZGRlZCB0byB0aGUgRE9NLlxuICAgKlxuICAgKiBAcGFyYW0gZm5cbiAgICovXG4gIGNvbnN0IG9uQWRkID0gKGZuOiAoZWw6IEhUTUxFbGVtZW50IHwgbnVsbCkgPT4gdm9pZCkgPT4ge1xuICAgIGVvUmVmLmN1cnJlbnQ/LnJlZ2lzdGVyT25BZGQoZm4pO1xuICB9O1xuXG4gIC8qKlxuICAgKiBGaXJlZCB3aGVuIHRoZSBIVE1MIGVsZW1lbnQgaXMgcmVtb3ZlZCBmcm9tIHRoZSBET00uXG4gICAqXG4gICAqIEBwYXJhbSBmblxuICAgKi9cbiAgY29uc3Qgb25SZW1vdmUgPSAoZm46IChlbDogSFRNTEVsZW1lbnQgfCBudWxsKSA9PiB2b2lkKSA9PiB7XG4gICAgZW9SZWYuY3VycmVudD8ucmVnaXN0ZXJPblJlbW92ZShmbik7XG4gIH07XG5cbiAgLyoqXG4gICAqIEZpcmVkIHdoZW4gdGhlIGNsYXNzIG9mIHRoZSBIVE1MIGVsZW1lbnQgY2hhbmdlcy5cbiAgICpcbiAgICogQHBhcmFtIGZuXG4gICAqL1xuICBjb25zdCBvbkNsYXNzQ2hhbmdlID0gKGZuOiAoY2xhc3Nlcz86IERPTVRva2VuTGlzdCkgPT4gdm9pZCkgPT4ge1xuICAgIGVvUmVmLmN1cnJlbnQ/LnJlZ2lzdGVyT25jbGFzc0NoYW5nZShmbik7XG4gIH07XG5cbiAgLyoqXG4gICAqIEZpcmVkIHdoZW4gYSBjbGFzcyBpcyBhZGRlZCB0byB0aGUgSFRNTCBlbGVtZW50LlxuICAgKlxuICAgKiBAcGFyYW0gY2xhc3NOYW1lXG4gICAqIEBwYXJhbSBmblxuICAgKi9cbiAgY29uc3Qgb25DbGFzc0FkZGVkID0gKGNsYXNzTmFtZTogc3RyaW5nLCBmbjogKCkgPT4gdm9pZCkgPT4ge1xuICAgIGVvUmVmLmN1cnJlbnQ/LnJlZ2lzdGVyT25DbGFzc0FkZGVkKGNsYXNzTmFtZSwgZm4pO1xuICB9O1xuXG4gIC8qKlxuICAgKiBGaXJlZCB3aGVuIGEgY2xhc3MgaXMgcmVtb3ZlZCBmcm9tIHRoZSBIVE1MIGVsZW1lbnQuXG4gICAqXG4gICAqIEBwYXJhbSBjbGFzc05hbWVcbiAgICogQHBhcmFtIGZuXG4gICAqL1xuICBjb25zdCBvbkNsYXNzUmVtb3ZlZCA9IChjbGFzc05hbWU6IHN0cmluZywgZm46ICgpID0+IHZvaWQpID0+IHtcbiAgICBlb1JlZi5jdXJyZW50Py5yZWdpc3Rlck9uQ2xhc3NSZW1vdmVkKGNsYXNzTmFtZSwgZm4pO1xuICB9O1xuXG4gIC8qKlxuICAgKiBGaXJlZCB3aGVuIGEgY2hpbGQgZWxlbWVudCBpcyBhZGRlZCB0byB0aGUgSFRNTCBlbGVtZW50LlxuICAgKlxuICAgKiBAcGFyYW0gZm5cbiAgICovXG4gIGNvbnN0IG9uQWRkQ2hpbGQgPSAoZm46IChub2Rlcz86IERPTVRva2VuTGlzdCkgPT4gdm9pZCkgPT4ge1xuICAgIGVvUmVmLmN1cnJlbnQ/LnJlZ2lzdGVyT25BZGRDaGlsZChmbik7XG4gIH07XG5cbiAgLyoqXG4gICAqIEZpcmVkIHdoZW4gYSBjaGlsZCBlbGVtZW50IGlzIHJlbW92ZWQgZnJvbSB0aGUgSFRNTCBlbGVtZW50LlxuICAgKlxuICAgKiBAcGFyYW0gZm5cbiAgICovXG4gIGNvbnN0IG9uUmVtb3ZlQ2hpbGQgPSAoZm46IChub2Rlcz86IERPTVRva2VuTGlzdCkgPT4gdm9pZCkgPT4ge1xuICAgIGVvUmVmLmN1cnJlbnQ/LnJlZ2lzdGVyT25SZW1vdmVDaGlsZChmbik7XG4gIH07XG5cbiAgLyoqXG4gICAqIEFsbG93cyBob29raW5nIGV2ZW50IGxpc3RlbmVycyB0byB0aGUgSFRNTCBlbGVtZW50LCBzdWNoIGFzIGBmb2N1c2AsIGBibHVyYCwgZXRjLlxuICAgKlxuICAgKiBAcGFyYW0gZXZlbnRcbiAgICogQHBhcmFtIGZuXG4gICAqL1xuICBjb25zdCBvbkV2ZW50ID0gPEsgZXh0ZW5kcyBrZXlvZiBIVE1MRWxlbWVudEV2ZW50TWFwPihcbiAgICBldmVudDogSyxcbiAgICBmbjogRXZlbnRMaXN0ZW5lck9yRXZlbnRMaXN0ZW5lck9iamVjdCxcbiAgKSA9PiB7XG4gICAgZW9SZWYuY3VycmVudC5yZWdpc3RlckV2ZW50KGV2ZW50LCBmbik7XG4gIH07XG5cbiAgLyoqXG4gICAqIFVzZWZ1bCB3aGVuIHJlbmRlcmluZyBhIFJlYWN0LmpzIGNvbXBvbmVudCBpbnNpZGUgdGhlIEhUTUwgZWxlbWVudC5cbiAgICpcbiAgICogQHBhcmFtIGZuXG4gICAqIEByZXR1cm5zXG4gICAqL1xuICBjb25zdCByZW5kZXIgPSAoZm46ICgpID0+IFJlYWN0RWxlbWVudCkgPT4ge1xuICAgIGlmICghcmVuZGVyQmxvY2tlZCkge1xuICAgICAgcmV0dXJuIGVvUmVmLmN1cnJlbnQucmVuZGVyKGZuKTtcbiAgICB9XG4gIH07XG5cbiAgLyoqXG4gICAqIENoZWNrcyBpZiB0aGUgZWxlbWVudCBleGlzdHMgaW4gdGhlIERPTS5cbiAgICpcbiAgICogQHJldHVybnNcbiAgICovXG4gIGNvbnN0IGV4aXN0cyA9ICgpID0+ICEhZW9SZWYuY3VycmVudC5nZXROb2RlKCk7XG5cbiAgLyoqXG4gICAqIENoZWNrcyBpZiByZW5kZXJpbmcgaXMgdW5ibG9ja2VkLlxuICAgKlxuICAgKiBAcmV0dXJuc1xuICAgKi9cbiAgY29uc3QgaXNSZW5kZXJlZCA9ICgpID0+ICFyZW5kZXJCbG9ja2VkO1xuXG4gIC8qKlxuICAgKiBUcmlnZ2VycyBhbiBldmVudCBmb3IgdGhlIEhUTUwgZWxlbWVudC5cbiAgICpcbiAgICogQHBhcmFtIGV2ZW50XG4gICAqL1xuICBjb25zdCBmaXJlID0gKGV2ZW50OiBNb3VzZUV2ZW50VHlwZXMpID0+IHtcbiAgICBlb1JlZi5jdXJyZW50LmZpcmUoZXZlbnQpO1xuICB9O1xuXG4gIC8qKlxuICAgKiBTaG93cyB0aGUgSFRNTCBlbGVtZW50LlxuICAgKlxuICAgKiBAcmV0dXJuc1xuICAgKi9cbiAgY29uc3Qgc2hvdyA9ICgpID0+IGVvUmVmLmN1cnJlbnQuc2hvdygpO1xuXG4gIC8qKlxuICAgKiBIaWRlcyB0aGUgSFRNTCBlbGVtZW50LlxuICAgKlxuICAgKiBAcmV0dXJuc1xuICAgKi9cbiAgY29uc3QgaGlkZSA9ICgpID0+IGVvUmVmLmN1cnJlbnQuaGlkZSgpO1xuXG4gIC8qKlxuICAgKiBCbG9ja3MgdGhlIHJlbmRlcmluZyBvZiBlbGVtZW50cy5cbiAgICpcbiAgICogQHJldHVybnNcbiAgICovXG4gIGNvbnN0IGJsb2NrUmVuZGVyaW5nID0gKCkgPT4gc2V0UmVuZGVyQmxvY2tlZCh0cnVlKTtcblxuICAvKipcbiAgICogVW5ibG9ja3MgdGhlIHJlbmRlcmluZyBvZiBlbGVtZW50cy5cbiAgICpcbiAgICogQHJldHVybnNcbiAgICovXG4gIGNvbnN0IHVuYmxvY2tSZW5kZXJpbmcgPSAoKSA9PiBzZXRSZW5kZXJCbG9ja2VkKGZhbHNlKTtcblxuICAvKipcbiAgICogQXBwbGllcyBDU1Mgc3R5bGVzIHRvIHRoZSBIVE1MIGVsZW1lbnQuXG4gICAqXG4gICAqIEBwYXJhbSBzdHlsZXNcbiAgICovXG4gIGNvbnN0IGFwcGx5U3R5bGUgPSAoc3R5bGVzOiBSZWFjdC5DU1NQcm9wZXJ0aWVzKSA9PiB7XG4gICAgY29uc3Qgbm9kZSA9IGVvUmVmPy5jdXJyZW50Py5nZXROb2RlKCk7XG4gICAgbm9kZSAmJiBPYmplY3QuYXNzaWduKG5vZGUuc3R5bGUsIHN0eWxlcyk7XG4gIH07XG5cbiAgdXNlRWZmZWN0KCgpID0+IHtcbiAgICBlb1JlZi5jdXJyZW50LmluaXQoKTtcbiAgICBlb1JlZi5jdXJyZW50LnJlZ2lzdGVyT25SZXNldCgoKSA9PiBzZXRSZW5kZXJCbG9ja2VkKElOSVRJQUxfUkVOREVSX1NUQVRFKSk7XG4gICAgRE9NT2JzZXJ2ZXIub2JzZXJ2ZSgpO1xuICAgIHJldHVybiAoKSA9PiBET01PYnNlcnZlci5yZW1vdmUoc2VsZWN0b3IpO1xuICB9LCBbc2VsZWN0b3IuZ2V0UGF0dGVybigpXSk7XG5cbiAgcmV0dXJuIHtcbiAgICB0YXJnZXROb2RlOiBlb1JlZi5jdXJyZW50LmdldE5vZGUoKSxcbiAgICBvbkNoYW5nZSxcbiAgICBvbkFkZCxcbiAgICBvblJlbW92ZSxcbiAgICBvbkNsYXNzQ2hhbmdlLFxuICAgIG9uQ2xhc3NBZGRlZCxcbiAgICBvbkNsYXNzUmVtb3ZlZCxcbiAgICBvbkFkZENoaWxkLFxuICAgIG9uUmVtb3ZlQ2hpbGQsXG4gICAgb25FdmVudCxcbiAgICBibG9ja1JlbmRlcmluZyxcbiAgICB1bmJsb2NrUmVuZGVyaW5nLFxuICAgIGV4aXN0cyxcbiAgICBpc1JlbmRlcmVkLFxuICAgIHJlbmRlcixcbiAgICBmaXJlLFxuICAgIHNob3csXG4gICAgaGlkZSxcbiAgICBhcHBseVN0eWxlLFxuICB9IHNhdGlzZmllcyBFbGVtZW50T2JzZXJ2ZXJVdGlsaXR5O1xufTtcbiIsImltcG9ydCB7IHVzZVJlZiwgdXNlU3RhdGUgfSBmcm9tIFwicmVhY3RcIjtcblxudHlwZSBBcnJvd1Bvc2l0aW9uID0gJ2x0JyB8ICdjdCcgfCAncnQnXG5cbmludGVyZmFjZSBBbmltYXRpb25Qcm9wcyB7XG4gICAgZWxlbWVudDogSFRNTEVsZW1lbnRcbiAgICB0YXJnZXRTY3JvbGw6IG51bWJlciBcbiAgICBkdXJhdGlvbjogbnVtYmVyIFxuICAgIGRpcmVjdGlvbj86ICdsdCcgfCAncnQnIFxuICAgIG11bHRpcGx5PzogbnVtYmVyIFxuICAgIG9mZnNldD86IG51bWJlclxuICAgIGNhbGxiYWNrPzogKHBvc2l0aW9uOiBBcnJvd1Bvc2l0aW9uKSA9PiB2b2lkXG59XG5cbmNvbnN0IGFuaW1hdGVIb3Jpem9udGFsU2Nyb2xsID0gKHsgZWxlbWVudCwgZHVyYXRpb24sIHRhcmdldFNjcm9sbCwgbXVsdGlwbHkgPSAxLCBkaXJlY3Rpb24sIGNhbGxiYWNrLCBvZmZzZXQgPSAwIH06IEFuaW1hdGlvblByb3BzKSA9PiB7XG4gICAgY29uc3Qgc3RhcnQgPSBlbGVtZW50LnNjcm9sbExlZnRcbiAgICBjb25zdCBkaXN0YW5jZSA9ICh0YXJnZXRTY3JvbGwgLSBzdGFydCkgKiBtdWx0aXBseTtcbiAgICBjb25zdCBzdGFydFRpbWUgPSBwZXJmb3JtYW5jZS5ub3coKTtcblxuICAgIGZ1bmN0aW9uIGVhc2VPdXRTaW5lKHg6IG51bWJlcik6IG51bWJlciB7XG4gICAgICByZXR1cm4gTWF0aC5zaW4oKHggKiBNYXRoLlBJKSAvIDIpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHNjcm9sbFN0ZXAoY3VycmVudFRpbWU6IG51bWJlcik6IHZvaWQge1xuICAgICAgICBjb25zdCB0aW1lRWxhcHNlZCA9IGN1cnJlbnRUaW1lIC0gc3RhcnRUaW1lO1xuICAgICAgICBjb25zdCBwcm9ncmVzcyA9IE1hdGgubWluKHRpbWVFbGFwc2VkIC8gZHVyYXRpb24sIDEpO1xuICAgICAgICBjb25zdCBlYXNpbmcgPSBlYXNlT3V0U2luZShwcm9ncmVzcyk7XG4gICAgICAgIGNvbnN0IHN0ZXAgPSBzdGFydCArIChkaXN0YW5jZSAqIGVhc2luZylcbiAgICAgICAgY29uc3QgY2FuU2Nyb2xsID0gKGRpcmVjdGlvbiA9PT0gJ3J0JyA/IChlbGVtZW50LnNjcm9sbExlZnQgPCBzdGVwKSA6IChlbGVtZW50LnNjcm9sbExlZnQgPiBzdGVwKSkgfHwgIWRpcmVjdGlvblxuICAgICAgICBcbiAgICAgICAgaWYgKHN0ZXAgPiAwICYmIGNhblNjcm9sbCkge1xuICAgICAgICAgIGVsZW1lbnQuc2Nyb2xsVG8oc3RlcCwgMClcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0aW1lRWxhcHNlZCA8IGR1cmF0aW9uKSB7XG4gICAgICAgICAgICByZXF1ZXN0QW5pbWF0aW9uRnJhbWUoc2Nyb2xsU3RlcCk7XG4gICAgICAgIH0gXG5cbiAgICAgICAgLy8gRW5kIG9mIHNjcm9sbGluZyBjb250YWluZXJcbiAgICAgICAgZWxzZSBpZiAoKGVsZW1lbnQuc2Nyb2xsTGVmdCArIG9mZnNldCkgPT09IGVsZW1lbnQuc2Nyb2xsV2lkdGgpIHtcbiAgICAgICAgICAgIGNhbGxiYWNrPy4oJ3J0JylcbiAgICAgICAgfSBcbiAgICAgICAgLy8gQmVnaW4gb2Ygc2Nyb2xsaW5nIGNvbnRhaW5lclxuICAgICAgICBlbHNlIGlmIChlbGVtZW50LnNjcm9sbExlZnQgPD0gMSkge1xuICAgICAgICAgICAgY2FsbGJhY2s/LignbHQnKVxuICAgICAgICB9XG4gICAgICAgIC8vIFNvbWV3aGVyZSBpbiB0aGUgbWlkZGxlXG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgY2FsbGJhY2s/LignY3QnKVxuICAgICAgICB9XG5cbiAgICB9XG5cbiAgICByZXF1ZXN0QW5pbWF0aW9uRnJhbWUoc2Nyb2xsU3RlcCk7XG59XG5cblxuZXhwb3J0IGNvbnN0IHVzZUdyYWJBbmRTY3JvbGwgPSAoZW5hYmxlZDogYm9vbGVhbiwgY2h1bmtXaWR0aDogbnVtYmVyLCBzcGVlZDogbnVtYmVyID0gNDAwLCBvZmZzZXQ6IG51bWJlciA9IDApID0+IHtcbiAgICBjb25zdCBjb250YWluZXJSZWYgPSB1c2VSZWY8SFRNTERpdkVsZW1lbnQ+KG51bGwpXG4gICAgY29uc3QgWyBsZWZ0QXJyb3csIHNldExlZnRBcnJvdyBdID0gdXNlU3RhdGUoZmFsc2UpXG4gICAgY29uc3QgWyByaWdodEFycm93LCBzZXRSaWdodEFycm93IF0gPSB1c2VTdGF0ZSh0cnVlKVxuXG4gICAgY29uc3QgaGFuZGxlQXJyb3dzID0gKHBvc2l0aW9uOiBBcnJvd1Bvc2l0aW9uKSA9PiB7XG4gICAgICAgIHN3aXRjaCAocG9zaXRpb24pIHtcbiAgICAgICAgICAgIGNhc2UgJ2x0JzpcbiAgICAgICAgICAgICAgICBzZXRMZWZ0QXJyb3coZmFsc2UpXG4gICAgICAgICAgICAgICAgc2V0UmlnaHRBcnJvdyh0cnVlKVxuICAgICAgICAgICAgICAgIGJyZWFrXG5cbiAgICAgICAgICAgIGNhc2UgJ3J0JzpcbiAgICAgICAgICAgICAgICBzZXRMZWZ0QXJyb3codHJ1ZSlcbiAgICAgICAgICAgICAgICBzZXRSaWdodEFycm93KGZhbHNlKVxuICAgICAgICAgICAgICAgIGJyZWFrXG5cbiAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgc2V0TGVmdEFycm93KHRydWUpXG4gICAgICAgICAgICAgICAgc2V0UmlnaHRBcnJvdyh0cnVlKVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgY29uc3QgYW5pbWF0aW9uVHJpZ2dlciA9ICgpID0+IHtcbiAgICAgICAgaWYgKGVuYWJsZWQgJiYgY29udGFpbmVyUmVmLmN1cnJlbnQpIHtcbiAgICAgICAgICAgIGNvbnN0IGRpc3QgPSAoY29udGFpbmVyUmVmPy5jdXJyZW50Py5zY3JvbGxMZWZ0IHx8IDApIC8gY2h1bmtXaWR0aFxuICAgICAgICAgICAgY29uc3QgdGFyZ2V0U2Nyb2xsID0gY2h1bmtXaWR0aCAqIChNYXRoLmZsb29yKGRpc3QpICsgKGRpc3QgJSAxID4gMC41ID8gMSA6IDApKVxuICAgICAgICAgICAgYW5pbWF0ZUhvcml6b250YWxTY3JvbGwoe1xuICAgICAgICAgICAgICAgIGVsZW1lbnQ6IGNvbnRhaW5lclJlZi5jdXJyZW50LCBcbiAgICAgICAgICAgICAgICB0YXJnZXRTY3JvbGwsIFxuICAgICAgICAgICAgICAgIGR1cmF0aW9uOiBzcGVlZCxcbiAgICAgICAgICAgICAgICBvZmZzZXQsXG4gICAgICAgICAgICAgICAgY2FsbGJhY2s6IGhhbmRsZUFycm93c1xuICAgICAgICAgICAgfSlcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGNvbnN0IG9uTmV4dCA9IChjYXJkc1RvU2xpZGU6IG51bWJlcikgPT4ge1xuICAgICAgICBpZiAoY29udGFpbmVyUmVmLmN1cnJlbnQpIHtcbiAgICAgICAgICAgIGNvbnN0IHRhcmdldFNjcm9sbCA9IGNvbnRhaW5lclJlZi5jdXJyZW50LnNjcm9sbExlZnQgKyBjaHVua1dpZHRoXG4gICAgICAgICAgICBhbmltYXRlSG9yaXpvbnRhbFNjcm9sbCh7XG4gICAgICAgICAgICAgICAgZWxlbWVudDogY29udGFpbmVyUmVmLmN1cnJlbnQsIFxuICAgICAgICAgICAgICAgIHRhcmdldFNjcm9sbCwgXG4gICAgICAgICAgICAgICAgZHVyYXRpb246IHNwZWVkLCBcbiAgICAgICAgICAgICAgICBkaXJlY3Rpb246ICdydCcsIFxuICAgICAgICAgICAgICAgIG11bHRpcGx5OiBjYXJkc1RvU2xpZGUsXG4gICAgICAgICAgICAgICAgb2Zmc2V0LFxuICAgICAgICAgICAgICAgIGNhbGxiYWNrOiBoYW5kbGVBcnJvd3NcbiAgICAgICAgICAgIH0pXG4gICAgICAgIH1cbiAgICB9XG4gICAgXG4gICAgY29uc3Qgb25QcmV2aW91cyA9IChjYXJkc1RvU2xpZGU6IG51bWJlcikgPT4ge1xuICAgICAgICBpZiAoY29udGFpbmVyUmVmLmN1cnJlbnQpIHtcbiAgICAgICAgICAgIGNvbnN0IHRhcmdldFNjcm9sbCA9IGNvbnRhaW5lclJlZi5jdXJyZW50LnNjcm9sbExlZnQgLSBjaHVua1dpZHRoXG4gICAgICAgICAgICBhbmltYXRlSG9yaXpvbnRhbFNjcm9sbCh7XG4gICAgICAgICAgICAgICAgZWxlbWVudDogY29udGFpbmVyUmVmLmN1cnJlbnQsIFxuICAgICAgICAgICAgICAgIHRhcmdldFNjcm9sbCwgXG4gICAgICAgICAgICAgICAgZHVyYXRpb246IHNwZWVkLCBcbiAgICAgICAgICAgICAgICBkaXJlY3Rpb246ICdsdCcsIFxuICAgICAgICAgICAgICAgIG11bHRpcGx5OiBjYXJkc1RvU2xpZGUsXG4gICAgICAgICAgICAgICAgb2Zmc2V0LFxuICAgICAgICAgICAgICAgIGNhbGxiYWNrOiBoYW5kbGVBcnJvd3NcbiAgICAgICAgICAgIH0pXG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgICBjb250YWluZXJSZWYsXG4gICAgICAgIGxlZnRBcnJvdyxcbiAgICAgICAgcmlnaHRBcnJvdyxcbiAgICAgICAgYW5pbWF0aW9uVHJpZ2dlcixcbiAgICAgICAgb25OZXh0LFxuICAgICAgICBvblByZXZpb3VzXG4gICAgfVxufSIsImltcG9ydCBSZWFjdCwge1xuICBjcmVhdGVDb250ZXh0LFxuICB1c2VDb250ZXh0LFxuICB1c2VDYWxsYmFjayxcbiAgdXNlTWVtbyxcbiAgUmVhY3ROb2RlLFxufSBmcm9tIFwicmVhY3RcIjtcbmltcG9ydCB7IHVzZUF0b21WYWx1ZSB9IGZyb20gXCJqb3RhaVwiO1xuaW1wb3J0IHsgYmFzZVVybEF0b20sIG9yZ0xldmVsQXBpS2V5QXRvbSB9IGZyb20gXCJzcmMvYXRvbXMvZW52aXZlL2Vudml2ZUNvbmZpZ1wiO1xuaW1wb3J0IHsgZ2V0TWVyY2hhbnRPcmdJZFF1ZXJ5IH0gZnJvbSBcInNyYy9hcHBsaWNhdGlvbi9tb2RlbHMvZ3JhcGhxbC9xdWVyaWVzL2dldE1lcmNoYW50T3JnSWRRdWVyeVwiO1xuaW1wb3J0IHsgdmFsaWRhdGVHcmFwaFFMT3JnSWQgfSBmcm9tIFwic3JjL2FwcGxpY2F0aW9uL21vZGVscy92YWxpZGF0b3JzL3ZhbGlkYXRlR3JhcGhRTE9yZ0lkXCI7XG5pbXBvcnQge1xuICBnZXRNZXJjaGFudENvbG9yc1F1ZXJ5LFxuICBHZXRNZXJjaGFudENvbG9yc1F1ZXJ5RGF0YSxcbiAgZ2V0TWVyY2hhbnRGcm9udGVuZENvbmZpZ1F1ZXJ5LFxuICBHZXRNZXJjaGFudEZyb250ZW5kQ29uZmlnUXVlcnlEYXRhLFxufSBmcm9tIFwic3JjL2FwcGxpY2F0aW9uL21vZGVscy9ncmFwaHFsXCI7XG5pbXBvcnQgeyB2YWxpZGF0ZUdyYXBoUUxDb2xvcnNDb25maWcgfSBmcm9tIFwic3JjL2FwcGxpY2F0aW9uL21vZGVscy92YWxpZGF0b3JzL3ZhbGlkYXRlR3JhcGhRTENvbG9yc0NvbmZpZ1wiO1xuaW1wb3J0IHsgdmFsaWRhdGVHcmFwaFFMRnJvbnRlbmRDb25maWcgfSBmcm9tIFwic3JjL2FwcGxpY2F0aW9uL21vZGVscy92YWxpZGF0b3JzL3ZhbGlkYXRlR3JhcGhRTEZyb250ZW5kQ29uZmlnXCI7XG5pbXBvcnQgeyBDb2xvck1hcHBpbmcgfSBmcm9tIFwic3JjL2FwcGxpY2F0aW9uL21vZGVscy9jb2xvcnNDb25maWdcIjtcbmltcG9ydCB7IEZyb250ZW5kQ29uZmlnIH0gZnJvbSBcInNyYy9hcHBsaWNhdGlvbi9tb2RlbHMvZnJvbnRlbmRDb25maWdcIjtcbmltcG9ydCBMb2dnZXIgZnJvbSBcInNyYy9hcHBsaWNhdGlvbi9sb2dnaW5nL2xvZ2dlclwiO1xuaW1wb3J0IHsgY29uZmlnVmVyc2lvbiB9IGZyb20gXCJzcmMvdHlwZXMvY29uZmlnLXZlcnNpb25zXCI7XG5pbXBvcnQge1xuICBDYW1lbENhc2VkUHJvcGVydGllc0RlZXAsXG4gIHRyYW5zZm9ybVNuYWtlVG9DYW1lbCxcbn0gZnJvbSBcInNyYy9hcHBsaWNhdGlvbi9tb2RlbHNcIjtcblxuaW50ZXJmYWNlIEJhc2VNZUNvbmZpZ1F1ZXJ5UmVzcG9uc2Uge1xuICBtZToge1xuICAgIG9yZz86IHtcbiAgICAgIGlkOiBzdHJpbmc7XG4gICAgfTtcbiAgICBnZXRQcm9kdWN0c0NvbmZpZ0J5VmVyc2lvbj86IHtcbiAgICAgIGZyb250ZW5kPzoge1xuICAgICAgICB2YWx1ZXM6IENhbWVsQ2FzZWRQcm9wZXJ0aWVzRGVlcDxHZXRNZXJjaGFudEZyb250ZW5kQ29uZmlnUXVlcnlEYXRhPjtcbiAgICAgIH07XG4gICAgICBjb2xvcnM/OiB7IHZhbHVlczogQ2FtZWxDYXNlZFByb3BlcnRpZXNEZWVwPEdldE1lcmNoYW50Q29sb3JzUXVlcnlEYXRhPiB9O1xuICAgIH07XG4gIH07XG59XG5leHBvcnQgdHlwZSBDb2xvcnNDb25maWdSZXNwb25zZSA9IENhbWVsQ2FzZWRQcm9wZXJ0aWVzRGVlcDxDb2xvck1hcHBpbmc+O1xuZXhwb3J0IHR5cGUgRnJvbnRlbmRDb25maWdSZXNwb25zZSA9IENhbWVsQ2FzZWRQcm9wZXJ0aWVzRGVlcDxGcm9udGVuZENvbmZpZz47XG5cbmV4cG9ydCB0eXBlIEdyYXBoUWxDb25maWdWYWx1ZXMgPSB7XG4gIGNvbG9yc0NvbmZpZz86IENvbG9yc0NvbmZpZ1Jlc3BvbnNlO1xuICBmcm9udGVuZENvbmZpZz86IENhbWVsQ2FzZWRQcm9wZXJ0aWVzRGVlcDxGcm9udGVuZENvbmZpZz47XG59O1xuXG5pbnRlcmZhY2UgR3JhcGhRTENvbnRleHRWYWx1ZSB7XG4gIGV4ZWN1dGVRdWVyeTogPFQ+KFxuICAgIHF1ZXJ5OiBzdHJpbmcsXG4gICAgdmFyaWFibGVzPzogUmVjb3JkPHN0cmluZywgdW5rbm93bj5cbiAgKSA9PiBQcm9taXNlPFQ+O1xuICBnZXRPcmdJZDogKCkgPT4gUHJvbWlzZTxzdHJpbmcgfCB1bmRlZmluZWQ+O1xuICBnZXRDb2xvcnNBbmRGcm9udGVuZENvbmZpZzogKCkgPT4gUHJvbWlzZTxHcmFwaFFsQ29uZmlnVmFsdWVzPjtcbiAgaXNSZWFkeTogYm9vbGVhbjtcbn1cblxuY29uc3QgR3JhcGhRTENvbnRleHQgPSBjcmVhdGVDb250ZXh0PEdyYXBoUUxDb250ZXh0VmFsdWUgfCBudWxsPihudWxsKTtcblxuY29uc3QgY29sb3JzQW5kRnJvbnRlbmRDb25maWdRdWVyeSA9ICgpID0+IGBcbiAgcXVlcnkgKCR2ZXJzaW9uOiBTdHJpbmcgPSBcIiR7Y29uZmlnVmVyc2lvbigpfVwiKSB7XG4gICAgbWUge1xuICAgICAgZ2V0UHJvZHVjdHNDb25maWdCeVZlcnNpb24odmVyc2lvbjogJHZlcnNpb24pIHtcbiAgICAgICAgZnJvbnRlbmQgeyB2YWx1ZXMgfVxuICAgICAgICBjb2xvcnMgeyB2YWx1ZXMgfVxuICAgICAgfVxuICAgIH1cbiAgfVxuYDtcblxudHlwZSBHcmFwaFFMUHJvdmlkZXJQcm9wcyA9IHtcbiAgY2hpbGRyZW46IFJlYWN0Tm9kZTtcbn07XG5cbmV4cG9ydCBjb25zdCBHcmFwaFFMUHJvdmlkZXIgPSAoeyBjaGlsZHJlbiB9OiBHcmFwaFFMUHJvdmlkZXJQcm9wcykgPT4ge1xuICBjb25zdCBhcGlLZXkgPSB1c2VBdG9tVmFsdWUob3JnTGV2ZWxBcGlLZXlBdG9tKTtcbiAgY29uc3QgYmFzZVVybCA9IHVzZUF0b21WYWx1ZShiYXNlVXJsQXRvbSk7XG5cbiAgY29uc3QgaXNSZWFkeSA9IEJvb2xlYW4oYXBpS2V5ICYmIGJhc2VVcmwpO1xuXG4gIGNvbnN0IGV4ZWN1dGVRdWVyeSA9IHVzZUNhbGxiYWNrKFxuICAgIGFzeW5jIChxdWVyeTogc3RyaW5nLCB2YXJpYWJsZXM/OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPikgPT4ge1xuICAgICAgaWYgKCFpc1JlYWR5KSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIkdyYXBoUUwgY2xpZW50IG5vdCByZWFkeSAtIG1pc3NpbmcgYXBpS2V5IG9yIGJhc2VVcmxcIik7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgZmV0Y2goYCR7YmFzZVVybH0vdjEvZ3JhcGhxbGAsIHtcbiAgICAgICAgbWV0aG9kOiBcIlBPU1RcIixcbiAgICAgICAgaGVhZGVyczoge1xuICAgICAgICAgIFwiQ29udGVudC1UeXBlXCI6IFwiYXBwbGljYXRpb24vanNvblwiLFxuICAgICAgICAgIEF1dGhvcml6YXRpb246IGBCZWFyZXIgJHthcGlLZXl9YCxcbiAgICAgICAgfSxcbiAgICAgICAgYm9keTogSlNPTi5zdHJpbmdpZnkoeyBxdWVyeSwgdmFyaWFibGVzIH0pLFxuICAgICAgfSk7XG5cbiAgICAgIGlmICghcmVzcG9uc2Uub2spIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBHcmFwaFFMIHJlcXVlc3QgZmFpbGVkOiAke3Jlc3BvbnNlLnN0YXR1c1RleHR9YCk7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHJlc3BvbnNlLmpzb24oKTtcbiAgICAgIGlmIChyZXN1bHQuZXJyb3JzKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgR3JhcGhRTCBlcnJvcnM6ICR7SlNPTi5zdHJpbmdpZnkocmVzdWx0LmVycm9ycyl9YCk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiByZXN1bHQuZGF0YTtcbiAgICB9LFxuICAgIFthcGlLZXksIGJhc2VVcmwsIGlzUmVhZHldXG4gICk7XG5cbiAgY29uc3QgZ2V0T3JnSWQgPSB1c2VDYWxsYmFjayhhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBleGVjdXRlUXVlcnkoZ2V0TWVyY2hhbnRPcmdJZFF1ZXJ5KTtcbiAgICByZXR1cm4gdmFsaWRhdGVHcmFwaFFMT3JnSWQocmVzcG9uc2UubWUub3JnPy5pZCk7XG4gIH0sIFtleGVjdXRlUXVlcnldKTtcblxuICBjb25zdCBnZXRDb2xvcnNBbmRGcm9udGVuZENvbmZpZyA9XG4gICAgdXNlQ2FsbGJhY2soYXN5bmMgKCk6IFByb21pc2U8R3JhcGhRbENvbmZpZ1ZhbHVlcz4gPT4ge1xuICAgICAgdHJ5IHtcbiAgICAgICAgY29uc3QgcXVlcnkgPSBhd2FpdCBjb2xvcnNBbmRGcm9udGVuZENvbmZpZ1F1ZXJ5KCk7XG4gICAgICAgIGlmICghcXVlcnkpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJDb2xvcnMgYW5kIGZyb250ZW5kIGNvbmZpZyBxdWVyeSBpcyBub3QgZGVmaW5lZFwiKTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IGV4ZWN1dGVRdWVyeShxdWVyeSk7XG4gICAgICAgIGNvbnN0IGNvbG9yc0NvbmZpZyA9XG4gICAgICAgICAgcmVzcG9uc2UubWUuZ2V0UHJvZHVjdHNDb25maWdCeVZlcnNpb24/LmNvbG9ycz8udmFsdWVzO1xuICAgICAgICBjb25zdCBmcm9udGVuZENvbmZpZyA9XG4gICAgICAgICAgcmVzcG9uc2UubWUuZ2V0UHJvZHVjdHNDb25maWdCeVZlcnNpb24/LmZyb250ZW5kPy52YWx1ZXM7XG4gICAgICAgIGNvbnN0IHRyYW5zZm9ybWVkQ29sb3JDb25maWcgPSB0cmFuc2Zvcm1TbmFrZVRvQ2FtZWwoY29sb3JzQ29uZmlnKTtcbiAgICAgICAgY29uc3QgdHJhbnNmb3JtZWRGcm9udGVuZENvbmZpZyA9IHRyYW5zZm9ybVNuYWtlVG9DYW1lbChmcm9udGVuZENvbmZpZyk7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgY29sb3JzQ29uZmlnOiB0cmFuc2Zvcm1lZENvbG9yQ29uZmlnIGFzIENvbG9yc0NvbmZpZ1Jlc3BvbnNlLFxuICAgICAgICAgIGZyb250ZW5kQ29uZmlnOiB0cmFuc2Zvcm1lZEZyb250ZW5kQ29uZmlnIGFzIEZyb250ZW5kQ29uZmlnUmVzcG9uc2UsXG4gICAgICAgIH07XG4gICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgTG9nZ2VyLmxvZ0Vycm9yKFxuICAgICAgICAgIFwiRXJyb3IgZmV0Y2hpbmcgZ3JhcGhxbCBjb2xvcnMgYW5kIGZyb250ZW5kIGNvbmZpZ1wiLFxuICAgICAgICAgIGVyclxuICAgICAgICApO1xuICAgICAgICByZXR1cm4geyBjb2xvcnNDb25maWc6IHVuZGVmaW5lZCwgZnJvbnRlbmRDb25maWc6IHVuZGVmaW5lZCB9O1xuICAgICAgfVxuICAgIH0sIFtleGVjdXRlUXVlcnldKTtcblxuICBjb25zdCB2YWx1ZSA9IHVzZU1lbW8oXG4gICAgKCkgPT4gKHtcbiAgICAgIGV4ZWN1dGVRdWVyeSxcbiAgICAgIGdldE9yZ0lkLFxuICAgICAgZ2V0Q29sb3JzQW5kRnJvbnRlbmRDb25maWcsXG4gICAgICBpc1JlYWR5LFxuICAgIH0pLFxuICAgIFtleGVjdXRlUXVlcnksIGdldE9yZ0lkLCBnZXRDb2xvcnNBbmRGcm9udGVuZENvbmZpZywgaXNSZWFkeV1cbiAgKTtcblxuICByZXR1cm4gKFxuICAgIDxHcmFwaFFMQ29udGV4dC5Qcm92aWRlciB2YWx1ZT17dmFsdWV9PntjaGlsZHJlbn08L0dyYXBoUUxDb250ZXh0LlByb3ZpZGVyPlxuICApO1xufTtcblxuZXhwb3J0IGNvbnN0IHVzZUdyYXBoUUxDbGllbnQgPSAoKSA9PiB7XG4gIGNvbnN0IGNvbnRleHQgPSB1c2VDb250ZXh0KEdyYXBoUUxDb250ZXh0KTtcbiAgaWYgKCFjb250ZXh0KSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFwidXNlR3JhcGhRTENsaWVudCBtdXN0IGJlIHVzZWQgd2l0aGluIGEgR3JhcGhRTFByb3ZpZGVyXCIpO1xuICB9XG4gIHJldHVybiBjb250ZXh0O1xufTtcbiIsImltcG9ydCB7IHVzZUNhbGxiYWNrLCB1c2VFZmZlY3QsIHVzZVN0YXRlIH0gZnJvbSBcInJlYWN0XCI7XG5pbXBvcnQgeyB1c2VHcmFwaFFMQ2xpZW50IH0gZnJvbSBcInNyYy9jb250ZXh0cy9ncmFwaHFsQ29udGV4dFwiO1xuaW1wb3J0IHsgQ29sb3JNYXBwaW5nIH0gZnJvbSBcInNyYy9hcHBsaWNhdGlvbi9tb2RlbHMvY29sb3JzQ29uZmlnXCI7XG5pbXBvcnQgeyBGcm9udGVuZENvbmZpZyB9IGZyb20gXCJzcmMvYXBwbGljYXRpb24vbW9kZWxzL2Zyb250ZW5kQ29uZmlnXCI7XG5pbXBvcnQgeyB0cmFuc2Zvcm1TbmFrZVRvQ2FtZWwgfSBmcm9tIFwic3JjL2FwcGxpY2F0aW9uL21vZGVsc1wiO1xuXG5leHBvcnQgY29uc3QgdXNlQ29sb3JzQW5kRnJvbnRlbmRDb25maWcgPSAoKSA9PiB7XG4gIGNvbnN0IHsgZ2V0Q29sb3JzQW5kRnJvbnRlbmRDb25maWcsIGlzUmVhZHkgfSA9IHVzZUdyYXBoUUxDbGllbnQoKTtcbiAgY29uc3QgW2RhdGEsIHNldERhdGFdID0gdXNlU3RhdGUoe30pO1xuICBjb25zdCBbbG9hZGluZywgc2V0TG9hZGluZ10gPSB1c2VTdGF0ZShmYWxzZSk7XG4gIGNvbnN0IFtlcnJvciwgc2V0RXJyb3JdID0gdXNlU3RhdGU8RXJyb3IgfCBudWxsPihudWxsKTtcblxuICBjb25zdCBmZXRjaENvbmZpZyA9IHVzZUNhbGxiYWNrKGFzeW5jICgpID0+IHtcbiAgICBpZiAoIWlzUmVhZHkpIHJldHVybjtcblxuICAgIHNldExvYWRpbmcodHJ1ZSk7XG4gICAgc2V0RXJyb3IobnVsbCk7XG5cbiAgICB0cnkge1xuICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgZ2V0Q29sb3JzQW5kRnJvbnRlbmRDb25maWcoKTtcbiAgICAgIHNldERhdGEocmVzdWx0KTtcbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIHNldEVycm9yKGVyciBpbnN0YW5jZW9mIEVycm9yID8gZXJyIDogbmV3IEVycm9yKFwiVW5rbm93biBlcnJvclwiKSk7XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgIHNldExvYWRpbmcoZmFsc2UpO1xuICAgIH1cbiAgfSwgW2dldENvbG9yc0FuZEZyb250ZW5kQ29uZmlnLCBpc1JlYWR5XSk7XG5cbiAgdXNlRWZmZWN0KCgpID0+IHtcbiAgICBmZXRjaENvbmZpZygpO1xuICB9LCBbZmV0Y2hDb25maWddKTtcblxuICByZXR1cm4geyBkYXRhLCBsb2FkaW5nLCBlcnJvciwgcmVmZXRjaDogZmV0Y2hDb25maWcgfTtcbn07XG5cbmV4cG9ydCBjb25zdCB1c2VPcmdJZCA9ICgpID0+IHtcbiAgY29uc3QgeyBnZXRPcmdJZCwgaXNSZWFkeSB9ID0gdXNlR3JhcGhRTENsaWVudCgpO1xuICBjb25zdCBbb3JnSWQsIHNldE9yZ0lkXSA9IHVzZVN0YXRlPHN0cmluZyB8IHVuZGVmaW5lZD4oKTtcbiAgY29uc3QgW2xvYWRpbmcsIHNldExvYWRpbmddID0gdXNlU3RhdGUoZmFsc2UpO1xuICBjb25zdCBbZXJyb3IsIHNldEVycm9yXSA9IHVzZVN0YXRlPEVycm9yIHwgbnVsbD4obnVsbCk7XG5cbiAgdXNlRWZmZWN0KCgpID0+IHtcbiAgICBpZiAoIWlzUmVhZHkpIHJldHVybjtcblxuICAgIGNvbnN0IGZldGNoT3JnSWQgPSBhc3luYyAoKSA9PiB7XG4gICAgICBzZXRMb2FkaW5nKHRydWUpO1xuICAgICAgc2V0RXJyb3IobnVsbCk7XG5cbiAgICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IGlkID0gYXdhaXQgZ2V0T3JnSWQoKTtcbiAgICAgICAgc2V0T3JnSWQoaWQpO1xuICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgIHNldEVycm9yKGVyciBpbnN0YW5jZW9mIEVycm9yID8gZXJyIDogbmV3IEVycm9yKFwiVW5rbm93biBlcnJvclwiKSk7XG4gICAgICB9IGZpbmFsbHkge1xuICAgICAgICBzZXRMb2FkaW5nKGZhbHNlKTtcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgZmV0Y2hPcmdJZCgpO1xuICB9LCBbZ2V0T3JnSWQsIGlzUmVhZHldKTtcblxuICByZXR1cm4geyBvcmdJZCwgbG9hZGluZywgZXJyb3IgfTtcbn07XG4iLCJpbXBvcnQgUmVhY3QsIHtcbiAgY3JlYXRlQ29udGV4dCxcbiAgdXNlQ2FsbGJhY2ssXG4gIHVzZUNvbnRleHQsXG4gIHVzZU1lbW8sXG4gIHVzZVN0YXRlLFxuICB1c2VFZmZlY3QsXG59IGZyb20gXCJyZWFjdFwiO1xuaW1wb3J0IFVBUGFyc2VyIGZyb20gXCJ1YS1wYXJzZXItanNcIjtcbmltcG9ydCBMb2dnZXIgZnJvbSBcInNyYy9hcHBsaWNhdGlvbi9sb2dnaW5nL2xvZ2dlclwiO1xuaW1wb3J0IENvbW1lcmNlQXBpQ2xpZW50IGZyb20gXCJzcmMvYXBwbGljYXRpb24vY29tbWVyY2UtYXBpXCI7XG5pbXBvcnQgeyB2NCBhcyB1dWlkIH0gZnJvbSBcInV1aWRcIjtcbmltcG9ydCB7IENsaWVudERldGFpbHMgfSBmcm9tIFwic3JjL2FwcGxpY2F0aW9uL21vZGVscy9jbGllbnREZXRhaWxzXCI7XG5pbXBvcnQgeyB1c2VMb2NhbFN0b3JhZ2UgfSBmcm9tIFwic3JjL2NvbnRleHRzL2xvY2FsU3RvcmFnZUNvbnRleHRcIjtcblxuLy8gSGVscGVyIGZ1bmN0aW9uIGZyb20gdGhlIG9yaWdpbmFsIHNlcnZpY2VcbmNvbnN0IGdldFVzZXJBZ2VudERldGFpbHMgPSAoKTogQ2xpZW50RGV0YWlscyA9PiB7XG4gIGNvbnN0IHVhUGFyc2VyID0gbmV3IFVBUGFyc2VyKCk7XG4gIGNvbnN0IHJlc3VsdCA9IHVhUGFyc2VyLmdldFJlc3VsdCgpO1xuXG4gIHJldHVybiB7XG4gICAgb3M6IHJlc3VsdD8ub3M/Lm5hbWUsXG4gICAgb3NWZXJzaW9uOiByZXN1bHQ/Lm9zPy52ZXJzaW9uLFxuICAgIGRldmljZUJyYW5kOiByZXN1bHQ/LmRldmljZT8udmVuZG9yLFxuICAgIGRldmljZU1hbnVmYWN0dXJlcjogcmVzdWx0Py5kZXZpY2U/LnZlbmRvcixcbiAgICBkZXZpY2VNb2RlbDogcmVzdWx0Py5kZXZpY2U/Lm1vZGVsLFxuICAgIGJyb3dzZXI6IHJlc3VsdD8uYnJvd3Nlcj8ubmFtZSxcbiAgICBicm93c2VyVmVyc2lvbjogcmVzdWx0Py5icm93c2VyPy52ZXJzaW9uLFxuICAgIHVzZXJBZ2VudDogcmVzdWx0Py51YSxcbiAgfTtcbn07XG5cbmV4cG9ydCBpbnRlcmZhY2UgVXNlcklkZW50aXR5Q29udGV4dFR5cGUge1xuICBpZGVudGlmeVVzZXI6ICgpID0+IFByb21pc2U8dm9pZD47XG4gIGdldFVzZXJJZE9yRGVmYXVsdDogKCkgPT4gc3RyaW5nO1xuICBnZXRVc2VySWRPdmVycmlkZUZyb21Mb2NhbFN0b3JhZ2U6ICgpID0+IHN0cmluZyB8IHVuZGVmaW5lZDtcbiAgZ2V0VXNlcklkRGVmYXVsdEZyb21Mb2NhbFN0b3JhZ2U6ICgpID0+IHN0cmluZyB8IHVuZGVmaW5lZDtcbiAgc2V0VXNlcklkRGVmYXVsdEluTG9jYWxTdG9yYWdlOiAodXNlcklkOiBzdHJpbmcpID0+IHN0cmluZztcbiAgc2V0VXNlcklkT3ZlcnJpZGVJbkxvY2FsU3RvcmFnZTogKHVzZXJJZDogc3RyaW5nKSA9PiBzdHJpbmc7XG4gIGNsZWFyVXNlcklkT3ZlcnJpZGVJbkxvY2FsU3RvcmFnZTogKCkgPT4gdm9pZDtcbiAgaXNSZWFkeTogYm9vbGVhbjtcbn1cblxuY29uc3QgVXNlcklkZW50aXR5Q29udGV4dCA9IGNyZWF0ZUNvbnRleHQ8VXNlcklkZW50aXR5Q29udGV4dFR5cGUgfCB1bmRlZmluZWQ+KFxuICB1bmRlZmluZWRcbik7XG5cbmV4cG9ydCBjb25zdCBVc2VySWRlbnRpdHlQcm92aWRlcjogUmVhY3QuRkM8eyBjaGlsZHJlbjogUmVhY3QuUmVhY3ROb2RlIH0+ID0gKHtcbiAgY2hpbGRyZW4sXG59KSA9PiB7XG4gIGNvbnN0IHtcbiAgICBnZXRJdGVtLFxuICAgIHNldEl0ZW0sXG4gICAgaXNBdmFpbGFibGU6IGxvY2FsU3RvcmFnZUlzUmVhZHksXG4gIH0gPSB1c2VMb2NhbFN0b3JhZ2UoKTtcblxuICBjb25zdCBbaXNSZWFkeSwgc2V0SXNSZWFkeV0gPSB1c2VTdGF0ZShmYWxzZSk7XG5cbiAgdXNlRWZmZWN0KCgpID0+IHtcbiAgICAvLyBBc3N1bWluZyBDb21tZXJjZUFwaUNsaWVudCBhbmQgb3RoZXIgZGVwZW5kZW5jaWVzIGFyZSByZWFkeSBpZiBsb2NhbFN0b3JhZ2UgaXMuXG4gICAgLy8gSW4gYSBtb3JlIGNvbXBsZXggc2NlbmFyaW8sIHlvdSBtaWdodCBoYXZlIG1vcmUgY2hlY2tzIGhlcmUuXG4gICAgc2V0SXNSZWFkeShsb2NhbFN0b3JhZ2VJc1JlYWR5KTtcbiAgfSwgW2xvY2FsU3RvcmFnZUlzUmVhZHldKTtcblxuICBjb25zdCBVU0VSX0lEX09WRVJSSURFX0tFWSA9IFwidjEtc3BpZmZ5LXVzZXItaWQtb3ZlcnJpZGVcIjtcbiAgY29uc3QgVVNFUl9JRF9ERUZBVUxUX0tFWSA9IFwidjEtc3BpZmZ5LXVzZXItaWQtZGVmYXVsdFwiO1xuXG4gIGNvbnN0IGdldFVzZXJJZE92ZXJyaWRlRnJvbUxvY2FsU3RvcmFnZSA9IHVzZUNhbGxiYWNrKCgpOlxuICAgIHwgc3RyaW5nXG4gICAgfCB1bmRlZmluZWQgPT4ge1xuICAgIHJldHVybiBnZXRJdGVtKFVTRVJfSURfT1ZFUlJJREVfS0VZKSA/PyB1bmRlZmluZWQ7XG4gIH0sIFtnZXRJdGVtXSk7XG5cbiAgY29uc3QgZ2V0VXNlcklkRGVmYXVsdEZyb21Mb2NhbFN0b3JhZ2UgPSB1c2VDYWxsYmFjaygoKTpcbiAgICB8IHN0cmluZ1xuICAgIHwgdW5kZWZpbmVkID0+IHtcbiAgICByZXR1cm4gZ2V0SXRlbShVU0VSX0lEX0RFRkFVTFRfS0VZKSA/PyB1bmRlZmluZWQ7XG4gIH0sIFtnZXRJdGVtXSk7XG5cbiAgY29uc3Qgc2V0VXNlcklkRGVmYXVsdEluTG9jYWxTdG9yYWdlID0gdXNlQ2FsbGJhY2soXG4gICAgKHVzZXJJZDogc3RyaW5nKTogc3RyaW5nID0+IHtcbiAgICAgIExvZ2dlci5sb2dJbmZvKFxuICAgICAgICBgc2V0VXNlcklkRGVmYXVsdEluTG9jYWxTdG9yYWdlIC0gU2V0dGluZyB1c2VyX2lkPSR7dXNlcklkfWBcbiAgICAgICk7XG4gICAgICBzZXRJdGVtKFVTRVJfSURfREVGQVVMVF9LRVksIHVzZXJJZCk7XG4gICAgICAvLyB3aW5kb3cuZGlzcGF0Y2hFdmVudCBpcyBoYW5kbGVkIGJ5IHVzZUxvY2FsU3RvcmFnZSBub3dcbiAgICAgIHJldHVybiB1c2VySWQ7XG4gICAgfSxcbiAgICBbc2V0SXRlbSwgVVNFUl9JRF9ERUZBVUxUX0tFWV1cbiAgKTtcblxuICBjb25zdCBzZXRVc2VySWRPdmVycmlkZUluTG9jYWxTdG9yYWdlID0gdXNlQ2FsbGJhY2soXG4gICAgKHVzZXJJZDogc3RyaW5nKTogc3RyaW5nID0+IHtcbiAgICAgIExvZ2dlci5sb2dJbmZvKFxuICAgICAgICBgc2V0VXNlcklkT3ZlcnJpZGVJbkxvY2FsU3RvcmFnZSAtIFNldHRpbmcgdXNlcl9pZD0ke3VzZXJJZH1gXG4gICAgICApO1xuICAgICAgc2V0SXRlbShVU0VSX0lEX09WRVJSSURFX0tFWSwgdXNlcklkKTtcbiAgICAgIC8vIHdpbmRvdy5kaXNwYXRjaEV2ZW50IGlzIGhhbmRsZWQgYnkgdXNlTG9jYWxTdG9yYWdlIG5vd1xuICAgICAgcmV0dXJuIHVzZXJJZDtcbiAgICB9LFxuICAgIFtzZXRJdGVtLCBVU0VSX0lEX09WRVJSSURFX0tFWV1cbiAgKTtcblxuICBjb25zdCBjbGVhclVzZXJJZE92ZXJyaWRlSW5Mb2NhbFN0b3JhZ2UgPSB1c2VDYWxsYmFjaygoKSA9PiB7XG4gICAgTG9nZ2VyLmxvZ0luZm8oYGNsZWFyVXNlcklkT3ZlcnJpZGVJbkxvY2FsU3RvcmFnZSAtIENsZWFyaW5nIHVzZXJfaWRgKTtcbiAgICAvLyBMb2NhbFN0b3JhZ2VTZXJ2aWNlLmdldExvY2FsU3RvcmFnZSgpPy5yZW1vdmVJdGVtKFVTRVJfSURfT1ZFUlJJREVfS0VZKTtcbiAgICAvLyB3aW5kb3cuZGlzcGF0Y2hFdmVudCBpcyBoYW5kbGVkIGJ5IHVzZUxvY2FsU3RvcmFnZSBub3dcbiAgICBzZXRJdGVtKFVTRVJfSURfT1ZFUlJJREVfS0VZLCBcIlwiKTsgLy8gU2V0IHRvIGVtcHR5IHN0cmluZyB0byBjbGVhclxuICB9LCBbc2V0SXRlbSwgVVNFUl9JRF9PVkVSUklERV9LRVldKTtcblxuICBjb25zdCBnZXRVc2VySWRPckRlZmF1bHQgPSB1c2VDYWxsYmFjaygoKTogc3RyaW5nID0+IHtcbiAgICBjb25zdCB1c2VySWRPdmVycmlkZSA9IGdldFVzZXJJZE92ZXJyaWRlRnJvbUxvY2FsU3RvcmFnZSgpO1xuICAgIGlmICh1c2VySWRPdmVycmlkZSkge1xuICAgICAgcmV0dXJuIHVzZXJJZE92ZXJyaWRlO1xuICAgIH1cblxuICAgIGNvbnN0IGRlZmF1bHRVc2VySWQgPSBnZXRVc2VySWREZWZhdWx0RnJvbUxvY2FsU3RvcmFnZSgpO1xuICAgIGlmIChkZWZhdWx0VXNlcklkKSB7XG4gICAgICByZXR1cm4gZGVmYXVsdFVzZXJJZDtcbiAgICB9XG5cbiAgICByZXR1cm4gc2V0VXNlcklkRGVmYXVsdEluTG9jYWxTdG9yYWdlKGBzcGlmZnktdXNlci1pZC0ke3V1aWQoKX1gKTtcbiAgfSwgW1xuICAgIGdldFVzZXJJZE92ZXJyaWRlRnJvbUxvY2FsU3RvcmFnZSxcbiAgICBnZXRVc2VySWREZWZhdWx0RnJvbUxvY2FsU3RvcmFnZSxcbiAgICBzZXRVc2VySWREZWZhdWx0SW5Mb2NhbFN0b3JhZ2UsXG4gIF0pO1xuXG4gIGNvbnN0IGlkZW50aWZ5VXNlciA9IHVzZUNhbGxiYWNrKGFzeW5jICgpOiBQcm9taXNlPHZvaWQ+ID0+IHtcbiAgICBpZiAoIWlzUmVhZHkpIHtcbiAgICAgIExvZ2dlci5sb2dXYXJuKFxuICAgICAgICBcIltVc2VySWRlbnRpdHlDb250ZXh0XSBDb250ZXh0IG5vdCByZWFkeSwgc2tpcHBpbmcgaWRlbnRpZnlVc2VyXCIsXG4gICAgICAgIHVuZGVmaW5lZFxuICAgICAgKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0cnkge1xuICAgICAgLy8gVGVtcG9yYXJpbHkgY29tbWVudGVkIG91dCB1bnRpbCBXaW5kb3dEYXRhTGF5ZXJTZXJ2aWNlIGlzIHJlc29sdmVkXG4gICAgICAvLyBjb25zdCBjZHBVc2VySWQgPSBXaW5kb3dEYXRhTGF5ZXJTZXJ2aWNlLmdldEdvb2dsZUFuYWx5dGljc0NsaWVudElkKCk7XG4gICAgICBjb25zdCBjZHBVc2VySWQgPSBcIlVOS05PV05fQ0RQX1VTRVJfSURcIjsgLy8gUGxhY2Vob2xkZXJcbiAgICAgIGNvbnN0IHVzZXJJZCA9IGdldFVzZXJJZE9yRGVmYXVsdCgpO1xuICAgICAgY29uc3QgdXNlckFnZW50RGV0YWlscyA9IGdldFVzZXJBZ2VudERldGFpbHMoKTtcblxuICAgICAgaWYgKCFjZHBVc2VySWQpIHtcbiAgICAgICAgTG9nZ2VyLmxvZ1dhcm4oXG4gICAgICAgICAgXCJbc3BpZmZ5LWFpXSBObyBHQSBDbGllbnQgSUQgZm91bmQsIHNraXBwaW5nIGlkZW50aWZ5VXNlclwiLFxuICAgICAgICAgIHVuZGVmaW5lZFxuICAgICAgICApO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIGF3YWl0IENvbW1lcmNlQXBpQ2xpZW50LmlkZW50aWZ5VXNlcih1c2VySWQsIGNkcFVzZXJJZCwgdXNlckFnZW50RGV0YWlscyk7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIExvZ2dlci5sb2dFcnJvcihcIltzcGlmZnktYWldIEVycm9yIGlkZW50aWZ5aW5nIHVzZXJcIiwgZXJyb3IpO1xuICAgIH1cbiAgfSwgW2lzUmVhZHksIGdldFVzZXJJZE9yRGVmYXVsdF0pO1xuXG4gIGNvbnN0IHZhbHVlID0gdXNlTWVtbyhcbiAgICAoKSA9PiAoe1xuICAgICAgaWRlbnRpZnlVc2VyLFxuICAgICAgZ2V0VXNlcklkT3JEZWZhdWx0LFxuICAgICAgZ2V0VXNlcklkT3ZlcnJpZGVGcm9tTG9jYWxTdG9yYWdlLFxuICAgICAgZ2V0VXNlcklkRGVmYXVsdEZyb21Mb2NhbFN0b3JhZ2UsXG4gICAgICBzZXRVc2VySWREZWZhdWx0SW5Mb2NhbFN0b3JhZ2UsXG4gICAgICBzZXRVc2VySWRPdmVycmlkZUluTG9jYWxTdG9yYWdlLFxuICAgICAgY2xlYXJVc2VySWRPdmVycmlkZUluTG9jYWxTdG9yYWdlLFxuICAgICAgaXNSZWFkeSxcbiAgICB9KSxcbiAgICBbXG4gICAgICBpZGVudGlmeVVzZXIsXG4gICAgICBnZXRVc2VySWRPckRlZmF1bHQsXG4gICAgICBnZXRVc2VySWRPdmVycmlkZUZyb21Mb2NhbFN0b3JhZ2UsXG4gICAgICBnZXRVc2VySWREZWZhdWx0RnJvbUxvY2FsU3RvcmFnZSxcbiAgICAgIHNldFVzZXJJZERlZmF1bHRJbkxvY2FsU3RvcmFnZSxcbiAgICAgIHNldFVzZXJJZE92ZXJyaWRlSW5Mb2NhbFN0b3JhZ2UsXG4gICAgICBjbGVhclVzZXJJZE92ZXJyaWRlSW5Mb2NhbFN0b3JhZ2UsXG4gICAgICBpc1JlYWR5LFxuICAgIF1cbiAgKTtcblxuICByZXR1cm4gKFxuICAgIDxVc2VySWRlbnRpdHlDb250ZXh0LlByb3ZpZGVyIHZhbHVlPXt2YWx1ZX0+XG4gICAgICB7Y2hpbGRyZW59XG4gICAgPC9Vc2VySWRlbnRpdHlDb250ZXh0LlByb3ZpZGVyPlxuICApO1xufTtcblxuZXhwb3J0IGNvbnN0IHVzZVVzZXJJZGVudGl0eSA9ICgpID0+IHtcbiAgY29uc3QgY29udGV4dCA9IHVzZUNvbnRleHQoVXNlcklkZW50aXR5Q29udGV4dCk7XG4gIGlmICghY29udGV4dCkge1xuICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgIFwidXNlVXNlcklkZW50aXR5IG11c3QgYmUgdXNlZCB3aXRoaW4gYSBVc2VySWRlbnRpdHlQcm92aWRlclwiXG4gICAgKTtcbiAgfVxuICByZXR1cm4gY29udGV4dDtcbn07XG4iLCJpbXBvcnQgeyB1c2VTdGF0ZSwgdXNlQ2FsbGJhY2sgfSBmcm9tIFwicmVhY3RcIjtcbmltcG9ydCB7IHVzZVVzZXJJZGVudGl0eSB9IGZyb20gXCJzcmMvY29udGV4dHMvdXNlcklkZW50aXR5Q29udGV4dFwiO1xuXG5leHBvcnQgY29uc3QgdXNlSWRlbnRpZnlVc2VyID0gKCkgPT4ge1xuICBjb25zdCB7IGlkZW50aWZ5VXNlciwgaXNSZWFkeSB9ID0gdXNlVXNlcklkZW50aXR5KCk7XG4gIGNvbnN0IFtsb2FkaW5nLCBzZXRMb2FkaW5nXSA9IHVzZVN0YXRlKGZhbHNlKTtcbiAgY29uc3QgW2Vycm9yLCBzZXRFcnJvcl0gPSB1c2VTdGF0ZTxFcnJvciB8IG51bGw+KG51bGwpO1xuXG4gIGNvbnN0IGV4ZWN1dGVJZGVudGlmeVVzZXIgPSB1c2VDYWxsYmFjayhhc3luYyAoKSA9PiB7XG4gICAgaWYgKCFpc1JlYWR5KSB7XG4gICAgICBzZXRFcnJvcihuZXcgRXJyb3IoXCJVc2VySWRlbnRpdHlDb250ZXh0IG5vdCByZWFkeS5cIikpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHNldExvYWRpbmcodHJ1ZSk7XG4gICAgc2V0RXJyb3IobnVsbCk7XG5cbiAgICB0cnkge1xuICAgICAgYXdhaXQgaWRlbnRpZnlVc2VyKCk7XG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICBzZXRFcnJvcihcbiAgICAgICAgZXJyIGluc3RhbmNlb2YgRXJyb3JcbiAgICAgICAgICA/IGVyclxuICAgICAgICAgIDogbmV3IEVycm9yKFwiVW5rbm93biBlcnJvciBkdXJpbmcgdXNlciBpZGVudGlmaWNhdGlvbi5cIilcbiAgICAgICk7XG4gICAgICB0aHJvdyBlcnI7XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgIHNldExvYWRpbmcoZmFsc2UpO1xuICAgIH1cbiAgfSwgW2lkZW50aWZ5VXNlciwgaXNSZWFkeV0pO1xuXG4gIHJldHVybiB7IGxvYWRpbmcsIGVycm9yLCBleGVjdXRlSWRlbnRpZnlVc2VyLCBpc1JlYWR5IH07XG59O1xuIiwiaW1wb3J0IHsgdXNlQXRvbVZhbHVlIH0gZnJvbSBcImpvdGFpXCI7XG5pbXBvcnQgeyBPcmdTaG9ydE5hbWUgfSBmcm9tIFwic3JjL2FwcGxpY2F0aW9uL21vZGVsc1wiO1xuaW1wb3J0IHsgb3JnU2hvcnROYW1lQXRvbSB9IGZyb20gXCJzcmMvYXRvbXMvZW52aXZlL2Vudml2ZUNvbmZpZ1wiO1xuYWJzdHJhY3QgY2xhc3MgSW1hZ2VSZXNvbHZlciB7XG4gIGFic3RyYWN0IHJlc29sdmUodXJsOiBzdHJpbmcsIHNpemU6IG51bWJlcik6IHN0cmluZztcbn1cblxuY2xhc3MgTWVyY2hhbnRJbWFnZVJlc29sdmVyIHtcbiAgcHJpdmF0ZSBzdGF0aWMgaW1hZ2VSZXNvbHZlck1hcCA9IG5ldyBNYXA8c3RyaW5nLCBJbWFnZVJlc29sdmVyPigpO1xuXG4gIHByaXZhdGUgc3RhdGljIGxvYWRNYXBwaW5nKCkge1xuICAgIGlmICh0aGlzLmltYWdlUmVzb2x2ZXJNYXAuc2l6ZSA9PT0gMCkge1xuICAgICAgdGhpcy5pbWFnZVJlc29sdmVyTWFwLnNldChPcmdTaG9ydE5hbWUuU3BhbngsIG5ldyBTaG9waWZ5SW1hZ2VSZXNvbHZlcigpKTtcbiAgICAgIHRoaXMuaW1hZ2VSZXNvbHZlck1hcC5zZXQoXG4gICAgICAgIE9yZ1Nob3J0TmFtZS5TcGFueFN0YWdpbmcsXG4gICAgICAgIG5ldyBTaG9waWZ5SW1hZ2VSZXNvbHZlcigpXG4gICAgICApO1xuICAgICAgdGhpcy5pbWFnZVJlc29sdmVyTWFwLnNldChcbiAgICAgICAgT3JnU2hvcnROYW1lLlVuaXF1ZVZpbnRhZ2UsXG4gICAgICAgIG5ldyBTaG9waWZ5SW1hZ2VSZXNvbHZlcigpXG4gICAgICApO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5pbWFnZVJlc29sdmVyTWFwO1xuICB9XG5cbiAgc3RhdGljIGdldChuYW1lOiBzdHJpbmcpIHtcbiAgICByZXR1cm4gdGhpcy5sb2FkTWFwcGluZygpLmdldChuYW1lKTtcbiAgfVxufVxuXG5jbGFzcyBTaG9waWZ5SW1hZ2VSZXNvbHZlciBleHRlbmRzIEltYWdlUmVzb2x2ZXIge1xuICByZXNvbHZlKHVybDogc3RyaW5nLCBzaXplOiBudW1iZXIpOiBzdHJpbmcge1xuICAgIGNvbnN0IHBhdHRlcm4gPSAvX1xcZCt4XFwuanBnLztcbiAgICBjb25zdCB1cmxIYXNQcmVmaXggPSBwYXR0ZXJuLnRlc3QodXJsKTtcbiAgICBjb25zdCBuZXdTaXplUHJlZml4ID0gYF8ke3NpemV9eC5qcGdgO1xuICAgIGlmICh1cmxIYXNQcmVmaXgpIHtcbiAgICAgIHJldHVybiB1cmwucmVwbGFjZShwYXR0ZXJuLCBuZXdTaXplUHJlZml4KTtcbiAgICB9XG4gICAgcmV0dXJuIHVybC5yZXBsYWNlKFwiLmpwZ1wiLCBuZXdTaXplUHJlZml4KTtcbiAgfVxufVxuXG5leHBvcnQgY29uc3QgdXNlSW1hZ2VSZXNvbHZlciA9ICgpID0+IHtcbiAgY29uc3Qgb3JnU2hvcnROYW1lID0gdXNlQXRvbVZhbHVlKG9yZ1Nob3J0TmFtZUF0b20pO1xuICBjb25zdCByZXNvbHZlID0gKGltYWdlPzogc3RyaW5nLCBzaXplPzogbnVtYmVyKSA9PiB7XG4gICAgaWYgKGltYWdlICYmIHNpemUgJiYgb3JnU2hvcnROYW1lKSB7XG4gICAgICBjb25zdCBuZXdJbWFnZVBhdGggPSBNZXJjaGFudEltYWdlUmVzb2x2ZXIuZ2V0KG9yZ1Nob3J0TmFtZSk/LnJlc29sdmUoXG4gICAgICAgIGltYWdlLFxuICAgICAgICBzaXplXG4gICAgICApO1xuICAgICAgcmV0dXJuIG5ld0ltYWdlUGF0aCB8fCBpbWFnZTtcbiAgICB9XG4gICAgcmV0dXJuIGltYWdlO1xuICB9O1xuXG4gIHJldHVybiB7XG4gICAgcmVzb2x2ZSxcbiAgfTtcbn07XG4iLCJpbXBvcnQgeyBSZWZPYmplY3QsIHVzZUVmZmVjdCwgdXNlU3RhdGUgfSBmcm9tICdyZWFjdCc7XG5cbi8vIGh0dHBzOi8vcmFzaWxiYWlkYXIubWVkaXVtLmNvbS90cmlnZ2VyLWV2ZW50LXdoZW4tZWxlbWVudC1lbnRlcnMtdmlld3BvcnQtdGhlLXJlYWN0LXdheS0xNjg1MDlkYTJlMjNcbmV4cG9ydCBjb25zdCB1c2VJbnRlcnNlY3Rpb24gPSAoZWxlbWVudDogUmVmT2JqZWN0PEhUTUxFbGVtZW50Piwgcm9vdE1hcmdpbjogc3RyaW5nKSA9PiB7XG4gIGNvbnN0IFtpc1Zpc2libGUsIHNldElzVmlzaWJsZV0gPSB1c2VTdGF0ZShmYWxzZSk7XG5cbiAgdXNlRWZmZWN0KCgpID0+IHtcbiAgICBjb25zdCBjdXJyZW50ID0gZWxlbWVudD8uY3VycmVudDtcbiAgICBjb25zdCBvYnNlcnZlciA9IG5ldyBJbnRlcnNlY3Rpb25PYnNlcnZlcihcbiAgICAgIChbZW50cnldKSA9PiB7XG4gICAgICAgIHNldElzVmlzaWJsZShlbnRyeS5pc0ludGVyc2VjdGluZyk7XG4gICAgICB9LFxuICAgICAgeyByb290TWFyZ2luIH0sXG4gICAgKTtcblxuICAgIGlmIChjdXJyZW50KSB7XG4gICAgICBvYnNlcnZlcj8ub2JzZXJ2ZShjdXJyZW50KTtcbiAgICB9XG5cbiAgICByZXR1cm4gKCkgPT4ge1xuICAgICAgaWYgKGN1cnJlbnQpIHtcbiAgICAgICAgb2JzZXJ2ZXIudW5vYnNlcnZlKGN1cnJlbnQpO1xuICAgICAgfVxuICAgIH07XG4gIH0sIFtdKTtcblxuICByZXR1cm4gaXNWaXNpYmxlO1xufTtcbiIsImltcG9ydCB7IHVzZVN0YXRlLCB1c2VFZmZlY3QgfSBmcm9tICdyZWFjdCc7XG5cbmV4cG9ydCBjb25zdCB1c2VJc1NtYWxsU2NyZWVuID0gKCkgPT4ge1xuICBjb25zdCBbaXNTbWFsbCwgc2V0SXNTbWFsbF0gPSB1c2VTdGF0ZShmYWxzZSk7XG5cbiAgdXNlRWZmZWN0KCgpID0+IHtcbiAgICBjb25zdCBtZWRpYVF1ZXJ5ID0gd2luZG93Lm1hdGNoTWVkaWEoJyhtYXgtd2lkdGg6IDQ3OXB4KScpO1xuXG4gICAgLy8gU2V0IGluaXRpYWwgdmFsdWVcbiAgICBzZXRJc1NtYWxsKG1lZGlhUXVlcnkubWF0Y2hlcyk7XG5cbiAgICAvLyBVcGRhdGUgc3RhdGUgd2hlbiB2aWV3cG9ydCBjaGFuZ2VzXG4gICAgY29uc3QgaGFuZGxlUmVzaXplID0gKGV2ZW50OiBNZWRpYVF1ZXJ5TGlzdEV2ZW50KSA9PiB7XG4gICAgICBzZXRJc1NtYWxsKGV2ZW50Lm1hdGNoZXMpO1xuICAgIH07XG5cbiAgICBtZWRpYVF1ZXJ5LmFkZEV2ZW50TGlzdGVuZXIoJ2NoYW5nZScsIGhhbmRsZVJlc2l6ZSk7XG5cbiAgICByZXR1cm4gKCkgPT4gbWVkaWFRdWVyeS5yZW1vdmVFdmVudExpc3RlbmVyKCdjaGFuZ2UnLCBoYW5kbGVSZXNpemUpO1xuICB9LCBbXSk7XG5cbiAgcmV0dXJuIGlzU21hbGw7XG59O1xuIiwiaW1wb3J0IHsgdXNlU3RhdGUsIHVzZUVmZmVjdCwgdXNlQ2FsbGJhY2sgfSBmcm9tIFwicmVhY3RcIjtcbmltcG9ydCB7XG4gIHVzZUxvY2FsU3RvcmFnZSxcbiAgTG9jYWxTdG9yYWdlS2V5cyxcbn0gZnJvbSBcIi4uL2NvbnRleHRzL2xvY2FsU3RvcmFnZUNvbnRleHRcIjtcbmltcG9ydCB7IExvY2FsU3RvcmFnZUV2ZW50TGlzdGVuZXIgfSBmcm9tIFwiLi4vYXBwbGljYXRpb24vbW9kZWxzL2xvY2FsU3RvcmFnZUV2ZW50TGlzdGVuZXJcIjtcblxuLy8gUmVhY3RpdmUgbG9jYWxTdG9yYWdlIHZhbHVlIGhvb2tcbmV4cG9ydCBjb25zdCB1c2VMb2NhbFN0b3JhZ2VWYWx1ZSA9IChrZXk6IHN0cmluZykgPT4ge1xuICBjb25zdCB7IGdldEl0ZW0sIHNldEl0ZW0sIGF0dGFjaExpc3RlbmVyLCBkZXRhY2hMaXN0ZW5lciB9ID1cbiAgICB1c2VMb2NhbFN0b3JhZ2UoKTtcbiAgY29uc3QgW3ZhbHVlLCBzZXRWYWx1ZV0gPSB1c2VTdGF0ZTxzdHJpbmcgfCBudWxsPigoKSA9PiBnZXRJdGVtKGtleSkpO1xuXG4gIHVzZUVmZmVjdCgoKSA9PiB7XG4gICAgY29uc3QgbGlzdGVuZXI6IExvY2FsU3RvcmFnZUV2ZW50TGlzdGVuZXIgPSB7XG4gICAgICBzdG9yYWdlS2V5OiBrZXksXG4gICAgICBsaXN0ZW5lcjogKGV2ZW50OiBTdG9yYWdlRXZlbnQpID0+IHtcbiAgICAgICAgc2V0VmFsdWUoZXZlbnQubmV3VmFsdWUpO1xuICAgICAgfSxcbiAgICB9O1xuXG4gICAgYXR0YWNoTGlzdGVuZXIobGlzdGVuZXIpO1xuICAgIHJldHVybiAoKSA9PiBkZXRhY2hMaXN0ZW5lcihsaXN0ZW5lcik7XG4gIH0sIFtrZXksIGF0dGFjaExpc3RlbmVyLCBkZXRhY2hMaXN0ZW5lcl0pO1xuXG4gIGNvbnN0IHVwZGF0ZVZhbHVlID0gdXNlQ2FsbGJhY2soXG4gICAgKG5ld1ZhbHVlOiBzdHJpbmcpID0+IHtcbiAgICAgIHNldEl0ZW0oa2V5LCBuZXdWYWx1ZSk7XG4gICAgICBzZXRWYWx1ZShuZXdWYWx1ZSk7XG4gICAgfSxcbiAgICBba2V5LCBzZXRJdGVtXVxuICApO1xuXG4gIHJldHVybiB7IHZhbHVlLCBzZXRWYWx1ZTogdXBkYXRlVmFsdWUgfTtcbn07XG5cbi8vIEZlYXR1cmUgZmxhZyBob29rIGZvciBTcGlmZnlcbmV4cG9ydCBjb25zdCB1c2VTcGlmZnlGZWF0dXJlRmxhZyA9ICgpID0+IHtcbiAgY29uc3QgeyBzZXRTcGlmZnlPbkZlYXR1cmVGbGFnIH0gPSB1c2VMb2NhbFN0b3JhZ2UoKTtcbiAgY29uc3QgeyB2YWx1ZSB9ID0gdXNlTG9jYWxTdG9yYWdlVmFsdWUoTG9jYWxTdG9yYWdlS2V5cy5TcGlmZnlPbk92ZXJyaWRlKTtcblxuICBjb25zdCBzZXRGbGFnID0gdXNlQ2FsbGJhY2soXG4gICAgKGZsYWc6IGJvb2xlYW4gfCBudWxsKSA9PiB7XG4gICAgICBzZXRTcGlmZnlPbkZlYXR1cmVGbGFnKGZsYWcpO1xuICAgIH0sXG4gICAgW3NldFNwaWZmeU9uRmVhdHVyZUZsYWddXG4gICk7XG5cbiAgcmV0dXJuIHtcbiAgICB2YWx1ZTogdmFsdWUgPT09IFwidHJ1ZVwiID8gdHJ1ZSA6IHZhbHVlID09PSBcImZhbHNlXCIgPyBmYWxzZSA6IG51bGwsXG4gICAgc2V0RmxhZyxcbiAgfTtcbn07XG5cbi8vIEZlYXR1cmUgZmxhZyBob29rIGZvciBFbnZpdmVcbmV4cG9ydCBjb25zdCB1c2VFbnZpdmVGZWF0dXJlRmxhZyA9ICgpID0+IHtcbiAgY29uc3QgeyBzZXRJdGVtLCBnZXRJdGVtIH0gPSB1c2VMb2NhbFN0b3JhZ2UoKTtcbiAgY29uc3QgeyB2YWx1ZSB9ID0gdXNlTG9jYWxTdG9yYWdlVmFsdWUoTG9jYWxTdG9yYWdlS2V5cy5FbnZpdmVPbk92ZXJyaWRlKTtcblxuICBjb25zdCBzZXRGbGFnID0gdXNlQ2FsbGJhY2soXG4gICAgKGZsYWc6IGJvb2xlYW4gfCBudWxsKSA9PiB7XG4gICAgICBpZiAoZmxhZyA9PT0gdHJ1ZSkge1xuICAgICAgICBzZXRJdGVtKExvY2FsU3RvcmFnZUtleXMuRW52aXZlT25PdmVycmlkZSwgXCJ0cnVlXCIpO1xuICAgICAgfSBlbHNlIGlmIChmbGFnID09PSBmYWxzZSkge1xuICAgICAgICBzZXRJdGVtKExvY2FsU3RvcmFnZUtleXMuRW52aXZlT25PdmVycmlkZSwgXCJmYWxzZVwiKTtcbiAgICAgIH1cbiAgICB9LFxuICAgIFtzZXRJdGVtXVxuICApO1xuXG4gIHJldHVybiB7XG4gICAgdmFsdWU6IHZhbHVlID09PSBcInRydWVcIiA/IHRydWUgOiB2YWx1ZSA9PT0gXCJmYWxzZVwiID8gZmFsc2UgOiBudWxsLFxuICAgIHNldEZsYWcsXG4gIH07XG59O1xuXG4vLyBTdG9yYWdlIGxpc3RlbmVyIGhvb2tcbmV4cG9ydCBjb25zdCB1c2VMb2NhbFN0b3JhZ2VMaXN0ZW5lciA9IChcbiAga2V5OiBzdHJpbmcsXG4gIGNhbGxiYWNrOiAoZXZlbnQ6IFN0b3JhZ2VFdmVudCkgPT4gdm9pZFxuKSA9PiB7XG4gIGNvbnN0IHsgYXR0YWNoTGlzdGVuZXIsIGRldGFjaExpc3RlbmVyIH0gPSB1c2VMb2NhbFN0b3JhZ2UoKTtcblxuICB1c2VFZmZlY3QoKCkgPT4ge1xuICAgIGNvbnN0IGxpc3RlbmVyOiBMb2NhbFN0b3JhZ2VFdmVudExpc3RlbmVyID0ge1xuICAgICAgc3RvcmFnZUtleToga2V5LFxuICAgICAgbGlzdGVuZXI6IGNhbGxiYWNrLFxuICAgIH07XG4gICAgYXR0YWNoTGlzdGVuZXIobGlzdGVuZXIpO1xuICAgIHJldHVybiAoKSA9PiBkZXRhY2hMaXN0ZW5lcihsaXN0ZW5lcik7XG4gIH0sIFtrZXksIGNhbGxiYWNrLCBhdHRhY2hMaXN0ZW5lciwgZGV0YWNoTGlzdGVuZXJdKTtcbn07XG4iLCJpbXBvcnQgeyBNZXNzYWdlLCBNZXNzYWdlUm9sZSwgTWVzc2FnZVR5cGUgfSBmcm9tICdzcmMvYXBwbGljYXRpb24vbW9kZWxzJztcblxudHlwZSBNZXNzYWdlRmluZGVyID0ge1xuICBtc2dzOiBNZXNzYWdlW11bXTtcbiAgdHlwZT86IE1lc3NhZ2VUeXBlO1xuICByb2xlPzogTWVzc2FnZVJvbGU7XG59O1xuXG5leHBvcnQgY29uc3QgdXNlTWVzc2FnZUZpbHRlciA9ICgpID0+IHtcbiAgY29uc3QgZmluZE1lc3NhZ2VJbmRleCA9ICh7IG1zZ3MsIHR5cGUsIHJvbGUgfTogTWVzc2FnZUZpbmRlcikgPT4ge1xuICAgIGxldCBsYXN0SW5kZXggPSAtMTtcbiAgICBtc2dzLmZvckVhY2goKHN1YkFycmF5LCBpbmRleCkgPT4ge1xuICAgICAgc3ViQXJyYXkuZm9yRWFjaCgob2JqKSA9PiB7XG4gICAgICAgIGlmIChvYmoudHlwZSA9PT0gdHlwZSB8fCBvYmoucm9sZSA9PT0gcm9sZSkgbGFzdEluZGV4ID0gaW5kZXg7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgICByZXR1cm4gbGFzdEluZGV4O1xuICB9O1xuXG4gIGNvbnN0IHJlbW92ZVByZXZpb3VzRGlzY3Vzc2lvbnMgPSAobXNnczogTWVzc2FnZVtdW10sIGluZGV4OiBudW1iZXIpID0+IHtcbiAgICBpZiAoaW5kZXggPiAtMSkge1xuICAgICAgY29uc3QgbGFzdE1lc3NhZ2VzID0gbXNncy5zbGljZShpbmRleCk7XG4gICAgICByZXR1cm4gbGFzdE1lc3NhZ2VzLmxlbmd0aCA+IDAgPyBsYXN0TWVzc2FnZXMgOiBtc2dzO1xuICAgIH1cbiAgICByZXR1cm4gbXNncztcbiAgfTtcblxuICBjb25zdCBnZXRGaWx0ZXJlZE1lc3NhZ2VzID0gKG1zZ3M6IE1lc3NhZ2VbXVtdLCBza2lwRmlsdGVyPzogYm9vbGVhbikgPT4ge1xuICAgIGNvbnN0IG1lc3NhZ2VNYXAgPSBtc2dzLnJlZHVjZShcbiAgICAgIChhY2MsIG1zZykgPT4ge1xuICAgICAgICBhY2NbbXNnWzBdLmlkXSA9IG1zZztcbiAgICAgICAgcmV0dXJuIGFjYztcbiAgICAgIH0sXG4gICAgICB7fSBhcyBSZWNvcmQ8c3RyaW5nLCBNZXNzYWdlW10+LFxuICAgICk7XG4gICAgY29uc3QgZGVkdXBsaWNhdGVkTXNncyA9IE9iamVjdC52YWx1ZXMobWVzc2FnZU1hcCk7XG4gICAgaWYgKCFza2lwRmlsdGVyKSB7XG4gICAgICBjb25zdCBpZHggPSBmaW5kTWVzc2FnZUluZGV4KHsgbXNnczogZGVkdXBsaWNhdGVkTXNncywgdHlwZTogTWVzc2FnZVR5cGUuU2VwYXJhdG9yIH0pO1xuICAgICAgcmV0dXJuIHJlbW92ZVByZXZpb3VzRGlzY3Vzc2lvbnMoZGVkdXBsaWNhdGVkTXNncywgaWR4KTtcbiAgICB9XG4gICAgcmV0dXJuIGRlZHVwbGljYXRlZE1zZ3M7XG4gIH07XG5cbiAgcmV0dXJuIHtcbiAgICBmaW5kTWVzc2FnZUluZGV4LFxuICAgIHJlbW92ZVByZXZpb3VzRGlzY3Vzc2lvbnMsXG4gICAgZ2V0RmlsdGVyZWRNZXNzYWdlcyxcbiAgfTtcbn07XG4iLCJpbXBvcnQgeyB1c2VFZmZlY3QgfSBmcm9tIFwicmVhY3RcIjtcblxuZXhwb3J0IGNvbnN0IHVzZU1lc3NhZ2VTY3JvbGxPYnNlcnZlciA9IChcbiAgICBib3hSZWY6IFJlYWN0LlJlZk9iamVjdDxIVE1MRGl2RWxlbWVudD4sIFxuICAgIHNjcm9sbFJlZjogUmVhY3QuUmVmT2JqZWN0PEhUTUxEaXZFbGVtZW50PiwgXG4gICAgb25TY3JvbGxDaGFuZ2U6IChwb3NpdGlvbjogbnVtYmVyKSA9PiB2b2lkXG4pID0+IHtcblxuICAgIGNvbnN0IGNhbGN1bGF0ZVNjcm9sbEhlaWdodCA9ICgpID0+IHtcbiAgICAgIGNvbnN0IGJveEhlaWdodCA9IGJveFJlZj8uY3VycmVudD8uZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkuaGVpZ2h0IHx8IDBcbiAgICAgIGNvbnN0IHNjcm9sbEhlaWdodCA9IHNjcm9sbFJlZj8uY3VycmVudD8uZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkuaGVpZ2h0IHx8IDBcbiAgICAgIHJldHVybiBib3hIZWlnaHQgLSBzY3JvbGxIZWlnaHRcbiAgICB9XG5cbiAgICBjb25zdCB1cGRhdGVTdGF0ZSA9ICgpID0+IHtcbiAgICAgIGNvbnN0IHNjcm9sbEhlaWdodCA9IGNhbGN1bGF0ZVNjcm9sbEhlaWdodCgpXG4gICAgICBpZiAoc2Nyb2xsSGVpZ2h0ID4gMCkge1xuICAgICAgICBvblNjcm9sbENoYW5nZShzY3JvbGxIZWlnaHQpXG4gICAgICB9XG4gICAgfVxuXG4gICAgdXNlRWZmZWN0KCgpID0+IHtcbiAgICAgIGxldCBib3hSTyA9IG51bGw7XG4gICAgICBsZXQgc2Nyb2xsUk8gPSBudWxsO1xuXG4gICAgICBpZiAoc2Nyb2xsUmVmPy5jdXJyZW50KSB7XG4gICAgICAgIGJveFJPID0gbmV3IFJlc2l6ZU9ic2VydmVyKHVwZGF0ZVN0YXRlKTtcbiAgICAgICAgYm94Uk8ub2JzZXJ2ZShzY3JvbGxSZWY/LmN1cnJlbnQpO1xuICAgICAgfVxuICAgICAgXG4gICAgICBpZiAoYm94UmVmPy5jdXJyZW50KSB7XG4gICAgICAgIHNjcm9sbFJPID0gbmV3IFJlc2l6ZU9ic2VydmVyKHVwZGF0ZVN0YXRlKTtcbiAgICAgICAgc2Nyb2xsUk8ub2JzZXJ2ZShib3hSZWY/LmN1cnJlbnQpO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gKCkgPT4ge1xuICAgICAgICBpZiAoc2Nyb2xsUmVmPy5jdXJyZW50ICYmIGJveFJPKSB7XG4gICAgICAgICAgYm94Uk8udW5vYnNlcnZlKHNjcm9sbFJlZj8uY3VycmVudCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoc2Nyb2xsUk8gJiYgYm94UmVmPy5jdXJyZW50KSB7XG4gICAgICAgICAgc2Nyb2xsUk8/LnVub2JzZXJ2ZShib3hSZWY/LmN1cnJlbnQpXG4gICAgICAgIH1cbiAgICAgIH07XG4gICAgfSwgW10pO1xuXG59IiwiaW1wb3J0IFJlYWN0LCB7IGNyZWF0ZUNvbnRleHQsIHVzZUNvbnRleHQsIHVzZU1lbW8sIFJlYWN0Tm9kZSB9IGZyb20gXCJyZWFjdFwiO1xuaW1wb3J0IHsgT3JnQ29uZmlnRmVhdHVyZUdhdGUgfSBmcm9tIFwic3JjL2FwcGxpY2F0aW9uL21vZGVscy9hcGkvb3JnQ29uZmlnUmVzdWx0c1wiO1xuaW1wb3J0IHsgRmVhdHVyZUdhdGVzIH0gZnJvbSBcInNyYy9hcHBsaWNhdGlvbi9tb2RlbHMvZmVhdHVyZUdhdGVzXCI7XG5pbXBvcnQgTG9nZ2VyIGZyb20gXCJzcmMvYXBwbGljYXRpb24vbG9nZ2luZy9sb2dnZXJcIjtcblxuLy8gVGhpcyBpcyB0aGUgY2xhc3MgdGhhdCB3YXMgcHJldmlvdXNseSBpbXBsaWNpdGx5IHVzZWQgb3IgZGVmaW5lZCBlbHNld2hlcmVcbmNsYXNzIEZlYXR1cmVGbGFnU2VydmljZSB7XG4gIHByaXZhdGUgZmVhdHVyZUdhdGVzOiBPcmdDb25maWdGZWF0dXJlR2F0ZVtdO1xuXG4gIGNvbnN0cnVjdG9yKGZlYXR1cmVHYXRlczogT3JnQ29uZmlnRmVhdHVyZUdhdGVbXSkge1xuICAgIHRoaXMuZmVhdHVyZUdhdGVzID0gZmVhdHVyZUdhdGVzO1xuICB9XG5cbiAgaXNGZWF0dXJlR2F0ZUVuYWJsZWQgPSAoZmVhdHVyZUdhdGU6IEZlYXR1cmVHYXRlcyk6IGJvb2xlYW4gPT4ge1xuICAgIGNvbnN0IGdhdGVWYWx1ZSA9IHRoaXMuZmVhdHVyZUdhdGVzLmZpbmQoXG4gICAgICAoZ2F0ZSkgPT4gZ2F0ZS5uYW1lID09PSBmZWF0dXJlR2F0ZVxuICAgICk7XG5cbiAgICAvLyBUT0RPOiBBZGQgbG9naWMgZm9yIG92ZXJyaWRlcyAocXVlcnkgcGFyYW1zLCB3aW5kb3csIHN0b3JlZCkgaWYgbmVlZGVkLCBzaW1pbGFyIHRvIHRoZSBvbGQgRmVhdHVyZUZsYWdDb250ZXh0LnRzeFxuICAgIC8vIEZvciBub3csIGRpcmVjdCB2YWx1ZSBmcm9tIGNvbmZpZyBpcyB1c2VkLlxuXG4gICAgaWYgKGdhdGVWYWx1ZSA9PSBudWxsIHx8IGdhdGVWYWx1ZS52YWx1ZSA9PSBudWxsKSB7XG4gICAgICBMb2dnZXIubG9nRGVidWcoXG4gICAgICAgIGBbc3BpZmZ5LWFpXSBpc0ZlYXR1cmVHYXRlRW5hYmxlZCBmZWF0dXJlR2F0ZToke2ZlYXR1cmVHYXRlfSB2YWx1ZSBpcyB1bmRlZmluZWQgLSByZXR1cm5pbmcgZmFsc2VgXG4gICAgICApO1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICByZXR1cm4gZ2F0ZVZhbHVlLnZhbHVlO1xuICB9O1xuXG4gIGlzQ2xpZW50U2Vzc2lvbkVuYWJsZWQgPSAoKTogYm9vbGVhbiA9PiB7XG4gICAgY29uc3QgaXNFbmFibGVkID1cbiAgICAgIHRoaXMuZmVhdHVyZUdhdGVzLmZpbHRlcihcbiAgICAgICAgKGdhdGUpID0+XG4gICAgICAgICAgZ2F0ZS5uYW1lID09PSBGZWF0dXJlR2F0ZXMuSXNDbGllbnRTZXNzaW9uRW5hYmxlZCAmJlxuICAgICAgICAgIGdhdGUudmFsdWUgPT09IHRydWVcbiAgICAgICkubGVuZ3RoID4gMDtcbiAgICByZXR1cm4gaXNFbmFibGVkO1xuICB9O1xuXG4gIGdldEZlYXR1cmVGbGFncyA9ICgpOiBSZWNvcmQ8c3RyaW5nLCBib29sZWFuPiA9PiB7XG4gICAgcmV0dXJuIE9iamVjdC5mcm9tRW50cmllcyhcbiAgICAgIE9iamVjdC52YWx1ZXMoRmVhdHVyZUdhdGVzKS5tYXAoKGZlYXR1cmVHYXRlOiBGZWF0dXJlR2F0ZXMpID0+IFtcbiAgICAgICAgZmVhdHVyZUdhdGUsXG4gICAgICAgIHRoaXMuaXNGZWF0dXJlR2F0ZUVuYWJsZWQoZmVhdHVyZUdhdGUpLFxuICAgICAgXSlcbiAgICApO1xuICB9O1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEZlYXR1cmVGbGFnQ29udGV4dFR5cGUge1xuICBmZWF0dXJlRmxhZ1NlcnZpY2U6IEZlYXR1cmVGbGFnU2VydmljZSB8IHVuZGVmaW5lZDtcbn1cblxuY29uc3QgRmVhdHVyZUZsYWdTZXJ2aWNlQ29udGV4dCA9IGNyZWF0ZUNvbnRleHQ8XG4gIEZlYXR1cmVGbGFnQ29udGV4dFR5cGUgfCB1bmRlZmluZWRcbj4odW5kZWZpbmVkKTtcblxuaW50ZXJmYWNlIEZlYXR1cmVGbGFnU2VydmljZVByb3ZpZGVyUHJvcHMge1xuICBmZWF0dXJlR2F0ZXM6IE9yZ0NvbmZpZ0ZlYXR1cmVHYXRlW107XG4gIGNoaWxkcmVuOiBSZWFjdE5vZGU7XG59XG5cbmV4cG9ydCBjb25zdCBGZWF0dXJlRmxhZ1NlcnZpY2VQcm92aWRlcjogUmVhY3QuRkM8XG4gIEZlYXR1cmVGbGFnU2VydmljZVByb3ZpZGVyUHJvcHNcbj4gPSAoeyBmZWF0dXJlR2F0ZXMsIGNoaWxkcmVuIH0pID0+IHtcbiAgY29uc3QgZmVhdHVyZUZsYWdTZXJ2aWNlID0gdXNlTWVtbyhcbiAgICAoKSA9PiBuZXcgRmVhdHVyZUZsYWdTZXJ2aWNlKGZlYXR1cmVHYXRlcyksXG4gICAgW2ZlYXR1cmVHYXRlc11cbiAgKTtcblxuICByZXR1cm4gKFxuICAgIDxGZWF0dXJlRmxhZ1NlcnZpY2VDb250ZXh0LlByb3ZpZGVyIHZhbHVlPXt7IGZlYXR1cmVGbGFnU2VydmljZSB9fT5cbiAgICAgIHtjaGlsZHJlbn1cbiAgICA8L0ZlYXR1cmVGbGFnU2VydmljZUNvbnRleHQuUHJvdmlkZXI+XG4gICk7XG59O1xuXG5leHBvcnQgY29uc3QgdXNlRmVhdHVyZUZsYWdTZXJ2aWNlID0gKCkgPT4ge1xuICBjb25zdCBjb250ZXh0ID0gdXNlQ29udGV4dChGZWF0dXJlRmxhZ1NlcnZpY2VDb250ZXh0KTtcbiAgaWYgKGNvbnRleHQgPT09IHVuZGVmaW5lZCkge1xuICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgIFwidXNlRmVhdHVyZUZsYWdTZXJ2aWNlIG11c3QgYmUgdXNlZCB3aXRoaW4gYSBGZWF0dXJlRmxhZ1NlcnZpY2VQcm92aWRlclwiXG4gICAgKTtcbiAgfVxuICByZXR1cm4gY29udGV4dDtcbn07XG4iLCJpbXBvcnQgUmVhY3QsIHtcbiAgY3JlYXRlQ29udGV4dCxcbiAgdXNlQ29udGV4dCxcbiAgUmVhY3ROb2RlLFxuICB1c2VTdGF0ZSxcbiAgdXNlRWZmZWN0LFxuICB1c2VNZW1vLFxufSBmcm9tIFwicmVhY3RcIjtcbmltcG9ydCB7IHVzZUF0b21WYWx1ZSwgdXNlU2V0QXRvbSB9IGZyb20gXCJqb3RhaVwiO1xuaW1wb3J0IHtcbiAgQmFzaWNPcmdJbmZvVHlwZSxcbiAgZ2V0T3JnSW5mbyxcbn0gZnJvbSBcInNyYy9hcHBsaWNhdGlvbi9tb2RlbHMvc3VwcG9ydGVkT3Jnc1wiO1xuaW1wb3J0IHsgdXNlQ29sb3JzQW5kRnJvbnRlbmRDb25maWcgfSBmcm9tIFwic3JjL2hvb2tzL3VzZUdyYXBoUUxDb25maWdcIjtcbmltcG9ydCB7IG9yZ1Nob3J0TmFtZUF0b20gfSBmcm9tIFwic3JjL2F0b21zL2Vudml2ZS9lbnZpdmVDb25maWdcIjtcbmltcG9ydCB7IGdldEF0b21TdG9yZSB9IGZyb20gXCJzcmMvYXRvbXMvYXRvbVN0b3JlL2F0b21TdG9yZVwiOyAvLyBJbXBvcnQgZ2V0QXRvbVN0b3JlXG5pbXBvcnQgeyBvcmdJZEF0b20gfSBmcm9tIFwic3JjL2F0b21zL29yZy9ncmFwaHFsQ29uZmlnXCI7IC8vIEltcG9ydCBuZXcgYXRvbXNcbmltcG9ydCB7IG5ld09yZ0NvbmZpZ0F0b20gfSBmcm9tIFwic3JjL2F0b21zL29yZy9uZXdPcmdDb25maWdBdG9tXCI7IC8vIEltcG9ydCBuZXdPcmdDb25maWdBdG9tXG5pbXBvcnQgeyBPcmdDb25maWdGZWF0dXJlR2F0ZSB9IGZyb20gXCJzcmMvYXBwbGljYXRpb24vbW9kZWxzL2FwaS9vcmdDb25maWdSZXN1bHRzXCI7IC8vIEltcG9ydCBPcmdDb25maWdGZWF0dXJlR2F0ZVxuaW1wb3J0IHsgRmVhdHVyZUZsYWdTZXJ2aWNlUHJvdmlkZXIgfSBmcm9tIFwic3JjL2NvbnRleHRzL2ZlYXR1cmVGbGFnU2VydmljZUNvbnRleHRcIjsgLy8gSW1wb3J0IEZlYXR1cmVGbGFnU2VydmljZVByb3ZpZGVyXG5pbXBvcnQgeyBDb2xvcnNDb25maWdSZXNwb25zZSwgRnJvbnRlbmRDb25maWdSZXNwb25zZSB9IGZyb20gXCIuL2dyYXBocWxDb250ZXh0XCI7XG5cbmV4cG9ydCBpbnRlcmZhY2UgTmV3T3JnQ29uZmlnQ29udGV4dFR5cGUge1xuICBjb21iaW5lZENvbmZpZz86XG4gICAgfCAoQmFzaWNPcmdJbmZvVHlwZSAmIHtcbiAgICAgICAgY29sb3JzQ29uZmlnPzogQ29sb3JzQ29uZmlnUmVzcG9uc2U7XG4gICAgICAgIGZyb250ZW5kQ29uZmlnPzogRnJvbnRlbmRDb25maWdSZXNwb25zZTtcbiAgICAgIH0pXG4gICAgfCBudWxsO1xuICBsb2FkaW5nOiBib29sZWFuO1xuICBlcnJvcjogRXJyb3IgfCBudWxsO1xufVxuXG5jb25zdCBOZXdPcmdDb25maWdDb250ZXh0ID0gY3JlYXRlQ29udGV4dDxOZXdPcmdDb25maWdDb250ZXh0VHlwZSB8IHVuZGVmaW5lZD4oXG4gIHVuZGVmaW5lZFxuKTtcblxuaW50ZXJmYWNlIE5ld09yZ0NvbmZpZ1Byb3ZpZGVyUHJvcHMge1xuICBjaGlsZHJlbjogUmVhY3ROb2RlO1xufVxuXG5leHBvcnQgY29uc3QgTmV3T3JnQ29uZmlnUHJvdmlkZXI6IFJlYWN0LkZDPE5ld09yZ0NvbmZpZ1Byb3ZpZGVyUHJvcHM+ID0gKHtcbiAgY2hpbGRyZW4sXG59KSA9PiB7XG4gIGNvbnN0IFtvbGRDb25maWcsIHNldE9sZENvbmZpZ10gPSB1c2VTdGF0ZTxCYXNpY09yZ0luZm9UeXBlIHwgdW5kZWZpbmVkPigpO1xuICBjb25zdCBvcmdTaG9ydE5hbWUgPSB1c2VBdG9tVmFsdWUob3JnU2hvcnROYW1lQXRvbSk7XG4gIGNvbnN0IHNldE5ld09yZ0NvbmZpZyA9IHVzZVNldEF0b20obmV3T3JnQ29uZmlnQXRvbSk7XG5cbiAgY29uc3QgeyBkYXRhOiBuZXdDb25maWcsIGxvYWRpbmcsIGVycm9yIH0gPSB1c2VDb2xvcnNBbmRGcm9udGVuZENvbmZpZygpO1xuXG4gIHVzZUVmZmVjdCgoKSA9PiB7XG4gICAgaWYgKG9yZ1Nob3J0TmFtZSkge1xuICAgICAgZ2V0T3JnSW5mbyhvcmdTaG9ydE5hbWUpLnRoZW4oc2V0T2xkQ29uZmlnKTtcbiAgICB9XG4gIH0sIFtvcmdTaG9ydE5hbWVdKTtcblxuICBjb25zdCBjb21iaW5lZENvbmZpZyA9IHVzZU1lbW8oKCkgPT4ge1xuICAgIGlmICghb2xkQ29uZmlnIHx8ICFuZXdDb25maWcpIHJldHVybiBudWxsO1xuICAgIHJldHVybiB7IC4uLm9sZENvbmZpZywgLi4ubmV3Q29uZmlnIH07XG4gIH0sIFtvbGRDb25maWcsIG5ld0NvbmZpZ10pO1xuXG4gIHVzZUVmZmVjdCgoKSA9PiB7XG4gICAgY29uc3QgYXRvbVN0b3JlID0gZ2V0QXRvbVN0b3JlKCk7XG4gICAgaWYgKGNvbWJpbmVkQ29uZmlnKSB7XG4gICAgICAvLyBUT0RPOiBSZXBsYWNlIHdpdGggYWN0dWFsIG9yZ0lkIHdoZW4gYXZhaWxhYmxlIGluIGNvbWJpbmVkQ29uZmlnXG4gICAgICBhdG9tU3RvcmUuc2V0KG9yZ0lkQXRvbSwgXCJtb2NrLW9yZy1pZFwiKTtcblxuICAgICAgc2V0TmV3T3JnQ29uZmlnKGNvbWJpbmVkQ29uZmlnKTtcbiAgICB9XG4gIH0sIFtjb21iaW5lZENvbmZpZywgc2V0TmV3T3JnQ29uZmlnXSk7XG5cbiAgY29uc3QgY29udGV4dFZhbHVlID0gdXNlTWVtbygoKSA9PiB7XG4gICAgaWYgKCFvcmdTaG9ydE5hbWUgfHwgKGxvYWRpbmcgJiYgIW9sZENvbmZpZykpIHtcbiAgICAgIHJldHVybiB7IGNvbWJpbmVkQ29uZmlnOiBudWxsLCBsb2FkaW5nOiB0cnVlLCBlcnJvcjogbnVsbCB9O1xuICAgIH1cblxuICAgIGlmIChlcnJvcikge1xuICAgICAgcmV0dXJuIHsgY29tYmluZWRDb25maWc6IG51bGwsIGxvYWRpbmc6IGZhbHNlLCBlcnJvciB9O1xuICAgIH1cblxuICAgIHJldHVybiB7IGNvbWJpbmVkQ29uZmlnLCBsb2FkaW5nOiBmYWxzZSwgZXJyb3I6IG51bGwgfTtcbiAgfSwgW29yZ1Nob3J0TmFtZSwgbG9hZGluZywgZXJyb3IsIG9sZENvbmZpZywgY29tYmluZWRDb25maWddKTtcblxuICAvLyBUT0RPOiBQcm92aWRlIGFjdHVhbCBmZWF0dXJlR2F0ZXMgd2hlbiBhdmFpbGFibGUgaW4gY29tYmluZWRDb25maWdcbiAgY29uc3QgZmVhdHVyZUdhdGVzOiBPcmdDb25maWdGZWF0dXJlR2F0ZVtdID0gW107XG5cbiAgcmV0dXJuIChcbiAgICA8TmV3T3JnQ29uZmlnQ29udGV4dC5Qcm92aWRlciB2YWx1ZT17Y29udGV4dFZhbHVlfT5cbiAgICAgIDxGZWF0dXJlRmxhZ1NlcnZpY2VQcm92aWRlciBmZWF0dXJlR2F0ZXM9e2ZlYXR1cmVHYXRlc30+XG4gICAgICAgIHtjaGlsZHJlbn1cbiAgICAgIDwvRmVhdHVyZUZsYWdTZXJ2aWNlUHJvdmlkZXI+XG4gICAgPC9OZXdPcmdDb25maWdDb250ZXh0LlByb3ZpZGVyPlxuICApO1xufTtcblxuZXhwb3J0IGNvbnN0IHVzZU5ld09yZ0NvbmZpZ0NvbnRleHQgPSAoKSA9PiB7XG4gIGNvbnN0IGNvbnRleHQgPSB1c2VDb250ZXh0KE5ld09yZ0NvbmZpZ0NvbnRleHQpO1xuICBpZiAoY29udGV4dCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgXCJ1c2VOZXdPcmdDb25maWdDb250ZXh0IG11c3QgYmUgdXNlZCB3aXRoaW4gYSBOZXdPcmdDb25maWdQcm92aWRlclwiXG4gICAgKTtcbiAgfVxuICByZXR1cm4gY29udGV4dDtcbn07XG4iLCJpbXBvcnQgeyB1c2VOZXdPcmdDb25maWdDb250ZXh0IH0gZnJvbSBcInNyYy9jb250ZXh0cy9uZXdPcmdDb25maWdDb250ZXh0XCI7XG5cbmV4cG9ydCBjb25zdCB1c2VOZXdPcmdDb25maWcgPSAoKSA9PiB7XG4gIGNvbnN0IHsgY29tYmluZWRDb25maWcsIGxvYWRpbmcsIGVycm9yIH0gPSB1c2VOZXdPcmdDb25maWdDb250ZXh0KCk7XG5cbiAgcmV0dXJuIHsgLi4uY29tYmluZWRDb25maWcsIGxvYWRpbmcsIGVycm9yIH07XG59O1xuIiwiaW1wb3J0IHtcbiAgUExQQXR0cmlidXRlQ2F0ZWdvcnksXG4gIFVzZXJFdmVudENhdGVnb3J5LFxufSBmcm9tIFwiQHNwaWZmeS1haS9jb21tZXJjZS1hcGktY2xpZW50XCI7XG5pbXBvcnQgeyBTZWFyY2hSZXN1bHQgfSBmcm9tIFwic3JjL2FwcGxpY2F0aW9uL21vZGVscy9hcGkvc2VhcmNoXCI7XG5pbXBvcnQgeyBVc2VyRXZlbnQsIFZhcmlhbnRJbmZvIH0gZnJvbSBcInNyYy9hcHBsaWNhdGlvbi9tb2RlbHNcIjtcbmltcG9ydCB7IHY0IGFzIHV1aWQgfSBmcm9tIFwidXVpZFwiO1xuXG5leHBvcnQgY29uc3QgaXNFbGVtZW50UGFydGlhbGx5VmlzaWJsZSA9IChlbD86IEhUTUxEaXZFbGVtZW50IHwgbnVsbCkgPT4ge1xuICBpZiAoIWVsKSByZXR1cm4gZmFsc2U7XG5cbiAgY29uc3QgcmVjdCA9IGVsLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICBjb25zdCB3aW5kb3dIZWlnaHQgPVxuICAgIHdpbmRvdy5pbm5lckhlaWdodCB8fCBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuY2xpZW50SGVpZ2h0O1xuICBjb25zdCB3aW5kb3dXaWR0aCA9IHdpbmRvdy5pbm5lcldpZHRoIHx8IGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5jbGllbnRXaWR0aDtcbiAgY29uc3QgdmVydGljYWxseVZpc2libGUgPVxuICAgIE1hdGgucm91bmQocmVjdC50b3ApIDwgd2luZG93SGVpZ2h0ICYmIE1hdGgucm91bmQocmVjdC5ib3R0b20pID4gMDtcbiAgY29uc3QgaG9yaXpvbnRhbGx5VmlzaWJsZSA9XG4gICAgTWF0aC5yb3VuZChyZWN0LmxlZnQpIDwgd2luZG93V2lkdGggJiYgTWF0aC5yb3VuZChyZWN0LnJpZ2h0KSA+IDA7XG4gIHJldHVybiB2ZXJ0aWNhbGx5VmlzaWJsZSAmJiBob3Jpem9udGFsbHlWaXNpYmxlO1xufTtcblxuZXhwb3J0IGNvbnN0IGNyZWF0ZUFwcExvYWRlZEV2ZW50ID0gKCk6IFVzZXJFdmVudCA9PiAoe1xuICBldmVudElkOiB1dWlkKCksXG4gIGNyZWF0ZWRBdDogbmV3IERhdGUoKS50b0lTT1N0cmluZygpLFxuICBjYXRlZ29yeTogVXNlckV2ZW50Q2F0ZWdvcnkuQXBwTG9hZGVkLFxufSk7XG5cbmV4cG9ydCBjb25zdCBjcmVhdGVWaXNpdFVzZXJFdmVudCA9ICh7XG4gIHZhcmlhbnRJbmZvLFxufToge1xuICB2YXJpYW50SW5mbzogVmFyaWFudEluZm87XG59KTogVXNlckV2ZW50IHwgdW5kZWZpbmVkID0+IHtcbiAgLy8gdGhpcyBpcyBhIHBkcCB2aXNpdCBldmVudFxuICBpZiAodmFyaWFudEluZm8udmFyaWFudCA9PT0gXCJwZHBcIiAmJiB2YXJpYW50SW5mby5wcm9kdWN0SWQgIT0gbnVsbCkge1xuICAgIHJldHVybiB7XG4gICAgICBldmVudElkOiB1dWlkKCksXG4gICAgICBjcmVhdGVkQXQ6IG5ldyBEYXRlKCkudG9JU09TdHJpbmcoKSxcbiAgICAgIGNhdGVnb3J5OiBVc2VyRXZlbnRDYXRlZ29yeS5QZHBWaXNpdCxcbiAgICAgIGF0dHJpYnV0ZXM6IHtcbiAgICAgICAgcHJvZHVjdElkOiB2YXJpYW50SW5mby5wcm9kdWN0SWQsXG4gICAgICAgIHBhcmVudFByb2R1Y3RJZDogdmFyaWFudEluZm8ucGFyZW50UHJvZHVjdElkID8/IFwiXCIsXG4gICAgICAgIHVybDogdmFyaWFudEluZm8udXJsID8/IFwiXCIsXG4gICAgICB9LFxuICAgIH07XG4gIH1cblxuICAvLyB0aGlzIGlzIGEgcGxwIHZpc2l0IGV2ZW50XG4gIGlmICh2YXJpYW50SW5mby52YXJpYW50ID09PSBcInBscFwiICYmIHZhcmlhbnRJbmZvLnBscElkICE9IG51bGwpIHtcbiAgICByZXR1cm4ge1xuICAgICAgZXZlbnRJZDogdXVpZCgpLFxuICAgICAgY3JlYXRlZEF0OiBuZXcgRGF0ZSgpLnRvSVNPU3RyaW5nKCksXG4gICAgICBjYXRlZ29yeTogVXNlckV2ZW50Q2F0ZWdvcnkuUGxwVmlzaXQsXG4gICAgICBhdHRyaWJ1dGVzOiB7XG4gICAgICAgIGNhdGVnb3J5OiBQTFBBdHRyaWJ1dGVDYXRlZ29yeS5JZCxcbiAgICAgICAgYXR0cmlidXRlczoge1xuICAgICAgICAgIGlkOiB2YXJpYW50SW5mby5wbHBJZCxcbiAgICAgICAgfSxcbiAgICAgIH0sXG4gICAgfTtcbiAgfVxuXG4gIGlmICh2YXJpYW50SW5mby52YXJpYW50ID09PSBcInBhZ2VfdmlzaXRcIikge1xuICAgIHJldHVybiB7XG4gICAgICBldmVudElkOiB1dWlkKCksXG4gICAgICBjcmVhdGVkQXQ6IG5ldyBEYXRlKCkudG9JU09TdHJpbmcoKSxcbiAgICAgIGNhdGVnb3J5OiBVc2VyRXZlbnRDYXRlZ29yeS5QYWdlVmlzaXQsXG4gICAgICBhdHRyaWJ1dGVzOiB7XG4gICAgICAgIHVybDogdmFyaWFudEluZm8udXJsLFxuICAgICAgICBwYWdlVmlzaXRDYXRlZ29yeTogdmFyaWFudEluZm8ucGFnZVZpc2l0Q2F0ZWdvcnksXG4gICAgICB9LFxuICAgIH07XG4gIH1cbiAgcmV0dXJuIHVuZGVmaW5lZDtcbn07XG5cbmNvbnN0IHBhcnNlVGltZSA9ICh0aW1lOiBzdHJpbmcsIHRpbWVab25lOiBzdHJpbmcpID0+IHtcbiAgY29uc3QgdGltZXMgPSB0aW1lLm1hdGNoKC9eKFswLTFdP1xcZCk6KFswLTVdXFxkKShBTXxQTSkkL2kpO1xuICBjb25zdCBob3VycyA9IHRpbWVzPy5bMV07XG4gIGNvbnN0IG1pbnV0ZXMgPSB0aW1lcz8uWzJdO1xuICBjb25zdCBwZXJpb2QgPSB0aW1lcz8uWzNdO1xuXG4gIGlmIChob3VycyAmJiBtaW51dGVzICYmIHBlcmlvZCkge1xuICAgIGNvbnN0IGRhdGUgPSBuZXcgRGF0ZSgpO1xuXG4gICAgLy8gQWRqdXN0IGhvdXJzIGZvciBBTS9QTVxuICAgIGxldCBhZGp1c3RlZEhvdXJzID0gMDtcbiAgICBpZiAocGVyaW9kLnRvVXBwZXJDYXNlKCkgPT09IFwiUE1cIiAmJiBob3VycyAhPT0gXCIxMlwiKSB7XG4gICAgICBhZGp1c3RlZEhvdXJzID0gcGFyc2VJbnQoaG91cnMpICsgMTI7XG4gICAgfVxuXG4gICAgaWYgKHBlcmlvZC50b1VwcGVyQ2FzZSgpID09PSBcIkFNXCIgJiYgaG91cnMgIT09IFwiMTJcIikge1xuICAgICAgYWRqdXN0ZWRIb3VycyA9IHBhcnNlSW50KGhvdXJzKTtcbiAgICB9XG5cbiAgICAvLyBDcmVhdGUgdGhlIGRhdGUgc3RyaW5nIHdpdGggdGltZSB6b25lXG4gICAgY29uc3QgZm9ybWF0dGVkRGF0ZSA9IGAke2RhdGUudG9JU09TdHJpbmcoKS5zcGxpdChcIlRcIilbMF19VCR7U3RyaW5nKFxuICAgICAgYWRqdXN0ZWRIb3Vyc1xuICAgICkucGFkU3RhcnQoMiwgXCIwXCIpfToke21pbnV0ZXN9OjAwYDtcbiAgICByZXR1cm4gbmV3IERhdGUoYCR7Zm9ybWF0dGVkRGF0ZX0ke3RpbWVab25lfWApO1xuICB9XG59O1xuXG5leHBvcnQgY29uc3QgaXNXaXRoaW5CdXNpbmVzc0hvdXJzID0gKFxuICBzdGFydFRpbWU6IHN0cmluZyxcbiAgZW5kVGltZTogc3RyaW5nLFxuICB0aW1lWm9uZTogc3RyaW5nXG4pID0+IHtcbiAgLy8gUGFyc2Ugc3RhcnQgYW5kIGVuZCB0aW1lc1xuICBjb25zdCBzdGFydCA9IHBhcnNlVGltZShzdGFydFRpbWUsIHRpbWVab25lKTtcbiAgbGV0IGVuZCA9IHBhcnNlVGltZShlbmRUaW1lLCB0aW1lWm9uZSk7XG5cbiAgaWYgKCFzdGFydCB8fCAhZW5kKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgbGV0IG5vdyA9IG5ldyBEYXRlKCk7XG5cbiAgLy8gSWYgdGhlIGVuZCBkYXRlIGlzIGdyZWF0ZXIgdGhhbiB0aGUgc3RhcnQgZGF0ZSwgYWRkIGEgZGF5IHRvIGJvdGggb2YgdGhlbVxuICAvLyBUaGlzIGhhbmRsZXMgY29uZmlndXJhdGlvbnMgc3VjaCBhcyBzdGFydFRpbWUgPSAxMDowMFBNIGFuZCBlbmRUaW1lID0gNzowMEFNXG4gIGlmIChlbmQgPCBzdGFydCkge1xuICAgIGVuZCA9IG5ldyBEYXRlKGVuZC5nZXRUaW1lKCkgKyAyNCAqIDYwICogNjAgKiAxMDAwKTtcbiAgICBub3cgPSBuZXcgRGF0ZShub3cuZ2V0VGltZSgpICsgMjQgKiA2MCAqIDYwICogMTAwMCk7XG4gIH1cblxuICAvLyBJZiB0aGUgZGF0ZSBjb252ZXJzaW9uIHNoaWZ0cyB0aGUgZW5kIGRhdGUgdG8gdGhlIG5leHQgZGF5LCBjb25zaWRlciBjb21wYXJpbmcgaXQgYWNyb3NzIG1pZG5pZ2h0XG4gIGlmIChlbmQuZ2V0VVRDRGF0ZSgpID4gc3RhcnQuZ2V0VVRDRGF0ZSgpKSB7XG4gICAgY29uc3QgY3Jvc3NpbmdNaWRuaWdodCA9IG5ldyBEYXRlKG5vdy5nZXRUaW1lKCkgKyAyNCAqIDYwICogNjAgKiAxMDAwKTtcbiAgICByZXR1cm4gc3RhcnQgPD0gbm93IHx8IGNyb3NzaW5nTWlkbmlnaHQgPD0gZW5kO1xuICB9XG5cbiAgLy8gQ2hlY2sgaWYgdGhlIGN1cnJlbnQgdGltZSBmYWxscyBiZXR3ZWVuIHN0YXJ0IGFuZCBlbmRcbiAgcmV0dXJuIG5vdyA+PSBzdGFydCAmJiBub3cgPD0gZW5kO1xufTtcblxuZXhwb3J0IGVudW0gU2VhcmNoUmVzdWx0c1N0YXRlIHtcbiAgTG9hZGluZyxcbiAgUmVzdWx0cyxcbiAgTm9SZXN1bHRzLFxufVxuXG5leHBvcnQgY29uc3QgZ2V0U2VhcmNoUmVzdWx0c1N0YXRlID0gKFxuICBpc0xvYWRpbmdTZWFyY2g6IGJvb2xlYW4sXG4gIHNlYXJjaERhdGE6IFNlYXJjaFJlc3VsdCB8IG51bGxcbik6IFNlYXJjaFJlc3VsdHNTdGF0ZSA9PiB7XG4gIGlmIChpc0xvYWRpbmdTZWFyY2gpIHtcbiAgICByZXR1cm4gU2VhcmNoUmVzdWx0c1N0YXRlLkxvYWRpbmc7XG4gIH1cbiAgaWYgKHNlYXJjaERhdGEpIHtcbiAgICByZXR1cm4gU2VhcmNoUmVzdWx0c1N0YXRlLlJlc3VsdHM7XG4gIH1cbiAgcmV0dXJuIFNlYXJjaFJlc3VsdHNTdGF0ZS5Ob1Jlc3VsdHM7XG59O1xuIiwiaW1wb3J0IHsgdXNlQXRvbSwgdXNlQXRvbVZhbHVlLCB1c2VTZXRBdG9tIH0gZnJvbSBcImpvdGFpXCI7XG5pbXBvcnQgeyB1c2VDYWxsYmFjaywgdXNlRWZmZWN0LCB1c2VNZW1vLCB1c2VSZWYsIHVzZVN0YXRlIH0gZnJvbSBcInJlYWN0XCI7XG5pbXBvcnQgeyB1c2VEZWJvdW5jZSB9IGZyb20gXCJzcmMvaG9va3MvdXNlRGVib3VuY2VcIjtcbmltcG9ydCB7IHVzZU5ld09yZ0NvbmZpZywgdXNlVHJhY2tDb21wb25lbnRWaXNpYmxlRXZlbnQgfSBmcm9tIFwic3JjL2hvb2tzXCI7XG5pbXBvcnQge1xuICBhZGRTZWFyY2hGaWx0ZXJBdG9tLFxuICBjbGVhclNlYXJjaEZpbHRlcnNBdG9tLFxuICBjcmVhdGVGaWx0ZXJPcHRpb24sXG4gIGZpbHRlcmVkU2VhcmNoUHJvZHVjdHNBdG9tLFxuICBwZXJmb3JtU2VhcmNoQXRvbSxcbiAgcmVtb3ZlU2VhcmNoRmlsdGVyQXRvbSxcbiAgc2VhcmNoQXRvbSxcbiAgc2VhcmNoRmlsdGVyc0F0b20sXG4gIHNlYXJjaFBhcmFtc0F0b20sXG4gIHNlYXJjaFByb2R1Y3RTb3J0aW5nQXRvbSxcbiAgc2VhcmNoU2VsZWN0ZWRGaWx0ZXJzQXRvbSxcbiAgU2VsZWN0ZWRGaWx0ZXJPcHRpb24sXG59IGZyb20gXCJzcmMvYXRvbXMvc2VhcmNoXCI7XG5pbXBvcnQge1xuICBhdXRvY29tcGxldGVTdGF0ZUF0b20sXG4gIGlzRmlsdGVyT3BlbkF0b20sXG59IGZyb20gXCJzcmMvYXRvbXMvZ2xvYmFsU2VhcmNoL2dsb2JhbFNlYXJjaFwiO1xuaW1wb3J0IHsgZm9ybWF0RmlsdGVyRGlzcGxheU5hbWUgfSBmcm9tIFwic3JjL2F0b21zL3NlYXJjaC91dGlsc1wiO1xuaW1wb3J0IHsgUHJvZHVjdFNvcnRpbmcgfSBmcm9tIFwic3JjL2F0b21zL3NlYXJjaC90eXBlc1wiO1xuaW1wb3J0IHtcbiAgU3BpZmZ5TWV0cmljc0V2ZW50TmFtZSxcbiAgdXNlQW1wbGl0dWRlLFxufSBmcm9tIFwic3JjL2NvbnRleHRzL2FtcGxpdHVkZUNvbnRleHRcIjtcbmltcG9ydCB7IFNwaWZmeVdpZGdldHMgfSBmcm9tIFwic3JjL2FwcGxpY2F0aW9uL21vZGVscy9zcGlmZnlXaWRnZXRzXCI7XG5pbXBvcnQgeyBQcm9kdWN0Q2FyZENvbmZpZyB9IGZyb20gXCJzcmMvY29udGV4dHMvdHlwZXNcIjtcbmltcG9ydCBMb2dnZXIgZnJvbSBcInNyYy9hcHBsaWNhdGlvbi9sb2dnaW5nL2xvZ2dlclwiO1xuaW1wb3J0IHsgU2VhcmNoUmVzdWx0IH0gZnJvbSBcInNyYy9hcHBsaWNhdGlvbi9tb2RlbHMvYXBpL3NlYXJjaFwiO1xuaW1wb3J0IHsgU2VhcmNoUmVzcG9uc2VQcm9kdWN0IH0gZnJvbSBcIkBzcGlmZnktYWkvY29tbWVyY2UtYXBpLWNsaWVudFwiO1xuaW1wb3J0IHtcbiAgU2VhcmNoRmlsdGVyRGF0dW0sXG4gIFNlbGVjdEZpbHRlckl0ZW0sXG59IGZyb20gXCJzcmMvdHlwZXMvc2VhcmNoLWZpbHRlci10eXBlc1wiO1xuaW1wb3J0IHsgZ2V0U2VhcmNoUmVzdWx0c1N0YXRlLCBTZWFyY2hSZXN1bHRzU3RhdGUgfSBmcm9tIFwiLi91dGlsc1wiO1xuaW1wb3J0IHsgb3JnU2hvcnROYW1lQXRvbSB9IGZyb20gXCJzcmMvYXRvbXMvZW52aXZlL2Vudml2ZUNvbmZpZ1wiO1xuXG5leHBvcnQgaW50ZXJmYWNlIFNlYXJjaFJlc3VsdHNIb2NQcm9wcyB7XG4gIC8vIERhdGFcbiAgc2VhcmNoRGF0YTogU2VhcmNoUmVzdWx0IHwgbnVsbDtcbiAgc2VhcmNoUmVzcG9uc2VJZDogc3RyaW5nO1xuICBtZXJjaGFudFNob3J0TmFtZTogc3RyaW5nO1xuICBwcm9kdWN0Q2FyZENvbmZpZzogUHJvZHVjdENhcmRDb25maWc7XG4gIHByb2R1Y3RMaXN0OiBTZWFyY2hSZXNwb25zZVByb2R1Y3RbXTtcbiAgYXV0b2NvbXBsZXRlUmVzdWx0czogc3RyaW5nW107XG4gIHNlYXJjaEZpbHRlcnM6IFNlYXJjaEZpbHRlckRhdHVtW107XG4gIGF2YWlsYWJsZUR5bmFtaWNGaWx0ZXJzOiB7IG5hbWU6IHN0cmluZzsgZGlzcGxheU5hbWU6IHN0cmluZyB9W107XG4gIHNlbGVjdGVkRmlsdGVyT3B0aW9uczogU2VsZWN0ZWRGaWx0ZXJPcHRpb25bXTtcblxuICAvLyBTdGF0ZVxuICBzZWFyY2hUZXh0OiBzdHJpbmc7XG4gIHNlYXJjaFJlc3VsdHNTdGF0ZTogU2VhcmNoUmVzdWx0c1N0YXRlO1xuICBpc0xvYWRpbmdBdXRvY29tcGxldGU6IGJvb2xlYW47XG4gIGlzTG9hZGluZ1NlYXJjaDogYm9vbGVhbjtcbiAgaXNGaWx0ZXJPcGVuOiBib29sZWFuO1xuICBpc0RpcnR5OiBib29sZWFuO1xuICBmb2N1c2VkSW5kZXg6IG51bWJlcjtcbiAgZm9jdXNlZE9wdGlvbklkOiBzdHJpbmcgfCB1bmRlZmluZWQ7XG5cbiAgLy8gVUlcbiAgZmlsdGVyQnV0dG9uVGV4dDogc3RyaW5nO1xuXG4gIC8vIEV2ZW50IEhhbmRsZXJzXG4gIG9uU2VhcmNoSW5wdXRDaGFuZ2U6ICh2YWx1ZTogc3RyaW5nKSA9PiB2b2lkO1xuICBvblN1Ym1pdFNlYXJjaDogKCkgPT4gdm9pZDtcbiAgb25BdXRvY29tcGxldGVTZWxlY3Q6IChzdWdnZXN0aW9uOiBzdHJpbmcpID0+IHZvaWQ7XG4gIG9uS2V5RG93bjogKGV2ZW50OiBSZWFjdC5LZXlib2FyZEV2ZW50PEhUTUxJbnB1dEVsZW1lbnQ+KSA9PiB2b2lkO1xuICBvblRvZ2dsZUR5bmFtaWNGaWx0ZXI6ICh7XG4gICAgZmlsdGVyLFxuICAgIGR5bmFtaWNGaWx0ZXJEaXNwbGF5TmFtZSxcbiAgfToge1xuICAgIGZpbHRlcjogc3RyaW5nO1xuICAgIGR5bmFtaWNGaWx0ZXJEaXNwbGF5TmFtZTogc3RyaW5nO1xuICB9KSA9PiB2b2lkO1xuICBvblNlbGVjdEZpbHRlckl0ZW06IFNlbGVjdEZpbHRlckl0ZW07XG4gIG9uUmVtb3ZlRmlsdGVyOiAoZmlsdGVyOiBTZWxlY3RlZEZpbHRlck9wdGlvbikgPT4gdm9pZDtcbiAgb25DbGVhckFsbEZpbHRlcnM6ICgpID0+IHZvaWQ7XG4gIHNldElzRmlsdGVyT3BlbjogKGlzRmlsdGVyT3BlbjogYm9vbGVhbikgPT4gdm9pZDtcblxuICAvLyBSZWZzXG4gIHNlYXJjaFJlc3VsdHNSZWY6IFJlYWN0LlJlZk9iamVjdDxIVE1MRGl2RWxlbWVudD47XG59XG5cbmV4cG9ydCBjb25zdCB1c2VTZWFyY2ggPSAoKTogU2VhcmNoUmVzdWx0c0hvY1Byb3BzID0+IHtcbiAgLy8gQXRvbXNcbiAgY29uc3QgY29uZmlnID0gdXNlTmV3T3JnQ29uZmlnKCk7XG4gIGNvbnN0IG9yZ1Nob3J0TmFtZSA9IHVzZUF0b21WYWx1ZShvcmdTaG9ydE5hbWVBdG9tKTtcbiAgY29uc3QgeyBkYXRhOiBzZWFyY2hEYXRhLCBsb2FkaW5nOiBpc0xvYWRpbmdTZWFyY2ggfSA9XG4gICAgdXNlQXRvbVZhbHVlKHNlYXJjaEF0b20pO1xuICBjb25zdCBwcm9kdWN0TGlzdCA9IHVzZUF0b21WYWx1ZShmaWx0ZXJlZFNlYXJjaFByb2R1Y3RzQXRvbSk7XG4gIGNvbnN0IHBlcmZvcm1TZWFyY2ggPSB1c2VTZXRBdG9tKHBlcmZvcm1TZWFyY2hBdG9tKTtcbiAgY29uc3QgW1xuICAgIHsgcmVzdWx0czogYXV0b2NvbXBsZXRlUmVzdWx0cywgaXNMb2FkaW5nOiBpc0xvYWRpbmdBdXRvY29tcGxldGUgfSxcbiAgICBzZXRBdXRvY29tcGxldGVTdGF0ZSxcbiAgXSA9IHVzZUF0b20oYXV0b2NvbXBsZXRlU3RhdGVBdG9tKTtcbiAgY29uc3QgW3sgcXVlcnkgfV0gPSB1c2VBdG9tKHNlYXJjaFBhcmFtc0F0b20pO1xuICBjb25zdCBbaXNGaWx0ZXJPcGVuLCBzZXRJc0ZpbHRlck9wZW5dID0gdXNlQXRvbShpc0ZpbHRlck9wZW5BdG9tKTtcbiAgY29uc3QgW3NlbGVjdGVkRmlsdGVyT3B0aW9uc10gPSB1c2VBdG9tKHNlYXJjaFNlbGVjdGVkRmlsdGVyc0F0b20pO1xuICBjb25zdCBhZGRGaWx0ZXIgPSB1c2VTZXRBdG9tKGFkZFNlYXJjaEZpbHRlckF0b20pO1xuICBjb25zdCByZW1vdmVGaWx0ZXIgPSB1c2VTZXRBdG9tKHJlbW92ZVNlYXJjaEZpbHRlckF0b20pO1xuICBjb25zdCBbcHJvZHVjdFNvcnRpbmcsIHNldFByb2R1Y3RTb3J0aW5nXSA9IHVzZUF0b20oc2VhcmNoUHJvZHVjdFNvcnRpbmdBdG9tKTtcbiAgY29uc3QgY2xlYXJGaWx0ZXJzID0gdXNlU2V0QXRvbShjbGVhclNlYXJjaEZpbHRlcnNBdG9tKTtcbiAgY29uc3Qgc2VhcmNoRmlsdGVycyA9IHVzZUF0b21WYWx1ZShzZWFyY2hGaWx0ZXJzQXRvbSk7XG5cbiAgLy8gU3RhdGVcbiAgY29uc3QgW2lzRGlydHksIHNldElzRGlydHldID0gdXNlU3RhdGUodHJ1ZSk7XG4gIGNvbnN0IFtmb2N1c2VkSW5kZXgsIHNldEZvY3VzZWRJbmRleF0gPSB1c2VTdGF0ZSgtMSk7XG4gIGNvbnN0IFtmb2N1c2VkT3B0aW9uSWQsIHNldEZvY3VzZWRPcHRpb25JZF0gPSB1c2VTdGF0ZTxzdHJpbmcgfCB1bmRlZmluZWQ+KFxuICAgIHVuZGVmaW5lZFxuICApO1xuICBjb25zdCBbc2VhcmNoVGV4dCwgc2V0U2VhcmNoVGV4dF0gPSB1c2VTdGF0ZShxdWVyeSB8fCBcIlwiKTtcblxuICAvLyBSZWZzXG4gIGNvbnN0IHNlYXJjaFJlc3VsdHNSZWYgPSB1c2VSZWY8SFRNTERpdkVsZW1lbnQ+KG51bGwpO1xuXG4gIC8vIERlcml2ZWQgU3RhdGVcbiAgY29uc3QgZGVib3VuY2VkU2VhcmNoVGV4dCA9IHVzZURlYm91bmNlKHNlYXJjaFRleHQsIDIwMCk7XG4gIGNvbnN0IHNlYXJjaFJlc3VsdHNTdGF0ZSA9IGdldFNlYXJjaFJlc3VsdHNTdGF0ZShpc0xvYWRpbmdTZWFyY2gsIHNlYXJjaERhdGEpO1xuXG4gIGNvbnN0IGR5bmFtaWNGaWx0ZXJzID0gc2VhcmNoRGF0YT8uZmlsdGVycyB8fCBbXTtcblxuICAvLyBQcm92aWRlIGZhbGxiYWNrIHZhbHVlcyB3aGVuIG9yZ1VJQ29uZmlnIGlzIG5vdCB5ZXQgYXZhaWxhYmxlXG4gIGNvbnN0IHNhZmVQcm9kdWN0Q2FyZENvbmZpZyA9IGNvbmZpZz8uZnJvbnRlbmRDb25maWc/LnVpQ29uZmlnc1xuICAgID8ucHJvZHVjdENhcmRDb25maWcgfHwge1xuICAgIHZhcmlhbnQ6IFwibWluaW1hbFwiLFxuICAgIGhvdmVyVmFyaWFudDogXCJub25lXCIsXG4gICAgbGF5b3V0VmFyaWFudDogXCJzcXVhcmVcIixcbiAgfTtcbiAgY29uc3Qgc2FmZU1lcmNoYW50U2hvcnROYW1lID0gb3JnU2hvcnROYW1lIHx8IFwiXCI7XG5cbiAgY29uc3QgYXZhaWxhYmxlRHluYW1pY0ZpbHRlcnMgPSB1c2VNZW1vKCgpID0+IHtcbiAgICByZXR1cm4gZHluYW1pY0ZpbHRlcnNcbiAgICAgIC5maWx0ZXIoXG4gICAgICAgIChkeW5hbWljRmlsdGVyTmFtZSkgPT5cbiAgICAgICAgICAhc2VsZWN0ZWRGaWx0ZXJPcHRpb25zLnNvbWUoXG4gICAgICAgICAgICAob3B0aW9uKSA9PiBvcHRpb24uaWQgPT09IGBkeW5hbWljOiR7ZHluYW1pY0ZpbHRlck5hbWV9YFxuICAgICAgICAgIClcbiAgICAgIClcbiAgICAgIC5tYXAoKGR5bmFtaWNGaWx0ZXJOYW1lKSA9PiAoe1xuICAgICAgICBuYW1lOiBkeW5hbWljRmlsdGVyTmFtZSxcbiAgICAgICAgZGlzcGxheU5hbWU6IGZvcm1hdEZpbHRlckRpc3BsYXlOYW1lKGR5bmFtaWNGaWx0ZXJOYW1lKSxcbiAgICAgIH0pKTtcbiAgfSwgW2R5bmFtaWNGaWx0ZXJzLCBzZWxlY3RlZEZpbHRlck9wdGlvbnNdKTtcblxuICBjb25zdCBmaWx0ZXJzID0gdXNlTWVtbygoKSA9PiB7XG4gICAgY29uc3Qgc29ydE9wdGlvbnMgPSBbXG4gICAgICB7XG4gICAgICAgIGZpbHRlckl0ZW1JZDogU3RyaW5nKFByb2R1Y3RTb3J0aW5nLkZFQVRVUkVEKSxcbiAgICAgICAgZGlzcGxheU5hbWU6IFwiUmVsZXZhbmNlXCIsXG4gICAgICAgIHByb2R1Y3RDb3VudDogMCxcbiAgICAgICAgaXNTZWxlY3RlZDogcHJvZHVjdFNvcnRpbmcgPT09IFByb2R1Y3RTb3J0aW5nLkZFQVRVUkVELFxuICAgICAgfSxcbiAgICAgIHtcbiAgICAgICAgZmlsdGVySXRlbUlkOiBTdHJpbmcoUHJvZHVjdFNvcnRpbmcuUFJJQ0VfQVNDKSxcbiAgICAgICAgZGlzcGxheU5hbWU6IFwiUHJpY2U6IExvdyB0byBIaWdoXCIsXG4gICAgICAgIHByb2R1Y3RDb3VudDogMCxcbiAgICAgICAgaXNTZWxlY3RlZDogcHJvZHVjdFNvcnRpbmcgPT09IFByb2R1Y3RTb3J0aW5nLlBSSUNFX0FTQyxcbiAgICAgIH0sXG4gICAgICB7XG4gICAgICAgIGZpbHRlckl0ZW1JZDogU3RyaW5nKFByb2R1Y3RTb3J0aW5nLlBSSUNFX0RFU0MpLFxuICAgICAgICBkaXNwbGF5TmFtZTogXCJQcmljZTogSGlnaCB0byBMb3dcIixcbiAgICAgICAgcHJvZHVjdENvdW50OiAwLFxuICAgICAgICBpc1NlbGVjdGVkOiBwcm9kdWN0U29ydGluZyA9PT0gUHJvZHVjdFNvcnRpbmcuUFJJQ0VfREVTQyxcbiAgICAgIH0sXG4gICAgXTtcblxuICAgIHJldHVybiBbXG4gICAgICB7IGZpbHRlcklkOiBcInNvcnRcIiwgZGlzcGxheU5hbWU6IFwiU09SVFwiLCBpdGVtczogc29ydE9wdGlvbnMgfSxcbiAgICAgIC4uLnNlYXJjaEZpbHRlcnMsXG4gICAgXSBhcyBTZWFyY2hGaWx0ZXJEYXR1bVtdO1xuICB9LCBbcHJvZHVjdFNvcnRpbmcsIHNlYXJjaEZpbHRlcnNdKTtcblxuICBjb25zdCBmaWx0ZXJCdXR0b25UZXh0ID0gdXNlTWVtbygoKSA9PiB7XG4gICAgY29uc3Qgc2VsZWN0ZWRDb3VudCA9IGZpbHRlcnMucmVkdWNlKChhY2M6IG51bWJlciwgZmlsdGVyKSA9PiB7XG4gICAgICBpZiAoZmlsdGVyLmZpbHRlcklkID09PSBcInNvcnRcIikge1xuICAgICAgICByZXR1cm4gYWNjO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGFjYyArIGZpbHRlci5pdGVtcy5maWx0ZXIoKGl0ZW0pID0+IGl0ZW0uaXNTZWxlY3RlZCkubGVuZ3RoO1xuICAgIH0sIDApO1xuICAgIGlmIChzZWxlY3RlZENvdW50ID09PSAwKSB7XG4gICAgICByZXR1cm4gXCJGaWx0ZXIgJiBTb3J0XCI7XG4gICAgfVxuICAgIHJldHVybiBgRmlsdGVyICYgU29ydCAoJHtzZWxlY3RlZENvdW50fSlgO1xuICB9LCBbZmlsdGVyc10pO1xuXG4gIC8vIENhbGxiYWNrc1xuICBjb25zdCB7IHRyYWNrRXZlbnQgfSA9IHVzZUFtcGxpdHVkZSgpO1xuXG4gIGNvbnN0IGhhbmRsZVRvZ2dsZUR5bmFtaWNGaWx0ZXIgPSB1c2VDYWxsYmFjayhcbiAgICAoe1xuICAgICAgZmlsdGVyLFxuICAgICAgZHluYW1pY0ZpbHRlckRpc3BsYXlOYW1lLFxuICAgIH06IHtcbiAgICAgIGZpbHRlcjogc3RyaW5nO1xuICAgICAgZHluYW1pY0ZpbHRlckRpc3BsYXlOYW1lOiBzdHJpbmc7XG4gICAgfSkgPT4ge1xuICAgICAgdHJhY2tFdmVudCh7XG4gICAgICAgIGV2ZW50TmFtZTogU3BpZmZ5TWV0cmljc0V2ZW50TmFtZS5TZWFyY2hGaWx0ZXJDbGlja2VkLFxuICAgICAgICBldmVudFByb3BzOiB7XG4gICAgICAgICAgZmlsdGVyVHlwZTogXCJEeW5hbWljXCIsXG4gICAgICAgICAgZmlsdGVyVmFsdWU6IGZpbHRlcixcbiAgICAgICAgICBxdWVyeVRleHQ6IHNlYXJjaFRleHQsXG4gICAgICAgIH0sXG4gICAgICB9KTtcbiAgICAgIGFkZEZpbHRlcihcbiAgICAgICAgY3JlYXRlRmlsdGVyT3B0aW9uKFwiZHluYW1pY1wiLCBmaWx0ZXIsIGR5bmFtaWNGaWx0ZXJEaXNwbGF5TmFtZSlcbiAgICAgICk7XG4gICAgfSxcbiAgICBbYWRkRmlsdGVyLCBzZWFyY2hUZXh0LCB0cmFja0V2ZW50XVxuICApO1xuXG4gIGNvbnN0IGhhbmRsZVJlbW92ZUZpbHRlciA9IHVzZUNhbGxiYWNrKFxuICAgIChmaWx0ZXI6IFNlbGVjdGVkRmlsdGVyT3B0aW9uKSA9PiB7XG4gICAgICByZW1vdmVGaWx0ZXIoZmlsdGVyLmlkKTtcbiAgICB9LFxuICAgIFtyZW1vdmVGaWx0ZXJdXG4gICk7XG5cbiAgY29uc3QgaGFuZGxlU3VibWl0U2VhcmNoID0gdXNlQ2FsbGJhY2soYXN5bmMgKCkgPT4ge1xuICAgIGlmIChzZWFyY2hUZXh0LnRyaW0oKSkge1xuICAgICAgdHJhY2tFdmVudCh7XG4gICAgICAgIGV2ZW50TmFtZTogU3BpZmZ5TWV0cmljc0V2ZW50TmFtZS5TZWFyY2hRdWVyeVN1Ym1pdHRlZCxcbiAgICAgICAgZXZlbnRQcm9wczoge1xuICAgICAgICAgIHNlYXJjaE9yaWdpbjogU3BpZmZ5V2lkZ2V0cy5TZWFyY2hSZXN1bHRzLFxuICAgICAgICAgIHF1ZXJ5VGV4dDogc2VhcmNoVGV4dC50cmltKCksXG4gICAgICAgIH0sXG4gICAgICAgIGFsc29TZW5kVG9Hb29nbGVBbmFseXRpY3M6IHRydWUsXG4gICAgICB9KTtcbiAgICAgIGNvbnN0IHVybCA9IG5ldyBVUkwod2luZG93LmxvY2F0aW9uLmhyZWYpO1xuICAgICAgdXJsLnNlYXJjaFBhcmFtcy5zZXQoXCJlc3FcIiwgc2VhcmNoVGV4dC50cmltKCkpO1xuICAgICAgd2luZG93Lmhpc3RvcnkucHVzaFN0YXRlKHt9LCBcIlwiLCB1cmwpO1xuICAgICAgcGVyZm9ybVNlYXJjaCh7IHF1ZXJ5OiBzZWFyY2hUZXh0LnRyaW0oKSB9KTtcbiAgICB9XG4gIH0sIFtwZXJmb3JtU2VhcmNoLCBzZWFyY2hUZXh0LCB0cmFja0V2ZW50XSk7XG5cbiAgY29uc3QgaGFuZGxlQXV0b2NvbXBsZXRlU2VsZWN0ID0gdXNlQ2FsbGJhY2soXG4gICAgKHN1Z2dlc3Rpb246IHN0cmluZykgPT4ge1xuICAgICAgc2V0U2VhcmNoVGV4dChzdWdnZXN0aW9uKTtcbiAgICAgIGhhbmRsZVN1Ym1pdFNlYXJjaCgpO1xuICAgIH0sXG4gICAgW2hhbmRsZVN1Ym1pdFNlYXJjaCwgc2V0U2VhcmNoVGV4dF1cbiAgKTtcblxuICBjb25zdCBoYW5kbGVLZXlEb3duID0gdXNlQ2FsbGJhY2soXG4gICAgKGV2ZW50OiBSZWFjdC5LZXlib2FyZEV2ZW50PEhUTUxJbnB1dEVsZW1lbnQ+KSA9PiB7XG4gICAgICBpZiAoZXZlbnQua2V5ID09PSBcIkFycm93RG93blwiKSB7XG4gICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIGNvbnN0IG5ld0luZGV4ID0gKGZvY3VzZWRJbmRleCArIDEpICUgYXV0b2NvbXBsZXRlUmVzdWx0cy5sZW5ndGg7XG4gICAgICAgIHNldEZvY3VzZWRJbmRleChuZXdJbmRleCk7XG4gICAgICAgIHNldEZvY3VzZWRPcHRpb25JZChgb3B0aW9uLSR7bmV3SW5kZXh9YCk7XG4gICAgICB9IGVsc2UgaWYgKGV2ZW50LmtleSA9PT0gXCJBcnJvd1VwXCIpIHtcbiAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgY29uc3QgbmV3SW5kZXggPVxuICAgICAgICAgIChmb2N1c2VkSW5kZXggLSAxICsgYXV0b2NvbXBsZXRlUmVzdWx0cy5sZW5ndGgpICVcbiAgICAgICAgICBhdXRvY29tcGxldGVSZXN1bHRzLmxlbmd0aDtcbiAgICAgICAgc2V0Rm9jdXNlZEluZGV4KG5ld0luZGV4KTtcbiAgICAgICAgc2V0Rm9jdXNlZE9wdGlvbklkKGBvcHRpb24tJHtuZXdJbmRleH1gKTtcbiAgICAgIH0gZWxzZSBpZiAoZXZlbnQua2V5ID09PSBcIkVudGVyXCIpIHtcbiAgICAgICAgaWYgKGZvY3VzZWRJbmRleCA9PT0gLTEpIHtcbiAgICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgIGhhbmRsZVN1Ym1pdFNlYXJjaCgpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgY29uc3Qgc3VnZ2VzdGlvblRleHQgPSBhdXRvY29tcGxldGVSZXN1bHRzW2ZvY3VzZWRJbmRleF07XG4gICAgICAgICAgaGFuZGxlQXV0b2NvbXBsZXRlU2VsZWN0KHN1Z2dlc3Rpb25UZXh0KTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmIChldmVudC5rZXkgPT09IFwiRXNjYXBlXCIpIHtcbiAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgc2V0Rm9jdXNlZEluZGV4KC0xKTtcbiAgICAgICAgc2V0Rm9jdXNlZE9wdGlvbklkKHVuZGVmaW5lZCk7XG4gICAgICB9XG4gICAgfSxcbiAgICBbXG4gICAgICBhdXRvY29tcGxldGVSZXN1bHRzLFxuICAgICAgZm9jdXNlZEluZGV4LFxuICAgICAgaGFuZGxlQXV0b2NvbXBsZXRlU2VsZWN0LFxuICAgICAgaGFuZGxlU3VibWl0U2VhcmNoLFxuICAgIF1cbiAgKTtcblxuICBjb25zdCBoYW5kbGVTZWFyY2hJbnB1dENoYW5nZSA9IChuZXdWYWx1ZTogc3RyaW5nKSA9PiB7XG4gICAgaWYgKG5ld1ZhbHVlLmxlbmd0aCA9PT0gMSkge1xuICAgICAgdHJhY2tFdmVudCh7XG4gICAgICAgIGV2ZW50TmFtZTogU3BpZmZ5TWV0cmljc0V2ZW50TmFtZS5TZWFyY2hJbnB1dFN0YXJ0ZWQsXG4gICAgICAgIGV2ZW50UHJvcHM6IHtcbiAgICAgICAgICBzZWFyY2hPcmlnaW46IFNwaWZmeVdpZGdldHMuU2VhcmNoUmVzdWx0cyxcbiAgICAgICAgfSxcbiAgICAgIH0pO1xuICAgIH1cbiAgICBzZXRTZWFyY2hUZXh0KG5ld1ZhbHVlKTtcbiAgICBzZXRJc0RpcnR5KHRydWUpO1xuICB9O1xuXG4gIGNvbnN0IGhhbmRsZVNlbGVjdEZpbHRlckl0ZW06IFNlbGVjdEZpbHRlckl0ZW0gPSB1c2VDYWxsYmFjayhcbiAgICAoe1xuICAgICAgZmlsdGVySWQsXG4gICAgICBmaWx0ZXJJdGVtSWQsXG4gICAgICBpc1NlbGVjdGVkLFxuICAgICAgZGlzcGxheU5hbWUsXG4gICAgfToge1xuICAgICAgZmlsdGVySWQ6IHN0cmluZztcbiAgICAgIGZpbHRlckl0ZW1JZDogc3RyaW5nO1xuICAgICAgaXNTZWxlY3RlZDogYm9vbGVhbjtcbiAgICAgIGRpc3BsYXlOYW1lOiBzdHJpbmc7XG4gICAgfSkgPT4ge1xuICAgICAgaWYgKGZpbHRlcklkID09PSBcInNvcnRcIikge1xuICAgICAgICBjb25zdCBuZXdTb3J0ID0gZmlsdGVySXRlbUlkIGFzIFByb2R1Y3RTb3J0aW5nO1xuICAgICAgICB0cmFja0V2ZW50KHtcbiAgICAgICAgICBldmVudE5hbWU6IFNwaWZmeU1ldHJpY3NFdmVudE5hbWUuU2VhcmNoU29ydENsaWNrZWQsXG4gICAgICAgICAgZXZlbnRQcm9wczoge1xuICAgICAgICAgICAgc29ydFR5cGU6IG5ld1NvcnQsXG4gICAgICAgICAgICBxdWVyeVRleHQ6IHNlYXJjaFRleHQsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSk7XG4gICAgICAgIHNldFByb2R1Y3RTb3J0aW5nKG5ld1NvcnQpO1xuICAgICAgfSBlbHNlIGlmICghaXNTZWxlY3RlZCkge1xuICAgICAgICByZW1vdmVGaWx0ZXIoYCR7ZmlsdGVySWR9OiR7ZmlsdGVySXRlbUlkfWApO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdHJhY2tFdmVudCh7XG4gICAgICAgICAgZXZlbnROYW1lOiBTcGlmZnlNZXRyaWNzRXZlbnROYW1lLlNlYXJjaEZpbHRlckNsaWNrZWQsXG4gICAgICAgICAgZXZlbnRQcm9wczoge1xuICAgICAgICAgICAgZmlsdGVyVHlwZTogXCJTdGF0aWNcIixcbiAgICAgICAgICAgIGZpbHRlckNhdGVnb3J5OiBmaWx0ZXJJZCxcbiAgICAgICAgICAgIGZpbHRlclZhbHVlOiBmaWx0ZXJJdGVtSWQsXG4gICAgICAgICAgICBxdWVyeVRleHQ6IHNlYXJjaFRleHQsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSk7XG4gICAgICAgIGFkZEZpbHRlcihjcmVhdGVGaWx0ZXJPcHRpb24oZmlsdGVySWQsIGZpbHRlckl0ZW1JZCwgZGlzcGxheU5hbWUpKTtcbiAgICAgIH1cbiAgICB9LFxuICAgIFthZGRGaWx0ZXIsIHJlbW92ZUZpbHRlciwgc2V0UHJvZHVjdFNvcnRpbmcsIHNlYXJjaFRleHQsIHRyYWNrRXZlbnRdXG4gICk7XG5cbiAgY29uc3QgaGFuZGxlQ2xlYXJBbGxGaWx0ZXJzID0gdXNlQ2FsbGJhY2soKCkgPT4ge1xuICAgIHNldFByb2R1Y3RTb3J0aW5nKFByb2R1Y3RTb3J0aW5nLkZFQVRVUkVEKTtcbiAgICBjbGVhckZpbHRlcnMoKTtcbiAgfSwgW3NldFByb2R1Y3RTb3J0aW5nLCBjbGVhckZpbHRlcnNdKTtcblxuICAvLyBTaWRlIEVmZmVjdHNcbiAgdXNlVHJhY2tDb21wb25lbnRWaXNpYmxlRXZlbnQoXG4gICAgU3BpZmZ5V2lkZ2V0cy5TZWFyY2hSZXN1bHRzLFxuICAgIHNlYXJjaFJlc3VsdHNSZWYsXG4gICAge30sXG4gICAgU3BpZmZ5TWV0cmljc0V2ZW50TmFtZS5TZWFyY2hDb21wb25lbnRWaXNpYmxlXG4gICk7XG5cbiAgdXNlRWZmZWN0KCgpID0+IHtcbiAgICBpZiAocHJvZHVjdExpc3QubGVuZ3RoID4gMCkge1xuICAgICAgdHJhY2tFdmVudCh7XG4gICAgICAgIGV2ZW50TmFtZTogU3BpZmZ5TWV0cmljc0V2ZW50TmFtZS5TZWFyY2hSZXN1bHRzVmlld2VkLFxuICAgICAgICBldmVudFByb3BzOiB7XG4gICAgICAgICAgcXVlcnlUZXh0OiBzZWFyY2hUZXh0LFxuICAgICAgICAgIHJlc3VsdHNDb3VudDogcHJvZHVjdExpc3QubGVuZ3RoLFxuICAgICAgICB9LFxuICAgICAgfSk7XG4gICAgfVxuICB9LCBbcHJvZHVjdExpc3QubGVuZ3RoLCBzZWFyY2hUZXh0LCB0cmFja0V2ZW50XSk7XG5cbiAgdXNlRWZmZWN0KCgpID0+IHtcbiAgICBpZiAocXVlcnkgJiYgcXVlcnkgIT09IHNlYXJjaFRleHQpIHtcbiAgICAgIHNldFNlYXJjaFRleHQocXVlcnkpO1xuICAgIH1cbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgcmVhY3QtaG9va3MvZXhoYXVzdGl2ZS1kZXBzXG4gIH0sIFtxdWVyeV0pO1xuXG4gIHVzZUVmZmVjdCgoKSA9PiB7XG4gICAgY29uc3QgZXNxID0gbmV3IFVSTFNlYXJjaFBhcmFtcyh3aW5kb3cubG9jYXRpb24uc2VhcmNoKS5nZXQoXCJlc3FcIik7XG4gICAgaWYgKGVzcSkge1xuICAgICAgc2V0U2VhcmNoVGV4dChlc3EpO1xuICAgICAgcGVyZm9ybVNlYXJjaCh7IHF1ZXJ5OiBlc3EgfSk7XG4gICAgfVxuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSByZWFjdC1ob29rcy9leGhhdXN0aXZlLWRlcHNcbiAgfSwgW3BlcmZvcm1TZWFyY2hdKTtcblxuICBjb25zdCBmZXRjaEF1dG9jb21wbGV0ZVN1Z2dlc3Rpb25zID0gKF9xdWVyeTogc3RyaW5nKSA9PiB7XG4gICAgLy8gVE9ETzogaW1wbGVtZW50IGF1dG9jb21wbGV0ZSBzdWdnZXN0aW9uc1xuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoW10pO1xuICB9O1xuXG4gIHVzZUVmZmVjdCgoKSA9PiB7XG4gICAgaWYgKGZldGNoQXV0b2NvbXBsZXRlU3VnZ2VzdGlvbnMgPT09IHVuZGVmaW5lZCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmICghaXNEaXJ0eSB8fCBkZWJvdW5jZWRTZWFyY2hUZXh0Lmxlbmd0aCA8PSAyKSB7XG4gICAgICBzZXRBdXRvY29tcGxldGVTdGF0ZSh7IHJlc3VsdHM6IFtdLCBpc0xvYWRpbmc6IGZhbHNlIH0pO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHNldEF1dG9jb21wbGV0ZVN0YXRlKChwcmV2KSA9PiAoeyAuLi5wcmV2LCBpc0xvYWRpbmc6IHRydWUgfSkpO1xuXG4gICAgY29uc3QgZmV0Y2hEYXRhID0gYXN5bmMgKCkgPT4ge1xuICAgICAgdHJ5IHtcbiAgICAgICAgY29uc3QgcmVzdWx0cyA9IGF3YWl0IGZldGNoQXV0b2NvbXBsZXRlU3VnZ2VzdGlvbnM/LihcbiAgICAgICAgICBkZWJvdW5jZWRTZWFyY2hUZXh0XG4gICAgICAgICk7XG4gICAgICAgIHNldEF1dG9jb21wbGV0ZVN0YXRlKHsgcmVzdWx0czogcmVzdWx0cyA/PyBbXSwgaXNMb2FkaW5nOiBmYWxzZSB9KTtcbiAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgIExvZ2dlci5sb2dFcnJvcihcIkZhaWxlZCB0byBmZXRjaCBhdXRvY29tcGxldGUgc3VnZ2VzdGlvbnM6XCIsIGVycm9yKTtcbiAgICAgICAgc2V0QXV0b2NvbXBsZXRlU3RhdGUoeyByZXN1bHRzOiBbXSwgaXNMb2FkaW5nOiBmYWxzZSB9KTtcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgZmV0Y2hEYXRhKCk7XG4gIH0sIFtkZWJvdW5jZWRTZWFyY2hUZXh0LCBpc0RpcnR5LCBzZXRBdXRvY29tcGxldGVTdGF0ZV0pO1xuXG4gIHJldHVybiB7XG4gICAgc2VhcmNoRGF0YSxcbiAgICBzZWFyY2hSZXNwb25zZUlkOiBzZWFyY2hEYXRhPy5zZWFyY2hSZXNwb25zZUlkID8/IFwiXCIsXG4gICAgbWVyY2hhbnRTaG9ydE5hbWU6IHNhZmVNZXJjaGFudFNob3J0TmFtZSxcbiAgICBwcm9kdWN0Q2FyZENvbmZpZzogc2FmZVByb2R1Y3RDYXJkQ29uZmlnLFxuICAgIHByb2R1Y3RMaXN0LFxuICAgIGF1dG9jb21wbGV0ZVJlc3VsdHMsXG4gICAgc2VhcmNoRmlsdGVyczogZmlsdGVycyxcbiAgICBhdmFpbGFibGVEeW5hbWljRmlsdGVycyxcbiAgICBzZWxlY3RlZEZpbHRlck9wdGlvbnMsXG4gICAgc2VhcmNoVGV4dCxcbiAgICBzZWFyY2hSZXN1bHRzU3RhdGUsXG4gICAgaXNMb2FkaW5nQXV0b2NvbXBsZXRlLFxuICAgIGlzTG9hZGluZ1NlYXJjaCxcbiAgICBpc0ZpbHRlck9wZW4sXG4gICAgaXNEaXJ0eSxcbiAgICBmb2N1c2VkSW5kZXgsXG4gICAgZm9jdXNlZE9wdGlvbklkLFxuICAgIGZpbHRlckJ1dHRvblRleHQsXG4gICAgb25TZWFyY2hJbnB1dENoYW5nZTogaGFuZGxlU2VhcmNoSW5wdXRDaGFuZ2UsXG4gICAgb25TdWJtaXRTZWFyY2g6IGhhbmRsZVN1Ym1pdFNlYXJjaCxcbiAgICBvbkF1dG9jb21wbGV0ZVNlbGVjdDogaGFuZGxlQXV0b2NvbXBsZXRlU2VsZWN0LFxuICAgIG9uS2V5RG93bjogaGFuZGxlS2V5RG93bixcbiAgICBvblRvZ2dsZUR5bmFtaWNGaWx0ZXI6IGhhbmRsZVRvZ2dsZUR5bmFtaWNGaWx0ZXIsXG4gICAgb25TZWxlY3RGaWx0ZXJJdGVtOiBoYW5kbGVTZWxlY3RGaWx0ZXJJdGVtLFxuICAgIG9uUmVtb3ZlRmlsdGVyOiBoYW5kbGVSZW1vdmVGaWx0ZXIsXG4gICAgb25DbGVhckFsbEZpbHRlcnM6IGhhbmRsZUNsZWFyQWxsRmlsdGVycyxcbiAgICBzZXRJc0ZpbHRlck9wZW4sXG4gICAgc2VhcmNoUmVzdWx0c1JlZixcbiAgfTtcbn07XG4iLCJpbXBvcnQgeyB1c2VBdG9tVmFsdWUgfSBmcm9tIFwiam90YWlcIjtcbmltcG9ydCB7XG4gIENvbnRleHRFbnZFbnVtLFxuICBDb250ZXh0U291cmNlRW51bSxcbn0gZnJvbSBcIkBzcGlmZnktYWkvY29tbWVyY2UtYXBpLWNsaWVudFwiO1xuaW1wb3J0IHsgVmFyaWFudEluZm8gfSBmcm9tIFwic3JjL2FwcGxpY2F0aW9uL21vZGVsc1wiO1xuaW1wb3J0IHsgVXNlcklkZW50aXR5Q29udGV4dFR5cGUgfSBmcm9tIFwic3JjL2NvbnRleHRzL3VzZXJJZGVudGl0eUNvbnRleHRcIjtcbmltcG9ydCB7IHZhcmlhbnRJbmZvQXRvbSB9IGZyb20gXCJzcmMvYXRvbXMvYXBwL3ZhcmlhbnRcIjtcbmltcG9ydCB7XG4gIGNvbnRleHRTb3VyY2VBdG9tLFxuICBlbnZBdG9tIGFzIGVudml2ZUVudkF0b20sXG4gIG9yZ1Nob3J0TmFtZUF0b20gYXMgZW52aXZlT3JnU2hvcnROYW1lQXRvbSxcbn0gZnJvbSBcInNyYy9hdG9tcy9lbnZpdmUvZW52aXZlQ29uZmlnXCI7XG5pbXBvcnQgeyBjaGF0SWRBdG9tLCB1c2VySWRBdG9tIH0gZnJvbSBcInNyYy9hdG9tcy9hcHAvaW5kZXhcIjtcbmltcG9ydCB7IHVzZU5ld09yZ0NvbmZpZ0NvbnRleHQgfSBmcm9tIFwic3JjL2NvbnRleHRzL25ld09yZ0NvbmZpZ0NvbnRleHRcIjtcbmltcG9ydCB7IHVzZU9yZ0lkIH0gZnJvbSBcInNyYy9ob29rcy91c2VHcmFwaFFMQ29uZmlnXCI7IC8vIEltcG9ydCB1c2VPcmdJZFxuXG5leHBvcnQgaW50ZXJmYWNlIEFwcERldGFpbHMge1xuICBvcmdJZDogc3RyaW5nO1xuICBvcmdTaG9ydE5hbWU6IHN0cmluZztcbiAgY2hhdElkOiBzdHJpbmc7XG4gIHVzZXJJZDogc3RyaW5nO1xuICBzb3VyY2U6IENvbnRleHRTb3VyY2VFbnVtO1xuICBlbnY6IENvbnRleHRFbnZFbnVtO1xuICB2YXJpYW50SW5mbzogVmFyaWFudEluZm87XG59XG5cbmV4cG9ydCBjb25zdCB1c2VBcHBEZXRhaWxzID0gKCk6IEFwcERldGFpbHMgPT4ge1xuICBjb25zdCB7IG9yZ0lkOiBmZXRjaGVkT3JnSWQgfSA9IHVzZU9yZ0lkKCk7IC8vIEdldCBvcmdJZCBmcm9tIHVzZU9yZ0lkIGhvb2tcbiAgY29uc3Qgb3JnSWQgPSBmZXRjaGVkT3JnSWQgPz8gXCJcIjsgLy8gUHJvdmlkZSBhIGRlZmF1bHQgZW1wdHkgc3RyaW5nIGlmIHVuZGVmaW5lZFxuXG4gIGNvbnN0IG9yZ1Nob3J0TmFtZSA9IHVzZUF0b21WYWx1ZShlbnZpdmVPcmdTaG9ydE5hbWVBdG9tKSA/PyBcInNwaWZmeS1haVwiO1xuICBjb25zdCBjaGF0SWQgPSB1c2VBdG9tVmFsdWUoY2hhdElkQXRvbSk7XG4gIGNvbnN0IHVzZXJJZCA9IHVzZUF0b21WYWx1ZSh1c2VySWRBdG9tKTtcbiAgY29uc3Qgc291cmNlID0gdXNlQXRvbVZhbHVlKGNvbnRleHRTb3VyY2VBdG9tKSA/PyBDb250ZXh0U291cmNlRW51bS5BcHA7XG4gIGNvbnN0IGVudiA9XG4gICAgKHVzZUF0b21WYWx1ZShlbnZpdmVFbnZBdG9tKSBhcyBDb250ZXh0RW52RW51bSkgPz8gQ29udGV4dEVudkVudW0uRGV2OyAvLyBDYXN0IHRvIENvbnRleHRFbnZFbnVtXG4gIGNvbnN0IHZhcmlhbnRJbmZvID0gdXNlQXRvbVZhbHVlKHZhcmlhbnRJbmZvQXRvbSk7XG5cbiAgcmV0dXJuIHtcbiAgICBvcmdJZCxcbiAgICBvcmdTaG9ydE5hbWUsXG4gICAgY2hhdElkLFxuICAgIHVzZXJJZCxcbiAgICBzb3VyY2UsXG4gICAgZW52LFxuICAgIHZhcmlhbnRJbmZvLFxuICB9O1xufTtcbiIsImltcG9ydCBSZWFjdCwge1xuICBjcmVhdGVDb250ZXh0LFxuICB1c2VDb250ZXh0LFxuICB1c2VDYWxsYmFjayxcbiAgdXNlTWVtbyxcbiAgdXNlRWZmZWN0LFxufSBmcm9tIFwicmVhY3RcIjtcbmltcG9ydCB7IHVzZUF0b21WYWx1ZSB9IGZyb20gXCJqb3RhaVwiO1xuaW1wb3J0IHtcbiAgQ29uZmlndXJhdGlvbixcbiAgUmVzcG9uc2VDYXRlZ29yeSxcbiAgUmVzcG9uc2VFcnJvcixcbiAgU2VhcmNoQXBpLFxufSBmcm9tIFwiQHNwaWZmeS1haS9jb21tZXJjZS1hcGktY2xpZW50XCI7XG5pbXBvcnQgeyBiYXNlVXJsQXRvbSB9IGZyb20gXCJzcmMvYXRvbXMvZW52aXZlL2Vudml2ZUNvbmZpZ1wiO1xuaW1wb3J0IExvZ2dlciBmcm9tIFwic3JjL2FwcGxpY2F0aW9uL2xvZ2dpbmcvbG9nZ2VyXCI7XG5pbXBvcnQgeyB1c2VBcHBEZXRhaWxzIH0gZnJvbSBcInNyYy9ob29rcy91c2VBcHBEZXRhaWxzXCI7XG5pbXBvcnQgeyB1c2VFbnZpdmVDb25maWcgfSBmcm9tIFwic3JjL2NvbnRleHRzL2Vudml2ZUNvbmZpZ0NvbnRleHRcIjtcbmltcG9ydCB7IFNlc3Npb25SZXN0YXJ0UmVxdWlyZWQgfSBmcm9tIFwic3JjL3R5cGVzL2V4Y2VwdGlvbnMvc2Vzc2lvbkV4Y2VwdGlvbnNcIjtcbmltcG9ydCB7IFVuc3VwcG9ydGVkUHJvZHVjdEV4Y2VwdGlvbiB9IGZyb20gXCJzcmMvdHlwZXMvZXhjZXB0aW9ucy91bnN1cHBvcnRlZFByb2R1Y3RFeGNlcHRpb25zXCI7XG5pbXBvcnQgeyBTZWFyY2hSZXN1bHQsIFNlYXJjaFBhcmFtcyB9IGZyb20gXCIuLi9hcHBsaWNhdGlvbi9tb2RlbHMvYXBpL3NlYXJjaFwiO1xuaW1wb3J0IHtcbiAgc2V0U2VhcmNoU2VydmljZUZ1bmN0aW9uLFxuICBjbGVhclNlYXJjaFNlcnZpY2VGdW5jdGlvbixcbn0gZnJvbSBcIi4uL2F0b21zL3NlYXJjaC9zZWFyY2hTZXJ2aWNlQWRhcHRlclwiO1xuXG5jb25zdCB0cmFuc2Zvcm1Qcm9kdWN0UmVzcG9uc2VzID0gKHByb2R1Y3RzOiBTZWFyY2hSZXN1bHRbXCJwcm9kdWN0c1wiXSkgPT5cbiAgcHJvZHVjdHMubWFwKChkYXRhKSA9PiAoe1xuICAgIGlkOiBkYXRhLmlkLFxuICAgIHJlc3BvbnNlSWQ6IGRhdGEucmVzcG9uc2VfaWQsXG4gICAgY2F0ZWdvcnk6IFJlc3BvbnNlQ2F0ZWdvcnkuUHJvZHVjdCxcbiAgICBkZXNjcmlwdGlvbjogZGF0YS5kZXNjcmlwdGlvbixcbiAgICBpbWFnZVVybDogZGF0YS5pbWFnZV91cmwsXG4gICAgaW1hZ2VVcmxzOiBkYXRhLmltYWdlX3VybHMsXG4gICAgdGl0bGU6IGRhdGEudGl0bGUsXG4gICAgdXJsOiBkYXRhLnVybCxcbiAgICBvcmlnaW5hbFByaWNlOiBkYXRhLm9yaWdpbmFsX3ByaWNlLFxuICAgIHNhbGVQcmljZTogZGF0YS5zYWxlX3ByaWNlLFxuICAgIGF2ZXJhZ2VSYXRpbmc6IGRhdGEuYXZlcmFnZV9yYXRpbmcsXG4gICAgbnVtYmVyUmV2aWV3czogZGF0YS5udW1iZXJfcmV2aWV3cyxcbiAgICBtZXRhZGF0YTogZGF0YS5tZXRhZGF0YSxcbiAgICBpc0ZvckdyaWQ6IGRhdGEuaXNfZm9yX2dyaWQsXG4gICAgY29sb3JzOiBkYXRhLmNvbG9ycyxcbiAgICBzaXplczogZGF0YS5zaXplcyxcbiAgICBmaWx0ZXJzOiBkYXRhLmZpbHRlcnMsXG4gIH0pKTtcblxuYXN5bmMgZnVuY3Rpb24gZXJyb3JSZXNwb25zZUJvZHkoZXJyb3I6IFJlc3BvbnNlRXJyb3IpIHtcbiAgdHJ5IHtcbiAgICByZXR1cm4gYXdhaXQgZXJyb3IucmVzcG9uc2UuanNvbigpO1xuICB9IGNhdGNoIHtcbiAgICByZXR1cm4ge307XG4gIH1cbn1cblxuYXN5bmMgZnVuY3Rpb24gdGhyb3dTZXNzaW9uUmVzdGFydFJlcXVpcmVkSWYoZXJyb3JNc2c6IHN0cmluZywgZXJyb3I6IHVua25vd24pIHtcbiAgaWYgKCEoZXJyb3IgaW5zdGFuY2VvZiBSZXNwb25zZUVycm9yKSkge1xuICAgIExvZ2dlci5sb2dJbmZvKGVycm9yTXNnLCBlcnJvcik7XG4gICAgdGhyb3cgZXJyb3I7XG4gIH1cblxuICBjb25zdCBlcnJvclJlc3BvbnNlID0gYXdhaXQgZXJyb3JSZXNwb25zZUJvZHkoZXJyb3IpO1xuICBpZiAoXG4gICAgZXJyb3JSZXNwb25zZT8ubWVzc2FnZT8udG9Mb3dlckNhc2UoKSA9PT0gXCJ1bnN1cHBvcnRlZCBwcm9kdWN0XCIgfHxcbiAgICBlcnJvclJlc3BvbnNlPy5hcHBfY29kZT8udG9VcHBlckNhc2UoKSA9PT0gXCJQUk9EVUNUX05PVF9GT1VORFwiXG4gICkge1xuICAgIHRocm93IG5ldyBVbnN1cHBvcnRlZFByb2R1Y3RFeGNlcHRpb24oKTtcbiAgfSBlbHNlIGlmIChcbiAgICBlcnJvclJlc3BvbnNlPy5hcHBfY29kZT8udG9VcHBlckNhc2UoKSA9PT0gXCJSRVNUQVJUX1NFU1NJT05cIiB8fFxuICAgIGVycm9yUmVzcG9uc2U/LnN1Yl9jb2RlPy50b1VwcGVyQ2FzZSgpID09PSBcIk5PVF9GT1VORFwiXG4gICkge1xuICAgIExvZ2dlci5sb2dJbmZvKFxuICAgICAgXCJTZXNzaW9uIGRvZXMgbm90IGV4aXN0LiBSZS1zdGFydCBzZXNzaW9uXCIsXG4gICAgICBlcnJvcixcbiAgICAgIGVycm9yLnJlc3BvbnNlLFxuICAgICAgZXJyb3JSZXNwb25zZVxuICAgICk7XG4gICAgdGhyb3cgbmV3IFNlc3Npb25SZXN0YXJ0UmVxdWlyZWQoKTtcbiAgfVxuXG4gIExvZ2dlci5sb2dJbmZvKGVycm9yTXNnLCBlcnJvcik7XG4gIHRocm93IGVycm9yO1xufVxuXG5pbnRlcmZhY2UgU2VhcmNoQ29udGV4dFZhbHVlIHtcbiAgc2VhcmNoUHJvZHVjdHM6IChwYXJhbXM6IFNlYXJjaFBhcmFtcykgPT4gUHJvbWlzZTxTZWFyY2hSZXN1bHQ+O1xuICBpc1JlYWR5OiBib29sZWFuO1xufVxuXG5jb25zdCBTZWFyY2hDb250ZXh0ID0gY3JlYXRlQ29udGV4dDxTZWFyY2hDb250ZXh0VmFsdWUgfCB1bmRlZmluZWQ+KHVuZGVmaW5lZCk7XG5cbmV4cG9ydCBjb25zdCBTZWFyY2hQcm92aWRlcjogUmVhY3QuRkM8eyBjaGlsZHJlbjogUmVhY3QuUmVhY3ROb2RlIH0+ID0gKHtcbiAgY2hpbGRyZW4sXG59KSA9PiB7XG4gIGNvbnN0IHsgb3JnTGV2ZWxBcGlLZXksIHB1YmxpY0tleSB9ID0gdXNlRW52aXZlQ29uZmlnKCk7XG4gIGNvbnN0IGFwaUtleSA9IG9yZ0xldmVsQXBpS2V5IHx8IHB1YmxpY0tleTsgLy8gUmVwbGljYXRlIGFwaUtleUF0b20gbG9naWNcbiAgY29uc3QgYXBwRGV0YWlscyA9IHVzZUFwcERldGFpbHMoKTtcbiAgY29uc3QgYmFzZVVybCA9IHVzZUF0b21WYWx1ZShiYXNlVXJsQXRvbSk7XG5cbiAgY29uc3QgaXNSZWFkeSA9IEJvb2xlYW4oYXBpS2V5ICYmIGFwcERldGFpbHMgJiYgYmFzZVVybCk7XG5cbiAgY29uc3Qgc2VhcmNoQXBpID0gdXNlTWVtbygoKSA9PiB7XG4gICAgaWYgKCFpc1JlYWR5KSByZXR1cm4gbnVsbDtcblxuICAgIGNvbnN0IGNvbmZpZzogQ29uZmlndXJhdGlvbiA9IG5ldyBDb25maWd1cmF0aW9uKHtcbiAgICAgIGFjY2Vzc1Rva2VuOiBhcGlLZXksXG4gICAgICBiYXNlUGF0aDogYmFzZVVybCxcbiAgICAgIGhlYWRlcnM6IHtcbiAgICAgICAgXCJDb250ZW50LVR5cGVcIjogXCJhcHBsaWNhdGlvbi9qc29uXCIsXG4gICAgICAgIEFjY2VwdDogXCJhcHBsaWNhdGlvbi9qc29uXCIsXG4gICAgICB9LFxuICAgIH0pO1xuICAgIHJldHVybiBuZXcgU2VhcmNoQXBpKGNvbmZpZyk7XG4gIH0sIFthcGlLZXksIGJhc2VVcmwsIGlzUmVhZHldKTtcblxuICBjb25zdCBzZWFyY2hQcm9kdWN0cyA9IHVzZUNhbGxiYWNrKFxuICAgIGFzeW5jIChwYXJhbXM6IFNlYXJjaFBhcmFtcyk6IFByb21pc2U8U2VhcmNoUmVzdWx0PiA9PiB7XG4gICAgICBpZiAoIWlzUmVhZHkgfHwgIXNlYXJjaEFwaSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJTZWFyY2hTZXJ2aWNlIG5vdCByZWFkeSAtIG1pc3NpbmcgZGVwZW5kZW5jaWVzXCIpO1xuICAgICAgfVxuXG4gICAgICB0cnkge1xuICAgICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHNlYXJjaEFwaS52MVNlYXJjaFF1ZXJ5R2V0KHtcbiAgICAgICAgICBxdWVyeTogcGFyYW1zLnF1ZXJ5LFxuICAgICAgICAgIGxpbWl0OiBwYXJhbXMubGltaXQsXG4gICAgICAgICAgb3JnX2lkOiBhcHBEZXRhaWxzLm9yZ0lkLFxuICAgICAgICAgIHVzZXJfaWQ6IGFwcERldGFpbHMudXNlcklkLFxuICAgICAgICB9KTtcbiAgICAgICAgY29uc3Qge1xuICAgICAgICAgIHByb2R1Y3RzLFxuICAgICAgICAgIGZpbHRlcnMsXG4gICAgICAgICAgc2VhcmNoX3Jlc3BvbnNlX2lkOiBzZWFyY2hSZXNwb25zZUlkLFxuICAgICAgICB9ID0gcmVzcG9uc2U7XG5cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBwcm9kdWN0czogdHJhbnNmb3JtUHJvZHVjdFJlc3BvbnNlcyhwcm9kdWN0cykgfHwgW10sXG4gICAgICAgICAgZmlsdGVyczogZmlsdGVycyB8fCBbXSxcbiAgICAgICAgICB0b3RhbFByb2R1Y3RDb3VudDogcHJvZHVjdHM/Lmxlbmd0aCB8fCAwLFxuICAgICAgICAgIHNlYXJjaFJlc3BvbnNlSWQ6IHNlYXJjaFJlc3BvbnNlSWQgfHwgXCJcIixcbiAgICAgICAgfTtcbiAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgIGF3YWl0IHRocm93U2Vzc2lvblJlc3RhcnRSZXF1aXJlZElmKFwiRmFpbGVkIHRvIHNlYXJjaCBwcm9kdWN0c1wiLCBlcnJvcik7XG4gICAgICAgIC8vIFRoaXMgcGFydCB3aWxsIG5vdCBiZSByZWFjaGVkIGlmIGFuIGV4Y2VwdGlvbiBpcyB0aHJvd24sIGJ1dCBpdCdzIHJlcXVpcmVkIGZvciB0eXBlIHNhZmV0eVxuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIHByb2R1Y3RzOiBbXSxcbiAgICAgICAgICBmaWx0ZXJzOiBbXSxcbiAgICAgICAgICB0b3RhbFByb2R1Y3RDb3VudDogMCxcbiAgICAgICAgICBzZWFyY2hSZXNwb25zZUlkOiBcIlwiLFxuICAgICAgICB9O1xuICAgICAgfVxuICAgIH0sXG4gICAgW3NlYXJjaEFwaSwgaXNSZWFkeSwgYXBwRGV0YWlsc11cbiAgKTtcblxuICAvLyBSZWdpc3RlciB0aGUgc2VhcmNoIGZ1bmN0aW9uIHdpdGggdGhlIGFkYXB0ZXIgZm9yIHVzZSBpbiBhdG9tc1xuICB1c2VFZmZlY3QoKCkgPT4ge1xuICAgIGlmIChpc1JlYWR5KSB7XG4gICAgICBzZXRTZWFyY2hTZXJ2aWNlRnVuY3Rpb24oc2VhcmNoUHJvZHVjdHMpO1xuICAgIH0gZWxzZSB7XG4gICAgICBjbGVhclNlYXJjaFNlcnZpY2VGdW5jdGlvbigpO1xuICAgIH1cblxuICAgIHJldHVybiAoKSA9PiB7XG4gICAgICBjbGVhclNlYXJjaFNlcnZpY2VGdW5jdGlvbigpO1xuICAgIH07XG4gIH0sIFtzZWFyY2hQcm9kdWN0cywgaXNSZWFkeV0pO1xuXG4gIGNvbnN0IHZhbHVlID0gdXNlTWVtbyhcbiAgICAoKSA9PiAoe1xuICAgICAgc2VhcmNoUHJvZHVjdHMsXG4gICAgICBpc1JlYWR5LFxuICAgIH0pLFxuICAgIFtzZWFyY2hQcm9kdWN0cywgaXNSZWFkeV1cbiAgKTtcblxuICByZXR1cm4gKFxuICAgIDxTZWFyY2hDb250ZXh0LlByb3ZpZGVyIHZhbHVlPXt2YWx1ZX0+e2NoaWxkcmVufTwvU2VhcmNoQ29udGV4dC5Qcm92aWRlcj5cbiAgKTtcbn07XG5cbmV4cG9ydCBjb25zdCB1c2VTZWFyY2hTZXJ2aWNlID0gKCkgPT4ge1xuICBjb25zdCBjb250ZXh0ID0gdXNlQ29udGV4dChTZWFyY2hDb250ZXh0KTtcbiAgaWYgKCFjb250ZXh0KSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFwidXNlU2VhcmNoU2VydmljZSBtdXN0IGJlIHVzZWQgd2l0aGluIGEgU2VhcmNoUHJvdmlkZXJcIik7XG4gIH1cbiAgcmV0dXJuIGNvbnRleHQ7XG59O1xuIiwiaW1wb3J0IHsgdXNlU3RhdGUsIHVzZUNhbGxiYWNrLCB1c2VFZmZlY3QgfSBmcm9tIFwicmVhY3RcIjtcbmltcG9ydCB7IHVzZVNlYXJjaFNlcnZpY2UgfSBmcm9tIFwic3JjL2NvbnRleHRzL3NlYXJjaENvbnRleHRcIjtcbmltcG9ydCB7IFNlYXJjaFJlc3VsdCwgU2VhcmNoUGFyYW1zIH0gZnJvbSBcInNyYy9hcHBsaWNhdGlvbi9tb2RlbHMvYXBpL3NlYXJjaFwiO1xuXG5leHBvcnQgY29uc3QgdXNlUHJvZHVjdFNlYXJjaCA9ICgpID0+IHtcbiAgY29uc3QgeyBzZWFyY2hQcm9kdWN0cywgaXNSZWFkeSB9ID0gdXNlU2VhcmNoU2VydmljZSgpO1xuICBjb25zdCBbZGF0YSwgc2V0RGF0YV0gPSB1c2VTdGF0ZTxTZWFyY2hSZXN1bHQgfCB1bmRlZmluZWQ+KCk7XG4gIGNvbnN0IFtsb2FkaW5nLCBzZXRMb2FkaW5nXSA9IHVzZVN0YXRlKGZhbHNlKTtcbiAgY29uc3QgW2Vycm9yLCBzZXRFcnJvcl0gPSB1c2VTdGF0ZTxFcnJvciB8IG51bGw+KG51bGwpO1xuXG4gIGNvbnN0IHNlYXJjaCA9IHVzZUNhbGxiYWNrKFxuICAgIGFzeW5jIChwYXJhbXM6IFNlYXJjaFBhcmFtcykgPT4ge1xuICAgICAgaWYgKCFpc1JlYWR5KSB7XG4gICAgICAgIHNldEVycm9yKG5ldyBFcnJvcihcIlNlYXJjaCBzZXJ2aWNlIG5vdCByZWFkeSAtIG1pc3NpbmcgZGVwZW5kZW5jaWVzXCIpKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBzZXRMb2FkaW5nKHRydWUpO1xuICAgICAgc2V0RXJyb3IobnVsbCk7XG5cbiAgICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHNlYXJjaFByb2R1Y3RzKHBhcmFtcyk7XG4gICAgICAgIHNldERhdGEocmVzdWx0KTtcbiAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICBzZXRFcnJvcihcbiAgICAgICAgICBlcnIgaW5zdGFuY2VvZiBFcnJvciA/IGVyciA6IG5ldyBFcnJvcihcIlVua25vd24gc2VhcmNoIGVycm9yXCIpXG4gICAgICAgICk7XG4gICAgICB9IGZpbmFsbHkge1xuICAgICAgICBzZXRMb2FkaW5nKGZhbHNlKTtcbiAgICAgIH1cbiAgICB9LFxuICAgIFtzZWFyY2hQcm9kdWN0cywgaXNSZWFkeV1cbiAgKTtcblxuICBjb25zdCByZXNldCA9IHVzZUNhbGxiYWNrKCgpID0+IHtcbiAgICBzZXREYXRhKHVuZGVmaW5lZCk7XG4gICAgc2V0RXJyb3IobnVsbCk7XG4gICAgc2V0TG9hZGluZyhmYWxzZSk7XG4gIH0sIFtdKTtcblxuICByZXR1cm4ge1xuICAgIGRhdGEsXG4gICAgbG9hZGluZyxcbiAgICBlcnJvcixcbiAgICBzZWFyY2gsXG4gICAgcmVzZXQsXG4gICAgaXNSZWFkeSxcbiAgfTtcbn07XG5cbmV4cG9ydCBjb25zdCB1c2VTZWFyY2hXaXRoUXVlcnkgPSAocGFyYW1zOiBTZWFyY2hQYXJhbXMgfCBudWxsKSA9PiB7XG4gIGNvbnN0IHsgc2VhcmNoUHJvZHVjdHMsIGlzUmVhZHkgfSA9IHVzZVNlYXJjaFNlcnZpY2UoKTtcbiAgY29uc3QgW2RhdGEsIHNldERhdGFdID0gdXNlU3RhdGU8U2VhcmNoUmVzdWx0IHwgdW5kZWZpbmVkPigpO1xuICBjb25zdCBbbG9hZGluZywgc2V0TG9hZGluZ10gPSB1c2VTdGF0ZShmYWxzZSk7XG4gIGNvbnN0IFtlcnJvciwgc2V0RXJyb3JdID0gdXNlU3RhdGU8RXJyb3IgfCBudWxsPihudWxsKTtcblxuICBjb25zdCBleGVjdXRlU2VhcmNoID0gdXNlQ2FsbGJhY2soXG4gICAgYXN5bmMgKHNlYXJjaFBhcmFtczogU2VhcmNoUGFyYW1zKSA9PiB7XG4gICAgICBpZiAoIWlzUmVhZHkpIHJldHVybjtcblxuICAgICAgc2V0TG9hZGluZyh0cnVlKTtcbiAgICAgIHNldEVycm9yKG51bGwpO1xuXG4gICAgICB0cnkge1xuICAgICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBzZWFyY2hQcm9kdWN0cyhzZWFyY2hQYXJhbXMpO1xuICAgICAgICBzZXREYXRhKHJlc3VsdCk7XG4gICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgc2V0RXJyb3IoXG4gICAgICAgICAgZXJyIGluc3RhbmNlb2YgRXJyb3IgPyBlcnIgOiBuZXcgRXJyb3IoXCJVbmtub3duIHNlYXJjaCBlcnJvclwiKVxuICAgICAgICApO1xuICAgICAgfSBmaW5hbGx5IHtcbiAgICAgICAgc2V0TG9hZGluZyhmYWxzZSk7XG4gICAgICB9XG4gICAgfSxcbiAgICBbc2VhcmNoUHJvZHVjdHMsIGlzUmVhZHldXG4gICk7XG5cbiAgdXNlRWZmZWN0KCgpID0+IHtcbiAgICBpZiAocGFyYW1zICYmIGlzUmVhZHkpIHtcbiAgICAgIGV4ZWN1dGVTZWFyY2gocGFyYW1zKTtcbiAgICB9XG4gIH0sIFtwYXJhbXMsIGlzUmVhZHksIGV4ZWN1dGVTZWFyY2hdKTtcblxuICBjb25zdCByZWZldGNoID0gdXNlQ2FsbGJhY2soKCkgPT4ge1xuICAgIGlmIChwYXJhbXMpIHtcbiAgICAgIGV4ZWN1dGVTZWFyY2gocGFyYW1zKTtcbiAgICB9XG4gIH0sIFtwYXJhbXMsIGV4ZWN1dGVTZWFyY2hdKTtcblxuICByZXR1cm4ge1xuICAgIGRhdGEsXG4gICAgbG9hZGluZyxcbiAgICBlcnJvcixcbiAgICByZWZldGNoLFxuICAgIGlzUmVhZHksXG4gIH07XG59O1xuIiwiaW1wb3J0IFJlYWN0LCB7XG4gIGNyZWF0ZUNvbnRleHQsXG4gIHVzZUNvbnRleHQsXG4gIHVzZUNhbGxiYWNrLFxuICB1c2VNZW1vLFxuICB1c2VFZmZlY3QsXG59IGZyb20gXCJyZWFjdFwiO1xuaW1wb3J0IExvZ2dlciBmcm9tIFwiLi4vYXBwbGljYXRpb24vbG9nZ2luZy9sb2dnZXJcIjtcblxuaW50ZXJmYWNlIFNlc3Npb25TdG9yYWdlQ29udGV4dFR5cGUge1xuICBzZXRJdGVtOiAoa2V5OiBzdHJpbmcsIHZhbHVlOiBzdHJpbmcpID0+IHZvaWQ7XG4gIGdldEl0ZW06IChrZXk6IHN0cmluZykgPT4gc3RyaW5nIHwgbnVsbDtcbiAgaXNBdmFpbGFibGU6IGJvb2xlYW47XG59XG5cbmNvbnN0IFNlc3Npb25TdG9yYWdlQ29udGV4dCA9IGNyZWF0ZUNvbnRleHQ8U2Vzc2lvblN0b3JhZ2VDb250ZXh0VHlwZSB8IG51bGw+KFxuICBudWxsXG4pO1xuXG5leHBvcnQgY29uc3QgU2Vzc2lvblN0b3JhZ2VQcm92aWRlcjogUmVhY3QuRkM8e1xuICBjaGlsZHJlbjogUmVhY3QuUmVhY3ROb2RlO1xufT4gPSAoeyBjaGlsZHJlbiB9KSA9PiB7XG4gIGNvbnN0IGlzQXZhaWxhYmxlID0gdXNlTWVtbygoKSA9PiB7XG4gICAgdHJ5IHtcbiAgICAgIHJldHVybiB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiICYmICEhd2luZG93LnNlc3Npb25TdG9yYWdlO1xuICAgIH0gY2F0Y2gge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfSwgW10pO1xuXG4gIHVzZUVmZmVjdCgoKSA9PiB7XG4gICAgaWYgKCFpc0F2YWlsYWJsZSkge1xuICAgICAgTG9nZ2VyLmxvZ0Vycm9yKFwic2Vzc2lvblN0b3JhZ2UgaXMgbm90IGF2YWlsYWJsZVwiLCB1bmRlZmluZWQpO1xuICAgIH1cbiAgfSwgW2lzQXZhaWxhYmxlXSk7XG5cbiAgY29uc3Qgc2V0SXRlbSA9IHVzZUNhbGxiYWNrKFxuICAgIChrZXk6IHN0cmluZywgdmFsdWU6IHN0cmluZykgPT4ge1xuICAgICAgaWYgKCFpc0F2YWlsYWJsZSkgcmV0dXJuO1xuICAgICAgc2Vzc2lvblN0b3JhZ2Uuc2V0SXRlbShrZXksIHZhbHVlKTtcbiAgICAgIHdpbmRvdy5kaXNwYXRjaEV2ZW50KFxuICAgICAgICBuZXcgU3RvcmFnZUV2ZW50KFwic3RvcmFnZVwiLCB7IGtleSwgbmV3VmFsdWU6IHZhbHVlIH0pXG4gICAgICApO1xuICAgIH0sXG4gICAgW2lzQXZhaWxhYmxlXVxuICApO1xuXG4gIGNvbnN0IGdldEl0ZW0gPSB1c2VDYWxsYmFjayhcbiAgICAoa2V5OiBzdHJpbmcpID0+IHtcbiAgICAgIGlmICghaXNBdmFpbGFibGUpIHJldHVybiBudWxsO1xuICAgICAgcmV0dXJuIHNlc3Npb25TdG9yYWdlLmdldEl0ZW0oa2V5KTtcbiAgICB9LFxuICAgIFtpc0F2YWlsYWJsZV1cbiAgKTtcblxuICBjb25zdCB2YWx1ZSA9IHVzZU1lbW8oXG4gICAgKCkgPT4gKHtcbiAgICAgIHNldEl0ZW0sXG4gICAgICBnZXRJdGVtLFxuICAgICAgaXNBdmFpbGFibGUsXG4gICAgfSksXG4gICAgW3NldEl0ZW0sIGdldEl0ZW0sIGlzQXZhaWxhYmxlXVxuICApO1xuXG4gIHJldHVybiAoXG4gICAgPFNlc3Npb25TdG9yYWdlQ29udGV4dC5Qcm92aWRlciB2YWx1ZT17dmFsdWV9PlxuICAgICAge2NoaWxkcmVufVxuICAgIDwvU2Vzc2lvblN0b3JhZ2VDb250ZXh0LlByb3ZpZGVyPlxuICApO1xufTtcblxuZXhwb3J0IGNvbnN0IHVzZVNlc3Npb25TdG9yYWdlID0gKCkgPT4ge1xuICBjb25zdCBjb250ZXh0ID0gdXNlQ29udGV4dChTZXNzaW9uU3RvcmFnZUNvbnRleHQpO1xuICBpZiAoIWNvbnRleHQpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICBcInVzZVNlc3Npb25TdG9yYWdlIG11c3QgYmUgdXNlZCB3aXRoaW4gYSBTZXNzaW9uU3RvcmFnZVByb3ZpZGVyXCJcbiAgICApO1xuICB9XG4gIHJldHVybiBjb250ZXh0O1xufTtcbiIsImltcG9ydCB7IHVzZVN0YXRlLCB1c2VFZmZlY3QsIHVzZUNhbGxiYWNrIH0gZnJvbSBcInJlYWN0XCI7XG5pbXBvcnQgeyB1c2VTZXNzaW9uU3RvcmFnZSB9IGZyb20gXCIuLi9jb250ZXh0cy9zZXNzaW9uU3RvcmFnZUNvbnRleHRcIjtcblxuZXhwb3J0IGNvbnN0IHVzZVNlc3Npb25TdG9yYWdlVmFsdWUgPSAoa2V5OiBzdHJpbmcpID0+IHtcbiAgY29uc3QgeyBnZXRJdGVtLCBzZXRJdGVtIH0gPSB1c2VTZXNzaW9uU3RvcmFnZSgpO1xuICBjb25zdCBbdmFsdWUsIHNldFZhbHVlXSA9IHVzZVN0YXRlPHN0cmluZyB8IG51bGw+KCgpID0+IGdldEl0ZW0oa2V5KSk7XG5cbiAgdXNlRWZmZWN0KCgpID0+IHtcbiAgICBjb25zdCBoYW5kbGVTdG9yYWdlQ2hhbmdlID0gKGV2ZW50OiBTdG9yYWdlRXZlbnQpID0+IHtcbiAgICAgIGlmIChldmVudC5rZXkgPT09IGtleSkge1xuICAgICAgICBzZXRWYWx1ZShldmVudC5uZXdWYWx1ZSk7XG4gICAgICB9XG4gICAgfTtcblxuICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKFwic3RvcmFnZVwiLCBoYW5kbGVTdG9yYWdlQ2hhbmdlKTtcbiAgICByZXR1cm4gKCkgPT4gd2luZG93LnJlbW92ZUV2ZW50TGlzdGVuZXIoXCJzdG9yYWdlXCIsIGhhbmRsZVN0b3JhZ2VDaGFuZ2UpO1xuICB9LCBba2V5LCBnZXRJdGVtXSk7XG5cbiAgY29uc3QgdXBkYXRlVmFsdWUgPSB1c2VDYWxsYmFjayhcbiAgICAobmV3VmFsdWU6IHN0cmluZykgPT4ge1xuICAgICAgc2V0SXRlbShrZXksIG5ld1ZhbHVlKTtcbiAgICAgIHNldFZhbHVlKG5ld1ZhbHVlKTtcbiAgICB9LFxuICAgIFtrZXksIHNldEl0ZW1dXG4gICk7XG5cbiAgcmV0dXJuIHsgdmFsdWUsIHNldFZhbHVlOiB1cGRhdGVWYWx1ZSB9O1xufTtcbiIsImltcG9ydCBSZWFjdCwgeyBjcmVhdGVDb250ZXh0LCB1c2VDYWxsYmFjaywgdXNlQ29udGV4dCwgdXNlTWVtbyB9IGZyb20gXCJyZWFjdFwiO1xuaW1wb3J0IHsgSWRFeHRyYWN0b3IgfSBmcm9tIFwic3JjL2NvbnRleHRzL3R5cGVzXCI7XG5pbXBvcnQgeyBwYXJzZUhyZWYgfSBmcm9tIFwic3JjL2FwcGxpY2F0aW9uL3V0aWxzL3VybHNQYXJzZXJcIjtcblxuaW50ZXJmYWNlIFNob3BpZnlVcmxDb250ZXh0VHlwZSB7XG4gIGdldFRyaW1tZWRQYXRoTmFtZTogKCkgPT4gc3RyaW5nIHwgbnVsbDtcbiAgZ2V0UGxwT3JQZHBJZDogKGV4dHJhY3RvcjogSWRFeHRyYWN0b3IpID0+IHN0cmluZyB8IG51bGw7XG4gIGlzT25QZHBQYWdlOiAoKSA9PiBib29sZWFuO1xuICBpc09uUGxwUGFnZTogKCkgPT4gYm9vbGVhbjtcbiAgaXNSZWFkeTogYm9vbGVhbjtcbn1cblxuY29uc3QgU2hvcGlmeVVybENvbnRleHQgPSBjcmVhdGVDb250ZXh0PFNob3BpZnlVcmxDb250ZXh0VHlwZSB8IHVuZGVmaW5lZD4oXG4gIHVuZGVmaW5lZFxuKTtcblxuZXhwb3J0IGNvbnN0IFNob3BpZnlVcmxQcm92aWRlcjogUmVhY3QuRkM8eyBjaGlsZHJlbjogUmVhY3QuUmVhY3ROb2RlIH0+ID0gKHtcbiAgY2hpbGRyZW4sXG59KSA9PiB7XG4gIGNvbnN0IGlzUmVhZHkgPSB0cnVlOyAvLyBObyBleHRlcm5hbCBkZXBlbmRlbmNpZXMsIHNvIGFsd2F5cyByZWFkeVxuXG4gIGNvbnN0IGdldFRyaW1tZWRQYXRoTmFtZSA9IHVzZUNhbGxiYWNrKCgpOiBzdHJpbmcgfCBudWxsID0+IHtcbiAgICBsZXQgeyBwYXRobmFtZSB9ID0gd2luZG93LmxvY2F0aW9uO1xuICAgIC8vIHN0cmlwIG91dCB0aGUgcHJveHkgcGF0aCBzbyBsb2NhbCBkZXYgc3RpbGwgd29ya3NcbiAgICBwYXRobmFtZSA9IHBhdGhuYW1lLnJlcGxhY2UoXCIvcHJveHlcIiwgXCJcIik7XG4gICAgLy8gcmVtb3ZlIHRyYWlsaW5nIGhhc2ggaWYgaXQgZXhpc3RzXG4gICAgcGF0aG5hbWUgPSBwYXRobmFtZS5yZXBsYWNlKC8jLiokLywgXCJcIik7XG4gICAgLy8gcmVtb3ZlIHRyYWlsaW5nIC8sIGllLiBzb21lIFVSTHMgY2FuIGVuZCB3aXRoICcvJyBsaWtlIC9jb2xsZWN0aW9ucy9jYXN0LWlyb24vXG4gICAgcGF0aG5hbWUgPSBwYXRobmFtZS5yZXBsYWNlKC9cXC8kLywgXCJcIik7XG5cbiAgICBpZiAocGF0aG5hbWUgPT09IHVuZGVmaW5lZCB8fCBwYXRobmFtZSA9PT0gbnVsbCB8fCBwYXRobmFtZS5sZW5ndGggPT09IDApIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIHJldHVybiBwYXRobmFtZTtcbiAgfSwgW10pO1xuXG4gIGNvbnN0IGdldFBscE9yUGRwSWQgPSB1c2VDYWxsYmFjayhcbiAgICAoZXh0cmFjdG9yOiBJZEV4dHJhY3Rvcik6IHN0cmluZyB8IG51bGwgPT4ge1xuICAgICAgaWYgKGV4dHJhY3RvciA9PT0gXCJzaG9waWZ5LXByb2R1Y3QtdmFyaWFudC1pZFwiKSB7XG4gICAgICAgIGNvbnN0IHBhcnNlZEhyZWYgPSBwYXJzZUhyZWYod2luZG93LmxvY2F0aW9uLmhyZWYpO1xuICAgICAgICBjb25zdCB2YXJpYW50SWQgPSBwYXJzZWRIcmVmPy51cmxTZWFyY2hQYXJhbXM/LmdldChcInZhcmlhbnRcIik7XG4gICAgICAgIGlmICghdmFyaWFudElkKSB7XG4gICAgICAgICAgcmV0dXJuIGdldFBscE9yUGRwSWQoXCJzaG9waWZ5LXByb2R1Y3QtaWRcIik7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHZhcmlhbnRJZDtcbiAgICAgIH1cblxuICAgICAgY29uc3QgcGF0aFNlZ21lbnQgPVxuICAgICAgICBleHRyYWN0b3IgPT09IFwic2hvcGlmeS1wcm9kdWN0LWlkXCIgPyBcInByb2R1Y3RzXCIgOiBcImNvbGxlY3Rpb25zXCI7XG4gICAgICBjb25zdCB0b2tlbnMgPSBnZXRUcmltbWVkUGF0aE5hbWUoKT8uc3BsaXQoXCIvXCIpO1xuICAgICAgY29uc3QgaWRJbmRleCA9IHRva2Vucz8uZmluZEluZGV4KCh0b2tlbikgPT4gdG9rZW4gPT09IHBhdGhTZWdtZW50KTtcbiAgICAgIGlmIChpZEluZGV4ICE9PSB1bmRlZmluZWQgJiYgaWRJbmRleCA+PSAwICYmIHRva2Vucykge1xuICAgICAgICByZXR1cm4gZGVjb2RlVVJJQ29tcG9uZW50KHRva2Vuc1tpZEluZGV4ICsgMV0pO1xuICAgICAgfVxuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfSxcbiAgICBbZ2V0VHJpbW1lZFBhdGhOYW1lXVxuICApO1xuXG4gIGNvbnN0IGlzT25QZHBQYWdlID0gdXNlQ2FsbGJhY2soKCk6IGJvb2xlYW4gPT4ge1xuICAgIHJldHVybiBnZXRUcmltbWVkUGF0aE5hbWUoKT8uaW5jbHVkZXMoXCIvcHJvZHVjdHNcIikgPz8gZmFsc2U7XG4gIH0sIFtnZXRUcmltbWVkUGF0aE5hbWVdKTtcblxuICBjb25zdCBpc09uUGxwUGFnZSA9IHVzZUNhbGxiYWNrKCgpOiBib29sZWFuID0+IHtcbiAgICByZXR1cm4gKFxuICAgICAgKGdldFRyaW1tZWRQYXRoTmFtZSgpPy5pbmNsdWRlcyhcIi9jb2xsZWN0aW9uc1wiKSAmJlxuICAgICAgICAhZ2V0VHJpbW1lZFBhdGhOYW1lKCk/LmluY2x1ZGVzKFwiL3Byb2R1Y3RzXCIpKSA/P1xuICAgICAgZmFsc2VcbiAgICApO1xuICB9LCBbZ2V0VHJpbW1lZFBhdGhOYW1lXSk7XG5cbiAgY29uc3QgdmFsdWUgPSB1c2VNZW1vKFxuICAgICgpID0+ICh7XG4gICAgICBnZXRUcmltbWVkUGF0aE5hbWUsXG4gICAgICBnZXRQbHBPclBkcElkLFxuICAgICAgaXNPblBkcFBhZ2UsXG4gICAgICBpc09uUGxwUGFnZSxcbiAgICAgIGlzUmVhZHksXG4gICAgfSksXG4gICAgW2dldFRyaW1tZWRQYXRoTmFtZSwgZ2V0UGxwT3JQZHBJZCwgaXNPblBkcFBhZ2UsIGlzT25QbHBQYWdlLCBpc1JlYWR5XVxuICApO1xuXG4gIHJldHVybiAoXG4gICAgPFNob3BpZnlVcmxDb250ZXh0LlByb3ZpZGVyIHZhbHVlPXt2YWx1ZX0+XG4gICAgICB7Y2hpbGRyZW59XG4gICAgPC9TaG9waWZ5VXJsQ29udGV4dC5Qcm92aWRlcj5cbiAgKTtcbn07XG5cbmV4cG9ydCBjb25zdCB1c2VTaG9waWZ5VXJsID0gKCkgPT4ge1xuICBjb25zdCBjb250ZXh0ID0gdXNlQ29udGV4dChTaG9waWZ5VXJsQ29udGV4dCk7XG4gIGlmICghY29udGV4dCkge1xuICAgIHRocm93IG5ldyBFcnJvcihcInVzZVNob3BpZnlVcmwgbXVzdCBiZSB1c2VkIHdpdGhpbiBhIFNob3BpZnlVcmxQcm92aWRlclwiKTtcbiAgfVxuICByZXR1cm4gY29udGV4dDtcbn07XG4iLCJpbXBvcnQgeyB1c2VDYWxsYmFjayB9IGZyb20gXCJyZWFjdFwiO1xuaW1wb3J0IHsgdXNlU2hvcGlmeVVybCB9IGZyb20gXCJzcmMvY29udGV4dHMvc2hvcGlmeVVybENvbnRleHRcIjtcbmltcG9ydCB7IElkRXh0cmFjdG9yIH0gZnJvbSBcInNyYy9jb250ZXh0cy90eXBlc1wiO1xuXG5leHBvcnQgY29uc3QgdXNlU2hvcGlmeVVybE9wZXJhdGlvbnMgPSAoKSA9PiB7XG4gIGNvbnN0IHtcbiAgICBnZXRUcmltbWVkUGF0aE5hbWUsXG4gICAgZ2V0UGxwT3JQZHBJZCxcbiAgICBpc09uUGRwUGFnZSxcbiAgICBpc09uUGxwUGFnZSxcbiAgICBpc1JlYWR5LFxuICB9ID0gdXNlU2hvcGlmeVVybCgpO1xuXG4gIHJldHVybiB7XG4gICAgZ2V0VHJpbW1lZFBhdGhOYW1lLFxuICAgIGdldFBscE9yUGRwSWQsXG4gICAgaXNPblBkcFBhZ2UsXG4gICAgaXNPblBscFBhZ2UsXG4gICAgaXNSZWFkeSxcbiAgfTtcbn07XG5cbmV4cG9ydCBjb25zdCB1c2VDdXJyZW50UGFnZVR5cGUgPSAoKSA9PiB7XG4gIGNvbnN0IHsgaXNPblBkcFBhZ2UsIGlzT25QbHBQYWdlLCBpc1JlYWR5IH0gPSB1c2VTaG9waWZ5VXJsKCk7XG5cbiAgY29uc3QgZ2V0UGFnZVR5cGUgPSB1c2VDYWxsYmFjaygoKSA9PiB7XG4gICAgaWYgKCFpc1JlYWR5KSByZXR1cm4gXCJ1bmtub3duXCI7XG4gICAgaWYgKGlzT25QZHBQYWdlKCkpIHJldHVybiBcInBkcFwiO1xuICAgIGlmIChpc09uUGxwUGFnZSgpKSByZXR1cm4gXCJwbHBcIjtcbiAgICByZXR1cm4gXCJvdGhlclwiO1xuICB9LCBbaXNSZWFkeSwgaXNPblBkcFBhZ2UsIGlzT25QbHBQYWdlXSk7XG5cbiAgcmV0dXJuIHsgZ2V0UGFnZVR5cGUsIGlzUmVhZHkgfTtcbn07XG5cbmV4cG9ydCBjb25zdCB1c2VQcm9kdWN0SWQgPSAoZXh0cmFjdG9yOiBJZEV4dHJhY3RvcikgPT4ge1xuICBjb25zdCB7IGdldFBscE9yUGRwSWQsIGlzUmVhZHkgfSA9IHVzZVNob3BpZnlVcmwoKTtcblxuICBjb25zdCBwcm9kdWN0SWQgPSB1c2VDYWxsYmFjaygoKSA9PiB7XG4gICAgaWYgKCFpc1JlYWR5KSByZXR1cm4gbnVsbDtcbiAgICByZXR1cm4gZ2V0UGxwT3JQZHBJZChleHRyYWN0b3IpO1xuICB9LCBbaXNSZWFkeSwgZ2V0UGxwT3JQZHBJZCwgZXh0cmFjdG9yXSk7XG5cbiAgcmV0dXJuIHsgcHJvZHVjdElkLCBpc1JlYWR5IH07XG59O1xuIiwiaW1wb3J0IHsgdXNlTWVtbyB9IGZyb20gJ3JlYWN0JztcblxuZXhwb3J0IHR5cGUgVW5pdCA9ICdwZXJjZW50JyB8ICdwaXhlbCc7XG5cbmV4cG9ydCBjb25zdCB1c2VTbmFwQ2FsY3VsYXRvciA9IChzbmFwczogbnVtYmVyW10sIG1heEhlaWdodDogbnVtYmVyLCB1bml0OiBVbml0KSA9PiB7XG4gIGNvbnN0IHZpZXdwb3J0SGVpZ2h0UHggPSBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuY2xpZW50SGVpZ2h0O1xuICBjb25zdCBzd2lwZXZpZXdIZWlnaHRQeCA9XG4gICAgdW5pdCA9PT0gJ3BlcmNlbnQnID8gTWF0aC5mbG9vcih2aWV3cG9ydEhlaWdodFB4ICogKG1heEhlaWdodCAvIDEwMCkpIDogbWF4SGVpZ2h0O1xuXG4gIGNvbnN0IHNuYXBzVG9QaXhlbHMgPSB1c2VNZW1vKFxuICAgICgpID0+XG4gICAgICBzbmFwcz8ubWFwKChzbmFwKSA9PlxuICAgICAgICBNYXRoLmFicyhcbiAgICAgICAgICAodW5pdCA9PT0gJ3BlcmNlbnQnID8gTWF0aC5mbG9vcihzd2lwZXZpZXdIZWlnaHRQeCAqIChzbmFwIC8gMTAwKSkgOiBzbmFwKSAtXG4gICAgICAgICAgICBzd2lwZXZpZXdIZWlnaHRQeCxcbiAgICAgICAgKSxcbiAgICAgICksXG4gICAgW3ZpZXdwb3J0SGVpZ2h0UHhdLFxuICApO1xuXG4gIGNvbnN0IGdldFBpeGVsVG9TbmFwID0gKHBpeGVsczogbnVtYmVyKSA9PiB7XG4gICAgY29uc3Qgc25hcElkeCA9IHNuYXBzVG9QaXhlbHM/LmluZGV4T2YocGl4ZWxzKSB8fCAwO1xuICAgIHJldHVybiBzbmFwcz8uW3NuYXBJZHhdIHx8IDA7XG4gIH07XG5cbiAgY29uc3QgZ2V0U25hcFRvUGl4ZWwgPSAoc25hcDogbnVtYmVyKSA9PiB7XG4gICAgY29uc3Qgc25hcElkeCA9IHNuYXBzPy5pbmRleE9mKHNuYXApIHx8IDA7XG4gICAgcmV0dXJuIHNuYXBzVG9QaXhlbHM/LltzbmFwSWR4XSB8fCAwO1xuICB9O1xuXG4gIHJldHVybiB7XG4gICAgdmlld3BvcnRIZWlnaHRQeCxcbiAgICBzbmFwc1RvUGl4ZWxzLFxuICAgIHN3aXBldmlld0hlaWdodFB4LFxuICAgIGdldFBpeGVsVG9TbmFwLFxuICAgIGdldFNuYXBUb1BpeGVsLFxuICB9O1xufTtcbiIsImltcG9ydCB7IHVzZUNvbnRleHQgfSBmcm9tICdyZWFjdCc7XG5pbXBvcnQgeyBTeXN0ZW1TZXR0aW5nc0NvbnRleHQgfSBmcm9tICdzcmMvY29udGV4dHMnO1xuXG5leHBvcnQgY29uc3QgdXNlU3lzdGVtU2V0dGluZ3NDb250ZXh0ID0gKCkgPT4ge1xuICBjb25zdCBjb250ZXh0ID0gdXNlQ29udGV4dChTeXN0ZW1TZXR0aW5nc0NvbnRleHQpO1xuXG4gIGlmICghY29udGV4dCkge1xuICAgIHRocm93IG5ldyBFcnJvcigndXNlU3lzdGVtU2V0dGluZ3NDb250ZXh0IG11c3QgYmUgdXNlZCB3aXRoaW4gYSBTeXN0ZW1TZXR0aW5nc0NvbnRleHRQcm92aWRlcicpO1xuICB9XG5cbiAgcmV0dXJuIHsgLi4uY29udGV4dCB9O1xufTtcbiIsImltcG9ydCB7IFJlZk9iamVjdCwgdXNlRWZmZWN0LCB1c2VSZWYgfSBmcm9tIFwicmVhY3RcIjtcbmltcG9ydCB7IFNwaWZmeVdpZGdldHMgfSBmcm9tIFwic3JjL2FwcGxpY2F0aW9uL21vZGVscy9zcGlmZnlXaWRnZXRzXCI7XG5pbXBvcnQgeyB1c2VJbnRlcnNlY3Rpb24gfSBmcm9tIFwic3JjL2hvb2tzL3VzZUludGVyc2VjdGlvblwiO1xuaW1wb3J0IHtcbiAgU3BpZmZ5TWV0cmljc0V2ZW50TmFtZSxcbiAgdXNlQW1wbGl0dWRlLFxufSBmcm9tIFwic3JjL2NvbnRleHRzL2FtcGxpdHVkZUNvbnRleHRcIjtcblxuLyoqXG4gKiBUcmFja3MgYSBjb21wb25lbnQgYW5kIGxvZ3MgYW4gZXZlbnQgdG8gQW1wbGl0dWRlIHdoZW4gdGhlIGNvbXBvbmVudCBpcyB2aXNpYmxlLlxuICpcbiAqIEBwYXJhbSBjb21wb25lbnQgLSBUaGUgY29tcG9uZW50IHRvIHRyYWNrLlxuICogQHBhcmFtIGVsZW1lbnQgLSBUaGUgZWxlbWVudCB0byB0cmFjayB2aXNpYmlsaXR5IG9mLlxuICogQHBhcmFtIGV2ZW50UHJvcHMgLSBBZGRpdGlvbmFsIHByb3BlcnRpZXMgdG8gaW5jbHVkZSB3aXRoIHRoZSBldmVudC5cbiAqIEBwYXJhbSBldmVudE5hbWUgLSBUaGUgQW1wbGl0dWRlIGV2ZW50IG5hbWUgdG8gdHJhY2sgKGRlZmF1bHRzIHRvIENoYXRDb21wb25lbnRWaXNpYmxlKS5cbiAqL1xuZXhwb3J0IGNvbnN0IHVzZVRyYWNrQ29tcG9uZW50VmlzaWJsZUV2ZW50ID0gKFxuICBjb21wb25lbnQ6IFNwaWZmeVdpZGdldHMsXG4gIGVsZW1lbnQ6IFJlZk9iamVjdDxIVE1MRWxlbWVudD4sXG4gIGV2ZW50UHJvcHM/OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPixcbiAgZXZlbnROYW1lOiBTcGlmZnlNZXRyaWNzRXZlbnROYW1lID0gU3BpZmZ5TWV0cmljc0V2ZW50TmFtZS5DaGF0Q29tcG9uZW50VmlzaWJsZVxuKSA9PiB7XG4gIGNvbnN0IGlzVmlzaWJsZSA9IHVzZUludGVyc2VjdGlvbihlbGVtZW50LCBcIjBweFwiKTtcbiAgY29uc3QgaGFzVHJhY2tlZEV2ZW50ID0gdXNlUmVmKGZhbHNlKTtcbiAgY29uc3QgeyB0cmFja0V2ZW50IH0gPSB1c2VBbXBsaXR1ZGUoKTtcblxuICBjb25zdCBjb21wb25lbnRQcm9wcyA9ICgoKSA9PiB7XG4gICAgaWYgKGV2ZW50TmFtZSA9PT0gU3BpZmZ5TWV0cmljc0V2ZW50TmFtZS5DaGF0Q29tcG9uZW50VmlzaWJsZSkge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgY2hhdF9jb21wb25lbnQ6IGNvbXBvbmVudCxcbiAgICAgICAgLi4uZXZlbnRQcm9wcyxcbiAgICAgIH07XG4gICAgfVxuICAgIGlmIChldmVudE5hbWUgPT09IFNwaWZmeU1ldHJpY3NFdmVudE5hbWUuU2VhcmNoQ29tcG9uZW50VmlzaWJsZSkge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgc2VhcmNoX2NvbXBvbmVudDogY29tcG9uZW50LFxuICAgICAgICAuLi5ldmVudFByb3BzLFxuICAgICAgfTtcbiAgICB9XG4gICAgLy8gRGVmYXVsdCBjYXNlIGZvciBvdGhlciBldmVudCB0eXBlc1xuICAgIHJldHVybiB7XG4gICAgICBjb21wb25lbnQ6IGNvbXBvbmVudCxcbiAgICAgIC4uLmV2ZW50UHJvcHMsXG4gICAgfTtcbiAgfSkoKTtcblxuICB1c2VFZmZlY3QoKCkgPT4ge1xuICAgIGlmIChpc1Zpc2libGUgJiYgIWhhc1RyYWNrZWRFdmVudC5jdXJyZW50KSB7XG4gICAgICB0cmFja0V2ZW50KHtcbiAgICAgICAgZXZlbnROYW1lOiBldmVudE5hbWUsXG4gICAgICAgIGV2ZW50UHJvcHM6IGNvbXBvbmVudFByb3BzLFxuICAgICAgfSk7XG4gICAgICBoYXNUcmFja2VkRXZlbnQuY3VycmVudCA9IHRydWU7XG4gICAgfVxuICB9LCBbaXNWaXNpYmxlLCBjb21wb25lbnQsIGV2ZW50UHJvcHMsIGV2ZW50TmFtZSwgY29tcG9uZW50UHJvcHMsIHRyYWNrRXZlbnRdKTtcbn07XG4iLCJpbXBvcnQgeyB1c2VBdG9tVmFsdWUgfSBmcm9tIFwiam90YWlcIjtcbmltcG9ydCB7IHVzZUVmZmVjdCwgdXNlUmVmIH0gZnJvbSBcInJlYWN0XCI7XG5pbXBvcnQge1xuICBTcGlmZnlNZXRyaWNzRXZlbnROYW1lLFxuICB1c2VBbXBsaXR1ZGUsXG59IGZyb20gXCJzcmMvY29udGV4dHMvYW1wbGl0dWRlQ29udGV4dFwiO1xuaW1wb3J0IHtcbiAgaGFzUGFyc2VkVmFyaWFudEluZm9BdG9tLFxuICB2YXJpYW50SW5mb0F0b20sXG59IGZyb20gXCJzcmMvYXRvbXMvYXBwL3ZhcmlhbnRcIjtcblxuLyoqXG4gKiBVcGRhdGVzIHRoZSBkZWZhdWx0IGFuYWx5dGljcyBwcm9wZXJ0aWVzIHdoZW5ldmVyIHRoZSB2YXJpYW50IGluZm8gY2hhbmdlcy4gVGhpcyBob29rIGFsc29cbiAqIHRyaWdnZXJzIGFueSBldmVudHMgdGhhdCBzaG91bGQgYmUgc2VudCBvbmNlIHBlciBwYWdlIHZpc2l0LlxuICovXG5leHBvcnQgY29uc3QgdXNlVXBkYXRlQW5hbHl0aWNzUHJvcHMgPSAoKSA9PiB7XG4gIGNvbnN0IHZhcmlhbnRJbmZvID0gdXNlQXRvbVZhbHVlKHZhcmlhbnRJbmZvQXRvbSk7XG4gIGNvbnN0IGhhc0luaXRpYWxpemVkID0gdXNlUmVmKGZhbHNlKTtcbiAgY29uc3QgaGFzUGFyc2VkVmFyaWFudEluZm8gPSB1c2VBdG9tVmFsdWUoaGFzUGFyc2VkVmFyaWFudEluZm9BdG9tKTtcbiAgY29uc3QgeyB0cmFja0V2ZW50LCBzZXRTdXBwbGVtZW50YWxEZWZhdWx0UHJvcHMgfSA9IHVzZUFtcGxpdHVkZSgpO1xuXG4gIHVzZUVmZmVjdCgoKSA9PiB7XG4gICAgY29uc3QgdmFyaWFudEluZm9XaXRoUHJlZml4ID0gT2JqZWN0LmZyb21FbnRyaWVzKFxuICAgICAgT2JqZWN0LmVudHJpZXModmFyaWFudEluZm8pLm1hcCgoW2tleSwgdmFsdWVdKSA9PiBbXG4gICAgICAgIGB2YXJpYW50SW5mby4ke2tleX1gLFxuICAgICAgICB2YWx1ZSxcbiAgICAgIF0pXG4gICAgKTtcblxuICAgIGNvbnN0IGRlZmF1bHRFdmVudFByb3BlcnRpZXM6IFJlY29yZDxzdHJpbmcsIHVua25vd24+ID0ge1xuICAgICAgcGFnZV92YXJpYW50OiB2YXJpYW50SW5mby52YXJpYW50LCAvLyBUT0RPOiBzaG91bGQgYmUgcmVtb3ZlZCBvdmVyIHRpbWUsIGFmdGVyIG1pZ3JhdGlvblxuICAgICAgLi4udmFyaWFudEluZm9XaXRoUHJlZml4LFxuICAgIH07XG5cbiAgICAvLyBUT0RPOiBzaG91bGQgYmUgcmVtb3ZlZCBvdmVyIHRpbWUsIGFmdGVyIG1pZ3JhdGlvblxuICAgIGlmICh2YXJpYW50SW5mby52YXJpYW50ID09PSBcInBkcFwiKSB7XG4gICAgICBkZWZhdWx0RXZlbnRQcm9wZXJ0aWVzLnByb2R1Y3RfaWQgPSB2YXJpYW50SW5mby5wcm9kdWN0SWQ7XG4gICAgfVxuXG4gICAgLy8gVE9ETzogc2hvdWxkIGJlIHJlbW92ZWQgb3ZlciB0aW1lLCBhZnRlciBtaWdyYXRpb25cbiAgICBpZiAodmFyaWFudEluZm8udmFyaWFudCA9PT0gXCJwbHBcIikge1xuICAgICAgZGVmYXVsdEV2ZW50UHJvcGVydGllcy5wbHBfaWQgPSB2YXJpYW50SW5mby5wbHBJZDtcbiAgICB9XG5cbiAgICAvLyBUT0RPOiBzaG91bGQgYmUgcmVtb3ZlZCBvdmVyIHRpbWUsIGFmdGVyIG1pZ3JhdGlvblxuICAgIGlmICh2YXJpYW50SW5mby52YXJpYW50ID09PSBcInBhZ2VfdmlzaXRcIikge1xuICAgICAgZGVmYXVsdEV2ZW50UHJvcGVydGllcy5wYWdlX3Zpc2l0X2NhdGVnb3J5ID1cbiAgICAgICAgdmFyaWFudEluZm8ucGFnZVZpc2l0Q2F0ZWdvcnk7XG4gICAgICBkZWZhdWx0RXZlbnRQcm9wZXJ0aWVzLnBhZ2VfdmlzaXRfdXJsID0gdmFyaWFudEluZm8udXJsO1xuICAgIH1cblxuICAgIHNldFN1cHBsZW1lbnRhbERlZmF1bHRQcm9wcyhkZWZhdWx0RXZlbnRQcm9wZXJ0aWVzKTtcblxuICAgIC8vIHB1dCBhbnkgZXZlbnRzIHRoYXQgc2hvdWxkIGJlIHNlbnQgb25jZSBwZXIgcGFnZSB2aXNpdCBoZXJlXG4gICAgaWYgKCFoYXNJbml0aWFsaXplZC5jdXJyZW50ICYmIGhhc1BhcnNlZFZhcmlhbnRJbmZvKSB7XG4gICAgICB0cmFja0V2ZW50KHtcbiAgICAgICAgZXZlbnROYW1lOiBTcGlmZnlNZXRyaWNzRXZlbnROYW1lLkJ1bmRsZUxvYWRlZCxcbiAgICAgIH0pO1xuICAgICAgaGFzSW5pdGlhbGl6ZWQuY3VycmVudCA9IHRydWU7XG4gICAgfVxuICB9LCBbXG4gICAgdmFyaWFudEluZm8sXG4gICAgaGFzUGFyc2VkVmFyaWFudEluZm8sXG4gICAgdHJhY2tFdmVudCxcbiAgICBzZXRTdXBwbGVtZW50YWxEZWZhdWx0UHJvcHMsXG4gIF0pO1xufTtcbiIsImltcG9ydCB7IFVzZXJFdmVudENhdGVnb3J5IH0gZnJvbSBcIkBzcGlmZnktYWkvY29tbWVyY2UtYXBpLWNsaWVudFwiO1xuaW1wb3J0IHsgdXNlQXRvbSwgdXNlQXRvbVZhbHVlLCB1c2VTZXRBdG9tIH0gZnJvbSBcImpvdGFpXCI7XG5pbXBvcnQge1xuICBjcmVhdGVDb250ZXh0LFxuICB1c2VFZmZlY3QsXG4gIHVzZVN0YXRlLFxuICBSZWFjdE5vZGUsXG4gIHVzZUNhbGxiYWNrLFxuICB1c2VNZW1vLFxufSBmcm9tIFwicmVhY3RcIjtcbmltcG9ydCBDb21tZXJjZUFwaUNsaWVudCBmcm9tIFwic3JjL2FwcGxpY2F0aW9uL2NvbW1lcmNlLWFwaVwiO1xuaW1wb3J0IHsgdjQgYXMgdXVpZCB9IGZyb20gXCJ1dWlkXCI7XG5pbXBvcnQgeyBTZXNzaW9uUmVzdGFydFJlcXVpcmVkIH0gZnJvbSBcInNyYy90eXBlcy9leGNlcHRpb25zL3Nlc3Npb25FeGNlcHRpb25zXCI7XG5pbXBvcnQgTG9nZ2VyIGZyb20gXCJzcmMvYXBwbGljYXRpb24vbG9nZ2luZy9sb2dnZXJcIjtcbmltcG9ydCB7XG4gIE1lc3NhZ2UsXG4gIE1lc3NhZ2VSb2xlLFxuICBNZXNzYWdlVHlwZSxcbiAgTmV4dE1lc3NhZ2VSZXF1ZXN0LFxuICBSZXNwb25zZSxcbn0gZnJvbSBcInNyYy9hcHBsaWNhdGlvbi9tb2RlbHNcIjtcbmltcG9ydCB7IFNwaWZmeU1ldHJpY3NFdmVudE5hbWUgfSBmcm9tIFwic3JjL2NvbnRleHRzL2FtcGxpdHVkZUNvbnRleHRcIjtcbmltcG9ydCB7IG1lc3NhZ2VGcm9tUmVzcG9uc2UgfSBmcm9tIFwic3JjL2FwcGxpY2F0aW9uL3V0aWxzXCI7XG5pbXBvcnQgeyBjaGF0SWRBdG9tLCB1c2VySWRBdG9tLCB2YXJpYW50SW5mb0F0b20gfSBmcm9tIFwic3JjL2F0b21zL2FwcFwiO1xuaW1wb3J0IHtcbiAgbWVzc2FnZXNBdG9tLFxuICByZXF1ZXN0RmFpbHVyZUF0b20sXG4gIHJlc3BvbnNlU3RyZWFtaW5nQXRvbSxcbiAgdXNlckhhc1JlcGxpZWRBdG9tLFxuICBQZXJmTWV0cmljc0V2ZW50cyxcbiAgbG9nUGVyZk1ldHJpY0F0b20sXG4gIHVzZXJFdmVudHNBdG9tLFxuICBzdWdnZXN0aW9uc0xvYWRpbmdBdG9tLFxuICBzdWdnZXN0aW9uc0F0b20sXG59IGZyb20gXCJzcmMvYXRvbXMvY2hhdFwiO1xuaW1wb3J0IHtcbiAgY2hhdFNlYXJjaFByb2R1Y3RTb3J0aW5nQXRvbSxcbiAgY2hhdFNlYXJjaFByb2R1Y3RzLFxuICBjaGF0U2VhcmNoU3RhdGVBdG9tLFxuICBoYW5kbGVTZWFyY2hSZXN1bHRzQXRvbSxcbiAgY2hhdFNlYXJjaElzTG9hZGluZ0F0b20sXG59IGZyb20gXCJzcmMvYXRvbXMvc2VhcmNoL2NoYXRTZWFyY2hcIjtcbmltcG9ydCB7IHVzZVN5c3RlbVNldHRpbmdzQ29udGV4dCB9IGZyb20gXCJzcmMvaG9va3NcIjtcbmltcG9ydCB7IGNyZWF0ZUFwcExvYWRlZEV2ZW50LCBjcmVhdGVWaXNpdFVzZXJFdmVudCB9IGZyb20gXCJzcmMvaG9va3MvdXRpbHNcIjtcbmltcG9ydCB7IHVzZU1lc3NhZ2VJbnRlcmNlcHRvciB9IGZyb20gXCJzcmMvaW50ZXJjZXB0b3JzL3VzZU1lc3NhZ2VJbnRlcmNlcHRvclwiO1xuaW1wb3J0IHsgc3VwcG9ydGVkRXZlbnRBdG9tIH0gZnJvbSBcInNyYy9hdG9tcy9hcHAvdmFyaWFudFwiO1xuaW1wb3J0IHsgY2hhdEF0b20gfSBmcm9tIFwic3JjL2F0b21zL2NoYXRcIjtcbmltcG9ydCB7IGdldEF0b21TdG9yZSB9IGZyb20gXCJzcmMvYXRvbXMvYXRvbVN0b3JlXCI7XG5pbXBvcnQge1xuICBjbGVhclVzZXJFdmVudEF0b20sXG4gIGNyZWF0ZVJlc3BvbnNlUGF5bG9hZCxcbiAgcHJvY2Vzc1VzZXJFdmVudEF0b20sXG4gIHVzZXJFdmVudFF1ZXVlQXRvbSxcbiAgdXNlclF1ZXVlRXZlbnRDb3VudEF0b20sXG59IGZyb20gXCJzcmMvYXRvbXMvY2hhdC9tZXNzYWdlUXVldWVcIjtcbmltcG9ydCB7IHVzZUFtcGxpdHVkZVRyYWNraW5nIH0gZnJvbSBcInNyYy9ob29rcy91c2VBbXBsaXR1ZGVPcGVyYXRpb25zXCI7XG5cbi8qKlxuICogUmVjb3JkIHRoZSBjaGF0IGFzc2lzdGFudCByZXNwb25zZSBpbiBBbXBsaXR1ZGVcbiAqXG4gKiBAcGFyYW0gc3RhcnRUaW1lTXMgVGhlIHN0YXJ0IHRpbWUgb2YgdGhlIGFzc2lzdGFudCByZXNwb25zZVxuICogQHBhcmFtIHBheWxvYWQgVGhlIHBheWxvYWQgdXNlZCB0byBnZW5lcmF0ZSB0aGUgcmVzcG9uc2VcbiAqL1xuY29uc3QgcmVjb3JkQXNzaXN0YW50UmVzcG9uc2UgPSAoXG4gIHN0YXJ0VGltZU1zOiBudW1iZXIsXG4gIHBheWxvYWQ6IE5leHRNZXNzYWdlUmVxdWVzdCxcbiAgdHJhY2s6IChcbiAgICBldmVudE5hbWU6IFNwaWZmeU1ldHJpY3NFdmVudE5hbWUsXG4gICAgZXZlbnRQcm9wcz86IFJlY29yZDxzdHJpbmcsIHVua25vd24+XG4gICkgPT4gdm9pZFxuKSA9PiB7XG4gIGNvbnN0IGF0b21TdG9yZSA9IGdldEF0b21TdG9yZSgpO1xuICBjb25zdCBjaGF0U3RhdGUgPSBhdG9tU3RvcmUuZ2V0KGNoYXRBdG9tKTtcbiAgY29uc3QgY2hhdFNlYXJjaFN0YXRlID0gYXRvbVN0b3JlLmdldChjaGF0U2VhcmNoU3RhdGVBdG9tKTtcbiAgY29uc3Qgc2VhcmNoUHJvZHVjdHMgPSBhdG9tU3RvcmUuZ2V0KGNoYXRTZWFyY2hQcm9kdWN0cyk7XG4gIGNvbnN0IHNlYXJjaFByb2R1Y3RzU29ydCA9IGF0b21TdG9yZS5nZXQoY2hhdFNlYXJjaFByb2R1Y3RTb3J0aW5nQXRvbSk7XG4gIGNvbnN0IGFzc2lzdGFudFJlc3BvbnNlVGltZU1zID0geyBzdGFydDogc3RhcnRUaW1lTXMsIGVuZDogRGF0ZS5ub3coKSB9O1xuICBsZXQgdXNlclF1ZXJ5UHJvcGVydHk6IHN0cmluZyB8IHVuZGVmaW5lZDtcblxuICBpZiAoXG4gICAgY2hhdFN0YXRlLnJlcGx5RXZlbnRDYXRlZ29yeSA9PT0gVXNlckV2ZW50Q2F0ZWdvcnkuU3VnZ2VzdGlvbkNsaWNrZWQgJiZcbiAgICBjaGF0U3RhdGUuc3VnZ2VzdGlvblxuICApIHtcbiAgICB1c2VyUXVlcnlQcm9wZXJ0eSA9IGNoYXRTdGF0ZS5zdWdnZXN0aW9uLmNvbnRlbnQ7XG4gIH0gZWxzZSBpZiAoY2hhdFN0YXRlLnVzZXJRdWVyeSAmJiBjaGF0U3RhdGUudXNlclF1ZXJ5Lmxlbmd0aCA+IDApIHtcbiAgICB1c2VyUXVlcnlQcm9wZXJ0eSA9IGNoYXRTdGF0ZS51c2VyUXVlcnk7XG4gIH1cblxuICBjb25zdCBldmVudFByb3BzOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiA9IHtcbiAgICByZXNwb25zZV90aW1lX21zOlxuICAgICAgYXNzaXN0YW50UmVzcG9uc2VUaW1lTXMuZW5kIC0gYXNzaXN0YW50UmVzcG9uc2VUaW1lTXMuc3RhcnQsXG4gICAgdXNlcl9ldmVudF90eXBlOiBjaGF0U3RhdGUucmVwbHlFdmVudENhdGVnb3J5LFxuICAgIHVzZXJfcXVlcnk6IHVzZXJRdWVyeVByb3BlcnR5LFxuICB9O1xuXG4gIGlmIChjaGF0U3RhdGUucmVwbHlFdmVudENhdGVnb3J5ID09PSBVc2VyRXZlbnRDYXRlZ29yeS5Gb3JtU3VibWl0dGVkKSB7XG4gICAgY29uc3QgbGFzdEFzc2lzdGFudFR1cm4gPSBjaGF0U3RhdGUubWVzc2FnZXNcbiAgICAgIC5maWx0ZXIoXG4gICAgICAgICh0dXJuKSA9PiB0dXJuLmxlbmd0aCA+IDAgJiYgdHVyblswXS5yb2xlID09PSBNZXNzYWdlUm9sZS5Bc3Npc3RhbnRcbiAgICAgIClcbiAgICAgIC5wb3AoKTtcbiAgICBjb25zdCBmb3JtVHlwZSA9IHBheWxvYWQudXNlckV2ZW50cz8uZmluZChcbiAgICAgIChldmVudCkgPT4gZXZlbnQuY2F0ZWdvcnkgPT09IFVzZXJFdmVudENhdGVnb3J5LkZvcm1TdWJtaXR0ZWRcbiAgICApPy5hdHRyaWJ1dGVzLmZvcm1UeXBlO1xuICAgIGNvbnN0IGZvcm1TdGF0dXMgPSBsYXN0QXNzaXN0YW50VHVybj8uc29tZShcbiAgICAgIChyZXNwb25zZSkgPT4gcmVzcG9uc2UudHlwZSA9PT0gTWVzc2FnZVR5cGUuT3JkZXJcbiAgICApO1xuICAgIGV2ZW50UHJvcHMuZm9ybV9zdWJtaXR0ZWRfYXR0cmlidXRlcyA9IHtcbiAgICAgIGZvcm1fdHlwZTogZm9ybVR5cGUsXG4gICAgICBzdGF0dXM6IGZvcm1TdGF0dXMgPyBcInN1Y2Nlc3NcIiA6IFwiZmFpbGVkXCIsXG4gICAgfTtcbiAgfVxuXG4gIGlmIChjaGF0U2VhcmNoU3RhdGUgPT09IFwicHJvZHVjdC1wYWdlXCIpIHtcbiAgICBldmVudFByb3BzLnNlYXJjaF9wcm9kdWN0c19yZXR1cm5lZCA9IHNlYXJjaFByb2R1Y3RzLmxlbmd0aDtcbiAgICBldmVudFByb3BzLnNlYXJjaF9wcm9kdWN0c19zb3J0X3R5cGUgPSBzZWFyY2hQcm9kdWN0c1NvcnQ7XG4gIH1cblxuICB0cmFjayhTcGlmZnlNZXRyaWNzRXZlbnROYW1lLkNoYXRBc3Npc3RhbnRSZXNwb25zZSwge1xuICAgIGV2ZW50UHJvcHMsXG4gIH0pO1xufTtcblxuaW50ZXJmYWNlIENoYXRDb250ZXh0UGFyYW1zIHt9XG5cbmNvbnN0IENoYXRDb250ZXh0ID0gY3JlYXRlQ29udGV4dDxDaGF0Q29udGV4dFBhcmFtcyB8IHVuZGVmaW5lZD4odW5kZWZpbmVkKTtcblxuY29uc3QgdXBkYXRlTWVzc2FnZVN0YXRlID0gKFxuICBtZXNzYWdlOiBNZXNzYWdlLFxuICBsYXN0TWVzc2FnZTogTWVzc2FnZSxcbiAgc2V0TWVzc2FnZXM6ICh1cGRhdGVyOiAocHJldjogTWVzc2FnZVtdW10pID0+IE1lc3NhZ2VbXVtdKSA9PiB2b2lkXG4pOiBNZXNzYWdlID0+IHtcbiAgaWYgKGxhc3RNZXNzYWdlID09IG51bGwpIHtcbiAgICBzZXRNZXNzYWdlcygocHJldikgPT4gWy4uLnByZXYsIFttZXNzYWdlXV0pO1xuICAgIHJldHVybiBtZXNzYWdlO1xuICB9XG4gIGlmIChcbiAgICBsYXN0TWVzc2FnZS50eXBlID09PSBNZXNzYWdlVHlwZS5UZXh0ICYmXG4gICAgbWVzc2FnZS50eXBlID09PSBNZXNzYWdlVHlwZS5UZXh0XG4gICkge1xuICAgIGNvbnN0IG5ld01lc3NhZ2UgPSB7XG4gICAgICAuLi5sYXN0TWVzc2FnZSxcbiAgICAgIG1ldGFkYXRhOiB7XG4gICAgICAgIC4uLmxhc3RNZXNzYWdlLm1ldGFkYXRhLFxuICAgICAgICBjb250ZW50OiBsYXN0TWVzc2FnZS5tZXRhZGF0YS5jb250ZW50ICsgbWVzc2FnZS5tZXRhZGF0YS5jb250ZW50LFxuICAgICAgfSxcbiAgICB9O1xuICAgIHNldE1lc3NhZ2VzKChwcmV2KSA9PiB7XG4gICAgICBjb25zdCBsYXN0VHVybiA9IHByZXZbcHJldi5sZW5ndGggLSAxXTtcbiAgICAgIHJldHVybiBbXG4gICAgICAgIC4uLnByZXYuc2xpY2UoMCwgcHJldi5sZW5ndGggLSAxKSxcbiAgICAgICAgWy4uLmxhc3RUdXJuLnNsaWNlKDAsIGxhc3RUdXJuLmxlbmd0aCAtIDEpLCBuZXdNZXNzYWdlXSxcbiAgICAgIF07XG4gICAgfSk7XG4gICAgcmV0dXJuIG5ld01lc3NhZ2U7XG4gIH1cbiAgc2V0TWVzc2FnZXMoKHByZXYpID0+IFtcbiAgICAuLi5wcmV2LnNsaWNlKDAsIHByZXYubGVuZ3RoIC0gMSksXG4gICAgWy4uLnByZXZbcHJldi5sZW5ndGggLSAxXSwgbWVzc2FnZV0sXG4gIF0pO1xuICByZXR1cm4gbWVzc2FnZTtcbn07XG5cbmNvbnN0IGhhbmRsZVN0cmVhbWluZ0Vycm9yID0gKFxuICBfZXJyb3I6IHVua25vd24sXG4gIHNldFJlcXVlc3RGYWlsdXJlOiAoZmFpbGVkOiBib29sZWFuKSA9PiB2b2lkLFxuICBzZXRNZXNzYWdlczogKHVwZGF0ZXI6IChwcmV2OiBNZXNzYWdlW11bXSkgPT4gTWVzc2FnZVtdW10pID0+IHZvaWRcbikgPT4ge1xuICBzZXRSZXF1ZXN0RmFpbHVyZSh0cnVlKTtcbiAgc2V0TWVzc2FnZXMoKHByZXYpID0+IFtcbiAgICAuLi5wcmV2LFxuICAgIFtcbiAgICAgIHtcbiAgICAgICAgaWQ6IHV1aWQoKSxcbiAgICAgICAgcm9sZTogTWVzc2FnZVJvbGUuQXNzaXN0YW50LFxuICAgICAgICB0eXBlOiBNZXNzYWdlVHlwZS5UZXh0LFxuICAgICAgICBjcmVhdGVkQXQ6IG5ldyBEYXRlKCkudG9JU09TdHJpbmcoKSxcbiAgICAgICAgbWV0YWRhdGE6IHtcbiAgICAgICAgICBjb250ZW50OlxuICAgICAgICAgICAgXCJJJ20gc29ycnkhIEknbSBoYXZpbmcgdHJvdWJsZSByaWdodCBub3cuIFBsZWFzZSByZWZyZXNoIHRoZSBwYWdlIG9yIHRyeSBhZ2FpbiBpbiBhIG1vbWVudC5cIixcbiAgICAgICAgfSxcbiAgICAgIH0sXG4gICAgXSxcbiAgXSk7XG59O1xuXG5jb25zdCBwcm9jZXNzU3RyZWFtaW5nUmVzcG9uc2UgPSBhc3luYyAoXG4gIHN0cmVhbTogQXN5bmNJdGVyYWJsZTxSZXNwb25zZT4sXG4gIG1lc3NhZ2VJbnRlcmNlcHRvcjoge1xuICAgIGludGVyY2VwdDogKHJlc3BvbnNlPzogUmVzcG9uc2UpID0+IGJvb2xlYW4gfCB1bmRlZmluZWQ7XG4gIH0sXG4gIGhhbmRsZVNlYXJjaFJlc3VsdHM6IChtZXNzYWdlOiBNZXNzYWdlKSA9PiB2b2lkLFxuICBzZXRNZXNzYWdlczogKHVwZGF0ZXI6IChwcmV2OiBNZXNzYWdlW11bXSkgPT4gTWVzc2FnZVtdW10pID0+IHZvaWQsXG4gIHNldFNlYXJjaElzTG9hZGluZzogKGxvYWRpbmc6IGJvb2xlYW4pID0+IHZvaWQsXG4gIGNoYXRJZDogc3RyaW5nXG4pOiBQcm9taXNlPHsgaGFzU2VhcmNoUmVzdWx0czogYm9vbGVhbiB9PiA9PiB7XG4gIGxldCBsYXN0TWVzc2FnZTogTWVzc2FnZSB8IHVuZGVmaW5lZDtcbiAgbGV0IGhhc1NlYXJjaFJlc3VsdHMgPSBmYWxzZTtcblxuICBmb3IgYXdhaXQgKGNvbnN0IHJlc3BvbnNlIG9mIHN0cmVhbSkge1xuICAgIHRyeSB7XG4gICAgICBpZiAobWVzc2FnZUludGVyY2VwdG9yLmludGVyY2VwdChyZXNwb25zZSkpIHtcbiAgICAgICAgcmV0dXJuIHsgaGFzU2VhcmNoUmVzdWx0cyB9O1xuICAgICAgfVxuXG4gICAgICBjb25zdCBtZXNzYWdlID0gbWVzc2FnZUZyb21SZXNwb25zZShyZXNwb25zZSk7XG4gICAgICBpZiAoIW1lc3NhZ2UpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiRmFpbGVkIHRvIHRyYW5zZm9ybSBBUEkgcmVzcG9uc2UgdG8gY2xpZW50IG1lc3NhZ2VcIik7XG4gICAgICB9XG5cbiAgICAgIGlmIChtZXNzYWdlLnR5cGUgPT09IE1lc3NhZ2VUeXBlLlByb2R1Y3RTZWFyY2gpIHtcbiAgICAgICAgaGFuZGxlU2VhcmNoUmVzdWx0cyhtZXNzYWdlKTtcbiAgICAgICAgaGFzU2VhcmNoUmVzdWx0cyA9IHRydWU7XG4gICAgICAgIHNldFNlYXJjaElzTG9hZGluZyhmYWxzZSk7IC8vIFVwZGF0ZSBzZWFyY2ggbG9hZGluZyBpbW1lZGlhdGVseSB3aGVuIHJlc3VsdHMgYXJlIGRldGVjdGVkXG4gICAgICB9XG5cbiAgICAgIGxhc3RNZXNzYWdlID0gdXBkYXRlTWVzc2FnZVN0YXRlKG1lc3NhZ2UsIGxhc3RNZXNzYWdlISwgc2V0TWVzc2FnZXMpO1xuICAgIH0gY2F0Y2ggKGVycm9yOiB1bmtub3duKSB7XG4gICAgICBMb2dnZXIubG9nV2FybihcbiAgICAgICAgYFtzcGlmZnktYWldIEZhaWxlZCB0byBnZW5lcmF0ZSByZXNwb25zZXMgZnJvbSBzdHJlYW0gY2hhdF9pZD0ke2NoYXRJZH1gLFxuICAgICAgICBlcnJvcixcbiAgICAgICAge1xuICAgICAgICAgIGxhc3RSZXNwb25zZTogbGFzdE1lc3NhZ2UsXG4gICAgICAgICAgcmVzcG9uc2UsXG4gICAgICAgIH1cbiAgICAgICk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHsgaGFzU2VhcmNoUmVzdWx0cyB9O1xufTtcblxuY29uc3QgQ2hhdENvbnRleHRQcm92aWRlciA9ICh7IGNoaWxkcmVuIH06IHsgY2hpbGRyZW46IFJlYWN0Tm9kZSB9KSA9PiB7XG4gIGNvbnN0IGxvZ1BlcmZNZXRyaWMgPSB1c2VTZXRBdG9tKGxvZ1BlcmZNZXRyaWNBdG9tKTtcbiAgY29uc3QgW3dpZGdldEluaXRpYWxpemVkLCBzZXRXaWRnZXRJbml0aWFsaXplZF0gPSB1c2VTdGF0ZShmYWxzZSk7XG4gIGNvbnN0IHNldFVzZXJIYXNSZXBsaWVkID0gdXNlU2V0QXRvbSh1c2VySGFzUmVwbGllZEF0b20pO1xuICAvLyBUT0RPOiBjcmVhdGUgYXRvbXMgZm9yIHNldHRpbmcvZ2V0dGluZyB0aGUgbGFzdCBtZXNzYWdlIHR1cm5cbiAgY29uc3QgW21lc3NhZ2VzLCBzZXRNZXNzYWdlc10gPSB1c2VBdG9tPE1lc3NhZ2VbXVtdPihtZXNzYWdlc0F0b20pO1xuICBjb25zdCBzZXRVc2VyRXZlbnRzID0gdXNlU2V0QXRvbSh1c2VyRXZlbnRzQXRvbSk7XG4gIGNvbnN0IHNldFN1Z2dlc3Rpb25zID0gdXNlU2V0QXRvbShzdWdnZXN0aW9uc0F0b20pO1xuICBjb25zdCBbc3VnZ2VzdGlvbnNMb2FkaW5nLCBzZXRTdWdnZXN0aW9uc0xvYWRpbmddID0gdXNlQXRvbTxib29sZWFuPihcbiAgICBzdWdnZXN0aW9uc0xvYWRpbmdBdG9tXG4gICk7XG4gIGNvbnN0IFtyZXNwb25zZVN0cmVhbWluZywgc2V0UmVzcG9uc2VTdHJlYW1pbmddID0gdXNlQXRvbTxib29sZWFuPihcbiAgICByZXNwb25zZVN0cmVhbWluZ0F0b21cbiAgKTtcbiAgY29uc3Qgc2V0UmVxdWVzdEZhaWx1cmUgPSB1c2VTZXRBdG9tKHJlcXVlc3RGYWlsdXJlQXRvbSk7XG4gIGNvbnN0IHVzZXJFdmVudHMgPSB1c2VBdG9tVmFsdWUodXNlckV2ZW50UXVldWVBdG9tKTtcbiAgY29uc3QgdXNlclF1ZXVlRXZlbnRDb3VudCA9IHVzZUF0b21WYWx1ZSh1c2VyUXVldWVFdmVudENvdW50QXRvbSk7XG4gIGNvbnN0IG1hcmtVc2VyRXZlbnRzUHJvY2Vzc2VkID0gdXNlU2V0QXRvbShwcm9jZXNzVXNlckV2ZW50QXRvbSk7XG4gIGNvbnN0IGNsZWFyVXNlckV2ZW50UXVldWUgPSB1c2VTZXRBdG9tKGNsZWFyVXNlckV2ZW50QXRvbSk7XG4gIGNvbnN0IHVzZXJJZCA9IHVzZUF0b21WYWx1ZSh1c2VySWRBdG9tKTtcbiAgY29uc3QgY2hhdElkID0gdXNlQXRvbVZhbHVlKGNoYXRJZEF0b20pO1xuICBjb25zdCBzdXBwb3J0ZWRFdmVudCA9IHVzZUF0b21WYWx1ZShzdXBwb3J0ZWRFdmVudEF0b20pO1xuICAvLyBUT0RPOiBSZXBsYWNlIHdpdGggYWN0dWFsIG9yZ0lkIGZyb20gdXNlRW52aXZlQ29uZmlnIG9yIE5ld09yZ0NvbmZpZ0NvbnRleHQgd2hlbiBhdmFpbGFibGVcbiAgY29uc3Qgb3JnSWQgPSBcIm1vY2stb3JnLWlkXCI7XG5cbiAgY29uc3QgdmFyaWFudEluZm8gPSB1c2VBdG9tVmFsdWUodmFyaWFudEluZm9BdG9tKTtcbiAgY29uc3Qgc2V0dGluZ3NDb250ZXh0ID0gdXNlU3lzdGVtU2V0dGluZ3NDb250ZXh0KCk7XG4gIGNvbnN0IG1lc3NhZ2VJbnRlcmNlcHRvciA9IHVzZU1lc3NhZ2VJbnRlcmNlcHRvcigpO1xuICBjb25zdCBoYW5kbGVTZWFyY2hSZXN1bHRzID0gdXNlU2V0QXRvbShoYW5kbGVTZWFyY2hSZXN1bHRzQXRvbSk7XG4gIGNvbnN0IHNldFNlYXJjaElzTG9hZGluZyA9IHVzZVNldEF0b20oY2hhdFNlYXJjaElzTG9hZGluZ0F0b20pO1xuICBjb25zdCB7IHRyYWNrIH0gPSB1c2VBbXBsaXR1ZGVUcmFja2luZygpO1xuXG4gIGNvbnN0IGdldFN0cmVhbWluZ1Jlc3BvbnNlcyA9IHVzZUNhbGxiYWNrKFxuICAgIGFzeW5jIChcbiAgICAgIHBheWxvYWQ6IE5leHRNZXNzYWdlUmVxdWVzdFxuICAgICk6IFByb21pc2U8eyBoYXNTZWFyY2hSZXN1bHRzOiBib29sZWFuIH0+ID0+IHtcbiAgICAgIGxvZ1BlcmZNZXRyaWMoUGVyZk1ldHJpY3NFdmVudHMuRmlyc3RSZXNwb25zZVN0YXJ0ZWQpO1xuICAgICAgY29uc3Qgc3RyZWFtID0gQ29tbWVyY2VBcGlDbGllbnQuZ2V0TmV4dFJlc3BvbnNlU3RyZWFtaW5nKHBheWxvYWQpO1xuXG4gICAgICB0cnkge1xuICAgICAgICBzZXRSZXF1ZXN0RmFpbHVyZShmYWxzZSk7XG5cbiAgICAgICAgY29uc3QgeyBoYXNTZWFyY2hSZXN1bHRzIH0gPSBhd2FpdCBwcm9jZXNzU3RyZWFtaW5nUmVzcG9uc2UoXG4gICAgICAgICAgc3RyZWFtLFxuICAgICAgICAgIG1lc3NhZ2VJbnRlcmNlcHRvcixcbiAgICAgICAgICBoYW5kbGVTZWFyY2hSZXN1bHRzLFxuICAgICAgICAgIHNldE1lc3NhZ2VzLFxuICAgICAgICAgIHNldFNlYXJjaElzTG9hZGluZyxcbiAgICAgICAgICBjaGF0SWRcbiAgICAgICAgKTtcblxuICAgICAgICByZXR1cm4geyBoYXNTZWFyY2hSZXN1bHRzIH07XG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIGhhbmRsZVN0cmVhbWluZ0Vycm9yKGUsIHNldFJlcXVlc3RGYWlsdXJlLCBzZXRNZXNzYWdlcyk7XG4gICAgICAgIHRocm93IGU7XG4gICAgICB9IGZpbmFsbHkge1xuICAgICAgICBsb2dQZXJmTWV0cmljKFBlcmZNZXRyaWNzRXZlbnRzLkZpcnN0UmVzcG9uc2VDb21wbGV0ZWQpO1xuICAgICAgfVxuICAgIH0sXG4gICAgW1xuICAgICAgbG9nUGVyZk1ldHJpYyxcbiAgICAgIHNldFJlcXVlc3RGYWlsdXJlLFxuICAgICAgbWVzc2FnZUludGVyY2VwdG9yLFxuICAgICAgaGFuZGxlU2VhcmNoUmVzdWx0cyxcbiAgICAgIHNldE1lc3NhZ2VzLFxuICAgICAgc2V0U2VhcmNoSXNMb2FkaW5nLFxuICAgICAgY2hhdElkLFxuICAgIF1cbiAgKTtcblxuICBjb25zdCBnZXRTdWdnZXN0aW9ucyA9IHVzZUNhbGxiYWNrKGFzeW5jICgpID0+IHtcbiAgICBsb2dQZXJmTWV0cmljKFBlcmZNZXRyaWNzRXZlbnRzLkZpcnN0U3VnZ2VzdGlvbnNTdGFydGVkKTtcbiAgICBzZXRTdWdnZXN0aW9uc0xvYWRpbmcodHJ1ZSk7XG4gICAgc2V0U3VnZ2VzdGlvbnMoW10pO1xuXG4gICAgY29uc3QgcGF5bG9hZFdpdGhvdXRBcHBMb2FkZWQgPSBjcmVhdGVSZXNwb25zZVBheWxvYWQoe1xuICAgICAgdXNlckV2ZW50czogW10sXG4gICAgICBnZW5lcmF0aW9uUGFyYW1zOiBzZXR0aW5nc0NvbnRleHQuZ2VuZXJhdGlvblBhcmFtcyxcbiAgICB9KTtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IENvbW1lcmNlQXBpQ2xpZW50LmdldE5leHRTdWdnZXN0aW9ucyhcbiAgICAgIHBheWxvYWRXaXRob3V0QXBwTG9hZGVkXG4gICAgKTtcblxuICAgIC8vIHNvcnQgdGhlIHN1Z2dlc3Rpb25zIGJ5IHNob3J0ZXN0IGxlbmd0aCBzbyB0aGUgcGlsbHMgY2FuIGJlIHN0YWNrZWQgaG9yaXpvbnRhbGx5XG4gICAgc2V0U3VnZ2VzdGlvbnMoXG4gICAgICByZXNwb25zZS5zb3J0KChhLCBiKSA9PiBhLmNvbnRlbnQubGVuZ3RoIC0gYi5jb250ZW50Lmxlbmd0aClcbiAgICApO1xuICAgIHNldFN1Z2dlc3Rpb25zTG9hZGluZyhmYWxzZSk7XG4gICAgbG9nUGVyZk1ldHJpYyhQZXJmTWV0cmljc0V2ZW50cy5GaXJzdFN1Z2dlc3Rpb25zQ29tcGxldGVkKTtcbiAgfSwgW1xuICAgIGxvZ1BlcmZNZXRyaWMsXG4gICAgc2V0U3VnZ2VzdGlvbnNMb2FkaW5nLFxuICAgIHNldFN1Z2dlc3Rpb25zLFxuICAgIHNldHRpbmdzQ29udGV4dC5nZW5lcmF0aW9uUGFyYW1zLFxuICBdKTtcblxuICBjb25zdCBnZXRSZXNwb25zZXMgPSB1c2VDYWxsYmFjayhcbiAgICBhc3luYyAocGF5bG9hZD86IE5leHRNZXNzYWdlUmVxdWVzdCkgPT4ge1xuICAgICAgdHJ5IHtcbiAgICAgICAgY29uc3QgcmVxdWVzdFBheWxvYWQgPVxuICAgICAgICAgIHBheWxvYWQgPz9cbiAgICAgICAgICBjcmVhdGVSZXNwb25zZVBheWxvYWQoe1xuICAgICAgICAgICAgdXNlckV2ZW50cyxcbiAgICAgICAgICAgIGdlbmVyYXRpb25QYXJhbXM6IHNldHRpbmdzQ29udGV4dC5nZW5lcmF0aW9uUGFyYW1zLFxuICAgICAgICAgIH0pO1xuXG4gICAgICAgIHNldFJlc3BvbnNlU3RyZWFtaW5nKHRydWUpO1xuICAgICAgICBzZXRTdWdnZXN0aW9ucyhbXSk7XG4gICAgICAgIGNvbnN0IHN0YXJ0VGltZU1zID0gRGF0ZS5ub3coKTtcblxuICAgICAgICBhd2FpdCBnZXRTdHJlYW1pbmdSZXNwb25zZXMocmVxdWVzdFBheWxvYWQpO1xuXG4gICAgICAgIHJlY29yZEFzc2lzdGFudFJlc3BvbnNlKHN0YXJ0VGltZU1zLCByZXF1ZXN0UGF5bG9hZCwgdHJhY2spO1xuICAgICAgICBhd2FpdCBnZXRTdWdnZXN0aW9ucygpO1xuICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgTG9nZ2VyLmxvZ0Vycm9yKFwiW3NwaWZmeS1haV0gZ2V0UmVzcG9uc2VzIGVycm9yXCIsIGVycm9yKTtcbiAgICAgIH0gZmluYWxseSB7XG4gICAgICAgIC8vIFJlbW92ZSBzZWFyY2ggbG9hZGluZyBtYW5hZ2VtZW50IGZyb20gaGVyZSAtIGl0J3Mgbm93IGhhbmRsZWQgaW5kZXBlbmRlbnRseVxuICAgICAgICAvLyBpbiB0aGUgcHJvY2Vzc1N0cmVhbWluZ1Jlc3BvbnNlIGZ1bmN0aW9uIHdoZW4gc2VhcmNoIHJlc3VsdHMgYXJlIGRldGVjdGVkXG4gICAgICAgIG1hcmtVc2VyRXZlbnRzUHJvY2Vzc2VkKHVzZXJFdmVudHMubWFwKCh7IGV2ZW50SWQgfSkgPT4gZXZlbnRJZCkpO1xuICAgICAgICBzZXRVc2VySGFzUmVwbGllZChmYWxzZSk7XG4gICAgICAgIHNldFJlc3BvbnNlU3RyZWFtaW5nKGZhbHNlKTtcbiAgICAgIH1cbiAgICB9LFxuICAgIFtcbiAgICAgIHVzZXJFdmVudHMsXG4gICAgICBzZXR0aW5nc0NvbnRleHQuZ2VuZXJhdGlvblBhcmFtcyxcbiAgICAgIHNldFJlc3BvbnNlU3RyZWFtaW5nLFxuICAgICAgc2V0U3VnZ2VzdGlvbnMsXG4gICAgICBnZXRTdHJlYW1pbmdSZXNwb25zZXMsXG4gICAgICBtYXJrVXNlckV2ZW50c1Byb2Nlc3NlZCxcbiAgICAgIGdldFN1Z2dlc3Rpb25zLFxuICAgICAgc2V0VXNlckhhc1JlcGxpZWQsXG4gICAgICB0cmFjayxcbiAgICBdXG4gICk7XG5cbiAgdXNlRWZmZWN0KCgpID0+IHtcbiAgICBjb25zdCBwcm9jZXNzVXNlckV2ZW50cyA9IGFzeW5jICgpID0+IHtcbiAgICAgIGlmIChyZXNwb25zZVN0cmVhbWluZyB8fCAhd2lkZ2V0SW5pdGlhbGl6ZWQpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBpZiAoXG4gICAgICAgICh2YXJpYW50SW5mby52YXJpYW50ID09PSBcInBkcFwiICYmICF2YXJpYW50SW5mby5wcm9kdWN0SWQpIHx8XG4gICAgICAgICh2YXJpYW50SW5mby52YXJpYW50ID09PSBcInBscFwiICYmICF2YXJpYW50SW5mby5wbHBJZCkgfHxcbiAgICAgICAgKHZhcmlhbnRJbmZvLnZhcmlhbnQgPT09IFwicGFnZV92aXNpdFwiICYmICF2YXJpYW50SW5mby51cmwpXG4gICAgICApIHtcbiAgICAgICAgTG9nZ2VyLmxvZ0RlYnVnKFxuICAgICAgICAgIFwiW3NwaWZmeS1haV0gdmFyaWFudEluZm8gaGFzIGludmFsaWQgdmFsdWVzLCBza2lwcGluZy4uLlwiLFxuICAgICAgICAgIHtcbiAgICAgICAgICAgIHZhcmlhbnRJbmZvLFxuICAgICAgICAgICAgc3VwcG9ydGVkRXZlbnQsXG4gICAgICAgICAgfVxuICAgICAgICApO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIExvZ2dlci5sb2dEZWJ1ZyhcbiAgICAgICAgYEFzc2lzdGFudHMgVHVybiBpc19jdXJyZW50bHlfc3RyZWFtaW5nPSR7cmVzcG9uc2VTdHJlYW1pbmd9IGluaXRpYWxpemVkPSR7d2lkZ2V0SW5pdGlhbGl6ZWR9YFxuICAgICAgKTtcbiAgICAgIHRyeSB7XG4gICAgICAgIGF3YWl0IGdldFJlc3BvbnNlcygpO1xuICAgICAgICBMb2dnZXIubG9nSW5mbyhgQXNzaXN0YW50cyBUdXJuIFtmaW5pc2hlZF1gKTtcbiAgICAgIH0gY2F0Y2ggKGVycm9yOiB1bmtub3duKSB7XG4gICAgICAgIExvZ2dlci5sb2dFcnJvcihcIltzcGlmZnktYWldIEFzc2lzdGFudHMgVHVybiBlcnJvclwiLCBlcnJvcik7XG4gICAgICB9XG4gICAgfTtcbiAgICBpZiAodXNlclF1ZXVlRXZlbnRDb3VudCA+IDApIHtcbiAgICAgIHByb2Nlc3NVc2VyRXZlbnRzKCk7XG4gICAgfVxuICB9LCBbXG4gICAgZ2V0UmVzcG9uc2VzLFxuICAgIHJlc3BvbnNlU3RyZWFtaW5nLFxuICAgIHVzZXJRdWV1ZUV2ZW50Q291bnQsXG4gICAgd2lkZ2V0SW5pdGlhbGl6ZWQsXG4gICAgdmFyaWFudEluZm8sXG4gICAgc3VwcG9ydGVkRXZlbnQsXG4gIF0pO1xuXG4gIHVzZUVmZmVjdCgoKSA9PiB7XG4gICAgaWYgKHdpZGdldEluaXRpYWxpemVkIHx8IHJlc3BvbnNlU3RyZWFtaW5nKSB7XG4gICAgICBMb2dnZXIubG9nRGVidWcoXG4gICAgICAgIGBbc3BpZmZ5LWFpXSBpbml0aWFsaXplV2lkZ2V0IFtza2lwcGVkXSBpc19jdXJyZW50bHlfc3RyZWFtaW5nPSR7cmVzcG9uc2VTdHJlYW1pbmd9IGlzX2luaXRpYWxpemVkPSR7d2lkZ2V0SW5pdGlhbGl6ZWR9YFxuICAgICAgKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCBoeWRyYXRlQ2hhdCA9IGFzeW5jICgpID0+IHtcbiAgICAgIHRyeSB7XG4gICAgICAgIExvZ2dlci5sb2dEZWJ1ZyhcbiAgICAgICAgICBgW3NwaWZmeS1haV0gaW5pdGlhbGl6ZVdpZGdldCBpc19jdXJyZW50bHlfc3RyZWFtaW5nPSR7cmVzcG9uc2VTdHJlYW1pbmd9IGlzX2luaXRpYWxpemVkPSR7d2lkZ2V0SW5pdGlhbGl6ZWR9YFxuICAgICAgICApO1xuICAgICAgICAvLyBvbiBtb3VudCwgdHJ5IHRvIGdldCB0aGUgcmVzcG9uc2VzIGZyb20gYW4gYWN0aXZlIHNlc3Npb24gaWYgb25lIGV4aXN0c1xuICAgICAgICBpZiAoIW9yZ0lkKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwib3JnSWQgaXMgbm90IGF2YWlsYWJsZVwiKTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCB7IG1lc3NhZ2VzOiBleGlzdGluZ01lc3NhZ2VzLCB1c2VyRXZlbnRzIH0gPVxuICAgICAgICAgIGF3YWl0IENvbW1lcmNlQXBpQ2xpZW50LmdldFJlc3BvbnNlcyhvcmdJZCwgY2hhdElkLCB1c2VySWQpO1xuICAgICAgICBzZXRNZXNzYWdlcyhbLi4uZXhpc3RpbmdNZXNzYWdlc10pO1xuICAgICAgICBzZXRVc2VyRXZlbnRzKFsuLi51c2VyRXZlbnRzXSk7XG4gICAgICAgIGdldFJlc3BvbnNlcygpO1xuICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgLy8gbm8gYWN0aXZlIGNoYXQgc2Vzc2lvbiB3YXMgZm91bmQsIHN0YXJ0IGEgbmV3IG9uZVxuICAgICAgICBMb2dnZXIubG9nSW5mbyhcbiAgICAgICAgICBgSW5pdCBjaGF0IFtleGNlcHRpb25dIGNoYXRfaWQ9JHtjaGF0SWR9IGVycm9yPSR7ZXJyb3J9YCxcbiAgICAgICAgICBlcnJvclxuICAgICAgICApO1xuICAgICAgICBpZiAoZXJyb3IgaW5zdGFuY2VvZiBTZXNzaW9uUmVzdGFydFJlcXVpcmVkKSB7XG4gICAgICAgICAgY29uc3QgYXBwTG9hZGVkRXZlbnQgPSBjcmVhdGVBcHBMb2FkZWRFdmVudCgpO1xuICAgICAgICAgIGNvbnN0IHZpc2l0RXZlbnQgPSBjcmVhdGVWaXNpdFVzZXJFdmVudCh7IHZhcmlhbnRJbmZvIH0pO1xuICAgICAgICAgIHNldE1lc3NhZ2VzKFtdKTtcbiAgICAgICAgICBjbGVhclVzZXJFdmVudFF1ZXVlKCk7XG4gICAgICAgICAgaWYgKHZpc2l0RXZlbnQpIHtcbiAgICAgICAgICAgIGNvbnN0IHBheWxvYWQgPSBjcmVhdGVSZXNwb25zZVBheWxvYWQoe1xuICAgICAgICAgICAgICB1c2VyRXZlbnRzOiBbYXBwTG9hZGVkRXZlbnQsIHZpc2l0RXZlbnRdLFxuICAgICAgICAgICAgICBnZW5lcmF0aW9uUGFyYW1zOiBzZXR0aW5nc0NvbnRleHQuZ2VuZXJhdGlvblBhcmFtcyxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgZ2V0UmVzcG9uc2VzKHBheWxvYWQpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSBmaW5hbGx5IHtcbiAgICAgICAgc2V0V2lkZ2V0SW5pdGlhbGl6ZWQodHJ1ZSk7XG4gICAgICB9XG4gICAgfTtcblxuICAgIGh5ZHJhdGVDaGF0KCk7XG4gIH0sIFtdKTtcblxuICBjb25zdCBvbkZvY3VzID0gdXNlQ2FsbGJhY2soYXN5bmMgKCkgPT4ge1xuICAgIHRyeSB7XG4gICAgICBpZiAoIXJlc3BvbnNlU3RyZWFtaW5nICYmICFzdWdnZXN0aW9uc0xvYWRpbmcgJiYgb3JnSWQpIHtcbiAgICAgICAgY29uc3QgeyBtZXNzYWdlczogZXhpc3RpbmdNZXNzYWdlcyB9ID1cbiAgICAgICAgICBhd2FpdCBDb21tZXJjZUFwaUNsaWVudC5nZXRSZXNwb25zZXMob3JnSWQsIGNoYXRJZCwgdXNlcklkKTtcblxuICAgICAgICBpZiAoZXhpc3RpbmdNZXNzYWdlcy5sZW5ndGggPiBtZXNzYWdlcy5sZW5ndGgpIHtcbiAgICAgICAgICBzZXRNZXNzYWdlcyhbLi4uZXhpc3RpbmdNZXNzYWdlc10pO1xuICAgICAgICAgIC8vIFRPRE86IElzIHRoaXMgYnVnIGhhY2sgc3RpbGwgbmVjZXNzYXJ5P1xuICAgICAgICAgIC8vIElmIGl0IGlzLCBjb21lIHVwIHdpdGggYSBiZXR0ZXIgc29sdXRpb24gZm9yIGl0XG4gICAgICAgICAgLy8gfSBlbHNlIGlmIChleGlzdGluZ01lc3NhZ2VzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgIC8vICAgLy8gaWYgdGhlcmUgd2FzIGFuIGVycm9yIGR1cmluZyB0aGUgaW5pdGlhbGl6YXRpb24gb2YgYSBuZXcgc2Vzc2lvbiwgdGhlIHNlc3Npb24gd291bGQgYmVcbiAgICAgICAgICAvLyAgIC8vIGNyZWF0ZWQgaW4gdGhlIGJhY2tlbmQgYnV0IHdpdGhvdXQgYW55IG1lc3NhZ2VzLiBSZXRyeSB0aGUgbmV4dF9yZXNwb25zZXMgcmVxdWVzdCB3aXRoXG4gICAgICAgICAgLy8gICAvLyB0aGUgY3VycmVudCBzZXQgb2YgcGFyYW1ldGVycyB0byBcImp1bXBzdGFydFwiIHRoZSBzZXNzaW9uXG4gICAgICAgICAgLy8gICB0cmlnZ2VyR2V0UmVzcG9uc2VDYWxsKCdvbkZvY3VzJyk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9IGNhdGNoIChlcnJvcjogdW5rbm93bikge1xuICAgICAgTG9nZ2VyLmxvZ0Vycm9yKFwiW3NwaWZmeS1haV0gb25Gb2N1cyBlcnJvclwiLCBlcnJvcik7XG4gICAgfVxuICB9LCBbXG4gICAgcmVzcG9uc2VTdHJlYW1pbmcsXG4gICAgc3VnZ2VzdGlvbnNMb2FkaW5nLFxuICAgIG9yZ0lkLFxuICAgIGNoYXRJZCxcbiAgICB1c2VySWQsXG4gICAgbWVzc2FnZXMubGVuZ3RoLFxuICAgIHNldE1lc3NhZ2VzLFxuICBdKTtcblxuICAvLyBsaXN0ZW4gZm9yIHBhZ2UgZm9jdXMgdG8gZ2V0IGxhdGVzdCBtZXNzYWdlcyBmcm9tIHRoZSBzZXJ2ZXJcbiAgdXNlRWZmZWN0KCgpID0+IHtcbiAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcihcImZvY3VzXCIsIG9uRm9jdXMpO1xuXG4gICAgcmV0dXJuICgpID0+IHtcbiAgICAgIHdpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKFwiZm9jdXNcIiwgb25Gb2N1cyk7XG4gICAgfTtcbiAgfSwgW29uRm9jdXNdKTtcblxuICBjb25zdCBjaGF0Q29udGV4dCA9IHVzZU1lbW8oKCkgPT4gKHt9KSwgW10pO1xuXG4gIHJldHVybiAoXG4gICAgPENoYXRDb250ZXh0LlByb3ZpZGVyIHZhbHVlPXtjaGF0Q29udGV4dH0+e2NoaWxkcmVufTwvQ2hhdENvbnRleHQuUHJvdmlkZXI+XG4gICk7XG59O1xuXG5leHBvcnQgeyBDaGF0Q29udGV4dCwgQ2hhdENvbnRleHRQcm92aWRlciB9O1xuZXhwb3J0IHR5cGUgeyBDaGF0Q29udGV4dFBhcmFtcyB9O1xuIiwiaW1wb3J0IFJlYWN0LCB7IFJlYWN0Tm9kZSB9IGZyb20gXCJyZWFjdFwiO1xuaW1wb3J0IHsgdXNlTmV3T3JnQ29uZmlnIH0gZnJvbSBcInNyYy9ob29rc1wiO1xuXG5pbnRlcmZhY2UgRW52aXZlQ3NzUHJvdmlkZXJQcm9wcyB7XG4gIGNoaWxkcmVuOiBSZWFjdE5vZGU7XG59XG5cbmV4cG9ydCBjb25zdCBFbnZpdmVDc3NQcm92aWRlcjogUmVhY3QuRkM8RW52aXZlQ3NzUHJvdmlkZXJQcm9wcz4gPSAoe1xuICBjaGlsZHJlbixcbn0pID0+IHtcbiAgY29uc3QgeyBjb2xvcnNDb25maWcsIGZyb250ZW5kQ29uZmlnLCBsb2FkaW5nIH0gPSB1c2VOZXdPcmdDb25maWcoKTtcbiAgbGV0IG1lcmNoYW50VGhlbWVDc3MgPSBgKiB7fWA7XG4gIGlmIChjb2xvcnNDb25maWcgJiYgIWxvYWRpbmcpIHtcbiAgICBtZXJjaGFudFRoZW1lQ3NzID0gYFxuKiB7XG4gIC0tc3BpZmZ5LWNvbG9ycy10ZXh0LXByaW1hcnk6ICR7Y29sb3JzQ29uZmlnLnRleHRQcmltYXJ5fTtcbiAgLS1zcGlmZnktY29sb3JzLXRleHQtc2Vjb25kYXJ5OiAke2NvbG9yc0NvbmZpZy50ZXh0U2Vjb25kYXJ5fTtcbiAgLS1zcGlmZnktY29sb3JzLXRleHQtYWNjZW50OiAke2NvbG9yc0NvbmZpZy50ZXh0QWNjZW50fTtcbiAgLS1zcGlmZnktY29sb3JzLXRleHQtbGluazogJHtjb2xvcnNDb25maWcudGV4dExpbmt9O1xuICAtLXNwaWZmeS1jb2xvcnMtdGV4dC1saWdodDogJHtjb2xvcnNDb25maWcudGV4dExpZ2h0fTtcbiAgLS1zcGlmZnktY29sb3JzLWJhY2tncm91bmQtcHJpbWFyeTogJHtjb2xvcnNDb25maWcuYmFja2dyb3VuZFByaW1hcnl9O1xuICAtLXNwaWZmeS1jb2xvcnMtYmFja2dyb3VuZC1zZWNvbmRhcnk6ICR7Y29sb3JzQ29uZmlnLmJhY2tncm91bmRTZWNvbmRhcnl9O1xuICAtLXNwaWZmeS1jb2xvcnMtYmFja2dyb3VuZC1zZWNvbmRhcnktZGFyazogJHtjb2xvcnNDb25maWcuYmFja2dyb3VuZFNlY29uZGFyeURhcmt9O1xuICAtLXNwaWZmeS1jb2xvcnMtYmFja2dyb3VuZC10ZXJ0aWFyeTogJHtjb2xvcnNDb25maWcuYmFja2dyb3VuZFRlcnRpYXJ5fTtcbiAgLS1zcGlmZnktY29sb3JzLWJhY2tncm91bmQtZGFyazogJHtjb2xvcnNDb25maWcuYmFja2dyb3VuZERhcmt9O1xuICAtLXNwaWZmeS1jb2xvcnMtYmFja2dyb3VuZC1saWdodDogJHtjb2xvcnNDb25maWcuYmFja2dyb3VuZExpZ2h0fTtcbiAgLS1zcGlmZnktY29sb3JzLWJhY2tncm91bmQtc2F0dXJhdGVkOiAke2NvbG9yc0NvbmZpZy5iYWNrZ3JvdW5kU2F0dXJhdGVkfTtcbiAgLS1zcGlmZnktY29sb3JzLWJvcmRlci1saWdodDogJHtjb2xvcnNDb25maWcuYm9yZGVyTGlnaHR9O1xuICAtLXNwaWZmeS1jb2xvcnMtYm9yZGVyLW1lZGl1bTogJHtjb2xvcnNDb25maWcuYm9yZGVyTWVkaXVtfTtcbiAgLS1zcGlmZnktY29sb3JzLWJvcmRlci1kYXJrOiAke2NvbG9yc0NvbmZpZy5ib3JkZXJEYXJrfTtcbiAgLS1zcGlmZnktY29sb3JzLWJvcmRlci1vdXRsaW5lOiAke2NvbG9yc0NvbmZpZy5ib3JkZXJPdXRsaW5lfTtcbiAgLS1zcGlmZnktY29sb3JzLWFjY2VudC1wcmltYXJ5OiAke2NvbG9yc0NvbmZpZy5hY2NlbnRQcmltYXJ5fTtcbiAgLS1zcGlmZnktY29sb3JzLWFjY2VudC1zZWNvbmRhcnk6ICR7Y29sb3JzQ29uZmlnLmFjY2VudFNlY29uZGFyeX07XG59YDtcbiAgfVxuICBjb25zb2xlLmxvZyhmcm9udGVuZENvbmZpZyk7XG4gIHJldHVybiAoXG4gICAgPD5cbiAgICAgIHtmcm9udGVuZENvbmZpZyA/IChcbiAgICAgICAgPHN0eWxlIGlkPVwibWVyY2hhbnQtY3NzLW92ZXJyaWRlc1wiPntgJHtmcm9udGVuZENvbmZpZy5tZXJjaGFudE92ZXJyaWRlQ3NzfWB9PC9zdHlsZT5cbiAgICAgICkgOiBudWxsfVxuICAgICAge2NvbG9yc0NvbmZpZyA/IChcbiAgICAgICAgPHN0eWxlIGlkPVwibWVyY2hhbnQtY3NzLWNvbG9yc1wiPntgJHttZXJjaGFudFRoZW1lQ3NzfWB9PC9zdHlsZT5cbiAgICAgICkgOiBudWxsfVxuXG4gICAgICB7Y2hpbGRyZW59XG4gICAgPC8+XG4gICk7XG59O1xuIiwiaW1wb3J0IHsgdXNlQXRvbVZhbHVlIH0gZnJvbSBcImpvdGFpXCI7XG5pbXBvcnQge1xuICBEaXNwYXRjaCxcbiAgUmVhY3ROb2RlLFxuICBTZXRTdGF0ZUFjdGlvbixcbiAgY3JlYXRlQ29udGV4dCxcbiAgdXNlTWVtbyxcbiAgdXNlU3RhdGUsXG59IGZyb20gXCJyZWFjdFwiO1xuaW1wb3J0IHsgR2VuZXJhdGlvblBhcmFtcyB9IGZyb20gXCJzcmMvYXBwbGljYXRpb24vbW9kZWxzXCI7XG5pbXBvcnQgeyBiYXNlVXJsQXRvbSB9IGZyb20gXCJzcmMvYXRvbXMvZW52aXZlL2Vudml2ZUNvbmZpZ1wiO1xuXG4vLyBUT0RPOiBSZWZhY3RvciB0aGlzIHRvIGEgY29tbW9uIHNlcnZpY2UgdGhhdCBoYW5kbGVzIHF1ZXJ5IHBhcmFtcyAoYW5kIHNwaWZmeSB2YXJpYWJsZXMgYWxsIHRvZ2V0aGVyKVxuY29uc3QgZ2V0Q2hhdE1vZGVsTmFtZSA9ICgpID0+IHtcbiAgY29uc3QgdXJsT2JqID0gbmV3IFVSTCh3aW5kb3cubG9jYXRpb24uaHJlZik7XG4gIGNvbnN0IHBhcmFtcyA9IG5ldyBVUkxTZWFyY2hQYXJhbXModXJsT2JqLnNlYXJjaCk7XG4gIGNvbnN0IHBhcmFtc09iaiA9IE9iamVjdC5mcm9tRW50cmllcyhwYXJhbXMuZW50cmllcygpKTtcbiAgcmV0dXJuIHBhcmFtc09iai5sbG1fbW9kZWxfbmFtZTtcbn07XG5cbmNvbnN0IGRlZmF1bHRHZW5lcmF0aW9uUGFyYW1zOiBHZW5lcmF0aW9uUGFyYW1zID0ge1xuICBzdHJlYW06IHRydWUsXG4gIG51bVN1Z2dlc3Rpb25zOiAzLFxuICBtb2RlbDogZ2V0Q2hhdE1vZGVsTmFtZSgpLFxufTtcblxuaW50ZXJmYWNlIFN5c3RlbVNldHRpbmdzQ29udGV4dFBhcmFtcyB7XG4gIGdlbmVyYXRpb25QYXJhbXM/OiBHZW5lcmF0aW9uUGFyYW1zO1xuICBzaG93RGVidWdCYXI/OiBib29sZWFuO1xuICBlbmRwb2ludFVSTD86IHN0cmluZztcbiAgc2V0R2VuZXJhdGlvblBhcmFtczogRGlzcGF0Y2g8U2V0U3RhdGVBY3Rpb248R2VuZXJhdGlvblBhcmFtcyB8IHVuZGVmaW5lZD4+O1xufVxuXG5pbnRlcmZhY2UgU3lzdGVtU2V0dGluZ3NDb250ZXh0UHJvdmlkZXJQcm9wcyB7XG4gIGNoaWxkcmVuOiBSZWFjdE5vZGU7XG4gIGdlbmVyYXRpb25QYXJhbXM/OiBHZW5lcmF0aW9uUGFyYW1zO1xuICBzaG93RGVidWdCYXI/OiBib29sZWFuO1xufVxuXG5jb25zdCBTeXN0ZW1TZXR0aW5nc0NvbnRleHQgPSBjcmVhdGVDb250ZXh0PFxuICBTeXN0ZW1TZXR0aW5nc0NvbnRleHRQYXJhbXMgfCB1bmRlZmluZWRcbj4odW5kZWZpbmVkKTtcblxuY29uc3QgU3lzdGVtU2V0dGluZ3NDb250ZXh0UHJvdmlkZXIgPSAoe1xuICBjaGlsZHJlbixcbiAgZ2VuZXJhdGlvblBhcmFtcyxcbiAgc2hvd0RlYnVnQmFyLFxufTogU3lzdGVtU2V0dGluZ3NDb250ZXh0UHJvdmlkZXJQcm9wcykgPT4ge1xuICBjb25zdCBbcGFyYW1zLCBzZXRQYXJhbXNdID0gdXNlU3RhdGU8R2VuZXJhdGlvblBhcmFtcyB8IHVuZGVmaW5lZD4oXG4gICAgKCkgPT4gZ2VuZXJhdGlvblBhcmFtcyA/PyBkZWZhdWx0R2VuZXJhdGlvblBhcmFtc1xuICApO1xuICBjb25zdCBlbmRwb2ludFVSTCA9IHVzZUF0b21WYWx1ZShiYXNlVXJsQXRvbSk7XG4gIGNvbnN0IHNldHRpbmdzQ29udGV4dFZhbHVlcyA9IHVzZU1lbW8oXG4gICAgKCkgPT4gKHtcbiAgICAgIGdlbmVyYXRpb25QYXJhbXM6IHBhcmFtcyxcbiAgICAgIHNob3dEZWJ1Z0JhcixcbiAgICAgIHNldEdlbmVyYXRpb25QYXJhbXM6IHNldFBhcmFtcyxcbiAgICAgIGVuZHBvaW50VVJMLFxuICAgIH0pLFxuICAgIFtnZW5lcmF0aW9uUGFyYW1zLCBlbmRwb2ludFVSTCwgc2hvd0RlYnVnQmFyXVxuICApO1xuXG4gIHJldHVybiAoXG4gICAgPFN5c3RlbVNldHRpbmdzQ29udGV4dC5Qcm92aWRlciB2YWx1ZT17c2V0dGluZ3NDb250ZXh0VmFsdWVzfT5cbiAgICAgIHtjaGlsZHJlbn1cbiAgICA8L1N5c3RlbVNldHRpbmdzQ29udGV4dC5Qcm92aWRlcj5cbiAgKTtcbn07XG5cbmV4cG9ydCB7XG4gIFN5c3RlbVNldHRpbmdzQ29udGV4dFByb3ZpZGVyLFxuICBTeXN0ZW1TZXR0aW5nc0NvbnRleHQsXG4gIGRlZmF1bHRHZW5lcmF0aW9uUGFyYW1zLFxufTtcbiJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFVQSxNQUFNLGFBQWEsY0FBcUMsS0FBSztBQUU3RCxNQUFhQSxlQUF3RCxFQUNuRSxlQUNJO0NBRUosTUFBTSxTQURrQixhQUFhLFdBQVcsSUFDZDtDQUVsQyxNQUFNLGlCQUFpQixrQkFBa0I7QUFDdkMsU0FBTztJQUNOLENBQUMsT0FBTyxDQUFDO0NBRVosTUFBTSxjQUFjLGFBQ2pCLFdBQW1CLGlCQUF5QjtBQUMzQyxTQUFPLEdBQUcsZ0JBQWdCLENBQUMsVUFBVSxhQUFhLEdBQUc7SUFFdkQsQ0FBQyxlQUFlLENBQ2pCO0NBRUQsTUFBTSxRQUFRLGVBQ0w7RUFDTDtFQUNBO0VBQ0E7RUFD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